JIT-inline `eqv?'

This commit is contained in:
Matthew Flatt 2011-04-22 21:20:50 -06:00
parent e78a60016f
commit f54d977de1
5 changed files with 150 additions and 2 deletions

View File

@ -15,7 +15,7 @@
(namespace-require 'racket/flonum) (namespace-require 'racket/flonum)
(namespace-require 'racket/fixnum) (namespace-require 'racket/fixnum)
(let* ([check-error-message (lambda (name proc [fixnum? #f]) (let* ([check-error-message (lambda (name proc [fixnum? #f])
(unless (memq name '(eq? not null? pair? list? (unless (memq name '(eq? eqv? not null? pair? list?
real? number? boolean? real? number? boolean?
procedure? symbol? procedure? symbol?
string? bytes? string? bytes?
@ -173,6 +173,22 @@
(un #t 'bytes? #"apple") (un #t 'bytes? #"apple")
(bin #f 'eq? 0 10) (bin #f 'eq? 0 10)
(bin-exact #t 'eq? 10 10)
(bin-exact #f 'eqv? 0 10)
(bin-exact #f 'eqv? "apple" "banana")
(bin-exact #t 'eqv? 10 10)
(bin-exact #t 'eqv? #\a #\a)
(bin-exact #f 'eqv? #\a #\b)
(bin-exact #t 'eqv? #\u3bb #\u3bb)
(bin-exact #f 'eqv? #\u3bb #\u3bc)
(bin-exact #t 'eqv? 1.0 1.0)
(bin-exact #f 'eqv? 1.0 2.0)
(bin-exact #t 'eqv? +nan.0 +nan.0)
(bin-exact #t 'eqv? 1/2 1/2)
(bin-exact #f 'eqv? 1/2 1/3)
(bin-exact #t 'eqv? 1+2i 1+2i)
(bin-exact #f 'eqv? 1+2i 1+3i)
(un #t 'zero? 0) (un #t 'zero? 0)
(un #f 'zero? 1) (un #f 'zero? 1)

View File

@ -95,7 +95,9 @@ void scheme_init_bool (Scheme_Env *env)
scheme_eq_prim = p; scheme_eq_prim = p;
scheme_add_global_constant("eq?", p, env); scheme_add_global_constant("eq?", p, env);
scheme_eqv_prim = scheme_make_folding_prim(eqv_prim, "eqv?", 2, 2, 1); p = scheme_make_folding_prim(eqv_prim, "eqv?", 2, 2, 1);
SCHEME_PRIM_PROC_FLAGS(p) |= SCHEME_PRIM_IS_BINARY_INLINED;
scheme_eqv_prim = p;
scheme_add_global_constant("eqv?", scheme_eqv_prim, env); scheme_add_global_constant("eqv?", scheme_eqv_prim, env);
scheme_equal_prim = scheme_make_prim_w_arity(equal_prim, "equal?", 2, 2); scheme_equal_prim = scheme_make_prim_w_arity(equal_prim, "equal?", 2, 2);

View File

@ -244,6 +244,7 @@ struct scheme_jit_common_record {
void *fl1_fail_code, *fl2rr_fail_code[2], *fl2fr_fail_code[2], *fl2rf_fail_code[2]; void *fl1_fail_code, *fl2rr_fail_code[2], *fl2fr_fail_code[2], *fl2rf_fail_code[2];
void *wcm_code, *wcm_nontail_code; void *wcm_code, *wcm_nontail_code;
void *apply_to_list_tail_code, *apply_to_list_code, *apply_to_list_multi_ok_code; void *apply_to_list_tail_code, *apply_to_list_code, *apply_to_list_multi_ok_code;
void *eqv_code, *eqv_branch_code;
#ifdef CAN_INLINE_ALLOC #ifdef CAN_INLINE_ALLOC
void *make_list_code, *make_list_star_code; void *make_list_code, *make_list_star_code;

View File

@ -2023,6 +2023,63 @@ static int common8(mz_jit_state *jitter, void *_data)
return 1; return 1;
} }
static int common9(mz_jit_state *jitter, void *_data)
{
int i;
/* eqv[_branch]_code */
/* arguments in R0 and R1; for branch, false return address in V1 */
for (i = 0; i < 2; i++) {
void *code;
GC_CAN_IGNORE jit_insn *ref;
code = jit_get_ip().ptr;
if (i == 0)
sjc.eqv_code = code;
else
sjc.eqv_branch_code = code;
mz_prolog(JIT_R2);
CHECK_LIMIT();
jit_prepare(2);
jit_pusharg_p(JIT_R0);
jit_pusharg_p(JIT_R1);
(void)jit_finish(scheme_eqv); /* NONGCING, so ok from a future thread */
jit_retval(JIT_R0);
CHECK_LIMIT();
__START_TINY_JUMPS__(1);
ref = jit_beqi_i(jit_forward(), JIT_R0, 0);
__END_TINY_JUMPS__(1);
if (i) {
mz_epilog(JIT_R2);
} else {
(void)jit_movi_p(JIT_R0, scheme_true);
mz_epilog(JIT_R2);
}
__START_TINY_JUMPS__(1);
mz_patch_branch(ref);
__END_TINY_JUMPS__(1);
if (i) {
mz_epilog_without_jmp();
jit_jmpr(JIT_V1);
} else {
(void)jit_movi_p(JIT_R0, scheme_false);
mz_epilog(JIT_R2);
}
scheme_jit_register_sub_func(jitter, code, scheme_false);
CHECK_LIMIT();
}
return 1;
}
int scheme_do_generate_common(mz_jit_state *jitter, void *_data) int scheme_do_generate_common(mz_jit_state *jitter, void *_data)
{ {
if (!common0(jitter, _data)) return 0; if (!common0(jitter, _data)) return 0;
@ -2035,6 +2092,7 @@ int scheme_do_generate_common(mz_jit_state *jitter, void *_data)
if (!common6(jitter, _data)) return 0; if (!common6(jitter, _data)) return 0;
if (!common7(jitter, _data)) return 0; if (!common7(jitter, _data)) return 0;
if (!common8(jitter, _data)) return 0; if (!common8(jitter, _data)) return 0;
if (!common9(jitter, _data)) return 0;
return 1; return 1;
} }

View File

@ -1697,6 +1697,77 @@ int scheme_generate_inlined_binary(mz_jit_state *jitter, Scheme_App3_Rec *app, i
__END_SHORT_JUMPS__(branch_short); __END_SHORT_JUMPS__(branch_short);
} }
return 1;
} else if (IS_NAMED_PRIM(rator, "eqv?")) {
GC_CAN_IGNORE jit_insn *ref_f1, *ref_f2, *ref_f3, *ref_f4, *ref_f5;
GC_CAN_IGNORE jit_insn *ref_d1, *ref_d2, *ref_t1;
generate_two_args(app->rand1, app->rand2, jitter, 0, 2);
CHECK_LIMIT();
if (need_sync) mz_rs_sync();
__START_SHORT_JUMPS__(branch_short);
if (for_branch) {
scheme_prepare_branch_jump(jitter, for_branch);
CHECK_LIMIT();
}
/* eq? */
ref_t1 = jit_beqr_p(jit_forward(), JIT_R0, JIT_R1);
/* if either is fixnum, result is false */
ref_f1 = jit_bmsi_ul(jit_forward(), JIT_R0, 0x1);
ref_f2 = jit_bmsi_ul(jit_forward(), JIT_R1, 0x1);
CHECK_LIMIT();
/* Both have a tag */
jit_ldxi_s(JIT_R2, JIT_R0, &((Scheme_Object *)0x0)->type);
jit_ldxi_s(JIT_V1, JIT_R1, &((Scheme_Object *)0x0)->type);
ref_f3 = jit_bner_i(jit_forward(), JIT_R2, JIT_V1);
/* check in range of type treated by eqv: */
ref_f4 = jit_blti_i(jit_forward(), JIT_R2, scheme_char_type);
ref_f5 = jit_bgti_i(jit_forward(), JIT_R2, scheme_complex_type);
CHECK_LIMIT();
/* in range of interesting types, so break out the generic comparison */
if (for_branch) {
scheme_add_branch_false_movi(for_branch, jit_patchable_movi_p(JIT_V1, jit_forward()));
(void)jit_calli(sjc.eqv_branch_code);
scheme_add_branch_false(for_branch, ref_f1);
scheme_add_branch_false(for_branch, ref_f2);
scheme_add_branch_false(for_branch, ref_f3);
scheme_add_branch_false(for_branch, ref_f4);
scheme_add_branch_false(for_branch, ref_f5);
mz_patch_branch(ref_t1);
scheme_branch_for_true(jitter, for_branch);
} else {
(void)jit_calli(sjc.eqv_code);
jit_retval(JIT_R0);
ref_d1 = jit_jmpi(jit_forward());
mz_patch_branch(ref_t1);
jit_movi_p(JIT_R0, scheme_true);
ref_d2 = jit_jmpi(jit_forward());
mz_patch_branch(ref_f1);
mz_patch_branch(ref_f2);
mz_patch_branch(ref_f3);
mz_patch_branch(ref_f4);
mz_patch_branch(ref_f5);
jit_movi_p(JIT_R0, scheme_false);
mz_patch_ucbranch(ref_d1);
mz_patch_ucbranch(ref_d2);
}
__END_SHORT_JUMPS__(branch_short);
return 1; return 1;
} else if (IS_NAMED_PRIM(rator, "=")) { } else if (IS_NAMED_PRIM(rator, "=")) {
scheme_generate_arith(jitter, rator, app->rand1, app->rand2, 2, 0, 0, 0, for_branch, branch_short, 0, 0, NULL); scheme_generate_arith(jitter, rator, app->rand1, app->rand2, 2, 0, 0, 0, for_branch, branch_short, 0, 0, NULL);