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);