summaryrefslogtreecommitdiff
path: root/src/main/java/com/seaofnodes/simple/node/AddNode.java
diff options
context:
space:
mode:
Diffstat (limited to 'src/main/java/com/seaofnodes/simple/node/AddNode.java')
-rw-r--r--src/main/java/com/seaofnodes/simple/node/AddNode.java44
1 files changed, 27 insertions, 17 deletions
diff --git a/src/main/java/com/seaofnodes/simple/node/AddNode.java b/src/main/java/com/seaofnodes/simple/node/AddNode.java
index 2bbe1053..a29ba73b 100644
--- a/src/main/java/com/seaofnodes/simple/node/AddNode.java
+++ b/src/main/java/com/seaofnodes/simple/node/AddNode.java
@@ -1,16 +1,19 @@
package com.seaofnodes.simple.node;
+import com.seaofnodes.simple.codegen.CodeGen;
import com.seaofnodes.simple.type.*;
-import static com.seaofnodes.simple.Parser.con;
-
public class AddNode extends ArithNode {
+ @Override boolean allowFloat() { return true; }
public AddNode(Node lhs, Node rhs) { super(null, lhs, rhs); }
+ public AddNode(Node lhs, Node rhs, byte mode) { super(null, lhs, rhs, mode); }
+ @Override public Tag serialTag() { return Tag.Add; }
@Override public String label() { return "Add"; }
@Override public String op() { return "+"; }
- @Override long doOp( long x, long y ) { return x + y; }
+ @Override long doOp( long x, long y ) { return x + y; }
+ @Override double doOp(double x, double y ) { return x + y; }
@Override TypeInteger doOp(TypeInteger x, TypeInteger y) {
// Fold ranges like {0-1} + {2-3} into {2-4}.
if( !overflow(x._min,y._min) &&
@@ -21,6 +24,11 @@ public class AddNode extends ArithNode {
@Override
public Node idealize () {
+ // Settle the one-shot arithmetic mode before applying family-specific
+ // algebraic identities.
+ if( _mode==0 )
+ return super.idealize();
+
Node lhs = in(1);
Node rhs = in(2);
if( rhs instanceof AddNode add && add.err()!=null )
@@ -29,12 +37,12 @@ public class AddNode extends ArithNode {
// Add of 0. We do not check for (0+x) because this will already
// canonicalize to (x+0)
- if( t2 == TypeInteger.ZERO && lhs._type instanceof TypeInteger )
+ if( t2 == TypeInteger.ZERO && lhs._type.isa(compute()) )
return lhs;
// Add of same to a multiply by 2
- if( lhs==rhs )
- return new ShlNode(null,lhs,con(1));
+ if( lhs==rhs && _mode==1 )
+ return new ShlNode(null,lhs,CodeGen.CODE.con(1));
// Goal: a left-spine set of adds, with constants on the rhs (which then fold).
@@ -44,7 +52,7 @@ public class AddNode extends ArithNode {
// x+(-y) becomes x-y
if( rhs instanceof MinusNode minus )
- return new SubNode(lhs,minus.in(1));
+ return new SubNode(lhs,minus.in(1),_mode);
// Now we might see (add add non) or (add non non) or (add add add) but never (add non add)
@@ -52,18 +60,21 @@ public class AddNode extends ArithNode {
// Swap to (x + y) + z
// Rotate (add add add) to remove the add on RHS
if( rhs instanceof AddNode add )
- return new AddNode(new AddNode(lhs,add.in(1)).peephole(), add.in(2));
+ return copy(copy(lhs,add.in(1)).peephole(), add.in(2));
// Now we might see (add add non) or (add non non) but never (add non add) nor (add add add)
- if( !(lhs instanceof AddNode) )
+ if( !(lhs instanceof AddNode) ) {
// Rotate; look for (add (phi cons) con/(phi cons))
- return spine_cmp(lhs,rhs,this) ? swap12() : phiCon(this,true);
+ if( spine_cmp(lhs,rhs,this) ) return swap12();
+ Node n = phiCon(this,true);
+ return n == null ? super.idealize() : n;
+ }
// Now we only see (add add non)
// Dead data cycle; comes about from dead infinite loops. Do nothing,
// the loop will peep as dead after a bit.
- if( lhs.in(1) == lhs )
+ if( lhs.nIns()>=2 && lhs.in(1) == lhs )
return null;
// Do we have (x + con1) + con2?
@@ -73,7 +84,7 @@ public class AddNode extends ArithNode {
// because if it later became a constant then we could make this
// transformation.
if( addDep(lhs.in(2))._type.isConstant() && rhs._type.isConstant() )
- return new AddNode(lhs.in(1),new AddNode(lhs.in(2),rhs).peephole());
+ return copy(lhs.in(1),copy(lhs.in(2),rhs).peephole());
// Do we have ((x + (phi cons)) + con) ?
@@ -87,13 +98,13 @@ public class AddNode extends ArithNode {
// Do we rotate (x + y) + z
// into (x + z) + y ?
if( spine_cmp(lhs.in(2),rhs,this) )
- return new AddNode(new AddNode(lhs.in(1),rhs).peephole(),lhs.in(2));
+ return copy(copy(lhs.in(1),rhs).peephole(),lhs.in(2));
return super.idealize();
}
// Rotation is only valid for associative ops, e.g. Add, Mul, And, Or, Xor.
- // Do we have ((phi cons)|(x + (phi cons)) + con|(phi cons)) ?
+ // Do we have ((phi cons)|(x + (phi cons)) + con|(phi cons)|(op y con)) ?
// Push constant up through the phi: x + (phi con0+con0 con1+con1...)
static Node phiCon(Node op, boolean rotate) {
Node lhs = op.in(1);
@@ -126,7 +137,7 @@ public class AddNode extends ArithNode {
for( int i=1; i<ns.length; i++ )
ns[i] = op.copy(lphi.in(i), rhs instanceof PhiNode ? rhs.in(i) : rhs).peephole();
String label = lphi._label + (rhs instanceof PhiNode rphi ? rphi._label : "");
- Node phi = new PhiNode(label,lphi._minType.meet(op._type),ns).peephole();
+ Node phi = new PhiNode(label,ns).peephole();
// Rotate needs another op, otherwise just the phi
return lhs==lphi ? phi : op.copy(lhs.in(1),phi);
}
@@ -164,6 +175,5 @@ public class AddNode extends ArithNode {
return lo._nid > hi._nid;
}
- @Override Node copy(Node lhs, Node rhs) { return new AddNode(lhs,rhs); }
- @Override Node copyF() { return new AddFNode(null,null); }
+ @Override Node copy(Node lhs, Node rhs) { return new AddNode(lhs,rhs,_mode); }
}