32#define DEBUG_TYPE "evl-iv-simplify"
36STATISTIC(NumEliminatedCanonicalIV,
"Number of canonical IVs we eliminated");
39 "enable-evl-indvar-simplify",
44struct EVLIndVarSimplifyImpl {
50 : SE(LAR.SE), ORE(ORE) {}
66 if (
Mul->getNumOperands() == 2) {
71 uint64_t V = Const->getAPInt().getLimitedValue();
80 if (
F.hasFnAttribute(Attribute::VScaleRange))
82 APInt V = ConstStep->getAPInt().
abs();
85 V = V.zextOrTrunc(
Fixed->getBitWidth());
86 uint64_t VF = V.udiv(*Fixed).getLimitedValue();
89 V.urem(*Fixed).isZero())
97bool EVLIndVarSimplifyImpl::run(
Loop &L) {
103 const MDOperand *EVLMD =
106 if (!EVLMD || !EVLMD->equalsStr(
"evl"))
110 ICmpInst *OrigLatchCmp =
L.getLatchCmpInst();
111 if (!LatchBlock || !OrigLatchCmp)
114 InductionDescriptor IVD;
115 PHINode *IndVar =
L.getInductionVariable(SE);
116 if (!IndVar || !
L.getInductionDescriptor(SE, IVD)) {
117 const char *Reason = (IndVar ?
"induction descriptor is not available"
118 :
"cannot recognize induction variable");
120 <<
" because" << Reason <<
"\n");
123 return OptimizationRemarkMissed(
DEBUG_TYPE,
"UnrecognizedIndVar",
124 L.getStartLoc(),
L.getHeader())
125 <<
"Cannot retrieve IV because " <<
ore::NV(
"Reason", Reason);
132 if (!
L.getIncomingAndBackEdge(InitBlock, BackEdgeBlock)) {
134 <<
L.getName() <<
"\n");
137 return OptimizationRemarkMissed(
DEBUG_TYPE,
"UnrecognizedLoopStructure",
138 L.getStartLoc(),
L.getHeader())
139 <<
"Does not have a unique incoming and backedge";
146 std::optional<Loop::LoopBounds> Bounds =
L.getBounds(SE);
148 LLVM_DEBUG(
dbgs() <<
"Could not obtain the bounds for loop " <<
L.getName()
152 return OptimizationRemarkMissed(
DEBUG_TYPE,
"UnrecognizedLoopStructure",
153 L.getStartLoc(),
L.getHeader())
154 <<
"Could not obtain the loop bounds";
159 Value *CanonicalIVInit = &Bounds->getInitialIVValue();
160 Value *CanonicalIVFinal = &Bounds->getFinalIVValue();
162 const SCEV *StepV = IVD.
getStep();
165 LLVM_DEBUG(
dbgs() <<
"Could not infer VF from IndVar step '" << *StepV
169 return OptimizationRemarkMissed(
DEBUG_TYPE,
"UnrecognizedIndVar",
170 L.getStartLoc(),
L.getHeader())
171 <<
"Could not infer VF from IndVar step "
181 using namespace PatternMatch;
184 Value *EVLIndVar =
nullptr;
185 Value *RemTC =
nullptr;
190 for (PHINode &PN : BB->
phis()) {
196 if (PN.getBasicBlockIndex(InitBlock) < 0 ||
197 PN.getBasicBlockIndex(BackEdgeBlock) < 0)
202 Value *Init = PN.getIncomingValueForBlock(InitBlock);
204 switch (Bounds->getDirection()) {
205 case Direction::Increasing:
206 if (Init != CanonicalIVInit)
209 case Direction::Decreasing:
210 if (Init != CanonicalIVFinal)
213 case Direction::Unknown:
216 if (Init != CanonicalIVInit && Init != CanonicalIVFinal)
220 Value *RecValue = PN.getIncomingValueForBlock(BackEdgeBlock);
221 assert(RecValue &&
"expect recurrent IndVar value");
223 LLVM_DEBUG(
dbgs() <<
"Found candidate PN of EVL-based IndVar: " << PN
231 EVLIndVar = RecValue;
236 if (!EVLIndVar || !TC)
239 LLVM_DEBUG(
dbgs() <<
"Using " << *EVLIndVar <<
" for EVL-based IndVar\n");
245 DL =
I->getDebugLoc();
248 DL =
L.getStartLoc();
251 return OptimizationRemark(
DEBUG_TYPE,
"UseEVLIndVar",
DL, Region)
252 <<
"Using " <<
ore::NV(
"EVLIndVar", EVLIndVar)
253 <<
" for EVL-based IndVar";
263 assert(LatchBranch->isConditional() &&
264 "expect the loop latch to be ended with a conditional branch");
265 ICmpInst::Predicate Pred;
266 if (LatchBranch->getSuccessor(0) ==
L.getHeader())
267 Pred = ICmpInst::ICMP_NE;
269 Pred = ICmpInst::ICMP_EQ;
272 auto *NewLatchCmp = Builder.CreateICmp(Pred, EVLIndVar, TC);
284 ++NumEliminatedCanonicalIV;
292 Function &
F = *L.getHeader()->getParent();
297 if (EVLIndVarSimplifyImpl(AR, ORE).
run(L))
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
MachineBasicBlock MachineBasicBlock::iterator DebugLoc DL
static cl::opt< bool > EnableEVLIndVarSimplify("enable-evl-indvar-simplify", cl::desc("Enable EVL-based induction variable simplify Pass"), cl::Hidden, cl::init(true))
static uint32_t getVFFromIndVar(const SCEV *Step, const Function &F)
Returns the constant part of vectorization factor from the induction variable's step value SCEV expre...
Loop::LoopBounds::Direction Direction
This header provides classes for managing a pipeline of passes over loops in LLVM IR.
This file defines the 'Statistic' class, which is designed to be an easy way to expose various metric...
#define STATISTIC(VARNAME, DESC)
Class for arbitrary precision integers.
APInt abs() const
Get the absolute value.
iterator_range< const_phi_iterator > phis() const
Returns a range that iterates over the phis in the basic block.
const Instruction * getTerminator() const LLVM_READONLY
Returns the terminator instruction if the block is well formed or null if the block is not well forme...
This class represents a range of values.
const APInt * getSingleElement() const
If this set contains a single element, return it, otherwise return null.
const SCEV * getStep() const
This class provides an interface for updating the loop pass manager based on mutations to the loop ne...
Represents a single loop in the control flow graph.
A set of analyses that are preserved following a run of a transformation pass.
static PreservedAnalyses all()
Construct a special preserved set that preserves all passes.
static PreservedAnalyses allInSet()
Construct a preserved analyses object with a single preserved set.
This class represents an analyzed expression in the program.
The main scalar evolution driver.
LLVM_ABI void replaceAllUsesWith(Value *V)
Change all uses of this to point to a new Value.
const ParentTy * getParent() const
@ BasicBlock
Various leaf nodes.
specific_intval< false > m_SpecificInt(const APInt &V)
Match a specific integer value or vector with all elements equal to the value.
match_combine_or< CastInst_match< OpTy, ZExtInst >, OpTy > m_ZExtOrSelf(const OpTy &Op)
bool match(Val *V, const Pattern &P)
specificval_ty m_Specific(const Value *V)
Match if we have a specific specified value.
IntrinsicID_match m_Intrinsic()
Match intrinsic calls like this: m_Intrinsic<Intrinsic::fabs>(m_Value(X))
BinaryOp_match< LHS, RHS, Instruction::Add, true > m_c_Add(const LHS &L, const RHS &R)
Matches a Add with LHS and RHS in either order.
class_match< Value > m_Value()
Match an arbitrary value and ignore it.
BinaryOp_match< LHS, RHS, Instruction::Sub > m_Sub(const LHS &L, const RHS &R)
initializer< Ty > init(const Ty &Val)
PointerTypeMap run(const Module &M)
Compute the PointerTypeMap for the module M.
DiagnosticInfoOptimizationBase::Argument NV
This is an optimization pass for GlobalISel generic memory operations.
FunctionAddr VTableAddr Value
LLVM_ABI bool getBooleanLoopAttribute(const Loop *TheLoop, StringRef Name)
Returns true if Name is applied to TheLoop and enabled.
LLVM_ABI bool RecursivelyDeleteTriviallyDeadInstructions(Value *V, const TargetLibraryInfo *TLI=nullptr, MemorySSAUpdater *MSSAU=nullptr, std::function< void(Value *)> AboutToDeleteCallback=std::function< void(Value *)>())
If the specified value is a trivially dead instruction, delete it.
decltype(auto) dyn_cast(const From &Val)
dyn_cast<X> - Return the argument parameter cast to the specified type.
LLVM_ABI std::optional< const MDOperand * > findStringMetadataForLoop(const Loop *TheLoop, StringRef Name)
Find string metadata for loop.
AnalysisManager< Loop, LoopStandardAnalysisResults & > LoopAnalysisManager
The loop analysis manager.
LLVM_ABI raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
constexpr bool isUInt(uint64_t x)
Checks if an unsigned integer fits into the given bit width.
LLVM_ABI ConstantRange getVScaleRange(const Function *F, unsigned BitWidth)
Determine the possible constant range of vscale with the given bit width, based on the vscale_range f...
bool isa(const From &Val)
isa<X> - Return true if the parameter to the template is an instance of one of the template type argu...
OuterAnalysisManagerProxy< FunctionAnalysisManager, Loop, LoopStandardAnalysisResults & > FunctionAnalysisManagerLoopProxy
A proxy from a FunctionAnalysisManager to a Loop.
IRBuilder(LLVMContext &, FolderTy, InserterTy, MDNode *, ArrayRef< OperandBundleDef >) -> IRBuilder< FolderTy, InserterTy >
decltype(auto) cast(const From &Val)
cast<X> - Return the argument parameter cast to the specified type.
LLVM_ABI bool RecursivelyDeleteDeadPHINode(PHINode *PN, const TargetLibraryInfo *TLI=nullptr, MemorySSAUpdater *MSSAU=nullptr)
If the specified value is an effectively dead PHI node, due to being a def-use chain of single-use no...
PreservedAnalyses run(Loop &L, LoopAnalysisManager &LAM, LoopStandardAnalysisResults &AR, LPMUpdater &U)
The adaptor from a function pass to a loop pass computes these analyses and makes them available to t...
Direction
An enum for the direction of the loop.