diff options
| author | Cliff Click <cliffc@acm.org> | 2026-10-28 09:43:58 -0700 |
|---|---|---|
| committer | Cliff Click <cliffc@acm.org> | 2026-10-28 09:43:58 -0700 |
| commit | 62db70539965abbe84f66c2e395d8c240e89177d (patch) | |
| tree | c466692f2d126b23e8fa6a8a03c8b7b6b75cf02a /chapter28b/src/main/java/com/seaofnodes | |
| parent | 696adef058d43695ac1c47a7223d9e7a8b8ab6ea (diff) | |
| download | Simple-62db70539965abbe84f66c2e395d8c240e89177d.tar.gz Simple-62db70539965abbe84f66c2e395d8c240e89177d.zip | |
Phases back to bneing driven top-down only
Diffstat (limited to 'chapter28b/src/main/java/com/seaofnodes')
| -rw-r--r-- | chapter28b/src/main/java/com/seaofnodes/simple/codegen/CodeGen.java | 54 | ||||
| -rw-r--r-- | chapter28b/src/main/java/com/seaofnodes/simple/node/CFGNode.java | 10 |
2 files changed, 18 insertions, 46 deletions
diff --git a/chapter28b/src/main/java/com/seaofnodes/simple/codegen/CodeGen.java b/chapter28b/src/main/java/com/seaofnodes/simple/codegen/CodeGen.java index e56068e7..2852e23d 100644 --- a/chapter28b/src/main/java/com/seaofnodes/simple/codegen/CodeGen.java +++ b/chapter28b/src/main/java/com/seaofnodes/simple/codegen/CodeGen.java @@ -261,17 +261,16 @@ public class CodeGen { step(target, Phase.FinalizeIR, this::finalizeIR, dump); // Final error check - bad programs fail here step(target, Phase.TypeCheck, this::typeCheck, dump); - if( cpu==null && target.ordinal()>=Phase.Lower.ordinal() && _phase.ordinal()<Phase.Lower.ordinal() ) - loadAllIR(); // Ideal evaluation needs code for calls left out of line. // Save reloadable ideal IR for a later seperate compilation step(target, Phase.Serialize, () -> Serialize.forTarget(this,target,inMemory), dump); - // Replace "fat" nodes with their exploded explicit IR; this can - // introduce CFG diamonds - step(target, Phase.Lower, this::lower, dump); + // Eval2 executes ideal operations, including CLInit, directly. Only + // machine compilation expands them before scheduling. + step(target, Phase.Lower, () -> { if( cpu!=null ) lower(); }, dump); // Compute the loop-tree, used for approximating exec frequencies for // scheduling and register allocation step(target, Phase.LoopTree, this::loopTree, dump); - // Drop imports for machine selection, retain them for ideal evaluation. + // Detach call-graph edges; ideal execution retains unloaded summaries + // as dispatch targets and schedules their bodies on first use. step(target, Phase.Unlink, () -> unlink(cpu!=null), dump); // Instruction selection step(target, Phase.Select, () -> instSelect(cpu,callingConv), dump); @@ -494,34 +493,6 @@ public class CodeGen { ParseAll.loadCompUnit(this,cu); } - // Evaluation needs implementations even for calls left out of line. E.g., - // this code is being run by the evaluator, and so doesn't get a link step. - // If, instead, the code was going to run natively, it would first go - // through a link step which would resolve all these call sites to code - // generated in other object files. Since no link step, we need acess to - // that other code right now. - public void loadAllIR() { - boolean loaded = false; - for( CompUnit cu : _compunits.values() ) { - if( cu._src!=null || cu._obj==null ) continue; - ElfReader elf = getElf(cu._obj); - if( elf._nodes!=null ) continue; - ParseAll.loadCompUnit(this,cu); - loaded=true; - } - if( !loaded ) return; - if( _phase.ordinal()<Phase.FinalizeIR.ordinal() ) return; - Phase prior = _phase; - try { - _phase=Phase.IterPostOpto; - _iter.iterate(this); - _phase=Phase.FinalizeIR; - FinalizeIR.run(this); - _phase=Phase.TypeCheck; - TypeCheck.run(this); - } finally { _phase=prior; } - } - // TypeCheck saves its successful analysis for Serialize. Loading bodies // or entering another graph-changing phase discards it. ClassInitDependencies _classInitDependencies; @@ -613,7 +584,8 @@ public class CodeGen { // --------------------------- // Build the loop tree; break never-exit loops public CodeGen loopTree() { - return phase(Phase.LoopTree, _phase==Phase.Lower, () -> _start.buildLoopTree(_linker,_stop)); + return phase(Phase.LoopTree, (_phase==Phase.Lower || _phase==Phase.TypeCheck || _phase==Phase.Serialize), + () -> _start.buildLoopTree(_linker,_stop)); } // --------------------------- @@ -654,7 +626,10 @@ public class CodeGen { unlink(true); } private void unlink(boolean removeImports) { - phase(Phase.Unlink, _phase==Phase.LoopTree, () -> Unlink.run(this,removeImports)); + phase(Phase.Unlink, _phase==Phase.LoopTree, () -> { + if( removeImports ) Unlink.run(this,true); + else Unlink.forEval(this,_start,_stop); + }); } // --------------------------- @@ -666,13 +641,6 @@ public class CodeGen { return phase(Phase.Schedule, (_phase==Phase.Unlink || _phase==Phase.Select), () -> GlobalCodeMotion.buildCFG(this)); } - // Evaluation branches from checked ideal IR directly to scheduling. - // CLInit remains an executable ideal operation; no Lower or Select pass. - public CodeGen scheduleForEval() { - return phase(Phase.Schedule, (_phase==Phase.TypeCheck || _phase==Phase.Serialize), - () -> _cfg=GlobalCodeMotion.forEval(this,_start,_stop)); - } - // --------------------------- // Local (basic block) scheduler phase, a classic list scheduler public CodeGen localSched() { return phase(Phase.LocalSched, _phase==Phase.Schedule, () -> ListScheduler.sched(this)); } diff --git a/chapter28b/src/main/java/com/seaofnodes/simple/node/CFGNode.java b/chapter28b/src/main/java/com/seaofnodes/simple/node/CFGNode.java index 7740df79..2e8c3ff9 100644 --- a/chapter28b/src/main/java/com/seaofnodes/simple/node/CFGNode.java +++ b/chapter28b/src/main/java/com/seaofnodes/simple/node/CFGNode.java @@ -207,7 +207,9 @@ public abstract class CFGNode extends Node { int pre = 1; _pre = pre++; for( FunNode fun : funs ) { - if( fun!=null && !fun.isDead() && !fun._type.isHigh() ) { + // Summaries have no executable CFG. Their loop trees are built + // only if Eval2 later loads the corresponding bodies. + if( fun!=null && !fun.isDead() && !fun._type.isHigh() && fun.summary()==null ) { work.push(fun); if(fun.in(1) instanceof StartCUNode start && start._pre==0 ) { start._pre = pre++; @@ -237,7 +239,7 @@ public abstract class CFGNode extends Node { for( Node use : _outputs ) if( use instanceof CFGNode usecfg ) { if( skip( usecfg ) ) { - if( usecfg._pre==0 && usecfg instanceof FunNode fun2 ) work.add( fun2 ); + if( usecfg._pre==0 && usecfg instanceof FunNode fun2 && fun2.summary()==null ) work.add( fun2 ); } else pre = usecfg._bltWalk( pre, use instanceof FunNode fuse ? fuse : fun, stop, post, work ); } @@ -285,9 +287,11 @@ public abstract class CFGNode extends Node { public boolean skip(CFGNode usecfg) { // Only walk control users that are alive. - // Do not walk from a Call to linked Fun's. + // Do not follow interprocedural edges. CLInit's call projection is + // only an analysis edge, not a branch in the caller's loop tree. return usecfg instanceof XCtrlNode || (this instanceof CallNode && usecfg instanceof FunNode) || + (this instanceof CLInitNode && usecfg instanceof CProjNode proj && proj._idx==3) || (this instanceof CProjNode proj && proj._idx==3 && proj.in(0) instanceof CLInitNode && usecfg instanceof FunNode) || (this instanceof ReturnNode && usecfg instanceof CallEndNode); } |
