mirror of
https://github.com/capstone-engine/llvm-capstone.git
synced 2025-01-10 10:01:42 +00:00
Revert [LOOPINFO] Extend Loop object to add utilities to get the loop bounds, step, induction variable, and guard branch.
This reverts r361517 (git commit 2049e4dd8f
)
llvm-svn: 361553
This commit is contained in:
parent
e8df27d925
commit
987fdfd9a7
@ -54,12 +54,9 @@ 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;
|
||||
@ -532,165 +529,6 @@ 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;
|
||||
|
||||
|
@ -17,13 +17,10 @@
|
||||
#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"
|
||||
@ -167,249 +164,6 @@ PHINode *Loop::getCanonicalInductionVariable() const {
|
||||
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) {
|
||||
|
@ -292,6 +292,33 @@ static LoopVector populateWorklist(Loop &L) {
|
||||
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.
|
||||
@ -1200,7 +1227,7 @@ bool LoopInterchangeTransform::transform() {
|
||||
if (InnerLoop->getSubLoops().empty()) {
|
||||
BasicBlock *InnerLoopPreHeader = InnerLoop->getLoopPreheader();
|
||||
LLVM_DEBUG(dbgs() << "Calling Split Inner Loop\n");
|
||||
PHINode *InductionPHI = InnerLoop->getInductionVariable(*SE);
|
||||
PHINode *InductionPHI = getInductionVariable(InnerLoop, SE);
|
||||
if (!InductionPHI) {
|
||||
LLVM_DEBUG(dbgs() << "Failed to find the point to split loop latch \n");
|
||||
return false;
|
||||
|
@ -7,10 +7,6 @@
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#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"
|
||||
@ -30,26 +26,6 @@ runWithLoopInfo(Module &M, StringRef FuncName,
|
||||
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;
|
||||
@ -234,879 +210,3 @@ 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));
|
||||
});
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user