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 auto MaskMatch = m_ICmp(m_VPValue(A), m_VPValue(B));
83 return (match(V, m_CombineOr(MaskMatch, m_Reverse(MaskMatch)))) &&
84 IsWideCanonicalIV(A) && B == Plan.getBackedgeTakenCount();
85}
86
87/// Returns true if \p R propagates poison from any operand to its result.
91 [](const VPRecipeBase *) { return true; })
92 .Case([](const VPReplicateRecipe *Rep) {
93 // GEP and casts propagate poison from all operands.
94 unsigned Opcode = Rep->getOpcode();
95 return Opcode == Instruction::GetElementPtr ||
96 Instruction::isCast(Opcode);
97 })
98 .Default([](const VPRecipeBase *) { return false; });
99}
100
101/// Returns true if \p V being poison is guaranteed to trigger UB because it
102/// propagates to the address of a memory recipe.
103static bool poisonGuaranteesUB(const VPValue *V) {
106
107 Worklist.push_back(V);
108
109 while (!Worklist.empty()) {
110 const VPValue *Current = Worklist.pop_back_val();
111 if (!Visited.insert(Current).second)
112 continue;
113
114 for (VPUser *U : Current->users()) {
115 // Check if Current is used as an address operand for load/store.
117 if (MemR->getAddr() == Current)
118 return true;
119 continue;
120 }
121 if (auto *Rep = dyn_cast<VPReplicateRecipe>(U)) {
122 unsigned Opcode = Rep->getOpcode();
123 if ((Opcode == Instruction::Load && Rep->getOperand(0) == Current) ||
124 (Opcode == Instruction::Store && Rep->getOperand(1) == Current))
125 return true;
126 }
127
128 // Check if poison propagates through this recipe to any of its users.
129 auto *R = cast<VPRecipeBase>(U);
130 for (const VPValue *Op : R->operands()) {
131 if (Op == Current && propagatesPoisonFromRecipeOp(R)) {
132 Worklist.push_back(R->getVPSingleValue());
133 break;
134 }
135 }
136 }
137 }
138
139 return false;
140}
141
143 // Like IR stripPointerCasts, look through GEPs with all-zero indices and
144 // casts to find a root GEP VPInstruction.
145 while (auto *PtrVPI = dyn_cast<VPInstruction>(Ptr)) {
146 unsigned Opcode = PtrVPI->getOpcode();
147 if (Opcode == Instruction::GetElementPtr) {
148 if (any_of(drop_begin(PtrVPI->operands()),
149 [](VPValue *Op) { return !match(Op, m_ZeroInt()); }))
150 return PtrVPI->getGEPNoWrapFlags();
151 Ptr = PtrVPI->getOperand(0);
152 continue;
153 }
154 if (Opcode != Instruction::BitCast && Opcode != Instruction::AddrSpaceCast)
155 break;
156 Ptr = PtrVPI->getOperand(0);
157 }
158 return GEPNoWrapFlags::none();
159}
160
163 const Loop *L) {
164 ScalarEvolution &SE = *PSE.getSE();
166 Value *LiveIn = V->getUnderlyingValue();
167 if (LiveIn && SE.isSCEVable(LiveIn->getType()))
168 return SE.getSCEV(LiveIn);
169 return SE.getCouldNotCompute();
170 }
171
172 if (auto *RV = dyn_cast<VPRegionValue>(V)) {
173 assert(RV == RV->getDefiningRegion()->getCanonicalIV() &&
174 "RegionValue must be canonical IV");
175 if (!L)
176 return SE.getCouldNotCompute();
177 return SE.getAddRecExpr(SE.getZero(RV->getType()), SE.getOne(RV->getType()),
179 }
180
181 // Helper to create SCEVs for binary and unary operations.
182 auto CreateSCEV = [&](ArrayRef<VPValue *> Ops,
183 function_ref<const SCEV *(ArrayRef<SCEVUse>)> CreateFn)
184 -> const SCEV * {
186 for (VPValue *Op : Ops) {
187 const SCEV *S = getSCEVExprForVPValue(Op, PSE, L);
189 return SE.getCouldNotCompute();
190 SCEVOps.push_back(S);
191 }
192 return CreateFn(SCEVOps);
193 };
194
195 VPValue *LHSVal, *RHSVal;
196 if (match(V, m_Add(m_VPValue(LHSVal), m_VPValue(RHSVal))))
197 return CreateSCEV({LHSVal, RHSVal}, [&](ArrayRef<SCEVUse> Ops) {
198 return SE.getAddExpr(Ops[0], Ops[1], SCEV::FlagAnyWrap, 0);
199 });
200 if (match(V, m_Sub(m_VPValue(LHSVal), m_VPValue(RHSVal))))
201 return CreateSCEV({LHSVal, RHSVal}, [&](ArrayRef<SCEVUse> Ops) {
202 return SE.getMinusSCEV(Ops[0], Ops[1], SCEV::FlagAnyWrap, 0);
203 });
204 if (match(V, m_Not(m_VPValue(LHSVal)))) {
205 // not X = xor X, -1 = -1 - X
206 return CreateSCEV({LHSVal}, [&](ArrayRef<SCEVUse> Ops) {
207 return SE.getMinusSCEV(SE.getMinusOne(Ops[0]->getType()), Ops[0]);
208 });
209 }
210 if (match(V, m_Mul(m_VPValue(LHSVal), m_VPValue(RHSVal))))
211 return CreateSCEV({LHSVal, RHSVal}, [&](ArrayRef<SCEVUse> Ops) {
212 return SE.getMulExpr(Ops[0], Ops[1], SCEV::FlagAnyWrap, 0);
213 });
214 if (match(V,
216 return CreateSCEV({LHSVal, RHSVal}, [&](ArrayRef<SCEVUse> Ops) {
217 return SE.getUDivExpr(Ops[0], Ops[1]);
218 });
219 // Handle AND with constant mask: x & (2^n - 1) can be represented as x % 2^n.
220 const APInt *Mask;
221 if (match(V, m_c_BinaryAnd(m_VPValue(LHSVal), m_APInt(Mask))) &&
222 (*Mask + 1).isPowerOf2())
223 return CreateSCEV({LHSVal}, [&](ArrayRef<SCEVUse> Ops) {
224 return SE.getURemExpr(Ops[0], SE.getConstant(*Mask + 1));
225 });
226 if (match(V, m_Trunc(m_VPValue(LHSVal)))) {
227 const VPlan *Plan = V->getDefiningRecipe()->getParent()->getPlan();
228 Type *DestTy = VPTypeAnalysis(*Plan).inferScalarType(V);
229 return CreateSCEV({LHSVal}, [&](ArrayRef<SCEVUse> Ops) {
230 return SE.getTruncateExpr(Ops[0], DestTy);
231 });
232 }
233 if (match(V, m_ZExt(m_VPValue(LHSVal)))) {
234 const VPlan *Plan = V->getDefiningRecipe()->getParent()->getPlan();
235 Type *DestTy = VPTypeAnalysis(*Plan).inferScalarType(V);
236 return CreateSCEV({LHSVal}, [&](ArrayRef<SCEVUse> Ops) {
237 return SE.getZeroExtendExpr(Ops[0], DestTy);
238 });
239 }
240 if (match(V, m_SExt(m_VPValue(LHSVal)))) {
241 const VPlan *Plan = V->getDefiningRecipe()->getParent()->getPlan();
242 Type *DestTy = VPTypeAnalysis(*Plan).inferScalarType(V);
243
244 // Mirror SCEV's createSCEV handling for sext(sub nsw): push sign extension
245 // onto the operands before computing the subtraction.
246 VPValue *SubLHS, *SubRHS;
247 auto *SubR = dyn_cast<VPRecipeWithIRFlags>(LHSVal);
248 if (match(LHSVal, m_Sub(m_VPValue(SubLHS), m_VPValue(SubRHS))) && SubR &&
249 SubR->hasNoSignedWrap() && poisonGuaranteesUB(LHSVal)) {
250 const SCEV *V1 = getSCEVExprForVPValue(SubLHS, PSE, L);
251 const SCEV *V2 = getSCEVExprForVPValue(SubRHS, PSE, L);
253 return SE.getMinusSCEV(SE.getSignExtendExpr(V1, DestTy),
254 SE.getSignExtendExpr(V2, DestTy), SCEV::FlagNSW);
255 }
256
257 return CreateSCEV({LHSVal}, [&](ArrayRef<SCEVUse> Ops) {
258 return SE.getSignExtendExpr(Ops[0], DestTy);
259 });
260 }
261 if (match(V,
263 return CreateSCEV({LHSVal, RHSVal}, [&](ArrayRef<SCEVUse> Ops) {
264 return SE.getUMaxExpr(Ops[0], Ops[1]);
265 });
266 if (match(V,
268 return CreateSCEV({LHSVal, RHSVal}, [&](ArrayRef<SCEVUse> Ops) {
269 return SE.getSMaxExpr(Ops[0], Ops[1]);
270 });
271 if (match(V,
273 return CreateSCEV({LHSVal, RHSVal}, [&](ArrayRef<SCEVUse> Ops) {
274 return SE.getUMinExpr(Ops[0], Ops[1]);
275 });
276 if (match(V,
278 return CreateSCEV({LHSVal, RHSVal}, [&](ArrayRef<SCEVUse> Ops) {
279 return SE.getSMinExpr(Ops[0], Ops[1]);
280 });
282 return CreateSCEV({LHSVal}, [&](ArrayRef<SCEVUse> Ops) {
283 // is_int_min_poison is local to this intrinsic: poison on INT_MIN is
284 // not proof that the input is never INT_MIN, nor that poison reaches
285 // UB. Do not translate it to SCEV's global IsNSW flag.
286 return SE.getAbsExpr(Ops[0], /*IsNSW=*/false);
287 });
288
290 Type *SourceElementType;
291 if (match(V, m_GetElementPtr(SourceElementType, Ops))) {
292 const SCEV *GEPExpr = CreateSCEV(Ops, [&](ArrayRef<SCEVUse> Ops) {
293 return SE.getGEPExpr(Ops.front(), Ops.drop_front(), SourceElementType);
294 });
295 return PSE.getPredicatedSCEV(GEPExpr);
296 }
297
298 // TODO: Support constructing SCEVs for more recipes as needed.
299 const VPRecipeBase *DefR = V->getDefiningRecipe();
300 const SCEV *Expr =
302 .Case([](const VPExpandSCEVRecipe *R) { return R->getSCEV(); })
303 .Case([&SE, &PSE, L](const VPWidenIntOrFpInductionRecipe *R) {
304 const SCEV *Step = getSCEVExprForVPValue(R->getStepValue(), PSE, L);
305 if (!L || isa<SCEVCouldNotCompute>(Step))
306 return SE.getCouldNotCompute();
307 const SCEV *Start =
308 getSCEVExprForVPValue(R->getStartValue(), PSE, L);
309 const SCEV *AddRec =
310 SE.getAddRecExpr(Start, Step, L, SCEV::FlagAnyWrap);
311 if (R->getTruncInst())
312 return SE.getTruncateExpr(AddRec, R->getScalarType());
313 return AddRec;
314 })
315 .Case([&SE, &PSE, L](const VPWidenPointerInductionRecipe *R) {
316 const SCEV *Start =
317 getSCEVExprForVPValue(R->getStartValue(), PSE, L);
318 if (!L || isa<SCEVCouldNotCompute>(Start))
319 return SE.getCouldNotCompute();
320 const SCEV *Step = getSCEVExprForVPValue(R->getStepValue(), PSE, L);
321 if (isa<SCEVCouldNotCompute>(Step))
322 return SE.getCouldNotCompute();
323 return SE.getAddRecExpr(Start, Step, L, SCEV::FlagAnyWrap);
324 })
325 .Case([&SE, &PSE, L](const VPDerivedIVRecipe *R) {
326 const SCEV *Start = getSCEVExprForVPValue(R->getOperand(0), PSE, L);
327 const SCEV *IV = getSCEVExprForVPValue(R->getOperand(1), PSE, L);
328 const SCEV *Scale = getSCEVExprForVPValue(R->getOperand(2), PSE, L);
329 if (any_of(ArrayRef({Start, IV, Scale}),
331 return SE.getCouldNotCompute();
332
333 return SE.getAddExpr(
334 SE.getTruncateOrSignExtend(Start, IV->getType()),
335 SE.getMulExpr(
336 IV, SE.getTruncateOrSignExtend(Scale, IV->getType())));
337 })
338 .Case([&SE, &PSE, L](const VPScalarIVStepsRecipe *R) {
339 const SCEV *IV = getSCEVExprForVPValue(R->getOperand(0), PSE, L);
340 const SCEV *Step = getSCEVExprForVPValue(R->getOperand(1), PSE, L);
342 return SE.getCouldNotCompute();
343 return SE.getTruncateOrSignExtend(IV, Step->getType());
344 })
345 .Default(
346 [&SE](const VPRecipeBase *) { return SE.getCouldNotCompute(); });
347
348 return PSE.getPredicatedSCEV(Expr);
349}
350
352 const Loop *L) {
353 // If address is an SCEVAddExpr, we require that all operands must be either
354 // be invariant or a (possibly sign-extend) affine AddRec.
355 if (auto *PtrAdd = dyn_cast<SCEVAddExpr>(Addr)) {
356 return all_of(PtrAdd->operands(), [&SE, L](const SCEV *Op) {
357 return SE.isLoopInvariant(Op, L) ||
358 match(Op, m_scev_SExt(m_scev_AffineAddRec(m_SCEV(), m_SCEV()))) ||
359 match(Op, m_scev_AffineAddRec(m_SCEV(), m_SCEV()));
360 });
361 }
362
363 // Otherwise, check if address is loop invariant or an affine add recurrence.
364 return SE.isLoopInvariant(Addr, L) ||
366}
367
368/// Returns true if \p Opcode preserves uniformity, i.e., if all operands are
369/// uniform, the result will also be uniform.
370static bool preservesUniformity(unsigned Opcode) {
371 if (Instruction::isBinaryOp(Opcode) || Instruction::isCast(Opcode))
372 return true;
373 switch (Opcode) {
374 case Instruction::Freeze:
375 case Instruction::GetElementPtr:
376 case Instruction::ICmp:
377 case Instruction::FCmp:
378 case Instruction::Select:
383 return true;
384 default:
385 return false;
386 }
387}
388
390 // Live-in, symbolic and region-values represent single-scalar values.
392 return true;
393
394 if (auto *Rep = dyn_cast<VPReplicateRecipe>(VPV)) {
395 const VPRegionBlock *RegionOfR = Rep->getRegion();
396 // Don't consider recipes in replicate regions as uniform yet; their first
397 // lane cannot be accessed when executing the replicate region for other
398 // lanes.
399 if (RegionOfR && RegionOfR->isReplicator())
400 return false;
401 return Rep->isSingleScalar() || (preservesUniformity(Rep->getOpcode()) &&
402 all_of(Rep->operands(), isSingleScalar));
403 }
406 if (auto *WidenR = dyn_cast<VPWidenRecipe>(VPV)) {
407 return preservesUniformity(WidenR->getOpcode()) &&
408 all_of(WidenR->operands(), isSingleScalar);
409 }
410 if (auto *VPI = dyn_cast<VPInstruction>(VPV))
411 return VPI->isSingleScalar() || VPI->isVectorToScalar() ||
412 (preservesUniformity(VPI->getOpcode()) &&
413 all_of(VPI->operands(), isSingleScalar));
414 if (auto *RR = dyn_cast<VPReductionRecipe>(VPV))
415 return !RR->isPartialReduction();
417 VPV))
418 return true;
419 if (auto *Expr = dyn_cast<VPExpressionRecipe>(VPV))
420 return Expr->isSingleScalar();
421
422 // VPExpandSCEVRecipes must be placed in the entry and are always uniform.
423 return isa<VPExpandSCEVRecipe>(VPV);
424}
425
427 // Live-ins and region values are uniform.
429 return true;
430
431 const VPRecipeBase *R = V->getDefiningRecipe();
432 const VPBasicBlock *VPBB = R ? R->getParent() : nullptr;
433 const VPlan *Plan = VPBB ? VPBB->getPlan() : nullptr;
434 if (VPBB) {
435 if ((VPBB == Plan->getVectorPreheader() || VPBB == Plan->getEntry())) {
436 if (match(V->getDefiningRecipe(),
438 return false;
439 return all_of(R->operands(), isUniformAcrossVFsAndUFs);
440 }
441 }
442
444 .Case([](const VPDerivedIVRecipe *R) { return true; })
445 .Case([](const VPReplicateRecipe *R) {
446 // Be conservative about side-effects, except for the
447 // known-side-effecting assumes and stores, which we know will be
448 // uniform.
449 return R->isSingleScalar() &&
450 (!R->mayHaveSideEffects() ||
451 isa<AssumeInst, StoreInst>(R->getUnderlyingInstr())) &&
452 all_of(R->operands(), isUniformAcrossVFsAndUFs);
453 })
454 .Case([](const VPWidenRecipe *R) {
455 return preservesUniformity(R->getOpcode()) &&
456 all_of(R->operands(), isUniformAcrossVFsAndUFs);
457 })
458 .Case([](const VPInstruction *VPI) {
459 return preservesUniformity(VPI->getOpcode()) &&
461 })
462 .Case([](const VPWidenCastRecipe *R) {
463 // A cast is uniform according to its operand.
464 return isUniformAcrossVFsAndUFs(R->getOperand(0));
465 })
466 .Default([](const VPRecipeBase *) { // A value is considered non-uniform
467 // unless proven otherwise.
468 return false;
469 });
470}
471
473 auto DepthFirst = vp_depth_first_shallow(Plan.getEntry());
474 auto I = find_if(DepthFirst, [&VPDT](VPBlockBase *VPB) {
475 return VPBlockUtils::isHeader(VPB, VPDT);
476 });
477 return I == DepthFirst.end() ? nullptr : cast<VPBasicBlock>(*I);
478}
479
481 if (!R)
482 return 1;
483 if (auto *RR = dyn_cast<VPReductionPHIRecipe>(R))
484 return RR->getVFScaleFactor();
485 if (auto *RR = dyn_cast<VPReductionRecipe>(R))
486 return RR->getVFScaleFactor();
487 if (auto *ER = dyn_cast<VPExpressionRecipe>(R))
488 return ER->getVFScaleFactor();
489 assert(
490 (!isa<VPInstruction>(R) || cast<VPInstruction>(R)->getOpcode() !=
492 "getting scaling factor of reduction-start-vector not implemented yet");
493 return 1;
494}
495
496bool vputils::cannotHoistOrSinkRecipe(const VPRecipeBase &R, bool Sinking) {
497 // Assumes don't alias anything or throw; as long as they're guaranteed to
498 // execute, they're safe to hoist. They should however not be sunk, as it
499 // would destroy information.
501 return Sinking;
502 // TODO: Relax checks in the future, e.g. we could also hoist reads, if their
503 // memory location is not modified in the vector loop.
504 if (R.mayHaveSideEffects() || R.mayReadFromMemory() || R.isPhi())
505 return true;
506 // Allocas cannot be hoisted.
507 auto *RepR = dyn_cast<VPReplicateRecipe>(&R);
508 return RepR && RepR->getOpcode() == Instruction::Alloca;
509}
510
511std::optional<VPValue *>
514 VPBasicBlock *LatchVPBB) {
515 // Given a plain CFG VPlan loop with countable latch exiting block
516 // \p LatchVPBB, we're looking to match the recipes contributing to the
517 // uncountable exit condition comparison (here, vp<%4>) back to either
518 // live-ins or the address nodes for the load used as part of the uncountable
519 // exit comparison so that we can either move them within the loop, or copy
520 // them to the preheader depending on the chosen method for dealing with
521 // stores in uncountable exit loops.
522 //
523 // Currently, the address of the load is restricted to a GEP with 2 operands
524 // and a live-in base address. This constraint may be relaxed later.
525 //
526 // VPlan ' for UF>=1' {
527 // Live-in vp<%0> = VF * UF
528 // Live-in vp<%1> = vector-trip-count
529 // Live-in ir<20> = original trip-count
530 //
531 // ir-bb<entry>:
532 // Successor(s): scalar.ph, vector.ph
533 //
534 // vector.ph:
535 // Successor(s): for.body
536 //
537 // for.body:
538 // EMIT vp<%2> = phi ir<0>, vp<%index.next>
539 // EMIT-SCALAR ir<%iv> = phi [ ir<0>, vector.ph ], [ ir<%iv.next>, for.inc ]
540 // EMIT ir<%uncountable.addr> = getelementptr inbounds nuw ir<%pred>,ir<%iv>
541 // EMIT ir<%uncountable.val> = load ir<%uncountable.addr>
542 // EMIT ir<%uncountable.cond> = icmp sgt ir<%uncountable.val>, ir<500>
543 // EMIT vp<%3> = masked-cond ir<%uncountable.cond>
544 // Successor(s): for.inc
545 //
546 // for.inc:
547 // EMIT ir<%iv.next> = add nuw nsw ir<%iv>, ir<1>
548 // EMIT ir<%countable.cond> = icmp eq ir<%iv.next>, ir<20>
549 // EMIT vp<%index.next> = add nuw vp<%2>, vp<%0>
550 // EMIT vp<%4> = any-of ir<%3>
551 // EMIT vp<%5> = icmp eq vp<%index.next>, vp<%1>
552 // EMIT vp<%6> = or vp<%4>, vp<%5>
553 // EMIT branch-on-cond vp<%6>
554 // Successor(s): middle.block, for.body
555 //
556 // middle.block:
557 // Successor(s): ir-bb<exit>, scalar.ph
558 //
559 // ir-bb<exit>:
560 // No successors
561 //
562 // scalar.ph:
563 // }
564
565 // Find the uncountable loop exit condition.
566 VPValue *UncountableCondition = nullptr;
567 if (!match(LatchVPBB->getTerminator(),
569 m_AnyOf(m_VPValue(UncountableCondition)), m_VPValue()))))
570 return std::nullopt;
571
573 Worklist.push_back(UncountableCondition);
574 while (!Worklist.empty()) {
575 VPValue *V = Worklist.pop_back_val();
576
577 // Any value defined outside the loop does not need to be copied.
578 if (V->isDefinedOutsideLoopRegions())
579 continue;
580
581 // FIXME: Remove the single user restriction; it's here because we're
582 // starting with the simplest set of loops we can, and multiple
583 // users means needing to add PHI nodes in the transform.
584 if (V->getNumUsers() > 1)
585 return std::nullopt;
586
587 VPValue *Op1, *Op2;
588 // Walk back through recipes until we find at least one load from memory.
589 if (match(V, m_ICmp(m_VPValue(Op1), m_VPValue(Op2)))) {
590 Worklist.push_back(Op1);
591 Worklist.push_back(Op2);
592 Recipes.push_back(cast<VPInstruction>(V->getDefiningRecipe()));
594 VPRecipeBase *GepR = Op1->getDefiningRecipe();
595 // Only matching base + single offset term for now.
596 if (GepR->getNumOperands() != 2)
597 return std::nullopt;
598 // Matching a GEP with a loop-invariant base ptr.
600 m_LiveIn(), m_VPValue())))
601 return std::nullopt;
602 Recipes.push_back(cast<VPInstruction>(V->getDefiningRecipe()));
603 Recipes.push_back(cast<VPInstruction>(GepR));
604 GEPs.push_back(cast<VPInstruction>(GepR));
606 m_VPValue(Op1)))) {
607 Worklist.push_back(Op1);
608 Recipes.push_back(cast<VPInstruction>(V->getDefiningRecipe()));
609 } else
610 return std::nullopt;
611 }
612
613 // If we couldn't match anything, don't return the condition. It may be
614 // defined outside the loop.
615 if (Recipes.empty() || GEPs.empty())
616 return std::nullopt;
617
618 return UncountableCondition;
619}
620
622 VPRegionBlock *LoopRegion = Plan.getVectorLoopRegion();
623 SmallVector<VPValue *> WideCanonicalIVs;
624 auto *WideCanonicalIV = vputils::findUserOf<VPWidenCanonicalIVRecipe>(
625 LoopRegion->getCanonicalIV());
626 assert(count_if(LoopRegion->getCanonicalIV()->users(),
628 "Must have at most one VPWideCanonicalIVRecipe");
629 if (WideCanonicalIV)
630 WideCanonicalIVs.push_back(WideCanonicalIV);
631
632 // Also include VPWidenIntOrFpInductionRecipes that represent a widened
633 // version of the canonical induction.
634 VPBasicBlock *HeaderVPBB = LoopRegion->getEntryBasicBlock();
635 for (VPRecipeBase &Phi : HeaderVPBB->phis()) {
636 auto *WidenOriginalIV = dyn_cast<VPWidenIntOrFpInductionRecipe>(&Phi);
637 if (WidenOriginalIV && WidenOriginalIV->isCanonical())
638 WideCanonicalIVs.push_back(WidenOriginalIV);
639 }
640
641 // Walk users of wide canonical IVs and find the single compare of the form
642 // (ICMP_ULE, WideCanonicalIV, backedge-taken-count).
643 VPSingleDefRecipe *HeaderMask = nullptr;
644 for (auto *Wide : WideCanonicalIVs) {
645 for (VPUser *U : Wide->users()) {
646 auto *VPI = dyn_cast<VPInstruction>(U);
647 if (!VPI || !vputils::isHeaderMask(VPI, Plan))
648 continue;
649
650 assert(VPI->getOperand(0) == Wide &&
651 "WidenCanonicalIV must be the first operand of the compare");
652 assert(!HeaderMask && "Multiple header masks found?");
653 HeaderMask = VPI;
654 }
655 }
656 return HeaderMask;
657}
658
661 VPBasicBlock *LastBB) {
662 assert(FirstBB->getParent() == LastBB->getParent() &&
663 "FirstBB and LastBB from different regions");
664#ifndef NDEBUG
665 bool InSingleSuccChain = false;
666 for (VPBlockBase *Succ = FirstBB; Succ; Succ = Succ->getSingleSuccessor())
667 InSingleSuccChain |= (Succ == LastBB);
668 assert(InSingleSuccChain &&
669 "LastBB unreachable from FirstBB in single-successor chain");
670#endif
671 auto Blocks = to_vector(
673 auto *LastIt = find(Blocks, LastBB);
674 assert(LastIt != Blocks.end() &&
675 "LastBB unreachable from FirstBB in depth-first traversal");
676 Blocks.erase(std::next(LastIt), Blocks.end());
677 return Blocks;
678}
679
681 const VPDominatorTree &VPDT) {
682 auto *VPBB = dyn_cast<VPBasicBlock>(VPB);
683 if (!VPBB)
684 return false;
685
686 // If VPBB is in a region R, VPBB is a loop header if R is a loop region with
687 // VPBB as its entry, i.e., free of predecessors.
688 if (auto *R = VPBB->getParent())
689 return !R->isReplicator() && !VPBB->hasPredecessors();
690
691 // A header dominates its second predecessor (the latch), with the other
692 // predecessor being the preheader
693 return VPB->getPredecessors().size() == 2 &&
694 VPDT.dominates(VPB, VPB->getPredecessors()[1]);
695}
696
698 const VPDominatorTree &VPDT) {
699 // A latch has a header as its last successor, with its other successors
700 // leaving the loop. A preheader OTOH has a header as its first (and only)
701 // successor.
702 return VPB->getNumSuccessors() >= 2 &&
704}
705
706std::optional<MemoryLocation>
708 auto *M = dyn_cast<VPIRMetadata>(&R);
709 if (!M)
710 return std::nullopt;
712 // Populate noalias metadata from VPIRMetadata.
713 if (MDNode *NoAliasMD = M->getMetadata(LLVMContext::MD_noalias))
714 Loc.AATags.NoAlias = NoAliasMD;
715 if (MDNode *AliasScopeMD = M->getMetadata(LLVMContext::MD_alias_scope))
716 Loc.AATags.Scope = AliasScopeMD;
717 return Loc;
718}
719
721 VPRegionBlock *LoopRegion = Plan.getVectorLoopRegion();
722 VPRegionValue *CanIV = LoopRegion->getCanonicalIV();
723 assert(CanIV && "Expected loop region to have a canonical IV");
724
725 VPSymbolicValue &VFxUF = Plan.getVFxUF();
726
727 // Check if \p Step matches the expected increment step, accounting for
728 // materialization of VFxUF and UF.
729 auto IsIncrementStep = [&](VPValue *Step) -> bool {
730 if (!VFxUF.isMaterialized())
731 return Step == &VFxUF;
732
733 VPSymbolicValue &UF = Plan.getUF();
734 if (!UF.isMaterialized())
735 return Step == &UF;
736
737 unsigned ConcreteUF = Plan.getConcreteUF();
738 // Fixed VF: step is just the concrete UF.
739 if (match(Step, m_SpecificInt(ConcreteUF)))
740 return true;
741
742 // Scalable VF: step involves VScale.
743 if (ConcreteUF == 1)
745 if (match(Step, m_c_Mul(m_SpecificInt(ConcreteUF),
747 return true;
748 // mul(VScale, ConcreteUF) may have been simplified to
749 // shl(VScale, log2(ConcreteUF)) when ConcreteUF is a power of 2.
750 return isPowerOf2_32(ConcreteUF) &&
753 m_SpecificInt(Log2_32(ConcreteUF))));
754 };
755
756 VPInstruction *Increment = nullptr;
757 for (VPUser *U : CanIV->users()) {
758 VPValue *Step;
759 if (isa<VPInstruction>(U) &&
760 match(U, m_c_Add(m_Specific(CanIV), m_VPValue(Step))) &&
761 IsIncrementStep(Step)) {
762 assert(!Increment && "There must be a unique increment");
764 }
765 }
766
767 assert((!VFxUF.isMaterialized() || Increment) &&
768 "After materializing VFxUF, an increment must exist");
769 assert((!Increment ||
770 LoopRegion->hasCanonicalIVNUW() == Increment->hasNoUnsignedWrap()) &&
771 "NUW flag in region and increment must match");
772 return Increment;
773}
774
775/// Find the ComputeReductionResult recipe for \p PhiR, looking through selects
776/// inserted for predicated reductions or tail folding.
778 VPValue *BackedgeVal = PhiR->getBackedgeValue();
780 BackedgeVal))
781 return Res;
782
783 // Look through selects inserted for tail folding or predicated reductions.
785 BackedgeVal, m_Select(m_VPValue(), m_VPValue(), m_VPValue()));
786 if (!SelR)
787 return nullptr;
790}
791
794 SmallVector<const VPValue *> WorkList = {V};
795
796 while (!WorkList.empty()) {
797 const VPValue *Cur = WorkList.pop_back_val();
798 if (!Seen.insert(Cur).second)
799 continue;
800
801 auto *Blend = dyn_cast<VPBlendRecipe>(Cur);
802 // Skip blends that use V only through a compare by checking if any incoming
803 // value was already visited.
804 if (Blend && none_of(seq<unsigned>(0, Blend->getNumIncomingValues()),
805 [&](unsigned I) {
806 return Seen.contains(Blend->getIncomingValue(I));
807 }))
808 continue;
809
810 for (VPUser *U : Cur->users()) {
811 if (auto *InterleaveR = dyn_cast<VPInterleaveBase>(U))
812 if (InterleaveR->getAddr() == Cur)
813 return true;
814 if (auto *RepR = dyn_cast<VPReplicateRecipe>(U)) {
815 if (RepR->getOpcode() == Instruction::Load &&
816 RepR->getOperand(0) == Cur)
817 return true;
818 if (RepR->getOpcode() == Instruction::Store &&
819 RepR->getOperand(1) == Cur)
820 return true;
821 }
823 if (MemR->getAddr() == Cur && MemR->isConsecutive())
824 return true;
825 }
826 }
827
828 // The legacy cost model only supports scalarization loads/stores with phi
829 // addresses, if the phi is directly used as load/store address. Don't
830 // traverse further for Blends.
831 if (Blend)
832 continue;
833
834 // Only traverse further through users that also define a value (and can
835 // thus have their own users walked).
836 for (VPUser *U : Cur->users())
837 if (auto *SDR = dyn_cast<VPSingleDefRecipe>(U))
838 WorkList.push_back(SDR);
839 }
840 return false;
841}
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 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
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.
Represents flags for the getelementptr instruction/expression.
static GEPNoWrapFlags none()
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 * getAbsExpr(const SCEV *Op, bool IsNSW)
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:4148
void appendRecipe(VPRecipeBase *Recipe)
Augment the existing recipes of a VPBasicBlock with an additional Recipe as the last recipe.
Definition VPlan.h:4223
iterator_range< iterator > phis()
Returns an iterator range over the PHI-like recipes in the block.
Definition VPlan.h:4236
VPRecipeBase * getTerminator()
If the block has multiple successors, return the branch recipe terminating the block.
Definition VPlan.cpp:628
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
const VPBlocksTy & getPredecessors() const
Definition VPlan.h:221
VPlan * getPlan()
Definition VPlan.cpp:178
const VPBasicBlock * getEntryBasicBlock() const
Definition VPlan.cpp:183
VPBlockBase * getSingleSuccessor() const
Definition VPlan.h:226
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.
static auto blocksOnly(T &&Range)
Return an iterator range over Range which only includes BlockTy blocks.
Definition VPlanUtils.h:295
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:3922
Template specialization of the standard LLVM dominator tree utility for VPBlockBases.
Recipe to expand a SCEV expression.
Definition VPlan.h:3770
virtual VPValue * getBackedgeValue()
Returns the incoming value from the loop backedge.
Definition VPlan.h:2347
This is a concrete Recipe that models a single VPlan-level instruction.
Definition VPlan.h:1220
@ ReductionStartVector
Start vector for reductions with 3 operands: the original start value, the identity value for the red...
Definition VPlan.h:1311
unsigned getOpcode() const
Definition VPlan.h:1395
VPRecipeBase is a base class modeling a sequence of one or more output IR instructions.
Definition VPlan.h:401
A recipe for handling reduction phis.
Definition VPlan.h:2691
VPRegionBlock represents a collection of VPBasicBlocks and VPRegionBlocks which form a Single-Entry-S...
Definition VPlan.h:4358
bool isReplicator() const
An indicator whether this region is to generate multiple replicated instances of output IR correspond...
Definition VPlan.h:4434
bool hasCanonicalIVNUW() const
Indicates if NUW is set for the canonical IV increment, for loop regions.
Definition VPlan.h:4483
VPRegionValue * getCanonicalIV()
Return the canonical induction variable of the region, null for replicating regions.
Definition VPlan.h:4470
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:3200
unsigned getOpcode() const
Definition VPlan.h:3272
A recipe for handling phi nodes of integer and floating-point inductions, producing their scalar valu...
Definition VPlan.h:3993
VPSingleDef is a base class for recipes for modeling a sequence of one or more output IR that define ...
Definition VPlan.h:605
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:335
operand_range operands()
Definition VPlanValue.h:403
unsigned getNumOperands() const
Definition VPlanValue.h:373
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:128
user_range users()
Definition VPlanValue.h:155
VPWidenCastRecipe is a recipe to create vector cast instructions.
Definition VPlan.h:1830
A recipe for handling GEP instructions.
Definition VPlan.h:2092
A recipe for handling phi nodes of integer and floating-point inductions, producing their vector valu...
Definition VPlan.h:2453
VPWidenRecipe is a recipe for producing a widened instruction using the opcode and operands of the re...
Definition VPlan.h:1774
VPlan models a candidate for vectorization, encoding various decisions take to produce efficient outp...
Definition VPlan.h:4506
VPBasicBlock * getEntry()
Definition VPlan.h:4602
VPValue * getTripCount() const
The trip count of the original loop.
Definition VPlan.h:4665
VPSymbolicValue & getVFxUF()
Returns VF * UF of the vector loop region.
Definition VPlan.h:4705
VPValue * getBackedgeTakenCount() const
Definition VPlan.h:4692
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:4779
LLVM_ABI_FOR_TEST VPRegionBlock * getVectorLoopRegion()
Returns the VPRegionBlock of the vector loop.
Definition VPlan.cpp:1065
unsigned getConcreteUF() const
Returns the concrete UF of the plan, after unrolling.
Definition VPlan.h:4757
VPBasicBlock * getVectorPreheader() const
Returns the preheader of the vector loop region, if one exists, or null otherwise.
Definition VPlan.h:4607
VPSymbolicValue & getUF()
Returns the UF of the vector loop region.
Definition VPlan.h:4702
bool hasScalarVFOnly() const
Definition VPlan.h:4747
VPSymbolicValue & getVF()
Returns the VF of the vector loop region.
Definition VPlan.h:4698
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.
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)
canonical_iv_match m_CanonicalIV()
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)
VPInstruction_match< VPInstruction::Reverse, Op0_t > m_Reverse(const Op0_t &Op0)
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...
VPValue * getOrCreateVPValueForSCEVExpr(VPlan &Plan, const SCEV *Expr)
Get or create a VPValue that corresponds to the expansion of Expr.
bool cannotHoistOrSinkRecipe(const VPRecipeBase &R, bool Sinking=false)
Return true if we do not know how to (mechanically) hoist or sink R.
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:137
bool isUniformAcrossVFsAndUFs(const VPValue *V)
Checks if V is uniform across all VF lanes and UF parts.
bool isUsedByLoadStoreAddress(const VPValue *V)
Returns true if V is used as part of the address of another load or store.
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...
GEPNoWrapFlags getGEPFlagsForPtr(VPValue *Ptr)
Returns the GEP nowrap flags for Ptr, looking through pointer casts mirroring Value::stripPointerCast...
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 drop_begin(T &&RangeOrContainer, size_t N=1)
Return a range covering RangeOrContainer with the first N elements excluded.
Definition STLExtras.h:315
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:1764
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
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:283
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
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
bool none_of(R &&Range, UnaryPredicate P)
Provide wrappers to std::none_of which take ranges instead of having to pass begin/end explicitly.
Definition STLExtras.h:1752
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:2018
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:1771
auto seq(T Begin, T End)
Iterate over an integral type from Begin up to - but not including - End.
Definition Sequence.h:305
@ 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:291