< prev index next >

src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/calc/AddNode.java

Print this page
rev 52509 : [mq]: graal2

@@ -1,7 +1,7 @@
 /*
- * Copyright (c) 2011, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2011, 2018, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
  * under the terms of the GNU General Public License version 2 only, as
  * published by the Free Software Foundation.

@@ -25,10 +25,11 @@
 package org.graalvm.compiler.nodes.calc;
 
 import org.graalvm.compiler.core.common.type.ArithmeticOpTable;
 import org.graalvm.compiler.core.common.type.ArithmeticOpTable.BinaryOp;
 import org.graalvm.compiler.core.common.type.ArithmeticOpTable.BinaryOp.Add;
+import org.graalvm.compiler.core.common.type.IntegerStamp;
 import org.graalvm.compiler.core.common.type.Stamp;
 import org.graalvm.compiler.graph.NodeClass;
 import org.graalvm.compiler.graph.spi.Canonicalizable.BinaryCommutative;
 import org.graalvm.compiler.graph.spi.CanonicalizerTool;
 import org.graalvm.compiler.lir.gen.ArithmeticLIRGeneratorTool;

@@ -36,11 +37,13 @@
 import org.graalvm.compiler.nodes.ConstantNode;
 import org.graalvm.compiler.nodes.NodeView;
 import org.graalvm.compiler.nodes.ValueNode;
 import org.graalvm.compiler.nodes.spi.NodeLIRBuilderTool;
 
+import jdk.vm.ci.code.CodeUtil;
 import jdk.vm.ci.meta.Constant;
+import jdk.vm.ci.meta.JavaConstant;
 import jdk.vm.ci.meta.Value;
 
 @NodeInfo(shortName = "+")
 public class AddNode extends BinaryArithmeticNode<Add> implements NarrowableArithmeticNode, BinaryCommutative<ValueNode> {
 

@@ -97,10 +100,58 @@
                 ValueNode reassociated = reassociate(self, ValueNode.isConstantPredicate(), forX, forY, view);
                 if (reassociated != self) {
                     return reassociated;
                 }
             }
+
+            // Attempt to optimize the pattern of an extend node between two add nodes.
+            if (c instanceof JavaConstant && (forX instanceof SignExtendNode || forX instanceof ZeroExtendNode)) {
+                IntegerConvertNode<?, ?> integerConvertNode = (IntegerConvertNode<?, ?>) forX;
+                ValueNode valueNode = integerConvertNode.getValue();
+                long constant = ((JavaConstant) c).asLong();
+                if (valueNode instanceof AddNode) {
+                    AddNode addBeforeExtend = (AddNode) valueNode;
+                    if (addBeforeExtend.getY().isConstant()) {
+                        // There is a second add before the extend node that also has a constant as
+                        // second operand. Therefore there will be canonicalizations triggered if we
+                        // can move the add above the extension. For this we need to check whether
+                        // the result of the addition is the same before the extension (which can be
+                        // either zero extend or sign extend).
+                        IntegerStamp beforeExtendStamp = (IntegerStamp) addBeforeExtend.stamp(view);
+                        int bits = beforeExtendStamp.getBits();
+                        if (constant >= CodeUtil.minValue(bits) && constant <= CodeUtil.maxValue(bits)) {
+                            IntegerStamp narrowConstantStamp = IntegerStamp.create(bits, constant, constant);
+
+                            if (!IntegerStamp.addCanOverflow(narrowConstantStamp, beforeExtendStamp)) {
+                                ConstantNode constantNode = ConstantNode.forIntegerStamp(narrowConstantStamp, constant);
+                                if (forX instanceof SignExtendNode) {
+                                    return SignExtendNode.create(AddNode.create(addBeforeExtend, constantNode, view), integerConvertNode.getResultBits(), view);
+                                } else {
+                                    assert forX instanceof ZeroExtendNode;
+
+                                    // Must check to not cross zero with the new add.
+                                    boolean crossesZeroPoint = true;
+                                    if (constant > 0) {
+                                        if (beforeExtendStamp.lowerBound() >= 0 || beforeExtendStamp.upperBound() < -constant) {
+                                            // We are good here.
+                                            crossesZeroPoint = false;
+                                        }
+                                    } else {
+                                        if (beforeExtendStamp.lowerBound() >= -constant || beforeExtendStamp.upperBound() < 0) {
+                                            // We are good here as well.
+                                            crossesZeroPoint = false;
+                                        }
+                                    }
+                                    if (!crossesZeroPoint) {
+                                        return ZeroExtendNode.create(AddNode.create(addBeforeExtend, constantNode, view), integerConvertNode.getResultBits(), view);
+                                    }
+                                }
+                            }
+                        }
+                    }
+                }
+            }
         }
         if (forX instanceof NegateNode) {
             return BinaryArithmeticNode.sub(forY, ((NegateNode) forX).getValue(), view);
         } else if (forY instanceof NegateNode) {
             return BinaryArithmeticNode.sub(forX, ((NegateNode) forY).getValue(), view);
< prev index next >