< prev index next >

src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.loop/src/org/graalvm/compiler/loop/LoopEx.java

Print this page
rev 56282 : [mq]: graal

@@ -59,13 +59,10 @@
 import org.graalvm.compiler.nodes.ValueNode;
 import org.graalvm.compiler.nodes.ValuePhiNode;
 import org.graalvm.compiler.nodes.calc.AddNode;
 import org.graalvm.compiler.nodes.calc.BinaryArithmeticNode;
 import org.graalvm.compiler.nodes.calc.CompareNode;
-import org.graalvm.compiler.nodes.calc.IntegerBelowNode;
-import org.graalvm.compiler.nodes.calc.IntegerEqualsNode;
-import org.graalvm.compiler.nodes.calc.IntegerLessThanNode;
 import org.graalvm.compiler.nodes.calc.LeftShiftNode;
 import org.graalvm.compiler.nodes.calc.MulNode;
 import org.graalvm.compiler.nodes.calc.NegateNode;
 import org.graalvm.compiler.nodes.calc.SignExtendNode;
 import org.graalvm.compiler.nodes.calc.SubNode;

@@ -209,10 +206,11 @@
             }
         }
         return count != 0;
     }
 
+    @SuppressWarnings("fallthrough")
     public boolean detectCounted() {
         if (countedLoopChecked) {
             return isCounted();
         }
         countedLoopChecked = true;

@@ -229,88 +227,106 @@
                     return false;
                 }
                 negated = true;
             }
             LogicNode ifTest = ifNode.condition();
-            if (!(ifTest instanceof IntegerLessThanNode) && !(ifTest instanceof IntegerEqualsNode)) {
-                if (ifTest instanceof IntegerBelowNode) {
-                    ifTest.getDebug().log("Ignored potential Counted loop at %s with |<|", loopBegin);
-                }
+            if (!(ifTest instanceof CompareNode)) {
                 return false;
             }
-            CompareNode lessThan = (CompareNode) ifTest;
+            CompareNode compare = (CompareNode) ifTest;
             Condition condition = null;
             InductionVariable iv = null;
             ValueNode limit = null;
-            if (isOutsideLoop(lessThan.getX())) {
-                iv = getInductionVariables().get(lessThan.getY());
+            if (isOutsideLoop(compare.getX())) {
+                iv = getInductionVariables().get(compare.getY());
                 if (iv != null) {
-                    condition = lessThan.condition().asCondition().mirror();
-                    limit = lessThan.getX();
+                    condition = compare.condition().asCondition().mirror();
+                    limit = compare.getX();
                 }
-            } else if (isOutsideLoop(lessThan.getY())) {
-                iv = getInductionVariables().get(lessThan.getX());
+            } else if (isOutsideLoop(compare.getY())) {
+                iv = getInductionVariables().get(compare.getX());
                 if (iv != null) {
-                    condition = lessThan.condition().asCondition();
-                    limit = lessThan.getY();
+                    condition = compare.condition().asCondition();
+                    limit = compare.getY();
                 }
             }
             if (condition == null) {
                 return false;
             }
             if (negated) {
                 condition = condition.negate();
             }
             boolean oneOff = false;
+            boolean unsigned = false;
             switch (condition) {
                 case EQ:
-                    return false;
-                case NE: {
-                    if (!iv.isConstantStride() || Math.abs(iv.constantStride()) != 1) {
+                    if (iv.initNode() == limit) {
+                        // allow "single iteration" case
+                        oneOff = true;
+                    } else {
                         return false;
                     }
+                    break;
+                case NE: {
                     IntegerStamp initStamp = (IntegerStamp) iv.initNode().stamp(NodeView.DEFAULT);
                     IntegerStamp limitStamp = (IntegerStamp) limit.stamp(NodeView.DEFAULT);
+                    IntegerStamp counterStamp = (IntegerStamp) iv.valueNode().stamp(NodeView.DEFAULT);
                     if (iv.direction() == Direction.Up) {
-                        if (initStamp.upperBound() > limitStamp.lowerBound()) {
+                        if (limitStamp.asConstant() != null && limitStamp.asConstant().asLong() == counterStamp.upperBound()) {
+                            // signed: i < MAX_INT
+                        } else if (limitStamp.asConstant() != null && limitStamp.asConstant().asLong() == counterStamp.unsignedUpperBound()) {
+                            unsigned = true;
+                        } else if (!iv.isConstantStride() || Math.abs(iv.constantStride()) != 1 || initStamp.upperBound() > limitStamp.lowerBound()) {
                             return false;
                         }
                     } else if (iv.direction() == Direction.Down) {
-                        if (initStamp.lowerBound() < limitStamp.upperBound()) {
+                        if (limitStamp.asConstant() != null && limitStamp.asConstant().asLong() == counterStamp.lowerBound()) {
+                            // signed: MIN_INT > i
+                        } else if (limitStamp.asConstant() != null && limitStamp.asConstant().asLong() == counterStamp.unsignedLowerBound()) {
+                            unsigned = true;
+                        } else if (!iv.isConstantStride() || Math.abs(iv.constantStride()) != 1 || initStamp.lowerBound() < limitStamp.upperBound()) {
                             return false;
                         }
                     } else {
                         return false;
                     }
                     break;
                 }
+                case BE:
+                    unsigned = true; // fall through
                 case LE:
                     oneOff = true;
                     if (iv.direction() != Direction.Up) {
                         return false;
                     }
                     break;
+                case BT:
+                    unsigned = true; // fall through
                 case LT:
                     if (iv.direction() != Direction.Up) {
                         return false;
                     }
                     break;
+                case AE:
+                    unsigned = true; // fall through
                 case GE:
                     oneOff = true;
                     if (iv.direction() != Direction.Down) {
                         return false;
                     }
                     break;
+                case AT:
+                    unsigned = true; // fall through
                 case GT:
                     if (iv.direction() != Direction.Down) {
                         return false;
                     }
                     break;
                 default:
                     throw GraalError.shouldNotReachHere(condition.toString());
             }
-            counted = new CountedLoopInfo(this, iv, ifNode, limit, oneOff, negated ? ifNode.falseSuccessor() : ifNode.trueSuccessor());
+            counted = new CountedLoopInfo(this, iv, ifNode, limit, oneOff, negated ? ifNode.falseSuccessor() : ifNode.trueSuccessor(), unsigned);
             return true;
         }
         return false;
     }
 
< prev index next >