@@ -747,6 +747,32 @@ public GuardingNode createOverFlowGuard() {
747
747
}
748
748
}
749
749
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
+ */
750
776
public LogicNode createOverflowGuardCondition () {
751
777
StructuredGraph graph = getLimitCheckedIV ().valueNode ().graph ();
752
778
if (counterNeverOverflows ()) {
@@ -757,18 +783,22 @@ public LogicNode createOverflowGuardCondition() {
757
783
LogicNode cond ; // we use a negated guard with a < condition to achieve a >=
758
784
ConstantNode one = ConstantNode .forIntegerStamp (stamp , 1 , graph );
759
785
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 );
763
791
}
764
- cond = graph .addOrUniqueWithInputs (integerHelper .createCompareNode (v1 , getTripCountLimit (), NodeView .DEFAULT ));
792
+ cond = graph .addOrUniqueWithInputs (integerHelper .createCompareNode (maxNonOverflowLimitValue , getTripCountLimit (), NodeView .DEFAULT ));
765
793
} else {
766
794
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 );
770
800
}
771
- cond = graph .addOrUniqueWithInputs (integerHelper .createCompareNode (getTripCountLimit (), v1 , NodeView .DEFAULT ));
801
+ cond = graph .addOrUniqueWithInputs (integerHelper .createCompareNode (getTripCountLimit (), minNonOverflowLimitValue , NodeView .DEFAULT ));
772
802
}
773
803
return cond ;
774
804
}
0 commit comments