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"
32#include "llvm/Analysis/Loads.h"
39#include "llvm/IR/Intrinsics.h"
40#include "llvm/IR/MDBuilder.h"
41#include "llvm/IR/Metadata.h"
46
47using namespace llvm;
48using namespace VPlanPatternMatch;
49using namespace SCEVPatternMatch;
50
52 VPlan &Plan, const TargetLibraryInfo &TLI) {
53
55 Plan.getVectorLoopRegion());
57 // Skip blocks outside region
58 if (!VPBB->getParent())
59 break;
60 VPRecipeBase *Term = VPBB->getTerminator();
61 auto EndIter = Term ? Term->getIterator() : VPBB->end();
62 // Introduce each ingredient into VPlan.
63 for (VPRecipeBase &Ingredient :
64 make_early_inc_range(make_range(VPBB->begin(), EndIter))) {
65
66 VPValue *VPV = Ingredient.getVPSingleValue();
67 if (!VPV->getUnderlyingValue())
68 continue;
69
71
72 // Atomic accesses and fences have ordering/atomicity semantics that
73 // cannot be preserved by lane-wise widening.
75 return false;
76
77 VPRecipeBase *NewRecipe = nullptr;
78 if (auto *PhiR = dyn_cast<VPPhi>(&Ingredient)) {
79 auto *Phi = cast<PHINode>(PhiR->getUnderlyingValue());
80 NewRecipe = new VPWidenPHIRecipe(PhiR->operands(), PhiR->getDebugLoc(),
81 Phi->getName());
82 } else if (auto *VPI = dyn_cast<VPInstruction>(&Ingredient)) {
83 assert(!isa<PHINode>(Inst) && "phis should be handled above");
84 // Create VPWidenMemoryRecipe for loads and stores.
85 if (LoadInst *Load = dyn_cast<LoadInst>(Inst)) {
86 NewRecipe = new VPWidenLoadRecipe(
87 *Load, Ingredient.getOperand(0), nullptr /*Mask*/,
88 false /*Consecutive*/, *VPI, Ingredient.getDebugLoc());
89 } else if (StoreInst *Store = dyn_cast<StoreInst>(Inst)) {
90 NewRecipe = new VPWidenStoreRecipe(
91 *Store, Ingredient.getOperand(1), Ingredient.getOperand(0),
92 nullptr /*Mask*/, false /*Consecutive*/, *VPI,
93 Ingredient.getDebugLoc());
95 NewRecipe = new VPWidenGEPRecipe(GEP->getSourceElementType(),
96 Ingredient.operands(), *VPI,
97 Ingredient.getDebugLoc(), GEP);
98 } else if (CallInst *CI = dyn_cast<CallInst>(Inst)) {
99 Intrinsic::ID VectorID = getVectorIntrinsicIDForCall(CI, &TLI);
100 if (VectorID == Intrinsic::not_intrinsic)
101 return false;
102
103 // The noalias.scope.decl intrinsic declares a noalias scope that
104 // is valid for a single iteration. Emitting it as a single-scalar
105 // replicate would incorrectly extend the scope across multiple
106 // original iterations packed into one vector iteration.
107 // FIXME: If we want to vectorize this loop, then we have to drop
108 // all the associated !alias.scope and !noalias.
109 if (VectorID == Intrinsic::experimental_noalias_scope_decl)
110 return false;
111
112 // These intrinsics are recognized by getVectorIntrinsicIDForCall
113 // but are not widenable. Emit them as replicate instead of widening.
114 if (VectorID == Intrinsic::assume ||
115 VectorID == Intrinsic::lifetime_end ||
116 VectorID == Intrinsic::lifetime_start ||
117 VectorID == Intrinsic::sideeffect ||
118 VectorID == Intrinsic::pseudoprobe) {
119 // If the operand of llvm.assume holds before vectorization, it will
120 // also hold per lane.
121 // llvm.pseudoprobe requires to be duplicated per lane for accurate
122 // sample count.
123 const bool IsSingleScalar = VectorID != Intrinsic::assume &&
124 VectorID != Intrinsic::pseudoprobe;
125 NewRecipe = new VPReplicateRecipe(CI, Ingredient.operands(),
126 /*IsSingleScalar=*/IsSingleScalar,
127 /*Mask=*/nullptr, *VPI, *VPI,
128 Ingredient.getDebugLoc());
129 } else {
130 NewRecipe = new VPWidenIntrinsicRecipe(
131 *CI, VectorID, drop_end(Ingredient.operands()), CI->getType(),
132 VPIRFlags(*CI), *VPI, CI->getDebugLoc());
133 }
134 } else if (auto *CI = dyn_cast<CastInst>(Inst)) {
135 NewRecipe = new VPWidenCastRecipe(
136 CI->getOpcode(), Ingredient.getOperand(0), CI->getType(), CI,
137 VPIRFlags(*CI), VPIRMetadata(*CI));
138 } else {
139 NewRecipe = new VPWidenRecipe(*Inst, Ingredient.operands(), *VPI,
140 *VPI, Ingredient.getDebugLoc());
141 }
142 } else {
144 "inductions must be created earlier");
145 continue;
146 }
147
148 NewRecipe->insertBefore(&Ingredient);
149 if (NewRecipe->getNumDefinedValues() == 1)
150 VPV->replaceAllUsesWith(NewRecipe->getVPSingleValue());
151 else
152 assert(NewRecipe->getNumDefinedValues() == 0 &&
153 "Only recpies with zero or one defined values expected");
154 Ingredient.eraseFromParent();
155 }
156 }
157 return true;
158}
159
160/// Helper for extra no-alias checks via known-safe recipe and SCEV.
163 VPReplicateRecipe &GroupLeader;
164 PredicatedScalarEvolution *PSE = nullptr;
165 const Loop *L = nullptr;
166
167 // Return true if \p A and \p B are known to not alias for all VFs in the
168 // plan, checked via the distance between the accesses
169 bool isNoAliasViaDistance(VPReplicateRecipe *A, VPReplicateRecipe *B) const {
170 if (A->getOpcode() != Instruction::Store ||
171 B->getOpcode() != Instruction::Store)
172 return false;
173
174 if (!PSE || !L)
175 return A == B;
176
177 VPValue *AddrA = A->getOperand(1);
178 const SCEV *SCEVA = vputils::getSCEVExprForVPValue(AddrA, *PSE, L);
179 VPValue *AddrB = B->getOperand(1);
180 const SCEV *SCEVB = vputils::getSCEVExprForVPValue(AddrB, *PSE, L);
182 return false;
183
184 const APInt *Distance;
185 ScalarEvolution &SE = *PSE->getSE();
186 if (!match(SE.getMinusSCEV(SCEVA, SCEVB), m_scev_APInt(Distance)))
187 return false;
188
189 const DataLayout &DL = SE.getDataLayout();
190 Type *TyA = A->getOperand(0)->getScalarType();
191 uint64_t SizeA = DL.getTypeStoreSize(TyA);
192 Type *TyB = B->getOperand(0)->getScalarType();
193 uint64_t SizeB = DL.getTypeStoreSize(TyB);
194
195 // Use the maximum store size to ensure no overlap from either direction.
196 // Currently only handles fixed sizes, as it is only used for
197 // replicating VPReplicateRecipes.
198 uint64_t MaxStoreSize = std::max(SizeA, SizeB);
199
200 auto VFs = B->getParent()->getPlan()->vectorFactors();
202 if (MaxVF.isScalable())
203 return false;
204 return Distance->abs().uge(
205 MaxVF.multiplyCoefficientBy(MaxStoreSize).getFixedValue());
206 }
207
208public:
211 const Loop &L)
212 : ExcludeRecipes(ExcludeRecipes.begin(), ExcludeRecipes.end()),
213 GroupLeader(GroupLeader), PSE(&PSE), L(&L) {}
214
215 SinkStoreInfo(VPReplicateRecipe &GroupLeader) : GroupLeader(GroupLeader) {}
216
217 /// Return true if \p R should be skipped during alias checking, either
218 /// because it's in the exclude set or because no-alias can be proven via
219 /// SCEV.
220 bool shouldSkip(VPRecipeBase &R) const {
222 return ExcludeRecipes.contains(Store) ||
223 (Store && isNoAliasViaDistance(Store, &GroupLeader));
224 }
225};
226
227/// Check if a memory operation doesn't alias with memory operations using
228/// scoped noalias metadata, in blocks in the single-successor chain between \p
229/// FirstBB and \p LastBB. If \p SinkInfo is std::nullopt, only recipes that may
230/// write to memory are checked (for load hoisting). Otherwise recipes that both
231/// read and write memory are checked, and SCEV is used to prove no-alias
232/// between the group leader and other replicate recipes (for store sinking).
233static bool
235 VPBasicBlock *FirstBB, VPBasicBlock *LastBB,
236 std::optional<SinkStoreInfo> SinkInfo = {}) {
237 bool CheckReads = SinkInfo.has_value();
238 for (VPBasicBlock *VPBB :
240 for (VPRecipeBase &R : *VPBB) {
241 if (SinkInfo && SinkInfo->shouldSkip(R))
242 continue;
243
244 // Skip recipes that don't need checking.
245 if (!R.mayWriteToMemory() && !(CheckReads && R.mayReadFromMemory()))
246 continue;
247
249 if (!Loc)
250 // Conservatively assume aliasing for memory operations without
251 // location.
252 return false;
253
255 return false;
256 }
257 }
258 return true;
259}
260
261/// Get the value type of the replicate load or store. \p IsLoad indicates
262/// whether it is a load.
264 return (IsLoad ? R : R->getOperand(0))->getScalarType();
265}
266
267/// Collect either replicated Loads or Stores grouped by their address SCEV and
268/// their load-store type, in a deep-traversal of the vector loop region in \p
269/// Plan.
270template <unsigned Opcode>
273 VPlan &Plan, PredicatedScalarEvolution &PSE, const Loop *L,
274 function_ref<bool(VPReplicateRecipe *)> FilterFn) {
275 static_assert(Opcode == Instruction::Load || Opcode == Instruction::Store,
276 "Only Load and Store opcodes supported");
277 constexpr bool IsLoad = (Opcode == Instruction::Load);
280 RecipesByAddressAndType;
283 for (VPRecipeBase &R : *VPBB) {
284 auto *RepR = dyn_cast<VPReplicateRecipe>(&R);
285 if (!RepR || RepR->getOpcode() != Opcode || !FilterFn(RepR))
286 continue;
287
288 // For loads, operand 0 is address; for stores, operand 1 is address.
289 VPValue *Addr = RepR->getOperand(IsLoad ? 0 : 1);
290 const Type *LoadStoreTy = getLoadStoreValueType(RepR, IsLoad);
291 const SCEV *AddrSCEV = vputils::getSCEVExprForVPValue(Addr, PSE, L);
292 if (!isa<SCEVCouldNotCompute>(AddrSCEV))
293 RecipesByAddressAndType[{AddrSCEV, LoadStoreTy}].push_back(RepR);
294 }
295 }
296 auto Groups = to_vector(RecipesByAddressAndType.values());
297 VPDominatorTree VPDT(Plan);
298 for (auto &Group : Groups) {
299 // Sort mem ops by dominance order, with earliest (most dominating) first.
301 return VPDT.properlyDominates(A, B);
302 });
303 }
304 return Groups;
305}
306
307static bool sinkScalarOperands(VPlan &Plan) {
308 auto Iter = vp_depth_first_deep(Plan.getEntry());
309 bool ScalarVFOnly = Plan.hasScalarVFOnly();
310 bool Changed = false;
311
313 auto InsertIfValidSinkCandidate = [ScalarVFOnly, &WorkList](
314 VPBasicBlock *SinkTo, VPValue *Op) {
315 auto *Candidate =
316 dyn_cast_or_null<VPSingleDefRecipe>(Op->getDefiningRecipe());
317 if (!Candidate)
318 return;
319
320 // We only know how to sink VPReplicateRecipes and VPScalarIVStepsRecipes
321 // for now.
323 return;
324
325 if (Candidate->getParent() == SinkTo ||
326 vputils::cannotHoistOrSinkRecipe(*Candidate, /*Sinking=*/true))
327 return;
328
329 if (auto *RepR = dyn_cast<VPReplicateRecipe>(Candidate))
330 if (!ScalarVFOnly && RepR->isSingleScalar())
331 return;
332
333 WorkList.insert({SinkTo, Candidate});
334 };
335
336 // First, collect the operands of all recipes in replicate blocks as seeds for
337 // sinking.
339 VPBasicBlock *EntryVPBB = VPR->getEntryBasicBlock();
340 if (!VPR->isReplicator() || EntryVPBB->getSuccessors().size() != 2)
341 continue;
342 VPBasicBlock *VPBB = cast<VPBasicBlock>(EntryVPBB->getSuccessors().front());
343 if (VPBB->getSingleSuccessor() != VPR->getExitingBasicBlock())
344 continue;
345 for (auto &Recipe : *VPBB)
346 for (VPValue *Op : Recipe.operands())
347 InsertIfValidSinkCandidate(VPBB, Op);
348 }
349
350 // Try to sink each replicate or scalar IV steps recipe in the worklist.
351 for (unsigned I = 0; I != WorkList.size(); ++I) {
352 VPBasicBlock *SinkTo;
353 VPSingleDefRecipe *SinkCandidate;
354 std::tie(SinkTo, SinkCandidate) = WorkList[I];
355
356 // All recipe users of SinkCandidate must be in the same block SinkTo or all
357 // users outside of SinkTo must only use the first lane of SinkCandidate. In
358 // the latter case, we need to duplicate SinkCandidate.
359 auto UsersOutsideSinkTo =
360 make_filter_range(SinkCandidate->users(), [SinkTo](VPUser *U) {
361 return cast<VPRecipeBase>(U)->getParent() != SinkTo;
362 });
363 if (any_of(UsersOutsideSinkTo, [SinkCandidate](VPUser *U) {
364 return !U->usesFirstLaneOnly(SinkCandidate);
365 }))
366 continue;
367 bool NeedsDuplicating = !UsersOutsideSinkTo.empty();
368
369 if (NeedsDuplicating) {
370 if (ScalarVFOnly)
371 continue;
372 VPSingleDefRecipe *Clone;
373 if (auto *SinkCandidateRepR =
374 dyn_cast<VPReplicateRecipe>(SinkCandidate)) {
375 // TODO: Handle converting to uniform recipes as separate transform,
376 // then cloning should be sufficient here.
378 SinkCandidateRepR->getOpcode(), SinkCandidate->operands(),
379 /*Mask=*/nullptr, *SinkCandidateRepR, *SinkCandidateRepR,
380 SinkCandidate->getDebugLoc(), SinkCandidate->getUnderlyingInstr());
381 // TODO: add ".cloned" suffix to name of Clone's VPValue.
382 } else {
383 Clone = SinkCandidate->clone();
384 }
385
386 Clone->insertBefore(SinkCandidate);
387 SinkCandidate->replaceUsesWithIf(Clone, [SinkTo](VPUser &U, unsigned) {
388 return cast<VPRecipeBase>(&U)->getParent() != SinkTo;
389 });
390 }
391 SinkCandidate->moveBefore(*SinkTo, SinkTo->getFirstNonPhi());
392 for (VPValue *Op : SinkCandidate->operands())
393 InsertIfValidSinkCandidate(SinkTo, Op);
394 Changed = true;
395 }
396 return Changed;
397}
398
399/// If \p R is a region with a VPBranchOnMaskRecipe in the entry block, return
400/// the mask.
402 auto *EntryBB = dyn_cast<VPBasicBlock>(R->getEntry());
403 if (!EntryBB || EntryBB->size() != 1 ||
404 !isa<VPBranchOnMaskRecipe>(EntryBB->begin()))
405 return nullptr;
406
407 return cast<VPBranchOnMaskRecipe>(&*EntryBB->begin())->getOperand(0);
408}
409
410/// If \p R is a triangle region, return the 'then' block of the triangle.
412 auto *EntryBB = cast<VPBasicBlock>(R->getEntry());
413 if (EntryBB->getNumSuccessors() != 2)
414 return nullptr;
415
416 auto *Succ0 = dyn_cast<VPBasicBlock>(EntryBB->getSuccessors()[0]);
417 auto *Succ1 = dyn_cast<VPBasicBlock>(EntryBB->getSuccessors()[1]);
418 if (!Succ0 || !Succ1)
419 return nullptr;
420
421 if (Succ0->getNumSuccessors() + Succ1->getNumSuccessors() != 1)
422 return nullptr;
423 if (Succ0->getSingleSuccessor() == Succ1)
424 return Succ0;
425 if (Succ1->getSingleSuccessor() == Succ0)
426 return Succ1;
427 return nullptr;
428}
429
430// Merge replicate regions in their successor region, if a replicate region
431// is connected to a successor replicate region with the same predicate by a
432// single, empty VPBasicBlock.
434 SmallPtrSet<VPRegionBlock *, 4> TransformedRegions;
435
436 // Collect replicate regions followed by an empty block, followed by another
437 // replicate region with matching masks to process front. This is to avoid
438 // iterator invalidation issues while merging regions.
441 vp_depth_first_deep(Plan.getEntry()))) {
442 if (!Region1->isReplicator())
443 continue;
444 auto *MiddleBasicBlock =
445 dyn_cast_or_null<VPBasicBlock>(Region1->getSingleSuccessor());
446 if (!MiddleBasicBlock || !MiddleBasicBlock->empty())
447 continue;
448
449 auto *Region2 =
450 dyn_cast_or_null<VPRegionBlock>(MiddleBasicBlock->getSingleSuccessor());
451 if (!Region2 || !Region2->isReplicator())
452 continue;
453
454 VPValue *Mask1 = getPredicatedMask(Region1);
455 VPValue *Mask2 = getPredicatedMask(Region2);
456 if (!Mask1 || Mask1 != Mask2)
457 continue;
458
459 assert(Mask1 && Mask2 && "both region must have conditions");
460 WorkList.push_back(Region1);
461 }
462
463 // Move recipes from Region1 to its successor region, if both are triangles.
464 for (VPRegionBlock *Region1 : WorkList) {
465 if (TransformedRegions.contains(Region1))
466 continue;
467 auto *MiddleBasicBlock = cast<VPBasicBlock>(Region1->getSingleSuccessor());
468 auto *Region2 = cast<VPRegionBlock>(MiddleBasicBlock->getSingleSuccessor());
469
470 VPBasicBlock *Then1 = getPredicatedThenBlock(Region1);
471 VPBasicBlock *Then2 = getPredicatedThenBlock(Region2);
472 if (!Then1 || !Then2)
473 continue;
474
475 // Note: No fusion-preventing memory dependencies are expected in either
476 // region. Such dependencies should be rejected during earlier dependence
477 // checks, which guarantee accesses can be re-ordered for vectorization.
478 //
479 // Move recipes to the successor region.
480 for (VPRecipeBase &ToMove : make_early_inc_range(reverse(*Then1)))
481 ToMove.moveBefore(*Then2, Then2->getFirstNonPhi());
482
483 auto *Merge1 = cast<VPBasicBlock>(Then1->getSingleSuccessor());
484 auto *Merge2 = cast<VPBasicBlock>(Then2->getSingleSuccessor());
485
486 // Move VPPredInstPHIRecipes from the merge block to the successor region's
487 // merge block. Update all users inside the successor region to use the
488 // original values.
489 for (VPRecipeBase &Phi1ToMove : make_early_inc_range(reverse(*Merge1))) {
490 VPValue *PredInst1 =
491 cast<VPPredInstPHIRecipe>(&Phi1ToMove)->getOperand(0);
492 VPValue *Phi1ToMoveV = Phi1ToMove.getVPSingleValue();
493 Phi1ToMoveV->replaceUsesWithIf(PredInst1, [Then2](VPUser &U, unsigned) {
494 return cast<VPRecipeBase>(&U)->getParent() == Then2;
495 });
496
497 // Remove phi recipes that are unused after merging the regions.
498 if (Phi1ToMove.getVPSingleValue()->user_empty()) {
499 Phi1ToMove.eraseFromParent();
500 continue;
501 }
502 Phi1ToMove.moveBefore(*Merge2, Merge2->begin());
503 }
504
505 // Remove the dead recipes in Region1's entry block.
506 for (VPRecipeBase &R :
507 make_early_inc_range(reverse(*Region1->getEntryBasicBlock())))
508 R.eraseFromParent();
509
510 // Finally, remove the first region.
511 for (VPBlockBase *Pred : make_early_inc_range(Region1->getPredecessors())) {
512 VPBlockUtils::disconnectBlocks(Pred, Region1);
513 VPBlockUtils::connectBlocks(Pred, MiddleBasicBlock);
514 }
515 VPBlockUtils::disconnectBlocks(Region1, MiddleBasicBlock);
516 TransformedRegions.insert(Region1);
517 }
518
519 return !TransformedRegions.empty();
520}
521
523 VPRegionBlock *ParentRegion,
524 VPlan &Plan) {
525 Instruction *Instr = PredRecipe->getUnderlyingInstr();
526 // Build the triangular if-then region.
527 std::string RegionName = (Twine("pred.") + Instr->getOpcodeName()).str();
528 assert(Instr->getParent() && "Predicated instruction not in any basic block");
529 auto *BlockInMask = PredRecipe->getMask();
530 auto *MaskDef = BlockInMask->getDefiningRecipe();
531 auto *BOMRecipe = new VPBranchOnMaskRecipe(
532 BlockInMask, MaskDef ? MaskDef->getDebugLoc() : DebugLoc::getUnknown());
533 auto *Entry =
534 Plan.createVPBasicBlock(Twine(RegionName) + ".entry", BOMRecipe);
535
536 // Replace predicated replicate recipe with a replicate recipe without a
537 // mask but in the replicate region.
538 auto *RecipeWithoutMask = new VPReplicateRecipe(
539 PredRecipe->getUnderlyingInstr(), PredRecipe->operandsWithoutMask(),
540 PredRecipe->isSingleScalar(), nullptr /*Mask*/, *PredRecipe, *PredRecipe,
541 PredRecipe->getDebugLoc());
542 auto *Pred =
543 Plan.createVPBasicBlock(Twine(RegionName) + ".if", RecipeWithoutMask);
544 auto *Exiting = Plan.createVPBasicBlock(Twine(RegionName) + ".continue");
546 Plan.createReplicateRegion(Entry, Exiting, RegionName);
547
548 // Note: first set Entry as region entry and then connect successors starting
549 // from it in order, to propagate the "parent" of each VPBasicBlock.
550 Region->setParent(ParentRegion);
551 VPBlockUtils::insertTwoBlocksAfter(Pred, Exiting, Entry);
552 VPBlockUtils::connectBlocks(Pred, Exiting);
553
554 if (!PredRecipe->user_empty()) {
555 auto *PHIRecipe = new VPPredInstPHIRecipe(RecipeWithoutMask,
556 RecipeWithoutMask->getDebugLoc());
557 Exiting->appendRecipe(PHIRecipe);
558 PredRecipe->replaceAllUsesWith(PHIRecipe);
559 }
560 PredRecipe->eraseFromParent();
561 return Region;
562}
563
564static void addReplicateRegions(VPlan &Plan) {
567 vp_depth_first_deep(Plan.getEntry()))) {
568 for (VPRecipeBase &R : *VPBB)
569 if (auto *RepR = dyn_cast<VPReplicateRecipe>(&R)) {
570 if (RepR->isPredicated())
571 WorkList.push_back(RepR);
572 }
573 }
574
575 unsigned BBNum = 0;
576 for (VPReplicateRecipe *RepR : WorkList) {
577 VPBasicBlock *CurrentBlock = RepR->getParent();
578 VPBasicBlock *SplitBlock = CurrentBlock->splitAt(RepR->getIterator());
579
580 BasicBlock *OrigBB = RepR->getUnderlyingInstr()->getParent();
581 SplitBlock->setName(
582 OrigBB->hasName() ? OrigBB->getName() + "." + Twine(BBNum++) : "");
583 // Record predicated instructions for above packing optimizations.
585 createReplicateRegion(RepR, CurrentBlock->getParent(), Plan);
587
588 VPRegionBlock *ParentRegion = Region->getParent();
589 if (ParentRegion && ParentRegion->getExiting() == CurrentBlock)
590 ParentRegion->setExiting(SplitBlock);
591 }
592}
593
597 vp_depth_first_deep(Plan.getEntry()))) {
598 // Don't fold the blocks in the skeleton of the Plan into their single
599 // predecessors for now.
600 // TODO: Remove restriction once more of the skeleton is modeled in VPlan.
601 if (!VPBB->getParent())
602 continue;
603 auto *PredVPBB =
604 dyn_cast_or_null<VPBasicBlock>(VPBB->getSinglePredecessor());
605 if (!PredVPBB || PredVPBB->getNumSuccessors() != 1 ||
606 isa<VPIRBasicBlock>(PredVPBB))
607 continue;
608 WorkList.push_back(VPBB);
609 }
610
611 for (VPBasicBlock *VPBB : WorkList) {
612 VPBasicBlock *PredVPBB = cast<VPBasicBlock>(VPBB->getSinglePredecessor());
613 for (VPRecipeBase &R : make_early_inc_range(*VPBB))
614 R.moveBefore(*PredVPBB, PredVPBB->end());
615 VPBlockUtils::disconnectBlocks(PredVPBB, VPBB);
616 auto *ParentRegion = VPBB->getParent();
617 if (ParentRegion && ParentRegion->getExiting() == VPBB)
618 ParentRegion->setExiting(PredVPBB);
619 VPBlockUtils::transferSuccessors(VPBB, PredVPBB);
620 // VPBB is now dead and will be cleaned up when the plan gets destroyed.
621 }
622 return !WorkList.empty();
623}
624
626 // Convert masked VPReplicateRecipes to if-then region blocks.
628
629 bool ShouldSimplify = true;
630 while (ShouldSimplify) {
631 ShouldSimplify = sinkScalarOperands(Plan);
632 ShouldSimplify |= mergeReplicateRegionsIntoSuccessors(Plan);
633 ShouldSimplify |= mergeBlocksIntoPredecessors(Plan);
634 }
635}
636
637/// Remove redundant casts of inductions.
638///
639/// Such redundant casts are casts of induction variables that can be ignored,
640/// because we already proved that the casted phi is equal to the uncasted phi
641/// in the vectorized loop. There is no need to vectorize the cast - the same
642/// value can be used for both the phi and casts in the vector loop.
644 for (auto &Phi : Plan.getVectorLoopRegion()->getEntryBasicBlock()->phis()) {
646 if (!IV || IV->getTruncInst())
647 continue;
648
649 // A sequence of IR Casts has potentially been recorded for IV, which
650 // *must be bypassed* when the IV is vectorized, because the vectorized IV
651 // will produce the desired casted value. This sequence forms a def-use
652 // chain and is provided in reverse order, ending with the cast that uses
653 // the IV phi. Search for the recipe of the last cast in the chain and
654 // replace it with the original IV. Note that only the final cast is
655 // expected to have users outside the cast-chain and the dead casts left
656 // over will be cleaned up later.
657 ArrayRef<Instruction *> Casts = IV->getInductionDescriptor().getCastInsts();
658 VPValue *FindMyCast = IV;
659 for (Instruction *IRCast : reverse(Casts)) {
660 VPSingleDefRecipe *FoundUserCast = nullptr;
661 for (auto *U : FindMyCast->users()) {
662 auto *UserCast = dyn_cast<VPSingleDefRecipe>(U);
663 if (UserCast && UserCast->getUnderlyingValue() == IRCast) {
664 FoundUserCast = UserCast;
665 break;
666 }
667 }
668 // A cast recipe in the chain may have been removed by earlier DCE.
669 if (!FoundUserCast)
670 break;
671 FindMyCast = FoundUserCast;
672 }
673 if (FindMyCast != IV)
674 FindMyCast->replaceAllUsesWith(IV);
675 }
676}
677
680 Instruction::BinaryOps InductionOpcode,
681 FPMathOperator *FPBinOp, Instruction *TruncI,
682 VPIRValue *StartV, VPValue *Step, DebugLoc DL,
683 VPBuilder &Builder) {
684 VPRegionBlock *LoopRegion = Plan.getVectorLoopRegion();
685 VPBasicBlock *HeaderVPBB = LoopRegion->getEntryBasicBlock();
686 VPValue *CanonicalIV = LoopRegion->getCanonicalIV();
687 VPSingleDefRecipe *BaseIV =
688 Builder.createDerivedIV(Kind, FPBinOp, StartV, CanonicalIV, Step);
689
690 // Truncate base induction if needed.
691 Type *ResultTy = BaseIV->getScalarType();
692 if (TruncI) {
693 Type *TruncTy = TruncI->getType();
694 assert(ResultTy->getScalarSizeInBits() > TruncTy->getScalarSizeInBits() &&
695 "Not truncating.");
696 assert(ResultTy->isIntegerTy() && "Truncation requires an integer type");
697 BaseIV = Builder.createScalarCast(Instruction::Trunc, BaseIV, TruncTy, DL);
698 ResultTy = TruncTy;
699 }
700
701 // Truncate step if needed.
702 Type *StepTy = Step->getScalarType();
703 if (ResultTy != StepTy) {
704 assert(StepTy->getScalarSizeInBits() > ResultTy->getScalarSizeInBits() &&
705 "Not truncating.");
706 assert(StepTy->isIntegerTy() && "Truncation requires an integer type");
707 auto *VecPreheader =
709 VPBuilder::InsertPointGuard Guard(Builder);
710 Builder.setInsertPoint(VecPreheader);
711 Step = Builder.createScalarCast(Instruction::Trunc, Step, ResultTy, DL);
712 }
713 return Builder.createScalarIVSteps(InductionOpcode, FPBinOp, BaseIV, Step,
714 &Plan.getVF(), DL);
715}
716
718 VPlan &Plan, ScalarEvolution &SE, const TargetTransformInfo &TTI,
720 const SmallPtrSetImpl<const Value *> &ValuesToIgnore) {
721 VPRegionBlock *LoopRegion = Plan.getVectorLoopRegion();
722 if (!LoopRegion)
723 return;
724
725 auto *WideCanIV =
727 if (!WideCanIV)
728 return;
729
730 Type *CanIVTy = LoopRegion->getCanonicalIVType();
731
732 // Replace the wide canonical IV with a scalar-iv-steps over the canonical
733 // IV.
734 if (Plan.hasScalarVFOnly() || vputils::onlyFirstLaneUsed(WideCanIV)) {
735 VPBuilder Builder(WideCanIV);
736 WideCanIV->replaceAllUsesWith(createScalarIVSteps(
737 Plan, InductionDescriptor::IK_IntInduction, Instruction::Add, nullptr,
738 nullptr, Plan.getZero(CanIVTy), Plan.getConstantInt(CanIVTy, 1),
739 WideCanIV->getDebugLoc(), Builder));
740 WideCanIV->eraseFromParent();
741 return;
742 }
743
744 if (vputils::onlyScalarValuesUsed(WideCanIV))
745 return;
746
747 // If a canonical VPWidenIntOrFpInductionRecipe already produces vector lanes
748 // in the header, reuse it instead of introducing another wide induction phi.
749 VPBasicBlock *Header = LoopRegion->getEntryBasicBlock();
750 for (VPRecipeBase &Phi : Header->phis()) {
752 if (!match(&Phi, m_CanonicalWidenIV(WidenIV)))
753 continue;
754 // The reused wide IV feeds the header mask, whose lanes may extend past
755 // the trip count; drop flags that only hold inside the scalar loop.
756 WidenIV->dropPoisonGeneratingFlags();
757 WideCanIV->replaceAllUsesWith(WidenIV);
758 WideCanIV->eraseFromParent();
759 return;
760 }
761
762 // Introduce a new VPWidenIntOrFpInductionRecipe if profitable.
763 auto *VecTy = VectorType::get(CanIVTy, VF);
764 InstructionCost BroadcastCost = TTI.getShuffleCost(
766 InstructionCost PHICost = TTI.getCFInstrCost(Instruction::PHI, CostKind);
767 if (PHICost > BroadcastCost)
768 return;
769
770 // Bail out if the additional wide induction phi increase the expected spill
771 // cost.
772 VPRegisterUsage UnrolledBase =
773 calculateRegisterUsageForPlan(Plan, VF, TTI, ValuesToIgnore)[0];
774 for (unsigned &NumUsers : make_second_range(UnrolledBase.MaxLocalUsers))
775 NumUsers *= UF;
776 unsigned RegClass = TTI.getRegisterClassForType(/*Vector=*/true, VecTy);
777 VPRegisterUsage Projected = UnrolledBase;
778 Projected.MaxLocalUsers[RegClass] += TTI.getRegUsageForType(VecTy);
779 if (Projected.spillCost(TTI, CostKind) >
780 UnrolledBase.spillCost(TTI, CostKind))
781 return;
782
785 VPValue *StepV = Plan.getConstantInt(CanIVTy, 1);
786 auto *NewWideIV = new VPWidenIntOrFpInductionRecipe(
787 /*IV=*/nullptr, Plan.getZero(CanIVTy), StepV, &Plan.getVF(), ID,
788 WideCanIV->getNoWrapFlags(), WideCanIV->getDebugLoc());
789 NewWideIV->insertBefore(&*Header->getFirstNonPhi());
790 WideCanIV->replaceAllUsesWith(NewWideIV);
791 WideCanIV->eraseFromParent();
792}
793
794/// Returns true if \p R is dead and can be removed.
795static bool isDeadRecipe(VPRecipeBase &R) {
796 // Do remove conditional assume instructions as their conditions may be
797 // flattened.
798 auto *RepR = dyn_cast<VPReplicateRecipe>(&R);
799 bool IsConditionalAssume = RepR && RepR->isPredicated() &&
801 if (IsConditionalAssume)
802 return true;
803
804 if (R.mayHaveSideEffects())
805 return false;
806
807 // Recipe is dead if no user keeps the recipe alive.
808 return all_of(R.definedValues(), [](VPValue *V) { return V->user_empty(); });
809}
810
813 Plan.getEntry());
815 // The recipes in the block are processed in reverse order, to catch chains
816 // of dead recipes.
817 for (VPRecipeBase &R : make_early_inc_range(reverse(*VPBB))) {
818 if (isDeadRecipe(R)) {
819 R.eraseFromParent();
820 continue;
821 }
822
823 // Check if R is a dead VPPhi <-> update cycle and remove it.
824 VPValue *Start, *Incoming;
825 if (!match(&R, m_VPPhi(m_VPValue(Start), m_VPValue(Incoming))))
826 continue;
827 auto *PhiR = cast<VPPhi>(&R);
828 VPUser *PhiUser = PhiR->getSingleUser();
829 if (!PhiUser)
830 continue;
831 if (PhiUser != Incoming->getDefiningRecipe() ||
832 Incoming->getNumUsers() != 1)
833 continue;
834 PhiR->replaceAllUsesWith(Start);
835 PhiR->eraseFromParent();
836 Incoming->getDefiningRecipe()->eraseFromParent();
837 }
838 }
839}
840
843 for (unsigned I = 0; I != Users.size(); ++I) {
845 for (VPValue *V : Cur->definedValues())
846 Users.insert_range(V->users());
847 }
848 return Users.takeVector();
849}
850
851/// Scalarize a VPWidenPointerInductionRecipe by replacing it with a PtrAdd
852/// (IndStart, ScalarIVSteps (0, Step)). This is used when the recipe only
853/// generates scalar values.
854static VPValue *
856 VPlan &Plan, VPBuilder &Builder) {
858 VPIRValue *StartV = Plan.getZero(ID.getStep()->getType());
859 VPValue *StepV = PtrIV->getOperand(1);
861 Plan, InductionDescriptor::IK_IntInduction, Instruction::Add, nullptr,
862 nullptr, StartV, StepV, PtrIV->getDebugLoc(), Builder);
863
864 return Builder.createPtrAdd(PtrIV->getStartValue(), Steps,
865 PtrIV->getDebugLoc(), "next.gep");
866}
867
868/// Legalize VPWidenPointerInductionRecipe, by replacing it with a PtrAdd
869/// (IndStart, ScalarIVSteps (0, Step)) if only its scalar values are used, as
870/// VPWidenPointerInductionRecipe will generate vectors only. If some users
871/// require vectors while other require scalars, the scalar uses need to extract
872/// the scalars from the generated vectors (Note that this is different to how
873/// int/fp inductions are handled). Legalize extract-from-ends using uniform
874/// VPReplicateRecipe of wide inductions to use regular VPReplicateRecipe, so
875/// the correct end value is available. Also optimize
876/// VPWidenIntOrFpInductionRecipe, if any of its users needs scalar values, by
877/// providing them scalar steps built on the canonical scalar IV and update the
878/// original IV's users. This is an optional optimization to reduce the needs of
879/// vector extracts.
882 bool HasOnlyVectorVFs = !Plan.hasScalarVFOnly();
883 VPBuilder Builder(HeaderVPBB, HeaderVPBB->getFirstNonPhi());
884 for (VPRecipeBase &Phi : HeaderVPBB->phis()) {
885 auto *PhiR = dyn_cast<VPWidenInductionRecipe>(&Phi);
886 if (!PhiR)
887 continue;
888
889 // Try to narrow wide and replicating recipes to uniform recipes, based on
890 // VPlan analysis.
891 // TODO: Apply to all recipes in the future, to replace legacy uniformity
892 // analysis.
893 auto Users = collectUsersRecursively(PhiR);
894 for (VPUser *U : reverse(Users)) {
895 auto *Def = dyn_cast<VPRecipeWithIRFlags>(U);
896 auto *RepR = dyn_cast<VPReplicateRecipe>(U);
897 // Skip recipes that shouldn't be narrowed.
898 if (!Def || !isa<VPReplicateRecipe, VPWidenRecipe>(Def) ||
899 Def->user_empty() || !Def->getUnderlyingValue() ||
900 (RepR && (RepR->isSingleScalar() || RepR->isPredicated())))
901 continue;
902
903 // Skip recipes that may have other lanes than their first used.
905 continue;
906
907 // TODO: Support scalarizing ExtractValue.
908 if (match(Def,
910 continue;
911
913 Def->getUnderlyingInstr()->getOpcode(), Def->operands(),
914 /*Mask=*/nullptr, *Def, {}, DebugLoc::getUnknown(),
915 Def->getUnderlyingInstr());
916 Clone->insertAfter(Def);
917 Def->replaceAllUsesWith(Clone);
918 }
919
920 // Replace wide pointer inductions which have only their scalars used by
921 // PtrAdd(IndStart, ScalarIVSteps (0, Step)).
922 if (auto *PtrIV = dyn_cast<VPWidenPointerInductionRecipe>(&Phi)) {
923 if (!Plan.hasScalarVFOnly() &&
924 !PtrIV->onlyScalarsGenerated(Plan.hasScalableVF()))
925 continue;
926
927 VPValue *PtrAdd = scalarizeVPWidenPointerInduction(PtrIV, Plan, Builder);
928 PtrIV->replaceAllUsesWith(PtrAdd);
929 continue;
930 }
931
932 // Replace widened induction with scalar steps for users that only use
933 // scalars.
934 auto *WideIV = cast<VPWidenIntOrFpInductionRecipe>(&Phi);
935 if (HasOnlyVectorVFs && none_of(WideIV->users(), [WideIV](VPUser *U) {
936 return U->usesScalars(WideIV);
937 }))
938 continue;
939
940 const InductionDescriptor &ID = WideIV->getInductionDescriptor();
942 Plan, ID.getKind(), ID.getInductionOpcode(),
943 dyn_cast_or_null<FPMathOperator>(ID.getInductionBinOp()),
944 WideIV->getTruncInst(), WideIV->getStartValue(), WideIV->getStepValue(),
945 WideIV->getDebugLoc(), Builder);
946
947 // Update scalar users of IV to use Step instead.
948 if (!HasOnlyVectorVFs) {
949 assert(!Plan.hasScalableVF() &&
950 "plans containing a scalar VF cannot also include scalable VFs");
951 WideIV->replaceAllUsesWith(Steps);
952 } else {
953 bool HasScalableVF = Plan.hasScalableVF();
954 WideIV->replaceUsesWithIf(Steps,
955 [WideIV, HasScalableVF](VPUser &U, unsigned) {
956 if (HasScalableVF)
957 return U.usesFirstLaneOnly(WideIV);
958 return U.usesScalars(WideIV);
959 });
960 }
961 }
962}
963
964/// Check if \p VPV is an untruncated wide induction, either before or after the
965/// increment. If so return the header IV (before the increment), otherwise
966/// return null.
969 auto *WideIV = dyn_cast<VPWidenInductionRecipe>(VPV);
970 if (WideIV) {
971 // VPV itself is a wide induction, separately compute the end value for exit
972 // users if it is not a truncated IV.
973 auto *IntOrFpIV = dyn_cast<VPWidenIntOrFpInductionRecipe>(WideIV);
974 return (IntOrFpIV && IntOrFpIV->getTruncInst()) ? nullptr : WideIV;
975 }
976
977 // Check if VPV is an optimizable induction increment.
978 VPRecipeBase *Def = VPV->getDefiningRecipe();
979 if (!Def || Def->getNumOperands() != 2)
980 return nullptr;
981 WideIV = dyn_cast<VPWidenInductionRecipe>(Def->getOperand(0));
982 if (!WideIV)
983 WideIV = dyn_cast<VPWidenInductionRecipe>(Def->getOperand(1));
984 if (!WideIV)
985 return nullptr;
986
987 auto IsWideIVInc = [&]() {
988 auto &ID = WideIV->getInductionDescriptor();
989
990 // Check if VPV increments the induction by the induction step.
991 VPValue *IVStep = WideIV->getStepValue();
992 switch (ID.getInductionOpcode()) {
993 case Instruction::Add:
994 return match(VPV, m_c_Add(m_Specific(WideIV), m_Specific(IVStep)));
995 case Instruction::FAdd:
996 return match(VPV, m_c_FAdd(m_Specific(WideIV), m_Specific(IVStep)));
997 case Instruction::FSub:
998 return match(VPV, m_Binary<Instruction::FSub>(m_Specific(WideIV),
999 m_Specific(IVStep)));
1000 case Instruction::Sub: {
1001 // IVStep will be the negated step of the subtraction. Check if Step == -1
1002 // * IVStep.
1003 VPValue *Step;
1004 if (!match(VPV, m_Sub(m_VPValue(), m_VPValue(Step))))
1005 return false;
1006 const SCEV *IVStepSCEV = vputils::getSCEVExprForVPValue(IVStep, PSE);
1007 const SCEV *StepSCEV = vputils::getSCEVExprForVPValue(Step, PSE);
1008 ScalarEvolution &SE = *PSE.getSE();
1009 return !isa<SCEVCouldNotCompute>(IVStepSCEV) &&
1010 !isa<SCEVCouldNotCompute>(StepSCEV) &&
1011 IVStepSCEV == SE.getNegativeSCEV(StepSCEV);
1012 }
1013 default:
1014 return ID.getKind() == InductionDescriptor::IK_PtrInduction &&
1015 match(VPV, m_GetElementPtr(m_Specific(WideIV),
1016 m_Specific(WideIV->getStepValue())));
1017 }
1018 llvm_unreachable("should have been covered by switch above");
1019 };
1020 return IsWideIVInc() ? WideIV : nullptr;
1021}
1022
1023/// Attempts to optimize the induction variable exit values for users in the
1024/// early exit block.
1027 VPValue *Incoming, *Mask;
1029 m_VPValue(Incoming))))
1030 return nullptr;
1031
1032 auto *WideIV = getOptimizableIVOf(Incoming, PSE);
1033 if (!WideIV)
1034 return nullptr;
1035
1036 auto *WideIntOrFp = dyn_cast<VPWidenIntOrFpInductionRecipe>(WideIV);
1037 if (WideIntOrFp && WideIntOrFp->getTruncInst())
1038 return nullptr;
1039
1040 // Calculate the final index.
1041 VPRegionBlock *LoopRegion = Plan.getVectorLoopRegion();
1042 auto *CanonicalIV = LoopRegion->getCanonicalIV();
1043 Type *CanonicalIVType = LoopRegion->getCanonicalIVType();
1044 auto *ExtractR = cast<VPInstruction>(Op);
1045 VPBuilder B(ExtractR);
1046
1047 DebugLoc DL = ExtractR->getDebugLoc();
1048 VPValue *FirstActiveLane = B.createFirstActiveLane(Mask, DL);
1049 FirstActiveLane = B.createScalarZExtOrTrunc(
1050 FirstActiveLane, CanonicalIVType, FirstActiveLane->getScalarType(), DL);
1051 VPValue *EndValue = B.createAdd(CanonicalIV, FirstActiveLane, DL);
1052
1053 // `getOptimizableIVOf()` always returns the pre-incremented IV, so if it
1054 // changed it means the exit is using the incremented value, so we need to
1055 // add the step.
1056 if (Incoming != WideIV) {
1057 VPValue *One = Plan.getConstantInt(CanonicalIVType, 1);
1058 EndValue = B.createAdd(EndValue, One, DL);
1059 }
1060
1061 if (!match(WideIV, m_CanonicalWidenIV())) {
1062 const InductionDescriptor &ID = WideIV->getInductionDescriptor();
1063 VPIRValue *Start = WideIV->getStartValue();
1064 VPValue *Step = WideIV->getStepValue();
1065 EndValue = B.createDerivedIV(
1066 ID.getKind(), dyn_cast_or_null<FPMathOperator>(ID.getInductionBinOp()),
1067 Start, EndValue, Step);
1068 }
1069
1070 return EndValue;
1071}
1072
1073/// Compute the end value for \p WideIV, unless it is truncated. Creates a
1074/// VPDerivedIVRecipe for non-canonical inductions.
1076 VPBuilder &VectorPHBuilder,
1077 VPValue *VectorTC) {
1078 auto *WideIntOrFp = dyn_cast<VPWidenIntOrFpInductionRecipe>(WideIV);
1079 // Truncated wide inductions resume from the last lane of their vector value
1080 // in the last vector iteration which is handled elsewhere.
1081 if (WideIntOrFp && WideIntOrFp->getTruncInst())
1082 return nullptr;
1083
1084 VPIRValue *Start = WideIV->getStartValue();
1085 VPValue *Step = WideIV->getStepValue();
1087 VPValue *EndValue = VectorTC;
1088 if (!match(WideIV, m_CanonicalWidenIV())) {
1089 EndValue = VectorPHBuilder.createDerivedIV(
1090 ID.getKind(), dyn_cast_or_null<FPMathOperator>(ID.getInductionBinOp()),
1091 Start, VectorTC, Step);
1092 }
1093
1094 // EndValue is derived from the vector trip count (which has the same type as
1095 // the widest induction) and thus may be wider than the induction here.
1096 Type *ScalarTypeOfWideIV = WideIV->getScalarType();
1097 if (ScalarTypeOfWideIV != EndValue->getScalarType()) {
1098 EndValue = VectorPHBuilder.createScalarCast(Instruction::Trunc, EndValue,
1099 ScalarTypeOfWideIV,
1100 WideIV->getDebugLoc());
1101 }
1102
1103 return EndValue;
1104}
1105
1106/// Attempts to optimize the induction variable exit values for users in the
1107/// exit block coming from the latch in the original scalar loop.
1108static VPValue *
1112 VPValue *Incoming;
1115 m_VPValue(Incoming)))))
1116 return nullptr;
1117
1118 VPWidenInductionRecipe *WideIV = getOptimizableIVOf(Incoming, PSE);
1119 if (!WideIV)
1120 return nullptr;
1121
1122 VPValue *EndValue = EndValues.lookup(WideIV);
1123 assert(EndValue && "Must have computed the end value up front");
1124
1125 // `getOptimizableIVOf()` always returns the pre-incremented IV, so if it
1126 // changed it means the exit is using the incremented value, so we don't
1127 // need to subtract the step.
1128 if (Incoming != WideIV)
1129 return EndValue;
1130
1131 // Otherwise, subtract the step from the EndValue.
1132 auto *ExtractR = cast<VPInstruction>(Op);
1133 VPBuilder B(ExtractR);
1134 VPValue *Step = WideIV->getStepValue();
1135 Type *ScalarTy = WideIV->getScalarType();
1136 if (ScalarTy->isIntegerTy())
1137 return B.createSub(EndValue, Step, DebugLoc::getUnknown(), "ind.escape");
1138 if (ScalarTy->isPointerTy()) {
1139 Type *StepTy = Step->getScalarType();
1140 auto *Zero = Plan.getZero(StepTy);
1141 return B.createPtrAdd(EndValue, B.createSub(Zero, Step),
1142 DebugLoc::getUnknown(), "ind.escape");
1143 }
1144 if (ScalarTy->isFloatingPointTy()) {
1145 const auto &ID = WideIV->getInductionDescriptor();
1146 return B.createNaryOp(
1147 ID.getInductionBinOp()->getOpcode() == Instruction::FAdd
1148 ? Instruction::FSub
1149 : Instruction::FAdd,
1150 {EndValue, Step}, {ID.getInductionBinOp()->getFastMathFlags()});
1151 }
1152 llvm_unreachable("all possible induction types must be handled");
1153 return nullptr;
1154}
1155
1157 VPlan &Plan, PredicatedScalarEvolution &PSE) {
1158 // Compute end values for all inductions.
1159 VPRegionBlock *VectorRegion = Plan.getVectorLoopRegion();
1160 auto *VectorPH = cast<VPBasicBlock>(VectorRegion->getSinglePredecessor());
1161 VPBuilder VectorPHBuilder(VectorPH, VectorPH->begin());
1163 VPValue *ResumeTC =
1164 Plan.hasTailFolded() ? Plan.getTripCount() : &Plan.getVectorTripCount();
1165 for (auto &Phi : VectorRegion->getEntryBasicBlock()->phis()) {
1166 auto *WideIV = dyn_cast<VPWidenInductionRecipe>(&Phi);
1167 if (!WideIV)
1168 continue;
1169 if (VPValue *EndValue =
1170 tryToComputeEndValueForInduction(WideIV, VectorPHBuilder, ResumeTC))
1171 EndValues[WideIV] = EndValue;
1172 }
1173
1174 VPBasicBlock *MiddleVPBB = Plan.getMiddleBlock();
1175 for (VPRecipeBase &R : make_early_inc_range(*MiddleVPBB)) {
1176 VPValue *Op;
1177 if (!match(&R, m_ExitingIVValue(m_VPValue(Op))))
1178 continue;
1179 auto *WideIV = cast<VPWidenInductionRecipe>(Op);
1180 if (VPValue *EndValue = EndValues.lookup(WideIV)) {
1181 R.getVPSingleValue()->replaceAllUsesWith(EndValue);
1182 R.eraseFromParent();
1183 }
1184 }
1185
1186 // Then, optimize exit block users.
1187 for (VPIRBasicBlock *ExitVPBB : Plan.getExitBlocks()) {
1188 for (VPRecipeBase &R : ExitVPBB->phis()) {
1189 auto *ExitIRI = cast<VPIRPhi>(&R);
1190
1191 for (auto [Idx, PredVPBB] : enumerate(ExitVPBB->getPredecessors())) {
1192 VPValue *Escape = nullptr;
1193 if (PredVPBB == MiddleVPBB)
1195 Plan, ExitIRI->getOperand(Idx), EndValues, PSE);
1196 else
1198 Plan, ExitIRI->getOperand(Idx), PSE);
1199 if (Escape)
1200 ExitIRI->setOperand(Idx, Escape);
1201 }
1202 }
1203 }
1204}
1205
1206/// Remove redundant ExpandSCEVRecipes in \p Plan's entry block by replacing
1207/// them with already existing recipes expanding the same SCEV expression.
1210
1211 for (VPRecipeBase &R :
1213 auto *ExpR = dyn_cast<VPExpandSCEVRecipe>(&R);
1214 if (!ExpR)
1215 continue;
1216
1217 const auto &[V, Inserted] = SCEV2VPV.try_emplace(ExpR->getSCEV(), ExpR);
1218 if (Inserted)
1219 continue;
1220
1221 ExpR->replaceAllUsesWith(V->second);
1222 if (ExpR == Plan.getTripCount())
1223 Plan.resetTripCount(V->second);
1224
1225 ExpR->eraseFromParent();
1226 }
1227}
1228
1230 SmallVector<VPValue *> WorkList;
1232 WorkList.push_back(V);
1233
1234 while (!WorkList.empty()) {
1235 VPValue *Cur = WorkList.pop_back_val();
1236 if (!Seen.insert(Cur).second)
1237 continue;
1238 VPRecipeBase *R = Cur->getDefiningRecipe();
1239 if (!R)
1240 continue;
1241 if (!isDeadRecipe(*R))
1242 continue;
1243 append_range(WorkList, R->operands());
1244 R->eraseFromParent();
1245 }
1246}
1247
1248/// Get any instruction opcode or intrinsic ID data embedded in recipe \p R.
1249/// Returns an optional pair, where the first element indicates whether it is
1250/// an intrinsic ID.
1251static std::optional<std::pair<bool, unsigned>>
1254 return std::make_pair(true, IID);
1255 return TypeSwitch<const VPSingleDefRecipe *,
1256 std::optional<std::pair<bool, unsigned>>>(R)
1259 [](auto *I) { return std::make_pair(false, I->getOpcode()); })
1260 .Case([](const VPWidenPHIRecipe *I) {
1261 return std::make_pair(false, Instruction::PHI);
1262 })
1263 .Case<VPVectorPointerRecipe, VPPredInstPHIRecipe, VPScalarIVStepsRecipe>(
1264 [](auto *I) {
1265 // For recipes that do not directly map to LLVM IR instructions,
1266 // assign opcodes after the last VPInstruction opcode (which is also
1267 // after the last IR Instruction opcode), based on the VPRecipeID.
1268 return std::make_pair(false, VPInstruction::OpsEnd + 1 +
1269 I->getVPRecipeID());
1270 })
1271 .Default([](auto *) { return std::nullopt; });
1272}
1273
1274/// Try to fold \p R using InstSimplifyFolder. Will succeed and return a
1275/// non-nullptr VPValue for a handled opcode or intrinsic ID if corresponding \p
1276/// Operands are foldable live-ins.
1278 ArrayRef<VPValue *> Operands,
1279 const DataLayout &DL) {
1280 auto OpcodeOrIID = getOpcodeOrIntrinsicID(&R);
1281 if (!OpcodeOrIID)
1282 return nullptr;
1283
1285 for (VPValue *Op : Operands) {
1286 VPValue *Candidate = Op;
1287 match(Op, m_Broadcast(m_VPValue(Candidate)));
1288 if (!match(Candidate, m_LiveIn()))
1289 return nullptr;
1290 Value *V = Candidate->getUnderlyingValue();
1291 if (!V)
1292 return nullptr;
1293 Ops.push_back(V);
1294 }
1295
1296 VPlan &Plan = *R.getParent()->getPlan();
1297 auto FoldToIRValue = [&]() -> Value * {
1298 InstSimplifyFolder Folder(DL);
1299 if (OpcodeOrIID->first) {
1300 // VPInstructions store the called intrinsic as last operand.
1301 if (isa<VPInstruction>(R))
1302 Ops.pop_back();
1303
1304 auto *RFlags = dyn_cast<VPRecipeWithIRFlags>(&R);
1305 return Folder.FoldIntrinsic(OpcodeOrIID->second, Ops, R.getScalarType(),
1306 RFlags ? RFlags->getFastMathFlagsOrNone()
1307 : FastMathFlags());
1308 }
1309 unsigned Opcode = OpcodeOrIID->second;
1310 if (Instruction::isBinaryOp(Opcode))
1311 return Folder.FoldBinOp(static_cast<Instruction::BinaryOps>(Opcode),
1312 Ops[0], Ops[1]);
1313 if (Instruction::isCast(Opcode))
1314 return Folder.FoldCast(static_cast<Instruction::CastOps>(Opcode), Ops[0],
1315 R.getVPSingleValue()->getScalarType());
1316 switch (Opcode) {
1317 case VPInstruction::Not:
1318 return Folder.FoldBinOp(Instruction::BinaryOps::Xor, Ops[0],
1320 case Instruction::Select:
1321 return Folder.FoldSelect(Ops[0], Ops[1], Ops[2]);
1322 case Instruction::ICmp:
1323 case Instruction::FCmp:
1324 return Folder.FoldCmp(cast<VPRecipeWithIRFlags>(R).getPredicate(), Ops[0],
1325 Ops[1]);
1326 case Instruction::GetElementPtr: {
1327 auto &RFlags = cast<VPRecipeWithIRFlags>(R);
1328 auto *GEP = cast<GetElementPtrInst>(RFlags.getUnderlyingInstr());
1329 return Folder.FoldGEP(GEP->getSourceElementType(), Ops[0],
1330 drop_begin(Ops), RFlags.getGEPNoWrapFlags());
1331 }
1334 return Folder.FoldGEP(IntegerType::getInt8Ty(Plan.getContext()), Ops[0],
1335 Ops[1],
1336 cast<VPRecipeWithIRFlags>(R).getGEPNoWrapFlags());
1337 // An extract of a live-in is an extract of a broadcast, so return the
1338 // broadcasted element.
1339 case Instruction::ExtractElement:
1340 assert(!Ops[0]->getType()->isVectorTy() && "Live-ins should be scalar");
1341 return Ops[0];
1342 }
1343 return nullptr;
1344 };
1345
1346 if (Value *V = FoldToIRValue())
1347 return Plan.getOrAddLiveIn(V);
1348 return nullptr;
1349}
1350
1351/// Try to simplify logical and bitwise recipes in \p Def.
1353 bool CanCreateNewRecipe) {
1354 VPlan *Plan = Def->getParent()->getPlan();
1355
1356 // Simplify (X && Y) | (X && !Y) -> X.
1357 // TODO: Split up into simpler, modular combines: (X && Y) | (X && Z) into X
1358 // && (Y | Z) and (X | !X) into true. This requires queuing newly created
1359 // recipes to be visited during simplification.
1360 VPValue *X, *Y, *Z;
1361 if (match(Def,
1364 Def->replaceAllUsesWith(X);
1365 Def->eraseFromParent();
1366 return true;
1367 }
1368
1369 // x | AllOnes -> AllOnes
1370 if (match(Def, m_c_BinaryOr(m_VPValue(X), m_AllOnes()))) {
1371 Def->replaceAllUsesWith(Plan->getAllOnesValue(Def->getScalarType()));
1372 return true;
1373 }
1374
1375 // x | 0 -> x
1376 if (match(Def, m_c_BinaryOr(m_VPValue(X), m_ZeroInt()))) {
1377 Def->replaceAllUsesWith(X);
1378 return true;
1379 }
1380
1381 // x | !x -> AllOnes
1382 if (match(Def, m_c_BinaryOr(m_VPValue(X), m_Not(m_Deferred(X))))) {
1383 Def->replaceAllUsesWith(Plan->getAllOnesValue(Def->getScalarType()));
1384 return true;
1385 }
1386
1387 // x & 0 -> 0
1388 if (match(Def, m_c_BinaryAnd(m_VPValue(X), m_ZeroInt()))) {
1389 Def->replaceAllUsesWith(Plan->getZero(Def->getScalarType()));
1390 return true;
1391 }
1392
1393 // x & AllOnes -> x
1394 if (match(Def, m_c_BinaryAnd(m_VPValue(X), m_AllOnes()))) {
1395 Def->replaceAllUsesWith(X);
1396 return true;
1397 }
1398
1399 // x && false -> false
1400 if (match(Def, m_c_LogicalAnd(m_VPValue(X), m_False()))) {
1401 Def->replaceAllUsesWith(Plan->getFalse());
1402 return true;
1403 }
1404
1405 // x && true -> x
1406 if (match(Def, m_c_LogicalAnd(m_VPValue(X), m_True()))) {
1407 Def->replaceAllUsesWith(X);
1408 return true;
1409 }
1410
1411 // (x && y) | (x && z) -> x && (y | z)
1412 if (CanCreateNewRecipe &&
1415 // Simplify only if one of the operands has one use to avoid creating an
1416 // extra recipe.
1417 (!Def->getOperand(0)->hasMoreThanOneUniqueUser() ||
1418 !Def->getOperand(1)->hasMoreThanOneUniqueUser())) {
1419 Def->replaceAllUsesWith(
1420 Builder.createLogicalAnd(X, Builder.createOr(Y, Z)));
1421 return true;
1422 }
1423
1424 // x && (x && y) -> x && y
1425 if (match(Def, m_LogicalAnd(m_VPValue(X),
1427 Def->replaceAllUsesWith(Def->getOperand(1));
1428 return true;
1429 }
1430
1431 // x && (y && x) -> x && y
1432 if (match(Def, m_LogicalAnd(m_VPValue(X),
1434 Def->replaceAllUsesWith(Builder.createLogicalAnd(X, Y));
1435 return true;
1436 }
1437
1438 // x && !x -> 0
1439 if (match(Def, m_LogicalAnd(m_VPValue(X), m_Not(m_Deferred(X))))) {
1440 Def->replaceAllUsesWith(Plan->getFalse());
1441 return true;
1442 }
1443
1444 if (match(Def, m_Select(m_VPValue(), m_VPValue(X), m_Deferred(X)))) {
1445 Def->replaceAllUsesWith(X);
1446 return true;
1447 }
1448
1449 // select c, false, true -> not c
1450 VPValue *C;
1451 if (CanCreateNewRecipe &&
1452 match(Def, m_Select(m_VPValue(C), m_False(), m_True()))) {
1453 Def->replaceAllUsesWith(Builder.createNot(C));
1454 return true;
1455 }
1456
1457 // select !c, x, y -> select c, y, x
1458 if (match(Def, m_Select(m_Not(m_VPValue(C)), m_VPValue(X), m_VPValue(Y)))) {
1459 Def->setOperand(0, C);
1460 Def->setOperand(1, Y);
1461 Def->setOperand(2, X);
1462 return true;
1463 }
1464
1465 // select x, (i1 y | z), y -> y | (x && z)
1466 if (CanCreateNewRecipe &&
1467 match(Def, m_Select(m_VPValue(X),
1469 m_Deferred(Y))) &&
1470 Y->getScalarType()->isIntegerTy(1)) {
1471 Def->replaceAllUsesWith(
1472 Builder.createOr(Y, Builder.createLogicalAnd(X, Z)));
1473 return true;
1474 }
1475
1476 return false;
1477}
1478
1479/// Try to simplify VPSingleDefRecipe \p Def.
1481 VPlan *Plan = Def->getParent()->getPlan();
1482
1483 // Simplification of live-in IR values for SingleDef recipes using
1484 // InstSimplifyFolder.
1485 const DataLayout &DL = Plan->getDataLayout();
1486 if (VPValue *V = tryToFoldLiveIns(*Def, Def->operands(), DL))
1487 return Def->replaceAllUsesWith(V);
1488
1489 // Fold PredPHI LiveIn -> LiveIn.
1490 if (auto *PredPHI = dyn_cast<VPPredInstPHIRecipe>(Def)) {
1491 VPValue *Op = PredPHI->getOperand(0);
1492 if (isa<VPIRValue>(Op))
1493 PredPHI->replaceAllUsesWith(Op);
1494 }
1495
1496 // Drop the mask of a predicated store masked by the header mask (which is
1497 // guaranteed to be true at least for the first lane) and both the stored
1498 // value and the address are uniform across VF and UF. The header mask is
1499 // still the abstract region value here.
1500 if (auto *RepR = dyn_cast<VPReplicateRecipe>(Def);
1501 RepR && RepR->isPredicated() && RepR->getOpcode() == Instruction::Store &&
1502 all_of(RepR->operandsWithoutMask(), vputils::isUniformAcrossVFsAndUFs) &&
1503 match(RepR->getMask(), m_HeaderMask())) {
1504 auto *Unmasked = new VPReplicateRecipe(
1505 RepR->getUnderlyingInstr(), RepR->operandsWithoutMask(),
1506 RepR->isSingleScalar(), /*Mask=*/nullptr, *RepR, *RepR,
1507 RepR->getDebugLoc());
1508 Unmasked->insertBefore(RepR);
1509 RepR->replaceAllUsesWith(Unmasked);
1510 RepR->eraseFromParent();
1511 return;
1512 }
1513
1514 VPBuilder Builder(Def);
1515
1516 // Avoid replacing VPInstructions with underlying values with new
1517 // VPInstructions, as we would fail to create widen/replicate recpes from the
1518 // new VPInstructions without an underlying value, and miss out on some
1519 // transformations that only apply to widened/replicated recipes later, by
1520 // doing so.
1521 // TODO: We should also not replace non-VPInstructions like VPWidenRecipe with
1522 // VPInstructions without underlying values, as those will get skipped during
1523 // cost computation.
1524 bool CanCreateNewRecipe =
1525 !isa<VPInstruction>(Def) || !Def->getUnderlyingValue();
1526
1527 VPValue *A;
1528 if (match(Def, m_Trunc(m_ZExtOrSExt(m_VPValue(A))))) {
1529 Type *TruncTy = Def->getScalarType();
1530 Type *ATy = A->getScalarType();
1531 if (TruncTy == ATy) {
1532 Def->replaceAllUsesWith(A);
1533 } else {
1534 // Don't replace a non-widened cast recipe with a widened cast.
1535 if (!isa<VPWidenCastRecipe>(Def))
1536 return;
1537 if (ATy->getScalarSizeInBits() < TruncTy->getScalarSizeInBits()) {
1538
1539 unsigned ExtOpcode = match(Def->getOperand(0), m_SExt(m_VPValue()))
1540 ? Instruction::SExt
1541 : Instruction::ZExt;
1542 auto *Ext = Builder.createWidenCast(Instruction::CastOps(ExtOpcode), A,
1543 TruncTy);
1544 if (auto *UnderlyingExt = Def->getOperand(0)->getUnderlyingValue()) {
1545 // UnderlyingExt has distinct return type, used to retain legacy cost.
1546 Ext->setUnderlyingValue(UnderlyingExt);
1547 }
1548 Def->replaceAllUsesWith(Ext);
1549 } else if (ATy->getScalarSizeInBits() > TruncTy->getScalarSizeInBits()) {
1550 auto *Trunc = Builder.createWidenCast(Instruction::Trunc, A, TruncTy);
1551 Def->replaceAllUsesWith(Trunc);
1552 }
1553 }
1554 }
1555
1556 if (simplifyLogicalRecipe(Def, Builder, CanCreateNewRecipe))
1557 return;
1558
1559 VPValue *X, *Y, *C;
1560 if (match(Def, m_c_Add(m_VPValue(A), m_ZeroInt())))
1561 return Def->replaceAllUsesWith(A);
1562
1563 if (match(Def, m_c_Mul(m_VPValue(A), m_One())))
1564 return Def->replaceAllUsesWith(A);
1565
1566 if (match(Def, m_c_Mul(m_VPValue(A), m_ZeroInt())))
1567 return Def->replaceAllUsesWith(Plan->getZero(Def->getScalarType()));
1568
1569 if (CanCreateNewRecipe && match(Def, m_c_Mul(m_VPValue(A), m_AllOnes()))) {
1570 // Preserve nsw from the Mul on the new Sub.
1572 false, cast<VPRecipeWithIRFlags>(Def)->hasNoSignedWrap()};
1573 return Def->replaceAllUsesWith(Builder.createSub(
1574 Plan->getZero(A->getScalarType()), A, Def->getDebugLoc(), "", NW));
1575 }
1576
1577 if (CanCreateNewRecipe &&
1579 // Preserve nsw from the Add and the Sub, if it's present on both, on the
1580 // new Sub.
1582 false,
1583 cast<VPRecipeWithIRFlags>(Def)->hasNoSignedWrap() &&
1584 cast<VPRecipeWithIRFlags>(Def->getOperand(Def->getOperand(0) == X))
1585 ->hasNoSignedWrap()};
1586 return Def->replaceAllUsesWith(
1587 Builder.createSub(X, Y, Def->getDebugLoc(), "", NW));
1588 }
1589
1590 const APInt *APC;
1591 if (CanCreateNewRecipe && match(Def, m_c_Mul(m_VPValue(A), m_APInt(APC))) &&
1592 APC->isPowerOf2()) {
1593 auto *MulR = cast<VPRecipeWithIRFlags>(Def);
1594 unsigned ShiftAmt = APC->exactLogBase2();
1595 VPIRFlags::WrapFlagsTy NW(MulR->hasNoUnsignedWrap(),
1596 MulR->hasNoSignedWrap() &&
1597 ShiftAmt != APC->getBitWidth() - 1);
1598 return Def->replaceAllUsesWith(Builder.createNaryOp(
1599 Instruction::Shl,
1600 {A, Plan->getConstantInt(APC->getBitWidth(), ShiftAmt)}, NW,
1601 Def->getDebugLoc()));
1602 }
1603
1604 if (CanCreateNewRecipe && match(Def, m_UDiv(m_VPValue(A), m_APInt(APC))) &&
1605 APC->isPowerOf2())
1606 return Def->replaceAllUsesWith(Builder.createNaryOp(
1607 Instruction::LShr,
1608 {A, Plan->getConstantInt(APC->getBitWidth(), APC->exactLogBase2())},
1609 *cast<VPRecipeWithIRFlags>(Def), Def->getDebugLoc()));
1610
1611 if (match(Def, m_Not(m_VPValue(A)))) {
1612 if (match(A, m_Not(m_VPValue(A))))
1613 return Def->replaceAllUsesWith(A);
1614
1615 // Try to fold Not into compares by adjusting the predicate in-place.
1616 CmpPredicate Pred;
1617 if (match(A, m_Cmp(Pred, m_VPValue(), m_VPValue()))) {
1618 auto *Cmp = cast<VPRecipeWithIRFlags>(A);
1619 if (all_of(Cmp->users(),
1621 m_Not(m_Specific(Cmp)),
1622 m_Select(m_Specific(Cmp), m_VPValue(), m_VPValue()))))) {
1623 Cmp->setPredicate(CmpInst::getInversePredicate(Pred));
1624 for (VPUser *U : to_vector(Cmp->users())) {
1625 auto *R = cast<VPSingleDefRecipe>(U);
1626 if (match(R, m_Select(m_Specific(Cmp), m_VPValue(X), m_VPValue(Y)))) {
1627 // select (cmp pred), x, y -> select (cmp inv_pred), y, x
1628 R->setOperand(1, Y);
1629 R->setOperand(2, X);
1630 } else {
1631 // not (cmp pred) -> cmp inv_pred
1632 assert(match(R, m_Not(m_Specific(Cmp))) && "Unexpected user");
1633 R->replaceAllUsesWith(Cmp);
1634 }
1635 }
1636 // If Cmp doesn't have a debug location, use the one from the negation,
1637 // to preserve the location.
1638 if (!Cmp->getDebugLoc() && Def->getDebugLoc())
1639 Cmp->setDebugLoc(Def->getDebugLoc());
1640 }
1641 }
1642 }
1643
1644 // Fold any-of (fcmp uno %A, %A), (fcmp uno %B, %B), ... ->
1645 // any-of (fcmp uno %A, %B), ...
1646 if (match(Def, m_AnyOf())) {
1648 VPRecipeBase *UnpairedCmp = nullptr;
1649 for (VPValue *Op : Def->operands()) {
1650 VPValue *X;
1651 if (Op->getNumUsers() > 1 ||
1653 m_Deferred(X)))) {
1654 NewOps.push_back(Op);
1655 } else if (!UnpairedCmp) {
1656 UnpairedCmp = Op->getDefiningRecipe();
1657 } else {
1658 NewOps.push_back(Builder.createFCmp(CmpInst::FCMP_UNO,
1659 UnpairedCmp->getOperand(0), X));
1660 UnpairedCmp = nullptr;
1661 }
1662 }
1663
1664 if (UnpairedCmp)
1665 NewOps.push_back(UnpairedCmp->getVPSingleValue());
1666
1667 if (NewOps.size() < Def->getNumOperands()) {
1668 VPValue *NewAnyOf = Builder.createNaryOp(VPInstruction::AnyOf, NewOps);
1669 return Def->replaceAllUsesWith(NewAnyOf);
1670 }
1671 }
1672
1673 // Fold (fcmp uno %X, %X) or (fcmp uno %Y, %Y) -> fcmp uno %X, %Y
1674 // This is useful for fmax/fmin without fast-math flags, where we need to
1675 // check if any operand is NaN.
1676 if (CanCreateNewRecipe &&
1678 m_Deferred(X)),
1680 m_Deferred(Y))))) {
1681 VPValue *NewCmp = Builder.createFCmp(CmpInst::FCMP_UNO, X, Y);
1682 return Def->replaceAllUsesWith(NewCmp);
1683 }
1684
1685 // Remove redundant DerviedIVs, that is 0 + A * 1 -> A and 0 + 0 * x -> 0.
1686 if ((match(Def, m_DerivedIV(m_ZeroInt(), m_VPValue(A), m_One())) ||
1687 match(Def, m_DerivedIV(m_ZeroInt(), m_ZeroInt(), m_VPValue()))) &&
1688 Def->getOperand(1)->getScalarType() == Def->getScalarType())
1689 return Def->replaceAllUsesWith(Def->getOperand(1));
1690
1692 m_One()))) {
1693 Type *WideStepTy = Def->getScalarType();
1694 if (X->getScalarType() != WideStepTy)
1695 X = Builder.createWidenCast(Instruction::Trunc, X, WideStepTy);
1696 Def->replaceAllUsesWith(X);
1697 return;
1698 }
1699
1700 // For i1 vp.merges produced by AnyOf reductions:
1701 // vp.merge true, (or x, y), x, evl -> vp.merge y, true, x, evl
1703 m_VPValue(X), m_VPValue())) &&
1705 Def->getScalarType()->isIntegerTy(1)) {
1706 Def->setOperand(1, Def->getOperand(0));
1707 Def->setOperand(0, Y);
1708 return;
1709 }
1710
1711 // Simplify MaskedCond with no block mask to its single operand.
1713 !cast<VPInstruction>(Def)->isMasked())
1714 return Def->replaceAllUsesWith(Def->getOperand(0));
1715
1716 // Look through ExtractLastLane.
1717 if (match(Def, m_ExtractLastLane(m_VPValue(A)))) {
1718 if (match(A, m_BuildVector())) {
1719 auto *BuildVector = cast<VPInstruction>(A);
1720 Def->replaceAllUsesWith(
1721 BuildVector->getOperand(BuildVector->getNumOperands() - 1));
1722 return;
1723 }
1724
1725 if (match(A, m_Broadcast(m_VPValue(X))))
1726 return Def->replaceAllUsesWith(X);
1727
1729 return Def->replaceAllUsesWith(A);
1730
1731 if (Plan->hasScalarVFOnly())
1732 return Def->replaceAllUsesWith(A);
1733 }
1734
1735 // Look through ExtractPenultimateElement (BuildVector ....).
1737 auto *BuildVector = cast<VPInstruction>(Def->getOperand(0));
1738 Def->replaceAllUsesWith(
1739 BuildVector->getOperand(BuildVector->getNumOperands() - 2));
1740 return;
1741 }
1742
1743 uint64_t Idx;
1745 auto *BuildVector = cast<VPInstruction>(Def->getOperand(0));
1746 Def->replaceAllUsesWith(BuildVector->getOperand(Idx));
1747 return;
1748 }
1749
1750 if (match(Def, m_BuildVector()) && all_equal(Def->operands())) {
1751 Def->replaceAllUsesWith(
1752 Builder.createNaryOp(VPInstruction::Broadcast, Def->getOperand(0)));
1753 return;
1754 }
1755
1756 // Replace uses of a BuildVector by users that only use its first lane with
1757 // its first operand directly.
1758 if (match(Def, m_BuildVector())) {
1759 Def->replaceUsesWithIf(Def->getOperand(0), [Def](VPUser &U, unsigned) {
1760 return U.usesFirstLaneOnly(Def);
1761 });
1762 }
1763
1764 // Look through broadcast of single-scalar when used as select conditions; in
1765 // that case the scalar condition can be used directly.
1766 if (match(Def,
1769 "broadcast operand must be single-scalar");
1770 Def->setOperand(0, C);
1771 return;
1772 }
1773
1774 if (match(Def, m_Broadcast(m_VPValue(X))))
1775 return Def->replaceUsesWithIf(
1776 X, [Def](const VPUser &U, unsigned) { return U.usesScalars(Def); });
1777
1779 if (Def->getNumOperands() == 1) {
1780 Def->replaceAllUsesWith(Def->getOperand(0));
1781 return;
1782 }
1783 if (auto *Phi = dyn_cast<VPFirstOrderRecurrencePHIRecipe>(Def)) {
1784 if (all_equal(Phi->incoming_values()))
1785 Phi->replaceAllUsesWith(Phi->getOperand(0));
1786 }
1787 return;
1788 }
1789
1790 VPIRValue *IRV;
1791 if (Def->getNumOperands() == 1 &&
1793 return Def->replaceAllUsesWith(IRV);
1794
1795 // Some simplifications can only be applied after unrolling. Perform them
1796 // below.
1797 if (!Plan->isUnrolled())
1798 return;
1799
1800 // After unrolling, extract-lane may be used to extract values from multiple
1801 // scalar sources. Only simplify when extracting from a single scalar source.
1802 VPValue *LaneToExtract;
1803 if (match(Def, m_ExtractLane(m_VPValue(LaneToExtract), m_VPValue(A)))) {
1804 // Simplify extract-lane(%lane_num, %scalar_val) -> %scalar_val.
1806 return Def->replaceAllUsesWith(A);
1807
1808 // Replace extract-lane(0, canonical-WIDEN-INDUCTION) with the region's
1809 // scalar canonical IV.
1811 if (match(LaneToExtract, m_ZeroInt()) &&
1812 match(A, m_CanonicalWidenIV(WidenIV)))
1813 return Def->replaceAllUsesWith(WidenIV->getRegion()->getCanonicalIV());
1814
1815 // Simplify extract-lane with single source to extract-element.
1816 Def->replaceAllUsesWith(Builder.createNaryOp(
1817 Instruction::ExtractElement, {A, LaneToExtract}, Def->getDebugLoc()));
1818 return;
1819 }
1820
1821 // Look for cycles where Def is of the form:
1822 // X = phi(0, IVInc) ; used only by IVInc, or by IVInc and Inc = X + Y
1823 // IVInc = X + Step ; used by X and Def
1824 // Def = IVInc + Y
1825 // Fold the increment Y into the phi's start value, replace Def with IVInc,
1826 // and if Inc exists, replace it with X.
1827 if (match(Def, m_Add(m_Add(m_VPValue(X), m_VPValue()), m_VPValue(Y))) &&
1828 isa<VPIRValue>(Y) &&
1829 match(X, m_VPPhi(m_ZeroInt(), m_Specific(Def->getOperand(0))))) {
1830 auto *Phi = cast<VPPhi>(X);
1831 auto *IVInc = Def->getOperand(0);
1832 if (IVInc->getNumUsers() == 2) {
1833 // If Phi has a second user (besides IVInc's defining recipe), it must
1834 // be Inc = Phi + Y for the fold to apply.
1836 findUserOf(Phi, m_Add(m_Specific(Phi), m_Specific(Y))));
1837 if (Phi->getNumUsers() == 1 || (Phi->getNumUsers() == 2 && Inc)) {
1838 Def->replaceAllUsesWith(IVInc);
1839 if (Inc)
1840 Inc->replaceAllUsesWith(Phi);
1841 Phi->setOperand(0, Y);
1842 return;
1843 }
1844 }
1845 }
1846
1847 // Simplify unrolled VectorPointer without offset, or with zero offset, to
1848 // just the pointer operand.
1849 if (auto *VPR = dyn_cast<VPVectorPointerRecipe>(Def))
1850 if (!VPR->getVFxPart() || match(VPR->getVFxPart(), m_ZeroInt()))
1851 return VPR->replaceAllUsesWith(VPR->getOperand(0));
1852
1853 // VPScalarIVSteps after unrolling can be replaced by their start value, if
1854 // the start index is zero and only the first lane 0 is demanded.
1855 if (auto *Steps = dyn_cast<VPScalarIVStepsRecipe>(Def)) {
1856 if (!Steps->getStartIndex() && vputils::onlyFirstLaneUsed(Steps)) {
1857 Steps->replaceAllUsesWith(Steps->getOperand(0));
1858 return;
1859 }
1860 }
1861 // Simplify redundant ReductionStartVector recipes after unrolling.
1862 VPValue *StartV;
1864 m_VPValue(StartV), m_VPValue(), m_VPValue()))) {
1865 Def->replaceUsesWithIf(StartV, [](const VPUser &U, unsigned Idx) {
1866 auto *PhiR = dyn_cast<VPReductionPHIRecipe>(&U);
1867 return PhiR && PhiR->isInLoop();
1868 });
1869 return;
1870 }
1871
1872 if (Plan->getConcreteUF() == 1 && match(Def, m_ExtractLastPart(m_VPValue(A))))
1873 return Def->replaceAllUsesWith(A);
1874}
1875
1885
1886/// Removes the permutation pattern \p Perm from any elementwise operations
1887/// in the plan, by constructing a new permutation via \p Build.
1888/// e.g. binop(perm(x), perm(y)) -> perm(binop(x,y)).
1889template <typename Match_t, typename Builder>
1890static void pullOutPermutations(VPlan &Plan, Match_t Perm, Builder Build) {
1892 vp_depth_first_deep(Plan.getEntry()))) {
1893 for (VPRecipeBase &R : make_early_inc_range(*VPBB)) {
1894 auto *Def = dyn_cast<VPSingleDefRecipe>(&R);
1895 if (!Def || !vputils::isElementwise(Def))
1896 continue;
1897
1898 // At least one of the ops must be a permutation.
1899 if (!any_of(Def->operands(), match_fn(Perm(m_VPValue()))))
1900 continue;
1901
1902 // All operands must be permuted or a live in (splat).
1903 if (!all_of(
1904 Def->operands(),
1906 continue;
1907
1908 VPValue *X;
1909 // Remove the inner permutations.
1910 for (unsigned I = 0; I < Def->getNumOperands(); I++)
1911 if (match(Def->getOperand(I), Perm(m_VPValue(X))))
1912 Def->setOperand(I, X);
1913
1914 VPSingleDefRecipe *Res = Build(Def);
1915 Res->insertAfter(Def);
1916 Def->replaceUsesWithIf(
1917 Res, [&Res](VPUser &U, unsigned _) { return &U != Res; });
1918 }
1919 }
1920}
1921
1923 // Pull out reverses from any elementwise op.
1924 // binop(reverse(x), reverse(y)) -> reverse(binop(x,y))
1926 Plan, [](const auto &X) { return m_Reverse(X); },
1927 [](auto *X) { return new VPInstruction(VPInstruction::Reverse, X); });
1928
1929 // reverse(reverse(x)) -> x
1930 VPValue *X;
1933 for (VPRecipeBase &R : make_early_inc_range(*VPBB))
1934 if (match(&R, m_Reverse(m_Reverse(m_VPValue(X)))))
1935 R.getVPSingleValue()->replaceAllUsesWith(X);
1936}
1937
1938/// Reassociate (headermask && x) && y -> headermask && (x && y) to allow the
1939/// header mask to be simplified further when tail folding, e.g. in
1940/// optimizeEVLMasks.
1941static void reassociateHeaderMask(VPlan &Plan) {
1942 VPValue *HeaderMask = Plan.getVectorLoopRegion()->getHeaderMask();
1943 if (!HeaderMask)
1944 return;
1945
1946 SmallVector<VPUser *> Worklist;
1947 for (VPUser *U : HeaderMask->users())
1948 if (match(U, m_LogicalAnd(m_Specific(HeaderMask), m_VPValue())))
1950
1951 while (!Worklist.empty()) {
1952 auto *R = dyn_cast<VPSingleDefRecipe>(Worklist.pop_back_val());
1953 VPValue *X, *Y;
1954 if (!R || !match(R, m_LogicalAnd(
1955 m_LogicalAnd(m_Specific(HeaderMask), m_VPValue(X)),
1956 m_VPValue(Y))))
1957 continue;
1958 append_range(Worklist, R->users());
1959 VPBuilder Builder(R);
1960 R->replaceAllUsesWith(
1961 Builder.createLogicalAnd(HeaderMask, Builder.createLogicalAnd(X, Y)));
1962 }
1963}
1964
1965static std::optional<Instruction::BinaryOps>
1967 switch (ID) {
1968 case Intrinsic::masked_udiv:
1969 return Instruction::UDiv;
1970 case Intrinsic::masked_sdiv:
1971 return Instruction::SDiv;
1972 case Intrinsic::masked_urem:
1973 return Instruction::URem;
1974 case Intrinsic::masked_srem:
1975 return Instruction::SRem;
1976 default:
1977 return {};
1978 }
1979}
1980
1982 if (Plan.hasScalarVFOnly())
1983 return;
1984
1986 vp_depth_first_deep(Plan.getEntry()))) {
1987 for (VPRecipeBase &R : make_early_inc_range(reverse(*VPBB))) {
1990 continue;
1991 auto *RepR = dyn_cast<VPReplicateRecipe>(&R);
1992 if (RepR && (RepR->isSingleScalar() || RepR->isPredicated()))
1993 continue;
1994
1995 auto *RepOrWidenR = cast<VPRecipeWithIRFlags>(&R);
1996 if (RepR && RepR->getOpcode() == Instruction::Store &&
1997 vputils::isSingleScalar(RepR->getOperand(1))) {
1998 auto *Clone = new VPReplicateRecipe(
1999 RepOrWidenR->getUnderlyingInstr(), RepOrWidenR->operands(),
2000 true /*IsSingleScalar*/, nullptr /*Mask*/, *RepR /*Flags*/,
2001 *RepR /*Metadata*/, RepR->getDebugLoc());
2002 Clone->insertBefore(RepOrWidenR);
2003 VPBuilder Builder(Clone);
2004 VPValue *ExtractOp = Clone->getOperand(0);
2005 if (vputils::isUniformAcrossVFsAndUFs(RepR->getOperand(1)))
2006 ExtractOp =
2007 Builder.createNaryOp(VPInstruction::ExtractLastPart, ExtractOp);
2008 ExtractOp =
2009 Builder.createNaryOp(VPInstruction::ExtractLastLane, ExtractOp);
2010 Clone->setOperand(0, ExtractOp);
2011 RepR->eraseFromParent();
2012 continue;
2013 }
2014
2015 // Narrow llvm.masked.{u,s}{div,rem} intrinsics with a safe divisor.
2016 if (auto *IntrR = dyn_cast<VPWidenIntrinsicRecipe>(RepOrWidenR)) {
2017 if (!vputils::onlyFirstLaneUsed(IntrR))
2018 continue;
2019 auto Opc = getUnmaskedDivRemOpcode(IntrR->getVectorIntrinsicID());
2020 if (!Opc)
2021 continue;
2022 VPBuilder Builder(IntrR);
2023 VPValue *SafeDivisor = Builder.createSelect(
2024 IntrR->getOperand(2), IntrR->getOperand(1),
2025 Plan.getConstantInt(IntrR->getScalarType(), 1));
2026 VPValue *Clone = Builder.createNaryOp(
2027 *Opc, {IntrR->getOperand(0), SafeDivisor},
2028 VPIRFlags::getDefaultFlags(*Opc), IntrR->getDebugLoc());
2029 IntrR->replaceAllUsesWith(Clone);
2030 IntrR->eraseFromParent();
2031 continue;
2032 }
2033
2034 // Skip recipes that aren't single scalars.
2035 if (!vputils::isSingleScalar(RepOrWidenR))
2036 continue;
2037
2038 // Predicate to check if a user of Op introduces extra broadcasts.
2039 auto IntroducesBCastOf = [](const VPValue *Op) {
2040 return [Op](const VPUser *U) {
2041 if (auto *VPI = dyn_cast<VPInstruction>(U)) {
2045 VPI->getOpcode()))
2046 return false;
2047 }
2048 return !U->usesScalars(Op);
2049 };
2050 };
2051
2052 if (any_of(RepOrWidenR->users(), IntroducesBCastOf(RepOrWidenR)) &&
2053 none_of(RepOrWidenR->operands(), [&](VPValue *Op) {
2054 if (any_of(
2055 make_filter_range(Op->users(), not_equal_to(RepOrWidenR)),
2056 IntroducesBCastOf(Op)))
2057 return false;
2058 // Non-constant live-ins require broadcasts, while constants do not
2059 // need explicit broadcasts.
2060 bool LiveInNeedsBroadcast =
2061 isa<VPIRValue>(Op) && !isa<VPConstant>(Op);
2062 auto *OpR = dyn_cast<VPReplicateRecipe>(Op);
2063 return LiveInNeedsBroadcast || (OpR && OpR->isSingleScalar());
2064 }))
2065 continue;
2066
2067 auto *Clone = VPBuilder::createSingleScalarOp(
2068 getOpcodeOrIntrinsicID(RepOrWidenR)->second, RepOrWidenR->operands(),
2069 /*Mask=*/nullptr, *RepOrWidenR, {}, DebugLoc::getUnknown(),
2070 RepOrWidenR->getUnderlyingInstr());
2071 Clone->insertBefore(RepOrWidenR);
2072 RepOrWidenR->replaceAllUsesWith(Clone);
2073 if (isDeadRecipe(*RepOrWidenR))
2074 RepOrWidenR->eraseFromParent();
2075 }
2076 }
2077}
2078
2079/// Try to see if all of \p Blend's masks share a common value logically and'ed
2080/// and remove it from the masks.
2082 if (Blend->isNormalized())
2083 return;
2084 VPValue *CommonEdgeMask;
2085 if (!match(Blend->getMask(0),
2086 m_LogicalAnd(m_VPValue(CommonEdgeMask), m_VPValue())))
2087 return;
2088 for (unsigned I = 0; I < Blend->getNumIncomingValues(); I++)
2089 if (!match(Blend->getMask(I),
2090 m_LogicalAnd(m_Specific(CommonEdgeMask), m_VPValue())))
2091 return;
2092 for (unsigned I = 0; I < Blend->getNumIncomingValues(); I++)
2093 Blend->setMask(I, Blend->getMask(I)->getDefiningRecipe()->getOperand(1));
2094}
2095
2096/// Normalize and simplify VPBlendRecipes. Should be run after simplifyRecipes
2097/// to make sure the masks are simplified.
2098static void simplifyBlends(VPlan &Plan) {
2101 for (VPRecipeBase &R : make_early_inc_range(*VPBB)) {
2102 auto *Blend = dyn_cast<VPBlendRecipe>(&R);
2103 if (!Blend)
2104 continue;
2105
2106 removeCommonBlendMask(Blend);
2107
2108 // Try to remove redundant blend recipes.
2109 SmallPtrSet<VPValue *, 4> UniqueValues;
2110 if (Blend->isNormalized() || !match(Blend->getMask(0), m_False()))
2111 UniqueValues.insert(Blend->getIncomingValue(0));
2112 for (unsigned I = 1; I != Blend->getNumIncomingValues(); ++I)
2113 if (!match(Blend->getMask(I), m_False()))
2114 UniqueValues.insert(Blend->getIncomingValue(I));
2115
2116 if (UniqueValues.size() == 1) {
2117 Blend->replaceAllUsesWith(*UniqueValues.begin());
2118 Blend->eraseFromParent();
2119 continue;
2120 }
2121
2122 if (Blend->isNormalized())
2123 continue;
2124
2125 // Normalize the blend so its first incoming value is used as the initial
2126 // value with the others blended into it.
2127
2128 unsigned StartIndex = 0;
2129 for (unsigned I = 0; I != Blend->getNumIncomingValues(); ++I) {
2130 // If a value's mask is used only by the blend then is can be deadcoded.
2131 // TODO: Find the most expensive mask that can be deadcoded, or a mask
2132 // that's used by multiple blends where it can be removed from them all.
2133 VPValue *Mask = Blend->getMask(I);
2134 if (Mask->hasOneUse() && !match(Mask, m_False())) {
2135 StartIndex = I;
2136 break;
2137 }
2138 }
2139
2140 SmallVector<VPValue *, 4> OperandsWithMask;
2141 OperandsWithMask.push_back(Blend->getIncomingValue(StartIndex));
2142
2143 for (unsigned I = 0; I != Blend->getNumIncomingValues(); ++I) {
2144 if (I == StartIndex)
2145 continue;
2146 OperandsWithMask.push_back(Blend->getIncomingValue(I));
2147 OperandsWithMask.push_back(Blend->getMask(I));
2148 }
2149
2150 auto *NewBlend =
2151 new VPBlendRecipe(cast_or_null<PHINode>(Blend->getUnderlyingValue()),
2152 OperandsWithMask, *Blend, Blend->getDebugLoc());
2153 NewBlend->insertBefore(&R);
2154
2155 VPValue *DeadMask = Blend->getMask(StartIndex);
2156 Blend->replaceAllUsesWith(NewBlend);
2157 Blend->eraseFromParent();
2159
2160 /// Simplify BLEND %a, %b, Not(%mask) -> BLEND %b, %a, %mask.
2161 VPValue *NewMask;
2162 if (NewBlend->getNumOperands() == 3 &&
2163 match(NewBlend->getMask(1), m_Not(m_VPValue(NewMask)))) {
2164 VPValue *Inc0 = NewBlend->getOperand(0);
2165 VPValue *Inc1 = NewBlend->getOperand(1);
2166 VPValue *OldMask = NewBlend->getOperand(2);
2167 NewBlend->setOperand(0, Inc1);
2168 NewBlend->setOperand(1, Inc0);
2169 NewBlend->setOperand(2, NewMask);
2170 if (OldMask->user_empty())
2171 cast<VPInstruction>(OldMask)->eraseFromParent();
2172 }
2173 }
2174 }
2175}
2176
2177/// Optimize the width of vector induction variables in \p Plan based on a known
2178/// constant Trip Count, \p BestVF and \p BestUF.
2180 ElementCount BestVF,
2181 unsigned BestUF) {
2182 // Only proceed if we have not completely removed the vector region.
2183 if (!Plan.getVectorLoopRegion())
2184 return false;
2185
2186 const APInt *TC;
2187 if (!BestVF.isFixed() || !match(Plan.getTripCount(), m_APInt(TC)))
2188 return false;
2189
2190 // Calculate the minimum power-of-2 bit width that can fit the known TC, VF
2191 // and UF. Returns at least 8.
2192 auto ComputeBitWidth = [](APInt TC, uint64_t Align) {
2193 APInt AlignedTC =
2196 APInt MaxVal = AlignedTC - 1;
2197 return std::max<unsigned>(PowerOf2Ceil(MaxVal.getActiveBits()), 8);
2198 };
2199 unsigned NewBitWidth =
2200 ComputeBitWidth(*TC, BestVF.getKnownMinValue() * BestUF);
2201
2202 LLVMContext &Ctx = Plan.getContext();
2203 auto *NewIVTy = IntegerType::get(Ctx, NewBitWidth);
2204
2205 bool MadeChange = false;
2206
2207 VPBasicBlock *HeaderVPBB = Plan.getVectorLoopRegion()->getEntryBasicBlock();
2208 for (VPRecipeBase &Phi : HeaderVPBB->phis()) {
2209 // Currently only handle canonical IVs as it is trivial to replace the start
2210 // and stop values, and we currently only perform the optimization when the
2211 // IV has a single use.
2213 if (!match(&Phi, m_CanonicalWidenIV(WideIV)))
2214 continue;
2215 if (WideIV->hasMoreThanOneUniqueUser() ||
2216 NewIVTy == WideIV->getScalarType())
2217 continue;
2218
2219 // Currently only handle cases where the single user is a header-mask
2220 // comparison with the backedge-taken-count.
2221 VPUser *SingleUser = WideIV->getSingleUser();
2222 if (!SingleUser ||
2223 !match(SingleUser,
2224 m_ICmp(m_Specific(WideIV),
2226 continue;
2227
2228 // Update IV operands and comparison bound to use new narrower type.
2229 assert(!WideIV->getTruncInst() &&
2230 "canonical IV is not expected to have a truncation");
2231 auto *NewWideIV = new VPWidenIntOrFpInductionRecipe(
2232 WideIV->getPHINode(), Plan.getZero(NewIVTy),
2233 Plan.getConstantInt(NewIVTy, 1), WideIV->getVFValue(),
2234 WideIV->getInductionDescriptor(), *WideIV, WideIV->getDebugLoc());
2235 NewWideIV->insertBefore(WideIV);
2236
2237 auto *NewBTC = new VPWidenCastRecipe(
2238 Instruction::Trunc, Plan.getOrCreateBackedgeTakenCount(), NewIVTy,
2239 nullptr, VPIRFlags::getDefaultFlags(Instruction::Trunc));
2240 Plan.getVectorPreheader()->appendRecipe(NewBTC);
2241 auto *Cmp = cast<VPInstruction>(WideIV->getSingleUser());
2242 Cmp->replaceAllUsesWith(
2243 VPBuilder(Cmp).createICmp(Cmp->getPredicate(), NewWideIV, NewBTC));
2244
2245 MadeChange = true;
2246 }
2247
2248 return MadeChange;
2249}
2250
2251/// Return true if \p Cond is known to be true for given \p BestVF and \p
2252/// BestUF.
2254 ElementCount BestVF, unsigned BestUF,
2257 return any_of(Cond->getDefiningRecipe()->operands(), [&Plan, BestVF, BestUF,
2258 &PSE](VPValue *C) {
2259 return isConditionTrueViaVFAndUF(C, Plan, BestVF, BestUF, PSE);
2260 });
2261
2262 auto *CanIV = Plan.getVectorLoopRegion()->getCanonicalIV();
2265 m_c_Add(m_Specific(CanIV), m_Specific(&Plan.getVFxUF())),
2266 m_Specific(&Plan.getVectorTripCount()))))
2267 return false;
2268
2269 // The compare checks CanIV + VFxUF == vector trip count. The vector trip
2270 // count is not conveniently available as SCEV so far, so we compare directly
2271 // against the original trip count. This is stricter than necessary, as we
2272 // will only return true if the trip count == vector trip count.
2273 const SCEV *VectorTripCount =
2275 if (isa<SCEVCouldNotCompute>(VectorTripCount))
2276 VectorTripCount = vputils::getSCEVExprForVPValue(Plan.getTripCount(), PSE);
2277 assert(!isa<SCEVCouldNotCompute>(VectorTripCount) &&
2278 "Trip count SCEV must be computable");
2279 ScalarEvolution &SE = *PSE.getSE();
2280 ElementCount NumElements = BestVF.multiplyCoefficientBy(BestUF);
2281 const SCEV *C = SE.getElementCount(VectorTripCount->getType(), NumElements);
2282 return SE.isKnownPredicate(CmpInst::ICMP_EQ, VectorTripCount, C);
2283}
2284
2285/// Try to replace multiple active lane masks used for control flow with
2286/// a single, wide active lane mask instruction followed by multiple
2287/// extract subvector intrinsics. This applies to the active lane mask
2288/// instructions both in the loop and in the preheader.
2289/// Incoming values of all ActiveLaneMaskPHIs are updated to use the
2290/// new extracts from the first active lane mask, which has it's last
2291/// operand (multiplier) set to UF.
2293 unsigned UF) {
2294 if (!EnableWideActiveLaneMask || !VF.isVector() || UF == 1)
2295 return false;
2296
2297 VPRegionBlock *VectorRegion = Plan.getVectorLoopRegion();
2298 VPBasicBlock *ExitingVPBB = VectorRegion->getExitingBasicBlock();
2299 auto *Term = &ExitingVPBB->back();
2300
2301 using namespace llvm::VPlanPatternMatch;
2303 m_VPValue(), m_VPValue(), m_VPValue())))))
2304 return false;
2305
2306 auto *Header = cast<VPBasicBlock>(VectorRegion->getEntry());
2307 LLVMContext &Ctx = Plan.getContext();
2308
2309 auto ExtractFromALM = [&](VPInstruction *ALM,
2310 SmallVectorImpl<VPValue *> &Extracts) {
2311 DebugLoc DL = ALM->getDebugLoc();
2312 for (unsigned Part = 0; Part < UF; ++Part) {
2314 Ops.append({ALM, Plan.getConstantInt(64, VF.getKnownMinValue() * Part)});
2315 auto *Ext =
2316 new VPWidenIntrinsicRecipe(Intrinsic::vector_extract, Ops,
2317 IntegerType::getInt1Ty(Ctx), {}, {}, DL);
2318 Extracts[Part] = Ext;
2319 Ext->insertAfter(ALM);
2320 }
2321 };
2322
2323 // Create a list of each active lane mask phi, ordered by unroll part.
2325 for (VPRecipeBase &R : Header->phis()) {
2327 if (!Phi)
2328 continue;
2329 VPValue *Index = nullptr;
2330 match(Phi->getBackedgeValue(),
2332 assert(Index && "Expected index from ActiveLaneMask instruction");
2333
2334 uint64_t Part;
2335 if (match(Index,
2337 m_VPValue(), m_Mul(m_VPValue(), m_ConstantInt(Part)))))
2338 Phis[Part] = Phi;
2339 else {
2340 // Anything other than a CanonicalIVIncrementForPart is part 0
2341 assert(!match(
2342 Index,
2344 Phis[0] = Phi;
2345 }
2346 }
2347
2348 assert(all_of(Phis, not_equal_to(nullptr)) &&
2349 "Expected one VPActiveLaneMaskPHIRecipe for each unroll part");
2350
2351 auto *EntryALM = cast<VPInstruction>(Phis[0]->getStartValue());
2352 auto *LoopALM = cast<VPInstruction>(Phis[0]->getBackedgeValue());
2353
2354 assert((EntryALM->getOpcode() == VPInstruction::ActiveLaneMask &&
2355 LoopALM->getOpcode() == VPInstruction::ActiveLaneMask) &&
2356 "Expected incoming values of Phi to be ActiveLaneMasks");
2357
2358 // When using wide lane masks, the return type of the get.active.lane.mask
2359 // intrinsic is VF x UF (last operand).
2360 VPValue *ALMMultiplier = Plan.getConstantInt(64, UF);
2361 EntryALM->setOperand(2, ALMMultiplier);
2362 LoopALM->setOperand(2, ALMMultiplier);
2363
2364 // Create UF x extract vectors and insert into preheader.
2365 SmallVector<VPValue *> EntryExtracts(UF);
2366 ExtractFromALM(EntryALM, EntryExtracts);
2367
2368 // Create UF x extract vectors and insert before the loop compare & branch,
2369 // updating the compare to use the first extract.
2370 SmallVector<VPValue *> LoopExtracts(UF);
2371 ExtractFromALM(LoopALM, LoopExtracts);
2372 VPInstruction *Not = cast<VPInstruction>(Term->getOperand(0));
2373 Not->setOperand(0, LoopExtracts[0]);
2374
2375 // Update the incoming values of active lane mask phis.
2376 for (unsigned Part = 0; Part < UF; ++Part) {
2377 Phis[Part]->setStartValue(EntryExtracts[Part]);
2378 Phis[Part]->setBackedgeValue(LoopExtracts[Part]);
2379 }
2380
2381 return true;
2382}
2383
2384/// Try to simplify the branch condition of \p Plan. This may restrict the
2385/// resulting plan to \p BestVF and \p BestUF.
2387 unsigned BestUF,
2389 VPRegionBlock *VectorRegion = Plan.getVectorLoopRegion();
2390 VPBasicBlock *ExitingVPBB = VectorRegion->getExitingBasicBlock();
2391 auto *Term = &ExitingVPBB->back();
2392 VPValue *Cond;
2393 auto m_CanIVInc = m_Add(m_VPValue(), m_Specific(&Plan.getVFxUF()));
2394 // Check if the branch condition compares the canonical IV increment (for main
2395 // loop), or the canonical IV increment plus an offset (for epilog loop).
2396 if (match(Term, m_BranchOnCount(
2397 m_CombineOr(m_CanIVInc, m_c_Add(m_CanIVInc, m_LiveIn())),
2398 m_VPValue())) ||
2400 m_VPValue(), m_VPValue(), m_VPValue()))))) {
2401 // Try to simplify the branch condition if VectorTC <= VF * UF when the
2402 // latch terminator is BranchOnCount or BranchOnCond(Not(ActiveLaneMask)).
2403 const SCEV *VectorTripCount =
2405 if (isa<SCEVCouldNotCompute>(VectorTripCount))
2406 VectorTripCount =
2408 assert(!isa<SCEVCouldNotCompute>(VectorTripCount) &&
2409 "Trip count SCEV must be computable");
2410 ScalarEvolution &SE = *PSE.getSE();
2411 ElementCount NumElements = BestVF.multiplyCoefficientBy(BestUF);
2412 const SCEV *C = SE.getElementCount(VectorTripCount->getType(), NumElements);
2413 if (!SE.isKnownPredicate(CmpInst::ICMP_ULE, VectorTripCount, C))
2414 return false;
2415 } else if (match(Term, m_BranchOnCond(m_VPValue(Cond))) ||
2417 // For BranchOnCond, check if we can prove the condition to be true using VF
2418 // and UF.
2419 if (!isConditionTrueViaVFAndUF(Cond, Plan, BestVF, BestUF, PSE))
2420 return false;
2421 } else {
2422 return false;
2423 }
2424
2425 // The vector loop region only executes once. Convert terminator of the
2426 // exiting block to exit in the first iteration.
2427 if (match(Term, m_BranchOnTwoConds())) {
2428 Term->setOperand(1, Plan.getTrue());
2429 return true;
2430 }
2431
2432 auto *BOC = new VPInstruction(VPInstruction::BranchOnCond, Plan.getTrue(), {},
2433 {}, Term->getDebugLoc());
2434 ExitingVPBB->appendRecipe(BOC);
2435 Term->eraseFromParent();
2436
2437 return true;
2438}
2439
2440/// From the definition of llvm.experimental.get.vector.length,
2441/// VPInstruction::ExplicitVectorLength(%AVL) = %AVL when %AVL <= VF.
2445 vp_depth_first_deep(Plan.getEntry()))) {
2446 for (VPRecipeBase &R : *VPBB) {
2447 VPValue *AVL;
2448 if (!match(&R, m_EVL(m_VPValue(AVL))))
2449 continue;
2450
2451 const SCEV *AVLSCEV = vputils::getSCEVExprForVPValue(AVL, PSE);
2452 if (isa<SCEVCouldNotCompute>(AVLSCEV))
2453 continue;
2454 ScalarEvolution &SE = *PSE.getSE();
2455 const SCEV *VFSCEV = SE.getElementCount(AVLSCEV->getType(), VF);
2456 if (!SE.isKnownPredicate(CmpInst::ICMP_ULE, AVLSCEV, VFSCEV))
2457 continue;
2458
2460 AVL, Type::getInt32Ty(Plan.getContext()), AVLSCEV->getType(),
2461 R.getDebugLoc());
2462 if (Trunc != AVL) {
2463 auto *TruncR = cast<VPSingleDefRecipe>(Trunc);
2464 const DataLayout &DL = Plan.getDataLayout();
2465 if (VPValue *Folded = tryToFoldLiveIns(*TruncR, TruncR->operands(), DL))
2466 Trunc = Folded;
2467 }
2468 R.getVPSingleValue()->replaceAllUsesWith(Trunc);
2469 return true;
2470 }
2471 }
2472 return false;
2473}
2474
2476 unsigned BestUF,
2478 assert(Plan.hasVF(BestVF) && "BestVF is not available in Plan");
2479 assert(Plan.hasUF(BestUF) && "BestUF is not available in Plan");
2480
2481 bool MadeChange = tryToReplaceALMWithWideALM(Plan, BestVF, BestUF);
2482 MadeChange |= simplifyBranchConditionForVFAndUF(Plan, BestVF, BestUF, PSE);
2483 MadeChange |= optimizeVectorInductionWidthForTCAndVFUF(Plan, BestVF, BestUF);
2484
2485 if (MadeChange) {
2486 Plan.setVF(BestVF);
2487 assert(Plan.getConcreteUF() == BestUF && "BestUF must match the Plan's UF");
2488 }
2489}
2490
2492 for (VPRecipeBase &R :
2494 auto *PhiR = dyn_cast<VPReductionPHIRecipe>(&R);
2495 if (!PhiR)
2496 continue;
2497 RecurKind RK = PhiR->getRecurrenceKind();
2498 if (RK != RecurKind::Add && RK != RecurKind::Mul && RK != RecurKind::Sub &&
2500 continue;
2501
2502 for (VPUser *U : collectUsersRecursively(PhiR))
2503 if (auto *RecWithFlags = dyn_cast<VPRecipeWithIRFlags>(U)) {
2504 RecWithFlags->dropPoisonGeneratingFlags();
2505 }
2506 }
2507}
2508
2509namespace {
2510struct VPCSEDenseMapInfo : public DenseMapInfo<VPSingleDefRecipe *> {
2511 /// If recipe \p R will lower to a GEP with a non-i8 source element type,
2512 /// return that source element type.
2513 static Type *getGEPSourceElementType(const VPSingleDefRecipe *R) {
2514 // All VPInstructions that lower to GEPs must have the i8 source element
2515 // type (as they are PtrAdds), so we omit it.
2517 .Case([](const VPReplicateRecipe *I) -> Type * {
2518 if (auto *GEP = dyn_cast<GetElementPtrInst>(I->getUnderlyingValue()))
2519 return GEP->getSourceElementType();
2520 return nullptr;
2521 })
2522 .Case<VPVectorPointerRecipe, VPWidenGEPRecipe>(
2523 [](auto *I) { return I->getSourceElementType(); })
2524 .Default([](auto *) { return nullptr; });
2525 }
2526
2527 /// Returns true if recipe \p Def can be safely handed for CSE.
2528 static bool canHandle(const VPSingleDefRecipe *Def) {
2529 // We can extend the list of handled recipes in the future,
2530 // provided we account for the data embedded in them while checking for
2531 // equality or hashing.
2532 auto C = getOpcodeOrIntrinsicID(Def);
2533
2534 // The issue with (Insert|Extract)Value is that the index of the
2535 // insert/extract is not a proper operand in LLVM IR, and hence also not in
2536 // VPlan.
2537 if (!C || (!C->first && (C->second == Instruction::InsertValue ||
2538 C->second == Instruction::ExtractValue)))
2539 return false;
2540
2541 // During CSE, we can only handle non-memory recipes, as memory can alias.
2542 return !Def->mayReadOrWriteMemory();
2543 }
2544
2545 /// Hash the underlying data of \p Def.
2546 static unsigned getHashValue(const VPSingleDefRecipe *Def) {
2547 hash_code Result = hash_combine(
2548 Def->getVPRecipeID(), getOpcodeOrIntrinsicID(Def),
2549 getGEPSourceElementType(Def), Def->getScalarType(),
2551 if (auto *RFlags = dyn_cast<VPRecipeWithIRFlags>(Def))
2552 if (RFlags->hasPredicate())
2553 return hash_combine(Result, RFlags->getPredicate());
2554 if (auto *SIVSteps = dyn_cast<VPScalarIVStepsRecipe>(Def))
2555 return hash_combine(Result, SIVSteps->getInductionOpcode());
2556 return Result;
2557 }
2558
2559 /// Check equality of underlying data of \p L and \p R.
2560 static bool isEqual(const VPSingleDefRecipe *L, const VPSingleDefRecipe *R) {
2561 if (L->getVPRecipeID() != R->getVPRecipeID() ||
2563 getGEPSourceElementType(L) != getGEPSourceElementType(R) ||
2565 !equal(L->operands(), R->operands()))
2566 return false;
2568 "must have valid opcode info for both recipes");
2569 if (auto *LFlags = dyn_cast<VPRecipeWithIRFlags>(L))
2570 if (LFlags->hasPredicate() &&
2571 LFlags->getPredicate() !=
2572 cast<VPRecipeWithIRFlags>(R)->getPredicate())
2573 return false;
2574 if (auto *LSIV = dyn_cast<VPScalarIVStepsRecipe>(L))
2575 if (LSIV->getInductionOpcode() !=
2576 cast<VPScalarIVStepsRecipe>(R)->getInductionOpcode())
2577 return false;
2578 // Phi recipes can only be equal if they are in the same VPBB, as they
2579 // implicitly depend on their predecessors.
2580 if (isa<VPWidenPHIRecipe>(L) && L->getParent() != R->getParent())
2581 return false;
2582 // Recipes in replicate regions implicitly depend on predicate. If either
2583 // recipe is in a replicate region, only consider them equal if both have
2584 // the same parent.
2585 const VPRegionBlock *RegionL = L->getRegion();
2586 const VPRegionBlock *RegionR = R->getRegion();
2587 if (((RegionL && RegionL->isReplicator()) ||
2588 (RegionR && RegionR->isReplicator())) &&
2589 L->getParent() != R->getParent())
2590 return false;
2591 return L->getScalarType() == R->getScalarType();
2592 }
2593};
2594} // end anonymous namespace
2595
2596/// Perform a common-subexpression-elimination of VPSingleDefRecipes on the \p
2597/// Plan.
2599 VPDominatorTree VPDT(Plan);
2601
2603 Plan.getEntry());
2605 for (VPRecipeBase &R : *VPBB) {
2606 auto *Def = dyn_cast<VPSingleDefRecipe>(&R);
2607 if (!Def || !VPCSEDenseMapInfo::canHandle(Def))
2608 continue;
2609 if (VPSingleDefRecipe *V = CSEMap.lookup(Def)) {
2610 // V must dominate Def for a valid replacement.
2611 if (!VPDT.dominates(V->getParent(), VPBB))
2612 continue;
2613 // Only keep flags present on both V and Def.
2614 if (auto *RFlags = dyn_cast<VPRecipeWithIRFlags>(V))
2615 RFlags->intersectFlags(*cast<VPRecipeWithIRFlags>(Def));
2616 Def->replaceAllUsesWith(V);
2617 continue;
2618 }
2619 CSEMap[Def] = Def;
2620 }
2621 }
2622}
2623
2624/// Return true if we do not know how to (mechanically) hoist or sink a
2625/// non-memory or memory recipe \p R out of a loop region. When sinking, passing
2626/// \p Sinking = true ensures that assumes aren't sunk.
2628 VPBasicBlock *LastBB,
2629 bool Sinking = false) {
2630 if (!isa<VPReplicateRecipe>(R) || !R.mayReadOrWriteMemory() ||
2632 return vputils::cannotHoistOrSinkRecipe(R, Sinking);
2633
2634 // Check that the memory operation doesn't alias between FirstBB and LastBB.
2635 auto MemLoc = vputils::getMemoryLocation(R);
2636
2637 // TODO: Could make use of SinkStoreInfo::isNoAliasViaDistance by collecting
2638 // stores upfront, and constructing a full SinkStoreInfo.
2639 auto SinkInfo =
2640 Sinking ? std::make_optional(SinkStoreInfo(cast<VPReplicateRecipe>(R)))
2641 : std::nullopt;
2642
2643 return !MemLoc ||
2644 !canHoistOrSinkWithNoAliasCheck(*MemLoc, FirstBB, LastBB, SinkInfo);
2645}
2646
2647/// Move loop-invariant recipes out of the vector loop region in \p Plan.
2648static void licm(VPlan &Plan) {
2649 VPBasicBlock *Preheader = Plan.getVectorPreheader();
2650
2651 // Hoist any loop invariant recipes from the vector loop region to the
2652 // preheader. Preform a shallow traversal of the vector loop region, to
2653 // exclude recipes in replicate regions. Since the top-level blocks in the
2654 // vector loop region are guaranteed to execute if the vector pre-header is,
2655 // we don't need to check speculation safety.
2656 VPRegionBlock *LoopRegion = Plan.getVectorLoopRegion();
2657 assert(Preheader->getSingleSuccessor() == LoopRegion &&
2658 "Expected vector prehader's successor to be the vector loop region");
2660 vp_depth_first_shallow(LoopRegion->getEntry()))) {
2661 for (VPRecipeBase &R : make_early_inc_range(*VPBB)) {
2662 if (cannotHoistOrSinkRecipe(R, LoopRegion->getEntryBasicBlock(),
2663 LoopRegion->getExitingBasicBlock()))
2664 continue;
2665 if (any_of(R.operands(), [](VPValue *Op) {
2666 return !Op->isDefinedOutsideLoopRegions();
2667 }))
2668 continue;
2669 R.moveBefore(*Preheader, Preheader->end());
2670 }
2671 }
2672
2673#ifndef NDEBUG
2674 VPDominatorTree VPDT(Plan);
2675#endif
2676 // Sink recipes with no users inside the vector loop region if all users are
2677 // in the same exit block of the region.
2678 // TODO: Extend to sink recipes from inner loops.
2680 LoopRegion->getEntry());
2682 for (VPRecipeBase &R : make_early_inc_range(reverse(*VPBB))) {
2683 if (cannotHoistOrSinkRecipe(R, LoopRegion->getEntryBasicBlock(),
2684 LoopRegion->getExitingBasicBlock(),
2685 /*Sinking=*/true))
2686 continue;
2687
2688 if (auto *RepR = dyn_cast<VPReplicateRecipe>(&R)) {
2689 assert(!RepR->isPredicated() &&
2690 "Expected prior transformation of predicated replicates to "
2691 "replicate regions");
2692 // narrowToSingleScalarRecipes should have already maximally narrowed
2693 // replicates to single-scalar replicates.
2694 // TODO: When unrolling, replicateByVF doesn't handle sunk
2695 // non-single-scalar replicates correctly.
2696 if (!RepR->isSingleScalar())
2697 continue;
2698
2699 // The pointer operand of stores must be loop-invariant.
2700 if (RepR->getOpcode() == Instruction::Store &&
2701 !RepR->getOperand(1)->isDefinedOutsideLoopRegions())
2702 continue;
2703 }
2704
2705 [[maybe_unused]] auto *RepR = dyn_cast<VPReplicateRecipe>(&R);
2706 assert((!R.mayWriteToMemory() ||
2707 (RepR && RepR->getOpcode() == Instruction::Store &&
2708 RepR->getOperand(1)->isDefinedOutsideLoopRegions())) &&
2709 "The only recipes that may write to memory are expected to be "
2710 "stores with invariant pointer-operand");
2711
2712 // TODO: Use R.definedValues() instead of casting to VPSingleDefRecipe to
2713 // support recipes with multiple defined values (e.g., interleaved loads).
2714 auto *Def = cast<VPSingleDefRecipe>(&R);
2715
2716 // Cannot sink the recipe if the user is defined in a loop region or a
2717 // non-successor of the vector loop region. Cannot sink if user is a phi
2718 // either.
2719 VPBasicBlock *SinkBB = nullptr;
2720 if (any_of(Def->users(), [&SinkBB, &LoopRegion](VPUser *U) {
2721 auto *UserR = cast<VPRecipeBase>(U);
2722 VPBasicBlock *Parent = UserR->getParent();
2723 // TODO: Support sinking when users are in multiple blocks.
2724 if (SinkBB && SinkBB != Parent)
2725 return true;
2726 SinkBB = Parent;
2727 // TODO: If the user is a PHI node, we should check the block of
2728 // incoming value. Support PHI node users if needed.
2729 return UserR->isPhi() || Parent->getEnclosingLoopRegion() ||
2730 Parent->getSinglePredecessor() != LoopRegion;
2731 }))
2732 continue;
2733
2734 if (!SinkBB)
2735 SinkBB = cast<VPBasicBlock>(LoopRegion->getSingleSuccessor());
2736
2737 // TODO: This will need to be a check instead of a assert after
2738 // conditional branches in vectorized loops are supported.
2739 assert(VPDT.properlyDominates(VPBB, SinkBB) &&
2740 "Defining block must dominate sink block");
2741 // TODO: Clone the recipe if users are on multiple exit paths, instead of
2742 // just moving.
2743 Def->moveBefore(*SinkBB, SinkBB->getFirstNonPhi());
2744 }
2745 }
2746}
2747
2749 VPlan &Plan, const MapVector<Instruction *, uint64_t> &MinBWs) {
2750 if (Plan.hasScalarVFOnly())
2751 return;
2752 // Keep track of created truncates, so they can be re-used. Note that we
2753 // cannot use RAUW after creating a new truncate, as this would could make
2754 // other uses have different types for their operands, making them invalidly
2755 // typed.
2757 VPBasicBlock *PH = Plan.getVectorPreheader();
2760 for (VPRecipeBase &R : make_early_inc_range(*VPBB)) {
2763 continue;
2764
2765 VPValue *ResultVPV = R.getVPSingleValue();
2766 auto *UI = cast_or_null<Instruction>(ResultVPV->getUnderlyingValue());
2767 unsigned NewResSizeInBits = MinBWs.lookup(UI);
2768 if (!NewResSizeInBits)
2769 continue;
2770
2771 // If the value wasn't vectorized, we must maintain the original scalar
2772 // type. Skip those here, after incrementing NumProcessedRecipes. Also
2773 // skip casts which do not need to be handled explicitly here, as
2774 // redundant casts will be removed during recipe simplification.
2776 continue;
2777
2778 Type *OldResTy = ResultVPV->getScalarType();
2779 unsigned OldResSizeInBits = OldResTy->getScalarSizeInBits();
2780 assert(OldResTy->isIntegerTy() && "only integer types supported");
2781 (void)OldResSizeInBits;
2782
2783 auto *NewResTy = IntegerType::get(Plan.getContext(), NewResSizeInBits);
2784
2785 // Any wrapping introduced by shrinking this operation shouldn't be
2786 // considered undefined behavior. So, we can't unconditionally copy
2787 // arithmetic wrapping flags to VPW.
2788 if (auto *VPW = dyn_cast<VPRecipeWithIRFlags>(&R))
2789 VPW->dropPoisonGeneratingFlags();
2790
2791 assert((OldResSizeInBits != NewResSizeInBits ||
2792 match(&R, m_ICmp(m_VPValue(), m_VPValue()))) &&
2793 "Only ICmps should not need extending the result.");
2794 assert(!isa<VPWidenStoreRecipe>(&R) && "stores cannot be narrowed");
2795
2796 // For loads/intrinsics we don't recreate the recipe; just wrap the
2797 // original wide result in a ZExt to OldResTy.
2799 if (OldResSizeInBits != NewResSizeInBits) {
2801 Instruction::ZExt, ResultVPV, OldResTy);
2802 ResultVPV->replaceAllUsesWith(Ext);
2803 Ext->setOperand(0, ResultVPV);
2804 }
2805 continue;
2806 }
2807
2808 // Shrink operands by introducing truncates as needed.
2809 unsigned StartIdx =
2810 match(&R, m_Select(m_VPValue(), m_VPValue(), m_VPValue())) ? 1 : 0;
2811 SmallVector<VPValue *> NewOperands(R.operands());
2812 for (VPValue *&Op : drop_begin(NewOperands, StartIdx)) {
2813 unsigned OpSizeInBits = Op->getScalarType()->getScalarSizeInBits();
2814 if (OpSizeInBits == NewResSizeInBits)
2815 continue;
2816 assert(OpSizeInBits > NewResSizeInBits && "nothing to truncate");
2817 auto [ProcessedIter, Inserted] = ProcessedTruncs.try_emplace(Op);
2818 if (Inserted) {
2819 VPBuilder Builder;
2820 if (isa<VPIRValue>(Op))
2821 Builder.setInsertPoint(PH);
2822 else
2823 Builder.setInsertPoint(&R);
2824 ProcessedIter->second =
2825 Builder.createWidenCast(Instruction::Trunc, Op, NewResTy);
2826 }
2827 Op = ProcessedIter->second;
2828 }
2829
2830 auto *NWR = cast<VPWidenRecipe>(&R)->cloneWithOperands(NewOperands);
2831 NWR->insertBefore(&R);
2832
2833 // Wrap NWR in a ZExt to preserve the original wide type for downstream
2834 // users (unless this is an ICmp, which produces i1 regardless).
2835 VPValue *Replacement = NWR->getVPSingleValue();
2836 if (OldResSizeInBits != NewResSizeInBits)
2837 Replacement =
2839 .createWidenCast(Instruction::ZExt, Replacement, OldResTy)
2840 ->getVPSingleValue();
2841 ResultVPV->replaceAllUsesWith(Replacement);
2842 R.eraseFromParent();
2843 }
2844 }
2845}
2846
2847bool VPlanTransforms::removeBranchOnConst(VPlan &Plan, bool OnlyLatches) {
2848 std::optional<VPDominatorTree> VPDT;
2849 if (OnlyLatches)
2850 VPDT.emplace(Plan);
2851
2852 // Collect all blocks before modifying the CFG so we can identify unreachable
2853 // ones after constant branch removal.
2855
2856 bool SimplifiedPhi = false;
2857 for (VPBasicBlock *VPBB : VPBlockUtils::blocksOnly<VPBasicBlock>(AllBlocks)) {
2858 VPValue *Cond;
2859 // Skip blocks that are not terminated by BranchOnCond.
2860 if (VPBB->empty() || !match(&VPBB->back(), m_BranchOnCond(m_VPValue(Cond))))
2861 continue;
2862
2863 if (OnlyLatches && !VPBlockUtils::isLatch(VPBB, *VPDT))
2864 continue;
2865
2866 assert(VPBB->getNumSuccessors() == 2 &&
2867 "Two successors expected for BranchOnCond");
2868 unsigned RemovedIdx;
2869 if (match(Cond, m_True()))
2870 RemovedIdx = 1;
2871 else if (match(Cond, m_False()))
2872 RemovedIdx = 0;
2873 else
2874 continue;
2875
2876 VPBasicBlock *RemovedSucc =
2877 cast<VPBasicBlock>(VPBB->getSuccessors()[RemovedIdx]);
2878 assert(count(RemovedSucc->getPredecessors(), VPBB) == 1 &&
2879 "There must be a single edge between VPBB and its successor");
2880 // Values coming from VPBB into phi recipes of RemovedSucc are removed from
2881 // these recipes.
2882 auto Phis = RemovedSucc->phis();
2883 for (VPRecipeBase &R : Phis)
2884 cast<VPPhiAccessors>(&R)->removeIncomingValueFor(VPBB);
2885 SimplifiedPhi |= !std::empty(Phis);
2886
2887 // Disconnect blocks and remove the terminator.
2888 VPBlockUtils::disconnectBlocks(VPBB, RemovedSucc);
2889 VPBB->back().eraseFromParent();
2890 }
2891
2892 // Compute which blocks are still reachable from the entry after constant
2893 // branch removal.
2896
2897 // Detach all unreachable blocks from their successors, removing their recipes
2898 // and incoming values from phi recipes.
2899 VPSymbolicValue Tmp(nullptr);
2900 for (VPBlockBase *B : AllBlocks) {
2901 if (Reachable.contains(B))
2902 continue;
2903 for (VPBlockBase *Succ : to_vector(B->successors())) {
2904 if (auto *SuccBB = dyn_cast<VPBasicBlock>(Succ))
2905 for (VPRecipeBase &R : SuccBB->phis())
2906 cast<VPPhiAccessors>(&R)->removeIncomingValueFor(B);
2908 }
2909 for (VPBasicBlock *DeadBB :
2911 for (VPRecipeBase &R : make_early_inc_range(*DeadBB)) {
2912 for (VPValue *Def : R.definedValues())
2913 Def->replaceAllUsesWith(&Tmp);
2914 R.eraseFromParent();
2915 }
2916 }
2917 }
2918 return SimplifiedPhi;
2919}
2920
2941
2942// Add a VPActiveLaneMaskPHIRecipe and related recipes to \p Plan and replace
2943// the loop terminator with a branch-on-cond recipe with the negated
2944// active-lane-mask as operand. Note that this turns the loop into an
2945// uncountable one. Only the existing terminator is replaced, all other existing
2946// recipes/users remain unchanged, except for poison-generating flags being
2947// dropped from the canonical IV increment. Return the created
2948// VPActiveLaneMaskPHIRecipe.
2949//
2950// The function adds the following recipes:
2951//
2952// vector.ph:
2953// %EntryInc = canonical-iv-increment-for-part CanonicalIVStart
2954// %EntryALM = active-lane-mask %EntryInc, TC
2955//
2956// vector.body:
2957// ...
2958// %P = active-lane-mask-phi [ %EntryALM, %vector.ph ], [ %ALM, %vector.body ]
2959// ...
2960// %InLoopInc = canonical-iv-increment-for-part CanonicalIVIncrement
2961// %ALM = active-lane-mask %InLoopInc, TC
2962// %Negated = Not %ALM
2963// branch-on-cond %Negated
2964//
2967 VPRegionBlock *TopRegion = Plan.getVectorLoopRegion();
2968 VPBasicBlock *EB = TopRegion->getExitingBasicBlock();
2969 VPValue *StartV = Plan.getZero(TopRegion->getCanonicalIVType());
2970 auto *CanonicalIVIncrement = TopRegion->getOrCreateCanonicalIVIncrement();
2971 // TODO: Check if dropping the flags is needed.
2972 TopRegion->clearCanonicalIVNUW(CanonicalIVIncrement);
2973 DebugLoc DL = CanonicalIVIncrement->getDebugLoc();
2974 // We can't use StartV directly in the ActiveLaneMask VPInstruction, since
2975 // we have to take unrolling into account. Each part needs to start at
2976 // Part * VF
2977 auto *VecPreheader = Plan.getVectorPreheader();
2978 VPBuilder Builder(VecPreheader);
2979
2980 // Create the ActiveLaneMask instruction using the correct start values.
2981 VPValue *TC = Plan.getTripCount();
2982 VPValue *VF = &Plan.getVF();
2983
2984 auto *EntryIncrement =
2985 Builder.createOverflowingOp(VPInstruction::CanonicalIVIncrementForPart,
2986 {StartV, VF}, {}, DL, "index.part.next");
2987
2988 // Create the active lane mask instruction in the VPlan preheader.
2989 VPValue *ALMMultiplier =
2990 Plan.getConstantInt(TopRegion->getCanonicalIVType(), 1);
2991 auto *EntryALM = Builder.createNaryOp(VPInstruction::ActiveLaneMask,
2992 {EntryIncrement, TC, ALMMultiplier}, DL,
2993 "active.lane.mask.entry");
2994
2995 // Now create the ActiveLaneMaskPhi recipe in the main loop using the
2996 // preheader ActiveLaneMask instruction.
2997 auto *LaneMaskPhi =
2999 auto *HeaderVPBB = TopRegion->getEntryBasicBlock();
3000 LaneMaskPhi->insertBefore(*HeaderVPBB, HeaderVPBB->begin());
3001
3002 // Create the active lane mask for the next iteration of the loop before the
3003 // original terminator.
3004 VPRecipeBase *OriginalTerminator = EB->getTerminator();
3005 Builder.setInsertPoint(OriginalTerminator);
3006 auto *InLoopIncrement = Builder.createOverflowingOp(
3008 {CanonicalIVIncrement, &Plan.getVF()}, {}, DL);
3009 auto *ALM = Builder.createNaryOp(VPInstruction::ActiveLaneMask,
3010 {InLoopIncrement, TC, ALMMultiplier}, DL,
3011 "active.lane.mask.next");
3012 LaneMaskPhi->addBackedgeValue(ALM);
3013
3014 // Replace the original terminator with BranchOnCond. We have to invert the
3015 // mask here because a true condition means jumping to the exit block.
3016 auto *NotMask = Builder.createNot(ALM, DL);
3017 Builder.createNaryOp(VPInstruction::BranchOnCond, {NotMask}, DL);
3018 OriginalTerminator->eraseFromParent();
3019 return LaneMaskPhi;
3020}
3021
3023 VPlan &Plan, bool UseActiveLaneMask, bool UseActiveLaneMaskForControlFlow) {
3024 VPRegionBlock *LoopRegion = Plan.getVectorLoopRegion();
3025 VPValue *HeaderMask = LoopRegion->getUsedHeaderMask();
3026 if (!HeaderMask)
3027 return;
3028
3029 if (UseActiveLaneMaskForControlFlow) {
3031 return;
3032 }
3033
3034 VPBasicBlock *Header = LoopRegion->getEntryBasicBlock();
3035 VPBuilder Builder(Header, Header->getFirstNonPhi());
3036 auto *WideCanonicalIV = Builder.insert(new VPWidenCanonicalIVRecipe(
3037 LoopRegion->getCanonicalIV(),
3038 VPIRFlags::WrapFlagsTy(/*HasNUW=*/true, /*HasNSW=*/false)));
3039 VPValue *Mask;
3040 if (UseActiveLaneMask) {
3041 VPValue *ALMMultiplier =
3042 Plan.getConstantInt(LoopRegion->getCanonicalIVType(), 1);
3043 Mask = Builder.createNaryOp(
3045 {WideCanonicalIV, Plan.getTripCount(), ALMMultiplier}, nullptr,
3046 "active.lane.mask");
3047 } else {
3048 Mask = Builder.createICmp(CmpInst::ICMP_ULE, WideCanonicalIV,
3050 }
3051 HeaderMask->replaceAllUsesWith(Mask);
3052}
3053
3054template <typename Op0_t, typename Op1_t> struct RemoveMask_match {
3055 Op0_t In;
3057
3058 RemoveMask_match(const Op0_t &In, Op1_t &Out) : In(In), Out(Out) {}
3059
3060 template <typename OpTy> bool match(OpTy *V) const {
3061 if (m_Specific(In).match(V)) {
3062 Out = nullptr;
3063 return true;
3064 }
3065 return m_LogicalAnd(m_Specific(In), m_VPValue(Out)).match(V);
3066 }
3067};
3068
3069/// Match a specific mask \p In, or a combination of it (logical-and In, Out).
3070/// Returns the remaining part \p Out if so, or nullptr otherwise.
3071template <typename Op0_t, typename Op1_t>
3072static inline RemoveMask_match<Op0_t, Op1_t> m_RemoveMask(const Op0_t &In,
3073 Op1_t &Out) {
3074 return RemoveMask_match<Op0_t, Op1_t>(In, Out);
3075}
3076
3077static std::optional<Intrinsic::ID> getVPDivRemIntrinsic(Intrinsic::ID IntrID) {
3078 switch (IntrID) {
3079 case Intrinsic::masked_udiv:
3080 return Intrinsic::vp_udiv;
3081 case Intrinsic::masked_sdiv:
3082 return Intrinsic::vp_sdiv;
3083 case Intrinsic::masked_urem:
3084 return Intrinsic::vp_urem;
3085 case Intrinsic::masked_srem:
3086 return Intrinsic::vp_srem;
3087 default:
3088 return std::nullopt;
3089 }
3090}
3091
3092/// Try to optimize a \p CurRecipe masked by \p HeaderMask to a corresponding
3093/// EVL-based recipe without the header mask. Returns nullptr if no EVL-based
3094/// recipe could be created.
3095/// \p HeaderMask Header Mask.
3096/// \p CurRecipe Recipe to be transform.
3097/// \p EVL The explicit vector length parameter of vector-predication
3098/// intrinsics.
3100 VPRecipeBase &CurRecipe, VPValue &EVL) {
3101 VPlan *Plan = CurRecipe.getParent()->getPlan();
3102 DebugLoc DL = CurRecipe.getDebugLoc();
3103 VPValue *Addr, *Mask, *EndPtr;
3104
3105 /// Adjust any end pointers so that they point to the end of EVL lanes not VF.
3106 auto AdjustEndPtr = [&CurRecipe, &EVL](VPValue *EndPtr) {
3107 auto *EVLEndPtr = cast<VPVectorEndPointerRecipe>(EndPtr)->clone();
3108 EVLEndPtr->insertBefore(&CurRecipe);
3109 // Cast EVL (i32) to match the VF operand's type.
3110 VPValue *EVLAsVF = VPBuilder(EVLEndPtr).createScalarZExtOrTrunc(
3111 &EVL, EVLEndPtr->getOperand(1)->getScalarType(), EVL.getScalarType(),
3113 EVLEndPtr->setOperand(1, EVLAsVF);
3114 return EVLEndPtr;
3115 };
3116
3117 auto GetVPReverse = [&CurRecipe, &EVL, Plan,
3119 if (!V)
3120 return nullptr;
3121 auto *Reverse = new VPWidenIntrinsicRecipe(
3122 Intrinsic::experimental_vp_reverse, {V, Plan->getTrue(), &EVL},
3123 V->getScalarType(), {}, {}, DL);
3124 Reverse->insertBefore(&CurRecipe);
3125 return Reverse;
3126 };
3127
3128 if (match(&CurRecipe,
3129 m_MaskedLoad(m_VPValue(Addr), m_RemoveMask(HeaderMask, Mask))))
3130 return new VPWidenLoadEVLRecipe(cast<VPWidenLoadRecipe>(CurRecipe), Addr,
3131 EVL, Mask);
3132
3133 if (match(&CurRecipe,
3134 m_MaskedLoad(m_VPValue(EndPtr),
3135 m_Reverse(m_RemoveMask(HeaderMask, Mask)))) &&
3136 match(EndPtr, m_VecEndPtr(m_VPValue(), m_Specific(&Plan->getVF())))) {
3137 Mask = GetVPReverse(Mask);
3138 Addr = AdjustEndPtr(EndPtr);
3139 auto *LoadR = new VPWidenLoadEVLRecipe(cast<VPWidenLoadRecipe>(CurRecipe),
3140 Addr, EVL, Mask);
3141 LoadR->insertBefore(&CurRecipe);
3142 VPValue *Poison = Plan->getPoison(LoadR->getScalarType());
3143 return new VPWidenIntrinsicRecipe(Intrinsic::vector_splice_left,
3144 {Poison, LoadR, &EVL},
3145 LoadR->getScalarType(), {}, {}, DL);
3146 }
3147
3148 VPValue *Stride;
3150 m_VPValue(Addr), m_VPValue(Stride),
3151 m_RemoveMask(HeaderMask, Mask),
3152 m_TruncOrSelf(m_Specific(&Plan->getVF()))))) {
3153 if (!Mask)
3154 Mask = Plan->getTrue();
3155 auto *NewLoad = cast<VPWidenMemIntrinsicRecipe>(&CurRecipe)->clone();
3156 NewLoad->setOperand(2, Mask);
3157 NewLoad->setOperand(3, &EVL);
3158 return NewLoad;
3159 }
3160
3161 VPValue *StoredVal;
3162 if (match(&CurRecipe, m_MaskedStore(m_VPValue(Addr), m_VPValue(StoredVal),
3163 m_RemoveMask(HeaderMask, Mask))))
3164 return new VPWidenStoreEVLRecipe(cast<VPWidenStoreRecipe>(CurRecipe), Addr,
3165 StoredVal, EVL, Mask);
3166
3167 if (match(&CurRecipe,
3168 m_MaskedStore(m_VPValue(EndPtr), m_VPValue(StoredVal),
3169 m_Reverse(m_RemoveMask(HeaderMask, Mask)))) &&
3170 match(EndPtr, m_VecEndPtr(m_VPValue(), m_Specific(&Plan->getVF())))) {
3171 Mask = GetVPReverse(Mask);
3172 Addr = AdjustEndPtr(EndPtr);
3173 VPValue *Poison = Plan->getPoison(StoredVal->getScalarType());
3174 auto *SpliceR = new VPWidenIntrinsicRecipe(
3175 Intrinsic::vector_splice_right, {StoredVal, Poison, &EVL},
3176 StoredVal->getScalarType(), {}, {}, DL);
3177 SpliceR->insertBefore(&CurRecipe);
3178 return new VPWidenStoreEVLRecipe(cast<VPWidenStoreRecipe>(CurRecipe), Addr,
3179 SpliceR, EVL, Mask);
3180 }
3181
3182 if (auto *Rdx = dyn_cast<VPReductionRecipe>(&CurRecipe))
3183 if (Rdx->isConditional() &&
3184 match(Rdx->getCondOp(), m_RemoveMask(HeaderMask, Mask)))
3185 return new VPReductionEVLRecipe(*Rdx, EVL, Mask);
3186
3187 if (auto *Interleave = dyn_cast<VPInterleaveRecipe>(&CurRecipe))
3188 if (Interleave->getMask() &&
3189 match(Interleave->getMask(), m_RemoveMask(HeaderMask, Mask)))
3190 return new VPInterleaveEVLRecipe(*Interleave, EVL, Mask);
3191
3192 VPValue *LHS, *RHS;
3193 if (match(&CurRecipe, m_SelectLike(m_RemoveMask(HeaderMask, Mask),
3195 return new VPWidenIntrinsicRecipe(
3196 Intrinsic::vp_merge, {Mask ? Mask : Plan->getTrue(), LHS, RHS, &EVL},
3197 LHS->getScalarType(), {}, {}, DL);
3198
3199 if (match(&CurRecipe, m_LastActiveLane(m_Specific(HeaderMask)))) {
3200 Type *Ty = CurRecipe.getVPSingleValue()->getScalarType();
3201 VPValue *ZExt =
3202 VPBuilder(&CurRecipe)
3203 .createScalarZExtOrTrunc(&EVL, Ty, EVL.getScalarType(), DL);
3204 return new VPInstruction(
3205 Instruction::Sub, {ZExt, Plan->getConstantInt(Ty, 1)},
3206 VPIRFlags::getDefaultFlags(Instruction::Sub), {}, DL);
3207 }
3208
3209 // lhs | (headermask && rhs) -> vp.merge rhs, true, lhs, evl
3210 if (match(&CurRecipe,
3212 m_LogicalAnd(m_Specific(HeaderMask), m_VPValue(RHS)))))
3213 return new VPWidenIntrinsicRecipe(Intrinsic::vp_merge,
3214 {RHS, Plan->getTrue(), LHS, &EVL},
3215 LHS->getScalarType(), {}, {}, DL);
3216
3217 if (auto *IntrR = dyn_cast<VPWidenIntrinsicRecipe>(&CurRecipe))
3218 if (auto VPID = getVPDivRemIntrinsic(IntrR->getVectorIntrinsicID()))
3219 if (match(IntrR->getOperand(2), m_RemoveMask(HeaderMask, Mask)))
3220 return new VPWidenIntrinsicRecipe(*VPID,
3221 {IntrR->getOperand(0),
3222 IntrR->getOperand(1),
3223 Mask ? Mask : Plan->getTrue(), &EVL},
3224 IntrR->getScalarType(), {}, {}, DL);
3225
3226 return nullptr;
3227}
3228
3229/// Optimize away any EVL-based header masks to VP intrinsic based recipes.
3230/// The transforms here need to preserve the original semantics.
3232 // Find the EVL-based header mask if it exists: icmp ult step-vector, EVL
3233 VPValue *HeaderMask = nullptr, *EVL = nullptr;
3236 m_VPValue(EVL))) &&
3237 match(EVL, m_EVL(m_VPValue()))) {
3238 HeaderMask = R.getVPSingleValue();
3239 break;
3240 }
3241 }
3242 if (!HeaderMask)
3243 return;
3244
3245 SmallVector<VPRecipeBase *> OldRecipes;
3246 for (VPUser *U : collectUsersRecursively(HeaderMask)) {
3248 if (auto *NewR = optimizeMaskToEVL(HeaderMask, *R, *EVL)) {
3249 NewR->insertBefore(R);
3250 for (auto [Old, New] :
3251 zip_equal(R->definedValues(), NewR->definedValues()))
3252 Old->replaceAllUsesWith(New);
3253 OldRecipes.push_back(R);
3254 }
3255 }
3256
3257 // Replace remaining (HeaderMask && Mask) with vp.merge (True, Mask,
3258 // False, EVL)
3259 for (VPUser *U : collectUsersRecursively(HeaderMask)) {
3260 VPValue *Mask;
3261 if (match(U, m_LogicalAnd(m_Specific(HeaderMask), m_VPValue(Mask)))) {
3262 auto *LogicalAnd = cast<VPInstruction>(U);
3263 auto *Merge = new VPWidenIntrinsicRecipe(
3264 Intrinsic::vp_merge, {Plan.getTrue(), Mask, Plan.getFalse(), EVL},
3265 Mask->getScalarType(), {}, {}, LogicalAnd->getDebugLoc());
3266 Merge->insertBefore(LogicalAnd);
3267 LogicalAnd->replaceAllUsesWith(Merge);
3268 OldRecipes.push_back(LogicalAnd);
3269 }
3270 }
3271
3272 // Pull out left splices from any elementwise op.
3273 // binop(splice.left(poison, x, evl), live-in)
3274 // -> splice.left(poison, binop(x,live-in), evl)
3276 Plan,
3277 [&EVL](const auto &X) {
3279 m_Specific(EVL));
3280 },
3281 [&Plan, &EVL](auto *X) {
3282 return new VPWidenIntrinsicRecipe(
3283 Intrinsic::vector_splice_left,
3284 {Plan.getPoison(X->getScalarType()), X, EVL}, X->getScalarType(),
3285 {}, {}, X->getDebugLoc());
3286 });
3287
3288 // Fold the following splice patterns:
3289 // splice.right(splice.left(poison, x, evl), poison, evl) -> x
3290 // vector.reverse(splice.left(poison, x, evl)) -> vp.reverse(x, true, evl)
3291 // splice.right(vector.reverse(x), poison, evl) -> vp.reverse(x, true, evl)
3292 for (VPUser *U : collectUsersRecursively(EVL)) {
3293 auto *R = cast<VPRecipeBase>(U);
3294 // Remove potentially dead left splices from the transform above.
3296 R->getVPSingleValue()->getNumUsers() == 0) {
3297 OldRecipes.push_back(R);
3298 continue;
3299 }
3300
3301 VPValue *X;
3304 m_Poison(), m_VPValue(X), m_Specific(EVL)),
3305 m_Poison(), m_Specific(EVL)))) {
3306 R->getVPSingleValue()->replaceAllUsesWith(X);
3307 OldRecipes.push_back(R);
3308 continue;
3309 }
3310
3311 if (!match(U,
3314 m_Poison(), m_VPValue(X), m_Specific(EVL))),
3316 m_Reverse(m_VPValue(X)), m_Poison(), m_Specific(EVL)))))
3317 continue;
3318
3319 auto *VPReverse = new VPWidenIntrinsicRecipe(
3320 Intrinsic::experimental_vp_reverse, {X, Plan.getTrue(), EVL},
3321 X->getScalarType(), {}, {}, R->getDebugLoc());
3322 VPReverse->insertBefore(R);
3323 R->getVPSingleValue()->replaceAllUsesWith(VPReverse);
3324 OldRecipes.push_back(R);
3325 }
3326
3327 for (VPRecipeBase *R : reverse(OldRecipes)) {
3328 SmallVector<VPValue *> PossiblyDead(R->operands());
3329 R->eraseFromParent();
3330 for (VPValue *Op : PossiblyDead)
3332 }
3333}
3334
3335/// After replacing the canonical IV with a EVL-based IV, fixup recipes that use
3336/// VF to use the EVL instead to avoid incorrect updates on the penultimate
3337/// iteration.
3338static void fixupVFUsersForEVL(VPlan &Plan, VPValue &EVL) {
3339 VPRegionBlock *LoopRegion = Plan.getVectorLoopRegion();
3340 VPBasicBlock *Header = LoopRegion->getEntryBasicBlock();
3341
3342 // EVL is i32 but VF/VFxUF are IdxTy. Convert as needed.
3343 VPValue *EVLAsIdx =
3347
3348 assert(all_of(Plan.getVF().users(),
3349 [&Plan](VPUser *U) {
3350 auto IsAllowedUser =
3351 IsaPred<VPVectorEndPointerRecipe, VPScalarIVStepsRecipe,
3352 VPWidenIntOrFpInductionRecipe,
3353 VPWidenMemIntrinsicRecipe>;
3354 if (match(U, m_Trunc(m_Specific(&Plan.getVF()))))
3355 return all_of(cast<VPSingleDefRecipe>(U)->users(),
3356 IsAllowedUser);
3357 return IsAllowedUser(U);
3358 }) &&
3359 "User of VF that we can't transform to EVL.");
3360 Plan.getVF().replaceUsesWithIf(EVLAsIdx, [](VPUser &U, unsigned Idx) {
3362 });
3363
3364 assert(all_of(Plan.getVFxUF().users(),
3366 m_c_Add(m_Specific(LoopRegion->getCanonicalIV()),
3367 m_Specific(&Plan.getVFxUF())),
3369 "Only users of VFxUF should be VPWidenPointerInductionRecipe and the "
3370 "increment of the canonical induction.");
3371 Plan.getVFxUF().replaceUsesWithIf(EVLAsIdx, [](VPUser &U, unsigned Idx) {
3372 // Only replace uses in VPWidenPointerInductionRecipe; The increment of the
3373 // canonical induction must not be updated.
3375 });
3376
3377 // Create a scalar phi to track the previous EVL if fixed-order recurrence is
3378 // contained.
3379 bool ContainsFORs =
3381 if (ContainsFORs) {
3382 // TODO: Use VPInstruction::ExplicitVectorLength to get maximum EVL.
3383 VPValue *MaxEVL = &Plan.getVF();
3384 // Emit VPScalarCastRecipe in preheader if VF is not a 32 bits integer.
3385 VPBuilder Builder(LoopRegion->getPreheaderVPBB());
3386 MaxEVL = Builder.createScalarZExtOrTrunc(
3387 MaxEVL, Type::getInt32Ty(Plan.getContext()), MaxEVL->getScalarType(),
3389
3390 Builder.setInsertPoint(Header, Header->getFirstNonPhi());
3391 VPValue *PrevEVL = Builder.createScalarPhi(
3392 {MaxEVL, &EVL}, DebugLoc::getUnknown(), "prev.evl");
3393
3396 for (VPRecipeBase &R : *VPBB) {
3397 VPValue *V1, *V2;
3398 if (!match(&R,
3400 m_VPValue(V1), m_VPValue(V2))))
3401 continue;
3402 VPValue *Imm = Plan.getOrAddLiveIn(
3405 Intrinsic::experimental_vp_splice,
3406 {V1, V2, Imm, Plan.getTrue(), PrevEVL, &EVL},
3407 R.getVPSingleValue()->getScalarType(), {}, {}, R.getDebugLoc());
3408 VPSplice->insertBefore(&R);
3409 R.getVPSingleValue()->replaceAllUsesWith(VPSplice);
3410 }
3411 }
3412 }
3413
3414 VPValue *HeaderMask = LoopRegion->getHeaderMask();
3415 if (!HeaderMask)
3416 return;
3417
3418 // Ensure that any reduction that uses a select to mask off tail lanes does so
3419 // in the vector loop, not the middle block, since EVL tail folding can have
3420 // tail elements in the penultimate iteration.
3421 assert(all_of(*Plan.getMiddleBlock(), [&Plan, HeaderMask](VPRecipeBase &R) {
3422 if (match(&R, m_ComputeReductionResult(m_Select(m_Specific(HeaderMask),
3423 m_VPValue(), m_VPValue()))))
3424 return R.getOperand(0)->getDefiningRecipe()->getRegion() ==
3425 Plan.getVectorLoopRegion();
3426 return true;
3427 }));
3428
3429 // Replace the abstract header mask with a mask equivalent to predicating by
3430 // EVL: icmp ult step-vector, EVL
3431 VPRecipeBase *EVLR = EVL.getDefiningRecipe();
3432 VPBuilder Builder(EVLR->getParent(), std::next(EVLR->getIterator()));
3433 Type *EVLType = EVL.getScalarType();
3434 VPValue *EVLMask = Builder.createICmp(
3436 Builder.createNaryOp(VPInstruction::StepVector, {}, EVLType), &EVL);
3437 HeaderMask->replaceAllUsesWith(EVLMask);
3438}
3439
3440/// Converts a tail folded vector loop region to step by
3441/// VPInstruction::ExplicitVectorLength elements instead of VF elements each
3442/// iteration.
3443///
3444/// - Add a VPCurrentIterationPHIRecipe and related recipes to \p Plan and
3445/// replaces all uses of the canonical IV except for the canonical IV
3446/// increment with a VPCurrentIterationPHIRecipe. The canonical IV is used
3447/// only for loop iterations counting after this transformation.
3448///
3449/// - The header mask is replaced with a header mask based on the EVL.
3450///
3451/// - Plans with FORs have a new phi added to keep track of the EVL of the
3452/// previous iteration, and VPFirstOrderRecurrencePHIRecipes are replaced with
3453/// @llvm.vp.splice.
3454///
3455/// The function uses the following definitions:
3456/// %StartV is the canonical induction start value.
3457///
3458/// The function adds the following recipes:
3459///
3460/// vector.ph:
3461/// ...
3462///
3463/// vector.body:
3464/// ...
3465/// %CurrentIter = CURRENT-ITERATION-PHI [ %StartV, %vector.ph ],
3466/// [ %NextIter, %vector.body ]
3467/// %AVL = phi [ trip-count, %vector.ph ], [ %NextAVL, %vector.body ]
3468/// %VPEVL = EXPLICIT-VECTOR-LENGTH %AVL
3469/// ...
3470/// %OpEVL = cast i32 %VPEVL to IVSize
3471/// %NextIter = add IVSize %OpEVL, %CurrentIter
3472/// %NextAVL = sub IVSize nuw %AVL, %OpEVL
3473/// ...
3474///
3475/// If MaxSafeElements is provided, the function adds the following recipes:
3476/// vector.ph:
3477/// ...
3478///
3479/// vector.body:
3480/// ...
3481/// %CurrentIter = CURRENT-ITERATION-PHI [ %StartV, %vector.ph ],
3482/// [ %NextIter, %vector.body ]
3483/// %AVL = phi [ trip-count, %vector.ph ], [ %NextAVL, %vector.body ]
3484/// %cmp = cmp ult %AVL, MaxSafeElements
3485/// %SAFE_AVL = select %cmp, %AVL, MaxSafeElements
3486/// %VPEVL = EXPLICIT-VECTOR-LENGTH %SAFE_AVL
3487/// ...
3488/// %OpEVL = cast i32 %VPEVL to IVSize
3489/// %NextIter = add IVSize %OpEVL, %CurrentIter
3490/// %NextAVL = sub IVSize nuw %AVL, %OpEVL
3491/// ...
3492///
3494 VPlan &Plan, const std::optional<unsigned> &MaxSafeElements) {
3495 if (Plan.hasScalarVFOnly())
3496 return;
3497 VPRegionBlock *LoopRegion = Plan.getVectorLoopRegion();
3498 VPBasicBlock *Header = LoopRegion->getEntryBasicBlock();
3499
3500 auto *CanonicalIV = LoopRegion->getCanonicalIV();
3501 auto *CanIVTy = LoopRegion->getCanonicalIVType();
3502 VPValue *StartV = Plan.getZero(CanIVTy);
3503 auto *CanonicalIVIncrement = LoopRegion->getOrCreateCanonicalIVIncrement();
3504
3505 // Create the CurrentIteration recipe in the vector loop.
3506 auto *CurrentIteration =
3508 CurrentIteration->insertBefore(*Header, Header->begin());
3509 VPBuilder Builder(Header, Header->getFirstNonPhi());
3510 // Create the AVL (application vector length), starting from TC -> 0 in steps
3511 // of EVL.
3512 VPPhi *AVLPhi = Builder.createScalarPhi(
3513 {Plan.getTripCount()}, DebugLoc::getCompilerGenerated(), "avl");
3514 VPValue *AVL = AVLPhi;
3515
3516 if (MaxSafeElements) {
3517 // Support for MaxSafeDist for correct loop emission.
3518 VPValue *AVLSafe = Plan.getConstantInt(CanIVTy, *MaxSafeElements);
3519 VPValue *Cmp = Builder.createICmp(ICmpInst::ICMP_ULT, AVL, AVLSafe);
3520 AVL = Builder.createSelect(Cmp, AVL, AVLSafe, DebugLoc::getUnknown(),
3521 "safe_avl");
3522 }
3523 auto *VPEVL = Builder.createNaryOp(VPInstruction::ExplicitVectorLength, AVL,
3524 DebugLoc::getUnknown(), "evl");
3525
3526 Builder.setInsertPoint(CanonicalIVIncrement);
3527 VPValue *OpVPEVL = VPEVL;
3528
3529 auto *I32Ty = Type::getInt32Ty(Plan.getContext());
3530 OpVPEVL = Builder.createScalarZExtOrTrunc(
3531 OpVPEVL, CanIVTy, I32Ty, CanonicalIVIncrement->getDebugLoc());
3532
3533 auto *NextIter = Builder.createAdd(
3534 OpVPEVL, CurrentIteration, CanonicalIVIncrement->getDebugLoc(),
3535 "current.iteration.next", CanonicalIVIncrement->getNoWrapFlags());
3536 CurrentIteration->addBackedgeValue(NextIter);
3537
3538 VPValue *NextAVL =
3539 Builder.createSub(AVLPhi, OpVPEVL, DebugLoc::getCompilerGenerated(),
3540 "avl.next", {/*NUW=*/true, /*NSW=*/false});
3541 AVLPhi->addIncoming(NextAVL);
3542
3543 fixupVFUsersForEVL(Plan, *VPEVL);
3544 removeDeadRecipes(Plan);
3545
3546 // Replace all uses of the canonical IV with VPCurrentIterationPHIRecipe
3547 // except for the canonical IV increment.
3548 CanonicalIV->replaceUsesWithIf(CurrentIteration,
3549 [CanonicalIVIncrement](VPUser &U, unsigned) {
3550 return &U != CanonicalIVIncrement;
3551 });
3552 // TODO: support unroll factor > 1.
3553 Plan.setUF(1);
3554}
3555
3557 // Find the vector loop entry by locating VPCurrentIterationPHIRecipe.
3558 // There should be only one VPCurrentIteration in the entire plan.
3559 VPCurrentIterationPHIRecipe *CurrentIteration = nullptr;
3560
3563 for (VPRecipeBase &R : VPBB->phis())
3564 if (auto *PhiR = dyn_cast<VPCurrentIterationPHIRecipe>(&R)) {
3565 assert(!CurrentIteration &&
3566 "Found multiple CurrentIteration. Only one expected");
3567 CurrentIteration = PhiR;
3568 }
3569
3570 // Early return if it is not variable-length stepping.
3571 if (!CurrentIteration)
3572 return;
3573
3574 VPBasicBlock *HeaderVPBB = CurrentIteration->getParent();
3575 VPValue *CurrentIterationIncr = CurrentIteration->getBackedgeValue();
3576
3577 // Convert CurrentIteration to concrete recipe.
3578 auto *ScalarR =
3579 VPBuilder(CurrentIteration)
3581 {CurrentIteration->getStartValue(), CurrentIterationIncr},
3582 CurrentIteration->getDebugLoc(), "current.iteration.iv");
3583 CurrentIteration->replaceAllUsesWith(ScalarR);
3584 CurrentIteration->eraseFromParent();
3585
3586 // Replace CanonicalIVInc with CurrentIteration increment if it exists.
3587 auto *CanonicalIV = cast<VPPhi>(&*HeaderVPBB->begin());
3588 if (auto *CanIVInc = findUserOf(
3589 CanonicalIV, m_c_Add(m_VPValue(), m_Specific(&Plan.getVFxUF())))) {
3590 cast<VPInstruction>(CanIVInc)->replaceAllUsesWith(CurrentIterationIncr);
3591 CanIVInc->eraseFromParent();
3592 }
3593}
3594
3596 VPRegionBlock *LoopRegion = Plan.getVectorLoopRegion();
3597 if (!LoopRegion)
3598 return;
3599 VPBasicBlock *Header = LoopRegion->getEntryBasicBlock();
3600 if (Header->empty())
3601 return;
3602 // The EVL IV is always at the beginning.
3603 auto *EVLPhi = dyn_cast<VPCurrentIterationPHIRecipe>(&Header->front());
3604 if (!EVLPhi)
3605 return;
3606
3607 // Bail if not an EVL tail folded loop.
3608 VPValue *AVL;
3609 if (!match(EVLPhi->getBackedgeValue(),
3610 m_c_Add(m_ZExtOrSelf(m_EVL(m_VPValue(AVL))), m_Specific(EVLPhi))))
3611 return;
3612
3613 // The AVL may be capped to a safe distance.
3614 VPValue *SafeAVL, *UnsafeAVL;
3615 if (match(AVL,
3617 m_VPValue(SafeAVL)),
3618 m_Deferred(UnsafeAVL), m_Deferred(SafeAVL))))
3619 AVL = UnsafeAVL;
3620
3621 VPValue *AVLNext;
3622 [[maybe_unused]] bool FoundAVLNext =
3624 m_Specific(Plan.getTripCount()), m_VPValue(AVLNext)));
3625 assert(FoundAVLNext && "Didn't find AVL backedge?");
3626
3627 VPBasicBlock *Latch = LoopRegion->getExitingBasicBlock();
3628 auto *LatchBr = cast<VPInstruction>(Latch->getTerminator());
3629 if (match(LatchBr, m_BranchOnCond(m_True())))
3630 return;
3631
3632 VPValue *CanIVInc;
3633 [[maybe_unused]] bool FoundIncrement = match(
3634 LatchBr,
3636 m_Specific(&Plan.getVectorTripCount()))));
3637 assert(FoundIncrement &&
3638 match(CanIVInc, m_Add(m_Specific(LoopRegion->getCanonicalIV()),
3639 m_Specific(&Plan.getVFxUF()))) &&
3640 "Expected BranchOnCond with ICmp comparing CanIV + VFxUF with vector "
3641 "trip count");
3642
3643 Type *AVLTy = AVLNext->getScalarType();
3644 VPBuilder Builder(LatchBr);
3645 LatchBr->setOperand(
3646 0, Builder.createICmp(CmpInst::ICMP_EQ, AVLNext, Plan.getZero(AVLTy)));
3647}
3648
3650 VPlan &Plan, PredicatedScalarEvolution &PSE,
3651 const DenseMap<Value *, const SCEV *> &StridesMap,
3652 const VPDominatorTree &VPDT) {
3653 // Replace VPValues for known constant strides guaranteed by predicated scalar
3654 // evolution that are guaranteed to be guarded by the runtime checks; that is,
3655 // blocks dominated by the vector preheader.
3656 assert(!Plan.getVectorLoopRegion() &&
3657 "expected to run before loop regions are created");
3658 VPBlockBase *Preheader = Plan.getEntry()->getSuccessors()[1];
3659 auto CanUseVersionedStride = [&VPDT, Preheader](VPUser &U, unsigned) {
3660 auto *R = cast<VPRecipeBase>(&U);
3661 VPBlockBase *Parent = R->getParent();
3662 return VPDT.dominates(Preheader, Parent);
3663 };
3664 ValueToSCEVMapTy RewriteMap;
3665 for (const SCEV *Stride : StridesMap.values()) {
3666 using namespace SCEVPatternMatch;
3667 auto *StrideV = cast<SCEVUnknown>(Stride)->getValue();
3668 const APInt *StrideConst;
3669 if (!match(PSE.getSCEV(StrideV), m_scev_APInt(StrideConst)))
3670 // Only handle constant strides for now.
3671 continue;
3672
3673 auto *CI = Plan.getConstantInt(*StrideConst);
3674 if (VPValue *StrideVPV = Plan.getLiveIn(StrideV))
3675 StrideVPV->replaceUsesWithIf(CI, CanUseVersionedStride);
3676
3677 // The versioned value may not be used in the loop directly but through a
3678 // sext/zext. Add new live-ins in those cases.
3679 for (Value *U : StrideV->users()) {
3681 continue;
3682 VPValue *StrideVPV = Plan.getLiveIn(U);
3683 if (!StrideVPV)
3684 continue;
3685 unsigned BW = U->getType()->getScalarSizeInBits();
3686 APInt C =
3687 isa<SExtInst>(U) ? StrideConst->sext(BW) : StrideConst->zext(BW);
3688 VPValue *CI = Plan.getConstantInt(C);
3689 StrideVPV->replaceUsesWithIf(CI, CanUseVersionedStride);
3690 }
3691 RewriteMap[StrideV] = PSE.getSCEV(StrideV);
3692 }
3693
3694 for (VPRecipeBase &R : *Plan.getEntry()) {
3695 auto *ExpSCEV = dyn_cast<VPExpandSCEVRecipe>(&R);
3696 if (!ExpSCEV)
3697 continue;
3698 const SCEV *ScevExpr = ExpSCEV->getSCEV();
3699 auto *NewSCEV =
3700 SCEVParameterRewriter::rewrite(ScevExpr, *PSE.getSE(), RewriteMap);
3701 if (NewSCEV != ScevExpr) {
3702 VPValue *NewExp = vputils::getOrCreateVPValueForSCEVExpr(Plan, NewSCEV);
3703 ExpSCEV->replaceAllUsesWith(NewExp);
3704 if (Plan.getTripCount() == ExpSCEV)
3705 Plan.resetTripCount(NewExp);
3706 }
3707 }
3708}
3709
3711 // Collect recipes in the backward slice of `Root` that may generate a poison
3712 // value that is used after vectorization.
3714 auto CollectPoisonGeneratingInstrsInBackwardSlice([&](VPRecipeBase *Root) {
3716 Worklist.push_back(Root);
3717
3718 // Traverse the backward slice of Root through its use-def chain.
3719 while (!Worklist.empty()) {
3720 VPRecipeBase *CurRec = Worklist.pop_back_val();
3721
3722 if (!Visited.insert(CurRec).second)
3723 continue;
3724
3725 // Prune search if we find another recipe generating a widen memory
3726 // instruction. Widen memory instructions involved in address computation
3727 // will lead to gather/scatter instructions, which don't need to be
3728 // handled.
3730 VPHeaderPHIRecipe>(CurRec))
3731 continue;
3732
3733 // This recipe contributes to the address computation of a widen
3734 // load/store. If the underlying instruction has poison-generating flags,
3735 // drop them directly.
3736 if (auto *RecWithFlags = dyn_cast<VPRecipeWithIRFlags>(CurRec)) {
3737 VPValue *A, *B;
3738 // Dropping disjoint from an OR may yield incorrect results, as some
3739 // analysis may have converted it to an Add implicitly (e.g. SCEV used
3740 // for dependence analysis). Instead, replace it with an equivalent Add.
3741 // This is possible as all users of the disjoint OR only access lanes
3742 // where the operands are disjoint or poison otherwise.
3743 if (match(RecWithFlags, m_BinaryOr(m_VPValue(A), m_VPValue(B))) &&
3744 RecWithFlags->isDisjoint()) {
3745 VPBuilder Builder(RecWithFlags);
3746 VPInstruction *New =
3747 Builder.createAdd(A, B, RecWithFlags->getDebugLoc());
3748 New->setUnderlyingValue(RecWithFlags->getUnderlyingValue());
3749 RecWithFlags->replaceAllUsesWith(New);
3750 RecWithFlags->eraseFromParent();
3751 CurRec = New;
3752 } else
3753 RecWithFlags->dropPoisonGeneratingFlags();
3754 } else {
3757 (void)Instr;
3758 assert((!Instr || !Instr->hasPoisonGeneratingFlags()) &&
3759 "found instruction with poison generating flags not covered by "
3760 "VPRecipeWithIRFlags");
3761 }
3762
3763 // Add new definitions to the worklist.
3764 for (VPValue *Operand : CurRec->operands())
3765 if (VPRecipeBase *OpDef = Operand->getDefiningRecipe())
3766 Worklist.push_back(OpDef);
3767 }
3768 });
3769
3770 // We want to exclude the tail folding case, as we don't need to drop flags
3771 // for operations computing the first lane in this case: the first lane of the
3772 // header mask must always be true. For reverse memory accesses, the mask is
3773 // wrapped in a Reverse, which is just a permutation of the header mask, so
3774 // peel it off before checking. The header mask is still the abstract region
3775 // value at this point (materialization happens later).
3776 auto IsNotHeaderMask = [](VPValue *Mask) {
3777 return Mask &&
3779 };
3780
3781 // Traverse all the recipes in the VPlan and collect the poison-generating
3782 // recipes in the backward slice starting at the address of a VPWidenRecipe or
3783 // VPInterleaveRecipe.
3784 auto Iter =
3787 for (VPRecipeBase &Recipe : *VPBB) {
3788 if (auto *WidenRec = dyn_cast<VPWidenMemoryRecipe>(&Recipe)) {
3789 VPRecipeBase *AddrDef = WidenRec->getAddr()->getDefiningRecipe();
3790 if (AddrDef && WidenRec->isConsecutive() &&
3791 IsNotHeaderMask(WidenRec->getMask()))
3792 CollectPoisonGeneratingInstrsInBackwardSlice(AddrDef);
3793 } else if (auto *InterleaveRec = dyn_cast<VPInterleaveRecipe>(&Recipe)) {
3794 VPRecipeBase *AddrDef = InterleaveRec->getAddr()->getDefiningRecipe();
3795 if (AddrDef && IsNotHeaderMask(InterleaveRec->getMask()))
3796 CollectPoisonGeneratingInstrsInBackwardSlice(AddrDef);
3797 }
3798 }
3799 }
3800}
3801
3803 VPlan &Plan,
3805 &InterleaveGroups,
3806 const bool &EpilogueAllowed) {
3807 if (InterleaveGroups.empty())
3808 return;
3809
3811 for (VPBasicBlock *VPBB :
3814 for (VPRecipeBase &R : make_filter_range(*VPBB, [](VPRecipeBase &R) {
3815 return isa<VPWidenMemoryRecipe>(&R);
3816 })) {
3817 auto *MemR = cast<VPWidenMemoryRecipe>(&R);
3818 IRMemberToRecipe[&MemR->getIngredient()] = MemR;
3819 }
3820
3821 // Interleave memory: for each Interleave Group we marked earlier as relevant
3822 // for this VPlan, replace the Recipes widening its memory instructions with a
3823 // single VPInterleaveRecipe at its insertion point.
3824 VPDominatorTree VPDT(Plan);
3825 for (const auto *IG : InterleaveGroups) {
3826 VPWidenMemoryRecipe *Start = nullptr;
3827 Instruction *StartMember = nullptr;
3828 for (auto *Member : IG->members())
3829 if (VPWidenMemoryRecipe *R = IRMemberToRecipe.lookup(Member)) {
3830 StartMember = Member;
3831 Start = R;
3832 break;
3833 }
3834 if (!StartMember) // All member recipes are dead, so the group is dead.
3835 continue;
3836 VPIRMetadata InterleaveMD(*Start);
3837 SmallVector<VPValue *, 4> StoredValues;
3838 for (unsigned I = 0; I < IG->getFactor(); ++I) {
3839 Instruction *MemberI = IG->getMember(I);
3840 if (!MemberI)
3841 continue;
3842 if (VPWidenMemoryRecipe *MemoryR = IRMemberToRecipe.lookup(MemberI)) {
3843 if (auto *StoreR = dyn_cast<VPWidenStoreRecipe>(MemoryR->getAsRecipe()))
3844 StoredValues.push_back(StoreR->getStoredValue());
3845 InterleaveMD.intersect(*MemoryR);
3846 } else {
3847 InterleaveMD.intersect(VPIRMetadata(*MemberI));
3848 }
3849 }
3850
3851 bool NeedsMaskForGaps =
3852 (IG->requiresScalarEpilogue() && !EpilogueAllowed) ||
3853 (!StoredValues.empty() && !IG->isFull());
3854
3855 Instruction *IRInsertPos = IG->getInsertPos();
3856 auto *InsertPos = IRMemberToRecipe.lookup(IRInsertPos);
3857 if (!InsertPos) {
3858 // InsertPos member is dead: find a new member that is alive.
3859 assert(isa<VPWidenLoadRecipe>(Start->getAsRecipe()) &&
3860 "Dead member in non-load group?");
3861 InsertPos = Start;
3862 for (Instruction *Member : IG->members())
3863 if (VPWidenMemoryRecipe *MemberR = IRMemberToRecipe.lookup(Member))
3864 if (VPDT.properlyDominates(MemberR->getAsRecipe(),
3865 InsertPos->getAsRecipe()))
3866 InsertPos = MemberR;
3867 IRInsertPos = &InsertPos->getIngredient();
3868 }
3869 VPRecipeBase *InsertPosR = InsertPos->getAsRecipe();
3870
3872 if (auto *Gep = dyn_cast<GetElementPtrInst>(
3873 getLoadStorePointerOperand(IRInsertPos)->stripPointerCasts()))
3874 NW = Gep->getNoWrapFlags().withoutNoUnsignedWrap();
3875
3876 // Get or create the start address for the interleave group.
3877 VPValue *Addr = Start->getAddr();
3878 VPRecipeBase *AddrDef = Addr->getDefiningRecipe();
3879 if (IG->getIndex(StartMember) != 0 ||
3880 (AddrDef && !VPDT.properlyDominates(AddrDef, InsertPosR))) {
3881 // Either member zero's recipe is dead, or we cannot re-use the address of
3882 // member zero because it does not dominate the insert position. Instead,
3883 // use the address of the insert position and create a PtrAdd adjusting it
3884 // to the address of member zero.
3885 // TODO: Hoist Addr's defining recipe (and any operands as needed) to
3886 // InsertPos or sink loads above zero members to join it.
3887 assert(IG->getIndex(IRInsertPos) != 0 &&
3888 "index of insert position shouldn't be zero");
3889 auto &DL = IRInsertPos->getDataLayout();
3890 APInt Offset(32,
3891 DL.getTypeAllocSize(getLoadStoreType(IRInsertPos)) *
3892 IG->getIndex(IRInsertPos),
3893 /*IsSigned=*/true);
3894 VPValue *OffsetVPV = Plan.getConstantInt(-Offset);
3895 VPBuilder B(InsertPosR);
3896 Addr = B.createNoWrapPtrAdd(InsertPos->getAddr(), OffsetVPV, NW);
3897 }
3898 // If the group is reverse, adjust the index to refer to the last vector
3899 // lane instead of the first. We adjust the index from the first vector
3900 // lane, rather than directly getting the pointer for lane VF - 1, because
3901 // the pointer operand of the interleaved access is supposed to be uniform.
3902 if (IG->isReverse()) {
3903 auto *ReversePtr = new VPVectorEndPointerRecipe(
3904 Addr, &Plan.getVF(), getLoadStoreType(IRInsertPos),
3905 -(int64_t)IG->getFactor(), NW, InsertPosR->getDebugLoc());
3906 ReversePtr->insertBefore(InsertPosR);
3907 Addr = ReversePtr;
3908 }
3909 auto *VPIG = new VPInterleaveRecipe(
3910 IG, Addr, StoredValues, InsertPos->getMask(), NeedsMaskForGaps,
3911 InterleaveMD, InsertPosR->getDebugLoc());
3912 VPIG->insertBefore(InsertPosR);
3913
3914 unsigned J = 0;
3915 for (unsigned i = 0; i < IG->getFactor(); ++i)
3916 if (Instruction *Member = IG->getMember(i)) {
3917 VPWidenMemoryRecipe *MemberR = IRMemberToRecipe.lookup(Member);
3918 if (!Member->getType()->isVoidTy()) {
3919 if (MemberR) {
3920 VPValue *OriginalV = MemberR->getAsRecipe()->getVPSingleValue();
3921 OriginalV->replaceAllUsesWith(VPIG->getVPValue(J));
3922 }
3923 J++;
3924 }
3925 if (MemberR)
3926 MemberR->getAsRecipe()->eraseFromParent();
3927 }
3928 }
3929}
3930
3931/// Expand a VPWidenIntOrFpInduction into executable recipes, for the initial
3932/// value, phi and backedge value. In the following example:
3933///
3934/// vector.ph:
3935/// Successor(s): vector loop
3936///
3937/// <x1> vector loop: {
3938/// vector.body:
3939/// WIDEN-INDUCTION %i = phi %start, %step, %vf
3940/// ...
3941/// EMIT branch-on-count ...
3942/// No successors
3943/// }
3944///
3945/// WIDEN-INDUCTION will get expanded to:
3946///
3947/// vector.ph:
3948/// ...
3949/// vp<%induction.start> = ...
3950/// vp<%induction.increment> = ...
3951///
3952/// Successor(s): vector loop
3953///
3954/// <x1> vector loop: {
3955/// vector.body:
3956/// ir<%i> = WIDEN-PHI vp<%induction.start>, vp<%vec.ind.next>
3957/// ...
3958/// vp<%vec.ind.next> = add ir<%i>, vp<%induction.increment>
3959/// EMIT branch-on-count ...
3960/// No successors
3961/// }
3962static void
3964 VPlan *Plan = WidenIVR->getParent()->getPlan();
3965 VPValue *Start = WidenIVR->getStartValue();
3966 VPValue *Step = WidenIVR->getStepValue();
3967 VPValue *VF = WidenIVR->getVFValue();
3968 DebugLoc DL = WidenIVR->getDebugLoc();
3969
3970 // The value from the original loop to which we are mapping the new induction
3971 // variable.
3972 Type *Ty = WidenIVR->getScalarType();
3973
3974 const InductionDescriptor &ID = WidenIVR->getInductionDescriptor();
3977 VPIRFlags Flags = *WidenIVR;
3978 if (ID.getKind() == InductionDescriptor::IK_IntInduction) {
3979 AddOp = Instruction::Add;
3980 MulOp = Instruction::Mul;
3981 } else {
3982 AddOp = ID.getInductionOpcode();
3983 MulOp = Instruction::FMul;
3984 }
3985
3986 // If the phi is truncated, truncate the start and step values.
3987 VPBuilder Builder(Plan->getVectorPreheader());
3988 Type *StepTy = Step->getScalarType();
3989 if (Ty->getScalarSizeInBits() < StepTy->getScalarSizeInBits()) {
3990 assert(StepTy->isIntegerTy() && "Truncation requires an integer type");
3991 Step = Builder.createScalarCast(Instruction::Trunc, Step, Ty, DL);
3992 Start = Builder.createScalarCast(Instruction::Trunc, Start, Ty, DL);
3993 StepTy = Ty;
3994 }
3995
3996 // Construct the initial value of the vector IV in the vector loop preheader.
3997 Type *IVIntTy =
3999 VPValue *Init = Builder.createNaryOp(VPInstruction::StepVector, {}, IVIntTy);
4000 if (StepTy->isFloatingPointTy())
4001 Init = Builder.createWidenCast(Instruction::UIToFP, Init, StepTy);
4002
4003 VPValue *SplatStart = Builder.createNaryOp(VPInstruction::Broadcast, Start);
4004 VPValue *SplatStep = Builder.createNaryOp(VPInstruction::Broadcast, Step);
4005
4006 Init = Builder.createNaryOp(MulOp, {Init, SplatStep}, Flags);
4007 Init = Builder.createNaryOp(AddOp, {SplatStart, Init}, Flags,
4008 DebugLoc::getUnknown(), "induction");
4009
4010 // Create the widened phi of the vector IV.
4011 auto *WidePHI = VPBuilder(WidenIVR).createWidenPhi(
4012 Init, WidenIVR->getDebugLoc(), "vec.ind");
4013
4014 // Create the backedge value for the vector IV.
4015 VPValue *Inc;
4016 VPValue *Prev;
4017 // If unrolled, use the increment and prev value from the operands.
4018 if (auto *SplatVF = WidenIVR->getSplatVFValue()) {
4019 Inc = SplatVF;
4020 Prev = WidenIVR->getLastUnrolledPartOperand();
4021 } else {
4022 // Move the insertion point after the VF definition when the VF is defined
4023 // inside a loop, such as for EVL tail-folding.
4024 if (VPRecipeBase *R = VF->getDefiningRecipe())
4025 if (R->getParent()->getEnclosingLoopRegion())
4026 Builder.setInsertPoint(R->getParent(), std::next(R->getIterator()));
4027
4028 // Multiply the vectorization factor by the step using integer or
4029 // floating-point arithmetic as appropriate.
4030 if (StepTy->isFloatingPointTy())
4031 VF = Builder.createScalarCast(Instruction::CastOps::UIToFP, VF, StepTy,
4032 DL);
4033 else
4034 VF = Builder.createScalarZExtOrTrunc(VF, StepTy, VF->getScalarType(), DL);
4035
4036 Inc = Builder.createNaryOp(MulOp, {Step, VF}, Flags);
4037 Inc = Builder.createNaryOp(VPInstruction::Broadcast, Inc);
4038 Prev = WidePHI;
4039 }
4040
4042 Builder.setInsertPoint(ExitingBB, ExitingBB->getTerminator()->getIterator());
4043 auto *Next = Builder.createNaryOp(AddOp, {Prev, Inc}, Flags,
4044 WidenIVR->getDebugLoc(), "vec.ind.next");
4045
4046 WidePHI->addIncoming(Next);
4047
4048 WidenIVR->replaceAllUsesWith(WidePHI);
4049}
4050
4051/// Expand a VPWidenPointerInductionRecipe into executable recipes, for the
4052/// initial value, phi and backedge value. In the following example:
4053///
4054/// <x1> vector loop: {
4055/// vector.body:
4056/// EMIT ir<%ptr.iv> = WIDEN-POINTER-INDUCTION %start, %step, %vf
4057/// ...
4058/// EMIT branch-on-count ...
4059/// }
4060///
4061/// WIDEN-POINTER-INDUCTION will get expanded to:
4062///
4063/// <x1> vector loop: {
4064/// vector.body:
4065/// EMIT-SCALAR %pointer.phi = phi %start, %ptr.ind
4066/// EMIT %mul = mul %stepvector, %step
4067/// EMIT %vector.gep = wide-ptradd %pointer.phi, %mul
4068/// ...
4069/// EMIT %ptr.ind = ptradd %pointer.phi, %vf
4070/// EMIT branch-on-count ...
4071/// }
4073 VPlan *Plan = R->getParent()->getPlan();
4074 VPValue *Start = R->getStartValue();
4075 VPValue *Step = R->getStepValue();
4076 VPValue *VF = R->getVFValue();
4077
4078 assert(R->getInductionDescriptor().getKind() ==
4080 "Not a pointer induction according to InductionDescriptor!");
4081 assert(R->getScalarType()->isPointerTy() && "Unexpected type.");
4082 assert(!R->onlyScalarsGenerated(Plan->hasScalableVF()) &&
4083 "Recipe should have been replaced");
4084
4085 VPBuilder Builder(R);
4086 DebugLoc DL = R->getDebugLoc();
4087
4088 // Build a scalar pointer phi.
4089 VPPhi *ScalarPtrPhi = Builder.createScalarPhi(Start, DL, "pointer.phi");
4090
4091 // Create actual address geps that use the pointer phi as base and a
4092 // vectorized version of the step value (<step*0, ..., step*N>) as offset.
4093 Builder.setInsertPoint(R->getParent(), R->getParent()->getFirstNonPhi());
4094 Type *StepTy = Step->getScalarType();
4095 VPValue *Offset = Builder.createNaryOp(VPInstruction::StepVector, {}, StepTy);
4096 Offset = Builder.createOverflowingOp(Instruction::Mul, {Offset, Step});
4097 VPValue *PtrAdd =
4098 Builder.createWidePtrAdd(ScalarPtrPhi, Offset, DL, "vector.gep");
4099 R->replaceAllUsesWith(PtrAdd);
4100
4101 // Create the backedge value for the scalar pointer phi.
4103 Builder.setInsertPoint(ExitingBB, ExitingBB->getTerminator()->getIterator());
4104 VF = Builder.createScalarZExtOrTrunc(VF, StepTy, VF->getScalarType(), DL);
4105 VPValue *Inc = Builder.createOverflowingOp(Instruction::Mul, {Step, VF});
4106
4107 VPValue *InductionGEP =
4108 Builder.createPtrAdd(ScalarPtrPhi, Inc, DL, "ptr.ind");
4109 ScalarPtrPhi->addIncoming(InductionGEP);
4110}
4111
4112/// Expand a VPDerivedIVRecipe into executable recipes.
4114 VPBuilder Builder(R);
4115 VPValue *Start = R->getStartValue();
4116 VPValue *Step = R->getStepValue();
4117 VPValue *Index = R->getIndex();
4118 Type *StepTy = Step->getScalarType();
4119 Type *IndexTy = Index->getScalarType();
4120 Index = StepTy->isIntegerTy()
4121 ? Builder.createScalarSExtOrTrunc(
4122 Index, StepTy, IndexTy, DebugLoc::getCompilerGenerated())
4123 : Builder.createScalarCast(Instruction::SIToFP, Index, StepTy,
4125 switch (R->getInductionKind()) {
4127 assert(Index->getScalarType() == Start->getScalarType() &&
4128 "Index type does not match StartValue type");
4129 return R->replaceAllUsesWith(Builder.createAdd(
4130 Start, Builder.createOverflowingOp(Instruction::Mul, {Index, Step})));
4131 }
4133 return R->replaceAllUsesWith(Builder.createPtrAdd(
4134 Start, Builder.createOverflowingOp(Instruction::Mul, {Index, Step})));
4136 assert(StepTy->isFloatingPointTy() && "Expected FP Step value");
4137 const FPMathOperator *FPBinOp = R->getFPBinOp();
4138 assert(FPBinOp &&
4139 (FPBinOp->getOpcode() == Instruction::FAdd ||
4140 FPBinOp->getOpcode() == Instruction::FSub) &&
4141 "Original BinOp should be defined for FP induction");
4142 FastMathFlags FMF = FPBinOp->getFastMathFlags();
4143 VPValue *FMul = Builder.createNaryOp(Instruction::FMul, {Step, Index}, FMF);
4144 return R->replaceAllUsesWith(
4145 Builder.createNaryOp(FPBinOp->getOpcode(), {Start, FMul}, FMF));
4146 }
4148 return;
4149 }
4150 llvm_unreachable("Unhandled induction kind");
4151}
4152
4154 // Replace loop regions with explicity CFG.
4155 SmallVector<VPRegionBlock *> LoopRegions;
4157 vp_depth_first_deep(Plan.getEntry()))) {
4158 if (!R->isReplicator())
4159 LoopRegions.push_back(R);
4160 }
4161 for (VPRegionBlock *R : LoopRegions)
4162 R->dissolveToCFGLoop();
4163}
4164
4167 // The transform runs after dissolving loop regions, so all VPBasicBlocks
4168 // terminated with BranchOnTwoConds are reached via a shallow traversal.
4171 if (!VPBB->empty() && match(&VPBB->back(), m_BranchOnTwoConds()))
4172 WorkList.push_back(cast<VPInstruction>(&VPBB->back()));
4173 }
4174
4175 // Expand BranchOnTwoConds instructions into explicit CFG with two new
4176 // single-condition branches:
4177 // 1. A branch that replaces BranchOnTwoConds, jumps to the first successor if
4178 // the first condition is true, and otherwise jumps to a new interim block.
4179 // 2. A branch that ends the interim block, jumps to the second successor if
4180 // the second condition is true, and otherwise jumps to the third
4181 // successor.
4182 for (VPInstruction *Br : WorkList) {
4183 assert(Br->getNumOperands() == 2 &&
4184 "BranchOnTwoConds must have exactly 2 conditions");
4185 DebugLoc DL = Br->getDebugLoc();
4186 VPBasicBlock *BrOnTwoCondsBB = Br->getParent();
4187 const auto Successors = to_vector(BrOnTwoCondsBB->getSuccessors());
4188 assert(Successors.size() == 3 &&
4189 "BranchOnTwoConds must have exactly 3 successors");
4190
4191 for (VPBlockBase *Succ : Successors)
4192 VPBlockUtils::disconnectBlocks(BrOnTwoCondsBB, Succ);
4193
4194 VPValue *Cond0 = Br->getOperand(0);
4195 VPValue *Cond1 = Br->getOperand(1);
4196 VPBlockBase *Succ0 = Successors[0];
4197 VPBlockBase *Succ1 = Successors[1];
4198 VPBlockBase *Succ2 = Successors[2];
4199
4200 // If the successor block for both conditions is the same, then combine the
4201 // two conditions and plant a single conditional branch.
4202 if (Succ0 == Succ1) {
4203 VPBuilder Builder(Br);
4204 VPValue *Combined = Builder.createOr(Cond0, Cond1, DL);
4205 Builder.createNaryOp(VPInstruction::BranchOnCond, {Combined}, DL);
4206 VPBlockUtils::connectBlocks(BrOnTwoCondsBB, Succ0);
4207 VPBlockUtils::connectBlocks(BrOnTwoCondsBB, Succ2);
4208 Br->eraseFromParent();
4209 continue;
4210 }
4211
4212 assert(!Succ0->getParent() && !Succ1->getParent() && !Succ2->getParent() &&
4213 !BrOnTwoCondsBB->getParent() && "regions must already be dissolved");
4214
4215 VPBasicBlock *InterimBB =
4216 Plan.createVPBasicBlock(BrOnTwoCondsBB->getName() + ".interim");
4217
4218 VPBuilder(BrOnTwoCondsBB)
4220 VPBlockUtils::connectBlocks(BrOnTwoCondsBB, Succ0);
4221 VPBlockUtils::connectBlocks(BrOnTwoCondsBB, InterimBB);
4222
4224 VPBlockUtils::connectBlocks(InterimBB, Succ1);
4225 VPBlockUtils::connectBlocks(InterimBB, Succ2);
4226 Br->eraseFromParent();
4227 }
4228}
4229
4232 vp_depth_first_deep(Plan.getEntry()))) {
4233 for (VPRecipeBase &R : make_early_inc_range(*VPBB)) {
4234 VPBuilder Builder(&R);
4235 if (auto *WidenIVR = dyn_cast<VPWidenIntOrFpInductionRecipe>(&R)) {
4237 WidenIVR->eraseFromParent();
4238 continue;
4239 }
4240
4241 if (auto *WidenIVR = dyn_cast<VPWidenPointerInductionRecipe>(&R)) {
4242 // If the recipe only generates scalars, scalarize it instead of
4243 // expanding it.
4244 if (WidenIVR->onlyScalarsGenerated(Plan.hasScalableVF())) {
4245 VPValue *PtrAdd =
4246 scalarizeVPWidenPointerInduction(WidenIVR, Plan, Builder);
4247 WidenIVR->replaceAllUsesWith(PtrAdd);
4248 WidenIVR->eraseFromParent();
4249 continue;
4250 }
4252 WidenIVR->eraseFromParent();
4253 continue;
4254 }
4255
4256 if (auto *DerivedIVR = dyn_cast<VPDerivedIVRecipe>(&R)) {
4257 expandVPDerivedIV(DerivedIVR);
4258 DerivedIVR->eraseFromParent();
4259 continue;
4260 }
4261
4262 if (auto *WideCanIV = dyn_cast<VPWidenCanonicalIVRecipe>(&R)) {
4263 VPValue *CanIV = WideCanIV->getCanonicalIV();
4264 Type *CanIVTy = CanIV->getScalarType();
4265 VPValue *Step = WideCanIV->getStepValue();
4266 if (!Step) {
4267 assert(Plan.getConcreteUF() == 1 &&
4268 "Expected unroller to have materialized step for UF != 1");
4269 Step = Plan.getZero(CanIVTy);
4270 }
4271 CanIV = Builder.createNaryOp(VPInstruction::Broadcast, CanIV);
4272 Step = Builder.createNaryOp(VPInstruction::Broadcast, Step);
4273 Step = Builder.createAdd(
4274 Step, Builder.createNaryOp(VPInstruction::StepVector, {}, CanIVTy));
4275 VPValue *CanVecIV =
4276 Builder.createAdd(CanIV, Step, WideCanIV->getDebugLoc(), "vec.iv",
4277 WideCanIV->getNoWrapFlags());
4278 WideCanIV->replaceAllUsesWith(CanVecIV);
4279 WideCanIV->eraseFromParent();
4280 continue;
4281 }
4282
4283 // Expand VPBlendRecipe into VPInstruction::Select.
4284 if (auto *Blend = dyn_cast<VPBlendRecipe>(&R)) {
4285 VPValue *Select = Blend->getIncomingValue(0);
4286 for (unsigned I = 1; I != Blend->getNumIncomingValues(); ++I)
4287 Select = Builder.createSelect(Blend->getMask(I),
4288 Blend->getIncomingValue(I), Select,
4289 R.getDebugLoc(), "predphi", *Blend);
4290 Blend->replaceAllUsesWith(Select);
4291 Blend->eraseFromParent();
4292 continue;
4293 }
4294
4295 if (auto *VEPR = dyn_cast<VPVectorEndPointerRecipe>(&R)) {
4296 if (!VEPR->getOffset()) {
4297 assert(Plan.getConcreteUF() == 1 &&
4298 "Expected unroller to have materialized offset for UF != 1");
4299 VEPR->materializeOffset();
4300 }
4301 continue;
4302 }
4303
4304 if (auto *Expr = dyn_cast<VPExpressionRecipe>(&R)) {
4305 Expr->decompose();
4306 Expr->eraseFromParent();
4307 continue;
4308 }
4309
4310 // Expand LastActiveLane into Not + FirstActiveLane + Sub.
4311 auto *LastActiveL = dyn_cast<VPInstruction>(&R);
4312 if (LastActiveL &&
4313 LastActiveL->getOpcode() == VPInstruction::LastActiveLane) {
4314 // Create Not(Mask) for all operands.
4316 for (VPValue *Op : LastActiveL->operands()) {
4317 VPValue *NotMask = Builder.createNot(Op, LastActiveL->getDebugLoc());
4318 NotMasks.push_back(NotMask);
4319 }
4320
4321 // Create FirstActiveLane on the inverted masks.
4322 VPValue *FirstInactiveLane = Builder.createFirstActiveLane(
4323 NotMasks, LastActiveL->getDebugLoc(), "first.inactive.lane");
4324
4325 // Subtract 1 to get the last active lane.
4326 VPValue *One =
4327 Plan.getConstantInt(FirstInactiveLane->getScalarType(), 1);
4328 VPValue *LastLane =
4329 Builder.createSub(FirstInactiveLane, One,
4330 LastActiveL->getDebugLoc(), "last.active.lane");
4331
4332 LastActiveL->replaceAllUsesWith(LastLane);
4333 LastActiveL->eraseFromParent();
4334 continue;
4335 }
4336
4337 // Lower MaskedCond with block mask to LogicalAnd.
4339 auto *VPI = cast<VPInstruction>(&R);
4340 assert(VPI->isMasked() &&
4341 "Unmasked MaskedCond should be simplified earlier");
4342 VPI->replaceAllUsesWith(Builder.createNaryOp(
4343 VPInstruction::LogicalAnd, {VPI->getMask(), VPI->getOperand(0)}));
4344 VPI->eraseFromParent();
4345 continue;
4346 }
4347
4348 // Lower CanonicalIVIncrementForPart to plain Add.
4349 if (match(
4350 &R,
4352 auto *VPI = cast<VPInstruction>(&R);
4353 VPValue *Add = Builder.createOverflowingOp(
4354 Instruction::Add, VPI->operands(), VPI->getNoWrapFlags(),
4355 VPI->getDebugLoc());
4356 VPI->replaceAllUsesWith(Add);
4357 VPI->eraseFromParent();
4358 continue;
4359 }
4360
4361 // Lower BranchOnCount to ICmp + BranchOnCond.
4362 VPValue *IV, *TC;
4363 if (match(&R, m_BranchOnCount(m_VPValue(IV), m_VPValue(TC)))) {
4364 auto *BranchOnCountInst = cast<VPInstruction>(&R);
4365 DebugLoc DL = BranchOnCountInst->getDebugLoc();
4366 VPValue *Cond = Builder.createICmp(CmpInst::ICMP_EQ, IV, TC, DL);
4367 Builder.createNaryOp(VPInstruction::BranchOnCond, Cond, DL);
4368 BranchOnCountInst->eraseFromParent();
4369 continue;
4370 }
4371
4372 VPValue *VectorStep;
4373 VPValue *ScalarStep;
4375 m_VPValue(VectorStep), m_VPValue(ScalarStep))))
4376 continue;
4377
4378 // Expand WideIVStep.
4379 auto *VPI = cast<VPInstruction>(&R);
4380 Type *IVTy = VPI->getScalarType();
4381 if (VectorStep->getScalarType() != IVTy) {
4383 ? Instruction::UIToFP
4384 : Instruction::Trunc;
4385 VectorStep = Builder.createWidenCast(CastOp, VectorStep, IVTy);
4386 }
4387
4388 assert(!match(ScalarStep, m_One()) && "Expected non-unit scalar-step");
4389 if (ScalarStep->getScalarType() != IVTy) {
4390 ScalarStep =
4391 Builder.createWidenCast(Instruction::Trunc, ScalarStep, IVTy);
4392 }
4393
4394 VPIRFlags Flags;
4395 unsigned MulOpc;
4396 if (IVTy->isFloatingPointTy()) {
4397 MulOpc = Instruction::FMul;
4398 Flags = VPI->getFastMathFlagsOrNone();
4399 } else {
4400 MulOpc = Instruction::Mul;
4401 Flags = VPIRFlags::getDefaultFlags(MulOpc);
4402 }
4403
4404 VPInstruction *Mul = Builder.createNaryOp(
4405 MulOpc, {VectorStep, ScalarStep}, Flags, R.getDebugLoc());
4406 VectorStep = Mul;
4407 VPI->replaceAllUsesWith(VectorStep);
4408 VPI->eraseFromParent();
4409 }
4410 }
4411}
4412
4413/// Returns the VPValue representing the uncountable exit comparison used by
4414/// AnyOf if the recipes it depends on can be traced back to live-ins and
4415/// the addresses (in GEP/PtrAdd form) of any (non-masked) load used in
4416/// generating the values for the comparison. The recipes are stored in
4417/// \p Recipes.
4418static std::optional<VPValue *>
4420 VPBasicBlock *LatchVPBB) {
4421 // Given a plain CFG VPlan loop with countable latch exiting block
4422 // \p LatchVPBB, we're looking to match the recipes contributing to the
4423 // uncountable exit condition comparison (here, vp<%4>) back to either
4424 // live-ins or the address nodes for the load used as part of the uncountable
4425 // exit comparison so that we can either move them within the loop, or copy
4426 // them to the preheader depending on the chosen method for dealing with
4427 // stores in uncountable exit loops.
4428 //
4429 // Currently, the address of the load is restricted to a GEP with 2 operands
4430 // and a live-in base address. This constraint may be relaxed later.
4431 //
4432 // VPlan ' for UF>=1' {
4433 // Live-in vp<%0> = VF * UF
4434 // Live-in vp<%1> = vector-trip-count
4435 // Live-in ir<20> = original trip-count
4436 //
4437 // ir-bb<entry>:
4438 // Successor(s): scalar.ph, vector.ph
4439 //
4440 // vector.ph:
4441 // Successor(s): for.body
4442 //
4443 // for.body:
4444 // EMIT vp<%2> = phi ir<0>, vp<%index.next>
4445 // EMIT-SCALAR ir<%iv> = phi [ ir<0>, vector.ph ], [ ir<%iv.next>, for.inc ]
4446 // EMIT ir<%uncountable.addr> = getelementptr inbounds nuw ir<%pred>,ir<%iv>
4447 // EMIT ir<%uncountable.val> = load ir<%uncountable.addr>
4448 // EMIT ir<%uncountable.cond> = icmp sgt ir<%uncountable.val>, ir<500>
4449 // EMIT vp<%3> = masked-cond ir<%uncountable.cond>
4450 // Successor(s): for.inc
4451 //
4452 // for.inc:
4453 // EMIT ir<%iv.next> = add nuw nsw ir<%iv>, ir<1>
4454 // EMIT ir<%countable.cond> = icmp eq ir<%iv.next>, ir<20>
4455 // EMIT vp<%index.next> = add nuw vp<%2>, vp<%0>
4456 // EMIT vp<%4> = any-of ir<%3>
4457 // EMIT vp<%5> = icmp eq vp<%index.next>, vp<%1>
4458 // EMIT branch-on-two-conds vp<%4>, vp<%5>
4459 // Successor(s): middle.block, middle.block, for.body
4460 //
4461 // middle.block:
4462 // Successor(s): ir-bb<exit>, scalar.ph
4463 //
4464 // ir-bb<exit>:
4465 // No successors
4466 //
4467 // scalar.ph:
4468 // }
4469
4470 // Find the uncountable loop exit condition.
4471 VPValue *UncountableCondition = nullptr;
4472 if (!match(LatchVPBB->getTerminator(),
4473 m_BranchOnTwoConds(m_AnyOf(m_VPValue(UncountableCondition)),
4474 m_VPValue())))
4475 return std::nullopt;
4476
4478 Worklist.push_back(UncountableCondition);
4479 while (!Worklist.empty()) {
4480 VPValue *V = Worklist.pop_back_val();
4481
4482 // Any value defined outside the loop does not need to be copied.
4483 if (V->isDefinedOutsideLoopRegions())
4484 continue;
4485
4486 // FIXME: Remove the single user restriction; it's here because we're
4487 // starting with the simplest set of loops we can, and multiple
4488 // users means needing to add PHI nodes in the transform.
4489 if (V->getNumUsers() > 1)
4490 return std::nullopt;
4491
4492 VPValue *Op1, *Op2;
4493 // Walk back through recipes until we find at least one load from memory.
4494 if (match(V, m_ICmp(m_VPValue(Op1), m_VPValue(Op2)))) {
4495 Worklist.push_back(Op1);
4496 Worklist.push_back(Op2);
4497 Recipes.push_back(cast<VPInstruction>(V->getDefiningRecipe()));
4498 } else if (match(V, m_VPInstruction<Instruction::Load>(m_VPValue(Op1)))) {
4499 VPRecipeBase *GepR = Op1->getDefiningRecipe();
4500 // Only matching base + single offset term for now.
4501 if (GepR->getNumOperands() != 2)
4502 return std::nullopt;
4503 // Matching a GEP with a loop-invariant base ptr.
4505 m_LiveIn(), m_VPValue())))
4506 return std::nullopt;
4507 Recipes.push_back(cast<VPInstruction>(V->getDefiningRecipe()));
4508 Recipes.push_back(cast<VPInstruction>(GepR));
4510 m_VPValue(Op1)))) {
4511 Worklist.push_back(Op1);
4512 Recipes.push_back(cast<VPInstruction>(V->getDefiningRecipe()));
4513 } else
4514 return std::nullopt;
4515 }
4516
4517 // If we couldn't match anything, don't return the condition. It may be
4518 // defined outside the loop.
4519 if (Recipes.empty() || none_of(Recipes, [](VPInstruction *I) {
4521 }))
4522 return std::nullopt;
4523
4524 return UncountableCondition;
4525}
4526
4532
4533/// Update \p Plan to mask memory operations in the loop based on whether the
4534/// early exit is taken or not.
4535///
4536/// We're currently expecting to find a loop with properties similar to the
4537/// following:
4538///
4539/// for.body:
4540/// ir<%indvars.iv> = WIDEN-INDUCTION nuw nsw ir<0>, ir<1>, vp<%0>
4541/// EMIT ir<%arrayidx> = getelementptr inbounds nuw ir<@c>, ir<%indvars.iv>
4542/// EMIT-SCALAR ir<%0> = load ir<%arrayidx>
4543/// EMIT ir<%cmp1> = icmp sgt ir<%0>, ir<5>
4544/// EMIT vp<%1> = masked-cond ir<%cmp1>
4545/// Successor(s): if.end
4546///
4547/// if.end:
4548/// EMIT ir<%arrayidx3> = getelementptr inbounds nuw ir<@src>, ir<%indvars.iv>
4549/// EMIT-SCALAR ir<%2> = load ir<%arrayidx3>
4550/// EMIT ir<%add> = add nsw ir<%2>, ir<42>
4551/// EMIT ir<%arrayidx5> = getelementptr inbounds nuw ir<@dst>, ir<%indvars.iv>
4552/// EMIT store ir<%add>, ir<%arrayidx5>
4553/// EMIT ir<%indvars.iv.next> = add nuw nsw ir<%indvars.iv>, ir<1>
4554/// EMIT vp<%3> = any-of ir<%1>
4555/// EMIT ir<%exitcond.not> = icmp eq ir<%indvars.iv.next>, ir<10000>
4556/// EMIT branch-on-two-conds vp<%3>, ir<%exitcond.not>
4557/// Successor(s): middle.block, middle.block, for.body
4558///
4559/// We currently expect LoopVectorizationLegality to ensure that:
4560/// * There must also be a counted exit. We will need to support speculative
4561/// or first-faulting loads before we can remove this restriction.
4562/// * Any stores within the loop must not alias with the load used for the
4563/// uncountable exit. We can relax this a bit with runtime aliasing checks.
4564/// * Other memory operations in the loop can take place before or after the
4565/// uncountable exit, but must also be unconditional. We need to support
4566/// combining the conditions in VPlanPredicator.
4567/// * The loop must have a single unconditional load contributing to the
4568/// uncountable exit comparison, and the other term must be loop-invariant.
4569/// Improving upon this requires work in getRecipesForUncountableExit to
4570/// handle more complex recipe graphs.
4573 VPBasicBlock *HeaderVPBB, VPBasicBlock *LatchVPBB, VPBasicBlock *MiddleVPBB,
4574 Loop *TheLoop, PredicatedScalarEvolution &PSE, DominatorTree &DT,
4575 AssumptionCache *AC) {
4576
4577 // Disconnect early exiting blocks from successors, remove branches. We
4578 // currently don't support multiple uses for recipes involved in creating
4579 // the uncountable exit condition.
4580 for (auto &Exit : Exits) {
4581 if (Exit.EarlyExitingVPBB == LatchVPBB)
4582 continue;
4583
4584 for (VPRecipeBase &R : Exit.EarlyExitVPBB->phis())
4585 cast<VPIRPhi>(&R)->removeIncomingValueFor(Exit.EarlyExitingVPBB);
4586 Exit.EarlyExitingVPBB->getTerminator()->eraseFromParent();
4587 VPBlockUtils::disconnectBlocks(Exit.EarlyExitingVPBB, Exit.EarlyExitVPBB);
4588 }
4589
4590 VPDominatorTree VPDT(Plan);
4591
4592 // We can abandon a VPlan entirely if we return false here, so we shouldn't
4593 // crash if some earlier assumptions on scalar IR don't hold for the vplan
4594 // version of the loop.
4595 SmallVector<VPInstruction *, 8> ConditionRecipes;
4596
4597 std::optional<VPValue *> Cond =
4598 getRecipesForUncountableExit(ConditionRecipes, LatchVPBB);
4599 if (!Cond)
4600 return false;
4601
4602 // Find load contributing to condition.
4603 // At the moment LoopVectorizationLegality only supports a single
4604 // early-exit expression with a compare and a single load that must
4605 // be unconditional.
4606 // TODO: Support more than one load.
4607 auto *Load =
4608 find_singleton<VPInstruction>(ConditionRecipes, [](auto *I, bool _) {
4610 ? I
4611 : nullptr;
4612 });
4613 assert(Load && "Couldn't find exactly one load");
4614 // TODO: Support conditional loads for uncountable exits.
4615 assert(VPDT.dominates(Load->getParent(), LatchVPBB) &&
4616 "Uncountable exit condition load is conditional.");
4617 VPInstruction *Ptr = cast<VPInstruction>(Load->getOperand(0));
4618
4619 // Ensure that we are guaranteed to be able to dereference the memory used
4620 // for determining the uncountable exit for the maximum possible number of
4621 // scalar iterations of the loop.
4622 //
4623 // TODO: Support first-faulting loads in cases where we don't know whether
4624 // all possible addresses are dereferenceable.
4625 {
4627 const SCEV *PtrSCEV = vputils::getSCEVExprForVPValue(Ptr, PSE, TheLoop);
4628 const DataLayout &DL = Plan.getDataLayout();
4629 APInt EltSize(DL.getIndexTypeSizeInBits(Ptr->getScalarType()),
4630 DL.getTypeStoreSize(Load->getScalarType()).getFixedValue());
4632 PtrSCEV, cast<LoadInst>(Load->getUnderlyingInstr())->getAlign(),
4633 PSE.getSE()->getConstant(EltSize), TheLoop, *PSE.getSE(), DT, AC,
4634 &Predicates))
4635 return false;
4636 }
4637
4638 // Check for a single GEP for the condition load to see if we can link it to
4639 // a widen IV recipe with a step of 1; we're only interested in contiguous
4640 // accesses for the condition load right now.
4641 auto *IV = cast<VPWidenInductionRecipe>(&HeaderVPBB->front());
4642 if (!match(IV->getStartValue(), m_SpecificInt(0)) ||
4643 !match(IV->getStepValue(), m_SpecificInt(1)))
4644 return false;
4646 m_Specific(IV))))
4647 return false;
4648
4649 // We want to guarantee that the uncountable exit condition (and the mask
4650 // we will generate from it) are available for all operations in the loop
4651 // that need to be masked. If the condition recipes are not already the first
4652 // recipes in the header after the last phi, move them there.
4653 auto InsertIt = HeaderVPBB->getFirstNonPhi();
4654 while (InsertIt != HeaderVPBB->end() &&
4655 is_contained(ConditionRecipes, &*InsertIt)) {
4656 erase(ConditionRecipes, &*InsertIt);
4657 InsertIt++;
4658 }
4659 for (auto *Recipe : reverse(ConditionRecipes))
4660 Recipe->moveBefore(*HeaderVPBB, InsertIt);
4661
4662 // Create a mask to represent all lanes that fully execute in the vector loop,
4663 // stopping short of any early exit.
4664 VPBuilder MaskBuilder(HeaderVPBB, InsertIt);
4665 VPValue *FirstActive = MaskBuilder.createFirstActiveLane(*Cond);
4666 Type *IVScalarTy = IV->getScalarType();
4667 Type *FirstActiveTy = FirstActive->getScalarType();
4668 VPValue *ALMMultiplier = Plan.getConstantInt(IVScalarTy, 1);
4669 VPValue *Zero = Plan.getZero(IVScalarTy);
4670 FirstActive = MaskBuilder.createScalarZExtOrTrunc(FirstActive, IVScalarTy,
4671 FirstActiveTy, DebugLoc());
4673 {Zero, FirstActive, ALMMultiplier},
4674 DebugLoc(), "uncountable.exit.mask");
4675
4676 // Convert all other memory operations to use the mask.
4677 for (VPBasicBlock *VPBB : vp_rpo_plain_cfg_loop_body(HeaderVPBB))
4678 for (VPRecipeBase &R : *VPBB)
4679 if (R.mayReadOrWriteMemory() && &R != Load) {
4680 // TODO: Handle conditional memory operations in the loop.
4681 if (!VPDT.dominates(R.getParent(), LatchVPBB))
4682 return false;
4683 cast<VPInstruction>(&R)->addMask(Mask);
4684 }
4685
4686 // Update middle block branch to compare (IV + however many lanes were active)
4687 // against the full trip count, since we may be exiting the vector loop early.
4688 // If we didn't take an early exit, we should get the equivalent of VF from
4689 // the FirstActiveLane.
4690 assert(match(MiddleVPBB->getTerminator(), m_BranchOnCond()) &&
4691 "Expected BranchOnCond terminator for MiddleVPBB");
4692 VPBuilder MiddleBuilder(MiddleVPBB->getTerminator());
4693 VPValue *ScalarIV = MiddleBuilder.createNaryOp(VPInstruction::ExtractLane,
4694 {Zero, IV}, DebugLoc());
4695 VPValue *ExitIV = MiddleBuilder.createAdd(ScalarIV, FirstActive);
4696 VPValue *FullTC =
4697 MiddleBuilder.createICmp(CmpInst::ICMP_EQ, ExitIV, Plan.getTripCount());
4698 MiddleVPBB->getTerminator()->setOperand(0, FullTC);
4699
4700 // Update resume phi in scalar.ph.
4701 VPBasicBlock *ScalarPH = Plan.getScalarPreheader();
4702 auto Phis = ScalarPH->phis();
4703 // TODO: Handle more than one Phi; re-derive from IV.
4704 // TODO: Handle reductions.
4705 if (range_size(Phis) != 1)
4706 return false;
4707 VPPhi *ContinueIV = cast<VPPhi>(Phis.begin());
4708 // Make sure we're referring to the same IV.
4709 assert(
4710 match(ContinueIV->getOperand(0),
4712 "Continuing from different IV");
4713 ContinueIV->setOperand(0, ExitIV);
4714 return true;
4715}
4716
4718 VPlan &Plan, VPBasicBlock *HeaderVPBB, VPBasicBlock *LatchVPBB,
4719 VPBasicBlock *MiddleVPBB, Loop *TheLoop, PredicatedScalarEvolution &PSE,
4721#ifndef NDEBUG
4722 VPDominatorTree VPDT(Plan);
4723#endif
4724 VPBuilder LatchBuilder(LatchVPBB->getTerminator());
4726 for (VPIRBasicBlock *ExitBlock : Plan.getExitBlocks()) {
4727 for (VPBlockBase *Pred : to_vector(ExitBlock->getPredecessors())) {
4728 if (Pred == MiddleVPBB)
4729 continue;
4730 // Collect condition for this early exit.
4731 auto *EarlyExitingVPBB = cast<VPBasicBlock>(Pred);
4732 VPBlockBase *TrueSucc = EarlyExitingVPBB->getSuccessors()[0];
4733 VPValue *CondOfEarlyExitingVPBB;
4734 [[maybe_unused]] bool Matched =
4735 match(EarlyExitingVPBB->getTerminator(),
4736 m_BranchOnCond(m_VPValue(CondOfEarlyExitingVPBB)));
4737 assert(Matched && "Terminator must be BranchOnCond");
4738
4739 // Insert the MaskedCond in the EarlyExitingVPBB so the predicator adds
4740 // the correct block mask.
4741 VPBuilder EarlyExitingBuilder(EarlyExitingVPBB->getTerminator());
4742 auto *CondToEarlyExit = EarlyExitingBuilder.createNaryOp(
4744 TrueSucc == ExitBlock
4745 ? CondOfEarlyExitingVPBB
4746 : EarlyExitingBuilder.createNot(CondOfEarlyExitingVPBB));
4747 assert((isa<VPIRValue>(CondOfEarlyExitingVPBB) ||
4748 !VPDT.properlyDominates(EarlyExitingVPBB, LatchVPBB) ||
4749 VPDT.properlyDominates(
4750 CondOfEarlyExitingVPBB->getDefiningRecipe()->getParent(),
4751 LatchVPBB)) &&
4752 "exit condition must dominate the latch");
4753 Exits.push_back({
4754 EarlyExitingVPBB,
4755 ExitBlock,
4756 CondToEarlyExit,
4757 });
4758 }
4759 }
4760
4761 assert(!Exits.empty() && "must have at least one early exit");
4762 // Sort exits by RPO order to get correct program order. RPO gives a
4763 // topological ordering of the CFG, ensuring upstream exits are checked
4764 // before downstream exits in the dispatch chain.
4766 HeaderVPBB);
4768 for (const auto &[Num, VPB] : enumerate(RPOT))
4769 RPOIdx[VPB] = Num;
4770 llvm::sort(Exits, [&RPOIdx](const EarlyExitInfo &A, const EarlyExitInfo &B) {
4771 return RPOIdx[A.EarlyExitingVPBB] < RPOIdx[B.EarlyExitingVPBB];
4772 });
4773#ifndef NDEBUG
4774 // After RPO sorting, verify that for any pair where one exit dominates
4775 // another, the dominating exit comes first. This is guaranteed by RPO
4776 // (topological order) and is required for the dispatch chain correctness.
4777 for (unsigned I = 0; I + 1 < Exits.size(); ++I)
4778 for (unsigned J = I + 1; J < Exits.size(); ++J)
4779 assert(!VPDT.properlyDominates(Exits[J].EarlyExitingVPBB,
4780 Exits[I].EarlyExitingVPBB) &&
4781 "RPO sort must place dominating exits before dominated ones");
4782#endif
4783
4784 // Build the AnyOf condition for the latch terminator using logical OR
4785 // to avoid poison propagation from later exit conditions when an earlier
4786 // exit is taken.
4787 VPValue *Combined = Exits[0].CondToExit;
4788 for (const EarlyExitInfo &Info : drop_begin(Exits))
4789 Combined = LatchBuilder.createLogicalOr(Combined, Info.CondToExit);
4790
4791 VPValue *IsAnyExitTaken =
4792 LatchBuilder.createNaryOp(VPInstruction::AnyOf, {Combined});
4793
4794 // Create a comparison for the latch exit condition and replace the
4795 // BranchOnCond with a BranchOnTwoConds. The original BranchOnCond's condition
4796 // is used as the latch-exit condition; canonical IV recipes have not been
4797 // introduced yet, so there is no BranchOnCount to derive the condition from.
4798 auto *LatchExitingBranch = cast<VPInstruction>(LatchVPBB->getTerminator());
4799 assert(LatchExitingBranch->getOpcode() == VPInstruction::BranchOnCond &&
4800 "Unexpected terminator");
4801 VPValue *IsLatchExitTaken = LatchExitingBranch->getOperand(0);
4802 DebugLoc LatchDL = LatchExitingBranch->getDebugLoc();
4803 LatchExitingBranch->eraseFromParent();
4804 LatchBuilder.setInsertPoint(LatchVPBB);
4806 {IsAnyExitTaken, IsLatchExitTaken}, LatchDL);
4807 LatchVPBB->clearSuccessors();
4808
4810 // If handling the exiting lane in the scalar loop, combine the exit
4811 // conditions into a single BranchOnCond.
4812 LatchVPBB->setSuccessors({MiddleVPBB, MiddleVPBB, HeaderVPBB});
4813 MiddleVPBB->clearPredecessors();
4814 MiddleVPBB->setPredecessors({LatchVPBB, LatchVPBB});
4816 Plan, Exits, HeaderVPBB, LatchVPBB, MiddleVPBB, TheLoop, PSE, DT, AC);
4817 }
4818
4819 // Create the vector.early.exit blocks.
4820 SmallVector<VPBasicBlock *> VectorEarlyExitVPBBs(Exits.size());
4821 for (unsigned Idx = 0; Idx != Exits.size(); ++Idx) {
4822 Twine BlockSuffix = Exits.size() == 1 ? "" : Twine(".") + Twine(Idx);
4823 VPBasicBlock *VectorEarlyExitVPBB =
4824 Plan.createVPBasicBlock("vector.early.exit" + BlockSuffix);
4825 VectorEarlyExitVPBBs[Idx] = VectorEarlyExitVPBB;
4826 }
4827
4828 // Create the dispatch block (or reuse the single exit block if only one
4829 // exit). The dispatch block computes the first active lane of the combined
4830 // condition and, for multiple exits, chains through conditions to determine
4831 // which exit to take.
4832 VPBasicBlock *DispatchVPBB =
4833 Exits.size() == 1 ? VectorEarlyExitVPBBs[0]
4834 : Plan.createVPBasicBlock("vector.early.exit.check");
4835 DispatchVPBB->setPredecessors({LatchVPBB});
4836 LatchVPBB->setSuccessors({DispatchVPBB, MiddleVPBB, HeaderVPBB});
4837 VPBuilder DispatchBuilder(DispatchVPBB, DispatchVPBB->begin());
4838 VPValue *FirstActiveLane = DispatchBuilder.createFirstActiveLane(
4839 {Combined}, DebugLoc::getUnknown(), "first.active.lane");
4840
4841 // For each early exit, disconnect the original exiting block
4842 // (early.exiting.I) from the exit block (ir-bb<exit.I>) and route through a
4843 // new vector.early.exit block. Update ir-bb<exit.I>'s phis to extract their
4844 // values at the first active lane:
4845 //
4846 // Input:
4847 // early.exiting.I:
4848 // ...
4849 // EMIT branch-on-cond vp<%cond.I>
4850 // Successor(s): in.loop.succ, ir-bb<exit.I>
4851 //
4852 // ir-bb<exit.I>:
4853 // IR %phi = phi [ vp<%incoming.I>, early.exiting.I ], ...
4854 //
4855 // Output:
4856 // early.exiting.I:
4857 // ...
4858 // Successor(s): in.loop.succ
4859 //
4860 // vector.early.exit.I:
4861 // EMIT vp<%exit.val> = extract-lane vp<%first.lane>, vp<%incoming.I>
4862 // Successor(s): ir-bb<exit.I>
4863 //
4864 // ir-bb<exit.I>:
4865 // IR %phi = phi ... (extra operand: vp<%exit.val> from
4866 // vector.early.exit.I)
4867 //
4868 for (auto [Exit, VectorEarlyExitVPBB] :
4869 zip_equal(Exits, VectorEarlyExitVPBBs)) {
4870 auto &[EarlyExitingVPBB, EarlyExitVPBB, _] = Exit;
4871 // Adjust the phi nodes in EarlyExitVPBB.
4872 // 1. remove incoming values from EarlyExitingVPBB,
4873 // 2. extract the incoming value at FirstActiveLane
4874 // 3. add back the extracts as last operands for the phis
4875 // Then adjust the CFG, removing the edge between EarlyExitingVPBB and
4876 // EarlyExitVPBB and adding a new edge between VectorEarlyExitVPBB and
4877 // EarlyExitVPBB. The extracts at FirstActiveLane are now the incoming
4878 // values from VectorEarlyExitVPBB.
4879 for (VPRecipeBase &R : EarlyExitVPBB->phis()) {
4880 auto *ExitIRI = cast<VPIRPhi>(&R);
4881 VPValue *IncomingVal =
4882 ExitIRI->getIncomingValueForBlock(EarlyExitingVPBB);
4883 VPValue *NewIncoming = IncomingVal;
4884 if (!isa<VPIRValue>(IncomingVal)) {
4885 VPBuilder EarlyExitBuilder(VectorEarlyExitVPBB);
4886 NewIncoming = EarlyExitBuilder.createNaryOp(
4887 VPInstruction::ExtractLane, {FirstActiveLane, IncomingVal},
4888 DebugLoc::getUnknown(), "early.exit.value");
4889 }
4890 ExitIRI->removeIncomingValueFor(EarlyExitingVPBB);
4891 ExitIRI->addIncoming(NewIncoming);
4892 }
4893
4894 EarlyExitingVPBB->getTerminator()->eraseFromParent();
4895 VPBlockUtils::disconnectBlocks(EarlyExitingVPBB, EarlyExitVPBB);
4896 VPBlockUtils::connectBlocks(VectorEarlyExitVPBB, EarlyExitVPBB);
4897 }
4898
4899 // Chain through exits: for each exit, check if its condition is true at
4900 // the first active lane. If so, take that exit; otherwise, try the next.
4901 // The last exit needs no check since it must be taken if all others fail.
4902 //
4903 // For 3 exits (cond.0, cond.1, cond.2), this creates:
4904 //
4905 // latch:
4906 // ...
4907 // EMIT vp<%combined> = logical-or vp<%cond.0>, vp<%cond.1>, vp<%cond.2>
4908 // ...
4909 //
4910 // vector.early.exit.check:
4911 // EMIT vp<%first.lane> = first-active-lane vp<%combined>
4912 // EMIT vp<%at.cond.0> = extract-lane vp<%first.lane>, vp<%cond.0>
4913 // EMIT branch-on-cond vp<%at.cond.0>
4914 // Successor(s): vector.early.exit.0, vector.early.exit.check.0
4915 //
4916 // vector.early.exit.check.0:
4917 // EMIT vp<%at.cond.1> = extract-lane vp<%first.lane>, vp<%cond.1>
4918 // EMIT branch-on-cond vp<%at.cond.1>
4919 // Successor(s): vector.early.exit.1, vector.early.exit.2
4920 VPBasicBlock *CurrentBB = DispatchVPBB;
4921 for (auto [I, Exit] : enumerate(ArrayRef(Exits).drop_back())) {
4922 VPValue *LaneVal = DispatchBuilder.createNaryOp(
4923 VPInstruction::ExtractLane, {FirstActiveLane, Exit.CondToExit},
4924 DebugLoc::getUnknown(), "exit.cond.at.lane");
4925
4926 // For the last dispatch, branch directly to the last exit on false;
4927 // otherwise, create a new check block.
4928 bool IsLastDispatch = (I + 2 == Exits.size());
4929 VPBasicBlock *FalseBB =
4930 IsLastDispatch ? VectorEarlyExitVPBBs.back()
4931 : Plan.createVPBasicBlock(
4932 Twine("vector.early.exit.check.") + Twine(I));
4933
4934 DispatchBuilder.createNaryOp(VPInstruction::BranchOnCond, {LaneVal});
4935 CurrentBB->setSuccessors({VectorEarlyExitVPBBs[I], FalseBB});
4936 VectorEarlyExitVPBBs[I]->setPredecessors({CurrentBB});
4937 FalseBB->setPredecessors({CurrentBB});
4938
4939 CurrentBB = FalseBB;
4940 DispatchBuilder.setInsertPoint(CurrentBB);
4941 }
4942
4943 return true;
4944}
4945
4946/// This function tries convert extended in-loop reductions to
4947/// VPExpressionRecipe and clamp the \p Range if it is beneficial and
4948/// valid. The created recipe must be decomposed to its constituent
4949/// recipes before execution.
4950static VPExpressionRecipe *
4952 VFRange &Range) {
4953 Type *RedTy = Red->getScalarType();
4954 VPValue *VecOp = Red->getVecOp();
4955
4956 assert(!Red->isPartialReduction() &&
4957 "This path does not support partial reductions");
4958
4959 // Clamp the range if using extended-reduction is profitable.
4960 auto IsExtendedRedValidAndClampRange =
4961 [&](unsigned Opcode, Instruction::CastOps ExtOpc, Type *SrcTy) -> bool {
4963 [&](ElementCount VF) {
4964 auto *SrcVecTy = cast<VectorType>(toVectorTy(SrcTy, VF));
4966
4968 InstructionCost ExtCost =
4969 cast<VPWidenCastRecipe>(VecOp)->computeCost(VF, Ctx);
4970 InstructionCost RedCost = Red->computeCost(VF, Ctx);
4971
4972 assert(!RedTy->isFloatingPointTy() &&
4973 "getExtendedReductionCost only supports integer types");
4974 ExtRedCost = Ctx.TTI.getExtendedReductionCost(
4975 Opcode, ExtOpc == Instruction::CastOps::ZExt, RedTy, SrcVecTy,
4976 Red->getFastMathFlagsOrNone(), CostKind);
4977 return ExtRedCost.isValid() && ExtRedCost < ExtCost + RedCost;
4978 },
4979 Range);
4980 };
4981
4982 VPValue *A;
4983 // Match reduce(ext)).
4985 IsExtendedRedValidAndClampRange(
4986 RecurrenceDescriptor::getOpcode(Red->getRecurrenceKind()),
4987 cast<VPWidenCastRecipe>(VecOp)->getOpcode(), A->getScalarType()))
4988 return new VPExpressionRecipe(cast<VPWidenCastRecipe>(VecOp), Red);
4989
4990 return nullptr;
4991}
4992
4993/// This function tries convert extended in-loop reductions to
4994/// VPExpressionRecipe and clamp the \p Range if it is beneficial
4995/// and valid. The created VPExpressionRecipe must be decomposed to its
4996/// constituent recipes before execution. Patterns of the
4997/// VPExpressionRecipe:
4998/// reduce.add(mul(...)),
4999/// reduce.add(mul(ext(A), ext(B))),
5000/// reduce.add(ext(mul(ext(A), ext(B)))).
5001/// reduce.fadd(fmul(ext(A), ext(B)))
5002static VPExpressionRecipe *
5004 VPCostContext &Ctx, VFRange &Range) {
5005 unsigned Opcode = RecurrenceDescriptor::getOpcode(Red->getRecurrenceKind());
5006 if (Opcode != Instruction::Add && Opcode != Instruction::Sub &&
5007 Opcode != Instruction::FAdd)
5008 return nullptr;
5009
5010 assert(!Red->isPartialReduction() &&
5011 "This path does not support partial reductions");
5012 Type *RedTy = Red->getScalarType();
5013
5014 // Clamp the range if using multiply-accumulate-reduction is profitable.
5015 auto IsMulAccValidAndClampRange =
5017 VPWidenCastRecipe *OuterExt) -> bool {
5019 [&](ElementCount VF) {
5021 Type *SrcTy = Ext0 ? Ext0->getOperand(0)->getScalarType() : RedTy;
5022 InstructionCost MulAccCost;
5023
5024 // getMulAccReductionCost for in-loop reductions does not support
5025 // mixed or floating-point extends.
5026 if (Ext0 && Ext1 &&
5027 (Ext0->getOpcode() != Ext1->getOpcode() ||
5028 Ext0->getOpcode() == Instruction::CastOps::FPExt))
5029 return false;
5030
5031 bool IsZExt =
5032 !Ext0 || Ext0->getOpcode() == Instruction::CastOps::ZExt;
5033 auto *SrcVecTy = cast<VectorType>(toVectorTy(SrcTy, VF));
5034 MulAccCost = Ctx.TTI.getMulAccReductionCost(IsZExt, Opcode, RedTy,
5035 SrcVecTy, CostKind);
5036
5037 InstructionCost MulCost = Mul->computeCost(VF, Ctx);
5038 InstructionCost RedCost = Red->computeCost(VF, Ctx);
5039 InstructionCost ExtCost = 0;
5040 if (Ext0)
5041 ExtCost += Ext0->computeCost(VF, Ctx);
5042 if (Ext1)
5043 ExtCost += Ext1->computeCost(VF, Ctx);
5044 if (OuterExt)
5045 ExtCost += OuterExt->computeCost(VF, Ctx);
5046
5047 return MulAccCost.isValid() &&
5048 MulAccCost < ExtCost + MulCost + RedCost;
5049 },
5050 Range);
5051 };
5052
5053 VPValue *VecOp = Red->getVecOp();
5054 VPRecipeBase *Sub = nullptr;
5055 VPValue *A, *B;
5056 VPValue *Tmp = nullptr;
5057
5058 if (RedTy->isFloatingPointTy())
5059 return nullptr;
5060
5061 // Sub reductions could have a sub between the add reduction and vec op.
5062 if (match(VecOp, m_Sub(m_ZeroInt(), m_VPValue(Tmp)))) {
5063 Sub = VecOp->getDefiningRecipe();
5064 VecOp = Tmp;
5065 }
5066
5067 // If ValB is a constant and can be safely extended, truncate it to the same
5068 // type as ExtA's operand, then extend it to the same type as ExtA. This
5069 // creates two uniform extends that can more easily be matched by the rest of
5070 // the bundling code. The ExtB reference, ValB and operand 1 of Mul are all
5071 // replaced with the new extend of the constant.
5072 auto ExtendAndReplaceConstantOp = [](VPWidenCastRecipe *ExtA,
5073 VPWidenCastRecipe *&ExtB, VPValue *&ValB,
5074 VPWidenRecipe *Mul) {
5075 if (!ExtA || ExtB || !isa<VPIRValue>(ValB))
5076 return;
5077 Type *NarrowTy = ExtA->getOperand(0)->getScalarType();
5078 Instruction::CastOps ExtOpc = ExtA->getOpcode();
5079 const APInt *Const;
5080 if (!match(ValB, m_APInt(Const)) ||
5082 Const, NarrowTy, TTI::getPartialReductionExtendKind(ExtOpc)))
5083 return;
5084 // The truncate ensures that the type of each extended operand is the
5085 // same, and it's been proven that the constant can be extended from
5086 // NarrowTy safely. Necessary since ExtA's extended operand would be
5087 // e.g. an i8, while the const will likely be an i32. This will be
5088 // elided by later optimisations.
5089 VPBuilder Builder(Mul);
5090 auto *Trunc =
5091 Builder.createWidenCast(Instruction::CastOps::Trunc, ValB, NarrowTy);
5092 Type *WideTy = ExtA->getScalarType();
5093 ValB = ExtB = Builder.createWidenCast(ExtOpc, Trunc, WideTy);
5094 Mul->setOperand(1, ExtB);
5095 };
5096
5097 // Try to match reduce.add(mul(...)).
5098 if (match(VecOp, m_Mul(m_VPValue(A), m_VPValue(B)))) {
5099 auto *RecipeA = dyn_cast<VPWidenCastRecipe>(A);
5100 auto *RecipeB = dyn_cast<VPWidenCastRecipe>(B);
5101 auto *Mul = cast<VPWidenRecipe>(VecOp);
5102
5103 // Convert reduce.add(mul(ext, const)) to reduce.add(mul(ext, ext(const)))
5104 ExtendAndReplaceConstantOp(RecipeA, RecipeB, B, Mul);
5105
5106 // Match reduce.add/sub(mul(ext, ext)).
5107 if (RecipeA && RecipeB && match(RecipeA, m_ZExtOrSExt(m_VPValue())) &&
5108 match(RecipeB, m_ZExtOrSExt(m_VPValue())) &&
5109 IsMulAccValidAndClampRange(Mul, RecipeA, RecipeB, nullptr)) {
5110 if (Sub)
5111 return new VPExpressionRecipe(RecipeA, RecipeB, Mul,
5112 cast<VPWidenRecipe>(Sub), Red);
5113 return new VPExpressionRecipe(RecipeA, RecipeB, Mul, Red);
5114 }
5115 // TODO: Add an expression type for this variant with a negated mul
5116 if (!Sub && IsMulAccValidAndClampRange(Mul, nullptr, nullptr, nullptr))
5117 return new VPExpressionRecipe(Mul, Red);
5118 }
5119 // TODO: Add an expression type for negated versions of other expression
5120 // variants.
5121 if (Sub)
5122 return nullptr;
5123
5124 // Match reduce.add(ext(mul(A, B))).
5125 if (match(VecOp, m_ZExtOrSExt(m_Mul(m_VPValue(A), m_VPValue(B))))) {
5126 auto *Ext = cast<VPWidenCastRecipe>(VecOp);
5127 auto *Mul = cast<VPWidenRecipe>(Ext->getOperand(0));
5128 auto *Ext0 = dyn_cast<VPWidenCastRecipe>(A);
5129 auto *Ext1 = dyn_cast<VPWidenCastRecipe>(B);
5130
5131 // reduce.add(ext(mul(ext, const)))
5132 // -> reduce.add(ext(mul(ext, ext(const))))
5133 ExtendAndReplaceConstantOp(Ext0, Ext1, B, Mul);
5134
5135 // reduce.add(ext(mul(ext(A), ext(B))))
5136 // -> reduce.add(mul(wider_ext(A), wider_ext(B)))
5137 // The inner extends must either have the same opcode as the outer extend or
5138 // be the same, in which case the multiply can never result in a negative
5139 // value and the outer extend can be folded away by doing wider
5140 // extends for the operands of the mul.
5141 if (Ext0 && Ext1 &&
5142 (Ext->getOpcode() == Ext0->getOpcode() || Ext0 == Ext1) &&
5143 Ext0->getOpcode() == Ext1->getOpcode() &&
5144 IsMulAccValidAndClampRange(Mul, Ext0, Ext1, Ext) && Mul->hasOneUse()) {
5145 auto *NewExt0 = new VPWidenCastRecipe(
5146 Ext0->getOpcode(), Ext0->getOperand(0), Ext->getScalarType(), nullptr,
5147 *Ext0, *Ext0, Ext0->getDebugLoc());
5148 NewExt0->insertBefore(Ext0);
5149
5150 VPWidenCastRecipe *NewExt1 = NewExt0;
5151 if (Ext0 != Ext1) {
5152 NewExt1 = new VPWidenCastRecipe(Ext1->getOpcode(), Ext1->getOperand(0),
5153 Ext->getScalarType(), nullptr, *Ext1,
5154 *Ext1, Ext1->getDebugLoc());
5155 NewExt1->insertBefore(Ext1);
5156 }
5157 auto *NewMul = Mul->cloneWithOperands({NewExt0, NewExt1});
5158 NewMul->insertBefore(Mul);
5159 Ext->replaceAllUsesWith(NewMul);
5160 Ext->eraseFromParent();
5161 Mul->eraseFromParent();
5162 return new VPExpressionRecipe(NewExt0, NewExt1, NewMul, Red);
5163 }
5164 }
5165 return nullptr;
5166}
5167
5168/// This function tries to create abstract recipes from the reduction recipe for
5169/// following optimizations and cost estimation.
5171 VPCostContext &Ctx,
5172 VFRange &Range) {
5173 // Creation of VPExpressions for partial reductions is entirely handled in
5174 // transformToPartialReduction.
5175 assert(!Red->isPartialReduction() &&
5176 "This path does not support partial reductions");
5177
5178 VPExpressionRecipe *AbstractR = nullptr;
5179 auto IP = std::next(Red->getIterator());
5180 auto *VPBB = Red->getParent();
5181 if (auto *MulAcc = tryToMatchAndCreateMulAccumulateReduction(Red, Ctx, Range))
5182 AbstractR = MulAcc;
5183 else if (auto *ExtRed = tryToMatchAndCreateExtendedReduction(Red, Ctx, Range))
5184 AbstractR = ExtRed;
5185 // Cannot create abstract inloop reduction recipes.
5186 if (!AbstractR)
5187 return;
5188
5189 AbstractR->insertBefore(*VPBB, IP);
5190 Red->replaceAllUsesWith(AbstractR);
5191}
5192
5203
5205 if (Plan.hasScalarVFOnly())
5206 return;
5207
5208#ifndef NDEBUG
5209 VPDominatorTree VPDT(Plan);
5210#endif
5211
5212 SmallVector<VPValue *> VPValues;
5213 if (VPValue *BTC = Plan.getBackedgeTakenCount())
5214 VPValues.push_back(BTC);
5215 append_range(VPValues, Plan.getLiveIns());
5216 for (VPRecipeBase &R : *Plan.getEntry())
5217 append_range(VPValues, R.definedValues());
5218
5219 auto *VectorPreheader = Plan.getVectorPreheader();
5220 for (VPValue *VPV : VPValues) {
5222 continue;
5223
5224 // Add explicit broadcast at the insert point that dominates all users.
5225 VPBasicBlock *HoistBlock = VectorPreheader;
5226 VPBasicBlock::iterator HoistPoint = VectorPreheader->end();
5227 for (VPUser *User : VPV->users()) {
5228 if (User->usesScalars(VPV))
5229 continue;
5230 if (cast<VPRecipeBase>(User)->getParent() == VectorPreheader)
5231 HoistPoint = HoistBlock->begin();
5232 else
5233 assert(VPDT.dominates(VectorPreheader,
5234 cast<VPRecipeBase>(User)->getParent()) &&
5235 "All users must be in the vector preheader or dominated by it");
5236 }
5237
5238 VPBuilder Builder(cast<VPBasicBlock>(HoistBlock), HoistPoint);
5239 auto *Broadcast = Builder.createNaryOp(VPInstruction::Broadcast, {VPV});
5240 VPV->replaceUsesWithIf(Broadcast,
5241 [VPV, Broadcast](VPUser &U, unsigned Idx) {
5242 return Broadcast != &U && !U.usesScalars(VPV);
5243 });
5244 }
5245}
5246
5247// Collect common metadata from a group of replicate recipes by intersecting
5248// metadata from all recipes in the group.
5250 VPIRMetadata CommonMetadata = *Recipes.front();
5251 for (VPReplicateRecipe *Recipe : drop_begin(Recipes))
5252 CommonMetadata.intersect(*Recipe);
5253 return CommonMetadata;
5254}
5255
5256template <unsigned Opcode>
5260 const Loop *L) {
5261 static_assert(Opcode == Instruction::Load || Opcode == Instruction::Store,
5262 "Only Load and Store opcodes supported");
5263 [[maybe_unused]] constexpr bool IsLoad = (Opcode == Instruction::Load);
5264
5265 // For each address, collect operations with the same or complementary masks.
5268 Plan, PSE, L,
5269 [](VPReplicateRecipe *RepR) { return RepR->isPredicated(); });
5270 for (auto Recipes : Groups) {
5271 if (Recipes.size() < 2)
5272 continue;
5273
5275 map_range(Recipes, bind_back<getLoadStoreValueType>(IsLoad))) &&
5276 "Expected all recipes in group to have the same load-store type");
5277
5278 // Collect groups with the same or complementary masks.
5279 for (VPReplicateRecipe *&RecipeI : Recipes) {
5280 if (!RecipeI)
5281 continue;
5282
5283 VPValue *MaskI = RecipeI->getMask();
5285 Group.push_back(RecipeI);
5286 RecipeI = nullptr;
5287
5288 // Find all operations with the same or complementary masks.
5289 bool HasComplementaryMask = false;
5290 for (VPReplicateRecipe *&RecipeJ : Recipes) {
5291 if (!RecipeJ)
5292 continue;
5293
5294 VPValue *MaskJ = RecipeJ->getMask();
5295 // Check if any operation in the group has a complementary mask with
5296 // another, that is M1 == NOT(M2) or M2 == NOT(M1).
5297 HasComplementaryMask |= match(MaskI, m_Not(m_Specific(MaskJ))) ||
5298 match(MaskJ, m_Not(m_Specific(MaskI)));
5299 Group.push_back(RecipeJ);
5300 RecipeJ = nullptr;
5301 }
5302
5303 if (HasComplementaryMask) {
5304 assert(Group.size() >= 2 && "must have at least 2 entries");
5305 AllGroups.push_back(std::move(Group));
5306 }
5307 }
5308 }
5309
5310 return AllGroups;
5311}
5312
5313// Find the recipe with minimum alignment in the group.
5314template <typename InstType>
5315static VPReplicateRecipe *
5317 return *min_element(Group, [](VPReplicateRecipe *A, VPReplicateRecipe *B) {
5318 return cast<InstType>(A->getUnderlyingInstr())->getAlign() <
5319 cast<InstType>(B->getUnderlyingInstr())->getAlign();
5320 });
5321}
5322
5325 const Loop *L) {
5326 auto Groups =
5328 if (Groups.empty())
5329 return;
5330
5331 // Process each group of loads.
5332 for (auto &Group : Groups) {
5333 // Try to use the earliest (most dominating) load to replace all others.
5334 VPReplicateRecipe *EarliestLoad = Group[0];
5335 VPBasicBlock *FirstBB = EarliestLoad->getParent();
5336 VPBasicBlock *LastBB = Group.back()->getParent();
5337
5338 // Check that the load doesn't alias with stores between first and last.
5339 auto LoadLoc = vputils::getMemoryLocation(*EarliestLoad);
5340 if (!LoadLoc || !canHoistOrSinkWithNoAliasCheck(*LoadLoc, FirstBB, LastBB))
5341 continue;
5342
5343 // Collect common metadata from all loads in the group.
5344 VPIRMetadata CommonMetadata = getCommonMetadata(Group);
5345
5346 // Find the load with minimum alignment to use.
5347 auto *LoadWithMinAlign = findRecipeWithMinAlign<LoadInst>(Group);
5348
5349 bool IsSingleScalar = EarliestLoad->isSingleScalar();
5350 assert(all_of(Group,
5351 [IsSingleScalar](VPReplicateRecipe *R) {
5352 return R->isSingleScalar() == IsSingleScalar;
5353 }) &&
5354 "all members in group must agree on IsSingleScalar");
5355
5356 // Create an unpredicated version of the earliest load with common
5357 // metadata.
5358 auto *UnpredicatedLoad = new VPReplicateRecipe(
5359 LoadWithMinAlign->getUnderlyingInstr(), {EarliestLoad->getOperand(0)},
5360 IsSingleScalar, /*Mask=*/nullptr, *EarliestLoad, CommonMetadata);
5361
5362 UnpredicatedLoad->insertBefore(EarliestLoad);
5363
5364 // Replace all loads in the group with the unpredicated load.
5365 for (VPReplicateRecipe *Load : Group) {
5366 Load->replaceAllUsesWith(UnpredicatedLoad);
5367 Load->eraseFromParent();
5368 }
5369 }
5370}
5371
5372static bool
5374 PredicatedScalarEvolution &PSE, const Loop &L) {
5375 auto StoreLoc = vputils::getMemoryLocation(*StoresToSink.front());
5376 if (!StoreLoc || !StoreLoc->AATags.Scope)
5377 return false;
5378
5379 // When sinking a group of stores, all members of the group alias each other.
5380 // Skip them during the alias checks.
5381 VPBasicBlock *FirstBB = StoresToSink.front()->getParent();
5382 VPBasicBlock *LastBB = StoresToSink.back()->getParent();
5383 SinkStoreInfo SinkInfo(StoresToSink, *StoresToSink[0], PSE, L);
5384 return canHoistOrSinkWithNoAliasCheck(*StoreLoc, FirstBB, LastBB, SinkInfo);
5385}
5386
5389 const Loop *L) {
5390 auto Groups =
5392 if (Groups.empty())
5393 return;
5394
5395 for (auto &Group : Groups) {
5396 if (!canSinkStoreWithNoAliasCheck(Group, PSE, *L))
5397 continue;
5398
5399 // Use the last (most dominated) store's location for the unconditional
5400 // store.
5401 VPReplicateRecipe *LastStore = Group.back();
5402 VPBasicBlock *InsertBB = LastStore->getParent();
5403
5404 // Collect common alias metadata from all stores in the group.
5405 VPIRMetadata CommonMetadata = getCommonMetadata(Group);
5406
5407 // Build select chain for stored values.
5408 VPValue *SelectedValue = Group[0]->getOperand(0);
5409 VPBuilder Builder(InsertBB, LastStore->getIterator());
5410
5411 bool IsSingleScalar = Group[0]->isSingleScalar();
5412 for (unsigned I = 1; I < Group.size(); ++I) {
5413 assert(IsSingleScalar == Group[I]->isSingleScalar() &&
5414 "all members in group must agree on IsSingleScalar");
5415 VPValue *Mask = Group[I]->getMask();
5416 VPValue *Value = Group[I]->getOperand(0);
5417 SelectedValue = Builder.createSelect(Mask, Value, SelectedValue,
5418 Group[I]->getDebugLoc());
5419 }
5420
5421 // Find the store with minimum alignment to use.
5422 auto *StoreWithMinAlign = findRecipeWithMinAlign<StoreInst>(Group);
5423
5424 // Create unconditional store with selected value and common metadata.
5425 auto *UnpredicatedStore = new VPReplicateRecipe(
5426 StoreWithMinAlign->getUnderlyingInstr(),
5427 {SelectedValue, LastStore->getOperand(1)}, IsSingleScalar,
5428 /*Mask=*/nullptr, *LastStore, CommonMetadata);
5429 UnpredicatedStore->insertBefore(*InsertBB, LastStore->getIterator());
5430
5431 // Remove all predicated stores from the group.
5432 for (VPReplicateRecipe *Store : Group)
5433 Store->eraseFromParent();
5434 }
5435}
5436
5438 VPlan &Plan, ElementCount BestVF, unsigned BestUF,
5440 assert(Plan.hasVF(BestVF) && "BestVF is not available in Plan");
5441 assert(Plan.hasUF(BestUF) && "BestUF is not available in Plan");
5442
5443 VPValue *TC = Plan.getTripCount();
5444 if (TC->user_empty())
5445 return;
5446
5447 // Skip cases for which the trip count may be non-trivial to materialize.
5448 // I.e., when a scalar tail is absent - due to tail folding, or when a scalar
5449 // tail is required.
5450 if (Plan.hasTailFolded() || !Plan.hasScalarTail() ||
5452 Plan.getScalarPreheader() ||
5453 !isa<VPIRValue>(TC))
5454 return;
5455
5456 // Materialize vector trip counts for constants early if it can simply
5457 // be computed as (Original TC / VF * UF) * VF * UF.
5458 // TODO: Compute vector trip counts for loops requiring a scalar epilogue and
5459 // tail-folded loops.
5460 ScalarEvolution &SE = *PSE.getSE();
5461 auto *TCScev = SE.getSCEV(TC->getLiveInIRValue());
5462 if (!isa<SCEVConstant>(TCScev))
5463 return;
5464 const SCEV *VFxUF = SE.getElementCount(TCScev->getType(), BestVF * BestUF);
5465 auto VecTCScev = SE.getMulExpr(SE.getUDivExpr(TCScev, VFxUF), VFxUF);
5466 if (auto *ConstVecTC = dyn_cast<SCEVConstant>(VecTCScev))
5467 Plan.getVectorTripCount().setUnderlyingValue(ConstVecTC->getValue());
5468}
5469
5471 VPBasicBlock *VectorPH) {
5473 if (BTC->user_empty())
5474 return;
5475
5476 VPBuilder Builder(VectorPH, VectorPH->begin());
5477 auto *TCTy = Plan.getTripCount()->getScalarType();
5478 auto *TCMO =
5479 Builder.createSub(Plan.getTripCount(), Plan.getConstantInt(TCTy, 1),
5480 DebugLoc::getCompilerGenerated(), "trip.count.minus.1");
5481 BTC->replaceAllUsesWith(TCMO);
5482}
5483
5485 if (Plan.hasScalarVFOnly())
5486 return;
5487
5488 VPRegionBlock *LoopRegion = Plan.getVectorLoopRegion();
5489 auto VPBBsOutsideLoopRegion = VPBlockUtils::blocksOnly<VPBasicBlock>(
5491 auto VPBBsInsideLoopRegion = VPBlockUtils::blocksOnly<VPBasicBlock>(
5492 vp_depth_first_shallow(LoopRegion->getEntry()));
5493 // Materialize Build(Struct)Vector for all replicating VPReplicateRecipes,
5494 // VPScalarIVStepsRecipe and VPInstructions, excluding ones in replicate
5495 // regions. Those are not materialized explicitly yet.
5496 // TODO: materialize build vectors for replicating recipes in replicating
5497 // regions.
5498 for (VPBasicBlock *VPBB :
5499 concat<VPBasicBlock *>(VPBBsOutsideLoopRegion, VPBBsInsideLoopRegion)) {
5500 for (VPRecipeBase &R : make_early_inc_range(*VPBB)) {
5502 continue;
5503 auto *DefR = cast<VPSingleDefRecipe>(&R);
5504 auto UsesVectorOrInsideReplicateRegion = [DefR, LoopRegion](VPUser *U) {
5505 VPRegionBlock *ParentRegion = cast<VPRecipeBase>(U)->getRegion();
5506 return !U->usesScalars(DefR) || ParentRegion != LoopRegion;
5507 };
5508 if ((isa<VPReplicateRecipe>(DefR) &&
5509 cast<VPReplicateRecipe>(DefR)->isSingleScalar()) ||
5510 (isa<VPInstruction>(DefR) &&
5512 !cast<VPInstruction>(DefR)->doesGeneratePerAllLanes())) ||
5513 none_of(DefR->users(), UsesVectorOrInsideReplicateRegion))
5514 continue;
5515
5516 Type *ScalarTy = DefR->getScalarType();
5517 unsigned Opcode = ScalarTy->isStructTy()
5520 auto *BuildVector = new VPInstruction(Opcode, {DefR});
5521 BuildVector->insertAfter(DefR);
5522
5523 DefR->replaceUsesWithIf(
5524 BuildVector, [BuildVector, &UsesVectorOrInsideReplicateRegion](
5525 VPUser &U, unsigned) {
5526 return &U != BuildVector && UsesVectorOrInsideReplicateRegion(&U);
5527 });
5528 }
5529 }
5530
5531 // Create explicit VPInstructions to convert vectors to scalars. The current
5532 // implementation is conservative - it may miss some cases that may or may not
5533 // be vector values. TODO: introduce Unpacks speculatively - remove them later
5534 // if they are known to operate on scalar values.
5535 for (VPBasicBlock *VPBB : VPBBsInsideLoopRegion) {
5536 for (VPRecipeBase &R : make_early_inc_range(*VPBB)) {
5538 VPDerivedIVRecipe>(&R))
5539 continue;
5540 for (VPValue *Def : R.definedValues()) {
5541 // Skip recipes that are single-scalar.
5542 // TODO: The Defs skipped here may or may not be vector values.
5543 // Introduce Unpacks, and remove them later, if they are guaranteed to
5544 // produce scalar values.
5545 if (vputils::isSingleScalar(Def))
5546 continue;
5547
5548 // Only introduce an Unpack if some, but not all, users use the first
5549 // lane only.
5550 unsigned NumFirstLaneUsers = count_if(Def->users(), [&Def](VPUser *U) {
5551 return U->usesFirstLaneOnly(Def);
5552 });
5553 if (!NumFirstLaneUsers || NumFirstLaneUsers == Def->getNumUsers())
5554 continue;
5555
5556 auto *Unpack = new VPInstruction(VPInstruction::Unpack, {Def});
5557 if (R.isPhi())
5558 Unpack->insertBefore(*VPBB, VPBB->getFirstNonPhi());
5559 else
5560 Unpack->insertAfter(&R);
5561 Def->replaceUsesWithIf(Unpack, [&Def](VPUser &U, unsigned) {
5562 return U.usesFirstLaneOnly(Def);
5563 });
5564 }
5565 }
5566 }
5567}
5568
5570 VPlan &Plan, VPBasicBlock *VectorPHVPBB, bool TailByMasking,
5571 bool RequiresScalarEpilogue, VPValue *Step,
5572 std::optional<uint64_t> MaxRuntimeStep) {
5573 VPSymbolicValue &VectorTC = Plan.getVectorTripCount();
5574 // There's nothing to do if there are no users of the vector trip count or its
5575 // IR value has already been set.
5576 if (VectorTC.user_empty() || VectorTC.getUnderlyingValue())
5577 return;
5578
5579 VPValue *TC = Plan.getTripCount();
5580 Type *TCTy = TC->getScalarType();
5581 VPBasicBlock::iterator InsertPt = VectorPHVPBB->begin();
5582 if (auto *StepR = Step->getDefiningRecipe()) {
5583 assert(VPDominatorTree(Plan).dominates(StepR->getParent(), VectorPHVPBB) &&
5584 "Step VPBB must dominate VectorPHVPBB");
5585 // Insert after Step's definition to maintain valid def-use ordering.
5586 InsertPt = std::next(StepR->getIterator());
5587 }
5588 VPBuilder Builder(VectorPHVPBB, InsertPt);
5589
5590 // For scalable steps, if TC is a constant and is divisible by the maximum
5591 // possible runtime step, then TC % Step == 0 for all valid vscale values
5592 // and the vector trip count equals TC directly.
5593 const APInt *TCVal;
5594 if (!RequiresScalarEpilogue && match(TC, m_APInt(TCVal)) && MaxRuntimeStep &&
5595 TCVal->urem(*MaxRuntimeStep) == 0) {
5596 VectorTC.replaceAllUsesWith(TC);
5597 return;
5598 }
5599
5600 // If the tail is to be folded by masking, round the number of iterations N
5601 // up to a multiple of Step instead of rounding down. This is done by first
5602 // adding Step-1 and then rounding down. Note that it's ok if this addition
5603 // overflows: the vector induction variable will eventually wrap to zero given
5604 // that it starts at zero and its Step is a power of two; the loop will then
5605 // exit, with the last early-exit vector comparison also producing all-true.
5606 if (TailByMasking) {
5607 TC = Builder.createAdd(
5608 TC, Builder.createSub(Step, Plan.getConstantInt(TCTy, 1)),
5609 DebugLoc::getCompilerGenerated(), "n.rnd.up");
5610 }
5611
5612 // Now we need to generate the expression for the part of the loop that the
5613 // vectorized body will execute. This is equal to N - (N % Step) if scalar
5614 // iterations are not required for correctness, or N - Step, otherwise. Step
5615 // is equal to the vectorization factor (number of SIMD elements) times the
5616 // unroll factor (number of SIMD instructions).
5617 VPValue *R =
5618 Builder.createNaryOp(Instruction::URem, {TC, Step},
5619 DebugLoc::getCompilerGenerated(), "n.mod.vf");
5620
5621 // There are cases where we *must* run at least one iteration in the remainder
5622 // loop. See the cost model for when this can happen. If the step evenly
5623 // divides the trip count, we set the remainder to be equal to the step. If
5624 // the step does not evenly divide the trip count, no adjustment is necessary
5625 // since there will already be scalar iterations. Note that the minimum
5626 // iterations check ensures that N >= Step.
5627 if (RequiresScalarEpilogue) {
5628 assert(!TailByMasking &&
5629 "requiring scalar epilogue is not supported with fail folding");
5630 VPValue *IsZero =
5631 Builder.createICmp(CmpInst::ICMP_EQ, R, Plan.getZero(TCTy));
5632 R = Builder.createSelect(IsZero, Step, R);
5633 }
5634
5635 VPValue *Res =
5636 Builder.createSub(TC, R, DebugLoc::getCompilerGenerated(), "n.vec");
5637 VectorTC.replaceAllUsesWith(Res);
5638}
5639
5641 ElementCount VFEC) {
5642 // If VF and VFxUF have already been materialized (no remaining users),
5643 // there's nothing more to do.
5644 if (Plan.getVF().isMaterialized()) {
5645 assert(Plan.getVFxUF().isMaterialized() &&
5646 "VF and VFxUF must be materialized together");
5647 return;
5648 }
5649
5650 VPBuilder Builder(VectorPH, VectorPH->begin());
5651 Type *TCTy = Plan.getTripCount()->getScalarType();
5652 VPValue &VF = Plan.getVF();
5653 VPValue &VFxUF = Plan.getVFxUF();
5654 // If there are no users of the runtime VF, compute VFxUF by constant folding
5655 // the multiplication of VF and UF.
5656 if (VF.user_empty()) {
5657 VPValue *RuntimeVFxUF =
5658 Builder.createElementCount(TCTy, VFEC * Plan.getConcreteUF());
5659 VFxUF.replaceAllUsesWith(RuntimeVFxUF);
5660 return;
5661 }
5662
5663 // For users of the runtime VF, compute it as VF * vscale, and VFxUF as (VF *
5664 // vscale) * UF.
5665 VPValue *RuntimeVF = Builder.createElementCount(TCTy, VFEC);
5667 VPValue *BC = Builder.createNaryOp(VPInstruction::Broadcast, RuntimeVF);
5669 BC, [&VF](VPUser &U, unsigned) { return !U.usesScalars(&VF); });
5670 }
5671 VF.replaceAllUsesWith(RuntimeVF);
5672
5673 VPValue *MulByUF = Builder.createOverflowingOp(
5674 Instruction::Mul,
5675 {RuntimeVF, Plan.getConstantInt(TCTy, Plan.getConcreteUF())},
5676 {true, false});
5677 VFxUF.replaceAllUsesWith(MulByUF);
5678}
5679
5681 VPRegionBlock *LoopRegion = Plan.getVectorLoopRegion();
5682 VPValue *HeaderMask = LoopRegion->getHeaderMask();
5683 Type *I1Ty = IntegerType::getInt1Ty(Plan.getContext());
5684
5685 VPBuilder Builder(Plan.getVectorPreheader());
5686 auto *AliasMask = Builder.createNaryOp(
5687 VPInstruction::IncomingAliasMask, {}, nullptr, {}, {},
5688 DebugLoc::getUnknown(), "incoming.alias.mask", I1Ty);
5689
5690 VPBasicBlock *Header = LoopRegion->getEntryBasicBlock();
5691 Builder = VPBuilder(Header, Header->getFirstNonPhi());
5692
5693 // Update all existing users of the header mask to "HeaderMask & AliasMask".
5694 auto *ClampedHeaderMask = Builder.createAnd(HeaderMask, AliasMask);
5695 HeaderMask->replaceUsesWithIf(ClampedHeaderMask, [&](VPUser &U, unsigned) {
5696 return &U != ClampedHeaderMask;
5697 });
5698}
5699
5700VPValue *
5702 ArrayRef<PointerDiffInfo> DiffChecks) {
5703 VPBuilder Builder(AliasCheckVPBB);
5704 Type *I1Ty = IntegerType::getInt1Ty(Plan.getContext());
5705
5706 VPValue *IncomingAliasMask = vputils::findIncomingAliasMask(Plan);
5707 assert(IncomingAliasMask && "Expected an alias mask!");
5708
5709 VPValue *AliasMask = nullptr;
5710 for (const PointerDiffInfo &Check : DiffChecks) {
5712 VPValue *Sink =
5714 Type *AddrType = Src->getScalarType();
5715
5716 // TODO: Only freeze the required pointer (not both src and sink).
5717 if (Check.NeedsFreeze) {
5718 Src = Builder.createScalarFreeze(Src, AddrType, DebugLoc::getUnknown());
5719 Sink = Builder.createScalarFreeze(Sink, AddrType, DebugLoc::getUnknown());
5720 }
5721
5722 // TODO: Generate loop_dependence_raw_mask when there's a read-after-write
5723 // dependency between the source and the sink. This is not necessary for
5724 // correctness of the mask, but using the "raw" variant prevents loads
5725 // depending on the completion of stores.
5726 VPWidenIntrinsicRecipe *WARMask = Builder.insert(new VPWidenIntrinsicRecipe(
5727 Intrinsic::loop_dependence_war_mask,
5728 {Src, Sink, Plan.getConstantInt(AddrType, Check.AccessSize)}, I1Ty));
5729
5730 if (AliasMask)
5731 AliasMask = Builder.createAnd(AliasMask, WARMask);
5732 else
5733 AliasMask = WARMask;
5734 }
5735
5737 Type *IndexTy = Plan.getDataLayout().getIndexType(Plan.getContext(), 0);
5738 VPValue *NumActive = Builder.createNaryOp(
5739 VPInstruction::NumActiveLanes, {AliasMask}, nullptr, {}, {},
5740 DebugLoc::getUnknown(), "num.active.lanes", IndexTy);
5741 VPValue *ClampedVF = Builder.createScalarZExtOrTrunc(
5742 NumActive, IVTy, IndexTy, DebugLoc::getCompilerGenerated());
5743
5744 IncomingAliasMask->replaceAllUsesWith(AliasMask);
5745
5746 return ClampedVF;
5747}
5748
5750 VPlan &Plan, ArrayRef<PointerDiffInfo> DiffChecks, bool HasBranchWeights) {
5751 VPBasicBlock *ClampedVFCheck =
5752 Plan.createVPBasicBlock("vector.clamped.vf.check");
5753
5754 VPValue *ClampedVF = materializeAliasMask(Plan, ClampedVFCheck, DiffChecks);
5755 VPBuilder Builder(ClampedVFCheck);
5757 Type *TCTy = Plan.getTripCount()->getScalarType();
5758
5759 // Check the "ClampedVF" from the alias mask is larger than one.
5760 VPValue *IsScalar =
5761 Builder.createICmp(CmpInst::ICMP_ULE, ClampedVF,
5762 Plan.getConstantInt(TCTy, 1), DL, "vf.is.scalar");
5763
5764 VPValue *TripCount = Plan.getTripCount();
5765 VPValue *MaxUIntTripCount =
5767 VPValue *DistanceToMax = Builder.createSub(MaxUIntTripCount, TripCount);
5768
5769 // For tail-folding: Don't execute the vector loop if (UMax - n) < ClampedVF.
5770 // Note: The ClampedVF may not be a power-of-two. This means the loop exit
5771 // condition (index.next == n.vec) may not be correct in the case of an
5772 // overflow. The issue is `n.vec` could be zero due to an overflow, but
5773 // index.next is not guaranteed to overflow to zero as the ClampedVF is not a
5774 // power-of-two).
5775 VPValue *TripCountCheck = Builder.createICmp(
5776 ICmpInst::ICMP_ULT, DistanceToMax, ClampedVF, DL, "vf.step.overflow");
5777
5778 VPValue *Cond = Builder.createOr(IsScalar, TripCountCheck, DL);
5779 attachVPCheckBlock(Plan, Cond, ClampedVFCheck, HasBranchWeights);
5780
5781 // Materialize the trip count early as this will add a use of (VFxUF) that
5782 // needs to be replaced with the ClampedVF.
5784 /*TailByMasking=*/true,
5785 /*RequiresScalarEpilogue=*/false,
5786 &Plan.getVFxUF());
5787
5788 assert(Plan.getConcreteUF() == 1 &&
5789 "Clamped VF not supported with interleaving");
5790 Plan.getVF().replaceAllUsesWith(ClampedVF);
5791 Plan.getVFxUF().replaceAllUsesWith(ClampedVF);
5792}
5793
5795 ScalarEvolution &SE) {
5796 auto *Entry = Plan.getEntry();
5797 VPBuilder Builder(Entry, Entry->begin());
5799 ->getIRBasicBlock()
5800 ->getTerminator()
5801 ->getDebugLoc();
5802 VPSCEVExpander Expander(Builder, SE, DL);
5803
5804 // Expand VPExpandSCEVRecipes to VPInstructions using VPSCEVExpander. During
5805 // the transition, unsupported VPExpandSCEVRecipes are skipped and left for
5806 // late expansion.
5807 for (VPRecipeBase &R : make_early_inc_range(*Entry)) {
5808 auto *ExpSCEV = dyn_cast<VPExpandSCEVRecipe>(&R);
5809 if (!ExpSCEV || ExpSCEV->user_empty())
5810 continue;
5811 Builder.setInsertPoint(ExpSCEV);
5812 VPValue *Expanded = Expander.tryToExpand(ExpSCEV->getSCEV());
5813 if (!Expanded)
5814 continue;
5815 ExpSCEV->replaceAllUsesWith(Expanded);
5816 // TripCount should not be used after expansion to VPInstructions. Reset to
5817 // poison to avoid dangling references.
5818 if (Plan.getTripCount() == ExpSCEV)
5819 Plan.resetTripCount(Plan.getPoison(ExpSCEV->getScalarType()));
5820 ExpSCEV->eraseFromParent();
5821 }
5822}
5823
5826 SCEVExpander Expander(SE, "induction", /*PreserveLCSSA=*/false);
5827
5828 auto *Entry = cast<VPIRBasicBlock>(Plan.getEntry());
5829 BasicBlock *EntryBB = Entry->getIRBasicBlock();
5830 DenseMap<const SCEV *, Value *> ExpandedSCEVs;
5831 // Expand remaining VPExpandSCEVRecipes to IR instructions using SCEVExpander.
5832 for (VPRecipeBase &R : make_early_inc_range(*Entry)) {
5833 auto *ExpSCEV = dyn_cast<VPExpandSCEVRecipe>(&R);
5834 if (!ExpSCEV)
5835 continue;
5836 const SCEV *Expr = ExpSCEV->getSCEV();
5837 Value *Res =
5838 Expander.expandCodeFor(Expr, Expr->getType(), EntryBB->getTerminator());
5839 ExpandedSCEVs[Expr] = Res;
5840 VPValue *Exp = Plan.getOrAddLiveIn(Res);
5841 ExpSCEV->replaceAllUsesWith(Exp);
5842 if (Plan.getTripCount() == ExpSCEV)
5843 Plan.resetTripCount(Exp);
5844 ExpSCEV->eraseFromParent();
5845 }
5847 "all VPExpandSCEVRecipes must have been expanded");
5848 // Add IR instructions in the entry basic block but not in the VPIRBasicBlock
5849 // to the VPIRBasicBlock.
5850 auto EI = Entry->begin();
5851 for (Instruction &I : drop_end(*EntryBB)) {
5852 if (EI != Entry->end() && isa<VPIRInstruction>(*EI) &&
5853 &cast<VPIRInstruction>(&*EI)->getInstruction() == &I) {
5854 EI++;
5855 continue;
5856 }
5858 }
5859
5860 return ExpandedSCEVs;
5861}
5862
5863/// Returns true if \p V is VPWidenLoadRecipe or VPInterleaveRecipe that can be
5864/// converted to a narrower recipe. \p V is used by a wide recipe that feeds a
5865/// store interleave group at index \p Idx, \p WideMember0 is the recipe feeding
5866/// the same interleave group at index 0. A VPWidenLoadRecipe can be narrowed to
5867/// an index-independent load if it feeds all wide ops at all indices (\p OpV
5868/// must be the operand at index \p OpIdx for both the recipe at lane 0, \p
5869/// WideMember0). A VPInterleaveRecipe can be narrowed to a wide load, if \p V
5870/// is defined at \p Idx of a load interleave group.
5871/// A live-in or recipe defined outside the loop region can be converted, if it
5872/// is the same across all lanes, or we can create a BuildVector for it.
5873static bool canNarrowLoad(VPSingleDefRecipe *WideMember0, unsigned OpIdx,
5874 VPValue *OpV, unsigned Idx, bool IsScalable) {
5875 VPValue *Member0Op = WideMember0->getOperand(OpIdx);
5876 if (Member0Op->isDefinedOutsideLoopRegions()) {
5877 // Operand matches Member0, broadcast across all fields for both live-ins
5878 // and recipes.
5879 if (Member0Op == OpV)
5880 return true;
5881 // Otherwise distinct per-field VPValues are assembled into a BuildVector.
5882 return !IsScalable && OpV->isDefinedOutsideLoopRegions() &&
5883 OpV->getScalarType() == Member0Op->getScalarType();
5884 }
5885 VPRecipeBase *Member0OpR = Member0Op->getDefiningRecipe();
5886 if (auto *W = dyn_cast<VPWidenLoadRecipe>(Member0OpR))
5887 // For scalable VFs, the narrowed plan processes vscale iterations at once,
5888 // so a shared wide load cannot be narrowed to a uniform scalar; bail out.
5889 return !IsScalable && !W->getMask() && W->isConsecutive() &&
5890 Member0Op == OpV;
5891 if (auto *IR = dyn_cast<VPInterleaveRecipe>(Member0OpR))
5892 return IR->getInterleaveGroup()->isFull() && IR->getVPValue(Idx) == OpV;
5893 return false;
5894}
5895
5896static bool canNarrowOps(ArrayRef<VPValue *> Ops, bool IsScalable) {
5898 auto *WideMember0 = dyn_cast<VPRecipeWithIRFlags>(Ops[0]);
5899 if (!WideMember0)
5900 return false;
5901 for (VPValue *V : Ops) {
5903 return false;
5904 auto *R = cast<VPRecipeWithIRFlags>(V);
5905 if (getOpcodeOrIntrinsicID(R) != getOpcodeOrIntrinsicID(WideMember0))
5906 return false;
5907 if (R->getScalarType() != WideMember0->getScalarType())
5908 return false;
5909 if (R->hasPredicate() && R->getPredicate() != WideMember0->getPredicate())
5910 return false;
5911 }
5912
5913 for (unsigned Idx = 0; Idx != WideMember0->getNumOperands(); ++Idx) {
5915 for (VPValue *Op : Ops)
5916 OpsI.push_back(Op->getDefiningRecipe()->getOperand(Idx));
5917
5918 if (canNarrowOps(OpsI, IsScalable))
5919 continue;
5920
5921 if (any_of(enumerate(OpsI), [WideMember0, Idx, IsScalable](const auto &P) {
5922 const auto &[OpIdx, OpV] = P;
5923 return !canNarrowLoad(WideMember0, Idx, OpV, OpIdx, IsScalable);
5924 }))
5925 return false;
5926 }
5927
5928 return true;
5929}
5930
5931/// Returns VF from \p VFs if \p IR is a full interleave group with factor and
5932/// number of members both equal to VF. The interleave group must also access
5933/// the full vector width.
5934static std::optional<ElementCount>
5937 const TargetTransformInfo &TTI) {
5938 if (!InterleaveR || InterleaveR->getMask())
5939 return std::nullopt;
5940
5941 Type *GroupElementTy = nullptr;
5942 if (InterleaveR->getStoredValues().empty()) {
5943 GroupElementTy = InterleaveR->getVPValue(0)->getScalarType();
5944 if (!all_of(InterleaveR->definedValues(), [GroupElementTy](VPValue *Op) {
5945 return Op->getScalarType() == GroupElementTy;
5946 }))
5947 return std::nullopt;
5948 } else {
5949 GroupElementTy = InterleaveR->getStoredValues()[0]->getScalarType();
5950 if (!all_of(InterleaveR->getStoredValues(), [GroupElementTy](VPValue *Op) {
5951 return Op->getScalarType() == GroupElementTy;
5952 }))
5953 return std::nullopt;
5954 }
5955
5956 auto IG = InterleaveR->getInterleaveGroup();
5957 if (IG->getFactor() != IG->getNumMembers())
5958 return std::nullopt;
5959
5960 auto GetVectorBitWidthForVF = [&TTI](ElementCount VF) {
5961 TypeSize Size = TTI.getRegisterBitWidth(
5964 assert(Size.isScalable() == VF.isScalable() &&
5965 "if Size is scalable, VF must be scalable and vice versa");
5966 return Size.getKnownMinValue();
5967 };
5968
5969 for (ElementCount VF : VFs) {
5970 unsigned MinVal = VF.getKnownMinValue();
5971 unsigned GroupSize = GroupElementTy->getScalarSizeInBits() * MinVal;
5972 if (IG->getFactor() == MinVal && GroupSize == GetVectorBitWidthForVF(VF))
5973 return {VF};
5974 }
5975 return std::nullopt;
5976}
5977
5978/// Returns true if \p VPValue is a narrow VPValue.
5979static bool isAlreadyNarrow(VPValue *VPV) {
5980 if (isa<VPIRValue>(VPV))
5981 return true;
5982 auto *RepR = dyn_cast<VPReplicateRecipe>(VPV);
5983 return RepR && RepR->isSingleScalar();
5984}
5985
5986// Convert the wide recipes defining the VPValues in \p Members feeding an
5987// interleave group to a single narrow variant. The first member is reused as
5988// the narrowed recipe. BuildVectors for live-in operands are inserted into \p
5989// Preheader.
5991 SmallPtrSetImpl<VPValue *> &NarrowedOps,
5992 VPBasicBlock *Preheader) {
5993 VPValue *V = Members.front();
5994 if (NarrowedOps.contains(V))
5995 return V;
5996
5997 if (V->isDefinedOutsideLoopRegions()) {
5998 assert(all_of(Members,
5999 [V](VPValue *M) {
6000 return M->isDefinedOutsideLoopRegions() &&
6001 M->getScalarType() == V->getScalarType();
6002 }) &&
6003 "expected distinct loop-invariant values of matching scalar type");
6004 auto *BV = new VPInstruction(VPInstruction::BuildVector, Members);
6005 Preheader->appendRecipe(BV);
6006 NarrowedOps.insert(BV);
6007 return BV;
6008 }
6009
6010 if (isAlreadyNarrow(V))
6011 return V;
6012
6013 VPRecipeBase *R = V->getDefiningRecipe();
6015 auto *WideMember0 = cast<VPRecipeWithIRFlags>(R);
6016 for (VPValue *Member : Members.drop_front())
6017 WideMember0->intersectFlags(*cast<VPRecipeWithIRFlags>(Member));
6018 for (unsigned Idx = 0, E = WideMember0->getNumOperands(); Idx != E; ++Idx) {
6020 for (VPValue *Member : Members)
6021 OpsI.push_back(Member->getDefiningRecipe()->getOperand(Idx));
6022 WideMember0->setOperand(
6023 Idx, narrowInterleaveGroupOp(OpsI, NarrowedOps, Preheader));
6024 }
6025 return V;
6026 }
6027
6028 if (auto *LoadGroup = dyn_cast<VPInterleaveRecipe>(R)) {
6029 // Narrow interleave group to wide load, as transformed VPlan will only
6030 // process one original iteration.
6031 auto *LI = cast<LoadInst>(LoadGroup->getInterleaveGroup()->getInsertPos());
6032 auto *L = new VPWidenLoadRecipe(*LI, LoadGroup->getAddr(),
6033 LoadGroup->getMask(), /*Consecutive=*/true,
6034 *LoadGroup, LoadGroup->getDebugLoc());
6035 L->insertBefore(LoadGroup);
6036 NarrowedOps.insert(L);
6037 return L;
6038 }
6039
6040 if (auto *RepR = dyn_cast<VPReplicateRecipe>(R)) {
6041 assert(RepR->isSingleScalar() && RepR->getOpcode() == Instruction::Load &&
6042 "must be a single scalar load");
6043 NarrowedOps.insert(RepR);
6044 return RepR;
6045 }
6046
6047 auto *WideLoad = cast<VPWidenLoadRecipe>(R);
6048 VPValue *PtrOp = WideLoad->getAddr();
6049 if (auto *VecPtr = dyn_cast<VPVectorPointerRecipe>(PtrOp))
6050 PtrOp = VecPtr->getOperand(0);
6051 // Narrow wide load to uniform scalar load, as transformed VPlan will only
6052 // process one original iteration.
6053 auto *N = new VPReplicateRecipe(&WideLoad->getIngredient(), {PtrOp},
6054 /*IsUniform*/ true,
6055 /*Mask*/ nullptr, {}, *WideLoad);
6056 N->insertBefore(WideLoad);
6057 NarrowedOps.insert(N);
6058 return N;
6059}
6060
6061std::unique_ptr<VPlan>
6063 const TargetTransformInfo &TTI) {
6064 VPRegionBlock *VectorLoop = Plan.getVectorLoopRegion();
6065
6066 if (!VectorLoop)
6067 return nullptr;
6068
6069 // Only handle single-block loops for now.
6070 if (VectorLoop->getEntryBasicBlock() != VectorLoop->getExitingBasicBlock())
6071 return nullptr;
6072
6073 // Skip plans when we may not be able to properly narrow.
6074 VPBasicBlock *Exiting = VectorLoop->getExitingBasicBlock();
6075 if (!match(&Exiting->back(), m_BranchOnCount()))
6076 return nullptr;
6077
6078 assert(match(&Exiting->back(),
6080 m_Specific(&Plan.getVectorTripCount()))) &&
6081 "unexpected branch-on-count");
6082
6084 std::optional<ElementCount> VFToOptimize;
6085 for (auto &R : *VectorLoop->getEntryBasicBlock()) {
6088 continue;
6089
6090 // Bail out on recipes not supported at the moment:
6091 // * phi recipes other than the canonical induction
6092 // * recipes writing to memory except interleave groups
6093 // Only support plans with a canonical induction phi.
6094 if (R.isPhi())
6095 return nullptr;
6096
6097 auto *InterleaveR = dyn_cast<VPInterleaveRecipe>(&R);
6098 if (R.mayWriteToMemory() && !InterleaveR)
6099 return nullptr;
6100
6101 // Bail out if any recipe defines a vector value used outside the
6102 // vector loop region.
6103 if (any_of(R.definedValues(), [&](VPValue *V) {
6104 return any_of(V->users(), [&](VPUser *U) {
6105 auto *UR = cast<VPRecipeBase>(U);
6106 return UR->getParent()->getParent() != VectorLoop;
6107 });
6108 }))
6109 return nullptr;
6110
6111 // All other ops are allowed, but we reject uses that cannot be converted
6112 // when checking all allowed consumers (store interleave groups) below.
6113 if (!InterleaveR)
6114 continue;
6115
6116 // Try to find a single VF, where all interleave groups are consecutive and
6117 // saturate the full vector width. If we already have a candidate VF, check
6118 // if it is applicable for the current InterleaveR, otherwise look for a
6119 // suitable VF across the Plan's VFs.
6121 VFToOptimize ? SmallVector<ElementCount>({*VFToOptimize})
6122 : to_vector(Plan.vectorFactors());
6123 std::optional<ElementCount> NarrowedVF =
6124 isConsecutiveInterleaveGroup(InterleaveR, VFs, TTI);
6125 if (!NarrowedVF || (VFToOptimize && NarrowedVF != VFToOptimize))
6126 return nullptr;
6127 VFToOptimize = NarrowedVF;
6128
6129 // Skip read interleave groups.
6130 if (InterleaveR->getStoredValues().empty())
6131 continue;
6132
6133 // Narrow interleave groups, if all operands are already matching narrow
6134 // ops.
6135 auto *Member0 = InterleaveR->getStoredValues()[0];
6136 if (isAlreadyNarrow(Member0) &&
6137 all_of(InterleaveR->getStoredValues(), equal_to(Member0))) {
6138 StoreGroups.push_back(InterleaveR);
6139 continue;
6140 }
6141
6142 // For now, we only support full interleave groups storing load interleave
6143 // groups.
6144 if (all_of(enumerate(InterleaveR->getStoredValues()), [](auto Op) {
6145 VPRecipeBase *DefR = Op.value()->getDefiningRecipe();
6146 if (!DefR)
6147 return false;
6148 auto *IR = dyn_cast<VPInterleaveRecipe>(DefR);
6149 return IR && IR->getInterleaveGroup()->isFull() &&
6150 IR->getVPValue(Op.index()) == Op.value();
6151 })) {
6152 StoreGroups.push_back(InterleaveR);
6153 continue;
6154 }
6155
6156 // Check if all values feeding InterleaveR are matching wide recipes, which
6157 // operands that can be narrowed.
6158 if (!canNarrowOps(InterleaveR->getStoredValues(),
6159 VFToOptimize->isScalable()))
6160 return nullptr;
6161 StoreGroups.push_back(InterleaveR);
6162 }
6163
6164 if (StoreGroups.empty())
6165 return nullptr;
6166
6167 VPBasicBlock *MiddleVPBB = Plan.getMiddleBlock();
6168 bool RequiresScalarEpilogue =
6169 MiddleVPBB->getNumSuccessors() == 1 &&
6170 MiddleVPBB->getSingleSuccessor() == Plan.getScalarPreheader();
6171 // Bail out for tail-folding (middle block with a single successor to exit).
6172 if (MiddleVPBB->getNumSuccessors() != 2 && !RequiresScalarEpilogue)
6173 return nullptr;
6174
6175 // All interleave groups in Plan can be narrowed for VFToOptimize. Split the
6176 // original Plan into 2: a) a new clone which contains all VFs of Plan, except
6177 // VFToOptimize, and b) the original Plan with VFToOptimize as single VF.
6178 // TODO: Handle cases where only some interleave groups can be narrowed.
6179 std::unique_ptr<VPlan> NewPlan;
6180 if (size(Plan.vectorFactors()) != 1) {
6181 NewPlan = std::unique_ptr<VPlan>(Plan.duplicate());
6182 Plan.setVF(*VFToOptimize);
6183 NewPlan->removeVF(*VFToOptimize);
6184 }
6185
6186 // Convert InterleaveGroup \p R to a single VPWidenLoadRecipe.
6187 SmallPtrSet<VPValue *, 4> NarrowedOps;
6188 VPBasicBlock *Preheader = Plan.getVectorPreheader();
6189 // Narrow operation tree rooted at store groups.
6190 for (auto *StoreGroup : StoreGroups) {
6191 VPValue *Res = narrowInterleaveGroupOp(StoreGroup->getStoredValues(),
6192 NarrowedOps, Preheader);
6193 auto *SI =
6194 cast<StoreInst>(StoreGroup->getInterleaveGroup()->getInsertPos());
6195 auto *S = new VPWidenStoreRecipe(*SI, StoreGroup->getAddr(), Res, nullptr,
6196 /*Consecutive=*/true, *StoreGroup,
6197 StoreGroup->getDebugLoc());
6198 S->insertBefore(StoreGroup);
6199 StoreGroup->eraseFromParent();
6200 }
6201
6202 // Adjust induction to reflect that the transformed plan only processes one
6203 // original iteration.
6205 Type *CanIVTy = VectorLoop->getCanonicalIVType();
6206 VPBasicBlock *VectorPH = Plan.getVectorPreheader();
6207 VPBuilder PHBuilder(VectorPH, VectorPH->begin());
6208
6209 VPValue *UF = &Plan.getUF();
6210 VPValue *Step;
6211 if (VFToOptimize->isScalable()) {
6212 VPValue *VScale =
6213 PHBuilder.createElementCount(CanIVTy, ElementCount::getScalable(1));
6214 Step = PHBuilder.createOverflowingOp(Instruction::Mul, {VScale, UF},
6215 {true, false});
6216 Plan.getVF().replaceAllUsesWith(VScale);
6217 } else {
6218 Step = UF;
6219 Plan.getVF().replaceAllUsesWith(Plan.getConstantInt(CanIVTy, 1));
6220 }
6221 // Materialize vector trip count with the narrowed step.
6222 materializeVectorTripCount(Plan, VectorPH, /*TailByMasking=*/false,
6223 RequiresScalarEpilogue, Step);
6224
6225 CanIVInc->setOperand(1, Step);
6226 Plan.getVFxUF().replaceAllUsesWith(Step);
6227
6228 removeDeadRecipes(Plan);
6229 assert(none_of(*VectorLoop->getEntryBasicBlock(),
6231 "All VPVectorPointerRecipes should have been removed");
6232 return NewPlan;
6233}
6234
6235/// Add branch weight metadata, if the \p Plan's middle block is terminated by a
6236/// BranchOnCond recipe.
6238 VPlan &Plan, ElementCount VF, std::optional<unsigned> VScaleForTuning) {
6239 VPBasicBlock *MiddleVPBB = Plan.getMiddleBlock();
6240 auto *MiddleTerm =
6242 // Only add branch metadata if there is a (conditional) terminator.
6243 if (!MiddleTerm)
6244 return;
6245
6246 assert(MiddleTerm->getOpcode() == VPInstruction::BranchOnCond &&
6247 "must have a BranchOnCond");
6248 // Assume that `TripCount % VectorStep ` is equally distributed.
6249 unsigned VectorStep = Plan.getConcreteUF() * VF.getKnownMinValue();
6250 if (VF.isScalable() && VScaleForTuning.has_value())
6251 VectorStep *= *VScaleForTuning;
6252 assert(VectorStep > 0 && "trip count should not be zero");
6253 MDBuilder MDB(Plan.getContext());
6254 MDNode *BranchWeights =
6255 MDB.createBranchWeights({1, VectorStep - 1}, /*IsExpected=*/false);
6256 MiddleTerm->setMetadata(LLVMContext::MD_prof, BranchWeights);
6257}
6258
6260 VFRange &Range) {
6261 VPRegionBlock *VectorRegion = Plan.getVectorLoopRegion();
6262 auto *MiddleVPBB = Plan.getMiddleBlock();
6263 VPBuilder MiddleBuilder(MiddleVPBB, MiddleVPBB->getFirstNonPhi());
6264
6265 auto IsScalableOne = [](ElementCount VF) -> bool {
6266 return VF == ElementCount::getScalable(1);
6267 };
6268
6269 for (auto &HeaderPhi : VectorRegion->getEntryBasicBlock()->phis()) {
6270 auto *FOR = dyn_cast<VPFirstOrderRecurrencePHIRecipe>(&HeaderPhi);
6271 if (!FOR)
6272 continue;
6273
6274 assert(VectorRegion->getSingleSuccessor() == Plan.getMiddleBlock() &&
6275 "Cannot handle loops with uncountable early exits");
6276
6277 // Find the existing splice for this FOR, created in
6278 // createHeaderPhiRecipes. All uses of FOR have already been replaced with
6279 // RecurSplice there; only RecurSplice itself still references FOR.
6280 auto *RecurSplice =
6282 assert(RecurSplice && "expected FirstOrderRecurrenceSplice");
6283
6284 // For VF vscale x 1, if vscale = 1, we are unable to extract the
6285 // penultimate value of the recurrence. Instead we rely on the existing
6286 // extract of the last element from the result of
6287 // VPInstruction::FirstOrderRecurrenceSplice.
6288 // TODO: Consider vscale_range info and UF.
6289 if (any_of(RecurSplice->users(),
6290 [](VPUser *U) { return !cast<VPRecipeBase>(U)->getRegion(); }) &&
6292 Range))
6293 return;
6294
6295 // This is the second phase of vectorizing first-order recurrences, creating
6296 // extracts for users outside the loop. An overview of the transformation is
6297 // described below. Suppose we have the following loop with some use after
6298 // the loop of the last a[i-1],
6299 //
6300 // for (int i = 0; i < n; ++i) {
6301 // t = a[i - 1];
6302 // b[i] = a[i] - t;
6303 // }
6304 // use t;
6305 //
6306 // There is a first-order recurrence on "a". For this loop, the shorthand
6307 // scalar IR looks like:
6308 //
6309 // scalar.ph:
6310 // s.init = a[-1]
6311 // br scalar.body
6312 //
6313 // scalar.body:
6314 // i = phi [0, scalar.ph], [i+1, scalar.body]
6315 // s1 = phi [s.init, scalar.ph], [s2, scalar.body]
6316 // s2 = a[i]
6317 // b[i] = s2 - s1
6318 // br cond, scalar.body, exit.block
6319 //
6320 // exit.block:
6321 // use = lcssa.phi [s1, scalar.body]
6322 //
6323 // In this example, s1 is a recurrence because it's value depends on the
6324 // previous iteration. In the first phase of vectorization, we created a
6325 // VPFirstOrderRecurrencePHIRecipe v1 for s1. Now we create the extracts
6326 // for users in the scalar preheader and exit block.
6327 //
6328 // vector.ph:
6329 // v_init = vector(..., ..., ..., a[-1])
6330 // br vector.body
6331 //
6332 // vector.body
6333 // i = phi [0, vector.ph], [i+4, vector.body]
6334 // v1 = phi [v_init, vector.ph], [v2, vector.body]
6335 // v2 = a[i, i+1, i+2, i+3]
6336 // v1' = splice(v1(3), v2(0, 1, 2))
6337 // b[i, i+1, i+2, i+3] = v2 - v1'
6338 // br cond, vector.body, middle.block
6339 //
6340 // middle.block:
6341 // vector.recur.extract.for.phi = v2(2)
6342 // vector.recur.extract = v2(3)
6343 // br cond, scalar.ph, exit.block
6344 //
6345 // scalar.ph:
6346 // scalar.recur.init = phi [vector.recur.extract, middle.block],
6347 // [s.init, otherwise]
6348 // br scalar.body
6349 //
6350 // scalar.body:
6351 // i = phi [0, scalar.ph], [i+1, scalar.body]
6352 // s1 = phi [scalar.recur.init, scalar.ph], [s2, scalar.body]
6353 // s2 = a[i]
6354 // b[i] = s2 - s1
6355 // br cond, scalar.body, exit.block
6356 //
6357 // exit.block:
6358 // lo = lcssa.phi [s1, scalar.body],
6359 // [vector.recur.extract.for.phi, middle.block]
6360 //
6361 // Update extracts of the splice in the middle block: they extract the
6362 // penultimate element of the recurrence.
6364 make_range(MiddleVPBB->getFirstNonPhi(), MiddleVPBB->end()))) {
6365 if (!match(&R, m_ExtractLastLaneOfLastPart(m_Specific(RecurSplice))))
6366 continue;
6367
6368 auto *ExtractR = cast<VPInstruction>(&R);
6369 VPValue *PenultimateElement = MiddleBuilder.createNaryOp(
6370 VPInstruction::ExtractPenultimateElement, RecurSplice->getOperand(1),
6371 {}, "vector.recur.extract.for.phi");
6372 for (VPUser *ExitU : to_vector(ExtractR->users())) {
6373 if (auto *ExitPhi = dyn_cast<VPIRPhi>(ExitU))
6374 ExitPhi->replaceUsesOfWith(ExtractR, PenultimateElement);
6375 }
6376 }
6377 }
6378}
6379
6380/// Check if \p V is a binary expression of a widened IV and a loop-invariant
6381/// value. Returns the widened IV if found, nullptr otherwise.
6383 auto *BinOp = dyn_cast<VPWidenRecipe>(V);
6384 if (!BinOp || !Instruction::isBinaryOp(BinOp->getOpcode()) ||
6385 Instruction::isIntDivRem(BinOp->getOpcode()))
6386 return nullptr;
6387
6388 VPValue *WidenIVCandidate = BinOp->getOperand(0);
6389 VPValue *InvariantCandidate = BinOp->getOperand(1);
6390 if (!isa<VPWidenIntOrFpInductionRecipe>(WidenIVCandidate))
6391 std::swap(WidenIVCandidate, InvariantCandidate);
6392
6393 if (!InvariantCandidate->isDefinedOutsideLoopRegions())
6394 return nullptr;
6395
6396 return dyn_cast<VPWidenIntOrFpInductionRecipe>(WidenIVCandidate);
6397}
6398
6399/// Create a scalar version of \p BinOp, with its \p WidenIV operand replaced
6400/// by \p ScalarIV, and place it after \p ScalarIV's defining recipe.
6404 BinOp->getNumOperands() == 2 && "BinOp must have 2 operands");
6405 auto *ClonedOp = BinOp->clone();
6406 if (ClonedOp->getOperand(0) == WidenIV) {
6407 ClonedOp->setOperand(0, ScalarIV);
6408 } else {
6409 assert(ClonedOp->getOperand(1) == WidenIV && "one operand must be WideIV");
6410 ClonedOp->setOperand(1, ScalarIV);
6411 }
6412 ClonedOp->insertAfter(ScalarIV->getDefiningRecipe());
6413 return ClonedOp;
6414}
6415
6418 Loop &L) {
6419 ScalarEvolution &SE = *PSE.getSE();
6420 VPRegionBlock *VectorLoopRegion = Plan.getVectorLoopRegion();
6421
6422 // Helper lambda to check if the IV range excludes the sentinel value. Try
6423 // signed first, then unsigned. Return an excluded sentinel if found,
6424 // otherwise return std::nullopt.
6425 auto CheckSentinel = [&SE](const SCEV *IVSCEV,
6426 bool UseMax) -> std::optional<APSInt> {
6427 unsigned BW = IVSCEV->getType()->getScalarSizeInBits();
6428 for (bool Signed : {true, false}) {
6429 APSInt Sentinel = UseMax ? APSInt::getMinValue(BW, /*Unsigned=*/!Signed)
6430 : APSInt::getMaxValue(BW, /*Unsigned=*/!Signed);
6431
6432 ConstantRange IVRange =
6433 Signed ? SE.getSignedRange(IVSCEV) : SE.getUnsignedRange(IVSCEV);
6434 if (!IVRange.contains(Sentinel))
6435 return Sentinel;
6436 }
6437 return std::nullopt;
6438 };
6439
6440 VPValue *HeaderMask = VectorLoopRegion->getHeaderMask();
6441 for (VPRecipeBase &Phi :
6442 make_early_inc_range(VectorLoopRegion->getEntryBasicBlock()->phis())) {
6443 auto *PhiR = dyn_cast<VPReductionPHIRecipe>(&Phi);
6445 PhiR->getRecurrenceKind()))
6446 continue;
6447
6448 Type *PhiTy = PhiR->getScalarType();
6449 if (PhiTy->isPointerTy() || PhiTy->isFloatingPointTy())
6450 continue;
6451
6452 // If there's a header mask, the backedge select will not be the find-last
6453 // select.
6454 VPValue *BackedgeVal = PhiR->getBackedgeValue();
6455 auto *FindLastSelect = cast<VPSingleDefRecipe>(BackedgeVal);
6456 if (HeaderMask &&
6457 !match(BackedgeVal,
6458 m_Select(m_Specific(HeaderMask),
6459 m_VPSingleDefRecipe(FindLastSelect), m_Specific(PhiR))))
6460 continue;
6461
6462 // Get the find-last expression from the find-last select of the reduction
6463 // phi. The find-last select should be a select between the phi and the
6464 // find-last expression.
6465 VPValue *Cond, *FindLastExpression;
6466 if (!match(FindLastSelect, m_SelectLike(m_VPValue(Cond), m_Specific(PhiR),
6467 m_VPValue(FindLastExpression))) &&
6468 !match(FindLastSelect,
6469 m_SelectLike(m_VPValue(Cond), m_VPValue(FindLastExpression),
6470 m_Specific(PhiR))))
6471 continue;
6472
6473 // Check if FindLastExpression is a simple expression of a widened IV. If
6474 // so, we can track the underlying IV instead and sink the expression.
6475 auto *IVOfExpressionToSink = getExpressionIV(FindLastExpression);
6476 const SCEV *IVSCEV = vputils::getSCEVExprForVPValue(
6477 IVOfExpressionToSink ? IVOfExpressionToSink : FindLastExpression, PSE,
6478 &L);
6479 const SCEV *Step;
6480 if (!match(IVSCEV, m_scev_AffineAddRec(m_SCEV(), m_SCEV(Step)))) {
6481 assert(!match(vputils::getSCEVExprForVPValue(FindLastExpression, PSE, &L),
6483 "IVOfExpressionToSink not being an AddRec must imply "
6484 "FindLastExpression not being an AddRec.");
6485 continue;
6486 }
6487
6488 // Determine direction from SCEV step.
6489 if (!SE.isKnownNonZero(Step))
6490 continue;
6491
6492 // Positive step means we need UMax/SMax to find the last IV value, and
6493 // UMin/SMin otherwise.
6494 bool UseMax = SE.isKnownPositive(Step);
6495 std::optional<APSInt> SentinelVal = CheckSentinel(IVSCEV, UseMax);
6496 bool UseSigned = SentinelVal && SentinelVal->isSigned();
6497
6498 // Sinking an expression will disable epilogue vectorization. Only use it,
6499 // if FindLastExpression cannot be vectorized via a sentinel. Sinking may
6500 // also prevent vectorizing using a sentinel (e.g., if the expression is a
6501 // multiply or divide by large constant, respectively), which also makes
6502 // sinking undesirable.
6503 if (IVOfExpressionToSink) {
6504 const SCEV *FindLastExpressionSCEV =
6505 vputils::getSCEVExprForVPValue(FindLastExpression, PSE, &L);
6506 if (match(FindLastExpressionSCEV,
6507 m_scev_AffineAddRec(m_SCEV(), m_SCEV(Step)))) {
6508 bool NewUseMax = SE.isKnownPositive(Step);
6509 if (auto NewSentinel =
6510 CheckSentinel(FindLastExpressionSCEV, NewUseMax)) {
6511 // The original expression already has a sentinel, so prefer not
6512 // sinking to keep epilogue vectorization possible.
6513 SentinelVal = *NewSentinel;
6514 UseSigned = NewSentinel->isSigned();
6515 UseMax = NewUseMax;
6516 IVSCEV = FindLastExpressionSCEV;
6517 IVOfExpressionToSink = nullptr;
6518 }
6519 }
6520 }
6521
6522 // If no sentinel was found, fall back to a boolean AnyOf reduction to track
6523 // if the condition was ever true. Requires the IV to not wrap, otherwise we
6524 // cannot use min/max.
6525 if (!SentinelVal) {
6526 auto *AR = cast<SCEVAddRecExpr>(IVSCEV);
6527 if (AR->hasNoSignedWrap())
6528 UseSigned = true;
6529 else if (AR->hasNoUnsignedWrap())
6530 UseSigned = false;
6531 else
6532 continue;
6533 }
6534
6536 BackedgeVal,
6538
6539 VPValue *NewFindLastSelect = BackedgeVal;
6540 VPValue *SelectCond = Cond;
6541 if (!SentinelVal || IVOfExpressionToSink) {
6542 // When we need to create a new select, normalize the condition so that
6543 // PhiR is the last operand and include the header mask if needed.
6544 DebugLoc DL = FindLastSelect->getDefiningRecipe()->getDebugLoc();
6545 VPBuilder LoopBuilder(FindLastSelect->getDefiningRecipe());
6546 if (FindLastSelect->getDefiningRecipe()->getOperand(1) == PhiR)
6547 SelectCond = LoopBuilder.createNot(SelectCond);
6548
6549 // When tail folding, mask the condition with the header mask to prevent
6550 // propagating poison from inactive lanes in the last vector iteration.
6551 if (HeaderMask)
6552 SelectCond = LoopBuilder.createLogicalAnd(HeaderMask, SelectCond);
6553
6554 if (SelectCond != Cond || IVOfExpressionToSink) {
6555 NewFindLastSelect = LoopBuilder.createSelect(
6556 SelectCond,
6557 IVOfExpressionToSink ? IVOfExpressionToSink : FindLastExpression,
6558 PhiR, DL);
6559 }
6560 }
6561
6562 // Create the reduction result in the middle block using sentinel directly.
6563 RecurKind MinMaxKind =
6564 UseMax ? (UseSigned ? RecurKind::SMax : RecurKind::UMax)
6565 : (UseSigned ? RecurKind::SMin : RecurKind::UMin);
6566 VPIRFlags Flags(MinMaxKind, /*IsOrdered=*/false, /*IsInLoop=*/false,
6567 FastMathFlags());
6568 DebugLoc ExitDL = RdxResult->getDebugLoc();
6569 VPBuilder MiddleBuilder(RdxResult);
6570 VPValue *ReducedIV =
6572 NewFindLastSelect, Flags, ExitDL);
6573
6574 // If IVOfExpressionToSink is an expression to sink, sink it now.
6575 VPValue *VectorRegionExitingVal = ReducedIV;
6576 if (IVOfExpressionToSink)
6577 VectorRegionExitingVal =
6578 cloneBinOpForScalarIV(cast<VPWidenRecipe>(FindLastExpression),
6579 ReducedIV, IVOfExpressionToSink);
6580
6581 VPValue *NewRdxResult;
6582 VPValue *StartVPV = PhiR->getStartValue();
6583 if (SentinelVal) {
6584 // Sentinel-based approach: reduce IVs with min/max, compare against
6585 // sentinel to detect if condition was ever true, select accordingly.
6586 VPValue *Sentinel = Plan.getConstantInt(*SentinelVal);
6587 auto *Cmp = MiddleBuilder.createICmp(CmpInst::ICMP_NE, ReducedIV,
6588 Sentinel, ExitDL);
6589 NewRdxResult = MiddleBuilder.createSelect(Cmp, VectorRegionExitingVal,
6590 StartVPV, ExitDL);
6591 StartVPV = Sentinel;
6592 } else {
6593 // Introduce a boolean AnyOf reduction to track if the condition was ever
6594 // true in the loop. Use it to select the initial start value, if it was
6595 // never true.
6596 auto *AnyOfPhi = new VPReductionPHIRecipe(
6597 /*Phi=*/nullptr, RecurKind::Or, *Plan.getFalse(), *Plan.getFalse(),
6598 RdxUnordered{1}, {}, /*HasUsesOutsideReductionChain=*/false);
6599 AnyOfPhi->insertAfter(PhiR);
6600
6601 VPBuilder LoopBuilder(BackedgeVal->getDefiningRecipe());
6602 VPValue *OrVal = LoopBuilder.createOr(AnyOfPhi, SelectCond);
6603 AnyOfPhi->setOperand(1, OrVal);
6604
6605 NewRdxResult = MiddleBuilder.createAnyOfReduction(
6606 OrVal, VectorRegionExitingVal, StartVPV, ExitDL);
6607
6608 // Initialize the IV reduction phi with the neutral element, not the
6609 // original start value, to ensure correct min/max reduction results.
6610 StartVPV = Plan.getOrAddLiveIn(
6611 getRecurrenceIdentity(MinMaxKind, IVSCEV->getType(), {}));
6612 }
6613 RdxResult->replaceAllUsesWith(NewRdxResult);
6614 RdxResult->eraseFromParent();
6615
6616 auto *NewPhiR = new VPReductionPHIRecipe(
6617 cast<PHINode>(PhiR->getUnderlyingInstr()), RecurKind::FindIV, *StartVPV,
6618 *NewFindLastSelect, RdxUnordered{1}, {},
6619 PhiR->hasUsesOutsideReductionChain());
6620 NewPhiR->insertBefore(PhiR);
6621 PhiR->replaceAllUsesWith(NewPhiR);
6622 PhiR->eraseFromParent();
6623 }
6624}
6625
6626namespace {
6627
6628using ExtendKind = TTI::PartialReductionExtendKind;
6629struct ReductionExtend {
6630 Type *SrcType = nullptr;
6631 ExtendKind Kind = ExtendKind::PR_None;
6632};
6633
6634/// Describes the extends used to compute the extended reduction operand.
6635/// ExtendB is optional. If ExtendB is present, ExtendsUser is a binary
6636/// operation.
6637struct ExtendedReductionOperand {
6638 /// The recipe that consumes the extends.
6639 VPWidenRecipe *ExtendsUser = nullptr;
6640 /// Extend descriptions (inputs to getPartialReductionCost).
6641 ReductionExtend ExtendA, ExtendB;
6642};
6643
6644/// A chain of recipes that form a partial reduction. Matches either
6645/// reduction_bin_op (extended op, accumulator), or
6646/// reduction_bin_op (accumulator, extended op).
6647/// The possible forms of the "extended op" are listed in
6648/// matchExtendedReductionOperand.
6649struct VPPartialReductionChain {
6650 /// The top-level binary operation that forms the reduction to a scalar
6651 /// after the loop body.
6652 VPWidenRecipe *ReductionBinOp = nullptr;
6653 /// The user of the extends that is then reduced.
6654 ExtendedReductionOperand ExtendedOp;
6655 /// The recurrence kind for the entire partial reduction chain.
6656 /// This allows distinguishing between Sub and AddWithSub recurrences,
6657 /// when the ReductionBinOp is a Instruction::Sub.
6658 RecurKind RK;
6659 /// The index of the accumulator operand of ReductionBinOp. The extended op
6660 /// is `1 - AccumulatorOpIdx`.
6661 unsigned AccumulatorOpIdx;
6662 unsigned ScaleFactor;
6663 /// Optional blend to represent predication for the block that updates the
6664 /// reduction.
6665 VPBlendRecipe *Blend = nullptr;
6666};
6667
6668// Return the incoming index of the single-use value in the blend, which is
6669// expected to be the predicated reduction update.
6670static std::optional<unsigned>
6671getBlendReductionUpdateValueIdx(VPBlendRecipe *Blend) {
6672 assert(Blend && !Blend->isNormalized() &&
6673 Blend->getNumIncomingValues() == 2 &&
6674 "Expected a non-normalized blend with two incoming values");
6675 bool FirstIncomingHasOneUse = Blend->getIncomingValue(0)->hasOneUse();
6676
6677 // Only the update value should have one use (the blend). The previous
6678 // value should always have at least two uses, the blend and the reduction.
6679 if (FirstIncomingHasOneUse == Blend->getIncomingValue(1)->hasOneUse())
6680 return std::nullopt;
6681 return FirstIncomingHasOneUse ? 0 : 1;
6682}
6683
6684static VPSingleDefRecipe *
6685optimizeExtendsForPartialReduction(VPSingleDefRecipe *Op) {
6686 // reduce.add(mul(ext(A), C))
6687 // -> reduce.add(mul(ext(A), ext(trunc(C))))
6688 const APInt *Const;
6689 if (match(Op, m_Mul(m_ZExtOrSExt(m_VPValue()), m_APInt(Const)))) {
6690 auto *ExtA = cast<VPWidenCastRecipe>(Op->getOperand(0));
6691 Instruction::CastOps ExtOpc = ExtA->getOpcode();
6692 Type *NarrowTy = ExtA->getOperand(0)->getScalarType();
6693 if (!Op->hasOneUse() ||
6695 Const, NarrowTy, TTI::getPartialReductionExtendKind(ExtOpc)))
6696 return Op;
6697
6698 VPBuilder Builder(Op);
6699 auto *Trunc = Builder.createWidenCast(Instruction::CastOps::Trunc,
6700 Op->getOperand(1), NarrowTy);
6701 Type *WideTy = ExtA->getScalarType();
6702 Op->setOperand(1, Builder.createWidenCast(ExtOpc, Trunc, WideTy));
6703 return Op;
6704 }
6705
6706 // reduce.add(abs(sub(ext(A), ext(B))))
6707 // -> reduce.add(ext(absolute-difference(A, B)))
6708 VPValue *X, *Y;
6711 auto *Sub = Op->getOperand(0)->getDefiningRecipe();
6712 auto *Ext = cast<VPWidenCastRecipe>(Sub->getOperand(0));
6713 assert(Ext->getOpcode() ==
6714 cast<VPWidenCastRecipe>(Sub->getOperand(1))->getOpcode() &&
6715 "Expected both the LHS and RHS extends to be the same");
6716 bool IsSigned = Ext->getOpcode() == Instruction::SExt;
6717 VPBuilder Builder(Op);
6718 Type *SrcTy = X->getScalarType();
6719 auto *FreezeX = Builder.insert(new VPWidenRecipe(Instruction::Freeze, {X}));
6720 auto *FreezeY = Builder.insert(new VPWidenRecipe(Instruction::Freeze, {Y}));
6721 auto *Max = Builder.insert(
6722 new VPWidenIntrinsicRecipe(IsSigned ? Intrinsic::smax : Intrinsic::umax,
6723 {FreezeX, FreezeY}, SrcTy));
6724 auto *Min = Builder.insert(
6725 new VPWidenIntrinsicRecipe(IsSigned ? Intrinsic::smin : Intrinsic::umin,
6726 {FreezeX, FreezeY}, SrcTy));
6727 auto *AbsDiff =
6728 Builder.insert(new VPWidenRecipe(Instruction::Sub, {Max, Min}));
6729 return Builder.createWidenCast(Instruction::CastOps::ZExt, AbsDiff,
6730 Op->getScalarType());
6731 }
6732
6733 // reduce.add(ext(mul(ext(A), ext(B))))
6734 // -> reduce.add(mul(wider_ext(A), wider_ext(B)))
6735 // TODO: Support this optimization for float types.
6737 m_ZExtOrSExt(m_VPValue()))))) {
6738 auto *Ext = cast<VPWidenCastRecipe>(Op);
6739 auto *Mul = cast<VPWidenRecipe>(Ext->getOperand(0));
6740 auto *MulLHS = cast<VPWidenCastRecipe>(Mul->getOperand(0));
6741 auto *MulRHS = cast<VPWidenCastRecipe>(Mul->getOperand(1));
6742 if (!Mul->hasOneUse() ||
6743 (Ext->getOpcode() != MulLHS->getOpcode() && MulLHS != MulRHS) ||
6744 MulLHS->getOpcode() != MulRHS->getOpcode())
6745 return Op;
6746 VPBuilder Builder(Mul);
6747 auto *NewLHS = Builder.createWidenCast(
6748 MulLHS->getOpcode(), MulLHS->getOperand(0), Ext->getScalarType());
6749 auto *NewRHS = MulLHS == MulRHS
6750 ? NewLHS
6751 : Builder.createWidenCast(MulRHS->getOpcode(),
6752 MulRHS->getOperand(0),
6753 Ext->getScalarType());
6754 auto *NewMul = Mul->cloneWithOperands({NewLHS, NewRHS});
6755 Builder.insert(NewMul);
6756 Op->replaceAllUsesWith(NewMul);
6757 Op->eraseFromParent();
6758 Mul->eraseFromParent();
6759 return NewMul;
6760 }
6761
6762 return Op;
6763}
6764
6765static VPExpressionRecipe *
6766createPartialReductionExpression(VPReductionRecipe *Red) {
6767 VPValue *VecOp = Red->getVecOp();
6768
6769 // reduce.[f]add(ext(op))
6770 // -> VPExpressionRecipe(op, red)
6771 if (match(VecOp, m_WidenAnyExtend(m_VPValue())))
6772 return new VPExpressionRecipe(cast<VPWidenCastRecipe>(VecOp), Red);
6773
6774 // reduce.[f]add(neg(ext(op)))
6775 // -> VPExpressionRecipe(op, sub/neg, red)
6776 if (match(VecOp, m_AnyNeg(m_WidenAnyExtend(m_VPValue())))) {
6777 auto *Neg = cast<VPWidenRecipe>(VecOp);
6778 auto *Ext =
6779 cast<VPWidenCastRecipe>(Neg->getOperand(Neg->getNumOperands() - 1));
6780 return new VPExpressionRecipe(Ext, Neg, Red);
6781 }
6782
6783 // reduce.[f]add([f]mul(ext(a), ext(b)))
6784 // -> VPExpressionRecipe(a, b, mul, red)
6785 if (match(VecOp, m_FMul(m_FPExt(m_VPValue()), m_FPExt(m_VPValue()))) ||
6786 match(VecOp,
6788 auto *Mul = cast<VPWidenRecipe>(VecOp);
6789 auto *ExtA = cast<VPWidenCastRecipe>(Mul->getOperand(0));
6790 auto *ExtB = cast<VPWidenCastRecipe>(Mul->getOperand(1));
6791 return new VPExpressionRecipe(ExtA, ExtB, Mul, Red);
6792 }
6793
6794 // reduce.fadd(fneg(fmul(fpext(a), fpext(b))))
6795 // -> VPExpressionRecipe(a, b, fmul, fsub, red)
6796 if (match(VecOp,
6798 auto *FNeg = cast<VPWidenRecipe>(VecOp);
6799 auto *FMul = cast<VPWidenRecipe>(FNeg->getOperand(0));
6800 auto *ExtA = cast<VPWidenCastRecipe>(FMul->getOperand(0));
6801 auto *ExtB = cast<VPWidenCastRecipe>(FMul->getOperand(1));
6802 return new VPExpressionRecipe(ExtA, ExtB, FMul, FNeg, Red);
6803 }
6804
6805 // reduce.add(neg(mul(ext(a), ext(b))))
6806 // -> VPExpressionRecipe(a, b, mul, sub, red)
6808 m_ZExtOrSExt(m_VPValue()))))) {
6809 auto *Sub = cast<VPWidenRecipe>(VecOp);
6810 auto *Mul = cast<VPWidenRecipe>(Sub->getOperand(1));
6811 auto *ExtA = cast<VPWidenCastRecipe>(Mul->getOperand(0));
6812 auto *ExtB = cast<VPWidenCastRecipe>(Mul->getOperand(1));
6813 return new VPExpressionRecipe(ExtA, ExtB, Mul, Sub, Red);
6814 }
6815
6816 llvm_unreachable("Unsupported expression");
6817}
6818
6819// Helper to transform a partial reduction chain into a partial reduction
6820// recipe. Assumes profitability has been checked.
6821static void transformToPartialReduction(const VPPartialReductionChain &Chain,
6822 VPlan &Plan,
6823 VPReductionPHIRecipe *RdxPhi) {
6824 VPWidenRecipe *WidenRecipe = Chain.ReductionBinOp;
6825 assert(WidenRecipe->getNumOperands() == 2 && "Expected binary operation");
6826
6827 VPValue *Accumulator = WidenRecipe->getOperand(Chain.AccumulatorOpIdx);
6828 auto *ExtendedOp = cast<VPSingleDefRecipe>(
6829 WidenRecipe->getOperand(1 - Chain.AccumulatorOpIdx));
6830
6831 // FIXME: Do these transforms before invoking the cost-model.
6832 ExtendedOp = optimizeExtendsForPartialReduction(ExtendedOp);
6833
6834 // Sub-reductions can be implemented in two ways:
6835 // (1) negate the operand in the vector loop (the default way).
6836 // (2) subtract the reduced value from the init value in the middle block.
6837 // Both ways keep the reduction itself as an 'add' reduction.
6838 //
6839 // The ISD nodes for partial reductions don't support folding the
6840 // sub/negation into its operands because the following is not a valid
6841 // transformation:
6842 // sub(0, mul(ext(a), ext(b)))
6843 // -> mul(ext(a), ext(sub(0, b)))
6844 //
6845 // It's therefore better to choose option (2) such that the partial
6846 // reduction is always positive (starting at '0') and to do a final
6847 // subtract in the middle block.
6848 if ((WidenRecipe->getOpcode() == Instruction::Sub &&
6849 Chain.RK != RecurKind::Sub) ||
6850 (WidenRecipe->getOpcode() == Instruction::FSub &&
6851 Chain.RK != RecurKind::FSub)) {
6852 VPBuilder Builder(WidenRecipe);
6853 Type *ElemTy = ExtendedOp->getScalarType();
6854 VPWidenRecipe *NegRecipe;
6855 if (WidenRecipe->getOpcode() == Instruction::FSub) {
6856 NegRecipe =
6857 new VPWidenRecipe(Instruction::FNeg, {ExtendedOp}, VPIRFlags(),
6859 } else {
6860 auto *Zero = Plan.getZero(ElemTy);
6861 NegRecipe =
6862 new VPWidenRecipe(Instruction::Sub, {Zero, ExtendedOp}, VPIRFlags(),
6864 }
6865 Builder.insert(NegRecipe);
6866 ExtendedOp = NegRecipe;
6867 }
6868
6869 // Check if WidenRecipe is the final result of the reduction. If so, look
6870 // through the Select recipe introduced by tail-folding, otherwise look
6871 // through any Blend recipe introduced by predication for the block.
6872 VPValue *ExitSearch =
6873 Chain.Blend ? cast<VPValue>(Chain.Blend) : cast<VPValue>(WidenRecipe);
6874
6875 VPValue *Cond = nullptr;
6877 findUserOf(ExitSearch, m_Select(m_VPValue(Cond), m_Specific(ExitSearch),
6878 m_Specific(RdxPhi))));
6879
6880 if (Chain.Blend) {
6881 std::optional<unsigned> BlendReductionIdx =
6882 getBlendReductionUpdateValueIdx(Chain.Blend);
6883 assert(BlendReductionIdx &&
6884 Chain.Blend->getIncomingValue(*BlendReductionIdx) == WidenRecipe &&
6885 "Expected blend to contain the reduction update");
6886 VPValue *BlendCond = Chain.Blend->getMask(*BlendReductionIdx);
6887 Cond = ExitValue ? VPBuilder(WidenRecipe)
6888 .createLogicalAnd(Cond, BlendCond,
6889 WidenRecipe->getDebugLoc())
6890 : BlendCond;
6891 }
6892
6893 bool IsLastInChain = RdxPhi->getBackedgeValue() == WidenRecipe ||
6894 RdxPhi->getBackedgeValue() == ExitValue ||
6895 RdxPhi->getBackedgeValue() == Chain.Blend;
6896 assert((!ExitValue || IsLastInChain) &&
6897 "if we found ExitValue, it must match RdxPhi's backedge value");
6898
6899 Type *PhiType = RdxPhi->getScalarType();
6900 RecurKind RdxKind =
6902 auto *PartialRed = new VPReductionRecipe(
6903 RdxKind,
6904 RdxKind == RecurKind::FAdd ? WidenRecipe->getFastMathFlagsOrNone()
6905 : FastMathFlags(),
6906 WidenRecipe->getUnderlyingInstr(), Accumulator, ExtendedOp, Cond,
6907 RdxUnordered{/*VFScaleFactor=*/Chain.ScaleFactor});
6908 PartialRed->insertBefore(WidenRecipe);
6909
6910 if (ExitValue)
6911 ExitValue->replaceAllUsesWith(PartialRed);
6912 if (Chain.Blend)
6913 Chain.Blend->replaceAllUsesWith(PartialRed);
6914 WidenRecipe->replaceAllUsesWith(PartialRed);
6915
6916 // For cost-model purposes, fold this into a VPExpression.
6917 VPExpressionRecipe *E = createPartialReductionExpression(PartialRed);
6918 E->insertBefore(WidenRecipe);
6919 PartialRed->replaceAllUsesWith(E);
6920
6921 // We only need to update the PHI node once, which is when we find the
6922 // last reduction in the chain.
6923 if (!IsLastInChain)
6924 return;
6925
6926 // Scale the PHI and ReductionStartVector by the VFScaleFactor
6927 assert(RdxPhi->getVFScaleFactor() == 1 && "scale factor must not be set");
6928 RdxPhi->setVFScaleFactor(Chain.ScaleFactor);
6929
6930 auto *StartInst = cast<VPInstruction>(RdxPhi->getStartValue());
6931 assert(StartInst->getOpcode() == VPInstruction::ReductionStartVector);
6932 auto *NewScaleFactor = Plan.getConstantInt(32, Chain.ScaleFactor);
6933 StartInst->setOperand(2, NewScaleFactor);
6934
6935 // If this is the last value in a sub-reduction chain, then update the PHI
6936 // node to start at `0` and update the reduction-result to subtract from
6937 // the PHI's start value.
6938 if (Chain.RK != RecurKind::Sub && Chain.RK != RecurKind::FSub)
6939 return;
6940
6941 VPValue *OldStartValue = StartInst->getOperand(0);
6942 StartInst->setOperand(0, StartInst->getOperand(1));
6943
6944 // Replace reduction_result by 'sub (startval, reductionresult)'.
6946 assert(RdxResult && "Could not find reduction result");
6947
6948 VPBuilder Builder = VPBuilder::getToInsertAfter(RdxResult);
6949 unsigned SubOpc = Chain.RK == RecurKind::FSub ? Instruction::BinaryOps::FSub
6950 : Instruction::BinaryOps::Sub;
6951 VPInstruction *NewResult = Builder.createNaryOp(
6952 SubOpc, {OldStartValue, RdxResult}, VPIRFlags::getDefaultFlags(SubOpc),
6953 RdxPhi->getDebugLoc());
6954 RdxResult->replaceUsesWithIf(
6955 NewResult,
6956 [&NewResult](VPUser &U, unsigned Idx) { return &U != NewResult; });
6957}
6958
6959/// Returns the cost of a link in a partial-reduction chain for a given VF.
6960static InstructionCost
6961getPartialReductionLinkCost(VPCostContext &CostCtx,
6962 const VPPartialReductionChain &Link,
6963 ElementCount VF) {
6964 Type *RdxType = Link.ReductionBinOp->getScalarType();
6965 const ExtendedReductionOperand &ExtendedOp = Link.ExtendedOp;
6966 std::optional<unsigned> BinOpc = std::nullopt;
6967 // If ExtendB is not none, then the "ExtendsUser" is the binary operation.
6968 if (ExtendedOp.ExtendB.Kind != ExtendKind::PR_None)
6969 BinOpc = ExtendedOp.ExtendsUser->getOpcode();
6970
6971 std::optional<llvm::FastMathFlags> Flags;
6972 if (RdxType->isFloatingPointTy())
6973 Flags = Link.ReductionBinOp->getFastMathFlagsOrNone();
6974
6975 auto GetLinkOpcode = [&Link]() -> unsigned {
6976 switch (Link.RK) {
6977 case RecurKind::Sub:
6978 return Instruction::Add;
6979 case RecurKind::FSub:
6980 return Instruction::FAdd;
6981 default:
6982 return Link.ReductionBinOp->getOpcode();
6983 }
6984 };
6985
6986 return CostCtx.TTI.getPartialReductionCost(
6987 GetLinkOpcode(), ExtendedOp.ExtendA.SrcType, ExtendedOp.ExtendB.SrcType,
6988 RdxType, VF, ExtendedOp.ExtendA.Kind, ExtendedOp.ExtendB.Kind, BinOpc,
6989 CostCtx.CostKind, Flags);
6990}
6991
6992static ExtendKind getPartialReductionExtendKind(VPWidenCastRecipe *Cast) {
6994}
6995
6996/// Checks if \p Op (which is an operand of \p UpdateR) is an extended reduction
6997/// operand. This is an operand where the source of the value (e.g. a load) has
6998/// been extended (sext, zext, or fpext) before it is used in the reduction.
6999///
7000/// Possible forms matched by this function:
7001/// - UpdateR(PrevValue, ext(...))
7002/// - UpdateR(PrevValue, mul(ext(...), ext(...)))
7003/// - UpdateR(PrevValue, mul(ext(...), Constant))
7004/// - UpdateR(PrevValue, ext(mul(ext(...), ext(...))))
7005/// - UpdateR(PrevValue, ext(mul(ext(...), Constant)))
7006/// - UpdateR(PrevValue, abs(sub(ext(...), ext(...)))
7007///
7008/// Note: The second operand of UpdateR corresponds to \p Op in the examples.
7009static std::optional<ExtendedReductionOperand>
7010matchExtendedReductionOperand(VPWidenRecipe *UpdateR, VPValue *Op) {
7011 assert(is_contained(UpdateR->operands(), Op) &&
7012 "Op should be operand of UpdateR");
7013
7014 // Try matching an absolute difference operand of the form
7015 // `abs(sub(ext(A), ext(B)))`. This will be later transformed into
7016 // `ext(absolute-difference(A, B))`. This allows us to perform the absolute
7017 // difference on a wider type and get the extend for "free" from the partial
7018 // reduction.
7019 VPValue *X, *Y;
7020 if (Op->hasOneUse() &&
7024 auto *Abs = cast<VPWidenIntrinsicRecipe>(Op);
7025 auto *Sub = cast<VPWidenRecipe>(Abs->getOperand(0));
7026 auto *LHSExt = cast<VPWidenCastRecipe>(Sub->getOperand(0));
7027 auto *RHSExt = cast<VPWidenCastRecipe>(Sub->getOperand(1));
7028 Type *LHSInputType = X->getScalarType();
7029 Type *RHSInputType = Y->getScalarType();
7030 if (LHSInputType != RHSInputType ||
7031 LHSExt->getOpcode() != RHSExt->getOpcode())
7032 return std::nullopt;
7033 // Note: This is essentially the same as matching ext(...) as we will
7034 // rewrite this operand to ext(absolute-difference(A, B)).
7035 return ExtendedReductionOperand{
7036 Sub,
7037 /*ExtendA=*/{LHSInputType, getPartialReductionExtendKind(LHSExt)},
7038 /*ExtendB=*/{}};
7039 }
7040
7041 std::optional<TTI::PartialReductionExtendKind> OuterExtKind;
7043 auto *CastRecipe = cast<VPWidenCastRecipe>(Op);
7044 VPValue *CastSource = CastRecipe->getOperand(0);
7045 OuterExtKind = getPartialReductionExtendKind(CastRecipe);
7046 if (match(CastSource, m_Mul(m_VPValue(), m_VPValue())) ||
7047 match(CastSource, m_FMul(m_VPValue(), m_VPValue()))) {
7048 // Match: ext(mul(...))
7049 // Record the outer extend kind and set `Op` to the mul. We can then match
7050 // this as a binary operation. Note: We can optimize out the outer extend
7051 // by widening the inner extends to match it. See
7052 // optimizeExtendsForPartialReduction.
7053 Op = CastSource;
7054 } else {
7055 return ExtendedReductionOperand{
7056 UpdateR,
7057 /*ExtendA=*/{CastSource->getScalarType(), *OuterExtKind},
7058 /*ExtendB=*/{}};
7059 }
7060 }
7061
7062 if (!Op->hasOneUse())
7063 return std::nullopt;
7064
7066 if (!MulOp ||
7067 !is_contained({Instruction::Mul, Instruction::FMul}, MulOp->getOpcode()))
7068 return std::nullopt;
7069
7070 // The rest of the matching assumes `Op` is a (possibly extended) mul
7071 // operation.
7072
7073 VPValue *LHS = MulOp->getOperand(0);
7074 VPValue *RHS = MulOp->getOperand(1);
7075
7076 // The LHS of the operation must always be an extend.
7078 return std::nullopt;
7079
7080 auto *LHSCast = cast<VPWidenCastRecipe>(LHS);
7081 Type *LHSInputType = LHSCast->getOperand(0)->getScalarType();
7082 ExtendKind LHSExtendKind = getPartialReductionExtendKind(LHSCast);
7083
7084 // The RHS of the operation can be an extend or a constant integer.
7085 const APInt *RHSConst = nullptr;
7086 VPWidenCastRecipe *RHSCast = nullptr;
7088 RHSCast = cast<VPWidenCastRecipe>(RHS);
7089 else if (!match(RHS, m_APInt(RHSConst)) ||
7090 !canConstantBeExtended(RHSConst, LHSInputType, LHSExtendKind))
7091 return std::nullopt;
7092
7093 // The outer extend kind must match the inner extends for folding.
7094 for (VPWidenCastRecipe *Cast : {LHSCast, RHSCast})
7095 if (Cast && OuterExtKind &&
7096 getPartialReductionExtendKind(Cast) != OuterExtKind)
7097 return std::nullopt;
7098
7099 Type *RHSInputType = LHSInputType;
7100 ExtendKind RHSExtendKind = LHSExtendKind;
7101 if (RHSCast) {
7102 RHSInputType = RHSCast->getOperand(0)->getScalarType();
7103 RHSExtendKind = getPartialReductionExtendKind(RHSCast);
7104 }
7105
7106 return ExtendedReductionOperand{
7107 MulOp, {LHSInputType, LHSExtendKind}, {RHSInputType, RHSExtendKind}};
7108}
7109
7110/// Examines each operation in the reduction chain corresponding to \p RedPhiR,
7111/// and determines if the target can use a cheaper operation with a wider
7112/// per-iteration input VF and narrower PHI VF. If successful, returns the chain
7113/// of operations in the reduction.
7114static std::optional<SmallVector<VPPartialReductionChain>>
7115getScaledReductions(VPReductionPHIRecipe *RedPhiR) {
7116 // Get the backedge value from the reduction PHI and find the
7117 // ComputeReductionResult that uses it (directly or through a select for
7118 // predicated reductions).
7119 auto *RdxResult = vputils::findComputeReductionResult(RedPhiR);
7120 if (!RdxResult)
7121 return std::nullopt;
7122 VPValue *ExitValue = RdxResult->getOperand(0);
7123 match(ExitValue, m_Select(m_VPValue(), m_VPValue(ExitValue), m_VPValue()));
7124
7126 RecurKind RK = RedPhiR->getRecurrenceKind();
7127 Type *PhiType = RedPhiR->getScalarType();
7128 TypeSize PHISize = PhiType->getPrimitiveSizeInBits();
7129
7130 // Work backwards from the ExitValue examining each reduction operation.
7131 VPValue *CurrentValue = ExitValue;
7132 while (CurrentValue != RedPhiR) {
7133 VPBlendRecipe *Blend = dyn_cast<VPBlendRecipe>(CurrentValue);
7134 std::optional<unsigned> BlendReductionIdx;
7135 if (Blend) {
7136 assert(!Blend->isNormalized() && "Expect Blend not to be normalized.");
7137 if (Blend->getNumIncomingValues() != 2)
7138 return std::nullopt;
7139
7140 BlendReductionIdx = getBlendReductionUpdateValueIdx(Blend);
7141 if (!BlendReductionIdx)
7142 return std::nullopt;
7143
7144 CurrentValue = Blend->getIncomingValue(*BlendReductionIdx);
7145 }
7146
7147 auto *UpdateR = dyn_cast<VPWidenRecipe>(CurrentValue);
7148 if (!UpdateR || !Instruction::isBinaryOp(UpdateR->getOpcode()))
7149 return std::nullopt;
7150
7151 VPValue *Op = UpdateR->getOperand(1);
7152 VPValue *PrevValue = UpdateR->getOperand(0);
7153
7154 // Find the extended operand. The other operand (PrevValue) is the next link
7155 // in the reduction chain.
7156 std::optional<ExtendedReductionOperand> ExtendedOp =
7157 matchExtendedReductionOperand(UpdateR, Op);
7158 if (!ExtendedOp) {
7159 ExtendedOp = matchExtendedReductionOperand(UpdateR, PrevValue);
7160 if (!ExtendedOp)
7161 return std::nullopt;
7162 std::swap(Op, PrevValue);
7163 }
7164
7165 // Look for VPBlend(reduce(PrevValue, Op), PrevValue), where
7166 // reduce is equal to CurrentValue. This can be lowered as
7167 // a conditional reduction by hoisting the select to the inputs.
7168 if (Blend && Blend->getIncomingValue(1 - *BlendReductionIdx) != PrevValue)
7169 return std::nullopt;
7170
7171 Type *ExtSrcType = ExtendedOp->ExtendA.SrcType;
7172 TypeSize ExtSrcSize = ExtSrcType->getPrimitiveSizeInBits();
7173 if (!PHISize.hasKnownScalarFactor(ExtSrcSize))
7174 return std::nullopt;
7175
7176 VPPartialReductionChain Link(
7177 {UpdateR, *ExtendedOp, RK,
7178 PrevValue == UpdateR->getOperand(0) ? 0U : 1U,
7179 static_cast<unsigned>(PHISize.getKnownScalarFactor(ExtSrcSize)),
7180 Blend});
7181 Chain.push_back(Link);
7182 CurrentValue = PrevValue;
7183 }
7184
7185 // The chain links were collected by traversing backwards from the exit value.
7186 // Reverse the chains so they are in program order.
7187 std::reverse(Chain.begin(), Chain.end());
7188 return Chain;
7189}
7190} // namespace
7191
7193 VPCostContext &CostCtx,
7194 VFRange &Range) {
7195 // Find all possible valid partial reductions, grouping chains by their PHI.
7196 // This grouping allows invalidating the whole chain, if any link is not a
7197 // valid partial reduction.
7199 ChainsByPhi;
7200 VPBasicBlock *HeaderVPBB = Plan.getVectorLoopRegion()->getEntryBasicBlock();
7201 for (VPRecipeBase &R : HeaderVPBB->phis()) {
7202 auto *RedPhiR = dyn_cast<VPReductionPHIRecipe>(&R);
7203 if (!RedPhiR)
7204 continue;
7205
7206 if (auto Chains = getScaledReductions(RedPhiR))
7207 ChainsByPhi.try_emplace(RedPhiR, std::move(*Chains));
7208 }
7209
7210 if (ChainsByPhi.empty())
7211 return;
7212
7213 // Build set of partial reduction operations and blends for user validation
7214 // and a map of reduction bin ops to their scale factors for scale validation.
7215 SmallPtrSet<VPRecipeBase *, 4> PartialReductionOps;
7216 SmallPtrSet<VPBlendRecipe *, 4> PartialReductionBlends;
7217 DenseMap<VPSingleDefRecipe *, unsigned> ScaledReductionMap;
7218 for (const auto &[_, Chains] : ChainsByPhi)
7219 for (const VPPartialReductionChain &Chain : Chains) {
7220 PartialReductionOps.insert(Chain.ExtendedOp.ExtendsUser);
7221 if (Chain.Blend)
7222 PartialReductionBlends.insert(Chain.Blend);
7223 ScaledReductionMap[Chain.ReductionBinOp] = Chain.ScaleFactor;
7224 }
7225
7226 // A partial reduction is invalid if any of its extends are used by
7227 // something that isn't another partial reduction. This is because the
7228 // extends are intended to be lowered along with the reduction itself.
7229 auto ExtendUsersValid = [&](VPValue *Ext) {
7230 return !isa<VPWidenCastRecipe>(Ext) || all_of(Ext->users(), [&](VPUser *U) {
7231 return PartialReductionOps.contains(cast<VPRecipeBase>(U));
7232 });
7233 };
7234
7235 auto IsProfitablePartialReductionChainForVF =
7236 [&](ArrayRef<VPPartialReductionChain> Chain, ElementCount VF) -> bool {
7237 InstructionCost PartialCost = 0, RegularCost = 0;
7238
7239 // The chain is a profitable partial reduction chain if the cost of handling
7240 // the entire chain is cheaper when using partial reductions than when
7241 // handling the entire chain using regular reductions.
7242 for (const VPPartialReductionChain &Link : Chain) {
7243 const ExtendedReductionOperand &ExtendedOp = Link.ExtendedOp;
7244 InstructionCost LinkCost = getPartialReductionLinkCost(CostCtx, Link, VF);
7245 if (!LinkCost.isValid())
7246 return false;
7247
7248 PartialCost += LinkCost;
7249 RegularCost += Link.ReductionBinOp->computeCost(VF, CostCtx);
7250 // If ExtendB is not none, then the "ExtendsUser" is the binary operation.
7251 if (ExtendedOp.ExtendB.Kind != ExtendKind::PR_None)
7252 RegularCost += ExtendedOp.ExtendsUser->computeCost(VF, CostCtx);
7253 for (VPValue *Op : ExtendedOp.ExtendsUser->operands())
7254 if (auto *Extend = dyn_cast<VPWidenCastRecipe>(Op))
7255 RegularCost += Extend->computeCost(VF, CostCtx);
7256 }
7257 return PartialCost.isValid() && PartialCost < RegularCost;
7258 };
7259
7260 // Validate chains: check that extends are only used by partial reductions,
7261 // and that reduction bin ops are only used by other partial reductions with
7262 // matching scale factors, are outside the loop region or the select
7263 // introduced by tail-folding. Otherwise we would create users of scaled
7264 // reductions where the types of the other operands don't match.
7265 for (auto &[RedPhiR, Chains] : ChainsByPhi) {
7266 for (const VPPartialReductionChain &Chain : Chains) {
7267 if (!all_of(Chain.ExtendedOp.ExtendsUser->operands(), ExtendUsersValid)) {
7268 Chains.clear();
7269 break;
7270 }
7271 auto UseIsValid = [&, RedPhiR = RedPhiR](VPUser *U) {
7272 if (auto *PhiR = dyn_cast<VPReductionPHIRecipe>(U))
7273 return PhiR == RedPhiR;
7274 auto *R = cast<VPSingleDefRecipe>(U);
7275
7276 if (auto *Blend = dyn_cast<VPBlendRecipe>(R))
7277 return Blend == Chain.Blend || PartialReductionBlends.contains(Blend);
7278
7279 return Chain.ScaleFactor == ScaledReductionMap.lookup_or(R, 0) ||
7281 m_Specific(Chain.ReductionBinOp))) ||
7282 match(R, m_Select(m_VPValue(), m_Specific(Chain.ReductionBinOp),
7283 m_Specific(RedPhiR)));
7284 };
7285 if (!all_of(Chain.ReductionBinOp->users(), UseIsValid)) {
7286 Chains.clear();
7287 break;
7288 }
7289
7290 // Check if the compute-reduction-result is used by a sunk store.
7291 // TODO: Also form partial reductions in those cases.
7292 if (auto *RdxResult = vputils::findComputeReductionResult(RedPhiR)) {
7293 if (any_of(RdxResult->users(), [](VPUser *U) {
7294 auto *RepR = dyn_cast<VPReplicateRecipe>(U);
7295 return RepR && RepR->getOpcode() == Instruction::Store;
7296 })) {
7297 Chains.clear();
7298 break;
7299 }
7300 }
7301 }
7302
7303 // Clear the chain if it is not profitable.
7305 [&, &Chains = Chains](ElementCount VF) {
7306 return IsProfitablePartialReductionChainForVF(Chains, VF);
7307 },
7308 Range))
7309 Chains.clear();
7310 }
7311
7312 for (auto &[Phi, Chains] : ChainsByPhi)
7313 for (const VPPartialReductionChain &Chain : Chains)
7314 transformToPartialReduction(Chain, Plan, Phi);
7315}
7316
7317/// If the pointer operand \p Addr of a memory access is an affine AddRec
7318/// w.r.t. \p L with a constant stride, return the stride in units of
7319/// \p AccessTy. Otherwise return std::nullopt.
7320static std::optional<int64_t> getConstantStride(VPValue *Addr, Type *AccessTy,
7322 const Loop *L) {
7323 const SCEV *AddrSCEV = vputils::getSCEVExprForVPValue(Addr, PSE, L);
7324 auto *AddRec = dyn_cast<SCEVAddRecExpr>(AddrSCEV);
7325 if (!AddRec)
7326 return {};
7327
7328 return getStrideFromAddRec(AddRec, L, AccessTy, /*Ptr=*/nullptr, PSE);
7329}
7330
7332 VPRecipeBuilder &RecipeBuilder,
7333 VPCostContext &CostCtx) {
7334 // Collect all loads/stores first. We will start with ones having simpler
7335 // decisions followed by more complex ones that are potentially
7336 // guided/dependent on the simpler ones.
7338 for (VPBasicBlock *VPBB :
7341 for (VPRecipeBase &R : *VPBB) {
7342 auto *VPI = dyn_cast<VPInstruction>(&R);
7343 if (VPI && VPI->getUnderlyingValue() &&
7344 is_contained({Instruction::Load, Instruction::Store},
7345 VPI->getOpcode()))
7346 MemOps.push_back(VPI);
7347 }
7348 }
7349
7350 // Few helpers to process different kinds of memory operations.
7351
7352 // To be used as argument to `VPlanTransforms::runPass` which explicitly
7353 // specified pass name, hence `VPlan &` parameter.
7354 auto ProcessSubset = [&](VPlan &, auto ProcessVPInst) {
7355 SmallVector<VPInstruction *> RemainingMemOps;
7356 for (VPInstruction *VPI : MemOps) {
7357 if (!ProcessVPInst(VPI))
7358 RemainingMemOps.push_back(VPI);
7359 }
7360
7361 MemOps.clear();
7362 std::swap(MemOps, RemainingMemOps);
7363 };
7364
7365 auto ReplaceWith = [&](VPInstruction *VPI, VPRecipeBase *New) {
7366 New->insertBefore(VPI);
7367 if (VPI->getOpcode() == Instruction::Load)
7368 VPI->replaceAllUsesWith(New->getVPSingleValue());
7369 VPI->eraseFromParent();
7370
7371 // VPI has been processed.
7372 return true;
7373 };
7374
7375 auto Scalarize = [&](VPInstruction *VPI) {
7376 return ReplaceWith(VPI, RecipeBuilder.handleReplication(VPI, Range));
7377 };
7378
7379 VPBasicBlock *MiddleVPBB = Plan.getMiddleBlock();
7380 VPBuilder FinalRedStoresBuilder(MiddleVPBB, MiddleVPBB->getFirstNonPhi());
7382 "lowerMemoryIdioms", ProcessSubset, Plan, [&](VPInstruction *VPI) {
7383 if (RecipeBuilder.replaceWithFinalIfReductionStore(
7384 VPI, FinalRedStoresBuilder))
7385 return true;
7386
7387 // Filter out scalar VPlan for the remaining idioms.
7389 [](ElementCount VF) { return VF.isScalar(); }, Range))
7390 return false;
7391
7392 if (VPHistogramRecipe *Histogram = RecipeBuilder.widenIfHistogram(VPI))
7393 return ReplaceWith(VPI, Histogram);
7394
7395 return false;
7396 });
7397
7398 // Filter out scalar VPlan for the remaining memory operations.
7400 [](ElementCount VF) { return VF.isScalar(); }, Range))
7401 return;
7402
7403 // If the instruction's allocated size doesn't equal it's type size, it
7404 // requires padding and will be scalarized.
7406 "scalarizeMemOpsWithIrregularTypes", ProcessSubset, Plan,
7407 [&](VPInstruction *VPI) {
7409 if (hasIrregularType(getLoadStoreType(I), I->getDataLayout()))
7410 return Scalarize(VPI);
7411
7412 return false;
7413 });
7414
7415 if (!RecipeBuilder.prefersVectorizedAddressing()) {
7417 "makeVPlanMemOpDecision", ProcessSubset, Plan, [&](VPInstruction *VPI) {
7419 bool IsLoad = VPI->getOpcode() == Instruction::Load;
7420 if (RecipeBuilder.isPredicatedInst(I) || !IsLoad ||
7422 return false;
7423
7424 // Scalarize loads used as addresses, matching the legacy CM. The load
7425 // is single-scalar if the pointer is loop-invariant, otherwise it is
7426 // replicated per-lane. No mask is needed as the load is not
7427 // predicated.
7428 VPValue *Ptr = VPI->getOperand(0);
7429 const SCEV *PtrSCEV =
7430 vputils::getSCEVExprForVPValue(Ptr, CostCtx.PSE, CostCtx.L);
7431 bool IsSingleScalarLoad =
7432 !isa<SCEVCouldNotCompute>(PtrSCEV) &&
7433 CostCtx.PSE.getSE()->isLoopInvariant(PtrSCEV, CostCtx.L);
7434
7435 ReplaceWith(VPI,
7437 I, Ptr, /*IsSingleScalar=*/IsSingleScalarLoad,
7438 /*Mask=*/nullptr, *VPI, *VPI, VPI->getDebugLoc()));
7439 return true;
7440 });
7441 }
7442
7443 // Widen unmasked unit-stride consecutive accesses, matching the legacy CM.
7445 "widenConsecutiveMemOps", ProcessSubset, Plan, [&](VPInstruction *VPI) {
7447 if (RecipeBuilder.isPredicatedInst(I))
7448 return false;
7449
7450 bool IsLoad = VPI->getOpcode() == Instruction::Load;
7451 VPValue *Ptr = VPI->getOperand(!IsLoad);
7452 Type *ScalarTy =
7453 IsLoad ? VPI->getScalarType() : VPI->getOperand(0)->getScalarType();
7454 if (getConstantStride(Ptr, ScalarTy, CostCtx.PSE, CostCtx.L) != 1)
7455 return false;
7456
7457 Type *StrideTy =
7459 VPValue *StrideOne = Plan.getConstantInt(StrideTy, 1);
7460 auto *VectorPtr = new VPVectorPointerRecipe(
7461 Ptr, ScalarTy, StrideOne, vputils::getGEPFlagsForPtr(Ptr),
7462 VPI->getDebugLoc());
7463 VectorPtr->insertBefore(VPI);
7464 VPRecipeBase *WidenedR;
7465 if (IsLoad)
7466 WidenedR = new VPWidenLoadRecipe(*cast<LoadInst>(I), VectorPtr,
7467 /*Mask=*/nullptr,
7468 /*Consecutive=*/true, *VPI,
7469 VPI->getDebugLoc());
7470 else
7471 WidenedR = new VPWidenStoreRecipe(
7472 *cast<StoreInst>(I), VectorPtr, VPI->getOperand(0),
7473 /*Mask=*/nullptr, /*Consecutive=*/true, *VPI, VPI->getDebugLoc());
7474 return ReplaceWith(VPI, WidenedR);
7475 });
7476
7477 VPlanTransforms::runPass("delegateMemOpWideningToLegacyCM", ProcessSubset,
7478 Plan, [&](VPInstruction *VPI) {
7479 if (VPRecipeBase *Recipe =
7480 RecipeBuilder.tryToWidenMemory(VPI, Range))
7481 return ReplaceWith(VPI, Recipe);
7482
7483 return Scalarize(VPI);
7484 });
7485}
7486
7489 [&](ElementCount VF) { return VF.isScalar(); }, Range))
7490 return;
7491
7493 Plan.getEntry());
7495 for (VPRecipeBase &R : make_early_inc_range(reverse(*VPBB))) {
7496 auto *VPI = dyn_cast<VPInstruction>(&R);
7497 if (!VPI)
7498 continue;
7499
7500 auto *I = cast_or_null<Instruction>(VPI->getUnderlyingValue());
7501 // Wouldn't be able to create a `VPReplicateRecipe` anyway.
7502 if (!I)
7503 continue;
7504
7505 // If executing other lanes produces side-effects we can't avoid them.
7506 if (VPI->mayHaveSideEffects())
7507 continue;
7508
7509 // We want to drop the mask operand, verify we can safely do that.
7510 if (VPI->isMasked() && !VPI->isSafeToSpeculativelyExecute())
7511 continue;
7512
7513 // Avoid rewriting IV increment as that interferes with
7514 // `removeRedundantCanonicalIVs`.
7515 if (VPI->getOpcode() == Instruction::Add &&
7517 continue;
7518
7519 // Other lanes are needed - can't drop them.
7521 continue;
7522
7523 auto *Recipe = VPBuilder::createSingleScalarOp(
7524 VPI->getOpcode(), VPI->operandsWithoutMask(), /*Mask=*/nullptr, *VPI,
7525 *VPI, VPI->getDebugLoc(), I);
7526 Recipe->insertBefore(VPI);
7527 VPI->replaceAllUsesWith(Recipe);
7528 VPI->eraseFromParent();
7529 }
7530 }
7531}
7532
7533/// Returns true if \p Info's parameter kinds are compatible with \p Args.
7534static bool areVFParamsOk(const VFInfo &Info, ArrayRef<VPValue *> Args,
7535 PredicatedScalarEvolution &PSE, const Loop *L) {
7536 ScalarEvolution *SE = PSE.getSE();
7537 return all_of(Info.Shape.Parameters, [&](VFParameter Param) {
7538 switch (Param.ParamKind) {
7539 case VFParamKind::Vector:
7540 case VFParamKind::GlobalPredicate:
7541 return true;
7542 case VFParamKind::OMP_Uniform:
7543 return SE->isSCEVable(Args[Param.ParamPos]->getScalarType()) &&
7544 SE->isLoopInvariant(
7545 vputils::getSCEVExprForVPValue(Args[Param.ParamPos], PSE, L),
7546 L);
7547 case VFParamKind::OMP_Linear:
7548 return match(vputils::getSCEVExprForVPValue(Args[Param.ParamPos], PSE, L),
7549 m_scev_AffineAddRec(
7550 m_SCEV(), m_scev_SpecificSInt(Param.LinearStepOrPos),
7551 m_SpecificLoop(L)));
7552 default:
7553 return false;
7554 }
7555 });
7556}
7557
7558/// Find a vector variant of \p CI for \p VF, respecting \p MaskRequired.
7559/// Returns the variant function, or nullptr. Masked variants are assumed to
7560/// take the mask as a trailing parameter.
7562 ElementCount VF, bool MaskRequired,
7564 const Loop *L) {
7565 if (CI->isNoBuiltin())
7566 return nullptr;
7567 auto Mappings = VFDatabase::getMappings(*CI);
7568 const auto *It = find_if(Mappings, [&](const VFInfo &Info) {
7569 return Info.Shape.VF == VF && (!MaskRequired || Info.isMasked()) &&
7570 areVFParamsOk(Info, Args, PSE, L);
7571 });
7572 if (It == Mappings.end())
7573 return nullptr;
7574 return CI->getModule()->getFunction(It->VectorName);
7575}
7576
7577namespace {
7578/// The outcome of choosing how to widen a call at a given VF.
7579struct CallWideningDecision {
7580 enum class KindTy { Scalarize, Intrinsic, VectorVariant };
7581 CallWideningDecision(KindTy Kind, Function *Variant = nullptr)
7582 : Kind(Kind), Variant(Variant) {}
7583 KindTy Kind;
7584
7585 /// Set when Kind == VectorVariant.
7587
7588 bool operator==(const CallWideningDecision &Other) const {
7589 return Kind == Other.Kind && Variant == Other.Variant;
7590 }
7591};
7592} // namespace
7593
7594/// Pick the cheapest widening for the call \p VPI at \p VF among scalarization,
7595/// vector intrinsic, and vector library variant.
7596static CallWideningDecision decideCallWidening(VPInstruction &VPI,
7598 ElementCount VF,
7599 VPCostContext &CostCtx) {
7600 auto *CI = cast<CallInst>(VPI.getUnderlyingInstr());
7601
7602 // Scalar VFs and calls forced or known to scalarize always replicate.
7603 if (VF.isScalar() || CostCtx.willBeScalarized(CI, VF))
7604 return CallWideningDecision::KindTy::Scalarize;
7605
7606 auto *CalledFn = cast<Function>(
7608 Type *ResultTy = VPI.getScalarType();
7610 bool MaskRequired = CostCtx.isMaskRequired(CI);
7611
7612 // Pseudo intrinsics (assume, lifetime, ...) are always scalarized.
7614 return CallWideningDecision::KindTy::Scalarize;
7615
7616 InstructionCost ScalarCost =
7617 VPReplicateRecipe::computeCallCost(CalledFn, ResultTy, Ops,
7618 /*IsSingleScalar=*/false, VF, CostCtx);
7619
7620 Function *VecFunc =
7621 findVectorVariant(CI, Ops, VF, MaskRequired, CostCtx.PSE, CostCtx.L);
7623 if (VecFunc)
7624 VecCallCost = VPWidenCallRecipe::computeCallCost(VecFunc, CostCtx);
7625
7626 // Prefer the intrinsic if it is at least as cheap as scalarizing and any
7627 // available vector variant.
7628 if (ID) {
7631 if (IntrinsicCost.isValid() && ScalarCost >= IntrinsicCost &&
7632 (!VecFunc || VecCallCost >= IntrinsicCost))
7633 return CallWideningDecision::KindTy::Intrinsic;
7634 }
7635
7636 // Otherwise, use a vector library variant when it beats scalarizing.
7637 if (VecFunc && ScalarCost >= VecCallCost)
7638 return {CallWideningDecision::KindTy::VectorVariant, VecFunc};
7639
7640 return CallWideningDecision::KindTy::Scalarize;
7641}
7642
7644 VPRecipeBuilder &RecipeBuilder,
7645 VPCostContext &CostCtx) {
7648 for (VPRecipeBase &R : make_early_inc_range(*VPBB)) {
7649 auto *VPI = dyn_cast<VPInstruction>(&R);
7650 if (!VPI || !VPI->getUnderlyingValue() ||
7651 VPI->getOpcode() != Instruction::Call)
7652 continue;
7653
7654 auto *CI = cast<CallInst>(VPI->getUnderlyingInstr());
7655 SmallVector<VPValue *, 4> Ops(VPI->op_begin(),
7656 VPI->op_begin() + CI->arg_size());
7657
7658 CallWideningDecision Decision =
7659 decideCallWidening(*VPI, Ops, Range.Start, CostCtx);
7661 [&](ElementCount VF) {
7662 return Decision == decideCallWidening(*VPI, Ops, VF, CostCtx);
7663 },
7664 Range);
7665
7666 VPSingleDefRecipe *Replacement = nullptr;
7667 switch (Decision.Kind) {
7668 case CallWideningDecision::KindTy::Intrinsic: {
7670 Type *ResultTy = VPI->getScalarType();
7671 Replacement = new VPWidenIntrinsicRecipe(*CI, ID, Ops, ResultTy, *VPI,
7672 *VPI, VPI->getDebugLoc());
7673 break;
7674 }
7675 case CallWideningDecision::KindTy::VectorVariant: {
7676 // Masked variants take the mask as a trailing parameter, so they have
7677 // one more parameter than the original call's arguments.
7678 if (Decision.Variant->arg_size() > Ops.size()) {
7679 VPValue *Mask = VPI->isMasked() ? VPI->getMask() : Plan.getTrue();
7680 Ops.push_back(Mask);
7681 }
7682 Ops.push_back(VPI->getOperand(VPI->getNumOperandsWithoutMask() - 1));
7683 Replacement = new VPWidenCallRecipe(CI, Decision.Variant, Ops, *VPI,
7684 *VPI, VPI->getDebugLoc());
7685 break;
7686 }
7687 case CallWideningDecision::KindTy::Scalarize:
7688 Replacement = RecipeBuilder.handleReplication(VPI, Range);
7689 break;
7690 }
7691
7692 Replacement->insertBefore(VPI);
7693 VPI->replaceAllUsesWith(Replacement);
7694 VPI->eraseFromParent();
7695 }
7696 }
7697}
7698
7701 Loop &L, VPCostContext &Ctx,
7702 VFRange &Range) {
7703 if (Plan.hasScalarVFOnly())
7704 return;
7705
7706 VPRegionBlock *VectorLoop = Plan.getVectorLoopRegion();
7707 VPValue *I32VF = nullptr;
7709 vp_depth_first_shallow(VectorLoop->getEntry()))) {
7710 for (VPRecipeBase &R : make_early_inc_range(*VPBB)) {
7711 auto *LoadR = dyn_cast<VPWidenLoadRecipe>(&R);
7712 // TODO: Support strided store.
7713 // TODO: Transform reverse access into strided access with -1 stride.
7714 // TODO: Transform gather/scatter with uniform address into strided access
7715 // with 0 stride.
7716 // TODO: Transform interleave access into multiple strided accesses.
7717 if (!LoadR || LoadR->isConsecutive())
7718 continue;
7719
7720 VPValue *Ptr = LoadR->getAddr();
7721 // Check if this is a strided access by analyzing the address SCEV for an
7722 // affine addRec.
7723 const SCEV *PtrSCEV = vputils::getSCEVExprForVPValue(Ptr, PSE, &L);
7724 const SCEV *Start;
7725 const SCEVConstant *Step;
7726 // TODO: Support non-constant loop invariant stride.
7727 if (!match(PtrSCEV,
7729 m_SpecificLoop(&L))))
7730 continue;
7731
7732 Type *LoadTy = LoadR->getScalarType();
7733 Align Alignment = LoadR->getAlign();
7734 auto IsProfitable = [&](ElementCount VF) {
7735 Type *DataTy = toVectorTy(LoadTy, VF);
7736 if (!Ctx.TTI.isLegalStridedLoadStore(DataTy, Alignment))
7737 return false;
7738 const InstructionCost CurrentCost = LoadR->computeCost(VF, Ctx);
7739 const InstructionCost StridedLoadStoreCost =
7741 Intrinsic::experimental_vp_strided_load, DataTy,
7742 LoadR->isMasked(), Alignment, Ctx);
7743 return StridedLoadStoreCost < CurrentCost;
7744 };
7745
7747 Range))
7748 continue;
7749
7750 // Invalidate the legacy widening decision so the cost of replaced load is
7751 // not counted during precomputeCosts.
7752 // TODO: Remove once the legacy exit cost computation is retired.
7753 for (ElementCount VF : Range)
7754 Ctx.invalidateWideningDecision(&LoadR->getIngredient(), VF);
7755
7756 // Get VF as i32 for the vector length operand.
7757 if (!I32VF) {
7758 VPBuilder Builder(Plan.getVectorPreheader());
7759 I32VF = Builder.createScalarZExtOrTrunc(
7760 &Plan.getVF(), Type::getInt32Ty(Plan.getContext()),
7762 }
7763
7764 VPBuilder Builder(LoadR);
7765 // Create the base pointer of strided access.
7766 // TODO: reuse VPDerivedIVRecipe for base pointer computation when it
7767 // supports a general VPValue as the start value.
7768 VPValue *StartVPV =
7769 VPSCEVExpander(Builder, *PSE.getSE(), LoadR->getDebugLoc())
7770 .tryToExpand(Start);
7771 if (!StartVPV)
7772 StartVPV = VPBuilder(Plan.getEntry()).createExpandSCEV(Start);
7773 VPValue *StrideInBytes = Plan.getOrAddLiveIn(Step->getValue());
7774 Type *IndexTy = Plan.getDataLayout().getIndexType(Ptr->getScalarType());
7775 assert(IndexTy == StrideInBytes->getScalarType() &&
7776 "Stride type from SCEV must match the index type");
7777 VPValue *CanIV = Builder.createScalarSExtOrTrunc(
7778 VectorLoop->getCanonicalIV(), IndexTy,
7779 VectorLoop->getCanonicalIVType(), DebugLoc::getUnknown());
7780 auto *AddRecPtr = cast<SCEVAddRecExpr>(PtrSCEV);
7781 auto *Offset = Builder.createOverflowingOp(
7782 Instruction::Mul, {CanIV, StrideInBytes},
7783 {AddRecPtr->hasNoUnsignedWrap(), /*HasNSW=*/false});
7784 GEPNoWrapFlags NWFlags = AddRecPtr->hasNoUnsignedWrap()
7787 VPValue *BasePtr = Builder.createNoWrapPtrAdd(StartVPV, Offset, NWFlags);
7788
7789 // Create a new vector pointer for strided access.
7790 VPValue *NewPtr = Builder.createVectorPointer(
7791 BasePtr, Type::getInt8Ty(Plan.getContext()), StrideInBytes, NWFlags,
7792 LoadR->getDebugLoc());
7793
7794 VPValue *Mask = LoadR->getMask();
7795 if (!Mask)
7796 Mask = Plan.getTrue();
7797 auto *StridedLoad = Builder.createWidenMemIntrinsic(
7798 Intrinsic::experimental_vp_strided_load,
7799 {NewPtr, StrideInBytes, Mask, I32VF}, LoadTy, Alignment, *LoadR,
7800 LoadR->getDebugLoc());
7801 LoadR->replaceAllUsesWith(StridedLoad);
7802 }
7803 }
7804}
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.
R600 Clause Merge
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")
static SymbolRef::Type getType(const Symbol *Sym)
Definition TapiFile.cpp:39
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 std::optional< std::pair< bool, unsigned > > getOpcodeOrIntrinsicID(const VPSingleDefRecipe *R)
Get any instruction opcode or intrinsic ID data embedded in recipe R.
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 RemoveMask_match< Op0_t, Op1_t > m_RemoveMask(const Op0_t &In, Op1_t &Out)
Match a specific mask In, or a combination of it (logical-and In, Out).
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 void fixupVFUsersForEVL(VPlan &Plan, VPValue &EVL)
After replacing the canonical IV with a EVL-based IV, fixup recipes that use VF to use the EVL instea...
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 bool isDeadRecipe(VPRecipeBase &R)
Returns true if R is dead and can be removed.
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 std::optional< Intrinsic::ID > getVPDivRemIntrinsic(Intrinsic::ID IntrID)
static void removeRedundantExpandSCEVRecipes(VPlan &Plan)
Remove redundant ExpandSCEVRecipes in Plan's entry block by replacing them with already existing reci...
static 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...
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 VPIRValue * tryToFoldLiveIns(VPSingleDefRecipe &R, ArrayRef< VPValue * > Operands, const DataLayout &DL)
Try to fold R using InstSimplifyFolder.
static SmallVector< VPUser * > collectUsersRecursively(VPValue *V)
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 recursivelyDeleteDeadRecipes(VPValue *V)
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 VPRecipeBase * optimizeMaskToEVL(VPValue *HeaderMask, VPRecipeBase &CurRecipe, VPValue &EVL)
Try to optimize a CurRecipe masked by HeaderMask to a corresponding EVL-based recipe without the head...
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...
static ConstantInt * getSigned(IntegerType *Ty, int64_t V, bool ImplicitTrunc=false)
Return a ConstantInt with the specified value for the specified type.
Definition Constants.h:135
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.
static LLVM_ABI Constant * getAllOnesValue(Type *Ty)
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:875
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.
InstSimplifyFolder - Use InstructionSimplify to fold operations to existing values.
static InstructionCost getInvalid(CostType Val=0)
bool isCast() const
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:1654
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:4026
VPBasicBlock serves as the leaf of the Hierarchical Control-Flow Graph.
Definition VPlan.h:4361
void appendRecipe(VPRecipeBase *Recipe)
Augment the existing recipes of a VPBasicBlock with an additional Recipe as the last recipe.
Definition VPlan.h:4436
RecipeListTy::iterator iterator
Instruction iterators...
Definition VPlan.h:4388
iterator end()
Definition VPlan.h:4398
iterator begin()
Recipe iterator methods.
Definition VPlan.h:4396
iterator_range< iterator > phis()
Returns an iterator range over the PHI-like recipes in the block.
Definition VPlan.h:4449
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:560
const VPRecipeBase & front() const
Definition VPlan.h:4408
VPRecipeBase * getTerminator()
If the block has multiple successors, return the branch recipe terminating the block.
Definition VPlan.cpp:639
const VPRecipeBase & back() const
Definition VPlan.h:4410
A recipe for vectorizing a phi-node as a sequence of mask-based select instructions.
Definition VPlan.h:2938
VPValue * getIncomingValue(unsigned Idx) const
Return incoming value number Idx.
Definition VPlan.h:2983
VPValue * getMask(unsigned Idx) const
Return mask number Idx.
Definition VPlan.h:2988
unsigned getNumIncomingValues() const
Return the number of incoming values, taking into account when normalized the first incoming value wi...
Definition VPlan.h:2978
void setMask(unsigned Idx, VPValue *V)
Set mask number Idx to V.
Definition VPlan.h:2994
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:2974
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:328
static void insertOnEdge(VPBlockBase *From, VPBlockBase *To, VPBlockBase *BlockPtr)
Inserts BlockPtr on the edge between From and To.
Definition VPlanUtils.h:347
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:237
static void connectBlocks(VPBlockBase *From, VPBlockBase *To, unsigned PredIdx=-1u, unsigned SuccIdx=-1u)
Connect VPBlockBases From and To bi-directionally.
Definition VPlanUtils.h:255
static void disconnectBlocks(VPBlockBase *From, VPBlockBase *To)
Disconnect VPBlockBases From and To bi-directionally.
Definition VPlanUtils.h:273
static auto blocksOnly(T &&Range)
Return an iterator range over Range which only includes BlockTy blocks.
Definition VPlanUtils.h:309
static void transferSuccessors(VPBlockBase *Old, VPBlockBase *New)
Transfer successors from Old to New. New must have no successors.
Definition VPlanUtils.h:293
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:3481
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="")
VPValue * createScalarZExtOrTrunc(VPValue *Op, Type *ResultTy, Type *SrcTy, DebugLoc DL)
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:1641
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="")
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.
VPPhi * createScalarPhi(ArrayRef< VPValue * > IncomingValues, DebugLoc DL=DebugLoc::getUnknown(), const Twine &Name="", const VPIRFlags &Flags={}, Type *ResultTy=nullptr)
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.
A recipe for generating the phi node tracking the current scalar iteration index.
Definition VPlan.h:4058
unsigned getNumDefinedValues() const
Returns the number of values defined by the VPDef.
Definition VPlanValue.h:576
VPValue * getVPSingleValue()
Returns the only VPValue defined by the VPDef.
Definition VPlanValue.h:549
VPValue * getVPValue(unsigned I)
Returns the VPValue with index I defined by the VPDef.
Definition VPlanValue.h:561
ArrayRef< VPRecipeValue * > definedValues()
Returns an ArrayRef of the values defined by the VPDef.
Definition VPlanValue.h:571
A recipe for converting the input value IV value to the corresponding value of an IV with different s...
Definition VPlan.h:4159
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:3526
A pure virtual base class for all recipes modeling header phis, including phis for first order recurr...
Definition VPlan.h:2433
virtual VPValue * getBackedgeValue()
Returns the incoming value from the loop backedge.
Definition VPlan.h:2480
VPValue * getStartValue()
Returns the start value of the phi, if one is set.
Definition VPlan.h:2469
A recipe representing a sequence of load -> update -> store as part of a histogram operation.
Definition VPlan.h:2160
A special type of VPBasicBlock that wraps an existing IR basic block.
Definition VPlan.h:4514
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:1471
@ 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:1415
const InterleaveGroup< Instruction > * getInterleaveGroup() const
Definition VPlan.h:3089
VPValue * getMask() const
Return the mask used by this recipe.
Definition VPlan.h:3081
ArrayRef< VPValue * > getStoredValues() const
Return the VPValues stored by this interleave group.
Definition VPlan.h:3110
A recipe for interleaved memory operations with vector-predication intrinsics.
Definition VPlan.h:3162
VPInterleaveRecipe is a recipe for transforming an interleave group of load or stores into one wide l...
Definition VPlan.h:3120
void addIncoming(VPValue *IncomingV)
Append IncomingV as an incoming value to the phi-like recipe.
Definition VPlan.h:1663
VPPredInstPHIRecipe is a recipe for generating the phi nodes needed when control converges back from ...
Definition VPlan.h:3684
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:352
A recipe to represent inloop reduction operations with vector-predication intrinsics,...
Definition VPlan.h:3332
A recipe for handling reduction phis.
Definition VPlan.h:2845
void setVFScaleFactor(unsigned ScaleFactor)
Set the VFScaleFactor for this reduction phi.
Definition VPlan.h:2896
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:2889
RecurKind getRecurrenceKind() const
Returns the recurrence kind of the reduction.
Definition VPlan.h:2902
A recipe to represent inloop, ordered or partial reduction operations.
Definition VPlan.h:3213
VPRegionBlock represents a collection of VPBasicBlocks and VPRegionBlocks which form a Single-Entry-S...
Definition VPlan.h:4586
const VPBlockBase * getEntry() const
Definition VPlan.h:4630
bool isReplicator() const
An indicator whether this region is to generate multiple replicated instances of output IR correspond...
Definition VPlan.h:4662
VPRegionValue * getUsedHeaderMask() const
Return the header mask if it exists and is used, or null otherwise.
Definition VPlan.h:4718
VPInstruction * getOrCreateCanonicalIVIncrement()
Get the canonical IV increment instruction if it exists.
Definition VPlan.cpp:864
void setExiting(VPBlockBase *ExitingBlock)
Set ExitingBlock as the exiting VPBlockBase of this VPRegionBlock.
Definition VPlan.h:4647
Type * getCanonicalIVType() const
Return the type of the canonical IV for loop regions.
Definition VPlan.h:4706
void clearCanonicalIVNUW(VPInstruction *Increment)
Unsets NUW for the canonical IV increment Increment, for loop regions.
Definition VPlan.h:4745
VPRegionValue * getCanonicalIV()
Return the canonical induction variable of the region, null for replicating regions.
Definition VPlan.h:4698
const VPBlockBase * getExiting() const
Definition VPlan.h:4642
VPBasicBlock * getPreheaderVPBB()
Returns the pre-header VPBasicBlock of the loop region.
Definition VPlan.h:4655
VPRegionValue * getHeaderMask() const
Return the header mask of the region, or null if not set.
Definition VPlan.h:4711
VPReplicateRecipe replicates a given instruction producing multiple scalar copies of the original sca...
Definition VPlan.h:3377
bool isSingleScalar() const
Definition VPlan.h:3435
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:3460
bool isPredicated() const
Definition VPlan.h:3437
VPValue * getMask()
Return the mask of a predicated VPReplicateRecipe.
Definition VPlan.h:3454
Lightweight SCEV-to-VPlan expander.
Definition VPlanUtils.h:175
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:4219
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:399
operand_range operands()
Definition VPlanValue.h:472
void setOperand(unsigned I, VPValue *New)
Definition VPlanValue.h:445
unsigned getNumOperands() const
Definition VPlanValue.h:439
VPValue * getOperand(unsigned N) const
Definition VPlanValue.h:440
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:1465
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:1468
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:1474
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:2263
A recipe to compute the pointers for widened memory accesses of SourceElementTy, with the Stride expr...
Definition VPlan.h:2345
A recipe for widening Call instructions using library calls.
Definition VPlan.h:2094
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:4102
VPWidenCastRecipe is a recipe to create vector cast instructions.
Definition VPlan.h:1876
Instruction::CastOps getOpcode() const
Definition VPlan.h:1912
A recipe for handling GEP instructions.
Definition VPlan.h:2203
Base class for widened induction (VPWidenIntOrFpInductionRecipe and VPWidenPointerInductionRecipe),...
Definition VPlan.h:2507
VPIRValue * getStartValue() const
Returns the start value of the induction.
Definition VPlan.h:2555
PHINode * getPHINode() const
Returns the underlying PHINode if one exists, or null otherwise.
Definition VPlan.h:2573
VPValue * getStepValue()
Returns the step value of the induction.
Definition VPlan.h:2558
const InductionDescriptor & getInductionDescriptor() const
Returns the induction descriptor for the recipe.
Definition VPlan.h:2578
A recipe for handling phi nodes of integer and floating-point inductions, producing their vector valu...
Definition VPlan.h:2607
VPValue * getSplatVFValue() const
If the recipe has been unrolled, return the VPValue for the induction increment, otherwise return nul...
Definition VPlan.h:2655
TruncInst * getTruncInst()
Returns the first defined value as TruncInst, if it is one or nullptr otherwise.
Definition VPlan.h:2666
VPValue * getLastUnrolledPartOperand()
Returns the VPValue representing the value of this induction at the last unrolled part,...
Definition VPlan.h:2677
A recipe for widening vector intrinsics.
Definition VPlan.h:1923
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:3720
virtual VPRecipeBase * getAsRecipe()=0
Return a VPRecipeBase* to the current object.
A recipe for widened phis.
Definition VPlan.h:2735
VPWidenRecipe is a recipe for producing a widened instruction using the opcode and operands of the re...
Definition VPlan.h:1815
InstructionCost computeCost(ElementCount VF, VPCostContext &Ctx) const override
Return the cost of this VPWidenRecipe.
VPWidenRecipe * clone() override
Clone the current recipe.
Definition VPlan.h:1836
unsigned getOpcode() const
Definition VPlan.h:1855
VPlan models a candidate for vectorization, encoding various decisions take to produce efficient outp...
Definition VPlan.h:4765
VPIRValue * getLiveIn(Value *V) const
Return the live-in VPIRValue for V, if there is one or nullptr otherwise.
Definition VPlan.h:5097
bool hasVF(ElementCount VF) const
Definition VPlan.h:4990
const DataLayout & getDataLayout() const
Definition VPlan.h:4972
LLVMContext & getContext() const
Definition VPlan.h:4968
VPBasicBlock * getEntry()
Definition VPlan.h:4861
bool hasScalableVF() const
Definition VPlan.h:4991
VPValue * getTripCount() const
The trip count of the original loop.
Definition VPlan.h:4926
VPValue * getOrCreateBackedgeTakenCount()
The backedge taken count of the original loop.
Definition VPlan.h:4947
iterator_range< SmallSetVector< ElementCount, 2 >::iterator > vectorFactors() const
Returns an iterator range over all VFs of the plan.
Definition VPlan.h:4997
VPIRValue * getFalse()
Return a VPIRValue wrapping i1 false.
Definition VPlan.h:5063
VPSymbolicValue & getVFxUF()
Returns VF * UF of the vector loop region.
Definition VPlan.h:4966
VPIRValue * getAllOnesValue(Type *Ty)
Return a VPIRValue wrapping the AllOnes value of type Ty.
Definition VPlan.h:5069
VPRegionBlock * createReplicateRegion(VPBlockBase *Entry, VPBlockBase *Exiting, const std::string &Name="")
Create a new replicate region with Entry, Exiting and Name.
Definition VPlan.h:5146
auto getLiveIns() const
Return the list of live-in VPValues available in the VPlan.
Definition VPlan.h:5100
bool hasUF(unsigned UF) const
Definition VPlan.h:5015
VPIRValue * getPoison(Type *Ty)
Return a VPIRValue wrapping a poison value of type Ty.
Definition VPlan.h:5091
ArrayRef< VPIRBasicBlock * > getExitBlocks() const
Return an ArrayRef containing VPIRBasicBlocks wrapping the exit blocks of the original scalar loop.
Definition VPlan.h:4920
VPSymbolicValue & getVectorTripCount()
The vector trip count.
Definition VPlan.h:4956
VPValue * getBackedgeTakenCount() const
Definition VPlan.h:4953
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:5040
VPIRValue * getZero(Type *Ty)
Return a VPIRValue wrapping the null value of type Ty.
Definition VPlan.h:5066
void setVF(ElementCount VF)
Definition VPlan.h:4978
bool isUnrolled() const
Returns true if the VPlan already has been unrolled, i.e.
Definition VPlan.h:5031
LLVM_ABI_FOR_TEST VPRegionBlock * getVectorLoopRegion()
Returns the VPRegionBlock of the vector loop.
Definition VPlan.cpp:1060
unsigned getConcreteUF() const
Returns the concrete UF of the plan, after unrolling.
Definition VPlan.h:5018
void resetTripCount(VPValue *NewTripCount)
Resets the trip count for the VPlan.
Definition VPlan.h:4940
VPBasicBlock * getMiddleBlock()
Returns the 'middle' block of the plan, that is the block that selects whether to execute the scalar ...
Definition VPlan.h:4896
VPBasicBlock * createVPBasicBlock(const Twine &Name, VPRecipeBase *Recipe=nullptr)
Create a new VPBasicBlock with Name and containing Recipe if present.
Definition VPlan.h:5123
VPIRValue * getTrue()
Return a VPIRValue wrapping i1 true.
Definition VPlan.h:5060
VPBasicBlock * getVectorPreheader() const
Returns the preheader of the vector loop region, if one exists, or null otherwise.
Definition VPlan.h:4866
VPSymbolicValue & getUF()
Returns the UF of the vector loop region.
Definition VPlan.h:4963
bool hasScalarVFOnly() const
Definition VPlan.h:5008
VPBasicBlock * getScalarPreheader() const
Return the VPBasicBlock for the preheader of the scalar loop.
Definition VPlan.h:4910
bool hasTailFolded() const
Returns true if the vector loop region is tail-folded.
Definition VPlan.h:4882
VPSymbolicValue & getVF()
Returns the VF of the vector loop region.
Definition VPlan.h:4959
void setUF(unsigned UF)
Definition VPlan.h:5023
bool hasScalarTail() const
Returns true if the scalar tail may execute after the vector loop, i.e.
Definition VPlan.h:5188
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:1216
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:5074
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)
match_combine_or< CastInst_match< OpTy, TruncInst >, OpTy > m_TruncOrSelf(const OpTy &Op)
auto m_Poison()
Match an arbitrary poison constant.
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)
match_combine_or< CastInst_match< OpTy, ZExtInst >, OpTy > m_ZExtOrSelf(const OpTy &Op)
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))
auto m_MaskedStore(const Opnd0 &Op0, const Opnd1 &Op1, const Opnd2 &Op2)
Matches MaskedStore Intrinsic.
auto m_MaskedLoad(const Opnd0 &Op0, const Opnd1 &Op1, const Opnd2 &Op2)
Matches MaskedLoad Intrinsic.
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.
VPInstruction_match< VPInstruction::StepVector > m_StepVector()
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.
VectorEndPointerRecipe_match< Op0_t, Op1_t > m_VecEndPtr(const Op0_t &Op0, const Op1_t &Op1)
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::ExplicitVectorLength, Op0_t > m_EVL(const Op0_t &Op0)
VPInstruction_match< VPInstruction::BuildVector > m_BuildVector()
BuildVector is matches only its opcode, w/o matching its operands as the number of operands is not fi...
VPInstruction_match< VPInstruction::ExtractPenultimateElement, Op0_t > m_ExtractPenultimateElement(const Op0_t &Op0)
match_bind< VPInstruction > m_VPInstruction(VPInstruction *&V)
Match a VPInstruction, capturing if we match.
VPInstruction_match< VPInstruction::FirstActiveLane, Op0_t > m_FirstActiveLane(const Op0_t &Op0)
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.
Intrinsic::ID getIntrinsicID(const Ty *R)
Return the intrinsic ID underlying a call.
Definition VPlanUtils.h:81
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.
VPValue * findIncomingAliasMask(const VPlan &Plan)
Finds the incoming alias-mask within the vector preheader.
VPRecipeBase * findRecipe(VPValue *Start, PredT Pred)
Search Start's users for a recipe satisfying Pred, looking through recipes with definitions.
Definition VPlanUtils.h:133
bool isElementwise(const VPValue *V)
Return true if V is elementwise, i.e. none of the lanes are permuted.
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.
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.
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:385
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:1859
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
@ Default
The result value is uniform if and only if all operands are uniform.
Definition Uniformity.h:20
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
RemoveMask_match(const Op0_t &In, Op1_t &Out)
bool match(OpTy *V) const
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:2827
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:1955
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:277
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 with vector-predication intrinsics, using the address to load f...
Definition VPlan.h:3834
A recipe for widening load operations, using the address to load from and an optional mask.
Definition VPlan.h:3784
A recipe for widening store operations with vector-predication intrinsics, using the value to store,...
Definition VPlan.h:3937
A recipe for widening store operations, using the stored value, the address to store to and an option...
Definition VPlan.h:3883
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 bool simplifyKnownEVL(VPlan &Plan, ElementCount VF, PredicatedScalarEvolution &PSE)
Try to simplify VPInstruction::ExplicitVectorLength recipes when the AVL is known to be <= VF,...
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 convertToVariableLengthStep(VPlan &Plan)
Transform loops with variable-length stepping after region dissolution.
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 addExplicitVectorLength(VPlan &Plan, const std::optional< unsigned > &MaxEVLSafeElements)
Add a VPCurrentIterationPHIRecipe and related recipes to Plan and replaces all uses of the canonical ...
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 optimizeEVLMasks(VPlan &Plan)
Optimize recipes which use an EVL-based header mask to VP intrinsics, for example:
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.
static void convertEVLExitCond(VPlan &Plan)
Replaces the exit condition from (branch-on-cond eq CanonicalIVInc, VectorTripCount) to (branch-on-co...