diff options
| author | Cliff Click <cliffc@acm.org> | 2025-05-04 13:25:38 -0700 |
|---|---|---|
| committer | Cliff Click <cliffc@acm.org> | 2025-05-04 13:25:38 -0700 |
| commit | 6afee244d59fc31ccdfa4e46dcc29c76b20e6e60 (patch) | |
| tree | 5dadeafd833743470ec2e3597f0950ff48d34e93 /chapter22/src/main/java | |
| parent | 2bedee089e65fa4d6a843e7497fc8bc5dc4be992 (diff) | |
| download | Simple-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')
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); } |
