summaryrefslogtreecommitdiff
path: root/src/main/java/com/seaofnodes/simple/node
diff options
context:
space:
mode:
authorCliff Click <cliffc@acm.org>2024-07-17 18:11:56 +0100
committerCliff Click <cliffc@acm.org>2024-10-23 17:51:09 -0700
commita080ea0774887141c26e38e57355e5520c49396a (patch)
treef88ffba2da6c662ddc5f245ca1e364d1128f787f /src/main/java/com/seaofnodes/simple/node
parentdc77490c735104497851ed8c12ae5c713ab05b04 (diff)
downloadSimple-linear-chapter12.tar.gz
Simple-linear-chapter12.zip
Chapter 12: Floatslinear-chapter12
Co-authored-by: Dibyendu Majumdar <mobile@majumdar.org.uk> Co-authored-by: Thalia Archibald <thalia@archibald.dev> Co-authored-by: XmiliaH <45106915+XmiliaH@users.noreply.github.com> Co-authored-by: Robert Obkircher <robert.obkircher@gmail.com>
Diffstat (limited to 'src/main/java/com/seaofnodes/simple/node')
-rw-r--r--src/main/java/com/seaofnodes/simple/node/AddFNode.java44
-rw-r--r--src/main/java/com/seaofnodes/simple/node/AddNode.java2
-rw-r--r--src/main/java/com/seaofnodes/simple/node/BoolNode.java31
-rw-r--r--src/main/java/com/seaofnodes/simple/node/CFGNode.java9
-rw-r--r--src/main/java/com/seaofnodes/simple/node/DivFNode.java46
-rw-r--r--src/main/java/com/seaofnodes/simple/node/DivNode.java1
-rw-r--r--src/main/java/com/seaofnodes/simple/node/LoadNode.java10
-rw-r--r--src/main/java/com/seaofnodes/simple/node/LoopNode.java9
-rw-r--r--src/main/java/com/seaofnodes/simple/node/MinusFNode.java36
-rw-r--r--src/main/java/com/seaofnodes/simple/node/MinusNode.java1
-rw-r--r--src/main/java/com/seaofnodes/simple/node/MulFNode.java51
-rw-r--r--src/main/java/com/seaofnodes/simple/node/MulNode.java1
-rw-r--r--src/main/java/com/seaofnodes/simple/node/MultiNode.java8
-rw-r--r--src/main/java/com/seaofnodes/simple/node/NeverNode.java4
-rw-r--r--src/main/java/com/seaofnodes/simple/node/Node.java24
-rw-r--r--src/main/java/com/seaofnodes/simple/node/NotNode.java4
-rw-r--r--src/main/java/com/seaofnodes/simple/node/PhiNode.java4
-rw-r--r--src/main/java/com/seaofnodes/simple/node/RegionNode.java4
-rw-r--r--src/main/java/com/seaofnodes/simple/node/StartNode.java2
-rw-r--r--src/main/java/com/seaofnodes/simple/node/StopNode.java2
-rw-r--r--src/main/java/com/seaofnodes/simple/node/SubFNode.java44
-rw-r--r--src/main/java/com/seaofnodes/simple/node/SubNode.java2
-rw-r--r--src/main/java/com/seaofnodes/simple/node/ToFloatNode.java30
23 files changed, 340 insertions, 29 deletions
diff --git a/src/main/java/com/seaofnodes/simple/node/AddFNode.java b/src/main/java/com/seaofnodes/simple/node/AddFNode.java
new file mode 100644
index 00000000..e5a2440c
--- /dev/null
+++ b/src/main/java/com/seaofnodes/simple/node/AddFNode.java
@@ -0,0 +1,44 @@
+package com.seaofnodes.simple.node;
+
+import com.seaofnodes.simple.type.Type;
+import com.seaofnodes.simple.type.TypeFloat;
+
+import java.util.BitSet;
+
+public class AddFNode extends Node {
+ public AddFNode(Node lhs, Node rhs) { super(null, lhs, rhs); }
+
+ @Override public String label() { return "AddF"; }
+
+ @Override public String glabel() { return "+"; }
+
+ @Override
+ StringBuilder _print1(StringBuilder sb, BitSet visited) {
+ in(1)._print0(sb.append("("), visited);
+ in(2)._print0(sb.append("+"), visited);
+ return sb.append(")");
+ }
+
+ @Override
+ public Type compute() {
+ if (in(1)._type instanceof TypeFloat i0 &&
+ in(2)._type instanceof TypeFloat i1) {
+ if (i0.isConstant() && i1.isConstant())
+ return TypeFloat.constant(i0.value()+i1.value());
+ }
+ return in(1)._type.meet(in(2)._type);
+ }
+
+ @Override
+ public Node idealize() {
+ Node lhs = in(1);
+ Type t2 = in(2)._type;
+
+ // Add of 1.
+ if ( t2.isConstant() && t2 instanceof TypeFloat i && i.value()==0 )
+ return lhs;
+
+ return null;
+ }
+ @Override Node copy(Node lhs, Node rhs) { return new AddFNode(lhs,rhs); }
+}
diff --git a/src/main/java/com/seaofnodes/simple/node/AddNode.java b/src/main/java/com/seaofnodes/simple/node/AddNode.java
index 2cc0b465..48350957 100644
--- a/src/main/java/com/seaofnodes/simple/node/AddNode.java
+++ b/src/main/java/com/seaofnodes/simple/node/AddNode.java
@@ -106,6 +106,7 @@ public class AddNode extends Node {
static Node phiCon(Node op, boolean rotate) {
Node lhs = op.in(1);
Node rhs = op.in(2);
+ if( rhs._type==TypeInteger.TOP ) return null;
// LHS is either a Phi of constants, or another op with Phi of constants
PhiNode lphi = pcon(lhs,op);
if( rotate && lphi==null && lhs.nIns() > 2 ) {
@@ -171,4 +172,5 @@ public class AddNode extends Node {
}
@Override Node copy(Node lhs, Node rhs) { return new AddNode(lhs,rhs); }
+ @Override Node copyF() { return new AddFNode(null,null); }
}
diff --git a/src/main/java/com/seaofnodes/simple/node/BoolNode.java b/src/main/java/com/seaofnodes/simple/node/BoolNode.java
index 9c15f01b..48faefd2 100644
--- a/src/main/java/com/seaofnodes/simple/node/BoolNode.java
+++ b/src/main/java/com/seaofnodes/simple/node/BoolNode.java
@@ -1,7 +1,10 @@
package com.seaofnodes.simple.node;
+import com.seaofnodes.simple.Parser;
+import com.seaofnodes.simple.Utils;
import com.seaofnodes.simple.type.Type;
import com.seaofnodes.simple.type.TypeInteger;
+import com.seaofnodes.simple.type.TypeFloat;
import com.seaofnodes.simple.type.TypeMemPtr;
import java.util.BitSet;
@@ -34,10 +37,17 @@ abstract public class BoolNode extends Node {
if (i0.isConstant() && i1.isConstant())
return TypeInteger.constant(doOp(i0.value(), i1.value()) ? 1 : 0);
}
- return in(1)._type.meet(in(2)._type);
+ if( in(1)._type instanceof TypeFloat i0 &&
+ in(2)._type instanceof TypeFloat i1 ) {
+ if (i0.isConstant() && i1.isConstant())
+ return TypeInteger.constant(doOp(i0.value(), i1.value()) ? 1 : 0);
+ }
+ return TypeInteger.BOT;
}
- abstract boolean doOp(long lhs, long rhs);
+ boolean doOp(long lhs, long rhs) { throw Utils.TODO(); }
+ boolean doOp(double lhs, double rhs) { throw Utils.TODO(); }
+ Node copyF(Node lhs, Node rhs) { throw Utils.TODO(); }
@Override
public Node idealize() {
@@ -49,11 +59,9 @@ abstract public class BoolNode extends Node {
if( this instanceof EQ ) {
if( !(in(2) instanceof ConstantNode) ) {
// con==noncon becomes noncon==con
- if( in(1) instanceof ConstantNode )
- return new EQ(in(2),in(1));
+ if( in(1) instanceof ConstantNode || in(1)._nid > in(2)._nid )
// Equals sorts by NID otherwise: non.high == non.low becomes non.low == non.high
- else if( in(1)._nid > in(2)._nid )
- return new EQ(in(2),in(1));
+ return in(1)._type instanceof TypeFloat ? new EQF(in(2),in(1)) : new EQ(in(2),in(1));
}
// Equals X==0 becomes a !X
if( (in(2)._type == TypeInteger.ZERO || in(2)._type == TypeMemPtr.NULLPTR) )
@@ -69,7 +77,12 @@ abstract public class BoolNode extends Node {
return null;
}
- public static class EQ extends BoolNode { public EQ(Node lhs, Node rhs) { super(lhs,rhs); } String op() { return "=="; } boolean doOp(long lhs, long rhs) { return lhs == rhs; } Node copy(Node lhs, Node rhs) { return new EQ(lhs,rhs); } }
- public static class LT extends BoolNode { public LT(Node lhs, Node rhs) { super(lhs,rhs); } String op() { return "<" ; } boolean doOp(long lhs, long rhs) { return lhs < rhs; } Node copy(Node lhs, Node rhs) { return new LT(lhs,rhs); } }
- public static class LE extends BoolNode { public LE(Node lhs, Node rhs) { super(lhs,rhs); } String op() { return "<="; } boolean doOp(long lhs, long rhs) { return lhs <= rhs; } Node copy(Node lhs, Node rhs) { return new LE(lhs,rhs); } }
+ public static class EQ extends BoolNode { public EQ(Node lhs, Node rhs) { super(lhs,rhs); } String op() { return "=="; } boolean doOp(long lhs, long rhs) { return lhs == rhs; } Node copy(Node lhs, Node rhs) { return new EQ(lhs,rhs); } Node copyF() { return new EQF(null,null); } }
+ public static class LT extends BoolNode { public LT(Node lhs, Node rhs) { super(lhs,rhs); } String op() { return "<" ; } boolean doOp(long lhs, long rhs) { return lhs < rhs; } Node copy(Node lhs, Node rhs) { return new LT(lhs,rhs); } Node copyF() { return new LTF(null,null); }}
+ public static class LE extends BoolNode { public LE(Node lhs, Node rhs) { super(lhs,rhs); } String op() { return "<="; } boolean doOp(long lhs, long rhs) { return lhs <= rhs; } Node copy(Node lhs, Node rhs) { return new LE(lhs,rhs); } Node copyF() { return new LEF(null,null); } }
+
+ public static class EQF extends EQ { public EQF(Node lhs, Node rhs) { super(lhs,rhs); } boolean doOp(double lhs, double rhs) { return lhs == rhs; } Node copyF() { return null; } }
+ public static class LTF extends LT { public LTF(Node lhs, Node rhs) { super(lhs,rhs); } boolean doOp(double lhs, double rhs) { return lhs < rhs; } Node copyF() { return null; } }
+ public static class LEF extends LE { public LEF(Node lhs, Node rhs) { super(lhs,rhs); } boolean doOp(double lhs, double rhs) { return lhs <= rhs; } Node copyF() { return null; } }
+
}
diff --git a/src/main/java/com/seaofnodes/simple/node/CFGNode.java b/src/main/java/com/seaofnodes/simple/node/CFGNode.java
index b605071b..07ba0fa4 100644
--- a/src/main/java/com/seaofnodes/simple/node/CFGNode.java
+++ b/src/main/java/com/seaofnodes/simple/node/CFGNode.java
@@ -52,16 +52,17 @@ public abstract class CFGNode extends Node {
public int idepth() { return _idepth==0 ? (_idepth=idom().idepth()+1) : _idepth; }
// Return the immediate dominator of this Node and compute dom tree depth.
- public CFGNode idom() { return cfg(0); }
+ public CFGNode idom(Node dep) { return cfg(0); }
+ public final CFGNode idom() { return idom(null); }
// Return the LCA of two idoms
- public CFGNode idom(CFGNode rhs) {
+ public CFGNode _idom(CFGNode rhs, Node dep) {
if( rhs==null ) return this;
CFGNode lhs = this;
while( lhs != rhs ) {
var comp = lhs.idepth() - rhs.idepth();
- if( comp >= 0 ) lhs = lhs.idom();
- if( comp <= 0 ) rhs = rhs.idom();
+ if( comp >= 0 ) lhs = ((CFGNode)lhs.addDep(dep)).idom();
+ if( comp <= 0 ) rhs = ((CFGNode)rhs.addDep(dep)).idom();
}
return lhs;
}
diff --git a/src/main/java/com/seaofnodes/simple/node/DivFNode.java b/src/main/java/com/seaofnodes/simple/node/DivFNode.java
new file mode 100644
index 00000000..36fd4524
--- /dev/null
+++ b/src/main/java/com/seaofnodes/simple/node/DivFNode.java
@@ -0,0 +1,46 @@
+package com.seaofnodes.simple.node;
+
+import com.seaofnodes.simple.type.Type;
+import com.seaofnodes.simple.type.TypeFloat;
+
+import java.util.BitSet;
+
+public class DivFNode extends Node {
+ public DivFNode(Node lhs, Node rhs) { super(null, lhs, rhs); }
+
+ @Override public String label() { return "DivF"; }
+
+ @Override public String glabel() { return "/"; }
+
+ @Override
+ StringBuilder _print1(StringBuilder sb, BitSet visited) {
+ in(1)._print0(sb.append("("), visited);
+ in(2)._print0(sb.append("/"), visited);
+ return sb.append(")");
+ }
+
+ @Override
+ public Type compute() {
+ if (in(1)._type instanceof TypeFloat i0 &&
+ in(2)._type instanceof TypeFloat i1) {
+ if (i0.isConstant() && i1.isConstant())
+ return TypeFloat.constant(i0.value()/i1.value());
+ }
+ return in(1)._type.meet(in(2)._type);
+ }
+
+ @Override
+ public Node idealize() {
+ Node lhs = in(1);
+ Node rhs = in(2);
+ Type t1 = lhs._type;
+ Type t2 = rhs._type;
+
+ // Div of 1.
+ if ( t2.isConstant() && t2 instanceof TypeFloat i && i.value()==1 )
+ return lhs;
+
+ return null;
+ }
+ @Override Node copy(Node lhs, Node rhs) { return new DivFNode(lhs,rhs); }
+}
diff --git a/src/main/java/com/seaofnodes/simple/node/DivNode.java b/src/main/java/com/seaofnodes/simple/node/DivNode.java
index 08ce70b8..e0c95019 100644
--- a/src/main/java/com/seaofnodes/simple/node/DivNode.java
+++ b/src/main/java/com/seaofnodes/simple/node/DivNode.java
@@ -40,4 +40,5 @@ public class DivNode extends Node {
}
@Override Node copy(Node lhs, Node rhs) { return new DivNode(lhs,rhs); }
+ @Override Node copyF() { return new DivFNode(null,null); }
}
diff --git a/src/main/java/com/seaofnodes/simple/node/LoadNode.java b/src/main/java/com/seaofnodes/simple/node/LoadNode.java
index 296237f4..244a0919 100644
--- a/src/main/java/com/seaofnodes/simple/node/LoadNode.java
+++ b/src/main/java/com/seaofnodes/simple/node/LoadNode.java
@@ -61,9 +61,13 @@ public class LoadNode extends MemOpNode {
if( profit(memphi,2) ||
// Else must not be a loop to count profit on LHS.
(!(memphi.region() instanceof LoopNode) && profit(memphi,1)) ) {
- Node ld1 = new LoadNode(_name,_alias,_declaredType,memphi.in(1),ptr()).peephole();
- Node ld2 = new LoadNode(_name,_alias,_declaredType,memphi.in(2),ptr()).peephole();
- return new PhiNode(_name,_type,memphi.region(),ld1,ld2);
+ if( ptr() instanceof NewNode || !(ptr() instanceof CastNode) ) {
+ if( !(ptr() instanceof NewNode) ) throw Utils.TODO(); // Validate
+
+ Node ld1 = new LoadNode(_name,_alias,_declaredType,memphi.in(1),ptr()).peephole();
+ Node ld2 = new LoadNode(_name,_alias,_declaredType,memphi.in(2),ptr()).peephole();
+ return new PhiNode(_name,_type,memphi.region(),ld1,ld2);
+ }
}
}
diff --git a/src/main/java/com/seaofnodes/simple/node/LoopNode.java b/src/main/java/com/seaofnodes/simple/node/LoopNode.java
index c662dee6..22862cb9 100644
--- a/src/main/java/com/seaofnodes/simple/node/LoopNode.java
+++ b/src/main/java/com/seaofnodes/simple/node/LoopNode.java
@@ -30,7 +30,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; }
// Bypass Region idom, same as the default idom() using use in(1) instead of in(0)
- @Override public CFGNode idom() { return entry(); }
+ @Override public CFGNode idom(Node dep) { return entry(); }
@Override public int loopDepth() {
if( _loopDepth!=0 ) return _loopDepth; // Was already set
@@ -60,8 +60,11 @@ public class LoopNode extends RegionNode {
// directly on the If) we found our exit.
CFGNode x = back();
while( x != this ) {
- if( x instanceof CProjNode exit )
- return; // Found an exit, not an infinite loop
+ if( x instanceof CProjNode exit && exit.in(0) instanceof IfNode iff ) {
+ Node other = iff.cproj(1-exit._idx);
+ if( !(other.out(0) instanceof LoopNode loop) || loop.entry()==exit )
+ return; // Found an exit, not an infinite loop
+ }
x = x.idom();
}
// Found a no-exit loop. Insert an exit
diff --git a/src/main/java/com/seaofnodes/simple/node/MinusFNode.java b/src/main/java/com/seaofnodes/simple/node/MinusFNode.java
new file mode 100644
index 00000000..9727f58b
--- /dev/null
+++ b/src/main/java/com/seaofnodes/simple/node/MinusFNode.java
@@ -0,0 +1,36 @@
+package com.seaofnodes.simple.node;
+
+import com.seaofnodes.simple.type.Type;
+import com.seaofnodes.simple.type.TypeFloat;
+
+import java.util.BitSet;
+
+public class MinusFNode extends Node {
+ public MinusFNode(Node in) { super(null, in); }
+
+ @Override public String label() { return "MinusF"; }
+
+ @Override public String glabel() { return "-"; }
+
+ @Override
+ StringBuilder _print1(StringBuilder sb, BitSet visited) {
+ in(1)._print0(sb.append("(-"), visited);
+ return sb.append(")");
+ }
+
+ @Override
+ public Type compute() {
+ if (in(1)._type instanceof TypeFloat i0)
+ return i0.isConstant() ? TypeFloat.constant(-i0.value()) : i0;
+ return TypeFloat.BOT;
+ }
+
+ @Override
+ public Node idealize() {
+ // -(-x) is x
+ if( in(1) instanceof MinusFNode minus )
+ return minus.in(1);
+
+ return null;
+ }
+}
diff --git a/src/main/java/com/seaofnodes/simple/node/MinusNode.java b/src/main/java/com/seaofnodes/simple/node/MinusNode.java
index 9b687613..ae8e9e1b 100644
--- a/src/main/java/com/seaofnodes/simple/node/MinusNode.java
+++ b/src/main/java/com/seaofnodes/simple/node/MinusNode.java
@@ -33,4 +33,5 @@ public class MinusNode extends Node {
return null;
}
+ @Override Node copyF() { return new MinusFNode(null); }
}
diff --git a/src/main/java/com/seaofnodes/simple/node/MulFNode.java b/src/main/java/com/seaofnodes/simple/node/MulFNode.java
new file mode 100644
index 00000000..2d44a9fb
--- /dev/null
+++ b/src/main/java/com/seaofnodes/simple/node/MulFNode.java
@@ -0,0 +1,51 @@
+package com.seaofnodes.simple.node;
+
+import com.seaofnodes.simple.type.Type;
+import com.seaofnodes.simple.type.TypeFloat;
+
+import java.util.BitSet;
+
+public class MulFNode extends Node {
+ public MulFNode(Node lhs, Node rhs) { super(null, lhs, rhs); }
+
+ @Override public String label() { return "MulF"; }
+
+ @Override public String glabel() { return "*"; }
+
+ @Override
+ StringBuilder _print1(StringBuilder sb, BitSet visited) {
+ in(1)._print0(sb.append("("), visited);
+ in(2)._print0(sb.append("*"), visited);
+ return sb.append(")");
+ }
+
+ @Override
+ public Type compute() {
+ if (in(1)._type instanceof TypeFloat i0 &&
+ in(2)._type instanceof TypeFloat i1) {
+ if (i0.isConstant() && i1.isConstant())
+ return TypeFloat.constant(i0.value()*i1.value());
+ }
+ return in(1)._type.meet(in(2)._type);
+ }
+
+ @Override
+ public Node idealize() {
+ Node lhs = in(1);
+ Node rhs = in(2);
+ Type t1 = lhs._type;
+ Type t2 = rhs._type;
+
+ // Mul of 1. We do not check for (1*x) because this will already
+ // canonicalize to (x*1)
+ if ( t2.isConstant() && t2 instanceof TypeFloat i && i.value()==1 )
+ return lhs;
+
+ // Move constants to RHS: con*arg becomes arg*con
+ if ( t1.isConstant() && !t2.isConstant() )
+ return swap12();
+
+ return null;
+ }
+ @Override Node copy(Node lhs, Node rhs) { return new MulFNode(lhs,rhs); }
+}
diff --git a/src/main/java/com/seaofnodes/simple/node/MulNode.java b/src/main/java/com/seaofnodes/simple/node/MulNode.java
index 7e9f88a2..8c8a6e0a 100644
--- a/src/main/java/com/seaofnodes/simple/node/MulNode.java
+++ b/src/main/java/com/seaofnodes/simple/node/MulNode.java
@@ -54,4 +54,5 @@ public class MulNode extends Node {
return null;
}
@Override Node copy(Node lhs, Node rhs) { return new MulNode(lhs,rhs); }
+ @Override Node copyF() { return new MulFNode(null,null); }
}
diff --git a/src/main/java/com/seaofnodes/simple/node/MultiNode.java b/src/main/java/com/seaofnodes/simple/node/MultiNode.java
index 379e140d..ac9c0045 100644
--- a/src/main/java/com/seaofnodes/simple/node/MultiNode.java
+++ b/src/main/java/com/seaofnodes/simple/node/MultiNode.java
@@ -9,4 +9,12 @@ public interface MultiNode extends OutNode {
return prj;
return null;
}
+
+ // Find a projection by index
+ default CProjNode cproj( int idx ) {
+ for( Node out : outs() )
+ if( out instanceof CProjNode prj && prj._idx==idx )
+ return prj;
+ return null;
+ }
}
diff --git a/src/main/java/com/seaofnodes/simple/node/NeverNode.java b/src/main/java/com/seaofnodes/simple/node/NeverNode.java
index f50d3503..e77ed653 100644
--- a/src/main/java/com/seaofnodes/simple/node/NeverNode.java
+++ b/src/main/java/com/seaofnodes/simple/node/NeverNode.java
@@ -3,6 +3,8 @@ package com.seaofnodes.simple.node;
import com.seaofnodes.simple.Parser;
import com.seaofnodes.simple.type.TypeInteger;
import com.seaofnodes.simple.type.Type;
+import com.seaofnodes.simple.type.TypeTuple;
+
import java.util.BitSet;
// "Never true" for infinite loop exits
@@ -13,7 +15,7 @@ public class NeverNode extends IfNode {
@Override StringBuilder _print1(StringBuilder sb, BitSet visited) { return sb.append("Never"); }
- @Override public Type compute() { return TypeInteger.BOT; }
+ @Override public Type compute() { return TypeTuple.IF_BOTH; }
@Override public Node idealize() { return null; }
}
diff --git a/src/main/java/com/seaofnodes/simple/node/Node.java b/src/main/java/com/seaofnodes/simple/node/Node.java
index fc49ad6a..52282737 100644
--- a/src/main/java/com/seaofnodes/simple/node/Node.java
+++ b/src/main/java/com/seaofnodes/simple/node/Node.java
@@ -1,10 +1,10 @@
package com.seaofnodes.simple.node;
import com.seaofnodes.simple.IRPrinter;
-import com.seaofnodes.simple.Parser;
import com.seaofnodes.simple.IterPeeps;
import com.seaofnodes.simple.Utils;
import com.seaofnodes.simple.type.Type;
+import com.seaofnodes.simple.type.TypeFloat;
import java.util.*;
import java.util.function.Function;
@@ -236,6 +236,7 @@ public abstract class Node implements OutNode {
*/
public void kill( ) {
unlock();
+ moveDepsToWorklist();
assert isUnused(); // Has no uses, so it is dead
_type=null; // Flag as dead
while( nIns()>0 ) { // Set all inputs to null, recursively killing unused Nodes
@@ -546,6 +547,27 @@ public abstract class Node implements OutNode {
/** Pinned in the schedule */
public boolean isPinned() { return false; }
+ // Semantic change to the graph (so NOT a peephole), used by the Parser.
+ // If any input is a float, flip to a float-flavored opcode and widen any
+ // non-float input.
+ public final Node widen() {
+ if( !hasFloatInput() ) return this;
+ Node flt = copyF();
+ if( flt==null ) return this;
+ for( int i=1; i<nIns(); i++ )
+ flt.setDef(i, in(i)._type instanceof TypeFloat ? in(i) : new ToFloatNode(in(i)).peephole());
+ kill();
+ return flt;
+ }
+ private boolean hasFloatInput() {
+ for( int i=1; i<nIns(); i++ )
+ if( in(i)._type instanceof TypeFloat )
+ return true;
+ return false;
+ }
+ Node copyF() { return null; }
+
+
// ------------------------------------------------------------------------
// Peephole utilities
diff --git a/src/main/java/com/seaofnodes/simple/node/NotNode.java b/src/main/java/com/seaofnodes/simple/node/NotNode.java
index 05e44eb0..3cf69520 100644
--- a/src/main/java/com/seaofnodes/simple/node/NotNode.java
+++ b/src/main/java/com/seaofnodes/simple/node/NotNode.java
@@ -21,8 +21,8 @@ public class NotNode extends Node {
public Type compute() {
Type t0 = in(1)._type;
switch( t0 ) {
- case TypeInteger i0:
- return i0.isConstant() ? TypeInteger.constant(i0.value()==0 ? 1 : 0) : i0;
+ case TypeInteger i0: return i0.isConstant() ? TypeInteger.constant(i0.value()==0 ? 1 : 0) : i0;
+ case TypeFloat i0: return i0.isConstant() ? TypeInteger.constant(i0.value()==0 ? 1 : 0) : i0;
case TypeMemPtr p0:
// top->top, bot->bot, null->1, *void->0, not-null ptr->0, ptr/nil->bot
// If input in null then true
diff --git a/src/main/java/com/seaofnodes/simple/node/PhiNode.java b/src/main/java/com/seaofnodes/simple/node/PhiNode.java
index a07dc140..ebed8dd1 100644
--- a/src/main/java/com/seaofnodes/simple/node/PhiNode.java
+++ b/src/main/java/com/seaofnodes/simple/node/PhiNode.java
@@ -100,10 +100,10 @@ public class PhiNode extends Node {
if( in(2)._type == in(2)._type.makeInit() ) nullx = 2;
if( nullx != -1 ) {
Node val = in(3-nullx);
- if( region().idom() instanceof IfNode iff && iff.pred().addDep(this)==val ) {
+ if( region().idom(this) instanceof IfNode iff && iff.pred().addDep(this)==val ) {
// Must walk the idom on the null side to make sure we hit False.
CFGNode idom = (CFGNode)region().in(nullx);
- while( idom.in(0) != iff ) idom = idom.idom();
+ while( idom.nIns() > 0 && idom.in(0) != iff ) idom = idom.idom();
if( idom instanceof CProjNode proj && proj._idx==1 )
return val;
}
diff --git a/src/main/java/com/seaofnodes/simple/node/RegionNode.java b/src/main/java/com/seaofnodes/simple/node/RegionNode.java
index dcc7ccef..d5105614 100644
--- a/src/main/java/com/seaofnodes/simple/node/RegionNode.java
+++ b/src/main/java/com/seaofnodes/simple/node/RegionNode.java
@@ -99,12 +99,12 @@ public class RegionNode extends CFGNode {
return _idepth=d;
}
- @Override public CFGNode idom() {
+ @Override public CFGNode idom(Node dep) {
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.
for( int i=1; i<nIns(); i++ )
- lca = cfg(i).idom(lca);
+ lca = cfg(i)._idom(lca,dep);
return lca;
}
diff --git a/src/main/java/com/seaofnodes/simple/node/StartNode.java b/src/main/java/com/seaofnodes/simple/node/StartNode.java
index 62fc8a6b..5f205ffd 100644
--- a/src/main/java/com/seaofnodes/simple/node/StartNode.java
+++ b/src/main/java/com/seaofnodes/simple/node/StartNode.java
@@ -75,7 +75,7 @@ public class StartNode extends CFGNode implements MultiNode {
// No immediate dominator, and idepth==0
@Override public int idepth() { return 0; }
- @Override public CFGNode idom() { return null; }
+ @Override public CFGNode idom(Node dep) { return null; }
@Override void _walkUnreach( BitSet visit, HashSet<CFGNode> unreach ) { }
diff --git a/src/main/java/com/seaofnodes/simple/node/StopNode.java b/src/main/java/com/seaofnodes/simple/node/StopNode.java
index 94b2ad6d..ab567bae 100644
--- a/src/main/java/com/seaofnodes/simple/node/StopNode.java
+++ b/src/main/java/com/seaofnodes/simple/node/StopNode.java
@@ -59,7 +59,7 @@ public class StopNode extends CFGNode {
d = Math.max(d,((CFGNode)n).idepth()+1);
return _idepth=d;
}
- @Override public CFGNode idom() { return null; }
+ @Override public CFGNode idom(Node dep) { return null; }
@Override public int loopDepth() { return (_loopDepth=1); }
diff --git a/src/main/java/com/seaofnodes/simple/node/SubFNode.java b/src/main/java/com/seaofnodes/simple/node/SubFNode.java
new file mode 100644
index 00000000..682930e0
--- /dev/null
+++ b/src/main/java/com/seaofnodes/simple/node/SubFNode.java
@@ -0,0 +1,44 @@
+package com.seaofnodes.simple.node;
+
+import com.seaofnodes.simple.type.Type;
+import com.seaofnodes.simple.type.TypeFloat;
+
+import java.util.BitSet;
+
+public class SubFNode extends Node {
+ public SubFNode(Node lhs, Node rhs) { super(null, lhs, rhs); }
+
+ @Override public String label() { return "SubF"; }
+
+ @Override public String glabel() { return "-"; }
+
+ @Override
+ StringBuilder _print1(StringBuilder sb, BitSet visited) {
+ in(1)._print0(sb.append("("), visited);
+ in(2)._print0(sb.append("-"), visited);
+ return sb.append(")");
+ }
+
+ @Override
+ public Type compute() {
+ if (in(1)._type instanceof TypeFloat i0 &&
+ in(2)._type instanceof TypeFloat i1) {
+ if (i0.isConstant() && i1.isConstant())
+ return TypeFloat.constant(i0.value()-i1.value());
+ }
+ return in(1)._type.meet(in(2)._type);
+ }
+
+ @Override
+ public Node idealize() {
+ Node lhs = in(1);
+ Type t2 = in(2)._type;
+
+ // Sub of 1.
+ if ( t2.isConstant() && t2 instanceof TypeFloat i && i.value()==0 )
+ return lhs;
+
+ return null;
+ }
+ @Override Node copy(Node lhs, Node rhs) { return new SubFNode(lhs,rhs); }
+}
diff --git a/src/main/java/com/seaofnodes/simple/node/SubNode.java b/src/main/java/com/seaofnodes/simple/node/SubNode.java
index 5ddcdb68..f0c77743 100644
--- a/src/main/java/com/seaofnodes/simple/node/SubNode.java
+++ b/src/main/java/com/seaofnodes/simple/node/SubNode.java
@@ -31,6 +31,7 @@ public class SubNode extends Node {
if (i0.isConstant() && i1.isConstant())
return TypeInteger.constant(i0.value()-i1.value());
}
+
return in(1)._type.meet(in(2)._type);
}
@@ -48,4 +49,5 @@ public class SubNode extends Node {
}
@Override Node copy(Node lhs, Node rhs) { return new SubNode(lhs,rhs); }
+ @Override Node copyF() { return new SubFNode(null,null); }
}
diff --git a/src/main/java/com/seaofnodes/simple/node/ToFloatNode.java b/src/main/java/com/seaofnodes/simple/node/ToFloatNode.java
new file mode 100644
index 00000000..1d147cf6
--- /dev/null
+++ b/src/main/java/com/seaofnodes/simple/node/ToFloatNode.java
@@ -0,0 +1,30 @@
+package com.seaofnodes.simple.node;
+
+import com.seaofnodes.simple.type.Type;
+import com.seaofnodes.simple.type.TypeFloat;
+import com.seaofnodes.simple.type.TypeInteger;
+
+import java.util.BitSet;
+
+public class ToFloatNode extends Node {
+ public ToFloatNode(Node lhs) { super(null, lhs); }
+
+ @Override public String label() { return "ToFloat"; }
+
+ @Override public String glabel() { return "(flt)"; }
+
+ @Override
+ StringBuilder _print1(StringBuilder sb, BitSet visited) {
+ return in(1)._print0(sb.append("(flt)"), visited);
+ }
+
+ @Override
+ public Type compute() {
+ if (in(1)._type instanceof TypeInteger i0 && i0.isConstant() )
+ return TypeFloat.constant(i0.value());
+ return TypeFloat.BOT;
+ }
+
+ @Override public Node idealize() { return null; }
+ @Override Node copy(Node lhs, Node rhs) { return new ToFloatNode(lhs); }
+}