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
21#include "llvm/Support/Debug.h"
25
26using namespace llvm;
27using namespace LoopVectorizationUtils;
28
29#define DEBUG_TYPE "loop-vectorize"
30
32
34 "vectorizer-maximize-bandwidth", cl::init(false), cl::Hidden,
35 cl::desc("Maximize bandwidth when selecting vectorization factor which "
36 "will be determined by the smallest type in loop."));
37
39 "vectorizer-maximize-bandwidth-for-vector-calls", cl::init(true),
41 cl::desc("Try wider VFs if they enable the use of vector variants"));
42
44 "vectorizer-consider-reg-pressure", cl::init(false), cl::Hidden,
45 cl::desc("Discard VFs if their register pressure is too high."));
46
48 "force-target-supports-scalable-vectors", cl::init(false), cl::Hidden,
50 "Pretend that scalable vectors are supported, even if the target does "
51 "not support them. This flag should only be used for testing."));
52
54 "prefer-inloop-reductions", cl::init(false), cl::Hidden,
55 cl::desc("Prefer in-loop vector reductions, "
56 "overriding the targets preference."));
57
58/// Note: This currently only applies to `llvm.masked.load` and
59/// `llvm.masked.store`. TODO: Extend this to cover other operations as needed.
61 "force-target-supports-masked-memory-ops", cl::init(false), cl::Hidden,
62 cl::desc("Assume the target supports masked memory operations (used for "
63 "testing)."));
64
66 "force-target-supports-gather-scatter-ops", cl::init(false), cl::Hidden,
67 cl::desc("Assume the target supports gather/scatter operations (used for "
68 "testing)."));
69
70/// Write a \p DebugMsg about vectorization to the debug output stream. If \p I
71/// is passed, the message relates to that particular instruction.
72#ifndef NDEBUG
73static void debugVectorizationMessage(const StringRef Prefix,
74 const StringRef DebugMsg,
75 Instruction *I) {
76 dbgs() << "LV: " << Prefix << DebugMsg;
77 if (I != nullptr)
78 dbgs() << " " << *I;
79 else
80 dbgs() << '.';
81 dbgs() << '\n';
82}
83#endif
84
85/// Create an analysis remark that explains why vectorization failed
86/// \p RemarkName is the identifier for the remark. If \p I is passed it is an
87/// instruction that prevents vectorization. Otherwise \p TheLoop is used for
88/// the location of the remark. If \p DL is passed, use it as debug location for
89/// the remark. \return the remark object that can be streamed to.
91 const Loop *TheLoop,
93 DebugLoc DL = {}) {
94 BasicBlock *CodeRegion = I ? I->getParent() : TheLoop->getHeader();
95 // If debug location is attached to the instruction, use it. Otherwise if DL
96 // was not provided, use the loop's.
97 if (I && I->getDebugLoc())
98 DL = I->getDebugLoc();
99 else if (!DL)
100 DL = TheLoop->getStartLoc();
101
102 return OptimizationRemarkAnalysis(DEBUG_TYPE, RemarkName, DL, CodeRegion);
103}
104
106 const StringRef DebugMsg, const StringRef OREMsg, const StringRef ORETag,
107 OptimizationRemarkEmitter *ORE, const Loop *TheLoop, Instruction *I) {
108 LLVM_DEBUG(debugVectorizationMessage("Not vectorizing: ", DebugMsg, I));
109 ORE->emit(createLVAnalysis(ORETag, TheLoop, I)
110 << "loop not vectorized: " << OREMsg);
111}
112
114 const StringRef Msg, const StringRef ORETag, OptimizationRemarkEmitter *ORE,
115 const Loop *TheLoop, Instruction *I, DebugLoc DL) {
117 ORE->emit(createLVAnalysis(ORETag, TheLoop, I, DL) << Msg);
118}
119
121 Loop *TheLoop,
122 ElementCount VFWidth,
123 unsigned IC) {
125 "Vectorizing: ", TheLoop->isInnermost() ? "innermost loop" : "outer loop",
126 nullptr));
127 StringRef LoopType = TheLoop->isInnermost() ? "" : "outer ";
128 ORE->emit([&]() {
129 return OptimizationRemark(DEBUG_TYPE, "Vectorized", TheLoop->getStartLoc(),
130 TheLoop->getHeader())
131 << "vectorized " << LoopType << "loop (vectorization width: "
132 << ore::NV("VectorizationFactor", VFWidth)
133 << ", interleaved count: " << ore::NV("InterleaveCount", IC) << ")";
134 });
135}
136
138 Align Alignment,
139 unsigned AddressSpace) const {
141 (IsLoad ? TTI.isLegalMaskedLoad(ScalarTy, Alignment, AddressSpace)
142 : TTI.isLegalMaskedStore(ScalarTy, Alignment, AddressSpace));
143}
144
146 ElementCount VF) const {
147 bool LI = isa<LoadInst>(V);
148 bool SI = isa<StoreInst>(V);
149 if (!LI && !SI)
150 return false;
151 auto *Ty = getLoadStoreType(V);
153 if (VF.isVector())
154 Ty = VectorType::get(Ty, VF);
156 (LI && TTI.isLegalMaskedGather(Ty, Align)) ||
157 (SI && TTI.isLegalMaskedScatter(Ty, Align));
158}
159
161 return TTI.supportsScalableVectors() || ForceTargetSupportsScalableVectors ||
163}
164
165bool VFSelectionContext::useMaxBandwidth(bool IsScalable) const {
169 return MaximizeBandwidth || (MaximizeBandwidth.getNumOccurrences() == 0 &&
170 (TTI.shouldMaximizeVectorBandwidth(RegKind) ||
172 Legal->hasVectorCallVariants())));
173}
174
176 if (ConsiderRegPressure.getNumOccurrences())
177 return ConsiderRegPressure;
178
179 // TODO: We should eventually consider register pressure for all targets. The
180 // TTI hook is temporary whilst target-specific issues are being fixed.
181 if (TTI.shouldConsiderVectorizationRegPressure())
182 return true;
183
184 if (!useMaxBandwidth(VF.isScalable()))
185 return false;
186 // Only calculate register pressure for VFs enabled by MaxBandwidth.
188 VF, VF.isScalable() ? MaxPermissibleVFWithoutMaxBW.ScalableVF
189 : MaxPermissibleVFWithoutMaxBW.FixedVF);
190}
191
192ElementCount VFSelectionContext::clampVFByMaxTripCount(
193 ElementCount VF, unsigned MaxTripCount, unsigned UserIC,
194 bool FoldTailByMasking, bool RequiresScalarEpilogue) const {
195 unsigned EstimatedVF = VF.getKnownMinValue();
196 if (VF.isScalable() && F.hasFnAttribute(Attribute::VScaleRange)) {
197 auto Attr = F.getFnAttribute(Attribute::VScaleRange);
198 auto Min = Attr.getVScaleRangeMin();
199 EstimatedVF *= Min;
200 }
201
202 // When a scalar epilogue is required, at least one iteration of the scalar
203 // loop has to execute. Adjust MaxTripCount accordingly to avoid picking a
204 // max VF that results in a dead vector loop.
205 if (MaxTripCount > 0 && RequiresScalarEpilogue)
206 MaxTripCount -= 1;
207
208 // When the user specifies an interleave count, we need to ensure that
209 // VF * UserIC <= MaxTripCount to avoid a dead vector loop.
210 unsigned IC = UserIC > 0 ? UserIC : 1;
211 unsigned EstimatedVFTimesIC = EstimatedVF * IC;
212
213 if (MaxTripCount && MaxTripCount <= EstimatedVFTimesIC &&
214 (!FoldTailByMasking || isPowerOf2_32(MaxTripCount))) {
215 // If upper bound loop trip count (TC) is known at compile time there is no
216 // point in choosing VF greater than TC / IC (as done in the loop below).
217 // Select maximum power of two which doesn't exceed TC / IC. If VF is
218 // scalable, we only fall back on a fixed VF when the TC is less than or
219 // equal to the known number of lanes.
220 auto ClampedUpperTripCount = llvm::bit_floor(MaxTripCount / IC);
221 if (ClampedUpperTripCount == 0)
222 ClampedUpperTripCount = 1;
223 LLVM_DEBUG(dbgs() << "LV: Clamping the MaxVF to maximum power of two not "
224 "exceeding the constant trip count"
225 << (UserIC > 0 ? " divided by UserIC" : "") << ": "
226 << ClampedUpperTripCount << "\n");
227 return ElementCount::get(ClampedUpperTripCount,
228 FoldTailByMasking ? VF.isScalable() : false);
229 }
230 return VF;
231}
232
233ElementCount VFSelectionContext::getMaximizedVFForTarget(
234 unsigned MaxTripCount, unsigned SmallestType, unsigned WidestType,
235 ElementCount MaxSafeVF, unsigned UserIC, bool FoldTailByMasking,
236 bool RequiresScalarEpilogue) {
237 bool ComputeScalableMaxVF = MaxSafeVF.isScalable();
238 const TypeSize WidestRegister = TTI.getRegisterBitWidth(
239 ComputeScalableMaxVF ? TargetTransformInfo::RGK_ScalableVector
241
242 // Convenience function to return the minimum of two ElementCounts.
243 auto MinVF = [](const ElementCount &LHS, const ElementCount &RHS) {
244 assert((LHS.isScalable() == RHS.isScalable()) &&
245 "Scalable flags must match");
247 };
248
249 // Ensure MaxVF is a power of 2; the dependence distance bound may not be.
250 // Note that both WidestRegister and WidestType may not be a powers of 2.
251 auto MaxVectorElementCount = ElementCount::get(
252 llvm::bit_floor(WidestRegister.getKnownMinValue() / WidestType),
253 ComputeScalableMaxVF);
254 MaxVectorElementCount = MinVF(MaxVectorElementCount, MaxSafeVF);
255 LLVM_DEBUG(dbgs() << "LV: The Widest register safe to use is: "
256 << (MaxVectorElementCount * WidestType) << " bits.\n");
257
258 if (!MaxVectorElementCount) {
259 LLVM_DEBUG(dbgs() << "LV: The target has no "
260 << (ComputeScalableMaxVF ? "scalable" : "fixed")
261 << " vector registers.\n");
262 return ElementCount::getFixed(1);
263 }
264
265 ElementCount MaxVF =
266 clampVFByMaxTripCount(MaxVectorElementCount, MaxTripCount, UserIC,
267 FoldTailByMasking, RequiresScalarEpilogue);
268 // If the MaxVF was already clamped, there's no point in trying to pick a
269 // larger one.
270 if (MaxVF != MaxVectorElementCount)
271 return MaxVF;
272
273 if (MaxVF.isScalable())
274 MaxPermissibleVFWithoutMaxBW.ScalableVF = MaxVF;
275 else
276 MaxPermissibleVFWithoutMaxBW.FixedVF = MaxVF;
277
278 if (useMaxBandwidth(ComputeScalableMaxVF)) {
279 auto MaxVectorElementCountMaxBW = ElementCount::get(
280 llvm::bit_floor(WidestRegister.getKnownMinValue() / SmallestType),
281 ComputeScalableMaxVF);
282 MaxVF = MinVF(MaxVectorElementCountMaxBW, MaxSafeVF);
283
284 if (ElementCount MinVF =
285 TTI.getMinimumVF(SmallestType, ComputeScalableMaxVF)) {
286 if (ElementCount::isKnownLT(MaxVF, MinVF)) {
287 LLVM_DEBUG(dbgs() << "LV: Overriding calculated MaxVF(" << MaxVF
288 << ") with target's minimum: " << MinVF << '\n');
289 MaxVF = MinVF;
290 }
291 }
292
293 MaxVF = clampVFByMaxTripCount(MaxVF, MaxTripCount, UserIC,
294 FoldTailByMasking, RequiresScalarEpilogue);
295 }
296 return MaxVF;
297}
298
299std::optional<unsigned> llvm::getMaxVScale(const Function &F,
300 const TargetTransformInfo &TTI) {
301 if (std::optional<unsigned> MaxVScale = TTI.getMaxVScale())
302 return MaxVScale;
303
304 if (F.hasFnAttribute(Attribute::VScaleRange))
305 return F.getFnAttribute(Attribute::VScaleRange).getVScaleRangeMax();
306
307 return std::nullopt;
308}
309
310bool VFSelectionContext::isScalableVectorizationAllowed() {
311 if (IsScalableVectorizationAllowed)
312 return *IsScalableVectorizationAllowed;
313
314 IsScalableVectorizationAllowed = false;
316 return false;
317
318 if (Hints->isScalableVectorizationDisabled()) {
319 reportVectorizationInfo("Scalable vectorization is explicitly disabled",
320 "ScalableVectorizationDisabled", ORE, TheLoop);
321 return false;
322 }
323
324 LLVM_DEBUG(dbgs() << "LV: Scalable vectorization is available\n");
325
326 auto MaxScalableVF = ElementCount::getScalable(
327 std::numeric_limits<ElementCount::ScalarTy>::max());
328
329 // Test that the loop-vectorizer can legalize all operations for this MaxVF.
330 // FIXME: While for scalable vectors this is currently sufficient, this should
331 // be replaced by a more detailed mechanism that filters out specific VFs,
332 // instead of invalidating vectorization for a whole set of VFs based on the
333 // MaxVF.
334
335 // Disable scalable vectorization if the loop contains unsupported reductions.
336 if (!all_of(Legal->getReductionVars(), [&](const auto &Reduction) -> bool {
337 return TTI.isLegalToVectorizeReduction(Reduction.second, MaxScalableVF);
338 })) {
340 "Scalable vectorization not supported for the reduction "
341 "operations found in this loop.",
342 "ScalableVFUnfeasible", ORE, TheLoop);
343 return false;
344 }
345
346 // Disable scalable vectorization if the loop contains any instructions
347 // with element types not supported for scalable vectors.
348 if (any_of(ElementTypesInLoop, [&](Type *Ty) {
349 return !Ty->isVoidTy() && !TTI.isElementTypeLegalForScalableVector(Ty);
350 })) {
351 reportVectorizationInfo("Scalable vectorization is not supported "
352 "for all element types found in this loop.",
353 "ScalableVFUnfeasible", ORE, TheLoop);
354 return false;
355 }
356
357 if (!Legal->isSafeForAnyVectorWidth() && !getMaxVScale(F, TTI)) {
358 reportVectorizationInfo("The target does not provide maximum vscale value "
359 "for safe distance analysis.",
360 "ScalableVFUnfeasible", ORE, TheLoop);
361 return false;
362 }
363
364 IsScalableVectorizationAllowed = true;
365 return true;
366}
367
369VFSelectionContext::getMaxLegalScalableVF(unsigned MaxSafeElements) {
370 if (!isScalableVectorizationAllowed())
372
373 auto MaxScalableVF = ElementCount::getScalable(
374 std::numeric_limits<ElementCount::ScalarTy>::max());
375 if (Legal->isSafeForAnyVectorWidth())
376 return MaxScalableVF;
377
378 std::optional<unsigned> MaxVScale = getMaxVScale(F, TTI);
379 // Limit MaxScalableVF by the maximum safe dependence distance.
380 MaxScalableVF = ElementCount::getScalable(MaxSafeElements / *MaxVScale);
381
382 if (!MaxScalableVF)
384 "Max legal vector width too small, scalable vectorization "
385 "unfeasible.",
386 "ScalableVFUnfeasible", ORE, TheLoop);
387
388 return MaxScalableVF;
389}
390
392 unsigned MaxTripCount, ElementCount UserVF, unsigned UserIC,
393 bool FoldTailByMasking, bool RequiresScalarEpilogue) {
394 auto [SmallestType, WidestType] = getSmallestAndWidestTypes();
395
396 // Get the maximum safe dependence distance in bits computed by LAA.
397 // It is computed by MaxVF * sizeOf(type) * 8, where type is taken from
398 // the memory accesses that is most restrictive (involved in the smallest
399 // dependence distance).
400 unsigned MaxSafeElementsPowerOf2 =
401 llvm::bit_floor(Legal->getMaxSafeVectorWidthInBits() / WidestType);
402 if (!Legal->isSafeForAnyStoreLoadForwardDistances()) {
403 unsigned SLDist = Legal->getMaxStoreLoadForwardSafeDistanceInBits();
404 MaxSafeElementsPowerOf2 =
405 std::min(MaxSafeElementsPowerOf2, SLDist / WidestType);
406 }
407
408 auto MaxSafeFixedVF = ElementCount::getFixed(MaxSafeElementsPowerOf2);
409 auto MaxSafeScalableVF = getMaxLegalScalableVF(MaxSafeElementsPowerOf2);
410
411 if (!Legal->isSafeForAnyVectorWidth())
412 MaxSafeElements = MaxSafeElementsPowerOf2;
413
414 LLVM_DEBUG(dbgs() << "LV: The max safe fixed VF is: " << MaxSafeFixedVF
415 << ".\n");
416 LLVM_DEBUG(dbgs() << "LV: The max safe scalable VF is: " << MaxSafeScalableVF
417 << ".\n");
418
419 // First analyze the UserVF, fall back if the UserVF should be ignored.
420 if (UserVF) {
421 auto MaxSafeUserVF =
422 UserVF.isScalable() ? MaxSafeScalableVF : MaxSafeFixedVF;
423
424 if (ElementCount::isKnownLE(UserVF, MaxSafeUserVF)) {
425 // If `VF=vscale x N` is safe, then so is `VF=N`
426 if (UserVF.isScalable())
427 return FixedScalableVFPair(
428 ElementCount::getFixed(UserVF.getKnownMinValue()), UserVF);
429
430 return UserVF;
431 }
432
433 assert(ElementCount::isKnownGT(UserVF, MaxSafeUserVF));
434
435 // Only clamp if the UserVF is not scalable. If the UserVF is scalable, it
436 // is better to ignore the hint and let the compiler choose a suitable VF.
437 if (!UserVF.isScalable()) {
438 LLVM_DEBUG(dbgs() << "LV: User VF=" << UserVF
439 << " is unsafe, clamping to max safe VF="
440 << MaxSafeFixedVF << ".\n");
441 ORE->emit([&]() {
442 return OptimizationRemarkAnalysis(DEBUG_TYPE, "VectorizationFactor",
443 TheLoop->getStartLoc(),
444 TheLoop->getHeader())
445 << "User-specified vectorization factor "
446 << ore::NV("UserVectorizationFactor", UserVF)
447 << " is unsafe, clamping to maximum safe vectorization factor "
448 << ore::NV("VectorizationFactor", MaxSafeFixedVF);
449 });
450 return MaxSafeFixedVF;
451 }
452
454 LLVM_DEBUG(dbgs() << "LV: User VF=" << UserVF
455 << " is ignored because scalable vectors are not "
456 "available.\n");
457 ORE->emit([&]() {
458 return OptimizationRemarkAnalysis(DEBUG_TYPE, "VectorizationFactor",
459 TheLoop->getStartLoc(),
460 TheLoop->getHeader())
461 << "User-specified vectorization factor "
462 << ore::NV("UserVectorizationFactor", UserVF)
463 << " is ignored because the target does not support scalable "
464 "vectors. The compiler will pick a more suitable value.";
465 });
466 } else {
467 LLVM_DEBUG(dbgs() << "LV: User VF=" << UserVF
468 << " is unsafe. Ignoring scalable UserVF.\n");
469 ORE->emit([&]() {
470 return OptimizationRemarkAnalysis(DEBUG_TYPE, "VectorizationFactor",
471 TheLoop->getStartLoc(),
472 TheLoop->getHeader())
473 << "User-specified vectorization factor "
474 << ore::NV("UserVectorizationFactor", UserVF)
475 << " is unsafe. Ignoring the hint to let the compiler pick a "
476 "more suitable value.";
477 });
478 }
479 }
480
481 LLVM_DEBUG(dbgs() << "LV: The Smallest and Widest types: " << SmallestType
482 << " / " << WidestType << " bits.\n");
483
486 if (auto MaxVF = getMaximizedVFForTarget(
487 MaxTripCount, SmallestType, WidestType, MaxSafeFixedVF, UserIC,
488 FoldTailByMasking, RequiresScalarEpilogue))
489 Result.FixedVF = MaxVF;
490
491 if (auto MaxVF = getMaximizedVFForTarget(
492 MaxTripCount, SmallestType, WidestType, MaxSafeScalableVF, UserIC,
493 FoldTailByMasking, RequiresScalarEpilogue))
494 if (MaxVF.isScalable()) {
495 Result.ScalableVF = MaxVF;
496 LLVM_DEBUG(dbgs() << "LV: Found feasible scalable VF = " << MaxVF
497 << "\n");
498 }
499
500 return Result;
501}
502
503std::pair<unsigned, unsigned>
505 unsigned MinWidth = -1U;
506 unsigned MaxWidth = 8;
507 const DataLayout &DL = F.getDataLayout();
508 // For in-loop reductions, no element types are added to ElementTypesInLoop
509 // if there are no loads/stores in the loop. In this case, check through the
510 // reduction variables to determine the maximum width.
511 if (ElementTypesInLoop.empty() && !Legal->getReductionVars().empty()) {
512 for (const auto &[_, RdxDesc] : Legal->getReductionVars()) {
513 // When finding the min width used by the recurrence we need to account
514 // for casts on the input operands of the recurrence.
515 MinWidth = std::min(
516 MinWidth,
517 std::min(RdxDesc.getMinWidthCastToRecurrenceTypeInBits(),
518 RdxDesc.getRecurrenceType()->getScalarSizeInBits()));
519 MaxWidth = std::max(MaxWidth,
520 RdxDesc.getRecurrenceType()->getScalarSizeInBits());
521 }
522 } else {
523 for (Type *T : ElementTypesInLoop) {
524 MinWidth = std::min<unsigned>(
525 MinWidth, DL.getTypeSizeInBits(T->getScalarType()).getFixedValue());
526 MaxWidth = std::max<unsigned>(
527 MaxWidth, DL.getTypeSizeInBits(T->getScalarType()).getFixedValue());
528 }
529 }
530 return {MinWidth, MaxWidth};
531}
532
534 const SmallPtrSetImpl<const Value *> *ValuesToIgnore) {
535 ElementTypesInLoop.clear();
536 // For each block.
537 for (BasicBlock *BB : TheLoop->blocks()) {
538 // For each instruction in the loop.
539 for (Instruction &I : *BB) {
540 Type *T = I.getType();
541
542 // Skip ignored values.
543 if (ValuesToIgnore && ValuesToIgnore->contains(&I))
544 continue;
545
546 // Only examine Loads, Stores and PHINodes.
548 continue;
549
550 // Examine PHI nodes that are reduction variables. Update the type to
551 // account for the recurrence type.
552 if (auto *PN = dyn_cast<PHINode>(&I)) {
553 if (!Legal->isReductionVariable(PN))
554 continue;
555 const RecurrenceDescriptor &RdxDesc =
556 Legal->getRecurrenceDescriptor(PN);
558 TTI.preferInLoopReduction(RdxDesc.getRecurrenceKind(),
559 RdxDesc.getRecurrenceType()))
560 continue;
561 T = RdxDesc.getRecurrenceType();
562 }
563
564 // Examine the stored values.
565 if (auto *ST = dyn_cast<StoreInst>(&I))
566 T = ST->getValueOperand()->getType();
567
568 assert(T->isSized() &&
569 "Expected the load/store/recurrence type to be sized");
570
571 ElementTypesInLoop.insert(T);
572 }
573 }
574}
575
576void VFSelectionContext::initializeVScaleForTuning() {
578 return;
579
580 if (F.hasFnAttribute(Attribute::VScaleRange)) {
581 auto Attr = F.getFnAttribute(Attribute::VScaleRange);
582 auto Min = Attr.getVScaleRangeMin();
583 auto Max = Attr.getVScaleRangeMax();
584 if (Max && Min == Max) {
585 VScaleForTuning = Max;
586 return;
587 }
588 }
589
590 VScaleForTuning = TTI.getVScaleForTuning();
591}
592
594 const RecurrenceDescriptor &RdxDesc) const {
595 return !Hints->allowReordering() && RdxDesc.isOrdered();
596}
597
599 LLVM_DEBUG(dbgs() << "LV: Performing code size checks.\n");
600
601 Loop *L = const_cast<Loop *>(TheLoop);
602 if (Legal->getRuntimePointerChecking()->Need) {
604 "Runtime ptr check is required with -Os/-Oz",
605 "runtime pointer checks needed. Enable vectorization of this "
606 "loop with '#pragma clang loop vectorize(enable)' when "
607 "compiling with -Os/-Oz",
608 "CantVersionLoopWithOptForSize", ORE, L);
609 return true;
610 }
611
612 if (!PSE.getPredicate().isAlwaysTrue()) {
614 "Runtime SCEV check is required with -Os/-Oz",
615 "runtime SCEV checks needed. Enable vectorization of this "
616 "loop with '#pragma clang loop vectorize(enable)' when "
617 "compiling with -Os/-Oz",
618 "CantVersionLoopWithOptForSize", ORE, L);
619 return true;
620 }
621
622 // FIXME: Avoid specializing for stride==1 instead of bailing out.
623 if (!Legal->getLAI()->getSymbolicStrides().empty()) {
625 "Runtime stride check for small trip count",
626 "runtime stride == 1 checks needed. Enable vectorization of "
627 "this loop without such check by compiling with -Os/-Oz",
628 "CantVersionLoopWithOptForSize", ORE, L);
629 return true;
630 }
631
632 return false;
633}
634
636 MinBWs = computeMinimumValueSizes(TheLoop->getBlocks(), *DB, &TTI);
637}
638
640 // Avoid duplicating work finding in-loop reductions.
641 if (!InLoopReductions.empty())
642 return;
643
644 for (const auto &Reduction : Legal->getReductionVars()) {
645 PHINode *Phi = Reduction.first;
646 const RecurrenceDescriptor &RdxDesc = Reduction.second;
647
648 // Multi-use reductions (e.g., used in FindLastIV patterns) are handled
649 // separately and should not be considered for in-loop reductions.
650 if (RdxDesc.hasUsesOutsideReductionChain())
651 continue;
652
653 // We don't collect reductions that are type promoted (yet).
654 if (RdxDesc.getRecurrenceType() != Phi->getType())
655 continue;
656
657 // In-loop AnyOf and FindIV reductions are not yet supported.
658 RecurKind Kind = RdxDesc.getRecurrenceKind();
662 continue;
663
664 // If the target would prefer this reduction to happen "in-loop", then we
665 // want to record it as such.
667 !TTI.preferInLoopReduction(Kind, Phi->getType()))
668 continue;
669
670 // Check that we can correctly put the reductions into the loop, by
671 // finding the chain of operations that leads from the phi to the loop
672 // exit value.
673 SmallVector<Instruction *, 4> ReductionOperations =
674 RdxDesc.getReductionOpChain(Phi, const_cast<Loop *>(TheLoop));
675 bool InLoop = !ReductionOperations.empty();
676
677 if (InLoop) {
678 InLoopReductions.insert(Phi);
679 // Add the elements to InLoopReductionImmediateChains for cost modelling.
680 Instruction *LastChain = Phi;
681 for (auto *I : ReductionOperations) {
682 InLoopReductionImmediateChains[I] = LastChain;
683 LastChain = I;
684 }
685 }
686 LLVM_DEBUG(dbgs() << "LV: Using " << (InLoop ? "inloop" : "out of loop")
687 << " reduction for phi: " << *Phi << "\n");
688 }
689}
690
691bool LoopVectorizationPlanner::isMoreProfitable(const VectorizationFactor &A,
692 const VectorizationFactor &B,
693 const unsigned MaxTripCount,
694 bool HasTail,
695 bool IsEpilogue) const {
696 InstructionCost CostA = A.Cost;
697 InstructionCost CostB = B.Cost;
698
699 // When there is a hint to always prefer scalable vectors, honour that hint.
701 if (A.Width.isScalable() && CostA.isValid() && !B.Width.isScalable() &&
702 !B.Width.isScalar())
703 return true;
704
705 // Improve estimate for the vector width if it is scalable.
706 unsigned EstimatedWidthA = A.Width.getKnownMinValue();
707 unsigned EstimatedWidthB = B.Width.getKnownMinValue();
708 if (std::optional<unsigned> VScale = Config.getVScaleForTuning()) {
709 if (A.Width.isScalable())
710 EstimatedWidthA *= *VScale;
711 if (B.Width.isScalable())
712 EstimatedWidthB *= *VScale;
713 }
714
715 // When optimizing for size choose whichever is smallest, which will be the
716 // one with the smallest cost for the whole loop. On a tie pick the larger
717 // vector width, on the assumption that throughput will be greater.
718 if (Config.CostKind == TTI::TCK_CodeSize)
719 return CostA < CostB ||
720 (CostA == CostB && EstimatedWidthA > EstimatedWidthB);
721
722 // Assume vscale may be larger than 1 (or the value being tuned for),
723 // so that scalable vectorization is slightly favorable over fixed-width
724 // vectorization.
725 bool PreferScalable = !TTI.preferFixedOverScalableIfEqualCost(IsEpilogue) &&
726 A.Width.isScalable() && !B.Width.isScalable();
727
728 auto CmpFn = [PreferScalable](const InstructionCost &LHS,
729 const InstructionCost &RHS) {
730 return PreferScalable ? LHS <= RHS : LHS < RHS;
731 };
732
733 // To avoid the need for FP division:
734 // (CostA / EstimatedWidthA) < (CostB / EstimatedWidthB)
735 // <=> (CostA * EstimatedWidthB) < (CostB * EstimatedWidthA)
736 bool LowerCostWithoutTC =
737 CmpFn(CostA * EstimatedWidthB, CostB * EstimatedWidthA);
738 if (!MaxTripCount)
739 return LowerCostWithoutTC;
740
741 auto GetCostForTC = [MaxTripCount, HasTail](unsigned VF,
742 InstructionCost VectorCost,
743 InstructionCost ScalarCost) {
744 // If the trip count is a known (possibly small) constant, the trip count
745 // will be rounded up to an integer number of iterations under
746 // FoldTailByMasking. The total cost in that case will be
747 // VecCost*ceil(TripCount/VF). When not folding the tail, the total
748 // cost will be VecCost*floor(TC/VF) + ScalarCost*(TC%VF). There will be
749 // some extra overheads, but for the purpose of comparing the costs of
750 // different VFs we can use this to compare the total loop-body cost
751 // expected after vectorization.
752 if (HasTail)
753 return VectorCost * (MaxTripCount / VF) +
754 ScalarCost * (MaxTripCount % VF);
755 return VectorCost * divideCeil(MaxTripCount, VF);
756 };
757
758 auto RTCostA = GetCostForTC(EstimatedWidthA, CostA, A.ScalarCost);
759 auto RTCostB = GetCostForTC(EstimatedWidthB, CostB, B.ScalarCost);
760 bool LowerCostWithTC = CmpFn(RTCostA, RTCostB);
761 LLVM_DEBUG(if (LowerCostWithTC != LowerCostWithoutTC) {
762 dbgs() << "LV: VF " << (LowerCostWithTC ? A.Width : B.Width)
763 << " has lower cost than VF "
764 << (LowerCostWithTC ? B.Width : A.Width)
765 << " when taking the cost of the remaining scalar loop iterations "
766 "into consideration for a maximum trip count of "
767 << MaxTripCount << ".\n";
768 });
769 return LowerCostWithTC;
770}
771
772bool LoopVectorizationPlanner::isMoreProfitable(const VectorizationFactor &A,
773 const VectorizationFactor &B,
774 bool HasTail,
775 bool IsEpilogue) const {
776 const unsigned MaxTripCount = PSE.getSmallConstantMaxTripCount();
777 return LoopVectorizationPlanner::isMoreProfitable(A, B, MaxTripCount, HasTail,
778 IsEpilogue);
779}
780
781// TODO: we could return a pair of values that specify the max VF and
782// min VF, to be used in `buildVPlans(MinVF, MaxVF)` instead of
783// `buildVPlans(VF, VF)`. We cannot do it because VPLAN at the moment
784// doesn't have a cost model that can choose which plan to execute if
785// more than one is generated.
788 if (UserVF.isScalable() && !supportsScalableVectors()) {
790 "Scalable vectorization requested but not supported by the target",
791 "the scalable user-specified vectorization width for outer-loop "
792 "vectorization cannot be used because the target does not support "
793 "scalable vectors.",
794 "ScalableVFUnfeasible", ORE, TheLoop);
796 }
797
798 ElementCount VF = UserVF;
799 if (VF.isZero()) {
800 auto [_, WidestType] = getSmallestAndWidestTypes();
801
802 auto RegKind = TTI.enableScalableVectorization()
805
806 TypeSize RegSize = TTI.getRegisterBitWidth(RegKind);
807 // The widest type may be wider than the register width and WidestType may
808 // not be a power of two; round the element count down to a power of two.
809 unsigned N = std::max<uint64_t>(
810 1, llvm::bit_floor(RegSize.getKnownMinValue() / WidestType));
811 VF = ElementCount::get(N, RegSize.isScalable());
812 LLVM_DEBUG(dbgs() << "LV: VPlan computed VF " << VF << ".\n");
813
814 // Make sure we have a VF > 1 for stress testing.
816 LLVM_DEBUG(dbgs() << "LV: VPlan stress testing: "
817 << "overriding computed VF.\n");
819 }
820 }
822 "VF needs to be a power of two");
823 if (VF.isScalar())
825 LLVM_DEBUG(dbgs() << "LV: Using " << (!UserVF.isZero() ? "user " : "")
826 << "VF " << VF << " to build VPlans.\n");
827 return FixedScalableVFPair(VF);
828}
unsigned RegSize
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")
#define DEBUG_TYPE
#define _
loop Loop Strength Reduction
This file defines the LoopVectorizationLegality class.
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
constexpr bool isVector() const
One or more elements.
Definition TypeSize.h:324
static constexpr ElementCount getScalable(ScalarTy MinVal)
Definition TypeSize.h:312
static constexpr ElementCount getFixed(ScalarTy MinVal)
Definition TypeSize.h:309
static constexpr ElementCount get(ScalarTy MinVal, bool Scalable)
Definition TypeSize.h:315
constexpr bool isScalar() const
Exactly one element.
Definition TypeSize.h:320
bool isInnermost() const
Return true if the loop does not contain any (natural) loops.
BlockT * getHeader() const
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:669
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
This pass provides access to the codegen interfaces that are needed for IR-level transformations.
@ 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
const TTI::TargetCostKind CostKind
The kind of cost that we are calculating.
bool runtimeChecksRequired()
Check whether vectorization would require runtime checks.
bool isLegalGatherOrScatter(Value *V, ElementCount VF) const
Returns true if the target machine can represent V as a masked gather or scatter operation.
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)
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.
LLVM Value Representation.
Definition Value.h:75
static LLVM_ABI VectorType * get(Type *ElementType, ElementCount EC)
This static method is the primary way to construct an VectorType.
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
Align getLoadStoreAlignment(const Value *I)
A helper function that returns the alignment of load or store instruction.
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
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
std::optional< unsigned > getMaxVScale(const Function &F, const TargetTransformInfo &TTI)
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:395
TargetTransformInfo TTI
RecurKind
These are the kinds of recurrences that we support.
Type * getLoadStoreType(const Value *I)
A helper function that returns the type of a load or store instruction.
T bit_floor(T Value)
Returns the largest integral power of two no greater than Value if Value is nonzero.
Definition bit.h:347
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
#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.