From 5a4f74ccaff640f56c74a5532656310626abe08b Mon Sep 17 00:00:00 2001 From: Nick Gasson Date: Tue, 13 Feb 2024 22:15:59 +0000 Subject: [PATCH] Extend local value numbering to argument slots --- src/jit/jit-optim.c | 49 +++++++++++++++++++++++++++++++++++++++++++-- test/test_jit.c | 31 ++++++++++++++++++++++++++++ 2 files changed, 78 insertions(+), 2 deletions(-) diff --git a/src/jit/jit-optim.c b/src/jit/jit-optim.c index eca86b21..92884fea 100644 --- a/src/jit/jit-optim.c +++ b/src/jit/jit-optim.c @@ -284,6 +284,7 @@ typedef unsigned valnum_t; #define SMALL_CONST 100 #define MAX_CONSTS 32 #define FIRST_VN (SMALL_CONST + MAX_CONSTS) +#define TRACK_ARGS 8 #define LVN_REG(r) ((jit_value_t){ .kind = JIT_VALUE_REG, .reg = (r) }) #define LVN_CONST(i) ((jit_value_t){ .kind = JIT_VALUE_INT64, .int64 = (i) }) @@ -415,6 +416,12 @@ static inline void lvn_kill_flags(lvn_state_t *state) state->regvn[state->func->nregs] = VN_INVALID; } +static void lvn_kill_args(lvn_state_t *state) +{ + for (int i = 0; i < TRACK_ARGS; i++) + state->regvn[state->func->nregs + i + 1] = VN_INVALID; +} + static void lvn_commute_const(jit_ir_t *ir, lvn_state_t *state) { assert(lvn_is_commutative(ir->op)); @@ -755,6 +762,38 @@ static void jit_lvn_clamp(jit_ir_t *ir, lvn_state_t *state) jit_lvn_generic(ir, state, VN_INVALID); } +static void jit_lvn_recv(jit_ir_t *ir, lvn_state_t *state) +{ + const unsigned nth = ir->arg1.int64; + if (nth >= TRACK_ARGS) + return; + + const unsigned vreg = state->func->nregs + 1 + nth; + + if (state->regvn[vreg] != VN_INVALID) + state->regvn[ir->result] = state->regvn[vreg]; + else { + valnum_t vn = lvn_new_value(state); + state->regvn[vreg] = vn; + state->regvn[ir->result] = vn; + } +} + +static void jit_lvn_send(jit_ir_t *ir, lvn_state_t *state) +{ + const unsigned nth = ir->arg1.int64; + if (nth >= TRACK_ARGS) + return; + else if (ir->arg2.kind != JIT_VALUE_REG) + return; + + const unsigned vreg = state->func->nregs + 1 + nth; + + valnum_t vn = lvn_value_num(ir->arg2, state); + if (vn != VN_INVALID && state->regvn[vreg] == vn) + lvn_convert_nop(ir); // Already in argument slot +} + static void jit_lvn_copy(jit_ir_t *ir, lvn_state_t *state) { if (ir->op == MACRO_MOVE && ir->arg2.kind == JIT_ADDR_CPOOL) @@ -903,7 +942,7 @@ void jit_do_lvn(jit_func_t *f) .nextvn = FIRST_VN }; - state.regvn = xmalloc_array(f->nregs + 1, sizeof(valnum_t)); + state.regvn = xmalloc_array(f->nregs + 1 + TRACK_ARGS, sizeof(valnum_t)); state.hashtab = xcalloc_array(state.tabsz, sizeof(lvn_tab_t)); bool reset = true; @@ -911,7 +950,7 @@ void jit_do_lvn(jit_func_t *f) reset = cfg_is_terminator(f, ir), ir++) { if (reset || ir->target) { - for (int j = 0; j < f->nregs + 1; j++) + for (int j = 0; j < f->nregs + 1 + TRACK_ARGS; j++) state.regvn[j] = VN_INVALID; } @@ -930,11 +969,17 @@ void jit_do_lvn(jit_func_t *f) case J_CSET: jit_lvn_cset(ir, &state); break; case J_JUMP: jit_lvn_jump(ir, &state); break; case J_CLAMP: jit_lvn_clamp(ir, &state); break; + case J_RECV: jit_lvn_recv(ir, &state); break; + case J_SEND: jit_lvn_send(ir, &state); break; case MACRO_MOVE: case MACRO_COPY: jit_lvn_copy(ir, &state); break; case MACRO_BZERO: jit_lvn_bzero(ir, &state); break; case MACRO_MEMSET: jit_lvn_memset(ir, &state); break; case MACRO_EXP: jit_lvn_exp(ir, &state); break; + case MACRO_EXIT: + case J_CALL: + lvn_kill_args(&state); + // Fall-through default: if (jit_writes_flags(ir)) state.regvn[f->nregs] = VN_INVALID; diff --git a/test/test_jit.c b/test/test_jit.c index 9651964b..d6eafe67 100644 --- a/test/test_jit.c +++ b/test/test_jit.c @@ -1953,6 +1953,36 @@ START_TEST(test_code1) } END_TEST +START_TEST(test_lvn10) +{ + jit_t *j = jit_new(NULL); + + const char *text1 = + " RECV R0, #0 \n" + " RECV R1, #1 \n" + " RECV R2, #2 \n" + " SEND #0, R0 \n" + " SEND #1, R1 \n" + " SEND #2, R2 \n" + " $EXIT #1 \n" + " RECV R3, #0 \n" + " SEND #0, R3 \n" + " RET \n"; + + jit_handle_t h1 = jit_assemble(j, ident_new("myfunc1"), text1); + + jit_func_t *f = jit_get_func(j, h1); + jit_do_lvn(f); + + ck_assert_int_eq(f->irbuf[3].op, J_NOP); + ck_assert_int_eq(f->irbuf[4].op, J_NOP); + ck_assert_int_eq(f->irbuf[5].op, J_NOP); + ck_assert_int_eq(f->irbuf[8].op, J_NOP); + + jit_free(j); +} +END_TEST + Suite *get_jit_tests(void) { Suite *s = suite_create("jit"); @@ -2007,6 +2037,7 @@ Suite *get_jit_tests(void) tcase_add_test(tc, test_cfg3); tcase_add_test(tc, test_dce2); tcase_add_test(tc, test_code1); + tcase_add_test(tc, test_lvn10); suite_add_tcase(s, tc); return s; -- 2.39.2