LLVM 23.0.0git
VPlanUtils.cpp
Go to the documentation of this file.
1//===- VPlanUtils.cpp - VPlan-related utilities ---------------------------===//
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#include "VPlanUtils.h"
10#include "VPlanAnalysis.h"
11#include "VPlanCFG.h"
12#include "VPlanDominatorTree.h"
13#include "VPlanPatternMatch.h"
14#include "llvm/ADT/TypeSwitch.h"
18
19using namespace llvm;
20using namespace llvm::VPlanPatternMatch;
21using namespace llvm::SCEVPatternMatch;
22
24 return all_of(Def->users(),
25 [Def](const VPUser *U) { return U->usesFirstLaneOnly(Def); });
26}
27
29 return all_of(Def->users(),
30 [Def](const VPUser *U) { return U->usesFirstPartOnly(Def); });
31}
32
34 return all_of(Def->users(),
35 [Def](const VPUser *U) { return U->usesScalars(Def); });
36}
37
39 if (auto *E = dyn_cast<SCEVConstant>(Expr))
40 return Plan.getOrAddLiveIn(E->getValue());
41 // Skip SCEV expansion if Expr is a SCEVUnknown wrapping a non-instruction
42 // value. Otherwise the value may be defined in a loop and using it directly
43 // will break LCSSA form. The SCEV expansion takes care of preserving LCSSA
44 // form.
45 auto *U = dyn_cast<SCEVUnknown>(Expr);
46 if (U && !isa<Instruction>(U->getValue()))
47 return Plan.getOrAddLiveIn(U->getValue());
48 auto *Expanded = new VPExpandSCEVRecipe(Expr);
49 Plan.getEntry()->appendRecipe(Expanded);
50 return Expanded;
51}
52
53bool vputils::isHeaderMask(const VPValue *V, const VPlan &Plan) {
55 return true;
56
57 auto IsWideCanonicalIV = [](VPValue *A) {
61 };
62
63 VPValue *A, *B;
64
65 auto m_CanonicalScalarIVSteps = m_ScalarIVSteps(
68 m_One(), m_Specific(&Plan.getVF()));
69
71 return B == Plan.getTripCount() &&
72 (match(A, m_CanonicalScalarIVSteps) || IsWideCanonicalIV(A));
73
74 // For scalar plans, the header mask uses the scalar steps.
75 if (match(V, m_ICmp(m_CanonicalScalarIVSteps,
77 assert(Plan.hasScalarVFOnly() &&
78 "Non-scalar VF using scalar IV steps for header mask?");
79 return true;
80 }
81
82 return match(V, m_ICmp(m_VPValue(A), m_VPValue(B))) && IsWideCanonicalIV(A) &&
83 B == Plan.getBackedgeTakenCount();
84}
85
86/// Returns true if \p R propagates poison from any operand to its result.
90 [](const VPRecipeBase *) { return true; })
91 .Case([](const VPReplicateRecipe *Rep) {
92 // GEP and casts propagate poison from all operands.
93 unsigned Opcode = Rep->getOpcode();
94 return Opcode == Instruction::GetElementPtr ||
95 Instruction::isCast(Opcode);
96 })
97 .Default([](const VPRecipeBase *) { return false; });
98}
99
100/// Returns true if \p V being poison is guaranteed to trigger UB because it
101/// propagates to the address of a memory recipe.
102static bool poisonGuaranteesUB(const VPValue *V) {
105
106 Worklist.push_back(V);
107
108 while (!Worklist.empty()) {
109 const VPValue *Current = Worklist.pop_back_val();
110 if (!Visited.insert(Current).second)
111 continue;
112
113 for (VPUser *U : Current->users()) {
114 // Check if Current is used as an address operand for load/store.
115 if (auto *MemR = dyn_cast<VPWidenMemoryRecipe>(U)) {
116 if (MemR->getAddr() == Current)
117 return true;
118 continue;
119 }
120 if (auto *Rep = dyn_cast<VPReplicateRecipe>(U)) {
121 unsigned Opcode = Rep->getOpcode();
122 if ((Opcode == Instruction::Load && Rep->getOperand(0) == Current) ||
123 (Opcode == Instruction::Store && Rep->getOperand(1) == Current))
124 return true;
125 }
126
127 // Check if poison propagates through this recipe to any of its users.
128 auto *R = cast<VPRecipeBase>(U);
129 for (const VPValue *Op : R->operands()) {
130 if (Op == Current && propagatesPoisonFromRecipeOp(R)) {
131 Worklist.push_back(R->getVPSingleValue());
132 break;
133 }
134 }
135 }
136 }
137
138 return false;
139}
140
143 const Loop *L) {
144 ScalarEvolution &SE = *PSE.getSE();
146 Value *LiveIn = V->getUnderlyingValue();
147 if (LiveIn && SE.isSCEVable(LiveIn->getType()))
148 return SE.getSCEV(LiveIn);
149 return SE.getCouldNotCompute();
150 }
151
152 if (auto *RV = dyn_cast<VPRegionValue>(V)) {
153 assert(RV == RV->getDefiningRegion()->getCanonicalIV() &&
154 "RegionValue must be canonical IV");
155 if (!L)
156 return SE.getCouldNotCompute();
157 return SE.getAddRecExpr(SE.getZero(RV->getType()), SE.getOne(RV->getType()),
159 }
160
161 // Helper to create SCEVs for binary and unary operations.
162 auto CreateSCEV = [&](ArrayRef<VPValue *> Ops,
163 function_ref<const SCEV *(ArrayRef<SCEVUse>)> CreateFn)
164 -> const SCEV * {
166 for (VPValue *Op : Ops) {
167 const SCEV *S = getSCEVExprForVPValue(Op, PSE, L);
169 return SE.getCouldNotCompute();
170 SCEVOps.push_back(S);
171 }
172 return CreateFn(SCEVOps);
173 };
174
175 VPValue *LHSVal, *RHSVal;
176 if (match(V, m_Add(m_VPValue(LHSVal), m_VPValue(RHSVal))))
177 return CreateSCEV({LHSVal, RHSVal}, [&](ArrayRef<SCEVUse> Ops) {
178 return SE.getAddExpr(Ops[0], Ops[1], SCEV::FlagAnyWrap, 0);
179 });
180 if (match(V, m_Sub(m_VPValue(LHSVal), m_VPValue(RHSVal))))
181 return CreateSCEV({LHSVal, RHSVal}, [&](ArrayRef<SCEVUse> Ops) {
182 return SE.getMinusSCEV(Ops[0], Ops[1], SCEV::FlagAnyWrap, 0);
183 });
184 if (match(V, m_Not(m_VPValue(LHSVal)))) {
185 // not X = xor X, -1 = -1 - X
186 return CreateSCEV({LHSVal}, [&](ArrayRef<SCEVUse> Ops) {
187 return SE.getMinusSCEV(SE.getMinusOne(Ops[0]->getType()), Ops[0]);
188 });
189 }
190 if (match(V, m_Mul(m_VPValue(LHSVal), m_VPValue(RHSVal))))
191 return CreateSCEV({LHSVal, RHSVal}, [&](ArrayRef<SCEVUse> Ops) {
192 return SE.getMulExpr(Ops[0], Ops[1], SCEV::FlagAnyWrap, 0);
193 });
194 if (match(V,
196 return CreateSCEV({LHSVal, RHSVal}, [&](ArrayRef<SCEVUse> Ops) {
197 return SE.getUDivExpr(Ops[0], Ops[1]);
198 });
199 // Handle AND with constant mask: x & (2^n - 1) can be represented as x % 2^n.
200 const APInt *Mask;
201 if (match(V, m_c_BinaryAnd(m_VPValue(LHSVal), m_APInt(Mask))) &&
202 (*Mask + 1).isPowerOf2())
203 return CreateSCEV({LHSVal}, [&](ArrayRef<SCEVUse> Ops) {
204 return SE.getURemExpr(Ops[0], SE.getConstant(*Mask + 1));
205 });
206 if (match(V, m_Trunc(m_VPValue(LHSVal)))) {
207 const VPlan *Plan = V->getDefiningRecipe()->getParent()->getPlan();
208 Type *DestTy = VPTypeAnalysis(*Plan).inferScalarType(V);
209 return CreateSCEV({LHSVal}, [&](ArrayRef<SCEVUse> Ops) {
210 return SE.getTruncateExpr(Ops[0], DestTy);
211 });
212 }
213 if (match(V, m_ZExt(m_VPValue(LHSVal)))) {
214 const VPlan *Plan = V->getDefiningRecipe()->getParent()->getPlan();
215 Type *DestTy = VPTypeAnalysis(*Plan).inferScalarType(V);
216 return CreateSCEV({LHSVal}, [&](ArrayRef<SCEVUse> Ops) {
217 return SE.getZeroExtendExpr(Ops[0], DestTy);
218 });
219 }
220 if (match(V, m_SExt(m_VPValue(LHSVal)))) {
221 const VPlan *Plan = V->getDefiningRecipe()->getParent()->getPlan();
222 Type *DestTy = VPTypeAnalysis(*Plan).inferScalarType(V);
223
224 // Mirror SCEV's createSCEV handling for sext(sub nsw): push sign extension
225 // onto the operands before computing the subtraction.
226 VPValue *SubLHS, *SubRHS;
227 auto *SubR = dyn_cast<VPRecipeWithIRFlags>(LHSVal);
228 if (match(LHSVal, m_Sub(m_VPValue(SubLHS), m_VPValue(SubRHS))) && SubR &&
229 SubR->hasNoSignedWrap() && poisonGuaranteesUB(LHSVal)) {
230 const SCEV *V1 = getSCEVExprForVPValue(SubLHS, PSE, L);
231 const SCEV *V2 = getSCEVExprForVPValue(SubRHS, PSE, L);
233 return SE.getMinusSCEV(SE.getSignExtendExpr(V1, DestTy),
234 SE.getSignExtendExpr(V2, DestTy), SCEV::FlagNSW);
235 }
236
237 return CreateSCEV({LHSVal}, [&](ArrayRef<SCEVUse> Ops) {
238 return SE.getSignExtendExpr(Ops[0], DestTy);
239 });
240 }
241 if (match(V,
243 return CreateSCEV({LHSVal, RHSVal}, [&](ArrayRef<SCEVUse> Ops) {
244 return SE.getUMaxExpr(Ops[0], Ops[1]);
245 });
246 if (match(V,
248 return CreateSCEV({LHSVal, RHSVal}, [&](ArrayRef<SCEVUse> Ops) {
249 return SE.getSMaxExpr(Ops[0], Ops[1]);
250 });
251 if (match(V,
253 return CreateSCEV({LHSVal, RHSVal}, [&](ArrayRef<SCEVUse> Ops) {
254 return SE.getUMinExpr(Ops[0], Ops[1]);
255 });
256 if (match(V,
258 return CreateSCEV({LHSVal, RHSVal}, [&](ArrayRef<SCEVUse> Ops) {
259 return SE.getSMinExpr(Ops[0], Ops[1]);
260 });
261
263 Type *SourceElementType;
264 if (match(V, m_GetElementPtr(SourceElementType, Ops))) {
265 const SCEV *GEPExpr = CreateSCEV(Ops, [&](ArrayRef<SCEVUse> Ops) {
266 return SE.getGEPExpr(Ops.front(), Ops.drop_front(), SourceElementType);
267 });
268 return PSE.getPredicatedSCEV(GEPExpr);
269 }
270
271 // TODO: Support constructing SCEVs for more recipes as needed.
272 const VPRecipeBase *DefR = V->getDefiningRecipe();
273 const SCEV *Expr =
275 .Case([](const VPExpandSCEVRecipe *R) { return R->getSCEV(); })
276 .Case([&SE, &PSE, L](const VPWidenIntOrFpInductionRecipe *R) {
277 const SCEV *Step = getSCEVExprForVPValue(R->getStepValue(), PSE, L);
278 if (!L || isa<SCEVCouldNotCompute>(Step))
279 return SE.getCouldNotCompute();
280 const SCEV *Start =
281 getSCEVExprForVPValue(R->getStartValue(), PSE, L);
282 const SCEV *AddRec =
283 SE.getAddRecExpr(Start, Step, L, SCEV::FlagAnyWrap);
284 if (R->getTruncInst())
285 return SE.getTruncateExpr(AddRec, R->getScalarType());
286 return AddRec;
287 })
288 .Case([&SE, &PSE, L](const VPWidenPointerInductionRecipe *R) {
289 const SCEV *Start =
290 getSCEVExprForVPValue(R->getStartValue(), PSE, L);
291 if (!L || isa<SCEVCouldNotCompute>(Start))
292 return SE.getCouldNotCompute();
293 const SCEV *Step = getSCEVExprForVPValue(R->getStepValue(), PSE, L);
294 if (isa<SCEVCouldNotCompute>(Step))
295 return SE.getCouldNotCompute();
296 return SE.getAddRecExpr(Start, Step, L, SCEV::FlagAnyWrap);
297 })
298 .Case([&SE, &PSE, L](const VPDerivedIVRecipe *R) {
299 const SCEV *Start = getSCEVExprForVPValue(R->getOperand(0), PSE, L);
300 const SCEV *IV = getSCEVExprForVPValue(R->getOperand(1), PSE, L);
301 const SCEV *Scale = getSCEVExprForVPValue(R->getOperand(2), PSE, L);
302 if (any_of(ArrayRef({Start, IV, Scale}),
304 return SE.getCouldNotCompute();
305
306 return SE.getAddExpr(
307 SE.getTruncateOrSignExtend(Start, IV->getType()),
308 SE.getMulExpr(
309 IV, SE.getTruncateOrSignExtend(Scale, IV->getType())));
310 })
311 .Case([&SE, &PSE, L](const VPScalarIVStepsRecipe *R) {
312 const SCEV *IV = getSCEVExprForVPValue(R->getOperand(0), PSE, L);
313 const SCEV *Step = getSCEVExprForVPValue(R->getOperand(1), PSE, L);
315 return SE.getCouldNotCompute();
316 return SE.getTruncateOrSignExtend(IV, Step->getType());
317 })
318 .Default(
319 [&SE](const VPRecipeBase *) { return SE.getCouldNotCompute(); });
320
321 return PSE.getPredicatedSCEV(Expr);
322}
323
325 const Loop *L) {
326 // If address is an SCEVAddExpr, we require that all operands must be either
327 // be invariant or a (possibly sign-extend) affine AddRec.
328 if (auto *PtrAdd = dyn_cast<SCEVAddExpr>(Addr)) {
329 return all_of(PtrAdd->operands(), [&SE, L](const SCEV *Op) {
330 return SE.isLoopInvariant(Op, L) ||
331 match(Op, m_scev_SExt(m_scev_AffineAddRec(m_SCEV(), m_SCEV()))) ||
332 match(Op, m_scev_AffineAddRec(m_SCEV(), m_SCEV()));
333 });
334 }
335
336 // Otherwise, check if address is loop invariant or an affine add recurrence.
337 return SE.isLoopInvariant(Addr, L) ||
339}
340
341/// Returns true if \p Opcode preserves uniformity, i.e., if all operands are
342/// uniform, the result will also be uniform.
343static bool preservesUniformity(unsigned Opcode) {
344 if (Instruction::isBinaryOp(Opcode) || Instruction::isCast(Opcode))
345 return true;
346 switch (Opcode) {
347 case Instruction::Freeze:
348 case Instruction::GetElementPtr:
349 case Instruction::ICmp:
350 case Instruction::FCmp:
351 case Instruction::Select:
356 return true;
357 default:
358 return false;
359 }
360}
361
363 // Live-in, symbolic and region-values represent single-scalar values.
365 return true;
366
367 if (auto *Rep = dyn_cast<VPReplicateRecipe>(VPV)) {
368 const VPRegionBlock *RegionOfR = Rep->getRegion();
369 // Don't consider recipes in replicate regions as uniform yet; their first
370 // lane cannot be accessed when executing the replicate region for other
371 // lanes.
372 if (RegionOfR && RegionOfR->isReplicator())
373 return false;
374 return Rep->isSingleScalar() || (preservesUniformity(Rep->getOpcode()) &&
375 all_of(Rep->operands(), isSingleScalar));
376 }
379 if (auto *WidenR = dyn_cast<VPWidenRecipe>(VPV)) {
380 return preservesUniformity(WidenR->getOpcode()) &&
381 all_of(WidenR->operands(), isSingleScalar);
382 }
383 if (auto *VPI = dyn_cast<VPInstruction>(VPV))
384 return VPI->isSingleScalar() || VPI->isVectorToScalar() ||
385 (preservesUniformity(VPI->getOpcode()) &&
386 all_of(VPI->operands(), isSingleScalar));
387 if (auto *RR = dyn_cast<VPReductionRecipe>(VPV))
388 return !RR->isPartialReduction();
390 VPV))
391 return true;
392 if (auto *Expr = dyn_cast<VPExpressionRecipe>(VPV))
393 return Expr->isSingleScalar();
394
395 // VPExpandSCEVRecipes must be placed in the entry and are always uniform.
396 return isa<VPExpandSCEVRecipe>(VPV);
397}
398
400 // Live-ins and region values are uniform.
402 return true;
403
404 VPRecipeBase *R = V->getDefiningRecipe();
405 VPBasicBlock *VPBB = R ? R->getParent() : nullptr;
406 VPlan *Plan = VPBB ? VPBB->getPlan() : nullptr;
407 if (VPBB) {
408 if ((VPBB == Plan->getVectorPreheader() || VPBB == Plan->getEntry())) {
409 if (match(V->getDefiningRecipe(),
411 return false;
412 return all_of(R->operands(), isUniformAcrossVFsAndUFs);
413 }
414 }
415
417 .Case([](const VPDerivedIVRecipe *R) { return true; })
418 .Case([](const VPReplicateRecipe *R) {
419 // Be conservative about side-effects, except for the
420 // known-side-effecting assumes and stores, which we know will be
421 // uniform.
422 return R->isSingleScalar() &&
423 (!R->mayHaveSideEffects() ||
424 isa<AssumeInst, StoreInst>(R->getUnderlyingInstr())) &&
425 all_of(R->operands(), isUniformAcrossVFsAndUFs);
426 })
427 .Case([](const VPWidenRecipe *R) {
428 return preservesUniformity(R->getOpcode()) &&
429 all_of(R->operands(), isUniformAcrossVFsAndUFs);
430 })
431 .Case([](const VPInstruction *VPI) {
432 return preservesUniformity(VPI->getOpcode()) &&
434 })
435 .Case([](const VPWidenCastRecipe *R) {
436 // A cast is uniform according to its operand.
437 return isUniformAcrossVFsAndUFs(R->getOperand(0));
438 })
439 .Default([](const VPRecipeBase *) { // A value is considered non-uniform
440 // unless proven otherwise.
441 return false;
442 });
443}
444
446 auto DepthFirst = vp_depth_first_shallow(Plan.getEntry());
447 auto I = find_if(DepthFirst, [&VPDT](VPBlockBase *VPB) {
448 return VPBlockUtils::isHeader(VPB, VPDT);
449 });
450 return I == DepthFirst.end() ? nullptr : cast<VPBasicBlock>(*I);
451}
452
454 if (!R)
455 return 1;
456 if (auto *RR = dyn_cast<VPReductionPHIRecipe>(R))
457 return RR->getVFScaleFactor();
458 if (auto *RR = dyn_cast<VPReductionRecipe>(R))
459 return RR->getVFScaleFactor();
460 if (auto *ER = dyn_cast<VPExpressionRecipe>(R))
461 return ER->getVFScaleFactor();
462 assert(
465 "getting scaling factor of reduction-start-vector not implemented yet");
466 return 1;
467}
468
469std::optional<VPValue *>
472 VPBasicBlock *LatchVPBB) {
473 // Given a plain CFG VPlan loop with countable latch exiting block
474 // \p LatchVPBB, we're looking to match the recipes contributing to the
475 // uncountable exit condition comparison (here, vp<%4>) back to either
476 // live-ins or the address nodes for the load used as part of the uncountable
477 // exit comparison so that we can either move them within the loop, or copy
478 // them to the preheader depending on the chosen method for dealing with
479 // stores in uncountable exit loops.
480 //
481 // Currently, the address of the load is restricted to a GEP with 2 operands
482 // and a live-in base address. This constraint may be relaxed later.
483 //
484 // VPlan ' for UF>=1' {
485 // Live-in vp<%0> = VF * UF
486 // Live-in vp<%1> = vector-trip-count
487 // Live-in ir<20> = original trip-count
488 //
489 // ir-bb<entry>:
490 // Successor(s): scalar.ph, vector.ph
491 //
492 // vector.ph:
493 // Successor(s): for.body
494 //
495 // for.body:
496 // EMIT vp<%2> = phi ir<0>, vp<%index.next>
497 // EMIT-SCALAR ir<%iv> = phi [ ir<0>, vector.ph ], [ ir<%iv.next>, for.inc ]
498 // EMIT ir<%uncountable.addr> = getelementptr inbounds nuw ir<%pred>,ir<%iv>
499 // EMIT ir<%uncountable.val> = load ir<%uncountable.addr>
500 // EMIT ir<%uncountable.cond> = icmp sgt ir<%uncountable.val>, ir<500>
501 // EMIT vp<%3> = masked-cond ir<%uncountable.cond>
502 // Successor(s): for.inc
503 //
504 // for.inc:
505 // EMIT ir<%iv.next> = add nuw nsw ir<%iv>, ir<1>
506 // EMIT ir<%countable.cond> = icmp eq ir<%iv.next>, ir<20>
507 // EMIT vp<%index.next> = add nuw vp<%2>, vp<%0>
508 // EMIT vp<%4> = any-of ir<%3>
509 // EMIT vp<%5> = icmp eq vp<%index.next>, vp<%1>
510 // EMIT vp<%6> = or vp<%4>, vp<%5>
511 // EMIT branch-on-cond vp<%6>
512 // Successor(s): middle.block, for.body
513 //
514 // middle.block:
515 // Successor(s): ir-bb<exit>, scalar.ph
516 //
517 // ir-bb<exit>:
518 // No successors
519 //
520 // scalar.ph:
521 // }
522
523 // Find the uncountable loop exit condition.
524 VPValue *UncountableCondition = nullptr;
525 if (!match(LatchVPBB->getTerminator(),
527 m_AnyOf(m_VPValue(UncountableCondition)), m_VPValue()))))
528 return std::nullopt;
529
531 Worklist.push_back(UncountableCondition);
532 while (!Worklist.empty()) {
533 VPValue *V = Worklist.pop_back_val();
534
535 // Any value defined outside the loop does not need to be copied.
536 if (V->isDefinedOutsideLoopRegions())
537 continue;
538
539 // FIXME: Remove the single user restriction; it's here because we're
540 // starting with the simplest set of loops we can, and multiple
541 // users means needing to add PHI nodes in the transform.
542 if (V->getNumUsers() > 1)
543 return std::nullopt;
544
545 VPValue *Op1, *Op2;
546 // Walk back through recipes until we find at least one load from memory.
547 if (match(V, m_ICmp(m_VPValue(Op1), m_VPValue(Op2)))) {
548 Worklist.push_back(Op1);
549 Worklist.push_back(Op2);
550 Recipes.push_back(cast<VPInstruction>(V->getDefiningRecipe()));
552 VPRecipeBase *GepR = Op1->getDefiningRecipe();
553 // Only matching base + single offset term for now.
554 if (GepR->getNumOperands() != 2)
555 return std::nullopt;
556 // Matching a GEP with a loop-invariant base ptr.
558 m_LiveIn(), m_VPValue())))
559 return std::nullopt;
560 Recipes.push_back(cast<VPInstruction>(V->getDefiningRecipe()));
561 Recipes.push_back(cast<VPInstruction>(GepR));
562 GEPs.push_back(cast<VPInstruction>(GepR));
564 m_VPValue(Op1)))) {
565 Worklist.push_back(Op1);
566 Recipes.push_back(cast<VPInstruction>(V->getDefiningRecipe()));
567 } else
568 return std::nullopt;
569 }
570
571 // If we couldn't match anything, don't return the condition. It may be
572 // defined outside the loop.
573 if (Recipes.empty() || GEPs.empty())
574 return std::nullopt;
575
576 return UncountableCondition;
577}
578
580 VPRegionBlock *LoopRegion = Plan.getVectorLoopRegion();
581 SmallVector<VPValue *> WideCanonicalIVs;
582 auto *FoundWidenCanonicalIVUser = find_if(
584 assert(count_if(LoopRegion->getCanonicalIV()->users(),
586 "Must have at most one VPWideCanonicalIVRecipe");
587 if (FoundWidenCanonicalIVUser !=
588 LoopRegion->getCanonicalIV()->users().end()) {
589 auto *WideCanonicalIV =
590 cast<VPWidenCanonicalIVRecipe>(*FoundWidenCanonicalIVUser);
591 WideCanonicalIVs.push_back(WideCanonicalIV);
592 }
593
594 // Also include VPWidenIntOrFpInductionRecipes that represent a widened
595 // version of the canonical induction.
596 VPBasicBlock *HeaderVPBB = LoopRegion->getEntryBasicBlock();
597 for (VPRecipeBase &Phi : HeaderVPBB->phis()) {
598 auto *WidenOriginalIV = dyn_cast<VPWidenIntOrFpInductionRecipe>(&Phi);
599 if (WidenOriginalIV && WidenOriginalIV->isCanonical())
600 WideCanonicalIVs.push_back(WidenOriginalIV);
601 }
602
603 // Walk users of wide canonical IVs and find the single compare of the form
604 // (ICMP_ULE, WideCanonicalIV, backedge-taken-count).
605 VPSingleDefRecipe *HeaderMask = nullptr;
606 for (auto *Wide : WideCanonicalIVs) {
607 for (VPUser *U : Wide->users()) {
608 auto *VPI = dyn_cast<VPInstruction>(U);
609 if (!VPI || !vputils::isHeaderMask(VPI, Plan))
610 continue;
611
612 assert(VPI->getOperand(0) == Wide &&
613 "WidenCanonicalIV must be the first operand of the compare");
614 assert(!HeaderMask && "Multiple header masks found?");
615 HeaderMask = VPI;
616 }
617 }
618 return HeaderMask;
619}
620
623 VPBasicBlock *LastBB) {
624 assert(FirstBB->getParent() == LastBB->getParent() &&
625 "FirstBB and LastBB from different regions");
626#ifndef NDEBUG
627 bool InSingleSuccChain = false;
628 for (VPBlockBase *Succ = FirstBB; Succ; Succ = Succ->getSingleSuccessor())
629 InSingleSuccChain |= (Succ == LastBB);
630 assert(InSingleSuccChain &&
631 "LastBB unreachable from FirstBB in single-successor chain");
632#endif
633 auto Blocks = to_vector(
635 auto *LastIt = find(Blocks, LastBB);
636 assert(LastIt != Blocks.end() &&
637 "LastBB unreachable from FirstBB in depth-first traversal");
638 Blocks.erase(std::next(LastIt), Blocks.end());
639 return Blocks;
640}
641
643 const VPDominatorTree &VPDT) {
644 auto *VPBB = dyn_cast<VPBasicBlock>(VPB);
645 if (!VPBB)
646 return false;
647
648 // If VPBB is in a region R, VPBB is a loop header if R is a loop region with
649 // VPBB as its entry, i.e., free of predecessors.
650 if (auto *R = VPBB->getParent())
651 return !R->isReplicator() && !VPBB->hasPredecessors();
652
653 // A header dominates its second predecessor (the latch), with the other
654 // predecessor being the preheader
655 return VPB->getPredecessors().size() == 2 &&
656 VPDT.dominates(VPB, VPB->getPredecessors()[1]);
657}
658
660 const VPDominatorTree &VPDT) {
661 // A latch has a header as its last successor, with its other successors
662 // leaving the loop. A preheader OTOH has a header as its first (and only)
663 // successor.
664 return VPB->getNumSuccessors() >= 2 &&
666}
667
668std::optional<MemoryLocation>
670 auto *M = dyn_cast<VPIRMetadata>(&R);
671 if (!M)
672 return std::nullopt;
674 // Populate noalias metadata from VPIRMetadata.
675 if (MDNode *NoAliasMD = M->getMetadata(LLVMContext::MD_noalias))
676 Loc.AATags.NoAlias = NoAliasMD;
677 if (MDNode *AliasScopeMD = M->getMetadata(LLVMContext::MD_alias_scope))
678 Loc.AATags.Scope = AliasScopeMD;
679 return Loc;
680}
681
683 VPRegionBlock *LoopRegion = Plan.getVectorLoopRegion();
684 VPRegionValue *CanIV = LoopRegion->getCanonicalIV();
685 assert(CanIV && "Expected loop region to have a canonical IV");
686
687 VPSymbolicValue &VFxUF = Plan.getVFxUF();
688
689 // Check if \p Step matches the expected increment step, accounting for
690 // materialization of VFxUF and UF.
691 auto IsIncrementStep = [&](VPValue *Step) -> bool {
692 if (!VFxUF.isMaterialized())
693 return Step == &VFxUF;
694
695 VPSymbolicValue &UF = Plan.getUF();
696 if (!UF.isMaterialized())
697 return Step == &UF;
698
699 unsigned ConcreteUF = Plan.getConcreteUF();
700 // Fixed VF: step is just the concrete UF.
701 if (match(Step, m_SpecificInt(ConcreteUF)))
702 return true;
703
704 // Scalable VF: step involves VScale.
705 if (ConcreteUF == 1)
707 if (match(Step, m_c_Mul(m_SpecificInt(ConcreteUF),
709 return true;
710 // mul(VScale, ConcreteUF) may have been simplified to
711 // shl(VScale, log2(ConcreteUF)) when ConcreteUF is a power of 2.
712 return isPowerOf2_32(ConcreteUF) &&
715 m_SpecificInt(Log2_32(ConcreteUF))));
716 };
717
718 VPInstruction *Increment = nullptr;
719 for (VPUser *U : CanIV->users()) {
720 VPValue *Step;
721 if (match(U, m_c_Add(m_Specific(CanIV), m_VPValue(Step))) &&
722 IsIncrementStep(Step)) {
723 assert(!Increment && "There must be a unique increment");
725 }
726 }
727
728 assert((!VFxUF.isMaterialized() || Increment) &&
729 "After materializing VFxUF, an increment must exist");
730 assert((!Increment ||
731 LoopRegion->hasCanonicalIVNUW() == Increment->hasNoUnsignedWrap()) &&
732 "NUW flag in region and increment must match");
733 return Increment;
734}
735
736/// Find the ComputeReductionResult recipe for \p PhiR, looking through selects
737/// inserted for predicated reductions or tail folding.
739 VPValue *BackedgeVal = PhiR->getBackedgeValue();
741 BackedgeVal))
742 return Res;
743
744 // Look through selects inserted for tail folding or predicated reductions.
746 BackedgeVal, m_Select(m_VPValue(), m_VPValue(), m_VPValue()));
747 if (!SelR)
748 return nullptr;
751}
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
static GCRegistry::Add< ErlangGC > A("erlang", "erlang-compatible garbage collector")
static GCRegistry::Add< OcamlGC > B("ocaml", "ocaml 3.10-compatible GC")
const AbstractManglingParser< Derived, Alloc >::OperatorInfo AbstractManglingParser< Derived, Alloc >::Ops[]
#define I(x, y, z)
Definition MD5.cpp:57
This file provides utility analysis objects describing memory locations.
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.
static std::optional< unsigned > getOpcode(ArrayRef< VPValue * > Values)
Returns the opcode of Values or ~0 if they do not all agree.
Definition VPlanSLP.cpp:247
static bool propagatesPoisonFromRecipeOp(const VPRecipeBase *R)
Returns true if R propagates poison from any operand to its result.
static bool preservesUniformity(unsigned Opcode)
Returns true if Opcode preserves uniformity, i.e., if all operands are uniform, the result will also ...
static bool poisonGuaranteesUB(const VPValue *V)
Returns true if V being poison is guaranteed to trigger UB because it propagates to the address of a ...
static const uint32_t IV[8]
Definition blake3_impl.h:83
Class for arbitrary precision integers.
Definition APInt.h:78
ArrayRef - Represent a constant reference to an array (0 or more elements consecutively in memory),...
Definition ArrayRef.h:40
bool dominates(const DomTreeNodeBase< NodeT > *A, const DomTreeNodeBase< NodeT > *B) const
dominates - Returns true iff A dominates B.
bool isCast() const
bool isBinaryOp() const
Represents a single loop in the control flow graph.
Definition LoopInfo.h:40
Metadata node.
Definition Metadata.h:1080
Representation for a specific memory location.
An interface layer with SCEV used to manage how we see SCEV expressions for values in the context of ...
ScalarEvolution * getSE() const
Returns the ScalarEvolution analysis used.
LLVM_ABI const SCEV * getPredicatedSCEV(const SCEV *Expr)
Returns the rewritten SCEV for Expr in the context of the current SCEV predicate.
This class represents an analyzed expression in the program.
static constexpr auto FlagAnyWrap
static constexpr auto FlagNSW
LLVM_ABI Type * getType() const
Return the LLVM type of this SCEV expression.
The main scalar evolution driver.
LLVM_ABI const SCEV * getUDivExpr(SCEVUse LHS, SCEVUse RHS)
Get a canonical unsigned division expression, or something simpler if possible.
LLVM_ABI const SCEV * getURemExpr(SCEVUse LHS, SCEVUse RHS)
Represents an unsigned remainder expression based on unsigned division.
LLVM_ABI const SCEV * getSMinExpr(SCEVUse LHS, SCEVUse RHS)
const SCEV * getZero(Type *Ty)
Return a SCEV for the constant 0 of a specific type.
LLVM_ABI const SCEV * getConstant(ConstantInt *V)
LLVM_ABI const SCEV * getSCEV(Value *V)
Return a SCEV expression for the full generality of the specified expression.
LLVM_ABI const SCEV * getMinusSCEV(SCEVUse LHS, SCEVUse RHS, SCEV::NoWrapFlags Flags=SCEV::FlagAnyWrap, unsigned Depth=0)
Return LHS-RHS.
LLVM_ABI const SCEV * getAddRecExpr(SCEVUse Start, SCEVUse Step, const Loop *L, SCEV::NoWrapFlags Flags)
Get an add recurrence expression for the specified loop.
const SCEV * getOne(Type *Ty)
Return a SCEV for the constant 1 of a specific type.
LLVM_ABI bool isLoopInvariant(const SCEV *S, const Loop *L)
Return true if the value of the given SCEV is unchanging in the specified loop.
LLVM_ABI const SCEV * getZeroExtendExpr(const SCEV *Op, Type *Ty, unsigned Depth=0)
LLVM_ABI bool isSCEVable(Type *Ty) const
Test if values of the given type are analyzable within the SCEV framework.
LLVM_ABI const SCEV * getTruncateExpr(const SCEV *Op, Type *Ty, unsigned Depth=0)
LLVM_ABI const SCEV * getUMaxExpr(SCEVUse LHS, SCEVUse RHS)
const SCEV * getMinusOne(Type *Ty)
Return a SCEV for the constant -1 of a specific type.
LLVM_ABI const SCEV * getCouldNotCompute()
LLVM_ABI const SCEV * getMulExpr(SmallVectorImpl< SCEVUse > &Ops, SCEV::NoWrapFlags Flags=SCEV::FlagAnyWrap, unsigned Depth=0)
Get a canonical multiply expression, or something simpler if possible.
LLVM_ABI const SCEV * getSignExtendExpr(const SCEV *Op, Type *Ty, unsigned Depth=0)
LLVM_ABI const SCEV * getAddExpr(SmallVectorImpl< SCEVUse > &Ops, SCEV::NoWrapFlags Flags=SCEV::FlagAnyWrap, unsigned Depth=0)
Get a canonical add expression, or something simpler if possible.
LLVM_ABI const SCEV * getSMaxExpr(SCEVUse LHS, SCEVUse RHS)
LLVM_ABI const SCEV * getGEPExpr(GEPOperator *GEP, ArrayRef< SCEVUse > IndexExprs)
Returns an expression for a GEP.
LLVM_ABI const SCEV * getUMinExpr(SCEVUse LHS, SCEVUse RHS, bool Sequential=false)
LLVM_ABI const SCEV * getTruncateOrSignExtend(const SCEV *V, Type *Ty, unsigned Depth=0)
Return a SCEV corresponding to a conversion of the input value to the specified type.
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...
void push_back(const T &Elt)
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
This class implements a switch-like dispatch statement for a value of 'T' using dyn_cast functionalit...
Definition TypeSwitch.h:89
TypeSwitch< T, ResultT > & Case(CallableT &&caseFn)
Add a case on the given type.
Definition TypeSwitch.h:98
The instances of the Type class are immutable: once they are created, they are never changed.
Definition Type.h:46
VPBasicBlock serves as the leaf of the Hierarchical Control-Flow Graph.
Definition VPlan.h:4160
void appendRecipe(VPRecipeBase *Recipe)
Augment the existing recipes of a VPBasicBlock with an additional Recipe as the last recipe.
Definition VPlan.h:4235
iterator_range< iterator > phis()
Returns an iterator range over the PHI-like recipes in the block.
Definition VPlan.h:4248
VPRecipeBase * getTerminator()
If the block has multiple successors, return the branch recipe terminating the block.
Definition VPlan.cpp:644
VPBlockBase is the building block of the Hierarchical Control-Flow Graph.
Definition VPlan.h:98
VPRegionBlock * getParent()
Definition VPlan.h:190
size_t getNumSuccessors() const
Definition VPlan.h:241
const VPBlocksTy & getPredecessors() const
Definition VPlan.h:226
VPlan * getPlan()
Definition VPlan.cpp:177
const VPBasicBlock * getEntryBasicBlock() const
Definition VPlan.cpp:182
VPBlockBase * getSingleSuccessor() const
Definition VPlan.h:231
const VPBlocksTy & getSuccessors() const
Definition VPlan.h:215
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.
static auto blocksOnly(T &&Range)
Return an iterator range over Range which only includes BlockTy blocks.
Definition VPlanUtils.h:276
static SmallVector< VPBasicBlock * > blocksInSingleSuccessorChainBetween(VPBasicBlock *FirstBB, VPBasicBlock *LastBB)
Returns the blocks between FirstBB and LastBB, where FirstBB to LastBB forms a single-sucessor chain.
A recipe for converting the input value IV value to the corresponding value of an IV with different s...
Definition VPlan.h:3909
Template specialization of the standard LLVM dominator tree utility for VPBlockBases.
Recipe to expand a SCEV expression.
Definition VPlan.h:3757
virtual VPValue * getBackedgeValue()
Returns the incoming value from the loop backedge.
Definition VPlan.h:2342
This is a concrete Recipe that models a single VPlan-level instruction.
Definition VPlan.h:1223
@ ReductionStartVector
Start vector for reductions with 3 operands: the original start value, the identity value for the red...
Definition VPlan.h:1318
unsigned getOpcode() const
Definition VPlan.h:1402
VPRecipeBase is a base class modeling a sequence of one or more output IR instructions.
Definition VPlan.h:406
A recipe for handling reduction phis.
Definition VPlan.h:2686
VPRegionBlock represents a collection of VPBasicBlocks and VPRegionBlocks which form a Single-Entry-S...
Definition VPlan.h:4370
bool isReplicator() const
An indicator whether this region is to generate multiple replicated instances of output IR correspond...
Definition VPlan.h:4446
bool hasCanonicalIVNUW() const
Indicates if NUW is set for the canonical IV increment, for loop regions.
Definition VPlan.h:4495
VPRegionValue * getCanonicalIV()
Return the canonical induction variable of the region, null for replicating regions.
Definition VPlan.h:4482
VPValues defined by a VPRegionBlock, like the canonical IV.
Definition VPlanValue.h:209
VPReplicateRecipe replicates a given instruction producing multiple scalar copies of the original sca...
Definition VPlan.h:3196
unsigned getOpcode() const
Definition VPlan.h:3266
A recipe for handling phi nodes of integer and floating-point inductions, producing their scalar valu...
Definition VPlan.h:3980
VPSingleDef is a base class for recipes for modeling a sequence of one or more output IR that define ...
Definition VPlan.h:606
An analysis for type-inference for VPValues.
Type * inferScalarType(const VPValue *V)
Infer the type of V. Returns the scalar type of V.
This class augments VPValue with operands which provide the inverse def-use edges from VPValue's user...
Definition VPlanValue.h:329
operand_range operands()
Definition VPlanValue.h:397
unsigned getNumOperands() const
Definition VPlanValue.h:367
This is the base class of the VPlan Def/Use graph, used for modeling the data flow into,...
Definition VPlanValue.h:49
VPRecipeBase * getDefiningRecipe()
Returns the recipe defining this VPValue or nullptr if it is not defined by a recipe,...
Definition VPlan.cpp:127
user_range users()
Definition VPlanValue.h:155
VPWidenCastRecipe is a recipe to create vector cast instructions.
Definition VPlan.h:1837
A recipe for handling GEP instructions.
Definition VPlan.h:2087
A recipe for handling phi nodes of integer and floating-point inductions, producing their vector valu...
Definition VPlan.h:2448
VPWidenRecipe is a recipe for producing a widened instruction using the opcode and operands of the re...
Definition VPlan.h:1781
VPlan models a candidate for vectorization, encoding various decisions take to produce efficient outp...
Definition VPlan.h:4518
VPBasicBlock * getEntry()
Definition VPlan.h:4610
VPValue * getTripCount() const
The trip count of the original loop.
Definition VPlan.h:4669
VPSymbolicValue & getVFxUF()
Returns VF * UF of the vector loop region.
Definition VPlan.h:4708
VPValue * getBackedgeTakenCount() const
Definition VPlan.h:4695
VPIRValue * getOrAddLiveIn(Value *V)
Gets the live-in VPIRValue for V or adds a new live-in (if none exists yet) for V.
Definition VPlan.h:4782
LLVM_ABI_FOR_TEST VPRegionBlock * getVectorLoopRegion()
Returns the VPRegionBlock of the vector loop.
Definition VPlan.cpp:1095
unsigned getConcreteUF() const
Returns the concrete UF of the plan, after unrolling.
Definition VPlan.h:4760
VPSymbolicValue & getUF()
Returns the UF of the vector loop region.
Definition VPlan.h:4705
bool hasScalarVFOnly() const
Definition VPlan.h:4750
VPBasicBlock * getVectorPreheader()
Returns the preheader of the vector loop region, if one exists, or null otherwise.
Definition VPlan.h:4615
VPSymbolicValue & getVF()
Returns the VF of the vector loop region.
Definition VPlan.h:4701
LLVM Value Representation.
Definition Value.h:75
Type * getType() const
All values are typed, get the type of this value.
Definition Value.h:255
An efficient, type-erasing, non-owning reference to a callable.
IteratorT end() const
SpecificConstantMatch m_ZeroInt()
Convenience matchers for specific integer values.
BinaryOp_match< SrcTy, SpecificConstantMatch, TargetOpcode::G_XOR, true > m_Not(const SrcTy &&Src)
Matches a register not-ed by a G_XOR.
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)
ap_match< APInt > m_APInt(const APInt *&Res)
Match a ConstantInt or splatted ConstantVector, binding the specified pointer to the contained APInt.
CastInst_match< OpTy, TruncInst > m_Trunc(const OpTy &Op)
Matches Trunc.
specific_intval< false > m_SpecificInt(const APInt &V)
Match a specific integer value or vector with all elements equal to the value.
bool match(Val *V, const Pattern &P)
specificval_ty m_Specific(const Value *V)
Match if we have a specific specified value.
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))
ThreeOps_match< Cond, LHS, RHS, Instruction::Select > m_Select(const Cond &C, const LHS &L, const RHS &R)
Matches SelectInst.
BinaryOp_match< LHS, RHS, Instruction::Mul > m_Mul(const LHS &L, const RHS &R)
CastInst_match< OpTy, ZExtInst > m_ZExt(const OpTy &Op)
Matches ZExt.
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.
CmpClass_match< LHS, RHS, ICmpInst > m_ICmp(CmpPredicate &Pred, const LHS &L, const RHS &R)
CastInst_match< OpTy, SExtInst > m_SExt(const OpTy &Op)
Matches SExt.
BinaryOp_match< LHS, RHS, Instruction::Mul, true > m_c_Mul(const LHS &L, const RHS &R)
Matches a Mul with LHS and RHS in either order.
BinaryOp_match< LHS, RHS, Instruction::Sub > m_Sub(const LHS &L, const RHS &R)
bool match(const SCEV *S, const Pattern &P)
SCEVAffineAddRec_match< Op0_t, Op1_t, match_isa< const Loop > > m_scev_AffineAddRec(const Op0_t &Op0, const Op1_t &Op1)
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::AnyOf > m_AnyOf()
AllRecipe_commutative_match< Instruction::Or, Op0_t, Op1_t > m_c_BinaryOr(const Op0_t &Op0, const Op1_t &Op1)
AllRecipe_match< Opcode, Op0_t, Op1_t > m_Binary(const Op0_t &Op0, const Op1_t &Op1)
VPInstruction_match< VPInstruction::ActiveLaneMask, Op0_t, Op1_t, Op2_t > m_ActiveLaneMask(const Op0_t &Op0, const Op1_t &Op1, const Op2_t &Op2)
auto m_GetElementPtr(const Op0_t &Op0, const Op1_t &Op1)
auto m_VPValue()
Match an arbitrary VPValue and ignore it.
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()
auto m_ScalarIVSteps(const Op0_t &Op0, const Op1_t &Op1, const Op2_t &Op2)
bool isSingleScalar(const VPValue *VPV)
Returns true if VPV is a single scalar, either because it produces the same value for all lanes or on...
bool isUniformAcrossVFsAndUFs(VPValue *V)
Checks if V is uniform across all VF lanes and UF parts.
VPValue * getOrCreateVPValueForSCEVExpr(VPlan &Plan, const SCEV *Expr)
Get or create a VPValue that corresponds to the expansion of Expr.
VPBasicBlock * getFirstLoopHeader(VPlan &Plan, VPDominatorTree &VPDT)
Returns the header block of the first, top-level loop, or null if none exist.
bool isAddressSCEVForCost(const SCEV *Addr, ScalarEvolution &SE, const Loop *L)
Returns true if Addr is an address SCEV that can be passed to TTI::getAddressComputationCost,...
bool onlyFirstPartUsed(const VPValue *Def)
Returns true if only the first part of Def is used.
VPInstruction * findComputeReductionResult(VPReductionPHIRecipe *PhiR)
Find the ComputeReductionResult recipe for PhiR, looking through selects inserted for predicated redu...
VPInstruction * findCanonicalIVIncrement(VPlan &Plan)
Find the canonical IV increment of Plan's vector loop region.
std::optional< MemoryLocation > getMemoryLocation(const VPRecipeBase &R)
Return a MemoryLocation for R with noalias metadata populated from R, if the recipe is supported and ...
bool onlyFirstLaneUsed(const VPValue *Def)
Returns true if only the first lane of Def is used.
VPSingleDefRecipe * findHeaderMask(VPlan &Plan)
Collect the header mask with the pattern: (ICMP_ULE, WideCanonicalIV, backedge-taken-count) TODO: Int...
bool onlyScalarValuesUsed(const VPValue *Def)
Returns true if only scalar values of Def are used by all users.
static VPRecipeBase * findUserOf(VPValue *V, const MatchT &P)
If V is used by a recipe matching pattern P, return it.
Definition VPlanUtils.h:132
LLVM_ABI_FOR_TEST std::optional< VPValue * > getRecipesForUncountableExit(SmallVectorImpl< VPInstruction * > &Recipes, SmallVectorImpl< VPInstruction * > &GEPs, VPBasicBlock *LatchVPBB)
Returns the VPValue representing the uncountable exit comparison used by AnyOf if the recipes it depe...
const SCEV * getSCEVExprForVPValue(const VPValue *V, PredicatedScalarEvolution &PSE, const Loop *L=nullptr)
Return the SCEV expression for V.
unsigned getVFScaleFactor(VPRecipeBase *R)
Get the VF scaling factor applied to the recipe's output, if the recipe has one.
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 find(R &&Range, const T &Val)
Provide wrappers to std::find which take ranges instead of having to pass begin/end explicitly.
Definition STLExtras.h:1765
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:1739
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
iterator_range< df_iterator< VPBlockDeepTraversalWrapper< VPBlockBase * > > > vp_depth_first_deep(VPBlockBase *G)
Returns an iterator range to traverse the graph starting at G in depth-first order while traversing t...
Definition VPlanCFG.h:265
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:1746
unsigned Log2_32(uint32_t Value)
Return the floor log base 2 of the specified value, -1 if the value is zero.
Definition MathExtras.h:331
constexpr bool isPowerOf2_32(uint32_t Value)
Return true if the argument is a power of two > 0.
Definition MathExtras.h:279
SmallVector< ValueTypeFromRangeType< R >, Size > to_vector(R &&Range)
Given a range of type R, iterate the entire range and return a SmallVector with elements of the vecto...
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
DWARFExpression::Operation Op
ArrayRef(const T &OneElt) -> ArrayRef< T >
auto count_if(R &&Range, UnaryPredicate P)
Wrapper function around std::count_if to count the number of times an element satisfying a given pred...
Definition STLExtras.h:2019
decltype(auto) cast(const From &Val)
cast<X> - Return the argument parameter cast to the specified type.
Definition Casting.h:559
auto find_if(R &&Range, UnaryPredicate P)
Provide wrappers to std::find_if which take ranges instead of having to pass begin/end explicitly.
Definition STLExtras.h:1772
@ Increment
Incrementally increasing token ID.
Definition AllocToken.h:26
@ Default
The result value is uniform if and only if all operands are uniform.
Definition Uniformity.h:20
constexpr detail::IsaCheckPredicate< Types... > IsaPred
Function object wrapper for the llvm::isa type check.
Definition Casting.h:866
A symbolic live-in VPValue, used for values like vector trip count, VF, and VFxUF.
Definition VPlanValue.h:280
bool isMaterialized() const
Returns true if this symbolic value has been materialized.
Definition VPlanValue.h:288