tweak JIT to improve and slightly generalize register tracking

This commit is contained in:
Matthew Flatt 2011-07-14 14:06:44 -06:00
parent 87a6b850a7
commit 825548f5dc
5 changed files with 82 additions and 37 deletions

View File

@ -1340,7 +1340,7 @@ static int generate_non_tail_with_branch(Scheme_Object *obj, mz_jit_state *jitte
CHECK_LIMIT();
scheme_mz_flostack_restore(jitter, flostack, flostack_pos, !for_branch, 1);
FOR_LOG(--jitter->log_depth);
/* mz_CLEAR_R0_STATUS(); --- not needed, since stack doesn't change */
/* mz_SET_REG_STATUS_VALID(0); --- not needed, since stack doesn't change */
return v;
}
@ -1429,7 +1429,7 @@ static int generate_non_tail_with_branch(Scheme_Object *obj, mz_jit_state *jitte
}
jitter->pushed_marks = save_pushed_marks;
mz_CLEAR_R0_STATUS();
mz_SET_REG_STATUS_VALID(0);
END_JIT_DATA(21);
}
@ -1654,7 +1654,7 @@ static int generate_branch(Scheme_Object *obj, mz_jit_state *jitter, int is_tail
scheme_signal_error("internal error: self position moved across branch");
/* False branch */
mz_CLEAR_R0_STATUS();
mz_SET_REG_STATUS_VALID(0);
scheme_mz_runstack_saved(jitter);
flostack = scheme_mz_flostack_save(jitter, &flostack_pos);
__START_SHORT_JUMPS__(then_short_ok);
@ -1718,7 +1718,7 @@ static int generate_branch(Scheme_Object *obj, mz_jit_state *jitter, int is_tail
if (nsrs1)
jitter->need_set_rs = 1;
mz_CLEAR_R0_STATUS();
mz_SET_REG_STATUS_VALID(0);
return 1;
}
@ -1820,19 +1820,44 @@ int scheme_generate(Scheme_Object *obj, mz_jit_state *jitter, int is_tail, int w
pos = mz_remap(SCHEME_LOCAL_POS(obj));
LOG_IT(("local %d [%d]\n", pos, SCHEME_LOCAL_FLAGS(obj)));
if (!result_ignored && (!flonum || !jitter->unbox)) {
int old_r0 = -1;
if (mz_CURRENT_R0_STATUS_VALID()) old_r0 = mz_CURRENT_R0_STATUS();
if (pos != old_r0) {
int valid, old_r0 = -1, old_r1 = -1;
if (mz_CURRENT_REG_STATUS_VALID()) {
valid = 1;
old_r0 = jitter->r0_status;
old_r1 = jitter->r1_status;
} else
valid = 0;
if (pos == old_r0) {
if (target != JIT_R0) {
jit_movr_p(target, JIT_R0);
if (target == JIT_R1)
jitter->r1_status = pos;
mz_SET_REG_STATUS_VALID(1);
}
} else if (pos == old_r1) {
if (target != JIT_R1) {
jit_movr_p(target, JIT_R1);
if (target == JIT_R0)
jitter->r1_status = pos;
mz_SET_REG_STATUS_VALID(1);
}
} else {
mz_rs_ldxi(target, pos);
VALIDATE_RESULT(target);
if (target == JIT_R0)
mz_RECORD_R0_STATUS(pos);
else {
/* R0 is unchanged */
mz_RECORD_R0_STATUS(old_r0);
if (target == JIT_R0) {
jitter->r0_status = pos;
jitter->r1_status = old_r1;
mz_SET_REG_STATUS_VALID(1);
} else if (target == JIT_R1) {
jitter->r1_status = pos;
jitter->r0_status = old_r0;
mz_SET_REG_STATUS_VALID(1);
} else if (valid) {
/* R0 and R1 are unchanged */
mz_SET_REG_STATUS_VALID(1);
}
} else if (target != JIT_R0) {
jit_movr_p(target, JIT_R0);
}
}
if (SCHEME_GET_LOCAL_FLAGS(obj) == SCHEME_LOCAL_CLEAR_ON_READ) {
@ -2721,7 +2746,9 @@ int scheme_generate(Scheme_Object *obj, mz_jit_state *jitter, int is_tail, int w
if (!unused) {
mz_rs_str(JIT_R0);
mz_RECORD_R0_STATUS(0);
jitter->r0_status = 0;
jitter->r1_status = -1;
mz_SET_REG_STATUS_VALID(1);
}
END_JIT_DATA(17);

View File

@ -310,7 +310,7 @@ typedef struct {
Scheme_Native_Closure *nc; /* for extract_globals and extract_closure_local, only */
Scheme_Closure_Data *self_data;
void *status_at_ptr;
int reg_status;
int r0_status, r1_status;
void *patch_depth;
int rs_virtual_offset;
int unbox, unbox_depth;
@ -340,10 +340,11 @@ typedef struct {
Branch_Info_Addr *addrs;
} Branch_Info;
#define mz_RECORD_R0_STATUS(s) (jitter->status_at_ptr = _jit.x.pc, jitter->reg_status = (s))
#define mz_CURRENT_R0_STATUS_VALID() (jitter->status_at_ptr == _jit.x.pc)
#define mz_CURRENT_R0_STATUS() (jitter->reg_status)
#define mz_CLEAR_R0_STATUS() (jitter->status_at_ptr = 0)
#define mz_CURRENT_REG_STATUS_VALID() (jitter->status_at_ptr == _jit.x.pc)
#define mz_SET_REG_STATUS_VALID(v) (jitter->status_at_ptr = (v ? _jit.x.pc : 0))
#define mz_SET_R0_STATUS_VALID(v) (jitter->status_at_ptr = (v ? _jit.x.pc : 0), \
jitter->r1_status = -1)
/* If JIT_THREAD_LOCAL is defined, then access to global variables
goes through a thread_local_pointers table. Call
@ -511,8 +512,12 @@ static void *top4;
register. */
#if 1
# define mz_rs_dec(n) (((jitter->reg_status >= 0) ? jitter->reg_status += (n) : 0), jitter->rs_virtual_offset -= (n))
# define mz_rs_inc(n) (jitter->reg_status -= (n), jitter->rs_virtual_offset += (n))
# define mz_rs_dec(n) (((jitter->r0_status >= 0) ? jitter->r0_status += (n) : 0), \
((jitter->r1_status >= 0) ? jitter->r1_status += (n) : 0), \
jitter->rs_virtual_offset -= (n))
# define mz_rs_inc(n) (jitter->r0_status -= (n), \
jitter->r1_status -= (n), \
jitter->rs_virtual_offset += (n))
# define mz_rs_ldxi(reg, n) jit_ldxi_p(reg, JIT_RUNSTACK, WORDS_TO_BYTES(((n) + jitter->rs_virtual_offset)))
# define mz_rs_ldr(reg) mz_rs_ldxi(reg, 0)
# define mz_rs_stxi(n, reg) jit_stxi_p(WORDS_TO_BYTES(((n) + jitter->rs_virtual_offset)), JIT_RUNSTACK, reg)

View File

@ -1085,8 +1085,7 @@ int scheme_generate_arith(mz_jit_state *jitter, Scheme_Object *rator, Scheme_Obj
va = JIT_R0;
} else {
if (simple_rand) {
pos = mz_remap(SCHEME_LOCAL_POS(rand));
mz_rs_ldxi(JIT_R1, pos);
scheme_generate(rand, jitter, 0, 0, 0, JIT_R1, NULL);
}
if (!unsafe_fx && !unsafe_fl) {
/* check both fixnum bits at once by ANDing into R2: */

View File

@ -1639,9 +1639,9 @@ int scheme_generate_app(Scheme_App_Rec *app, Scheme_Object **alt_rands, int num_
&& (!direct_self || !is_tail || no_call || (i + 1 < num_rands))
&& !inline_direct_args) {
int r0;
r0 = (mz_CURRENT_R0_STATUS_VALID() ? mz_CURRENT_R0_STATUS() : -1);
r0 = mz_CURRENT_REG_STATUS_VALID();
mz_rs_stxi(i + offset, JIT_R0);
if (r0 > -1) mz_RECORD_R0_STATUS(r0);
mz_SET_REG_STATUS_VALID(r0);
}
}
/* not sync'd... */

View File

@ -177,7 +177,7 @@ static int generate_inlined_type_test(mz_jit_state *jitter, Scheme_App2_Rec *app
Branch_Info *for_branch, int branch_short, int need_sync)
{
GC_CAN_IGNORE jit_insn *ref, *ref2, *ref3, *ref4, *ref5;
int int_ok, r0_set, r0;
int int_ok, reg_valid;
int_ok = ((lo_ty <= scheme_integer_type) && (scheme_integer_type <= hi_ty));
@ -194,13 +194,9 @@ static int generate_inlined_type_test(mz_jit_state *jitter, Scheme_App2_Rec *app
__START_SHORT_JUMPS__(branch_short);
r0_set = 0;
r0 = 0;
reg_valid = 0;
if (for_branch) {
if (mz_CURRENT_R0_STATUS_VALID()) {
r0_set = 1;
r0 = mz_CURRENT_R0_STATUS();
}
reg_valid = mz_CURRENT_REG_STATUS_VALID();
scheme_prepare_branch_jump(jitter, for_branch);
CHECK_LIMIT();
}
@ -256,9 +252,7 @@ static int generate_inlined_type_test(mz_jit_state *jitter, Scheme_App2_Rec *app
/* In case true is a fall-through, note that the test
didn't disturb R0: */
if (r0_set) {
mz_RECORD_R0_STATUS(r0);
}
mz_SET_R0_STATUS_VALID(reg_valid);
scheme_branch_for_true(jitter, for_branch);
CHECK_LIMIT();
@ -1261,6 +1255,7 @@ static int generate_two_args(Scheme_Object *rand1, Scheme_Object *rand2, mz_jit_
scheme_generate_non_tail(rand1, jitter, 0, 1, 0); /* no sync... */
CHECK_LIMIT();
jit_movr_p(JIT_R1, JIT_R0);
scheme_generate(rand2, jitter, 0, 0, 0, JIT_R0, NULL); /* no sync... */
@ -1268,9 +1263,18 @@ static int generate_two_args(Scheme_Object *rand1, Scheme_Object *rand2, mz_jit_
if (order_matters) {
/* Swap arguments: */
int reg_status;
reg_status = mz_CURRENT_REG_STATUS_VALID();
jit_movr_p(JIT_R2, JIT_R0);
jit_movr_p(JIT_R0, JIT_R1);
jit_movr_p(JIT_R1, JIT_R2);
if (reg_status) {
int pos;
pos = jitter->r0_status;
jitter->r0_status = jitter->r1_status;
jitter->r1_status = pos;
mz_SET_REG_STATUS_VALID(1);
}
} else
direction = -1;
@ -1673,7 +1677,7 @@ int scheme_generate_inlined_binary(mz_jit_state *jitter, Scheme_App3_Rec *app, i
if (SCHEME_TYPE(a1) > _scheme_values_types_) {
/* Compare to constant: */
int retptr;
int retptr, reg_status;
mz_runstack_skipped(jitter, 2);
@ -1697,6 +1701,8 @@ int scheme_generate_inlined_binary(mz_jit_state *jitter, Scheme_App3_Rec *app, i
scheme_prepare_branch_jump(jitter, for_branch);
CHECK_LIMIT();
}
reg_status = mz_CURRENT_REG_STATUS_VALID();
#ifdef JIT_PRECISE_GC
if (retptr) {
@ -1707,6 +1713,14 @@ int scheme_generate_inlined_binary(mz_jit_state *jitter, Scheme_App3_Rec *app, i
ref = mz_bnei_p(jit_forward(), JIT_R0, a1);
if (for_branch) {
/* In case true is a fall-through, note that the test
didn't disturb R0 (and maybe not R1): */
#ifdef JIT_PRECISE_GC
if (retptr)
mz_SET_R0_STATUS_VALID(reg_status);
else
#endif
mz_SET_REG_STATUS_VALID(reg_status);
scheme_add_branch_false(for_branch, ref);
scheme_branch_for_true(jitter, for_branch);
CHECK_LIMIT();