Skip to content

Commit

Permalink
tmp
Browse files Browse the repository at this point in the history
  • Loading branch information
ShawSumma committed Oct 20, 2023
1 parent 5fbd3d1 commit 0e5a0b6
Show file tree
Hide file tree
Showing 11 changed files with 172 additions and 119 deletions.
2 changes: 2 additions & 0 deletions tb/src/jit.c
Original file line number Diff line number Diff line change
@@ -1,8 +1,10 @@
#include "tb_internal.h"
#include "host.h"

#ifdef _WIN32
#define WIN32_LEAN_AND_MEAN
#include <windows.h>
#endif

enum {
ALLOC_GRANULARITY = 16,
Expand Down
61 changes: 40 additions & 21 deletions tb/src/opt/branches.h
Original file line number Diff line number Diff line change
@@ -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);
Expand Down Expand Up @@ -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);

Expand Down Expand Up @@ -270,21 +272,53 @@ 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) {
taken = i + 1;
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
Expand All @@ -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);
}
}
}
Expand Down
4 changes: 2 additions & 2 deletions tb/src/opt/cfg.h
Original file line number Diff line number Diff line change
Expand Up @@ -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) {
Expand Down Expand Up @@ -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;
}
Expand Down
41 changes: 0 additions & 41 deletions tb/src/opt/fold.h
Original file line number Diff line number Diff line change
@@ -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:
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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:
Expand Down
23 changes: 8 additions & 15 deletions tb/src/opt/gcm.h
Original file line number Diff line number Diff line change
Expand Up @@ -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]);
}
}

Expand All @@ -166,25 +159,25 @@ 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);

// 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];
}
}
Expand Down
1 change: 1 addition & 0 deletions tb/src/opt/gvn.h
Original file line number Diff line number Diff line change
Expand Up @@ -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:
Expand Down
78 changes: 75 additions & 3 deletions tb/src/opt/lattice.h
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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();
}
Expand All @@ -98,18 +103,49 @@ 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: {
// [amin, amax] ^ [bmin, bmax] => [min(amin, bmin), max(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 (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;
Expand All @@ -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();
}
}
10 changes: 6 additions & 4 deletions tb/src/opt/mem2reg.h
Original file line number Diff line number Diff line change
Expand Up @@ -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),
Expand Down Expand Up @@ -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);
}
Expand Down Expand Up @@ -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);
Expand All @@ -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]);
Expand Down
Loading

0 comments on commit 0e5a0b6

Please sign in to comment.