LLVM 24.0.0git
LoopVectorizationPlanner.cpp
Go to the documentation of this file.
1//===- LoopVectorizationPlanner.cpp - VF selection and planning -----------===//
2//
3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6//
7//===----------------------------------------------------------------------===//
8///
9/// \file
10/// This file implements VFSelectionContext methods for loop vectorization
11/// VF selection, independent of cost-modeling decisions.
12///
13//===----------------------------------------------------------------------===//
14
16#include "VPlanUtils.h"
22#include "llvm/Support/Debug.h"
26
27using namespace llvm;
28using namespace LoopVectorizationUtils;
29
30#define DEBUG_TYPE "loop-vectorize"
31
33
35 "vectorizer-maximize-bandwidth", cl::init(false), cl::Hidden,
36 cl::desc("Maximize bandwidth when selecting vectorization factor which "
37 "will be determined by the smallest type in loop."));
38
40 "vectorizer-maximize-bandwidth-for-vector-calls", cl::init(true),
42 cl::desc("Try wider VFs if they enable the use of vector variants"));
43
45 "vectorizer-consider-reg-pressure", cl::init(false), cl::Hidden,
46 cl::desc("Discard VFs if their register pressure is too high."));
47
49 "force-target-supports-scalable-vectors", cl::init(false), cl::Hidden,
51 "Pretend that scalable vectors are supported, even if the target does "
52 "not support them. This flag should only be used for testing."));
53
55 "prefer-inloop-reductions", cl::init(false), cl::Hidden,
56 cl::desc("Prefer in-loop vector reductions, "
57 "overriding the targets preference."));
58
59/// Note: This currently only applies to `llvm.masked.load` and
60/// `llvm.masked.store`. TODO: Extend this to cover other operations as needed.
62 "force-target-supports-masked-memory-ops", cl::init(false), cl::Hidden,
63 cl::desc("Assume the target supports masked memory operations (used for "
64 "testing)."));
65
67 "force-target-supports-gather-scatter-ops", cl::init(false), cl::Hidden,
68 cl::desc("Assume the target supports gather/scatter operations (used for "
69 "testing)."));
70
72 "scalable-epilogue-vf-cost-scale-factor", cl::init(2.0), cl::Hidden,
73 cl::desc("Scale the cost of scalable epilogue VFs by this factor."));
74
75/// Write a \p DebugMsg about vectorization to the debug output stream. If \p I
76/// is passed, the message relates to that particular instruction.
77#ifndef NDEBUG
78static void debugVectorizationMessage(const StringRef Prefix,
79 const StringRef DebugMsg,
80 Instruction *I) {
81 dbgs() << "LV: " << Prefix << DebugMsg;
82 if (I != nullptr)
83 dbgs() << " " << *I;
84 else
85 dbgs() << '.';
86 dbgs() << '\n';
87}
88#endif
89
90/// Create an analysis remark that explains why vectorization failed
91/// \p RemarkName is the identifier for the remark. If \p I is passed it is an
92/// instruction that prevents vectorization. Otherwise \p TheLoop is used for
93/// the location of the remark. If \p DL is passed, use it as debug location for
94/// the remark. \return the remark object that can be streamed to.
96 const Loop *TheLoop,
98 DebugLoc DL = {}) {
99 BasicBlock *CodeRegion = I ? I->getParent() : TheLoop->getHeader();
100 // If debug location is attached to the instruction, use it. Otherwise if DL
101 // was not provided, use the loop's.
102 if (I && I->getDebugLoc())
103 DL = I->getDebugLoc();
104 else if (!DL)
105 DL = TheLoop->getStartLoc();
106
107 return OptimizationRemarkAnalysis(DEBUG_TYPE, RemarkName, DL, CodeRegion);
108}
109
111 const StringRef DebugMsg, const StringRef OREMsg, const StringRef ORETag,
112 OptimizationRemarkEmitter *ORE, const Loop *TheLoop, Instruction *I) {
113 LLVM_DEBUG(debugVectorizationMessage("Not vectorizing: ", DebugMsg, I));
114 ORE->emit(createLVAnalysis(ORETag, TheLoop, I)
115 << "loop not vectorized: " << OREMsg);
116}
117
119 const StringRef Msg, const StringRef ORETag, OptimizationRemarkEmitter *ORE,
120 const Loop *TheLoop, Instruction *I, DebugLoc DL) {
122 ORE->emit(createLVAnalysis(ORETag, TheLoop, I, DL) << Msg);
123}
124
126 Loop *TheLoop,
127 ElementCount VFWidth,
128 unsigned IC) {
130 "Vectorizing: ", TheLoop->isInnermost() ? "innermost loop" : "outer loop",
131 nullptr));
132 StringRef LoopType = TheLoop->isInnermost() ? "" : "outer ";
133 ORE->emit([&]() {
134 return OptimizationRemark(DEBUG_TYPE, "Vectorized", TheLoop->getStartLoc(),
135 TheLoop->getHeader())
136 << "vectorized " << LoopType << "loop (vectorization width: "
137 << ore::NV("VectorizationFactor", VFWidth)
138 << ", interleaved count: " << ore::NV("InterleaveCount", IC) << ")";
139 });
140}
141
143 Align Alignment,
144 unsigned AddressSpace) const {
146 (IsLoad ? TTI.isLegalMaskedLoad(ScalarTy, Alignment, AddressSpace)
147 : TTI.isLegalMaskedStore(ScalarTy, Alignment, AddressSpace));
148}
149
151 Align Alignment,
152 ElementCount VF) const {
153 Type *VectorTy = toVectorTy(ScalarTy, VF);
155 (IsLoad ? TTI.isLegalMaskedGather(VectorTy, Alignment)
156 : TTI.isLegalMaskedScatter(VectorTy, Alignment));
157}
158
160 return TTI.supportsScalableVectors() || ForceTargetSupportsScalableVectors ||
162}
163
164bool VFSelectionContext::useMaxBandwidth(bool IsScalable) const {
168 return MaximizeBandwidth || (MaximizeBandwidth.getNumOccurrences() == 0 &&
169 (TTI.shouldMaximizeVectorBandwidth(RegKind) ||
171 Legal->hasVectorCallVariants())));
172}
173
175 if (ConsiderRegPressure.getNumOccurrences())
176 return ConsiderRegPressure;
177
178 // TODO: We should eventually consider register pressure for all targets. The
179 // TTI hook is temporary whilst target-specific issues are being fixed.
180 if (TTI.shouldConsiderVectorizationRegPressure())
181 return true;
182
183 if (!useMaxBandwidth(VF.isScalable()))
184 return false;
185 // Only calculate register pressure for VFs enabled by MaxBandwidth.
187 VF, VF.isScalable() ? MaxPermissibleVFWithoutMaxBW.ScalableVF
188 : MaxPermissibleVFWithoutMaxBW.FixedVF);
189}
190
191ElementCount VFSelectionContext::clampVFByMaxTripCount(
192 ElementCount VF, unsigned MaxTripCount, unsigned UserIC,
193 bool FoldTailByMasking, bool RequiresScalarEpilogue) const {
194 unsigned EstimatedVF = VF.getKnownMinValue();
195 if (VF.isScalable() && F.hasFnAttribute(Attribute::VScaleRange)) {
196 auto Attr = F.getFnAttribute(Attribute::VScaleRange);
197 auto Min = Attr.getVScaleRangeMin();
198 EstimatedVF *= Min;
199 }
200
201 // When a scalar epilogue is required, at least one iteration of the scalar
202 // loop has to execute. Adjust MaxTripCount accordingly to avoid picking a
203 // max VF that results in a dead vector loop.
204 if (MaxTripCount > 0 && RequiresScalarEpilogue)
205 MaxTripCount -= 1;
206
207 // When the user specifies an interleave count, we need to ensure that
208 // VF * UserIC <= MaxTripCount to avoid a dead vector loop.
209 unsigned IC = UserIC > 0 ? UserIC : 1;
210 unsigned EstimatedVFTimesIC = EstimatedVF * IC;
211
212 if (MaxTripCount && MaxTripCount <= EstimatedVFTimesIC &&
213 (!FoldTailByMasking || isPowerOf2_32(MaxTripCount))) {
214 // If upper bound loop trip count (TC) is known at compile time there is no
215 // point in choosing VF greater than TC / IC (as done in the loop below).
216 // Select maximum power of two which doesn't exceed TC / IC. If VF is
217 // scalable, we only fall back on a fixed VF when the TC is less than or
218 // equal to the known number of lanes.
219 auto ClampedUpperTripCount = llvm::bit_floor(MaxTripCount / IC);
220 if (ClampedUpperTripCount == 0)
221 ClampedUpperTripCount = 1;
222 LLVM_DEBUG(dbgs() << "LV: Clamping the MaxVF to maximum power of two not "
223 "exceeding the constant trip count"
224 << (UserIC > 0 ? " divided by UserIC" : "") << ": "
225 << ClampedUpperTripCount << "\n");
226 return ElementCount::get(ClampedUpperTripCount,
227 FoldTailByMasking ? VF.isScalable() : false);
228 }
229 return VF;
230}
231
232ElementCount VFSelectionContext::getMaximizedVFForTarget(
233 unsigned MaxTripCount, unsigned SmallestType, unsigned WidestType,
234 ElementCount MaxSafeVF, unsigned UserIC, bool FoldTailByMasking,
235 bool RequiresScalarEpilogue) {
236 bool ComputeScalableMaxVF = MaxSafeVF.isScalable();
237 const TypeSize WidestRegister = TTI.getRegisterBitWidth(
238 ComputeScalableMaxVF ? TargetTransformInfo::RGK_ScalableVector
240
241 // Convenience function to return the minimum of two ElementCounts.
242 auto MinVF = [](const ElementCount &LHS, const ElementCount &RHS) {
243 assert((LHS.isScalable() == RHS.isScalable()) &&
244 "Scalable flags must match");
246 };
247
248 // Ensure MaxVF is a power of 2; the dependence distance bound may not be.
249 // Note that both WidestRegister and WidestType may not be a powers of 2.
250 auto MaxVectorElementCount = ElementCount::get(
251 llvm::bit_floor(WidestRegister.getKnownMinValue() / WidestType),
252 ComputeScalableMaxVF);
253 MaxVectorElementCount = MinVF(MaxVectorElementCount, MaxSafeVF);
254 LLVM_DEBUG(dbgs() << "LV: The Widest register safe to use is: "
255 << (MaxVectorElementCount * WidestType) << " bits.\n");
256
257 if (!MaxVectorElementCount) {
258 LLVM_DEBUG(dbgs() << "LV: The target has no "
259 << (ComputeScalableMaxVF ? "scalable" : "fixed")
260 << " vector registers.\n");
261 return ElementCount::getFixed(1);
262 }
263
264 ElementCount MaxVF =
265 clampVFByMaxTripCount(MaxVectorElementCount, MaxTripCount, UserIC,
266 FoldTailByMasking, RequiresScalarEpilogue);
267 // If the MaxVF was already clamped, there's no point in trying to pick a
268 // larger one.
269 if (MaxVF != MaxVectorElementCount)
270 return MaxVF;
271
272 if (MaxVF.isScalable())
273 MaxPermissibleVFWithoutMaxBW.ScalableVF = MaxVF;
274 else
275 MaxPermissibleVFWithoutMaxBW.FixedVF = MaxVF;
276
277 if (useMaxBandwidth(ComputeScalableMaxVF)) {
278 auto MaxVectorElementCountMaxBW = ElementCount::get(
279 llvm::bit_floor(WidestRegister.getKnownMinValue() / SmallestType),
280 ComputeScalableMaxVF);
281 MaxVF = MinVF(MaxVectorElementCountMaxBW, MaxSafeVF);
282
283 if (ElementCount MinVF =
284 TTI.getMinimumVF(SmallestType, ComputeScalableMaxVF)) {
285 if (ElementCount::isKnownLT(MaxVF, MinVF)) {
286 LLVM_DEBUG(dbgs() << "LV: Overriding calculated MaxVF(" << MaxVF
287 << ") with target's minimum: " << MinVF << '\n');
288 MaxVF = MinVF;
289 }
290 }
291
292 MaxVF = clampVFByMaxTripCount(MaxVF, MaxTripCount, UserIC,
293 FoldTailByMasking, RequiresScalarEpilogue);
294 }
295 return MaxVF;
296}
297
298std::optional<unsigned> llvm::getMaxVScale(const Function &F) {
299 if (F.hasFnAttribute(Attribute::VScaleRange))
300 return F.getFnAttribute(Attribute::VScaleRange).getVScaleRangeMax();
301
302 return std::nullopt;
303}
304
305std::optional<uint64_t>
307 if (EC.isFixed())
308 return EC.getFixedValue();
309
310 if (std::optional<unsigned> MaxVScale = getMaxVScale(F))
311 return uint64_t(EC.getKnownMinValue()) * *MaxVScale;
312
313 return std::nullopt;
314}
315
316bool VFSelectionContext::isScalableVectorizationAllowed() {
317 if (IsScalableVectorizationAllowed)
318 return *IsScalableVectorizationAllowed;
319
320 IsScalableVectorizationAllowed = false;
322 return false;
323
324 if (Hints->isScalableVectorizationDisabled()) {
325 reportVectorizationInfo("Scalable vectorization is explicitly disabled",
326 "ScalableVectorizationDisabled", ORE, TheLoop);
327 return false;
328 }
329
330 LLVM_DEBUG(dbgs() << "LV: Scalable vectorization is available\n");
331
332 auto MaxScalableVF = ElementCount::getScalable(
333 std::numeric_limits<ElementCount::ScalarTy>::max());
334
335 // Test that the loop-vectorizer can legalize all operations for this MaxVF.
336 // FIXME: While for scalable vectors this is currently sufficient, this should
337 // be replaced by a more detailed mechanism that filters out specific VFs,
338 // instead of invalidating vectorization for a whole set of VFs based on the
339 // MaxVF.
340
341 // Disable scalable vectorization if the loop contains unsupported reductions.
342 if (!all_of(Legal->getReductionVars(), [&](const auto &Reduction) -> bool {
343 return TTI.isLegalToVectorizeReduction(Reduction.second, MaxScalableVF);
344 })) {
346 "Scalable vectorization not supported for the reduction "
347 "operations found in this loop.",
348 "ScalableVFUnfeasible", ORE, TheLoop);
349 return false;
350 }
351
352 // Disable scalable vectorization if the loop contains any instructions
353 // with element types not supported for scalable vectors.
354 if (any_of(ElementTypesInLoop, [&](Type *Ty) {
355 return !Ty->isVoidTy() && !TTI.isElementTypeLegalForScalableVector(Ty);
356 })) {
357 reportVectorizationInfo("Scalable vectorization is not supported "
358 "for all element types found in this loop.",
359 "ScalableVFUnfeasible", ORE, TheLoop);
360 return false;
361 }
362
363 if (!Legal->isSafeForAnyVectorWidth() && !getMaxVScale(F)) {
364 reportVectorizationInfo("The target does not provide maximum vscale value "
365 "for safe distance analysis.",
366 "ScalableVFUnfeasible", ORE, TheLoop);
367 return false;
368 }
369
370 IsScalableVectorizationAllowed = true;
371 return true;
372}
373
375VFSelectionContext::getMaxLegalScalableVF(unsigned MaxSafeElements) {
376 if (!isScalableVectorizationAllowed())
378
379 auto MaxScalableVF = ElementCount::getScalable(
380 std::numeric_limits<ElementCount::ScalarTy>::max());
381 if (Legal->isSafeForAnyVectorWidth())
382 return MaxScalableVF;
383
384 std::optional<unsigned> MaxVScale = getMaxVScale(F);
385 // Limit MaxScalableVF by the maximum safe dependence distance.
386 MaxScalableVF = ElementCount::getScalable(MaxSafeElements / *MaxVScale);
387
388 if (!MaxScalableVF)
390 "Max legal vector width too small, scalable vectorization "
391 "unfeasible.",
392 "ScalableVFUnfeasible", ORE, TheLoop);
393
394 return MaxScalableVF;
395}
396
398 unsigned MaxTripCount, ElementCount UserVF, unsigned UserIC,
399 bool FoldTailByMasking, bool RequiresScalarEpilogue) {
400 auto [SmallestType, WidestType] = getSmallestAndWidestTypes();
401
402 // Get the maximum safe dependence distance in bits computed by LAA.
403 // It is computed by MaxVF * sizeOf(type) * 8, where type is taken from
404 // the memory accesses that is most restrictive (involved in the smallest
405 // dependence distance).
406 unsigned MaxSafeElementsPowerOf2 =
407 llvm::bit_floor(Legal->getMaxSafeVectorWidthInBits() / WidestType);
408 if (!Legal->isSafeForAnyStoreLoadForwardDistances()) {
409 unsigned SLDist = Legal->getMaxStoreLoadForwardSafeDistanceInBits();
410 MaxSafeElementsPowerOf2 =
411 std::min(MaxSafeElementsPowerOf2, SLDist / WidestType);
412 }
413
414 auto MaxSafeFixedVF = ElementCount::getFixed(MaxSafeElementsPowerOf2);
415 auto MaxSafeScalableVF = getMaxLegalScalableVF(MaxSafeElementsPowerOf2);
416
417 if (!Legal->isSafeForAnyVectorWidth())
418 MaxSafeElements = MaxSafeElementsPowerOf2;
419
420 LLVM_DEBUG(dbgs() << "LV: The max safe fixed VF is: " << MaxSafeFixedVF
421 << ".\n");
422 LLVM_DEBUG(dbgs() << "LV: The max safe scalable VF is: " << MaxSafeScalableVF
423 << ".\n");
424
425 // First analyze the UserVF, fall back if the UserVF should be ignored.
426 if (UserVF) {
427 auto MaxSafeUserVF =
428 UserVF.isScalable() ? MaxSafeScalableVF : MaxSafeFixedVF;
429
430 if (ElementCount::isKnownLE(UserVF, MaxSafeUserVF)) {
431 // If `VF=vscale x N` is safe, then so is `VF=N`
432 if (UserVF.isScalable())
433 return FixedScalableVFPair(
434 ElementCount::getFixed(UserVF.getKnownMinValue()), UserVF);
435
436 return UserVF;
437 }
438
439 assert(ElementCount::isKnownGT(UserVF, MaxSafeUserVF));
440
441 // Only clamp if the UserVF is not scalable. If the UserVF is scalable, it
442 // is better to ignore the hint and let the compiler choose a suitable VF.
443 if (!UserVF.isScalable()) {
444 LLVM_DEBUG(dbgs() << "LV: User VF=" << UserVF
445 << " is unsafe, clamping to max safe VF="
446 << MaxSafeFixedVF << ".\n");
447 ORE->emit([&]() {
448 return OptimizationRemarkAnalysis(DEBUG_TYPE, "VectorizationFactor",
449 TheLoop->getStartLoc(),
450 TheLoop->getHeader())
451 << "User-specified vectorization factor "
452 << ore::NV("UserVectorizationFactor", UserVF)
453 << " is unsafe, clamping to maximum safe vectorization factor "
454 << ore::NV("VectorizationFactor", MaxSafeFixedVF);
455 });
456 return MaxSafeFixedVF;
457 }
458
460 LLVM_DEBUG(dbgs() << "LV: User VF=" << UserVF
461 << " is ignored because scalable vectors are not "
462 "available.\n");
463 ORE->emit([&]() {
464 return OptimizationRemarkAnalysis(DEBUG_TYPE, "VectorizationFactor",
465 TheLoop->getStartLoc(),
466 TheLoop->getHeader())
467 << "User-specified vectorization factor "
468 << ore::NV("UserVectorizationFactor", UserVF)
469 << " is ignored because the target does not support scalable "
470 "vectors. The compiler will pick a more suitable value.";
471 });
472 } else {
473 LLVM_DEBUG(dbgs() << "LV: User VF=" << UserVF
474 << " is unsafe. Ignoring scalable UserVF.\n");
475 ORE->emit([&]() {
476 return OptimizationRemarkAnalysis(DEBUG_TYPE, "VectorizationFactor",
477 TheLoop->getStartLoc(),
478 TheLoop->getHeader())
479 << "User-specified vectorization factor "
480 << ore::NV("UserVectorizationFactor", UserVF)
481 << " is unsafe. Ignoring the hint to let the compiler pick a "
482 "more suitable value.";
483 });
484 }
485 }
486
487 LLVM_DEBUG(dbgs() << "LV: The Smallest and Widest types: " << SmallestType
488 << " / " << WidestType << " bits.\n");
489
492 if (auto MaxVF = getMaximizedVFForTarget(
493 MaxTripCount, SmallestType, WidestType, MaxSafeFixedVF, UserIC,
494 FoldTailByMasking, RequiresScalarEpilogue))
495 Result.FixedVF = MaxVF;
496
497 if (auto MaxVF = getMaximizedVFForTarget(
498 MaxTripCount, SmallestType, WidestType, MaxSafeScalableVF, UserIC,
499 FoldTailByMasking, RequiresScalarEpilogue))
500 if (MaxVF.isScalable()) {
501 Result.ScalableVF = MaxVF;
502 LLVM_DEBUG(dbgs() << "LV: Found feasible scalable VF = " << MaxVF
503 << "\n");
504 }
505
506 return Result;
507}
508
509std::pair<unsigned, unsigned>
511 unsigned MinWidth = -1U;
512 unsigned MaxWidth = 8;
513 const DataLayout &DL = F.getDataLayout();
514 // For in-loop reductions, no element types are added to ElementTypesInLoop
515 // if there are no loads/stores in the loop. In this case, check through the
516 // reduction variables to determine the maximum width.
517 if (ElementTypesInLoop.empty() && !Legal->getReductionVars().empty()) {
518 for (const auto &[_, RdxDesc] : Legal->getReductionVars()) {
519 // When finding the min width used by the recurrence we need to account
520 // for casts on the input operands of the recurrence.
521 MinWidth = std::min(
522 MinWidth,
523 std::min(RdxDesc.getMinWidthCastToRecurrenceTypeInBits(),
524 RdxDesc.getRecurrenceType()->getScalarSizeInBits()));
525 MaxWidth = std::max(MaxWidth,
526 RdxDesc.getRecurrenceType()->getScalarSizeInBits());
527 }
528 } else {
529 for (Type *T : ElementTypesInLoop) {
530 MinWidth = std::min<unsigned>(
531 MinWidth, DL.getTypeSizeInBits(T->getScalarType()).getFixedValue());
532 MaxWidth = std::max<unsigned>(
533 MaxWidth, DL.getTypeSizeInBits(T->getScalarType()).getFixedValue());
534 }
535 }
536
537 // If the loop has no loads/stores or reductions (e.g. a search loop with an
538 // early exit), MinWidth is never updated and is left at its sentinel value.
539 // Fall back to MaxWidth to keep the SmallestType <= WidestType invariant, so
540 // callers such as the max-bandwidth VF computation don't divide by the
541 // sentinel and collapse the VF to zero.
542 if (MinWidth == -1U)
543 MinWidth = MaxWidth;
544
545 return {MinWidth, MaxWidth};
546}
547
549 const SmallPtrSetImpl<const Value *> *ValuesToIgnore) {
550 ElementTypesInLoop.clear();
551 // For each block.
552 for (BasicBlock *BB : TheLoop->blocks()) {
553 // For each instruction in the loop.
554 for (Instruction &I : *BB) {
555 Type *T = I.getType();
556
557 // Skip ignored values.
558 if (ValuesToIgnore && ValuesToIgnore->contains(&I))
559 continue;
560
561 // Only examine Loads, Stores and PHINodes.
563 continue;
564
565 // Examine PHI nodes that are reduction variables. Update the type to
566 // account for the recurrence type.
567 if (auto *PN = dyn_cast<PHINode>(&I)) {
568 if (!Legal->isReductionVariable(PN))
569 continue;
570 const RecurrenceDescriptor &RdxDesc =
571 Legal->getRecurrenceDescriptor(PN);
573 TTI.preferInLoopReduction(RdxDesc.getRecurrenceKind(),
574 RdxDesc.getRecurrenceType()))
575 continue;
576 T = RdxDesc.getRecurrenceType();
577 }
578
579 // Examine the stored values.
580 if (auto *ST = dyn_cast<StoreInst>(&I))
581 T = ST->getValueOperand()->getType();
582
583 assert(T->isSized() &&
584 "Expected the load/store/recurrence type to be sized");
585
586 ElementTypesInLoop.insert(T);
587 }
588 }
589}
590
591void VFSelectionContext::initializeVScaleForTuning() {
593 return;
594
595 if (F.hasFnAttribute(Attribute::VScaleRange)) {
596 auto Attr = F.getFnAttribute(Attribute::VScaleRange);
597 auto Min = Attr.getVScaleRangeMin();
598 auto Max = Attr.getVScaleRangeMax();
599 if (Max && Min == Max) {
600 VScaleForTuning = Max;
601 return;
602 }
603 }
604
605 VScaleForTuning = TTI.getVScaleForTuning();
606}
607
609 const RecurrenceDescriptor &RdxDesc) const {
610 return !Hints->allowReordering() && RdxDesc.isOrdered();
611}
612
614 LLVM_DEBUG(dbgs() << "LV: Performing code size checks.\n");
615
616 Loop *L = const_cast<Loop *>(TheLoop);
617 if (Legal->getRuntimePointerChecking()->Need) {
619 "Runtime ptr check is required with -Os/-Oz",
620 "runtime pointer checks needed. Enable vectorization of this "
621 "loop with '#pragma clang loop vectorize(enable)' when "
622 "compiling with -Os/-Oz",
623 "CantVersionLoopWithOptForSize", ORE, L);
624 return true;
625 }
626
627 if (!PSE.getPredicate().isAlwaysTrue()) {
629 "Runtime SCEV check is required with -Os/-Oz",
630 "runtime SCEV checks needed. Enable vectorization of this "
631 "loop with '#pragma clang loop vectorize(enable)' when "
632 "compiling with -Os/-Oz",
633 "CantVersionLoopWithOptForSize", ORE, L);
634 return true;
635 }
636
637 // FIXME: Avoid specializing for stride==1 instead of bailing out.
638 if (!Legal->getLAI()->getSymbolicStrides().empty()) {
640 "Runtime stride check for small trip count",
641 "runtime stride == 1 checks needed. Enable vectorization of "
642 "this loop without such check by compiling with -Os/-Oz",
643 "CantVersionLoopWithOptForSize", ORE, L);
644 return true;
645 }
646
647 return false;
648}
649
651 MinBWs = computeMinimumValueSizes(TheLoop->getBlocks(), *DB, &TTI);
652}
653
655 // Avoid duplicating work finding in-loop reductions.
656 if (!InLoopReductions.empty())
657 return;
658
659 for (const auto &Reduction : Legal->getReductionVars()) {
660 PHINode *Phi = Reduction.first;
661 const RecurrenceDescriptor &RdxDesc = Reduction.second;
662
663 // Multi-use reductions (e.g., used in FindLastIV patterns) are handled
664 // separately and should not be considered for in-loop reductions.
665 if (RdxDesc.hasUsesOutsideReductionChain())
666 continue;
667
668 // We don't collect reductions that are type promoted (yet).
669 if (RdxDesc.getRecurrenceType() != Phi->getType())
670 continue;
671
672 // In-loop AnyOf and FindIV reductions are not yet supported.
673 RecurKind Kind = RdxDesc.getRecurrenceKind();
677 continue;
678
679 // If the target would prefer this reduction to happen "in-loop", then we
680 // want to record it as such.
682 !TTI.preferInLoopReduction(Kind, Phi->getType()))
683 continue;
684
685 // Check that we can correctly put the reductions into the loop, by
686 // finding the chain of operations that leads from the phi to the loop
687 // exit value.
688 SmallVector<Instruction *, 4> ReductionOperations =
689 RdxDesc.getReductionOpChain(Phi, const_cast<Loop *>(TheLoop));
690 bool InLoop = !ReductionOperations.empty();
691
692 if (InLoop) {
693 InLoopReductions.insert(Phi);
694 // Add the elements to InLoopReductionImmediateChains for cost modelling.
695 Instruction *LastChain = Phi;
696 for (auto *I : ReductionOperations) {
697 InLoopReductionImmediateChains[I] = LastChain;
698 LastChain = I;
699 }
700 }
701 LLVM_DEBUG(dbgs() << "LV: Using " << (InLoop ? "inloop" : "out of loop")
702 << " reduction for phi: " << *Phi << "\n");
703 }
704}
705
706bool LoopVectorizationPlanner::isMoreProfitable(const VectorizationFactor &A,
707 const VectorizationFactor &B,
708 const unsigned MaxTripCount,
709 bool HasTail,
710 bool IsEpilogue) const {
711 InstructionCost CostA = A.Cost;
712 InstructionCost CostB = B.Cost;
713
714 // When there is a hint to always prefer scalable vectors, honour that hint.
716 if (A.Width.isScalable() && CostA.isValid() && !B.Width.isScalable() &&
717 !B.Width.isScalar())
718 return true;
719
720 // Favor fixed VFs for epilogue loops by scaling the costs of scalable VFs
721 // 'ScalableEpilogueVFCostScaleFactor' (default 2.0). This is intended to
722 // model that fixed VFs are more likely to be fully unrolled (or optimized
723 // out) post vectorization. TODO: Reconsider this restriction for predicated
724 // epilogues (once supported).
725 if (IsEpilogue && A.Width.isScalable() != B.Width.isScalable() &&
726 A.Cost.isValid() && B.Cost.isValid()) {
727 auto [FixedCost, ScalableCost] = std::make_pair(CostA, CostB);
728 if (B.Width.isFixed())
729 std::swap(FixedCost, ScalableCost);
730
731 ScalableCost *= ScalableEpilogueVFCostScaleFactor;
732
733 if (FixedCost <= ScalableCost)
734 return A.Width.isFixed();
735 }
736
737 // Improve estimate for the vector width if it is scalable.
738 unsigned EstimatedWidthA = A.Width.getKnownMinValue();
739 unsigned EstimatedWidthB = B.Width.getKnownMinValue();
740 if (std::optional<unsigned> VScale = Config.getVScaleForTuning()) {
741 if (A.Width.isScalable())
742 EstimatedWidthA *= *VScale;
743 if (B.Width.isScalable())
744 EstimatedWidthB *= *VScale;
745 }
746
747 // When optimizing for size choose whichever is smallest, which will be the
748 // one with the smallest cost for the whole loop. On a tie pick the larger
749 // vector width, on the assumption that throughput will be greater.
750 if (Config.CostKind == TTI::TCK_CodeSize)
751 return CostA < CostB ||
752 (CostA == CostB && EstimatedWidthA > EstimatedWidthB);
753
754 // Assume vscale may be larger than 1 (or the value being tuned for),
755 // so that scalable vectorization is slightly favorable over fixed-width
756 // vectorization.
757 bool PreferScalable = !TTI.preferFixedOverScalableIfEqualCost() &&
758 A.Width.isScalable() && !B.Width.isScalable();
759
760 auto CmpFn = [PreferScalable](const InstructionCost &LHS,
761 const InstructionCost &RHS) {
762 return PreferScalable ? LHS <= RHS : LHS < RHS;
763 };
764
765 // To avoid the need for FP division:
766 // (CostA / EstimatedWidthA) < (CostB / EstimatedWidthB)
767 // <=> (CostA * EstimatedWidthB) < (CostB * EstimatedWidthA)
768 bool LowerCostWithoutTC =
769 CmpFn(CostA * EstimatedWidthB, CostB * EstimatedWidthA);
770 if (!MaxTripCount)
771 return LowerCostWithoutTC;
772
773 auto GetCostForTC = [MaxTripCount, HasTail](unsigned VF,
774 InstructionCost VectorCost,
775 InstructionCost ScalarCost) {
776 // If the trip count is a known (possibly small) constant, the trip count
777 // will be rounded up to an integer number of iterations under
778 // FoldTailByMasking. The total cost in that case will be
779 // VecCost*ceil(TripCount/VF). When not folding the tail, the total
780 // cost will be VecCost*floor(TC/VF) + ScalarCost*(TC%VF). There will be
781 // some extra overheads, but for the purpose of comparing the costs of
782 // different VFs we can use this to compare the total loop-body cost
783 // expected after vectorization.
784 if (HasTail)
785 return VectorCost * (MaxTripCount / VF) +
786 ScalarCost * (MaxTripCount % VF);
787 return VectorCost * divideCeil(MaxTripCount, VF);
788 };
789
790 auto RTCostA = GetCostForTC(EstimatedWidthA, CostA, A.ScalarCost);
791 auto RTCostB = GetCostForTC(EstimatedWidthB, CostB, B.ScalarCost);
792 bool LowerCostWithTC = CmpFn(RTCostA, RTCostB);
793 LLVM_DEBUG(if (LowerCostWithTC != LowerCostWithoutTC) {
794 dbgs() << "LV: VF " << (LowerCostWithTC ? A.Width : B.Width)
795 << " has lower cost than VF "
796 << (LowerCostWithTC ? B.Width : A.Width)
797 << " when taking the cost of the remaining scalar loop iterations "
798 "into consideration for a maximum trip count of "
799 << MaxTripCount << ".\n";
800 });
801 return LowerCostWithTC;
802}
803
804bool LoopVectorizationPlanner::isMoreProfitable(const VectorizationFactor &A,
805 const VectorizationFactor &B,
806 bool HasTail,
807 bool IsEpilogue) const {
808 const unsigned MaxTripCount = PSE.getSmallConstantMaxTripCount();
809 return LoopVectorizationPlanner::isMoreProfitable(A, B, MaxTripCount, HasTail,
810 IsEpilogue);
811}
812
813// TODO: we could return a pair of values that specify the max VF and
814// min VF, to be used in `buildVPlans(MinVF, MaxVF)` instead of
815// `buildVPlans(VF, VF)`. We cannot do it because VPLAN at the moment
816// doesn't have a cost model that can choose which plan to execute if
817// more than one is generated.
820 if (UserVF.isScalable() && !supportsScalableVectors()) {
822 "Scalable vectorization requested but not supported by the target",
823 "the scalable user-specified vectorization width for outer-loop "
824 "vectorization cannot be used because the target does not support "
825 "scalable vectors.",
826 "ScalableVFUnfeasible", ORE, TheLoop);
828 }
829
830 ElementCount VF = UserVF;
831 if (VF.isZero()) {
832 auto [_, WidestType] = getSmallestAndWidestTypes();
833
834 auto RegKind = TTI.enableScalableVectorization()
837
838 TypeSize RegSize = TTI.getRegisterBitWidth(RegKind);
839 // The widest type may be wider than the register width and WidestType may
840 // not be a power of two; round the element count down to a power of two.
841 unsigned N = std::max<uint64_t>(
842 1, llvm::bit_floor(RegSize.getKnownMinValue() / WidestType));
843 VF = ElementCount::get(N, RegSize.isScalable());
844 LLVM_DEBUG(dbgs() << "LV: VPlan computed VF " << VF << ".\n");
845
846 // Make sure we have a VF > 1 for stress testing.
848 LLVM_DEBUG(dbgs() << "LV: VPlan stress testing: "
849 << "overriding computed VF.\n");
851 }
852 }
854 "VF needs to be a power of two");
855 if (VF.isScalar())
857 LLVM_DEBUG(dbgs() << "LV: Using " << (!UserVF.isZero() ? "user " : "")
858 << "VF " << VF << " to build VPlans.\n");
859 return FixedScalableVFPair(VF);
860}
861
862/// \returns true if the VPlan contains header phi recipes that are not
863/// currently supported for epilogue vectorization.
865 return any_of(
867 [](VPRecipeBase &R) {
868 switch (R.getVPRecipeID()) {
869 case VPRecipeBase::VPFirstOrderRecurrencePHISC:
870 // TODO: Add support for fixed-order recurrences.
871 return true;
872 case VPRecipeBase::VPWidenIntOrFpInductionSC:
873 return !cast<VPWidenIntOrFpInductionRecipe>(&R)->getPHINode();
874 case VPRecipeBase::VPReductionPHISC: {
875 auto *RedPhi = cast<VPReductionPHIRecipe>(&R);
876 // TODO: Support FMinNum/FMaxNum, FindLast reductions, and reductions
877 // without underlying values.
878 RecurKind Kind = RedPhi->getRecurrenceKind();
879 if (RecurrenceDescriptor::isFPMinMaxNumRecurrenceKind(Kind) ||
880 RecurrenceDescriptor::isFindLastRecurrenceKind(Kind) ||
881 !RedPhi->getUnderlyingValue())
882 return true;
883 // TODO: Add support for FindIV reductions with sunk expressions: the
884 // resume value from the main loop is in expression domain (e.g.,
885 // mul(ReducedIV, 3)), but the epilogue tracks raw IV values. A sunk
886 // expression is identified by a non-VPInstruction user of
887 // ComputeReductionResult.
888 if (RecurrenceDescriptor::isFindIVRecurrenceKind(Kind)) {
889 auto *RdxResult = vputils::findComputeReductionResult(RedPhi);
890 assert(RdxResult &&
891 "FindIV reduction must have ComputeReductionResult");
892 return any_of(RdxResult->users(),
893 std::not_fn(IsaPred<VPInstruction>));
894 }
895 return false;
896 }
897 default:
898 return false;
899 };
900 });
901}
902
903bool LoopVectorizationPlanner::isCandidateForEpilogueVectorization(
904 VPlan &MainPlan) const {
905 // Bail out if the plan contains header phi recipes not yet supported
906 // for epilogue vectorization.
907 if (hasUnsupportedHeaderPhiRecipe(MainPlan))
908 return false;
909
910 // Epilogue vectorization code has not been auditted to ensure it handles
911 // non-latch exits properly. It may be fine, but it needs auditted and
912 // tested.
913 // TODO: Add support for loops with an early exit.
914 if (OrigLoop->getExitingBlock() != OrigLoop->getLoopLatch())
915 return false;
916
917 return true;
918}
unsigned RegSize
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
unsigned uint64_t
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")
#define DEBUG_TYPE
#define _
loop Loop Strength Reduction
This file defines the LoopVectorizationLegality class.
static cl::opt< float > ScalableEpilogueVFCostScaleFactor("scalable-epilogue-vf-cost-scale-factor", cl::init(2.0), cl::Hidden, cl::desc("Scale the cost of scalable epilogue VFs by this factor."))
static bool hasUnsupportedHeaderPhiRecipe(VPlan &Plan)
static void debugVectorizationMessage(const StringRef Prefix, const StringRef DebugMsg, Instruction *I)
Write a DebugMsg about vectorization to the debug output stream.
static cl::opt< bool > ForceTargetSupportsGatherScatterOps("force-target-supports-gather-scatter-ops", cl::init(false), cl::Hidden, cl::desc("Assume the target supports gather/scatter operations (used for " "testing)."))
cl::opt< bool > VPlanBuildOuterloopStressTest
static cl::opt< bool > ForceTargetSupportsScalableVectors("force-target-supports-scalable-vectors", cl::init(false), cl::Hidden, cl::desc("Pretend that scalable vectors are supported, even if the target does " "not support them. This flag should only be used for testing."))
static cl::opt< bool > ConsiderRegPressure("vectorizer-consider-reg-pressure", cl::init(false), cl::Hidden, cl::desc("Discard VFs if their register pressure is too high."))
static cl::opt< bool > UseWiderVFIfCallVariantsPresent("vectorizer-maximize-bandwidth-for-vector-calls", cl::init(true), cl::Hidden, cl::desc("Try wider VFs if they enable the use of vector variants"))
static OptimizationRemarkAnalysis createLVAnalysis(StringRef RemarkName, const Loop *TheLoop, Instruction *I, DebugLoc DL={})
Create an analysis remark that explains why vectorization failed RemarkName is the identifier for the...
static cl::opt< bool > ForceTargetSupportsMaskedMemoryOps("force-target-supports-masked-memory-ops", cl::init(false), cl::Hidden, cl::desc("Assume the target supports masked memory operations (used for " "testing)."))
Note: This currently only applies to llvm.masked.load and llvm.masked.store.
static cl::opt< bool > MaximizeBandwidth("vectorizer-maximize-bandwidth", cl::init(false), cl::Hidden, cl::desc("Maximize bandwidth when selecting vectorization factor which " "will be determined by the smallest type in loop."))
This file provides a LoopVectorizationPlanner class.
#define F(x, y, z)
Definition MD5.cpp:54
#define I(x, y, z)
Definition MD5.cpp:57
#define T
const char * Msg
#define LLVM_DEBUG(...)
Definition Debug.h:119
Value * RHS
Value * LHS
LLVM Basic Block Representation.
Definition BasicBlock.h:62
A parsed version of the target data layout string in and methods for querying it.
Definition DataLayout.h:64
A debug info location.
Definition DebugLoc.h:126
static constexpr ElementCount getScalable(ScalarTy MinVal)
Definition TypeSize.h:308
static constexpr ElementCount getFixed(ScalarTy MinVal)
Definition TypeSize.h:305
static constexpr ElementCount get(ScalarTy MinVal, bool Scalable)
Definition TypeSize.h:311
constexpr bool isScalar() const
Exactly one element.
Definition TypeSize.h:316
bool isInnermost() const
Return true if the loop does not contain any (natural) loops.
BlockT * getHeader() const
bool hasVectorCallVariants() const
Returns true if there is at least one function call in the loop which has a vectorized variant availa...
Represents a single loop in the control flow graph.
Definition LoopInfo.h:40
DebugLoc getStartLoc() const
Return the debug location of the start of this loop.
Definition LoopInfo.cpp:695
Diagnostic information for optimization analysis remarks.
The optimization diagnostic interface.
LLVM_ABI void emit(DiagnosticInfoOptimizationBase &OptDiag)
Output the remark via the diagnostic handler and to the optimization record file.
Diagnostic information for applied optimization remarks.
The RecurrenceDescriptor is used to identify recurrences variables in a loop.
Type * getRecurrenceType() const
Returns the type of the recurrence.
bool hasUsesOutsideReductionChain() const
Returns true if the reduction PHI has any uses outside the reduction chain.
static bool isFindLastRecurrenceKind(RecurKind Kind)
Returns true if the recurrence kind is of the form select(cmp(),x,y) where one of (x,...
LLVM_ABI SmallVector< Instruction *, 4 > getReductionOpChain(PHINode *Phi, Loop *L) const
Attempts to find a chain of operations from Phi to LoopExitInst that can be treated as a set of reduc...
static bool isAnyOfRecurrenceKind(RecurKind Kind)
Returns true if the recurrence kind is of the form select(cmp(),x,y) where one of (x,...
RecurKind getRecurrenceKind() const
bool isOrdered() const
Expose an ordered FP reduction to the instance users.
static bool isFindIVRecurrenceKind(RecurKind Kind)
Returns true if the recurrence kind is of the form select(cmp(),x,y) where one of (x,...
A templated base class for SmallPtrSet which provides the typesafe interface that is common across al...
bool contains(ConstPtrType Ptr) const
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
Represent a constant reference to a string, i.e.
Definition StringRef.h:56
@ TCK_CodeSize
Instruction code size.
The instances of the Type class are immutable: once they are created, they are never changed.
Definition Type.h:46
bool isVoidTy() const
Return true if this is 'void'.
Definition Type.h:141
FixedScalableVFPair computeVPlanOuterloopVF(ElementCount UserVF)
Returns a scalable VF to use for outer-loop vectorization if the target supports it and a fixed VF ot...
std::pair< unsigned, unsigned > getSmallestAndWidestTypes() const
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.
FixedScalableVFPair computeFeasibleMaxVF(unsigned MaxTripCount, ElementCount UserVF, unsigned UserIC, bool FoldTailByMasking, bool RequiresScalarEpilogue)
const LoopVectorizeHints & getHints() const
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.
iterator_range< iterator > phis()
Returns an iterator range over the PHI-like recipes in the block.
Definition VPlan.h:4541
const VPBasicBlock * getEntryBasicBlock() const
Definition VPlan.cpp:216
VPRecipeBase is a base class modeling a sequence of one or more output IR instructions.
Definition VPlan.h:412
VPlan models a candidate for vectorization, encoding various decisions take to produce efficient outp...
Definition VPlan.h:4865
LLVM_ABI_FOR_TEST VPRegionBlock * getVectorLoopRegion()
Returns the VPRegionBlock of the vector loop.
Definition VPlan.cpp:1086
static constexpr bool isKnownLE(const FixedOrScalableQuantity &LHS, const FixedOrScalableQuantity &RHS)
Definition TypeSize.h:230
static constexpr bool isKnownLT(const FixedOrScalableQuantity &LHS, const FixedOrScalableQuantity &RHS)
Definition TypeSize.h:216
constexpr bool isScalable() const
Returns whether the quantity is scaled by a runtime quantity (vscale).
Definition TypeSize.h:168
constexpr ScalarTy getKnownMinValue() const
Returns the minimum value this quantity can represent.
Definition TypeSize.h:165
constexpr bool isZero() const
Definition TypeSize.h:153
static constexpr bool isKnownGT(const FixedOrScalableQuantity &LHS, const FixedOrScalableQuantity &RHS)
Definition TypeSize.h:223
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.
initializer< Ty > init(const Ty &Val)
DiagnosticInfoOptimizationBase::Argument NV
This is an optimization pass for GlobalISel generic memory operations.
bool all_of(R &&range, UnaryPredicate P)
Provide wrappers to std::all_of which take ranges instead of having to pass begin/end explicitly.
Definition STLExtras.h:1739
decltype(auto) dyn_cast(const From &Val)
dyn_cast<X> - Return the argument parameter cast to the specified type.
Definition Casting.h:643
bool any_of(R &&range, UnaryPredicate P)
Provide wrappers to std::any_of which take ranges instead of having to pass begin/end explicitly.
Definition STLExtras.h:1746
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
LLVM_ABI raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
Definition Debug.cpp:209
bool isa(const From &Val)
isa<X> - Return true if the parameter to the template is an instance of one of the template type argu...
Definition Casting.h:547
constexpr T divideCeil(U Numerator, V Denominator)
Returns the integer ceil(Numerator / Denominator).
Definition MathExtras.h:389
TargetTransformInfo TTI
RecurKind
These are the kinds of recurrences that we support.
std::optional< unsigned > getMaxVScale(const Function &F)
T bit_floor(T Value)
Returns the largest integral power of two no greater than Value if Value is nonzero.
Definition bit.h:347
Type * toVectorTy(Type *Scalar, ElementCount EC)
A helper function for converting Scalar types to vector types.
LLVM_ABI MapVector< Instruction *, uint64_t > computeMinimumValueSizes(ArrayRef< BasicBlock * > Blocks, DemandedBits &DB, const TargetTransformInfo *TTI=nullptr)
Compute a map of integer instructions to their minimum legal type size.
cl::opt< bool > PreferInLoopReductions
void swap(llvm::BitVector &LHS, llvm::BitVector &RHS)
Implement std::swap in terms of BitVector swap.
Definition BitVector.h:880
#define N
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).
static FixedScalableVFPair getNone()
TODO: The following VectorizationFactor was pulled out of LoopVectorizationCostModel class.
static LLVM_ABI ElementCount VectorizationFactor
VF as overridden by the user.