change JIT inlining of `/' to be fast on a fixnum result

This commit is contained in:
Matthew Flatt 2012-11-04 15:24:19 -07:00
parent ef3eb3154a
commit 1126f02ddd
2 changed files with 46 additions and 56 deletions

View File

@ -475,6 +475,10 @@
(tri 3 '/ (lambda () 30) 5 2 void)
(tri 12 '/ (lambda () 30) 5 1/2 void)
(bin-exact (/ 1.1 2.3) 'fl/ 1.1 2.3 #t)
(bin 4/3 '/ 4 3)
(bin -4/3 '/ 4 -3)
(bin -4/3 '/ -4 3)
(bin 4/3 '/ -4 -3)
(bin-int 3 'quotient 10 3)
(bin-int -3 'quotient 10 -3)

View File

@ -1125,11 +1125,6 @@ int scheme_generate_arith(mz_jit_state *jitter, Scheme_Object *rator, Scheme_Obj
CHECK_LIMIT();
/* sync'd in three branches below */
if (arith == ARITH_DIV) {
if (rand2 || (v != 1) || reversed)
has_fixnum_fast = 0;
}
/* rand2 in R0, and rand in R1 unless it's simple */
if (simple_rand || simple_rand2) {
@ -1299,7 +1294,7 @@ int scheme_generate_arith(mz_jit_state *jitter, Scheme_Object *rator, Scheme_Obj
if (!unsafe_fl) {
if (arith) {
if (((arith == ARITH_QUOT) || (arith == ARITH_REM) || (arith == ARITH_MOD)) && !rand2) {
if (((arith == ARITH_DIV) || (arith == ARITH_QUOT) || (arith == ARITH_REM) || (arith == ARITH_MOD)) && !rand2) {
(void)jit_movi_p(JIT_R1, scheme_make_integer(v));
rand2 = scheme_true;
reversed = !reversed;
@ -1338,54 +1333,58 @@ int scheme_generate_arith(mz_jit_state *jitter, Scheme_Object *rator, Scheme_Obj
else
(void)jit_bomulr_l(refslow, JIT_V1, JIT_R2);
jit_ori_ul(JIT_R0, JIT_V1, 0x1);
} else if (arith == ARITH_DIV) {
if (has_fixnum_fast) {
/* No fast path for fixnum division, yet */
(void)jit_jmpi(refslow);
}
} else if ((arith == ARITH_QUOT) || (arith == ARITH_REM) || (arith == ARITH_MOD)) {
} else if ((arith == ARITH_DIV) || (arith == ARITH_QUOT) || (arith == ARITH_REM) || (arith == ARITH_MOD)) {
if (reversed) {
jit_rshi_l(JIT_V1, JIT_R0, 0x1);
jit_rshi_l(JIT_R2, JIT_R1, 0x1);
if (reversed) {
} else {
jit_rshi_l(JIT_R2, JIT_R0, 0x1);
jit_rshi_l(JIT_V1, JIT_R1, 0x1);
}
if (!unsafe_fx || overflow_refslow)
(void)jit_beqi_l(refslow, JIT_R2, 0);
if (arith == ARITH_MOD) {
generate_modulo_setup(jitter, branch_short, JIT_V1, JIT_R2);
CHECK_LIMIT();
}
if (arith == ARITH_QUOT)
if ((arith == ARITH_DIV) || (arith == ARITH_QUOT))
jit_divr_l(JIT_R0, JIT_V1, JIT_R2);
else
jit_modr_l(JIT_R0, JIT_V1, JIT_R2);
} else {
if (!unsafe_fx || overflow_refslow)
(void)jit_beqi_l(refslow, JIT_V1, 0);
if (arith == ARITH_MOD) {
generate_modulo_setup(jitter, branch_short, JIT_R2, JIT_V1);
CHECK_LIMIT();
}
if (arith == ARITH_QUOT)
jit_divr_l(JIT_R0, JIT_R2, JIT_V1);
if (arith == ARITH_DIV) {
GC_CAN_IGNORE jit_insn *refx;
if (reversed)
jit_mulr_l(JIT_R2, JIT_R0, JIT_R2);
else
jit_modr_l(JIT_R0, JIT_R2, JIT_V1);
}
if (arith == ARITH_MOD) {
jit_mulr_l(JIT_V1, JIT_R0, JIT_V1);
__START_INNER_TINY__(branch_short);
refx = jit_beqr_l(jit_forward(), JIT_R2, JIT_V1);
__END_INNER_TINY__(branch_short);
/* restore R0 argument: */
if (reversed)
jit_lshi_l(JIT_R0, JIT_V1, 1);
else
jit_lshi_l(JIT_R0, JIT_R2, 1);
jit_ori_l(JIT_R0, JIT_R0, 0x1);
(void)jit_jmpi(refslow);
__START_INNER_TINY__(branch_short);
mz_patch_branch(refx);
__END_INNER_TINY__(branch_short);
} else if (arith == ARITH_MOD) {
GC_CAN_IGNORE jit_insn *refx, *refy;
__START_INNER_TINY__(branch_short);
refy = jit_beqi_l(jit_forward(), JIT_R0, 0);
refx = jit_bmci_l(jit_forward(), JIT_R1, 0x1);
if (reversed)
jit_subr_l(JIT_R0, JIT_R2, JIT_R0);
else
jit_subr_l(JIT_R0, JIT_V1, JIT_R0);
mz_patch_branch(refx);
refx = jit_bmci_l(jit_forward(), JIT_R1, 0x2);
jit_negr_l(JIT_R0, JIT_R0);
mz_patch_branch(refx);
mz_patch_branch(refy);
__END_INNER_TINY__(branch_short);
}
if (arith == ARITH_QUOT) {
} else if (arith == ARITH_QUOT) {
/* watch out for negation of most negative fixnum,
which is a positive number too big for a fixnum */
if (!unsafe_fx || overflow_refslow) {
@ -1551,16 +1550,6 @@ int scheme_generate_arith(mz_jit_state *jitter, Scheme_Object *rator, Scheme_Obj
}
jit_ori_ul(JIT_R0, JIT_V1, 0x1);
}
} else if (arith == ARITH_DIV) {
if ((v == 1) && !reversed) {
/* R0 already is the answer */
} else {
if (has_fixnum_fast) {
/* No general fast path for fixnum division, yet */
(void)jit_movi_p(JIT_R1, scheme_make_integer(v));
(void)jit_jmpi(refslow);
}
}
} else {
if (arith == ARITH_AND) {
/* and */
@ -1877,10 +1866,7 @@ int scheme_generate_nary_arith(mz_jit_state *jitter, Scheme_App_Rec *app,
# define mzSET_USE_FL(x) /* empty */
#endif
if (arith == ARITH_DIV) {
/* can't inline fixnum '/' */
use_fx = 0;
} else if ((arith == ARITH_AND)
if ((arith == ARITH_AND)
|| (arith == ARITH_IOR)
|| (arith == ARITH_XOR)) {
/* bitwise operators are fixnum, only */