Skip to content

Commit 937b46d

Browse files
kittyoracledavleopo
authored andcommitted
[GR-69165] Fix loop limit check guard
PullRequest: graal/22004
2 parents cdcfe38 + 2cc3362 commit 937b46d

File tree

1 file changed

+38
-8
lines changed

1 file changed

+38
-8
lines changed

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

Lines changed: 38 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -747,6 +747,32 @@ 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+
* }
759+
* Most of the time, this loop will execute a limited amount of iterations, and the value of
760+
* {@code i} inside the loop body will be in the interval {@code [0, limit)}. However, in the
761+
* rare cases that {@code limit == Integer.MAX_VALUE}, the addition {@code i += 2} will
762+
* overflow, and the loop would not terminate. In those cases, We cannot treat the loop as a
763+
* counted loop. As a result, we insert a guard for those circumstances. The guard is
764+
* conservative, that is it will catch all cases where the calculation of the induction variable
765+
* overflows, and it may catch cases where the calculation does not actually overflow. In the
766+
* example, the guard would be:
767+
* {@snippet :
768+
* if (limit > Integer.MAX_VALUE - 1) {
769+
* deoptimize();
770+
* }
771+
* }
772+
* This method creates the aforementioned guard, it has the value {@code true} if the
773+
* calculation may overflow, and {@code false} if it cannot, in such cases assumptions about
774+
* counted loops hold.
775+
*/
750776
public LogicNode createOverflowGuardCondition() {
751777
StructuredGraph graph = getLimitCheckedIV().valueNode().graph();
752778
if (counterNeverOverflows()) {
@@ -757,18 +783,22 @@ public LogicNode createOverflowGuardCondition() {
757783
LogicNode cond; // we use a negated guard with a < condition to achieve a >=
758784
ConstantNode one = ConstantNode.forIntegerStamp(stamp, 1, graph);
759785
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);
786+
// overflow ~ (tripCountLimit + stride) overflow ~ tripCountLimit > maxValue - stride
787+
ValueNode maxValue = ConstantNode.forIntegerStamp(stamp, integerHelper.maxValue(), graph);
788+
ValueNode maxNonOverflowLimitValue = BinaryArithmeticNode.sub(graph, maxValue, getLimitCheckedIV().strideNode(), NodeView.DEFAULT);
789+
if (!isLimitIncluded) {
790+
maxNonOverflowLimitValue = BinaryArithmeticNode.add(graph, maxNonOverflowLimitValue, one, NodeView.DEFAULT);
763791
}
764-
cond = graph.addOrUniqueWithInputs(integerHelper.createCompareNode(v1, getTripCountLimit(), NodeView.DEFAULT));
792+
cond = graph.addOrUniqueWithInputs(integerHelper.createCompareNode(maxNonOverflowLimitValue, getTripCountLimit(), NodeView.DEFAULT));
765793
} else {
766794
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);
795+
// overflow ~ (tripCountLimit + stride) overflow ~ tripCountLimit < minValue - stride
796+
ValueNode minValue = ConstantNode.forIntegerStamp(stamp, integerHelper.minValue(), graph);
797+
ValueNode minNonOverflowLimitValue = BinaryArithmeticNode.sub(graph, minValue, getLimitCheckedIV().strideNode(), NodeView.DEFAULT);
798+
if (!isLimitIncluded) {
799+
minNonOverflowLimitValue = BinaryArithmeticNode.sub(graph, minNonOverflowLimitValue, one, NodeView.DEFAULT);
770800
}
771-
cond = graph.addOrUniqueWithInputs(integerHelper.createCompareNode(getTripCountLimit(), v1, NodeView.DEFAULT));
801+
cond = graph.addOrUniqueWithInputs(integerHelper.createCompareNode(getTripCountLimit(), minNonOverflowLimitValue, NodeView.DEFAULT));
772802
}
773803
return cond;
774804
}

0 commit comments

Comments
 (0)