shithub: sl

Download patch

ref: edc9ab0af768f32581e07a3dda239ba3a9b07233
parent: 3f4a4920030c1b18c16ee4c49a4a92181807f63c
author: Sigrid Solveig Haflínudóttir <sigrid@ftrv.se>
date: Wed Feb 12 20:19:18 EST 2025

vm: fast path for fixnum negation

--- a/src/cvalues.c
+++ b/src/cvalues.c
@@ -879,12 +879,6 @@
 	fixnum_t pi;
 	void *a;
 
-	if(isfixnum(n)){
-		i64 = -(int64_t)numval(n);
-i64neg:
-		return fits_fixnum(i64) ? fixnum(i64) : mk_mpint(vtomp(i64, nil));
-	}
-
 	if(num_to_ptr(n, &pi, &pt, &a)){
 		switch(pt){
 		case T_DOUBLE: return mk_double(-*(double*)a);
@@ -895,10 +889,9 @@
 		case T_UINT16: return fixnum(-(fixnum_t)*(uint16_t*)a);
 		case T_UINT32:
 			i64 = -(int64_t)*(uint32_t*)a;
-			if(0){
+			goto i64neg;
 		case T_INT32:
-				i64 = -(int64_t)*(int32_t*)a;
-			}
+			i64 = -(int64_t)*(int32_t*)a;
 			goto i64neg;
 		case T_INT64:
 			i64 = *(int64_t*)a;
@@ -905,7 +898,8 @@
 			if(i64 == INT64_MIN)
 				return mk_mpint(uvtomp((uint64_t)INT64_MAX+1, nil));
 			i64 = -i64;
-			goto i64neg;
+i64neg:
+			return fits_fixnum(i64) ? fixnum(i64) : mk_mpint(vtomp(i64, nil));
 		case T_UINT64:
 			ui64 = *(uint64_t*)a;
 			if(ui64 >= (uint64_t)INT64_MAX+1){
--- a/src/flisp.c
+++ b/src/flisp.c
@@ -880,6 +880,7 @@
 	cons_t *c;
 	value_t *pv, v, e;
 	function_t *fn;
+	int64_t i64;
 	int x;
 
 	n = 0;
--- a/src/vm.inc
+++ b/src/vm.inc
@@ -1,3 +1,10 @@
+#define fixnum_neg(x) ( \
+	i64 = -(int64_t)(numval(x)), \
+	i64 == INT64_MIN \
+		? mk_mpint(uvtomp((uint64_t)INT64_MAX+1, nil)) \
+		: (fits_fixnum(i64) ? fixnum(i64) : mk_mpint(vtomp(i64, nil))) \
+)
+
 OP(OP_LOADA0)
 	PUSH(FL(stack)[bp]);
 	NEXT_OP;
@@ -179,7 +186,8 @@
 OP(OP_SUB2)
 LABEL(do_sub2):
 		FL(stack)[ipd] = (uintptr_t)ip;
-		FL(stack)[FL(sp)-1] = fl_neg(FL(stack)[FL(sp)-1]);
+		v = FL(stack)[FL(sp)-1];
+		FL(stack)[FL(sp)-1] = isfixnum(v) ? fixnum_neg(v) : fl_neg(v);
 	}
 	{
 		value_t a, b, q;
@@ -659,7 +667,8 @@
 OP(OP_NEG)
 LABEL(do_neg):
 	FL(stack)[ipd] = (uintptr_t)ip;
-	FL(stack)[FL(sp)-1] = fl_neg(FL(stack)[FL(sp)-1]);
+	v = FL(stack)[FL(sp)-1];
+	FL(stack)[FL(sp)-1] = isfixnum(v) ? fixnum_neg(v) : fl_neg(v);
 	NEXT_OP;
 
 OP(OP_FIXNUMP)
@@ -832,7 +841,8 @@
 	// so it can handle rest args properly
 	PUSH(FL(stack)[i]);
 	FL(stack)[i] = fixnum(0);
-	FL(stack)[i+1] = fl_neg(fl_add_any(&FL(stack)[i], n));
+	v = fl_add_any(&FL(stack)[i], n);
+	FL(stack)[i+1] = isfixnum(v) ? fixnum_neg(v) : fl_neg(v);
 	FL(stack)[i] = POP();
 	v = fl_add_any(&FL(stack)[i], 2);
 	POPN(n);