summaryrefslogtreecommitdiff
path: root/chapter28b/src/main/java/com
diff options
context:
space:
mode:
authorCliff Click <cliffc@acm.org>2026-10-28 09:43:58 -0700
committerCliff Click <cliffc@acm.org>2026-10-28 09:43:58 -0700
commit62db70539965abbe84f66c2e395d8c240e89177d (patch)
treec466692f2d126b23e8fa6a8a03c8b7b6b75cf02a /chapter28b/src/main/java/com
parent696adef058d43695ac1c47a7223d9e7a8b8ab6ea (diff)
downloadSimple-62db70539965abbe84f66c2e395d8c240e89177d.tar.gz
Simple-62db70539965abbe84f66c2e395d8c240e89177d.zip
Phases back to bneing driven top-down only
Diffstat (limited to 'chapter28b/src/main/java/com')
-rw-r--r--chapter28b/src/main/java/com/seaofnodes/simple/codegen/CodeGen.java54
-rw-r--r--chapter28b/src/main/java/com/seaofnodes/simple/node/CFGNode.java10
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);
}