summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--ir.c30
-rw-r--r--main.c28
-rw-r--r--test.lang8
3 files changed, 56 insertions, 10 deletions
diff --git a/ir.c b/ir.c
index a9fcd44..3ed9535 100644
--- a/ir.c
+++ b/ir.c
@@ -722,8 +722,17 @@ zero_no_effect: if (node_eql_i64(CAR(n), 0)) return CDR(n);
}
break;
+ case N_RETURN:
+ if (CTRL(n)->val.type.lvl == T_XCTRL) return CTRL(n);
+ break;
+
case N_PROJ:
if (T(CTRL(n), N_IF_ELSE) && CTRL(n)->val.type.t == T_TUPLE) {
+ if (CTRL(n)->val.tuple.data[n->val.i].type.lvl == T_XCTRL) {
+ return node_new_lit(p, (Value) {
+ .type = { .lvl = T_XCTRL, .t = T_NONE }
+ });
+ }
if (CTRL(n)->val.tuple.data[(n->val.i + 1) % CTRL(n)->val.tuple.len].type.lvl == T_XCTRL) {
return CTRL(CTRL(n));
}
@@ -736,6 +745,27 @@ zero_no_effect: if (node_eql_i64(CAR(n), 0)) return CDR(n);
if (IN(CTRL(n), 0)->val.type.lvl == T_XCTRL) return CDR(n);
break;
+ case N_REGION:
+ {
+ int live_in = 0;
+ for (int i = 0; i < n->in.len; i++) {
+ if (IN(n, i)->val.type.lvl != T_XCTRL) live_in++;
+ }
+ if (live_in == 1) {
+ for (int i = 0; i < n->in.len; i++) {
+ if (IN(n, i)->val.type.lvl != T_XCTRL) {
+ return IN(n, i);
+ }
+ }
+ }
+ if (live_in == 0) {
+ return node_new_lit(p, (Value) {
+ .type = { .lvl = T_XCTRL, .t = T_NONE }
+ });
+ }
+ }
+ break;
+
default:
break;
}
diff --git a/main.c b/main.c
index 4a7a3d4..edeb6a5 100644
--- a/main.c
+++ b/main.c
@@ -48,8 +48,13 @@ void parse_return(Lexer *l, Proc *p) {
}
n = node_new(p, N_RETURN, p->ctrl, e);
}
- node_add(p, n, p->stop);
- p->ctrl = n;
+ n = node_peephole(n, p, l);
+ if (n->val.type.lvl != T_XCTRL) {
+ node_add(p, n, p->stop);
+ }
+ p->ctrl = node_new_lit(p, (Value) {
+ .type = { .lvl = T_XCTRL, .t = T_NONE }
+ });
}
void parse_let(Lexer *l, Proc *p) {
@@ -154,11 +159,11 @@ void parse_if(Lexer *l, Proc *p) {
if_false->val.i = 1;
if_true = node_peephole(if_true, p, l);
if_false = node_peephole(if_false, p, l);
+ node_remove(p, if_node, p->keepalive);
assert(if_true->in.len > 0);
assert(if_false->in.len > 0);
node_add(p, if_true, p->keepalive);
node_add(p, if_false, p->keepalive);
- node_remove(p, if_node, p->keepalive);
ScopeNameList scope_before = { 0 }, scope_true = { 0 }, scope_false = { 0 };
scope_collect(&p->scope, p, &scope_before, &p->arena);
if (cond->val.type.lvl == T_CONST) {
@@ -184,20 +189,26 @@ void parse_if(Lexer *l, Proc *p) {
ctrl_else = p->ctrl;
node_add(p, ctrl_else, p->keepalive);
}
+ Node *ctrl_was = p->ctrl;
+ //node_add(p, ctrl_was, p->keepalive);
+ Node *region;
if (ctrl_else) {
//assert(ctrl_if->in.len > 0);
//assert(ctrl_else->in.len > 0);
- p->ctrl = node_peephole(node_new(p, N_REGION, ctrl_if, ctrl_else), p, l);
+ region = node_new(p, N_REGION, ctrl_if, ctrl_else);
+ node_add_out(p, region, p->keepalive);
node_remove(p, ctrl_if, p->keepalive);
node_remove(p, ctrl_else, p->keepalive);
} else {
//assert(ctrl_if->in.len > 0);
//assert(if_false->in.len > 0);
- p->ctrl = node_peephole(node_new(p, N_REGION, ctrl_if, if_false), p, l);
+ region = node_new(p, N_REGION, ctrl_if, if_false);
+ node_add_out(p, region, p->keepalive);
node_remove(p, ctrl_if, p->keepalive);
assert(if_true->refs > 0);
assert(if_false->refs > 0);
}
+ p->ctrl = region;
node_remove(p, if_true, p->keepalive);
node_remove(p, if_false, p->keepalive);
//p->ctrl = node_peephole(node_new(p, N_REGION, if_true, if_false), p, l);
@@ -206,6 +217,13 @@ void parse_if(Lexer *l, Proc *p) {
scope_uncollect(&p->scope, p, &scope_true);
scope_uncollect(&p->scope, p, &scope_false);
scope_uncollect(&p->scope, p, &scope_before);
+ fprintf(stderr, "%ld\n", p->ctrl->out.len);
+ node_del_out(p->ctrl, p->keepalive);
+ assert(p->ctrl == region);
+ /* make sure we're not orphaning any phi nodes*/
+ if (p->ctrl->out.len < 1) {
+ p->ctrl = node_peephole(p->ctrl, p, l);
+ }
}
void parse_stmt(Lexer *l, Proc *p) {
diff --git a/test.lang b/test.lang
index 2d3c42d..f717086 100644
--- a/test.lang
+++ b/test.lang
@@ -1,8 +1,6 @@
func main(a, b i64) i64 {
- if true {
- a := 3
- } else {
- a := 5
+ if a < b {
+ return a + b
}
- return a
+ return b
}