summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--chapter22/src/main/java/com/seaofnodes/simple/node/MemMergeNode.java32
-rw-r--r--chapter22/src/main/java/com/seaofnodes/simple/node/StoreNode.java7
-rw-r--r--chapter23/README.md10
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 {