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/// LoopVectorizationPlanner - drives the vectorization process after having
12/// passed Legality checks.
13/// The planner builds and optimizes the Vectorization Plans which record the
14/// decisions how to vectorize the given loop. In particular, represent the
15/// control-flow of the vectorized version, the replication of instructions that
16/// are to be scalarized, and interleave access groups.
17///
18/// Also provides a VPlan-based builder utility analogous to IRBuilder.
19/// It provides an instruction-level API for generating VPInstructions while
20/// abstracting away the Recipe manipulation details.
21//===----------------------------------------------------------------------===//
22
23#ifndef LLVM_TRANSFORMS_VECTORIZE_LOOPVECTORIZATIONPLANNER_H
24#define LLVM_TRANSFORMS_VECTORIZE_LOOPVECTORIZATIONPLANNER_H
25
26#include "VPlan.h"
27#include "VPlanUtils.h"
28#include "llvm/ADT/SmallSet.h"
31#include <optional>
32
33namespace {
34class GeneratedRTChecks;
35}
36
37namespace llvm {
38
40class LoopInfo;
41class DominatorTree;
49struct VPRegisterUsage;
50struct VFRange;
51struct VectorizeOptions;
52
53/// \return An upper bound for vscale based on TTI or the vscale_range
54/// attribute.
55std::optional<unsigned> getMaxVScale(const Function &F);
56
57/// \return The upper bound for the runtime value of \p EC, or std::nullopt
58/// if the upper bound is unknown.
59std::optional<uint64_t>
61
62// Utility functions that are used by different vectorization classes
64
65/// Reports a vectorization failure: print \p DebugMsg for debugging
66/// purposes along with the corresponding optimization remark \p RemarkName.
67/// If \p I is passed, it is an instruction that prevents vectorization.
68/// Otherwise, the loop \p TheLoop is used for the location of the remark.
69void reportVectorizationFailure(const StringRef DebugMsg,
70 const StringRef OREMsg, const StringRef ORETag,
72 const Loop *TheLoop, Instruction *I = nullptr);
73
74/// Same as above, but the debug message and optimization remark are identical
75inline void reportVectorizationFailure(const StringRef DebugMsg,
76 const StringRef ORETag,
78 const Loop *TheLoop,
79 Instruction *I = nullptr) {
80 reportVectorizationFailure(DebugMsg, DebugMsg, ORETag, ORE, TheLoop, I);
81}
82
83/// Reports an informative message: print \p Msg for debugging purposes as well
84/// as an optimization remark. Uses either \p I as location of the remark, or
85/// otherwise \p TheLoop. If \p DL is passed, use it as debug location for the
86/// remark.
87void reportVectorizationInfo(const StringRef Msg, const StringRef ORETag,
89 const Loop *TheLoop, Instruction *I = nullptr,
90 DebugLoc DL = {});
91
92/// Report successful vectorization of the loop. In case an outer loop is
93/// vectorized, prepend "outer" to the vectorization remark.
94void reportVectorization(OptimizationRemarkEmitter *ORE, Loop *TheLoop,
95 ElementCount VFWidth, unsigned IC);
96
97} // namespace LoopVectorizationUtils
98
99/// Default inserter for VPBuilderBase, inserting \p R before \p It.
102 R->insertBefore(It);
103 }
104};
105
106/// VPlan-based builder utility similar to IRBuilder. Recipes are inserted via
107/// \p InserterTy.
108template <typename InserterTy> class VPBuilderBase : public InserterTy {
109private:
110 class VPInsertPoint {
111 VPBasicBlock::iterator Iterator;
112
113 public:
114 /// Creates a new insertion point which doesn't point to anything.
115 VPInsertPoint() = default;
116
117 /// Creates a new insertion point to insert before \p Iterator.
118 VPInsertPoint(VPBasicBlock::iterator Iterator) : Iterator(Iterator) {}
119
120 /// Creates a new insertion point to insert before \p R.
121 VPInsertPoint(VPRecipeBase *R) : Iterator(R->getIterator()) {}
122
123 /// Creates a new insertion point to insert at the end of \p Block.
124 VPInsertPoint(VPBasicBlock *Block) : Iterator(Block->end()) {}
125
126 /// Returns true if this insert point is set.
127 operator bool() const { return Iterator.isValid(); }
128
129 VPBasicBlock *getBlock() const {
130 return Iterator.isValid() ? Iterator.getNodeParent() : nullptr;
131 }
132 VPBasicBlock::iterator getIterator() const { return Iterator; }
133
134 operator VPRecipeBase *() const {
135 return Iterator == getBlock()->end() ? nullptr : &*Iterator;
136 }
137 };
138
139 VPInsertPoint InsertPt;
140
141protected:
142 /// Insert \p R at InsertPt if InsertPt is set.
143 template <typename T> T *tryInsertInstruction(T *R) {
144 if (InsertPt)
145 InserterTy::insertHelper(R, InsertPt.getIterator());
146 return R;
147 }
148
151 const VPIRMetadata &MD, DebugLoc DL,
152 const Twine &Name = "") {
154 new VPInstruction(Opcode, Operands, {}, MD, DL, Name));
155 }
156
157public:
158 VPlan &getPlan() const {
159 assert(InsertPt && "Insert block must be set");
160 return *InsertPt.getBlock()->getPlan();
161 }
162
163 VPBuilderBase() = default;
164 VPBuilderBase(const VPInsertPoint &IP) : InsertPt(IP) {}
165 VPBuilderBase(InserterTy Inserter) : InserterTy(Inserter) {}
166
167 /// Get the recipe at the current insert point or nullptr if the insert point
168 /// is the end of the block.
169 VPRecipeBase *getRecipeAtInsertPoint() const { return InsertPt; }
170
171 VPBasicBlock *getInsertBlock() const { return InsertPt.getBlock(); }
172
173 /// Create a builder to insert after \p R.
175 return VPBuilderBase(std::next(R->getIterator()));
176 }
177
178 /// Sets the current insert point to a previously-saved location.
179 void restoreIP(VPInsertPoint IP) { InsertPt = IP; }
180
181 /// Set the current insert point.
182 void setInsertPoint(const VPInsertPoint &IP) {
183 assert(IP && "Attempting to set a null insert point");
184 InsertPt = IP;
185 }
186
187 /// Insert \p R at the current insertion point. Returns \p R unchanged.
188 template <typename T> [[maybe_unused]] T *insert(T *R) {
189 InserterTy::insertHelper(R, InsertPt.getIterator());
190 return R;
191 }
192
193 /// Create an N-ary operation with \p Opcode, \p Operands and set \p Inst as
194 /// its underlying Instruction.
196 Instruction *Inst = nullptr,
197 const VPIRFlags &Flags = {},
198 const VPIRMetadata &MD = {},
200 const Twine &Name = "", Type *ResultTy = nullptr,
201 const VPIRAttributes &Attrs = {}) {
202 VPInstruction *NewVPInst = tryInsertInstruction(new VPInstruction(
203 Opcode, Operands, Flags, MD, DL, Name, ResultTy, Attrs));
204 NewVPInst->setUnderlyingValue(Inst);
205 return NewVPInst;
206 }
208 DebugLoc DL, const Twine &Name = "") {
209 return createInstruction(Opcode, Operands, {}, DL, Name);
210 }
212 const VPIRFlags &Flags,
214 const Twine &Name = "") {
216 new VPInstruction(Opcode, Operands, Flags, {}, DL, Name));
217 }
218
220 Type *ResultTy, const VPIRFlags &Flags = {},
222 const Twine &Name = "") {
224 new VPInstruction(Opcode, Operands, Flags, {}, DL, Name, ResultTy));
225 }
226
229 const Twine &Name = "") {
230 // Assume that the maximum possible number of elements in a vector fits
231 // within the index type for the default address space.
232 VPlan &Plan = getPlan();
233 Type *IndexTy = Plan.getDataLayout().getIndexType(Plan.getContext(), 0);
235 VPInstruction::FirstActiveLane, Masks, {}, {}, DL, Name, IndexTy));
236 }
237
240 const Twine &Name = "") {
241 // Assume that the maximum possible number of elements in a vector fits
242 // within the index type for the default address space.
243 VPlan &Plan = getPlan();
244 Type *IndexTy = Plan.getDataLayout().getIndexType(Plan.getContext(), 0);
246 VPInstruction::LastActiveLane, Masks, {}, {}, DL, Name, IndexTy));
247 }
248
250 unsigned Opcode, ArrayRef<VPValue *> Operands,
251 VPRecipeWithIRFlags::WrapFlagsTy WrapFlags = {false, false},
252 DebugLoc DL = DebugLoc::getUnknown(), const Twine &Name = "") {
254 new VPInstruction(Opcode, Operands, WrapFlags, {}, DL, Name));
255 }
256
259 const Twine &Name = "") {
260 return createInstruction(VPInstruction::Not, {Operand}, {}, DL, Name);
261 }
262
265 const Twine &Name = "") {
266 return createInstruction(Instruction::BinaryOps::And, {LHS, RHS}, {}, DL,
267 Name);
268 }
269
272 const Twine &Name = "") {
273
275 Instruction::BinaryOps::Or, {LHS, RHS},
276 VPRecipeWithIRFlags::DisjointFlagsTy(false), {}, DL, Name));
277 }
278
281 const Twine &Name = "",
282 VPRecipeWithIRFlags::WrapFlagsTy WrapFlags = {false, false}) {
283 return createOverflowingOp(Instruction::Add, {LHS, RHS}, WrapFlags, DL,
284 Name);
285 }
286
287 VPInstruction *
289 const Twine &Name = "",
290 VPRecipeWithIRFlags::WrapFlagsTy WrapFlags = {false, false}) {
291 return createOverflowingOp(Instruction::Sub, {LHS, RHS}, WrapFlags, DL,
292 Name);
293 }
294
300
306
307 /// Create a select of \p TrueVal and \p FalseVal based on \p Cond, using the
308 /// default flags for the result type, unless \p Flags is set.
310 VPValue *FalseVal,
312 const Twine &Name = "",
313 std::optional<VPIRFlags> Flags = std::nullopt) {
315 new VPInstruction(Instruction::Select, {Cond, TrueVal, FalseVal},
316 Flags.value_or(VPIRFlags::getDefaultFlags(
317 Instruction::Select, TrueVal->getScalarType())),
318 {}, DL, Name));
319 }
320
321 /// Create a new ICmp VPInstruction with predicate \p Pred and operands \p A
322 /// and \p B.
325 const Twine &Name = "") {
327 Pred <= CmpInst::LAST_ICMP_PREDICATE && "invalid predicate");
329 new VPInstruction(Instruction::ICmp, {A, B}, Pred, {}, DL, Name));
330 }
331
332 /// Create a new FCmp VPInstruction with predicate \p Pred and operands \p A
333 /// and \p B.
336 const Twine &Name = "") {
338 Pred <= CmpInst::LAST_FCMP_PREDICATE && "invalid predicate");
340 new VPInstruction(Instruction::FCmp, {A, B},
341 VPIRFlags(Pred, FastMathFlags()), {}, DL, Name));
342 }
343
344 /// Create an AnyOf reduction pattern: or-reduce \p ChainOp, freeze the
345 /// result, then select between \p TrueVal and \p FalseVal.
347 VPValue *FalseVal,
349 assert(ChainOp->getScalarType()->isIntegerTy(1) &&
350 "ChainOp must be i1 for AnyOf reduction");
351 VPIRFlags Flags(RecurKind::Or, /*IsOrdered=*/false, /*IsInLoop=*/false,
352 FastMathFlags());
354 {ChainOp}, Flags, DL);
355 auto *Freeze = createNaryOp(Instruction::Freeze, {OrReduce}, DL);
356 return createSelect(Freeze, TrueVal, FalseVal, DL, "rdx.select");
357 }
358
361 const Twine &Name = "") {
362 return createNoWrapPtrAdd(Ptr, Offset, GEPNoWrapFlags::none(), DL, Name);
363 }
364
366 GEPNoWrapFlags GEPFlags,
368 const Twine &Name = "") {
370 VPInstruction::PtrAdd, {Ptr, Offset}, GEPFlags, {}, DL, Name));
371 }
372
380
381 /// Create a phi with \p IncomingValues, using the default flags for the
382 /// result type, unless \p Flags is set.
385 const Twine &Name = "",
386 std::optional<VPIRFlags> Flags = std::nullopt,
387 Type *ResultTy = nullptr) {
388 Type *ScalarTy = ResultTy ? ResultTy : IncomingValues[0]->getScalarType();
389 return tryInsertInstruction(new VPPhi(
390 IncomingValues,
391 Flags.value_or(VPIRFlags::getDefaultFlags(Instruction::PHI, ScalarTy)),
392 DL, Name, ResultTy));
393 }
394
397 const Twine &Name = "") {
398 return tryInsertInstruction(new VPWidenPHIRecipe(IncomingValues, DL, Name));
399 }
400
402 VPlan &Plan = getPlan();
403 unsigned MinEC = EC.getKnownMinValue();
404 if (EC.isScalable()) {
405 VPValue *VScale = createVScale(Ty);
406 if (MinEC == 1)
407 return VScale;
408 // TODO: Move this optimization into createOverflowingOp directly.
409 if (isPowerOf2_32(MinEC)) {
410 VPValue *ShtAmt = Plan.getConstantInt(Ty, Log2_32(MinEC));
411 return createOverflowingOp(Instruction::Shl, {VScale, ShtAmt},
412 {true, false});
413 }
414 VPValue *MulAmt = Plan.getConstantInt(Ty, MinEC);
415 return createOverflowingOp(Instruction::Mul, {VScale, MulAmt},
416 {true, false});
417 }
418 return Plan.getConstantInt(Ty, MinEC);
419 }
420
421 /// Convert \p Current to \p Start + \p Current * \p Step.
423 FPMathOperator *FPBinOp, VPValue *Start,
424 VPValue *Current, VPValue *Step,
425 const VPIRFlags::WrapFlagsTy &Flags = {}) {
427 new VPDerivedIVRecipe(Kind, FPBinOp, Start, Current, Step, Flags));
428 }
429
431 Type *ResultTy, DebugLoc DL,
432 std::optional<VPIRFlags> Flags = std::nullopt,
433 const VPIRMetadata &Metadata = {}) {
435 Opcode, Op, Flags.value_or(VPIRFlags::getDefaultFlags(Opcode)),
436 Metadata, DL, "", ResultTy));
437 }
438
439 /// Create a scalar call to the intrinsic \p IntrinsicID with \p Operands, and
440 /// result type \p ResultTy
443 Type *ResultTy, DebugLoc DL,
444 const Twine &Name = "") {
445 VPlan &Plan = getPlan();
447 Ops.push_back(Plan.getConstantInt(8 * sizeof(IntrinsicID), IntrinsicID));
449 {}, {}, DL, Name, ResultTy));
450 }
451
452 /// Create a scalar llvm.vscale call.
455 return createScalarIntrinsic(Intrinsic::vscale, {}, ResultTy, DL);
456 }
457
459 Type *SrcTy = Op->getScalarType();
460 if (ResultTy == SrcTy)
461 return Op;
462 Instruction::CastOps CastOp =
463 ResultTy->getScalarSizeInBits() < SrcTy->getScalarSizeInBits()
464 ? Instruction::Trunc
465 : Instruction::ZExt;
466 return createScalarCast(CastOp, Op, ResultTy, DL);
467 }
468
470 Type *SrcTy = Op->getScalarType();
471 if (ResultTy == SrcTy)
472 return Op;
473 Instruction::CastOps CastOp =
474 ResultTy->getScalarSizeInBits() < SrcTy->getScalarSizeInBits()
475 ? Instruction::Trunc
476 : Instruction::SExt;
477 return createScalarCast(CastOp, Op, ResultTy, DL);
478 }
479
481 const Twine &Name = "") {
482 return createNaryOp(Instruction::Freeze, Op, DL, Name);
483 }
484
486 Type *ResultTy) {
487 assert(Op->getScalarType() != ResultTy &&
488 "must not create a no-op cast recipe");
490 Opcode, Op, ResultTy, nullptr, VPIRFlags::getDefaultFlags(Opcode)));
491 }
492
493 /// Create a single-scalar recipe with \p Opcode and \p Operands without
494 /// inserting it.
495 static VPSingleDefRecipe *
497 VPValue *Mask, const VPIRFlags &Flags,
499 Type *ResultTy, Instruction *UV) {
500 if (Instruction::isCast(Opcode)) {
501 assert(!Mask && "Cast cannot be predicated");
502 auto *VPI = new VPInstruction(Opcode, Operands, Flags, Metadata, DL,
503 UV->getName(), ResultTy);
504 VPI->setUnderlyingValue(UV);
505 return VPI;
506 }
507 auto *RepR = new VPReplicateRecipe(UV, Operands, /*IsSingleScalar=*/true,
508 Mask, Flags, Metadata, DL);
509 assert(RepR->getScalarType() == ResultTy && "unexpected result type");
510 return RepR;
511 }
512
515 FPMathOperator *FPBinOp, VPValue *IV, VPValue *Step,
516 VPValue *VF, DebugLoc DL) {
518 IV, Step, VF, InductionOpcode,
519 FPBinOp ? FPBinOp->getFastMathFlags() : FastMathFlags(), DL));
520 }
521
525
527 createVectorPointer(VPValue *Ptr, Type *SourceElementTy, VPValue *Stride,
528 GEPNoWrapFlags GEPFlags, DebugLoc DL) {
530 new VPVectorPointerRecipe(Ptr, SourceElementTy, Stride, GEPFlags, DL));
531 }
532
533 /// Create a vector pointer recipe for a consecutive memory access to \p Ptr
534 /// with element type \p SourceElementTy.
536 Type *SourceElementTy,
537 bool Reverse, DebugLoc DL) {
538 VPlan &Plan = getPlan();
540 if (Reverse) {
541 // When folding the tail, we may compute an address that we don't in the
542 // original scalar loop: drop the GEP no-wrap flags in this case.
543 // Otherwise preserve existing flags without no-unsigned-wrap, as we will
544 // emit negative indices.
545 GEPNoWrapFlags ReverseFlags = Plan.hasTailFolded()
547 : Flags.withoutNoUnsignedWrap();
549 new VPVectorEndPointerRecipe(Ptr, &Plan.getVF(), SourceElementTy,
550 /*Stride=*/-1, ReverseFlags, DL));
551 }
552 Type *StrideTy = Plan.getDataLayout().getIndexType(Ptr->getScalarType());
553 VPValue *StrideOne = Plan.getConstantInt(StrideTy, 1);
554 return createVectorPointer(Ptr, SourceElementTy, StrideOne, Flags, DL);
555 }
556
558 Intrinsic::ID VectorIntrinsicID, ArrayRef<VPValue *> CallArguments,
559 Type *Ty, Align Alignment, const VPIRMetadata &MD, DebugLoc DL) {
561 VectorIntrinsicID, CallArguments, Ty, Alignment, MD, DL));
562 }
563
564 /// Create a recipe widening \p Load, loading from \p Addr with \p Mask (may
565 /// be null).
567 VPValue *Mask, bool Consecutive,
568 Align Alignment,
569 const VPIRMetadata &Metadata,
570 DebugLoc DL) {
572 Load, Addr, Mask, Consecutive, Alignment, Metadata, DL));
573 }
574
575 /// Create a recipe widening \p Store, storing \p StoredVal to \p Addr with
576 /// \p Mask (may be null).
578 VPValue *StoredVal, VPValue *Mask,
579 bool Consecutive, Align Alignment,
580 const VPIRMetadata &Metadata,
581 DebugLoc DL) {
583 Store, Addr, StoredVal, Mask, Consecutive, Alignment, Metadata, DL));
584 }
585
586 //===--------------------------------------------------------------------===//
587 // RAII helpers.
588 //===--------------------------------------------------------------------===//
589
590 /// RAII object that stores the current insertion point and restores it when
591 /// the object is destroyed.
593 VPBuilderBase &Builder;
594 VPInsertPoint InsertPt;
595
596 public:
597 InsertPointGuard(VPBuilderBase &B) : Builder(B), InsertPt(B.InsertPt) {}
598
601
602 ~InsertPointGuard() { Builder.restoreIP(InsertPt); }
603 };
604};
605
606/// TODO: The following VectorizationFactor was pulled out of
607/// LoopVectorizationCostModel class. LV also deals with
608/// VectorizerParams::VectorizationFactor.
609/// We need to streamline them.
610
611/// Information about vectorization costs.
613 /// Vector width with best cost.
615
616 /// Cost of the loop with that width.
618
619 /// Cost of the scalar loop.
621
622 /// The minimum trip count required to make vectorization profitable, e.g. due
623 /// to runtime checks.
625
629
630 /// Width 1 means no vectorization, cost 0 means uncomputed cost.
632 return {ElementCount::getFixed(1), 0, 0};
633 }
634};
635
636/// A class that represents two vectorization factors (initialized with 0 by
637/// default). One for fixed-width vectorization and one for scalable
638/// vectorization. This can be used by the vectorizer to choose from a range of
639/// fixed and/or scalable VFs in order to find the most cost-effective VF to
640/// vectorize with.
644
646 : FixedVF(ElementCount::getFixed(0)),
647 ScalableVF(ElementCount::getScalable(0)) {}
649 *(Max.isScalable() ? &ScalableVF : &FixedVF) = Max;
650 }
654 assert(!FixedVF.isScalable() && ScalableVF.isScalable() &&
655 "Invalid scalable properties");
656 }
657
659
660 /// \return true if either fixed- or scalable VF is non-zero.
661 explicit operator bool() const { return FixedVF || ScalableVF; }
662};
663
664/// Holds state needed to make cost decisions before computing costs per-VF,
665/// including the maximum VFs.
667 using VectorKind = TargetTransformInfo::VectorKind;
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(VectorKind Kind, Type *ElementTy = nullptr) const;
671 bool useMaxBandwidth(bool IsScalable, Type *ElementTy = nullptr) const {
672 return useMaxBandwidth(
673 IsScalable ? VectorKind::Scalable : VectorKind::FixedWidth, ElementTy);
674 }
675
676 struct TypeWidths {
677 unsigned SmallestTypeForMaxBandwidth;
678 unsigned SmallestType;
679 unsigned WidestType;
680 };
681
682 /// \return The size (in bits) of the of the types used to determine the
683 /// possible VFs. That is the widest type in the loop and the smallest type
684 /// the target wants to maximize vector bandwidth for. We ignore values that
685 /// remain scalar such as 64 bit loop indices.
686 TypeWidths getTypeWidthsForVFSelection() const;
687
688 /// \return the maximized element count based on the targets vector
689 /// registers and the loop trip-count, but limited to a maximum safe VF.
690 /// This is a helper function of computeFeasibleMaxVF.
691 ElementCount getMaximizedVFForTarget(unsigned MaxTripCount,
692 const TypeWidths &TyWidths,
693 ElementCount MaxSafeVF, unsigned UserIC,
694 bool FoldTailByMasking,
695 bool RequiresScalarEpilogue);
696
697 /// If \p VF * \p UserIC > MaxTripcount, clamps VF to the next lower VF
698 /// that results in VF * UserIC <= MaxTripCount.
699 ElementCount clampVFByMaxTripCount(ElementCount VF, unsigned MaxTripCount,
700 unsigned UserIC, bool FoldTailByMasking,
701 bool RequiresScalarEpilogue) const;
702
703 /// Checks if scalable vectorization is supported and enabled. Caches the
704 /// result to avoid repeated debug dumps for repeated queries.
705 bool isScalableVectorizationAllowed();
706
707 /// \return the maximum legal scalable VF, based on the safe max number
708 /// of elements.
709 ElementCount getMaxLegalScalableVF(unsigned MaxSafeElements);
710
711 /// Initializes the value of vscale used for tuning the cost model. If
712 /// vscale_range.min == vscale_range.max then return vscale_range.max, else
713 /// return the value returned by the corresponding TTI method.
714 void initializeVScaleForTuning();
715
716 const VectorizeOptions &Opts;
717 const TargetTransformInfo &TTI;
718 const LoopVectorizationLegality *Legal;
719 const Loop *TheLoop;
720 const Function &F;
722 DemandedBits *DB;
724 const LoopVectorizeHints *Hints;
725
726 /// Cached result of isScalableVectorizationAllowed.
727 std::optional<bool> IsScalableVectorizationAllowed;
728
729 /// Used to store the value of vscale used for tuning the cost model. It is
730 /// initialized during object construction.
731 std::optional<unsigned> VScaleForTuning;
732
733 /// The highest VF possible for this loop, without using MaxBandwidth.
734 FixedScalableVFPair MaxPermissibleVFWithoutMaxBW;
735
736 /// All element types found in the loop.
737 SmallPtrSet<Type *, 16> ElementTypesInLoop;
738
739 /// PHINodes of the reductions that should be expanded in-loop. Set by
740 /// collectInLoopReductions.
741 SmallPtrSet<PHINode *, 4> InLoopReductions;
742
743 /// Maximum safe number of elements to be processed per vector iteration,
744 /// which do not prevent store-load forwarding and are safe with regard to the
745 /// memory dependencies. Required for EVL-based vectorization, where this
746 /// value is used as the upper bound of the safe AVL. Set by
747 /// computeFeasibleMaxVF.
748 std::optional<unsigned> MaxSafeElements;
749
750 /// Map of scalar integer values to the smallest bitwidth they can be legally
751 /// represented as. The vector equivalents of these values should be truncated
752 /// to this type.
754
755public:
756 /// The kind of cost that we are calculating.
758
759 /// Whether this loop should be optimized for size based on function attribute
760 /// or profile information.
761 const bool OptForSize;
762
763 VFSelectionContext(const VectorizeOptions &Opts,
764 const TargetTransformInfo &TTI,
765 const LoopVectorizationLegality *Legal,
766 const Loop *TheLoop, const Function &F,
769 const LoopVectorizeHints *Hints, bool OptForSize)
770 : Opts(Opts), TTI(TTI), Legal(Legal), TheLoop(TheLoop), F(F), PSE(PSE),
771 DB(DB), ORE(ORE), Hints(Hints),
772 CostKind(F.hasMinSize() ? TTI::TCK_CodeSize : TTI::TCK_RecipThroughput),
774 initializeVScaleForTuning();
775 }
776
777 /// \return The vscale value used for tuning the cost model.
778 std::optional<unsigned> getVScaleForTuning() const { return VScaleForTuning; }
779
780 const VectorizeOptions &getOpts() const { return Opts; }
781
782 const TargetTransformInfo &getTTI() const { return TTI; }
783
784 PredicatedScalarEvolution &getPSE() const { return PSE; }
785
786 /// \return The loop being analyzed.
787 const Loop *getLoop() const { return TheLoop; }
788
789 /// \return The vectorization hints for the loop being analyzed.
790 const LoopVectorizeHints &getHints() const { return *Hints; }
791
792 /// Returns true if epilogue vectorization is considered profitable for a
793 /// main loop with vectorization factor \p VF and interleave count \p IC.
794 bool isEpilogueVectorizationProfitable(ElementCount VF, unsigned IC) const;
795
796 /// \return True if register pressure should be considered for the given VF.
798
799 /// \return True if scalable vectors are supported by the target or forced.
800 bool supportsScalableVectors() const;
801
802 /// Collect element types in the loop that need widening.
804 const SmallPtrSetImpl<const Value *> *ValuesToIgnore = nullptr);
805
806 /// \return An upper bound for the vectorization factors for both
807 /// fixed and scalable vectorization, where the minimum-known number of
808 /// elements is a power-of-2 larger than zero. If scalable vectorization is
809 /// disabled or unsupported, then the scalable part will be equal to
810 /// ElementCount::getScalable(0). Also sets MaxSafeElements.
811 FixedScalableVFPair computeFeasibleMaxVF(unsigned MaxTripCount,
812 ElementCount UserVF, unsigned UserIC,
813 bool FoldTailByMasking,
814 bool RequiresScalarEpilogue);
815
816 /// Return maximum safe number of elements to be processed per vector
817 /// iteration, which do not prevent store-load forwarding and are safe with
818 /// regard to the memory dependencies. Required for EVL-based VPlans to
819 /// correctly calculate AVL (application vector length) as min(remaining AVL,
820 /// MaxSafeElements). Set by computeFeasibleMaxVF.
821 /// TODO: need to consider adjusting cost model to use this value as a
822 /// vectorization factor for EVL-based vectorization.
823 std::optional<unsigned> getMaxSafeElements() const { return MaxSafeElements; }
824
825 /// Returns true if we should use strict in-order reductions for the given
826 /// RdxDesc. This is true if the -enable-strict-reductions flag is passed,
827 /// the IsOrdered flag of RdxDesc is set and we do not allow reordering
828 /// of FP operations.
829 bool useOrderedReductions(const RecurrenceDescriptor &RdxDesc) const;
830
831 /// Returns true if the target machine supports a masked load (if \p IsLoad)
832 /// or masked store of scalar type \p ScalarTy with \p Alignment in address
833 /// space \p AddressSpace. The caller must ensure the access is consecutive or
834 /// part of an interleave group.
835 bool isLegalMaskedLoadOrStore(bool IsLoad, Type *ScalarTy, Align Alignment,
836 unsigned AddressSpace) const;
837
838 /// Returns true if the target machine supports a gather (if \p IsLoad)
839 /// or scatter of scalar type \p ScalarTy with \p Alignment for vectorization
840 /// factor \p VF.
841 bool isLegalGatherOrScatter(bool IsLoad, Type *ScalarTy, Align Alignment,
842 ElementCount VF) const;
843
844 /// Split reductions into those that happen in the loop, and those that
845 /// happen outside. In-loop reductions are collected into InLoopReductions.
847
848 /// Returns true if the Phi is part of an inloop reduction.
849 bool isInLoopReduction(PHINode *Phi) const {
850 return InLoopReductions.contains(Phi);
851 }
852
853 /// Returns the set of in-loop reduction PHIs.
855 return InLoopReductions;
856 }
857
858 /// Check whether vectorization would require runtime checks. When optimizing
859 /// for size, returning true here aborts vectorization.
861
862 /// Returns a scalable VF to use for outer-loop vectorization if the target
863 /// supports it and a fixed VF otherwise.
865
866 /// Compute smallest bitwidth each instruction can be represented with.
867 /// The vector equivalents of these instructions should be truncated to this
868 /// type.
870
871 /// \returns The smallest bitwidth each instruction can be represented with.
873 return MinBWs;
874 }
875};
876
877/// Planner drives the vectorization process after having passed
878/// Legality checks.
880 const VectorizeOptions &Opts;
881
882 /// The loop that we evaluate.
883 Loop *OrigLoop;
884
885 /// Loop Info analysis.
886 LoopInfo *LI;
887
888 /// The dominator tree.
889 DominatorTree *DT;
890
891 /// Target Library Info.
892 const TargetLibraryInfo *TLI;
893
894 /// Target Transform Info.
895 const TargetTransformInfo &TTI;
896
897 /// The legality analysis.
899
900 /// The profitability analysis. Cleared after making cost based decisions.
901 /// This instance should never be used in any function that takes an explicit
902 /// PlanCM reference, since that instance overrides this one.
903 std::unique_ptr<LoopVectorizationCostModel> CM;
904
905 /// VF selection state independent of cost-modeling decisions.
906 VFSelectionContext &Config;
907
909
911
912 /// Lazily fetch BranchProbabilityInfo, independent of BlockFrequencyInfo.
913 std::function<const BranchProbabilityInfo &()> GetBPI;
914
916
917 /// Profitable vector factors.
919
920 /// A builder used to construct the current plan.
921 VPBuilder Builder;
922
923 /// Computes the cost of \p Plan for vectorization factor \p VF, using
924 /// \p PlanCM as the cost model.
925 ///
926 /// The current implementation requires access to the
927 /// LoopVectorizationLegality to handle inductions and reductions, which is
928 /// why it is kept separate from the VPlan-only cost infrastructure.
929 ///
930 /// TODO: Move to VPlan::cost once the use of LoopVectorizationLegality has
931 /// been retired.
933 LoopVectorizationCostModel &PlanCM) const;
934
935 /// Precompute costs for certain instructions using the legacy cost model. The
936 /// function is used to bring up the VPlan-based cost model to initially avoid
937 /// taking different decisions due to inaccuracies in the legacy cost model.
938 InstructionCost precomputeCosts(VPlan &Plan, ElementCount VF,
939 VPCostContext &CostCtx) const;
940
941public:
943 Loop *L, LoopInfo *LI, DominatorTree *DT, const TargetLibraryInfo *TLI,
945 std::unique_ptr<LoopVectorizationCostModel> CM,
948 std::function<const BranchProbabilityInfo &()> GetBPI);
949
951
952 /// Return the cost model. Must not be called after clearCostModel().
954 assert(CM && "Cost model has already been cleared");
955 return *CM;
956 }
957
958 /// Destroy the cost model.
959 void clearCostModel();
960
961 /// Return true if there is at least one VPlan for a vector VF
962 bool hasVectorPlan() const {
963 return any_of(
964 VPlans, [&](const VPlanPtr &Plan) { return !Plan->hasScalarVFOnly(); });
965 }
966
967 /// Returns true if there is at least one VPlan.
968 bool hasAPlan() const { return !VPlans.empty(); }
969
970 /// Build VPlans for the specified \p UserVF and \p UserIC if they are
971 /// non-zero or all applicable candidate VFs otherwise. If vectorization and
972 /// interleaving should be avoided up-front, no plans are generated.
973 void plan(ElementCount UserVF, unsigned UserIC);
974
975 /// Return the VPlan for \p VF. At the moment, there is always a single VPlan
976 /// for each VF.
977 VPlan &getPlanFor(ElementCount VF) const;
978
979 /// Compute and return the most profitable vectorization factor and the
980 /// corresponding best VPlan. Also collect all profitable VFs in
981 /// ProfitableVFs.
982 std::pair<VectorizationFactor, VPlan *> computeBestVF();
983
984 /// \return The desired interleave count.
985 /// If interleave count has been specified by metadata it will be returned.
986 /// Otherwise, the interleave count is computed and returned. VF and LoopCost
987 /// are the selected vectorization factor and the cost of the selected VF.
988 unsigned selectInterleaveCount(VPlan &Plan, ElementCount VF,
989 InstructionCost LoopCost);
990
991 /// Generate the IR code for the vectorized loop captured in VPlan \p BestPlan
992 /// according to the best selected \p VF and \p UF. \p HasRuntimeChecks is
993 /// used to decide whether runtime unrolling of the scalar loop is disabled.
994 ///
995 /// TODO: \p EpilogueVecKind should be removed once the re-use issue has been
996 /// fixed.
997 ///
998 /// When vectorizing the main loop, \p TrackedBlocks are updated to the
999 /// VPIRBasicBlocks wrapping the blocks generated for them.
1000 ///
1001 /// Returns a mapping of SCEVs to their expanded IR values.
1002 /// Note that this is a temporary workaround needed due to the current
1003 /// epilogue handling.
1005 None, ///< Not part of epilogue vectorization.
1006 MainLoop, ///< Vectorizing the main loop of epilogue vectorization.
1007 Epilogue ///< Vectorizing the epilogue loop.
1008 };
1010 executePlan(ElementCount VF, unsigned UF, VPlan &BestPlan,
1011 bool HasRuntimeChecks,
1012 EpilogueVectorizationKind EpilogueVecKind =
1014 MutableArrayRef<VPBasicBlock *> TrackedBlocks = {});
1015
1016#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
1017 void printPlans(raw_ostream &O);
1018#endif
1019
1020 /// Look through the existing plans and return true if we have one with
1021 /// vectorization factor \p VF.
1023 return any_of(VPlans,
1024 [&](const VPlanPtr &Plan) { return Plan->hasVF(VF); });
1025 }
1026
1027 /// Test a \p Predicate on a \p Range of VF's. Return the value of applying
1028 /// \p Predicate on Range.Start, possibly decreasing Range.End such that the
1029 /// returned value holds for the entire \p Range.
1030 static bool
1031 getDecisionAndClampRange(const std::function<bool(ElementCount)> &Predicate,
1032 VFRange &Range);
1033
1034 /// \return A VPlan for the most profitable epilogue vectorization, with its
1035 /// VF narrowed to the chosen factor. The returned plan is a duplicate.
1036 /// Returns nullptr if epilogue vectorization is not supported or not
1037 /// profitable for the loop. \p ScalarEpilogueAllowed indicates whether the
1038 /// epilogue lowering policy permits creating a scalar epilogue at all.
1039 std::unique_ptr<VPlan> selectBestEpiloguePlan(VPlan &MainPlan,
1040 ElementCount MainLoopVF,
1041 unsigned IC,
1042 bool ScalarEpilogueAllowed);
1043
1044 /// Emit remarks for recipes with invalid costs in the available VPlans.
1046
1047 /// Create a check to \p Plan to see if the vector loop should be executed
1048 /// based on its trip count. When \p TailFoldedEpilogue is true, the
1049 /// tail-folded vector epilogue executes all iterations not executed by
1050 /// the main vector loop, so the check never needs to branch to the scalar
1051 /// loop.
1052 void addMinimumIterationCheck(VPlan &Plan, ElementCount VF, unsigned UF,
1053 ElementCount MinProfitableTripCount,
1054 bool TailFoldedEpilogue) const;
1055
1056 /// Attach the runtime checks of \p RTChecks to \p Plan. \p VF and \p UF are
1057 /// used to compute the thresholds of difference checks.
1058 void attachRuntimeChecks(VPlan &Plan, GeneratedRTChecks &RTChecks,
1059 ElementCount VF, unsigned UF,
1060 bool HasBranchWeights) const;
1061
1062 /// Update loop metadata and profile info for both the scalar remainder loop
1063 /// and \p VectorLoop, if it exists. Keeps all loop hints from the original
1064 /// loop on the vector loop and replaces vectorizer-specific metadata. The
1065 /// loop ID of the original loop \p OrigLoopID must be passed, together with
1066 /// the average trip count and invocation weight of the original loop (\p
1067 /// OrigAverageTripCount and \p OrigLoopInvocationWeight respectively). They
1068 /// cannot be retrieved after the plan has been executed, as the original loop
1069 /// may have been removed. \p UnrollVectorizedLoop indicates whether the
1070 /// target wants the vector loop left eligible for runtime unrolling.
1072 Loop *VectorLoop, VPBasicBlock *HeaderVPBB, const VPlan &Plan,
1073 bool VectorizingEpilogue, MDNode *OrigLoopID,
1074 std::optional<unsigned> OrigAverageTripCount,
1075 unsigned OrigLoopInvocationWeight, unsigned EstimatedVFxUF,
1076 bool DisableRuntimeUnroll, bool UnrollVectorizedLoop);
1077
1078private:
1079 /// Build VPlan for the forced epilogue VF. If vectorization and tail-folding
1080 /// should be avoided up-front, no tail-folded plans are generated.
1081 bool planForEpilogueTF();
1082
1083 /// Build an initial VPlan, with HCFG wrapping the original scalar loop and
1084 /// scalar transformations applied. Returns null if an initial VPlan cannot
1085 /// be built. \p PlanCM is the cost model to use for decisions made while
1086 /// building the plan.
1087 VPlanPtr tryToBuildVPlan1(LoopVectorizationCostModel &PlanCM);
1088
1089 /// Build a VPlan using VPRecipes according to the information gathered by
1090 /// Legal and VPlan-based analysis. For outer loops, performs basic recipe
1091 /// conversion only. For inner loops, \p Range's largest included VF is
1092 /// restricted to the maximum VF the returned VPlan is valid for. If no VPlan
1093 /// can be built for the input range, set the largest included VF to the
1094 /// maximum VF for which no plan could be built. Each VPlan is built starting
1095 /// from a copy of \p InitialPlan, which is a plain CFG VPlan wrapping the
1096 /// original scalar loop. \p PlanCM is the cost model used for legality
1097 /// and widening decisions while building the plan.
1098 VPlanPtr tryToBuildVPlan(VPlanPtr InitialPlan, VFRange &Range,
1100
1101 /// Build VPlans for power-of-2 VF's between \p MinVF and \p MaxVF inclusive,
1102 /// based on \p VPlan1 and according to the information gathered by Legal
1103 /// when it checked if it is legal to vectorize the loop. \p PlanCM is
1104 /// the cost model to build these VPlans.
1105 void buildVPlans(VPlan &VPlan1, ElementCount MinVF, ElementCount MaxVF,
1107
1108 /// Add ComputeReductionResult recipes to the middle block to compute the
1109 /// final reduction results. Add Select recipes to the latch block when
1110 /// folding tail, to feed ComputeReductionResult with the last or penultimate
1111 /// iteration values according to the header mask. \p PlanCM is the cost
1112 /// model used to build \p Plan.
1113 void addReductionResultComputation(VPlanPtr &Plan, ElementCount MinVF,
1115
1116 /// Returns true if the per-lane cost of VectorizationFactor A is lower than
1117 /// that of B.
1118 bool isMoreProfitable(const VectorizationFactor &A,
1119 const VectorizationFactor &B, bool HasTail,
1120 bool IsEpilogue = false) const;
1121
1122 /// Returns true if the per-lane cost of VectorizationFactor A is lower than
1123 /// that of B in the context of vectorizing a loop with known \p MaxTripCount.
1124 bool isMoreProfitable(const VectorizationFactor &A,
1125 const VectorizationFactor &B,
1126 const unsigned MaxTripCount, bool HasTail,
1127 bool IsEpilogue = false) const;
1128
1129 /// Determines if we have the infrastructure to vectorize the loop and its
1130 /// epilogue, assuming the main loop is vectorized by \p MainPlan.
1131 bool isCandidateForEpilogueVectorization(VPlan &MainPlan) const;
1132};
1133
1134} // namespace llvm
1135
1136#endif // LLVM_TRANSFORMS_VECTORIZE_LOOPVECTORIZATIONPLANNER_H
bool IsScalable
SDValue Pred
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
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.
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 addMinimumIterationCheck(VPlan &Plan, ElementCount VF, unsigned UF, ElementCount MinProfitableTripCount, bool TailFoldedEpilogue) const
Create a check to Plan to see if the vector loop should be executed based on its trip count.
void clearCostModel()
Destroy the cost model.
VPlan & getPlanFor(ElementCount VF) const
Return the VPlan for VF.
Definition VPlan.cpp:1661
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:1712
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:1647
DenseMap< const SCEV *, Value * > executePlan(ElementCount VF, unsigned UF, VPlan &BestPlan, bool HasRuntimeChecks, EpilogueVectorizationKind EpilogueVecKind=EpilogueVectorizationKind::None, MutableArrayRef< VPBasicBlock * > TrackedBlocks={})
void printPlans(raw_ostream &O)
Definition VPlan.cpp:1816
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...
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:39
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.
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:4533
RecipeListTy::iterator iterator
Instruction iterators...
Definition VPlan.h:4564
iterator end()
Definition VPlan.h:4574
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:4303
Recipe to expand a SCEV expression.
Definition VPlan.h:4127
Class to record and manage LLVM IR flags.
Definition VPlan.h:683
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:1152
This is a concrete Recipe that models a single VPlan-level instruction.
Definition VPlan.h:1322
@ Intrinsic
Calls a scalar intrinsic. The intrinsic ID is the last operand.
Definition VPlan.h:1449
@ ComputeReductionResult
Reduce the operands to the final reduction result using the operation specified via the operation's V...
Definition VPlan.h:1381
VPRecipeBase is a base class modeling a sequence of one or more output IR instructions.
Definition VPlan.h:402
VPReplicateRecipe replicates a given instruction producing multiple scalar copies of the original sca...
Definition VPlan.h:3495
A recipe for handling phi nodes of integer and floating-point inductions, producing their scalar valu...
Definition VPlan.h:4364
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:2317
A recipe to compute the pointers for widened memory accesses of SourceElementTy, with the Stride expr...
Definition VPlan.h:2399
VPWidenCastRecipe is a recipe to create vector cast instructions.
Definition VPlan.h:1899
A recipe for widening vector memory intrinsics.
Definition VPlan.h:2076
A recipe for widened phis.
Definition VPlan.h:2777
VPlan models a candidate for vectorization, encoding various decisions take to produce efficient outp...
Definition VPlan.h:4951
const DataLayout & getDataLayout() const
Definition VPlan.h:5152
LLVMContext & getContext() const
Definition VPlan.h:5148
bool hasTailFolded() const
Returns true if the vector loop region is tail-folded.
Definition VPlan.h:5064
VPSymbolicValue & getVF()
Returns the VF of the vector loop region.
Definition VPlan.h:5139
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:5258
LLVM_ABI StringRef getName() const
Return a constant reference to the value's name.
Definition Value.cpp:314
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:66
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
@ 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:76
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:3910
A recipe for widening store operations, using the stored value, the address to store to and an option...
Definition VPlan.h:4018
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)