LLVM 24.0.0git
LoopVectorizationPlanner.h
Go to the documentation of this file.
1//===- LoopVectorizationPlanner.h - Planner for LoopVectorization ---------===//
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 provides a LoopVectorizationPlanner class.
11/// InnerLoopVectorizer vectorizes loops which contain only one basic
12/// LoopVectorizationPlanner - drives the vectorization process after having
13/// passed Legality checks.
14/// The planner builds and optimizes the Vectorization Plans which record the
15/// decisions how to vectorize the given loop. In particular, represent the
16/// control-flow of the vectorized version, the replication of instructions that
17/// are to be scalarized, and interleave access groups.
18///
19/// Also provides a VPlan-based builder utility analogous to IRBuilder.
20/// It provides an instruction-level API for generating VPInstructions while
21/// abstracting away the Recipe manipulation details.
22//===----------------------------------------------------------------------===//
23
24#ifndef LLVM_TRANSFORMS_VECTORIZE_LOOPVECTORIZATIONPLANNER_H
25#define LLVM_TRANSFORMS_VECTORIZE_LOOPVECTORIZATIONPLANNER_H
26
27#include "VPlan.h"
28#include "VPlanUtils.h"
29#include "llvm/ADT/SmallSet.h"
32#include <optional>
33
34namespace {
35class GeneratedRTChecks;
36}
37
38namespace llvm {
39
41class LoopInfo;
42class DominatorTree;
50struct VPRegisterUsage;
51struct VFRange;
52struct VectorizeOptions;
53
54/// \return An upper bound for vscale based on TTI or the vscale_range
55/// attribute.
56std::optional<unsigned> getMaxVScale(const Function &F);
57
58/// \return The upper bound for the runtime value of \p EC, or std::nullopt
59/// if the upper bound is unknown.
60std::optional<uint64_t>
62
63// Utility functions that are used by different vectorization classes
65
66/// Reports a vectorization failure: print \p DebugMsg for debugging
67/// purposes along with the corresponding optimization remark \p RemarkName.
68/// If \p I is passed, it is an instruction that prevents vectorization.
69/// Otherwise, the loop \p TheLoop is used for the location of the remark.
70void reportVectorizationFailure(const StringRef DebugMsg,
71 const StringRef OREMsg, const StringRef ORETag,
73 const Loop *TheLoop, Instruction *I = nullptr);
74
75/// Same as above, but the debug message and optimization remark are identical
76inline void reportVectorizationFailure(const StringRef DebugMsg,
77 const StringRef ORETag,
79 const Loop *TheLoop,
80 Instruction *I = nullptr) {
81 reportVectorizationFailure(DebugMsg, DebugMsg, ORETag, ORE, TheLoop, I);
82}
83
84/// Reports an informative message: print \p Msg for debugging purposes as well
85/// as an optimization remark. Uses either \p I as location of the remark, or
86/// otherwise \p TheLoop. If \p DL is passed, use it as debug location for the
87/// remark.
88void reportVectorizationInfo(const StringRef Msg, const StringRef ORETag,
90 const Loop *TheLoop, Instruction *I = nullptr,
91 DebugLoc DL = {});
92
93/// Report successful vectorization of the loop. In case an outer loop is
94/// vectorized, prepend "outer" to the vectorization remark.
95void reportVectorization(OptimizationRemarkEmitter *ORE, Loop *TheLoop,
96 ElementCount VFWidth, unsigned IC);
97
98} // namespace LoopVectorizationUtils
99
100/// Default inserter for VPBuilderBase, inserting \p R before \p It.
103 R->insertBefore(It);
104 }
105};
106
107/// VPlan-based builder utility similar to IRBuilder. Recipes are inserted via
108/// \p InserterTy.
109template <typename InserterTy> class VPBuilderBase : public InserterTy {
110private:
111 class VPInsertPoint {
112 VPBasicBlock::iterator Iterator;
113
114 public:
115 /// Creates a new insertion point which doesn't point to anything.
116 VPInsertPoint() = default;
117
118 /// Creates a new insertion point to insert before \p Iterator.
119 VPInsertPoint(VPBasicBlock::iterator Iterator) : Iterator(Iterator) {}
120
121 /// Creates a new insertion point to insert before \p R.
122 VPInsertPoint(VPRecipeBase *R) : Iterator(R->getIterator()) {}
123
124 /// Creates a new insertion point to insert at the end of \p Block.
125 VPInsertPoint(VPBasicBlock *Block) : Iterator(Block->end()) {}
126
127 /// Returns true if this insert point is set.
128 operator bool() const { return Iterator.isValid(); }
129
130 VPBasicBlock *getBlock() const {
131 return Iterator.isValid() ? Iterator.getNodeParent() : nullptr;
132 }
133 VPBasicBlock::iterator getIterator() const { return Iterator; }
134
135 operator VPRecipeBase *() const {
136 return Iterator == getBlock()->end() ? nullptr : &*Iterator;
137 }
138 };
139
140 VPInsertPoint InsertPt;
141
142protected:
143 /// Insert \p R at InsertPt if InsertPt is set.
144 template <typename T> T *tryInsertInstruction(T *R) {
145 if (InsertPt)
146 InserterTy::insertHelper(R, InsertPt.getIterator());
147 return R;
148 }
149
152 const VPIRMetadata &MD, DebugLoc DL,
153 const Twine &Name = "") {
155 new VPInstruction(Opcode, Operands, {}, MD, DL, Name));
156 }
157
158public:
159 VPlan &getPlan() const {
160 assert(InsertPt && "Insert block must be set");
161 return *InsertPt.getBlock()->getPlan();
162 }
163
164 VPBuilderBase() = default;
165 VPBuilderBase(const VPInsertPoint &IP) : InsertPt(IP) {}
166 VPBuilderBase(InserterTy Inserter) : InserterTy(Inserter) {}
167
168 /// Get the recipe at the current insert point or nullptr if the insert point
169 /// is the end of the block.
170 VPRecipeBase *getRecipeAtInsertPoint() const { return InsertPt; }
171
172 VPBasicBlock *getInsertBlock() const { return InsertPt.getBlock(); }
173
174 /// Create a builder to insert after \p R.
176 return VPBuilderBase(std::next(R->getIterator()));
177 }
178
179 /// Sets the current insert point to a previously-saved location.
180 void restoreIP(VPInsertPoint IP) { InsertPt = IP; }
181
182 /// Set the current insert point.
183 void setInsertPoint(const VPInsertPoint &IP) {
184 assert(IP && "Attempting to set a null insert point");
185 InsertPt = IP;
186 }
187
188 /// Insert \p R at the current insertion point. Returns \p R unchanged.
189 template <typename T> [[maybe_unused]] T *insert(T *R) {
190 InserterTy::insertHelper(R, InsertPt.getIterator());
191 return R;
192 }
193
194 /// Create an N-ary operation with \p Opcode, \p Operands and set \p Inst as
195 /// its underlying Instruction.
197 Instruction *Inst = nullptr,
198 const VPIRFlags &Flags = {},
199 const VPIRMetadata &MD = {},
201 const Twine &Name = "", Type *ResultTy = nullptr,
202 const VPIRAttributes &Attrs = {}) {
203 VPInstruction *NewVPInst = tryInsertInstruction(new VPInstruction(
204 Opcode, Operands, Flags, MD, DL, Name, ResultTy, Attrs));
205 NewVPInst->setUnderlyingValue(Inst);
206 return NewVPInst;
207 }
209 DebugLoc DL, const Twine &Name = "") {
210 return createInstruction(Opcode, Operands, {}, DL, Name);
211 }
213 const VPIRFlags &Flags,
215 const Twine &Name = "") {
217 new VPInstruction(Opcode, Operands, Flags, {}, DL, Name));
218 }
219
221 Type *ResultTy, const VPIRFlags &Flags = {},
223 const Twine &Name = "") {
225 new VPInstruction(Opcode, Operands, Flags, {}, DL, Name, ResultTy));
226 }
227
230 const Twine &Name = "") {
231 // Assume that the maximum possible number of elements in a vector fits
232 // within the index type for the default address space.
233 VPlan &Plan = getPlan();
234 Type *IndexTy = Plan.getDataLayout().getIndexType(Plan.getContext(), 0);
236 VPInstruction::FirstActiveLane, Masks, {}, {}, DL, Name, IndexTy));
237 }
238
241 const Twine &Name = "") {
242 // Assume that the maximum possible number of elements in a vector fits
243 // within the index type for the default address space.
244 VPlan &Plan = getPlan();
245 Type *IndexTy = Plan.getDataLayout().getIndexType(Plan.getContext(), 0);
247 VPInstruction::LastActiveLane, Masks, {}, {}, DL, Name, IndexTy));
248 }
249
251 unsigned Opcode, ArrayRef<VPValue *> Operands,
252 VPRecipeWithIRFlags::WrapFlagsTy WrapFlags = {false, false},
253 DebugLoc DL = DebugLoc::getUnknown(), const Twine &Name = "") {
255 new VPInstruction(Opcode, Operands, WrapFlags, {}, DL, Name));
256 }
257
260 const Twine &Name = "") {
261 return createInstruction(VPInstruction::Not, {Operand}, {}, DL, Name);
262 }
263
266 const Twine &Name = "") {
267 return createInstruction(Instruction::BinaryOps::And, {LHS, RHS}, {}, DL,
268 Name);
269 }
270
273 const Twine &Name = "") {
274
276 Instruction::BinaryOps::Or, {LHS, RHS},
277 VPRecipeWithIRFlags::DisjointFlagsTy(false), {}, DL, Name));
278 }
279
282 const Twine &Name = "",
283 VPRecipeWithIRFlags::WrapFlagsTy WrapFlags = {false, false}) {
284 return createOverflowingOp(Instruction::Add, {LHS, RHS}, WrapFlags, DL,
285 Name);
286 }
287
288 VPInstruction *
290 const Twine &Name = "",
291 VPRecipeWithIRFlags::WrapFlagsTy WrapFlags = {false, false}) {
292 return createOverflowingOp(Instruction::Sub, {LHS, RHS}, WrapFlags, DL,
293 Name);
294 }
295
301
307
308 /// Create a select of \p TrueVal and \p FalseVal based on \p Cond, using the
309 /// default flags for the result type, unless \p Flags is set.
311 VPValue *FalseVal,
313 const Twine &Name = "",
314 std::optional<VPIRFlags> Flags = std::nullopt) {
316 new VPInstruction(Instruction::Select, {Cond, TrueVal, FalseVal},
317 Flags.value_or(VPIRFlags::getDefaultFlags(
318 Instruction::Select, TrueVal->getScalarType())),
319 {}, DL, Name));
320 }
321
322 /// Create a new ICmp VPInstruction with predicate \p Pred and operands \p A
323 /// and \p B.
326 const Twine &Name = "") {
328 Pred <= CmpInst::LAST_ICMP_PREDICATE && "invalid predicate");
330 new VPInstruction(Instruction::ICmp, {A, B}, Pred, {}, DL, Name));
331 }
332
333 /// Create a new FCmp VPInstruction with predicate \p Pred and operands \p A
334 /// and \p B.
337 const Twine &Name = "") {
339 Pred <= CmpInst::LAST_FCMP_PREDICATE && "invalid predicate");
341 new VPInstruction(Instruction::FCmp, {A, B},
342 VPIRFlags(Pred, FastMathFlags()), {}, DL, Name));
343 }
344
345 /// Create an AnyOf reduction pattern: or-reduce \p ChainOp, freeze the
346 /// result, then select between \p TrueVal and \p FalseVal.
348 VPValue *FalseVal,
350 assert(ChainOp->getScalarType()->isIntegerTy(1) &&
351 "ChainOp must be i1 for AnyOf reduction");
352 VPIRFlags Flags(RecurKind::Or, /*IsOrdered=*/false, /*IsInLoop=*/false,
353 FastMathFlags());
355 {ChainOp}, Flags, DL);
356 auto *Freeze = createNaryOp(Instruction::Freeze, {OrReduce}, DL);
357 return createSelect(Freeze, TrueVal, FalseVal, DL, "rdx.select");
358 }
359
362 const Twine &Name = "") {
363 return createNoWrapPtrAdd(Ptr, Offset, GEPNoWrapFlags::none(), DL, Name);
364 }
365
367 GEPNoWrapFlags GEPFlags,
369 const Twine &Name = "") {
371 VPInstruction::PtrAdd, {Ptr, Offset}, GEPFlags, {}, DL, Name));
372 }
373
381
382 /// Create a phi with \p IncomingValues, using the default flags for the
383 /// result type, unless \p Flags is set.
386 const Twine &Name = "",
387 std::optional<VPIRFlags> Flags = std::nullopt,
388 Type *ResultTy = nullptr) {
389 Type *ScalarTy = ResultTy ? ResultTy : IncomingValues[0]->getScalarType();
390 return tryInsertInstruction(new VPPhi(
391 IncomingValues,
392 Flags.value_or(VPIRFlags::getDefaultFlags(Instruction::PHI, ScalarTy)),
393 DL, Name, ResultTy));
394 }
395
398 const Twine &Name = "") {
399 return tryInsertInstruction(new VPWidenPHIRecipe(IncomingValues, DL, Name));
400 }
401
403 VPlan &Plan = getPlan();
404 unsigned MinEC = EC.getKnownMinValue();
405 if (EC.isScalable()) {
406 VPValue *VScale = createVScale(Ty);
407 if (MinEC == 1)
408 return VScale;
409 // TODO: Move this optimization into createOverflowingOp directly.
410 if (isPowerOf2_32(MinEC)) {
411 VPValue *ShtAmt = Plan.getConstantInt(Ty, Log2_32(MinEC));
412 return createOverflowingOp(Instruction::Shl, {VScale, ShtAmt},
413 {true, false});
414 }
415 VPValue *MulAmt = Plan.getConstantInt(Ty, MinEC);
416 return createOverflowingOp(Instruction::Mul, {VScale, MulAmt},
417 {true, false});
418 }
419 return Plan.getConstantInt(Ty, MinEC);
420 }
421
422 /// Convert \p Current to \p Start + \p Current * \p Step.
424 FPMathOperator *FPBinOp, VPValue *Start,
425 VPValue *Current, VPValue *Step,
426 const VPIRFlags::WrapFlagsTy &Flags = {}) {
428 new VPDerivedIVRecipe(Kind, FPBinOp, Start, Current, Step, Flags));
429 }
430
432 Type *ResultTy, DebugLoc DL,
433 std::optional<VPIRFlags> Flags = std::nullopt,
434 const VPIRMetadata &Metadata = {}) {
436 Opcode, Op, Flags.value_or(VPIRFlags::getDefaultFlags(Opcode)),
437 Metadata, DL, "", ResultTy));
438 }
439
440 /// Create a scalar call to the intrinsic \p IntrinsicID with \p Operands, and
441 /// result type \p ResultTy
444 Type *ResultTy, DebugLoc DL,
445 const Twine &Name = "") {
446 VPlan &Plan = getPlan();
448 Ops.push_back(Plan.getConstantInt(8 * sizeof(IntrinsicID), IntrinsicID));
450 {}, {}, DL, Name, ResultTy));
451 }
452
453 /// Create a scalar llvm.vscale call.
456 return createScalarIntrinsic(Intrinsic::vscale, {}, ResultTy, DL);
457 }
458
460 Type *SrcTy = Op->getScalarType();
461 if (ResultTy == SrcTy)
462 return Op;
463 Instruction::CastOps CastOp =
464 ResultTy->getScalarSizeInBits() < SrcTy->getScalarSizeInBits()
465 ? Instruction::Trunc
466 : Instruction::ZExt;
467 return createScalarCast(CastOp, Op, ResultTy, DL);
468 }
469
471 Type *SrcTy = Op->getScalarType();
472 if (ResultTy == SrcTy)
473 return Op;
474 Instruction::CastOps CastOp =
475 ResultTy->getScalarSizeInBits() < SrcTy->getScalarSizeInBits()
476 ? Instruction::Trunc
477 : Instruction::SExt;
478 return createScalarCast(CastOp, Op, ResultTy, DL);
479 }
480
482 const Twine &Name = "") {
483 return createNaryOp(Instruction::Freeze, Op, DL, Name);
484 }
485
487 Type *ResultTy) {
488 assert(Op->getScalarType() != ResultTy &&
489 "must not create a no-op cast recipe");
491 Opcode, Op, ResultTy, nullptr, VPIRFlags::getDefaultFlags(Opcode)));
492 }
493
494 /// Create a single-scalar recipe with \p Opcode and \p Operands without
495 /// inserting it.
496 static VPSingleDefRecipe *
498 VPValue *Mask, const VPIRFlags &Flags,
500 Type *ResultTy, Instruction *UV) {
501 if (Instruction::isCast(Opcode)) {
502 assert(!Mask && "Cast cannot be predicated");
503 auto *VPI = new VPInstruction(Opcode, Operands, Flags, Metadata, DL,
504 UV->getName(), ResultTy);
505 VPI->setUnderlyingValue(UV);
506 return VPI;
507 }
508 auto *RepR = new VPReplicateRecipe(UV, Operands, /*IsSingleScalar=*/true,
509 Mask, Flags, Metadata, DL);
510 assert(RepR->getScalarType() == ResultTy && "unexpected result type");
511 return RepR;
512 }
513
516 FPMathOperator *FPBinOp, VPValue *IV, VPValue *Step,
517 VPValue *VF, DebugLoc DL) {
519 IV, Step, VF, InductionOpcode,
520 FPBinOp ? FPBinOp->getFastMathFlags() : FastMathFlags(), DL));
521 }
522
526
528 createVectorPointer(VPValue *Ptr, Type *SourceElementTy, VPValue *Stride,
529 GEPNoWrapFlags GEPFlags, DebugLoc DL) {
531 new VPVectorPointerRecipe(Ptr, SourceElementTy, Stride, GEPFlags, DL));
532 }
533
534 /// Create a vector pointer recipe for a consecutive memory access to \p Ptr
535 /// with element type \p SourceElementTy.
537 Type *SourceElementTy,
538 bool Reverse, DebugLoc DL) {
539 VPlan &Plan = getPlan();
541 if (Reverse) {
542 // When folding the tail, we may compute an address that we don't in the
543 // original scalar loop: drop the GEP no-wrap flags in this case.
544 // Otherwise preserve existing flags without no-unsigned-wrap, as we will
545 // emit negative indices.
546 GEPNoWrapFlags ReverseFlags = Plan.hasTailFolded()
548 : Flags.withoutNoUnsignedWrap();
550 new VPVectorEndPointerRecipe(Ptr, &Plan.getVF(), SourceElementTy,
551 /*Stride=*/-1, ReverseFlags, DL));
552 }
553 Type *StrideTy = Plan.getDataLayout().getIndexType(Ptr->getScalarType());
554 VPValue *StrideOne = Plan.getConstantInt(StrideTy, 1);
555 return createVectorPointer(Ptr, SourceElementTy, StrideOne, Flags, DL);
556 }
557
559 Intrinsic::ID VectorIntrinsicID, ArrayRef<VPValue *> CallArguments,
560 Type *Ty, Align Alignment, const VPIRMetadata &MD, DebugLoc DL) {
562 VectorIntrinsicID, CallArguments, Ty, Alignment, MD, DL));
563 }
564
565 /// Create a recipe widening \p Load, loading from \p Addr with \p Mask (may
566 /// be null).
568 VPValue *Mask, bool Consecutive,
569 Align Alignment,
570 const VPIRMetadata &Metadata,
571 DebugLoc DL) {
573 Load, Addr, Mask, Consecutive, Alignment, Metadata, DL));
574 }
575
576 /// Create a recipe widening \p Store, storing \p StoredVal to \p Addr with
577 /// \p Mask (may be null).
579 VPValue *StoredVal, VPValue *Mask,
580 bool Consecutive, Align Alignment,
581 const VPIRMetadata &Metadata,
582 DebugLoc DL) {
584 Store, Addr, StoredVal, Mask, Consecutive, Alignment, Metadata, DL));
585 }
586
587 //===--------------------------------------------------------------------===//
588 // RAII helpers.
589 //===--------------------------------------------------------------------===//
590
591 /// RAII object that stores the current insertion point and restores it when
592 /// the object is destroyed.
594 VPBuilderBase &Builder;
595 VPInsertPoint InsertPt;
596
597 public:
598 InsertPointGuard(VPBuilderBase &B) : Builder(B), InsertPt(B.InsertPt) {}
599
602
603 ~InsertPointGuard() { Builder.restoreIP(InsertPt); }
604 };
605};
606
607/// TODO: The following VectorizationFactor was pulled out of
608/// LoopVectorizationCostModel class. LV also deals with
609/// VectorizerParams::VectorizationFactor.
610/// We need to streamline them.
611
612/// Information about vectorization costs.
614 /// Vector width with best cost.
616
617 /// Cost of the loop with that width.
619
620 /// Cost of the scalar loop.
622
623 /// The minimum trip count required to make vectorization profitable, e.g. due
624 /// to runtime checks.
626
630
631 /// Width 1 means no vectorization, cost 0 means uncomputed cost.
633 return {ElementCount::getFixed(1), 0, 0};
634 }
635};
636
637/// A class that represents two vectorization factors (initialized with 0 by
638/// default). One for fixed-width vectorization and one for scalable
639/// vectorization. This can be used by the vectorizer to choose from a range of
640/// fixed and/or scalable VFs in order to find the most cost-effective VF to
641/// vectorize with.
645
647 : FixedVF(ElementCount::getFixed(0)),
648 ScalableVF(ElementCount::getScalable(0)) {}
650 *(Max.isScalable() ? &ScalableVF : &FixedVF) = Max;
651 }
655 assert(!FixedVF.isScalable() && ScalableVF.isScalable() &&
656 "Invalid scalable properties");
657 }
658
660
661 /// \return true if either fixed- or scalable VF is non-zero.
662 explicit operator bool() const { return FixedVF || ScalableVF; }
663};
664
665/// Holds state needed to make cost decisions before computing costs per-VF,
666/// including the maximum VFs.
668 /// \return True if maximizing vector bandwidth is enabled by the target or
669 /// user options, for the given register kind (scalable or fixed-width).
670 bool useMaxBandwidth(bool IsScalable) const;
671
672 /// \return the maximized element count based on the targets vector
673 /// registers and the loop trip-count, but limited to a maximum safe VF.
674 /// This is a helper function of computeFeasibleMaxVF.
675 ElementCount getMaximizedVFForTarget(unsigned MaxTripCount,
676 unsigned SmallestType,
677 unsigned WidestType,
678 ElementCount MaxSafeVF, unsigned UserIC,
679 bool FoldTailByMasking,
680 bool RequiresScalarEpilogue);
681
682 /// If \p VF * \p UserIC > MaxTripcount, clamps VF to the next lower VF
683 /// that results in VF * UserIC <= MaxTripCount.
684 ElementCount clampVFByMaxTripCount(ElementCount VF, unsigned MaxTripCount,
685 unsigned UserIC, bool FoldTailByMasking,
686 bool RequiresScalarEpilogue) const;
687
688 /// Checks if scalable vectorization is supported and enabled. Caches the
689 /// result to avoid repeated debug dumps for repeated queries.
690 bool isScalableVectorizationAllowed();
691
692 /// \return the maximum legal scalable VF, based on the safe max number
693 /// of elements.
694 ElementCount getMaxLegalScalableVF(unsigned MaxSafeElements);
695
696 /// Initializes the value of vscale used for tuning the cost model. If
697 /// vscale_range.min == vscale_range.max then return vscale_range.max, else
698 /// return the value returned by the corresponding TTI method.
699 void initializeVScaleForTuning();
700
701 const VectorizeOptions &Opts;
702 const TargetTransformInfo &TTI;
703 const LoopVectorizationLegality *Legal;
704 const Loop *TheLoop;
705 const Function &F;
707 DemandedBits *DB;
709 const LoopVectorizeHints *Hints;
710
711 /// Cached result of isScalableVectorizationAllowed.
712 std::optional<bool> IsScalableVectorizationAllowed;
713
714 /// Used to store the value of vscale used for tuning the cost model. It is
715 /// initialized during object construction.
716 std::optional<unsigned> VScaleForTuning;
717
718 /// The highest VF possible for this loop, without using MaxBandwidth.
719 FixedScalableVFPair MaxPermissibleVFWithoutMaxBW;
720
721 /// All element types found in the loop.
722 SmallPtrSet<Type *, 16> ElementTypesInLoop;
723
724 /// PHINodes of the reductions that should be expanded in-loop. Set by
725 /// collectInLoopReductions.
726 SmallPtrSet<PHINode *, 4> InLoopReductions;
727
728 /// Maximum safe number of elements to be processed per vector iteration,
729 /// which do not prevent store-load forwarding and are safe with regard to the
730 /// memory dependencies. Required for EVL-based vectorization, where this
731 /// value is used as the upper bound of the safe AVL. Set by
732 /// computeFeasibleMaxVF.
733 std::optional<unsigned> MaxSafeElements;
734
735 /// Map of scalar integer values to the smallest bitwidth they can be legally
736 /// represented as. The vector equivalents of these values should be truncated
737 /// to this type.
739
740public:
741 /// The kind of cost that we are calculating.
743
744 /// Whether this loop should be optimized for size based on function attribute
745 /// or profile information.
746 const bool OptForSize;
747
748 VFSelectionContext(const VectorizeOptions &Opts,
749 const TargetTransformInfo &TTI,
750 const LoopVectorizationLegality *Legal,
751 const Loop *TheLoop, const Function &F,
754 const LoopVectorizeHints *Hints, bool OptForSize)
755 : Opts(Opts), TTI(TTI), Legal(Legal), TheLoop(TheLoop), F(F), PSE(PSE),
756 DB(DB), ORE(ORE), Hints(Hints),
757 CostKind(F.hasMinSize() ? TTI::TCK_CodeSize : TTI::TCK_RecipThroughput),
759 initializeVScaleForTuning();
760 }
761
762 /// \return The vscale value used for tuning the cost model.
763 std::optional<unsigned> getVScaleForTuning() const { return VScaleForTuning; }
764
765 const VectorizeOptions &getOpts() const { return Opts; }
766
767 const TargetTransformInfo &getTTI() const { return TTI; }
768
769 PredicatedScalarEvolution &getPSE() const { return PSE; }
770
771 /// \return The loop being analyzed.
772 const Loop *getLoop() const { return TheLoop; }
773
774 /// \return The vectorization hints for the loop being analyzed.
775 const LoopVectorizeHints &getHints() const { return *Hints; }
776
777 /// Returns true if epilogue vectorization is considered profitable for a
778 /// main loop with vectorization factor \p VF and interleave count \p IC.
779 bool isEpilogueVectorizationProfitable(ElementCount VF, unsigned IC) const;
780
781 /// \return True if register pressure should be considered for the given VF.
783
784 /// \return True if scalable vectors are supported by the target or forced.
785 bool supportsScalableVectors() const;
786
787 /// Collect element types in the loop that need widening.
789 const SmallPtrSetImpl<const Value *> *ValuesToIgnore = nullptr);
790
791 /// \return The size (in bits) of the smallest and widest types in the code
792 /// that need to be vectorized. We ignore values that remain scalar such as
793 /// 64 bit loop indices.
794 std::pair<unsigned, unsigned> getSmallestAndWidestTypes() const;
795
796 /// \return An upper bound for the vectorization factors for both
797 /// fixed and scalable vectorization, where the minimum-known number of
798 /// elements is a power-of-2 larger than zero. If scalable vectorization is
799 /// disabled or unsupported, then the scalable part will be equal to
800 /// ElementCount::getScalable(0). Also sets MaxSafeElements.
801 FixedScalableVFPair computeFeasibleMaxVF(unsigned MaxTripCount,
802 ElementCount UserVF, unsigned UserIC,
803 bool FoldTailByMasking,
804 bool RequiresScalarEpilogue);
805
806 /// Return maximum safe number of elements to be processed per vector
807 /// iteration, which do not prevent store-load forwarding and are safe with
808 /// regard to the memory dependencies. Required for EVL-based VPlans to
809 /// correctly calculate AVL (application vector length) as min(remaining AVL,
810 /// MaxSafeElements). Set by computeFeasibleMaxVF.
811 /// TODO: need to consider adjusting cost model to use this value as a
812 /// vectorization factor for EVL-based vectorization.
813 std::optional<unsigned> getMaxSafeElements() const { return MaxSafeElements; }
814
815 /// Returns true if we should use strict in-order reductions for the given
816 /// RdxDesc. This is true if the -enable-strict-reductions flag is passed,
817 /// the IsOrdered flag of RdxDesc is set and we do not allow reordering
818 /// of FP operations.
819 bool useOrderedReductions(const RecurrenceDescriptor &RdxDesc) const;
820
821 /// Returns true if the target machine supports a masked load (if \p IsLoad)
822 /// or masked store of scalar type \p ScalarTy with \p Alignment in address
823 /// space \p AddressSpace. The caller must ensure the access is consecutive or
824 /// part of an interleave group.
825 bool isLegalMaskedLoadOrStore(bool IsLoad, Type *ScalarTy, Align Alignment,
826 unsigned AddressSpace) const;
827
828 /// Returns true if the target machine supports a gather (if \p IsLoad)
829 /// or scatter of scalar type \p ScalarTy with \p Alignment for vectorization
830 /// factor \p VF.
831 bool isLegalGatherOrScatter(bool IsLoad, Type *ScalarTy, Align Alignment,
832 ElementCount VF) const;
833
834 /// Split reductions into those that happen in the loop, and those that
835 /// happen outside. In-loop reductions are collected into InLoopReductions.
837
838 /// Returns true if the Phi is part of an inloop reduction.
839 bool isInLoopReduction(PHINode *Phi) const {
840 return InLoopReductions.contains(Phi);
841 }
842
843 /// Returns the set of in-loop reduction PHIs.
845 return InLoopReductions;
846 }
847
848 /// Check whether vectorization would require runtime checks. When optimizing
849 /// for size, returning true here aborts vectorization.
851
852 /// Returns a scalable VF to use for outer-loop vectorization if the target
853 /// supports it and a fixed VF otherwise.
855
856 /// Compute smallest bitwidth each instruction can be represented with.
857 /// The vector equivalents of these instructions should be truncated to this
858 /// type.
860
861 /// \returns The smallest bitwidth each instruction can be represented with.
863 return MinBWs;
864 }
865};
866
867/// Planner drives the vectorization process after having passed
868/// Legality checks.
870 const VectorizeOptions &Opts;
871
872 /// The loop that we evaluate.
873 Loop *OrigLoop;
874
875 /// Loop Info analysis.
876 LoopInfo *LI;
877
878 /// The dominator tree.
879 DominatorTree *DT;
880
881 /// Target Library Info.
882 const TargetLibraryInfo *TLI;
883
884 /// Target Transform Info.
885 const TargetTransformInfo &TTI;
886
887 /// The legality analysis.
889
890 /// The profitability analysis. Cleared after making cost based decisions.
891 /// This instance should never be used in any function that takes an explicit
892 /// PlanCM reference, since that instance overrides this one.
893 std::unique_ptr<LoopVectorizationCostModel> CM;
894
895 /// VF selection state independent of cost-modeling decisions.
896 VFSelectionContext &Config;
897
899
901
902 /// Lazily fetch BranchProbabilityInfo, independent of BlockFrequencyInfo.
903 std::function<const BranchProbabilityInfo &()> GetBPI;
904
906
907 /// Profitable vector factors.
909
910 /// A builder used to construct the current plan.
911 VPBuilder Builder;
912
913 /// Computes the cost of \p Plan for vectorization factor \p VF, using
914 /// \p PlanCM as the cost model.
915 ///
916 /// The current implementation requires access to the
917 /// LoopVectorizationLegality to handle inductions and reductions, which is
918 /// why it is kept separate from the VPlan-only cost infrastructure.
919 ///
920 /// TODO: Move to VPlan::cost once the use of LoopVectorizationLegality has
921 /// been retired.
923 LoopVectorizationCostModel &PlanCM) const;
924
925 /// Precompute costs for certain instructions using the legacy cost model. The
926 /// function is used to bring up the VPlan-based cost model to initially avoid
927 /// taking different decisions due to inaccuracies in the legacy cost model.
928 InstructionCost precomputeCosts(VPlan &Plan, ElementCount VF,
929 VPCostContext &CostCtx) const;
930
931public:
933 Loop *L, LoopInfo *LI, DominatorTree *DT, const TargetLibraryInfo *TLI,
935 std::unique_ptr<LoopVectorizationCostModel> CM,
938 std::function<const BranchProbabilityInfo &()> GetBPI);
939
941
942 /// Return the cost model. Must not be called after clearCostModel().
944 assert(CM && "Cost model has already been cleared");
945 return *CM;
946 }
947
948 /// Destroy the cost model.
949 void clearCostModel();
950
951 /// Return true if there is at least one VPlan for a vector VF
952 bool hasVectorPlan() const {
953 return any_of(
954 VPlans, [&](const VPlanPtr &Plan) { return !Plan->hasScalarVFOnly(); });
955 }
956
957 /// Returns true if there is at least one VPlan.
958 bool hasAPlan() const { return !VPlans.empty(); }
959
960 /// Build VPlans for the specified \p UserVF and \p UserIC if they are
961 /// non-zero or all applicable candidate VFs otherwise. If vectorization and
962 /// interleaving should be avoided up-front, no plans are generated.
963 void plan(ElementCount UserVF, unsigned UserIC);
964
965 /// Return the VPlan for \p VF. At the moment, there is always a single VPlan
966 /// for each VF.
967 VPlan &getPlanFor(ElementCount VF) const;
968
969 /// Compute and return the most profitable vectorization factor and the
970 /// corresponding best VPlan. Also collect all profitable VFs in
971 /// ProfitableVFs.
972 std::pair<VectorizationFactor, VPlan *> computeBestVF();
973
974 /// \return The desired interleave count.
975 /// If interleave count has been specified by metadata it will be returned.
976 /// Otherwise, the interleave count is computed and returned. VF and LoopCost
977 /// are the selected vectorization factor and the cost of the selected VF.
978 unsigned selectInterleaveCount(VPlan &Plan, ElementCount VF,
979 InstructionCost LoopCost);
980
981 /// Generate the IR code for the vectorized loop captured in VPlan \p BestPlan
982 /// according to the best selected \p VF and \p UF.
983 ///
984 /// TODO: \p EpilogueVecKind should be removed once the re-use issue has been
985 /// fixed.
986 ///
987 /// When vectorizing the main loop, \p TrackedBlocks are updated to the
988 /// VPIRBasicBlocks wrapping the blocks generated for them.
989 ///
990 /// Returns a mapping of SCEVs to their expanded IR values.
991 /// Note that this is a temporary workaround needed due to the current
992 /// epilogue handling.
994 None, ///< Not part of epilogue vectorization.
995 MainLoop, ///< Vectorizing the main loop of epilogue vectorization.
996 Epilogue ///< Vectorizing the epilogue loop.
997 };
999 executePlan(ElementCount VF, unsigned UF, VPlan &BestPlan,
1001 EpilogueVectorizationKind EpilogueVecKind =
1003 MutableArrayRef<VPBasicBlock *> TrackedBlocks = {});
1004
1005#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
1006 void printPlans(raw_ostream &O);
1007#endif
1008
1009 /// Look through the existing plans and return true if we have one with
1010 /// vectorization factor \p VF.
1012 return any_of(VPlans,
1013 [&](const VPlanPtr &Plan) { return Plan->hasVF(VF); });
1014 }
1015
1016 /// Test a \p Predicate on a \p Range of VF's. Return the value of applying
1017 /// \p Predicate on Range.Start, possibly decreasing Range.End such that the
1018 /// returned value holds for the entire \p Range.
1019 static bool
1020 getDecisionAndClampRange(const std::function<bool(ElementCount)> &Predicate,
1021 VFRange &Range);
1022
1023 /// \return A VPlan for the most profitable epilogue vectorization, with its
1024 /// VF narrowed to the chosen factor. The returned plan is a duplicate.
1025 /// Returns nullptr if epilogue vectorization is not supported or not
1026 /// profitable for the loop. \p ScalarEpilogueAllowed indicates whether the
1027 /// epilogue lowering policy permits creating a scalar epilogue at all.
1028 std::unique_ptr<VPlan> selectBestEpiloguePlan(VPlan &MainPlan,
1029 ElementCount MainLoopVF,
1030 unsigned IC,
1031 bool ScalarEpilogueAllowed);
1032
1033 /// Emit remarks for recipes with invalid costs in the available VPlans.
1035
1036 /// Create a check to \p Plan to see if the vector loop should be executed
1037 /// based on its trip count.
1038 void addMinimumIterationCheck(VPlan &Plan, ElementCount VF, unsigned UF,
1039 ElementCount MinProfitableTripCount) const;
1040
1041 /// Attach the runtime checks of \p RTChecks to \p Plan. \p VF and \p UF are
1042 /// used to compute the thresholds of difference checks.
1043 void attachRuntimeChecks(VPlan &Plan, GeneratedRTChecks &RTChecks,
1044 ElementCount VF, unsigned UF,
1045 bool HasBranchWeights) const;
1046
1047 /// Update loop metadata and profile info for both the scalar remainder loop
1048 /// and \p VectorLoop, if it exists. Keeps all loop hints from the original
1049 /// loop on the vector loop and replaces vectorizer-specific metadata. The
1050 /// loop ID of the original loop \p OrigLoopID must be passed, together with
1051 /// the average trip count and invocation weight of the original loop (\p
1052 /// OrigAverageTripCount and \p OrigLoopInvocationWeight respectively). They
1053 /// cannot be retrieved after the plan has been executed, as the original loop
1054 /// may have been removed. \p UnrollVectorizedLoop indicates whether the
1055 /// target wants the vector loop left eligible for runtime unrolling.
1057 Loop *VectorLoop, VPBasicBlock *HeaderVPBB, const VPlan &Plan,
1058 bool VectorizingEpilogue, MDNode *OrigLoopID,
1059 std::optional<unsigned> OrigAverageTripCount,
1060 unsigned OrigLoopInvocationWeight, unsigned EstimatedVFxUF,
1061 bool DisableRuntimeUnroll, bool UnrollVectorizedLoop);
1062
1063private:
1064 /// Build an initial VPlan, with HCFG wrapping the original scalar loop and
1065 /// scalar transformations applied. Returns null if an initial VPlan cannot
1066 /// be built. \p PlanCM is the cost model to use for decisions made while
1067 /// building the plan.
1068 VPlanPtr tryToBuildVPlan1(LoopVectorizationCostModel &PlanCM);
1069
1070 /// Build a VPlan using VPRecipes according to the information gathered by
1071 /// Legal and VPlan-based analysis. For outer loops, performs basic recipe
1072 /// conversion only. For inner loops, \p Range's largest included VF is
1073 /// restricted to the maximum VF the returned VPlan is valid for. If no VPlan
1074 /// can be built for the input range, set the largest included VF to the
1075 /// maximum VF for which no plan could be built. Each VPlan is built starting
1076 /// from a copy of \p InitialPlan, which is a plain CFG VPlan wrapping the
1077 /// original scalar loop. \p PlanCM is the cost model used for legality
1078 /// and widening decisions while building the plan.
1079 VPlanPtr tryToBuildVPlan(VPlanPtr InitialPlan, VFRange &Range,
1081
1082 /// Build VPlans for power-of-2 VF's between \p MinVF and \p MaxVF inclusive,
1083 /// based on \p VPlan1 and according to the information gathered by Legal
1084 /// when it checked if it is legal to vectorize the loop. \p PlanCM is
1085 /// the cost model to build these VPlans.
1086 void buildVPlans(VPlan &VPlan1, ElementCount MinVF, ElementCount MaxVF,
1088
1089 /// Add ComputeReductionResult recipes to the middle block to compute the
1090 /// final reduction results. Add Select recipes to the latch block when
1091 /// folding tail, to feed ComputeReductionResult with the last or penultimate
1092 /// iteration values according to the header mask. \p PlanCM is the cost
1093 /// model used to build \p Plan.
1094 void addReductionResultComputation(VPlanPtr &Plan, ElementCount MinVF,
1096
1097 /// Returns true if the per-lane cost of VectorizationFactor A is lower than
1098 /// that of B.
1099 bool isMoreProfitable(const VectorizationFactor &A,
1100 const VectorizationFactor &B, bool HasTail,
1101 bool IsEpilogue = false) const;
1102
1103 /// Returns true if the per-lane cost of VectorizationFactor A is lower than
1104 /// that of B in the context of vectorizing a loop with known \p MaxTripCount.
1105 bool isMoreProfitable(const VectorizationFactor &A,
1106 const VectorizationFactor &B,
1107 const unsigned MaxTripCount, bool HasTail,
1108 bool IsEpilogue = false) const;
1109
1110 /// Determines if we have the infrastructure to vectorize the loop and its
1111 /// epilogue, assuming the main loop is vectorized by \p MainPlan.
1112 bool isCandidateForEpilogueVectorization(VPlan &MainPlan) const;
1113};
1114
1115/// A helper function that returns true if the given type is irregular. The
1116/// type is irregular if its allocated size doesn't equal the store size of an
1117/// element of the corresponding vector type.
1118inline bool hasIrregularType(Type *Ty, const DataLayout &DL) {
1119 // Determine if an array of N elements of type Ty is "bitcast compatible"
1120 // with a <N x Ty> vector.
1121 // This is only true if there is no padding between the array elements.
1122 return DL.getTypeAllocSizeInBits(Ty) != DL.getTypeSizeInBits(Ty);
1123}
1124
1125} // namespace llvm
1126
1127#endif // LLVM_TRANSFORMS_VECTORIZE_LOOPVECTORIZATIONPLANNER_H
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
MachineBasicBlock MachineBasicBlock::iterator DebugLoc DL
static GCRegistry::Add< ErlangGC > A("erlang", "erlang-compatible garbage collector")
static GCRegistry::Add< OcamlGC > B("ocaml", "ocaml 3.10-compatible GC")
This file defines an InstructionCost class that is used when calculating the cost of an instruction,...
const AbstractManglingParser< Derived, Alloc >::OperatorInfo AbstractManglingParser< Derived, Alloc >::Ops[]
#define F(x, y, z)
Definition MD5.cpp:54
#define I(x, y, z)
Definition MD5.cpp:57
#define T
ConstantRange Range(APInt(BitWidth, Low), APInt(BitWidth, High))
SmallVector< MachineOperand, 4 > Cond
SI Fold Operands
const char * Msg
This file defines the SmallSet class.
This pass exposes codegen information to IR-level passes.
This file contains the declarations of the Vectorization Plan base classes:
Value * RHS
Value * LHS
static const uint32_t IV[8]
Definition blake3_impl.h:83
Represent a constant reference to an array (0 or more elements consecutively in memory),...
Definition ArrayRef.h:40
Analysis providing branch probability information.
Predicate
This enumeration lists the possible predicates for CmpInst subclasses.
Definition InstrTypes.h:740
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 getUnknown()
Definition DebugLoc.h:153
Concrete subclass of DominatorTreeBase that is used to compute a normal dominator tree.
Definition Dominators.h:122
static constexpr ElementCount getFixed(ScalarTy MinVal)
Definition TypeSize.h:306
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
Represents flags for the getelementptr instruction/expression.
static GEPNoWrapFlags none()
InductionKind
This enum represents the kinds of inductions that we support.
InnerLoopVectorizer vectorizes loops which contain only one basic block to a specified vectorization ...
bool isCast() const
An instruction for reading from memory.
LoopVectorizationCostModel - estimates the expected speedups due to vectorization.
LoopVectorizationLegality checks if it is legal to vectorize a loop, and to what vectorization factor...
EpilogueVectorizationKind
Generate the IR code for the vectorized loop captured in VPlan BestPlan according to the best selecte...
@ MainLoop
Vectorizing the main loop of epilogue vectorization.
void clearCostModel()
Destroy the cost model.
VPlan & getPlanFor(ElementCount VF) const
Return the VPlan for VF.
Definition VPlan.cpp:1660
void updateLoopMetadataAndProfileInfo(Loop *VectorLoop, VPBasicBlock *HeaderVPBB, const VPlan &Plan, bool VectorizingEpilogue, MDNode *OrigLoopID, std::optional< unsigned > OrigAverageTripCount, unsigned OrigLoopInvocationWeight, unsigned EstimatedVFxUF, bool DisableRuntimeUnroll, bool UnrollVectorizedLoop)
Update loop metadata and profile info for both the scalar remainder loop and VectorLoop,...
Definition VPlan.cpp:1711
bool hasAPlan() const
Returns true if there is at least one VPlan.
LoopVectorizationCostModel & getCostModel()
Return the cost model. Must not be called after clearCostModel().
LoopVectorizationPlanner(Loop *L, LoopInfo *LI, DominatorTree *DT, const TargetLibraryInfo *TLI, const TargetTransformInfo &TTI, LoopVectorizationLegality *Legal, std::unique_ptr< LoopVectorizationCostModel > CM, VFSelectionContext &Config, PredicatedScalarEvolution &PSE, OptimizationRemarkEmitter *ORE, std::function< const BranchProbabilityInfo &()> GetBPI)
unsigned selectInterleaveCount(VPlan &Plan, ElementCount VF, InstructionCost LoopCost)
void attachRuntimeChecks(VPlan &Plan, GeneratedRTChecks &RTChecks, ElementCount VF, unsigned UF, bool HasBranchWeights) const
Attach the runtime checks of RTChecks to Plan.
bool hasVectorPlan() const
Return true if there is at least one VPlan for a vector VF.
void emitInvalidCostRemarks(OptimizationRemarkEmitter *ORE)
Emit remarks for recipes with invalid costs in the available VPlans.
static bool getDecisionAndClampRange(const std::function< bool(ElementCount)> &Predicate, VFRange &Range)
Test a Predicate on a Range of VF's.
Definition VPlan.cpp:1646
DenseMap< const SCEV *, Value * > executePlan(ElementCount VF, unsigned UF, VPlan &BestPlan, InnerLoopVectorizer &LB, DominatorTree *DT, EpilogueVectorizationKind EpilogueVecKind=EpilogueVectorizationKind::None, MutableArrayRef< VPBasicBlock * > TrackedBlocks={})
void printPlans(raw_ostream &O)
Definition VPlan.cpp:1815
std::unique_ptr< VPlan > selectBestEpiloguePlan(VPlan &MainPlan, ElementCount MainLoopVF, unsigned IC, bool ScalarEpilogueAllowed)
void plan(ElementCount UserVF, unsigned UserIC)
Build VPlans for the specified UserVF and UserIC if they are non-zero or all applicable candidate VFs...
void addMinimumIterationCheck(VPlan &Plan, ElementCount VF, unsigned UF, ElementCount MinProfitableTripCount) const
Create a check to Plan to see if the vector loop should be executed based on its trip count.
bool hasPlanWithVF(ElementCount VF) const
Look through the existing plans and return true if we have one with vectorization factor VF.
std::pair< VectorizationFactor, VPlan * > computeBestVF()
Compute and return the most profitable vectorization factor and the corresponding best VPlan.
Utility class for getting and setting loop vectorizer hints in the form of loop metadata.
Represents a single loop in the control flow graph.
Definition LoopInfo.h:40
Metadata node.
Definition Metadata.h:1081
This class implements a map that also provides access to all stored values in a deterministic order.
Definition MapVector.h:38
Root of the metadata hierarchy.
Definition Metadata.h:64
Represent a mutable reference to an array (0 or more elements consecutively in memory),...
Definition ArrayRef.h:294
The optimization diagnostic interface.
An interface layer with SCEV used to manage how we see SCEV expressions for values in the context of ...
The RecurrenceDescriptor is used to identify recurrences variables in a loop.
This class represents an analyzed expression in the program.
A templated base class for SmallPtrSet which provides the typesafe interface that is common across al...
SmallPtrSet - This class implements a set which is optimized for holding SmallSize or less elements.
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
An instruction for storing to memory.
Represent a constant reference to a string, i.e.
Definition StringRef.h:56
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.
TargetCostKind
The kind of cost model.
Twine - A lightweight data structure for efficiently representing the concatenation of temporary valu...
Definition Twine.h:82
The instances of the Type class are immutable: once they are created, they are never changed.
Definition Type.h:46
LLVM_ABI unsigned getScalarSizeInBits() const LLVM_READONLY
If this is a vector type, return the getPrimitiveSizeInBits value for the element type.
Definition Type.cpp:222
bool isIntegerTy() const
True if this is an instance of IntegerType.
Definition Type.h:252
Holds state needed to make cost decisions before computing costs per-VF, including the maximum VFs.
PredicatedScalarEvolution & getPSE() const
const VectorizeOptions & getOpts() const
const bool OptForSize
Whether this loop should be optimized for size based on function attribute or profile information.
FixedScalableVFPair computeVPlanOuterloopVF(ElementCount UserVF)
Returns a scalable VF to use for outer-loop vectorization if the target supports it and a fixed VF ot...
bool isInLoopReduction(PHINode *Phi) const
Returns true if the Phi is part of an inloop reduction.
std::pair< unsigned, unsigned > getSmallestAndWidestTypes() const
const TTI::TargetCostKind CostKind
The kind of cost that we are calculating.
VFSelectionContext(const VectorizeOptions &Opts, const TargetTransformInfo &TTI, const LoopVectorizationLegality *Legal, const Loop *TheLoop, const Function &F, PredicatedScalarEvolution &PSE, DemandedBits *DB, OptimizationRemarkEmitter *ORE, const LoopVectorizeHints *Hints, bool OptForSize)
bool runtimeChecksRequired()
Check whether vectorization would require runtime checks.
bool isLegalGatherOrScatter(bool IsLoad, Type *ScalarTy, Align Alignment, ElementCount VF) const
Returns true if the target machine supports a gather (if IsLoad) or scatter of scalar type ScalarTy w...
bool isLegalMaskedLoadOrStore(bool IsLoad, Type *ScalarTy, Align Alignment, unsigned AddressSpace) const
Returns true if the target machine supports a masked load (if IsLoad) or masked store of scalar type ...
void collectInLoopReductions()
Split reductions into those that happen in the loop, and those that happen outside.
const TargetTransformInfo & getTTI() const
const SmallPtrSetImpl< PHINode * > & getInLoopReductions() const
Returns the set of in-loop reduction PHIs.
std::optional< unsigned > getMaxSafeElements() const
Return maximum safe number of elements to be processed per vector iteration, which do not prevent sto...
FixedScalableVFPair computeFeasibleMaxVF(unsigned MaxTripCount, ElementCount UserVF, unsigned UserIC, bool FoldTailByMasking, bool RequiresScalarEpilogue)
const MapVector< Instruction *, uint64_t > & getMinimalBitwidths() const
const LoopVectorizeHints & getHints() const
bool isEpilogueVectorizationProfitable(ElementCount VF, unsigned IC) const
Returns true if epilogue vectorization is considered profitable for a main loop with vectorization fa...
bool useOrderedReductions(const RecurrenceDescriptor &RdxDesc) const
Returns true if we should use strict in-order reductions for the given RdxDesc.
bool shouldConsiderRegPressureForVF(ElementCount VF) const
void collectElementTypesForWidening(const SmallPtrSetImpl< const Value * > *ValuesToIgnore=nullptr)
Collect element types in the loop that need widening.
std::optional< unsigned > getVScaleForTuning() const
void computeMinimalBitwidths()
Compute smallest bitwidth each instruction can be represented with.
VPBasicBlock serves as the leaf of the Hierarchical Control-Flow Graph.
Definition VPlan.h:4465
RecipeListTy::iterator iterator
Instruction iterators...
Definition VPlan.h:4496
iterator end()
Definition VPlan.h:4506
InsertPointGuard(const InsertPointGuard &)=delete
InsertPointGuard & operator=(const InsertPointGuard &)=delete
VPInstruction * createFreeze(VPValue *Op, DebugLoc DL=DebugLoc::getUnknown(), const Twine &Name="")
VPInstruction * createInstruction(unsigned Opcode, ArrayRef< VPValue * > Operands, const VPIRMetadata &MD, DebugLoc DL, const Twine &Name="")
static VPBuilderBase getToInsertAfter(VPRecipeBase *R)
Create a builder to insert after R.
void restoreIP(VPInsertPoint IP)
Sets the current insert point to a previously-saved location.
VPVectorPointerRecipe * createVectorPointer(VPValue *Ptr, Type *SourceElementTy, VPValue *Stride, GEPNoWrapFlags GEPFlags, DebugLoc DL)
VPInstruction * createLogicalAnd(VPValue *LHS, VPValue *RHS, DebugLoc DL=DebugLoc::getUnknown(), const Twine &Name="")
VPInstruction * createOverflowingOp(unsigned Opcode, ArrayRef< VPValue * > Operands, VPRecipeWithIRFlags::WrapFlagsTy WrapFlags={false, false}, DebugLoc DL=DebugLoc::getUnknown(), const Twine &Name="")
VPInstruction * createWidePtrAdd(VPValue *Ptr, VPValue *Offset, 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 ...
T * tryInsertInstruction(T *R)
Insert R at InsertPt if InsertPt is set.
VPPhi * createScalarPhi(ArrayRef< VPValue * > IncomingValues, DebugLoc DL=DebugLoc::getUnknown(), const Twine &Name="", std::optional< VPIRFlags > Flags=std::nullopt, Type *ResultTy=nullptr)
Create a phi with IncomingValues, using the default flags for the result type, unless Flags is set.
VPInstruction * createNoWrapPtrAdd(VPValue *Ptr, VPValue *Offset, GEPNoWrapFlags GEPFlags, DebugLoc DL=DebugLoc::getUnknown(), const Twine &Name="")
VPInstruction * createAnd(VPValue *LHS, VPValue *RHS, DebugLoc DL=DebugLoc::getUnknown(), const Twine &Name="")
VPInstruction * createNaryOp(unsigned Opcode, ArrayRef< VPValue * > Operands, DebugLoc DL, const Twine &Name="")
VPExpandSCEVRecipe * createExpandSCEV(const SCEV *Expr)
VPDerivedIVRecipe * createDerivedIV(InductionDescriptor::InductionKind Kind, FPMathOperator *FPBinOp, VPValue *Start, VPValue *Current, VPValue *Step, const VPIRFlags::WrapFlagsTy &Flags={})
Convert Current to Start + Current * Step.
VPBuilderBase(const VPInsertPoint &IP)
VPInstruction * createPtrAdd(VPValue *Ptr, VPValue *Offset, DebugLoc DL=DebugLoc::getUnknown(), const Twine &Name="")
VPWidenCastRecipe * createWidenCast(Instruction::CastOps Opcode, VPValue *Op, Type *ResultTy)
T * insert(T *R)
Insert R at the current insertion point. Returns R unchanged.
VPRecipeBase * getRecipeAtInsertPoint() const
Get the recipe at the current insert point or nullptr if the insert point is the end of the block.
VPInstruction * createAdd(VPValue *LHS, VPValue *RHS, DebugLoc DL=DebugLoc::getUnknown(), const Twine &Name="", VPRecipeWithIRFlags::WrapFlagsTy WrapFlags={false, false})
VPInstruction * createSelect(VPValue *Cond, VPValue *TrueVal, VPValue *FalseVal, DebugLoc DL=DebugLoc::getUnknown(), const Twine &Name="", std::optional< VPIRFlags > Flags=std::nullopt)
Create a select of TrueVal and FalseVal based on Cond, using the default flags for the result type,...
VPValue * createScalarZExtOrTrunc(VPValue *Op, Type *ResultTy, DebugLoc DL)
static VPSingleDefRecipe * createSingleScalarOp(unsigned Opcode, ArrayRef< VPValue * > Operands, VPValue *Mask, const VPIRFlags &Flags, const VPIRMetadata &Metadata, DebugLoc DL, Type *ResultTy, Instruction *UV)
Create a single-scalar recipe with Opcode and Operands without inserting it.
VPWidenLoadRecipe * createWidenLoad(LoadInst &Load, VPValue *Addr, VPValue *Mask, bool Consecutive, Align Alignment, const VPIRMetadata &Metadata, DebugLoc DL)
Create a recipe widening Load, loading from Addr with Mask (may be null).
VPInstruction * createLogicalOr(VPValue *LHS, VPValue *RHS, DebugLoc DL=DebugLoc::getUnknown(), const Twine &Name="")
VPValue * createScalarSExtOrTrunc(VPValue *Op, Type *ResultTy, DebugLoc DL)
VPBasicBlock * getInsertBlock() const
VPInstruction * createVScale(Type *ResultTy, DebugLoc DL=DebugLoc::getUnknown())
Create a scalar llvm.vscale call.
VPInstruction * createScalarCast(Instruction::CastOps Opcode, VPValue *Op, Type *ResultTy, DebugLoc DL, std::optional< VPIRFlags > Flags=std::nullopt, const VPIRMetadata &Metadata={})
VPInstruction * createScalarIntrinsic(Intrinsic::ID IntrinsicID, ArrayRef< VPValue * > Operands, Type *ResultTy, DebugLoc DL, const Twine &Name="")
Create a scalar call to the intrinsic IntrinsicID with Operands, and result type ResultTy.
VPInstruction * createNaryOp(unsigned Opcode, ArrayRef< VPValue * > Operands, Type *ResultTy, const VPIRFlags &Flags={}, DebugLoc DL=DebugLoc::getUnknown(), const Twine &Name="")
VPInstruction * createNot(VPValue *Operand, DebugLoc DL=DebugLoc::getUnknown(), const Twine &Name="")
VPInstruction * createLastActiveLane(ArrayRef< VPValue * > Masks, DebugLoc DL=DebugLoc::getUnknown(), const Twine &Name="")
void setInsertPoint(const VPInsertPoint &IP)
Set the current insert point.
VPBuilderBase()=default
VPInstruction * createNaryOp(unsigned Opcode, ArrayRef< VPValue * > Operands, const VPIRFlags &Flags, DebugLoc DL=DebugLoc::getUnknown(), const Twine &Name="")
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, const VPIRAttributes &Attrs={})
Create an N-ary operation with Opcode, Operands and set Inst as its underlying Instruction.
VPSingleDefRecipe * createConsecutiveVectorPointer(VPValue *Ptr, Type *SourceElementTy, bool Reverse, DebugLoc DL)
Create a vector pointer recipe for a consecutive memory access to Ptr with element type SourceElement...
VPInstruction * createSub(VPValue *LHS, VPValue *RHS, DebugLoc DL=DebugLoc::getUnknown(), const Twine &Name="", VPRecipeWithIRFlags::WrapFlagsTy WrapFlags={false, false})
VPWidenMemIntrinsicRecipe * createWidenMemIntrinsic(Intrinsic::ID VectorIntrinsicID, ArrayRef< VPValue * > CallArguments, Type *Ty, Align Alignment, const VPIRMetadata &MD, DebugLoc DL)
VPInstruction * createFirstActiveLane(ArrayRef< VPValue * > Masks, DebugLoc DL=DebugLoc::getUnknown(), const Twine &Name="")
VPBuilderBase(InserterTy Inserter)
VPScalarIVStepsRecipe * createScalarIVSteps(Instruction::BinaryOps InductionOpcode, FPMathOperator *FPBinOp, VPValue *IV, VPValue *Step, VPValue *VF, DebugLoc DL)
VPInstruction * createFCmp(CmpInst::Predicate Pred, VPValue *A, VPValue *B, DebugLoc DL=DebugLoc::getUnknown(), const Twine &Name="")
Create a new FCmp VPInstruction with predicate Pred and operands A and B.
VPWidenPHIRecipe * createWidenPhi(ArrayRef< VPValue * > IncomingValues, DebugLoc DL=DebugLoc::getUnknown(), const Twine &Name="")
VPValue * createElementCount(Type *Ty, ElementCount EC)
VPWidenStoreRecipe * createWidenStore(StoreInst &Store, VPValue *Addr, VPValue *StoredVal, VPValue *Mask, bool Consecutive, Align Alignment, const VPIRMetadata &Metadata, DebugLoc DL)
Create a recipe widening Store, storing StoredVal to Addr with Mask (may be null).
VPInstruction * createOr(VPValue *LHS, VPValue *RHS, DebugLoc DL=DebugLoc::getUnknown(), const Twine &Name="")
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.
A recipe for converting Current into Start + Current * Step.
Definition VPlan.h:4236
Recipe to expand a SCEV expression.
Definition VPlan.h:4060
Class to record and manage LLVM IR flags.
Definition VPlan.h:682
static LLVM_ABI_FOR_TEST VPIRFlags getDefaultFlags(unsigned Opcode, Type *ResultTy=nullptr)
Returns default flags for Opcode and scalar ResultTy for opcodes that support it, asserts otherwise.
Helper to manage IR metadata for recipes.
Definition VPlan.h:1151
This is a concrete Recipe that models a single VPlan-level instruction.
Definition VPlan.h:1321
@ Intrinsic
Calls a scalar intrinsic. The intrinsic ID is the last operand.
Definition VPlan.h:1448
@ ComputeReductionResult
Reduce the operands to the final reduction result using the operation specified via the operation's V...
Definition VPlan.h:1380
VPRecipeBase is a base class modeling a sequence of one or more output IR instructions.
Definition VPlan.h:403
VPReplicateRecipe replicates a given instruction producing multiple scalar copies of the original sca...
Definition VPlan.h:3428
A recipe for handling phi nodes of integer and floating-point inductions, producing their scalar valu...
Definition VPlan.h:4297
VPSingleDefRecipe is a base class for recipes that model a sequence of one or more output IR that def...
Definition VPlan.h:605
This is the base class of the VPlan Def/Use graph, used for modeling the data flow into,...
Definition VPlanValue.h:50
Type * getScalarType() const
Returns the scalar type of this VPValue, dispatching based on the concrete subclass.
Definition VPlan.cpp:142
A recipe to compute a pointer to the last element of each part of a widened memory access for widened...
Definition VPlan.h:2305
A recipe to compute the pointers for widened memory accesses of SourceElementTy, with the Stride expr...
Definition VPlan.h:2387
VPWidenCastRecipe is a recipe to create vector cast instructions.
Definition VPlan.h:1887
A recipe for widening vector memory intrinsics.
Definition VPlan.h:2064
A recipe for widened phis.
Definition VPlan.h:2765
VPlan models a candidate for vectorization, encoding various decisions take to produce efficient outp...
Definition VPlan.h:4883
const DataLayout & getDataLayout() const
Definition VPlan.h:5084
LLVMContext & getContext() const
Definition VPlan.h:5080
bool hasTailFolded() const
Returns true if the vector loop region is tail-folded.
Definition VPlan.h:4996
VPSymbolicValue & getVF()
Returns the VF of the vector loop region.
Definition VPlan.h:5071
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:5190
LLVM_ABI StringRef getName() const
Return a constant reference to the value's name.
Definition Value.cpp:315
void reportVectorizationFailure(const StringRef DebugMsg, const StringRef OREMsg, const StringRef ORETag, OptimizationRemarkEmitter *ORE, const Loop *TheLoop, Instruction *I=nullptr)
Reports a vectorization failure: print DebugMsg for debugging purposes along with the corresponding o...
void reportVectorizationInfo(const StringRef Msg, const StringRef ORETag, OptimizationRemarkEmitter *ORE, const Loop *TheLoop, Instruction *I=nullptr, DebugLoc DL={})
Reports an informative message: print Msg for debugging purposes as well as an optimization remark.
void reportVectorization(OptimizationRemarkEmitter *ORE, Loop *TheLoop, ElementCount VFWidth, unsigned IC)
Report successful vectorization of the loop.
GEPNoWrapFlags getGEPFlagsForPtr(VPValue *Ptr)
Returns the GEP nowrap flags for Ptr, looking through pointer casts mirroring Value::stripPointerCast...
This is an optimization pass for GlobalISel generic memory operations.
@ Offset
Definition DWP.cpp:577
@ Load
The value being inserted comes from a load (InsertElement only).
@ Store
The extracted value is stored (ExtractElement only).
VPBuilderBase<> VPBuilder
Definition VPlan.h:67
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:1762
unsigned Log2_32(uint32_t Value)
Return the floor log base 2 of the specified value, -1 if the value is zero.
Definition MathExtras.h:326
std::optional< uint64_t > getMaxRuntimeElementCount(ElementCount EC, const Function &F)
constexpr bool isPowerOf2_32(uint32_t Value)
Return true if the argument is a power of two > 0.
Definition MathExtras.h:280
bool hasIrregularType(Type *Ty, const DataLayout &DL)
A helper function that returns true if the given type is irregular.
@ Or
Bitwise or logical OR of integers.
DWARFExpression::Operation Op
std::optional< unsigned > getMaxVScale(const Function &F)
std::unique_ptr< VPlan > VPlanPtr
Definition VPlan.h:77
This struct is a compact representation of a valid (non-zero power of two) alignment.
Definition Alignment.h:39
A class that represents two vectorization factors (initialized with 0 by default).
FixedScalableVFPair(const ElementCount &FixedVF, const ElementCount &ScalableVF)
FixedScalableVFPair(const ElementCount &Max)
static FixedScalableVFPair getNone()
A range of powers-of-2 vectorization factors with fixed start and adjustable end.
Default inserter for VPBuilderBase, inserting R before It.
void insertHelper(VPRecipeBase *R, VPBasicBlock::iterator It)
Struct to hold various analysis needed for cost computations.
A struct that represents some properties of the register usage of a loop.
A recipe for widening load operations, using the address to load from and an optional mask.
Definition VPlan.h:3843
A recipe for widening store operations, using the stored value, the address to store to and an option...
Definition VPlan.h:3951
TODO: The following VectorizationFactor was pulled out of LoopVectorizationCostModel class.
InstructionCost Cost
Cost of the loop with that width.
ElementCount MinProfitableTripCount
The minimum trip count required to make vectorization profitable, e.g.
ElementCount Width
Vector width with best cost.
InstructionCost ScalarCost
Cost of the scalar loop.
static VectorizationFactor Disabled()
Width 1 means no vectorization, cost 0 means uncomputed cost.
VectorizationFactor(ElementCount Width, InstructionCost Cost, InstructionCost ScalarCost)