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(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(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 for (unsigned Part = 1; Part != UF; ++Part) {
321 VPRecipeBase *Copy = R.clone();
322 Copy->insertBefore(InsertPt);
323 addRecipeForPart(&R, Copy, Part);
324
325 // Phi operands are updated once all other recipes have been unrolled.
326 if (isa<VPWidenPHIRecipe>(Copy))
327 continue;
328
329 VPValue *Op;
331 m_VPValue(), m_VPValue(Op)))) {
332 Copy->setOperand(0, getValueForPart(Op, Part - 1));
333 Copy->setOperand(1, getValueForPart(Op, Part));
334 continue;
335 }
337 m_VPValue(Op), m_VPValue()))) {
338 Copy->setOperand(0, Op);
339 Copy->setOperand(1, Plan.getConstantInt(64, Part));
340 continue;
341 }
343 VPBuilder Builder(&R);
344 const DataLayout &DL = Plan.getDataLayout();
345 Type *IndexTy =
348 : DL.getIndexType(R.getVPSingleValue()->getScalarType());
349 VPValue *VF = Builder.createScalarZExtOrTrunc(&Plan.getVF(), IndexTy,
351 // VFxUF does not wrap, so VF * Part also cannot wrap.
352 VPValue *VFxPart = Builder.createOverflowingOp(
353 Instruction::Mul, {VF, Plan.getConstantInt(IndexTy, Part)},
354 {true, true});
355 if (auto *VecPtr = dyn_cast<VPVectorPointerRecipe>(Copy))
356 VecPtr->addPerPartOffset(VFxPart);
357 else
358 cast<VPWidenCanonicalIVRecipe>(Copy)->addPerPartStep(VFxPart);
359 continue;
360 }
361 if (auto *Red = dyn_cast<VPReductionRecipe>(&R)) {
362 auto *Phi = dyn_cast<VPReductionPHIRecipe>(R.getOperand(0));
363 if (Phi && Phi->isOrdered()) {
364 auto &Parts = VPV2Parts[Phi];
365 if (Part == 1) {
366 Parts.clear();
367 Parts.push_back(Red);
368 }
369 Parts.push_back(Copy->getVPSingleValue());
370 Phi->setOperand(1, Copy->getVPSingleValue());
371 }
372 }
373 if (auto *VEPR = dyn_cast<VPVectorEndPointerRecipe>(Copy)) {
374 // Materialize PartN offset for VectorEndPointer.
375 VEPR->setOperand(0, R.getOperand(0));
376 VEPR->setOperand(1, R.getOperand(1));
377 VEPR->materializeOffset(Part);
378 continue;
379 }
380
381 remapOperands(Copy, Part);
382
383 if (auto *ScalarIVSteps = dyn_cast<VPScalarIVStepsRecipe>(Copy))
384 addStartIndexForScalarSteps(ScalarIVSteps, Part, Plan);
385
386 if (match(Copy,
388 VPBuilder Builder(Copy);
389 VPValue *ScaledByPart = Builder.createOverflowingOp(
390 Instruction::Mul, {Copy->getOperand(1), getConstantInt(Part)});
391 Copy->setOperand(1, ScaledByPart);
392 }
393 }
394 if (auto *VEPR = dyn_cast<VPVectorEndPointerRecipe>(&R)) {
395 // Materialize Part0 offset for VectorEndPointer.
396 VEPR->materializeOffset();
397 }
398 if (auto *WideCanIV = dyn_cast<VPWidenCanonicalIVRecipe>(&R)) {
399 // Set Part0 step for WidenCanonicalIV.
400 WideCanIV->addPerPartStep(getConstantInt(0));
401 }
402}
403
404void UnrollState::unrollBlock(VPBlockBase *VPB) {
405 auto *VPR = dyn_cast<VPRegionBlock>(VPB);
406 if (VPR) {
407 if (VPR->isReplicator())
408 return unrollReplicateRegionByUF(VPR);
409
410 // Traverse blocks in region in RPO to ensure defs are visited before uses
411 // across blocks.
412 ReversePostOrderTraversal<VPBlockShallowTraversalWrapper<VPBlockBase *>>
413 RPOT(VPR->getEntry());
414 for (VPBlockBase *VPB : RPOT)
415 unrollBlock(VPB);
416 return;
417 }
418
419 // VPB is a VPBasicBlock; unroll it, i.e., unroll its recipes.
420 auto *VPBB = cast<VPBasicBlock>(VPB);
421 auto InsertPtForPhi = VPBB->getFirstNonPhi();
422 for (VPRecipeBase &R : make_early_inc_range(*VPBB)) {
423 if (ToSkip.contains(&R) || isa<VPIRInstruction>(&R))
424 continue;
425
426 // Add all VPValues for all parts to AnyOf, FirstActiveLaneMask and
427 // ComputeReductionResult which combine all parts to compute the final
428 // value.
429 VPValue *Op1;
431 match(&R,
433 match(&R, m_FirstActiveLane(m_VPValue(Op1))) ||
434 match(&R, m_LastActiveLane(m_VPValue(Op1))) ||
436 auto *VPI = cast<VPInstruction>(&R);
437 addUniformForAllParts(VPI);
438 for (unsigned Part = 1; Part != UF; ++Part)
439 VPI->addOperand(getValueForPart(Op1, Part));
440 continue;
441 }
442 VPValue *Op0;
443 if (match(&R, m_ExtractLane(m_VPValue(Op0), m_VPValue(Op1)))) {
444 auto *VPI = cast<VPInstruction>(&R);
445 addUniformForAllParts(VPI);
446 for (unsigned Part = 1; Part != UF; ++Part)
447 VPI->addOperand(getValueForPart(Op1, Part));
448 continue;
449 }
450
451 VPValue *Op2;
453 m_VPValue(Op2)))) {
454 auto *VPI = cast<VPInstruction>(&R);
455 addUniformForAllParts(VPI);
456 for (unsigned Part = 1; Part != UF; ++Part) {
457 VPI->addOperand(getValueForPart(Op1, Part));
458 VPI->addOperand(getValueForPart(Op2, Part));
459 }
460 continue;
461 }
462
463 if (Plan.hasScalarVFOnly()) {
464 if (match(&R, m_ExtractLastPart(m_VPValue(Op0))) ||
466 auto *I = cast<VPInstruction>(&R);
467 bool IsPenultimatePart =
469 unsigned PartIdx = IsPenultimatePart ? UF - 2 : UF - 1;
470 // For scalar VF, directly use the scalar part value.
471 I->replaceAllUsesWith(getValueForPart(Op0, PartIdx));
472 continue;
473 }
474 }
475 // For vector VF, the penultimate element is always extracted from the last part.
478 addUniformForAllParts(cast<VPSingleDefRecipe>(&R));
479 R.setOperand(0, getValueForPart(Op0, UF - 1));
480 continue;
481 }
482
483 if (match(&R,
485 auto *ALM = cast<VPInstruction>(&R);
486 ALM->setOperand(2, getConstantInt(UF));
487 continue;
488 }
489
490 if (match(&R,
493 cast<VPInstruction>(&R)->setOperand(0, Plan.getConstantInt(64, UF));
494 continue;
495 }
496
497 auto *SingleDef = dyn_cast<VPSingleDefRecipe>(&R);
498 if (SingleDef && vputils::isUniformAcrossVFsAndUFs(SingleDef)) {
499 addUniformForAllParts(SingleDef);
500 continue;
501 }
502
503 if (auto *H = dyn_cast<VPHeaderPHIRecipe>(&R)) {
504 unrollHeaderPHIByUF(H, InsertPtForPhi);
505 continue;
506 }
507
508 unrollRecipeByUF(R);
509 }
510}
511
512void VPlanTransforms::unrollByUF(VPlan &Plan, unsigned UF) {
513 assert(UF > 0 && "Unroll factor must be positive");
514 Plan.setUF(UF);
515 llvm::scope_exit Cleanup([&Plan, UF]() {
516 auto Iter = vp_depth_first_deep(Plan.getEntry());
517 // Remove recipes that are redundant after unrolling.
519 for (VPInstruction &VPI :
521 if (VPI.getOpcode() == VPInstruction::CanonicalIVIncrementForPart &&
522 VPI.getOperand(1) == &Plan.getVF()) {
523 VPI.replaceAllUsesWith(VPI.getOperand(0));
524 VPI.eraseFromParent();
525 }
526 }
527 }
528
529 Type *TCTy = Plan.getTripCount()->getScalarType();
530 Plan.getUF().replaceAllUsesWith(Plan.getConstantInt(TCTy, UF));
531 });
532 if (UF == 1) {
533 return;
534 }
535
536 UnrollState Unroller(Plan, UF);
537
538 // Iterate over all blocks in the plan starting from Entry, and unroll
539 // recipes inside them. This includes the vector preheader and middle blocks,
540 // which may set up or post-process per-part values.
542 Plan.getEntry());
543 for (VPBlockBase *VPB : RPOT)
544 Unroller.unrollBlock(VPB);
545
546 unsigned Part = 1;
547 // Remap operands of cloned header phis to update backedge values. The header
548 // phis cloned during unrolling are just after the header phi for part 0.
549 // Reset Part to 1 when reaching the first (part 0) recipe of a block.
550 for (VPRecipeBase &H :
552 // The second operand of Fixed Order Recurrence phi's, feeding the spliced
553 // value across the backedge, needs to remap to the last part of the spliced
554 // value.
556 Unroller.remapOperand(&H, 1, UF - 1);
557 continue;
558 }
559 if (Unroller.contains(H.getVPSingleValue())) {
560 Part = 1;
561 continue;
562 }
563 Unroller.remapOperands(&H, Part);
564 Part++;
565 }
566
568}
569
570/// Add a lane offset to the start index of \p Steps.
571static void addLaneToStartIndex(VPScalarIVStepsRecipe *Steps, unsigned Lane,
572 VPlan &Plan, VPRecipeBase *InsertPt) {
573 assert(Lane > 0 && "Zero lane adds no offset to start index");
574 Type *BaseIVTy = Steps->getOperand(0)->getScalarType();
575
576 VPValue *OldStartIndex = Steps->getStartIndex();
577 VPValue *LaneOffset;
578 unsigned AddOpcode;
579 // TODO: Retrieve the flags from Steps unconditionally.
580 VPIRFlags Flags;
581 if (BaseIVTy->isFloatingPointTy()) {
582 // The start index counts upwards, so accumulate with FAdd regardless of the
583 // induction opcode; see VPScalarIVStepsRecipe.
584 LaneOffset = Plan.getOrAddLiveIn(ConstantFP::get(BaseIVTy, Lane));
585 AddOpcode = Instruction::FAdd;
586 Flags = VPIRFlags(FastMathFlags());
587 } else {
588 unsigned BaseIVBits = BaseIVTy->getScalarSizeInBits();
589 LaneOffset = Plan.getConstantInt(
590 APInt(BaseIVBits, Lane, /*isSigned*/ false, /*implicitTrunc*/ true));
591 AddOpcode = Instruction::Add;
592 Flags = VPIRFlags(VPIRFlags::WrapFlagsTy(false, false));
593 }
594
595 VPValue *NewStartIndex = LaneOffset;
596 if (OldStartIndex) {
597 VPBuilder Builder(InsertPt);
598 NewStartIndex =
599 Builder.createNaryOp(AddOpcode, {OldStartIndex, LaneOffset}, Flags);
600 }
601 Steps->setStartIndex(NewStartIndex);
602}
603
604/// Create a single-scalar clone of \p DefR (must be a VPReplicateRecipe,
605/// VPInstruction or VPScalarIVStepsRecipe) for lane \p Lane. Use \p
606/// Def2LaneDefs to look up scalar definitions for operands of \DefR.
607static VPValue *
608cloneForLane(VPlan &Plan, VPBuilder &Builder, Type *IdxTy,
609 VPSingleDefRecipe *DefR, VPLane Lane,
610 const DenseMap<VPValue *, SmallVector<VPValue *>> &Def2LaneDefs) {
612 "DefR must be a VPReplicateRecipe, VPInstruction or "
613 "VPScalarIVStepsRecipe");
614 VPValue *Op;
616 auto LaneDefs = Def2LaneDefs.find(Op);
617 if (LaneDefs != Def2LaneDefs.end())
618 return LaneDefs->second[Lane.getKnownLane()];
619
620 VPValue *Idx = Plan.getConstantInt(IdxTy, Lane.getKnownLane());
621 return Builder.createNaryOp(Instruction::ExtractElement, {Op, Idx});
622 }
623
624 // Collect the operands at Lane, creating extracts as needed.
626 for (VPValue *Op : DefR->operands()) {
627 // If Op is a definition that has been unrolled, directly use the clone for
628 // the corresponding lane.
629 auto LaneDefs = Def2LaneDefs.find(Op);
630 if (LaneDefs != Def2LaneDefs.end()) {
631 NewOps.push_back(LaneDefs->second[Lane.getKnownLane()]);
632 continue;
633 }
634 if (Lane.getKind() == VPLane::Kind::ScalableLast) {
635 // Look through mandatory Unpack.
636 [[maybe_unused]] bool Matched =
638 assert(Matched && "original op must have been Unpack");
639 auto *ExtractPart =
640 Builder.createNaryOp(VPInstruction::ExtractLastPart, {Op});
641 NewOps.push_back(
642 Builder.createNaryOp(VPInstruction::ExtractLastLane, {ExtractPart}));
643 continue;
644 }
646 NewOps.push_back(Op);
647 continue;
648 }
649
650 VPValue *Idx = Plan.getConstantInt(IdxTy, Lane.getKnownLane());
651 VPValue *Ext = Builder.createNaryOp(Instruction::ExtractElement, {Op, Idx});
652 NewOps.push_back(Ext);
653 }
654
656 if (auto *RepR = dyn_cast<VPReplicateRecipe>(DefR)) {
657 // TODO: have cloning of replicate recipes also provide the desired result
658 // coupled with setting its operands to NewOps (deriving IsSingleScalar and
659 // Mask from the operands?)
661 RepR->getOpcode(), NewOps, /*Mask=*/nullptr, *RepR, *RepR,
662 RepR->getDebugLoc(), RepR->getScalarType(), RepR->getUnderlyingInstr());
663 } else {
664 New = DefR->clone();
665 for (const auto &[Idx, Op] : enumerate(NewOps)) {
666 New->setOperand(Idx, Op);
667 }
668 if (auto *Steps = dyn_cast<VPScalarIVStepsRecipe>(New)) {
669 // Skip lane 0: an absent start index is implicitly zero.
670 unsigned KnownLane = Lane.getKnownLane();
671 if (KnownLane != 0)
672 addLaneToStartIndex(Steps, KnownLane, Plan, DefR);
673 }
674 }
675 New->insertBefore(DefR);
676 return New;
677}
678
679/// Converts the frequency \p Freq with which a block is entered to branch
680/// weights for the branch guarding it, or nullptr if \p Freq is unknown or
681/// estimated.
682static MDNode *
683convertFrequencyToBranchWeights(std::optional<VPExecutionFrequency> Freq,
684 LLVMContext &Ctx) {
685 if (!Freq || Freq->IsEstimated)
686 return nullptr;
688
689 // Use the numerators of P and its complement as weights and reduce them via
690 // gcd to keep them small. Neither is zero, as P is neither zero nor one.
691 uint32_t Taken = P.getNumerator();
692 uint32_t NotTaken = P.getCompl().getNumerator();
693 uint32_t GCD = std::gcd(Taken, NotTaken);
694 return MDBuilder(Ctx).createBranchWeights(Taken / GCD, NotTaken / GCD);
695}
696
697/// Convert recipes in region blocks to operate on a single lane 0.
698/// VPReplicateRecipes are converted to single-scalar ones, branch-on-mask is
699/// converted into BranchOnCond, PredInstPhi recipes are replaced by scalar phi
700/// recipes with an additional poison operand, and extracts are created as
701/// needed.
703 VPBlockBase *Entry,
704 ElementCount VF) {
705 VPValue *Idx0 = Plan.getZero(IdxTy);
706 for (VPBlockBase *VPB : vp_depth_first_shallow(Entry)) {
708 assert(
709 !isa<VPWidenPHIRecipe>(&OldR) &&
710 !match(&OldR,
714 "must not contain wide phis, inserts or extracts before conversion");
715
716 VPBuilder Builder(&OldR);
717 DebugLoc OldDL = OldR.getDebugLoc();
718 // For scalar VF, operands are already scalar; no extraction needed.
719 if (!VF.isScalar()) {
720 for (const auto &[I, Op] : enumerate(OldR.operands())) {
721 // Skip operands that don't need extraction: values defined in the
722 // same block (already scalar), or values that are already single
723 // scalars.
724 // TODO: Support isSingleScalar for VPScalarIVStepsRecipe.
725 auto *DefR = Op->getDefiningRecipe();
727 DefR->getParent() == VPB) ||
729 continue;
730
731 // Extract lane zero from values defined outside the region.
732 VPValue *Extract = Builder.createNaryOp(Instruction::ExtractElement,
733 {Op, Idx0}, OldDL);
734 OldR.setOperand(I, Extract);
735 }
736 }
737
738 if (auto *RepR = dyn_cast<VPReplicateRecipe>(&OldR)) {
740 RepR->getOpcode(), to_vector(RepR->operands()), /*Mask=*/nullptr,
741 *RepR, *RepR, OldDL, RepR->getScalarType(),
742 RepR->getUnderlyingInstr());
743 NewR->insertBefore(RepR);
744 RepR->replaceAllUsesWith(NewR);
745 RepR->eraseFromParent();
746 } else if (auto *BranchOnMask = dyn_cast<VPBranchOnMaskRecipe>(&OldR)) {
747 // Turn the frequency of the predicated block into branch weights.
748 auto *BOC = Builder.createNaryOp(VPInstruction::BranchOnCond,
749 {BranchOnMask->getOperand(0)}, OldDL);
751 BranchOnMask->getExecutionFrequency(), Plan.getContext()))
752 BOC->setMetadata(LLVMContext::MD_prof, Weights);
753 BranchOnMask->eraseFromParent();
754 } else if (auto *PredPhi = dyn_cast<VPPredInstPHIRecipe>(&OldR)) {
755 VPValue *PredOp = PredPhi->getOperand(0);
756 Type *PredTy = PredOp->getScalarType();
757 VPValue *Poison = Plan.getPoison(PredTy);
758 VPPhi *NewPhi = Builder.createScalarPhi({Poison, PredOp}, OldDL);
759 PredPhi->replaceAllUsesWith(NewPhi);
760 PredPhi->eraseFromParent();
761 } else {
762 // TODO: Support isSingleScalar for VPScalarIVStepsRecipe.
764 (isa<VPInstruction>(OldR) &&
765 vputils::isSingleScalar(OldR.getVPSingleValue()))) &&
766 "unexpected unhandled recipe");
767 }
768 }
769 }
770}
771
772/// Update recipes in the cloned blocks rooted at \p NewEntry to match \p Lane,
773/// using the original blocks rooted at \p OldEntry as reference.
774static void processLaneForReplicateRegion(VPlan &Plan, Type *IdxTy,
775 unsigned Lane, VPBasicBlock *OldEntry,
776 VPBasicBlock *NewEntry) {
777 DenseMap<VPValue *, VPValue *> Old2NewVPValues;
778 VPValue *IdxLane = Plan.getConstantInt(IdxTy, Lane);
779 for (const auto &[OldBB, NewBB] :
781 vp_depth_first_shallow(NewEntry))) {
782 for (auto &&[OldR, NewR] :
784 for (const auto &[OldV, NewV] :
785 zip_equal(OldR.definedValues(), NewR.definedValues()))
786 Old2NewVPValues[OldV] = NewV;
787
788 // Remap operands to use lane-specific values.
789 for (const auto &[I, OldOp] : enumerate(NewR.operands())) {
790 // Use cloned value if operand was defined in the region.
791 if (auto *NewOp = Old2NewVPValues.lookup(OldOp))
792 NewR.setOperand(I, NewOp);
793 }
794
795 if (auto *Steps = dyn_cast<VPScalarIVStepsRecipe>(&NewR)) {
796 addLaneToStartIndex(Steps, Lane, Plan, Steps);
797 } else if (match(&NewR, m_ExtractElement(m_VPValue(), m_VPValue()))) {
798 assert(match(NewR.getOperand(1), m_ZeroInt()) &&
799 "extract indices must be zero");
800 NewR.setOperand(1, IdxLane);
801 } else if (auto *NewPhi = dyn_cast<VPPhi>(&NewR)) {
802 auto *OldPhi = cast<VPPhi>(&OldR);
804 "VPPhis expected to have only first lane used");
805 auto *BVUser = dyn_cast_or_null<VPInstruction>(OldPhi->getSingleUser());
806 if (BVUser && match(BVUser, m_BuildVector())) {
807 assert(BVUser->getOperand(0) == OldPhi &&
808 "Unexpected first operand of build vector user");
809 BVUser->setOperand(Lane, NewPhi);
810 }
811 }
812 }
813 }
814}
815
816/// Dissolve a single replicate region by replicating its blocks for each lane
817/// of \p VF. The region is disconnected, its blocks are reparented, cloned for
818/// each lane, and reconnected in sequence.
820 VPlan &Plan, Type *IdxTy) {
821 auto *FirstLaneEntry = cast<VPBasicBlock>(Region->getEntry());
822 auto *FirstLaneExiting = cast<VPBasicBlock>(Region->getExiting());
823
824 // Disconnect and dissolve the region.
825 VPBlockBase *Predecessor = Region->getSinglePredecessor();
826 assert(Predecessor && "Replicate region must have a single predecessor");
827 auto *Successor = cast<VPBasicBlock>(Region->getSingleSuccessor());
830
831 VPRegionBlock *ParentRegion = Region->getParent();
832 for (VPBlockBase *VPB : vp_depth_first_shallow(FirstLaneEntry))
833 VPB->setParent(ParentRegion);
834
835 // Process the original blocks for lane 0: converting their recipes to
836 // single-scalar.
837 convertRecipesInRegionBlocksToSingleScalar(Plan, IdxTy, FirstLaneEntry, VF);
838
839 // For scalar VF, just wire the blocks and return; no cloning or packing
840 // needed.
841 if (VF.isScalar()) {
842 VPBlockUtils::connectBlocks(Predecessor, FirstLaneEntry);
843 VPBlockUtils::connectBlocks(FirstLaneExiting, Successor);
844 return;
845 }
846
847 // Create a BuildVector in successor block for every VPPhi in (first lane's)
848 // exiting block having vector uses. All their
849 // operands are initialized to poison and will be replaced when processing
850 // each clone, except for the operand of the first lane which set here.
851 // BuildVectors are recorded to be replaced later by chains of insert-element
852 // and widen phis.
853 unsigned NumLanes = VF.getFixedValue();
854 SmallVector<VPInstruction *> BuildVectors;
855 for (auto &R : FirstLaneExiting->phis()) {
856 auto *Phi = cast<VPPhi>(&R);
858 continue;
859
860 Type *ScalarTy = Phi->getScalarType();
861 VPValue *Poison = Plan.getPoison(ScalarTy);
862 SmallVector<VPValue *> BVOps(NumLanes, Poison);
863 auto *BV = new VPInstruction(VPInstruction::BuildVector, BVOps);
864 BuildVectors.push_back(BV);
865 Phi->replaceAllUsesWith(BV);
866 BV->setOperand(0, Phi);
867 BV->insertBefore(Successor->getFirstNonPhi());
868 }
869
870 // Clone converted blocks for remaining lanes and process each in reverse
871 // order, connecting each lane's Exiting block to the subsequent lane's entry.
872 VPBlockBase *NextLaneEntry = Successor;
873 for (int Lane = NumLanes - 1; Lane > 0; --Lane) {
874 const auto &[CurrentLaneEntry, CurrentLaneExiting] =
875 VPBlockUtils::cloneFrom(FirstLaneEntry);
876 for (VPBlockBase *VPB : vp_depth_first_shallow(CurrentLaneEntry))
877 VPB->setParent(ParentRegion);
878 processLaneForReplicateRegion(Plan, IdxTy, Lane,
879 cast<VPBasicBlock>(FirstLaneEntry),
880 cast<VPBasicBlock>(CurrentLaneEntry));
881 VPBlockUtils::connectBlocks(CurrentLaneExiting, NextLaneEntry);
882 NextLaneEntry = CurrentLaneEntry;
883 }
884
885 // Connect Predecessor to FirstLaneEntry, and FirstLaneRegionExit to
886 // NextLaneEntry which is the second lane region entry. The latter is
887 // done last so that earlier clonings from FirstLaneEntry stop at
888 // FirstLaneExiting.
889 VPBlockUtils::connectBlocks(Predecessor, FirstLaneEntry);
890 VPBlockUtils::connectBlocks(FirstLaneExiting, NextLaneEntry);
891
892 // Fold BuildVector fed by scalar phis into VPWidenPHIRecipes with
893 // InsertElement per lane.
894 // TODO: check if this folding should be dropped.
895 for (VPInstruction *BV : BuildVectors) {
896 assert(BV->getNumOperands() == NumLanes &&
897 "BuildVector must have one operand per lane");
898 for (const auto &[Idx, Op] : enumerate(BV->operands())) {
899 auto *ScalarPhi = cast<VPPhi>(Op);
900 auto DL = ScalarPhi->getDebugLoc();
901 auto *PredOp = cast<VPSingleDefRecipe>(ScalarPhi->getOperand(1));
902 VPValue *Poison = ScalarPhi->getOperand(0);
903 VPValue *PrevVal = Idx == 0 ? Poison : BV->getOperand(Idx - 1);
904 auto Builder = VPBuilder::getToInsertAfter(PredOp->getDefiningRecipe());
905 auto *Insert = Builder.createNaryOp(
906 Instruction::InsertElement,
907 {PrevVal, PredOp, Plan.getConstantInt(64, Idx)}, DL);
908 Builder.setInsertPoint(ScalarPhi);
909 auto *NewPhi = Builder.createWidenPhi({PrevVal, Insert}, DL);
910 ScalarPhi->replaceAllUsesWith(NewPhi);
911 ScalarPhi->eraseFromParent();
912 }
913 BV->replaceAllUsesWith(BV->getOperand(NumLanes - 1));
914 BV->eraseFromParent();
915 }
916}
917
918/// Collect and dissolve all replicate regions in the vector loop, replicating
919/// their blocks and recipes for each lane of \p VF.
921 Type *IdxTy) {
922 // Collect all replicate regions before modifying the CFG.
923 SmallVector<VPRegionBlock *> ReplicateRegions;
926 if (Region->isReplicator())
927 ReplicateRegions.push_back(Region);
928 }
929
930 assert((ReplicateRegions.empty() || !VF.isScalable()) &&
931 "cannot replicate across scalable VFs");
932
933 // Dissolve replicate regions by replicating their blocks for each lane.
934 // Traversing regions in reverse ensures that the successor of every region
935 // being processed is a basic-block, rather than another region.
936 for (VPRegionBlock *Region : reverse(ReplicateRegions))
937 dissolveReplicateRegion(Region, VF, Plan, IdxTy);
938
940}
941
943 Type *IdxTy = IntegerType::get(
945
946 if (Plan.hasScalarVFOnly()) {
947 // When Plan is only unrolled by UF, replicating by VF amounts to dissolving
948 // replicate regions.
949 replicateReplicateRegionsByVF(Plan, VF, IdxTy);
950 return;
951 }
952
953 // Visit all VPBBs outside the loop region and directly inside the top-level
954 // loop region.
955 auto VPBBsOutsideLoopRegion = VPBlockUtils::blocksOnly<VPBasicBlock>(
957 auto VPBBsInsideLoopRegion = VPBlockUtils::blocksOnly<VPBasicBlock>(
959 auto VPBBsToUnroll =
960 concat<VPBasicBlock *>(VPBBsOutsideLoopRegion, VPBBsInsideLoopRegion);
961 // A mapping of current VPValue definitions to collections of new VPValues
962 // defined per lane. Serves to hook-up potential users of current VPValue
963 // definition that are replicated-per-VF later.
965 // The removal of current recipes being replaced by new ones needs to be
966 // delayed after Def2LaneDefs is no longer in use.
968 for (VPBasicBlock *VPBB : VPBBsToUnroll) {
969 for (VPRecipeBase &R : make_early_inc_range(*VPBB)) {
971 continue;
972
973 auto *DefR = cast<VPSingleDefRecipe>(&R);
974 VPBuilder Builder(DefR);
975 if (DefR->user_empty()) {
976 // Create single-scalar version of DefR for all lanes.
977 for (unsigned I = 0; I != VF.getKnownMinValue(); ++I)
978 cloneForLane(Plan, Builder, IdxTy, DefR, VPLane(I), Def2LaneDefs);
979 DefR->eraseFromParent();
980 continue;
981 }
982 /// Create single-scalar version of DefR for all lanes.
983 SmallVector<VPValue *> LaneDefs;
984 for (unsigned I = 0; I != VF.getKnownMinValue(); ++I)
985 LaneDefs.push_back(
986 cloneForLane(Plan, Builder, IdxTy, DefR, VPLane(I), Def2LaneDefs));
987
988 Def2LaneDefs[DefR] = LaneDefs;
989 // Pack the lanes for vector users.
991 DefR->replaceUsesWithIf(
992 Builder.createNaryOp(VPInstruction::BuildVector, LaneDefs),
993 [DefR](VPUser *U) { return !U->usesScalars(DefR); });
994 }
995 /// Users that only demand the first lane can use the definition for lane
996 /// 0. If DefR is a single scalar, all lanes are equal and all scalar
997 /// users can use lane 0.
998 bool IsSingleScalar = vputils::isSingleScalar(DefR);
999 DefR->replaceUsesWithIf(LaneDefs[0], [DefR, IsSingleScalar](VPUser *U) {
1000 if (U->usesFirstLaneOnly(DefR) ||
1001 (IsSingleScalar && U->usesScalars(DefR)))
1002 return true;
1003 auto *VPI = dyn_cast<VPInstruction>(U);
1004 return VPI && Instruction::isCast(VPI->getOpcode());
1005 });
1006 ToRemove.push_back(DefR);
1007 }
1008 }
1009
1010 replicateReplicateRegionsByVF(Plan, VF, IdxTy);
1011 // Replace the lane extracts created when dissolving replicate regions.
1012 for (VPSingleDefRecipe *DefR : reverse(ToRemove)) {
1013 for (VPUser *U : to_vector(DefR->users())) {
1014 uint64_t Lane;
1015 [[maybe_unused]] bool Match =
1017 assert(Match && "unexpected remaining user");
1018 auto *Ext = cast<VPInstruction>(U);
1019 Ext->replaceAllUsesWith(Def2LaneDefs.at(DefR)[Lane]);
1020 Ext->eraseFromParent();
1021 }
1022 DefR->eraseFromParent();
1023 }
1024}
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:480
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:1187
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:811
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:793
constexpr bool isScalar() const
Exactly one element.
Definition TypeSize.h:317
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:76
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:365
BlockT * getEntry() const
Get the entry BasicBlock of the Region.
Definition RegionInfo.h:323
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:4494
RecipeListTy::iterator iterator
Instruction iterators...
Definition VPlan.h:4525
iterator_range< iterator > phis()
Returns an iterator range over the PHI-like recipes in the block.
Definition VPlan.h:4588
VPBlockBase is the building block of the Hierarchical Control-Flow Graph.
Definition VPlan.h:99
const VPBasicBlock * getEntryBasicBlock() const
Definition VPlan.cpp:183
void setParent(VPRegionBlock *P)
Definition VPlan.h:207
VPBlockBase * getSingleSuccessor() const
Definition VPlan.h:237
static auto blocksAs(T &&Range)
Return an iterator range over Range with each block cast to BlockTy.
Definition VPlanUtils.h:448
static void connectBlocks(VPBlockBase *From, VPBlockBase *To, unsigned PredIdx=-1u, unsigned SuccIdx=-1u)
Connect VPBlockBases From and To bi-directionally.
Definition VPlanUtils.h:375
static void disconnectBlocks(VPBlockBase *From, VPBlockBase *To)
Disconnect VPBlockBases From and To bi-directionally.
Definition VPlanUtils.h:393
static void insertBlockBefore(VPBlockBase *NewBlock, VPBlockBase *BlockPtr)
Insert disconnected block NewBlock before Blockptr.
Definition VPlanUtils.h:342
static auto blocksOnly(T &&Range)
Return an iterator range over Range which only includes BlockTy blocks.
Definition VPlanUtils.h:441
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:656
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:562
ArrayRef< VPRecipeValue * > definedValues()
Returns an ArrayRef of the values defined by the VPDef.
Definition VPlanValue.h:572
BasicBlock * getIRBasicBlock() const
Definition VPlan.h:4677
Class to record and manage LLVM IR flags.
Definition VPlan.h:685
This is a concrete Recipe that models a single VPlan-level instruction.
Definition VPlan.h:1324
@ WideIVStep
Scale the first operand (vector step) by the second operand (scalar-step).
Definition VPlan.h:1447
@ ReductionStartVector
Start vector for reductions with 3 operands: the original start value, the identity value for the red...
Definition VPlan.h:1425
@ BuildVector
Creates a fixed-width vector containing all operands.
Definition VPlan.h:1375
@ CanonicalIVIncrementForPart
Definition VPlan.h:1360
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:406
DebugLoc getDebugLoc() const
Returns the debug location of the recipe.
Definition VPlan.h:550
VPRegionBlock represents a collection of VPBasicBlocks and VPRegionBlocks which form a Single-Entry-S...
Definition VPlan.h:4725
VPRegionBlock * clone() override
Clone all blocks in the single-entry single-exit region of the block and their recipes without updati...
Definition VPlan.cpp:713
const VPBlockBase * getEntry() const
Definition VPlan.h:4769
bool isReplicator() const
An indicator whether this region is to generate multiple replicated instances of output IR correspond...
Definition VPlan.h:4801
Type * getCanonicalIVType() const
Return the type of the canonical IV for loop regions.
Definition VPlan.h:4853
A recipe for handling phi nodes of integer and floating-point inductions, producing their scalar valu...
Definition VPlan.h:4326
void setStartIndex(VPValue *StartIndex)
Set or add the StartIndex operand.
Definition VPlan.h:4370
VPValue * getStartIndex() const
Return the StartIndex, or null if known to be zero, valid only after unrolling.
Definition VPlan.h:4365
VPValue * getVFValue() const
Return the number of scalars to produce per unroll part, used to compute StartIndex during unrolling.
Definition VPlan.h:4361
VPSingleDefRecipe is a base class for recipes that model a sequence of one or more output IR that def...
Definition VPlan.h:608
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:396
operand_range operands()
Definition VPlanValue.h:472
VPValue * getOperand(unsigned N) const
Definition VPlanValue.h:437
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:142
void replaceAllUsesWith(VPValue *New)
Definition VPlan.cpp:1475
VPlan models a candidate for vectorization, encoding various decisions take to produce efficient outp...
Definition VPlan.h:4912
const DataLayout & getDataLayout() const
Definition VPlan.h:5113
LLVMContext & getContext() const
Definition VPlan.h:5109
VPBasicBlock * getEntry()
Definition VPlan.h:5004
VPValue * getTripCount() const
The trip count of the original loop.
Definition VPlan.h:5076
VPIRValue * getPoison(Type *Ty)
Return a VPIRValue wrapping a poison value of type Ty.
Definition VPlan.h:5236
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:5185
VPIRValue * getZero(Type *Ty)
Return a VPIRValue wrapping the null value of type Ty.
Definition VPlan.h:5211
LLVM_ABI_FOR_TEST VPRegionBlock * getVectorLoopRegion()
Returns the VPRegionBlock of the vector loop.
Definition VPlan.cpp:1065
VPSymbolicValue & getUF()
Returns the UF of the vector loop region.
Definition VPlan.h:5104
bool hasScalarVFOnly() const
Definition VPlan.h:5153
VPIRBasicBlock * getScalarHeader() const
Return the VPIRBasicBlock wrapping the header of the scalar loop.
Definition VPlan.h:5066
VPSymbolicValue & getVF()
Returns the VF of the vector loop region.
Definition VPlan.h:5100
void setUF(unsigned UF)
Definition VPlan.h:5168
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:5219
constexpr ScalarTy getFixedValue() const
Definition TypeSize.h:201
constexpr bool isScalable() const
Returns whether the quantity is scaled by a runtime quantity (vscale).
Definition TypeSize.h:169
constexpr ScalarTy getKnownMinValue() const
Returns the minimum value this quantity can represent.
Definition TypeSize.h:166
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)
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 by all users.
bool onlyFirstLaneUsed(const VPValue *Def)
Returns true if only the first lane of Def is used by all users.
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:69
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...