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
35
36 // Verify that phi-like recipes are at the beginning of \p VPBB, with no
37 // other recipes in between. Also check that only header blocks contain
38 // VPHeaderPHIRecipes.
39 bool verifyPhiRecipes(const VPBasicBlock *VPBB);
40
41 /// Verify that \p LastActiveLane's operand is guaranteed to be a prefix-mask.
42 bool verifyLastActiveLaneRecipe(const VPInstruction &LastActiveLane) const;
43
44 /// Verify that the stored scalar type of \p R is consistent with the types
45 /// derived from its operands. A null stored type is tolerated during the
46 /// transition to fully threaded scalar types; once set, it must agree with
47 /// the operand-derived type.
48 bool verifyRecipeTypes(const VPRecipeBase &R) const;
49
50 bool verifyVPBasicBlock(const VPBasicBlock *VPBB);
51
52 bool verifyBlock(const VPBlockBase *VPB);
53
54 /// Helper function that verifies the CFG invariants of the VPBlockBases
55 /// within
56 /// \p Region. Checks in this function are generic for VPBlockBases. They are
57 /// not specific for VPBasicBlocks or VPRegionBlocks.
58 bool verifyBlocksInRegion(const VPRegionBlock *Region);
59
60 /// Verify the CFG invariants of VPRegionBlock \p Region and its nested
61 /// VPBlockBases. Do not recurse inside nested VPRegionBlocks.
62 bool verifyRegion(const VPRegionBlock *Region);
63
64 /// Verify the CFG invariants of VPRegionBlock \p Region and its nested
65 /// VPBlockBases. Recurse inside nested VPRegionBlocks.
66 bool verifyRegionRec(const VPRegionBlock *Region);
67
68public:
69 VPlanVerifier(VPDominatorTree &VPDT) : VPDT(VPDT) {}
70
71 bool verify(const VPlan &Plan);
72};
73} // namespace
74
75bool VPlanVerifier::verifyPhiRecipes(const VPBasicBlock *VPBB) {
76 auto RecipeI = VPBB->begin();
77 auto End = VPBB->end();
78 unsigned NumActiveLaneMaskPhiRecipes = 0;
79 bool IsHeaderVPBB = VPBlockUtils::isHeader(VPBB, VPDT);
80 while (RecipeI != End && RecipeI->isPhi()) {
82 NumActiveLaneMaskPhiRecipes++;
83
84 if (IsHeaderVPBB &&
86 errs() << "Found non-header PHI recipe in header VPBB";
87#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
88 errs() << ": ";
89 RecipeI->dump();
90#endif
91 return false;
92 }
93
94 if (!IsHeaderVPBB && isa<VPHeaderPHIRecipe>(*RecipeI)) {
95 errs() << "Found header PHI recipe in non-header VPBB";
96#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
97 errs() << ": ";
98 RecipeI->dump();
99#endif
100 return false;
101 }
102
104 RecipeI->getIterator() != VPBB->begin()) {
105 errs() << "CurrentIteration PHI is not the first recipe\n";
106 return false;
107 }
108
109 // Check if the recipe operands match the number of predecessors.
110 // TODO Extend to other phi-like recipes.
111 if (auto *PhiIRI = dyn_cast<VPIRPhi>(&*RecipeI)) {
112 if (PhiIRI->getNumOperands() != VPBB->getNumPredecessors()) {
113 errs() << "Phi-like recipe with different number of operands and "
114 "predecessors.\n";
115 // TODO: Print broken recipe. At the moment printing an ill-formed
116 // phi-like recipe may crash.
117 return false;
118 }
119 }
120
121 RecipeI++;
122 }
123
124 if (!VPBB->getPlan()->isUnrolled() && NumActiveLaneMaskPhiRecipes > 1) {
125 errs() << "There should be no more than one VPActiveLaneMaskPHIRecipe";
126 return false;
127 }
128
129 while (RecipeI != End) {
130 if (RecipeI->isPhi() && !isa<VPBlendRecipe>(&*RecipeI)) {
131 errs() << "Found phi-like recipe after non-phi recipe";
132
133#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
134 errs() << ": ";
135 RecipeI->dump();
136 errs() << "after\n";
137 std::prev(RecipeI)->dump();
138#endif
139 return false;
140 }
141 RecipeI++;
142 }
143 return true;
144}
145
146static bool isKnownMonotonic(VPValue *V) {
147 VPValue *X, *Y;
148 if (match(V, m_Add(m_VPValue(X), m_VPValue(Y))))
149 return cast<VPRecipeWithIRFlags>(V)->hasNoUnsignedWrap() &&
151 if (match(V, m_StepVector()))
152 return true;
153 // Only handle a subset of IVs until we can guarantee there's no overflow.
154 if (auto *WidenIV = dyn_cast<VPWidenIntOrFpInductionRecipe>(V))
155 return WidenIV->isCanonical() || WidenIV->hasNoUnsignedWrap();
156 if (auto *Steps = dyn_cast<VPScalarIVStepsRecipe>(V))
157 return match(Steps->getOperand(0),
161 match(Steps->getStepValue(), m_One());
163 return true;
165}
166
167bool VPlanVerifier::verifyLastActiveLaneRecipe(
168 const VPInstruction &LastActiveLane) const {
169 assert(LastActiveLane.getOpcode() == VPInstruction::LastActiveLane &&
170 "must be called with VPInstruction::LastActiveLane");
171
172 if (LastActiveLane.getNumOperands() < 1) {
173 errs() << "LastActiveLane must have at least one operand\n";
174 return false;
175 }
176
177 const VPlan &Plan = *LastActiveLane.getParent()->getPlan();
178 // All operands must be prefix-mask. This means an icmp ult/ule LHS, RHS where
179 // the LHS is monotonically increasing and RHS is uniform across VFs and UF.
180 for (VPValue *Op : LastActiveLane.operands()) {
181 VPValue *Mask = Op;
182 VPValue *HeaderMask;
183
184 // Look through any `and`s with a loop_dependence_war_mask, which is always
185 // a prefix mask. TODO: Verify the full loop.dependence.mask chain.
186 if (match(Op,
188 m_VPValue(HeaderMask),
192 m_VPValue()),
194 Mask = HeaderMask;
195
196 if (vputils::isHeaderMask(Mask, Plan))
197 continue;
198
199 CmpPredicate Pred;
200 VPValue *LHS, *RHS;
201 if (match(Mask, m_ICmp(Pred, m_VPValue(LHS), m_VPValue(RHS))) &&
202 (Pred == CmpInst::ICMP_ULE || Pred == CmpInst::ICMP_ULT) &&
205 match(RHS, m_EVL(m_VPValue()))))
206 continue;
207
208 errs() << "LastActiveLane operand ";
209#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
210 VPSlotTracker Tracker(&Plan);
211 Op->printAsOperand(errs(), Tracker);
212#endif
213 errs() << " must be prefix mask (a header mask or an "
214 "EVL-derived mask currently)\n";
215 return false;
216 }
217
218 return true;
219}
220
221bool VPlanVerifier::verifyRecipeTypes(const VPRecipeBase &R) const {
222 const auto *SR = dyn_cast<VPSingleDefRecipe>(&R);
223 if (!SR)
224 return true;
225
226 auto CheckScalarType = [&](Type *Derived) -> bool {
227 if (Derived == SR->getScalarType())
228 return true;
229 errs() << "Recipe result type does not match type derived from operands";
230#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
231 errs() << ": ";
232 R.dump();
233#endif
234 errs() << "\n";
235 return false;
236 };
237
238 auto CheckOperandTypes = [&]() -> bool {
239 if (all_of(drop_begin(R.operands()), [&R](VPValue *Op) {
240 return R.getOperand(0)->getScalarType() == Op->getScalarType();
241 }))
242 return true;
243 errs() << "Recipe operand types do not match";
244#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
245 errs() << ": ";
246 R.dump();
247#endif
248 errs() << "\n";
249 return false;
250 };
251
252 if (auto *WII = dyn_cast<VPWidenIntOrFpInductionRecipe>(&R))
253 return CheckScalarType(WII->getTruncInst()
254 ? WII->getTruncInst()->getType()
255 : WII->getStartValue()->getScalarType());
256
257 switch (R.getVPRecipeID()) {
258 case VPRecipeBase::VPVectorPointerSC:
259 case VPRecipeBase::VPVectorEndPointerSC:
260 case VPRecipeBase::VPWidenGEPSC:
261 case VPRecipeBase::VPScalarIVStepsSC:
262 case VPRecipeBase::VPWidenPointerInductionSC:
263 case VPRecipeBase::VPDerivedIVSC:
264 return CheckScalarType(R.getOperand(0)->getScalarType());
265 case VPRecipeBase::VPWidenPHISC:
266 case VPRecipeBase::VPPredInstPHISC:
267 case VPRecipeBase::VPReductionPHISC:
268 case VPRecipeBase::VPActiveLaneMaskPHISC:
269 case VPRecipeBase::VPCurrentIterationPHISC:
270 case VPRecipeBase::VPFirstOrderRecurrencePHISC:
271 return CheckOperandTypes() &&
272 CheckScalarType(R.getOperand(0)->getScalarType());
273 case VPRecipeBase::VPInstructionSC: {
274 auto *VPI = cast<VPInstruction>(&R);
277 ArrayRef<unsigned>{
278 Instruction::ExtractValue, VPInstruction::FirstActiveLane,
280 VPInstruction::IncomingAliasMask, Instruction::Load,
281 Instruction::Alloca, Instruction::Call},
282 VPI->getOpcode()))
283 return true;
284 SmallVector<VPValue *, 4> Ops(VPI->operandsWithoutMask());
285 return CheckScalarType(
286 computeScalarTypeForInstruction(VPI->getOpcode(), Ops));
287 }
288 case VPRecipeBase::VPReplicateSC: {
289 auto *RepR = cast<VPReplicateRecipe>(&R);
290 SmallVector<VPValue *, 4> Ops(RepR->operands());
291 if (RepR->isPredicated())
292 Ops.pop_back();
293 return CheckScalarType(
294 VPReplicateRecipe::computeScalarType(RepR->getUnderlyingInstr(), Ops));
295 }
296 case VPRecipeBase::VPWidenSC: {
297 SmallVector<VPValue *, 4> Ops(R.operands());
298 return CheckScalarType(computeScalarTypeForInstruction(
300 }
301 case VPRecipeBase::VPExpressionSC:
302 return CheckScalarType(cast<VPExpressionRecipe>(&R)
303 ->getOperandOfResultType()
304 ->getScalarType());
305 default:
306 return true;
307 }
308 llvm_unreachable("all recipes must be handled above");
309}
310
311bool VPlanVerifier::verifyVPBasicBlock(const VPBasicBlock *VPBB) {
312 if (!verifyPhiRecipes(VPBB))
313 return false;
314
315 // Verify that defs in VPBB dominate all their uses.
316 DenseMap<const VPRecipeBase *, unsigned> RecipeNumbering;
317 unsigned Cnt = 0;
318 for (const VPRecipeBase &R : *VPBB)
319 RecipeNumbering[&R] = Cnt++;
320
321 for (const VPRecipeBase &R : *VPBB) {
322 if (isa<VPIRInstruction>(&R) && !isa<VPIRBasicBlock>(VPBB)) {
323 errs() << "VPIRInstructions ";
324#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
325 R.dump();
326 errs() << " ";
327#endif
328 errs() << "not in a VPIRBasicBlock!\n";
329 return false;
330 }
331 if (!verifyRecipeTypes(R))
332 return false;
333 for (const VPValue *V : R.definedValues()) {
334 // Verify that each defined value has a scalar type.
335 if (!V->getScalarType()) {
336 errs() << "VPValue without scalar type!\n";
337 return false;
338 }
339
340 // MaskedCond may be used from blocks it don't dominate; the block will be
341 // linearized and it will dominate its users after linearization.
343 continue;
344
345 for (const VPUser *U : V->users()) {
346 auto *UI = cast<VPRecipeBase>(U);
347 if (isa<VPIRPhi>(UI) &&
348 UI->getNumOperands() != UI->getParent()->getNumPredecessors()) {
349 errs() << "Phi-like recipe with different number of operands and "
350 "predecessors.\n";
351 return false;
352 }
353
354 if (auto *Phi = dyn_cast<VPPhiAccessors>(UI)) {
355 for (const auto &[IncomingVPV, IncomingVPBB] :
356 Phi->incoming_values_and_blocks()) {
357 if (IncomingVPV != V)
358 continue;
359
360 if (VPDT.dominates(VPBB, IncomingVPBB))
361 continue;
362
363 errs() << "Incoming def does not dominate incoming block!\n";
364#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
365 VPSlotTracker Tracker(VPBB->getPlan());
366 IncomingVPV->getDefiningRecipe()->print(errs(), " ", Tracker);
367 errs() << "\n does not dominate " << IncomingVPBB->getName()
368 << " for\n";
369 UI->print(errs(), " ", Tracker);
370#endif
371 return false;
372 }
373 continue;
374 }
375 // TODO: Also verify VPPredInstPHIRecipe.
377 continue;
378
379 // If the user is in the same block, check it comes after R in the
380 // block.
381 if (UI->getParent() == VPBB) {
382 if (RecipeNumbering[UI] >= RecipeNumbering[&R])
383 continue;
384 } else {
385 if (VPDT.dominates(VPBB, UI->getParent()))
386 continue;
387 }
388
389 // Recipes in blocks with a MaskedCond may be used in exit blocks; the
390 // block will be linearized and its recipes will dominate their users
391 // after linearization.
392 bool BlockHasMaskedCond = any_of(*VPBB, [](const VPRecipeBase &R) {
394 });
395 if (BlockHasMaskedCond &&
396 any_of(VPBB->getPlan()->getExitBlocks(), [UI](VPIRBasicBlock *EB) {
397 return is_contained(EB->getPredecessors(), UI->getParent());
398 })) {
399 continue;
400 }
401
402 errs() << "Use before def!\n";
403#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
404 VPSlotTracker Tracker(VPBB->getPlan());
405 UI->print(errs(), " ", Tracker);
406 errs() << "\n before\n";
407 R.print(errs(), " ", Tracker);
408 errs() << "\n";
409#endif
410 return false;
411 }
412 }
413 if (const auto *VPI = dyn_cast<VPInstruction>(&R)) {
414 switch (VPI->getOpcode()) {
416 if (!verifyLastActiveLaneRecipe(*VPI))
417 return false;
418 break;
419 default:
420 break;
421 }
422 }
423 if (const auto *ScalarIVSteps = dyn_cast<VPScalarIVStepsRecipe>(&R)) {
424 unsigned NumOps = ScalarIVSteps->getNumOperands();
425 if (NumOps != 3 && NumOps != 4) {
426 errs() << "VPScalarIVStepsRecipe must have 3 or 4 operands\n";
427 return false;
428 }
429 }
430 }
431
432 auto *IRBB = dyn_cast<VPIRBasicBlock>(VPBB);
433 if (!IRBB)
434 return true;
435
436 if (!WrappedIRBBs.insert(IRBB->getIRBasicBlock()).second) {
437 errs() << "Same IR basic block used by multiple wrapper blocks!\n";
438 return false;
439 }
440
441 return true;
442}
443
444bool VPlanVerifier::verifyBlock(const VPBlockBase *VPB) {
445 auto *VPBB = dyn_cast<VPBasicBlock>(VPB);
446 // Check block's condition bit.
447 if (VPBB && !isa<VPIRBasicBlock>(VPB)) {
448 // For plain CFG VPlans, verify header and latch block structure.
449 if (!VPBB->getParent()) {
450 if (VPBlockUtils::isHeader(VPBB, VPDT)) {
451 if (VPB->getNumPredecessors() != 2) {
452 errs()
453 << "Header block in plain CFG VPlan must have 2 predecessors!\n";
454 return false;
455 }
456 // Predecessor 0 is preheader, predecessor 1 is latch.
457 if (!VPBlockUtils::isLatch(VPB->getPredecessors()[1], VPDT)) {
458 errs() << "Header's second predecessor must be the latch!\n";
459 return false;
460 }
461 }
462
463 if (VPBlockUtils::isLatch(VPBB, VPDT)) {
464 auto BranchTerminator =
467 if (!match(VPBB->getTerminator(), BranchTerminator)) {
468 errs() << "Latch block must have a branch terminator!\n";
469 return false;
470 }
471 // Successor 0 is middle block, successor 1 is header.
472 if (VPBlockUtils::isHeader(VPB->getSuccessors()[0], VPDT)) {
473 errs() << "Latch's first successor must not be the header (must be "
474 "middle block)!\n";
475 return false;
476 }
477 }
478 } else if (VPB->getNumSuccessors() > 1 ||
479 (VPBB->isExiting() && !VPBB->getParent()->isReplicator())) {
480 if (!VPBB->getTerminator()) {
481 errs() << "Block has multiple successors but doesn't "
482 "have a proper branch recipe!\n";
483 return false;
484 }
485 } else if (VPBB->getTerminator()) {
486 errs() << "Unexpected branch recipe!\n";
487 return false;
488 }
489 }
490
491 // Check block's successors.
492 const auto &Successors = VPB->getSuccessors();
493 for (const VPBlockBase *Succ : Successors) {
494 // There must be a bi-directional link between block and successor.
495 const auto &SuccPreds = Succ->getPredecessors();
496 if (!is_contained(SuccPreds, VPB)) {
497 errs() << "Missing predecessor link.\n";
498 return false;
499 }
500 }
501
502 // Check block's predecessors.
503 const auto &Predecessors = VPB->getPredecessors();
504
505 for (const VPBlockBase *Pred : Predecessors) {
506 // Block and predecessor must be inside the same region.
507 if (Pred->getParent() != VPB->getParent()) {
508 errs() << "Predecessor is not in the same region.\n";
509 return false;
510 }
511
512 // There must be a bi-directional link between block and predecessor.
513 const auto &PredSuccs = Pred->getSuccessors();
514 if (!is_contained(PredSuccs, VPB)) {
515 errs() << "Missing successor link.\n";
516 return false;
517 }
518 }
519 return !VPBB || verifyVPBasicBlock(VPBB);
520}
521
522bool VPlanVerifier::verifyBlocksInRegion(const VPRegionBlock *Region) {
523 for (const VPBlockBase *VPB : vp_depth_first_shallow(Region->getEntry())) {
524 // Check block's parent.
525 if (VPB->getParent() != Region) {
526 errs() << "VPBlockBase has wrong parent\n";
527 return false;
528 }
529
530 if (!verifyBlock(VPB))
531 return false;
532 }
533 return true;
534}
535
536bool VPlanVerifier::verifyRegion(const VPRegionBlock *Region) {
537 const VPBlockBase *Entry = Region->getEntry();
538 const VPBlockBase *Exiting = Region->getExiting();
539
540 // Entry and Exiting shouldn't have any predecessor/successor, respectively.
541 if (Entry->hasPredecessors()) {
542 errs() << "region entry block has predecessors\n";
543 return false;
544 }
545 if (Exiting->getNumSuccessors() != 0) {
546 errs() << "region exiting block has successors\n";
547 return false;
548 }
549
550 return verifyBlocksInRegion(Region);
551}
552
553bool VPlanVerifier::verifyRegionRec(const VPRegionBlock *Region) {
554 // Recurse inside nested regions and check all blocks inside the region.
555 return verifyRegion(Region) &&
557 [this](const VPBlockBase *VPB) {
558 const auto *SubRegion = dyn_cast<VPRegionBlock>(VPB);
559 return !SubRegion || verifyRegionRec(SubRegion);
560 });
561}
562
563bool VPlanVerifier::verify(const VPlan &Plan) {
565 [this](const VPBlockBase *VPB) { return !verifyBlock(VPB); }))
566 return false;
567
568 const VPRegionBlock *TopRegion = Plan.getVectorLoopRegion();
569 // TODO: Verify all blocks using vp_depth_first_deep iterators.
570 if (!TopRegion)
571 return true;
572
573 if (!verifyRegionRec(TopRegion))
574 return false;
575
576 if (TopRegion->getParent()) {
577 errs() << "VPlan Top Region should have no parent.\n";
578 return false;
579 }
580
581 const VPBasicBlock *Entry = dyn_cast<VPBasicBlock>(TopRegion->getEntry());
582 if (!Entry) {
583 errs() << "VPlan entry block is not a VPBasicBlock\n";
584 return false;
585 }
586
587 const VPBasicBlock *Exiting = dyn_cast<VPBasicBlock>(TopRegion->getExiting());
588 if (!Exiting) {
589 errs() << "VPlan exiting block is not a VPBasicBlock\n";
590 return false;
591 }
592
593 if (Exiting->empty()) {
594 errs() << "VPlan vector loop exiting block must end with BranchOnCount, "
595 "BranchOnCond, or BranchOnTwoConds VPInstruction but is empty\n";
596 return false;
597 }
598
599 auto *LastInst = dyn_cast<VPInstruction>(std::prev(Exiting->end()));
600 if (!match(LastInst, m_CombineOr(m_BranchOnCond(),
602 m_BranchOnTwoConds())))) {
603 errs() << "VPlan vector loop exit must end with BranchOnCount, "
604 "BranchOnCond, or BranchOnTwoConds VPInstruction\n";
605 return false;
606 }
607
608 return true;
609}
610
612 VPDominatorTree VPDT(const_cast<VPlan &>(Plan));
613 VPlanVerifier Verifier(VPDT);
614 return Verifier.verify(Plan);
615}
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
#define X(NUM, ENUM, NAME)
Definition ELF.h:853
static Value * getOpcode(Value &V, Type &Ty, InstrumentationConfig &IConf, InstrumentorIRBuilderTy &IIRB)
const size_t AbstractManglingParser< Derived, Alloc >::NumOps
const AbstractManglingParser< Derived, Alloc >::OperatorInfo AbstractManglingParser< Derived, Alloc >::Ops[]
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:4338
iterator end()
Definition VPlan.h:4375
iterator begin()
Recipe iterator methods.
Definition VPlan.h:4373
bool empty() const
Definition VPlan.h:4384
VPBlockBase is the building block of the Hierarchical Control-Flow Graph.
Definition VPlan.h:94
VPRegionBlock * getParent()
Definition VPlan.h:186
size_t getNumSuccessors() const
Definition VPlan.h:237
size_t getNumPredecessors() const
Definition VPlan.h:238
const VPBlocksTy & getPredecessors() const
Definition VPlan.h:222
VPlan * getPlan()
Definition VPlan.cpp:211
const VPBlocksTy & getSuccessors() const
Definition VPlan.h:211
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:1225
unsigned getOpcode() const
Definition VPlan.h:1416
VPRecipeBase is a base class modeling a sequence of one or more output IR instructions.
Definition VPlan.h:402
VPBasicBlock * getParent()
Definition VPlan.h:477
VPRegionBlock represents a collection of VPBasicBlocks and VPRegionBlocks which form a Single-Entry-S...
Definition VPlan.h:4548
const VPBlockBase * getEntry() const
Definition VPlan.h:4592
const VPBlockBase * getExiting() const
Definition VPlan.h:4604
static Type * computeScalarType(const Instruction *I, ArrayRef< VPValue * > Operands)
Compute the scalar result type for a VPReplicateRecipe wrapping I with Operands (excluding any predic...
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:4696
VPBasicBlock * getEntry()
Definition VPlan.h:4792
bool isUnrolled() const
Returns true if the VPlan already has been unrolled, i.e.
Definition VPlan.h:4960
LLVM_ABI_FOR_TEST VPRegionBlock * getVectorLoopRegion()
Returns the VPRegionBlock of the vector loop.
Definition VPlan.cpp:1068
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
constexpr std::underlying_type_t< E > Mask()
Get a bitmask with 1s in all places up to the high-order bit of E's largest value.
@ 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.
IntrinsicID_match m_Intrinsic()
Match intrinsic calls like this: m_Intrinsic<Intrinsic::fabs>(m_Value(X))
CmpClass_match< LHS, RHS, ICmpInst > m_ICmp(CmpPredicate &Pred, const LHS &L, const RHS &R)
AllRecipe_commutative_match< Instruction::And, Op0_t, Op1_t > m_c_BinaryAnd(const Op0_t &Op0, const Op1_t &Op1)
Match a binary AND operation.
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
class LLVM_GSL_OWNER SmallVector
Forward declaration of SmallVector so that calculateSmallVectorDefaultInlinedElements can reference s...
LLVM_ABI Type * computeScalarTypeForInstruction(unsigned Opcode, ArrayRef< VPValue * > Operands)
Compute the scalar result type for an IR Opcode given Operands.
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
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.