diff --git a/tb/src/jit.c b/tb/src/jit.c index 603c4f3e..1c235e29 100644 --- a/tb/src/jit.c +++ b/tb/src/jit.c @@ -1,8 +1,10 @@ #include "tb_internal.h" #include "host.h" +#ifdef _WIN32 #define WIN32_LEAN_AND_MEAN #include +#endif enum { ALLOC_GRANULARITY = 16, diff --git a/tb/src/opt/branches.h b/tb/src/opt/branches.h index 52094a6f..d9fa4d10 100644 --- a/tb/src/opt/branches.h +++ b/tb/src/opt/branches.h @@ -1,3 +1,4 @@ +enum { MAX_DOM_WALK = 10 }; static TB_Node* ideal_region(TB_Passes* restrict p, TB_Function* f, TB_Node* n) { TB_NodeRegion* r = TB_NODE_GET_EXTRA(n); @@ -82,7 +83,8 @@ static TB_Node* ideal_phi(TB_Passes* restrict opt, TB_Function* f, TB_Node* n) { // TB_Node* left = region->inputs[0]; TB_Node* right = region->inputs[1]; - if (left->inputs[0]->type == TB_BRANCH && left->inputs[0] == right->inputs[0]) { + if (left->type == TB_PROJ && right->type == TB_PROJ && + left->inputs[0]->type == TB_BRANCH && left->inputs[0] == right->inputs[0]) { TB_Node* branch = left->inputs[0]; TB_NodeBranch* header_br = TB_NODE_GET_EXTRA(branch); @@ -270,13 +272,11 @@ static TB_Node* ideal_branch(TB_Passes* restrict opt, TB_Function* f, TB_Node* n if (n->input_count == 2) { Lattice* key = lattice_universe_get(&opt->universe, n->inputs[1]); - // we can walk the dominator tree to see if the condition is already - // been checked. - + ptrdiff_t taken = -1; if (key->tag == LATTICE_INT && key->_int.min == key->_int.max) { int64_t key_const = key->_int.max; + taken = 0; - size_t taken = 0; FOREACH_N(i, 0, br->succ_count - 1) { int64_t case_key = br->keys[i]; if (key_const == case_key) { @@ -284,7 +284,41 @@ static TB_Node* ideal_branch(TB_Passes* restrict opt, TB_Function* f, TB_Node* n break; } } + } else if (br->succ_count == 2) { + // TODO(NeGate): extend this to JOIN redundant checks to ideally + // narrow on more complex checks. + int64_t* primary_keys = br->keys; + + // check for redundant conditions in the doms. + TB_Node* initial_bb = get_block_begin(n->inputs[0]); + for (User* u = n->inputs[1]->users; u; u = u->next) { + if (u->n->type != TB_BRANCH || u->slot != 1 || u->n == n) { + continue; + } + + TB_Node* end = u->n; + int64_t* keys = TB_NODE_GET_EXTRA_T(end, TB_NodeBranch)->keys; + if (TB_NODE_GET_EXTRA_T(end, TB_NodeBranch)->succ_count != 2 && keys[0] != primary_keys[0]) { + continue; + } + + for (User* succ_user = end->users; succ_user; succ_user = succ_user->next) { + assert(succ_user->n->type == TB_PROJ); + int index = TB_NODE_GET_EXTRA_T(succ_user->n, TB_NodeProj)->index; + TB_Node* succ = cfg_next_bb_after_cproj(succ_user->n); + + // we must be dominating for this to work + if (!lattice_dommy(&opt->universe, succ, initial_bb)) { + continue; + } + + taken = index; + goto match; + } + } + } + if (taken >= 0) match: { TB_Node* dead = make_dead_node(f, opt); // convert dead projections into DEAD and convert live projection into index 0 @@ -300,23 +334,8 @@ static TB_Node* ideal_branch(TB_Passes* restrict opt, TB_Function* f, TB_Node* n // if we folded away from a region, then we should subsume // the degen phis. assert(proj->users->next == NULL); - TB_Node* succ = proj->users->n; - if (succ->type == TB_REGION) { - int phi_i = proj->users->slot; - - User* u = succ->users; - while (u != NULL) { - User* next = u->next; - if (u->n->type == TB_PHI) { - tb_pass_mark_users(opt, u->n); - subsume_node(opt, f, u->n, u->n->inputs[phi_i + 1]); - } - u = next; - } - } - tb_pass_kill_node(opt, proj); - set_input(opt, succ, n->inputs[0], 0); + set_input(opt, proj->users->n, n->inputs[0], proj->users->slot); } } } diff --git a/tb/src/opt/cfg.h b/tb/src/opt/cfg.h index 2cd0201a..9400c1f0 100644 --- a/tb/src/opt/cfg.h +++ b/tb/src/opt/cfg.h @@ -10,7 +10,7 @@ TB_CFG tb_compute_rpo(TB_Function* f, TB_Passes* p) { return tb_compute_rpo2(f, &p->worklist, &p->stack); } -static TB_Node* next_control(Worklist* ws, TB_Node* n) { +static TB_Node* mark_next_control(Worklist* ws, TB_Node* n) { // unless it's a branch (aka a terminator), it'll have one successor TB_Node* next = NULL; for (User* u = n->users; u; u = u->next) { @@ -61,7 +61,7 @@ TB_CFG tb_compute_rpo2(TB_Function* f, Worklist* ws, DynArray(TB_Node*)* tmp_sta TB_Node* entry = n; TB_BasicBlock bb = { .id = cfg.block_count++ }; while (!cfg_is_terminator(n)) { - TB_Node* next = next_control(ws, n); + TB_Node* next = mark_next_control(ws, n); if (next == NULL) { break; } diff --git a/tb/src/opt/fold.h b/tb/src/opt/fold.h index 0e645720..8243dc4f 100644 --- a/tb/src/opt/fold.h +++ b/tb/src/opt/fold.h @@ -1,18 +1,4 @@ -#define MASK_UPTO(pos) (~UINT64_C(0) >> (64 - pos)) -#define BEXTR(src,pos) (((src) >> (pos)) & 1) -uint64_t tb__sxt(uint64_t src, uint64_t src_bits, uint64_t dst_bits) { - uint64_t sign_bit = BEXTR(src, src_bits-1); - uint64_t mask = MASK_UPTO(dst_bits) & ~MASK_UPTO(src_bits); - - uint64_t dst = src & ~mask; - return dst | (sign_bit ? mask : 0); -} - -uint64_t tb__mask(uint64_t bits) { - return ~UINT64_C(0) >> (64 - bits); -} - static bool is_associative(TB_NodeTypeEnum type) { switch (type) { case TB_ADD: case TB_MUL: @@ -138,11 +124,6 @@ static Lattice* dataflow_trunc(TB_Passes* restrict opt, LatticeUniverse* uni, TB return lattice_intern(uni, (Lattice){ LATTICE_INT, ._int = { min, max, zeros, ones } }); } -static int64_t wrapped_int_add(int64_t x, int64_t y) { return (uint64_t)x + (uint64_t)y; } -static int64_t wrapped_int_sub(int64_t x, int64_t y) { return (uint64_t)x - (uint64_t)y; } -static int64_t wrapped_int_mul(int64_t x, int64_t y) { return (uint64_t)x * (uint64_t)y; } -static bool wrapped_int_lt(int64_t x, int64_t y, int bits) { return (int64_t)tb__sxt(x, bits, 64) < (int64_t)tb__sxt(y, bits, 64); } - static bool sub_overflow(uint64_t x, uint64_t y, uint64_t xy, int bits) { uint64_t v = (x ^ y) & (xy ^ x); // check the sign bit @@ -455,28 +436,6 @@ static TB_Node* ideal_extension(TB_Passes* restrict opt, TB_Function* f, TB_Node return NULL; } -static TB_Node* identity_extension(TB_Passes* restrict opt, TB_Function* f, TB_Node* n) { - TB_Node* src = n->inputs[1]; - if (src->type == TB_INTEGER_CONST) { - uint64_t src_i = TB_NODE_GET_EXTRA_T(src, TB_NodeInt)->value; - - size_t src_bits = src->dt.data; - size_t dst_bits = n->dt.data; - - uint64_t mask = ~UINT64_C(0) >> (64 - src_bits); - uint64_t val; - if (n->type == TB_SIGN_EXT) { - val = tb__sxt(src_i, src_bits, dst_bits); - } else { - val = src_i & mask; - } - - return make_int_node(f, opt, n->dt, val); - } else { - return n; - } -} - static int node_pos(TB_Node* n) { switch (n->type) { case TB_PHI: diff --git a/tb/src/opt/gcm.h b/tb/src/opt/gcm.h index 45e43ab9..9c67c07a 100644 --- a/tb/src/opt/gcm.h +++ b/tb/src/opt/gcm.h @@ -143,14 +143,7 @@ void tb_pass_schedule(TB_Passes* p, TB_CFG cfg) { worklist_clear_visited(ws); FOREACH_N(i, 0, cfg.block_count) { TB_BasicBlock* best = &nl_map_get_checked(cfg.node_to_block, ws->items[i]); - if (i == 0) { - worklist_test_n_set(ws, p->f->start_node); - nl_map_put(p->scheduled, p->f->start_node, best); - } - best->items = nl_hashset_alloc(32); - nl_map_put(p->scheduled, ws->items[i], best); - worklist_test_n_set(ws, ws->items[i]); } } @@ -166,12 +159,8 @@ void tb_pass_schedule(TB_Passes* p, TB_CFG cfg) { nl_map_put(p->scheduled, start, bb); } - // schedule top of BB - nl_hashset_put2(&bb->items, bb_node, node_hash, node_compare); - nl_map_put(p->scheduled, bb_node, bb); - TB_Node* n = bb->end; - while (n != bb_node) { + for (;;) { DO_IF(TB_OPTDEBUG_GCM)(printf("%s: v%u pinned to .bb%d\n", p->f->super.name, n->gvn, bb->id)); nl_hashset_put2(&bb->items, n, node_hash, node_compare); nl_map_put(p->scheduled, n, bb); @@ -179,12 +168,16 @@ void tb_pass_schedule(TB_Passes* p, TB_CFG cfg) { // mark projections into the same block for (User* use = n->users; use; use = use->next) { TB_Node* proj = use->n; - if (proj->type == TB_PROJ) { - nl_hashset_put2(&bb->items, proj, node_hash, node_compare); - nl_map_put(p->scheduled, proj, bb); + if (use->slot == 0 && (proj->type == TB_PROJ || proj->type == TB_PHI)) { + if (nl_map_get(p->scheduled, proj) < 0) { + DO_IF(TB_OPTDEBUG_GCM)(printf("%s: proj v%u pinned to .bb%d\n", p->f->super.name, proj->gvn, bb->id)); + nl_hashset_put2(&bb->items, proj, node_hash, node_compare); + nl_map_put(p->scheduled, proj, bb); + } } } + if (n == bb_node) break; n = n->inputs[0]; } } diff --git a/tb/src/opt/gvn.h b/tb/src/opt/gvn.h index f9519ea9..622ee690 100644 --- a/tb/src/opt/gvn.h +++ b/tb/src/opt/gvn.h @@ -72,6 +72,7 @@ static size_t extra_bytes(TB_Node* n) { case TB_SELECT: case TB_MERGEMEM: case TB_DEAD: + case TB_NULL: return 0; case TB_START: diff --git a/tb/src/opt/lattice.h b/tb/src/opt/lattice.h index 99bc6e76..bc4ea6aa 100644 --- a/tb/src/opt/lattice.h +++ b/tb/src/opt/lattice.h @@ -12,6 +12,7 @@ static bool lattice_cmp(void* a, void* b) { } static bool lattice_is_const_int(Lattice* l) { return l->_int.min == l->_int.max; } +static bool lattice_is_const(Lattice* l) { return l->tag == LATTICE_INT && l->_int.min == l->_int.max; } static void lattice_universe_map(LatticeUniverse* uni, TB_Node* n, Lattice* l) { // reserve cap, slow path :p @@ -89,6 +90,10 @@ static Lattice* lattice_top(LatticeUniverse* uni, TB_DataType dt) { return lattice_intern(uni, (Lattice){ LATTICE_POINTER, ._ptr = { LATTICE_UNKNOWN } }); } + case TB_CONTROL: { + return lattice_intern(uni, (Lattice){ LATTICE_CONTROL, ._ctrl = { NULL } }); + } + default: tb_todo(); } @@ -98,8 +103,36 @@ static Lattice* lattice_top(LatticeUniverse* uni, TB_DataType dt) { // known X ^ unknown => unknown (commutative btw) #define TRIFECTA_MEET(a, b) ((a).trifecta == (b).trifecta ? (a).trifecta : LATTICE_UNKNOWN) +#define MASK_UPTO(pos) (~UINT64_C(0) >> (64 - pos)) +#define BEXTR(src,pos) (((src) >> (pos)) & 1) +uint64_t tb__sxt(uint64_t src, uint64_t src_bits, uint64_t dst_bits) { + uint64_t sign_bit = BEXTR(src, src_bits-1); + uint64_t mask = MASK_UPTO(dst_bits) & ~MASK_UPTO(src_bits); + + uint64_t dst = src & ~mask; + return dst | (sign_bit ? mask : 0); +} + +static uint64_t tb__mask(uint64_t bits) { + return ~UINT64_C(0) >> (64 - bits); +} + +static LatticeTrifecta lattice_trifecta_join(LatticeTrifecta a, LatticeTrifecta b) { + if ((a == LATTICE_KNOWN_NOT_NULL && b == LATTICE_KNOWN_NULL) || + (a == LATTICE_KNOWN_NULL && b == LATTICE_KNOWN_NOT_NULL)) { + tb_panic("trying to join to disjoint sets :("); + } + + return a == LATTICE_UNKNOWN ? b : a; +} + +static int64_t wrapped_int_add(int64_t x, int64_t y) { return (uint64_t)x + (uint64_t)y; } +static int64_t wrapped_int_sub(int64_t x, int64_t y) { return (uint64_t)x - (uint64_t)y; } +static int64_t wrapped_int_mul(int64_t x, int64_t y) { return (uint64_t)x * (uint64_t)y; } +static bool wrapped_int_lt(int64_t x, int64_t y, int bits) { return (int64_t)tb__sxt(x, bits, 64) < (int64_t)tb__sxt(y, bits, 64); } + // generates the greatest lower bound between a and b -static Lattice* lattice_meet(LatticeUniverse* uni, Lattice* a, Lattice* b) { +static Lattice* lattice_meet(LatticeUniverse* uni, Lattice* a, Lattice* b, TB_DataType dt) { assert(a->tag == b->tag); switch (a->tag) { case LATTICE_INT: { @@ -107,9 +140,12 @@ static Lattice* lattice_meet(LatticeUniverse* uni, Lattice* a, Lattice* b) { LatticeInt aa = a->_int; LatticeInt bb = b->_int; + int bits = dt.data; + uint64_t mask = tb__mask(dt.data); + LatticeInt i = { aa.min, aa.max }; - if (i.min > bb.min) i.min = bb.min; - if (i.max < bb.max) i.max = bb.max; + if (wrapped_int_lt(bb.min, i.min, bits)) i.min = bb.min; + if (wrapped_int_lt(i.max, bb.max, bits)) i.max = bb.max; i.known_zeros = aa.known_zeros & bb.known_zeros; i.known_ones = aa.known_ones & bb.known_ones; @@ -130,3 +166,39 @@ static Lattice* lattice_meet(LatticeUniverse* uni, Lattice* a, Lattice* b) { default: tb_todo(); } } + +// generates the lowest upper bound between a and b +static Lattice* lattice_join(LatticeUniverse* uni, Lattice* a, Lattice* b, TB_DataType dt) { + assert(a->tag == b->tag); + switch (a->tag) { + case LATTICE_INT: { + // [amin, amax] ^ [bmin, bmax] => [max(amin, bmin), min(amax, bmax)] + LatticeInt aa = a->_int; + LatticeInt bb = b->_int; + + int bits = dt.data; + uint64_t mask = tb__mask(dt.data); + + LatticeInt i = { aa.min, aa.max }; + if (wrapped_int_lt(i.min, bb.min, bits)) i.min = bb.min; + if (wrapped_int_lt(bb.max, i.max, bits)) i.max = bb.max; + + i.known_zeros = aa.known_zeros | bb.known_zeros; + i.known_ones = aa.known_ones | bb.known_ones; + return lattice_intern(uni, (Lattice){ LATTICE_INT, ._int = i }); + } + + case LATTICE_FLOAT32: + case LATTICE_FLOAT64: { + LatticeFloat f = { .trifecta = lattice_trifecta_join(a->_float.trifecta, b->_float.trifecta) }; + return lattice_intern(uni, (Lattice){ a->tag, ._float = f }); + } + + case LATTICE_POINTER: { + LatticePointer p = { .trifecta = lattice_trifecta_join(a->_ptr.trifecta, b->_ptr.trifecta) }; + return lattice_intern(uni, (Lattice){ LATTICE_POINTER, ._ptr = p }); + } + + default: tb_todo(); + } +} diff --git a/tb/src/opt/mem2reg.h b/tb/src/opt/mem2reg.h index 068038e0..eaeab293 100644 --- a/tb/src/opt/mem2reg.h +++ b/tb/src/opt/mem2reg.h @@ -164,9 +164,6 @@ static void ssa_rename(Mem2Reg_Ctx* c, TB_Function* f, TB_Node* bb, DynArray(TB_ TB_BasicBlock* bb_info = &nl_map_get_checked(c->cfg.node_to_block, bb); TB_Node* end = bb_info->end; - tb_pass_mark(p, bb); - tb_pass_mark_users(p, bb); - DO_IF(TB_OPTDEBUG_MEM2REG)( printf(" FORST %u: ", bb->gvn), print_node_sexpr(bb, 0), @@ -235,7 +232,7 @@ static void ssa_rename(Mem2Reg_Ctx* c, TB_Function* f, TB_Node* bb, DynArray(TB_ if (kill) { TB_Node* into = n->inputs[1]; tb_pass_mark(c->p, into); - tb_pass_mark(c->p, n); + tb_pass_mark_users(c->p, into); set_input(p, n, NULL, 1); subsume_node(p, c->f, n, into); } @@ -363,6 +360,7 @@ bool tb_pass_mem2reg(TB_Passes* p) { c.cfg = tb_compute_rpo(f, p); c.blocks = &p->worklist.items[0]; + worklist_clear_visited(&p->worklist); tb_compute_dominators(f, p, c.cfg); TB_DominanceFrontiers* df = tb_get_dominance_frontiers(f, p, c.cfg, c.blocks); @@ -375,6 +373,10 @@ bool tb_pass_mem2reg(TB_Passes* p) { TB_Node* bb = c.blocks[i]; TB_BasicBlock* bb_info = &nl_map_get_checked(c.cfg.node_to_block, bb); + // mark into worklist + worklist_test_n_set(&p->worklist, bb); + tb_pass_mark_users(p, bb); + if (i == 0) { // start block can use the input memory as the earliest point insert_phis(&c, bb, f->params[1]); diff --git a/tb/src/opt/optimizer.c b/tb/src/opt/optimizer.c index b67ff5ab..7e667949 100644 --- a/tb/src/opt/optimizer.c +++ b/tb/src/opt/optimizer.c @@ -252,7 +252,7 @@ static bool lattice_dommy(LatticeUniverse* uni, TB_Node* expected_dom, TB_Node* assert(l->tag == LATTICE_CONTROL); TB_Node* new_bb = l->_ctrl.idom; - if (bb == new_bb) { + if (new_bb == NULL) { return false; } bb = new_bb; @@ -627,10 +627,6 @@ static TB_Node* identity(TB_Passes* restrict p, TB_Function* f, TB_Node* n, TB_P case TB_CMP_ULE: return identity_int_binop(p, f, n); - case TB_SIGN_EXT: - case TB_ZERO_EXT: - return identity_extension(p, f, n); - case TB_MEMBER_ACCESS: if (TB_NODE_GET_EXTRA_T(n, TB_NodeMember)->offset == 0) { return n->inputs[1]; @@ -650,12 +646,6 @@ static TB_Node* identity(TB_Passes* restrict p, TB_Function* f, TB_Node* n, TB_P } assert(same); - if (same->dt.type == TB_MEMORY) { - TB_NodeRegion* r = TB_NODE_GET_EXTRA(n->inputs[0]); - if (r->mem_in == n) r->mem_in = NULL; - if (r->mem_out == n) r->mem_out = NULL; - } - tb_pass_mark_users(p, n->inputs[0]); return same; } else { @@ -712,8 +702,9 @@ static Lattice* dataflow(TB_Passes* restrict p, LatticeUniverse* uni, TB_Node* n // meet all inputs case TB_PHI: { Lattice* l = lattice_universe_get(uni, n->inputs[1]); + TB_DataType dt = n->dt; FOREACH_N(i, 2, n->input_count) { - l = lattice_meet(uni, l, lattice_universe_get(uni, n->inputs[i])); + l = lattice_meet(uni, l, lattice_universe_get(uni, n->inputs[i]), dt); } return l; } @@ -771,21 +762,20 @@ static void validate_node_users(TB_Node* n) { static void print_lattice(Lattice* l, TB_DataType dt) { switch (l->tag) { - case LATTICE_INT: - assert(dt.type == TB_INT); - printf("[%"PRId64, tb__sxt(l->_int.min, dt.data, 64)); - // printf("[%#"PRIx64, l->_int.min); - if (l->_int.min != l->_int.max) { - // printf(" - %#"PRIx64, l->_int.max); - printf(" - %"PRId64, tb__sxt(l->_int.max, dt.data, 64)); - } + case LATTICE_INT: { + assert(dt.type == TB_INT); + printf("[%"PRId64, tb__sxt(l->_int.min, dt.data, 64)); + if (l->_int.min != l->_int.max) { + printf(",%"PRId64, tb__sxt(l->_int.max, dt.data, 64)); + } - uint64_t known = l->_int.known_zeros | l->_int.known_ones; - if (known && known != UINT64_MAX) { - printf("; zeros=%#"PRIx64", ones=%#"PRIx64, l->_int.known_zeros, l->_int.known_ones); + uint64_t known = l->_int.known_zeros | l->_int.known_ones; + if (known && known != UINT64_MAX) { + printf("; zeros=%#"PRIx64", ones=%#"PRIx64, l->_int.known_zeros, l->_int.known_ones); + } + printf("]"); + break; } - printf("]"); - break; case LATTICE_POINTER: { static const char* tri[] = { "unknown", "null", "~null" }; @@ -802,6 +792,7 @@ static bool peephole(TB_Passes* restrict p, TB_Function* f, TB_Node* n, TB_Peeph // must've dead sometime between getting scheduled and getting // here. if (n->type != TB_END && n->users == NULL) { + tb_pass_kill_node(p, n); return false; } diff --git a/tb/src/passes.h b/tb/src/passes.h index c7787181..3f5468d1 100644 --- a/tb/src/passes.h +++ b/tb/src/passes.h @@ -2,7 +2,7 @@ #include "tb_internal.h" #define TB_OPTDEBUG_STATS 0 -#define TB_OPTDEBUG_PEEP 0 +#define TB_OPTDEBUG_PEEP 1 #define TB_OPTDEBUG_LOOP 0 #define TB_OPTDEBUG_SROA 0 #define TB_OPTDEBUG_GCM 0 @@ -261,7 +261,7 @@ static TB_Node* get_pred(TB_Node* n, int i) { TB_Node* parent = n->inputs[0]; // start or cprojs with multiple users (it's a BB) will just exit - if (parent->type == TB_START || (parent->type == TB_REGION && n->users->next == NULL)) { + if (parent->type == TB_START || n->users->next != NULL) { return n; } n = parent; @@ -270,9 +270,28 @@ static TB_Node* get_pred(TB_Node* n, int i) { while (!cfg_is_bb_entry(n)) { n = n->inputs[0]; } + return n; } +static TB_Node* next_control(TB_Node* n) { + // unless it's a branch (aka a terminator), it'll have one successor + TB_Node* next = NULL; + for (User* u = n->users; u; u = u->next) { + TB_Node* succ = u->n; + + // we can't treat regions in the chain + if (succ->type == TB_REGION) break; + + // we've found the next step in control flow + if (cfg_is_control(succ)) { + return succ; + } + } + + return NULL; +} + static TB_Node* get_block_begin(TB_Node* n) { while (!cfg_is_bb_entry(n)) { n = n->inputs[0]; diff --git a/vm/jit/tb.c b/vm/jit/tb.c index 604f015b..a19e06c8 100644 --- a/vm/jit/tb.c +++ b/vm/jit/tb.c @@ -305,11 +305,6 @@ TB_Node *vm_tb_func_body(vm_tb_state_t *state, TB_Function *fun, TB_Node **args, } TB_Node *vm_tb_func_body_call(vm_tb_state_t *state, TB_Function *fun, TB_Node **args, vm_rblock_t *rblock) { - TB_Node *comp_params[2]; - - comp_params[0] = tb_inst_uint(fun, TB_TYPE_PTR, (uint64_t)state); - comp_params[1] = tb_inst_uint(fun, TB_TYPE_PTR, (uint64_t)rblock); - // vm_tb_rfunc_comp(state, rblock); // printf("%p\n", rblock->cache); @@ -585,7 +580,6 @@ TB_Node *vm_tb_func_body_once(vm_tb_state_t *state, TB_Function *fun, TB_Node ** TB_SwitchEntry keys[VM_TAG_MAX - 1]; for (size_t i = 1; i < VM_TAG_MAX; i++) { - keys[i - 1].key = i; // vm_block_t *next_block = vm_tb_rblock_version(branch.rtargets[i]); TB_Node **next_args = vm_malloc(sizeof(TB_Node *) * branch.targets[0]->nargs); for (size_t j = 0; j < branch.targets[0]->nargs; j++) { @@ -601,6 +595,7 @@ TB_Node *vm_tb_func_body_once(vm_tb_state_t *state, TB_Function *fun, TB_Node ** next_args[j] = vm_tb_func_read_arg(fun, regs, next_arg); } } + keys[i - 1].key = i; keys[i - 1].value = vm_tb_func_body(state, fun, next_args, branch.rtargets[i]); } tb_inst_branch(