os

An operating system
git clone https://erai.gay/code/os/
Log | Files | Refs | README | LICENSE

commit 2b05fa5fc81752451f2d77c65d1576cbab6dd4a3
parent 5c2fd7178042b54c0c2e5b9045d66cd2853a66ed
Author: erai <erai@omiltem.net>
Date:   Sun,  2 Feb 2025 18:33:47 +0000

flow control graph simplification

Diffstat:
Mcc0.c | 72++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Mir.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