Skip to content

Commit 3c4b6b8

Browse files
kittyoracledavleopo
authored andcommitted
Fix loop limit check guard
1 parent 831b011 commit 3c4b6b8

File tree

1 file changed

+37
-8
lines changed

1 file changed

+37
-8
lines changed

compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/nodes/loop/CountedLoopInfo.java

Lines changed: 37 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -747,6 +747,31 @@ public GuardingNode createOverFlowGuard() {
747747
}
748748
}
749749

750+
/**
751+
* Creates an overflow guard condition, that is the condition such that if it is satisfied, the
752+
* induction variable will overflow, and we have to treat the loop as a non-counted one.
753+
* <p>
754+
* For example, given this loop:
755+
* {@snippet :
756+
* for (int i = 0; i < limit; i += 2) {}
757+
* }
758+
* Most of the time, this loop will execute a limited amount of iterations, and the value of
759+
* {@code i} inside the loop body will be in the interval {@code [0, limit)}. However, in the
760+
* rare cases that {@code limit == Integer.MAX_VALUE}, the addition {@code i += 2} will
761+
* overflow, and the loop would not terminate. In those cases, We cannot treat the loop as a
762+
* counted loop. As a result, we insert a guard for those circumstances. The guard is
763+
* conservative, that is it will catch all cases where the calculation of the induction variable
764+
* overflows, and it may catch cases where the calculation does not actually overflow. In the
765+
* example, the guard would be:
766+
* {@snippet :
767+
* if (limit > Integer.MAX_VALUE - 1) {
768+
* deoptimize();
769+
* }
770+
* }
771+
* This method creates the aforementioned guard, it has the value {@code true} if the
772+
* calculation may overflow, and {@code false} if it cannot, in such cases assumptions about
773+
* counted loops hold.
774+
*/
750775
public LogicNode createOverflowGuardCondition() {
751776
StructuredGraph graph = getLimitCheckedIV().valueNode().graph();
752777
if (counterNeverOverflows()) {
@@ -757,18 +782,22 @@ public LogicNode createOverflowGuardCondition() {
757782
LogicNode cond; // we use a negated guard with a < condition to achieve a >=
758783
ConstantNode one = ConstantNode.forIntegerStamp(stamp, 1, graph);
759784
if (getLimitCheckedIV().direction() == InductionVariable.Direction.Up) {
760-
ValueNode v1 = BinaryArithmeticNode.sub(ConstantNode.forIntegerStamp(stamp, integerHelper.maxValue()), BinaryArithmeticNode.sub(getLimitCheckedIV().strideNode(), one));
761-
if (isLimitIncluded) {
762-
v1 = BinaryArithmeticNode.sub(v1, one);
785+
// overflow ~ (tripCountLimit + stride) overflow ~ tripCountLimit > maxValue - stride
786+
ValueNode maxValue = ConstantNode.forIntegerStamp(stamp, integerHelper.maxValue(), graph);
787+
ValueNode maxNonOverflowLimitValue = BinaryArithmeticNode.sub(graph, maxValue, getLimitCheckedIV().strideNode(), NodeView.DEFAULT);
788+
if (!isLimitIncluded) {
789+
maxNonOverflowLimitValue = BinaryArithmeticNode.add(graph, maxNonOverflowLimitValue, one, NodeView.DEFAULT);
763790
}
764-
cond = graph.addOrUniqueWithInputs(integerHelper.createCompareNode(v1, getTripCountLimit(), NodeView.DEFAULT));
791+
cond = graph.addOrUniqueWithInputs(integerHelper.createCompareNode(maxNonOverflowLimitValue, getTripCountLimit(), NodeView.DEFAULT));
765792
} else {
766793
assert getLimitCheckedIV().direction() == Direction.Down : Assertions.errorMessage(getLimitCheckedIV());
767-
ValueNode v1 = BinaryArithmeticNode.add(ConstantNode.forIntegerStamp(stamp, integerHelper.minValue()), BinaryArithmeticNode.sub(one, getLimitCheckedIV().strideNode()));
768-
if (isLimitIncluded) {
769-
v1 = BinaryArithmeticNode.add(v1, one);
794+
// overflow ~ (tripCountLimit + stride) overflow ~ tripCountLimit < minValue - stride
795+
ValueNode minValue = ConstantNode.forIntegerStamp(stamp, integerHelper.minValue(), graph);
796+
ValueNode minNonOverflowLimitValue = BinaryArithmeticNode.sub(graph, minValue, getLimitCheckedIV().strideNode(), NodeView.DEFAULT);
797+
if (!isLimitIncluded) {
798+
minNonOverflowLimitValue = BinaryArithmeticNode.sub(graph, minNonOverflowLimitValue, one, NodeView.DEFAULT);
770799
}
771-
cond = graph.addOrUniqueWithInputs(integerHelper.createCompareNode(getTripCountLimit(), v1, NodeView.DEFAULT));
800+
cond = graph.addOrUniqueWithInputs(integerHelper.createCompareNode(getTripCountLimit(), minNonOverflowLimitValue, NodeView.DEFAULT));
772801
}
773802
return cond;
774803
}

0 commit comments

Comments
 (0)