LLVM 23.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
36
37 // Verify that phi-like recipes are at the beginning of \p VPBB, with no
38 // other recipes in between. Also check that only header blocks contain
39 // VPHeaderPHIRecipes.
40 bool verifyPhiRecipes(const VPBasicBlock *VPBB);
41
42 /// Verify that \p LastActiveLane's operand is guaranteed to be a prefix-mask.
43 bool verifyLastActiveLaneRecipe(const VPInstruction &LastActiveLane) const;
44
45 /// Verify that the stored scalar type of \p R is consistent with the types
46 /// derived from its operands. A null stored type is tolerated during the
47 /// transition to fully threaded scalar types; once set, it must agree with
48 /// the operand-derived type.
49 bool verifyRecipeTypes(const VPRecipeBase &R) 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 : VPDT(VPDT), TypeInfo(TypeInfo) {}
72
73 bool verify(const VPlan &Plan);
74};
75} // namespace
76
77bool VPlanVerifier::verifyPhiRecipes(const VPBasicBlock *VPBB) {
78 auto RecipeI = VPBB->begin();
79 auto End = VPBB->end();
80 unsigned NumActiveLaneMaskPhiRecipes = 0;
81 bool IsHeaderVPBB = VPBlockUtils::isHeader(VPBB, VPDT);
82 while (RecipeI != End && RecipeI->isPhi()) {
84 NumActiveLaneMaskPhiRecipes++;
85
86 if (IsHeaderVPBB &&
88 errs() << "Found non-header PHI recipe in header VPBB";
89#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
90 errs() << ": ";
91 RecipeI->dump();
92#endif
93 return false;
94 }
95
96 if (!IsHeaderVPBB && isa<VPHeaderPHIRecipe>(*RecipeI)) {
97 errs() << "Found header PHI recipe in non-header VPBB";
98#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
99 errs() << ": ";
100 RecipeI->dump();
101#endif
102 return false;
103 }
104
106 RecipeI->getIterator() != VPBB->begin()) {
107 errs() << "CurrentIteration PHI is not the first recipe\n";
108 return false;
109 }
110
111 // Check if the recipe operands match the number of predecessors.
112 // TODO Extend to other phi-like recipes.
113 if (auto *PhiIRI = dyn_cast<VPIRPhi>(&*RecipeI)) {
114 if (PhiIRI->getNumOperands() != VPBB->getNumPredecessors()) {
115 errs() << "Phi-like recipe with different number of operands and "
116 "predecessors.\n";
117 // TODO: Print broken recipe. At the moment printing an ill-formed
118 // phi-like recipe may crash.
119 return false;
120 }
121 }
122
123 RecipeI++;
124 }
125
126 if (!VPBB->getPlan()->isUnrolled() && NumActiveLaneMaskPhiRecipes > 1) {
127 errs() << "There should be no more than one VPActiveLaneMaskPHIRecipe";
128 return false;
129 }
130
131 while (RecipeI != End) {
132 if (RecipeI->isPhi() && !isa<VPBlendRecipe>(&*RecipeI)) {
133 errs() << "Found phi-like recipe after non-phi recipe";
134
135#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
136 errs() << ": ";
137 RecipeI->dump();
138 errs() << "after\n";
139 std::prev(RecipeI)->dump();
140#endif
141 return false;
142 }
143 RecipeI++;
144 }
145 return true;
146}
147
148static bool isKnownMonotonic(VPValue *V) {
149 VPValue *X, *Y;
150 if (match(V, m_Add(m_VPValue(X), m_VPValue(Y))))
151 return cast<VPRecipeWithIRFlags>(V)->hasNoUnsignedWrap() &&
153 if (match(V, m_StepVector()))
154 return true;
155 // Only handle a subset of IVs until we can guarantee there's no overflow.
156 if (auto *WidenIV = dyn_cast<VPWidenIntOrFpInductionRecipe>(V))
157 return WidenIV->isCanonical() || WidenIV->hasNoUnsignedWrap();
158 if (auto *Steps = dyn_cast<VPScalarIVStepsRecipe>(V))
159 return match(Steps->getOperand(0),
163 match(Steps->getStepValue(), m_One());
165 return true;
167}
168
169bool VPlanVerifier::verifyLastActiveLaneRecipe(
170 const VPInstruction &LastActiveLane) const {
171 assert(LastActiveLane.getOpcode() == VPInstruction::LastActiveLane &&
172 "must be called with VPInstruction::LastActiveLane");
173
174 if (LastActiveLane.getNumOperands() < 1) {
175 errs() << "LastActiveLane must have at least one operand\n";
176 return false;
177 }
178
179 const VPlan &Plan = *LastActiveLane.getParent()->getPlan();
180 // All operands must be prefix-mask. This means an icmp ult/ule LHS, RHS where
181 // the LHS is monotonically increasing and RHS is uniform across VFs and UF.
182 for (VPValue *Op : LastActiveLane.operands()) {
183 if (vputils::isHeaderMask(Op, Plan))
184 continue;
185
186 CmpPredicate Pred;
187 VPValue *LHS, *RHS;
188 if (match(Op, m_ICmp(Pred, m_VPValue(LHS), m_VPValue(RHS))) &&
189 (Pred == CmpInst::ICMP_ULE || Pred == CmpInst::ICMP_ULT) &&
192 match(RHS, m_EVL(m_VPValue()))))
193 continue;
194
195 errs() << "LastActiveLane operand ";
196#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
197 VPSlotTracker Tracker(&Plan);
198 Op->printAsOperand(errs(), Tracker);
199#endif
200 errs() << " must be prefix mask (a header mask or an "
201 "EVL-derived mask currently)\n";
202 return false;
203 }
204
205 return true;
206}
207
208bool VPlanVerifier::verifyRecipeTypes(const VPRecipeBase &R) const {
209 const auto *SR = dyn_cast<VPSingleDefRecipe>(&R);
210 if (!SR)
211 return true;
212
213 auto CheckScalarType = [&](Type *Derived) -> bool {
214 if (Derived == SR->getScalarType())
215 return true;
216 errs() << "Recipe result type does not match type derived from operands";
217#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
218 errs() << ": ";
219 R.dump();
220#endif
221 errs() << "\n";
222 return false;
223 };
224
225 auto CheckOperandTypes = [&]() -> bool {
226 if (all_of(drop_begin(R.operands()), [&R](VPValue *Op) {
227 return getScalarTypeOrInfer(R.getOperand(0)) ==
228 getScalarTypeOrInfer(Op);
229 }))
230 return true;
231 errs() << "Recipe operand types do not match";
232#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
233 errs() << ": ";
234 R.dump();
235#endif
236 errs() << "\n";
237 return false;
238 };
239
240 if (auto *WII = dyn_cast<VPWidenIntOrFpInductionRecipe>(&R))
241 return CheckScalarType(WII->getTruncInst()
242 ? WII->getTruncInst()->getType()
243 : WII->getStartValue()->getScalarType());
244
245 switch (R.getVPRecipeID()) {
246 case VPRecipeBase::VPVectorPointerSC:
247 case VPRecipeBase::VPVectorEndPointerSC:
248 case VPRecipeBase::VPWidenGEPSC:
249 case VPRecipeBase::VPScalarIVStepsSC:
250 case VPRecipeBase::VPWidenPointerInductionSC:
251 case VPRecipeBase::VPDerivedIVSC:
252 return CheckScalarType(getScalarTypeOrInfer(R.getOperand(0)));
253 case VPRecipeBase::VPWidenPHISC:
254 case VPRecipeBase::VPPredInstPHISC:
255 case VPRecipeBase::VPReductionPHISC:
256 case VPRecipeBase::VPActiveLaneMaskPHISC:
257 case VPRecipeBase::VPCurrentIterationPHISC:
258 case VPRecipeBase::VPFirstOrderRecurrencePHISC:
259 return CheckOperandTypes() &&
260 CheckScalarType(getScalarTypeOrInfer(R.getOperand(0)));
261 default:
262 return true;
263 }
264 llvm_unreachable("all recipes must be handled above");
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 if (!verifyRecipeTypes(R))
288 return false;
289 for (const VPValue *V : R.definedValues()) {
290 // Verify that we can infer a scalar type for each defined value. With
291 // assertions enabled, inferScalarType will perform some consistency
292 // checks during type inference.
293 if (!TypeInfo.inferScalarType(V)) {
294 errs() << "Failed to infer scalar type!\n";
295 return false;
296 }
297
298 // MaskedCond may be used from blocks it don't dominate; the block will be
299 // linearized and it will dominate its users after linearization.
301 continue;
302
303 for (const VPUser *U : V->users()) {
304 auto *UI = cast<VPRecipeBase>(U);
305 if (isa<VPIRPhi>(UI) &&
306 UI->getNumOperands() != UI->getParent()->getNumPredecessors()) {
307 errs() << "Phi-like recipe with different number of operands and "
308 "predecessors.\n";
309 return false;
310 }
311
312 if (auto *Phi = dyn_cast<VPPhiAccessors>(UI)) {
313 for (const auto &[IncomingVPV, IncomingVPBB] :
314 Phi->incoming_values_and_blocks()) {
315 if (IncomingVPV != V)
316 continue;
317
318 if (VPDT.dominates(VPBB, IncomingVPBB))
319 continue;
320
321 errs() << "Incoming def does not dominate incoming block!\n";
322#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
323 VPSlotTracker Tracker(VPBB->getPlan());
324 IncomingVPV->getDefiningRecipe()->print(errs(), " ", Tracker);
325 errs() << "\n does not dominate " << IncomingVPBB->getName()
326 << " for\n";
327 UI->print(errs(), " ", Tracker);
328#endif
329 return false;
330 }
331 continue;
332 }
333 // TODO: Also verify VPPredInstPHIRecipe.
335 continue;
336
337 // If the user is in the same block, check it comes after R in the
338 // block.
339 if (UI->getParent() == VPBB) {
340 if (RecipeNumbering[UI] >= RecipeNumbering[&R])
341 continue;
342 } else {
343 if (VPDT.dominates(VPBB, UI->getParent()))
344 continue;
345 }
346
347 // Recipes in blocks with a MaskedCond may be used in exit blocks; the
348 // block will be linearized and its recipes will dominate their users
349 // after linearization.
350 bool BlockHasMaskedCond = any_of(*VPBB, [](const VPRecipeBase &R) {
352 });
353 if (BlockHasMaskedCond &&
354 any_of(VPBB->getPlan()->getExitBlocks(), [UI](VPIRBasicBlock *EB) {
355 return is_contained(EB->getPredecessors(), UI->getParent());
356 })) {
357 continue;
358 }
359
360 errs() << "Use before def!\n";
361#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
362 VPSlotTracker Tracker(VPBB->getPlan());
363 UI->print(errs(), " ", Tracker);
364 errs() << "\n before\n";
365 R.print(errs(), " ", Tracker);
366 errs() << "\n";
367#endif
368 return false;
369 }
370 }
371 if (const auto *VPI = dyn_cast<VPInstruction>(&R)) {
372 switch (VPI->getOpcode()) {
374 if (!verifyLastActiveLaneRecipe(*VPI))
375 return false;
376 break;
377 default:
378 break;
379 }
380 }
381 if (const auto *ScalarIVSteps = dyn_cast<VPScalarIVStepsRecipe>(&R)) {
382 unsigned NumOps = ScalarIVSteps->getNumOperands();
383 if (NumOps != 3 && NumOps != 4) {
384 errs() << "VPScalarIVStepsRecipe must have 3 or 4 operands\n";
385 return false;
386 }
387 }
388 }
389
390 auto *IRBB = dyn_cast<VPIRBasicBlock>(VPBB);
391 if (!IRBB)
392 return true;
393
394 if (!WrappedIRBBs.insert(IRBB->getIRBasicBlock()).second) {
395 errs() << "Same IR basic block used by multiple wrapper blocks!\n";
396 return false;
397 }
398
399 return true;
400}
401
402bool VPlanVerifier::verifyBlock(const VPBlockBase *VPB) {
403 auto *VPBB = dyn_cast<VPBasicBlock>(VPB);
404 // Check block's condition bit.
405 if (VPBB && !isa<VPIRBasicBlock>(VPB)) {
406 // For plain CFG VPlans, verify header and latch block structure.
407 if (!VPBB->getParent()) {
408 if (VPBlockUtils::isHeader(VPBB, VPDT)) {
409 if (VPB->getNumPredecessors() != 2) {
410 errs()
411 << "Header block in plain CFG VPlan must have 2 predecessors!\n";
412 return false;
413 }
414 // Predecessor 0 is preheader, predecessor 1 is latch.
415 if (!VPBlockUtils::isLatch(VPB->getPredecessors()[1], VPDT)) {
416 errs() << "Header's second predecessor must be the latch!\n";
417 return false;
418 }
419 }
420
421 if (VPBlockUtils::isLatch(VPBB, VPDT)) {
422 auto BranchTerminator =
425 if (!match(VPBB->getTerminator(), BranchTerminator)) {
426 errs() << "Latch block must have a branch terminator!\n";
427 return false;
428 }
429 // Successor 0 is middle block, successor 1 is header.
430 if (VPBlockUtils::isHeader(VPB->getSuccessors()[0], VPDT)) {
431 errs() << "Latch's first successor must not be the header (must be "
432 "middle block)!\n";
433 return false;
434 }
435 }
436 } else if (VPB->getNumSuccessors() > 1 ||
437 (VPBB->isExiting() && !VPBB->getParent()->isReplicator())) {
438 if (!VPBB->getTerminator()) {
439 errs() << "Block has multiple successors but doesn't "
440 "have a proper branch recipe!\n";
441 return false;
442 }
443 } else if (VPBB->getTerminator()) {
444 errs() << "Unexpected branch recipe!\n";
445 return false;
446 }
447 }
448
449 // Check block's successors.
450 const auto &Successors = VPB->getSuccessors();
451 for (const VPBlockBase *Succ : Successors) {
452 // There must be a bi-directional link between block and successor.
453 const auto &SuccPreds = Succ->getPredecessors();
454 if (!is_contained(SuccPreds, VPB)) {
455 errs() << "Missing predecessor link.\n";
456 return false;
457 }
458 }
459
460 // Check block's predecessors.
461 const auto &Predecessors = VPB->getPredecessors();
462
463 for (const VPBlockBase *Pred : Predecessors) {
464 // Block and predecessor must be inside the same region.
465 if (Pred->getParent() != VPB->getParent()) {
466 errs() << "Predecessor is not in the same region.\n";
467 return false;
468 }
469
470 // There must be a bi-directional link between block and predecessor.
471 const auto &PredSuccs = Pred->getSuccessors();
472 if (!is_contained(PredSuccs, VPB)) {
473 errs() << "Missing successor link.\n";
474 return false;
475 }
476 }
477 return !VPBB || verifyVPBasicBlock(VPBB);
478}
479
480bool VPlanVerifier::verifyBlocksInRegion(const VPRegionBlock *Region) {
481 for (const VPBlockBase *VPB : vp_depth_first_shallow(Region->getEntry())) {
482 // Check block's parent.
483 if (VPB->getParent() != Region) {
484 errs() << "VPBlockBase has wrong parent\n";
485 return false;
486 }
487
488 if (!verifyBlock(VPB))
489 return false;
490 }
491 return true;
492}
493
494bool VPlanVerifier::verifyRegion(const VPRegionBlock *Region) {
495 const VPBlockBase *Entry = Region->getEntry();
496 const VPBlockBase *Exiting = Region->getExiting();
497
498 // Entry and Exiting shouldn't have any predecessor/successor, respectively.
499 if (Entry->hasPredecessors()) {
500 errs() << "region entry block has predecessors\n";
501 return false;
502 }
503 if (Exiting->getNumSuccessors() != 0) {
504 errs() << "region exiting block has successors\n";
505 return false;
506 }
507
508 return verifyBlocksInRegion(Region);
509}
510
511bool VPlanVerifier::verifyRegionRec(const VPRegionBlock *Region) {
512 // Recurse inside nested regions and check all blocks inside the region.
513 return verifyRegion(Region) &&
515 [this](const VPBlockBase *VPB) {
516 const auto *SubRegion = dyn_cast<VPRegionBlock>(VPB);
517 return !SubRegion || verifyRegionRec(SubRegion);
518 });
519}
520
521bool VPlanVerifier::verify(const VPlan &Plan) {
523 [this](const VPBlockBase *VPB) { return !verifyBlock(VPB); }))
524 return false;
525
526 const VPRegionBlock *TopRegion = Plan.getVectorLoopRegion();
527 // TODO: Verify all blocks using vp_depth_first_deep iterators.
528 if (!TopRegion)
529 return true;
530
531 if (!verifyRegionRec(TopRegion))
532 return false;
533
534 if (TopRegion->getParent()) {
535 errs() << "VPlan Top Region should have no parent.\n";
536 return false;
537 }
538
539 const VPBasicBlock *Entry = dyn_cast<VPBasicBlock>(TopRegion->getEntry());
540 if (!Entry) {
541 errs() << "VPlan entry block is not a VPBasicBlock\n";
542 return false;
543 }
544
545 const VPBasicBlock *Exiting = dyn_cast<VPBasicBlock>(TopRegion->getExiting());
546 if (!Exiting) {
547 errs() << "VPlan exiting block is not a VPBasicBlock\n";
548 return false;
549 }
550
551 if (Exiting->empty()) {
552 errs() << "VPlan vector loop exiting block must end with BranchOnCount, "
553 "BranchOnCond, or BranchOnTwoConds VPInstruction but is empty\n";
554 return false;
555 }
556
557 auto *LastInst = dyn_cast<VPInstruction>(std::prev(Exiting->end()));
558 if (!match(LastInst, m_CombineOr(m_BranchOnCond(),
560 m_BranchOnTwoConds())))) {
561 errs() << "VPlan vector loop exit must end with BranchOnCount, "
562 "BranchOnCond, or BranchOnTwoConds VPInstruction\n";
563 return false;
564 }
565
566 return true;
567}
568
570 VPDominatorTree VPDT(const_cast<VPlan &>(Plan));
571 VPTypeAnalysis TypeInfo(Plan);
572 VPlanVerifier Verifier(VPDT, TypeInfo);
573 return Verifier.verify(Plan);
574}
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
#define X(NUM, ENUM, NAME)
Definition ELF.h:853
const size_t AbstractManglingParser< Derived, Alloc >::NumOps
ppc ctr loops verify
verify safepoint Safepoint IR Verifier
This file defines the SmallPtrSet class.
static TableGen::Emitter::Opt Y("gen-skeleton-entry", EmitSkeleton, "Generate example skeleton entry")
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 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:
Value * RHS
Value * LHS
@ ICMP_ULT
unsigned less than
Definition InstrTypes.h:765
@ ICMP_ULE
unsigned less or equal
Definition InstrTypes.h:766
bool dominates(const DomTreeNodeBase< NodeT > *A, const DomTreeNodeBase< NodeT > *B) const
dominates - Returns true iff A dominates B.
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.
VPBasicBlock serves as the leaf of the Hierarchical Control-Flow Graph.
Definition VPlan.h:4263
iterator end()
Definition VPlan.h:4300
iterator begin()
Recipe iterator methods.
Definition VPlan.h:4298
bool empty() const
Definition VPlan.h:4309
VPBlockBase is the building block of the Hierarchical Control-Flow Graph.
Definition VPlan.h:93
VPRegionBlock * getParent()
Definition VPlan.h:185
size_t getNumSuccessors() const
Definition VPlan.h:236
size_t getNumPredecessors() const
Definition VPlan.h:237
const VPBlocksTy & getPredecessors() const
Definition VPlan.h:221
VPlan * getPlan()
Definition VPlan.cpp:211
const VPBlocksTy & getSuccessors() const
Definition VPlan.h:210
static bool isLatch(const VPBlockBase *VPB, const VPDominatorTree &VPDT)
Returns true if VPB is a loop latch, using isHeader().
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:1227
unsigned getOpcode() const
Definition VPlan.h:1410
VPRecipeBase is a base class modeling a sequence of one or more output IR instructions.
Definition VPlan.h:401
VPBasicBlock * getParent()
Definition VPlan.h:476
VPRegionBlock represents a collection of VPBasicBlocks and VPRegionBlocks which form a Single-Entry-S...
Definition VPlan.h:4473
const VPBlockBase * getEntry() const
Definition VPlan.h:4517
const VPBlockBase * getExiting() const
Definition VPlan.h:4529
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:455
unsigned getNumOperands() const
Definition VPlanValue.h:422
This is the base class of the VPlan Def/Use graph, used for modeling the data flow into,...
Definition VPlanValue.h:50
VPlan models a candidate for vectorization, encoding various decisions take to produce efficient outp...
Definition VPlan.h:4621
VPBasicBlock * getEntry()
Definition VPlan.h:4717
bool isUnrolled() const
Returns true if the VPlan already has been unrolled, i.e.
Definition VPlan.h:4885
LLVM_ABI_FOR_TEST VPRegionBlock * getVectorLoopRegion()
Returns the VPRegionBlock of the vector loop.
Definition VPlan.cpp:1098
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
@ Entry
Definition COFF.h:862
SpecificConstantMatch m_ZeroInt()
Convenience matchers for specific integer values.
match_combine_or< Ty... > m_CombineOr(const Ty &...Ps)
Combine pattern matchers matching any of Ps patterns.
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)
VPInstruction_match< VPInstruction::StepVector > m_StepVector()
VPInstruction_match< VPInstruction::BranchOnTwoConds > m_BranchOnTwoConds()
VPInstruction_match< VPInstruction::BranchOnCount > m_BranchOnCount()
canonical_iv_match m_CanonicalIV()
auto m_VPValue()
Match an arbitrary VPValue and ignore it.
VPInstruction_match< VPInstruction::ExplicitVectorLength, Op0_t > m_EVL(const Op0_t &Op0)
match_bind< VPInstruction > m_VPInstruction(VPInstruction *&V)
Match a VPInstruction, capturing if we match.
auto m_DerivedIV(const Op0_t &Op0, const Op1_t &Op1, const Op2_t &Op2)
VPInstruction_match< VPInstruction::BranchOnCond > m_BranchOnCond()
NodeAddr< PhiNode * > Phi
Definition RDFGraph.h:390
bool isUniformAcrossVFsAndUFs(const 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.
auto drop_begin(T &&RangeOrContainer, size_t N=1)
Return a range covering RangeOrContainer with the first N elements excluded.
Definition STLExtras.h:315
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:1738
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:253
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:1745
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.
DWARFExpression::Operation Op
LLVM_ABI Type * getScalarTypeOrInfer(VPValue *V)
Return the scalar type of V.
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:1946
LLVM_ABI_FOR_TEST bool verifyVPlanIsValid(const VPlan &Plan)
Verify invariants for general VPlans.