summaryrefslogtreecommitdiff
path: root/chapter22/src/main/java/com
diff options
context:
space:
mode:
authorCliff Click <cliffc@acm.org>2025-05-04 13:25:38 -0700
committerCliff Click <cliffc@acm.org>2025-05-04 13:25:38 -0700
commit6afee244d59fc31ccdfa4e46dcc29c76b20e6e60 (patch)
tree5dadeafd833743470ec2e3597f0950ff48d34e93 /chapter22/src/main/java/com
parent2bedee089e65fa4d6a843e7497fc8bc5dc4be992 (diff)
downloadSimple-6afee244d59fc31ccdfa4e46dcc29c76b20e6e60.tar.gz
Simple-6afee244d59fc31ccdfa4e46dcc29c76b20e6e60.zip
Unwind back to 8b int/ptr.
GCM bug: unlinking a call shuffles StartNode output order, might miss a later unlink. RA bug spilling a constant to 2 different fixed stack slots. Turn off broken store-of-sign-extend check.
Diffstat (limited to 'chapter22/src/main/java/com')
-rw-r--r--chapter22/src/main/java/com/seaofnodes/simple/codegen/GlobalCodeMotion.java14
-rw-r--r--chapter22/src/main/java/com/seaofnodes/simple/codegen/RegAlloc.java13
-rw-r--r--chapter22/src/main/java/com/seaofnodes/simple/node/Node.java2
-rw-r--r--chapter22/src/main/java/com/seaofnodes/simple/node/StoreNode.java20
-rw-r--r--chapter22/src/main/java/com/seaofnodes/simple/node/cpus/riscv/MemOpRISC.java12
-rw-r--r--chapter22/src/main/java/com/seaofnodes/simple/sys/sys.smp14
-rw-r--r--chapter22/src/main/java/com/seaofnodes/simple/type/TypeMemPtr.java2
7 files changed, 50 insertions, 27 deletions
diff --git a/chapter22/src/main/java/com/seaofnodes/simple/codegen/GlobalCodeMotion.java b/chapter22/src/main/java/com/seaofnodes/simple/codegen/GlobalCodeMotion.java
index e904dc66..c05cfe2e 100644
--- a/chapter22/src/main/java/com/seaofnodes/simple/codegen/GlobalCodeMotion.java
+++ b/chapter22/src/main/java/com/seaofnodes/simple/codegen/GlobalCodeMotion.java
@@ -13,6 +13,19 @@ public abstract class GlobalCodeMotion {
// Node.use(0) is always a block tail (either IfNode or head of the
// following block). There are no unreachable infinite loops.
public static void buildCFG( CodeGen code ) {
+ // Unlink all linked calls. This can remove RPC constants which
+ // shuffled the StartNode outputs so requires a while loop.
+ boolean done=false;
+ while(!done) {
+ done = true;
+ for( Node use : code._start._outputs )
+ if( use instanceof FunNode fun )
+ for( Node c : fun._inputs )
+ if( c instanceof CallNode call )
+ { call.unlink_all(); done=false; }
+ }
+
+
Ary<CFGNode> rpo = new Ary<>(CFGNode.class);
_rpo_cfg(null, code._start, code.visit(), rpo);
// Reverse in-place
@@ -32,7 +45,6 @@ public abstract class GlobalCodeMotion {
// Post-Order of CFG
private static void _rpo_cfg(CFGNode def, Node use, BitSet visit, Ary<CFGNode> rpo) {
- if( use instanceof CallNode call ) call.unlink_all();
if( !(use instanceof CFGNode cfg) || visit.get(cfg._nid) )
return; // Been there, done that
if( def instanceof ReturnNode && use instanceof CallEndNode )
diff --git a/chapter22/src/main/java/com/seaofnodes/simple/codegen/RegAlloc.java b/chapter22/src/main/java/com/seaofnodes/simple/codegen/RegAlloc.java
index e1051fc6..e4a48750 100644
--- a/chapter22/src/main/java/com/seaofnodes/simple/codegen/RegAlloc.java
+++ b/chapter22/src/main/java/com/seaofnodes/simple/codegen/RegAlloc.java
@@ -285,7 +285,7 @@ public class RegAlloc {
// Split by class
for( RegMask rmask : rclass ) {
- Node split = makeSplit(def,"popular",round,lrg);
+ Node split = makeSplit(def,"popular",round,lrg,rmask);
split.insertAfter( def );
if( split.nIns()>1 ) split.setDef(1,def);
// all uses by class to split
@@ -491,15 +491,17 @@ public class RegAlloc {
Node def = n.in(i);
// Effective block for use
CFGNode cfg = n instanceof PhiNode phi ? phi.region().cfg(i) : n.cfg0();
+ // Use-side RegMask, if available
+ RegMask umask = n instanceof MachNode mach ? mach.regmap(i) : null;
// Def is a split ?
if( skip && def instanceof SplitNode ) {
- boolean singleReg = n instanceof MachNode mach && mach.regmap(i).size1();
+ boolean singleReg = umask!=null && umask.size1();
// Same block, multiple registers, split is only used by n,
// assume this is good enough and do not split again.
if( cfg==def.cfg0() && def.nOuts()==1 && !singleReg )
return;
}
- makeSplit(def,kind,round,lrg).insertBefore(n, i);
+ makeSplit(def,kind,round,lrg,umask).insertBefore(n, i);
// Skip split-of-split same block
if( skip && def instanceof SplitNode && cfg==def.cfg0() )
n.in(i).setDefOrdered(1,def.in(1));
@@ -526,8 +528,9 @@ public class RegAlloc {
}
}
- private Node makeSplit( Node def, String kind, byte round, LRG lrg ) {
- Node split = def instanceof MachNode mach && mach.isClone()
+ private Node makeSplit( Node def, String kind, byte round, LRG lrg, RegMask umask ) {
+ // Clone simple constants if possible
+ Node split = def instanceof MachNode mach && mach.isClone() && (umask==null || mach.outregmap().overlap(umask))
? mach.copy()
: _code._mach.split(kind,round,lrg);
_lrgs.put(split,lrg);
diff --git a/chapter22/src/main/java/com/seaofnodes/simple/node/Node.java b/chapter22/src/main/java/com/seaofnodes/simple/node/Node.java
index 18a8bc14..39010f3d 100644
--- a/chapter22/src/main/java/com/seaofnodes/simple/node/Node.java
+++ b/chapter22/src/main/java/com/seaofnodes/simple/node/Node.java
@@ -43,7 +43,7 @@ public abstract class Node implements Cloneable {
* walked in either direction. These outputs are typically used for
* efficient optimizations but otherwise have no semantics meaning.
*/
- public Ary<Node> _outputs;
+ public Ary<Node> _outputs;
/**
diff --git a/chapter22/src/main/java/com/seaofnodes/simple/node/StoreNode.java b/chapter22/src/main/java/com/seaofnodes/simple/node/StoreNode.java
index 87190f37..0beef65c 100644
--- a/chapter22/src/main/java/com/seaofnodes/simple/node/StoreNode.java
+++ b/chapter22/src/main/java/com/seaofnodes/simple/node/StoreNode.java
@@ -84,18 +84,14 @@ public class StoreNode extends MemOpNode {
}
}
- if( val() instanceof SarNode shr &&
- shr.in(1) instanceof ShlNode shl &&
- shr.in(2)._type.isConstant() &&
- shl.in(2)._type.isConstant() ) {
-
- ConstantNode shr_s = (ConstantNode)(shr.in(2));
- ConstantNode shl_s = (ConstantNode)(shl.in(2));
-
- if( shl_s._type == shr_s._type )
- //return setDef(3, shl.in(1));
- throw Utils.TODO();
- }
+ // TODO: Needs more love: the shift amount depends on the store size
+ //if( val() instanceof SarNode shr &&
+ // shr.in(1) instanceof ShlNode shl &&
+ // shr.in(2)._type.isConstant() &&
+ // shl.in(2)._type.isConstant() ) {
+ // if( shl.in(2)._type == shr.in(2)._type )
+ // return setDef(3, shl.in(1));
+ //}
return null;
}
diff --git a/chapter22/src/main/java/com/seaofnodes/simple/node/cpus/riscv/MemOpRISC.java b/chapter22/src/main/java/com/seaofnodes/simple/node/cpus/riscv/MemOpRISC.java
index 7f9b582a..8b84a2b9 100644
--- a/chapter22/src/main/java/com/seaofnodes/simple/node/cpus/riscv/MemOpRISC.java
+++ b/chapter22/src/main/java/com/seaofnodes/simple/node/cpus/riscv/MemOpRISC.java
@@ -35,8 +35,9 @@ public abstract class MemOpRISC extends MemOpNode implements MachNode {
if(this instanceof StoreRISC) {
if( _declaredType == TypeInteger. I8 || _declaredType == TypeInteger.U8 || _declaredType == TypeInteger.BOOL) func3=0; // SB
if( _declaredType == TypeInteger.I16 || _declaredType == TypeInteger.U16 ) func3=1; // SH
- if( _declaredType == TypeInteger.I32 || _declaredType == TypeInteger.U32 || _declaredType instanceof TypeMemPtr) func3=2; // SW
- if( _declaredType == TypeInteger.BOT ) func3=3; // SD
+ if( _declaredType == TypeInteger.I32 || _declaredType == TypeInteger.U32 ) func3=2; // SW
+ if( _declaredType instanceof TypeMemPtr) func3=3; // SD
+ if( _declaredType == TypeInteger.BOT ) func3=3; // SD
if( func3 == -1 ) throw Utils.TODO();
return func3;
}
@@ -50,9 +51,10 @@ public abstract class MemOpRISC extends MemOpNode implements MachNode {
if( _declaredType == TypeInteger.U32 ) func3=6; // LWU
// float
- if(_declaredType == TypeFloat.F32) func3 = 2; // fLW fSW
- if(_declaredType == TypeFloat.F64) func3 = 3; // fLD fSD
- if( _declaredType instanceof TypeMemPtr) func3 = 6; // 4 byte pointers(pick lw/u)
+ if( _declaredType == TypeFloat.F32) func3 = 2; // fLW fSW
+ if( _declaredType == TypeFloat.F64) func3 = 3; // fLD fSD
+
+ if( _declaredType instanceof TypeMemPtr) func3 = 3; // 8 byte pointers (pick ld)
if( func3 == -1 ) throw Utils.TODO();
return func3;
}
diff --git a/chapter22/src/main/java/com/seaofnodes/simple/sys/sys.smp b/chapter22/src/main/java/com/seaofnodes/simple/sys/sys.smp
index 64c1b93e..6b12ba20 100644
--- a/chapter22/src/main/java/com/seaofnodes/simple/sys/sys.smp
+++ b/chapter22/src/main/java/com/seaofnodes/simple/sys/sys.smp
@@ -3,8 +3,18 @@
// top-level default import
struct sys {
// libc bindings
+ /** https://www.man7.org/linux/man-pages/man2/<libc call>.2.html */
struct libc {
- /** https://www.man7.org/linux/man-pages/man2/write.2.html */
- { i32 u8[~] i32 -> i32 } write = "C";
+ // fd buf len -> len
+ { i32 u8[~] i32 -> i32 } write = "C";
+ // addr len prot flags fd off -> void*
+ { i64 i64 i32 i32 i32 i32 -> i64 } mmap = "C";
+ // mmap flags
+ i32 PROT_EXEC = 4;
+ i32 PROT_READ = 1;
+ i32 PROT_WRITE= 2;
+ i32 PROT_NONE = 0;
+ i32 MAP_PRIVATE = 2;
+ i32 MAP_ANON = 32;
};
};
diff --git a/chapter22/src/main/java/com/seaofnodes/simple/type/TypeMemPtr.java b/chapter22/src/main/java/com/seaofnodes/simple/type/TypeMemPtr.java
index 8c038f8e..78605e81 100644
--- a/chapter22/src/main/java/com/seaofnodes/simple/type/TypeMemPtr.java
+++ b/chapter22/src/main/java/com/seaofnodes/simple/type/TypeMemPtr.java
@@ -82,7 +82,7 @@ public class TypeMemPtr extends TypeNil {
// Is forward-reference
@Override public boolean isFRef() { return _obj.isFRef(); }
- @Override public int log_size() { return 2; } // (1<<3)==4-byte pointers
+ @Override public int log_size() { return 3; } // (1<<3)==8-byte pointers
@Override int hash() { return _obj.hashCode() ^ super.hash() ^ (_one ? 2048 : 0); }