From be4ce3ed66e81b4be5bf54b21557a47fb61d5f0c Mon Sep 17 00:00:00 2001 From: Matthew Flatt Date: Sat, 17 Nov 2012 08:49:36 -0700 Subject: [PATCH] skip some unneeded fixnum tests in JIT-generated code --- collects/tests/racket/optimize.rktl | 10 +++- src/racket/src/jit.h | 1 + src/racket/src/jitarith.c | 74 +++++++++++++++++++++++++---- src/racket/src/jitinline.c | 32 ++++++++++--- src/racket/src/optimize.c | 1 + 5 files changed, 101 insertions(+), 17 deletions(-) diff --git a/collects/tests/racket/optimize.rktl b/collects/tests/racket/optimize.rktl index 69d096b529..d7ae1fc779 100644 --- a/collects/tests/racket/optimize.rktl +++ b/collects/tests/racket/optimize.rktl @@ -81,7 +81,15 @@ (when (boolean? v) ;; (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 ',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]) (check-error-message op (eval `(lambda (x) (,op x ',arg2)))) (check-error-message op (eval `(lambda (x) (,op ',arg1 x)))) diff --git a/src/racket/src/jit.h b/src/racket/src/jit.h index e417152811..e2124a0483 100644 --- a/src/racket/src/jit.h +++ b/src/racket/src/jit.h @@ -1263,6 +1263,7 @@ Scheme_Object *scheme_jit_make_two_element_ivector(Scheme_Object *a, Scheme_Obje /* 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_directly(Scheme_Object *obj); int scheme_generate_unboxing(mz_jit_state *jitter, int target); diff --git a/src/racket/src/jitarith.c b/src/racket/src/jitarith.c index 604b4d41c3..009c134ed3 100644 --- a/src/racket/src/jitarith.c +++ b/src/racket/src/jitarith.c @@ -30,6 +30,18 @@ #define JITARITH_TS_PROCS #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) { /* 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; ref4 = NULL; } 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 (SCHEME_INTP(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; } + 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) { int dir; 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) { int va; - if (SCHEME_INTP(rand)) { - va = JIT_R0; /* check only rand2 */ - } else if (SCHEME_INTP(rand2)) { + if (scheme_jit_is_fixnum(rand)) { + if (scheme_jit_is_fixnum(rand2)) { + va = -1; /* no check needed */ + } else { + va = JIT_R0; /* check only rand2 */ + } + } else if (scheme_jit_is_fixnum(rand2)) { va = JIT_R1; /* check only rand */ } else { if (!unsafe_fx && !unsafe_fl) { @@ -1125,7 +1159,10 @@ int scheme_generate_arith(mz_jit_state *jitter, Scheme_Object *rator, Scheme_Obj mz_rs_sync(); __START_TINY_JUMPS_IF_COMPACT__(1); - ref2 = jit_bmsi_ul(jit_forward(), va, 0x1); + if (va == -1) + ref2 = jit_jmpi(jit_forward()); + else + ref2 = jit_bmsi_ul(jit_forward(), va, 0x1); __END_TINY_JUMPS_IF_COMPACT__(1); } else { ref2 = NULL; @@ -1145,7 +1182,10 @@ int scheme_generate_arith(mz_jit_state *jitter, Scheme_Object *rator, Scheme_Obj if (!unsafe_fx && !unsafe_fl) { if (!has_fixnum_fast) { __START_TINY_JUMPS_IF_COMPACT__(1); - mz_patch_branch(ref2); + if (va == -1) + mz_patch_ucbranch(ref2); + else + mz_patch_branch(ref2); __END_TINY_JUMPS_IF_COMPACT__(1); } @@ -1155,7 +1195,10 @@ int scheme_generate_arith(mz_jit_state *jitter, Scheme_Object *rator, Scheme_Obj if (has_fixnum_fast) { __START_TINY_JUMPS_IF_COMPACT__(1); - mz_patch_branch(ref2); + if (va == -1) + mz_patch_ucbranch(ref2); + else + mz_patch_branch(ref2); __END_TINY_JUMPS_IF_COMPACT__(1); } } else { @@ -1166,10 +1209,17 @@ int scheme_generate_arith(mz_jit_state *jitter, Scheme_Object *rator, Scheme_Obj CHECK_LIMIT(); } else { /* Only one argument: */ + int is_fx; + + is_fx = scheme_jit_is_fixnum(rand); + if (!unsafe_fx && !unsafe_fl) { mz_rs_sync(); __START_TINY_JUMPS_IF_COMPACT__(1); - ref2 = jit_bmsi_ul(jit_forward(), JIT_R0, 0x1); + if (is_fx) + ref2 = jit_jmpi(jit_forward()); + else + ref2 = jit_bmsi_ul(jit_forward(), JIT_R0, 0x1); __END_TINY_JUMPS_IF_COMPACT__(1); } else { if (for_branch) mz_rs_sync(); @@ -1193,7 +1243,10 @@ int scheme_generate_arith(mz_jit_state *jitter, Scheme_Object *rator, Scheme_Obj if (!unsafe_fx && !unsafe_fl) { if (!has_fixnum_fast) { __START_TINY_JUMPS_IF_COMPACT__(1); - mz_patch_branch(ref2); + if (is_fx) + mz_patch_ucbranch(ref2); + else + mz_patch_branch(ref2); __END_TINY_JUMPS_IF_COMPACT__(1); } @@ -1203,7 +1256,10 @@ int scheme_generate_arith(mz_jit_state *jitter, Scheme_Object *rator, Scheme_Obj if (has_fixnum_fast) { __START_TINY_JUMPS_IF_COMPACT__(1); - mz_patch_branch(ref2); + if (is_fx) + mz_patch_ucbranch(ref2); + else + mz_patch_branch(ref2); __END_TINY_JUMPS_IF_COMPACT__(1); } } else { diff --git a/src/racket/src/jitinline.c b/src/racket/src/jitinline.c index 8bf749ad42..0c148bca3c 100644 --- a/src/racket/src/jitinline.c +++ b/src/racket/src/jitinline.c @@ -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, int for_fl, int unsafe, 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, 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 @@ -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) (void)mz_beqi_t(reffail, JIT_R0, scheme_proc_chaperone_type, JIT_R2); if (!unsafe) { - if (!int_ready) + if (!int_ready && !known_fixnum_index) (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); if (for_fx) { (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); generate_vector_op(jitter, 0, 0, base_offset, 0, unsafe, 0, 0, can_chaperone, for_struct, for_fx, 0, + scheme_jit_is_fixnum(app->rand2), 0, dest); CHECK_LIMIT(); } else if (which == 3) { /* flvector-ref is relatively simple and worth inlining */ generate_vector_op(jitter, 0, 0, base_offset, 1, unsafe, unbox, 0, can_chaperone, for_struct, for_fx, 0, + scheme_jit_is_fixnum(app->rand2), 0, dest); CHECK_LIMIT(); } 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); generate_vector_op(jitter, 0, 1, base_offset, 0, unsafe, 0, 0, can_chaperone, for_struct, for_fx, 0, + scheme_jit_is_fixnum(app->rand2), 0, dest); CHECK_LIMIT(); } else if (which == 3) { /* flvector-ref is relatively simple and worth inlining */ generate_vector_op(jitter, 0, 1, base_offset, 1, unsafe, unbox, 0, can_chaperone, for_struct, for_fx, 0, + scheme_jit_is_fixnum(app->rand2), 0, dest); CHECK_LIMIT(); } 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!")) { which = 0; for_fx = 1; + if (scheme_jit_is_fixnum(app->args[3])) + for_fx = 2; } else if (IS_NAMED_PRIM(rator, "unsafe-vector*-set!")) { which = 0; unsafe = 1; @@ -3464,6 +3472,8 @@ int scheme_generate_inlined_nary(mz_jit_state *jitter, Scheme_App_Rec *app, int unsafe = 1; can_chaperone = 0; for_fx = 1; + if (scheme_jit_is_fixnum(app->args[3])) + for_fx = 2; } else if (IS_NAMED_PRIM(rator, "unsafe-vector-set!")) { which = 0; 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); generate_vector_op(jitter, 1, 0, base_offset, 0, unsafe, 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(); } else if (which == 3) { /* flvector-set! is relatively simple and worth inlining */ generate_vector_op(jitter, 1, 0, base_offset, 1, unsafe, 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(); } else if ((which == 4) || (which == 5)) { /* 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); generate_vector_op(jitter, 1, 1, base_offset, 0, unsafe, 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(); } else if ((which == 4) || (which == 5)) { /* 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 */ generate_vector_op(jitter, 1, 1, base_offset, 1, unsafe, 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(); } else if (which == 1) { if (unsafe) { diff --git a/src/racket/src/optimize.c b/src/racket/src/optimize.c index a8c59dd2c8..1ddf2fb55f 100644 --- a/src/racket/src/optimize.c +++ b/src/racket/src/optimize.c @@ -2046,6 +2046,7 @@ static int produces_local_type(Scheme_Object *rator, int argc) } int scheme_expr_produces_local_type(Scheme_Object *expr) +/* can be called by the JIT */ { while (1) { switch (SCHEME_TYPE(expr)) {