LLVM 24.0.0git
VPlanLowering.cpp
Go to the documentation of this file.
1//===- VPlanLowering.cpp - VPlan-to-VPlan lowering transforms -------------===//
2//
3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6//
7//===----------------------------------------------------------------------===//
8///
9/// \file
10/// This file implements VPlan-to-VPlan lowering transformations, which
11/// prepare an optimized VPlan for execution.
12///
13//===----------------------------------------------------------------------===//
14
16#include "VPlan.h"
17#include "VPlanAnalysis.h"
18#include "VPlanCFG.h"
19#include "VPlanDominatorTree.h"
20#include "VPlanHelpers.h"
21#include "VPlanPatternMatch.h"
22#include "VPlanTransforms.h"
23#include "VPlanUtils.h"
24#include "llvm/ADT/APInt.h"
25#include "llvm/ADT/STLExtras.h"
30#include "llvm/IR/Intrinsics.h"
31#include "llvm/IR/MDBuilder.h"
32#include "llvm/IR/Metadata.h"
36
37using namespace llvm;
38using namespace VPlanPatternMatch;
39using namespace SCEVPatternMatch;
40
44 const SmallPtrSetImpl<const Value *> &ValuesToIgnore) {
45 VPRegionBlock *LoopRegion = Plan.getVectorLoopRegion();
46 if (!LoopRegion)
47 return;
48
49 auto *WideCanIV =
51 if (!WideCanIV)
52 return;
53
54 Type *CanIVTy = LoopRegion->getCanonicalIVType();
55
56 // Replace the wide canonical IV with a scalar-iv-steps over the canonical
57 // IV.
58 if (Plan.hasScalarVFOnly() || vputils::onlyFirstLaneUsed(WideCanIV)) {
59 VPBuilder Builder(WideCanIV);
60 WideCanIV->replaceAllUsesWith(vputils::createScalarIVSteps(
61 Plan, InductionDescriptor::IK_IntInduction, Instruction::Add, nullptr,
62 nullptr, Plan.getZero(CanIVTy), Plan.getConstantInt(CanIVTy, 1),
63 WideCanIV->getDebugLoc(), Builder,
64 {static_cast<bool>(WideCanIV->getNoWrapFlags().HasNUW), false}));
65 WideCanIV->eraseFromParent();
66 return;
67 }
68
69 if (vputils::onlyScalarValuesUsed(WideCanIV))
70 return;
71
72 // If a canonical VPWidenIntOrFpInductionRecipe already produces vector lanes
73 // in the header, reuse it instead of introducing another wide induction phi.
74 VPBasicBlock *Header = LoopRegion->getEntryBasicBlock();
75 for (VPRecipeBase &Phi : Header->phis()) {
77 if (!match(&Phi, m_CanonicalWidenIV(WidenIV)))
78 continue;
79 // The reused wide IV feeds the header mask, whose lanes may extend past
80 // the trip count; drop flags that only hold inside the scalar loop.
82 WideCanIV->replaceAllUsesWith(WidenIV);
83 WideCanIV->eraseFromParent();
84 return;
85 }
86
87 // Introduce a new VPWidenIntOrFpInductionRecipe if profitable.
88 auto *VecTy = VectorType::get(CanIVTy, VF);
89 InstructionCost BroadcastCost = TTI.getShuffleCost(
91 InstructionCost PHICost = TTI.getCFInstrCost(Instruction::PHI, CostKind);
92 if (PHICost > BroadcastCost)
93 return;
94
95 // Bail out if the additional wide induction phi increase the expected spill
96 // cost.
97 VPRegisterUsage UnrolledBase =
98 calculateRegisterUsageForPlan(Plan, VF, TTI, ValuesToIgnore)[0];
99 for (unsigned &NumUsers : make_second_range(UnrolledBase.MaxLocalUsers))
100 NumUsers *= UF;
101 unsigned RegClass = TTI.getRegisterClassForType(/*Vector=*/true, VecTy);
102 VPRegisterUsage Projected = UnrolledBase;
103 Projected.MaxLocalUsers[RegClass] += TTI.getRegUsageForType(VecTy);
104 if (Projected.spillCost(TTI, CostKind) >
105 UnrolledBase.spillCost(TTI, CostKind))
106 return;
107
110 VPValue *StepV = Plan.getConstantInt(CanIVTy, 1);
111 auto *NewWideIV = new VPWidenIntOrFpInductionRecipe(
112 /*IV=*/nullptr, Plan.getZero(CanIVTy), StepV, &Plan.getVF(), ID,
113 WideCanIV->getNoWrapFlags(), WideCanIV->getDebugLoc());
114 NewWideIV->insertBefore(&*Header->getFirstNonPhi());
115 WideCanIV->replaceAllUsesWith(NewWideIV);
116 WideCanIV->eraseFromParent();
117}
118
119// Add a VPActiveLaneMaskPHIRecipe and related recipes to \p Plan and replace
120// the loop terminator with a branch-on-cond recipe with the negated
121// active-lane-mask as operand. Note that this turns the loop into an
122// uncountable one. Only the existing terminator is replaced, all other existing
123// recipes/users remain unchanged, except for poison-generating flags being
124// dropped from the canonical IV increment. Return the created
125// VPActiveLaneMaskPHIRecipe.
126//
127// The function adds the following recipes:
128//
129// vector.ph:
130// %EntryInc = canonical-iv-increment-for-part CanonicalIVStart
131// %EntryALM = active-lane-mask %EntryInc, TC
132//
133// vector.body:
134// ...
135// %P = active-lane-mask-phi [ %EntryALM, %vector.ph ], [ %ALM, %vector.body ]
136// ...
137// %InLoopInc = canonical-iv-increment-for-part CanonicalIVIncrement
138// %ALM = active-lane-mask %InLoopInc, TC
139// %Negated = Not %ALM
140// branch-on-cond %Negated
141//
144 VPRegionBlock *TopRegion = Plan.getVectorLoopRegion();
145 VPBasicBlock *EB = TopRegion->getExitingBasicBlock();
146 VPValue *StartV = Plan.getZero(TopRegion->getCanonicalIVType());
147 auto *CanonicalIVIncrement = TopRegion->getOrCreateCanonicalIVIncrement();
148 // TODO: Check if dropping the flags is needed.
149 TopRegion->clearCanonicalIVNUW(CanonicalIVIncrement);
150 DebugLoc DL = CanonicalIVIncrement->getDebugLoc();
151 // We can't use StartV directly in the ActiveLaneMask VPInstruction, since
152 // we have to take unrolling into account. Each part needs to start at
153 // Part * VF
154 auto *VecPreheader = Plan.getVectorPreheader();
155 VPBuilder Builder(VecPreheader);
156
157 // Create the ActiveLaneMask instruction using the correct start values.
158 VPValue *TC = Plan.getTripCount();
159 VPValue *VF = &Plan.getVF();
160
161 auto *EntryIncrement =
162 Builder.createOverflowingOp(VPInstruction::CanonicalIVIncrementForPart,
163 {StartV, VF}, {}, DL, "index.part.next");
164
165 // Create the active lane mask instruction in the VPlan preheader.
166 VPValue *ALMMultiplier =
167 Plan.getConstantInt(TopRegion->getCanonicalIVType(), 1);
168 auto *EntryALM = Builder.createNaryOp(VPInstruction::ActiveLaneMask,
169 {EntryIncrement, TC, ALMMultiplier}, DL,
170 "active.lane.mask.entry");
171
172 // Now create the ActiveLaneMaskPhi recipe in the main loop using the
173 // preheader ActiveLaneMask instruction.
174 auto *LaneMaskPhi =
176 auto *HeaderVPBB = TopRegion->getEntryBasicBlock();
177 LaneMaskPhi->insertBefore(*HeaderVPBB, HeaderVPBB->begin());
178
179 // Create the active lane mask for the next iteration of the loop before the
180 // original terminator.
181 VPRecipeBase *OriginalTerminator = EB->getTerminator();
182 Builder.setInsertPoint(OriginalTerminator);
183 auto *InLoopIncrement = Builder.createOverflowingOp(
185 {CanonicalIVIncrement, &Plan.getVF()}, {}, DL);
186 auto *ALM = Builder.createNaryOp(VPInstruction::ActiveLaneMask,
187 {InLoopIncrement, TC, ALMMultiplier}, DL,
188 "active.lane.mask.next");
189 LaneMaskPhi->addBackedgeValue(ALM);
190
191 // Replace the original terminator with BranchOnCond. We have to invert the
192 // mask here because a true condition means jumping to the exit block.
193 auto *NotMask = Builder.createNot(ALM, DL);
194 Builder.createNaryOp(VPInstruction::BranchOnCond, {NotMask}, DL);
195 OriginalTerminator->eraseFromParent();
196 return LaneMaskPhi;
197}
198
200 VPlan &Plan, bool UseActiveLaneMask, bool UseActiveLaneMaskForControlFlow) {
201 VPRegionBlock *LoopRegion = Plan.getVectorLoopRegion();
202 VPValue *HeaderMask = LoopRegion->getUsedHeaderMask();
203 if (!HeaderMask)
204 return;
205
206 if (UseActiveLaneMaskForControlFlow) {
208 return;
209 }
210
211 VPBasicBlock *Header = LoopRegion->getEntryBasicBlock();
212 VPBuilder Builder(Header, Header->getFirstNonPhi());
213 auto *WideCanonicalIV = Builder.insert(new VPWidenCanonicalIVRecipe(
214 LoopRegion->getCanonicalIV(),
215 VPIRFlags::WrapFlagsTy(/*HasNUW=*/true, /*HasNSW=*/false)));
216 VPValue *Mask;
217 if (UseActiveLaneMask) {
218 VPValue *ALMMultiplier =
219 Plan.getConstantInt(LoopRegion->getCanonicalIVType(), 1);
220 Mask = Builder.createNaryOp(
222 {WideCanonicalIV, Plan.getTripCount(), ALMMultiplier}, nullptr,
223 "active.lane.mask");
224 } else {
225 Mask = Builder.createICmp(CmpInst::ICMP_ULE, WideCanonicalIV,
227 }
228 HeaderMask->replaceAllUsesWith(Mask);
229}
230
231/// Expand a VPWidenIntOrFpInduction into executable recipes, for the initial
232/// value, phi and backedge value. In the following example:
233///
234/// vector.ph:
235/// Successor(s): vector loop
236///
237/// <x1> vector loop: {
238/// vector.body:
239/// WIDEN-INDUCTION %i = phi %start, %step, %vf
240/// ...
241/// EMIT branch-on-count ...
242/// No successors
243/// }
244///
245/// WIDEN-INDUCTION will get expanded to:
246///
247/// vector.ph:
248/// ...
249/// vp<%induction.start> = ...
250/// vp<%induction.increment> = ...
251///
252/// Successor(s): vector loop
253///
254/// <x1> vector loop: {
255/// vector.body:
256/// ir<%i> = WIDEN-PHI vp<%induction.start>, vp<%vec.ind.next>
257/// ...
258/// vp<%vec.ind.next> = add ir<%i>, vp<%induction.increment>
259/// EMIT branch-on-count ...
260/// No successors
261/// }
262static void
264 VPlan *Plan = WidenIVR->getParent()->getPlan();
265 VPValue *Start = WidenIVR->getStartValue();
266 VPValue *Step = WidenIVR->getStepValue();
267 VPValue *VF = WidenIVR->getVFValue();
268 DebugLoc DL = WidenIVR->getDebugLoc();
269
270 // The value from the original loop to which we are mapping the new induction
271 // variable.
272 Type *Ty = WidenIVR->getScalarType();
273
274 const InductionDescriptor &ID = WidenIVR->getInductionDescriptor();
277 VPIRFlags Flags = *WidenIVR;
278 if (ID.getKind() == InductionDescriptor::IK_IntInduction) {
279 AddOp = Instruction::Add;
280 MulOp = Instruction::Mul;
281 } else {
282 AddOp = ID.getInductionOpcode();
283 MulOp = Instruction::FMul;
284 }
285
286 // If the phi is truncated, truncate the start and step values.
287 VPBuilder Builder(Plan->getVectorPreheader());
288 Type *StepTy = Step->getScalarType();
289 if (Ty->getScalarSizeInBits() < StepTy->getScalarSizeInBits()) {
290 assert(StepTy->isIntegerTy() && "Truncation requires an integer type");
291 Step = Builder.createScalarCast(Instruction::Trunc, Step, Ty, DL);
292 Start = Builder.createScalarCast(Instruction::Trunc, Start, Ty, DL);
293 StepTy = Ty;
294 }
295
296 // Construct the initial value of the vector IV in the vector loop preheader.
297 Type *IVIntTy =
299 VPValue *Init = Builder.createNaryOp(VPInstruction::StepVector, {}, IVIntTy);
300 if (StepTy->isFloatingPointTy())
301 Init = Builder.createWidenCast(Instruction::UIToFP, Init, StepTy);
302
303 VPValue *SplatStart = Builder.createNaryOp(VPInstruction::Broadcast, Start);
304 VPValue *SplatStep = Builder.createNaryOp(VPInstruction::Broadcast, Step);
305
306 Init = Builder.createNaryOp(MulOp, {Init, SplatStep}, Flags);
307 Init = Builder.createNaryOp(AddOp, {SplatStart, Init}, Flags,
308 DebugLoc::getUnknown(), "induction");
309
310 // Create the widened phi of the vector IV.
311 auto *WidePHI = VPBuilder(WidenIVR).createWidenPhi(
312 Init, WidenIVR->getDebugLoc(), "vec.ind");
313
314 // Create the backedge value for the vector IV.
315 VPValue *Inc;
316 VPValue *Prev;
317 // If unrolled, use the increment and prev value from the operands.
318 if (auto *SplatVF = WidenIVR->getSplatVFValue()) {
319 Inc = SplatVF;
320 Prev = WidenIVR->getLastUnrolledPartOperand();
321 } else {
322 // Move the insertion point after the VF definition when the VF is defined
323 // inside a loop, such as for EVL tail-folding.
324 if (VPRecipeBase *R = VF->getDefiningRecipe())
325 if (R->getParent()->getEnclosingLoopRegion())
326 Builder.setInsertPoint(R->getParent(), std::next(R->getIterator()));
327
328 // Multiply the vectorization factor by the step using integer or
329 // floating-point arithmetic as appropriate.
330 if (StepTy->isFloatingPointTy())
331 VF = Builder.createScalarCast(Instruction::CastOps::UIToFP, VF, StepTy,
332 DL);
333 else
334 VF = Builder.createScalarZExtOrTrunc(VF, StepTy, DL);
335
336 Inc = Builder.createNaryOp(MulOp, {Step, VF}, Flags);
337 Inc = Builder.createNaryOp(VPInstruction::Broadcast, Inc);
338 Prev = WidePHI;
339 }
340
342 Builder.setInsertPoint(ExitingBB, ExitingBB->getTerminator()->getIterator());
343 auto *Next = Builder.createNaryOp(AddOp, {Prev, Inc}, Flags,
344 WidenIVR->getDebugLoc(), "vec.ind.next");
345
346 WidePHI->addIncoming(Next);
347
348 WidenIVR->replaceAllUsesWith(WidePHI);
349}
350
351/// Expand a VPWidenPointerInductionRecipe into executable recipes, for the
352/// initial value, phi and backedge value. In the following example:
353///
354/// <x1> vector loop: {
355/// vector.body:
356/// EMIT ir<%ptr.iv> = WIDEN-POINTER-INDUCTION %start, %step, %vf
357/// ...
358/// EMIT branch-on-count ...
359/// }
360///
361/// WIDEN-POINTER-INDUCTION will get expanded to:
362///
363/// <x1> vector loop: {
364/// vector.body:
365/// EMIT-SCALAR %pointer.phi = phi %start, %ptr.ind
366/// EMIT %mul = mul %stepvector, %step
367/// EMIT %vector.gep = wide-ptradd %pointer.phi, %mul
368/// ...
369/// EMIT %ptr.ind = ptradd %pointer.phi, %vf
370/// EMIT branch-on-count ...
371/// }
373 VPlan *Plan = R->getParent()->getPlan();
374 VPValue *Start = R->getStartValue();
375 VPValue *Step = R->getStepValue();
376 VPValue *VF = R->getVFValue();
377
378 assert(R->getInductionDescriptor().getKind() ==
380 "Not a pointer induction according to InductionDescriptor!");
381 assert(R->getScalarType()->isPointerTy() && "Unexpected type.");
382 assert(!R->onlyScalarsGenerated(Plan->hasScalableVF()) &&
383 "Recipe should have been replaced");
384
385 VPBuilder Builder(R);
386 DebugLoc DL = R->getDebugLoc();
387
388 // Build a scalar pointer phi.
389 VPPhi *ScalarPtrPhi = Builder.createScalarPhi(Start, DL, "pointer.phi");
390
391 // Create actual address geps that use the pointer phi as base and a
392 // vectorized version of the step value (<step*0, ..., step*N>) as offset.
393 Builder.setInsertPoint(R->getParent(), R->getParent()->getFirstNonPhi());
394 Type *StepTy = Step->getScalarType();
395 VPValue *Offset = Builder.createNaryOp(VPInstruction::StepVector, {}, StepTy);
396 Offset = Builder.createOverflowingOp(Instruction::Mul, {Offset, Step});
397 VPValue *PtrAdd =
398 Builder.createWidePtrAdd(ScalarPtrPhi, Offset, DL, "vector.gep");
399 R->replaceAllUsesWith(PtrAdd);
400
401 // Create the backedge value for the scalar pointer phi.
403 Builder.setInsertPoint(ExitingBB, ExitingBB->getTerminator()->getIterator());
404 VF = Builder.createScalarZExtOrTrunc(VF, StepTy, DL);
405 VPValue *Inc = Builder.createOverflowingOp(Instruction::Mul, {Step, VF});
406
407 VPValue *InductionGEP =
408 Builder.createPtrAdd(ScalarPtrPhi, Inc, DL, "ptr.ind");
409 ScalarPtrPhi->addIncoming(InductionGEP);
410}
411
412/// Expand a VPDerivedIVRecipe into executable recipes.
414 VPBuilder Builder(R);
415 VPValue *Start = R->getStartValue();
416 VPValue *Step = R->getStepValue();
417 VPValue *Index = R->getIndex();
418 Type *StepTy = Step->getScalarType();
419 Index = StepTy->isIntegerTy()
420 ? Builder.createScalarZExtOrTrunc(
421 Index, StepTy, DebugLoc::getCompilerGenerated())
422 : Builder.createScalarCast(Instruction::SIToFP, Index, StepTy,
424 VPIRFlags::WrapFlagsTy Flags = R->getNoWrapFlags();
425 switch (R->getInductionKind()) {
427 assert(Index->getScalarType() == Start->getScalarType() &&
428 "Index type does not match StartValue type");
429 return R->replaceAllUsesWith(Builder.createAdd(
430 Start,
431 Builder.createOverflowingOp(Instruction::Mul, {Index, Step}, Flags),
432 DebugLoc::getUnknown(), "", Flags));
433 }
435 return R->replaceAllUsesWith(Builder.createPtrAdd(
436 Start,
437 Builder.createOverflowingOp(Instruction::Mul, {Index, Step}, Flags)));
439 assert(StepTy->isFloatingPointTy() && "Expected FP Step value");
440 const FPMathOperator *FPBinOp = R->getFPBinOp();
441 assert(FPBinOp &&
442 (FPBinOp->getOpcode() == Instruction::FAdd ||
443 FPBinOp->getOpcode() == Instruction::FSub) &&
444 "Original BinOp should be defined for FP induction");
445 FastMathFlags FMF = FPBinOp->getFastMathFlags();
446 VPValue *FMul = Builder.createNaryOp(Instruction::FMul, {Step, Index}, FMF);
447 return R->replaceAllUsesWith(
448 Builder.createNaryOp(FPBinOp->getOpcode(), {Start, FMul}, FMF));
449 }
451 return;
452 }
453 llvm_unreachable("Unhandled induction kind");
454}
455
457 // Replace loop regions with explicity CFG.
460 vp_depth_first_deep(Plan.getEntry()))) {
461 if (!R->isReplicator())
462 LoopRegions.push_back(R);
463 }
464 for (VPRegionBlock *R : LoopRegions)
465 R->dissolveToCFGLoop();
466}
467
470 // The transform runs after dissolving loop regions, so all VPBasicBlocks
471 // terminated with BranchOnTwoConds are reached via a shallow traversal.
474 if (!VPBB->empty() && match(&VPBB->back(), m_BranchOnTwoConds()))
475 WorkList.push_back(cast<VPInstruction>(&VPBB->back()));
476 }
477
478 // Expand BranchOnTwoConds instructions into explicit CFG with two new
479 // single-condition branches:
480 // 1. A branch that replaces BranchOnTwoConds, jumps to the first successor if
481 // the first condition is true, and otherwise jumps to a new interim block.
482 // 2. A branch that ends the interim block, jumps to the second successor if
483 // the second condition is true, and otherwise jumps to the third
484 // successor.
485 for (VPInstruction *Br : WorkList) {
486 assert(Br->getNumOperands() == 2 &&
487 "BranchOnTwoConds must have exactly 2 conditions");
488 DebugLoc DL = Br->getDebugLoc();
489 VPBasicBlock *BrOnTwoCondsBB = Br->getParent();
490 const auto Successors = to_vector(BrOnTwoCondsBB->getSuccessors());
491 assert(Successors.size() == 3 &&
492 "BranchOnTwoConds must have exactly 3 successors");
493
494 for (VPBlockBase *Succ : Successors)
495 VPBlockUtils::disconnectBlocks(BrOnTwoCondsBB, Succ);
496
497 VPValue *Cond0 = Br->getOperand(0);
498 VPValue *Cond1 = Br->getOperand(1);
499 VPBlockBase *Succ0 = Successors[0];
500 VPBlockBase *Succ1 = Successors[1];
501 VPBlockBase *Succ2 = Successors[2];
502
503 // If the successor block for both conditions is the same, then combine the
504 // two conditions and plant a single conditional branch.
505 if (Succ0 == Succ1) {
506 VPBuilder Builder(Br);
507 VPValue *Combined = Builder.createOr(Cond0, Cond1, DL);
508 Builder.createNaryOp(VPInstruction::BranchOnCond, {Combined}, DL);
509 VPBlockUtils::connectBlocks(BrOnTwoCondsBB, Succ0);
510 VPBlockUtils::connectBlocks(BrOnTwoCondsBB, Succ2);
511 Br->eraseFromParent();
512 continue;
513 }
514
515 assert(!Succ0->getParent() && !Succ1->getParent() && !Succ2->getParent() &&
516 !BrOnTwoCondsBB->getParent() && "regions must already be dissolved");
517
518 VPBasicBlock *InterimBB =
519 Plan.createVPBasicBlock(BrOnTwoCondsBB->getName() + ".interim");
520
521 VPBuilder(BrOnTwoCondsBB)
523 VPBlockUtils::connectBlocks(BrOnTwoCondsBB, Succ0);
524 VPBlockUtils::connectBlocks(BrOnTwoCondsBB, InterimBB);
525
527 VPBlockUtils::connectBlocks(InterimBB, Succ1);
528 VPBlockUtils::connectBlocks(InterimBB, Succ2);
529 Br->eraseFromParent();
530 }
531}
532
535 vp_depth_first_deep(Plan.getEntry()))) {
536 for (VPRecipeBase &R : make_early_inc_range(*VPBB)) {
537 VPBuilder Builder(&R);
538 if (auto *WidenIVR = dyn_cast<VPWidenIntOrFpInductionRecipe>(&R)) {
540 WidenIVR->eraseFromParent();
541 continue;
542 }
543
544 if (auto *WidenIVR = dyn_cast<VPWidenPointerInductionRecipe>(&R)) {
545 // If the recipe only generates scalars, scalarize it instead of
546 // expanding it.
547 if (WidenIVR->onlyScalarsGenerated(Plan.hasScalableVF())) {
549 WidenIVR, Plan, Builder);
550 WidenIVR->replaceAllUsesWith(PtrAdd);
551 WidenIVR->eraseFromParent();
552 continue;
553 }
555 WidenIVR->eraseFromParent();
556 continue;
557 }
558
559 if (auto *DerivedIVR = dyn_cast<VPDerivedIVRecipe>(&R)) {
560 expandVPDerivedIV(DerivedIVR);
561 DerivedIVR->eraseFromParent();
562 continue;
563 }
564
565 if (auto *WideCanIV = dyn_cast<VPWidenCanonicalIVRecipe>(&R)) {
566 VPValue *CanIV = WideCanIV->getCanonicalIV();
567 Type *CanIVTy = CanIV->getScalarType();
568 VPValue *Step = WideCanIV->getStepValue();
569 if (!Step) {
570 assert(Plan.getConcreteUF() == 1 &&
571 "Expected unroller to have materialized step for UF != 1");
572 Step = Plan.getZero(CanIVTy);
573 }
574 CanIV = Builder.createNaryOp(VPInstruction::Broadcast, CanIV);
575 Step = Builder.createNaryOp(VPInstruction::Broadcast, Step);
576 Step = Builder.createAdd(
577 Step, Builder.createNaryOp(VPInstruction::StepVector, {}, CanIVTy));
578 VPValue *CanVecIV =
579 Builder.createAdd(CanIV, Step, WideCanIV->getDebugLoc(), "vec.iv",
580 WideCanIV->getNoWrapFlags());
581 WideCanIV->replaceAllUsesWith(CanVecIV);
582 WideCanIV->eraseFromParent();
583 continue;
584 }
585
586 // Expand VPBlendRecipe into VPInstruction::Select.
587 if (auto *Blend = dyn_cast<VPBlendRecipe>(&R)) {
588 VPValue *Select = Blend->getIncomingValue(0);
589 for (unsigned I = 1; I != Blend->getNumIncomingValues(); ++I)
590 Select = Builder.createSelect(Blend->getMask(I),
591 Blend->getIncomingValue(I), Select,
592 R.getDebugLoc(), "predphi", *Blend);
593 Blend->replaceAllUsesWith(Select);
594 Blend->eraseFromParent();
595 continue;
596 }
597
598 if (auto *VEPR = dyn_cast<VPVectorEndPointerRecipe>(&R)) {
599 if (!VEPR->getOffset()) {
600 assert(Plan.getConcreteUF() == 1 &&
601 "Expected unroller to have materialized offset for UF != 1");
602 VEPR->materializeOffset();
603 }
604 continue;
605 }
606
607 if (auto *Expr = dyn_cast<VPExpressionRecipe>(&R)) {
608 Expr->decompose();
609 Expr->eraseFromParent();
610 continue;
611 }
612
613 // Expand LastActiveLane into Not + FirstActiveLane + Sub.
614 auto *LastActiveL = dyn_cast<VPInstruction>(&R);
615 if (LastActiveL &&
616 LastActiveL->getOpcode() == VPInstruction::LastActiveLane) {
617 // Create Not(Mask) for all operands.
619 for (VPValue *Op : LastActiveL->operands()) {
620 VPValue *NotMask = Builder.createNot(Op, LastActiveL->getDebugLoc());
621 NotMasks.push_back(NotMask);
622 }
623
624 // Create FirstActiveLane on the inverted masks.
625 VPValue *FirstInactiveLane = Builder.createFirstActiveLane(
626 NotMasks, LastActiveL->getDebugLoc(), "first.inactive.lane");
627
628 // Subtract 1 to get the last active lane.
629 VPValue *One =
630 Plan.getConstantInt(FirstInactiveLane->getScalarType(), 1);
631 VPValue *LastLane =
632 Builder.createSub(FirstInactiveLane, One,
633 LastActiveL->getDebugLoc(), "last.active.lane");
634
635 LastActiveL->replaceAllUsesWith(LastLane);
636 LastActiveL->eraseFromParent();
637 continue;
638 }
639
640 // Lower MaskedCond with block mask to LogicalAnd.
642 auto *VPI = cast<VPInstruction>(&R);
643 assert(VPI->isMasked() &&
644 "Unmasked MaskedCond should be simplified earlier");
645 VPI->replaceAllUsesWith(Builder.createNaryOp(
646 VPInstruction::LogicalAnd, {VPI->getMask(), VPI->getOperand(0)}));
647 VPI->eraseFromParent();
648 continue;
649 }
650
651 // Lower CanonicalIVIncrementForPart to plain Add.
652 if (match(
653 &R,
655 auto *VPI = cast<VPInstruction>(&R);
656 VPValue *Add = Builder.createOverflowingOp(
657 Instruction::Add, VPI->operands(), VPI->getNoWrapFlags(),
658 VPI->getDebugLoc());
659 VPI->replaceAllUsesWith(Add);
660 VPI->eraseFromParent();
661 continue;
662 }
663
664 // Lower BranchOnCount to ICmp + BranchOnCond.
665 VPValue *IV, *TC;
666 if (match(&R, m_BranchOnCount(m_VPValue(IV), m_VPValue(TC)))) {
667 auto *BranchOnCountInst = cast<VPInstruction>(&R);
668 DebugLoc DL = BranchOnCountInst->getDebugLoc();
669 VPValue *Cond = Builder.createICmp(CmpInst::ICMP_EQ, IV, TC, DL);
670 Builder.createNaryOp(VPInstruction::BranchOnCond, Cond, DL);
671 BranchOnCountInst->eraseFromParent();
672 continue;
673 }
674
675 VPValue *VectorStep;
676 VPValue *ScalarStep;
678 m_VPValue(VectorStep), m_VPValue(ScalarStep))))
679 continue;
680
681 // Expand WideIVStep.
682 auto *VPI = cast<VPInstruction>(&R);
683 Type *IVTy = VPI->getScalarType();
684 if (VectorStep->getScalarType() != IVTy) {
686 ? Instruction::UIToFP
687 : Instruction::Trunc;
688 VectorStep = Builder.createWidenCast(CastOp, VectorStep, IVTy);
689 }
690
691 assert(!match(ScalarStep, m_One()) && "Expected non-unit scalar-step");
692 if (ScalarStep->getScalarType() != IVTy) {
693 ScalarStep =
694 Builder.createWidenCast(Instruction::Trunc, ScalarStep, IVTy);
695 }
696
697 VPIRFlags Flags;
698 unsigned MulOpc;
699 if (IVTy->isFloatingPointTy()) {
700 MulOpc = Instruction::FMul;
701 Flags = VPI->getFastMathFlagsOrNone();
702 } else {
703 MulOpc = Instruction::Mul;
704 Flags = VPIRFlags::getDefaultFlags(MulOpc);
705 }
706
707 VPInstruction *Mul = Builder.createNaryOp(
708 MulOpc, {VectorStep, ScalarStep}, Flags, R.getDebugLoc());
709 VectorStep = Mul;
710 VPI->replaceAllUsesWith(VectorStep);
711 VPI->eraseFromParent();
712 }
713 }
714}
715
717 if (Plan.hasScalarVFOnly())
718 return;
719
720#ifndef NDEBUG
721 VPDominatorTree VPDT(Plan);
722#endif
723
724 SmallVector<VPValue *> VPValues;
725 if (VPValue *BTC = Plan.getBackedgeTakenCount())
726 VPValues.push_back(BTC);
727 append_range(VPValues, Plan.getLiveIns());
728 for (VPRecipeBase &R : *Plan.getEntry())
729 append_range(VPValues, R.definedValues());
730
731 auto *VectorPreheader = Plan.getVectorPreheader();
732 for (VPValue *VPV : VPValues) {
734 continue;
735
736 // Add explicit broadcast at the insert point that dominates all users.
737 VPBasicBlock *HoistBlock = VectorPreheader;
738 VPBasicBlock::iterator HoistPoint = VectorPreheader->end();
739 for (VPUser *User : VPV->users()) {
740 if (User->usesScalars(VPV))
741 continue;
742 if (cast<VPRecipeBase>(User)->getParent() == VectorPreheader)
743 HoistPoint = HoistBlock->begin();
744 else
745 assert(VPDT.dominates(VectorPreheader,
746 cast<VPRecipeBase>(User)->getParent()) &&
747 "All users must be in the vector preheader or dominated by it");
748 }
749
750 VPBuilder Builder(cast<VPBasicBlock>(HoistBlock), HoistPoint);
751 auto *Broadcast = Builder.createNaryOp(VPInstruction::Broadcast, {VPV});
752 VPV->replaceUsesWithIf(Broadcast,
753 [VPV, Broadcast](VPUser &U, unsigned Idx) {
754 return Broadcast != &U && !U.usesScalars(VPV);
755 });
756 }
757}
758
760 VPlan &Plan, ElementCount BestVF, unsigned BestUF,
762 assert(Plan.hasVF(BestVF) && "BestVF is not available in Plan");
763 assert(Plan.hasUF(BestUF) && "BestUF is not available in Plan");
764
765 VPValue *TC = Plan.getTripCount();
766 if (TC->user_empty())
767 return;
768
769 // Skip cases for which the trip count may be non-trivial to materialize.
770 // I.e., when a scalar tail is absent - due to tail folding, or when a scalar
771 // tail is required.
772 if (Plan.hasTailFolded() || !Plan.hasScalarTail() ||
774 Plan.getScalarPreheader() ||
775 !isa<VPIRValue>(TC))
776 return;
777
778 // Materialize vector trip counts for constants early if it can simply
779 // be computed as (Original TC / VF * UF) * VF * UF.
780 // TODO: Compute vector trip counts for loops requiring a scalar epilogue and
781 // tail-folded loops.
782 ScalarEvolution &SE = *PSE.getSE();
783 auto *TCScev = SE.getSCEV(TC->getLiveInIRValue());
784 if (!isa<SCEVConstant>(TCScev))
785 return;
786 const SCEV *VFxUF = SE.getElementCount(TCScev->getType(), BestVF * BestUF);
787 auto VecTCScev = SE.getMulExpr(SE.getUDivExpr(TCScev, VFxUF), VFxUF);
788 if (auto *ConstVecTC = dyn_cast<SCEVConstant>(VecTCScev))
789 Plan.getVectorTripCount().setUnderlyingValue(ConstVecTC->getValue());
790}
791
793 VPBasicBlock *VectorPH) {
795 if (BTC->user_empty())
796 return;
797
798 VPBuilder Builder(VectorPH, VectorPH->begin());
799 auto *TCTy = Plan.getTripCount()->getScalarType();
800 auto *TCMO =
801 Builder.createSub(Plan.getTripCount(), Plan.getConstantInt(TCTy, 1),
802 DebugLoc::getCompilerGenerated(), "trip.count.minus.1");
803 BTC->replaceAllUsesWith(TCMO);
804}
805
807 if (Plan.hasScalarVFOnly())
808 return;
809
810 VPRegionBlock *LoopRegion = Plan.getVectorLoopRegion();
811 auto VPBBsOutsideLoopRegion = VPBlockUtils::blocksOnly<VPBasicBlock>(
813 auto VPBBsInsideLoopRegion = VPBlockUtils::blocksOnly<VPBasicBlock>(
814 vp_depth_first_shallow(LoopRegion->getEntry()));
815 // Materialize Build(Struct)Vector for all replicating VPReplicateRecipes,
816 // VPScalarIVStepsRecipe and VPInstructions, excluding ones in replicate
817 // regions. Those are not materialized explicitly yet.
818 // TODO: materialize build vectors for replicating recipes in replicating
819 // regions.
820 for (VPBasicBlock *VPBB :
821 concat<VPBasicBlock *>(VPBBsOutsideLoopRegion, VPBBsInsideLoopRegion)) {
822 for (VPRecipeBase &R : make_early_inc_range(*VPBB)) {
824 continue;
825 auto *DefR = cast<VPSingleDefRecipe>(&R);
826 auto UsesVectorOrInsideReplicateRegion = [DefR, LoopRegion](VPUser *U) {
827 VPRegionBlock *ParentRegion = cast<VPRecipeBase>(U)->getRegion();
828 return !U->usesScalars(DefR) || ParentRegion != LoopRegion;
829 };
830 if (none_of(DefR->users(), UsesVectorOrInsideReplicateRegion))
831 continue;
832
833 Type *ScalarTy = DefR->getScalarType();
834 unsigned Opcode = ScalarTy->isStructTy()
837 auto *BuildVector = new VPInstruction(Opcode, {DefR});
838 BuildVector->insertAfter(DefR);
839
840 DefR->replaceUsesWithIf(
841 BuildVector, [BuildVector, &UsesVectorOrInsideReplicateRegion](
842 VPUser &U, unsigned) {
843 return &U != BuildVector && UsesVectorOrInsideReplicateRegion(&U);
844 });
845 }
846 }
847
848 // Create explicit VPInstructions to convert vectors to scalars. The current
849 // implementation is conservative - it may miss some cases that may or may not
850 // be vector values. TODO: introduce Unpacks speculatively - remove them later
851 // if they are known to operate on scalar values.
852 for (VPBasicBlock *VPBB : VPBBsInsideLoopRegion) {
853 for (VPRecipeBase &R : make_early_inc_range(*VPBB)) {
856 continue;
857 for (VPValue *Def : R.definedValues()) {
858 // Skip recipes that are single-scalar.
859 // TODO: The Defs skipped here may or may not be vector values.
860 // Introduce Unpacks, and remove them later, if they are guaranteed to
861 // produce scalar values.
863 continue;
864
865 // Only introduce an Unpack if some, but not all, users use the first
866 // lane only.
867 unsigned NumFirstLaneUsers = count_if(Def->users(), [&Def](VPUser *U) {
868 return U->usesFirstLaneOnly(Def);
869 });
870 if (!NumFirstLaneUsers || NumFirstLaneUsers == Def->getNumUsers())
871 continue;
872
873 auto *Unpack = new VPInstruction(VPInstruction::Unpack, {Def});
874 if (R.isPhi())
875 Unpack->insertBefore(*VPBB, VPBB->getFirstNonPhi());
876 else
877 Unpack->insertAfter(&R);
878 Def->replaceUsesWithIf(Unpack, [&Def](VPUser &U, unsigned) {
879 return U.usesFirstLaneOnly(Def);
880 });
881 }
882 }
883 }
884}
885
887 VPlan &Plan, VPBasicBlock *VectorPHVPBB, bool TailByMasking,
888 bool RequiresScalarEpilogue, VPValue *Step,
889 std::optional<uint64_t> MaxRuntimeStep) {
890 VPSymbolicValue &VectorTC = Plan.getVectorTripCount();
891 // There's nothing to do if there are no users of the vector trip count or its
892 // IR value has already been set.
893 if (VectorTC.user_empty() || VectorTC.getUnderlyingValue())
894 return;
895
896 VPValue *TC = Plan.getTripCount();
897 Type *TCTy = TC->getScalarType();
898 VPBasicBlock::iterator InsertPt = VectorPHVPBB->begin();
899 if (auto *StepR = Step->getDefiningRecipe()) {
900 assert(VPDominatorTree(Plan).dominates(StepR->getParent(), VectorPHVPBB) &&
901 "Step VPBB must dominate VectorPHVPBB");
902 // Insert after Step's definition to maintain valid def-use ordering.
903 InsertPt = std::next(StepR->getIterator());
904 }
905 VPBuilder Builder(VectorPHVPBB, InsertPt);
906
907 // For scalable steps, if TC is a constant and is divisible by the maximum
908 // possible runtime step, then TC % Step == 0 for all valid vscale values
909 // and the vector trip count equals TC directly.
910 const APInt *TCVal;
911 if (!RequiresScalarEpilogue && match(TC, m_APInt(TCVal)) && MaxRuntimeStep &&
912 TCVal->urem(*MaxRuntimeStep) == 0) {
913 VectorTC.replaceAllUsesWith(TC);
914 return;
915 }
916
917 // If the tail is to be folded by masking, round the number of iterations N
918 // up to a multiple of Step instead of rounding down. This is done by first
919 // adding Step-1 and then rounding down. Note that it's ok if this addition
920 // overflows: the vector induction variable will eventually wrap to zero given
921 // that it starts at zero and its Step is a power of two; the loop will then
922 // exit, with the last early-exit vector comparison also producing all-true.
923 if (TailByMasking) {
924 TC = Builder.createAdd(
925 TC, Builder.createSub(Step, Plan.getConstantInt(TCTy, 1)),
926 DebugLoc::getCompilerGenerated(), "n.rnd.up");
927 }
928
929 // Now we need to generate the expression for the part of the loop that the
930 // vectorized body will execute. This is equal to N - (N % Step) if scalar
931 // iterations are not required for correctness, or N - Step, otherwise. Step
932 // is equal to the vectorization factor (number of SIMD elements) times the
933 // unroll factor (number of SIMD instructions).
934 VPValue *R =
935 Builder.createNaryOp(Instruction::URem, {TC, Step},
936 DebugLoc::getCompilerGenerated(), "n.mod.vf");
937
938 // There are cases where we *must* run at least one iteration in the remainder
939 // loop. See the cost model for when this can happen. If the step evenly
940 // divides the trip count, we set the remainder to be equal to the step. If
941 // the step does not evenly divide the trip count, no adjustment is necessary
942 // since there will already be scalar iterations. Note that the minimum
943 // iterations check ensures that N >= Step.
944 if (RequiresScalarEpilogue) {
945 assert(!TailByMasking &&
946 "requiring scalar epilogue is not supported with fail folding");
947 VPValue *IsZero =
948 Builder.createICmp(CmpInst::ICMP_EQ, R, Plan.getZero(TCTy));
949 R = Builder.createSelect(IsZero, Step, R);
950 }
951
952 VPValue *Res =
953 Builder.createSub(TC, R, DebugLoc::getCompilerGenerated(), "n.vec");
954 VectorTC.replaceAllUsesWith(Res);
955}
956
958 ElementCount VFEC) {
959 // If VF and VFxUF have already been materialized (no remaining users),
960 // there's nothing more to do.
961 if (Plan.getVF().isMaterialized()) {
962 assert(Plan.getVFxUF().isMaterialized() &&
963 "VF and VFxUF must be materialized together");
964 return;
965 }
966
967 VPBuilder Builder(VectorPH, VectorPH->begin());
968 Type *TCTy = Plan.getTripCount()->getScalarType();
969 VPValue &VF = Plan.getVF();
970 VPValue &VFxUF = Plan.getVFxUF();
971 // If there are no users of the runtime VF, compute VFxUF by constant folding
972 // the multiplication of VF and UF.
973 if (VF.user_empty()) {
974 VPValue *RuntimeVFxUF =
975 Builder.createElementCount(TCTy, VFEC * Plan.getConcreteUF());
976 VFxUF.replaceAllUsesWith(RuntimeVFxUF);
977 return;
978 }
979
980 // For users of the runtime VF, compute it as VF * vscale, and VFxUF as (VF *
981 // vscale) * UF.
982 VPValue *RuntimeVF = Builder.createElementCount(TCTy, VFEC);
984 VPValue *BC = Builder.createNaryOp(VPInstruction::Broadcast, RuntimeVF);
986 BC, [&VF](VPUser &U, unsigned) { return !U.usesScalars(&VF); });
987 }
988 VF.replaceAllUsesWith(RuntimeVF);
989
990 VPValue *MulByUF = Builder.createOverflowingOp(
991 Instruction::Mul,
992 {RuntimeVF, Plan.getConstantInt(TCTy, Plan.getConcreteUF())},
993 {true, false});
994 VFxUF.replaceAllUsesWith(MulByUF);
995}
996
997VPValue *
999 ArrayRef<PointerDiffInfo> DiffChecks) {
1000 VPBuilder Builder(AliasCheckVPBB);
1001 Type *I1Ty = IntegerType::getInt1Ty(Plan.getContext());
1002
1003 VPValue *IncomingAliasMask = vputils::findIncomingAliasMask(Plan);
1004 assert(IncomingAliasMask && "Expected an alias mask!");
1005
1006 VPValue *AliasMask = nullptr;
1007 for (const PointerDiffInfo &Check : DiffChecks) {
1009 VPValue *Sink =
1011 Type *AddrType = Src->getScalarType();
1012
1013 // TODO: Only freeze the required pointer (not both src and sink).
1014 if (Check.NeedsFreeze) {
1015 Src = Builder.createScalarFreeze(Src, AddrType, DebugLoc::getUnknown());
1016 Sink = Builder.createScalarFreeze(Sink, AddrType, DebugLoc::getUnknown());
1017 }
1018
1019 // TODO: Generate loop_dependence_raw_mask when there's a read-after-write
1020 // dependency between the source and the sink. This is not necessary for
1021 // correctness of the mask, but using the "raw" variant prevents loads
1022 // depending on the completion of stores.
1023 VPWidenIntrinsicRecipe *WARMask = Builder.insert(new VPWidenIntrinsicRecipe(
1024 Intrinsic::loop_dependence_war_mask,
1025 {Src, Sink, Plan.getConstantInt(AddrType, Check.AccessSize)}, I1Ty));
1026
1027 if (AliasMask)
1028 AliasMask = Builder.createAnd(AliasMask, WARMask);
1029 else
1030 AliasMask = WARMask;
1031 }
1032
1034 Type *IndexTy = Plan.getDataLayout().getIndexType(Plan.getContext(), 0);
1035 VPValue *NumActive = Builder.createNaryOp(
1036 VPInstruction::NumActiveLanes, {AliasMask}, nullptr, {}, {},
1037 DebugLoc::getUnknown(), "num.active.lanes", IndexTy);
1038 VPValue *ClampedVF = Builder.createScalarZExtOrTrunc(
1039 NumActive, IVTy, DebugLoc::getCompilerGenerated());
1040
1041 IncomingAliasMask->replaceAllUsesWith(AliasMask);
1042
1043 return ClampedVF;
1044}
1045
1047 VPlan &Plan, ArrayRef<PointerDiffInfo> DiffChecks, bool HasBranchWeights) {
1048 VPBasicBlock *ClampedVFCheck =
1049 Plan.createVPBasicBlock("vector.clamped.vf.check");
1050
1051 VPValue *ClampedVF = materializeAliasMask(Plan, ClampedVFCheck, DiffChecks);
1052 VPBuilder Builder(ClampedVFCheck);
1054 Type *TCTy = Plan.getTripCount()->getScalarType();
1055
1056 // Check the "ClampedVF" from the alias mask is larger than one.
1057 VPValue *IsScalar =
1058 Builder.createICmp(CmpInst::ICMP_ULE, ClampedVF,
1059 Plan.getConstantInt(TCTy, 1), DL, "vf.is.scalar");
1060
1061 VPValue *TripCount = Plan.getTripCount();
1062 VPValue *MaxUIntTripCount =
1064 VPValue *DistanceToMax = Builder.createSub(MaxUIntTripCount, TripCount);
1065
1066 // For tail-folding: Don't execute the vector loop if (UMax - n) < ClampedVF.
1067 // Note: The ClampedVF may not be a power-of-two. This means the loop exit
1068 // condition (index.next == n.vec) may not be correct in the case of an
1069 // overflow. The issue is `n.vec` could be zero due to an overflow, but
1070 // index.next is not guaranteed to overflow to zero as the ClampedVF is not a
1071 // power-of-two).
1072 VPValue *TripCountCheck = Builder.createICmp(
1073 ICmpInst::ICMP_ULT, DistanceToMax, ClampedVF, DL, "vf.step.overflow");
1074
1075 VPValue *Cond = Builder.createOr(IsScalar, TripCountCheck, DL);
1076 attachVPCheckBlock(Plan, Cond, ClampedVFCheck, HasBranchWeights);
1077
1078 // Materialize the trip count early as this will add a use of (VFxUF) that
1079 // needs to be replaced with the ClampedVF.
1081 /*TailByMasking=*/true,
1082 /*RequiresScalarEpilogue=*/false,
1083 &Plan.getVFxUF());
1084
1085 assert(Plan.getConcreteUF() == 1 &&
1086 "Clamped VF not supported with interleaving");
1087 Plan.getVF().replaceAllUsesWith(ClampedVF);
1088 Plan.getVFxUF().replaceAllUsesWith(ClampedVF);
1089}
1090
1092 ScalarEvolution &SE) {
1093 auto *Entry = Plan.getEntry();
1094 VPBuilder Builder(Entry, Entry->begin());
1096 ->getIRBasicBlock()
1097 ->getTerminator()
1098 ->getDebugLoc();
1099 VPSCEVExpander Expander(Builder, SE, DL);
1100
1101 // Expand VPExpandSCEVRecipes to VPInstructions using VPSCEVExpander. During
1102 // the transition, unsupported VPExpandSCEVRecipes are skipped and left for
1103 // late expansion.
1104 for (VPRecipeBase &R : make_early_inc_range(*Entry)) {
1105 auto *ExpSCEV = dyn_cast<VPExpandSCEVRecipe>(&R);
1106 if (!ExpSCEV || ExpSCEV->user_empty())
1107 continue;
1108 Builder.setInsertPoint(ExpSCEV);
1109 VPValue *Expanded = Expander.tryToExpand(ExpSCEV->getSCEV());
1110 if (!Expanded)
1111 continue;
1112 ExpSCEV->replaceAllUsesWith(Expanded);
1113 // TripCount should not be used after expansion to VPInstructions. Reset to
1114 // poison to avoid dangling references.
1115 if (Plan.getTripCount() == ExpSCEV)
1116 Plan.resetTripCount(Plan.getPoison(ExpSCEV->getScalarType()));
1117 ExpSCEV->eraseFromParent();
1118 }
1119}
1120
1123 SCEVExpander Expander(SE, "induction", /*PreserveLCSSA=*/false);
1124
1125 auto *Entry = cast<VPIRBasicBlock>(Plan.getEntry());
1126 BasicBlock *EntryBB = Entry->getIRBasicBlock();
1127 DenseMap<const SCEV *, Value *> ExpandedSCEVs;
1128 // Expand remaining VPExpandSCEVRecipes to IR instructions using SCEVExpander.
1129 for (VPRecipeBase &R : make_early_inc_range(*Entry)) {
1130 auto *ExpSCEV = dyn_cast<VPExpandSCEVRecipe>(&R);
1131 if (!ExpSCEV)
1132 continue;
1133 const SCEV *Expr = ExpSCEV->getSCEV();
1134 Value *Res =
1135 Expander.expandCodeFor(Expr, Expr->getType(), EntryBB->getTerminator());
1136 ExpandedSCEVs[Expr] = Res;
1137 VPValue *Exp = Plan.getOrAddLiveIn(Res);
1138 ExpSCEV->replaceAllUsesWith(Exp);
1139 if (Plan.getTripCount() == ExpSCEV)
1140 Plan.resetTripCount(Exp);
1141 ExpSCEV->eraseFromParent();
1142 }
1144 "all VPExpandSCEVRecipes must have been expanded");
1145 // Add IR instructions in the entry basic block but not in the VPIRBasicBlock
1146 // to the VPIRBasicBlock.
1147 auto EI = Entry->begin();
1148 for (Instruction &I : drop_end(*EntryBB)) {
1149 if (EI != Entry->end() && isa<VPIRInstruction>(*EI) &&
1150 &cast<VPIRInstruction>(&*EI)->getInstruction() == &I) {
1151 EI++;
1152 continue;
1153 }
1155 }
1156
1157 return ExpandedSCEVs;
1158}
1159
1160/// Add branch weight metadata, if the \p Plan's middle block is terminated by a
1161/// BranchOnCond recipe.
1163 VPlan &Plan, ElementCount VF, std::optional<unsigned> VScaleForTuning) {
1164 VPBasicBlock *MiddleVPBB = Plan.getMiddleBlock();
1165 auto *MiddleTerm =
1167 // Only add branch metadata if there is a (conditional) terminator.
1168 if (!MiddleTerm)
1169 return;
1170
1171 assert(MiddleTerm->getOpcode() == VPInstruction::BranchOnCond &&
1172 "must have a BranchOnCond");
1173 // Assume that `TripCount % VectorStep ` is equally distributed.
1174 unsigned VectorStep = Plan.getConcreteUF() * VF.getKnownMinValue();
1175 if (VF.isScalable() && VScaleForTuning.has_value())
1176 VectorStep *= *VScaleForTuning;
1177 assert(VectorStep > 0 && "trip count should not be zero");
1178 MDBuilder MDB(Plan.getContext());
1179 MDNode *BranchWeights =
1180 MDB.createBranchWeights({1, VectorStep - 1}, /*IsExpected=*/false);
1181 MiddleTerm->setMetadata(LLVMContext::MD_prof, BranchWeights);
1182}
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
AMDGPU Register Bank Select
This file implements a class to represent arbitrary precision integral constant values and operations...
MachineBasicBlock MachineBasicBlock::iterator DebugLoc DL
static const Function * getParent(const Value *V)
static cl::opt< OutputCostKind > CostKind("cost-kind", cl::desc("Target cost kind"), cl::init(OutputCostKind::RecipThroughput), cl::values(clEnumValN(OutputCostKind::RecipThroughput, "throughput", "Reciprocal throughput"), clEnumValN(OutputCostKind::Latency, "latency", "Instruction latency"), clEnumValN(OutputCostKind::CodeSize, "code-size", "Code size"), clEnumValN(OutputCostKind::SizeAndLatency, "size-latency", "Code size and latency"), clEnumValN(OutputCostKind::All, "all", "Print all cost kinds")))
static std::pair< Value *, APInt > getMask(Value *WideMask, unsigned Factor, ElementCount LeafValueEC)
This file provides a LoopVectorizationPlanner class.
#define I(x, y, z)
Definition MD5.cpp:57
This file contains the declarations for metadata subclasses.
const SmallVectorImpl< MachineOperand > & Cond
static bool dominates(InstrPosIndexes &PosIndexes, const MachineInstr &A, const MachineInstr &B)
This file contains some templates that are useful if you are working with the STL at all.
This file defines the SmallPtrSet class.
This file implements dominator tree analysis for a single level of a VPlan's H-CFG.
This file contains the declarations of different VPlan-related auxiliary helpers.
static VPActiveLaneMaskPHIRecipe * addVPLaneMaskPhiAndUpdateExitBranch(VPlan &Plan)
static void expandVPDerivedIV(VPDerivedIVRecipe *R)
Expand a VPDerivedIVRecipe into executable recipes.
static void expandVPWidenIntOrFpInduction(VPWidenIntOrFpInductionRecipe *WidenIVR)
Expand a VPWidenIntOrFpInduction into executable recipes, for the initial value, phi and backedge val...
static void expandVPWidenPointerInduction(VPWidenPointerInductionRecipe *R)
Expand a VPWidenPointerInductionRecipe into executable recipes, for the initial value,...
This file provides utility VPlan to VPlan transformations.
This file contains the declarations of the Vectorization Plan base classes:
static const uint32_t IV[8]
Definition blake3_impl.h:83
Class for arbitrary precision integers.
Definition APInt.h:78
LLVM_ABI APInt urem(const APInt &RHS) const
Unsigned remainder operation.
Definition APInt.cpp:1692
Represent a constant reference to an array (0 or more elements consecutively in memory),...
Definition ArrayRef.h:40
LLVM Basic Block Representation.
Definition BasicBlock.h:62
const Instruction * getTerminator() const LLVM_READONLY
Returns the terminator instruction; assumes that the block is well-formed.
Definition BasicBlock.h:237
@ ICMP_ULT
unsigned less than
Definition InstrTypes.h:765
@ ICMP_ULE
unsigned less or equal
Definition InstrTypes.h:766
LLVM_ABI IntegerType * getIndexType(LLVMContext &C, unsigned AddressSpace) const
Returns the type of a GEP index in AddressSpace.
A debug info location.
Definition DebugLoc.h:126
static DebugLoc getCompilerGenerated()
Definition DebugLoc.h:154
static DebugLoc getUnknown()
Definition DebugLoc.h:153
bool dominates(const DomTreeNodeBase< NodeT > *A, const DomTreeNodeBase< NodeT > *B) const
dominates - Returns true iff A dominates B.
Utility class for floating point operations which can have information about relaxed accuracy require...
Definition Operator.h:202
FastMathFlags getFastMathFlags() const
Convenience function for getting all the fast-math flags.
Definition Operator.h:291
Convenience struct for specifying and reasoning about fast-math flags.
Definition FMF.h:23
A struct for saving information about induction variables.
static LLVM_ABI InductionDescriptor getCanonicalIntInduction(Type *Ty, ScalarEvolution &SE)
Returns the canonical integer induction for type Ty with start = 0 and step = 1.
@ IK_NoInduction
Not an induction variable.
@ IK_FpInduction
Floating point induction variable.
@ IK_PtrInduction
Pointer induction var. Step = C.
@ IK_IntInduction
Integer induction variable. Step = C.
static LLVM_ABI IntegerType * get(LLVMContext &C, unsigned NumBits)
This static method is the primary way of constructing an IntegerType.
Definition Type.cpp:348
LLVM_ABI MDNode * createBranchWeights(uint32_t TrueWeight, uint32_t FalseWeight, bool IsExpected=false)
Return metadata containing two branch weights.
Definition MDBuilder.cpp:38
Metadata node.
Definition Metadata.h:1069
unsigned getOpcode() const
Return the opcode for this Instruction or ConstantExpr.
Definition Operator.h:43
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.
This class uses information about analyze scalars to rewrite expressions in canonical form.
LLVM_ABI Value * expandCodeFor(SCEVUse SH, Type *Ty, BasicBlock::iterator I)
Insert code to directly compute the specified SCEV expression into the program.
This class represents an analyzed expression in the program.
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 * getSCEV(Value *V)
Return a SCEV expression for the full generality of the specified expression.
LLVM_ABI const SCEV * getElementCount(Type *Ty, ElementCount EC, SCEV::NoWrapFlags Flags=SCEV::FlagAnyWrap)
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.
A templated base class for SmallPtrSet which provides the typesafe interface that is common across al...
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 pass provides access to the codegen interfaces that are needed for IR-level transformations.
TargetCostKind
The kind of cost model.
@ SK_Broadcast
Broadcast element 0 to all other elements.
The instances of the Type class are immutable: once they are created, they are never changed.
Definition Type.h:46
Type * getScalarType() const
If this is a vector type, return the element type, otherwise return 'this'.
Definition Type.h:368
bool isStructTy() const
True if this is an instance of StructType.
Definition Type.h:276
LLVM_ABI unsigned getScalarSizeInBits() const LLVM_READONLY
If this is a vector type, return the getPrimitiveSizeInBits value for the element type.
Definition Type.cpp:232
static LLVM_ABI IntegerType * getInt1Ty(LLVMContext &C)
Definition Type.cpp:306
bool isFloatingPointTy() const
Return true if this is one of the floating-point types.
Definition Type.h:186
bool isIntegerTy() const
True if this is an instance of IntegerType.
Definition Type.h:257
A recipe for generating the active lane mask for the vector loop that is used to predicate the vector...
Definition VPlan.h:4041
VPBasicBlock serves as the leaf of the Hierarchical Control-Flow Graph.
Definition VPlan.h:4380
RecipeListTy::iterator iterator
Instruction iterators...
Definition VPlan.h:4407
iterator begin()
Recipe iterator methods.
Definition VPlan.h:4415
VPRecipeBase * getTerminator()
If the block has multiple successors, return the branch recipe terminating the block.
Definition VPlan.cpp:663
VPBlockBase is the building block of the Hierarchical Control-Flow Graph.
Definition VPlan.h:94
VPRegionBlock * getParent()
Definition VPlan.h:192
const VPBasicBlock * getExitingBasicBlock() const
Definition VPlan.cpp:236
VPlan * getPlan()
Definition VPlan.cpp:211
const std::string & getName() const
Definition VPlan.h:183
const VPBasicBlock * getEntryBasicBlock() const
Definition VPlan.cpp:216
VPBlockBase * getSingleSuccessor() const
Definition VPlan.h:233
const VPBlocksTy & getSuccessors() const
Definition VPlan.h:217
static auto blocksAs(T &&Range)
Return an iterator range over Range with each block cast to BlockTy.
Definition VPlanUtils.h:402
static void connectBlocks(VPBlockBase *From, VPBlockBase *To, unsigned PredIdx=-1u, unsigned SuccIdx=-1u)
Connect VPBlockBases From and To bi-directionally.
Definition VPlanUtils.h:330
static void disconnectBlocks(VPBlockBase *From, VPBlockBase *To)
Disconnect VPBlockBases From and To bi-directionally.
Definition VPlanUtils.h:348
static auto blocksOnly(T &&Range)
Return an iterator range over Range which only includes BlockTy blocks.
Definition VPlanUtils.h:384
VPlan-based builder utility analogous to IRBuilder.
VPWidenPHIRecipe * createWidenPhi(ArrayRef< VPValue * > IncomingValues, DebugLoc DL=DebugLoc::getUnknown(), const Twine &Name="")
VPInstruction * createNaryOp(unsigned Opcode, ArrayRef< VPValue * > Operands, Instruction *Inst=nullptr, const VPIRFlags &Flags={}, const VPIRMetadata &MD={}, DebugLoc DL=DebugLoc::getUnknown(), const Twine &Name="", Type *ResultTy=nullptr)
Create an N-ary operation with Opcode, Operands and set Inst as its underlying Instruction.
A recipe for converting Current into Start + Current * Step.
Definition VPlan.h:4174
Template specialization of the standard LLVM dominator tree utility for VPBlockBases.
Class to record and manage LLVM IR flags.
Definition VPlan.h:704
static VPIRFlags getDefaultFlags(unsigned Opcode, Type *ResultTy=nullptr)
Returns default flags for Opcode and scalar ResultTy for opcodes that support it, asserts otherwise.
void dropPoisonGeneratingFlags()
Drop all poison-generating flags.
Definition VPlan.h:902
static LLVM_ABI_FOR_TEST VPIRInstruction * create(Instruction &I)
Create a new VPIRPhi for \I , if it is a PHINode, otherwise create a VPIRInstruction.
This is a concrete Recipe that models a single VPlan-level instruction.
Definition VPlan.h:1234
@ Unpack
Extracts all lanes from its (non-scalable) vector operand.
Definition VPlan.h:1277
@ BuildVector
Creates a fixed-width vector containing all operands.
Definition VPlan.h:1272
@ BuildStructVector
Given operands of (the same) struct type, creates a struct of fixed- width vectors each containing a ...
Definition VPlan.h:1269
@ CanonicalIVIncrementForPart
Definition VPlan.h:1253
void addIncoming(VPValue *IncomingV)
Append IncomingV as an incoming value to the phi-like recipe.
Definition VPlan.h:1667
VPRecipeBase is a base class modeling a sequence of one or more output IR instructions.
Definition VPlan.h:411
VPBasicBlock * getParent()
Definition VPlan.h:483
DebugLoc getDebugLoc() const
Returns the debug location of the recipe.
Definition VPlan.h:561
void insertBefore(VPRecipeBase *InsertPos)
Insert an unlinked recipe into a basic block immediately before the specified recipe.
void insertAfter(VPRecipeBase *InsertPos)
Insert an unlinked Recipe into a basic block immediately after the specified Recipe.
iplist< VPRecipeBase >::iterator eraseFromParent()
This method unlinks 'this' from the containing basic block and deletes it.
Type * getScalarType() const
Returns the scalar type of this VPRecipeValue.
Definition VPlanValue.h:354
VPRegionBlock represents a collection of VPBasicBlocks and VPRegionBlocks which form a Single-Entry-S...
Definition VPlan.h:4605
const VPBlockBase * getEntry() const
Definition VPlan.h:4649
VPRegionValue * getUsedHeaderMask() const
Return the header mask if it exists and is used, or null otherwise.
Definition VPlan.h:4745
VPInstruction * getOrCreateCanonicalIVIncrement()
Get the canonical IV increment instruction if it exists.
Definition VPlan.cpp:898
Type * getCanonicalIVType() const
Return the type of the canonical IV for loop regions.
Definition VPlan.h:4733
void clearCanonicalIVNUW(VPInstruction *Increment)
Unsets NUW for the canonical IV increment Increment, for loop regions.
Definition VPlan.h:4772
VPRegionValue * getCanonicalIV()
Return the canonical induction variable of the region, null for replicating regions.
Definition VPlan.h:4725
VPReplicateRecipe replicates a given instruction producing multiple scalar copies of the original sca...
Definition VPlan.h:3388
Lightweight SCEV-to-VPlan expander.
Definition VPlanUtils.h:250
VPValue * tryToExpand(const SCEV *S)
Try to expand S into recipes and live-ins using the builder.
A recipe for handling phi nodes of integer and floating-point inductions, producing their scalar valu...
Definition VPlan.h:4235
A symbolic live-in VPValue, used for values like vector trip count, VF, and VFxUF.
Definition VPlanValue.h:217
bool isMaterialized() const
Returns true if this value has been materialized.
Definition VPlanValue.h:235
This class augments VPValue with operands which provide the inverse def-use edges from VPValue's user...
Definition VPlanValue.h:401
This is the base class of the VPlan Def/Use graph, used for modeling the data flow into,...
Definition VPlanValue.h:50
Type * getScalarType() const
Returns the scalar type of this VPValue, dispatching based on the concrete subclass.
Definition VPlan.cpp:149
Value * getLiveInIRValue() const
Return the underlying IR value for a VPIRValue.
Definition VPlan.cpp:143
VPRecipeBase * getDefiningRecipe()
Returns the recipe defining this VPValue or nullptr if it is not defined by a recipe,...
Definition VPlan.cpp:130
Value * getUnderlyingValue() const
Return the underlying Value attached to this VPValue.
Definition VPlanValue.h:75
bool user_empty() const
Definition VPlanValue.h:161
void setUnderlyingValue(Value *Val)
Definition VPlanValue.h:209
void replaceAllUsesWith(VPValue *New)
Definition VPlan.cpp:1495
void replaceUsesWithIf(VPValue *New, llvm::function_ref< bool(VPUser &U, unsigned Idx)> ShouldReplace)
Go through the uses list for this VPValue and make each use point to New if the callback ShouldReplac...
Definition VPlan.cpp:1501
A Recipe for widening the canonical induction variable of the vector loop.
Definition VPlan.h:4117
VPIRValue * getStartValue() const
Returns the start value of the induction.
Definition VPlan.h:2559
VPValue * getStepValue()
Returns the step value of the induction.
Definition VPlan.h:2562
const InductionDescriptor & getInductionDescriptor() const
Returns the induction descriptor for the recipe.
Definition VPlan.h:2582
A recipe for handling phi nodes of integer and floating-point inductions, producing their vector valu...
Definition VPlan.h:2611
VPValue * getSplatVFValue() const
If the recipe has been unrolled, return the VPValue for the induction increment, otherwise return nul...
Definition VPlan.h:2659
VPValue * getLastUnrolledPartOperand()
Returns the VPValue representing the value of this induction at the last unrolled part,...
Definition VPlan.h:2685
A recipe for widening vector intrinsics.
Definition VPlan.h:1927
VPlan models a candidate for vectorization, encoding various decisions take to produce efficient outp...
Definition VPlan.h:4792
bool hasVF(ElementCount VF) const
Definition VPlan.h:5017
const DataLayout & getDataLayout() const
Definition VPlan.h:4999
LLVMContext & getContext() const
Definition VPlan.h:4995
VPBasicBlock * getEntry()
Definition VPlan.h:4888
bool hasScalableVF() const
Definition VPlan.h:5018
VPValue * getTripCount() const
The trip count of the original loop.
Definition VPlan.h:4953
VPValue * getOrCreateBackedgeTakenCount()
The backedge taken count of the original loop.
Definition VPlan.h:4974
VPSymbolicValue & getVFxUF()
Returns VF * UF of the vector loop region.
Definition VPlan.h:4993
auto getLiveIns() const
Return the list of live-in VPValues available in the VPlan.
Definition VPlan.h:5127
bool hasUF(unsigned UF) const
Definition VPlan.h:5042
VPIRValue * getPoison(Type *Ty)
Return a VPIRValue wrapping a poison value of type Ty.
Definition VPlan.h:5118
VPSymbolicValue & getVectorTripCount()
The vector trip count.
Definition VPlan.h:4983
VPValue * getBackedgeTakenCount() const
Definition VPlan.h:4980
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:5067
VPIRValue * getZero(Type *Ty)
Return a VPIRValue wrapping the null value of type Ty.
Definition VPlan.h:5093
LLVM_ABI_FOR_TEST VPRegionBlock * getVectorLoopRegion()
Returns the VPRegionBlock of the vector loop.
Definition VPlan.cpp:1080
unsigned getConcreteUF() const
Returns the concrete UF of the plan, after unrolling.
Definition VPlan.h:5045
void resetTripCount(VPValue *NewTripCount)
Resets the trip count for the VPlan.
Definition VPlan.h:4967
VPBasicBlock * getMiddleBlock()
Returns the 'middle' block of the plan, that is the block that selects whether to execute the scalar ...
Definition VPlan.h:4923
VPBasicBlock * createVPBasicBlock(const Twine &Name, VPRecipeBase *Recipe=nullptr)
Create a new VPBasicBlock with Name and containing Recipe if present.
Definition VPlan.h:5150
VPBasicBlock * getVectorPreheader() const
Returns the preheader of the vector loop region, if one exists, or null otherwise.
Definition VPlan.h:4893
bool hasScalarVFOnly() const
Definition VPlan.h:5035
VPBasicBlock * getScalarPreheader() const
Return the VPBasicBlock for the preheader of the scalar loop.
Definition VPlan.h:4937
bool hasTailFolded() const
Returns true if the vector loop region is tail-folded.
Definition VPlan.h:4909
VPSymbolicValue & getVF()
Returns the VF of the vector loop region.
Definition VPlan.h:4986
bool hasScalarTail() const
Returns true if the scalar tail may execute after the vector loop, i.e.
Definition VPlan.h:5220
VPIRValue * getConstantInt(Type *Ty, uint64_t Val, bool IsSigned=false)
Return a VPIRValue wrapping a ConstantInt with the given type and value.
Definition VPlan.h:5101
LLVM Value Representation.
Definition Value.h:75
iterator_range< user_iterator > users()
Definition Value.h:426
static LLVM_ABI VectorType * get(Type *ElementType, ElementCount EC)
This static method is the primary way to construct an VectorType.
constexpr bool isScalable() const
Returns whether the quantity is scaled by a runtime quantity (vscale).
Definition TypeSize.h:168
constexpr ScalarTy getKnownMinValue() const
Returns the minimum value this quantity can represent.
Definition TypeSize.h:165
self_iterator getIterator()
Definition ilist_node.h:123
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
ap_match< APInt > m_APInt(const APInt *&Res)
Match a ConstantInt or splatted ConstantVector, binding the specified pointer to the contained APInt.
bool match(Val *V, const Pattern &P)
cst_pred_ty< is_one > m_One()
Match an integer 1 or a vector with all elements equal to 1.
VPInstruction_match< VPInstruction::BranchOnTwoConds > m_BranchOnTwoConds()
canonical_widen_iv_match m_CanonicalWidenIV()
VPInstruction_match< VPInstruction::BranchOnCount > m_BranchOnCount()
auto m_VPValue()
Match an arbitrary VPValue and ignore it.
VPRecipeBase * findUserOf(VPValue *V, const MatchT &P)
If V is used by a recipe matching pattern P, return it.
match_bind< VPInstruction > m_VPInstruction(VPInstruction *&V)
Match a VPInstruction, capturing if we match.
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 onlyFirstLaneUsed(const VPValue *Def)
Returns true if only the first lane of Def is used.
VPValue * findIncomingAliasMask(const VPlan &Plan)
Finds the incoming alias-mask within the vector preheader.
bool doesGeneratePerAllLanes(const VPRecipeBase *R)
Returns true if R produces scalar values for all VF lanes.
bool onlyScalarValuesUsed(const VPValue *Def)
Returns true if only scalar values of Def are used by all users.
VPValue * scalarizeVPWidenPointerInduction(VPWidenPointerInductionRecipe *PtrIV, VPlan &Plan, VPBuilder &Builder)
Scalarize a VPWidenPointerInductionRecipe by replacing it with a PtrAdd (IndStart,...
VPScalarIVStepsRecipe * createScalarIVSteps(VPlan &Plan, InductionDescriptor::InductionKind Kind, Instruction::BinaryOps InductionOpcode, FPMathOperator *FPBinOp, Instruction *TruncI, VPIRValue *StartV, VPValue *Step, DebugLoc DL, VPBuilder &Builder, const VPIRFlags::WrapFlagsTy &Flags={})
Create a scalar-iv-steps recipe over Plan's canonical IV for an induction of Kind with InductionOpcod...
This is an optimization pass for GlobalISel generic memory operations.
@ Offset
Definition DWP.cpp:578
decltype(auto) dyn_cast(const From &Val)
dyn_cast<X> - Return the argument parameter cast to the specified type.
Definition Casting.h:643
void append_range(Container &C, Range &&R)
Wrapper function to append range R to container C.
Definition STLExtras.h:2208
iterator_range< early_inc_iterator_impl< detail::IterOfRange< RangeT > > > make_early_inc_range(RangeT &&Range)
Make a range that does early increment to allow mutation of the underlying range without disrupting i...
Definition STLExtras.h:633
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:250
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:285
SmallVector< VPRegisterUsage, 8 > calculateRegisterUsageForPlan(VPlan &Plan, ArrayRef< ElementCount > VFs, const TargetTransformInfo &TTI, const SmallPtrSetImpl< const Value * > &ValuesToIgnore)
Estimate the register usage for Plan and vectorization factors in VFs by calculating the highest numb...
detail::concat_range< ValueT, RangeTs... > concat(RangeTs &&...Ranges)
Returns a concatenated range across two or more ranges.
Definition STLExtras.h:1151
auto dyn_cast_or_null(const Y &Val)
Definition Casting.h:753
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:1753
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
auto drop_end(T &&RangeOrContainer, size_t N=1)
Return a range covering RangeOrContainer with the last N elements excluded.
Definition STLExtras.h:322
TargetTransformInfo TTI
@ Mul
Product of integers.
@ FMul
Product of floats.
@ Add
Sum of integers.
DWARFExpression::Operation Op
auto make_second_range(ContainerTy &&c)
Given a container of pairs, return a range over the second elements.
Definition STLExtras.h:1409
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
RelativeUniformCounterPtr ValuesPtrExpr VTableAddr Next
Definition InstrProf.h:147
constexpr detail::IsaCheckPredicate< Types... > IsaPred
Function object wrapper for the llvm::isa type check.
Definition Casting.h:866
A struct that represents some properties of the register usage of a loop.
SmallMapVector< unsigned, unsigned, 4 > MaxLocalUsers
Holds the maximum number of concurrent live intervals in the loop.
InstructionCost spillCost(const TargetTransformInfo &TTI, TargetTransformInfo::TargetCostKind CostKind, unsigned OverrideMaxNumRegs=0) const
Calculate the estimated cost of any spills due to using more registers than the number available for ...
static VPValue * materializeAliasMask(VPlan &Plan, VPBasicBlock *AliasCheckVPBB, ArrayRef< PointerDiffInfo > DiffChecks)
Materializes within the AliasCheckVPBB block.
static void expandSCEVsToVPInstructions(VPlan &Plan, ScalarEvolution &SE)
Try to expand VPExpandSCEVRecipes in Plan's entry block to VPInstructions.
static void materializeBroadcasts(VPlan &Plan)
Add explicit broadcasts for live-ins and VPValues defined in Plan's entry block if they are used as v...
static void materializePacksAndUnpacks(VPlan &Plan)
Add explicit Build[Struct]Vector recipes to Pack multiple scalar values into vectors and Unpack recip...
static void materializeFactors(VPlan &Plan, VPBasicBlock *VectorPH, ElementCount VF)
Materialize UF, VF and VFxUF to be computed explicitly using VPInstructions.
static void materializeBackedgeTakenCount(VPlan &Plan, VPBasicBlock *VectorPH)
Materialize the backedge-taken count to be computed explicitly using VPInstructions.
static void replaceWideCanonicalIVWithWideIV(VPlan &Plan, ScalarEvolution &SE, const TargetTransformInfo &TTI, TargetTransformInfo::TargetCostKind CostKind, ElementCount VF, unsigned UF, const SmallPtrSetImpl< const Value * > &ValuesToIgnore)
Replace a VPWidenCanonicalIVRecipe if it is present in Plan, with a VPWidenIntOrFpInductionRecipe,...
static void materializeHeaderMask(VPlan &Plan, bool UseActiveLaneMask, bool UseActiveLaneMaskForControlFlow)
Materialize the abstract header mask of the loop region into concrete recipes: an active-lane-mask if...
static void addBranchWeightToMiddleTerminator(VPlan &Plan, ElementCount VF, std::optional< unsigned > VScaleForTuning)
Add branch weight metadata, if the Plan's middle block is terminated by a BranchOnCond recipe.
static void materializeAliasMaskCheckBlock(VPlan &Plan, ArrayRef< PointerDiffInfo > DiffChecks, bool HasBranchWeights)
Materializes the alias mask within a check block before the loop.
static DenseMap< const SCEV *, Value * > expandSCEVs(VPlan &Plan, ScalarEvolution &SE)
Expand remaining VPExpandSCEVRecipes in Plan's entry block using SCEVExpander.
static void convertToConcreteRecipes(VPlan &Plan)
Lower abstract recipes to concrete ones, that can be codegen'd.
static void expandBranchOnTwoConds(VPlan &Plan)
Expand BranchOnTwoConds instructions into explicit CFG with BranchOnCond instructions.
static void materializeVectorTripCount(VPlan &Plan, VPBasicBlock *VectorPHVPBB, bool TailByMasking, bool RequiresScalarEpilogue, VPValue *Step, std::optional< uint64_t > MaxRuntimeStep=std::nullopt)
Materialize vector trip count computations to a set of VPInstructions.
static void materializeConstantVectorTripCount(VPlan &Plan, ElementCount BestVF, unsigned BestUF, PredicatedScalarEvolution &PSE)
static void attachVPCheckBlock(VPlan &Plan, VPValue *Cond, VPBasicBlock *CheckBlock, bool AddBranchWeights)
Wrap runtime check block CheckBlock in a VPIRBB and Cond in a VPValue and connect the block to Plan,...
static void dissolveLoopRegions(VPlan &Plan)
Replace loop regions with explicit CFG.