summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--chapter16/src/main/java/com/seaofnodes/simple/node/LoadNode.java8
-rw-r--r--chapter16/src/main/java/com/seaofnodes/simple/node/NewNode.java4
-rw-r--r--chapter16/src/main/java/com/seaofnodes/simple/node/StoreNode.java41
-rw-r--r--chapter16/src/test/java/com/seaofnodes/simple/Chapter15Test.java3
4 files changed, 40 insertions, 16 deletions
diff --git a/chapter16/src/main/java/com/seaofnodes/simple/node/LoadNode.java b/chapter16/src/main/java/com/seaofnodes/simple/node/LoadNode.java
index be6fba11..c4abed12 100644
--- a/chapter16/src/main/java/com/seaofnodes/simple/node/LoadNode.java
+++ b/chapter16/src/main/java/com/seaofnodes/simple/node/LoadNode.java
@@ -2,9 +2,7 @@ package com.seaofnodes.simple.node;
import com.seaofnodes.simple.Utils;
import com.seaofnodes.simple.Parser;
-import com.seaofnodes.simple.type.Type;
-import com.seaofnodes.simple.type.TypeMem;
-import com.seaofnodes.simple.type.TypeStruct;
+import com.seaofnodes.simple.type.*;
import java.util.BitSet;
/**
@@ -57,7 +55,7 @@ public class LoadNode extends MemOpNode {
// Simple Load-after-New on same address.
if( mem() instanceof ProjNode p && p.in(0) instanceof NewNode nnn &&
ptr == nnn.proj(1) ) // Must check same object
- return nnn.findAlias(_alias); // Load from New init
+ return nnn.in(nnn.findAlias(_alias)); // Load from New init
// Load-after-Store on same address, but bypassing provably unrelated
// stores. This is a more complex superset of the above two peeps.
@@ -81,7 +79,7 @@ public class LoadNode extends MemOpNode {
case ProjNode mproj:
if( mproj.in(0) instanceof NewNode nnn1 ) {
if( ptr instanceof ProjNode pproj && pproj.in(0) == mproj.in(0) )
- return nnn1.findAlias(_alias); // Load from New init
+ return nnn1.in(nnn1.findAlias(_alias)); // Load from New init
if( !(ptr instanceof ProjNode pproj && pproj.in(0) instanceof NewNode nnn2) )
break outer; // Cannot tell, ptr not related to New
mem = nnn1.in(_alias);// Bypass unrelated New
diff --git a/chapter16/src/main/java/com/seaofnodes/simple/node/NewNode.java b/chapter16/src/main/java/com/seaofnodes/simple/node/NewNode.java
index cb6ee464..1e6d2baa 100644
--- a/chapter16/src/main/java/com/seaofnodes/simple/node/NewNode.java
+++ b/chapter16/src/main/java/com/seaofnodes/simple/node/NewNode.java
@@ -45,8 +45,8 @@ public class NewNode extends Node implements MultiNode {
}
// Find matching alias input
- Node findAlias(int alias) {
- return in(2+_ptr._obj.findAlias(alias)+_len);
+ int findAlias(int alias) {
+ return 2+_ptr._obj.findAlias(alias)+_len;
}
diff --git a/chapter16/src/main/java/com/seaofnodes/simple/node/StoreNode.java b/chapter16/src/main/java/com/seaofnodes/simple/node/StoreNode.java
index b1c74b94..7b1bddd5 100644
--- a/chapter16/src/main/java/com/seaofnodes/simple/node/StoreNode.java
+++ b/chapter16/src/main/java/com/seaofnodes/simple/node/StoreNode.java
@@ -55,27 +55,52 @@ public class StoreNode extends MemOpNode {
// required init-store being stomped by a first user store.
if( mem() instanceof StoreNode st &&
ptr()==st.ptr() && // Must check same object
- off()==st.off() && // And same offset
+ off()==st.off() && // And same offset (could be "same alias" but this handles arrays to same index)
ptr()._type instanceof TypeMemPtr && // No bother if weird dead pointers
// Must have exactly one use of "this" or you get weird
// non-serializable memory effects in the worse case.
- st.checkNoUseBeyond(this) ) {
+ checkOnlyUse(st) ) {
assert _name.equals(st._name); // Equiv class aliasing is perfect
setDef(1,st.mem());
return this;
}
+ // Simple store-after-new on same address. Should pick up the
+ // an init-store being stomped by a first user store.
+ if( mem() instanceof ProjNode st && st .in(0) instanceof NewNode nnn &&
+ ptr() instanceof ProjNode ptr && ptr.in(0) == nnn &&
+ ptr()._type instanceof TypeMemPtr tmp && // No bother if weird dead pointers
+ // Cannot fold a store of a single element over the array body initializer value
+ !(tmp._obj.isAry() && tmp._obj._fields[1]._alias==_alias) &&
+ // Very sad strong cutout: val has to be legal to hoist to a New
+ // input, which means it cannot depend on the New. Many many
+ // things are legal here but difficult to check without doing a
+ // full dominator check. Example failure:
+ // "struct C { C? c; }; C self = new C { c=self; }"
+ val()._type.isHighOrConst() &&
+ // Must have exactly one use of "this" or you get weird
+ // non-serializable memory effects in the worse case.
+ checkOnlyUse(st) &&
+ // Folding away a broken store
+ err()==null ) {
+ nnn.setDef(nnn.findAlias(_alias),val());
+ // Must retype the NewNode
+ nnn ._type = nnn. compute();
+ mem()._type = mem().compute();
+ return st;
+ }
+
return null;
}
- // Check that `this` has no uses beyond `that`
- private boolean checkNoUseBeyond(Node that) {
- if( nOuts()==1 ) return true;
+ // Check that "mem" has no uses except "this"
+ private boolean checkOnlyUse(Node mem) {
+ if( mem.nOuts()==1 ) return true;
// Add deps on the other uses (can be e.g. ScopeNode mid-parse) so that
// when the other uses go away we can retry.
- for( Node use : _outputs )
- if( use != that )
- use.addDep(that);
+ for( Node use : mem._outputs )
+ if( use != this )
+ use.addDep(this);
return false;
}
diff --git a/chapter16/src/test/java/com/seaofnodes/simple/Chapter15Test.java b/chapter16/src/test/java/com/seaofnodes/simple/Chapter15Test.java
index a9b34748..93a9c85c 100644
--- a/chapter16/src/test/java/com/seaofnodes/simple/Chapter15Test.java
+++ b/chapter16/src/test/java/com/seaofnodes/simple/Chapter15Test.java
@@ -130,8 +130,9 @@ else {
return rez;
""");
StopNode stop = parser.parse().iterate();
- assertEquals("return Phi(Region117,1.2,Phi(Region114,2.3,.y));", stop.toString());
+ assertEquals("return Phi(Region117,1.2,Phi(Region114,2.3,3.14));", stop.toString());
assertEquals(3.14, Evaluator.evaluate(stop, 0));
+ assertEquals(1.2 , Evaluator.evaluate(stop, 1));
}
@Ignore