diff options
Diffstat (limited to 'chapter21/src/main/java')
8 files changed, 72 insertions, 34 deletions
diff --git a/chapter21/src/main/java/com/seaofnodes/simple/node/Node.java b/chapter21/src/main/java/com/seaofnodes/simple/node/Node.java index e13b77a2..c02a4924 100644 --- a/chapter21/src/main/java/com/seaofnodes/simple/node/Node.java +++ b/chapter21/src/main/java/com/seaofnodes/simple/node/Node.java @@ -16,14 +16,14 @@ import static com.seaofnodes.simple.codegen.CodeGen.CODE; * The Node class provides common functionality used by all subtypes. * Subtypes of Node specialize by overriding methods. */ -public abstract class Node { +public abstract class Node implements Cloneable { /** * Each node has a unique dense Node ID within a compilation context * The ID is useful for debugging, for using as an offset in a bitvector, * as well as for computing equality of nodes (to be implemented later). */ - public final int _nid; + public int _nid; /** * Inputs to the node. These are use-def references to Nodes. @@ -32,7 +32,7 @@ public abstract class Node { * Ordering is required because e.g. "a/b" is different from "b/a". * The first input (offset 0) is often a {@link CFGNode} node. */ - public final Ary<Node> _inputs; + public Ary<Node> _inputs; /** * Outputs reference Nodes that are not null and have this Node as an @@ -43,7 +43,7 @@ public abstract class Node { * walked in either direction. These outputs are typically used for * efficient optimizations but otherwise have no semantics meaning. */ - public final Ary<Node> _outputs; + public Ary<Node> _outputs; /** @@ -679,6 +679,18 @@ public abstract class Node { // Does not need to be implemented in isCFG() nodes. Node copy(Node lhs, Node rhs) { throw Utils.TODO("Binary ops need to implement copy"); } + public Node copy() { + Node n; + try { n = (Node)clone(); } + catch( Exception e ) { throw new RuntimeException(e); } + n._nid = CODE.getUID(); // allocate unique dense ID + n._inputs = new Ary<>(Node.class); + n._outputs = new Ary<>(Node.class); + n._deps = null; + n._hash = 0; + return n; + } + // Report any post-optimize errors public Parser.ParseException err() { return null; } diff --git a/chapter21/src/main/java/com/seaofnodes/simple/node/PhiNode.java b/chapter21/src/main/java/com/seaofnodes/simple/node/PhiNode.java index f66e7ad4..be31dd38 100644 --- a/chapter21/src/main/java/com/seaofnodes/simple/node/PhiNode.java +++ b/chapter21/src/main/java/com/seaofnodes/simple/node/PhiNode.java @@ -80,31 +80,38 @@ public class PhiNode extends Node { if( r.in(i)._type == Type.XCONTROL ) return null; - // Pull "down" a common data op. One less op in the world. One more - // Phi, but Phis do not make code. - // Phi(op(A,B),op(Q,R),op(X,Y)) becomes - // op(Phi(A,Q,X), Phi(B,R,Y)). + // Generic "pull down op" Node op = in(1); - if( !isMem() && op.nIns()==3 && op.in(0)==null && same_op() ) { + if( same_op() ) { assert !(op instanceof CFGNode); - Node[] lhss = new Node[nIns()]; - Node[] rhss = new Node[nIns()]; - lhss[0] = rhss[0] = in(0); // Set Region - for( int i=1; i<nIns(); i++ ) { - lhss[i] = in(i).in(1); - rhss[i] = in(i).in(2); + boolean solo=true; + for( int i=1; i<nIns(); i++ ) + if( in(i).nOuts() > 1 || in(i).in(0)!=null ) + { solo=false; break; } + if( solo ) { + Node cp = op.copy(); + cp.addDef(null); // No control + + for( int j=1; j<op.nIns(); j++ ) { + boolean needsPhi = false; + Node x = op.in(j); // Jth input from sample #1 + for( int i=2; i<nIns(); i++ ) + if( in(i).in(j) != x ) + { needsPhi=true; break; } + if( needsPhi ) { + x = new PhiNode(_label,op.in(j)._type.glb()); + x.addDef(region()); + for( int i=1; i<nIns(); i++ ) + x.addDef(in(i).in(j)); + x = x.peephole(); + } + cp.addDef(x); + } + // Test not running backwards, which can happen for e.g. And's + if( cp.compute().isa(compute()) ) + return cp; + cp.kill(); } - Node phi_lhs = new PhiNode(_label, _declaredType,lhss).peephole(); - Node phi_rhs = new PhiNode(_label, _declaredType,rhss).peephole(); - Node down = op.copy(phi_lhs,phi_rhs); - // Test not running backwards, which can happen for e.g. And's - if( down.compute().isa(compute()) ) - return down; - in(1).in(1).addDep(this); - in(1).in(2).addDep(this); - in(2).in(1).addDep(this); - in(2).in(2).addDep(this); - down.kill(); } // If merging Phi(N, cast(N)) - we are losing the cast JOIN effects, so just remove. diff --git a/chapter21/src/main/java/com/seaofnodes/simple/node/StoreNode.java b/chapter21/src/main/java/com/seaofnodes/simple/node/StoreNode.java index 7f43f53c..e8f5c4e2 100644 --- a/chapter21/src/main/java/com/seaofnodes/simple/node/StoreNode.java +++ b/chapter21/src/main/java/com/seaofnodes/simple/node/StoreNode.java @@ -84,7 +84,6 @@ public class StoreNode extends MemOpNode { } } - return null; } diff --git a/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/arm/CastARM.java b/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/arm/CastARM.java new file mode 100644 index 00000000..a5a4e112 --- /dev/null +++ b/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/arm/CastARM.java @@ -0,0 +1,18 @@ +package com.seaofnodes.simple.node.cpus.arm; + +import com.seaofnodes.simple.SB; +import com.seaofnodes.simple.codegen.CodeGen; +import com.seaofnodes.simple.codegen.Encoding; +import com.seaofnodes.simple.codegen.RegMask; +import com.seaofnodes.simple.node.CastNode; +import com.seaofnodes.simple.node.MachNode; + +public class CastARM extends CastNode implements MachNode { + public CastARM( CastNode cast ) { super(cast); } + @Override public String op() { return label(); } + @Override public RegMask regmap(int i) { assert i==1; return RegMask.FULL; } + @Override public RegMask outregmap() { return RegMask.FULL; } + @Override public int twoAddress( ) { return 1; } + @Override public void encoding( Encoding enc ) { } + @Override public void asm(CodeGen code, SB sb) { _t.print(sb.p(code.reg(in(1))).p(" isa ")); } +} diff --git a/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/arm/IntARM.java b/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/arm/IntARM.java index 8affb4c6..0a07b07a 100644 --- a/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/arm/IntARM.java +++ b/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/arm/IntARM.java @@ -4,6 +4,7 @@ import com.seaofnodes.simple.*; import com.seaofnodes.simple.codegen.*; import com.seaofnodes.simple.node.ConstantNode; import com.seaofnodes.simple.node.MachNode; +import com.seaofnodes.simple.type.Type; import com.seaofnodes.simple.type.TypeInteger; // Integer constants @@ -19,7 +20,7 @@ public class IntARM extends ConstantNode implements MachNode { @Override public void encoding( Encoding enc ) { short self = enc.reg(this); - long x = ((TypeInteger)_con).value(); + long x = _con==Type.NIL ? 0 : ((TypeInteger)_con).value(); int nb0 = 0; int nb1 = 0; // Count number of 0000 and FFFF blocks diff --git a/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/arm/arm.java b/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/arm/arm.java index 0aea0ae9..bedda4e2 100644 --- a/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/arm/arm.java +++ b/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/arm/arm.java @@ -620,7 +620,7 @@ public class arm extends Machine { case AndNode and -> and(and); case BoolNode bool -> cmp(bool); case CallNode call -> call(call); - case CastNode cast -> new CastNode(cast); + case CastNode cast -> new CastARM(cast); case CallEndNode cend -> new CallEndARM(cend); case CProjNode c -> new CProjNode(c); case ConstantNode con -> con(con); @@ -696,7 +696,7 @@ public class arm extends Machine { : new SubARM(sub); } - private Node con(ConstantNode con) { + private Node con( ConstantNode con ) { if( !con._con.isConstant() ) return new ConstantNode( con ); // Default unknown caller inputs return switch( con._con ) { case TypeInteger ti -> new IntARM(con); @@ -705,7 +705,7 @@ public class arm extends Machine { case TypeMemPtr tmp -> new ConstantNode(con); case TypeNil tn -> throw Utils.TODO(); // TOP, BOTTOM, XCtrl, Ctrl, etc. Never any executable code. - case Type t -> new ConstantNode(con); + case Type t -> t==Type.NIL ? new IntARM(con) : new ConstantNode(con); }; } diff --git a/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/riscv/IntRISC.java b/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/riscv/IntRISC.java index 764c49e6..70d5c18f 100644 --- a/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/riscv/IntRISC.java +++ b/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/riscv/IntRISC.java @@ -4,6 +4,7 @@ import com.seaofnodes.simple.*; import com.seaofnodes.simple.codegen.*; import com.seaofnodes.simple.node.ConstantNode; import com.seaofnodes.simple.node.MachNode; +import com.seaofnodes.simple.type.Type; import com.seaofnodes.simple.type.TypeInteger; // 12-bit integer constant. Larger constants are made up in the instruction @@ -17,10 +18,10 @@ public class IntRISC extends ConstantNode implements MachNode { @Override public IntRISC copy() { return new IntRISC(this); } @Override public void encoding( Encoding enc ) { short dst = enc.reg(this); - TypeInteger ti = (TypeInteger)_con; + int val = _con==Type.NIL ? 0 : (int)(((TypeInteger)_con).value() & 0xFFF); // Explicit truncation of larger immediates; this will sign-extend on // load and this is handled during instruction selection. - enc.add4(riscv.i_type(riscv.OP_IMM, dst, 0, riscv.ZERO, (int)(ti.value() & 0xFFF))); + enc.add4(riscv.i_type(riscv.OP_IMM, dst, 0, riscv.ZERO, val)); } @Override public void asm(CodeGen code, SB sb) { String reg = code.reg(this); diff --git a/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/x86_64_v2.java b/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/x86_64_v2.java index b4c382c5..12b3a12c 100644 --- a/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/x86_64_v2.java +++ b/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/x86_64_v2.java @@ -573,7 +573,7 @@ public class x86_64_v2 extends Machine { return new CmpX86(bool); } - private Node con(ConstantNode con) { + private Node con( ConstantNode con ) { if(!con._con.isConstant()) return new ConstantNode(con); // Default unknown caller inputs return switch (con._con) { case TypeInteger ti -> new IntX86(con); |
