commit 2b05fa5fc81752451f2d77c65d1576cbab6dd4a3
parent 5c2fd7178042b54c0c2e5b9045d66cd2853a66ed
Author: erai <erai@omiltem.net>
Date: Sun, 2 Feb 2025 18:33:47 +0000
flow control graph simplification
Diffstat:
M | cc0.c | | | 72 | ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ |
M | ir.om | | | 103 | ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++- |
2 files changed, 174 insertions(+), 1 deletion(-)
diff --git a/cc0.c b/cc0.c
@@ -770,6 +770,9 @@ void( my_iraddarg)(struct my_irfunc* my_ic,unsigned char* my_name,struct my_type
void( my_iraddop)(struct my_irfunc* my_ic,struct my_irop* my_o);
void( my_iraddvar)(struct my_irfunc* my_ic,unsigned char* my_name,struct my_type* my_t);
void( my_irblock_dead_expr)(struct my_irfunc* my_ic,struct my_irblock* my_b);
+void( my_irblock_flow)(struct my_irfunc* my_ic);
+void( my_irblock_flow2)(struct my_irfunc* my_ic,struct my_irblock* my_ib);
+void( my_irblock_flow3)(struct my_irfunc* my_ic,struct my_irblock* my_ib);
void( my_irblock_fold)(struct my_irfunc* my_ic,struct my_irblock* my_b);
void( my_irbranch)(struct my_irfunc* my_ic,struct my_irop* my_cond,struct my_irblock* my_alt,struct my_irblock* my_next);
struct my_irop*( my_ircall)(struct my_irfunc* my_ic,struct my_node* my_n);
@@ -4517,6 +4520,7 @@ void( my_ir_optimize)(struct my_irfunc* my_ic){
(my_irblock_fold)((my_ic),(((my_ic)->my_blocks)[my_i]));
(my_i)=((unsigned long)(((unsigned long)(my_i))+((unsigned long)(1UL))));
}
+ (my_irblock_flow)((my_ic));
}
void( my_iraddarg)(struct my_irfunc* my_ic,unsigned char* my_name,struct my_type* my_t){
struct my_irvar** my_iv = 0;
@@ -4585,6 +4589,74 @@ void( my_irblock_dead_expr)(struct my_irfunc* my_ic,struct my_irblock* my_b){
}
((my_b)->my_ops_len)=(my_j);
}
+void( my_irblock_flow)(struct my_irfunc* my_ic){
+ (my_irblock_flow2)((my_ic),(((my_ic)->my_blocks)[0UL]));
+ (my_irblock_flow3)((my_ic),(((my_ic)->my_blocks)[0UL]));
+ (my_irreset)((((my_ic)->my_blocks)[0UL]));
+}
+void( my_irblock_flow2)(struct my_irfunc* my_ic,struct my_irblock* my_ib){
+ unsigned long my_kind = 0;
+ if ((my_ib)->my_mark) {
+ ((my_ib)->my_mark)=(2UL);
+ return;
+ }
+ ((my_ib)->my_mark)=(1UL);
+ (my_kind)=((((my_ib)->my_ops)[(unsigned long)(((unsigned long)((my_ib)->my_ops_len))-((unsigned long)(1UL)))])->my_kind);
+ if ((unsigned long)(((long)(my_kind))==((long)(my_IOP_BRANCH)))) {
+ (my_irblock_flow2)((my_ic),((my_ib)->my_alt));
+ if ((unsigned long)(((unsigned long)(((long)(((my_ib)->my_alt)->my_ops_len))==((long)(1UL))))&&((unsigned long)(((long)(((((my_ib)->my_alt)->my_ops)[0UL])->my_kind))==((long)(my_IOP_JUMP)))))) {
+ ((my_ib)->my_alt)=(((my_ib)->my_alt)->my_out);
+ }
+ }
+ if ((unsigned long)(((unsigned long)(((long)(my_kind))==((long)(my_IOP_BRANCH))))||((unsigned long)(((unsigned long)(((long)(my_kind))==((long)(my_IOP_CALL))))||((unsigned long)(((long)(my_kind))==((long)(my_IOP_JUMP)))))))) {
+ (my_irblock_flow2)((my_ic),((my_ib)->my_out));
+ if ((unsigned long)(((unsigned long)(((long)(((my_ib)->my_out)->my_ops_len))==((long)(1UL))))&&((unsigned long)(((long)(((((my_ib)->my_out)->my_ops)[0UL])->my_kind))==((long)(my_IOP_JUMP)))))) {
+ ((my_ib)->my_out)=(((my_ib)->my_out)->my_out);
+ }
+ }
+}
+void( my_irblock_flow3)(struct my_irfunc* my_ic,struct my_irblock* my_ib){
+ struct my_irblock* my_out = 0;
+ unsigned long my_kind = 0;
+ unsigned long my_i = 0;
+ if ((unsigned long)(((long)((my_ib)->my_mark))==((long)(3UL)))) {
+ return;
+ }
+ ((my_ib)->my_mark)=(3UL);
+ while (1) {
+ (my_kind)=((((my_ib)->my_ops)[(unsigned long)(((unsigned long)((my_ib)->my_ops_len))-((unsigned long)(1UL)))])->my_kind);
+ if ((unsigned long)(((long)(my_kind))==((long)(my_IOP_BRANCH)))) {
+ (my_irblock_flow3)((my_ic),((my_ib)->my_alt));
+ break;
+ }
+ if ((unsigned long)(((long)(my_kind))!=((long)(my_IOP_JUMP)))) {
+ break;
+ }
+ (my_out)=((my_ib)->my_out);
+ if ((unsigned long)(((long)((my_out)->my_mark))==((long)(2UL)))) {
+ (my_ib)=(my_out);
+ ((my_ib)->my_mark)=(3UL);
+ continue;
+ }
+ if ((unsigned long)(((long)((my_out)->my_mark))==((long)(3UL)))) {
+ break;
+ }
+ ((my_ib)->my_out)=((void *)0);
+ ((my_ib)->my_ops_len)=((unsigned long)(((unsigned long)((my_ib)->my_ops_len))-((unsigned long)(1UL))));
+ ((my_ib)->my_done)=(0UL);
+ (my_i)=(0UL);
+ while (1) {
+ if ((unsigned long)(((long)(my_i))==((long)((my_out)->my_ops_len)))) {
+ break;
+ }
+ (my_iraddop)((my_ic),(((my_out)->my_ops)[my_i]));
+ (my_i)=((unsigned long)(((unsigned long)(my_i))+((unsigned long)(1UL))));
+ }
+ ((my_ib)->my_out)=((my_out)->my_out);
+ ((my_ib)->my_alt)=((my_out)->my_alt);
+ ((my_ib)->my_done)=(1UL);
+ }
+}
void( my_irblock_fold)(struct my_irfunc* my_ic,struct my_irblock* my_b){
unsigned long my_i = 0;
struct my_irop* my_o = 0;
diff --git a/ir.om b/ir.om
@@ -2374,6 +2374,100 @@ func irblock_fold(ic: *irfunc, b: *irblock) {
}
}
+func irblock_flow2(ic: *irfunc, ib: *irblock) {
+ var kind: int;
+
+ if ib.mark {
+ ib.mark = 2;
+ return;
+ }
+
+ ib.mark = 1;
+
+ kind = ib.ops[ib.ops_len - 1].kind;
+
+ if kind == IOP_BRANCH {
+ irblock_flow2(ic, ib.alt);
+
+ if ib.alt.ops_len == 1 && ib.alt.ops[0].kind == IOP_JUMP {
+ ib.alt = ib.alt.out;
+ }
+ }
+
+ if kind == IOP_BRANCH || kind == IOP_CALL || kind == IOP_JUMP {
+ irblock_flow2(ic, ib.out);
+
+ if ib.out.ops_len == 1 && ib.out.ops[0].kind == IOP_JUMP {
+ ib.out = ib.out.out;
+ }
+ }
+}
+
+func irblock_flow3(ic: *irfunc, ib: *irblock) {
+ var out: *irblock;
+ var kind: int;
+ var i: int;
+
+ if ib.mark == 3 {
+ return;
+ }
+
+ ib.mark = 3;
+
+ loop {
+ kind = ib.ops[ib.ops_len - 1].kind;
+
+ if kind == IOP_BRANCH {
+ irblock_flow3(ic, ib.alt);
+ break;
+ }
+
+ if kind != IOP_JUMP {
+ break;
+ }
+
+ out = ib.out;
+
+ if out.mark == 2 {
+ ib = out;
+ ib.mark = 3;
+ continue;
+ }
+
+ if out.mark == 3 {
+ break;
+ }
+
+ // Delete the jump
+ ib.out = nil;
+ ib.ops_len = ib.ops_len - 1;
+ ib.done = 0;
+
+ // Concatenate the block
+ i = 0;
+ loop {
+ if i == out.ops_len {
+ break;
+ }
+
+ iraddop(ic, out.ops[i]);
+
+ i = i + 1;
+ }
+
+ // Possible branch
+ ib.out = out.out;
+ ib.alt = out.alt;
+ ib.done = 1;
+ }
+}
+
+func irblock_flow(ic: *irfunc) {
+ irblock_flow2(ic, ic.blocks[0]);
+ irblock_flow3(ic, ic.blocks[0]);
+ irreset(ic.blocks[0]);
+}
+
func ir_optimize(ic: *irfunc) {
var i: int;
@@ -2401,12 +2495,14 @@ func ir_optimize(ic: *irfunc) {
i = i + 1;
}
+ irblock_flow(ic);
+
// live values
// value forwarding
// common subexpression
- // flow control simplification
// inlining
+
// register allocation
// instruction selection
}
@@ -2414,9 +2510,14 @@ func ir_optimize(ic: *irfunc) {
// loop detection
// unrolling
// loop motion / fusion
+
// strength reduction / algebra
+
// alias analysis
+
// type check with ir
// parse to ir
+
// c generator from ir
+
// intrinsics