mirror of
https://github.com/odin-lang/Odin.git
synced 2026-04-18 12:30:28 +00:00
v0.0.5
Fix enumerations to so they work as integers in indices; Add llir_opt.c and llir_print.c
This commit is contained in:
@@ -4,7 +4,7 @@
|
||||
set exe_name=odin.exe
|
||||
|
||||
:: Debug = 0, Release = 1
|
||||
set release_mode=0
|
||||
set release_mode=1
|
||||
|
||||
set compiler_flags= -nologo -Oi -TC -fp:fast -fp:except- -Gm- -MP -FC -GS- -EHsc- -GR-
|
||||
|
||||
|
||||
@@ -1,33 +1,60 @@
|
||||
#import "atomic.odin";
|
||||
#import "fmt.odin";
|
||||
#import "hash.odin";
|
||||
#import "math.odin";
|
||||
#import "mem.odin";
|
||||
#import "opengl.odin";
|
||||
#import "os.odin";
|
||||
#import "sync.odin";
|
||||
#import "utf8.odin";
|
||||
#import win32 "sys/windows.odin";
|
||||
|
||||
Thing :: enum f64 {
|
||||
_, // Ignore first value
|
||||
A = 1<<(10*iota),
|
||||
B,
|
||||
C,
|
||||
D,
|
||||
}
|
||||
|
||||
|
||||
main :: proc() {
|
||||
msg := "Hellope";
|
||||
list := []int{1, 4, 7, 3, 7, 2, 1};
|
||||
{
|
||||
Byte_Size :: enum f64 {
|
||||
_, // Ignore first value
|
||||
KB = 1<<(10*iota),
|
||||
MB,
|
||||
GB,
|
||||
TB,
|
||||
PB,
|
||||
}
|
||||
|
||||
for value : msg {
|
||||
fmt.println(value);
|
||||
using Byte_Size;
|
||||
fmt.println(KB, MB, GB, TB, PB);
|
||||
}
|
||||
for value : list {
|
||||
fmt.println(value);
|
||||
{
|
||||
x := if 1 < 2 {
|
||||
y := 123;
|
||||
give y-2;
|
||||
} else {
|
||||
give 0;
|
||||
};
|
||||
|
||||
x += {
|
||||
x := 2;
|
||||
give x;
|
||||
};
|
||||
|
||||
fmt.println("x =", x);
|
||||
}
|
||||
for val, idx : 12 ..< 17 {
|
||||
fmt.println(val, idx);
|
||||
{
|
||||
list := []int{1, 4, 7, 3, 7, 2, 1};
|
||||
for value : list {
|
||||
fmt.println(value);
|
||||
}
|
||||
for val, idx : 12 ..< 17 {
|
||||
fmt.println(val, idx);
|
||||
}
|
||||
msg := "Hellope";
|
||||
for value : msg {
|
||||
fmt.println(value);
|
||||
}
|
||||
}
|
||||
{
|
||||
i := 0;
|
||||
while i < 2 {
|
||||
i += 1;
|
||||
}
|
||||
|
||||
// Idiom to emulate C-style for loops
|
||||
while x := 0; x < 2 {
|
||||
defer x += 1;
|
||||
// Body of code
|
||||
// ++ and -- have been removed
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1019,7 +1019,8 @@ i64 check_array_count(Checker *c, AstNode *e) {
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
if (is_type_untyped(o.type) || is_type_integer(o.type)) {
|
||||
Type *type = base_type(base_enum_type(o.type));
|
||||
if (is_type_untyped(type) || is_type_integer(type)) {
|
||||
if (o.value.kind == ExactValue_Integer) {
|
||||
i64 count = o.value.value_integer;
|
||||
if (count >= 0) {
|
||||
@@ -1655,7 +1656,7 @@ void check_shift(Checker *c, Operand *x, Operand *y, AstNode *node) {
|
||||
}
|
||||
|
||||
bool x_is_untyped = is_type_untyped(x->type);
|
||||
if (!(is_type_integer(x->type) || (x_is_untyped && x_val.kind == ExactValue_Integer))) {
|
||||
if (!(is_type_integer(base_enum_type(x->type)) || (x_is_untyped && x_val.kind == ExactValue_Integer))) {
|
||||
gbString err_str = expr_to_string(x->expr);
|
||||
error_node(node, "Shifted operand `%s` must be an integer", err_str);
|
||||
gb_string_free(err_str);
|
||||
@@ -1663,7 +1664,7 @@ void check_shift(Checker *c, Operand *x, Operand *y, AstNode *node) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (is_type_unsigned(y->type)) {
|
||||
if (is_type_unsigned(base_enum_type(y->type))) {
|
||||
|
||||
} else if (is_type_untyped(y->type)) {
|
||||
convert_to_typed(c, y, t_untyped_integer, 0);
|
||||
@@ -1700,7 +1701,7 @@ void check_shift(Checker *c, Operand *x, Operand *y, AstNode *node) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (!is_type_integer(x->type)) {
|
||||
if (!is_type_integer(base_enum_type(x->type))) {
|
||||
// NOTE(bill): It could be an untyped float but still representable
|
||||
// as an integer
|
||||
x->type = t_untyped_integer;
|
||||
@@ -1709,7 +1710,7 @@ void check_shift(Checker *c, Operand *x, Operand *y, AstNode *node) {
|
||||
x->value = exact_value_shift(be->op.kind, x_val, make_exact_value_integer(amount));
|
||||
|
||||
if (is_type_typed(x->type)) {
|
||||
check_is_expressible(c, x, base_type(x->type));
|
||||
check_is_expressible(c, x, base_type(base_enum_type(x->type)));
|
||||
}
|
||||
return;
|
||||
}
|
||||
@@ -2416,7 +2417,7 @@ bool check_index_value(Checker *c, AstNode *index_value, i64 max_count, i64 *val
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!is_type_integer(operand.type)) {
|
||||
if (!is_type_integer(base_enum_type(operand.type))) {
|
||||
gbString expr_str = expr_to_string(operand.expr);
|
||||
error_node(operand.expr, "Index `%s` must be an integer", expr_str);
|
||||
gb_string_free(expr_str);
|
||||
|
||||
@@ -601,7 +601,10 @@ void check_stmt_internal(Checker *c, AstNode *node, u32 flags) {
|
||||
goto skip_expr;
|
||||
}
|
||||
|
||||
if (!is_type_integer(x.type) && !is_type_float(x.type) && !is_type_pointer(x.type)) {
|
||||
Type *type = x.type;
|
||||
Type *bt = base_type(base_enum_type(type));
|
||||
|
||||
if (!is_type_integer(bt) && !is_type_float(bt) && !is_type_pointer(bt)) {
|
||||
error(ie->op, "Only numerical and pointer types are allowed within interval expressions");
|
||||
goto skip_expr;
|
||||
}
|
||||
@@ -623,7 +626,7 @@ void check_stmt_internal(Checker *c, AstNode *node, u32 flags) {
|
||||
|
||||
add_type_and_value(&c->info, ie->left, x.mode, x.type, x.value);
|
||||
add_type_and_value(&c->info, ie->right, y.mode, y.type, y.value);
|
||||
val = x.type;
|
||||
val = type;
|
||||
idx = t_int;
|
||||
} else {
|
||||
Operand operand = {Addressing_Invalid};
|
||||
|
||||
494
src/llir_opt.c
Normal file
494
src/llir_opt.c
Normal file
@@ -0,0 +1,494 @@
|
||||
// Optimizations for the LLIR code
|
||||
|
||||
void llir_opt_add_operands(llirValueArray *ops, llirInstr *i) {
|
||||
switch (i->kind) {
|
||||
case llirInstr_Comment:
|
||||
break;
|
||||
case llirInstr_Local:
|
||||
break;
|
||||
case llirInstr_ZeroInit:
|
||||
array_add(ops, i->ZeroInit.address);
|
||||
break;
|
||||
case llirInstr_Store:
|
||||
array_add(ops, i->Store.address);
|
||||
array_add(ops, i->Store.value);
|
||||
break;
|
||||
case llirInstr_Load:
|
||||
array_add(ops, i->Load.address);
|
||||
break;
|
||||
case llirInstr_ArrayElementPtr:
|
||||
array_add(ops, i->ArrayElementPtr.address);
|
||||
array_add(ops, i->ArrayElementPtr.elem_index);
|
||||
break;
|
||||
case llirInstr_StructElementPtr:
|
||||
array_add(ops, i->StructElementPtr.address);
|
||||
break;
|
||||
case llirInstr_PtrOffset:
|
||||
array_add(ops, i->PtrOffset.address);
|
||||
array_add(ops, i->PtrOffset.offset);
|
||||
break;
|
||||
case llirInstr_ArrayExtractValue:
|
||||
array_add(ops, i->ArrayExtractValue.address);
|
||||
break;
|
||||
case llirInstr_StructExtractValue:
|
||||
array_add(ops, i->StructExtractValue.address);
|
||||
break;
|
||||
case llirInstr_Conv:
|
||||
array_add(ops, i->Conv.value);
|
||||
break;
|
||||
case llirInstr_Jump:
|
||||
break;
|
||||
case llirInstr_If:
|
||||
array_add(ops, i->If.cond);
|
||||
break;
|
||||
case llirInstr_Return:
|
||||
if (i->Return.value != NULL) {
|
||||
array_add(ops, i->Return.value);
|
||||
}
|
||||
break;
|
||||
case llirInstr_Select:
|
||||
array_add(ops, i->Select.cond);
|
||||
break;
|
||||
case llirInstr_Phi:
|
||||
for_array(j, i->Phi.edges) {
|
||||
array_add(ops, i->Phi.edges.e[j]);
|
||||
}
|
||||
break;
|
||||
case llirInstr_Unreachable:
|
||||
break;
|
||||
case llirInstr_UnaryOp:
|
||||
array_add(ops, i->UnaryOp.expr);
|
||||
break;
|
||||
case llirInstr_BinaryOp:
|
||||
array_add(ops, i->BinaryOp.left);
|
||||
array_add(ops, i->BinaryOp.right);
|
||||
break;
|
||||
case llirInstr_Call:
|
||||
array_add(ops, i->Call.value);
|
||||
for (isize j = 0; j < i->Call.arg_count; j++) {
|
||||
array_add(ops, i->Call.args[j]);
|
||||
}
|
||||
break;
|
||||
case llirInstr_VectorExtractElement:
|
||||
array_add(ops, i->VectorExtractElement.vector);
|
||||
array_add(ops, i->VectorExtractElement.index);
|
||||
break;
|
||||
case llirInstr_VectorInsertElement:
|
||||
array_add(ops, i->VectorInsertElement.vector);
|
||||
array_add(ops, i->VectorInsertElement.elem);
|
||||
array_add(ops, i->VectorInsertElement.index);
|
||||
break;
|
||||
case llirInstr_VectorShuffle:
|
||||
array_add(ops, i->VectorShuffle.vector);
|
||||
break;
|
||||
case llirInstr_StartupRuntime:
|
||||
break;
|
||||
case llirInstr_BoundsCheck:
|
||||
array_add(ops, i->BoundsCheck.index);
|
||||
array_add(ops, i->BoundsCheck.len);
|
||||
break;
|
||||
case llirInstr_SliceBoundsCheck:
|
||||
array_add(ops, i->SliceBoundsCheck.low);
|
||||
array_add(ops, i->SliceBoundsCheck.high);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
void llir_opt_block_replace_pred(llirBlock *b, llirBlock *from, llirBlock *to) {
|
||||
for_array(i, b->preds) {
|
||||
llirBlock *pred = b->preds.e[i];
|
||||
if (pred == from) {
|
||||
b->preds.e[i] = to;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void llir_opt_block_replace_succ(llirBlock *b, llirBlock *from, llirBlock *to) {
|
||||
for_array(i, b->succs) {
|
||||
llirBlock *succ = b->succs.e[i];
|
||||
if (succ == from) {
|
||||
b->succs.e[i] = to;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool llir_opt_block_has_phi(llirBlock *b) {
|
||||
return b->instrs.e[0]->Instr.kind == llirInstr_Phi;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
llirValueArray llir_get_block_phi_nodes(llirBlock *b) {
|
||||
llirValueArray phis = {0};
|
||||
for_array(i, b->instrs) {
|
||||
llirInstr *instr = &b->instrs.e[i]->Instr;
|
||||
if (instr->kind != llirInstr_Phi) {
|
||||
phis = b->instrs;
|
||||
phis.count = i;
|
||||
return phis;
|
||||
}
|
||||
}
|
||||
return phis;
|
||||
}
|
||||
|
||||
void llir_remove_pred(llirBlock *b, llirBlock *p) {
|
||||
llirValueArray phis = llir_get_block_phi_nodes(b);
|
||||
isize i = 0;
|
||||
for_array(j, b->preds) {
|
||||
llirBlock *pred = b->preds.e[j];
|
||||
if (pred != p) {
|
||||
b->preds.e[i] = b->preds.e[j];
|
||||
for_array(k, phis) {
|
||||
llirInstrPhi *phi = &phis.e[k]->Instr.Phi;
|
||||
phi->edges.e[i] = phi->edges.e[j];
|
||||
}
|
||||
i++;
|
||||
}
|
||||
}
|
||||
b->preds.count = i;
|
||||
for_array(k, phis) {
|
||||
llirInstrPhi *phi = &phis.e[k]->Instr.Phi;
|
||||
phi->edges.count = i;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void llir_remove_dead_blocks(llirProcedure *proc) {
|
||||
isize j = 0;
|
||||
for_array(i, proc->blocks) {
|
||||
llirBlock *b = proc->blocks.e[i];
|
||||
if (b == NULL) {
|
||||
continue;
|
||||
}
|
||||
// NOTE(bill): Swap order
|
||||
b->index = j;
|
||||
proc->blocks.e[j++] = b;
|
||||
}
|
||||
proc->blocks.count = j;
|
||||
}
|
||||
|
||||
void llir_mark_reachable(llirBlock *b) {
|
||||
isize const WHITE = 0;
|
||||
isize const BLACK = -1;
|
||||
b->index = BLACK;
|
||||
for_array(i, b->succs) {
|
||||
llirBlock *succ = b->succs.e[i];
|
||||
if (succ->index == WHITE) {
|
||||
llir_mark_reachable(succ);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void llir_remove_unreachable_blocks(llirProcedure *proc) {
|
||||
isize const WHITE = 0;
|
||||
isize const BLACK = -1;
|
||||
for_array(i, proc->blocks) {
|
||||
proc->blocks.e[i]->index = WHITE;
|
||||
}
|
||||
|
||||
llir_mark_reachable(proc->blocks.e[0]);
|
||||
|
||||
for_array(i, proc->blocks) {
|
||||
llirBlock *b = proc->blocks.e[i];
|
||||
if (b->index == WHITE) {
|
||||
for_array(j, b->succs) {
|
||||
llirBlock *c = b->succs.e[j];
|
||||
if (c->index == BLACK) {
|
||||
llir_remove_pred(c, b);
|
||||
}
|
||||
}
|
||||
// NOTE(bill): Mark as empty but don't actually free it
|
||||
// As it's been allocated with an arena
|
||||
proc->blocks.e[i] = NULL;
|
||||
}
|
||||
}
|
||||
llir_remove_dead_blocks(proc);
|
||||
}
|
||||
|
||||
bool llir_opt_block_fusion(llirProcedure *proc, llirBlock *a) {
|
||||
if (a->succs.count != 1) {
|
||||
return false;
|
||||
}
|
||||
llirBlock *b = a->succs.e[0];
|
||||
if (b->preds.count != 1) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (llir_opt_block_has_phi(b)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
array_pop(&a->instrs); // Remove branch at end
|
||||
for_array(i, b->instrs) {
|
||||
array_add(&a->instrs, b->instrs.e[i]);
|
||||
llir_set_instr_parent(b->instrs.e[i], a);
|
||||
}
|
||||
|
||||
array_clear(&a->succs);
|
||||
for_array(i, b->succs) {
|
||||
array_add(&a->succs, b->succs.e[i]);
|
||||
}
|
||||
|
||||
// Fix preds links
|
||||
for_array(i, b->succs) {
|
||||
llir_opt_block_replace_pred(b->succs.e[i], b, a);
|
||||
}
|
||||
|
||||
proc->blocks.e[b->index] = NULL;
|
||||
return true;
|
||||
}
|
||||
|
||||
void llir_opt_blocks(llirProcedure *proc) {
|
||||
llir_remove_unreachable_blocks(proc);
|
||||
|
||||
#if 1
|
||||
bool changed = true;
|
||||
while (changed) {
|
||||
changed = false;
|
||||
for_array(i, proc->blocks) {
|
||||
llirBlock *b = proc->blocks.e[i];
|
||||
if (b == NULL) {
|
||||
continue;
|
||||
}
|
||||
GB_ASSERT(b->index == i);
|
||||
|
||||
if (llir_opt_block_fusion(proc, b)) {
|
||||
changed = true;
|
||||
}
|
||||
// TODO(bill): other simple block optimizations
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
llir_remove_dead_blocks(proc);
|
||||
}
|
||||
void llir_opt_build_referrers(llirProcedure *proc) {
|
||||
gbTempArenaMemory tmp = gb_temp_arena_memory_begin(&proc->module->tmp_arena);
|
||||
|
||||
llirValueArray ops = {0}; // NOTE(bill): Act as a buffer
|
||||
array_init_reserve(&ops, proc->module->tmp_allocator, 64); // HACK(bill): This _could_ overflow the temp arena
|
||||
for_array(i, proc->blocks) {
|
||||
llirBlock *b = proc->blocks.e[i];
|
||||
for_array(j, b->instrs) {
|
||||
llirValue *instr = b->instrs.e[j];
|
||||
array_clear(&ops);
|
||||
llir_opt_add_operands(&ops, &instr->Instr);
|
||||
for_array(k, ops) {
|
||||
llirValue *op = ops.e[k];
|
||||
if (op == NULL) {
|
||||
continue;
|
||||
}
|
||||
llirValueArray *refs = llir_value_referrers(op);
|
||||
if (refs != NULL) {
|
||||
array_add(refs, instr);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
gb_temp_arena_memory_end(tmp);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
// State of Lengauer-Tarjan algorithm
|
||||
// Based on this paper: http://jgaa.info/accepted/2006/GeorgiadisTarjanWerneck2006.10.1.pdf
|
||||
typedef struct llirLTState {
|
||||
isize count;
|
||||
// NOTE(bill): These are arrays
|
||||
llirBlock **sdom; // Semidominator
|
||||
llirBlock **parent; // Parent in DFS traversal of CFG
|
||||
llirBlock **ancestor;
|
||||
} llirLTState;
|
||||
|
||||
// §2.2 - bottom of page
|
||||
void llir_lt_link(llirLTState *lt, llirBlock *p, llirBlock *q) {
|
||||
lt->ancestor[q->index] = p;
|
||||
}
|
||||
|
||||
i32 llir_lt_depth_first_search(llirLTState *lt, llirBlock *p, i32 i, llirBlock **preorder) {
|
||||
preorder[i] = p;
|
||||
p->dom.pre = i++;
|
||||
lt->sdom[p->index] = p;
|
||||
llir_lt_link(lt, NULL, p);
|
||||
for_array(index, p->succs) {
|
||||
llirBlock *q = p->succs.e[index];
|
||||
if (lt->sdom[q->index] == NULL) {
|
||||
lt->parent[q->index] = p;
|
||||
i = llir_lt_depth_first_search(lt, q, i, preorder);
|
||||
}
|
||||
}
|
||||
return i;
|
||||
}
|
||||
|
||||
llirBlock *llir_lt_eval(llirLTState *lt, llirBlock *v) {
|
||||
llirBlock *u = v;
|
||||
for (;
|
||||
lt->ancestor[v->index] != NULL;
|
||||
v = lt->ancestor[v->index]) {
|
||||
if (lt->sdom[v->index]->dom.pre < lt->sdom[u->index]->dom.pre) {
|
||||
u = v;
|
||||
}
|
||||
}
|
||||
return u;
|
||||
}
|
||||
|
||||
typedef struct llirDomPrePost {
|
||||
i32 pre, post;
|
||||
} llirDomPrePost;
|
||||
|
||||
llirDomPrePost llir_opt_number_dom_tree(llirBlock *v, i32 pre, i32 post) {
|
||||
llirDomPrePost result = {pre, post};
|
||||
|
||||
v->dom.pre = pre++;
|
||||
for_array(i, v->dom.children) {
|
||||
result = llir_opt_number_dom_tree(v->dom.children.e[i], result.pre, result.post);
|
||||
}
|
||||
v->dom.post = post++;
|
||||
|
||||
result.pre = pre;
|
||||
result.post = post;
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
// NOTE(bill): Requires `llir_opt_blocks` to be called before this
|
||||
void llir_opt_build_dom_tree(llirProcedure *proc) {
|
||||
// Based on this paper: http://jgaa.info/accepted/2006/GeorgiadisTarjanWerneck2006.10.1.pdf
|
||||
|
||||
gbTempArenaMemory tmp = gb_temp_arena_memory_begin(&proc->module->tmp_arena);
|
||||
|
||||
isize n = proc->blocks.count;
|
||||
llirBlock **buf = gb_alloc_array(proc->module->tmp_allocator, llirBlock *, 5*n);
|
||||
|
||||
llirLTState lt = {0};
|
||||
lt.count = n;
|
||||
lt.sdom = &buf[0*n];
|
||||
lt.parent = &buf[1*n];
|
||||
lt.ancestor = &buf[2*n];
|
||||
|
||||
llirBlock **preorder = &buf[3*n];
|
||||
llirBlock **buckets = &buf[4*n];
|
||||
llirBlock *root = proc->blocks.e[0];
|
||||
|
||||
// Step 1 - number vertices
|
||||
i32 pre_num = llir_lt_depth_first_search(<, root, 0, preorder);
|
||||
gb_memmove(buckets, preorder, n*gb_size_of(preorder[0]));
|
||||
|
||||
for (i32 i = n-1; i > 0; i--) {
|
||||
llirBlock *w = preorder[i];
|
||||
|
||||
// Step 3 - Implicitly define idom for nodes
|
||||
for (llirBlock *v = buckets[i]; v != w; v = buckets[v->dom.pre]) {
|
||||
llirBlock *u = llir_lt_eval(<, v);
|
||||
if (lt.sdom[u->index]->dom.pre < i) {
|
||||
v->dom.idom = u;
|
||||
} else {
|
||||
v->dom.idom = w;
|
||||
}
|
||||
}
|
||||
|
||||
// Step 2 - Compute all sdoms
|
||||
lt.sdom[w->index] = lt.parent[w->index];
|
||||
for_array(pred_index, w->preds) {
|
||||
llirBlock *v = w->preds.e[pred_index];
|
||||
llirBlock *u = llir_lt_eval(<, v);
|
||||
if (lt.sdom[u->index]->dom.pre < lt.sdom[w->index]->dom.pre) {
|
||||
lt.sdom[w->index] = lt.sdom[u->index];
|
||||
}
|
||||
}
|
||||
|
||||
llir_lt_link(<, lt.parent[w->index], w);
|
||||
|
||||
if (lt.parent[w->index] == lt.sdom[w->index]) {
|
||||
w->dom.idom = lt.parent[w->index];
|
||||
} else {
|
||||
buckets[i] = buckets[lt.sdom[w->index]->dom.pre];
|
||||
buckets[lt.sdom[w->index]->dom.pre] = w;
|
||||
}
|
||||
}
|
||||
|
||||
// The rest of Step 3
|
||||
for (llirBlock *v = buckets[0]; v != root; v = buckets[v->dom.pre]) {
|
||||
v->dom.idom = root;
|
||||
}
|
||||
|
||||
// Step 4 - Explicitly define idom for nodes (in preorder)
|
||||
for (isize i = 1; i < n; i++) {
|
||||
llirBlock *w = preorder[i];
|
||||
if (w == root) {
|
||||
w->dom.idom = NULL;
|
||||
} else {
|
||||
// Weird tree relationships here!
|
||||
|
||||
if (w->dom.idom != lt.sdom[w->index]) {
|
||||
w->dom.idom = w->dom.idom->dom.idom;
|
||||
}
|
||||
|
||||
// Calculate children relation as inverse of idom
|
||||
if (w->dom.idom->dom.children.e == NULL) {
|
||||
// TODO(bill): Is this good enough for memory allocations?
|
||||
array_init(&w->dom.idom->dom.children, heap_allocator());
|
||||
}
|
||||
array_add(&w->dom.idom->dom.children, w);
|
||||
}
|
||||
}
|
||||
|
||||
llir_opt_number_dom_tree(root, 0, 0);
|
||||
|
||||
gb_temp_arena_memory_end(tmp);
|
||||
}
|
||||
|
||||
void llir_opt_mem2reg(llirProcedure *proc) {
|
||||
// TODO(bill): llir_opt_mem2reg
|
||||
}
|
||||
|
||||
|
||||
|
||||
void llir_opt_tree(llirGen *s) {
|
||||
s->opt_called = true;
|
||||
|
||||
for_array(member_index, s->module.procs) {
|
||||
llirProcedure *proc = s->module.procs.e[member_index];
|
||||
if (proc->blocks.count == 0) { // Prototype/external procedure
|
||||
continue;
|
||||
}
|
||||
|
||||
llir_opt_blocks(proc);
|
||||
#if 1
|
||||
llir_opt_build_referrers(proc);
|
||||
llir_opt_build_dom_tree(proc);
|
||||
|
||||
// TODO(bill): llir optimization
|
||||
// [ ] cse (common-subexpression) elim
|
||||
// [ ] copy elim
|
||||
// [ ] dead code elim
|
||||
// [ ] dead store/load elim
|
||||
// [ ] phi elim
|
||||
// [ ] short circuit elim
|
||||
// [ ] bounds check elim
|
||||
// [ ] lift/mem2reg
|
||||
// [ ] lift/mem2reg
|
||||
|
||||
llir_opt_mem2reg(proc);
|
||||
#endif
|
||||
|
||||
GB_ASSERT(proc->blocks.count > 0);
|
||||
llir_number_proc_registers(proc);
|
||||
}
|
||||
}
|
||||
1515
src/llir_print.c
Normal file
1515
src/llir_print.c
Normal file
File diff suppressed because it is too large
Load Diff
@@ -11,6 +11,7 @@ extern "C" {
|
||||
// #include "printer.c"
|
||||
#include "checker/checker.c"
|
||||
#include "llir.c"
|
||||
#include "llir_opt.c"
|
||||
#include "llir_print.c"
|
||||
// #include "vm.c"
|
||||
|
||||
@@ -168,6 +169,9 @@ int main(int argc, char **argv) {
|
||||
timings_start_section(&timings, str_lit("llvm ir gen"));
|
||||
llir_gen_tree(&llir);
|
||||
|
||||
timings_start_section(&timings, str_lit("llvm ir opt tree"));
|
||||
llir_opt_tree(&llir);
|
||||
|
||||
timings_start_section(&timings, str_lit("llvm ir print"));
|
||||
print_llvm_ir(&llir);
|
||||
|
||||
|
||||
@@ -1262,6 +1262,9 @@ bool is_semicolon_optional_for_node(AstFile *f, AstNode *s) {
|
||||
case AstNode_HelperType:
|
||||
return is_semicolon_optional_for_node(f, s->HelperType.type);
|
||||
|
||||
case AstNode_PointerType:
|
||||
return is_semicolon_optional_for_node(f, s->PointerType.type);
|
||||
|
||||
case AstNode_StructType:
|
||||
case AstNode_UnionType:
|
||||
case AstNode_RawUnionType:
|
||||
|
||||
Reference in New Issue
Block a user