changeset 23368:02bb6d11986c

ConditionalNode optimizations should be performed on suitable If diamonds
author Tom Rodriguez <tom.rodriguez@oracle.com>
date Tue, 02 Feb 2016 12:24:43 -0800
parents 1f75da663952
children 533b3e243531
files graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/IfNode.java graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/ConditionalNode.java
diffstat 2 files changed, 69 insertions(+), 14 deletions(-) [+]
line wrap: on
line diff
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/IfNode.java	Tue Feb 02 15:54:14 2016 +0100
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/IfNode.java	Tue Feb 02 12:24:43 2016 -0800
@@ -221,6 +221,10 @@
             return;
         }
 
+        if (conditionalNodeOptimization(tool)) {
+            return;
+        }
+
         if (falseSuccessor().hasNoUsages() && (!(falseSuccessor() instanceof LoopExitNode)) && falseSuccessor().next() instanceof IfNode) {
             AbstractBeginNode intermediateBegin = falseSuccessor();
             IfNode nextIf = (IfNode) intermediateBegin.next();
@@ -253,6 +257,48 @@
         }
     }
 
+    /**
+     * Try to optimize this as if it were a {@link ConditionalNode}.
+     */
+    private boolean conditionalNodeOptimization(SimplifierTool tool) {
+        if (trueSuccessor().next() instanceof AbstractEndNode && falseSuccessor().next() instanceof AbstractEndNode) {
+            AbstractEndNode trueEnd = (AbstractEndNode) trueSuccessor().next();
+            AbstractEndNode falseEnd = (AbstractEndNode) falseSuccessor().next();
+            if (trueEnd.merge() != falseEnd.merge()) {
+                return false;
+            }
+            if (!(trueEnd.merge() instanceof MergeNode)) {
+                return false;
+            }
+            MergeNode merge = (MergeNode) trueEnd.merge();
+            if (merge.usages().count() != 1 || merge.phis().count() != 1) {
+                return false;
+            }
+            PhiNode phi = merge.phis().first();
+            ValueNode falseValue = phi.valueAt(falseEnd);
+            ValueNode trueValue = phi.valueAt(trueEnd);
+
+            ValueNode result = ConditionalNode.canonicalizeConditional(condition, trueValue, falseValue, phi.stamp());
+            if (result != null) {
+                /*
+                 * canonicalizeConditional returns possibly new nodes so add them to the graph.
+                 */
+                if (result.graph() == null) {
+                    result = graph().addOrUniqueWithInputs(result);
+                }
+                /*
+                 * This optimization can be performed even if multiple values merge at this phi
+                 * since the two inputs get simplified into one.
+                 */
+                phi.setValueAt(trueEnd, result);
+                removeThroughFalseBranch(tool);
+                return true;
+            }
+        }
+
+        return false;
+    }
+
     private void pushNodesThroughIf(SimplifierTool tool) {
         assert trueSuccessor().hasNoUsages() && falseSuccessor().hasNoUsages();
         // push similar nodes upwards through the if, thereby deduplicating them
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/ConditionalNode.java	Tue Feb 02 15:54:14 2016 +0100
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/ConditionalNode.java	Tue Feb 02 12:24:43 2016 -0800
@@ -129,14 +129,23 @@
             return synonym;
         }
 
+        ValueNode result = canonicalizeConditional(condition, trueValue(), falseValue(), stamp);
+        if (result != null) {
+            return result;
+        }
+
+        return this;
+    }
+
+    public static ValueNode canonicalizeConditional(LogicNode condition, ValueNode trueValue, ValueNode falseValue, Stamp stamp) {
         // this optimizes the case where a value that can only be 0 or 1 is materialized to 0 or 1
-        if (trueValue().isConstant() && falseValue().isConstant() && condition instanceof IntegerEqualsNode) {
+        if (trueValue.isConstant() && falseValue.isConstant() && condition instanceof IntegerEqualsNode) {
             IntegerEqualsNode equals = (IntegerEqualsNode) condition;
             if (equals.getY().isConstant() && equals.getY().asConstant().equals(JavaConstant.INT_0) && equals.getX().stamp() instanceof IntegerStamp) {
                 IntegerStamp equalsXStamp = (IntegerStamp) equals.getX().stamp();
                 if (equalsXStamp.upMask() == 1) {
-                    if (trueValue().asConstant().equals(JavaConstant.INT_0) && falseValue().asConstant().equals(JavaConstant.INT_1)) {
-                        return IntegerConvertNode.convertUnsigned(equals.getX(), stamp());
+                    if (trueValue.asConstant().equals(JavaConstant.INT_0) && falseValue.asConstant().equals(JavaConstant.INT_1)) {
+                        return IntegerConvertNode.convertUnsigned(equals.getX(), stamp);
                     }
                 }
             }
@@ -144,26 +153,26 @@
         if (condition instanceof CompareNode && ((CompareNode) condition).condition() == Condition.EQ) {
             // optimize the pattern (x == y) ? x : y
             CompareNode compare = (CompareNode) condition;
-            if ((compare.getX() == trueValue() && compare.getY() == falseValue()) || (compare.getX() == falseValue() && compare.getY() == trueValue())) {
-                return falseValue();
+            if ((compare.getX() == trueValue && compare.getY() == falseValue) || (compare.getX() == falseValue && compare.getY() == trueValue)) {
+                return falseValue;
             }
         }
-        if (trueValue() == falseValue()) {
-            return trueValue();
+        if (trueValue == falseValue) {
+            return trueValue;
         }
 
-        if (condition instanceof IntegerLessThanNode && trueValue().stamp() instanceof IntegerStamp) {
+        if (condition instanceof IntegerLessThanNode && trueValue.stamp() instanceof IntegerStamp) {
             /*
              * Convert a conditional add ((x < 0) ? (x + y) : x) into (x + (y & (x >> (bits - 1))))
              * to avoid the test.
              */
             IntegerLessThanNode lt = (IntegerLessThanNode) condition;
             if (lt.getY().isConstant() && lt.getY().asConstant().isDefaultForKind()) {
-                if (falseValue() == lt.getX()) {
-                    if (trueValue() instanceof AddNode) {
-                        AddNode add = (AddNode) trueValue();
-                        if (add.getX() == falseValue()) {
-                            int bits = ((IntegerStamp) trueValue().stamp()).getBits();
+                if (falseValue == lt.getX()) {
+                    if (trueValue instanceof AddNode) {
+                        AddNode add = (AddNode) trueValue;
+                        if (add.getX() == falseValue) {
+                            int bits = ((IntegerStamp) trueValue.stamp()).getBits();
                             ValueNode shift = new RightShiftNode(lt.getX(), ConstantNode.forIntegerBits(32, bits - 1));
                             ValueNode and = new AndNode(shift, add.getY());
                             return new AddNode(add.getX(), and);
@@ -173,7 +182,7 @@
             }
         }
 
-        return this;
+        return null;
     }
 
     private static ValueNode findSynonym(ValueNode condition, ValueNode trueValue, ValueNode falseValue) {