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#include "llvm/IR/MDBuilder.h"
29#include <numeric>
30
31using namespace llvm;
32using namespace llvm::VPlanPatternMatch;
33
34namespace {
35
36/// Helper to hold state needed for unrolling. It holds the Plan to unroll by
37/// UF. It also holds copies of VPValues across UF-1 unroll parts to facilitate
38/// the unrolling transformation, where the original VPValues are retained for
39/// part zero.
40class UnrollState {
41 /// Plan to unroll.
42 VPlan &Plan;
43 /// Unroll factor to unroll by.
44 const unsigned UF;
45
46 /// Unrolling may create recipes that should not be unrolled themselves.
47 /// Those are tracked in ToSkip.
48 SmallPtrSet<VPRecipeBase *, 8> ToSkip;
49
50 // Associate with each VPValue of part 0 its unrolled instances of parts 1,
51 // ..., UF-1.
52 DenseMap<VPValue *, SmallVector<VPValue *>> VPV2Parts;
53
54 /// Unroll replicate region \p VPR by cloning the region UF - 1 times.
55 void unrollReplicateRegionByUF(VPRegionBlock *VPR);
56
57 /// Unroll recipe \p R by cloning it UF - 1 times, unless it is uniform across
58 /// all parts.
59 void unrollRecipeByUF(VPRecipeBase &R);
60
61 /// Unroll header phi recipe \p R. How exactly the recipe gets unrolled
62 /// depends on the concrete header phi. Inserts newly created recipes at \p
63 /// InsertPtForPhi.
64 void unrollHeaderPHIByUF(VPHeaderPHIRecipe *R,
65 VPBasicBlock::iterator InsertPtForPhi);
66
67 /// Unroll a widen induction recipe \p IV. This introduces recipes to compute
68 /// the induction steps for each part.
69 void unrollWidenInductionByUF(VPWidenInductionRecipe *IV,
70 VPBasicBlock::iterator InsertPtForPhi);
71
72 VPValue *getConstantInt(unsigned Part) {
73 Type *CanIVIntTy = Plan.getVectorLoopRegion()->getCanonicalIVType();
74 return Plan.getConstantInt(CanIVIntTy, Part);
75 }
76
77public:
78 UnrollState(VPlan &Plan, unsigned UF) : Plan(Plan), UF(UF) {}
79
80 void unrollBlock(VPBlockBase *VPB);
81
82 VPValue *getValueForPart(VPValue *V, unsigned Part) {
83 if (Part == 0 || isa<VPIRValue, VPSymbolicValue>(V))
84 return V;
85 assert((VPV2Parts.contains(V) && VPV2Parts[V].size() >= Part) &&
86 "accessed value does not exist");
87 return VPV2Parts[V][Part - 1];
88 }
89
90 /// Given a single original recipe \p OrigR (of part zero), and its copy \p
91 /// CopyR for part \p Part, map every VPValue defined by \p OrigR to its
92 /// corresponding VPValue defined by \p CopyR.
93 void addRecipeForPart(VPRecipeBase *OrigR, VPRecipeBase *CopyR,
94 unsigned Part) {
95 for (const auto &[Idx, VPV] : enumerate(OrigR->definedValues())) {
96 const auto &[V, _] = VPV2Parts.try_emplace(VPV);
97 assert(V->second.size() == Part - 1 && "earlier parts not set");
98 V->second.push_back(CopyR->getVPValue(Idx));
99 }
100 }
101
102 /// Given a uniform recipe \p R, add it for all parts.
103 void addUniformForAllParts(VPSingleDefRecipe *R) {
104 const auto &[V, Inserted] = VPV2Parts.try_emplace(R);
105 assert(Inserted && "uniform value already added");
106 for (unsigned Part = 0; Part != UF; ++Part)
107 V->second.push_back(R);
108 }
109
110 bool contains(VPValue *VPV) const { return VPV2Parts.contains(VPV); }
111
112 /// Update \p R's operand at \p OpIdx with its corresponding VPValue for part
113 /// \p P.
114 void remapOperand(VPRecipeBase *R, unsigned OpIdx, unsigned Part) {
115 auto *Op = R->getOperand(OpIdx);
116 R->setOperand(OpIdx, getValueForPart(Op, Part));
117 }
118
119 /// Update \p R's operands with their corresponding VPValues for part \p P.
120 void remapOperands(VPRecipeBase *R, unsigned Part) {
121 for (const auto &[OpIdx, Op] : enumerate(R->operands()))
122 R->setOperand(OpIdx, getValueForPart(Op, Part));
123 }
124};
125} // namespace
126
128 unsigned Part, VPlan &Plan) {
129 if (Part == 0)
130 return;
131
132 VPBuilder Builder(Steps);
133 Type *BaseIVTy = Steps->getOperand(0)->getScalarType();
134 Type *IntStepTy =
135 IntegerType::get(BaseIVTy->getContext(), BaseIVTy->getScalarSizeInBits());
136 VPValue *StartIndex = Steps->getVFValue();
137 if (Part > 1) {
138 StartIndex = Builder.createOverflowingOp(
139 Instruction::Mul,
140 {StartIndex, Plan.getConstantInt(StartIndex->getScalarType(), Part)});
141 }
142 StartIndex = Builder.createScalarSExtOrTrunc(StartIndex, IntStepTy,
143 Steps->getDebugLoc());
144
145 if (BaseIVTy->isFloatingPointTy())
146 StartIndex = Builder.createScalarCast(Instruction::SIToFP, StartIndex,
147 BaseIVTy, Steps->getDebugLoc());
148
149 Steps->setStartIndex(StartIndex);
150}
151
152void UnrollState::unrollReplicateRegionByUF(VPRegionBlock *VPR) {
153 VPBlockBase *InsertPt = VPR->getSingleSuccessor();
154 for (unsigned Part = 1; Part != UF; ++Part) {
155 auto *Copy = VPR->clone();
156 VPBlockUtils::insertBlockBefore(Copy, InsertPt);
157
158 auto PartI = vp_depth_first_shallow(Copy->getEntry());
159 auto Part0 = vp_depth_first_shallow(VPR->getEntry());
160 for (const auto &[PartIVPBB, Part0VPBB] :
163 for (const auto &[PartIR, Part0R] : zip(*PartIVPBB, *Part0VPBB)) {
164 remapOperands(&PartIR, Part);
165 if (auto *Steps = dyn_cast<VPScalarIVStepsRecipe>(&PartIR))
166 addStartIndexForScalarSteps(Steps, Part, Plan);
167
168 addRecipeForPart(&Part0R, &PartIR, Part);
169 }
170 }
171 }
172}
173
174void UnrollState::unrollWidenInductionByUF(
175 VPWidenInductionRecipe *IV, VPBasicBlock::iterator InsertPtForPhi) {
176 VPBasicBlock *PH = cast<VPBasicBlock>(
177 IV->getParent()->getEnclosingLoopRegion()->getSinglePredecessor());
178 Type *IVTy = IV->getScalarType();
179 auto &ID = IV->getInductionDescriptor();
180 FastMathFlags FMF;
181 VPIRFlags::WrapFlagsTy WrapFlags(false, false);
182 if (auto *IntOrFPInd = dyn_cast<VPWidenIntOrFpInductionRecipe>(IV)) {
183 FMF = IntOrFPInd->getFastMathFlagsOrNone();
184 WrapFlags = IntOrFPInd->getNoWrapFlagsOrNone();
185 }
186
187 VPValue *ScalarStep = IV->getStepValue();
188 VPBuilder Builder(PH);
189 Type *VectorStepTy = IVTy->isPointerTy() ? ScalarStep->getScalarType() : IVTy;
190 VPInstruction *VectorStep = Builder.createNaryOp(
191 VPInstruction::WideIVStep, {&Plan.getVF(), ScalarStep}, VectorStepTy, FMF,
192 IV->getDebugLoc());
193
194 ToSkip.insert(VectorStep);
195
196 // Now create recipes to compute the induction steps for part 1 .. UF. Part 0
197 // remains the header phi. Parts > 0 are computed by adding Step to the
198 // previous part. The header phi recipe will get 2 new operands: the step
199 // value for a single part and the last part, used to compute the backedge
200 // value during VPWidenInductionRecipe::execute.
201 // %Part.0 = VPWidenInductionRecipe %Start, %ScalarStep, %VectorStep, %Part.3
202 // %Part.1 = %Part.0 + %VectorStep
203 // %Part.2 = %Part.1 + %VectorStep
204 // %Part.3 = %Part.2 + %VectorStep
205 //
206 // The newly added recipes are added to ToSkip to avoid interleaving them
207 // again.
208 VPValue *Prev = IV;
209 Builder.setInsertPoint(IV->getParent(), InsertPtForPhi);
210 unsigned AddOpc;
211 VPIRFlags AddFlags;
212 if (IVTy->isPointerTy()) {
214 AddFlags = GEPNoWrapFlags::none();
215 } else if (IVTy->isFloatingPointTy()) {
216 AddOpc = ID.getInductionOpcode();
217 AddFlags = FMF;
218 } else {
219 AddOpc = Instruction::Add;
220 AddFlags = WrapFlags;
222 AddFlags = VPIRFlags::WrapFlagsTy(/*NUW=*/true, /*NSW=*/false);
223 }
224 for (unsigned Part = 1; Part != UF; ++Part) {
225 std::string Name =
226 Part > 1 ? "step.add." + std::to_string(Part) : "step.add";
227
228 VPInstruction *Add =
229 Builder.createNaryOp(AddOpc,
230 {
231 Prev,
232 VectorStep,
233 },
234 AddFlags, IV->getDebugLoc(), Name);
235 ToSkip.insert(Add);
236 addRecipeForPart(IV, Add, Part);
237 Prev = Add;
238 }
239 IV->addUnrolledPartOperands(VectorStep, Prev);
240}
241
242void UnrollState::unrollHeaderPHIByUF(VPHeaderPHIRecipe *R,
243 VPBasicBlock::iterator InsertPtForPhi) {
244 // First-order recurrences pass a single vector or scalar through their header
245 // phis, irrespective of interleaving.
247 return;
248
249 // Generate step vectors for each unrolled part.
250 if (auto *IV = dyn_cast<VPWidenInductionRecipe>(R)) {
251 unrollWidenInductionByUF(IV, InsertPtForPhi);
252 return;
253 }
254
255 auto *RdxPhi = dyn_cast<VPReductionPHIRecipe>(R);
256 if (RdxPhi && RdxPhi->isOrdered())
257 return;
258
259 auto InsertPt = std::next(R->getIterator());
260 for (unsigned Part = 1; Part != UF; ++Part) {
261 VPRecipeBase *Copy = R->clone();
262 Copy->insertBefore(*R->getParent(), InsertPt);
263 addRecipeForPart(R, Copy, Part);
264 if (RdxPhi) {
265 // If the start value is a ReductionStartVector, use the identity value
266 // (second operand) for unrolled parts. If the scaling factor is > 1,
267 // create a new ReductionStartVector with the scale factor and both
268 // operands set to the identity value.
269 if (auto *VPI = dyn_cast<VPInstruction>(RdxPhi->getStartValue())) {
270 assert(VPI->getOpcode() == VPInstruction::ReductionStartVector &&
271 "unexpected start VPInstruction");
272 if (Part != 1)
273 continue;
274 VPValue *StartV;
275 if (match(VPI->getOperand(2), m_One())) {
276 StartV = VPI->getOperand(1);
277 } else {
278 auto *C = VPI->clone();
279 C->setOperand(0, C->getOperand(1));
280 C->insertAfter(VPI);
281 StartV = C;
282 }
283 for (unsigned Part = 1; Part != UF; ++Part)
284 VPV2Parts[VPI][Part - 1] = StartV;
285 }
286 } else {
288 "unexpected header phi recipe not needing unrolled part");
289 }
290 }
291}
292
293/// Handle non-header-phi recipes.
294void UnrollState::unrollRecipeByUF(VPRecipeBase &R) {
296 return;
297
298 if (auto *VPI = dyn_cast<VPInstruction>(&R)) {
300 addUniformForAllParts(VPI);
301 return;
302 }
303 }
304 if (auto *RepR = dyn_cast<VPReplicateRecipe>(&R)) {
305 if (isa<StoreInst>(RepR->getUnderlyingValue()) &&
306 RepR->getOperand(1)->isDefinedOutsideLoopRegions()) {
307 // Stores to an invariant address only need to store the last part.
308 remapOperands(&R, UF - 1);
309 return;
310 }
311 if (match(RepR,
313 addUniformForAllParts(RepR);
314 return;
315 }
316 }
317
318 // Unroll non-uniform recipes.
319 auto InsertPt = std::next(R.getIterator());
320 VPBasicBlock &VPBB = *R.getParent();
321 for (unsigned Part = 1; Part != UF; ++Part) {
322 VPRecipeBase *Copy = R.clone();
323 Copy->insertBefore(VPBB, InsertPt);
324 addRecipeForPart(&R, Copy, Part);
325
326 // Phi operands are updated once all other recipes have been unrolled.
327 if (isa<VPWidenPHIRecipe>(Copy))
328 continue;
329
330 VPValue *Op;
332 m_VPValue(), m_VPValue(Op)))) {
333 Copy->setOperand(0, getValueForPart(Op, Part - 1));
334 Copy->setOperand(1, getValueForPart(Op, Part));
335 continue;
336 }
338 m_VPValue(Op), m_VPValue()))) {
339 Copy->setOperand(0, Op);
340 Copy->setOperand(1, Plan.getConstantInt(64, Part));
341 continue;
342 }
344 VPBuilder Builder(&R);
345 const DataLayout &DL = Plan.getDataLayout();
346 Type *IndexTy =
349 : DL.getIndexType(R.getVPSingleValue()->getScalarType());
350 VPValue *VF = Builder.createScalarZExtOrTrunc(&Plan.getVF(), IndexTy,
352 // VFxUF does not wrap, so VF * Part also cannot wrap.
353 VPValue *VFxPart = Builder.createOverflowingOp(
354 Instruction::Mul, {VF, Plan.getConstantInt(IndexTy, Part)},
355 {true, true});
356 if (auto *VecPtr = dyn_cast<VPVectorPointerRecipe>(Copy))
357 VecPtr->addPerPartOffset(VFxPart);
358 else
359 cast<VPWidenCanonicalIVRecipe>(Copy)->addPerPartStep(VFxPart);
360 continue;
361 }
362 if (auto *Red = dyn_cast<VPReductionRecipe>(&R)) {
363 auto *Phi = dyn_cast<VPReductionPHIRecipe>(R.getOperand(0));
364 if (Phi && Phi->isOrdered()) {
365 auto &Parts = VPV2Parts[Phi];
366 if (Part == 1) {
367 Parts.clear();
368 Parts.push_back(Red);
369 }
370 Parts.push_back(Copy->getVPSingleValue());
371 Phi->setOperand(1, Copy->getVPSingleValue());
372 }
373 }
374 if (auto *VEPR = dyn_cast<VPVectorEndPointerRecipe>(Copy)) {
375 // Materialize PartN offset for VectorEndPointer.
376 VEPR->setOperand(0, R.getOperand(0));
377 VEPR->setOperand(1, R.getOperand(1));
378 VEPR->materializeOffset(Part);
379 continue;
380 }
381
382 remapOperands(Copy, Part);
383
384 if (auto *ScalarIVSteps = dyn_cast<VPScalarIVStepsRecipe>(Copy))
385 addStartIndexForScalarSteps(ScalarIVSteps, Part, Plan);
386
387 if (match(Copy,
389 VPBuilder Builder(Copy);
390 VPValue *ScaledByPart = Builder.createOverflowingOp(
391 Instruction::Mul, {Copy->getOperand(1), getConstantInt(Part)});
392 Copy->setOperand(1, ScaledByPart);
393 }
394 }
395 if (auto *VEPR = dyn_cast<VPVectorEndPointerRecipe>(&R)) {
396 // Materialize Part0 offset for VectorEndPointer.
397 VEPR->materializeOffset();
398 }
399 if (auto *WideCanIV = dyn_cast<VPWidenCanonicalIVRecipe>(&R)) {
400 // Set Part0 step for WidenCanonicalIV.
401 WideCanIV->addPerPartStep(getConstantInt(0));
402 }
403}
404
405void UnrollState::unrollBlock(VPBlockBase *VPB) {
406 auto *VPR = dyn_cast<VPRegionBlock>(VPB);
407 if (VPR) {
408 if (VPR->isReplicator())
409 return unrollReplicateRegionByUF(VPR);
410
411 // Traverse blocks in region in RPO to ensure defs are visited before uses
412 // across blocks.
413 ReversePostOrderTraversal<VPBlockShallowTraversalWrapper<VPBlockBase *>>
414 RPOT(VPR->getEntry());
415 for (VPBlockBase *VPB : RPOT)
416 unrollBlock(VPB);
417 return;
418 }
419
420 // VPB is a VPBasicBlock; unroll it, i.e., unroll its recipes.
421 auto *VPBB = cast<VPBasicBlock>(VPB);
422 auto InsertPtForPhi = VPBB->getFirstNonPhi();
423 for (VPRecipeBase &R : make_early_inc_range(*VPBB)) {
424 if (ToSkip.contains(&R) || isa<VPIRInstruction>(&R))
425 continue;
426
427 // Add all VPValues for all parts to AnyOf, FirstActiveLaneMask and
428 // ComputeReductionResult which combine all parts to compute the final
429 // value.
430 VPValue *Op1;
432 match(&R,
434 match(&R, m_FirstActiveLane(m_VPValue(Op1))) ||
435 match(&R, m_LastActiveLane(m_VPValue(Op1))) ||
437 auto *VPI = cast<VPInstruction>(&R);
438 addUniformForAllParts(VPI);
439 for (unsigned Part = 1; Part != UF; ++Part)
440 VPI->addOperand(getValueForPart(Op1, Part));
441 continue;
442 }
443 VPValue *Op0;
444 if (match(&R, m_ExtractLane(m_VPValue(Op0), m_VPValue(Op1)))) {
445 auto *VPI = cast<VPInstruction>(&R);
446 addUniformForAllParts(VPI);
447 for (unsigned Part = 1; Part != UF; ++Part)
448 VPI->addOperand(getValueForPart(Op1, Part));
449 continue;
450 }
451
452 VPValue *Op2;
454 m_VPValue(Op2)))) {
455 auto *VPI = cast<VPInstruction>(&R);
456 addUniformForAllParts(VPI);
457 for (unsigned Part = 1; Part != UF; ++Part) {
458 VPI->addOperand(getValueForPart(Op1, Part));
459 VPI->addOperand(getValueForPart(Op2, Part));
460 }
461 continue;
462 }
463
464 if (Plan.hasScalarVFOnly()) {
465 if (match(&R, m_ExtractLastPart(m_VPValue(Op0))) ||
467 auto *I = cast<VPInstruction>(&R);
468 bool IsPenultimatePart =
470 unsigned PartIdx = IsPenultimatePart ? UF - 2 : UF - 1;
471 // For scalar VF, directly use the scalar part value.
472 I->replaceAllUsesWith(getValueForPart(Op0, PartIdx));
473 continue;
474 }
475 }
476 // For vector VF, the penultimate element is always extracted from the last part.
479 addUniformForAllParts(cast<VPSingleDefRecipe>(&R));
480 R.setOperand(0, getValueForPart(Op0, UF - 1));
481 continue;
482 }
483
484 if (match(&R,
486 auto *ALM = cast<VPInstruction>(&R);
487 ALM->setOperand(2, getConstantInt(UF));
488 continue;
489 }
490
491 if (match(&R,
494 cast<VPInstruction>(&R)->setOperand(0, Plan.getConstantInt(64, UF));
495 continue;
496 }
497
498 auto *SingleDef = dyn_cast<VPSingleDefRecipe>(&R);
499 if (SingleDef && vputils::isUniformAcrossVFsAndUFs(SingleDef)) {
500 addUniformForAllParts(SingleDef);
501 continue;
502 }
503
504 if (auto *H = dyn_cast<VPHeaderPHIRecipe>(&R)) {
505 unrollHeaderPHIByUF(H, InsertPtForPhi);
506 continue;
507 }
508
509 unrollRecipeByUF(R);
510 }
511}
512
513void VPlanTransforms::unrollByUF(VPlan &Plan, unsigned UF) {
514 assert(UF > 0 && "Unroll factor must be positive");
515 Plan.setUF(UF);
516 llvm::scope_exit Cleanup([&Plan, UF]() {
517 auto Iter = vp_depth_first_deep(Plan.getEntry());
518 // Remove recipes that are redundant after unrolling.
520 for (VPInstruction &VPI :
522 if (VPI.getOpcode() == VPInstruction::CanonicalIVIncrementForPart &&
523 VPI.getOperand(1) == &Plan.getVF()) {
524 VPI.replaceAllUsesWith(VPI.getOperand(0));
525 VPI.eraseFromParent();
526 }
527 }
528 }
529
530 Type *TCTy = Plan.getTripCount()->getScalarType();
531 Plan.getUF().replaceAllUsesWith(Plan.getConstantInt(TCTy, UF));
532 });
533 if (UF == 1) {
534 return;
535 }
536
537 UnrollState Unroller(Plan, UF);
538
539 // Iterate over all blocks in the plan starting from Entry, and unroll
540 // recipes inside them. This includes the vector preheader and middle blocks,
541 // which may set up or post-process per-part values.
543 Plan.getEntry());
544 for (VPBlockBase *VPB : RPOT)
545 Unroller.unrollBlock(VPB);
546
547 unsigned Part = 1;
548 // Remap operands of cloned header phis to update backedge values. The header
549 // phis cloned during unrolling are just after the header phi for part 0.
550 // Reset Part to 1 when reaching the first (part 0) recipe of a block.
551 for (VPRecipeBase &H :
553 // The second operand of Fixed Order Recurrence phi's, feeding the spliced
554 // value across the backedge, needs to remap to the last part of the spliced
555 // value.
557 Unroller.remapOperand(&H, 1, UF - 1);
558 continue;
559 }
560 if (Unroller.contains(H.getVPSingleValue())) {
561 Part = 1;
562 continue;
563 }
564 Unroller.remapOperands(&H, Part);
565 Part++;
566 }
567
569}
570
571/// Add a lane offset to the start index of \p Steps.
572static void addLaneToStartIndex(VPScalarIVStepsRecipe *Steps, unsigned Lane,
573 VPlan &Plan, VPRecipeBase *InsertPt) {
574 assert(Lane > 0 && "Zero lane adds no offset to start index");
575 Type *BaseIVTy = Steps->getOperand(0)->getScalarType();
576
577 VPValue *OldStartIndex = Steps->getStartIndex();
578 VPValue *LaneOffset;
579 unsigned AddOpcode;
580 // TODO: Retrieve the flags from Steps unconditionally.
581 VPIRFlags Flags;
582 if (BaseIVTy->isFloatingPointTy()) {
583 // The start index counts upwards, so accumulate with FAdd regardless of the
584 // induction opcode; see VPScalarIVStepsRecipe.
585 LaneOffset = Plan.getOrAddLiveIn(ConstantFP::get(BaseIVTy, Lane));
586 AddOpcode = Instruction::FAdd;
587 Flags = VPIRFlags(FastMathFlags());
588 } else {
589 unsigned BaseIVBits = BaseIVTy->getScalarSizeInBits();
590 LaneOffset = Plan.getConstantInt(
591 APInt(BaseIVBits, Lane, /*isSigned*/ false, /*implicitTrunc*/ true));
592 AddOpcode = Instruction::Add;
593 Flags = VPIRFlags(VPIRFlags::WrapFlagsTy(false, false));
594 }
595
596 VPValue *NewStartIndex = LaneOffset;
597 if (OldStartIndex) {
598 VPBuilder Builder(InsertPt);
599 NewStartIndex =
600 Builder.createNaryOp(AddOpcode, {OldStartIndex, LaneOffset}, Flags);
601 }
602 Steps->setStartIndex(NewStartIndex);
603}
604
605/// Create a single-scalar clone of \p DefR (must be a VPReplicateRecipe,
606/// VPInstruction or VPScalarIVStepsRecipe) for lane \p Lane. Use \p
607/// Def2LaneDefs to look up scalar definitions for operands of \DefR.
608static VPValue *
609cloneForLane(VPlan &Plan, VPBuilder &Builder, Type *IdxTy,
610 VPSingleDefRecipe *DefR, VPLane Lane,
611 const DenseMap<VPValue *, SmallVector<VPValue *>> &Def2LaneDefs) {
613 "DefR must be a VPReplicateRecipe, VPInstruction or "
614 "VPScalarIVStepsRecipe");
615 VPValue *Op;
617 auto LaneDefs = Def2LaneDefs.find(Op);
618 if (LaneDefs != Def2LaneDefs.end())
619 return LaneDefs->second[Lane.getKnownLane()];
620
621 VPValue *Idx = Plan.getConstantInt(IdxTy, Lane.getKnownLane());
622 return Builder.createNaryOp(Instruction::ExtractElement, {Op, Idx});
623 }
624
625 // Collect the operands at Lane, creating extracts as needed.
627 for (VPValue *Op : DefR->operands()) {
628 // If Op is a definition that has been unrolled, directly use the clone for
629 // the corresponding lane.
630 auto LaneDefs = Def2LaneDefs.find(Op);
631 if (LaneDefs != Def2LaneDefs.end()) {
632 NewOps.push_back(LaneDefs->second[Lane.getKnownLane()]);
633 continue;
634 }
635 if (Lane.getKind() == VPLane::Kind::ScalableLast) {
636 // Look through mandatory Unpack.
637 [[maybe_unused]] bool Matched =
639 assert(Matched && "original op must have been Unpack");
640 auto *ExtractPart =
641 Builder.createNaryOp(VPInstruction::ExtractLastPart, {Op});
642 NewOps.push_back(
643 Builder.createNaryOp(VPInstruction::ExtractLastLane, {ExtractPart}));
644 continue;
645 }
647 NewOps.push_back(Op);
648 continue;
649 }
650
651 VPValue *Idx = Plan.getConstantInt(IdxTy, Lane.getKnownLane());
652 VPValue *Ext = Builder.createNaryOp(Instruction::ExtractElement, {Op, Idx});
653 NewOps.push_back(Ext);
654 }
655
657 if (auto *RepR = dyn_cast<VPReplicateRecipe>(DefR)) {
658 // TODO: have cloning of replicate recipes also provide the desired result
659 // coupled with setting its operands to NewOps (deriving IsSingleScalar and
660 // Mask from the operands?)
662 RepR->getOpcode(), NewOps, /*Mask=*/nullptr, *RepR, *RepR,
663 RepR->getDebugLoc(), RepR->getScalarType(), RepR->getUnderlyingInstr());
664 } else {
665 New = DefR->clone();
666 for (const auto &[Idx, Op] : enumerate(NewOps)) {
667 New->setOperand(Idx, Op);
668 }
669 if (auto *Steps = dyn_cast<VPScalarIVStepsRecipe>(New)) {
670 // Skip lane 0: an absent start index is implicitly zero.
671 unsigned KnownLane = Lane.getKnownLane();
672 if (KnownLane != 0)
673 addLaneToStartIndex(Steps, KnownLane, Plan, DefR);
674 }
675 }
676 New->insertBefore(DefR);
677 return New;
678}
679
680/// Converts the frequency \p Freq with which a block is entered to branch
681/// weights for the branch guarding it, or nullptr if \p Freq is unknown or
682/// estimated.
683static MDNode *
684convertFrequencyToBranchWeights(std::optional<VPExecutionFrequency> Freq,
685 LLVMContext &Ctx) {
686 if (!Freq || Freq->IsEstimated)
687 return nullptr;
689
690 // Use the numerators of P and its complement as weights and reduce them via
691 // gcd to keep them small. Neither is zero, as P is neither zero nor one.
692 uint32_t Taken = P.getNumerator();
693 uint32_t NotTaken = P.getCompl().getNumerator();
694 uint32_t GCD = std::gcd(Taken, NotTaken);
695 return MDBuilder(Ctx).createBranchWeights(Taken / GCD, NotTaken / GCD);
696}
697
698/// Convert recipes in region blocks to operate on a single lane 0.
699/// VPReplicateRecipes are converted to single-scalar ones, branch-on-mask is
700/// converted into BranchOnCond, PredInstPhi recipes are replaced by scalar phi
701/// recipes with an additional poison operand, and extracts are created as
702/// needed.
704 VPBlockBase *Entry,
705 ElementCount VF) {
706 VPValue *Idx0 = Plan.getZero(IdxTy);
707 for (VPBlockBase *VPB : vp_depth_first_shallow(Entry)) {
709 assert(
710 !isa<VPWidenPHIRecipe>(&OldR) &&
711 !match(&OldR,
715 "must not contain wide phis, inserts or extracts before conversion");
716
717 VPBuilder Builder(&OldR);
718 DebugLoc OldDL = OldR.getDebugLoc();
719 // For scalar VF, operands are already scalar; no extraction needed.
720 if (!VF.isScalar()) {
721 for (const auto &[I, Op] : enumerate(OldR.operands())) {
722 // Skip operands that don't need extraction: values defined in the
723 // same block (already scalar), or values that are already single
724 // scalars.
725 // TODO: Support isSingleScalar for VPScalarIVStepsRecipe.
726 auto *DefR = Op->getDefiningRecipe();
728 DefR->getParent() == VPB) ||
730 continue;
731
732 // Extract lane zero from values defined outside the region.
733 VPValue *Extract = Builder.createNaryOp(Instruction::ExtractElement,
734 {Op, Idx0}, OldDL);
735 OldR.setOperand(I, Extract);
736 }
737 }
738
739 if (auto *RepR = dyn_cast<VPReplicateRecipe>(&OldR)) {
741 RepR->getOpcode(), to_vector(RepR->operands()), /*Mask=*/nullptr,
742 *RepR, *RepR, OldDL, RepR->getScalarType(),
743 RepR->getUnderlyingInstr());
744 NewR->insertBefore(RepR);
745 RepR->replaceAllUsesWith(NewR);
746 RepR->eraseFromParent();
747 } else if (auto *BranchOnMask = dyn_cast<VPBranchOnMaskRecipe>(&OldR)) {
748 // Turn the frequency of the predicated block into branch weights.
749 auto *BOC = Builder.createNaryOp(VPInstruction::BranchOnCond,
750 {BranchOnMask->getOperand(0)}, OldDL);
752 BranchOnMask->getExecutionFrequency(), Plan.getContext()))
753 BOC->setMetadata(LLVMContext::MD_prof, Weights);
754 BranchOnMask->eraseFromParent();
755 } else if (auto *PredPhi = dyn_cast<VPPredInstPHIRecipe>(&OldR)) {
756 VPValue *PredOp = PredPhi->getOperand(0);
757 Type *PredTy = PredOp->getScalarType();
758 VPValue *Poison = Plan.getPoison(PredTy);
759 VPPhi *NewPhi = Builder.createScalarPhi({Poison, PredOp}, OldDL);
760 PredPhi->replaceAllUsesWith(NewPhi);
761 PredPhi->eraseFromParent();
762 } else {
763 // TODO: Support isSingleScalar for VPScalarIVStepsRecipe.
765 (isa<VPInstruction>(OldR) &&
766 vputils::isSingleScalar(OldR.getVPSingleValue()))) &&
767 "unexpected unhandled recipe");
768 }
769 }
770 }
771}
772
773/// Update recipes in the cloned blocks rooted at \p NewEntry to match \p Lane,
774/// using the original blocks rooted at \p OldEntry as reference.
775static void processLaneForReplicateRegion(VPlan &Plan, Type *IdxTy,
776 unsigned Lane, VPBasicBlock *OldEntry,
777 VPBasicBlock *NewEntry) {
778 DenseMap<VPValue *, VPValue *> Old2NewVPValues;
779 VPValue *IdxLane = Plan.getConstantInt(IdxTy, Lane);
780 for (const auto &[OldBB, NewBB] :
782 vp_depth_first_shallow(NewEntry))) {
783 for (auto &&[OldR, NewR] :
785 for (const auto &[OldV, NewV] :
786 zip_equal(OldR.definedValues(), NewR.definedValues()))
787 Old2NewVPValues[OldV] = NewV;
788
789 // Remap operands to use lane-specific values.
790 for (const auto &[I, OldOp] : enumerate(NewR.operands())) {
791 // Use cloned value if operand was defined in the region.
792 if (auto *NewOp = Old2NewVPValues.lookup(OldOp))
793 NewR.setOperand(I, NewOp);
794 }
795
796 if (auto *Steps = dyn_cast<VPScalarIVStepsRecipe>(&NewR)) {
797 addLaneToStartIndex(Steps, Lane, Plan, Steps);
798 } else if (match(&NewR, m_ExtractElement(m_VPValue(), m_VPValue()))) {
799 assert(match(NewR.getOperand(1), m_ZeroInt()) &&
800 "extract indices must be zero");
801 NewR.setOperand(1, IdxLane);
802 } else if (auto *NewPhi = dyn_cast<VPPhi>(&NewR)) {
803 auto *OldPhi = cast<VPPhi>(&OldR);
805 "VPPhis expected to have only first lane used");
806 auto *BVUser = dyn_cast_or_null<VPInstruction>(OldPhi->getSingleUser());
807 if (BVUser && match(BVUser, m_CombineOr(m_BuildVector(),
809 assert(BVUser->getOperand(0) == OldPhi &&
810 "Unexpected first operand of build vector user");
811 BVUser->setOperand(Lane, NewPhi);
812 }
813 }
814 }
815 }
816}
817
818/// Dissolve a single replicate region by replicating its blocks for each lane
819/// of \p VF. The region is disconnected, its blocks are reparented, cloned for
820/// each lane, and reconnected in sequence.
822 VPlan &Plan, Type *IdxTy) {
823 auto *FirstLaneEntry = cast<VPBasicBlock>(Region->getEntry());
824 auto *FirstLaneExiting = cast<VPBasicBlock>(Region->getExiting());
825
826 // Disconnect and dissolve the region.
827 VPBlockBase *Predecessor = Region->getSinglePredecessor();
828 assert(Predecessor && "Replicate region must have a single predecessor");
829 auto *Successor = cast<VPBasicBlock>(Region->getSingleSuccessor());
832
833 VPRegionBlock *ParentRegion = Region->getParent();
834 for (VPBlockBase *VPB : vp_depth_first_shallow(FirstLaneEntry))
835 VPB->setParent(ParentRegion);
836
837 // Process the original blocks for lane 0: converting their recipes to
838 // single-scalar.
839 convertRecipesInRegionBlocksToSingleScalar(Plan, IdxTy, FirstLaneEntry, VF);
840
841 // For scalar VF, just wire the blocks and return; no cloning or packing
842 // needed.
843 if (VF.isScalar()) {
844 VPBlockUtils::connectBlocks(Predecessor, FirstLaneEntry);
845 VPBlockUtils::connectBlocks(FirstLaneExiting, Successor);
846 return;
847 }
848
849 // Create a BuildVector or BuildStructVector in successor block for every
850 // VPPhi in (first lane's) exiting block having vector uses. All their
851 // operands are initialized to poison and will be replaced when processing
852 // each clone, except for the operand of the first lane which set here.
853 // BuildVectors are recorded to be replaced later by chains of insert-element
854 // and widen phi's.
855 unsigned NumLanes = VF.getFixedValue();
856 SmallVector<VPInstruction *> BuildVectors;
857 for (auto &R : FirstLaneExiting->phis()) {
858 auto *Phi = cast<VPPhi>(&R);
860 continue;
861
862 Type *ScalarTy = Phi->getScalarType();
863 bool IsStruct = isa<StructType>(ScalarTy);
864 VPValue *Poison = Plan.getPoison(ScalarTy);
865 SmallVector<VPValue *> BVOps(NumLanes, Poison);
866 auto *BV = new VPInstruction(IsStruct ? VPInstruction::BuildStructVector
868 BVOps);
869 if (!IsStruct)
870 BuildVectors.push_back(BV);
871 Phi->replaceAllUsesWith(BV);
872 BV->setOperand(0, Phi);
873 BV->insertBefore(*Successor, Successor->getFirstNonPhi());
874 }
875
876 // Clone converted blocks for remaining lanes and process each in reverse
877 // order, connecting each lane's Exiting block to the subsequent lane's entry.
878 VPBlockBase *NextLaneEntry = Successor;
879 for (int Lane = NumLanes - 1; Lane > 0; --Lane) {
880 const auto &[CurrentLaneEntry, CurrentLaneExiting] =
881 VPBlockUtils::cloneFrom(FirstLaneEntry);
882 for (VPBlockBase *VPB : vp_depth_first_shallow(CurrentLaneEntry))
883 VPB->setParent(ParentRegion);
884 processLaneForReplicateRegion(Plan, IdxTy, Lane,
885 cast<VPBasicBlock>(FirstLaneEntry),
886 cast<VPBasicBlock>(CurrentLaneEntry));
887 VPBlockUtils::connectBlocks(CurrentLaneExiting, NextLaneEntry);
888 NextLaneEntry = CurrentLaneEntry;
889 }
890
891 // Connect Predecessor to FirstLaneEntry, and FirstLaneRegionExit to
892 // NextLaneEntry which is the second lane region entry. The latter is
893 // done last so that earlier clonings from FirstLaneEntry stop at
894 // FirstLaneExiting.
895 VPBlockUtils::connectBlocks(Predecessor, FirstLaneEntry);
896 VPBlockUtils::connectBlocks(FirstLaneExiting, NextLaneEntry);
897
898 // Fold BuildVector fed by scalar phis into VPWidenPHIRecipes with
899 // InsertElement per lane.
900 // TODO: check if this folding should be dropped.
901 for (VPInstruction *BV : BuildVectors) {
902 assert(BV->getNumOperands() == NumLanes &&
903 "BuildVector must have one operand per lane");
904 for (const auto &[Idx, Op] : enumerate(BV->operands())) {
905 auto *ScalarPhi = cast<VPPhi>(Op);
906 auto DL = ScalarPhi->getDebugLoc();
907 auto *PredOp = cast<VPSingleDefRecipe>(ScalarPhi->getOperand(1));
908 VPValue *Poison = ScalarPhi->getOperand(0);
909 VPValue *PrevVal = Idx == 0 ? Poison : BV->getOperand(Idx - 1);
910 auto Builder = VPBuilder::getToInsertAfter(PredOp->getDefiningRecipe());
911 auto *Insert = Builder.createNaryOp(
912 Instruction::InsertElement,
913 {PrevVal, PredOp, Plan.getConstantInt(64, Idx)}, DL);
914 Builder.setInsertPoint(ScalarPhi);
915 auto *NewPhi = Builder.createWidenPhi({PrevVal, Insert}, DL);
916 ScalarPhi->replaceAllUsesWith(NewPhi);
917 ScalarPhi->eraseFromParent();
918 }
919 BV->replaceAllUsesWith(BV->getOperand(NumLanes - 1));
920 BV->eraseFromParent();
921 }
922}
923
924/// Collect and dissolve all replicate regions in the vector loop, replicating
925/// their blocks and recipes for each lane of \p VF.
927 Type *IdxTy) {
928 // Collect all replicate regions before modifying the CFG.
929 SmallVector<VPRegionBlock *> ReplicateRegions;
932 if (Region->isReplicator())
933 ReplicateRegions.push_back(Region);
934 }
935
936 assert((ReplicateRegions.empty() || !VF.isScalable()) &&
937 "cannot replicate across scalable VFs");
938
939 // Dissolve replicate regions by replicating their blocks for each lane.
940 // Traversing regions in reverse ensures that the successor of every region
941 // being processed is a basic-block, rather than another region.
942 for (VPRegionBlock *Region : reverse(ReplicateRegions))
943 dissolveReplicateRegion(Region, VF, Plan, IdxTy);
944
946}
947
949 Type *IdxTy = IntegerType::get(
951
952 if (Plan.hasScalarVFOnly()) {
953 // When Plan is only unrolled by UF, replicating by VF amounts to dissolving
954 // replicate regions.
955 replicateReplicateRegionsByVF(Plan, VF, IdxTy);
956 return;
957 }
958
959 // Visit all VPBBs outside the loop region and directly inside the top-level
960 // loop region.
961 auto VPBBsOutsideLoopRegion = VPBlockUtils::blocksOnly<VPBasicBlock>(
963 auto VPBBsInsideLoopRegion = VPBlockUtils::blocksOnly<VPBasicBlock>(
965 auto VPBBsToUnroll =
966 concat<VPBasicBlock *>(VPBBsOutsideLoopRegion, VPBBsInsideLoopRegion);
967 // A mapping of current VPValue definitions to collections of new VPValues
968 // defined per lane. Serves to hook-up potential users of current VPValue
969 // definition that are replicated-per-VF later.
971 // The removal of current recipes being replaced by new ones needs to be
972 // delayed after Def2LaneDefs is no longer in use.
974 for (VPBasicBlock *VPBB : VPBBsToUnroll) {
975 for (VPRecipeBase &R : make_early_inc_range(*VPBB)) {
977 continue;
978
979 auto *DefR = cast<VPSingleDefRecipe>(&R);
980 VPBuilder Builder(DefR);
981 if (DefR->user_empty()) {
982 // Create single-scalar version of DefR for all lanes.
983 for (unsigned I = 0; I != VF.getKnownMinValue(); ++I)
984 cloneForLane(Plan, Builder, IdxTy, DefR, VPLane(I), Def2LaneDefs);
985 DefR->eraseFromParent();
986 continue;
987 }
988 /// Create single-scalar version of DefR for all lanes.
989 SmallVector<VPValue *> LaneDefs;
990 for (unsigned I = 0; I != VF.getKnownMinValue(); ++I)
991 LaneDefs.push_back(
992 cloneForLane(Plan, Builder, IdxTy, DefR, VPLane(I), Def2LaneDefs));
993
994 Def2LaneDefs[DefR] = LaneDefs;
995 // Pack the lanes for vector users.
997 unsigned Opcode = DefR->getScalarType()->isStructTy()
1000 DefR->replaceUsesWithIf(
1001 Builder.createNaryOp(Opcode, LaneDefs),
1002 [DefR](VPUser &U) { return !U.usesScalars(DefR); });
1003 }
1004 /// Users that only demand the first lane can use the definition for lane
1005 /// 0.
1006 DefR->replaceUsesWithIf(LaneDefs[0], [DefR](VPUser &U) {
1007 if (U.usesFirstLaneOnly(DefR))
1008 return true;
1009 auto *VPI = dyn_cast<VPInstruction>(&U);
1010 return VPI && Instruction::isCast(VPI->getOpcode());
1011 });
1012 ToRemove.push_back(DefR);
1013 }
1014 }
1015
1016 replicateReplicateRegionsByVF(Plan, VF, IdxTy);
1017 // Replace the lane extracts created when dissolving replicate regions.
1018 for (VPSingleDefRecipe *DefR : reverse(ToRemove)) {
1019 for (VPUser *U : to_vector(DefR->users())) {
1020 uint64_t Lane;
1021 [[maybe_unused]] bool Match =
1023 assert(Match && "unexpected remaining user");
1024 auto *Ext = cast<VPInstruction>(U);
1025 Ext->replaceAllUsesWith(Def2LaneDefs.at(DefR)[Lane]);
1026 Ext->eraseFromParent();
1027 }
1028 DefR->eraseFromParent();
1029 }
1030}
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
#define P(N)
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 MDNode * convertFrequencyToBranchWeights(std::optional< VPExecutionFrequency > Freq, LLVMContext &Ctx)
Converts the frequency Freq with which a block is entered to branch weights for the branch guarding i...
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:1162
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 & at(const_arg_type_t< KeyT > Val)
Return the entry for the specified key, or abort if no such entry exists.
Definition DenseMap.h:812
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:794
constexpr bool isScalar() const
Exactly one element.
Definition TypeSize.h:316
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:338
This is an important class for using LLVM in a threaded context.
Definition LLVMContext.h:68
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:1081
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:277
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:222
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:4437
RecipeListTy::iterator iterator
Instruction iterators...
Definition VPlan.h:4464
iterator_range< iterator > phis()
Returns an iterator range over the PHI-like recipes in the block.
Definition VPlan.h:4525
iterator getFirstNonPhi()
Return the position of the first non-phi node recipe in the block.
Definition VPlan.cpp:233
VPBlockBase is the building block of the Hierarchical Control-Flow Graph.
Definition VPlan.h:97
const VPBasicBlock * getEntryBasicBlock() const
Definition VPlan.cpp:188
void setParent(VPRegionBlock *P)
Definition VPlan.h:205
VPBlockBase * getSingleSuccessor() const
Definition VPlan.h:235
static auto blocksAs(T &&Range)
Return an iterator range over Range with each block cast to BlockTy.
Definition VPlanUtils.h:420
static void connectBlocks(VPBlockBase *From, VPBlockBase *To, unsigned PredIdx=-1u, unsigned SuccIdx=-1u)
Connect VPBlockBases From and To bi-directionally.
Definition VPlanUtils.h:347
static void disconnectBlocks(VPBlockBase *From, VPBlockBase *To)
Disconnect VPBlockBases From and To bi-directionally.
Definition VPlanUtils.h:365
static void insertBlockBefore(VPBlockBase *NewBlock, VPBlockBase *BlockPtr)
Insert disconnected block NewBlock before Blockptr.
Definition VPlanUtils.h:314
static auto blocksOnly(T &&Range)
Return an iterator range over Range which only includes BlockTy blocks.
Definition VPlanUtils.h:413
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:661
static VPBuilderBase getToInsertAfter(VPRecipeBase *R)
static VPSingleDefRecipe * createSingleScalarOp(unsigned Opcode, ArrayRef< VPValue * > Operands, VPValue *Mask, const VPIRFlags &Flags, const VPIRMetadata &Metadata, DebugLoc DL, Type *ResultTy, Instruction *UV)
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:4614
Class to record and manage LLVM IR flags.
Definition VPlan.h:688
This is a concrete Recipe that models a single VPlan-level instruction.
Definition VPlan.h:1282
@ WideIVStep
Scale the first operand (vector step) by the second operand (scalar-step).
Definition VPlan.h:1408
@ ReductionStartVector
Start vector for reductions with 3 operands: the original start value, the identity value for the red...
Definition VPlan.h:1387
@ BuildVector
Creates a fixed-width vector containing all operands.
Definition VPlan.h:1337
@ BuildStructVector
Given operands of (the same) struct type, creates a struct of fixed- width vectors each containing a ...
Definition VPlan.h:1334
@ CanonicalIVIncrementForPart
Definition VPlan.h:1318
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:403
DebugLoc getDebugLoc() const
Returns the debug location of the recipe.
Definition VPlan.h:553
VPRegionBlock represents a collection of VPBasicBlocks and VPRegionBlocks which form a Single-Entry-S...
Definition VPlan.h:4662
VPRegionBlock * clone() override
Clone all blocks in the single-entry single-exit region of the block and their recipes without updati...
Definition VPlan.cpp:718
const VPBlockBase * getEntry() const
Definition VPlan.h:4706
bool isReplicator() const
An indicator whether this region is to generate multiple replicated instances of output IR correspond...
Definition VPlan.h:4738
Type * getCanonicalIVType() const
Return the type of the canonical IV for loop regions.
Definition VPlan.h:4790
A recipe for handling phi nodes of integer and floating-point inductions, producing their scalar valu...
Definition VPlan.h:4279
void setStartIndex(VPValue *StartIndex)
Set or add the StartIndex operand.
Definition VPlan.h:4323
VPValue * getStartIndex() const
Return the StartIndex, or null if known to be zero, valid only after unrolling.
Definition VPlan.h:4318
VPValue * getVFValue() const
Return the number of scalars to produce per unroll part, used to compute StartIndex during unrolling.
Definition VPlan.h:4314
VPSingleDefRecipe is a base class for recipes that model a sequence of one or more output IR that def...
Definition VPlan.h:611
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:397
operand_range operands()
Definition VPlanValue.h:473
VPValue * getOperand(unsigned N) const
Definition VPlanValue.h:438
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:147
void replaceAllUsesWith(VPValue *New)
Definition VPlan.cpp:1457
VPlan models a candidate for vectorization, encoding various decisions take to produce efficient outp...
Definition VPlan.h:4849
const DataLayout & getDataLayout() const
Definition VPlan.h:5063
LLVMContext & getContext() const
Definition VPlan.h:5059
VPBasicBlock * getEntry()
Definition VPlan.h:4945
VPValue * getTripCount() const
The trip count of the original loop.
Definition VPlan.h:5017
VPIRValue * getPoison(Type *Ty)
Return a VPIRValue wrapping a poison value of type Ty.
Definition VPlan.h:5186
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:5135
VPIRValue * getZero(Type *Ty)
Return a VPIRValue wrapping the null value of type Ty.
Definition VPlan.h:5161
LLVM_ABI_FOR_TEST VPRegionBlock * getVectorLoopRegion()
Returns the VPRegionBlock of the vector loop.
Definition VPlan.cpp:1035
VPSymbolicValue & getUF()
Returns the UF of the vector loop region.
Definition VPlan.h:5054
bool hasScalarVFOnly() const
Definition VPlan.h:5103
VPIRBasicBlock * getScalarHeader() const
Return the VPIRBasicBlock wrapping the header of the scalar loop.
Definition VPlan.h:5007
VPSymbolicValue & getVF()
Returns the VF of the vector loop region.
Definition VPlan.h:5050
void setUF(unsigned UF)
Definition VPlan.h:5118
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:5169
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)
specificval_ty m_Specific(const Value *V)
Match if we have a specific specified value.
cst_pred_ty< is_one > m_One()
Match an integer 1 or a vector with all elements equal to 1.
auto m_Intrinsic(const Ts &...Ops)
Match intrinsic calls like this: m_Intrinsic<Intrinsic::fabs>(m_Value(X))
auto m_ConstantInt()
Match an arbitrary ConstantInt and ignore it.
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
BranchProbability getExecutionProbability(BlockFrequency Freq)
Returns Freq as a BranchProbability, relative to the full mass.
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 onlyScalarValuesUsed(const VPValue *Def)
Returns true if only scalar values of Def are used by all users.
LLVM_ABI_FOR_TEST 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.
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:846
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:856
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:2570
decltype(auto) dyn_cast(const From &Val)
dyn_cast<X> - Return the argument parameter cast to the specified type.
Definition Casting.h:643
VPBuilderBase<> VPBuilder
Definition VPlan.h:67
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:649
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:1167
auto make_isa_range(RangeT &&Range)
Return a range over Range containing only elements for which isa<T> holds, casting each of them to T.
Definition STLExtras.h:567
auto dyn_cast_or_null(const Y &Val)
Definition Casting.h:753
auto reverse(ContainerTy &&C)
Definition STLExtras.h:408
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...