LLVM 24.0.0git
VPlanUnroll.cpp
Go to the documentation of this file.
1//===-- VPlanUnroll.cpp - VPlan unroller ----------------------------------===//
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 explicit unrolling for VPlans.
11///
12//===----------------------------------------------------------------------===//
13
14#include "VPRecipeBuilder.h"
15#include "VPlan.h"
16#include "VPlanAnalysis.h"
17#include "VPlanCFG.h"
18#include "VPlanHelpers.h"
19#include "VPlanPatternMatch.h"
20#include "VPlanTransforms.h"
21#include "VPlanUtils.h"
23#include "llvm/ADT/STLExtras.h"
24#include "llvm/ADT/ScopeExit.h"
26#include "llvm/IR/Constants.h"
27#include "llvm/IR/Intrinsics.h"
28
29using namespace llvm;
30using namespace llvm::VPlanPatternMatch;
31
32namespace {
33
34/// Helper to hold state needed for unrolling. It holds the Plan to unroll by
35/// UF. It also holds copies of VPValues across UF-1 unroll parts to facilitate
36/// the unrolling transformation, where the original VPValues are retained for
37/// part zero.
38class UnrollState {
39 /// Plan to unroll.
40 VPlan &Plan;
41 /// Unroll factor to unroll by.
42 const unsigned UF;
43
44 /// Unrolling may create recipes that should not be unrolled themselves.
45 /// Those are tracked in ToSkip.
46 SmallPtrSet<VPRecipeBase *, 8> ToSkip;
47
48 // Associate with each VPValue of part 0 its unrolled instances of parts 1,
49 // ..., UF-1.
50 DenseMap<VPValue *, SmallVector<VPValue *>> VPV2Parts;
51
52 /// Unroll replicate region \p VPR by cloning the region UF - 1 times.
53 void unrollReplicateRegionByUF(VPRegionBlock *VPR);
54
55 /// Unroll recipe \p R by cloning it UF - 1 times, unless it is uniform across
56 /// all parts.
57 void unrollRecipeByUF(VPRecipeBase &R);
58
59 /// Unroll header phi recipe \p R. How exactly the recipe gets unrolled
60 /// depends on the concrete header phi. Inserts newly created recipes at \p
61 /// InsertPtForPhi.
62 void unrollHeaderPHIByUF(VPHeaderPHIRecipe *R,
63 VPBasicBlock::iterator InsertPtForPhi);
64
65 /// Unroll a widen induction recipe \p IV. This introduces recipes to compute
66 /// the induction steps for each part.
67 void unrollWidenInductionByUF(VPWidenInductionRecipe *IV,
68 VPBasicBlock::iterator InsertPtForPhi);
69
70 VPValue *getConstantInt(unsigned Part) {
71 Type *CanIVIntTy = Plan.getVectorLoopRegion()->getCanonicalIVType();
72 return Plan.getConstantInt(CanIVIntTy, Part);
73 }
74
75public:
76 UnrollState(VPlan &Plan, unsigned UF) : Plan(Plan), UF(UF) {}
77
78 void unrollBlock(VPBlockBase *VPB);
79
80 VPValue *getValueForPart(VPValue *V, unsigned Part) {
81 if (Part == 0 || isa<VPIRValue, VPSymbolicValue>(V))
82 return V;
83 assert((VPV2Parts.contains(V) && VPV2Parts[V].size() >= Part) &&
84 "accessed value does not exist");
85 return VPV2Parts[V][Part - 1];
86 }
87
88 /// Given a single original recipe \p OrigR (of part zero), and its copy \p
89 /// CopyR for part \p Part, map every VPValue defined by \p OrigR to its
90 /// corresponding VPValue defined by \p CopyR.
91 void addRecipeForPart(VPRecipeBase *OrigR, VPRecipeBase *CopyR,
92 unsigned Part) {
93 for (const auto &[Idx, VPV] : enumerate(OrigR->definedValues())) {
94 const auto &[V, _] = VPV2Parts.try_emplace(VPV);
95 assert(V->second.size() == Part - 1 && "earlier parts not set");
96 V->second.push_back(CopyR->getVPValue(Idx));
97 }
98 }
99
100 /// Given a uniform recipe \p R, add it for all parts.
101 void addUniformForAllParts(VPSingleDefRecipe *R) {
102 const auto &[V, Inserted] = VPV2Parts.try_emplace(R);
103 assert(Inserted && "uniform value already added");
104 for (unsigned Part = 0; Part != UF; ++Part)
105 V->second.push_back(R);
106 }
107
108 bool contains(VPValue *VPV) const { return VPV2Parts.contains(VPV); }
109
110 /// Update \p R's operand at \p OpIdx with its corresponding VPValue for part
111 /// \p P.
112 void remapOperand(VPRecipeBase *R, unsigned OpIdx, unsigned Part) {
113 auto *Op = R->getOperand(OpIdx);
114 R->setOperand(OpIdx, getValueForPart(Op, Part));
115 }
116
117 /// Update \p R's operands with their corresponding VPValues for part \p P.
118 void remapOperands(VPRecipeBase *R, unsigned Part) {
119 for (const auto &[OpIdx, Op] : enumerate(R->operands()))
120 R->setOperand(OpIdx, getValueForPart(Op, Part));
121 }
122};
123} // namespace
124
126 unsigned Part, VPlan &Plan) {
127 if (Part == 0)
128 return;
129
130 VPBuilder Builder(Steps);
131 Type *BaseIVTy = Steps->getOperand(0)->getScalarType();
132 Type *IntStepTy =
133 IntegerType::get(BaseIVTy->getContext(), BaseIVTy->getScalarSizeInBits());
134 VPValue *StartIndex = Steps->getVFValue();
135 if (Part > 1) {
136 StartIndex = Builder.createOverflowingOp(
137 Instruction::Mul,
138 {StartIndex, Plan.getConstantInt(StartIndex->getScalarType(), Part)});
139 }
140 StartIndex = Builder.createScalarSExtOrTrunc(StartIndex, IntStepTy,
141 Steps->getDebugLoc());
142
143 if (BaseIVTy->isFloatingPointTy())
144 StartIndex = Builder.createScalarCast(Instruction::SIToFP, StartIndex,
145 BaseIVTy, Steps->getDebugLoc());
146
147 Steps->setStartIndex(StartIndex);
148}
149
150void UnrollState::unrollReplicateRegionByUF(VPRegionBlock *VPR) {
151 VPBlockBase *InsertPt = VPR->getSingleSuccessor();
152 for (unsigned Part = 1; Part != UF; ++Part) {
153 auto *Copy = VPR->clone();
154 VPBlockUtils::insertBlockBefore(Copy, InsertPt);
155
156 auto PartI = vp_depth_first_shallow(Copy->getEntry());
157 auto Part0 = vp_depth_first_shallow(VPR->getEntry());
158 for (const auto &[PartIVPBB, Part0VPBB] :
161 for (const auto &[PartIR, Part0R] : zip(*PartIVPBB, *Part0VPBB)) {
162 remapOperands(&PartIR, Part);
163 if (auto *Steps = dyn_cast<VPScalarIVStepsRecipe>(&PartIR))
164 addStartIndexForScalarSteps(Steps, Part, Plan);
165
166 addRecipeForPart(&Part0R, &PartIR, Part);
167 }
168 }
169 }
170}
171
172void UnrollState::unrollWidenInductionByUF(
173 VPWidenInductionRecipe *IV, VPBasicBlock::iterator InsertPtForPhi) {
174 VPBasicBlock *PH = cast<VPBasicBlock>(
175 IV->getParent()->getEnclosingLoopRegion()->getSinglePredecessor());
176 Type *IVTy = IV->getScalarType();
177 auto &ID = IV->getInductionDescriptor();
178 FastMathFlags FMF;
179 VPIRFlags::WrapFlagsTy WrapFlags(false, false);
180 if (auto *IntOrFPInd = dyn_cast<VPWidenIntOrFpInductionRecipe>(IV)) {
181 FMF = IntOrFPInd->getFastMathFlagsOrNone();
182 WrapFlags = IntOrFPInd->getNoWrapFlagsOrNone();
183 }
184
185 VPValue *ScalarStep = IV->getStepValue();
186 VPBuilder Builder(PH);
187 Type *VectorStepTy = IVTy->isPointerTy() ? ScalarStep->getScalarType() : IVTy;
188 VPInstruction *VectorStep = Builder.createNaryOp(
189 VPInstruction::WideIVStep, {&Plan.getVF(), ScalarStep}, VectorStepTy, FMF,
190 IV->getDebugLoc());
191
192 ToSkip.insert(VectorStep);
193
194 // Now create recipes to compute the induction steps for part 1 .. UF. Part 0
195 // remains the header phi. Parts > 0 are computed by adding Step to the
196 // previous part. The header phi recipe will get 2 new operands: the step
197 // value for a single part and the last part, used to compute the backedge
198 // value during VPWidenInductionRecipe::execute.
199 // %Part.0 = VPWidenInductionRecipe %Start, %ScalarStep, %VectorStep, %Part.3
200 // %Part.1 = %Part.0 + %VectorStep
201 // %Part.2 = %Part.1 + %VectorStep
202 // %Part.3 = %Part.2 + %VectorStep
203 //
204 // The newly added recipes are added to ToSkip to avoid interleaving them
205 // again.
206 VPValue *Prev = IV;
207 Builder.setInsertPoint(IV->getParent(), InsertPtForPhi);
208 unsigned AddOpc;
209 VPIRFlags AddFlags;
210 if (IVTy->isPointerTy()) {
212 AddFlags = GEPNoWrapFlags::none();
213 } else if (IVTy->isFloatingPointTy()) {
214 AddOpc = ID.getInductionOpcode();
215 AddFlags = FMF;
216 } else {
217 AddOpc = Instruction::Add;
218 AddFlags = WrapFlags;
220 AddFlags = VPIRFlags::WrapFlagsTy(/*NUW=*/true, /*NSW=*/false);
221 }
222 for (unsigned Part = 1; Part != UF; ++Part) {
223 std::string Name =
224 Part > 1 ? "step.add." + std::to_string(Part) : "step.add";
225
226 VPInstruction *Add =
227 Builder.createNaryOp(AddOpc,
228 {
229 Prev,
230 VectorStep,
231 },
232 AddFlags, IV->getDebugLoc(), Name);
233 ToSkip.insert(Add);
234 addRecipeForPart(IV, Add, Part);
235 Prev = Add;
236 }
237 IV->addUnrolledPartOperands(VectorStep, Prev);
238}
239
240void UnrollState::unrollHeaderPHIByUF(VPHeaderPHIRecipe *R,
241 VPBasicBlock::iterator InsertPtForPhi) {
242 // First-order recurrences pass a single vector or scalar through their header
243 // phis, irrespective of interleaving.
245 return;
246
247 // Generate step vectors for each unrolled part.
248 if (auto *IV = dyn_cast<VPWidenInductionRecipe>(R)) {
249 unrollWidenInductionByUF(IV, InsertPtForPhi);
250 return;
251 }
252
253 auto *RdxPhi = dyn_cast<VPReductionPHIRecipe>(R);
254 if (RdxPhi && RdxPhi->isOrdered())
255 return;
256
257 auto InsertPt = std::next(R->getIterator());
258 for (unsigned Part = 1; Part != UF; ++Part) {
259 VPRecipeBase *Copy = R->clone();
260 Copy->insertBefore(*R->getParent(), InsertPt);
261 addRecipeForPart(R, Copy, Part);
262 if (RdxPhi) {
263 // If the start value is a ReductionStartVector, use the identity value
264 // (second operand) for unrolled parts. If the scaling factor is > 1,
265 // create a new ReductionStartVector with the scale factor and both
266 // operands set to the identity value.
267 if (auto *VPI = dyn_cast<VPInstruction>(RdxPhi->getStartValue())) {
268 assert(VPI->getOpcode() == VPInstruction::ReductionStartVector &&
269 "unexpected start VPInstruction");
270 if (Part != 1)
271 continue;
272 VPValue *StartV;
273 if (match(VPI->getOperand(2), m_One())) {
274 StartV = VPI->getOperand(1);
275 } else {
276 auto *C = VPI->clone();
277 C->setOperand(0, C->getOperand(1));
278 C->insertAfter(VPI);
279 StartV = C;
280 }
281 for (unsigned Part = 1; Part != UF; ++Part)
282 VPV2Parts[VPI][Part - 1] = StartV;
283 }
284 } else {
286 "unexpected header phi recipe not needing unrolled part");
287 }
288 }
289}
290
291/// Handle non-header-phi recipes.
292void UnrollState::unrollRecipeByUF(VPRecipeBase &R) {
294 return;
295
296 if (auto *VPI = dyn_cast<VPInstruction>(&R)) {
298 addUniformForAllParts(VPI);
299 return;
300 }
301 }
302 if (auto *RepR = dyn_cast<VPReplicateRecipe>(&R)) {
303 if (isa<StoreInst>(RepR->getUnderlyingValue()) &&
304 RepR->getOperand(1)->isDefinedOutsideLoopRegions()) {
305 // Stores to an invariant address only need to store the last part.
306 remapOperands(&R, UF - 1);
307 return;
308 }
309 if (match(RepR,
311 addUniformForAllParts(RepR);
312 return;
313 }
314 }
315
316 // Unroll non-uniform recipes.
317 auto InsertPt = std::next(R.getIterator());
318 VPBasicBlock &VPBB = *R.getParent();
319 for (unsigned Part = 1; Part != UF; ++Part) {
320 VPRecipeBase *Copy = R.clone();
321 Copy->insertBefore(VPBB, InsertPt);
322 addRecipeForPart(&R, Copy, Part);
323
324 // Phi operands are updated once all other recipes have been unrolled.
325 if (isa<VPWidenPHIRecipe>(Copy))
326 continue;
327
328 VPValue *Op;
330 m_VPValue(), m_VPValue(Op)))) {
331 Copy->setOperand(0, getValueForPart(Op, Part - 1));
332 Copy->setOperand(1, getValueForPart(Op, Part));
333 continue;
334 }
336 m_VPValue(Op), m_VPValue()))) {
337 Copy->setOperand(0, Op);
338 Copy->setOperand(1, Plan.getConstantInt(64, Part));
339 continue;
340 }
342 VPBuilder Builder(&R);
343 const DataLayout &DL = Plan.getDataLayout();
344 Type *IndexTy =
347 : DL.getIndexType(R.getVPSingleValue()->getScalarType());
348 VPValue *VF = Builder.createScalarZExtOrTrunc(&Plan.getVF(), IndexTy,
350 // VFxUF does not wrap, so VF * Part also cannot wrap.
351 VPValue *VFxPart = Builder.createOverflowingOp(
352 Instruction::Mul, {VF, Plan.getConstantInt(IndexTy, Part)},
353 {true, true});
354 if (auto *VecPtr = dyn_cast<VPVectorPointerRecipe>(Copy))
355 VecPtr->addPerPartOffset(VFxPart);
356 else
357 cast<VPWidenCanonicalIVRecipe>(Copy)->addPerPartStep(VFxPart);
358 continue;
359 }
360 if (auto *Red = dyn_cast<VPReductionRecipe>(&R)) {
361 auto *Phi = dyn_cast<VPReductionPHIRecipe>(R.getOperand(0));
362 if (Phi && Phi->isOrdered()) {
363 auto &Parts = VPV2Parts[Phi];
364 if (Part == 1) {
365 Parts.clear();
366 Parts.push_back(Red);
367 }
368 Parts.push_back(Copy->getVPSingleValue());
369 Phi->setOperand(1, Copy->getVPSingleValue());
370 }
371 }
372 if (auto *VEPR = dyn_cast<VPVectorEndPointerRecipe>(Copy)) {
373 // Materialize PartN offset for VectorEndPointer.
374 VEPR->setOperand(0, R.getOperand(0));
375 VEPR->setOperand(1, R.getOperand(1));
376 VEPR->materializeOffset(Part);
377 continue;
378 }
379
380 remapOperands(Copy, Part);
381
382 if (auto *ScalarIVSteps = dyn_cast<VPScalarIVStepsRecipe>(Copy))
383 addStartIndexForScalarSteps(ScalarIVSteps, Part, Plan);
384
385 if (match(Copy,
387 VPBuilder Builder(Copy);
388 VPValue *ScaledByPart = Builder.createOverflowingOp(
389 Instruction::Mul, {Copy->getOperand(1), getConstantInt(Part)});
390 Copy->setOperand(1, ScaledByPart);
391 }
392 }
393 if (auto *VEPR = dyn_cast<VPVectorEndPointerRecipe>(&R)) {
394 // Materialize Part0 offset for VectorEndPointer.
395 VEPR->materializeOffset();
396 }
397 if (auto *WideCanIV = dyn_cast<VPWidenCanonicalIVRecipe>(&R)) {
398 // Set Part0 step for WidenCanonicalIV.
399 WideCanIV->addPerPartStep(getConstantInt(0));
400 }
401}
402
403void UnrollState::unrollBlock(VPBlockBase *VPB) {
404 auto *VPR = dyn_cast<VPRegionBlock>(VPB);
405 if (VPR) {
406 if (VPR->isReplicator())
407 return unrollReplicateRegionByUF(VPR);
408
409 // Traverse blocks in region in RPO to ensure defs are visited before uses
410 // across blocks.
411 ReversePostOrderTraversal<VPBlockShallowTraversalWrapper<VPBlockBase *>>
412 RPOT(VPR->getEntry());
413 for (VPBlockBase *VPB : RPOT)
414 unrollBlock(VPB);
415 return;
416 }
417
418 // VPB is a VPBasicBlock; unroll it, i.e., unroll its recipes.
419 auto *VPBB = cast<VPBasicBlock>(VPB);
420 auto InsertPtForPhi = VPBB->getFirstNonPhi();
421 for (VPRecipeBase &R : make_early_inc_range(*VPBB)) {
422 if (ToSkip.contains(&R) || isa<VPIRInstruction>(&R))
423 continue;
424
425 // Add all VPValues for all parts to AnyOf, FirstActiveLaneMask and
426 // ComputeReductionResult which combine all parts to compute the final
427 // value.
428 VPValue *Op1;
430 match(&R, m_FirstActiveLane(m_VPValue(Op1))) ||
431 match(&R, m_LastActiveLane(m_VPValue(Op1))) ||
433 auto *VPI = cast<VPInstruction>(&R);
434 addUniformForAllParts(VPI);
435 for (unsigned Part = 1; Part != UF; ++Part)
436 VPI->addOperand(getValueForPart(Op1, Part));
437 continue;
438 }
439 VPValue *Op0;
440 if (match(&R, m_ExtractLane(m_VPValue(Op0), m_VPValue(Op1)))) {
441 auto *VPI = cast<VPInstruction>(&R);
442 addUniformForAllParts(VPI);
443 for (unsigned Part = 1; Part != UF; ++Part)
444 VPI->addOperand(getValueForPart(Op1, Part));
445 continue;
446 }
447
448 VPValue *Op2;
450 m_VPValue(Op2)))) {
451 auto *VPI = cast<VPInstruction>(&R);
452 addUniformForAllParts(VPI);
453 for (unsigned Part = 1; Part != UF; ++Part) {
454 VPI->addOperand(getValueForPart(Op1, Part));
455 VPI->addOperand(getValueForPart(Op2, Part));
456 }
457 continue;
458 }
459
460 if (Plan.hasScalarVFOnly()) {
461 if (match(&R, m_ExtractLastPart(m_VPValue(Op0))) ||
463 auto *I = cast<VPInstruction>(&R);
464 bool IsPenultimatePart =
466 unsigned PartIdx = IsPenultimatePart ? UF - 2 : UF - 1;
467 // For scalar VF, directly use the scalar part value.
468 I->replaceAllUsesWith(getValueForPart(Op0, PartIdx));
469 continue;
470 }
471 }
472 // For vector VF, the penultimate element is always extracted from the last part.
475 addUniformForAllParts(cast<VPSingleDefRecipe>(&R));
476 R.setOperand(0, getValueForPart(Op0, UF - 1));
477 continue;
478 }
479
480 if (match(&R,
482 auto *ALM = cast<VPInstruction>(&R);
483 ALM->setOperand(2, getConstantInt(UF));
484 continue;
485 }
486
487 auto *SingleDef = dyn_cast<VPSingleDefRecipe>(&R);
488 if (SingleDef && vputils::isUniformAcrossVFsAndUFs(SingleDef)) {
489 addUniformForAllParts(SingleDef);
490 continue;
491 }
492
493 if (auto *H = dyn_cast<VPHeaderPHIRecipe>(&R)) {
494 unrollHeaderPHIByUF(H, InsertPtForPhi);
495 continue;
496 }
497
498 unrollRecipeByUF(R);
499 }
500}
501
502void VPlanTransforms::unrollByUF(VPlan &Plan, unsigned UF) {
503 assert(UF > 0 && "Unroll factor must be positive");
504 Plan.setUF(UF);
505 llvm::scope_exit Cleanup([&Plan, UF]() {
506 auto Iter = vp_depth_first_deep(Plan.getEntry());
507 // Remove recipes that are redundant after unrolling.
509 for (VPRecipeBase &R : make_early_inc_range(*VPBB)) {
510 auto *VPI = dyn_cast<VPInstruction>(&R);
511 if (VPI &&
512 VPI->getOpcode() == VPInstruction::CanonicalIVIncrementForPart &&
513 VPI->getOperand(1) == &Plan.getVF()) {
514 VPI->replaceAllUsesWith(VPI->getOperand(0));
515 VPI->eraseFromParent();
516 }
517 }
518 }
519
520 Type *TCTy = Plan.getTripCount()->getScalarType();
521 Plan.getUF().replaceAllUsesWith(Plan.getConstantInt(TCTy, UF));
522 });
523 if (UF == 1) {
524 return;
525 }
526
527 UnrollState Unroller(Plan, UF);
528
529 // Iterate over all blocks in the plan starting from Entry, and unroll
530 // recipes inside them. This includes the vector preheader and middle blocks,
531 // which may set up or post-process per-part values.
533 Plan.getEntry());
534 for (VPBlockBase *VPB : RPOT)
535 Unroller.unrollBlock(VPB);
536
537 unsigned Part = 1;
538 // Remap operands of cloned header phis to update backedge values. The header
539 // phis cloned during unrolling are just after the header phi for part 0.
540 // Reset Part to 1 when reaching the first (part 0) recipe of a block.
541 for (VPRecipeBase &H :
543 // The second operand of Fixed Order Recurrence phi's, feeding the spliced
544 // value across the backedge, needs to remap to the last part of the spliced
545 // value.
547 Unroller.remapOperand(&H, 1, UF - 1);
548 continue;
549 }
550 if (Unroller.contains(H.getVPSingleValue())) {
551 Part = 1;
552 continue;
553 }
554 Unroller.remapOperands(&H, Part);
555 Part++;
556 }
557
559}
560
561/// Add a lane offset to the start index of \p Steps.
562static void addLaneToStartIndex(VPScalarIVStepsRecipe *Steps, unsigned Lane,
563 VPlan &Plan, VPRecipeBase *InsertPt) {
564 assert(Lane > 0 && "Zero lane adds no offset to start index");
565 Type *BaseIVTy = Steps->getOperand(0)->getScalarType();
566
567 VPValue *OldStartIndex = Steps->getStartIndex();
568 VPValue *LaneOffset;
569 unsigned AddOpcode;
570 // TODO: Retrieve the flags from Steps unconditionally.
571 VPIRFlags Flags;
572 if (BaseIVTy->isFloatingPointTy()) {
573 int SignedLane = static_cast<int>(Lane);
574 if (!OldStartIndex && Steps->getInductionOpcode() == Instruction::FSub)
575 SignedLane = -SignedLane;
576 LaneOffset = Plan.getOrAddLiveIn(ConstantFP::get(BaseIVTy, SignedLane));
577 AddOpcode = Steps->getInductionOpcode();
578 Flags = VPIRFlags(FastMathFlags());
579 } else {
580 unsigned BaseIVBits = BaseIVTy->getScalarSizeInBits();
581 LaneOffset = Plan.getConstantInt(
582 APInt(BaseIVBits, Lane, /*isSigned*/ false, /*implicitTrunc*/ true));
583 AddOpcode = Instruction::Add;
584 Flags = VPIRFlags(VPIRFlags::WrapFlagsTy(false, false));
585 }
586
587 VPValue *NewStartIndex = LaneOffset;
588 if (OldStartIndex) {
589 VPBuilder Builder(InsertPt);
590 NewStartIndex =
591 Builder.createNaryOp(AddOpcode, {OldStartIndex, LaneOffset}, Flags);
592 }
593 Steps->setStartIndex(NewStartIndex);
594}
595
596/// Create a single-scalar clone of \p DefR (must be a VPReplicateRecipe,
597/// VPInstruction or VPScalarIVStepsRecipe) for lane \p Lane. Use \p
598/// Def2LaneDefs to look up scalar definitions for operands of \DefR.
599static VPValue *
600cloneForLane(VPlan &Plan, VPBuilder &Builder, Type *IdxTy,
601 VPSingleDefRecipe *DefR, VPLane Lane,
602 const DenseMap<VPValue *, SmallVector<VPValue *>> &Def2LaneDefs) {
604 "DefR must be a VPReplicateRecipe, VPInstruction or "
605 "VPScalarIVStepsRecipe");
606 VPValue *Op;
608 auto LaneDefs = Def2LaneDefs.find(Op);
609 if (LaneDefs != Def2LaneDefs.end())
610 return LaneDefs->second[Lane.getKnownLane()];
611
612 VPValue *Idx = Plan.getConstantInt(IdxTy, Lane.getKnownLane());
613 return Builder.createNaryOp(Instruction::ExtractElement, {Op, Idx});
614 }
615
616 // Collect the operands at Lane, creating extracts as needed.
618 for (VPValue *Op : DefR->operands()) {
619 // If Op is a definition that has been unrolled, directly use the clone for
620 // the corresponding lane.
621 auto LaneDefs = Def2LaneDefs.find(Op);
622 if (LaneDefs != Def2LaneDefs.end()) {
623 NewOps.push_back(LaneDefs->second[Lane.getKnownLane()]);
624 continue;
625 }
626 if (Lane.getKind() == VPLane::Kind::ScalableLast) {
627 // Look through mandatory Unpack.
628 [[maybe_unused]] bool Matched =
630 assert(Matched && "original op must have been Unpack");
631 auto *ExtractPart =
632 Builder.createNaryOp(VPInstruction::ExtractLastPart, {Op});
633 NewOps.push_back(
634 Builder.createNaryOp(VPInstruction::ExtractLastLane, {ExtractPart}));
635 continue;
636 }
638 NewOps.push_back(Op);
639 continue;
640 }
641
642 // Look through buildvector to avoid unnecessary extracts.
643 if (match(Op, m_BuildVector())) {
644 NewOps.push_back(
645 cast<VPInstruction>(Op)->getOperand(Lane.getKnownLane()));
646 continue;
647 }
648 VPValue *Idx = Plan.getConstantInt(IdxTy, Lane.getKnownLane());
649 VPValue *Ext = Builder.createNaryOp(Instruction::ExtractElement, {Op, Idx});
650 NewOps.push_back(Ext);
651 }
652
654 if (auto *RepR = dyn_cast<VPReplicateRecipe>(DefR)) {
655 // TODO: have cloning of replicate recipes also provide the desired result
656 // coupled with setting its operands to NewOps (deriving IsSingleScalar and
657 // Mask from the operands?)
659 RepR->getOpcode(), NewOps, /*Mask=*/nullptr, *RepR, *RepR,
660 RepR->getDebugLoc(), RepR->getUnderlyingInstr());
661 } else {
662 New = DefR->clone();
663 for (const auto &[Idx, Op] : enumerate(NewOps)) {
664 New->setOperand(Idx, Op);
665 }
666 if (auto *Steps = dyn_cast<VPScalarIVStepsRecipe>(New)) {
667 // Skip lane 0: an absent start index is implicitly zero.
668 unsigned KnownLane = Lane.getKnownLane();
669 if (KnownLane != 0)
670 addLaneToStartIndex(Steps, KnownLane, Plan, DefR);
671 }
672 }
673 New->insertBefore(DefR);
674 return New;
675}
676
677/// Convert recipes in region blocks to operate on a single lane 0.
678/// VPReplicateRecipes are converted to single-scalar ones, branch-on-mask is
679/// converted into BranchOnCond, PredInstPhi recipes are replaced by scalar phi
680/// recipes with an additional poison operand, and extracts are created as
681/// needed.
683 VPBlockBase *Entry,
684 ElementCount VF) {
685 VPValue *Idx0 = Plan.getZero(IdxTy);
686 for (VPBlockBase *VPB : vp_depth_first_shallow(Entry)) {
688 assert(
689 !isa<VPWidenPHIRecipe>(&OldR) &&
690 !match(&OldR,
694 "must not contain wide phis, inserts or extracts before conversion");
695
696 VPBuilder Builder(&OldR);
697 DebugLoc OldDL = OldR.getDebugLoc();
698 // For scalar VF, operands are already scalar; no extraction needed.
699 if (!VF.isScalar()) {
700 for (const auto &[I, Op] : enumerate(OldR.operands())) {
701 // Skip operands that don't need extraction: values defined in the
702 // same block (already scalar), or values that are already single
703 // scalars.
704 // TODO: Support isSingleScalar for VPScalarIVStepsRecipe.
705 auto *DefR = Op->getDefiningRecipe();
707 DefR->getParent() == VPB) ||
709 continue;
710
711 // Extract lane zero from values defined outside the region.
712 VPValue *Extract = Builder.createNaryOp(Instruction::ExtractElement,
713 {Op, Idx0}, OldDL);
714 OldR.setOperand(I, Extract);
715 }
716 }
717
718 if (auto *RepR = dyn_cast<VPReplicateRecipe>(&OldR)) {
720 RepR->getOpcode(), to_vector(RepR->operands()), /*Mask=*/nullptr,
721 *RepR, *RepR, OldDL, RepR->getUnderlyingInstr());
722 NewR->insertBefore(RepR);
723 RepR->replaceAllUsesWith(NewR);
724 RepR->eraseFromParent();
725 } else if (auto *BranchOnMask = dyn_cast<VPBranchOnMaskRecipe>(&OldR)) {
726 Builder.createNaryOp(VPInstruction::BranchOnCond,
727 {BranchOnMask->getOperand(0)}, OldDL);
728 BranchOnMask->eraseFromParent();
729 } else if (auto *PredPhi = dyn_cast<VPPredInstPHIRecipe>(&OldR)) {
730 VPValue *PredOp = PredPhi->getOperand(0);
731 Type *PredTy = PredOp->getScalarType();
732 VPValue *Poison = Plan.getPoison(PredTy);
733 VPPhi *NewPhi = Builder.createScalarPhi({Poison, PredOp}, OldDL);
734 PredPhi->replaceAllUsesWith(NewPhi);
735 PredPhi->eraseFromParent();
736 } else {
737 // TODO: Support isSingleScalar for VPScalarIVStepsRecipe.
739 (isa<VPInstruction>(OldR) &&
740 vputils::isSingleScalar(OldR.getVPSingleValue()))) &&
741 "unexpected unhandled recipe");
742 }
743 }
744 }
745}
746
747/// Update recipes in the cloned blocks rooted at \p NewEntry to match \p Lane,
748/// using the original blocks rooted at \p OldEntry as reference.
749static void processLaneForReplicateRegion(VPlan &Plan, Type *IdxTy,
750 unsigned Lane, VPBasicBlock *OldEntry,
751 VPBasicBlock *NewEntry) {
752 DenseMap<VPValue *, VPValue *> Old2NewVPValues;
753 VPValue *IdxLane = Plan.getConstantInt(IdxTy, Lane);
754 for (const auto &[OldBB, NewBB] :
756 vp_depth_first_shallow(NewEntry))) {
757 for (auto &&[OldR, NewR] :
759 for (const auto &[OldV, NewV] :
760 zip_equal(OldR.definedValues(), NewR.definedValues()))
761 Old2NewVPValues[OldV] = NewV;
762
763 // Remap operands to use lane-specific values.
764 for (const auto &[I, OldOp] : enumerate(NewR.operands())) {
765 // Use cloned value if operand was defined in the region.
766 if (auto *NewOp = Old2NewVPValues.lookup(OldOp))
767 NewR.setOperand(I, NewOp);
768 }
769
770 if (auto *Steps = dyn_cast<VPScalarIVStepsRecipe>(&NewR)) {
771 addLaneToStartIndex(Steps, Lane, Plan, Steps);
772 } else if (match(&NewR, m_ExtractElement(m_VPValue(), m_VPValue()))) {
773 assert(match(NewR.getOperand(1), m_ZeroInt()) &&
774 "extract indices must be zero");
775 NewR.setOperand(1, IdxLane);
776 } else if (auto *NewPhi = dyn_cast<VPPhi>(&NewR)) {
777 auto *OldPhi = cast<VPPhi>(&OldR);
779 "VPPhis expected to have only first lane used");
780 auto *BVUser = dyn_cast_or_null<VPInstruction>(OldPhi->getSingleUser());
781 if (BVUser && match(BVUser, m_CombineOr(m_BuildVector(),
783 assert(BVUser->getOperand(0) == OldPhi &&
784 "Unexpected first operand of build vector user");
785 BVUser->setOperand(Lane, NewPhi);
786 }
787 }
788 }
789 }
790}
791
792/// Dissolve a single replicate region by replicating its blocks for each lane
793/// of \p VF. The region is disconnected, its blocks are reparented, cloned for
794/// each lane, and reconnected in sequence.
796 VPlan &Plan, Type *IdxTy) {
797 auto *FirstLaneEntry = cast<VPBasicBlock>(Region->getEntry());
798 auto *FirstLaneExiting = cast<VPBasicBlock>(Region->getExiting());
799
800 // Disconnect and dissolve the region.
801 VPBlockBase *Predecessor = Region->getSinglePredecessor();
802 assert(Predecessor && "Replicate region must have a single predecessor");
803 auto *Successor = cast<VPBasicBlock>(Region->getSingleSuccessor());
806
807 VPRegionBlock *ParentRegion = Region->getParent();
808 for (VPBlockBase *VPB : vp_depth_first_shallow(FirstLaneEntry))
809 VPB->setParent(ParentRegion);
810
811 // Process the original blocks for lane 0: converting their recipes to
812 // single-scalar.
813 convertRecipesInRegionBlocksToSingleScalar(Plan, IdxTy, FirstLaneEntry, VF);
814
815 // For scalar VF, just wire the blocks and return; no cloning or packing
816 // needed.
817 if (VF.isScalar()) {
818 VPBlockUtils::connectBlocks(Predecessor, FirstLaneEntry);
819 VPBlockUtils::connectBlocks(FirstLaneExiting, Successor);
820 return;
821 }
822
823 // Create a BuildVector or BuildStructVector in successor block for every
824 // VPPhi in (first lane's) exiting block having vector uses. All their
825 // operands are initialized to poison and will be replaced when processing
826 // each clone, except for the operand of the first lane which set here.
827 // BuildVectors are recorded to be replaced later by chains of insert-element
828 // and widen phi's.
829 unsigned NumLanes = VF.getFixedValue();
830 SmallVector<VPInstruction *> BuildVectors;
831 for (auto &R : FirstLaneExiting->phis()) {
832 auto *Phi = cast<VPPhi>(&R);
834 continue;
835
836 Type *ScalarTy = Phi->getScalarType();
837 bool IsStruct = isa<StructType>(ScalarTy);
838 VPValue *Poison = Plan.getPoison(ScalarTy);
839 SmallVector<VPValue *> BVOps(NumLanes, Poison);
840 auto *BV = new VPInstruction(IsStruct ? VPInstruction::BuildStructVector
842 BVOps);
843 if (!IsStruct)
844 BuildVectors.push_back(BV);
845 Phi->replaceAllUsesWith(BV);
846 BV->setOperand(0, Phi);
847 BV->insertBefore(*Successor, Successor->getFirstNonPhi());
848 }
849
850 // Clone converted blocks for remaining lanes and process each in reverse
851 // order, connecting each lane's Exiting block to the subsequent lane's entry.
852 VPBlockBase *NextLaneEntry = Successor;
853 for (int Lane = NumLanes - 1; Lane > 0; --Lane) {
854 const auto &[CurrentLaneEntry, CurrentLaneExiting] =
855 VPBlockUtils::cloneFrom(FirstLaneEntry);
856 for (VPBlockBase *VPB : vp_depth_first_shallow(CurrentLaneEntry))
857 VPB->setParent(ParentRegion);
858 processLaneForReplicateRegion(Plan, IdxTy, Lane,
859 cast<VPBasicBlock>(FirstLaneEntry),
860 cast<VPBasicBlock>(CurrentLaneEntry));
861 VPBlockUtils::connectBlocks(CurrentLaneExiting, NextLaneEntry);
862 NextLaneEntry = CurrentLaneEntry;
863 }
864
865 // Connect Predecessor to FirstLaneEntry, and FirstLaneRegionExit to
866 // NextLaneEntry which is the second lane region entry. The latter is
867 // done last so that earlier clonings from FirstLaneEntry stop at
868 // FirstLaneExiting.
869 VPBlockUtils::connectBlocks(Predecessor, FirstLaneEntry);
870 VPBlockUtils::connectBlocks(FirstLaneExiting, NextLaneEntry);
871
872 // Fold BuildVector fed by scalar phis into VPWidenPHIRecipes with
873 // InsertElement per lane.
874 // TODO: check if this folding should be dropped.
875 for (VPInstruction *BV : BuildVectors) {
876 assert(BV->getNumOperands() == NumLanes &&
877 "BuildVector must have one operand per lane");
878 for (const auto &[Idx, Op] : enumerate(BV->operands())) {
879 auto *ScalarPhi = cast<VPPhi>(Op);
880 auto DL = ScalarPhi->getDebugLoc();
881 auto *PredOp = cast<VPSingleDefRecipe>(ScalarPhi->getOperand(1));
882 VPValue *Poison = ScalarPhi->getOperand(0);
883 VPValue *PrevVal = Idx == 0 ? Poison : BV->getOperand(Idx - 1);
884 auto Builder = VPBuilder::getToInsertAfter(PredOp->getDefiningRecipe());
885 auto *Insert = Builder.createNaryOp(
886 Instruction::InsertElement,
887 {PrevVal, PredOp, Plan.getConstantInt(64, Idx)}, DL);
888 Builder.setInsertPoint(ScalarPhi);
889 auto *NewPhi = Builder.createWidenPhi({PrevVal, Insert}, DL);
890 ScalarPhi->replaceAllUsesWith(NewPhi);
891 ScalarPhi->eraseFromParent();
892 }
893 BV->replaceAllUsesWith(BV->getOperand(NumLanes - 1));
894 BV->eraseFromParent();
895 }
896}
897
898/// Collect and dissolve all replicate regions in the vector loop, replicating
899/// their blocks and recipes for each lane of \p VF.
901 Type *IdxTy) {
902 // Collect all replicate regions before modifying the CFG.
903 SmallVector<VPRegionBlock *> ReplicateRegions;
906 if (Region->isReplicator())
907 ReplicateRegions.push_back(Region);
908 }
909
910 assert((ReplicateRegions.empty() || !VF.isScalable()) &&
911 "cannot replicate across scalable VFs");
912
913 // Dissolve replicate regions by replicating their blocks for each lane.
914 // Traversing regions in reverse ensures that the successor of every region
915 // being processed is a basic-block, rather than another region.
916 for (VPRegionBlock *Region : reverse(ReplicateRegions))
917 dissolveReplicateRegion(Region, VF, Plan, IdxTy);
918
920}
921
923 Type *IdxTy = IntegerType::get(
925
926 if (Plan.hasScalarVFOnly()) {
927 // When Plan is only unrolled by UF, replicating by VF amounts to dissolving
928 // replicate regions.
929 replicateReplicateRegionsByVF(Plan, VF, IdxTy);
930 return;
931 }
932
933 // Visit all VPBBs outside the loop region and directly inside the top-level
934 // loop region.
935 auto VPBBsOutsideLoopRegion = VPBlockUtils::blocksOnly<VPBasicBlock>(
937 auto VPBBsInsideLoopRegion = VPBlockUtils::blocksOnly<VPBasicBlock>(
939 auto VPBBsToUnroll =
940 concat<VPBasicBlock *>(VPBBsOutsideLoopRegion, VPBBsInsideLoopRegion);
941 // A mapping of current VPValue definitions to collections of new VPValues
942 // defined per lane. Serves to hook-up potential users of current VPValue
943 // definition that are replicated-per-VF later.
945 // The removal of current recipes being replaced by new ones needs to be
946 // delayed after Def2LaneDefs is no longer in use.
948 for (VPBasicBlock *VPBB : VPBBsToUnroll) {
949 for (VPRecipeBase &R : make_early_inc_range(*VPBB)) {
951 continue;
952
953 auto *DefR = cast<VPSingleDefRecipe>(&R);
954 VPBuilder Builder(DefR);
955 if (DefR->user_empty()) {
956 // Create single-scalar version of DefR for all lanes.
957 for (unsigned I = 0; I != VF.getKnownMinValue(); ++I)
958 cloneForLane(Plan, Builder, IdxTy, DefR, VPLane(I), Def2LaneDefs);
959 DefR->eraseFromParent();
960 continue;
961 }
962 /// Create single-scalar version of DefR for all lanes.
963 SmallVector<VPValue *> LaneDefs;
964 for (unsigned I = 0; I != VF.getKnownMinValue(); ++I)
965 LaneDefs.push_back(
966 cloneForLane(Plan, Builder, IdxTy, DefR, VPLane(I), Def2LaneDefs));
967
968 Def2LaneDefs[DefR] = LaneDefs;
969 /// Users that only demand the first lane can use the definition for lane
970 /// 0.
971 DefR->replaceUsesWithIf(LaneDefs[0], [DefR](VPUser &U, unsigned) {
972 if (U.usesFirstLaneOnly(DefR))
973 return true;
974 auto *VPI = dyn_cast<VPInstructionWithType>(&U);
975 return VPI && Instruction::isCast(VPI->getOpcode());
976 });
977
978 // Update each build vector user that currently has DefR as its only
979 // operand, to have all LaneDefs as its operands.
980 for (VPUser *U : to_vector(DefR->users())) {
981 auto *VPI = dyn_cast<VPInstruction>(U);
982 if (!VPI || (VPI->getOpcode() != VPInstruction::BuildVector &&
983 VPI->getOpcode() != VPInstruction::BuildStructVector))
984 continue;
985 assert(VPI->getNumOperands() == 1 &&
986 "Build(Struct)Vector must have a single operand before "
987 "replicating by VF");
988 VPI->setOperand(0, LaneDefs[0]);
989 for (VPValue *LaneDef : drop_begin(LaneDefs))
990 VPI->addOperand(LaneDef);
991 }
992 ToRemove.push_back(DefR);
993 }
994 }
995 for (auto *R : reverse(ToRemove))
996 R->eraseFromParent();
997
998 replicateReplicateRegionsByVF(Plan, VF, IdxTy);
999}
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
ReachingDefInfo InstSet & ToRemove
MachineBasicBlock MachineBasicBlock::iterator DebugLoc DL
static GCRegistry::Add< ShadowStackGC > C("shadow-stack", "Very portable GC for uncooperative code generators")
This file contains the declarations for the subclasses of Constant, which represent the different fla...
static bool isCanonical(const MDString *S)
ManagedStatic< HTTPClientCleanup > Cleanup
#define _
#define I(x, y, z)
Definition MD5.cpp:57
#define H(x, y, z)
Definition MD5.cpp:56
This file builds on the ADT/GraphTraits.h file to build a generic graph post order iterator.
This file contains some templates that are useful if you are working with the STL at all.
static bool contains(SmallPtrSetImpl< ConstantExpr * > &Cache, ConstantExpr *Expr, Constant *C)
Definition Value.cpp:484
This file defines the scope_exit class, which executes user-defined cleanup logic at scope exit.
static ConstantInt * getConstantInt(Value *V, const DataLayout &DL)
Extract ConstantInt from value, looking through IntToPtr and PointerNullValue.
This file contains the declarations of different VPlan-related auxiliary helpers.
This file provides utility VPlan to VPlan transformations.
static void addLaneToStartIndex(VPScalarIVStepsRecipe *Steps, unsigned Lane, VPlan &Plan, VPRecipeBase *InsertPt)
Add a lane offset to the start index of Steps.
static void replicateReplicateRegionsByVF(VPlan &Plan, ElementCount VF, Type *IdxTy)
Collect and dissolve all replicate regions in the vector loop, replicating their blocks and recipes f...
static VPValue * cloneForLane(VPlan &Plan, VPBuilder &Builder, Type *IdxTy, VPSingleDefRecipe *DefR, VPLane Lane, const DenseMap< VPValue *, SmallVector< VPValue * > > &Def2LaneDefs)
Create a single-scalar clone of DefR (must be a VPReplicateRecipe, VPInstruction or VPScalarIVStepsRe...
static void addStartIndexForScalarSteps(VPScalarIVStepsRecipe *Steps, unsigned Part, VPlan &Plan)
static void convertRecipesInRegionBlocksToSingleScalar(VPlan &Plan, Type *IdxTy, VPBlockBase *Entry, ElementCount VF)
Convert recipes in region blocks to operate on a single lane 0.
static void dissolveReplicateRegion(VPRegionBlock *Region, ElementCount VF, VPlan &Plan, Type *IdxTy)
Dissolve a single replicate region by replicating its blocks for each lane of VF.
static void processLaneForReplicateRegion(VPlan &Plan, Type *IdxTy, unsigned Lane, VPBasicBlock *OldEntry, VPBasicBlock *NewEntry)
Update recipes in the cloned blocks rooted at NewEntry to match Lane, using the original blocks roote...
static void remapOperands(VPBlockBase *Entry, VPBlockBase *NewEntry, DenseMap< VPValue *, VPValue * > &Old2NewVPValues)
Definition VPlan.cpp:1202
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 LLVMContext & getContext() const
Get the context in which this basic block lives.
A debug info location.
Definition DebugLoc.h:126
static DebugLoc getUnknown()
Definition DebugLoc.h:153
ValueT lookup(const_arg_type_t< KeyT > Val) const
Return the entry for the specified key, or a default constructed value if no such entry exists.
Definition DenseMap.h:250
constexpr bool isScalar() const
Exactly one element.
Definition TypeSize.h:320
Convenience struct for specifying and reasoning about fast-math flags.
Definition FMF.h:23
static GEPNoWrapFlags none()
bool isCast() const
static LLVM_ABI IntegerType * get(LLVMContext &C, unsigned NumBits)
This static method is the primary way of constructing an IntegerType.
Definition Type.cpp:348
RegionT * getParent() const
Get the parent of the Region.
Definition RegionInfo.h:362
BlockT * getEntry() const
Get the entry BasicBlock of the Region.
Definition RegionInfo.h:320
std::pair< iterator, bool > insert(PtrType Ptr)
Inserts Ptr if and only if there is no element in the container equal to Ptr.
bool contains(ConstPtrType Ptr) const
void push_back(const T &Elt)
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
The instances of the Type class are immutable: once they are created, they are never changed.
Definition Type.h:46
bool isPointerTy() const
True if this is an instance of PointerType.
Definition Type.h:282
LLVMContext & getContext() const
Return the LLVMContext in which this type was uniqued.
Definition Type.h:130
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
bool isFloatingPointTy() const
Return true if this is one of the floating-point types.
Definition Type.h:186
VPBasicBlock serves as the leaf of the Hierarchical Control-Flow Graph.
Definition VPlan.h:4389
RecipeListTy::iterator iterator
Instruction iterators...
Definition VPlan.h:4416
iterator_range< iterator > phis()
Returns an iterator range over the PHI-like recipes in the block.
Definition VPlan.h:4477
iterator getFirstNonPhi()
Return the position of the first non-phi node recipe in the block.
Definition VPlan.cpp:266
VPBlockBase is the building block of the Hierarchical Control-Flow Graph.
Definition VPlan.h:94
const VPBasicBlock * getEntryBasicBlock() const
Definition VPlan.cpp:216
void setParent(VPRegionBlock *P)
Definition VPlan.h:203
VPBlockBase * getSingleSuccessor() const
Definition VPlan.h:233
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 void insertBlockBefore(VPBlockBase *NewBlock, VPBlockBase *BlockPtr)
Insert disconnected block NewBlock before Blockptr.
Definition VPlanUtils.h:294
static auto blocksOnly(T &&Range)
Return an iterator range over Range which only includes BlockTy blocks.
Definition VPlanUtils.h:384
static std::pair< VPBlockBase *, VPBlockBase * > cloneFrom(VPBlockBase *Entry)
Clone the CFG for all nodes reachable from Entry, including cloning the blocks and their recipes.
Definition VPlan.cpp:712
VPlan-based builder utility analogous to IRBuilder.
static VPBuilder getToInsertAfter(VPRecipeBase *R)
Create a VPBuilder to insert after R.
static VPSingleDefRecipe * createSingleScalarOp(unsigned Opcode, ArrayRef< VPValue * > Operands, VPValue *Mask, const VPIRFlags &Flags, const VPIRMetadata &Metadata, DebugLoc DL, Instruction *UV)
Create a single-scalar recipe with Opcode and Operands without inserting it.
VPValue * getVPValue(unsigned I)
Returns the VPValue with index I defined by the VPDef.
Definition VPlanValue.h:563
ArrayRef< VPRecipeValue * > definedValues()
Returns an ArrayRef of the values defined by the VPDef.
Definition VPlanValue.h:573
BasicBlock * getIRBasicBlock() const
Definition VPlan.h:4566
Class to record and manage LLVM IR flags.
Definition VPlan.h:704
This is a concrete Recipe that models a single VPlan-level instruction.
Definition VPlan.h:1234
@ WideIVStep
Scale the first operand (vector step) by the second operand (scalar-step).
Definition VPlan.h:1361
@ ReductionStartVector
Start vector for reductions with 3 operands: the original start value, the identity value for the red...
Definition VPlan.h:1332
@ BuildVector
Creates a fixed-width vector containing all operands.
Definition VPlan.h:1281
@ BuildStructVector
Given operands of (the same) struct type, creates a struct of fixed- width vectors each containing a ...
Definition VPlan.h:1278
@ CanonicalIVIncrementForPart
Definition VPlan.h:1262
In what follows, the term "input IR" refers to code that is fed into the vectorizer whereas the term ...
Kind getKind() const
Returns the Kind of lane offset.
unsigned getKnownLane() const
Returns a compile-time known value for the lane index and asserts if the lane can only be calculated ...
@ ScalableLast
For ScalableLast, Lane is the offset from the start of the last N-element subvector in a scalable vec...
VPRecipeBase is a base class modeling a sequence of one or more output IR instructions.
Definition VPlan.h:411
DebugLoc getDebugLoc() const
Returns the debug location of the recipe.
Definition VPlan.h:561
VPRegionBlock represents a collection of VPBasicBlocks and VPRegionBlocks which form a Single-Entry-S...
Definition VPlan.h:4614
VPRegionBlock * clone() override
Clone all blocks in the single-entry single-exit region of the block and their recipes without updati...
Definition VPlan.cpp:769
const VPBlockBase * getEntry() const
Definition VPlan.h:4658
bool isReplicator() const
An indicator whether this region is to generate multiple replicated instances of output IR correspond...
Definition VPlan.h:4690
Type * getCanonicalIVType() const
Return the type of the canonical IV for loop regions.
Definition VPlan.h:4742
A recipe for handling phi nodes of integer and floating-point inductions, producing their scalar valu...
Definition VPlan.h:4244
Instruction::BinaryOps getInductionOpcode() const
Definition VPlan.h:4305
void setStartIndex(VPValue *StartIndex)
Set or add the StartIndex operand.
Definition VPlan.h:4288
VPValue * getStartIndex() const
Return the StartIndex, or null if known to be zero, valid only after unrolling.
Definition VPlan.h:4283
VPValue * getVFValue() const
Return the number of scalars to produce per unroll part, used to compute StartIndex during unrolling.
Definition VPlan.h:4279
VPSingleDefRecipe is a base class for recipes that model a sequence of one or more output IR that def...
Definition VPlan.h:619
VPSingleDefRecipe * clone() override=0
Clone the current recipe.
This class augments VPValue with operands which provide the inverse def-use edges from VPValue's user...
Definition VPlanValue.h:401
operand_range operands()
Definition VPlanValue.h:474
VPValue * getOperand(unsigned N) const
Definition VPlanValue.h:442
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
void replaceAllUsesWith(VPValue *New)
Definition VPlan.cpp:1495
VPlan models a candidate for vectorization, encoding various decisions take to produce efficient outp...
Definition VPlan.h:4801
const DataLayout & getDataLayout() const
Definition VPlan.h:5008
VPBasicBlock * getEntry()
Definition VPlan.h:4897
VPValue * getTripCount() const
The trip count of the original loop.
Definition VPlan.h:4962
VPIRValue * getPoison(Type *Ty)
Return a VPIRValue wrapping a poison value of type Ty.
Definition VPlan.h:5127
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:5076
VPIRValue * getZero(Type *Ty)
Return a VPIRValue wrapping the null value of type Ty.
Definition VPlan.h:5102
LLVM_ABI_FOR_TEST VPRegionBlock * getVectorLoopRegion()
Returns the VPRegionBlock of the vector loop.
Definition VPlan.cpp:1080
VPSymbolicValue & getUF()
Returns the UF of the vector loop region.
Definition VPlan.h:4999
bool hasScalarVFOnly() const
Definition VPlan.h:5044
VPIRBasicBlock * getScalarHeader() const
Return the VPIRBasicBlock wrapping the header of the scalar loop.
Definition VPlan.h:4952
VPSymbolicValue & getVF()
Returns the VF of the vector loop region.
Definition VPlan.h:4995
void setUF(unsigned UF)
Definition VPlan.h:5059
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:5110
constexpr ScalarTy getFixedValue() const
Definition TypeSize.h:200
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
SpecificConstantMatch m_ZeroInt()
Convenience matchers for specific integer values.
match_combine_or< Ty... > m_CombineOr(const Ty &...Ps)
Combine pattern matchers matching any of Ps patterns.
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.
auto m_Intrinsic(const Ts &...Ops)
Match intrinsic calls like this: m_Intrinsic<Intrinsic::fabs>(m_Value(X))
VPInstruction_match< VPInstruction::ExtractLastLane, VPInstruction_match< VPInstruction::ExtractLastPart, Op0_t > > m_ExtractLastLaneOfLastPart(const Op0_t &Op0)
VPInstruction_match< VPInstruction::ComputeReductionResult, Op0_t > m_ComputeReductionResult(const Op0_t &Op0)
VPInstruction_match< VPInstruction::WideActiveLaneMask, Op0_t, Op1_t, Op2_t > m_WideActiveLaneMask(const Op0_t &Op0, const Op1_t &Op1, const Op2_t &Op2)
VPInstruction_match< Instruction::InsertElement, Op0_t, Op1_t, Op2_t > m_InsertElement(const Op0_t &Op0, const Op1_t &Op1, const Op2_t &Op2)
VPInstruction_match< VPInstruction::LastActiveLane, Op0_t > m_LastActiveLane(const Op0_t &Op0)
VPInstruction_match< VPInstruction::ExtractLastActive, Op0_t, Op1_t, Op2_t > m_ExtractLastActive(const Op0_t &Op0, const Op1_t &Op1, const Op2_t &Op2)
VPInstruction_match< Instruction::ExtractElement, Op0_t, Op1_t > m_ExtractElement(const Op0_t &Op0, const Op1_t &Op1)
VPInstruction_match< VPInstruction::BranchOnCount > m_BranchOnCount()
auto m_VPValue()
Match an arbitrary VPValue and ignore it.
VPInstruction_match< VPInstruction::ExtractLastPart, Op0_t > m_ExtractLastPart(const Op0_t &Op0)
VPInstruction_match< VPInstruction::BuildVector > m_BuildVector()
BuildVector is matches only its opcode, w/o matching its operands as the number of operands is not fi...
VPInstruction_match< VPInstruction::ExtractPenultimateElement, Op0_t > m_ExtractPenultimateElement(const Op0_t &Op0)
match_bind< VPInstruction > m_VPInstruction(VPInstruction *&V)
Match a VPInstruction, capturing if we match.
VPInstruction_match< VPInstruction::FirstActiveLane, Op0_t > m_FirstActiveLane(const Op0_t &Op0)
VPInstruction_match< VPInstruction::BranchOnCond > m_BranchOnCond()
VPInstruction_match< VPInstruction::ExtractLane, Op0_t, Op1_t > m_ExtractLane(const Op0_t &Op0, const Op1_t &Op1)
VPInstruction_match< VPInstruction::BuildStructVector > m_BuildStructVector()
BuildStructVector matches only its opcode, w/o matching its operands as the number of operands is not...
NodeAddr< PhiNode * > Phi
Definition RDFGraph.h:390
bool isSingleScalar(const VPValue *VPV)
Returns true if VPV is a single scalar, either because it produces the same value for all lanes or on...
bool onlyFirstPartUsed(const VPValue *Def)
Returns true if only the first part of Def is used.
bool onlyFirstLaneUsed(const VPValue *Def)
Returns true if only the first lane of Def is used.
bool doesGeneratePerAllLanes(const VPRecipeBase *R)
Returns true if R produces scalar values for all VF lanes.
bool isUniformAcrossVFsAndUFs(const VPValue *V)
Checks if V is uniform across all VF lanes and UF parts.
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
detail::zippy< detail::zip_shortest, T, U, Args... > zip(T &&t, U &&u, Args &&...args)
zip iterator for two or more iteratable types.
Definition STLExtras.h:830
detail::zippy< detail::zip_first, T, U, Args... > zip_equal(T &&t, U &&u, Args &&...args)
zip iterator that assumes that all iteratees have the same length.
Definition STLExtras.h:840
auto enumerate(FirstRange &&First, RestRanges &&...Rest)
Given two or more input ranges, returns a new range whose values are tuples (A, B,...
Definition STLExtras.h:2554
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< 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
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
auto reverse(ContainerTy &&C)
Definition STLExtras.h:407
bool isa_and_present(const Y &Val)
isa_and_present<X> - Functionally identical to isa, except that a null value is accepted.
Definition Casting.h:669
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
@ Add
Sum of integers.
DWARFExpression::Operation Op
decltype(auto) cast(const From &Val)
cast<X> - Return the argument parameter cast to the specified type.
Definition Casting.h:559
static void unrollByUF(VPlan &Plan, unsigned UF)
Explicitly unroll Plan by UF.
static bool mergeBlocksIntoPredecessors(VPlan &Plan)
Remove redundant VPBasicBlocks by merging them into their single predecessor if the latter has a sing...
static void removeDeadRecipes(VPlan &Plan)
Remove dead recipes from Plan.
static void replicateByVF(VPlan &Plan, ElementCount VF)
Replace replicating VPReplicateRecipe, VPScalarIVStepsRecipe and VPInstruction in Plan with VF single...