LLVM: lib/Transforms/Scalar/IndVarSimplify.cpp File Reference (original) (raw)

Go to the source code of this file.

Classes
struct FloatingPointIV
Represents a floating-point induction variable pattern that may be convertible to integer form. More...
struct IntegerIV
Represents the integer values for a converted IV. More...
Macros
#define DEBUG_TYPE "indvars"
Functions
STATISTIC (NumWidened, "Number of indvars widened")
STATISTIC (NumReplaced, "Number of exit values replaced")
STATISTIC (NumLFTR, "Number of loop exit tests replaced")
STATISTIC (NumElimExt, "Number of IV sign/zero extends eliminated")
STATISTIC (NumElimIV, "Number of congruent IVs eliminated")
static bool ConvertToSInt (const APFloat &APF, int64_t &IntVal)
Convert APF to an integer, if possible.
static bool isRepresentableAsExactInteger (const APFloat &FPVal, int64_t IntVal)
Ensure we stay within the bounds of fp values that can be represented as integers without gaps, which are 2^24 and 2^53 for IEEE-754 single and double precision respectively (both on negative and positive side).
static CmpInst::Predicate getIntegerPredicate (CmpInst::Predicate FPPred)
static std::optional< FloatingPointIV > maybeFloatingPointRecurrence (Loop *L, PHINode *PN)
Analyze a PN to determine whether it represents a simple floating-point induction variable, with constant fp init, increment, and exit values.
static std::optional< IntegerIV > tryConvertToIntegerIV (const FloatingPointIV &FPIV)
Ensure that the floating-point IV can be converted to a semantics-preserving signed 32-bit integer IV.
static void canonicalizeToIntegerIV (Loop *L, PHINode *PN, const FloatingPointIV &FPIV, const IntegerIV &IIV, const TargetLibraryInfo *TLI, std::unique_ptr< MemorySSAUpdater > &MSSAU)
Rewrite the floating-point IV as an integer IV.
static void visitIVCast (CastInst *Cast, WideIVInfo &WI, ScalarEvolution *SE, const TargetTransformInfo *TTI)
Update information about the induction variable that is extended by this sign or zero extend operation.
static PHINode * getLoopPhiForCounter (Value *IncV, Loop *L)
Given an Value which is hoped to be part of an add recurance in the given loop, return the associated Phi node if so.
static bool isLoopExitTestBasedOn (Value *V, BasicBlock *ExitingBB)
Whether the current loop exit test is based on this value.
static bool needsLFTR (Loop *L, BasicBlock *ExitingBB)
linearFunctionTestReplace policy.
static bool hasConcreteDefImpl (Value *V, SmallPtrSetImpl< Value * > &Visited, unsigned Depth)
Recursive helper for hasConcreteDef().
static bool hasConcreteDef (Value *V)
Return true if the given value is concrete.
static bool isLoopCounter (PHINode *Phi, Loop *L, ScalarEvolution *SE)
Return true if the given phi is a "counter" in L.
static PHINode * FindLoopCounter (Loop *L, BasicBlock *ExitingBB, const SCEV *BECount, ScalarEvolution *SE, DominatorTree *DT)
Search the loop header for a loop counter (anadd rec w/step of one) suitable for use by LFTR.
static Value * genLoopLimit (PHINode *IndVar, BasicBlock *ExitingBB, const SCEV *ExitCount, bool UsePostInc, Loop *L, SCEVExpander &Rewriter, ScalarEvolution *SE)
Insert an IR expression which computes the value held by the IV IndVar (which must be an loop counter w/unit stride) after the backedge of loop L is taken ExitCount times.
static void replaceExitCond (BranchInst *BI, Value *NewCond, SmallVectorImpl< WeakTrackingVH > &DeadInsts)
static Constant * createFoldedExitCond (const Loop *L, BasicBlock *ExitingBB, bool IsTaken)
static void foldExit (const Loop *L, BasicBlock *ExitingBB, bool IsTaken, SmallVectorImpl< WeakTrackingVH > &DeadInsts)
static void replaceLoopPHINodesWithPreheaderValues (LoopInfo *LI, Loop *L, SmallVectorImpl< WeakTrackingVH > &DeadInsts, ScalarEvolution &SE)
static Value * createInvariantCond (const Loop *L, BasicBlock *ExitingBB, const ScalarEvolution::LoopInvariantPredicate &LIP, SCEVExpander &Rewriter)
static std::optional< Value * > createReplacement (ICmpInst *ICmp, const Loop *L, BasicBlock *ExitingBB, const SCEV *MaxIter, bool Inverted, bool SkipLastIter, ScalarEvolution *SE, SCEVExpander &Rewriter)
static bool optimizeLoopExitWithUnknownExitCount (const Loop *L, BranchInst *BI, BasicBlock *ExitingBB, const SCEV *MaxIter, bool SkipLastIter, ScalarEvolution *SE, SCEVExpander &Rewriter, SmallVectorImpl< WeakTrackingVH > &DeadInsts)
static bool crashingBBWithoutEffect (const BasicBlock &BB)
Variables
static cl::opt< ReplaceExitVal > ReplaceExitValue ("replexitval", cl::Hidden, cl::init(OnlyCheapRepl), cl::desc("Choose the strategy to replace exit value in IndVarSimplify"), cl::values(clEnumValN(NeverRepl, "never", "never replace exit value"), clEnumValN(OnlyCheapRepl, "cheap", "only replace exit value when the cost is cheap"), clEnumValN(UnusedIndVarInLoop, "unusedindvarinloop", "only replace exit value when it is an unused " "induction variable in the loop and has cheap replacement cost"), clEnumValN(NoHardUse, "noharduse", "only replace exit values when loop def likely dead"), clEnumValN(AlwaysRepl, "always", "always replace exit value whenever possible")))
static cl::opt< bool > UsePostIncrementRanges ("indvars-post-increment-ranges", cl::Hidden, cl::desc("Use post increment control-dependent ranges in IndVarSimplify"), cl::init(true))
static cl::opt< bool > DisableLFTR ("disable-lftr", cl::Hidden, cl::init(false), cl::desc("Disable Linear Function Test Replace optimization"))
static cl::opt< bool > LoopPredication ("indvars-predicate-loops", cl::Hidden, cl::init(true), cl::desc("Predicate conditions in read only loops"))
static cl::opt< bool > LoopPredicationTraps ("indvars-predicate-loop-traps", cl::Hidden, cl::init(true), cl::desc("Predicate conditions that trap in loops with only local writes"))
static cl::opt< bool > AllowIVWidening ("indvars-widen-indvars", cl::Hidden, cl::init(true), cl::desc("Allow widening of indvars to eliminate s/zext"))

DEBUG_TYPE

#define DEBUG_TYPE "indvars"

canonicalizeToIntegerIV()

Rewrite the floating-point IV as an integer IV.

Definition at line 425 of file IndVarSimplify.cpp.

References llvm::PHINode::addIncoming(), llvm::cast(), FloatingPointIV::Compare, llvm::PHINode::Create(), llvm::dbgs(), IntegerIV::ExitValue, llvm::PoisonValue::get(), llvm::Value::getContext(), llvm::Instruction::getDebugLoc(), llvm::PHINode::getIncomingBlock(), llvm::PHINode::getIncomingValue(), llvm::Type::getInt32Ty(), llvm::ilist_node_impl< OptionsT >::getIterator(), llvm::Value::getName(), llvm::ilist_detail::node_parent_access< NodeTy, ParentTy >::getParent(), llvm::CmpInst::getPredicateName(), llvm::ConstantInt::getSigned(), llvm::Value::getType(), IntegerIV::IncrValue, IntegerIV::InitValue, llvm::Int32Ty, LLVM_DEBUG, IntegerIV::NewPred, llvm::RecursivelyDeleteTriviallyDeadInstructions(), llvm::Value::replaceAllUsesWith(), llvm::Instruction::setDebugLoc(), llvm::Value::takeName(), and llvm::Instruction::user_back().

ConvertToSInt()

crashingBBWithoutEffect()

createFoldedExitCond()

createInvariantCond()

createReplacement()

Definition at line 1353 of file IndVarSimplify.cpp.

References llvm::cast(), createFoldedExitCond(), createInvariantCond(), llvm::dyn_cast(), llvm::ScalarEvolution::evaluatePredicateAt(), llvm::ICmpInst::getCmpPredicate(), llvm::ICmpInst::getInverseCmpPredicate(), llvm::ScalarEvolution::getLoopInvariantExitCondDuringFirstIterations(), llvm::ScalarEvolution::getMinusOne(), llvm::ScalarEvolution::getMinusSCEV(), llvm::ScalarEvolution::getOne(), llvm::User::getOperand(), llvm::ScalarEvolution::getSCEVAtScope(), llvm::BasicBlock::getTerminator(), llvm::ScalarEvolution::getTruncateExpr(), llvm::SCEV::getType(), llvm::ScalarEvolution::getTypeSizeInBits(), llvm::ScalarEvolution::getUMinFromMismatchedTypes(), llvm::ScalarEvolution::getZeroExtendExpr(), llvm::CmpInst::ICMP_ULE, llvm::ScalarEvolution::isKnownPredicateAt(), LHS, RHS, and llvm::UMin.

Referenced by optimizeLoopExitWithUnknownExitCount().

FindLoopCounter()

Search the loop header for a loop counter (anadd rec w/step of one) suitable for use by LFTR.

If multiple counters are available, select the "best" one based profitable heuristics.

BECount may be an i8* pointer type. The pointer difference is already valid count without scaling the address stride, so it remains a pointer expression as far as SCEV is concerned.

Definition at line 939 of file IndVarSimplify.cpp.

References assert(), llvm::cast(), Cond, DL, llvm::ScalarEvolution::getSCEV(), llvm::BasicBlock::getTerminator(), llvm::SCEV::getType(), llvm::Value::getType(), llvm::ScalarEvolution::getTypeSizeInBits(), hasConcreteDef(), I, llvm::isa(), llvm::isAlmostDeadIV(), isLoopCounter(), isLoopExitTestBasedOn(), llvm::SCEV::isZero(), and llvm::mustExecuteUBIfPoisonOnPathTo().

foldExit()

genLoopLimit()

Insert an IR expression which computes the value held by the IV IndVar (which must be an loop counter w/unit stride) after the backedge of loop L is taken ExitCount times.

Definition at line 1019 of file IndVarSimplify.cpp.

References assert(), llvm::cast(), llvm::SCEVAddRecExpr::evaluateAtIteration(), llvm::SCEVAddRecExpr::getPostIncExpr(), llvm::ScalarEvolution::getSCEV(), llvm::SCEVAddRecExpr::getStart(), llvm::SCEVAddRecExpr::getStepRecurrence(), llvm::BasicBlock::getTerminator(), llvm::ScalarEvolution::getTruncateExpr(), llvm::SCEV::getType(), llvm::SCEVAddRecExpr::getType(), llvm::Value::getType(), llvm::ScalarEvolution::getTypeSizeInBits(), llvm::isa(), llvm::Type::isIntegerTy(), isLoopCounter(), llvm::ScalarEvolution::isLoopInvariant(), and llvm::SCEV::isOne().

getIntegerPredicate()

Definition at line 235 of file IndVarSimplify.cpp.

References llvm::CmpInst::BAD_ICMP_PREDICATE, llvm::CmpInst::FCMP_OEQ, llvm::CmpInst::FCMP_OGE, llvm::CmpInst::FCMP_OGT, llvm::CmpInst::FCMP_OLE, llvm::CmpInst::FCMP_OLT, llvm::CmpInst::FCMP_ONE, llvm::CmpInst::FCMP_UEQ, llvm::CmpInst::FCMP_UGE, llvm::CmpInst::FCMP_UGT, llvm::CmpInst::FCMP_ULE, llvm::CmpInst::FCMP_ULT, llvm::CmpInst::FCMP_UNE, llvm::CmpInst::ICMP_EQ, llvm::CmpInst::ICMP_NE, llvm::CmpInst::ICMP_SGE, llvm::CmpInst::ICMP_SGT, llvm::CmpInst::ICMP_SLE, and llvm::CmpInst::ICMP_SLT.

Referenced by tryConvertToIntegerIV().

getLoopPhiForCounter()

hasConcreteDef()

hasConcreteDefImpl()

isLoopCounter()

Return true if the given phi is a "counter" in L.

A counter is an add recurance (of integer or pointer type) with an arbitrary start, and a step of 1. Note that L must have exactly one latch.

Definition at line 914 of file IndVarSimplify.cpp.

References assert(), getLoopPhiForCounter(), llvm::ScalarEvolution::getSCEV(), llvm::isa(), llvm::ScalarEvolution::isSCEVable(), llvm::SCEVPatternMatch::m_SCEV(), llvm::SCEVPatternMatch::m_scev_AffineAddRec(), llvm::SCEVPatternMatch::m_scev_One(), llvm::SCEVPatternMatch::m_SpecificLoop(), and llvm::SCEVPatternMatch::match().

Referenced by FindLoopCounter(), and genLoopLimit().

isLoopExitTestBasedOn()

isRepresentableAsExactInteger()

maybeFloatingPointRecurrence()

needsLFTR()

linearFunctionTestReplace policy.

Return true unless we can show that the current exit test is already sufficiently canonical.

Definition at line 822 of file IndVarSimplify.cpp.

References assert(), llvm::cast(), Cond, llvm::dyn_cast(), llvm::BranchInst::getCondition(), getLoopPhiForCounter(), llvm::BasicBlock::getTerminator(), llvm::CmpInst::ICMP_EQ, llvm::CmpInst::ICMP_NE, LHS, RHS, and std::swap().

optimizeLoopExitWithUnknownExitCount()

Definition at line 1410 of file IndVarSimplify.cpp.

References assert(), Changed, llvm::ScalarEvolution::computeExitLimitFromCond(), llvm::SmallPtrSetImpl< PtrType >::count(), createReplacement(), llvm::dbgs(), llvm::dyn_cast(), llvm::SmallVectorTemplateCommon< T, typename >::empty(), llvm::SmallPtrSetImpl< PtrType >::erase(), llvm::BranchInst::getCondition(), llvm::ScalarEvolution::getExitCount(), llvm::Value::getName(), llvm::ScalarEvolution::getNoopOrZeroExtend(), llvm::BranchInst::getSuccessor(), llvm::SCEV::getType(), llvm::ScalarEvolution::getWiderType(), llvm::Value::hasOneUse(), llvm::SmallPtrSetImpl< PtrType >::insert(), llvm::isa(), LHS, LLVM_DEBUG, llvm::PatternMatch::m_LogicalAnd(), llvm::PatternMatch::m_LogicalOr(), llvm::PatternMatch::m_Value(), llvm::SCEVPatternMatch::match(), llvm::SmallVectorImpl< T >::pop_back_val(), llvm::SmallVectorTemplateBase< T, bool >::push_back(), llvm::Value::replaceAllUsesWith(), RHS, llvm::SmallPtrSetImplBase::size(), llvm::SmallVectorTemplateCommon< T, typename >::size(), and llvm::ScalarEvolution::SymbolicMaximum.

replaceExitCond()

replaceLoopPHINodesWithPreheaderValues()

Definition at line 1295 of file IndVarSimplify.cpp.

References assert(), llvm::cast(), llvm::SmallVectorImpl< T >::emplace_back(), llvm::SmallVectorTemplateCommon< T, typename >::empty(), llvm::ScalarEvolution::forgetValue(), llvm::PHINode::getIncomingValueForBlock(), I, llvm::SmallPtrSetImpl< PtrType >::insert(), llvm::SmallVectorImpl< T >::pop_back_val(), llvm::SmallVectorTemplateBase< T, bool >::push_back(), llvm::Value::replaceAllUsesWith(), llvm::LoopInfo::replacementPreservesLCSSAForm(), llvm::simplifyInstruction(), and llvm::Value::users().

STATISTIC() [1/5]

STATISTIC ( NumElimExt ,
"Number of IV sign/zero extends eliminated" )

STATISTIC() [2/5]

STATISTIC ( NumElimIV ,
"Number of congruent IVs eliminated" )

STATISTIC() [3/5]

STATISTIC ( NumLFTR ,
"Number of loop exit tests replaced" )

STATISTIC() [4/5]

STATISTIC ( NumReplaced ,
"Number of exit values replaced" )

STATISTIC() [5/5]

STATISTIC ( NumWidened ,
"Number of indvars widened" )

tryConvertToIntegerIV()

Ensure that the floating-point IV can be converted to a semantics-preserving signed 32-bit integer IV.

Returns a IntegerIV struct if possible, std::nullopt otherwise.

Definition at line 333 of file IndVarSimplify.cpp.

References llvm::CmpInst::BAD_ICMP_PREDICATE, FloatingPointIV::Compare, ConvertToSInt(), FloatingPointIV::ExitValue, getIntegerPredicate(), llvm::CmpInst::getPredicate(), llvm::CmpInst::ICMP_EQ, llvm::CmpInst::ICMP_NE, llvm::CmpInst::ICMP_SGE, llvm::CmpInst::ICMP_SGT, llvm::CmpInst::ICMP_SLE, llvm::CmpInst::ICMP_SLT, FloatingPointIV::IncrValue, FloatingPointIV::InitValue, llvm::isInt(), isRepresentableAsExactInteger(), and Range.

visitIVCast()

AllowIVWidening

cl::opt< bool > AllowIVWidening("indvars-widen-indvars", cl::Hidden, cl::init(true), cl::desc("Allow widening of indvars to eliminate s/zext")) ( "indvars-widen-indvars" , cl::Hidden , cl::init(true) , cl::desc("Allow widening of indvars to eliminate s/zext") ) static

DisableLFTR

cl::opt< bool > DisableLFTR("disable-lftr", cl::Hidden, cl::init(false), cl::desc("Disable Linear Function Test Replace optimization")) ( "disable-lftr" , cl::Hidden , cl::init(false) , cl::desc("Disable Linear Function Test Replace optimization") ) static

LoopPredication

cl::opt< bool > LoopPredication("indvars-predicate-loops", cl::Hidden, cl::init(true), cl::desc("Predicate conditions in read only loops")) ( "indvars-predicate-loops" , cl::Hidden , cl::init(true) , cl::desc("Predicate conditions in read only loops") ) static

LoopPredicationTraps

cl::opt< bool > LoopPredicationTraps("indvars-predicate-loop-traps", cl::Hidden, cl::init(true), cl::desc("Predicate conditions that trap in loops with only local writes")) ( "indvars-predicate-loop-traps" , cl::Hidden , cl::init(true) , cl::desc("Predicate conditions that trap in loops with only local writes") ) static

ReplaceExitValue

cl::opt< ReplaceExitVal > ReplaceExitValue("replexitval", cl::Hidden, cl::init(OnlyCheapRepl), cl::desc("Choose the strategy to replace exit value in IndVarSimplify"), cl::values( clEnumValN(NeverRepl, "never", "never replace exit value"), clEnumValN(OnlyCheapRepl, "cheap", "only replace exit value when the cost is cheap"), clEnumValN( UnusedIndVarInLoop, "unusedindvarinloop", "only replace exit value when it is an unused " "induction variable in the loop and has cheap replacement cost"), clEnumValN(NoHardUse, "noharduse", "only replace exit values when loop def likely dead"), clEnumValN(AlwaysRepl, "always", "always replace exit value whenever possible"))) ( "replexitval" , cl::Hidden , cl::init(OnlyCheapRepl) , cl::desc("Choose the strategy to replace exit value in IndVarSimplify") , cl::values( clEnumValN(NeverRepl, "never", "never replace exit value"), clEnumValN(OnlyCheapRepl, "cheap", "only replace exit value when the cost is cheap"), clEnumValN( UnusedIndVarInLoop, "unusedindvarinloop", "only replace exit value when it is an unused " "induction variable in the loop and has cheap replacement cost"), clEnumValN(NoHardUse, "noharduse", "only replace exit values when loop def likely dead"), clEnumValN(AlwaysRepl, "always", "always replace exit value whenever possible")) ) static

UsePostIncrementRanges

cl::opt< bool > UsePostIncrementRanges("indvars-post-increment-ranges", cl::Hidden, cl::desc("Use post increment control-dependent ranges in IndVarSimplify"), cl::init(true)) ( "indvars-post-increment-ranges" , cl::Hidden , cl::desc("Use post increment control-dependent ranges in IndVarSimplify") , cl::init(true) ) static