LLVM 22.0.0git
VPlanVerifier.cpp
Go to the documentation of this file.
1//===-- VPlanVerifier.cpp -------------------------------------------------===//
2//
3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6//
7//===----------------------------------------------------------------------===//
8///
9/// \file
10/// This file defines the class VPlanVerifier, which contains utility functions
11/// to check the consistency and invariants of a VPlan.
12///
13//===----------------------------------------------------------------------===//
14
15#include "VPlanVerifier.h"
16#include "VPlan.h"
17#include "VPlanCFG.h"
18#include "VPlanDominatorTree.h"
19#include "VPlanHelpers.h"
20#include "VPlanPatternMatch.h"
21#include "VPlanUtils.h"
23#include "llvm/ADT/TypeSwitch.h"
24
25#define DEBUG_TYPE "loop-vectorize"
26
27using namespace llvm;
28using namespace VPlanPatternMatch;
29
30namespace {
31class VPlanVerifier {
32 const VPDominatorTree &VPDT;
33 VPTypeAnalysis &TypeInfo;
34 bool VerifyLate;
35
37
38 // Verify that phi-like recipes are at the beginning of \p VPBB, with no
39 // other recipes in between. Also check that only header blocks contain
40 // VPHeaderPHIRecipes.
41 bool verifyPhiRecipes(const VPBasicBlock *VPBB);
42
43 /// Verify that \p EVL is used correctly. The user must be either in
44 /// EVL-based recipes as a last operand or VPInstruction::Add which is
45 /// incoming value into EVL's recipe.
46 bool verifyEVLRecipe(const VPInstruction &EVL) const;
47
48 /// Verify that \p LastActiveLane's operand is guaranteed to be a prefix-mask.
49 bool verifyLastActiveLaneRecipe(const VPInstruction &LastActiveLane) const;
50
51 bool verifyVPBasicBlock(const VPBasicBlock *VPBB);
52
53 bool verifyBlock(const VPBlockBase *VPB);
54
55 /// Helper function that verifies the CFG invariants of the VPBlockBases
56 /// within
57 /// \p Region. Checks in this function are generic for VPBlockBases. They are
58 /// not specific for VPBasicBlocks or VPRegionBlocks.
59 bool verifyBlocksInRegion(const VPRegionBlock *Region);
60
61 /// Verify the CFG invariants of VPRegionBlock \p Region and its nested
62 /// VPBlockBases. Do not recurse inside nested VPRegionBlocks.
63 bool verifyRegion(const VPRegionBlock *Region);
64
65 /// Verify the CFG invariants of VPRegionBlock \p Region and its nested
66 /// VPBlockBases. Recurse inside nested VPRegionBlocks.
67 bool verifyRegionRec(const VPRegionBlock *Region);
68
69public:
70 VPlanVerifier(VPDominatorTree &VPDT, VPTypeAnalysis &TypeInfo,
71 bool VerifyLate)
72 : VPDT(VPDT), TypeInfo(TypeInfo), VerifyLate(VerifyLate) {}
73
74 bool verify(const VPlan &Plan);
75};
76} // namespace
77
78bool VPlanVerifier::verifyPhiRecipes(const VPBasicBlock *VPBB) {
79 auto RecipeI = VPBB->begin();
80 auto End = VPBB->end();
81 unsigned NumActiveLaneMaskPhiRecipes = 0;
82 bool IsHeaderVPBB = VPBlockUtils::isHeader(VPBB, VPDT);
83 while (RecipeI != End && RecipeI->isPhi()) {
85 NumActiveLaneMaskPhiRecipes++;
86
87 if (IsHeaderVPBB &&
89 errs() << "Found non-header PHI recipe in header VPBB";
90#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
91 errs() << ": ";
92 RecipeI->dump();
93#endif
94 return false;
95 }
96
97 if (!IsHeaderVPBB && isa<VPHeaderPHIRecipe>(*RecipeI)) {
98 errs() << "Found header PHI recipe in non-header VPBB";
99#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
100 errs() << ": ";
101 RecipeI->dump();
102#endif
103 return false;
104 }
105
106 // Check if the recipe operands match the number of predecessors.
107 // TODO Extend to other phi-like recipes.
108 if (auto *PhiIRI = dyn_cast<VPIRPhi>(&*RecipeI)) {
109 if (PhiIRI->getNumOperands() != VPBB->getNumPredecessors()) {
110 errs() << "Phi-like recipe with different number of operands and "
111 "predecessors.\n";
112 // TODO: Print broken recipe. At the moment printing an ill-formed
113 // phi-like recipe may crash.
114 return false;
115 }
116 }
117
118 RecipeI++;
119 }
120
121 if (!VerifyLate && NumActiveLaneMaskPhiRecipes > 1) {
122 errs() << "There should be no more than one VPActiveLaneMaskPHIRecipe";
123 return false;
124 }
125
126 while (RecipeI != End) {
127 if (RecipeI->isPhi() && !isa<VPBlendRecipe>(&*RecipeI)) {
128 errs() << "Found phi-like recipe after non-phi recipe";
129
130#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
131 errs() << ": ";
132 RecipeI->dump();
133 errs() << "after\n";
134 std::prev(RecipeI)->dump();
135#endif
136 return false;
137 }
138 RecipeI++;
139 }
140 return true;
141}
142
143bool VPlanVerifier::verifyEVLRecipe(const VPInstruction &EVL) const {
145 errs() << "verifyEVLRecipe should only be called on "
146 "VPInstruction::ExplicitVectorLength\n";
147 return false;
148 }
149 auto VerifyEVLUse = [&](const VPRecipeBase &R,
150 const unsigned ExpectedIdx) -> bool {
152 unsigned UseCount = count(Ops, &EVL);
153 if (UseCount != 1 || Ops[ExpectedIdx] != &EVL) {
154 errs() << "EVL is used as non-last operand in EVL-based recipe\n";
155 return false;
156 }
157 return true;
158 };
159 return all_of(EVL.users(), [this, &VerifyEVLUse](VPUser *U) {
160 return TypeSwitch<const VPUser *, bool>(U)
161 .Case<VPWidenIntrinsicRecipe>([&](const VPWidenIntrinsicRecipe *S) {
162 return VerifyEVLUse(*S, S->getNumOperands() - 1);
163 })
164 .Case<VPWidenStoreEVLRecipe, VPReductionEVLRecipe,
165 VPWidenIntOrFpInductionRecipe, VPWidenPointerInductionRecipe>(
166 [&](const VPRecipeBase *S) { return VerifyEVLUse(*S, 2); })
167 .Case<VPScalarIVStepsRecipe>([&](auto *R) {
168 if (R->getNumOperands() != 3) {
169 errs() << "Unrolling with EVL tail folding not yet supported\n";
170 return false;
171 }
172 return VerifyEVLUse(*R, 2);
173 })
174 .Case<VPWidenLoadEVLRecipe, VPVectorEndPointerRecipe,
175 VPInterleaveEVLRecipe>(
176 [&](const VPRecipeBase *R) { return VerifyEVLUse(*R, 1); })
177 .Case<VPInstructionWithType>(
178 [&](const VPInstructionWithType *S) { return VerifyEVLUse(*S, 0); })
179 .Case<VPInstruction>([&](const VPInstruction *I) {
180 if (I->getOpcode() == Instruction::PHI ||
181 I->getOpcode() == Instruction::ICmp ||
182 I->getOpcode() == Instruction::Sub)
183 return VerifyEVLUse(*I, 1);
184 switch (I->getOpcode()) {
185 case Instruction::Add:
186 break;
187 case Instruction::UIToFP:
188 case Instruction::Trunc:
189 case Instruction::ZExt:
190 case Instruction::Mul:
191 case Instruction::Shl:
192 case Instruction::FMul:
194 // Opcodes above can only use EVL after wide inductions have been
195 // expanded.
196 if (!VerifyLate) {
197 errs() << "EVL used by unexpected VPInstruction\n";
198 return false;
199 }
200 break;
201 default:
202 errs() << "EVL used by unexpected VPInstruction\n";
203 return false;
204 }
205 // EVLIVIncrement is only used by EVLIV & BranchOnCount.
206 // Having more than two users is unexpected.
207 if (I->getOpcode() != VPInstruction::Broadcast &&
208 I->getNumUsers() != 1 &&
209 (I->getNumUsers() != 2 ||
211 m_VPValue()))))) {
212 errs() << "EVL is used in VPInstruction with multiple users\n";
213 return false;
214 }
215 if (!VerifyLate && !isa<VPEVLBasedIVPHIRecipe>(*I->users().begin())) {
216 errs() << "Result of VPInstruction::Add with EVL operand is "
217 "not used by VPEVLBasedIVPHIRecipe\n";
218 return false;
219 }
220 return true;
221 })
222 .Default([&](const VPUser *U) {
223 errs() << "EVL has unexpected user\n";
224 return false;
225 });
226 });
227}
228
229bool VPlanVerifier::verifyLastActiveLaneRecipe(
230 const VPInstruction &LastActiveLane) const {
231 assert(LastActiveLane.getOpcode() == VPInstruction::LastActiveLane &&
232 "must be called with VPInstruction::LastActiveLane");
233
234 if (LastActiveLane.getNumOperands() < 1) {
235 errs() << "LastActiveLane must have at least one operand\n";
236 return false;
237 }
238
239 const VPlan &Plan = *LastActiveLane.getParent()->getPlan();
240 // All operands must be prefix-mask. Currently we check for header masks or
241 // EVL-derived masks, as those are currently the only operands in practice,
242 // but this may need updating in the future.
243 for (VPValue *Op : LastActiveLane.operands()) {
244 if (vputils::isHeaderMask(Op, Plan))
245 continue;
246
247 // Masks derived from EVL are also fine.
248 auto BroadcastOrEVL =
250 if (match(Op, m_CombineOr(m_ICmp(m_StepVector(), BroadcastOrEVL),
251 m_ICmp(BroadcastOrEVL, m_StepVector()))))
252 continue;
253
254 errs() << "LastActiveLane operand ";
255#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
256 VPSlotTracker Tracker(&Plan);
257 Op->printAsOperand(errs(), Tracker);
258#endif
259 errs() << " must be prefix mask (a header mask or an "
260 "EVL-derived mask currently)\n";
261 return false;
262 }
263
264 return true;
265}
266
267bool VPlanVerifier::verifyVPBasicBlock(const VPBasicBlock *VPBB) {
268 if (!verifyPhiRecipes(VPBB))
269 return false;
270
271 // Verify that defs in VPBB dominate all their uses.
272 DenseMap<const VPRecipeBase *, unsigned> RecipeNumbering;
273 unsigned Cnt = 0;
274 for (const VPRecipeBase &R : *VPBB)
275 RecipeNumbering[&R] = Cnt++;
276
277 for (const VPRecipeBase &R : *VPBB) {
278 if (isa<VPIRInstruction>(&R) && !isa<VPIRBasicBlock>(VPBB)) {
279 errs() << "VPIRInstructions ";
280#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
281 R.dump();
282 errs() << " ";
283#endif
284 errs() << "not in a VPIRBasicBlock!\n";
285 return false;
286 }
287 for (const VPValue *V : R.definedValues()) {
288 // Verify that we can infer a scalar type for each defined value. With
289 // assertions enabled, inferScalarType will perform some consistency
290 // checks during type inference.
291 if (!TypeInfo.inferScalarType(V)) {
292 errs() << "Failed to infer scalar type!\n";
293 return false;
294 }
295
296 for (const VPUser *U : V->users()) {
297 auto *UI = cast<VPRecipeBase>(U);
298 if (isa<VPIRPhi>(UI) &&
299 UI->getNumOperands() != UI->getParent()->getNumPredecessors()) {
300 errs() << "Phi-like recipe with different number of operands and "
301 "predecessors.\n";
302 return false;
303 }
304
305 if (auto *Phi = dyn_cast<VPPhiAccessors>(UI)) {
306 for (const auto &[IncomingVPV, IncomingVPBB] :
307 Phi->incoming_values_and_blocks()) {
308 if (IncomingVPV != V)
309 continue;
310
311 if (VPDT.dominates(VPBB, IncomingVPBB))
312 continue;
313
314 errs() << "Incoming def does not dominate incoming block!\n";
315#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
316 VPSlotTracker Tracker(VPBB->getPlan());
317 IncomingVPV->getDefiningRecipe()->print(errs(), " ", Tracker);
318 errs() << "\n does not dominate " << IncomingVPBB->getName()
319 << " for\n";
320 UI->print(errs(), " ", Tracker);
321#endif
322 return false;
323 }
324 continue;
325 }
326 // TODO: Also verify VPPredInstPHIRecipe.
328 continue;
329
330 // If the user is in the same block, check it comes after R in the
331 // block.
332 if (UI->getParent() == VPBB) {
333 if (RecipeNumbering[UI] >= RecipeNumbering[&R])
334 continue;
335 } else {
336 if (VPDT.dominates(VPBB, UI->getParent()))
337 continue;
338 }
339
340 errs() << "Use before def!\n";
341#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
342 VPSlotTracker Tracker(VPBB->getPlan());
343 UI->print(errs(), " ", Tracker);
344 errs() << "\n before\n";
345 R.print(errs(), " ", Tracker);
346 errs() << "\n";
347#endif
348 return false;
349 }
350 }
351 if (const auto *VPI = dyn_cast<VPInstruction>(&R)) {
352 switch (VPI->getOpcode()) {
354 if (!verifyEVLRecipe(*VPI)) {
355 errs() << "EVL VPValue is not used correctly\n";
356 return false;
357 }
358 break;
360 if (!verifyLastActiveLaneRecipe(*VPI))
361 return false;
362 break;
363 default:
364 break;
365 }
366 }
367 }
368
369 auto *IRBB = dyn_cast<VPIRBasicBlock>(VPBB);
370 if (!IRBB)
371 return true;
372
373 if (!WrappedIRBBs.insert(IRBB->getIRBasicBlock()).second) {
374 errs() << "Same IR basic block used by multiple wrapper blocks!\n";
375 return false;
376 }
377
378 return true;
379}
380
381/// Utility function that checks whether \p VPBlockVec has duplicate
382/// VPBlockBases.
383static bool hasDuplicates(const SmallVectorImpl<VPBlockBase *> &VPBlockVec) {
385 for (const auto *Block : VPBlockVec) {
386 if (!VPBlockSet.insert(Block).second)
387 return true;
388 }
389 return false;
390}
391
392bool VPlanVerifier::verifyBlock(const VPBlockBase *VPB) {
393 auto *VPBB = dyn_cast<VPBasicBlock>(VPB);
394 // Check block's condition bit.
395 if (VPBB && !isa<VPIRBasicBlock>(VPB)) {
396 if (VPB->getNumSuccessors() > 1 ||
397 (VPBB->getParent() && VPBB->isExiting() &&
398 !VPBB->getParent()->isReplicator())) {
399 if (!VPBB->getTerminator()) {
400 errs() << "Block has multiple successors but doesn't "
401 "have a proper branch recipe!\n";
402 return false;
403 }
404 } else if (VPBB->getTerminator()) {
405 errs() << "Unexpected branch recipe!\n";
406 return false;
407 }
408 }
409
410 // Check block's successors.
411 const auto &Successors = VPB->getSuccessors();
412 // There must be only one instance of a successor in block's successor list.
413 // TODO: This won't work for switch statements.
414 if (hasDuplicates(Successors)) {
415 errs() << "Multiple instances of the same successor.\n";
416 return false;
417 }
418
419 for (const VPBlockBase *Succ : Successors) {
420 // There must be a bi-directional link between block and successor.
421 const auto &SuccPreds = Succ->getPredecessors();
422 if (!is_contained(SuccPreds, VPB)) {
423 errs() << "Missing predecessor link.\n";
424 return false;
425 }
426 }
427
428 // Check block's predecessors.
429 const auto &Predecessors = VPB->getPredecessors();
430 // There must be only one instance of a predecessor in block's predecessor
431 // list.
432 // TODO: This won't work for switch statements.
433 if (hasDuplicates(Predecessors)) {
434 errs() << "Multiple instances of the same predecessor.\n";
435 return false;
436 }
437
438 for (const VPBlockBase *Pred : Predecessors) {
439 // Block and predecessor must be inside the same region.
440 if (Pred->getParent() != VPB->getParent()) {
441 errs() << "Predecessor is not in the same region.\n";
442 return false;
443 }
444
445 // There must be a bi-directional link between block and predecessor.
446 const auto &PredSuccs = Pred->getSuccessors();
447 if (!is_contained(PredSuccs, VPB)) {
448 errs() << "Missing successor link.\n";
449 return false;
450 }
451 }
452 return !VPBB || verifyVPBasicBlock(VPBB);
453}
454
455bool VPlanVerifier::verifyBlocksInRegion(const VPRegionBlock *Region) {
456 for (const VPBlockBase *VPB : vp_depth_first_shallow(Region->getEntry())) {
457 // Check block's parent.
458 if (VPB->getParent() != Region) {
459 errs() << "VPBlockBase has wrong parent\n";
460 return false;
461 }
462
463 if (!verifyBlock(VPB))
464 return false;
465 }
466 return true;
467}
468
469bool VPlanVerifier::verifyRegion(const VPRegionBlock *Region) {
470 const VPBlockBase *Entry = Region->getEntry();
471 const VPBlockBase *Exiting = Region->getExiting();
472
473 // Entry and Exiting shouldn't have any predecessor/successor, respectively.
474 if (Entry->hasPredecessors()) {
475 errs() << "region entry block has predecessors\n";
476 return false;
477 }
478 if (Exiting->getNumSuccessors() != 0) {
479 errs() << "region exiting block has successors\n";
480 return false;
481 }
482
483 return verifyBlocksInRegion(Region);
484}
485
486bool VPlanVerifier::verifyRegionRec(const VPRegionBlock *Region) {
487 // Recurse inside nested regions and check all blocks inside the region.
488 return verifyRegion(Region) &&
490 [this](const VPBlockBase *VPB) {
491 const auto *SubRegion = dyn_cast<VPRegionBlock>(VPB);
492 return !SubRegion || verifyRegionRec(SubRegion);
493 });
494}
495
496bool VPlanVerifier::verify(const VPlan &Plan) {
498 [this](const VPBlockBase *VPB) { return !verifyBlock(VPB); }))
499 return false;
500
501 const VPRegionBlock *TopRegion = Plan.getVectorLoopRegion();
502 // TODO: Verify all blocks using vp_depth_first_deep iterators.
503 if (!TopRegion)
504 return true;
505
506 if (!verifyRegionRec(TopRegion))
507 return false;
508
509 if (TopRegion->getParent()) {
510 errs() << "VPlan Top Region should have no parent.\n";
511 return false;
512 }
513
514 const VPBasicBlock *Entry = dyn_cast<VPBasicBlock>(TopRegion->getEntry());
515 if (!Entry) {
516 errs() << "VPlan entry block is not a VPBasicBlock\n";
517 return false;
518 }
519
520 if (!isa<VPCanonicalIVPHIRecipe>(&*Entry->begin())) {
521 errs() << "VPlan vector loop header does not start with a "
522 "VPCanonicalIVPHIRecipe\n";
523 return false;
524 }
525
526 const VPBasicBlock *Exiting = dyn_cast<VPBasicBlock>(TopRegion->getExiting());
527 if (!Exiting) {
528 errs() << "VPlan exiting block is not a VPBasicBlock\n";
529 return false;
530 }
531
532 if (Exiting->empty()) {
533 errs() << "VPlan vector loop exiting block must end with BranchOnCount, "
534 "BranchOnCond, or BranchOnTwoConds VPInstruction but is empty\n";
535 return false;
536 }
537
538 auto *LastInst = dyn_cast<VPInstruction>(std::prev(Exiting->end()));
539 if (!match(LastInst, m_CombineOr(m_BranchOnCond(),
541 m_BranchOnTwoConds())))) {
542 errs() << "VPlan vector loop exit must end with BranchOnCount, "
543 "BranchOnCond, or BranchOnTwoConds VPInstruction\n";
544 return false;
545 }
546
547 return true;
548}
549
550bool llvm::verifyVPlanIsValid(const VPlan &Plan, bool VerifyLate) {
551 VPDominatorTree VPDT(const_cast<VPlan &>(Plan));
552 VPTypeAnalysis TypeInfo(Plan);
553 VPlanVerifier Verifier(VPDT, TypeInfo, VerifyLate);
554 return Verifier.verify(Plan);
555}
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
@ Default
const AbstractManglingParser< Derived, Alloc >::OperatorInfo AbstractManglingParser< Derived, Alloc >::Ops[]
#define I(x, y, z)
Definition MD5.cpp:57
ppc ctr loops verify
verify safepoint Safepoint IR Verifier
This file defines the SmallPtrSet 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.
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:
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.
Definition DenseSet.h:291
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.
Definition VPlan.h:3944
iterator end()
Definition VPlan.h:3981
iterator begin()
Recipe iterator methods.
Definition VPlan.h:3979
bool empty() const
Definition VPlan.h:3990
VPBlockBase is the building block of the Hierarchical Control-Flow Graph.
Definition VPlan.h:81
VPRegionBlock * getParent()
Definition VPlan.h:173
size_t getNumSuccessors() const
Definition VPlan.h:219
size_t getNumPredecessors() const
Definition VPlan.h:220
const VPBlocksTy & getPredecessors() const
Definition VPlan.h:204
VPlan * getPlan()
Definition VPlan.cpp:161
const VPBlocksTy & getSuccessors() const
Definition VPlan.h:198
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.
Definition VPlan.h:1034
unsigned getOpcode() const
Definition VPlan.h:1191
VPBasicBlock * getParent()
Definition VPlan.h:408
VPRegionBlock represents a collection of VPBasicBlocks and VPRegionBlocks which form a Single-Entry-S...
Definition VPlan.h:4132
const VPBlockBase * getEntry() const
Definition VPlan.h:4168
const VPBlockBase * getExiting() const
Definition VPlan.h:4180
An analysis for type-inference for VPValues.
Type * inferScalarType(const VPValue *V)
Infer the type of V. Returns the scalar type of V.
operand_range operands()
Definition VPlanValue.h:270
unsigned getNumOperands() const
Definition VPlanValue.h:240
user_range users()
Definition VPlanValue.h:132
VPlan models a candidate for vectorization, encoding various decisions take to produce efficient outp...
Definition VPlan.h:4262
VPBasicBlock * getEntry()
Definition VPlan.h:4351
LLVM_ABI_FOR_TEST VPRegionBlock * getVectorLoopRegion()
Returns the VPRegionBlock of the vector loop.
Definition VPlan.cpp:1011
std::pair< iterator, bool > insert(const ValueT &V)
Definition DenseSet.h:202
@ Entry
Definition COFF.h:862
bool match(Val *V, const Pattern &P)
specificval_ty m_Specific(const Value *V)
Match if we have a specific specified value.
CmpClass_match< LHS, RHS, ICmpInst > m_ICmp(CmpPredicate &Pred, const LHS &L, const RHS &R)
MatchFunctor< Val, Pattern > match_fn(const Pattern &P)
A match functor that can be used as a UnaryPredicate in functional algorithms like all_of.
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()
VPInstruction_match< VPInstruction::BranchOnCount > m_BranchOnCount()
VPInstruction_match< VPInstruction::Broadcast, Op0_t > m_Broadcast(const Op0_t &Op0)
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
Definition RDFGraph.h:390
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.
Definition Types.h:26
bool all_of(R &&range, UnaryPredicate P)
Provide wrappers to std::all_of which take ranges instead of having to pass begin/end explicitly.
Definition STLExtras.h:1737
LLVM_ABI_FOR_TEST bool verifyVPlanIsValid(const VPlan &Plan, bool VerifyLate=false)
Verify invariants for general VPlans.
decltype(auto) dyn_cast(const From &Val)
dyn_cast<X> - Return the argument parameter cast to the specified type.
Definition Casting.h:643
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.
Definition VPlanCFG.h:216
bool any_of(R &&range, UnaryPredicate P)
Provide wrappers to std::any_of which take ranges instead of having to pass begin/end explicitly.
Definition STLExtras.h:1744
bool none_of(R &&Range, UnaryPredicate P)
Provide wrappers to std::none_of which take ranges instead of having to pass begin/end explicitly.
Definition STLExtras.h:1751
class LLVM_GSL_OWNER SmallVector
Forward declaration of SmallVector so that calculateSmallVectorDefaultInlinedElements can reference s...
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...
Definition Casting.h:547
LLVM_ABI raw_fd_ostream & errs()
This returns a reference to a raw_ostream for standard error.
auto count(R &&Range, const E &Element)
Wrapper function around std::count to count the number of times an element Element occurs in the give...
Definition STLExtras.h:2002
DWARFExpression::Operation Op
decltype(auto) cast(const From &Val)
cast<X> - Return the argument parameter cast to the specified type.
Definition Casting.h:559
bool is_contained(R &&Range, const E &Element)
Returns true if Element is found in Range.
Definition STLExtras.h:1945