<div dir="ltr">This has been reverted in r252231 to fix a miscompile.  See bug:<div><a href="https://llvm.org/bugs/show_bug.cgi?id=25421">https://llvm.org/bugs/show_bug.cgi?id=25421</a><br></div></div><div class="gmail_extra"><br><div class="gmail_quote">On Thu, Oct 22, 2015 at 12:57 PM, Sanjoy Das via llvm-commits <span dir="ltr"><<a href="mailto:llvm-commits@lists.llvm.org" target="_blank">llvm-commits@lists.llvm.org</a>></span> wrote:<br><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">Author: sanjoy<br>
Date: Thu Oct 22 14:57:29 2015<br>
New Revision: 251050<br>
<br>
URL: <a href="http://llvm.org/viewvc/llvm-project?rev=251050&view=rev" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project?rev=251050&view=rev</a><br>
Log:<br>
[SCEV] Teach SCEV some axioms about non-wrapping arithmetic<br>
<br>
Summary:<br>
 - A s<  (A + C)<nsw> if C >  0<br>
 - A s<= (A + C)<nsw> if C >= 0<br>
 - (A + C)<nsw> s<  A if C <  0<br>
 - (A + C)<nsw> s<= A if C <= 0<br>
<br>
Right now `C` needs to be a constant, but we can later generalize it to<br>
be a non-constant if needed.<br>
<br>
Reviewers: atrick, hfinkel, reames, nlewycky<br>
<br>
Subscribers: sanjoy, llvm-commits<br>
<br>
Differential Revision: <a href="http://reviews.llvm.org/D13686" rel="noreferrer" target="_blank">http://reviews.llvm.org/D13686</a><br>
<br>
Modified:<br>
    llvm/trunk/include/llvm/Analysis/ScalarEvolution.h<br>
    llvm/trunk/lib/Analysis/ScalarEvolution.cpp<br>
    llvm/trunk/test/Transforms/IndVarSimplify/eliminate-comparison.ll<br>
<br>
Modified: llvm/trunk/include/llvm/Analysis/ScalarEvolution.h<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/Analysis/ScalarEvolution.h?rev=251050&r1=251049&r2=251050&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/Analysis/ScalarEvolution.h?rev=251050&r1=251049&r2=251050&view=diff</a><br>
==============================================================================<br>
--- llvm/trunk/include/llvm/Analysis/ScalarEvolution.h (original)<br>
+++ llvm/trunk/include/llvm/Analysis/ScalarEvolution.h Thu Oct 22 14:57:29 2015<br>
@@ -576,6 +576,14 @@ namespace llvm {<br>
     bool isKnownPredicateWithRanges(ICmpInst::Predicate Pred,<br>
                                     const SCEV *LHS, const SCEV *RHS);<br>
<br>
+    /// Try to prove the condition described by "LHS Pred RHS" by ruling out<br>
+    /// integer overflow.<br>
+    ///<br>
+    /// For instance, this will return true for "A s< (A + C)<nsw>" if C is<br>
+    /// positive.<br>
+    bool isKnownPredicateViaNoOverflow(ICmpInst::Predicate Pred,<br>
+                                       const SCEV *LHS, const SCEV *RHS);<br>
+<br>
     /// Try to split Pred LHS RHS into logical conjunctions (and's) and try to<br>
     /// prove them individually.<br>
     bool isKnownPredicateViaSplitting(ICmpInst::Predicate Pred, const SCEV *LHS,<br>
<br>
Modified: llvm/trunk/lib/Analysis/ScalarEvolution.cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Analysis/ScalarEvolution.cpp?rev=251050&r1=251049&r2=251050&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Analysis/ScalarEvolution.cpp?rev=251050&r1=251049&r2=251050&view=diff</a><br>
==============================================================================<br>
--- llvm/trunk/lib/Analysis/ScalarEvolution.cpp (original)<br>
+++ llvm/trunk/lib/Analysis/ScalarEvolution.cpp Thu Oct 22 14:57:29 2015<br>
@@ -7162,6 +7162,60 @@ ScalarEvolution::isKnownPredicateWithRan<br>
   return false;<br>
 }<br>
<br>
+bool ScalarEvolution::isKnownPredicateViaNoOverflow(ICmpInst::Predicate Pred,<br>
+                                                    const SCEV *LHS,<br>
+                                                    const SCEV *RHS) {<br>
+<br>
+  // Match Result to (X + Y)<ExpectedFlags> where Y is a constant integer.<br>
+  // Return Y via OutY.<br>
+  auto MatchBinaryAddToConst =<br>
+      [this](const SCEV *Result, const SCEV *X, APInt &OutY,<br>
+             SCEV::NoWrapFlags ExpectedFlags) {<br>
+    const SCEV *NonConstOp, *ConstOp;<br>
+    SCEV::NoWrapFlags FlagsPresent;<br>
+<br>
+    if (!splitBinaryAdd(Result, ConstOp, NonConstOp, FlagsPresent) ||<br>
+        !isa<SCEVConstant>(ConstOp) || NonConstOp != X)<br>
+      return false;<br>
+<br>
+    OutY = cast<SCEVConstant>(ConstOp)->getValue()->getValue();<br>
+    return (FlagsPresent & ExpectedFlags) != 0;<br>
+  };<br>
+<br>
+  APInt C;<br>
+<br>
+  switch (Pred) {<br>
+  default:<br>
+    break;<br>
+<br>
+  case ICmpInst::ICMP_SGE:<br>
+    std::swap(LHS, RHS);<br>
+  case ICmpInst::ICMP_SLE:<br>
+    // X s<= (X + C)<nsw> if C >= 0<br>
+    if (MatchBinaryAddToConst(RHS, LHS, C, SCEV::FlagNSW) && C.isNonNegative())<br>
+      return true;<br>
+<br>
+    // (X + C)<nsw> s<= X if C <= 0<br>
+    if (MatchBinaryAddToConst(LHS, RHS, C, SCEV::FlagNSW) &&<br>
+        !C.isStrictlyPositive())<br>
+      return true;<br>
+<br>
+  case ICmpInst::ICMP_SGT:<br>
+    std::swap(LHS, RHS);<br>
+  case ICmpInst::ICMP_SLT:<br>
+    // X s< (X + C)<nsw> if C > 0<br>
+    if (MatchBinaryAddToConst(RHS, LHS, C, SCEV::FlagNSW) &&<br>
+        C.isStrictlyPositive())<br>
+      return true;<br>
+<br>
+    // (X + C)<nsw> s< X if C < 0<br>
+    if (MatchBinaryAddToConst(LHS, RHS, C, SCEV::FlagNSW) && C.isNegative())<br>
+      return true;<br>
+  }<br>
+<br>
+  return false;<br>
+}<br>
+<br>
 bool ScalarEvolution::isKnownPredicateViaSplitting(ICmpInst::Predicate Pred,<br>
                                                    const SCEV *LHS,<br>
                                                    const SCEV *RHS) {<br>
@@ -7811,8 +7865,9 @@ ScalarEvolution::isImpliedCondOperandsHe<br>
   auto IsKnownPredicateFull =<br>
       [this](ICmpInst::Predicate Pred, const SCEV *LHS, const SCEV *RHS) {<br>
     return isKnownPredicateWithRanges(Pred, LHS, RHS) ||<br>
-        IsKnownPredicateViaMinOrMax(*this, Pred, LHS, RHS) ||<br>
-        IsKnownPredicateViaAddRecStart(*this, Pred, LHS, RHS);<br>
+           IsKnownPredicateViaMinOrMax(*this, Pred, LHS, RHS) ||<br>
+           IsKnownPredicateViaAddRecStart(*this, Pred, LHS, RHS) ||<br>
+           isKnownPredicateViaNoOverflow(Pred, LHS, RHS);<br>
   };<br>
<br>
   switch (Pred) {<br>
<br>
Modified: llvm/trunk/test/Transforms/IndVarSimplify/eliminate-comparison.ll<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/IndVarSimplify/eliminate-comparison.ll?rev=251050&r1=251049&r2=251050&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/IndVarSimplify/eliminate-comparison.ll?rev=251050&r1=251049&r2=251050&view=diff</a><br>
==============================================================================<br>
--- llvm/trunk/test/Transforms/IndVarSimplify/eliminate-comparison.ll (original)<br>
+++ llvm/trunk/test/Transforms/IndVarSimplify/eliminate-comparison.ll Thu Oct 22 14:57:29 2015<br>
@@ -477,4 +477,63 @@ define void @func_21(i32* %length.ptr, i<br>
   ret void<br>
 }<br>
<br>
+define void @func_22(i32* %length.ptr) {<br>
+; CHECK-LABEL: @func_22(<br>
+<br>
+; This checks that the backedge condition, (I + 1) < Length - 1 implies<br>
+; (I + 1) < Length<br>
+ entry:<br>
+  %length = load i32, i32* %length.ptr, !range !0<br>
+  %lim = sub i32 %length, 1<br>
+  %entry.cond = icmp sgt i32 %length, 1<br>
+  br i1 %entry.cond, label %loop, label %leave<br>
+<br>
+ loop:<br>
+; CHECK: loop:<br>
+  %iv = phi i32 [ 0, %entry ], [ %iv.inc, %be ]<br>
+  %iv.inc = add i32 %iv, 1<br>
+  %range.check = icmp slt i32 %iv, %length<br>
+  br i1 %range.check, label %be, label %leave<br>
+; CHECK:   br i1 true, label %be, label %leave.loopexit<br>
+; CHECK: be:<br>
+<br>
+ be:<br>
+  call void @side_effect()<br>
+  %be.cond = icmp slt i32 %iv.inc, %lim<br>
+  br i1 %be.cond, label %loop, label %leave<br>
+<br>
+ leave:<br>
+  ret void<br>
+}<br>
+<br>
+define void @func_23(i32* %length.ptr) {<br>
+; CHECK-LABEL: @func_23(<br>
+<br>
+; This checks that the backedge condition, (I + 1) < Length - 1 implies<br>
+; (I + 1) < Length<br>
+ entry:<br>
+  %length = load i32, i32* %length.ptr, !range !0<br>
+  %lim = sub i32 %length, 1<br>
+  %entry.cond = icmp sgt i32 %length, 1<br>
+  br i1 %entry.cond, label %loop, label %leave<br>
+<br>
+ loop:<br>
+; CHECK: loop:<br>
+  %iv = phi i32 [ 0, %entry ], [ %iv.inc, %be ]<br>
+  %iv.inc = add i32 %iv, 1<br>
+  %range.check = icmp sle i32 %iv, %length<br>
+  br i1 %range.check, label %be, label %leave<br>
+; CHECK:   br i1 true, label %be, label %leave.loopexit<br>
+; CHECK: be:<br>
+<br>
+ be:<br>
+  call void @side_effect()<br>
+  %be.cond = icmp sle i32 %iv.inc, %lim<br>
+  br i1 %be.cond, label %loop, label %leave<br>
+<br>
+ leave:<br>
+  ret void<br>
+}<br>
+<br>
+<br>
 !0 = !{i32 0, i32 2147483647}<br>
<br>
<br>
_______________________________________________<br>
llvm-commits mailing list<br>
<a href="mailto:llvm-commits@lists.llvm.org">llvm-commits@lists.llvm.org</a><br>
<a href="http://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-commits" rel="noreferrer" target="_blank">http://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-commits</a><br>
</blockquote></div><br></div>