diff options
| -rw-r--r-- | chapter22/src/main/java/com/seaofnodes/simple/node/MemMergeNode.java | 32 | ||||
| -rw-r--r-- | chapter22/src/main/java/com/seaofnodes/simple/node/StoreNode.java | 7 | ||||
| -rw-r--r-- | chapter23/README.md | 10 |
3 files changed, 38 insertions, 11 deletions
diff --git a/chapter22/src/main/java/com/seaofnodes/simple/node/MemMergeNode.java b/chapter22/src/main/java/com/seaofnodes/simple/node/MemMergeNode.java index e936ee58..9f2fdd16 100644 --- a/chapter22/src/main/java/com/seaofnodes/simple/node/MemMergeNode.java +++ b/chapter22/src/main/java/com/seaofnodes/simple/node/MemMergeNode.java @@ -65,24 +65,38 @@ public class MemMergeNode extends Node { @Override public Node idealize() { if( inProgress() ) return null; + // Fold defaults into the default + boolean progress=false, allDefault=true; + for( int i=2; i<nIns(); i++ ) + if( in(1) == in(i) ) { setDef(i,null); progress=true; } + else { allDefault=false; } + // If not merging any memory (all memory is just the default) - if( allDefault() ) + if( allDefault ) return in(1); // Become default memory - return null; - } - private boolean allDefault() { - for( int i=2; i<nIns(); i++ ) - if( in(1) != in(i) ) - return false; - return true; + // Collapse stacked all-mem + if( in(1) instanceof MemMergeNode mem ) { + // Goal is to swap my default mem with mem's default mem + for( int i=2; i<mem.nIns(); i++ ) { + if( mem.in(i) != null ) { + // deeper default mem has a non-default + if( i>=nIns() || in(i)==null ) + setDefX(i,mem.in(i)); + } + } + setDef(1,mem.in(1)); + return this; + } + + return progress ? this : null; } public Node in( Var v ) { return in(v._idx); } public Node alias( int alias ) { - return in(alias<nIns() && in(alias)!=null ? alias : 1); + return alias < nIns() && in(alias)!=null ? in(alias) : in(1); } Node alias( int alias, Node st ) { diff --git a/chapter22/src/main/java/com/seaofnodes/simple/node/StoreNode.java b/chapter22/src/main/java/com/seaofnodes/simple/node/StoreNode.java index 2e9e38d5..9b561bed 100644 --- a/chapter22/src/main/java/com/seaofnodes/simple/node/StoreNode.java +++ b/chapter22/src/main/java/com/seaofnodes/simple/node/StoreNode.java @@ -71,6 +71,12 @@ public class StoreNode extends MemOpNode { return this; } + // Simple store-after-MemMerge to a known alias can bypass. Happens when inlining. + if( mem() instanceof MemMergeNode mem ) { + setDef(1,mem.alias(_alias)); + return this; + } + // Value is automatically truncated by narrow store if( val() instanceof AndNode and && and.in(2)._type.isConstant() ) { int log = _declaredType.log_size(); @@ -84,6 +90,7 @@ public class StoreNode extends MemOpNode { } } + // Store will chop high order bits off; math to change those bits can be dropped. if( val() instanceof SarNode shr && shr.in(1) instanceof ShlNode shl && shr.in(2)._type.isConstant() && diff --git a/chapter23/README.md b/chapter23/README.md index 433ecf03..5625fa61 100644 --- a/chapter23/README.md +++ b/chapter23/README.md @@ -12,8 +12,14 @@ You can also read [this chapter](https://github.com/SeaOfNodes/Simple/tree/linea The idea is that structs have fields indexed by names, and arrays have fields indexed by numbers, and these ideas are compatible with each other. This idea -has been used by the C language for a long time - following a normal struct C -allows an array and can index it with the usual array syntax. +has been used by the C language for a long time - an array can follow a normal +struct C and can index it with the usual array syntax. + +The alternative, using a field to hold a pointer to an array, exchanges some +flexibility for an extra indirection. The obvious flexibility allows swapping +the array out (generally for a larger one) and this is the basis of very common +`Vector` or `ArrayList` generic containers. + ```java struct str { |
