@@ -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