25#define DEBUG_TYPE "loop-vectorize"
43 bool verifyLastActiveLaneRecipe(
const VPInstruction &LastActiveLane)
const;
65 : VPDT(VPDT), TypeInfo(TypeInfo) {}
71bool VPlanVerifier::verifyPhiRecipes(
const VPBasicBlock *VPBB) {
72 auto RecipeI = VPBB->
begin();
73 auto End = VPBB->
end();
74 unsigned NumActiveLaneMaskPhiRecipes = 0;
76 while (RecipeI != End && RecipeI->isPhi()) {
78 NumActiveLaneMaskPhiRecipes++;
82 errs() <<
"Found non-header PHI recipe in header VPBB";
83#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
91 errs() <<
"Found header PHI recipe in non-header VPBB";
92#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
101 errs() <<
"CurrentIteration PHI is not immediately after canonical IV\n";
109 errs() <<
"Phi-like recipe with different number of operands and "
121 errs() <<
"There should be no more than one VPActiveLaneMaskPHIRecipe";
125 while (RecipeI != End) {
127 errs() <<
"Found phi-like recipe after non-phi recipe";
129#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
133 std::prev(RecipeI)->dump();
151 return WidenIV->isCanonical();
153 return match(Steps->getOperand(0),
163bool VPlanVerifier::verifyLastActiveLaneRecipe(
164 const VPInstruction &LastActiveLane)
const {
166 "must be called with VPInstruction::LastActiveLane");
169 errs() <<
"LastActiveLane must have at least one operand\n";
176 for (VPValue *
Op : LastActiveLane.
operands()) {
189 errs() <<
"LastActiveLane operand ";
190#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
191 VPSlotTracker Tracker(&Plan);
192 Op->printAsOperand(
errs(), Tracker);
194 errs() <<
" must be prefix mask (a header mask or an "
195 "EVL-derived mask currently)\n";
202bool VPlanVerifier::verifyVPBasicBlock(
const VPBasicBlock *VPBB) {
203 if (!verifyPhiRecipes(VPBB))
207 DenseMap<const VPRecipeBase *, unsigned> RecipeNumbering;
209 for (
const VPRecipeBase &R : *VPBB)
210 RecipeNumbering[&
R] = Cnt++;
212 for (
const VPRecipeBase &R : *VPBB) {
214 errs() <<
"VPIRInstructions ";
215#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
219 errs() <<
"not in a VPIRBasicBlock!\n";
222 for (
const VPValue *V :
R.definedValues()) {
227 errs() <<
"Failed to infer scalar type!\n";
231 for (
const VPUser *U :
V->users()) {
234 UI->getNumOperands() != UI->getParent()->getNumPredecessors()) {
235 errs() <<
"Phi-like recipe with different number of operands and "
241 for (
const auto &[IncomingVPV, IncomingVPBB] :
242 Phi->incoming_values_and_blocks()) {
243 if (IncomingVPV != V)
249 errs() <<
"Incoming def does not dominate incoming block!\n";
250#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
251 VPSlotTracker Tracker(VPBB->getPlan());
252 IncomingVPV->getDefiningRecipe()->print(
errs(),
" ", Tracker);
253 errs() <<
"\n does not dominate " << IncomingVPBB->getName()
255 UI->print(
errs(),
" ", Tracker);
267 if (UI->getParent() == VPBB) {
268 if (RecipeNumbering[UI] >= RecipeNumbering[&R])
271 if (VPDT.
dominates(VPBB, UI->getParent()))
275 errs() <<
"Use before def!\n";
276#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
277 VPSlotTracker Tracker(VPBB->getPlan());
278 UI->print(
errs(),
" ", Tracker);
279 errs() <<
"\n before\n";
280 R.print(
errs(),
" ", Tracker);
287 switch (VPI->getOpcode()) {
289 if (!verifyLastActiveLaneRecipe(*VPI))
302 if (!WrappedIRBBs.
insert(IRBB->getIRBasicBlock()).second) {
303 errs() <<
"Same IR basic block used by multiple wrapper blocks!\n";
314 for (
const auto *
Block : VPBlockVec) {
321bool VPlanVerifier::verifyBlock(
const VPBlockBase *VPB) {
326 (VPBB->getParent() && VPBB->isExiting() &&
327 !VPBB->getParent()->isReplicator())) {
328 if (!VPBB->getTerminator()) {
329 errs() <<
"Block has multiple successors but doesn't "
330 "have a proper branch recipe!\n";
333 }
else if (VPBB->getTerminator()) {
334 errs() <<
"Unexpected branch recipe!\n";
344 errs() <<
"Multiple instances of the same successor.\n";
348 for (
const VPBlockBase *Succ : Successors) {
350 const auto &SuccPreds = Succ->getPredecessors();
352 errs() <<
"Missing predecessor link.\n";
363 errs() <<
"Multiple instances of the same predecessor.\n";
367 for (
const VPBlockBase *Pred : Predecessors) {
369 if (Pred->getParent() != VPB->
getParent()) {
370 errs() <<
"Predecessor is not in the same region.\n";
375 const auto &PredSuccs = Pred->getSuccessors();
377 errs() <<
"Missing successor link.\n";
381 return !VPBB || verifyVPBasicBlock(VPBB);
384bool VPlanVerifier::verifyBlocksInRegion(
const VPRegionBlock *Region) {
388 errs() <<
"VPBlockBase has wrong parent\n";
392 if (!verifyBlock(VPB))
398bool VPlanVerifier::verifyRegion(
const VPRegionBlock *Region) {
400 const VPBlockBase *Exiting =
Region->getExiting();
403 if (
Entry->hasPredecessors()) {
404 errs() <<
"region entry block has predecessors\n";
408 errs() <<
"region exiting block has successors\n";
412 return verifyBlocksInRegion(Region);
415bool VPlanVerifier::verifyRegionRec(
const VPRegionBlock *Region) {
417 return verifyRegion(Region) &&
419 [
this](
const VPBlockBase *VPB) {
420 const auto *SubRegion = dyn_cast<VPRegionBlock>(VPB);
421 return !SubRegion || verifyRegionRec(SubRegion);
425bool VPlanVerifier::verify(
const VPlan &Plan) {
427 [
this](
const VPBlockBase *VPB) { return !verifyBlock(VPB); }))
435 if (!verifyRegionRec(TopRegion))
439 errs() <<
"VPlan Top Region should have no parent.\n";
445 errs() <<
"VPlan entry block is not a VPBasicBlock\n";
450 errs() <<
"VPlan vector loop header does not start with a "
451 "VPCanonicalIVPHIRecipe\n";
457 errs() <<
"VPlan exiting block is not a VPBasicBlock\n";
461 if (Exiting->
empty()) {
462 errs() <<
"VPlan vector loop exiting block must end with BranchOnCount, "
463 "BranchOnCond, or BranchOnTwoConds VPInstruction but is empty\n";
471 errs() <<
"VPlan vector loop exit must end with BranchOnCount, "
472 "BranchOnCond, or BranchOnTwoConds VPInstruction\n";
482 VPlanVerifier
Verifier(VPDT, TypeInfo);
483 return Verifier.verify(Plan);
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
verify safepoint Safepoint IR Verifier
This file defines the SmallPtrSet class.
static TableGen::Emitter::Opt Y("gen-skeleton-entry", EmitSkeleton, "Generate example skeleton entry")
static TableGen::Emitter::OptClass< SkeletonEmitter > X("gen-skeleton-class", "Generate example skeleton class")
This file implements the TypeSwitch template, which mimics a switch() statement whose cases are type ...
This file implements dominator tree analysis for a single level of a VPlan's H-CFG.
This file contains the declarations of different VPlan-related auxiliary helpers.
static bool hasDuplicates(const SmallVectorImpl< VPBlockBase * > &VPBlockVec)
Utility function that checks whether VPBlockVec has duplicate VPBlockBases.
static bool isKnownMonotonic(VPValue *V)
This file declares the class VPlanVerifier, which contains utility functions to check the consistency...
This file contains the declarations of the Vectorization Plan base classes:
@ ICMP_ULT
unsigned less than
@ ICMP_ULE
unsigned less or equal
bool dominates(const DomTreeNodeBase< NodeT > *A, const DomTreeNodeBase< NodeT > *B) const
dominates - Returns true iff A dominates B.
Implements a dense probed hash-table based set with some number of buckets stored inline.
std::pair< iterator, bool > insert(PtrType Ptr)
Inserts Ptr if and only if there is no element in the container equal to Ptr.
SmallPtrSet - This class implements a set which is optimized for holding SmallSize or less elements.
This class consists of common code factored out of the SmallVector class to reduce code duplication b...
VPBasicBlock serves as the leaf of the Hierarchical Control-Flow Graph.
iterator begin()
Recipe iterator methods.
VPBlockBase is the building block of the Hierarchical Control-Flow Graph.
VPRegionBlock * getParent()
size_t getNumSuccessors() const
size_t getNumPredecessors() const
const VPBlocksTy & getPredecessors() const
const VPBlocksTy & getSuccessors() const
static bool isHeader(const VPBlockBase *VPB, const VPDominatorTree &VPDT)
Returns true if VPB is a loop header, based on regions or VPDT in their absence.
Template specialization of the standard LLVM dominator tree utility for VPBlockBases.
This is a concrete Recipe that models a single VPlan-level instruction.
unsigned getOpcode() const
VPBasicBlock * getParent()
VPRegionBlock represents a collection of VPBasicBlocks and VPRegionBlocks which form a Single-Entry-S...
const VPBlockBase * getEntry() const
const VPBlockBase * getExiting() const
An analysis for type-inference for VPValues.
Type * inferScalarType(const VPValue *V)
Infer the type of V. Returns the scalar type of V.
unsigned getNumOperands() const
This is the base class of the VPlan Def/Use graph, used for modeling the data flow into,...
VPlan models a candidate for vectorization, encoding various decisions take to produce efficient outp...
VPBasicBlock * getEntry()
bool isUnrolled() const
Returns true if the VPlan already has been unrolled, i.e.
LLVM_ABI_FOR_TEST VPRegionBlock * getVectorLoopRegion()
Returns the VPRegionBlock of the vector loop.
std::pair< iterator, bool > insert(const ValueT &V)
SpecificConstantMatch m_ZeroInt()
Convenience matchers for specific integer values.
BinaryOp_match< LHS, RHS, Instruction::Add > m_Add(const LHS &L, const RHS &R)
bool match(Val *V, const Pattern &P)
cst_pred_ty< is_one > m_One()
Match an integer 1 or a vector with all elements equal to 1.
CmpClass_match< LHS, RHS, ICmpInst > m_ICmp(CmpPredicate &Pred, const LHS &L, const RHS &R)
match_combine_or< LTy, RTy > m_CombineOr(const LTy &L, const RTy &R)
Combine two pattern matchers matching L || R.
VPInstruction_match< VPInstruction::StepVector > m_StepVector()
VPInstruction_match< VPInstruction::BranchOnTwoConds > m_BranchOnTwoConds()
VPDerivedIV_match< Op0_t, Op1_t, Op2_t > m_DerivedIV(const Op0_t &Op0, const Op1_t &Op1, const Op2_t &Op2)
VPInstruction_match< VPInstruction::BranchOnCount > m_BranchOnCount()
class_match< VPValue > m_VPValue()
Match an arbitrary VPValue and ignore it.
VPInstruction_match< VPInstruction::ExplicitVectorLength, Op0_t > m_EVL(const Op0_t &Op0)
VPInstruction_match< VPInstruction::BranchOnCond > m_BranchOnCond()
NodeAddr< PhiNode * > Phi
bool isUniformAcrossVFsAndUFs(VPValue *V)
Checks if V is uniform across all VF lanes and UF parts.
bool isHeaderMask(const VPValue *V, const VPlan &Plan)
Return true if V is a header mask in Plan.
This is an optimization pass for GlobalISel generic memory operations.
bool all_of(R &&range, UnaryPredicate P)
Provide wrappers to std::all_of which take ranges instead of having to pass begin/end explicitly.
decltype(auto) dyn_cast(const From &Val)
dyn_cast<X> - Return the argument parameter cast to the specified type.
iterator_range< df_iterator< VPBlockShallowTraversalWrapper< VPBlockBase * > > > vp_depth_first_shallow(VPBlockBase *G)
Returns an iterator range to traverse the graph starting at G in depth-first order.
bool isa_and_nonnull(const Y &Val)
bool any_of(R &&range, UnaryPredicate P)
Provide wrappers to std::any_of which take ranges instead of having to pass begin/end explicitly.
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...
LLVM_ABI raw_fd_ostream & errs()
This returns a reference to a raw_ostream for standard error.
DWARFExpression::Operation Op
decltype(auto) cast(const From &Val)
cast<X> - Return the argument parameter cast to the specified type.
bool is_contained(R &&Range, const E &Element)
Returns true if Element is found in Range.
LLVM_ABI_FOR_TEST bool verifyVPlanIsValid(const VPlan &Plan)
Verify invariants for general VPlans.