LLVM 24.0.0git
SLPVectorizer.cpp
Go to the documentation of this file.
1//===- SLPVectorizer.cpp - A bottom up SLP Vectorizer ---------------------===//
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// This pass implements the Bottom Up SLP vectorizer. It detects consecutive
10// stores that can be put together into vector-stores. Next, it attempts to
11// construct vectorizable tree using the use-def chains. If a profitable tree
12// was found, the SLP vectorizer performs vectorization on the tree.
13//
14// The pass is inspired by the work described in the paper:
15// "Loop-Aware SLP in GCC" by Ira Rosen, Dorit Nuzman, Ayal Zaks.
16//
17//===----------------------------------------------------------------------===//
18
23#include "llvm/ADT/DenseMap.h"
24#include "llvm/ADT/DenseSet.h"
26#include "llvm/ADT/STLExtras.h"
27#include "llvm/ADT/ScopeExit.h"
29#include "llvm/ADT/SetVector.h"
32#include "llvm/ADT/SmallSet.h"
35#include "llvm/ADT/Statistic.h"
36#include "llvm/ADT/iterator.h"
46#include "llvm/Analysis/Loads.h"
56#include "llvm/IR/Attributes.h"
57#include "llvm/IR/BasicBlock.h"
58#include "llvm/IR/CFG.h"
59#include "llvm/IR/Constant.h"
60#include "llvm/IR/Constants.h"
61#include "llvm/IR/DataLayout.h"
63#include "llvm/IR/Dominators.h"
64#include "llvm/IR/Function.h"
65#include "llvm/IR/IRBuilder.h"
66#include "llvm/IR/InstrTypes.h"
67#include "llvm/IR/Instruction.h"
70#include "llvm/IR/Intrinsics.h"
71#include "llvm/IR/Module.h"
72#include "llvm/IR/Operator.h"
75#include "llvm/IR/Type.h"
76#include "llvm/IR/Use.h"
77#include "llvm/IR/User.h"
78#include "llvm/IR/Value.h"
79#include "llvm/IR/ValueHandle.h"
81#ifdef EXPENSIVE_CHECKS
82#include "llvm/IR/Verifier.h"
83#endif
84#include "llvm/Pass.h"
89#include "llvm/Support/Debug.h"
101#include <algorithm>
102#include <cassert>
103#include <cstdint>
104#include <iterator>
105#include <map>
106#include <memory>
107#include <optional>
108#include <set>
109#include <string>
110#include <tuple>
111#include <utility>
112
113using namespace llvm;
114using namespace llvm::PatternMatch;
115using namespace slpvectorizer;
116using namespace std::placeholders;
117
118#define SV_NAME "slp-vectorizer"
119#define DEBUG_TYPE "SLP"
120
121STATISTIC(NumVectorInstructions, "Number of vector instructions generated");
122STATISTIC(NumStridedStoreChains, "Number of vectorized stride stores");
123STATISTIC(NumStoreChains, "Number of vector stores created");
124STATISTIC(NumVectorizedStores, "Number of vectorized stores");
125
126DEBUG_COUNTER(VectorizedGraphs, "slp-vectorized",
127 "Controls which SLP graphs should be vectorized.");
128
129static cl::opt<bool>
130 RunSLPVectorization("vectorize-slp", cl::init(true), cl::Hidden,
131 cl::desc("Run the SLP vectorization passes"));
132
133static cl::opt<bool>
134 SLPReVec("slp-revec", cl::init(false), cl::Hidden,
135 cl::desc("Enable vectorization for wider vector utilization"));
136
137static cl::opt<int>
139 cl::desc("Only vectorize if you gain more than this "
140 "number "));
141
142static cl::opt<bool>
143ShouldVectorizeHor("slp-vectorize-hor", cl::init(true), cl::Hidden,
144 cl::desc("Attempt to vectorize horizontal reductions"));
145
147 "slp-vectorize-hor-store", cl::init(false), cl::Hidden,
148 cl::desc(
149 "Attempt to vectorize horizontal reductions feeding into a store"));
150
152 "slp-split-alternate-instructions", cl::init(true), cl::Hidden,
153 cl::desc("Improve the code quality by splitting alternate instructions"));
154
156 "slp-inst-count-check", cl::init(true), cl::Hidden,
157 cl::desc("Reject vectorization if vector instruction count exceeds "
158 "scalar instruction count"));
159
160static cl::opt<int>
162 cl::desc("Attempt to vectorize for this register size in bits"));
163
166 cl::desc("Maximum SLP vectorization factor (0=unlimited)"));
167
168/// Limits the size of scheduling regions in a block.
169/// It avoid long compile times for _very_ large blocks where vector
170/// instructions are spread over a wide range.
171/// This limit is way higher than needed by real-world functions.
172static cl::opt<int>
173ScheduleRegionSizeBudget("slp-schedule-budget", cl::init(100000), cl::Hidden,
174 cl::desc("Limit the size of the SLP scheduling region per block"));
175
177 "slp-min-reg-size", cl::init(128), cl::Hidden,
178 cl::desc("Attempt to vectorize for this register size in bits"));
179
181 "slp-recursion-max-depth", cl::init(12), cl::Hidden,
182 cl::desc("Limit the recursion depth when building a vectorizable tree"));
183
185 "slp-min-tree-size", cl::init(3), cl::Hidden,
186 cl::desc("Only vectorize small trees if they are fully vectorizable"));
187
189 "slp-phi-vectorization-budget", cl::init(1024), cl::Hidden,
190 cl::desc("Do not vectorize a bundle of PHI nodes if the product of the "
191 "bundle size and the number of incoming values exceeds this "
192 "value, to limit the compile time spent on wide PHIs"));
193
194// The maximum depth that the look-ahead score heuristic will explore.
195// The higher this value, the higher the compilation time overhead.
197 "slp-max-look-ahead-depth", cl::init(2), cl::Hidden,
198 cl::desc("The maximum look-ahead depth for operand reordering scores"));
199
200// The maximum depth that the look-ahead score heuristic will explore
201// when it probing among candidates for vectorization tree roots.
202// The higher this value, the higher the compilation time overhead but unlike
203// similar limit for operands ordering this is less frequently used, hence
204// impact of higher value is less noticeable.
206 "slp-max-root-look-ahead-depth", cl::init(2), cl::Hidden,
207 cl::desc("The maximum look-ahead depth for searching best rooting option"));
208
210 "slp-min-strided-loads", cl::init(2), cl::Hidden,
211 cl::desc("The minimum number of loads, which should be considered strided, "
212 "if the stride is > 1 or is runtime value"));
213
215 "slp-min-strided-stores", cl::init(2), cl::Hidden,
216 cl::desc(
217 "The minimum number of stores, which should be considered strided, "
218 "if the stride is > 1 or is runtime value"));
219
221 "slp-max-stride", cl::init(8), cl::Hidden,
222 cl::desc("The maximum stride, considered to be profitable."));
223
224static cl::opt<bool>
225 EnableStridedStores("slp-enable-strided-stores", cl::init(false),
227 cl::desc("Enable SLP trees to be built from strided "
228 "store chains."));
229
231 "slp-enable-masked-stores", cl::init(true), cl::Hidden,
232 cl::desc("Enable vectorization of non-consecutive stores as a single "
233 "masked store, when the target supports masked stores."));
234
235static cl::opt<bool>
236 DisableTreeReorder("slp-disable-tree-reorder", cl::init(false), cl::Hidden,
237 cl::desc("Disable tree reordering even if it is "
238 "profitable. Used for testing only."));
239
240static cl::opt<bool>
241 ForceStridedLoads("slp-force-strided-loads", cl::init(false), cl::Hidden,
242 cl::desc("Generate strided loads even if they are not "
243 "profitable. Used for testing only."));
244
245static cl::opt<bool>
246 ViewSLPTree("view-slp-tree", cl::Hidden,
247 cl::desc("Display the SLP trees with Graphviz"));
248
250 "slp-vectorize-non-power-of-2", cl::init(false), cl::Hidden,
251 cl::desc("Try to vectorize with non-power-of-2 number of elements."));
252
254 "slp-postprocess-stores-operands", cl::init(false), cl::Hidden,
255 cl::desc("Force vectorization of non-vectorizable stores operands."));
256
258 "slp-non-vectorizables-as-reductions", cl::init(false), cl::Hidden,
259 cl::desc(
260 "Use non-vectorizable instructions as potential reduction roots."));
261
263 "slp-vectorize-poor-throughput", cl::init(true), cl::Hidden,
264 cl::desc("Use poor-throughput instructions (e.g. fdiv, frem, fsqrt) as "
265 "standalone vectorization seeds."));
266
268 "slp-vectorize-once-used", cl::init(true), cl::Hidden,
269 cl::desc("Use instructions with the single user as standalone "
270 "vectorization seeds."));
271
272/// True when \p slp-vectorize-non-power-of-2 is enabled and \p NumElts is a
273/// supported non-power-of-2 width: \p NumElts + 1 must be a power of two
274/// (e.g. 3 or 7 lanes, i.e. almost a full power-of-2 register).
275static bool isAllowedNonPowerOf2VF(unsigned NumElts) {
276 return VectorizeNonPowerOf2 && has_single_bit(NumElts + 1);
277}
278
279/// Enables vectorization of copyable elements.
281 "slp-copyable-elements", cl::init(true), cl::Hidden,
282 cl::desc("Try to replace values with the idempotent instructions for "
283 "better vectorization."));
284
285/// Gather operands of associative single-use binary chains into one node.
287 "slp-reassociate-ops", cl::init(true), cl::Hidden,
288 cl::desc("Gather operands of associative binary chains into one node."));
289
290/// The family-realigned seed already groups the vectorizable columns; the
291/// VLOperands polish on top is quadratic in the column count, so past this
292/// many columns keep the seed instead.
294 "slp-reassociate-reorder-limit", cl::init(32), cl::Hidden,
295 cl::desc("Max flattened operand columns for which associative-chain "
296 "reordering runs the full operand reorder."));
297
299 "slp-cost-loop-trip-count", cl::init(2), cl::Hidden,
300 cl::desc("Loop trip count, considered by the cost model during "
301 "modeling (0=loops are ignored and considered flat code)"));
302
303/// Refine the loop-aware cost scaling of gather/buildvector tree entries by
304/// using the per-lane execution scale of the operand that feeds each lane,
305/// instead of a single whole-entry scale. This matches the LICM hoisting
306/// performed by optimizeGatherSequence() at codegen time: lanes whose
307/// operands are loop-invariant in an inner loop contribute the outer loop's
308/// execution scale rather than the inner loop's, which avoids over-costing
309/// buildvectors that bridge values from outer loop nests into an inner loop.
311 "slp-per-lane-gather-scale", cl::init(true), cl::Hidden,
312 cl::desc("Use per-lane execution scale for gather/buildvector tree "
313 "entries to model LICM-hoistable buildvector sequences."));
314
315/// Enable versioning of a basic block with runtime alias checks.
317 "slp-vectorize-with-runtime-alias-checks", cl::init(true), cl::Hidden,
318 cl::desc("Allow SLP to version a block with runtime alias checks to "
319 "vectorize trees blocked by may-alias memory dependencies."));
320
321/// Maximum number of runtime alias checks (one per pair of base objects) that
322/// may guard a single versioned region.
324 "slp-max-runtime-alias-checks", cl::init(8), cl::Hidden,
325 cl::desc("The maximum number of runtime alias checks generated to guard a "
326 "single SLP-vectorized region."));
327
328/// The runtime checks and the guard branch execute on both the vector and the
329/// scalar fallback path, so they add overhead to the scalar code.
331 "slp-runtime-alias-checks-max-scalar-cost-percent", cl::init(25),
333 cl::desc("Maximum SLP runtime alias check cost, as a percentage of the "
334 "guarded scalar region cost, before versioning is rejected to "
335 "avoid pessimizing the scalar fallback path."));
336
337// Limit the number of alias checks. The limit is chosen so that
338// it has no negative effect on the llvm benchmarks.
339static const unsigned AliasedCheckLimit = 10;
340
341// Another limit for the alias checks: The maximum distance between load/store
342// instructions where alias checks are done.
343// This limit is useful for very large basic blocks.
344static const unsigned MaxMemDepDistance = 160;
345
346/// If the ScheduleRegionSizeBudget is exhausted, we allow small scheduling
347/// regions to be handled.
348static const int MinScheduleRegionSize = 16;
349
350/// Maximum allowed number of operands in the PHI nodes.
351static const unsigned MaxPHINumOperands = 128;
352
353/// Predicate for the element types that the SLP vectorizer supports.
354///
355/// The most important thing to filter here are types which are invalid in LLVM
356/// vectors. We also filter target specific types which have absolutely no
357/// meaningful vectorization path such as x86_fp80 and ppc_f128. This just
358/// avoids spending time checking the cost model and realizing that they will
359/// be inevitably scalarized.
360static bool isValidElementType(Type *Ty) {
361 // TODO: Support ScalableVectorType.
362 if (SLPReVec && isVectorizedTy(Ty) && !getVectorizedTypeVF(Ty).isScalable())
363 Ty = toScalarizedTy(Ty);
364 return canVectorizeTy(Ty) && !Ty->isX86_FP80Ty() && !Ty->isPPC_FP128Ty() &&
365 !Ty->isVoidTy();
366}
367
368/// Returns the "element type" of the given value/instruction \p V.
369/// For stores, returns the stored value type; for insertelement (when ReVec is
370/// off), the inserted operand type. For compares, the default is to return the
371/// result type (i1); when \p LookThroughCmp is true, returns the type of the
372/// compared operands instead, which is needed for vector width calculations
373/// (the width is determined by the operand type, not the i1 result).
374static Type *getValueType(Value *V, bool LookThroughCmp = false) {
375 if (auto *SI = dyn_cast<StoreInst>(V))
376 return SI->getValueOperand()->getType();
377 if (LookThroughCmp)
378 if (auto *CI = dyn_cast<CmpInst>(V))
379 return CI->getOperand(0)->getType();
380 if (!SLPReVec)
381 if (auto *IE = dyn_cast<InsertElementInst>(V))
382 return IE->getOperand(1)->getType();
383 if (auto *IV = dyn_cast<InsertValueInst>(V))
384 return IV->getOperand(1)->getType();
385 return V->getType();
386}
387
388/// \returns the vector type of ScalarTy based on vectorization factor.
389static Type *getWidenedType(Type *ScalarTy, unsigned VF) {
390 if (VF == 1 && !isVectorizedTy(ScalarTy)) {
391 // Workaround for 1 x vector types: toVectorizedTy returns the type
392 // unchanged when EC is scalar, but BoUpSLP relies on widening to
393 // <1 x ScalarTy> (or struct of <1 x ElTy>) to keep the rest of the
394 // pipeline operating on vector types.
395 if (auto *StructTy = dyn_cast<StructType>(ScalarTy)) {
397 "expected unpacked struct literal");
398 assert(all_of(StructTy->elements(), VectorType::isValidElementType) &&
399 "expected all element types to be valid vector element types");
400 return StructType::get(
401 StructTy->getContext(),
402 map_to_vector(StructTy->elements(), [&](Type *ElTy) -> Type * {
403 return FixedVectorType::get(ElTy, 1);
404 }));
405 }
406 return FixedVectorType::get(ScalarTy, 1);
407 }
408 return toVectorizedTy(toScalarizedTy(ScalarTy),
409 ElementCount::getFixed(VF * getNumElements(ScalarTy)));
410}
411
412/// Returns the number of elements of the given type \p Ty, not less than \p Sz,
413/// which forms type, which splits by \p TTI into whole vector types during
414/// legalization.
416 Type *Ty, unsigned Sz) {
417 if (!isValidElementType(Ty) || isa<StructType>(Ty))
418 return bit_ceil(Sz);
419 // Find the number of elements, which forms full vectors.
420 const unsigned NumParts = TTI.getNumberOfParts(getWidenedType(Ty, Sz));
421 if (NumParts == 0 || NumParts >= Sz)
422 return bit_ceil(Sz);
423 return bit_ceil(divideCeil(Sz, NumParts)) * NumParts;
424}
425
426/// Returns the number of elements of the given type \p Ty, not greater than \p
427/// Sz, which forms type, which splits by \p TTI into whole vector types during
428/// legalization.
429static unsigned
431 unsigned Sz) {
432 if (!isValidElementType(Ty) || isa<StructType>(Ty))
433 return bit_floor(Sz);
434 // Find the number of elements, which forms full vectors.
435 unsigned NumParts = TTI.getNumberOfParts(getWidenedType(Ty, Sz));
436 if (NumParts == 0 || NumParts >= Sz)
437 return bit_floor(Sz);
438 unsigned RegVF = bit_ceil(divideCeil(Sz, NumParts));
439 if (RegVF > Sz)
440 return bit_floor(Sz);
441 return (Sz / RegVF) * RegVF;
442}
443
444/// For a non-power-of-2 \p NumElts-wide integer div/rem \p Opcode, returns the
445/// padded full-register vector type if padding is structurally possible, or
446/// nullptr if the vector already fills a register or the opcode is not
447/// div/rem. Does not check profitability; see getMaskedDivRemCost for that.
449 unsigned Opcode, Type *ScalarTy,
450 unsigned NumElts) {
451 if (!Instruction::isIntDivRem(Opcode) || has_single_bit(NumElts))
452 return nullptr;
453 unsigned PaddedNumElts =
454 getFullVectorNumberOfElements(TTI, ScalarTy, NumElts);
455 if (PaddedNumElts == NumElts)
456 return nullptr;
457 return cast<FixedVectorType>(getWidenedType(ScalarTy, PaddedNumElts));
458}
459
460/// For a non-power-of-2 \p NumElts-wide integer div/rem \p Opcode, checks if
461/// padding to a full register and using the masked div/rem intrinsic is
462/// cheaper than the direct vector op. Returns the cost of the masked
463/// alternative, or an invalid cost if it is not applicable or not cheaper.
464static InstructionCost
466 Type *ScalarTy, unsigned NumElts,
468 FixedVectorType **PaddedTy = nullptr) {
469 FixedVectorType *PaddedVecTy =
470 getMaskedDivRemType(TTI, Opcode, ScalarTy, NumElts);
471 if (!PaddedVecTy)
473 // One mask bit per element of the padded vector, not per padded lane.
474 auto *MaskTy =
476 PaddedVecTy->getNumElements());
477 InstructionCost DirectCost = TTI.getArithmeticInstrCost(
478 Opcode, getWidenedType(ScalarTy, NumElts), CostKind);
479 IntrinsicCostAttributes ICA(getMaskedDivRemIntrinsic(Opcode), PaddedVecTy,
480 {PaddedVecTy, PaddedVecTy, MaskTy});
481 InstructionCost MaskedCost = TTI.getIntrinsicInstrCost(ICA, CostKind);
482 if (!MaskedCost.isValid() || MaskedCost >= DirectCost)
484 if (PaddedTy)
485 *PaddedTy = PaddedVecTy;
486 return MaskedCost;
487}
488
489/// Checks if the vector of instructions can be represented as a shuffle, like:
490/// %x0 = extractelement <4 x i8> %x, i32 0
491/// %x3 = extractelement <4 x i8> %x, i32 3
492/// %y1 = extractelement <4 x i8> %y, i32 1
493/// %y2 = extractelement <4 x i8> %y, i32 2
494/// %x0x0 = mul i8 %x0, %x0
495/// %x3x3 = mul i8 %x3, %x3
496/// %y1y1 = mul i8 %y1, %y1
497/// %y2y2 = mul i8 %y2, %y2
498/// %ins1 = insertelement <4 x i8> poison, i8 %x0x0, i32 0
499/// %ins2 = insertelement <4 x i8> %ins1, i8 %x3x3, i32 1
500/// %ins3 = insertelement <4 x i8> %ins2, i8 %y1y1, i32 2
501/// %ins4 = insertelement <4 x i8> %ins3, i8 %y2y2, i32 3
502/// ret <4 x i8> %ins4
503/// can be transformed into:
504/// %1 = shufflevector <4 x i8> %x, <4 x i8> %y, <4 x i32> <i32 0, i32 3, i32 5,
505/// i32 6>
506/// %2 = mul <4 x i8> %1, %1
507/// ret <4 x i8> %2
508/// Mask will return the Shuffle Mask equivalent to the extracted elements.
509/// TODO: Can we split off and reuse the shuffle mask detection from
510/// ShuffleVectorInst/getShuffleCost?
511static std::optional<TargetTransformInfo::ShuffleKind>
513 AssumptionCache *AC) {
514 const auto *It = find_if(VL, IsaPred<ExtractElementInst>);
515 if (It == VL.end())
516 return std::nullopt;
517 unsigned Size = accumulate(VL, 0u, [](unsigned S, Value *V) {
518 auto *EI = dyn_cast<ExtractElementInst>(V);
519 if (!EI)
520 return S;
521 auto *VTy = dyn_cast<FixedVectorType>(EI->getVectorOperandType());
522 if (!VTy)
523 return S;
524 return std::max(S, VTy->getNumElements());
525 });
526
527 Value *Vec1 = nullptr;
528 Value *Vec2 = nullptr;
529 bool HasNonUndefVec = any_of(VL, [&](Value *V) {
530 auto *EE = dyn_cast<ExtractElementInst>(V);
531 if (!EE)
532 return false;
533 Value *Vec = EE->getVectorOperand();
534 if (isa<UndefValue>(Vec))
535 return false;
536 return isGuaranteedNotToBePoison(Vec, AC);
537 });
538 enum ShuffleMode { Unknown, Select, Permute };
539 ShuffleMode CommonShuffleMode = Unknown;
540 Mask.assign(VL.size(), PoisonMaskElem);
541 for (unsigned I = 0, E = VL.size(); I < E; ++I) {
542 // Undef, or a copyable lane modeled on an extract main op, can be
543 // represented as an undef element in a vector.
544 if (isa<UndefValue>(VL[I]))
545 continue;
546 auto *EI = dyn_cast<ExtractElementInst>(VL[I]);
547 if (!EI)
548 continue;
549 if (isa<ScalableVectorType>(EI->getVectorOperandType()))
550 return std::nullopt;
551 auto *Vec = EI->getVectorOperand();
552 // We can extractelement from undef or poison vector.
554 continue;
555 // All vector operands must have the same number of vector elements.
556 if (isa<UndefValue>(Vec)) {
557 Mask[I] = I;
558 } else {
559 if (isa<UndefValue>(EI->getIndexOperand()))
560 continue;
561 auto *Idx = dyn_cast<ConstantInt>(EI->getIndexOperand());
562 if (!Idx)
563 return std::nullopt;
564 // Undefined behavior if Idx is negative or >= Size.
565 if (Idx->getValue().uge(Size))
566 continue;
567 unsigned IntIdx = Idx->getValue().getZExtValue();
568 Mask[I] = IntIdx;
569 }
570 if (isUndefVector(Vec).all() && HasNonUndefVec)
571 continue;
572 // For correct shuffling we have to have at most 2 different vector operands
573 // in all extractelement instructions.
574 if (!Vec1 || Vec1 == Vec) {
575 Vec1 = Vec;
576 } else if (!Vec2 || Vec2 == Vec) {
577 Vec2 = Vec;
578 Mask[I] += Size;
579 } else {
580 return std::nullopt;
581 }
582 if (CommonShuffleMode == Permute)
583 continue;
584 // If the extract index is not the same as the operation number, it is a
585 // permutation.
586 if (Mask[I] % Size != I) {
587 CommonShuffleMode = Permute;
588 continue;
589 }
590 CommonShuffleMode = Select;
591 }
592 // If we're not crossing lanes in different vectors, consider it as blending.
593 if (CommonShuffleMode == Select && Vec2)
595 // If Vec2 was never used, we have a permutation of a single vector, otherwise
596 // we have permutation of 2 vectors.
599}
600
601/// Returns true if widened type of \p Ty elements with size \p Sz represents
602/// full vector type, i.e. adding extra element results in extra parts upon type
603/// legalization.
605 unsigned Sz) {
606 if (Sz <= 1)
607 return false;
609 return false;
610 if (has_single_bit(Sz))
611 return true;
612 if (isa<StructType>(Ty))
613 return false;
614 const unsigned NumParts = TTI.getNumberOfParts(getWidenedType(Ty, Sz));
615 return NumParts > 0 && NumParts < Sz && has_single_bit(Sz / NumParts) &&
616 Sz % NumParts == 0;
617}
618
619/// Returns number of parts, the type \p VecTy will be split at the codegen
620/// phase. If the type is going to be scalarized or does not uses whole
621/// registers, returns 1.
622static unsigned
624 const unsigned Limit = std::numeric_limits<unsigned>::max()) {
625 if (isa<StructType>(VecTy))
626 return 1;
627 unsigned NumParts = TTI.getNumberOfParts(VecTy);
628 if (NumParts == 0 || NumParts >= Limit)
629 return 1;
630 unsigned Sz = getNumElements(VecTy);
631 unsigned ScalarSz = getNumElements(ScalarTy);
632 Type *ElementTy = toScalarizedTy(VecTy);
633 unsigned PWSz = getFullVectorNumberOfElements(TTI, ElementTy, Sz);
634 if (NumParts >= Sz || PWSz % NumParts != 0 ||
635 (PWSz / NumParts) % ScalarSz != 0 ||
636 !hasFullVectorsOrPowerOf2(TTI, ElementTy, PWSz / NumParts))
637 return 1;
638 const unsigned NumElts = PWSz / NumParts;
639 if (divideCeil(Sz, NumElts) != NumParts)
640 return 1;
641 return NumParts;
642}
643
644/// Bottom Up SLP Vectorizer.
646 class TreeEntry;
647 class ScheduleEntity;
648 class ScheduleData;
649 class ScheduleCopyableData;
650 class ScheduleBundle;
653
654public:
655 /// If we decide to generate strided load / store, this struct contains all
656 /// the necessary info. It's fields are calculated by analyzeRtStrideCandidate
657 /// and analyzeConstantStrideCandidate. Note that Stride can be given either
658 /// as a SCEV or as a Value if it already exists. To get the stride in bytes,
659 /// StrideVal (or value obtained from StrideSCEV) has to by multiplied by the
660 /// size of element of FixedVectorType.
662 Value *StrideVal = nullptr;
663 const SCEV *StrideSCEV = nullptr;
664 FixedVectorType *Ty = nullptr;
665 };
666
667 /// Tracks the state we can represent the loads in the given sequence.
676
683
685 TargetLibraryInfo *TLi, AAResults *Aa, LoopInfo *Li,
688 : BatchAA(*Aa), F(Func), SE(Se), TTI(Tti), TLI(TLi), LI(Li), DT(Dt),
689 AC(AC), DB(DB), DL(DL), ORE(ORE), CostKind(getSLPCostKind(Func)),
690 Builder(Se->getContext(), TargetFolder(*DL)) {
691 CodeMetrics::collectEphemeralValues(F, AC, EphValues);
692 // Use the vector register size specified by the target unless overridden
693 // by a command-line option.
694 // TODO: It would be better to limit the vectorization factor based on
695 // data type rather than just register size. For example, x86 AVX has
696 // 256-bit registers, but it does not support integer operations
697 // at that width (that requires AVX2).
698 if (MaxVectorRegSizeOption.getNumOccurrences())
699 MaxVecRegSize = MaxVectorRegSizeOption;
700 else
701 MaxVecRegSize =
702 TTI->getRegisterBitWidth(TargetTransformInfo::RGK_FixedWidthVector)
703 .getFixedValue();
704
705 if (MinVectorRegSizeOption.getNumOccurrences())
706 MinVecRegSize = MinVectorRegSizeOption;
707 else
708 MinVecRegSize = TTI->getMinVectorRegisterBitWidth();
709 }
710
711 /// Vectorize the tree that starts with the elements in \p VL.
712 /// Returns the vectorized root.
714
715 /// Vectorize the tree but with the list of externally used values \p
716 /// ExternallyUsedValues. Values in this MapVector can be replaced but the
717 /// generated extractvalue instructions.
718 Value *
719 vectorizeTree(const ExtraValueToDebugLocsMap &ExternallyUsedValues,
720 Instruction *ReductionRoot = nullptr,
721 ArrayRef<std::tuple<WeakTrackingVH, unsigned, bool, bool>>
722 VectorValuesAndScales = {});
723
724 /// \returns the cost incurred by unwanted spills and fills, caused by
725 /// holding live values over call sites.
727
729
730 /// Calculates the cost of the subtrees, trims non-profitable ones and returns
731 /// final cost.
734 Instruction *RdxRoot = nullptr);
735
736 /// \returns the vectorization cost of the subtree that starts at \p VL.
737 /// A negative number means that this is profitable.
739 ArrayRef<Value *> VectorizedVals = {},
740 InstructionCost ReductionCost = TTI::TCC_Free,
741 Instruction *RdxRoot = nullptr);
742
743 /// Construct a vectorizable tree that starts at \p Roots, ignoring users for
744 /// the purpose of scheduling and extraction in the \p UserIgnoreLst.
745 void buildTree(ArrayRef<Value *> Roots,
746 const SmallDenseSet<Value *> &UserIgnoreLst);
747
748 /// Construct a vectorizable tree that starts at \p Roots.
749 void buildTree(ArrayRef<Value *> Roots);
750
751 /// Sets the narrowed reduction chain instructions, dropped together with
752 /// the reduction.
754 NarrowedChainInsts.insert(Insts.begin(), Insts.end());
755 }
756
757 /// Returns true if the last buildTree() observed a may-alias memory
758 /// dependency between two distinct, range-checkable base objects, i.e. a
759 /// dependency that could be turned into a runtime alias check.
761 return HasRuntimeCheckableBlockers;
762 }
763
764 /// Records whether a may-alias dependency between distinct, range-checkable
765 /// base objects has been observed, so the caller can decide to retry with
766 /// runtime alias checks enabled.
768 HasRuntimeCheckableBlockers = V;
769 }
770
771 /// Returns true if the last buildTree() kept a may-alias memory dependency
772 /// that is not runtime-checkable (call or a non-simple mem access). Such a
773 /// dependency cannot be dropped, so a runtime-checks retry cannot unblock the
774 /// region and would be pure overhead.
775 bool hasNonCheckableMemBlocker() const { return HasNonCheckableMemBlocker; }
776
777 /// Records that a non-runtime-checkable may-alias dependency was kept.
778 void setHasNonCheckableMemBlocker(bool V) { HasNonCheckableMemBlocker = V; }
779
780 /// Returns true if the current vectorization attempt may drop
781 /// runtime-checkable may-alias dependencies and guard the region with
782 /// runtime alias checks.
783 bool isTryingRuntimeAliasChecks() const { return TryRuntimeAliasChecks; }
784
785 /// Enables or disables dropping runtime-checkable may-alias dependencies in
786 /// favor of runtime alias checks for the current vectorization attempt.
787 void setTryRuntimeAliasChecks(bool V) { TryRuntimeAliasChecks = V; }
788
789 /// Resets the runtime alias check data.
791 HasRuntimeCheckableBlockers = false;
792 HasNonCheckableMemBlocker = false;
793 RTChecksFinalized = false;
794 RTChecks.clear();
795 RTOrigBodyOrder.clear();
796 }
797
798 /// Snapshots RTChecks.BB's body (non-PHI, non-terminator) into
799 /// RTOrigBodyOrder in program order, for the scalar fallback.
801
802 /// Returns true if \p BB satisfies the block-level preconditions for runtime
803 /// alias check versioning (straight-line, outside any loop, duplicable, not a
804 /// scalar fallback, function not optimized for size). These checks do not
805 /// depend on the collected checks, so they can gate the (expensive)
806 /// optimistic retry before any tree is rebuilt.
808
809 /// Returns true if the runtime alias checks can be safely emitted to guard
810 /// the vectorized region.
812
813 /// Returns true if \p BB is a scalar fallback block created by runtime alias
814 /// check versioning.
816 return ScalarFallbackBlocks.contains(BB);
817 }
818
819 /// Returns true if an optimistic runtime-checks versioning attempt already
820 /// failed for \p BB, so further retries in the same block can be skipped.
822 return FailedRuntimeChecksBlocks.contains(BB);
823 }
824
825 /// Records that an optimistic runtime-checks versioning attempt failed for
826 /// \p BB.
828 FailedRuntimeChecksBlocks.insert(BB);
829 }
830
831 /// Returns the modeled cost of the runtime alias checks collected during the
832 /// last (optimistic) buildTree().
834
835 /// Returns true if the last (optimistic) buildTree() collected any runtime
836 /// alias checks that must guard the vectorized region.
837 bool hasRuntimeAliasChecks() const { return !RTChecks.BasePairs.empty(); }
838
839 /// Returns true if vectorization changed the CFG (i.e. a block was versioned
840 /// with runtime alias checks). When true, CFG analyses must not be preserved.
841 bool isCFGChanged() const { return CFGChanged; }
842
843 TreeEntry &getRootNode() {
844 assert(!VectorizableTree.empty() && "No graph to get the first node from");
845 return *VectorizableTree.front();
846 }
847
848 const TreeEntry &getRootNode() const {
849 assert(!VectorizableTree.empty() && "No graph to get the first node from");
850 return *VectorizableTree.front();
851 }
852
853 /// Returns the scalars of the root node.
855
856 /// Returns the lane the given value is vectorized to in the root node.
857 unsigned findRootLaneForValue(Value *V) const {
858 return getRootNode().findLaneForValue(V);
859 }
860
861 /// Returns the type/is-signed info for the root node in the graph without
862 /// casting.
863 std::optional<std::pair<Type *, bool>> getRootNodeTypeWithNoCast() const {
864 const TreeEntry &Root = getRootNode();
865 if (Root.State != TreeEntry::Vectorize || Root.isAltShuffle() ||
866 !Root.Scalars.front()->getType()->isIntegerTy())
867 return std::nullopt;
868 auto It = MinBWs.find(&Root);
869 if (It != MinBWs.end())
870 return std::make_pair(IntegerType::get(Root.Scalars.front()->getContext(),
871 It->second.first),
872 It->second.second);
873 if (Root.getOpcode() == Instruction::ZExt ||
874 Root.getOpcode() == Instruction::SExt)
875 return std::make_pair(cast<CastInst>(Root.getMainOp())->getSrcTy(),
876 Root.getOpcode() == Instruction::SExt);
877 return std::nullopt;
878 }
879
880 /// Checks if the root graph node can be emitted with narrower bitwidth at
881 /// codegen and returns it signedness, if so.
883 return MinBWs.at(&getRootNode()).second;
884 }
885
886 /// Returns reduction type after minbitdth analysis.
888 if (ReductionBitWidth == 0 ||
889 !getRootNodeScalars().front()->getType()->isIntegerTy() ||
890 ReductionBitWidth >=
891 DL->getTypeSizeInBits(getRootNodeScalars().front()->getType()))
894 getRootNode().getVectorFactor()));
897 ReductionBitWidth),
898 getRootNode().getVectorFactor()));
899 }
900
901 /// Returns true if the tree results in one of the reduced bitcasts variants.
902 bool isReducedBitcastRoot() const {
903 return getRootNode().hasState() &&
904 (getRootNode().CombinedOp == TreeEntry::ReducedBitcast ||
905 getRootNode().CombinedOp == TreeEntry::ReducedBitcastBSwap ||
906 getRootNode().CombinedOp == TreeEntry::ReducedBitcastLoads ||
907 getRootNode().CombinedOp == TreeEntry::ReducedBitcastBSwapLoads) &&
908 getRootNode().State == TreeEntry::Vectorize;
909 }
910
911 /// Returns true if the tree results in the reduced cmp bitcast root.
913 return getRootNode().hasState() &&
914 getRootNode().CombinedOp == TreeEntry::ReducedCmpBitcast &&
915 getRootNode().State == TreeEntry::Vectorize;
916 }
917
918 /// Returns true if the tree is a reduction tree.
919 bool isReductionTree() const { return UserIgnoreList != nullptr; }
920
921 /// Builds external uses of the vectorized scalars, i.e. the list of
922 /// vectorized scalars to be extracted, their lanes and their scalar users. \p
923 /// ExternallyUsedValues contains additional list of external uses to handle
924 /// vectorization of reductions.
925 void
926 buildExternalUses(const ExtraValueToDebugLocsMap &ExternallyUsedValues = {});
927
928 /// Transforms graph nodes to target specific representations, if profitable.
929 void transformNodes();
930
931 /// Clear the internal data structures that are created by 'buildTree'.
932 void deleteTree() {
933 VectorizableTree.clear();
934 ScalarToTreeEntries.clear();
935 DeletedNodes.clear();
936 TransformedToGatherNodes.clear();
937 OperandsToTreeEntry.clear();
938 ScalarsInSplitNodes.clear();
939 MustGather.clear();
940 ReassocScalarToTreeEntries.clear();
941 KeptReassocScalars.clear();
942 NonScheduledFirst.clear();
943 EntryToLastInstruction.clear();
944 LastInstructionToPos.clear();
945 LoadEntriesToVectorize.clear();
946 IsGraphTransformMode = false;
947 GatheredLoadsEntriesFirst.reset();
948 CompressEntryToData.clear();
949 ExternalUses.clear();
950 ExternalUsesAsOriginalScalar.clear();
951 ExternalUsesWithNonUsers.clear();
952 ExternalUseReplacements.clear();
953 RTChecks.clear();
954 HasRuntimeCheckableBlockers = false;
955 HasNonCheckableMemBlocker = false;
956 RTChecksFinalized = false;
957 for (auto &Iter : BlocksSchedules) {
958 BlockScheduling *BS = Iter.second.get();
959 BS->clear();
960 }
961 MinBWs.clear();
962 ReductionBitWidth = 0;
963 BaseGraphSize = 1;
964 CastMaxMinBWSizes.reset();
965 ExtraBitWidthNodes.clear();
966 InstrElementSize.clear();
967 UserIgnoreList = nullptr;
968 NarrowedChainInsts.clear();
969 PostponedGathers.clear();
970 ValueToGatherNodes.clear();
971 TreeEntryToStridedPtrInfoMap.clear();
972 CurrentLoopNest.clear();
973 MergedLoopBTCs.clear();
974 }
975
976 unsigned getTreeSize() const { return VectorizableTree.size(); }
977
978 /// Returns the base graph size, before any transformations.
979 unsigned getCanonicalGraphSize() const { return BaseGraphSize; }
980
981 /// Perform LICM and CSE on the newly generated gather sequences.
983
984 /// Does this non-empty order represent an identity order? Identity
985 /// should be represented as an empty order, so this is used to
986 /// decide if we can canonicalize a computed order. Undef elements
987 /// (represented as size) are ignored.
989 assert(!Order.empty() && "expected non-empty order");
990 const unsigned Sz = Order.size();
991 return all_of(enumerate(Order), [&](const auto &P) {
992 return P.value() == P.index() || P.value() == Sz;
993 });
994 }
995
996 /// Checks if the specified gather tree entry \p TE can be represented as a
997 /// shuffled vector entry + (possibly) permutation with other gathers. It
998 /// implements the checks only for possibly ordered scalars (Loads,
999 /// ExtractElement, ExtractValue), which can be part of the graph.
1000 /// \param TopToBottom If true, used for the whole tree rotation, false - for
1001 /// sub-tree rotations. \param IgnoreReorder true, if the order of the root
1002 /// node might be ignored.
1003 std::optional<OrdersType> findReusedOrderedScalars(const TreeEntry &TE,
1004 bool TopToBottom,
1005 bool IgnoreReorder);
1006
1007 /// Sort loads into increasing pointers offsets to allow greater clustering.
1008 std::optional<OrdersType> findPartiallyOrderedLoads(const TreeEntry &TE);
1009
1010 /// Gets reordering data for the given tree entry. If the entry is vectorized
1011 /// - just return ReorderIndices, otherwise check if the scalars can be
1012 /// reordered and return the most optimal order.
1013 /// \return std::nullopt if ordering is not important, empty order, if
1014 /// identity order is important, or the actual order.
1015 /// \param TopToBottom If true, include the order of vectorized stores and
1016 /// insertelement nodes, otherwise skip them.
1017 /// \param IgnoreReorder true, if the root node order can be ignored.
1018 std::optional<OrdersType>
1019 getReorderingData(const TreeEntry &TE, bool TopToBottom, bool IgnoreReorder);
1020
1021 /// Checks if it is profitable to reorder the current tree.
1022 /// If the tree does not contain many profitable reordable nodes, better to
1023 /// skip it to save compile time.
1024 bool isProfitableToReorder() const;
1025
1026 /// Reorders the current graph to the most profitable order starting from the
1027 /// root node to the leaf nodes. The best order is chosen only from the nodes
1028 /// of the same size (vectorization factor). Smaller nodes are considered
1029 /// parts of subgraph with smaller VF and they are reordered independently. We
1030 /// can make it because we still need to extend smaller nodes to the wider VF
1031 /// and we can merge reordering shuffles with the widening shuffles.
1032 void reorderTopToBottom();
1033
1034 /// Reorders the current graph to the most profitable order starting from
1035 /// leaves to the root. It allows to rotate small subgraphs and reduce the
1036 /// number of reshuffles if the leaf nodes use the same order. In this case we
1037 /// can merge the orders and just shuffle user node instead of shuffling its
1038 /// operands. Plus, even the leaf nodes have different orders, it allows to
1039 /// sink reordering in the graph closer to the root node and merge it later
1040 /// during analysis.
1041 void reorderBottomToTop(bool IgnoreReorder = false);
1042
1043 /// Marks the schedule data of the copyable-modeled operands of \p TE for
1044 /// dependency recalculation at the next bundle scheduling.
1045 void markCopyableDepsForRecalc(TreeEntry &TE);
1046
1047 /// \return The vector element size in bits to use when vectorizing the
1048 /// expression tree ending at \p V. If V is a store, the size is the width of
1049 /// the stored value. Otherwise, the size is the width of the largest loaded
1050 /// value reaching V. This method is used by the vectorizer to calculate
1051 /// vectorization factors.
1052 unsigned getVectorElementSize(Value *V);
1053
1054 /// Compute the minimum type sizes required to represent the entries in a
1055 /// vectorizable tree.
1057
1058 // \returns maximum vector register size as set by TTI or overridden by cl::opt.
1059 unsigned getMaxVecRegSize() const {
1060 return MaxVecRegSize;
1061 }
1062
1063 // \returns minimum vector register size as set by cl::opt.
1064 unsigned getMinVecRegSize() const {
1065 return MinVecRegSize;
1066 }
1067
1068 /// \returns the number of parts, the type \p VecTy is split at the codegen
1069 /// phase. The type legalization queries are repeated for the very same types
1070 /// during the analysis, so the results are cached for the function.
1072 Type *VecTy, Type *ScalarTy,
1073 unsigned Limit = std::numeric_limits<unsigned>::max()) const {
1074 auto [It, Inserted] =
1075 NumberOfPartsCache.try_emplace(std::make_tuple(VecTy, ScalarTy, Limit));
1076 if (Inserted)
1077 It->second = ::getNumberOfParts(*TTI, VecTy, ScalarTy, Limit);
1078 return It->second;
1079 }
1080
1081 unsigned getMinVF(unsigned Sz) const {
1082 return std::max(2U, getMinVecRegSize() / Sz);
1083 }
1084
1085 unsigned getMaximumVF(unsigned ElemWidth, unsigned Opcode) const {
1086 unsigned MaxVF = MaxVFOption.getNumOccurrences() ?
1087 MaxVFOption : TTI->getMaximumVF(ElemWidth, Opcode);
1088 return MaxVF ? MaxVF : UINT_MAX;
1089 }
1090
1091 /// Check if homogeneous aggregate is isomorphic to some VectorType.
1092 /// Accepts homogeneous multidimensional aggregate of scalars/vectors like
1093 /// {[4 x i16], [4 x i16]}, { <2 x float>, <2 x float> },
1094 /// {{{i16, i16}, {i16, i16}}, {{i16, i16}, {i16, i16}}} and so on.
1095 ///
1096 /// \returns number of elements in vector if isomorphism exists, 0 otherwise.
1097 unsigned canMapToVector(Type *T) const;
1098
1099 /// \returns true if the vectorized insertvalue result can be stored directly
1100 /// as a vector, i.e. every insertvalue with an external user is consumed by a
1101 /// single store only.
1102 bool canVectorStoreInsertValue(const TreeEntry *E) const;
1103
1104 /// \returns the source vector type for an InsertElement/InsertValue
1105 /// buildvector node \p E: the inserted vector type for insertelement, or a
1106 /// vector of the inserted scalar type wide enough to cover the highest
1107 /// inserted index for insertvalue.
1108 FixedVectorType *getInsertBuildVectorSrcTy(const TreeEntry *E) const;
1109
1110 /// \returns True if the VectorizableTree is both tiny and not fully
1111 /// vectorizable. We do not vectorize such trees.
1112 bool isTreeTinyAndNotFullyVectorizable(bool ForReduction = false) const;
1113
1114 /// Checks if the graph and all its subgraphs cannot be better vectorized.
1115 /// It may happen, if all gather nodes are loads and they cannot be
1116 /// "clusterized". In this case even subgraphs cannot be vectorized more
1117 /// effectively than the base graph.
1118 bool isTreeNotExtendable() const;
1119
1120 bool isStridedLoad(ArrayRef<Value *> PointerOps, Type *ScalarTy,
1121 Align Alignment, const int64_t Diff,
1122 const size_t Sz) const;
1123
1124 /// Return true if an array of scalar loads can be replaced with a strided
1125 /// load (with constant stride).
1126 ///
1127 /// It is possible that the load gets "widened". Suppose that originally each
1128 /// load loads `k` bytes and `PointerOps` can be arranged as follows (`%s` is
1129 /// constant): %b + 0 * %s + 0 %b + 0 * %s + 1 %b + 0 * %s + 2
1130 /// ...
1131 /// %b + 0 * %s + (w - 1)
1132 ///
1133 /// %b + 1 * %s + 0
1134 /// %b + 1 * %s + 1
1135 /// %b + 1 * %s + 2
1136 /// ...
1137 /// %b + 1 * %s + (w - 1)
1138 /// ...
1139 ///
1140 /// %b + (n - 1) * %s + 0
1141 /// %b + (n - 1) * %s + 1
1142 /// %b + (n - 1) * %s + 2
1143 /// ...
1144 /// %b + (n - 1) * %s + (w - 1)
1145 ///
1146 /// In this case we will generate a strided load of type `<n x (k * w)>`.
1147 ///
1148 /// \param PointerOps list of pointer arguments of loads.
1149 /// \param ElemTy original scalar type of loads.
1150 /// \param Alignment alignment of the first load.
1151 /// \param SortedIndices is the order of PointerOps as returned by
1152 /// `sortPtrAccesses`
1153 /// \param Diff Pointer difference between the lowest and the highes pointer
1154 /// in `PointerOps` as returned by `getPointersDiff`.
1155 /// \param Ptr0 first pointer in `PointersOps`.
1156 /// \param PtrN last pointer in `PointersOps`.
1157 /// \param SPtrInfo If the function return `true`, it also sets all the fields
1158 /// of `SPtrInfo` necessary to generate the strided load later.
1160 const ArrayRef<Value *> PointerOps, Type *ElemTy, Align Alignment,
1161 const SmallVectorImpl<unsigned> &SortedIndices, const int64_t Diff,
1162 Value *Ptr0, StridedPtrInfo &SPtrInfo) const;
1163
1164 /// Return true if an array of scalar loads can be replaced with a strided
1165 /// load (with run-time stride).
1166 /// \param PointerOps list of pointer arguments of loads.
1167 /// \param ScalarTy type of loads.
1168 /// \param CommonAlignment common alignement of loads as computed by
1169 /// `computeCommonAlignment<LoadInst>`.
1170 /// \param SortedIndicies is a list of indicies computed by this function such
1171 /// that the sequence `PointerOps[SortedIndices[0]],
1172 /// PointerOps[SortedIndicies[1]], ..., PointerOps[SortedIndices[n]]` is
1173 /// ordered by the coefficient of the stride. For example, if PointerOps is
1174 /// `%base + %stride, %base, %base + 2 * stride` the `SortedIndices` will be
1175 /// `[1, 0, 2]`. We follow the convention that if `SortedIndices` has to be
1176 /// `0, 1, 2, 3, ...` we return empty vector for `SortedIndicies`.
1177 /// \param SPtrInfo If the function return `true`, it also sets all the fields
1178 /// of `SPtrInfo` necessary to generate the strided load later.
1179 /// \param IsLoad Is this a strided load (true) or strided store (false)
1180 bool analyzeRtStrideCandidate(ArrayRef<Value *> PointerOps, Type *ScalarTy,
1181 Align CommonAlignment,
1182 SmallVectorImpl<unsigned> &SortedIndices,
1183 StridedPtrInfo &SPtrInfo, bool IsLoad) const;
1184
1185 /// Checks if the given array of loads can be represented as a vectorized,
1186 /// scatter or just simple gather.
1187 /// \param VL list of loads.
1188 /// \param VL0 main load value.
1189 /// \param Order returned order of load instructions.
1190 /// \param PointerOps returned list of pointer operands.
1191 /// \param BestVF return best vector factor, if recursive check found better
1192 /// vectorization sequences rather than masked gather.
1193 /// \param TryRecursiveCheck used to check if long masked gather can be
1194 /// represented as a serie of loads/insert subvector, if profitable.
1197 SmallVectorImpl<Value *> &PointerOps,
1198 StridedPtrInfo &SPtrInfo,
1199 unsigned *BestVF = nullptr,
1200 bool TryRecursiveCheck = true) const;
1201
1202 /// Checks whether some existing tree entry has scalars equal to \p VL.
1203 /// \p S is the common opcode of \p VL when one exists; an empty \p S means
1204 /// the values have no common opcode (mixed buildvector/gather candidates).
1206 auto IsSame = [&](const TreeEntry *TE) { return TE->isSame(VL); };
1207 if (S) {
1208 // Any vectorized or gather entry equal to VL must contain S.getMainOp()
1209 // (the representative instruction, which is also the recorded scalar
1210 // for copyable-elements bundles), so probing the MainOp-indexed maps
1211 // is sufficient and avoids scanning the whole tree.
1212 return any_of(getTreeEntries(S.getMainOp()), IsSame) ||
1213 any_of(ValueToGatherNodes.lookup(S.getMainOp()), IsSame);
1214 }
1215 // No common opcode: only gather entries can match. Each non-constant
1216 // value in VL has to be in the gather entry's scalar list and is
1217 // therefore present in ValueToGatherNodes. Probe by VL members instead
1218 // of scanning the whole tree (O(tree) -> O(|VL|)).
1220 for (Value *V : VL) {
1221 // Constants/poisons are not tracked in ValueToGatherNodes.
1222 if (isConstant(V))
1223 continue;
1224 for (const TreeEntry *TE : ValueToGatherNodes.lookup(V)) {
1225 if (!Visited.insert(TE).second)
1226 continue;
1227 if (IsSame(TE))
1228 return true;
1229 }
1230 }
1231 return false;
1232 }
1233
1234 /// Registers non-vectorizable sequence of loads
1235 template <typename T> void registerNonVectorizableLoads(ArrayRef<T *> VL) {
1236 ListOfKnonwnNonVectorizableLoads.insert(hash_value(VL));
1237 }
1238
1239 /// Checks if the given loads sequence is known as not vectorizable
1240 template <typename T>
1242 return ListOfKnonwnNonVectorizableLoads.contains(hash_value(VL));
1243 }
1244
1246
1247 /// This structure holds any data we need about the edges being traversed
1248 /// during buildTreeRec(). We keep track of:
1249 /// (i) the user TreeEntry index, and
1250 /// (ii) the index of the edge.
1251 struct EdgeInfo {
1252 EdgeInfo() = default;
1253 EdgeInfo(TreeEntry *UserTE, unsigned EdgeIdx)
1255 /// The user TreeEntry.
1256 TreeEntry *UserTE = nullptr;
1257 /// The operand index of the use.
1258 unsigned EdgeIdx = UINT_MAX;
1259#ifndef NDEBUG
1261 const BoUpSLP::EdgeInfo &EI) {
1262 EI.dump(OS);
1263 return OS;
1264 }
1265 /// Debug print.
1266 void dump(raw_ostream &OS) const {
1267 OS << "{User:" << (UserTE ? std::to_string(UserTE->Idx) : "null")
1268 << " EdgeIdx:" << EdgeIdx << "}";
1269 }
1270 LLVM_DUMP_METHOD void dump() const { dump(dbgs()); }
1271#endif
1272 bool operator == (const EdgeInfo &Other) const {
1273 return UserTE == Other.UserTE && EdgeIdx == Other.EdgeIdx;
1274 }
1275
1276 operator bool() const { return UserTE != nullptr; }
1277 };
1278 friend struct DenseMapInfo<EdgeInfo>;
1279
1280 /// A helper class used for scoring candidates for two consecutive lanes.
1282 const TargetLibraryInfo &TLI;
1283 const DataLayout &DL;
1284 ScalarEvolution &SE;
1285 const BoUpSLP &R;
1286 int NumLanes; // Total number of lanes (aka vectorization factor).
1287 int MaxLevel; // The maximum recursion depth for accumulating score.
1288
1289 public:
1291 ScalarEvolution &SE, const BoUpSLP &R, int NumLanes,
1292 int MaxLevel)
1293 : TLI(TLI), DL(DL), SE(SE), R(R), NumLanes(NumLanes),
1294 MaxLevel(MaxLevel) {}
1295
1296 // The hard-coded scores listed here are not very important, though it shall
1297 // be higher for better matches to improve the resulting cost. When
1298 // computing the scores of matching one sub-tree with another, we are
1299 // basically counting the number of values that are matching. So even if all
1300 // scores are set to 1, we would still get a decent matching result.
1301 // However, sometimes we have to break ties. For example we may have to
1302 // choose between matching loads vs matching opcodes. This is what these
1303 // scores are helping us with: they provide the order of preference. Also,
1304 // this is important if the scalar is externally used or used in another
1305 // tree entry node in the different lane.
1306
1307 /// Loads from consecutive memory addresses, e.g. load(A[i]), load(A[i+1]).
1308 static constexpr int ScoreConsecutiveLoads = 40;
1309 /// The same load multiple times. This should have a better score than
1310 /// `ScoreSplat` because it in x86 for a 2-lane vector we can represent it
1311 /// with `movddup (%reg), xmm0` which has a throughput of 0.5 versus 0.5 for
1312 /// a vector load and 1.0 for a broadcast.
1313 static constexpr int ScoreSplatLoads = 30;
1314 /// Loads from reversed memory addresses, e.g. load(A[i+1]), load(A[i]).
1315 static constexpr int ScoreReversedLoads = 30;
1316 /// A load candidate for masked gather.
1317 static constexpr int ScoreMaskedGatherCandidate = 10;
1318 /// ExtractElementInst from same vector and consecutive indexes.
1319 static constexpr int ScoreConsecutiveExtracts = 40;
1320 /// ExtractElementInst from same vector and reversed indices.
1321 static constexpr int ScoreReversedExtracts = 30;
1322 /// Constants.
1323 static constexpr int ScoreConstants = 15;
1324 /// Same constants.
1325 static constexpr int ScoreSameConstants = 17;
1326 /// Instructions with the same opcode.
1327 static constexpr int ScoreSameOpcode = 20;
1328 /// Instructions with alt opcodes (e.g, add + sub).
1329 static constexpr int ScoreAltOpcodes = 10;
1330 /// Identical instructions (a.k.a. splat or broadcast).
1331 static constexpr int ScoreSplat = 10;
1332 /// Matching with an undef is preferable to failing.
1333 static constexpr int ScoreUndef = 10;
1334 /// Score for failing to find a decent match.
1335 static constexpr int ScoreFail = 0;
1336 /// Score if all users are vectorized.
1337 static constexpr int ScoreAllUserVectorized = 10;
1338
1339 /// \returns the score of placing \p V1 and \p V2 in consecutive lanes.
1340 /// \p U1 and \p U2 are the users of \p V1 and \p V2.
1341 /// Also, checks if \p V1 and \p V2 are compatible with instructions in \p
1342 /// MainAltOps.
1344 ArrayRef<Value *> MainAltOps) const {
1345 if (!isValidElementType(V1->getType()) ||
1348
1349 if (V1 == V2) {
1350 if (isa<LoadInst>(V1)) {
1351 // Retruns true if the users of V1 and V2 won't need to be extracted.
1352 auto AllUsersAreInternal = [U1, U2, this](Value *V1, Value *V2) {
1353 // Bail out if we have too many uses to save compilation time.
1354 if (V1->hasNUsesOrMore(UsesLimit) || V2->hasNUsesOrMore(UsesLimit))
1355 return false;
1356
1357 auto AllUsersVectorized = [U1, U2, this](Value *V) {
1358 return llvm::all_of(V->users(), [U1, U2, this](Value *U) {
1359 return U == U1 || U == U2 || R.isVectorized(U);
1360 });
1361 };
1362 return AllUsersVectorized(V1) && AllUsersVectorized(V2);
1363 };
1364 // A broadcast of a load can be cheaper on some targets.
1365 if (R.TTI->isLegalBroadcastLoad(V1->getType(),
1366 ElementCount::getFixed(NumLanes)) &&
1367 ((int)V1->getNumUses() == NumLanes ||
1368 AllUsersAreInternal(V1, V2)))
1370 }
1371 if (isa<UndefValue>(V1))
1373 if (isConstant(V1))
1376 }
1377
1378 auto CheckSameEntryOrFail = [&]() {
1379 if (ArrayRef<TreeEntry *> TEs1 = R.getTreeEntries(V1); !TEs1.empty()) {
1381 if (ArrayRef<TreeEntry *> TEs2 = R.getTreeEntries(V2);
1382 !TEs2.empty() &&
1383 any_of(TEs2, [&](TreeEntry *E) { return Set.contains(E); }))
1385 }
1387 };
1388
1389 auto *LI1 = dyn_cast<LoadInst>(V1);
1390 auto *LI2 = dyn_cast<LoadInst>(V2);
1391 if (LI1 && LI2) {
1392 if (LI1->getParent() != LI2->getParent() || !LI1->isSimple() ||
1393 !LI2->isSimple())
1394 return CheckSameEntryOrFail();
1395
1396 std::optional<int64_t> Dist = getPointersDiff(
1397 LI1->getType(), LI1->getPointerOperand(), LI2->getType(),
1398 LI2->getPointerOperand(), DL, SE, /*StrictCheck=*/true);
1399 if (!Dist || *Dist == 0) {
1400 if (getUnderlyingObject(LI1->getPointerOperand()) ==
1401 getUnderlyingObject(LI2->getPointerOperand()) &&
1402 R.TTI->isLegalMaskedGather(
1403 getWidenedType(LI1->getType(), NumLanes), LI1->getAlign()))
1405 return CheckSameEntryOrFail();
1406 }
1407 // The distance is too large - still may be profitable to use masked
1408 // loads/gathers.
1409 if (std::abs(*Dist) > NumLanes / 2)
1411 // This still will detect consecutive loads, but we might have "holes"
1412 // in some cases. It is ok for non-power-2 vectorization and may produce
1413 // better results. It should not affect current vectorization.
1416 }
1417
1418 auto *C1 = dyn_cast<Constant>(V1);
1419 auto *C2 = dyn_cast<Constant>(V2);
1420 if (C1 && C2)
1422
1423 // Consider constants and buildvector compatible.
1424 if ((C1 && isa<InsertElementInst>(V2)) ||
1425 (C2 && isa<InsertElementInst>(V1)))
1427
1428 // Extracts from consecutive indexes of the same vector better score as
1429 // the extracts could be optimized away.
1430 Value *EV1;
1431 ConstantInt *Ex1Idx;
1432 if (match(V1, m_ExtractElt(m_Value(EV1), m_ConstantInt(Ex1Idx)))) {
1433 // Undefs are always profitable for extractelements.
1434 // Compiler can easily combine poison and extractelement <non-poison> or
1435 // undef and extractelement <poison>. But combining undef +
1436 // extractelement <non-poison-but-may-produce-poison> requires some
1437 // extra operations.
1438 if (isa<UndefValue>(V2))
1439 return (isa<PoisonValue>(V2) || isUndefVector(EV1).all())
1442 Value *EV2 = nullptr;
1443 ConstantInt *Ex2Idx = nullptr;
1444 if (match(V2,
1446 m_Undef())))) {
1447 // Undefs are always profitable for extractelements.
1448 if (!Ex2Idx)
1450 if (isUndefVector(EV2).all() && EV2->getType() == EV1->getType())
1452 if (EV2 == EV1) {
1453 int Idx1 = Ex1Idx->getZExtValue();
1454 int Idx2 = Ex2Idx->getZExtValue();
1455 int Dist = Idx2 - Idx1;
1456 // The distance is too large - still may be profitable to use
1457 // shuffles.
1458 if (std::abs(Dist) == 0)
1460 if (std::abs(Dist) > NumLanes / 2)
1464 }
1466 }
1467 return CheckSameEntryOrFail();
1468 }
1469
1470 auto *I1 = dyn_cast<Instruction>(V1);
1471 auto *I2 = dyn_cast<Instruction>(V2);
1472 if (I1 && I2) {
1473 if (I1->getParent() != I2->getParent())
1474 return CheckSameEntryOrFail();
1475 Value *V;
1476 Value *Cond;
1477 // ZExt i1 to something must be considered same opcode for select i1
1478 // cmp, x, y
1479 // Required to better match the transformation after
1480 // BoUpSLP::matchesInversedZExtSelect analysis.
1481 if ((match(I1, m_ZExt(m_Value(V))) &&
1482 match(I2, m_Select(m_Value(Cond), m_Value(), m_Value())) &&
1483 V->getType() == Cond->getType()) ||
1484 (match(I2, m_ZExt(m_Value(V))) &&
1485 match(I1, m_Select(m_Value(Cond), m_Value(), m_Value())) &&
1486 V->getType() == Cond->getType()))
1488 SmallVector<Value *, 4> Ops(MainAltOps);
1489 Ops.push_back(I1);
1490 Ops.push_back(I2);
1492 // Note: Only consider instructions with <= 2 operands to avoid
1493 // complexity explosion.
1494 if (S &&
1495 (S.getMainOp()->getNumOperands() <= 2 || !MainAltOps.empty() ||
1496 !S.isAltShuffle()) &&
1497 all_of(Ops, [&S](Value *V) {
1498 return isa<PoisonValue>(V) ||
1499 cast<Instruction>(V)->getNumOperands() ==
1501 }))
1504 }
1505
1506 if (I1 && isa<PoisonValue>(V2))
1508
1509 if (isa<UndefValue>(V2))
1511
1512 return CheckSameEntryOrFail();
1513 }
1514
1515 /// Go through the operands of \p LHS and \p RHS recursively until
1516 /// MaxLevel, and return the cummulative score. \p U1 and \p U2 are
1517 /// the users of \p LHS and \p RHS (that is \p LHS and \p RHS are operands
1518 /// of \p U1 and \p U2), except at the beginning of the recursion where
1519 /// these are set to nullptr.
1520 ///
1521 /// For example:
1522 /// \verbatim
1523 /// A[0] B[0] A[1] B[1] C[0] D[0] B[1] A[1]
1524 /// \ / \ / \ / \ /
1525 /// + + + +
1526 /// G1 G2 G3 G4
1527 /// \endverbatim
1528 /// The getScoreAtLevelRec(G1, G2) function will try to match the nodes at
1529 /// each level recursively, accumulating the score. It starts from matching
1530 /// the additions at level 0, then moves on to the loads (level 1). The
1531 /// score of G1 and G2 is higher than G1 and G3, because {A[0],A[1]} and
1532 /// {B[0],B[1]} match with LookAheadHeuristics::ScoreConsecutiveLoads, while
1533 /// {A[0],C[0]} has a score of LookAheadHeuristics::ScoreFail.
1534 /// Please note that the order of the operands does not matter, as we
1535 /// evaluate the score of all profitable combinations of operands. In
1536 /// other words the score of G1 and G4 is the same as G1 and G2. This
1537 /// heuristic is based on ideas described in:
1538 /// Look-ahead SLP: Auto-vectorization in the presence of commutative
1539 /// operations, CGO 2018 by Vasileios Porpodas, Rodrigo C. O. Rocha,
1540 /// Luís F. W. Góes
1542 Instruction *U2, int CurrLevel,
1543 ArrayRef<Value *> MainAltOps) const {
1544
1545 // Get the shallow score of V1 and V2.
1546 int ShallowScoreAtThisLevel =
1547 getShallowScore(LHS, RHS, U1, U2, MainAltOps);
1548
1549 // If reached MaxLevel,
1550 // or if V1 and V2 are not instructions,
1551 // or if they are SPLAT,
1552 // or if they are not consecutive,
1553 // or if profitable to vectorize loads or extractelements, early return
1554 // the current cost.
1555 auto *I1 = dyn_cast<Instruction>(LHS);
1556 auto *I2 = dyn_cast<Instruction>(RHS);
1557 if (CurrLevel == MaxLevel || !(I1 && I2) || I1 == I2 ||
1558 ShallowScoreAtThisLevel == LookAheadHeuristics::ScoreFail ||
1559 (((isa<LoadInst>(I1) && isa<LoadInst>(I2)) ||
1560 (I1->getNumOperands() > 2 && I2->getNumOperands() > 2) ||
1562 ShallowScoreAtThisLevel))
1563 return ShallowScoreAtThisLevel;
1564 assert(I1 && I2 && "Should have early exited.");
1565
1566 // Contains the I2 operand indexes that got matched with I1 operands.
1567 SmallSet<unsigned, 4> Op2Used;
1568
1569 // Recursion towards the operands of I1 and I2. We are trying all possible
1570 // operand pairs, and keeping track of the best score.
1571 if (I1->getNumOperands() != I2->getNumOperands())
1573 for (unsigned OpIdx1 = 0, NumOperands1 = I1->getNumOperands();
1574 OpIdx1 != NumOperands1; ++OpIdx1) {
1575 // Try to pair op1I with the best operand of I2.
1576 int MaxTmpScore = 0;
1577 unsigned MaxOpIdx2 = 0;
1578 bool FoundBest = false;
1579 // If I2 is commutative try all combinations.
1580 unsigned FromIdx = isCommutative(I2) ? 0 : OpIdx1;
1581 unsigned ToIdx = isCommutative(I2)
1582 ? I2->getNumOperands()
1583 : std::min(I2->getNumOperands(), OpIdx1 + 1);
1584 assert(FromIdx <= ToIdx && "Bad index");
1585 for (unsigned OpIdx2 = FromIdx; OpIdx2 != ToIdx; ++OpIdx2) {
1586 // Skip operands already paired with OpIdx1.
1587 if (Op2Used.count(OpIdx2))
1588 continue;
1589 // Recursively calculate the cost at each level
1590 int TmpScore =
1591 getScoreAtLevelRec(I1->getOperand(OpIdx1), I2->getOperand(OpIdx2),
1592 I1, I2, CurrLevel + 1, {});
1593 // Look for the best score.
1594 if (TmpScore > LookAheadHeuristics::ScoreFail &&
1595 TmpScore > MaxTmpScore) {
1596 MaxTmpScore = TmpScore;
1597 MaxOpIdx2 = OpIdx2;
1598 FoundBest = true;
1599 }
1600 }
1601 if (FoundBest) {
1602 // Pair {OpIdx1, MaxOpIdx2} was found to be best. Never revisit it.
1603 Op2Used.insert(MaxOpIdx2);
1604 ShallowScoreAtThisLevel += MaxTmpScore;
1605 }
1606 }
1607 return ShallowScoreAtThisLevel;
1608 }
1609 };
1610 /// A helper data structure to hold the operands of a vector of instructions.
1611 /// This supports a fixed vector length for all operand vectors.
1613 /// For each operand we need (i) the value, and (ii) the opcode that it
1614 /// would be attached to if the expression was in a left-linearized form.
1615 /// This is required to avoid illegal operand reordering.
1616 /// For example:
1617 /// \verbatim
1618 /// 0 Op1
1619 /// |/
1620 /// Op1 Op2 Linearized + Op2
1621 /// \ / ----------> |/
1622 /// - -
1623 ///
1624 /// Op1 - Op2 (0 + Op1) - Op2
1625 /// \endverbatim
1626 ///
1627 /// Value Op1 is attached to a '+' operation, and Op2 to a '-'.
1628 ///
1629 /// Another way to think of this is to track all the operations across the
1630 /// path from the operand all the way to the root of the tree and to
1631 /// calculate the operation that corresponds to this path. For example, the
1632 /// path from Op2 to the root crosses the RHS of the '-', therefore the
1633 /// corresponding operation is a '-' (which matches the one in the
1634 /// linearized tree, as shown above).
1635 ///
1636 /// For lack of a better term, we refer to this operation as Accumulated
1637 /// Path Operation (APO).
1638 struct OperandData {
1639 OperandData() = default;
1640 OperandData(Value *V, bool APO, bool IsUsed)
1641 : V(V), APO(APO), IsUsed(IsUsed) {}
1642 /// The operand value.
1643 Value *V = nullptr;
1644 /// TreeEntries only allow a single opcode, or an alternate sequence of
1645 /// them (e.g, +, -). Therefore, we can safely use a boolean value for the
1646 /// APO. It is set to 'true' if 'V' is attached to an inverse operation
1647 /// in the left-linearized form (e.g., Sub/Div), and 'false' otherwise
1648 /// (e.g., Add/Mul)
1649 bool APO = false;
1650 /// Helper data for the reordering function.
1651 bool IsUsed = false;
1652 };
1653
1654 /// During operand reordering, we are trying to select the operand at lane
1655 /// that matches best with the operand at the neighboring lane. Our
1656 /// selection is based on the type of value we are looking for. For example,
1657 /// if the neighboring lane has a load, we need to look for a load that is
1658 /// accessing a consecutive address. These strategies are summarized in the
1659 /// 'ReorderingMode' enumerator.
1660 enum class ReorderingMode {
1661 Load, ///< Matching loads to consecutive memory addresses
1662 Opcode, ///< Matching instructions based on opcode (same or alternate)
1663 Constant, ///< Matching constants
1664 Splat, ///< Matching the same instruction multiple times (broadcast)
1665 Failed, ///< We failed to create a vectorizable group
1666 };
1667
1668 using OperandDataVec = SmallVector<OperandData, 2>;
1669
1670 /// A vector of operand vectors.
1672 /// When VL[0] is IntrinsicInst, ArgSize is CallBase::arg_size. When VL[0]
1673 /// is not IntrinsicInst, ArgSize is User::getNumOperands.
1674 unsigned ArgSize = 0;
1675
1676 const TargetLibraryInfo &TLI;
1677 const DataLayout &DL;
1678 ScalarEvolution &SE;
1679 const BoUpSLP &R;
1680 const Loop *L = nullptr;
1681
1682 /// \returns the operand data at \p OpIdx and \p Lane.
1683 OperandData &getData(unsigned OpIdx, unsigned Lane) {
1684 return OpsVec[OpIdx][Lane];
1685 }
1686
1687 /// \returns the operand data at \p OpIdx and \p Lane. Const version.
1688 const OperandData &getData(unsigned OpIdx, unsigned Lane) const {
1689 return OpsVec[OpIdx][Lane];
1690 }
1691
1692 /// Clears the used flag for all entries.
1693 void clearUsed() {
1694 for (unsigned OpIdx = 0, NumOperands = getNumOperands();
1695 OpIdx != NumOperands; ++OpIdx)
1696 for (unsigned Lane = 0, NumLanes = getNumLanes(); Lane != NumLanes;
1697 ++Lane)
1698 OpsVec[OpIdx][Lane].IsUsed = false;
1699 }
1700
1701 /// Swap the operand at \p OpIdx1 with that one at \p OpIdx2.
1702 void swap(unsigned OpIdx1, unsigned OpIdx2, unsigned Lane) {
1703 std::swap(OpsVec[OpIdx1][Lane], OpsVec[OpIdx2][Lane]);
1704 }
1705
1706 /// \param Lane lane of the operands under analysis.
1707 /// \param OpIdx operand index in \p Lane lane we're looking the best
1708 /// candidate for.
1709 /// \param Idx operand index of the current candidate value.
1710 /// \returns The additional score due to possible broadcasting of the
1711 /// elements in the lane. It is more profitable to have power-of-2 unique
1712 /// elements in the lane, it will be vectorized with higher probability
1713 /// after removing duplicates. Currently the SLP vectorizer supports only
1714 /// vectorization of the power-of-2 number of unique scalars.
1715 int getSplatScore(unsigned Lane, unsigned OpIdx, unsigned Idx,
1716 const SmallBitVector &UsedLanes) const {
1717 Value *IdxLaneV = getData(Idx, Lane).V;
1718 if (!isa<Instruction>(IdxLaneV) || IdxLaneV == getData(OpIdx, Lane).V ||
1719 isa<ExtractElementInst>(IdxLaneV))
1720 return 0;
1722 for (unsigned Ln : seq<unsigned>(getNumLanes())) {
1723 if (Ln == Lane)
1724 continue;
1725 Value *OpIdxLnV = getData(OpIdx, Ln).V;
1726 if (!isa<Instruction>(OpIdxLnV))
1727 return 0;
1728 Uniques.try_emplace(OpIdxLnV, Ln);
1729 }
1730 unsigned UniquesCount = Uniques.size();
1731 auto IdxIt = Uniques.find(IdxLaneV);
1732 unsigned UniquesCntWithIdxLaneV =
1733 IdxIt != Uniques.end() ? UniquesCount : UniquesCount + 1;
1734 Value *OpIdxLaneV = getData(OpIdx, Lane).V;
1735 auto OpIdxIt = Uniques.find(OpIdxLaneV);
1736 unsigned UniquesCntWithOpIdxLaneV =
1737 OpIdxIt != Uniques.end() ? UniquesCount : UniquesCount + 1;
1738 if (UniquesCntWithIdxLaneV == UniquesCntWithOpIdxLaneV)
1739 return 0;
1740 return std::min(bit_ceil(UniquesCntWithOpIdxLaneV) -
1741 UniquesCntWithOpIdxLaneV,
1742 UniquesCntWithOpIdxLaneV -
1743 bit_floor(UniquesCntWithOpIdxLaneV)) -
1744 ((IdxIt != Uniques.end() && UsedLanes.test(IdxIt->second))
1745 ? UniquesCntWithIdxLaneV - bit_floor(UniquesCntWithIdxLaneV)
1746 : bit_ceil(UniquesCntWithIdxLaneV) - UniquesCntWithIdxLaneV);
1747 }
1748
1749 /// \param Lane lane of the operands under analysis.
1750 /// \param OpIdx operand index in \p Lane lane we're looking the best
1751 /// candidate for.
1752 /// \param Idx operand index of the current candidate value.
1753 /// \returns The additional score for the scalar which users are all
1754 /// vectorized.
1755 int getExternalUseScore(unsigned Lane, unsigned OpIdx, unsigned Idx) const {
1756 Value *IdxLaneV = getData(Idx, Lane).V;
1757 Value *OpIdxLaneV = getData(OpIdx, Lane).V;
1758 // Do not care about number of uses for vector-like instructions
1759 // (extractelement/extractvalue with constant indices), they are extracts
1760 // themselves and already externally used. Vectorization of such
1761 // instructions does not add extra extractelement instruction, just may
1762 // remove it.
1763 if (isVectorLikeInstWithConstOps(IdxLaneV) &&
1764 isVectorLikeInstWithConstOps(OpIdxLaneV))
1766 auto *IdxLaneI = dyn_cast<Instruction>(IdxLaneV);
1767 if (!IdxLaneI || !isa<Instruction>(OpIdxLaneV))
1768 return 0;
1769 return R.areAllUsersVectorized(IdxLaneI)
1771 : 0;
1772 }
1773
1774 /// Score scaling factor for fully compatible instructions but with
1775 /// different number of external uses. Allows better selection of the
1776 /// instructions with less external uses.
1777 static constexpr int ScoreScaleFactor = 10;
1778 /// Scale factor for constants only.
1779 static constexpr int ScoreConstantScaleFactor = 6;
1780
1781 /// \Returns the look-ahead score, which tells us how much the sub-trees
1782 /// rooted at \p LHS and \p RHS match, the more they match the higher the
1783 /// score. This helps break ties in an informed way when we cannot decide on
1784 /// the order of the operands by just considering the immediate
1785 /// predecessors.
1786 int getLookAheadScore(Value *LHS, Value *RHS, ArrayRef<Value *> MainAltOps,
1787 int Lane, unsigned OpIdx, unsigned Idx,
1788 bool &IsUsed, const SmallBitVector &UsedLanes) {
1789 LookAheadHeuristics LookAhead(TLI, DL, SE, R, getNumLanes(),
1791 // Keep track of the instruction stack as we recurse into the operands
1792 // during the look-ahead score exploration.
1793 int Score =
1794 LookAhead.getScoreAtLevelRec(LHS, RHS, /*U1=*/nullptr, /*U2=*/nullptr,
1795 /*CurrLevel=*/1, MainAltOps);
1796 if (Score) {
1797 int SplatScore =
1798 getSplatScore(Lane, OpIdx, Idx, UsedLanes) * ScoreScaleFactor;
1799 if (Score <= -SplatScore) {
1800 // Failed score.
1801 Score = 0;
1802 } else {
1803 Score += SplatScore;
1804 // Scale score to see the difference between different operands
1805 // and similar operands but all vectorized/not all vectorized
1806 // uses. It does not affect actual selection of the best
1807 // compatible operand in general, just allows to select the
1808 // operand with all vectorized uses.
1809 const int SF = (LHS == RHS && isConstant(LHS))
1810 ? ScoreConstantScaleFactor
1811 : ScoreScaleFactor;
1812 Score *= SF;
1813 Score += getExternalUseScore(Lane, OpIdx, Idx);
1814 IsUsed = true;
1815 }
1816 }
1817 return Score;
1818 }
1819
1820 /// Best defined scores per lanes between the passes. Used to choose the
1821 /// best operand (with the highest score) between the passes.
1822 /// The key - {Operand Index, Lane}.
1823 /// The value - the best score between the passes for the lane and the
1824 /// operand.
1826 BestScoresPerLanes;
1827
1828 // Search all operands in Ops[*][Lane] for the one that matches best
1829 // Ops[OpIdx][LastLane] and return its opreand index.
1830 // If no good match can be found, return std::nullopt.
1831 std::optional<unsigned>
1832 getBestOperand(unsigned OpIdx, int Lane, int LastLane,
1833 ArrayRef<ReorderingMode> ReorderingModes,
1834 ArrayRef<Value *> MainAltOps,
1835 const SmallBitVector &UsedLanes) {
1836 unsigned NumOperands = getNumOperands();
1837
1838 // The operand of the previous lane at OpIdx.
1839 Value *OpLastLane = getData(OpIdx, LastLane).V;
1840
1841 // Our strategy mode for OpIdx.
1842 ReorderingMode RMode = ReorderingModes[OpIdx];
1843 if (RMode == ReorderingMode::Failed)
1844 return std::nullopt;
1845
1846 // The linearized opcode of the operand at OpIdx, Lane.
1847 bool OpIdxAPO = getData(OpIdx, Lane).APO;
1848
1849 // The best operand index and its score.
1850 // Sometimes we have more than one option (e.g., Opcode and Undefs), so we
1851 // are using the score to differentiate between the two.
1852 struct BestOpData {
1853 std::optional<unsigned> Idx;
1854 unsigned Score = 0;
1855 } BestOp;
1856 BestOp.Score =
1857 BestScoresPerLanes.try_emplace(std::make_pair(OpIdx, Lane), 0)
1858 .first->second;
1859
1860 // Track if the operand must be marked as used. If the operand is set to
1861 // Score 1 explicitly (because of non power-of-2 unique scalars, we may
1862 // want to reestimate the operands again on the following iterations).
1863 bool IsUsed = RMode == ReorderingMode::Splat ||
1864 RMode == ReorderingMode::Constant ||
1865 RMode == ReorderingMode::Load;
1866 // Iterate through all unused operands and look for the best.
1867 for (unsigned Idx = 0; Idx != NumOperands; ++Idx) {
1868 // Get the operand at Idx and Lane.
1869 OperandData &OpData = getData(Idx, Lane);
1870 Value *Op = OpData.V;
1871 bool OpAPO = OpData.APO;
1872
1873 // Skip already selected operands.
1874 if (OpData.IsUsed)
1875 continue;
1876
1877 // Skip if we are trying to move the operand to a position with a
1878 // different opcode in the linearized tree form. This would break the
1879 // semantics.
1880 if (OpAPO != OpIdxAPO)
1881 continue;
1882
1883 // Look for an operand that matches the current mode.
1884 switch (RMode) {
1885 case ReorderingMode::Load:
1886 case ReorderingMode::Opcode: {
1887 bool LeftToRight = Lane > LastLane;
1888 Value *OpLeft = (LeftToRight) ? OpLastLane : Op;
1889 Value *OpRight = (LeftToRight) ? Op : OpLastLane;
1890 int Score = getLookAheadScore(OpLeft, OpRight, MainAltOps, Lane,
1891 OpIdx, Idx, IsUsed, UsedLanes);
1892 if (Score > static_cast<int>(BestOp.Score) ||
1893 (Score > 0 && Score == static_cast<int>(BestOp.Score) &&
1894 Idx == OpIdx)) {
1895 BestOp.Idx = Idx;
1896 BestOp.Score = Score;
1897 BestScoresPerLanes[std::make_pair(OpIdx, Lane)] = Score;
1898 }
1899 break;
1900 }
1901 case ReorderingMode::Constant:
1902 if (isa<Constant>(Op) ||
1903 (!BestOp.Score && L && L->isLoopInvariant(Op))) {
1904 BestOp.Idx = Idx;
1905 if (isa<Constant>(Op)) {
1907 BestScoresPerLanes[std::make_pair(OpIdx, Lane)] =
1909 }
1911 IsUsed = false;
1912 }
1913 break;
1914 case ReorderingMode::Splat:
1915 if (Op == OpLastLane || (!BestOp.Score && isa<Constant>(Op))) {
1916 IsUsed = Op == OpLastLane;
1917 if (Op == OpLastLane) {
1918 BestOp.Score = LookAheadHeuristics::ScoreSplat;
1919 BestScoresPerLanes[std::make_pair(OpIdx, Lane)] =
1921 }
1922 BestOp.Idx = Idx;
1923 }
1924 break;
1925 case ReorderingMode::Failed:
1926 llvm_unreachable("Not expected Failed reordering mode.");
1927 }
1928 }
1929
1930 if (BestOp.Idx) {
1931 getData(*BestOp.Idx, Lane).IsUsed = IsUsed;
1932 return BestOp.Idx;
1933 }
1934 // If we could not find a good match return std::nullopt.
1935 return std::nullopt;
1936 }
1937
1938 /// Helper for reorderOperandVecs.
1939 /// \returns the lane that we should start reordering from. This is the one
1940 /// which has the least number of operands that can freely move about or
1941 /// less profitable because it already has the most optimal set of operands.
1942 unsigned getBestLaneToStartReordering() const {
1943 unsigned Min = UINT_MAX;
1944 unsigned SameOpNumber = 0;
1945 // std::pair<unsigned, unsigned> is used to implement a simple voting
1946 // algorithm and choose the lane with the least number of operands that
1947 // can freely move about or less profitable because it already has the
1948 // most optimal set of operands. The first unsigned is a counter for
1949 // voting, the second unsigned is the counter of lanes with instructions
1950 // with same/alternate opcodes and same parent basic block.
1952 // Try to be closer to the original results, if we have multiple lanes
1953 // with same cost. If 2 lanes have the same cost, use the one with the
1954 // highest index.
1955 for (int I = getNumLanes(); I > 0; --I) {
1956 unsigned Lane = I - 1;
1957 OperandsOrderData NumFreeOpsHash =
1958 getMaxNumOperandsThatCanBeReordered(Lane);
1959 // Compare the number of operands that can move and choose the one with
1960 // the least number.
1961 if (NumFreeOpsHash.NumOfAPOs < Min) {
1962 Min = NumFreeOpsHash.NumOfAPOs;
1963 SameOpNumber = NumFreeOpsHash.NumOpsWithSameOpcodeParent;
1964 HashMap.clear();
1965 HashMap[NumFreeOpsHash.Hash] = std::make_pair(1, Lane);
1966 } else if (NumFreeOpsHash.NumOfAPOs == Min &&
1967 NumFreeOpsHash.NumOpsWithSameOpcodeParent < SameOpNumber) {
1968 // Select the most optimal lane in terms of number of operands that
1969 // should be moved around.
1970 SameOpNumber = NumFreeOpsHash.NumOpsWithSameOpcodeParent;
1971 HashMap[NumFreeOpsHash.Hash] = std::make_pair(1, Lane);
1972 } else if (NumFreeOpsHash.NumOfAPOs == Min &&
1973 NumFreeOpsHash.NumOpsWithSameOpcodeParent == SameOpNumber) {
1974 auto [It, Inserted] =
1975 HashMap.try_emplace(NumFreeOpsHash.Hash, 1, Lane);
1976 if (!Inserted)
1977 ++It->second.first;
1978 }
1979 }
1980 // Select the lane with the minimum counter.
1981 unsigned BestLane = 0;
1982 unsigned CntMin = UINT_MAX;
1983 for (const auto &Data : reverse(HashMap)) {
1984 if (Data.second.first < CntMin) {
1985 CntMin = Data.second.first;
1986 BestLane = Data.second.second;
1987 }
1988 }
1989 return BestLane;
1990 }
1991
1992 /// Data structure that helps to reorder operands.
1993 struct OperandsOrderData {
1994 /// The best number of operands with the same APOs, which can be
1995 /// reordered.
1996 unsigned NumOfAPOs = UINT_MAX;
1997 /// Number of operands with the same/alternate instruction opcode and
1998 /// parent.
1999 unsigned NumOpsWithSameOpcodeParent = 0;
2000 /// Hash for the actual operands ordering.
2001 /// Used to count operands, actually their position id and opcode
2002 /// value. It is used in the voting mechanism to find the lane with the
2003 /// least number of operands that can freely move about or less profitable
2004 /// because it already has the most optimal set of operands. Can be
2005 /// replaced with SmallVector<unsigned> instead but hash code is faster
2006 /// and requires less memory.
2007 unsigned Hash = 0;
2008 };
2009 /// \returns the maximum number of operands that are allowed to be reordered
2010 /// for \p Lane and the number of compatible instructions(with the same
2011 /// parent/opcode). This is used as a heuristic for selecting the first lane
2012 /// to start operand reordering.
2013 OperandsOrderData getMaxNumOperandsThatCanBeReordered(unsigned Lane) const {
2014 unsigned CntTrue = 0;
2015 unsigned NumOperands = getNumOperands();
2016 // Operands with the same APO can be reordered. We therefore need to count
2017 // how many of them we have for each APO, like this: Cnt[APO] = x.
2018 // Since we only have two APOs, namely true and false, we can avoid using
2019 // a map. Instead we can simply count the number of operands that
2020 // correspond to one of them (in this case the 'true' APO), and calculate
2021 // the other by subtracting it from the total number of operands.
2022 // Operands with the same instruction opcode and parent are more
2023 // profitable since we don't need to move them in many cases, with a high
2024 // probability such lane already can be vectorized effectively.
2025 bool AllUndefs = true;
2026 unsigned NumOpsWithSameOpcodeParent = 0;
2027 Instruction *OpcodeI = nullptr;
2028 BasicBlock *Parent = nullptr;
2029 unsigned Hash = 0;
2030 for (unsigned OpIdx = 0; OpIdx != NumOperands; ++OpIdx) {
2031 const OperandData &OpData = getData(OpIdx, Lane);
2032 if (OpData.APO)
2033 ++CntTrue;
2034 // Use Boyer-Moore majority voting for finding the majority opcode and
2035 // the number of times it occurs.
2036 if (auto *I = dyn_cast<Instruction>(OpData.V)) {
2037 if (!OpcodeI || !getSameOpcode({OpcodeI, I}, TLI) ||
2038 I->getParent() != Parent) {
2039 if (NumOpsWithSameOpcodeParent == 0) {
2040 NumOpsWithSameOpcodeParent = 1;
2041 OpcodeI = I;
2042 Parent = I->getParent();
2043 } else {
2044 --NumOpsWithSameOpcodeParent;
2045 }
2046 } else {
2047 ++NumOpsWithSameOpcodeParent;
2048 }
2049 }
2050 Hash = hash_combine(
2051 Hash, hash_value((OpIdx + 1) * (OpData.V->getValueID() + 1)));
2052 AllUndefs = AllUndefs && isa<UndefValue>(OpData.V);
2053 }
2054 if (AllUndefs)
2055 return {};
2056 OperandsOrderData Data;
2057 Data.NumOfAPOs = std::max(CntTrue, NumOperands - CntTrue);
2058 Data.NumOpsWithSameOpcodeParent = NumOpsWithSameOpcodeParent;
2059 Data.Hash = Hash;
2060 return Data;
2061 }
2062
2063 /// Go through the instructions in VL and append their operands.
2064 void appendOperands(ArrayRef<Value *> VL, ArrayRef<ValueList> Operands,
2065 const InstructionsState &S) {
2066 assert(!Operands.empty() && !VL.empty() && "Bad list of operands");
2067 assert((empty() || all_of(Operands,
2068 [this](const ValueList &VL) {
2069 return VL.size() == getNumLanes();
2070 })) &&
2071 "Expected same number of lanes");
2072 assert(S.valid() && "InstructionsState is invalid.");
2073 // IntrinsicInst::isCommutative returns true if swapping the first "two"
2074 // arguments to the intrinsic produces the same result.
2075 Instruction *MainOp = S.getMainOp();
2076 ArgSize = getNumberOfPotentiallyCommutativeOps(MainOp);
2077 OpsVec.resize(ArgSize);
2078 unsigned NumLanes = VL.size();
2079 for (OperandDataVec &Ops : OpsVec)
2080 Ops.resize(NumLanes);
2081 for (unsigned Lane : seq<unsigned>(NumLanes)) {
2082 // Our tree has just 3 nodes: the root and two operands.
2083 // It is therefore trivial to get the APO. We only need to check the
2084 // opcode of V and whether the operand at OpIdx is the LHS or RHS
2085 // operand. The LHS operand of both add and sub is never attached to an
2086 // inversese operation in the linearized form, therefore its APO is
2087 // false. The RHS is true only if V is an inverse operation.
2088
2089 // Since operand reordering is performed on groups of commutative
2090 // operations or alternating sequences (e.g., +, -), we can safely tell
2091 // the inverse operations by checking commutativity.
2092 auto *I = dyn_cast<Instruction>(VL[Lane]);
2093 if (!I && isa<PoisonValue>(VL[Lane])) {
2094 for (unsigned OpIdx : seq<unsigned>(ArgSize))
2095 OpsVec[OpIdx][Lane] = {Operands[OpIdx][Lane], true, false};
2096 continue;
2097 }
2098 bool IsInverseOperation = false;
2099 if (S.isCopyableElement(VL[Lane])) {
2100 // The value is a copyable element.
2101 IsInverseOperation =
2102 !isCommutative(MainOp, VL[Lane], /*IsCopyable=*/true);
2103 } else {
2104 assert(I && "Expected instruction");
2105 auto [SelectedOp, Ops] = convertTo(I, S);
2106 // We cannot check commutativity by the converted instruction
2107 // (SelectedOp) because isCommutative also examines def-use
2108 // relationships.
2109 IsInverseOperation = !isCommutative(SelectedOp, I);
2110 }
2111 for (unsigned OpIdx : seq<unsigned>(ArgSize)) {
2112 bool APO = (OpIdx == 0) ? false : IsInverseOperation;
2113 OpsVec[OpIdx][Lane] = {Operands[OpIdx][Lane], APO, false};
2114 }
2115 }
2116 }
2117
2118 /// \returns the number of operands.
2119 unsigned getNumOperands() const { return ArgSize; }
2120
2121 /// \returns the number of lanes.
2122 unsigned getNumLanes() const { return OpsVec[0].size(); }
2123
2124 /// \returns the operand value at \p OpIdx and \p Lane.
2125 Value *getValue(unsigned OpIdx, unsigned Lane) const {
2126 return getData(OpIdx, Lane).V;
2127 }
2128
2129 /// \returns true if the data structure is empty.
2130 bool empty() const { return OpsVec.empty(); }
2131
2132 /// Clears the data.
2133 void clear() { OpsVec.clear(); }
2134
2135 /// \Returns true if there are enough operands identical to \p Op to fill
2136 /// the whole vector (it is mixed with constants or loop invariant values).
2137 /// Note: This modifies the 'IsUsed' flag, so a cleanUsed() must follow.
2138 bool shouldBroadcast(Value *Op, unsigned OpIdx, unsigned Lane) {
2139 assert(Op == getValue(OpIdx, Lane) &&
2140 "Op is expected to be getValue(OpIdx, Lane).");
2141 // Small number of loads - try load matching.
2142 if (isa<LoadInst>(Op) && getNumLanes() == 2 && getNumOperands() == 2)
2143 return false;
2144 bool OpAPO = getData(OpIdx, Lane).APO;
2145 bool IsInvariant = L && L->isLoopInvariant(Op);
2146 unsigned Cnt = 0;
2147 for (unsigned Ln = 0, Lns = getNumLanes(); Ln != Lns; ++Ln) {
2148 if (Ln == Lane)
2149 continue;
2150 // This is set to true if we found a candidate for broadcast at Lane.
2151 bool FoundCandidate = false;
2152 for (unsigned OpI = 0, OpE = getNumOperands(); OpI != OpE; ++OpI) {
2153 OperandData &Data = getData(OpI, Ln);
2154 if (Data.APO != OpAPO || Data.IsUsed)
2155 continue;
2156 Value *OpILane = getValue(OpI, Lane);
2157 bool IsConstantOp = isa<Constant>(OpILane);
2158 // Consider the broadcast candidate if:
2159 // 1. Same value is found in one of the operands.
2160 if (Data.V == Op ||
2161 // 2. The operand in the given lane is not constant but there is a
2162 // constant operand in another lane (which can be moved to the
2163 // given lane). In this case we can represent it as a simple
2164 // permutation of constant and broadcast.
2165 (!IsConstantOp &&
2166 ((Lns > 2 && isa<Constant>(Data.V)) ||
2167 // 2.1. If we have only 2 lanes, need to check that value in the
2168 // next lane does not build same opcode sequence.
2169 (Lns == 2 &&
2170 !getSameOpcode({Op, getValue((OpI + 1) % OpE, Ln)}, TLI) &&
2171 isa<Constant>(Data.V)))) ||
2172 // 3. The operand in the current lane is loop invariant (can be
2173 // hoisted out) and another operand is also a loop invariant
2174 // (though not a constant). In this case the whole vector can be
2175 // hoisted out.
2176 // FIXME: need to teach the cost model about this case for better
2177 // estimation.
2178 (IsInvariant && !isa<Constant>(Data.V) &&
2179 !getSameOpcode({Op, Data.V}, TLI) &&
2180 L->isLoopInvariant(Data.V))) {
2181 FoundCandidate = true;
2182 Data.IsUsed = Data.V == Op;
2183 if (Data.V == Op)
2184 ++Cnt;
2185 break;
2186 }
2187 }
2188 if (!FoundCandidate)
2189 return false;
2190 }
2191 return getNumLanes() == 2 || Cnt > 1;
2192 }
2193
2194 /// Checks if there is at least single compatible operand in lanes other
2195 /// than \p Lane, compatible with the operand \p Op.
2196 bool canBeVectorized(Instruction *Op, unsigned OpIdx, unsigned Lane) const {
2197 assert(Op == getValue(OpIdx, Lane) &&
2198 "Op is expected to be getValue(OpIdx, Lane).");
2199 bool OpAPO = getData(OpIdx, Lane).APO;
2200 for (unsigned Ln = 0, Lns = getNumLanes(); Ln != Lns; ++Ln) {
2201 if (Ln == Lane)
2202 continue;
2203 if (any_of(seq<unsigned>(getNumOperands()), [&](unsigned OpI) {
2204 const OperandData &Data = getData(OpI, Ln);
2205 if (Data.APO != OpAPO || Data.IsUsed)
2206 return true;
2207 Value *OpILn = getValue(OpI, Ln);
2208 return (L && L->isLoopInvariant(OpILn)) ||
2209 (getSameOpcode({Op, OpILn}, TLI) &&
2210 allSameBlock({Op, OpILn}));
2211 }))
2212 return true;
2213 }
2214 return false;
2215 }
2216
2217 public:
2218 /// Initialize with all the operands of the instruction vector \p RootVL.
2220 const InstructionsState &S, const BoUpSLP &R)
2221 : TLI(*R.TLI), DL(*R.DL), SE(*R.SE), R(R),
2222 L(R.LI->getLoopFor(S.getMainOp()->getParent())) {
2223 // Append all the operands of RootVL.
2224 appendOperands(RootVL, Operands, S);
2225 }
2226
2227 /// Initialize with flattened operand columns of an associative node.
2228 /// ArgSize is taken from \p Operands, APO is always false.
2230 const BoUpSLP &R)
2231 : TLI(*R.TLI), DL(*R.DL), SE(*R.SE), R(R), L(R.LI->getLoopFor(BB)) {
2232 assert(!Operands.empty() && "Expected at least one operand column");
2233 ArgSize = Operands.size();
2234 OpsVec.resize(ArgSize);
2235 unsigned NumLanes = Operands.front().size();
2236 for (auto [OpIdx, Ops] : enumerate(OpsVec)) {
2237 Ops.resize(NumLanes);
2238 for (unsigned Lane : seq<unsigned>(NumLanes))
2239 Ops[Lane] = OperandData(Operands[OpIdx][Lane], /*APO=*/false,
2240 /*IsUsed=*/false);
2241 }
2242 }
2243
2244 /// \Returns a value vector with the operands across all lanes for the
2245 /// opearnd at \p OpIdx.
2246 ValueList getVL(unsigned OpIdx) const {
2247 ValueList OpVL(OpsVec[OpIdx].size());
2248 assert(OpsVec[OpIdx].size() == getNumLanes() &&
2249 "Expected same num of lanes across all operands");
2250 for (unsigned Lane = 0, Lanes = getNumLanes(); Lane != Lanes; ++Lane)
2251 OpVL[Lane] = OpsVec[OpIdx][Lane].V;
2252 return OpVL;
2253 }
2254
2255 // Performs operand reordering for 2 or more operands.
2256 // The original operands are in OrigOps[OpIdx][Lane].
2257 // The reordered operands are returned in 'SortedOps[OpIdx][Lane]'.
2258 void reorder() {
2259 unsigned NumOperands = getNumOperands();
2260 unsigned NumLanes = getNumLanes();
2261 // Each operand has its own mode. We are using this mode to help us select
2262 // the instructions for each lane, so that they match best with the ones
2263 // we have selected so far.
2264 SmallVector<ReorderingMode, 2> ReorderingModes(NumOperands);
2265
2266 // This is a greedy single-pass algorithm. We are going over each lane
2267 // once and deciding on the best order right away with no back-tracking.
2268 // However, in order to increase its effectiveness, we start with the lane
2269 // that has operands that can move the least. For example, given the
2270 // following lanes:
2271 // Lane 0 : A[0] = B[0] + C[0] // Visited 3rd
2272 // Lane 1 : A[1] = C[1] - B[1] // Visited 1st
2273 // Lane 2 : A[2] = B[2] + C[2] // Visited 2nd
2274 // Lane 3 : A[3] = C[3] - B[3] // Visited 4th
2275 // we will start at Lane 1, since the operands of the subtraction cannot
2276 // be reordered. Then we will visit the rest of the lanes in a circular
2277 // fashion. That is, Lanes 2, then Lane 0, and finally Lane 3.
2278
2279 // Find the first lane that we will start our search from.
2280 unsigned FirstLane = getBestLaneToStartReordering();
2281
2282 // Initialize the modes.
2283 for (unsigned OpIdx = 0; OpIdx != NumOperands; ++OpIdx) {
2284 Value *OpLane0 = getValue(OpIdx, FirstLane);
2285 // Keep track if we have instructions with all the same opcode on one
2286 // side.
2287 if (auto *OpILane0 = dyn_cast<Instruction>(OpLane0)) {
2288 // Check if OpLane0 should be broadcast.
2289 if (shouldBroadcast(OpLane0, OpIdx, FirstLane) ||
2290 !canBeVectorized(OpILane0, OpIdx, FirstLane))
2291 ReorderingModes[OpIdx] = ReorderingMode::Splat;
2292 else if (isa<LoadInst>(OpILane0))
2293 ReorderingModes[OpIdx] = ReorderingMode::Load;
2294 else
2295 ReorderingModes[OpIdx] = ReorderingMode::Opcode;
2296 } else if (isa<Constant>(OpLane0)) {
2297 ReorderingModes[OpIdx] = ReorderingMode::Constant;
2298 } else if (isa<Argument>(OpLane0)) {
2299 // Our best hope is a Splat. It may save some cost in some cases.
2300 ReorderingModes[OpIdx] = ReorderingMode::Splat;
2301 } else {
2302 llvm_unreachable("Unexpected value kind.");
2303 }
2304 }
2305
2306 // Check that we don't have same operands. No need to reorder if operands
2307 // are just perfect diamond or shuffled diamond match. Do not do it only
2308 // for possible broadcasts.
2309 auto &&SkipReordering = [this]() {
2310 SmallPtrSet<Value *, 4> UniqueValues;
2311 ArrayRef<OperandData> Op0 = OpsVec.front();
2312 for (const OperandData &Data : Op0)
2313 UniqueValues.insert(Data.V);
2315 ArrayRef(OpsVec).slice(1, getNumOperands() - 1)) {
2316 if (any_of(Op, [&UniqueValues](const OperandData &Data) {
2317 return !UniqueValues.contains(Data.V);
2318 }))
2319 return false;
2320 }
2321 return UniqueValues.size() != 2;
2322 };
2323
2324 // If the initial strategy fails for any of the operand indexes, then we
2325 // perform reordering again in a second pass. This helps avoid assigning
2326 // high priority to the failed strategy, and should improve reordering for
2327 // the non-failed operand indexes.
2328 for (int Pass = 0; Pass != 2; ++Pass) {
2329 // Check if no need to reorder operands since they're are perfect or
2330 // shuffled diamond match.
2331 // Need to do it to avoid extra external use cost counting for
2332 // shuffled matches, which may cause regressions.
2333 if (SkipReordering())
2334 break;
2335 // Skip the second pass if the first pass did not fail.
2336 bool StrategyFailed = false;
2337 // Mark all operand data as free to use.
2338 clearUsed();
2339 // We keep the original operand order for the FirstLane, so reorder the
2340 // rest of the lanes. We are visiting the nodes in a circular fashion,
2341 // using FirstLane as the center point and increasing the radius
2342 // distance.
2343 SmallVector<SmallVector<Value *, 2>> MainAltOps(NumOperands);
2344 for (unsigned I = 0; I < NumOperands; ++I)
2345 MainAltOps[I].push_back(getData(I, FirstLane).V);
2346
2347 SmallBitVector UsedLanes(NumLanes);
2348 UsedLanes.set(FirstLane);
2349 for (unsigned Distance = 1; Distance != NumLanes; ++Distance) {
2350 // Visit the lane on the right and then the lane on the left.
2351 for (int Direction : {+1, -1}) {
2352 int Lane = FirstLane + Direction * Distance;
2353 if (Lane < 0 || Lane >= (int)NumLanes)
2354 continue;
2355 UsedLanes.set(Lane);
2356 int LastLane = Lane - Direction;
2357 assert(LastLane >= 0 && LastLane < (int)NumLanes &&
2358 "Out of bounds");
2359 // Look for a good match for each operand.
2360 for (unsigned OpIdx = 0; OpIdx != NumOperands; ++OpIdx) {
2361 // Search for the operand that matches SortedOps[OpIdx][Lane-1].
2362 std::optional<unsigned> BestIdx =
2363 getBestOperand(OpIdx, Lane, LastLane, ReorderingModes,
2364 MainAltOps[OpIdx], UsedLanes);
2365 // By not selecting a value, we allow the operands that follow to
2366 // select a better matching value. We will get a non-null value in
2367 // the next run of getBestOperand().
2368 if (BestIdx) {
2369 // Swap the current operand with the one returned by
2370 // getBestOperand().
2371 swap(OpIdx, *BestIdx, Lane);
2372 } else {
2373 // Enable the second pass.
2374 StrategyFailed = true;
2375 }
2376 // Try to get the alternate opcode and follow it during analysis.
2377 if (MainAltOps[OpIdx].size() != 2) {
2378 OperandData &AltOp = getData(OpIdx, Lane);
2379 InstructionsState OpS =
2380 getSameOpcode({MainAltOps[OpIdx].front(), AltOp.V}, TLI);
2381 if (OpS && OpS.isAltShuffle())
2382 MainAltOps[OpIdx].push_back(AltOp.V);
2383 }
2384 }
2385 }
2386 }
2387 // Skip second pass if the strategy did not fail.
2388 if (!StrategyFailed)
2389 break;
2390 }
2391 }
2392
2393#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
2394 LLVM_DUMP_METHOD static StringRef getModeStr(ReorderingMode RMode) {
2395 switch (RMode) {
2396 case ReorderingMode::Load:
2397 return "Load";
2398 case ReorderingMode::Opcode:
2399 return "Opcode";
2400 case ReorderingMode::Constant:
2401 return "Constant";
2402 case ReorderingMode::Splat:
2403 return "Splat";
2404 case ReorderingMode::Failed:
2405 return "Failed";
2406 }
2407 llvm_unreachable("Unimplemented Reordering Type");
2408 }
2409
2410 LLVM_DUMP_METHOD static raw_ostream &printMode(ReorderingMode RMode,
2411 raw_ostream &OS) {
2412 return OS << getModeStr(RMode);
2413 }
2414
2415 /// Debug print.
2416 LLVM_DUMP_METHOD static void dumpMode(ReorderingMode RMode) {
2417 printMode(RMode, dbgs());
2418 }
2419
2420 friend raw_ostream &operator<<(raw_ostream &OS, ReorderingMode RMode) {
2421 return printMode(RMode, OS);
2422 }
2423
2425 const unsigned Indent = 2;
2426 unsigned Cnt = 0;
2427 for (const OperandDataVec &OpDataVec : OpsVec) {
2428 OS << "Operand " << Cnt++ << "\n";
2429 for (const OperandData &OpData : OpDataVec) {
2430 OS.indent(Indent) << "{";
2431 if (Value *V = OpData.V)
2432 OS << *V;
2433 else
2434 OS << "null";
2435 OS << ", APO:" << OpData.APO << "}\n";
2436 }
2437 OS << "\n";
2438 }
2439 return OS;
2440 }
2441
2442 /// Debug print.
2443 LLVM_DUMP_METHOD void dump() const { print(dbgs()); }
2444#endif
2445 };
2446
2447 /// Evaluate each pair in \p Candidates and return index into \p Candidates
2448 /// for a pair which have highest score deemed to have best chance to form
2449 /// root of profitable tree to vectorize. Return std::nullopt if no candidate
2450 /// scored above the LookAheadHeuristics::ScoreFail. \param Limit Lower limit
2451 /// of the cost, considered to be good enough score.
2452 std::pair<std::optional<int>, int>
2453 findBestRootPair(ArrayRef<std::pair<Value *, Value *>> Candidates,
2454 int Limit = LookAheadHeuristics::ScoreFail) const {
2455 LookAheadHeuristics LookAhead(*TLI, *DL, *SE, *this, /*NumLanes=*/2,
2457 int BestScore = Limit;
2458 std::optional<int> Index;
2459 for (int I : seq<int>(0, Candidates.size())) {
2460 int Score = LookAhead.getScoreAtLevelRec(Candidates[I].first,
2461 Candidates[I].second,
2462 /*U1=*/nullptr, /*U2=*/nullptr,
2463 /*CurrLevel=*/1, {});
2464 if (Score > BestScore) {
2465 BestScore = Score;
2466 Index = I;
2467 }
2468 }
2469 return std::make_pair(Index, BestScore);
2470 }
2471
2472 /// Checks if the instruction is marked for deletion.
2473 bool isDeleted(Instruction *I) const { return DeletedInstructions.count(I); }
2474
2475 /// Checks if the value is used only by the assume-like intrinsics.
2476 bool isEphemeralValue(const Value *V) const { return EphValues.contains(V); }
2477
2478 /// Removes an instruction from its block and eventually deletes it.
2479 /// It's like Instruction::eraseFromParent() except that the actual deletion
2480 /// is delayed until BoUpSLP is destructed.
2482 DeletedInstructions.insert(I);
2483 }
2484
2485 /// Remove instructions from the parent function and clear the operands of \p
2486 /// DeadVals instructions, marking for deletion trivially dead operands.
2487 template <typename T>
2489 ArrayRef<T *> DeadVals,
2490 ArrayRef<std::tuple<WeakTrackingVH, unsigned, bool, bool>>
2491 VectorValuesAndScales) {
2493 for (T *V : DeadVals) {
2494 auto *I = cast<Instruction>(V);
2496 }
2497 DenseSet<Value *> Processed;
2498 for (T *V : DeadVals) {
2499 if (!V || !Processed.insert(V).second)
2500 continue;
2501 auto *I = cast<Instruction>(V);
2503 ArrayRef<TreeEntry *> Entries = getTreeEntries(I);
2504 for (Use &U : I->operands()) {
2505 if (auto *OpI = dyn_cast_if_present<Instruction>(U.get());
2506 OpI && !DeletedInstructions.contains(OpI) && OpI->hasOneUser() &&
2508 !ExternalUseReplacements.contains(OpI) &&
2509 (Entries.empty() || none_of(Entries, [&](const TreeEntry *Entry) {
2510 return Entry->VectorizedValue == OpI;
2511 })))
2512 DeadInsts.push_back(OpI);
2513 }
2514 I->dropAllReferences();
2515 }
2516 for (T *V : DeadVals) {
2517 auto *I = cast<Instruction>(V);
2518 if (!I->getParent())
2519 continue;
2520 assert((I->use_empty() || all_of(I->uses(),
2521 [&](Use &U) {
2522 return isDeleted(
2523 cast<Instruction>(U.getUser()));
2524 })) &&
2525 "trying to erase instruction with users.");
2526 I->removeFromParent();
2527 SE->forgetValue(I);
2528 }
2529 // Process the dead instruction list until empty.
2530 while (!DeadInsts.empty()) {
2531 Value *V = DeadInsts.pop_back_val();
2533 if (!VI || !VI->getParent())
2534 continue;
2536 "Live instruction found in dead worklist!");
2537 assert(VI->use_empty() && "Instructions with uses are not dead.");
2538
2539 // Don't lose the debug info while deleting the instructions.
2540 salvageDebugInfo(*VI);
2541
2542 // Null out all of the instruction's operands to see if any operand
2543 // becomes dead as we go.
2544 for (Use &OpU : VI->operands()) {
2545 Value *OpV = OpU.get();
2546 if (!OpV)
2547 continue;
2548 OpU.set(nullptr);
2549
2550 if (!OpV->use_empty())
2551 continue;
2552
2553 // If the operand is an instruction that became dead as we nulled out
2554 // the operand, and if it is 'trivially' dead, delete it in a future
2555 // loop iteration.
2556 if (auto *OpI = dyn_cast<Instruction>(OpV))
2557 if (!DeletedInstructions.contains(OpI) &&
2558 !ExternalUseReplacements.contains(OpI) &&
2559 (!OpI->getType()->isVectorTy() ||
2560 none_of(
2561 VectorValuesAndScales,
2562 [&](const std::tuple<WeakTrackingVH, unsigned, bool, bool>
2563 &V) { return std::get<0>(V) == OpI; })) &&
2565 DeadInsts.push_back(OpI);
2566 }
2567
2568 VI->removeFromParent();
2569 eraseInstruction(VI);
2570 SE->forgetValue(VI);
2571 }
2572 }
2573
2574 /// Checks if the instruction was already analyzed for being possible
2575 /// reduction root.
2577 return AnalyzedReductionsRoots.count(I);
2578 }
2579 /// Register given instruction as already analyzed for being possible
2580 /// reduction root.
2582 AnalyzedReductionsRoots.insert(I);
2583 }
2584 /// Checks if the provided list of reduced values was checked already for
2585 /// vectorization.
2587 return AnalyzedReductionVals.contains(hash_value(VL));
2588 }
2589 /// Adds the list of reduced values to list of already checked values for the
2590 /// vectorization.
2592 AnalyzedReductionVals.insert(hash_value(VL));
2593 }
2594 /// Checks if the value was already a part of the analyzed vector node.
2595 bool isAnalyzedScalar(const Value *V) const {
2596 return AnalyzedScalars.contains(V);
2597 }
2598 /// Checks if the given bundle was already rejected as non-vectorizable.
2600 return AnalyzedBundles.contains(hash_value(VL));
2601 }
2602 /// Registers the bundle as rejected for the vectorization.
2604 AnalyzedBundles.insert(hash_value(VL));
2605 }
2606 /// Clear the list of the analyzed reduction root instructions.
2608 AnalyzedReductionsRoots.clear();
2609 AnalyzedReductionVals.clear();
2610 AnalyzedBundles.clear();
2611 AnalyzedMinBWVals.clear();
2612 }
2613 /// Checks if the given value is gathered in one of the nodes.
2614 bool isAnyGathered(const SmallDenseSet<Value *> &Vals) const {
2615 return any_of(MustGather, [&](Value *V) { return Vals.contains(V); });
2616 }
2617 /// Checks if the given value is gathered in one of the nodes.
2618 bool isGathered(const Value *V) const {
2619 return MustGather.contains(V);
2620 }
2621 /// Checks if the specified value was not schedule.
2622 bool isNotScheduled(const Value *V) const {
2623 return NonScheduledFirst.contains(V);
2624 }
2625
2626 /// Check if \p V is a peeled reassociated scalar still owned by a live
2627 /// (non-deleted, non-gathered) tree entry.
2628 bool isReassocScalarVectorized(const Value *V) const {
2629 auto It = ReassocScalarToTreeEntries.find(V);
2630 return It != ReassocScalarToTreeEntries.end() &&
2631 any_of(It->second, [&](const TreeEntry *E) {
2632 return !DeletedNodes.contains(E) &&
2633 !TransformedToGatherNodes.contains(E);
2634 });
2635 }
2636
2637 /// Check if the value is vectorized in the tree.
2638 bool isVectorized(const Value *V) const {
2639 assert(V && "V cannot be nullptr.");
2641 return true;
2642 return any_of(getTreeEntries(V), [&](const TreeEntry *E) {
2643 return !DeletedNodes.contains(E) && !TransformedToGatherNodes.contains(E);
2644 });
2645 }
2646
2647 /// Returns true if the role of \p I is already decided by its user: a deleted
2648 /// user was folded into some other vector by an earlier attempt.
2650 return any_of(I->users(), [&](User *U) {
2651 auto *UI = dyn_cast<Instruction>(U);
2652 return UI && isDeleted(UI);
2653 });
2654 }
2655
2656 /// Checks if it is legal and profitable to build SplitVectorize node for the
2657 /// given \p VL.
2658 /// \param Op1 first homogeneous scalars.
2659 /// \param Op2 second homogeneous scalars.
2660 /// \param ReorderIndices indices to reorder the scalars.
2661 /// \returns true if the node was successfully built.
2663 const InstructionsState &LocalState,
2666 OrdersType &ReorderIndices) const;
2667
2668 ~BoUpSLP();
2669
2670private:
2671 /// Determine if a node \p E in can be demoted to a smaller type with a
2672 /// truncation. We collect the entries that will be demoted in ToDemote.
2673 /// \param E Node for analysis
2674 /// \param ToDemote indices of the nodes to be demoted.
2675 bool collectValuesToDemote(
2676 const TreeEntry &E, bool IsProfitableToDemoteRoot, unsigned &BitWidth,
2678 const SmallDenseSet<unsigned, 8> &NodesToKeepBWs, unsigned &MaxDepthLevel,
2679 bool &IsProfitableToDemote, bool IsTruncRoot) const;
2680
2681 /// Builds the list of reorderable operands on the edges \p Edges of the \p
2682 /// UserTE, which allow reordering (i.e. the operands can be reordered because
2683 /// they have only one user and reordarable).
2684 /// \param ReorderableGathers List of all gather nodes that require reordering
2685 /// (e.g., gather of extractlements or partially vectorizable loads).
2686 /// \param GatherOps List of gather operand nodes for \p UserTE that require
2687 /// reordering, subset of \p NonVectorized.
2688 void buildReorderableOperands(
2689 TreeEntry *UserTE,
2690 SmallVectorImpl<std::pair<unsigned, TreeEntry *>> &Edges,
2691 const SmallPtrSetImpl<const TreeEntry *> &ReorderableGathers,
2692 SmallVectorImpl<TreeEntry *> &GatherOps);
2693
2694 /// Checks if the given \p TE is a gather node with clustered reused scalars
2695 /// and reorders it per given \p Mask.
2696 void reorderNodeWithReuses(TreeEntry &TE, ArrayRef<int> Mask) const;
2697
2698 /// Checks if all users of \p I are the part of the vectorization tree.
2699 bool areAllUsersVectorized(
2700 Instruction *I,
2701 const SmallDenseSet<Value *> *VectorizedVals = nullptr) const;
2702
2703 /// Estimates the number of scalar instructions in the tree, each weighted by
2704 /// its loop-nest trip count (nest-invariant entries are dropped when
2705 /// \p TreeLoop is non-null).
2706 uint64_t getNumScalarInsts(bool HasTreeLoop);
2707
2708 /// Estimates the number of vector instructions (including buildvectors,
2709 /// shuffles, and extracts) the tree produces, weighted like
2710 /// getNumScalarInsts().
2711 uint64_t getNumVectorInsts(bool HasTreeLoop);
2712
2713 /// Return information about the vector formed for the specified index
2714 /// of a vector of (the same) instruction.
2717
2718 /// \returns the graph entry for the \p Idx operand of the \p E entry.
2719 const TreeEntry *getOperandEntry(const TreeEntry *E, unsigned Idx) const;
2720 TreeEntry *getOperandEntry(TreeEntry *E, unsigned Idx) {
2721 return const_cast<TreeEntry *>(
2722 getOperandEntry(const_cast<const TreeEntry *>(E), Idx));
2723 }
2724
2725 /// Gets the root instruction for the given node. If the node is a strided
2726 /// load/store node with the reverse order, the root instruction is the last
2727 /// one.
2728 Instruction *getRootEntryInstruction(const TreeEntry &Entry) const;
2729
2730 /// \returns Cast context for the given graph node.
2732 getCastContextHint(const TreeEntry &TE) const;
2733
2734 /// \returns the scale of the given tree entry to the loop iteration.
2735 /// \p Scalar is the scalar value from the entry, if using the parent for the
2736 /// external use.
2737 /// \p U is the user of the vectorized value from the entry, if using the
2738 /// parent for the external use.
2739 uint64_t getScaleToLoopIterations(const TreeEntry &TE,
2740 Value *Scalar = nullptr,
2741 Instruction *U = nullptr);
2742
2743 /// \returns the product of trip counts of the loop \p L and all of its
2744 /// enclosing loops. Unlike the state kept by getScaleToLoopIterations(),
2745 /// this helper depends only on the loop structure and is independent of
2746 /// per-entry operand invariance. Returns 1 when loop-aware cost modeling
2747 /// is disabled or \p L is null.
2748 uint64_t getLoopNestScale(const Loop *L);
2749
2750 /// \returns a refined execution scale for a gather/buildvector tree entry
2751 /// \p TE. The scale is computed as the average of per-lane execution
2752 /// scales: each lane's scale is the loop-nest scale of the loop that
2753 /// contains the lane's defining instruction (or 1 if the lane is a
2754 /// constant / loop-invariant non-instruction value). This models the
2755 /// LICM hoisting that optimizeGatherSequence() performs after vectorization
2756 /// for inserts with loop-invariant operands. Falls back to the whole-entry
2757 /// scale when per-lane information is unavailable or the feature is off.
2758 uint64_t getGatherNodeEffectiveScale(const TreeEntry &TE,
2759 Instruction *U = nullptr);
2760
2761 /// \returns the loop-nest execution scale of \p TE.
2762 uint64_t getEntryEffectiveScale(const TreeEntry &TE,
2763 Instruction *U = nullptr);
2764
2765 /// Get the loop nest for the given loop \p L.
2766 ArrayRef<const Loop *> getLoopNest(const Loop *L);
2767
2768 /// \returns the cost of the vectorizable entry.
2769 InstructionCost getEntryCost(const TreeEntry *E,
2770 ArrayRef<Value *> VectorizedVals,
2771 SmallPtrSetImpl<Value *> &CheckedExtracts);
2772
2773 /// Estimates spill/reload cost from vector register pressure for \p E at the
2774 /// point of emitting its vector result type \p FinalVecTy. \p ScalarTy is the
2775 /// scalar/slot type used to widen into \p VecTy/\p FinalVecTy and may itself
2776 /// be a FixedVectorType in ReVec mode or an adjusted type due to MinBWs.
2778 getVectorSpillReloadCost(const TreeEntry *E, Type *ScalarTy, Type *VecTy,
2779 Type *FinalVecTy,
2780 const TTI::TargetCostKind CostKind) const;
2781
2782 /// This is the recursive part of buildTree.
2783 void buildTreeRec(ArrayRef<Value *> Roots, unsigned Depth, const EdgeInfo &EI,
2784 unsigned InterleaveFactor = 0);
2785
2786 /// \returns true if the ExtractElement/ExtractValue instructions in \p VL can
2787 /// be vectorized to use the original vector (or aggregate "bitcast" to a
2788 /// vector) and sets \p CurrentOrder to the identity permutation; otherwise
2789 /// returns false, setting \p CurrentOrder to either an empty vector or a
2790 /// non-identity permutation that allows to reuse extract instructions.
2791 /// \param ResizeAllowed indicates whether it is allowed to handle subvector
2792 /// extract order.
2793 bool canReuseExtract(ArrayRef<Value *> VL,
2794 SmallVectorImpl<unsigned> &CurrentOrder,
2795 bool ResizeAllowed = false) const;
2796
2797 /// Vectorize a single entry in the tree.
2798 Value *vectorizeTree(TreeEntry *E);
2799
2800 /// Vectorize a single entry in the tree, the \p Idx-th operand of the entry
2801 /// \p E.
2802 Value *vectorizeOperand(TreeEntry *E, unsigned NodeIdx);
2803
2804 /// Create a new vector from a list of scalar values. Produces a sequence
2805 /// which exploits values reused across lanes, and arranges the inserts
2806 /// for ease of later optimization.
2807 template <typename BVTy, typename ResTy, typename... Args>
2808 ResTy processBuildVector(const TreeEntry *E, Type *ScalarTy, Args &...Params);
2809
2810 /// Create a new vector from a list of scalar values. Produces a sequence
2811 /// which exploits values reused across lanes, and arranges the inserts
2812 /// for ease of later optimization.
2813 Value *createBuildVector(const TreeEntry *E, Type *ScalarTy);
2814
2815 /// Returns the instruction in the bundle, which can be used as a base point
2816 /// for scheduling. Usually it is the last instruction in the bundle, except
2817 /// for the case when all operands are external (in this case, it is the first
2818 /// instruction in the list).
2819 Instruction &getLastInstructionInBundle(const TreeEntry *E);
2820
2821 /// Tries to find extractelement instructions with constant indices from fixed
2822 /// vector type and gather such instructions into a bunch, which highly likely
2823 /// might be detected as a shuffle of 1 or 2 input vectors. If this attempt
2824 /// was successful, the matched scalars are replaced by poison values in \p VL
2825 /// for future analysis.
2826 std::optional<TargetTransformInfo::ShuffleKind>
2827 tryToGatherSingleRegisterExtractElements(MutableArrayRef<Value *> VL,
2828 SmallVectorImpl<int> &Mask) const;
2829
2830 /// Tries to find extractelement instructions with constant indices from fixed
2831 /// vector type and gather such instructions into a bunch, which highly likely
2832 /// might be detected as a shuffle of 1 or 2 input vectors. If this attempt
2833 /// was successful, the matched scalars are replaced by poison values in \p VL
2834 /// for future analysis.
2836 tryToGatherExtractElements(SmallVectorImpl<Value *> &VL,
2838 unsigned NumParts) const;
2839
2840 /// Checks if the gathered \p VL can be represented as a single register
2841 /// shuffle(s) of previous tree entries.
2842 /// \param TE Tree entry checked for permutation.
2843 /// \param VL List of scalars (a subset of the TE scalar), checked for
2844 /// permutations. Must form single-register vector.
2845 /// \param ForOrder Tries to fetch the best candidates for ordering info. Also
2846 /// commands to build the mask using the original vector value, without
2847 /// relying on the potential reordering.
2848 /// \returns ShuffleKind, if gathered values can be represented as shuffles of
2849 /// previous tree entries. \p Part of \p Mask is filled with the shuffle mask.
2850 std::optional<TargetTransformInfo::ShuffleKind>
2851 isGatherShuffledSingleRegisterEntry(
2852 const TreeEntry *TE, ArrayRef<Value *> VL, MutableArrayRef<int> Mask,
2853 SmallVectorImpl<const TreeEntry *> &Entries, unsigned Part, bool ForOrder,
2854 unsigned SliceSize);
2855
2856 /// Checks if the gathered \p VL can be represented as multi-register
2857 /// shuffle(s) of previous tree entries.
2858 /// \param TE Tree entry checked for permutation.
2859 /// \param VL List of scalars (a subset of the TE scalar), checked for
2860 /// permutations.
2861 /// \param ForOrder Tries to fetch the best candidates for ordering info. Also
2862 /// commands to build the mask using the original vector value, without
2863 /// relying on the potential reordering.
2864 /// \returns per-register series of ShuffleKind, if gathered values can be
2865 /// represented as shuffles of previous tree entries. \p Mask is filled with
2866 /// the shuffle mask (also on per-register base).
2868 isGatherShuffledEntry(
2869 const TreeEntry *TE, ArrayRef<Value *> VL, SmallVectorImpl<int> &Mask,
2871 unsigned NumParts, bool ForOrder = false);
2872
2873 /// \returns the cost of gathering (inserting) the values in \p VL into a
2874 /// vector.
2875 /// \param ForPoisonSrc true if initial vector is poison, false otherwise.
2876 InstructionCost getGatherCost(ArrayRef<Value *> VL, bool ForPoisonSrc,
2877 Type *ScalarTy) const;
2878
2879 /// Set the Builder insert point to one after the last instruction in
2880 /// the bundle
2881 void setInsertPointAfterBundle(const TreeEntry *E);
2882
2883 /// \returns a vector from a collection of scalars in \p VL. if \p Root is not
2884 /// specified, the starting vector value is poison.
2885 Value *
2886 gather(ArrayRef<Value *> VL, Value *Root, Type *ScalarTy,
2887 function_ref<Value *(Value *, Value *, ArrayRef<int>)> CreateShuffle);
2888
2889 /// \returns whether the VectorizableTree is fully vectorizable and will
2890 /// be beneficial even the tree height is tiny.
2891 bool isFullyVectorizableTinyTree(bool ForReduction) const;
2892
2893 /// Run through the list of all gathered loads in the graph and try to find
2894 /// vector loads/masked gathers instead of regular gathers. Later these loads
2895 /// are reshufled to build final gathered nodes.
2896 void tryToVectorizeGatheredLoads(
2897 const SmallMapVector<
2898 std::tuple<BasicBlock *, Value *, Type *>,
2899 SmallVector<SmallVector<std::pair<LoadInst *, int64_t>>>, 8>
2900 &GatheredLoads);
2901
2902 /// Helper for `findExternalStoreUsersReorderIndices()`. It iterates over the
2903 /// users of \p TE and collects the stores. It returns the map from the store
2904 /// pointers to the collected stores.
2906 collectUserStores(const BoUpSLP::TreeEntry *TE) const;
2907
2908 /// Helper for `findExternalStoreUsersReorderIndices()`. It checks if the
2909 /// stores in \p StoresVec can form a vector instruction. If so it returns
2910 /// true and populates \p ReorderIndices with the shuffle indices of the
2911 /// stores when compared to the sorted vector.
2912 bool canFormVector(ArrayRef<StoreInst *> StoresVec,
2913 OrdersType &ReorderIndices) const;
2914
2915 /// Iterates through the users of \p TE, looking for scalar stores that can be
2916 /// potentially vectorized in a future SLP-tree. If found, it keeps track of
2917 /// their order and builds an order index vector for each store bundle. It
2918 /// returns all these order vectors found.
2919 /// We run this after the tree has formed, otherwise we may come across user
2920 /// instructions that are not yet in the tree.
2922 findExternalStoreUsersReorderIndices(TreeEntry *TE) const;
2923
2924 /// Tries to reorder the gathering node for better vectorization
2925 /// opportunities.
2926 void reorderGatherNode(TreeEntry &TE);
2927
2928 /// Checks if the tree represents disjoint or reduction of shl(zext, (0, 8,
2929 /// .., 56))-like pattern.
2930 /// If the int shifts unique, also strided, but not ordered, sets \p Order.
2931 /// If the node can be represented as a bitcast + bswap, sets \p IsBSwap.
2932 /// If the root nodes are loads, sets \p ForLoads to true.
2933 bool matchesShlZExt(const TreeEntry &TE, OrdersType &Order, bool &IsBSwap,
2934 bool &ForLoads) const;
2935
2936 /// Checks if the \p SelectTE matches zext+selects, which can be inversed for
2937 /// better codegen in case like zext (icmp ne), select (icmp eq), ....
2938 bool matchesInversedZExtSelect(
2939 const TreeEntry &SelectTE,
2940 SmallVectorImpl<unsigned> &InversedCmpsIndices) const;
2941
2942 /// Checks if the tree is reduction or of bit selects, like select %cmp, <1,
2943 /// 2, 4, 8, ..>, zeroinitializer, which can be reduced just to a bitcast %cmp
2944 /// to in.
2945 bool matchesSelectOfBits(const TreeEntry &SelectTE) const;
2946
2947 class TreeEntry {
2948 public:
2949 using VecTreeTy = SmallVector<std::unique_ptr<TreeEntry>, 8>;
2950 TreeEntry(VecTreeTy &Container) : Container(Container) {}
2951
2952 /// \returns Common mask for reorder indices and reused scalars.
2953 SmallVector<int> getCommonMask() const {
2954 if (State == TreeEntry::SplitVectorize)
2955 return {};
2956 SmallVector<int> Mask;
2957 inversePermutation(ReorderIndices, Mask);
2958 addMask(Mask, ReuseShuffleIndices);
2959 return Mask;
2960 }
2961
2962 /// \returns The mask for split nodes.
2963 SmallVector<int> getSplitMask() const {
2964 assert(State == TreeEntry::SplitVectorize && !ReorderIndices.empty() &&
2965 "Expected only split vectorize node.");
2966 unsigned CommonVF = std::max<unsigned>(
2967 CombinedEntriesWithIndices.back().second,
2968 Scalars.size() - CombinedEntriesWithIndices.back().second);
2969 const unsigned Scale = getNumElements(Scalars.front()->getType());
2970 CommonVF *= Scale;
2971 SmallVector<int> Mask(getVectorFactor() * Scale, PoisonMaskElem);
2972 for (auto [Idx, I] : enumerate(ReorderIndices)) {
2973 for (unsigned K : seq<unsigned>(Scale)) {
2974 Mask[Scale * I + K] =
2975 Scale * Idx + K +
2976 (Idx >= CombinedEntriesWithIndices.back().second
2977 ? CommonVF - CombinedEntriesWithIndices.back().second * Scale
2978 : 0);
2979 }
2980 }
2981 return Mask;
2982 }
2983
2984 /// Updates (reorders) SplitVectorize node according to the given mask \p
2985 /// Mask and order \p MaskOrder.
2986 void reorderSplitNode(unsigned Idx, ArrayRef<int> Mask,
2987 ArrayRef<int> MaskOrder);
2988
2989 /// \returns true if the scalars in VL are equal to this entry.
2990 bool isSame(ArrayRef<Value *> VL) const {
2991 auto &&IsSame = [VL](ArrayRef<Value *> Scalars, ArrayRef<int> Mask) {
2992 if (Mask.size() != VL.size() && VL.size() == Scalars.size())
2993 return std::equal(VL.begin(), VL.end(), Scalars.begin());
2994 return VL.size() == Mask.size() &&
2995 std::equal(VL.begin(), VL.end(), Mask.begin(),
2996 [Scalars](Value *V, int Idx) {
2997 return isa<PoisonValue>(V) ||
2998 (Idx != PoisonMaskElem && V == Scalars[Idx]);
2999 });
3000 };
3001 if (!ReorderIndices.empty()) {
3002 // TODO: implement matching if the nodes are just reordered, still can
3003 // treat the vector as the same if the list of scalars matches VL
3004 // directly, without reordering.
3005 SmallVector<int> Mask;
3006 inversePermutation(ReorderIndices, Mask);
3007 if (VL.size() == Scalars.size())
3008 return IsSame(Scalars, Mask);
3009 if (VL.size() == ReuseShuffleIndices.size()) {
3010 addMask(Mask, ReuseShuffleIndices);
3011 return IsSame(Scalars, Mask);
3012 }
3013 return false;
3014 }
3015 return IsSame(Scalars, ReuseShuffleIndices);
3016 }
3017
3018 /// \returns true if current entry has same operands as \p TE.
3019 bool hasEqualOperands(const TreeEntry &TE) const {
3020 if (TE.getNumOperands() != getNumOperands())
3021 return false;
3022 SmallBitVector Used(getNumOperands());
3023 for (unsigned I = 0, E = getNumOperands(); I < E; ++I) {
3024 unsigned PrevCount = Used.count();
3025 for (unsigned K = 0; K < E; ++K) {
3026 if (Used.test(K))
3027 continue;
3028 if (getOperand(K) == TE.getOperand(I)) {
3029 Used.set(K);
3030 break;
3031 }
3032 }
3033 // Check if we actually found the matching operand.
3034 if (PrevCount == Used.count())
3035 return false;
3036 }
3037 return true;
3038 }
3039
3040 /// \return Final vectorization factor for the node. Defined by the total
3041 /// number of vectorized scalars, including those, used several times in the
3042 /// entry and counted in the \a ReuseShuffleIndices, if any.
3043 unsigned getVectorFactor() const {
3044 if (!ReuseShuffleIndices.empty())
3045 return ReuseShuffleIndices.size();
3046 return Scalars.size();
3047 };
3048
3049 /// Checks if the current node is a gather node.
3050 bool isGather() const { return State == NeedToGather; }
3051
3052 /// A vector of scalars.
3053 ValueList Scalars;
3054
3055 /// The Scalars are vectorized into this value. It is initialized to Null.
3056 WeakTrackingVH VectorizedValue = nullptr;
3057
3058 /// Do we need to gather this sequence or vectorize it
3059 /// (either with vector instruction or with scatter/gather
3060 /// intrinsics for store/load)?
3061 enum EntryState {
3062 Vectorize, ///< The node is regularly vectorized.
3063 ScatterVectorize, ///< Masked scatter/gather node.
3064 StridedVectorize, ///< Strided loads (and stores)
3065 ExpandVectorize, ///< Masked stores, the values are expanded into
3066 ///< a wider vector and vectorized with a mask.
3067 CompressVectorize, ///< (Masked) load with compress.
3068 BlendedLoadVectorize, ///< (Masked) loads blended via `select` from two
3069 ///< candidate base pointers.
3070 NeedToGather, ///< Gather/buildvector node.
3071 CombinedVectorize, ///< Vectorized node, combined with its user into more
3072 ///< complex node like select/cmp to minmax, mul/add to
3073 ///< fma, etc. Must be used for the following nodes in
3074 ///< the pattern, not the very first one.
3075 SplitVectorize, ///< Splits the node into 2 subnodes, vectorizes them
3076 ///< independently and then combines back.
3077 };
3078 EntryState State;
3079
3080 /// List of combined opcodes supported by the vectorizer.
3081 enum CombinedOpcode {
3082 NotCombinedOp = -1,
3083 MinMax = Instruction::OtherOpsEnd + 1,
3084 FMulAdd,
3085 ReducedBitcast,
3086 ReducedBitcastBSwap,
3087 ReducedBitcastLoads,
3088 ReducedBitcastBSwapLoads,
3089 ReducedCmpBitcast,
3090 };
3091 CombinedOpcode CombinedOp = NotCombinedOp;
3092
3093 /// Does this sequence require some shuffling?
3094 SmallVector<int, 4> ReuseShuffleIndices;
3095
3096 /// Does this entry require reordering?
3097 SmallVector<unsigned, 4> ReorderIndices;
3098
3099 /// Points back to the VectorizableTree.
3100 ///
3101 /// Only used for Graphviz right now. Unfortunately GraphTrait::NodeRef has
3102 /// to be a pointer and needs to be able to initialize the child iterator.
3103 /// Thus we need a reference back to the container to translate the indices
3104 /// to entries.
3105 VecTreeTy &Container;
3106
3107 /// The TreeEntry index containing the user of this entry.
3108 EdgeInfo UserTreeIndex;
3109
3110 /// The index of this treeEntry in VectorizableTree.
3111 unsigned Idx = 0;
3112
3113 /// For gather/buildvector/alt opcode nodes, which are combined from
3114 /// other nodes as a series of insertvector instructions.
3115 SmallVector<std::pair<unsigned, unsigned>, 2> CombinedEntriesWithIndices;
3116
3117 /// For ExtractValue entries that are vectorized via the struct-call path
3118 /// (checkEVsForVecCalls succeeded during tree building), stores the common
3119 /// field-index path shared by all scalars in the bundle. Empty for all
3120 /// other entry kinds.
3121 SmallVector<unsigned, 1> StructEVIndices;
3122
3123 private:
3124 /// The operands of each instruction in each lane Operands[op_index][lane].
3125 /// Note: This helps avoid the replication of the code that performs the
3126 /// reordering of operands during buildTreeRec() and vectorizeTree().
3127 SmallVector<ValueList, 2> Operands;
3128
3129 /// Copyable elements of the entry node.
3130 SmallPtrSet<const Value *, 4> CopyableElements;
3131
3132 /// Intermediate instructions peeled from an associative chain (e.g. the
3133 /// inner add in add(add(v0,x),v1)). Not part of Scalars.
3134 SmallVector<Value *, 4> ReassocScalars;
3135
3136 /// Sign of each flattened operand column of a reassociated add/sub
3137 /// chain, parallel to the operand columns: a negated column is
3138 /// subtracted from the positive total. Empty when no column is negated.
3139 SmallBitVector ReassocNegatedOps;
3140
3141 /// MainOp and AltOp are recorded inside. S should be obtained from
3142 /// newTreeEntry.
3143 InstructionsState S = InstructionsState::invalid();
3144
3145 /// Interleaving factor for interleaved loads Vectorize nodes.
3146 unsigned InterleaveFactor = 0;
3147
3148 /// True if the node does not require scheduling.
3149 bool DoesNotNeedToSchedule = false;
3150
3151 /// Set this bundle's \p OpIdx'th operand to \p OpVL.
3152 void setOperand(unsigned OpIdx, ArrayRef<Value *> OpVL) {
3153 if (Operands.size() < OpIdx + 1)
3154 Operands.resize(OpIdx + 1);
3155 assert(Operands[OpIdx].empty() && "Already resized?");
3156 assert(OpVL.size() <= Scalars.size() &&
3157 "Number of operands is greater than the number of scalars.");
3158 Operands[OpIdx].resize(OpVL.size());
3159 copy(OpVL, Operands[OpIdx].begin());
3160 }
3161
3162 /// Maps values to their lanes in the node.
3163 mutable SmallDenseMap<Value *, unsigned> ValueToLane;
3164
3165 public:
3166 /// Returns interleave factor for interleave nodes.
3167 unsigned getInterleaveFactor() const { return InterleaveFactor; }
3168 /// Sets interleaving factor for the interleaving nodes.
3169 void setInterleave(unsigned Factor) { InterleaveFactor = Factor; }
3170
3171 /// Marks the node as one that does not require scheduling.
3172 void setDoesNotNeedToSchedule() { DoesNotNeedToSchedule = true; }
3173 /// Returns true if the node is marked as one that does not require
3174 /// scheduling.
3175 bool doesNotNeedToSchedule() const { return DoesNotNeedToSchedule; }
3176
3177 /// Set this bundle's operands from \p Operands.
3178 void setOperands(ArrayRef<ValueList> Operands) {
3179 for (unsigned I : seq<unsigned>(Operands.size()))
3180 setOperand(I, Operands[I]);
3181 }
3182
3183 /// Reorders operands of the node to the given mask \p Mask.
3184 void reorderOperands(ArrayRef<int> Mask) {
3185 for (ValueList &Operand : Operands)
3186 reorderScalars(Operand, Mask);
3187 }
3188
3189 /// \returns the \p OpIdx operand of this TreeEntry.
3190 ValueList &getOperand(unsigned OpIdx) {
3191 assert(OpIdx < Operands.size() && "Off bounds");
3192 return Operands[OpIdx];
3193 }
3194
3195 /// \returns the \p OpIdx operand of this TreeEntry.
3196 ArrayRef<Value *> getOperand(unsigned OpIdx) const {
3197 assert(OpIdx < Operands.size() && "Off bounds");
3198 return Operands[OpIdx];
3199 }
3200
3201 /// \returns the number of operands.
3202 unsigned getNumOperands() const { return Operands.size(); }
3203
3204 /// \return the single \p OpIdx operand.
3205 Value *getSingleOperand(unsigned OpIdx) const {
3206 assert(OpIdx < Operands.size() && "Off bounds");
3207 assert(!Operands[OpIdx].empty() && "No operand available");
3208 return Operands[OpIdx][0];
3209 }
3210
3211 /// Some of the instructions in the list have alternate opcodes.
3212 bool isAltShuffle() const { return S.isAltShuffle(); }
3213
3214 Instruction *getMatchingMainOpOrAltOp(Instruction *I) const {
3215 return S.getMatchingMainOpOrAltOp(I);
3216 }
3217
3218 /// Chooses the correct key for scheduling data. If \p Op has the same (or
3219 /// alternate) opcode as \p OpValue, the key is \p Op. Otherwise the key is
3220 /// \p OpValue.
3221 Value *isOneOf(Value *Op) const {
3222 auto *I = dyn_cast<Instruction>(Op);
3223 if (I && getMatchingMainOpOrAltOp(I))
3224 return Op;
3225 return S.getMainOp();
3226 }
3227
3228 void setOperations(const InstructionsState &S) {
3229 assert(S && "InstructionsState is invalid.");
3230 this->S = S;
3231 }
3232
3233 Instruction *getMainOp() const { return S.getMainOp(); }
3234
3235 Instruction *getAltOp() const { return S.getAltOp(); }
3236
3237 /// The main/alternate opcodes for the list of instructions.
3238 unsigned getOpcode() const { return S.getOpcode(); }
3239
3240 unsigned getAltOpcode() const { return S.getAltOpcode(); }
3241
3242 bool hasState() const { return S.valid(); }
3243
3244 /// Add \p V to the list of copyable elements.
3245 void addCopyableElement(Value *V) {
3246 assert(S.isCopyableElement(V) && "Not a copyable element.");
3247 CopyableElements.insert(V);
3248 }
3249
3250 /// Returns true if \p V is a copyable element.
3251 bool isCopyableElement(Value *V) const {
3252 return CopyableElements.contains(V);
3253 }
3254
3255 /// Checks if the value \p V is a transformed instruction, compatible either
3256 /// with main or alternate ops.
3257 bool isExpandedBinOp(Value *V) const {
3258 assert(hasState() && "InstructionsState is invalid.");
3259 if (isCopyableElement(V))
3260 return false;
3261 return S.isExpandedBinOp(V);
3262 }
3263
3264 /// Checks if the operand at index \p Idx of instruction \p I is an expanded
3265 /// operand.
3266 bool isExpandedOperand(Instruction *I, unsigned Idx) const {
3267 assert(hasState() && "InstructionsState is invalid.");
3268 if (isCopyableElement(I))
3269 return false;
3270 if (!isExpandedBinOp(I))
3271 return false;
3272 return S.isExpandedOperand(I, Idx);
3273 }
3274
3275 /// Returns true if any scalar in the list is a copyable element.
3276 bool hasCopyableElements() const { return !CopyableElements.empty(); }
3277
3278 /// Adds \p V to the peeled reassociated scalars.
3279 void addReassocScalar(Value *V) { ReassocScalars.push_back(V); }
3280
3281 /// True if operands were gathered from an associative chain.
3282 bool hasReassocScalars() const { return !ReassocScalars.empty(); }
3283
3284 /// Returns peeled reassociated scalars.
3285 ArrayRef<Value *> getReassocScalars() const { return ReassocScalars; }
3286
3287 /// Records the signs of the flattened operand columns.
3288 void setReassocNegatedOps(const SmallBitVector &NegatedOps) {
3289 assert(NegatedOps.size() == getNumOperands() &&
3290 "Signs must cover all operand columns.");
3291 ReassocNegatedOps = NegatedOps;
3292 }
3293
3294 /// True if operand column \p Idx is subtracted rather than added.
3295 bool isReassocNegatedOp(unsigned Idx) const {
3296 return Idx < ReassocNegatedOps.size() && ReassocNegatedOps[Idx];
3297 }
3298
3299 /// Returns the state of the operations.
3300 const InstructionsState &getOperations() const { return S; }
3301
3302 /// When ReuseReorderShuffleIndices is empty it just returns position of \p
3303 /// V within vector of Scalars. Otherwise, try to remap on its reuse index.
3304 unsigned findLaneForValue(Value *V) const {
3305 auto Res = ValueToLane.try_emplace(V, getVectorFactor());
3306 if (!Res.second)
3307 return Res.first->second;
3308 unsigned &FoundLane = Res.first->getSecond();
3309 // Poison can take any lane, match it to the lane of the first non-poison
3310 // scalar.
3311 auto IsMatch = [V](Value *S) {
3312 return isa<PoisonValue>(V) ? !isa<PoisonValue>(S) : S == V;
3313 };
3314 for (auto *It = find_if(Scalars, IsMatch), *End = Scalars.end();
3315 It != End; std::advance(It, 1)) {
3316 if (!IsMatch(*It))
3317 continue;
3318 FoundLane = std::distance(Scalars.begin(), It);
3319 assert(FoundLane < Scalars.size() && "Couldn't find extract lane");
3320 if (!ReorderIndices.empty())
3321 FoundLane = ReorderIndices[FoundLane];
3322 assert(FoundLane < Scalars.size() && "Couldn't find extract lane");
3323 if (ReuseShuffleIndices.empty())
3324 break;
3325 if (auto *RIt = find(ReuseShuffleIndices, FoundLane);
3326 RIt != ReuseShuffleIndices.end()) {
3327 FoundLane = std::distance(ReuseShuffleIndices.begin(), RIt);
3328 break;
3329 }
3330 }
3331 assert(FoundLane < getVectorFactor() && "Unable to find given value.");
3332 return FoundLane;
3333 }
3334
3335 /// Build a shuffle mask for graph entry which represents a merge of main
3336 /// and alternate operations.
3337 void
3338 buildAltOpShuffleMask(const function_ref<bool(Instruction *)> IsAltOp,
3339 SmallVectorImpl<int> &Mask,
3340 SmallVectorImpl<Value *> *OpScalars = nullptr,
3341 SmallVectorImpl<Value *> *AltScalars = nullptr) const;
3342
3343 /// Return true if this is a non-power-of-2 node.
3344 bool isNonPowOf2Vec() const {
3345 bool IsNonPowerOf2 = !has_single_bit(Scalars.size());
3346 return IsNonPowerOf2;
3347 }
3348
3349 Value *getOrdered(unsigned Idx) const {
3350 if (ReorderIndices.empty())
3351 return Scalars[Idx];
3352 SmallVector<int> Mask;
3353 inversePermutation(ReorderIndices, Mask);
3354 return Scalars[Mask[Idx]];
3355 }
3356
3357#ifndef NDEBUG
3358 /// Debug printer.
3359 LLVM_DUMP_METHOD void dump() const {
3360 dbgs() << Idx << ".\n";
3361 for (unsigned OpI = 0, OpE = Operands.size(); OpI != OpE; ++OpI) {
3362 dbgs() << "Operand " << OpI << ":\n";
3363 for (const Value *V : Operands[OpI])
3364 dbgs().indent(2) << *V << "\n";
3365 }
3366 dbgs() << "Scalars: \n";
3367 for (Value *V : Scalars) {
3368 dbgs().indent(2) << *V
3369 << ((S && S.isExpandedBinOp(V)) ? " [[Expanded]]\n"
3370 : "\n");
3371 }
3372 dbgs() << "State: ";
3373 if (S && hasCopyableElements())
3374 dbgs() << "[[Copyable]] ";
3375 switch (State) {
3376 case Vectorize:
3377 if (InterleaveFactor > 0) {
3378 dbgs() << "Vectorize with interleave factor " << InterleaveFactor
3379 << "\n";
3380 } else {
3381 dbgs() << "Vectorize\n";
3382 }
3383 break;
3384 case ScatterVectorize:
3385 dbgs() << "ScatterVectorize\n";
3386 break;
3387 case StridedVectorize:
3388 dbgs() << "StridedVectorize\n";
3389 break;
3390 case ExpandVectorize:
3391 dbgs() << "ExpandVectorize\n";
3392 break;
3393 case CompressVectorize:
3394 dbgs() << "CompressVectorize\n";
3395 break;
3396 case BlendedLoadVectorize:
3397 dbgs() << "BlendedLoadVectorize\n";
3398 break;
3399 case NeedToGather:
3400 dbgs() << "NeedToGather\n";
3401 break;
3402 case CombinedVectorize:
3403 dbgs() << "CombinedVectorize\n";
3404 break;
3405 case SplitVectorize:
3406 dbgs() << "SplitVectorize\n";
3407 break;
3408 }
3409 if (S) {
3410 dbgs() << "MainOp: " << *S.getMainOp() << "\n";
3411 dbgs() << "AltOp: " << *S.getAltOp() << "\n";
3412 } else {
3413 dbgs() << "MainOp: NULL\n";
3414 dbgs() << "AltOp: NULL\n";
3415 }
3416 dbgs() << "VectorizedValue: ";
3417 if (VectorizedValue)
3418 dbgs() << *VectorizedValue << "\n";
3419 else
3420 dbgs() << "NULL\n";
3421 dbgs() << "ReuseShuffleIndices: ";
3422 if (ReuseShuffleIndices.empty())
3423 dbgs() << "Empty";
3424 else
3425 for (int ReuseIdx : ReuseShuffleIndices)
3426 dbgs() << ReuseIdx << ", ";
3427 dbgs() << "\n";
3428 dbgs() << "ReorderIndices: ";
3429 for (unsigned ReorderIdx : ReorderIndices)
3430 dbgs() << ReorderIdx << ", ";
3431 dbgs() << "\n";
3432 dbgs() << "UserTreeIndex: ";
3433 if (UserTreeIndex)
3434 dbgs() << UserTreeIndex;
3435 else
3436 dbgs() << "<invalid>";
3437 dbgs() << "\n";
3438 if (!StructEVIndices.empty()) {
3439 dbgs() << "StructEVIndices: ";
3440 interleaveComma(StructEVIndices, dbgs());
3441 dbgs() << "\n";
3442 }
3443 if (!CombinedEntriesWithIndices.empty()) {
3444 dbgs() << "Combined entries: ";
3445 interleaveComma(CombinedEntriesWithIndices, dbgs(), [&](const auto &P) {
3446 dbgs() << "Entry index " << P.first << " with offset " << P.second;
3447 });
3448 dbgs() << "\n";
3449 }
3450 }
3451#endif
3452 };
3453
3454#ifndef NDEBUG
3455 void dumpTreeCosts(const TreeEntry *E, InstructionCost ReuseShuffleCost,
3456 InstructionCost VecCost, InstructionCost ScalarCost,
3457 StringRef Banner) const {
3458 dbgs() << "SLP: " << Banner << ":\n";
3459 E->dump();
3460 dbgs() << "SLP: Costs:\n";
3461 dbgs() << "SLP: ReuseShuffleCost = " << ReuseShuffleCost << "\n";
3462 dbgs() << "SLP: VectorCost = " << VecCost << "\n";
3463 dbgs() << "SLP: ScalarCost = " << ScalarCost << "\n";
3464 dbgs() << "SLP: ReuseShuffleCost + VecCost - ScalarCost = "
3465 << ReuseShuffleCost + VecCost - ScalarCost << "\n";
3466 }
3467#endif
3468
3469 /// Create a new gather TreeEntry
3470 TreeEntry *newGatherTreeEntry(ArrayRef<Value *> VL,
3471 const InstructionsState &S,
3472 const EdgeInfo &UserTreeIdx,
3473 ArrayRef<int> ReuseShuffleIndices = {}) {
3474 auto Invalid = ScheduleBundle::invalid();
3475 return newTreeEntry(VL, Invalid, S, UserTreeIdx, ReuseShuffleIndices);
3476 }
3477
3478 /// Create a new VectorizableTree entry.
3479 TreeEntry *newTreeEntry(ArrayRef<Value *> VL, ScheduleBundle &Bundle,
3480 const InstructionsState &S,
3481 const EdgeInfo &UserTreeIdx,
3482 ArrayRef<int> ReuseShuffleIndices = {},
3483 ArrayRef<unsigned> ReorderIndices = {},
3484 unsigned InterleaveFactor = 0) {
3485 TreeEntry::EntryState EntryState =
3486 Bundle ? TreeEntry::Vectorize : TreeEntry::NeedToGather;
3487 TreeEntry *E = newTreeEntry(VL, EntryState, Bundle, S, UserTreeIdx,
3488 ReuseShuffleIndices, ReorderIndices);
3489 if (E && InterleaveFactor > 0)
3490 E->setInterleave(InterleaveFactor);
3491 return E;
3492 }
3493
3494 TreeEntry *newTreeEntry(ArrayRef<Value *> VL,
3495 TreeEntry::EntryState EntryState,
3496 ScheduleBundle &Bundle, const InstructionsState &S,
3497 const EdgeInfo &UserTreeIdx,
3498 ArrayRef<int> ReuseShuffleIndices = {},
3499 ArrayRef<unsigned> ReorderIndices = {}) {
3500 assert(((!Bundle && (EntryState == TreeEntry::NeedToGather ||
3501 EntryState == TreeEntry::SplitVectorize)) ||
3502 (Bundle && EntryState != TreeEntry::NeedToGather &&
3503 EntryState != TreeEntry::SplitVectorize)) &&
3504 "Need to vectorize gather entry?");
3505 // Gathered loads still gathered? Do not create entry, use the original one.
3506 if (GatheredLoadsEntriesFirst.has_value() &&
3507 EntryState == TreeEntry::NeedToGather && S &&
3508 S.getOpcode() == Instruction::Load && UserTreeIdx.EdgeIdx == UINT_MAX &&
3509 !UserTreeIdx.UserTE)
3510 return nullptr;
3511 VectorizableTree.push_back(std::make_unique<TreeEntry>(VectorizableTree));
3512 TreeEntry *Last = VectorizableTree.back().get();
3513 Last->Idx = VectorizableTree.size() - 1;
3514 Last->State = EntryState;
3515 if (UserTreeIdx.UserTE)
3516 OperandsToTreeEntry.try_emplace(
3517 std::make_pair(UserTreeIdx.UserTE, UserTreeIdx.EdgeIdx), Last);
3518 Last->ReuseShuffleIndices.append(ReuseShuffleIndices.begin(),
3519 ReuseShuffleIndices.end());
3520 if (ReorderIndices.empty()) {
3521 Last->Scalars.assign(VL.begin(), VL.end());
3522 if (S)
3523 Last->setOperations(S);
3524 } else {
3525 // Reorder scalars and build final mask.
3526 Last->Scalars.assign(VL.size(), nullptr);
3527 transform(ReorderIndices, Last->Scalars.begin(),
3528 [VL](unsigned Idx) -> Value * {
3529 if (Idx >= VL.size())
3530 return UndefValue::get(VL.front()->getType());
3531 return VL[Idx];
3532 });
3533 InstructionsState S = getSameOpcode(Last->Scalars, *TLI);
3534 if (S)
3535 Last->setOperations(S);
3536 Last->ReorderIndices.append(ReorderIndices.begin(), ReorderIndices.end());
3537 }
3538 if (EntryState == TreeEntry::SplitVectorize) {
3539 assert(S && "Split nodes must have operations.");
3540 Last->setOperations(S);
3541 SmallPtrSet<Value *, 4> Processed;
3542 for (Value *V : VL) {
3543 auto *I = dyn_cast<Instruction>(V);
3544 if (!I)
3545 continue;
3546 auto It = ScalarsInSplitNodes.find(V);
3547 if (It == ScalarsInSplitNodes.end()) {
3548 ScalarsInSplitNodes.try_emplace(V).first->getSecond().push_back(Last);
3549 (void)Processed.insert(V);
3550 } else if (Processed.insert(V).second) {
3551 assert(!is_contained(It->getSecond(), Last) &&
3552 "Value already associated with the node.");
3553 It->getSecond().push_back(Last);
3554 }
3555 }
3556 } else if (!Last->isGather()) {
3557 if (isa<PHINode>(S.getMainOp()) ||
3560 doesNotNeedToSchedule(VL)) ||
3561 all_of(VL, [&](Value *V) { return S.isNonSchedulable(V); }))
3562 Last->setDoesNotNeedToSchedule();
3563 SmallPtrSet<Value *, 4> Processed;
3564 for (Value *V : VL) {
3565 if (isa<PoisonValue>(V))
3566 continue;
3567 if (S.isCopyableElement(V)) {
3568 Last->addCopyableElement(V);
3569 continue;
3570 }
3571 auto It = ScalarToTreeEntries.find(V);
3572 if (It == ScalarToTreeEntries.end()) {
3573 ScalarToTreeEntries.try_emplace(V).first->getSecond().push_back(Last);
3574 (void)Processed.insert(V);
3575 } else if (Processed.insert(V).second) {
3576 assert(!is_contained(It->getSecond(), Last) &&
3577 "Value already associated with the node.");
3578 It->getSecond().push_back(Last);
3579 }
3580 }
3581 // Update the scheduler bundle to point to this TreeEntry.
3582 assert((!Bundle.getBundle().empty() || Last->doesNotNeedToSchedule()) &&
3583 "Bundle and VL out of sync");
3584 if (!Bundle.getBundle().empty()) {
3585#if !defined(NDEBUG) || defined(EXPENSIVE_CHECKS)
3586 auto *BundleMember = Bundle.getBundle().begin();
3587 SmallPtrSet<Value *, 4> Processed;
3588 for (Value *V : VL) {
3589 if (S.isNonSchedulable(V) || !Processed.insert(V).second)
3590 continue;
3591 ++BundleMember;
3592 }
3593 assert(BundleMember == Bundle.getBundle().end() &&
3594 "Bundle and VL out of sync");
3595#endif
3596 Bundle.setTreeEntry(Last);
3597 }
3598 } else {
3599 // Build a map for gathered scalars to the nodes where they are used.
3600 bool AllConstsOrCasts = true;
3601 for (Value *V : VL) {
3603 S.isCopyableElement(V))
3604 Last->addCopyableElement(V);
3605 if (!isConstant(V)) {
3606 auto *I = dyn_cast<CastInst>(V);
3607 AllConstsOrCasts &= I && I->getType()->isIntegerTy();
3608 if (UserTreeIdx.EdgeIdx != UINT_MAX || !UserTreeIdx.UserTE ||
3609 !UserTreeIdx.UserTE->isGather())
3610 ValueToGatherNodes.try_emplace(V).first->getSecond().insert(Last);
3611 }
3612 }
3613 if (AllConstsOrCasts)
3614 CastMaxMinBWSizes =
3615 std::make_pair(std::numeric_limits<unsigned>::max(), 1);
3616 MustGather.insert_range(VL);
3617 }
3618
3619 if (UserTreeIdx.UserTE)
3620 Last->UserTreeIndex = UserTreeIdx;
3621 return Last;
3622 }
3623
3624 /// -- Vectorization State --
3625 /// Holds all of the tree entries.
3626 TreeEntry::VecTreeTy VectorizableTree;
3627
3628#ifndef NDEBUG
3629 /// Debug printer.
3630 LLVM_DUMP_METHOD void dumpVectorizableTree() const {
3631 for (unsigned Id = 0, IdE = VectorizableTree.size(); Id != IdE; ++Id) {
3632 VectorizableTree[Id]->dump();
3633 if (TransformedToGatherNodes.contains(VectorizableTree[Id].get()))
3634 dbgs() << "[[TRANSFORMED TO GATHER]]";
3635 else if (DeletedNodes.contains(VectorizableTree[Id].get()))
3636 dbgs() << "[[DELETED NODE]]";
3637 dbgs() << "\n";
3638 }
3639 }
3640#endif
3641
3642 /// Get list of vector entries, associated with the value \p V.
3643 ArrayRef<TreeEntry *> getTreeEntries(const Value *V) const {
3644 assert(V && "V cannot be nullptr.");
3645 auto It = ScalarToTreeEntries.find(V);
3646 if (It == ScalarToTreeEntries.end())
3647 return {};
3648 return It->getSecond();
3649 }
3650
3651 /// Get list of split vector entries, associated with the value \p V.
3652 ArrayRef<TreeEntry *> getSplitTreeEntries(Value *V) const {
3653 assert(V && "V cannot be nullptr.");
3654 auto It = ScalarsInSplitNodes.find(V);
3655 if (It == ScalarsInSplitNodes.end())
3656 return {};
3657 return It->getSecond();
3658 }
3659
3660 /// Returns first vector node for value \p V, matching values \p VL.
3661 TreeEntry *getSameValuesTreeEntry(Value *V, ArrayRef<Value *> VL,
3662 bool SameVF = false) const {
3663 assert(V && "V cannot be nullptr.");
3664 for (TreeEntry *TE : ScalarToTreeEntries.lookup(V))
3665 if ((!SameVF || TE->getVectorFactor() == VL.size()) && TE->isSame(VL))
3666 return TE;
3667 return nullptr;
3668 }
3669
3670 /// Contains all the outputs of legality analysis for a list of values to
3671 /// vectorize.
3672 class ScalarsVectorizationLegality {
3673 InstructionsState S;
3674 bool IsLegal;
3675 bool TryToFindDuplicates;
3676 bool TrySplitVectorize;
3677
3678 public:
3679 ScalarsVectorizationLegality(InstructionsState S, bool IsLegal,
3680 bool TryToFindDuplicates = true,
3681 bool TrySplitVectorize = false)
3682 : S(S), IsLegal(IsLegal), TryToFindDuplicates(TryToFindDuplicates),
3683 TrySplitVectorize(TrySplitVectorize) {
3684 assert((!IsLegal || (S.valid() && TryToFindDuplicates)) &&
3685 "Inconsistent state");
3686 }
3687 const InstructionsState &getInstructionsState() const { return S; };
3688 bool isLegal() const { return IsLegal; }
3689 bool tryToFindDuplicates() const { return TryToFindDuplicates; }
3690 bool trySplitVectorize() const { return TrySplitVectorize; }
3691 };
3692
3693 /// Checks if the specified list of the instructions/values can be vectorized
3694 /// in general.
3695 ScalarsVectorizationLegality
3696 getScalarsVectorizationLegality(ArrayRef<Value *> VL, unsigned Depth,
3697 const EdgeInfo &UserTreeIdx) const;
3698
3699 /// Checks if the specified list of the instructions/values can be vectorized
3700 /// and fills required data before actual scheduling of the instructions.
3701 TreeEntry::EntryState getScalarsVectorizationState(
3702 const InstructionsState &S, ArrayRef<Value *> VL,
3703 bool IsScatterVectorizeUserTE, OrdersType &CurrentOrder,
3704 SmallVectorImpl<Value *> &PointerOps, StridedPtrInfo &SPtrInfo,
3705 SmallVectorImpl<int> &ReuseShuffleIndices);
3706
3707 /// Maps a specific scalar to its tree entry(ies).
3708 SmallDenseMap<Value *, SmallVector<TreeEntry *>> ScalarToTreeEntries;
3709
3710 /// List of deleted non-profitable nodes.
3711 SmallPtrSet<const TreeEntry *, 8> DeletedNodes;
3712
3713 /// List of nodes, transformed to gathered, with their conservative
3714 /// gather/buildvector cost estimation.
3715 SmallDenseMap<const TreeEntry *, InstructionCost> TransformedToGatherNodes;
3716
3717 /// Maps the operand index and entry to the corresponding tree entry.
3718 SmallDenseMap<std::pair<const TreeEntry *, unsigned>, TreeEntry *>
3719 OperandsToTreeEntry;
3720
3721 /// Scalars, used in split vectorize nodes.
3722 SmallDenseMap<Value *, SmallVector<TreeEntry *>> ScalarsInSplitNodes;
3723
3724 /// Maps a value to the proposed vectorizable size.
3725 SmallDenseMap<Value *, unsigned> InstrElementSize;
3726
3727 /// A list of scalars that we found that we need to keep as scalars.
3728 ValueSet MustGather;
3729
3730 /// Maps each peeled reassociated scalar to owning entries. Keeps them
3731 /// treated as vectorized while an owner is live.
3732 SmallDenseMap<const Value *, SmallVector<const TreeEntry *>>
3733 ReassocScalarToTreeEntries;
3734
3735 /// Peeled reassociated scalars that must survive erasure: claimed by a
3736 /// gather node, listed in some tree entry's scalars, or feeding another
3737 /// kept scalar.
3738 SmallPtrSet<const Value *, 8> KeptReassocScalars;
3739
3740 /// A set of first non-schedulable values.
3741 ValueSet NonScheduledFirst;
3742
3743 /// A map between the vectorized entries and the last instructions in the
3744 /// bundles. The bundles are built in use order, not in the def order of the
3745 /// instructions. So, we cannot rely directly on the last instruction in the
3746 /// bundle being the last instruction in the program order during
3747 /// vectorization process since the basic blocks are affected, need to
3748 /// pre-gather them before.
3749 SmallDenseMap<const TreeEntry *, WeakTrackingVH> EntryToLastInstruction;
3750
3751 /// Keeps the mapping between the last instructions and their insertion
3752 /// points, which is an instruction-after-the-last-instruction.
3753 SmallDenseMap<const Instruction *, Instruction *> LastInstructionToPos;
3754
3755 /// List of gather nodes, depending on other gather/vector nodes, which should
3756 /// be emitted after the vector instruction emission process to correctly
3757 /// handle order of the vector instructions and shuffles.
3758 SetVector<const TreeEntry *> PostponedGathers;
3759
3760 using ValueToGatherNodesMap =
3761 DenseMap<Value *, SmallSetVector<const TreeEntry *, 4>>;
3762 ValueToGatherNodesMap ValueToGatherNodes;
3763
3764 SmallDenseMap<TreeEntry *, StridedPtrInfo> TreeEntryToStridedPtrInfoMap;
3765
3766 /// A list of the load entries (node indices), which can be vectorized using
3767 /// strided or masked gather approach, but attempted to be represented as
3768 /// contiguous loads.
3769 SetVector<unsigned> LoadEntriesToVectorize;
3770
3771 /// true if graph nodes transforming mode is on.
3772 bool IsGraphTransformMode = false;
3773
3774 /// The index of the first gathered load entry in the VectorizeTree.
3775 std::optional<unsigned> GatheredLoadsEntriesFirst;
3776
3777 /// Maps compress entries to their mask data for the final codegen.
3778 SmallDenseMap<const TreeEntry *,
3779 std::tuple<SmallVector<int>, VectorType *, unsigned, bool>>
3780 CompressEntryToData;
3781
3782 /// The loop nest, used to check if only a single loop nest is vectorized, not
3783 /// multiple, to avoid side-effects from the loop-aware cost model.
3784 SmallVector<const Loop *> CurrentLoopNest;
3785
3786 /// Per-depth SCEVs trip counts at every loop level where the tree builder has
3787 /// joined diverging sibling loops.
3788 SmallVector<const SCEV *> MergedLoopBTCs;
3789
3790 /// Maps the loops to their loop nests.
3791 SmallDenseMap<const Loop *, SmallVector<const Loop *>> LoopToLoopNest;
3792
3793 /// Per-loop cache of nest scale factors: the product of trip counts of the
3794 /// loop and all of its ancestors. Shared by getLoopNestScale() and (via it)
3795 /// by getScaleToLoopIterations() and getGatherNodeEffectiveScale().
3796 SmallDenseMap<const Loop *, uint64_t> LoopNestScaleCache;
3797
3798 /// This POD struct describes one external user in the vectorized tree.
3799 struct ExternalUser {
3800 ExternalUser(Value *S, llvm::User *U, const TreeEntry &E, unsigned L)
3801 : Scalar(S), User(U), E(E), Lane(L) {}
3802
3803 /// Which scalar in our function.
3804 Value *Scalar = nullptr;
3805
3806 /// Which user that uses the scalar.
3807 llvm::User *User = nullptr;
3808
3809 /// Vector node, the value is part of.
3810 const TreeEntry &E;
3811
3812 /// Which lane does the scalar belong to.
3813 unsigned Lane;
3814 };
3815 using UserList = SmallVector<ExternalUser, 16>;
3816
3817 /// Checks if two instructions may access the same memory.
3818 ///
3819 /// \p Loc1 is the location of \p Inst1. It is passed explicitly because it
3820 /// is invariant in the calling loop.
3821 bool isAliased(const MemoryLocation &Loc1, Instruction *Inst1,
3822 Instruction *Inst2) {
3823 assert(Loc1.Ptr && isSimple(Inst1) && "Expected simple first instruction.");
3824 // First check if the result is already in the cache.
3825 AliasCacheKey Key = std::make_pair(Inst1, Inst2);
3826 auto Res = AliasCache.try_emplace(Key);
3827 if (!Res.second)
3828 return Res.first->second;
3829 bool Aliased = isModOrRefSet(BatchAA.getModRefInfo(Inst2, Loc1));
3830 // Store the result in the cache.
3831 Res.first->getSecond() = Aliased;
3832 return Aliased;
3833 }
3834
3835 /// Returns true if the may-alias dependency between simple load/store
3836 /// instructions \p Inst1 and \p Inst2 could be disambiguated by a runtime
3837 /// alias check.
3838 bool isRuntimeCheckableAliasPair(Instruction *Inst1, Instruction *Inst2);
3839
3840 /// Records the (distinct base object) pair behind the may-alias dependency
3841 /// of \p Inst1 and \p Inst2 as a runtime alias check guarding the region in
3842 /// block \p BB. Returns true if the pair was recorded.
3843 bool recordRuntimeAliasCheck(BasicBlock *BB, Instruction *Inst1,
3844 Instruction *Inst2);
3845
3846 /// Emits the collected runtime alias checks and versions the affected block,
3847 /// duplicating its body into a scalar fallback guarded by the checks.
3848 void versionBlocksForRuntimeChecks();
3849
3850 /// Builds the i1 value that is true when any pair of checked base objects
3851 /// overlaps at runtime. The base address bounds are materialized from their
3852 /// SCEVs with \p Exp.
3853 Value *emitRuntimeAliasCheck(IRBuilderBase &Builder, SCEVExpander &Exp);
3854
3855 /// Data to model and emit the runtime alias checks.
3856 struct RuntimeAliasCheckInfo {
3857 /// The block whose body is guarded by the checks. Exactly one block is
3858 /// supported per attempt.
3859 BasicBlock *BB = nullptr;
3860 /// Pairs of base objects that must be proven disjoint.
3861 SmallSetVector<std::pair<const Value *, const Value *>, 4> BasePairs;
3862 /// Accessed address range [Low, High) for each involved base object.
3863 SmallMapVector<const Value *, std::pair<const SCEV *, const SCEV *>, 4>
3864 Bounds;
3865
3866 void clear() {
3867 BB = nullptr;
3868 BasePairs.clear();
3869 Bounds.clear();
3870 }
3871 };
3872
3873 /// When true, scheduling drops may-alias memory dependencies between
3874 /// distinct, range-checkable base objects and records them as runtime alias
3875 /// checks instead.
3876 bool TryRuntimeAliasChecks = false;
3877
3878 /// Runtime alias checks collected during the last optimistic buildTree().
3879 RuntimeAliasCheckInfo RTChecks;
3880
3881 /// Base-object pairs already proven disjoint by the block's runtime alias
3882 /// check.
3883 SmallDenseMap<BasicBlock *,
3884 SmallDenseSet<std::pair<const Value *, const Value *>, 4>, 2>
3885 VersionedBlockCheckedPairs;
3886
3887 /// Scalar fallback blocks.
3888 SmallPtrSet<BasicBlock *, 4> ScalarFallbackBlocks;
3889
3890 /// Blocks for which a runtime-checks versioning attempt was made
3891 /// and did not produce a profitable versioning.
3892 SmallPtrSet<BasicBlock *, 8> FailedRuntimeChecksBlocks;
3893
3894 /// Returns true if a may-alias dependency between the simple load/store
3895 /// instructions \p Inst1 and \p Inst2 in block \p BB is already covered by a
3896 /// runtime alias check emitted for \p BB by a previous versioning.
3897 bool isCoveredByExistingVersionCheck(BasicBlock *BB, Instruction *Inst1,
3898 Instruction *Inst2) const;
3899
3900 /// True, if a may-alias dependency between distinct, range-checkable base
3901 /// objects is observed (whether or not it was dropped).
3902 bool HasRuntimeCheckableBlockers = false;
3903
3904 /// True, if a kept may-alias dependency is not runtime-checkable (call or a
3905 /// non-simple memaccess).
3906 bool HasNonCheckableMemBlocker = false;
3907
3908 /// Runtime checks are validated and bounded the collected checks.
3909 bool RTChecksFinalized = false;
3910
3911 /// Set when a block was versioned with runtime alias checks, which changes
3912 /// the CFG. Used to drop CFG-analysis preservation for the run.
3913 bool CFGChanged = false;
3914
3915 /// Guarded block body (non-PHI, non-terminator) in original source order.
3916 SmallVector<Instruction *> RTOrigBodyOrder;
3917
3918 using AliasCacheKey = std::pair<Instruction *, Instruction *>;
3919
3920 /// Cache for alias results.
3921 /// TODO: consider moving this to the AliasAnalysis itself.
3922 SmallDenseMap<AliasCacheKey, bool> AliasCache;
3923
3924 // Cache for pointerMayBeCaptured calls inside AA. This is preserved
3925 // globally through SLP because we don't perform any action which
3926 // invalidates capture results.
3927 BatchAAResults BatchAA;
3928
3929 /// Temporary store for deleted instructions. Instructions will be deleted
3930 /// eventually when the BoUpSLP is destructed. The deferral is required to
3931 /// ensure that there are no incorrect collisions in the AliasCache, which
3932 /// can happen if a new instruction is allocated at the same address as a
3933 /// previously deleted instruction.
3934 DenseSet<Instruction *> DeletedInstructions;
3935
3936 /// Set of the instruction, being analyzed already for reductions.
3937 SmallPtrSet<Instruction *, 16> AnalyzedReductionsRoots;
3938
3939 /// Set of hashes for the list of reduction values already being analyzed.
3940 DenseSet<size_t> AnalyzedReductionVals;
3941
3942 /// Set of hashes for the bundles, rejected as non-vectorizable.
3943 SmallDenseSet<size_t, 8> AnalyzedBundles;
3944
3945 /// Set of the values, which were a part of the analyzed vector nodes.
3946 SmallPtrSet<const Value *, 32> AnalyzedScalars;
3947
3948 /// Cache of the number of parts for the types and the parts limit.
3949 mutable SmallDenseMap<std::tuple<Type *, Type *, unsigned>, unsigned>
3950 NumberOfPartsCache;
3951
3952 /// Values, already been analyzed for mininmal bitwidth and found to be
3953 /// non-profitable.
3954 DenseSet<Value *> AnalyzedMinBWVals;
3955
3956 /// A list of values that need to extracted out of the tree.
3957 /// This list holds pairs of (Internal Scalar : External User). External User
3958 /// can be nullptr, it means that this Internal Scalar will be used later,
3959 /// after vectorization.
3960 UserList ExternalUses;
3961
3962 /// A list of GEPs which can be reaplced by scalar GEPs instead of
3963 /// extractelement instructions.
3964 SmallPtrSet<Value *, 4> ExternalUsesAsOriginalScalar;
3965
3966 /// A list of scalar to be extracted without specific user necause of too many
3967 /// uses.
3968 SmallPtrSet<Value *, 4> ExternalUsesWithNonUsers;
3969
3970 /// Replacements emitted for the external uses without users, consumed after
3971 /// the tree vectorization; must not be collected as dead operands of the
3972 /// erased scalars.
3973 SmallPtrSet<Value *, 4> ExternalUseReplacements;
3974
3975 /// Values used only by @llvm.assume calls.
3976 SmallPtrSet<const Value *, 32> EphValues;
3977
3978 /// Holds all of the instructions that we gathered, shuffle instructions and
3979 /// extractelements.
3980 SetVector<Instruction *> GatherShuffleExtractSeq;
3981
3982 /// A list of blocks that we are going to CSE.
3983 DenseSet<BasicBlock *> CSEBlocks;
3984
3985 /// List of hashes of vector of loads, which are known to be non vectorizable.
3986 DenseSet<size_t> ListOfKnonwnNonVectorizableLoads;
3987
3988 /// Represents a scheduling entity, either ScheduleData, ScheduleCopyableData
3989 /// or ScheduleBundle. ScheduleData used to gather dependecies for a single
3990 /// instructions, while ScheduleBundle represents a batch of instructions,
3991 /// going to be groupped together. ScheduleCopyableData models extra user for
3992 /// "copyable" instructions.
3993 class ScheduleEntity {
3994 friend class ScheduleBundle;
3995 friend class ScheduleData;
3996 friend class ScheduleCopyableData;
3997
3998 protected:
3999 enum class Kind { ScheduleData, ScheduleBundle, ScheduleCopyableData };
4000 Kind getKind() const { return K; }
4001 ScheduleEntity(Kind K) : K(K) {}
4002
4003 private:
4004 /// Used for getting a "good" final ordering of instructions.
4005 int SchedulingPriority = 0;
4006 /// True if this instruction (or bundle) is scheduled (or considered as
4007 /// scheduled in the dry-run).
4008 bool IsScheduled = false;
4009 /// The kind of the ScheduleEntity.
4010 const Kind K = Kind::ScheduleData;
4011
4012 public:
4013 ScheduleEntity() = delete;
4014 /// Gets/sets the scheduling priority.
4015 void setSchedulingPriority(int Priority) { SchedulingPriority = Priority; }
4016 int getSchedulingPriority() const { return SchedulingPriority; }
4017 bool isReady() const {
4018 if (const auto *SD = dyn_cast<ScheduleData>(this))
4019 return SD->isReady();
4020 if (const auto *CD = dyn_cast<ScheduleCopyableData>(this))
4021 return CD->isReady();
4022 return cast<ScheduleBundle>(this)->isReady();
4023 }
4024 /// Returns true if the dependency information has been calculated.
4025 /// Note that depenendency validity can vary between instructions within
4026 /// a single bundle.
4027 bool hasValidDependencies() const {
4028 if (const auto *SD = dyn_cast<ScheduleData>(this))
4029 return SD->hasValidDependencies();
4030 if (const auto *CD = dyn_cast<ScheduleCopyableData>(this))
4031 return CD->hasValidDependencies();
4032 return cast<ScheduleBundle>(this)->hasValidDependencies();
4033 }
4034 /// Gets the number of unscheduled dependencies.
4035 int getUnscheduledDeps() const {
4036 if (const auto *SD = dyn_cast<ScheduleData>(this))
4037 return SD->getUnscheduledDeps();
4038 if (const auto *CD = dyn_cast<ScheduleCopyableData>(this))
4039 return CD->getUnscheduledDeps();
4040 return cast<ScheduleBundle>(this)->unscheduledDepsInBundle();
4041 }
4042 /// Increments the number of unscheduled dependencies.
4043 int incrementUnscheduledDeps(int Incr) {
4044 if (auto *SD = dyn_cast<ScheduleData>(this))
4045 return SD->incrementUnscheduledDeps(Incr);
4046 return cast<ScheduleCopyableData>(this)->incrementUnscheduledDeps(Incr);
4047 }
4048 /// Gets the number of dependencies.
4049 int getDependencies() const {
4050 if (const auto *SD = dyn_cast<ScheduleData>(this))
4051 return SD->getDependencies();
4052 return cast<ScheduleCopyableData>(this)->getDependencies();
4053 }
4054 /// Gets the instruction.
4055 Instruction *getInst() const {
4056 if (const auto *SD = dyn_cast<ScheduleData>(this))
4057 return SD->getInst();
4058 return cast<ScheduleCopyableData>(this)->getInst();
4059 }
4060
4061 /// Gets/sets if the bundle is scheduled.
4062 bool isScheduled() const { return IsScheduled; }
4063 void setScheduled(bool Scheduled) { IsScheduled = Scheduled; }
4064
4065 static bool classof(const ScheduleEntity *) { return true; }
4066
4067#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
4068 void dump(raw_ostream &OS) const {
4069 if (const auto *SD = dyn_cast<ScheduleData>(this))
4070 return SD->dump(OS);
4071 if (const auto *CD = dyn_cast<ScheduleCopyableData>(this))
4072 return CD->dump(OS);
4073 return cast<ScheduleBundle>(this)->dump(OS);
4074 }
4075
4076 LLVM_DUMP_METHOD void dump() const {
4077 dump(dbgs());
4078 dbgs() << '\n';
4079 }
4080#endif // if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
4081 };
4082
4083#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
4085 const BoUpSLP::ScheduleEntity &SE) {
4086 SE.dump(OS);
4087 return OS;
4088 }
4089#endif
4090
4091 /// Contains all scheduling relevant data for an instruction.
4092 /// A ScheduleData either represents a single instruction or a member of an
4093 /// instruction bundle (= a group of instructions which is combined into a
4094 /// vector instruction).
4095 class ScheduleData final : public ScheduleEntity {
4096 public:
4097 // The initial value for the dependency counters. It means that the
4098 // dependencies are not calculated yet.
4099 enum { InvalidDeps = -1 };
4100
4101 ScheduleData() : ScheduleEntity(Kind::ScheduleData) {}
4102 static bool classof(const ScheduleEntity *Entity) {
4103 return Entity->getKind() == Kind::ScheduleData;
4104 }
4105
4106 void init(int BlockSchedulingRegionID, Instruction *I) {
4107 NextLoadStore = nullptr;
4108 IsScheduled = false;
4109 SchedulingRegionID = BlockSchedulingRegionID;
4110 clearDependencies();
4111 Inst = I;
4112 }
4113
4114 /// Verify basic self consistency properties
4115 void verify() {
4116 if (hasValidDependencies()) {
4117 assert(UnscheduledDeps <= Dependencies && "invariant");
4118 } else {
4119 assert(UnscheduledDeps == Dependencies && "invariant");
4120 }
4121
4122 if (IsScheduled) {
4123 assert(hasValidDependencies() && UnscheduledDeps == 0 &&
4124 "unexpected scheduled state");
4125 }
4126 }
4127
4128 /// Returns true if the dependency information has been calculated.
4129 /// Note that depenendency validity can vary between instructions within
4130 /// a single bundle.
4131 bool hasValidDependencies() const { return Dependencies != InvalidDeps; }
4132
4133 /// Returns true if it is ready for scheduling, i.e. it has no more
4134 /// unscheduled depending instructions/bundles.
4135 bool isReady() const { return UnscheduledDeps == 0 && !IsScheduled; }
4136
4137 /// Modifies the number of unscheduled dependencies for this instruction,
4138 /// and returns the number of remaining dependencies for the containing
4139 /// bundle.
4140 int incrementUnscheduledDeps(int Incr) {
4141 assert(hasValidDependencies() &&
4142 "increment of unscheduled deps would be meaningless");
4143 UnscheduledDeps += Incr;
4144 assert(UnscheduledDeps >= 0 &&
4145 "Expected valid number of unscheduled deps");
4146 return UnscheduledDeps;
4147 }
4148
4149 /// Sets the number of unscheduled dependencies to the number of
4150 /// dependencies.
4151 void resetUnscheduledDeps() { UnscheduledDeps = Dependencies; }
4152
4153 /// Clears all dependency information.
4154 void clearDependencies() {
4155 clearDirectDependencies();
4156 MemoryDependencies.clear();
4157 ControlDependencies.clear();
4158 }
4159
4160 /// Clears all direct dependencies only, except for control and memory
4161 /// dependencies.
4162 /// Required for copyable elements to correctly handle control/memory deps
4163 /// and avoid extra reclaculation of such deps.
4164 void clearDirectDependencies() {
4165 Dependencies = InvalidDeps;
4166 resetUnscheduledDeps();
4167 IsScheduled = false;
4168 }
4169
4170 /// Gets the number of unscheduled dependencies.
4171 int getUnscheduledDeps() const { return UnscheduledDeps; }
4172 /// Gets the number of dependencies.
4173 int getDependencies() const { return Dependencies; }
4174 /// Initializes the number of dependencies.
4175 void initDependencies() { Dependencies = 0; }
4176 /// Increments the number of dependencies.
4177 void incDependencies() { Dependencies++; }
4178
4179 /// Gets scheduling region ID.
4180 int getSchedulingRegionID() const { return SchedulingRegionID; }
4181
4182 /// Gets the instruction.
4183 Instruction *getInst() const { return Inst; }
4184
4185 /// Gets the list of memory dependencies.
4186 ArrayRef<ScheduleData *> getMemoryDependencies() const {
4187 return MemoryDependencies;
4188 }
4189 /// Adds a memory dependency.
4190 void addMemoryDependency(ScheduleData *Dep) {
4191 MemoryDependencies.push_back(Dep);
4192 }
4193 /// Gets the list of control dependencies.
4194 ArrayRef<ScheduleData *> getControlDependencies() const {
4195 return ControlDependencies;
4196 }
4197 /// Adds a control dependency.
4198 void addControlDependency(ScheduleData *Dep) {
4199 ControlDependencies.push_back(Dep);
4200 }
4201 /// Gets/sets the next load/store instruction in the block.
4202 ScheduleData *getNextLoadStore() const { return NextLoadStore; }
4203 void setNextLoadStore(ScheduleData *Next) { NextLoadStore = Next; }
4204
4205 void dump(raw_ostream &OS) const { OS << *Inst; }
4206
4207 LLVM_DUMP_METHOD void dump() const {
4208 dump(dbgs());
4209 dbgs() << '\n';
4210 }
4211
4212 private:
4213 Instruction *Inst = nullptr;
4214
4215 /// Single linked list of all memory instructions (e.g. load, store, call)
4216 /// in the block - until the end of the scheduling region.
4217 ScheduleData *NextLoadStore = nullptr;
4218
4219 /// The dependent memory instructions.
4220 /// This list is derived on demand in calculateDependencies().
4221 SmallVector<ScheduleData *> MemoryDependencies;
4222
4223 /// List of instructions which this instruction could be control dependent
4224 /// on. Allowing such nodes to be scheduled below this one could introduce
4225 /// a runtime fault which didn't exist in the original program.
4226 /// ex: this is a load or udiv following a readonly call which inf loops
4227 SmallVector<ScheduleData *> ControlDependencies;
4228
4229 /// This ScheduleData is in the current scheduling region if this matches
4230 /// the current SchedulingRegionID of BlockScheduling.
4231 int SchedulingRegionID = 0;
4232
4233 /// The number of dependencies. Constitutes of the number of users of the
4234 /// instruction plus the number of dependent memory instructions (if any).
4235 /// This value is calculated on demand.
4236 /// If InvalidDeps, the number of dependencies is not calculated yet.
4237 int Dependencies = InvalidDeps;
4238
4239 /// The number of dependencies minus the number of dependencies of scheduled
4240 /// instructions. As soon as this is zero, the instruction/bundle gets ready
4241 /// for scheduling.
4242 /// Note that this is negative as long as Dependencies is not calculated.
4243 int UnscheduledDeps = InvalidDeps;
4244 };
4245
4246#ifndef NDEBUG
4248 const BoUpSLP::ScheduleData &SD) {
4249 SD.dump(OS);
4250 return OS;
4251 }
4252#endif
4253
4254 class ScheduleBundle final : public ScheduleEntity {
4255 /// The schedule data for the instructions in the bundle.
4257 /// True if this bundle is valid.
4258 bool IsValid = true;
4259 /// The TreeEntry that this instruction corresponds to.
4260 TreeEntry *TE = nullptr;
4261 ScheduleBundle(bool IsValid)
4262 : ScheduleEntity(Kind::ScheduleBundle), IsValid(IsValid) {}
4263
4264 public:
4265 ScheduleBundle() : ScheduleEntity(Kind::ScheduleBundle) {}
4266 static bool classof(const ScheduleEntity *Entity) {
4267 return Entity->getKind() == Kind::ScheduleBundle;
4268 }
4269
4270 /// Verify basic self consistency properties
4271 void verify() const {
4272 for (const ScheduleEntity *SD : Bundle) {
4273 if (SD->hasValidDependencies()) {
4274 assert(SD->getUnscheduledDeps() <= SD->getDependencies() &&
4275 "invariant");
4276 } else {
4277 assert(SD->getUnscheduledDeps() == SD->getDependencies() &&
4278 "invariant");
4279 }
4280
4281 if (isScheduled()) {
4282 assert(SD->hasValidDependencies() && SD->getUnscheduledDeps() == 0 &&
4283 "unexpected scheduled state");
4284 }
4285 }
4286 }
4287
4288 /// Returns the number of unscheduled dependencies in the bundle.
4289 int unscheduledDepsInBundle() const {
4290 assert(*this && "bundle must not be empty");
4291 int Sum = 0;
4292 for (const ScheduleEntity *BundleMember : Bundle) {
4293 if (BundleMember->getUnscheduledDeps() == ScheduleData::InvalidDeps)
4294 return ScheduleData::InvalidDeps;
4295 Sum += BundleMember->getUnscheduledDeps();
4296 }
4297 return Sum;
4298 }
4299
4300 /// Returns true if the dependency information has been calculated.
4301 /// Note that depenendency validity can vary between instructions within
4302 /// a single bundle.
4303 bool hasValidDependencies() const {
4304 return all_of(Bundle, [](const ScheduleEntity *SD) {
4305 return SD->hasValidDependencies();
4306 });
4307 }
4308
4309 /// Returns true if it is ready for scheduling, i.e. it has no more
4310 /// unscheduled depending instructions/bundles.
4311 bool isReady() const {
4312 assert(*this && "bundle must not be empty");
4313 return unscheduledDepsInBundle() == 0 && !isScheduled();
4314 }
4315
4316 /// Returns the bundle of scheduling data, associated with the current
4317 /// instruction.
4318 ArrayRef<ScheduleEntity *> getBundle() { return Bundle; }
4319 ArrayRef<const ScheduleEntity *> getBundle() const { return Bundle; }
4320 /// Adds an instruction to the bundle.
4321 void add(ScheduleEntity *SD) { Bundle.push_back(SD); }
4322
4323 /// Gets/sets the associated tree entry.
4324 void setTreeEntry(TreeEntry *TE) { this->TE = TE; }
4325 TreeEntry *getTreeEntry() const { return TE; }
4326
4327 static ScheduleBundle invalid() { return {false}; }
4328
4329 operator bool() const { return IsValid; }
4330
4331#ifndef NDEBUG
4332 void dump(raw_ostream &OS) const {
4333 if (!*this) {
4334 OS << "[]";
4335 return;
4336 }
4337 OS << '[';
4338 interleaveComma(Bundle, OS, [&](const ScheduleEntity *SD) {
4340 OS << "<Copyable>";
4341 OS << *SD->getInst();
4342 });
4343 OS << ']';
4344 }
4345
4346 LLVM_DUMP_METHOD void dump() const {
4347 dump(dbgs());
4348 dbgs() << '\n';
4349 }
4350#endif // NDEBUG
4351 };
4352
4353#ifndef NDEBUG
4355 const BoUpSLP::ScheduleBundle &Bundle) {
4356 Bundle.dump(OS);
4357 return OS;
4358 }
4359#endif
4360
4361 /// Contains all scheduling relevant data for the copyable instruction.
4362 /// It models the virtual instructions, supposed to replace the original
4363 /// instructions. E.g., if instruction %0 = load is a part of the bundle [%0,
4364 /// %1], where %1 = add, then the ScheduleCopyableData models virtual
4365 /// instruction %virt = add %0, 0.
4366 class ScheduleCopyableData final : public ScheduleEntity {
4367 /// The source schedule data for the instruction.
4368 Instruction *Inst = nullptr;
4369 /// The edge information for the instruction.
4370 const EdgeInfo EI;
4371 /// This ScheduleData is in the current scheduling region if this matches
4372 /// the current SchedulingRegionID of BlockScheduling.
4373 int SchedulingRegionID = 0;
4374 /// Bundle, this data is part of.
4375 ScheduleBundle &Bundle;
4376
4377 public:
4378 ScheduleCopyableData(int BlockSchedulingRegionID, Instruction *I,
4379 const EdgeInfo &EI, ScheduleBundle &Bundle)
4380 : ScheduleEntity(Kind::ScheduleCopyableData), Inst(I), EI(EI),
4381 SchedulingRegionID(BlockSchedulingRegionID), Bundle(Bundle) {}
4382 static bool classof(const ScheduleEntity *Entity) {
4383 return Entity->getKind() == Kind::ScheduleCopyableData;
4384 }
4385
4386 /// Verify basic self consistency properties
4387 void verify() {
4388 if (hasValidDependencies()) {
4389 assert(UnscheduledDeps <= Dependencies && "invariant");
4390 } else {
4391 assert(UnscheduledDeps == Dependencies && "invariant");
4392 }
4393
4394 if (IsScheduled) {
4395 assert(hasValidDependencies() && UnscheduledDeps == 0 &&
4396 "unexpected scheduled state");
4397 }
4398 }
4399
4400 /// Returns true if the dependency information has been calculated.
4401 /// Note that depenendency validity can vary between instructions within
4402 /// a single bundle.
4403 bool hasValidDependencies() const {
4404 return Dependencies != ScheduleData::InvalidDeps;
4405 }
4406
4407 /// Returns true if it is ready for scheduling, i.e. it has no more
4408 /// unscheduled depending instructions/bundles.
4409 bool isReady() const { return UnscheduledDeps == 0 && !IsScheduled; }
4410
4411 /// Modifies the number of unscheduled dependencies for this instruction,
4412 /// and returns the number of remaining dependencies for the containing
4413 /// bundle.
4414 int incrementUnscheduledDeps(int Incr) {
4415 assert(hasValidDependencies() &&
4416 "increment of unscheduled deps would be meaningless");
4417 UnscheduledDeps += Incr;
4418 assert(UnscheduledDeps >= 0 && "invariant");
4419 return UnscheduledDeps;
4420 }
4421
4422 /// Sets the number of unscheduled dependencies to the number of
4423 /// dependencies.
4424 void resetUnscheduledDeps() { UnscheduledDeps = Dependencies; }
4425
4426 /// Gets the number of unscheduled dependencies.
4427 int getUnscheduledDeps() const { return UnscheduledDeps; }
4428 /// Gets the number of dependencies.
4429 int getDependencies() const { return Dependencies; }
4430 /// Initializes the number of dependencies.
4431 void initDependencies() { Dependencies = 0; }
4432 /// Increments the number of dependencies.
4433 void incDependencies() { Dependencies++; }
4434
4435 /// Gets scheduling region ID.
4436 int getSchedulingRegionID() const { return SchedulingRegionID; }
4437
4438 /// Gets the instruction.
4439 Instruction *getInst() const { return Inst; }
4440
4441 /// Clears all dependency information.
4442 void clearDependencies() {
4443 Dependencies = ScheduleData::InvalidDeps;
4444 UnscheduledDeps = ScheduleData::InvalidDeps;
4445 IsScheduled = false;
4446 }
4447
4448 /// Gets the edge information.
4449 const EdgeInfo &getEdgeInfo() const { return EI; }
4450
4451 /// Gets the bundle.
4452 ScheduleBundle &getBundle() { return Bundle; }
4453 const ScheduleBundle &getBundle() const { return Bundle; }
4454
4455#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
4456 void dump(raw_ostream &OS) const { OS << "[Copyable]" << *getInst(); }
4457
4458 LLVM_DUMP_METHOD void dump() const {
4459 dump(dbgs());
4460 dbgs() << '\n';
4461 }
4462#endif // !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
4463
4464 private:
4465 /// true, if it has valid dependency information. These nodes always have
4466 /// only single dependency.
4467 int Dependencies = ScheduleData::InvalidDeps;
4468
4469 /// The number of dependencies minus the number of dependencies of scheduled
4470 /// instructions. As soon as this is zero, the instruction/bundle gets ready
4471 /// for scheduling.
4472 /// Note that this is negative as long as Dependencies is not calculated.
4473 int UnscheduledDeps = ScheduleData::InvalidDeps;
4474 };
4475
4476#ifndef NDEBUG
4477 friend inline raw_ostream &
4478 operator<<(raw_ostream &OS, const BoUpSLP::ScheduleCopyableData &SD) {
4479 SD.dump(OS);
4480 return OS;
4481 }
4482#endif
4483
4484 friend struct GraphTraits<BoUpSLP *>;
4485 friend struct DOTGraphTraits<BoUpSLP *>;
4486
4487 /// Contains all scheduling data for a basic block.
4488 /// It does not schedules instructions, which are not memory read/write
4489 /// instructions and their operands are either constants, or arguments, or
4490 /// phis, or instructions from others blocks, or their users are phis or from
4491 /// the other blocks. The resulting vector instructions can be placed at the
4492 /// beginning of the basic block without scheduling (if operands does not need
4493 /// to be scheduled) or at the end of the block (if users are outside of the
4494 /// block). It allows to save some compile time and memory used by the
4495 /// compiler.
4496 /// ScheduleData is assigned for each instruction in between the boundaries of
4497 /// the tree entry, even for those, which are not part of the graph. It is
4498 /// required to correctly follow the dependencies between the instructions and
4499 /// their correct scheduling. The ScheduleData is not allocated for the
4500 /// instructions, which do not require scheduling, like phis, nodes with
4501 /// extractelements/insertelements only or nodes with instructions, with
4502 /// uses/operands outside of the block.
4503 struct BlockScheduling {
4504 BlockScheduling(BasicBlock *BB)
4505 : BB(BB), ChunkSize(BB->size()), ChunkPos(ChunkSize) {}
4506
4507 void clear() {
4508 ScheduledBundles.clear();
4509 ScheduledBundlesList.clear();
4510 ScheduleCopyableDataMap.clear();
4511 ScheduleCopyableDataMapByInst.clear();
4512 ScheduleCopyableDataMapByInstUser.clear();
4513 ScheduleCopyableDataMapByUsers.clear();
4514 ReadyInsts.clear();
4515 RecalcCopyableOperandDeps.clear();
4516 IgnoredMemDeps.clear();
4517 ScheduleStart = nullptr;
4518 ScheduleEnd = nullptr;
4519 FirstLoadStoreInRegion = nullptr;
4520 LastLoadStoreInRegion = nullptr;
4521 RegionHasStackSave = false;
4522
4523 // Reduce the maximum schedule region size by the size of the
4524 // previous scheduling run.
4525 ScheduleRegionSizeLimit -= ScheduleRegionSize;
4526 if (ScheduleRegionSizeLimit < MinScheduleRegionSize)
4527 ScheduleRegionSizeLimit = MinScheduleRegionSize;
4528 ScheduleRegionSize = 0;
4529
4530 // Make a new scheduling region, i.e. all existing ScheduleData is not
4531 // in the new region yet.
4532 ++SchedulingRegionID;
4533 }
4534
4535 ScheduleData *getScheduleData(Instruction *I) {
4536 if (!I)
4537 return nullptr;
4538 if (BB != I->getParent())
4539 // Avoid lookup if can't possibly be in map.
4540 return nullptr;
4541 ScheduleData *SD = ScheduleDataMap.lookup(I);
4542 if (SD && isInSchedulingRegion(*SD))
4543 return SD;
4544 return nullptr;
4545 }
4546
4547 ScheduleData *getScheduleData(Value *V) {
4548 return getScheduleData(dyn_cast<Instruction>(V));
4549 }
4550
4551 /// Returns the ScheduleCopyableData for the given edge (user tree entry and
4552 /// operand number) and value.
4553 ScheduleCopyableData *getScheduleCopyableData(const EdgeInfo &EI,
4554 const Value *V) const {
4555 if (ScheduleCopyableDataMap.empty())
4556 return nullptr;
4557 auto It = ScheduleCopyableDataMap.find(std::make_pair(EI, V));
4558 if (It == ScheduleCopyableDataMap.end())
4559 return nullptr;
4560 ScheduleCopyableData *SD = It->getSecond().get();
4561 if (!isInSchedulingRegion(*SD))
4562 return nullptr;
4563 return SD;
4564 }
4565
4566 /// Returns the ScheduleCopyableData for the given user \p User, operand
4567 /// number and operand \p V.
4569 getScheduleCopyableData(const Value *User, unsigned OperandIdx,
4570 const Value *V) {
4571 if (ScheduleCopyableDataMapByInstUser.empty())
4572 return {};
4573 const auto It = ScheduleCopyableDataMapByInstUser.find(
4574 std::make_pair(std::make_pair(User, OperandIdx), V));
4575 if (It == ScheduleCopyableDataMapByInstUser.end())
4576 return {};
4578 for (ScheduleCopyableData *SD : It->getSecond()) {
4579 if (isInSchedulingRegion(*SD))
4580 Res.push_back(SD);
4581 }
4582 return Res;
4583 }
4584
4585 /// Returns true if all operands of the given instruction \p User are
4586 /// replaced by copyable data.
4587 /// \param User The user instruction.
4588 /// \param Op The operand, which might be replaced by the copyable data.
4589 /// \param SLP The SLP tree.
4590 /// \param NumOps The number of operands used. If the instruction uses the
4591 /// same operand several times, check for the first use, then the second,
4592 /// etc.
4593 bool areAllOperandsReplacedByCopyableData(Instruction *User,
4594 Instruction *Op, BoUpSLP &SLP,
4595 unsigned NumOps) const {
4596 assert(NumOps > 0 && "No operands");
4597 if (ScheduleCopyableDataMap.empty())
4598 return false;
4599 SmallDenseMap<TreeEntry *, unsigned> PotentiallyReorderedEntriesCount;
4600 ArrayRef<TreeEntry *> Entries = SLP.getTreeEntries(User);
4601 if (Entries.empty())
4602 return false;
4603 unsigned CurNumOps = 0;
4604 for (const Use &U : User->operands()) {
4605 if (U.get() != Op)
4606 continue;
4607 ++CurNumOps;
4608 // Check all tree entries, if they have operands replaced by copyable
4609 // data.
4610 for (TreeEntry *TE : Entries) {
4611 unsigned Inc = 0;
4612 bool IsNonSchedulableWithParentPhiNode =
4613 TE->doesNotNeedToSchedule() && TE->UserTreeIndex &&
4614 TE->UserTreeIndex.UserTE->hasState() &&
4615 TE->UserTreeIndex.UserTE->State != TreeEntry::SplitVectorize &&
4616 TE->UserTreeIndex.UserTE->getOpcode() == Instruction::PHI;
4617 // Count the number of unique phi nodes, which are the parent for
4618 // parent entry, and exit, if all the unique phis are processed.
4619 if (IsNonSchedulableWithParentPhiNode) {
4620 SmallPtrSet<Value *, 4> ParentsUniqueUsers;
4621 const TreeEntry *ParentTE = TE->UserTreeIndex.UserTE;
4622 for (Value *V : ParentTE->Scalars) {
4623 auto *PHI = dyn_cast<PHINode>(V);
4624 if (!PHI)
4625 continue;
4626 if (ParentsUniqueUsers.insert(PHI).second &&
4627 is_contained(PHI->incoming_values(), User))
4628 ++Inc;
4629 }
4630 } else {
4631 Inc = count(TE->Scalars, User);
4632 }
4633
4634 // Check if the user is commutative.
4635 // The commutatives are handled later, as their operands can be
4636 // reordered.
4637 // Same applies even for non-commutative cmps, because we can invert
4638 // their predicate potentially and, thus, reorder the operands.
4639 bool IsCommutativeUser =
4640 isCommutative(User) &&
4641 isCommutableOperand(User, User, U.getOperandNo());
4642 if (!IsCommutativeUser) {
4643 Instruction *MainOp = TE->getMatchingMainOpOrAltOp(User);
4644 IsCommutativeUser =
4645 isCommutative(MainOp, User) &&
4646 isCommutableOperand(MainOp, User, U.getOperandNo());
4647 }
4648 // The commutative user with the same operands can be safely
4649 // considered as non-commutative, operands reordering does not change
4650 // the semantics. Same for cmps with the same operands: inverting
4651 // the predicate does not change the operand columns in this case.
4652 assert(
4653 (!IsCommutativeUser ||
4654 (((isCommutative(User) && isCommutableOperand(User, User, 0) &&
4655 isCommutableOperand(User, User, 1)) ||
4656 (isCommutative(TE->getMatchingMainOpOrAltOp(User), User) &&
4657 isCommutableOperand(TE->getMatchingMainOpOrAltOp(User), User,
4658 0) &&
4659 isCommutableOperand(TE->getMatchingMainOpOrAltOp(User), User,
4660 1))))) &&
4661 "Expected commutative user with 2 first commutable operands");
4662 bool IsCommutativeWithSameOps =
4663 IsCommutativeUser && User->getOperand(0) == User->getOperand(1);
4664 if ((!IsCommutativeUser || IsCommutativeWithSameOps) &&
4665 (!isa<CmpInst>(User) ||
4666 User->getOperand(0) == User->getOperand(1))) {
4667 if (CurNumOps != NumOps)
4668 continue;
4669 // A reassociated node flattens the operand chain, so the operand
4670 // may be placed in any operand column rather than at the
4671 // instruction's operand number.
4672 if (TE->hasReassocScalars()) {
4673 bool ReplacedByCopyable = false;
4674 for (auto It = find(TE->Scalars, User); It != TE->Scalars.end();
4675 It = find(make_range(std::next(It), TE->Scalars.end()),
4676 User)) {
4677 int Lane = std::distance(TE->Scalars.begin(), It);
4678 for (unsigned OpIdx : seq<unsigned>(TE->getNumOperands()))
4679 ReplacedByCopyable |=
4680 TE->getOperand(OpIdx)[Lane] == Op &&
4681 getScheduleCopyableData(EdgeInfo(TE, OpIdx), Op);
4682 }
4683 if (ReplacedByCopyable)
4684 continue;
4685 return false;
4686 }
4687 EdgeInfo EI(TE, U.getOperandNo());
4688 if (getScheduleCopyableData(EI, Op))
4689 continue;
4690 return false;
4691 }
4692 // Only count the occurrence matching this call's NumOps.
4693 if (CurNumOps != NumOps)
4694 continue;
4695 PotentiallyReorderedEntriesCount.try_emplace(TE, 0)
4696 .first->getSecond() += Inc;
4697 }
4698 }
4699 if (PotentiallyReorderedEntriesCount.empty())
4700 return true;
4701 // Check the commutative/cmp entries.
4702 for (auto &P : PotentiallyReorderedEntriesCount) {
4703 SmallPtrSet<Value *, 4> ParentsUniqueUsers;
4704 bool IsNonSchedulableWithParentPhiNode =
4705 P.first->doesNotNeedToSchedule() && P.first->UserTreeIndex &&
4706 P.first->UserTreeIndex.UserTE->hasState() &&
4707 P.first->UserTreeIndex.UserTE->State != TreeEntry::SplitVectorize &&
4708 P.first->UserTreeIndex.UserTE->getOpcode() == Instruction::PHI;
4709 auto *It = find(P.first->Scalars, User);
4710 do {
4711 assert(It != P.first->Scalars.end() &&
4712 "User is not in the tree entry");
4713 int Lane = std::distance(P.first->Scalars.begin(), It);
4714 assert(Lane >= 0 && "Lane is not found");
4716 !P.first->ReorderIndices.empty())
4717 Lane = P.first->ReorderIndices[Lane];
4718 assert(Lane < static_cast<int>(P.first->Scalars.size()) &&
4719 "Couldn't find extract lane");
4720 // Count the number of unique phi nodes, which are the parent for
4721 // parent entry, and exit, if all the unique phis are processed.
4722 if (IsNonSchedulableWithParentPhiNode) {
4723 const TreeEntry *ParentTE = P.first->UserTreeIndex.UserTE;
4724 Value *User = ParentTE->Scalars[Lane];
4725 if (!ParentsUniqueUsers.insert(User).second) {
4726 It =
4727 find(make_range(std::next(It), P.first->Scalars.end()), User);
4728 continue;
4729 }
4730 }
4731 // Flattened nodes may place an operand in any column; scan all of
4732 // them so copyable scheduling does not double-count.
4733 for (unsigned OpIdx :
4734 seq<unsigned>(P.first->hasReassocScalars()
4735 ? P.first->getNumOperands()
4737 P.first->getMainOp()))) {
4738 if (P.first->getOperand(OpIdx)[Lane] == Op &&
4739 getScheduleCopyableData(EdgeInfo(P.first, OpIdx), Op))
4740 --P.getSecond();
4741 }
4742 // If parent node is schedulable, it will be handled correctly.
4743 It = find(make_range(std::next(It), P.first->Scalars.end()), User);
4744 } while (It != P.first->Scalars.end());
4745 }
4746 return all_of(PotentiallyReorderedEntriesCount,
4747 [&](const std::pair<const TreeEntry *, unsigned> &P) {
4748 return P.second == NumOps - 1;
4749 });
4750 }
4751
4753 getScheduleCopyableData(const Instruction *I) const {
4754 if (ScheduleCopyableDataMapByInst.empty())
4755 return {};
4756 const auto It = ScheduleCopyableDataMapByInst.find(I);
4757 if (It == ScheduleCopyableDataMapByInst.end())
4758 return {};
4760 for (ScheduleCopyableData *SD : It->getSecond()) {
4761 if (isInSchedulingRegion(*SD))
4762 Res.push_back(SD);
4763 }
4764 return Res;
4765 }
4766
4768 getScheduleCopyableDataUsers(const Instruction *User) const {
4769 if (ScheduleCopyableDataMapByUsers.empty())
4770 return {};
4771 const auto It = ScheduleCopyableDataMapByUsers.find(User);
4772 if (It == ScheduleCopyableDataMapByUsers.end())
4773 return {};
4775 for (ScheduleCopyableData *SD : It->getSecond()) {
4776 if (isInSchedulingRegion(*SD))
4777 Res.push_back(SD);
4778 }
4779 return Res;
4780 }
4781
4782 /// Reordering \p TE permutes its operand columns and may move an operand
4783 /// between the edges covered and not covered by copyable scheduling
4784 /// data, making the computed dependency counts stale. Mark the schedule
4785 /// data of \p TE's copyable-modeled operands for recalculation at the
4786 /// next bundle scheduling.
4787 void markCopyableDepsForRecalc(const TreeEntry &TE) {
4788 for (unsigned OpIdx : seq<unsigned>(TE.getNumOperands()))
4789 for (Value *V : TE.getOperand(OpIdx))
4790 if (auto *I = dyn_cast<Instruction>(V))
4791 if (ScheduleData *SD = getScheduleData(I);
4792 SD && !getScheduleCopyableData(I).empty())
4793 RecalcCopyableOperandDeps.insert(SD);
4794 }
4795
4796 ScheduleCopyableData &addScheduleCopyableData(const EdgeInfo &EI,
4797 Instruction *I,
4798 int SchedulingRegionID,
4799 ScheduleBundle &Bundle) {
4800 assert(!getScheduleCopyableData(EI, I) && "already in the map");
4801 ScheduleCopyableData *CD =
4802 ScheduleCopyableDataMap
4803 .try_emplace(std::make_pair(EI, I),
4804 std::make_unique<ScheduleCopyableData>(
4805 SchedulingRegionID, I, EI, Bundle))
4806 .first->getSecond()
4807 .get();
4808 ScheduleCopyableDataMapByInst[I].push_back(CD);
4809 if (EI.UserTE) {
4810 ArrayRef<Value *> Op = EI.UserTE->getOperand(EI.EdgeIdx);
4811 const auto *It = find(Op, I);
4812 assert(It != Op.end() && "Lane not set");
4813 SmallPtrSet<Instruction *, 4> Visited;
4814 do {
4815 int Lane = std::distance(Op.begin(), It);
4816 assert(Lane >= 0 && "Lane not set");
4817 if (isa<StoreInst, InsertValueInst>(EI.UserTE->Scalars[Lane]) &&
4818 !EI.UserTE->ReorderIndices.empty())
4819 Lane = EI.UserTE->ReorderIndices[Lane];
4820 assert(Lane < static_cast<int>(EI.UserTE->Scalars.size()) &&
4821 "Couldn't find extract lane");
4822 auto *In = cast<Instruction>(EI.UserTE->Scalars[Lane]);
4823 if (!Visited.insert(In).second) {
4824 It = find(make_range(std::next(It), Op.end()), I);
4825 continue;
4826 }
4827 ScheduleCopyableDataMapByInstUser
4828 .try_emplace(std::make_pair(std::make_pair(In, EI.EdgeIdx), I))
4829 .first->getSecond()
4830 .push_back(CD);
4831 ScheduleCopyableDataMapByUsers.try_emplace(I)
4832 .first->getSecond()
4833 .insert(CD);
4834 // Remove extra deps for users, becoming non-immediate users of the
4835 // instruction. It may happen, if the chain of same copyable elements
4836 // appears in the tree.
4837 if (In == I) {
4838 EdgeInfo UserEI = EI.UserTE->UserTreeIndex;
4839 if (ScheduleCopyableData *UserCD =
4840 getScheduleCopyableData(UserEI, In))
4841 ScheduleCopyableDataMapByUsers[I].remove(UserCD);
4842 }
4843 It = find(make_range(std::next(It), Op.end()), I);
4844 } while (It != Op.end());
4845 } else {
4846 ScheduleCopyableDataMapByUsers.try_emplace(I).first->getSecond().insert(
4847 CD);
4848 }
4849 return *CD;
4850 }
4851
4852 ArrayRef<ScheduleBundle *> getScheduleBundles(Value *V) const {
4853 auto *I = dyn_cast<Instruction>(V);
4854 if (!I)
4855 return {};
4856 auto It = ScheduledBundles.find(I);
4857 if (It == ScheduledBundles.end())
4858 return {};
4859 return It->getSecond();
4860 }
4861
4862 /// Returns true if the entity is in the scheduling region.
4863 bool isInSchedulingRegion(const ScheduleEntity &SD) const {
4864 if (const auto *Data = dyn_cast<ScheduleData>(&SD))
4865 return Data->getSchedulingRegionID() == SchedulingRegionID;
4866 if (const auto *CD = dyn_cast<ScheduleCopyableData>(&SD))
4867 return CD->getSchedulingRegionID() == SchedulingRegionID;
4868 return all_of(cast<ScheduleBundle>(SD).getBundle(),
4869 [&](const ScheduleEntity *BundleMember) {
4870 return isInSchedulingRegion(*BundleMember);
4871 });
4872 }
4873
4874 /// Marks an instruction as scheduled and puts all dependent ready
4875 /// instructions into the ready-list.
4876 template <typename ReadyListType>
4877 void schedule(const BoUpSLP &R, const InstructionsState &S,
4878 const EdgeInfo &EI, ScheduleEntity *Data,
4879 ReadyListType &ReadyList) {
4880 auto ProcessBundleMember = [&](ScheduleEntity *BundleMember,
4882 // Handle the def-use chain dependencies.
4883
4884 // Decrement the unscheduled counter and insert to ready list if ready.
4885 auto DecrUnsched = [&](auto *Data, bool IsControl = false) {
4886 if ((IsControl || Data->hasValidDependencies()) &&
4887 Data->incrementUnscheduledDeps(-1) == 0) {
4888 // There are no more unscheduled dependencies after
4889 // decrementing, so we can put the dependent instruction
4890 // into the ready list.
4891 SmallVector<ScheduleBundle *, 1> CopyableBundle;
4893 if (auto *CD = dyn_cast<ScheduleCopyableData>(Data)) {
4894 CopyableBundle.push_back(&CD->getBundle());
4895 Bundles = CopyableBundle;
4896 } else {
4897 Bundles = getScheduleBundles(Data->getInst());
4898 }
4899 if (!Bundles.empty()) {
4900 for (ScheduleBundle *Bundle : Bundles) {
4901 if (Bundle->unscheduledDepsInBundle() == 0) {
4902 assert(!Bundle->isScheduled() &&
4903 "already scheduled bundle gets ready");
4904 ReadyList.insert(Bundle);
4906 << "SLP: gets ready: " << *Bundle << "\n");
4907 }
4908 }
4909 return;
4910 }
4911 assert(!Data->isScheduled() &&
4912 "already scheduled bundle gets ready");
4914 "Expected non-copyable data");
4915 ReadyList.insert(Data);
4916 LLVM_DEBUG(dbgs() << "SLP: gets ready: " << *Data << "\n");
4917 }
4918 };
4919
4920 auto DecrUnschedForInst = [&](Instruction *User, unsigned OpIdx,
4921 Instruction *I) {
4922 if (!ScheduleCopyableDataMap.empty()) {
4924 getScheduleCopyableData(User, OpIdx, I);
4925 bool ReleasedAsCopyable = false;
4926 for (ScheduleCopyableData *CD : CopyableData) {
4927 // Copyable elements modeled on a copyable user lane depend on
4928 // the user's copyable scheduling data, not on the user itself,
4929 // and are released when that copyable data is scheduled. The
4930 // user's own schedule data still carries the def-use dependency
4931 // in this case, so it must be released below.
4932 if (CD->getEdgeInfo().UserTE->isCopyableElement(User))
4933 continue;
4934 DecrUnsched(CD, /*IsControl=*/false);
4935 ReleasedAsCopyable = true;
4936 }
4937 if (ReleasedAsCopyable)
4938 return;
4939 }
4940 if (ScheduleData *OpSD = getScheduleData(I))
4941 DecrUnsched(OpSD, /*IsControl=*/false);
4942 };
4943
4944 // If BundleMember is a vector bundle, its operands may have been
4945 // reordered during buildTree(). We therefore need to get its operands
4946 // through the TreeEntry.
4947 if (!Bundles.empty()) {
4948 auto *In = BundleMember->getInst();
4949 // Count uses of each instruction operand.
4950 SmallDenseMap<const Instruction *, unsigned> OperandsUses;
4951 unsigned TotalOpCount = 0;
4952 if (isa<ScheduleCopyableData>(BundleMember)) {
4953 // Copyable data is used only once (uses itself).
4954 TotalOpCount = OperandsUses[In] = 1;
4955 } else {
4956 for (const Use &U : In->operands()) {
4957 if (auto *I = dyn_cast<Instruction>(U.get())) {
4958 auto Res = OperandsUses.try_emplace(I, 0);
4959 unsigned ExtraDeps = 1;
4960 // Count all expanded operands in the binops.
4961 for (ScheduleBundle *Bundle : Bundles) {
4962 if (const TreeEntry *TE = Bundle->getTreeEntry()) {
4963 if (TE->isExpandedBinOp(In))
4964 ++ExtraDeps;
4965 } else if (S.isExpandedBinOp(In)) {
4966 ++ExtraDeps;
4967 }
4968 }
4969 Res.first->getSecond() += ExtraDeps;
4970 TotalOpCount += ExtraDeps;
4971 }
4972 }
4973 }
4974 // Tracks whether the bundle member instruction itself shows up in
4975 // some operand column of its node (only copyable elements modeled
4976 // through their own operands, like absorbed fmuls, do not).
4977 bool FoundInOpColumns = false;
4978 // Decrement the unscheduled counter and insert to ready list if
4979 // ready.
4980 auto DecrUnschedForInst =
4981 [&](Instruction *I, TreeEntry *UserTE, unsigned OpIdx,
4982 SmallDenseSet<std::pair<const ScheduleEntity *, unsigned>>
4983 &Checked,
4984 bool IsExpandedOperand = false,
4985 bool CopyableDepsOnly = false) {
4986 if (!ScheduleCopyableDataMap.empty()) {
4987 const EdgeInfo EI = {UserTE, OpIdx};
4988 if (ScheduleCopyableData *CD =
4989 getScheduleCopyableData(EI, I)) {
4990 if (!Checked.insert(std::make_pair(CD, OpIdx)).second)
4991 return;
4992 DecrUnsched(CD, /*IsControl=*/false);
4993 return;
4994 }
4995 }
4996 if (CopyableDepsOnly)
4997 return;
4998 auto It = OperandsUses.find(I);
4999 if (It == OperandsUses.end()) {
5000 // Column value may be a peeled intermediate, not a direct
5001 // operand of In; its deps are released when it is scheduled.
5002 LLVM_DEBUG(dbgs() << "SLP: operand " << *I
5003 << " not modeled as a direct operand of "
5004 << *In << ", skipping.\n");
5005 return;
5006 }
5007 if (It->second > 0) {
5008 if (ScheduleData *OpSD = getScheduleData(I)) {
5009 if (!IsExpandedOperand &&
5010 !Checked.insert(std::make_pair(OpSD, OpIdx)).second)
5011 return;
5012 --It->getSecond();
5013 assert(TotalOpCount > 0 && "No more operands to decrement");
5014 --TotalOpCount;
5015 DecrUnsched(OpSD, /*IsControl=*/false);
5016 } else {
5017 --It->getSecond();
5018 assert(TotalOpCount > 0 && "No more operands to decrement");
5019 --TotalOpCount;
5020 }
5021 }
5022 };
5023
5024 SmallDenseSet<std::pair<const ScheduleEntity *, unsigned>> Checked;
5025 for (ScheduleBundle *Bundle : Bundles) {
5026 if (ScheduleCopyableDataMap.empty() && TotalOpCount == 0)
5027 break;
5028 SmallPtrSet<Value *, 4> ParentsUniqueUsers;
5029 // Need to search for the lane since the tree entry can be
5030 // reordered.
5031 auto *It = find(Bundle->getTreeEntry()->Scalars, In);
5032 bool IsNonSchedulableWithParentPhiNode =
5033 Bundle->getTreeEntry()->doesNotNeedToSchedule() &&
5034 Bundle->getTreeEntry()->UserTreeIndex &&
5035 Bundle->getTreeEntry()->UserTreeIndex.UserTE->hasState() &&
5036 Bundle->getTreeEntry()->UserTreeIndex.UserTE->State !=
5037 TreeEntry::SplitVectorize &&
5038 Bundle->getTreeEntry()->UserTreeIndex.UserTE->getOpcode() ==
5039 Instruction::PHI;
5040 do {
5041 int Lane =
5042 std::distance(Bundle->getTreeEntry()->Scalars.begin(), It);
5043 assert(Lane >= 0 && "Lane not set");
5045 !Bundle->getTreeEntry()->ReorderIndices.empty())
5046 Lane = Bundle->getTreeEntry()->ReorderIndices[Lane];
5047 assert(Lane < static_cast<int>(
5048 Bundle->getTreeEntry()->Scalars.size()) &&
5049 "Couldn't find extract lane");
5050
5051 // Since vectorization tree is being built recursively this
5052 // assertion ensures that the tree entry has all operands set
5053 // before reaching this code. Couple of exceptions known at the
5054 // moment are extracts where their second (immediate) operand is
5055 // not added. Since immediates do not affect scheduler behavior
5056 // this is considered okay.
5057 assert(
5058 In &&
5060 In->getNumOperands() ==
5061 Bundle->getTreeEntry()->getNumOperands() ||
5062 (isa<ZExtInst>(In) && Bundle->getTreeEntry()->getOpcode() ==
5063 Instruction::Select) ||
5064 Bundle->getTreeEntry()->isCopyableElement(In) ||
5065 Bundle->getTreeEntry()->hasReassocScalars()) &&
5066 "Missed TreeEntry operands?");
5067
5068 // Count the number of unique phi nodes, which are the parent
5069 // entry, and handle the non-copyable deps only on the first lane
5070 // for each such phi. Copyable deps are counted per operand column
5071 // lane and are released on every lane.
5072 bool CopyableDepsOnly =
5073 IsNonSchedulableWithParentPhiNode &&
5074 !ParentsUniqueUsers
5075 .insert(Bundle->getTreeEntry()
5076 ->UserTreeIndex.UserTE->Scalars[Lane])
5077 .second;
5078
5079 // A blended-load operand node is the synthetic blend mask, not an
5080 // IR operand of the load. Use the real pointer operand for
5081 // scheduling so the def-use counters stay balanced; the mask is
5082 // available earlier through the pointer's select.
5083 bool IsBlended = Bundle->getTreeEntry()->State ==
5084 TreeEntry::BlendedLoadVectorize;
5085 for (unsigned OpIdx :
5086 seq<unsigned>(Bundle->getTreeEntry()->getNumOperands()))
5087 if (auto *I = dyn_cast<Instruction>(
5088 IsBlended ? In->getOperand(OpIdx)
5089 : Bundle->getTreeEntry()->getOperand(
5090 OpIdx)[Lane])) {
5091 FoundInOpColumns |= (I == In) && !CopyableDepsOnly;
5092 LLVM_DEBUG(dbgs() << "SLP: check for readiness (def): "
5093 << *I << "\n");
5094 DecrUnschedForInst(
5095 I, Bundle->getTreeEntry(), OpIdx, Checked,
5096 Bundle->getTreeEntry()->isExpandedOperand(In, OpIdx),
5097 /*CopyableDepsOnly=*/CopyableDepsOnly);
5098 }
5099 // If parent node is schedulable, it will be handled correctly.
5100 if (Bundle->getTreeEntry()->isCopyableElement(In))
5101 break;
5102 It = std::find(std::next(It),
5103 Bundle->getTreeEntry()->Scalars.end(), In);
5104 } while (It != Bundle->getTreeEntry()->Scalars.end());
5105 }
5106 // A copyable element absorbed into its user modeling (e.g. a
5107 // copyable fmul turned into fmuladd(a, b, -0.0)) does not appear in
5108 // the operand columns of its own node, so the scan above never
5109 // releases the schedule data of the copyable instruction itself.
5110 // Release it here to keep the unscheduled-deps counters balanced,
5111 // consuming its self-use count so the reassociated-operand release
5112 // below cannot release the same schedule data twice.
5113 if (isa<ScheduleCopyableData>(BundleMember) && !FoundInOpColumns) {
5114 auto UseIt = OperandsUses.find(In);
5115 if (UseIt != OperandsUses.end() && UseIt->second > 0) {
5116 --UseIt->getSecond();
5117 --TotalOpCount;
5118 }
5119 if (ScheduleData *OpSD = getScheduleData(In))
5120 DecrUnsched(OpSD, /*IsControl=*/false);
5121 }
5122 // Vector intrinsics may keep some arguments scalar (e.g. the
5123 // exponent of llvm.powi). Such scalar arguments are not modeled as
5124 // tree-entry operands, so the per-lane loop above never releases the
5125 // dependency that calculateDependencies() registered for the
5126 // definition feeding such an argument. Release it here to keep the
5127 // unscheduled-deps counters balanced; otherwise the operand's bundle
5128 // may never become ready and scheduling would assert.
5129 if (TotalOpCount > 0) {
5130 if (auto *CI = dyn_cast<CallInst>(In)) {
5132 for (unsigned ArgIdx : seq<unsigned>(CI->arg_size())) {
5133 if (!isVectorIntrinsicWithScalarOpAtArg(ID, ArgIdx, R.TTI))
5134 continue;
5135 auto *OpI = dyn_cast<Instruction>(CI->getArgOperand(ArgIdx));
5136 if (!OpI)
5137 continue;
5138 auto UseIt = OperandsUses.find(OpI);
5139 if (UseIt == OperandsUses.end() || UseIt->second == 0)
5140 continue;
5141 --UseIt->getSecond();
5142 --TotalOpCount;
5143 if (ScheduleData *OpSD = getScheduleData(OpI)) {
5145 << "SLP: check for readiness (scalar arg): "
5146 << *OpI << "\n");
5147 DecrUnsched(OpSD, /*IsControl=*/false);
5148 }
5149 }
5150 }
5151 // Peeled intermediates stay as direct operands but drop out of
5152 // operand columns; release their scheduling deps here.
5153 for (const ScheduleBundle *Bundle : Bundles) {
5154 if (TotalOpCount == 0)
5155 break;
5156 TreeEntry *TE = Bundle->getTreeEntry();
5157 if (!TE->hasReassocScalars())
5158 continue;
5159 for (Value *V : TE->getReassocScalars()) {
5160 auto *OpI = dyn_cast<Instruction>(V);
5161 if (!OpI)
5162 continue;
5163 auto UseIt = OperandsUses.find(OpI);
5164 if (UseIt == OperandsUses.end() || UseIt->second == 0)
5165 continue;
5166 LLVM_DEBUG(dbgs() << "SLP: check for readiness "
5167 "(reassociated operand): "
5168 << *OpI << "\n");
5169 // Copyable deps may live on per-edge ScheduleCopyableData.
5170 bool ReleasedAsCopyable = false;
5171 if (!ScheduleCopyableDataMap.empty()) {
5172 for (const Use &U : In->operands()) {
5173 if (U.get() != OpI)
5174 continue;
5175 for (ScheduleCopyableData *CD :
5176 getScheduleCopyableData(In, U.getOperandNo(), OpI)) {
5177 // Deps of reassoc scalars modeled as copyable tree
5178 // operands are released by the operand scan above;
5179 // release each remaining dep only once.
5180 if (Checked.insert(std::make_pair(CD, U.getOperandNo()))
5181 .second)
5182 DecrUnsched(CD, /*IsControl=*/false);
5183 }
5184 }
5185 // The dep is released through copyable data only if this
5186 // very entry models the scalar as a copyable operand on one
5187 // of its edges, mirroring the dependency calculation;
5188 // copyable data on some other entry's edge does not cover
5189 // the dep registered for this entry.
5190 for (auto It = find(TE->Scalars, In);
5191 It != TE->Scalars.end() && !ReleasedAsCopyable;
5192 It = find(make_range(std::next(It), TE->Scalars.end()),
5193 In)) {
5194 int Lane = std::distance(TE->Scalars.begin(), It);
5195 for (unsigned OpIdx : seq<unsigned>(TE->getNumOperands()))
5196 ReleasedAsCopyable |=
5197 TE->getOperand(OpIdx)[Lane] == OpI &&
5198 getScheduleCopyableData(EdgeInfo(TE, OpIdx), OpI);
5199 }
5200 }
5201 if (!ReleasedAsCopyable) {
5202 if (ScheduleData *OpSD = getScheduleData(OpI))
5203 for (unsigned I = 0, E = UseIt->second; I != E; ++I)
5204 DecrUnsched(OpSD, /*IsControl=*/false);
5205 }
5206 TotalOpCount -= UseIt->second;
5207 UseIt->second = 0;
5208 }
5209 }
5210 }
5211 } else {
5212 // If BundleMember is a stand-alone instruction, no operand reordering
5213 // has taken place, so we directly access its operands.
5214 for (Use &U : BundleMember->getInst()->operands()) {
5215 if (auto *I = dyn_cast<Instruction>(U.get())) {
5217 << "SLP: check for readiness (def): " << *I << "\n");
5218 DecrUnschedForInst(BundleMember->getInst(), U.getOperandNo(), I);
5219 }
5220 }
5221 }
5222 // Handle the memory dependencies.
5223 auto *SD = dyn_cast<ScheduleData>(BundleMember);
5224 if (!SD)
5225 return;
5226 SmallPtrSet<const ScheduleData *, 4> VisitedMemory;
5227 for (ScheduleData *MemoryDep : SD->getMemoryDependencies()) {
5228 if (!VisitedMemory.insert(MemoryDep).second)
5229 continue;
5230 // There are no more unscheduled dependencies after decrementing,
5231 // so we can put the dependent instruction into the ready list.
5232 LLVM_DEBUG(dbgs() << "SLP: check for readiness (mem): "
5233 << *MemoryDep << "\n");
5234 DecrUnsched(MemoryDep);
5235 }
5236 // Handle the control dependencies.
5237 SmallPtrSet<const ScheduleData *, 4> VisitedControl;
5238 for (ScheduleData *Dep : SD->getControlDependencies()) {
5239 if (!VisitedControl.insert(Dep).second)
5240 continue;
5241 // There are no more unscheduled dependencies after decrementing,
5242 // so we can put the dependent instruction into the ready list.
5244 << "SLP: check for readiness (ctrl): " << *Dep << "\n");
5245 DecrUnsched(Dep, /*IsControl=*/true);
5246 }
5247 };
5248 if (auto *SD = dyn_cast<ScheduleData>(Data)) {
5249 SD->setScheduled(/*Scheduled=*/true);
5250 LLVM_DEBUG(dbgs() << "SLP: schedule " << *SD << "\n");
5253 Instruction *In = SD->getInst();
5254 ArrayRef<TreeEntry *> Entries = R.getTreeEntries(In);
5255 if (!Entries.empty()) {
5256 for (TreeEntry *TE : Entries) {
5258 In->getNumOperands() != TE->getNumOperands() &&
5259 !TE->hasReassocScalars())
5260 continue;
5261 auto &BundlePtr =
5262 PseudoBundles.emplace_back(std::make_unique<ScheduleBundle>());
5263 BundlePtr->setTreeEntry(TE);
5264 BundlePtr->add(SD);
5265 Bundles.push_back(BundlePtr.get());
5266 }
5267 }
5268 ProcessBundleMember(SD, Bundles);
5269 } else {
5270 ScheduleBundle &Bundle = *cast<ScheduleBundle>(Data);
5271 Bundle.setScheduled(/*Scheduled=*/true);
5272 LLVM_DEBUG(dbgs() << "SLP: schedule " << Bundle << "\n");
5273 auto AreAllBundlesScheduled =
5274 [&](const ScheduleEntity *SD,
5275 ArrayRef<ScheduleBundle *> SDBundles) {
5277 return true;
5278 return !SDBundles.empty() &&
5279 all_of(SDBundles, [&](const ScheduleBundle *SDBundle) {
5280 return SDBundle->isScheduled();
5281 });
5282 };
5283 for (ScheduleEntity *SD : Bundle.getBundle()) {
5286 SDBundles = getScheduleBundles(SD->getInst());
5287 if (!AreAllBundlesScheduled(SD, SDBundles))
5288 continue;
5289 SD->setScheduled(/*Scheduled=*/true);
5290 Instruction *In = SD->getInst();
5291 // The instruction may also belong to tree entries that do not need
5292 // scheduling (e.g. all their values are used outside the block), so
5293 // no schedule bundle is registered for them. Such an entry can still
5294 // model one of this instruction's operands as a copyable element, or
5295 // model the instruction itself as an expanded binop, registered on
5296 // that non-scheduled parent edge. That dependency would never be
5297 // decremented when the instruction is scheduled through a different
5298 // bundle, leaving the operand's bundle permanently unscheduled and
5299 // tripping the unscheduled-deps assertion. Add pseudo-bundles for
5300 // these missing tree entries, so their operand dependencies are
5301 // decremented here as well. Real operand dependencies are protected
5302 // against double counting by the per-operand use counter.
5303 if (isa<ScheduleCopyableData>(SD) ||
5304 (ScheduleCopyableDataMap.empty() &&
5305 none_of(R.getTreeEntries(In), [&](const TreeEntry *TE) {
5306 return TE->isExpandedBinOp(In);
5307 }))) {
5308 ProcessBundleMember(SD, isa<ScheduleCopyableData>(SD) ? &Bundle
5309 : SDBundles);
5310 continue;
5311 }
5313 SmallVector<ScheduleBundle *> AllBundles(SDBundles.begin(),
5314 SDBundles.end());
5315 for (TreeEntry *TE : R.getTreeEntries(In)) {
5316 if (TE->isCopyableElement(In))
5317 continue;
5319 In->getNumOperands() != TE->getNumOperands() &&
5320 !TE->hasReassocScalars())
5321 continue;
5322 if (any_of(SDBundles, [&](const ScheduleBundle *SDBundle) {
5323 return SDBundle->getTreeEntry() == TE;
5324 }))
5325 continue;
5326 ScheduleBundle &PseudoBundle =
5327 *PseudoBundles.emplace_back(std::make_unique<ScheduleBundle>());
5328 PseudoBundle.setTreeEntry(TE);
5329 PseudoBundle.add(SD);
5330 AllBundles.push_back(&PseudoBundle);
5331 }
5332 ProcessBundleMember(SD, AllBundles);
5333 }
5334 }
5335 }
5336
5337 /// Verify basic self consistency properties of the data structure.
5338 void verify() {
5339 if (!ScheduleStart)
5340 return;
5341
5342 assert(ScheduleStart->getParent() == ScheduleEnd->getParent() &&
5343 ScheduleStart->comesBefore(ScheduleEnd) &&
5344 "Not a valid scheduling region?");
5345
5346 for (auto *I = ScheduleStart; I != ScheduleEnd; I = I->getNextNode()) {
5347 ArrayRef<ScheduleBundle *> Bundles = getScheduleBundles(I);
5348 if (!Bundles.empty()) {
5349 for (ScheduleBundle *Bundle : Bundles) {
5350 assert(isInSchedulingRegion(*Bundle) &&
5351 "primary schedule data not in window?");
5352 Bundle->verify();
5353 }
5354 continue;
5355 }
5356 auto *SD = getScheduleData(I);
5357 if (!SD)
5358 continue;
5359 assert(isInSchedulingRegion(*SD) &&
5360 "primary schedule data not in window?");
5361 SD->verify();
5362 }
5363
5364 assert(all_of(ReadyInsts,
5365 [](const ScheduleEntity *Bundle) {
5366 return Bundle->isReady();
5367 }) &&
5368 "item in ready list not ready?");
5369 }
5370
5371 /// Put all instructions into the ReadyList which are ready for scheduling.
5372 template <typename ReadyListType>
5373 void initialFillReadyList(ReadyListType &ReadyList) {
5374 SmallPtrSet<ScheduleBundle *, 16> Visited;
5375 for (auto *I = ScheduleStart; I != ScheduleEnd; I = I->getNextNode()) {
5376 ScheduleData *SD = getScheduleData(I);
5377 if (SD && SD->hasValidDependencies() && SD->isReady()) {
5378 if (ArrayRef<ScheduleBundle *> Bundles = getScheduleBundles(I);
5379 !Bundles.empty()) {
5380 for (ScheduleBundle *Bundle : Bundles) {
5381 if (!Visited.insert(Bundle).second)
5382 continue;
5383 if (Bundle->hasValidDependencies() && Bundle->isReady()) {
5384 ReadyList.insert(Bundle);
5385 LLVM_DEBUG(dbgs() << "SLP: initially in ready list: "
5386 << *Bundle << "\n");
5387 }
5388 }
5389 continue;
5390 }
5391 ReadyList.insert(SD);
5393 << "SLP: initially in ready list: " << *SD << "\n");
5394 }
5395 }
5396 }
5397
5398 /// Build a bundle from the ScheduleData nodes corresponding to the
5399 /// scalar instruction for each lane.
5400 /// \param VL The list of scalar instructions.
5401 /// \param S The state of the instructions.
5402 /// \param EI The edge in the SLP graph or the user node/operand number.
5403 ScheduleBundle &buildBundle(ArrayRef<Value *> VL,
5404 const InstructionsState &S, const EdgeInfo &EI);
5405
5406 /// Checks if a bundle of instructions can be scheduled, i.e. has no
5407 /// cyclic dependencies. This is only a dry-run, no instructions are
5408 /// actually moved at this stage.
5409 /// \returns the scheduling bundle. The returned Optional value is not
5410 /// std::nullopt if \p VL is allowed to be scheduled.
5411 std::optional<ScheduleBundle *>
5412 tryScheduleBundle(ArrayRef<Value *> VL, BoUpSLP *SLP,
5413 const InstructionsState &S, const EdgeInfo &EI);
5414
5415 /// Allocates schedule data chunk.
5416 ScheduleData *allocateScheduleDataChunks();
5417
5418 /// Extends the scheduling region so that V is inside the region.
5419 /// \returns true if the region size is within the limit.
5420 bool extendSchedulingRegion(Value *V, const InstructionsState &S);
5421
5422 /// Initialize the ScheduleData structures for new instructions in the
5423 /// scheduling region.
5424 void initScheduleData(Instruction *FromI, Instruction *ToI,
5425 ScheduleData *PrevLoadStore,
5426 ScheduleData *NextLoadStore);
5427
5428 /// Updates the dependency information of a bundle and of all instructions/
5429 /// bundles which depend on the original bundle.
5430 void calculateDependencies(ScheduleBundle &Bundle, bool InsertInReadyList,
5431 BoUpSLP *SLP,
5432 const SmallPtrSetImpl<Value *> &ExpandedOps,
5433 ArrayRef<ScheduleData *> ControlDeps = {});
5434
5435 /// Sets all instruction in the scheduling region to un-scheduled.
5436 void resetSchedule();
5437
5438 BasicBlock *BB;
5439
5440 /// Simple memory allocation for ScheduleData.
5442
5443 /// The size of a ScheduleData array in ScheduleDataChunks.
5444 int ChunkSize;
5445
5446 /// The allocator position in the current chunk, which is the last entry
5447 /// of ScheduleDataChunks.
5448 int ChunkPos;
5449
5450 /// Attaches ScheduleData to Instruction.
5451 /// Note that the mapping survives during all vectorization iterations, i.e.
5452 /// ScheduleData structures are recycled.
5453 SmallDenseMap<Instruction *, ScheduleData *> ScheduleDataMap;
5454
5455 /// Attaches ScheduleCopyableData to EdgeInfo (UserTreeEntry + operand
5456 /// number) and the operand instruction, represented as copyable element.
5457 SmallDenseMap<std::pair<EdgeInfo, const Value *>,
5458 std::unique_ptr<ScheduleCopyableData>>
5459 ScheduleCopyableDataMap;
5460
5461 /// Represents mapping between instruction and all related
5462 /// ScheduleCopyableData (for all uses in the tree, represenedt as copyable
5463 /// element). The SLP tree may contain several representations of the same
5464 /// instruction.
5465 SmallDenseMap<const Instruction *, SmallVector<ScheduleCopyableData *>>
5466 ScheduleCopyableDataMapByInst;
5467
5468 /// Represents mapping between user value and operand number, the operand
5469 /// value and all related ScheduleCopyableData. The relation is 1:n, because
5470 /// the same user may refernce the same operand in different tree entries
5471 /// and the operand may be modelled by the different copyable data element.
5472 SmallDenseMap<std::pair<std::pair<const Value *, unsigned>, const Value *>,
5474 ScheduleCopyableDataMapByInstUser;
5475
5476 /// Represents mapping between instruction and all related
5477 /// ScheduleCopyableData. It represents the mapping between the actual
5478 /// instruction and the last copyable data element in the chain. E.g., if
5479 /// the graph models the following instructions:
5480 /// %0 = non-add instruction ...
5481 /// ...
5482 /// %4 = add %3, 1
5483 /// %5 = add %4, 1
5484 /// %6 = insertelement poison, %0, 0
5485 /// %7 = insertelement %6, %5, 1
5486 /// And the graph is modeled as:
5487 /// [%5, %0] -> [%4, copyable %0 <0> ] -> [%3, copyable %0 <1> ]
5488 /// -> [1, 0] -> [%1, 0]
5489 ///
5490 /// this map will map %0 only to the copyable element <1>, which is the last
5491 /// user (direct user of the actual instruction). <0> uses <1>, so <1> will
5492 /// keep the map to <0>, not the %0.
5493 SmallDenseMap<const Instruction *,
5494 SmallSetVector<ScheduleCopyableData *, 4>>
5495 ScheduleCopyableDataMapByUsers;
5496
5497 /// Attaches ScheduleBundle to Instruction.
5498 SmallDenseMap<Instruction *, SmallVector<ScheduleBundle *>>
5499 ScheduledBundles;
5500 /// The list of ScheduleBundles.
5501 SmallVector<std::unique_ptr<ScheduleBundle>> ScheduledBundlesList;
5502
5503 /// The ready-list for scheduling (only used for the dry-run).
5504 SetVector<ScheduleEntity *> ReadyInsts;
5505
5506 /// The first instruction of the scheduling region.
5507 Instruction *ScheduleStart = nullptr;
5508
5509 /// The first instruction _after_ the scheduling region.
5510 Instruction *ScheduleEnd = nullptr;
5511
5512 /// The first memory accessing instruction in the scheduling region
5513 /// (can be null).
5514 ScheduleData *FirstLoadStoreInRegion = nullptr;
5515
5516 /// The last memory accessing instruction in the scheduling region
5517 /// (can be null).
5518 ScheduleData *LastLoadStoreInRegion = nullptr;
5519
5520 /// Is there an llvm.stacksave or llvm.stackrestore in the scheduling
5521 /// region? Used to optimize the dependence calculation for the
5522 /// common case where there isn't.
5523 bool RegionHasStackSave = false;
5524
5525 /// The current size of the scheduling region.
5526 int ScheduleRegionSize = 0;
5527
5528 /// The maximum size allowed for the scheduling region.
5529 int ScheduleRegionSizeLimit = ScheduleRegionSizeBudget;
5530
5531 /// Operands that are modeled as copyable elements in a previously built
5532 /// vectorized node and that are used directly by another,
5533 /// not-yet-registered node sharing a schedulable instruction with it. Their
5534 /// direct dependencies must be recomputed at the next bundle scheduling,
5535 /// when the new node is already registered in the tree, so that the direct
5536 /// use is accounted for. If the new node is the last scheduled bundle and
5537 /// no further scheduling consumes this list, the leftover entries are
5538 /// dropped on the next region reset and the dependencies are recomputed
5539 /// against the full tree in scheduleBlock instead. A set is used to avoid
5540 /// recomputing the same operand more than once.
5541 SmallSetVector<ScheduleData *, 8> RecalcCopyableOperandDeps;
5542
5543 /// Ordered pairs (Src, Dst) of memory instructions whose may-alias
5544 /// dependency has been dropped in favor of a runtime alias check.
5545 SmallDenseSet<std::pair<Instruction *, Instruction *>, 8> IgnoredMemDeps;
5546
5547 /// The ID of the scheduling region. For a new vectorization iteration this
5548 /// is incremented which "removes" all ScheduleData from the region.
5549 /// Make sure that the initial SchedulingRegionID is greater than the
5550 /// initial SchedulingRegionID in ScheduleData (which is 0).
5551 int SchedulingRegionID = 1;
5552 };
5553
5554 /// Attaches the BlockScheduling structures to basic blocks.
5555 MapVector<BasicBlock *, std::unique_ptr<BlockScheduling>> BlocksSchedules;
5556
5557 /// Performs the "real" scheduling. Done before vectorization is actually
5558 /// performed in a basic block.
5559 void scheduleBlock(const BoUpSLP &R, BlockScheduling *BS);
5560
5561 /// List of users to ignore during scheduling and that don't need extracting.
5562 const SmallDenseSet<Value *> *UserIgnoreList = nullptr;
5563
5564 /// Narrowed reduction chain instructions, dropped together with the
5565 /// reduction. Subset of UserIgnoreList.
5566 SmallPtrSet<Value *, 4> NarrowedChainInsts;
5567
5568 /// A DenseMapInfo implementation for holding DenseMaps and DenseSets of
5569 /// sorted SmallVectors of unsigned.
5570 struct OrdersTypeDenseMapInfo {
5571 static unsigned getHashValue(const OrdersType &V) {
5572 return static_cast<unsigned>(hash_combine_range(V));
5573 }
5574
5575 static bool isEqual(const OrdersType &LHS, const OrdersType &RHS) {
5576 return LHS == RHS;
5577 }
5578 };
5579
5580 // Analysis and block reference.
5581 Function *F;
5582 ScalarEvolution *SE;
5583 TargetTransformInfo *TTI;
5584 TargetLibraryInfo *TLI;
5585 LoopInfo *LI;
5586 DominatorTree *DT;
5587 AssumptionCache *AC;
5588 DemandedBits *DB;
5589 const DataLayout *DL;
5590 OptimizationRemarkEmitter *ORE;
5591 /// Cached cost-model mode for this function.
5592 /// If -Os/-Oz, use CodeSize. Otherwise use RecipThroughput.
5594
5595 unsigned MaxVecRegSize; // This is set by TTI or overridden by cl::opt.
5596 unsigned MinVecRegSize; // Set by cl::opt (default: 128).
5597
5598 /// Instruction builder to construct the vectorized tree.
5599 IRBuilder<TargetFolder> Builder;
5600
5601 /// A map of scalar integer values to the smallest bit width with which they
5602 /// can legally be represented. The values map to (width, signed) pairs,
5603 /// where "width" indicates the minimum bit width and "signed" is True if the
5604 /// value must be signed-extended, rather than zero-extended, back to its
5605 /// original width.
5606 DenseMap<const TreeEntry *, std::pair<uint64_t, bool>> MinBWs;
5607
5608 /// Final size of the reduced vector, if the current graph represents the
5609 /// input for the reduction and it was possible to narrow the size of the
5610 /// reduction.
5611 unsigned ReductionBitWidth = 0;
5612
5613 /// Canonical graph size before the transformations.
5614 unsigned BaseGraphSize = 1;
5615
5616 /// If the tree contains any zext/sext/trunc nodes, contains max-min pair of
5617 /// type sizes, used in the tree.
5618 std::optional<std::pair<unsigned, unsigned>> CastMaxMinBWSizes;
5619
5620 /// Indices of the vectorized nodes, which supposed to be the roots of the new
5621 /// bitwidth analysis attempt, like trunc, IToFP or ICmp.
5622 DenseSet<unsigned> ExtraBitWidthNodes;
5623};
5624
5625template <> struct llvm::DenseMapInfo<BoUpSLP::EdgeInfo> {
5628 static unsigned getHashValue(const BoUpSLP::EdgeInfo &Val) {
5629 return detail::combineHashValue(FirstInfo::getHashValue(Val.UserTE),
5630 SecondInfo::getHashValue(Val.EdgeIdx));
5631 }
5632
5633 static bool isEqual(const BoUpSLP::EdgeInfo &LHS,
5634 const BoUpSLP::EdgeInfo &RHS) {
5635 return LHS == RHS;
5636 }
5637};
5638
5639template <> struct llvm::GraphTraits<BoUpSLP *> {
5640 using TreeEntry = BoUpSLP::TreeEntry;
5641
5642 /// NodeRef has to be a pointer per the GraphWriter.
5644
5645 using ContainerTy = BoUpSLP::TreeEntry::VecTreeTy;
5646
5647 /// Add the VectorizableTree to the index iterator to be able to return
5648 /// TreeEntry pointers.
5650 : public iterator_adaptor_base<
5651 ChildIteratorType, SmallVector<BoUpSLP::EdgeInfo, 1>::iterator> {
5653
5657
5658 NodeRef operator*() { return I->UserTE; }
5659 };
5660
5661 static NodeRef getEntryNode(BoUpSLP &R) { return &R.getRootNode(); }
5662
5664 return {&N->UserTreeIndex, N->Container};
5665 }
5666
5668 return {&N->UserTreeIndex + 1, N->Container};
5669 }
5670
5671 /// For the node iterator we just need to turn the TreeEntry iterator into a
5672 /// TreeEntry* iterator so that it dereferences to NodeRef.
5674 using ItTy = ContainerTy::iterator;
5675 ItTy It;
5676
5677 public:
5678 nodes_iterator(const ItTy &It2) : It(It2) {}
5679 NodeRef operator*() { return It->get(); }
5681 ++It;
5682 return *this;
5683 }
5684 bool operator!=(const nodes_iterator &N2) const { return N2.It != It; }
5685 };
5686
5688 return nodes_iterator(R->VectorizableTree.begin());
5689 }
5690
5692 return nodes_iterator(R->VectorizableTree.end());
5693 }
5694
5695 static unsigned size(BoUpSLP *R) { return R->VectorizableTree.size(); }
5696};
5697
5698template <>
5700 using TreeEntry = BoUpSLP::TreeEntry;
5701
5702 DOTGraphTraits(bool IsSimple = false) : DefaultDOTGraphTraits(IsSimple) {}
5703
5704 std::string getNodeLabel(const TreeEntry *Entry, const BoUpSLP *R) {
5705 std::string Str;
5706 raw_string_ostream OS(Str);
5707 OS << Entry->Idx << ".\n";
5708 if (isSplat(Entry->Scalars))
5709 OS << "<splat> ";
5710 for (auto *V : Entry->Scalars) {
5711 OS << *V;
5712 if (llvm::any_of(R->ExternalUses, [&](const BoUpSLP::ExternalUser &EU) {
5713 return EU.Scalar == V;
5714 }))
5715 OS << " <extract>";
5716 OS << "\n";
5717 }
5718 return Str;
5719 }
5720
5721 static std::string getNodeAttributes(const TreeEntry *Entry,
5722 const BoUpSLP *) {
5723 if (Entry->isGather())
5724 return "color=red";
5725 if (Entry->State == TreeEntry::ScatterVectorize ||
5726 Entry->State == TreeEntry::StridedVectorize ||
5727 Entry->State == TreeEntry::ExpandVectorize ||
5728 Entry->State == TreeEntry::CompressVectorize ||
5729 Entry->State == TreeEntry::BlendedLoadVectorize)
5730 return "color=blue";
5731 return "";
5732 }
5733};
5734
5737 for (auto *I : DeletedInstructions) {
5738 if (!I->getParent()) {
5739 // Temporarily insert instruction back to erase them from parent and
5740 // memory later.
5741 if (isa<PHINode>(I))
5742 // Phi nodes must be the very first instructions in the block.
5743 I->insertBefore(F->getEntryBlock(),
5744 F->getEntryBlock().getFirstNonPHIIt());
5745 else
5746 I->insertBefore(F->getEntryBlock().getTerminator()->getIterator());
5747 continue;
5748 }
5749 for (Use &U : I->operands()) {
5750 auto *Op = dyn_cast<Instruction>(U.get());
5751 if (Op && !DeletedInstructions.count(Op) && Op->hasOneUser() &&
5753 DeadInsts.emplace_back(Op);
5754 }
5755 I->dropAllReferences();
5756 }
5757 for (auto *I : DeletedInstructions) {
5758 assert(I->use_empty() &&
5759 "trying to erase instruction with users.");
5760 I->eraseFromParent();
5761 }
5762
5763 // Cleanup any dead scalar code feeding the vectorized instructions
5765
5766#ifdef EXPENSIVE_CHECKS
5767 // If we could guarantee that this call is not extremely slow, we could
5768 // remove the ifdef limitation (see PR47712).
5769 assert(!verifyFunction(*F, &dbgs()));
5770#endif
5771}
5772
5773/// Reorders the given \p Reuses mask according to the given \p Mask. \p Reuses
5774/// contains original mask for the scalars reused in the node. Procedure
5775/// transform this mask in accordance with the given \p Mask.
5777 assert(!Mask.empty() && Reuses.size() == Mask.size() &&
5778 "Expected non-empty mask.");
5779 SmallVector<int> Prev(Reuses.begin(), Reuses.end());
5780 Prev.swap(Reuses);
5781 for (unsigned I = 0, E = Prev.size(); I < E; ++I)
5782 if (Mask[I] != PoisonMaskElem)
5783 Reuses[Mask[I]] = Prev[I];
5784}
5785
5786/// Reorders the given \p Order according to the given \p Mask. \p Order - is
5787/// the original order of the scalars. Procedure transforms the provided order
5788/// in accordance with the given \p Mask. If the resulting \p Order is just an
5789/// identity order, \p Order is cleared.
5791 bool BottomOrder = false) {
5792 assert(!Mask.empty() && "Expected non-empty mask.");
5793 unsigned Sz = Mask.size();
5794 if (BottomOrder) {
5795 SmallVector<unsigned> PrevOrder;
5796 if (Order.empty()) {
5797 PrevOrder.resize(Sz);
5798 std::iota(PrevOrder.begin(), PrevOrder.end(), 0);
5799 } else {
5800 PrevOrder.swap(Order);
5801 }
5802 Order.assign(Sz, Sz);
5803 for (unsigned I = 0; I < Sz; ++I)
5804 if (Mask[I] != PoisonMaskElem)
5805 Order[I] = PrevOrder[Mask[I]];
5806 if (all_of(enumerate(Order), [&](const auto &Data) {
5807 return Data.value() == Sz || Data.index() == Data.value();
5808 })) {
5809 Order.clear();
5810 return;
5811 }
5812 fixupOrderingIndices(Order);
5813 return;
5814 }
5815 SmallVector<int> MaskOrder;
5816 if (Order.empty()) {
5817 MaskOrder.resize(Sz);
5818 std::iota(MaskOrder.begin(), MaskOrder.end(), 0);
5819 } else {
5820 inversePermutation(Order, MaskOrder);
5821 }
5822 reorderReuses(MaskOrder, Mask);
5823 if (ShuffleVectorInst::isIdentityMask(MaskOrder, Sz)) {
5824 Order.clear();
5825 return;
5826 }
5827 Order.assign(Sz, Sz);
5828 for (unsigned I = 0; I < Sz; ++I)
5829 if (MaskOrder[I] != PoisonMaskElem)
5830 Order[MaskOrder[I]] = I;
5831 fixupOrderingIndices(Order);
5832}
5833
5834std::optional<BoUpSLP::OrdersType>
5835BoUpSLP::findReusedOrderedScalars(const BoUpSLP::TreeEntry &TE,
5836 bool TopToBottom, bool IgnoreReorder) {
5837 assert(TE.isGather() && "Expected gather node only.");
5838 // Try to find subvector extract/insert patterns and reorder only such
5839 // patterns.
5840 SmallVector<Value *> GatheredScalars(TE.Scalars.begin(), TE.Scalars.end());
5841 Type *ScalarTy = GatheredScalars.front()->getType();
5842 size_t NumScalars = GatheredScalars.size();
5843 if (!isValidElementType(ScalarTy))
5844 return std::nullopt;
5845 auto *VecTy = getWidenedType(ScalarTy, NumScalars);
5846 unsigned NumParts = getNumberOfParts(VecTy, ScalarTy, NumScalars);
5847 SmallVector<int> ExtractMask;
5848 SmallVector<int> Mask;
5851 tryToGatherExtractElements(GatheredScalars, ExtractMask, NumParts);
5853 isGatherShuffledEntry(&TE, GatheredScalars, Mask, Entries, NumParts,
5854 /*ForOrder=*/true);
5855 // No shuffled operands - ignore.
5856 if (GatherShuffles.empty() && ExtractShuffles.empty())
5857 return std::nullopt;
5858 OrdersType CurrentOrder(NumScalars, NumScalars);
5859 if (GatherShuffles.size() == 1 &&
5860 *GatherShuffles.front() == TTI::SK_PermuteSingleSrc &&
5861 Entries.front().front()->isSame(TE.Scalars)) {
5862 // If the full matched node in whole tree rotation - no need to consider the
5863 // matching order, rotating the whole tree.
5864 if (TopToBottom)
5865 return std::nullopt;
5866 // No need to keep the order for the same user node.
5867 if (Entries.front().front()->UserTreeIndex.UserTE ==
5868 TE.UserTreeIndex.UserTE)
5869 return std::nullopt;
5870 // No need to keep the order for the matched root node, if it can be freely
5871 // reordered.
5872 if (!IgnoreReorder && Entries.front().front()->Idx == 0)
5873 return std::nullopt;
5874 // If shuffling 2 elements only and the matching node has reverse reuses -
5875 // no need to count order, both work fine.
5876 if (!Entries.front().front()->ReuseShuffleIndices.empty() &&
5877 TE.getVectorFactor() == 2 && Mask.size() == 2 &&
5878 any_of(enumerate(Entries.front().front()->ReuseShuffleIndices),
5879 [](const auto &P) {
5880 return P.value() % 2 != static_cast<int>(P.index()) % 2;
5881 }))
5882 return std::nullopt;
5883
5884 // Perfect match in the graph, will reuse the previously vectorized
5885 // node. Cost is 0.
5886 std::iota(CurrentOrder.begin(), CurrentOrder.end(), 0);
5887 return CurrentOrder;
5888 }
5889 auto IsSplatMask = [](ArrayRef<int> Mask) {
5890 int SingleElt = PoisonMaskElem;
5891 return all_of(Mask, [&](int I) {
5892 if (SingleElt == PoisonMaskElem && I != PoisonMaskElem)
5893 SingleElt = I;
5894 return I == PoisonMaskElem || I == SingleElt;
5895 });
5896 };
5897 // Exclusive broadcast mask - ignore.
5898 if ((ExtractShuffles.empty() && IsSplatMask(Mask) &&
5899 (Entries.size() != 1 ||
5900 Entries.front().front()->ReorderIndices.empty())) ||
5901 (GatherShuffles.empty() && IsSplatMask(ExtractMask)))
5902 return std::nullopt;
5903 SmallBitVector ShuffledSubMasks(NumParts);
5904 auto TransformMaskToOrder = [&](MutableArrayRef<unsigned> CurrentOrder,
5905 ArrayRef<int> Mask, int PartSz, int NumParts,
5906 function_ref<unsigned(unsigned)> GetVF) {
5907 for (int I : seq<int>(NumParts)) {
5908 if (ShuffledSubMasks.test(I))
5909 continue;
5910 const int VF = GetVF(I);
5911 if (VF == 0)
5912 continue;
5913 unsigned Limit = getNumElems(CurrentOrder.size(), PartSz, I);
5914 MutableArrayRef<unsigned> Slice = CurrentOrder.slice(I * PartSz, Limit);
5915 // Shuffle of at least 2 vectors - ignore.
5916 if (any_of(Slice, not_equal_to(NumScalars))) {
5917 llvm::fill(Slice, NumScalars);
5918 ShuffledSubMasks.set(I);
5919 continue;
5920 }
5921 // Try to include as much elements from the mask as possible.
5922 int FirstMin = INT_MAX;
5923 int SecondVecFound = false;
5924 for (int K : seq<int>(Limit)) {
5925 int Idx = Mask[I * PartSz + K];
5926 if (Idx == PoisonMaskElem) {
5927 Value *V = GatheredScalars[I * PartSz + K];
5928 if (isConstant(V) && !isa<PoisonValue>(V)) {
5929 SecondVecFound = true;
5930 break;
5931 }
5932 continue;
5933 }
5934 if (Idx < VF) {
5935 if (FirstMin > Idx)
5936 FirstMin = Idx;
5937 } else {
5938 SecondVecFound = true;
5939 break;
5940 }
5941 }
5942 FirstMin = (FirstMin / PartSz) * PartSz;
5943 // Shuffle of at least 2 vectors - ignore.
5944 if (SecondVecFound) {
5945 llvm::fill(Slice, NumScalars);
5946 ShuffledSubMasks.set(I);
5947 continue;
5948 }
5949 for (int K : seq<int>(Limit)) {
5950 int Idx = Mask[I * PartSz + K];
5951 if (Idx == PoisonMaskElem)
5952 continue;
5953 Idx -= FirstMin;
5954 if (Idx >= PartSz) {
5955 // Cross-part / second-vector reference: this slice cannot be
5956 // ordered as a single first-vector permutation, give up.
5957 SecondVecFound = true;
5958 break;
5959 }
5960 // For the last partial slice, Limit < PartSz and Idx in [Limit,
5961 // PartSz) addresses the unused padded tail (no scalar at that
5962 // position). Skip the write but keep ordering the remaining K's.
5963 if (static_cast<unsigned>(I * PartSz + Idx) >= CurrentOrder.size())
5964 continue;
5965 if (CurrentOrder[I * PartSz + Idx] >
5966 static_cast<unsigned>(I * PartSz + K) &&
5967 CurrentOrder[I * PartSz + Idx] !=
5968 static_cast<unsigned>(I * PartSz + Idx))
5969 CurrentOrder[I * PartSz + Idx] = I * PartSz + K;
5970 }
5971 // Shuffle of at least 2 vectors - ignore.
5972 if (SecondVecFound) {
5973 llvm::fill(Slice, NumScalars);
5974 ShuffledSubMasks.set(I);
5975 continue;
5976 }
5977 }
5978 };
5979 int PartSz = getPartNumElems(NumScalars, NumParts);
5980 if (!ExtractShuffles.empty())
5981 TransformMaskToOrder(
5982 CurrentOrder, ExtractMask, PartSz, NumParts, [&](unsigned I) {
5983 if (I >= ExtractShuffles.size() || !ExtractShuffles[I])
5984 return 0U;
5985 unsigned VF = 0;
5986 unsigned Sz = getNumElems(TE.getVectorFactor(), PartSz, I);
5987 for (unsigned Idx : seq<unsigned>(Sz)) {
5988 int K = I * PartSz + Idx;
5989 if (static_cast<unsigned>(K) >= ExtractMask.size())
5990 break;
5991 if (ExtractMask[K] == PoisonMaskElem)
5992 continue;
5993 if (!TE.ReuseShuffleIndices.empty())
5994 K = TE.ReuseShuffleIndices[K];
5995 if (K == PoisonMaskElem)
5996 continue;
5997 if (!TE.ReorderIndices.empty())
5998 K = std::distance(TE.ReorderIndices.begin(),
5999 find(TE.ReorderIndices, K));
6000 auto *EI = dyn_cast<ExtractElementInst>(TE.Scalars[K]);
6001 if (!EI)
6002 continue;
6003 VF = std::max(VF, EI->getVectorOperandType()
6004 ->getElementCount()
6005 .getKnownMinValue());
6006 }
6007 return VF;
6008 });
6009 // Check special corner case - single shuffle of the same entry.
6010 if (GatherShuffles.size() == 1 && NumParts != 1) {
6011 if (ShuffledSubMasks.any())
6012 return std::nullopt;
6013 PartSz = NumScalars;
6014 NumParts = 1;
6015 }
6016 if (!Entries.empty())
6017 TransformMaskToOrder(CurrentOrder, Mask, PartSz, NumParts, [&](unsigned I) {
6018 if (I >= GatherShuffles.size() || !GatherShuffles[I])
6019 return 0U;
6020 return std::max(Entries[I].front()->getVectorFactor(),
6021 Entries[I].back()->getVectorFactor());
6022 });
6023 unsigned NumUndefs = count(CurrentOrder, NumScalars);
6024 if (ShuffledSubMasks.all() || (NumScalars > 2 && NumUndefs >= NumScalars / 2))
6025 return std::nullopt;
6026 return std::move(CurrentOrder);
6027}
6028
6029static bool arePointersCompatible(Value *Ptr1, Value *Ptr2,
6030 const TargetLibraryInfo &TLI,
6031 bool CompareOpcodes = true) {
6034 return false;
6035 auto *GEP1 = dyn_cast<GetElementPtrInst>(Ptr1);
6036 auto *GEP2 = dyn_cast<GetElementPtrInst>(Ptr2);
6037 return (!GEP1 || GEP1->getNumOperands() == 2) &&
6038 (!GEP2 || GEP2->getNumOperands() == 2) &&
6039 (((!GEP1 || isConstant(GEP1->getOperand(1))) &&
6040 (!GEP2 || isConstant(GEP2->getOperand(1)))) ||
6041 !CompareOpcodes ||
6042 (GEP1 && GEP2 &&
6043 getSameOpcode({GEP1->getOperand(1), GEP2->getOperand(1)}, TLI)));
6044}
6045
6046/// Calculates minimal alignment as a common alignment.
6047template <typename T>
6049 Align CommonAlignment = cast<T>(VL.consume_front())->getAlign();
6050 for (Value *V : VL)
6051 CommonAlignment = std::min(CommonAlignment, cast<T>(V)->getAlign());
6052 return CommonAlignment;
6053}
6054
6055/// Check if \p Order represents reverse order.
6057 assert(!Order.empty() &&
6058 "Order is empty. Please check it before using isReverseOrder.");
6059 unsigned Sz = Order.size();
6060 return all_of(enumerate(Order), [&](const auto &Pair) {
6061 return Pair.value() == Sz || Sz - Pair.index() - 1 == Pair.value();
6062 });
6063}
6064
6065/// Checks if the provided list of pointers \p Pointers represents the strided
6066/// pointers for type ElemTy. If they are not, nullptr is returned.
6067/// Otherwise, SCEV* of the stride value is returned.
6068/// If `PointerOps` can be rearanged into the following sequence:
6069/// ```
6070/// %x + c_0 * stride,
6071/// %x + c_1 * stride,
6072/// %x + c_2 * stride
6073/// ...
6074/// ```
6075/// where each `c_i` is constant. The SCEV of the `stride` will be returned.
6076static const SCEV *calculateRtStride(ArrayRef<Value *> PointerOps, Type *ElemTy,
6077 const DataLayout &DL, ScalarEvolution &SE,
6078 SmallVectorImpl<unsigned> &SortedIndices) {
6080 const SCEV *PtrSCEVLowest = nullptr;
6081 const SCEV *PtrSCEVHighest = nullptr;
6082 // Find lower/upper pointers from the PointerOps (i.e. with lowest and highest
6083 // addresses).
6084 for (Value *Ptr : PointerOps) {
6085 const SCEV *PtrSCEV = SE.getSCEV(Ptr);
6086 if (!PtrSCEV)
6087 return nullptr;
6088 SCEVs.push_back(PtrSCEV);
6089 if (!PtrSCEVLowest && !PtrSCEVHighest) {
6090 PtrSCEVLowest = PtrSCEVHighest = PtrSCEV;
6091 continue;
6092 }
6093 const SCEV *Diff = SE.getMinusSCEV(PtrSCEV, PtrSCEVLowest);
6094 if (isa<SCEVCouldNotCompute>(Diff))
6095 return nullptr;
6096 if (Diff->isNonConstantNegative()) {
6097 PtrSCEVLowest = PtrSCEV;
6098 continue;
6099 }
6100 const SCEV *Diff1 = SE.getMinusSCEV(PtrSCEVHighest, PtrSCEV);
6101 if (isa<SCEVCouldNotCompute>(Diff1))
6102 return nullptr;
6103 if (Diff1->isNonConstantNegative()) {
6104 PtrSCEVHighest = PtrSCEV;
6105 continue;
6106 }
6107 }
6108 // Dist = PtrSCEVHighest - PtrSCEVLowest;
6109 const SCEV *Dist = SE.getMinusSCEV(PtrSCEVHighest, PtrSCEVLowest);
6110 if (isa<SCEVCouldNotCompute>(Dist))
6111 return nullptr;
6112 int Size = DL.getTypeStoreSize(ElemTy);
6113 auto TryGetStride = [&](const SCEV *Dist,
6114 const SCEV *Multiplier) -> const SCEV * {
6115 if (const auto *M = dyn_cast<SCEVMulExpr>(Dist)) {
6116 if (M->getOperand(0) == Multiplier)
6117 return M->getOperand(1);
6118 if (M->getOperand(1) == Multiplier)
6119 return M->getOperand(0);
6120 return nullptr;
6121 }
6122 if (Multiplier == Dist)
6123 return SE.getConstant(Dist->getType(), 1);
6124 return SE.getUDivExactExpr(Dist, Multiplier);
6125 };
6126 // Stride_in_elements = Dist / element_size * (num_elems - 1).
6127 const SCEV *Stride = nullptr;
6128 if (Size != 1 || SCEVs.size() > 1) {
6129 const SCEV *Sz = SE.getConstant(Dist->getType(), Size * (SCEVs.size() - 1));
6130 Stride = TryGetStride(Dist, Sz);
6131 if (!Stride)
6132 return nullptr;
6133 }
6134 if (!Stride || isa<SCEVConstant>(Stride))
6135 return nullptr;
6136 // Iterate through all pointers and check if all distances are
6137 // unique multiple of Stride.
6138 using DistOrdPair = std::pair<int64_t, int>;
6139 auto Compare = llvm::less_first();
6140 std::set<DistOrdPair, decltype(Compare)> Offsets(Compare);
6141 bool IsConsecutive = true;
6142 for (const auto [Idx, PtrSCEV] : enumerate(SCEVs)) {
6143 unsigned Dist = 0;
6144 if (PtrSCEV != PtrSCEVLowest) {
6145 const SCEV *Diff = SE.getMinusSCEV(PtrSCEV, PtrSCEVLowest);
6146 const SCEV *Coeff = TryGetStride(Diff, Stride);
6147 if (!Coeff)
6148 return nullptr;
6149 const auto *SC = dyn_cast<SCEVConstant>(Coeff);
6150 if (!SC || isa<SCEVCouldNotCompute>(SC))
6151 return nullptr;
6152 if (!SE.getMinusSCEV(PtrSCEV, SE.getAddExpr(PtrSCEVLowest,
6153 SE.getMulExpr(Stride, SC)))
6154 ->isZero())
6155 return nullptr;
6156 Dist = SC->getAPInt().getZExtValue();
6157 }
6158 // If the strides are not the same or repeated, we can't vectorize.
6159 if ((Dist / Size) * Size != Dist || (Dist / Size) >= SCEVs.size())
6160 return nullptr;
6161 auto Res = Offsets.emplace(Dist, Idx);
6162 if (!Res.second)
6163 return nullptr;
6164 // Consecutive order if the inserted element is the last one.
6165 IsConsecutive = IsConsecutive && std::next(Res.first) == Offsets.end();
6166 }
6167 SortedIndices.clear();
6168 if (!IsConsecutive) {
6169 // Fill SortedIndices array only if it is non-consecutive.
6170 SortedIndices.resize(PointerOps.size());
6171 for (const auto [Idx, Pair] : enumerate(Offsets))
6172 SortedIndices[Idx] = Pair.second;
6173 }
6174 return Stride;
6175}
6176
6177/// This is similar to TargetTransformInfo::getScalarizationOverhead, but if
6178/// ScalarTy is a FixedVectorType, a vector will be inserted or extracted
6179/// instead of a scalar.
6181 const TargetTransformInfo &TTI, Type *ScalarTy, VectorType *Ty,
6182 const APInt &DemandedElts, bool Insert, bool Extract,
6183 const TTI::TargetCostKind CostKind, bool ForPoisonSrc = true,
6184 ArrayRef<Value *> VL = {},
6187 "ScalableVectorType is not supported.");
6188 assert(getNumElements(ScalarTy) * DemandedElts.getBitWidth() ==
6189 getNumElements(Ty) &&
6190 "Incorrect usage.");
6191 if (auto *VecTy = dyn_cast<FixedVectorType>(ScalarTy)) {
6192 assert(SLPReVec && "Only supported by REVEC.");
6193 // If ScalarTy is FixedVectorType, we should use CreateInsertVector instead
6194 // of CreateInsertElement.
6195 unsigned ScalarTyNumElements = VecTy->getNumElements();
6196 InstructionCost Cost = 0;
6197 for (unsigned I : seq(DemandedElts.getBitWidth())) {
6198 if (!DemandedElts[I])
6199 continue;
6200 if (Insert)
6202 I * ScalarTyNumElements, VecTy);
6203 if (Extract)
6205 I * ScalarTyNumElements, VecTy);
6206 }
6207 return Cost;
6208 }
6209 return TTI.getScalarizationOverhead(Ty, DemandedElts, Insert, Extract,
6210 CostKind, ForPoisonSrc, VL, VIC);
6211}
6212
6213/// This is similar to TargetTransformInfo::getVectorInstrCost, but if ScalarTy
6214/// is a FixedVectorType, a vector will be extracted instead of a scalar.
6216 const TargetTransformInfo &TTI, Type *ScalarTy, unsigned Opcode, Type *Val,
6217 const TTI::TargetCostKind CostKind, unsigned Index, Value *Scalar,
6218 ArrayRef<std::tuple<Value *, User *, int>> ScalarUserAndIdx) {
6219 if (Opcode == Instruction::ExtractElement) {
6220 if (auto *VecTy = dyn_cast<FixedVectorType>(ScalarTy)) {
6221 assert(SLPReVec && "Only supported by REVEC.");
6222 assert(isa<VectorType>(Val) && "Val must be a vector type.");
6224 cast<VectorType>(Val), CostKind, {},
6225 Index * VecTy->getNumElements(), VecTy);
6226 }
6227 }
6228 return TTI.getVectorInstrCost(Opcode, Val, CostKind, Index, Scalar,
6229 ScalarUserAndIdx);
6230}
6231
6232/// This is similar to TargetTransformInfo::getExtractWithExtendCost, but if Dst
6233/// is a FixedVectorType, a vector will be extracted instead of a scalar.
6234static InstructionCost
6236 Type *Dst, VectorType *VecTy, unsigned Index,
6238 if (isVectorizedTy(Dst)) {
6239 assert(SLPReVec && "Only supported by REVEC.");
6240 auto *SubTp = cast<FixedVectorType>(
6243 Index * getNumElements(Dst), SubTp) +
6244 TTI.getCastInstrCost(Opcode, Dst, SubTp, TTI::CastContextHint::None,
6245 CostKind);
6246 }
6247 return TTI.getExtractWithExtendCost(Opcode, Dst, VecTy, Index, CostKind);
6248}
6249
6250/// Creates subvector insert. Generates shuffle using \p Generator or
6251/// using default shuffle.
6253 IRBuilderBase &Builder, Value *Vec, Value *V, unsigned Index,
6254 function_ref<Value *(Value *, Value *, ArrayRef<int>)> Generator = {}) {
6255 if (isa<PoisonValue>(Vec) && isa<PoisonValue>(V))
6256 return Vec;
6257 const unsigned SubVecVF = getNumElements(V->getType());
6258 // Create shuffle, insertvector requires that index is multiple of
6259 // the subvector length.
6260 const unsigned VecVF = getNumElements(Vec->getType());
6262 if (isa<PoisonValue>(Vec)) {
6263 auto *Begin = std::next(Mask.begin(), Index);
6264 std::iota(Begin, std::next(Begin, SubVecVF), 0);
6265 Vec = Builder.CreateShuffleVector(V, Mask);
6266 return Vec;
6267 }
6268 std::iota(Mask.begin(), Mask.end(), 0);
6269 std::iota(std::next(Mask.begin(), Index),
6270 std::next(Mask.begin(), Index + SubVecVF), VecVF);
6271 if (Generator)
6272 return Generator(Vec, V, Mask);
6273 // 1. Resize V to the size of Vec.
6274 SmallVector<int> ResizeMask(VecVF, PoisonMaskElem);
6275 std::iota(ResizeMask.begin(), std::next(ResizeMask.begin(), SubVecVF), 0);
6276 V = Builder.CreateShuffleVector(V, ResizeMask);
6277 // 2. Insert V into Vec.
6278 return Builder.CreateShuffleVector(Vec, V, Mask);
6279}
6280
6281/// Generates subvector extract using \p Generator or using default shuffle.
6283 unsigned SubVecVF, unsigned Index) {
6284 SmallVector<int> Mask(SubVecVF, PoisonMaskElem);
6285 std::iota(Mask.begin(), Mask.end(), Index);
6286 return Builder.CreateShuffleVector(Vec, Mask);
6287}
6288
6289/// Builds compress-like mask for shuffles for the given \p PointerOps, ordered
6290/// with \p Order.
6291/// \return true if the mask represents strided access, false - otherwise.
6293 ArrayRef<unsigned> Order, Type *ScalarTy,
6294 const DataLayout &DL, ScalarEvolution &SE,
6295 SmallVectorImpl<int> &CompressMask) {
6296 const unsigned Sz = PointerOps.size();
6297 CompressMask.assign(Sz, PoisonMaskElem);
6298 // The first element always set.
6299 CompressMask[0] = 0;
6300 // Check if the mask represents strided access.
6301 std::optional<unsigned> Stride = 0;
6302 Value *Ptr0 = Order.empty() ? PointerOps.front() : PointerOps[Order.front()];
6303 for (unsigned I : seq<unsigned>(1, Sz)) {
6304 Value *Ptr = Order.empty() ? PointerOps[I] : PointerOps[Order[I]];
6305 std::optional<int64_t> OptPos =
6306 getPointersDiff(ScalarTy, Ptr0, ScalarTy, Ptr, DL, SE);
6307 if (!OptPos || OptPos > std::numeric_limits<unsigned>::max())
6308 return false;
6309 unsigned Pos = static_cast<unsigned>(*OptPos);
6310 CompressMask[I] = Pos;
6311 if (!Stride)
6312 continue;
6313 if (*Stride == 0) {
6314 *Stride = Pos;
6315 continue;
6316 }
6317 if (Pos != *Stride * I)
6318 Stride.reset();
6319 }
6320 return Stride.has_value();
6321}
6322
6323/// Checks if the \p VL can be transformed to a (masked)load + compress or
6324/// (masked) interleaved load.
6326 ArrayRef<Value *> VL, ArrayRef<Value *> PointerOps,
6329 const DominatorTree &DT, const TargetLibraryInfo &TLI,
6331 const function_ref<bool(Value *)> AreAllUsersVectorized, bool &IsMasked,
6332 unsigned &InterleaveFactor, SmallVectorImpl<int> &CompressMask,
6333 VectorType *&LoadVecTy) {
6334 InterleaveFactor = 0;
6335 Type *ScalarTy = VL.front()->getType();
6336 const size_t Sz = VL.size();
6337 auto *VecTy = cast<VectorType>(getWidenedType(ScalarTy, Sz));
6338 SmallVector<int> Mask;
6339 if (!Order.empty())
6340 inversePermutation(Order, Mask);
6341 // Check external uses.
6342 for (const auto [I, V] : enumerate(VL)) {
6343 if (AreAllUsersVectorized(V))
6344 continue;
6345 InstructionCost ExtractCost =
6346 TTI.getVectorInstrCost(Instruction::ExtractElement, VecTy, CostKind,
6347 Mask.empty() ? I : Mask[I]);
6348 InstructionCost ScalarCost =
6349 TTI.getInstructionCost(cast<Instruction>(V), CostKind);
6350 if (ExtractCost <= ScalarCost)
6351 return false;
6352 }
6353 Value *Ptr0;
6354 Value *PtrN;
6355 if (Order.empty()) {
6356 Ptr0 = PointerOps.front();
6357 PtrN = PointerOps.back();
6358 } else {
6359 Ptr0 = PointerOps[Order.front()];
6360 PtrN = PointerOps[Order.back()];
6361 }
6362 std::optional<int64_t> Diff =
6363 getPointersDiff(ScalarTy, Ptr0, ScalarTy, PtrN, DL, SE);
6364 if (!Diff)
6365 return false;
6366 const size_t MaxRegSize =
6368 .getFixedValue();
6369 // Check for very large distances between elements.
6370 if (*Diff / Sz >= MaxRegSize / 8)
6371 return false;
6372 LoadVecTy = cast<FixedVectorType>(getWidenedType(ScalarTy, *Diff + 1));
6373 auto *LI = cast<LoadInst>(Order.empty() ? VL.front() : VL[Order.front()]);
6374 Align CommonAlignment = LI->getAlign();
6375 SimplifyQuery SQ(
6376 DL, &TLI, &DT, &AC,
6377 cast<LoadInst>(Order.empty() ? VL.back() : VL[Order.back()]));
6378 IsMasked = !isSafeToLoadUnconditionally(Ptr0, LoadVecTy, CommonAlignment, SQ);
6379 if (IsMasked && !TTI.isLegalMaskedLoad(LoadVecTy, CommonAlignment,
6380 LI->getPointerAddressSpace()))
6381 return false;
6382 // TODO: perform the analysis of each scalar load for better
6383 // safe-load-unconditionally analysis.
6384 bool IsStrided =
6385 buildCompressMask(PointerOps, Order, ScalarTy, DL, SE, CompressMask);
6386 assert(CompressMask.size() >= 2 && "At least two elements are required");
6387 SmallVector<Value *> OrderedPointerOps(PointerOps);
6388 if (!Order.empty())
6389 reorderScalars(OrderedPointerOps, Mask);
6390 auto [ScalarGEPCost, VectorGEPCost] =
6391 getGEPCosts(TTI, OrderedPointerOps, OrderedPointerOps.front(),
6392 Instruction::Load, CostKind, ScalarTy, LoadVecTy);
6393 // The cost of scalar loads.
6394 InstructionCost ScalarLoadsCost =
6396 [&](InstructionCost C, Value *V) {
6397 return C + TTI.getInstructionCost(cast<Instruction>(V),
6398 CostKind);
6399 }) +
6400 ScalarGEPCost;
6401 APInt DemandedElts = APInt::getAllOnes(Sz);
6402 InstructionCost GatherCost =
6403 getScalarizationOverhead(TTI, ScalarTy, VecTy, DemandedElts,
6404 /*Insert=*/true,
6405 /*Extract=*/false, CostKind) +
6406 ScalarLoadsCost;
6407 InstructionCost LoadCost = 0;
6408 if (IsMasked) {
6409 LoadCost = TTI.getMemIntrinsicInstrCost(
6410 MemIntrinsicCostAttributes(Intrinsic::masked_load, LoadVecTy,
6411 CommonAlignment,
6412 LI->getPointerAddressSpace()),
6413 CostKind);
6414 } else {
6415 LoadCost =
6416 TTI.getMemoryOpCost(Instruction::Load, LoadVecTy, CommonAlignment,
6417 LI->getPointerAddressSpace(), CostKind);
6418 }
6419 if (IsStrided && !IsMasked && Order.empty()) {
6420 // Check for potential segmented(interleaved) loads.
6421 VectorType *AlignedLoadVecTy = cast<VectorType>(getWidenedType(
6422 ScalarTy, getFullVectorNumberOfElements(TTI, ScalarTy, *Diff + 1)));
6423 SimplifyQuery SQ(DL, &TLI, &DT, &AC, cast<LoadInst>(VL.back()));
6424 if (!isSafeToLoadUnconditionally(Ptr0, AlignedLoadVecTy, CommonAlignment,
6425 SQ))
6426 AlignedLoadVecTy = LoadVecTy;
6427 if (TTI.isLegalInterleavedAccessType(AlignedLoadVecTy, CompressMask[1],
6428 CommonAlignment,
6429 LI->getPointerAddressSpace())) {
6430 InstructionCost InterleavedCost =
6431 VectorGEPCost + TTI.getInterleavedMemoryOpCost(
6432 Instruction::Load, AlignedLoadVecTy,
6433 CompressMask[1], {}, CommonAlignment,
6434 LI->getPointerAddressSpace(), CostKind, IsMasked);
6435 if (InterleavedCost < GatherCost) {
6436 InterleaveFactor = CompressMask[1];
6437 LoadVecTy = AlignedLoadVecTy;
6438 return true;
6439 }
6440 }
6441 }
6442 // Estimating the compression shuffle cost below can be extremely expensive
6443 // for a very wide LoadVecTy, which is split into a large number of vector
6444 // registers (see processShuffleMasks). The shuffle cost is always
6445 // non-negative, so if the load cost alone already reaches the gather cost the
6446 // masked-load-compress cannot be profitable. Bail out before the costly
6447 // shuffle cost estimation in that case.
6448 if (VectorGEPCost + LoadCost >= GatherCost)
6449 return false;
6450 InstructionCost CompressCost = getShuffleCost(
6451 TTI, TTI::SK_PermuteSingleSrc, LoadVecTy, CostKind, CompressMask);
6452 if (!Order.empty()) {
6453 SmallVector<int> NewMask(Sz, PoisonMaskElem);
6454 for (unsigned I : seq<unsigned>(Sz)) {
6455 NewMask[I] = CompressMask[Mask[I]];
6456 }
6457 CompressMask.swap(NewMask);
6458 }
6459 InstructionCost TotalVecCost = VectorGEPCost + LoadCost + CompressCost;
6460 return TotalVecCost < GatherCost;
6461}
6462
6463/// Checks if the \p VL can be transformed to a (masked)load + compress or
6464/// (masked) interleaved load.
6465static bool
6468 const DataLayout &DL, ScalarEvolution &SE,
6469 AssumptionCache &AC, const DominatorTree &DT,
6470 const TargetLibraryInfo &TLI,
6472 const function_ref<bool(Value *)> AreAllUsersVectorized) {
6473 bool IsMasked;
6474 unsigned InterleaveFactor;
6475 SmallVector<int> CompressMask;
6476 VectorType *LoadVecTy;
6477 return isMaskedLoadCompress(VL, PointerOps, Order, TTI, DL, SE, AC, DT, TLI,
6478 CostKind, AreAllUsersVectorized, IsMasked,
6479 InterleaveFactor, CompressMask, LoadVecTy);
6480}
6481
6482/// Checks if the stores \p VL with pointers \p PointerOps can be lowered as a
6483/// single masked store. On success \p StoreVecTy is the widened store type and
6484/// \p ReuseShuffleIndices is the expand mask that places each stored value at
6485/// its element offset from the base (poison in the gaps).
6487 ArrayRef<Value *> VL, ArrayRef<Value *> PointerOps,
6489 const DataLayout &DL, ScalarEvolution &SE, Align CommonAlignment,
6490 SmallVectorImpl<int> &ReuseShuffleIndices, FixedVectorType *&StoreVecTy) {
6491 Type *ScalarTy = cast<StoreInst>(VL.front())->getValueOperand()->getType();
6492 const size_t Sz = VL.size();
6493 // Only simple scalar element types are supported.
6494 if (Sz < 2 || (!ScalarTy->isIntOrPtrTy() && !ScalarTy->isFloatingPointTy()))
6495 return false;
6496 Value *Ptr0 = Order.empty() ? PointerOps.front() : PointerOps[Order.front()];
6497 Value *PtrN = Order.empty() ? PointerOps.back() : PointerOps[Order.back()];
6498 std::optional<int64_t> Diff =
6499 getPointersDiff(ScalarTy, Ptr0, ScalarTy, PtrN, DL, SE);
6500 if (!Diff || *Diff <= 0)
6501 return false;
6502 // Avoid widened vectors with very large gaps between the stored elements.
6503 const unsigned MaxRegSize =
6505 .getFixedValue();
6506 const unsigned ScalarBits = DL.getTypeSizeInBits(ScalarTy).getFixedValue();
6507 if (ScalarBits == 0 ||
6508 static_cast<uint64_t>(*Diff) / Sz >= MaxRegSize / ScalarBits)
6509 return false;
6510 StoreVecTy = cast<FixedVectorType>(getWidenedType(ScalarTy, *Diff + 1));
6511 unsigned AS = cast<StoreInst>(VL.front())->getPointerAddressSpace();
6512 if (!TTI.isLegalMaskedStore(StoreVecTy, CommonAlignment, AS,
6514 return false;
6515 // Build the expand mask: store I (in address-sorted order) is placed at its
6516 // element offset from the base, other widened lanes are poison.
6517 ReuseShuffleIndices.assign(*Diff + 1, PoisonMaskElem);
6518 int64_t Prev = -1;
6519 for (unsigned I : seq<unsigned>(Sz)) {
6520 Value *Ptr = Order.empty() ? PointerOps[I] : PointerOps[Order[I]];
6521 std::optional<int64_t> Off =
6522 getPointersDiff(ScalarTy, Ptr0, ScalarTy, Ptr, DL, SE);
6523 if (!Off || *Off <= Prev || *Off > *Diff)
6524 return false;
6525 ReuseShuffleIndices[*Off] = static_cast<int>(I);
6526 Prev = *Off;
6527 }
6528 return true;
6529}
6530
6531/// Checks if strided loads can be generated out of \p VL loads with pointers \p
6532/// PointerOps:
6533/// 1. Target with strided load support is detected.
6534/// 2. The number of loads is greater than MinProfitableStridedLoads, or the
6535/// potential stride <= MaxProfitableStride and the potential stride is
6536/// power-of-2 (to avoid perf regressions for the very small number of loads)
6537/// and max distance > number of loads, or potential stride is -1.
6538/// 3. The loads are ordered, or number of unordered loads <=
6539/// MaxProfitableUnorderedLoads, or loads are in reversed order. (this check is
6540/// to avoid extra costs for very expensive shuffles).
6541/// 4. Any pointer operand is an instruction with the users outside of the
6542/// current graph (for masked gathers extra extractelement instructions
6543/// might be required).
6545 Align Alignment, const int64_t Diff,
6546 const size_t Sz) const {
6547 if (Diff % (Sz - 1) != 0)
6548 return false;
6549
6550 // Try to generate strided load node.
6551 auto IsAnyPointerUsedOutGraph = any_of(PointerOps, [&](Value *V) {
6552 return isa<Instruction>(V) && any_of(V->users(), [&](User *U) {
6553 return !isVectorized(U) && !MustGather.contains(U);
6554 });
6555 });
6556
6557 const uint64_t AbsoluteDiff = std::abs(Diff);
6558 auto *VecTy = getWidenedType(ScalarTy, Sz);
6559 if (IsAnyPointerUsedOutGraph ||
6560 (AbsoluteDiff > Sz &&
6562 (AbsoluteDiff <= MaxProfitableStride * Sz && AbsoluteDiff % Sz == 0 &&
6563 has_single_bit(AbsoluteDiff / Sz)))) ||
6564 Diff == -(static_cast<int64_t>(Sz) - 1)) {
6565 int64_t Stride = Diff / static_cast<int64_t>(Sz - 1);
6566 if (Diff != Stride * static_cast<int64_t>(Sz - 1))
6567 return false;
6568 if (!TTI->isLegalStridedLoadStore(VecTy, Alignment))
6569 return false;
6570 return true;
6571 }
6572 return false;
6573}
6574
6576 const ArrayRef<Value *> PointerOps, Type *ScalarTy, Align Alignment,
6577 const SmallVectorImpl<unsigned> &SortedIndices, const int64_t Diff,
6578 Value *Ptr0, StridedPtrInfo &SPtrInfo) const {
6579 const size_t Sz = PointerOps.size();
6580 SmallVector<int64_t> SortedOffsetsFromBase(Sz);
6581 // Go through `PointerOps` in sorted order and record offsets from
6582 // PointerOps[0]. We use PointerOps[0] rather than Ptr0 because
6583 // sortPtrAccesses only validates getPointersDiff for pairs relative to
6584 // PointerOps[0]. This is safe since only offset differences are used below.
6585 for (unsigned I : seq<unsigned>(Sz)) {
6586 Value *Ptr =
6587 SortedIndices.empty() ? PointerOps[I] : PointerOps[SortedIndices[I]];
6588 std::optional<int64_t> Offset =
6589 getPointersDiff(ScalarTy, PointerOps[0], ScalarTy, Ptr, *DL, *SE);
6590 assert(Offset && "sortPtrAccesses should have validated this pointer");
6591 SortedOffsetsFromBase[I] = *Offset;
6592 }
6593
6594 // The code below checks that `SortedOffsetsFromBase` looks as follows:
6595 // ```
6596 // [
6597 // (e_{0, 0}, e_{0, 1}, ..., e_{0, GroupSize - 1}), // first group
6598 // (e_{1, 0}, e_{1, 1}, ..., e_{1, GroupSize - 1}), // secon group
6599 // ...
6600 // (e_{NumGroups - 1, 0}, e_{NumGroups - 1, 1}, ..., e_{NumGroups - 1,
6601 // GroupSize - 1}), // last group
6602 // ]
6603 // ```
6604 // The distance between consecutive elements within each group should all be
6605 // the same `StrideWithinGroup`. The distance between the first elements of
6606 // consecutive groups should all be the same `StrideBetweenGroups`.
6607
6608 int64_t StrideWithinGroup =
6609 SortedOffsetsFromBase[1] - SortedOffsetsFromBase[0];
6610 // Determine size of the first group. Later we will check that all other
6611 // groups have the same size.
6612 auto IsEndOfGroupIndex = [=, &SortedOffsetsFromBase](unsigned Idx) {
6613 return SortedOffsetsFromBase[Idx] - SortedOffsetsFromBase[Idx - 1] !=
6614 StrideWithinGroup;
6615 };
6616 auto Indices = seq<unsigned>(1, Sz);
6617 auto FoundIt = llvm::find_if(Indices, IsEndOfGroupIndex);
6618 unsigned GroupSize = FoundIt != Indices.end() ? *FoundIt : Sz;
6619
6620 unsigned VecSz = Sz;
6621 Type *NewScalarTy = ScalarTy;
6622
6623 // Quick detour: at this point we can say what the type of strided load would
6624 // be if all the checks pass. Check if this type is legal for the target.
6625 bool NeedsWidening = Sz != GroupSize;
6626 const uint64_t UnitBitWidth = DL->getTypeSizeInBits(ScalarTy).getFixedValue();
6627 if (NeedsWidening) {
6628 if (Sz % GroupSize != 0)
6629 return false;
6630
6631 if (StrideWithinGroup != 1)
6632 return false;
6633 VecSz = Sz / GroupSize;
6634 NewScalarTy = Type::getIntNTy(SE->getContext(), UnitBitWidth * GroupSize);
6635 } else if (ScalarTy->isVectorTy()) {
6636 NewScalarTy = Type::getIntNTy(SE->getContext(), UnitBitWidth);
6637 }
6638
6639 if (!isStridedLoad(PointerOps, NewScalarTy, Alignment, Diff, VecSz))
6640 return false;
6641
6642 int64_t StrideIntVal = StrideWithinGroup;
6643 if (NeedsWidening) {
6644 // Continue with checking the "shape" of `SortedOffsetsFromBase`.
6645 // Check that the strides between groups are all the same.
6646 unsigned CurrentGroupStartIdx = GroupSize;
6647 int64_t StrideBetweenGroups =
6648 SortedOffsetsFromBase[GroupSize] - SortedOffsetsFromBase[0];
6649 StrideIntVal = StrideBetweenGroups;
6650 for (; CurrentGroupStartIdx < Sz; CurrentGroupStartIdx += GroupSize) {
6651 if (SortedOffsetsFromBase[CurrentGroupStartIdx] -
6652 SortedOffsetsFromBase[CurrentGroupStartIdx - GroupSize] !=
6653 StrideBetweenGroups)
6654 return false;
6655 }
6656
6657 auto CheckGroup = [=](const unsigned StartIdx) -> bool {
6658 auto Indices = seq<unsigned>(StartIdx + 1, Sz);
6659 auto FoundIt = llvm::find_if(Indices, IsEndOfGroupIndex);
6660 unsigned GroupEndIdx = FoundIt != Indices.end() ? *FoundIt : Sz;
6661 return GroupEndIdx - StartIdx == GroupSize;
6662 };
6663 for (unsigned I = 0; I < Sz; I += GroupSize) {
6664 if (!CheckGroup(I))
6665 return false;
6666 }
6667 }
6668
6669 Type *StrideTy = DL->getIndexType(Ptr0->getType());
6670 SPtrInfo.StrideVal = ConstantInt::getSigned(StrideTy, StrideIntVal);
6671 SPtrInfo.Ty = cast<FixedVectorType>(getWidenedType(NewScalarTy, VecSz));
6672 return true;
6673}
6674
6676 Type *BaseTy, Align CommonAlignment,
6677 SmallVectorImpl<unsigned> &SortedIndices,
6678 StridedPtrInfo &SPtrInfo,
6679 bool IsLoad) const {
6680 // If each value in `PointerOps` is of the form `%x + Offset` where `Offset`
6681 // is constant, we partition `PointerOps` sequence into subsequences of
6682 // pointers with the same offset. For each offset we record values from
6683 // `PointerOps` and their indicies in `PointerOps`.
6685 OffsetToPointerOpIdxMap;
6686 // Track to make sure that only VecSz different stride multiples are consumed
6687 // Prevents cases such as:
6688 // 1, x + 0, x + 1, 2x + 0 from being recognized as legal RT strided as there
6689 // are 2 "0" and 2 "1" offsets and a stride of "x" between both offsets
6690 SmallDenseSet<const SCEV *> StrideMultiples;
6691 for (auto [Idx, Ptr] : enumerate(PointerOps)) {
6692 const SCEV *PtrSCEV = SE->getSCEV(Ptr);
6693 if (!PtrSCEV)
6694 return false;
6695
6696 const auto *Add = dyn_cast<SCEVAddExpr>(PtrSCEV);
6697 int64_t Offset = 0;
6698 const SCEV *StrideMultiple = PtrSCEV;
6699 if (Add) {
6700 // `Offset` is non-zero.
6701 for (int I : seq<int>(Add->getNumOperands())) {
6702 const auto *SC = dyn_cast<SCEVConstant>(Add->getOperand(I));
6703 if (!SC)
6704 continue;
6705 Offset = SC->getAPInt().getSExtValue();
6706 if (Offset >= std::numeric_limits<int64_t>::max() - 1) {
6707 Offset = 0;
6708 continue;
6709 }
6710 StrideMultiple = SE->getMinusSCEV(StrideMultiple, SC);
6711 break;
6712 }
6713 }
6714 OffsetToPointerOpIdxMap[Offset].first.push_back(Ptr);
6715 OffsetToPointerOpIdxMap[Offset].second.push_back(Idx);
6716 StrideMultiples.insert(StrideMultiple);
6717 }
6718 unsigned NumOffsets = OffsetToPointerOpIdxMap.size();
6719
6720 // Quick detour: at this point we can say what the type of strided load would
6721 // be if all the checks pass. Check if this type is legal for the target.
6722 const unsigned Sz = PointerOps.size();
6723 unsigned VecSz = Sz;
6724 Type *NewScalarTy = BaseTy;
6725 if (NumOffsets > 1) {
6726 if (Sz % NumOffsets != 0)
6727 return false;
6728 VecSz = Sz / NumOffsets;
6729 }
6730
6731 if (StrideMultiples.size() != VecSz)
6732 return false;
6733
6734 if (NumOffsets > 1 || BaseTy->isVectorTy())
6735 NewScalarTy = Type::getIntNTy(
6736 SE->getContext(),
6737 DL->getTypeSizeInBits(BaseTy).getFixedValue() * NumOffsets);
6738 auto *StridedLoadTy =
6739 cast<FixedVectorType>(getWidenedType(NewScalarTy, VecSz));
6740 unsigned MinProfitableStridedOps =
6742 const unsigned BaseTyNumElts = getNumElements(BaseTy);
6743 if (Sz * BaseTyNumElts < MinProfitableStridedOps ||
6744 !TTI->isTypeLegal(StridedLoadTy) ||
6745 !TTI->isLegalStridedLoadStore(StridedLoadTy, CommonAlignment))
6746 return false;
6747
6748 // Check if the offsets are contiguous and that each group has the required
6749 // size.
6750 SmallVector<int64_t> SortedOffsetsV(NumOffsets);
6751 for (auto [Idx, MapPair] : enumerate(OffsetToPointerOpIdxMap)) {
6752 if (MapPair.second.first.size() != VecSz)
6753 return false;
6754 SortedOffsetsV[Idx] = MapPair.first;
6755 }
6756 sort(SortedOffsetsV);
6757
6758 if (NumOffsets > 1) {
6759 int64_t BaseBytes = DL->getTypeStoreSize(BaseTy);
6760 for (int I : seq<int>(1, SortedOffsetsV.size())) {
6761 if (SortedOffsetsV[I] - SortedOffsetsV[I - 1] != BaseBytes)
6762 return false;
6763 }
6764 }
6765
6766 // Introduce some notation for the explanations below. Let `PointerOps_j`
6767 // denote the subsequence of `PointerOps` with offsets equal to
6768 // `SortedOffsetsV[j]`. Let `SortedIndices_j` be a such that the sequence
6769 // ```
6770 // PointerOps_j[SortedIndices_j[0]],
6771 // PointerOps_j[SortedIndices_j[1]],
6772 // PointerOps_j[SortedIndices_j[2]],
6773 // ...
6774 // ```
6775 // is sorted. Also, let `IndicesInAllPointerOps_j` be the vector
6776 // of indices of the subsequence `PointerOps_j` in all of `PointerOps`,
6777 // i.e `PointerOps_j[i] = PointerOps[IndicesInAllPointerOps_j[i]]`.
6778 // The entire sorted `PointerOps` looks like this:
6779 // ```
6780 // PointerOps_0[SortedIndices_0[0]] = PointerOps[IndicesInAllPointerOps_0[0]],
6781 // PointerOps_1[SortedIndices_1[0]] = PointerOps[IndicesInAllPointerOps_1[0]],
6782 // PointerOps_2[SortedIndices_2[0]] = PointerOps[IndicesInAllPointerOps_2[0]],
6783 // ...
6784 // PointerOps_(NumOffsets - 1)[SortedIndices_(NumOffsets - 1)[0]] =
6785 // PointerOps[IndicesInAllPointerOps_(NumOffsets - 1)[0]],
6786 //
6787 // PointerOps_0[SortedIndices_0[1]] = PointerOps[IndicesInAllPointerOps_0[1]],
6788 // PointerOps_1[SortedIndices_1[1]] = PointerOps[IndicesInAllPointerOps_1[1]],
6789 // PointerOps_2[SortedIndices_2[1]] = PointerOps[IndicesInAllPointerOps_2[1]],
6790 // ...
6791 // PointerOps_(NumOffsets - 1)[SortedIndices_(NumOffsets - 1)[1]] =
6792 // PointerOps[IndicesInAllPointerOps_(NumOffsets - 1)[1]],
6793 //
6794 // PointerOps_0[SortedIndices_0[2]] = PointerOps[IndicesInAllPointerOps_0[2]],
6795 // PointerOps_1[SortedIndices_1[2]] = PointerOps[IndicesInAllPointerOps_1[2]],
6796 // PointerOps_2[SortedIndices_2[2]] = PointerOps[IndicesInAllPointerOps_2[2]],
6797 // ...
6798 // PointerOps_(NumOffsets - 1)[SortedIndices_(NumOffsets - 1)[2]] =
6799 // PointerOps[IndicesInAllPointerOps_(NumOffsets - 1)[2]],
6800 // ...
6801 // ...
6802 // ...
6803 // PointerOps_0[SortedIndices_0[VecSz - 1]] =
6804 // PointerOps[IndicesInAllPointerOps_0[VecSz - 1]],
6805 // PointerOps_1[SortedIndices_1[VecSz - 1]] =
6806 // PointerOps[IndicesInAllPointerOps_1[VecSz - 1]],
6807 // PointerOps_2[SortedIndices_2[VecSz - 1]] =
6808 // PointerOps[IndicesInAllPointerOps_2[VecSz - 1]],
6809 // ...
6810 // PointerOps_(NumOffsets - 1)[SortedIndices_(NumOffsets - 1)[VecSz - 1]] =
6811 // PointerOps[IndicesInAllPointerOps_(NumOffsets - 1)[VecSz - 1]],
6812 // ```
6813 // In order to be able to generate a strided load, for each `PointerOps_j`
6814 // check that the distance between adjacent pointers are all equal to the same
6815 // value (stride).
6816 //
6817 // As we do that, also calculate SortedIndices. Since we should not modify
6818 // `SortedIndices` unless we know that all the checks succeed, record the
6819 // indicies into `SortedIndicesDraft`.
6820 SmallVector<unsigned> SortedIndicesDraft(Sz);
6821
6822 // Given sorted indices for a particular offset (as calculated by
6823 // calculateRtStride), update the `SortedIndicesDraft` for all of PointerOps.
6824 // Let `Offset` be `SortedOffsetsV[OffsetNum]`.
6825 // \param `OffsetNum` the index of `Offset` in `SortedOffsetsV`.
6826 // \param `IndicesInAllPointerOps` vector of indices of the
6827 // subsequence `PointerOps_OffsetNum` in `PointerOps`, i.e. using the above
6828 // notation `IndicesInAllPointerOps = IndicesInAllPointerOps_OffsetNum`.
6829 // \param `SortedIndicesForOffset = SortedIndices_OffsetNum`
6830 auto UpdateSortedIndices =
6831 [&](SmallVectorImpl<unsigned> &SortedIndicesForOffset,
6832 ArrayRef<unsigned> IndicesInAllPointerOps, const int64_t OffsetNum) {
6833 if (SortedIndicesForOffset.empty()) {
6834 SortedIndicesForOffset.resize(IndicesInAllPointerOps.size());
6835 std::iota(SortedIndicesForOffset.begin(),
6836 SortedIndicesForOffset.end(), 0);
6837 }
6838 for (const auto [Num, Idx] : enumerate(SortedIndicesForOffset)) {
6839 SortedIndicesDraft[Num * NumOffsets + OffsetNum] =
6840 IndicesInAllPointerOps[Idx];
6841 }
6842 };
6843
6844 int64_t LowestOffset = SortedOffsetsV[0];
6845 ArrayRef<Value *> PointerOps0 = OffsetToPointerOpIdxMap[LowestOffset].first;
6846
6847 SmallVector<unsigned> SortedIndicesForOffset0;
6848 const SCEV *Stride0 =
6849 calculateRtStride(PointerOps0, BaseTy, *DL, *SE, SortedIndicesForOffset0);
6850 if (!Stride0)
6851 return false;
6852
6853 ArrayRef<unsigned> IndicesInAllPointerOps0 =
6854 OffsetToPointerOpIdxMap[LowestOffset].second;
6855 UpdateSortedIndices(SortedIndicesForOffset0, IndicesInAllPointerOps0, 0);
6856
6857 // Now that we know what the common stride and coefficients has to be check
6858 // the remaining `PointerOps_j`.
6859 SmallVector<unsigned> SortedIndicesForOffset;
6860 for (int J : seq<int>(1, NumOffsets)) {
6861 SortedIndicesForOffset.clear();
6862
6863 int64_t Offset = SortedOffsetsV[J];
6864 ArrayRef<Value *> PointerOpsForOffset =
6865 OffsetToPointerOpIdxMap[Offset].first;
6866 ArrayRef<unsigned> IndicesInAllPointerOps =
6867 OffsetToPointerOpIdxMap[Offset].second;
6868 const SCEV *StrideWithinGroup = calculateRtStride(
6869 PointerOpsForOffset, BaseTy, *DL, *SE, SortedIndicesForOffset);
6870
6871 if (!StrideWithinGroup || StrideWithinGroup != Stride0)
6872 return false;
6873
6874 UpdateSortedIndices(SortedIndicesForOffset, IndicesInAllPointerOps, J);
6875 }
6876
6877 SortedIndices.clear();
6878 SortedIndices = std::move(SortedIndicesDraft);
6879 SPtrInfo.StrideSCEV = Stride0;
6880 SPtrInfo.Ty = StridedLoadTy;
6881 return true;
6882}
6883
6885 ArrayRef<Value *> VL, const Value *VL0, SmallVectorImpl<unsigned> &Order,
6886 SmallVectorImpl<Value *> &PointerOps, StridedPtrInfo &SPtrInfo,
6887 unsigned *BestVF, bool TryRecursiveCheck) const {
6888 // Check that a vectorized load would load the same memory as a scalar
6889 // load. For example, we don't want to vectorize loads that are smaller
6890 // than 8-bit. Even though we have a packed struct {<i2, i2, i2, i2>} LLVM
6891 // treats loading/storing it as an i8 struct. If we vectorize loads/stores
6892 // from such a struct, we read/write packed bits disagreeing with the
6893 // unvectorized version.
6894 if (BestVF)
6895 *BestVF = 0;
6897 return LoadsState::Gather;
6898 Type *ScalarTy = VL0->getType();
6899
6900 if (DL->getTypeSizeInBits(ScalarTy) != DL->getTypeAllocSizeInBits(ScalarTy))
6901 return LoadsState::Gather;
6902
6903 // Make sure all loads in the bundle are simple - we can't vectorize
6904 // atomic or volatile loads.
6905 PointerOps.clear();
6906 const size_t Sz = VL.size();
6907 PointerOps.resize(Sz);
6908 auto *POIter = PointerOps.begin();
6909 for (Value *V : VL) {
6910 auto *L = dyn_cast<LoadInst>(V);
6911 if (!L || !L->isSimple())
6912 return LoadsState::Gather;
6913 *POIter = L->getPointerOperand();
6914 ++POIter;
6915 }
6916
6917 Order.clear();
6918 // Check the order of pointer operands or that all pointers are the same.
6919 bool IsSorted = sortPtrAccesses(PointerOps, ScalarTy, *DL, *SE, Order);
6920
6921 auto *VecTy = dyn_cast<VectorType>(getWidenedType(ScalarTy, Sz));
6922 if (!VecTy)
6923 return LoadsState::Gather;
6924 Align CommonAlignment = computeCommonAlignment<LoadInst>(VL);
6925 // Cache masked gather legality - both the !IsSorted path below and the
6926 // post-branch check use the same VecTy/CommonAlignment, and the underlying
6927 // TTI calls are virtual.
6928 std::optional<bool> MaskedGatherLegal;
6929 auto IsMaskedGatherLegal = [&] {
6930 if (!MaskedGatherLegal)
6931 MaskedGatherLegal =
6932 TTI->isLegalMaskedGather(VecTy, CommonAlignment) &&
6933 !TTI->forceScalarizeMaskedGather(VecTy, CommonAlignment);
6934 return *MaskedGatherLegal;
6935 };
6936 if (!IsSorted) {
6937 // Check for a group of loads, each selecting its address (directly, or
6938 // via a constant-offset GEP) between the same two candidate base
6939 // pointers - the shape if-converted, fully-unrolled loop bodies of the
6940 // form `x = cond ? A[i] : B[i]` take. If found, model it as two masked
6941 // loads (one per candidate) blended by the (vectorized) condition,
6942 // rather than falling back to a gather of the individual scalar loads.
6943 Value *TrueBase = nullptr;
6944 Value *FalseBase = nullptr;
6945 SmallVector<Value *> Conditions;
6946 if (isSelectedBaseLoad(ScalarTy, PointerOps, *DL, TrueBase, FalseBase,
6947 Conditions) &&
6948 TTI->isLegalMaskedLoad(VecTy, CommonAlignment,
6949 cast<LoadInst>(VL0)->getPointerAddressSpace()))
6951
6952 if (analyzeRtStrideCandidate(PointerOps, ScalarTy, CommonAlignment, Order,
6953 SPtrInfo, /*isLoad=*/true))
6955
6956 if (!IsMaskedGatherLegal())
6957 return LoadsState::Gather;
6958
6959 if (!all_of(PointerOps, [&](Value *P) {
6960 return arePointersCompatible(P, PointerOps.front(), *TLI);
6961 }))
6962 return LoadsState::Gather;
6963
6964 } else {
6965 Value *Ptr0;
6966 Value *PtrN;
6967 if (Order.empty()) {
6968 Ptr0 = PointerOps.front();
6969 PtrN = PointerOps.back();
6970 } else {
6971 Ptr0 = PointerOps[Order.front()];
6972 PtrN = PointerOps[Order.back()];
6973 }
6974 // sortPtrAccesses validates getPointersDiff for all pointers relative to
6975 // PointerOps[0], so compute the span using PointerOps[0] as intermediate:
6976 // Diff = offset(PtrN) - offset(Ptr0) relative to PointerOps[0]
6977 std::optional<int64_t> Diff0 =
6978 getPointersDiff(ScalarTy, PointerOps[0], ScalarTy, Ptr0, *DL, *SE);
6979 std::optional<int64_t> DiffN =
6980 getPointersDiff(ScalarTy, PointerOps[0], ScalarTy, PtrN, *DL, *SE);
6981 assert(Diff0 && DiffN &&
6982 "sortPtrAccesses should have validated these pointers");
6983 int64_t Diff = *DiffN - *Diff0;
6984 // Check that the sorted loads are consecutive.
6985 if (static_cast<uint64_t>(Diff) == Sz - 1)
6986 return LoadsState::Vectorize;
6987 if (isMaskedLoadCompress(VL, PointerOps, Order, *TTI, *DL, *SE, *AC, *DT,
6988 *TLI, CostKind, [&](Value *V) {
6989 return areAllUsersVectorized(
6990 cast<Instruction>(V), UserIgnoreList);
6991 }))
6993 Align Alignment =
6994 cast<LoadInst>(Order.empty() ? VL.front() : VL[Order.front()])
6995 ->getAlign();
6996 if (analyzeConstantStrideCandidate(PointerOps, ScalarTy, Alignment, Order,
6997 Diff, Ptr0, SPtrInfo))
6999 }
7000 if (!IsMaskedGatherLegal())
7001 return LoadsState::Gather;
7002 // Correctly identify compare the cost of loads + shuffles rather than
7003 // strided/masked gather loads. Returns true if vectorized + shuffles
7004 // representation is better than just gather.
7005 auto CheckForShuffledLoads = [&, &TTI = *TTI](Align CommonAlignment,
7006 unsigned *BestVF,
7007 bool ProfitableGatherPointers) {
7008 if (BestVF)
7009 *BestVF = 0;
7010 // Compare masked gather cost and loads + insert subvector costs.
7011 auto [ScalarGEPCost, VectorGEPCost] =
7012 getGEPCosts(TTI, PointerOps, PointerOps.front(), Instruction::Load,
7013 CostKind, ScalarTy, VecTy);
7014 // Estimate the cost of masked gather GEP. If not a splat, roughly
7015 // estimate as a buildvector, otherwise estimate as splat.
7016 APInt DemandedElts = APInt::getAllOnes(Sz);
7017 Type *PtrScalarTy = PointerOps.front()->getType()->getScalarType();
7018 auto *PtrVecTy = cast<VectorType>(getWidenedType(PtrScalarTy, Sz));
7019 // Cache the underlying object of PointerOps.front() - it is invariant
7020 // across the per-V comparisons below and getUnderlyingObject walks
7021 // GEP/cast chains.
7022 const Value *FrontUO = getUnderlyingObject(PointerOps.front());
7023 if (static_cast<unsigned>(count_if(
7024 PointerOps, IsaPred<GetElementPtrInst>)) < PointerOps.size() - 1 ||
7025 any_of(PointerOps,
7026 [&](Value *V) { return getUnderlyingObject(V) != FrontUO; }))
7027 VectorGEPCost += getScalarizationOverhead(TTI, PtrScalarTy, PtrVecTy,
7028 DemandedElts, /*Insert=*/true,
7029 /*Extract=*/false, CostKind);
7030 else
7031 VectorGEPCost +=
7033 TTI, PtrScalarTy, PtrVecTy, APInt::getOneBitSet(Sz, 0),
7034 /*Insert=*/true, /*Extract=*/false, CostKind) +
7035 getShuffleCost(TTI, TTI::SK_Broadcast, PtrVecTy, CostKind);
7036 // The cost of scalar loads.
7037 InstructionCost ScalarLoadsCost =
7039 [&](InstructionCost C, Value *V) {
7040 return C + TTI.getInstructionCost(cast<Instruction>(V),
7041 CostKind);
7042 }) +
7043 ScalarGEPCost;
7044 // The cost of masked gather.
7045 InstructionCost MaskedGatherCost =
7046 TTI.getMemIntrinsicInstrCost(
7047 MemIntrinsicCostAttributes(Intrinsic::masked_gather, VecTy,
7049 /*VariableMask=*/false, CommonAlignment),
7050 CostKind) +
7051 (ProfitableGatherPointers ? 0 : VectorGEPCost);
7052 InstructionCost GatherCost =
7053 getScalarizationOverhead(TTI, ScalarTy, VecTy, DemandedElts,
7054 /*Insert=*/true,
7055 /*Extract=*/false, CostKind) +
7056 ScalarLoadsCost;
7057 // The list of loads is small or perform partial check already - directly
7058 // compare masked gather cost and gather cost.
7059 constexpr unsigned ListLimit = 4;
7060 if (!TryRecursiveCheck || VL.size() < ListLimit)
7061 return MaskedGatherCost - GatherCost >= -SLPCostThreshold;
7062
7063 unsigned Sz = DL->getTypeSizeInBits(ScalarTy);
7064 unsigned MinVF = getMinVF(2 * Sz);
7065 DemandedElts.clearAllBits();
7066 // Iterate through possible vectorization factors and check if vectorized +
7067 // shuffles is better than just gather.
7068 for (unsigned VF =
7069 getFloorFullVectorNumberOfElements(TTI, ScalarTy, VL.size() - 1);
7070 VF >= MinVF;
7071 VF = getFloorFullVectorNumberOfElements(TTI, ScalarTy, VF - 1)) {
7073 for (unsigned Cnt = 0, End = VL.size(); Cnt < End; Cnt += VF) {
7074 const unsigned SliceVF = std::min(VF, End - Cnt);
7075 ArrayRef<Value *> Slice = VL.slice(Cnt, SliceVF);
7077 SmallVector<Value *> PointerOps;
7078 LoadsState LS = canVectorizeLoads(Slice, Slice.front(), Order,
7079 PointerOps, SPtrInfo, BestVF,
7080 /*TryRecursiveCheck=*/false);
7081 // Check that the sorted loads are consecutive.
7082 if (LS == LoadsState::Gather) {
7083 if (BestVF) {
7084 DemandedElts.setAllBits();
7085 break;
7086 }
7087 DemandedElts.setBits(Cnt, Cnt + SliceVF);
7088 continue;
7089 }
7090 // If need the reorder - consider as high-cost masked gather for now.
7091 if ((LS == LoadsState::Vectorize ||
7094 !Order.empty() && !isReverseOrder(Order))
7096 States.emplace_back(Cnt, LS);
7097 }
7098 if (DemandedElts.isAllOnes())
7099 // All loads gathered - try smaller VF.
7100 continue;
7101 // Can be vectorized later as a serie of loads/insertelements.
7102 InstructionCost VecLdCost = 0;
7103 if (!DemandedElts.isZero()) {
7104 VecLdCost = getScalarizationOverhead(TTI, ScalarTy, VecTy, DemandedElts,
7105 /*Insert=*/true,
7106 /*Extract=*/false, CostKind) +
7107 ScalarGEPCost;
7108 for (unsigned Idx : seq<unsigned>(VL.size()))
7109 if (DemandedElts[Idx])
7110 VecLdCost +=
7111 TTI.getInstructionCost(cast<Instruction>(VL[Idx]), CostKind);
7112 }
7113 for (const auto &[SliceStart, LS] : States) {
7114 const unsigned SliceVF = std::min<unsigned>(VF, VL.size() - SliceStart);
7115 auto *SubVecTy = cast<VectorType>(getWidenedType(ScalarTy, SliceVF));
7116 auto *LI0 = cast<LoadInst>(VL[SliceStart]);
7117 InstructionCost VectorGEPCost =
7118 (LS == LoadsState::ScatterVectorize && ProfitableGatherPointers)
7119 ? 0
7120 : getGEPCosts(TTI,
7121 ArrayRef(PointerOps).slice(SliceStart, SliceVF),
7122 LI0->getPointerOperand(), Instruction::Load,
7123 CostKind, ScalarTy, SubVecTy)
7124 .second;
7125 if (LS == LoadsState::ScatterVectorize) {
7126 if (static_cast<unsigned>(
7127 count_if(PointerOps, IsaPred<GetElementPtrInst>)) <
7128 PointerOps.size() - 1 ||
7129 any_of(PointerOps, [&](Value *V) {
7130 return getUnderlyingObject(V) != FrontUO;
7131 }))
7132 VectorGEPCost += getScalarizationOverhead(
7133 TTI, ScalarTy, SubVecTy, APInt::getAllOnes(SliceVF),
7134 /*Insert=*/true, /*Extract=*/false, CostKind);
7135 else
7136 VectorGEPCost +=
7138 TTI, ScalarTy, SubVecTy, APInt::getOneBitSet(SliceVF, 0),
7139 /*Insert=*/true, /*Extract=*/false, CostKind) +
7140 getShuffleCost(TTI, TTI::SK_Broadcast, SubVecTy, CostKind);
7141 }
7142 switch (LS) {
7144 VecLdCost +=
7145 TTI.getMemoryOpCost(Instruction::Load, SubVecTy, LI0->getAlign(),
7146 LI0->getPointerAddressSpace(), CostKind,
7148 VectorGEPCost;
7149 break;
7151 VecLdCost += TTI.getMemIntrinsicInstrCost(
7153 Intrinsic::experimental_vp_strided_load,
7154 SubVecTy, LI0->getPointerOperand(),
7155 /*VariableMask=*/false, CommonAlignment),
7156 CostKind) +
7157 VectorGEPCost;
7158 break;
7160 VecLdCost +=
7161 TTI.getMemIntrinsicInstrCost(
7162 MemIntrinsicCostAttributes(Intrinsic::masked_load, SubVecTy,
7163 CommonAlignment,
7164 LI0->getPointerAddressSpace()),
7165 CostKind) +
7166 getShuffleCost(TTI, TTI::SK_PermuteSingleSrc, SubVecTy, CostKind);
7167 break;
7169 VecLdCost += TTI.getMemIntrinsicInstrCost(
7171 Intrinsic::masked_gather, SubVecTy,
7172 LI0->getPointerOperand(),
7173 /*VariableMask=*/false, CommonAlignment),
7174 CostKind) +
7175 VectorGEPCost;
7176 break;
7178 // Two masked loads (one per candidate base) plus a select; no address
7179 // vector is materialized, so VectorGEPCost is skipped.
7180 VecLdCost +=
7181 getBlendedLoadCost(TTI, SubVecTy, CommonAlignment,
7182 LI0->getPointerAddressSpace(), CostKind);
7183 break;
7184 case LoadsState::Gather:
7185 llvm_unreachable("Gathers are not added to States");
7186 }
7187 SmallVector<int> ShuffleMask(VL.size());
7188 const unsigned SliceIdx = SliceStart / VF;
7189 for (int Idx : seq<int>(VL.size()))
7190 ShuffleMask[Idx] = Idx / VF == SliceIdx ? VL.size() + Idx % VF : Idx;
7191 if (SliceStart > 0)
7192 VecLdCost +=
7193 getShuffleCost(TTI, TTI::SK_InsertSubvector, VecTy, CostKind,
7194 ShuffleMask, SliceStart, SubVecTy);
7195 }
7196 // If masked gather cost is higher - better to vectorize, so
7197 // consider it as a gather node. It will be better estimated
7198 // later.
7199 if (MaskedGatherCost >= VecLdCost &&
7200 VecLdCost - GatherCost < -SLPCostThreshold) {
7201 if (BestVF)
7202 *BestVF = VF;
7203 return true;
7204 }
7205 }
7206 return MaskedGatherCost - GatherCost >= -SLPCostThreshold;
7207 };
7208 // TODO: need to improve analysis of the pointers, if not all of them are
7209 // GEPs or have > 2 operands, we end up with a gather node, which just
7210 // increases the cost.
7211 Loop *L = LI->getLoopFor(cast<LoadInst>(VL0)->getParent());
7212 bool ProfitableGatherPointers =
7213 L && Sz > 2 && static_cast<unsigned>(count_if(PointerOps, [L](Value *V) {
7214 return L->isLoopInvariant(V);
7215 })) <= Sz / 2;
7216 if (ProfitableGatherPointers || all_of(PointerOps, [](Value *P) {
7218 return (!GEP && doesNotNeedToBeScheduled(P)) ||
7219 (GEP && GEP->getNumOperands() == 2 &&
7220 isa<Constant, Instruction>(GEP->getOperand(1)));
7221 })) {
7222 // Check if potential masked gather can be represented as series
7223 // of loads + insertsubvectors.
7224 // If masked gather cost is higher - better to vectorize, so
7225 // consider it as a gather node. It will be better estimated
7226 // later.
7227 if (!TryRecursiveCheck || !CheckForShuffledLoads(CommonAlignment, BestVF,
7228 ProfitableGatherPointers))
7230 }
7231
7232 return LoadsState::Gather;
7233}
7234
7236 ArrayRef<BasicBlock *> BBs, Type *ElemTy,
7237 const DataLayout &DL, ScalarEvolution &SE,
7238 SmallVectorImpl<unsigned> &SortedIndices) {
7239 assert(
7240 all_of(VL, [](const Value *V) { return V->getType()->isPointerTy(); }) &&
7241 "Expected list of pointer operands.");
7242 // Map from bases to a vector of (Ptr, Offset, OrigIdx), which we insert each
7243 // Ptr into, sort and return the sorted indices with values next to one
7244 // another.
7246 std::pair<BasicBlock *, Value *>,
7248 Bases;
7249 Bases
7250 .try_emplace(std::make_pair(
7252 .first->second.emplace_back().emplace_back(VL.front(), 0U, 0U);
7253
7254 SortedIndices.clear();
7255 for (auto [Cnt, Ptr] : enumerate(VL.drop_front())) {
7256 auto Key = std::make_pair(BBs[Cnt + 1],
7258 bool Found = any_of(Bases.try_emplace(Key).first->second,
7259 [&, &Cnt = Cnt, &Ptr = Ptr](auto &Base) {
7260 std::optional<int64_t> Diff =
7261 getPointersDiff(ElemTy, std::get<0>(Base.front()),
7262 ElemTy, Ptr, DL, SE,
7263 /*StrictCheck=*/true);
7264 if (!Diff)
7265 return false;
7266
7267 Base.emplace_back(Ptr, *Diff, Cnt + 1);
7268 return true;
7269 });
7270
7271 if (!Found) {
7272 // If we haven't found enough to usefully cluster, return early.
7273 if (Bases.size() > VL.size() / 2 - 1)
7274 return false;
7275
7276 // Not found already - add a new Base
7277 Bases.find(Key)->second.emplace_back().emplace_back(Ptr, 0, Cnt + 1);
7278 }
7279 }
7280
7281 if (Bases.size() == VL.size())
7282 return false;
7283
7284 if (Bases.size() == 1 && (Bases.front().second.size() == 1 ||
7285 Bases.front().second.size() == VL.size()))
7286 return false;
7287
7288 // For each of the bases sort the pointers by Offset and check if any of the
7289 // base become consecutively allocated.
7290 auto ComparePointers = [](Value *Ptr1, Value *Ptr2) {
7291 SmallPtrSet<Value *, 13> FirstPointers;
7292 SmallPtrSet<Value *, 13> SecondPointers;
7293 Value *P1 = Ptr1;
7294 Value *P2 = Ptr2;
7295 unsigned Depth = 0;
7296 while (!FirstPointers.contains(P2) && !SecondPointers.contains(P1)) {
7297 if (P1 == P2 || Depth > RecursionMaxDepth)
7298 return false;
7299 FirstPointers.insert(P1);
7300 SecondPointers.insert(P2);
7301 P1 = getUnderlyingObject(P1, /*MaxLookup=*/1);
7302 P2 = getUnderlyingObject(P2, /*MaxLookup=*/1);
7303 ++Depth;
7304 }
7305 assert((FirstPointers.contains(P2) || SecondPointers.contains(P1)) &&
7306 "Unable to find matching root.");
7307 return FirstPointers.contains(P2) && !SecondPointers.contains(P1);
7308 };
7309 for (auto &Base : Bases) {
7310 for (auto &Vec : Base.second) {
7311 if (Vec.size() > 1) {
7313 int64_t InitialOffset = std::get<1>(Vec[0]);
7314 bool AnyConsecutive =
7315 all_of(enumerate(Vec), [InitialOffset](const auto &P) {
7316 return std::get<1>(P.value()) ==
7317 int64_t(P.index()) + InitialOffset;
7318 });
7319 // Fill SortedIndices array only if it looks worth-while to sort the
7320 // ptrs.
7321 if (!AnyConsecutive)
7322 return false;
7323 }
7324 }
7325 stable_sort(Base.second, [&](const auto &V1, const auto &V2) {
7326 return ComparePointers(std::get<0>(V1.front()), std::get<0>(V2.front()));
7327 });
7328 }
7329
7330 for (auto &T : Bases)
7331 for (const auto &Vec : T.second)
7332 for (const auto &P : Vec)
7333 SortedIndices.push_back(std::get<2>(P));
7334
7335 assert(SortedIndices.size() == VL.size() &&
7336 "Expected SortedIndices to be the size of VL");
7337 return true;
7338}
7339
7340std::optional<BoUpSLP::OrdersType>
7341BoUpSLP::findPartiallyOrderedLoads(const BoUpSLP::TreeEntry &TE) {
7342 assert(TE.isGather() && "Expected gather node only.");
7343 Type *ScalarTy = TE.Scalars[0]->getType();
7344
7346 Ptrs.reserve(TE.Scalars.size());
7348 BBs.reserve(TE.Scalars.size());
7349 for (Value *V : TE.Scalars) {
7350 auto *L = dyn_cast<LoadInst>(V);
7351 if (!L || !L->isSimple())
7352 return std::nullopt;
7353 Ptrs.push_back(L->getPointerOperand());
7354 BBs.push_back(L->getParent());
7355 }
7356
7357 BoUpSLP::OrdersType Order;
7358 if (!LoadEntriesToVectorize.contains(TE.Idx) &&
7359 clusterSortPtrAccesses(Ptrs, BBs, ScalarTy, *DL, *SE, Order))
7360 return std::move(Order);
7361 return std::nullopt;
7362}
7363
7364/// Check if two insertelement instructions are from the same buildvector.
7367 function_ref<Value *(InsertElementInst *)> GetBaseOperand) {
7368 // Instructions must be from the same basic blocks.
7369 if (VU->getParent() != V->getParent())
7370 return false;
7371 // Checks if 2 insertelements are from the same buildvector.
7372 if (VU->getType() != V->getType())
7373 return false;
7374 // Multiple used inserts are separate nodes.
7375 if (!VU->hasOneUse() && !V->hasOneUse())
7376 return false;
7377 auto *IE1 = VU;
7378 auto *IE2 = V;
7379 std::optional<unsigned> Idx1 = getElementIndex(IE1);
7380 std::optional<unsigned> Idx2 = getElementIndex(IE2);
7381 if (Idx1 == std::nullopt || Idx2 == std::nullopt)
7382 return false;
7383 // Go through the vector operand of insertelement instructions trying to find
7384 // either VU as the original vector for IE2 or V as the original vector for
7385 // IE1.
7387 bool IsReusedIdx = false;
7388 do {
7389 if (IE2 == VU && !IE1)
7390 return VU->hasOneUse();
7391 if (IE1 == V && !IE2)
7392 return V->hasOneUse();
7393 if (IE1 && IE1 != V) {
7394 unsigned Idx1 = getElementIndex(IE1).value_or(*Idx2);
7395 IsReusedIdx |= ReusedIdx.test(Idx1);
7396 ReusedIdx.set(Idx1);
7397 if ((IE1 != VU && !IE1->hasOneUse()) || IsReusedIdx)
7398 IE1 = nullptr;
7399 else
7400 IE1 = dyn_cast_or_null<InsertElementInst>(GetBaseOperand(IE1));
7401 }
7402 if (IE2 && IE2 != VU) {
7403 unsigned Idx2 = getElementIndex(IE2).value_or(*Idx1);
7404 IsReusedIdx |= ReusedIdx.test(Idx2);
7405 ReusedIdx.set(Idx2);
7406 if ((IE2 != V && !IE2->hasOneUse()) || IsReusedIdx)
7407 IE2 = nullptr;
7408 else
7409 IE2 = dyn_cast_or_null<InsertElementInst>(GetBaseOperand(IE2));
7410 }
7411 } while (!IsReusedIdx && (IE1 || IE2));
7412 return false;
7413}
7414
7415std::optional<BoUpSLP::OrdersType>
7416BoUpSLP::getReorderingData(const TreeEntry &TE, bool TopToBottom,
7417 bool IgnoreReorder) {
7418 // No need to reorder if need to shuffle reuses, still need to shuffle the
7419 // node.
7420 if (!TE.ReuseShuffleIndices.empty()) {
7421 if (isSplat(TE.Scalars))
7422 return std::nullopt;
7423 // Check if reuse shuffle indices can be improved by reordering.
7424 // For this, check that reuse mask is "clustered", i.e. each scalar values
7425 // is used once in each submask of size <number_of_scalars>.
7426 // Example: 4 scalar values.
7427 // ReuseShuffleIndices mask: 0, 1, 2, 3, 3, 2, 0, 1 - clustered.
7428 // 0, 1, 2, 3, 3, 3, 1, 0 - not clustered, because
7429 // element 3 is used twice in the second submask.
7430 unsigned Sz = TE.Scalars.size();
7431 if (TE.isGather()) {
7432 if (std::optional<OrdersType> CurrentOrder =
7433 findReusedOrderedScalars(TE, TopToBottom, IgnoreReorder)) {
7434 SmallVector<int> Mask;
7435 fixupOrderingIndices(*CurrentOrder);
7436 inversePermutation(*CurrentOrder, Mask);
7437 addMask(Mask, TE.ReuseShuffleIndices);
7438 OrdersType Res(TE.getVectorFactor(), TE.getVectorFactor());
7439 unsigned Sz = TE.Scalars.size();
7440 for (int K = 0, E = TE.getVectorFactor() / Sz; K < E; ++K) {
7441 for (auto [I, Idx] : enumerate(ArrayRef(Mask).slice(K * Sz, Sz)))
7442 if (Idx != PoisonMaskElem)
7443 Res[Idx + K * Sz] = I + K * Sz;
7444 }
7445 return std::move(Res);
7446 }
7447 }
7448 if (Sz == 2 && TE.getVectorFactor() == 4 &&
7449 ::getNumberOfParts(*TTI,
7450 getWidenedType(getValueType(TE.Scalars.front()),
7451 2 * TE.getVectorFactor()),
7452 getValueType(TE.Scalars.front())) == 1)
7453 return std::nullopt;
7454 if (TE.ReuseShuffleIndices.size() % Sz != 0)
7455 return std::nullopt;
7456 if (!ShuffleVectorInst::isOneUseSingleSourceMask(TE.ReuseShuffleIndices,
7457 Sz)) {
7458 SmallVector<int> ReorderMask(Sz, PoisonMaskElem);
7459 if (TE.ReorderIndices.empty())
7460 std::iota(ReorderMask.begin(), ReorderMask.end(), 0);
7461 else
7462 inversePermutation(TE.ReorderIndices, ReorderMask);
7463 addMask(ReorderMask, TE.ReuseShuffleIndices);
7464 unsigned VF = ReorderMask.size();
7465 OrdersType ResOrder(VF, VF);
7466 unsigned NumParts = divideCeil(VF, Sz);
7467 SmallBitVector UsedVals(NumParts);
7468 for (unsigned I = 0; I < VF; I += Sz) {
7469 int Val = PoisonMaskElem;
7470 unsigned UndefCnt = 0;
7471 unsigned Limit = std::min(Sz, VF - I);
7472 if (any_of(ArrayRef(ReorderMask).slice(I, Limit),
7473 [&](int Idx) {
7474 if (Val == PoisonMaskElem && Idx != PoisonMaskElem)
7475 Val = Idx;
7476 if (Idx == PoisonMaskElem)
7477 ++UndefCnt;
7478 return Idx != PoisonMaskElem && Idx != Val;
7479 }) ||
7480 Val >= static_cast<int>(NumParts) || Val == PoisonMaskElem ||
7481 UsedVals.test(Val) || UndefCnt > Sz / 2)
7482 return std::nullopt;
7483 UsedVals.set(Val);
7484 for (unsigned K = 0; K < NumParts; ++K) {
7485 unsigned Idx = Val + Sz * K;
7486 if (Idx < VF && I + K < VF)
7487 ResOrder[Idx] = I + K;
7488 }
7489 }
7490 return std::move(ResOrder);
7491 }
7492 unsigned VF = TE.getVectorFactor();
7493 // Try build correct order for extractelement instructions.
7494 SmallVector<int> ReusedMask(TE.ReuseShuffleIndices.begin(),
7495 TE.ReuseShuffleIndices.end());
7496 if (TE.hasState() && TE.getOpcode() == Instruction::ExtractElement &&
7497 !TE.hasCopyableElements() && all_of(TE.Scalars, [Sz](Value *V) {
7498 if (isa<PoisonValue>(V))
7499 return true;
7500 std::optional<unsigned> Idx = getExtractIndex(cast<Instruction>(V));
7501 return Idx && *Idx < Sz;
7502 })) {
7503 assert(!TE.isAltShuffle() && "Alternate instructions are only supported "
7504 "by BinaryOperator and CastInst.");
7505 SmallVector<int> ReorderMask(Sz, PoisonMaskElem);
7506 if (TE.ReorderIndices.empty())
7507 std::iota(ReorderMask.begin(), ReorderMask.end(), 0);
7508 else
7509 inversePermutation(TE.ReorderIndices, ReorderMask);
7510 for (unsigned I = 0; I < VF; ++I) {
7511 int &Idx = ReusedMask[I];
7512 if (Idx == PoisonMaskElem)
7513 continue;
7514 Value *V = TE.Scalars[ReorderMask[Idx]];
7515 std::optional<unsigned> EI = getExtractIndex(cast<Instruction>(V));
7516 Idx = std::distance(ReorderMask.begin(), find(ReorderMask, *EI));
7517 }
7518 }
7519 // Build the order of the VF size, need to reorder reuses shuffles, they are
7520 // always of VF size.
7521 OrdersType ResOrder(VF);
7522 std::iota(ResOrder.begin(), ResOrder.end(), 0);
7523 auto *It = ResOrder.begin();
7524 for (unsigned K = 0; K < VF; K += Sz) {
7525 OrdersType CurrentOrder(TE.ReorderIndices);
7526 SmallVector<int> SubMask{ArrayRef(ReusedMask).slice(K, Sz)};
7527 if (SubMask.front() == PoisonMaskElem)
7528 std::iota(SubMask.begin(), SubMask.end(), 0);
7529 reorderOrder(CurrentOrder, SubMask);
7530 transform(CurrentOrder, It, [K](unsigned Pos) { return Pos + K; });
7531 std::advance(It, Sz);
7532 }
7533 if (TE.isGather() && all_of(enumerate(ResOrder), [](const auto &Data) {
7534 return Data.index() == Data.value();
7535 }))
7536 return std::nullopt; // No need to reorder.
7537 return std::move(ResOrder);
7538 }
7539 if (TE.State == TreeEntry::StridedVectorize && !TopToBottom &&
7540 (!TE.UserTreeIndex || !TE.UserTreeIndex.UserTE->hasState() ||
7541 !Instruction::isBinaryOp(TE.UserTreeIndex.UserTE->getOpcode())) &&
7542 (TE.ReorderIndices.empty() || isReverseOrder(TE.ReorderIndices)))
7543 return std::nullopt;
7544 if (TE.State == TreeEntry::SplitVectorize ||
7545 ((TE.State == TreeEntry::Vectorize ||
7546 TE.State == TreeEntry::StridedVectorize ||
7547 TE.State == TreeEntry::ExpandVectorize ||
7548 TE.State == TreeEntry::CompressVectorize ||
7549 TE.State == TreeEntry::BlendedLoadVectorize) &&
7552 TE.getMainOp()))))) {
7553 assert((TE.State == TreeEntry::SplitVectorize || !TE.isAltShuffle()) &&
7554 "Alternate instructions are only supported by "
7555 "BinaryOperator and CastInst.");
7556 return TE.ReorderIndices;
7557 }
7558 if (!TopToBottom && IgnoreReorder && TE.State == TreeEntry::Vectorize &&
7559 TE.isAltShuffle()) {
7560 assert(TE.ReuseShuffleIndices.empty() &&
7561 "ReuseShuffleIndices should be "
7562 "empty for alternate instructions.");
7563 SmallVector<int> Mask;
7564 TE.buildAltOpShuffleMask(
7565 [&](Instruction *I) {
7566 assert(TE.getMatchingMainOpOrAltOp(I) &&
7567 "Unexpected main/alternate opcode");
7568 return isAlternateInstruction(I, TE.getMainOp(), TE.getAltOp(), *TLI);
7569 },
7570 Mask);
7571 const int VF = TE.getVectorFactor();
7572 OrdersType ResOrder(VF, VF);
7573 for (unsigned I : seq<unsigned>(VF)) {
7574 if (Mask[I] == PoisonMaskElem)
7575 continue;
7576 ResOrder[Mask[I] % VF] = I;
7577 }
7578 return std::move(ResOrder);
7579 }
7580 if (!TE.ReorderIndices.empty())
7581 return TE.ReorderIndices;
7582 if (TE.State == TreeEntry::Vectorize && TE.getOpcode() == Instruction::PHI) {
7583 if (!TE.ReorderIndices.empty())
7584 return TE.ReorderIndices;
7585
7586 SmallVector<Instruction *> UserBVHead(TE.Scalars.size());
7587 for (auto [I, V] : zip(UserBVHead, TE.Scalars)) {
7588 if (isa<Constant>(V) || !V->hasNUsesOrMore(1))
7589 continue;
7590 auto *II = dyn_cast<InsertElementInst>(*V->user_begin());
7591 if (!II)
7592 continue;
7593 Instruction *BVHead = nullptr;
7594 BasicBlock *BB = II->getParent();
7595 while (II && II->hasOneUse() && II->getParent() == BB) {
7596 BVHead = II;
7597 II = dyn_cast<InsertElementInst>(II->getOperand(0));
7598 }
7599 I = BVHead;
7600 }
7601
7602 auto CompareByBasicBlocks = [&](BasicBlock *BB1, BasicBlock *BB2) {
7603 assert(BB1 != BB2 && "Expected different basic blocks.");
7604 if (!DT->isReachableFromEntry(BB1))
7605 return false;
7606 if (!DT->isReachableFromEntry(BB2))
7607 return true;
7608 auto *NodeA = DT->getNode(BB1);
7609 auto *NodeB = DT->getNode(BB2);
7610 assert(NodeA && "Should only process reachable instructions");
7611 assert(NodeB && "Should only process reachable instructions");
7612 assert((NodeA == NodeB) ==
7613 (NodeA->getDFSNumIn() == NodeB->getDFSNumIn()) &&
7614 "Different nodes should have different DFS numbers");
7615 return NodeA->getDFSNumIn() < NodeB->getDFSNumIn();
7616 };
7617 auto PHICompare = [&](unsigned I1, unsigned I2) {
7618 Value *V1 = TE.Scalars[I1];
7619 Value *V2 = TE.Scalars[I2];
7620 if (V1 == V2 || (V1->use_empty() && V2->use_empty()))
7621 return false;
7622 if (isa<PoisonValue>(V1))
7623 return true;
7624 if (isa<PoisonValue>(V2))
7625 return false;
7626 if (V1->getNumUses() < V2->getNumUses())
7627 return true;
7628 if (V1->getNumUses() > V2->getNumUses())
7629 return false;
7630 auto *FirstUserOfPhi1 = cast<Instruction>(*V1->user_begin());
7631 auto *FirstUserOfPhi2 = cast<Instruction>(*V2->user_begin());
7632 if (FirstUserOfPhi1->getParent() != FirstUserOfPhi2->getParent())
7633 return CompareByBasicBlocks(FirstUserOfPhi1->getParent(),
7634 FirstUserOfPhi2->getParent());
7635 auto *IE1 = dyn_cast<InsertElementInst>(FirstUserOfPhi1);
7636 auto *IE2 = dyn_cast<InsertElementInst>(FirstUserOfPhi2);
7637 auto *EE1 = dyn_cast<ExtractElementInst>(FirstUserOfPhi1);
7638 auto *EE2 = dyn_cast<ExtractElementInst>(FirstUserOfPhi2);
7639 if (IE1 && !IE2)
7640 return true;
7641 if (!IE1 && IE2)
7642 return false;
7643 if (IE1 && IE2) {
7644 if (UserBVHead[I1] && !UserBVHead[I2])
7645 return true;
7646 if (!UserBVHead[I1])
7647 return false;
7648 if (UserBVHead[I1] == UserBVHead[I2])
7649 return getElementIndex(IE1) < getElementIndex(IE2);
7650 if (UserBVHead[I1]->getParent() != UserBVHead[I2]->getParent())
7651 return CompareByBasicBlocks(UserBVHead[I1]->getParent(),
7652 UserBVHead[I2]->getParent());
7653 return UserBVHead[I1]->comesBefore(UserBVHead[I2]);
7654 }
7655 if (EE1 && !EE2)
7656 return true;
7657 if (!EE1 && EE2)
7658 return false;
7659 if (EE1 && EE2) {
7660 auto *Inst1 = dyn_cast<Instruction>(EE1->getOperand(0));
7661 auto *Inst2 = dyn_cast<Instruction>(EE2->getOperand(0));
7662 auto *P1 = dyn_cast<Argument>(EE1->getOperand(0));
7663 auto *P2 = dyn_cast<Argument>(EE2->getOperand(0));
7664 if (!Inst2 && !P2)
7665 return Inst1 || P1;
7666 if (EE1->getOperand(0) == EE2->getOperand(0))
7667 return getElementIndex(EE1) < getElementIndex(EE2);
7668 if (!Inst1 && Inst2)
7669 return false;
7670 if (Inst1 && Inst2) {
7671 if (Inst1->getParent() != Inst2->getParent())
7672 return CompareByBasicBlocks(Inst1->getParent(), Inst2->getParent());
7673 return Inst1->comesBefore(Inst2);
7674 }
7675 if (!P1 && P2)
7676 return false;
7677 assert(P1 && P2 &&
7678 "Expected either instructions or arguments vector operands.");
7679 return P1->getArgNo() < P2->getArgNo();
7680 }
7681 return false;
7682 };
7683 OrdersType Phis(TE.Scalars.size());
7684 std::iota(Phis.begin(), Phis.end(), 0);
7685 stable_sort(Phis, PHICompare);
7686 if (isIdentityOrder(Phis))
7687 return std::nullopt; // No need to reorder.
7688 return std::move(Phis);
7689 }
7690 if (TE.isGather() &&
7691 (!TE.hasState() || !TE.isAltShuffle() ||
7692 ScalarsInSplitNodes.contains(TE.getMainOp())) &&
7693 allSameType(TE.Scalars)) {
7694 // TODO: add analysis of other gather nodes with extractelement
7695 // instructions and other values/instructions, not only undefs.
7696 // Nodes with copyable lanes may mix in non-extract lanes, for which the
7697 // extract-index order is not applicable.
7698 if (((TE.hasState() && TE.getOpcode() == Instruction::ExtractElement &&
7699 !TE.hasCopyableElements()) ||
7701 any_of(TE.Scalars, IsaPred<ExtractElementInst>))) &&
7702 all_of(TE.Scalars, [](Value *V) {
7703 auto *EE = dyn_cast<ExtractElementInst>(V);
7704 return !EE || isa<FixedVectorType>(EE->getVectorOperandType());
7705 })) {
7706 // Check that gather of extractelements can be represented as
7707 // just a shuffle of a single vector.
7708 OrdersType CurrentOrder;
7709 bool Reuse =
7710 canReuseExtract(TE.Scalars, CurrentOrder, /*ResizeAllowed=*/true);
7711 if (Reuse || !CurrentOrder.empty())
7712 return std::move(CurrentOrder);
7713 }
7714 // If the gather node is <undef, v, .., poison> and
7715 // insertelement poison, v, 0 [+ permute]
7716 // is cheaper than
7717 // insertelement poison, v, n - try to reorder.
7718 // If rotating the whole graph, exclude the permute cost, the whole graph
7719 // might be transformed.
7720 int Sz = TE.Scalars.size();
7721 if (isSplat(TE.Scalars) && !allConstant(TE.Scalars) &&
7722 count_if(TE.Scalars, IsaPred<UndefValue>) == Sz - 1) {
7723 const auto *It = find_if_not(TE.Scalars, isConstant);
7724 if (It == TE.Scalars.begin())
7725 return OrdersType();
7726 auto *Ty =
7727 cast<VectorType>(getWidenedType(TE.Scalars.front()->getType(), Sz));
7728 if (It != TE.Scalars.end()) {
7729 OrdersType Order(Sz, Sz);
7730 unsigned Idx = std::distance(TE.Scalars.begin(), It);
7731 Order[Idx] = 0;
7732 fixupOrderingIndices(Order);
7733 SmallVector<int> Mask;
7734 inversePermutation(Order, Mask);
7735 InstructionCost PermuteCost =
7736 TopToBottom ? 0
7738 CostKind, Mask);
7739 InstructionCost InsertFirstCost =
7740 TTI->getVectorInstrCost(Instruction::InsertElement, Ty, CostKind, 0,
7741 PoisonValue::get(Ty), *It);
7742 InstructionCost InsertIdxCost =
7743 TTI->getVectorInstrCost(Instruction::InsertElement, Ty, CostKind,
7744 Idx, PoisonValue::get(Ty), *It);
7745 if (InsertFirstCost + PermuteCost < InsertIdxCost) {
7746 OrdersType Order(Sz, Sz);
7747 Order[Idx] = 0;
7748 return std::move(Order);
7749 }
7750 }
7751 }
7752 if (isSplat(TE.Scalars))
7753 return std::nullopt;
7754 if (TE.Scalars.size() >= 3)
7755 if (std::optional<OrdersType> Order = findPartiallyOrderedLoads(TE))
7756 return Order;
7757 // Check if can include the order of vectorized loads. For masked gathers do
7758 // extra analysis later, so include such nodes into a special list.
7759 if (TE.hasState() && TE.getOpcode() == Instruction::Load) {
7760 SmallVector<Value *> PointerOps;
7761 StridedPtrInfo SPtrInfo;
7762 OrdersType CurrentOrder;
7763 LoadsState Res = canVectorizeLoads(TE.Scalars, TE.Scalars.front(),
7764 CurrentOrder, PointerOps, SPtrInfo);
7768 return std::move(CurrentOrder);
7769 }
7770 if (std::optional<OrdersType> CurrentOrder =
7771 findReusedOrderedScalars(TE, TopToBottom, IgnoreReorder))
7772 return CurrentOrder;
7773 }
7774 return std::nullopt;
7775}
7776
7777/// Checks if the given mask is a "clustered" mask with the same clusters of
7778/// size \p Sz, which are not identity submasks.
7780 unsigned Sz) {
7781 ArrayRef<int> FirstCluster = Mask.slice(0, Sz);
7782 if (ShuffleVectorInst::isIdentityMask(FirstCluster, Sz))
7783 return false;
7784 for (unsigned I = Sz, E = Mask.size(); I < E; I += Sz) {
7785 ArrayRef<int> Cluster = Mask.slice(I, Sz);
7786 if (Cluster != FirstCluster)
7787 return false;
7788 }
7789 return true;
7790}
7791
7792void BoUpSLP::reorderNodeWithReuses(TreeEntry &TE, ArrayRef<int> Mask) const {
7793 // Reorder reuses mask.
7794 reorderReuses(TE.ReuseShuffleIndices, Mask);
7795 const unsigned Sz = TE.Scalars.size();
7796 // For vectorized and non-clustered reused no need to do anything else.
7797 if (!TE.isGather() ||
7799 Sz) ||
7800 !isRepeatedNonIdentityClusteredMask(TE.ReuseShuffleIndices, Sz))
7801 return;
7802 SmallVector<int> NewMask;
7803 inversePermutation(TE.ReorderIndices, NewMask);
7804 addMask(NewMask, TE.ReuseShuffleIndices);
7805 // Clear reorder since it is going to be applied to the new mask.
7806 TE.ReorderIndices.clear();
7807 // Try to improve gathered nodes with clustered reuses, if possible.
7808 ArrayRef<int> Slice = ArrayRef(NewMask).slice(0, Sz);
7809 SmallVector<unsigned> NewOrder(Slice);
7810 inversePermutation(NewOrder, NewMask);
7811 reorderScalars(TE.Scalars, NewMask);
7812 // Fill the reuses mask with the identity submasks.
7813 for (auto *It = TE.ReuseShuffleIndices.begin(),
7814 *End = TE.ReuseShuffleIndices.end();
7815 It != End; std::advance(It, Sz))
7816 std::iota(It, std::next(It, Sz), 0);
7817}
7818
7820 ArrayRef<unsigned> SecondaryOrder) {
7821 assert((SecondaryOrder.empty() || Order.size() == SecondaryOrder.size()) &&
7822 "Expected same size of orders");
7823 size_t Sz = Order.size();
7824 SmallBitVector UsedIndices(Sz);
7825 for (unsigned Idx : seq<unsigned>(0, Sz)) {
7826 if (Order[Idx] != Sz)
7827 UsedIndices.set(Order[Idx]);
7828 }
7829 if (SecondaryOrder.empty()) {
7830 for (unsigned Idx : seq<unsigned>(0, Sz))
7831 if (Order[Idx] == Sz && !UsedIndices.test(Idx))
7832 Order[Idx] = Idx;
7833 } else {
7834 for (unsigned Idx : seq<unsigned>(0, Sz))
7835 if (SecondaryOrder[Idx] != Sz && Order[Idx] == Sz &&
7836 !UsedIndices.test(SecondaryOrder[Idx]))
7837 Order[Idx] = SecondaryOrder[Idx];
7838 }
7839}
7840
7843 return false;
7844
7845 constexpr unsigned TinyVF = 2;
7846 constexpr unsigned TinyTree = 10;
7847 constexpr unsigned PhiOpsLimit = 12;
7848 constexpr unsigned GatherLoadsLimit = 2;
7849 if (VectorizableTree.size() <= TinyTree)
7850 return true;
7851 if (getRootNode().hasState() && !getRootNode().isGather() &&
7852 (getRootNode().getOpcode() == Instruction::Store ||
7853 getRootNode().getOpcode() == Instruction::PHI ||
7854 (getRootNode().getVectorFactor() <= TinyVF &&
7855 (getRootNode().getOpcode() == Instruction::PtrToInt ||
7856 getRootNode().getOpcode() == Instruction::PtrToAddr ||
7857 getRootNode().getOpcode() == Instruction::ICmp))) &&
7858 getRootNode().ReorderIndices.empty()) {
7859 // Check if the tree has only single store and single (unordered) load node,
7860 // other nodes are phis or geps/binops, combined with phis, and/or single
7861 // gather load node
7862 if (getRootNode().hasState() &&
7863 getRootNode().getOpcode() == Instruction::PHI &&
7864 getRootNodeScalars().size() == TinyVF &&
7865 getRootNode().getNumOperands() > PhiOpsLimit)
7866 return false;
7867 // Single node, which require reorder - skip.
7868 if (getRootNode().hasState() &&
7869 getRootNode().getOpcode() == Instruction::Store &&
7870 getRootNode().ReorderIndices.empty()) {
7871 const unsigned ReorderedSplitsCnt =
7872 count_if(VectorizableTree, [&](const std::unique_ptr<TreeEntry> &TE) {
7873 return TE->State == TreeEntry::SplitVectorize &&
7874 !TE->ReorderIndices.empty() && TE->UserTreeIndex.UserTE &&
7875 TE->UserTreeIndex.UserTE->State == TreeEntry::Vectorize &&
7876 isCommutative(TE->UserTreeIndex.UserTE->getMainOp());
7877 });
7878 if (ReorderedSplitsCnt <= 1 &&
7879 static_cast<unsigned>(count_if(
7880 VectorizableTree, [&](const std::unique_ptr<TreeEntry> &TE) {
7881 return ((!TE->isGather() &&
7882 (TE->ReorderIndices.empty() ||
7883 (TE->UserTreeIndex.UserTE &&
7884 TE->UserTreeIndex.UserTE->State ==
7885 TreeEntry::Vectorize &&
7886 !TE->UserTreeIndex.UserTE->ReuseShuffleIndices
7887 .empty()))) ||
7888 (TE->isGather() && TE->ReorderIndices.empty() &&
7889 (!TE->hasState() || TE->isAltShuffle() ||
7890 TE->getOpcode() == Instruction::Load ||
7891 TE->getOpcode() == Instruction::ZExt ||
7892 TE->getOpcode() == Instruction::SExt))) &&
7893 (getRootNode().getVectorFactor() > TinyVF ||
7894 !TE->isGather() || none_of(TE->Scalars, [&](Value *V) {
7895 return !isConstant(V) && isVectorized(V);
7896 }));
7897 })) >= VectorizableTree.size() - ReorderedSplitsCnt)
7898 return false;
7899 }
7900 bool HasPhis = false;
7901 bool HasLoad = true;
7902 unsigned GatherLoads = 0;
7903 for (const std::unique_ptr<TreeEntry> &TE :
7904 ArrayRef(VectorizableTree).drop_front()) {
7905 if (TE->State == TreeEntry::SplitVectorize)
7906 continue;
7907 if (!TE->hasState()) {
7908 if (all_of(TE->Scalars, IsaPred<Constant, PHINode>) ||
7910 continue;
7911 if (getRootNodeScalars().size() == TinyVF &&
7913 continue;
7914 return true;
7915 }
7916 if (TE->getOpcode() == Instruction::Load && TE->ReorderIndices.empty()) {
7917 if (!TE->isGather()) {
7918 HasLoad = false;
7919 continue;
7920 }
7921 if (HasLoad)
7922 return true;
7923 ++GatherLoads;
7924 if (GatherLoads >= GatherLoadsLimit)
7925 return true;
7926 }
7927 if (TE->getOpcode() == Instruction::GetElementPtr ||
7928 Instruction::isBinaryOp(TE->getOpcode()))
7929 continue;
7930 if (TE->getOpcode() != Instruction::PHI &&
7931 (!TE->hasCopyableElements() ||
7932 static_cast<unsigned>(count_if(TE->Scalars, IsaPred<PHINode>)) <
7933 TE->Scalars.size() / 2))
7934 return true;
7935 if (getRootNodeScalars().size() == TinyVF &&
7936 TE->getNumOperands() > PhiOpsLimit)
7937 return false;
7938 HasPhis = true;
7939 }
7940 return !HasPhis;
7941 }
7942 return true;
7943}
7944
7945void BoUpSLP::TreeEntry::reorderSplitNode(unsigned Idx, ArrayRef<int> Mask,
7946 ArrayRef<int> MaskOrder) {
7947 assert(State == TreeEntry::SplitVectorize && "Expected split user node.");
7948 SmallVector<int> NewMask(getVectorFactor());
7949 SmallVector<int> NewMaskOrder(getVectorFactor());
7950 std::iota(NewMask.begin(), NewMask.end(), 0);
7951 std::iota(NewMaskOrder.begin(), NewMaskOrder.end(), 0);
7952 if (Idx == 0) {
7953 copy(Mask, NewMask.begin());
7954 copy(MaskOrder, NewMaskOrder.begin());
7955 } else {
7956 assert(Idx == 1 && "Expected either 0 or 1 index.");
7957 unsigned Offset = CombinedEntriesWithIndices.back().second;
7958 for (unsigned I : seq<unsigned>(Mask.size())) {
7959 NewMask[I + Offset] = Mask[I] + Offset;
7960 NewMaskOrder[I + Offset] = MaskOrder[I] + Offset;
7961 }
7962 }
7963 reorderScalars(Scalars, NewMask);
7964 reorderOrder(ReorderIndices, NewMaskOrder, /*BottomOrder=*/true);
7965 if (!ReorderIndices.empty() && BoUpSLP::isIdentityOrder(ReorderIndices))
7966 ReorderIndices.clear();
7967}
7968
7970 if (!TE.hasState())
7971 return;
7972 if (auto It = BlocksSchedules.find(TE.getMainOp()->getParent());
7973 It != BlocksSchedules.end())
7974 It->second->markCopyableDepsForRecalc(TE);
7975}
7976
7978 // Maps VF to the graph nodes.
7980 // ExtractElement gather nodes which can be vectorized and need to handle
7981 // their ordering.
7983
7984 // Phi nodes can have preferred ordering based on their result users
7986
7987 // AltShuffles can also have a preferred ordering that leads to fewer
7988 // instructions, e.g., the addsub instruction in x86.
7989 DenseMap<const TreeEntry *, OrdersType> AltShufflesToOrders;
7990
7991 // Maps a TreeEntry to the reorder indices of external users.
7993 ExternalUserReorderMap;
7994 // TODO: Reordering of struct types is not supported.
7995 if (any_of(VectorizableTree, [](const std::unique_ptr<TreeEntry> &TE) {
7996 return TE->State == TreeEntry::Vectorize &&
7997 isa<StructType>(getValueType(TE->Scalars.front()));
7998 }))
7999 return;
8000 // Compute IgnoreReorder once - it depends only on UserIgnoreList and
8001 // getRootNode(), which do not change during this loop.
8002 const bool IgnoreReorder =
8003 !UserIgnoreList && getRootNode().hasState() &&
8004 (getRootNode().getOpcode() == Instruction::InsertElement ||
8005 getRootNode().getOpcode() == Instruction::InsertValue ||
8006 getRootNode().getOpcode() == Instruction::Store);
8007 // Find all reorderable nodes with the given VF.
8008 // Currently the are vectorized stores,loads,extracts + some gathering of
8009 // extracts.
8010 for_each(VectorizableTree, [&, &TTIRef = *TTI](
8011 const std::unique_ptr<TreeEntry> &TE) {
8012 // Look for external users that will probably be vectorized.
8013 SmallVector<OrdersType, 1> ExternalUserReorderIndices =
8014 findExternalStoreUsersReorderIndices(TE.get());
8015 if (!ExternalUserReorderIndices.empty()) {
8016 VFToOrderedEntries[TE->getVectorFactor()].insert(TE.get());
8017 ExternalUserReorderMap.try_emplace(TE.get(),
8018 std::move(ExternalUserReorderIndices));
8019 }
8020
8021 // Patterns like [fadd,fsub] can be combined into a single instruction in
8022 // x86. Reordering them into [fsub,fadd] blocks this pattern. So we need
8023 // to take into account their order when looking for the most used order.
8024 if (TE->hasState() && TE->isAltShuffle() &&
8025 TE->State != TreeEntry::SplitVectorize) {
8026 Type *ScalarTy = TE->Scalars[0]->getType();
8027 auto *VecTy =
8028 cast<VectorType>(getWidenedType(ScalarTy, TE->Scalars.size()));
8029 unsigned Opcode0 = TE->getOpcode();
8030 unsigned Opcode1 = TE->getAltOpcode();
8031 SmallBitVector OpcodeMask(
8032 getAltInstrMask(TE->Scalars, ScalarTy, Opcode0, Opcode1));
8033 // If this pattern is supported by the target then we consider the order.
8034 if (TTIRef.isLegalAltInstr(VecTy, Opcode0, Opcode1, OpcodeMask)) {
8035 VFToOrderedEntries[TE->getVectorFactor()].insert(TE.get());
8036 AltShufflesToOrders.try_emplace(TE.get(), OrdersType());
8037 }
8038 // TODO: Check the reverse order too.
8039 }
8040
8041 if (std::optional<OrdersType> CurrentOrder =
8042 getReorderingData(*TE, /*TopToBottom=*/true, IgnoreReorder)) {
8043 // Do not include ordering for nodes used in the alt opcode vectorization,
8044 // better to reorder them during bottom-to-top stage. If follow the order
8045 // here, it causes reordering of the whole graph though actually it is
8046 // profitable just to reorder the subgraph that starts from the alternate
8047 // opcode vectorization node. Such nodes already end-up with the shuffle
8048 // instruction and it is just enough to change this shuffle rather than
8049 // rotate the scalars for the whole graph.
8050 unsigned Cnt = 0;
8051 const TreeEntry *UserTE = TE.get();
8052 while (UserTE && Cnt < RecursionMaxDepth) {
8053 if (!UserTE->UserTreeIndex)
8054 break;
8055 if (UserTE->UserTreeIndex.UserTE->State == TreeEntry::Vectorize &&
8056 UserTE->UserTreeIndex.UserTE->isAltShuffle() &&
8057 UserTE->UserTreeIndex.UserTE->Idx != 0)
8058 return;
8059 UserTE = UserTE->UserTreeIndex.UserTE;
8060 ++Cnt;
8061 }
8062 VFToOrderedEntries[TE->getVectorFactor()].insert(TE.get());
8063 if (!(TE->State == TreeEntry::Vectorize ||
8064 TE->State == TreeEntry::StridedVectorize ||
8065 TE->State == TreeEntry::ExpandVectorize ||
8066 TE->State == TreeEntry::SplitVectorize ||
8067 TE->State == TreeEntry::CompressVectorize ||
8068 TE->State == TreeEntry::BlendedLoadVectorize) ||
8069 !TE->ReuseShuffleIndices.empty())
8070 GathersToOrders.try_emplace(TE.get(), *CurrentOrder);
8071 if (TE->State == TreeEntry::Vectorize &&
8072 TE->getOpcode() == Instruction::PHI)
8073 PhisToOrders.try_emplace(TE.get(), *CurrentOrder);
8074 }
8075 });
8076
8077 // Reorder the graph nodes according to their vectorization factor.
8078 for (unsigned VF = getRootNode().getVectorFactor();
8079 !VFToOrderedEntries.empty() && VF > 1; --VF) {
8080 auto It = VFToOrderedEntries.find(VF);
8081 if (It == VFToOrderedEntries.end())
8082 continue;
8083 // Try to find the most profitable order. We just are looking for the most
8084 // used order and reorder scalar elements in the nodes according to this
8085 // mostly used order.
8086 ArrayRef<TreeEntry *> OrderedEntries = It->second.getArrayRef();
8087 // Delete VF entry upon exit.
8088 llvm::scope_exit Cleanup([&]() { VFToOrderedEntries.erase(It); });
8089
8090 // All operands are reordered and used only in this node - propagate the
8091 // most used order to the user node.
8094 OrdersUses;
8095 for (const TreeEntry *OpTE : OrderedEntries) {
8096 // No need to reorder this nodes, still need to extend and to use shuffle,
8097 // just need to merge reordering shuffle and the reuse shuffle.
8098 if (!OpTE->ReuseShuffleIndices.empty() && !GathersToOrders.count(OpTE) &&
8099 OpTE->State != TreeEntry::SplitVectorize)
8100 continue;
8101 // Count number of orders uses.
8102 const auto &Order = [OpTE, &GathersToOrders, &AltShufflesToOrders,
8103 &PhisToOrders]() -> const OrdersType & {
8104 if (OpTE->isGather() || !OpTE->ReuseShuffleIndices.empty()) {
8105 auto It = GathersToOrders.find(OpTE);
8106 if (It != GathersToOrders.end())
8107 return It->second;
8108 }
8109 if (OpTE->hasState() && OpTE->isAltShuffle()) {
8110 auto It = AltShufflesToOrders.find(OpTE);
8111 if (It != AltShufflesToOrders.end())
8112 return It->second;
8113 }
8114 if (OpTE->State == TreeEntry::Vectorize &&
8115 OpTE->getOpcode() == Instruction::PHI) {
8116 auto It = PhisToOrders.find(OpTE);
8117 if (It != PhisToOrders.end())
8118 return It->second;
8119 }
8120 return OpTE->ReorderIndices;
8121 }();
8122 // First consider the order of the external scalar users.
8123 auto It = ExternalUserReorderMap.find(OpTE);
8124 if (It != ExternalUserReorderMap.end()) {
8125 const auto &ExternalUserReorderIndices = It->second;
8126 // If the OpTE vector factor != number of scalars - use natural order,
8127 // it is an attempt to reorder node with reused scalars but with
8128 // external uses.
8129 if (OpTE->getVectorFactor() != OpTE->Scalars.size()) {
8130 OrdersUses.try_emplace(OrdersType(), 0).first->second +=
8131 ExternalUserReorderIndices.size();
8132 } else {
8133 for (const OrdersType &ExtOrder : ExternalUserReorderIndices)
8134 ++OrdersUses.try_emplace(ExtOrder, 0).first->second;
8135 }
8136 // No other useful reorder data in this entry.
8137 if (Order.empty())
8138 continue;
8139 }
8140 // Stores actually store the mask, not the order, need to invert.
8141 if (OpTE->State == TreeEntry::Vectorize &&
8142 OpTE->getOpcode() == Instruction::Store && !Order.empty()) {
8143 assert(!OpTE->isAltShuffle() &&
8144 "Alternate instructions are only supported by BinaryOperator "
8145 "and CastInst.");
8146 SmallVector<int> Mask;
8147 inversePermutation(Order, Mask);
8148 unsigned E = Order.size();
8149 OrdersType CurrentOrder(E, E);
8150 transform(Mask, CurrentOrder.begin(), [E](int Idx) {
8151 return Idx == PoisonMaskElem ? E : static_cast<unsigned>(Idx);
8152 });
8153 fixupOrderingIndices(CurrentOrder);
8154 ++OrdersUses.try_emplace(CurrentOrder, 0).first->second;
8155 } else {
8156 ++OrdersUses.try_emplace(Order, 0).first->second;
8157 }
8158 }
8159 if (OrdersUses.empty())
8160 continue;
8161 // Choose the most used order.
8162 unsigned IdentityCnt = 0;
8163 unsigned FilledIdentityCnt = 0;
8164 OrdersType IdentityOrder(VF, VF);
8165 for (auto &Pair : OrdersUses) {
8166 if (Pair.first.empty() || isIdentityOrder(Pair.first)) {
8167 if (!Pair.first.empty())
8168 FilledIdentityCnt += Pair.second;
8169 IdentityCnt += Pair.second;
8170 combineOrders(IdentityOrder, Pair.first);
8171 }
8172 }
8173 MutableArrayRef<unsigned> BestOrder = IdentityOrder;
8174 unsigned Cnt = IdentityCnt;
8175 for (auto &Pair : OrdersUses) {
8176 // Prefer identity order. But, if filled identity found (non-empty order)
8177 // with same number of uses, as the new candidate order, we can choose
8178 // this candidate order.
8179 if (Cnt < Pair.second ||
8180 (Cnt == IdentityCnt && IdentityCnt == FilledIdentityCnt &&
8181 Cnt == Pair.second && !BestOrder.empty() &&
8182 isIdentityOrder(BestOrder))) {
8183 combineOrders(Pair.first, BestOrder);
8184 BestOrder = Pair.first;
8185 Cnt = Pair.second;
8186 } else {
8187 combineOrders(BestOrder, Pair.first);
8188 }
8189 }
8190 // Set order of the user node.
8191 if (isIdentityOrder(BestOrder))
8192 continue;
8193 fixupOrderingIndices(BestOrder);
8194 SmallVector<int> Mask;
8195 inversePermutation(BestOrder, Mask);
8196 SmallVector<int> MaskOrder(BestOrder.size(), PoisonMaskElem);
8197 unsigned E = BestOrder.size();
8198 transform(BestOrder, MaskOrder.begin(), [E](unsigned I) {
8199 return I < E ? static_cast<int>(I) : PoisonMaskElem;
8200 });
8201 // Do an actual reordering, if profitable.
8202 for (std::unique_ptr<TreeEntry> &TE : VectorizableTree) {
8203 // Just do the reordering for the nodes with the given VF.
8204 if (TE->Scalars.size() != VF) {
8205 if (TE->ReuseShuffleIndices.size() == VF &&
8206 TE->State != TreeEntry::ExpandVectorize) {
8207 assert(TE->State != TreeEntry::SplitVectorize &&
8208 "Split vectorized not expected.");
8209 // Need to reorder the reuses masks of the operands with smaller VF to
8210 // be able to find the match between the graph nodes and scalar
8211 // operands of the given node during vectorization/cost estimation.
8212 assert(
8213 (!TE->UserTreeIndex ||
8214 TE->UserTreeIndex.UserTE->Scalars.size() == VF ||
8215 TE->UserTreeIndex.UserTE->Scalars.size() == TE->Scalars.size() ||
8216 TE->UserTreeIndex.UserTE->State == TreeEntry::SplitVectorize) &&
8217 "All users must be of VF size.");
8218 if (SLPReVec) {
8219 assert(SLPReVec && "Only supported by REVEC.");
8220 // ShuffleVectorInst does not do reorderOperands (and it should not
8221 // because ShuffleVectorInst supports only a limited set of
8222 // patterns). Only do reorderNodeWithReuses if the user is not
8223 // ShuffleVectorInst.
8224 if (TE->UserTreeIndex && TE->UserTreeIndex.UserTE->hasState() &&
8225 isa<ShuffleVectorInst>(TE->UserTreeIndex.UserTE->getMainOp()))
8226 continue;
8227 }
8228 // Update ordering of the operands with the smaller VF than the given
8229 // one.
8230 reorderNodeWithReuses(*TE, Mask);
8231 // Update orders in user split vectorize nodes.
8232 if (TE->UserTreeIndex &&
8233 TE->UserTreeIndex.UserTE->State == TreeEntry::SplitVectorize)
8234 TE->UserTreeIndex.UserTE->reorderSplitNode(
8235 TE->UserTreeIndex.EdgeIdx, Mask, MaskOrder);
8236 }
8237 continue;
8238 }
8239 if ((TE->State == TreeEntry::SplitVectorize &&
8240 TE->ReuseShuffleIndices.empty()) ||
8241 ((TE->State == TreeEntry::Vectorize ||
8242 TE->State == TreeEntry::StridedVectorize ||
8243 TE->State == TreeEntry::ExpandVectorize ||
8244 TE->State == TreeEntry::CompressVectorize ||
8245 TE->State == TreeEntry::BlendedLoadVectorize) &&
8247 InsertElementInst, InsertValueInst>(TE->getMainOp()) ||
8248 (SLPReVec && isa<ShuffleVectorInst>(TE->getMainOp()))))) {
8249 assert(
8250 (!TE->isAltShuffle() || (TE->State == TreeEntry::SplitVectorize &&
8251 TE->ReuseShuffleIndices.empty())) &&
8252 "Alternate instructions are only supported by BinaryOperator "
8253 "and CastInst.");
8254 // Build correct orders for extract{element,value}, loads,
8255 // stores and alternate (split) nodes.
8256 reorderOrder(TE->ReorderIndices, Mask);
8258 TE->getMainOp())) {
8259 TE->reorderOperands(Mask);
8261 }
8262 } else {
8263 // Reorder the node and its operands.
8264 TE->reorderOperands(Mask);
8266 assert(TE->ReorderIndices.empty() &&
8267 "Expected empty reorder sequence.");
8268 reorderScalars(TE->Scalars, Mask);
8269 }
8270 if (!TE->ReuseShuffleIndices.empty() &&
8271 TE->State != TreeEntry::ExpandVectorize) {
8272 // Apply reversed order to keep the original ordering of the reused
8273 // elements to avoid extra reorder indices shuffling. An ExpandVectorize
8274 // store keeps its expand mask fixed and carries the reorder in
8275 // ReorderIndices, so it is excluded here.
8276 OrdersType CurrentOrder;
8277 reorderOrder(CurrentOrder, MaskOrder);
8278 SmallVector<int> NewReuses;
8279 inversePermutation(CurrentOrder, NewReuses);
8280 addMask(NewReuses, TE->ReuseShuffleIndices);
8281 TE->ReuseShuffleIndices.swap(NewReuses);
8282 } else if (TE->UserTreeIndex &&
8283 TE->UserTreeIndex.UserTE->State == TreeEntry::SplitVectorize)
8284 // Update orders in user split vectorize nodes.
8285 TE->UserTreeIndex.UserTE->reorderSplitNode(TE->UserTreeIndex.EdgeIdx,
8286 Mask, MaskOrder);
8287 }
8288 }
8289}
8290
8291void BoUpSLP::buildReorderableOperands(
8292 TreeEntry *UserTE, SmallVectorImpl<std::pair<unsigned, TreeEntry *>> &Edges,
8293 const SmallPtrSetImpl<const TreeEntry *> &ReorderableGathers,
8294 SmallVectorImpl<TreeEntry *> &GatherOps) {
8295 for (unsigned I : seq<unsigned>(UserTE->getNumOperands())) {
8296 if (any_of(Edges, [I](const std::pair<unsigned, TreeEntry *> &OpData) {
8297 return OpData.first == I &&
8298 (OpData.second->State == TreeEntry::Vectorize ||
8299 OpData.second->State == TreeEntry::StridedVectorize ||
8300 OpData.second->State == TreeEntry::ExpandVectorize ||
8301 OpData.second->State == TreeEntry::CompressVectorize ||
8302 OpData.second->State == TreeEntry::BlendedLoadVectorize ||
8303 OpData.second->State == TreeEntry::SplitVectorize);
8304 }))
8305 continue;
8306 // Do not request operands, if they do not exist.
8307 if (UserTE->hasState()) {
8308 if (UserTE->getOpcode() == Instruction::ExtractElement ||
8309 UserTE->getOpcode() == Instruction::ExtractValue)
8310 continue;
8311 if ((UserTE->getOpcode() == Instruction::InsertElement ||
8312 UserTE->getOpcode() == Instruction::InsertValue) &&
8313 I == 0)
8314 continue;
8315 if (UserTE->getOpcode() == Instruction::Store && I == 1 &&
8316 (UserTE->State == TreeEntry::Vectorize ||
8317 UserTE->State == TreeEntry::StridedVectorize ||
8318 UserTE->State == TreeEntry::ExpandVectorize))
8319 continue;
8320 if (UserTE->getOpcode() == Instruction::Load &&
8321 (UserTE->State == TreeEntry::Vectorize ||
8322 UserTE->State == TreeEntry::StridedVectorize ||
8323 UserTE->State == TreeEntry::CompressVectorize ||
8324 UserTE->State == TreeEntry::BlendedLoadVectorize))
8325 continue;
8326 }
8327 TreeEntry *TE = getOperandEntry(UserTE, I);
8328 assert(TE && "Expected operand entry.");
8329 if (!TE->isGather()) {
8330 // Add the node to the list of the ordered nodes with the identity
8331 // order.
8332 Edges.emplace_back(I, TE);
8333 // Add ScatterVectorize nodes to the list of operands, where just
8334 // reordering of the scalars is required. Similar to the gathers, so
8335 // simply add to the list of gathered ops.
8336 // If there are reused scalars, process this node as a regular vectorize
8337 // node, just reorder reuses mask.
8338 if (TE->State == TreeEntry::ScatterVectorize &&
8339 TE->ReuseShuffleIndices.empty() && TE->ReorderIndices.empty())
8340 GatherOps.push_back(TE);
8341 continue;
8342 }
8343 if (ReorderableGathers.contains(TE))
8344 GatherOps.push_back(TE);
8345 }
8346}
8347
8348void BoUpSLP::reorderBottomToTop(bool IgnoreReorder) {
8349 struct TreeEntryCompare {
8350 bool operator()(const TreeEntry *LHS, const TreeEntry *RHS) const {
8351 if (LHS->UserTreeIndex && RHS->UserTreeIndex)
8352 return LHS->UserTreeIndex.UserTE->Idx < RHS->UserTreeIndex.UserTE->Idx;
8353 return LHS->Idx < RHS->Idx;
8354 }
8355 };
8357 DenseSet<const TreeEntry *> GathersToOrders;
8358 // Find all reorderable leaf nodes with the given VF.
8359 // Currently the are vectorized loads,extracts without alternate operands +
8360 // some gathering of extracts.
8362 for (const std::unique_ptr<TreeEntry> &TE : VectorizableTree) {
8363 if (TE->State != TreeEntry::Vectorize &&
8364 TE->State != TreeEntry::StridedVectorize &&
8365 TE->State != TreeEntry::ExpandVectorize &&
8366 TE->State != TreeEntry::CompressVectorize &&
8367 TE->State != TreeEntry::BlendedLoadVectorize &&
8368 TE->State != TreeEntry::SplitVectorize)
8369 NonVectorized.insert(TE.get());
8370 if (std::optional<OrdersType> CurrentOrder =
8371 getReorderingData(*TE, /*TopToBottom=*/false, IgnoreReorder)) {
8372 Queue.push(TE.get());
8373 if (!(TE->State == TreeEntry::Vectorize ||
8374 TE->State == TreeEntry::StridedVectorize ||
8375 TE->State == TreeEntry::ExpandVectorize ||
8376 TE->State == TreeEntry::CompressVectorize ||
8377 TE->State == TreeEntry::BlendedLoadVectorize ||
8378 TE->State == TreeEntry::SplitVectorize) ||
8379 !TE->ReuseShuffleIndices.empty())
8380 GathersToOrders.insert(TE.get());
8381 }
8382 }
8383
8384 // 1. Propagate order to the graph nodes, which use only reordered nodes.
8385 // I.e., if the node has operands, that are reordered, try to make at least
8386 // one operand order in the natural order and reorder others + reorder the
8387 // user node itself.
8388 SmallPtrSet<const TreeEntry *, 4> Visited, RevisitedOps;
8389 while (!Queue.empty()) {
8390 // 1. Filter out only reordered nodes.
8391 std::pair<TreeEntry *, SmallVector<std::pair<unsigned, TreeEntry *>>> Users;
8392 TreeEntry *TE = Queue.top();
8393 const TreeEntry *UserTE = TE->UserTreeIndex.UserTE;
8394 Queue.pop();
8395 SmallVector<TreeEntry *> OrderedOps(1, TE);
8396 while (!Queue.empty()) {
8397 TE = Queue.top();
8398 if (!UserTE || UserTE != TE->UserTreeIndex.UserTE)
8399 break;
8400 Queue.pop();
8401 OrderedOps.push_back(TE);
8402 }
8403 for (TreeEntry *TE : OrderedOps) {
8404 if (!(TE->State == TreeEntry::Vectorize ||
8405 TE->State == TreeEntry::StridedVectorize ||
8406 TE->State == TreeEntry::ExpandVectorize ||
8407 TE->State == TreeEntry::CompressVectorize ||
8408 TE->State == TreeEntry::BlendedLoadVectorize ||
8409 TE->State == TreeEntry::SplitVectorize ||
8410 (TE->isGather() && GathersToOrders.contains(TE))) ||
8411 !TE->UserTreeIndex ||
8412 TE->UserTreeIndex.UserTE->State == TreeEntry::BlendedLoadVectorize ||
8413 !TE->ReuseShuffleIndices.empty() || !Visited.insert(TE).second)
8414 continue;
8415 // Build a map between user nodes and their operands order to speedup
8416 // search. The graph currently does not provide this dependency directly.
8417 Users.first = TE->UserTreeIndex.UserTE;
8418 Users.second.emplace_back(TE->UserTreeIndex.EdgeIdx, TE);
8419 }
8420 if (Users.first) {
8421 auto &Data = Users;
8422 // TODO: Reordering of struct types is not supported.
8423 if (Data.first->State == TreeEntry::Vectorize &&
8424 isa<StructType>(getValueType(Data.first->Scalars.front())))
8425 continue;
8426 if (Data.first->State == TreeEntry::SplitVectorize) {
8427 assert(
8428 Data.second.size() <= 2 &&
8429 "Expected not greater than 2 operands for split vectorize node.");
8430 if (any_of(Data.second,
8431 [](const auto &Op) { return !Op.second->UserTreeIndex; }))
8432 continue;
8433 // Update orders in user split vectorize nodes.
8434 assert(Data.first->CombinedEntriesWithIndices.size() == 2 &&
8435 "Expected exactly 2 entries.");
8436 for (const auto &P : Data.first->CombinedEntriesWithIndices) {
8437 TreeEntry &OpTE = *VectorizableTree[P.first];
8438 // The order of an operand that has both reordered and reused scalars
8439 // cannot be absorbed into the split node cleanly: clearing the
8440 // reorder indices while keeping the reuse mask (or vice versa)
8441 // desyncs the split node scalars from the operand effective order.
8442 // Skip reordering for such operands.
8443 if (OpTE.State != TreeEntry::SplitVectorize &&
8444 !OpTE.ReorderIndices.empty() && !OpTE.ReuseShuffleIndices.empty())
8445 continue;
8446 OrdersType Order = OpTE.ReorderIndices;
8447 if (Order.empty() || !OpTE.ReuseShuffleIndices.empty()) {
8448 if (!OpTE.isGather() && OpTE.ReuseShuffleIndices.empty())
8449 continue;
8450 const auto BestOrder =
8451 getReorderingData(OpTE, /*TopToBottom=*/false, IgnoreReorder);
8452 if (!BestOrder || BestOrder->empty() || isIdentityOrder(*BestOrder))
8453 continue;
8454 Order = *BestOrder;
8455 }
8456 fixupOrderingIndices(Order);
8457 SmallVector<int> Mask;
8458 inversePermutation(Order, Mask);
8459 const unsigned E = Order.size();
8460 SmallVector<int> MaskOrder(E, PoisonMaskElem);
8461 transform(Order, MaskOrder.begin(), [E](unsigned I) {
8462 return I < E ? static_cast<int>(I) : PoisonMaskElem;
8463 });
8464 Data.first->reorderSplitNode(P.second ? 1 : 0, Mask, MaskOrder);
8465 // Clear ordering of the operand.
8466 if (!OpTE.ReorderIndices.empty()) {
8467 OpTE.ReorderIndices.clear();
8468 } else if (!OpTE.ReuseShuffleIndices.empty()) {
8469 reorderReuses(OpTE.ReuseShuffleIndices, Mask);
8470 } else {
8471 assert(OpTE.isGather() && "Expected only gather/buildvector node.");
8472 reorderScalars(OpTE.Scalars, Mask);
8473 }
8474 }
8475 if (Data.first->ReuseShuffleIndices.empty() &&
8476 !Data.first->ReorderIndices.empty()) {
8477 // Insert user node to the list to try to sink reordering deeper in
8478 // the graph.
8479 Queue.push(Data.first);
8480 }
8481 continue;
8482 }
8483 // Do not move the operand order to the root PHI node when the root
8484 // order must be preserved: the root has no user to take over the order
8485 // and it cannot be dropped at the end of the reordering.
8486 if (!IgnoreReorder && Data.first == &getRootNode() &&
8487 !Data.first->UserTreeIndex &&
8488 Data.first->State == TreeEntry::Vectorize &&
8489 Data.first->getOpcode() == Instruction::PHI &&
8490 Data.first->ReuseShuffleIndices.empty())
8491 continue;
8492 // Check that operands are used only in the User node.
8493 SmallVector<TreeEntry *> GatherOps;
8494 buildReorderableOperands(Data.first, Data.second, NonVectorized,
8495 GatherOps);
8496 // All operands are reordered and used only in this node - propagate the
8497 // most used order to the user node.
8500 OrdersUses;
8501 // Do the analysis for each tree entry only once, otherwise the order of
8502 // the same node my be considered several times, though might be not
8503 // profitable.
8506 for (const auto &Op : Data.second) {
8507 TreeEntry *OpTE = Op.second;
8508 if (!VisitedOps.insert(OpTE).second)
8509 continue;
8510 if (!OpTE->ReuseShuffleIndices.empty() && !GathersToOrders.count(OpTE))
8511 continue;
8512 const auto Order = [&]() -> const OrdersType {
8513 if (OpTE->isGather() || !OpTE->ReuseShuffleIndices.empty())
8514 return getReorderingData(*OpTE, /*TopToBottom=*/false,
8515 IgnoreReorder)
8516 .value_or(OrdersType(1));
8517 return OpTE->ReorderIndices;
8518 }();
8519 // The order is partially ordered, skip it in favor of fully non-ordered
8520 // orders.
8521 if (Order.size() == 1)
8522 continue;
8523
8524 // Check that the reordering does not increase number of shuffles, i.e.
8525 // same-values-nodes has same parents or their parents has same parents.
8526 if (!Order.empty() && !isIdentityOrder(Order)) {
8527 Value *Root = OpTE->hasState()
8528 ? OpTE->getMainOp()
8529 : *find_if_not(OpTE->Scalars, isConstant);
8530 auto GetSameNodesUsers = [&](Value *Root) {
8532 for (const TreeEntry *TE : ValueToGatherNodes.lookup(Root)) {
8533 if (TE != OpTE && TE->UserTreeIndex &&
8534 TE->getVectorFactor() == OpTE->getVectorFactor() &&
8535 TE->Scalars.size() == OpTE->Scalars.size() &&
8536 ((TE->ReorderIndices.empty() && OpTE->isSame(TE->Scalars)) ||
8537 (OpTE->ReorderIndices.empty() && TE->isSame(OpTE->Scalars))))
8538 Res.insert(TE->UserTreeIndex.UserTE);
8539 }
8540 for (const TreeEntry *TE : getTreeEntries(Root)) {
8541 if (TE != OpTE && TE->UserTreeIndex &&
8542 TE->getVectorFactor() == OpTE->getVectorFactor() &&
8543 TE->Scalars.size() == OpTE->Scalars.size() &&
8544 ((TE->ReorderIndices.empty() && OpTE->isSame(TE->Scalars)) ||
8545 (OpTE->ReorderIndices.empty() && TE->isSame(OpTE->Scalars))))
8546 Res.insert(TE->UserTreeIndex.UserTE);
8547 }
8548 return Res.takeVector();
8549 };
8550 auto GetNumOperands = [](const TreeEntry *TE) {
8551 if (TE->State == TreeEntry::SplitVectorize)
8552 return TE->getNumOperands();
8553 if (auto *CI = dyn_cast<CallInst>(TE->getMainOp()); CI)
8554 return CI->arg_size();
8555 return TE->getNumOperands();
8556 };
8557 auto NodeShouldBeReorderedWithOperands = [&, TTI = TTI](
8558 const TreeEntry *TE) {
8560 if (auto *CI = dyn_cast<CallInst>(TE->getMainOp()); CI)
8561 ID = getVectorIntrinsicIDForCall(CI, TLI);
8562 for (unsigned Idx : seq<unsigned>(GetNumOperands(TE))) {
8563 if (ID != Intrinsic::not_intrinsic &&
8565 continue;
8566 const TreeEntry *Op = getOperandEntry(TE, Idx);
8567 if (Op->isGather() && Op->hasState()) {
8568 const TreeEntry *VecOp =
8569 getSameValuesTreeEntry(Op->getMainOp(), Op->Scalars);
8570 if (VecOp)
8571 Op = VecOp;
8572 }
8573 if (Op->ReorderIndices.empty() && Op->ReuseShuffleIndices.empty())
8574 return false;
8575 }
8576 return true;
8577 };
8578 SmallVector<TreeEntry *> Users = GetSameNodesUsers(Root);
8579 if (!Users.empty() && !all_of(Users, [&](TreeEntry *UTE) {
8580 if (!RevisitedOps.insert(UTE).second)
8581 return false;
8582 return UTE == Data.first || !UTE->ReorderIndices.empty() ||
8583 !UTE->ReuseShuffleIndices.empty() ||
8584 (UTE->UserTreeIndex &&
8585 UTE->UserTreeIndex.UserTE == Data.first) ||
8586 (Data.first->UserTreeIndex &&
8587 Data.first->UserTreeIndex.UserTE == UTE) ||
8588 (IgnoreReorder && UTE->UserTreeIndex &&
8589 UTE->UserTreeIndex.UserTE->Idx == 0) ||
8590 NodeShouldBeReorderedWithOperands(UTE);
8591 }))
8592 continue;
8593 for (TreeEntry *UTE : Users) {
8595 if (auto *CI = dyn_cast<CallInst>(UTE->getMainOp()); CI)
8596 ID = getVectorIntrinsicIDForCall(CI, TLI);
8597 for (unsigned Idx : seq<unsigned>(GetNumOperands(UTE))) {
8598 if (ID != Intrinsic::not_intrinsic &&
8600 continue;
8601 const TreeEntry *Op = getOperandEntry(UTE, Idx);
8602 Visited.erase(Op);
8603 Queue.push(const_cast<TreeEntry *>(Op));
8604 }
8605 }
8606 }
8607 unsigned NumOps = count_if(
8608 Data.second, [OpTE](const std::pair<unsigned, TreeEntry *> &P) {
8609 return P.second == OpTE;
8610 });
8611 // Stores actually store the mask, not the order, need to invert.
8612 if (OpTE->State == TreeEntry::Vectorize &&
8613 OpTE->getOpcode() == Instruction::Store && !Order.empty()) {
8614 assert(!OpTE->isAltShuffle() &&
8615 "Alternate instructions are only supported by BinaryOperator "
8616 "and CastInst.");
8617 SmallVector<int> Mask;
8618 inversePermutation(Order, Mask);
8619 unsigned E = Order.size();
8620 OrdersType CurrentOrder(E, E);
8621 transform(Mask, CurrentOrder.begin(), [E](int Idx) {
8622 return Idx == PoisonMaskElem ? E : static_cast<unsigned>(Idx);
8623 });
8624 fixupOrderingIndices(CurrentOrder);
8625 OrdersUses.try_emplace(CurrentOrder, 0).first->second += NumOps;
8626 } else {
8627 OrdersUses.try_emplace(Order, 0).first->second += NumOps;
8628 }
8629 auto Res = OrdersUses.try_emplace(OrdersType(), 0);
8630 const auto AllowsReordering = [&](const TreeEntry *TE) {
8631 if (!TE->ReorderIndices.empty() || !TE->ReuseShuffleIndices.empty() ||
8632 (TE->State == TreeEntry::Vectorize && TE->isAltShuffle()) ||
8633 (IgnoreReorder && TE->Idx == 0))
8634 return true;
8635 if (TE->isGather()) {
8636 if (GathersToOrders.contains(TE))
8637 return !getReorderingData(*TE, /*TopToBottom=*/false,
8638 IgnoreReorder)
8639 .value_or(OrdersType(1))
8640 .empty();
8641 return true;
8642 }
8643 return false;
8644 };
8645 if (OpTE->UserTreeIndex) {
8646 TreeEntry *UserTE = OpTE->UserTreeIndex.UserTE;
8647 if (!VisitedUsers.insert(UserTE).second)
8648 continue;
8649 // May reorder user node if it requires reordering, has reused
8650 // scalars, is an alternate op vectorize node or its op nodes require
8651 // reordering.
8652 if (AllowsReordering(UserTE))
8653 continue;
8654 // Check if users allow reordering.
8655 // Currently look up just 1 level of operands to avoid increase of
8656 // the compile time.
8657 // Profitable to reorder if definitely more operands allow
8658 // reordering rather than those with natural order.
8660 if (static_cast<unsigned>(count_if(
8661 Ops, [UserTE, &AllowsReordering](
8662 const std::pair<unsigned, TreeEntry *> &Op) {
8663 return AllowsReordering(Op.second) &&
8664 Op.second->UserTreeIndex.UserTE == UserTE;
8665 })) <= Ops.size() / 2)
8666 ++Res.first->second;
8667 }
8668 }
8669 if (OrdersUses.empty()) {
8670 Visited.insert_range(llvm::make_second_range(Data.second));
8671 continue;
8672 }
8673 // Choose the most used order.
8674 unsigned IdentityCnt = 0;
8675 unsigned VF = Data.second.front().second->getVectorFactor();
8676 OrdersType IdentityOrder(VF, VF);
8677 for (auto &Pair : OrdersUses) {
8678 if (Pair.first.empty() || isIdentityOrder(Pair.first)) {
8679 IdentityCnt += Pair.second;
8680 combineOrders(IdentityOrder, Pair.first);
8681 }
8682 }
8683 MutableArrayRef<unsigned> BestOrder = IdentityOrder;
8684 unsigned Cnt = IdentityCnt;
8685 for (auto &Pair : OrdersUses) {
8686 // Prefer identity order. But, if filled identity found (non-empty
8687 // order) with same number of uses, as the new candidate order, we can
8688 // choose this candidate order.
8689 if (Cnt < Pair.second) {
8690 combineOrders(Pair.first, BestOrder);
8691 BestOrder = Pair.first;
8692 Cnt = Pair.second;
8693 } else {
8694 combineOrders(BestOrder, Pair.first);
8695 }
8696 }
8697 // Set order of the user node.
8698 if (isIdentityOrder(BestOrder)) {
8699 Visited.insert_range(llvm::make_second_range(Data.second));
8700 continue;
8701 }
8702 fixupOrderingIndices(BestOrder);
8703 // Erase operands from OrderedEntries list and adjust their orders.
8704 VisitedOps.clear();
8705 SmallVector<int> Mask;
8706 inversePermutation(BestOrder, Mask);
8707 SmallVector<int> MaskOrder(BestOrder.size(), PoisonMaskElem);
8708 unsigned E = BestOrder.size();
8709 transform(BestOrder, MaskOrder.begin(), [E](unsigned I) {
8710 return I < E ? static_cast<int>(I) : PoisonMaskElem;
8711 });
8712 for (const std::pair<unsigned, TreeEntry *> &Op : Data.second) {
8713 TreeEntry *TE = Op.second;
8714 if (!VisitedOps.insert(TE).second)
8715 continue;
8716 // TODO: Reordering of struct types is not supported.
8717 if (TE->State == TreeEntry::Vectorize &&
8718 isa<StructType>(getValueType(TE->Scalars.front())))
8719 continue;
8720 if (TE->ReuseShuffleIndices.size() == BestOrder.size()) {
8721 reorderNodeWithReuses(*TE, Mask);
8722 continue;
8723 }
8724 // Gathers are processed separately.
8725 if (TE->State != TreeEntry::Vectorize &&
8726 TE->State != TreeEntry::StridedVectorize &&
8727 TE->State != TreeEntry::ExpandVectorize &&
8728 TE->State != TreeEntry::CompressVectorize &&
8729 TE->State != TreeEntry::BlendedLoadVectorize &&
8730 TE->State != TreeEntry::SplitVectorize &&
8731 (TE->State != TreeEntry::ScatterVectorize ||
8732 TE->ReorderIndices.empty()))
8733 continue;
8734 assert((BestOrder.size() == TE->ReorderIndices.size() ||
8735 TE->ReorderIndices.empty()) &&
8736 "Non-matching sizes of user/operand entries.");
8737 reorderOrder(TE->ReorderIndices, Mask);
8738 if (IgnoreReorder && TE == &getRootNode())
8739 IgnoreReorder = false;
8740 }
8741 // For gathers just need to reorder its scalars.
8742 for (TreeEntry *Gather : GatherOps) {
8743 assert(Gather->ReorderIndices.empty() &&
8744 "Unexpected reordering of gathers.");
8745 if (!Gather->ReuseShuffleIndices.empty()) {
8746 // Just reorder reuses indices.
8747 reorderReuses(Gather->ReuseShuffleIndices, Mask);
8748 continue;
8749 }
8750 // A ScatterVectorize (masked gather) node is scheduled, and the
8751 // scheduler reads its operand list at the same lane where the scalar
8752 // load sits, so Scalars and the operand list must stay aligned.
8753 // Record the reorder in ReorderIndices (applied by the final shuffle)
8754 // instead of physically permuting the scalars, matching how a scatter
8755 // node with a non-empty order is reordered above.
8756 if (Gather->State == TreeEntry::ScatterVectorize) {
8757 reorderOrder(Gather->ReorderIndices, Mask);
8758 Visited.insert(Gather);
8759 continue;
8760 }
8761 reorderScalars(Gather->Scalars, Mask);
8762 Visited.insert(Gather);
8763 }
8764 // Reorder operands of the user node and set the ordering for the user
8765 // node itself.
8766 auto IsNotProfitableAltCodeNode = [](const TreeEntry &TE) {
8767 return TE.isAltShuffle() &&
8768 (!TE.ReuseShuffleIndices.empty() || TE.getVectorFactor() == 2 ||
8769 TE.ReorderIndices.empty());
8770 };
8771 if (Data.first->State != TreeEntry::Vectorize ||
8773 Data.first->getMainOp()) ||
8774 IsNotProfitableAltCodeNode(*Data.first)) {
8775 Data.first->reorderOperands(Mask);
8777 }
8779 Data.first->getMainOp()) ||
8780 IsNotProfitableAltCodeNode(*Data.first) ||
8781 Data.first->State == TreeEntry::CompressVectorize) {
8782 reorderScalars(Data.first->Scalars, Mask);
8783 reorderOrder(Data.first->ReorderIndices, MaskOrder,
8784 /*BottomOrder=*/true);
8785 if (Data.first->ReuseShuffleIndices.empty() &&
8786 !Data.first->ReorderIndices.empty() &&
8787 !IsNotProfitableAltCodeNode(*Data.first)) {
8788 // Insert user node to the list to try to sink reordering deeper in
8789 // the graph.
8790 Queue.push(Data.first);
8791 }
8792 } else {
8793 reorderOrder(Data.first->ReorderIndices, Mask);
8794 }
8795 }
8796 }
8797 // If the reordering is unnecessary, just remove the reorder.
8798 if (IgnoreReorder && !getRootNode().ReorderIndices.empty() &&
8799 getRootNode().ReuseShuffleIndices.empty())
8800 getRootNode().ReorderIndices.clear();
8801}
8802
8803Instruction *BoUpSLP::getRootEntryInstruction(const TreeEntry &Entry) const {
8804 if (Entry.hasState() &&
8805 (Entry.getOpcode() == Instruction::Store ||
8806 Entry.getOpcode() == Instruction::Load) &&
8807 Entry.State == TreeEntry::StridedVectorize &&
8808 !Entry.ReorderIndices.empty() && isReverseOrder(Entry.ReorderIndices))
8809 return dyn_cast<Instruction>(Entry.Scalars[Entry.ReorderIndices.front()]);
8810 return dyn_cast<Instruction>(Entry.Scalars.front());
8811}
8812
8814 const ExtraValueToDebugLocsMap &ExternallyUsedValues) {
8815 const size_t NumVectScalars = ScalarToTreeEntries.size() + 1;
8816 DenseMap<Value *, unsigned> ScalarToExtUses;
8817 // Peeled scalars still claimed by the tree (gathered, listed in some
8818 // entry's scalars, or modeled as a copyable element, which is emitted as
8819 // a scalar) survive as plain code, along with the peeled scalars
8820 // in their operand chains, which no vector node can rematerialize.
8821 KeptReassocScalars.clear();
8822 SmallVector<const Value *, 8> KeptWorklist;
8823 for (const auto &[V, Owners] : ReassocScalarToTreeEntries)
8824 if ((isGathered(V) || !getTreeEntries(V).empty() ||
8825 any_of(Owners,
8826 [V = V](const TreeEntry *TE) {
8827 return TE->isCopyableElement(const_cast<Value *>(V));
8828 })) &&
8829 KeptReassocScalars.insert(V).second)
8830 KeptWorklist.push_back(V);
8831 while (!KeptWorklist.empty()) {
8832 const Value *V = KeptWorklist.pop_back_val();
8833 for (const Value *Op : cast<Instruction>(V)->operand_values())
8834 if (ReassocScalarToTreeEntries.contains(Op) &&
8835 KeptReassocScalars.insert(Op).second)
8836 KeptWorklist.push_back(Op);
8837 }
8838 // Collect the values that we need to extract from the tree.
8839 for (auto &TEPtr : VectorizableTree) {
8840 TreeEntry *Entry = TEPtr.get();
8841
8842 // No need to handle users of gathered values.
8843 if (Entry->isGather() || Entry->State == TreeEntry::SplitVectorize ||
8844 DeletedNodes.contains(Entry) ||
8845 TransformedToGatherNodes.contains(Entry))
8846 continue;
8847
8848 // For each lane:
8849 for (int Lane = 0, LE = Entry->Scalars.size(); Lane != LE; ++Lane) {
8850 Value *Scalar = Entry->Scalars[Lane];
8851 if (!isa<Instruction>(Scalar) || Entry->isCopyableElement(Scalar))
8852 continue;
8853 bool IsStructScalar = isa<StructType>(Scalar->getType());
8854
8855 // All uses must be replaced already? No need to do it again.
8856 auto It = ScalarToExtUses.find(Scalar);
8857 if (It != ScalarToExtUses.end() && !ExternalUses[It->second].User)
8858 continue;
8859
8860 if (!IsStructScalar && Scalar->hasNUsesOrMore(NumVectScalars)) {
8861 unsigned FoundLane = Entry->findLaneForValue(Scalar);
8862 LLVM_DEBUG(dbgs() << "SLP: Need to extract from lane " << FoundLane
8863 << " from " << *Scalar << "for many users.\n");
8864 It = ScalarToExtUses.try_emplace(Scalar, ExternalUses.size()).first;
8865 ExternalUses.emplace_back(Scalar, nullptr, *Entry, FoundLane);
8866 ExternalUsesWithNonUsers.insert(Scalar);
8867 continue;
8868 }
8869
8870 // Check if the scalar is externally used as an extra arg.
8871 const auto ExtI = ExternallyUsedValues.find(Scalar);
8872 if (ExtI != ExternallyUsedValues.end()) {
8873 unsigned FoundLane = Entry->findLaneForValue(Scalar);
8874 LLVM_DEBUG(dbgs() << "SLP: Need to extract: Extra arg from lane "
8875 << FoundLane << " from " << *Scalar << ".\n");
8876 ScalarToExtUses.try_emplace(Scalar, ExternalUses.size());
8877 ExternalUses.emplace_back(Scalar, nullptr, *Entry, FoundLane);
8878 continue;
8879 }
8880 for (User *U : Scalar->users()) {
8881 LLVM_DEBUG(dbgs() << "SLP: Checking user:" << *U << ".\n");
8882
8883 Instruction *UserInst = dyn_cast<Instruction>(U);
8884 if (!UserInst || isDeleted(UserInst))
8885 continue;
8886
8887 // Ignore users in the user ignore list.
8888 if (UserIgnoreList && UserIgnoreList->contains(UserInst))
8889 continue;
8890
8891 // Peeled reassociated scalars are subsumed by the flattened node and
8892 // erased during vectorization, not external users. Kept ones survive
8893 // and their uses of erased scalars become extracts like any other.
8894 if (isReassocScalarVectorized(UserInst) &&
8895 !KeptReassocScalars.contains(UserInst)) {
8896 LLVM_DEBUG(dbgs() << "SLP: \tInternal (reassociated) user will be "
8897 "removed:"
8898 << *U << ".\n");
8899 continue;
8900 }
8901
8902 // Skip in-tree scalars that become vectors
8903 if (ArrayRef<TreeEntry *> UseEntries = getTreeEntries(U);
8904 any_of(UseEntries, [this](const TreeEntry *UseEntry) {
8905 return !DeletedNodes.contains(UseEntry) &&
8906 !TransformedToGatherNodes.contains(UseEntry);
8907 })) {
8908 // Some in-tree scalars will remain as scalar in vectorized
8909 // instructions. If that is the case, the one in FoundLane will
8910 // be used.
8911 if (!((Scalar->getType()->getScalarType()->isPointerTy() &&
8912 isa<LoadInst, StoreInst>(UserInst)) ||
8913 isa<CallInst>(UserInst)) ||
8914 all_of(UseEntries, [&](TreeEntry *UseEntry) {
8915 if (DeletedNodes.contains(UseEntry) ||
8916 TransformedToGatherNodes.contains(UseEntry))
8917 return true;
8918 return UseEntry->State == TreeEntry::ScatterVectorize ||
8920 Scalar, getRootEntryInstruction(*UseEntry), TLI,
8921 TTI);
8922 })) {
8923 LLVM_DEBUG(dbgs() << "SLP: \tInternal user will be removed:" << *U
8924 << ".\n");
8925 assert(none_of(UseEntries,
8926 [](TreeEntry *UseEntry) {
8927 return UseEntry->isGather();
8928 }) &&
8929 "Bad state");
8930 continue;
8931 }
8932 if (!IsStructScalar) {
8933 U = nullptr;
8934 if (It != ScalarToExtUses.end()) {
8935 ExternalUses[It->second].User = nullptr;
8936 break;
8937 }
8938 }
8939 }
8940
8941 if (U && !IsStructScalar && Scalar->hasNUsesOrMore(UsesLimit))
8942 U = nullptr;
8943 unsigned FoundLane = Entry->findLaneForValue(Scalar);
8944 LLVM_DEBUG(dbgs() << "SLP: Need to extract:" << *UserInst
8945 << " from lane " << FoundLane << " from " << *Scalar
8946 << ".\n");
8947 It = ScalarToExtUses.try_emplace(Scalar, ExternalUses.size()).first;
8948 ExternalUses.emplace_back(Scalar, U, *Entry, FoundLane);
8949 ExternalUsesWithNonUsers.insert(Scalar);
8950 if (!U)
8951 break;
8952 }
8953 }
8954 }
8955
8956 // The expansion of the runtime stride may reuse an in-tree instruction with
8957 // the matching SCEV, which gets erased upon vectorization. Register an
8958 // external use for it to replace the stride operand with the extract.
8960 for (const auto &[StridedTE, SPtrInfo] : TreeEntryToStridedPtrInfoMap)
8961 if (SPtrInfo.StrideSCEV && !SPtrInfo.StrideVal &&
8962 !DeletedNodes.contains(StridedTE) &&
8963 !TransformedToGatherNodes.contains(StridedTE))
8964 Strides.emplace_back(SPtrInfo.StrideSCEV,
8965 StridedTE->getMainOp()->getParent());
8966 if (Strides.empty())
8967 return;
8968 for (const std::unique_ptr<TreeEntry> &TEPtr : VectorizableTree) {
8969 TreeEntry *Entry = TEPtr.get();
8970 if (Entry->isGather() || Entry->State == TreeEntry::SplitVectorize ||
8971 DeletedNodes.contains(Entry) ||
8972 TransformedToGatherNodes.contains(Entry))
8973 continue;
8974 for (Value *Scalar : Entry->Scalars) {
8975 auto *I = dyn_cast<Instruction>(Scalar);
8976 if (!I || Entry->isCopyableElement(I) || !SE->isSCEVable(I->getType()))
8977 continue;
8978 const SCEV *ScalarSCEV = SE->getSCEV(I);
8979 if (isa<SCEVConstant>(ScalarSCEV) ||
8980 none_of(Strides, [&](const auto &Stride) {
8981 return DT->dominates(I, Stride.second->getTerminator()) &&
8982 SCEVExprContains(Stride.first, [ScalarSCEV](const SCEV *S) {
8983 return S == ScalarSCEV;
8984 });
8985 }))
8986 continue;
8987 auto It = ScalarToExtUses.find(Scalar);
8988 if (It != ScalarToExtUses.end()) {
8989 // Replace all uses: the stride operand is emitted later, during the
8990 // codegen.
8991 ExternalUses[It->second].User = nullptr;
8992 continue;
8993 }
8994 unsigned FoundLane = Entry->findLaneForValue(Scalar);
8995 LLVM_DEBUG(dbgs() << "SLP: Need to extract: strided load stride from "
8996 "lane "
8997 << FoundLane << " from " << *Scalar << ".\n");
8998 ScalarToExtUses.try_emplace(Scalar, ExternalUses.size());
8999 ExternalUses.emplace_back(Scalar, nullptr, *Entry, FoundLane);
9000 ExternalUsesWithNonUsers.insert(Scalar);
9001 }
9002 }
9003}
9004
9006BoUpSLP::collectUserStores(const BoUpSLP::TreeEntry *TE) const {
9009 PtrToStoresMap;
9010 for (unsigned Lane : seq<unsigned>(0, TE->Scalars.size())) {
9011 Value *V = TE->Scalars[Lane];
9012 // Don't iterate over the users of constant data.
9013 if (!isa<Instruction>(V))
9014 continue;
9015 // To save compilation time we don't visit if we have too many users.
9016 if (V->hasNUsesOrMore(UsesLimit))
9017 break;
9018
9019 // Collect stores per pointer object.
9020 for (User *U : V->users()) {
9021 auto *SI = dyn_cast<StoreInst>(U);
9022 // Test whether we can handle the store. V might be a global, which could
9023 // be used in a different function.
9024 if (SI == nullptr || !SI->isSimple() || SI->getFunction() != F ||
9025 !isValidElementType(SI->getValueOperand()->getType()))
9026 continue;
9027 // Skip entry if already
9028 if (isVectorized(U))
9029 continue;
9030
9031 Value *Ptr =
9032 getUnderlyingObject(SI->getPointerOperand(), RecursionMaxDepth);
9033 auto &StoresVec = PtrToStoresMap[{SI->getParent(),
9034 SI->getValueOperand()->getType(), Ptr}];
9035 // For now just keep one store per pointer object per lane.
9036 // TODO: Extend this to support multiple stores per pointer per lane
9037 if (StoresVec.size() > Lane)
9038 continue;
9039 if (!StoresVec.empty()) {
9040 std::optional<int64_t> Diff = getPointersDiff(
9041 SI->getValueOperand()->getType(), SI->getPointerOperand(),
9042 SI->getValueOperand()->getType(),
9043 StoresVec.front()->getPointerOperand(), *DL, *SE,
9044 /*StrictCheck=*/true);
9045 // We failed to compare the pointers so just abandon this store.
9046 if (!Diff)
9047 continue;
9048 }
9049 StoresVec.push_back(SI);
9050 }
9051 }
9052 SmallVector<SmallVector<StoreInst *>> Res(PtrToStoresMap.size());
9053 unsigned I = 0;
9054 for (auto &P : PtrToStoresMap) {
9055 Res[I].swap(P.second);
9056 ++I;
9057 }
9058 return Res;
9059}
9060
9061bool BoUpSLP::canFormVector(ArrayRef<StoreInst *> StoresVec,
9062 OrdersType &ReorderIndices) const {
9063 // We check whether the stores in StoreVec can form a vector by sorting them
9064 // and checking whether they are consecutive.
9065
9066 // To avoid calling getPointersDiff() while sorting we create a vector of
9067 // pairs {store, offset from first} and sort this instead.
9069 StoreInst *S0 = StoresVec[0];
9070 StoreOffsetVec.emplace_back(0, 0);
9071 Type *S0Ty = S0->getValueOperand()->getType();
9072 Value *S0Ptr = S0->getPointerOperand();
9073 for (unsigned Idx : seq<unsigned>(1, StoresVec.size())) {
9074 StoreInst *SI = StoresVec[Idx];
9075 std::optional<int64_t> Diff =
9076 getPointersDiff(S0Ty, S0Ptr, SI->getValueOperand()->getType(),
9077 SI->getPointerOperand(), *DL, *SE,
9078 /*StrictCheck=*/true);
9079 StoreOffsetVec.emplace_back(*Diff, Idx);
9080 }
9081
9082 // Check if the stores are consecutive by checking if their difference is 1.
9083 if (StoreOffsetVec.size() != StoresVec.size())
9084 return false;
9085 sort(StoreOffsetVec, llvm::less_first());
9086 unsigned Idx = 0;
9087 int64_t PrevDist = 0;
9088 for (const auto &P : StoreOffsetVec) {
9089 if (Idx > 0 && P.first != PrevDist + 1)
9090 return false;
9091 PrevDist = P.first;
9092 ++Idx;
9093 }
9094
9095 // Calculate the shuffle indices according to their offset against the sorted
9096 // StoreOffsetVec.
9097 ReorderIndices.assign(StoresVec.size(), 0);
9098 bool IsIdentity = true;
9099 for (auto [I, P] : enumerate(StoreOffsetVec)) {
9100 ReorderIndices[P.second] = I;
9101 IsIdentity &= P.second == I;
9102 }
9103 // Identity order (e.g., {0,1,2,3}) is modeled as an empty OrdersType in
9104 // reorderTopToBottom() and reorderBottomToTop(), so we are following the
9105 // same convention here.
9106 if (IsIdentity)
9107 ReorderIndices.clear();
9108
9109 return true;
9110}
9111
9112#ifndef NDEBUG
9114 for (unsigned Idx : Order)
9115 dbgs() << Idx << ", ";
9116 dbgs() << "\n";
9117}
9118#endif
9119
9121BoUpSLP::findExternalStoreUsersReorderIndices(TreeEntry *TE) const {
9122 unsigned NumLanes = TE->Scalars.size();
9123
9124 SmallVector<SmallVector<StoreInst *>> Stores = collectUserStores(TE);
9125
9126 // Holds the reorder indices for each candidate store vector that is a user of
9127 // the current TreeEntry.
9128 SmallVector<OrdersType, 1> ExternalReorderIndices;
9129
9130 // Now inspect the stores collected per pointer and look for vectorization
9131 // candidates. For each candidate calculate the reorder index vector and push
9132 // it into `ExternalReorderIndices`
9133 for (ArrayRef<StoreInst *> StoresVec : Stores) {
9134 // If we have fewer than NumLanes stores, then we can't form a vector.
9135 if (StoresVec.size() != NumLanes)
9136 continue;
9137
9138 // If the stores are not consecutive then abandon this StoresVec.
9139 OrdersType ReorderIndices;
9140 if (!canFormVector(StoresVec, ReorderIndices))
9141 continue;
9142
9143 // We now know that the scalars in StoresVec can form a vector instruction,
9144 // so set the reorder indices.
9145 ExternalReorderIndices.push_back(ReorderIndices);
9146 }
9147 return ExternalReorderIndices;
9148}
9149
9151 const SmallDenseSet<Value *> &UserIgnoreLst) {
9152 deleteTree();
9153 assert(TreeEntryToStridedPtrInfoMap.empty() &&
9154 "TreeEntryToStridedPtrInfoMap is not cleared");
9155 UserIgnoreList = &UserIgnoreLst;
9156 if (!allSameType(Roots))
9157 return;
9158 buildTreeRec(Roots, 0, EdgeInfo());
9159}
9160
9162 deleteTree();
9163 assert(TreeEntryToStridedPtrInfoMap.empty() &&
9164 "TreeEntryToStridedPtrInfoMap is not cleared");
9165 if (!allSameType(Roots))
9166 return;
9167 buildTreeRec(Roots, 0, EdgeInfo());
9168}
9169
9170/// Tries to find subvector of loads and builds new vector of only loads if can
9171/// be profitable.
9173 const BoUpSLP &R, ArrayRef<Value *> VL, const DataLayout &DL,
9175 SmallVectorImpl<SmallVector<std::pair<LoadInst *, int64_t>>> &GatheredLoads,
9176 bool AddNew = true) {
9177 if (VL.empty())
9178 return;
9179 Type *ScalarTy = getValueType(VL.front());
9180 if (!isValidElementType(ScalarTy))
9181 return;
9183 SmallVector<DenseMap<int64_t, LoadInst *>> ClusteredDistToLoad;
9184 for (Value *V : VL) {
9185 auto *LI = dyn_cast<LoadInst>(V);
9186 if (!LI)
9187 continue;
9188 if (R.isDeleted(LI) || R.isVectorized(LI) || !LI->isSimple())
9189 continue;
9190 bool IsFound = false;
9191 for (auto [Map, Data] : zip(ClusteredDistToLoad, ClusteredLoads)) {
9192 assert(LI->getParent() == Data.front().first->getParent() &&
9193 LI->getType() == Data.front().first->getType() &&
9194 getUnderlyingObject(LI->getPointerOperand(), RecursionMaxDepth) ==
9195 getUnderlyingObject(Data.front().first->getPointerOperand(),
9197 "Expected loads with the same type, same parent and same "
9198 "underlying pointer.");
9199 std::optional<int64_t> Dist = getPointersDiff(
9200 LI->getType(), LI->getPointerOperand(), Data.front().first->getType(),
9201 Data.front().first->getPointerOperand(), DL, SE,
9202 /*StrictCheck=*/true);
9203 if (!Dist)
9204 continue;
9205 auto It = Map.find(*Dist);
9206 if (It != Map.end() && It->second != LI)
9207 continue;
9208 if (It == Map.end()) {
9209 Data.emplace_back(LI, *Dist);
9210 Map.try_emplace(*Dist, LI);
9211 }
9212 IsFound = true;
9213 break;
9214 }
9215 if (!IsFound) {
9216 ClusteredLoads.emplace_back().emplace_back(LI, 0);
9217 ClusteredDistToLoad.emplace_back().try_emplace(0, LI);
9218 }
9219 }
9220 auto FindMatchingLoads =
9223 &GatheredLoads,
9225 int64_t &Offset, unsigned &Start) {
9226 if (Loads.empty())
9227 return GatheredLoads.end();
9228 LoadInst *LI = Loads.front().first;
9229 for (auto [Idx, Data] : enumerate(GatheredLoads)) {
9230 if (Idx < Start)
9231 continue;
9232 ToAdd.clear();
9233 if (LI->getParent() != Data.front().first->getParent() ||
9234 LI->getType() != Data.front().first->getType())
9235 continue;
9236 std::optional<int64_t> Dist =
9238 Data.front().first->getType(),
9239 Data.front().first->getPointerOperand(), DL, SE,
9240 /*StrictCheck=*/true);
9241 if (!Dist)
9242 continue;
9243 SmallSet<int64_t, 4> DataDists;
9245 for (std::pair<LoadInst *, int64_t> P : Data) {
9246 DataDists.insert(P.second);
9247 DataLoads.insert(P.first);
9248 }
9249 // Found matching gathered loads - check if all loads are unique or
9250 // can be effectively vectorized.
9251 unsigned NumUniques = 0;
9252 for (auto [Cnt, Pair] : enumerate(Loads)) {
9253 bool Used = DataLoads.contains(Pair.first);
9254 if (!Used && !DataDists.contains(*Dist + Pair.second)) {
9255 ++NumUniques;
9256 ToAdd.insert(Cnt);
9257 } else if (Used) {
9258 Repeated.insert(Cnt);
9259 }
9260 }
9261 if (NumUniques > 0 &&
9262 (Loads.size() == NumUniques ||
9263 (Loads.size() - NumUniques >= 2 &&
9264 Loads.size() - NumUniques >= Loads.size() / 2 &&
9265 (has_single_bit(Data.size() + NumUniques) ||
9266 bit_ceil(Data.size()) <
9267 bit_ceil(Data.size() + NumUniques))))) {
9268 Offset = *Dist;
9269 Start = Idx + 1;
9270 return std::next(GatheredLoads.begin(), Idx);
9271 }
9272 }
9273 ToAdd.clear();
9274 return GatheredLoads.end();
9275 };
9276 for (ArrayRef<std::pair<LoadInst *, int64_t>> Data : ClusteredLoads) {
9277 unsigned Start = 0;
9278 SetVector<unsigned> ToAdd, LocalToAdd, Repeated;
9279 int64_t Offset = 0;
9280 auto *It = FindMatchingLoads(Data, GatheredLoads, LocalToAdd, Repeated,
9281 Offset, Start);
9282 while (It != GatheredLoads.end()) {
9283 assert(!LocalToAdd.empty() && "Expected some elements to add.");
9284 for (unsigned Idx : LocalToAdd)
9285 It->emplace_back(Data[Idx].first, Data[Idx].second + Offset);
9286 ToAdd.insert_range(LocalToAdd);
9287 It = FindMatchingLoads(Data, GatheredLoads, LocalToAdd, Repeated, Offset,
9288 Start);
9289 }
9290 if (any_of(seq<unsigned>(Data.size()), [&](unsigned Idx) {
9291 return !ToAdd.contains(Idx) && !Repeated.contains(Idx);
9292 })) {
9293 auto AddNewLoads =
9295 for (unsigned Idx : seq<unsigned>(Data.size())) {
9296 if (ToAdd.contains(Idx) || Repeated.contains(Idx))
9297 continue;
9298 Loads.push_back(Data[Idx]);
9299 }
9300 };
9301 if (!AddNew) {
9302 LoadInst *LI = Data.front().first;
9303 It = find_if(
9304 GatheredLoads, [&](ArrayRef<std::pair<LoadInst *, int64_t>> PD) {
9305 return PD.front().first->getParent() == LI->getParent() &&
9306 PD.front().first->getType() == LI->getType();
9307 });
9308 while (It != GatheredLoads.end()) {
9309 AddNewLoads(*It);
9310 It = std::find_if(
9311 std::next(It), GatheredLoads.end(),
9312 [&](ArrayRef<std::pair<LoadInst *, int64_t>> PD) {
9313 return PD.front().first->getParent() == LI->getParent() &&
9314 PD.front().first->getType() == LI->getType();
9315 });
9316 }
9317 }
9318 GatheredLoads.emplace_back().append(Data.begin(), Data.end());
9319 AddNewLoads(GatheredLoads.emplace_back());
9320 }
9321 }
9322}
9323
9324void BoUpSLP::tryToVectorizeGatheredLoads(
9325 const SmallMapVector<
9326 std::tuple<BasicBlock *, Value *, Type *>,
9327 SmallVector<SmallVector<std::pair<LoadInst *, int64_t>>>, 8>
9328 &GatheredLoads) {
9329 GatheredLoadsEntriesFirst = VectorizableTree.size();
9330
9331 SmallVector<SmallPtrSet<const Value *, 4>> LoadSetsToVectorize(
9332 LoadEntriesToVectorize.size());
9333 for (auto [Idx, Set] : zip(LoadEntriesToVectorize, LoadSetsToVectorize))
9334 Set.insert_range(VectorizableTree[Idx]->Scalars);
9335
9336 // Sort loads by distance.
9337 auto LoadSorter = [](const std::pair<LoadInst *, int64_t> &L1,
9338 const std::pair<LoadInst *, int64_t> &L2) {
9339 return L1.second > L2.second;
9340 };
9341
9342 auto IsMaskedGatherSupported = [&, TTI = TTI](ArrayRef<LoadInst *> Loads) {
9343 ArrayRef<Value *> Values(reinterpret_cast<Value *const *>(Loads.begin()),
9344 Loads.size());
9346 auto *Ty = cast<VectorType>(
9347 getWidenedType(Loads.front()->getType(), Loads.size()));
9348 return TTI->isLegalMaskedGather(Ty, Alignment) &&
9349 !TTI->forceScalarizeMaskedGather(Ty, Alignment);
9350 };
9351
9352 auto GetVectorizedRanges = [this](ArrayRef<LoadInst *> Loads,
9353 BoUpSLP::ValueSet &VectorizedLoads,
9354 SmallVectorImpl<LoadInst *> &NonVectorized,
9355 bool Final, unsigned MaxVF) {
9357 unsigned StartIdx = 0;
9358 SmallVector<int> CandidateVFs;
9359 if (isAllowedNonPowerOf2VF(MaxVF))
9360 CandidateVFs.push_back(MaxVF);
9361 for (int NumElts = getFloorFullVectorNumberOfElements(
9362 *TTI, Loads.front()->getType(), MaxVF);
9363 NumElts > 1; NumElts = getFloorFullVectorNumberOfElements(
9364 *TTI, Loads.front()->getType(), NumElts - 1)) {
9365 CandidateVFs.push_back(NumElts);
9366 if (VectorizeNonPowerOf2 && NumElts > 2)
9367 CandidateVFs.push_back(NumElts - 1);
9368 }
9369
9370 if (Final && CandidateVFs.empty())
9371 return Results;
9372
9373 unsigned BestVF = Final ? CandidateVFs.back() : 0;
9374 for (unsigned NumElts : CandidateVFs) {
9375 if (Final && NumElts > BestVF)
9376 continue;
9377 SmallVector<unsigned> MaskedGatherVectorized;
9378 for (unsigned Cnt = StartIdx, E = Loads.size(); Cnt < E;
9379 ++Cnt) {
9380 ArrayRef<LoadInst *> Slice =
9381 ArrayRef(Loads).slice(Cnt, std::min(NumElts, E - Cnt));
9382 if (VectorizedLoads.count(Slice.front()) ||
9383 VectorizedLoads.count(Slice.back()) ||
9385 continue;
9386 // Check if it is profitable to try vectorizing gathered loads. It is
9387 // profitable if we have more than 3 consecutive loads or if we have
9388 // less but all users are vectorized or deleted.
9389 bool AllowToVectorize = false;
9390 // Check if it is profitable to vectorize 2-elements loads.
9391 if (NumElts == 2) {
9392 bool IsLegalBroadcastLoad = TTI->isLegalBroadcastLoad(
9393 Slice.front()->getType(), ElementCount::getFixed(NumElts));
9394 auto CheckIfAllowed = [=](ArrayRef<LoadInst *> Slice) {
9395 for (LoadInst *LI : Slice) {
9396 // If single use/user - allow to vectorize.
9397 if (LI->hasOneUse())
9398 continue;
9399 // 1. Check if number of uses equals number of users.
9400 // 2. All users are deleted.
9401 // 3. The load broadcasts are not allowed or the load is not
9402 // broadcasted.
9403 if (static_cast<unsigned int>(std::distance(
9404 LI->user_begin(), LI->user_end())) != LI->getNumUses())
9405 return false;
9406 if (!IsLegalBroadcastLoad)
9407 continue;
9408 if (LI->hasNUsesOrMore(UsesLimit))
9409 return false;
9410 for (User *U : LI->users()) {
9411 if (auto *UI = dyn_cast<Instruction>(U); UI && isDeleted(UI))
9412 continue;
9413 for (const TreeEntry *UTE : getTreeEntries(U)) {
9414 for (int I : seq<int>(UTE->getNumOperands())) {
9415 if (all_of(UTE->getOperand(I), [LI](Value *V) {
9416 return V == LI || isa<PoisonValue>(V);
9417 }))
9418 // Found legal broadcast - do not vectorize.
9419 return false;
9420 }
9421 }
9422 }
9423 }
9424 return true;
9425 };
9426 AllowToVectorize = CheckIfAllowed(Slice);
9427 } else {
9428 AllowToVectorize =
9429 NumElts >= 3 ||
9430 any_of(ValueToGatherNodes.at(Slice.front()),
9431 [=](const TreeEntry *TE) {
9432 return TE->Scalars.size() == 2 &&
9433 ((TE->Scalars.front() == Slice.front() &&
9434 TE->Scalars.back() == Slice.back()) ||
9435 (TE->Scalars.front() == Slice.back() &&
9436 TE->Scalars.back() == Slice.front()));
9437 });
9438 }
9439 if (AllowToVectorize) {
9440 SmallVector<Value *> PointerOps;
9441 OrdersType CurrentOrder;
9442 // Try to build vector load.
9444 reinterpret_cast<Value *const *>(Slice.begin()), Slice.size());
9445 StridedPtrInfo SPtrInfo;
9446 LoadsState LS = canVectorizeLoads(Values, Slice.front(), CurrentOrder,
9447 PointerOps, SPtrInfo, &BestVF);
9448 if (LS != LoadsState::Gather ||
9449 (BestVF > 1 && static_cast<unsigned>(NumElts) == 2 * BestVF)) {
9450 if (LS == LoadsState::ScatterVectorize) {
9451 if (MaskedGatherVectorized.empty() ||
9452 Cnt >= MaskedGatherVectorized.back() + NumElts)
9453 MaskedGatherVectorized.push_back(Cnt);
9454 continue;
9455 }
9456 if (LS != LoadsState::Gather) {
9457 Results.emplace_back(Values, LS);
9458 VectorizedLoads.insert_range(Slice);
9459 // If we vectorized initial block, no need to try to vectorize it
9460 // again.
9461 if (Cnt == StartIdx)
9462 StartIdx += NumElts;
9463 }
9464 // Check if the whole array was vectorized already - exit.
9465 if (StartIdx >= Loads.size())
9466 break;
9467 // Erase last masked gather candidate, if another candidate within
9468 // the range is found to be better.
9469 if (!MaskedGatherVectorized.empty() &&
9470 Cnt < MaskedGatherVectorized.back() + NumElts)
9471 MaskedGatherVectorized.pop_back();
9472 Cnt += NumElts - 1;
9473 continue;
9474 }
9475 }
9476 if (!AllowToVectorize || BestVF == 0)
9478 }
9479 // Mark masked gathers candidates as vectorized, if any.
9480 for (unsigned Cnt : MaskedGatherVectorized) {
9481 ArrayRef<LoadInst *> Slice = ArrayRef(Loads).slice(
9482 Cnt, std::min<unsigned>(NumElts, Loads.size() - Cnt));
9484 reinterpret_cast<Value *const *>(Slice.begin()), Slice.size());
9486 VectorizedLoads.insert_range(Slice);
9487 // If we vectorized initial block, no need to try to vectorize it again.
9488 if (Cnt == StartIdx)
9489 StartIdx += NumElts;
9490 }
9491 }
9492 for (LoadInst *LI : Loads) {
9493 if (!VectorizedLoads.contains(LI))
9494 NonVectorized.push_back(LI);
9495 }
9496 return Results;
9497 };
9498 auto ProcessGatheredLoads =
9499 [&, &TTI = *TTI](
9501 bool Final = false) {
9502 SmallVector<LoadInst *> NonVectorized;
9503 for (ArrayRef<std::pair<LoadInst *, int64_t>> LoadsDists :
9504 GatheredLoads) {
9505 if (LoadsDists.size() <= 1) {
9506 NonVectorized.push_back(LoadsDists.back().first);
9507 continue;
9508 }
9510 LoadsDists);
9511 SmallVector<LoadInst *> OriginalLoads(make_first_range(LoadsDists));
9512 stable_sort(LocalLoadsDists, LoadSorter);
9514 unsigned MaxConsecutiveDistance = 0;
9515 unsigned CurrentConsecutiveDist = 1;
9516 int64_t LastDist = LocalLoadsDists.front().second;
9517 bool AllowMaskedGather = IsMaskedGatherSupported(OriginalLoads);
9518 for (const std::pair<LoadInst *, int64_t> &L : LocalLoadsDists) {
9519 if (isVectorized(L.first))
9520 continue;
9521 assert(LastDist >= L.second &&
9522 "Expected first distance always not less than second");
9523 if (static_cast<uint64_t>(LastDist - L.second) ==
9524 CurrentConsecutiveDist) {
9525 ++CurrentConsecutiveDist;
9526 MaxConsecutiveDistance =
9527 std::max(MaxConsecutiveDistance, CurrentConsecutiveDist);
9528 Loads.push_back(L.first);
9529 continue;
9530 }
9531 if (!AllowMaskedGather && CurrentConsecutiveDist == 1 &&
9532 !Loads.empty())
9533 Loads.pop_back();
9534 CurrentConsecutiveDist = 1;
9535 LastDist = L.second;
9536 Loads.push_back(L.first);
9537 }
9538 if (Loads.size() <= 1)
9539 continue;
9540 if (AllowMaskedGather)
9541 MaxConsecutiveDistance = Loads.size();
9542 else if (MaxConsecutiveDistance < 2)
9543 continue;
9544 BoUpSLP::ValueSet VectorizedLoads;
9545 SmallVector<LoadInst *> SortedNonVectorized;
9547 GetVectorizedRanges(Loads, VectorizedLoads, SortedNonVectorized,
9548 Final, MaxConsecutiveDistance);
9549 if (!Results.empty() && !SortedNonVectorized.empty() &&
9550 OriginalLoads.size() == Loads.size() &&
9551 MaxConsecutiveDistance == Loads.size() &&
9553 [](const std::pair<ArrayRef<Value *>, LoadsState> &P) {
9554 return P.second == LoadsState::ScatterVectorize;
9555 })) {
9556 VectorizedLoads.clear();
9557 SmallVector<LoadInst *> UnsortedNonVectorized;
9559 UnsortedResults =
9560 GetVectorizedRanges(OriginalLoads, VectorizedLoads,
9561 UnsortedNonVectorized, Final,
9562 OriginalLoads.size());
9563 if (SortedNonVectorized.size() >= UnsortedNonVectorized.size()) {
9564 SortedNonVectorized.swap(UnsortedNonVectorized);
9565 Results.swap(UnsortedResults);
9566 }
9567 }
9568 for (auto [Slice, _] : Results) {
9569 LLVM_DEBUG(dbgs() << "SLP: Trying to vectorize gathered loads ("
9570 << Slice.size() << ")\n");
9571 if (any_of(Slice, [&](Value *V) { return isVectorized(V); })) {
9572 for (Value *L : Slice)
9573 if (!isVectorized(L))
9574 SortedNonVectorized.push_back(cast<LoadInst>(L));
9575 continue;
9576 }
9577
9578 // Select maximum VF as a maximum of user gathered nodes and
9579 // distance between scalar loads in these nodes.
9580 unsigned MaxVF = Slice.size();
9581 unsigned UserMaxVF = 0;
9582 unsigned InterleaveFactor = 0;
9583 if (MaxVF == 2) {
9584 UserMaxVF = MaxVF;
9585 } else {
9586 // Found distance between segments of the interleaved loads.
9587 std::optional<unsigned> InterleavedLoadsDistance = 0;
9588 unsigned Order = 0;
9589 std::optional<unsigned> CommonVF = 0;
9590 DenseMap<const TreeEntry *, unsigned> EntryToPosition;
9591 SmallPtrSet<const TreeEntry *, 8> DeinterleavedNodes;
9592 for (auto [Idx, V] : enumerate(Slice)) {
9593 for (const TreeEntry *E : ValueToGatherNodes.at(V)) {
9594 UserMaxVF = std::max<unsigned>(UserMaxVF, E->Scalars.size());
9595 unsigned Pos =
9596 EntryToPosition.try_emplace(E, Idx).first->second;
9597 UserMaxVF = std::max<unsigned>(UserMaxVF, Idx - Pos + 1);
9598 if (CommonVF) {
9599 if (*CommonVF == 0) {
9600 CommonVF = E->Scalars.size();
9601 continue;
9602 }
9603 if (*CommonVF != E->Scalars.size())
9604 CommonVF.reset();
9605 }
9606 // Check if the load is the part of the interleaved load.
9607 if (Pos != Idx && InterleavedLoadsDistance) {
9608 if (!DeinterleavedNodes.contains(E) &&
9609 any_of(E->Scalars, [&, Slice = Slice](Value *V) {
9610 if (isa<Constant>(V))
9611 return false;
9612 if (isVectorized(V))
9613 return true;
9614 const auto &Nodes = ValueToGatherNodes.at(V);
9615 return (Nodes.size() != 1 || !Nodes.contains(E)) &&
9616 !is_contained(Slice, V);
9617 })) {
9618 InterleavedLoadsDistance.reset();
9619 continue;
9620 }
9621 DeinterleavedNodes.insert(E);
9622 if (*InterleavedLoadsDistance == 0) {
9623 InterleavedLoadsDistance = Idx - Pos;
9624 continue;
9625 }
9626 if ((Idx - Pos) % *InterleavedLoadsDistance != 0 ||
9627 (Idx - Pos) / *InterleavedLoadsDistance < Order)
9628 InterleavedLoadsDistance.reset();
9629 Order = (Idx - Pos) / InterleavedLoadsDistance.value_or(1);
9630 }
9631 }
9632 }
9633 DeinterleavedNodes.clear();
9634 // Check if the large load represents interleaved load operation.
9635 if (InterleavedLoadsDistance.value_or(0) > 1 &&
9636 CommonVF.value_or(0) != 0) {
9637 InterleaveFactor = bit_ceil(*InterleavedLoadsDistance);
9638 unsigned VF = *CommonVF;
9639 OrdersType Order;
9640 SmallVector<Value *> PointerOps;
9641 StridedPtrInfo SPtrInfo;
9642 // Segmented load detected - vectorize at maximum vector factor.
9643 if (InterleaveFactor <= Slice.size() &&
9644 TTI.isLegalInterleavedAccessType(
9646 getWidenedType(Slice.front()->getType(), VF)),
9647 InterleaveFactor,
9648 cast<LoadInst>(Slice.front())->getAlign(),
9649 cast<LoadInst>(Slice.front())
9650 ->getPointerAddressSpace()) &&
9651 canVectorizeLoads(Slice, Slice.front(), Order, PointerOps,
9652 SPtrInfo) == LoadsState::Vectorize) {
9653 UserMaxVF = InterleaveFactor * VF;
9654 } else {
9655 InterleaveFactor = 0;
9656 }
9657 }
9658 // Cannot represent the loads as consecutive vectorizable nodes -
9659 // just exit.
9660 unsigned ConsecutiveNodesSize = 0;
9661 if (!LoadEntriesToVectorize.empty() && InterleaveFactor == 0 &&
9662 any_of(zip(LoadEntriesToVectorize, LoadSetsToVectorize),
9663 [&, Slice = Slice](const auto &P) {
9664 const auto *It = find_if(Slice, [&](Value *V) {
9665 return std::get<1>(P).contains(V);
9666 });
9667 if (It == Slice.end())
9668 return false;
9669 const TreeEntry &TE =
9670 *VectorizableTree[std::get<0>(P)];
9671 ArrayRef<Value *> VL = TE.Scalars;
9672 OrdersType Order;
9673 SmallVector<Value *> PointerOps;
9674 StridedPtrInfo SPtrInfo;
9676 VL, VL.front(), Order, PointerOps, SPtrInfo);
9677 if (State == LoadsState::ScatterVectorize ||
9680 return false;
9681 ConsecutiveNodesSize += VL.size();
9682 size_t Start = std::distance(Slice.begin(), It);
9683 size_t Sz = Slice.size() - Start;
9684 return Sz < VL.size() ||
9685 Slice.slice(Start, VL.size()) != VL;
9686 }))
9687 continue;
9688 // Try to build long masked gather loads.
9689 UserMaxVF = bit_ceil(UserMaxVF);
9690 if (InterleaveFactor == 0 &&
9691 any_of(seq<unsigned>(Slice.size() / UserMaxVF),
9692 [&, Slice = Slice](unsigned Idx) {
9693 OrdersType Order;
9694 SmallVector<Value *> PointerOps;
9695 StridedPtrInfo SPtrInfo;
9696 return canVectorizeLoads(
9697 Slice.slice(Idx * UserMaxVF, UserMaxVF),
9698 Slice[Idx * UserMaxVF], Order, PointerOps,
9699 SPtrInfo) == LoadsState::ScatterVectorize;
9700 }))
9701 UserMaxVF = MaxVF;
9702 if (Slice.size() != ConsecutiveNodesSize)
9703 MaxVF = std::min<unsigned>(MaxVF, UserMaxVF);
9704 }
9705 for (unsigned VF = MaxVF; VF >= 2; VF /= 2) {
9706 bool IsVectorized = true;
9707 for (unsigned I = 0, E = Slice.size(); I < E; I += VF) {
9708 ArrayRef<Value *> SubSlice =
9709 Slice.slice(I, std::min(VF, E - I));
9710 if (isVectorized(SubSlice.front()))
9711 continue;
9712 // Check if the subslice is to be-vectorized entry, which is not
9713 // equal to entry.
9714 if (any_of(zip(LoadEntriesToVectorize, LoadSetsToVectorize),
9715 [&](const auto &P) {
9716 return !SubSlice.equals(
9717 VectorizableTree[std::get<0>(P)]
9718 ->Scalars) &&
9719 set_is_subset(SubSlice, std::get<1>(P));
9720 }))
9721 continue;
9722 unsigned Sz = VectorizableTree.size();
9723 // A chunk smaller than InterleaveFactor cannot form an
9724 // interleave group; keep it non-interleaved instead.
9725 buildTreeRec(
9726 SubSlice, 0, EdgeInfo(),
9727 SubSlice.size() >= InterleaveFactor ? InterleaveFactor : 0);
9728 if (Sz == VectorizableTree.size()) {
9729 IsVectorized = false;
9730 // Try non-interleaved vectorization with smaller vector
9731 // factor.
9732 if (InterleaveFactor > 0) {
9733 VF = 2 * (MaxVF / InterleaveFactor);
9734 InterleaveFactor = 0;
9735 }
9736 continue;
9737 }
9738 }
9739 if (IsVectorized)
9740 break;
9741 }
9742 }
9743 NonVectorized.append(SortedNonVectorized);
9744 }
9745 return NonVectorized;
9746 };
9747 for (const auto &GLs : GatheredLoads) {
9748 const auto &Ref = GLs.second;
9749 SmallVector<LoadInst *> NonVectorized = ProcessGatheredLoads(Ref);
9750 if (!Ref.empty() && !NonVectorized.empty() &&
9751 accumulate(
9752 Ref, 0u,
9753 [](unsigned S, ArrayRef<std::pair<LoadInst *, int64_t>> LoadsDists)
9754 -> unsigned { return S + LoadsDists.size(); }) !=
9755 NonVectorized.size() &&
9756 IsMaskedGatherSupported(NonVectorized)) {
9758 FinalGatheredLoads;
9759 for (LoadInst *LI : NonVectorized) {
9760 // Reinsert non-vectorized loads to other list of loads with the same
9761 // base pointers.
9762 gatherPossiblyVectorizableLoads(*this, LI, *DL, *SE, *TTI,
9763 FinalGatheredLoads,
9764 /*AddNew=*/false);
9765 }
9766 // Final attempt to vectorize non-vectorized loads.
9767 (void)ProcessGatheredLoads(FinalGatheredLoads, /*Final=*/true);
9768 }
9769 }
9770 // Try to vectorize postponed load entries, previously marked as gathered.
9771 for (unsigned Idx : LoadEntriesToVectorize) {
9772 const TreeEntry &E = *VectorizableTree[Idx];
9773 SmallVector<Value *> GatheredScalars(E.Scalars.begin(), E.Scalars.end());
9774 // Avoid reordering, if possible.
9775 if (!E.ReorderIndices.empty()) {
9776 // Build a mask out of the reorder indices and reorder scalars per this
9777 // mask.
9778 SmallVector<int> ReorderMask;
9779 inversePermutation(E.ReorderIndices, ReorderMask);
9780 reorderScalars(GatheredScalars, ReorderMask);
9781 }
9782 buildTreeRec(GatheredScalars, 0, EdgeInfo());
9783 }
9784 // If no new entries created, consider it as no gathered loads entries must be
9785 // handled.
9786 if (static_cast<unsigned>(*GatheredLoadsEntriesFirst) ==
9787 VectorizableTree.size())
9788 GatheredLoadsEntriesFirst.reset();
9789}
9790
9791/// Generates key/subkey pair for the given value to provide effective sorting
9792/// of the values and better detection of the vectorizable values sequences. The
9793/// keys/subkeys can be used for better sorting of the values themselves (keys)
9794/// and in values subgroups (subkeys).
9795static std::pair<size_t, size_t> generateKeySubkey(
9796 Value *V, const TargetLibraryInfo *TLI,
9797 function_ref<hash_code(size_t, LoadInst *)> LoadsSubkeyGenerator,
9798 bool AllowAlternate) {
9799 hash_code Key = hash_value(V->getValueID() + 2);
9800 hash_code SubKey = hash_value(0);
9801 // Sort the loads by the distance between the pointers.
9802 if (auto *LI = dyn_cast<LoadInst>(V)) {
9803 Key = hash_combine(LI->getType(), hash_value(Instruction::Load), Key);
9804 if (LI->isSimple())
9805 SubKey = hash_value(LoadsSubkeyGenerator(Key, LI));
9806 else
9807 Key = SubKey = hash_value(LI);
9808 } else if (isVectorLikeInstWithConstOps(V)) {
9809 // Sort extracts by the vector operands.
9811 Key = hash_value(Value::UndefValueVal + 1);
9812 if (auto *EI = dyn_cast<ExtractElementInst>(V)) {
9813 if (!isUndefVector(EI->getVectorOperand()).all() &&
9814 !isa<UndefValue>(EI->getIndexOperand()))
9815 SubKey = hash_value(EI->getVectorOperand());
9816 }
9817 } else if (auto *I = dyn_cast<Instruction>(V)) {
9818 // Sort other instructions just by the opcodes except for CMPInst.
9819 // For CMP also sort by the predicate kind.
9821 isValidForAlternation(I->getOpcode())) {
9822 if (AllowAlternate)
9823 Key = hash_value(isa<BinaryOperator>(I) ? 1 : 0);
9824 else
9825 Key = hash_combine(hash_value(I->getOpcode()), Key);
9826 SubKey = hash_combine(
9827 hash_value(I->getOpcode()), hash_value(I->getType()),
9829 ? I->getType()
9830 : cast<CastInst>(I)->getOperand(0)->getType()));
9831 // For casts, look through the only operand to improve compile time.
9832 if (isa<CastInst>(I)) {
9833 std::pair<size_t, size_t> OpVals =
9834 generateKeySubkey(I->getOperand(0), TLI, LoadsSubkeyGenerator,
9835 /*AllowAlternate=*/true);
9836 Key = hash_combine(OpVals.first, Key);
9837 SubKey = hash_combine(OpVals.first, SubKey);
9838 }
9839 } else if (auto *CI = dyn_cast<CmpInst>(I)) {
9840 CmpInst::Predicate Pred = CI->getPredicate();
9841 if (CI->isCommutative())
9842 Pred = std::min(Pred, CmpInst::getInversePredicate(Pred));
9844 SubKey = hash_combine(hash_value(I->getOpcode()), hash_value(Pred),
9845 hash_value(SwapPred),
9846 hash_value(CI->getOperand(0)->getType()));
9847 } else if (auto *Call = dyn_cast<CallInst>(I)) {
9849 if (isTriviallyVectorizable(ID)) {
9850 if (ID == Intrinsic::fmuladd)
9851 ID = Intrinsic::fma;
9852 SubKey = hash_combine(hash_value(I->getOpcode()), hash_value(ID));
9853 } else if (!VFDatabase(*Call).getMappings(*Call).empty()) {
9854 SubKey = hash_combine(hash_value(I->getOpcode()),
9855 hash_value(Call->getCalledFunction()));
9856 } else {
9858 SubKey = hash_combine(hash_value(I->getOpcode()), hash_value(Call));
9859 }
9860 for (const CallBase::BundleOpInfo &Op : Call->bundle_op_infos())
9861 SubKey = hash_combine(hash_value(Op.Begin), hash_value(Op.End),
9862 hash_value(Op.Tag), SubKey);
9863 } else if (auto *Gep = dyn_cast<GetElementPtrInst>(I)) {
9864 if (Gep->getNumOperands() == 2 && isa<ConstantInt>(Gep->getOperand(1)))
9865 SubKey = hash_value(Gep->getPointerOperand());
9866 else
9867 SubKey = hash_value(Gep);
9868 } else if (BinaryOperator::isIntDivRem(I->getOpcode()) &&
9869 !isa<ConstantInt>(I->getOperand(1))) {
9870 // Do not try to vectorize instructions with potentially high cost.
9871 SubKey = hash_value(I);
9872 } else {
9873 SubKey = hash_value(I->getOpcode());
9874 }
9875 Key = hash_combine(hash_value(I->getParent()->getNumber()), Key);
9876 }
9877 return std::make_pair(Key, SubKey);
9878}
9879
9880/// Checks if the specified instruction \p I is an main operation for the given
9881/// \p MainOp and \p AltOp instructions.
9882static bool isMainInstruction(Instruction *I, Instruction *MainOp,
9883 Instruction *AltOp, const TargetLibraryInfo &TLI);
9884
9885/// Builds the arguments types vector for the given call instruction with the
9886/// given \p ID for the specified vector factor.
9889 const unsigned VF, unsigned MinBW,
9890 const TargetTransformInfo *TTI) {
9891 SmallVector<Type *> ArgTys;
9892 for (auto [Idx, Arg] : enumerate(CI->args())) {
9893 if (ID != Intrinsic::not_intrinsic) {
9895 ArgTys.push_back(Arg->getType());
9896 continue;
9897 }
9898 if (MinBW > 0) {
9899 ArgTys.push_back(
9900 getWidenedType(IntegerType::get(CI->getContext(), MinBW), VF));
9901 continue;
9902 }
9903 }
9904 ArgTys.push_back(getWidenedType(Arg->getType(), VF));
9905 }
9906 return ArgTys;
9907}
9908
9909/// Calculates the costs of vectorized intrinsic (if possible) and vectorized
9910/// function (if possible) calls. Returns invalid cost for the corresponding
9911/// calls, if they cannot be vectorized/will be scalarized.
9912static std::pair<InstructionCost, InstructionCost>
9914 const TargetLibraryInfo *TLI, ArrayRef<Type *> ArgTys,
9916 auto Shape = VFShape::get(CI->getFunctionType(),
9918 false /*HasGlobalPred*/);
9919 Function *VecFunc = VFDatabase(*CI).getVectorizedFunction(Shape);
9920 auto LibCost = InstructionCost::getInvalid();
9921 if (!CI->isNoBuiltin() && VecFunc) {
9922 // Calculate the cost of the vector library call.
9923 // If the corresponding vector call is cheaper, return its cost.
9924 LibCost = TTI->getCallInstrCost(nullptr, VecTy, ArgTys, CostKind);
9925 }
9927
9928 // Calculate the cost of the vector intrinsic call.
9929 FastMathFlags FMF;
9930 if (auto *FPCI = dyn_cast<FPMathOperator>(CI))
9931 FMF = FPCI->getFastMathFlags();
9932 const InstructionCost ScalarLimit = 10000;
9933 IntrinsicCostAttributes CostAttrs(ID, VecTy, ArgTys, FMF, nullptr,
9934 LibCost.isValid() ? LibCost : ScalarLimit);
9935 auto IntrinsicCost = TTI->getIntrinsicInstrCost(CostAttrs, CostKind);
9936 if (LibCost.isValid()) {
9937 if (IntrinsicCost > LibCost)
9939 } else if (IntrinsicCost > ScalarLimit) {
9940 // A type-based query always scalarizes struct-returning intrinsics (e.g.
9941 // llvm.sincos), which do not have a VFDatabase name mapping. Retry with an
9942 // argument-aware query (as the loop vectorizer does) so such lowerings are
9943 // taken into account.
9944 SmallVector<const Value *> Args(CI->args());
9945 IntrinsicCostAttributes ArgAwareAttrs(
9946 ID, VecTy, Args, ArgTys, FMF, dyn_cast<IntrinsicInst>(CI), ScalarLimit);
9947 IntrinsicCost = TTI->getIntrinsicInstrCost(ArgAwareAttrs, CostKind);
9948 if (IntrinsicCost > ScalarLimit)
9950 }
9951
9952 return {IntrinsicCost, LibCost};
9953}
9954
9955/// \returns the reciprocal-throughput cost of \p I widened to \p VF lanes (an
9956/// arithmetic op or a vectorizable call).
9958 const TargetTransformInfo &TTI,
9959 const TargetLibraryInfo &TLI,
9962 "getVectorOpCost expects an arithmetic op or a vectorizable call.");
9963 Type *VecTy = getWidenedType(I->getType(), VF);
9964 if (auto *CI = dyn_cast<CallInst>(I)) {
9966 SmallVector<Type *> ArgTys = buildIntrinsicArgTypes(CI, ID, VF, 0, &TTI);
9967 auto [IntrCost, LibCost] =
9968 getVectorCallCosts(CI, VecTy, &TTI, &TLI, ArgTys, CostKind);
9969 return std::min(IntrCost, LibCost);