LLVM 24.0.0git
VPlanTransforms.cpp
Go to the documentation of this file.
1//===-- VPlanTransforms.cpp - Utility VPlan to VPlan transforms -----------===//
2//
3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6//
7//===----------------------------------------------------------------------===//
8///
9/// \file
10/// This file implements a set of utility VPlan to VPlan transformations.
11///
12//===----------------------------------------------------------------------===//
13
14#include "VPlanTransforms.h"
15#include "VPRecipeBuilder.h"
16#include "VPlan.h"
17#include "VPlanAnalysis.h"
18#include "VPlanCFG.h"
19#include "VPlanDominatorTree.h"
20#include "VPlanHelpers.h"
21#include "VPlanPatternMatch.h"
22#include "VPlanUtils.h"
23#include "VPlanVerifier.h"
24#include "llvm/ADT/APInt.h"
26#include "llvm/ADT/STLExtras.h"
27#include "llvm/ADT/SetVector.h"
29#include "llvm/ADT/TypeSwitch.h"
31#include "llvm/Analysis/Loads.h"
38#include "llvm/IR/Intrinsics.h"
39#include "llvm/IR/MDBuilder.h"
40#include "llvm/IR/Metadata.h"
45
46using namespace llvm;
47using namespace VPlanPatternMatch;
48using namespace SCEVPatternMatch;
49
51 VPlan &Plan, const TargetLibraryInfo &TLI) {
52
54 Plan.getVectorLoopRegion());
56 // Skip blocks outside region
57 if (!VPBB->getParent())
58 break;
59 VPRecipeBase *Term = VPBB->getTerminator();
60 auto EndIter = Term ? Term->getIterator() : VPBB->end();
61 // Introduce each ingredient into VPlan.
62 for (VPRecipeBase &Ingredient :
63 make_early_inc_range(make_range(VPBB->begin(), EndIter))) {
64
65 VPValue *VPV = Ingredient.getVPSingleValue();
66 if (!VPV->getUnderlyingValue())
67 continue;
68
70
71 // Atomic accesses and fences have ordering/atomicity semantics that
72 // cannot be preserved by lane-wise widening.
74 return false;
75
76 VPRecipeBase *NewRecipe = nullptr;
77 if (auto *PhiR = dyn_cast<VPPhi>(&Ingredient)) {
78 auto *Phi = cast<PHINode>(PhiR->getUnderlyingValue());
79 NewRecipe = new VPWidenPHIRecipe(PhiR->operands(), PhiR->getDebugLoc(),
80 Phi->getName());
81 } else if (auto *VPI = dyn_cast<VPInstruction>(&Ingredient)) {
82 assert(!isa<PHINode>(Inst) && "phis should be handled above");
83 // Create VPWidenMemoryRecipe for loads and stores.
84 if (LoadInst *Load = dyn_cast<LoadInst>(Inst)) {
85 NewRecipe = new VPWidenLoadRecipe(
86 *Load, Ingredient.getOperand(0), nullptr /*Mask*/,
87 false /*Consecutive*/, *VPI, Ingredient.getDebugLoc());
88 } else if (StoreInst *Store = dyn_cast<StoreInst>(Inst)) {
89 NewRecipe = new VPWidenStoreRecipe(
90 *Store, Ingredient.getOperand(1), Ingredient.getOperand(0),
91 nullptr /*Mask*/, false /*Consecutive*/, *VPI,
92 Ingredient.getDebugLoc());
94 NewRecipe = new VPWidenGEPRecipe(GEP->getSourceElementType(),
95 Ingredient.operands(), *VPI,
96 Ingredient.getDebugLoc(), GEP);
97 } else if (CallInst *CI = dyn_cast<CallInst>(Inst)) {
98 Intrinsic::ID VectorID = getVectorIntrinsicIDForCall(CI, &TLI);
99 if (VectorID == Intrinsic::not_intrinsic)
100 return false;
101
102 // The noalias.scope.decl intrinsic declares a noalias scope that
103 // is valid for a single iteration. Emitting it as a single-scalar
104 // replicate would incorrectly extend the scope across multiple
105 // original iterations packed into one vector iteration.
106 // FIXME: If we want to vectorize this loop, then we have to drop
107 // all the associated !alias.scope and !noalias.
108 if (VectorID == Intrinsic::experimental_noalias_scope_decl)
109 return false;
110
111 // These intrinsics are recognized by getVectorIntrinsicIDForCall
112 // but are not widenable. Emit them as replicate instead of widening.
113 if (VectorID == Intrinsic::assume ||
114 VectorID == Intrinsic::lifetime_end ||
115 VectorID == Intrinsic::lifetime_start ||
116 VectorID == Intrinsic::sideeffect ||
117 VectorID == Intrinsic::pseudoprobe) {
118 // If the operand of llvm.assume holds before vectorization, it will
119 // also hold per lane.
120 // llvm.pseudoprobe requires to be duplicated per lane for accurate
121 // sample count.
122 const bool IsSingleScalar = VectorID != Intrinsic::assume &&
123 VectorID != Intrinsic::pseudoprobe;
124 NewRecipe = new VPReplicateRecipe(CI, Ingredient.operands(),
125 /*IsSingleScalar=*/IsSingleScalar,
126 /*Mask=*/nullptr, *VPI, *VPI,
127 Ingredient.getDebugLoc());
128 } else {
129 NewRecipe = new VPWidenIntrinsicRecipe(
130 *CI, VectorID, drop_end(Ingredient.operands()), CI->getType(),
131 VPIRFlags(*CI), *VPI, CI->getDebugLoc());
132 }
133 } else if (auto *CI = dyn_cast<CastInst>(Inst)) {
134 NewRecipe = new VPWidenCastRecipe(
135 CI->getOpcode(), Ingredient.getOperand(0), CI->getType(), CI,
136 VPIRFlags(*CI), VPIRMetadata(*CI));
137 } else {
138 NewRecipe = new VPWidenRecipe(*Inst, Ingredient.operands(), *VPI,
139 *VPI, Ingredient.getDebugLoc());
140 }
141 } else {
143 "inductions must be created earlier");
144 continue;
145 }
146
147 NewRecipe->insertBefore(&Ingredient);
148 if (NewRecipe->getNumDefinedValues() == 1)
149 VPV->replaceAllUsesWith(NewRecipe->getVPSingleValue());
150 else
151 assert(NewRecipe->getNumDefinedValues() == 0 &&
152 "Only recpies with zero or one defined values expected");
153 Ingredient.eraseFromParent();
154 }
155 }
156 return true;
157}
158
159/// Helper for extra no-alias checks via known-safe recipe and SCEV.
162 VPReplicateRecipe &GroupLeader;
163 PredicatedScalarEvolution *PSE = nullptr;
164 const Loop *L = nullptr;
165
166 // Return true if \p A and \p B are known to not alias for all VFs in the
167 // plan, checked via the distance between the accesses
168 bool isNoAliasViaDistance(VPReplicateRecipe *A, VPReplicateRecipe *B) const {
169 if (A->getOpcode() != Instruction::Store ||
170 B->getOpcode() != Instruction::Store)
171 return false;
172
173 if (!PSE || !L)
174 return A == B;
175
176 VPValue *AddrA = A->getOperand(1);
177 const SCEV *SCEVA = vputils::getSCEVExprForVPValue(AddrA, *PSE, L);
178 VPValue *AddrB = B->getOperand(1);
179 const SCEV *SCEVB = vputils::getSCEVExprForVPValue(AddrB, *PSE, L);
181 return false;
182
183 const APInt *Distance;
184 ScalarEvolution &SE = *PSE->getSE();
185 if (!match(SE.getMinusSCEV(SCEVA, SCEVB), m_scev_APInt(Distance)))
186 return false;
187
188 const DataLayout &DL = SE.getDataLayout();
189 Type *TyA = A->getOperand(0)->getScalarType();
190 uint64_t SizeA = DL.getTypeStoreSize(TyA);
191 Type *TyB = B->getOperand(0)->getScalarType();
192 uint64_t SizeB = DL.getTypeStoreSize(TyB);
193
194 // Use the maximum store size to ensure no overlap from either direction.
195 // Currently only handles fixed sizes, as it is only used for
196 // replicating VPReplicateRecipes.
197 uint64_t MaxStoreSize = std::max(SizeA, SizeB);
198
199 auto VFs = B->getParent()->getPlan()->vectorFactors();
201 if (MaxVF.isScalable())
202 return false;
203 return Distance->abs().uge(
204 MaxVF.multiplyCoefficientBy(MaxStoreSize).getFixedValue());
205 }
206
207public:
210 const Loop &L)
211 : ExcludeRecipes(ExcludeRecipes.begin(), ExcludeRecipes.end()),
212 GroupLeader(GroupLeader), PSE(&PSE), L(&L) {}
213
214 SinkStoreInfo(VPReplicateRecipe &GroupLeader) : GroupLeader(GroupLeader) {}
215
216 /// Return true if \p R should be skipped during alias checking, either
217 /// because it's in the exclude set or because no-alias can be proven via
218 /// SCEV.
219 bool shouldSkip(VPRecipeBase &R) const {
221 return ExcludeRecipes.contains(Store) ||
222 (Store && isNoAliasViaDistance(Store, &GroupLeader));
223 }
224};
225
226/// Check if a memory operation doesn't alias with memory operations using
227/// scoped noalias metadata, in blocks in the single-successor chain between \p
228/// FirstBB and \p LastBB. If \p SinkInfo is std::nullopt, only recipes that may
229/// write to memory are checked (for load hoisting). Otherwise recipes that both
230/// read and write memory are checked, and SCEV is used to prove no-alias
231/// between the group leader and other replicate recipes (for store sinking).
232static bool
234 VPBasicBlock *FirstBB, VPBasicBlock *LastBB,
235 std::optional<SinkStoreInfo> SinkInfo = {}) {
236 bool CheckReads = SinkInfo.has_value();
237 for (VPBasicBlock *VPBB :
239 for (VPRecipeBase &R : *VPBB) {
240 if (SinkInfo && SinkInfo->shouldSkip(R))
241 continue;
242
243 // Skip recipes that don't need checking.
244 if (!R.mayWriteToMemory() && !(CheckReads && R.mayReadFromMemory()))
245 continue;
246
248 if (!Loc)
249 // Conservatively assume aliasing for memory operations without
250 // location.
251 return false;
252
254 return false;
255 }
256 }
257 return true;
258}
259
260/// Get the value type of the replicate load or store. \p IsLoad indicates
261/// whether it is a load.
263 return (IsLoad ? R : R->getOperand(0))->getScalarType();
264}
265
266/// Collect either replicated Loads or Stores grouped by their address SCEV and
267/// their load-store type, in a deep-traversal of the vector loop region in \p
268/// Plan.
269template <unsigned Opcode>
272 VPlan &Plan, PredicatedScalarEvolution &PSE, const Loop *L,
273 function_ref<bool(VPReplicateRecipe *)> FilterFn) {
274 static_assert(Opcode == Instruction::Load || Opcode == Instruction::Store,
275 "Only Load and Store opcodes supported");
276 constexpr bool IsLoad = (Opcode == Instruction::Load);
279 RecipesByAddressAndType;
282 for (VPRecipeBase &R : *VPBB) {
283 auto *RepR = dyn_cast<VPReplicateRecipe>(&R);
284 if (!RepR || RepR->getOpcode() != Opcode || !FilterFn(RepR))
285 continue;
286
287 // For loads, operand 0 is address; for stores, operand 1 is address.
288 VPValue *Addr = RepR->getOperand(IsLoad ? 0 : 1);
289 const Type *LoadStoreTy = getLoadStoreValueType(RepR, IsLoad);
290 const SCEV *AddrSCEV = vputils::getSCEVExprForVPValue(Addr, PSE, L);
291 if (!isa<SCEVCouldNotCompute>(AddrSCEV))
292 RecipesByAddressAndType[{AddrSCEV, LoadStoreTy}].push_back(RepR);
293 }
294 }
295 auto Groups = to_vector(RecipesByAddressAndType.values());
296 VPDominatorTree VPDT(Plan);
297 for (auto &Group : Groups) {
298 // Sort mem ops by dominance order, with earliest (most dominating) first.
300 return VPDT.properlyDominates(A, B);
301 });
302 }
303 return Groups;
304}
305
306static bool sinkScalarOperands(VPlan &Plan) {
307 auto Iter = vp_depth_first_deep(Plan.getEntry());
308 bool ScalarVFOnly = Plan.hasScalarVFOnly();
309 bool Changed = false;
310
312 auto InsertIfValidSinkCandidate = [ScalarVFOnly, &WorkList](
313 VPBasicBlock *SinkTo, VPValue *Op) {
314 auto *Candidate =
315 dyn_cast_or_null<VPSingleDefRecipe>(Op->getDefiningRecipe());
316 if (!Candidate)
317 return;
318
319 // We only know how to sink VPReplicateRecipes and VPScalarIVStepsRecipes
320 // for now.
322 return;
323
324 if (Candidate->getParent() == SinkTo ||
325 vputils::cannotHoistOrSinkRecipe(*Candidate, /*Sinking=*/true))
326 return;
327
328 if (auto *RepR = dyn_cast<VPReplicateRecipe>(Candidate))
329 if (!ScalarVFOnly && RepR->isSingleScalar())
330 return;
331
332 WorkList.insert({SinkTo, Candidate});
333 };
334
335 // First, collect the operands of all recipes in replicate blocks as seeds for
336 // sinking.
338 VPBasicBlock *EntryVPBB = VPR->getEntryBasicBlock();
339 if (!VPR->isReplicator() || EntryVPBB->getSuccessors().size() != 2)
340 continue;
341 VPBasicBlock *VPBB = cast<VPBasicBlock>(EntryVPBB->getSuccessors().front());
342 if (VPBB->getSingleSuccessor() != VPR->getExitingBasicBlock())
343 continue;
344 for (auto &Recipe : *VPBB)
345 for (VPValue *Op : Recipe.operands())
346 InsertIfValidSinkCandidate(VPBB, Op);
347 }
348
349 // Try to sink each replicate or scalar IV steps recipe in the worklist.
350 for (unsigned I = 0; I != WorkList.size(); ++I) {
351 VPBasicBlock *SinkTo;
352 VPSingleDefRecipe *SinkCandidate;
353 std::tie(SinkTo, SinkCandidate) = WorkList[I];
354
355 // All recipe users of SinkCandidate must be in the same block SinkTo or all
356 // users outside of SinkTo must only use the first lane of SinkCandidate. In
357 // the latter case, we need to duplicate SinkCandidate.
358 auto UsersOutsideSinkTo =
359 make_filter_range(SinkCandidate->users(), [SinkTo](VPUser *U) {
360 return cast<VPRecipeBase>(U)->getParent() != SinkTo;
361 });
362 if (any_of(UsersOutsideSinkTo, [SinkCandidate](VPUser *U) {
363 return !U->usesFirstLaneOnly(SinkCandidate);
364 }))
365 continue;
366 bool NeedsDuplicating = !UsersOutsideSinkTo.empty();
367
368 if (NeedsDuplicating) {
369 if (ScalarVFOnly)
370 continue;
371 VPSingleDefRecipe *Clone;
372 if (auto *SinkCandidateRepR =
373 dyn_cast<VPReplicateRecipe>(SinkCandidate)) {
374 // TODO: Handle converting to uniform recipes as separate transform,
375 // then cloning should be sufficient here.
377 SinkCandidateRepR->getOpcode(), SinkCandidate->operands(),
378 /*Mask=*/nullptr, *SinkCandidateRepR, *SinkCandidateRepR,
379 SinkCandidate->getDebugLoc(), SinkCandidate->getUnderlyingInstr());
380 // TODO: add ".cloned" suffix to name of Clone's VPValue.
381 } else {
382 Clone = SinkCandidate->clone();
383 }
384
385 Clone->insertBefore(SinkCandidate);
386 SinkCandidate->replaceUsesWithIf(Clone, [SinkTo](VPUser &U, unsigned) {
387 return cast<VPRecipeBase>(&U)->getParent() != SinkTo;
388 });
389 }
390 SinkCandidate->moveBefore(*SinkTo, SinkTo->getFirstNonPhi());
391 for (VPValue *Op : SinkCandidate->operands())
392 InsertIfValidSinkCandidate(SinkTo, Op);
393 Changed = true;
394 }
395 return Changed;
396}
397
398/// If \p R is a region with a VPBranchOnMaskRecipe in the entry block, return
399/// the mask.
401 auto *EntryBB = dyn_cast<VPBasicBlock>(R->getEntry());
402 if (!EntryBB || EntryBB->size() != 1 ||
403 !isa<VPBranchOnMaskRecipe>(EntryBB->begin()))
404 return nullptr;
405
406 return cast<VPBranchOnMaskRecipe>(&*EntryBB->begin())->getOperand(0);
407}
408
409/// If \p R is a triangle region, return the 'then' block of the triangle.
411 auto *EntryBB = cast<VPBasicBlock>(R->getEntry());
412 if (EntryBB->getNumSuccessors() != 2)
413 return nullptr;
414
415 auto *Succ0 = dyn_cast<VPBasicBlock>(EntryBB->getSuccessors()[0]);
416 auto *Succ1 = dyn_cast<VPBasicBlock>(EntryBB->getSuccessors()[1]);
417 if (!Succ0 || !Succ1)
418 return nullptr;
419
420 if (Succ0->getNumSuccessors() + Succ1->getNumSuccessors() != 1)
421 return nullptr;
422 if (Succ0->getSingleSuccessor() == Succ1)
423 return Succ0;
424 if (Succ1->getSingleSuccessor() == Succ0)
425 return Succ1;
426 return nullptr;
427}
428
429// Merge replicate regions in their successor region, if a replicate region
430// is connected to a successor replicate region with the same predicate by a
431// single, empty VPBasicBlock.
433 SmallPtrSet<VPRegionBlock *, 4> TransformedRegions;
434
435 // Collect replicate regions followed by an empty block, followed by another
436 // replicate region with matching masks to process front. This is to avoid
437 // iterator invalidation issues while merging regions.
440 vp_depth_first_deep(Plan.getEntry()))) {
441 if (!Region1->isReplicator())
442 continue;
443 auto *MiddleBasicBlock =
444 dyn_cast_or_null<VPBasicBlock>(Region1->getSingleSuccessor());
445 if (!MiddleBasicBlock || !MiddleBasicBlock->empty())
446 continue;
447
448 auto *Region2 =
449 dyn_cast_or_null<VPRegionBlock>(MiddleBasicBlock->getSingleSuccessor());
450 if (!Region2 || !Region2->isReplicator())
451 continue;
452
453 VPValue *Mask1 = getPredicatedMask(Region1);
454 VPValue *Mask2 = getPredicatedMask(Region2);
455 if (!Mask1 || Mask1 != Mask2)
456 continue;
457
458 assert(Mask1 && Mask2 && "both region must have conditions");
459 WorkList.push_back(Region1);
460 }
461
462 // Move recipes from Region1 to its successor region, if both are triangles.
463 for (VPRegionBlock *Region1 : WorkList) {
464 if (TransformedRegions.contains(Region1))
465 continue;
466 auto *MiddleBasicBlock = cast<VPBasicBlock>(Region1->getSingleSuccessor());
467 auto *Region2 = cast<VPRegionBlock>(MiddleBasicBlock->getSingleSuccessor());
468
469 VPBasicBlock *Then1 = getPredicatedThenBlock(Region1);
470 VPBasicBlock *Then2 = getPredicatedThenBlock(Region2);
471 if (!Then1 || !Then2)
472 continue;
473
474 // Note: No fusion-preventing memory dependencies are expected in either
475 // region. Such dependencies should be rejected during earlier dependence
476 // checks, which guarantee accesses can be re-ordered for vectorization.
477 //
478 // Move recipes to the successor region.
479 for (VPRecipeBase &ToMove : make_early_inc_range(reverse(*Then1)))
480 ToMove.moveBefore(*Then2, Then2->getFirstNonPhi());
481
482 auto *Merge1 = cast<VPBasicBlock>(Then1->getSingleSuccessor());
483 auto *Merge2 = cast<VPBasicBlock>(Then2->getSingleSuccessor());
484
485 // Move VPPredInstPHIRecipes from the merge block to the successor region's
486 // merge block. Update all users inside the successor region to use the
487 // original values.
488 for (VPRecipeBase &Phi1ToMove : make_early_inc_range(reverse(*Merge1))) {
489 VPValue *PredInst1 =
490 cast<VPPredInstPHIRecipe>(&Phi1ToMove)->getOperand(0);
491 VPValue *Phi1ToMoveV = Phi1ToMove.getVPSingleValue();
492 Phi1ToMoveV->replaceUsesWithIf(PredInst1, [Then2](VPUser &U, unsigned) {
493 return cast<VPRecipeBase>(&U)->getParent() == Then2;
494 });
495
496 // Remove phi recipes that are unused after merging the regions.
497 if (Phi1ToMove.getVPSingleValue()->user_empty()) {
498 Phi1ToMove.eraseFromParent();
499 continue;
500 }
501 Phi1ToMove.moveBefore(*Merge2, Merge2->begin());
502 }
503
504 // Remove the dead recipes in Region1's entry block.
505 for (VPRecipeBase &R :
506 make_early_inc_range(reverse(*Region1->getEntryBasicBlock())))
507 R.eraseFromParent();
508
509 // Finally, remove the first region.
510 for (VPBlockBase *Pred : make_early_inc_range(Region1->getPredecessors())) {
511 VPBlockUtils::disconnectBlocks(Pred, Region1);
512 VPBlockUtils::connectBlocks(Pred, MiddleBasicBlock);
513 }
514 VPBlockUtils::disconnectBlocks(Region1, MiddleBasicBlock);
515 TransformedRegions.insert(Region1);
516 }
517
518 return !TransformedRegions.empty();
519}
520
522 VPRegionBlock *ParentRegion,
523 VPlan &Plan) {
524 Instruction *Instr = PredRecipe->getUnderlyingInstr();
525 // Build the triangular if-then region.
526 std::string RegionName = (Twine("pred.") + Instr->getOpcodeName()).str();
527 assert(Instr->getParent() && "Predicated instruction not in any basic block");
528 auto *BlockInMask = PredRecipe->getMask();
529 auto *MaskDef = BlockInMask->getDefiningRecipe();
530 auto *BOMRecipe = new VPBranchOnMaskRecipe(
531 BlockInMask, MaskDef ? MaskDef->getDebugLoc() : DebugLoc::getUnknown());
532 auto *Entry =
533 Plan.createVPBasicBlock(Twine(RegionName) + ".entry", BOMRecipe);
534
535 // Replace predicated replicate recipe with a replicate recipe without a
536 // mask but in the replicate region.
537 auto *RecipeWithoutMask = new VPReplicateRecipe(
538 PredRecipe->getUnderlyingInstr(), PredRecipe->operandsWithoutMask(),
539 PredRecipe->isSingleScalar(), nullptr /*Mask*/, *PredRecipe, *PredRecipe,
540 PredRecipe->getDebugLoc());
541 auto *Pred =
542 Plan.createVPBasicBlock(Twine(RegionName) + ".if", RecipeWithoutMask);
543 auto *Exiting = Plan.createVPBasicBlock(Twine(RegionName) + ".continue");
545 Plan.createReplicateRegion(Entry, Exiting, RegionName);
546
547 // Note: first set Entry as region entry and then connect successors starting
548 // from it in order, to propagate the "parent" of each VPBasicBlock.
549 Region->setParent(ParentRegion);
550 VPBlockUtils::insertTwoBlocksAfter(Pred, Exiting, Entry);
551 VPBlockUtils::connectBlocks(Pred, Exiting);
552
553 if (!PredRecipe->user_empty()) {
554 auto *PHIRecipe = new VPPredInstPHIRecipe(RecipeWithoutMask,
555 RecipeWithoutMask->getDebugLoc());
556 Exiting->appendRecipe(PHIRecipe);
557 PredRecipe->replaceAllUsesWith(PHIRecipe);
558 }
559 PredRecipe->eraseFromParent();
560 return Region;
561}
562
563static void addReplicateRegions(VPlan &Plan) {
566 vp_depth_first_deep(Plan.getEntry()))) {
567 for (VPRecipeBase &R : *VPBB)
568 if (auto *RepR = dyn_cast<VPReplicateRecipe>(&R)) {
569 if (RepR->isPredicated())
570 WorkList.push_back(RepR);
571 }
572 }
573
574 unsigned BBNum = 0;
575 for (VPReplicateRecipe *RepR : WorkList) {
576 VPBasicBlock *CurrentBlock = RepR->getParent();
577 VPBasicBlock *SplitBlock = CurrentBlock->splitAt(RepR->getIterator());
578
579 BasicBlock *OrigBB = RepR->getUnderlyingInstr()->getParent();
580 SplitBlock->setName(
581 OrigBB->hasName() ? OrigBB->getName() + "." + Twine(BBNum++) : "");
582 // Record predicated instructions for above packing optimizations.
584 createReplicateRegion(RepR, CurrentBlock->getParent(), Plan);
586
587 VPRegionBlock *ParentRegion = Region->getParent();
588 if (ParentRegion && ParentRegion->getExiting() == CurrentBlock)
589 ParentRegion->setExiting(SplitBlock);
590 }
591}
592
596 vp_depth_first_deep(Plan.getEntry()))) {
597 // Don't fold the blocks in the skeleton of the Plan into their single
598 // predecessors for now.
599 // TODO: Remove restriction once more of the skeleton is modeled in VPlan.
600 if (!VPBB->getParent())
601 continue;
602 auto *PredVPBB =
603 dyn_cast_or_null<VPBasicBlock>(VPBB->getSinglePredecessor());
604 if (!PredVPBB || PredVPBB->getNumSuccessors() != 1 ||
605 isa<VPIRBasicBlock>(PredVPBB))
606 continue;
607 WorkList.push_back(VPBB);
608 }
609
610 for (VPBasicBlock *VPBB : WorkList) {
611 VPBasicBlock *PredVPBB = cast<VPBasicBlock>(VPBB->getSinglePredecessor());
612 for (VPRecipeBase &R : make_early_inc_range(*VPBB))
613 R.moveBefore(*PredVPBB, PredVPBB->end());
614 VPBlockUtils::disconnectBlocks(PredVPBB, VPBB);
615 auto *ParentRegion = VPBB->getParent();
616 if (ParentRegion && ParentRegion->getExiting() == VPBB)
617 ParentRegion->setExiting(PredVPBB);
618 VPBlockUtils::transferSuccessors(VPBB, PredVPBB);
619 // VPBB is now dead and will be cleaned up when the plan gets destroyed.
620 }
621 return !WorkList.empty();
622}
623
625 // Convert masked VPReplicateRecipes to if-then region blocks.
627
628 bool ShouldSimplify = true;
629 while (ShouldSimplify) {
630 ShouldSimplify = sinkScalarOperands(Plan);
631 ShouldSimplify |= mergeReplicateRegionsIntoSuccessors(Plan);
632 ShouldSimplify |= mergeBlocksIntoPredecessors(Plan);
633 }
634}
635
636/// Remove redundant casts of inductions.
637///
638/// Such redundant casts are casts of induction variables that can be ignored,
639/// because we already proved that the casted phi is equal to the uncasted phi
640/// in the vectorized loop. There is no need to vectorize the cast - the same
641/// value can be used for both the phi and casts in the vector loop.
643 for (auto &Phi : Plan.getVectorLoopRegion()->getEntryBasicBlock()->phis()) {
645 if (!IV || IV->getTruncInst())
646 continue;
647
648 // A sequence of IR Casts has potentially been recorded for IV, which
649 // *must be bypassed* when the IV is vectorized, because the vectorized IV
650 // will produce the desired casted value. This sequence forms a def-use
651 // chain and is provided in reverse order, ending with the cast that uses
652 // the IV phi. Search for the recipe of the last cast in the chain and
653 // replace it with the original IV. Note that only the final cast is
654 // expected to have users outside the cast-chain and the dead casts left
655 // over will be cleaned up later.
656 ArrayRef<Instruction *> Casts = IV->getInductionDescriptor().getCastInsts();
657 VPValue *FindMyCast = IV;
658 for (Instruction *IRCast : reverse(Casts)) {
659 VPSingleDefRecipe *FoundUserCast = nullptr;
660 for (auto *U : FindMyCast->users()) {
661 auto *UserCast = dyn_cast<VPSingleDefRecipe>(U);
662 if (UserCast && UserCast->getUnderlyingValue() == IRCast) {
663 FoundUserCast = UserCast;
664 break;
665 }
666 }
667 // A cast recipe in the chain may have been removed by earlier DCE.
668 if (!FoundUserCast)
669 break;
670 FindMyCast = FoundUserCast;
671 }
672 if (FindMyCast != IV)
673 FindMyCast->replaceAllUsesWith(IV);
674 }
675}
676
679 Instruction::BinaryOps InductionOpcode,
680 FPMathOperator *FPBinOp, Instruction *TruncI,
681 VPIRValue *StartV, VPValue *Step, DebugLoc DL,
682 VPBuilder &Builder) {
683 VPRegionBlock *LoopRegion = Plan.getVectorLoopRegion();
684 VPBasicBlock *HeaderVPBB = LoopRegion->getEntryBasicBlock();
685 VPValue *CanonicalIV = LoopRegion->getCanonicalIV();
686 VPSingleDefRecipe *BaseIV =
687 Builder.createDerivedIV(Kind, FPBinOp, StartV, CanonicalIV, Step);
688
689 // Truncate base induction if needed.
690 Type *ResultTy = BaseIV->getScalarType();
691 if (TruncI) {
692 Type *TruncTy = TruncI->getType();
693 assert(ResultTy->getScalarSizeInBits() > TruncTy->getScalarSizeInBits() &&
694 "Not truncating.");
695 assert(ResultTy->isIntegerTy() && "Truncation requires an integer type");
696 BaseIV = Builder.createScalarCast(Instruction::Trunc, BaseIV, TruncTy, DL);
697 ResultTy = TruncTy;
698 }
699
700 // Truncate step if needed.
701 Type *StepTy = Step->getScalarType();
702 if (ResultTy != StepTy) {
703 assert(StepTy->getScalarSizeInBits() > ResultTy->getScalarSizeInBits() &&
704 "Not truncating.");
705 assert(StepTy->isIntegerTy() && "Truncation requires an integer type");
706 auto *VecPreheader =
708 VPBuilder::InsertPointGuard Guard(Builder);
709 Builder.setInsertPoint(VecPreheader);
710 Step = Builder.createScalarCast(Instruction::Trunc, Step, ResultTy, DL);
711 }
712 return Builder.createScalarIVSteps(InductionOpcode, FPBinOp, BaseIV, Step,
713 &Plan.getVF(), DL);
714}
715
717 VPlan &Plan, ScalarEvolution &SE, const TargetTransformInfo &TTI,
719 const SmallPtrSetImpl<const Value *> &ValuesToIgnore) {
720 VPRegionBlock *LoopRegion = Plan.getVectorLoopRegion();
721 if (!LoopRegion)
722 return;
723
724 auto *WideCanIV =
726 if (!WideCanIV)
727 return;
728
729 Type *CanIVTy = LoopRegion->getCanonicalIVType();
730
731 // Replace the wide canonical IV with a scalar-iv-steps over the canonical
732 // IV.
733 if (Plan.hasScalarVFOnly() || vputils::onlyFirstLaneUsed(WideCanIV)) {
734 VPBuilder Builder(WideCanIV);
735 WideCanIV->replaceAllUsesWith(createScalarIVSteps(
736 Plan, InductionDescriptor::IK_IntInduction, Instruction::Add, nullptr,
737 nullptr, Plan.getZero(CanIVTy), Plan.getConstantInt(CanIVTy, 1),
738 WideCanIV->getDebugLoc(), Builder));
739 WideCanIV->eraseFromParent();
740 return;
741 }
742
743 if (vputils::onlyScalarValuesUsed(WideCanIV))
744 return;
745
746 // If a canonical VPWidenIntOrFpInductionRecipe already produces vector lanes
747 // in the header, reuse it instead of introducing another wide induction phi.
748 VPBasicBlock *Header = LoopRegion->getEntryBasicBlock();
749 for (VPRecipeBase &Phi : Header->phis()) {
751 if (!match(&Phi, m_CanonicalWidenIV(WidenIV)))
752 continue;
753 // The reused wide IV feeds the header mask, whose lanes may extend past
754 // the trip count; drop flags that only hold inside the scalar loop.
755 WidenIV->dropPoisonGeneratingFlags();
756 WideCanIV->replaceAllUsesWith(WidenIV);
757 WideCanIV->eraseFromParent();
758 return;
759 }
760
761 // Introduce a new VPWidenIntOrFpInductionRecipe if profitable.
762 auto *VecTy = VectorType::get(CanIVTy, VF);
763 InstructionCost BroadcastCost = TTI.getShuffleCost(
765 InstructionCost PHICost = TTI.getCFInstrCost(Instruction::PHI, CostKind);
766 if (PHICost > BroadcastCost)
767 return;
768
769 // Bail out if the additional wide induction phi increase the expected spill
770 // cost.
771 VPRegisterUsage UnrolledBase =
772 calculateRegisterUsageForPlan(Plan, VF, TTI, ValuesToIgnore)[0];
773 for (unsigned &NumUsers : make_second_range(UnrolledBase.MaxLocalUsers))
774 NumUsers *= UF;
775 unsigned RegClass = TTI.getRegisterClassForType(/*Vector=*/true, VecTy);
776 VPRegisterUsage Projected = UnrolledBase;
777 Projected.MaxLocalUsers[RegClass] += TTI.getRegUsageForType(VecTy);
778 if (Projected.spillCost(TTI, CostKind) >
779 UnrolledBase.spillCost(TTI, CostKind))
780 return;
781
784 VPValue *StepV = Plan.getConstantInt(CanIVTy, 1);
785 auto *NewWideIV = new VPWidenIntOrFpInductionRecipe(
786 /*IV=*/nullptr, Plan.getZero(CanIVTy), StepV, &Plan.getVF(), ID,
787 WideCanIV->getNoWrapFlags(), WideCanIV->getDebugLoc());
788 NewWideIV->insertBefore(&*Header->getFirstNonPhi());
789 WideCanIV->replaceAllUsesWith(NewWideIV);
790 WideCanIV->eraseFromParent();
791}
792
795 Plan.getEntry());
797 // The recipes in the block are processed in reverse order, to catch chains
798 // of dead recipes.
799 for (VPRecipeBase &R : make_early_inc_range(reverse(*VPBB))) {
800 if (vputils::isDeadRecipe(R)) {
801 R.eraseFromParent();
802 continue;
803 }
804
805 // Check if R is a dead VPPhi <-> update cycle and remove it.
806 VPValue *Start, *Incoming;
807 if (!match(&R, m_VPPhi(m_VPValue(Start), m_VPValue(Incoming))))
808 continue;
809 auto *PhiR = cast<VPPhi>(&R);
810 VPUser *PhiUser = PhiR->getSingleUser();
811 if (!PhiUser)
812 continue;
813 if (PhiUser != Incoming->getDefiningRecipe() ||
814 Incoming->getNumUsers() != 1)
815 continue;
816 PhiR->replaceAllUsesWith(Start);
817 PhiR->eraseFromParent();
818 Incoming->getDefiningRecipe()->eraseFromParent();
819 }
820 }
821}
822
823/// Scalarize a VPWidenPointerInductionRecipe by replacing it with a PtrAdd
824/// (IndStart, ScalarIVSteps (0, Step)). This is used when the recipe only
825/// generates scalar values.
826static VPValue *
828 VPlan &Plan, VPBuilder &Builder) {
830 VPIRValue *StartV = Plan.getZero(ID.getStep()->getType());
831 VPValue *StepV = PtrIV->getOperand(1);
833 Plan, InductionDescriptor::IK_IntInduction, Instruction::Add, nullptr,
834 nullptr, StartV, StepV, PtrIV->getDebugLoc(), Builder);
835
836 return Builder.createPtrAdd(PtrIV->getStartValue(), Steps,
837 PtrIV->getDebugLoc(), "next.gep");
838}
839
840/// Legalize VPWidenPointerInductionRecipe, by replacing it with a PtrAdd
841/// (IndStart, ScalarIVSteps (0, Step)) if only its scalar values are used, as
842/// VPWidenPointerInductionRecipe will generate vectors only. If some users
843/// require vectors while other require scalars, the scalar uses need to extract
844/// the scalars from the generated vectors (Note that this is different to how
845/// int/fp inductions are handled). Legalize extract-from-ends using uniform
846/// VPReplicateRecipe of wide inductions to use regular VPReplicateRecipe, so
847/// the correct end value is available. Also optimize
848/// VPWidenIntOrFpInductionRecipe, if any of its users needs scalar values, by
849/// providing them scalar steps built on the canonical scalar IV and update the
850/// original IV's users. This is an optional optimization to reduce the needs of
851/// vector extracts.
854 bool HasOnlyVectorVFs = !Plan.hasScalarVFOnly();
855 VPBuilder Builder(HeaderVPBB, HeaderVPBB->getFirstNonPhi());
856 for (VPRecipeBase &Phi : HeaderVPBB->phis()) {
857 auto *PhiR = dyn_cast<VPWidenInductionRecipe>(&Phi);
858 if (!PhiR)
859 continue;
860
861 // Try to narrow wide and replicating recipes to uniform recipes, based on
862 // VPlan analysis.
863 // TODO: Apply to all recipes in the future, to replace legacy uniformity
864 // analysis.
866 for (VPUser *U : reverse(Users)) {
867 auto *Def = dyn_cast<VPRecipeWithIRFlags>(U);
868 auto *RepR = dyn_cast<VPReplicateRecipe>(U);
869 // Skip recipes that shouldn't be narrowed.
870 if (!Def || !isa<VPReplicateRecipe, VPWidenRecipe>(Def) ||
871 Def->user_empty() || !Def->getUnderlyingValue() ||
872 (RepR && (RepR->isSingleScalar() || RepR->isPredicated())))
873 continue;
874
875 // Skip recipes that may have other lanes than their first used.
877 continue;
878
879 // TODO: Support scalarizing ExtractValue.
880 if (match(Def,
882 continue;
883
885 Def->getUnderlyingInstr()->getOpcode(), Def->operands(),
886 /*Mask=*/nullptr, *Def, {}, DebugLoc::getUnknown(),
887 Def->getUnderlyingInstr());
888 Clone->insertAfter(Def);
889 Def->replaceAllUsesWith(Clone);
890 }
891
892 // Replace wide pointer inductions which have only their scalars used by
893 // PtrAdd(IndStart, ScalarIVSteps (0, Step)).
894 if (auto *PtrIV = dyn_cast<VPWidenPointerInductionRecipe>(&Phi)) {
895 if (!Plan.hasScalarVFOnly() &&
896 !PtrIV->onlyScalarsGenerated(Plan.hasScalableVF()))
897 continue;
898
899 VPValue *PtrAdd = scalarizeVPWidenPointerInduction(PtrIV, Plan, Builder);
900 PtrIV->replaceAllUsesWith(PtrAdd);
901 continue;
902 }
903
904 // Replace widened induction with scalar steps for users that only use
905 // scalars.
906 auto *WideIV = cast<VPWidenIntOrFpInductionRecipe>(&Phi);
907 if (HasOnlyVectorVFs && none_of(WideIV->users(), [WideIV](VPUser *U) {
908 return U->usesScalars(WideIV);
909 }))
910 continue;
911
912 const InductionDescriptor &ID = WideIV->getInductionDescriptor();
914 Plan, ID.getKind(), ID.getInductionOpcode(),
915 dyn_cast_or_null<FPMathOperator>(ID.getInductionBinOp()),
916 WideIV->getTruncInst(), WideIV->getStartValue(), WideIV->getStepValue(),
917 WideIV->getDebugLoc(), Builder);
918
919 // Update scalar users of IV to use Step instead.
920 if (!HasOnlyVectorVFs) {
921 assert(!Plan.hasScalableVF() &&
922 "plans containing a scalar VF cannot also include scalable VFs");
923 WideIV->replaceAllUsesWith(Steps);
924 } else {
925 bool HasScalableVF = Plan.hasScalableVF();
926 WideIV->replaceUsesWithIf(Steps,
927 [WideIV, HasScalableVF](VPUser &U, unsigned) {
928 if (HasScalableVF)
929 return U.usesFirstLaneOnly(WideIV);
930 return U.usesScalars(WideIV);
931 });
932 }
933 }
934}
935
936/// Check if \p VPV is an untruncated wide induction, either before or after the
937/// increment. If so return the header IV (before the increment), otherwise
938/// return null.
941 auto *WideIV = dyn_cast<VPWidenInductionRecipe>(VPV);
942 if (WideIV) {
943 // VPV itself is a wide induction, separately compute the end value for exit
944 // users if it is not a truncated IV.
945 auto *IntOrFpIV = dyn_cast<VPWidenIntOrFpInductionRecipe>(WideIV);
946 return (IntOrFpIV && IntOrFpIV->getTruncInst()) ? nullptr : WideIV;
947 }
948
949 // Check if VPV is an optimizable induction increment.
950 VPRecipeBase *Def = VPV->getDefiningRecipe();
951 if (!Def || Def->getNumOperands() != 2)
952 return nullptr;
953 WideIV = dyn_cast<VPWidenInductionRecipe>(Def->getOperand(0));
954 if (!WideIV)
955 WideIV = dyn_cast<VPWidenInductionRecipe>(Def->getOperand(1));
956 if (!WideIV)
957 return nullptr;
958
959 auto IsWideIVInc = [&]() {
960 auto &ID = WideIV->getInductionDescriptor();
961
962 // Check if VPV increments the induction by the induction step.
963 VPValue *IVStep = WideIV->getStepValue();
964 switch (ID.getInductionOpcode()) {
965 case Instruction::Add:
966 return match(VPV, m_c_Add(m_Specific(WideIV), m_Specific(IVStep)));
967 case Instruction::FAdd:
968 return match(VPV, m_c_FAdd(m_Specific(WideIV), m_Specific(IVStep)));
969 case Instruction::FSub:
970 return match(VPV, m_Binary<Instruction::FSub>(m_Specific(WideIV),
971 m_Specific(IVStep)));
972 case Instruction::Sub: {
973 // IVStep will be the negated step of the subtraction. Check if Step == -1
974 // * IVStep.
975 VPValue *Step;
976 if (!match(VPV, m_Sub(m_VPValue(), m_VPValue(Step))))
977 return false;
978 const SCEV *IVStepSCEV = vputils::getSCEVExprForVPValue(IVStep, PSE);
979 const SCEV *StepSCEV = vputils::getSCEVExprForVPValue(Step, PSE);
980 ScalarEvolution &SE = *PSE.getSE();
981 return !isa<SCEVCouldNotCompute>(IVStepSCEV) &&
982 !isa<SCEVCouldNotCompute>(StepSCEV) &&
983 IVStepSCEV == SE.getNegativeSCEV(StepSCEV);
984 }
985 default:
986 return ID.getKind() == InductionDescriptor::IK_PtrInduction &&
987 match(VPV, m_GetElementPtr(m_Specific(WideIV),
988 m_Specific(WideIV->getStepValue())));
989 }
990 llvm_unreachable("should have been covered by switch above");
991 };
992 return IsWideIVInc() ? WideIV : nullptr;
993}
994
995/// Attempts to optimize the induction variable exit values for users in the
996/// early exit block.
999 VPValue *Incoming, *Mask;
1001 m_VPValue(Incoming))))
1002 return nullptr;
1003
1004 auto *WideIV = getOptimizableIVOf(Incoming, PSE);
1005 if (!WideIV)
1006 return nullptr;
1007
1008 auto *WideIntOrFp = dyn_cast<VPWidenIntOrFpInductionRecipe>(WideIV);
1009 if (WideIntOrFp && WideIntOrFp->getTruncInst())
1010 return nullptr;
1011
1012 // Calculate the final index.
1013 VPRegionBlock *LoopRegion = Plan.getVectorLoopRegion();
1014 auto *CanonicalIV = LoopRegion->getCanonicalIV();
1015 Type *CanonicalIVType = LoopRegion->getCanonicalIVType();
1016 auto *ExtractR = cast<VPInstruction>(Op);
1017 VPBuilder B(ExtractR);
1018
1019 DebugLoc DL = ExtractR->getDebugLoc();
1020 VPValue *FirstActiveLane = B.createFirstActiveLane(Mask, DL);
1021 FirstActiveLane =
1022 B.createScalarZExtOrTrunc(FirstActiveLane, CanonicalIVType, DL);
1023 VPValue *EndValue = B.createAdd(CanonicalIV, FirstActiveLane, DL);
1024
1025 // `getOptimizableIVOf()` always returns the pre-incremented IV, so if it
1026 // changed it means the exit is using the incremented value, so we need to
1027 // add the step.
1028 if (Incoming != WideIV) {
1029 VPValue *One = Plan.getConstantInt(CanonicalIVType, 1);
1030 EndValue = B.createAdd(EndValue, One, DL);
1031 }
1032
1033 if (!match(WideIV, m_CanonicalWidenIV())) {
1034 const InductionDescriptor &ID = WideIV->getInductionDescriptor();
1035 VPIRValue *Start = WideIV->getStartValue();
1036 VPValue *Step = WideIV->getStepValue();
1037 EndValue = B.createDerivedIV(
1038 ID.getKind(), dyn_cast_or_null<FPMathOperator>(ID.getInductionBinOp()),
1039 Start, EndValue, Step);
1040 }
1041
1042 return EndValue;
1043}
1044
1045/// Compute the end value for \p WideIV, unless it is truncated. Creates a
1046/// VPDerivedIVRecipe for non-canonical inductions.
1048 VPBuilder &VectorPHBuilder,
1049 VPValue *VectorTC) {
1050 auto *WideIntOrFp = dyn_cast<VPWidenIntOrFpInductionRecipe>(WideIV);
1051 // Truncated wide inductions resume from the last lane of their vector value
1052 // in the last vector iteration which is handled elsewhere.
1053 if (WideIntOrFp && WideIntOrFp->getTruncInst())
1054 return nullptr;
1055
1056 VPIRValue *Start = WideIV->getStartValue();
1057 VPValue *Step = WideIV->getStepValue();
1059 VPValue *EndValue = VectorTC;
1060 if (!match(WideIV, m_CanonicalWidenIV())) {
1061 EndValue = VectorPHBuilder.createDerivedIV(
1062 ID.getKind(), dyn_cast_or_null<FPMathOperator>(ID.getInductionBinOp()),
1063 Start, VectorTC, Step);
1064 }
1065
1066 // EndValue is derived from the vector trip count (which has the same type as
1067 // the widest induction) and thus may be wider than the induction here.
1068 Type *ScalarTypeOfWideIV = WideIV->getScalarType();
1069 if (ScalarTypeOfWideIV != EndValue->getScalarType()) {
1070 EndValue = VectorPHBuilder.createScalarCast(Instruction::Trunc, EndValue,
1071 ScalarTypeOfWideIV,
1072 WideIV->getDebugLoc());
1073 }
1074
1075 return EndValue;
1076}
1077
1078/// Attempts to optimize the induction variable exit values for users in the
1079/// exit block coming from the latch in the original scalar loop.
1080static VPValue *
1084 VPValue *Incoming;
1087 m_VPValue(Incoming)))))
1088 return nullptr;
1089
1090 VPWidenInductionRecipe *WideIV = getOptimizableIVOf(Incoming, PSE);
1091 if (!WideIV)
1092 return nullptr;
1093
1094 VPValue *EndValue = EndValues.lookup(WideIV);
1095 assert(EndValue && "Must have computed the end value up front");
1096
1097 // `getOptimizableIVOf()` always returns the pre-incremented IV, so if it
1098 // changed it means the exit is using the incremented value, so we don't
1099 // need to subtract the step.
1100 if (Incoming != WideIV)
1101 return EndValue;
1102
1103 // Otherwise, subtract the step from the EndValue.
1104 auto *ExtractR = cast<VPInstruction>(Op);
1105 VPBuilder B(ExtractR);
1106 VPValue *Step = WideIV->getStepValue();
1107 Type *ScalarTy = WideIV->getScalarType();
1108 if (ScalarTy->isIntegerTy())
1109 return B.createSub(EndValue, Step, DebugLoc::getUnknown(), "ind.escape");
1110 if (ScalarTy->isPointerTy()) {
1111 Type *StepTy = Step->getScalarType();
1112 auto *Zero = Plan.getZero(StepTy);
1113 return B.createPtrAdd(EndValue, B.createSub(Zero, Step),
1114 DebugLoc::getUnknown(), "ind.escape");
1115 }
1116 if (ScalarTy->isFloatingPointTy()) {
1117 const auto &ID = WideIV->getInductionDescriptor();
1118 return B.createNaryOp(
1119 ID.getInductionBinOp()->getOpcode() == Instruction::FAdd
1120 ? Instruction::FSub
1121 : Instruction::FAdd,
1122 {EndValue, Step}, {ID.getInductionBinOp()->getFastMathFlags()});
1123 }
1124 llvm_unreachable("all possible induction types must be handled");
1125 return nullptr;
1126}
1127
1129 VPlan &Plan, PredicatedScalarEvolution &PSE) {
1130 // Compute end values for all inductions.
1131 VPRegionBlock *VectorRegion = Plan.getVectorLoopRegion();
1132 auto *VectorPH = cast<VPBasicBlock>(VectorRegion->getSinglePredecessor());
1133 VPBuilder VectorPHBuilder(VectorPH, VectorPH->begin());
1135 VPValue *ResumeTC =
1136 Plan.hasTailFolded() ? Plan.getTripCount() : &Plan.getVectorTripCount();
1137 for (auto &Phi : VectorRegion->getEntryBasicBlock()->phis()) {
1138 auto *WideIV = dyn_cast<VPWidenInductionRecipe>(&Phi);
1139 if (!WideIV)
1140 continue;
1141 if (VPValue *EndValue =
1142 tryToComputeEndValueForInduction(WideIV, VectorPHBuilder, ResumeTC))
1143 EndValues[WideIV] = EndValue;
1144 }
1145
1146 VPBasicBlock *MiddleVPBB = Plan.getMiddleBlock();
1147 for (VPRecipeBase &R : make_early_inc_range(*MiddleVPBB)) {
1148 VPValue *Op;
1149 if (!match(&R, m_ExitingIVValue(m_VPValue(Op))))
1150 continue;
1151 auto *WideIV = cast<VPWidenInductionRecipe>(Op);
1152 if (VPValue *EndValue = EndValues.lookup(WideIV)) {
1153 R.getVPSingleValue()->replaceAllUsesWith(EndValue);
1154 R.eraseFromParent();
1155 }
1156 }
1157
1158 // Then, optimize exit block users.
1159 for (VPIRBasicBlock *ExitVPBB : Plan.getExitBlocks()) {
1160 for (VPRecipeBase &R : ExitVPBB->phis()) {
1161 auto *ExitIRI = cast<VPIRPhi>(&R);
1162
1163 for (auto [Idx, PredVPBB] : enumerate(ExitVPBB->getPredecessors())) {
1164 VPValue *Escape = nullptr;
1165 if (PredVPBB == MiddleVPBB)
1167 Plan, ExitIRI->getOperand(Idx), EndValues, PSE);
1168 else
1170 Plan, ExitIRI->getOperand(Idx), PSE);
1171 if (Escape)
1172 ExitIRI->setOperand(Idx, Escape);
1173 }
1174 }
1175 }
1176}
1177
1178/// Remove redundant ExpandSCEVRecipes in \p Plan's entry block by replacing
1179/// them with already existing recipes expanding the same SCEV expression.
1182
1183 for (VPRecipeBase &R :
1185 auto *ExpR = dyn_cast<VPExpandSCEVRecipe>(&R);
1186 if (!ExpR)
1187 continue;
1188
1189 const auto &[V, Inserted] = SCEV2VPV.try_emplace(ExpR->getSCEV(), ExpR);
1190 if (Inserted)
1191 continue;
1192
1193 ExpR->replaceAllUsesWith(V->second);
1194 if (ExpR == Plan.getTripCount())
1195 Plan.resetTripCount(V->second);
1196
1197 ExpR->eraseFromParent();
1198 }
1199}
1200
1201/// Try to simplify logical and bitwise recipes in \p Def.
1203 bool CanCreateNewRecipe) {
1204 VPlan *Plan = Def->getParent()->getPlan();
1205
1206 // Simplify (X && Y) | (X && !Y) -> X.
1207 // TODO: Split up into simpler, modular combines: (X && Y) | (X && Z) into X
1208 // && (Y | Z) and (X | !X) into true. This requires queuing newly created
1209 // recipes to be visited during simplification.
1210 VPValue *X, *Y, *Z;
1211 if (match(Def,
1214 Def->replaceAllUsesWith(X);
1215 Def->eraseFromParent();
1216 return true;
1217 }
1218
1219 // x | AllOnes -> AllOnes
1220 if (match(Def, m_c_BinaryOr(m_VPValue(X), m_AllOnes()))) {
1221 Def->replaceAllUsesWith(Plan->getAllOnesValue(Def->getScalarType()));
1222 return true;
1223 }
1224
1225 // x | 0 -> x
1226 if (match(Def, m_c_BinaryOr(m_VPValue(X), m_ZeroInt()))) {
1227 Def->replaceAllUsesWith(X);
1228 return true;
1229 }
1230
1231 // x | !x -> AllOnes
1232 if (match(Def, m_c_BinaryOr(m_VPValue(X), m_Not(m_Deferred(X))))) {
1233 Def->replaceAllUsesWith(Plan->getAllOnesValue(Def->getScalarType()));
1234 return true;
1235 }
1236
1237 // x & 0 -> 0
1238 if (match(Def, m_c_BinaryAnd(m_VPValue(X), m_ZeroInt()))) {
1239 Def->replaceAllUsesWith(Plan->getZero(Def->getScalarType()));
1240 return true;
1241 }
1242
1243 // x & AllOnes -> x
1244 if (match(Def, m_c_BinaryAnd(m_VPValue(X), m_AllOnes()))) {
1245 Def->replaceAllUsesWith(X);
1246 return true;
1247 }
1248
1249 // x && false -> false
1250 if (match(Def, m_c_LogicalAnd(m_VPValue(X), m_False()))) {
1251 Def->replaceAllUsesWith(Plan->getFalse());
1252 return true;
1253 }
1254
1255 // x && true -> x
1256 if (match(Def, m_c_LogicalAnd(m_VPValue(X), m_True()))) {
1257 Def->replaceAllUsesWith(X);
1258 return true;
1259 }
1260
1261 // (x && y) | (x && z) -> x && (y | z)
1262 if (CanCreateNewRecipe &&
1265 // Simplify only if one of the operands has one use to avoid creating an
1266 // extra recipe.
1267 (!Def->getOperand(0)->hasMoreThanOneUniqueUser() ||
1268 !Def->getOperand(1)->hasMoreThanOneUniqueUser())) {
1269 Def->replaceAllUsesWith(
1270 Builder.createLogicalAnd(X, Builder.createOr(Y, Z)));
1271 return true;
1272 }
1273
1274 // x && (x && y) -> x && y
1275 if (match(Def, m_LogicalAnd(m_VPValue(X),
1277 Def->replaceAllUsesWith(Def->getOperand(1));
1278 return true;
1279 }
1280
1281 // x && (y && x) -> x && y
1282 if (match(Def, m_LogicalAnd(m_VPValue(X),
1284 Def->replaceAllUsesWith(Builder.createLogicalAnd(X, Y));
1285 return true;
1286 }
1287
1288 // x && !x -> 0
1289 if (match(Def, m_LogicalAnd(m_VPValue(X), m_Not(m_Deferred(X))))) {
1290 Def->replaceAllUsesWith(Plan->getFalse());
1291 return true;
1292 }
1293
1294 if (match(Def, m_Select(m_VPValue(), m_VPValue(X), m_Deferred(X)))) {
1295 Def->replaceAllUsesWith(X);
1296 return true;
1297 }
1298
1299 // select c, false, true -> not c
1300 VPValue *C;
1301 if (CanCreateNewRecipe &&
1302 match(Def, m_Select(m_VPValue(C), m_False(), m_True()))) {
1303 Def->replaceAllUsesWith(Builder.createNot(C));
1304 return true;
1305 }
1306
1307 // select !c, x, y -> select c, y, x
1308 if (match(Def, m_Select(m_Not(m_VPValue(C)), m_VPValue(X), m_VPValue(Y)))) {
1309 Def->setOperand(0, C);
1310 Def->setOperand(1, Y);
1311 Def->setOperand(2, X);
1312 return true;
1313 }
1314
1315 // select x, (i1 y | z), y -> y | (x && z)
1316 if (CanCreateNewRecipe &&
1317 match(Def, m_Select(m_VPValue(X),
1319 m_Deferred(Y))) &&
1320 Y->getScalarType()->isIntegerTy(1)) {
1321 Def->replaceAllUsesWith(
1322 Builder.createOr(Y, Builder.createLogicalAnd(X, Z)));
1323 return true;
1324 }
1325
1326 return false;
1327}
1328
1329/// Try to simplify VPSingleDefRecipe \p Def.
1331 VPlan *Plan = Def->getParent()->getPlan();
1332
1333 // Simplification of live-in IR values for SingleDef recipes using
1334 // InstSimplifyFolder.
1335 const DataLayout &DL = Plan->getDataLayout();
1336 if (VPValue *V = vputils::tryToFoldLiveIns(*Def, Def->operands(), DL))
1337 return Def->replaceAllUsesWith(V);
1338
1339 // Fold PredPHI LiveIn -> LiveIn.
1340 if (auto *PredPHI = dyn_cast<VPPredInstPHIRecipe>(Def)) {
1341 VPValue *Op = PredPHI->getOperand(0);
1342 if (isa<VPIRValue>(Op))
1343 PredPHI->replaceAllUsesWith(Op);
1344 }
1345
1346 // Drop the mask of a predicated store masked by the header mask (which is
1347 // guaranteed to be true at least for the first lane) and both the stored
1348 // value and the address are uniform across VF and UF. The header mask is
1349 // still the abstract region value here.
1350 if (auto *RepR = dyn_cast<VPReplicateRecipe>(Def);
1351 RepR && RepR->isPredicated() && RepR->getOpcode() == Instruction::Store &&
1352 all_of(RepR->operandsWithoutMask(), vputils::isUniformAcrossVFsAndUFs) &&
1353 match(RepR->getMask(), m_HeaderMask())) {
1354 auto *Unmasked = new VPReplicateRecipe(
1355 RepR->getUnderlyingInstr(), RepR->operandsWithoutMask(),
1356 RepR->isSingleScalar(), /*Mask=*/nullptr, *RepR, *RepR,
1357 RepR->getDebugLoc());
1358 Unmasked->insertBefore(RepR);
1359 RepR->replaceAllUsesWith(Unmasked);
1360 RepR->eraseFromParent();
1361 return;
1362 }
1363
1364 VPBuilder Builder(Def);
1365
1366 // Avoid replacing VPInstructions with underlying values with new
1367 // VPInstructions, as we would fail to create widen/replicate recpes from the
1368 // new VPInstructions without an underlying value, and miss out on some
1369 // transformations that only apply to widened/replicated recipes later, by
1370 // doing so.
1371 // TODO: We should also not replace non-VPInstructions like VPWidenRecipe with
1372 // VPInstructions without underlying values, as those will get skipped during
1373 // cost computation.
1374 bool CanCreateNewRecipe =
1375 !isa<VPInstruction>(Def) || !Def->getUnderlyingValue();
1376
1377 VPValue *A;
1378 if (match(Def, m_Trunc(m_ZExtOrSExt(m_VPValue(A))))) {
1379 Type *TruncTy = Def->getScalarType();
1380 Type *ATy = A->getScalarType();
1381 if (TruncTy == ATy) {
1382 Def->replaceAllUsesWith(A);
1383 } else {
1384 // Don't replace a non-widened cast recipe with a widened cast.
1385 if (!isa<VPWidenCastRecipe>(Def))
1386 return;
1387 if (ATy->getScalarSizeInBits() < TruncTy->getScalarSizeInBits()) {
1388
1389 unsigned ExtOpcode = match(Def->getOperand(0), m_SExt(m_VPValue()))
1390 ? Instruction::SExt
1391 : Instruction::ZExt;
1392 auto *Ext = Builder.createWidenCast(Instruction::CastOps(ExtOpcode), A,
1393 TruncTy);
1394 if (auto *UnderlyingExt = Def->getOperand(0)->getUnderlyingValue()) {
1395 // UnderlyingExt has distinct return type, used to retain legacy cost.
1396 Ext->setUnderlyingValue(UnderlyingExt);
1397 }
1398 Def->replaceAllUsesWith(Ext);
1399 } else if (ATy->getScalarSizeInBits() > TruncTy->getScalarSizeInBits()) {
1400 auto *Trunc = Builder.createWidenCast(Instruction::Trunc, A, TruncTy);
1401 Def->replaceAllUsesWith(Trunc);
1402 }
1403 }
1404 }
1405
1406 if (simplifyLogicalRecipe(Def, Builder, CanCreateNewRecipe))
1407 return;
1408
1409 VPValue *X, *Y, *C;
1410 if (match(Def, m_c_Add(m_VPValue(A), m_ZeroInt())))
1411 return Def->replaceAllUsesWith(A);
1412
1413 if (match(Def, m_c_Mul(m_VPValue(A), m_One())))
1414 return Def->replaceAllUsesWith(A);
1415
1416 if (match(Def, m_c_Mul(m_VPValue(A), m_ZeroInt())))
1417 return Def->replaceAllUsesWith(Plan->getZero(Def->getScalarType()));
1418
1419 if (CanCreateNewRecipe && match(Def, m_c_Mul(m_VPValue(A), m_AllOnes()))) {
1420 // Preserve nsw from the Mul on the new Sub.
1422 false, cast<VPRecipeWithIRFlags>(Def)->hasNoSignedWrap()};
1423 return Def->replaceAllUsesWith(Builder.createSub(
1424 Plan->getZero(A->getScalarType()), A, Def->getDebugLoc(), "", NW));
1425 }
1426
1427 if (CanCreateNewRecipe &&
1429 // Preserve nsw from the Add and the Sub, if it's present on both, on the
1430 // new Sub.
1432 false,
1433 cast<VPRecipeWithIRFlags>(Def)->hasNoSignedWrap() &&
1434 cast<VPRecipeWithIRFlags>(Def->getOperand(Def->getOperand(0) == X))
1435 ->hasNoSignedWrap()};
1436 return Def->replaceAllUsesWith(
1437 Builder.createSub(X, Y, Def->getDebugLoc(), "", NW));
1438 }
1439
1440 const APInt *APC;
1441 if (CanCreateNewRecipe && match(Def, m_c_Mul(m_VPValue(A), m_APInt(APC))) &&
1442 APC->isPowerOf2()) {
1443 auto *MulR = cast<VPRecipeWithIRFlags>(Def);
1444 unsigned ShiftAmt = APC->exactLogBase2();
1445 VPIRFlags::WrapFlagsTy NW(MulR->hasNoUnsignedWrap(),
1446 MulR->hasNoSignedWrap() &&
1447 ShiftAmt != APC->getBitWidth() - 1);
1448 return Def->replaceAllUsesWith(Builder.createNaryOp(
1449 Instruction::Shl,
1450 {A, Plan->getConstantInt(APC->getBitWidth(), ShiftAmt)}, NW,
1451 Def->getDebugLoc()));
1452 }
1453
1454 if (CanCreateNewRecipe && match(Def, m_UDiv(m_VPValue(A), m_APInt(APC))) &&
1455 APC->isPowerOf2())
1456 return Def->replaceAllUsesWith(Builder.createNaryOp(
1457 Instruction::LShr,
1458 {A, Plan->getConstantInt(APC->getBitWidth(), APC->exactLogBase2())},
1459 *cast<VPRecipeWithIRFlags>(Def), Def->getDebugLoc()));
1460
1461 if (match(Def, m_Not(m_VPValue(A)))) {
1462 if (match(A, m_Not(m_VPValue(A))))
1463 return Def->replaceAllUsesWith(A);
1464
1465 // Try to fold Not into compares by adjusting the predicate in-place.
1466 CmpPredicate Pred;
1467 if (match(A, m_Cmp(Pred, m_VPValue(), m_VPValue()))) {
1468 auto *Cmp = cast<VPRecipeWithIRFlags>(A);
1469 if (all_of(Cmp->users(),
1471 m_Not(m_Specific(Cmp)),
1472 m_Select(m_Specific(Cmp), m_VPValue(), m_VPValue()))))) {
1473 Cmp->setPredicate(CmpInst::getInversePredicate(Pred));
1474 for (VPUser *U : to_vector(Cmp->users())) {
1475 auto *R = cast<VPSingleDefRecipe>(U);
1476 if (match(R, m_Select(m_Specific(Cmp), m_VPValue(X), m_VPValue(Y)))) {
1477 // select (cmp pred), x, y -> select (cmp inv_pred), y, x
1478 R->setOperand(1, Y);
1479 R->setOperand(2, X);
1480 } else {
1481 // not (cmp pred) -> cmp inv_pred
1482 assert(match(R, m_Not(m_Specific(Cmp))) && "Unexpected user");
1483 R->replaceAllUsesWith(Cmp);
1484 }
1485 }
1486 // If Cmp doesn't have a debug location, use the one from the negation,
1487 // to preserve the location.
1488 if (!Cmp->getDebugLoc() && Def->getDebugLoc())
1489 Cmp->setDebugLoc(Def->getDebugLoc());
1490 }
1491 }
1492 }
1493
1494 // Fold any-of (fcmp uno %A, %A), (fcmp uno %B, %B), ... ->
1495 // any-of (fcmp uno %A, %B), ...
1496 if (match(Def, m_AnyOf())) {
1498 VPRecipeBase *UnpairedCmp = nullptr;
1499 for (VPValue *Op : Def->operands()) {
1500 VPValue *X;
1501 if (Op->getNumUsers() > 1 ||
1503 m_Deferred(X)))) {
1504 NewOps.push_back(Op);
1505 } else if (!UnpairedCmp) {
1506 UnpairedCmp = Op->getDefiningRecipe();
1507 } else {
1508 NewOps.push_back(Builder.createFCmp(CmpInst::FCMP_UNO,
1509 UnpairedCmp->getOperand(0), X));
1510 UnpairedCmp = nullptr;
1511 }
1512 }
1513
1514 if (UnpairedCmp)
1515 NewOps.push_back(UnpairedCmp->getVPSingleValue());
1516
1517 if (NewOps.size() < Def->getNumOperands()) {
1518 VPValue *NewAnyOf = Builder.createNaryOp(VPInstruction::AnyOf, NewOps);
1519 return Def->replaceAllUsesWith(NewAnyOf);
1520 }
1521 }
1522
1523 // Fold (fcmp uno %X, %X) or (fcmp uno %Y, %Y) -> fcmp uno %X, %Y
1524 // This is useful for fmax/fmin without fast-math flags, where we need to
1525 // check if any operand is NaN.
1526 if (CanCreateNewRecipe &&
1528 m_Deferred(X)),
1530 m_Deferred(Y))))) {
1531 VPValue *NewCmp = Builder.createFCmp(CmpInst::FCMP_UNO, X, Y);
1532 return Def->replaceAllUsesWith(NewCmp);
1533 }
1534
1535 // Remove redundant DerviedIVs, that is 0 + A * 1 -> A and 0 + 0 * x -> 0.
1536 if ((match(Def, m_DerivedIV(m_ZeroInt(), m_VPValue(A), m_One())) ||
1537 match(Def, m_DerivedIV(m_ZeroInt(), m_ZeroInt(), m_VPValue()))) &&
1538 Def->getOperand(1)->getScalarType() == Def->getScalarType())
1539 return Def->replaceAllUsesWith(Def->getOperand(1));
1540
1542 m_One()))) {
1543 Type *WideStepTy = Def->getScalarType();
1544 if (X->getScalarType() != WideStepTy)
1545 X = Builder.createWidenCast(Instruction::Trunc, X, WideStepTy);
1546 Def->replaceAllUsesWith(X);
1547 return;
1548 }
1549
1550 // For i1 vp.merges produced by AnyOf reductions:
1551 // vp.merge true, (or x, y), x, evl -> vp.merge y, true, x, evl
1553 m_VPValue(X), m_VPValue())) &&
1555 Def->getScalarType()->isIntegerTy(1)) {
1556 Def->setOperand(1, Def->getOperand(0));
1557 Def->setOperand(0, Y);
1558 return;
1559 }
1560
1561 // Simplify MaskedCond with no block mask to its single operand.
1563 !cast<VPInstruction>(Def)->isMasked())
1564 return Def->replaceAllUsesWith(Def->getOperand(0));
1565
1566 // Look through ExtractLastLane.
1567 if (match(Def, m_ExtractLastLane(m_VPValue(A)))) {
1568 if (match(A, m_BuildVector())) {
1569 auto *BuildVector = cast<VPInstruction>(A);
1570 Def->replaceAllUsesWith(
1571 BuildVector->getOperand(BuildVector->getNumOperands() - 1));
1572 return;
1573 }
1574
1575 if (match(A, m_Broadcast(m_VPValue(X))))
1576 return Def->replaceAllUsesWith(X);
1577
1579 return Def->replaceAllUsesWith(A);
1580
1581 if (Plan->hasScalarVFOnly())
1582 return Def->replaceAllUsesWith(A);
1583 }
1584
1585 // Look through ExtractPenultimateElement (BuildVector ....).
1587 auto *BuildVector = cast<VPInstruction>(Def->getOperand(0));
1588 Def->replaceAllUsesWith(
1589 BuildVector->getOperand(BuildVector->getNumOperands() - 2));
1590 return;
1591 }
1592
1593 uint64_t Idx;
1595 auto *BuildVector = cast<VPInstruction>(Def->getOperand(0));
1596 Def->replaceAllUsesWith(BuildVector->getOperand(Idx));
1597 return;
1598 }
1599
1600 if (match(Def, m_BuildVector()) && all_equal(Def->operands())) {
1601 Def->replaceAllUsesWith(
1602 Builder.createNaryOp(VPInstruction::Broadcast, Def->getOperand(0)));
1603 return;
1604 }
1605
1606 // Replace uses of a BuildVector by users that only use its first lane with
1607 // its first operand directly.
1608 if (match(Def, m_BuildVector())) {
1609 Def->replaceUsesWithIf(Def->getOperand(0), [Def](VPUser &U, unsigned) {
1610 return U.usesFirstLaneOnly(Def);
1611 });
1612 }
1613
1614 // Look through broadcast of single-scalar when used as select conditions; in
1615 // that case the scalar condition can be used directly.
1616 if (match(Def,
1619 "broadcast operand must be single-scalar");
1620 Def->setOperand(0, C);
1621 return;
1622 }
1623
1624 if (match(Def, m_Broadcast(m_VPValue(X))))
1625 return Def->replaceUsesWithIf(
1626 X, [Def](const VPUser &U, unsigned) { return U.usesScalars(Def); });
1627
1629 if (Def->getNumOperands() == 1) {
1630 Def->replaceAllUsesWith(Def->getOperand(0));
1631 return;
1632 }
1633 if (auto *Phi = dyn_cast<VPFirstOrderRecurrencePHIRecipe>(Def)) {
1634 if (all_equal(Phi->incoming_values()))
1635 Phi->replaceAllUsesWith(Phi->getOperand(0));
1636 }
1637 return;
1638 }
1639
1640 VPIRValue *IRV;
1641 if (Def->getNumOperands() == 1 &&
1643 return Def->replaceAllUsesWith(IRV);
1644
1645 // Some simplifications can only be applied after unrolling. Perform them
1646 // below.
1647 if (!Plan->isUnrolled())
1648 return;
1649
1650 // After unrolling, extract-lane may be used to extract values from multiple
1651 // scalar sources. Only simplify when extracting from a single scalar source.
1652 VPValue *LaneToExtract;
1653 if (match(Def, m_ExtractLane(m_VPValue(LaneToExtract), m_VPValue(A)))) {
1654 // Simplify extract-lane(%lane_num, %scalar_val) -> %scalar_val.
1656 return Def->replaceAllUsesWith(A);
1657
1658 // Replace extract-lane(0, canonical-WIDEN-INDUCTION) with the region's
1659 // scalar canonical IV.
1661 if (match(LaneToExtract, m_ZeroInt()) &&
1662 match(A, m_CanonicalWidenIV(WidenIV)))
1663 return Def->replaceAllUsesWith(WidenIV->getRegion()->getCanonicalIV());
1664
1665 // Simplify extract-lane with single source to extract-element.
1666 Def->replaceAllUsesWith(Builder.createNaryOp(
1667 Instruction::ExtractElement, {A, LaneToExtract}, Def->getDebugLoc()));
1668 return;
1669 }
1670
1671 // Look for cycles where Def is of the form:
1672 // X = phi(0, IVInc) ; used only by IVInc, or by IVInc and Inc = X + Y
1673 // IVInc = X + Step ; used by X and Def
1674 // Def = IVInc + Y
1675 // Fold the increment Y into the phi's start value, replace Def with IVInc,
1676 // and if Inc exists, replace it with X.
1677 if (match(Def, m_Add(m_Add(m_VPValue(X), m_VPValue()), m_VPValue(Y))) &&
1678 isa<VPIRValue>(Y) &&
1679 match(X, m_VPPhi(m_ZeroInt(), m_Specific(Def->getOperand(0))))) {
1680 auto *Phi = cast<VPPhi>(X);
1681 auto *IVInc = Def->getOperand(0);
1682 if (IVInc->getNumUsers() == 2) {
1683 // If Phi has a second user (besides IVInc's defining recipe), it must
1684 // be Inc = Phi + Y for the fold to apply.
1686 findUserOf(Phi, m_Add(m_Specific(Phi), m_Specific(Y))));
1687 if (Phi->getNumUsers() == 1 || (Phi->getNumUsers() == 2 && Inc)) {
1688 Def->replaceAllUsesWith(IVInc);
1689 if (Inc)
1690 Inc->replaceAllUsesWith(Phi);
1691 Phi->setOperand(0, Y);
1692 return;
1693 }
1694 }
1695 }
1696
1697 // Simplify unrolled VectorPointer without offset, or with zero offset, to
1698 // just the pointer operand.
1699 if (auto *VPR = dyn_cast<VPVectorPointerRecipe>(Def))
1700 if (!VPR->getVFxPart() || match(VPR->getVFxPart(), m_ZeroInt()))
1701 return VPR->replaceAllUsesWith(VPR->getOperand(0));
1702
1703 // VPScalarIVSteps after unrolling can be replaced by their start value, if
1704 // the start index is zero and only the first lane 0 is demanded.
1705 if (auto *Steps = dyn_cast<VPScalarIVStepsRecipe>(Def)) {
1706 if (!Steps->getStartIndex() && vputils::onlyFirstLaneUsed(Steps)) {
1707 Steps->replaceAllUsesWith(Steps->getOperand(0));
1708 return;
1709 }
1710 }
1711 // Simplify redundant ReductionStartVector recipes after unrolling.
1712 VPValue *StartV;
1714 m_VPValue(StartV), m_VPValue(), m_VPValue()))) {
1715 Def->replaceUsesWithIf(StartV, [](const VPUser &U, unsigned Idx) {
1716 auto *PhiR = dyn_cast<VPReductionPHIRecipe>(&U);
1717 return PhiR && PhiR->isInLoop();
1718 });
1719 return;
1720 }
1721
1722 if (Plan->getConcreteUF() == 1 && match(Def, m_ExtractLastPart(m_VPValue(A))))
1723 return Def->replaceAllUsesWith(A);
1724}
1725
1735
1737 // Pull out reverses from any elementwise op.
1738 // binop(reverse(x), reverse(y)) -> reverse(binop(x,y))
1740 Plan, [](VPValue *&X) { return m_Reverse(m_VPValue(X)); },
1741 [](auto *X) { return new VPInstruction(VPInstruction::Reverse, X); });
1742
1743 // reverse(reverse(x)) -> x
1744 VPValue *X;
1747 for (VPRecipeBase &R : make_early_inc_range(*VPBB))
1748 if (match(&R, m_Reverse(m_Reverse(m_VPValue(X)))))
1749 R.getVPSingleValue()->replaceAllUsesWith(X);
1750}
1751
1752/// Reassociate (headermask && x) && y -> headermask && (x && y) to allow the
1753/// header mask to be simplified further when tail folding, e.g. in
1754/// optimizeEVLMasks.
1755static void reassociateHeaderMask(VPlan &Plan) {
1756 VPValue *HeaderMask = Plan.getVectorLoopRegion()->getHeaderMask();
1757 if (!HeaderMask)
1758 return;
1759
1760 SmallVector<VPUser *> Worklist;
1761 for (VPUser *U : HeaderMask->users())
1762 if (match(U, m_LogicalAnd(m_Specific(HeaderMask), m_VPValue())))
1764
1765 while (!Worklist.empty()) {
1766 auto *R = dyn_cast<VPSingleDefRecipe>(Worklist.pop_back_val());
1767 VPValue *X, *Y;
1768 if (!R || !match(R, m_LogicalAnd(
1769 m_LogicalAnd(m_Specific(HeaderMask), m_VPValue(X)),
1770 m_VPValue(Y))))
1771 continue;
1772 append_range(Worklist, R->users());
1773 VPBuilder Builder(R);
1774 R->replaceAllUsesWith(
1775 Builder.createLogicalAnd(HeaderMask, Builder.createLogicalAnd(X, Y)));
1776 }
1777}
1778
1779static std::optional<Instruction::BinaryOps>
1781 switch (ID) {
1782 case Intrinsic::masked_udiv:
1783 return Instruction::UDiv;
1784 case Intrinsic::masked_sdiv:
1785 return Instruction::SDiv;
1786 case Intrinsic::masked_urem:
1787 return Instruction::URem;
1788 case Intrinsic::masked_srem:
1789 return Instruction::SRem;
1790 default:
1791 return {};
1792 }
1793}
1794
1796 if (Plan.hasScalarVFOnly())
1797 return;
1798
1800 vp_depth_first_deep(Plan.getEntry()))) {
1801 for (VPRecipeBase &R : make_early_inc_range(reverse(*VPBB))) {
1804 continue;
1805 auto *RepR = dyn_cast<VPReplicateRecipe>(&R);
1806 if (RepR && (RepR->isSingleScalar() || RepR->isPredicated()))
1807 continue;
1808
1809 auto *RepOrWidenR = cast<VPRecipeWithIRFlags>(&R);
1810 if (RepR && RepR->getOpcode() == Instruction::Store &&
1811 vputils::isSingleScalar(RepR->getOperand(1))) {
1812 auto *Clone = new VPReplicateRecipe(
1813 RepOrWidenR->getUnderlyingInstr(), RepOrWidenR->operands(),
1814 true /*IsSingleScalar*/, nullptr /*Mask*/, *RepR /*Flags*/,
1815 *RepR /*Metadata*/, RepR->getDebugLoc());
1816 Clone->insertBefore(RepOrWidenR);
1817 VPBuilder Builder(Clone);
1818 VPValue *ExtractOp = Clone->getOperand(0);
1819 if (vputils::isUniformAcrossVFsAndUFs(RepR->getOperand(1)))
1820 ExtractOp =
1821 Builder.createNaryOp(VPInstruction::ExtractLastPart, ExtractOp);
1822 ExtractOp =
1823 Builder.createNaryOp(VPInstruction::ExtractLastLane, ExtractOp);
1824 Clone->setOperand(0, ExtractOp);
1825 RepR->eraseFromParent();
1826 continue;
1827 }
1828
1829 // Narrow llvm.masked.{u,s}{div,rem} intrinsics with a safe divisor.
1830 if (auto *IntrR = dyn_cast<VPWidenIntrinsicRecipe>(RepOrWidenR)) {
1831 if (!vputils::onlyFirstLaneUsed(IntrR))
1832 continue;
1833 auto Opc = getUnmaskedDivRemOpcode(IntrR->getVectorIntrinsicID());
1834 if (!Opc)
1835 continue;
1836 VPBuilder Builder(IntrR);
1837 VPValue *SafeDivisor = Builder.createSelect(
1838 IntrR->getOperand(2), IntrR->getOperand(1),
1839 Plan.getConstantInt(IntrR->getScalarType(), 1));
1840 VPValue *Clone = Builder.createNaryOp(
1841 *Opc, {IntrR->getOperand(0), SafeDivisor},
1842 VPIRFlags::getDefaultFlags(*Opc), IntrR->getDebugLoc());
1843 IntrR->replaceAllUsesWith(Clone);
1844 IntrR->eraseFromParent();
1845 continue;
1846 }
1847
1848 // Skip recipes that aren't single scalars.
1849 if (!vputils::isSingleScalar(RepOrWidenR))
1850 continue;
1851
1852 // Predicate to check if a user of Op introduces extra broadcasts.
1853 auto IntroducesBCastOf = [](const VPValue *Op) {
1854 return [Op](const VPUser *U) {
1855 if (auto *VPI = dyn_cast<VPInstruction>(U)) {
1859 VPI->getOpcode()))
1860 return false;
1861 }
1862 return !U->usesScalars(Op);
1863 };
1864 };
1865
1866 if (any_of(RepOrWidenR->users(), IntroducesBCastOf(RepOrWidenR)) &&
1867 none_of(RepOrWidenR->operands(), [&](VPValue *Op) {
1868 if (any_of(
1869 make_filter_range(Op->users(), not_equal_to(RepOrWidenR)),
1870 IntroducesBCastOf(Op)))
1871 return false;
1872 // Non-constant live-ins require broadcasts, while constants do not
1873 // need explicit broadcasts.
1874 bool LiveInNeedsBroadcast =
1875 isa<VPIRValue>(Op) && !isa<VPConstant>(Op);
1876 auto *OpR = dyn_cast<VPReplicateRecipe>(Op);
1877 return LiveInNeedsBroadcast || (OpR && OpR->isSingleScalar());
1878 }))
1879 continue;
1880
1881 auto *Clone = VPBuilder::createSingleScalarOp(
1882 vputils::getOpcode(RepOrWidenR), RepOrWidenR->operands(),
1883 /*Mask=*/nullptr, *RepOrWidenR, {}, DebugLoc::getUnknown(),
1884 RepOrWidenR->getUnderlyingInstr());
1885 Clone->insertBefore(RepOrWidenR);
1886 RepOrWidenR->replaceAllUsesWith(Clone);
1887 if (vputils::isDeadRecipe(*RepOrWidenR))
1888 RepOrWidenR->eraseFromParent();
1889 }
1890 }
1891}
1892
1893/// Try to see if all of \p Blend's masks share a common value logically and'ed
1894/// and remove it from the masks.
1896 if (Blend->isNormalized())
1897 return;
1898 VPValue *CommonEdgeMask;
1899 if (!match(Blend->getMask(0),
1900 m_LogicalAnd(m_VPValue(CommonEdgeMask), m_VPValue())))
1901 return;
1902 for (unsigned I = 0; I < Blend->getNumIncomingValues(); I++)
1903 if (!match(Blend->getMask(I),
1904 m_LogicalAnd(m_Specific(CommonEdgeMask), m_VPValue())))
1905 return;
1906 for (unsigned I = 0; I < Blend->getNumIncomingValues(); I++)
1907 Blend->setMask(I, Blend->getMask(I)->getDefiningRecipe()->getOperand(1));
1908}
1909
1910/// Normalize and simplify VPBlendRecipes. Should be run after simplifyRecipes
1911/// to make sure the masks are simplified.
1912static void simplifyBlends(VPlan &Plan) {
1915 for (VPRecipeBase &R : make_early_inc_range(*VPBB)) {
1916 auto *Blend = dyn_cast<VPBlendRecipe>(&R);
1917 if (!Blend)
1918 continue;
1919
1920 removeCommonBlendMask(Blend);
1921
1922 // Try to remove redundant blend recipes.
1923 SmallPtrSet<VPValue *, 4> UniqueValues;
1924 if (Blend->isNormalized() || !match(Blend->getMask(0), m_False()))
1925 UniqueValues.insert(Blend->getIncomingValue(0));
1926 for (unsigned I = 1; I != Blend->getNumIncomingValues(); ++I)
1927 if (!match(Blend->getMask(I), m_False()))
1928 UniqueValues.insert(Blend->getIncomingValue(I));
1929
1930 if (UniqueValues.size() == 1) {
1931 Blend->replaceAllUsesWith(*UniqueValues.begin());
1932 Blend->eraseFromParent();
1933 continue;
1934 }
1935
1936 if (Blend->isNormalized())
1937 continue;
1938
1939 // Normalize the blend so its first incoming value is used as the initial
1940 // value with the others blended into it.
1941
1942 unsigned StartIndex = 0;
1943 for (unsigned I = 0; I != Blend->getNumIncomingValues(); ++I) {
1944 // If a value's mask is used only by the blend then is can be deadcoded.
1945 // TODO: Find the most expensive mask that can be deadcoded, or a mask
1946 // that's used by multiple blends where it can be removed from them all.
1947 VPValue *Mask = Blend->getMask(I);
1948 if (Mask->hasOneUse() && !match(Mask, m_False())) {
1949 StartIndex = I;
1950 break;
1951 }
1952 }
1953
1954 SmallVector<VPValue *, 4> OperandsWithMask;
1955 OperandsWithMask.push_back(Blend->getIncomingValue(StartIndex));
1956
1957 for (unsigned I = 0; I != Blend->getNumIncomingValues(); ++I) {
1958 if (I == StartIndex)
1959 continue;
1960 OperandsWithMask.push_back(Blend->getIncomingValue(I));
1961 OperandsWithMask.push_back(Blend->getMask(I));
1962 }
1963
1964 auto *NewBlend =
1965 new VPBlendRecipe(cast_or_null<PHINode>(Blend->getUnderlyingValue()),
1966 OperandsWithMask, *Blend, Blend->getDebugLoc());
1967 NewBlend->insertBefore(&R);
1968
1969 VPValue *DeadMask = Blend->getMask(StartIndex);
1970 Blend->replaceAllUsesWith(NewBlend);
1971 Blend->eraseFromParent();
1973
1974 /// Simplify BLEND %a, %b, Not(%mask) -> BLEND %b, %a, %mask.
1975 VPValue *NewMask;
1976 if (NewBlend->getNumOperands() == 3 &&
1977 match(NewBlend->getMask(1), m_Not(m_VPValue(NewMask)))) {
1978 VPValue *Inc0 = NewBlend->getOperand(0);
1979 VPValue *Inc1 = NewBlend->getOperand(1);
1980 VPValue *OldMask = NewBlend->getOperand(2);
1981 NewBlend->setOperand(0, Inc1);
1982 NewBlend->setOperand(1, Inc0);
1983 NewBlend->setOperand(2, NewMask);
1984 if (OldMask->user_empty())
1985 cast<VPInstruction>(OldMask)->eraseFromParent();
1986 }
1987 }
1988 }
1989}
1990
1991/// Optimize the width of vector induction variables in \p Plan based on a known
1992/// constant Trip Count, \p BestVF and \p BestUF.
1994 ElementCount BestVF,
1995 unsigned BestUF) {
1996 // Only proceed if we have not completely removed the vector region.
1997 if (!Plan.getVectorLoopRegion())
1998 return false;
1999
2000 const APInt *TC;
2001 if (!BestVF.isFixed() || !match(Plan.getTripCount(), m_APInt(TC)))
2002 return false;
2003
2004 // Calculate the minimum power-of-2 bit width that can fit the known TC, VF
2005 // and UF. Returns at least 8.
2006 auto ComputeBitWidth = [](APInt TC, uint64_t Align) {
2007 APInt AlignedTC =
2010 APInt MaxVal = AlignedTC - 1;
2011 return std::max<unsigned>(PowerOf2Ceil(MaxVal.getActiveBits()), 8);
2012 };
2013 unsigned NewBitWidth =
2014 ComputeBitWidth(*TC, BestVF.getKnownMinValue() * BestUF);
2015
2016 LLVMContext &Ctx = Plan.getContext();
2017 auto *NewIVTy = IntegerType::get(Ctx, NewBitWidth);
2018
2019 bool MadeChange = false;
2020
2021 VPBasicBlock *HeaderVPBB = Plan.getVectorLoopRegion()->getEntryBasicBlock();
2022 for (VPRecipeBase &Phi : HeaderVPBB->phis()) {
2023 // Currently only handle canonical IVs as it is trivial to replace the start
2024 // and stop values, and we currently only perform the optimization when the
2025 // IV has a single use.
2027 if (!match(&Phi, m_CanonicalWidenIV(WideIV)))
2028 continue;
2029 if (WideIV->hasMoreThanOneUniqueUser() ||
2030 NewIVTy == WideIV->getScalarType())
2031 continue;
2032
2033 // Currently only handle cases where the single user is a header-mask
2034 // comparison with the backedge-taken-count.
2035 VPUser *SingleUser = WideIV->getSingleUser();
2036 if (!SingleUser ||
2037 !match(SingleUser,
2038 m_ICmp(m_Specific(WideIV),
2040 continue;
2041
2042 // Update IV operands and comparison bound to use new narrower type.
2043 assert(!WideIV->getTruncInst() &&
2044 "canonical IV is not expected to have a truncation");
2045 auto *NewWideIV = new VPWidenIntOrFpInductionRecipe(
2046 WideIV->getPHINode(), Plan.getZero(NewIVTy),
2047 Plan.getConstantInt(NewIVTy, 1), WideIV->getVFValue(),
2048 WideIV->getInductionDescriptor(), *WideIV, WideIV->getDebugLoc());
2049 NewWideIV->insertBefore(WideIV);
2050
2051 auto *NewBTC = new VPWidenCastRecipe(
2052 Instruction::Trunc, Plan.getOrCreateBackedgeTakenCount(), NewIVTy,
2053 nullptr, VPIRFlags::getDefaultFlags(Instruction::Trunc));
2054 Plan.getVectorPreheader()->appendRecipe(NewBTC);
2055 auto *Cmp = cast<VPInstruction>(WideIV->getSingleUser());
2056 Cmp->replaceAllUsesWith(
2057 VPBuilder(Cmp).createICmp(Cmp->getPredicate(), NewWideIV, NewBTC));
2058
2059 MadeChange = true;
2060 }
2061
2062 return MadeChange;
2063}
2064
2065/// Return true if \p Cond is known to be true for given \p BestVF and \p
2066/// BestUF.
2068 ElementCount BestVF, unsigned BestUF,
2071 return any_of(Cond->getDefiningRecipe()->operands(), [&Plan, BestVF, BestUF,
2072 &PSE](VPValue *C) {
2073 return isConditionTrueViaVFAndUF(C, Plan, BestVF, BestUF, PSE);
2074 });
2075
2076 auto *CanIV = Plan.getVectorLoopRegion()->getCanonicalIV();
2079 m_c_Add(m_Specific(CanIV), m_Specific(&Plan.getVFxUF())),
2080 m_Specific(&Plan.getVectorTripCount()))))
2081 return false;
2082
2083 // The compare checks CanIV + VFxUF == vector trip count. The vector trip
2084 // count is not conveniently available as SCEV so far, so we compare directly
2085 // against the original trip count. This is stricter than necessary, as we
2086 // will only return true if the trip count == vector trip count.
2087 const SCEV *VectorTripCount =
2089 if (isa<SCEVCouldNotCompute>(VectorTripCount))
2090 VectorTripCount = vputils::getSCEVExprForVPValue(Plan.getTripCount(), PSE);
2091 assert(!isa<SCEVCouldNotCompute>(VectorTripCount) &&
2092 "Trip count SCEV must be computable");
2093 ScalarEvolution &SE = *PSE.getSE();
2094 ElementCount NumElements = BestVF.multiplyCoefficientBy(BestUF);
2095 const SCEV *C = SE.getElementCount(VectorTripCount->getType(), NumElements);
2096 return SE.isKnownPredicate(CmpInst::ICMP_EQ, VectorTripCount, C);
2097}
2098
2099/// Try to replace multiple active lane masks used for control flow with
2100/// a single, wide active lane mask instruction followed by multiple
2101/// extract subvector intrinsics. This applies to the active lane mask
2102/// instructions both in the loop and in the preheader.
2103/// Incoming values of all ActiveLaneMaskPHIs are updated to use the
2104/// new extracts from the first active lane mask, which has it's last
2105/// operand (multiplier) set to UF.
2107 unsigned UF) {
2108 if (!EnableWideActiveLaneMask || !VF.isVector() || UF == 1)
2109 return false;
2110
2111 VPRegionBlock *VectorRegion = Plan.getVectorLoopRegion();
2112 VPBasicBlock *ExitingVPBB = VectorRegion->getExitingBasicBlock();
2113 auto *Term = &ExitingVPBB->back();
2114
2115 using namespace llvm::VPlanPatternMatch;
2117 m_VPValue(), m_VPValue(), m_VPValue())))))
2118 return false;
2119
2120 auto *Header = cast<VPBasicBlock>(VectorRegion->getEntry());
2121 LLVMContext &Ctx = Plan.getContext();
2122
2123 auto ExtractFromALM = [&](VPInstruction *ALM,
2124 SmallVectorImpl<VPValue *> &Extracts) {
2125 DebugLoc DL = ALM->getDebugLoc();
2126 for (unsigned Part = 0; Part < UF; ++Part) {
2128 Ops.append({ALM, Plan.getConstantInt(64, VF.getKnownMinValue() * Part)});
2129 auto *Ext =
2130 new VPWidenIntrinsicRecipe(Intrinsic::vector_extract, Ops,
2131 IntegerType::getInt1Ty(Ctx), {}, {}, DL);
2132 Extracts[Part] = Ext;
2133 Ext->insertAfter(ALM);
2134 }
2135 };
2136
2137 // Create a list of each active lane mask phi, ordered by unroll part.
2139 for (VPRecipeBase &R : Header->phis()) {
2141 if (!Phi)
2142 continue;
2143 VPValue *Index = nullptr;
2144 match(Phi->getBackedgeValue(),
2146 assert(Index && "Expected index from ActiveLaneMask instruction");
2147
2148 uint64_t Part;
2149 if (match(Index,
2151 m_VPValue(), m_Mul(m_VPValue(), m_ConstantInt(Part)))))
2152 Phis[Part] = Phi;
2153 else {
2154 // Anything other than a CanonicalIVIncrementForPart is part 0
2155 assert(!match(
2156 Index,
2158 Phis[0] = Phi;
2159 }
2160 }
2161
2162 assert(all_of(Phis, not_equal_to(nullptr)) &&
2163 "Expected one VPActiveLaneMaskPHIRecipe for each unroll part");
2164
2165 auto *EntryALM = cast<VPInstruction>(Phis[0]->getStartValue());
2166 auto *LoopALM = cast<VPInstruction>(Phis[0]->getBackedgeValue());
2167
2168 assert((EntryALM->getOpcode() == VPInstruction::ActiveLaneMask &&
2169 LoopALM->getOpcode() == VPInstruction::ActiveLaneMask) &&
2170 "Expected incoming values of Phi to be ActiveLaneMasks");
2171
2172 // When using wide lane masks, the return type of the get.active.lane.mask
2173 // intrinsic is VF x UF (last operand).
2174 VPValue *ALMMultiplier = Plan.getConstantInt(64, UF);
2175 EntryALM->setOperand(2, ALMMultiplier);
2176 LoopALM->setOperand(2, ALMMultiplier);
2177
2178 // Create UF x extract vectors and insert into preheader.
2179 SmallVector<VPValue *> EntryExtracts(UF);
2180 ExtractFromALM(EntryALM, EntryExtracts);
2181
2182 // Create UF x extract vectors and insert before the loop compare & branch,
2183 // updating the compare to use the first extract.
2184 SmallVector<VPValue *> LoopExtracts(UF);
2185 ExtractFromALM(LoopALM, LoopExtracts);
2186 VPInstruction *Not = cast<VPInstruction>(Term->getOperand(0));
2187 Not->setOperand(0, LoopExtracts[0]);
2188
2189 // Update the incoming values of active lane mask phis.
2190 for (unsigned Part = 0; Part < UF; ++Part) {
2191 Phis[Part]->setStartValue(EntryExtracts[Part]);
2192 Phis[Part]->setBackedgeValue(LoopExtracts[Part]);
2193 }
2194
2195 return true;
2196}
2197
2198/// Try to simplify the branch condition of \p Plan. This may restrict the
2199/// resulting plan to \p BestVF and \p BestUF.
2201 unsigned BestUF,
2203 VPRegionBlock *VectorRegion = Plan.getVectorLoopRegion();
2204 VPBasicBlock *ExitingVPBB = VectorRegion->getExitingBasicBlock();
2205 auto *Term = &ExitingVPBB->back();
2206 VPValue *Cond;
2207 auto m_CanIVInc = m_Add(m_VPValue(), m_Specific(&Plan.getVFxUF()));
2208 // Check if the branch condition compares the canonical IV increment (for main
2209 // loop), or the canonical IV increment plus an offset (for epilog loop).
2210 if (match(Term, m_BranchOnCount(
2211 m_CombineOr(m_CanIVInc, m_c_Add(m_CanIVInc, m_LiveIn())),
2212 m_VPValue())) ||
2214 m_VPValue(), m_VPValue(), m_VPValue()))))) {
2215 // Try to simplify the branch condition if VectorTC <= VF * UF when the
2216 // latch terminator is BranchOnCount or BranchOnCond(Not(ActiveLaneMask)).
2217 const SCEV *VectorTripCount =
2219 if (isa<SCEVCouldNotCompute>(VectorTripCount))
2220 VectorTripCount =
2222 assert(!isa<SCEVCouldNotCompute>(VectorTripCount) &&
2223 "Trip count SCEV must be computable");
2224 ScalarEvolution &SE = *PSE.getSE();
2225 ElementCount NumElements = BestVF.multiplyCoefficientBy(BestUF);
2226 const SCEV *C = SE.getElementCount(VectorTripCount->getType(), NumElements);
2227 if (!SE.isKnownPredicate(CmpInst::ICMP_ULE, VectorTripCount, C))
2228 return false;
2229 } else if (match(Term, m_BranchOnCond(m_VPValue(Cond))) ||
2231 // For BranchOnCond, check if we can prove the condition to be true using VF
2232 // and UF.
2233 if (!isConditionTrueViaVFAndUF(Cond, Plan, BestVF, BestUF, PSE))
2234 return false;
2235 } else {
2236 return false;
2237 }
2238
2239 // The vector loop region only executes once. Convert terminator of the
2240 // exiting block to exit in the first iteration.
2241 if (match(Term, m_BranchOnTwoConds())) {
2242 Term->setOperand(1, Plan.getTrue());
2243 return true;
2244 }
2245
2246 auto *BOC = new VPInstruction(VPInstruction::BranchOnCond, Plan.getTrue(), {},
2247 {}, Term->getDebugLoc());
2248 ExitingVPBB->appendRecipe(BOC);
2249 Term->eraseFromParent();
2250
2251 return true;
2252}
2253
2255 unsigned BestUF,
2257 assert(Plan.hasVF(BestVF) && "BestVF is not available in Plan");
2258 assert(Plan.hasUF(BestUF) && "BestUF is not available in Plan");
2259
2260 bool MadeChange = tryToReplaceALMWithWideALM(Plan, BestVF, BestUF);
2261 MadeChange |= simplifyBranchConditionForVFAndUF(Plan, BestVF, BestUF, PSE);
2262 MadeChange |= optimizeVectorInductionWidthForTCAndVFUF(Plan, BestVF, BestUF);
2263
2264 if (MadeChange) {
2265 Plan.setVF(BestVF);
2266 assert(Plan.getConcreteUF() == BestUF && "BestUF must match the Plan's UF");
2267 }
2268}
2269
2271 for (VPRecipeBase &R :
2273 auto *PhiR = dyn_cast<VPReductionPHIRecipe>(&R);
2274 if (!PhiR)
2275 continue;
2276 RecurKind RK = PhiR->getRecurrenceKind();
2277 if (RK != RecurKind::Add && RK != RecurKind::Mul && RK != RecurKind::Sub &&
2279 continue;
2280
2282 if (auto *RecWithFlags = dyn_cast<VPRecipeWithIRFlags>(U)) {
2283 RecWithFlags->dropPoisonGeneratingFlags();
2284 }
2285 }
2286}
2287
2288namespace {
2289struct VPCSEDenseMapInfo : public DenseMapInfo<VPSingleDefRecipe *> {
2290 /// If recipe \p R will lower to a GEP with a non-i8 source element type,
2291 /// return that source element type.
2292 static Type *getGEPSourceElementType(const VPSingleDefRecipe *R) {
2293 // All VPInstructions that lower to GEPs must have the i8 source element
2294 // type (as they are PtrAdds), so we omit it.
2296 .Case([](const VPReplicateRecipe *I) -> Type * {
2297 if (auto *GEP = dyn_cast<GetElementPtrInst>(I->getUnderlyingValue()))
2298 return GEP->getSourceElementType();
2299 return nullptr;
2300 })
2301 .Case<VPVectorPointerRecipe, VPWidenGEPRecipe>(
2302 [](auto *I) { return I->getSourceElementType(); })
2303 .Default([](auto *) { return nullptr; });
2304 }
2305
2306 /// Returns true if recipe \p Def can be safely handed for CSE.
2307 static bool canHandle(const VPSingleDefRecipe *Def) {
2308 // We can extend the list of handled recipes in the future,
2309 // provided we account for the data embedded in them while checking for
2310 // equality or hashing.
2312
2313 // The issue with (Insert|Extract)Value is that the index of the
2314 // insert/extract is not a proper operand in LLVM IR, and hence also not in
2315 // VPlan.
2316 if (!C || (!C->first && (C->second == Instruction::InsertValue ||
2317 C->second == Instruction::ExtractValue)))
2318 return false;
2319
2320 // During CSE, we can only handle non-memory recipes, as memory can alias.
2321 return !Def->mayReadOrWriteMemory();
2322 }
2323
2324 /// Hash the underlying data of \p Def.
2325 static unsigned getHashValue(const VPSingleDefRecipe *Def) {
2326 hash_code Result = hash_combine(
2327 Def->getVPRecipeID(), vputils::getOpcodeOrIntrinsicID(Def),
2328 getGEPSourceElementType(Def), Def->getScalarType(),
2330 if (auto *RFlags = dyn_cast<VPRecipeWithIRFlags>(Def))
2331 if (RFlags->hasPredicate())
2332 return hash_combine(Result, RFlags->getPredicate());
2333 if (auto *SIVSteps = dyn_cast<VPScalarIVStepsRecipe>(Def))
2334 return hash_combine(Result, SIVSteps->getInductionOpcode());
2335 return Result;
2336 }
2337
2338 /// Check equality of underlying data of \p L and \p R.
2339 static bool isEqual(const VPSingleDefRecipe *L, const VPSingleDefRecipe *R) {
2340 if (L->getVPRecipeID() != R->getVPRecipeID() ||
2343 getGEPSourceElementType(L) != getGEPSourceElementType(R) ||
2345 !equal(L->operands(), R->operands()))
2346 return false;
2349 "must have valid opcode info for both recipes");
2350 if (auto *LFlags = dyn_cast<VPRecipeWithIRFlags>(L))
2351 if (LFlags->hasPredicate() &&
2352 LFlags->getPredicate() !=
2353 cast<VPRecipeWithIRFlags>(R)->getPredicate())
2354 return false;
2355 if (auto *LSIV = dyn_cast<VPScalarIVStepsRecipe>(L))
2356 if (LSIV->getInductionOpcode() !=
2357 cast<VPScalarIVStepsRecipe>(R)->getInductionOpcode())
2358 return false;
2359 // Phi recipes can only be equal if they are in the same VPBB, as they
2360 // implicitly depend on their predecessors.
2361 if (isa<VPWidenPHIRecipe>(L) && L->getParent() != R->getParent())
2362 return false;
2363 // Recipes in replicate regions implicitly depend on predicate. If either
2364 // recipe is in a replicate region, only consider them equal if both have
2365 // the same parent.
2366 const VPRegionBlock *RegionL = L->getRegion();
2367 const VPRegionBlock *RegionR = R->getRegion();
2368 if (((RegionL && RegionL->isReplicator()) ||
2369 (RegionR && RegionR->isReplicator())) &&
2370 L->getParent() != R->getParent())
2371 return false;
2372 return L->getScalarType() == R->getScalarType();
2373 }
2374};
2375} // end anonymous namespace
2376
2377/// Perform a common-subexpression-elimination of VPSingleDefRecipes on the \p
2378/// Plan.
2380 VPDominatorTree VPDT(Plan);
2382
2384 Plan.getEntry());
2386 for (VPRecipeBase &R : *VPBB) {
2387 auto *Def = dyn_cast<VPSingleDefRecipe>(&R);
2388 if (!Def || !VPCSEDenseMapInfo::canHandle(Def))
2389 continue;
2390 if (VPSingleDefRecipe *V = CSEMap.lookup(Def)) {
2391 // V must dominate Def for a valid replacement.
2392 if (!VPDT.dominates(V->getParent(), VPBB))
2393 continue;
2394 // Only keep flags present on both V and Def.
2395 if (auto *RFlags = dyn_cast<VPRecipeWithIRFlags>(V))
2396 RFlags->intersectFlags(*cast<VPRecipeWithIRFlags>(Def));
2397 Def->replaceAllUsesWith(V);
2398 continue;
2399 }
2400 CSEMap[Def] = Def;
2401 }
2402 }
2403}
2404
2405/// Return true if we do not know how to (mechanically) hoist or sink a
2406/// non-memory or memory recipe \p R out of a loop region. When sinking, passing
2407/// \p Sinking = true ensures that assumes aren't sunk.
2409 VPBasicBlock *LastBB,
2410 bool Sinking = false) {
2411 if (!isa<VPReplicateRecipe>(R) || !R.mayReadOrWriteMemory() ||
2413 return vputils::cannotHoistOrSinkRecipe(R, Sinking);
2414
2415 // Check that the memory operation doesn't alias between FirstBB and LastBB.
2416 auto MemLoc = vputils::getMemoryLocation(R);
2417
2418 // TODO: Could make use of SinkStoreInfo::isNoAliasViaDistance by collecting
2419 // stores upfront, and constructing a full SinkStoreInfo.
2420 auto SinkInfo =
2421 Sinking ? std::make_optional(SinkStoreInfo(cast<VPReplicateRecipe>(R)))
2422 : std::nullopt;
2423
2424 return !MemLoc ||
2425 !canHoistOrSinkWithNoAliasCheck(*MemLoc, FirstBB, LastBB, SinkInfo);
2426}
2427
2428/// Move loop-invariant recipes out of the vector loop region in \p Plan.
2429static void licm(VPlan &Plan) {
2430 VPBasicBlock *Preheader = Plan.getVectorPreheader();
2431
2432 // Hoist any loop invariant recipes from the vector loop region to the
2433 // preheader. Preform a shallow traversal of the vector loop region, to
2434 // exclude recipes in replicate regions. Since the top-level blocks in the
2435 // vector loop region are guaranteed to execute if the vector pre-header is,
2436 // we don't need to check speculation safety.
2437 VPRegionBlock *LoopRegion = Plan.getVectorLoopRegion();
2438 assert(Preheader->getSingleSuccessor() == LoopRegion &&
2439 "Expected vector prehader's successor to be the vector loop region");
2441 vp_depth_first_shallow(LoopRegion->getEntry()))) {
2442 for (VPRecipeBase &R : make_early_inc_range(*VPBB)) {
2443 if (cannotHoistOrSinkRecipe(R, LoopRegion->getEntryBasicBlock(),
2444 LoopRegion->getExitingBasicBlock()))
2445 continue;
2446 if (any_of(R.operands(), [](VPValue *Op) {
2447 return !Op->isDefinedOutsideLoopRegions();
2448 }))
2449 continue;
2450 R.moveBefore(*Preheader, Preheader->end());
2451 }
2452 }
2453
2454#ifndef NDEBUG
2455 VPDominatorTree VPDT(Plan);
2456#endif
2457 // Sink recipes with no users inside the vector loop region if all users are
2458 // in the same exit block of the region.
2459 // TODO: Extend to sink recipes from inner loops.
2461 LoopRegion->getEntry());
2463 for (VPRecipeBase &R : make_early_inc_range(reverse(*VPBB))) {
2464 if (cannotHoistOrSinkRecipe(R, LoopRegion->getEntryBasicBlock(),
2465 LoopRegion->getExitingBasicBlock(),
2466 /*Sinking=*/true))
2467 continue;
2468
2469 if (auto *RepR = dyn_cast<VPReplicateRecipe>(&R)) {
2470 assert(!RepR->isPredicated() &&
2471 "Expected prior transformation of predicated replicates to "
2472 "replicate regions");
2473 // narrowToSingleScalarRecipes should have already maximally narrowed
2474 // replicates to single-scalar replicates.
2475 // TODO: When unrolling, replicateByVF doesn't handle sunk
2476 // non-single-scalar replicates correctly.
2477 if (!RepR->isSingleScalar())
2478 continue;
2479
2480 // The pointer operand of stores must be loop-invariant.
2481 if (RepR->getOpcode() == Instruction::Store &&
2482 !RepR->getOperand(1)->isDefinedOutsideLoopRegions())
2483 continue;
2484 }
2485
2486 [[maybe_unused]] auto *RepR = dyn_cast<VPReplicateRecipe>(&R);
2487 assert((!R.mayWriteToMemory() ||
2488 (RepR && RepR->getOpcode() == Instruction::Store &&
2489 RepR->getOperand(1)->isDefinedOutsideLoopRegions())) &&
2490 "The only recipes that may write to memory are expected to be "
2491 "stores with invariant pointer-operand");
2492
2493 // TODO: Use R.definedValues() instead of casting to VPSingleDefRecipe to
2494 // support recipes with multiple defined values (e.g., interleaved loads).
2495 auto *Def = cast<VPSingleDefRecipe>(&R);
2496
2497 // Cannot sink the recipe if the user is defined in a loop region or a
2498 // non-successor of the vector loop region. Cannot sink if user is a phi
2499 // either.
2500 VPBasicBlock *SinkBB = nullptr;
2501 if (any_of(Def->users(), [&SinkBB, &LoopRegion](VPUser *U) {
2502 auto *UserR = cast<VPRecipeBase>(U);
2503 VPBasicBlock *Parent = UserR->getParent();
2504 // TODO: Support sinking when users are in multiple blocks.
2505 if (SinkBB && SinkBB != Parent)
2506 return true;
2507 SinkBB = Parent;
2508 // TODO: If the user is a PHI node, we should check the block of
2509 // incoming value. Support PHI node users if needed.
2510 return UserR->isPhi() || Parent->getEnclosingLoopRegion() ||
2511 Parent->getSinglePredecessor() != LoopRegion;
2512 }))
2513 continue;
2514
2515 if (!SinkBB)
2516 SinkBB = cast<VPBasicBlock>(LoopRegion->getSingleSuccessor());
2517
2518 // TODO: This will need to be a check instead of a assert after
2519 // conditional branches in vectorized loops are supported.
2520 assert(VPDT.properlyDominates(VPBB, SinkBB) &&
2521 "Defining block must dominate sink block");
2522 // TODO: Clone the recipe if users are on multiple exit paths, instead of
2523 // just moving.
2524 Def->moveBefore(*SinkBB, SinkBB->getFirstNonPhi());
2525 }
2526 }
2527}
2528
2530 VPlan &Plan, const MapVector<Instruction *, uint64_t> &MinBWs) {
2531 if (Plan.hasScalarVFOnly())
2532 return;
2533 // Keep track of created truncates, so they can be re-used. Note that we
2534 // cannot use RAUW after creating a new truncate, as this would could make
2535 // other uses have different types for their operands, making them invalidly
2536 // typed.
2538 VPBasicBlock *PH = Plan.getVectorPreheader();
2541 for (VPRecipeBase &R : make_early_inc_range(*VPBB)) {
2544 continue;
2545
2546 VPValue *ResultVPV = R.getVPSingleValue();
2547 auto *UI = cast_or_null<Instruction>(ResultVPV->getUnderlyingValue());
2548 unsigned NewResSizeInBits = MinBWs.lookup(UI);
2549 if (!NewResSizeInBits)
2550 continue;
2551
2552 // If the value wasn't vectorized, we must maintain the original scalar
2553 // type. Skip those here, after incrementing NumProcessedRecipes. Also
2554 // skip casts which do not need to be handled explicitly here, as
2555 // redundant casts will be removed during recipe simplification.
2557 continue;
2558
2559 Type *OldResTy = ResultVPV->getScalarType();
2560 unsigned OldResSizeInBits = OldResTy->getScalarSizeInBits();
2561 assert(OldResTy->isIntegerTy() && "only integer types supported");
2562 (void)OldResSizeInBits;
2563
2564 auto *NewResTy = IntegerType::get(Plan.getContext(), NewResSizeInBits);
2565
2566 // Any wrapping introduced by shrinking this operation shouldn't be
2567 // considered undefined behavior. So, we can't unconditionally copy
2568 // arithmetic wrapping flags to VPW.
2569 if (auto *VPW = dyn_cast<VPRecipeWithIRFlags>(&R))
2570 VPW->dropPoisonGeneratingFlags();
2571
2572 assert((OldResSizeInBits != NewResSizeInBits ||
2573 match(&R, m_ICmp(m_VPValue(), m_VPValue()))) &&
2574 "Only ICmps should not need extending the result.");
2575 assert(!isa<VPWidenStoreRecipe>(&R) && "stores cannot be narrowed");
2576
2577 // For loads/intrinsics we don't recreate the recipe; just wrap the
2578 // original wide result in a ZExt to OldResTy.
2580 if (OldResSizeInBits != NewResSizeInBits) {
2582 Instruction::ZExt, ResultVPV, OldResTy);
2583 ResultVPV->replaceAllUsesWith(Ext);
2584 Ext->setOperand(0, ResultVPV);
2585 }
2586 continue;
2587 }
2588
2589 // Shrink operands by introducing truncates as needed.
2590 unsigned StartIdx =
2591 match(&R, m_Select(m_VPValue(), m_VPValue(), m_VPValue())) ? 1 : 0;
2592 SmallVector<VPValue *> NewOperands(R.operands());
2593 for (VPValue *&Op : drop_begin(NewOperands, StartIdx)) {
2594 unsigned OpSizeInBits = Op->getScalarType()->getScalarSizeInBits();
2595 if (OpSizeInBits == NewResSizeInBits)
2596 continue;
2597 assert(OpSizeInBits > NewResSizeInBits && "nothing to truncate");
2598 auto [ProcessedIter, Inserted] = ProcessedTruncs.try_emplace(Op);
2599 if (Inserted) {
2600 VPBuilder Builder;
2601 if (isa<VPIRValue>(Op))
2602 Builder.setInsertPoint(PH);
2603 else
2604 Builder.setInsertPoint(&R);
2605 ProcessedIter->second =
2606 Builder.createWidenCast(Instruction::Trunc, Op, NewResTy);
2607 }
2608 Op = ProcessedIter->second;
2609 }
2610
2611 auto *NWR = cast<VPWidenRecipe>(&R)->cloneWithOperands(NewOperands);
2612 NWR->insertBefore(&R);
2613
2614 // Wrap NWR in a ZExt to preserve the original wide type for downstream
2615 // users (unless this is an ICmp, which produces i1 regardless).
2616 VPValue *Replacement = NWR->getVPSingleValue();
2617 if (OldResSizeInBits != NewResSizeInBits)
2618 Replacement =
2620 .createWidenCast(Instruction::ZExt, Replacement, OldResTy)
2621 ->getVPSingleValue();
2622 ResultVPV->replaceAllUsesWith(Replacement);
2623 R.eraseFromParent();
2624 }
2625 }
2626}
2627
2628bool VPlanTransforms::removeBranchOnConst(VPlan &Plan, bool OnlyLatches) {
2629 std::optional<VPDominatorTree> VPDT;
2630 if (OnlyLatches)
2631 VPDT.emplace(Plan);
2632
2633 // Collect all blocks before modifying the CFG so we can identify unreachable
2634 // ones after constant branch removal.
2636
2637 bool SimplifiedPhi = false;
2638 for (VPBasicBlock *VPBB : VPBlockUtils::blocksOnly<VPBasicBlock>(AllBlocks)) {
2639 VPValue *Cond;
2640 // Skip blocks that are not terminated by BranchOnCond.
2641 if (VPBB->empty() || !match(&VPBB->back(), m_BranchOnCond(m_VPValue(Cond))))
2642 continue;
2643
2644 if (OnlyLatches && !VPBlockUtils::isLatch(VPBB, *VPDT))
2645 continue;
2646
2647 assert(VPBB->getNumSuccessors() == 2 &&
2648 "Two successors expected for BranchOnCond");
2649 unsigned RemovedIdx;
2650 if (match(Cond, m_True()))
2651 RemovedIdx = 1;
2652 else if (match(Cond, m_False()))
2653 RemovedIdx = 0;
2654 else
2655 continue;
2656
2657 VPBasicBlock *RemovedSucc =
2658 cast<VPBasicBlock>(VPBB->getSuccessors()[RemovedIdx]);
2659 assert(count(RemovedSucc->getPredecessors(), VPBB) == 1 &&
2660 "There must be a single edge between VPBB and its successor");
2661 // Values coming from VPBB into phi recipes of RemovedSucc are removed from
2662 // these recipes.
2663 auto Phis = RemovedSucc->phis();
2664 for (VPRecipeBase &R : Phis)
2665 cast<VPPhiAccessors>(&R)->removeIncomingValueFor(VPBB);
2666 SimplifiedPhi |= !std::empty(Phis);
2667
2668 // Disconnect blocks and remove the terminator.
2669 VPBlockUtils::disconnectBlocks(VPBB, RemovedSucc);
2670 VPBB->back().eraseFromParent();
2671 }
2672
2673 // Compute which blocks are still reachable from the entry after constant
2674 // branch removal.
2677
2678 // Detach all unreachable blocks from their successors, removing their recipes
2679 // and incoming values from phi recipes.
2680 VPSymbolicValue Tmp(nullptr);
2681 for (VPBlockBase *B : AllBlocks) {
2682 if (Reachable.contains(B))
2683 continue;
2684 for (VPBlockBase *Succ : to_vector(B->successors())) {
2685 if (auto *SuccBB = dyn_cast<VPBasicBlock>(Succ))
2686 for (VPRecipeBase &R : SuccBB->phis())
2687 cast<VPPhiAccessors>(&R)->removeIncomingValueFor(B);
2689 }
2690 for (VPBasicBlock *DeadBB :
2692 for (VPRecipeBase &R : make_early_inc_range(*DeadBB)) {
2693 for (VPValue *Def : R.definedValues())
2694 Def->replaceAllUsesWith(&Tmp);
2695 R.eraseFromParent();
2696 }
2697 }
2698 }
2699 return SimplifiedPhi;
2700}
2701
2722
2723// Add a VPActiveLaneMaskPHIRecipe and related recipes to \p Plan and replace
2724// the loop terminator with a branch-on-cond recipe with the negated
2725// active-lane-mask as operand. Note that this turns the loop into an
2726// uncountable one. Only the existing terminator is replaced, all other existing
2727// recipes/users remain unchanged, except for poison-generating flags being
2728// dropped from the canonical IV increment. Return the created
2729// VPActiveLaneMaskPHIRecipe.
2730//
2731// The function adds the following recipes:
2732//
2733// vector.ph:
2734// %EntryInc = canonical-iv-increment-for-part CanonicalIVStart
2735// %EntryALM = active-lane-mask %EntryInc, TC
2736//
2737// vector.body:
2738// ...
2739// %P = active-lane-mask-phi [ %EntryALM, %vector.ph ], [ %ALM, %vector.body ]
2740// ...
2741// %InLoopInc = canonical-iv-increment-for-part CanonicalIVIncrement
2742// %ALM = active-lane-mask %InLoopInc, TC
2743// %Negated = Not %ALM
2744// branch-on-cond %Negated
2745//
2748 VPRegionBlock *TopRegion = Plan.getVectorLoopRegion();
2749 VPBasicBlock *EB = TopRegion->getExitingBasicBlock();
2750 VPValue *StartV = Plan.getZero(TopRegion->getCanonicalIVType());
2751 auto *CanonicalIVIncrement = TopRegion->getOrCreateCanonicalIVIncrement();
2752 // TODO: Check if dropping the flags is needed.
2753 TopRegion->clearCanonicalIVNUW(CanonicalIVIncrement);
2754 DebugLoc DL = CanonicalIVIncrement->getDebugLoc();
2755 // We can't use StartV directly in the ActiveLaneMask VPInstruction, since
2756 // we have to take unrolling into account. Each part needs to start at
2757 // Part * VF
2758 auto *VecPreheader = Plan.getVectorPreheader();
2759 VPBuilder Builder(VecPreheader);
2760
2761 // Create the ActiveLaneMask instruction using the correct start values.
2762 VPValue *TC = Plan.getTripCount();
2763 VPValue *VF = &Plan.getVF();
2764
2765 auto *EntryIncrement =
2766 Builder.createOverflowingOp(VPInstruction::CanonicalIVIncrementForPart,
2767 {StartV, VF}, {}, DL, "index.part.next");
2768
2769 // Create the active lane mask instruction in the VPlan preheader.
2770 VPValue *ALMMultiplier =
2771 Plan.getConstantInt(TopRegion->getCanonicalIVType(), 1);
2772 auto *EntryALM = Builder.createNaryOp(VPInstruction::ActiveLaneMask,
2773 {EntryIncrement, TC, ALMMultiplier}, DL,
2774 "active.lane.mask.entry");
2775
2776 // Now create the ActiveLaneMaskPhi recipe in the main loop using the
2777 // preheader ActiveLaneMask instruction.
2778 auto *LaneMaskPhi =
2780 auto *HeaderVPBB = TopRegion->getEntryBasicBlock();
2781 LaneMaskPhi->insertBefore(*HeaderVPBB, HeaderVPBB->begin());
2782
2783 // Create the active lane mask for the next iteration of the loop before the
2784 // original terminator.
2785 VPRecipeBase *OriginalTerminator = EB->getTerminator();
2786 Builder.setInsertPoint(OriginalTerminator);
2787 auto *InLoopIncrement = Builder.createOverflowingOp(
2789 {CanonicalIVIncrement, &Plan.getVF()}, {}, DL);
2790 auto *ALM = Builder.createNaryOp(VPInstruction::ActiveLaneMask,
2791 {InLoopIncrement, TC, ALMMultiplier}, DL,
2792 "active.lane.mask.next");
2793 LaneMaskPhi->addBackedgeValue(ALM);
2794
2795 // Replace the original terminator with BranchOnCond. We have to invert the
2796 // mask here because a true condition means jumping to the exit block.
2797 auto *NotMask = Builder.createNot(ALM, DL);
2798 Builder.createNaryOp(VPInstruction::BranchOnCond, {NotMask}, DL);
2799 OriginalTerminator->eraseFromParent();
2800 return LaneMaskPhi;
2801}
2802
2804 VPlan &Plan, bool UseActiveLaneMask, bool UseActiveLaneMaskForControlFlow) {
2805 VPRegionBlock *LoopRegion = Plan.getVectorLoopRegion();
2806 VPValue *HeaderMask = LoopRegion->getUsedHeaderMask();
2807 if (!HeaderMask)
2808 return;
2809
2810 if (UseActiveLaneMaskForControlFlow) {
2812 return;
2813 }
2814
2815 VPBasicBlock *Header = LoopRegion->getEntryBasicBlock();
2816 VPBuilder Builder(Header, Header->getFirstNonPhi());
2817 auto *WideCanonicalIV = Builder.insert(new VPWidenCanonicalIVRecipe(
2818 LoopRegion->getCanonicalIV(),
2819 VPIRFlags::WrapFlagsTy(/*HasNUW=*/true, /*HasNSW=*/false)));
2820 VPValue *Mask;
2821 if (UseActiveLaneMask) {
2822 VPValue *ALMMultiplier =
2823 Plan.getConstantInt(LoopRegion->getCanonicalIVType(), 1);
2824 Mask = Builder.createNaryOp(
2826 {WideCanonicalIV, Plan.getTripCount(), ALMMultiplier}, nullptr,
2827 "active.lane.mask");
2828 } else {
2829 Mask = Builder.createICmp(CmpInst::ICMP_ULE, WideCanonicalIV,
2831 }
2832 HeaderMask->replaceAllUsesWith(Mask);
2833}
2834
2836 VPlan &Plan, PredicatedScalarEvolution &PSE,
2837 const DenseMap<Value *, const SCEV *> &StridesMap,
2838 const VPDominatorTree &VPDT) {
2839 // Replace VPValues for known constant strides guaranteed by predicated scalar
2840 // evolution that are guaranteed to be guarded by the runtime checks; that is,
2841 // blocks dominated by the vector preheader.
2842 assert(!Plan.getVectorLoopRegion() &&
2843 "expected to run before loop regions are created");
2844 VPBlockBase *Preheader = Plan.getEntry()->getSuccessors()[1];
2845 auto CanUseVersionedStride = [&VPDT, Preheader](VPUser &U, unsigned) {
2846 auto *R = cast<VPRecipeBase>(&U);
2847 VPBlockBase *Parent = R->getParent();
2848 return VPDT.dominates(Preheader, Parent);
2849 };
2850 ValueToSCEVMapTy RewriteMap;
2851 for (const SCEV *Stride : StridesMap.values()) {
2852 using namespace SCEVPatternMatch;
2853 auto *StrideV = cast<SCEVUnknown>(Stride)->getValue();
2854 const APInt *StrideConst;
2855 if (!match(PSE.getSCEV(StrideV), m_scev_APInt(StrideConst)))
2856 // Only handle constant strides for now.
2857 continue;
2858
2859 auto *CI = Plan.getConstantInt(*StrideConst);
2860 if (VPValue *StrideVPV = Plan.getLiveIn(StrideV))
2861 StrideVPV->replaceUsesWithIf(CI, CanUseVersionedStride);
2862
2863 // The versioned value may not be used in the loop directly but through a
2864 // sext/zext. Add new live-ins in those cases.
2865 for (Value *U : StrideV->users()) {
2867 continue;
2868 VPValue *StrideVPV = Plan.getLiveIn(U);
2869 if (!StrideVPV)
2870 continue;
2871 unsigned BW = U->getType()->getScalarSizeInBits();
2872 APInt C =
2873 isa<SExtInst>(U) ? StrideConst->sext(BW) : StrideConst->zext(BW);
2874 VPValue *CI = Plan.getConstantInt(C);
2875 StrideVPV->replaceUsesWithIf(CI, CanUseVersionedStride);
2876 }
2877 RewriteMap[StrideV] = PSE.getSCEV(StrideV);
2878 }
2879
2880 for (VPRecipeBase &R : *Plan.getEntry()) {
2881 auto *ExpSCEV = dyn_cast<VPExpandSCEVRecipe>(&R);
2882 if (!ExpSCEV)
2883 continue;
2884 const SCEV *ScevExpr = ExpSCEV->getSCEV();
2885 auto *NewSCEV =
2886 SCEVParameterRewriter::rewrite(ScevExpr, *PSE.getSE(), RewriteMap);
2887 if (NewSCEV != ScevExpr) {
2888 VPValue *NewExp = vputils::getOrCreateVPValueForSCEVExpr(Plan, NewSCEV);
2889 ExpSCEV->replaceAllUsesWith(NewExp);
2890 if (Plan.getTripCount() == ExpSCEV)
2891 Plan.resetTripCount(NewExp);
2892 }
2893 }
2894}
2895
2897 // Collect recipes in the backward slice of `Root` that may generate a poison
2898 // value that is used after vectorization.
2900 auto CollectPoisonGeneratingInstrsInBackwardSlice([&](VPRecipeBase *Root) {
2902 Worklist.push_back(Root);
2903
2904 // Traverse the backward slice of Root through its use-def chain.
2905 while (!Worklist.empty()) {
2906 VPRecipeBase *CurRec = Worklist.pop_back_val();
2907
2908 if (!Visited.insert(CurRec).second)
2909 continue;
2910
2911 // Prune search if we find another recipe generating a widen memory
2912 // instruction. Widen memory instructions involved in address computation
2913 // will lead to gather/scatter instructions, which don't need to be
2914 // handled.
2916 VPHeaderPHIRecipe>(CurRec))
2917 continue;
2918
2919 // This recipe contributes to the address computation of a widen
2920 // load/store. If the underlying instruction has poison-generating flags,
2921 // drop them directly.
2922 if (auto *RecWithFlags = dyn_cast<VPRecipeWithIRFlags>(CurRec)) {
2923 VPValue *A, *B;
2924 // Dropping disjoint from an OR may yield incorrect results, as some
2925 // analysis may have converted it to an Add implicitly (e.g. SCEV used
2926 // for dependence analysis). Instead, replace it with an equivalent Add.
2927 // This is possible as all users of the disjoint OR only access lanes
2928 // where the operands are disjoint or poison otherwise.
2929 if (match(RecWithFlags, m_BinaryOr(m_VPValue(A), m_VPValue(B))) &&
2930 RecWithFlags->isDisjoint()) {
2931 VPBuilder Builder(RecWithFlags);
2932 VPInstruction *New =
2933 Builder.createAdd(A, B, RecWithFlags->getDebugLoc());
2934 New->setUnderlyingValue(RecWithFlags->getUnderlyingValue());
2935 RecWithFlags->replaceAllUsesWith(New);
2936 RecWithFlags->eraseFromParent();
2937 CurRec = New;
2938 } else
2939 RecWithFlags->dropPoisonGeneratingFlags();
2940 } else {
2943 (void)Instr;
2944 assert((!Instr || !Instr->hasPoisonGeneratingFlags()) &&
2945 "found instruction with poison generating flags not covered by "
2946 "VPRecipeWithIRFlags");
2947 }
2948
2949 // Add new definitions to the worklist.
2950 for (VPValue *Operand : CurRec->operands())
2951 if (VPRecipeBase *OpDef = Operand->getDefiningRecipe())
2952 Worklist.push_back(OpDef);
2953 }
2954 });
2955
2956 // We want to exclude the tail folding case, as we don't need to drop flags
2957 // for operations computing the first lane in this case: the first lane of the
2958 // header mask must always be true. For reverse memory accesses, the mask is
2959 // wrapped in a Reverse, which is just a permutation of the header mask, so
2960 // peel it off before checking. The header mask is still the abstract region
2961 // value at this point (materialization happens later).
2962 auto IsNotHeaderMask = [](VPValue *Mask) {
2963 return Mask &&
2965 };
2966
2967 // Traverse all the recipes in the VPlan and collect the poison-generating
2968 // recipes in the backward slice starting at the address of a VPWidenRecipe or
2969 // VPInterleaveRecipe.
2970 auto Iter =
2973 for (VPRecipeBase &Recipe : *VPBB) {
2974 if (auto *WidenRec = dyn_cast<VPWidenMemoryRecipe>(&Recipe)) {
2975 VPRecipeBase *AddrDef = WidenRec->getAddr()->getDefiningRecipe();
2976 if (AddrDef && WidenRec->isConsecutive() &&
2977 IsNotHeaderMask(WidenRec->getMask()))
2978 CollectPoisonGeneratingInstrsInBackwardSlice(AddrDef);
2979 } else if (auto *InterleaveRec = dyn_cast<VPInterleaveRecipe>(&Recipe)) {
2980 VPRecipeBase *AddrDef = InterleaveRec->getAddr()->getDefiningRecipe();
2981 if (AddrDef && IsNotHeaderMask(InterleaveRec->getMask()))
2982 CollectPoisonGeneratingInstrsInBackwardSlice(AddrDef);
2983 }
2984 }
2985 }
2986}
2987
2989 VPlan &Plan,
2991 &InterleaveGroups,
2992 const bool &EpilogueAllowed) {
2993 if (InterleaveGroups.empty())
2994 return;
2995
2997 for (VPBasicBlock *VPBB :
3000 for (VPRecipeBase &R : make_filter_range(*VPBB, [](VPRecipeBase &R) {
3001 return isa<VPWidenMemoryRecipe>(&R);
3002 })) {
3003 auto *MemR = cast<VPWidenMemoryRecipe>(&R);
3004 IRMemberToRecipe[&MemR->getIngredient()] = MemR;
3005 }
3006
3007 // Interleave memory: for each Interleave Group we marked earlier as relevant
3008 // for this VPlan, replace the Recipes widening its memory instructions with a
3009 // single VPInterleaveRecipe at its insertion point.
3010 VPDominatorTree VPDT(Plan);
3011 for (const auto *IG : InterleaveGroups) {
3012 VPWidenMemoryRecipe *Start = nullptr;
3013 Instruction *StartMember = nullptr;
3014 for (auto *Member : IG->members())
3015 if (VPWidenMemoryRecipe *R = IRMemberToRecipe.lookup(Member)) {
3016 StartMember = Member;
3017 Start = R;
3018 break;
3019 }
3020 if (!StartMember) // All member recipes are dead, so the group is dead.
3021 continue;
3022 VPIRMetadata InterleaveMD(*Start);
3023 SmallVector<VPValue *, 4> StoredValues;
3024 for (unsigned I = 0; I < IG->getFactor(); ++I) {
3025 Instruction *MemberI = IG->getMember(I);
3026 if (!MemberI)
3027 continue;
3028 if (VPWidenMemoryRecipe *MemoryR = IRMemberToRecipe.lookup(MemberI)) {
3029 if (auto *StoreR = dyn_cast<VPWidenStoreRecipe>(MemoryR->getAsRecipe()))
3030 StoredValues.push_back(StoreR->getStoredValue());
3031 InterleaveMD.intersect(*MemoryR);
3032 } else {
3033 InterleaveMD.intersect(VPIRMetadata(*MemberI));
3034 }
3035 }
3036
3037 bool NeedsMaskForGaps =
3038 (IG->requiresScalarEpilogue() && !EpilogueAllowed) ||
3039 (!StoredValues.empty() && !IG->isFull());
3040
3041 Instruction *IRInsertPos = IG->getInsertPos();
3042 auto *InsertPos = IRMemberToRecipe.lookup(IRInsertPos);
3043 if (!InsertPos) {
3044 // InsertPos member is dead: find a new member that is alive.
3045 assert(isa<VPWidenLoadRecipe>(Start->getAsRecipe()) &&
3046 "Dead member in non-load group?");
3047 InsertPos = Start;
3048 for (Instruction *Member : IG->members())
3049 if (VPWidenMemoryRecipe *MemberR = IRMemberToRecipe.lookup(Member))
3050 if (VPDT.properlyDominates(MemberR->getAsRecipe(),
3051 InsertPos->getAsRecipe()))
3052 InsertPos = MemberR;
3053 IRInsertPos = &InsertPos->getIngredient();
3054 }
3055 VPRecipeBase *InsertPosR = InsertPos->getAsRecipe();
3056
3058 if (auto *Gep = dyn_cast<GetElementPtrInst>(
3059 getLoadStorePointerOperand(IRInsertPos)->stripPointerCasts()))
3060 NW = Gep->getNoWrapFlags().withoutNoUnsignedWrap();
3061
3062 // Get or create the start address for the interleave group.
3063 VPValue *Addr = Start->getAddr();
3064 VPRecipeBase *AddrDef = Addr->getDefiningRecipe();
3065 if (IG->getIndex(StartMember) != 0 ||
3066 (AddrDef && !VPDT.properlyDominates(AddrDef, InsertPosR))) {
3067 // Either member zero's recipe is dead, or we cannot re-use the address of
3068 // member zero because it does not dominate the insert position. Instead,
3069 // use the address of the insert position and create a PtrAdd adjusting it
3070 // to the address of member zero.
3071 // TODO: Hoist Addr's defining recipe (and any operands as needed) to
3072 // InsertPos or sink loads above zero members to join it.
3073 assert(IG->getIndex(IRInsertPos) != 0 &&
3074 "index of insert position shouldn't be zero");
3075 auto &DL = IRInsertPos->getDataLayout();
3076 APInt Offset(32,
3077 DL.getTypeAllocSize(getLoadStoreType(IRInsertPos)) *
3078 IG->getIndex(IRInsertPos),
3079 /*IsSigned=*/true);
3080 VPValue *OffsetVPV = Plan.getConstantInt(-Offset);
3081 VPBuilder B(InsertPosR);
3082 Addr = B.createNoWrapPtrAdd(InsertPos->getAddr(), OffsetVPV, NW);
3083 }
3084 // If the group is reverse, adjust the index to refer to the last vector
3085 // lane instead of the first. We adjust the index from the first vector
3086 // lane, rather than directly getting the pointer for lane VF - 1, because
3087 // the pointer operand of the interleaved access is supposed to be uniform.
3088 if (IG->isReverse()) {
3089 auto *ReversePtr = new VPVectorEndPointerRecipe(
3090 Addr, &Plan.getVF(), getLoadStoreType(IRInsertPos),
3091 -(int64_t)IG->getFactor(), NW, InsertPosR->getDebugLoc());
3092 ReversePtr->insertBefore(InsertPosR);
3093 Addr = ReversePtr;
3094 }
3095 auto *VPIG = new VPInterleaveRecipe(
3096 IG, Addr, StoredValues, InsertPos->getMask(), NeedsMaskForGaps,
3097 InterleaveMD, InsertPosR->getDebugLoc());
3098 VPIG->insertBefore(InsertPosR);
3099
3100 unsigned J = 0;
3101 for (unsigned i = 0; i < IG->getFactor(); ++i)
3102 if (Instruction *Member = IG->getMember(i)) {
3103 VPWidenMemoryRecipe *MemberR = IRMemberToRecipe.lookup(Member);
3104 if (!Member->getType()->isVoidTy()) {
3105 if (MemberR) {
3106 VPValue *OriginalV = MemberR->getAsRecipe()->getVPSingleValue();
3107 OriginalV->replaceAllUsesWith(VPIG->getVPValue(J));
3108 }
3109 J++;
3110 }
3111 if (MemberR)
3112 MemberR->getAsRecipe()->eraseFromParent();
3113 }
3114 }
3115}
3116
3117/// Expand a VPWidenIntOrFpInduction into executable recipes, for the initial
3118/// value, phi and backedge value. In the following example:
3119///
3120/// vector.ph:
3121/// Successor(s): vector loop
3122///
3123/// <x1> vector loop: {
3124/// vector.body:
3125/// WIDEN-INDUCTION %i = phi %start, %step, %vf
3126/// ...
3127/// EMIT branch-on-count ...
3128/// No successors
3129/// }
3130///
3131/// WIDEN-INDUCTION will get expanded to:
3132///
3133/// vector.ph:
3134/// ...
3135/// vp<%induction.start> = ...
3136/// vp<%induction.increment> = ...
3137///
3138/// Successor(s): vector loop
3139///
3140/// <x1> vector loop: {
3141/// vector.body:
3142/// ir<%i> = WIDEN-PHI vp<%induction.start>, vp<%vec.ind.next>
3143/// ...
3144/// vp<%vec.ind.next> = add ir<%i>, vp<%induction.increment>
3145/// EMIT branch-on-count ...
3146/// No successors
3147/// }
3148static void
3150 VPlan *Plan = WidenIVR->getParent()->getPlan();
3151 VPValue *Start = WidenIVR->getStartValue();
3152 VPValue *Step = WidenIVR->getStepValue();
3153 VPValue *VF = WidenIVR->getVFValue();
3154 DebugLoc DL = WidenIVR->getDebugLoc();
3155
3156 // The value from the original loop to which we are mapping the new induction
3157 // variable.
3158 Type *Ty = WidenIVR->getScalarType();
3159
3160 const InductionDescriptor &ID = WidenIVR->getInductionDescriptor();
3163 VPIRFlags Flags = *WidenIVR;
3164 if (ID.getKind() == InductionDescriptor::IK_IntInduction) {
3165 AddOp = Instruction::Add;
3166 MulOp = Instruction::Mul;
3167 } else {
3168 AddOp = ID.getInductionOpcode();
3169 MulOp = Instruction::FMul;
3170 }
3171
3172 // If the phi is truncated, truncate the start and step values.
3173 VPBuilder Builder(Plan->getVectorPreheader());
3174 Type *StepTy = Step->getScalarType();
3175 if (Ty->getScalarSizeInBits() < StepTy->getScalarSizeInBits()) {
3176 assert(StepTy->isIntegerTy() && "Truncation requires an integer type");
3177 Step = Builder.createScalarCast(Instruction::Trunc, Step, Ty, DL);
3178 Start = Builder.createScalarCast(Instruction::Trunc, Start, Ty, DL);
3179 StepTy = Ty;
3180 }
3181
3182 // Construct the initial value of the vector IV in the vector loop preheader.
3183 Type *IVIntTy =
3185 VPValue *Init = Builder.createNaryOp(VPInstruction::StepVector, {}, IVIntTy);
3186 if (StepTy->isFloatingPointTy())
3187 Init = Builder.createWidenCast(Instruction::UIToFP, Init, StepTy);
3188
3189 VPValue *SplatStart = Builder.createNaryOp(VPInstruction::Broadcast, Start);
3190 VPValue *SplatStep = Builder.createNaryOp(VPInstruction::Broadcast, Step);
3191
3192 Init = Builder.createNaryOp(MulOp, {Init, SplatStep}, Flags);
3193 Init = Builder.createNaryOp(AddOp, {SplatStart, Init}, Flags,
3194 DebugLoc::getUnknown(), "induction");
3195
3196 // Create the widened phi of the vector IV.
3197 auto *WidePHI = VPBuilder(WidenIVR).createWidenPhi(
3198 Init, WidenIVR->getDebugLoc(), "vec.ind");
3199
3200 // Create the backedge value for the vector IV.
3201 VPValue *Inc;
3202 VPValue *Prev;
3203 // If unrolled, use the increment and prev value from the operands.
3204 if (auto *SplatVF = WidenIVR->getSplatVFValue()) {
3205 Inc = SplatVF;
3206 Prev = WidenIVR->getLastUnrolledPartOperand();
3207 } else {
3208 // Move the insertion point after the VF definition when the VF is defined
3209 // inside a loop, such as for EVL tail-folding.
3210 if (VPRecipeBase *R = VF->getDefiningRecipe())
3211 if (R->getParent()->getEnclosingLoopRegion())
3212 Builder.setInsertPoint(R->getParent(), std::next(R->getIterator()));
3213
3214 // Multiply the vectorization factor by the step using integer or
3215 // floating-point arithmetic as appropriate.
3216 if (StepTy->isFloatingPointTy())
3217 VF = Builder.createScalarCast(Instruction::CastOps::UIToFP, VF, StepTy,
3218 DL);
3219 else
3220 VF = Builder.createScalarZExtOrTrunc(VF, StepTy, DL);
3221
3222 Inc = Builder.createNaryOp(MulOp, {Step, VF}, Flags);
3223 Inc = Builder.createNaryOp(VPInstruction::Broadcast, Inc);
3224 Prev = WidePHI;
3225 }
3226
3228 Builder.setInsertPoint(ExitingBB, ExitingBB->getTerminator()->getIterator());
3229 auto *Next = Builder.createNaryOp(AddOp, {Prev, Inc}, Flags,
3230 WidenIVR->getDebugLoc(), "vec.ind.next");
3231
3232 WidePHI->addIncoming(Next);
3233
3234 WidenIVR->replaceAllUsesWith(WidePHI);
3235}
3236
3237/// Expand a VPWidenPointerInductionRecipe into executable recipes, for the
3238/// initial value, phi and backedge value. In the following example:
3239///
3240/// <x1> vector loop: {
3241/// vector.body:
3242/// EMIT ir<%ptr.iv> = WIDEN-POINTER-INDUCTION %start, %step, %vf
3243/// ...
3244/// EMIT branch-on-count ...
3245/// }
3246///
3247/// WIDEN-POINTER-INDUCTION will get expanded to:
3248///
3249/// <x1> vector loop: {
3250/// vector.body:
3251/// EMIT-SCALAR %pointer.phi = phi %start, %ptr.ind
3252/// EMIT %mul = mul %stepvector, %step
3253/// EMIT %vector.gep = wide-ptradd %pointer.phi, %mul
3254/// ...
3255/// EMIT %ptr.ind = ptradd %pointer.phi, %vf
3256/// EMIT branch-on-count ...
3257/// }
3259 VPlan *Plan = R->getParent()->getPlan();
3260 VPValue *Start = R->getStartValue();
3261 VPValue *Step = R->getStepValue();
3262 VPValue *VF = R->getVFValue();
3263
3264 assert(R->getInductionDescriptor().getKind() ==
3266 "Not a pointer induction according to InductionDescriptor!");
3267 assert(R->getScalarType()->isPointerTy() && "Unexpected type.");
3268 assert(!R->onlyScalarsGenerated(Plan->hasScalableVF()) &&
3269 "Recipe should have been replaced");
3270
3271 VPBuilder Builder(R);
3272 DebugLoc DL = R->getDebugLoc();
3273
3274 // Build a scalar pointer phi.
3275 VPPhi *ScalarPtrPhi = Builder.createScalarPhi(Start, DL, "pointer.phi");
3276
3277 // Create actual address geps that use the pointer phi as base and a
3278 // vectorized version of the step value (<step*0, ..., step*N>) as offset.
3279 Builder.setInsertPoint(R->getParent(), R->getParent()->getFirstNonPhi());
3280 Type *StepTy = Step->getScalarType();
3281 VPValue *Offset = Builder.createNaryOp(VPInstruction::StepVector, {}, StepTy);
3282 Offset = Builder.createOverflowingOp(Instruction::Mul, {Offset, Step});
3283 VPValue *PtrAdd =
3284 Builder.createWidePtrAdd(ScalarPtrPhi, Offset, DL, "vector.gep");
3285 R->replaceAllUsesWith(PtrAdd);
3286
3287 // Create the backedge value for the scalar pointer phi.
3289 Builder.setInsertPoint(ExitingBB, ExitingBB->getTerminator()->getIterator());
3290 VF = Builder.createScalarZExtOrTrunc(VF, StepTy, DL);
3291 VPValue *Inc = Builder.createOverflowingOp(Instruction::Mul, {Step, VF});
3292
3293 VPValue *InductionGEP =
3294 Builder.createPtrAdd(ScalarPtrPhi, Inc, DL, "ptr.ind");
3295 ScalarPtrPhi->addIncoming(InductionGEP);
3296}
3297
3298/// Expand a VPDerivedIVRecipe into executable recipes.
3300 VPBuilder Builder(R);
3301 VPValue *Start = R->getStartValue();
3302 VPValue *Step = R->getStepValue();
3303 VPValue *Index = R->getIndex();
3304 Type *StepTy = Step->getScalarType();
3305 Index = StepTy->isIntegerTy()
3306 ? Builder.createScalarSExtOrTrunc(
3307 Index, StepTy, DebugLoc::getCompilerGenerated())
3308 : Builder.createScalarCast(Instruction::SIToFP, Index, StepTy,
3310 switch (R->getInductionKind()) {
3312 assert(Index->getScalarType() == Start->getScalarType() &&
3313 "Index type does not match StartValue type");
3314 return R->replaceAllUsesWith(Builder.createAdd(
3315 Start, Builder.createOverflowingOp(Instruction::Mul, {Index, Step})));
3316 }
3318 return R->replaceAllUsesWith(Builder.createPtrAdd(
3319 Start, Builder.createOverflowingOp(Instruction::Mul, {Index, Step})));
3321 assert(StepTy->isFloatingPointTy() && "Expected FP Step value");
3322 const FPMathOperator *FPBinOp = R->getFPBinOp();
3323 assert(FPBinOp &&
3324 (FPBinOp->getOpcode() == Instruction::FAdd ||
3325 FPBinOp->getOpcode() == Instruction::FSub) &&
3326 "Original BinOp should be defined for FP induction");
3327 FastMathFlags FMF = FPBinOp->getFastMathFlags();
3328 VPValue *FMul = Builder.createNaryOp(Instruction::FMul, {Step, Index}, FMF);
3329 return R->replaceAllUsesWith(
3330 Builder.createNaryOp(FPBinOp->getOpcode(), {Start, FMul}, FMF));
3331 }
3333 return;
3334 }
3335 llvm_unreachable("Unhandled induction kind");
3336}
3337
3339 // Replace loop regions with explicity CFG.
3340 SmallVector<VPRegionBlock *> LoopRegions;
3342 vp_depth_first_deep(Plan.getEntry()))) {
3343 if (!R->isReplicator())
3344 LoopRegions.push_back(R);
3345 }
3346 for (VPRegionBlock *R : LoopRegions)
3347 R->dissolveToCFGLoop();
3348}
3349
3352 // The transform runs after dissolving loop regions, so all VPBasicBlocks
3353 // terminated with BranchOnTwoConds are reached via a shallow traversal.
3356 if (!VPBB->empty() && match(&VPBB->back(), m_BranchOnTwoConds()))
3357 WorkList.push_back(cast<VPInstruction>(&VPBB->back()));
3358 }
3359
3360 // Expand BranchOnTwoConds instructions into explicit CFG with two new
3361 // single-condition branches:
3362 // 1. A branch that replaces BranchOnTwoConds, jumps to the first successor if
3363 // the first condition is true, and otherwise jumps to a new interim block.
3364 // 2. A branch that ends the interim block, jumps to the second successor if
3365 // the second condition is true, and otherwise jumps to the third
3366 // successor.
3367 for (VPInstruction *Br : WorkList) {
3368 assert(Br->getNumOperands() == 2 &&
3369 "BranchOnTwoConds must have exactly 2 conditions");
3370 DebugLoc DL = Br->getDebugLoc();
3371 VPBasicBlock *BrOnTwoCondsBB = Br->getParent();
3372 const auto Successors = to_vector(BrOnTwoCondsBB->getSuccessors());
3373 assert(Successors.size() == 3 &&
3374 "BranchOnTwoConds must have exactly 3 successors");
3375
3376 for (VPBlockBase *Succ : Successors)
3377 VPBlockUtils::disconnectBlocks(BrOnTwoCondsBB, Succ);
3378
3379 VPValue *Cond0 = Br->getOperand(0);
3380 VPValue *Cond1 = Br->getOperand(1);
3381 VPBlockBase *Succ0 = Successors[0];
3382 VPBlockBase *Succ1 = Successors[1];
3383 VPBlockBase *Succ2 = Successors[2];
3384
3385 // If the successor block for both conditions is the same, then combine the
3386 // two conditions and plant a single conditional branch.
3387 if (Succ0 == Succ1) {
3388 VPBuilder Builder(Br);
3389 VPValue *Combined = Builder.createOr(Cond0, Cond1, DL);
3390 Builder.createNaryOp(VPInstruction::BranchOnCond, {Combined}, DL);
3391 VPBlockUtils::connectBlocks(BrOnTwoCondsBB, Succ0);
3392 VPBlockUtils::connectBlocks(BrOnTwoCondsBB, Succ2);
3393 Br->eraseFromParent();
3394 continue;
3395 }
3396
3397 assert(!Succ0->getParent() && !Succ1->getParent() && !Succ2->getParent() &&
3398 !BrOnTwoCondsBB->getParent() && "regions must already be dissolved");
3399
3400 VPBasicBlock *InterimBB =
3401 Plan.createVPBasicBlock(BrOnTwoCondsBB->getName() + ".interim");
3402
3403 VPBuilder(BrOnTwoCondsBB)
3405 VPBlockUtils::connectBlocks(BrOnTwoCondsBB, Succ0);
3406 VPBlockUtils::connectBlocks(BrOnTwoCondsBB, InterimBB);
3407
3409 VPBlockUtils::connectBlocks(InterimBB, Succ1);
3410 VPBlockUtils::connectBlocks(InterimBB, Succ2);
3411 Br->eraseFromParent();
3412 }
3413}
3414
3417 vp_depth_first_deep(Plan.getEntry()))) {
3418 for (VPRecipeBase &R : make_early_inc_range(*VPBB)) {
3419 VPBuilder Builder(&R);
3420 if (auto *WidenIVR = dyn_cast<VPWidenIntOrFpInductionRecipe>(&R)) {
3422 WidenIVR->eraseFromParent();
3423 continue;
3424 }
3425
3426 if (auto *WidenIVR = dyn_cast<VPWidenPointerInductionRecipe>(&R)) {
3427 // If the recipe only generates scalars, scalarize it instead of
3428 // expanding it.
3429 if (WidenIVR->onlyScalarsGenerated(Plan.hasScalableVF())) {
3430 VPValue *PtrAdd =
3431 scalarizeVPWidenPointerInduction(WidenIVR, Plan, Builder);
3432 WidenIVR->replaceAllUsesWith(PtrAdd);
3433 WidenIVR->eraseFromParent();
3434 continue;
3435 }
3437 WidenIVR->eraseFromParent();
3438 continue;
3439 }
3440
3441 if (auto *DerivedIVR = dyn_cast<VPDerivedIVRecipe>(&R)) {
3442 expandVPDerivedIV(DerivedIVR);
3443 DerivedIVR->eraseFromParent();
3444 continue;
3445 }
3446
3447 if (auto *WideCanIV = dyn_cast<VPWidenCanonicalIVRecipe>(&R)) {
3448 VPValue *CanIV = WideCanIV->getCanonicalIV();
3449 Type *CanIVTy = CanIV->getScalarType();
3450 VPValue *Step = WideCanIV->getStepValue();
3451 if (!Step) {
3452 assert(Plan.getConcreteUF() == 1 &&
3453 "Expected unroller to have materialized step for UF != 1");
3454 Step = Plan.getZero(CanIVTy);
3455 }
3456 CanIV = Builder.createNaryOp(VPInstruction::Broadcast, CanIV);
3457 Step = Builder.createNaryOp(VPInstruction::Broadcast, Step);
3458 Step = Builder.createAdd(
3459 Step, Builder.createNaryOp(VPInstruction::StepVector, {}, CanIVTy));
3460 VPValue *CanVecIV =
3461 Builder.createAdd(CanIV, Step, WideCanIV->getDebugLoc(), "vec.iv",
3462 WideCanIV->getNoWrapFlags());
3463 WideCanIV->replaceAllUsesWith(CanVecIV);
3464 WideCanIV->eraseFromParent();
3465 continue;
3466 }
3467
3468 // Expand VPBlendRecipe into VPInstruction::Select.
3469 if (auto *Blend = dyn_cast<VPBlendRecipe>(&R)) {
3470 VPValue *Select = Blend->getIncomingValue(0);
3471 for (unsigned I = 1; I != Blend->getNumIncomingValues(); ++I)
3472 Select = Builder.createSelect(Blend->getMask(I),
3473 Blend->getIncomingValue(I), Select,
3474 R.getDebugLoc(), "predphi", *Blend);
3475 Blend->replaceAllUsesWith(Select);
3476 Blend->eraseFromParent();
3477 continue;
3478 }
3479
3480 if (auto *VEPR = dyn_cast<VPVectorEndPointerRecipe>(&R)) {
3481 if (!VEPR->getOffset()) {
3482 assert(Plan.getConcreteUF() == 1 &&
3483 "Expected unroller to have materialized offset for UF != 1");
3484 VEPR->materializeOffset();
3485 }
3486 continue;
3487 }
3488
3489 if (auto *Expr = dyn_cast<VPExpressionRecipe>(&R)) {
3490 Expr->decompose();
3491 Expr->eraseFromParent();
3492 continue;
3493 }
3494
3495 // Expand LastActiveLane into Not + FirstActiveLane + Sub.
3496 auto *LastActiveL = dyn_cast<VPInstruction>(&R);
3497 if (LastActiveL &&
3498 LastActiveL->getOpcode() == VPInstruction::LastActiveLane) {
3499 // Create Not(Mask) for all operands.
3501 for (VPValue *Op : LastActiveL->operands()) {
3502 VPValue *NotMask = Builder.createNot(Op, LastActiveL->getDebugLoc());
3503 NotMasks.push_back(NotMask);
3504 }
3505
3506 // Create FirstActiveLane on the inverted masks.
3507 VPValue *FirstInactiveLane = Builder.createFirstActiveLane(
3508 NotMasks, LastActiveL->getDebugLoc(), "first.inactive.lane");
3509
3510 // Subtract 1 to get the last active lane.
3511 VPValue *One =
3512 Plan.getConstantInt(FirstInactiveLane->getScalarType(), 1);
3513 VPValue *LastLane =
3514 Builder.createSub(FirstInactiveLane, One,
3515 LastActiveL->getDebugLoc(), "last.active.lane");
3516
3517 LastActiveL->replaceAllUsesWith(LastLane);
3518 LastActiveL->eraseFromParent();
3519 continue;
3520 }
3521
3522 // Lower MaskedCond with block mask to LogicalAnd.
3524 auto *VPI = cast<VPInstruction>(&R);
3525 assert(VPI->isMasked() &&
3526 "Unmasked MaskedCond should be simplified earlier");
3527 VPI->replaceAllUsesWith(Builder.createNaryOp(
3528 VPInstruction::LogicalAnd, {VPI->getMask(), VPI->getOperand(0)}));
3529 VPI->eraseFromParent();
3530 continue;
3531 }
3532
3533 // Lower CanonicalIVIncrementForPart to plain Add.
3534 if (match(
3535 &R,
3537 auto *VPI = cast<VPInstruction>(&R);
3538 VPValue *Add = Builder.createOverflowingOp(
3539 Instruction::Add, VPI->operands(), VPI->getNoWrapFlags(),
3540 VPI->getDebugLoc());
3541 VPI->replaceAllUsesWith(Add);
3542 VPI->eraseFromParent();
3543 continue;
3544 }
3545
3546 // Lower BranchOnCount to ICmp + BranchOnCond.
3547 VPValue *IV, *TC;
3548 if (match(&R, m_BranchOnCount(m_VPValue(IV), m_VPValue(TC)))) {
3549 auto *BranchOnCountInst = cast<VPInstruction>(&R);
3550 DebugLoc DL = BranchOnCountInst->getDebugLoc();
3551 VPValue *Cond = Builder.createICmp(CmpInst::ICMP_EQ, IV, TC, DL);
3552 Builder.createNaryOp(VPInstruction::BranchOnCond, Cond, DL);
3553 BranchOnCountInst->eraseFromParent();
3554 continue;
3555 }
3556
3557 VPValue *VectorStep;
3558 VPValue *ScalarStep;
3560 m_VPValue(VectorStep), m_VPValue(ScalarStep))))
3561 continue;
3562
3563 // Expand WideIVStep.
3564 auto *VPI = cast<VPInstruction>(&R);
3565 Type *IVTy = VPI->getScalarType();
3566 if (VectorStep->getScalarType() != IVTy) {
3568 ? Instruction::UIToFP
3569 : Instruction::Trunc;
3570 VectorStep = Builder.createWidenCast(CastOp, VectorStep, IVTy);
3571 }
3572
3573 assert(!match(ScalarStep, m_One()) && "Expected non-unit scalar-step");
3574 if (ScalarStep->getScalarType() != IVTy) {
3575 ScalarStep =
3576 Builder.createWidenCast(Instruction::Trunc, ScalarStep, IVTy);
3577 }
3578
3579 VPIRFlags Flags;
3580 unsigned MulOpc;
3581 if (IVTy->isFloatingPointTy()) {
3582 MulOpc = Instruction::FMul;
3583 Flags = VPI->getFastMathFlagsOrNone();
3584 } else {
3585 MulOpc = Instruction::Mul;
3586 Flags = VPIRFlags::getDefaultFlags(MulOpc);
3587 }
3588
3589 VPInstruction *Mul = Builder.createNaryOp(
3590 MulOpc, {VectorStep, ScalarStep}, Flags, R.getDebugLoc());
3591 VectorStep = Mul;
3592 VPI->replaceAllUsesWith(VectorStep);
3593 VPI->eraseFromParent();
3594 }
3595 }
3596}
3597
3598/// Returns the VPValue representing the uncountable exit comparison used by
3599/// AnyOf if the recipes it depends on can be traced back to live-ins and
3600/// the addresses (in GEP/PtrAdd form) of any (non-masked) load used in
3601/// generating the values for the comparison. The recipes are stored in
3602/// \p Recipes.
3603static std::optional<VPValue *>
3605 VPBasicBlock *LatchVPBB) {
3606 // Given a plain CFG VPlan loop with countable latch exiting block
3607 // \p LatchVPBB, we're looking to match the recipes contributing to the
3608 // uncountable exit condition comparison (here, vp<%4>) back to either
3609 // live-ins or the address nodes for the load used as part of the uncountable
3610 // exit comparison so that we can either move them within the loop, or copy
3611 // them to the preheader depending on the chosen method for dealing with
3612 // stores in uncountable exit loops.
3613 //
3614 // Currently, the address of the load is restricted to a GEP with 2 operands
3615 // and a live-in base address. This constraint may be relaxed later.
3616 //
3617 // VPlan ' for UF>=1' {
3618 // Live-in vp<%0> = VF * UF
3619 // Live-in vp<%1> = vector-trip-count
3620 // Live-in ir<20> = original trip-count
3621 //
3622 // ir-bb<entry>:
3623 // Successor(s): scalar.ph, vector.ph
3624 //
3625 // vector.ph:
3626 // Successor(s): for.body
3627 //
3628 // for.body:
3629 // EMIT vp<%2> = phi ir<0>, vp<%index.next>
3630 // EMIT-SCALAR ir<%iv> = phi [ ir<0>, vector.ph ], [ ir<%iv.next>, for.inc ]
3631 // EMIT ir<%uncountable.addr> = getelementptr inbounds nuw ir<%pred>,ir<%iv>
3632 // EMIT ir<%uncountable.val> = load ir<%uncountable.addr>
3633 // EMIT ir<%uncountable.cond> = icmp sgt ir<%uncountable.val>, ir<500>
3634 // EMIT vp<%3> = masked-cond ir<%uncountable.cond>
3635 // Successor(s): for.inc
3636 //
3637 // for.inc:
3638 // EMIT ir<%iv.next> = add nuw nsw ir<%iv>, ir<1>
3639 // EMIT ir<%countable.cond> = icmp eq ir<%iv.next>, ir<20>
3640 // EMIT vp<%index.next> = add nuw vp<%2>, vp<%0>
3641 // EMIT vp<%4> = any-of ir<%3>
3642 // EMIT vp<%5> = icmp eq vp<%index.next>, vp<%1>
3643 // EMIT branch-on-two-conds vp<%4>, vp<%5>
3644 // Successor(s): middle.block, middle.block, for.body
3645 //
3646 // middle.block:
3647 // Successor(s): ir-bb<exit>, scalar.ph
3648 //
3649 // ir-bb<exit>:
3650 // No successors
3651 //
3652 // scalar.ph:
3653 // }
3654
3655 // Find the uncountable loop exit condition.
3656 VPValue *UncountableCondition = nullptr;
3657 if (!match(LatchVPBB->getTerminator(),
3658 m_BranchOnTwoConds(m_AnyOf(m_VPValue(UncountableCondition)),
3659 m_VPValue())))
3660 return std::nullopt;
3661
3663 Worklist.push_back(UncountableCondition);
3664 while (!Worklist.empty()) {
3665 VPValue *V = Worklist.pop_back_val();
3666
3667 // Any value defined outside the loop does not need to be copied.
3668 if (V->isDefinedOutsideLoopRegions())
3669 continue;
3670
3671 // FIXME: Remove the single user restriction; it's here because we're
3672 // starting with the simplest set of loops we can, and multiple
3673 // users means needing to add PHI nodes in the transform.
3674 if (V->getNumUsers() > 1)
3675 return std::nullopt;
3676
3677 VPValue *Op1, *Op2;
3678 // Walk back through recipes until we find at least one load from memory.
3679 if (match(V, m_ICmp(m_VPValue(Op1), m_VPValue(Op2)))) {
3680 Worklist.push_back(Op1);
3681 Worklist.push_back(Op2);
3682 Recipes.push_back(cast<VPInstruction>(V->getDefiningRecipe()));
3683 } else if (match(V, m_VPInstruction<Instruction::Load>(m_VPValue(Op1)))) {
3684 VPRecipeBase *GepR = Op1->getDefiningRecipe();
3685 // Only matching base + single offset term for now.
3686 if (GepR->getNumOperands() != 2)
3687 return std::nullopt;
3688 // Matching a GEP with a loop-invariant base ptr.
3690 m_LiveIn(), m_VPValue())))
3691 return std::nullopt;
3692 Recipes.push_back(cast<VPInstruction>(V->getDefiningRecipe()));
3693 Recipes.push_back(cast<VPInstruction>(GepR));
3695 m_VPValue(Op1)))) {
3696 Worklist.push_back(Op1);
3697 Recipes.push_back(cast<VPInstruction>(V->getDefiningRecipe()));
3698 } else
3699 return std::nullopt;
3700 }
3701
3702 // If we couldn't match anything, don't return the condition. It may be
3703 // defined outside the loop.
3704 if (Recipes.empty() || none_of(Recipes, [](VPInstruction *I) {
3706 }))
3707 return std::nullopt;
3708
3709 return UncountableCondition;
3710}
3711
3717
3718/// Update \p Plan to mask memory operations in the loop based on whether the
3719/// early exit is taken or not.
3720///
3721/// We're currently expecting to find a loop with properties similar to the
3722/// following:
3723///
3724/// for.body:
3725/// ir<%indvars.iv> = WIDEN-INDUCTION nuw nsw ir<0>, ir<1>, vp<%0>
3726/// EMIT ir<%arrayidx> = getelementptr inbounds nuw ir<@c>, ir<%indvars.iv>
3727/// EMIT-SCALAR ir<%0> = load ir<%arrayidx>
3728/// EMIT ir<%cmp1> = icmp sgt ir<%0>, ir<5>
3729/// EMIT vp<%1> = masked-cond ir<%cmp1>
3730/// Successor(s): if.end
3731///
3732/// if.end:
3733/// EMIT ir<%arrayidx3> = getelementptr inbounds nuw ir<@src>, ir<%indvars.iv>
3734/// EMIT-SCALAR ir<%2> = load ir<%arrayidx3>
3735/// EMIT ir<%add> = add nsw ir<%2>, ir<42>
3736/// EMIT ir<%arrayidx5> = getelementptr inbounds nuw ir<@dst>, ir<%indvars.iv>
3737/// EMIT store ir<%add>, ir<%arrayidx5>
3738/// EMIT ir<%indvars.iv.next> = add nuw nsw ir<%indvars.iv>, ir<1>
3739/// EMIT vp<%3> = any-of ir<%1>
3740/// EMIT ir<%exitcond.not> = icmp eq ir<%indvars.iv.next>, ir<10000>
3741/// EMIT branch-on-two-conds vp<%3>, ir<%exitcond.not>
3742/// Successor(s): middle.block, middle.block, for.body
3743///
3744/// We currently expect LoopVectorizationLegality to ensure that:
3745/// * There must also be a counted exit. We will need to support speculative
3746/// or first-faulting loads before we can remove this restriction.
3747/// * Any stores within the loop must not alias with the load used for the
3748/// uncountable exit. We can relax this a bit with runtime aliasing checks.
3749/// * Other memory operations in the loop can take place before or after the
3750/// uncountable exit, but must also be unconditional. We need to support
3751/// combining the conditions in VPlanPredicator.
3752/// * The loop must have a single unconditional load contributing to the
3753/// uncountable exit comparison, and the other term must be loop-invariant.
3754/// Improving upon this requires work in getRecipesForUncountableExit to
3755/// handle more complex recipe graphs.
3758 VPBasicBlock *HeaderVPBB, VPBasicBlock *LatchVPBB, VPBasicBlock *MiddleVPBB,
3759 Loop *TheLoop, PredicatedScalarEvolution &PSE, DominatorTree &DT,
3760 AssumptionCache *AC) {
3761
3762 // Disconnect early exiting blocks from successors, remove branches. We
3763 // currently don't support multiple uses for recipes involved in creating
3764 // the uncountable exit condition.
3765 for (auto &Exit : Exits) {
3766 if (Exit.EarlyExitingVPBB == LatchVPBB)
3767 continue;
3768
3769 for (VPRecipeBase &R : Exit.EarlyExitVPBB->phis())
3770 cast<VPIRPhi>(&R)->removeIncomingValueFor(Exit.EarlyExitingVPBB);
3771 Exit.EarlyExitingVPBB->getTerminator()->eraseFromParent();
3772 VPBlockUtils::disconnectBlocks(Exit.EarlyExitingVPBB, Exit.EarlyExitVPBB);
3773 }
3774
3775 VPDominatorTree VPDT(Plan);
3776
3777 // We can abandon a VPlan entirely if we return false here, so we shouldn't
3778 // crash if some earlier assumptions on scalar IR don't hold for the vplan
3779 // version of the loop.
3780 SmallVector<VPInstruction *, 8> ConditionRecipes;
3781
3782 std::optional<VPValue *> Cond =
3783 getRecipesForUncountableExit(ConditionRecipes, LatchVPBB);
3784 if (!Cond)
3785 return false;
3786
3787 // Find load contributing to condition.
3788 // At the moment LoopVectorizationLegality only supports a single
3789 // early-exit expression with a compare and a single load that must
3790 // be unconditional.
3791 // TODO: Support more than one load.
3792 auto *Load =
3793 find_singleton<VPInstruction>(ConditionRecipes, [](auto *I, bool _) {
3795 ? I
3796 : nullptr;
3797 });
3798 assert(Load && "Couldn't find exactly one load");
3799 // TODO: Support conditional loads for uncountable exits.
3800 assert(VPDT.dominates(Load->getParent(), LatchVPBB) &&
3801 "Uncountable exit condition load is conditional.");
3802 VPInstruction *Ptr = cast<VPInstruction>(Load->getOperand(0));
3803
3804 // Ensure that we are guaranteed to be able to dereference the memory used
3805 // for determining the uncountable exit for the maximum possible number of
3806 // scalar iterations of the loop.
3807 //
3808 // TODO: Support first-faulting loads in cases where we don't know whether
3809 // all possible addresses are dereferenceable.
3810 {
3812 const SCEV *PtrSCEV = vputils::getSCEVExprForVPValue(Ptr, PSE, TheLoop);
3813 const DataLayout &DL = Plan.getDataLayout();
3814 APInt EltSize(DL.getIndexTypeSizeInBits(Ptr->getScalarType()),
3815 DL.getTypeStoreSize(Load->getScalarType()).getFixedValue());
3817 PtrSCEV, cast<LoadInst>(Load->getUnderlyingInstr())->getAlign(),
3818 PSE.getSE()->getConstant(EltSize), TheLoop, *PSE.getSE(), DT, AC,
3819 &Predicates))
3820 return false;
3821 }
3822
3823 // Check for a single GEP for the condition load to see if we can link it to
3824 // a widen IV recipe with a step of 1; we're only interested in contiguous
3825 // accesses for the condition load right now.
3826 auto *IV = cast<VPWidenInductionRecipe>(&HeaderVPBB->front());
3827 if (!match(IV->getStartValue(), m_SpecificInt(0)) ||
3828 !match(IV->getStepValue(), m_SpecificInt(1)))
3829 return false;
3831 m_Specific(IV))))
3832 return false;
3833
3834 // We want to guarantee that the uncountable exit condition (and the mask
3835 // we will generate from it) are available for all operations in the loop
3836 // that need to be masked. If the condition recipes are not already the first
3837 // recipes in the header after the last phi, move them there.
3838 auto InsertIt = HeaderVPBB->getFirstNonPhi();
3839 while (InsertIt != HeaderVPBB->end() &&
3840 is_contained(ConditionRecipes, &*InsertIt)) {
3841 erase(ConditionRecipes, &*InsertIt);
3842 InsertIt++;
3843 }
3844 for (auto *Recipe : reverse(ConditionRecipes))
3845 Recipe->moveBefore(*HeaderVPBB, InsertIt);
3846
3847 // Create a mask to represent all lanes that fully execute in the vector loop,
3848 // stopping short of any early exit.
3849 VPBuilder MaskBuilder(HeaderVPBB, InsertIt);
3850 VPValue *FirstActive = MaskBuilder.createFirstActiveLane(*Cond);
3851 Type *IVScalarTy = IV->getScalarType();
3852 VPValue *ALMMultiplier = Plan.getConstantInt(IVScalarTy, 1);
3853 VPValue *Zero = Plan.getZero(IVScalarTy);
3854 FirstActive =
3855 MaskBuilder.createScalarZExtOrTrunc(FirstActive, IVScalarTy, DebugLoc());
3857 {Zero, FirstActive, ALMMultiplier},
3858 DebugLoc(), "uncountable.exit.mask");
3859
3860 // Convert all other memory operations to use the mask.
3861 for (VPBasicBlock *VPBB : vp_rpo_plain_cfg_loop_body(HeaderVPBB))
3862 for (VPRecipeBase &R : *VPBB)
3863 if (R.mayReadOrWriteMemory() && &R != Load) {
3864 // TODO: Handle conditional memory operations in the loop.
3865 if (!VPDT.dominates(R.getParent(), LatchVPBB))
3866 return false;
3867 cast<VPInstruction>(&R)->addMask(Mask);
3868 }
3869
3870 // Update middle block branch to compare (IV + however many lanes were active)
3871 // against the full trip count, since we may be exiting the vector loop early.
3872 // If we didn't take an early exit, we should get the equivalent of VF from
3873 // the FirstActiveLane.
3874 assert(match(MiddleVPBB->getTerminator(), m_BranchOnCond()) &&
3875 "Expected BranchOnCond terminator for MiddleVPBB");
3876 VPBuilder MiddleBuilder(MiddleVPBB->getTerminator());
3877 VPValue *ScalarIV = MiddleBuilder.createNaryOp(VPInstruction::ExtractLane,
3878 {Zero, IV}, DebugLoc());
3879 VPValue *ExitIV = MiddleBuilder.createAdd(ScalarIV, FirstActive);
3880 VPValue *FullTC =
3881 MiddleBuilder.createICmp(CmpInst::ICMP_EQ, ExitIV, Plan.getTripCount());
3882 MiddleVPBB->getTerminator()->setOperand(0, FullTC);
3883
3884 // Update resume phi in scalar.ph.
3885 VPBasicBlock *ScalarPH = Plan.getScalarPreheader();
3886 auto Phis = ScalarPH->phis();
3887 // TODO: Handle more than one Phi; re-derive from IV.
3888 // TODO: Handle reductions.
3889 if (range_size(Phis) != 1)
3890 return false;
3891 VPPhi *ContinueIV = cast<VPPhi>(Phis.begin());
3892 // Make sure we're referring to the same IV.
3893 assert(
3894 match(ContinueIV->getOperand(0),
3896 "Continuing from different IV");
3897 ContinueIV->setOperand(0, ExitIV);
3898 return true;
3899}
3900
3902 VPlan &Plan, VPBasicBlock *HeaderVPBB, VPBasicBlock *LatchVPBB,
3903 VPBasicBlock *MiddleVPBB, Loop *TheLoop, PredicatedScalarEvolution &PSE,
3905#ifndef NDEBUG
3906 VPDominatorTree VPDT(Plan);
3907#endif
3908 VPBuilder LatchBuilder(LatchVPBB->getTerminator());
3910 for (VPIRBasicBlock *ExitBlock : Plan.getExitBlocks()) {
3911 for (VPBlockBase *Pred : to_vector(ExitBlock->getPredecessors())) {
3912 if (Pred == MiddleVPBB)
3913 continue;
3914 // Collect condition for this early exit.
3915 auto *EarlyExitingVPBB = cast<VPBasicBlock>(Pred);
3916 VPBlockBase *TrueSucc = EarlyExitingVPBB->getSuccessors()[0];
3917 VPValue *CondOfEarlyExitingVPBB;
3918 [[maybe_unused]] bool Matched =
3919 match(EarlyExitingVPBB->getTerminator(),
3920 m_BranchOnCond(m_VPValue(CondOfEarlyExitingVPBB)));
3921 assert(Matched && "Terminator must be BranchOnCond");
3922
3923 // Insert the MaskedCond in the EarlyExitingVPBB so the predicator adds
3924 // the correct block mask.
3925 VPBuilder EarlyExitingBuilder(EarlyExitingVPBB->getTerminator());
3926 auto *CondToEarlyExit = EarlyExitingBuilder.createNaryOp(
3928 TrueSucc == ExitBlock
3929 ? CondOfEarlyExitingVPBB
3930 : EarlyExitingBuilder.createNot(CondOfEarlyExitingVPBB));
3931 assert((isa<VPIRValue>(CondOfEarlyExitingVPBB) ||
3932 !VPDT.properlyDominates(EarlyExitingVPBB, LatchVPBB) ||
3933 VPDT.properlyDominates(
3934 CondOfEarlyExitingVPBB->getDefiningRecipe()->getParent(),
3935 LatchVPBB)) &&
3936 "exit condition must dominate the latch");
3937 Exits.push_back({
3938 EarlyExitingVPBB,
3939 ExitBlock,
3940 CondToEarlyExit,
3941 });
3942 }
3943 }
3944
3945 assert(!Exits.empty() && "must have at least one early exit");
3946 // Sort exits by RPO order to get correct program order. RPO gives a
3947 // topological ordering of the CFG, ensuring upstream exits are checked
3948 // before downstream exits in the dispatch chain.
3950 HeaderVPBB);
3952 for (const auto &[Num, VPB] : enumerate(RPOT))
3953 RPOIdx[VPB] = Num;
3954 llvm::sort(Exits, [&RPOIdx](const EarlyExitInfo &A, const EarlyExitInfo &B) {
3955 return RPOIdx[A.EarlyExitingVPBB] < RPOIdx[B.EarlyExitingVPBB];
3956 });
3957#ifndef NDEBUG
3958 // After RPO sorting, verify that for any pair where one exit dominates
3959 // another, the dominating exit comes first. This is guaranteed by RPO
3960 // (topological order) and is required for the dispatch chain correctness.
3961 for (unsigned I = 0; I + 1 < Exits.size(); ++I)
3962 for (unsigned J = I + 1; J < Exits.size(); ++J)
3963 assert(!VPDT.properlyDominates(Exits[J].EarlyExitingVPBB,
3964 Exits[I].EarlyExitingVPBB) &&
3965 "RPO sort must place dominating exits before dominated ones");
3966#endif
3967
3968 // Build the AnyOf condition for the latch terminator using logical OR
3969 // to avoid poison propagation from later exit conditions when an earlier
3970 // exit is taken.
3971 VPValue *Combined = Exits[0].CondToExit;
3972 for (const EarlyExitInfo &Info : drop_begin(Exits))
3973 Combined = LatchBuilder.createLogicalOr(Combined, Info.CondToExit);
3974
3975 VPValue *IsAnyExitTaken =
3976 LatchBuilder.createNaryOp(VPInstruction::AnyOf, {Combined});
3977
3978 // Create a comparison for the latch exit condition and replace the
3979 // BranchOnCond with a BranchOnTwoConds. The original BranchOnCond's condition
3980 // is used as the latch-exit condition; canonical IV recipes have not been
3981 // introduced yet, so there is no BranchOnCount to derive the condition from.
3982 auto *LatchExitingBranch = cast<VPInstruction>(LatchVPBB->getTerminator());
3983 assert(LatchExitingBranch->getOpcode() == VPInstruction::BranchOnCond &&
3984 "Unexpected terminator");
3985 VPValue *IsLatchExitTaken = LatchExitingBranch->getOperand(0);
3986 DebugLoc LatchDL = LatchExitingBranch->getDebugLoc();
3987 LatchExitingBranch->eraseFromParent();
3988 LatchBuilder.setInsertPoint(LatchVPBB);
3990 {IsAnyExitTaken, IsLatchExitTaken}, LatchDL);
3991 LatchVPBB->clearSuccessors();
3992
3994 // If handling the exiting lane in the scalar loop, combine the exit
3995 // conditions into a single BranchOnCond.
3996 LatchVPBB->setSuccessors({MiddleVPBB, MiddleVPBB, HeaderVPBB});
3997 MiddleVPBB->clearPredecessors();
3998 MiddleVPBB->setPredecessors({LatchVPBB, LatchVPBB});
4000 Plan, Exits, HeaderVPBB, LatchVPBB, MiddleVPBB, TheLoop, PSE, DT, AC);
4001 }
4002
4003 // Create the vector.early.exit blocks.
4004 SmallVector<VPBasicBlock *> VectorEarlyExitVPBBs(Exits.size());
4005 for (unsigned Idx = 0; Idx != Exits.size(); ++Idx) {
4006 Twine BlockSuffix = Exits.size() == 1 ? "" : Twine(".") + Twine(Idx);
4007 VPBasicBlock *VectorEarlyExitVPBB =
4008 Plan.createVPBasicBlock("vector.early.exit" + BlockSuffix);
4009 VectorEarlyExitVPBBs[Idx] = VectorEarlyExitVPBB;
4010 }
4011
4012 // Create the dispatch block (or reuse the single exit block if only one
4013 // exit). The dispatch block computes the first active lane of the combined
4014 // condition and, for multiple exits, chains through conditions to determine
4015 // which exit to take.
4016 VPBasicBlock *DispatchVPBB =
4017 Exits.size() == 1 ? VectorEarlyExitVPBBs[0]
4018 : Plan.createVPBasicBlock("vector.early.exit.check");
4019 DispatchVPBB->setPredecessors({LatchVPBB});
4020 LatchVPBB->setSuccessors({DispatchVPBB, MiddleVPBB, HeaderVPBB});
4021 VPBuilder DispatchBuilder(DispatchVPBB, DispatchVPBB->begin());
4022 VPValue *FirstActiveLane = DispatchBuilder.createFirstActiveLane(
4023 {Combined}, DebugLoc::getUnknown(), "first.active.lane");
4024
4025 // For each early exit, disconnect the original exiting block
4026 // (early.exiting.I) from the exit block (ir-bb<exit.I>) and route through a
4027 // new vector.early.exit block. Update ir-bb<exit.I>'s phis to extract their
4028 // values at the first active lane:
4029 //
4030 // Input:
4031 // early.exiting.I:
4032 // ...
4033 // EMIT branch-on-cond vp<%cond.I>
4034 // Successor(s): in.loop.succ, ir-bb<exit.I>
4035 //
4036 // ir-bb<exit.I>:
4037 // IR %phi = phi [ vp<%incoming.I>, early.exiting.I ], ...
4038 //
4039 // Output:
4040 // early.exiting.I:
4041 // ...
4042 // Successor(s): in.loop.succ
4043 //
4044 // vector.early.exit.I:
4045 // EMIT vp<%exit.val> = extract-lane vp<%first.lane>, vp<%incoming.I>
4046 // Successor(s): ir-bb<exit.I>
4047 //
4048 // ir-bb<exit.I>:
4049 // IR %phi = phi ... (extra operand: vp<%exit.val> from
4050 // vector.early.exit.I)
4051 //
4052 for (auto [Exit, VectorEarlyExitVPBB] :
4053 zip_equal(Exits, VectorEarlyExitVPBBs)) {
4054 auto &[EarlyExitingVPBB, EarlyExitVPBB, _] = Exit;
4055 // Adjust the phi nodes in EarlyExitVPBB.
4056 // 1. remove incoming values from EarlyExitingVPBB,
4057 // 2. extract the incoming value at FirstActiveLane
4058 // 3. add back the extracts as last operands for the phis
4059 // Then adjust the CFG, removing the edge between EarlyExitingVPBB and
4060 // EarlyExitVPBB and adding a new edge between VectorEarlyExitVPBB and
4061 // EarlyExitVPBB. The extracts at FirstActiveLane are now the incoming
4062 // values from VectorEarlyExitVPBB.
4063 for (VPRecipeBase &R : EarlyExitVPBB->phis()) {
4064 auto *ExitIRI = cast<VPIRPhi>(&R);
4065 VPValue *IncomingVal =
4066 ExitIRI->getIncomingValueForBlock(EarlyExitingVPBB);
4067 VPValue *NewIncoming = IncomingVal;
4068 if (!isa<VPIRValue>(IncomingVal)) {
4069 VPBuilder EarlyExitBuilder(VectorEarlyExitVPBB);
4070 NewIncoming = EarlyExitBuilder.createNaryOp(
4071 VPInstruction::ExtractLane, {FirstActiveLane, IncomingVal},
4072 DebugLoc::getUnknown(), "early.exit.value");
4073 }
4074 ExitIRI->removeIncomingValueFor(EarlyExitingVPBB);
4075 ExitIRI->addIncoming(NewIncoming);
4076 }
4077
4078 EarlyExitingVPBB->getTerminator()->eraseFromParent();
4079 VPBlockUtils::disconnectBlocks(EarlyExitingVPBB, EarlyExitVPBB);
4080 VPBlockUtils::connectBlocks(VectorEarlyExitVPBB, EarlyExitVPBB);
4081 }
4082
4083 // Chain through exits: for each exit, check if its condition is true at
4084 // the first active lane. If so, take that exit; otherwise, try the next.
4085 // The last exit needs no check since it must be taken if all others fail.
4086 //
4087 // For 3 exits (cond.0, cond.1, cond.2), this creates:
4088 //
4089 // latch:
4090 // ...
4091 // EMIT vp<%combined> = logical-or vp<%cond.0>, vp<%cond.1>, vp<%cond.2>
4092 // ...
4093 //
4094 // vector.early.exit.check:
4095 // EMIT vp<%first.lane> = first-active-lane vp<%combined>
4096 // EMIT vp<%at.cond.0> = extract-lane vp<%first.lane>, vp<%cond.0>
4097 // EMIT branch-on-cond vp<%at.cond.0>
4098 // Successor(s): vector.early.exit.0, vector.early.exit.check.0
4099 //
4100 // vector.early.exit.check.0:
4101 // EMIT vp<%at.cond.1> = extract-lane vp<%first.lane>, vp<%cond.1>
4102 // EMIT branch-on-cond vp<%at.cond.1>
4103 // Successor(s): vector.early.exit.1, vector.early.exit.2
4104 VPBasicBlock *CurrentBB = DispatchVPBB;
4105 for (auto [I, Exit] : enumerate(ArrayRef(Exits).drop_back())) {
4106 VPValue *LaneVal = DispatchBuilder.createNaryOp(
4107 VPInstruction::ExtractLane, {FirstActiveLane, Exit.CondToExit},
4108 DebugLoc::getUnknown(), "exit.cond.at.lane");
4109
4110 // For the last dispatch, branch directly to the last exit on false;
4111 // otherwise, create a new check block.
4112 bool IsLastDispatch = (I + 2 == Exits.size());
4113 VPBasicBlock *FalseBB =
4114 IsLastDispatch ? VectorEarlyExitVPBBs.back()
4115 : Plan.createVPBasicBlock(
4116 Twine("vector.early.exit.check.") + Twine(I));
4117
4118 DispatchBuilder.createNaryOp(VPInstruction::BranchOnCond, {LaneVal});
4119 CurrentBB->setSuccessors({VectorEarlyExitVPBBs[I], FalseBB});
4120 VectorEarlyExitVPBBs[I]->setPredecessors({CurrentBB});
4121 FalseBB->setPredecessors({CurrentBB});
4122
4123 CurrentBB = FalseBB;
4124 DispatchBuilder.setInsertPoint(CurrentBB);
4125 }
4126
4127 return true;
4128}
4129
4130/// This function tries convert extended in-loop reductions to
4131/// VPExpressionRecipe and clamp the \p Range if it is beneficial and
4132/// valid. The created recipe must be decomposed to its constituent
4133/// recipes before execution.
4134static VPExpressionRecipe *
4136 VFRange &Range) {
4137 Type *RedTy = Red->getScalarType();
4138 VPValue *VecOp = Red->getVecOp();
4139
4140 assert(!Red->isPartialReduction() &&
4141 "This path does not support partial reductions");
4142
4143 // Clamp the range if using extended-reduction is profitable.
4144 auto IsExtendedRedValidAndClampRange =
4145 [&](unsigned Opcode, Instruction::CastOps ExtOpc, Type *SrcTy) -> bool {
4147 [&](ElementCount VF) {
4148 auto *SrcVecTy = cast<VectorType>(toVectorTy(SrcTy, VF));
4150
4152 InstructionCost ExtCost =
4153 cast<VPWidenCastRecipe>(VecOp)->computeCost(VF, Ctx);
4154 InstructionCost RedCost = Red->computeCost(VF, Ctx);
4155
4156 assert(!RedTy->isFloatingPointTy() &&
4157 "getExtendedReductionCost only supports integer types");
4158 ExtRedCost = Ctx.TTI.getExtendedReductionCost(
4159 Opcode, ExtOpc == Instruction::CastOps::ZExt, RedTy, SrcVecTy,
4160 Red->getFastMathFlagsOrNone(), CostKind);
4161 return ExtRedCost.isValid() && ExtRedCost < ExtCost + RedCost;
4162 },
4163 Range);
4164 };
4165
4166 VPValue *A;
4167 // Match reduce(ext)).
4169 IsExtendedRedValidAndClampRange(
4170 RecurrenceDescriptor::getOpcode(Red->getRecurrenceKind()),
4171 cast<VPWidenCastRecipe>(VecOp)->getOpcode(), A->getScalarType()))
4172 return new VPExpressionRecipe(cast<VPWidenCastRecipe>(VecOp), Red);
4173
4174 return nullptr;
4175}
4176
4177/// This function tries convert extended in-loop reductions to
4178/// VPExpressionRecipe and clamp the \p Range if it is beneficial
4179/// and valid. The created VPExpressionRecipe must be decomposed to its
4180/// constituent recipes before execution. Patterns of the
4181/// VPExpressionRecipe:
4182/// reduce.add(mul(...)),
4183/// reduce.add(mul(ext(A), ext(B))),
4184/// reduce.add(ext(mul(ext(A), ext(B)))).
4185/// reduce.fadd(fmul(ext(A), ext(B)))
4186static VPExpressionRecipe *
4188 VPCostContext &Ctx, VFRange &Range) {
4189 unsigned Opcode = RecurrenceDescriptor::getOpcode(Red->getRecurrenceKind());
4190 if (Opcode != Instruction::Add && Opcode != Instruction::Sub &&
4191 Opcode != Instruction::FAdd)
4192 return nullptr;
4193
4194 assert(!Red->isPartialReduction() &&
4195 "This path does not support partial reductions");
4196 Type *RedTy = Red->getScalarType();
4197
4198 // Clamp the range if using multiply-accumulate-reduction is profitable.
4199 auto IsMulAccValidAndClampRange =
4201 VPWidenCastRecipe *OuterExt) -> bool {
4203 [&](ElementCount VF) {
4205 Type *SrcTy = Ext0 ? Ext0->getOperand(0)->getScalarType() : RedTy;
4206 InstructionCost MulAccCost;
4207
4208 // getMulAccReductionCost for in-loop reductions does not support
4209 // mixed or floating-point extends.
4210 if (Ext0 && Ext1 &&
4211 (Ext0->getOpcode() != Ext1->getOpcode() ||
4212 Ext0->getOpcode() == Instruction::CastOps::FPExt))
4213 return false;
4214
4215 bool IsZExt =
4216 !Ext0 || Ext0->getOpcode() == Instruction::CastOps::ZExt;
4217 auto *SrcVecTy = cast<VectorType>(toVectorTy(SrcTy, VF));
4218 MulAccCost = Ctx.TTI.getMulAccReductionCost(IsZExt, Opcode, RedTy,
4219 SrcVecTy, CostKind);
4220
4221 InstructionCost MulCost = Mul->computeCost(VF, Ctx);
4222 InstructionCost RedCost = Red->computeCost(VF, Ctx);
4223 InstructionCost ExtCost = 0;
4224 if (Ext0)
4225 ExtCost += Ext0->computeCost(VF, Ctx);
4226 if (Ext1)
4227 ExtCost += Ext1->computeCost(VF, Ctx);
4228 if (OuterExt)
4229 ExtCost += OuterExt->computeCost(VF, Ctx);
4230
4231 return MulAccCost.isValid() &&
4232 MulAccCost < ExtCost + MulCost + RedCost;
4233 },
4234 Range);
4235 };
4236
4237 VPValue *VecOp = Red->getVecOp();
4238 VPRecipeBase *Sub = nullptr;
4239 VPValue *A, *B;
4240 VPValue *Tmp = nullptr;
4241
4242 if (RedTy->isFloatingPointTy())
4243 return nullptr;
4244
4245 // Sub reductions could have a sub between the add reduction and vec op.
4246 if (match(VecOp, m_Sub(m_ZeroInt(), m_VPValue(Tmp)))) {
4247 Sub = VecOp->getDefiningRecipe();
4248 VecOp = Tmp;
4249 }
4250
4251 // If ValB is a constant and can be safely extended, truncate it to the same
4252 // type as ExtA's operand, then extend it to the same type as ExtA. This
4253 // creates two uniform extends that can more easily be matched by the rest of
4254 // the bundling code. The ExtB reference, ValB and operand 1 of Mul are all
4255 // replaced with the new extend of the constant.
4256 auto ExtendAndReplaceConstantOp = [](VPWidenCastRecipe *ExtA,
4257 VPWidenCastRecipe *&ExtB, VPValue *&ValB,
4258 VPWidenRecipe *Mul) {
4259 if (!ExtA || ExtB || !isa<VPIRValue>(ValB))
4260 return;
4261 Type *NarrowTy = ExtA->getOperand(0)->getScalarType();
4262 Instruction::CastOps ExtOpc = ExtA->getOpcode();
4263 const APInt *Const;
4264 if (!match(ValB, m_APInt(Const)) ||
4266 Const, NarrowTy, TTI::getPartialReductionExtendKind(ExtOpc)))
4267 return;
4268 // The truncate ensures that the type of each extended operand is the
4269 // same, and it's been proven that the constant can be extended from
4270 // NarrowTy safely. Necessary since ExtA's extended operand would be
4271 // e.g. an i8, while the const will likely be an i32. This will be
4272 // elided by later optimisations.
4273 VPBuilder Builder(Mul);
4274 auto *Trunc =
4275 Builder.createWidenCast(Instruction::CastOps::Trunc, ValB, NarrowTy);
4276 Type *WideTy = ExtA->getScalarType();
4277 ValB = ExtB = Builder.createWidenCast(ExtOpc, Trunc, WideTy);
4278 Mul->setOperand(1, ExtB);
4279 };
4280
4281 // Try to match reduce.add(mul(...)).
4282 if (match(VecOp, m_Mul(m_VPValue(A), m_VPValue(B)))) {
4283 auto *RecipeA = dyn_cast<VPWidenCastRecipe>(A);
4284 auto *RecipeB = dyn_cast<VPWidenCastRecipe>(B);
4285 auto *Mul = cast<VPWidenRecipe>(VecOp);
4286
4287 // Convert reduce.add(mul(ext, const)) to reduce.add(mul(ext, ext(const)))
4288 ExtendAndReplaceConstantOp(RecipeA, RecipeB, B, Mul);
4289
4290 // Match reduce.add/sub(mul(ext, ext)).
4291 if (RecipeA && RecipeB && match(RecipeA, m_ZExtOrSExt(m_VPValue())) &&
4292 match(RecipeB, m_ZExtOrSExt(m_VPValue())) &&
4293 IsMulAccValidAndClampRange(Mul, RecipeA, RecipeB, nullptr)) {
4294 if (Sub)
4295 return new VPExpressionRecipe(RecipeA, RecipeB, Mul,
4296 cast<VPWidenRecipe>(Sub), Red);
4297 return new VPExpressionRecipe(RecipeA, RecipeB, Mul, Red);
4298 }
4299 // TODO: Add an expression type for this variant with a negated mul
4300 if (!Sub && IsMulAccValidAndClampRange(Mul, nullptr, nullptr, nullptr))
4301 return new VPExpressionRecipe(Mul, Red);
4302 }
4303 // TODO: Add an expression type for negated versions of other expression
4304 // variants.
4305 if (Sub)
4306 return nullptr;
4307
4308 // Match reduce.add(ext(mul(A, B))).
4309 if (match(VecOp, m_ZExtOrSExt(m_Mul(m_VPValue(A), m_VPValue(B))))) {
4310 auto *Ext = cast<VPWidenCastRecipe>(VecOp);
4311 auto *Mul = cast<VPWidenRecipe>(Ext->getOperand(0));
4312 auto *Ext0 = dyn_cast<VPWidenCastRecipe>(A);
4313 auto *Ext1 = dyn_cast<VPWidenCastRecipe>(B);
4314
4315 // reduce.add(ext(mul(ext, const)))
4316 // -> reduce.add(ext(mul(ext, ext(const))))
4317 ExtendAndReplaceConstantOp(Ext0, Ext1, B, Mul);
4318
4319 // reduce.add(ext(mul(ext(A), ext(B))))
4320 // -> reduce.add(mul(wider_ext(A), wider_ext(B)))
4321 // The inner extends must either have the same opcode as the outer extend or
4322 // be the same, in which case the multiply can never result in a negative
4323 // value and the outer extend can be folded away by doing wider
4324 // extends for the operands of the mul.
4325 if (Ext0 && Ext1 &&
4326 (Ext->getOpcode() == Ext0->getOpcode() || Ext0 == Ext1) &&
4327 Ext0->getOpcode() == Ext1->getOpcode() &&
4328 IsMulAccValidAndClampRange(Mul, Ext0, Ext1, Ext) && Mul->hasOneUse()) {
4329 auto *NewExt0 = new VPWidenCastRecipe(
4330 Ext0->getOpcode(), Ext0->getOperand(0), Ext->getScalarType(), nullptr,
4331 *Ext0, *Ext0, Ext0->getDebugLoc());
4332 NewExt0->insertBefore(Ext0);
4333
4334 VPWidenCastRecipe *NewExt1 = NewExt0;
4335 if (Ext0 != Ext1) {
4336 NewExt1 = new VPWidenCastRecipe(Ext1->getOpcode(), Ext1->getOperand(0),
4337 Ext->getScalarType(), nullptr, *Ext1,
4338 *Ext1, Ext1->getDebugLoc());
4339 NewExt1->insertBefore(Ext1);
4340 }
4341 auto *NewMul = Mul->cloneWithOperands({NewExt0, NewExt1});
4342 NewMul->insertBefore(Mul);
4343 Ext->replaceAllUsesWith(NewMul);
4344 Ext->eraseFromParent();
4345 Mul->eraseFromParent();
4346 return new VPExpressionRecipe(NewExt0, NewExt1, NewMul, Red);
4347 }
4348 }
4349 return nullptr;
4350}
4351
4352/// This function tries to create abstract recipes from the reduction recipe for
4353/// following optimizations and cost estimation.
4355 VPCostContext &Ctx,
4356 VFRange &Range) {
4357 // Creation of VPExpressions for partial reductions is entirely handled in
4358 // transformToPartialReduction.
4359 assert(!Red->isPartialReduction() &&
4360 "This path does not support partial reductions");
4361
4362 VPExpressionRecipe *AbstractR = nullptr;
4363 auto IP = std::next(Red->getIterator());
4364 auto *VPBB = Red->getParent();
4365 if (auto *MulAcc = tryToMatchAndCreateMulAccumulateReduction(Red, Ctx, Range))
4366 AbstractR = MulAcc;
4367 else if (auto *ExtRed = tryToMatchAndCreateExtendedReduction(Red, Ctx, Range))
4368 AbstractR = ExtRed;
4369 // Cannot create abstract inloop reduction recipes.
4370 if (!AbstractR)
4371 return;
4372
4373 AbstractR->insertBefore(*VPBB, IP);
4374 Red->replaceAllUsesWith(AbstractR);
4375}
4376
4387
4389 if (Plan.hasScalarVFOnly())
4390 return;
4391
4392#ifndef NDEBUG
4393 VPDominatorTree VPDT(Plan);
4394#endif
4395
4396 SmallVector<VPValue *> VPValues;
4397 if (VPValue *BTC = Plan.getBackedgeTakenCount())
4398 VPValues.push_back(BTC);
4399 append_range(VPValues, Plan.getLiveIns());
4400 for (VPRecipeBase &R : *Plan.getEntry())
4401 append_range(VPValues, R.definedValues());
4402
4403 auto *VectorPreheader = Plan.getVectorPreheader();
4404 for (VPValue *VPV : VPValues) {
4406 continue;
4407
4408 // Add explicit broadcast at the insert point that dominates all users.
4409 VPBasicBlock *HoistBlock = VectorPreheader;
4410 VPBasicBlock::iterator HoistPoint = VectorPreheader->end();
4411 for (VPUser *User : VPV->users()) {
4412 if (User->usesScalars(VPV))
4413 continue;
4414 if (cast<VPRecipeBase>(User)->getParent() == VectorPreheader)
4415 HoistPoint = HoistBlock->begin();
4416 else
4417 assert(VPDT.dominates(VectorPreheader,
4418 cast<VPRecipeBase>(User)->getParent()) &&
4419 "All users must be in the vector preheader or dominated by it");
4420 }
4421
4422 VPBuilder Builder(cast<VPBasicBlock>(HoistBlock), HoistPoint);
4423 auto *Broadcast = Builder.createNaryOp(VPInstruction::Broadcast, {VPV});
4424 VPV->replaceUsesWithIf(Broadcast,
4425 [VPV, Broadcast](VPUser &U, unsigned Idx) {
4426 return Broadcast != &U && !U.usesScalars(VPV);
4427 });
4428 }
4429}
4430
4431// Collect common metadata from a group of replicate recipes by intersecting
4432// metadata from all recipes in the group.
4434 VPIRMetadata CommonMetadata = *Recipes.front();
4435 for (VPReplicateRecipe *Recipe : drop_begin(Recipes))
4436 CommonMetadata.intersect(*Recipe);
4437 return CommonMetadata;
4438}
4439
4440template <unsigned Opcode>
4444 const Loop *L) {
4445 static_assert(Opcode == Instruction::Load || Opcode == Instruction::Store,
4446 "Only Load and Store opcodes supported");
4447 [[maybe_unused]] constexpr bool IsLoad = (Opcode == Instruction::Load);
4448
4449 // For each address, collect operations with the same or complementary masks.
4452 Plan, PSE, L,
4453 [](VPReplicateRecipe *RepR) { return RepR->isPredicated(); });
4454 for (auto Recipes : Groups) {
4455 if (Recipes.size() < 2)
4456 continue;
4457
4459 map_range(Recipes, bind_back<getLoadStoreValueType>(IsLoad))) &&
4460 "Expected all recipes in group to have the same load-store type");
4461
4462 // Collect groups with the same or complementary masks.
4463 for (VPReplicateRecipe *&RecipeI : Recipes) {
4464 if (!RecipeI)
4465 continue;
4466
4467 VPValue *MaskI = RecipeI->getMask();
4469 Group.push_back(RecipeI);
4470 RecipeI = nullptr;
4471
4472 // Find all operations with the same or complementary masks.
4473 bool HasComplementaryMask = false;
4474 for (VPReplicateRecipe *&RecipeJ : Recipes) {
4475 if (!RecipeJ)
4476 continue;
4477
4478 VPValue *MaskJ = RecipeJ->getMask();
4479 // Check if any operation in the group has a complementary mask with
4480 // another, that is M1 == NOT(M2) or M2 == NOT(M1).
4481 HasComplementaryMask |= match(MaskI, m_Not(m_Specific(MaskJ))) ||
4482 match(MaskJ, m_Not(m_Specific(MaskI)));
4483 Group.push_back(RecipeJ);
4484 RecipeJ = nullptr;
4485 }
4486
4487 if (HasComplementaryMask) {
4488 assert(Group.size() >= 2 && "must have at least 2 entries");
4489 AllGroups.push_back(std::move(Group));
4490 }
4491 }
4492 }
4493
4494 return AllGroups;
4495}
4496
4497// Find the recipe with minimum alignment in the group.
4498template <typename InstType>
4499static VPReplicateRecipe *
4501 return *min_element(Group, [](VPReplicateRecipe *A, VPReplicateRecipe *B) {
4502 return cast<InstType>(A->getUnderlyingInstr())->getAlign() <
4503 cast<InstType>(B->getUnderlyingInstr())->getAlign();
4504 });
4505}
4506
4509 const Loop *L) {
4510 auto Groups =
4512 if (Groups.empty())
4513 return;
4514
4515 // Process each group of loads.
4516 for (auto &Group : Groups) {
4517 // Try to use the earliest (most dominating) load to replace all others.
4518 VPReplicateRecipe *EarliestLoad = Group[0];
4519 VPBasicBlock *FirstBB = EarliestLoad->getParent();
4520 VPBasicBlock *LastBB = Group.back()->getParent();
4521
4522 // Check that the load doesn't alias with stores between first and last.
4523 auto LoadLoc = vputils::getMemoryLocation(*EarliestLoad);
4524 if (!LoadLoc || !canHoistOrSinkWithNoAliasCheck(*LoadLoc, FirstBB, LastBB))
4525 continue;
4526
4527 // Collect common metadata from all loads in the group.
4528 VPIRMetadata CommonMetadata = getCommonMetadata(Group);
4529
4530 // Find the load with minimum alignment to use.
4531 auto *LoadWithMinAlign = findRecipeWithMinAlign<LoadInst>(Group);
4532
4533 bool IsSingleScalar = EarliestLoad->isSingleScalar();
4534 assert(all_of(Group,
4535 [IsSingleScalar](VPReplicateRecipe *R) {
4536 return R->isSingleScalar() == IsSingleScalar;
4537 }) &&
4538 "all members in group must agree on IsSingleScalar");
4539
4540 // Create an unpredicated version of the earliest load with common
4541 // metadata.
4542 auto *UnpredicatedLoad = new VPReplicateRecipe(
4543 LoadWithMinAlign->getUnderlyingInstr(), {EarliestLoad->getOperand(0)},
4544 IsSingleScalar, /*Mask=*/nullptr, *EarliestLoad, CommonMetadata);
4545
4546 UnpredicatedLoad->insertBefore(EarliestLoad);
4547
4548 // Replace all loads in the group with the unpredicated load.
4549 for (VPReplicateRecipe *Load : Group) {
4550 Load->replaceAllUsesWith(UnpredicatedLoad);
4551 Load->eraseFromParent();
4552 }
4553 }
4554}
4555
4556static bool
4558 PredicatedScalarEvolution &PSE, const Loop &L) {
4559 auto StoreLoc = vputils::getMemoryLocation(*StoresToSink.front());
4560 if (!StoreLoc || !StoreLoc->AATags.Scope)
4561 return false;
4562
4563 // When sinking a group of stores, all members of the group alias each other.
4564 // Skip them during the alias checks.
4565 VPBasicBlock *FirstBB = StoresToSink.front()->getParent();
4566 VPBasicBlock *LastBB = StoresToSink.back()->getParent();
4567 SinkStoreInfo SinkInfo(StoresToSink, *StoresToSink[0], PSE, L);
4568 return canHoistOrSinkWithNoAliasCheck(*StoreLoc, FirstBB, LastBB, SinkInfo);
4569}
4570
4573 const Loop *L) {
4574 auto Groups =
4576 if (Groups.empty())
4577 return;
4578
4579 for (auto &Group : Groups) {
4580 if (!canSinkStoreWithNoAliasCheck(Group, PSE, *L))
4581 continue;
4582
4583 // Use the last (most dominated) store's location for the unconditional
4584 // store.
4585 VPReplicateRecipe *LastStore = Group.back();
4586 VPBasicBlock *InsertBB = LastStore->getParent();
4587
4588 // Collect common alias metadata from all stores in the group.
4589 VPIRMetadata CommonMetadata = getCommonMetadata(Group);
4590
4591 // Build select chain for stored values.
4592 VPValue *SelectedValue = Group[0]->getOperand(0);
4593 VPBuilder Builder(InsertBB, LastStore->getIterator());
4594
4595 bool IsSingleScalar = Group[0]->isSingleScalar();
4596 for (unsigned I = 1; I < Group.size(); ++I) {
4597 assert(IsSingleScalar == Group[I]->isSingleScalar() &&
4598 "all members in group must agree on IsSingleScalar");
4599 VPValue *Mask = Group[I]->getMask();
4600 VPValue *Value = Group[I]->getOperand(0);
4601 SelectedValue = Builder.createSelect(Mask, Value, SelectedValue,
4602 Group[I]->getDebugLoc());
4603 }
4604
4605 // Find the store with minimum alignment to use.
4606 auto *StoreWithMinAlign = findRecipeWithMinAlign<StoreInst>(Group);
4607
4608 // Create unconditional store with selected value and common metadata.
4609 auto *UnpredicatedStore = new VPReplicateRecipe(
4610 StoreWithMinAlign->getUnderlyingInstr(),
4611 {SelectedValue, LastStore->getOperand(1)}, IsSingleScalar,
4612 /*Mask=*/nullptr, *LastStore, CommonMetadata);
4613 UnpredicatedStore->insertBefore(*InsertBB, LastStore->getIterator());
4614
4615 // Remove all predicated stores from the group.
4616 for (VPReplicateRecipe *Store : Group)
4617 Store->eraseFromParent();
4618 }
4619}
4620
4622 VPlan &Plan, ElementCount BestVF, unsigned BestUF,
4624 assert(Plan.hasVF(BestVF) && "BestVF is not available in Plan");
4625 assert(Plan.hasUF(BestUF) && "BestUF is not available in Plan");
4626
4627 VPValue *TC = Plan.getTripCount();
4628 if (TC->user_empty())
4629 return;
4630
4631 // Skip cases for which the trip count may be non-trivial to materialize.
4632 // I.e., when a scalar tail is absent - due to tail folding, or when a scalar
4633 // tail is required.
4634 if (Plan.hasTailFolded() || !Plan.hasScalarTail() ||
4636 Plan.getScalarPreheader() ||
4637 !isa<VPIRValue>(TC))
4638 return;
4639
4640 // Materialize vector trip counts for constants early if it can simply
4641 // be computed as (Original TC / VF * UF) * VF * UF.
4642 // TODO: Compute vector trip counts for loops requiring a scalar epilogue and
4643 // tail-folded loops.
4644 ScalarEvolution &SE = *PSE.getSE();
4645 auto *TCScev = SE.getSCEV(TC->getLiveInIRValue());
4646 if (!isa<SCEVConstant>(TCScev))
4647 return;
4648 const SCEV *VFxUF = SE.getElementCount(TCScev->getType(), BestVF * BestUF);
4649 auto VecTCScev = SE.getMulExpr(SE.getUDivExpr(TCScev, VFxUF), VFxUF);
4650 if (auto *ConstVecTC = dyn_cast<SCEVConstant>(VecTCScev))
4651 Plan.getVectorTripCount().setUnderlyingValue(ConstVecTC->getValue());
4652}
4653
4655 VPBasicBlock *VectorPH) {
4657 if (BTC->user_empty())
4658 return;
4659
4660 VPBuilder Builder(VectorPH, VectorPH->begin());
4661 auto *TCTy = Plan.getTripCount()->getScalarType();
4662 auto *TCMO =
4663 Builder.createSub(Plan.getTripCount(), Plan.getConstantInt(TCTy, 1),
4664 DebugLoc::getCompilerGenerated(), "trip.count.minus.1");
4665 BTC->replaceAllUsesWith(TCMO);
4666}
4667
4669 if (Plan.hasScalarVFOnly())
4670 return;
4671
4672 VPRegionBlock *LoopRegion = Plan.getVectorLoopRegion();
4673 auto VPBBsOutsideLoopRegion = VPBlockUtils::blocksOnly<VPBasicBlock>(
4675 auto VPBBsInsideLoopRegion = VPBlockUtils::blocksOnly<VPBasicBlock>(
4676 vp_depth_first_shallow(LoopRegion->getEntry()));
4677 // Materialize Build(Struct)Vector for all replicating VPReplicateRecipes,
4678 // VPScalarIVStepsRecipe and VPInstructions, excluding ones in replicate
4679 // regions. Those are not materialized explicitly yet.
4680 // TODO: materialize build vectors for replicating recipes in replicating
4681 // regions.
4682 for (VPBasicBlock *VPBB :
4683 concat<VPBasicBlock *>(VPBBsOutsideLoopRegion, VPBBsInsideLoopRegion)) {
4684 for (VPRecipeBase &R : make_early_inc_range(*VPBB)) {
4686 continue;
4687 auto *DefR = cast<VPSingleDefRecipe>(&R);
4688 auto UsesVectorOrInsideReplicateRegion = [DefR, LoopRegion](VPUser *U) {
4689 VPRegionBlock *ParentRegion = cast<VPRecipeBase>(U)->getRegion();
4690 return !U->usesScalars(DefR) || ParentRegion != LoopRegion;
4691 };
4692 if (none_of(DefR->users(), UsesVectorOrInsideReplicateRegion))
4693 continue;
4694
4695 Type *ScalarTy = DefR->getScalarType();
4696 unsigned Opcode = ScalarTy->isStructTy()
4699 auto *BuildVector = new VPInstruction(Opcode, {DefR});
4700 BuildVector->insertAfter(DefR);
4701
4702 DefR->replaceUsesWithIf(
4703 BuildVector, [BuildVector, &UsesVectorOrInsideReplicateRegion](
4704 VPUser &U, unsigned) {
4705 return &U != BuildVector && UsesVectorOrInsideReplicateRegion(&U);
4706 });
4707 }
4708 }
4709
4710 // Create explicit VPInstructions to convert vectors to scalars. The current
4711 // implementation is conservative - it may miss some cases that may or may not
4712 // be vector values. TODO: introduce Unpacks speculatively - remove them later
4713 // if they are known to operate on scalar values.
4714 for (VPBasicBlock *VPBB : VPBBsInsideLoopRegion) {
4715 for (VPRecipeBase &R : make_early_inc_range(*VPBB)) {
4717 VPDerivedIVRecipe>(&R))
4718 continue;
4719 for (VPValue *Def : R.definedValues()) {
4720 // Skip recipes that are single-scalar.
4721 // TODO: The Defs skipped here may or may not be vector values.
4722 // Introduce Unpacks, and remove them later, if they are guaranteed to
4723 // produce scalar values.
4724 if (vputils::isSingleScalar(Def))
4725 continue;
4726
4727 // Only introduce an Unpack if some, but not all, users use the first
4728 // lane only.
4729 unsigned NumFirstLaneUsers = count_if(Def->users(), [&Def](VPUser *U) {
4730 return U->usesFirstLaneOnly(Def);
4731 });
4732 if (!NumFirstLaneUsers || NumFirstLaneUsers == Def->getNumUsers())
4733 continue;
4734
4735 auto *Unpack = new VPInstruction(VPInstruction::Unpack, {Def});
4736 if (R.isPhi())
4737 Unpack->insertBefore(*VPBB, VPBB->getFirstNonPhi());
4738 else
4739 Unpack->insertAfter(&R);
4740 Def->replaceUsesWithIf(Unpack, [&Def](VPUser &U, unsigned) {
4741 return U.usesFirstLaneOnly(Def);
4742 });
4743 }
4744 }
4745 }
4746}
4747
4749 VPlan &Plan, VPBasicBlock *VectorPHVPBB, bool TailByMasking,
4750 bool RequiresScalarEpilogue, VPValue *Step,
4751 std::optional<uint64_t> MaxRuntimeStep) {
4752 VPSymbolicValue &VectorTC = Plan.getVectorTripCount();
4753 // There's nothing to do if there are no users of the vector trip count or its
4754 // IR value has already been set.
4755 if (VectorTC.user_empty() || VectorTC.getUnderlyingValue())
4756 return;
4757
4758 VPValue *TC = Plan.getTripCount();
4759 Type *TCTy = TC->getScalarType();
4760 VPBasicBlock::iterator InsertPt = VectorPHVPBB->begin();
4761 if (auto *StepR = Step->getDefiningRecipe()) {
4762 assert(VPDominatorTree(Plan).dominates(StepR->getParent(), VectorPHVPBB) &&
4763 "Step VPBB must dominate VectorPHVPBB");
4764 // Insert after Step's definition to maintain valid def-use ordering.
4765 InsertPt = std::next(StepR->getIterator());
4766 }
4767 VPBuilder Builder(VectorPHVPBB, InsertPt);
4768
4769 // For scalable steps, if TC is a constant and is divisible by the maximum
4770 // possible runtime step, then TC % Step == 0 for all valid vscale values
4771 // and the vector trip count equals TC directly.
4772 const APInt *TCVal;
4773 if (!RequiresScalarEpilogue && match(TC, m_APInt(TCVal)) && MaxRuntimeStep &&
4774 TCVal->urem(*MaxRuntimeStep) == 0) {
4775 VectorTC.replaceAllUsesWith(TC);
4776 return;
4777 }
4778
4779 // If the tail is to be folded by masking, round the number of iterations N
4780 // up to a multiple of Step instead of rounding down. This is done by first
4781 // adding Step-1 and then rounding down. Note that it's ok if this addition
4782 // overflows: the vector induction variable will eventually wrap to zero given
4783 // that it starts at zero and its Step is a power of two; the loop will then
4784 // exit, with the last early-exit vector comparison also producing all-true.
4785 if (TailByMasking) {
4786 TC = Builder.createAdd(
4787 TC, Builder.createSub(Step, Plan.getConstantInt(TCTy, 1)),
4788 DebugLoc::getCompilerGenerated(), "n.rnd.up");
4789 }
4790
4791 // Now we need to generate the expression for the part of the loop that the
4792 // vectorized body will execute. This is equal to N - (N % Step) if scalar
4793 // iterations are not required for correctness, or N - Step, otherwise. Step
4794 // is equal to the vectorization factor (number of SIMD elements) times the
4795 // unroll factor (number of SIMD instructions).
4796 VPValue *R =
4797 Builder.createNaryOp(Instruction::URem, {TC, Step},
4798 DebugLoc::getCompilerGenerated(), "n.mod.vf");
4799
4800 // There are cases where we *must* run at least one iteration in the remainder
4801 // loop. See the cost model for when this can happen. If the step evenly
4802 // divides the trip count, we set the remainder to be equal to the step. If
4803 // the step does not evenly divide the trip count, no adjustment is necessary
4804 // since there will already be scalar iterations. Note that the minimum
4805 // iterations check ensures that N >= Step.
4806 if (RequiresScalarEpilogue) {
4807 assert(!TailByMasking &&
4808 "requiring scalar epilogue is not supported with fail folding");
4809 VPValue *IsZero =
4810 Builder.createICmp(CmpInst::ICMP_EQ, R, Plan.getZero(TCTy));
4811 R = Builder.createSelect(IsZero, Step, R);
4812 }
4813
4814 VPValue *Res =
4815 Builder.createSub(TC, R, DebugLoc::getCompilerGenerated(), "n.vec");
4816 VectorTC.replaceAllUsesWith(Res);
4817}
4818
4820 ElementCount VFEC) {
4821 // If VF and VFxUF have already been materialized (no remaining users),
4822 // there's nothing more to do.
4823 if (Plan.getVF().isMaterialized()) {
4824 assert(Plan.getVFxUF().isMaterialized() &&
4825 "VF and VFxUF must be materialized together");
4826 return;
4827 }
4828
4829 VPBuilder Builder(VectorPH, VectorPH->begin());
4830 Type *TCTy = Plan.getTripCount()->getScalarType();
4831 VPValue &VF = Plan.getVF();
4832 VPValue &VFxUF = Plan.getVFxUF();
4833 // If there are no users of the runtime VF, compute VFxUF by constant folding
4834 // the multiplication of VF and UF.
4835 if (VF.user_empty()) {
4836 VPValue *RuntimeVFxUF =
4837 Builder.createElementCount(TCTy, VFEC * Plan.getConcreteUF());
4838 VFxUF.replaceAllUsesWith(RuntimeVFxUF);
4839 return;
4840 }
4841
4842 // For users of the runtime VF, compute it as VF * vscale, and VFxUF as (VF *
4843 // vscale) * UF.
4844 VPValue *RuntimeVF = Builder.createElementCount(TCTy, VFEC);
4846 VPValue *BC = Builder.createNaryOp(VPInstruction::Broadcast, RuntimeVF);
4848 BC, [&VF](VPUser &U, unsigned) { return !U.usesScalars(&VF); });
4849 }
4850 VF.replaceAllUsesWith(RuntimeVF);
4851
4852 VPValue *MulByUF = Builder.createOverflowingOp(
4853 Instruction::Mul,
4854 {RuntimeVF, Plan.getConstantInt(TCTy, Plan.getConcreteUF())},
4855 {true, false});
4856 VFxUF.replaceAllUsesWith(MulByUF);
4857}
4858
4860 VPRegionBlock *LoopRegion = Plan.getVectorLoopRegion();
4861 VPValue *HeaderMask = LoopRegion->getHeaderMask();
4862 Type *I1Ty = IntegerType::getInt1Ty(Plan.getContext());
4863
4864 VPBuilder Builder(Plan.getVectorPreheader());
4865 auto *AliasMask = Builder.createNaryOp(
4866 VPInstruction::IncomingAliasMask, {}, nullptr, {}, {},
4867 DebugLoc::getUnknown(), "incoming.alias.mask", I1Ty);
4868
4869 VPBasicBlock *Header = LoopRegion->getEntryBasicBlock();
4870 Builder = VPBuilder(Header, Header->getFirstNonPhi());
4871
4872 // Update all existing users of the header mask to "HeaderMask & AliasMask".
4873 auto *ClampedHeaderMask = Builder.createAnd(HeaderMask, AliasMask);
4874 HeaderMask->replaceUsesWithIf(ClampedHeaderMask, [&](VPUser &U, unsigned) {
4875 return &U != ClampedHeaderMask;
4876 });
4877}
4878
4879VPValue *
4881 ArrayRef<PointerDiffInfo> DiffChecks) {
4882 VPBuilder Builder(AliasCheckVPBB);
4883 Type *I1Ty = IntegerType::getInt1Ty(Plan.getContext());
4884
4885 VPValue *IncomingAliasMask = vputils::findIncomingAliasMask(Plan);
4886 assert(IncomingAliasMask && "Expected an alias mask!");
4887
4888 VPValue *AliasMask = nullptr;
4889 for (const PointerDiffInfo &Check : DiffChecks) {
4891 VPValue *Sink =
4893 Type *AddrType = Src->getScalarType();
4894
4895 // TODO: Only freeze the required pointer (not both src and sink).
4896 if (Check.NeedsFreeze) {
4897 Src = Builder.createScalarFreeze(Src, AddrType, DebugLoc::getUnknown());
4898 Sink = Builder.createScalarFreeze(Sink, AddrType, DebugLoc::getUnknown());
4899 }
4900
4901 // TODO: Generate loop_dependence_raw_mask when there's a read-after-write
4902 // dependency between the source and the sink. This is not necessary for
4903 // correctness of the mask, but using the "raw" variant prevents loads
4904 // depending on the completion of stores.
4905 VPWidenIntrinsicRecipe *WARMask = Builder.insert(new VPWidenIntrinsicRecipe(
4906 Intrinsic::loop_dependence_war_mask,
4907 {Src, Sink, Plan.getConstantInt(AddrType, Check.AccessSize)}, I1Ty));
4908
4909 if (AliasMask)
4910 AliasMask = Builder.createAnd(AliasMask, WARMask);
4911 else
4912 AliasMask = WARMask;
4913 }
4914
4916 Type *IndexTy = Plan.getDataLayout().getIndexType(Plan.getContext(), 0);
4917 VPValue *NumActive = Builder.createNaryOp(
4918 VPInstruction::NumActiveLanes, {AliasMask}, nullptr, {}, {},
4919 DebugLoc::getUnknown(), "num.active.lanes", IndexTy);
4920 VPValue *ClampedVF = Builder.createScalarZExtOrTrunc(
4921 NumActive, IVTy, DebugLoc::getCompilerGenerated());
4922
4923 IncomingAliasMask->replaceAllUsesWith(AliasMask);
4924
4925 return ClampedVF;
4926}
4927
4929 VPlan &Plan, ArrayRef<PointerDiffInfo> DiffChecks, bool HasBranchWeights) {
4930 VPBasicBlock *ClampedVFCheck =
4931 Plan.createVPBasicBlock("vector.clamped.vf.check");
4932
4933 VPValue *ClampedVF = materializeAliasMask(Plan, ClampedVFCheck, DiffChecks);
4934 VPBuilder Builder(ClampedVFCheck);
4936 Type *TCTy = Plan.getTripCount()->getScalarType();
4937
4938 // Check the "ClampedVF" from the alias mask is larger than one.
4939 VPValue *IsScalar =
4940 Builder.createICmp(CmpInst::ICMP_ULE, ClampedVF,
4941 Plan.getConstantInt(TCTy, 1), DL, "vf.is.scalar");
4942
4943 VPValue *TripCount = Plan.getTripCount();
4944 VPValue *MaxUIntTripCount =
4946 VPValue *DistanceToMax = Builder.createSub(MaxUIntTripCount, TripCount);
4947
4948 // For tail-folding: Don't execute the vector loop if (UMax - n) < ClampedVF.
4949 // Note: The ClampedVF may not be a power-of-two. This means the loop exit
4950 // condition (index.next == n.vec) may not be correct in the case of an
4951 // overflow. The issue is `n.vec` could be zero due to an overflow, but
4952 // index.next is not guaranteed to overflow to zero as the ClampedVF is not a
4953 // power-of-two).
4954 VPValue *TripCountCheck = Builder.createICmp(
4955 ICmpInst::ICMP_ULT, DistanceToMax, ClampedVF, DL, "vf.step.overflow");
4956
4957 VPValue *Cond = Builder.createOr(IsScalar, TripCountCheck, DL);
4958 attachVPCheckBlock(Plan, Cond, ClampedVFCheck, HasBranchWeights);
4959
4960 // Materialize the trip count early as this will add a use of (VFxUF) that
4961 // needs to be replaced with the ClampedVF.
4963 /*TailByMasking=*/true,
4964 /*RequiresScalarEpilogue=*/false,
4965 &Plan.getVFxUF());
4966
4967 assert(Plan.getConcreteUF() == 1 &&
4968 "Clamped VF not supported with interleaving");
4969 Plan.getVF().replaceAllUsesWith(ClampedVF);
4970 Plan.getVFxUF().replaceAllUsesWith(ClampedVF);
4971}
4972
4974 ScalarEvolution &SE) {
4975 auto *Entry = Plan.getEntry();
4976 VPBuilder Builder(Entry, Entry->begin());
4978 ->getIRBasicBlock()
4979 ->getTerminator()
4980 ->getDebugLoc();
4981 VPSCEVExpander Expander(Builder, SE, DL);
4982
4983 // Expand VPExpandSCEVRecipes to VPInstructions using VPSCEVExpander. During
4984 // the transition, unsupported VPExpandSCEVRecipes are skipped and left for
4985 // late expansion.
4986 for (VPRecipeBase &R : make_early_inc_range(*Entry)) {
4987 auto *ExpSCEV = dyn_cast<VPExpandSCEVRecipe>(&R);
4988 if (!ExpSCEV || ExpSCEV->user_empty())
4989 continue;
4990 Builder.setInsertPoint(ExpSCEV);
4991 VPValue *Expanded = Expander.tryToExpand(ExpSCEV->getSCEV());
4992 if (!Expanded)
4993 continue;
4994 ExpSCEV->replaceAllUsesWith(Expanded);
4995 // TripCount should not be used after expansion to VPInstructions. Reset to
4996 // poison to avoid dangling references.
4997 if (Plan.getTripCount() == ExpSCEV)
4998 Plan.resetTripCount(Plan.getPoison(ExpSCEV->getScalarType()));
4999 ExpSCEV->eraseFromParent();
5000 }
5001}
5002
5005 SCEVExpander Expander(SE, "induction", /*PreserveLCSSA=*/false);
5006
5007 auto *Entry = cast<VPIRBasicBlock>(Plan.getEntry());
5008 BasicBlock *EntryBB = Entry->getIRBasicBlock();
5009 DenseMap<const SCEV *, Value *> ExpandedSCEVs;
5010 // Expand remaining VPExpandSCEVRecipes to IR instructions using SCEVExpander.
5011 for (VPRecipeBase &R : make_early_inc_range(*Entry)) {
5012 auto *ExpSCEV = dyn_cast<VPExpandSCEVRecipe>(&R);
5013 if (!ExpSCEV)
5014 continue;
5015 const SCEV *Expr = ExpSCEV->getSCEV();
5016 Value *Res =
5017 Expander.expandCodeFor(Expr, Expr->getType(), EntryBB->getTerminator());
5018 ExpandedSCEVs[Expr] = Res;
5019 VPValue *Exp = Plan.getOrAddLiveIn(Res);
5020 ExpSCEV->replaceAllUsesWith(Exp);
5021 if (Plan.getTripCount() == ExpSCEV)
5022 Plan.resetTripCount(Exp);
5023 ExpSCEV->eraseFromParent();
5024 }
5026 "all VPExpandSCEVRecipes must have been expanded");
5027 // Add IR instructions in the entry basic block but not in the VPIRBasicBlock
5028 // to the VPIRBasicBlock.
5029 auto EI = Entry->begin();
5030 for (Instruction &I : drop_end(*EntryBB)) {
5031 if (EI != Entry->end() && isa<VPIRInstruction>(*EI) &&
5032 &cast<VPIRInstruction>(&*EI)->getInstruction() == &I) {
5033 EI++;
5034 continue;
5035 }
5037 }
5038
5039 return ExpandedSCEVs;
5040}
5041
5042/// Returns true if \p V is VPWidenLoadRecipe or VPInterleaveRecipe that can be
5043/// converted to a narrower recipe. \p V is used by a wide recipe that feeds a
5044/// store interleave group at index \p Idx, \p WideMember0 is the recipe feeding
5045/// the same interleave group at index 0. A VPWidenLoadRecipe can be narrowed to
5046/// an index-independent load if it feeds all wide ops at all indices (\p OpV
5047/// must be the operand at index \p OpIdx for both the recipe at lane 0, \p
5048/// WideMember0). A VPInterleaveRecipe can be narrowed to a wide load, if \p V
5049/// is defined at \p Idx of a load interleave group.
5050/// A live-in or recipe defined outside the loop region can be converted, if it
5051/// is the same across all lanes, or we can create a BuildVector for it.
5052static bool canNarrowLoad(VPSingleDefRecipe *WideMember0, unsigned OpIdx,
5053 VPValue *OpV, unsigned Idx, bool IsScalable) {
5054 VPValue *Member0Op = WideMember0->getOperand(OpIdx);
5055 if (Member0Op->isDefinedOutsideLoopRegions()) {
5056 // Operand matches Member0, broadcast across all fields for both live-ins
5057 // and recipes.
5058 if (Member0Op == OpV)
5059 return true;
5060 // Otherwise distinct per-field VPValues are assembled into a BuildVector.
5061 return !IsScalable && OpV->isDefinedOutsideLoopRegions() &&
5062 OpV->getScalarType() == Member0Op->getScalarType();
5063 }
5064 VPRecipeBase *Member0OpR = Member0Op->getDefiningRecipe();
5065 if (auto *W = dyn_cast<VPWidenLoadRecipe>(Member0OpR))
5066 // For scalable VFs, the narrowed plan processes vscale iterations at once,
5067 // so a shared wide load cannot be narrowed to a uniform scalar; bail out.
5068 return !IsScalable && !W->getMask() && W->isConsecutive() &&
5069 Member0Op == OpV;
5070 if (auto *IR = dyn_cast<VPInterleaveRecipe>(Member0OpR))
5071 return IR->getInterleaveGroup()->isFull() && IR->getVPValue(Idx) == OpV;
5072 return false;
5073}
5074
5075static bool canNarrowOps(ArrayRef<VPValue *> Ops, bool IsScalable) {
5077 auto *WideMember0 = dyn_cast<VPRecipeWithIRFlags>(Ops[0]);
5078 if (!WideMember0)
5079 return false;
5080 for (VPValue *V : Ops) {
5082 return false;
5083 auto *R = cast<VPRecipeWithIRFlags>(V);
5084 if (vputils::getOpcode(R) != vputils::getOpcode(WideMember0))
5085 return false;
5086 if (R->getScalarType() != WideMember0->getScalarType())
5087 return false;
5088 if (R->hasPredicate() && R->getPredicate() != WideMember0->getPredicate())
5089 return false;
5090 }
5091
5092 for (unsigned Idx = 0; Idx != WideMember0->getNumOperands(); ++Idx) {
5094 for (VPValue *Op : Ops)
5095 OpsI.push_back(Op->getDefiningRecipe()->getOperand(Idx));
5096
5097 if (canNarrowOps(OpsI, IsScalable))
5098 continue;
5099
5100 if (any_of(enumerate(OpsI), [WideMember0, Idx, IsScalable](const auto &P) {
5101 const auto &[OpIdx, OpV] = P;
5102 return !canNarrowLoad(WideMember0, Idx, OpV, OpIdx, IsScalable);
5103 }))
5104 return false;
5105 }
5106
5107 return true;
5108}
5109
5110/// Returns VF from \p VFs if \p IR is a full interleave group with factor and
5111/// number of members both equal to VF. The interleave group must also access
5112/// the full vector width.
5113static std::optional<ElementCount>
5116 const TargetTransformInfo &TTI) {
5117 if (!InterleaveR || InterleaveR->getMask())
5118 return std::nullopt;
5119
5120 Type *GroupElementTy = nullptr;
5121 if (InterleaveR->getStoredValues().empty()) {
5122 GroupElementTy = InterleaveR->getVPValue(0)->getScalarType();
5123 if (!all_of(InterleaveR->definedValues(), [GroupElementTy](VPValue *Op) {
5124 return Op->getScalarType() == GroupElementTy;
5125 }))
5126 return std::nullopt;
5127 } else {
5128 GroupElementTy = InterleaveR->getStoredValues()[0]->getScalarType();
5129 if (!all_of(InterleaveR->getStoredValues(), [GroupElementTy](VPValue *Op) {
5130 return Op->getScalarType() == GroupElementTy;
5131 }))
5132 return std::nullopt;
5133 }
5134
5135 auto IG = InterleaveR->getInterleaveGroup();
5136 if (IG->getFactor() != IG->getNumMembers())
5137 return std::nullopt;
5138
5139 auto GetVectorBitWidthForVF = [&TTI](ElementCount VF) {
5140 TypeSize Size = TTI.getRegisterBitWidth(
5143 assert(Size.isScalable() == VF.isScalable() &&
5144 "if Size is scalable, VF must be scalable and vice versa");
5145 return Size.getKnownMinValue();
5146 };
5147
5148 for (ElementCount VF : VFs) {
5149 unsigned MinVal = VF.getKnownMinValue();
5150 unsigned GroupSize = GroupElementTy->getScalarSizeInBits() * MinVal;
5151 if (IG->getFactor() == MinVal && GroupSize == GetVectorBitWidthForVF(VF))
5152 return {VF};
5153 }
5154 return std::nullopt;
5155}
5156
5157/// Returns true if \p VPValue is a narrow VPValue.
5158static bool isAlreadyNarrow(VPValue *VPV) {
5159 if (isa<VPIRValue>(VPV))
5160 return true;
5161 auto *RepR = dyn_cast<VPReplicateRecipe>(VPV);
5162 return RepR && RepR->isSingleScalar();
5163}
5164
5165// Convert the wide recipes defining the VPValues in \p Members feeding an
5166// interleave group to a single narrow variant. The first member is reused as
5167// the narrowed recipe. BuildVectors for live-in operands are inserted into \p
5168// Preheader.
5170 SmallPtrSetImpl<VPValue *> &NarrowedOps,
5171 VPBasicBlock *Preheader) {
5172 VPValue *V = Members.front();
5173 if (NarrowedOps.contains(V))
5174 return V;
5175
5176 if (V->isDefinedOutsideLoopRegions()) {
5177 assert(all_of(Members,
5178 [V](VPValue *M) {
5179 return M->isDefinedOutsideLoopRegions() &&
5180 M->getScalarType() == V->getScalarType();
5181 }) &&
5182 "expected distinct loop-invariant values of matching scalar type");
5183 auto *BV = new VPInstruction(VPInstruction::BuildVector, Members);
5184 Preheader->appendRecipe(BV);
5185 NarrowedOps.insert(BV);
5186 return BV;
5187 }
5188
5189 if (isAlreadyNarrow(V))
5190 return V;
5191
5192 VPRecipeBase *R = V->getDefiningRecipe();
5194 auto *WideMember0 = cast<VPRecipeWithIRFlags>(R);
5195 for (VPValue *Member : Members.drop_front())
5196 WideMember0->intersectFlags(*cast<VPRecipeWithIRFlags>(Member));
5197 for (unsigned Idx = 0, E = WideMember0->getNumOperands(); Idx != E; ++Idx) {
5199 for (VPValue *Member : Members)
5200 OpsI.push_back(Member->getDefiningRecipe()->getOperand(Idx));
5201 WideMember0->setOperand(
5202 Idx, narrowInterleaveGroupOp(OpsI, NarrowedOps, Preheader));
5203 }
5204 return V;
5205 }
5206
5207 if (auto *LoadGroup = dyn_cast<VPInterleaveRecipe>(R)) {
5208 // Narrow interleave group to wide load, as transformed VPlan will only
5209 // process one original iteration.
5210 auto *LI = cast<LoadInst>(LoadGroup->getInterleaveGroup()->getInsertPos());
5211 auto *L = new VPWidenLoadRecipe(*LI, LoadGroup->getAddr(),
5212 LoadGroup->getMask(), /*Consecutive=*/true,
5213 *LoadGroup, LoadGroup->getDebugLoc());
5214 L->insertBefore(LoadGroup);
5215 NarrowedOps.insert(L);
5216 return L;
5217 }
5218
5219 if (auto *RepR = dyn_cast<VPReplicateRecipe>(R)) {
5220 assert(RepR->isSingleScalar() && RepR->getOpcode() == Instruction::Load &&
5221 "must be a single scalar load");
5222 NarrowedOps.insert(RepR);
5223 return RepR;
5224 }
5225
5226 auto *WideLoad = cast<VPWidenLoadRecipe>(R);
5227 VPValue *PtrOp = WideLoad->getAddr();
5228 if (auto *VecPtr = dyn_cast<VPVectorPointerRecipe>(PtrOp))
5229 PtrOp = VecPtr->getOperand(0);
5230 // Narrow wide load to uniform scalar load, as transformed VPlan will only
5231 // process one original iteration.
5232 auto *N = new VPReplicateRecipe(&WideLoad->getIngredient(), {PtrOp},
5233 /*IsUniform*/ true,
5234 /*Mask*/ nullptr, {}, *WideLoad);
5235 N->insertBefore(WideLoad);
5236 NarrowedOps.insert(N);
5237 return N;
5238}
5239
5240std::unique_ptr<VPlan>
5242 const TargetTransformInfo &TTI) {
5243 VPRegionBlock *VectorLoop = Plan.getVectorLoopRegion();
5244
5245 if (!VectorLoop)
5246 return nullptr;
5247
5248 // Only handle single-block loops for now.
5249 if (VectorLoop->getEntryBasicBlock() != VectorLoop->getExitingBasicBlock())
5250 return nullptr;
5251
5252 // Skip plans when we may not be able to properly narrow.
5253 VPBasicBlock *Exiting = VectorLoop->getExitingBasicBlock();
5254 if (!match(&Exiting->back(), m_BranchOnCount()))
5255 return nullptr;
5256
5257 assert(match(&Exiting->back(),
5259 m_Specific(&Plan.getVectorTripCount()))) &&
5260 "unexpected branch-on-count");
5261
5263 std::optional<ElementCount> VFToOptimize;
5264 for (auto &R : *VectorLoop->getEntryBasicBlock()) {
5267 continue;
5268
5269 // Bail out on recipes not supported at the moment:
5270 // * phi recipes other than the canonical induction
5271 // * recipes writing to memory except interleave groups
5272 // Only support plans with a canonical induction phi.
5273 if (R.isPhi())
5274 return nullptr;
5275
5276 auto *InterleaveR = dyn_cast<VPInterleaveRecipe>(&R);
5277 if (R.mayWriteToMemory() && !InterleaveR)
5278 return nullptr;
5279
5280 // Bail out if any recipe defines a vector value used outside the
5281 // vector loop region.
5282 if (any_of(R.definedValues(), [&](VPValue *V) {
5283 return any_of(V->users(), [&](VPUser *U) {
5284 auto *UR = cast<VPRecipeBase>(U);
5285 return UR->getParent()->getParent() != VectorLoop;
5286 });
5287 }))
5288 return nullptr;
5289
5290 // All other ops are allowed, but we reject uses that cannot be converted
5291 // when checking all allowed consumers (store interleave groups) below.
5292 if (!InterleaveR)
5293 continue;
5294
5295 // Try to find a single VF, where all interleave groups are consecutive and
5296 // saturate the full vector width. If we already have a candidate VF, check
5297 // if it is applicable for the current InterleaveR, otherwise look for a
5298 // suitable VF across the Plan's VFs.
5300 VFToOptimize ? SmallVector<ElementCount>({*VFToOptimize})
5301 : to_vector(Plan.vectorFactors());
5302 std::optional<ElementCount> NarrowedVF =
5303 isConsecutiveInterleaveGroup(InterleaveR, VFs, TTI);
5304 if (!NarrowedVF || (VFToOptimize && NarrowedVF != VFToOptimize))
5305 return nullptr;
5306 VFToOptimize = NarrowedVF;
5307
5308 // Skip read interleave groups.
5309 if (InterleaveR->getStoredValues().empty())
5310 continue;
5311
5312 // Narrow interleave groups, if all operands are already matching narrow
5313 // ops.
5314 auto *Member0 = InterleaveR->getStoredValues()[0];
5315 if (isAlreadyNarrow(Member0) &&
5316 all_of(InterleaveR->getStoredValues(), equal_to(Member0))) {
5317 StoreGroups.push_back(InterleaveR);
5318 continue;
5319 }
5320
5321 // For now, we only support full interleave groups storing load interleave
5322 // groups.
5323 if (all_of(enumerate(InterleaveR->getStoredValues()), [](auto Op) {
5324 VPRecipeBase *DefR = Op.value()->getDefiningRecipe();
5325 if (!DefR)
5326 return false;
5327 auto *IR = dyn_cast<VPInterleaveRecipe>(DefR);
5328 return IR && IR->getInterleaveGroup()->isFull() &&
5329 IR->getVPValue(Op.index()) == Op.value();
5330 })) {
5331 StoreGroups.push_back(InterleaveR);
5332 continue;
5333 }
5334
5335 // Check if all values feeding InterleaveR are matching wide recipes, which
5336 // operands that can be narrowed.
5337 if (!canNarrowOps(InterleaveR->getStoredValues(),
5338 VFToOptimize->isScalable()))
5339 return nullptr;
5340 StoreGroups.push_back(InterleaveR);
5341 }
5342
5343 if (StoreGroups.empty())
5344 return nullptr;
5345
5346 VPBasicBlock *MiddleVPBB = Plan.getMiddleBlock();
5347 bool RequiresScalarEpilogue =
5348 MiddleVPBB->getNumSuccessors() == 1 &&
5349 MiddleVPBB->getSingleSuccessor() == Plan.getScalarPreheader();
5350 // Bail out for tail-folding (middle block with a single successor to exit).
5351 if (MiddleVPBB->getNumSuccessors() != 2 && !RequiresScalarEpilogue)
5352 return nullptr;
5353
5354 // All interleave groups in Plan can be narrowed for VFToOptimize. Split the
5355 // original Plan into 2: a) a new clone which contains all VFs of Plan, except
5356 // VFToOptimize, and b) the original Plan with VFToOptimize as single VF.
5357 // TODO: Handle cases where only some interleave groups can be narrowed.
5358 std::unique_ptr<VPlan> NewPlan;
5359 if (size(Plan.vectorFactors()) != 1) {
5360 NewPlan = std::unique_ptr<VPlan>(Plan.duplicate());
5361 Plan.setVF(*VFToOptimize);
5362 NewPlan->removeVF(*VFToOptimize);
5363 }
5364
5365 // Convert InterleaveGroup \p R to a single VPWidenLoadRecipe.
5366 SmallPtrSet<VPValue *, 4> NarrowedOps;
5367 VPBasicBlock *Preheader = Plan.getVectorPreheader();
5368 // Narrow operation tree rooted at store groups.
5369 for (auto *StoreGroup : StoreGroups) {
5370 VPValue *Res = narrowInterleaveGroupOp(StoreGroup->getStoredValues(),
5371 NarrowedOps, Preheader);
5372 auto *SI =
5373 cast<StoreInst>(StoreGroup->getInterleaveGroup()->getInsertPos());
5374 auto *S = new VPWidenStoreRecipe(*SI, StoreGroup->getAddr(), Res, nullptr,
5375 /*Consecutive=*/true, *StoreGroup,
5376 StoreGroup->getDebugLoc());
5377 S->insertBefore(StoreGroup);
5378 StoreGroup->eraseFromParent();
5379 }
5380
5381 // Adjust induction to reflect that the transformed plan only processes one
5382 // original iteration.
5384 Type *CanIVTy = VectorLoop->getCanonicalIVType();
5385 VPBasicBlock *VectorPH = Plan.getVectorPreheader();
5386 VPBuilder PHBuilder(VectorPH, VectorPH->begin());
5387
5388 VPValue *UF = &Plan.getUF();
5389 VPValue *Step;
5390 if (VFToOptimize->isScalable()) {
5391 VPValue *VScale =
5392 PHBuilder.createElementCount(CanIVTy, ElementCount::getScalable(1));
5393 Step = PHBuilder.createOverflowingOp(Instruction::Mul, {VScale, UF},
5394 {true, false});
5395 Plan.getVF().replaceAllUsesWith(VScale);
5396 } else {
5397 Step = UF;
5398 Plan.getVF().replaceAllUsesWith(Plan.getConstantInt(CanIVTy, 1));
5399 }
5400 // Materialize vector trip count with the narrowed step.
5401 materializeVectorTripCount(Plan, VectorPH, /*TailByMasking=*/false,
5402 RequiresScalarEpilogue, Step);
5403
5404 CanIVInc->setOperand(1, Step);
5405 Plan.getVFxUF().replaceAllUsesWith(Step);
5406
5407 removeDeadRecipes(Plan);
5408 assert(none_of(*VectorLoop->getEntryBasicBlock(),
5410 "All VPVectorPointerRecipes should have been removed");
5411 return NewPlan;
5412}
5413
5414/// Add branch weight metadata, if the \p Plan's middle block is terminated by a
5415/// BranchOnCond recipe.
5417 VPlan &Plan, ElementCount VF, std::optional<unsigned> VScaleForTuning) {
5418 VPBasicBlock *MiddleVPBB = Plan.getMiddleBlock();
5419 auto *MiddleTerm =
5421 // Only add branch metadata if there is a (conditional) terminator.
5422 if (!MiddleTerm)
5423 return;
5424
5425 assert(MiddleTerm->getOpcode() == VPInstruction::BranchOnCond &&
5426 "must have a BranchOnCond");
5427 // Assume that `TripCount % VectorStep ` is equally distributed.
5428 unsigned VectorStep = Plan.getConcreteUF() * VF.getKnownMinValue();
5429 if (VF.isScalable() && VScaleForTuning.has_value())
5430 VectorStep *= *VScaleForTuning;
5431 assert(VectorStep > 0 && "trip count should not be zero");
5432 MDBuilder MDB(Plan.getContext());
5433 MDNode *BranchWeights =
5434 MDB.createBranchWeights({1, VectorStep - 1}, /*IsExpected=*/false);
5435 MiddleTerm->setMetadata(LLVMContext::MD_prof, BranchWeights);
5436}
5437
5439 VFRange &Range) {
5440 VPRegionBlock *VectorRegion = Plan.getVectorLoopRegion();
5441 auto *MiddleVPBB = Plan.getMiddleBlock();
5442 VPBuilder MiddleBuilder(MiddleVPBB, MiddleVPBB->getFirstNonPhi());
5443
5444 auto IsScalableOne = [](ElementCount VF) -> bool {
5445 return VF == ElementCount::getScalable(1);
5446 };
5447
5448 for (auto &HeaderPhi : VectorRegion->getEntryBasicBlock()->phis()) {
5449 auto *FOR = dyn_cast<VPFirstOrderRecurrencePHIRecipe>(&HeaderPhi);
5450 if (!FOR)
5451 continue;
5452
5453 assert(VectorRegion->getSingleSuccessor() == Plan.getMiddleBlock() &&
5454 "Cannot handle loops with uncountable early exits");
5455
5456 // Find the existing splice for this FOR, created in
5457 // createHeaderPhiRecipes. All uses of FOR have already been replaced with
5458 // RecurSplice there; only RecurSplice itself still references FOR.
5459 auto *RecurSplice =
5461 assert(RecurSplice && "expected FirstOrderRecurrenceSplice");
5462
5463 // For VF vscale x 1, if vscale = 1, we are unable to extract the
5464 // penultimate value of the recurrence. Instead we rely on the existing
5465 // extract of the last element from the result of
5466 // VPInstruction::FirstOrderRecurrenceSplice.
5467 // TODO: Consider vscale_range info and UF.
5468 if (any_of(RecurSplice->users(),
5469 [](VPUser *U) { return !cast<VPRecipeBase>(U)->getRegion(); }) &&
5471 Range))
5472 return;
5473
5474 // This is the second phase of vectorizing first-order recurrences, creating
5475 // extracts for users outside the loop. An overview of the transformation is
5476 // described below. Suppose we have the following loop with some use after
5477 // the loop of the last a[i-1],
5478 //
5479 // for (int i = 0; i < n; ++i) {
5480 // t = a[i - 1];
5481 // b[i] = a[i] - t;
5482 // }
5483 // use t;
5484 //
5485 // There is a first-order recurrence on "a". For this loop, the shorthand
5486 // scalar IR looks like:
5487 //
5488 // scalar.ph:
5489 // s.init = a[-1]
5490 // br scalar.body
5491 //
5492 // scalar.body:
5493 // i = phi [0, scalar.ph], [i+1, scalar.body]
5494 // s1 = phi [s.init, scalar.ph], [s2, scalar.body]
5495 // s2 = a[i]
5496 // b[i] = s2 - s1
5497 // br cond, scalar.body, exit.block
5498 //
5499 // exit.block:
5500 // use = lcssa.phi [s1, scalar.body]
5501 //
5502 // In this example, s1 is a recurrence because it's value depends on the
5503 // previous iteration. In the first phase of vectorization, we created a
5504 // VPFirstOrderRecurrencePHIRecipe v1 for s1. Now we create the extracts
5505 // for users in the scalar preheader and exit block.
5506 //
5507 // vector.ph:
5508 // v_init = vector(..., ..., ..., a[-1])
5509 // br vector.body
5510 //
5511 // vector.body
5512 // i = phi [0, vector.ph], [i+4, vector.body]
5513 // v1 = phi [v_init, vector.ph], [v2, vector.body]
5514 // v2 = a[i, i+1, i+2, i+3]
5515 // v1' = splice(v1(3), v2(0, 1, 2))
5516 // b[i, i+1, i+2, i+3] = v2 - v1'
5517 // br cond, vector.body, middle.block
5518 //
5519 // middle.block:
5520 // vector.recur.extract.for.phi = v2(2)
5521 // vector.recur.extract = v2(3)
5522 // br cond, scalar.ph, exit.block
5523 //
5524 // scalar.ph:
5525 // scalar.recur.init = phi [vector.recur.extract, middle.block],
5526 // [s.init, otherwise]
5527 // br scalar.body
5528 //
5529 // scalar.body:
5530 // i = phi [0, scalar.ph], [i+1, scalar.body]
5531 // s1 = phi [scalar.recur.init, scalar.ph], [s2, scalar.body]
5532 // s2 = a[i]
5533 // b[i] = s2 - s1
5534 // br cond, scalar.body, exit.block
5535 //
5536 // exit.block:
5537 // lo = lcssa.phi [s1, scalar.body],
5538 // [vector.recur.extract.for.phi, middle.block]
5539 //
5540 // Update extracts of the splice in the middle block: they extract the
5541 // penultimate element of the recurrence.
5543 make_range(MiddleVPBB->getFirstNonPhi(), MiddleVPBB->end()))) {
5544 if (!match(&R, m_ExtractLastLaneOfLastPart(m_Specific(RecurSplice))))
5545 continue;
5546
5547 auto *ExtractR = cast<VPInstruction>(&R);
5548 VPValue *PenultimateElement = MiddleBuilder.createNaryOp(
5549 VPInstruction::ExtractPenultimateElement, RecurSplice->getOperand(1),
5550 {}, "vector.recur.extract.for.phi");
5551 for (VPUser *ExitU : to_vector(ExtractR->users())) {
5552 if (auto *ExitPhi = dyn_cast<VPIRPhi>(ExitU))
5553 ExitPhi->replaceUsesOfWith(ExtractR, PenultimateElement);
5554 }
5555 }
5556 }
5557}
5558
5559/// Check if \p V is a binary expression of a widened IV and a loop-invariant
5560/// value. Returns the widened IV if found, nullptr otherwise.
5562 auto *BinOp = dyn_cast<VPWidenRecipe>(V);
5563 if (!BinOp || !Instruction::isBinaryOp(BinOp->getOpcode()) ||
5564 Instruction::isIntDivRem(BinOp->getOpcode()))
5565 return nullptr;
5566
5567 VPValue *WidenIVCandidate = BinOp->getOperand(0);
5568 VPValue *InvariantCandidate = BinOp->getOperand(1);
5569 if (!isa<VPWidenIntOrFpInductionRecipe>(WidenIVCandidate))
5570 std::swap(WidenIVCandidate, InvariantCandidate);
5571
5572 if (!InvariantCandidate->isDefinedOutsideLoopRegions())
5573 return nullptr;
5574
5575 return dyn_cast<VPWidenIntOrFpInductionRecipe>(WidenIVCandidate);
5576}
5577
5578/// Create a scalar version of \p BinOp, with its \p WidenIV operand replaced
5579/// by \p ScalarIV, and place it after \p ScalarIV's defining recipe.
5583 BinOp->getNumOperands() == 2 && "BinOp must have 2 operands");
5584 auto *ClonedOp = BinOp->clone();
5585 if (ClonedOp->getOperand(0) == WidenIV) {
5586 ClonedOp->setOperand(0, ScalarIV);
5587 } else {
5588 assert(ClonedOp->getOperand(1) == WidenIV && "one operand must be WideIV");
5589 ClonedOp->setOperand(1, ScalarIV);
5590 }
5591 ClonedOp->insertAfter(ScalarIV->getDefiningRecipe());
5592 return ClonedOp;
5593}
5594
5597 Loop &L) {
5598 ScalarEvolution &SE = *PSE.getSE();
5599 VPRegionBlock *VectorLoopRegion = Plan.getVectorLoopRegion();
5600
5601 // Helper lambda to check if the IV range excludes the sentinel value. Try
5602 // signed first, then unsigned. Return an excluded sentinel if found,
5603 // otherwise return std::nullopt.
5604 auto CheckSentinel = [&SE](const SCEV *IVSCEV,
5605 bool UseMax) -> std::optional<APSInt> {
5606 unsigned BW = IVSCEV->getType()->getScalarSizeInBits();
5607 for (bool Signed : {true, false}) {
5608 APSInt Sentinel = UseMax ? APSInt::getMinValue(BW, /*Unsigned=*/!Signed)
5609 : APSInt::getMaxValue(BW, /*Unsigned=*/!Signed);
5610
5611 ConstantRange IVRange =
5612 Signed ? SE.getSignedRange(IVSCEV) : SE.getUnsignedRange(IVSCEV);
5613 if (!IVRange.contains(Sentinel))
5614 return Sentinel;
5615 }
5616 return std::nullopt;
5617 };
5618
5619 VPValue *HeaderMask = VectorLoopRegion->getHeaderMask();
5620 for (VPRecipeBase &Phi :
5621 make_early_inc_range(VectorLoopRegion->getEntryBasicBlock()->phis())) {
5622 auto *PhiR = dyn_cast<VPReductionPHIRecipe>(&Phi);
5624 PhiR->getRecurrenceKind()))
5625 continue;
5626
5627 Type *PhiTy = PhiR->getScalarType();
5628 if (PhiTy->isPointerTy() || PhiTy->isFloatingPointTy())
5629 continue;
5630
5631 // If there's a header mask, the backedge select will not be the find-last
5632 // select.
5633 VPValue *BackedgeVal = PhiR->getBackedgeValue();
5634 auto *FindLastSelect = cast<VPSingleDefRecipe>(BackedgeVal);
5635 if (HeaderMask &&
5636 !match(BackedgeVal,
5637 m_Select(m_Specific(HeaderMask),
5638 m_VPSingleDefRecipe(FindLastSelect), m_Specific(PhiR))))
5639 continue;
5640
5641 // Get the find-last expression from the find-last select of the reduction
5642 // phi. The find-last select should be a select between the phi and the
5643 // find-last expression.
5644 VPValue *Cond, *FindLastExpression;
5645 if (!match(FindLastSelect, m_SelectLike(m_VPValue(Cond), m_Specific(PhiR),
5646 m_VPValue(FindLastExpression))) &&
5647 !match(FindLastSelect,
5648 m_SelectLike(m_VPValue(Cond), m_VPValue(FindLastExpression),
5649 m_Specific(PhiR))))
5650 continue;
5651
5652 // Check if FindLastExpression is a simple expression of a widened IV. If
5653 // so, we can track the underlying IV instead and sink the expression.
5654 auto *IVOfExpressionToSink = getExpressionIV(FindLastExpression);
5655 const SCEV *IVSCEV = vputils::getSCEVExprForVPValue(
5656 IVOfExpressionToSink ? IVOfExpressionToSink : FindLastExpression, PSE,
5657 &L);
5658 const SCEV *Step;
5659 if (!match(IVSCEV, m_scev_AffineAddRec(m_SCEV(), m_SCEV(Step)))) {
5660 assert(!match(vputils::getSCEVExprForVPValue(FindLastExpression, PSE, &L),
5662 "IVOfExpressionToSink not being an AddRec must imply "
5663 "FindLastExpression not being an AddRec.");
5664 continue;
5665 }
5666
5667 // Determine direction from SCEV step.
5668 if (!SE.isKnownNonZero(Step))
5669 continue;
5670
5671 // Positive step means we need UMax/SMax to find the last IV value, and
5672 // UMin/SMin otherwise.
5673 bool UseMax = SE.isKnownPositive(Step);
5674 std::optional<APSInt> SentinelVal = CheckSentinel(IVSCEV, UseMax);
5675 bool UseSigned = SentinelVal && SentinelVal->isSigned();
5676
5677 // Sinking an expression will disable epilogue vectorization. Only use it,
5678 // if FindLastExpression cannot be vectorized via a sentinel. Sinking may
5679 // also prevent vectorizing using a sentinel (e.g., if the expression is a
5680 // multiply or divide by large constant, respectively), which also makes
5681 // sinking undesirable.
5682 if (IVOfExpressionToSink) {
5683 const SCEV *FindLastExpressionSCEV =
5684 vputils::getSCEVExprForVPValue(FindLastExpression, PSE, &L);
5685 if (match(FindLastExpressionSCEV,
5686 m_scev_AffineAddRec(m_SCEV(), m_SCEV(Step)))) {
5687 bool NewUseMax = SE.isKnownPositive(Step);
5688 if (auto NewSentinel =
5689 CheckSentinel(FindLastExpressionSCEV, NewUseMax)) {
5690 // The original expression already has a sentinel, so prefer not
5691 // sinking to keep epilogue vectorization possible.
5692 SentinelVal = *NewSentinel;
5693 UseSigned = NewSentinel->isSigned();
5694 UseMax = NewUseMax;
5695 IVSCEV = FindLastExpressionSCEV;
5696 IVOfExpressionToSink = nullptr;
5697 }
5698 }
5699 }
5700
5701 // If no sentinel was found, fall back to a boolean AnyOf reduction to track
5702 // if the condition was ever true. Requires the IV to not wrap, otherwise we
5703 // cannot use min/max.
5704 if (!SentinelVal) {
5705 auto *AR = cast<SCEVAddRecExpr>(IVSCEV);
5706 if (AR->hasNoSignedWrap())
5707 UseSigned = true;
5708 else if (AR->hasNoUnsignedWrap())
5709 UseSigned = false;
5710 else
5711 continue;
5712 }
5713
5715 BackedgeVal,
5717
5718 VPValue *NewFindLastSelect = BackedgeVal;
5719 VPValue *SelectCond = Cond;
5720 if (!SentinelVal || IVOfExpressionToSink) {
5721 // When we need to create a new select, normalize the condition so that
5722 // PhiR is the last operand and include the header mask if needed.
5723 DebugLoc DL = FindLastSelect->getDefiningRecipe()->getDebugLoc();
5724 VPBuilder LoopBuilder(FindLastSelect->getDefiningRecipe());
5725 if (FindLastSelect->getDefiningRecipe()->getOperand(1) == PhiR)
5726 SelectCond = LoopBuilder.createNot(SelectCond);
5727
5728 // When tail folding, mask the condition with the header mask to prevent
5729 // propagating poison from inactive lanes in the last vector iteration.
5730 if (HeaderMask)
5731 SelectCond = LoopBuilder.createLogicalAnd(HeaderMask, SelectCond);
5732
5733 if (SelectCond != Cond || IVOfExpressionToSink) {
5734 NewFindLastSelect = LoopBuilder.createSelect(
5735 SelectCond,
5736 IVOfExpressionToSink ? IVOfExpressionToSink : FindLastExpression,
5737 PhiR, DL);
5738 }
5739 }
5740
5741 // Create the reduction result in the middle block using sentinel directly.
5742 RecurKind MinMaxKind =
5743 UseMax ? (UseSigned ? RecurKind::SMax : RecurKind::UMax)
5744 : (UseSigned ? RecurKind::SMin : RecurKind::UMin);
5745 VPIRFlags Flags(MinMaxKind, /*IsOrdered=*/false, /*IsInLoop=*/false,
5746 FastMathFlags());
5747 DebugLoc ExitDL = RdxResult->getDebugLoc();
5748 VPBuilder MiddleBuilder(RdxResult);
5749 VPValue *ReducedIV =
5751 NewFindLastSelect, Flags, ExitDL);
5752
5753 // If IVOfExpressionToSink is an expression to sink, sink it now.
5754 VPValue *VectorRegionExitingVal = ReducedIV;
5755 if (IVOfExpressionToSink)
5756 VectorRegionExitingVal =
5757 cloneBinOpForScalarIV(cast<VPWidenRecipe>(FindLastExpression),
5758 ReducedIV, IVOfExpressionToSink);
5759
5760 VPValue *NewRdxResult;
5761 VPValue *StartVPV = PhiR->getStartValue();
5762 if (SentinelVal) {
5763 // Sentinel-based approach: reduce IVs with min/max, compare against
5764 // sentinel to detect if condition was ever true, select accordingly.
5765 VPValue *Sentinel = Plan.getConstantInt(*SentinelVal);
5766 auto *Cmp = MiddleBuilder.createICmp(CmpInst::ICMP_NE, ReducedIV,
5767 Sentinel, ExitDL);
5768 NewRdxResult = MiddleBuilder.createSelect(Cmp, VectorRegionExitingVal,
5769 StartVPV, ExitDL);
5770 StartVPV = Sentinel;
5771 } else {
5772 // Introduce a boolean AnyOf reduction to track if the condition was ever
5773 // true in the loop. Use it to select the initial start value, if it was
5774 // never true.
5775 auto *AnyOfPhi = new VPReductionPHIRecipe(
5776 /*Phi=*/nullptr, RecurKind::Or, *Plan.getFalse(), *Plan.getFalse(),
5777 RdxUnordered{1}, {}, /*HasUsesOutsideReductionChain=*/false);
5778 AnyOfPhi->insertAfter(PhiR);
5779
5780 VPBuilder LoopBuilder(BackedgeVal->getDefiningRecipe());
5781 VPValue *OrVal = LoopBuilder.createOr(AnyOfPhi, SelectCond);
5782 AnyOfPhi->setOperand(1, OrVal);
5783
5784 NewRdxResult = MiddleBuilder.createAnyOfReduction(
5785 OrVal, VectorRegionExitingVal, StartVPV, ExitDL);
5786
5787 // Initialize the IV reduction phi with the neutral element, not the
5788 // original start value, to ensure correct min/max reduction results.
5789 StartVPV = Plan.getOrAddLiveIn(
5790 getRecurrenceIdentity(MinMaxKind, IVSCEV->getType(), {}));
5791 }
5792 RdxResult->replaceAllUsesWith(NewRdxResult);
5793 RdxResult->eraseFromParent();
5794
5795 auto *NewPhiR = new VPReductionPHIRecipe(
5796 cast<PHINode>(PhiR->getUnderlyingInstr()), RecurKind::FindIV, *StartVPV,
5797 *NewFindLastSelect, RdxUnordered{1}, {},
5798 PhiR->hasUsesOutsideReductionChain());
5799 NewPhiR->insertBefore(PhiR);
5800 PhiR->replaceAllUsesWith(NewPhiR);
5801 PhiR->eraseFromParent();
5802 }
5803}
5804
5805namespace {
5806
5807using ExtendKind = TTI::PartialReductionExtendKind;
5808struct ReductionExtend {
5809 Type *SrcType = nullptr;
5810 ExtendKind Kind = ExtendKind::PR_None;
5811};
5812
5813/// Describes the extends used to compute the extended reduction operand.
5814/// ExtendB is optional. If ExtendB is present, ExtendsUser is a binary
5815/// operation.
5816struct ExtendedReductionOperand {
5817 /// The recipe that consumes the extends.
5818 VPWidenRecipe *ExtendsUser = nullptr;
5819 /// Extend descriptions (inputs to getPartialReductionCost).
5820 ReductionExtend ExtendA, ExtendB;
5821};
5822
5823/// A chain of recipes that form a partial reduction. Matches either
5824/// reduction_bin_op (extended op, accumulator), or
5825/// reduction_bin_op (accumulator, extended op).
5826/// The possible forms of the "extended op" are listed in
5827/// matchExtendedReductionOperand.
5828struct VPPartialReductionChain {
5829 /// The top-level binary operation that forms the reduction to a scalar
5830 /// after the loop body.
5831 VPWidenRecipe *ReductionBinOp = nullptr;
5832 /// The user of the extends that is then reduced.
5833 ExtendedReductionOperand ExtendedOp;
5834 /// The recurrence kind for the entire partial reduction chain.
5835 /// This allows distinguishing between Sub and AddWithSub recurrences,
5836 /// when the ReductionBinOp is a Instruction::Sub.
5837 RecurKind RK;
5838 /// The index of the accumulator operand of ReductionBinOp. The extended op
5839 /// is `1 - AccumulatorOpIdx`.
5840 unsigned AccumulatorOpIdx;
5841 unsigned ScaleFactor;
5842 /// Optional blend to represent predication for the block that updates the
5843 /// reduction.
5844 VPBlendRecipe *Blend = nullptr;
5845};
5846
5847// Return the incoming index of the single-use value in the blend, which is
5848// expected to be the predicated reduction update.
5849static std::optional<unsigned>
5850getBlendReductionUpdateValueIdx(VPBlendRecipe *Blend) {
5851 assert(Blend && !Blend->isNormalized() &&
5852 Blend->getNumIncomingValues() == 2 &&
5853 "Expected a non-normalized blend with two incoming values");
5854 bool FirstIncomingHasOneUse = Blend->getIncomingValue(0)->hasOneUse();
5855
5856 // Only the update value should have one use (the blend). The previous
5857 // value should always have at least two uses, the blend and the reduction.
5858 if (FirstIncomingHasOneUse == Blend->getIncomingValue(1)->hasOneUse())
5859 return std::nullopt;
5860 return FirstIncomingHasOneUse ? 0 : 1;
5861}
5862
5863static VPSingleDefRecipe *
5864optimizeExtendsForPartialReduction(VPSingleDefRecipe *Op) {
5865 // reduce.add(mul(ext(A), C))
5866 // -> reduce.add(mul(ext(A), ext(trunc(C))))
5867 const APInt *Const;
5868 if (match(Op, m_Mul(m_ZExtOrSExt(m_VPValue()), m_APInt(Const)))) {
5869 auto *ExtA = cast<VPWidenCastRecipe>(Op->getOperand(0));
5870 Instruction::CastOps ExtOpc = ExtA->getOpcode();
5871 Type *NarrowTy = ExtA->getOperand(0)->getScalarType();
5872 if (!Op->hasOneUse() ||
5874 Const, NarrowTy, TTI::getPartialReductionExtendKind(ExtOpc)))
5875 return Op;
5876
5877 VPBuilder Builder(Op);
5878 auto *Trunc = Builder.createWidenCast(Instruction::CastOps::Trunc,
5879 Op->getOperand(1), NarrowTy);
5880 Type *WideTy = ExtA->getScalarType();
5881 Op->setOperand(1, Builder.createWidenCast(ExtOpc, Trunc, WideTy));
5882 return Op;
5883 }
5884
5885 // reduce.add(abs(sub(ext(A), ext(B))))
5886 // -> reduce.add(ext(absolute-difference(A, B)))
5887 VPValue *X, *Y;
5890 auto *Sub = Op->getOperand(0)->getDefiningRecipe();
5891 auto *Ext = cast<VPWidenCastRecipe>(Sub->getOperand(0));
5892 assert(Ext->getOpcode() ==
5893 cast<VPWidenCastRecipe>(Sub->getOperand(1))->getOpcode() &&
5894 "Expected both the LHS and RHS extends to be the same");
5895 bool IsSigned = Ext->getOpcode() == Instruction::SExt;
5896 VPBuilder Builder(Op);
5897 Type *SrcTy = X->getScalarType();
5898 auto *FreezeX = Builder.insert(new VPWidenRecipe(Instruction::Freeze, {X}));
5899 auto *FreezeY = Builder.insert(new VPWidenRecipe(Instruction::Freeze, {Y}));
5900 auto *Max = Builder.insert(
5901 new VPWidenIntrinsicRecipe(IsSigned ? Intrinsic::smax : Intrinsic::umax,
5902 {FreezeX, FreezeY}, SrcTy));
5903 auto *Min = Builder.insert(
5904 new VPWidenIntrinsicRecipe(IsSigned ? Intrinsic::smin : Intrinsic::umin,
5905 {FreezeX, FreezeY}, SrcTy));
5906 auto *AbsDiff =
5907 Builder.insert(new VPWidenRecipe(Instruction::Sub, {Max, Min}));
5908 return Builder.createWidenCast(Instruction::CastOps::ZExt, AbsDiff,
5909 Op->getScalarType());
5910 }
5911
5912 // reduce.add(ext(mul(ext(A), ext(B))))
5913 // -> reduce.add(mul(wider_ext(A), wider_ext(B)))
5914 // TODO: Support this optimization for float types.
5916 m_ZExtOrSExt(m_VPValue()))))) {
5917 auto *Ext = cast<VPWidenCastRecipe>(Op);
5918 auto *Mul = cast<VPWidenRecipe>(Ext->getOperand(0));
5919 auto *MulLHS = cast<VPWidenCastRecipe>(Mul->getOperand(0));
5920 auto *MulRHS = cast<VPWidenCastRecipe>(Mul->getOperand(1));
5921 if (!Mul->hasOneUse() ||
5922 (Ext->getOpcode() != MulLHS->getOpcode() && MulLHS != MulRHS) ||
5923 MulLHS->getOpcode() != MulRHS->getOpcode())
5924 return Op;
5925 VPBuilder Builder(Mul);
5926 auto *NewLHS = Builder.createWidenCast(
5927 MulLHS->getOpcode(), MulLHS->getOperand(0), Ext->getScalarType());
5928 auto *NewRHS = MulLHS == MulRHS
5929 ? NewLHS
5930 : Builder.createWidenCast(MulRHS->getOpcode(),
5931 MulRHS->getOperand(0),
5932 Ext->getScalarType());
5933 auto *NewMul = Mul->cloneWithOperands({NewLHS, NewRHS});
5934 Builder.insert(NewMul);
5935 Op->replaceAllUsesWith(NewMul);
5936 Op->eraseFromParent();
5937 Mul->eraseFromParent();
5938 return NewMul;
5939 }
5940
5941 return Op;
5942}
5943
5944static VPExpressionRecipe *
5945createPartialReductionExpression(VPReductionRecipe *Red) {
5946 VPValue *VecOp = Red->getVecOp();
5947
5948 // reduce.[f]add(ext(op))
5949 // -> VPExpressionRecipe(op, red)
5950 if (match(VecOp, m_WidenAnyExtend(m_VPValue())))
5951 return new VPExpressionRecipe(cast<VPWidenCastRecipe>(VecOp), Red);
5952
5953 // reduce.[f]add(neg(ext(op)))
5954 // -> VPExpressionRecipe(op, sub/neg, red)
5955 if (match(VecOp, m_AnyNeg(m_WidenAnyExtend(m_VPValue())))) {
5956 auto *Neg = cast<VPWidenRecipe>(VecOp);
5957 auto *Ext =
5958 cast<VPWidenCastRecipe>(Neg->getOperand(Neg->getNumOperands() - 1));
5959 return new VPExpressionRecipe(Ext, Neg, Red);
5960 }
5961
5962 // reduce.[f]add([f]mul(ext(a), ext(b)))
5963 // -> VPExpressionRecipe(a, b, mul, red)
5964 if (match(VecOp, m_FMul(m_FPExt(m_VPValue()), m_FPExt(m_VPValue()))) ||
5965 match(VecOp,
5967 auto *Mul = cast<VPWidenRecipe>(VecOp);
5968 auto *ExtA = cast<VPWidenCastRecipe>(Mul->getOperand(0));
5969 auto *ExtB = cast<VPWidenCastRecipe>(Mul->getOperand(1));
5970 return new VPExpressionRecipe(ExtA, ExtB, Mul, Red);
5971 }
5972
5973 // reduce.fadd(fneg(fmul(fpext(a), fpext(b))))
5974 // -> VPExpressionRecipe(a, b, fmul, fsub, red)
5975 if (match(VecOp,
5977 auto *FNeg = cast<VPWidenRecipe>(VecOp);
5978 auto *FMul = cast<VPWidenRecipe>(FNeg->getOperand(0));
5979 auto *ExtA = cast<VPWidenCastRecipe>(FMul->getOperand(0));
5980 auto *ExtB = cast<VPWidenCastRecipe>(FMul->getOperand(1));
5981 return new VPExpressionRecipe(ExtA, ExtB, FMul, FNeg, Red);
5982 }
5983
5984 // reduce.add(neg(mul(ext(a), ext(b))))
5985 // -> VPExpressionRecipe(a, b, mul, sub, red)
5987 m_ZExtOrSExt(m_VPValue()))))) {
5988 auto *Sub = cast<VPWidenRecipe>(VecOp);
5989 auto *Mul = cast<VPWidenRecipe>(Sub->getOperand(1));
5990 auto *ExtA = cast<VPWidenCastRecipe>(Mul->getOperand(0));
5991 auto *ExtB = cast<VPWidenCastRecipe>(Mul->getOperand(1));
5992 return new VPExpressionRecipe(ExtA, ExtB, Mul, Sub, Red);
5993 }
5994
5995 llvm_unreachable("Unsupported expression");
5996}
5997
5998// Helper to transform a partial reduction chain into a partial reduction
5999// recipe. Assumes profitability has been checked.
6000static void transformToPartialReduction(const VPPartialReductionChain &Chain,
6001 VPlan &Plan,
6002 VPReductionPHIRecipe *RdxPhi) {
6003 VPWidenRecipe *WidenRecipe = Chain.ReductionBinOp;
6004 assert(WidenRecipe->getNumOperands() == 2 && "Expected binary operation");
6005
6006 VPValue *Accumulator = WidenRecipe->getOperand(Chain.AccumulatorOpIdx);
6007 auto *ExtendedOp = cast<VPSingleDefRecipe>(
6008 WidenRecipe->getOperand(1 - Chain.AccumulatorOpIdx));
6009
6010 // FIXME: Do these transforms before invoking the cost-model.
6011 ExtendedOp = optimizeExtendsForPartialReduction(ExtendedOp);
6012
6013 // Sub-reductions can be implemented in two ways:
6014 // (1) negate the operand in the vector loop (the default way).
6015 // (2) subtract the reduced value from the init value in the middle block.
6016 // Both ways keep the reduction itself as an 'add' reduction.
6017 //
6018 // The ISD nodes for partial reductions don't support folding the
6019 // sub/negation into its operands because the following is not a valid
6020 // transformation:
6021 // sub(0, mul(ext(a), ext(b)))
6022 // -> mul(ext(a), ext(sub(0, b)))
6023 //
6024 // It's therefore better to choose option (2) such that the partial
6025 // reduction is always positive (starting at '0') and to do a final
6026 // subtract in the middle block.
6027 if ((WidenRecipe->getOpcode() == Instruction::Sub &&
6028 Chain.RK != RecurKind::Sub) ||
6029 (WidenRecipe->getOpcode() == Instruction::FSub &&
6030 Chain.RK != RecurKind::FSub)) {
6031 VPBuilder Builder(WidenRecipe);
6032 Type *ElemTy = ExtendedOp->getScalarType();
6033 VPWidenRecipe *NegRecipe;
6034 if (WidenRecipe->getOpcode() == Instruction::FSub) {
6035 NegRecipe =
6036 new VPWidenRecipe(Instruction::FNeg, {ExtendedOp}, VPIRFlags(),
6038 } else {
6039 auto *Zero = Plan.getZero(ElemTy);
6040 NegRecipe =
6041 new VPWidenRecipe(Instruction::Sub, {Zero, ExtendedOp}, VPIRFlags(),
6043 }
6044 Builder.insert(NegRecipe);
6045 ExtendedOp = NegRecipe;
6046 }
6047
6048 // Check if WidenRecipe is the final result of the reduction. If so, look
6049 // through the Select recipe introduced by tail-folding, otherwise look
6050 // through any Blend recipe introduced by predication for the block.
6051 VPValue *ExitSearch =
6052 Chain.Blend ? cast<VPValue>(Chain.Blend) : cast<VPValue>(WidenRecipe);
6053
6054 VPValue *Cond = nullptr;
6056 findUserOf(ExitSearch, m_Select(m_VPValue(Cond), m_Specific(ExitSearch),
6057 m_Specific(RdxPhi))));
6058
6059 if (Chain.Blend) {
6060 std::optional<unsigned> BlendReductionIdx =
6061 getBlendReductionUpdateValueIdx(Chain.Blend);
6062 assert(BlendReductionIdx &&
6063 Chain.Blend->getIncomingValue(*BlendReductionIdx) == WidenRecipe &&
6064 "Expected blend to contain the reduction update");
6065 VPValue *BlendCond = Chain.Blend->getMask(*BlendReductionIdx);
6066 Cond = ExitValue ? VPBuilder(WidenRecipe)
6067 .createLogicalAnd(Cond, BlendCond,
6068 WidenRecipe->getDebugLoc())
6069 : BlendCond;
6070 }
6071
6072 bool IsLastInChain = RdxPhi->getBackedgeValue() == WidenRecipe ||
6073 RdxPhi->getBackedgeValue() == ExitValue ||
6074 RdxPhi->getBackedgeValue() == Chain.Blend;
6075 assert((!ExitValue || IsLastInChain) &&
6076 "if we found ExitValue, it must match RdxPhi's backedge value");
6077
6078 Type *PhiType = RdxPhi->getScalarType();
6079 RecurKind RdxKind =
6081 auto *PartialRed = new VPReductionRecipe(
6082 RdxKind,
6083 RdxKind == RecurKind::FAdd ? WidenRecipe->getFastMathFlagsOrNone()
6084 : FastMathFlags(),
6085 WidenRecipe->getUnderlyingInstr(), Accumulator, ExtendedOp, Cond,
6086 RdxUnordered{/*VFScaleFactor=*/Chain.ScaleFactor});
6087 PartialRed->insertBefore(WidenRecipe);
6088
6089 if (ExitValue)
6090 ExitValue->replaceAllUsesWith(PartialRed);
6091 if (Chain.Blend)
6092 Chain.Blend->replaceAllUsesWith(PartialRed);
6093 WidenRecipe->replaceAllUsesWith(PartialRed);
6094
6095 // For cost-model purposes, fold this into a VPExpression.
6096 VPExpressionRecipe *E = createPartialReductionExpression(PartialRed);
6097 E->insertBefore(WidenRecipe);
6098 PartialRed->replaceAllUsesWith(E);
6099
6100 // We only need to update the PHI node once, which is when we find the
6101 // last reduction in the chain.
6102 if (!IsLastInChain)
6103 return;
6104
6105 // Scale the PHI and ReductionStartVector by the VFScaleFactor
6106 assert(RdxPhi->getVFScaleFactor() == 1 && "scale factor must not be set");
6107 RdxPhi->setVFScaleFactor(Chain.ScaleFactor);
6108
6109 auto *StartInst = cast<VPInstruction>(RdxPhi->getStartValue());
6110 assert(StartInst->getOpcode() == VPInstruction::ReductionStartVector);
6111 auto *NewScaleFactor = Plan.getConstantInt(32, Chain.ScaleFactor);
6112 StartInst->setOperand(2, NewScaleFactor);
6113
6114 // If this is the last value in a sub-reduction chain, then update the PHI
6115 // node to start at `0` and update the reduction-result to subtract from
6116 // the PHI's start value.
6117 if (Chain.RK != RecurKind::Sub && Chain.RK != RecurKind::FSub)
6118 return;
6119
6120 VPValue *OldStartValue = StartInst->getOperand(0);
6121 StartInst->setOperand(0, StartInst->getOperand(1));
6122
6123 // Replace reduction_result by 'sub (startval, reductionresult)'.
6125 assert(RdxResult && "Could not find reduction result");
6126
6127 VPBuilder Builder = VPBuilder::getToInsertAfter(RdxResult);
6128 unsigned SubOpc = Chain.RK == RecurKind::FSub ? Instruction::BinaryOps::FSub
6129 : Instruction::BinaryOps::Sub;
6130 VPInstruction *NewResult = Builder.createNaryOp(
6131 SubOpc, {OldStartValue, RdxResult}, VPIRFlags::getDefaultFlags(SubOpc),
6132 RdxPhi->getDebugLoc());
6133 RdxResult->replaceUsesWithIf(
6134 NewResult,
6135 [&NewResult](VPUser &U, unsigned Idx) { return &U != NewResult; });
6136}
6137
6138/// Returns the cost of a link in a partial-reduction chain for a given VF.
6139static InstructionCost
6140getPartialReductionLinkCost(VPCostContext &CostCtx,
6141 const VPPartialReductionChain &Link,
6142 ElementCount VF) {
6143 Type *RdxType = Link.ReductionBinOp->getScalarType();
6144 const ExtendedReductionOperand &ExtendedOp = Link.ExtendedOp;
6145 std::optional<unsigned> BinOpc = std::nullopt;
6146 // If ExtendB is not none, then the "ExtendsUser" is the binary operation.
6147 if (ExtendedOp.ExtendB.Kind != ExtendKind::PR_None)
6148 BinOpc = ExtendedOp.ExtendsUser->getOpcode();
6149
6150 std::optional<llvm::FastMathFlags> Flags;
6151 if (RdxType->isFloatingPointTy())
6152 Flags = Link.ReductionBinOp->getFastMathFlagsOrNone();
6153
6154 auto GetLinkOpcode = [&Link]() -> unsigned {
6155 switch (Link.RK) {
6156 case RecurKind::Sub:
6157 return Instruction::Add;
6158 case RecurKind::FSub:
6159 return Instruction::FAdd;
6160 default:
6161 return Link.ReductionBinOp->getOpcode();
6162 }
6163 };
6164
6165 return CostCtx.TTI.getPartialReductionCost(
6166 GetLinkOpcode(), ExtendedOp.ExtendA.SrcType, ExtendedOp.ExtendB.SrcType,
6167 RdxType, VF, ExtendedOp.ExtendA.Kind, ExtendedOp.ExtendB.Kind, BinOpc,
6168 CostCtx.CostKind, Flags);
6169}
6170
6171static ExtendKind getPartialReductionExtendKind(VPWidenCastRecipe *Cast) {
6173}
6174
6175/// Checks if \p Op (which is an operand of \p UpdateR) is an extended reduction
6176/// operand. This is an operand where the source of the value (e.g. a load) has
6177/// been extended (sext, zext, or fpext) before it is used in the reduction.
6178///
6179/// Possible forms matched by this function:
6180/// - UpdateR(PrevValue, ext(...))
6181/// - UpdateR(PrevValue, mul(ext(...), ext(...)))
6182/// - UpdateR(PrevValue, mul(ext(...), Constant))
6183/// - UpdateR(PrevValue, ext(mul(ext(...), ext(...))))
6184/// - UpdateR(PrevValue, ext(mul(ext(...), Constant)))
6185/// - UpdateR(PrevValue, abs(sub(ext(...), ext(...)))
6186///
6187/// Note: The second operand of UpdateR corresponds to \p Op in the examples.
6188static std::optional<ExtendedReductionOperand>
6189matchExtendedReductionOperand(VPWidenRecipe *UpdateR, VPValue *Op) {
6190 assert(is_contained(UpdateR->operands(), Op) &&
6191 "Op should be operand of UpdateR");
6192
6193 // Try matching an absolute difference operand of the form
6194 // `abs(sub(ext(A), ext(B)))`. This will be later transformed into
6195 // `ext(absolute-difference(A, B))`. This allows us to perform the absolute
6196 // difference on a wider type and get the extend for "free" from the partial
6197 // reduction.
6198 VPValue *X, *Y;
6199 if (Op->hasOneUse() &&
6203 auto *Abs = cast<VPWidenIntrinsicRecipe>(Op);
6204 auto *Sub = cast<VPWidenRecipe>(Abs->getOperand(0));
6205 auto *LHSExt = cast<VPWidenCastRecipe>(Sub->getOperand(0));
6206 auto *RHSExt = cast<VPWidenCastRecipe>(Sub->getOperand(1));
6207 Type *LHSInputType = X->getScalarType();
6208 Type *RHSInputType = Y->getScalarType();
6209 if (LHSInputType != RHSInputType ||
6210 LHSExt->getOpcode() != RHSExt->getOpcode())
6211 return std::nullopt;
6212 // Note: This is essentially the same as matching ext(...) as we will
6213 // rewrite this operand to ext(absolute-difference(A, B)).
6214 return ExtendedReductionOperand{
6215 Sub,
6216 /*ExtendA=*/{LHSInputType, getPartialReductionExtendKind(LHSExt)},
6217 /*ExtendB=*/{}};
6218 }
6219
6220 std::optional<TTI::PartialReductionExtendKind> OuterExtKind;
6222 auto *CastRecipe = cast<VPWidenCastRecipe>(Op);
6223 VPValue *CastSource = CastRecipe->getOperand(0);
6224 OuterExtKind = getPartialReductionExtendKind(CastRecipe);
6225 if (match(CastSource, m_Mul(m_VPValue(), m_VPValue())) ||
6226 match(CastSource, m_FMul(m_VPValue(), m_VPValue()))) {
6227 // Match: ext(mul(...))
6228 // Record the outer extend kind and set `Op` to the mul. We can then match
6229 // this as a binary operation. Note: We can optimize out the outer extend
6230 // by widening the inner extends to match it. See
6231 // optimizeExtendsForPartialReduction.
6232 Op = CastSource;
6233 } else {
6234 return ExtendedReductionOperand{
6235 UpdateR,
6236 /*ExtendA=*/{CastSource->getScalarType(), *OuterExtKind},
6237 /*ExtendB=*/{}};
6238 }
6239 }
6240
6241 if (!Op->hasOneUse())
6242 return std::nullopt;
6243
6245 if (!MulOp ||
6246 !is_contained({Instruction::Mul, Instruction::FMul}, MulOp->getOpcode()))
6247 return std::nullopt;
6248
6249 // The rest of the matching assumes `Op` is a (possibly extended) mul
6250 // operation.
6251
6252 VPValue *LHS = MulOp->getOperand(0);
6253 VPValue *RHS = MulOp->getOperand(1);
6254
6255 // The LHS of the operation must always be an extend.
6257 return std::nullopt;
6258
6259 auto *LHSCast = cast<VPWidenCastRecipe>(LHS);
6260 Type *LHSInputType = LHSCast->getOperand(0)->getScalarType();
6261 ExtendKind LHSExtendKind = getPartialReductionExtendKind(LHSCast);
6262
6263 // The RHS of the operation can be an extend or a constant integer.
6264 const APInt *RHSConst = nullptr;
6265 VPWidenCastRecipe *RHSCast = nullptr;
6267 RHSCast = cast<VPWidenCastRecipe>(RHS);
6268 else if (!match(RHS, m_APInt(RHSConst)) ||
6269 !canConstantBeExtended(RHSConst, LHSInputType, LHSExtendKind))
6270 return std::nullopt;
6271
6272 // The outer extend kind must match the inner extends for folding.
6273 for (VPWidenCastRecipe *Cast : {LHSCast, RHSCast})
6274 if (Cast && OuterExtKind &&
6275 getPartialReductionExtendKind(Cast) != OuterExtKind)
6276 return std::nullopt;
6277
6278 Type *RHSInputType = LHSInputType;
6279 ExtendKind RHSExtendKind = LHSExtendKind;
6280 if (RHSCast) {
6281 RHSInputType = RHSCast->getOperand(0)->getScalarType();
6282 RHSExtendKind = getPartialReductionExtendKind(RHSCast);
6283 }
6284
6285 return ExtendedReductionOperand{
6286 MulOp, {LHSInputType, LHSExtendKind}, {RHSInputType, RHSExtendKind}};
6287}
6288
6289/// Examines each operation in the reduction chain corresponding to \p RedPhiR,
6290/// and determines if the target can use a cheaper operation with a wider
6291/// per-iteration input VF and narrower PHI VF. If successful, returns the chain
6292/// of operations in the reduction.
6293static std::optional<SmallVector<VPPartialReductionChain>>
6294getScaledReductions(VPReductionPHIRecipe *RedPhiR) {
6295 // Get the backedge value from the reduction PHI and find the
6296 // ComputeReductionResult that uses it (directly or through a select for
6297 // predicated reductions).
6298 auto *RdxResult = vputils::findComputeReductionResult(RedPhiR);
6299 if (!RdxResult)
6300 return std::nullopt;
6301 VPValue *ExitValue = RdxResult->getOperand(0);
6302 match(ExitValue, m_Select(m_VPValue(), m_VPValue(ExitValue), m_VPValue()));
6303
6305 RecurKind RK = RedPhiR->getRecurrenceKind();
6306 Type *PhiType = RedPhiR->getScalarType();
6307 TypeSize PHISize = PhiType->getPrimitiveSizeInBits();
6308
6309 // Work backwards from the ExitValue examining each reduction operation.
6310 VPValue *CurrentValue = ExitValue;
6311 while (CurrentValue != RedPhiR) {
6312 VPBlendRecipe *Blend = dyn_cast<VPBlendRecipe>(CurrentValue);
6313 std::optional<unsigned> BlendReductionIdx;
6314 if (Blend) {
6315 assert(!Blend->isNormalized() && "Expect Blend not to be normalized.");
6316 if (Blend->getNumIncomingValues() != 2)
6317 return std::nullopt;
6318
6319 BlendReductionIdx = getBlendReductionUpdateValueIdx(Blend);
6320 if (!BlendReductionIdx)
6321 return std::nullopt;
6322
6323 CurrentValue = Blend->getIncomingValue(*BlendReductionIdx);
6324 }
6325
6326 auto *UpdateR = dyn_cast<VPWidenRecipe>(CurrentValue);
6327 if (!UpdateR || !Instruction::isBinaryOp(UpdateR->getOpcode()))
6328 return std::nullopt;
6329
6330 VPValue *Op = UpdateR->getOperand(1);
6331 VPValue *PrevValue = UpdateR->getOperand(0);
6332
6333 // Find the extended operand. The other operand (PrevValue) is the next link
6334 // in the reduction chain.
6335 std::optional<ExtendedReductionOperand> ExtendedOp =
6336 matchExtendedReductionOperand(UpdateR, Op);
6337 if (!ExtendedOp) {
6338 ExtendedOp = matchExtendedReductionOperand(UpdateR, PrevValue);
6339 if (!ExtendedOp)
6340 return std::nullopt;
6341 std::swap(Op, PrevValue);
6342 }
6343
6344 // Look for VPBlend(reduce(PrevValue, Op), PrevValue), where
6345 // reduce is equal to CurrentValue. This can be lowered as
6346 // a conditional reduction by hoisting the select to the inputs.
6347 if (Blend && Blend->getIncomingValue(1 - *BlendReductionIdx) != PrevValue)
6348 return std::nullopt;
6349
6350 Type *ExtSrcType = ExtendedOp->ExtendA.SrcType;
6351 TypeSize ExtSrcSize = ExtSrcType->getPrimitiveSizeInBits();
6352 if (!PHISize.hasKnownScalarFactor(ExtSrcSize))
6353 return std::nullopt;
6354
6355 VPPartialReductionChain Link(
6356 {UpdateR, *ExtendedOp, RK,
6357 PrevValue == UpdateR->getOperand(0) ? 0U : 1U,
6358 static_cast<unsigned>(PHISize.getKnownScalarFactor(ExtSrcSize)),
6359 Blend});
6360 Chain.push_back(Link);
6361 CurrentValue = PrevValue;
6362 }
6363
6364 // The chain links were collected by traversing backwards from the exit value.
6365 // Reverse the chains so they are in program order.
6366 std::reverse(Chain.begin(), Chain.end());
6367 return Chain;
6368}
6369} // namespace
6370
6372 VPCostContext &CostCtx,
6373 VFRange &Range) {
6374 // Find all possible valid partial reductions, grouping chains by their PHI.
6375 // This grouping allows invalidating the whole chain, if any link is not a
6376 // valid partial reduction.
6378 ChainsByPhi;
6379 VPBasicBlock *HeaderVPBB = Plan.getVectorLoopRegion()->getEntryBasicBlock();
6380 for (VPRecipeBase &R : HeaderVPBB->phis()) {
6381 auto *RedPhiR = dyn_cast<VPReductionPHIRecipe>(&R);
6382 if (!RedPhiR)
6383 continue;
6384
6385 if (auto Chains = getScaledReductions(RedPhiR))
6386 ChainsByPhi.try_emplace(RedPhiR, std::move(*Chains));
6387 }
6388
6389 if (ChainsByPhi.empty())
6390 return;
6391
6392 // Build set of partial reduction operations and blends for user validation
6393 // and a map of reduction bin ops to their scale factors for scale validation.
6394 SmallPtrSet<VPRecipeBase *, 4> PartialReductionOps;
6395 SmallPtrSet<VPBlendRecipe *, 4> PartialReductionBlends;
6396 DenseMap<VPSingleDefRecipe *, unsigned> ScaledReductionMap;
6397 for (const auto &[_, Chains] : ChainsByPhi)
6398 for (const VPPartialReductionChain &Chain : Chains) {
6399 PartialReductionOps.insert(Chain.ExtendedOp.ExtendsUser);
6400 if (Chain.Blend)
6401 PartialReductionBlends.insert(Chain.Blend);
6402 ScaledReductionMap[Chain.ReductionBinOp] = Chain.ScaleFactor;
6403 }
6404
6405 // A partial reduction is invalid if any of its extends are used by
6406 // something that isn't another partial reduction. This is because the
6407 // extends are intended to be lowered along with the reduction itself.
6408 auto ExtendUsersValid = [&](VPValue *Ext) {
6409 return !isa<VPWidenCastRecipe>(Ext) || all_of(Ext->users(), [&](VPUser *U) {
6410 return PartialReductionOps.contains(cast<VPRecipeBase>(U));
6411 });
6412 };
6413
6414 auto IsProfitablePartialReductionChainForVF =
6415 [&](ArrayRef<VPPartialReductionChain> Chain, ElementCount VF) -> bool {
6416 InstructionCost PartialCost = 0, RegularCost = 0;
6417
6418 // The chain is a profitable partial reduction chain if the cost of handling
6419 // the entire chain is cheaper when using partial reductions than when
6420 // handling the entire chain using regular reductions.
6421 for (const VPPartialReductionChain &Link : Chain) {
6422 const ExtendedReductionOperand &ExtendedOp = Link.ExtendedOp;
6423 InstructionCost LinkCost = getPartialReductionLinkCost(CostCtx, Link, VF);
6424 if (!LinkCost.isValid())
6425 return false;
6426
6427 PartialCost += LinkCost;
6428 RegularCost += Link.ReductionBinOp->computeCost(VF, CostCtx);
6429 // If ExtendB is not none, then the "ExtendsUser" is the binary operation.
6430 if (ExtendedOp.ExtendB.Kind != ExtendKind::PR_None)
6431 RegularCost += ExtendedOp.ExtendsUser->computeCost(VF, CostCtx);
6432 for (VPValue *Op : ExtendedOp.ExtendsUser->operands())
6433 if (auto *Extend = dyn_cast<VPWidenCastRecipe>(Op))
6434 RegularCost += Extend->computeCost(VF, CostCtx);
6435 }
6436 return PartialCost.isValid() && PartialCost < RegularCost;
6437 };
6438
6439 // Validate chains: check that extends are only used by partial reductions,
6440 // and that reduction bin ops are only used by other partial reductions with
6441 // matching scale factors, are outside the loop region or the select
6442 // introduced by tail-folding. Otherwise we would create users of scaled
6443 // reductions where the types of the other operands don't match.
6444 for (auto &[RedPhiR, Chains] : ChainsByPhi) {
6445 for (const VPPartialReductionChain &Chain : Chains) {
6446 if (!all_of(Chain.ExtendedOp.ExtendsUser->operands(), ExtendUsersValid)) {
6447 Chains.clear();
6448 break;
6449 }
6450 auto UseIsValid = [&, RedPhiR = RedPhiR](VPUser *U) {
6451 if (auto *PhiR = dyn_cast<VPReductionPHIRecipe>(U))
6452 return PhiR == RedPhiR;
6453 auto *R = cast<VPSingleDefRecipe>(U);
6454
6455 if (auto *Blend = dyn_cast<VPBlendRecipe>(R))
6456 return Blend == Chain.Blend || PartialReductionBlends.contains(Blend);
6457
6458 return Chain.ScaleFactor == ScaledReductionMap.lookup_or(R, 0) ||
6460 m_Specific(Chain.ReductionBinOp))) ||
6461 match(R, m_Select(m_VPValue(), m_Specific(Chain.ReductionBinOp),
6462 m_Specific(RedPhiR)));
6463 };
6464 if (!all_of(Chain.ReductionBinOp->users(), UseIsValid)) {
6465 Chains.clear();
6466 break;
6467 }
6468
6469 // Check if the compute-reduction-result is used by a sunk store.
6470 // TODO: Also form partial reductions in those cases.
6471 if (auto *RdxResult = vputils::findComputeReductionResult(RedPhiR)) {
6472 if (any_of(RdxResult->users(), [](VPUser *U) {
6473 auto *RepR = dyn_cast<VPReplicateRecipe>(U);
6474 return RepR && RepR->getOpcode() == Instruction::Store;
6475 })) {
6476 Chains.clear();
6477 break;
6478 }
6479 }
6480 }
6481
6482 // Clear the chain if it is not profitable.
6484 [&, &Chains = Chains](ElementCount VF) {
6485 return IsProfitablePartialReductionChainForVF(Chains, VF);
6486 },
6487 Range))
6488 Chains.clear();
6489 }
6490
6491 for (auto &[Phi, Chains] : ChainsByPhi)
6492 for (const VPPartialReductionChain &Chain : Chains)
6493 transformToPartialReduction(Chain, Plan, Phi);
6494}
6495
6496/// If the pointer operand \p Addr of a memory access is an affine AddRec
6497/// w.r.t. \p L with a constant stride, return the stride in units of
6498/// \p AccessTy. Otherwise return std::nullopt.
6499static std::optional<int64_t> getConstantStride(VPValue *Addr, Type *AccessTy,
6501 const Loop *L) {
6502 const SCEV *AddrSCEV = vputils::getSCEVExprForVPValue(Addr, PSE, L);
6503 auto *AddRec = dyn_cast<SCEVAddRecExpr>(AddrSCEV);
6504 if (!AddRec)
6505 return {};
6506
6507 return getStrideFromAddRec(AddRec, L, AccessTy, /*Ptr=*/nullptr, PSE);
6508}
6509
6511 VPRecipeBuilder &RecipeBuilder,
6512 VPCostContext &CostCtx) {
6513 // Collect all loads/stores first. We will start with ones having simpler
6514 // decisions followed by more complex ones that are potentially
6515 // guided/dependent on the simpler ones.
6517 for (VPBasicBlock *VPBB :
6520 for (VPRecipeBase &R : *VPBB) {
6521 auto *VPI = dyn_cast<VPInstruction>(&R);
6522 if (VPI && VPI->getUnderlyingValue() &&
6523 is_contained({Instruction::Load, Instruction::Store},
6524 VPI->getOpcode()))
6525 MemOps.push_back(VPI);
6526 }
6527 }
6528
6529 // Few helpers to process different kinds of memory operations.
6530
6531 // To be used as argument to `VPlanTransforms::runPass` which explicitly
6532 // specified pass name, hence `VPlan &` parameter.
6533 auto ProcessSubset = [&](VPlan &, auto ProcessVPInst) {
6534 SmallVector<VPInstruction *> RemainingMemOps;
6535 for (VPInstruction *VPI : MemOps) {
6536 if (!ProcessVPInst(VPI))
6537 RemainingMemOps.push_back(VPI);
6538 }
6539
6540 MemOps.clear();
6541 std::swap(MemOps, RemainingMemOps);
6542 };
6543
6544 auto ReplaceWith = [&](VPInstruction *VPI, VPRecipeBase *New) {
6545 New->insertBefore(VPI);
6546 if (VPI->getOpcode() == Instruction::Load)
6547 VPI->replaceAllUsesWith(New->getVPSingleValue());
6548 VPI->eraseFromParent();
6549
6550 // VPI has been processed.
6551 return true;
6552 };
6553
6554 auto Scalarize = [&](VPInstruction *VPI) {
6555 return ReplaceWith(VPI, RecipeBuilder.handleReplication(VPI, Range));
6556 };
6557
6558 VPBasicBlock *MiddleVPBB = Plan.getMiddleBlock();
6559 VPBuilder FinalRedStoresBuilder(MiddleVPBB, MiddleVPBB->getFirstNonPhi());
6561 "lowerMemoryIdioms", ProcessSubset, Plan, [&](VPInstruction *VPI) {
6562 if (RecipeBuilder.replaceWithFinalIfReductionStore(
6563 VPI, FinalRedStoresBuilder))
6564 return true;
6565
6566 // Filter out scalar VPlan for the remaining idioms.
6568 [](ElementCount VF) { return VF.isScalar(); }, Range))
6569 return false;
6570
6571 if (VPHistogramRecipe *Histogram = RecipeBuilder.widenIfHistogram(VPI))
6572 return ReplaceWith(VPI, Histogram);
6573
6574 return false;
6575 });
6576
6577 // Filter out scalar VPlan for the remaining memory operations.
6579 [](ElementCount VF) { return VF.isScalar(); }, Range))
6580 return;
6581
6582 // If the instruction's allocated size doesn't equal it's type size, it
6583 // requires padding and will be scalarized.
6585 "scalarizeMemOpsWithIrregularTypes", ProcessSubset, Plan,
6586 [&](VPInstruction *VPI) {
6588 if (hasIrregularType(getLoadStoreType(I), I->getDataLayout()))
6589 return Scalarize(VPI);
6590
6591 return false;
6592 });
6593
6594 if (!RecipeBuilder.prefersVectorizedAddressing()) {
6596 "makeVPlanMemOpDecision", ProcessSubset, Plan, [&](VPInstruction *VPI) {
6598 bool IsLoad = VPI->getOpcode() == Instruction::Load;
6599 if (RecipeBuilder.isPredicatedInst(I) || !IsLoad ||
6601 return false;
6602
6603 // Scalarize loads used as addresses, matching the legacy CM. The load
6604 // is single-scalar if the pointer is loop-invariant, otherwise it is
6605 // replicated per-lane. No mask is needed as the load is not
6606 // predicated.
6607 VPValue *Ptr = VPI->getOperand(0);
6608 const SCEV *PtrSCEV =
6609 vputils::getSCEVExprForVPValue(Ptr, CostCtx.PSE, CostCtx.L);
6610 bool IsSingleScalarLoad =
6611 !isa<SCEVCouldNotCompute>(PtrSCEV) &&
6612 CostCtx.PSE.getSE()->isLoopInvariant(PtrSCEV, CostCtx.L);
6613
6614 ReplaceWith(VPI,
6616 I, Ptr, /*IsSingleScalar=*/IsSingleScalarLoad,
6617 /*Mask=*/nullptr, *VPI, *VPI, VPI->getDebugLoc()));
6618 return true;
6619 });
6620 }
6621
6622 // Widen unmasked unit-stride consecutive accesses, matching the legacy CM.
6624 "widenConsecutiveMemOps", ProcessSubset, Plan, [&](VPInstruction *VPI) {
6626 if (RecipeBuilder.isPredicatedInst(I))
6627 return false;
6628
6629 bool IsLoad = VPI->getOpcode() == Instruction::Load;
6630 VPValue *Ptr = VPI->getOperand(!IsLoad);
6631 Type *ScalarTy =
6632 IsLoad ? VPI->getScalarType() : VPI->getOperand(0)->getScalarType();
6633 if (getConstantStride(Ptr, ScalarTy, CostCtx.PSE, CostCtx.L) != 1)
6634 return false;
6635
6636 Type *StrideTy =
6638 VPValue *StrideOne = Plan.getConstantInt(StrideTy, 1);
6639 auto *VectorPtr = new VPVectorPointerRecipe(
6640 Ptr, ScalarTy, StrideOne, vputils::getGEPFlagsForPtr(Ptr),
6641 VPI->getDebugLoc());
6642 VectorPtr->insertBefore(VPI);
6643 VPRecipeBase *WidenedR;
6644 if (IsLoad)
6645 WidenedR = new VPWidenLoadRecipe(*cast<LoadInst>(I), VectorPtr,
6646 /*Mask=*/nullptr,
6647 /*Consecutive=*/true, *VPI,
6648 VPI->getDebugLoc());
6649 else
6650 WidenedR = new VPWidenStoreRecipe(
6651 *cast<StoreInst>(I), VectorPtr, VPI->getOperand(0),
6652 /*Mask=*/nullptr, /*Consecutive=*/true, *VPI, VPI->getDebugLoc());
6653 return ReplaceWith(VPI, WidenedR);
6654 });
6655
6656 VPlanTransforms::runPass("delegateMemOpWideningToLegacyCM", ProcessSubset,
6657 Plan, [&](VPInstruction *VPI) {
6658 if (VPRecipeBase *Recipe =
6659 RecipeBuilder.tryToWidenMemory(VPI, Range))
6660 return ReplaceWith(VPI, Recipe);
6661
6662 return Scalarize(VPI);
6663 });
6664}
6665
6668 [&](ElementCount VF) { return VF.isScalar(); }, Range))
6669 return;
6670
6672 Plan.getEntry());
6674 for (VPRecipeBase &R : make_early_inc_range(reverse(*VPBB))) {
6675 auto *VPI = dyn_cast<VPInstruction>(&R);
6676 if (!VPI)
6677 continue;
6678
6679 auto *I = cast_or_null<Instruction>(VPI->getUnderlyingValue());
6680 // Wouldn't be able to create a `VPReplicateRecipe` anyway.
6681 if (!I)
6682 continue;
6683
6684 // If executing other lanes produces side-effects we can't avoid them.
6685 if (VPI->mayHaveSideEffects())
6686 continue;
6687
6688 // We want to drop the mask operand, verify we can safely do that.
6689 if (VPI->isMasked() && !VPI->isSafeToSpeculativelyExecute())
6690 continue;
6691
6692 // Avoid rewriting IV increment as that interferes with
6693 // `removeRedundantCanonicalIVs`.
6694 if (VPI->getOpcode() == Instruction::Add &&
6696 continue;
6697
6698 // Other lanes are needed - can't drop them.
6700 continue;
6701
6702 auto *Recipe = VPBuilder::createSingleScalarOp(
6703 VPI->getOpcode(), VPI->operandsWithoutMask(), /*Mask=*/nullptr, *VPI,
6704 *VPI, VPI->getDebugLoc(), I);
6705 Recipe->insertBefore(VPI);
6706 VPI->replaceAllUsesWith(Recipe);
6707 VPI->eraseFromParent();
6708 }
6709 }
6710}
6711
6712/// Returns true if \p Info's parameter kinds are compatible with \p Args.
6713static bool areVFParamsOk(const VFInfo &Info, ArrayRef<VPValue *> Args,
6714 PredicatedScalarEvolution &PSE, const Loop *L) {
6715 ScalarEvolution *SE = PSE.getSE();
6716 return all_of(Info.Shape.Parameters, [&](VFParameter Param) {
6717 switch (Param.ParamKind) {
6718 case VFParamKind::Vector:
6719 case VFParamKind::GlobalPredicate:
6720 return true;
6721 case VFParamKind::OMP_Uniform:
6722 return SE->isSCEVable(Args[Param.ParamPos]->getScalarType()) &&
6723 SE->isLoopInvariant(
6724 vputils::getSCEVExprForVPValue(Args[Param.ParamPos], PSE, L),
6725 L);
6726 case VFParamKind::OMP_Linear:
6727 return match(vputils::getSCEVExprForVPValue(Args[Param.ParamPos], PSE, L),
6728 m_scev_AffineAddRec(
6729 m_SCEV(), m_scev_SpecificSInt(Param.LinearStepOrPos),
6730 m_SpecificLoop(L)));
6731 default:
6732 return false;
6733 }
6734 });
6735}
6736
6737/// Find a vector variant of \p CI for \p VF, respecting \p MaskRequired.
6738/// Returns the variant function, or nullptr. Masked variants are assumed to
6739/// take the mask as a trailing parameter.
6741 ElementCount VF, bool MaskRequired,
6743 const Loop *L) {
6744 if (CI->isNoBuiltin())
6745 return nullptr;
6746 auto Mappings = VFDatabase::getMappings(*CI);
6747 const auto *It = find_if(Mappings, [&](const VFInfo &Info) {
6748 return Info.Shape.VF == VF && (!MaskRequired || Info.isMasked()) &&
6749 areVFParamsOk(Info, Args, PSE, L);
6750 });
6751 if (It == Mappings.end())
6752 return nullptr;
6753 return CI->getModule()->getFunction(It->VectorName);
6754}
6755
6756namespace {
6757/// The outcome of choosing how to widen a call at a given VF.
6758struct CallWideningDecision {
6759 enum class KindTy { Scalarize, Intrinsic, VectorVariant };
6760 CallWideningDecision(KindTy Kind, Function *Variant = nullptr)
6761 : Kind(Kind), Variant(Variant) {}
6762 KindTy Kind;
6763
6764 /// Set when Kind == VectorVariant.
6766
6767 bool operator==(const CallWideningDecision &Other) const {
6768 return Kind == Other.Kind && Variant == Other.Variant;
6769 }
6770};
6771} // namespace
6772
6773/// Pick the cheapest widening for the call \p VPI at \p VF among scalarization,
6774/// vector intrinsic, and vector library variant.
6775static CallWideningDecision decideCallWidening(VPInstruction &VPI,
6777 ElementCount VF,
6778 VPCostContext &CostCtx) {
6779 auto *CI = cast<CallInst>(VPI.getUnderlyingInstr());
6780
6781 // Scalar VFs and calls forced or known to scalarize always replicate.
6782 if (VF.isScalar() || CostCtx.willBeScalarized(CI, VF))
6783 return CallWideningDecision::KindTy::Scalarize;
6784
6785 auto *CalledFn = cast<Function>(
6787 Type *ResultTy = VPI.getScalarType();
6789 bool MaskRequired = CostCtx.isMaskRequired(CI);
6790
6791 // Pseudo intrinsics (assume, lifetime, ...) are always scalarized.
6793 return CallWideningDecision::KindTy::Scalarize;
6794
6795 InstructionCost ScalarCost =
6796 VPReplicateRecipe::computeCallCost(CalledFn, ResultTy, Ops,
6797 /*IsSingleScalar=*/false, VF, CostCtx);
6798
6799 Function *VecFunc =
6800 findVectorVariant(CI, Ops, VF, MaskRequired, CostCtx.PSE, CostCtx.L);
6802 if (VecFunc)
6803 VecCallCost = VPWidenCallRecipe::computeCallCost(VecFunc, CostCtx);
6804
6805 // Prefer the intrinsic if it is at least as cheap as scalarizing and any
6806 // available vector variant.
6807 if (ID) {
6810 if (IntrinsicCost.isValid() && ScalarCost >= IntrinsicCost &&
6811 (!VecFunc || VecCallCost >= IntrinsicCost))
6812 return CallWideningDecision::KindTy::Intrinsic;
6813 }
6814
6815 // Otherwise, use a vector library variant when it beats scalarizing.
6816 if (VecFunc && ScalarCost >= VecCallCost)
6817 return {CallWideningDecision::KindTy::VectorVariant, VecFunc};
6818
6819 return CallWideningDecision::KindTy::Scalarize;
6820}
6821
6823 VPRecipeBuilder &RecipeBuilder,
6824 VPCostContext &CostCtx) {
6827 for (VPRecipeBase &R : make_early_inc_range(*VPBB)) {
6828 auto *VPI = dyn_cast<VPInstruction>(&R);
6829 if (!VPI || !VPI->getUnderlyingValue() ||
6830 VPI->getOpcode() != Instruction::Call)
6831 continue;
6832
6833 auto *CI = cast<CallInst>(VPI->getUnderlyingInstr());
6834 SmallVector<VPValue *, 4> Ops(VPI->op_begin(),
6835 VPI->op_begin() + CI->arg_size());
6836
6837 CallWideningDecision Decision =
6838 decideCallWidening(*VPI, Ops, Range.Start, CostCtx);
6840 [&](ElementCount VF) {
6841 return Decision == decideCallWidening(*VPI, Ops, VF, CostCtx);
6842 },
6843 Range);
6844
6845 VPSingleDefRecipe *Replacement = nullptr;
6846 switch (Decision.Kind) {
6847 case CallWideningDecision::KindTy::Intrinsic: {
6849 Type *ResultTy = VPI->getScalarType();
6850 Replacement = new VPWidenIntrinsicRecipe(*CI, ID, Ops, ResultTy, *VPI,
6851 *VPI, VPI->getDebugLoc());
6852 break;
6853 }
6854 case CallWideningDecision::KindTy::VectorVariant: {
6855 // Masked variants take the mask as a trailing parameter, so they have
6856 // one more parameter than the original call's arguments.
6857 if (Decision.Variant->arg_size() > Ops.size()) {
6858 VPValue *Mask = VPI->isMasked() ? VPI->getMask() : Plan.getTrue();
6859 Ops.push_back(Mask);
6860 }
6861 Ops.push_back(VPI->getOperand(VPI->getNumOperandsWithoutMask() - 1));
6862 Replacement = new VPWidenCallRecipe(CI, Decision.Variant, Ops, *VPI,
6863 *VPI, VPI->getDebugLoc());
6864 break;
6865 }
6866 case CallWideningDecision::KindTy::Scalarize:
6867 Replacement = RecipeBuilder.handleReplication(VPI, Range);
6868 break;
6869 }
6870
6871 Replacement->insertBefore(VPI);
6872 VPI->replaceAllUsesWith(Replacement);
6873 VPI->eraseFromParent();
6874 }
6875 }
6876}
6877
6880 Loop &L, VPCostContext &Ctx,
6881 VFRange &Range) {
6882 if (Plan.hasScalarVFOnly())
6883 return;
6884
6885 VPRegionBlock *VectorLoop = Plan.getVectorLoopRegion();
6886 VPValue *I32VF = nullptr;
6888 vp_depth_first_shallow(VectorLoop->getEntry()))) {
6889 for (VPRecipeBase &R : make_early_inc_range(*VPBB)) {
6890 auto *LoadR = dyn_cast<VPWidenLoadRecipe>(&R);
6891 // TODO: Support strided store.
6892 // TODO: Transform reverse access into strided access with -1 stride.
6893 // TODO: Transform gather/scatter with uniform address into strided access
6894 // with 0 stride.
6895 // TODO: Transform interleave access into multiple strided accesses.
6896 if (!LoadR || LoadR->isConsecutive())
6897 continue;
6898
6899 VPValue *Ptr = LoadR->getAddr();
6900 // Check if this is a strided access by analyzing the address SCEV for an
6901 // affine addRec.
6902 const SCEV *PtrSCEV = vputils::getSCEVExprForVPValue(Ptr, PSE, &L);
6903 const SCEV *Start;
6904 const SCEVConstant *Step;
6905 // TODO: Support non-constant loop invariant stride.
6906 if (!match(PtrSCEV,
6908 m_SpecificLoop(&L))))
6909 continue;
6910
6911 Type *LoadTy = LoadR->getScalarType();
6912 Align Alignment = LoadR->getAlign();
6913 auto IsProfitable = [&](ElementCount VF) {
6914 Type *DataTy = toVectorTy(LoadTy, VF);
6915 if (!Ctx.TTI.isLegalStridedLoadStore(DataTy, Alignment))
6916 return false;
6917 const InstructionCost CurrentCost = LoadR->computeCost(VF, Ctx);
6918 const InstructionCost StridedLoadStoreCost =
6920 Intrinsic::experimental_vp_strided_load, DataTy,
6921 LoadR->isMasked(), Alignment, Ctx);
6922 return StridedLoadStoreCost < CurrentCost;
6923 };
6924
6926 Range))
6927 continue;
6928
6929 // Invalidate the legacy widening decision so the cost of replaced load is
6930 // not counted during precomputeCosts.
6931 // TODO: Remove once the legacy exit cost computation is retired.
6932 for (ElementCount VF : Range)
6933 Ctx.invalidateWideningDecision(&LoadR->getIngredient(), VF);
6934
6935 // Get VF as i32 for the vector length operand.
6936 if (!I32VF) {
6937 VPBuilder Builder(Plan.getVectorPreheader());
6938 I32VF = Builder.createScalarZExtOrTrunc(
6939 &Plan.getVF(), Type::getInt32Ty(Plan.getContext()),
6941 }
6942
6943 VPBuilder Builder(LoadR);
6944 // Create the base pointer of strided access.
6945 // TODO: reuse VPDerivedIVRecipe for base pointer computation when it
6946 // supports a general VPValue as the start value.
6947 VPValue *StartVPV =
6948 VPSCEVExpander(Builder, *PSE.getSE(), LoadR->getDebugLoc())
6949 .tryToExpand(Start);
6950 if (!StartVPV)
6951 StartVPV = VPBuilder(Plan.getEntry()).createExpandSCEV(Start);
6952 VPValue *StrideInBytes = Plan.getOrAddLiveIn(Step->getValue());
6953 Type *IndexTy = Plan.getDataLayout().getIndexType(Ptr->getScalarType());
6954 assert(IndexTy == StrideInBytes->getScalarType() &&
6955 "Stride type from SCEV must match the index type");
6956 VPValue *CanIV = Builder.createScalarSExtOrTrunc(
6957 VectorLoop->getCanonicalIV(), IndexTy, DebugLoc::getUnknown());
6958 auto *AddRecPtr = cast<SCEVAddRecExpr>(PtrSCEV);
6959 auto *Offset = Builder.createOverflowingOp(
6960 Instruction::Mul, {CanIV, StrideInBytes},
6961 {AddRecPtr->hasNoUnsignedWrap(), /*HasNSW=*/false});
6962 GEPNoWrapFlags NWFlags = AddRecPtr->hasNoUnsignedWrap()
6965 VPValue *BasePtr = Builder.createNoWrapPtrAdd(StartVPV, Offset, NWFlags);
6966
6967 // Create a new vector pointer for strided access.
6968 VPValue *NewPtr = Builder.createVectorPointer(
6969 BasePtr, Type::getInt8Ty(Plan.getContext()), StrideInBytes, NWFlags,
6970 LoadR->getDebugLoc());
6971
6972 VPValue *Mask = LoadR->getMask();
6973 if (!Mask)
6974 Mask = Plan.getTrue();
6975 auto *StridedLoad = Builder.createWidenMemIntrinsic(
6976 Intrinsic::experimental_vp_strided_load,
6977 {NewPtr, StrideInBytes, Mask, I32VF}, LoadTy, Alignment, *LoadR,
6978 LoadR->getDebugLoc());
6979 LoadR->replaceAllUsesWith(StridedLoad);
6980 }
6981 }
6982}
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
AMDGPU Register Bank Select
This file implements a class to represent arbitrary precision integral constant values and operations...
MachineBasicBlock MachineBasicBlock::iterator DebugLoc DL
static bool isEqual(const Function &Caller, const Function &Callee)
static const Function * getParent(const Value *V)
#define X(NUM, ENUM, NAME)
Definition ELF.h:856
static GCRegistry::Add< ErlangGC > A("erlang", "erlang-compatible garbage collector")
static GCRegistry::Add< CoreCLRGC > E("coreclr", "CoreCLR-compatible GC")
static GCRegistry::Add< OcamlGC > B("ocaml", "ocaml 3.10-compatible GC")
static cl::opt< OutputCostKind > CostKind("cost-kind", cl::desc("Target cost kind"), cl::init(OutputCostKind::RecipThroughput), cl::values(clEnumValN(OutputCostKind::RecipThroughput, "throughput", "Reciprocal throughput"), clEnumValN(OutputCostKind::Latency, "latency", "Instruction latency"), clEnumValN(OutputCostKind::CodeSize, "code-size", "Code size"), clEnumValN(OutputCostKind::SizeAndLatency, "size-latency", "Code size and latency"), clEnumValN(OutputCostKind::All, "all", "Print all cost kinds")))
static cl::opt< IntrinsicCostStrategy > IntrinsicCost("intrinsic-cost-strategy", cl::desc("Costing strategy for intrinsic instructions"), cl::init(IntrinsicCostStrategy::InstructionCost), cl::values(clEnumValN(IntrinsicCostStrategy::InstructionCost, "instruction-cost", "Use TargetTransformInfo::getInstructionCost"), clEnumValN(IntrinsicCostStrategy::IntrinsicCost, "intrinsic-cost", "Use TargetTransformInfo::getIntrinsicInstrCost"), clEnumValN(IntrinsicCostStrategy::TypeBasedIntrinsicCost, "type-based-intrinsic-cost", "Calculate the intrinsic cost based only on argument types")))
@ Default
Hexagon Common GEP
#define _
iv Induction Variable Users
Definition IVUsers.cpp:48
iv users
Definition IVUsers.cpp:48
static std::pair< Value *, APInt > getMask(Value *WideMask, unsigned Factor, ElementCount LeafValueEC)
const AbstractManglingParser< Derived, Alloc >::OperatorInfo AbstractManglingParser< Derived, Alloc >::Ops[]
licm
Definition LICM.cpp:383
Legalize the Machine IR a function s Machine IR
Definition Legalizer.cpp:81
#define I(x, y, z)
Definition MD5.cpp:57
This file provides utility analysis objects describing memory locations.
This file contains the declarations for metadata subclasses.
MachineInstr unsigned OpIdx
ConstantRange Range(APInt(BitWidth, Low), APInt(BitWidth, High))
#define P(N)
This file builds on the ADT/GraphTraits.h file to build a generic graph post order iterator.
const SmallVectorImpl< MachineOperand > & Cond
static bool dominates(InstrPosIndexes &PosIndexes, const MachineInstr &A, const MachineInstr &B)
Func MI getDebugLoc()))
This file contains some templates that are useful if you are working with the STL at all.
This is the interface for a metadata-based scoped no-alias analysis.
This file implements a set that has insertion order iteration characteristics.
This file defines the SmallPtrSet class.
static TableGen::Emitter::Opt Y("gen-skeleton-entry", EmitSkeleton, "Generate example skeleton entry")
This file implements the TypeSwitch template, which mimics a switch() statement whose cases are type ...
This file implements dominator tree analysis for a single level of a VPlan's H-CFG.
This file contains the declarations of different VPlan-related auxiliary helpers.
static SmallVector< SmallVector< VPReplicateRecipe *, 4 > > collectComplementaryPredicatedMemOps(VPlan &Plan, PredicatedScalarEvolution &PSE, const Loop *L)
static void removeCommonBlendMask(VPBlendRecipe *Blend)
Try to see if all of Blend's masks share a common value logically and'ed and remove it from the masks...
static void tryToCreateAbstractReductionRecipe(VPReductionRecipe *Red, VPCostContext &Ctx, VFRange &Range)
This function tries to create abstract recipes from the reduction recipe for following optimizations ...
static VPReplicateRecipe * findRecipeWithMinAlign(ArrayRef< VPReplicateRecipe * > Group)
static bool handleUncountableExitsWithSideEffects(VPlan &Plan, SmallVectorImpl< EarlyExitInfo > &Exits, VPBasicBlock *HeaderVPBB, VPBasicBlock *LatchVPBB, VPBasicBlock *MiddleVPBB, Loop *TheLoop, PredicatedScalarEvolution &PSE, DominatorTree &DT, AssumptionCache *AC)
Update Plan to mask memory operations in the loop based on whether the early exit is taken or not.
static CallWideningDecision decideCallWidening(VPInstruction &VPI, ArrayRef< VPValue * > Ops, ElementCount VF, VPCostContext &CostCtx)
Pick the cheapest widening for the call VPI at VF among scalarization, vector intrinsic,...
static bool areVFParamsOk(const VFInfo &Info, ArrayRef< VPValue * > Args, PredicatedScalarEvolution &PSE, const Loop *L)
Returns true if Info's parameter kinds are compatible with Args.
static std::optional< VPValue * > getRecipesForUncountableExit(SmallVectorImpl< VPInstruction * > &Recipes, VPBasicBlock *LatchVPBB)
Returns the VPValue representing the uncountable exit comparison used by AnyOf if the recipes it depe...
static bool simplifyLogicalRecipe(VPSingleDefRecipe *Def, VPBuilder &Builder, bool CanCreateNewRecipe)
Try to simplify logical and bitwise recipes in Def.
static bool sinkScalarOperands(VPlan &Plan)
static std::optional< int64_t > getConstantStride(VPValue *Addr, Type *AccessTy, PredicatedScalarEvolution &PSE, const Loop *L)
If the pointer operand Addr of a memory access is an affine AddRec w.r.t.
static bool simplifyBranchConditionForVFAndUF(VPlan &Plan, ElementCount BestVF, unsigned BestUF, PredicatedScalarEvolution &PSE)
Try to simplify the branch condition of Plan.
static VPValue * cloneBinOpForScalarIV(VPWidenRecipe *BinOp, VPValue *ScalarIV, VPWidenIntOrFpInductionRecipe *WidenIV)
Create a scalar version of BinOp, with its WidenIV operand replaced by ScalarIV, and place it after S...
static VPWidenIntOrFpInductionRecipe * getExpressionIV(VPValue *V)
Check if V is a binary expression of a widened IV and a loop-invariant value.
static void removeRedundantInductionCasts(VPlan &Plan)
Remove redundant casts of inductions.
static bool isConditionTrueViaVFAndUF(VPValue *Cond, VPlan &Plan, ElementCount BestVF, unsigned BestUF, PredicatedScalarEvolution &PSE)
Return true if Cond is known to be true for given BestVF and BestUF.
static bool tryToReplaceALMWithWideALM(VPlan &Plan, ElementCount VF, unsigned UF)
Try to replace multiple active lane masks used for control flow with a single, wide active lane mask ...
static VPExpressionRecipe * tryToMatchAndCreateExtendedReduction(VPReductionRecipe *Red, VPCostContext &Ctx, VFRange &Range)
This function tries convert extended in-loop reductions to VPExpressionRecipe and clamp the Range if ...
static std::optional< ElementCount > isConsecutiveInterleaveGroup(VPInterleaveRecipe *InterleaveR, ArrayRef< ElementCount > VFs, const TargetTransformInfo &TTI)
Returns VF from VFs if IR is a full interleave group with factor and number of members both equal to ...
static Type * getLoadStoreValueType(VPReplicateRecipe *R, bool IsLoad)
Get the value type of the replicate load or store.
static VPIRMetadata getCommonMetadata(ArrayRef< VPReplicateRecipe * > Recipes)
static VPValue * getPredicatedMask(VPRegionBlock *R)
If R is a region with a VPBranchOnMaskRecipe in the entry block, return the mask.
static bool mergeReplicateRegionsIntoSuccessors(VPlan &Plan)
static Function * findVectorVariant(CallInst *CI, ArrayRef< VPValue * > Args, ElementCount VF, bool MaskRequired, PredicatedScalarEvolution &PSE, const Loop *L)
Find a vector variant of CI for VF, respecting MaskRequired.
static VPScalarIVStepsRecipe * createScalarIVSteps(VPlan &Plan, InductionDescriptor::InductionKind Kind, Instruction::BinaryOps InductionOpcode, FPMathOperator *FPBinOp, Instruction *TruncI, VPIRValue *StartV, VPValue *Step, DebugLoc DL, VPBuilder &Builder)
static VPWidenInductionRecipe * getOptimizableIVOf(VPValue *VPV, PredicatedScalarEvolution &PSE)
Check if VPV is an untruncated wide induction, either before or after the increment.
static bool canNarrowLoad(VPSingleDefRecipe *WideMember0, unsigned OpIdx, VPValue *OpV, unsigned Idx, bool IsScalable)
Returns true if V is VPWidenLoadRecipe or VPInterleaveRecipe that can be converted to a narrower reci...
static void simplifyRecipe(VPSingleDefRecipe *Def)
Try to simplify VPSingleDefRecipe Def.
static void legalizeAndOptimizeInductions(VPlan &Plan)
Legalize VPWidenPointerInductionRecipe, by replacing it with a PtrAdd (IndStart, ScalarIVSteps (0,...
static void addReplicateRegions(VPlan &Plan)
static SmallVector< SmallVector< VPReplicateRecipe *, 4 > > collectGroupedReplicateMemOps(VPlan &Plan, PredicatedScalarEvolution &PSE, const Loop *L, function_ref< bool(VPReplicateRecipe *)> FilterFn)
Collect either replicated Loads or Stores grouped by their address SCEV and their load-store type,...
static VPValue * tryToComputeEndValueForInduction(VPWidenInductionRecipe *WideIV, VPBuilder &VectorPHBuilder, VPValue *VectorTC)
Compute the end value for WideIV, unless it is truncated.
static void removeRedundantExpandSCEVRecipes(VPlan &Plan)
Remove redundant ExpandSCEVRecipes in Plan's entry block by replacing them with already existing reci...
static VPValue * optimizeEarlyExitInductionUser(VPlan &Plan, VPValue *Op, PredicatedScalarEvolution &PSE)
Attempts to optimize the induction variable exit values for users in the early exit block.
static VPValue * narrowInterleaveGroupOp(ArrayRef< VPValue * > Members, SmallPtrSetImpl< VPValue * > &NarrowedOps, VPBasicBlock *Preheader)
static VPValue * scalarizeVPWidenPointerInduction(VPWidenPointerInductionRecipe *PtrIV, VPlan &Plan, VPBuilder &Builder)
Scalarize a VPWidenPointerInductionRecipe by replacing it with a PtrAdd (IndStart,...
static VPValue * optimizeLatchExitInductionUser(VPlan &Plan, VPValue *Op, DenseMap< VPValue *, VPValue * > &EndValues, PredicatedScalarEvolution &PSE)
Attempts to optimize the induction variable exit values for users in the exit block coming from the l...
static void reassociateHeaderMask(VPlan &Plan)
Reassociate (headermask && x) && y -> headermask && (x && y) to allow the header mask to be simplifie...
static VPActiveLaneMaskPHIRecipe * addVPLaneMaskPhiAndUpdateExitBranch(VPlan &Plan)
static void expandVPDerivedIV(VPDerivedIVRecipe *R)
Expand a VPDerivedIVRecipe into executable recipes.
static VPBasicBlock * getPredicatedThenBlock(VPRegionBlock *R)
If R is a triangle region, return the 'then' block of the triangle.
static bool canHoistOrSinkWithNoAliasCheck(const MemoryLocation &MemLoc, VPBasicBlock *FirstBB, VPBasicBlock *LastBB, std::optional< SinkStoreInfo > SinkInfo={})
Check if a memory operation doesn't alias with memory operations using scoped noalias metadata,...
static VPRegionBlock * createReplicateRegion(VPReplicateRecipe *PredRecipe, VPRegionBlock *ParentRegion, VPlan &Plan)
static void simplifyBlends(VPlan &Plan)
Normalize and simplify VPBlendRecipes.
static bool cannotHoistOrSinkRecipe(VPRecipeBase &R, VPBasicBlock *FirstBB, VPBasicBlock *LastBB, bool Sinking=false)
Return true if we do not know how to (mechanically) hoist or sink a non-memory or memory recipe R out...
static std::optional< Instruction::BinaryOps > getUnmaskedDivRemOpcode(Intrinsic::ID ID)
static bool isAlreadyNarrow(VPValue *VPV)
Returns true if VPValue is a narrow VPValue.
static bool canNarrowOps(ArrayRef< VPValue * > Ops, bool IsScalable)
static bool optimizeVectorInductionWidthForTCAndVFUF(VPlan &Plan, ElementCount BestVF, unsigned BestUF)
Optimize the width of vector induction variables in Plan based on a known constant Trip Count,...
static VPExpressionRecipe * tryToMatchAndCreateMulAccumulateReduction(VPReductionRecipe *Red, VPCostContext &Ctx, VFRange &Range)
This function tries convert extended in-loop reductions to VPExpressionRecipe and clamp the Range if ...
static bool canSinkStoreWithNoAliasCheck(ArrayRef< VPReplicateRecipe * > StoresToSink, PredicatedScalarEvolution &PSE, const Loop &L)
static void expandVPWidenIntOrFpInduction(VPWidenIntOrFpInductionRecipe *WidenIVR)
Expand a VPWidenIntOrFpInduction into executable recipes, for the initial value, phi and backedge val...
static void expandVPWidenPointerInduction(VPWidenPointerInductionRecipe *R)
Expand a VPWidenPointerInductionRecipe into executable recipes, for the initial value,...
static void narrowToSingleScalarRecipes(VPlan &Plan)
This file provides utility VPlan to VPlan transformations.
#define RUN_VPLAN_PASS(PASS,...)
This file declares the class VPlanVerifier, which contains utility functions to check the consistency...
This file contains the declarations of the Vectorization Plan base classes:
static const X86InstrFMA3Group Groups[]
Value * RHS
Value * LHS
BinaryOperator * Mul
static const uint32_t IV[8]
Definition blake3_impl.h:83
Helper for extra no-alias checks via known-safe recipe and SCEV.
SinkStoreInfo(ArrayRef< VPReplicateRecipe * > ExcludeRecipes, VPReplicateRecipe &GroupLeader, PredicatedScalarEvolution &PSE, const Loop &L)
SinkStoreInfo(VPReplicateRecipe &GroupLeader)
bool shouldSkip(VPRecipeBase &R) const
Return true if R should be skipped during alias checking, either because it's in the exclude set or b...
Class for arbitrary precision integers.
Definition APInt.h:78
LLVM_ABI APInt zext(unsigned width) const
Zero extend to a new width.
Definition APInt.cpp:1055
unsigned getActiveBits() const
Compute the number of active bits in the value.
Definition APInt.h:1537
APInt abs() const
Get the absolute value.
Definition APInt.h:1820
LLVM_ABI APInt urem(const APInt &RHS) const
Unsigned remainder operation.
Definition APInt.cpp:1692
unsigned getBitWidth() const
Return the number of bits in the APInt.
Definition APInt.h:1513
int32_t exactLogBase2() const
Definition APInt.h:1808
LLVM_ABI APInt sext(unsigned width) const
Sign extend to a new width.
Definition APInt.cpp:1028
bool isPowerOf2() const
Check if this APInt's value is a power of two greater than zero.
Definition APInt.h:441
bool uge(const APInt &RHS) const
Unsigned greater or equal comparison.
Definition APInt.h:1230
An arbitrary precision integer that knows its signedness.
Definition APSInt.h:24
static APSInt getMinValue(uint32_t numBits, bool Unsigned)
Return the APSInt representing the minimum integer value with the given bit width and signedness.
Definition APSInt.h:310
static APSInt getMaxValue(uint32_t numBits, bool Unsigned)
Return the APSInt representing the maximum integer value with the given bit width and signedness.
Definition APSInt.h:302
@ NoAlias
The two locations do not alias at all.
Represent a constant reference to an array (0 or more elements consecutively in memory),...
Definition ArrayRef.h:40
const T & back() const
Get the last element.
Definition ArrayRef.h:150
ArrayRef< T > drop_front(size_t N=1) const
Drop the first N elements of the array.
Definition ArrayRef.h:194
const T & front() const
Get the first element.
Definition ArrayRef.h:144
A cache of @llvm.assume calls within a function.
LLVM Basic Block Representation.
Definition BasicBlock.h:62
const Function * getParent() const
Return the enclosing method, or null if none.
Definition BasicBlock.h:213
const Instruction * getTerminator() const LLVM_READONLY
Returns the terminator instruction; assumes that the block is well-formed.
Definition BasicBlock.h:237
bool isNoBuiltin() const
Return true if the call should not be treated as a call to a builtin.
This class represents a function call, abstracting a target machine's calling convention.
@ ICMP_ULT
unsigned less than
Definition InstrTypes.h:765
@ ICMP_NE
not equal
Definition InstrTypes.h:762
@ ICMP_ULE
unsigned less or equal
Definition InstrTypes.h:766
@ FCMP_UNO
1 0 0 0 True if unordered: isnan(X) | isnan(Y)
Definition InstrTypes.h:750
Predicate getInversePredicate() const
For example, EQ -> NE, UGT -> ULE, SLT -> SGE, OEQ -> UNE, UGT -> OLE, OLT -> UGE,...
Definition InstrTypes.h:852
An abstraction over a floating-point predicate, and a pack of an integer predicate with samesign info...
This class represents a range of values.
LLVM_ABI bool contains(const APInt &Val) const
Return true if the specified value is in the set.
A parsed version of the target data layout string in and methods for querying it.
Definition DataLayout.h:64
LLVM_ABI IntegerType * getIndexType(LLVMContext &C, unsigned AddressSpace) const
Returns the type of a GEP index in AddressSpace.
A debug info location.
Definition DebugLoc.h:126
static DebugLoc getCompilerGenerated()
Definition DebugLoc.h:154
static DebugLoc getUnknown()
Definition DebugLoc.h:153
ValueT lookup(const_arg_type_t< KeyT > Val) const
Return the entry for the specified key, or a default constructed value if no such entry exists.
Definition DenseMap.h:250
std::pair< iterator, bool > try_emplace(KeyT &&Key, Ts &&...Args)
Definition DenseMap.h:299
ValueT lookup_or(const_arg_type_t< KeyT > Val, U &&Default) const
Definition DenseMap.h:260
bool dominates(const DomTreeNodeBase< NodeT > *A, const DomTreeNodeBase< NodeT > *B) const
dominates - Returns true iff A dominates B.
Concrete subclass of DominatorTreeBase that is used to compute a normal dominator tree.
Definition Dominators.h:151
constexpr bool isVector() const
One or more elements.
Definition TypeSize.h:324
static constexpr ElementCount getScalable(ScalarTy MinVal)
Definition TypeSize.h:312
constexpr bool isScalar() const
Exactly one element.
Definition TypeSize.h:320
Utility class for floating point operations which can have information about relaxed accuracy require...
Definition Operator.h:202
FastMathFlags getFastMathFlags() const
Convenience function for getting all the fast-math flags.
Definition Operator.h:291
Convenience struct for specifying and reasoning about fast-math flags.
Definition FMF.h:23
size_t arg_size() const
Definition Function.h:878
Represents flags for the getelementptr instruction/expression.
static GEPNoWrapFlags noUnsignedWrap()
bool hasNoUnsignedWrap() const
GEPNoWrapFlags withoutNoUnsignedWrap() const
static GEPNoWrapFlags none()
an instruction for type-safe pointer arithmetic to access elements of arrays and structs
A struct for saving information about induction variables.
static LLVM_ABI InductionDescriptor getCanonicalIntInduction(Type *Ty, ScalarEvolution &SE)
Returns the canonical integer induction for type Ty with start = 0 and step = 1.
InductionKind
This enum represents the kinds of inductions that we support.
@ IK_NoInduction
Not an induction variable.
@ IK_FpInduction
Floating point induction variable.
@ IK_PtrInduction
Pointer induction var. Step = C.
@ IK_IntInduction
Integer induction variable. Step = C.
static InstructionCost getInvalid(CostType Val=0)
LLVM_ABI const Module * getModule() const
Return the module owning the function this instruction belongs to or nullptr it the function does not...
bool isBinaryOp() const
LLVM_ABI const DataLayout & getDataLayout() const
Get the data layout of the module this instruction belongs to.
bool isIntDivRem() const
static LLVM_ABI IntegerType * get(LLVMContext &C, unsigned NumBits)
This static method is the primary way of constructing an IntegerType.
Definition Type.cpp:348
The group of interleaved loads/stores sharing the same stride and close to each other.
This is an important class for using LLVM in a threaded context.
Definition LLVMContext.h:68
An instruction for reading from memory.
static bool getDecisionAndClampRange(const std::function< bool(ElementCount)> &Predicate, VFRange &Range)
Test a Predicate on a Range of VF's.
Definition VPlan.cpp:1659
Represents a single loop in the control flow graph.
Definition LoopInfo.h:40
LLVM_ABI MDNode * createBranchWeights(uint32_t TrueWeight, uint32_t FalseWeight, bool IsExpected=false)
Return metadata containing two branch weights.
Definition MDBuilder.cpp:38
Metadata node.
Definition Metadata.h:1069
This class implements a map that also provides access to all stored values in a deterministic order.
Definition MapVector.h:38
ValueT lookup(const KeyT &Key) const
Definition MapVector.h:110
std::pair< iterator, bool > try_emplace(const KeyT &Key, Ts &&...Args)
Definition MapVector.h:118
bool empty() const
Definition MapVector.h:79
Representation for a specific memory location.
Function * getFunction(StringRef Name) const
Look up the specified function in the module symbol table.
Definition Module.cpp:235
unsigned getOpcode() const
Return the opcode for this Instruction or ConstantExpr.
Definition Operator.h:43
Post-order traversal of a graph.
An interface layer with SCEV used to manage how we see SCEV expressions for values in the context of ...
ScalarEvolution * getSE() const
Returns the ScalarEvolution analysis used.
LLVM_ABI const SCEV * getSCEV(Value *V)
Returns the SCEV expression of V, in the context of the current SCEV predicate.
static LLVM_ABI unsigned getOpcode(RecurKind Kind)
Returns the opcode corresponding to the RecurrenceKind.
static bool isFindLastRecurrenceKind(RecurKind Kind)
Returns true if the recurrence kind is of the form select(cmp(),x,y) where one of (x,...
RegionT * getParent() const
Get the parent of the Region.
Definition RegionInfo.h:362
This class represents a constant integer value.
ConstantInt * getValue() const
This class uses information about analyze scalars to rewrite expressions in canonical form.
LLVM_ABI Value * expandCodeFor(SCEVUse SH, Type *Ty, BasicBlock::iterator I)
Insert code to directly compute the specified SCEV expression into the program.
static const SCEV * rewrite(const SCEV *Scev, ScalarEvolution &SE, ValueToSCEVMapTy &Map)
This class represents an analyzed expression in the program.
LLVM_ABI Type * getType() const
Return the LLVM type of this SCEV expression.
The main scalar evolution driver.
LLVM_ABI const SCEV * getUDivExpr(SCEVUse LHS, SCEVUse RHS)
Get a canonical unsigned division expression, or something simpler if possible.
const DataLayout & getDataLayout() const
Return the DataLayout associated with the module this SCEV instance is operating on.
LLVM_ABI const SCEV * getNegativeSCEV(const SCEV *V, SCEV::NoWrapFlags Flags=SCEV::FlagAnyWrap)
Return the SCEV object corresponding to -V.
LLVM_ABI bool isKnownNonZero(const SCEV *S)
Test if the given expression is known to be non-zero.
LLVM_ABI const SCEV * getConstant(ConstantInt *V)
LLVM_ABI const SCEV * getSCEV(Value *V)
Return a SCEV expression for the full generality of the specified expression.
LLVM_ABI const SCEV * getMinusSCEV(SCEVUse LHS, SCEVUse RHS, SCEV::NoWrapFlags Flags=SCEV::FlagAnyWrap, unsigned Depth=0)
Return LHS-RHS.
ConstantRange getSignedRange(const SCEV *S)
Determine the signed range for a particular SCEV.
LLVM_ABI bool isLoopInvariant(const SCEV *S, const Loop *L)
Return true if the value of the given SCEV is unchanging in the specified loop.
LLVM_ABI bool isKnownPositive(const SCEV *S)
Test if the given expression is known to be positive.
LLVM_ABI const SCEV * getElementCount(Type *Ty, ElementCount EC, SCEV::NoWrapFlags Flags=SCEV::FlagAnyWrap)
ConstantRange getUnsignedRange(const SCEV *S)
Determine the unsigned range for a particular SCEV.
LLVM_ABI const SCEV * getMulExpr(SmallVectorImpl< SCEVUse > &Ops, SCEV::NoWrapFlags Flags=SCEV::FlagAnyWrap, unsigned Depth=0)
Get a canonical multiply expression, or something simpler if possible.
LLVM_ABI bool isKnownPredicate(CmpPredicate Pred, SCEVUse LHS, SCEVUse RHS)
Test if the given expression is known to satisfy the condition described by Pred, LHS,...
static LLVM_ABI AliasResult alias(const MemoryLocation &LocA, const MemoryLocation &LocB)
A vector that has set insertion semantics.
Definition SetVector.h:57
size_type size() const
Determine the number of elements in the SetVector.
Definition SetVector.h:103
bool insert(const value_type &X)
Insert a new element into the SetVector.
Definition SetVector.h:151
size_type size() const
Definition SmallPtrSet.h:99
A templated base class for SmallPtrSet which provides the typesafe interface that is common across al...
std::pair< iterator, bool > insert(PtrType Ptr)
Inserts Ptr if and only if there is no element in the container equal to Ptr.
iterator begin() const
bool contains(ConstPtrType Ptr) const
SmallPtrSet - This class implements a set which is optimized for holding SmallSize or less elements.
This class consists of common code factored out of the SmallVector class to reduce code duplication b...
void push_back(const T &Elt)
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
An instruction for storing to memory.
Provides information about what library functions are available for the current target.
This pass provides access to the codegen interfaces that are needed for IR-level transformations.
static LLVM_ABI PartialReductionExtendKind getPartialReductionExtendKind(Instruction *I)
Get the kind of extension that an instruction represents.
TargetCostKind
The kind of cost model.
@ TCK_RecipThroughput
Reciprocal throughput.
LLVM_ABI InstructionCost getPartialReductionCost(unsigned Opcode, Type *InputTypeA, Type *InputTypeB, Type *AccumType, ElementCount VF, PartialReductionExtendKind OpAExtend, PartialReductionExtendKind OpBExtend, std::optional< unsigned > BinOp, TTI::TargetCostKind CostKind, std::optional< FastMathFlags > FMF) const
@ SK_Broadcast
Broadcast element 0 to all other elements.
Twine - A lightweight data structure for efficiently representing the concatenation of temporary valu...
Definition Twine.h:82
This class implements a switch-like dispatch statement for a value of 'T' using dyn_cast functionalit...
Definition TypeSwitch.h:89
TypeSwitch< T, ResultT > & Case(CallableT &&caseFn)
Add a case on the given type.
Definition TypeSwitch.h:98
The instances of the Type class are immutable: once they are created, they are never changed.
Definition Type.h:46
static LLVM_ABI IntegerType * getInt32Ty(LLVMContext &C)
Definition Type.cpp:309
bool isPointerTy() const
True if this is an instance of PointerType.
Definition Type.h:282
static LLVM_ABI IntegerType * getInt8Ty(LLVMContext &C)
Definition Type.cpp:307
Type * getScalarType() const
If this is a vector type, return the element type, otherwise return 'this'.
Definition Type.h:368
bool isStructTy() const
True if this is an instance of StructType.
Definition Type.h:276
LLVM_ABI TypeSize getPrimitiveSizeInBits() const LLVM_READONLY
Return the basic size of this type if it is a primitive type.
Definition Type.cpp:197
LLVM_ABI unsigned getScalarSizeInBits() const LLVM_READONLY
If this is a vector type, return the getPrimitiveSizeInBits value for the element type.
Definition Type.cpp:232
static LLVM_ABI IntegerType * getInt1Ty(LLVMContext &C)
Definition Type.cpp:306
bool isFloatingPointTy() const
Return true if this is one of the floating-point types.
Definition Type.h:186
bool isIntegerTy() const
True if this is an instance of IntegerType.
Definition Type.h:257
op_range operands()
Definition User.h:267
static SmallVector< VFInfo, 8 > getMappings(const CallInst &CI)
Retrieve all the VFInfo instances associated to the CallInst CI.
Definition VectorUtils.h:76
A recipe for generating the active lane mask for the vector loop that is used to predicate the vector...
Definition VPlan.h:4027
VPBasicBlock serves as the leaf of the Hierarchical Control-Flow Graph.
Definition VPlan.h:4365
void appendRecipe(VPRecipeBase *Recipe)
Augment the existing recipes of a VPBasicBlock with an additional Recipe as the last recipe.
Definition VPlan.h:4440
RecipeListTy::iterator iterator
Instruction iterators...
Definition VPlan.h:4392
iterator end()
Definition VPlan.h:4402
iterator begin()
Recipe iterator methods.
Definition VPlan.h:4400
iterator_range< iterator > phis()
Returns an iterator range over the PHI-like recipes in the block.
Definition VPlan.h:4453
iterator getFirstNonPhi()
Return the position of the first non-phi node recipe in the block.
Definition VPlan.cpp:266
VPBasicBlock * splitAt(iterator SplitAt)
Split current block at SplitAt by inserting a new block between the current block and its successors ...
Definition VPlan.cpp:564
const VPRecipeBase & front() const
Definition VPlan.h:4412
VPRecipeBase * getTerminator()
If the block has multiple successors, return the branch recipe terminating the block.
Definition VPlan.cpp:643
const VPRecipeBase & back() const
Definition VPlan.h:4414
A recipe for vectorizing a phi-node as a sequence of mask-based select instructions.
Definition VPlan.h:2935
VPValue * getIncomingValue(unsigned Idx) const
Return incoming value number Idx.
Definition VPlan.h:2980
VPValue * getMask(unsigned Idx) const
Return mask number Idx.
Definition VPlan.h:2985
unsigned getNumIncomingValues() const
Return the number of incoming values, taking into account when normalized the first incoming value wi...
Definition VPlan.h:2975
void setMask(unsigned Idx, VPValue *V)
Set mask number Idx to V.
Definition VPlan.h:2991
bool isNormalized() const
A normalized blend is one that has an odd number of operands, whereby the first operand does not have...
Definition VPlan.h:2971
VPBlockBase is the building block of the Hierarchical Control-Flow Graph.
Definition VPlan.h:94
void setSuccessors(ArrayRef< VPBlockBase * > NewSuccs)
Set each VPBasicBlock in NewSuccss as successor of this VPBlockBase.
Definition VPlan.h:312
VPRegionBlock * getParent()
Definition VPlan.h:189
const VPBasicBlock * getExitingBasicBlock() const
Definition VPlan.cpp:236
size_t getNumSuccessors() const
Definition VPlan.h:240
void setPredecessors(ArrayRef< VPBlockBase * > NewPreds)
Set each VPBasicBlock in NewPreds as predecessor of this VPBlockBase.
Definition VPlan.h:303
const VPBlocksTy & getPredecessors() const
Definition VPlan.h:225
VPlan * getPlan()
Definition VPlan.cpp:211
const std::string & getName() const
Definition VPlan.h:180
void clearSuccessors()
Remove all the successors of this block.
Definition VPlan.h:322
VPBlockBase * getSinglePredecessor() const
Definition VPlan.h:236
void clearPredecessors()
Remove all the predecessor of this block.
Definition VPlan.h:319
const VPBasicBlock * getEntryBasicBlock() const
Definition VPlan.cpp:216
VPBlockBase * getSingleHierarchicalPredecessor()
Definition VPlan.h:276
VPBlockBase * getSingleSuccessor() const
Definition VPlan.h:230
const VPBlocksTy & getSuccessors() const
Definition VPlan.h:214
static auto blocksAs(T &&Range)
Return an iterator range over Range with each block cast to BlockTy.
Definition VPlanUtils.h:379
static void insertOnEdge(VPBlockBase *From, VPBlockBase *To, VPBlockBase *BlockPtr)
Inserts BlockPtr on the edge between From and To.
Definition VPlanUtils.h:398
static bool isLatch(const VPBlockBase *VPB, const VPDominatorTree &VPDT)
Returns true if VPB is a loop latch, using isHeader().
static void insertTwoBlocksAfter(VPBlockBase *IfTrue, VPBlockBase *IfFalse, VPBlockBase *BlockPtr)
Insert disconnected VPBlockBases IfTrue and IfFalse after BlockPtr.
Definition VPlanUtils.h:288
static void connectBlocks(VPBlockBase *From, VPBlockBase *To, unsigned PredIdx=-1u, unsigned SuccIdx=-1u)
Connect VPBlockBases From and To bi-directionally.
Definition VPlanUtils.h:306
static void disconnectBlocks(VPBlockBase *From, VPBlockBase *To)
Disconnect VPBlockBases From and To bi-directionally.
Definition VPlanUtils.h:324
static auto blocksOnly(T &&Range)
Return an iterator range over Range which only includes BlockTy blocks.
Definition VPlanUtils.h:360
static void transferSuccessors(VPBlockBase *Old, VPBlockBase *New)
Transfer successors from Old to New. New must have no successors.
Definition VPlanUtils.h:344
static SmallVector< VPBasicBlock * > blocksInSingleSuccessorChainBetween(VPBasicBlock *FirstBB, VPBasicBlock *LastBB)
Returns the blocks between FirstBB and LastBB, where FirstBB to LastBB forms a single-sucessor chain.
A recipe for generating conditional branches on the bits of a mask.
Definition VPlan.h:3482
RAII object that stores the current insertion point and restores it when the object is destroyed.
VPlan-based builder utility analogous to IRBuilder.
VPDerivedIVRecipe * createDerivedIV(InductionDescriptor::InductionKind Kind, FPMathOperator *FPBinOp, VPValue *Start, VPValue *Current, VPValue *Step)
Convert the input value Current to the corresponding value of an induction with Start and Step values...
VPInstruction * createFirstActiveLane(ArrayRef< VPValue * > Masks, DebugLoc DL=DebugLoc::getUnknown(), const Twine &Name="")
VPInstruction * createAdd(VPValue *LHS, VPValue *RHS, DebugLoc DL=DebugLoc::getUnknown(), const Twine &Name="", VPRecipeWithIRFlags::WrapFlagsTy WrapFlags={false, false})
VPInstruction * createOr(VPValue *LHS, VPValue *RHS, DebugLoc DL=DebugLoc::getUnknown(), const Twine &Name="")
VPInstruction * createLogicalOr(VPValue *LHS, VPValue *RHS, DebugLoc DL=DebugLoc::getUnknown(), const Twine &Name="")
VPInstruction * createNot(VPValue *Operand, DebugLoc DL=DebugLoc::getUnknown(), const Twine &Name="")
VPInstruction * createAnyOfReduction(VPValue *ChainOp, VPValue *TrueVal, VPValue *FalseVal, DebugLoc DL=DebugLoc::getUnknown())
Create an AnyOf reduction pattern: or-reduce ChainOp, freeze the result, then select between TrueVal ...
Definition VPlan.cpp:1646
VPInstruction * createLogicalAnd(VPValue *LHS, VPValue *RHS, DebugLoc DL=DebugLoc::getUnknown(), const Twine &Name="")
VPInstruction * createScalarCast(Instruction::CastOps Opcode, VPValue *Op, Type *ResultTy, DebugLoc DL, const VPIRMetadata &Metadata={})
VPWidenPHIRecipe * createWidenPhi(ArrayRef< VPValue * > IncomingValues, DebugLoc DL=DebugLoc::getUnknown(), const Twine &Name="")
VPValue * createScalarZExtOrTrunc(VPValue *Op, Type *ResultTy, DebugLoc DL)
static VPBuilder getToInsertAfter(VPRecipeBase *R)
Create a VPBuilder to insert after R.
VPWidenCastRecipe * createWidenCast(Instruction::CastOps Opcode, VPValue *Op, Type *ResultTy)
VPInstruction * createICmp(CmpInst::Predicate Pred, VPValue *A, VPValue *B, DebugLoc DL=DebugLoc::getUnknown(), const Twine &Name="")
Create a new ICmp VPInstruction with predicate Pred and operands A and B.
VPInstruction * createSelect(VPValue *Cond, VPValue *TrueVal, VPValue *FalseVal, DebugLoc DL=DebugLoc::getUnknown(), const Twine &Name="", const VPIRFlags &Flags={})
VPExpandSCEVRecipe * createExpandSCEV(const SCEV *Expr)
VPInstruction * createNaryOp(unsigned Opcode, ArrayRef< VPValue * > Operands, Instruction *Inst=nullptr, const VPIRFlags &Flags={}, const VPIRMetadata &MD={}, DebugLoc DL=DebugLoc::getUnknown(), const Twine &Name="", Type *ResultTy=nullptr)
Create an N-ary operation with Opcode, Operands and set Inst as its underlying Instruction.
static VPSingleDefRecipe * createSingleScalarOp(unsigned Opcode, ArrayRef< VPValue * > Operands, VPValue *Mask, const VPIRFlags &Flags, const VPIRMetadata &Metadata, DebugLoc DL, Instruction *UV)
Create a single-scalar recipe with Opcode and Operands without inserting it.
void setInsertPoint(VPBasicBlock *TheBB)
This specifies that created VPInstructions should be appended to the end of the specified block.
unsigned getNumDefinedValues() const
Returns the number of values defined by the VPDef.
Definition VPlanValue.h:578
VPValue * getVPSingleValue()
Returns the only VPValue defined by the VPDef.
Definition VPlanValue.h:551
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
A recipe for converting the input value IV value to the corresponding value of an IV with different s...
Definition VPlan.h:4160
Template specialization of the standard LLVM dominator tree utility for VPBlockBases.
bool properlyDominates(const VPRecipeBase *A, const VPRecipeBase *B) const
A recipe to combine multiple recipes into a single 'expression' recipe, which should be considered a ...
Definition VPlan.h:3527
A pure virtual base class for all recipes modeling header phis, including phis for first order recurr...
Definition VPlan.h:2427
virtual VPValue * getBackedgeValue()
Returns the incoming value from the loop backedge.
Definition VPlan.h:2474
VPValue * getStartValue()
Returns the start value of the phi, if one is set.
Definition VPlan.h:2463
A recipe representing a sequence of load -> update -> store as part of a histogram operation.
Definition VPlan.h:2154
A special type of VPBasicBlock that wraps an existing IR basic block.
Definition VPlan.h:4518
Class to record and manage LLVM IR flags.
Definition VPlan.h:695
static VPIRFlags getDefaultFlags(unsigned Opcode)
Returns default flags for Opcode for opcodes that support it, asserts otherwise.
LLVM_ABI_FOR_TEST FastMathFlags getFastMathFlagsOrNone() const
void dropPoisonGeneratingFlags()
Drop all poison-generating flags.
Definition VPlan.h:893
static LLVM_ABI_FOR_TEST VPIRInstruction * create(Instruction &I)
Create a new VPIRPhi for \I , if it is a PHINode, otherwise create a VPIRInstruction.
Helper to manage IR metadata for recipes.
Definition VPlan.h:1169
void intersect(const VPIRMetadata &MD)
Intersect this VPIRMetadata object with MD, keeping only metadata nodes that are common to both.
This is a concrete Recipe that models a single VPlan-level instruction.
Definition VPlan.h:1224
unsigned getNumOperandsWithoutMask() const
Returns the number of operands, excluding the mask if the VPInstruction is masked.
Definition VPlan.h:1466
@ ExtractLane
Extracts a single lane (first operand) from a set of vector operands.
Definition VPlan.h:1317
@ Unpack
Extracts all lanes from its (non-scalable) vector operand.
Definition VPlan.h:1267
@ ReductionStartVector
Start vector for reductions with 3 operands: the original start value, the identity value for the red...
Definition VPlan.h:1313
@ BuildVector
Creates a fixed-width vector containing all operands.
Definition VPlan.h:1262
@ BuildStructVector
Given operands of (the same) struct type, creates a struct of fixed- width vectors each containing a ...
Definition VPlan.h:1259
@ CanonicalIVIncrementForPart
Definition VPlan.h:1243
@ ComputeReductionResult
Reduce the operands to the final reduction result using the operation specified via the operation's V...
Definition VPlan.h:1270
unsigned getOpcode() const
Definition VPlan.h:1410
const InterleaveGroup< Instruction > * getInterleaveGroup() const
Definition VPlan.h:3086
VPValue * getMask() const
Return the mask used by this recipe.
Definition VPlan.h:3078
ArrayRef< VPValue * > getStoredValues() const
Return the VPValues stored by this interleave group.
Definition VPlan.h:3107
VPInterleaveRecipe is a recipe for transforming an interleave group of load or stores into one wide l...
Definition VPlan.h:3117
void addIncoming(VPValue *IncomingV)
Append IncomingV as an incoming value to the phi-like recipe.
Definition VPlan.h:1657
VPPredInstPHIRecipe is a recipe for generating the phi nodes needed when control converges back from ...
Definition VPlan.h:3685
VPRecipeBase is a base class modeling a sequence of one or more output IR instructions.
Definition VPlan.h:402
VPBasicBlock * getParent()
Definition VPlan.h:474
DebugLoc getDebugLoc() const
Returns the debug location of the recipe.
Definition VPlan.h:552
void moveBefore(VPBasicBlock &BB, iplist< VPRecipeBase >::iterator I)
Unlink this recipe and insert into BB before I.
void insertBefore(VPRecipeBase *InsertPos)
Insert an unlinked recipe into a basic block immediately before the specified recipe.
void insertAfter(VPRecipeBase *InsertPos)
Insert an unlinked Recipe into a basic block immediately after the specified Recipe.
iplist< VPRecipeBase >::iterator eraseFromParent()
This method unlinks 'this' from the containing basic block and deletes it.
Helper class to create VPRecipies from IR instructions.
VPHistogramRecipe * widenIfHistogram(VPInstruction *VPI)
If VPI represents a histogram operation (as determined by LoopVectorizationLegality) make that safe f...
bool prefersVectorizedAddressing() const
Returns true if the target prefers vectorized addressing.
VPRecipeBase * tryToWidenMemory(VPInstruction *VPI, VFRange &Range)
Check if the load or store instruction VPI should widened for Range.Start and potentially masked.
bool replaceWithFinalIfReductionStore(VPInstruction *VPI, VPBuilder &FinalRedStoresBuilder)
If VPI is a store of a reduction into an invariant address, delete it.
VPSingleDefRecipe * handleReplication(VPInstruction *VPI, VFRange &Range)
Build a replicating or single-scalar recipe for VPI.
bool isPredicatedInst(Instruction *I) const
Returns true if I needs to be predicated (i.e.
Type * getScalarType() const
Returns the scalar type of this VPRecipeValue.
Definition VPlanValue.h:354
A recipe for handling reduction phis.
Definition VPlan.h:2842
void setVFScaleFactor(unsigned ScaleFactor)
Set the VFScaleFactor for this reduction phi.
Definition VPlan.h:2893
unsigned getVFScaleFactor() const
Get the factor that the VF of this recipe's output should be scaled by, or 1 if it isn't scaled.
Definition VPlan.h:2886
RecurKind getRecurrenceKind() const
Returns the recurrence kind of the reduction.
Definition VPlan.h:2899
A recipe to represent inloop, ordered or partial reduction operations.
Definition VPlan.h:3210
VPRegionBlock represents a collection of VPBasicBlocks and VPRegionBlocks which form a Single-Entry-S...
Definition VPlan.h:4590
const VPBlockBase * getEntry() const
Definition VPlan.h:4634
bool isReplicator() const
An indicator whether this region is to generate multiple replicated instances of output IR correspond...
Definition VPlan.h:4666
VPRegionValue * getUsedHeaderMask() const
Return the header mask if it exists and is used, or null otherwise.
Definition VPlan.h:4722
VPInstruction * getOrCreateCanonicalIVIncrement()
Get the canonical IV increment instruction if it exists.
Definition VPlan.cpp:868
void setExiting(VPBlockBase *ExitingBlock)
Set ExitingBlock as the exiting VPBlockBase of this VPRegionBlock.
Definition VPlan.h:4651
Type * getCanonicalIVType() const
Return the type of the canonical IV for loop regions.
Definition VPlan.h:4710
void clearCanonicalIVNUW(VPInstruction *Increment)
Unsets NUW for the canonical IV increment Increment, for loop regions.
Definition VPlan.h:4749
VPRegionValue * getCanonicalIV()
Return the canonical induction variable of the region, null for replicating regions.
Definition VPlan.h:4702
const VPBlockBase * getExiting() const
Definition VPlan.h:4646
VPRegionValue * getHeaderMask() const
Return the header mask of the region, or null if not set.
Definition VPlan.h:4715
VPReplicateRecipe replicates a given instruction producing multiple scalar copies of the original sca...
Definition VPlan.h:3374
bool isSingleScalar() const
Returns true if the recipe produces a single scalar value.
Definition VPlan.h:3433
static InstructionCost computeCallCost(Function *CalledFn, Type *ResultTy, ArrayRef< const VPValue * > ArgOps, bool IsSingleScalar, ElementCount VF, VPCostContext &Ctx)
Return the cost of scalarizing a call to CalledFn with argument operands ArgOps for a given VF.
operand_range operandsWithoutMask()
Return the recipe's operands, excluding the mask of a predicated recipe.
Definition VPlan.h:3461
bool isPredicated() const
Definition VPlan.h:3438
VPValue * getMask()
Return the mask of a predicated VPReplicateRecipe.
Definition VPlan.h:3455
Lightweight SCEV-to-VPlan expander.
Definition VPlanUtils.h:226
VPValue * tryToExpand(const SCEV *S)
Try to expand S into recipes and live-ins using the builder.
A recipe for handling phi nodes of integer and floating-point inductions, producing their scalar valu...
Definition VPlan.h:4220
VPSingleDefRecipe is a base class for recipes that model a sequence of one or more output IR that def...
Definition VPlan.h:610
Instruction * getUnderlyingInstr()
Returns the underlying instruction.
Definition VPlan.h:680
VPSingleDefRecipe * clone() override=0
Clone the current recipe.
A symbolic live-in VPValue, used for values like vector trip count, VF, and VFxUF.
Definition VPlanValue.h:217
bool isMaterialized() const
Returns true if this value has been materialized.
Definition VPlanValue.h:235
This class augments VPValue with operands which provide the inverse def-use edges from VPValue's user...
Definition VPlanValue.h:401
operand_range operands()
Definition VPlanValue.h:474
void setOperand(unsigned I, VPValue *New)
Definition VPlanValue.h:447
unsigned getNumOperands() const
Definition VPlanValue.h:441
VPValue * getOperand(unsigned N) const
Definition VPlanValue.h:442
This is the base class of the VPlan Def/Use graph, used for modeling the data flow into,...
Definition VPlanValue.h:50
Type * getScalarType() const
Returns the scalar type of this VPValue, dispatching based on the concrete subclass.
Definition VPlan.cpp:149
Value * getLiveInIRValue() const
Return the underlying IR value for a VPIRValue.
Definition VPlan.cpp:143
bool isDefinedOutsideLoopRegions() const
Returns true if the VPValue is defined outside any loop.
Definition VPlan.cpp:1470
VPRecipeBase * getDefiningRecipe()
Returns the recipe defining this VPValue or nullptr if it is not defined by a recipe,...
Definition VPlan.cpp:130
bool hasMoreThanOneUniqueUser() const
Returns true if the value has more than one unique user.
Definition VPlanValue.h:164
Value * getUnderlyingValue() const
Return the underlying Value attached to this VPValue.
Definition VPlanValue.h:75
bool user_empty() const
Definition VPlanValue.h:161
bool hasOneUse() const
Definition VPlanValue.h:175
void setUnderlyingValue(Value *Val)
Definition VPlanValue.h:209
VPUser * getSingleUser()
Return the single user of this value, or nullptr if there is not exactly one user.
Definition VPlanValue.h:179
void replaceAllUsesWith(VPValue *New)
Definition VPlan.cpp:1473
unsigned getNumUsers() const
Definition VPlanValue.h:115
void replaceUsesWithIf(VPValue *New, llvm::function_ref< bool(VPUser &U, unsigned Idx)> ShouldReplace)
Go through the uses list for this VPValue and make each use point to New if the callback ShouldReplac...
Definition VPlan.cpp:1479
user_range users()
Definition VPlanValue.h:157
A recipe to compute a pointer to the last element of each part of a widened memory access for widened...
Definition VPlan.h:2257
A recipe to compute the pointers for widened memory accesses of SourceElementTy, with the Stride expr...
Definition VPlan.h:2339
A recipe for widening Call instructions using library calls.
Definition VPlan.h:2088
static InstructionCost computeCallCost(Function *Variant, VPCostContext &Ctx)
Return the cost of widening a call using the vector function Variant.
A Recipe for widening the canonical induction variable of the vector loop.
Definition VPlan.h:4103
VPWidenCastRecipe is a recipe to create vector cast instructions.
Definition VPlan.h:1870
Instruction::CastOps getOpcode() const
Definition VPlan.h:1906
A recipe for handling GEP instructions.
Definition VPlan.h:2197
Base class for widened induction (VPWidenIntOrFpInductionRecipe and VPWidenPointerInductionRecipe),...
Definition VPlan.h:2501
VPIRValue * getStartValue() const
Returns the start value of the induction.
Definition VPlan.h:2549
PHINode * getPHINode() const
Returns the underlying PHINode if one exists, or null otherwise.
Definition VPlan.h:2567
VPValue * getStepValue()
Returns the step value of the induction.
Definition VPlan.h:2552
const InductionDescriptor & getInductionDescriptor() const
Returns the induction descriptor for the recipe.
Definition VPlan.h:2572
A recipe for handling phi nodes of integer and floating-point inductions, producing their vector valu...
Definition VPlan.h:2601
VPValue * getSplatVFValue() const
If the recipe has been unrolled, return the VPValue for the induction increment, otherwise return nul...
Definition VPlan.h:2649
TruncInst * getTruncInst()
Returns the first defined value as TruncInst, if it is one or nullptr otherwise.
Definition VPlan.h:2660
VPValue * getLastUnrolledPartOperand()
Returns the VPValue representing the value of this induction at the last unrolled part,...
Definition VPlan.h:2671
A recipe for widening vector intrinsics.
Definition VPlan.h:1917
static InstructionCost computeCallCost(Intrinsic::ID ID, ArrayRef< const VPValue * > Operands, const VPRecipeWithIRFlags &R, ElementCount VF, VPCostContext &Ctx)
Compute the cost of a vector intrinsic with ID and Operands.
static InstructionCost computeMemIntrinsicCost(Intrinsic::ID IID, Type *Ty, bool IsMasked, Align Alignment, VPCostContext &Ctx)
Helper function for computing the cost of vector memory intrinsic.
A common mixin class for widening memory operations.
Definition VPlan.h:3721
virtual VPRecipeBase * getAsRecipe()=0
Return a VPRecipeBase* to the current object.
A recipe for widened phis.
Definition VPlan.h:2729
VPWidenRecipe is a recipe for producing a widened instruction using the opcode and operands of the re...
Definition VPlan.h:1809
InstructionCost computeCost(ElementCount VF, VPCostContext &Ctx) const override
Return the cost of this VPWidenRecipe.
VPWidenRecipe * clone() override
Clone the current recipe.
Definition VPlan.h:1830
unsigned getOpcode() const
Definition VPlan.h:1849
VPlan models a candidate for vectorization, encoding various decisions take to produce efficient outp...
Definition VPlan.h:4769
VPIRValue * getLiveIn(Value *V) const
Return the live-in VPIRValue for V, if there is one or nullptr otherwise.
Definition VPlan.h:5101
bool hasVF(ElementCount VF) const
Definition VPlan.h:4994
const DataLayout & getDataLayout() const
Definition VPlan.h:4976
LLVMContext & getContext() const
Definition VPlan.h:4972
VPBasicBlock * getEntry()
Definition VPlan.h:4865
bool hasScalableVF() const
Definition VPlan.h:4995
VPValue * getTripCount() const
The trip count of the original loop.
Definition VPlan.h:4930
VPValue * getOrCreateBackedgeTakenCount()
The backedge taken count of the original loop.
Definition VPlan.h:4951
iterator_range< SmallSetVector< ElementCount, 2 >::iterator > vectorFactors() const
Returns an iterator range over all VFs of the plan.
Definition VPlan.h:5001
VPIRValue * getFalse()
Return a VPIRValue wrapping i1 false.
Definition VPlan.h:5067
VPSymbolicValue & getVFxUF()
Returns VF * UF of the vector loop region.
Definition VPlan.h:4970
VPIRValue * getAllOnesValue(Type *Ty)
Return a VPIRValue wrapping the AllOnes value of type Ty.
Definition VPlan.h:5073
VPRegionBlock * createReplicateRegion(VPBlockBase *Entry, VPBlockBase *Exiting, const std::string &Name="")
Create a new replicate region with Entry, Exiting and Name.
Definition VPlan.h:5150
auto getLiveIns() const
Return the list of live-in VPValues available in the VPlan.
Definition VPlan.h:5104
bool hasUF(unsigned UF) const
Definition VPlan.h:5019
VPIRValue * getPoison(Type *Ty)
Return a VPIRValue wrapping a poison value of type Ty.
Definition VPlan.h:5095
ArrayRef< VPIRBasicBlock * > getExitBlocks() const
Return an ArrayRef containing VPIRBasicBlocks wrapping the exit blocks of the original scalar loop.
Definition VPlan.h:4924
VPSymbolicValue & getVectorTripCount()
The vector trip count.
Definition VPlan.h:4960
VPValue * getBackedgeTakenCount() const
Definition VPlan.h:4957
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:5044
VPIRValue * getZero(Type *Ty)
Return a VPIRValue wrapping the null value of type Ty.
Definition VPlan.h:5070
void setVF(ElementCount VF)
Definition VPlan.h:4982
bool isUnrolled() const
Returns true if the VPlan already has been unrolled, i.e.
Definition VPlan.h:5035
LLVM_ABI_FOR_TEST VPRegionBlock * getVectorLoopRegion()
Returns the VPRegionBlock of the vector loop.
Definition VPlan.cpp:1065
unsigned getConcreteUF() const
Returns the concrete UF of the plan, after unrolling.
Definition VPlan.h:5022
void resetTripCount(VPValue *NewTripCount)
Resets the trip count for the VPlan.
Definition VPlan.h:4944
VPBasicBlock * getMiddleBlock()
Returns the 'middle' block of the plan, that is the block that selects whether to execute the scalar ...
Definition VPlan.h:4900
VPBasicBlock * createVPBasicBlock(const Twine &Name, VPRecipeBase *Recipe=nullptr)
Create a new VPBasicBlock with Name and containing Recipe if present.
Definition VPlan.h:5127
VPIRValue * getTrue()
Return a VPIRValue wrapping i1 true.
Definition VPlan.h:5064
VPBasicBlock * getVectorPreheader() const
Returns the preheader of the vector loop region, if one exists, or null otherwise.
Definition VPlan.h:4870
VPSymbolicValue & getUF()
Returns the UF of the vector loop region.
Definition VPlan.h:4967
bool hasScalarVFOnly() const
Definition VPlan.h:5012
VPBasicBlock * getScalarPreheader() const
Return the VPBasicBlock for the preheader of the scalar loop.
Definition VPlan.h:4914
bool hasTailFolded() const
Returns true if the vector loop region is tail-folded.
Definition VPlan.h:4886
VPSymbolicValue & getVF()
Returns the VF of the vector loop region.
Definition VPlan.h:4963
bool hasScalarTail() const
Returns true if the scalar tail may execute after the vector loop, i.e.
Definition VPlan.h:5192
LLVM_ABI_FOR_TEST VPlan * duplicate()
Clone the current VPlan, update all VPValues of the new VPlan and cloned recipes to refer to the clon...
Definition VPlan.cpp:1221
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:5078
LLVM Value Representation.
Definition Value.h:75
Type * getType() const
All values are typed, get the type of this value.
Definition Value.h:255
iterator_range< user_iterator > users()
Definition Value.h:426
bool hasName() const
Definition Value.h:261
LLVM_ABI StringRef getName() const
Return a constant reference to the value's name.
Definition Value.cpp:319
static LLVM_ABI VectorType * get(Type *ElementType, ElementCount EC)
This static method is the primary way to construct an VectorType.
constexpr bool hasKnownScalarFactor(const FixedOrScalableQuantity &RHS) const
Returns true if there exists a value X where RHS.multiplyCoefficientBy(X) will result in a value whos...
Definition TypeSize.h:269
constexpr ScalarTy getFixedValue() const
Definition TypeSize.h:200
constexpr ScalarTy getKnownScalarFactor(const FixedOrScalableQuantity &RHS) const
Returns a value X where RHS.multiplyCoefficientBy(X) will result in a value whose quantity matches ou...
Definition TypeSize.h:277
static constexpr bool isKnownLT(const FixedOrScalableQuantity &LHS, const FixedOrScalableQuantity &RHS)
Definition TypeSize.h:216
constexpr bool isScalable() const
Returns whether the quantity is scaled by a runtime quantity (vscale).
Definition TypeSize.h:168
constexpr LeafTy multiplyCoefficientBy(ScalarTy RHS) const
Definition TypeSize.h:256
constexpr bool isFixed() const
Returns true if the quantity is not scaled by vscale.
Definition TypeSize.h:171
constexpr ScalarTy getKnownMinValue() const
Returns the minimum value this quantity can represent.
Definition TypeSize.h:165
An efficient, type-erasing, non-owning reference to a callable.
self_iterator getIterator()
Definition ilist_node.h:123
Changed
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
LLVM_ABI APInt RoundingUDiv(const APInt &A, const APInt &B, APInt::Rounding RM)
Return A unsign-divided by B, rounded by the given rounding mode.
Definition APInt.cpp:2798
unsigned ID
LLVM IR allows to use arbitrary numbers as calling convention identifiers.
Definition CallingConv.h:24
@ C
The default llvm calling convention, compatible with C.
Definition CallingConv.h:34
std::variant< std::monostate, Loc::Single, Loc::Multi, Loc::MMI, Loc::EntryValue > Variant
Alias for the std::variant specialization base class of DbgVariable.
Definition DwarfDebug.h:190
SpecificConstantMatch m_ZeroInt()
Convenience matchers for specific integer values.
BinaryOp_match< SrcTy, SpecificConstantMatch, TargetOpcode::G_XOR, true > m_Not(const SrcTy &&Src)
Matches a register not-ed by a G_XOR.
OneUse_match< SubPat > m_OneUse(const SubPat &SP)
match_combine_or< Ty... > m_CombineOr(const Ty &...Ps)
Combine pattern matchers matching any of Ps patterns.
cst_pred_ty< is_all_ones > m_AllOnes()
Match an integer or vector with all bits set.
auto m_Cmp()
Matches any compare instruction and ignore it.
BinaryOp_match< LHS, RHS, Instruction::Add > m_Add(const LHS &L, const RHS &R)
ap_match< APInt > m_APInt(const APInt *&Res)
Match a ConstantInt or splatted ConstantVector, binding the specified pointer to the contained APInt.
CastInst_match< OpTy, TruncInst > m_Trunc(const OpTy &Op)
Matches Trunc.
LogicalOp_match< LHS, RHS, Instruction::And > m_LogicalAnd(const LHS &L, const RHS &R)
Matches L && R either in the form of L & R or L ?
specific_intval< false > m_SpecificInt(const APInt &V)
Match a specific integer value or vector with all elements equal to the value.
BinaryOp_match< LHS, RHS, Instruction::FMul > m_FMul(const LHS &L, const RHS &R)
bool match(Val *V, const Pattern &P)
match_deferred< Value > m_Deferred(Value *const &V)
Like m_Specific(), but works if the specific value to match is determined as part of the same match()...
specificval_ty m_Specific(const Value *V)
Match if we have a specific specified value.
auto match_fn(const Pattern &P)
A match functor that can be used as a UnaryPredicate in functional algorithms like all_of.
cst_pred_ty< is_one > m_One()
Match an integer 1 or a vector with all elements equal to 1.
ThreeOps_match< Cond, LHS, RHS, Instruction::Select > m_Select(const Cond &C, const LHS &L, const RHS &R)
Matches SelectInst.
SpecificCmpClass_match< LHS, RHS, CmpInst > m_SpecificCmp(CmpPredicate MatchPred, const LHS &L, const RHS &R)
BinaryOp_match< LHS, RHS, Instruction::Mul > m_Mul(const LHS &L, const RHS &R)
CastInst_match< OpTy, FPExtInst > m_FPExt(const OpTy &Op)
SpecificCmpClass_match< LHS, RHS, ICmpInst > m_SpecificICmp(CmpPredicate MatchPred, const LHS &L, const RHS &R)
BinaryOp_match< LHS, RHS, Instruction::UDiv > m_UDiv(const LHS &L, const RHS &R)
SelectLike_match< CondTy, LTy, RTy > m_SelectLike(const CondTy &C, const LTy &TrueC, const RTy &FalseC)
Matches a value that behaves like a boolean-controlled select, i.e.
BinaryOp_match< LHS, RHS, Instruction::Add, true > m_c_Add(const LHS &L, const RHS &R)
Matches a Add with LHS and RHS in either order.
auto m_Intrinsic(const Ts &...Ops)
Match intrinsic calls like this: m_Intrinsic<Intrinsic::fabs>(m_Value(X))
CmpClass_match< LHS, RHS, ICmpInst > m_ICmp(CmpPredicate &Pred, const LHS &L, const RHS &R)
match_combine_or< CastInst_match< OpTy, ZExtInst >, CastInst_match< OpTy, SExtInst > > m_ZExtOrSExt(const OpTy &Op)
FNeg_match< OpTy > m_FNeg(const OpTy &X)
Match 'fneg X' as 'fsub -0.0, X'.
BinaryOp_match< LHS, RHS, Instruction::FAdd, true > m_c_FAdd(const LHS &L, const RHS &R)
Matches FAdd with LHS and RHS in either order.
LogicalOp_match< LHS, RHS, Instruction::And, true > m_c_LogicalAnd(const LHS &L, const RHS &R)
Matches L && R with LHS and RHS in either order.
auto m_LogicalAnd()
Matches L && R where L and R are arbitrary values.
CastInst_match< OpTy, SExtInst > m_SExt(const OpTy &Op)
Matches SExt.
BinaryOp_match< LHS, RHS, Instruction::Mul, true > m_c_Mul(const LHS &L, const RHS &R)
Matches a Mul with LHS and RHS in either order.
BinaryOp_match< LHS, RHS, Instruction::Sub > m_Sub(const LHS &L, const RHS &R)
auto m_ConstantInt()
Match an arbitrary ConstantInt and ignore it.
bind_cst_ty m_scev_APInt(const APInt *&C)
Match an SCEV constant and bind it to an APInt.
specificloop_ty m_SpecificLoop(const Loop *L)
bool match(const SCEV *S, const Pattern &P)
SCEVAffineAddRec_match< Op0_t, Op1_t, match_isa< const Loop > > m_scev_AffineAddRec(const Op0_t &Op0, const Op1_t &Op1)
VPInstruction_match< VPInstruction::ExtractLastLane, VPInstruction_match< VPInstruction::ExtractLastPart, Op0_t > > m_ExtractLastLaneOfLastPart(const Op0_t &Op0)
AllRecipe_commutative_match< Instruction::And, Op0_t, Op1_t > m_c_BinaryAnd(const Op0_t &Op0, const Op1_t &Op1)
Match a binary AND operation.
AllRecipe_match< Instruction::Or, Op0_t, Op1_t > m_BinaryOr(const Op0_t &Op0, const Op1_t &Op1)
Match a binary OR operation.
VPInstruction_match< VPInstruction::AnyOf > m_AnyOf()
AllRecipe_commutative_match< Instruction::Or, Op0_t, Op1_t > m_c_BinaryOr(const Op0_t &Op0, const Op1_t &Op1)
VPInstruction_match< VPInstruction::ComputeReductionResult, Op0_t > m_ComputeReductionResult(const Op0_t &Op0)
auto m_WidenAnyExtend(const Op0_t &Op0)
match_bind< VPIRValue > m_VPIRValue(VPIRValue *&V)
Match a VPIRValue.
auto m_VPPhi(const Op0_t &Op0, const Op1_t &Op1)
VPInstruction_match< VPInstruction::BranchOnTwoConds > m_BranchOnTwoConds()
AllRecipe_match< Opcode, Op0_t, Op1_t > m_Binary(const Op0_t &Op0, const Op1_t &Op1)
VPInstruction_match< VPInstruction::LastActiveLane, Op0_t > m_LastActiveLane(const Op0_t &Op0)
auto m_WidenIntrinsic(const T &...Ops)
canonical_widen_iv_match m_CanonicalWidenIV()
VPInstruction_match< VPInstruction::ExitingIVValue, Op0_t > m_ExitingIVValue(const Op0_t &Op0)
VPInstruction_match< Instruction::ExtractElement, Op0_t, Op1_t > m_ExtractElement(const Op0_t &Op0, const Op1_t &Op1)
specific_intval< 1 > m_False()
VPInstruction_match< VPInstruction::ExtractLastLane, Op0_t > m_ExtractLastLane(const Op0_t &Op0)
VPInstruction_match< VPInstruction::ActiveLaneMask, Op0_t, Op1_t, Op2_t > m_ActiveLaneMask(const Op0_t &Op0, const Op1_t &Op1, const Op2_t &Op2)
match_bind< VPSingleDefRecipe > m_VPSingleDefRecipe(VPSingleDefRecipe *&V)
Match a VPSingleDefRecipe, capturing if we match.
VPInstruction_match< VPInstruction::BranchOnCount > m_BranchOnCount()
auto m_GetElementPtr(const Op0_t &Op0, const Op1_t &Op1)
specific_intval< 1 > m_True()
auto m_VPValue()
Match an arbitrary VPValue and ignore it.
VPInstruction_match< VPInstruction::ExtractLastPart, Op0_t > m_ExtractLastPart(const Op0_t &Op0)
VPRecipeBase * findUserOf(VPValue *V, const MatchT &P)
If V is used by a recipe matching pattern P, return it.
VPInstruction_match< VPInstruction::Broadcast, Op0_t > m_Broadcast(const Op0_t &Op0)
header_mask_match m_HeaderMask()
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)
auto m_DerivedIV(const Op0_t &Op0, const Op1_t &Op1, const Op2_t &Op2)
VPInstruction_match< VPInstruction::BranchOnCond > m_BranchOnCond()
VPInstruction_match< VPInstruction::ExtractLane, Op0_t, Op1_t > m_ExtractLane(const Op0_t &Op0, const Op1_t &Op1)
auto m_AnyNeg(const Op0_t &Op0)
VPInstruction_match< VPInstruction::Reverse, Op0_t > m_Reverse(const Op0_t &Op0)
NodeAddr< DefNode * > Def
Definition RDFGraph.h:386
bool isSingleScalar(const VPValue *VPV)
Returns true if VPV is a single scalar, either because it produces the same value for all lanes or on...
VPValue * getOrCreateVPValueForSCEVExpr(VPlan &Plan, const SCEV *Expr)
Get or create a VPValue that corresponds to the expansion of Expr.
bool cannotHoistOrSinkRecipe(const VPRecipeBase &R, bool Sinking=false)
Return true if we do not know how to (mechanically) hoist or sink R.
unsigned getOpcode(const VPValue *V)
Return the instruction opcode for the recipe defining V or 0 for unsupported recipes and VPValues not...
VPInstruction * findComputeReductionResult(VPReductionPHIRecipe *PhiR)
Find the ComputeReductionResult recipe for PhiR, looking through selects inserted for predicated redu...
VPInstruction * findCanonicalIVIncrement(VPlan &Plan)
Find the canonical IV increment of Plan's vector loop region.
std::optional< MemoryLocation > getMemoryLocation(const VPRecipeBase &R)
Return a MemoryLocation for R with noalias metadata populated from R, if the recipe is supported and ...
bool onlyFirstLaneUsed(const VPValue *Def)
Returns true if only the first lane of Def is used.
VPIRValue * tryToFoldLiveIns(VPSingleDefRecipe &R, ArrayRef< VPValue * > Operands, const DataLayout &DL)
Try to fold R using InstSimplifyFolder.
VPValue * findIncomingAliasMask(const VPlan &Plan)
Finds the incoming alias-mask within the vector preheader.
void recursivelyDeleteDeadRecipes(VPValue *V)
Recursively delete V and any of its operands that become dead.
bool doesGeneratePerAllLanes(const VPRecipeBase *R)
Returns true if R produces scalar values for all VF lanes.
bool isDeadRecipe(VPRecipeBase &R)
Returns true if R is dead, i.e.
VPRecipeBase * findRecipe(VPValue *Start, PredT Pred)
Search Start's users for a recipe satisfying Pred, looking through recipes with definitions.
Definition VPlanUtils.h:146
bool onlyScalarValuesUsed(const VPValue *Def)
Returns true if only scalar values of Def are used by all users.
bool isUniformAcrossVFsAndUFs(const VPValue *V)
Checks if V is uniform across all VF lanes and UF parts.
bool isUsedByLoadStoreAddress(const VPValue *V)
Returns true if V is used as part of the address of another load or store.
std::optional< std::pair< bool, unsigned > > getOpcodeOrIntrinsicID(const VPValue *V)
Get the instruction opcode or intrinsic ID for the recipe defining V.
GEPNoWrapFlags getGEPFlagsForPtr(VPValue *Ptr)
Returns the GEP nowrap flags for Ptr, looking through pointer casts mirroring Value::stripPointerCast...
const SCEV * getSCEVExprForVPValue(const VPValue *V, PredicatedScalarEvolution &PSE, const Loop *L=nullptr)
Return the SCEV expression for V.
void pullOutPermutations(VPlan &Plan, Match_t Perm, Builder Build)
Removes the permutation pattern Perm from any elementwise operations in the plan, by constructing a n...
Definition VPlanUtils.h:212
SmallVector< VPUser * > collectUsersRecursively(VPValue *V)
Collect all users of V, looking through recipes that define other values.
This is an optimization pass for GlobalISel generic memory operations.
auto drop_begin(T &&RangeOrContainer, size_t N=1)
Return a range covering RangeOrContainer with the first N elements excluded.
Definition STLExtras.h:315
SmallVector< VPBasicBlock * > vp_rpo_plain_cfg_loop_body(VPBasicBlock *Header)
Returns the VPBasicBlocks forming the loop body of a plain (pre-region) VPlan in reverse post-order s...
Definition VPlanCFG.h:262
@ Offset
Definition DWP.cpp:578
constexpr auto not_equal_to(T &&Arg)
Functor variant of std::not_equal_to that can be used as a UnaryPredicate in functional algorithms li...
Definition STLExtras.h:2180
void stable_sort(R &&Range)
Definition STLExtras.h:2116
auto min_element(R &&Range)
Provide wrappers to std::min_element which take ranges instead of having to pass begin/end explicitly...
Definition STLExtras.h:2078
bool all_of(R &&range, UnaryPredicate P)
Provide wrappers to std::all_of which take ranges instead of having to pass begin/end explicitly.
Definition STLExtras.h:1739
auto size(R &&Range, std::enable_if_t< std::is_base_of< std::random_access_iterator_tag, typename std::iterator_traits< decltype(Range.begin())>::iterator_category >::value, void > *=nullptr)
Get the size of a range.
Definition STLExtras.h:1669
LLVM_ABI Intrinsic::ID getVectorIntrinsicIDForCall(const CallInst *CI, const TargetLibraryInfo *TLI)
Returns intrinsic ID for call.
detail::zippy< detail::zip_first, T, U, Args... > zip_equal(T &&t, U &&u, Args &&...args)
zip iterator that assumes that all iteratees have the same length.
Definition STLExtras.h:840
DenseMap< const Value *, const SCEV * > ValueToSCEVMapTy
auto enumerate(FirstRange &&First, RestRanges &&...Rest)
Given two or more input ranges, returns a new range whose values are tuples (A, B,...
Definition STLExtras.h:2554
decltype(auto) dyn_cast(const From &Val)
dyn_cast<X> - Return the argument parameter cast to the specified type.
Definition Casting.h:643
const Value * getLoadStorePointerOperand(const Value *V)
A helper function that returns the pointer operand of a load or store instruction.
@ Load
The value being inserted comes from a load (InsertElement only).
@ Store
The extracted value is stored (ExtractElement only).
constexpr from_range_t from_range
iterator_range< T > make_range(T x, T y)
Convenience function for iterating over sub-ranges.
void append_range(Container &C, Range &&R)
Wrapper function to append range R to container C.
Definition STLExtras.h:2208
iterator_range< early_inc_iterator_impl< detail::IterOfRange< RangeT > > > make_early_inc_range(RangeT &&Range)
Make a range that does early increment to allow mutation of the underlying range without disrupting i...
Definition STLExtras.h:633
auto cast_or_null(const Y &Val)
Definition Casting.h:714
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
constexpr auto bind_back(FnT &&Fn, BindArgsT &&...BindArgs)
C++23 bind_back.
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
constexpr auto equal_to(T &&Arg)
Functor variant of std::equal_to that can be used as a UnaryPredicate in functional algorithms like a...
Definition STLExtras.h:2173
bool operator==(const AddressRangeValuePair &LHS, const AddressRangeValuePair &RHS)
SmallVector< VPRegisterUsage, 8 > calculateRegisterUsageForPlan(VPlan &Plan, ArrayRef< ElementCount > VFs, const TargetTransformInfo &TTI, const SmallPtrSetImpl< const Value * > &ValuesToIgnore)
Estimate the register usage for Plan and vectorization factors in VFs by calculating the highest numb...
auto map_range(ContainerTy &&C, FuncTy F)
Return a range that applies F to the elements of C.
Definition STLExtras.h:365
detail::concat_range< ValueT, RangeTs... > concat(RangeTs &&...Ranges)
Returns a concatenated range across two or more ranges.
Definition STLExtras.h:1151
uint64_t PowerOf2Ceil(uint64_t A)
Returns the power of two which is greater than or equal to the given value.
Definition MathExtras.h:386
auto dyn_cast_or_null(const Y &Val)
Definition Casting.h:753
void erase(Container &C, ValueType V)
Wrapper function to remove a value from a container:
Definition STLExtras.h:2200
bool any_of(R &&range, UnaryPredicate P)
Provide wrappers to std::any_of which take ranges instead of having to pass begin/end explicitly.
Definition STLExtras.h:1746
auto reverse(ContainerTy &&C)
Definition STLExtras.h:407
constexpr size_t range_size(R &&Range)
Returns the size of the Range, i.e., the number of elements.
Definition STLExtras.h:1694
void sort(IteratorTy Start, IteratorTy End)
Definition STLExtras.h:1636
bool hasIrregularType(Type *Ty, const DataLayout &DL)
A helper function that returns true if the given type is irregular.
LLVM_ABI_FOR_TEST cl::opt< bool > EnableWideActiveLaneMask
UncountableExitStyle
Different methods of handling early exits.
Definition VPlan.h:79
@ MaskedHandleExitInScalarLoop
All memory operations other than the load(s) required to determine whether an uncountable exit occurr...
Definition VPlan.h:89
bool none_of(R &&Range, UnaryPredicate P)
Provide wrappers to std::none_of which take ranges instead of having to pass begin/end explicitly.
Definition STLExtras.h:1753
SmallVector< ValueTypeFromRangeType< R >, Size > to_vector(R &&Range)
Given a range of type R, iterate the entire range and return a SmallVector with elements of the vecto...
iterator_range< filter_iterator< detail::IterOfRange< RangeT >, PredicateT > > make_filter_range(RangeT &&Range, PredicateT Pred)
Convenience function that takes a range of elements and a predicate, and return a new filter_iterator...
Definition STLExtras.h:551
bool canConstantBeExtended(const APInt *C, Type *NarrowType, TTI::PartialReductionExtendKind ExtKind)
Check if a constant CI can be safely treated as having been extended from a narrower type with the gi...
Definition VPlan.cpp:1864
T * find_singleton(R &&Range, Predicate P, bool AllowRepeats=false)
Return the single value in Range that satisfies P(<member of Range> *, AllowRepeats)->T * returning n...
Definition STLExtras.h:1837
class LLVM_GSL_OWNER SmallVector
Forward declaration of SmallVector so that calculateSmallVectorDefaultInlinedElements can reference s...
bool isa(const From &Val)
isa<X> - Return true if the parameter to the template is an instance of one of the template type argu...
Definition Casting.h:547
auto drop_end(T &&RangeOrContainer, size_t N=1)
Return a range covering RangeOrContainer with the last N elements excluded.
Definition STLExtras.h:322
@ Other
Any other memory.
Definition ModRef.h:68
TargetTransformInfo TTI
RecurKind
These are the kinds of recurrences that we support.
@ UMin
Unsigned integer min implemented in terms of select(cmp()).
@ FindIV
FindIV reduction with select(icmp(),x,y) where one of (x,y) is a loop induction variable (increasing ...
@ Or
Bitwise or logical OR of integers.
@ Mul
Product of integers.
@ FSub
Subtraction of floats.
@ FMul
Product of floats.
@ SMax
Signed integer max implemented in terms of select(cmp()).
@ SMin
Signed integer min implemented in terms of select(cmp()).
@ Sub
Subtraction of integers.
@ Add
Sum of integers.
@ AddChainWithSubs
A chain of adds and subs.
@ FAdd
Sum of floats.
@ UMax
Unsigned integer max implemented in terms of select(cmp()).
LLVM_ABI Value * getRecurrenceIdentity(RecurKind K, Type *Tp, FastMathFlags FMF)
Given information about an recurrence kind, return the identity for the @llvm.vector....
LLVM_ABI BasicBlock * SplitBlock(BasicBlock *Old, BasicBlock::iterator SplitPt, DominatorTree *DT, LoopInfo *LI=nullptr, MemorySSAUpdater *MSSAU=nullptr, const Twine &BBName="")
Split the specified block at the specified instruction.
auto count(R &&Range, const E &Element)
Wrapper function around std::count to count the number of times an element Element occurs in the give...
Definition STLExtras.h:2012
DWARFExpression::Operation Op
auto max_element(R &&Range)
Provide wrappers to std::max_element which take ranges instead of having to pass begin/end explicitly...
Definition STLExtras.h:2088
ArrayRef(const T &OneElt) -> ArrayRef< T >
auto make_second_range(ContainerTy &&c)
Given a container of pairs, return a range over the second elements.
Definition STLExtras.h:1409
auto count_if(R &&Range, UnaryPredicate P)
Wrapper function around std::count_if to count the number of times an element satisfying a given pred...
Definition STLExtras.h:2019
decltype(auto) cast(const From &Val)
cast<X> - Return the argument parameter cast to the specified type.
Definition Casting.h:559
auto find_if(R &&Range, UnaryPredicate P)
Provide wrappers to std::find_if which take ranges instead of having to pass begin/end explicitly.
Definition STLExtras.h:1772
bool is_contained(R &&Range, const E &Element)
Returns true if Element is found in Range.
Definition STLExtras.h:1947
Type * getLoadStoreType(const Value *I)
A helper function that returns the type of a load or store instruction.
RelativeUniformCounterPtr ValuesPtrExpr VTableAddr Next
Definition InstrProf.h:147
bool all_equal(std::initializer_list< T > Values)
Returns true if all Values in the initializer lists are equal or the list.
Definition STLExtras.h:2166
hash_code hash_combine(const Ts &...args)
Combine values into a single hash_code.
Definition Hashing.h:305
LLVM_ABI std::optional< int64_t > getStrideFromAddRec(const SCEVAddRecExpr *AR, const Loop *Lp, Type *AccessTy, Value *Ptr, PredicatedScalarEvolution &PSE)
If AR is an affine AddRec for Lp with a constant step, return the step in units of AccessTy's allocat...
bool equal(L &&LRange, R &&RRange)
Wrapper function around std::equal to detect if pair-wise elements between two ranges are the same.
Definition STLExtras.h:2146
Type * toVectorTy(Type *Scalar, ElementCount EC)
A helper function for converting Scalar types to vector types.
LLVM_ABI bool isDereferenceableAndAlignedInLoop(LoadInst *LI, Loop *L, ScalarEvolution &SE, DominatorTree &DT, AssumptionCache *AC=nullptr, SmallVectorImpl< const SCEVPredicate * > *Predicates=nullptr)
Return true if we can prove that the given load (which is assumed to be within the specified loop) wo...
Definition Loads.cpp:304
constexpr detail::IsaCheckPredicate< Types... > IsaPred
Function object wrapper for the llvm::isa type check.
Definition Casting.h:866
hash_code hash_combine_range(InputIteratorT first, InputIteratorT last)
Compute a hash_code for a sequence of values.
Definition Hashing.h:285
void swap(llvm::BitVector &LHS, llvm::BitVector &RHS)
Implement std::swap in terms of BitVector swap.
Definition BitVector.h:880
#define N
VPBasicBlock * EarlyExitingVPBB
VPIRBasicBlock * EarlyExitVPBB
This struct is a compact representation of a valid (non-zero power of two) alignment.
Definition Alignment.h:39
An information struct used to provide DenseMap with the various necessary components for a given valu...
This reduction is unordered with the partial result scaled down by some factor.
Definition VPlan.h:2824
Holds the VFShape for a specific scalar to vector function mapping.
Encapsulates information needed to describe a parameter.
A range of powers-of-2 vectorization factors with fixed start and adjustable end.
Struct to hold various analysis needed for cost computations.
static bool isFreeScalarIntrinsic(Intrinsic::ID ID)
Returns true if ID is a pseudo intrinsic that is dropped via scalarization rather than widened.
Definition VPlan.cpp:1960
bool isMaskRequired(Instruction *I) const
Forwards to LoopVectorizationCostModel::isMaskRequired.
PredicatedScalarEvolution & PSE
bool willBeScalarized(Instruction *I, ElementCount VF) const
Returns true if I is known to be scalarized at VF.
TargetTransformInfo::TargetCostKind CostKind
const TargetLibraryInfo & TLI
const TargetTransformInfo & TTI
A VPValue representing a live-in from the input IR or a constant.
Definition VPlanValue.h:279
Type * getType() const
Returns the type of the underlying IR value.
Definition VPlan.cpp:147
A struct that represents some properties of the register usage of a loop.
SmallMapVector< unsigned, unsigned, 4 > MaxLocalUsers
Holds the maximum number of concurrent live intervals in the loop.
InstructionCost spillCost(const TargetTransformInfo &TTI, TargetTransformInfo::TargetCostKind CostKind, unsigned OverrideMaxNumRegs=0) const
Calculate the estimated cost of any spills due to using more registers than the number available for ...
A recipe for widening load operations, using the address to load from and an optional mask.
Definition VPlan.h:3785
A recipe for widening store operations, using the stored value, the address to store to and an option...
Definition VPlan.h:3884
static VPValue * materializeAliasMask(VPlan &Plan, VPBasicBlock *AliasCheckVPBB, ArrayRef< PointerDiffInfo > DiffChecks)
Materializes within the AliasCheckVPBB block.
static LLVM_ABI_FOR_TEST bool tryToConvertVPInstructionsToVPRecipes(VPlan &Plan, const TargetLibraryInfo &TLI)
Replaces the VPInstructions in Plan with corresponding widen recipes.
static decltype(auto) runPass(StringRef PassName, PassTy &&Pass, VPlan &Plan, ArgsTy &&...Args)
Helper to run a VPlan pass Pass on VPlan, forwarding extra arguments to the pass.
static void expandSCEVsToVPInstructions(VPlan &Plan, ScalarEvolution &SE)
Try to expand VPExpandSCEVRecipes in Plan's entry block to VPInstructions.
static void materializeBroadcasts(VPlan &Plan)
Add explicit broadcasts for live-ins and VPValues defined in Plan's entry block if they are used as v...
static void materializePacksAndUnpacks(VPlan &Plan)
Add explicit Build[Struct]Vector recipes to Pack multiple scalar values into vectors and Unpack recip...
static void createInterleaveGroups(VPlan &Plan, const SmallPtrSetImpl< const InterleaveGroup< Instruction > * > &InterleaveGroups, const bool &EpilogueAllowed)
static void materializeFactors(VPlan &Plan, VPBasicBlock *VectorPH, ElementCount VF)
Materialize UF, VF and VFxUF to be computed explicitly using VPInstructions.
static void materializeBackedgeTakenCount(VPlan &Plan, VPBasicBlock *VectorPH)
Materialize the backedge-taken count to be computed explicitly using VPInstructions.
static void replaceWideCanonicalIVWithWideIV(VPlan &Plan, ScalarEvolution &SE, const TargetTransformInfo &TTI, TargetTransformInfo::TargetCostKind CostKind, ElementCount VF, unsigned UF, const SmallPtrSetImpl< const Value * > &ValuesToIgnore)
Replace a VPWidenCanonicalIVRecipe if it is present in Plan, with a VPWidenIntOrFpInductionRecipe,...
static void createAndOptimizeReplicateRegions(VPlan &Plan)
Wrap predicated VPReplicateRecipes with a mask operand in an if-then region block and remove the mask...
static void materializeHeaderMask(VPlan &Plan, bool UseActiveLaneMask, bool UseActiveLaneMaskForControlFlow)
Materialize the abstract header mask of the loop region into concrete recipes: an active-lane-mask if...
static void addBranchWeightToMiddleTerminator(VPlan &Plan, ElementCount VF, std::optional< unsigned > VScaleForTuning)
Add branch weight metadata, if the Plan's middle block is terminated by a BranchOnCond recipe.
static std::unique_ptr< VPlan > narrowInterleaveGroups(VPlan &Plan, const TargetTransformInfo &TTI)
Try to find a single VF among Plan's VFs for which all interleave groups (with known minimum VF eleme...
static void optimizeInductionLiveOutUsers(VPlan &Plan, PredicatedScalarEvolution &PSE)
If there's a single exit block, optimize its phi recipes that use exiting IV values by feeding them p...
static void materializeAliasMaskCheckBlock(VPlan &Plan, ArrayRef< PointerDiffInfo > DiffChecks, bool HasBranchWeights)
Materializes the alias mask within a check block before the loop.
static DenseMap< const SCEV *, Value * > expandSCEVs(VPlan &Plan, ScalarEvolution &SE)
Expand remaining VPExpandSCEVRecipes in Plan's entry block using SCEVExpander.
static void convertToConcreteRecipes(VPlan &Plan)
Lower abstract recipes to concrete ones, that can be codegen'd.
static void makeMemOpWideningDecisions(VPlan &Plan, VFRange &Range, VPRecipeBuilder &RecipeBuilder, VPCostContext &CostCtx)
Convert load/store VPInstructions in Plan into widened or replicate recipes.
static void expandBranchOnTwoConds(VPlan &Plan)
Expand BranchOnTwoConds instructions into explicit CFG with BranchOnCond instructions.
static void materializeVectorTripCount(VPlan &Plan, VPBasicBlock *VectorPHVPBB, bool TailByMasking, bool RequiresScalarEpilogue, VPValue *Step, std::optional< uint64_t > MaxRuntimeStep=std::nullopt)
Materialize vector trip count computations to a set of VPInstructions.
static void hoistPredicatedLoads(VPlan &Plan, PredicatedScalarEvolution &PSE, const Loop *L)
Hoist predicated loads from the same address to the loop entry block, if they are guaranteed to execu...
static bool mergeBlocksIntoPredecessors(VPlan &Plan)
Remove redundant VPBasicBlocks by merging them into their single predecessor if the latter has a sing...
static void attachAliasMaskToHeaderMask(VPlan &Plan)
Attaches the alias-mask to the existing header-mask.
static void optimizeFindIVReductions(VPlan &Plan, PredicatedScalarEvolution &PSE, Loop &L)
Optimize FindLast reductions selecting IVs (or expressions of IVs) by converting them to FindIV reduc...
static void convertToAbstractRecipes(VPlan &Plan, VPCostContext &Ctx, VFRange &Range)
This function converts initial recipes to the abstract recipes and clamps Range based on cost model f...
static void materializeConstantVectorTripCount(VPlan &Plan, ElementCount BestVF, unsigned BestUF, PredicatedScalarEvolution &PSE)
static void makeScalarizationDecisions(VPlan &Plan, VFRange &Range)
Make VPlan-based scalarization decision prior to delegating to the ones made by the legacy CM.
static void simplifyReverses(VPlan &Plan)
Cancel out redundant reverses in Plan, e.g. reverse(reverse(x)) -> x.
static void makeCallWideningDecisions(VPlan &Plan, VFRange &Range, VPRecipeBuilder &RecipeBuilder, VPCostContext &CostCtx)
Convert call VPInstructions in Plan into widened call, vector intrinsic or replicate recipes based on...
static void adjustFirstOrderRecurrenceMiddleUsers(VPlan &Plan, VFRange &Range)
Adjust first-order recurrence users in the middle block: create penultimate element extracts for LCSS...
static void removeDeadRecipes(VPlan &Plan)
Remove dead recipes from Plan.
static void simplifyRecipes(VPlan &Plan)
Perform instcombine-like simplifications on recipes in Plan.
static void sinkPredicatedStores(VPlan &Plan, PredicatedScalarEvolution &PSE, const Loop *L)
Sink predicated stores to the same address with complementary predicates (P and NOT P) to an uncondit...
static void replaceSymbolicStrides(VPlan &Plan, PredicatedScalarEvolution &PSE, const DenseMap< Value *, const SCEV * > &StridesMap, const VPDominatorTree &VPDT)
Replace symbolic strides from StridesMap in Plan with constants when possible.
static bool removeBranchOnConst(VPlan &Plan, bool OnlyLatches=false)
Remove BranchOnCond recipes with true or false conditions together with removing dead edges to their ...
static void convertToStridedAccesses(VPlan &Plan, PredicatedScalarEvolution &PSE, Loop &L, VPCostContext &Ctx, VFRange &Range)
Transform widen memory recipes into strided access recipes when legal and profitable.
static bool handleUncountableEarlyExits(VPlan &Plan, VPBasicBlock *HeaderVPBB, VPBasicBlock *LatchVPBB, VPBasicBlock *MiddleVPBB, Loop *TheLoop, PredicatedScalarEvolution &PSE, DominatorTree &DT, AssumptionCache *AC, UncountableExitStyle Style)
Update Plan to account for uncountable early exits by introducing appropriate branching logic in the ...
static void clearReductionWrapFlags(VPlan &Plan)
Clear NSW/NUW flags from reduction instructions if necessary.
static void createPartialReductions(VPlan &Plan, VPCostContext &CostCtx, VFRange &Range)
Detect and create partial reduction recipes for scaled reductions in Plan.
static void cse(VPlan &Plan)
Perform common-subexpression-elimination on Plan.
static void attachVPCheckBlock(VPlan &Plan, VPValue *Cond, VPBasicBlock *CheckBlock, bool AddBranchWeights)
Wrap runtime check block CheckBlock in a VPIRBB and Cond in a VPValue and connect the block to Plan,...
static LLVM_ABI_FOR_TEST void optimize(VPlan &Plan)
Apply VPlan-to-VPlan optimizations to Plan, including induction recipe optimizations,...
static void dissolveLoopRegions(VPlan &Plan)
Replace loop regions with explicit CFG.
static void truncateToMinimalBitwidths(VPlan &Plan, const MapVector< Instruction *, uint64_t > &MinBWs)
Insert truncates and extends for any truncated recipe.
static void dropPoisonGeneratingRecipes(VPlan &Plan)
Drop poison flags from recipes that may generate a poison value that is used after vectorization,...
static void optimizeForVFAndUF(VPlan &Plan, ElementCount BestVF, unsigned BestUF, PredicatedScalarEvolution &PSE)
Optimize Plan based on BestVF and BestUF.