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) {}
65 if (
const auto *
Mul = dyn_cast<SCEVMulExpr>(Step)) {
69 if (
const auto *Const = dyn_cast<SCEVConstant>(
LHS);
70 Const && isa<SCEVVScale>(
RHS)) {
71 uint64_t V = Const->getAPInt().getLimitedValue();
72 if (llvm::isUInt<32>(V))
80 if (
F.hasFnAttribute(Attribute::VScaleRange))
81 if (
const auto *ConstStep = dyn_cast<SCEVConstant>(Step)) {
82 APInt V = ConstStep->getAPInt().abs();
85 V = V.zextOrTrunc(
Fixed->getBitWidth());
86 uint64_t VF = V.udiv(*Fixed).getLimitedValue();
87 if (VF && llvm::isUInt<32>(VF) &&
89 V.urem(*Fixed).isZero())
97bool EVLIndVarSimplifyImpl::run(
Loop &L) {
106 if (!EVLMD || !EVLMD->equalsStr(
"evl"))
110 ICmpInst *OrigLatchCmp =
L.getLatchCmpInst();
111 if (!LatchBlock || !OrigLatchCmp)
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");
124 L.getStartLoc(),
L.getHeader())
125 <<
"Cannot retrieve IV because " <<
ore::NV(
"Reason", Reason);
132 if (!
L.getIncomingAndBackEdge(InitBlock, BackEdgeBlock)) {
134 <<
L.getName() <<
"\n");
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()
153 L.getStartLoc(),
L.getHeader())
154 <<
"Could not obtain the loop bounds";
159 Value *CanonicalIVInit = &Bounds->getInitialIVValue();
160 Value *CanonicalIVFinal = &Bounds->getFinalIVValue();
165 LLVM_DEBUG(
dbgs() <<
"Could not infer VF from IndVar step '" << *StepV
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;
187 auto IntrinsicMatch = m_Intrinsic<Intrinsic::experimental_get_vector_length>(
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");
244 if (
auto *
I = dyn_cast<Instruction>(EVLIndVar)) {
245 DL =
I->getDebugLoc();
248 DL =
L.getStartLoc();
252 <<
"Using " <<
ore::NV(
"EVLIndVar", EVLIndVar)
253 <<
" for EVL-based IndVar";
262 auto *LatchBranch = cast<BranchInst>(LatchBlock->
getTerminator());
263 assert(LatchBranch->isConditional() &&
264 "expect the loop latch to be ended with a conditional branch");
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))
298 return PreservedAnalyses::allInSet<CFGAnalyses>();
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...
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.
A container for analyses that lazily runs them and caches their results.
PassT::Result & getResult(IRUnitT &IR, ExtraArgTs... ExtraArgs)
Get the result of an analysis pass for a given IR unit.
LLVM Basic Block Representation.
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...
Predicate
This enumeration lists the possible predicates for CmpInst subclasses.
This class represents a range of values.
const APInt * getSingleElement() const
If this set contains a single element, return it, otherwise return null.
This instruction compares its operands according to the predicate given to the constructor.
This provides a uniform API for creating instructions and inserting them into a basic block: either a...
A struct for saving information about induction variables.
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.
Tracking metadata reference owned by Metadata.
An analysis over an "inner" IR unit that provides access to an analysis manager over a "outer" IR uni...
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.
This class represents an analyzed expression in the program.
The main scalar evolution driver.
Value * getOperand(unsigned i) const
unsigned getNumOperands() const
LLVM Value Representation.
LLVM_ABI void replaceAllUsesWith(Value *V)
Change all uses of this to point to a new Value.
const ParentTy * getParent() const
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.
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.
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.
LLVM_ABI std::optional< const MDOperand * > findStringMetadataForLoop(const Loop *TheLoop, StringRef Name)
Find string metadata for loop.
LLVM_ABI raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
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...
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.