diff options
| author | Cliff Click <cliffc@acm.org> | 2024-10-18 08:47:29 -0700 |
|---|---|---|
| committer | Cliff Click <cliffc@acm.org> | 2024-10-21 08:52:01 -0700 |
| commit | c4c8ee708c6948dcfa41be61eb96e744d5c6d3f8 (patch) | |
| tree | 65de12a176d3277a4874d6c9d2550eafedfb96dc /chapter16/src/main/java/com | |
| parent | 8ecde979dee25f08bdd3360f19eeb85ead5dd2ca (diff) | |
| download | Simple-c4c8ee708c6948dcfa41be61eb96e744d5c6d3f8.tar.gz Simple-c4c8ee708c6948dcfa41be61eb96e744d5c6d3f8.zip | |
Missing init-store-after-new opt
Diffstat (limited to 'chapter16/src/main/java/com')
3 files changed, 38 insertions, 15 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; } |
