# HG changeset patch # User Tom Rodriguez # Date 1454444683 28800 # Node ID 02bb6d11986c4839c8b5399bc4a1b46cddda8a9e # Parent 1f75da663952502403089558b1ba6eaaa8664205 ConditionalNode optimizations should be performed on suitable If diamonds diff -r 1f75da663952 -r 02bb6d11986c graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/IfNode.java --- 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 diff -r 1f75da663952 -r 02bb6d11986c graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/ConditionalNode.java --- 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) {