summaryrefslogtreecommitdiff
path: root/chapter17/src/main/java/com/seaofnodes
diff options
context:
space:
mode:
Diffstat (limited to 'chapter17/src/main/java/com/seaofnodes')
-rw-r--r--chapter17/src/main/java/com/seaofnodes/simple/IterPeeps.java19
-rw-r--r--chapter17/src/main/java/com/seaofnodes/simple/Parser.java28
-rw-r--r--chapter17/src/main/java/com/seaofnodes/simple/node/PhiNode.java2
3 files changed, 33 insertions, 16 deletions
diff --git a/chapter17/src/main/java/com/seaofnodes/simple/IterPeeps.java b/chapter17/src/main/java/com/seaofnodes/simple/IterPeeps.java
index 81b89513..36f053f9 100644
--- a/chapter17/src/main/java/com/seaofnodes/simple/IterPeeps.java
+++ b/chapter17/src/main/java/com/seaofnodes/simple/IterPeeps.java
@@ -1,25 +1,24 @@
package com.seaofnodes.simple;
import com.seaofnodes.simple.node.*;
-import com.seaofnodes.simple.type.Type;
-import java.util.ArrayList;
import java.util.Arrays;
import java.util.BitSet;
import java.util.Random;
/**
- * The IterOptim runs after parsing. It iterates the peepholes to a fixed point
+ * The IterPeeps runs after parsing. It iterates the peepholes to a fixed point
* so that no more peepholes apply. This should be linear because peepholes rarely
* (never?) increase code size. The graph should monotonically reduce in some
* dimension, which is usually size. It might also reduce in e.g. number of
* MulNodes or Load/Store nodes, swapping out more "expensive" Nodes for cheaper
* ones.
- *
+ * <br>
* The theoretical overall worklist is mindless just grabbing the next thing and
- * doing it. If the graph changes, put the neighbors on the worklist. Lather,
- * Rinse, Repeat until the worklist runs dry.
- *
+ * doing it. If the graph changes, put the neighbors on the worklist.
+ * <br>
+ * Lather, Rinse, Repeat until the worklist runs dry.
+ * <p>
* The main issues we have to deal with:
*
* <ul>
@@ -29,7 +28,7 @@ import java.util.Random;
* is stable and correct between peepholes. In our case `Node.subsume` does
* most of the munging, building on our prior stable Node utilities.</li>
*
- * <li>Changing a Node also changes the graph "neighborhood". The neigbors need to
+ * <li>Changing a Node also changes the graph "neighborhood". The neighbors need to
* be checked to see if THEY can also peephole, and so on. After any peephole
* or graph update we put a Nodes uses and defs on the worklist.</li>
*
@@ -39,7 +38,7 @@ import java.util.Random;
* check is linear at each peephole step... so quadratic overall. Its a useful
* assert, but one we can disable once the overall algorithm is stable - and
* then turn it back on again when some new set of peepholes is misbehaving.
- * The code for this is turned on in `IterOptim.iterate` as `assert
+ * The code for this is turned on in `IterPeeps.iterate` as `assert
* progressOnList(stop);`</li>
* </ul>
*/
@@ -115,7 +114,7 @@ public abstract class IterPeeps {
int old_cnt = Node.ITER_CNT, old_nop = Node.ITER_NOP_CNT;
Node changed = stop.walk( n -> {
Node m = n;
- if( n.compute().isa(n._type) ) { // Types must be forwards, even if on worklist
+ if( n.compute().isa(n._type) && (!n.iskeep() || n._nid<=5) ) { // Types must be forwards, even if on worklist
if( WORK.on(n) ) return null;
m = n.peepholeOpt();
if( m==null ) return null;
diff --git a/chapter17/src/main/java/com/seaofnodes/simple/Parser.java b/chapter17/src/main/java/com/seaofnodes/simple/Parser.java
index a4f7462e..e2f8ad32 100644
--- a/chapter17/src/main/java/com/seaofnodes/simple/Parser.java
+++ b/chapter17/src/main/java/com/seaofnodes/simple/Parser.java
@@ -476,7 +476,7 @@ public class Parser {
_xScopes.pop(); // Discard pushed from graph display
RegionNode r = ctrl(tScope.mergeScopes(fScope));
- Node ret = stmt ? r : peep(new PhiNode("",lhs._type.meet(rhs._type),r,lhs,rhs));
+ Node ret = stmt ? r : peep(new PhiNode("",lhs._type.meet(rhs._type),r,lhs.unkeep(),rhs));
r.peephole();
return ret;
}
@@ -838,11 +838,29 @@ public class Parser {
* Parse a unary minus expression.
*
* <pre>
- * unaryExpr : ('-') | '!') unaryExpr | postfixExpr | primaryExpr
+ * unaryExpr : ('-') unaryExpr | '!') unaryExpr | postfixExpr | primaryExpr | '--' Id | '++' Id
* </pre>
* @return a unary expression {@link Node}, never {@code null}
*/
private Node parseUnary() {
+ // Pre-dec/pre-inc
+ int old = pos();
+ if( match("--") || match("++") ) {
+ int delta = _lexer.peek(-1)=='+' ? 1 : -1; // Pre vs post
+ String name = _lexer.matchId();
+ if( name!=null ) {
+ ScopeMinNode.Var n = _scope.lookup(name);
+ if( n != null ) {
+ if( n._final )
+ throw error("Cannot reassign final '"+n._name+"'");
+ Node expr = peep(new AddNode(_scope.in(n),con(delta)));
+ _scope.update(n,expr);
+ return expr;
+ }
+ }
+ // Reset, try again
+ pos(old);
+ }
if (match("-")) return peep(new MinusNode(parseUnary()).widen());
if (match("!")) return peep(new NotNode(parseUnary()));
return parsePostfix(parsePrimary());
@@ -892,7 +910,7 @@ public class Parser {
if( t==null ) throw error("Expected a type");
// Parse ary[ length_expr ]
if( match("[") ) {
- Node len = parseExpression().keep();
+ Node len = parseExpression();
if( !(len._type instanceof TypeInteger) )
throw error("Cannot allocate an array with length "+len._type);
require("]");
@@ -964,8 +982,8 @@ public class Parser {
private Node newArray(TypeStruct ary, Node len) {
int base = ary.aryBase ();
int scale= ary.aryScale();
- Node size = peep(new AddNode(con(base),peep(new ShlNode(len,con(scale)))));
- ALTMP.clear(); ALTMP.add(len); ALTMP.add(con(ary._fields[1]._type.makeInit()));
+ Node size = peep(new AddNode(con(base),peep(new ShlNode(len.keep(),con(scale)))));
+ ALTMP.clear(); ALTMP.add(len.unkeep()); ALTMP.add(con(ary._fields[1]._type.makeInit()));
return newStruct(ary,size,0,ALTMP);
}
diff --git a/chapter17/src/main/java/com/seaofnodes/simple/node/PhiNode.java b/chapter17/src/main/java/com/seaofnodes/simple/node/PhiNode.java
index f0140ce6..58ce6b47 100644
--- a/chapter17/src/main/java/com/seaofnodes/simple/node/PhiNode.java
+++ b/chapter17/src/main/java/com/seaofnodes/simple/node/PhiNode.java
@@ -101,7 +101,7 @@ public class PhiNode extends Node {
if( in(2)._type == in(2)._type.makeInit() ) nullx = 2;
if( nullx != -1 ) {
Node val = in(3-nullx);
- if( r.idom(this) instanceof IfNode iff && iff.pred().addDep(this)==val ) {
+ if( r.idom(this).addDep(this) instanceof IfNode iff && iff.pred().addDep(this)==val ) {
// Must walk the idom on the null side to make sure we hit False.
CFGNode idom = (CFGNode)r.in(nullx);
while( idom.nIns() > 0 && idom.in(0) != iff ) idom = idom.idom();