Skip to content

Commit

Permalink
brought back some branching peeps
Browse files Browse the repository at this point in the history
  • Loading branch information
RealNeGate committed Jan 20, 2024
1 parent d638473 commit ad77755
Show file tree
Hide file tree
Showing 6 changed files with 95 additions and 100 deletions.
31 changes: 23 additions & 8 deletions main/objdump.h
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,7 @@ int run_objdump(int argc, const char** argv) {
printf("\n");
}

#if 0
#if 1
printf("\n note:\n");
printf(" r - read w - write x - execute\n");
printf(" c - code u - uninit i - init\n");
Expand Down Expand Up @@ -98,6 +98,9 @@ int run_objdump(int argc, const char** argv) {
// print disassembly
for (size_t i = 0; i < parser.section_count; i++) {
TB_ObjectSection* s = &sections[i];
if ((s->flags & TB_COFF_SECTION_CODE) == 0) {
continue;
}

printf("DUMP: %.*s\n", (int) s->name.length, s->name.data);

Expand All @@ -110,17 +113,29 @@ int run_objdump(int argc, const char** argv) {
const uint8_t* data = s->raw_data.data;
if (s->flags & TB_COFF_SECTION_CODE) {
// dump assembly
size_t pos = 0, count = 0;
uint64_t pos = 0;
while (pos < s->raw_data.length) {
printf(" %08zx: ", pos);
ptrdiff_t delta = tb_print_disassembly_inst(TB_ARCH_X86_64, s->raw_data.length - pos, data + pos);
if (delta < 0) {
printf(" %8"PRIx64": ", pos);

TB_X86_Inst inst;
if (tb_x86_disasm(&inst, s->raw_data.length - pos, data + pos)) {
// print first 10 bytes
size_t i = 0;
for (; i < inst.length && i < 10; i++) {
printf("%02x ", data[pos + i]);
}

for (; i < 10; i++) {
printf(" ");
}

// print op
tb_x86_print_inst(stdout, &inst);
pos += inst.length;
} else {
printf("ERROR\n");
pos += 1;
} else {
pos += delta;
}
count += 1;
}
printf("\n");
} else {
Expand Down
15 changes: 12 additions & 3 deletions tb/include/tb.h
Original file line number Diff line number Diff line change
Expand Up @@ -1303,12 +1303,16 @@ TB_API void tb_inst_ret(TB_Function* f, size_t count, TB_Node** values);
// Cooler IR building
////////////////////////////////
typedef struct TB_GraphBuilder TB_GraphBuilder;
enum { TB_GRAPH_BUILDER_PARAMS = 1 };
enum { TB_GRAPH_BUILDER_PARAMS = 0 };

// arena isn't for the function, it's for the builder
TB_API TB_GraphBuilder* tb_builder_enter(TB_Function* f, TB_Arena* arena);
TB_API void tb_builder_exit(TB_GraphBuilder* g);

// sometimes you wanna make a scope and have some shit in there... use this
TB_API int tb_builder_save(TB_GraphBuilder* g);
TB_API void tb_builder_restore(TB_GraphBuilder* g, int v);

// ( -- a )
TB_API void tb_builder_uint(TB_GraphBuilder* g, TB_DataType dt, uint64_t x);
TB_API void tb_builder_sint(TB_GraphBuilder* g, TB_DataType dt, int64_t x);
Expand Down Expand Up @@ -1337,17 +1341,22 @@ TB_API void tb_builder_load(TB_GraphBuilder* g, int mem_var, bool ctrl_dep, TB_D
// ( addr val -- )
TB_API void tb_builder_store(TB_GraphBuilder* g, int mem_var, TB_CharUnits align);

// locals (variables but as stack vars)
TB_API TB_Node* tb_builder_local(TB_GraphBuilder* g, TB_CharUnits size, TB_CharUnits align);
TB_API void tb_builder_push(TB_GraphBuilder* g, TB_Node* n);
TB_API TB_Node* tb_builder_pop(TB_GraphBuilder* g);

// variables (these are just named stack slots)
// ( a -- )
//
// we take the top item in the stack and treat it as a
// variable we'll might later fiddle with, the control
// flow primitives will diff changes to insert phis.
TB_API int tb_builder_var(TB_GraphBuilder* g);
TB_API int tb_builder_decl(TB_GraphBuilder* g);
// ( -- a )
TB_API void tb_builder_get_var(TB_GraphBuilder* g, int id);
// ( a -- )
TB_API void tb_builder_assign(TB_GraphBuilder* g, int id);
TB_API void tb_builder_set_var(TB_GraphBuilder* g, int id);

// control flow primitives
// ( a -- )
Expand Down
1 change: 1 addition & 0 deletions tb/include/tb_x64.h
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,7 @@ typedef struct {
int64_t imm;
} TB_X86_Inst;

void tb_x86_print_inst(FILE* fp, TB_X86_Inst* inst);
bool tb_x86_disasm(TB_X86_Inst* restrict inst, size_t length, const uint8_t* data);
const char* tb_x86_reg_name(int8_t reg, TB_X86_DataType dt);
const char* tb_x86_type_name(TB_X86_DataType dt);
Expand Down
59 changes: 1 addition & 58 deletions tb/src/disasm.c
Original file line number Diff line number Diff line change
@@ -1,34 +1,5 @@
#include <tb_x64.h>

static void print_memory_operand(TB_X86_Inst* restrict inst) {
uint8_t base = inst->regs & 0xFF;
uint8_t index = (inst->regs >> 8) & 0xFF;

if (inst->flags & TB_X86_INSTR_INDIRECT) {
if ((inst->regs & 0xFFFF) == 0xFFFF) {
printf("[rip");
} else {
printf("%s [", tb_x86_type_name(inst->dt));
if (base != 0xFF) {
printf("%s", tb_x86_reg_name(base, TB_X86_TYPE_QWORD));
}

if (index != 0xFF) {
printf(" + %s*%d", tb_x86_reg_name(index, TB_X86_TYPE_QWORD), 1 << inst->scale);
}
}

if (inst->disp > 0) {
printf(" + %x", inst->disp);
} else if (inst->disp < 0) {
printf(" - %x", -inst->disp);
}
printf("]");
} else if (base != 0xFF) {
printf("%s", tb_x86_reg_name(base, inst->dt));
}
}

ptrdiff_t tb_print_disassembly_inst(TB_Arch arch, size_t length, const void* ptr) {
switch (arch) {
#ifdef TB_HAS_X64
Expand All @@ -38,35 +9,7 @@ ptrdiff_t tb_print_disassembly_inst(TB_Arch arch, size_t length, const void* ptr
return -1;
}

const char* mnemonic = tb_x86_mnemonic(&inst);
printf("%s", mnemonic);
if (inst.dt >= TB_X86_TYPE_SSE_SS && inst.dt <= TB_X86_TYPE_SSE_PD) {
static const char* strs[] = { "ss", "sd", "ps", "pd" };
printf("%s", strs[inst.dt - TB_X86_TYPE_SSE_SS]);
}
printf(" ");

uint8_t rx = (inst.regs >> 16) & 0xFF;
if (inst.flags & TB_X86_INSTR_DIRECTION) {
print_memory_operand(&inst);
if (rx != 255) {
printf(", ");
printf("%s", tb_x86_reg_name(rx, inst.dt));
}
} else {
if (rx != 255) {
printf("%s", tb_x86_reg_name(rx, inst.dt));
printf(", ");
}
print_memory_operand(&inst);
}

if (inst.flags & TB_X86_INSTR_IMMEDIATE) {
printf(", ");
printf("%#"PRIx64, inst.imm);
}

printf("\n");
tb_x86_print_inst(stdout, &inst);
return inst.length;
}
#endif
Expand Down
17 changes: 13 additions & 4 deletions tb/src/new_builder.c
Original file line number Diff line number Diff line change
Expand Up @@ -62,11 +62,10 @@ TB_GraphBuilder* tb_builder_enter(TB_Function* f, TB_Arena* arena) {
g->ctrl = tb_platform_heap_alloc(g->ctrl_cap * sizeof(TB_GraphCtrl));
g->vals = tb_platform_heap_alloc(g->val_cap * sizeof(TB_Node*));

assert(g->val_cap >= 1 + f->param_count);
g->val_cnt = 1 + f->param_count;
g->vals[0] = f->params[2];
assert(g->val_cap >= f->param_count);
g->val_cnt = f->param_count;
FOREACH_N(i, 0, f->param_count) {
g->vals[1 + i] = f->params[3 + i];
g->vals[i] = f->params[3 + i];
}

return g;
Expand All @@ -75,6 +74,15 @@ TB_GraphBuilder* tb_builder_enter(TB_Function* f, TB_Arena* arena) {
void tb_builder_exit(TB_GraphBuilder* g) {
}

int tb_builder_save(TB_GraphBuilder* g) {
return g->val_cnt;
}

void tb_builder_restore(TB_GraphBuilder* g, int v) {
assert(g->val_cnt >= v);
g->val_cnt = v;
}

void tb_builder_uint(TB_GraphBuilder* g, TB_DataType dt, uint64_t x) {
assert(TB_IS_POINTER_TYPE(dt) || TB_IS_INTEGER_TYPE(dt));
if (dt.type == TB_INT && dt.data < 64) {
Expand Down Expand Up @@ -196,6 +204,7 @@ void tb_builder_store(TB_GraphBuilder* g, int mem_var, TB_CharUnits alignment) {

TB_Node* val = pop(g);
TB_Node* addr = pop(g);
assert(g->vals[mem_var]->dt.type == TB_MEMORY);

TB_Node* n = tb_alloc_node(f, TB_STORE, TB_TYPE_MEMORY, 4, sizeof(TB_NodeMemAccess));
set_input(f, n, f->trace.bot_ctrl, 0);
Expand Down
72 changes: 45 additions & 27 deletions tb/src/opt/branches.h
Original file line number Diff line number Diff line change
Expand Up @@ -268,60 +268,78 @@ static TB_Node* ideal_branch(TB_Passes* restrict opt, TB_Function* f, TB_Node* n
// if (a && b) A else B => if (a ? b : 0) A else B
//
// TODO(NeGate): implement form which works on an arbitrary falsey
/*if (n->inputs[0]->type == TB_REGION && n->inputs[0]->input_count == 2 && is_empty_bb(opt, n)) {
TB_Node* bb = n->inputs[0];
if (n->inputs[0]->type == TB_PROJ && n->inputs[0]->inputs[0]->type == TB_BRANCH && is_empty_bb(opt, n)) {
uint64_t falsey = br->keys[0];
TB_Node* pred_branch = bb->inputs[0]->inputs[0];
TB_Node* pred_branch = n->inputs[0]->inputs[0];

int index = TB_NODE_GET_EXTRA_T(n->inputs[0], TB_NodeProj)->index;

// needs one pred
uint64_t pred_falsey;
if (bb->input_count == 1 && is_if_branch(pred_branch, &pred_falsey)) {
if (is_if_branch(pred_branch, &pred_falsey) && pred_falsey == 0) {
TB_NodeBranch* pred_br_info = TB_NODE_GET_EXTRA(pred_branch);

bool bb_on_false = pred_br_info->succ[0] == bb;
TB_Node* shared_edge = pred_br_info->succ[!bb_on_false];
// check our parent's aux path
User* other_proj = proj_with_index(pred_branch, 1 - index);
TB_Node* shared_edge = cfg_next_bb_after_cproj(other_proj->n);

// check our aux path
User* other_proj2 = proj_with_index(n, 1 - index);
TB_Node* shared_edge2 = cfg_next_bb_after_cproj(other_proj2->n);

// if they're the same then we've got a shortcircuit eval setup
if (shared_edge == shared_edge2) {
assert(shared_edge->type == TB_REGION);
FOR_USERS(phis, shared_edge) if (phis->n->type == TB_PHI) {
tb_todo();
}

int shared_i = -1;
if (shared_edge == br->succ[0]) shared_i = 0;
if (shared_edge == br->succ[1]) shared_i = 1;
// remove pred from shared edge
int shared_i = other_proj->n->users->slot;
remove_input(f, shared_edge, shared_i);
FOR_USERS(use, shared_edge) {
if (use->n->type == TB_PHI && use->slot == 0) {
remove_input(f, use->n, shared_i + 1);
tb_pass_mark(opt, use->n);
}
}

if (shared_i >= 0) {
TB_Node* pred_cmp = pred_branch->inputs[1];
TB_Node* before = pred_branch->inputs[0];
TB_Node* cmp = pred_branch->inputs[1];

// convert first branch into an unconditional into bb
transmute_goto(opt, f, pred_branch, bb);
// remove first branch
tb_pass_kill_node(f, pred_branch);
set_input(f, n, before, 0);

// we wanna normalize into a comparison (not a boolean -> boolean)
if (!(pred_cmp->dt.type == TB_INT && pred_cmp->dt.data == 1)) {
assert(pred_cmp->dt.type != TB_FLOAT && "TODO");
TB_Node* imm = make_int_node(f, opt, pred_cmp->dt, pred_falsey);
tb_pass_mark(opt, imm);
if (!(cmp->dt.type == TB_INT && cmp->dt.data == 1)) {
assert(cmp->dt.type != TB_FLOAT && "TODO");
TB_Node* imm = make_int_node(f, opt, cmp->dt, pred_falsey);

TB_Node* new_node = tb_alloc_node(f, TB_CMP_NE, TB_TYPE_BOOL, 3, sizeof(TB_NodeCompare));
set_input(f, new_node, pred_cmp, 1);
set_input(f, new_node, cmp, 1);
set_input(f, new_node, imm, 2);
TB_NODE_SET_EXTRA(new_node, TB_NodeCompare, .cmp_dt = pred_cmp->dt);
TB_NODE_SET_EXTRA(new_node, TB_NodeCompare, .cmp_dt = cmp->dt);

tb_pass_mark(opt, new_node);
pred_cmp = new_node;
cmp = new_node;
}

TB_Node* false_node = make_int_node(f, opt, n->inputs[1]->dt, falsey);
tb_pass_mark(opt, false_node);
// construct branchless merge
TB_Node* false_node = make_int_node(f, opt, n->inputs[1]->dt, 0);

// a ? b : 0
TB_Node* selector = tb_alloc_node(f, TB_SELECT, n->inputs[1]->dt, 4, 0);
set_input(f, selector, pred_cmp, 1);
set_input(f, selector, n->inputs[1], 2 + bb_on_false);
set_input(f, selector, false_node, 2 + !bb_on_false);
set_input(f, selector, cmp, 1);
set_input(f, selector, n->inputs[1], 2);
set_input(f, selector, false_node, 3);

set_input(f, n, selector, 1);
tb_pass_mark(opt, selector);
return n;
}
}
}*/
}

// br ((y <= x)) => br (x < y) flipped conditions
if (cmp_type == TB_CMP_SLE || cmp_type == TB_CMP_ULE) {
Expand Down

0 comments on commit ad77755

Please sign in to comment.