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