<div dir="rtl"><div dir="ltr">Since && has higher precedence than ||, should the assert</div><div dir="ltr"><br></div><div dir="ltr"><font face="monospace, monospace"><span style="font-size:12.8000001907349px">assert(!(RCKind & InductiveRangeCheck::RANGE_</span><span style="font-size:12.8000001907349px">CHECK_UPPER) ||</span><br style="font-size:12.8000001907349px"><span style="font-size:12.8000001907349px">         Length && "</span><span class="" style="font-size:12.8000001907349px;background-color:rgb(255,255,255)">contract</span><span style="font-size:12.8000001907349px"> </span><span class="" style="font-size:12.8000001907349px;background-color:rgb(255,255,255)">with</span><span style="font-size:12.8000001907349px"> </span><span class="" style="font-size:12.8000001907349px;background-color:rgb(255,255,255)">SplitRangeCheckCondition</span><span style="font-size:12.8000001907349px">!");</span><br></font></div><div dir="ltr"><span style="font-size:12.8000001907349px"><br></span></div><div dir="ltr"><span style="font-size:12.8000001907349px">actually be</span></div><div dir="ltr"><span style="font-size:12.8000001907349px"><br></span></div><div dir="ltr"><font face="monospace, monospace"><span style="font-size:12.8000001907349px">assert((!(RCKind & InductiveRangeCheck::RANGE_</span><span style="font-size:12.8000001907349px">CHECK_UPPER) ||</span><br style="font-size:12.8000001907349px"><span style="font-size:12.8000001907349px">         Length) && "</span><span class="" style="font-size:12.8000001907349px;background-color:rgb(255,255,255)">contract</span><span style="font-size:12.8000001907349px"> </span><span class="" style="font-size:12.8000001907349px;background-color:rgb(255,255,255)">with</span><span style="font-size:12.8000001907349px"> </span><span class="" style="font-size:12.8000001907349px;background-color:rgb(255,255,255)">SplitRangeCheckCondition</span><span style="font-size:12.8000001907349px">!");</span></font><span style="font-size:12.8000001907349px"><br></span></div><div dir="ltr"><div dir="ltr"><br></div><div><span style="font-size:12.8000001907349px"><br></span></div></div></div><div class="gmail_extra"><br><div class="gmail_quote"><div dir="ltr">2015-03-17 2:42 GMT+02:00 Sanjoy Das <span dir="ltr"><<a href="mailto:sanjoy@playingwithpointers.com" target="_blank">sanjoy@playingwithpointers.com</a>></span>:</div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">Author: sanjoy<br>
Date: Mon Mar 16 19:42:13 2015<br>
New Revision: 232444<br>
<br>
URL: <a href="http://llvm.org/viewvc/llvm-project?rev=232444&view=rev" target="_blank">http://llvm.org/viewvc/llvm-project?rev=232444&view=rev</a><br>
Log:<br>
[IRCE] Support half-range checks.<br>
<br>
This change to IRCE gets it to recognize "half" range checks.  Half<br>
range checks are range checks that only either check if the index is<br>
`slt` some positive integer ("length") or if the index is `sge` `0`.<br>
<br>
The range solver does not try to be clever / aggressive about solving<br>
half-range checks -- it transforms "I < L" to "0 <= I < L" and "0 <= I"<br>
to "0 <= I < INT_SMAX".  This is safe, but not always optimal.<br>
<br>
Added:<br>
    llvm/trunk/test/Transforms/IRCE/only-lower-check.ll<br>
    llvm/trunk/test/Transforms/IRCE/only-upper-check.ll<br>
Modified:<br>
    llvm/trunk/lib/Transforms/Scalar/InductiveRangeCheckElimination.cpp<br>
<br>
Modified: llvm/trunk/lib/Transforms/Scalar/InductiveRangeCheckElimination.cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Transforms/Scalar/InductiveRangeCheckElimination.cpp?rev=232444&r1=232443&r2=232444&view=diff" target="_blank">http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Transforms/Scalar/InductiveRangeCheckElimination.cpp?rev=232444&r1=232443&r2=232444&view=diff</a><br>
==============================================================================<br>
--- llvm/trunk/lib/Transforms/Scalar/InductiveRangeCheckElimination.cpp (original)<br>
+++ llvm/trunk/lib/Transforms/Scalar/InductiveRangeCheckElimination.cpp Mon Mar 16 19:42:13 2015<br>
@@ -96,23 +96,40 @@ namespace {<br>
 ///<br>
 ///  and<br>
 ///<br>
-///  2. a condition that is provably true for some range of values taken by the<br>
-///     containing loop's induction variable.<br>
+///  2. a condition that is provably true for some contiguous range of values<br>
+///     taken by the containing loop's induction variable.<br>
 ///<br>
-/// Currently all inductive range checks are branches conditional on an<br>
-/// expression of the form<br>
-///<br>
-///   0 <= (Offset + Scale * I) < Length<br>
-///<br>
-/// where `I' is the canonical induction variable of a loop to which Offset and<br>
-/// Scale are loop invariant, and Length is >= 0.  Currently the 'false' branch<br>
-/// is considered cold, looking at profiling data to verify that is a TODO.<br>
-<br>
 class InductiveRangeCheck {<br>
+  // Classifies a range check<br>
+  enum RangeCheckKind {<br>
+    // Range check of the form "0 <= I".<br>
+    RANGE_CHECK_LOWER = 1,<br>
+<br>
+    // Range check of the form "I < L" where L is known positive.<br>
+    RANGE_CHECK_UPPER = 2,<br>
+<br>
+    // The logical and of the RANGE_CHECK_LOWER and RANGE_CHECK_UPPER<br>
+    // conditions.<br>
+    RANGE_CHECK_BOTH = RANGE_CHECK_LOWER | RANGE_CHECK_UPPER,<br>
+<br>
+    // Unrecognized range check condition.<br>
+    RANGE_CHECK_UNKNOWN = (unsigned)-1<br>
+  };<br>
+<br>
+  static const char *rangeCheckKindToStr(RangeCheckKind);<br>
+<br>
   const SCEV *Offset;<br>
   const SCEV *Scale;<br>
   Value *Length;<br>
   BranchInst *Branch;<br>
+  RangeCheckKind Kind;<br>
+<br>
+  static RangeCheckKind parseRangeCheckICmp(ICmpInst *ICI, ScalarEvolution &SE,<br>
+                                            Value *&Index, Value *&Length);<br>
+<br>
+  static InductiveRangeCheck::RangeCheckKind<br>
+  parseRangeCheck(Loop *L, ScalarEvolution &SE, Value *Condition,<br>
+                  const SCEV *&Index, Value *&UpperLimit);<br>
<br>
   InductiveRangeCheck() :<br>
     Offset(nullptr), Scale(nullptr), Length(nullptr), Branch(nullptr) { }<br>
@@ -124,13 +141,17 @@ public:<br>
<br>
   void print(raw_ostream &OS) const {<br>
     OS << "InductiveRangeCheck:\n";<br>
+    OS << "  Kind: " << rangeCheckKindToStr(Kind) << "\n";<br>
     OS << "  Offset: ";<br>
     Offset->print(OS);<br>
     OS << "  Scale: ";<br>
     Scale->print(OS);<br>
     OS << "  Length: ";<br>
-    Length->print(OS);<br>
-    OS << "  Branch: ";<br>
+    if (Length)<br>
+      Length->print(OS);<br>
+    else<br>
+      OS << "(null)";<br>
+    OS << "\n  Branch: ";<br>
     getBranch()->print(OS);<br>
     OS << "\n";<br>
   }<br>
@@ -207,160 +228,146 @@ char InductiveRangeCheckElimination::ID<br>
 INITIALIZE_PASS(InductiveRangeCheckElimination, "irce",<br>
                 "Inductive range check elimination", false, false)<br>
<br>
-static bool IsLowerBoundCheck(Value *Check, Value *&IndexV) {<br>
-  using namespace llvm::PatternMatch;<br>
+const char *InductiveRangeCheck::rangeCheckKindToStr(<br>
+    InductiveRangeCheck::RangeCheckKind RCK) {<br>
+  switch (RCK) {<br>
+  case InductiveRangeCheck::RANGE_CHECK_UNKNOWN:<br>
+    return "RANGE_CHECK_UNKNOWN";<br>
<br>
-  ICmpInst::Predicate Pred = ICmpInst::BAD_ICMP_PREDICATE;<br>
-  Value *LHS = nullptr, *RHS = nullptr;<br>
+  case InductiveRangeCheck::RANGE_CHECK_UPPER:<br>
+    return "RANGE_CHECK_UPPER";<br>
<br>
-  if (!match(Check, m_ICmp(Pred, m_Value(LHS), m_Value(RHS))))<br>
-    return false;<br>
+  case InductiveRangeCheck::RANGE_CHECK_LOWER:<br>
+    return "RANGE_CHECK_LOWER";<br>
+<br>
+  case InductiveRangeCheck::RANGE_CHECK_BOTH:<br>
+    return "RANGE_CHECK_BOTH";<br>
+  }<br>
+<br>
+  llvm_unreachable("unknown range check type!");<br>
+}<br>
+<br>
+/// Parse a single ICmp instruction, `ICI`, into a range check.  If `ICI`<br>
+/// cannot<br>
+/// be interpreted as a range check, return `RANGE_CHECK_UNKNOWN` and set<br>
+/// `Index` and `Length` to `nullptr`.  Otherwise set `Index` to the value<br>
+/// being<br>
+/// range checked, and set `Length` to the upper limit `Index` is being range<br>
+/// checked with if (and only if) the range check type is stronger or equal to<br>
+/// RANGE_CHECK_UPPER.<br>
+///<br>
+InductiveRangeCheck::RangeCheckKind<br>
+InductiveRangeCheck::parseRangeCheckICmp(ICmpInst *ICI, ScalarEvolution &SE,<br>
+                                         Value *&Index, Value *&Length) {<br>
+<br>
+  using namespace llvm::PatternMatch;<br>
+<br>
+  ICmpInst::Predicate Pred = ICI->getPredicate();<br>
+  Value *LHS = ICI->getOperand(0);<br>
+  Value *RHS = ICI->getOperand(1);<br>
<br>
   switch (Pred) {<br>
   default:<br>
-    return false;<br>
+    return RANGE_CHECK_UNKNOWN;<br>
<br>
   case ICmpInst::ICMP_SLE:<br>
     std::swap(LHS, RHS);<br>
   // fallthrough<br>
   case ICmpInst::ICMP_SGE:<br>
-    if (!match(RHS, m_ConstantInt<0>()))<br>
-      return false;<br>
-    IndexV = LHS;<br>
-    return true;<br>
+    if (match(RHS, m_ConstantInt<0>())) {<br>
+      Index = LHS;<br>
+      return RANGE_CHECK_LOWER;<br>
+    }<br>
+    return RANGE_CHECK_UNKNOWN;<br>
<br>
   case ICmpInst::ICMP_SLT:<br>
     std::swap(LHS, RHS);<br>
   // fallthrough<br>
   case ICmpInst::ICMP_SGT:<br>
-    if (!match(RHS, m_ConstantInt<-1>()))<br>
-      return false;<br>
-    IndexV = LHS;<br>
-    return true;<br>
-  }<br>
-}<br>
-<br>
-static bool IsUpperBoundCheck(Value *Check, Value *Index, Value *&UpperLimit) {<br>
-  using namespace llvm::PatternMatch;<br>
-<br>
-  ICmpInst::Predicate Pred = ICmpInst::BAD_ICMP_PREDICATE;<br>
-  Value *LHS = nullptr, *RHS = nullptr;<br>
-<br>
-  if (!match(Check, m_ICmp(Pred, m_Value(LHS), m_Value(RHS))))<br>
-    return false;<br>
+    if (match(RHS, m_ConstantInt<-1>())) {<br>
+      Index = LHS;<br>
+      return RANGE_CHECK_LOWER;<br>
+    }<br>
<br>
-  switch (Pred) {<br>
-  default:<br>
-    return false;<br>
+    if (SE.isKnownNonNegative(SE.getSCEV(LHS))) {<br>
+      Index = RHS;<br>
+      Length = LHS;<br>
+      return RANGE_CHECK_UPPER;<br>
+    }<br>
+    return RANGE_CHECK_UNKNOWN;<br>
<br>
-  case ICmpInst::ICMP_SGT:<br>
+  case ICmpInst::ICMP_ULT:<br>
     std::swap(LHS, RHS);<br>
   // fallthrough<br>
-  case ICmpInst::ICMP_SLT:<br>
-    if (LHS != Index)<br>
-      return false;<br>
-    UpperLimit = RHS;<br>
-    return true;<br>
-<br>
   case ICmpInst::ICMP_UGT:<br>
-    std::swap(LHS, RHS);<br>
-  // fallthrough<br>
-  case ICmpInst::ICMP_ULT:<br>
-    if (LHS != Index)<br>
-      return false;<br>
-    UpperLimit = RHS;<br>
-    return true;<br>
+    if (SE.isKnownNonNegative(SE.getSCEV(LHS))) {<br>
+      Index = RHS;<br>
+      Length = LHS;<br>
+      return RANGE_CHECK_BOTH;<br>
+    }<br>
+    return RANGE_CHECK_UNKNOWN;<br>
   }<br>
+<br>
+  llvm_unreachable("default clause returns!");<br>
 }<br>
<br>
-/// Split a condition into something semantically equivalent to (0 <= I <<br>
-/// Limit), both comparisons signed and Len loop invariant on L and positive.<br>
-/// On success, return true and set Index to I and UpperLimit to Limit.  Return<br>
-/// false on failure (we may still write to UpperLimit and Index on failure).<br>
-/// It does not try to interpret I as a loop index.<br>
-///<br>
-static bool SplitRangeCheckCondition(Loop *L, ScalarEvolution &SE,<br>
+/// Parses an arbitrary condition into a range check.  `Length` is set only if<br>
+/// the range check is recognized to be `RANGE_CHECK_UPPER` or stronger.<br>
+InductiveRangeCheck::RangeCheckKind<br>
+InductiveRangeCheck::parseRangeCheck(Loop *L, ScalarEvolution &SE,<br>
                                      Value *Condition, const SCEV *&Index,<br>
-                                     Value *&UpperLimit) {<br>
-<br>
-  // TODO: currently this catches some silly cases like comparing "%idx slt 1".<br>
-  // Our transformations are still correct, but less likely to be profitable in<br>
-  // those cases.  We have to come up with some heuristics that pick out the<br>
-  // range checks that are more profitable to clone a loop for.  This function<br>
-  // in general can be made more robust.<br>
-<br>
+                                     Value *&Length) {<br>
   using namespace llvm::PatternMatch;<br>
<br>
   Value *A = nullptr;<br>
   Value *B = nullptr;<br>
-  ICmpInst::Predicate Pred = ICmpInst::BAD_ICMP_PREDICATE;<br>
-<br>
-  // In these early checks we assume that the matched UpperLimit is positive.<br>
-  // We'll verify that fact later, before returning true.<br>
<br>
   if (match(Condition, m_And(m_Value(A), m_Value(B)))) {<br>
-    Value *IndexV = nullptr;<br>
-    Value *ExpectedUpperBoundCheck = nullptr;<br>
+    Value *IndexA = nullptr, *IndexB = nullptr;<br>
+    Value *LengthA = nullptr, *LengthB = nullptr;<br>
+    ICmpInst *ICmpA = dyn_cast<ICmpInst>(A), *ICmpB = dyn_cast<ICmpInst>(B);<br>
<br>
-    if (IsLowerBoundCheck(A, IndexV))<br>
-      ExpectedUpperBoundCheck = B;<br>
-    else if (IsLowerBoundCheck(B, IndexV))<br>
-      ExpectedUpperBoundCheck = A;<br>
-    else<br>
-      return false;<br>
+    if (!ICmpA || !ICmpB)<br>
+      return InductiveRangeCheck::RANGE_CHECK_UNKNOWN;<br>
<br>
-    if (!IsUpperBoundCheck(ExpectedUpperBoundCheck, IndexV, UpperLimit))<br>
-      return false;<br>
+    auto RCKindA = parseRangeCheckICmp(ICmpA, SE, IndexA, LengthA);<br>
+    auto RCKindB = parseRangeCheckICmp(ICmpB, SE, IndexB, LengthB);<br>
<br>
-    Index = SE.getSCEV(IndexV);<br>
+    if (RCKindA == InductiveRangeCheck::RANGE_CHECK_UNKNOWN ||<br>
+        RCKindB == InductiveRangeCheck::RANGE_CHECK_UNKNOWN)<br>
+      return InductiveRangeCheck::RANGE_CHECK_UNKNOWN;<br>
<br>
-    if (isa<SCEVCouldNotCompute>(Index))<br>
-      return false;<br>
+    if (IndexA != IndexB)<br>
+      return InductiveRangeCheck::RANGE_CHECK_UNKNOWN;<br>
<br>
-  } else if (match(Condition, m_ICmp(Pred, m_Value(A), m_Value(B)))) {<br>
-    switch (Pred) {<br>
-    default:<br>
-      return false;<br>
+    if (LengthA != nullptr && LengthB != nullptr && LengthA != LengthB)<br>
+      return InductiveRangeCheck::RANGE_CHECK_UNKNOWN;<br>
<br>
-    case ICmpInst::ICMP_SGT:<br>
-      std::swap(A, B);<br>
-    // fall through<br>
-    case ICmpInst::ICMP_SLT:<br>
-      UpperLimit = B;<br>
-      Index = SE.getSCEV(A);<br>
-      if (isa<SCEVCouldNotCompute>(Index) || !SE.isKnownNonNegative(Index))<br>
-        return false;<br>
-      break;<br>
+    Index = SE.getSCEV(IndexA);<br>
+    if (isa<SCEVCouldNotCompute>(Index))<br>
+      return InductiveRangeCheck::RANGE_CHECK_UNKNOWN;<br>
<br>
-    case ICmpInst::ICMP_UGT:<br>
-      std::swap(A, B);<br>
-    // fall through<br>
-    case ICmpInst::ICMP_ULT:<br>
-      UpperLimit = B;<br>
-      Index = SE.getSCEV(A);<br>
-      if (isa<SCEVCouldNotCompute>(Index))<br>
-        return false;<br>
-      break;<br>
-    }<br>
-  } else {<br>
-    return false;<br>
+    Length = LengthA == nullptr ? LengthB : LengthA;<br>
+<br>
+    return (InductiveRangeCheck::RangeCheckKind)(RCKindA | RCKindB);<br>
   }<br>
<br>
-  const SCEV *UpperLimitSCEV = SE.getSCEV(UpperLimit);<br>
-  if (isa<SCEVCouldNotCompute>(UpperLimitSCEV) ||<br>
-      !SE.isKnownNonNegative(UpperLimitSCEV))<br>
-    return false;<br>
+  if (ICmpInst *ICI = dyn_cast<ICmpInst>(Condition)) {<br>
+    Value *IndexVal = nullptr;<br>
<br>
-  if (SE.getLoopDisposition(UpperLimitSCEV, L) !=<br>
-      ScalarEvolution::LoopInvariant) {<br>
-    DEBUG(dbgs() << " in function: " << L->getHeader()->getParent()->getName()<br>
-                 << " ";<br>
-          dbgs() << " UpperLimit is not loop invariant: "<br>
-                 << UpperLimit->getName() << "\n";);<br>
-    return false;<br>
+    auto RCKind = parseRangeCheckICmp(ICI, SE, IndexVal, Length);<br>
+<br>
+    if (RCKind == InductiveRangeCheck::RANGE_CHECK_UNKNOWN)<br>
+      return InductiveRangeCheck::RANGE_CHECK_UNKNOWN;<br>
+<br>
+    Index = SE.getSCEV(IndexVal);<br>
+    if (isa<SCEVCouldNotCompute>(Index))<br>
+      return InductiveRangeCheck::RANGE_CHECK_UNKNOWN;<br>
+<br>
+    return RCKind;<br>
   }<br>
<br>
-  return true;<br>
+  return InductiveRangeCheck::RANGE_CHECK_UNKNOWN;<br>
 }<br>
<br>
<br>
@@ -380,10 +387,15 @@ InductiveRangeCheck::create(InductiveRan<br>
   Value *Length = nullptr;<br>
   const SCEV *IndexSCEV = nullptr;<br>
<br>
-  if (!SplitRangeCheckCondition(L, SE, BI->getCondition(), IndexSCEV, Length))<br>
+  auto RCKind = InductiveRangeCheck::parseRangeCheck(L, SE, BI->getCondition(),<br>
+                                                     IndexSCEV, Length);<br>
+<br>
+  if (RCKind == InductiveRangeCheck::RANGE_CHECK_UNKNOWN)<br>
     return nullptr;<br>
<br>
-  assert(IndexSCEV && Length && "contract with SplitRangeCheckCondition!");<br>
+  assert(IndexSCEV && "contract with SplitRangeCheckCondition!");<br>
+  assert(!(RCKind & InductiveRangeCheck::RANGE_CHECK_UPPER) ||<br>
+         Length && "contract with SplitRangeCheckCondition!");<br>
<br>
   const SCEVAddRecExpr *IndexAddRec = dyn_cast<SCEVAddRecExpr>(IndexSCEV);<br>
   bool IsAffineIndex =<br>
@@ -397,6 +409,7 @@ InductiveRangeCheck::create(InductiveRan<br>
   IRC->Offset = IndexAddRec->getStart();<br>
   IRC->Scale = IndexAddRec->getStepRecurrence(SE);<br>
   IRC->Branch = BI;<br>
+  IRC->Kind = RCKind;<br>
   return IRC;<br>
 }<br>
<br>
@@ -1294,8 +1307,19 @@ InductiveRangeCheck::computeSafeIteratio<br>
   const SCEV *M = SE.getMinusSCEV(C, A);<br>
<br>
   const SCEV *Begin = SE.getNegativeSCEV(M);<br>
-  const SCEV *End = SE.getMinusSCEV(SE.getSCEV(getLength()), M);<br>
+  const SCEV *UpperLimit = nullptr;<br>
+<br>
+  // We strengthen "0 <= I" to "0 <= I < INT_SMAX" and "I < L" to "0 <= I < L".<br>
+  // We can potentially do much better here.<br>
+  if (Value *V = getLength()) {<br>
+    UpperLimit = SE.getSCEV(V);<br>
+  } else {<br>
+    assert(Kind == InductiveRangeCheck::RANGE_CHECK_LOWER && "invariant!");<br>
+    unsigned BitWidth = cast<IntegerType>(IndVar->getType())->getBitWidth();<br>
+    UpperLimit = SE.getConstant(APInt::getSignedMaxValue(BitWidth));<br>
+  }<br>
<br>
+  const SCEV *End = SE.getMinusSCEV(UpperLimit, M);<br>
   return InductiveRangeCheck::Range(Begin, End);<br>
 }<br>
<br>
<br>
Added: llvm/trunk/test/Transforms/IRCE/only-lower-check.ll<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/IRCE/only-lower-check.ll?rev=232444&view=auto" target="_blank">http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/IRCE/only-lower-check.ll?rev=232444&view=auto</a><br>
==============================================================================<br>
--- llvm/trunk/test/Transforms/IRCE/only-lower-check.ll (added)<br>
+++ llvm/trunk/test/Transforms/IRCE/only-lower-check.ll Mon Mar 16 19:42:13 2015<br>
@@ -0,0 +1,37 @@<br>
+; RUN: opt -debug-only=irce -irce < %s 2>&1 | FileCheck %s<br>
+<br>
+; CHECK: irce: loop has 1 inductive range checks:<br>
+; CHECK-NEXT: InductiveRangeCheck:<br>
+; CHECK-NEXT:   Kind: RANGE_CHECK_LOWER<br>
+; CHECK-NEXT:   Offset: (-1 + %n)  Scale: -1  Length: (null)<br>
+; CHECK-NEXT:   Branch:   br i1 %abc, label %in.bounds, label %out.of.bounds<br>
+; CHECK-NEXT: irce: in function only_lower_check: constrained Loop at depth 1 containing: %loop<header><exiting>,%in.bounds<latch><exiting><br>
+<br>
+define void @only_lower_check(i32 *%arr, i32 *%a_len_ptr, i32 %n) {<br>
+ entry:<br>
+  %len = load i32, i32* %a_len_ptr, !range !0<br>
+  %first.itr.check = icmp sgt i32 %n, 0<br>
+  %start = sub i32 %n, 1<br>
+  br i1 %first.itr.check, label %loop, label %exit<br>
+<br>
+ loop:<br>
+  %idx = phi i32 [ %start, %entry ] , [ %idx.dec, %in.bounds ]<br>
+  %idx.dec = sub i32 %idx, 1<br>
+  %abc = icmp sge i32 %idx, 0<br>
+  br i1 %abc, label %in.bounds, label %out.of.bounds, !prof !1<br>
+<br>
+ in.bounds:<br>
+  %addr = getelementptr i32, i32* %arr, i32 %idx<br>
+  store i32 0, i32* %addr<br>
+  %next = icmp sgt i32 %idx.dec, -1<br>
+  br i1 %next, label %loop, label %exit<br>
+<br>
+ out.of.bounds:<br>
+  ret void<br>
+<br>
+ exit:<br>
+  ret void<br>
+}<br>
+<br>
+!0 = !{i32 0, i32 2147483647}<br>
+!1 = !{!"branch_weights", i32 64, i32 4}<br>
<br>
Added: llvm/trunk/test/Transforms/IRCE/only-upper-check.ll<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/IRCE/only-upper-check.ll?rev=232444&view=auto" target="_blank">http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/IRCE/only-upper-check.ll?rev=232444&view=auto</a><br>
==============================================================================<br>
--- llvm/trunk/test/Transforms/IRCE/only-upper-check.ll (added)<br>
+++ llvm/trunk/test/Transforms/IRCE/only-upper-check.ll Mon Mar 16 19:42:13 2015<br>
@@ -0,0 +1,37 @@<br>
+; RUN: opt -irce -debug-only=irce %s -S 2>&1 | FileCheck %s<br>
+<br>
+; CHECK: irce: loop has 1 inductive range checks:<br>
+; CHECK-NEXT:InductiveRangeCheck:<br>
+; CHECK-NEXT:  Kind: RANGE_CHECK_UPPER<br>
+; CHECK-NEXT:  Offset: %offset  Scale: 1  Length:   %len = load i32, i32* %a_len_ptr, !range !0<br>
+; CHECK-NEXT:  Branch:   br i1 %abc, label %in.bounds, label %out.of.bounds, !prof !1<br>
+; CHECK-NEXT: irce: in function incrementing: constrained Loop at depth 1 containing: %loop<header><exiting>,%in.bounds<latch><exiting><br>
+<br>
+define void @incrementing(i32 *%arr, i32 *%a_len_ptr, i32 %n, i32 %offset) {<br>
+ entry:<br>
+  %len = load i32, i32* %a_len_ptr, !range !0<br>
+  %first.itr.check = icmp sgt i32 %n, 0<br>
+  br i1 %first.itr.check, label %loop, label %exit<br>
+<br>
+ loop:<br>
+  %idx = phi i32 [ 0, %entry ] , [ %idx.next, %in.bounds ]<br>
+  %idx.next = add i32 %idx, 1<br>
+  %array.idx = add i32 %idx, %offset<br>
+  %abc = icmp slt i32 %array.idx, %len<br>
+  br i1 %abc, label %in.bounds, label %out.of.bounds, !prof !1<br>
+<br>
+ in.bounds:<br>
+  %addr = getelementptr i32, i32* %arr, i32 %array.idx<br>
+  store i32 0, i32* %addr<br>
+  %next = icmp slt i32 %idx.next, %n<br>
+  br i1 %next, label %loop, label %exit<br>
+<br>
+ out.of.bounds:<br>
+  ret void<br>
+<br>
+ exit:<br>
+  ret void<br>
+}<br>
+<br>
+!0 = !{i32 0, i32 2147483647}<br>
+!1 = !{!"branch_weights", i32 64, i32 4}<br>
<br>
<br>
_______________________________________________<br>
llvm-commits mailing list<br>
<a href="mailto:llvm-commits@cs.uiuc.edu">llvm-commits@cs.uiuc.edu</a><br>
<a href="http://lists.cs.uiuc.edu/mailman/listinfo/llvm-commits" target="_blank">http://lists.cs.uiuc.edu/mailman/listinfo/llvm-commits</a><br>
</blockquote></div><br></div>