summaryrefslogtreecommitdiff
path: root/chapter11/src/main/java/com/seaofnodes
diff options
context:
space:
mode:
authorCliff Click <cliffc@acm.org>2026-09-19 22:31:42 -0700
committerCliff Click <cliffc@acm.org>2026-09-19 22:31:42 -0700
commit6e59fc1b71f2098c8baf90a6c54e5a33b7291e94 (patch)
treecb097fb6fdb0f7941ac7e784f56e11750ab14c53 /chapter11/src/main/java/com/seaofnodes
parent45bd2e5fae4cbbee0ddd07094755c2f995178f28 (diff)
downloadSimple-6e59fc1b71f2098c8baf90a6c54e5a33b7291e94.tar.gz
Simple-6e59fc1b71f2098c8baf90a6c54e5a33b7291e94.zip
Unify mixed-return checking and results
Unify dominator caching.
Diffstat (limited to 'chapter11/src/main/java/com/seaofnodes')
-rw-r--r--chapter11/src/main/java/com/seaofnodes/simple/GlobalCodeMotion.java4
-rw-r--r--chapter11/src/main/java/com/seaofnodes/simple/node/CFGNode.java15
-rw-r--r--chapter11/src/main/java/com/seaofnodes/simple/node/LoopNode.java2
-rw-r--r--chapter11/src/main/java/com/seaofnodes/simple/node/RegionNode.java11
-rw-r--r--chapter11/src/main/java/com/seaofnodes/simple/node/StopNode.java2
5 files changed, 20 insertions, 14 deletions
diff --git a/chapter11/src/main/java/com/seaofnodes/simple/GlobalCodeMotion.java b/chapter11/src/main/java/com/seaofnodes/simple/GlobalCodeMotion.java
index 14540d46..99f2f0ea 100644
--- a/chapter11/src/main/java/com/seaofnodes/simple/GlobalCodeMotion.java
+++ b/chapter11/src/main/java/com/seaofnodes/simple/GlobalCodeMotion.java
@@ -148,7 +148,7 @@ public abstract class GlobalCodeMotion {
assert early != null;
CFGNode lca = null;
for( Node use : n._outputs )
- lca = use_block(n,use, late).idom(lca);
+ lca = use_block(n,use, late).domLCA(lca);
// Loads may need anti-dependencies, raising their LCA
if( n instanceof LoadNode load )
@@ -226,7 +226,7 @@ public abstract class GlobalCodeMotion {
for( ; stblk != defblk.idom(); stblk = stblk.idom() ) {
// Store and Load overlap, need anti-dependence
if( stblk._anti==load._nid ) {
- lca = stblk.idom(lca); // Raise Loads LCA
+ lca = stblk.domLCA(lca); // Raise Loads LCA
if( lca == stblk && st != null && Utils.find(st._inputs,load) == -1 ) // And if something moved,
st.addDef(load); // Add anti-dep as well
return lca; // Cap this stores' anti-dep to here
diff --git a/chapter11/src/main/java/com/seaofnodes/simple/node/CFGNode.java b/chapter11/src/main/java/com/seaofnodes/simple/node/CFGNode.java
index b605071b..e02dd1e1 100644
--- a/chapter11/src/main/java/com/seaofnodes/simple/node/CFGNode.java
+++ b/chapter11/src/main/java/com/seaofnodes/simple/node/CFGNode.java
@@ -48,18 +48,25 @@ public abstract class CFGNode extends Node {
* <p>
* See {@link <a href="https://en.wikipedia.org/wiki/Dominator_(graph_theory)">...</a>}
*/
- public int _idepth;
- public int idepth() { return _idepth==0 ? (_idepth=idom().idepth()+1) : _idepth; }
+ public char _idepth;
+ public int idepth() { return _idepth!=0 ? _idepth : cacheIDepth(idom().idepth()+1); }
+ // Zero depth means uncached. Check before narrowing so overflow cannot wrap.
+ final int cacheIDepth(int depth) {
+ assert 0 <= depth && depth <= Character.MAX_VALUE : "Dominator depth exceeds 65535";
+ return _idepth = (char)depth;
+ }
+
// Return the immediate dominator of this Node and compute dom tree depth.
public CFGNode idom() { return cfg(0); }
// Return the LCA of two idoms
- public CFGNode idom(CFGNode rhs) {
+ public CFGNode domLCA(CFGNode rhs) {
if( rhs==null ) return this;
CFGNode lhs = this;
while( lhs != rhs ) {
- var comp = lhs.idepth() - rhs.idepth();
+ if( lhs==null || rhs==null ) return null;
+ int comp = lhs.idepth() - rhs.idepth();
if( comp >= 0 ) lhs = lhs.idom();
if( comp <= 0 ) rhs = rhs.idom();
}
diff --git a/chapter11/src/main/java/com/seaofnodes/simple/node/LoopNode.java b/chapter11/src/main/java/com/seaofnodes/simple/node/LoopNode.java
index c662dee6..45549f1d 100644
--- a/chapter11/src/main/java/com/seaofnodes/simple/node/LoopNode.java
+++ b/chapter11/src/main/java/com/seaofnodes/simple/node/LoopNode.java
@@ -28,7 +28,7 @@ public class LoopNode extends RegionNode {
}
// Bypass Region idom, same as the default idom() using use in(1) instead of in(0)
- @Override public int idepth() { return _idepth==0 ? (_idepth=idom().idepth()+1) : _idepth; }
+ @Override public int idepth() { return _idepth!=0 ? _idepth : cacheIDepth(entry().idepth()+1); }
// Bypass Region idom, same as the default idom() using use in(1) instead of in(0)
@Override public CFGNode idom() { return entry(); }
diff --git a/chapter11/src/main/java/com/seaofnodes/simple/node/RegionNode.java b/chapter11/src/main/java/com/seaofnodes/simple/node/RegionNode.java
index dcc7ccef..060dfb45 100644
--- a/chapter11/src/main/java/com/seaofnodes/simple/node/RegionNode.java
+++ b/chapter11/src/main/java/com/seaofnodes/simple/node/RegionNode.java
@@ -92,19 +92,18 @@ public class RegionNode extends CFGNode {
// Immediate dominator of Region is a little more complicated.
@Override public int idepth() {
if( _idepth!=0 ) return _idepth;
- int d=0;
+ int depth=0;
for( Node n : _inputs )
if( n!=null )
- d = Math.max(d,((CFGNode)n).idepth()+1);
- return _idepth=d;
+ depth = Math.max(depth,((CFGNode)n).idepth()+1);
+ return cacheIDepth(depth);
}
@Override public CFGNode idom() {
CFGNode lca = null;
- // Walk the LHS & RHS idom trees in parallel until they match, or either fails.
- // Because this does not cache, it can be linear in the size of the program.
+ // Recompute from predecessors: CFG edits can change the dominator.
for( int i=1; i<nIns(); i++ )
- lca = cfg(i).idom(lca);
+ lca = cfg(i).domLCA(lca);
return lca;
}
diff --git a/chapter11/src/main/java/com/seaofnodes/simple/node/StopNode.java b/chapter11/src/main/java/com/seaofnodes/simple/node/StopNode.java
index 94b2ad6d..2bef4f50 100644
--- a/chapter11/src/main/java/com/seaofnodes/simple/node/StopNode.java
+++ b/chapter11/src/main/java/com/seaofnodes/simple/node/StopNode.java
@@ -57,7 +57,7 @@ public class StopNode extends CFGNode {
for( Node n : _inputs )
if( n!=null )
d = Math.max(d,((CFGNode)n).idepth()+1);
- return _idepth=d;
+ return cacheIDepth(d);
}
@Override public CFGNode idom() { return null; }