skip some unneeded fixnum tests in JIT-generated code

This commit is contained in:
Matthew Flatt 2012-11-17 08:49:36 -07:00
parent 4041e65a86
commit be4ce3ed66
5 changed files with 101 additions and 17 deletions

View File

@ -81,7 +81,15 @@
(when (boolean? v) (when (boolean? v)
;; (printf " for branch...\n") ;; (printf " for branch...\n")
(test (if v 'yes 'no) name ((eval `(lambda (x) (if (,op x ',arg2) 'yes 'no))) arg1)) (test (if v 'yes 'no) name ((eval `(lambda (x) (if (,op x ',arg2) 'yes 'no))) arg1))
(test (if v 'yes 'no) name ((eval `(lambda (x) (if (,op ',arg1 x) 'yes 'no))) arg2)))))] (test (if v 'yes 'no) name ((eval `(lambda (x) (if (,op ',arg1 x) 'yes 'no))) arg2)))
(when (fixnum? arg2)
(test v name ((eval `(lambda (x) (let ([x2 (fx+ (random 1) ',arg2)])
(,op x x2))))
arg1)))
(when (fixnum? arg1)
(test v name ((eval `(lambda (y) (let ([x1 (fx+ (random 1) ',arg1)])
(,op x1 y))))
arg2)))))]
[bin-exact (lambda (v op arg1 arg2 [check-fixnum-as-bad? #f]) [bin-exact (lambda (v op arg1 arg2 [check-fixnum-as-bad? #f])
(check-error-message op (eval `(lambda (x) (,op x ',arg2)))) (check-error-message op (eval `(lambda (x) (,op x ',arg2))))
(check-error-message op (eval `(lambda (x) (,op ',arg1 x)))) (check-error-message op (eval `(lambda (x) (,op ',arg1 x))))

View File

@ -1263,6 +1263,7 @@ Scheme_Object *scheme_jit_make_two_element_ivector(Scheme_Object *a, Scheme_Obje
/* jitarith */ /* jitarith */
/**********************************************************************/ /**********************************************************************/
int scheme_jit_is_fixnum(Scheme_Object *rand);
int scheme_can_unbox_inline(Scheme_Object *obj, int fuel, int regs, int unsafely); int scheme_can_unbox_inline(Scheme_Object *obj, int fuel, int regs, int unsafely);
int scheme_can_unbox_directly(Scheme_Object *obj); int scheme_can_unbox_directly(Scheme_Object *obj);
int scheme_generate_unboxing(mz_jit_state *jitter, int target); int scheme_generate_unboxing(mz_jit_state *jitter, int target);

View File

@ -30,6 +30,18 @@
#define JITARITH_TS_PROCS #define JITARITH_TS_PROCS
#include "jit_ts.c" #include "jit_ts.c"
int scheme_jit_is_fixnum(Scheme_Object *rand)
{
if (SCHEME_INTP(rand)
|| (SAME_TYPE(SCHEME_TYPE(rand), scheme_local_type)
&& (SCHEME_GET_LOCAL_TYPE(rand) == SCHEME_LOCAL_TYPE_FIXNUM)))
return 1;
else if (scheme_expr_produces_local_type(rand) == SCHEME_LOCAL_TYPE_FIXNUM)
return 1;
else
return 0;
}
static int can_reorder_unboxing(Scheme_Object *rand, Scheme_Object *rand2) static int can_reorder_unboxing(Scheme_Object *rand, Scheme_Object *rand2)
{ {
/* Can we reorder `rand' and `rand2', given that we want floating-point /* Can we reorder `rand' and `rand2', given that we want floating-point
@ -1038,6 +1050,18 @@ int scheme_generate_arith(mz_jit_state *jitter, Scheme_Object *rator, Scheme_Obj
ref = NULL; ref = NULL;
ref4 = NULL; ref4 = NULL;
} else { } else {
if (!unsafe_fl
&& ((arith == ARITH_MIN)
|| (arith == ARITH_MAX)
|| (arith == ARITH_AND)
|| (arith == ARITH_IOR)
|| (arith == ARITH_XOR))) {
/* No slow path necessary for fixnum arguments. */
if (scheme_jit_is_fixnum(rand) && (!rand2 || scheme_jit_is_fixnum(rand2))) {
unsafe_fx = 1;
}
}
if (rand2) { if (rand2) {
if (SCHEME_INTP(rand2) if (SCHEME_INTP(rand2)
&& SCHEME_INT_SMALL_ENOUGH(rand2) && SCHEME_INT_SMALL_ENOUGH(rand2)
@ -1082,6 +1106,12 @@ int scheme_generate_arith(mz_jit_state *jitter, Scheme_Object *rator, Scheme_Obj
reversed = 1; reversed = 1;
} }
if (!unsafe_fl && !unsafe_fx
&& (scheme_jit_is_fixnum(rand) && (!rand2 || scheme_jit_is_fixnum(rand2)))) {
/* Since we'll get a fix num, skip flonum variant */
has_flonum_fast = 0;
}
if (rand2) { if (rand2) {
int dir; int dir;
dir = scheme_generate_two_args(rand, rand2, jitter, 0, orig_args); dir = scheme_generate_two_args(rand, rand2, jitter, 0, orig_args);
@ -1109,9 +1139,13 @@ int scheme_generate_arith(mz_jit_state *jitter, Scheme_Object *rator, Scheme_Obj
if (rand2) { if (rand2) {
int va; int va;
if (SCHEME_INTP(rand)) { if (scheme_jit_is_fixnum(rand)) {
if (scheme_jit_is_fixnum(rand2)) {
va = -1; /* no check needed */
} else {
va = JIT_R0; /* check only rand2 */ va = JIT_R0; /* check only rand2 */
} else if (SCHEME_INTP(rand2)) { }
} else if (scheme_jit_is_fixnum(rand2)) {
va = JIT_R1; /* check only rand */ va = JIT_R1; /* check only rand */
} else { } else {
if (!unsafe_fx && !unsafe_fl) { if (!unsafe_fx && !unsafe_fl) {
@ -1125,6 +1159,9 @@ int scheme_generate_arith(mz_jit_state *jitter, Scheme_Object *rator, Scheme_Obj
mz_rs_sync(); mz_rs_sync();
__START_TINY_JUMPS_IF_COMPACT__(1); __START_TINY_JUMPS_IF_COMPACT__(1);
if (va == -1)
ref2 = jit_jmpi(jit_forward());
else
ref2 = jit_bmsi_ul(jit_forward(), va, 0x1); ref2 = jit_bmsi_ul(jit_forward(), va, 0x1);
__END_TINY_JUMPS_IF_COMPACT__(1); __END_TINY_JUMPS_IF_COMPACT__(1);
} else { } else {
@ -1145,6 +1182,9 @@ int scheme_generate_arith(mz_jit_state *jitter, Scheme_Object *rator, Scheme_Obj
if (!unsafe_fx && !unsafe_fl) { if (!unsafe_fx && !unsafe_fl) {
if (!has_fixnum_fast) { if (!has_fixnum_fast) {
__START_TINY_JUMPS_IF_COMPACT__(1); __START_TINY_JUMPS_IF_COMPACT__(1);
if (va == -1)
mz_patch_ucbranch(ref2);
else
mz_patch_branch(ref2); mz_patch_branch(ref2);
__END_TINY_JUMPS_IF_COMPACT__(1); __END_TINY_JUMPS_IF_COMPACT__(1);
} }
@ -1155,6 +1195,9 @@ int scheme_generate_arith(mz_jit_state *jitter, Scheme_Object *rator, Scheme_Obj
if (has_fixnum_fast) { if (has_fixnum_fast) {
__START_TINY_JUMPS_IF_COMPACT__(1); __START_TINY_JUMPS_IF_COMPACT__(1);
if (va == -1)
mz_patch_ucbranch(ref2);
else
mz_patch_branch(ref2); mz_patch_branch(ref2);
__END_TINY_JUMPS_IF_COMPACT__(1); __END_TINY_JUMPS_IF_COMPACT__(1);
} }
@ -1166,9 +1209,16 @@ int scheme_generate_arith(mz_jit_state *jitter, Scheme_Object *rator, Scheme_Obj
CHECK_LIMIT(); CHECK_LIMIT();
} else { } else {
/* Only one argument: */ /* Only one argument: */
int is_fx;
is_fx = scheme_jit_is_fixnum(rand);
if (!unsafe_fx && !unsafe_fl) { if (!unsafe_fx && !unsafe_fl) {
mz_rs_sync(); mz_rs_sync();
__START_TINY_JUMPS_IF_COMPACT__(1); __START_TINY_JUMPS_IF_COMPACT__(1);
if (is_fx)
ref2 = jit_jmpi(jit_forward());
else
ref2 = jit_bmsi_ul(jit_forward(), JIT_R0, 0x1); ref2 = jit_bmsi_ul(jit_forward(), JIT_R0, 0x1);
__END_TINY_JUMPS_IF_COMPACT__(1); __END_TINY_JUMPS_IF_COMPACT__(1);
} else { } else {
@ -1193,6 +1243,9 @@ int scheme_generate_arith(mz_jit_state *jitter, Scheme_Object *rator, Scheme_Obj
if (!unsafe_fx && !unsafe_fl) { if (!unsafe_fx && !unsafe_fl) {
if (!has_fixnum_fast) { if (!has_fixnum_fast) {
__START_TINY_JUMPS_IF_COMPACT__(1); __START_TINY_JUMPS_IF_COMPACT__(1);
if (is_fx)
mz_patch_ucbranch(ref2);
else
mz_patch_branch(ref2); mz_patch_branch(ref2);
__END_TINY_JUMPS_IF_COMPACT__(1); __END_TINY_JUMPS_IF_COMPACT__(1);
} }
@ -1203,6 +1256,9 @@ int scheme_generate_arith(mz_jit_state *jitter, Scheme_Object *rator, Scheme_Obj
if (has_fixnum_fast) { if (has_fixnum_fast) {
__START_TINY_JUMPS_IF_COMPACT__(1); __START_TINY_JUMPS_IF_COMPACT__(1);
if (is_fx)
mz_patch_ucbranch(ref2);
else
mz_patch_branch(ref2); mz_patch_branch(ref2);
__END_TINY_JUMPS_IF_COMPACT__(1); __END_TINY_JUMPS_IF_COMPACT__(1);
} }

View File

@ -2026,7 +2026,9 @@ static int generate_binary_char(mz_jit_state *jitter, Scheme_App3_Rec *app,
static int generate_vector_op(mz_jit_state *jitter, int set, int int_ready, int base_offset, static int generate_vector_op(mz_jit_state *jitter, int set, int int_ready, int base_offset,
int for_fl, int unsafe, int for_fl, int unsafe,
int unbox_flonum, int result_ignored, int can_chaperone, int unbox_flonum, int result_ignored, int can_chaperone,
int for_struct, int for_fx, int check_mutable, int dest) int for_struct, int for_fx, int check_mutable,
int known_fixnum_index, int known_fixnum_val,
int dest)
/* R0 has vector. In set mode, R2 has value; if not unboxed, not unsafe, or can chaperone, /* R0 has vector. In set mode, R2 has value; if not unboxed, not unsafe, or can chaperone,
RUNSTACK has space for a temporary (intended for R2). RUNSTACK has space for a temporary (intended for R2).
If int_ready, R1 has num index (for safe or can-chaperone mode) and V1 has pre-computed If int_ready, R1 has num index (for safe or can-chaperone mode) and V1 has pre-computed
@ -2085,9 +2087,9 @@ static int generate_vector_op(mz_jit_state *jitter, int set, int int_ready, int
if (for_struct && unsafe && can_chaperone) if (for_struct && unsafe && can_chaperone)
(void)mz_beqi_t(reffail, JIT_R0, scheme_proc_chaperone_type, JIT_R2); (void)mz_beqi_t(reffail, JIT_R0, scheme_proc_chaperone_type, JIT_R2);
if (!unsafe) { if (!unsafe) {
if (!int_ready) if (!int_ready && !known_fixnum_index)
(void)jit_bmci_ul(reffail, JIT_R1, 0x1); (void)jit_bmci_ul(reffail, JIT_R1, 0x1);
if (set && for_fx) if (set && for_fx && !known_fixnum_val)
(void)jit_bmci_ul(reffail, JIT_R2, 0x1); (void)jit_bmci_ul(reffail, JIT_R2, 0x1);
if (for_fx) { if (for_fx) {
(void)mz_bnei_t(reffail, JIT_R0, scheme_fxvector_type, JIT_R2); (void)mz_bnei_t(reffail, JIT_R0, scheme_fxvector_type, JIT_R2);
@ -2751,12 +2753,14 @@ int scheme_generate_inlined_binary(mz_jit_state *jitter, Scheme_App3_Rec *app, i
if (can_chaperone) scheme_mz_need_space(jitter, 3); if (can_chaperone) scheme_mz_need_space(jitter, 3);
generate_vector_op(jitter, 0, 0, base_offset, 0, unsafe, generate_vector_op(jitter, 0, 0, base_offset, 0, unsafe,
0, 0, can_chaperone, for_struct, for_fx, 0, 0, 0, can_chaperone, for_struct, for_fx, 0,
scheme_jit_is_fixnum(app->rand2), 0,
dest); dest);
CHECK_LIMIT(); CHECK_LIMIT();
} else if (which == 3) { } else if (which == 3) {
/* flvector-ref is relatively simple and worth inlining */ /* flvector-ref is relatively simple and worth inlining */
generate_vector_op(jitter, 0, 0, base_offset, 1, unsafe, generate_vector_op(jitter, 0, 0, base_offset, 1, unsafe,
unbox, 0, can_chaperone, for_struct, for_fx, 0, unbox, 0, can_chaperone, for_struct, for_fx, 0,
scheme_jit_is_fixnum(app->rand2), 0,
dest); dest);
CHECK_LIMIT(); CHECK_LIMIT();
} else if (which == 1) { } else if (which == 1) {
@ -2812,12 +2816,14 @@ int scheme_generate_inlined_binary(mz_jit_state *jitter, Scheme_App3_Rec *app, i
if (can_chaperone) scheme_mz_need_space(jitter, 3); if (can_chaperone) scheme_mz_need_space(jitter, 3);
generate_vector_op(jitter, 0, 1, base_offset, 0, unsafe, generate_vector_op(jitter, 0, 1, base_offset, 0, unsafe,
0, 0, can_chaperone, for_struct, for_fx, 0, 0, 0, can_chaperone, for_struct, for_fx, 0,
scheme_jit_is_fixnum(app->rand2), 0,
dest); dest);
CHECK_LIMIT(); CHECK_LIMIT();
} else if (which == 3) { } else if (which == 3) {
/* flvector-ref is relatively simple and worth inlining */ /* flvector-ref is relatively simple and worth inlining */
generate_vector_op(jitter, 0, 1, base_offset, 1, unsafe, generate_vector_op(jitter, 0, 1, base_offset, 1, unsafe,
unbox, 0, can_chaperone, for_struct, for_fx, 0, unbox, 0, can_chaperone, for_struct, for_fx, 0,
scheme_jit_is_fixnum(app->rand2), 0,
dest); dest);
CHECK_LIMIT(); CHECK_LIMIT();
} else if (which == 1) { } else if (which == 1) {
@ -3455,6 +3461,8 @@ int scheme_generate_inlined_nary(mz_jit_state *jitter, Scheme_App_Rec *app, int
} else if (IS_NAMED_PRIM(rator, "fxvector-set!")) { } else if (IS_NAMED_PRIM(rator, "fxvector-set!")) {
which = 0; which = 0;
for_fx = 1; for_fx = 1;
if (scheme_jit_is_fixnum(app->args[3]))
for_fx = 2;
} else if (IS_NAMED_PRIM(rator, "unsafe-vector*-set!")) { } else if (IS_NAMED_PRIM(rator, "unsafe-vector*-set!")) {
which = 0; which = 0;
unsafe = 1; unsafe = 1;
@ -3464,6 +3472,8 @@ int scheme_generate_inlined_nary(mz_jit_state *jitter, Scheme_App_Rec *app, int
unsafe = 1; unsafe = 1;
can_chaperone = 0; can_chaperone = 0;
for_fx = 1; for_fx = 1;
if (scheme_jit_is_fixnum(app->args[3]))
for_fx = 2;
} else if (IS_NAMED_PRIM(rator, "unsafe-vector-set!")) { } else if (IS_NAMED_PRIM(rator, "unsafe-vector-set!")) {
which = 0; which = 0;
unsafe = 1; unsafe = 1;
@ -3631,13 +3641,17 @@ int scheme_generate_inlined_nary(mz_jit_state *jitter, Scheme_App_Rec *app, int
if (can_chaperone) scheme_mz_need_space(jitter, 3); if (can_chaperone) scheme_mz_need_space(jitter, 3);
generate_vector_op(jitter, 1, 0, base_offset, 0, unsafe, generate_vector_op(jitter, 1, 0, base_offset, 0, unsafe,
flonum_arg, result_ignored, can_chaperone, flonum_arg, result_ignored, can_chaperone,
for_struct, for_fx, check_mutable, dest); for_struct, for_fx, check_mutable,
scheme_jit_is_fixnum(app->args[2]), for_fx > 1,
dest);
CHECK_LIMIT(); CHECK_LIMIT();
} else if (which == 3) { } else if (which == 3) {
/* flvector-set! is relatively simple and worth inlining */ /* flvector-set! is relatively simple and worth inlining */
generate_vector_op(jitter, 1, 0, base_offset, 1, unsafe, generate_vector_op(jitter, 1, 0, base_offset, 1, unsafe,
flonum_arg, result_ignored, can_chaperone, flonum_arg, result_ignored, can_chaperone,
for_struct, for_fx, 0, dest); for_struct, for_fx, 0,
scheme_jit_is_fixnum(app->args[2]), for_fx > 1,
dest);
CHECK_LIMIT(); CHECK_LIMIT();
} else if ((which == 4) || (which == 5)) { } else if ((which == 4) || (which == 5)) {
/* unsafe-{s,u}16vector-set! */ /* unsafe-{s,u}16vector-set! */
@ -3700,7 +3714,9 @@ int scheme_generate_inlined_nary(mz_jit_state *jitter, Scheme_App_Rec *app, int
if (can_chaperone) scheme_mz_need_space(jitter, 3); if (can_chaperone) scheme_mz_need_space(jitter, 3);
generate_vector_op(jitter, 1, 1, base_offset, 0, unsafe, generate_vector_op(jitter, 1, 1, base_offset, 0, unsafe,
flonum_arg, result_ignored, can_chaperone, flonum_arg, result_ignored, can_chaperone,
for_struct, for_fx, check_mutable, dest); for_struct, for_fx, check_mutable,
scheme_jit_is_fixnum(app->args[2]), for_fx > 1,
dest);
CHECK_LIMIT(); CHECK_LIMIT();
} else if ((which == 4) || (which == 5)) { } else if ((which == 4) || (which == 5)) {
/* unsafe-{s,u}16vector-set! */ /* unsafe-{s,u}16vector-set! */
@ -3718,7 +3734,9 @@ int scheme_generate_inlined_nary(mz_jit_state *jitter, Scheme_App_Rec *app, int
/* flvector-set! is relatively simple and worth inlining */ /* flvector-set! is relatively simple and worth inlining */
generate_vector_op(jitter, 1, 1, base_offset, 1, unsafe, generate_vector_op(jitter, 1, 1, base_offset, 1, unsafe,
flonum_arg, result_ignored, can_chaperone, flonum_arg, result_ignored, can_chaperone,
for_struct, for_fx, 0, dest); for_struct, for_fx, 0,
scheme_jit_is_fixnum(app->args[2]), for_fx > 1,
dest);
CHECK_LIMIT(); CHECK_LIMIT();
} else if (which == 1) { } else if (which == 1) {
if (unsafe) { if (unsafe) {

View File

@ -2046,6 +2046,7 @@ static int produces_local_type(Scheme_Object *rator, int argc)
} }
int scheme_expr_produces_local_type(Scheme_Object *expr) int scheme_expr_produces_local_type(Scheme_Object *expr)
/* can be called by the JIT */
{ {
while (1) { while (1) {
switch (SCHEME_TYPE(expr)) { switch (SCHEME_TYPE(expr)) {