[llvm] r361517 - [LOOPINFO] Extend Loop object to add utilities to get the loop bounds, step, induction variable, and guard branch.

Florian Hahn via llvm-commits llvm-commits at lists.llvm.org
Thu May 23 11:11:18 PDT 2019


It looks like the commit message is out-of-sync with the patch, the guard handling is not part of the patch. Also, the patch on Phabricator had some outstanding comments, which might would have been good to address before committing IMO.

Cheers,
Florian

> On May 23, 2019, at 18:56, Kit Barton via llvm-commits <llvm-commits at lists.llvm.org> wrote:
> 
> Author: kbarton
> Date: Thu May 23 10:56:35 2019
> New Revision: 361517
> 
> URL: http://llvm.org/viewvc/llvm-project?rev=361517&view=rev
> Log:
>    [LOOPINFO] Extend Loop object to add utilities to get the loop bounds, step, induction variable, and guard branch.
> 
>    Summary:
>    This PR extends the loop object with more utilities to get loop bounds, step, induction variable, and guard branch. There already exists passes which try to obtain the loop induction variable in their own pass, e.g. loop interchange. It would be useful to have a common area to get these information. Moreover, loop fusion (https://reviews.llvm.org/D55851) is planning to use getGuard() to extend the kind of loops it is able to fuse, e.g. rotated loop with non-constant upper bound, which would have a loop guard.
> 
>      /// Example:
>      /// for (int i = lb; i < ub; i+=step)
>      ///   <loop body>
>      /// --- pseudo LLVMIR ---
>      /// beforeloop:
>      ///   guardcmp = (lb < ub)
>      ///   if (guardcmp) goto preheader; else goto afterloop
>      /// preheader:
>      /// loop:
>      ///   i1 = phi[{lb, preheader}, {i2, latch}]
>      ///   <loop body>
>      ///   i2 = i1 + step
>      /// latch:
>      ///   cmp = (i2 < ub)
>      ///   if (cmp) goto loop
>      /// exit:
>      /// afterloop:
>      ///
>      /// getBounds
>      ///   getInitialIVValue      --> lb
>      ///   getStepInst            --> i2 = i1 + step
>      ///   getStepValue           --> step
>      ///   getFinalIVValue        --> ub
>      ///   getCanonicalPredicate  --> '<'
>      ///   getDirection           --> Increasing
>      /// getGuard             --> if (guardcmp) goto loop; else goto afterloop
>      /// getInductionVariable          --> i1
>      /// getAuxiliaryInductionVariable --> {i1}
>      /// isCanonical                   --> false
> 
>    Committed on behalf of @Whitney (Whitney Tsang).
> 
>    Reviewers: kbarton, hfinkel, dmgreen, Meinersbur, jdoerfert, syzaara, fhahn
> 
>    Reviewed By: kbarton
> 
>    Subscribers: tvvikram, bmahjour, etiotto, fhahn, jsji, hiraditya, llvm-commits
> 
>    Tags: #llvm
> 
>    Differential Revision: https://reviews.llvm.org/D60565
> 
> Modified:
>    llvm/trunk/include/llvm/Analysis/LoopInfo.h
>    llvm/trunk/lib/Analysis/LoopInfo.cpp
>    llvm/trunk/lib/Transforms/Scalar/LoopInterchange.cpp
>    llvm/trunk/unittests/Analysis/LoopInfoTest.cpp
> 
> Modified: llvm/trunk/include/llvm/Analysis/LoopInfo.h
> URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/Analysis/LoopInfo.h?rev=361517&r1=361516&r2=361517&view=diff
> ==============================================================================
> --- llvm/trunk/include/llvm/Analysis/LoopInfo.h (original)
> +++ llvm/trunk/include/llvm/Analysis/LoopInfo.h Thu May 23 10:56:35 2019
> @@ -54,9 +54,12 @@ namespace llvm {
> class DominatorTree;
> class LoopInfo;
> class Loop;
> +class InductionDescriptor;
> class MDNode;
> class MemorySSAUpdater;
> class PHINode;
> +class PostDominatorTree;
> +class ScalarEvolution;
> class raw_ostream;
> template <class N, bool IsPostDom> class DominatorTreeBase;
> template <class N, class M> class LoopInfoBase;
> @@ -529,6 +532,165 @@ public:
>   bool getIncomingAndBackEdge(BasicBlock *&Incoming,
>                               BasicBlock *&Backedge) const;
> 
> +  /// Below are some utilities to get loop bounds and induction variable, and
> +  /// check if a given phinode is an auxiliary induction variable, as well as
> +  /// checking if the loop is canonical.
> +  ///
> +  /// Here is an example:
> +  /// \code
> +  /// for (int i = lb; i < ub; i+=step)
> +  ///   <loop body>
> +  /// --- pseudo LLVMIR ---
> +  /// beforeloop:
> +  ///   guardcmp = (lb < ub)
> +  ///   if (guardcmp) goto preheader; else goto afterloop
> +  /// preheader:
> +  /// loop:
> +  ///   i_1 = phi[{lb, preheader}, {i_2, latch}]
> +  ///   <loop body>
> +  ///   i_2 = i_1 + step
> +  /// latch:
> +  ///   cmp = (i_2 < ub)
> +  ///   if (cmp) goto loop
> +  /// exit:
> +  /// afterloop:
> +  /// \endcode
> +  ///
> +  /// - getBounds
> +  ///   - getInitialIVValue      --> lb
> +  ///   - getStepInst            --> i_2 = i_1 + step
> +  ///   - getStepValue           --> step
> +  ///   - getFinalIVValue        --> ub
> +  ///   - getCanonicalPredicate  --> '<'
> +  ///   - getDirection           --> Increasing
> +  ///
> +  /// - getInductionVariable            --> i_1
> +  /// - isAuxiliaryInductionVariable(x) --> true if x == i_1
> +  /// - isCanonical                     --> false
> +  struct LoopBounds {
> +    /// Return the LoopBounds object if
> +    /// - the given \p IndVar is an induction variable
> +    /// - the initial value of the induction variable can be found
> +    /// - the step instruction of the induction variable can be found
> +    /// - the final value of the induction variable can be found
> +    ///
> +    /// Else None.
> +    static Optional<Loop::LoopBounds> getBounds(const Loop &L, PHINode &IndVar,
> +                                                ScalarEvolution &SE);
> +
> +    /// Get the initial value of the loop induction variable.
> +    Value &getInitialIVValue() const { return InitialIVValue; }
> +
> +    /// Get the instruction that updates the loop induction variable.
> +    Instruction &getStepInst() const { return StepInst; }
> +
> +    /// Get the step that the loop induction variable gets updated by in each
> +    /// loop iteration. Return nullptr if not found.
> +    Value *getStepValue() const { return StepValue; }
> +
> +    /// Get the final value of the loop induction variable.
> +    Value &getFinalIVValue() const { return FinalIVValue; }
> +
> +    /// Return the canonical predicate for the latch compare instruction, if
> +    /// able to be calcuated. Else BAD_ICMP_PREDICATE.
> +    ///
> +    /// A predicate is considered as canonical if requirements below are all
> +    /// satisfied:
> +    /// 1. The first successor of the latch branch is the loop header
> +    ///    If not, inverse the predicate.
> +    /// 2. One of the operands of the latch comparison is StepInst
> +    ///    If not, and
> +    ///    - if the current calcuated predicate is not ne or eq, flip the
> +    ///      predicate.
> +    ///    - else if the loop is increasing, return slt
> +    ///      (notice that it is safe to change from ne or eq to sign compare)
> +    ///    - else if the loop is decreasing, return sgt
> +    ///      (notice that it is safe to change from ne or eq to sign compare)
> +    ///
> +    /// Here is an example when both (1) and (2) are not satisfied:
> +    /// \code
> +    /// loop.header:
> +    ///  %iv = phi [%initialiv, %loop.preheader], [%inc, %loop.header]
> +    ///  %inc = add %iv, %step
> +    ///  %cmp = slt %iv, %finaliv
> +    ///  br %cmp, %loop.exit, %loop.header
> +    /// loop.exit:
> +    /// \endcode
> +    /// - The second successor of the latch branch is the loop header instead
> +    ///   of the first successor (slt -> sge)
> +    /// - The first operand of the latch comparison (%cmp) is the IndVar (%iv)
> +    ///   instead of the StepInst (%inc) (sge -> sgt)
> +    ///
> +    /// The predicate would be sgt if both (1) and (2) are satisfied.
> +    /// getCanonicalPredicate() returns sgt for this example.
> +    /// Note: The IR is not changed.
> +    ICmpInst::Predicate getCanonicalPredicate() const;
> +
> +    /// An enum for the direction of the loop
> +    /// - for (int i = 0; i < ub; ++i)  --> Increasing
> +    /// - for (int i = ub; i > 0; --i)  --> Descresing
> +    /// - for (int i = x; i != y; i+=z) --> Unknown
> +    enum class Direction { Increasing, Decreasing, Unknown };
> +
> +    /// Get the direction of the loop.
> +    Direction getDirection() const;
> +
> +  private:
> +    LoopBounds(const Loop &Loop, Value &I, Instruction &SI, Value *SV, Value &F,
> +               ScalarEvolution &SE)
> +        : L(Loop), InitialIVValue(I), StepInst(SI), StepValue(SV),
> +          FinalIVValue(F), SE(SE) {}
> +
> +    const Loop &L;
> +
> +    // The initial value of the loop induction variable
> +    Value &InitialIVValue;
> +
> +    // The instruction that updates the loop induction variable
> +    Instruction &StepInst;
> +
> +    // The value that the loop induction variable gets updated by in each loop
> +    // iteration
> +    Value *StepValue;
> +
> +    // The final value of the loop induction variable
> +    Value &FinalIVValue;
> +
> +    ScalarEvolution &SE;
> +  };
> +
> +  /// Return the struct LoopBounds collected if all struct members are found,
> +  /// else None.
> +  Optional<LoopBounds> getBounds(ScalarEvolution &SE) const;
> +
> +  /// Return the loop induction variable if found, else return nullptr.
> +  /// An instruction is considered as the loop induction variable if
> +  /// - it is an induction variable of the loop; and
> +  /// - it is used to determine the condition of the branch in the loop latch
> +  ///
> +  /// Note: the induction variable doesn't need to be canonical, i.e. starts at
> +  /// zero and increments by one each time through the loop (but it can be).
> +  PHINode *getInductionVariable(ScalarEvolution &SE) const;
> +
> +  /// Get the loop induction descriptor for the loop induction variable. Return
> +  /// true if the loop induction variable is found.
> +  bool getInductionDescriptor(ScalarEvolution &SE,
> +                              InductionDescriptor &IndDesc) const;
> +
> +  /// Return true if the given PHINode \p AuxIndVar is
> +  /// - in the loop header
> +  /// - not used outside of the loop
> +  /// - incremented by a loop invariant step for each loop iteration
> +  /// - step instruction opcode should be add or sub
> +  /// Note: auxiliary induction variable is not required to be used in the
> +  ///       conditional branch in the loop latch. (but it can be)
> +  bool isAuxiliaryInductionVariable(PHINode &AuxIndVar,
> +                                    ScalarEvolution &SE) const;
> +
> +  /// Return true if the loop induction variable starts at zero and increments
> +  /// by one each time through the loop.
> +  bool isCanonical(ScalarEvolution &SE) const;
> +
>   /// Return true if the Loop is in LCSSA form.
>   bool isLCSSAForm(DominatorTree &DT) const;
> 
> 
> Modified: llvm/trunk/lib/Analysis/LoopInfo.cpp
> URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Analysis/LoopInfo.cpp?rev=361517&r1=361516&r2=361517&view=diff
> ==============================================================================
> --- llvm/trunk/lib/Analysis/LoopInfo.cpp (original)
> +++ llvm/trunk/lib/Analysis/LoopInfo.cpp Thu May 23 10:56:35 2019
> @@ -17,10 +17,13 @@
> #include "llvm/ADT/DepthFirstIterator.h"
> #include "llvm/ADT/ScopeExit.h"
> #include "llvm/ADT/SmallPtrSet.h"
> +#include "llvm/Analysis/IVDescriptors.h"
> #include "llvm/Analysis/LoopInfoImpl.h"
> #include "llvm/Analysis/LoopIterator.h"
> #include "llvm/Analysis/MemorySSA.h"
> #include "llvm/Analysis/MemorySSAUpdater.h"
> +#include "llvm/Analysis/PostDominators.h"
> +#include "llvm/Analysis/ScalarEvolutionExpressions.h"
> #include "llvm/Analysis/ValueTracking.h"
> #include "llvm/Config/llvm-config.h"
> #include "llvm/IR/CFG.h"
> @@ -164,6 +167,249 @@ PHINode *Loop::getCanonicalInductionVari
>   return nullptr;
> }
> 
> +/// Return true if V1 and V2 have the same value ignoring bit width.
> +static bool isEqualIgnoreBitwidth(Value &V1, Value &V2, ScalarEvolution &SE) {
> +  const SCEV *S1 = SE.getSCEV(&V1);
> +  const SCEV *S2 = SE.getSCEV(&V2);
> +  Type *WiderType = SE.getWiderType(S1->getType(), S2->getType());
> +  S1 = SE.getNoopOrAnyExtend(S1, WiderType);
> +  S2 = SE.getNoopOrAnyExtend(S2, WiderType);
> +  return SE.getMinusSCEV(S1, S2)->isZero();
> +}
> +
> +/// Get the latch condition instruction.
> +static ICmpInst *getLatchCmpInst(const Loop &L) {
> +  if (BasicBlock *Latch = L.getLoopLatch())
> +    if (BranchInst *BI = dyn_cast_or_null<BranchInst>(Latch->getTerminator()))
> +      if (BI->isConditional())
> +        return dyn_cast<ICmpInst>(BI->getCondition());
> +
> +  return nullptr;
> +}
> +
> +/// Return the final value of the loop induction variable if found.
> +static Value *findFinalIVValue(const Loop &L, const PHINode &IndVar,
> +                               const Instruction &StepInst) {
> +  ICmpInst *LatchCmpInst = getLatchCmpInst(L);
> +  if (!LatchCmpInst)
> +    return nullptr;
> +
> +  Value *Op0 = LatchCmpInst->getOperand(0);
> +  Value *Op1 = LatchCmpInst->getOperand(1);
> +  if (Op0 == &IndVar || Op0 == &StepInst)
> +    return Op1;
> +
> +  if (Op1 == &IndVar || Op1 == &StepInst)
> +    return Op0;
> +
> +  return nullptr;
> +}
> +
> +Optional<Loop::LoopBounds> Loop::LoopBounds::getBounds(const Loop &L,
> +                                                       PHINode &IndVar,
> +                                                       ScalarEvolution &SE) {
> +  InductionDescriptor IndDesc;
> +  if (!InductionDescriptor::isInductionPHI(&IndVar, &L, &SE, IndDesc))
> +    return None;
> +
> +  Value *InitialIVValue = IndDesc.getStartValue();
> +  Instruction *StepInst = IndDesc.getInductionBinOp();
> +  if (!InitialIVValue || !StepInst)
> +    return None;
> +
> +  const SCEV *Step = IndDesc.getStep();
> +  Value *StepInstOp1 = StepInst->getOperand(1);
> +  Value *StepInstOp0 = StepInst->getOperand(0);
> +  Value *StepValue = nullptr;
> +  if (SE.getSCEV(StepInstOp1) == Step)
> +    StepValue = StepInstOp1;
> +  else if (SE.getSCEV(StepInstOp0) == Step)
> +    StepValue = StepInstOp0;
> +
> +  Value *FinalIVValue = findFinalIVValue(L, IndVar, *StepInst);
> +  if (!FinalIVValue)
> +    return None;
> +
> +  return LoopBounds(L, *InitialIVValue, *StepInst, StepValue, *FinalIVValue,
> +                    SE);
> +}
> +
> +using Direction = Loop::LoopBounds::Direction;
> +
> +ICmpInst::Predicate Loop::LoopBounds::getCanonicalPredicate() const {
> +  BasicBlock *Latch = L.getLoopLatch();
> +  assert(Latch && "Expecting valid latch");
> +
> +  BranchInst *BI = dyn_cast_or_null<BranchInst>(Latch->getTerminator());
> +  assert(BI && BI->isConditional() && "Expecting conditional latch branch");
> +
> +  ICmpInst *LatchCmpInst = dyn_cast<ICmpInst>(BI->getCondition());
> +  assert(LatchCmpInst &&
> +         "Expecting the latch compare instruction to be a CmpInst");
> +
> +  // Need to inverse the predicate when first successor is not the loop
> +  // header
> +  ICmpInst::Predicate Pred = (BI->getSuccessor(0) == L.getHeader())
> +                                 ? LatchCmpInst->getPredicate()
> +                                 : LatchCmpInst->getInversePredicate();
> +
> +  if (LatchCmpInst->getOperand(0) == &getFinalIVValue())
> +    Pred = ICmpInst::getSwappedPredicate(Pred);
> +
> +  // Need to flip strictness of the predicate when the latch compare instruction
> +  // is not using StepInst
> +  if (LatchCmpInst->getOperand(0) == &getStepInst() ||
> +      LatchCmpInst->getOperand(1) == &getStepInst())
> +    return Pred;
> +
> +  // Cannot flip strictness of NE and EQ
> +  if (Pred != ICmpInst::ICMP_NE && Pred != ICmpInst::ICMP_EQ)
> +    return ICmpInst::getFlippedStrictnessPredicate(Pred);
> +
> +  Direction D = getDirection();
> +  if (D == Direction::Increasing)
> +    return ICmpInst::ICMP_SLT;
> +
> +  if (D == Direction::Decreasing)
> +    return ICmpInst::ICMP_SGT;
> +
> +  // If cannot determine the direction, then unable to find the canonical
> +  // predicate
> +  return ICmpInst::BAD_ICMP_PREDICATE;
> +}
> +
> +Direction Loop::LoopBounds::getDirection() const {
> +  if (const SCEVAddRecExpr *StepAddRecExpr =
> +          dyn_cast<SCEVAddRecExpr>(SE.getSCEV(&getStepInst())))
> +    if (const SCEV *StepRecur = StepAddRecExpr->getStepRecurrence(SE)) {
> +      if (SE.isKnownPositive(StepRecur))
> +        return Direction::Increasing;
> +      if (SE.isKnownNegative(StepRecur))
> +        return Direction::Decreasing;
> +    }
> +
> +  return Direction::Unknown;
> +}
> +
> +Optional<Loop::LoopBounds> Loop::getBounds(ScalarEvolution &SE) const {
> +  if (PHINode *IndVar = getInductionVariable(SE))
> +    return LoopBounds::getBounds(*this, *IndVar, SE);
> +
> +  return None;
> +}
> +
> +PHINode *Loop::getInductionVariable(ScalarEvolution &SE) const {
> +  if (!isLoopSimplifyForm())
> +    return nullptr;
> +
> +  BasicBlock *Header = getHeader();
> +  assert(Header && "Expected a valid loop header");
> +  BasicBlock *Latch = getLoopLatch();
> +  assert(Latch && "Expected a valid loop latch");
> +  ICmpInst *CmpInst = getLatchCmpInst(*this);
> +  if (!CmpInst)
> +    return nullptr;
> +
> +  // case 1:
> +  // IndVar = phi[{InitialValue, preheader}, {StepInst, latch}]
> +  // StepInst = IndVar + step
> +  // cmp = StepInst < FinalValue
> +  Instruction *LatchCmpOp0 = dyn_cast<Instruction>(CmpInst->getOperand(0));
> +  Instruction *LatchCmpOp1 = dyn_cast<Instruction>(CmpInst->getOperand(1));
> +  // Loop over all of the PHI nodes in loop header, store the PHI node that has
> +  // incoming value from latch equals to the StepInst
> +  BinaryOperator *StepInst = nullptr;
> +  PHINode *IndVar = nullptr;
> +  for (PHINode &PN : Header->phis()) {
> +    Value *IncomingValue = PN.getIncomingValueForBlock(Latch);
> +    assert(IncomingValue && "Expecting valid incoming value from latch");
> +    if (IncomingValue == LatchCmpOp0 || IncomingValue == LatchCmpOp1) {
> +      IndVar = &PN;
> +      StepInst = dyn_cast<BinaryOperator>(IncomingValue);
> +      if (StepInst)
> +        if (isEqualIgnoreBitwidth(*StepInst->getOperand(0), *IndVar, SE) ||
> +            isEqualIgnoreBitwidth(*StepInst->getOperand(1), *IndVar, SE))
> +          return IndVar;
> +    }
> +  }
> +
> +  // case 2:
> +  // IndVar = phi[{InitialValue, preheader}, {StepInst, latch}]
> +  // StepInst = IndVar + step
> +  // cmp = IndVar < FinalValue
> +  for (Value *Op : CmpInst->operands()) {
> +    PHINode *IndVar = dyn_cast<PHINode>(Op);
> +    if (!IndVar)
> +      continue;
> +
> +    if (IndVar->getParent() != Header)
> +      continue;
> +
> +    Value *IncomingValue = IndVar->getIncomingValueForBlock(Latch);
> +    assert(IncomingValue && "Expecting valid incoming value from latch");
> +    StepInst = dyn_cast<BinaryOperator>(IncomingValue);
> +    if (StepInst)
> +      if (StepInst->getOperand(0) == IndVar ||
> +          StepInst->getOperand(1) == IndVar)
> +        return IndVar;
> +  }
> +
> +  return nullptr;
> +}
> +
> +bool Loop::getInductionDescriptor(ScalarEvolution &SE,
> +                                  InductionDescriptor &IndDesc) const {
> +  if (PHINode *IndVar = getInductionVariable(SE))
> +    return InductionDescriptor::isInductionPHI(IndVar, this, &SE, IndDesc);
> +
> +  return false;
> +}
> +
> +bool Loop::isAuxiliaryInductionVariable(PHINode &AuxIndVar,
> +                                        ScalarEvolution &SE) const {
> +  // Located in the loop header
> +  BasicBlock *Header = getHeader();
> +  if (AuxIndVar.getParent() != Header)
> +    return false;
> +
> +  // No uses outside of the loop
> +  for (User *U : AuxIndVar.users())
> +    if (const Instruction *I = dyn_cast<Instruction>(U))
> +      if (!contains(I))
> +        return false;
> +
> +  InductionDescriptor IndDesc;
> +  if (!InductionDescriptor::isInductionPHI(&AuxIndVar, this, &SE, IndDesc))
> +    return false;
> +
> +  // The step instruction opcode should be add or sub.
> +  if (IndDesc.getInductionOpcode() != Instruction::Add &&
> +      IndDesc.getInductionOpcode() != Instruction::Sub)
> +    return false;
> +
> +  // Incremented by a loop invariant step for each loop iteration
> +  return SE.isLoopInvariant(IndDesc.getStep(), this);
> +}
> +
> +bool Loop::isCanonical(ScalarEvolution &SE) const {
> +  InductionDescriptor IndDesc;
> +  if (!getInductionDescriptor(SE, IndDesc))
> +    return false;
> +
> +  ConstantInt *Init = dyn_cast_or_null<ConstantInt>(IndDesc.getStartValue());
> +  if (!Init || !Init->isZero())
> +    return false;
> +
> +  if (IndDesc.getInductionOpcode() != Instruction::Add)
> +    return false;
> +
> +  ConstantInt *Step = IndDesc.getConstIntStepValue();
> +  if (!Step || !Step->isOne())
> +    return false;
> +
> +  return true;
> +}
> +
> // Check that 'BB' doesn't have any uses outside of the 'L'
> static bool isBlockInLCSSAForm(const Loop &L, const BasicBlock &BB,
>                                DominatorTree &DT) {
> 
> Modified: llvm/trunk/lib/Transforms/Scalar/LoopInterchange.cpp
> URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Transforms/Scalar/LoopInterchange.cpp?rev=361517&r1=361516&r2=361517&view=diff
> ==============================================================================
> --- llvm/trunk/lib/Transforms/Scalar/LoopInterchange.cpp (original)
> +++ llvm/trunk/lib/Transforms/Scalar/LoopInterchange.cpp Thu May 23 10:56:35 2019
> @@ -292,33 +292,6 @@ static LoopVector populateWorklist(Loop
>   return LoopList;
> }
> 
> -static PHINode *getInductionVariable(Loop *L, ScalarEvolution *SE) {
> -  PHINode *InnerIndexVar = L->getCanonicalInductionVariable();
> -  if (InnerIndexVar)
> -    return InnerIndexVar;
> -  if (L->getLoopLatch() == nullptr || L->getLoopPredecessor() == nullptr)
> -    return nullptr;
> -  for (BasicBlock::iterator I = L->getHeader()->begin(); isa<PHINode>(I); ++I) {
> -    PHINode *PhiVar = cast<PHINode>(I);
> -    Type *PhiTy = PhiVar->getType();
> -    if (!PhiTy->isIntegerTy() && !PhiTy->isFloatingPointTy() &&
> -        !PhiTy->isPointerTy())
> -      return nullptr;
> -    const SCEVAddRecExpr *AddRec =
> -        dyn_cast<SCEVAddRecExpr>(SE->getSCEV(PhiVar));
> -    if (!AddRec || !AddRec->isAffine())
> -      continue;
> -    const SCEV *Step = AddRec->getStepRecurrence(*SE);
> -    if (!isa<SCEVConstant>(Step))
> -      continue;
> -    // Found the induction variable.
> -    // FIXME: Handle loops with more than one induction variable. Note that,
> -    // currently, legality makes sure we have only one induction variable.
> -    return PhiVar;
> -  }
> -  return nullptr;
> -}
> -
> namespace {
> 
> /// LoopInterchangeLegality checks if it is legal to interchange the loop.
> @@ -1227,7 +1200,7 @@ bool LoopInterchangeTransform::transform
>   if (InnerLoop->getSubLoops().empty()) {
>     BasicBlock *InnerLoopPreHeader = InnerLoop->getLoopPreheader();
>     LLVM_DEBUG(dbgs() << "Calling Split Inner Loop\n");
> -    PHINode *InductionPHI = getInductionVariable(InnerLoop, SE);
> +    PHINode *InductionPHI = InnerLoop->getInductionVariable(*SE);
>     if (!InductionPHI) {
>       LLVM_DEBUG(dbgs() << "Failed to find the point to split loop latch \n");
>       return false;
> 
> Modified: llvm/trunk/unittests/Analysis/LoopInfoTest.cpp
> URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/unittests/Analysis/LoopInfoTest.cpp?rev=361517&r1=361516&r2=361517&view=diff
> ==============================================================================
> --- llvm/trunk/unittests/Analysis/LoopInfoTest.cpp (original)
> +++ llvm/trunk/unittests/Analysis/LoopInfoTest.cpp Thu May 23 10:56:35 2019
> @@ -7,6 +7,10 @@
> //===----------------------------------------------------------------------===//
> 
> #include "llvm/Analysis/LoopInfo.h"
> +#include "llvm/Analysis/AssumptionCache.h"
> +#include "llvm/Analysis/PostDominators.h"
> +#include "llvm/Analysis/ScalarEvolution.h"
> +#include "llvm/Analysis/TargetLibraryInfo.h"
> #include "llvm/AsmParser/Parser.h"
> #include "llvm/IR/Dominators.h"
> #include "llvm/Support/SourceMgr.h"
> @@ -26,6 +30,26 @@ runWithLoopInfo(Module &M, StringRef Fun
>   Test(*F, LI);
> }
> 
> +/// Build the loop info and scalar evolution for the function and run the Test.
> +static void runWithLoopInfoPlus(
> +    Module &M, StringRef FuncName,
> +    function_ref<void(Function &F, LoopInfo &LI, ScalarEvolution &SE,
> +                      PostDominatorTree &PDT)>
> +        Test) {
> +  auto *F = M.getFunction(FuncName);
> +  ASSERT_NE(F, nullptr) << "Could not find " << FuncName;
> +
> +  TargetLibraryInfoImpl TLII;
> +  TargetLibraryInfo TLI(TLII);
> +  AssumptionCache AC(*F);
> +  DominatorTree DT(*F);
> +  LoopInfo LI(DT);
> +  ScalarEvolution SE(*F, TLI, AC, DT, LI);
> +
> +  PostDominatorTree PDT(*F);
> +  Test(*F, LI, SE, PDT);
> +}
> +
> static std::unique_ptr<Module> makeLLVMModule(LLVMContext &Context,
>                                               const char *ModuleStr) {
>   SMDiagnostic Err;
> @@ -210,3 +234,879 @@ TEST(LoopInfoTest, PreorderTraversals) {
>   EXPECT_EQ(&L_0_1, ReverseSiblingPreorder[6]);
>   EXPECT_EQ(&L_0_0, ReverseSiblingPreorder[7]);
> }
> +
> +TEST(LoopInfoTest, CanonicalLoop) {
> +  const char *ModuleStr =
> +      "define void @foo(i32* %A, i32 %ub) {\n"
> +      "entry:\n"
> +      "  %guardcmp = icmp slt i32 0, %ub\n"
> +      "  br i1 %guardcmp, label %for.preheader, label %for.end\n"
> +      "for.preheader:\n"
> +      "  br label %for.body\n"
> +      "for.body:\n"
> +      "  %i = phi i32 [ 0, %for.preheader ], [ %inc, %for.body ]\n"
> +      "  %idxprom = sext i32 %i to i64\n"
> +      "  %arrayidx = getelementptr inbounds i32, i32* %A, i64 %idxprom\n"
> +      "  store i32 %i, i32* %arrayidx, align 4\n"
> +      "  %inc = add nsw i32 %i, 1\n"
> +      "  %cmp = icmp slt i32 %inc, %ub\n"
> +      "  br i1 %cmp, label %for.body, label %for.exit\n"
> +      "for.exit:\n"
> +      "  br label %for.end\n"
> +      "for.end:\n"
> +      "  ret void\n"
> +      "}\n";
> +
> +  // Parse the module.
> +  LLVMContext Context;
> +  std::unique_ptr<Module> M = makeLLVMModule(Context, ModuleStr);
> +
> +  runWithLoopInfoPlus(
> +      *M, "foo",
> +      [&](Function &F, LoopInfo &LI, ScalarEvolution &SE,
> +          PostDominatorTree &PDT) {
> +        Function::iterator FI = F.begin();
> +        // First two basic block are entry and for.preheader - skip them.
> +        ++FI;
> +        BasicBlock *Header = &*(++FI);
> +        assert(Header->getName() == "for.body");
> +        Loop *L = LI.getLoopFor(Header);
> +        EXPECT_NE(L, nullptr);
> +
> +        Optional<Loop::LoopBounds> Bounds = L->getBounds(SE);
> +        EXPECT_NE(Bounds, None);
> +        ConstantInt *InitialIVValue =
> +            dyn_cast<ConstantInt>(&Bounds->getInitialIVValue());
> +        EXPECT_TRUE(InitialIVValue && InitialIVValue->isZero());
> +        EXPECT_EQ(Bounds->getStepInst().getName(), "inc");
> +        ConstantInt *StepValue =
> +            dyn_cast_or_null<ConstantInt>(Bounds->getStepValue());
> +        EXPECT_TRUE(StepValue && StepValue->isOne());
> +        EXPECT_EQ(Bounds->getFinalIVValue().getName(), "ub");
> +        EXPECT_EQ(Bounds->getCanonicalPredicate(), ICmpInst::ICMP_SLT);
> +        EXPECT_EQ(Bounds->getDirection(),
> +                  Loop::LoopBounds::Direction::Increasing);
> +        EXPECT_EQ(L->getInductionVariable(SE)->getName(), "i");
> +      });
> +}
> +
> +TEST(LoopInfoTest, LoopWithInverseGuardSuccs) {
> +  const char *ModuleStr =
> +      "define void @foo(i32* %A, i32 %ub) {\n"
> +      "entry:\n"
> +      "  %guardcmp = icmp sge i32 0, %ub\n"
> +      "  br i1 %guardcmp, label %for.end, label %for.preheader\n"
> +      "for.preheader:\n"
> +      "  br label %for.body\n"
> +      "for.body:\n"
> +      "  %i = phi i32 [ 0, %for.preheader ], [ %inc, %for.body ]\n"
> +      "  %idxprom = sext i32 %i to i64\n"
> +      "  %arrayidx = getelementptr inbounds i32, i32* %A, i64 %idxprom\n"
> +      "  store i32 %i, i32* %arrayidx, align 4\n"
> +      "  %inc = add nsw i32 %i, 1\n"
> +      "  %cmp = icmp slt i32 %inc, %ub\n"
> +      "  br i1 %cmp, label %for.body, label %for.exit\n"
> +      "for.exit:\n"
> +      "  br label %for.end\n"
> +      "for.end:\n"
> +      "  ret void\n"
> +      "}\n";
> +
> +  // Parse the module.
> +  LLVMContext Context;
> +  std::unique_ptr<Module> M = makeLLVMModule(Context, ModuleStr);
> +
> +  runWithLoopInfoPlus(
> +      *M, "foo",
> +      [&](Function &F, LoopInfo &LI, ScalarEvolution &SE,
> +          PostDominatorTree &PDT) {
> +        Function::iterator FI = F.begin();
> +        // First two basic block are entry and for.preheader - skip them.
> +        ++FI;
> +        BasicBlock *Header = &*(++FI);
> +        assert(Header->getName() == "for.body");
> +        Loop *L = LI.getLoopFor(Header);
> +        EXPECT_NE(L, nullptr);
> +
> +        Optional<Loop::LoopBounds> Bounds = L->getBounds(SE);
> +        EXPECT_NE(Bounds, None);
> +        ConstantInt *InitialIVValue =
> +            dyn_cast<ConstantInt>(&Bounds->getInitialIVValue());
> +        EXPECT_TRUE(InitialIVValue && InitialIVValue->isZero());
> +        EXPECT_EQ(Bounds->getStepInst().getName(), "inc");
> +        ConstantInt *StepValue =
> +            dyn_cast_or_null<ConstantInt>(Bounds->getStepValue());
> +        EXPECT_TRUE(StepValue && StepValue->isOne());
> +        EXPECT_EQ(Bounds->getFinalIVValue().getName(), "ub");
> +        EXPECT_EQ(Bounds->getCanonicalPredicate(), ICmpInst::ICMP_SLT);
> +        EXPECT_EQ(Bounds->getDirection(),
> +                  Loop::LoopBounds::Direction::Increasing);
> +        EXPECT_EQ(L->getInductionVariable(SE)->getName(), "i");
> +      });
> +}
> +
> +TEST(LoopInfoTest, LoopWithSwappedGuardCmp) {
> +  const char *ModuleStr =
> +      "define void @foo(i32* %A, i32 %ub) {\n"
> +      "entry:\n"
> +      "  %guardcmp = icmp sgt i32 %ub, 0\n"
> +      "  br i1 %guardcmp, label %for.preheader, label %for.end\n"
> +      "for.preheader:\n"
> +      "  br label %for.body\n"
> +      "for.body:\n"
> +      "  %i = phi i32 [ 0, %for.preheader ], [ %inc, %for.body ]\n"
> +      "  %idxprom = sext i32 %i to i64\n"
> +      "  %arrayidx = getelementptr inbounds i32, i32* %A, i64 %idxprom\n"
> +      "  store i32 %i, i32* %arrayidx, align 4\n"
> +      "  %inc = add nsw i32 %i, 1\n"
> +      "  %cmp = icmp sge i32 %inc, %ub\n"
> +      "  br i1 %cmp, label %for.exit, label %for.body\n"
> +      "for.exit:\n"
> +      "  br label %for.end\n"
> +      "for.end:\n"
> +      "  ret void\n"
> +      "}\n";
> +
> +  // Parse the module.
> +  LLVMContext Context;
> +  std::unique_ptr<Module> M = makeLLVMModule(Context, ModuleStr);
> +
> +  runWithLoopInfoPlus(
> +      *M, "foo",
> +      [&](Function &F, LoopInfo &LI, ScalarEvolution &SE,
> +          PostDominatorTree &PDT) {
> +        Function::iterator FI = F.begin();
> +        // First two basic block are entry and for.preheader - skip them.
> +        ++FI;
> +        BasicBlock *Header = &*(++FI);
> +        assert(Header->getName() == "for.body");
> +        Loop *L = LI.getLoopFor(Header);
> +        EXPECT_NE(L, nullptr);
> +
> +        Optional<Loop::LoopBounds> Bounds = L->getBounds(SE);
> +        EXPECT_NE(Bounds, None);
> +        ConstantInt *InitialIVValue =
> +            dyn_cast<ConstantInt>(&Bounds->getInitialIVValue());
> +        EXPECT_TRUE(InitialIVValue && InitialIVValue->isZero());
> +        EXPECT_EQ(Bounds->getStepInst().getName(), "inc");
> +        ConstantInt *StepValue =
> +            dyn_cast_or_null<ConstantInt>(Bounds->getStepValue());
> +        EXPECT_TRUE(StepValue && StepValue->isOne());
> +        EXPECT_EQ(Bounds->getFinalIVValue().getName(), "ub");
> +        EXPECT_EQ(Bounds->getCanonicalPredicate(), ICmpInst::ICMP_SLT);
> +        EXPECT_EQ(Bounds->getDirection(),
> +                  Loop::LoopBounds::Direction::Increasing);
> +        EXPECT_EQ(L->getInductionVariable(SE)->getName(), "i");
> +      });
> +}
> +
> +TEST(LoopInfoTest, LoopWithInverseLatchSuccs) {
> +  const char *ModuleStr =
> +      "define void @foo(i32* %A, i32 %ub) {\n"
> +      "entry:\n"
> +      "  %guardcmp = icmp slt i32 0, %ub\n"
> +      "  br i1 %guardcmp, label %for.preheader, label %for.end\n"
> +      "for.preheader:\n"
> +      "  br label %for.body\n"
> +      "for.body:\n"
> +      "  %i = phi i32 [ 0, %for.preheader ], [ %inc, %for.body ]\n"
> +      "  %idxprom = sext i32 %i to i64\n"
> +      "  %arrayidx = getelementptr inbounds i32, i32* %A, i64 %idxprom\n"
> +      "  store i32 %i, i32* %arrayidx, align 4\n"
> +      "  %inc = add nsw i32 %i, 1\n"
> +      "  %cmp = icmp sge i32 %inc, %ub\n"
> +      "  br i1 %cmp, label %for.exit, label %for.body\n"
> +      "for.exit:\n"
> +      "  br label %for.end\n"
> +      "for.end:\n"
> +      "  ret void\n"
> +      "}\n";
> +
> +  // Parse the module.
> +  LLVMContext Context;
> +  std::unique_ptr<Module> M = makeLLVMModule(Context, ModuleStr);
> +
> +  runWithLoopInfoPlus(
> +      *M, "foo",
> +      [&](Function &F, LoopInfo &LI, ScalarEvolution &SE,
> +          PostDominatorTree &PDT) {
> +        Function::iterator FI = F.begin();
> +        // First two basic block are entry and for.preheader - skip them.
> +        ++FI;
> +        BasicBlock *Header = &*(++FI);
> +        assert(Header->getName() == "for.body");
> +        Loop *L = LI.getLoopFor(Header);
> +        EXPECT_NE(L, nullptr);
> +
> +        Optional<Loop::LoopBounds> Bounds = L->getBounds(SE);
> +        EXPECT_NE(Bounds, None);
> +        ConstantInt *InitialIVValue =
> +            dyn_cast<ConstantInt>(&Bounds->getInitialIVValue());
> +        EXPECT_TRUE(InitialIVValue && InitialIVValue->isZero());
> +        EXPECT_EQ(Bounds->getStepInst().getName(), "inc");
> +        ConstantInt *StepValue =
> +            dyn_cast_or_null<ConstantInt>(Bounds->getStepValue());
> +        EXPECT_TRUE(StepValue && StepValue->isOne());
> +        EXPECT_EQ(Bounds->getFinalIVValue().getName(), "ub");
> +        EXPECT_EQ(Bounds->getCanonicalPredicate(), ICmpInst::ICMP_SLT);
> +        EXPECT_EQ(Bounds->getDirection(),
> +                  Loop::LoopBounds::Direction::Increasing);
> +        EXPECT_EQ(L->getInductionVariable(SE)->getName(), "i");
> +      });
> +}
> +
> +TEST(LoopInfoTest, LoopWithLatchCmpNE) {
> +  const char *ModuleStr =
> +      "define void @foo(i32* %A, i32 %ub) {\n"
> +      "entry:\n"
> +      "  %guardcmp = icmp slt i32 0, %ub\n"
> +      "  br i1 %guardcmp, label %for.preheader, label %for.end\n"
> +      "for.preheader:\n"
> +      "  br label %for.body\n"
> +      "for.body:\n"
> +      "  %i = phi i32 [ 0, %for.preheader ], [ %inc, %for.body ]\n"
> +      "  %idxprom = sext i32 %i to i64\n"
> +      "  %arrayidx = getelementptr inbounds i32, i32* %A, i64 %idxprom\n"
> +      "  store i32 %i, i32* %arrayidx, align 4\n"
> +      "  %inc = add nsw i32 %i, 1\n"
> +      "  %cmp = icmp ne i32 %i, %ub\n"
> +      "  br i1 %cmp, label %for.body, label %for.exit\n"
> +      "for.exit:\n"
> +      "  br label %for.end\n"
> +      "for.end:\n"
> +      "  ret void\n"
> +      "}\n";
> +
> +  // Parse the module.
> +  LLVMContext Context;
> +  std::unique_ptr<Module> M = makeLLVMModule(Context, ModuleStr);
> +
> +  runWithLoopInfoPlus(
> +      *M, "foo",
> +      [&](Function &F, LoopInfo &LI, ScalarEvolution &SE,
> +          PostDominatorTree &PDT) {
> +        Function::iterator FI = F.begin();
> +        // First two basic block are entry and for.preheader - skip them.
> +        ++FI;
> +        BasicBlock *Header = &*(++FI);
> +        assert(Header->getName() == "for.body");
> +        Loop *L = LI.getLoopFor(Header);
> +        EXPECT_NE(L, nullptr);
> +
> +        Optional<Loop::LoopBounds> Bounds = L->getBounds(SE);
> +        EXPECT_NE(Bounds, None);
> +        ConstantInt *InitialIVValue =
> +            dyn_cast<ConstantInt>(&Bounds->getInitialIVValue());
> +        EXPECT_TRUE(InitialIVValue && InitialIVValue->isZero());
> +        EXPECT_EQ(Bounds->getStepInst().getName(), "inc");
> +        ConstantInt *StepValue =
> +            dyn_cast_or_null<ConstantInt>(Bounds->getStepValue());
> +        EXPECT_TRUE(StepValue && StepValue->isOne());
> +        EXPECT_EQ(Bounds->getFinalIVValue().getName(), "ub");
> +        EXPECT_EQ(Bounds->getCanonicalPredicate(), ICmpInst::ICMP_SLT);
> +        EXPECT_EQ(Bounds->getDirection(),
> +                  Loop::LoopBounds::Direction::Increasing);
> +        EXPECT_EQ(L->getInductionVariable(SE)->getName(), "i");
> +      });
> +}
> +
> +TEST(LoopInfoTest, LoopWithGuardCmpSLE) {
> +  const char *ModuleStr =
> +      "define void @foo(i32* %A, i32 %ub) {\n"
> +      "entry:\n"
> +      "  %ubPlusOne = add i32 %ub, 1\n"
> +      "  %guardcmp = icmp sle i32 0, %ub\n"
> +      "  br i1 %guardcmp, label %for.preheader, label %for.end\n"
> +      "for.preheader:\n"
> +      "  br label %for.body\n"
> +      "for.body:\n"
> +      "  %i = phi i32 [ 0, %for.preheader ], [ %inc, %for.body ]\n"
> +      "  %idxprom = sext i32 %i to i64\n"
> +      "  %arrayidx = getelementptr inbounds i32, i32* %A, i64 %idxprom\n"
> +      "  store i32 %i, i32* %arrayidx, align 4\n"
> +      "  %inc = add nsw i32 %i, 1\n"
> +      "  %cmp = icmp ne i32 %i, %ubPlusOne\n"
> +      "  br i1 %cmp, label %for.body, label %for.exit\n"
> +      "for.exit:\n"
> +      "  br label %for.end\n"
> +      "for.end:\n"
> +      "  ret void\n"
> +      "}\n";
> +
> +  // Parse the module.
> +  LLVMContext Context;
> +  std::unique_ptr<Module> M = makeLLVMModule(Context, ModuleStr);
> +
> +  runWithLoopInfoPlus(
> +      *M, "foo",
> +      [&](Function &F, LoopInfo &LI, ScalarEvolution &SE,
> +          PostDominatorTree &PDT) {
> +        Function::iterator FI = F.begin();
> +        // First two basic block are entry and for.preheader - skip them.
> +        ++FI;
> +        BasicBlock *Header = &*(++FI);
> +        assert(Header->getName() == "for.body");
> +        Loop *L = LI.getLoopFor(Header);
> +        EXPECT_NE(L, nullptr);
> +
> +        Optional<Loop::LoopBounds> Bounds = L->getBounds(SE);
> +        EXPECT_NE(Bounds, None);
> +        ConstantInt *InitialIVValue =
> +            dyn_cast<ConstantInt>(&Bounds->getInitialIVValue());
> +        EXPECT_TRUE(InitialIVValue && InitialIVValue->isZero());
> +        EXPECT_EQ(Bounds->getStepInst().getName(), "inc");
> +        ConstantInt *StepValue =
> +            dyn_cast_or_null<ConstantInt>(Bounds->getStepValue());
> +        EXPECT_TRUE(StepValue && StepValue->isOne());
> +        EXPECT_EQ(Bounds->getFinalIVValue().getName(), "ubPlusOne");
> +        EXPECT_EQ(Bounds->getCanonicalPredicate(), ICmpInst::ICMP_SLT);
> +        EXPECT_EQ(Bounds->getDirection(),
> +                  Loop::LoopBounds::Direction::Increasing);
> +        EXPECT_EQ(L->getInductionVariable(SE)->getName(), "i");
> +      });
> +}
> +
> +TEST(LoopInfoTest, LoopNonConstantStep) {
> +  const char *ModuleStr =
> +      "define void @foo(i32* %A, i32 %ub, i32 %step) {\n"
> +      "entry:\n"
> +      "  %guardcmp = icmp slt i32 0, %ub\n"
> +      "  br i1 %guardcmp, label %for.preheader, label %for.end\n"
> +      "for.preheader:\n"
> +      "  br label %for.body\n"
> +      "for.body:\n"
> +      "  %i = phi i32 [ 0, %for.preheader ], [ %inc, %for.body ]\n"
> +      "  %idxprom = zext i32 %i to i64\n"
> +      "  %arrayidx = getelementptr inbounds i32, i32* %A, i64 %idxprom\n"
> +      "  store i32 %i, i32* %arrayidx, align 4\n"
> +      "  %inc = add nsw i32 %i, %step\n"
> +      "  %cmp = icmp slt i32 %inc, %ub\n"
> +      "  br i1 %cmp, label %for.body, label %for.exit\n"
> +      "for.exit:\n"
> +      "  br label %for.end\n"
> +      "for.end:\n"
> +      "  ret void\n"
> +      "}\n";
> +
> +  // Parse the module.
> +  LLVMContext Context;
> +  std::unique_ptr<Module> M = makeLLVMModule(Context, ModuleStr);
> +
> +  runWithLoopInfoPlus(
> +      *M, "foo",
> +      [&](Function &F, LoopInfo &LI, ScalarEvolution &SE,
> +          PostDominatorTree &PDT) {
> +        Function::iterator FI = F.begin();
> +        // First two basic block are entry and for.preheader - skip them.
> +        ++FI;
> +        BasicBlock *Header = &*(++FI);
> +        assert(Header->getName() == "for.body");
> +        Loop *L = LI.getLoopFor(Header);
> +        EXPECT_NE(L, nullptr);
> +
> +        Optional<Loop::LoopBounds> Bounds = L->getBounds(SE);
> +        EXPECT_NE(Bounds, None);
> +        ConstantInt *InitialIVValue =
> +            dyn_cast<ConstantInt>(&Bounds->getInitialIVValue());
> +        EXPECT_TRUE(InitialIVValue && InitialIVValue->isZero());
> +        EXPECT_EQ(Bounds->getStepInst().getName(), "inc");
> +        EXPECT_EQ(Bounds->getStepValue()->getName(), "step");
> +        EXPECT_EQ(Bounds->getFinalIVValue().getName(), "ub");
> +        EXPECT_EQ(Bounds->getCanonicalPredicate(), ICmpInst::ICMP_SLT);
> +        EXPECT_EQ(Bounds->getDirection(), Loop::LoopBounds::Direction::Unknown);
> +        EXPECT_EQ(L->getInductionVariable(SE)->getName(), "i");
> +      });
> +}
> +
> +TEST(LoopInfoTest, LoopUnsignedBounds) {
> +  const char *ModuleStr =
> +      "define void @foo(i32* %A, i32 %ub) {\n"
> +      "entry:\n"
> +      "  %guardcmp = icmp ult i32 0, %ub\n"
> +      "  br i1 %guardcmp, label %for.preheader, label %for.end\n"
> +      "for.preheader:\n"
> +      "  br label %for.body\n"
> +      "for.body:\n"
> +      "  %i = phi i32 [ 0, %for.preheader ], [ %inc, %for.body ]\n"
> +      "  %idxprom = zext i32 %i to i64\n"
> +      "  %arrayidx = getelementptr inbounds i32, i32* %A, i64 %idxprom\n"
> +      "  store i32 %i, i32* %arrayidx, align 4\n"
> +      "  %inc = add i32 %i, 1\n"
> +      "  %cmp = icmp ult i32 %inc, %ub\n"
> +      "  br i1 %cmp, label %for.body, label %for.exit\n"
> +      "for.exit:\n"
> +      "  br label %for.end\n"
> +      "for.end:\n"
> +      "  ret void\n"
> +      "}\n";
> +
> +  // Parse the module.
> +  LLVMContext Context;
> +  std::unique_ptr<Module> M = makeLLVMModule(Context, ModuleStr);
> +
> +  runWithLoopInfoPlus(
> +      *M, "foo",
> +      [&](Function &F, LoopInfo &LI, ScalarEvolution &SE,
> +          PostDominatorTree &PDT) {
> +        Function::iterator FI = F.begin();
> +        // First two basic block are entry and for.preheader - skip them.
> +        ++FI;
> +        BasicBlock *Header = &*(++FI);
> +        assert(Header->getName() == "for.body");
> +        Loop *L = LI.getLoopFor(Header);
> +        EXPECT_NE(L, nullptr);
> +
> +        Optional<Loop::LoopBounds> Bounds = L->getBounds(SE);
> +        EXPECT_NE(Bounds, None);
> +        ConstantInt *InitialIVValue =
> +            dyn_cast<ConstantInt>(&Bounds->getInitialIVValue());
> +        EXPECT_TRUE(InitialIVValue && InitialIVValue->isZero());
> +        EXPECT_EQ(Bounds->getStepInst().getName(), "inc");
> +        ConstantInt *StepValue =
> +            dyn_cast_or_null<ConstantInt>(Bounds->getStepValue());
> +        EXPECT_TRUE(StepValue && StepValue->isOne());
> +        EXPECT_EQ(Bounds->getFinalIVValue().getName(), "ub");
> +        EXPECT_EQ(Bounds->getCanonicalPredicate(), ICmpInst::ICMP_ULT);
> +        EXPECT_EQ(Bounds->getDirection(),
> +                  Loop::LoopBounds::Direction::Increasing);
> +        EXPECT_EQ(L->getInductionVariable(SE)->getName(), "i");
> +      });
> +}
> +
> +TEST(LoopInfoTest, DecreasingLoop) {
> +  const char *ModuleStr =
> +      "define void @foo(i32* %A, i32 %ub) {\n"
> +      "entry:\n"
> +      "  %guardcmp = icmp slt i32 0, %ub\n"
> +      "  br i1 %guardcmp, label %for.preheader, label %for.end\n"
> +      "for.preheader:\n"
> +      "  br label %for.body\n"
> +      "for.body:\n"
> +      "  %i = phi i32 [ %ub, %for.preheader ], [ %inc, %for.body ]\n"
> +      "  %idxprom = sext i32 %i to i64\n"
> +      "  %arrayidx = getelementptr inbounds i32, i32* %A, i64 %idxprom\n"
> +      "  store i32 %i, i32* %arrayidx, align 4\n"
> +      "  %inc = sub nsw i32 %i, 1\n"
> +      "  %cmp = icmp sgt i32 %inc, 0\n"
> +      "  br i1 %cmp, label %for.body, label %for.exit\n"
> +      "for.exit:\n"
> +      "  br label %for.end\n"
> +      "for.end:\n"
> +      "  ret void\n"
> +      "}\n";
> +
> +  // Parse the module.
> +  LLVMContext Context;
> +  std::unique_ptr<Module> M = makeLLVMModule(Context, ModuleStr);
> +
> +  runWithLoopInfoPlus(
> +      *M, "foo",
> +      [&](Function &F, LoopInfo &LI, ScalarEvolution &SE,
> +          PostDominatorTree &PDT) {
> +        Function::iterator FI = F.begin();
> +        // First two basic block are entry and for.preheader - skip them.
> +        ++FI;
> +        BasicBlock *Header = &*(++FI);
> +        assert(Header->getName() == "for.body");
> +        Loop *L = LI.getLoopFor(Header);
> +        EXPECT_NE(L, nullptr);
> +
> +        Optional<Loop::LoopBounds> Bounds = L->getBounds(SE);
> +        EXPECT_NE(Bounds, None);
> +        EXPECT_EQ(Bounds->getInitialIVValue().getName(), "ub");
> +        EXPECT_EQ(Bounds->getStepInst().getName(), "inc");
> +        ConstantInt *StepValue =
> +            dyn_cast_or_null<ConstantInt>(Bounds->getStepValue());
> +        EXPECT_EQ(StepValue, nullptr);
> +        ConstantInt *FinalIVValue =
> +            dyn_cast<ConstantInt>(&Bounds->getFinalIVValue());
> +        EXPECT_TRUE(FinalIVValue && FinalIVValue->isZero());
> +        EXPECT_EQ(Bounds->getCanonicalPredicate(), ICmpInst::ICMP_SGT);
> +        EXPECT_EQ(Bounds->getDirection(),
> +                  Loop::LoopBounds::Direction::Decreasing);
> +        EXPECT_EQ(L->getInductionVariable(SE)->getName(), "i");
> +      });
> +}
> +
> +TEST(LoopInfoTest, CannotFindDirection) {
> +  const char *ModuleStr =
> +      "define void @foo(i32* %A, i32 %ub, i32 %step) {\n"
> +      "entry:\n"
> +      "  %guardcmp = icmp slt i32 0, %ub\n"
> +      "  br i1 %guardcmp, label %for.preheader, label %for.end\n"
> +      "for.preheader:\n"
> +      "  br label %for.body\n"
> +      "for.body:\n"
> +      "  %i = phi i32 [ 0, %for.preheader ], [ %inc, %for.body ]\n"
> +      "  %idxprom = sext i32 %i to i64\n"
> +      "  %arrayidx = getelementptr inbounds i32, i32* %A, i64 %idxprom\n"
> +      "  store i32 %i, i32* %arrayidx, align 4\n"
> +      "  %inc = add nsw i32 %i, %step\n"
> +      "  %cmp = icmp ne i32 %i, %ub\n"
> +      "  br i1 %cmp, label %for.body, label %for.exit\n"
> +      "for.exit:\n"
> +      "  br label %for.end\n"
> +      "for.end:\n"
> +      "  ret void\n"
> +      "}\n";
> +
> +  // Parse the module.
> +  LLVMContext Context;
> +  std::unique_ptr<Module> M = makeLLVMModule(Context, ModuleStr);
> +
> +  runWithLoopInfoPlus(*M, "foo",
> +                      [&](Function &F, LoopInfo &LI, ScalarEvolution &SE,
> +                          PostDominatorTree &PDT) {
> +                        Function::iterator FI = F.begin();
> +                        // First two basic block are entry and for.preheader
> +                        // - skip them.
> +                        ++FI;
> +                        BasicBlock *Header = &*(++FI);
> +                        assert(Header->getName() == "for.body");
> +                        Loop *L = LI.getLoopFor(Header);
> +                        EXPECT_NE(L, nullptr);
> +
> +                        Optional<Loop::LoopBounds> Bounds = L->getBounds(SE);
> +                        EXPECT_NE(Bounds, None);
> +                        ConstantInt *InitialIVValue =
> +                            dyn_cast<ConstantInt>(&Bounds->getInitialIVValue());
> +                        EXPECT_TRUE(InitialIVValue && InitialIVValue->isZero());
> +                        EXPECT_EQ(Bounds->getStepInst().getName(), "inc");
> +                        EXPECT_EQ(Bounds->getStepValue()->getName(), "step");
> +                        EXPECT_EQ(Bounds->getFinalIVValue().getName(), "ub");
> +                        EXPECT_EQ(Bounds->getCanonicalPredicate(),
> +                                  ICmpInst::BAD_ICMP_PREDICATE);
> +                        EXPECT_EQ(Bounds->getDirection(),
> +                                  Loop::LoopBounds::Direction::Unknown);
> +                        EXPECT_EQ(L->getInductionVariable(SE)->getName(), "i");
> +                      });
> +}
> +
> +TEST(LoopInfoTest, ZextIndVar) {
> +  const char *ModuleStr =
> +      "define void @foo(i32* %A, i32 %ub) {\n"
> +      "entry:\n"
> +      "  %guardcmp = icmp slt i32 0, %ub\n"
> +      "  br i1 %guardcmp, label %for.preheader, label %for.end\n"
> +      "for.preheader:\n"
> +      "  br label %for.body\n"
> +      "for.body:\n"
> +      "  %indvars.iv = phi i64 [ 0, %for.preheader ], [ %indvars.iv.next, %for.body ]\n"
> +      "  %i = phi i32 [ 0, %for.preheader ], [ %inc, %for.body ]\n"
> +      "  %idxprom = sext i32 %i to i64\n"
> +      "  %arrayidx = getelementptr inbounds i32, i32* %A, i64 %idxprom\n"
> +      "  store i32 %i, i32* %arrayidx, align 4\n"
> +      "  %indvars.iv.next = add nuw nsw i64 %indvars.iv, 1\n"
> +      "  %inc = add nsw i32 %i, 1\n"
> +      "  %wide.trip.count = zext i32 %ub to i64\n"
> +      "  %exitcond = icmp ne i64 %indvars.iv.next, %wide.trip.count\n"
> +      "  br i1 %exitcond, label %for.body, label %for.exit\n"
> +      "for.exit:\n"
> +      "  br label %for.end\n"
> +      "for.end:\n"
> +      "  ret void\n"
> +      "}\n";
> +
> +  // Parse the module.
> +  LLVMContext Context;
> +  std::unique_ptr<Module> M = makeLLVMModule(Context, ModuleStr);
> +
> +  runWithLoopInfoPlus(
> +      *M, "foo",
> +      [&](Function &F, LoopInfo &LI, ScalarEvolution &SE,
> +          PostDominatorTree &PDT) {
> +        Function::iterator FI = F.begin();
> +        // First two basic block are entry and for.preheader - skip them.
> +        ++FI;
> +        BasicBlock *Header = &*(++FI);
> +        assert(Header->getName() == "for.body");
> +        Loop *L = LI.getLoopFor(Header);
> +        EXPECT_NE(L, nullptr);
> +
> +        Optional<Loop::LoopBounds> Bounds = L->getBounds(SE);
> +        EXPECT_NE(Bounds, None);
> +        ConstantInt *InitialIVValue =
> +            dyn_cast<ConstantInt>(&Bounds->getInitialIVValue());
> +        EXPECT_TRUE(InitialIVValue && InitialIVValue->isZero());
> +        EXPECT_EQ(Bounds->getStepInst().getName(), "indvars.iv.next");
> +        ConstantInt *StepValue =
> +            dyn_cast_or_null<ConstantInt>(Bounds->getStepValue());
> +        EXPECT_TRUE(StepValue && StepValue->isOne());
> +        EXPECT_EQ(Bounds->getFinalIVValue().getName(), "wide.trip.count");
> +        EXPECT_EQ(Bounds->getCanonicalPredicate(), ICmpInst::ICMP_NE);
> +        EXPECT_EQ(Bounds->getDirection(),
> +                  Loop::LoopBounds::Direction::Increasing);
> +        EXPECT_EQ(L->getInductionVariable(SE)->getName(), "indvars.iv");
> +      });
> +}
> +
> +TEST(LoopInfoTest, UnguardedLoop) {
> +  const char *ModuleStr =
> +      "define void @foo(i32* %A, i32 %ub) {\n"
> +      "entry:\n"
> +      "  br label %for.body\n"
> +      "for.body:\n"
> +      "  %i = phi i32 [ 0, %entry ], [ %inc, %for.body ]\n"
> +      "  %idxprom = sext i32 %i to i64\n"
> +      "  %arrayidx = getelementptr inbounds i32, i32* %A, i64 %idxprom\n"
> +      "  store i32 %i, i32* %arrayidx, align 4\n"
> +      "  %inc = add nsw i32 %i, 1\n"
> +      "  %cmp = icmp slt i32 %inc, %ub\n"
> +      "  br i1 %cmp, label %for.body, label %for.exit\n"
> +      "for.exit:\n"
> +      "  br label %for.end\n"
> +      "for.end:\n"
> +      "  ret void\n"
> +      "}\n";
> +
> +  // Parse the module.
> +  LLVMContext Context;
> +  std::unique_ptr<Module> M = makeLLVMModule(Context, ModuleStr);
> +
> +  runWithLoopInfoPlus(
> +      *M, "foo",
> +      [&](Function &F, LoopInfo &LI, ScalarEvolution &SE,
> +          PostDominatorTree &PDT) {
> +        Function::iterator FI = F.begin();
> +        // First basic block is entry - skip it.
> +        BasicBlock *Header = &*(++FI);
> +        assert(Header->getName() == "for.body");
> +        Loop *L = LI.getLoopFor(Header);
> +        EXPECT_NE(L, nullptr);
> +
> +        Optional<Loop::LoopBounds> Bounds = L->getBounds(SE);
> +        EXPECT_NE(Bounds, None);
> +        ConstantInt *InitialIVValue =
> +            dyn_cast<ConstantInt>(&Bounds->getInitialIVValue());
> +        EXPECT_TRUE(InitialIVValue && InitialIVValue->isZero());
> +        EXPECT_EQ(Bounds->getStepInst().getName(), "inc");
> +        ConstantInt *StepValue =
> +            dyn_cast_or_null<ConstantInt>(Bounds->getStepValue());
> +        EXPECT_TRUE(StepValue && StepValue->isOne());
> +        EXPECT_EQ(Bounds->getFinalIVValue().getName(), "ub");
> +        EXPECT_EQ(Bounds->getCanonicalPredicate(), ICmpInst::ICMP_SLT);
> +        EXPECT_EQ(Bounds->getDirection(),
> +                  Loop::LoopBounds::Direction::Increasing);
> +        EXPECT_EQ(L->getInductionVariable(SE)->getName(), "i");
> +      });
> +}
> +
> +TEST(LoopInfoTest, UnguardedLoopWithControlFlow) {
> +  const char *ModuleStr =
> +      "define void @foo(i32* %A, i32 %ub, i1 %cond) {\n"
> +      "entry:\n"
> +      "  br i1 %cond, label %for.preheader, label %for.end\n"
> +      "for.preheader:\n"
> +      "  br label %for.body\n"
> +      "for.body:\n"
> +      "  %i = phi i32 [ 0, %for.preheader ], [ %inc, %for.body ]\n"
> +      "  %idxprom = sext i32 %i to i64\n"
> +      "  %arrayidx = getelementptr inbounds i32, i32* %A, i64 %idxprom\n"
> +      "  store i32 %i, i32* %arrayidx, align 4\n"
> +      "  %inc = add nsw i32 %i, 1\n"
> +      "  %cmp = icmp slt i32 %inc, %ub\n"
> +      "  br i1 %cmp, label %for.body, label %for.exit\n"
> +      "for.exit:\n"
> +      "  br label %for.end\n"
> +      "for.end:\n"
> +      "  ret void\n"
> +      "}\n";
> +
> +  // Parse the module.
> +  LLVMContext Context;
> +  std::unique_ptr<Module> M = makeLLVMModule(Context, ModuleStr);
> +
> +  runWithLoopInfoPlus(
> +      *M, "foo",
> +      [&](Function &F, LoopInfo &LI, ScalarEvolution &SE,
> +          PostDominatorTree &PDT) {
> +        Function::iterator FI = F.begin();
> +        // First two basic block are entry and for.preheader - skip them.
> +        ++FI;
> +        BasicBlock *Header = &*(++FI);
> +        assert(Header->getName() == "for.body");
> +        Loop *L = LI.getLoopFor(Header);
> +        EXPECT_NE(L, nullptr);
> +
> +        Optional<Loop::LoopBounds> Bounds = L->getBounds(SE);
> +        EXPECT_NE(Bounds, None);
> +        ConstantInt *InitialIVValue =
> +            dyn_cast<ConstantInt>(&Bounds->getInitialIVValue());
> +        EXPECT_TRUE(InitialIVValue && InitialIVValue->isZero());
> +        EXPECT_EQ(Bounds->getStepInst().getName(), "inc");
> +        ConstantInt *StepValue =
> +            dyn_cast_or_null<ConstantInt>(Bounds->getStepValue());
> +        EXPECT_TRUE(StepValue && StepValue->isOne());
> +        EXPECT_EQ(Bounds->getFinalIVValue().getName(), "ub");
> +        EXPECT_EQ(Bounds->getCanonicalPredicate(), ICmpInst::ICMP_SLT);
> +        EXPECT_EQ(Bounds->getDirection(),
> +                  Loop::LoopBounds::Direction::Increasing);
> +        EXPECT_EQ(L->getInductionVariable(SE)->getName(), "i");
> +      });
> +}
> +
> +TEST(LoopInfoTest, LoopNest) {
> +  const char *ModuleStr =
> +      "define void @foo(i32* %A, i32 %ub) {\n"
> +      "entry:\n"
> +      "  %guardcmp = icmp slt i32 0, %ub\n"
> +      "  br i1 %guardcmp, label %for.outer.preheader, label %for.end\n"
> +      "for.outer.preheader:\n"
> +      "  br label %for.outer\n"
> +      "for.outer:\n"
> +      "  %j = phi i32 [ 0, %for.outer.preheader ], [ %inc.outer, %for.outer.latch ]\n"
> +      "  br i1 %guardcmp, label %for.inner.preheader, label %for.outer.latch\n"
> +      "for.inner.preheader:\n"
> +      "  br label %for.inner\n"
> +      "for.inner:\n"
> +      "  %i = phi i32 [ 0, %for.inner.preheader ], [ %inc, %for.inner ]\n"
> +      "  %idxprom = sext i32 %i to i64\n"
> +      "  %arrayidx = getelementptr inbounds i32, i32* %A, i64 %idxprom\n"
> +      "  store i32 %i, i32* %arrayidx, align 4\n"
> +      "  %inc = add nsw i32 %i, 1\n"
> +      "  %cmp = icmp slt i32 %inc, %ub\n"
> +      "  br i1 %cmp, label %for.inner, label %for.inner.exit\n"
> +      "for.inner.exit:\n"
> +      "  br label %for.outer.latch\n"
> +      "for.outer.latch:\n"
> +      "  %inc.outer = add nsw i32 %j, 1\n"
> +      "  %cmp.outer = icmp slt i32 %inc.outer, %ub\n"
> +      "  br i1 %cmp.outer, label %for.outer, label %for.outer.exit\n"
> +      "for.outer.exit:\n"
> +      "  br label %for.end\n"
> +      "for.end:\n"
> +      "  ret void\n"
> +      "}\n";
> +
> +  // Parse the module.
> +  LLVMContext Context;
> +  std::unique_ptr<Module> M = makeLLVMModule(Context, ModuleStr);
> +
> +  runWithLoopInfoPlus(
> +      *M, "foo",
> +      [&](Function &F, LoopInfo &LI, ScalarEvolution &SE,
> +          PostDominatorTree &PDT) {
> +        Function::iterator FI = F.begin();
> +        // First two basic block are entry and for.outer.preheader - skip them.
> +        ++FI;
> +        BasicBlock *Header = &*(++FI);
> +        assert(Header->getName() == "for.outer");
> +        Loop *L = LI.getLoopFor(Header);
> +        EXPECT_NE(L, nullptr);
> +
> +        Optional<Loop::LoopBounds> Bounds = L->getBounds(SE);
> +        EXPECT_NE(Bounds, None);
> +        ConstantInt *InitialIVValue =
> +            dyn_cast<ConstantInt>(&Bounds->getInitialIVValue());
> +        EXPECT_TRUE(InitialIVValue && InitialIVValue->isZero());
> +        EXPECT_EQ(Bounds->getStepInst().getName(), "inc.outer");
> +        ConstantInt *StepValue =
> +            dyn_cast_or_null<ConstantInt>(Bounds->getStepValue());
> +        EXPECT_TRUE(StepValue && StepValue->isOne());
> +        EXPECT_EQ(Bounds->getFinalIVValue().getName(), "ub");
> +        EXPECT_EQ(Bounds->getCanonicalPredicate(), ICmpInst::ICMP_SLT);
> +        EXPECT_EQ(Bounds->getDirection(),
> +                  Loop::LoopBounds::Direction::Increasing);
> +        EXPECT_EQ(L->getInductionVariable(SE)->getName(), "j");
> +
> +        // Next two basic blocks are for.outer and for.inner.preheader - skip
> +        // them.
> +        ++FI;
> +        Header = &*(++FI);
> +        assert(Header->getName() == "for.inner");
> +        L = LI.getLoopFor(Header);
> +        EXPECT_NE(L, nullptr);
> +
> +        Optional<Loop::LoopBounds> InnerBounds = L->getBounds(SE);
> +        EXPECT_NE(InnerBounds, None);
> +        InitialIVValue =
> +            dyn_cast<ConstantInt>(&InnerBounds->getInitialIVValue());
> +        EXPECT_TRUE(InitialIVValue && InitialIVValue->isZero());
> +        EXPECT_EQ(InnerBounds->getStepInst().getName(), "inc");
> +        StepValue = dyn_cast_or_null<ConstantInt>(InnerBounds->getStepValue());
> +        EXPECT_TRUE(StepValue && StepValue->isOne());
> +        EXPECT_EQ(InnerBounds->getFinalIVValue().getName(), "ub");
> +        EXPECT_EQ(InnerBounds->getCanonicalPredicate(), ICmpInst::ICMP_SLT);
> +        EXPECT_EQ(InnerBounds->getDirection(),
> +                  Loop::LoopBounds::Direction::Increasing);
> +        EXPECT_EQ(L->getInductionVariable(SE)->getName(), "i");
> +      });
> +}
> +
> +TEST(LoopInfoTest, AuxiliaryIV) {
> +  const char *ModuleStr =
> +      "define void @foo(i32* %A, i32 %ub) {\n"
> +      "entry:\n"
> +      "  %guardcmp = icmp slt i32 0, %ub\n"
> +      "  br i1 %guardcmp, label %for.preheader, label %for.end\n"
> +      "for.preheader:\n"
> +      "  br label %for.body\n"
> +      "for.body:\n"
> +      "  %i = phi i32 [ 0, %for.preheader ], [ %inc, %for.body ]\n"
> +      "  %aux = phi i32 [ 0, %for.preheader ], [ %auxinc, %for.body ]\n"
> +      "  %loopvariant = phi i32 [ 0, %for.preheader ], [ %loopvariantinc, %for.body ]\n"
> +      "  %usedoutside = phi i32 [ 0, %for.preheader ], [ %usedoutsideinc, %for.body ]\n"
> +      "  %mulopcode = phi i32 [ 0, %for.preheader ], [ %mulopcodeinc, %for.body ]\n"
> +      "  %idxprom = sext i32 %i to i64\n"
> +      "  %arrayidx = getelementptr inbounds i32, i32* %A, i64 %idxprom\n"
> +      "  store i32 %i, i32* %arrayidx, align 4\n"
> +      "  %mulopcodeinc = mul nsw i32 %mulopcode, 5\n"
> +      "  %usedoutsideinc = add nsw i32 %usedoutside, 5\n"
> +      "  %loopvariantinc = add nsw i32 %loopvariant, %i\n"
> +      "  %auxinc = add nsw i32 %aux, 5\n"
> +      "  %inc = add nsw i32 %i, 1\n"
> +      "  %cmp = icmp slt i32 %inc, %ub\n"
> +      "  br i1 %cmp, label %for.body, label %for.exit\n"
> +      "for.exit:\n"
> +      "  %lcssa = phi i32 [ %usedoutside, %for.body ]\n"
> +      "  br label %for.end\n"
> +      "for.end:\n"
> +      "  ret void\n"
> +      "}\n";
> +
> +  // Parse the module.
> +  LLVMContext Context;
> +  std::unique_ptr<Module> M = makeLLVMModule(Context, ModuleStr);
> +
> +  runWithLoopInfoPlus(
> +      *M, "foo",
> +      [&](Function &F, LoopInfo &LI, ScalarEvolution &SE,
> +          PostDominatorTree &PDT) {
> +        Function::iterator FI = F.begin();
> +        // First two basic block are entry and for.preheader - skip them.
> +        ++FI;
> +        BasicBlock *Header = &*(++FI);
> +        assert(Header->getName() == "for.body");
> +        Loop *L = LI.getLoopFor(Header);
> +        EXPECT_NE(L, nullptr);
> +
> +        Optional<Loop::LoopBounds> Bounds = L->getBounds(SE);
> +        EXPECT_NE(Bounds, None);
> +        ConstantInt *InitialIVValue =
> +            dyn_cast<ConstantInt>(&Bounds->getInitialIVValue());
> +        EXPECT_TRUE(InitialIVValue && InitialIVValue->isZero());
> +        EXPECT_EQ(Bounds->getStepInst().getName(), "inc");
> +        ConstantInt *StepValue =
> +            dyn_cast_or_null<ConstantInt>(Bounds->getStepValue());
> +        EXPECT_TRUE(StepValue && StepValue->isOne());
> +        EXPECT_EQ(Bounds->getFinalIVValue().getName(), "ub");
> +        EXPECT_EQ(Bounds->getCanonicalPredicate(), ICmpInst::ICMP_SLT);
> +        EXPECT_EQ(Bounds->getDirection(),
> +                  Loop::LoopBounds::Direction::Increasing);
> +        EXPECT_EQ(L->getInductionVariable(SE)->getName(), "i");
> +        BasicBlock::iterator II = Header->begin();
> +        PHINode &Instruction_i = cast<PHINode>(*(II));
> +        EXPECT_TRUE(L->isAuxiliaryInductionVariable(Instruction_i, SE));
> +        PHINode &Instruction_aux = cast<PHINode>(*(++II));
> +        EXPECT_TRUE(L->isAuxiliaryInductionVariable(Instruction_aux, SE));
> +        PHINode &Instruction_loopvariant = cast<PHINode>(*(++II));
> +        EXPECT_FALSE(
> +            L->isAuxiliaryInductionVariable(Instruction_loopvariant, SE));
> +        PHINode &Instruction_usedoutside = cast<PHINode>(*(++II));
> +        EXPECT_FALSE(
> +            L->isAuxiliaryInductionVariable(Instruction_usedoutside, SE));
> +        PHINode &Instruction_mulopcode = cast<PHINode>(*(++II));
> +        EXPECT_FALSE(
> +            L->isAuxiliaryInductionVariable(Instruction_mulopcode, SE));
> +      });
> +}
> 
> 
> _______________________________________________
> llvm-commits mailing list
> llvm-commits at lists.llvm.org
> https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-commits



More information about the llvm-commits mailing list