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
24#include "llvm/ADT/DenseMap.h"
25#include "llvm/ADT/DenseSet.h"
27#include "llvm/ADT/STLExtras.h"
28#include "llvm/ADT/ScopeExit.h"
30#include "llvm/ADT/SetVector.h"
33#include "llvm/ADT/SmallSet.h"
36#include "llvm/ADT/Statistic.h"
37#include "llvm/ADT/iterator.h"
47#include "llvm/Analysis/Loads.h"
57#include "llvm/IR/Attributes.h"
58#include "llvm/IR/BasicBlock.h"
59#include "llvm/IR/CFG.h"
60#include "llvm/IR/Constant.h"
61#include "llvm/IR/Constants.h"
62#include "llvm/IR/DataLayout.h"
64#include "llvm/IR/Dominators.h"
65#include "llvm/IR/Function.h"
66#include "llvm/IR/IRBuilder.h"
67#include "llvm/IR/InstrTypes.h"
68#include "llvm/IR/Instruction.h"
71#include "llvm/IR/Intrinsics.h"
72#include "llvm/IR/MDBuilder.h"
73#include "llvm/IR/Module.h"
74#include "llvm/IR/Operator.h"
77#include "llvm/IR/Type.h"
78#include "llvm/IR/Use.h"
79#include "llvm/IR/User.h"
80#include "llvm/IR/Value.h"
81#include "llvm/IR/ValueHandle.h"
83#ifdef EXPENSIVE_CHECKS
84#include "llvm/IR/Verifier.h"
85#endif
86#include "llvm/Pass.h"
91#include "llvm/Support/Debug.h"
103#include <algorithm>
104#include <cassert>
105#include <cstdint>
106#include <iterator>
107#include <map>
108#include <memory>
109#include <optional>
110#include <set>
111#include <string>
112#include <tuple>
113#include <utility>
114
115using namespace llvm;
116using namespace llvm::PatternMatch;
117using namespace slpvectorizer;
118using namespace std::placeholders;
119
120#define SV_NAME "slp-vectorizer"
121#define DEBUG_TYPE "SLP"
122
123STATISTIC(NumVectorInstructions, "Number of vector instructions generated");
124STATISTIC(NumStridedStoreChains, "Number of vectorized stride stores");
125STATISTIC(NumStoreChains, "Number of vector stores created");
126STATISTIC(NumVectorizedStores, "Number of vectorized stores");
127
128DEBUG_COUNTER(VectorizedGraphs, "slp-vectorized",
129 "Controls which SLP graphs should be vectorized.");
130
131static cl::opt<bool>
132 RunSLPVectorization("vectorize-slp", cl::init(true), cl::Hidden,
133 cl::desc("Run the SLP vectorization passes"));
134
135static cl::opt<bool>
136 SLPReVec("slp-revec", cl::init(false), cl::Hidden,
137 cl::desc("Enable vectorization for wider vector utilization"));
138
139static cl::opt<int>
141 cl::desc("Only vectorize if you gain more than this "
142 "number "));
143
144static cl::opt<bool>
145ShouldVectorizeHor("slp-vectorize-hor", cl::init(true), cl::Hidden,
146 cl::desc("Attempt to vectorize horizontal reductions"));
147
149 "slp-vectorize-hor-store", cl::init(false), cl::Hidden,
150 cl::desc(
151 "Attempt to vectorize horizontal reductions feeding into a store"));
152
154 "slp-split-alternate-instructions", cl::init(true), cl::Hidden,
155 cl::desc("Improve the code quality by splitting alternate instructions"));
156
158 "slp-inst-count-check", cl::init(true), cl::Hidden,
159 cl::desc("Reject vectorization if vector instruction count exceeds "
160 "scalar instruction count"));
161
162static cl::opt<int>
164 cl::desc("Attempt to vectorize for this register size in bits"));
165
168 cl::desc("Maximum SLP vectorization factor (0=unlimited)"));
169
170/// Limits the size of scheduling regions in a block.
171/// It avoid long compile times for _very_ large blocks where vector
172/// instructions are spread over a wide range.
173/// This limit is way higher than needed by real-world functions.
174static cl::opt<int>
175ScheduleRegionSizeBudget("slp-schedule-budget", cl::init(100000), cl::Hidden,
176 cl::desc("Limit the size of the SLP scheduling region per block"));
177
179 "slp-min-reg-size", cl::init(128), cl::Hidden,
180 cl::desc("Attempt to vectorize for this register size in bits"));
181
183 "slp-recursion-max-depth", cl::init(12), cl::Hidden,
184 cl::desc("Limit the recursion depth when building a vectorizable tree"));
185
187 "slp-min-tree-size", cl::init(3), cl::Hidden,
188 cl::desc("Only vectorize small trees if they are fully vectorizable"));
189
191 "slp-phi-vectorization-budget", cl::init(1024), cl::Hidden,
192 cl::desc("Do not vectorize a bundle of PHI nodes if the product of the "
193 "bundle size and the number of incoming values exceeds this "
194 "value, to limit the compile time spent on wide PHIs"));
195
196// The maximum depth that the look-ahead score heuristic will explore.
197// The higher this value, the higher the compilation time overhead.
199 "slp-max-look-ahead-depth", cl::init(2), cl::Hidden,
200 cl::desc("The maximum look-ahead depth for operand reordering scores"));
201
202// The maximum depth that the look-ahead score heuristic will explore
203// when it probing among candidates for vectorization tree roots.
204// The higher this value, the higher the compilation time overhead but unlike
205// similar limit for operands ordering this is less frequently used, hence
206// impact of higher value is less noticeable.
208 "slp-max-root-look-ahead-depth", cl::init(2), cl::Hidden,
209 cl::desc("The maximum look-ahead depth for searching best rooting option"));
210
212 "slp-min-strided-loads", cl::init(2), cl::Hidden,
213 cl::desc("The minimum number of loads, which should be considered strided, "
214 "if the stride is > 1 or is runtime value"));
215
217 "slp-min-strided-stores", cl::init(2), cl::Hidden,
218 cl::desc(
219 "The minimum number of stores, which should be considered strided, "
220 "if the stride is > 1 or is runtime value"));
221
223 "slp-max-stride", cl::init(8), cl::Hidden,
224 cl::desc("The maximum stride, considered to be profitable."));
225
226static cl::opt<bool>
227 EnableStridedStores("slp-enable-strided-stores", cl::init(false),
229 cl::desc("Enable SLP trees to be built from strided "
230 "store chains."));
231
233 "slp-enable-masked-stores", cl::init(true), cl::Hidden,
234 cl::desc("Enable vectorization of non-consecutive stores as a single "
235 "masked store, when the target supports masked stores."));
236
237static cl::opt<bool>
238 DisableTreeReorder("slp-disable-tree-reorder", cl::init(false), cl::Hidden,
239 cl::desc("Disable tree reordering even if it is "
240 "profitable. Used for testing only."));
241
242static cl::opt<bool>
243 ForceStridedLoads("slp-force-strided-loads", cl::init(false), cl::Hidden,
244 cl::desc("Generate strided loads even if they are not "
245 "profitable. Used for testing only."));
246
247static cl::opt<bool>
248 ViewSLPTree("view-slp-tree", cl::Hidden,
249 cl::desc("Display the SLP trees with Graphviz"));
250
252 "slp-vectorize-non-power-of-2", cl::init(false), cl::Hidden,
253 cl::desc("Try to vectorize with non-power-of-2 number of elements."));
254
256 "slp-postprocess-stores-operands", cl::init(false), cl::Hidden,
257 cl::desc("Force vectorization of non-vectorizable stores operands."));
258
260 "slp-non-vectorizables-as-reductions", cl::init(false), cl::Hidden,
261 cl::desc(
262 "Use non-vectorizable instructions as potential reduction roots."));
263
265 "slp-vectorize-poor-throughput", cl::init(true), cl::Hidden,
266 cl::desc("Use poor-throughput instructions (e.g. fdiv, frem, fsqrt) as "
267 "standalone vectorization seeds."));
268
270 "slp-vectorize-once-used", cl::init(true), cl::Hidden,
271 cl::desc("Use instructions with the single user as standalone "
272 "vectorization seeds."));
273
274/// True when \p slp-vectorize-non-power-of-2 is enabled and \p NumElts is a
275/// supported non-power-of-2 width: \p NumElts + 1 must be a power of two
276/// (e.g. 3 or 7 lanes, i.e. almost a full power-of-2 register).
277static bool isAllowedNonPowerOf2VF(unsigned NumElts) {
278 return VectorizeNonPowerOf2 && has_single_bit(NumElts + 1);
279}
280
281/// Enables vectorization of copyable elements.
283 "slp-copyable-elements", cl::init(true), cl::Hidden,
284 cl::desc("Try to replace values with the idempotent instructions for "
285 "better vectorization."));
286
287/// Gather operands of associative single-use binary chains into one node.
289 "slp-reassociate-ops", cl::init(true), cl::Hidden,
290 cl::desc("Gather operands of associative binary chains into one node."));
291
292/// The family-realigned seed already groups the vectorizable columns; the
293/// VLOperands polish on top is quadratic in the column count, so past this
294/// many columns keep the seed instead.
296 "slp-reassociate-reorder-limit", cl::init(32), cl::Hidden,
297 cl::desc("Max flattened operand columns for which associative-chain "
298 "reordering runs the full operand reorder."));
299
301 "slp-cost-loop-trip-count", cl::init(2), cl::Hidden,
302 cl::desc("Loop trip count, considered by the cost model during "
303 "modeling (0=loops are ignored and considered flat code)"));
304
305/// Refine the loop-aware cost scaling of gather/buildvector tree entries by
306/// using the per-lane execution scale of the operand that feeds each lane,
307/// instead of a single whole-entry scale. This matches the LICM hoisting
308/// performed by optimizeGatherSequence() at codegen time: lanes whose
309/// operands are loop-invariant in an inner loop contribute the outer loop's
310/// execution scale rather than the inner loop's, which avoids over-costing
311/// buildvectors that bridge values from outer loop nests into an inner loop.
313 "slp-per-lane-gather-scale", cl::init(true), cl::Hidden,
314 cl::desc("Use per-lane execution scale for gather/buildvector tree "
315 "entries to model LICM-hoistable buildvector sequences."));
316
317/// Enable versioning of a basic block with runtime alias checks.
319 "slp-vectorize-with-runtime-alias-checks", cl::init(true), cl::Hidden,
320 cl::desc("Allow SLP to version a block with runtime alias checks to "
321 "vectorize trees blocked by may-alias memory dependencies."));
322
323/// Maximum number of runtime alias checks (one per pair of base objects) that
324/// may guard a single versioned region.
326 "slp-max-runtime-alias-checks", cl::init(8), cl::Hidden,
327 cl::desc("The maximum number of runtime alias checks generated to guard a "
328 "single SLP-vectorized region."));
329
330/// The runtime checks and the guard branch execute on both the vector and the
331/// scalar fallback path, so they add overhead to the scalar code.
333 "slp-runtime-alias-checks-max-scalar-cost-percent", cl::init(25),
335 cl::desc("Maximum SLP runtime alias check cost, as a percentage of the "
336 "guarded scalar region cost, before versioning is rejected to "
337 "avoid pessimizing the scalar fallback path."));
338
339// Limit the number of alias checks. The limit is chosen so that
340// it has no negative effect on the llvm benchmarks.
341static const unsigned AliasedCheckLimit = 10;
342
343// Another limit for the alias checks: The maximum distance between load/store
344// instructions where alias checks are done.
345// This limit is useful for very large basic blocks.
346static const unsigned MaxMemDepDistance = 160;
347
348/// If the ScheduleRegionSizeBudget is exhausted, we allow small scheduling
349/// regions to be handled.
350static const int MinScheduleRegionSize = 16;
351
352/// Maximum allowed number of operands in the PHI nodes.
353static const unsigned MaxPHINumOperands = 128;
354
355/// Checks if the vector of instructions can be represented as a shuffle, like:
356/// %x0 = extractelement <4 x i8> %x, i32 0
357/// %x3 = extractelement <4 x i8> %x, i32 3
358/// %y1 = extractelement <4 x i8> %y, i32 1
359/// %y2 = extractelement <4 x i8> %y, i32 2
360/// %x0x0 = mul i8 %x0, %x0
361/// %x3x3 = mul i8 %x3, %x3
362/// %y1y1 = mul i8 %y1, %y1
363/// %y2y2 = mul i8 %y2, %y2
364/// %ins1 = insertelement <4 x i8> poison, i8 %x0x0, i32 0
365/// %ins2 = insertelement <4 x i8> %ins1, i8 %x3x3, i32 1
366/// %ins3 = insertelement <4 x i8> %ins2, i8 %y1y1, i32 2
367/// %ins4 = insertelement <4 x i8> %ins3, i8 %y2y2, i32 3
368/// ret <4 x i8> %ins4
369/// can be transformed into:
370/// %1 = shufflevector <4 x i8> %x, <4 x i8> %y, <4 x i32> <i32 0, i32 3, i32 5,
371/// i32 6>
372/// %2 = mul <4 x i8> %1, %1
373/// ret <4 x i8> %2
374/// Mask will return the Shuffle Mask equivalent to the extracted elements.
375/// TODO: Can we split off and reuse the shuffle mask detection from
376/// ShuffleVectorInst/getShuffleCost?
377static std::optional<TargetTransformInfo::ShuffleKind>
379 AssumptionCache *AC) {
380 const auto *It = find_if(VL, IsaPred<ExtractElementInst>);
381 if (It == VL.end())
382 return std::nullopt;
383 unsigned Size = accumulate(VL, 0u, [](unsigned S, Value *V) {
384 auto *EI = dyn_cast<ExtractElementInst>(V);
385 if (!EI)
386 return S;
387 auto *VTy = dyn_cast<FixedVectorType>(EI->getVectorOperandType());
388 if (!VTy)
389 return S;
390 return std::max(S, VTy->getNumElements());
391 });
392
393 Value *Vec1 = nullptr;
394 Value *Vec2 = nullptr;
395 bool HasNonUndefVec = any_of(VL, [&](Value *V) {
396 auto *EE = dyn_cast<ExtractElementInst>(V);
397 if (!EE)
398 return false;
399 Value *Vec = EE->getVectorOperand();
400 if (isa<UndefValue>(Vec))
401 return false;
402 return isGuaranteedNotToBePoison(Vec, AC);
403 });
404 enum ShuffleMode { Unknown, Select, Permute };
405 ShuffleMode CommonShuffleMode = Unknown;
406 Mask.assign(VL.size(), PoisonMaskElem);
407 for (unsigned I = 0, E = VL.size(); I < E; ++I) {
408 // Undef, or a copyable lane modeled on an extract main op, can be
409 // represented as an undef element in a vector.
410 if (isa<UndefValue>(VL[I]))
411 continue;
412 auto *EI = dyn_cast<ExtractElementInst>(VL[I]);
413 if (!EI)
414 continue;
415 if (isa<ScalableVectorType>(EI->getVectorOperandType()))
416 return std::nullopt;
417 auto *Vec = EI->getVectorOperand();
418 // We can extractelement from undef or poison vector.
420 continue;
421 // All vector operands must have the same number of vector elements.
422 if (isa<UndefValue>(Vec)) {
423 Mask[I] = I;
424 } else {
425 if (isa<UndefValue>(EI->getIndexOperand()))
426 continue;
427 auto *Idx = dyn_cast<ConstantInt>(EI->getIndexOperand());
428 if (!Idx)
429 return std::nullopt;
430 // Undefined behavior if Idx is negative or >= Size.
431 if (Idx->getValue().uge(Size))
432 continue;
433 unsigned IntIdx = Idx->getValue().getZExtValue();
434 Mask[I] = IntIdx;
435 }
436 if (isUndefVector(Vec).all() && HasNonUndefVec)
437 continue;
438 // For correct shuffling we have to have at most 2 different vector operands
439 // in all extractelement instructions.
440 if (!Vec1 || Vec1 == Vec) {
441 Vec1 = Vec;
442 } else if (!Vec2 || Vec2 == Vec) {
443 Vec2 = Vec;
444 Mask[I] += Size;
445 } else {
446 return std::nullopt;
447 }
448 if (CommonShuffleMode == Permute)
449 continue;
450 // If the extract index is not the same as the operation number, it is a
451 // permutation.
452 if (Mask[I] % Size != I) {
453 CommonShuffleMode = Permute;
454 continue;
455 }
456 CommonShuffleMode = Select;
457 }
458 // If we're not crossing lanes in different vectors, consider it as blending.
459 if (CommonShuffleMode == Select && Vec2)
461 // If Vec2 was never used, we have a permutation of a single vector, otherwise
462 // we have permutation of 2 vectors.
465}
466
467/// Returns number of parts, the type \p VecTy will be split at the codegen
468/// phase. If the type is going to be scalarized or does not uses whole
469/// registers, returns 1.
470static unsigned
472 const unsigned Limit = std::numeric_limits<unsigned>::max()) {
473 if (isa<StructType>(VecTy))
474 return 1;
475 unsigned NumParts = TTI.getNumberOfParts(VecTy);
476 if (NumParts == 0 || NumParts >= Limit)
477 return 1;
478 unsigned Sz = getNumElements(VecTy);
479 unsigned ScalarSz = getNumElements(ScalarTy);
480 Type *ElementTy = toScalarizedTy(VecTy);
481 unsigned PWSz = getFullVectorNumberOfElements(TTI, ElementTy, Sz, SLPReVec);
482 if (NumParts >= Sz || PWSz % NumParts != 0 ||
483 (PWSz / NumParts) % ScalarSz != 0 ||
484 !hasFullVectorsOrPowerOf2(TTI, ElementTy, PWSz / NumParts, SLPReVec))
485 return 1;
486 const unsigned NumElts = PWSz / NumParts;
487 if (divideCeil(Sz, NumElts) != NumParts)
488 return 1;
489 return NumParts;
490}
491
492/// Bottom Up SLP Vectorizer.
494 class TreeEntry;
495 class ScheduleEntity;
496 class ScheduleData;
497 class ScheduleCopyableData;
498 class ScheduleBundle;
501
502public:
503 /// If we decide to generate strided load / store, this struct contains all
504 /// the necessary info. It's fields are calculated by analyzeRtStrideCandidate
505 /// and analyzeConstantStrideCandidate. Note that Stride can be given either
506 /// as a SCEV or as a Value if it already exists. To get the stride in bytes,
507 /// StrideVal (or value obtained from StrideSCEV) has to by multiplied by the
508 /// size of element of FixedVectorType.
510 Value *StrideVal = nullptr;
511 const SCEV *StrideSCEV = nullptr;
512 FixedVectorType *Ty = nullptr;
513 };
514
515 /// Tracks the state we can represent the loads in the given sequence.
524
531
533 TargetLibraryInfo *TLi, AAResults *Aa, LoopInfo *Li,
536 : BatchAA(*Aa), F(Func), SE(Se), TTI(Tti), TLI(TLi), LI(Li), DT(Dt),
537 AC(AC), DB(DB), DL(DL), ORE(ORE), CostKind(getSLPCostKind(Func)),
538 Builder(Se->getContext(), TargetFolder(*DL)) {
539 CodeMetrics::collectEphemeralValues(F, AC, EphValues);
540 // Use the vector register size specified by the target unless overridden
541 // by a command-line option.
542 // TODO: It would be better to limit the vectorization factor based on
543 // data type rather than just register size. For example, x86 AVX has
544 // 256-bit registers, but it does not support integer operations
545 // at that width (that requires AVX2).
546 if (MaxVectorRegSizeOption.getNumOccurrences())
547 MaxVecRegSize = MaxVectorRegSizeOption;
548 else
549 MaxVecRegSize =
550 TTI->getRegisterBitWidth(TargetTransformInfo::RGK_FixedWidthVector)
551 .getFixedValue();
552
553 if (MinVectorRegSizeOption.getNumOccurrences())
554 MinVecRegSize = MinVectorRegSizeOption;
555 else
556 MinVecRegSize = TTI->getMinVectorRegisterBitWidth();
557 }
558
559 /// Vectorize the tree that starts with the elements in \p VL.
560 /// Returns the vectorized root.
562
563 /// Vectorize the tree but with the list of externally used values \p
564 /// ExternallyUsedValues. Values in this MapVector can be replaced but the
565 /// generated extractvalue instructions.
566 Value *
567 vectorizeTree(const ExtraValueToDebugLocsMap &ExternallyUsedValues,
568 Instruction *ReductionRoot = nullptr,
569 ArrayRef<std::tuple<WeakTrackingVH, unsigned, bool, bool>>
570 VectorValuesAndScales = {});
571
572 /// \returns the cost incurred by unwanted spills and fills, caused by
573 /// holding live values over call sites.
575
577
578 /// Calculates the cost of the subtrees, trims non-profitable ones and returns
579 /// final cost.
582 Instruction *RdxRoot = nullptr);
583
584 /// \returns the vectorization cost of the subtree that starts at \p VL.
585 /// A negative number means that this is profitable.
587 ArrayRef<Value *> VectorizedVals = {},
588 InstructionCost ReductionCost = TTI::TCC_Free,
589 Instruction *RdxRoot = nullptr);
590
591 /// Construct a vectorizable tree that starts at \p Roots, ignoring users for
592 /// the purpose of scheduling and extraction in the \p UserIgnoreLst.
593 void buildTree(ArrayRef<Value *> Roots,
594 const SmallDenseSet<Value *> &UserIgnoreLst);
595
596 /// Construct a vectorizable tree that starts at \p Roots.
597 void buildTree(ArrayRef<Value *> Roots);
598
599 /// Sets the narrowed reduction chain instructions, dropped together with
600 /// the reduction.
602 NarrowedChainInsts.insert(Insts.begin(), Insts.end());
603 }
604
605 /// Returns true if the last buildTree() observed a may-alias memory
606 /// dependency between two distinct, range-checkable base objects, i.e. a
607 /// dependency that could be turned into a runtime alias check.
609 return HasRuntimeCheckableBlockers;
610 }
611
612 /// Records whether a may-alias dependency between distinct, range-checkable
613 /// base objects has been observed, so the caller can decide to retry with
614 /// runtime alias checks enabled.
616 HasRuntimeCheckableBlockers = V;
617 }
618
619 /// Returns true if the last buildTree() kept a may-alias memory dependency
620 /// that is not runtime-checkable (call or a non-simple mem access). Such a
621 /// dependency cannot be dropped, so a runtime-checks retry cannot unblock the
622 /// region and would be pure overhead.
623 bool hasNonCheckableMemBlocker() const { return HasNonCheckableMemBlocker; }
624
625 /// Records that a non-runtime-checkable may-alias dependency was kept.
626 void setHasNonCheckableMemBlocker(bool V) { HasNonCheckableMemBlocker = V; }
627
628 /// Returns true if the current vectorization attempt may drop
629 /// runtime-checkable may-alias dependencies and guard the region with
630 /// runtime alias checks.
631 bool isTryingRuntimeAliasChecks() const { return TryRuntimeAliasChecks; }
632
633 /// Enables or disables dropping runtime-checkable may-alias dependencies in
634 /// favor of runtime alias checks for the current vectorization attempt.
635 void setTryRuntimeAliasChecks(bool V) { TryRuntimeAliasChecks = V; }
636
637 /// Resets the runtime alias check data.
639 HasRuntimeCheckableBlockers = false;
640 HasNonCheckableMemBlocker = false;
641 RTChecksFinalized = false;
642 RTChecks.clear();
643 RTOrigBodyOrder.clear();
644 }
645
646 /// Snapshots RTChecks.BB's body (non-PHI, non-terminator) into
647 /// RTOrigBodyOrder in program order, for the scalar fallback.
649
650 /// Returns true if \p BB satisfies the block-level preconditions for runtime
651 /// alias check versioning (straight-line, outside any loop, duplicable, not a
652 /// scalar fallback, function not optimized for size). These checks do not
653 /// depend on the collected checks, so they can gate the (expensive)
654 /// optimistic retry before any tree is rebuilt.
656
657 /// Returns true if the runtime alias checks can be safely emitted to guard
658 /// the vectorized region.
660
661 /// Returns true if \p BB is a scalar fallback block created by runtime alias
662 /// check versioning.
664 return ScalarFallbackBlocks.contains(BB);
665 }
666
667 /// Returns true if an optimistic runtime-checks versioning attempt already
668 /// failed for \p BB, so further retries in the same block can be skipped.
670 return FailedRuntimeChecksBlocks.contains(BB);
671 }
672
673 /// Records that an optimistic runtime-checks versioning attempt failed for
674 /// \p BB.
676 FailedRuntimeChecksBlocks.insert(BB);
677 }
678
679 /// Returns the modeled cost of the runtime alias checks collected during the
680 /// last (optimistic) buildTree().
682
683 /// Returns true if the last (optimistic) buildTree() collected any runtime
684 /// alias checks that must guard the vectorized region.
685 bool hasRuntimeAliasChecks() const { return !RTChecks.BasePairs.empty(); }
686
687 /// Returns true if vectorization changed the CFG (i.e. a block was versioned
688 /// with runtime alias checks). When true, CFG analyses must not be preserved.
689 bool isCFGChanged() const { return CFGChanged; }
690
691 TreeEntry &getRootNode() {
692 assert(!VectorizableTree.empty() && "No graph to get the first node from");
693 return *VectorizableTree.front();
694 }
695
696 const TreeEntry &getRootNode() const {
697 assert(!VectorizableTree.empty() && "No graph to get the first node from");
698 return *VectorizableTree.front();
699 }
700
701 /// Returns the scalars of the root node.
703
704 /// Returns the lane the given value is vectorized to in the root node.
705 unsigned findRootLaneForValue(Value *V) const {
706 return getRootNode().findLaneForValue(V);
707 }
708
709 /// Returns the type/is-signed info for the root node in the graph without
710 /// casting.
711 std::optional<std::pair<Type *, bool>> getRootNodeTypeWithNoCast() const {
712 const TreeEntry &Root = getRootNode();
713 if (Root.State != TreeEntry::Vectorize || Root.isAltShuffle() ||
714 !Root.Scalars.front()->getType()->isIntegerTy())
715 return std::nullopt;
716 auto It = MinBWs.find(&Root);
717 if (It != MinBWs.end())
718 return std::make_pair(IntegerType::get(Root.Scalars.front()->getContext(),
719 It->second.first),
720 It->second.second);
721 if (Root.getOpcode() == Instruction::ZExt ||
722 Root.getOpcode() == Instruction::SExt)
723 return std::make_pair(cast<CastInst>(Root.getMainOp())->getSrcTy(),
724 Root.getOpcode() == Instruction::SExt);
725 return std::nullopt;
726 }
727
728 /// Checks if the root graph node can be emitted with narrower bitwidth at
729 /// codegen and returns it signedness, if so.
731 return MinBWs.at(&getRootNode()).second;
732 }
733
734 /// Returns reduction type after minbitdth analysis.
736 if (ReductionBitWidth == 0 ||
737 !getRootNodeScalars().front()->getType()->isIntegerTy() ||
738 ReductionBitWidth >=
739 DL->getTypeSizeInBits(getRootNodeScalars().front()->getType()))
742 getRootNode().getVectorFactor()));
745 ReductionBitWidth),
746 getRootNode().getVectorFactor()));
747 }
748
749 /// Returns true if the tree results in one of the reduced bitcasts variants.
750 bool isReducedBitcastRoot() const {
751 return getRootNode().hasState() &&
752 (getRootNode().CombinedOp == TreeEntry::ReducedBitcast ||
753 getRootNode().CombinedOp == TreeEntry::ReducedBitcastBSwap ||
754 getRootNode().CombinedOp == TreeEntry::ReducedBitcastLoads ||
755 getRootNode().CombinedOp == TreeEntry::ReducedBitcastBSwapLoads) &&
756 getRootNode().State == TreeEntry::Vectorize;
757 }
758
759 /// Returns true if the tree results in the reduced cmp bitcast root.
761 return getRootNode().hasState() &&
762 getRootNode().CombinedOp == TreeEntry::ReducedCmpBitcast &&
763 getRootNode().State == TreeEntry::Vectorize;
764 }
765
766 /// Returns true if the tree is a reduction tree.
767 bool isReductionTree() const { return UserIgnoreList != nullptr; }
768
769 /// Builds external uses of the vectorized scalars, i.e. the list of
770 /// vectorized scalars to be extracted, their lanes and their scalar users. \p
771 /// ExternallyUsedValues contains additional list of external uses to handle
772 /// vectorization of reductions.
773 void
774 buildExternalUses(const ExtraValueToDebugLocsMap &ExternallyUsedValues = {});
775
776 /// Transforms graph nodes to target specific representations, if profitable.
777 void transformNodes();
778
779 /// Clear the internal data structures that are created by 'buildTree'.
780 void deleteTree() {
781 VectorizableTree.clear();
782 ScalarToTreeEntries.clear();
783 DeletedNodes.clear();
784 TransformedToGatherNodes.clear();
785 OperandsToTreeEntry.clear();
786 ScalarsInSplitNodes.clear();
787 MustGather.clear();
788 ReassocScalarToTreeEntries.clear();
789 KeptReassocScalars.clear();
790 NonScheduledFirst.clear();
791 EntryToLastInstruction.clear();
792 LastInstructionToPos.clear();
793 LoadEntriesToVectorize.clear();
794 IsGraphTransformMode = false;
795 GatheredLoadsEntriesFirst.reset();
796 SplatGatheredScalarsRoots.clear();
797 CompressEntryToData.clear();
798 ExternalUses.clear();
799 ExternalUsesAsOriginalScalar.clear();
800 ExternalUsesWithNonUsers.clear();
801 ExternalUseReplacements.clear();
802 RTChecks.clear();
803 HasRuntimeCheckableBlockers = false;
804 HasNonCheckableMemBlocker = false;
805 RTChecksFinalized = false;
806 for (auto &Iter : BlocksSchedules) {
807 BlockScheduling *BS = Iter.second.get();
808 BS->clear();
809 }
810 MinBWs.clear();
811 ReductionBitWidth = 0;
812 BaseGraphSize = 1;
813 CastMaxMinBWSizes.reset();
814 ExtraBitWidthNodes.clear();
815 InstrElementSize.clear();
816 UserIgnoreList = nullptr;
817 NarrowedChainInsts.clear();
818 PostponedGathers.clear();
819 ValueToGatherNodes.clear();
820 TreeEntryToStridedPtrInfoMap.clear();
821 CurrentLoopNest.clear();
822 MergedLoopBTCs.clear();
823 }
824
825 unsigned getTreeSize() const { return VectorizableTree.size(); }
826
827 /// Returns the base graph size, before any transformations.
828 unsigned getCanonicalGraphSize() const { return BaseGraphSize; }
829
830 /// Perform LICM and CSE on the newly generated gather sequences.
832
833 /// Does this non-empty order represent an identity order? Identity
834 /// should be represented as an empty order, so this is used to
835 /// decide if we can canonicalize a computed order. Undef elements
836 /// (represented as size) are ignored.
838 assert(!Order.empty() && "expected non-empty order");
839 const unsigned Sz = Order.size();
840 return all_of(enumerate(Order), [&](const auto &P) {
841 return P.value() == P.index() || P.value() == Sz;
842 });
843 }
844
845 /// Checks if the specified gather tree entry \p TE can be represented as a
846 /// shuffled vector entry + (possibly) permutation with other gathers. It
847 /// implements the checks only for possibly ordered scalars (Loads,
848 /// ExtractElement, ExtractValue), which can be part of the graph.
849 /// \param TopToBottom If true, used for the whole tree rotation, false - for
850 /// sub-tree rotations. \param IgnoreReorder true, if the order of the root
851 /// node might be ignored.
852 std::optional<OrdersType> findReusedOrderedScalars(const TreeEntry &TE,
853 bool TopToBottom,
854 bool IgnoreReorder);
855
856 /// Sort loads into increasing pointers offsets to allow greater clustering.
857 std::optional<OrdersType> findPartiallyOrderedLoads(const TreeEntry &TE);
858
859 /// Gets reordering data for the given tree entry. If the entry is vectorized
860 /// - just return ReorderIndices, otherwise check if the scalars can be
861 /// reordered and return the most optimal order.
862 /// \return std::nullopt if ordering is not important, empty order, if
863 /// identity order is important, or the actual order.
864 /// \param TopToBottom If true, include the order of vectorized stores and
865 /// insertelement nodes, otherwise skip them.
866 /// \param IgnoreReorder true, if the root node order can be ignored.
867 std::optional<OrdersType>
868 getReorderingData(const TreeEntry &TE, bool TopToBottom, bool IgnoreReorder);
869
870 /// Checks if it is profitable to reorder the current tree.
871 /// If the tree does not contain many profitable reordable nodes, better to
872 /// skip it to save compile time.
873 bool isProfitableToReorder() const;
874
875 /// Reorders the current graph to the most profitable order starting from the
876 /// root node to the leaf nodes. The best order is chosen only from the nodes
877 /// of the same size (vectorization factor). Smaller nodes are considered
878 /// parts of subgraph with smaller VF and they are reordered independently. We
879 /// can make it because we still need to extend smaller nodes to the wider VF
880 /// and we can merge reordering shuffles with the widening shuffles.
881 void reorderTopToBottom();
882
883 /// Reorders the current graph to the most profitable order starting from
884 /// leaves to the root. It allows to rotate small subgraphs and reduce the
885 /// number of reshuffles if the leaf nodes use the same order. In this case we
886 /// can merge the orders and just shuffle user node instead of shuffling its
887 /// operands. Plus, even the leaf nodes have different orders, it allows to
888 /// sink reordering in the graph closer to the root node and merge it later
889 /// during analysis.
890 void reorderBottomToTop(bool IgnoreReorder = false);
891
892 /// Marks the schedule data of the copyable-modeled operands of \p TE for
893 /// dependency recalculation at the next bundle scheduling.
894 void markCopyableDepsForRecalc(TreeEntry &TE);
895
896 /// \return The vector element size in bits to use when vectorizing the
897 /// expression tree ending at \p V. If V is a store, the size is the width of
898 /// the stored value. Otherwise, the size is the width of the largest loaded
899 /// value reaching V. This method is used by the vectorizer to calculate
900 /// vectorization factors.
901 unsigned getVectorElementSize(Value *V);
902
903 /// Compute the minimum type sizes required to represent the entries in a
904 /// vectorizable tree.
906
907 // \returns maximum vector register size as set by TTI or overridden by cl::opt.
908 unsigned getMaxVecRegSize() const {
909 return MaxVecRegSize;
910 }
911
912 // \returns minimum vector register size as set by cl::opt.
913 unsigned getMinVecRegSize() const {
914 return MinVecRegSize;
915 }
916
917 /// \returns the number of parts, the type \p VecTy is split at the codegen
918 /// phase. The type legalization queries are repeated for the very same types
919 /// during the analysis, so the results are cached for the function.
921 Type *VecTy, Type *ScalarTy,
922 unsigned Limit = std::numeric_limits<unsigned>::max()) const {
923 auto [It, Inserted] =
924 NumberOfPartsCache.try_emplace(std::make_tuple(VecTy, ScalarTy, Limit));
925 if (Inserted)
926 It->second = ::getNumberOfParts(*TTI, VecTy, ScalarTy, Limit);
927 return It->second;
928 }
929
930 unsigned getMinVF(unsigned Sz) const {
931 return std::max(2U, getMinVecRegSize() / Sz);
932 }
933
934 unsigned getMaximumVF(unsigned ElemWidth, unsigned Opcode) const {
935 unsigned MaxVF = MaxVFOption.getNumOccurrences() ?
936 MaxVFOption : TTI->getMaximumVF(ElemWidth, Opcode);
937 return MaxVF ? MaxVF : UINT_MAX;
938 }
939
940 /// Check if homogeneous aggregate is isomorphic to some VectorType.
941 /// Accepts homogeneous multidimensional aggregate of scalars/vectors like
942 /// {[4 x i16], [4 x i16]}, { <2 x float>, <2 x float> },
943 /// {{{i16, i16}, {i16, i16}}, {{i16, i16}, {i16, i16}}} and so on.
944 ///
945 /// \returns number of elements in vector if isomorphism exists, 0 otherwise.
946 unsigned canMapToVector(Type *T) const;
947
948 /// \returns true if the vectorized insertvalue result can be stored directly
949 /// as a vector, i.e. every insertvalue with an external user is consumed by a
950 /// single store only.
951 bool canVectorStoreInsertValue(const TreeEntry *E) const;
952
953 /// \returns the source vector type for an InsertElement/InsertValue
954 /// buildvector node \p E: the inserted vector type for insertelement, or a
955 /// vector of the inserted scalar type wide enough to cover the highest
956 /// inserted index for insertvalue.
957 FixedVectorType *getInsertBuildVectorSrcTy(const TreeEntry *E) const;
958
959 /// \returns True if the VectorizableTree is both tiny and not fully
960 /// vectorizable. We do not vectorize such trees.
961 bool isTreeTinyAndNotFullyVectorizable(bool ForReduction = false) const;
962
963 /// Checks if the graph and all its subgraphs cannot be better vectorized.
964 /// It may happen, if all gather nodes are loads and they cannot be
965 /// "clusterized". In this case even subgraphs cannot be vectorized more
966 /// effectively than the base graph.
967 bool isTreeNotExtendable() const;
968
969 bool isStridedLoad(ArrayRef<Value *> PointerOps, Type *ScalarTy,
970 Align Alignment, const int64_t Diff,
971 const size_t Sz) const;
972
973 /// Return true if an array of scalar loads can be replaced with a strided
974 /// load (with constant stride).
975 ///
976 /// It is possible that the load gets "widened". Suppose that originally each
977 /// load loads `k` bytes and `PointerOps` can be arranged as follows (`%s` is
978 /// constant): %b + 0 * %s + 0 %b + 0 * %s + 1 %b + 0 * %s + 2
979 /// ...
980 /// %b + 0 * %s + (w - 1)
981 ///
982 /// %b + 1 * %s + 0
983 /// %b + 1 * %s + 1
984 /// %b + 1 * %s + 2
985 /// ...
986 /// %b + 1 * %s + (w - 1)
987 /// ...
988 ///
989 /// %b + (n - 1) * %s + 0
990 /// %b + (n - 1) * %s + 1
991 /// %b + (n - 1) * %s + 2
992 /// ...
993 /// %b + (n - 1) * %s + (w - 1)
994 ///
995 /// In this case we will generate a strided load of type `<n x (k * w)>`.
996 ///
997 /// \param PointerOps list of pointer arguments of loads.
998 /// \param ElemTy original scalar type of loads.
999 /// \param Alignment alignment of the first load.
1000 /// \param SortedIndices is the order of PointerOps as returned by
1001 /// `sortPtrAccesses`
1002 /// \param Diff Pointer difference between the lowest and the highes pointer
1003 /// in `PointerOps` as returned by `getPointersDiff`.
1004 /// \param Ptr0 first pointer in `PointersOps`.
1005 /// \param PtrN last pointer in `PointersOps`.
1006 /// \param SPtrInfo If the function return `true`, it also sets all the fields
1007 /// of `SPtrInfo` necessary to generate the strided load later.
1009 const ArrayRef<Value *> PointerOps, Type *ElemTy, Align Alignment,
1010 const SmallVectorImpl<unsigned> &SortedIndices, const int64_t Diff,
1011 Value *Ptr0, StridedPtrInfo &SPtrInfo) const;
1012
1013 /// Return true if an array of scalar loads can be replaced with a strided
1014 /// load (with run-time stride).
1015 /// \param PointerOps list of pointer arguments of loads.
1016 /// \param ScalarTy type of loads.
1017 /// \param CommonAlignment common alignement of loads as computed by
1018 /// `computeCommonAlignment<LoadInst>`.
1019 /// \param SortedIndicies is a list of indicies computed by this function such
1020 /// that the sequence `PointerOps[SortedIndices[0]],
1021 /// PointerOps[SortedIndicies[1]], ..., PointerOps[SortedIndices[n]]` is
1022 /// ordered by the coefficient of the stride. For example, if PointerOps is
1023 /// `%base + %stride, %base, %base + 2 * stride` the `SortedIndices` will be
1024 /// `[1, 0, 2]`. We follow the convention that if `SortedIndices` has to be
1025 /// `0, 1, 2, 3, ...` we return empty vector for `SortedIndicies`.
1026 /// \param SPtrInfo If the function return `true`, it also sets all the fields
1027 /// of `SPtrInfo` necessary to generate the strided load later.
1028 /// \param IsLoad Is this a strided load (true) or strided store (false)
1029 bool analyzeRtStrideCandidate(ArrayRef<Value *> PointerOps, Type *ScalarTy,
1030 Align CommonAlignment,
1031 SmallVectorImpl<unsigned> &SortedIndices,
1032 StridedPtrInfo &SPtrInfo, bool IsLoad) const;
1033
1034 /// Checks if the given array of loads can be represented as a vectorized,
1035 /// scatter or just simple gather.
1036 /// \param VL list of loads.
1037 /// \param VL0 main load value.
1038 /// \param Order returned order of load instructions.
1039 /// \param PointerOps returned list of pointer operands.
1040 /// \param BestVF return best vector factor, if recursive check found better
1041 /// vectorization sequences rather than masked gather.
1042 /// \param TryRecursiveCheck used to check if long masked gather can be
1043 /// represented as a serie of loads/insert subvector, if profitable.
1046 SmallVectorImpl<Value *> &PointerOps,
1047 StridedPtrInfo &SPtrInfo,
1048 unsigned *BestVF = nullptr,
1049 bool TryRecursiveCheck = true) const;
1050
1051 /// Checks whether some existing tree entry has scalars equal to \p VL.
1052 /// \p S is the common opcode of \p VL when one exists; an empty \p S means
1053 /// the values have no common opcode (mixed buildvector/gather candidates).
1055 auto IsSame = [&](const TreeEntry *TE) { return TE->isSame(VL); };
1056 if (S) {
1057 // Any vectorized or gather entry equal to VL must contain S.getMainOp()
1058 // (the representative instruction, which is also the recorded scalar
1059 // for copyable-elements bundles), so probing the MainOp-indexed maps
1060 // is sufficient and avoids scanning the whole tree.
1061 return any_of(getTreeEntries(S.getMainOp()), IsSame) ||
1062 any_of(ValueToGatherNodes.lookup(S.getMainOp()), IsSame);
1063 }
1064 // No common opcode: only gather entries can match. Each non-constant
1065 // value in VL has to be in the gather entry's scalar list and is
1066 // therefore present in ValueToGatherNodes. Probe by VL members instead
1067 // of scanning the whole tree (O(tree) -> O(|VL|)).
1069 for (Value *V : VL) {
1070 // Constants/poisons are not tracked in ValueToGatherNodes.
1071 if (isConstant(V))
1072 continue;
1073 for (const TreeEntry *TE : ValueToGatherNodes.lookup(V)) {
1074 if (!Visited.insert(TE).second)
1075 continue;
1076 if (IsSame(TE))
1077 return true;
1078 }
1079 }
1080 return false;
1081 }
1082
1083 /// Registers non-vectorizable sequence of loads
1084 template <typename T> void registerNonVectorizableLoads(ArrayRef<T *> VL) {
1085 ListOfKnonwnNonVectorizableLoads.insert(hash_value(VL));
1086 }
1087
1088 /// Checks if the given loads sequence is known as not vectorizable
1089 template <typename T>
1091 return ListOfKnonwnNonVectorizableLoads.contains(hash_value(VL));
1092 }
1093
1095
1096 /// This structure holds any data we need about the edges being traversed
1097 /// during buildTreeRec(). We keep track of:
1098 /// (i) the user TreeEntry index, and
1099 /// (ii) the index of the edge.
1100 struct EdgeInfo {
1101 EdgeInfo() = default;
1102 EdgeInfo(TreeEntry *UserTE, unsigned EdgeIdx)
1104 /// The user TreeEntry.
1105 TreeEntry *UserTE = nullptr;
1106 /// The operand index of the use.
1107 unsigned EdgeIdx = UINT_MAX;
1108#ifndef NDEBUG
1110 const BoUpSLP::EdgeInfo &EI) {
1111 EI.dump(OS);
1112 return OS;
1113 }
1114 /// Debug print.
1115 void dump(raw_ostream &OS) const {
1116 OS << "{User:" << (UserTE ? std::to_string(UserTE->Idx) : "null")
1117 << " EdgeIdx:" << EdgeIdx << "}";
1118 }
1119 LLVM_DUMP_METHOD void dump() const { dump(dbgs()); }
1120#endif
1121 bool operator == (const EdgeInfo &Other) const {
1122 return UserTE == Other.UserTE && EdgeIdx == Other.EdgeIdx;
1123 }
1124
1125 operator bool() const { return UserTE != nullptr; }
1126 };
1127 friend struct DenseMapInfo<EdgeInfo>;
1128
1129 /// A helper class used for scoring candidates for two consecutive lanes.
1131 const TargetLibraryInfo &TLI;
1132 const DataLayout &DL;
1133 ScalarEvolution &SE;
1134 const BoUpSLP &R;
1135 int NumLanes; // Total number of lanes (aka vectorization factor).
1136 int MaxLevel; // The maximum recursion depth for accumulating score.
1137
1138 public:
1140 ScalarEvolution &SE, const BoUpSLP &R, int NumLanes,
1141 int MaxLevel)
1142 : TLI(TLI), DL(DL), SE(SE), R(R), NumLanes(NumLanes),
1143 MaxLevel(MaxLevel) {}
1144
1145 // The hard-coded scores listed here are not very important, though it shall
1146 // be higher for better matches to improve the resulting cost. When
1147 // computing the scores of matching one sub-tree with another, we are
1148 // basically counting the number of values that are matching. So even if all
1149 // scores are set to 1, we would still get a decent matching result.
1150 // However, sometimes we have to break ties. For example we may have to
1151 // choose between matching loads vs matching opcodes. This is what these
1152 // scores are helping us with: they provide the order of preference. Also,
1153 // this is important if the scalar is externally used or used in another
1154 // tree entry node in the different lane.
1155
1156 /// Loads from consecutive memory addresses, e.g. load(A[i]), load(A[i+1]).
1157 static constexpr int ScoreConsecutiveLoads = 40;
1158 /// The same load multiple times. This should have a better score than
1159 /// `ScoreSplat` because it in x86 for a 2-lane vector we can represent it
1160 /// with `movddup (%reg), xmm0` which has a throughput of 0.5 versus 0.5 for
1161 /// a vector load and 1.0 for a broadcast.
1162 static constexpr int ScoreSplatLoads = 30;
1163 /// Loads from reversed memory addresses, e.g. load(A[i+1]), load(A[i]).
1164 static constexpr int ScoreReversedLoads = 30;
1165 /// A load candidate for masked gather.
1166 static constexpr int ScoreMaskedGatherCandidate = 10;
1167 /// ExtractElementInst from same vector and consecutive indexes.
1168 static constexpr int ScoreConsecutiveExtracts = 40;
1169 /// ExtractElementInst from same vector and reversed indices.
1170 static constexpr int ScoreReversedExtracts = 30;
1171 /// Constants.
1172 static constexpr int ScoreConstants = 15;
1173 /// Same constants.
1174 static constexpr int ScoreSameConstants = 17;
1175 /// Instructions with the same opcode.
1176 static constexpr int ScoreSameOpcode = 20;
1177 /// Instructions with alt opcodes (e.g, add + sub).
1178 static constexpr int ScoreAltOpcodes = 10;
1179 /// Identical instructions (a.k.a. splat or broadcast).
1180 static constexpr int ScoreSplat = 10;
1181 /// Matching with an undef is preferable to failing.
1182 static constexpr int ScoreUndef = 10;
1183 /// Score for failing to find a decent match.
1184 static constexpr int ScoreFail = 0;
1185 /// Score if all users are vectorized.
1186 static constexpr int ScoreAllUserVectorized = 10;
1187
1188 /// \returns the score of placing \p V1 and \p V2 in consecutive lanes.
1189 /// \p U1 and \p U2 are the users of \p V1 and \p V2.
1190 /// Also, checks if \p V1 and \p V2 are compatible with instructions in \p
1191 /// MainAltOps.
1193 ArrayRef<Value *> MainAltOps) const {
1194 if (!isValidElementType(V1->getType(), SLPReVec) ||
1197
1198 if (V1 == V2) {
1199 if (isa<LoadInst>(V1)) {
1200 // Retruns true if the users of V1 and V2 won't need to be extracted.
1201 auto AllUsersAreInternal = [U1, U2, this](Value *V1, Value *V2) {
1202 // Bail out if we have too many uses to save compilation time.
1203 if (V1->hasNUsesOrMore(UsesLimit) || V2->hasNUsesOrMore(UsesLimit))
1204 return false;
1205
1206 auto AllUsersVectorized = [U1, U2, this](Value *V) {
1207 return llvm::all_of(V->users(), [U1, U2, this](Value *U) {
1208 return U == U1 || U == U2 || R.isVectorized(U);
1209 });
1210 };
1211 return AllUsersVectorized(V1) && AllUsersVectorized(V2);
1212 };
1213 // A broadcast of a load can be cheaper on some targets.
1214 if (R.TTI->isLegalBroadcastLoad(V1->getType(),
1215 ElementCount::getFixed(NumLanes)) &&
1216 ((int)V1->getNumUses() == NumLanes ||
1217 AllUsersAreInternal(V1, V2)))
1219 }
1220 if (isa<UndefValue>(V1))
1222 if (isConstant(V1))
1225 }
1226
1227 auto CheckSameEntryOrFail = [&]() {
1228 if (ArrayRef<TreeEntry *> TEs1 = R.getTreeEntries(V1); !TEs1.empty()) {
1230 if (ArrayRef<TreeEntry *> TEs2 = R.getTreeEntries(V2);
1231 !TEs2.empty() &&
1232 any_of(TEs2, [&](TreeEntry *E) { return Set.contains(E); }))
1234 }
1236 };
1237
1238 auto *LI1 = dyn_cast<LoadInst>(V1);
1239 auto *LI2 = dyn_cast<LoadInst>(V2);
1240 if (LI1 && LI2) {
1241 if (LI1->getParent() != LI2->getParent() || !LI1->isSimple() ||
1242 !LI2->isSimple())
1243 return CheckSameEntryOrFail();
1244
1245 std::optional<int64_t> Dist = getPointersDiff(
1246 LI1->getType(), LI1->getPointerOperand(), LI2->getType(),
1247 LI2->getPointerOperand(), DL, SE, /*StrictCheck=*/true);
1248 if (!Dist || *Dist == 0) {
1249 if (getUnderlyingObject(LI1->getPointerOperand()) ==
1250 getUnderlyingObject(LI2->getPointerOperand()) &&
1251 R.TTI->isLegalMaskedGather(
1252 getWidenedType(LI1->getType(), NumLanes), LI1->getAlign()))
1254 return CheckSameEntryOrFail();
1255 }
1256 // The distance is too large - still may be profitable to use masked
1257 // loads/gathers.
1258 if (std::abs(*Dist) > NumLanes / 2)
1260 // This still will detect consecutive loads, but we might have "holes"
1261 // in some cases. It is ok for non-power-2 vectorization and may produce
1262 // better results. It should not affect current vectorization.
1265 }
1266
1267 auto *C1 = dyn_cast<Constant>(V1);
1268 auto *C2 = dyn_cast<Constant>(V2);
1269 if (C1 && C2)
1271
1272 // Consider constants and buildvector compatible.
1273 if ((C1 && isa<InsertElementInst>(V2)) ||
1274 (C2 && isa<InsertElementInst>(V1)))
1276
1277 // Extracts from consecutive indexes of the same vector better score as
1278 // the extracts could be optimized away.
1279 Value *EV1;
1280 ConstantInt *Ex1Idx;
1281 if (match(V1, m_ExtractElt(m_Value(EV1), m_ConstantInt(Ex1Idx)))) {
1282 // Undefs are always profitable for extractelements.
1283 // Compiler can easily combine poison and extractelement <non-poison> or
1284 // undef and extractelement <poison>. But combining undef +
1285 // extractelement <non-poison-but-may-produce-poison> requires some
1286 // extra operations.
1287 if (isa<UndefValue>(V2))
1288 return (isa<PoisonValue>(V2) || isUndefVector(EV1).all())
1291 Value *EV2 = nullptr;
1292 ConstantInt *Ex2Idx = nullptr;
1293 if (match(V2,
1295 m_Undef())))) {
1296 // Undefs are always profitable for extractelements.
1297 if (!Ex2Idx)
1299 if (isUndefVector(EV2).all() && EV2->getType() == EV1->getType())
1301 if (EV2 == EV1) {
1302 int Idx1 = Ex1Idx->getZExtValue();
1303 int Idx2 = Ex2Idx->getZExtValue();
1304 int Dist = Idx2 - Idx1;
1305 // The distance is too large - still may be profitable to use
1306 // shuffles.
1307 if (std::abs(Dist) == 0)
1309 if (std::abs(Dist) > NumLanes / 2)
1313 }
1315 }
1316 return CheckSameEntryOrFail();
1317 }
1318
1319 auto *I1 = dyn_cast<Instruction>(V1);
1320 auto *I2 = dyn_cast<Instruction>(V2);
1321 if (I1 && I2) {
1322 if (I1->getParent() != I2->getParent())
1323 return CheckSameEntryOrFail();
1324 Value *V;
1325 Value *Cond;
1326 // ZExt i1 to something must be considered same opcode for select i1
1327 // cmp, x, y
1328 // Required to better match the transformation after
1329 // BoUpSLP::matchesInversedZExtSelect analysis.
1330 if ((match(I1, m_ZExt(m_Value(V))) &&
1331 match(I2, m_Select(m_Value(Cond), m_Value(), m_Value())) &&
1332 V->getType() == Cond->getType()) ||
1333 (match(I2, m_ZExt(m_Value(V))) &&
1334 match(I1, m_Select(m_Value(Cond), m_Value(), m_Value())) &&
1335 V->getType() == Cond->getType()))
1337 SmallVector<Value *, 4> Ops(MainAltOps);
1338 Ops.push_back(I1);
1339 Ops.push_back(I2);
1341 // Note: Only consider instructions with <= 2 operands to avoid
1342 // complexity explosion.
1343 if (S &&
1344 (S.getMainOp()->getNumOperands() <= 2 || !MainAltOps.empty() ||
1345 !S.isAltShuffle()) &&
1346 all_of(Ops, [&S](Value *V) {
1347 return isa<PoisonValue>(V) ||
1348 cast<Instruction>(V)->getNumOperands() ==
1350 }))
1353 }
1354
1355 if (I1 && isa<PoisonValue>(V2))
1357
1358 if (isa<UndefValue>(V2))
1360
1361 return CheckSameEntryOrFail();
1362 }
1363
1364 /// Go through the operands of \p LHS and \p RHS recursively until
1365 /// MaxLevel, and return the cummulative score. \p U1 and \p U2 are
1366 /// the users of \p LHS and \p RHS (that is \p LHS and \p RHS are operands
1367 /// of \p U1 and \p U2), except at the beginning of the recursion where
1368 /// these are set to nullptr.
1369 ///
1370 /// For example:
1371 /// \verbatim
1372 /// A[0] B[0] A[1] B[1] C[0] D[0] B[1] A[1]
1373 /// \ / \ / \ / \ /
1374 /// + + + +
1375 /// G1 G2 G3 G4
1376 /// \endverbatim
1377 /// The getScoreAtLevelRec(G1, G2) function will try to match the nodes at
1378 /// each level recursively, accumulating the score. It starts from matching
1379 /// the additions at level 0, then moves on to the loads (level 1). The
1380 /// score of G1 and G2 is higher than G1 and G3, because {A[0],A[1]} and
1381 /// {B[0],B[1]} match with LookAheadHeuristics::ScoreConsecutiveLoads, while
1382 /// {A[0],C[0]} has a score of LookAheadHeuristics::ScoreFail.
1383 /// Please note that the order of the operands does not matter, as we
1384 /// evaluate the score of all profitable combinations of operands. In
1385 /// other words the score of G1 and G4 is the same as G1 and G2. This
1386 /// heuristic is based on ideas described in:
1387 /// Look-ahead SLP: Auto-vectorization in the presence of commutative
1388 /// operations, CGO 2018 by Vasileios Porpodas, Rodrigo C. O. Rocha,
1389 /// Luís F. W. Góes
1391 Instruction *U2, int CurrLevel,
1392 ArrayRef<Value *> MainAltOps) const {
1393
1394 // Get the shallow score of V1 and V2.
1395 int ShallowScoreAtThisLevel =
1396 getShallowScore(LHS, RHS, U1, U2, MainAltOps);
1397
1398 // If reached MaxLevel,
1399 // or if V1 and V2 are not instructions,
1400 // or if they are SPLAT,
1401 // or if they are not consecutive,
1402 // or if profitable to vectorize loads or extractelements, early return
1403 // the current cost.
1404 auto *I1 = dyn_cast<Instruction>(LHS);
1405 auto *I2 = dyn_cast<Instruction>(RHS);
1406 if (CurrLevel == MaxLevel || !(I1 && I2) || I1 == I2 ||
1407 ShallowScoreAtThisLevel == LookAheadHeuristics::ScoreFail ||
1408 (((isa<LoadInst>(I1) && isa<LoadInst>(I2)) ||
1409 (I1->getNumOperands() > 2 && I2->getNumOperands() > 2) ||
1411 ShallowScoreAtThisLevel))
1412 return ShallowScoreAtThisLevel;
1413 assert(I1 && I2 && "Should have early exited.");
1414
1415 // Contains the I2 operand indexes that got matched with I1 operands.
1416 SmallSet<unsigned, 4> Op2Used;
1417
1418 // Recursion towards the operands of I1 and I2. We are trying all possible
1419 // operand pairs, and keeping track of the best score.
1420 if (I1->getNumOperands() != I2->getNumOperands())
1422 for (unsigned OpIdx1 = 0, NumOperands1 = I1->getNumOperands();
1423 OpIdx1 != NumOperands1; ++OpIdx1) {
1424 // Try to pair op1I with the best operand of I2.
1425 int MaxTmpScore = 0;
1426 unsigned MaxOpIdx2 = 0;
1427 bool FoundBest = false;
1428 // If I2 is commutative try all combinations.
1429 unsigned FromIdx = isCommutative(I2) ? 0 : OpIdx1;
1430 unsigned ToIdx = isCommutative(I2)
1431 ? I2->getNumOperands()
1432 : std::min(I2->getNumOperands(), OpIdx1 + 1);
1433 assert(FromIdx <= ToIdx && "Bad index");
1434 for (unsigned OpIdx2 = FromIdx; OpIdx2 != ToIdx; ++OpIdx2) {
1435 // Skip operands already paired with OpIdx1.
1436 if (Op2Used.count(OpIdx2))
1437 continue;
1438 // Recursively calculate the cost at each level
1439 int TmpScore =
1440 getScoreAtLevelRec(I1->getOperand(OpIdx1), I2->getOperand(OpIdx2),
1441 I1, I2, CurrLevel + 1, {});
1442 // Look for the best score.
1443 if (TmpScore > LookAheadHeuristics::ScoreFail &&
1444 TmpScore > MaxTmpScore) {
1445 MaxTmpScore = TmpScore;
1446 MaxOpIdx2 = OpIdx2;
1447 FoundBest = true;
1448 }
1449 }
1450 if (FoundBest) {
1451 // Pair {OpIdx1, MaxOpIdx2} was found to be best. Never revisit it.
1452 Op2Used.insert(MaxOpIdx2);
1453 ShallowScoreAtThisLevel += MaxTmpScore;
1454 }
1455 }
1456 return ShallowScoreAtThisLevel;
1457 }
1458 };
1459 /// A helper data structure to hold the operands of a vector of instructions.
1460 /// This supports a fixed vector length for all operand vectors.
1462 /// For each operand we need (i) the value, and (ii) the opcode that it
1463 /// would be attached to if the expression was in a left-linearized form.
1464 /// This is required to avoid illegal operand reordering.
1465 /// For example:
1466 /// \verbatim
1467 /// 0 Op1
1468 /// |/
1469 /// Op1 Op2 Linearized + Op2
1470 /// \ / ----------> |/
1471 /// - -
1472 ///
1473 /// Op1 - Op2 (0 + Op1) - Op2
1474 /// \endverbatim
1475 ///
1476 /// Value Op1 is attached to a '+' operation, and Op2 to a '-'.
1477 ///
1478 /// Another way to think of this is to track all the operations across the
1479 /// path from the operand all the way to the root of the tree and to
1480 /// calculate the operation that corresponds to this path. For example, the
1481 /// path from Op2 to the root crosses the RHS of the '-', therefore the
1482 /// corresponding operation is a '-' (which matches the one in the
1483 /// linearized tree, as shown above).
1484 ///
1485 /// For lack of a better term, we refer to this operation as Accumulated
1486 /// Path Operation (APO).
1487 struct OperandData {
1488 OperandData() = default;
1489 OperandData(Value *V, bool APO, bool IsUsed)
1490 : V(V), APO(APO), IsUsed(IsUsed) {}
1491 /// The operand value.
1492 Value *V = nullptr;
1493 /// TreeEntries only allow a single opcode, or an alternate sequence of
1494 /// them (e.g, +, -). Therefore, we can safely use a boolean value for the
1495 /// APO. It is set to 'true' if 'V' is attached to an inverse operation
1496 /// in the left-linearized form (e.g., Sub/Div), and 'false' otherwise
1497 /// (e.g., Add/Mul)
1498 bool APO = false;
1499 /// Helper data for the reordering function.
1500 bool IsUsed = false;
1501 };
1502
1503 /// During operand reordering, we are trying to select the operand at lane
1504 /// that matches best with the operand at the neighboring lane. Our
1505 /// selection is based on the type of value we are looking for. For example,
1506 /// if the neighboring lane has a load, we need to look for a load that is
1507 /// accessing a consecutive address. These strategies are summarized in the
1508 /// 'ReorderingMode' enumerator.
1509 enum class ReorderingMode {
1510 Load, ///< Matching loads to consecutive memory addresses
1511 Opcode, ///< Matching instructions based on opcode (same or alternate)
1512 Constant, ///< Matching constants
1513 Splat, ///< Matching the same instruction multiple times (broadcast)
1514 Failed, ///< We failed to create a vectorizable group
1515 };
1516
1517 using OperandDataVec = SmallVector<OperandData, 2>;
1518
1519 /// A vector of operand vectors.
1521 /// When VL[0] is IntrinsicInst, ArgSize is CallBase::arg_size. When VL[0]
1522 /// is not IntrinsicInst, ArgSize is User::getNumOperands.
1523 unsigned ArgSize = 0;
1524
1525 const TargetLibraryInfo &TLI;
1526 const DataLayout &DL;
1527 ScalarEvolution &SE;
1528 const BoUpSLP &R;
1529 const Loop *L = nullptr;
1530
1531 /// \returns the operand data at \p OpIdx and \p Lane.
1532 OperandData &getData(unsigned OpIdx, unsigned Lane) {
1533 return OpsVec[OpIdx][Lane];
1534 }
1535
1536 /// \returns the operand data at \p OpIdx and \p Lane. Const version.
1537 const OperandData &getData(unsigned OpIdx, unsigned Lane) const {
1538 return OpsVec[OpIdx][Lane];
1539 }
1540
1541 /// Clears the used flag for all entries.
1542 void clearUsed() {
1543 for (unsigned OpIdx = 0, NumOperands = getNumOperands();
1544 OpIdx != NumOperands; ++OpIdx)
1545 for (unsigned Lane = 0, NumLanes = getNumLanes(); Lane != NumLanes;
1546 ++Lane)
1547 OpsVec[OpIdx][Lane].IsUsed = false;
1548 }
1549
1550 /// Swap the operand at \p OpIdx1 with that one at \p OpIdx2.
1551 void swap(unsigned OpIdx1, unsigned OpIdx2, unsigned Lane) {
1552 std::swap(OpsVec[OpIdx1][Lane], OpsVec[OpIdx2][Lane]);
1553 }
1554
1555 /// \param Lane lane of the operands under analysis.
1556 /// \param OpIdx operand index in \p Lane lane we're looking the best
1557 /// candidate for.
1558 /// \param Idx operand index of the current candidate value.
1559 /// \returns The additional score due to possible broadcasting of the
1560 /// elements in the lane. It is more profitable to have power-of-2 unique
1561 /// elements in the lane, it will be vectorized with higher probability
1562 /// after removing duplicates. Currently the SLP vectorizer supports only
1563 /// vectorization of the power-of-2 number of unique scalars.
1564 int getSplatScore(unsigned Lane, unsigned OpIdx, unsigned Idx,
1565 const SmallBitVector &UsedLanes) const {
1566 Value *IdxLaneV = getData(Idx, Lane).V;
1567 if (!isa<Instruction>(IdxLaneV) || IdxLaneV == getData(OpIdx, Lane).V ||
1568 isa<ExtractElementInst>(IdxLaneV))
1569 return 0;
1571 for (unsigned Ln : seq<unsigned>(getNumLanes())) {
1572 if (Ln == Lane)
1573 continue;
1574 Value *OpIdxLnV = getData(OpIdx, Ln).V;
1575 if (!isa<Instruction>(OpIdxLnV))
1576 return 0;
1577 Uniques.try_emplace(OpIdxLnV, Ln);
1578 }
1579 unsigned UniquesCount = Uniques.size();
1580 auto IdxIt = Uniques.find(IdxLaneV);
1581 unsigned UniquesCntWithIdxLaneV =
1582 IdxIt != Uniques.end() ? UniquesCount : UniquesCount + 1;
1583 Value *OpIdxLaneV = getData(OpIdx, Lane).V;
1584 auto OpIdxIt = Uniques.find(OpIdxLaneV);
1585 unsigned UniquesCntWithOpIdxLaneV =
1586 OpIdxIt != Uniques.end() ? UniquesCount : UniquesCount + 1;
1587 if (UniquesCntWithIdxLaneV == UniquesCntWithOpIdxLaneV)
1588 return 0;
1589 return std::min(bit_ceil(UniquesCntWithOpIdxLaneV) -
1590 UniquesCntWithOpIdxLaneV,
1591 UniquesCntWithOpIdxLaneV -
1592 bit_floor(UniquesCntWithOpIdxLaneV)) -
1593 ((IdxIt != Uniques.end() && UsedLanes.test(IdxIt->second))
1594 ? UniquesCntWithIdxLaneV - bit_floor(UniquesCntWithIdxLaneV)
1595 : bit_ceil(UniquesCntWithIdxLaneV) - UniquesCntWithIdxLaneV);
1596 }
1597
1598 /// \param Lane lane of the operands under analysis.
1599 /// \param OpIdx operand index in \p Lane lane we're looking the best
1600 /// candidate for.
1601 /// \param Idx operand index of the current candidate value.
1602 /// \returns The additional score for the scalar which users are all
1603 /// vectorized.
1604 int getExternalUseScore(unsigned Lane, unsigned OpIdx, unsigned Idx) const {
1605 Value *IdxLaneV = getData(Idx, Lane).V;
1606 Value *OpIdxLaneV = getData(OpIdx, Lane).V;
1607 // Do not care about number of uses for vector-like instructions
1608 // (extractelement/extractvalue with constant indices), they are extracts
1609 // themselves and already externally used. Vectorization of such
1610 // instructions does not add extra extractelement instruction, just may
1611 // remove it.
1612 if (isVectorLikeInstWithConstOps(IdxLaneV) &&
1613 isVectorLikeInstWithConstOps(OpIdxLaneV))
1615 auto *IdxLaneI = dyn_cast<Instruction>(IdxLaneV);
1616 if (!IdxLaneI || !isa<Instruction>(OpIdxLaneV))
1617 return 0;
1618 return R.areAllUsersVectorized(IdxLaneI)
1620 : 0;
1621 }
1622
1623 /// Score scaling factor for fully compatible instructions but with
1624 /// different number of external uses. Allows better selection of the
1625 /// instructions with less external uses.
1626 static constexpr int ScoreScaleFactor = 10;
1627 /// Scale factor for constants only.
1628 static constexpr int ScoreConstantScaleFactor = 6;
1629
1630 /// \Returns the look-ahead score, which tells us how much the sub-trees
1631 /// rooted at \p LHS and \p RHS match, the more they match the higher the
1632 /// score. This helps break ties in an informed way when we cannot decide on
1633 /// the order of the operands by just considering the immediate
1634 /// predecessors.
1635 int getLookAheadScore(Value *LHS, Value *RHS, ArrayRef<Value *> MainAltOps,
1636 int Lane, unsigned OpIdx, unsigned Idx,
1637 bool &IsUsed, const SmallBitVector &UsedLanes) {
1638 LookAheadHeuristics LookAhead(TLI, DL, SE, R, getNumLanes(),
1640 // Keep track of the instruction stack as we recurse into the operands
1641 // during the look-ahead score exploration.
1642 int Score =
1643 LookAhead.getScoreAtLevelRec(LHS, RHS, /*U1=*/nullptr, /*U2=*/nullptr,
1644 /*CurrLevel=*/1, MainAltOps);
1645 if (Score) {
1646 int SplatScore =
1647 getSplatScore(Lane, OpIdx, Idx, UsedLanes) * ScoreScaleFactor;
1648 if (Score <= -SplatScore) {
1649 // Failed score.
1650 Score = 0;
1651 } else {
1652 Score += SplatScore;
1653 // Scale score to see the difference between different operands
1654 // and similar operands but all vectorized/not all vectorized
1655 // uses. It does not affect actual selection of the best
1656 // compatible operand in general, just allows to select the
1657 // operand with all vectorized uses.
1658 const int SF = (LHS == RHS && isConstant(LHS))
1659 ? ScoreConstantScaleFactor
1660 : ScoreScaleFactor;
1661 Score *= SF;
1662 Score += getExternalUseScore(Lane, OpIdx, Idx);
1663 IsUsed = true;
1664 }
1665 }
1666 return Score;
1667 }
1668
1669 /// Best defined scores per lanes between the passes. Used to choose the
1670 /// best operand (with the highest score) between the passes.
1671 /// The key - {Operand Index, Lane}.
1672 /// The value - the best score between the passes for the lane and the
1673 /// operand.
1675 BestScoresPerLanes;
1676
1677 // Search all operands in Ops[*][Lane] for the one that matches best
1678 // Ops[OpIdx][LastLane] and return its opreand index.
1679 // If no good match can be found, return std::nullopt.
1680 std::optional<unsigned>
1681 getBestOperand(unsigned OpIdx, int Lane, int LastLane,
1682 ArrayRef<ReorderingMode> ReorderingModes,
1683 ArrayRef<Value *> MainAltOps,
1684 const SmallBitVector &UsedLanes) {
1685 unsigned NumOperands = getNumOperands();
1686
1687 // The operand of the previous lane at OpIdx.
1688 Value *OpLastLane = getData(OpIdx, LastLane).V;
1689
1690 // Our strategy mode for OpIdx.
1691 ReorderingMode RMode = ReorderingModes[OpIdx];
1692 if (RMode == ReorderingMode::Failed)
1693 return std::nullopt;
1694
1695 // The linearized opcode of the operand at OpIdx, Lane.
1696 bool OpIdxAPO = getData(OpIdx, Lane).APO;
1697
1698 // The best operand index and its score.
1699 // Sometimes we have more than one option (e.g., Opcode and Undefs), so we
1700 // are using the score to differentiate between the two.
1701 struct BestOpData {
1702 std::optional<unsigned> Idx;
1703 unsigned Score = 0;
1704 } BestOp;
1705 BestOp.Score =
1706 BestScoresPerLanes.try_emplace(std::make_pair(OpIdx, Lane), 0)
1707 .first->second;
1708
1709 // Track if the operand must be marked as used. If the operand is set to
1710 // Score 1 explicitly (because of non power-of-2 unique scalars, we may
1711 // want to reestimate the operands again on the following iterations).
1712 bool IsUsed = RMode == ReorderingMode::Splat ||
1713 RMode == ReorderingMode::Constant ||
1714 RMode == ReorderingMode::Load;
1715 // Iterate through all unused operands and look for the best.
1716 for (unsigned Idx = 0; Idx != NumOperands; ++Idx) {
1717 // Get the operand at Idx and Lane.
1718 OperandData &OpData = getData(Idx, Lane);
1719 Value *Op = OpData.V;
1720 bool OpAPO = OpData.APO;
1721
1722 // Skip already selected operands.
1723 if (OpData.IsUsed)
1724 continue;
1725
1726 // Skip if we are trying to move the operand to a position with a
1727 // different opcode in the linearized tree form. This would break the
1728 // semantics.
1729 if (OpAPO != OpIdxAPO)
1730 continue;
1731
1732 // Look for an operand that matches the current mode.
1733 switch (RMode) {
1734 case ReorderingMode::Load:
1735 case ReorderingMode::Opcode: {
1736 bool LeftToRight = Lane > LastLane;
1737 Value *OpLeft = (LeftToRight) ? OpLastLane : Op;
1738 Value *OpRight = (LeftToRight) ? Op : OpLastLane;
1739 int Score = getLookAheadScore(OpLeft, OpRight, MainAltOps, Lane,
1740 OpIdx, Idx, IsUsed, UsedLanes);
1741 if (Score > static_cast<int>(BestOp.Score) ||
1742 (Score > 0 && Score == static_cast<int>(BestOp.Score) &&
1743 Idx == OpIdx)) {
1744 BestOp.Idx = Idx;
1745 BestOp.Score = Score;
1746 BestScoresPerLanes[std::make_pair(OpIdx, Lane)] = Score;
1747 }
1748 break;
1749 }
1750 case ReorderingMode::Constant:
1751 if (isa<Constant>(Op) ||
1752 (!BestOp.Score && L && L->isLoopInvariant(Op))) {
1753 BestOp.Idx = Idx;
1754 if (isa<Constant>(Op)) {
1756 BestScoresPerLanes[std::make_pair(OpIdx, Lane)] =
1758 }
1760 IsUsed = false;
1761 }
1762 break;
1763 case ReorderingMode::Splat:
1764 if (Op == OpLastLane || (!BestOp.Score && isa<Constant>(Op))) {
1765 IsUsed = Op == OpLastLane;
1766 if (Op == OpLastLane) {
1767 BestOp.Score = LookAheadHeuristics::ScoreSplat;
1768 BestScoresPerLanes[std::make_pair(OpIdx, Lane)] =
1770 }
1771 BestOp.Idx = Idx;
1772 }
1773 break;
1774 case ReorderingMode::Failed:
1775 llvm_unreachable("Not expected Failed reordering mode.");
1776 }
1777 }
1778
1779 if (BestOp.Idx) {
1780 getData(*BestOp.Idx, Lane).IsUsed = IsUsed;
1781 return BestOp.Idx;
1782 }
1783 // If we could not find a good match return std::nullopt.
1784 return std::nullopt;
1785 }
1786
1787 /// Helper for reorderOperandVecs.
1788 /// \returns the lane that we should start reordering from. This is the one
1789 /// which has the least number of operands that can freely move about or
1790 /// less profitable because it already has the most optimal set of operands.
1791 unsigned getBestLaneToStartReordering() const {
1792 unsigned Min = UINT_MAX;
1793 unsigned SameOpNumber = 0;
1794 // std::pair<unsigned, unsigned> is used to implement a simple voting
1795 // algorithm and choose the lane with the least number of operands that
1796 // can freely move about or less profitable because it already has the
1797 // most optimal set of operands. The first unsigned is a counter for
1798 // voting, the second unsigned is the counter of lanes with instructions
1799 // with same/alternate opcodes and same parent basic block.
1801 // Try to be closer to the original results, if we have multiple lanes
1802 // with same cost. If 2 lanes have the same cost, use the one with the
1803 // highest index.
1804 for (int I = getNumLanes(); I > 0; --I) {
1805 unsigned Lane = I - 1;
1806 OperandsOrderData NumFreeOpsHash =
1807 getMaxNumOperandsThatCanBeReordered(Lane);
1808 // Compare the number of operands that can move and choose the one with
1809 // the least number.
1810 if (NumFreeOpsHash.NumOfAPOs < Min) {
1811 Min = NumFreeOpsHash.NumOfAPOs;
1812 SameOpNumber = NumFreeOpsHash.NumOpsWithSameOpcodeParent;
1813 HashMap.clear();
1814 HashMap[NumFreeOpsHash.Hash] = std::make_pair(1, Lane);
1815 } else if (NumFreeOpsHash.NumOfAPOs == Min &&
1816 NumFreeOpsHash.NumOpsWithSameOpcodeParent < SameOpNumber) {
1817 // Select the most optimal lane in terms of number of operands that
1818 // should be moved around.
1819 SameOpNumber = NumFreeOpsHash.NumOpsWithSameOpcodeParent;
1820 HashMap[NumFreeOpsHash.Hash] = std::make_pair(1, Lane);
1821 } else if (NumFreeOpsHash.NumOfAPOs == Min &&
1822 NumFreeOpsHash.NumOpsWithSameOpcodeParent == SameOpNumber) {
1823 auto [It, Inserted] =
1824 HashMap.try_emplace(NumFreeOpsHash.Hash, 1, Lane);
1825 if (!Inserted)
1826 ++It->second.first;
1827 }
1828 }
1829 // Select the lane with the minimum counter.
1830 unsigned BestLane = 0;
1831 unsigned CntMin = UINT_MAX;
1832 for (const auto &Data : reverse(HashMap)) {
1833 if (Data.second.first < CntMin) {
1834 CntMin = Data.second.first;
1835 BestLane = Data.second.second;
1836 }
1837 }
1838 return BestLane;
1839 }
1840
1841 /// Data structure that helps to reorder operands.
1842 struct OperandsOrderData {
1843 /// The best number of operands with the same APOs, which can be
1844 /// reordered.
1845 unsigned NumOfAPOs = UINT_MAX;
1846 /// Number of operands with the same/alternate instruction opcode and
1847 /// parent.
1848 unsigned NumOpsWithSameOpcodeParent = 0;
1849 /// Hash for the actual operands ordering.
1850 /// Used to count operands, actually their position id and opcode
1851 /// value. It is used in the voting mechanism to find the lane with the
1852 /// least number of operands that can freely move about or less profitable
1853 /// because it already has the most optimal set of operands. Can be
1854 /// replaced with SmallVector<unsigned> instead but hash code is faster
1855 /// and requires less memory.
1856 unsigned Hash = 0;
1857 };
1858 /// \returns the maximum number of operands that are allowed to be reordered
1859 /// for \p Lane and the number of compatible instructions(with the same
1860 /// parent/opcode). This is used as a heuristic for selecting the first lane
1861 /// to start operand reordering.
1862 OperandsOrderData getMaxNumOperandsThatCanBeReordered(unsigned Lane) const {
1863 unsigned CntTrue = 0;
1864 unsigned NumOperands = getNumOperands();
1865 // Operands with the same APO can be reordered. We therefore need to count
1866 // how many of them we have for each APO, like this: Cnt[APO] = x.
1867 // Since we only have two APOs, namely true and false, we can avoid using
1868 // a map. Instead we can simply count the number of operands that
1869 // correspond to one of them (in this case the 'true' APO), and calculate
1870 // the other by subtracting it from the total number of operands.
1871 // Operands with the same instruction opcode and parent are more
1872 // profitable since we don't need to move them in many cases, with a high
1873 // probability such lane already can be vectorized effectively.
1874 bool AllUndefs = true;
1875 unsigned NumOpsWithSameOpcodeParent = 0;
1876 Instruction *OpcodeI = nullptr;
1877 BasicBlock *Parent = nullptr;
1878 unsigned Hash = 0;
1879 for (unsigned OpIdx = 0; OpIdx != NumOperands; ++OpIdx) {
1880 const OperandData &OpData = getData(OpIdx, Lane);
1881 if (OpData.APO)
1882 ++CntTrue;
1883 // Use Boyer-Moore majority voting for finding the majority opcode and
1884 // the number of times it occurs.
1885 if (auto *I = dyn_cast<Instruction>(OpData.V)) {
1886 if (!OpcodeI || !getSameOpcode({OpcodeI, I}, TLI) ||
1887 I->getParent() != Parent) {
1888 if (NumOpsWithSameOpcodeParent == 0) {
1889 NumOpsWithSameOpcodeParent = 1;
1890 OpcodeI = I;
1891 Parent = I->getParent();
1892 } else {
1893 --NumOpsWithSameOpcodeParent;
1894 }
1895 } else {
1896 ++NumOpsWithSameOpcodeParent;
1897 }
1898 }
1899 Hash = hash_combine(
1900 Hash, hash_value((OpIdx + 1) * (OpData.V->getValueID() + 1)));
1901 AllUndefs = AllUndefs && isa<UndefValue>(OpData.V);
1902 }
1903 if (AllUndefs)
1904 return {};
1905 OperandsOrderData Data;
1906 Data.NumOfAPOs = std::max(CntTrue, NumOperands - CntTrue);
1907 Data.NumOpsWithSameOpcodeParent = NumOpsWithSameOpcodeParent;
1908 Data.Hash = Hash;
1909 return Data;
1910 }
1911
1912 /// Go through the instructions in VL and append their operands.
1913 void appendOperands(ArrayRef<Value *> VL, ArrayRef<ValueList> Operands,
1914 const InstructionsState &S) {
1915 assert(!Operands.empty() && !VL.empty() && "Bad list of operands");
1916 assert((empty() || all_of(Operands,
1917 [this](const ValueList &VL) {
1918 return VL.size() == getNumLanes();
1919 })) &&
1920 "Expected same number of lanes");
1921 assert(S.valid() && "InstructionsState is invalid.");
1922 // IntrinsicInst::isCommutative returns true if swapping the first "two"
1923 // arguments to the intrinsic produces the same result.
1924 Instruction *MainOp = S.getMainOp();
1925 ArgSize = getNumberOfPotentiallyCommutativeOps(MainOp);
1926 OpsVec.resize(ArgSize);
1927 unsigned NumLanes = VL.size();
1928 for (OperandDataVec &Ops : OpsVec)
1929 Ops.resize(NumLanes);
1930 for (unsigned Lane : seq<unsigned>(NumLanes)) {
1931 // Our tree has just 3 nodes: the root and two operands.
1932 // It is therefore trivial to get the APO. We only need to check the
1933 // opcode of V and whether the operand at OpIdx is the LHS or RHS
1934 // operand. The LHS operand of both add and sub is never attached to an
1935 // inversese operation in the linearized form, therefore its APO is
1936 // false. The RHS is true only if V is an inverse operation.
1937
1938 // Since operand reordering is performed on groups of commutative
1939 // operations or alternating sequences (e.g., +, -), we can safely tell
1940 // the inverse operations by checking commutativity.
1941 auto *I = dyn_cast<Instruction>(VL[Lane]);
1942 if (!I && isa<PoisonValue>(VL[Lane])) {
1943 for (unsigned OpIdx : seq<unsigned>(ArgSize))
1944 OpsVec[OpIdx][Lane] = {Operands[OpIdx][Lane], true, false};
1945 continue;
1946 }
1947 bool IsInverseOperation = false;
1948 if (S.isCopyableElement(VL[Lane])) {
1949 // The value is a copyable element.
1950 IsInverseOperation =
1951 !isCommutative(MainOp, VL[Lane], /*IsCopyable=*/true);
1952 } else {
1953 assert(I && "Expected instruction");
1954 auto [SelectedOp, Ops] = convertTo(I, S);
1955 // We cannot check commutativity by the converted instruction
1956 // (SelectedOp) because isCommutative also examines def-use
1957 // relationships.
1958 IsInverseOperation = !isCommutative(SelectedOp, I);
1959 }
1960 for (unsigned OpIdx : seq<unsigned>(ArgSize)) {
1961 bool APO = (OpIdx == 0) ? false : IsInverseOperation;
1962 OpsVec[OpIdx][Lane] = {Operands[OpIdx][Lane], APO, false};
1963 }
1964 }
1965 }
1966
1967 /// \returns the number of operands.
1968 unsigned getNumOperands() const { return ArgSize; }
1969
1970 /// \returns the number of lanes.
1971 unsigned getNumLanes() const { return OpsVec[0].size(); }
1972
1973 /// \returns the operand value at \p OpIdx and \p Lane.
1974 Value *getValue(unsigned OpIdx, unsigned Lane) const {
1975 return getData(OpIdx, Lane).V;
1976 }
1977
1978 /// \returns true if the data structure is empty.
1979 bool empty() const { return OpsVec.empty(); }
1980
1981 /// Clears the data.
1982 void clear() { OpsVec.clear(); }
1983
1984 /// \Returns true if there are enough operands identical to \p Op to fill
1985 /// the whole vector (it is mixed with constants or loop invariant values).
1986 /// Note: This modifies the 'IsUsed' flag, so a cleanUsed() must follow.
1987 bool shouldBroadcast(Value *Op, unsigned OpIdx, unsigned Lane) {
1988 assert(Op == getValue(OpIdx, Lane) &&
1989 "Op is expected to be getValue(OpIdx, Lane).");
1990 // Small number of loads - try load matching.
1991 if (isa<LoadInst>(Op) && getNumLanes() == 2 && getNumOperands() == 2)
1992 return false;
1993 bool OpAPO = getData(OpIdx, Lane).APO;
1994 bool IsInvariant = L && L->isLoopInvariant(Op);
1995 unsigned Cnt = 0;
1996 for (unsigned Ln = 0, Lns = getNumLanes(); Ln != Lns; ++Ln) {
1997 if (Ln == Lane)
1998 continue;
1999 // This is set to true if we found a candidate for broadcast at Lane.
2000 bool FoundCandidate = false;
2001 for (unsigned OpI = 0, OpE = getNumOperands(); OpI != OpE; ++OpI) {
2002 OperandData &Data = getData(OpI, Ln);
2003 if (Data.APO != OpAPO || Data.IsUsed)
2004 continue;
2005 Value *OpILane = getValue(OpI, Lane);
2006 bool IsConstantOp = isa<Constant>(OpILane);
2007 // Consider the broadcast candidate if:
2008 // 1. Same value is found in one of the operands.
2009 if (Data.V == Op ||
2010 // 2. The operand in the given lane is not constant but there is a
2011 // constant operand in another lane (which can be moved to the
2012 // given lane). In this case we can represent it as a simple
2013 // permutation of constant and broadcast.
2014 (!IsConstantOp &&
2015 ((Lns > 2 && isa<Constant>(Data.V)) ||
2016 // 2.1. If we have only 2 lanes, need to check that value in the
2017 // next lane does not build same opcode sequence.
2018 (Lns == 2 &&
2019 !getSameOpcode({Op, getValue((OpI + 1) % OpE, Ln)}, TLI) &&
2020 isa<Constant>(Data.V)))) ||
2021 // 3. The operand in the current lane is loop invariant (can be
2022 // hoisted out) and another operand is also a loop invariant
2023 // (though not a constant). In this case the whole vector can be
2024 // hoisted out.
2025 // FIXME: need to teach the cost model about this case for better
2026 // estimation.
2027 (IsInvariant && !isa<Constant>(Data.V) &&
2028 !getSameOpcode({Op, Data.V}, TLI) &&
2029 L->isLoopInvariant(Data.V))) {
2030 FoundCandidate = true;
2031 Data.IsUsed = Data.V == Op;
2032 if (Data.V == Op)
2033 ++Cnt;
2034 break;
2035 }
2036 }
2037 if (!FoundCandidate)
2038 return false;
2039 }
2040 return getNumLanes() == 2 || Cnt > 1;
2041 }
2042
2043 /// Checks if there is at least single compatible operand in lanes other
2044 /// than \p Lane, compatible with the operand \p Op.
2045 bool canBeVectorized(Instruction *Op, unsigned OpIdx, unsigned Lane) const {
2046 assert(Op == getValue(OpIdx, Lane) &&
2047 "Op is expected to be getValue(OpIdx, Lane).");
2048 bool OpAPO = getData(OpIdx, Lane).APO;
2049 for (unsigned Ln = 0, Lns = getNumLanes(); Ln != Lns; ++Ln) {
2050 if (Ln == Lane)
2051 continue;
2052 if (any_of(seq<unsigned>(getNumOperands()), [&](unsigned OpI) {
2053 const OperandData &Data = getData(OpI, Ln);
2054 if (Data.APO != OpAPO || Data.IsUsed)
2055 return true;
2056 Value *OpILn = getValue(OpI, Ln);
2057 return (L && L->isLoopInvariant(OpILn)) ||
2058 (getSameOpcode({Op, OpILn}, TLI) &&
2059 allSameBlock({Op, OpILn}));
2060 }))
2061 return true;
2062 }
2063 return false;
2064 }
2065
2066 public:
2067 /// Initialize with all the operands of the instruction vector \p RootVL.
2069 const InstructionsState &S, const BoUpSLP &R)
2070 : TLI(*R.TLI), DL(*R.DL), SE(*R.SE), R(R),
2071 L(R.LI->getLoopFor(S.getMainOp()->getParent())) {
2072 // Append all the operands of RootVL.
2073 appendOperands(RootVL, Operands, S);
2074 }
2075
2076 /// Initialize with flattened operand columns of an associative node.
2077 /// ArgSize is taken from \p Operands, APO is always false.
2079 const BoUpSLP &R)
2080 : TLI(*R.TLI), DL(*R.DL), SE(*R.SE), R(R), L(R.LI->getLoopFor(BB)) {
2081 assert(!Operands.empty() && "Expected at least one operand column");
2082 ArgSize = Operands.size();
2083 OpsVec.resize(ArgSize);
2084 unsigned NumLanes = Operands.front().size();
2085 for (auto [OpIdx, Ops] : enumerate(OpsVec)) {
2086 Ops.resize(NumLanes);
2087 for (unsigned Lane : seq<unsigned>(NumLanes))
2088 Ops[Lane] = OperandData(Operands[OpIdx][Lane], /*APO=*/false,
2089 /*IsUsed=*/false);
2090 }
2091 }
2092
2093 /// \Returns a value vector with the operands across all lanes for the
2094 /// opearnd at \p OpIdx.
2095 ValueList getVL(unsigned OpIdx) const {
2096 ValueList OpVL(OpsVec[OpIdx].size());
2097 assert(OpsVec[OpIdx].size() == getNumLanes() &&
2098 "Expected same num of lanes across all operands");
2099 for (unsigned Lane = 0, Lanes = getNumLanes(); Lane != Lanes; ++Lane)
2100 OpVL[Lane] = OpsVec[OpIdx][Lane].V;
2101 return OpVL;
2102 }
2103
2104 // Performs operand reordering for 2 or more operands.
2105 // The original operands are in OrigOps[OpIdx][Lane].
2106 // The reordered operands are returned in 'SortedOps[OpIdx][Lane]'.
2107 void reorder() {
2108 unsigned NumOperands = getNumOperands();
2109 unsigned NumLanes = getNumLanes();
2110 // Each operand has its own mode. We are using this mode to help us select
2111 // the instructions for each lane, so that they match best with the ones
2112 // we have selected so far.
2113 SmallVector<ReorderingMode, 2> ReorderingModes(NumOperands);
2114
2115 // This is a greedy single-pass algorithm. We are going over each lane
2116 // once and deciding on the best order right away with no back-tracking.
2117 // However, in order to increase its effectiveness, we start with the lane
2118 // that has operands that can move the least. For example, given the
2119 // following lanes:
2120 // Lane 0 : A[0] = B[0] + C[0] // Visited 3rd
2121 // Lane 1 : A[1] = C[1] - B[1] // Visited 1st
2122 // Lane 2 : A[2] = B[2] + C[2] // Visited 2nd
2123 // Lane 3 : A[3] = C[3] - B[3] // Visited 4th
2124 // we will start at Lane 1, since the operands of the subtraction cannot
2125 // be reordered. Then we will visit the rest of the lanes in a circular
2126 // fashion. That is, Lanes 2, then Lane 0, and finally Lane 3.
2127
2128 // Find the first lane that we will start our search from.
2129 unsigned FirstLane = getBestLaneToStartReordering();
2130
2131 // Initialize the modes.
2132 for (unsigned OpIdx = 0; OpIdx != NumOperands; ++OpIdx) {
2133 Value *OpLane0 = getValue(OpIdx, FirstLane);
2134 // Keep track if we have instructions with all the same opcode on one
2135 // side.
2136 if (auto *OpILane0 = dyn_cast<Instruction>(OpLane0)) {
2137 // Check if OpLane0 should be broadcast.
2138 if (shouldBroadcast(OpLane0, OpIdx, FirstLane) ||
2139 !canBeVectorized(OpILane0, OpIdx, FirstLane))
2140 ReorderingModes[OpIdx] = ReorderingMode::Splat;
2141 else if (isa<LoadInst>(OpILane0))
2142 ReorderingModes[OpIdx] = ReorderingMode::Load;
2143 else
2144 ReorderingModes[OpIdx] = ReorderingMode::Opcode;
2145 } else if (isa<Constant>(OpLane0)) {
2146 ReorderingModes[OpIdx] = ReorderingMode::Constant;
2147 } else if (isa<Argument>(OpLane0)) {
2148 // Our best hope is a Splat. It may save some cost in some cases.
2149 ReorderingModes[OpIdx] = ReorderingMode::Splat;
2150 } else {
2151 llvm_unreachable("Unexpected value kind.");
2152 }
2153 }
2154
2155 // Check that we don't have same operands. No need to reorder if operands
2156 // are just perfect diamond or shuffled diamond match. Do not do it only
2157 // for possible broadcasts.
2158 auto &&SkipReordering = [this]() {
2159 SmallPtrSet<Value *, 4> UniqueValues;
2160 ArrayRef<OperandData> Op0 = OpsVec.front();
2161 for (const OperandData &Data : Op0)
2162 UniqueValues.insert(Data.V);
2164 ArrayRef(OpsVec).slice(1, getNumOperands() - 1)) {
2165 if (any_of(Op, [&UniqueValues](const OperandData &Data) {
2166 return !UniqueValues.contains(Data.V);
2167 }))
2168 return false;
2169 }
2170 return UniqueValues.size() != 2;
2171 };
2172
2173 // If the initial strategy fails for any of the operand indexes, then we
2174 // perform reordering again in a second pass. This helps avoid assigning
2175 // high priority to the failed strategy, and should improve reordering for
2176 // the non-failed operand indexes.
2177 for (int Pass = 0; Pass != 2; ++Pass) {
2178 // Check if no need to reorder operands since they're are perfect or
2179 // shuffled diamond match.
2180 // Need to do it to avoid extra external use cost counting for
2181 // shuffled matches, which may cause regressions.
2182 if (SkipReordering())
2183 break;
2184 // Skip the second pass if the first pass did not fail.
2185 bool StrategyFailed = false;
2186 // Mark all operand data as free to use.
2187 clearUsed();
2188 // We keep the original operand order for the FirstLane, so reorder the
2189 // rest of the lanes. We are visiting the nodes in a circular fashion,
2190 // using FirstLane as the center point and increasing the radius
2191 // distance.
2192 SmallVector<SmallVector<Value *, 2>> MainAltOps(NumOperands);
2193 for (unsigned I = 0; I < NumOperands; ++I)
2194 MainAltOps[I].push_back(getData(I, FirstLane).V);
2195
2196 SmallBitVector UsedLanes(NumLanes);
2197 UsedLanes.set(FirstLane);
2198 for (unsigned Distance = 1; Distance != NumLanes; ++Distance) {
2199 // Visit the lane on the right and then the lane on the left.
2200 for (int Direction : {+1, -1}) {
2201 int Lane = FirstLane + Direction * Distance;
2202 if (Lane < 0 || Lane >= (int)NumLanes)
2203 continue;
2204 UsedLanes.set(Lane);
2205 int LastLane = Lane - Direction;
2206 assert(LastLane >= 0 && LastLane < (int)NumLanes &&
2207 "Out of bounds");
2208 // Look for a good match for each operand.
2209 for (unsigned OpIdx = 0; OpIdx != NumOperands; ++OpIdx) {
2210 // Search for the operand that matches SortedOps[OpIdx][Lane-1].
2211 std::optional<unsigned> BestIdx =
2212 getBestOperand(OpIdx, Lane, LastLane, ReorderingModes,
2213 MainAltOps[OpIdx], UsedLanes);
2214 // By not selecting a value, we allow the operands that follow to
2215 // select a better matching value. We will get a non-null value in
2216 // the next run of getBestOperand().
2217 if (BestIdx) {
2218 // Swap the current operand with the one returned by
2219 // getBestOperand().
2220 swap(OpIdx, *BestIdx, Lane);
2221 } else {
2222 // Enable the second pass.
2223 StrategyFailed = true;
2224 }
2225 // Try to get the alternate opcode and follow it during analysis.
2226 if (MainAltOps[OpIdx].size() != 2) {
2227 OperandData &AltOp = getData(OpIdx, Lane);
2228 InstructionsState OpS =
2229 getSameOpcode({MainAltOps[OpIdx].front(), AltOp.V}, TLI);
2230 if (OpS && OpS.isAltShuffle())
2231 MainAltOps[OpIdx].push_back(AltOp.V);
2232 }
2233 }
2234 }
2235 }
2236 // Skip second pass if the strategy did not fail.
2237 if (!StrategyFailed)
2238 break;
2239 }
2240 }
2241
2242#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
2243 LLVM_DUMP_METHOD static StringRef getModeStr(ReorderingMode RMode) {
2244 switch (RMode) {
2245 case ReorderingMode::Load:
2246 return "Load";
2247 case ReorderingMode::Opcode:
2248 return "Opcode";
2249 case ReorderingMode::Constant:
2250 return "Constant";
2251 case ReorderingMode::Splat:
2252 return "Splat";
2253 case ReorderingMode::Failed:
2254 return "Failed";
2255 }
2256 llvm_unreachable("Unimplemented Reordering Type");
2257 }
2258
2259 LLVM_DUMP_METHOD static raw_ostream &printMode(ReorderingMode RMode,
2260 raw_ostream &OS) {
2261 return OS << getModeStr(RMode);
2262 }
2263
2264 /// Debug print.
2265 LLVM_DUMP_METHOD static void dumpMode(ReorderingMode RMode) {
2266 printMode(RMode, dbgs());
2267 }
2268
2269 friend raw_ostream &operator<<(raw_ostream &OS, ReorderingMode RMode) {
2270 return printMode(RMode, OS);
2271 }
2272
2274 const unsigned Indent = 2;
2275 unsigned Cnt = 0;
2276 for (const OperandDataVec &OpDataVec : OpsVec) {
2277 OS << "Operand " << Cnt++ << "\n";
2278 for (const OperandData &OpData : OpDataVec) {
2279 OS.indent(Indent) << "{";
2280 if (Value *V = OpData.V)
2281 OS << *V;
2282 else
2283 OS << "null";
2284 OS << ", APO:" << OpData.APO << "}\n";
2285 }
2286 OS << "\n";
2287 }
2288 return OS;
2289 }
2290
2291 /// Debug print.
2292 LLVM_DUMP_METHOD void dump() const { print(dbgs()); }
2293#endif
2294 };
2295
2296 /// Evaluate each pair in \p Candidates and return index into \p Candidates
2297 /// for a pair which have highest score deemed to have best chance to form
2298 /// root of profitable tree to vectorize. Return std::nullopt if no candidate
2299 /// scored above the LookAheadHeuristics::ScoreFail. \param Limit Lower limit
2300 /// of the cost, considered to be good enough score.
2301 std::pair<std::optional<int>, int>
2302 findBestRootPair(ArrayRef<std::pair<Value *, Value *>> Candidates,
2303 int Limit = LookAheadHeuristics::ScoreFail) const {
2304 LookAheadHeuristics LookAhead(*TLI, *DL, *SE, *this, /*NumLanes=*/2,
2306 int BestScore = Limit;
2307 std::optional<int> Index;
2308 for (int I : seq<int>(0, Candidates.size())) {
2309 int Score = LookAhead.getScoreAtLevelRec(Candidates[I].first,
2310 Candidates[I].second,
2311 /*U1=*/nullptr, /*U2=*/nullptr,
2312 /*CurrLevel=*/1, {});
2313 if (Score > BestScore) {
2314 BestScore = Score;
2315 Index = I;
2316 }
2317 }
2318 return std::make_pair(Index, BestScore);
2319 }
2320
2321 /// Checks if the instruction is marked for deletion.
2322 bool isDeleted(Instruction *I) const { return DeletedInstructions.count(I); }
2323
2324 /// Checks if the value is used only by the assume-like intrinsics.
2325 bool isEphemeralValue(const Value *V) const { return EphValues.contains(V); }
2326
2327 /// Removes an instruction from its block and eventually deletes it.
2328 /// It's like Instruction::eraseFromParent() except that the actual deletion
2329 /// is delayed until BoUpSLP is destructed.
2331 DeletedInstructions.insert(I);
2332 }
2333
2334 /// Remove instructions from the parent function and clear the operands of \p
2335 /// DeadVals instructions, marking for deletion trivially dead operands.
2336 template <typename T>
2338 ArrayRef<T *> DeadVals,
2339 ArrayRef<std::tuple<WeakTrackingVH, unsigned, bool, bool>>
2340 VectorValuesAndScales) {
2342 for (T *V : DeadVals) {
2343 auto *I = cast<Instruction>(V);
2345 }
2346 DenseSet<Value *> Processed;
2347 for (T *V : DeadVals) {
2348 if (!V || !Processed.insert(V).second)
2349 continue;
2350 auto *I = cast<Instruction>(V);
2352 ArrayRef<TreeEntry *> Entries = getTreeEntries(I);
2353 for (Use &U : I->operands()) {
2354 if (auto *OpI = dyn_cast_if_present<Instruction>(U.get());
2355 OpI && !DeletedInstructions.contains(OpI) && OpI->hasOneUser() &&
2357 !ExternalUseReplacements.contains(OpI) &&
2358 (Entries.empty() || none_of(Entries, [&](const TreeEntry *Entry) {
2359 return Entry->VectorizedValue == OpI;
2360 })))
2361 DeadInsts.push_back(OpI);
2362 }
2363 I->dropAllReferences();
2364 }
2365 for (T *V : DeadVals) {
2366 auto *I = cast<Instruction>(V);
2367 if (!I->getParent())
2368 continue;
2369 assert((I->use_empty() || all_of(I->uses(),
2370 [&](Use &U) {
2371 return isDeleted(
2372 cast<Instruction>(U.getUser()));
2373 })) &&
2374 "trying to erase instruction with users.");
2375 I->removeFromParent();
2376 SE->forgetValue(I);
2377 }
2378 // Process the dead instruction list until empty.
2379 while (!DeadInsts.empty()) {
2380 Value *V = DeadInsts.pop_back_val();
2382 if (!VI || !VI->getParent())
2383 continue;
2385 "Live instruction found in dead worklist!");
2386 assert(VI->use_empty() && "Instructions with uses are not dead.");
2387
2388 // Don't lose the debug info while deleting the instructions.
2389 salvageDebugInfo(*VI);
2390
2391 // Null out all of the instruction's operands to see if any operand
2392 // becomes dead as we go.
2393 for (Use &OpU : VI->operands()) {
2394 Value *OpV = OpU.get();
2395 if (!OpV)
2396 continue;
2397 OpU.set(nullptr);
2398
2399 if (!OpV->use_empty())
2400 continue;
2401
2402 // If the operand is an instruction that became dead as we nulled out
2403 // the operand, and if it is 'trivially' dead, delete it in a future
2404 // loop iteration.
2405 if (auto *OpI = dyn_cast<Instruction>(OpV))
2406 if (!DeletedInstructions.contains(OpI) &&
2407 !ExternalUseReplacements.contains(OpI) &&
2408 (!OpI->getType()->isVectorTy() ||
2409 none_of(
2410 VectorValuesAndScales,
2411 [&](const std::tuple<WeakTrackingVH, unsigned, bool, bool>
2412 &V) { return std::get<0>(V) == OpI; })) &&
2414 DeadInsts.push_back(OpI);
2415 }
2416
2417 VI->removeFromParent();
2418 eraseInstruction(VI);
2419 SE->forgetValue(VI);
2420 }
2421 }
2422
2423 /// Checks if the instruction was already analyzed for being possible
2424 /// reduction root.
2426 return AnalyzedReductionsRoots.count(I);
2427 }
2428 /// Register given instruction as already analyzed for being possible
2429 /// reduction root.
2431 AnalyzedReductionsRoots.insert(I);
2432 }
2433 /// Checks if the provided list of reduced values was checked already for
2434 /// vectorization.
2436 return AnalyzedReductionVals.contains(hash_value(VL));
2437 }
2438 /// Adds the list of reduced values to list of already checked values for the
2439 /// vectorization.
2441 AnalyzedReductionVals.insert(hash_value(VL));
2442 }
2443 /// Checks if the value was already a part of the analyzed vector node.
2444 bool isAnalyzedScalar(const Value *V) const {
2445 return AnalyzedScalars.contains(V);
2446 }
2447 /// Checks if the given bundle was already rejected as non-vectorizable.
2449 return AnalyzedBundles.contains(hash_value(VL));
2450 }
2451 /// Registers the bundle as rejected for the vectorization.
2453 AnalyzedBundles.insert(hash_value(VL));
2454 }
2455 /// Clear the list of the analyzed reduction root instructions.
2457 AnalyzedReductionsRoots.clear();
2458 AnalyzedReductionVals.clear();
2459 AnalyzedBundles.clear();
2460 AnalyzedMinBWVals.clear();
2461 }
2462 /// Checks if the given value is gathered in one of the nodes.
2463 bool isAnyGathered(const SmallDenseSet<Value *> &Vals) const {
2464 return any_of(MustGather, [&](Value *V) { return Vals.contains(V); });
2465 }
2466 /// Checks if the given value is gathered in one of the nodes.
2467 bool isGathered(const Value *V) const {
2468 return MustGather.contains(V);
2469 }
2470 /// Checks if the specified value was not schedule.
2471 bool isNotScheduled(const Value *V) const {
2472 return NonScheduledFirst.contains(V);
2473 }
2474
2475 /// Check if \p V is a peeled reassociated scalar still owned by a live
2476 /// (non-deleted, non-gathered) tree entry.
2477 bool isReassocScalarVectorized(const Value *V) const {
2478 auto It = ReassocScalarToTreeEntries.find(V);
2479 return It != ReassocScalarToTreeEntries.end() &&
2480 any_of(It->second, [&](const TreeEntry *E) {
2481 return !DeletedNodes.contains(E) &&
2482 !TransformedToGatherNodes.contains(E);
2483 });
2484 }
2485
2486 /// Check if the value is vectorized in the tree.
2487 bool isVectorized(const Value *V) const {
2488 assert(V && "V cannot be nullptr.");
2490 return true;
2491 return any_of(getTreeEntries(V), [&](const TreeEntry *E) {
2492 return !DeletedNodes.contains(E) && !TransformedToGatherNodes.contains(E);
2493 });
2494 }
2495
2496 /// Returns true if the role of \p I is already decided by its user: a deleted
2497 /// user was folded into some other vector by an earlier attempt.
2499 return any_of(I->users(), [&](User *U) {
2500 auto *UI = dyn_cast<Instruction>(U);
2501 return UI && isDeleted(UI);
2502 });
2503 }
2504
2505 /// Checks if it is legal and profitable to build SplitVectorize node for the
2506 /// given \p VL.
2507 /// \param Op1 first homogeneous scalars.
2508 /// \param Op2 second homogeneous scalars.
2509 /// \param ReorderIndices indices to reorder the scalars.
2510 /// \returns true if the node was successfully built.
2512 const InstructionsState &LocalState,
2515 OrdersType &ReorderIndices) const;
2516
2517 ~BoUpSLP();
2518
2519private:
2520 /// Determine if a node \p E in can be demoted to a smaller type with a
2521 /// truncation. We collect the entries that will be demoted in ToDemote.
2522 /// \param E Node for analysis
2523 /// \param ToDemote indices of the nodes to be demoted.
2524 bool collectValuesToDemote(
2525 const TreeEntry &E, bool IsProfitableToDemoteRoot, unsigned &BitWidth,
2527 const SmallDenseSet<unsigned, 8> &NodesToKeepBWs, unsigned &MaxDepthLevel,
2528 bool &IsProfitableToDemote, bool IsTruncRoot) const;
2529
2530 /// Builds the list of reorderable operands on the edges \p Edges of the \p
2531 /// UserTE, which allow reordering (i.e. the operands can be reordered because
2532 /// they have only one user and reordarable).
2533 /// \param ReorderableGathers List of all gather nodes that require reordering
2534 /// (e.g., gather of extractlements or partially vectorizable loads).
2535 /// \param GatherOps List of gather operand nodes for \p UserTE that require
2536 /// reordering, subset of \p NonVectorized.
2537 void buildReorderableOperands(
2538 TreeEntry *UserTE,
2539 SmallVectorImpl<std::pair<unsigned, TreeEntry *>> &Edges,
2540 const SmallPtrSetImpl<const TreeEntry *> &ReorderableGathers,
2541 SmallVectorImpl<TreeEntry *> &GatherOps);
2542
2543 /// Checks if the given \p TE is a gather node with clustered reused scalars
2544 /// and reorders it per given \p Mask.
2545 void reorderNodeWithReuses(TreeEntry &TE, ArrayRef<int> Mask) const;
2546
2547 /// Checks if all users of \p I are the part of the vectorization tree.
2548 bool areAllUsersVectorized(
2549 Instruction *I,
2550 const SmallDenseSet<Value *> *VectorizedVals = nullptr) const;
2551
2552 /// Estimates the number of scalar instructions in the tree, each weighted by
2553 /// its loop-nest trip count (nest-invariant entries are dropped when
2554 /// \p TreeLoop is non-null).
2555 uint64_t getNumScalarInsts(bool HasTreeLoop);
2556
2557 /// Estimates the number of vector instructions (including buildvectors,
2558 /// shuffles, and extracts) the tree produces, weighted like
2559 /// getNumScalarInsts().
2560 uint64_t getNumVectorInsts(bool HasTreeLoop);
2561
2562 /// Return information about the vector formed for the specified index
2563 /// of a vector of (the same) instruction.
2566
2567 /// \returns the graph entry for the \p Idx operand of the \p E entry.
2568 const TreeEntry *getOperandEntry(const TreeEntry *E, unsigned Idx) const;
2569 TreeEntry *getOperandEntry(TreeEntry *E, unsigned Idx) {
2570 return const_cast<TreeEntry *>(
2571 getOperandEntry(const_cast<const TreeEntry *>(E), Idx));
2572 }
2573
2574 /// Gets the root instruction for the given node. If the node is a strided
2575 /// load/store node with the reverse order, the root instruction is the last
2576 /// one.
2577 Instruction *getRootEntryInstruction(const TreeEntry &Entry) const;
2578
2579 /// \returns Cast context for the given graph node.
2581 getCastContextHint(const TreeEntry &TE) const;
2582
2583 /// \returns the scale of the given tree entry to the loop iteration.
2584 /// \p Scalar is the scalar value from the entry, if using the parent for the
2585 /// external use.
2586 /// \p U is the user of the vectorized value from the entry, if using the
2587 /// parent for the external use.
2588 uint64_t getScaleToLoopIterations(const TreeEntry &TE,
2589 Value *Scalar = nullptr,
2590 Instruction *U = nullptr);
2591
2592 /// \returns the product of trip counts of the loop \p L and all of its
2593 /// enclosing loops. Unlike the state kept by getScaleToLoopIterations(),
2594 /// this helper depends only on the loop structure and is independent of
2595 /// per-entry operand invariance. Returns 1 when loop-aware cost modeling
2596 /// is disabled or \p L is null.
2597 uint64_t getLoopNestScale(const Loop *L);
2598
2599 /// \returns a refined execution scale for a gather/buildvector tree entry
2600 /// \p TE. The scale is computed as the average of per-lane execution
2601 /// scales: each lane's scale is the loop-nest scale of the loop that
2602 /// contains the lane's defining instruction (or 1 if the lane is a
2603 /// constant / loop-invariant non-instruction value). This models the
2604 /// LICM hoisting that optimizeGatherSequence() performs after vectorization
2605 /// for inserts with loop-invariant operands. Falls back to the whole-entry
2606 /// scale when per-lane information is unavailable or the feature is off.
2607 uint64_t getGatherNodeEffectiveScale(const TreeEntry &TE,
2608 Instruction *U = nullptr);
2609
2610 /// \returns the loop-nest execution scale of \p TE.
2611 uint64_t getEntryEffectiveScale(const TreeEntry &TE,
2612 Instruction *U = nullptr);
2613
2614 /// Get the loop nest for the given loop \p L.
2615 ArrayRef<const Loop *> getLoopNest(const Loop *L);
2616
2617 /// \returns the cost of the vectorizable entry.
2618 InstructionCost getEntryCost(const TreeEntry *E,
2619 ArrayRef<Value *> VectorizedVals,
2620 SmallPtrSetImpl<Value *> &CheckedExtracts);
2621
2622 /// Estimates spill/reload cost from vector register pressure for \p E at the
2623 /// point of emitting its vector result type \p FinalVecTy. \p ScalarTy is the
2624 /// scalar/slot type used to widen into \p VecTy/\p FinalVecTy and may itself
2625 /// be a FixedVectorType in ReVec mode or an adjusted type due to MinBWs.
2627 getVectorSpillReloadCost(const TreeEntry *E, Type *ScalarTy, Type *VecTy,
2628 Type *FinalVecTy,
2629 const TTI::TargetCostKind CostKind) const;
2630
2631 /// This is the recursive part of buildTree.
2632 void buildTreeRec(ArrayRef<Value *> Roots, unsigned Depth, const EdgeInfo &EI,
2633 unsigned InterleaveFactor = 0);
2634
2635 /// \returns true if the ExtractElement/ExtractValue instructions in \p VL can
2636 /// be vectorized to use the original vector (or aggregate "bitcast" to a
2637 /// vector) and sets \p CurrentOrder to the identity permutation; otherwise
2638 /// returns false, setting \p CurrentOrder to either an empty vector or a
2639 /// non-identity permutation that allows to reuse extract instructions.
2640 /// \param ResizeAllowed indicates whether it is allowed to handle subvector
2641 /// extract order.
2642 bool canReuseExtract(ArrayRef<Value *> VL,
2643 SmallVectorImpl<unsigned> &CurrentOrder,
2644 bool ResizeAllowed = false) const;
2645
2646 /// Vectorize a single entry in the tree.
2647 Value *vectorizeTree(TreeEntry *E);
2648
2649 /// Vectorize a single entry in the tree, the \p Idx-th operand of the entry
2650 /// \p E.
2651 Value *vectorizeOperand(TreeEntry *E, unsigned NodeIdx);
2652
2653 /// Create a new vector from a list of scalar values. Produces a sequence
2654 /// which exploits values reused across lanes, and arranges the inserts
2655 /// for ease of later optimization.
2656 template <typename BVTy, typename ResTy, typename... Args>
2657 ResTy processBuildVector(const TreeEntry *E, Type *ScalarTy, Args &...Params);
2658
2659 /// Create a new vector from a list of scalar values. Produces a sequence
2660 /// which exploits values reused across lanes, and arranges the inserts
2661 /// for ease of later optimization.
2662 Value *createBuildVector(const TreeEntry *E, Type *ScalarTy);
2663
2664 /// Returns the instruction in the bundle, which can be used as a base point
2665 /// for scheduling. Usually it is the last instruction in the bundle, except
2666 /// for the case when all operands are external (in this case, it is the first
2667 /// instruction in the list).
2668 Instruction &getLastInstructionInBundle(const TreeEntry *E);
2669
2670 /// Tries to find extractelement instructions with constant indices from fixed
2671 /// vector type and gather such instructions into a bunch, which highly likely
2672 /// might be detected as a shuffle of 1 or 2 input vectors. If this attempt
2673 /// was successful, the matched scalars are replaced by poison values in \p VL
2674 /// for future analysis.
2675 std::optional<TargetTransformInfo::ShuffleKind>
2676 tryToGatherSingleRegisterExtractElements(MutableArrayRef<Value *> VL,
2677 SmallVectorImpl<int> &Mask) const;
2678
2679 /// Tries to find extractelement instructions with constant indices from fixed
2680 /// vector type and gather such instructions into a bunch, which highly likely
2681 /// might be detected as a shuffle of 1 or 2 input vectors. If this attempt
2682 /// was successful, the matched scalars are replaced by poison values in \p VL
2683 /// for future analysis.
2685 tryToGatherExtractElements(SmallVectorImpl<Value *> &VL,
2687 unsigned NumParts) const;
2688
2689 /// Checks if the gathered \p VL can be represented as a single register
2690 /// shuffle(s) of previous tree entries.
2691 /// \param TE Tree entry checked for permutation.
2692 /// \param VL List of scalars (a subset of the TE scalar), checked for
2693 /// permutations. Must form single-register vector.
2694 /// \param ForOrder Tries to fetch the best candidates for ordering info. Also
2695 /// commands to build the mask using the original vector value, without
2696 /// relying on the potential reordering.
2697 /// \returns ShuffleKind, if gathered values can be represented as shuffles of
2698 /// previous tree entries. \p Part of \p Mask is filled with the shuffle mask.
2699 std::optional<TargetTransformInfo::ShuffleKind>
2700 isGatherShuffledSingleRegisterEntry(
2701 const TreeEntry *TE, ArrayRef<Value *> VL, MutableArrayRef<int> Mask,
2702 SmallVectorImpl<const TreeEntry *> &Entries, unsigned Part, bool ForOrder,
2703 unsigned SliceSize);
2704
2705 /// Checks if the gathered \p VL can be represented as multi-register
2706 /// shuffle(s) of previous tree entries.
2707 /// \param TE Tree entry checked for permutation.
2708 /// \param VL List of scalars (a subset of the TE scalar), checked for
2709 /// permutations.
2710 /// \param ForOrder Tries to fetch the best candidates for ordering info. Also
2711 /// commands to build the mask using the original vector value, without
2712 /// relying on the potential reordering.
2713 /// \returns per-register series of ShuffleKind, if gathered values can be
2714 /// represented as shuffles of previous tree entries. \p Mask is filled with
2715 /// the shuffle mask (also on per-register base).
2717 isGatherShuffledEntry(
2718 const TreeEntry *TE, ArrayRef<Value *> VL, SmallVectorImpl<int> &Mask,
2720 unsigned NumParts, bool ForOrder = false);
2721
2722 /// \returns the cost of gathering (inserting) the values in \p VL into a
2723 /// vector.
2724 /// \param ForPoisonSrc true if initial vector is poison, false otherwise.
2725 InstructionCost getGatherCost(ArrayRef<Value *> VL, bool ForPoisonSrc,
2726 Type *ScalarTy) const;
2727
2728 /// Set the Builder insert point to one after the last instruction in
2729 /// the bundle
2730 void setInsertPointAfterBundle(const TreeEntry *E);
2731
2732 /// \returns a vector from a collection of scalars in \p VL. if \p Root is not
2733 /// specified, the starting vector value is poison.
2734 Value *
2735 gather(ArrayRef<Value *> VL, Value *Root, Type *ScalarTy,
2736 function_ref<Value *(Value *, Value *, ArrayRef<int>)> CreateShuffle);
2737
2738 /// \returns whether the VectorizableTree is fully vectorizable and will
2739 /// be beneficial even the tree height is tiny.
2740 bool isFullyVectorizableTinyTree(bool ForReduction) const;
2741
2742 /// Run through the list of all gathered loads in the graph and try to find
2743 /// vector loads/masked gathers instead of regular gathers. Later these loads
2744 /// are reshufled to build final gathered nodes.
2745 void tryToVectorizeGatheredLoads(
2746 const SmallMapVector<
2747 std::tuple<BasicBlock *, Value *, Type *>,
2748 SmallVector<SmallVector<std::pair<LoadInst *, int64_t>>>, 8>
2749 &GatheredLoads);
2750
2751 /// Run through the gather nodes that are splats of the same instruction and
2752 /// try to vectorize the unique splatted values together as a separate
2753 /// subtree. The splat gathers are then emitted as broadcasts of the
2754 /// vectorized subtree instead of insertion sequences.
2755 void tryToVectorizeSplatGatheredScalars();
2756
2757 /// Helper for `findExternalStoreUsersReorderIndices()`. It iterates over the
2758 /// users of \p TE and collects the stores. It returns the map from the store
2759 /// pointers to the collected stores.
2761 collectUserStores(const BoUpSLP::TreeEntry *TE) const;
2762
2763 /// Helper for `findExternalStoreUsersReorderIndices()`. It checks if the
2764 /// stores in \p StoresVec can form a vector instruction. If so it returns
2765 /// true and populates \p ReorderIndices with the shuffle indices of the
2766 /// stores when compared to the sorted vector.
2767 bool canFormVector(ArrayRef<StoreInst *> StoresVec,
2768 OrdersType &ReorderIndices) const;
2769
2770 /// Iterates through the users of \p TE, looking for scalar stores that can be
2771 /// potentially vectorized in a future SLP-tree. If found, it keeps track of
2772 /// their order and builds an order index vector for each store bundle. It
2773 /// returns all these order vectors found.
2774 /// We run this after the tree has formed, otherwise we may come across user
2775 /// instructions that are not yet in the tree.
2777 findExternalStoreUsersReorderIndices(TreeEntry *TE) const;
2778
2779 /// Tries to reorder the gathering node for better vectorization
2780 /// opportunities.
2781 void reorderGatherNode(TreeEntry &TE);
2782
2783 /// Checks if the tree represents disjoint or reduction of shl(zext, (0, 8,
2784 /// .., 56))-like pattern.
2785 /// If the int shifts unique, also strided, but not ordered, sets \p Order.
2786 /// If the node can be represented as a bitcast + bswap, sets \p IsBSwap.
2787 /// If the root nodes are loads, sets \p ForLoads to true.
2788 bool matchesShlZExt(const TreeEntry &TE, OrdersType &Order, bool &IsBSwap,
2789 bool &ForLoads) const;
2790
2791 /// Checks if the \p SelectTE matches zext+selects, which can be inversed for
2792 /// better codegen in case like zext (icmp ne), select (icmp eq), ....
2793 bool matchesInversedZExtSelect(
2794 const TreeEntry &SelectTE,
2795 SmallVectorImpl<unsigned> &InversedCmpsIndices) const;
2796
2797 /// Checks if the tree is reduction or of bit selects, like select %cmp, <1,
2798 /// 2, 4, 8, ..>, zeroinitializer, which can be reduced just to a bitcast %cmp
2799 /// to in.
2800 bool matchesSelectOfBits(const TreeEntry &SelectTE) const;
2801
2802 class TreeEntry {
2803 public:
2804 using VecTreeTy = SmallVector<std::unique_ptr<TreeEntry>, 8>;
2805 TreeEntry(VecTreeTy &Container) : Container(Container) {}
2806
2807 /// \returns Common mask for reorder indices and reused scalars.
2808 SmallVector<int> getCommonMask() const {
2809 if (State == TreeEntry::SplitVectorize)
2810 return {};
2811 SmallVector<int> Mask;
2812 inversePermutation(ReorderIndices, Mask);
2813 addMask(Mask, ReuseShuffleIndices);
2814 return Mask;
2815 }
2816
2817 /// \returns The mask for split nodes.
2818 SmallVector<int> getSplitMask() const {
2819 assert(State == TreeEntry::SplitVectorize && !ReorderIndices.empty() &&
2820 "Expected only split vectorize node.");
2821 unsigned CommonVF = std::max<unsigned>(
2822 CombinedEntriesWithIndices.back().second,
2823 Scalars.size() - CombinedEntriesWithIndices.back().second);
2824 const unsigned Scale = getNumElements(Scalars.front()->getType());
2825 CommonVF *= Scale;
2826 SmallVector<int> Mask(getVectorFactor() * Scale, PoisonMaskElem);
2827 for (auto [Idx, I] : enumerate(ReorderIndices)) {
2828 for (unsigned K : seq<unsigned>(Scale)) {
2829 Mask[Scale * I + K] =
2830 Scale * Idx + K +
2831 (Idx >= CombinedEntriesWithIndices.back().second
2832 ? CommonVF - CombinedEntriesWithIndices.back().second * Scale
2833 : 0);
2834 }
2835 }
2836 return Mask;
2837 }
2838
2839 /// Updates (reorders) SplitVectorize node according to the given mask \p
2840 /// Mask and order \p MaskOrder.
2841 void reorderSplitNode(unsigned Idx, ArrayRef<int> Mask,
2842 ArrayRef<int> MaskOrder);
2843
2844 /// \returns true if the scalars in VL are equal to this entry.
2845 bool isSame(ArrayRef<Value *> VL) const {
2846 auto &&IsSame = [VL](ArrayRef<Value *> Scalars, ArrayRef<int> Mask) {
2847 if (Mask.size() != VL.size() && VL.size() == Scalars.size())
2848 return std::equal(VL.begin(), VL.end(), Scalars.begin());
2849 return VL.size() == Mask.size() &&
2850 std::equal(VL.begin(), VL.end(), Mask.begin(),
2851 [Scalars](Value *V, int Idx) {
2852 return isa<PoisonValue>(V) ||
2853 (Idx != PoisonMaskElem && V == Scalars[Idx]);
2854 });
2855 };
2856 if (!ReorderIndices.empty()) {
2857 // TODO: implement matching if the nodes are just reordered, still can
2858 // treat the vector as the same if the list of scalars matches VL
2859 // directly, without reordering.
2860 SmallVector<int> Mask;
2861 inversePermutation(ReorderIndices, Mask);
2862 if (VL.size() == Scalars.size())
2863 return IsSame(Scalars, Mask);
2864 if (VL.size() == ReuseShuffleIndices.size()) {
2865 addMask(Mask, ReuseShuffleIndices);
2866 return IsSame(Scalars, Mask);
2867 }
2868 return false;
2869 }
2870 return IsSame(Scalars, ReuseShuffleIndices);
2871 }
2872
2873 /// \returns true if current entry has same operands as \p TE.
2874 bool hasEqualOperands(const TreeEntry &TE) const {
2875 if (TE.getNumOperands() != getNumOperands())
2876 return false;
2877 SmallBitVector Used(getNumOperands());
2878 for (unsigned I = 0, E = getNumOperands(); I < E; ++I) {
2879 unsigned PrevCount = Used.count();
2880 for (unsigned K = 0; K < E; ++K) {
2881 if (Used.test(K))
2882 continue;
2883 if (getOperand(K) == TE.getOperand(I)) {
2884 Used.set(K);
2885 break;
2886 }
2887 }
2888 // Check if we actually found the matching operand.
2889 if (PrevCount == Used.count())
2890 return false;
2891 }
2892 return true;
2893 }
2894
2895 /// \return Final vectorization factor for the node. Defined by the total
2896 /// number of vectorized scalars, including those, used several times in the
2897 /// entry and counted in the \a ReuseShuffleIndices, if any.
2898 unsigned getVectorFactor() const {
2899 if (!ReuseShuffleIndices.empty())
2900 return ReuseShuffleIndices.size();
2901 return Scalars.size();
2902 };
2903
2904 /// Checks if the current node is a gather node.
2905 bool isGather() const { return State == NeedToGather; }
2906
2907 /// A vector of scalars.
2908 ValueList Scalars;
2909
2910 /// The Scalars are vectorized into this value. It is initialized to Null.
2911 WeakTrackingVH VectorizedValue = nullptr;
2912
2913 /// Do we need to gather this sequence or vectorize it
2914 /// (either with vector instruction or with scatter/gather
2915 /// intrinsics for store/load)?
2916 enum EntryState {
2917 Vectorize, ///< The node is regularly vectorized.
2918 ScatterVectorize, ///< Masked scatter/gather node.
2919 StridedVectorize, ///< Strided loads (and stores)
2920 ExpandVectorize, ///< Masked stores, the values are expanded into
2921 ///< a wider vector and vectorized with a mask.
2922 CompressVectorize, ///< (Masked) load with compress.
2923 BlendedLoadVectorize, ///< (Masked) loads blended via `select` from two
2924 ///< candidate base pointers.
2925 NeedToGather, ///< Gather/buildvector node.
2926 CombinedVectorize, ///< Vectorized node, combined with its user into more
2927 ///< complex node like select/cmp to minmax, mul/add to
2928 ///< fma, etc. Must be used for the following nodes in
2929 ///< the pattern, not the very first one.
2930 SplitVectorize, ///< Splits the node into 2 subnodes, vectorizes them
2931 ///< independently and then combines back.
2932 };
2933 EntryState State;
2934
2935 /// List of combined opcodes supported by the vectorizer.
2936 enum CombinedOpcode {
2937 NotCombinedOp = -1,
2938 MinMax = Instruction::OtherOpsEnd + 1,
2939 FMulAdd,
2940 ReducedBitcast,
2941 ReducedBitcastBSwap,
2942 ReducedBitcastLoads,
2943 ReducedBitcastBSwapLoads,
2944 ReducedCmpBitcast,
2945 };
2946 CombinedOpcode CombinedOp = NotCombinedOp;
2947
2948 /// Does this sequence require some shuffling?
2949 SmallVector<int, 4> ReuseShuffleIndices;
2950
2951 /// Does this entry require reordering?
2952 SmallVector<unsigned, 4> ReorderIndices;
2953
2954 /// Points back to the VectorizableTree.
2955 ///
2956 /// Only used for Graphviz right now. Unfortunately GraphTrait::NodeRef has
2957 /// to be a pointer and needs to be able to initialize the child iterator.
2958 /// Thus we need a reference back to the container to translate the indices
2959 /// to entries.
2960 VecTreeTy &Container;
2961
2962 /// The TreeEntry index containing the user of this entry.
2963 EdgeInfo UserTreeIndex;
2964
2965 /// The index of this treeEntry in VectorizableTree.
2966 unsigned Idx = 0;
2967
2968 /// For gather/buildvector/alt opcode nodes, which are combined from
2969 /// other nodes as a series of insertvector instructions.
2970 SmallVector<std::pair<unsigned, unsigned>, 2> CombinedEntriesWithIndices;
2971
2972 /// For ExtractValue entries that are vectorized via the struct-call path
2973 /// (checkEVsForVecCalls succeeded during tree building), stores the common
2974 /// field-index path shared by all scalars in the bundle. Empty for all
2975 /// other entry kinds.
2976 SmallVector<unsigned, 1> StructEVIndices;
2977
2978 private:
2979 /// The operands of each instruction in each lane Operands[op_index][lane].
2980 /// Note: This helps avoid the replication of the code that performs the
2981 /// reordering of operands during buildTreeRec() and vectorizeTree().
2982 SmallVector<ValueList, 2> Operands;
2983
2984 /// Copyable elements of the entry node.
2985 SmallPtrSet<const Value *, 4> CopyableElements;
2986
2987 /// Intermediate instructions peeled from an associative chain (e.g. the
2988 /// inner add in add(add(v0,x),v1)). Not part of Scalars.
2989 SmallVector<Value *, 4> ReassocScalars;
2990
2991 /// Sign of each flattened operand column of a reassociated add/sub
2992 /// chain, parallel to the operand columns: a negated column is
2993 /// subtracted from the positive total. Empty when no column is negated.
2994 SmallBitVector ReassocNegatedOps;
2995
2996 /// MainOp and AltOp are recorded inside. S should be obtained from
2997 /// newTreeEntry.
2998 InstructionsState S = InstructionsState::invalid();
2999
3000 /// Interleaving factor for interleaved loads Vectorize nodes.
3001 unsigned InterleaveFactor = 0;
3002
3003 /// True if the node does not require scheduling.
3004 bool DoesNotNeedToSchedule = false;
3005
3006 /// Set this bundle's \p OpIdx'th operand to \p OpVL.
3007 void setOperand(unsigned OpIdx, ArrayRef<Value *> OpVL) {
3008 if (Operands.size() < OpIdx + 1)
3009 Operands.resize(OpIdx + 1);
3010 assert(Operands[OpIdx].empty() && "Already resized?");
3011 assert(OpVL.size() <= Scalars.size() &&
3012 "Number of operands is greater than the number of scalars.");
3013 Operands[OpIdx].resize(OpVL.size());
3014 copy(OpVL, Operands[OpIdx].begin());
3015 }
3016
3017 /// Maps values to their lanes in the node.
3018 mutable SmallDenseMap<Value *, unsigned> ValueToLane;
3019
3020 public:
3021 /// Returns interleave factor for interleave nodes.
3022 unsigned getInterleaveFactor() const { return InterleaveFactor; }
3023 /// Sets interleaving factor for the interleaving nodes.
3024 void setInterleave(unsigned Factor) { InterleaveFactor = Factor; }
3025
3026 /// Marks the node as one that does not require scheduling.
3027 void setDoesNotNeedToSchedule() { DoesNotNeedToSchedule = true; }
3028 /// Returns true if the node is marked as one that does not require
3029 /// scheduling.
3030 bool doesNotNeedToSchedule() const { return DoesNotNeedToSchedule; }
3031
3032 /// Set this bundle's operands from \p Operands.
3033 void setOperands(ArrayRef<ValueList> Operands) {
3034 for (unsigned I : seq<unsigned>(Operands.size()))
3035 setOperand(I, Operands[I]);
3036 }
3037
3038 /// Reorders operands of the node to the given mask \p Mask.
3039 void reorderOperands(ArrayRef<int> Mask) {
3040 for (ValueList &Operand : Operands)
3041 reorderScalars(Operand, Mask);
3042 }
3043
3044 /// \returns the \p OpIdx operand of this TreeEntry.
3045 ValueList &getOperand(unsigned OpIdx) {
3046 assert(OpIdx < Operands.size() && "Off bounds");
3047 return Operands[OpIdx];
3048 }
3049
3050 /// \returns the \p OpIdx operand of this TreeEntry.
3051 ArrayRef<Value *> getOperand(unsigned OpIdx) const {
3052 assert(OpIdx < Operands.size() && "Off bounds");
3053 return Operands[OpIdx];
3054 }
3055
3056 /// \returns the number of operands.
3057 unsigned getNumOperands() const { return Operands.size(); }
3058
3059 /// \return the single \p OpIdx operand.
3060 Value *getSingleOperand(unsigned OpIdx) const {
3061 assert(OpIdx < Operands.size() && "Off bounds");
3062 assert(!Operands[OpIdx].empty() && "No operand available");
3063 return Operands[OpIdx][0];
3064 }
3065
3066 /// Some of the instructions in the list have alternate opcodes.
3067 bool isAltShuffle() const { return S.isAltShuffle(); }
3068
3069 Instruction *getMatchingMainOpOrAltOp(Instruction *I) const {
3070 return S.getMatchingMainOpOrAltOp(I);
3071 }
3072
3073 /// Chooses the correct key for scheduling data. If \p Op has the same (or
3074 /// alternate) opcode as \p OpValue, the key is \p Op. Otherwise the key is
3075 /// \p OpValue.
3076 Value *isOneOf(Value *Op) const {
3077 auto *I = dyn_cast<Instruction>(Op);
3078 if (I && getMatchingMainOpOrAltOp(I))
3079 return Op;
3080 return S.getMainOp();
3081 }
3082
3083 void setOperations(const InstructionsState &S) {
3084 assert(S && "InstructionsState is invalid.");
3085 this->S = S;
3086 }
3087
3088 Instruction *getMainOp() const { return S.getMainOp(); }
3089
3090 Instruction *getAltOp() const { return S.getAltOp(); }
3091
3092 /// The main/alternate opcodes for the list of instructions.
3093 unsigned getOpcode() const { return S.getOpcode(); }
3094
3095 unsigned getAltOpcode() const { return S.getAltOpcode(); }
3096
3097 bool hasState() const { return S.valid(); }
3098
3099 /// Add \p V to the list of copyable elements.
3100 void addCopyableElement(Value *V) {
3101 assert(S.isCopyableElement(V) && "Not a copyable element.");
3102 CopyableElements.insert(V);
3103 }
3104
3105 /// Returns true if \p V is a copyable element.
3106 bool isCopyableElement(Value *V) const {
3107 return CopyableElements.contains(V);
3108 }
3109
3110 /// Checks if the value \p V is a transformed instruction, compatible either
3111 /// with main or alternate ops.
3112 bool isExpandedBinOp(Value *V) const {
3113 assert(hasState() && "InstructionsState is invalid.");
3114 if (isCopyableElement(V))
3115 return false;
3116 return S.isExpandedBinOp(V);
3117 }
3118
3119 /// Checks if the operand at index \p Idx of instruction \p I is an expanded
3120 /// operand.
3121 bool isExpandedOperand(Instruction *I, unsigned Idx) const {
3122 assert(hasState() && "InstructionsState is invalid.");
3123 if (isCopyableElement(I))
3124 return false;
3125 if (!isExpandedBinOp(I))
3126 return false;
3127 return S.isExpandedOperand(I, Idx);
3128 }
3129
3130 /// Returns true if any scalar in the list is a copyable element.
3131 bool hasCopyableElements() const { return !CopyableElements.empty(); }
3132
3133 /// Adds \p V to the peeled reassociated scalars.
3134 void addReassocScalar(Value *V) { ReassocScalars.push_back(V); }
3135
3136 /// True if operands were gathered from an associative chain.
3137 bool hasReassocScalars() const { return !ReassocScalars.empty(); }
3138
3139 /// Returns peeled reassociated scalars.
3140 ArrayRef<Value *> getReassocScalars() const { return ReassocScalars; }
3141
3142 /// Records the signs of the flattened operand columns.
3143 void setReassocNegatedOps(const SmallBitVector &NegatedOps) {
3144 assert(NegatedOps.size() == getNumOperands() &&
3145 "Signs must cover all operand columns.");
3146 ReassocNegatedOps = NegatedOps;
3147 }
3148
3149 /// True if operand column \p Idx is subtracted rather than added.
3150 bool isReassocNegatedOp(unsigned Idx) const {
3151 return Idx < ReassocNegatedOps.size() && ReassocNegatedOps[Idx];
3152 }
3153
3154 /// Returns the state of the operations.
3155 const InstructionsState &getOperations() const { return S; }
3156
3157 /// When ReuseReorderShuffleIndices is empty it just returns position of \p
3158 /// V within vector of Scalars. Otherwise, try to remap on its reuse index.
3159 unsigned findLaneForValue(Value *V) const {
3160 auto Res = ValueToLane.try_emplace(V, getVectorFactor());
3161 if (!Res.second)
3162 return Res.first->second;
3163 unsigned &FoundLane = Res.first->getSecond();
3164 // Poison can take any lane, match it to the lane of the first non-poison
3165 // scalar.
3166 auto IsMatch = [V](Value *S) {
3167 return isa<PoisonValue>(V) ? !isa<PoisonValue>(S) : S == V;
3168 };
3169 for (auto *It = find_if(Scalars, IsMatch), *End = Scalars.end();
3170 It != End; std::advance(It, 1)) {
3171 if (!IsMatch(*It))
3172 continue;
3173 FoundLane = std::distance(Scalars.begin(), It);
3174 assert(FoundLane < Scalars.size() && "Couldn't find extract lane");
3175 if (!ReorderIndices.empty())
3176 FoundLane = ReorderIndices[FoundLane];
3177 assert(FoundLane < Scalars.size() && "Couldn't find extract lane");
3178 if (ReuseShuffleIndices.empty())
3179 break;
3180 if (auto *RIt = find(ReuseShuffleIndices, FoundLane);
3181 RIt != ReuseShuffleIndices.end()) {
3182 FoundLane = std::distance(ReuseShuffleIndices.begin(), RIt);
3183 break;
3184 }
3185 }
3186 assert(FoundLane < getVectorFactor() && "Unable to find given value.");
3187 return FoundLane;
3188 }
3189
3190 /// Build a shuffle mask for graph entry which represents a merge of main
3191 /// and alternate operations.
3192 void
3193 buildAltOpShuffleMask(const function_ref<bool(Instruction *)> IsAltOp,
3194 SmallVectorImpl<int> &Mask,
3195 SmallVectorImpl<Value *> *OpScalars = nullptr,
3196 SmallVectorImpl<Value *> *AltScalars = nullptr) const;
3197
3198 /// Return true if this is a non-power-of-2 node.
3199 bool isNonPowOf2Vec() const {
3200 bool IsNonPowerOf2 = !has_single_bit(Scalars.size());
3201 return IsNonPowerOf2;
3202 }
3203
3204 Value *getOrdered(unsigned Idx) const {
3205 if (ReorderIndices.empty())
3206 return Scalars[Idx];
3207 SmallVector<int> Mask;
3208 inversePermutation(ReorderIndices, Mask);
3209 return Scalars[Mask[Idx]];
3210 }
3211
3212#ifndef NDEBUG
3213 /// Debug printer.
3214 LLVM_DUMP_METHOD void dump() const {
3215 dbgs() << Idx << ".\n";
3216 for (unsigned OpI = 0, OpE = Operands.size(); OpI != OpE; ++OpI) {
3217 dbgs() << "Operand " << OpI << ":\n";
3218 for (const Value *V : Operands[OpI])
3219 dbgs().indent(2) << *V << "\n";
3220 }
3221 dbgs() << "Scalars: \n";
3222 for (Value *V : Scalars) {
3223 dbgs().indent(2) << *V
3224 << ((S && S.isExpandedBinOp(V)) ? " [[Expanded]]\n"
3225 : "\n");
3226 }
3227 dbgs() << "State: ";
3228 if (S && hasCopyableElements())
3229 dbgs() << "[[Copyable]] ";
3230 switch (State) {
3231 case Vectorize:
3232 if (InterleaveFactor > 0) {
3233 dbgs() << "Vectorize with interleave factor " << InterleaveFactor
3234 << "\n";
3235 } else {
3236 dbgs() << "Vectorize\n";
3237 }
3238 break;
3239 case ScatterVectorize:
3240 dbgs() << "ScatterVectorize\n";
3241 break;
3242 case StridedVectorize:
3243 dbgs() << "StridedVectorize\n";
3244 break;
3245 case ExpandVectorize:
3246 dbgs() << "ExpandVectorize\n";
3247 break;
3248 case CompressVectorize:
3249 dbgs() << "CompressVectorize\n";
3250 break;
3251 case BlendedLoadVectorize:
3252 dbgs() << "BlendedLoadVectorize\n";
3253 break;
3254 case NeedToGather:
3255 dbgs() << "NeedToGather\n";
3256 break;
3257 case CombinedVectorize:
3258 dbgs() << "CombinedVectorize\n";
3259 break;
3260 case SplitVectorize:
3261 dbgs() << "SplitVectorize\n";
3262 break;
3263 }
3264 if (S) {
3265 dbgs() << "MainOp: " << *S.getMainOp() << "\n";
3266 dbgs() << "AltOp: " << *S.getAltOp() << "\n";
3267 } else {
3268 dbgs() << "MainOp: NULL\n";
3269 dbgs() << "AltOp: NULL\n";
3270 }
3271 dbgs() << "VectorizedValue: ";
3272 if (VectorizedValue)
3273 dbgs() << *VectorizedValue << "\n";
3274 else
3275 dbgs() << "NULL\n";
3276 dbgs() << "ReuseShuffleIndices: ";
3277 if (ReuseShuffleIndices.empty())
3278 dbgs() << "Empty";
3279 else
3280 for (int ReuseIdx : ReuseShuffleIndices)
3281 dbgs() << ReuseIdx << ", ";
3282 dbgs() << "\n";
3283 dbgs() << "ReorderIndices: ";
3284 for (unsigned ReorderIdx : ReorderIndices)
3285 dbgs() << ReorderIdx << ", ";
3286 dbgs() << "\n";
3287 dbgs() << "UserTreeIndex: ";
3288 if (UserTreeIndex)
3289 dbgs() << UserTreeIndex;
3290 else
3291 dbgs() << "<invalid>";
3292 dbgs() << "\n";
3293 if (!StructEVIndices.empty()) {
3294 dbgs() << "StructEVIndices: ";
3295 interleaveComma(StructEVIndices, dbgs());
3296 dbgs() << "\n";
3297 }
3298 if (!CombinedEntriesWithIndices.empty()) {
3299 dbgs() << "Combined entries: ";
3300 interleaveComma(CombinedEntriesWithIndices, dbgs(), [&](const auto &P) {
3301 dbgs() << "Entry index " << P.first << " with offset " << P.second;
3302 });
3303 dbgs() << "\n";
3304 }
3305 }
3306#endif
3307 };
3308
3309#ifndef NDEBUG
3310 void dumpTreeCosts(const TreeEntry *E, InstructionCost ReuseShuffleCost,
3311 InstructionCost VecCost, InstructionCost ScalarCost,
3312 StringRef Banner) const {
3313 dbgs() << "SLP: " << Banner << ":\n";
3314 E->dump();
3315 dbgs() << "SLP: Costs:\n";
3316 dbgs() << "SLP: ReuseShuffleCost = " << ReuseShuffleCost << "\n";
3317 dbgs() << "SLP: VectorCost = " << VecCost << "\n";
3318 dbgs() << "SLP: ScalarCost = " << ScalarCost << "\n";
3319 dbgs() << "SLP: ReuseShuffleCost + VecCost - ScalarCost = "
3320 << ReuseShuffleCost + VecCost - ScalarCost << "\n";
3321 }
3322#endif
3323
3324 /// Create a new gather TreeEntry
3325 TreeEntry *newGatherTreeEntry(ArrayRef<Value *> VL,
3326 const InstructionsState &S,
3327 const EdgeInfo &UserTreeIdx,
3328 ArrayRef<int> ReuseShuffleIndices = {}) {
3329 auto Invalid = ScheduleBundle::invalid();
3330 return newTreeEntry(VL, Invalid, S, UserTreeIdx, ReuseShuffleIndices);
3331 }
3332
3333 /// Create a new VectorizableTree entry.
3334 TreeEntry *newTreeEntry(ArrayRef<Value *> VL, ScheduleBundle &Bundle,
3335 const InstructionsState &S,
3336 const EdgeInfo &UserTreeIdx,
3337 ArrayRef<int> ReuseShuffleIndices = {},
3338 ArrayRef<unsigned> ReorderIndices = {},
3339 unsigned InterleaveFactor = 0) {
3340 TreeEntry::EntryState EntryState =
3341 Bundle ? TreeEntry::Vectorize : TreeEntry::NeedToGather;
3342 TreeEntry *E = newTreeEntry(VL, EntryState, Bundle, S, UserTreeIdx,
3343 ReuseShuffleIndices, ReorderIndices);
3344 if (E && InterleaveFactor > 0)
3345 E->setInterleave(InterleaveFactor);
3346 return E;
3347 }
3348
3349 TreeEntry *newTreeEntry(ArrayRef<Value *> VL,
3350 TreeEntry::EntryState EntryState,
3351 ScheduleBundle &Bundle, const InstructionsState &S,
3352 const EdgeInfo &UserTreeIdx,
3353 ArrayRef<int> ReuseShuffleIndices = {},
3354 ArrayRef<unsigned> ReorderIndices = {}) {
3355 assert(((!Bundle && (EntryState == TreeEntry::NeedToGather ||
3356 EntryState == TreeEntry::SplitVectorize)) ||
3357 (Bundle && EntryState != TreeEntry::NeedToGather &&
3358 EntryState != TreeEntry::SplitVectorize)) &&
3359 "Need to vectorize gather entry?");
3360 // Gathered loads still gathered? Do not create entry, use the original one.
3361 if (GatheredLoadsEntriesFirst.has_value() &&
3362 EntryState == TreeEntry::NeedToGather && S &&
3363 S.getOpcode() == Instruction::Load && UserTreeIdx.EdgeIdx == UINT_MAX &&
3364 !UserTreeIdx.UserTE)
3365 return nullptr;
3366 VectorizableTree.push_back(std::make_unique<TreeEntry>(VectorizableTree));
3367 TreeEntry *Last = VectorizableTree.back().get();
3368 Last->Idx = VectorizableTree.size() - 1;
3369 Last->State = EntryState;
3370 if (UserTreeIdx.UserTE)
3371 OperandsToTreeEntry.try_emplace(
3372 std::make_pair(UserTreeIdx.UserTE, UserTreeIdx.EdgeIdx), Last);
3373 Last->ReuseShuffleIndices.append(ReuseShuffleIndices.begin(),
3374 ReuseShuffleIndices.end());
3375 if (ReorderIndices.empty()) {
3376 Last->Scalars.assign(VL.begin(), VL.end());
3377 if (S)
3378 Last->setOperations(S);
3379 } else {
3380 // Reorder scalars and build final mask.
3381 Last->Scalars.assign(VL.size(), nullptr);
3382 transform(ReorderIndices, Last->Scalars.begin(),
3383 [VL](unsigned Idx) -> Value * {
3384 if (Idx >= VL.size())
3385 return UndefValue::get(VL.front()->getType());
3386 return VL[Idx];
3387 });
3388 InstructionsState S = getSameOpcode(Last->Scalars, *TLI);
3389 if (S)
3390 Last->setOperations(S);
3391 Last->ReorderIndices.append(ReorderIndices.begin(), ReorderIndices.end());
3392 }
3393 if (EntryState == TreeEntry::SplitVectorize) {
3394 assert(S && "Split nodes must have operations.");
3395 Last->setOperations(S);
3396 SmallPtrSet<Value *, 4> Processed;
3397 for (Value *V : VL) {
3398 auto *I = dyn_cast<Instruction>(V);
3399 if (!I)
3400 continue;
3401 auto It = ScalarsInSplitNodes.find(V);
3402 if (It == ScalarsInSplitNodes.end()) {
3403 ScalarsInSplitNodes.try_emplace(V).first->getSecond().push_back(Last);
3404 (void)Processed.insert(V);
3405 } else if (Processed.insert(V).second) {
3406 assert(!is_contained(It->getSecond(), Last) &&
3407 "Value already associated with the node.");
3408 It->getSecond().push_back(Last);
3409 }
3410 }
3411 } else if (!Last->isGather()) {
3412 if (isa<PHINode>(S.getMainOp()) ||
3415 doesNotNeedToSchedule(VL)) ||
3416 all_of(VL, [&](Value *V) { return S.isNonSchedulable(V); }))
3417 Last->setDoesNotNeedToSchedule();
3418 SmallPtrSet<Value *, 4> Processed;
3419 for (Value *V : VL) {
3420 if (isa<PoisonValue>(V))
3421 continue;
3422 if (S.isCopyableElement(V)) {
3423 Last->addCopyableElement(V);
3424 continue;
3425 }
3426 auto It = ScalarToTreeEntries.find(V);
3427 if (It == ScalarToTreeEntries.end()) {
3428 ScalarToTreeEntries.try_emplace(V).first->getSecond().push_back(Last);
3429 (void)Processed.insert(V);
3430 } else if (Processed.insert(V).second) {
3431 assert(!is_contained(It->getSecond(), Last) &&
3432 "Value already associated with the node.");
3433 It->getSecond().push_back(Last);
3434 }
3435 }
3436 // Update the scheduler bundle to point to this TreeEntry.
3437 assert((!Bundle.getBundle().empty() || Last->doesNotNeedToSchedule()) &&
3438 "Bundle and VL out of sync");
3439 if (!Bundle.getBundle().empty()) {
3440#if !defined(NDEBUG) || defined(EXPENSIVE_CHECKS)
3441 auto *BundleMember = Bundle.getBundle().begin();
3442 SmallPtrSet<Value *, 4> Processed;
3443 for (Value *V : VL) {
3444 if (S.isNonSchedulable(V) || !Processed.insert(V).second)
3445 continue;
3446 ++BundleMember;
3447 }
3448 assert(BundleMember == Bundle.getBundle().end() &&
3449 "Bundle and VL out of sync");
3450#endif
3451 Bundle.setTreeEntry(Last);
3452 }
3453 } else {
3454 // Build a map for gathered scalars to the nodes where they are used.
3455 bool AllConstsOrCasts = true;
3456 for (Value *V : VL) {
3458 S.isCopyableElement(V))
3459 Last->addCopyableElement(V);
3460 if (!isConstant(V)) {
3461 auto *I = dyn_cast<CastInst>(V);
3462 AllConstsOrCasts &= I && I->getType()->isIntegerTy();
3463 if (UserTreeIdx.EdgeIdx != UINT_MAX || !UserTreeIdx.UserTE ||
3464 !UserTreeIdx.UserTE->isGather())
3465 ValueToGatherNodes.try_emplace(V).first->getSecond().insert(Last);
3466 }
3467 }
3468 if (AllConstsOrCasts)
3469 CastMaxMinBWSizes =
3470 std::make_pair(std::numeric_limits<unsigned>::max(), 1);
3471 MustGather.insert_range(VL);
3472 }
3473
3474 if (UserTreeIdx.UserTE)
3475 Last->UserTreeIndex = UserTreeIdx;
3476 return Last;
3477 }
3478
3479 /// -- Vectorization State --
3480 /// Holds all of the tree entries.
3481 TreeEntry::VecTreeTy VectorizableTree;
3482
3483#ifndef NDEBUG
3484 /// Debug printer.
3485 LLVM_DUMP_METHOD void dumpVectorizableTree() const {
3486 for (unsigned Id = 0, IdE = VectorizableTree.size(); Id != IdE; ++Id) {
3487 VectorizableTree[Id]->dump();
3488 if (TransformedToGatherNodes.contains(VectorizableTree[Id].get()))
3489 dbgs() << "[[TRANSFORMED TO GATHER]]";
3490 else if (DeletedNodes.contains(VectorizableTree[Id].get()))
3491 dbgs() << "[[DELETED NODE]]";
3492 dbgs() << "\n";
3493 }
3494 }
3495#endif
3496
3497 /// Get list of vector entries, associated with the value \p V.
3498 ArrayRef<TreeEntry *> getTreeEntries(const Value *V) const {
3499 assert(V && "V cannot be nullptr.");
3500 auto It = ScalarToTreeEntries.find(V);
3501 if (It == ScalarToTreeEntries.end())
3502 return {};
3503 return It->getSecond();
3504 }
3505
3506 /// Get list of split vector entries, associated with the value \p V.
3507 ArrayRef<TreeEntry *> getSplitTreeEntries(Value *V) const {
3508 assert(V && "V cannot be nullptr.");
3509 auto It = ScalarsInSplitNodes.find(V);
3510 if (It == ScalarsInSplitNodes.end())
3511 return {};
3512 return It->getSecond();
3513 }
3514
3515 /// Returns first vector node for value \p V, matching values \p VL.
3516 TreeEntry *getSameValuesTreeEntry(Value *V, ArrayRef<Value *> VL,
3517 bool SameVF = false) const {
3518 assert(V && "V cannot be nullptr.");
3519 for (TreeEntry *TE : ScalarToTreeEntries.lookup(V))
3520 if ((!SameVF || TE->getVectorFactor() == VL.size()) && TE->isSame(VL))
3521 return TE;
3522 return nullptr;
3523 }
3524
3525 /// Contains all the outputs of legality analysis for a list of values to
3526 /// vectorize.
3527 class ScalarsVectorizationLegality {
3528 InstructionsState S;
3529 bool IsLegal;
3530 bool TryToFindDuplicates;
3531 bool TrySplitVectorize;
3532
3533 public:
3534 ScalarsVectorizationLegality(InstructionsState S, bool IsLegal,
3535 bool TryToFindDuplicates = true,
3536 bool TrySplitVectorize = false)
3537 : S(S), IsLegal(IsLegal), TryToFindDuplicates(TryToFindDuplicates),
3538 TrySplitVectorize(TrySplitVectorize) {
3539 assert((!IsLegal || (S.valid() && TryToFindDuplicates)) &&
3540 "Inconsistent state");
3541 }
3542 const InstructionsState &getInstructionsState() const { return S; };
3543 bool isLegal() const { return IsLegal; }
3544 bool tryToFindDuplicates() const { return TryToFindDuplicates; }
3545 bool trySplitVectorize() const { return TrySplitVectorize; }
3546 };
3547
3548 /// Checks if the specified list of the instructions/values can be vectorized
3549 /// in general.
3550 ScalarsVectorizationLegality
3551 getScalarsVectorizationLegality(ArrayRef<Value *> VL, unsigned Depth,
3552 const EdgeInfo &UserTreeIdx) const;
3553
3554 /// Checks if the specified list of the instructions/values can be vectorized
3555 /// and fills required data before actual scheduling of the instructions.
3556 TreeEntry::EntryState getScalarsVectorizationState(
3557 const InstructionsState &S, ArrayRef<Value *> VL,
3558 bool IsScatterVectorizeUserTE, OrdersType &CurrentOrder,
3559 SmallVectorImpl<Value *> &PointerOps, StridedPtrInfo &SPtrInfo,
3560 SmallVectorImpl<int> &ReuseShuffleIndices);
3561
3562 /// Maps a specific scalar to its tree entry(ies).
3563 SmallDenseMap<Value *, SmallVector<TreeEntry *>> ScalarToTreeEntries;
3564
3565 /// List of deleted non-profitable nodes.
3566 SmallPtrSet<const TreeEntry *, 8> DeletedNodes;
3567
3568 /// List of nodes, transformed to gathered, with their conservative
3569 /// gather/buildvector cost estimation.
3570 SmallDenseMap<const TreeEntry *, InstructionCost> TransformedToGatherNodes;
3571
3572 /// Maps the operand index and entry to the corresponding tree entry.
3573 SmallDenseMap<std::pair<const TreeEntry *, unsigned>, TreeEntry *>
3574 OperandsToTreeEntry;
3575
3576 /// Scalars, used in split vectorize nodes.
3577 SmallDenseMap<Value *, SmallVector<TreeEntry *>> ScalarsInSplitNodes;
3578
3579 /// Maps a value to the proposed vectorizable size.
3580 SmallDenseMap<Value *, unsigned> InstrElementSize;
3581
3582 /// A list of scalars that we found that we need to keep as scalars.
3583 ValueSet MustGather;
3584
3585 /// Maps each peeled reassociated scalar to owning entries. Keeps them
3586 /// treated as vectorized while an owner is live.
3587 SmallDenseMap<const Value *, SmallVector<const TreeEntry *>>
3588 ReassocScalarToTreeEntries;
3589
3590 /// Peeled reassociated scalars that must survive erasure: claimed by a
3591 /// gather node, listed in some tree entry's scalars, or feeding another
3592 /// kept scalar.
3593 SmallPtrSet<const Value *, 8> KeptReassocScalars;
3594
3595 /// A set of first non-schedulable values.
3596 ValueSet NonScheduledFirst;
3597
3598 /// A map between the vectorized entries and the last instructions in the
3599 /// bundles. The bundles are built in use order, not in the def order of the
3600 /// instructions. So, we cannot rely directly on the last instruction in the
3601 /// bundle being the last instruction in the program order during
3602 /// vectorization process since the basic blocks are affected, need to
3603 /// pre-gather them before.
3604 SmallDenseMap<const TreeEntry *, WeakTrackingVH> EntryToLastInstruction;
3605
3606 /// Keeps the mapping between the last instructions and their insertion
3607 /// points, which is an instruction-after-the-last-instruction.
3608 SmallDenseMap<const Instruction *, Instruction *> LastInstructionToPos;
3609
3610 /// List of gather nodes, depending on other gather/vector nodes, which should
3611 /// be emitted after the vector instruction emission process to correctly
3612 /// handle order of the vector instructions and shuffles.
3613 SetVector<const TreeEntry *> PostponedGathers;
3614
3615 using ValueToGatherNodesMap =
3616 DenseMap<Value *, SmallSetVector<const TreeEntry *, 4>>;
3617 ValueToGatherNodesMap ValueToGatherNodes;
3618
3619 SmallDenseMap<TreeEntry *, StridedPtrInfo> TreeEntryToStridedPtrInfoMap;
3620
3621 /// A list of the load entries (node indices), which can be vectorized using
3622 /// strided or masked gather approach, but attempted to be represented as
3623 /// contiguous loads.
3624 SetVector<unsigned> LoadEntriesToVectorize;
3625
3626 /// true if graph nodes transforming mode is on.
3627 bool IsGraphTransformMode = false;
3628
3629 /// The index of the first gathered load entry in the VectorizeTree.
3630 std::optional<unsigned> GatheredLoadsEntriesFirst;
3631
3632 /// Root entries of the subtrees built for the splat gather nodes' unique
3633 /// scalars. They have no users in the tree and must be emitted explicitly
3634 /// before the root node.
3635 SmallVector<TreeEntry *> SplatGatheredScalarsRoots;
3636
3637 /// Maps compress entries to their mask data for the final codegen.
3638 SmallDenseMap<const TreeEntry *,
3639 std::tuple<SmallVector<int>, VectorType *, unsigned, bool>>
3640 CompressEntryToData;
3641
3642 /// The loop nest, used to check if only a single loop nest is vectorized, not
3643 /// multiple, to avoid side-effects from the loop-aware cost model.
3644 SmallVector<const Loop *> CurrentLoopNest;
3645
3646 /// Per-depth SCEVs trip counts at every loop level where the tree builder has
3647 /// joined diverging sibling loops.
3648 SmallVector<const SCEV *> MergedLoopBTCs;
3649
3650 /// Maps the loops to their loop nests.
3651 SmallDenseMap<const Loop *, SmallVector<const Loop *>> LoopToLoopNest;
3652
3653 /// Per-loop cache of nest scale factors: the product of trip counts of the
3654 /// loop and all of its ancestors. Shared by getLoopNestScale() and (via it)
3655 /// by getScaleToLoopIterations() and getGatherNodeEffectiveScale().
3656 SmallDenseMap<const Loop *, uint64_t> LoopNestScaleCache;
3657
3658 /// This POD struct describes one external user in the vectorized tree.
3659 struct ExternalUser {
3660 ExternalUser(Value *S, llvm::User *U, const TreeEntry &E, unsigned L)
3661 : Scalar(S), User(U), E(E), Lane(L) {}
3662
3663 /// Which scalar in our function.
3664 Value *Scalar = nullptr;
3665
3666 /// Which user that uses the scalar.
3667 llvm::User *User = nullptr;
3668
3669 /// Vector node, the value is part of.
3670 const TreeEntry &E;
3671
3672 /// Which lane does the scalar belong to.
3673 unsigned Lane;
3674 };
3675 using UserList = SmallVector<ExternalUser, 16>;
3676
3677 /// Checks if two instructions may access the same memory.
3678 ///
3679 /// \p Loc1 is the location of \p Inst1. It is passed explicitly because it
3680 /// is invariant in the calling loop.
3681 bool isAliased(const MemoryLocation &Loc1, Instruction *Inst1,
3682 Instruction *Inst2) {
3683 assert(Loc1.Ptr && isSimple(Inst1) && "Expected simple first instruction.");
3684 // First check if the result is already in the cache.
3685 AliasCacheKey Key = std::make_pair(Inst1, Inst2);
3686 auto Res = AliasCache.try_emplace(Key);
3687 if (!Res.second)
3688 return Res.first->second;
3689 bool Aliased = isModOrRefSet(BatchAA.getModRefInfo(Inst2, Loc1));
3690 // Store the result in the cache.
3691 Res.first->getSecond() = Aliased;
3692 return Aliased;
3693 }
3694
3695 /// Returns true if the may-alias dependency between simple load/store
3696 /// instructions \p Inst1 and \p Inst2 could be disambiguated by a runtime
3697 /// alias check.
3698 bool isRuntimeCheckableAliasPair(Instruction *Inst1, Instruction *Inst2);
3699
3700 /// Records the (distinct base object) pair behind the may-alias dependency
3701 /// of \p Inst1 and \p Inst2 as a runtime alias check guarding the region in
3702 /// block \p BB. Returns true if the pair was recorded.
3703 bool recordRuntimeAliasCheck(BasicBlock *BB, Instruction *Inst1,
3704 Instruction *Inst2);
3705
3706 /// Emits the collected runtime alias checks and versions the affected block,
3707 /// duplicating its body into a scalar fallback guarded by the checks.
3708 void versionBlocksForRuntimeChecks();
3709
3710 /// Builds the i1 value that is true when any pair of checked base objects
3711 /// overlaps at runtime. The base address bounds are materialized from their
3712 /// SCEVs with \p Exp.
3713 Value *emitRuntimeAliasCheck(IRBuilderBase &Builder, SCEVExpander &Exp);
3714
3715 /// Data to model and emit the runtime alias checks.
3716 struct RuntimeAliasCheckInfo {
3717 /// The block whose body is guarded by the checks. Exactly one block is
3718 /// supported per attempt.
3719 BasicBlock *BB = nullptr;
3720 /// Pairs of base objects that must be proven disjoint.
3721 SmallSetVector<std::pair<const Value *, const Value *>, 4> BasePairs;
3722 /// Accessed address range [Low, High) for each involved base object.
3723 SmallMapVector<const Value *, std::pair<const SCEV *, const SCEV *>, 4>
3724 Bounds;
3725
3726 void clear() {
3727 BB = nullptr;
3728 BasePairs.clear();
3729 Bounds.clear();
3730 }
3731 };
3732
3733 /// When true, scheduling drops may-alias memory dependencies between
3734 /// distinct, range-checkable base objects and records them as runtime alias
3735 /// checks instead.
3736 bool TryRuntimeAliasChecks = false;
3737
3738 /// Runtime alias checks collected during the last optimistic buildTree().
3739 RuntimeAliasCheckInfo RTChecks;
3740
3741 /// Base-object pairs already proven disjoint by the block's runtime alias
3742 /// check.
3743 SmallDenseMap<BasicBlock *,
3744 SmallDenseSet<std::pair<const Value *, const Value *>, 4>, 2>
3745 VersionedBlockCheckedPairs;
3746
3747 /// Scalar fallback blocks.
3748 SmallPtrSet<BasicBlock *, 4> ScalarFallbackBlocks;
3749
3750 /// Blocks for which a runtime-checks versioning attempt was made
3751 /// and did not produce a profitable versioning.
3752 SmallPtrSet<BasicBlock *, 8> FailedRuntimeChecksBlocks;
3753
3754 /// Returns true if a may-alias dependency between the simple load/store
3755 /// instructions \p Inst1 and \p Inst2 in block \p BB is already covered by a
3756 /// runtime alias check emitted for \p BB by a previous versioning.
3757 bool isCoveredByExistingVersionCheck(BasicBlock *BB, Instruction *Inst1,
3758 Instruction *Inst2) const;
3759
3760 /// True, if a may-alias dependency between distinct, range-checkable base
3761 /// objects is observed (whether or not it was dropped).
3762 bool HasRuntimeCheckableBlockers = false;
3763
3764 /// True, if a kept may-alias dependency is not runtime-checkable (call or a
3765 /// non-simple memaccess).
3766 bool HasNonCheckableMemBlocker = false;
3767
3768 /// Runtime checks are validated and bounded the collected checks.
3769 bool RTChecksFinalized = false;
3770
3771 /// Set when a block was versioned with runtime alias checks, which changes
3772 /// the CFG. Used to drop CFG-analysis preservation for the run.
3773 bool CFGChanged = false;
3774
3775 /// Guarded block body (non-PHI, non-terminator) in original source order.
3776 SmallVector<Instruction *> RTOrigBodyOrder;
3777
3778 using AliasCacheKey = std::pair<Instruction *, Instruction *>;
3779
3780 /// Cache for alias results.
3781 /// TODO: consider moving this to the AliasAnalysis itself.
3782 SmallDenseMap<AliasCacheKey, bool> AliasCache;
3783
3784 // Cache for pointerMayBeCaptured calls inside AA. This is preserved
3785 // globally through SLP because we don't perform any action which
3786 // invalidates capture results.
3787 BatchAAResults BatchAA;
3788
3789 /// Temporary store for deleted instructions. Instructions will be deleted
3790 /// eventually when the BoUpSLP is destructed. The deferral is required to
3791 /// ensure that there are no incorrect collisions in the AliasCache, which
3792 /// can happen if a new instruction is allocated at the same address as a
3793 /// previously deleted instruction.
3794 DenseSet<Instruction *> DeletedInstructions;
3795
3796 /// Set of the instruction, being analyzed already for reductions.
3797 SmallPtrSet<Instruction *, 16> AnalyzedReductionsRoots;
3798
3799 /// Set of hashes for the list of reduction values already being analyzed.
3800 DenseSet<size_t> AnalyzedReductionVals;
3801
3802 /// Set of hashes for the bundles, rejected as non-vectorizable.
3803 SmallDenseSet<size_t, 8> AnalyzedBundles;
3804
3805 /// Set of the values, which were a part of the analyzed vector nodes.
3806 SmallPtrSet<const Value *, 32> AnalyzedScalars;
3807
3808 /// Cache of the number of parts for the types and the parts limit.
3809 mutable SmallDenseMap<std::tuple<Type *, Type *, unsigned>, unsigned>
3810 NumberOfPartsCache;
3811
3812 /// Values, already been analyzed for mininmal bitwidth and found to be
3813 /// non-profitable.
3814 DenseSet<Value *> AnalyzedMinBWVals;
3815
3816 /// A list of values that need to extracted out of the tree.
3817 /// This list holds pairs of (Internal Scalar : External User). External User
3818 /// can be nullptr, it means that this Internal Scalar will be used later,
3819 /// after vectorization.
3820 UserList ExternalUses;
3821
3822 /// A list of GEPs which can be reaplced by scalar GEPs instead of
3823 /// extractelement instructions.
3824 SmallPtrSet<Value *, 4> ExternalUsesAsOriginalScalar;
3825
3826 /// A list of scalar to be extracted without specific user necause of too many
3827 /// uses.
3828 SmallPtrSet<Value *, 4> ExternalUsesWithNonUsers;
3829
3830 /// Replacements emitted for the external uses without users, consumed after
3831 /// the tree vectorization; must not be collected as dead operands of the
3832 /// erased scalars.
3833 SmallPtrSet<Value *, 4> ExternalUseReplacements;
3834
3835 /// Values used only by @llvm.assume calls.
3836 SmallPtrSet<const Value *, 32> EphValues;
3837
3838 /// Holds all of the instructions that we gathered, shuffle instructions and
3839 /// extractelements.
3840 SetVector<Instruction *> GatherShuffleExtractSeq;
3841
3842 /// A list of blocks that we are going to CSE.
3843 DenseSet<BasicBlock *> CSEBlocks;
3844
3845 /// List of hashes of vector of loads, which are known to be non vectorizable.
3846 DenseSet<size_t> ListOfKnonwnNonVectorizableLoads;
3847
3848 /// Represents a scheduling entity, either ScheduleData, ScheduleCopyableData
3849 /// or ScheduleBundle. ScheduleData used to gather dependecies for a single
3850 /// instructions, while ScheduleBundle represents a batch of instructions,
3851 /// going to be groupped together. ScheduleCopyableData models extra user for
3852 /// "copyable" instructions.
3853 class ScheduleEntity {
3854 friend class ScheduleBundle;
3855 friend class ScheduleData;
3856 friend class ScheduleCopyableData;
3857
3858 protected:
3859 enum class Kind { ScheduleData, ScheduleBundle, ScheduleCopyableData };
3860 Kind getKind() const { return K; }
3861 ScheduleEntity(Kind K) : K(K) {}
3862
3863 private:
3864 /// Used for getting a "good" final ordering of instructions.
3865 int SchedulingPriority = 0;
3866 /// True if this instruction (or bundle) is scheduled (or considered as
3867 /// scheduled in the dry-run).
3868 bool IsScheduled = false;
3869 /// The kind of the ScheduleEntity.
3870 const Kind K = Kind::ScheduleData;
3871
3872 public:
3873 ScheduleEntity() = delete;
3874 /// Gets/sets the scheduling priority.
3875 void setSchedulingPriority(int Priority) { SchedulingPriority = Priority; }
3876 int getSchedulingPriority() const { return SchedulingPriority; }
3877 bool isReady() const {
3878 if (const auto *SD = dyn_cast<ScheduleData>(this))
3879 return SD->isReady();
3880 if (const auto *CD = dyn_cast<ScheduleCopyableData>(this))
3881 return CD->isReady();
3882 return cast<ScheduleBundle>(this)->isReady();
3883 }
3884 /// Returns true if the dependency information has been calculated.
3885 /// Note that depenendency validity can vary between instructions within
3886 /// a single bundle.
3887 bool hasValidDependencies() const {
3888 if (const auto *SD = dyn_cast<ScheduleData>(this))
3889 return SD->hasValidDependencies();
3890 if (const auto *CD = dyn_cast<ScheduleCopyableData>(this))
3891 return CD->hasValidDependencies();
3892 return cast<ScheduleBundle>(this)->hasValidDependencies();
3893 }
3894 /// Gets the number of unscheduled dependencies.
3895 int getUnscheduledDeps() const {
3896 if (const auto *SD = dyn_cast<ScheduleData>(this))
3897 return SD->getUnscheduledDeps();
3898 if (const auto *CD = dyn_cast<ScheduleCopyableData>(this))
3899 return CD->getUnscheduledDeps();
3900 return cast<ScheduleBundle>(this)->unscheduledDepsInBundle();
3901 }
3902 /// Increments the number of unscheduled dependencies.
3903 int incrementUnscheduledDeps(int Incr) {
3904 if (auto *SD = dyn_cast<ScheduleData>(this))
3905 return SD->incrementUnscheduledDeps(Incr);
3906 return cast<ScheduleCopyableData>(this)->incrementUnscheduledDeps(Incr);
3907 }
3908 /// Gets the number of dependencies.
3909 int getDependencies() const {
3910 if (const auto *SD = dyn_cast<ScheduleData>(this))
3911 return SD->getDependencies();
3912 return cast<ScheduleCopyableData>(this)->getDependencies();
3913 }
3914 /// Gets the instruction.
3915 Instruction *getInst() const {
3916 if (const auto *SD = dyn_cast<ScheduleData>(this))
3917 return SD->getInst();
3918 return cast<ScheduleCopyableData>(this)->getInst();
3919 }
3920
3921 /// Gets/sets if the bundle is scheduled.
3922 bool isScheduled() const { return IsScheduled; }
3923 void setScheduled(bool Scheduled) { IsScheduled = Scheduled; }
3924
3925 static bool classof(const ScheduleEntity *) { return true; }
3926
3927#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
3928 void dump(raw_ostream &OS) const {
3929 if (const auto *SD = dyn_cast<ScheduleData>(this))
3930 return SD->dump(OS);
3931 if (const auto *CD = dyn_cast<ScheduleCopyableData>(this))
3932 return CD->dump(OS);
3933 return cast<ScheduleBundle>(this)->dump(OS);
3934 }
3935
3936 LLVM_DUMP_METHOD void dump() const {
3937 dump(dbgs());
3938 dbgs() << '\n';
3939 }
3940#endif // if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
3941 };
3942
3943#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
3945 const BoUpSLP::ScheduleEntity &SE) {
3946 SE.dump(OS);
3947 return OS;
3948 }
3949#endif
3950
3951 /// Contains all scheduling relevant data for an instruction.
3952 /// A ScheduleData either represents a single instruction or a member of an
3953 /// instruction bundle (= a group of instructions which is combined into a
3954 /// vector instruction).
3955 class ScheduleData final : public ScheduleEntity {
3956 public:
3957 // The initial value for the dependency counters. It means that the
3958 // dependencies are not calculated yet.
3959 enum { InvalidDeps = -1 };
3960
3961 ScheduleData() : ScheduleEntity(Kind::ScheduleData) {}
3962 static bool classof(const ScheduleEntity *Entity) {
3963 return Entity->getKind() == Kind::ScheduleData;
3964 }
3965
3966 void init(int BlockSchedulingRegionID, Instruction *I) {
3967 NextLoadStore = nullptr;
3968 IsScheduled = false;
3969 SchedulingRegionID = BlockSchedulingRegionID;
3970 clearDependencies();
3971 Inst = I;
3972 }
3973
3974 /// Verify basic self consistency properties
3975 void verify() {
3976 if (hasValidDependencies()) {
3977 assert(UnscheduledDeps <= Dependencies && "invariant");
3978 } else {
3979 assert(UnscheduledDeps == Dependencies && "invariant");
3980 }
3981
3982 if (IsScheduled) {
3983 assert(hasValidDependencies() && UnscheduledDeps == 0 &&
3984 "unexpected scheduled state");
3985 }
3986 }
3987
3988 /// Returns true if the dependency information has been calculated.
3989 /// Note that depenendency validity can vary between instructions within
3990 /// a single bundle.
3991 bool hasValidDependencies() const { return Dependencies != InvalidDeps; }
3992
3993 /// Returns true if it is ready for scheduling, i.e. it has no more
3994 /// unscheduled depending instructions/bundles.
3995 bool isReady() const { return UnscheduledDeps == 0 && !IsScheduled; }
3996
3997 /// Modifies the number of unscheduled dependencies for this instruction,
3998 /// and returns the number of remaining dependencies for the containing
3999 /// bundle.
4000 int incrementUnscheduledDeps(int Incr) {
4001 assert(hasValidDependencies() &&
4002 "increment of unscheduled deps would be meaningless");
4003 UnscheduledDeps += Incr;
4004 assert(UnscheduledDeps >= 0 &&
4005 "Expected valid number of unscheduled deps");
4006 return UnscheduledDeps;
4007 }
4008
4009 /// Sets the number of unscheduled dependencies to the number of
4010 /// dependencies.
4011 void resetUnscheduledDeps() { UnscheduledDeps = Dependencies; }
4012
4013 /// Clears all dependency information.
4014 void clearDependencies() {
4015 clearDirectDependencies();
4016 MemoryDependencies.clear();
4017 ControlDependencies.clear();
4018 }
4019
4020 /// Clears all direct dependencies only, except for control and memory
4021 /// dependencies.
4022 /// Required for copyable elements to correctly handle control/memory deps
4023 /// and avoid extra reclaculation of such deps.
4024 void clearDirectDependencies() {
4025 Dependencies = InvalidDeps;
4026 resetUnscheduledDeps();
4027 IsScheduled = false;
4028 }
4029
4030 /// Gets the number of unscheduled dependencies.
4031 int getUnscheduledDeps() const { return UnscheduledDeps; }
4032 /// Gets the number of dependencies.
4033 int getDependencies() const { return Dependencies; }
4034 /// Initializes the number of dependencies.
4035 void initDependencies() { Dependencies = 0; }
4036 /// Increments the number of dependencies.
4037 void incDependencies() { Dependencies++; }
4038
4039 /// Gets scheduling region ID.
4040 int getSchedulingRegionID() const { return SchedulingRegionID; }
4041
4042 /// Gets the instruction.
4043 Instruction *getInst() const { return Inst; }
4044
4045 /// Gets the list of memory dependencies.
4046 ArrayRef<ScheduleData *> getMemoryDependencies() const {
4047 return MemoryDependencies;
4048 }
4049 /// Adds a memory dependency.
4050 void addMemoryDependency(ScheduleData *Dep) {
4051 MemoryDependencies.push_back(Dep);
4052 }
4053 /// Gets the list of control dependencies.
4054 ArrayRef<ScheduleData *> getControlDependencies() const {
4055 return ControlDependencies;
4056 }
4057 /// Adds a control dependency.
4058 void addControlDependency(ScheduleData *Dep) {
4059 ControlDependencies.push_back(Dep);
4060 }
4061 /// Gets/sets the next load/store instruction in the block.
4062 ScheduleData *getNextLoadStore() const { return NextLoadStore; }
4063 void setNextLoadStore(ScheduleData *Next) { NextLoadStore = Next; }
4064
4065 void dump(raw_ostream &OS) const { OS << *Inst; }
4066
4067 LLVM_DUMP_METHOD void dump() const {
4068 dump(dbgs());
4069 dbgs() << '\n';
4070 }
4071
4072 private:
4073 Instruction *Inst = nullptr;
4074
4075 /// Single linked list of all memory instructions (e.g. load, store, call)
4076 /// in the block - until the end of the scheduling region.
4077 ScheduleData *NextLoadStore = nullptr;
4078
4079 /// The dependent memory instructions.
4080 /// This list is derived on demand in calculateDependencies().
4081 SmallVector<ScheduleData *> MemoryDependencies;
4082
4083 /// List of instructions which this instruction could be control dependent
4084 /// on. Allowing such nodes to be scheduled below this one could introduce
4085 /// a runtime fault which didn't exist in the original program.
4086 /// ex: this is a load or udiv following a readonly call which inf loops
4087 SmallVector<ScheduleData *> ControlDependencies;
4088
4089 /// This ScheduleData is in the current scheduling region if this matches
4090 /// the current SchedulingRegionID of BlockScheduling.
4091 int SchedulingRegionID = 0;
4092
4093 /// The number of dependencies. Constitutes of the number of users of the
4094 /// instruction plus the number of dependent memory instructions (if any).
4095 /// This value is calculated on demand.
4096 /// If InvalidDeps, the number of dependencies is not calculated yet.
4097 int Dependencies = InvalidDeps;
4098
4099 /// The number of dependencies minus the number of dependencies of scheduled
4100 /// instructions. As soon as this is zero, the instruction/bundle gets ready
4101 /// for scheduling.
4102 /// Note that this is negative as long as Dependencies is not calculated.
4103 int UnscheduledDeps = InvalidDeps;
4104 };
4105
4106#ifndef NDEBUG
4108 const BoUpSLP::ScheduleData &SD) {
4109 SD.dump(OS);
4110 return OS;
4111 }
4112#endif
4113
4114 class ScheduleBundle final : public ScheduleEntity {
4115 /// The schedule data for the instructions in the bundle.
4117 /// True if this bundle is valid.
4118 bool IsValid = true;
4119 /// The TreeEntry that this instruction corresponds to.
4120 TreeEntry *TE = nullptr;
4121 ScheduleBundle(bool IsValid)
4122 : ScheduleEntity(Kind::ScheduleBundle), IsValid(IsValid) {}
4123
4124 public:
4125 ScheduleBundle() : ScheduleEntity(Kind::ScheduleBundle) {}
4126 static bool classof(const ScheduleEntity *Entity) {
4127 return Entity->getKind() == Kind::ScheduleBundle;
4128 }
4129
4130 /// Verify basic self consistency properties
4131 void verify() const {
4132 for (const ScheduleEntity *SD : Bundle) {
4133 if (SD->hasValidDependencies()) {
4134 assert(SD->getUnscheduledDeps() <= SD->getDependencies() &&
4135 "invariant");
4136 } else {
4137 assert(SD->getUnscheduledDeps() == SD->getDependencies() &&
4138 "invariant");
4139 }
4140
4141 if (isScheduled()) {
4142 assert(SD->hasValidDependencies() && SD->getUnscheduledDeps() == 0 &&
4143 "unexpected scheduled state");
4144 }
4145 }
4146 }
4147
4148 /// Returns the number of unscheduled dependencies in the bundle.
4149 int unscheduledDepsInBundle() const {
4150 assert(*this && "bundle must not be empty");
4151 int Sum = 0;
4152 for (const ScheduleEntity *BundleMember : Bundle) {
4153 if (BundleMember->getUnscheduledDeps() == ScheduleData::InvalidDeps)
4154 return ScheduleData::InvalidDeps;
4155 Sum += BundleMember->getUnscheduledDeps();
4156 }
4157 return Sum;
4158 }
4159
4160 /// Returns true if the dependency information has been calculated.
4161 /// Note that depenendency validity can vary between instructions within
4162 /// a single bundle.
4163 bool hasValidDependencies() const {
4164 return all_of(Bundle, [](const ScheduleEntity *SD) {
4165 return SD->hasValidDependencies();
4166 });
4167 }
4168
4169 /// Returns true if it is ready for scheduling, i.e. it has no more
4170 /// unscheduled depending instructions/bundles.
4171 bool isReady() const {
4172 assert(*this && "bundle must not be empty");
4173 return unscheduledDepsInBundle() == 0 && !isScheduled();
4174 }
4175
4176 /// Returns the bundle of scheduling data, associated with the current
4177 /// instruction.
4178 ArrayRef<ScheduleEntity *> getBundle() { return Bundle; }
4179 ArrayRef<const ScheduleEntity *> getBundle() const { return Bundle; }
4180 /// Adds an instruction to the bundle.
4181 void add(ScheduleEntity *SD) { Bundle.push_back(SD); }
4182
4183 /// Gets/sets the associated tree entry.
4184 void setTreeEntry(TreeEntry *TE) { this->TE = TE; }
4185 TreeEntry *getTreeEntry() const { return TE; }
4186
4187 static ScheduleBundle invalid() { return {false}; }
4188
4189 operator bool() const { return IsValid; }
4190
4191#ifndef NDEBUG
4192 void dump(raw_ostream &OS) const {
4193 if (!*this) {
4194 OS << "[]";
4195 return;
4196 }
4197 OS << '[';
4198 interleaveComma(Bundle, OS, [&](const ScheduleEntity *SD) {
4200 OS << "<Copyable>";
4201 OS << *SD->getInst();
4202 });
4203 OS << ']';
4204 }
4205
4206 LLVM_DUMP_METHOD void dump() const {
4207 dump(dbgs());
4208 dbgs() << '\n';
4209 }
4210#endif // NDEBUG
4211 };
4212
4213#ifndef NDEBUG
4215 const BoUpSLP::ScheduleBundle &Bundle) {
4216 Bundle.dump(OS);
4217 return OS;
4218 }
4219#endif
4220
4221 /// Contains all scheduling relevant data for the copyable instruction.
4222 /// It models the virtual instructions, supposed to replace the original
4223 /// instructions. E.g., if instruction %0 = load is a part of the bundle [%0,
4224 /// %1], where %1 = add, then the ScheduleCopyableData models virtual
4225 /// instruction %virt = add %0, 0.
4226 class ScheduleCopyableData final : public ScheduleEntity {
4227 /// The source schedule data for the instruction.
4228 Instruction *Inst = nullptr;
4229 /// The edge information for the instruction.
4230 const EdgeInfo EI;
4231 /// This ScheduleData is in the current scheduling region if this matches
4232 /// the current SchedulingRegionID of BlockScheduling.
4233 int SchedulingRegionID = 0;
4234 /// Bundle, this data is part of.
4235 ScheduleBundle &Bundle;
4236
4237 public:
4238 ScheduleCopyableData(int BlockSchedulingRegionID, Instruction *I,
4239 const EdgeInfo &EI, ScheduleBundle &Bundle)
4240 : ScheduleEntity(Kind::ScheduleCopyableData), Inst(I), EI(EI),
4241 SchedulingRegionID(BlockSchedulingRegionID), Bundle(Bundle) {}
4242 static bool classof(const ScheduleEntity *Entity) {
4243 return Entity->getKind() == Kind::ScheduleCopyableData;
4244 }
4245
4246 /// Verify basic self consistency properties
4247 void verify() {
4248 if (hasValidDependencies()) {
4249 assert(UnscheduledDeps <= Dependencies && "invariant");
4250 } else {
4251 assert(UnscheduledDeps == Dependencies && "invariant");
4252 }
4253
4254 if (IsScheduled) {
4255 assert(hasValidDependencies() && UnscheduledDeps == 0 &&
4256 "unexpected scheduled state");
4257 }
4258 }
4259
4260 /// Returns true if the dependency information has been calculated.
4261 /// Note that depenendency validity can vary between instructions within
4262 /// a single bundle.
4263 bool hasValidDependencies() const {
4264 return Dependencies != ScheduleData::InvalidDeps;
4265 }
4266
4267 /// Returns true if it is ready for scheduling, i.e. it has no more
4268 /// unscheduled depending instructions/bundles.
4269 bool isReady() const { return UnscheduledDeps == 0 && !IsScheduled; }
4270
4271 /// Modifies the number of unscheduled dependencies for this instruction,
4272 /// and returns the number of remaining dependencies for the containing
4273 /// bundle.
4274 int incrementUnscheduledDeps(int Incr) {
4275 assert(hasValidDependencies() &&
4276 "increment of unscheduled deps would be meaningless");
4277 UnscheduledDeps += Incr;
4278 assert(UnscheduledDeps >= 0 && "invariant");
4279 return UnscheduledDeps;
4280 }
4281
4282 /// Sets the number of unscheduled dependencies to the number of
4283 /// dependencies.
4284 void resetUnscheduledDeps() { UnscheduledDeps = Dependencies; }
4285
4286 /// Gets the number of unscheduled dependencies.
4287 int getUnscheduledDeps() const { return UnscheduledDeps; }
4288 /// Gets the number of dependencies.
4289 int getDependencies() const { return Dependencies; }
4290 /// Initializes the number of dependencies.
4291 void initDependencies() { Dependencies = 0; }
4292 /// Increments the number of dependencies.
4293 void incDependencies() { Dependencies++; }
4294
4295 /// Gets scheduling region ID.
4296 int getSchedulingRegionID() const { return SchedulingRegionID; }
4297
4298 /// Gets the instruction.
4299 Instruction *getInst() const { return Inst; }
4300
4301 /// Clears all dependency information.
4302 void clearDependencies() {
4303 Dependencies = ScheduleData::InvalidDeps;
4304 UnscheduledDeps = ScheduleData::InvalidDeps;
4305 IsScheduled = false;
4306 }
4307
4308 /// Gets the edge information.
4309 const EdgeInfo &getEdgeInfo() const { return EI; }
4310
4311 /// Gets the bundle.
4312 ScheduleBundle &getBundle() { return Bundle; }
4313 const ScheduleBundle &getBundle() const { return Bundle; }
4314
4315#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
4316 void dump(raw_ostream &OS) const { OS << "[Copyable]" << *getInst(); }
4317
4318 LLVM_DUMP_METHOD void dump() const {
4319 dump(dbgs());
4320 dbgs() << '\n';
4321 }
4322#endif // !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
4323
4324 private:
4325 /// true, if it has valid dependency information. These nodes always have
4326 /// only single dependency.
4327 int Dependencies = ScheduleData::InvalidDeps;
4328
4329 /// The number of dependencies minus the number of dependencies of scheduled
4330 /// instructions. As soon as this is zero, the instruction/bundle gets ready
4331 /// for scheduling.
4332 /// Note that this is negative as long as Dependencies is not calculated.
4333 int UnscheduledDeps = ScheduleData::InvalidDeps;
4334 };
4335
4336#ifndef NDEBUG
4337 friend inline raw_ostream &
4338 operator<<(raw_ostream &OS, const BoUpSLP::ScheduleCopyableData &SD) {
4339 SD.dump(OS);
4340 return OS;
4341 }
4342#endif
4343
4344 friend struct GraphTraits<BoUpSLP *>;
4345 friend struct DOTGraphTraits<BoUpSLP *>;
4346
4347 /// Contains all scheduling data for a basic block.
4348 /// It does not schedules instructions, which are not memory read/write
4349 /// instructions and their operands are either constants, or arguments, or
4350 /// phis, or instructions from others blocks, or their users are phis or from
4351 /// the other blocks. The resulting vector instructions can be placed at the
4352 /// beginning of the basic block without scheduling (if operands does not need
4353 /// to be scheduled) or at the end of the block (if users are outside of the
4354 /// block). It allows to save some compile time and memory used by the
4355 /// compiler.
4356 /// ScheduleData is assigned for each instruction in between the boundaries of
4357 /// the tree entry, even for those, which are not part of the graph. It is
4358 /// required to correctly follow the dependencies between the instructions and
4359 /// their correct scheduling. The ScheduleData is not allocated for the
4360 /// instructions, which do not require scheduling, like phis, nodes with
4361 /// extractelements/insertelements only or nodes with instructions, with
4362 /// uses/operands outside of the block.
4363 struct BlockScheduling {
4364 BlockScheduling(BasicBlock *BB)
4365 : BB(BB), ChunkSize(BB->size()), ChunkPos(ChunkSize) {}
4366
4367 void clear() {
4368 ScheduledBundles.clear();
4369 ScheduledBundlesList.clear();
4370 ScheduleCopyableDataMap.clear();
4371 ScheduleCopyableDataMapByInst.clear();
4372 ScheduleCopyableDataMapByInstUser.clear();
4373 ScheduleCopyableDataMapByUsers.clear();
4374 ReadyInsts.clear();
4375 RecalcCopyableOperandDeps.clear();
4376 IgnoredMemDeps.clear();
4377 ScheduleStart = nullptr;
4378 ScheduleEnd = nullptr;
4379 FirstLoadStoreInRegion = nullptr;
4380 LastLoadStoreInRegion = nullptr;
4381 RegionHasStackSave = false;
4382
4383 // Reduce the maximum schedule region size by the size of the
4384 // previous scheduling run.
4385 ScheduleRegionSizeLimit -= ScheduleRegionSize;
4386 if (ScheduleRegionSizeLimit < MinScheduleRegionSize)
4387 ScheduleRegionSizeLimit = MinScheduleRegionSize;
4388 ScheduleRegionSize = 0;
4389
4390 // Make a new scheduling region, i.e. all existing ScheduleData is not
4391 // in the new region yet.
4392 ++SchedulingRegionID;
4393 }
4394
4395 ScheduleData *getScheduleData(Instruction *I) {
4396 if (!I)
4397 return nullptr;
4398 if (BB != I->getParent())
4399 // Avoid lookup if can't possibly be in map.
4400 return nullptr;
4401 ScheduleData *SD = ScheduleDataMap.lookup(I);
4402 if (SD && isInSchedulingRegion(*SD))
4403 return SD;
4404 return nullptr;
4405 }
4406
4407 ScheduleData *getScheduleData(Value *V) {
4408 return getScheduleData(dyn_cast<Instruction>(V));
4409 }
4410
4411 /// Returns the ScheduleCopyableData for the given edge (user tree entry and
4412 /// operand number) and value.
4413 ScheduleCopyableData *getScheduleCopyableData(const EdgeInfo &EI,
4414 const Value *V) const {
4415 if (ScheduleCopyableDataMap.empty())
4416 return nullptr;
4417 auto It = ScheduleCopyableDataMap.find(std::make_pair(EI, V));
4418 if (It == ScheduleCopyableDataMap.end())
4419 return nullptr;
4420 ScheduleCopyableData *SD = It->getSecond().get();
4421 if (!isInSchedulingRegion(*SD))
4422 return nullptr;
4423 return SD;
4424 }
4425
4426 /// Returns the ScheduleCopyableData for the given user \p User, operand
4427 /// number and operand \p V.
4429 getScheduleCopyableData(const Value *User, unsigned OperandIdx,
4430 const Value *V) {
4431 if (ScheduleCopyableDataMapByInstUser.empty())
4432 return {};
4433 const auto It = ScheduleCopyableDataMapByInstUser.find(
4434 std::make_pair(std::make_pair(User, OperandIdx), V));
4435 if (It == ScheduleCopyableDataMapByInstUser.end())
4436 return {};
4438 for (ScheduleCopyableData *SD : It->getSecond()) {
4439 if (isInSchedulingRegion(*SD))
4440 Res.push_back(SD);
4441 }
4442 return Res;
4443 }
4444
4445 /// Returns true if all operands of the given instruction \p User are
4446 /// replaced by copyable data.
4447 /// \param User The user instruction.
4448 /// \param Op The operand, which might be replaced by the copyable data.
4449 /// \param SLP The SLP tree.
4450 /// \param NumOps The number of operands used. If the instruction uses the
4451 /// same operand several times, check for the first use, then the second,
4452 /// etc.
4453 bool areAllOperandsReplacedByCopyableData(Instruction *User,
4454 Instruction *Op, BoUpSLP &SLP,
4455 unsigned NumOps) const {
4456 assert(NumOps > 0 && "No operands");
4457 if (ScheduleCopyableDataMap.empty())
4458 return false;
4459 SmallDenseMap<TreeEntry *, unsigned> PotentiallyReorderedEntriesCount;
4460 ArrayRef<TreeEntry *> Entries = SLP.getTreeEntries(User);
4461 if (Entries.empty())
4462 return false;
4463 unsigned CurNumOps = 0;
4464 for (const Use &U : User->operands()) {
4465 if (U.get() != Op)
4466 continue;
4467 ++CurNumOps;
4468 // Check all tree entries, if they have operands replaced by copyable
4469 // data.
4470 for (TreeEntry *TE : Entries) {
4471 unsigned Inc = 0;
4472 bool IsNonSchedulableWithParentPhiNode =
4473 TE->doesNotNeedToSchedule() && TE->UserTreeIndex &&
4474 TE->UserTreeIndex.UserTE->hasState() &&
4475 TE->UserTreeIndex.UserTE->State != TreeEntry::SplitVectorize &&
4476 TE->UserTreeIndex.UserTE->getOpcode() == Instruction::PHI;
4477 // Count the number of unique phi nodes, which are the parent for
4478 // parent entry, and exit, if all the unique phis are processed.
4479 if (IsNonSchedulableWithParentPhiNode) {
4480 SmallPtrSet<Value *, 4> ParentsUniqueUsers;
4481 const TreeEntry *ParentTE = TE->UserTreeIndex.UserTE;
4482 for (Value *V : ParentTE->Scalars) {
4483 auto *PHI = dyn_cast<PHINode>(V);
4484 if (!PHI)
4485 continue;
4486 if (ParentsUniqueUsers.insert(PHI).second &&
4487 is_contained(PHI->incoming_values(), User))
4488 ++Inc;
4489 }
4490 } else {
4491 Inc = count(TE->Scalars, User);
4492 }
4493
4494 // Check if the user is commutative.
4495 // The commutatives are handled later, as their operands can be
4496 // reordered.
4497 // Same applies even for non-commutative cmps, because we can invert
4498 // their predicate potentially and, thus, reorder the operands.
4499 bool IsCommutativeUser =
4500 isCommutative(User) &&
4501 isCommutableOperand(User, User, U.getOperandNo());
4502 if (!IsCommutativeUser) {
4503 Instruction *MainOp = TE->getMatchingMainOpOrAltOp(User);
4504 IsCommutativeUser =
4505 isCommutative(MainOp, User) &&
4506 isCommutableOperand(MainOp, User, U.getOperandNo());
4507 }
4508 // The commutative user with the same operands can be safely
4509 // considered as non-commutative, operands reordering does not change
4510 // the semantics. Same for cmps with the same operands: inverting
4511 // the predicate does not change the operand columns in this case.
4512 assert(
4513 (!IsCommutativeUser ||
4514 (((isCommutative(User) && isCommutableOperand(User, User, 0) &&
4515 isCommutableOperand(User, User, 1)) ||
4516 (isCommutative(TE->getMatchingMainOpOrAltOp(User), User) &&
4517 isCommutableOperand(TE->getMatchingMainOpOrAltOp(User), User,
4518 0) &&
4519 isCommutableOperand(TE->getMatchingMainOpOrAltOp(User), User,
4520 1))))) &&
4521 "Expected commutative user with 2 first commutable operands");
4522 bool IsCommutativeWithSameOps =
4523 IsCommutativeUser && User->getOperand(0) == User->getOperand(1);
4524 if ((!IsCommutativeUser || IsCommutativeWithSameOps) &&
4525 (!isa<CmpInst>(User) ||
4526 User->getOperand(0) == User->getOperand(1))) {
4527 if (CurNumOps != NumOps)
4528 continue;
4529 // A reassociated node flattens the operand chain, so the operand
4530 // may be placed in any operand column rather than at the
4531 // instruction's operand number.
4532 if (TE->hasReassocScalars()) {
4533 bool ReplacedByCopyable = false;
4534 for (auto It = find(TE->Scalars, User); It != TE->Scalars.end();
4535 It = find(make_range(std::next(It), TE->Scalars.end()),
4536 User)) {
4537 int Lane = std::distance(TE->Scalars.begin(), It);
4538 for (unsigned OpIdx : seq<unsigned>(TE->getNumOperands()))
4539 ReplacedByCopyable |=
4540 TE->getOperand(OpIdx)[Lane] == Op &&
4541 getScheduleCopyableData(EdgeInfo(TE, OpIdx), Op);
4542 }
4543 if (ReplacedByCopyable)
4544 continue;
4545 return false;
4546 }
4547 EdgeInfo EI(TE, U.getOperandNo());
4548 if (getScheduleCopyableData(EI, Op))
4549 continue;
4550 return false;
4551 }
4552 // Only count the occurrence matching this call's NumOps.
4553 if (CurNumOps != NumOps)
4554 continue;
4555 PotentiallyReorderedEntriesCount.try_emplace(TE, 0)
4556 .first->getSecond() += Inc;
4557 }
4558 }
4559 if (PotentiallyReorderedEntriesCount.empty())
4560 return true;
4561 // Check the commutative/cmp entries.
4562 for (auto &P : PotentiallyReorderedEntriesCount) {
4563 SmallPtrSet<Value *, 4> ParentsUniqueUsers;
4564 bool IsNonSchedulableWithParentPhiNode =
4565 P.first->doesNotNeedToSchedule() && P.first->UserTreeIndex &&
4566 P.first->UserTreeIndex.UserTE->hasState() &&
4567 P.first->UserTreeIndex.UserTE->State != TreeEntry::SplitVectorize &&
4568 P.first->UserTreeIndex.UserTE->getOpcode() == Instruction::PHI;
4569 auto *It = find(P.first->Scalars, User);
4570 do {
4571 assert(It != P.first->Scalars.end() &&
4572 "User is not in the tree entry");
4573 int Lane = std::distance(P.first->Scalars.begin(), It);
4574 assert(Lane >= 0 && "Lane is not found");
4576 !P.first->ReorderIndices.empty())
4577 Lane = P.first->ReorderIndices[Lane];
4578 assert(Lane < static_cast<int>(P.first->Scalars.size()) &&
4579 "Couldn't find extract lane");
4580 // Count the number of unique phi nodes, which are the parent for
4581 // parent entry, and exit, if all the unique phis are processed.
4582 if (IsNonSchedulableWithParentPhiNode) {
4583 const TreeEntry *ParentTE = P.first->UserTreeIndex.UserTE;
4584 Value *User = ParentTE->Scalars[Lane];
4585 if (!ParentsUniqueUsers.insert(User).second) {
4586 It =
4587 find(make_range(std::next(It), P.first->Scalars.end()), User);
4588 continue;
4589 }
4590 }
4591 // Flattened nodes may place an operand in any column; scan all of
4592 // them so copyable scheduling does not double-count.
4593 for (unsigned OpIdx :
4594 seq<unsigned>(P.first->hasReassocScalars()
4595 ? P.first->getNumOperands()
4597 P.first->getMainOp()))) {
4598 if (P.first->getOperand(OpIdx)[Lane] == Op &&
4599 getScheduleCopyableData(EdgeInfo(P.first, OpIdx), Op))
4600 --P.getSecond();
4601 }
4602 // If parent node is schedulable, it will be handled correctly.
4603 It = find(make_range(std::next(It), P.first->Scalars.end()), User);
4604 } while (It != P.first->Scalars.end());
4605 }
4606 return all_of(PotentiallyReorderedEntriesCount,
4607 [&](const std::pair<const TreeEntry *, unsigned> &P) {
4608 return P.second == NumOps - 1;
4609 });
4610 }
4611
4613 getScheduleCopyableData(const Instruction *I) const {
4614 if (ScheduleCopyableDataMapByInst.empty())
4615 return {};
4616 const auto It = ScheduleCopyableDataMapByInst.find(I);
4617 if (It == ScheduleCopyableDataMapByInst.end())
4618 return {};
4620 for (ScheduleCopyableData *SD : It->getSecond()) {
4621 if (isInSchedulingRegion(*SD))
4622 Res.push_back(SD);
4623 }
4624 return Res;
4625 }
4626
4628 getScheduleCopyableDataUsers(const Instruction *User) const {
4629 if (ScheduleCopyableDataMapByUsers.empty())
4630 return {};
4631 const auto It = ScheduleCopyableDataMapByUsers.find(User);
4632 if (It == ScheduleCopyableDataMapByUsers.end())
4633 return {};
4635 for (ScheduleCopyableData *SD : It->getSecond()) {
4636 if (isInSchedulingRegion(*SD))
4637 Res.push_back(SD);
4638 }
4639 return Res;
4640 }
4641
4642 /// Reordering \p TE permutes its operand columns and may move an operand
4643 /// between the edges covered and not covered by copyable scheduling
4644 /// data, making the computed dependency counts stale. Mark the schedule
4645 /// data of \p TE's copyable-modeled operands for recalculation at the
4646 /// next bundle scheduling.
4647 void markCopyableDepsForRecalc(const TreeEntry &TE) {
4648 for (unsigned OpIdx : seq<unsigned>(TE.getNumOperands()))
4649 for (Value *V : TE.getOperand(OpIdx))
4650 if (auto *I = dyn_cast<Instruction>(V))
4651 if (ScheduleData *SD = getScheduleData(I);
4652 SD && !getScheduleCopyableData(I).empty())
4653 RecalcCopyableOperandDeps.insert(SD);
4654 }
4655
4656 ScheduleCopyableData &addScheduleCopyableData(const EdgeInfo &EI,
4657 Instruction *I,
4658 int SchedulingRegionID,
4659 ScheduleBundle &Bundle) {
4660 assert(!getScheduleCopyableData(EI, I) && "already in the map");
4661 ScheduleCopyableData *CD =
4662 ScheduleCopyableDataMap
4663 .try_emplace(std::make_pair(EI, I),
4664 std::make_unique<ScheduleCopyableData>(
4665 SchedulingRegionID, I, EI, Bundle))
4666 .first->getSecond()
4667 .get();
4668 ScheduleCopyableDataMapByInst[I].push_back(CD);
4669 if (EI.UserTE) {
4670 ArrayRef<Value *> Op = EI.UserTE->getOperand(EI.EdgeIdx);
4671 const auto *It = find(Op, I);
4672 assert(It != Op.end() && "Lane not set");
4673 SmallPtrSet<Instruction *, 4> Visited;
4674 do {
4675 int Lane = std::distance(Op.begin(), It);
4676 assert(Lane >= 0 && "Lane not set");
4677 if (isa<StoreInst, InsertValueInst>(EI.UserTE->Scalars[Lane]) &&
4678 !EI.UserTE->ReorderIndices.empty())
4679 Lane = EI.UserTE->ReorderIndices[Lane];
4680 assert(Lane < static_cast<int>(EI.UserTE->Scalars.size()) &&
4681 "Couldn't find extract lane");
4682 auto *In = cast<Instruction>(EI.UserTE->Scalars[Lane]);
4683 if (!Visited.insert(In).second) {
4684 It = find(make_range(std::next(It), Op.end()), I);
4685 continue;
4686 }
4687 ScheduleCopyableDataMapByInstUser
4688 .try_emplace(std::make_pair(std::make_pair(In, EI.EdgeIdx), I))
4689 .first->getSecond()
4690 .push_back(CD);
4691 ScheduleCopyableDataMapByUsers.try_emplace(I)
4692 .first->getSecond()
4693 .insert(CD);
4694 // Remove extra deps for users, becoming non-immediate users of the
4695 // instruction. It may happen, if the chain of same copyable elements
4696 // appears in the tree.
4697 if (In == I) {
4698 EdgeInfo UserEI = EI.UserTE->UserTreeIndex;
4699 if (ScheduleCopyableData *UserCD =
4700 getScheduleCopyableData(UserEI, In))
4701 ScheduleCopyableDataMapByUsers[I].remove(UserCD);
4702 }
4703 It = find(make_range(std::next(It), Op.end()), I);
4704 } while (It != Op.end());
4705 } else {
4706 ScheduleCopyableDataMapByUsers.try_emplace(I).first->getSecond().insert(
4707 CD);
4708 }
4709 return *CD;
4710 }
4711
4712 ArrayRef<ScheduleBundle *> getScheduleBundles(Value *V) const {
4713 auto *I = dyn_cast<Instruction>(V);
4714 if (!I)
4715 return {};
4716 auto It = ScheduledBundles.find(I);
4717 if (It == ScheduledBundles.end())
4718 return {};
4719 return It->getSecond();
4720 }
4721
4722 /// Returns true if the entity is in the scheduling region.
4723 bool isInSchedulingRegion(const ScheduleEntity &SD) const {
4724 if (const auto *Data = dyn_cast<ScheduleData>(&SD))
4725 return Data->getSchedulingRegionID() == SchedulingRegionID;
4726 if (const auto *CD = dyn_cast<ScheduleCopyableData>(&SD))
4727 return CD->getSchedulingRegionID() == SchedulingRegionID;
4728 return all_of(cast<ScheduleBundle>(SD).getBundle(),
4729 [&](const ScheduleEntity *BundleMember) {
4730 return isInSchedulingRegion(*BundleMember);
4731 });
4732 }
4733
4734 /// Marks an instruction as scheduled and puts all dependent ready
4735 /// instructions into the ready-list.
4736 template <typename ReadyListType>
4737 void schedule(const BoUpSLP &R, const InstructionsState &S,
4738 const EdgeInfo &EI, ScheduleEntity *Data,
4739 ReadyListType &ReadyList) {
4740 auto ProcessBundleMember = [&](ScheduleEntity *BundleMember,
4742 // Handle the def-use chain dependencies.
4743
4744 // Decrement the unscheduled counter and insert to ready list if ready.
4745 auto DecrUnsched = [&](auto *Data, bool IsControl = false) {
4746 if ((IsControl || Data->hasValidDependencies()) &&
4747 Data->incrementUnscheduledDeps(-1) == 0) {
4748 // There are no more unscheduled dependencies after
4749 // decrementing, so we can put the dependent instruction
4750 // into the ready list.
4751 SmallVector<ScheduleBundle *, 1> CopyableBundle;
4753 if (auto *CD = dyn_cast<ScheduleCopyableData>(Data)) {
4754 CopyableBundle.push_back(&CD->getBundle());
4755 Bundles = CopyableBundle;
4756 } else {
4757 Bundles = getScheduleBundles(Data->getInst());
4758 }
4759 if (!Bundles.empty()) {
4760 for (ScheduleBundle *Bundle : Bundles) {
4761 if (Bundle->unscheduledDepsInBundle() == 0) {
4762 assert(!Bundle->isScheduled() &&
4763 "already scheduled bundle gets ready");
4764 ReadyList.insert(Bundle);
4766 << "SLP: gets ready: " << *Bundle << "\n");
4767 }
4768 }
4769 return;
4770 }
4771 assert(!Data->isScheduled() &&
4772 "already scheduled bundle gets ready");
4774 "Expected non-copyable data");
4775 ReadyList.insert(Data);
4776 LLVM_DEBUG(dbgs() << "SLP: gets ready: " << *Data << "\n");
4777 }
4778 };
4779
4780 auto DecrUnschedForInst = [&](Instruction *User, unsigned OpIdx,
4781 Instruction *I) {
4782 if (!ScheduleCopyableDataMap.empty()) {
4784 getScheduleCopyableData(User, OpIdx, I);
4785 bool ReleasedAsCopyable = false;
4786 for (ScheduleCopyableData *CD : CopyableData) {
4787 // Copyable elements modeled on a copyable user lane depend on
4788 // the user's copyable scheduling data, not on the user itself,
4789 // and are released when that copyable data is scheduled. The
4790 // user's own schedule data still carries the def-use dependency
4791 // in this case, so it must be released below.
4792 if (CD->getEdgeInfo().UserTE->isCopyableElement(User))
4793 continue;
4794 DecrUnsched(CD, /*IsControl=*/false);
4795 ReleasedAsCopyable = true;
4796 }
4797 if (ReleasedAsCopyable)
4798 return;
4799 }
4800 if (ScheduleData *OpSD = getScheduleData(I))
4801 DecrUnsched(OpSD, /*IsControl=*/false);
4802 };
4803
4804 // If BundleMember is a vector bundle, its operands may have been
4805 // reordered during buildTree(). We therefore need to get its operands
4806 // through the TreeEntry.
4807 if (!Bundles.empty()) {
4808 auto *In = BundleMember->getInst();
4809 // Count uses of each instruction operand.
4810 SmallDenseMap<const Instruction *, unsigned> OperandsUses;
4811 unsigned TotalOpCount = 0;
4812 if (isa<ScheduleCopyableData>(BundleMember)) {
4813 // Copyable data is used only once (uses itself).
4814 TotalOpCount = OperandsUses[In] = 1;
4815 } else {
4816 for (const Use &U : In->operands()) {
4817 if (auto *I = dyn_cast<Instruction>(U.get())) {
4818 auto Res = OperandsUses.try_emplace(I, 0);
4819 unsigned ExtraDeps = 1;
4820 // Count all expanded operands in the binops.
4821 for (ScheduleBundle *Bundle : Bundles) {
4822 if (const TreeEntry *TE = Bundle->getTreeEntry()) {
4823 if (TE->isExpandedBinOp(In))
4824 ++ExtraDeps;
4825 } else if (S.isExpandedBinOp(In)) {
4826 ++ExtraDeps;
4827 }
4828 }
4829 Res.first->getSecond() += ExtraDeps;
4830 TotalOpCount += ExtraDeps;
4831 }
4832 }
4833 }
4834 // Tracks whether the bundle member instruction itself shows up in
4835 // some operand column of its node (only copyable elements modeled
4836 // through their own operands, like absorbed fmuls, do not).
4837 bool FoundInOpColumns = false;
4838 // Decrement the unscheduled counter and insert to ready list if
4839 // ready.
4840 auto DecrUnschedForInst =
4841 [&](Instruction *I, TreeEntry *UserTE, unsigned OpIdx,
4842 SmallDenseSet<std::pair<const ScheduleEntity *, unsigned>>
4843 &Checked,
4844 bool IsExpandedOperand = false,
4845 bool CopyableDepsOnly = false) {
4846 if (!ScheduleCopyableDataMap.empty()) {
4847 const EdgeInfo EI = {UserTE, OpIdx};
4848 if (ScheduleCopyableData *CD =
4849 getScheduleCopyableData(EI, I)) {
4850 if (!Checked.insert(std::make_pair(CD, OpIdx)).second)
4851 return;
4852 DecrUnsched(CD, /*IsControl=*/false);
4853 return;
4854 }
4855 }
4856 if (CopyableDepsOnly)
4857 return;
4858 auto It = OperandsUses.find(I);
4859 if (It == OperandsUses.end()) {
4860 // Column value may be a peeled intermediate, not a direct
4861 // operand of In; its deps are released when it is scheduled.
4862 LLVM_DEBUG(dbgs() << "SLP: operand " << *I
4863 << " not modeled as a direct operand of "
4864 << *In << ", skipping.\n");
4865 return;
4866 }
4867 if (It->second > 0) {
4868 if (ScheduleData *OpSD = getScheduleData(I)) {
4869 if (!IsExpandedOperand &&
4870 !Checked.insert(std::make_pair(OpSD, OpIdx)).second)
4871 return;
4872 --It->getSecond();
4873 assert(TotalOpCount > 0 && "No more operands to decrement");
4874 --TotalOpCount;
4875 DecrUnsched(OpSD, /*IsControl=*/false);
4876 } else {
4877 --It->getSecond();
4878 assert(TotalOpCount > 0 && "No more operands to decrement");
4879 --TotalOpCount;
4880 }
4881 }
4882 };
4883
4884 SmallDenseSet<std::pair<const ScheduleEntity *, unsigned>> Checked;
4885 for (ScheduleBundle *Bundle : Bundles) {
4886 if (ScheduleCopyableDataMap.empty() && TotalOpCount == 0)
4887 break;
4888 SmallPtrSet<Value *, 4> ParentsUniqueUsers;
4889 // Need to search for the lane since the tree entry can be
4890 // reordered.
4891 auto *It = find(Bundle->getTreeEntry()->Scalars, In);
4892 bool IsNonSchedulableWithParentPhiNode =
4893 Bundle->getTreeEntry()->doesNotNeedToSchedule() &&
4894 Bundle->getTreeEntry()->UserTreeIndex &&
4895 Bundle->getTreeEntry()->UserTreeIndex.UserTE->hasState() &&
4896 Bundle->getTreeEntry()->UserTreeIndex.UserTE->State !=
4897 TreeEntry::SplitVectorize &&
4898 Bundle->getTreeEntry()->UserTreeIndex.UserTE->getOpcode() ==
4899 Instruction::PHI;
4900 do {
4901 int Lane =
4902 std::distance(Bundle->getTreeEntry()->Scalars.begin(), It);
4903 assert(Lane >= 0 && "Lane not set");
4905 !Bundle->getTreeEntry()->ReorderIndices.empty())
4906 Lane = Bundle->getTreeEntry()->ReorderIndices[Lane];
4907 assert(Lane < static_cast<int>(
4908 Bundle->getTreeEntry()->Scalars.size()) &&
4909 "Couldn't find extract lane");
4910
4911 // Since vectorization tree is being built recursively this
4912 // assertion ensures that the tree entry has all operands set
4913 // before reaching this code. Couple of exceptions known at the
4914 // moment are extracts where their second (immediate) operand is
4915 // not added. Since immediates do not affect scheduler behavior
4916 // this is considered okay.
4917 assert(
4918 In &&
4920 In->getNumOperands() ==
4921 Bundle->getTreeEntry()->getNumOperands() ||
4922 (isa<ZExtInst>(In) && Bundle->getTreeEntry()->getOpcode() ==
4923 Instruction::Select) ||
4924 Bundle->getTreeEntry()->isCopyableElement(In) ||
4925 Bundle->getTreeEntry()->hasReassocScalars()) &&
4926 "Missed TreeEntry operands?");
4927
4928 // Count the number of unique phi nodes, which are the parent
4929 // entry, and handle the non-copyable deps only on the first lane
4930 // for each such phi. Copyable deps are counted per operand column
4931 // lane and are released on every lane.
4932 bool CopyableDepsOnly =
4933 IsNonSchedulableWithParentPhiNode &&
4934 !ParentsUniqueUsers
4935 .insert(Bundle->getTreeEntry()
4936 ->UserTreeIndex.UserTE->Scalars[Lane])
4937 .second;
4938
4939 // A blended-load operand node is the synthetic blend mask, not an
4940 // IR operand of the load. Use the real pointer operand for
4941 // scheduling so the def-use counters stay balanced; the mask is
4942 // available earlier through the pointer's select.
4943 bool IsBlended = Bundle->getTreeEntry()->State ==
4944 TreeEntry::BlendedLoadVectorize;
4945 for (unsigned OpIdx :
4946 seq<unsigned>(Bundle->getTreeEntry()->getNumOperands()))
4947 if (auto *I = dyn_cast<Instruction>(
4948 IsBlended ? In->getOperand(OpIdx)
4949 : Bundle->getTreeEntry()->getOperand(
4950 OpIdx)[Lane])) {
4951 FoundInOpColumns |= (I == In) && !CopyableDepsOnly;
4952 LLVM_DEBUG(dbgs() << "SLP: check for readiness (def): "
4953 << *I << "\n");
4954 DecrUnschedForInst(
4955 I, Bundle->getTreeEntry(), OpIdx, Checked,
4956 Bundle->getTreeEntry()->isExpandedOperand(In, OpIdx),
4957 /*CopyableDepsOnly=*/CopyableDepsOnly);
4958 }
4959 // If parent node is schedulable, it will be handled correctly.
4960 if (Bundle->getTreeEntry()->isCopyableElement(In))
4961 break;
4962 It = std::find(std::next(It),
4963 Bundle->getTreeEntry()->Scalars.end(), In);
4964 } while (It != Bundle->getTreeEntry()->Scalars.end());
4965 }
4966 // A copyable element absorbed into its user modeling (e.g. a
4967 // copyable fmul turned into fmuladd(a, b, -0.0)) does not appear in
4968 // the operand columns of its own node, so the scan above never
4969 // releases the schedule data of the copyable instruction itself.
4970 // Release it here to keep the unscheduled-deps counters balanced,
4971 // consuming its self-use count so the reassociated-operand release
4972 // below cannot release the same schedule data twice.
4973 if (isa<ScheduleCopyableData>(BundleMember) && !FoundInOpColumns) {
4974 auto UseIt = OperandsUses.find(In);
4975 if (UseIt != OperandsUses.end() && UseIt->second > 0) {
4976 --UseIt->getSecond();
4977 --TotalOpCount;
4978 }
4979 if (ScheduleData *OpSD = getScheduleData(In))
4980 DecrUnsched(OpSD, /*IsControl=*/false);
4981 }
4982 // Vector intrinsics may keep some arguments scalar (e.g. the
4983 // exponent of llvm.powi). Such scalar arguments are not modeled as
4984 // tree-entry operands, so the per-lane loop above never releases the
4985 // dependency that calculateDependencies() registered for the
4986 // definition feeding such an argument. Release it here to keep the
4987 // unscheduled-deps counters balanced; otherwise the operand's bundle
4988 // may never become ready and scheduling would assert.
4989 if (TotalOpCount > 0) {
4990 if (auto *CI = dyn_cast<CallInst>(In)) {
4992 for (unsigned ArgIdx : seq<unsigned>(CI->arg_size())) {
4993 if (!isVectorIntrinsicWithScalarOpAtArg(ID, ArgIdx, R.TTI))
4994 continue;
4995 auto *OpI = dyn_cast<Instruction>(CI->getArgOperand(ArgIdx));
4996 if (!OpI)
4997 continue;
4998 auto UseIt = OperandsUses.find(OpI);
4999 if (UseIt == OperandsUses.end() || UseIt->second == 0)
5000 continue;
5001 --UseIt->getSecond();
5002 --TotalOpCount;
5003 if (ScheduleData *OpSD = getScheduleData(OpI)) {
5005 << "SLP: check for readiness (scalar arg): "
5006 << *OpI << "\n");
5007 DecrUnsched(OpSD, /*IsControl=*/false);
5008 }
5009 }
5010 }
5011 // Peeled intermediates stay as direct operands but drop out of
5012 // operand columns; release their scheduling deps here.
5013 for (const ScheduleBundle *Bundle : Bundles) {
5014 if (TotalOpCount == 0)
5015 break;
5016 TreeEntry *TE = Bundle->getTreeEntry();
5017 if (!TE->hasReassocScalars())
5018 continue;
5019 for (Value *V : TE->getReassocScalars()) {
5020 auto *OpI = dyn_cast<Instruction>(V);
5021 if (!OpI)
5022 continue;
5023 auto UseIt = OperandsUses.find(OpI);
5024 if (UseIt == OperandsUses.end() || UseIt->second == 0)
5025 continue;
5026 LLVM_DEBUG(dbgs() << "SLP: check for readiness "
5027 "(reassociated operand): "
5028 << *OpI << "\n");
5029 // Copyable deps may live on per-edge ScheduleCopyableData.
5030 bool ReleasedAsCopyable = false;
5031 if (!ScheduleCopyableDataMap.empty()) {
5032 for (const Use &U : In->operands()) {
5033 if (U.get() != OpI)
5034 continue;
5035 for (ScheduleCopyableData *CD :
5036 getScheduleCopyableData(In, U.getOperandNo(), OpI)) {
5037 // Deps of reassoc scalars modeled as copyable tree
5038 // operands are released by the operand scan above;
5039 // release each remaining dep only once.
5040 if (Checked.insert(std::make_pair(CD, U.getOperandNo()))
5041 .second)
5042 DecrUnsched(CD, /*IsControl=*/false);
5043 }
5044 }
5045 // The dep is released through copyable data only if this
5046 // very entry models the scalar as a copyable operand on one
5047 // of its edges, mirroring the dependency calculation;
5048 // copyable data on some other entry's edge does not cover
5049 // the dep registered for this entry.
5050 for (auto It = find(TE->Scalars, In);
5051 It != TE->Scalars.end() && !ReleasedAsCopyable;
5052 It = find(make_range(std::next(It), TE->Scalars.end()),
5053 In)) {
5054 int Lane = std::distance(TE->Scalars.begin(), It);
5055 for (unsigned OpIdx : seq<unsigned>(TE->getNumOperands()))
5056 ReleasedAsCopyable |=
5057 TE->getOperand(OpIdx)[Lane] == OpI &&
5058 getScheduleCopyableData(EdgeInfo(TE, OpIdx), OpI);
5059 }
5060 }
5061 if (!ReleasedAsCopyable) {
5062 if (ScheduleData *OpSD = getScheduleData(OpI))
5063 for (unsigned I = 0, E = UseIt->second; I != E; ++I)
5064 DecrUnsched(OpSD, /*IsControl=*/false);
5065 }
5066 TotalOpCount -= UseIt->second;
5067 UseIt->second = 0;
5068 }
5069 }
5070 }
5071 } else {
5072 // If BundleMember is a stand-alone instruction, no operand reordering
5073 // has taken place, so we directly access its operands.
5074 for (Use &U : BundleMember->getInst()->operands()) {
5075 if (auto *I = dyn_cast<Instruction>(U.get())) {
5077 << "SLP: check for readiness (def): " << *I << "\n");
5078 DecrUnschedForInst(BundleMember->getInst(), U.getOperandNo(), I);
5079 }
5080 }
5081 }
5082 // Handle the memory dependencies.
5083 auto *SD = dyn_cast<ScheduleData>(BundleMember);
5084 if (!SD)
5085 return;
5086 SmallPtrSet<const ScheduleData *, 4> VisitedMemory;
5087 for (ScheduleData *MemoryDep : SD->getMemoryDependencies()) {
5088 if (!VisitedMemory.insert(MemoryDep).second)
5089 continue;
5090 // There are no more unscheduled dependencies after decrementing,
5091 // so we can put the dependent instruction into the ready list.
5092 LLVM_DEBUG(dbgs() << "SLP: check for readiness (mem): "
5093 << *MemoryDep << "\n");
5094 DecrUnsched(MemoryDep);
5095 }
5096 // Handle the control dependencies.
5097 SmallPtrSet<const ScheduleData *, 4> VisitedControl;
5098 for (ScheduleData *Dep : SD->getControlDependencies()) {
5099 if (!VisitedControl.insert(Dep).second)
5100 continue;
5101 // There are no more unscheduled dependencies after decrementing,
5102 // so we can put the dependent instruction into the ready list.
5104 << "SLP: check for readiness (ctrl): " << *Dep << "\n");
5105 DecrUnsched(Dep, /*IsControl=*/true);
5106 }
5107 };
5108 if (auto *SD = dyn_cast<ScheduleData>(Data)) {
5109 SD->setScheduled(/*Scheduled=*/true);
5110 LLVM_DEBUG(dbgs() << "SLP: schedule " << *SD << "\n");
5113 Instruction *In = SD->getInst();
5114 ArrayRef<TreeEntry *> Entries = R.getTreeEntries(In);
5115 if (!Entries.empty()) {
5116 for (TreeEntry *TE : Entries) {
5118 In->getNumOperands() != TE->getNumOperands() &&
5119 !TE->hasReassocScalars())
5120 continue;
5121 auto &BundlePtr =
5122 PseudoBundles.emplace_back(std::make_unique<ScheduleBundle>());
5123 BundlePtr->setTreeEntry(TE);
5124 BundlePtr->add(SD);
5125 Bundles.push_back(BundlePtr.get());
5126 }
5127 }
5128 ProcessBundleMember(SD, Bundles);
5129 } else {
5130 ScheduleBundle &Bundle = *cast<ScheduleBundle>(Data);
5131 Bundle.setScheduled(/*Scheduled=*/true);
5132 LLVM_DEBUG(dbgs() << "SLP: schedule " << Bundle << "\n");
5133 auto AreAllBundlesScheduled =
5134 [&](const ScheduleEntity *SD,
5135 ArrayRef<ScheduleBundle *> SDBundles) {
5137 return true;
5138 return !SDBundles.empty() &&
5139 all_of(SDBundles, [&](const ScheduleBundle *SDBundle) {
5140 return SDBundle->isScheduled();
5141 });
5142 };
5143 for (ScheduleEntity *SD : Bundle.getBundle()) {
5146 SDBundles = getScheduleBundles(SD->getInst());
5147 if (!AreAllBundlesScheduled(SD, SDBundles))
5148 continue;
5149 SD->setScheduled(/*Scheduled=*/true);
5150 Instruction *In = SD->getInst();
5151 // The instruction may also belong to tree entries that do not need
5152 // scheduling (e.g. all their values are used outside the block), so
5153 // no schedule bundle is registered for them. Such an entry can still
5154 // model one of this instruction's operands as a copyable element, or
5155 // model the instruction itself as an expanded binop, registered on
5156 // that non-scheduled parent edge. That dependency would never be
5157 // decremented when the instruction is scheduled through a different
5158 // bundle, leaving the operand's bundle permanently unscheduled and
5159 // tripping the unscheduled-deps assertion. Add pseudo-bundles for
5160 // these missing tree entries, so their operand dependencies are
5161 // decremented here as well. Real operand dependencies are protected
5162 // against double counting by the per-operand use counter.
5163 if (isa<ScheduleCopyableData>(SD) ||
5164 (ScheduleCopyableDataMap.empty() &&
5165 none_of(R.getTreeEntries(In), [&](const TreeEntry *TE) {
5166 return TE->isExpandedBinOp(In);
5167 }))) {
5168 ProcessBundleMember(SD, isa<ScheduleCopyableData>(SD) ? &Bundle
5169 : SDBundles);
5170 continue;
5171 }
5173 SmallVector<ScheduleBundle *> AllBundles(SDBundles.begin(),
5174 SDBundles.end());
5175 for (TreeEntry *TE : R.getTreeEntries(In)) {
5176 if (TE->isCopyableElement(In))
5177 continue;
5179 In->getNumOperands() != TE->getNumOperands() &&
5180 !TE->hasReassocScalars())
5181 continue;
5182 if (any_of(SDBundles, [&](const ScheduleBundle *SDBundle) {
5183 return SDBundle->getTreeEntry() == TE;
5184 }))
5185 continue;
5186 ScheduleBundle &PseudoBundle =
5187 *PseudoBundles.emplace_back(std::make_unique<ScheduleBundle>());
5188 PseudoBundle.setTreeEntry(TE);
5189 PseudoBundle.add(SD);
5190 AllBundles.push_back(&PseudoBundle);
5191 }
5192 ProcessBundleMember(SD, AllBundles);
5193 }
5194 }
5195 }
5196
5197 /// Verify basic self consistency properties of the data structure.
5198 void verify() {
5199 if (!ScheduleStart)
5200 return;
5201
5202 assert(ScheduleStart->getParent() == ScheduleEnd->getParent() &&
5203 ScheduleStart->comesBefore(ScheduleEnd) &&
5204 "Not a valid scheduling region?");
5205
5206 for (auto *I = ScheduleStart; I != ScheduleEnd; I = I->getNextNode()) {
5207 ArrayRef<ScheduleBundle *> Bundles = getScheduleBundles(I);
5208 if (!Bundles.empty()) {
5209 for (ScheduleBundle *Bundle : Bundles) {
5210 assert(isInSchedulingRegion(*Bundle) &&
5211 "primary schedule data not in window?");
5212 Bundle->verify();
5213 }
5214 continue;
5215 }
5216 auto *SD = getScheduleData(I);
5217 if (!SD)
5218 continue;
5219 assert(isInSchedulingRegion(*SD) &&
5220 "primary schedule data not in window?");
5221 SD->verify();
5222 }
5223
5224 assert(all_of(ReadyInsts,
5225 [](const ScheduleEntity *Bundle) {
5226 return Bundle->isReady();
5227 }) &&
5228 "item in ready list not ready?");
5229 }
5230
5231 /// Put all instructions into the ReadyList which are ready for scheduling.
5232 template <typename ReadyListType>
5233 void initialFillReadyList(ReadyListType &ReadyList) {
5234 SmallPtrSet<ScheduleBundle *, 16> Visited;
5235 for (auto *I = ScheduleStart; I != ScheduleEnd; I = I->getNextNode()) {
5236 ScheduleData *SD = getScheduleData(I);
5237 if (SD && SD->hasValidDependencies() && SD->isReady()) {
5238 if (ArrayRef<ScheduleBundle *> Bundles = getScheduleBundles(I);
5239 !Bundles.empty()) {
5240 for (ScheduleBundle *Bundle : Bundles) {
5241 if (!Visited.insert(Bundle).second)
5242 continue;
5243 if (Bundle->hasValidDependencies() && Bundle->isReady()) {
5244 ReadyList.insert(Bundle);
5245 LLVM_DEBUG(dbgs() << "SLP: initially in ready list: "
5246 << *Bundle << "\n");
5247 }
5248 }
5249 continue;
5250 }
5251 ReadyList.insert(SD);
5253 << "SLP: initially in ready list: " << *SD << "\n");
5254 }
5255 }
5256 }
5257
5258 /// Build a bundle from the ScheduleData nodes corresponding to the
5259 /// scalar instruction for each lane.
5260 /// \param VL The list of scalar instructions.
5261 /// \param S The state of the instructions.
5262 /// \param EI The edge in the SLP graph or the user node/operand number.
5263 ScheduleBundle &buildBundle(ArrayRef<Value *> VL,
5264 const InstructionsState &S, const EdgeInfo &EI);
5265
5266 /// Checks if a bundle of instructions can be scheduled, i.e. has no
5267 /// cyclic dependencies. This is only a dry-run, no instructions are
5268 /// actually moved at this stage.
5269 /// \returns the scheduling bundle. The returned Optional value is not
5270 /// std::nullopt if \p VL is allowed to be scheduled.
5271 std::optional<ScheduleBundle *>
5272 tryScheduleBundle(ArrayRef<Value *> VL, BoUpSLP *SLP,
5273 const InstructionsState &S, const EdgeInfo &EI);
5274
5275 /// Allocates schedule data chunk.
5276 ScheduleData *allocateScheduleDataChunks();
5277
5278 /// Extends the scheduling region so that V is inside the region.
5279 /// \returns true if the region size is within the limit.
5280 bool extendSchedulingRegion(Value *V, const InstructionsState &S);
5281
5282 /// Initialize the ScheduleData structures for new instructions in the
5283 /// scheduling region.
5284 void initScheduleData(Instruction *FromI, Instruction *ToI,
5285 ScheduleData *PrevLoadStore,
5286 ScheduleData *NextLoadStore);
5287
5288 /// Updates the dependency information of a bundle and of all instructions/
5289 /// bundles which depend on the original bundle.
5290 void calculateDependencies(ScheduleBundle &Bundle, bool InsertInReadyList,
5291 BoUpSLP *SLP,
5292 const SmallPtrSetImpl<Value *> &ExpandedOps,
5293 ArrayRef<ScheduleData *> ControlDeps = {});
5294
5295 /// Sets all instruction in the scheduling region to un-scheduled.
5296 void resetSchedule();
5297
5298 BasicBlock *BB;
5299
5300 /// Simple memory allocation for ScheduleData.
5302
5303 /// The size of a ScheduleData array in ScheduleDataChunks.
5304 int ChunkSize;
5305
5306 /// The allocator position in the current chunk, which is the last entry
5307 /// of ScheduleDataChunks.
5308 int ChunkPos;
5309
5310 /// Attaches ScheduleData to Instruction.
5311 /// Note that the mapping survives during all vectorization iterations, i.e.
5312 /// ScheduleData structures are recycled.
5313 SmallDenseMap<Instruction *, ScheduleData *> ScheduleDataMap;
5314
5315 /// Attaches ScheduleCopyableData to EdgeInfo (UserTreeEntry + operand
5316 /// number) and the operand instruction, represented as copyable element.
5317 SmallDenseMap<std::pair<EdgeInfo, const Value *>,
5318 std::unique_ptr<ScheduleCopyableData>>
5319 ScheduleCopyableDataMap;
5320
5321 /// Represents mapping between instruction and all related
5322 /// ScheduleCopyableData (for all uses in the tree, represenedt as copyable
5323 /// element). The SLP tree may contain several representations of the same
5324 /// instruction.
5325 SmallDenseMap<const Instruction *, SmallVector<ScheduleCopyableData *>>
5326 ScheduleCopyableDataMapByInst;
5327
5328 /// Represents mapping between user value and operand number, the operand
5329 /// value and all related ScheduleCopyableData. The relation is 1:n, because
5330 /// the same user may refernce the same operand in different tree entries
5331 /// and the operand may be modelled by the different copyable data element.
5332 SmallDenseMap<std::pair<std::pair<const Value *, unsigned>, const Value *>,
5334 ScheduleCopyableDataMapByInstUser;
5335
5336 /// Represents mapping between instruction and all related
5337 /// ScheduleCopyableData. It represents the mapping between the actual
5338 /// instruction and the last copyable data element in the chain. E.g., if
5339 /// the graph models the following instructions:
5340 /// %0 = non-add instruction ...
5341 /// ...
5342 /// %4 = add %3, 1
5343 /// %5 = add %4, 1
5344 /// %6 = insertelement poison, %0, 0
5345 /// %7 = insertelement %6, %5, 1
5346 /// And the graph is modeled as:
5347 /// [%5, %0] -> [%4, copyable %0 <0> ] -> [%3, copyable %0 <1> ]
5348 /// -> [1, 0] -> [%1, 0]
5349 ///
5350 /// this map will map %0 only to the copyable element <1>, which is the last
5351 /// user (direct user of the actual instruction). <0> uses <1>, so <1> will
5352 /// keep the map to <0>, not the %0.
5353 SmallDenseMap<const Instruction *,
5354 SmallSetVector<ScheduleCopyableData *, 4>>
5355 ScheduleCopyableDataMapByUsers;
5356
5357 /// Attaches ScheduleBundle to Instruction.
5358 SmallDenseMap<Instruction *, SmallVector<ScheduleBundle *>>
5359 ScheduledBundles;
5360 /// The list of ScheduleBundles.
5361 SmallVector<std::unique_ptr<ScheduleBundle>> ScheduledBundlesList;
5362
5363 /// The ready-list for scheduling (only used for the dry-run).
5364 SetVector<ScheduleEntity *> ReadyInsts;
5365
5366 /// The first instruction of the scheduling region.
5367 Instruction *ScheduleStart = nullptr;
5368
5369 /// The first instruction _after_ the scheduling region.
5370 Instruction *ScheduleEnd = nullptr;
5371
5372 /// The first memory accessing instruction in the scheduling region
5373 /// (can be null).
5374 ScheduleData *FirstLoadStoreInRegion = nullptr;
5375
5376 /// The last memory accessing instruction in the scheduling region
5377 /// (can be null).
5378 ScheduleData *LastLoadStoreInRegion = nullptr;
5379
5380 /// Is there an llvm.stacksave or llvm.stackrestore in the scheduling
5381 /// region? Used to optimize the dependence calculation for the
5382 /// common case where there isn't.
5383 bool RegionHasStackSave = false;
5384
5385 /// The current size of the scheduling region.
5386 int ScheduleRegionSize = 0;
5387
5388 /// The maximum size allowed for the scheduling region.
5389 int ScheduleRegionSizeLimit = ScheduleRegionSizeBudget;
5390
5391 /// Operands that are modeled as copyable elements in a previously built
5392 /// vectorized node and that are used directly by another,
5393 /// not-yet-registered node sharing a schedulable instruction with it. Their
5394 /// direct dependencies must be recomputed at the next bundle scheduling,
5395 /// when the new node is already registered in the tree, so that the direct
5396 /// use is accounted for. If the new node is the last scheduled bundle and
5397 /// no further scheduling consumes this list, the leftover entries are
5398 /// dropped on the next region reset and the dependencies are recomputed
5399 /// against the full tree in scheduleBlock instead. A set is used to avoid
5400 /// recomputing the same operand more than once.
5401 SmallSetVector<ScheduleData *, 8> RecalcCopyableOperandDeps;
5402
5403 /// Ordered pairs (Src, Dst) of memory instructions whose may-alias
5404 /// dependency has been dropped in favor of a runtime alias check.
5405 SmallDenseSet<std::pair<Instruction *, Instruction *>, 8> IgnoredMemDeps;
5406
5407 /// The ID of the scheduling region. For a new vectorization iteration this
5408 /// is incremented which "removes" all ScheduleData from the region.
5409 /// Make sure that the initial SchedulingRegionID is greater than the
5410 /// initial SchedulingRegionID in ScheduleData (which is 0).
5411 int SchedulingRegionID = 1;
5412 };
5413
5414 /// Attaches the BlockScheduling structures to basic blocks.
5415 MapVector<BasicBlock *, std::unique_ptr<BlockScheduling>> BlocksSchedules;
5416
5417 /// Performs the "real" scheduling. Done before vectorization is actually
5418 /// performed in a basic block.
5419 void scheduleBlock(const BoUpSLP &R, BlockScheduling *BS);
5420
5421 /// List of users to ignore during scheduling and that don't need extracting.
5422 const SmallDenseSet<Value *> *UserIgnoreList = nullptr;
5423
5424 /// Narrowed reduction chain instructions, dropped together with the
5425 /// reduction. Subset of UserIgnoreList.
5426 SmallPtrSet<Value *, 4> NarrowedChainInsts;
5427
5428 /// A DenseMapInfo implementation for holding DenseMaps and DenseSets of
5429 /// sorted SmallVectors of unsigned.
5430 struct OrdersTypeDenseMapInfo {
5431 static unsigned getHashValue(const OrdersType &V) {
5432 return static_cast<unsigned>(hash_combine_range(V));
5433 }
5434
5435 static bool isEqual(const OrdersType &LHS, const OrdersType &RHS) {
5436 return LHS == RHS;
5437 }
5438 };
5439
5440 // Analysis and block reference.
5441 Function *F;
5442 ScalarEvolution *SE;
5443 TargetTransformInfo *TTI;
5444 TargetLibraryInfo *TLI;
5445 LoopInfo *LI;
5446 DominatorTree *DT;
5447 AssumptionCache *AC;
5448 DemandedBits *DB;
5449 const DataLayout *DL;
5450 OptimizationRemarkEmitter *ORE;
5451 /// Cached cost-model mode for this function.
5452 /// If -Os/-Oz, use CodeSize. Otherwise use RecipThroughput.
5454
5455 unsigned MaxVecRegSize; // This is set by TTI or overridden by cl::opt.
5456 unsigned MinVecRegSize; // Set by cl::opt (default: 128).
5457
5458 /// Instruction builder to construct the vectorized tree.
5459 IRBuilder<TargetFolder> Builder;
5460
5461 /// A map of scalar integer values to the smallest bit width with which they
5462 /// can legally be represented. The values map to (width, signed) pairs,
5463 /// where "width" indicates the minimum bit width and "signed" is True if the
5464 /// value must be signed-extended, rather than zero-extended, back to its
5465 /// original width.
5466 DenseMap<const TreeEntry *, std::pair<uint64_t, bool>> MinBWs;
5467
5468 /// Final size of the reduced vector, if the current graph represents the
5469 /// input for the reduction and it was possible to narrow the size of the
5470 /// reduction.
5471 unsigned ReductionBitWidth = 0;
5472
5473 /// Canonical graph size before the transformations.
5474 unsigned BaseGraphSize = 1;
5475
5476 /// If the tree contains any zext/sext/trunc nodes, contains max-min pair of
5477 /// type sizes, used in the tree.
5478 std::optional<std::pair<unsigned, unsigned>> CastMaxMinBWSizes;
5479
5480 /// Indices of the vectorized nodes, which supposed to be the roots of the new
5481 /// bitwidth analysis attempt, like trunc, IToFP or ICmp.
5482 DenseSet<unsigned> ExtraBitWidthNodes;
5483};
5484
5485template <> struct llvm::DenseMapInfo<BoUpSLP::EdgeInfo> {
5488 static unsigned getHashValue(const BoUpSLP::EdgeInfo &Val) {
5489 return detail::combineHashValue(FirstInfo::getHashValue(Val.UserTE),
5490 SecondInfo::getHashValue(Val.EdgeIdx));
5491 }
5492
5493 static bool isEqual(const BoUpSLP::EdgeInfo &LHS,
5494 const BoUpSLP::EdgeInfo &RHS) {
5495 return LHS == RHS;
5496 }
5497};
5498
5499template <> struct llvm::GraphTraits<BoUpSLP *> {
5500 using TreeEntry = BoUpSLP::TreeEntry;
5501
5502 /// NodeRef has to be a pointer per the GraphWriter.
5504
5505 using ContainerTy = BoUpSLP::TreeEntry::VecTreeTy;
5506
5507 /// Add the VectorizableTree to the index iterator to be able to return
5508 /// TreeEntry pointers.
5510 : public iterator_adaptor_base<
5511 ChildIteratorType, SmallVector<BoUpSLP::EdgeInfo, 1>::iterator> {
5513
5517
5518 NodeRef operator*() { return I->UserTE; }
5519 };
5520
5521 static NodeRef getEntryNode(BoUpSLP &R) { return &R.getRootNode(); }
5522
5524 return {&N->UserTreeIndex, N->Container};
5525 }
5526
5528 return {&N->UserTreeIndex + 1, N->Container};
5529 }
5530
5531 /// For the node iterator we just need to turn the TreeEntry iterator into a
5532 /// TreeEntry* iterator so that it dereferences to NodeRef.
5534 using ItTy = ContainerTy::iterator;
5535 ItTy It;
5536
5537 public:
5538 nodes_iterator(const ItTy &It2) : It(It2) {}
5539 NodeRef operator*() { return It->get(); }
5541 ++It;
5542 return *this;
5543 }
5544 bool operator!=(const nodes_iterator &N2) const { return N2.It != It; }
5545 };
5546
5548 return nodes_iterator(R->VectorizableTree.begin());
5549 }
5550
5552 return nodes_iterator(R->VectorizableTree.end());
5553 }
5554
5555 static unsigned size(BoUpSLP *R) { return R->VectorizableTree.size(); }
5556};
5557
5558template <>
5560 using TreeEntry = BoUpSLP::TreeEntry;
5561
5562 DOTGraphTraits(bool IsSimple = false) : DefaultDOTGraphTraits(IsSimple) {}
5563
5564 std::string getNodeLabel(const TreeEntry *Entry, const BoUpSLP *R) {
5565 std::string Str;
5566 raw_string_ostream OS(Str);
5567 OS << Entry->Idx << ".\n";
5568 if (isSplat(Entry->Scalars))
5569 OS << "<splat> ";
5570 for (auto *V : Entry->Scalars) {
5571 OS << *V;
5572 if (llvm::any_of(R->ExternalUses, [&](const BoUpSLP::ExternalUser &EU) {
5573 return EU.Scalar == V;
5574 }))
5575 OS << " <extract>";
5576 OS << "\n";
5577 }
5578 return Str;
5579 }
5580
5581 static std::string getNodeAttributes(const TreeEntry *Entry,
5582 const BoUpSLP *) {
5583 if (Entry->isGather())
5584 return "color=red";
5585 if (Entry->State == TreeEntry::ScatterVectorize ||
5586 Entry->State == TreeEntry::StridedVectorize ||
5587 Entry->State == TreeEntry::ExpandVectorize ||
5588 Entry->State == TreeEntry::CompressVectorize ||
5589 Entry->State == TreeEntry::BlendedLoadVectorize)
5590 return "color=blue";
5591 return "";
5592 }
5593};
5594
5597 for (auto *I : DeletedInstructions) {
5598 if (!I->getParent()) {
5599 // Temporarily insert instruction back to erase them from parent and
5600 // memory later.
5601 if (isa<PHINode>(I))
5602 // Phi nodes must be the very first instructions in the block.
5603 I->insertBefore(F->getEntryBlock(),
5604 F->getEntryBlock().getFirstNonPHIIt());
5605 else
5606 I->insertBefore(F->getEntryBlock().getTerminator()->getIterator());
5607 continue;
5608 }
5609 for (Use &U : I->operands()) {
5610 auto *Op = dyn_cast<Instruction>(U.get());
5611 if (Op && !DeletedInstructions.count(Op) && Op->hasOneUser() &&
5613 DeadInsts.emplace_back(Op);
5614 }
5615 I->dropAllReferences();
5616 }
5617 for (auto *I : DeletedInstructions) {
5618 assert(I->use_empty() &&
5619 "trying to erase instruction with users.");
5620 I->eraseFromParent();
5621 }
5622
5623 // Cleanup any dead scalar code feeding the vectorized instructions
5625
5626#ifdef EXPENSIVE_CHECKS
5627 // If we could guarantee that this call is not extremely slow, we could
5628 // remove the ifdef limitation (see PR47712).
5629 assert(!verifyFunction(*F, &dbgs()));
5630#endif
5631}
5632
5633/// Reorders the given \p Reuses mask according to the given \p Mask. \p Reuses
5634/// contains original mask for the scalars reused in the node. Procedure
5635/// transform this mask in accordance with the given \p Mask.
5637 assert(!Mask.empty() && Reuses.size() == Mask.size() &&
5638 "Expected non-empty mask.");
5639 SmallVector<int> Prev(Reuses.begin(), Reuses.end());
5640 Prev.swap(Reuses);
5641 for (unsigned I = 0, E = Prev.size(); I < E; ++I)
5642 if (Mask[I] != PoisonMaskElem)
5643 Reuses[Mask[I]] = Prev[I];
5644}
5645
5646/// Reorders the given \p Order according to the given \p Mask. \p Order - is
5647/// the original order of the scalars. Procedure transforms the provided order
5648/// in accordance with the given \p Mask. If the resulting \p Order is just an
5649/// identity order, \p Order is cleared.
5651 bool BottomOrder = false) {
5652 assert(!Mask.empty() && "Expected non-empty mask.");
5653 unsigned Sz = Mask.size();
5654 if (BottomOrder) {
5655 SmallVector<unsigned> PrevOrder;
5656 if (Order.empty()) {
5657 PrevOrder.resize(Sz);
5658 std::iota(PrevOrder.begin(), PrevOrder.end(), 0);
5659 } else {
5660 PrevOrder.swap(Order);
5661 }
5662 Order.assign(Sz, Sz);
5663 for (unsigned I = 0; I < Sz; ++I)
5664 if (Mask[I] != PoisonMaskElem)
5665 Order[I] = PrevOrder[Mask[I]];
5666 if (all_of(enumerate(Order), [&](const auto &Data) {
5667 return Data.value() == Sz || Data.index() == Data.value();
5668 })) {
5669 Order.clear();
5670 return;
5671 }
5672 fixupOrderingIndices(Order);
5673 return;
5674 }
5675 SmallVector<int> MaskOrder;
5676 if (Order.empty()) {
5677 MaskOrder.resize(Sz);
5678 std::iota(MaskOrder.begin(), MaskOrder.end(), 0);
5679 } else {
5680 inversePermutation(Order, MaskOrder);
5681 }
5682 reorderReuses(MaskOrder, Mask);
5683 if (ShuffleVectorInst::isIdentityMask(MaskOrder, Sz)) {
5684 Order.clear();
5685 return;
5686 }
5687 Order.assign(Sz, Sz);
5688 for (unsigned I = 0; I < Sz; ++I)
5689 if (MaskOrder[I] != PoisonMaskElem)
5690 Order[MaskOrder[I]] = I;
5691 fixupOrderingIndices(Order);
5692}
5693
5694std::optional<BoUpSLP::OrdersType>
5695BoUpSLP::findReusedOrderedScalars(const BoUpSLP::TreeEntry &TE,
5696 bool TopToBottom, bool IgnoreReorder) {
5697 assert(TE.isGather() && "Expected gather node only.");
5698 // Try to find subvector extract/insert patterns and reorder only such
5699 // patterns.
5700 SmallVector<Value *> GatheredScalars(TE.Scalars.begin(), TE.Scalars.end());
5701 Type *ScalarTy = GatheredScalars.front()->getType();
5702 size_t NumScalars = GatheredScalars.size();
5703 if (!isValidElementType(ScalarTy, SLPReVec))
5704 return std::nullopt;
5705 auto *VecTy = getWidenedType(ScalarTy, NumScalars);
5706 unsigned NumParts = getNumberOfParts(VecTy, ScalarTy, NumScalars);
5707 SmallVector<int> ExtractMask;
5708 SmallVector<int> Mask;
5711 tryToGatherExtractElements(GatheredScalars, ExtractMask, NumParts);
5713 isGatherShuffledEntry(&TE, GatheredScalars, Mask, Entries, NumParts,
5714 /*ForOrder=*/true);
5715 // No shuffled operands - ignore.
5716 if (GatherShuffles.empty() && ExtractShuffles.empty())
5717 return std::nullopt;
5718 OrdersType CurrentOrder(NumScalars, NumScalars);
5719 if (GatherShuffles.size() == 1 &&
5720 *GatherShuffles.front() == TTI::SK_PermuteSingleSrc &&
5721 Entries.front().front()->isSame(TE.Scalars)) {
5722 // If the full matched node in whole tree rotation - no need to consider the
5723 // matching order, rotating the whole tree.
5724 if (TopToBottom)
5725 return std::nullopt;
5726 // No need to keep the order for the same user node.
5727 if (Entries.front().front()->UserTreeIndex.UserTE ==
5728 TE.UserTreeIndex.UserTE)
5729 return std::nullopt;
5730 // No need to keep the order for the matched root node, if it can be freely
5731 // reordered.
5732 if (!IgnoreReorder && Entries.front().front()->Idx == 0)
5733 return std::nullopt;
5734 // If shuffling 2 elements only and the matching node has reverse reuses -
5735 // no need to count order, both work fine.
5736 if (!Entries.front().front()->ReuseShuffleIndices.empty() &&
5737 TE.getVectorFactor() == 2 && Mask.size() == 2 &&
5738 any_of(enumerate(Entries.front().front()->ReuseShuffleIndices),
5739 [](const auto &P) {
5740 return P.value() % 2 != static_cast<int>(P.index()) % 2;
5741 }))
5742 return std::nullopt;
5743
5744 // Perfect match in the graph, will reuse the previously vectorized
5745 // node. Cost is 0.
5746 std::iota(CurrentOrder.begin(), CurrentOrder.end(), 0);
5747 return CurrentOrder;
5748 }
5749 auto IsSplatMask = [](ArrayRef<int> Mask) {
5750 int SingleElt = PoisonMaskElem;
5751 return all_of(Mask, [&](int I) {
5752 if (SingleElt == PoisonMaskElem && I != PoisonMaskElem)
5753 SingleElt = I;
5754 return I == PoisonMaskElem || I == SingleElt;
5755 });
5756 };
5757 // Exclusive broadcast mask - ignore.
5758 if ((ExtractShuffles.empty() && IsSplatMask(Mask) &&
5759 (Entries.size() != 1 ||
5760 Entries.front().front()->ReorderIndices.empty())) ||
5761 (GatherShuffles.empty() && IsSplatMask(ExtractMask)))
5762 return std::nullopt;
5763 SmallBitVector ShuffledSubMasks(NumParts);
5764 auto TransformMaskToOrder = [&](MutableArrayRef<unsigned> CurrentOrder,
5765 ArrayRef<int> Mask, int PartSz, int NumParts,
5766 function_ref<unsigned(unsigned)> GetVF) {
5767 for (int I : seq<int>(NumParts)) {
5768 if (ShuffledSubMasks.test(I))
5769 continue;
5770 const int VF = GetVF(I);
5771 if (VF == 0)
5772 continue;
5773 unsigned Limit = getNumElems(CurrentOrder.size(), PartSz, I);
5774 MutableArrayRef<unsigned> Slice = CurrentOrder.slice(I * PartSz, Limit);
5775 // Shuffle of at least 2 vectors - ignore.
5776 if (any_of(Slice, not_equal_to(NumScalars))) {
5777 llvm::fill(Slice, NumScalars);
5778 ShuffledSubMasks.set(I);
5779 continue;
5780 }
5781 // Try to include as much elements from the mask as possible.
5782 int FirstMin = INT_MAX;
5783 int SecondVecFound = false;
5784 for (int K : seq<int>(Limit)) {
5785 int Idx = Mask[I * PartSz + K];
5786 if (Idx == PoisonMaskElem) {
5787 Value *V = GatheredScalars[I * PartSz + K];
5788 if (isConstant(V) && !isa<PoisonValue>(V)) {
5789 SecondVecFound = true;
5790 break;
5791 }
5792 continue;
5793 }
5794 if (Idx < VF) {
5795 if (FirstMin > Idx)
5796 FirstMin = Idx;
5797 } else {
5798 SecondVecFound = true;
5799 break;
5800 }
5801 }
5802 FirstMin = (FirstMin / PartSz) * PartSz;
5803 // Shuffle of at least 2 vectors - ignore.
5804 if (SecondVecFound) {
5805 llvm::fill(Slice, NumScalars);
5806 ShuffledSubMasks.set(I);
5807 continue;
5808 }
5809 for (int K : seq<int>(Limit)) {
5810 int Idx = Mask[I * PartSz + K];
5811 if (Idx == PoisonMaskElem)
5812 continue;
5813 Idx -= FirstMin;
5814 if (Idx >= PartSz) {
5815 // Cross-part / second-vector reference: this slice cannot be
5816 // ordered as a single first-vector permutation, give up.
5817 SecondVecFound = true;
5818 break;
5819 }
5820 // For the last partial slice, Limit < PartSz and Idx in [Limit,
5821 // PartSz) addresses the unused padded tail (no scalar at that
5822 // position). Skip the write but keep ordering the remaining K's.
5823 if (static_cast<unsigned>(I * PartSz + Idx) >= CurrentOrder.size())
5824 continue;
5825 if (CurrentOrder[I * PartSz + Idx] >
5826 static_cast<unsigned>(I * PartSz + K) &&
5827 CurrentOrder[I * PartSz + Idx] !=
5828 static_cast<unsigned>(I * PartSz + Idx))
5829 CurrentOrder[I * PartSz + Idx] = I * PartSz + K;
5830 }
5831 // Shuffle of at least 2 vectors - ignore.
5832 if (SecondVecFound) {
5833 llvm::fill(Slice, NumScalars);
5834 ShuffledSubMasks.set(I);
5835 continue;
5836 }
5837 }
5838 };
5839 int PartSz = getPartNumElems(NumScalars, NumParts);
5840 if (!ExtractShuffles.empty())
5841 TransformMaskToOrder(
5842 CurrentOrder, ExtractMask, PartSz, NumParts, [&](unsigned I) {
5843 if (I >= ExtractShuffles.size() || !ExtractShuffles[I])
5844 return 0U;
5845 unsigned VF = 0;
5846 unsigned Sz = getNumElems(TE.getVectorFactor(), PartSz, I);
5847 for (unsigned Idx : seq<unsigned>(Sz)) {
5848 int K = I * PartSz + Idx;
5849 if (static_cast<unsigned>(K) >= ExtractMask.size())
5850 break;
5851 if (ExtractMask[K] == PoisonMaskElem)
5852 continue;
5853 if (!TE.ReuseShuffleIndices.empty())
5854 K = TE.ReuseShuffleIndices[K];
5855 if (K == PoisonMaskElem)
5856 continue;
5857 if (!TE.ReorderIndices.empty())
5858 K = std::distance(TE.ReorderIndices.begin(),
5859 find(TE.ReorderIndices, K));
5860 auto *EI = dyn_cast<ExtractElementInst>(TE.Scalars[K]);
5861 if (!EI)
5862 continue;
5863 VF = std::max(VF, EI->getVectorOperandType()
5864 ->getElementCount()
5865 .getKnownMinValue());
5866 }
5867 return VF;
5868 });
5869 // Check special corner case - single shuffle of the same entry.
5870 if (GatherShuffles.size() == 1 && NumParts != 1) {
5871 if (ShuffledSubMasks.any())
5872 return std::nullopt;
5873 PartSz = NumScalars;
5874 NumParts = 1;
5875 }
5876 if (!Entries.empty())
5877 TransformMaskToOrder(CurrentOrder, Mask, PartSz, NumParts, [&](unsigned I) {
5878 if (I >= GatherShuffles.size() || !GatherShuffles[I])
5879 return 0U;
5880 return std::max(Entries[I].front()->getVectorFactor(),
5881 Entries[I].back()->getVectorFactor());
5882 });
5883 unsigned NumUndefs = count(CurrentOrder, NumScalars);
5884 if (ShuffledSubMasks.all() || (NumScalars > 2 && NumUndefs >= NumScalars / 2))
5885 return std::nullopt;
5886 return std::move(CurrentOrder);
5887}
5888
5889static bool arePointersCompatible(Value *Ptr1, Value *Ptr2,
5890 const TargetLibraryInfo &TLI,
5891 bool CompareOpcodes = true) {
5894 return false;
5895 auto *GEP1 = dyn_cast<GetElementPtrInst>(Ptr1);
5896 auto *GEP2 = dyn_cast<GetElementPtrInst>(Ptr2);
5897 return (!GEP1 || GEP1->getNumOperands() == 2) &&
5898 (!GEP2 || GEP2->getNumOperands() == 2) &&
5899 (((!GEP1 || isConstant(GEP1->getOperand(1))) &&
5900 (!GEP2 || isConstant(GEP2->getOperand(1)))) ||
5901 !CompareOpcodes ||
5902 (GEP1 && GEP2 &&
5903 getSameOpcode({GEP1->getOperand(1), GEP2->getOperand(1)}, TLI)));
5904}
5905
5906/// Calculates minimal alignment as a common alignment.
5907template <typename T>
5909 Align CommonAlignment = cast<T>(VL.consume_front())->getAlign();
5910 for (Value *V : VL)
5911 CommonAlignment = std::min(CommonAlignment, cast<T>(V)->getAlign());
5912 return CommonAlignment;
5913}
5914
5915/// Check if \p Order represents reverse order.
5917 assert(!Order.empty() &&
5918 "Order is empty. Please check it before using isReverseOrder.");
5919 unsigned Sz = Order.size();
5920 return all_of(enumerate(Order), [&](const auto &Pair) {
5921 return Pair.value() == Sz || Sz - Pair.index() - 1 == Pair.value();
5922 });
5923}
5924
5925/// Checks if the provided list of pointers \p Pointers represents the strided
5926/// pointers for type ElemTy. If they are not, nullptr is returned.
5927/// Otherwise, SCEV* of the stride value is returned.
5928/// If `PointerOps` can be rearanged into the following sequence:
5929/// ```
5930/// %x + c_0 * stride,
5931/// %x + c_1 * stride,
5932/// %x + c_2 * stride
5933/// ...
5934/// ```
5935/// where each `c_i` is constant. The SCEV of the `stride` will be returned.
5936static const SCEV *calculateRtStride(ArrayRef<Value *> PointerOps, Type *ElemTy,
5937 const DataLayout &DL, ScalarEvolution &SE,
5938 SmallVectorImpl<unsigned> &SortedIndices) {
5940 const SCEV *PtrSCEVLowest = nullptr;
5941 const SCEV *PtrSCEVHighest = nullptr;
5942 // Find lower/upper pointers from the PointerOps (i.e. with lowest and highest
5943 // addresses).
5944 for (Value *Ptr : PointerOps) {
5945 const SCEV *PtrSCEV = SE.getSCEV(Ptr);
5946 if (!PtrSCEV)
5947 return nullptr;
5948 SCEVs.push_back(PtrSCEV);
5949 if (!PtrSCEVLowest && !PtrSCEVHighest) {
5950 PtrSCEVLowest = PtrSCEVHighest = PtrSCEV;
5951 continue;
5952 }
5953 const SCEV *Diff = SE.getMinusSCEV(PtrSCEV, PtrSCEVLowest);
5954 if (isa<SCEVCouldNotCompute>(Diff))
5955 return nullptr;
5956 if (Diff->isNonConstantNegative()) {
5957 PtrSCEVLowest = PtrSCEV;
5958 continue;
5959 }
5960 const SCEV *Diff1 = SE.getMinusSCEV(PtrSCEVHighest, PtrSCEV);
5961 if (isa<SCEVCouldNotCompute>(Diff1))
5962 return nullptr;
5963 if (Diff1->isNonConstantNegative()) {
5964 PtrSCEVHighest = PtrSCEV;
5965 continue;
5966 }
5967 }
5968 // Dist = PtrSCEVHighest - PtrSCEVLowest;
5969 const SCEV *Dist = SE.getMinusSCEV(PtrSCEVHighest, PtrSCEVLowest);
5970 if (isa<SCEVCouldNotCompute>(Dist))
5971 return nullptr;
5972 int Size = DL.getTypeStoreSize(ElemTy);
5973 auto TryGetStride = [&](const SCEV *Dist,
5974 const SCEV *Multiplier) -> const SCEV * {
5975 if (const auto *M = dyn_cast<SCEVMulExpr>(Dist)) {
5976 if (M->getOperand(0) == Multiplier)
5977 return M->getOperand(1);
5978 if (M->getOperand(1) == Multiplier)
5979 return M->getOperand(0);
5980 return nullptr;
5981 }
5982 if (Multiplier == Dist)
5983 return SE.getConstant(Dist->getType(), 1);
5984 return SE.getUDivExactExpr(Dist, Multiplier);
5985 };
5986 // Stride_in_elements = Dist / element_size * (num_elems - 1).
5987 const SCEV *Stride = nullptr;
5988 if (Size != 1 || SCEVs.size() > 1) {
5989 const SCEV *Sz = SE.getConstant(Dist->getType(), Size * (SCEVs.size() - 1));
5990 Stride = TryGetStride(Dist, Sz);
5991 if (!Stride)
5992 return nullptr;
5993 }
5994 if (!Stride || isa<SCEVConstant>(Stride))
5995 return nullptr;
5996 // Iterate through all pointers and check if all distances are
5997 // unique multiple of Stride.
5998 using DistOrdPair = std::pair<int64_t, int>;
5999 auto Compare = llvm::less_first();
6000 std::set<DistOrdPair, decltype(Compare)> Offsets(Compare);
6001 bool IsConsecutive = true;
6002 for (const auto [Idx, PtrSCEV] : enumerate(SCEVs)) {
6003 unsigned Dist = 0;
6004 if (PtrSCEV != PtrSCEVLowest) {
6005 const SCEV *Diff = SE.getMinusSCEV(PtrSCEV, PtrSCEVLowest);
6006 const SCEV *Coeff = TryGetStride(Diff, Stride);
6007 if (!Coeff)
6008 return nullptr;
6009 const auto *SC = dyn_cast<SCEVConstant>(Coeff);
6010 if (!SC || isa<SCEVCouldNotCompute>(SC))
6011 return nullptr;
6012 if (!SE.getMinusSCEV(PtrSCEV, SE.getAddExpr(PtrSCEVLowest,
6013 SE.getMulExpr(Stride, SC)))
6014 ->isZero())
6015 return nullptr;
6016 Dist = SC->getAPInt().getZExtValue();
6017 }
6018 // If the strides are not the same or repeated, we can't vectorize.
6019 if ((Dist / Size) * Size != Dist || (Dist / Size) >= SCEVs.size())
6020 return nullptr;
6021 auto Res = Offsets.emplace(Dist, Idx);
6022 if (!Res.second)
6023 return nullptr;
6024 // Consecutive order if the inserted element is the last one.
6025 IsConsecutive = IsConsecutive && std::next(Res.first) == Offsets.end();
6026 }
6027 SortedIndices.clear();
6028 if (!IsConsecutive) {
6029 // Fill SortedIndices array only if it is non-consecutive.
6030 SortedIndices.resize(PointerOps.size());
6031 for (const auto [Idx, Pair] : enumerate(Offsets))
6032 SortedIndices[Idx] = Pair.second;
6033 }
6034 return Stride;
6035}
6036
6037/// Creates subvector insert. Generates shuffle using \p Generator or
6038/// using default shuffle.
6040 IRBuilderBase &Builder, Value *Vec, Value *V, unsigned Index,
6041 function_ref<Value *(Value *, Value *, ArrayRef<int>)> Generator = {}) {
6042 if (isa<PoisonValue>(Vec) && isa<PoisonValue>(V))
6043 return Vec;
6044 const unsigned SubVecVF = getNumElements(V->getType());
6045 // Create shuffle, insertvector requires that index is multiple of
6046 // the subvector length.
6047 const unsigned VecVF = getNumElements(Vec->getType());
6049 if (isa<PoisonValue>(Vec)) {
6050 auto *Begin = std::next(Mask.begin(), Index);
6051 std::iota(Begin, std::next(Begin, SubVecVF), 0);
6052 Vec = Builder.CreateShuffleVector(V, Mask);
6053 return Vec;
6054 }
6055 std::iota(Mask.begin(), Mask.end(), 0);
6056 std::iota(std::next(Mask.begin(), Index),
6057 std::next(Mask.begin(), Index + SubVecVF), VecVF);
6058 if (Generator)
6059 return Generator(Vec, V, Mask);
6060 // 1. Resize V to the size of Vec.
6061 SmallVector<int> ResizeMask(VecVF, PoisonMaskElem);
6062 std::iota(ResizeMask.begin(), std::next(ResizeMask.begin(), SubVecVF), 0);
6063 V = Builder.CreateShuffleVector(V, ResizeMask);
6064 // 2. Insert V into Vec.
6065 return Builder.CreateShuffleVector(Vec, V, Mask);
6066}
6067
6068/// Generates subvector extract using \p Generator or using default shuffle.
6070 unsigned SubVecVF, unsigned Index) {
6071 SmallVector<int> Mask(SubVecVF, PoisonMaskElem);
6072 std::iota(Mask.begin(), Mask.end(), Index);
6073 return Builder.CreateShuffleVector(Vec, Mask);
6074}
6075
6076/// Builds compress-like mask for shuffles for the given \p PointerOps, ordered
6077/// with \p Order.
6078/// \return true if the mask represents strided access, false - otherwise.
6080 ArrayRef<unsigned> Order, Type *ScalarTy,
6081 const DataLayout &DL, ScalarEvolution &SE,
6082 SmallVectorImpl<int> &CompressMask) {
6083 const unsigned Sz = PointerOps.size();
6084 CompressMask.assign(Sz, PoisonMaskElem);
6085 // The first element always set.
6086 CompressMask[0] = 0;
6087 // Check if the mask represents strided access.
6088 std::optional<unsigned> Stride = 0;
6089 Value *Ptr0 = Order.empty() ? PointerOps.front() : PointerOps[Order.front()];
6090 for (unsigned I : seq<unsigned>(1, Sz)) {
6091 Value *Ptr = Order.empty() ? PointerOps[I] : PointerOps[Order[I]];
6092 std::optional<int64_t> OptPos =
6093 getPointersDiff(ScalarTy, Ptr0, ScalarTy, Ptr, DL, SE);
6094 if (!OptPos || OptPos > std::numeric_limits<unsigned>::max())
6095 return false;
6096 unsigned Pos = static_cast<unsigned>(*OptPos);
6097 CompressMask[I] = Pos;
6098 if (!Stride)
6099 continue;
6100 if (*Stride == 0) {
6101 *Stride = Pos;
6102 continue;
6103 }
6104 if (Pos != *Stride * I)
6105 Stride.reset();
6106 }
6107 return Stride.has_value();
6108}
6109
6110/// Checks if the \p VL can be transformed to a (masked)load + compress or
6111/// (masked) interleaved load.
6113 ArrayRef<Value *> VL, ArrayRef<Value *> PointerOps,
6116 const DominatorTree &DT, const TargetLibraryInfo &TLI,
6118 const function_ref<bool(Value *)> AreAllUsersVectorized, bool &IsMasked,
6119 unsigned &InterleaveFactor, SmallVectorImpl<int> &CompressMask,
6120 VectorType *&LoadVecTy) {
6121 InterleaveFactor = 0;
6122 Type *ScalarTy = VL.front()->getType();
6123 const size_t Sz = VL.size();
6124 auto *VecTy = cast<VectorType>(getWidenedType(ScalarTy, Sz));
6125 SmallVector<int> Mask;
6126 if (!Order.empty())
6127 inversePermutation(Order, Mask);
6128 // Check external uses.
6129 for (const auto [I, V] : enumerate(VL)) {
6130 if (AreAllUsersVectorized(V))
6131 continue;
6132 InstructionCost ExtractCost =
6133 TTI.getVectorInstrCost(Instruction::ExtractElement, VecTy, CostKind,
6134 Mask.empty() ? I : Mask[I]);
6135 InstructionCost ScalarCost =
6136 TTI.getInstructionCost(cast<Instruction>(V), CostKind);
6137 if (ExtractCost <= ScalarCost)
6138 return false;
6139 }
6140 Value *Ptr0;
6141 Value *PtrN;
6142 if (Order.empty()) {
6143 Ptr0 = PointerOps.front();
6144 PtrN = PointerOps.back();
6145 } else {
6146 Ptr0 = PointerOps[Order.front()];
6147 PtrN = PointerOps[Order.back()];
6148 }
6149 std::optional<int64_t> Diff =
6150 getPointersDiff(ScalarTy, Ptr0, ScalarTy, PtrN, DL, SE);
6151 if (!Diff)
6152 return false;
6153 const size_t MaxRegSize =
6155 .getFixedValue();
6156 // Check for very large distances between elements.
6157 if (*Diff / Sz >= MaxRegSize / 8)
6158 return false;
6159 LoadVecTy = cast<FixedVectorType>(getWidenedType(ScalarTy, *Diff + 1));
6160 auto *LI = cast<LoadInst>(Order.empty() ? VL.front() : VL[Order.front()]);
6161 Align CommonAlignment = LI->getAlign();
6162 SimplifyQuery SQ(
6163 DL, &TLI, &DT, &AC,
6164 cast<LoadInst>(Order.empty() ? VL.back() : VL[Order.back()]));
6165 IsMasked = !isSafeToLoadUnconditionally(Ptr0, LoadVecTy, CommonAlignment, SQ);
6166 if (IsMasked && !TTI.isLegalMaskedLoad(LoadVecTy, CommonAlignment,
6167 LI->getPointerAddressSpace()))
6168 return false;
6169 // TODO: perform the analysis of each scalar load for better
6170 // safe-load-unconditionally analysis.
6171 bool IsStrided =
6172 buildCompressMask(PointerOps, Order, ScalarTy, DL, SE, CompressMask);
6173 assert(CompressMask.size() >= 2 && "At least two elements are required");
6174 SmallVector<Value *> OrderedPointerOps(PointerOps);
6175 if (!Order.empty())
6176 reorderScalars(OrderedPointerOps, Mask);
6177 auto [ScalarGEPCost, VectorGEPCost] =
6178 getGEPCosts(TTI, OrderedPointerOps, OrderedPointerOps.front(),
6179 Instruction::Load, CostKind, ScalarTy, LoadVecTy);
6180 // The cost of scalar loads.
6181 InstructionCost ScalarLoadsCost =
6183 [&](InstructionCost C, Value *V) {
6184 return C + TTI.getInstructionCost(cast<Instruction>(V),
6185 CostKind);
6186 }) +
6187 ScalarGEPCost;
6188 APInt DemandedElts = APInt::getAllOnes(Sz);
6189 InstructionCost GatherCost =
6190 getScalarizationOverhead(TTI, SLPReVec, ScalarTy, VecTy, DemandedElts,
6191 /*Insert=*/true,
6192 /*Extract=*/false, CostKind) +
6193 ScalarLoadsCost;
6194 InstructionCost LoadCost = 0;
6195 if (IsMasked) {
6196 LoadCost = TTI.getMemIntrinsicInstrCost(
6197 MemIntrinsicCostAttributes(Intrinsic::masked_load, LoadVecTy,
6198 CommonAlignment,
6199 LI->getPointerAddressSpace()),
6200 CostKind);
6201 } else {
6202 LoadCost =
6203 TTI.getMemoryOpCost(Instruction::Load, LoadVecTy, CommonAlignment,
6204 LI->getPointerAddressSpace(), CostKind);
6205 }
6206 if (IsStrided && !IsMasked && Order.empty()) {
6207 // Check for potential segmented(interleaved) loads.
6208 VectorType *AlignedLoadVecTy = cast<VectorType>(getWidenedType(
6209 ScalarTy,
6210 getFullVectorNumberOfElements(TTI, ScalarTy, *Diff + 1, SLPReVec)));
6211 SimplifyQuery SQ(DL, &TLI, &DT, &AC, cast<LoadInst>(VL.back()));
6212 if (!isSafeToLoadUnconditionally(Ptr0, AlignedLoadVecTy, CommonAlignment,
6213 SQ))
6214 AlignedLoadVecTy = LoadVecTy;
6215 if (TTI.isLegalInterleavedAccessType(AlignedLoadVecTy, CompressMask[1],
6216 CommonAlignment,
6217 LI->getPointerAddressSpace())) {
6218 InstructionCost InterleavedCost =
6219 VectorGEPCost + TTI.getInterleavedMemoryOpCost(
6220 Instruction::Load, AlignedLoadVecTy,
6221 CompressMask[1], {}, CommonAlignment,
6222 LI->getPointerAddressSpace(), CostKind, IsMasked);
6223 if (InterleavedCost < GatherCost) {
6224 InterleaveFactor = CompressMask[1];
6225 LoadVecTy = AlignedLoadVecTy;
6226 return true;
6227 }
6228 }
6229 }
6230 // Estimating the compression shuffle cost below can be extremely expensive
6231 // for a very wide LoadVecTy, which is split into a large number of vector
6232 // registers (see processShuffleMasks). The shuffle cost is always
6233 // non-negative, so if the load cost alone already reaches the gather cost the
6234 // masked-load-compress cannot be profitable. Bail out before the costly
6235 // shuffle cost estimation in that case.
6236 if (VectorGEPCost + LoadCost >= GatherCost)
6237 return false;
6238 InstructionCost CompressCost = getShuffleCost(
6239 TTI, TTI::SK_PermuteSingleSrc, LoadVecTy, CostKind, CompressMask);
6240 if (!Order.empty()) {
6241 SmallVector<int> NewMask(Sz, PoisonMaskElem);
6242 for (unsigned I : seq<unsigned>(Sz)) {
6243 NewMask[I] = CompressMask[Mask[I]];
6244 }
6245 CompressMask.swap(NewMask);
6246 }
6247 InstructionCost TotalVecCost = VectorGEPCost + LoadCost + CompressCost;
6248 return TotalVecCost < GatherCost;
6249}
6250
6251/// Checks if the \p VL can be transformed to a (masked)load + compress or
6252/// (masked) interleaved load.
6253static bool
6256 const DataLayout &DL, ScalarEvolution &SE,
6257 AssumptionCache &AC, const DominatorTree &DT,
6258 const TargetLibraryInfo &TLI,
6260 const function_ref<bool(Value *)> AreAllUsersVectorized) {
6261 bool IsMasked;
6262 unsigned InterleaveFactor;
6263 SmallVector<int> CompressMask;
6264 VectorType *LoadVecTy;
6265 return isMaskedLoadCompress(VL, PointerOps, Order, TTI, DL, SE, AC, DT, TLI,
6266 CostKind, AreAllUsersVectorized, IsMasked,
6267 InterleaveFactor, CompressMask, LoadVecTy);
6268}
6269
6270/// Checks if the stores \p VL with pointers \p PointerOps can be lowered as a
6271/// single masked store. On success \p StoreVecTy is the widened store type and
6272/// \p ReuseShuffleIndices is the expand mask that places each stored value at
6273/// its element offset from the base (poison in the gaps).
6275 ArrayRef<Value *> VL, ArrayRef<Value *> PointerOps,
6277 const DataLayout &DL, ScalarEvolution &SE, Align CommonAlignment,
6278 SmallVectorImpl<int> &ReuseShuffleIndices, FixedVectorType *&StoreVecTy) {
6279 Type *ScalarTy = cast<StoreInst>(VL.front())->getValueOperand()->getType();
6280 const size_t Sz = VL.size();
6281 // Only simple scalar element types are supported.
6282 if (Sz < 2 || (!ScalarTy->isIntOrPtrTy() && !ScalarTy->isFloatingPointTy()))
6283 return false;
6284 Value *Ptr0 = Order.empty() ? PointerOps.front() : PointerOps[Order.front()];
6285 Value *PtrN = Order.empty() ? PointerOps.back() : PointerOps[Order.back()];
6286 std::optional<int64_t> Diff =
6287 getPointersDiff(ScalarTy, Ptr0, ScalarTy, PtrN, DL, SE);
6288 if (!Diff || *Diff <= 0)
6289 return false;
6290 // Avoid widened vectors with very large gaps between the stored elements.
6291 const unsigned MaxRegSize =
6293 .getFixedValue();
6294 const unsigned ScalarBits = DL.getTypeSizeInBits(ScalarTy).getFixedValue();
6295 if (ScalarBits == 0 ||
6296 static_cast<uint64_t>(*Diff) / Sz >= MaxRegSize / ScalarBits)
6297 return false;
6298 StoreVecTy = cast<FixedVectorType>(getWidenedType(ScalarTy, *Diff + 1));
6299 unsigned AS = cast<StoreInst>(VL.front())->getPointerAddressSpace();
6300 if (!TTI.isLegalMaskedStore(StoreVecTy, CommonAlignment, AS,
6302 return false;
6303 // Build the expand mask: store I (in address-sorted order) is placed at its
6304 // element offset from the base, other widened lanes are poison.
6305 ReuseShuffleIndices.assign(*Diff + 1, PoisonMaskElem);
6306 int64_t Prev = -1;
6307 for (unsigned I : seq<unsigned>(Sz)) {
6308 Value *Ptr = Order.empty() ? PointerOps[I] : PointerOps[Order[I]];
6309 std::optional<int64_t> Off =
6310 getPointersDiff(ScalarTy, Ptr0, ScalarTy, Ptr, DL, SE);
6311 if (!Off || *Off <= Prev || *Off > *Diff)
6312 return false;
6313 ReuseShuffleIndices[*Off] = static_cast<int>(I);
6314 Prev = *Off;
6315 }
6316 return true;
6317}
6318
6319/// Checks if strided loads can be generated out of \p VL loads with pointers \p
6320/// PointerOps:
6321/// 1. Target with strided load support is detected.
6322/// 2. The number of loads is greater than MinProfitableStridedLoads, or the
6323/// potential stride <= MaxProfitableStride and the potential stride is
6324/// power-of-2 (to avoid perf regressions for the very small number of loads)
6325/// and max distance > number of loads, or potential stride is -1.
6326/// 3. The loads are ordered, or number of unordered loads <=
6327/// MaxProfitableUnorderedLoads, or loads are in reversed order. (this check is
6328/// to avoid extra costs for very expensive shuffles).
6329/// 4. Any pointer operand is an instruction with the users outside of the
6330/// current graph (for masked gathers extra extractelement instructions
6331/// might be required).
6333 Align Alignment, const int64_t Diff,
6334 const size_t Sz) const {
6335 if (Diff % (Sz - 1) != 0)
6336 return false;
6337
6338 // Try to generate strided load node.
6339 auto IsAnyPointerUsedOutGraph = any_of(PointerOps, [&](Value *V) {
6340 return isa<Instruction>(V) && any_of(V->users(), [&](User *U) {
6341 return !isVectorized(U) && !MustGather.contains(U);
6342 });
6343 });
6344
6345 const uint64_t AbsoluteDiff = std::abs(Diff);
6346 auto *VecTy = getWidenedType(ScalarTy, Sz);
6347 if (IsAnyPointerUsedOutGraph ||
6348 (AbsoluteDiff > Sz &&
6350 (AbsoluteDiff <= MaxProfitableStride * Sz && AbsoluteDiff % Sz == 0 &&
6351 has_single_bit(AbsoluteDiff / Sz)))) ||
6352 Diff == -(static_cast<int64_t>(Sz) - 1)) {
6353 int64_t Stride = Diff / static_cast<int64_t>(Sz - 1);
6354 if (Diff != Stride * static_cast<int64_t>(Sz - 1))
6355 return false;
6356 if (!TTI->isLegalStridedLoadStore(VecTy, Alignment))
6357 return false;
6358 return true;
6359 }
6360 return false;
6361}
6362
6364 const ArrayRef<Value *> PointerOps, Type *ScalarTy, Align Alignment,
6365 const SmallVectorImpl<unsigned> &SortedIndices, const int64_t Diff,
6366 Value *Ptr0, StridedPtrInfo &SPtrInfo) const {
6367 const size_t Sz = PointerOps.size();
6368 SmallVector<int64_t> SortedOffsetsFromBase(Sz);
6369 // Go through `PointerOps` in sorted order and record offsets from
6370 // PointerOps[0]. We use PointerOps[0] rather than Ptr0 because
6371 // sortPtrAccesses only validates getPointersDiff for pairs relative to
6372 // PointerOps[0]. This is safe since only offset differences are used below.
6373 for (unsigned I : seq<unsigned>(Sz)) {
6374 Value *Ptr =
6375 SortedIndices.empty() ? PointerOps[I] : PointerOps[SortedIndices[I]];
6376 std::optional<int64_t> Offset =
6377 getPointersDiff(ScalarTy, PointerOps[0], ScalarTy, Ptr, *DL, *SE);
6378 assert(Offset && "sortPtrAccesses should have validated this pointer");
6379 SortedOffsetsFromBase[I] = *Offset;
6380 }
6381
6382 // The code below checks that `SortedOffsetsFromBase` looks as follows:
6383 // ```
6384 // [
6385 // (e_{0, 0}, e_{0, 1}, ..., e_{0, GroupSize - 1}), // first group
6386 // (e_{1, 0}, e_{1, 1}, ..., e_{1, GroupSize - 1}), // secon group
6387 // ...
6388 // (e_{NumGroups - 1, 0}, e_{NumGroups - 1, 1}, ..., e_{NumGroups - 1,
6389 // GroupSize - 1}), // last group
6390 // ]
6391 // ```
6392 // The distance between consecutive elements within each group should all be
6393 // the same `StrideWithinGroup`. The distance between the first elements of
6394 // consecutive groups should all be the same `StrideBetweenGroups`.
6395
6396 int64_t StrideWithinGroup =
6397 SortedOffsetsFromBase[1] - SortedOffsetsFromBase[0];
6398 // Determine size of the first group. Later we will check that all other
6399 // groups have the same size.
6400 auto IsEndOfGroupIndex = [=, &SortedOffsetsFromBase](unsigned Idx) {
6401 return SortedOffsetsFromBase[Idx] - SortedOffsetsFromBase[Idx - 1] !=
6402 StrideWithinGroup;
6403 };
6404 auto Indices = seq<unsigned>(1, Sz);
6405 auto FoundIt = llvm::find_if(Indices, IsEndOfGroupIndex);
6406 unsigned GroupSize = FoundIt != Indices.end() ? *FoundIt : Sz;
6407
6408 unsigned VecSz = Sz;
6409 Type *NewScalarTy = ScalarTy;
6410
6411 // Quick detour: at this point we can say what the type of strided load would
6412 // be if all the checks pass. Check if this type is legal for the target.
6413 bool NeedsWidening = Sz != GroupSize;
6414 const uint64_t UnitBitWidth = DL->getTypeSizeInBits(ScalarTy).getFixedValue();
6415 if (NeedsWidening) {
6416 if (Sz % GroupSize != 0)
6417 return false;
6418
6419 if (StrideWithinGroup != 1)
6420 return false;
6421 VecSz = Sz / GroupSize;
6422 NewScalarTy = Type::getIntNTy(SE->getContext(), UnitBitWidth * GroupSize);
6423 } else if (ScalarTy->isVectorTy()) {
6424 NewScalarTy = Type::getIntNTy(SE->getContext(), UnitBitWidth);
6425 }
6426
6427 if (!isStridedLoad(PointerOps, NewScalarTy, Alignment, Diff, VecSz))
6428 return false;
6429
6430 int64_t StrideIntVal = StrideWithinGroup;
6431 if (NeedsWidening) {
6432 // Continue with checking the "shape" of `SortedOffsetsFromBase`.
6433 // Check that the strides between groups are all the same.
6434 unsigned CurrentGroupStartIdx = GroupSize;
6435 int64_t StrideBetweenGroups =
6436 SortedOffsetsFromBase[GroupSize] - SortedOffsetsFromBase[0];
6437 StrideIntVal = StrideBetweenGroups;
6438 for (; CurrentGroupStartIdx < Sz; CurrentGroupStartIdx += GroupSize) {
6439 if (SortedOffsetsFromBase[CurrentGroupStartIdx] -
6440 SortedOffsetsFromBase[CurrentGroupStartIdx - GroupSize] !=
6441 StrideBetweenGroups)
6442 return false;
6443 }
6444
6445 auto CheckGroup = [=](const unsigned StartIdx) -> bool {
6446 auto Indices = seq<unsigned>(StartIdx + 1, Sz);
6447 auto FoundIt = llvm::find_if(Indices, IsEndOfGroupIndex);
6448 unsigned GroupEndIdx = FoundIt != Indices.end() ? *FoundIt : Sz;
6449 return GroupEndIdx - StartIdx == GroupSize;
6450 };
6451 for (unsigned I = 0; I < Sz; I += GroupSize) {
6452 if (!CheckGroup(I))
6453 return false;
6454 }
6455 }
6456
6457 Type *StrideTy = DL->getIndexType(Ptr0->getType());
6458 SPtrInfo.StrideVal = ConstantInt::getSigned(StrideTy, StrideIntVal);
6459 SPtrInfo.Ty = cast<FixedVectorType>(getWidenedType(NewScalarTy, VecSz));
6460 return true;
6461}
6462
6464 Type *BaseTy, Align CommonAlignment,
6465 SmallVectorImpl<unsigned> &SortedIndices,
6466 StridedPtrInfo &SPtrInfo,
6467 bool IsLoad) const {
6468 const unsigned Sz = PointerOps.size();
6469 const unsigned MinProfitableStridedOps =
6471 if (Sz * getNumElements(BaseTy) < MinProfitableStridedOps)
6472 return false;
6473
6474 // The element type of the strided access is fixed by the number of distinct
6475 // constant offsets the pointers fall into, which has to divide their number.
6476 auto GetStridedTy = [&](unsigned NumOffsets) -> FixedVectorType * {
6477 Type *NewScalarTy = BaseTy;
6478 if (NumOffsets > 1 || BaseTy->isVectorTy())
6479 NewScalarTy = Type::getIntNTy(
6480 SE->getContext(),
6481 DL->getTypeSizeInBits(BaseTy).getFixedValue() * NumOffsets);
6483 getWidenedType(NewScalarTy, Sz / NumOffsets));
6484 };
6485 auto IsLegalStridedTy = [&](FixedVectorType *StridedTy) {
6486 return StridedTy && TTI->isTypeLegal(StridedTy) &&
6487 TTI->isLegalStridedLoadStore(StridedTy, CommonAlignment);
6488 };
6489 // Determining the offsets below builds SCEVs for every pointer, which is
6490 // expensive. Bail out if the target does not support any strided accesses at
6491 // all.
6492 if (none_of(seq<unsigned>(1, Sz), [&](unsigned NumOffsets) {
6493 return Sz % NumOffsets == 0 &&
6494 IsLegalStridedTy(GetStridedTy(NumOffsets));
6495 }))
6496 return false;
6497
6498 // If each value in `PointerOps` is of the form `%x + Offset` where `Offset`
6499 // is constant, we partition `PointerOps` sequence into subsequences of
6500 // pointers with the same offset. For each offset we record values from
6501 // `PointerOps` and their indicies in `PointerOps`.
6503 OffsetToPointerOpIdxMap;
6504 // Track to make sure that only VecSz different stride multiples are consumed
6505 // Prevents cases such as:
6506 // 1, x + 0, x + 1, 2x + 0 from being recognized as legal RT strided as there
6507 // are 2 "0" and 2 "1" offsets and a stride of "x" between both offsets
6508 SmallDenseSet<const SCEV *> StrideMultiples;
6509 for (auto [Idx, Ptr] : enumerate(PointerOps)) {
6510 const SCEV *PtrSCEV = SE->getSCEV(Ptr);
6511 if (!PtrSCEV)
6512 return false;
6513
6514 const auto *Add = dyn_cast<SCEVAddExpr>(PtrSCEV);
6515 int64_t Offset = 0;
6516 const SCEV *StrideMultiple = PtrSCEV;
6517 if (Add) {
6518 // `Offset` is non-zero.
6519 for (int I : seq<int>(Add->getNumOperands())) {
6520 const auto *SC = dyn_cast<SCEVConstant>(Add->getOperand(I));
6521 if (!SC)
6522 continue;
6523 Offset = SC->getAPInt().getSExtValue();
6524 if (Offset >= std::numeric_limits<int64_t>::max() - 1) {
6525 Offset = 0;
6526 continue;
6527 }
6528 StrideMultiple = SE->getMinusSCEV(StrideMultiple, SC);
6529 break;
6530 }
6531 }
6532 OffsetToPointerOpIdxMap[Offset].first.push_back(Ptr);
6533 OffsetToPointerOpIdxMap[Offset].second.push_back(Idx);
6534 StrideMultiples.insert(StrideMultiple);
6535 }
6536 unsigned NumOffsets = OffsetToPointerOpIdxMap.size();
6537
6538 // Quick detour: at this point we can say what the type of strided load would
6539 // be if all the checks pass. Check if this type is legal for the target.
6540 unsigned VecSz = Sz;
6541 if (NumOffsets > 1) {
6542 if (Sz % NumOffsets != 0)
6543 return false;
6544 VecSz = Sz / NumOffsets;
6545 }
6546
6547 if (StrideMultiples.size() != VecSz)
6548 return false;
6549
6550 auto *StridedLoadTy = GetStridedTy(NumOffsets);
6551 if (!IsLegalStridedTy(StridedLoadTy))
6552 return false;
6553
6554 // Check if the offsets are contiguous and that each group has the required
6555 // size.
6556 SmallVector<int64_t> SortedOffsetsV(NumOffsets);
6557 for (auto [Idx, MapPair] : enumerate(OffsetToPointerOpIdxMap)) {
6558 if (MapPair.second.first.size() != VecSz)
6559 return false;
6560 SortedOffsetsV[Idx] = MapPair.first;
6561 }
6562 sort(SortedOffsetsV);
6563
6564 if (NumOffsets > 1) {
6565 int64_t BaseBytes = DL->getTypeStoreSize(BaseTy);
6566 for (int I : seq<int>(1, SortedOffsetsV.size())) {
6567 if (SortedOffsetsV[I] - SortedOffsetsV[I - 1] != BaseBytes)
6568 return false;
6569 }
6570 }
6571
6572 // Introduce some notation for the explanations below. Let `PointerOps_j`
6573 // denote the subsequence of `PointerOps` with offsets equal to
6574 // `SortedOffsetsV[j]`. Let `SortedIndices_j` be a such that the sequence
6575 // ```
6576 // PointerOps_j[SortedIndices_j[0]],
6577 // PointerOps_j[SortedIndices_j[1]],
6578 // PointerOps_j[SortedIndices_j[2]],
6579 // ...
6580 // ```
6581 // is sorted. Also, let `IndicesInAllPointerOps_j` be the vector
6582 // of indices of the subsequence `PointerOps_j` in all of `PointerOps`,
6583 // i.e `PointerOps_j[i] = PointerOps[IndicesInAllPointerOps_j[i]]`.
6584 // The entire sorted `PointerOps` looks like this:
6585 // ```
6586 // PointerOps_0[SortedIndices_0[0]] = PointerOps[IndicesInAllPointerOps_0[0]],
6587 // PointerOps_1[SortedIndices_1[0]] = PointerOps[IndicesInAllPointerOps_1[0]],
6588 // PointerOps_2[SortedIndices_2[0]] = PointerOps[IndicesInAllPointerOps_2[0]],
6589 // ...
6590 // PointerOps_(NumOffsets - 1)[SortedIndices_(NumOffsets - 1)[0]] =
6591 // PointerOps[IndicesInAllPointerOps_(NumOffsets - 1)[0]],
6592 //
6593 // PointerOps_0[SortedIndices_0[1]] = PointerOps[IndicesInAllPointerOps_0[1]],
6594 // PointerOps_1[SortedIndices_1[1]] = PointerOps[IndicesInAllPointerOps_1[1]],
6595 // PointerOps_2[SortedIndices_2[1]] = PointerOps[IndicesInAllPointerOps_2[1]],
6596 // ...
6597 // PointerOps_(NumOffsets - 1)[SortedIndices_(NumOffsets - 1)[1]] =
6598 // PointerOps[IndicesInAllPointerOps_(NumOffsets - 1)[1]],
6599 //
6600 // PointerOps_0[SortedIndices_0[2]] = PointerOps[IndicesInAllPointerOps_0[2]],
6601 // PointerOps_1[SortedIndices_1[2]] = PointerOps[IndicesInAllPointerOps_1[2]],
6602 // PointerOps_2[SortedIndices_2[2]] = PointerOps[IndicesInAllPointerOps_2[2]],
6603 // ...
6604 // PointerOps_(NumOffsets - 1)[SortedIndices_(NumOffsets - 1)[2]] =
6605 // PointerOps[IndicesInAllPointerOps_(NumOffsets - 1)[2]],
6606 // ...
6607 // ...
6608 // ...
6609 // PointerOps_0[SortedIndices_0[VecSz - 1]] =
6610 // PointerOps[IndicesInAllPointerOps_0[VecSz - 1]],
6611 // PointerOps_1[SortedIndices_1[VecSz - 1]] =
6612 // PointerOps[IndicesInAllPointerOps_1[VecSz - 1]],
6613 // PointerOps_2[SortedIndices_2[VecSz - 1]] =
6614 // PointerOps[IndicesInAllPointerOps_2[VecSz - 1]],
6615 // ...
6616 // PointerOps_(NumOffsets - 1)[SortedIndices_(NumOffsets - 1)[VecSz - 1]] =
6617 // PointerOps[IndicesInAllPointerOps_(NumOffsets - 1)[VecSz - 1]],
6618 // ```
6619 // In order to be able to generate a strided load, for each `PointerOps_j`
6620 // check that the distance between adjacent pointers are all equal to the same
6621 // value (stride).
6622 //
6623 // As we do that, also calculate SortedIndices. Since we should not modify
6624 // `SortedIndices` unless we know that all the checks succeed, record the
6625 // indicies into `SortedIndicesDraft`.
6626 SmallVector<unsigned> SortedIndicesDraft(Sz);
6627
6628 // Given sorted indices for a particular offset (as calculated by
6629 // calculateRtStride), update the `SortedIndicesDraft` for all of PointerOps.
6630 // Let `Offset` be `SortedOffsetsV[OffsetNum]`.
6631 // \param `OffsetNum` the index of `Offset` in `SortedOffsetsV`.
6632 // \param `IndicesInAllPointerOps` vector of indices of the
6633 // subsequence `PointerOps_OffsetNum` in `PointerOps`, i.e. using the above
6634 // notation `IndicesInAllPointerOps = IndicesInAllPointerOps_OffsetNum`.
6635 // \param `SortedIndicesForOffset = SortedIndices_OffsetNum`
6636 auto UpdateSortedIndices =
6637 [&](SmallVectorImpl<unsigned> &SortedIndicesForOffset,
6638 ArrayRef<unsigned> IndicesInAllPointerOps, const int64_t OffsetNum) {
6639 if (SortedIndicesForOffset.empty()) {
6640 SortedIndicesForOffset.resize(IndicesInAllPointerOps.size());
6641 std::iota(SortedIndicesForOffset.begin(),
6642 SortedIndicesForOffset.end(), 0);
6643 }
6644 for (const auto [Num, Idx] : enumerate(SortedIndicesForOffset)) {
6645 SortedIndicesDraft[Num * NumOffsets + OffsetNum] =
6646 IndicesInAllPointerOps[Idx];
6647 }
6648 };
6649
6650 int64_t LowestOffset = SortedOffsetsV[0];
6651 ArrayRef<Value *> PointerOps0 = OffsetToPointerOpIdxMap[LowestOffset].first;
6652
6653 SmallVector<unsigned> SortedIndicesForOffset0;
6654 const SCEV *Stride0 =
6655 calculateRtStride(PointerOps0, BaseTy, *DL, *SE, SortedIndicesForOffset0);
6656 if (!Stride0)
6657 return false;
6658
6659 ArrayRef<unsigned> IndicesInAllPointerOps0 =
6660 OffsetToPointerOpIdxMap[LowestOffset].second;
6661 UpdateSortedIndices(SortedIndicesForOffset0, IndicesInAllPointerOps0, 0);
6662
6663 // Now that we know what the common stride and coefficients has to be check
6664 // the remaining `PointerOps_j`.
6665 SmallVector<unsigned> SortedIndicesForOffset;
6666 for (int J : seq<int>(1, NumOffsets)) {
6667 SortedIndicesForOffset.clear();
6668
6669 int64_t Offset = SortedOffsetsV[J];
6670 ArrayRef<Value *> PointerOpsForOffset =
6671 OffsetToPointerOpIdxMap[Offset].first;
6672 ArrayRef<unsigned> IndicesInAllPointerOps =
6673 OffsetToPointerOpIdxMap[Offset].second;
6674 const SCEV *StrideWithinGroup = calculateRtStride(
6675 PointerOpsForOffset, BaseTy, *DL, *SE, SortedIndicesForOffset);
6676
6677 if (!StrideWithinGroup || StrideWithinGroup != Stride0)
6678 return false;
6679
6680 UpdateSortedIndices(SortedIndicesForOffset, IndicesInAllPointerOps, J);
6681 }
6682
6683 SortedIndices.clear();
6684 SortedIndices = std::move(SortedIndicesDraft);
6685 SPtrInfo.StrideSCEV = Stride0;
6686 SPtrInfo.Ty = StridedLoadTy;
6687 return true;
6688}
6689
6691 ArrayRef<Value *> VL, const Value *VL0, SmallVectorImpl<unsigned> &Order,
6692 SmallVectorImpl<Value *> &PointerOps, StridedPtrInfo &SPtrInfo,
6693 unsigned *BestVF, bool TryRecursiveCheck) const {
6694 // Check that a vectorized load would load the same memory as a scalar
6695 // load. For example, we don't want to vectorize loads that are smaller
6696 // than 8-bit. Even though we have a packed struct {<i2, i2, i2, i2>} LLVM
6697 // treats loading/storing it as an i8 struct. If we vectorize loads/stores
6698 // from such a struct, we read/write packed bits disagreeing with the
6699 // unvectorized version.
6700 if (BestVF)
6701 *BestVF = 0;
6703 return LoadsState::Gather;
6704 Type *ScalarTy = VL0->getType();
6705
6706 if (DL->getTypeSizeInBits(ScalarTy) != DL->getTypeAllocSizeInBits(ScalarTy))
6707 return LoadsState::Gather;
6708
6709 // Make sure all loads in the bundle are simple - we can't vectorize
6710 // atomic or volatile loads.
6711 PointerOps.clear();
6712 const size_t Sz = VL.size();
6713 PointerOps.resize(Sz);
6714 auto *POIter = PointerOps.begin();
6715 for (Value *V : VL) {
6716 auto *L = dyn_cast<LoadInst>(V);
6717 if (!L || !L->isSimple())
6718 return LoadsState::Gather;
6719 *POIter = L->getPointerOperand();
6720 ++POIter;
6721 }
6722
6723 Order.clear();
6724 // Check the order of pointer operands or that all pointers are the same.
6725 bool IsSorted = sortPtrAccesses(PointerOps, ScalarTy, *DL, *SE, Order);
6726
6727 auto *VecTy = dyn_cast<VectorType>(getWidenedType(ScalarTy, Sz));
6728 if (!VecTy)
6729 return LoadsState::Gather;
6730 Align CommonAlignment = computeCommonAlignment<LoadInst>(VL);
6731 // Cache masked gather legality - both the !IsSorted path below and the
6732 // post-branch check use the same VecTy/CommonAlignment, and the underlying
6733 // TTI calls are virtual.
6734 std::optional<bool> MaskedGatherLegal;
6735 auto IsMaskedGatherLegal = [&] {
6736 if (!MaskedGatherLegal)
6737 MaskedGatherLegal =
6738 TTI->isLegalMaskedGather(VecTy, CommonAlignment) &&
6739 !TTI->forceScalarizeMaskedGather(VecTy, CommonAlignment);
6740 return *MaskedGatherLegal;
6741 };
6742 if (!IsSorted) {
6743 // Check for a group of loads, each selecting its address (directly, or
6744 // via a constant-offset GEP) between the same two candidate base
6745 // pointers - the shape if-converted, fully-unrolled loop bodies of the
6746 // form `x = cond ? A[i] : B[i]` take. If found, model it as two masked
6747 // loads (one per candidate) blended by the (vectorized) condition,
6748 // rather than falling back to a gather of the individual scalar loads.
6749 Value *TrueBase = nullptr;
6750 Value *FalseBase = nullptr;
6751 SmallVector<Value *> Conditions;
6752 if (isSelectedBaseLoad(ScalarTy, PointerOps, *DL, TrueBase, FalseBase,
6753 Conditions) &&
6754 TTI->isLegalMaskedLoad(VecTy, CommonAlignment,
6755 cast<LoadInst>(VL0)->getPointerAddressSpace()))
6757
6758 if (analyzeRtStrideCandidate(PointerOps, ScalarTy, CommonAlignment, Order,
6759 SPtrInfo, /*isLoad=*/true))
6761
6762 if (!IsMaskedGatherLegal())
6763 return LoadsState::Gather;
6764
6765 if (!all_of(PointerOps, [&](Value *P) {
6766 return arePointersCompatible(P, PointerOps.front(), *TLI);
6767 }))
6768 return LoadsState::Gather;
6769
6770 } else {
6771 Value *Ptr0;
6772 Value *PtrN;
6773 if (Order.empty()) {
6774 Ptr0 = PointerOps.front();
6775 PtrN = PointerOps.back();
6776 } else {
6777 Ptr0 = PointerOps[Order.front()];
6778 PtrN = PointerOps[Order.back()];
6779 }
6780 // sortPtrAccesses validates getPointersDiff for all pointers relative to
6781 // PointerOps[0], so compute the span using PointerOps[0] as intermediate:
6782 // Diff = offset(PtrN) - offset(Ptr0) relative to PointerOps[0]
6783 std::optional<int64_t> Diff0 =
6784 getPointersDiff(ScalarTy, PointerOps[0], ScalarTy, Ptr0, *DL, *SE);
6785 std::optional<int64_t> DiffN =
6786 getPointersDiff(ScalarTy, PointerOps[0], ScalarTy, PtrN, *DL, *SE);
6787 assert(Diff0 && DiffN &&
6788 "sortPtrAccesses should have validated these pointers");
6789 int64_t Diff = *DiffN - *Diff0;
6790 // Check that the sorted loads are consecutive.
6791 if (static_cast<uint64_t>(Diff) == Sz - 1)
6792 return LoadsState::Vectorize;
6793 if (isMaskedLoadCompress(VL, PointerOps, Order, *TTI, *DL, *SE, *AC, *DT,
6794 *TLI, CostKind, [&](Value *V) {
6795 return areAllUsersVectorized(
6796 cast<Instruction>(V), UserIgnoreList);
6797 }))
6799 Align Alignment =
6800 cast<LoadInst>(Order.empty() ? VL.front() : VL[Order.front()])
6801 ->getAlign();
6802 if (analyzeConstantStrideCandidate(PointerOps, ScalarTy, Alignment, Order,
6803 Diff, Ptr0, SPtrInfo))
6805 }
6806 if (!IsMaskedGatherLegal())
6807 return LoadsState::Gather;
6808 // Correctly identify compare the cost of loads + shuffles rather than
6809 // strided/masked gather loads. Returns true if vectorized + shuffles
6810 // representation is better than just gather.
6811 auto CheckForShuffledLoads = [&, &TTI = *TTI](Align CommonAlignment,
6812 unsigned *BestVF,
6813 bool ProfitableGatherPointers) {
6814 if (BestVF)
6815 *BestVF = 0;
6816 // Compare masked gather cost and loads + insert subvector costs.
6817 auto [ScalarGEPCost, VectorGEPCost] =
6818 getGEPCosts(TTI, PointerOps, PointerOps.front(), Instruction::Load,
6819 CostKind, ScalarTy, VecTy);
6820 // Estimate the cost of masked gather GEP. If not a splat, roughly
6821 // estimate as a buildvector, otherwise estimate as splat.
6822 APInt DemandedElts = APInt::getAllOnes(Sz);
6823 Type *PtrScalarTy = PointerOps.front()->getType()->getScalarType();
6824 auto *PtrVecTy = cast<VectorType>(getWidenedType(PtrScalarTy, Sz));
6825 // Cache the underlying object of PointerOps.front() - it is invariant
6826 // across the per-V comparisons below and getUnderlyingObject walks
6827 // GEP/cast chains.
6828 const Value *FrontUO = getUnderlyingObject(PointerOps.front());
6829 if (static_cast<unsigned>(count_if(
6830 PointerOps, IsaPred<GetElementPtrInst>)) < PointerOps.size() - 1 ||
6831 any_of(PointerOps,
6832 [&](Value *V) { return getUnderlyingObject(V) != FrontUO; }))
6833 VectorGEPCost += getScalarizationOverhead(
6834 TTI, SLPReVec, PtrScalarTy, PtrVecTy, DemandedElts, /*Insert=*/true,
6835 /*Extract=*/false, CostKind);
6836 else
6837 VectorGEPCost +=
6839 TTI, SLPReVec, PtrScalarTy, PtrVecTy, APInt::getOneBitSet(Sz, 0),
6840 /*Insert=*/true, /*Extract=*/false, CostKind) +
6841 getShuffleCost(TTI, TTI::SK_Broadcast, PtrVecTy, CostKind);
6842 // The cost of scalar loads.
6843 InstructionCost ScalarLoadsCost =
6845 [&](InstructionCost C, Value *V) {
6846 return C + TTI.getInstructionCost(cast<Instruction>(V),
6847 CostKind);
6848 }) +
6849 ScalarGEPCost;
6850 // The cost of masked gather.
6851 InstructionCost MaskedGatherCost =
6852 TTI.getMemIntrinsicInstrCost(
6853 MemIntrinsicCostAttributes(Intrinsic::masked_gather, VecTy,
6855 /*VariableMask=*/false, CommonAlignment),
6856 CostKind) +
6857 (ProfitableGatherPointers ? 0 : VectorGEPCost);
6858 InstructionCost GatherCost =
6859 getScalarizationOverhead(TTI, SLPReVec, ScalarTy, VecTy, DemandedElts,
6860 /*Insert=*/true,
6861 /*Extract=*/false, CostKind) +
6862 ScalarLoadsCost;
6863 // The list of loads is small or perform partial check already - directly
6864 // compare masked gather cost and gather cost.
6865 constexpr unsigned ListLimit = 4;
6866 if (!TryRecursiveCheck || VL.size() < ListLimit)
6867 return MaskedGatherCost - GatherCost >= -SLPCostThreshold;
6868
6869 unsigned Sz = DL->getTypeSizeInBits(ScalarTy);
6870 unsigned MinVF = getMinVF(2 * Sz);
6871 DemandedElts.clearAllBits();
6872 // Iterate through possible vectorization factors and check if vectorized +
6873 // shuffles is better than just gather.
6874 for (unsigned VF = getFloorFullVectorNumberOfElements(
6875 TTI, ScalarTy, VL.size() - 1, SLPReVec);
6876 VF >= MinVF; VF = getFloorFullVectorNumberOfElements(
6877 TTI, ScalarTy, VF - 1, SLPReVec)) {
6879 for (unsigned Cnt = 0, End = VL.size(); Cnt < End; Cnt += VF) {
6880 const unsigned SliceVF = std::min(VF, End - Cnt);
6881 ArrayRef<Value *> Slice = VL.slice(Cnt, SliceVF);
6883 SmallVector<Value *> PointerOps;
6884 LoadsState LS = canVectorizeLoads(Slice, Slice.front(), Order,
6885 PointerOps, SPtrInfo, BestVF,
6886 /*TryRecursiveCheck=*/false);
6887 // Check that the sorted loads are consecutive.
6888 if (LS == LoadsState::Gather) {
6889 if (BestVF) {
6890 DemandedElts.setAllBits();
6891 break;
6892 }
6893 DemandedElts.setBits(Cnt, Cnt + SliceVF);
6894 continue;
6895 }
6896 // If need the reorder - consider as high-cost masked gather for now.
6897 if ((LS == LoadsState::Vectorize ||
6900 !Order.empty() && !isReverseOrder(Order))
6902 States.emplace_back(Cnt, LS);
6903 }
6904 if (DemandedElts.isAllOnes())
6905 // All loads gathered - try smaller VF.
6906 continue;
6907 // Can be vectorized later as a serie of loads/insertelements.
6908 InstructionCost VecLdCost = 0;
6909 if (!DemandedElts.isZero()) {
6910 VecLdCost = getScalarizationOverhead(TTI, SLPReVec, ScalarTy, VecTy,
6911 DemandedElts,
6912 /*Insert=*/true,
6913 /*Extract=*/false, CostKind) +
6914 ScalarGEPCost;
6915 for (unsigned Idx : seq<unsigned>(VL.size()))
6916 if (DemandedElts[Idx])
6917 VecLdCost +=
6918 TTI.getInstructionCost(cast<Instruction>(VL[Idx]), CostKind);
6919 }
6920 for (const auto &[SliceStart, LS] : States) {
6921 const unsigned SliceVF = std::min<unsigned>(VF, VL.size() - SliceStart);
6922 auto *SubVecTy = cast<VectorType>(getWidenedType(ScalarTy, SliceVF));
6923 auto *LI0 = cast<LoadInst>(VL[SliceStart]);
6924 InstructionCost VectorGEPCost =
6925 (LS == LoadsState::ScatterVectorize && ProfitableGatherPointers)
6926 ? 0
6927 : getGEPCosts(TTI,
6928 ArrayRef(PointerOps).slice(SliceStart, SliceVF),
6929 LI0->getPointerOperand(), Instruction::Load,
6930 CostKind, ScalarTy, SubVecTy)
6931 .second;
6932 if (LS == LoadsState::ScatterVectorize) {
6933 if (static_cast<unsigned>(
6934 count_if(PointerOps, IsaPred<GetElementPtrInst>)) <
6935 PointerOps.size() - 1 ||
6936 any_of(PointerOps, [&](Value *V) {
6937 return getUnderlyingObject(V) != FrontUO;
6938 }))
6939 VectorGEPCost += getScalarizationOverhead(
6940 TTI, SLPReVec, ScalarTy, SubVecTy, APInt::getAllOnes(SliceVF),
6941 /*Insert=*/true, /*Extract=*/false, CostKind);
6942 else
6943 VectorGEPCost +=
6944 getScalarizationOverhead(TTI, SLPReVec, ScalarTy, SubVecTy,
6945 APInt::getOneBitSet(SliceVF, 0),
6946 /*Insert=*/true, /*Extract=*/false,
6947 CostKind) +
6948 getShuffleCost(TTI, TTI::SK_Broadcast, SubVecTy, CostKind);
6949 }
6950 switch (LS) {
6952 VecLdCost +=
6953 TTI.getMemoryOpCost(Instruction::Load, SubVecTy, LI0->getAlign(),
6954 LI0->getPointerAddressSpace(), CostKind,
6956 VectorGEPCost;
6957 break;
6959 VecLdCost += TTI.getMemIntrinsicInstrCost(
6961 Intrinsic::experimental_vp_strided_load,
6962 SubVecTy, LI0->getPointerOperand(),
6963 /*VariableMask=*/false, CommonAlignment),
6964 CostKind) +
6965 VectorGEPCost;
6966 break;
6968 VecLdCost +=
6969 TTI.getMemIntrinsicInstrCost(
6970 MemIntrinsicCostAttributes(Intrinsic::masked_load, SubVecTy,
6971 CommonAlignment,
6972 LI0->getPointerAddressSpace()),
6973 CostKind) +
6974 getShuffleCost(TTI, TTI::SK_PermuteSingleSrc, SubVecTy, CostKind);
6975 break;
6977 VecLdCost += TTI.getMemIntrinsicInstrCost(
6979 Intrinsic::masked_gather, SubVecTy,
6980 LI0->getPointerOperand(),
6981 /*VariableMask=*/false, CommonAlignment),
6982 CostKind) +
6983 VectorGEPCost;
6984 break;
6986 // Two masked loads (one per candidate base) plus a select; no address
6987 // vector is materialized, so VectorGEPCost is skipped.
6988 VecLdCost +=
6989 getBlendedLoadCost(TTI, SubVecTy, CommonAlignment,
6990 LI0->getPointerAddressSpace(), CostKind);
6991 break;
6992 case LoadsState::Gather:
6993 llvm_unreachable("Gathers are not added to States");
6994 }
6995 SmallVector<int> ShuffleMask(VL.size());
6996 const unsigned SliceIdx = SliceStart / VF;
6997 for (int Idx : seq<int>(VL.size()))
6998 ShuffleMask[Idx] = Idx / VF == SliceIdx ? VL.size() + Idx % VF : Idx;
6999 if (SliceStart > 0)
7000 VecLdCost +=
7001 getShuffleCost(TTI, TTI::SK_InsertSubvector, VecTy, CostKind,
7002 ShuffleMask, SliceStart, SubVecTy);
7003 }
7004 // If masked gather cost is higher - better to vectorize, so
7005 // consider it as a gather node. It will be better estimated
7006 // later.
7007 if (MaskedGatherCost >= VecLdCost &&
7008 VecLdCost - GatherCost < -SLPCostThreshold) {
7009 if (BestVF)
7010 *BestVF = VF;
7011 return true;
7012 }
7013 }
7014 return MaskedGatherCost - GatherCost >= -SLPCostThreshold;
7015 };
7016 // TODO: need to improve analysis of the pointers, if not all of them are
7017 // GEPs or have > 2 operands, we end up with a gather node, which just
7018 // increases the cost.
7019 Loop *L = LI->getLoopFor(cast<LoadInst>(VL0)->getParent());
7020 bool ProfitableGatherPointers =
7021 L && Sz > 2 && static_cast<unsigned>(count_if(PointerOps, [L](Value *V) {
7022 return L->isLoopInvariant(V);
7023 })) <= Sz / 2;
7024 if (ProfitableGatherPointers || all_of(PointerOps, [](Value *P) {
7026 return (!GEP && doesNotNeedToBeScheduled(P)) ||
7027 (GEP && GEP->getNumOperands() == 2 &&
7028 isa<Constant, Instruction>(GEP->getOperand(1)));
7029 })) {
7030 // Check if potential masked gather can be represented as series
7031 // of loads + insertsubvectors.
7032 // If masked gather cost is higher - better to vectorize, so
7033 // consider it as a gather node. It will be better estimated
7034 // later.
7035 if (!TryRecursiveCheck || !CheckForShuffledLoads(CommonAlignment, BestVF,
7036 ProfitableGatherPointers))
7038 }
7039
7040 return LoadsState::Gather;
7041}
7042
7044 ArrayRef<BasicBlock *> BBs, Type *ElemTy,
7045 const DataLayout &DL, ScalarEvolution &SE,
7046 SmallVectorImpl<unsigned> &SortedIndices) {
7047 assert(
7048 all_of(VL, [](const Value *V) { return V->getType()->isPointerTy(); }) &&
7049 "Expected list of pointer operands.");
7050 // Map from bases to a vector of (Ptr, Offset, OrigIdx), which we insert each
7051 // Ptr into, sort and return the sorted indices with values next to one
7052 // another.
7054 std::pair<BasicBlock *, Value *>,
7056 Bases;
7057 Bases
7058 .try_emplace(std::make_pair(
7060 .first->second.emplace_back().emplace_back(VL.front(), 0U, 0U);
7061
7062 SortedIndices.clear();
7063 for (auto [Cnt, Ptr] : enumerate(VL.drop_front())) {
7064 auto Key = std::make_pair(BBs[Cnt + 1],
7066 bool Found = any_of(Bases.try_emplace(Key).first->second,
7067 [&, &Cnt = Cnt, &Ptr = Ptr](auto &Base) {
7068 std::optional<int64_t> Diff =
7069 getPointersDiff(ElemTy, std::get<0>(Base.front()),
7070 ElemTy, Ptr, DL, SE,
7071 /*StrictCheck=*/true);
7072 if (!Diff)
7073 return false;
7074
7075 Base.emplace_back(Ptr, *Diff, Cnt + 1);
7076 return true;
7077 });
7078
7079 if (!Found) {
7080 // If we haven't found enough to usefully cluster, return early.
7081 if (Bases.size() > VL.size() / 2 - 1)
7082 return false;
7083
7084 // Not found already - add a new Base
7085 Bases.find(Key)->second.emplace_back().emplace_back(Ptr, 0, Cnt + 1);
7086 }
7087 }
7088
7089 if (Bases.size() == VL.size())
7090 return false;
7091
7092 if (Bases.size() == 1 && (Bases.front().second.size() == 1 ||
7093 Bases.front().second.size() == VL.size()))
7094 return false;
7095
7096 // For each of the bases sort the pointers by Offset and check if any of the
7097 // base become consecutively allocated.
7098 auto ComparePointers = [](Value *Ptr1, Value *Ptr2) {
7099 SmallPtrSet<Value *, 13> FirstPointers;
7100 SmallPtrSet<Value *, 13> SecondPointers;
7101 Value *P1 = Ptr1;
7102 Value *P2 = Ptr2;
7103 unsigned Depth = 0;
7104 while (!FirstPointers.contains(P2) && !SecondPointers.contains(P1)) {
7105 if (P1 == P2 || Depth > RecursionMaxDepth)
7106 return false;
7107 FirstPointers.insert(P1);
7108 SecondPointers.insert(P2);
7109 P1 = getUnderlyingObject(P1, /*MaxLookup=*/1);
7110 P2 = getUnderlyingObject(P2, /*MaxLookup=*/1);
7111 ++Depth;
7112 }
7113 assert((FirstPointers.contains(P2) || SecondPointers.contains(P1)) &&
7114 "Unable to find matching root.");
7115 return FirstPointers.contains(P2) && !SecondPointers.contains(P1);
7116 };
7117 for (auto &Base : Bases) {
7118 for (auto &Vec : Base.second) {
7119 if (Vec.size() > 1) {
7121 int64_t InitialOffset = std::get<1>(Vec[0]);
7122 bool AnyConsecutive =
7123 all_of(enumerate(Vec), [InitialOffset](const auto &P) {
7124 return std::get<1>(P.value()) ==
7125 int64_t(P.index()) + InitialOffset;
7126 });
7127 // Fill SortedIndices array only if it looks worth-while to sort the
7128 // ptrs.
7129 if (!AnyConsecutive)
7130 return false;
7131 }
7132 }
7133 stable_sort(Base.second, [&](const auto &V1, const auto &V2) {
7134 return ComparePointers(std::get<0>(V1.front()), std::get<0>(V2.front()));
7135 });
7136 }
7137
7138 for (auto &T : Bases)
7139 for (const auto &Vec : T.second)
7140 for (const auto &P : Vec)
7141 SortedIndices.push_back(std::get<2>(P));
7142
7143 assert(SortedIndices.size() == VL.size() &&
7144 "Expected SortedIndices to be the size of VL");
7145 return true;
7146}
7147
7148std::optional<BoUpSLP::OrdersType>
7149BoUpSLP::findPartiallyOrderedLoads(const BoUpSLP::TreeEntry &TE) {
7150 assert(TE.isGather() && "Expected gather node only.");
7151 Type *ScalarTy = TE.Scalars[0]->getType();
7152
7154 Ptrs.reserve(TE.Scalars.size());
7156 BBs.reserve(TE.Scalars.size());
7157 for (Value *V : TE.Scalars) {
7158 auto *L = dyn_cast<LoadInst>(V);
7159 if (!L || !L->isSimple())
7160 return std::nullopt;
7161 Ptrs.push_back(L->getPointerOperand());
7162 BBs.push_back(L->getParent());
7163 }
7164
7165 BoUpSLP::OrdersType Order;
7166 if (!LoadEntriesToVectorize.contains(TE.Idx) &&
7167 clusterSortPtrAccesses(Ptrs, BBs, ScalarTy, *DL, *SE, Order))
7168 return std::move(Order);
7169 return std::nullopt;
7170}
7171
7172/// Check if two insertelement instructions are from the same buildvector.
7175 function_ref<Value *(InsertElementInst *)> GetBaseOperand) {
7176 // Instructions must be from the same basic blocks.
7177 if (VU->getParent() != V->getParent())
7178 return false;
7179 // Checks if 2 insertelements are from the same buildvector.
7180 if (VU->getType() != V->getType())
7181 return false;
7182 // Multiple used inserts are separate nodes.
7183 if (!VU->hasOneUse() && !V->hasOneUse())
7184 return false;
7185 auto *IE1 = VU;
7186 auto *IE2 = V;
7187 std::optional<unsigned> Idx1 = getElementIndex(IE1);
7188 std::optional<unsigned> Idx2 = getElementIndex(IE2);
7189 if (Idx1 == std::nullopt || Idx2 == std::nullopt)
7190 return false;
7191 // Go through the vector operand of insertelement instructions trying to find
7192 // either VU as the original vector for IE2 or V as the original vector for
7193 // IE1.
7195 bool IsReusedIdx = false;
7196 do {
7197 if (IE2 == VU && !IE1)
7198 return VU->hasOneUse();
7199 if (IE1 == V && !IE2)
7200 return V->hasOneUse();
7201 if (IE1 && IE1 != V) {
7202 unsigned Idx1 = getElementIndex(IE1).value_or(*Idx2);
7203 IsReusedIdx |= ReusedIdx.test(Idx1);
7204 ReusedIdx.set(Idx1);
7205 if ((IE1 != VU && !IE1->hasOneUse()) || IsReusedIdx)
7206 IE1 = nullptr;
7207 else
7208 IE1 = dyn_cast_or_null<InsertElementInst>(GetBaseOperand(IE1));
7209 }
7210 if (IE2 && IE2 != VU) {
7211 unsigned Idx2 = getElementIndex(IE2).value_or(*Idx1);
7212 IsReusedIdx |= ReusedIdx.test(Idx2);
7213 ReusedIdx.set(Idx2);
7214 if ((IE2 != V && !IE2->hasOneUse()) || IsReusedIdx)
7215 IE2 = nullptr;
7216 else
7217 IE2 = dyn_cast_or_null<InsertElementInst>(GetBaseOperand(IE2));
7218 }
7219 } while (!IsReusedIdx && (IE1 || IE2));
7220 return false;
7221}
7222
7223std::optional<BoUpSLP::OrdersType>
7224BoUpSLP::getReorderingData(const TreeEntry &TE, bool TopToBottom,
7225 bool IgnoreReorder) {
7226 // No need to reorder if need to shuffle reuses, still need to shuffle the
7227 // node.
7228 if (!TE.ReuseShuffleIndices.empty()) {
7229 if (isSplat(TE.Scalars))
7230 return std::nullopt;
7231 // Check if reuse shuffle indices can be improved by reordering.
7232 // For this, check that reuse mask is "clustered", i.e. each scalar values
7233 // is used once in each submask of size <number_of_scalars>.
7234 // Example: 4 scalar values.
7235 // ReuseShuffleIndices mask: 0, 1, 2, 3, 3, 2, 0, 1 - clustered.
7236 // 0, 1, 2, 3, 3, 3, 1, 0 - not clustered, because
7237 // element 3 is used twice in the second submask.
7238 unsigned Sz = TE.Scalars.size();
7239 if (TE.isGather()) {
7240 if (std::optional<OrdersType> CurrentOrder =
7241 findReusedOrderedScalars(TE, TopToBottom, IgnoreReorder)) {
7242 SmallVector<int> Mask;
7243 fixupOrderingIndices(*CurrentOrder);
7244 inversePermutation(*CurrentOrder, Mask);
7245 addMask(Mask, TE.ReuseShuffleIndices);
7246 OrdersType Res(TE.getVectorFactor(), TE.getVectorFactor());
7247 unsigned Sz = TE.Scalars.size();
7248 for (int K = 0, E = TE.getVectorFactor() / Sz; K < E; ++K) {
7249 for (auto [I, Idx] : enumerate(ArrayRef(Mask).slice(K * Sz, Sz)))
7250 if (Idx != PoisonMaskElem)
7251 Res[Idx + K * Sz] = I + K * Sz;
7252 }
7253 return std::move(Res);
7254 }
7255 }
7256 if (Sz == 2 && TE.getVectorFactor() == 4 &&
7258 *TTI,
7259 getWidenedType(getValueType(TE.Scalars.front(), SLPReVec),
7260 2 * TE.getVectorFactor()),
7261 getValueType(TE.Scalars.front(), SLPReVec)) == 1)
7262 return std::nullopt;
7263 if (TE.ReuseShuffleIndices.size() % Sz != 0)
7264 return std::nullopt;
7265 if (!ShuffleVectorInst::isOneUseSingleSourceMask(TE.ReuseShuffleIndices,
7266 Sz)) {
7267 SmallVector<int> ReorderMask(Sz, PoisonMaskElem);
7268 if (TE.ReorderIndices.empty())
7269 std::iota(ReorderMask.begin(), ReorderMask.end(), 0);
7270 else
7271 inversePermutation(TE.ReorderIndices, ReorderMask);
7272 addMask(ReorderMask, TE.ReuseShuffleIndices);
7273 unsigned VF = ReorderMask.size();
7274 OrdersType ResOrder(VF, VF);
7275 unsigned NumParts = divideCeil(VF, Sz);
7276 SmallBitVector UsedVals(NumParts);
7277 for (unsigned I = 0; I < VF; I += Sz) {
7278 int Val = PoisonMaskElem;
7279 unsigned UndefCnt = 0;
7280 unsigned Limit = std::min(Sz, VF - I);
7281 if (any_of(ArrayRef(ReorderMask).slice(I, Limit),
7282 [&](int Idx) {
7283 if (Val == PoisonMaskElem && Idx != PoisonMaskElem)
7284 Val = Idx;
7285 if (Idx == PoisonMaskElem)
7286 ++UndefCnt;
7287 return Idx != PoisonMaskElem && Idx != Val;
7288 }) ||
7289 Val >= static_cast<int>(NumParts) || Val == PoisonMaskElem ||
7290 UsedVals.test(Val) || UndefCnt > Sz / 2)
7291 return std::nullopt;
7292 UsedVals.set(Val);
7293 for (unsigned K = 0; K < NumParts; ++K) {
7294 unsigned Idx = Val + Sz * K;
7295 if (Idx < VF && I + K < VF)
7296 ResOrder[Idx] = I + K;
7297 }
7298 }
7299 return std::move(ResOrder);
7300 }
7301 unsigned VF = TE.getVectorFactor();
7302 // Try build correct order for extractelement instructions.
7303 SmallVector<int> ReusedMask(TE.ReuseShuffleIndices.begin(),
7304 TE.ReuseShuffleIndices.end());
7305 if (TE.hasState() && TE.getOpcode() == Instruction::ExtractElement &&
7306 !TE.hasCopyableElements() && all_of(TE.Scalars, [Sz](Value *V) {
7307 if (isa<PoisonValue>(V))
7308 return true;
7309 std::optional<unsigned> Idx = getExtractIndex(cast<Instruction>(V));
7310 return Idx && *Idx < Sz;
7311 })) {
7312 assert(!TE.isAltShuffle() && "Alternate instructions are only supported "
7313 "by BinaryOperator and CastInst.");
7314 SmallVector<int> ReorderMask(Sz, PoisonMaskElem);
7315 if (TE.ReorderIndices.empty())
7316 std::iota(ReorderMask.begin(), ReorderMask.end(), 0);
7317 else
7318 inversePermutation(TE.ReorderIndices, ReorderMask);
7319 for (unsigned I = 0; I < VF; ++I) {
7320 int &Idx = ReusedMask[I];
7321 if (Idx == PoisonMaskElem)
7322 continue;
7323 Value *V = TE.Scalars[ReorderMask[Idx]];
7324 std::optional<unsigned> EI = getExtractIndex(cast<Instruction>(V));
7325 Idx = std::distance(ReorderMask.begin(), find(ReorderMask, *EI));
7326 }
7327 }
7328 // Build the order of the VF size, need to reorder reuses shuffles, they are
7329 // always of VF size.
7330 OrdersType ResOrder(VF);
7331 std::iota(ResOrder.begin(), ResOrder.end(), 0);
7332 auto *It = ResOrder.begin();
7333 for (unsigned K = 0; K < VF; K += Sz) {
7334 OrdersType CurrentOrder(TE.ReorderIndices);
7335 SmallVector<int> SubMask{ArrayRef(ReusedMask).slice(K, Sz)};
7336 if (SubMask.front() == PoisonMaskElem)
7337 std::iota(SubMask.begin(), SubMask.end(), 0);
7338 reorderOrder(CurrentOrder, SubMask);
7339 transform(CurrentOrder, It, [K](unsigned Pos) { return Pos + K; });
7340 std::advance(It, Sz);
7341 }
7342 if (TE.isGather() && all_of(enumerate(ResOrder), [](const auto &Data) {
7343 return Data.index() == Data.value();
7344 }))
7345 return std::nullopt; // No need to reorder.
7346 return std::move(ResOrder);
7347 }
7348 if (TE.State == TreeEntry::StridedVectorize && !TopToBottom &&
7349 (!TE.UserTreeIndex || !TE.UserTreeIndex.UserTE->hasState() ||
7350 !Instruction::isBinaryOp(TE.UserTreeIndex.UserTE->getOpcode())) &&
7351 (TE.ReorderIndices.empty() || isReverseOrder(TE.ReorderIndices)))
7352 return std::nullopt;
7353 if (TE.State == TreeEntry::SplitVectorize ||
7354 ((TE.State == TreeEntry::Vectorize ||
7355 TE.State == TreeEntry::StridedVectorize ||
7356 TE.State == TreeEntry::ExpandVectorize ||
7357 TE.State == TreeEntry::CompressVectorize ||
7358 TE.State == TreeEntry::BlendedLoadVectorize) &&
7361 TE.getMainOp()))))) {
7362 assert((TE.State == TreeEntry::SplitVectorize || !TE.isAltShuffle()) &&
7363 "Alternate instructions are only supported by "
7364 "BinaryOperator and CastInst.");
7365 return TE.ReorderIndices;
7366 }
7367 if (!TopToBottom && IgnoreReorder && TE.State == TreeEntry::Vectorize &&
7368 TE.isAltShuffle()) {
7369 assert(TE.ReuseShuffleIndices.empty() &&
7370 "ReuseShuffleIndices should be "
7371 "empty for alternate instructions.");
7372 SmallVector<int> Mask;
7373 TE.buildAltOpShuffleMask(
7374 [&](Instruction *I) {
7375 assert(TE.getMatchingMainOpOrAltOp(I) &&
7376 "Unexpected main/alternate opcode");
7377 return isAlternateInstruction(I, TE.getMainOp(), TE.getAltOp(), *TLI);
7378 },
7379 Mask);
7380 const int VF = TE.getVectorFactor();
7381 OrdersType ResOrder(VF, VF);
7382 for (unsigned I : seq<unsigned>(VF)) {
7383 if (Mask[I] == PoisonMaskElem)
7384 continue;
7385 ResOrder[Mask[I] % VF] = I;
7386 }
7387 return std::move(ResOrder);
7388 }
7389 if (!TE.ReorderIndices.empty())
7390 return TE.ReorderIndices;
7391 if (TE.State == TreeEntry::Vectorize && TE.getOpcode() == Instruction::PHI) {
7392 if (!TE.ReorderIndices.empty())
7393 return TE.ReorderIndices;
7394
7395 SmallVector<Instruction *> UserBVHead(TE.Scalars.size());
7396 for (auto [I, V] : zip(UserBVHead, TE.Scalars)) {
7397 if (isa<Constant>(V) || !V->hasNUsesOrMore(1))
7398 continue;
7399 auto *II = dyn_cast<InsertElementInst>(*V->user_begin());
7400 if (!II)
7401 continue;
7402 Instruction *BVHead = nullptr;
7403 BasicBlock *BB = II->getParent();
7404 while (II && II->hasOneUse() && II->getParent() == BB) {
7405 BVHead = II;
7406 II = dyn_cast<InsertElementInst>(II->getOperand(0));
7407 }
7408 I = BVHead;
7409 }
7410
7411 auto CompareByBasicBlocks = [&](BasicBlock *BB1, BasicBlock *BB2) {
7412 assert(BB1 != BB2 && "Expected different basic blocks.");
7413 if (!DT->isReachableFromEntry(BB1))
7414 return false;
7415 if (!DT->isReachableFromEntry(BB2))
7416 return true;
7417 auto *NodeA = DT->getNode(BB1);
7418 auto *NodeB = DT->getNode(BB2);
7419 assert(NodeA && "Should only process reachable instructions");
7420 assert(NodeB && "Should only process reachable instructions");
7421 assert((NodeA == NodeB) ==
7422 (NodeA->getDFSNumIn() == NodeB->getDFSNumIn()) &&
7423 "Different nodes should have different DFS numbers");
7424 return NodeA->getDFSNumIn() < NodeB->getDFSNumIn();
7425 };
7426 auto PHICompare = [&](unsigned I1, unsigned I2) {
7427 Value *V1 = TE.Scalars[I1];
7428 Value *V2 = TE.Scalars[I2];
7429 if (V1 == V2 || (V1->use_empty() && V2->use_empty()))
7430 return false;
7431 if (isa<PoisonValue>(V1))
7432 return true;
7433 if (isa<PoisonValue>(V2))
7434 return false;
7435 if (V1->getNumUses() < V2->getNumUses())
7436 return true;
7437 if (V1->getNumUses() > V2->getNumUses())
7438 return false;
7439 auto *FirstUserOfPhi1 = cast<Instruction>(*V1->user_begin());
7440 auto *FirstUserOfPhi2 = cast<Instruction>(*V2->user_begin());
7441 if (FirstUserOfPhi1->getParent() != FirstUserOfPhi2->getParent())
7442 return CompareByBasicBlocks(FirstUserOfPhi1->getParent(),
7443 FirstUserOfPhi2->getParent());
7444 auto *IE1 = dyn_cast<InsertElementInst>(FirstUserOfPhi1);
7445 auto *IE2 = dyn_cast<InsertElementInst>(FirstUserOfPhi2);
7446 auto *EE1 = dyn_cast<ExtractElementInst>(FirstUserOfPhi1);
7447 auto *EE2 = dyn_cast<ExtractElementInst>(FirstUserOfPhi2);
7448 if (IE1 && !IE2)
7449 return true;
7450 if (!IE1 && IE2)
7451 return false;
7452 if (IE1 && IE2) {
7453 if (UserBVHead[I1] && !UserBVHead[I2])
7454 return true;
7455 if (!UserBVHead[I1])
7456 return false;
7457 if (UserBVHead[I1] == UserBVHead[I2])
7458 return getElementIndex(IE1) < getElementIndex(IE2);
7459 if (UserBVHead[I1]->getParent() != UserBVHead[I2]->getParent())
7460 return CompareByBasicBlocks(UserBVHead[I1]->getParent(),
7461 UserBVHead[I2]->getParent());
7462 return UserBVHead[I1]->comesBefore(UserBVHead[I2]);
7463 }
7464 if (EE1 && !EE2)
7465 return true;
7466 if (!EE1 && EE2)
7467 return false;
7468 if (EE1 && EE2) {
7469 auto *Inst1 = dyn_cast<Instruction>(EE1->getOperand(0));
7470 auto *Inst2 = dyn_cast<Instruction>(EE2->getOperand(0));
7471 auto *P1 = dyn_cast<Argument>(EE1->getOperand(0));
7472 auto *P2 = dyn_cast<Argument>(EE2->getOperand(0));
7473 if (!Inst2 && !P2)
7474 return Inst1 || P1;
7475 if (EE1->getOperand(0) == EE2->getOperand(0))
7476 return getElementIndex(EE1) < getElementIndex(EE2);
7477 if (!Inst1 && Inst2)
7478 return false;
7479 if (Inst1 && Inst2) {
7480 if (Inst1->getParent() != Inst2->getParent())
7481 return CompareByBasicBlocks(Inst1->getParent(), Inst2->getParent());
7482 return Inst1->comesBefore(Inst2);
7483 }
7484 if (!P1 && P2)
7485 return false;
7486 assert(P1 && P2 &&
7487 "Expected either instructions or arguments vector operands.");
7488 return P1->getArgNo() < P2->getArgNo();
7489 }
7490 return false;
7491 };
7492 OrdersType Phis(TE.Scalars.size());
7493 std::iota(Phis.begin(), Phis.end(), 0);
7494 stable_sort(Phis, PHICompare);
7495 if (isIdentityOrder(Phis))
7496 return std::nullopt; // No need to reorder.
7497 return std::move(Phis);
7498 }
7499 if (TE.isGather() &&
7500 (!TE.hasState() || !TE.isAltShuffle() ||
7501 ScalarsInSplitNodes.contains(TE.getMainOp())) &&
7502 allSameType(TE.Scalars)) {
7503 // TODO: add analysis of other gather nodes with extractelement
7504 // instructions and other values/instructions, not only undefs.
7505 // Nodes with copyable lanes may mix in non-extract lanes, for which the
7506 // extract-index order is not applicable.
7507 if (((TE.hasState() && TE.getOpcode() == Instruction::ExtractElement &&
7508 !TE.hasCopyableElements()) ||
7510 any_of(TE.Scalars, IsaPred<ExtractElementInst>))) &&
7511 all_of(TE.Scalars, [](Value *V) {
7512 auto *EE = dyn_cast<ExtractElementInst>(V);
7513 return !EE || isa<FixedVectorType>(EE->getVectorOperandType());
7514 })) {
7515 // Check that gather of extractelements can be represented as
7516 // just a shuffle of a single vector.
7517 OrdersType CurrentOrder;
7518 bool Reuse =
7519 canReuseExtract(TE.Scalars, CurrentOrder, /*ResizeAllowed=*/true);
7520 if (Reuse || !CurrentOrder.empty())
7521 return std::move(CurrentOrder);
7522 }
7523 // If the gather node is <undef, v, .., poison> and
7524 // insertelement poison, v, 0 [+ permute]
7525 // is cheaper than
7526 // insertelement poison, v, n - try to reorder.
7527 // If rotating the whole graph, exclude the permute cost, the whole graph
7528 // might be transformed.
7529 int Sz = TE.Scalars.size();
7530 if (isSplat(TE.Scalars) && !allConstant(TE.Scalars) &&
7531 count_if(TE.Scalars, IsaPred<UndefValue>) == Sz - 1) {
7532 const auto *It = find_if_not(TE.Scalars, isConstant);
7533 if (It == TE.Scalars.begin())
7534 return OrdersType();
7535 auto *Ty =
7536 cast<VectorType>(getWidenedType(TE.Scalars.front()->getType(), Sz));
7537 if (It != TE.Scalars.end()) {
7538 OrdersType Order(Sz, Sz);
7539 unsigned Idx = std::distance(TE.Scalars.begin(), It);
7540 Order[Idx] = 0;
7541 fixupOrderingIndices(Order);
7542 SmallVector<int> Mask;
7543 inversePermutation(Order, Mask);
7544 InstructionCost PermuteCost =
7545 TopToBottom ? 0
7547 CostKind, Mask);
7548 InstructionCost InsertFirstCost =
7549 TTI->getVectorInstrCost(Instruction::InsertElement, Ty, CostKind, 0,
7550 PoisonValue::get(Ty), *It);
7551 InstructionCost InsertIdxCost =
7552 TTI->getVectorInstrCost(Instruction::InsertElement, Ty, CostKind,
7553 Idx, PoisonValue::get(Ty), *It);
7554 if (InsertFirstCost + PermuteCost < InsertIdxCost) {
7555 OrdersType Order(Sz, Sz);
7556 Order[Idx] = 0;
7557 return std::move(Order);
7558 }
7559 }
7560 }
7561 if (isSplat(TE.Scalars))
7562 return std::nullopt;
7563 if (TE.Scalars.size() >= 3)
7564 if (std::optional<OrdersType> Order = findPartiallyOrderedLoads(TE))
7565 return Order;
7566 // Check if can include the order of vectorized loads. For masked gathers do
7567 // extra analysis later, so include such nodes into a special list.
7568 if (TE.hasState() && TE.getOpcode() == Instruction::Load) {
7569 SmallVector<Value *> PointerOps;
7570 StridedPtrInfo SPtrInfo;
7571 OrdersType CurrentOrder;
7572 LoadsState Res = canVectorizeLoads(TE.Scalars, TE.Scalars.front(),
7573 CurrentOrder, PointerOps, SPtrInfo);
7577 return std::move(CurrentOrder);
7578 }
7579 if (std::optional<OrdersType> CurrentOrder =
7580 findReusedOrderedScalars(TE, TopToBottom, IgnoreReorder))
7581 return CurrentOrder;
7582 }
7583 return std::nullopt;
7584}
7585
7586/// Checks if the given mask is a "clustered" mask with the same clusters of
7587/// size \p Sz, which are not identity submasks.
7589 unsigned Sz) {
7590 ArrayRef<int> FirstCluster = Mask.slice(0, Sz);
7591 if (ShuffleVectorInst::isIdentityMask(FirstCluster, Sz))
7592 return false;
7593 for (unsigned I = Sz, E = Mask.size(); I < E; I += Sz) {
7594 ArrayRef<int> Cluster = Mask.slice(I, Sz);
7595 if (Cluster != FirstCluster)
7596 return false;
7597 }
7598 return true;
7599}
7600
7601void BoUpSLP::reorderNodeWithReuses(TreeEntry &TE, ArrayRef<int> Mask) const {
7602 // Reorder reuses mask.
7603 reorderReuses(TE.ReuseShuffleIndices, Mask);
7604 const unsigned Sz = TE.Scalars.size();
7605 // For vectorized and non-clustered reused no need to do anything else.
7606 if (!TE.isGather() ||
7608 Sz) ||
7609 !isRepeatedNonIdentityClusteredMask(TE.ReuseShuffleIndices, Sz))
7610 return;
7611 SmallVector<int> NewMask;
7612 inversePermutation(TE.ReorderIndices, NewMask);
7613 addMask(NewMask, TE.ReuseShuffleIndices);
7614 // Clear reorder since it is going to be applied to the new mask.
7615 TE.ReorderIndices.clear();
7616 // Try to improve gathered nodes with clustered reuses, if possible.
7617 ArrayRef<int> Slice = ArrayRef(NewMask).slice(0, Sz);
7618 SmallVector<unsigned> NewOrder(Slice);
7619 inversePermutation(NewOrder, NewMask);
7620 reorderScalars(TE.Scalars, NewMask);
7621 // Fill the reuses mask with the identity submasks.
7622 for (auto *It = TE.ReuseShuffleIndices.begin(),
7623 *End = TE.ReuseShuffleIndices.end();
7624 It != End; std::advance(It, Sz))
7625 std::iota(It, std::next(It, Sz), 0);
7626}
7627
7629 ArrayRef<unsigned> SecondaryOrder) {
7630 assert((SecondaryOrder.empty() || Order.size() == SecondaryOrder.size()) &&
7631 "Expected same size of orders");
7632 size_t Sz = Order.size();
7633 SmallBitVector UsedIndices(Sz);
7634 for (unsigned Idx : seq<unsigned>(0, Sz)) {
7635 if (Order[Idx] != Sz)
7636 UsedIndices.set(Order[Idx]);
7637 }
7638 if (SecondaryOrder.empty()) {
7639 for (unsigned Idx : seq<unsigned>(0, Sz))
7640 if (Order[Idx] == Sz && !UsedIndices.test(Idx))
7641 Order[Idx] = Idx;
7642 } else {
7643 for (unsigned Idx : seq<unsigned>(0, Sz))
7644 if (SecondaryOrder[Idx] != Sz && Order[Idx] == Sz &&
7645 !UsedIndices.test(SecondaryOrder[Idx]))
7646 Order[Idx] = SecondaryOrder[Idx];
7647 }
7648}
7649
7652 return false;
7653
7654 constexpr unsigned TinyVF = 2;
7655 constexpr unsigned TinyTree = 10;
7656 constexpr unsigned PhiOpsLimit = 12;
7657 constexpr unsigned GatherLoadsLimit = 2;
7658 if (VectorizableTree.size() <= TinyTree)
7659 return true;
7660 if (getRootNode().hasState() && !getRootNode().isGather() &&
7661 (getRootNode().getOpcode() == Instruction::Store ||
7662 getRootNode().getOpcode() == Instruction::PHI ||
7663 (getRootNode().getVectorFactor() <= TinyVF &&
7664 (getRootNode().getOpcode() == Instruction::PtrToInt ||
7665 getRootNode().getOpcode() == Instruction::PtrToAddr ||
7666 getRootNode().getOpcode() == Instruction::ICmp))) &&
7667 getRootNode().ReorderIndices.empty()) {
7668 // Check if the tree has only single store and single (unordered) load node,
7669 // other nodes are phis or geps/binops, combined with phis, and/or single
7670 // gather load node
7671 if (getRootNode().hasState() &&
7672 getRootNode().getOpcode() == Instruction::PHI &&
7673 getRootNodeScalars().size() == TinyVF &&
7674 getRootNode().getNumOperands() > PhiOpsLimit)
7675 return false;
7676 // Single node, which require reorder - skip.
7677 if (getRootNode().hasState() &&
7678 getRootNode().getOpcode() == Instruction::Store &&
7679 getRootNode().ReorderIndices.empty()) {
7680 const unsigned ReorderedSplitsCnt =
7681 count_if(VectorizableTree, [&](const std::unique_ptr<TreeEntry> &TE) {
7682 return TE->State == TreeEntry::SplitVectorize &&
7683 !TE->ReorderIndices.empty() && TE->UserTreeIndex.UserTE &&
7684 TE->UserTreeIndex.UserTE->State == TreeEntry::Vectorize &&
7685 isCommutative(TE->UserTreeIndex.UserTE->getMainOp());
7686 });
7687 if (ReorderedSplitsCnt <= 1 &&
7688 static_cast<unsigned>(count_if(
7689 VectorizableTree, [&](const std::unique_ptr<TreeEntry> &TE) {
7690 return ((!TE->isGather() &&
7691 (TE->ReorderIndices.empty() ||
7692 (TE->UserTreeIndex.UserTE &&
7693 TE->UserTreeIndex.UserTE->State ==
7694 TreeEntry::Vectorize &&
7695 !TE->UserTreeIndex.UserTE->ReuseShuffleIndices
7696 .empty()))) ||
7697 (TE->isGather() && TE->ReorderIndices.empty() &&
7698 (!TE->hasState() || TE->isAltShuffle() ||
7699 TE->getOpcode() == Instruction::Load ||
7700 TE->getOpcode() == Instruction::ZExt ||
7701 TE->getOpcode() == Instruction::SExt))) &&
7702 (getRootNode().getVectorFactor() > TinyVF ||
7703 !TE->isGather() || none_of(TE->Scalars, [&](Value *V) {
7704 return !isConstant(V) && isVectorized(V);
7705 }));
7706 })) >= VectorizableTree.size() - ReorderedSplitsCnt)
7707 return false;
7708 }
7709 bool HasPhis = false;
7710 bool HasLoad = true;
7711 unsigned GatherLoads = 0;
7712 for (const std::unique_ptr<TreeEntry> &TE :
7713 ArrayRef(VectorizableTree).drop_front()) {
7714 if (TE->State == TreeEntry::SplitVectorize)
7715 continue;
7716 if (!TE->hasState()) {
7717 if (all_of(TE->Scalars, IsaPred<Constant, PHINode>) ||
7719 continue;
7720 if (getRootNodeScalars().size() == TinyVF &&
7722 continue;
7723 return true;
7724 }
7725 if (TE->getOpcode() == Instruction::Load && TE->ReorderIndices.empty()) {
7726 if (!TE->isGather()) {
7727 HasLoad = false;
7728 continue;
7729 }
7730 if (HasLoad)
7731 return true;
7732 ++GatherLoads;
7733 if (GatherLoads >= GatherLoadsLimit)
7734 return true;
7735 }
7736 if (TE->getOpcode() == Instruction::GetElementPtr ||
7737 Instruction::isBinaryOp(TE->getOpcode()))
7738 continue;
7739 if (TE->getOpcode() != Instruction::PHI &&
7740 (!TE->hasCopyableElements() ||
7741 static_cast<unsigned>(count_if(TE->Scalars, IsaPred<PHINode>)) <
7742 TE->Scalars.size() / 2))
7743 return true;
7744 if (getRootNodeScalars().size() == TinyVF &&
7745 TE->getNumOperands() > PhiOpsLimit)
7746 return false;
7747 HasPhis = true;
7748 }
7749 return !HasPhis;
7750 }
7751 return true;
7752}
7753
7754void BoUpSLP::TreeEntry::reorderSplitNode(unsigned Idx, ArrayRef<int> Mask,
7755 ArrayRef<int> MaskOrder) {
7756 assert(State == TreeEntry::SplitVectorize && "Expected split user node.");
7757 SmallVector<int> NewMask(getVectorFactor());
7758 SmallVector<int> NewMaskOrder(getVectorFactor());
7759 std::iota(NewMask.begin(), NewMask.end(), 0);
7760 std::iota(NewMaskOrder.begin(), NewMaskOrder.end(), 0);
7761 if (Idx == 0) {
7762 copy(Mask, NewMask.begin());
7763 copy(MaskOrder, NewMaskOrder.begin());
7764 } else {
7765 assert(Idx == 1 && "Expected either 0 or 1 index.");
7766 unsigned Offset = CombinedEntriesWithIndices.back().second;
7767 for (unsigned I : seq<unsigned>(Mask.size())) {
7768 NewMask[I + Offset] = Mask[I] + Offset;
7769 NewMaskOrder[I + Offset] = MaskOrder[I] + Offset;
7770 }
7771 }
7772 reorderScalars(Scalars, NewMask);
7773 reorderOrder(ReorderIndices, NewMaskOrder, /*BottomOrder=*/true);
7774 if (!ReorderIndices.empty() && BoUpSLP::isIdentityOrder(ReorderIndices))
7775 ReorderIndices.clear();
7776}
7777
7779 if (!TE.hasState())
7780 return;
7781 if (auto It = BlocksSchedules.find(TE.getMainOp()->getParent());
7782 It != BlocksSchedules.end())
7783 It->second->markCopyableDepsForRecalc(TE);
7784}
7785
7787 // Maps VF to the graph nodes.
7789 // ExtractElement gather nodes which can be vectorized and need to handle
7790 // their ordering.
7792
7793 // Phi nodes can have preferred ordering based on their result users
7795
7796 // AltShuffles can also have a preferred ordering that leads to fewer
7797 // instructions, e.g., the addsub instruction in x86.
7798 DenseMap<const TreeEntry *, OrdersType> AltShufflesToOrders;
7799
7800 // Maps a TreeEntry to the reorder indices of external users.
7802 ExternalUserReorderMap;
7803 // TODO: Reordering of struct types is not supported.
7804 if (any_of(VectorizableTree, [](const std::unique_ptr<TreeEntry> &TE) {
7805 return TE->State == TreeEntry::Vectorize &&
7806 isa<StructType>(getValueType(TE->Scalars.front(), SLPReVec));
7807 }))
7808 return;
7809 // Compute IgnoreReorder once - it depends only on UserIgnoreList and
7810 // getRootNode(), which do not change during this loop.
7811 const bool IgnoreReorder =
7812 !UserIgnoreList && getRootNode().hasState() &&
7813 (getRootNode().getOpcode() == Instruction::InsertElement ||
7814 getRootNode().getOpcode() == Instruction::InsertValue ||
7815 getRootNode().getOpcode() == Instruction::Store);
7816 // Find all reorderable nodes with the given VF.
7817 // Currently the are vectorized stores,loads,extracts + some gathering of
7818 // extracts.
7819 for_each(VectorizableTree, [&, &TTIRef = *TTI](
7820 const std::unique_ptr<TreeEntry> &TE) {
7821 // Look for external users that will probably be vectorized.
7822 SmallVector<OrdersType, 1> ExternalUserReorderIndices =
7823 findExternalStoreUsersReorderIndices(TE.get());
7824 if (!ExternalUserReorderIndices.empty()) {
7825 VFToOrderedEntries[TE->getVectorFactor()].insert(TE.get());
7826 ExternalUserReorderMap.try_emplace(TE.get(),
7827 std::move(ExternalUserReorderIndices));
7828 }
7829
7830 // Patterns like [fadd,fsub] can be combined into a single instruction in
7831 // x86. Reordering them into [fsub,fadd] blocks this pattern. So we need
7832 // to take into account their order when looking for the most used order.
7833 if (TE->hasState() && TE->isAltShuffle() &&
7834 TE->State != TreeEntry::SplitVectorize) {
7835 Type *ScalarTy = TE->Scalars[0]->getType();
7836 auto *VecTy =
7837 cast<VectorType>(getWidenedType(ScalarTy, TE->Scalars.size()));
7838 unsigned Opcode0 = TE->getOpcode();
7839 unsigned Opcode1 = TE->getAltOpcode();
7840 SmallBitVector OpcodeMask(
7841 getAltInstrMask(TE->Scalars, ScalarTy, Opcode0, Opcode1));
7842 // If this pattern is supported by the target then we consider the order.
7843 if (TTIRef.isLegalAltInstr(VecTy, Opcode0, Opcode1, OpcodeMask)) {
7844 VFToOrderedEntries[TE->getVectorFactor()].insert(TE.get());
7845 AltShufflesToOrders.try_emplace(TE.get(), OrdersType());
7846 }
7847 // TODO: Check the reverse order too.
7848 }
7849
7850 if (std::optional<OrdersType> CurrentOrder =
7851 getReorderingData(*TE, /*TopToBottom=*/true, IgnoreReorder)) {
7852 // Do not include ordering for nodes used in the alt opcode vectorization,
7853 // better to reorder them during bottom-to-top stage. If follow the order
7854 // here, it causes reordering of the whole graph though actually it is
7855 // profitable just to reorder the subgraph that starts from the alternate
7856 // opcode vectorization node. Such nodes already end-up with the shuffle
7857 // instruction and it is just enough to change this shuffle rather than
7858 // rotate the scalars for the whole graph.
7859 unsigned Cnt = 0;
7860 const TreeEntry *UserTE = TE.get();
7861 while (UserTE && Cnt < RecursionMaxDepth) {
7862 if (!UserTE->UserTreeIndex)
7863 break;
7864 if (UserTE->UserTreeIndex.UserTE->State == TreeEntry::Vectorize &&
7865 UserTE->UserTreeIndex.UserTE->isAltShuffle() &&
7866 UserTE->UserTreeIndex.UserTE->Idx != 0)
7867 return;
7868 UserTE = UserTE->UserTreeIndex.UserTE;
7869 ++Cnt;
7870 }
7871 VFToOrderedEntries[TE->getVectorFactor()].insert(TE.get());
7872 if (!(TE->State == TreeEntry::Vectorize ||
7873 TE->State == TreeEntry::StridedVectorize ||
7874 TE->State == TreeEntry::ExpandVectorize ||
7875 TE->State == TreeEntry::SplitVectorize ||
7876 TE->State == TreeEntry::CompressVectorize ||
7877 TE->State == TreeEntry::BlendedLoadVectorize) ||
7878 !TE->ReuseShuffleIndices.empty())
7879 GathersToOrders.try_emplace(TE.get(), *CurrentOrder);
7880 if (TE->State == TreeEntry::Vectorize &&
7881 TE->getOpcode() == Instruction::PHI)
7882 PhisToOrders.try_emplace(TE.get(), *CurrentOrder);
7883 }
7884 });
7885
7886 // Reorder the graph nodes according to their vectorization factor.
7887 for (unsigned VF = getRootNode().getVectorFactor();
7888 !VFToOrderedEntries.empty() && VF > 1; --VF) {
7889 auto It = VFToOrderedEntries.find(VF);
7890 if (It == VFToOrderedEntries.end())
7891 continue;
7892 // Try to find the most profitable order. We just are looking for the most
7893 // used order and reorder scalar elements in the nodes according to this
7894 // mostly used order.
7895 ArrayRef<TreeEntry *> OrderedEntries = It->second.getArrayRef();
7896 // Delete VF entry upon exit.
7897 llvm::scope_exit Cleanup([&]() { VFToOrderedEntries.erase(It); });
7898
7899 // All operands are reordered and used only in this node - propagate the
7900 // most used order to the user node.
7903 OrdersUses;
7904 for (const TreeEntry *OpTE : OrderedEntries) {
7905 // No need to reorder this nodes, still need to extend and to use shuffle,
7906 // just need to merge reordering shuffle and the reuse shuffle.
7907 if (!OpTE->ReuseShuffleIndices.empty() && !GathersToOrders.count(OpTE) &&
7908 OpTE->State != TreeEntry::SplitVectorize)
7909 continue;
7910 // Count number of orders uses.
7911 const auto &Order = [OpTE, &GathersToOrders, &AltShufflesToOrders,
7912 &PhisToOrders]() -> const OrdersType & {
7913 if (OpTE->isGather() || !OpTE->ReuseShuffleIndices.empty()) {
7914 auto It = GathersToOrders.find(OpTE);
7915 if (It != GathersToOrders.end())
7916 return It->second;
7917 }
7918 if (OpTE->hasState() && OpTE->isAltShuffle()) {
7919 auto It = AltShufflesToOrders.find(OpTE);
7920 if (It != AltShufflesToOrders.end())
7921 return It->second;
7922 }
7923 if (OpTE->State == TreeEntry::Vectorize &&
7924 OpTE->getOpcode() == Instruction::PHI) {
7925 auto It = PhisToOrders.find(OpTE);
7926 if (It != PhisToOrders.end())
7927 return It->second;
7928 }
7929 return OpTE->ReorderIndices;
7930 }();
7931 // First consider the order of the external scalar users.
7932 auto It = ExternalUserReorderMap.find(OpTE);
7933 if (It != ExternalUserReorderMap.end()) {
7934 const auto &ExternalUserReorderIndices = It->second;
7935 // If the OpTE vector factor != number of scalars - use natural order,
7936 // it is an attempt to reorder node with reused scalars but with
7937 // external uses.
7938 if (OpTE->getVectorFactor() != OpTE->Scalars.size()) {
7939 OrdersUses.try_emplace(OrdersType(), 0).first->second +=
7940 ExternalUserReorderIndices.size();
7941 } else {
7942 for (const OrdersType &ExtOrder : ExternalUserReorderIndices)
7943 ++OrdersUses.try_emplace(ExtOrder, 0).first->second;
7944 }
7945 // No other useful reorder data in this entry.
7946 if (Order.empty())
7947 continue;
7948 }
7949 // Stores actually store the mask, not the order, need to invert.
7950 if (OpTE->State == TreeEntry::Vectorize &&
7951 OpTE->getOpcode() == Instruction::Store && !Order.empty()) {
7952 assert(!OpTE->isAltShuffle() &&
7953 "Alternate instructions are only supported by BinaryOperator "
7954 "and CastInst.");
7955 SmallVector<int> Mask;
7956 inversePermutation(Order, Mask);
7957 unsigned E = Order.size();
7958 OrdersType CurrentOrder(E, E);
7959 transform(Mask, CurrentOrder.begin(), [E](int Idx) {
7960 return Idx == PoisonMaskElem ? E : static_cast<unsigned>(Idx);
7961 });
7962 fixupOrderingIndices(CurrentOrder);
7963 ++OrdersUses.try_emplace(CurrentOrder, 0).first->second;
7964 } else {
7965 ++OrdersUses.try_emplace(Order, 0).first->second;
7966 }
7967 }
7968 if (OrdersUses.empty())
7969 continue;
7970 // Choose the most used order.
7971 unsigned IdentityCnt = 0;
7972 unsigned FilledIdentityCnt = 0;
7973 OrdersType IdentityOrder(VF, VF);
7974 for (auto &Pair : OrdersUses) {
7975 if (Pair.first.empty() || isIdentityOrder(Pair.first)) {
7976 if (!Pair.first.empty())
7977 FilledIdentityCnt += Pair.second;
7978 IdentityCnt += Pair.second;
7979 combineOrders(IdentityOrder, Pair.first);
7980 }
7981 }
7982 MutableArrayRef<unsigned> BestOrder = IdentityOrder;
7983 unsigned Cnt = IdentityCnt;
7984 for (auto &Pair : OrdersUses) {
7985 // Prefer identity order. But, if filled identity found (non-empty order)
7986 // with same number of uses, as the new candidate order, we can choose
7987 // this candidate order.
7988 if (Cnt < Pair.second ||
7989 (Cnt == IdentityCnt && IdentityCnt == FilledIdentityCnt &&
7990 Cnt == Pair.second && !BestOrder.empty() &&
7991 isIdentityOrder(BestOrder))) {
7992 combineOrders(Pair.first, BestOrder);
7993 BestOrder = Pair.first;
7994 Cnt = Pair.second;
7995 } else {
7996 combineOrders(BestOrder, Pair.first);
7997 }
7998 }
7999 // Set order of the user node.
8000 if (isIdentityOrder(BestOrder))
8001 continue;
8002 fixupOrderingIndices(BestOrder);
8003 SmallVector<int> Mask;
8004 inversePermutation(BestOrder, Mask);
8005 SmallVector<int> MaskOrder(BestOrder.size(), PoisonMaskElem);
8006 unsigned E = BestOrder.size();
8007 transform(BestOrder, MaskOrder.begin(), [E](unsigned I) {
8008 return I < E ? static_cast<int>(I) : PoisonMaskElem;
8009 });
8010 // Do an actual reordering, if profitable.
8011 for (std::unique_ptr<TreeEntry> &TE : VectorizableTree) {
8012 // Just do the reordering for the nodes with the given VF.
8013 if (TE->Scalars.size() != VF) {
8014 if (TE->ReuseShuffleIndices.size() == VF &&
8015 TE->State != TreeEntry::ExpandVectorize) {
8016 assert(TE->State != TreeEntry::SplitVectorize &&
8017 "Split vectorized not expected.");
8018 // Need to reorder the reuses masks of the operands with smaller VF to
8019 // be able to find the match between the graph nodes and scalar
8020 // operands of the given node during vectorization/cost estimation.
8021 assert(
8022 (!TE->UserTreeIndex ||
8023 TE->UserTreeIndex.UserTE->Scalars.size() == VF ||
8024 TE->UserTreeIndex.UserTE->Scalars.size() == TE->Scalars.size() ||
8025 TE->UserTreeIndex.UserTE->State == TreeEntry::SplitVectorize) &&
8026 "All users must be of VF size.");
8027 if (SLPReVec) {
8028 assert(SLPReVec && "Only supported by REVEC.");
8029 // ShuffleVectorInst does not do reorderOperands (and it should not
8030 // because ShuffleVectorInst supports only a limited set of
8031 // patterns). Only do reorderNodeWithReuses if the user is not
8032 // ShuffleVectorInst.
8033 if (TE->UserTreeIndex && TE->UserTreeIndex.UserTE->hasState() &&
8034 isa<ShuffleVectorInst>(TE->UserTreeIndex.UserTE->getMainOp()))
8035 continue;
8036 }
8037 // Update ordering of the operands with the smaller VF than the given
8038 // one.
8039 reorderNodeWithReuses(*TE, Mask);
8040 // Update orders in user split vectorize nodes.
8041 if (TE->UserTreeIndex &&
8042 TE->UserTreeIndex.UserTE->State == TreeEntry::SplitVectorize)
8043 TE->UserTreeIndex.UserTE->reorderSplitNode(
8044 TE->UserTreeIndex.EdgeIdx, Mask, MaskOrder);
8045 }
8046 continue;
8047 }
8048 if ((TE->State == TreeEntry::SplitVectorize &&
8049 TE->ReuseShuffleIndices.empty()) ||
8050 ((TE->State == TreeEntry::Vectorize ||
8051 TE->State == TreeEntry::StridedVectorize ||
8052 TE->State == TreeEntry::ExpandVectorize ||
8053 TE->State == TreeEntry::CompressVectorize ||
8054 TE->State == TreeEntry::BlendedLoadVectorize) &&
8056 InsertElementInst, InsertValueInst>(TE->getMainOp()) ||
8057 (SLPReVec && isa<ShuffleVectorInst>(TE->getMainOp()))))) {
8058 assert(
8059 (!TE->isAltShuffle() || (TE->State == TreeEntry::SplitVectorize &&
8060 TE->ReuseShuffleIndices.empty())) &&
8061 "Alternate instructions are only supported by BinaryOperator "
8062 "and CastInst.");
8063 // Build correct orders for extract{element,value}, loads,
8064 // stores and alternate (split) nodes.
8065 reorderOrder(TE->ReorderIndices, Mask);
8067 TE->getMainOp())) {
8068 TE->reorderOperands(Mask);
8070 }
8071 } else {
8072 // Reorder the node and its operands.
8073 TE->reorderOperands(Mask);
8075 assert(TE->ReorderIndices.empty() &&
8076 "Expected empty reorder sequence.");
8077 reorderScalars(TE->Scalars, Mask);
8078 }
8079 if (!TE->ReuseShuffleIndices.empty() &&
8080 TE->State != TreeEntry::ExpandVectorize) {
8081 // Apply reversed order to keep the original ordering of the reused
8082 // elements to avoid extra reorder indices shuffling. An ExpandVectorize
8083 // store keeps its expand mask fixed and carries the reorder in
8084 // ReorderIndices, so it is excluded here.
8085 OrdersType CurrentOrder;
8086 reorderOrder(CurrentOrder, MaskOrder);
8087 SmallVector<int> NewReuses;
8088 inversePermutation(CurrentOrder, NewReuses);
8089 addMask(NewReuses, TE->ReuseShuffleIndices);
8090 TE->ReuseShuffleIndices.swap(NewReuses);
8091 } else if (TE->UserTreeIndex &&
8092 TE->UserTreeIndex.UserTE->State == TreeEntry::SplitVectorize)
8093 // Update orders in user split vectorize nodes.
8094 TE->UserTreeIndex.UserTE->reorderSplitNode(TE->UserTreeIndex.EdgeIdx,
8095 Mask, MaskOrder);
8096 }
8097 }
8098}
8099
8100void BoUpSLP::buildReorderableOperands(
8101 TreeEntry *UserTE, SmallVectorImpl<std::pair<unsigned, TreeEntry *>> &Edges,
8102 const SmallPtrSetImpl<const TreeEntry *> &ReorderableGathers,
8103 SmallVectorImpl<TreeEntry *> &GatherOps) {
8104 for (unsigned I : seq<unsigned>(UserTE->getNumOperands())) {
8105 if (any_of(Edges, [I](const std::pair<unsigned, TreeEntry *> &OpData) {
8106 return OpData.first == I &&
8107 (OpData.second->State == TreeEntry::Vectorize ||
8108 OpData.second->State == TreeEntry::StridedVectorize ||
8109 OpData.second->State == TreeEntry::ExpandVectorize ||
8110 OpData.second->State == TreeEntry::CompressVectorize ||
8111 OpData.second->State == TreeEntry::BlendedLoadVectorize ||
8112 OpData.second->State == TreeEntry::SplitVectorize);
8113 }))
8114 continue;
8115 // Do not request operands, if they do not exist.
8116 if (UserTE->hasState()) {
8117 if (UserTE->getOpcode() == Instruction::ExtractElement ||
8118 UserTE->getOpcode() == Instruction::ExtractValue)
8119 continue;
8120 if ((UserTE->getOpcode() == Instruction::InsertElement ||
8121 UserTE->getOpcode() == Instruction::InsertValue) &&
8122 I == 0)
8123 continue;
8124 if (UserTE->getOpcode() == Instruction::Store && I == 1 &&
8125 (UserTE->State == TreeEntry::Vectorize ||
8126 UserTE->State == TreeEntry::StridedVectorize ||
8127 UserTE->State == TreeEntry::ExpandVectorize))
8128 continue;
8129 if (UserTE->getOpcode() == Instruction::Load &&
8130 (UserTE->State == TreeEntry::Vectorize ||
8131 UserTE->State == TreeEntry::StridedVectorize ||
8132 UserTE->State == TreeEntry::CompressVectorize ||
8133 UserTE->State == TreeEntry::BlendedLoadVectorize))
8134 continue;
8135 }
8136 TreeEntry *TE = getOperandEntry(UserTE, I);
8137 assert(TE && "Expected operand entry.");
8138 if (!TE->isGather()) {
8139 // Add the node to the list of the ordered nodes with the identity
8140 // order.
8141 Edges.emplace_back(I, TE);
8142 // Add ScatterVectorize nodes to the list of operands, where just
8143 // reordering of the scalars is required. Similar to the gathers, so
8144 // simply add to the list of gathered ops.
8145 // If there are reused scalars, process this node as a regular vectorize
8146 // node, just reorder reuses mask.
8147 if (TE->State == TreeEntry::ScatterVectorize &&
8148 TE->ReuseShuffleIndices.empty() && TE->ReorderIndices.empty())
8149 GatherOps.push_back(TE);
8150 continue;
8151 }
8152 if (ReorderableGathers.contains(TE))
8153 GatherOps.push_back(TE);
8154 }
8155}
8156
8157void BoUpSLP::reorderBottomToTop(bool IgnoreReorder) {
8158 struct TreeEntryCompare {
8159 bool operator()(const TreeEntry *LHS, const TreeEntry *RHS) const {
8160 if (LHS->UserTreeIndex && RHS->UserTreeIndex)
8161 return LHS->UserTreeIndex.UserTE->Idx < RHS->UserTreeIndex.UserTE->Idx;
8162 return LHS->Idx < RHS->Idx;
8163 }
8164 };
8166 DenseSet<const TreeEntry *> GathersToOrders;
8167 // Find all reorderable leaf nodes with the given VF.
8168 // Currently the are vectorized loads,extracts without alternate operands +
8169 // some gathering of extracts.
8171 for (const std::unique_ptr<TreeEntry> &TE : VectorizableTree) {
8172 if (TE->State != TreeEntry::Vectorize &&
8173 TE->State != TreeEntry::StridedVectorize &&
8174 TE->State != TreeEntry::ExpandVectorize &&
8175 TE->State != TreeEntry::CompressVectorize &&
8176 TE->State != TreeEntry::BlendedLoadVectorize &&
8177 TE->State != TreeEntry::SplitVectorize)
8178 NonVectorized.insert(TE.get());
8179 if (std::optional<OrdersType> CurrentOrder =
8180 getReorderingData(*TE, /*TopToBottom=*/false, IgnoreReorder)) {
8181 Queue.push(TE.get());
8182 if (!(TE->State == TreeEntry::Vectorize ||
8183 TE->State == TreeEntry::StridedVectorize ||
8184 TE->State == TreeEntry::ExpandVectorize ||
8185 TE->State == TreeEntry::CompressVectorize ||
8186 TE->State == TreeEntry::BlendedLoadVectorize ||
8187 TE->State == TreeEntry::SplitVectorize) ||
8188 !TE->ReuseShuffleIndices.empty())
8189 GathersToOrders.insert(TE.get());
8190 }
8191 }
8192
8193 // 1. Propagate order to the graph nodes, which use only reordered nodes.
8194 // I.e., if the node has operands, that are reordered, try to make at least
8195 // one operand order in the natural order and reorder others + reorder the
8196 // user node itself.
8197 SmallPtrSet<const TreeEntry *, 4> Visited, RevisitedOps;
8198 while (!Queue.empty()) {
8199 // 1. Filter out only reordered nodes.
8200 std::pair<TreeEntry *, SmallVector<std::pair<unsigned, TreeEntry *>>> Users;
8201 TreeEntry *TE = Queue.top();
8202 const TreeEntry *UserTE = TE->UserTreeIndex.UserTE;
8203 Queue.pop();
8204 SmallVector<TreeEntry *> OrderedOps(1, TE);
8205 while (!Queue.empty()) {
8206 TE = Queue.top();
8207 if (!UserTE || UserTE != TE->UserTreeIndex.UserTE)
8208 break;
8209 Queue.pop();
8210 OrderedOps.push_back(TE);
8211 }
8212 for (TreeEntry *TE : OrderedOps) {
8213 if (!(TE->State == TreeEntry::Vectorize ||
8214 TE->State == TreeEntry::StridedVectorize ||
8215 TE->State == TreeEntry::ExpandVectorize ||
8216 TE->State == TreeEntry::CompressVectorize ||
8217 TE->State == TreeEntry::BlendedLoadVectorize ||
8218 TE->State == TreeEntry::SplitVectorize ||
8219 (TE->isGather() && GathersToOrders.contains(TE))) ||
8220 !TE->UserTreeIndex ||
8221 TE->UserTreeIndex.UserTE->State == TreeEntry::BlendedLoadVectorize ||
8222 !TE->ReuseShuffleIndices.empty() || !Visited.insert(TE).second)
8223 continue;
8224 // Build a map between user nodes and their operands order to speedup
8225 // search. The graph currently does not provide this dependency directly.
8226 Users.first = TE->UserTreeIndex.UserTE;
8227 Users.second.emplace_back(TE->UserTreeIndex.EdgeIdx, TE);
8228 }
8229 if (Users.first) {
8230 auto &Data = Users;
8231 // TODO: Reordering of struct types is not supported.
8232 if (Data.first->State == TreeEntry::Vectorize &&
8233 isa<StructType>(getValueType(Data.first->Scalars.front(), SLPReVec)))
8234 continue;
8235 if (Data.first->State == TreeEntry::SplitVectorize) {
8236 assert(
8237 Data.second.size() <= 2 &&
8238 "Expected not greater than 2 operands for split vectorize node.");
8239 if (any_of(Data.second,
8240 [](const auto &Op) { return !Op.second->UserTreeIndex; }))
8241 continue;
8242 // Update orders in user split vectorize nodes.
8243 assert(Data.first->CombinedEntriesWithIndices.size() == 2 &&
8244 "Expected exactly 2 entries.");
8245 for (const auto &P : Data.first->CombinedEntriesWithIndices) {
8246 TreeEntry &OpTE = *VectorizableTree[P.first];
8247 // The order of an operand that has both reordered and reused scalars
8248 // cannot be absorbed into the split node cleanly: clearing the
8249 // reorder indices while keeping the reuse mask (or vice versa)
8250 // desyncs the split node scalars from the operand effective order.
8251 // Skip reordering for such operands.
8252 if (OpTE.State != TreeEntry::SplitVectorize &&
8253 !OpTE.ReorderIndices.empty() && !OpTE.ReuseShuffleIndices.empty())
8254 continue;
8255 OrdersType Order = OpTE.ReorderIndices;
8256 if (Order.empty() || !OpTE.ReuseShuffleIndices.empty()) {
8257 if (!OpTE.isGather() && OpTE.ReuseShuffleIndices.empty())
8258 continue;
8259 const auto BestOrder =
8260 getReorderingData(OpTE, /*TopToBottom=*/false, IgnoreReorder);
8261 if (!BestOrder || BestOrder->empty() || isIdentityOrder(*BestOrder))
8262 continue;
8263 Order = *BestOrder;
8264 }
8265 fixupOrderingIndices(Order);
8266 SmallVector<int> Mask;
8267 inversePermutation(Order, Mask);
8268 const unsigned E = Order.size();
8269 SmallVector<int> MaskOrder(E, PoisonMaskElem);
8270 transform(Order, MaskOrder.begin(), [E](unsigned I) {
8271 return I < E ? static_cast<int>(I) : PoisonMaskElem;
8272 });
8273 Data.first->reorderSplitNode(P.second ? 1 : 0, Mask, MaskOrder);
8274 // Clear ordering of the operand.
8275 if (!OpTE.ReorderIndices.empty()) {
8276 OpTE.ReorderIndices.clear();
8277 } else if (!OpTE.ReuseShuffleIndices.empty()) {
8278 reorderReuses(OpTE.ReuseShuffleIndices, Mask);
8279 } else {
8280 assert(OpTE.isGather() && "Expected only gather/buildvector node.");
8281 reorderScalars(OpTE.Scalars, Mask);
8282 }
8283 }
8284 if (Data.first->ReuseShuffleIndices.empty() &&
8285 !Data.first->ReorderIndices.empty()) {
8286 // Insert user node to the list to try to sink reordering deeper in
8287 // the graph.
8288 Queue.push(Data.first);
8289 }
8290 continue;
8291 }
8292 // Do not move the operand order to the root PHI node when the root
8293 // order must be preserved: the root has no user to take over the order
8294 // and it cannot be dropped at the end of the reordering.
8295 if (!IgnoreReorder && Data.first == &getRootNode() &&
8296 !Data.first->UserTreeIndex &&
8297 Data.first->State == TreeEntry::Vectorize &&
8298 Data.first->getOpcode() == Instruction::PHI &&
8299 Data.first->ReuseShuffleIndices.empty())
8300 continue;
8301 // Check that operands are used only in the User node.
8302 SmallVector<TreeEntry *> GatherOps;
8303 buildReorderableOperands(Data.first, Data.second, NonVectorized,
8304 GatherOps);
8305 // All operands are reordered and used only in this node - propagate the
8306 // most used order to the user node.
8309 OrdersUses;
8310 // Do the analysis for each tree entry only once, otherwise the order of
8311 // the same node my be considered several times, though might be not
8312 // profitable.
8315 for (const auto &Op : Data.second) {
8316 TreeEntry *OpTE = Op.second;
8317 if (!VisitedOps.insert(OpTE).second)
8318 continue;
8319 if (!OpTE->ReuseShuffleIndices.empty() && !GathersToOrders.count(OpTE))
8320 continue;
8321 const auto Order = [&]() -> const OrdersType {
8322 if (OpTE->isGather() || !OpTE->ReuseShuffleIndices.empty())
8323 return getReorderingData(*OpTE, /*TopToBottom=*/false,
8324 IgnoreReorder)
8325 .value_or(OrdersType(1));
8326 return OpTE->ReorderIndices;
8327 }();
8328 // The order is partially ordered, skip it in favor of fully non-ordered
8329 // orders.
8330 if (Order.size() == 1)
8331 continue;
8332
8333 // Check that the reordering does not increase number of shuffles, i.e.
8334 // same-values-nodes has same parents or their parents has same parents.
8335 if (!Order.empty() && !isIdentityOrder(Order)) {
8336 Value *Root = OpTE->hasState()
8337 ? OpTE->getMainOp()
8338 : *find_if_not(OpTE->Scalars, isConstant);
8339 auto GetSameNodesUsers = [&](Value *Root) {
8341 for (const TreeEntry *TE : ValueToGatherNodes.lookup(Root)) {
8342 if (TE != OpTE && TE->UserTreeIndex &&
8343 TE->getVectorFactor() == OpTE->getVectorFactor() &&
8344 TE->Scalars.size() == OpTE->Scalars.size() &&
8345 ((TE->ReorderIndices.empty() && OpTE->isSame(TE->Scalars)) ||
8346 (OpTE->ReorderIndices.empty() && TE->isSame(OpTE->Scalars))))
8347 Res.insert(TE->UserTreeIndex.UserTE);
8348 }
8349 for (const TreeEntry *TE : getTreeEntries(Root)) {
8350 if (TE != OpTE && TE->UserTreeIndex &&
8351 TE->getVectorFactor() == OpTE->getVectorFactor() &&
8352 TE->Scalars.size() == OpTE->Scalars.size() &&
8353 ((TE->ReorderIndices.empty() && OpTE->isSame(TE->Scalars)) ||
8354 (OpTE->ReorderIndices.empty() && TE->isSame(OpTE->Scalars))))
8355 Res.insert(TE->UserTreeIndex.UserTE);
8356 }
8357 return Res.takeVector();
8358 };
8359 auto GetNumOperands = [](const TreeEntry *TE) {
8360 if (TE->State == TreeEntry::SplitVectorize)
8361 return TE->getNumOperands();
8362 if (auto *CI = dyn_cast<CallInst>(TE->getMainOp()); CI)
8363 return CI->arg_size();
8364 return TE->getNumOperands();
8365 };
8366 auto NodeShouldBeReorderedWithOperands = [&, TTI = TTI](
8367 const TreeEntry *TE) {
8369 if (auto *CI = dyn_cast<CallInst>(TE->getMainOp()); CI)
8370 ID = getVectorIntrinsicIDForCall(CI, TLI);
8371 for (unsigned Idx : seq<unsigned>(GetNumOperands(TE))) {
8372 if (ID != Intrinsic::not_intrinsic &&
8374 continue;
8375 const TreeEntry *Op = getOperandEntry(TE, Idx);
8376 if (Op->isGather() && Op->hasState()) {
8377 const TreeEntry *VecOp =
8378 getSameValuesTreeEntry(Op->getMainOp(), Op->Scalars);
8379 if (VecOp)
8380 Op = VecOp;
8381 }
8382 if (Op->ReorderIndices.empty() && Op->ReuseShuffleIndices.empty())
8383 return false;
8384 }
8385 return true;
8386 };
8387 SmallVector<TreeEntry *> Users = GetSameNodesUsers(Root);
8388 if (!Users.empty() && !all_of(Users, [&](TreeEntry *UTE) {
8389 if (!RevisitedOps.insert(UTE).second)
8390 return false;
8391 return UTE == Data.first || !UTE->ReorderIndices.empty() ||
8392 !UTE->ReuseShuffleIndices.empty() ||
8393 (UTE->UserTreeIndex &&
8394 UTE->UserTreeIndex.UserTE == Data.first) ||
8395 (Data.first->UserTreeIndex &&
8396 Data.first->UserTreeIndex.UserTE == UTE) ||
8397 (IgnoreReorder && UTE->UserTreeIndex &&
8398 UTE->UserTreeIndex.UserTE->Idx == 0) ||
8399 NodeShouldBeReorderedWithOperands(UTE);
8400 }))
8401 continue;
8402 for (TreeEntry *UTE : Users) {
8404 if (auto *CI = dyn_cast<CallInst>(UTE->getMainOp()); CI)
8405 ID = getVectorIntrinsicIDForCall(CI, TLI);
8406 for (unsigned Idx : seq<unsigned>(GetNumOperands(UTE))) {
8407 if (ID != Intrinsic::not_intrinsic &&
8409 continue;
8410 const TreeEntry *Op = getOperandEntry(UTE, Idx);
8411 Visited.erase(Op);
8412 Queue.push(const_cast<TreeEntry *>(Op));
8413 }
8414 }
8415 }
8416 unsigned NumOps = count_if(
8417 Data.second, [OpTE](const std::pair<unsigned, TreeEntry *> &P) {
8418 return P.second == OpTE;
8419 });
8420 // Stores actually store the mask, not the order, need to invert.
8421 if (OpTE->State == TreeEntry::Vectorize &&
8422 OpTE->getOpcode() == Instruction::Store && !Order.empty()) {
8423 assert(!OpTE->isAltShuffle() &&
8424 "Alternate instructions are only supported by BinaryOperator "
8425 "and CastInst.");
8426 SmallVector<int> Mask;
8427 inversePermutation(Order, Mask);
8428 unsigned E = Order.size();
8429 OrdersType CurrentOrder(E, E);
8430 transform(Mask, CurrentOrder.begin(), [E](int Idx) {
8431 return Idx == PoisonMaskElem ? E : static_cast<unsigned>(Idx);
8432 });
8433 fixupOrderingIndices(CurrentOrder);
8434 OrdersUses.try_emplace(CurrentOrder, 0).first->second += NumOps;
8435 } else {
8436 OrdersUses.try_emplace(Order, 0).first->second += NumOps;
8437 }
8438 auto Res = OrdersUses.try_emplace(OrdersType(), 0);
8439 const auto AllowsReordering = [&](const TreeEntry *TE) {
8440 if (!TE->ReorderIndices.empty() || !TE->ReuseShuffleIndices.empty() ||
8441 (TE->State == TreeEntry::Vectorize && TE->isAltShuffle()) ||
8442 (IgnoreReorder && TE->Idx == 0))
8443 return true;
8444 if (TE->isGather()) {
8445 if (GathersToOrders.contains(TE))
8446 return !getReorderingData(*TE, /*TopToBottom=*/false,
8447 IgnoreReorder)
8448 .value_or(OrdersType(1))
8449 .empty();
8450 return true;
8451 }
8452 return false;
8453 };
8454 if (OpTE->UserTreeIndex) {
8455 TreeEntry *UserTE = OpTE->UserTreeIndex.UserTE;
8456 if (!VisitedUsers.insert(UserTE).second)
8457 continue;
8458 // May reorder user node if it requires reordering, has reused
8459 // scalars, is an alternate op vectorize node or its op nodes require
8460 // reordering.
8461 if (AllowsReordering(UserTE))
8462 continue;
8463 // Check if users allow reordering.
8464 // Currently look up just 1 level of operands to avoid increase of
8465 // the compile time.
8466 // Profitable to reorder if definitely more operands allow
8467 // reordering rather than those with natural order.
8469 if (static_cast<unsigned>(count_if(
8470 Ops, [UserTE, &AllowsReordering](
8471 const std::pair<unsigned, TreeEntry *> &Op) {
8472 return AllowsReordering(Op.second) &&
8473 Op.second->UserTreeIndex.UserTE == UserTE;
8474 })) <= Ops.size() / 2)
8475 ++Res.first->second;
8476 }
8477 }
8478 if (OrdersUses.empty()) {
8479 Visited.insert_range(llvm::make_second_range(Data.second));
8480 continue;
8481 }
8482 // Choose the most used order.
8483 unsigned IdentityCnt = 0;
8484 unsigned VF = Data.second.front().second->getVectorFactor();
8485 OrdersType IdentityOrder(VF, VF);
8486 for (auto &Pair : OrdersUses) {
8487 if (Pair.first.empty() || isIdentityOrder(Pair.first)) {
8488 IdentityCnt += Pair.second;
8489 combineOrders(IdentityOrder, Pair.first);
8490 }
8491 }
8492 MutableArrayRef<unsigned> BestOrder = IdentityOrder;
8493 unsigned Cnt = IdentityCnt;
8494 for (auto &Pair : OrdersUses) {
8495 // Prefer identity order. But, if filled identity found (non-empty
8496 // order) with same number of uses, as the new candidate order, we can
8497 // choose this candidate order.
8498 if (Cnt < Pair.second) {
8499 combineOrders(Pair.first, BestOrder);
8500 BestOrder = Pair.first;
8501 Cnt = Pair.second;
8502 } else {
8503 combineOrders(BestOrder, Pair.first);
8504 }
8505 }
8506 // Set order of the user node.
8507 if (isIdentityOrder(BestOrder)) {
8508 Visited.insert_range(llvm::make_second_range(Data.second));
8509 continue;
8510 }
8511 fixupOrderingIndices(BestOrder);
8512 // Erase operands from OrderedEntries list and adjust their orders.
8513 VisitedOps.clear();
8514 SmallVector<int> Mask;
8515 inversePermutation(BestOrder, Mask);
8516 SmallVector<int> MaskOrder(BestOrder.size(), PoisonMaskElem);
8517 unsigned E = BestOrder.size();
8518 transform(BestOrder, MaskOrder.begin(), [E](unsigned I) {
8519 return I < E ? static_cast<int>(I) : PoisonMaskElem;
8520 });
8521 for (const std::pair<unsigned, TreeEntry *> &Op : Data.second) {
8522 TreeEntry *TE = Op.second;
8523 if (!VisitedOps.insert(TE).second)
8524 continue;
8525 // TODO: Reordering of struct types is not supported.
8526 if (TE->State == TreeEntry::Vectorize &&
8527 isa<StructType>(getValueType(TE->Scalars.front(), SLPReVec)))
8528 continue;
8529 if (TE->ReuseShuffleIndices.size() == BestOrder.size()) {
8530 reorderNodeWithReuses(*TE, Mask);
8531 continue;
8532 }
8533 // Gathers are processed separately.
8534 if (TE->State != TreeEntry::Vectorize &&
8535 TE->State != TreeEntry::StridedVectorize &&
8536 TE->State != TreeEntry::ExpandVectorize &&
8537 TE->State != TreeEntry::CompressVectorize &&
8538 TE->State != TreeEntry::BlendedLoadVectorize &&
8539 TE->State != TreeEntry::SplitVectorize &&
8540 (TE->State != TreeEntry::ScatterVectorize ||
8541 TE->ReorderIndices.empty()))
8542 continue;
8543 assert((BestOrder.size() == TE->ReorderIndices.size() ||
8544 TE->ReorderIndices.empty()) &&
8545 "Non-matching sizes of user/operand entries.");
8546 reorderOrder(TE->ReorderIndices, Mask);
8547 if (IgnoreReorder && TE == &getRootNode())
8548 IgnoreReorder = false;
8549 }
8550 // For gathers just need to reorder its scalars.
8551 for (TreeEntry *Gather : GatherOps) {
8552 assert(Gather->ReorderIndices.empty() &&
8553 "Unexpected reordering of gathers.");
8554 if (!Gather->ReuseShuffleIndices.empty()) {
8555 // Just reorder reuses indices.
8556 reorderReuses(Gather->ReuseShuffleIndices, Mask);
8557 continue;
8558 }
8559 // A ScatterVectorize (masked gather) node is scheduled, and the
8560 // scheduler reads its operand list at the same lane where the scalar
8561 // load sits, so Scalars and the operand list must stay aligned.
8562 // Record the reorder in ReorderIndices (applied by the final shuffle)
8563 // instead of physically permuting the scalars, matching how a scatter
8564 // node with a non-empty order is reordered above.
8565 if (Gather->State == TreeEntry::ScatterVectorize) {
8566 reorderOrder(Gather->ReorderIndices, Mask);
8567 Visited.insert(Gather);
8568 continue;
8569 }
8570 reorderScalars(Gather->Scalars, Mask);
8571 Visited.insert(Gather);
8572 }
8573 // Reorder operands of the user node and set the ordering for the user
8574 // node itself.
8575 auto IsNotProfitableAltCodeNode = [](const TreeEntry &TE) {
8576 return TE.isAltShuffle() &&
8577 (!TE.ReuseShuffleIndices.empty() || TE.getVectorFactor() == 2 ||
8578 TE.ReorderIndices.empty());
8579 };
8580 if (Data.first->State != TreeEntry::Vectorize ||
8582 Data.first->getMainOp()) ||
8583 IsNotProfitableAltCodeNode(*Data.first)) {
8584 Data.first->reorderOperands(Mask);
8586 }
8588 Data.first->getMainOp()) ||
8589 IsNotProfitableAltCodeNode(*Data.first) ||
8590 Data.first->State == TreeEntry::CompressVectorize) {
8591 reorderScalars(Data.first->Scalars, Mask);
8592 reorderOrder(Data.first->ReorderIndices, MaskOrder,
8593 /*BottomOrder=*/true);
8594 if (Data.first->ReuseShuffleIndices.empty() &&
8595 !Data.first->ReorderIndices.empty() &&
8596 !IsNotProfitableAltCodeNode(*Data.first)) {
8597 // Insert user node to the list to try to sink reordering deeper in
8598 // the graph.
8599 Queue.push(Data.first);
8600 }
8601 } else {
8602 reorderOrder(Data.first->ReorderIndices, Mask);
8603 }
8604 }
8605 }
8606 // If the reordering is unnecessary, just remove the reorder.
8607 if (IgnoreReorder && !getRootNode().ReorderIndices.empty() &&
8608 getRootNode().ReuseShuffleIndices.empty())
8609 getRootNode().ReorderIndices.clear();
8610}
8611
8612Instruction *BoUpSLP::getRootEntryInstruction(const TreeEntry &Entry) const {
8613 if (Entry.hasState() &&
8614 (Entry.getOpcode() == Instruction::Store ||
8615 Entry.getOpcode() == Instruction::Load) &&
8616 Entry.State == TreeEntry::StridedVectorize &&
8617 !Entry.ReorderIndices.empty() && isReverseOrder(Entry.ReorderIndices))
8618 return dyn_cast<Instruction>(Entry.Scalars[Entry.ReorderIndices.front()]);
8619 return dyn_cast<Instruction>(Entry.Scalars.front());
8620}
8621
8623 const ExtraValueToDebugLocsMap &ExternallyUsedValues) {
8624 const size_t NumVectScalars = ScalarToTreeEntries.size() + 1;
8625 DenseMap<Value *, unsigned> ScalarToExtUses;
8626 // Peeled scalars still claimed by the tree (gathered, listed in some
8627 // entry's scalars, or modeled as a copyable element, which is emitted as
8628 // a scalar) survive as plain code, along with the peeled scalars
8629 // in their operand chains, which no vector node can rematerialize.
8630 KeptReassocScalars.clear();
8631 SmallVector<const Value *, 8> KeptWorklist;
8632 for (const auto &[V, Owners] : ReassocScalarToTreeEntries)
8633 if ((isGathered(V) || !getTreeEntries(V).empty() ||
8634 any_of(Owners,
8635 [V = V](const TreeEntry *TE) {
8636 return TE->isCopyableElement(const_cast<Value *>(V));
8637 })) &&
8638 KeptReassocScalars.insert(V).second)
8639 KeptWorklist.push_back(V);
8640 while (!KeptWorklist.empty()) {
8641 const Value *V = KeptWorklist.pop_back_val();
8642 for (const Value *Op : cast<Instruction>(V)->operand_values())
8643 if (ReassocScalarToTreeEntries.contains(Op) &&
8644 KeptReassocScalars.insert(Op).second)
8645 KeptWorklist.push_back(Op);
8646 }
8647 // Collect the values that we need to extract from the tree.
8648 for (auto &TEPtr : VectorizableTree) {
8649 TreeEntry *Entry = TEPtr.get();
8650
8651 // No need to handle users of gathered values.
8652 if (Entry->isGather() || Entry->State == TreeEntry::SplitVectorize ||
8653 DeletedNodes.contains(Entry) ||
8654 TransformedToGatherNodes.contains(Entry))
8655 continue;
8656
8657 // For each lane:
8658 for (int Lane = 0, LE = Entry->Scalars.size(); Lane != LE; ++Lane) {
8659 Value *Scalar = Entry->Scalars[Lane];
8660 if (!isa<Instruction>(Scalar) || Entry->isCopyableElement(Scalar))
8661 continue;
8662 bool IsStructScalar = isa<StructType>(Scalar->getType());
8663
8664 // All uses must be replaced already? No need to do it again.
8665 auto It = ScalarToExtUses.find(Scalar);
8666 if (It != ScalarToExtUses.end() && !ExternalUses[It->second].User)
8667 continue;
8668
8669 if (!IsStructScalar && Scalar->hasNUsesOrMore(NumVectScalars)) {
8670 unsigned FoundLane = Entry->findLaneForValue(Scalar);
8671 LLVM_DEBUG(dbgs() << "SLP: Need to extract from lane " << FoundLane
8672 << " from " << *Scalar << "for many users.\n");
8673 It = ScalarToExtUses.try_emplace(Scalar, ExternalUses.size()).first;
8674 ExternalUses.emplace_back(Scalar, nullptr, *Entry, FoundLane);
8675 ExternalUsesWithNonUsers.insert(Scalar);
8676 continue;
8677 }
8678
8679 // Check if the scalar is externally used as an extra arg.
8680 const auto ExtI = ExternallyUsedValues.find(Scalar);
8681 if (ExtI != ExternallyUsedValues.end()) {
8682 unsigned FoundLane = Entry->findLaneForValue(Scalar);
8683 LLVM_DEBUG(dbgs() << "SLP: Need to extract: Extra arg from lane "
8684 << FoundLane << " from " << *Scalar << ".\n");
8685 ScalarToExtUses.try_emplace(Scalar, ExternalUses.size());
8686 ExternalUses.emplace_back(Scalar, nullptr, *Entry, FoundLane);
8687 continue;
8688 }
8689 for (User *U : Scalar->users()) {
8690 LLVM_DEBUG(dbgs() << "SLP: Checking user:" << *U << ".\n");
8691
8692 Instruction *UserInst = dyn_cast<Instruction>(U);
8693 if (!UserInst || isDeleted(UserInst))
8694 continue;
8695
8696 // Ignore users in the user ignore list.
8697 if (UserIgnoreList && UserIgnoreList->contains(UserInst))
8698 continue;
8699
8700 // Peeled reassociated scalars are subsumed by the flattened node and
8701 // erased during vectorization, not external users. Kept ones survive
8702 // and their uses of erased scalars become extracts like any other.
8703 if (isReassocScalarVectorized(UserInst) &&
8704 !KeptReassocScalars.contains(UserInst)) {
8705 LLVM_DEBUG(dbgs() << "SLP: \tInternal (reassociated) user will be "
8706 "removed:"
8707 << *U << ".\n");
8708 continue;
8709 }
8710
8711 // Skip in-tree scalars that become vectors
8712 if (ArrayRef<TreeEntry *> UseEntries = getTreeEntries(U);
8713 any_of(UseEntries, [this](const TreeEntry *UseEntry) {
8714 return !DeletedNodes.contains(UseEntry) &&
8715 !TransformedToGatherNodes.contains(UseEntry);
8716 })) {
8717 // Some in-tree scalars will remain as scalar in vectorized
8718 // instructions. If that is the case, the one in FoundLane will
8719 // be used.
8720 if (!((Scalar->getType()->getScalarType()->isPointerTy() &&
8721 isa<LoadInst, StoreInst>(UserInst)) ||
8722 isa<CallInst>(UserInst)) ||
8723 all_of(UseEntries, [&](TreeEntry *UseEntry) {
8724 if (DeletedNodes.contains(UseEntry) ||
8725 TransformedToGatherNodes.contains(UseEntry))
8726 return true;
8727 return UseEntry->State == TreeEntry::ScatterVectorize ||
8729 Scalar, getRootEntryInstruction(*UseEntry), TLI,
8730 TTI);
8731 })) {
8732 LLVM_DEBUG(dbgs() << "SLP: \tInternal user will be removed:" << *U
8733 << ".\n");
8734 assert(none_of(UseEntries,
8735 [](TreeEntry *UseEntry) {
8736 return UseEntry->isGather();
8737 }) &&
8738 "Bad state");
8739 continue;
8740 }
8741 if (!IsStructScalar) {
8742 U = nullptr;
8743 if (It != ScalarToExtUses.end()) {
8744 ExternalUses[It->second].User = nullptr;
8745 break;
8746 }
8747 }
8748 }
8749
8750 if (U && !IsStructScalar && Scalar->hasNUsesOrMore(UsesLimit))
8751 U = nullptr;
8752 unsigned FoundLane = Entry->findLaneForValue(Scalar);
8753 LLVM_DEBUG(dbgs() << "SLP: Need to extract:" << *UserInst
8754 << " from lane " << FoundLane << " from " << *Scalar
8755 << ".\n");
8756 It = ScalarToExtUses.try_emplace(Scalar, ExternalUses.size()).first;
8757 ExternalUses.emplace_back(Scalar, U, *Entry, FoundLane);
8758 ExternalUsesWithNonUsers.insert(Scalar);
8759 if (!U)
8760 break;
8761 }
8762 }
8763 }
8764
8765 // The expansion of the runtime stride may reuse an in-tree instruction with
8766 // the matching SCEV, which gets erased upon vectorization. Register an
8767 // external use for it to replace the stride operand with the extract.
8769 for (const auto &[StridedTE, SPtrInfo] : TreeEntryToStridedPtrInfoMap)
8770 if (SPtrInfo.StrideSCEV && !SPtrInfo.StrideVal &&
8771 !DeletedNodes.contains(StridedTE) &&
8772 !TransformedToGatherNodes.contains(StridedTE))
8773 Strides.emplace_back(SPtrInfo.StrideSCEV,
8774 StridedTE->getMainOp()->getParent());
8775 if (Strides.empty())
8776 return;
8777 for (const std::unique_ptr<TreeEntry> &TEPtr : VectorizableTree) {
8778 TreeEntry *Entry = TEPtr.get();
8779 if (Entry->isGather() || Entry->State == TreeEntry::SplitVectorize ||
8780 DeletedNodes.contains(Entry) ||
8781 TransformedToGatherNodes.contains(Entry))
8782 continue;
8783 for (Value *Scalar : Entry->Scalars) {
8784 auto *I = dyn_cast<Instruction>(Scalar);
8785 if (!I || Entry->isCopyableElement(I) || !SE->isSCEVable(I->getType()))
8786 continue;
8787 const SCEV *ScalarSCEV = SE->getSCEV(I);
8788 if (isa<SCEVConstant>(ScalarSCEV) ||
8789 none_of(Strides, [&](const auto &Stride) {
8790 return DT->dominates(I, Stride.second->getTerminator()) &&
8791 SCEVExprContains(Stride.first, [ScalarSCEV](const SCEV *S) {
8792 return S == ScalarSCEV;
8793 });
8794 }))
8795 continue;
8796 auto It = ScalarToExtUses.find(Scalar);
8797 if (It != ScalarToExtUses.end()) {
8798 // Replace all uses: the stride operand is emitted later, during the
8799 // codegen.
8800 ExternalUses[It->second].User = nullptr;
8801 continue;
8802 }
8803 unsigned FoundLane = Entry->findLaneForValue(Scalar);
8804 LLVM_DEBUG(dbgs() << "SLP: Need to extract: strided load stride from "
8805 "lane "
8806 << FoundLane << " from " << *Scalar << ".\n");
8807 ScalarToExtUses.try_emplace(Scalar, ExternalUses.size());
8808 ExternalUses.emplace_back(Scalar, nullptr, *Entry, FoundLane);
8809 ExternalUsesWithNonUsers.insert(Scalar);
8810 }
8811 }
8812}
8813
8815BoUpSLP::collectUserStores(const BoUpSLP::TreeEntry *TE) const {
8818 PtrToStoresMap;
8819 for (unsigned Lane : seq<unsigned>(0, TE->Scalars.size())) {
8820 Value *V = TE->Scalars[Lane];
8821 // Don't iterate over the users of constant data.
8822 if (!isa<Instruction>(V))
8823 continue;
8824 // To save compilation time we don't visit if we have too many users.
8825 if (V->hasNUsesOrMore(UsesLimit))
8826 break;
8827
8828 // Collect stores per pointer object.
8829 for (User *U : V->users()) {
8830 auto *SI = dyn_cast<StoreInst>(U);
8831 // Test whether we can handle the store. V might be a global, which could
8832 // be used in a different function.
8833 if (SI == nullptr || !SI->isSimple() || SI->getFunction() != F ||
8834 !isValidElementType(SI->getValueOperand()->getType(), SLPReVec))
8835 continue;
8836 // Skip entry if already
8837 if (isVectorized(U))
8838 continue;
8839
8840 Value *Ptr =
8841 getUnderlyingObject(SI->getPointerOperand(), RecursionMaxDepth);
8842 auto &StoresVec = PtrToStoresMap[{SI->getParent(),
8843 SI->getValueOperand()->getType(), Ptr}];
8844 // For now just keep one store per pointer object per lane.
8845 // TODO: Extend this to support multiple stores per pointer per lane
8846 if (StoresVec.size() > Lane)
8847 continue;
8848 if (!StoresVec.empty()) {
8849 std::optional<int64_t> Diff = getPointersDiff(
8850 SI->getValueOperand()->getType(), SI->getPointerOperand(),
8851 SI->getValueOperand()->getType(),
8852 StoresVec.front()->getPointerOperand(), *DL, *SE,
8853 /*StrictCheck=*/true);
8854 // We failed to compare the pointers so just abandon this store.
8855 if (!Diff)
8856 continue;
8857 }
8858 StoresVec.push_back(SI);
8859 }
8860 }
8861 SmallVector<SmallVector<StoreInst *>> Res(PtrToStoresMap.size());
8862 unsigned I = 0;
8863 for (auto &P : PtrToStoresMap) {
8864 Res[I].swap(P.second);
8865 ++I;
8866 }
8867 return Res;
8868}
8869
8870bool BoUpSLP::canFormVector(ArrayRef<StoreInst *> StoresVec,
8871 OrdersType &ReorderIndices) const {
8872 // We check whether the stores in StoreVec can form a vector by sorting them
8873 // and checking whether they are consecutive.
8874
8875 // To avoid calling getPointersDiff() while sorting we create a vector of
8876 // pairs {store, offset from first} and sort this instead.
8878 StoreInst *S0 = StoresVec[0];
8879 StoreOffsetVec.emplace_back(0, 0);
8880 Type *S0Ty = S0->getValueOperand()->getType();
8881 Value *S0Ptr = S0->getPointerOperand();
8882 for (unsigned Idx : seq<unsigned>(1, StoresVec.size())) {
8883 StoreInst *SI = StoresVec[Idx];
8884 std::optional<int64_t> Diff =
8885 getPointersDiff(S0Ty, S0Ptr, SI->getValueOperand()->getType(),
8886 SI->getPointerOperand(), *DL, *SE,
8887 /*StrictCheck=*/true);
8888 StoreOffsetVec.emplace_back(*Diff, Idx);
8889 }
8890
8891 // Check if the stores are consecutive by checking if their difference is 1.
8892 if (StoreOffsetVec.size() != StoresVec.size())
8893 return false;
8894 sort(StoreOffsetVec, llvm::less_first());
8895 unsigned Idx = 0;
8896 int64_t PrevDist = 0;
8897 for (const auto &P : StoreOffsetVec) {
8898 if (Idx > 0 && P.first != PrevDist + 1)
8899 return false;
8900 PrevDist = P.first;
8901 ++Idx;
8902 }
8903
8904 // Calculate the shuffle indices according to their offset against the sorted
8905 // StoreOffsetVec.
8906 ReorderIndices.assign(StoresVec.size(), 0);
8907 bool IsIdentity = true;
8908 for (auto [I, P] : enumerate(StoreOffsetVec)) {
8909 ReorderIndices[P.second] = I;
8910 IsIdentity &= P.second == I;
8911 }
8912 // Identity order (e.g., {0,1,2,3}) is modeled as an empty OrdersType in
8913 // reorderTopToBottom() and reorderBottomToTop(), so we are following the
8914 // same convention here.
8915 if (IsIdentity)
8916 ReorderIndices.clear();
8917
8918 return true;
8919}
8920
8921#ifndef NDEBUG
8923 for (unsigned Idx : Order)
8924 dbgs() << Idx << ", ";
8925 dbgs() << "\n";
8926}
8927#endif
8928
8930BoUpSLP::findExternalStoreUsersReorderIndices(TreeEntry *TE) const {
8931 unsigned NumLanes = TE->Scalars.size();
8932
8933 SmallVector<SmallVector<StoreInst *>> Stores = collectUserStores(TE);
8934
8935 // Holds the reorder indices for each candidate store vector that is a user of
8936 // the current TreeEntry.
8937 SmallVector<OrdersType, 1> ExternalReorderIndices;
8938
8939 // Now inspect the stores collected per pointer and look for vectorization
8940 // candidates. For each candidate calculate the reorder index vector and push
8941 // it into `ExternalReorderIndices`
8942 for (ArrayRef<StoreInst *> StoresVec : Stores) {
8943 // If we have fewer than NumLanes stores, then we can't form a vector.
8944 if (StoresVec.size() != NumLanes)
8945 continue;
8946
8947 // If the stores are not consecutive then abandon this StoresVec.
8948 OrdersType ReorderIndices;
8949 if (!canFormVector(StoresVec, ReorderIndices))
8950 continue;
8951
8952 // We now know that the scalars in StoresVec can form a vector instruction,
8953 // so set the reorder indices.
8954 ExternalReorderIndices.push_back(ReorderIndices);
8955 }
8956 return ExternalReorderIndices;
8957}
8958
8960 const SmallDenseSet<Value *> &UserIgnoreLst) {
8961 deleteTree();
8962 assert(TreeEntryToStridedPtrInfoMap.empty() &&
8963 "TreeEntryToStridedPtrInfoMap is not cleared");
8964 UserIgnoreList = &UserIgnoreLst;
8965 if (!allSameType(Roots))
8966 return;
8967 buildTreeRec(Roots, 0, EdgeInfo());
8968 // Build splat-gather subtrees here so the reordering passes cover them too.
8969 tryToVectorizeSplatGatheredScalars();
8970}
8971
8973 deleteTree();
8974 assert(TreeEntryToStridedPtrInfoMap.empty() &&
8975 "TreeEntryToStridedPtrInfoMap is not cleared");
8976 if (!allSameType(Roots))
8977 return;
8978 buildTreeRec(Roots, 0, EdgeInfo());
8979 // Build splat-gather subtrees here so the reordering passes cover them too.
8980 tryToVectorizeSplatGatheredScalars();
8981}
8982
8983/// Tries to find subvector of loads and builds new vector of only loads if can
8984/// be profitable.
8986 const BoUpSLP &R, ArrayRef<Value *> VL, const DataLayout &DL,
8988 SmallVectorImpl<SmallVector<std::pair<LoadInst *, int64_t>>> &GatheredLoads,
8989 bool AddNew = true) {
8990 if (VL.empty())
8991 return;
8992 Type *ScalarTy = getValueType(VL.front(), SLPReVec);
8993 if (!isValidElementType(ScalarTy, SLPReVec))
8994 return;
8996 SmallVector<DenseMap<int64_t, LoadInst *>> ClusteredDistToLoad;
8997 for (Value *V : VL) {
8998 auto *LI = dyn_cast<LoadInst>(V);
8999 if (!LI)
9000 continue;
9001 if (R.isDeleted(LI) || R.isVectorized(LI) || !LI->isSimple())
9002 continue;
9003 bool IsFound = false;
9004 for (auto [Map, Data] : zip(ClusteredDistToLoad, ClusteredLoads)) {
9005 assert(LI->getParent() == Data.front().first->getParent() &&
9006 LI->getType() == Data.front().first->getType() &&
9007 getUnderlyingObject(LI->getPointerOperand(), RecursionMaxDepth) ==
9008 getUnderlyingObject(Data.front().first->getPointerOperand(),
9010 "Expected loads with the same type, same parent and same "
9011 "underlying pointer.");
9012 std::optional<int64_t> Dist = getPointersDiff(
9013 LI->getType(), LI->getPointerOperand(), Data.front().first->getType(),
9014 Data.front().first->getPointerOperand(), DL, SE,
9015 /*StrictCheck=*/true);
9016 if (!Dist)
9017 continue;
9018 auto It = Map.find(*Dist);
9019 if (It != Map.end() && It->second != LI)
9020 continue;
9021 if (It == Map.end()) {
9022 Data.emplace_back(LI, *Dist);
9023 Map.try_emplace(*Dist, LI);
9024 }
9025 IsFound = true;
9026 break;
9027 }
9028 if (!IsFound) {
9029 ClusteredLoads.emplace_back().emplace_back(LI, 0);
9030 ClusteredDistToLoad.emplace_back().try_emplace(0, LI);
9031 }
9032 }
9033 auto FindMatchingLoads =
9036 &GatheredLoads,
9038 int64_t &Offset, unsigned &Start) {
9039 if (Loads.empty())
9040 return GatheredLoads.end();
9041 LoadInst *LI = Loads.front().first;
9042 for (auto [Idx, Data] : enumerate(GatheredLoads)) {
9043 if (Idx < Start)
9044 continue;
9045 ToAdd.clear();
9046 if (LI->getParent() != Data.front().first->getParent() ||
9047 LI->getType() != Data.front().first->getType())
9048 continue;
9049 std::optional<int64_t> Dist =
9051 Data.front().first->getType(),
9052 Data.front().first->getPointerOperand(), DL, SE,
9053 /*StrictCheck=*/true);
9054 if (!Dist)
9055 continue;
9056 SmallSet<int64_t, 4> DataDists;
9058 for (std::pair<LoadInst *, int64_t> P : Data) {
9059 DataDists.insert(P.second);
9060 DataLoads.insert(P.first);
9061 }
9062 // Found matching gathered loads - check if all loads are unique or
9063 // can be effectively vectorized.
9064 unsigned NumUniques = 0;
9065 for (auto [Cnt, Pair] : enumerate(Loads)) {
9066 bool Used = DataLoads.contains(Pair.first);
9067 if (!Used && !DataDists.contains(*Dist + Pair.second)) {
9068 ++NumUniques;
9069 ToAdd.insert(Cnt);
9070 } else if (Used) {
9071 Repeated.insert(Cnt);
9072 }
9073 }
9074 if (NumUniques > 0 &&
9075 (Loads.size() == NumUniques ||
9076 (Loads.size() - NumUniques >= 2 &&
9077 Loads.size() - NumUniques >= Loads.size() / 2 &&
9078 (has_single_bit(Data.size() + NumUniques) ||
9079 bit_ceil(Data.size()) <
9080 bit_ceil(Data.size() + NumUniques))))) {
9081 Offset = *Dist;
9082 Start = Idx + 1;
9083 return std::next(GatheredLoads.begin(), Idx);
9084 }
9085 }
9086 ToAdd.clear();
9087 return GatheredLoads.end();
9088 };
9089 for (ArrayRef<std::pair<LoadInst *, int64_t>> Data : ClusteredLoads) {
9090 unsigned Start = 0;
9091 SetVector<unsigned> ToAdd, LocalToAdd, Repeated;
9092 int64_t Offset = 0;
9093 auto *It = FindMatchingLoads(Data, GatheredLoads, LocalToAdd, Repeated,
9094 Offset, Start);
9095 while (It != GatheredLoads.end()) {
9096 assert(!LocalToAdd.empty() && "Expected some elements to add.");
9097 for (unsigned Idx : LocalToAdd)
9098 It->emplace_back(Data[Idx].first, Data[Idx].second + Offset);
9099 ToAdd.insert_range(LocalToAdd);
9100 It = FindMatchingLoads(Data, GatheredLoads, LocalToAdd, Repeated, Offset,
9101 Start);
9102 }
9103 if (any_of(seq<unsigned>(Data.size()), [&](unsigned Idx) {
9104 return !ToAdd.contains(Idx) && !Repeated.contains(Idx);
9105 })) {
9106 auto AddNewLoads =
9108 for (unsigned Idx : seq<unsigned>(Data.size())) {
9109 if (ToAdd.contains(Idx) || Repeated.contains(Idx))
9110 continue;
9111 Loads.push_back(Data[Idx]);
9112 }
9113 };
9114 if (!AddNew) {
9115 LoadInst *LI = Data.front().first;
9116 It = find_if(
9117 GatheredLoads, [&](ArrayRef<std::pair<LoadInst *, int64_t>> PD) {
9118 return PD.front().first->getParent() == LI->getParent() &&
9119 PD.front().first->getType() == LI->getType();
9120 });
9121 while (It != GatheredLoads.end()) {
9122 AddNewLoads(*It);
9123 It = std::find_if(
9124 std::next(It), GatheredLoads.end(),
9125 [&](ArrayRef<std::pair<LoadInst *, int64_t>> PD) {
9126 return PD.front().first->getParent() == LI->getParent() &&
9127 PD.front().first->getType() == LI->getType();
9128 });
9129 }
9130 }
9131 GatheredLoads.emplace_back().append(Data.begin(), Data.end());
9132 AddNewLoads(GatheredLoads.emplace_back());
9133 }
9134 }
9135}
9136
9137void BoUpSLP::tryToVectorizeGatheredLoads(
9138 const SmallMapVector<
9139 std::tuple<BasicBlock *, Value *, Type *>,
9140 SmallVector<SmallVector<std::pair<LoadInst *, int64_t>>>, 8>
9141 &GatheredLoads) {
9142 GatheredLoadsEntriesFirst = VectorizableTree.size();
9143
9144 SmallVector<SmallPtrSet<const Value *, 4>> LoadSetsToVectorize(
9145 LoadEntriesToVectorize.size());
9146 for (auto [Idx, Set] : zip(LoadEntriesToVectorize, LoadSetsToVectorize))
9147 Set.insert_range(VectorizableTree[Idx]->Scalars);
9148
9149 // Sort loads by distance.
9150 auto LoadSorter = [](const std::pair<LoadInst *, int64_t> &L1,
9151 const std::pair<LoadInst *, int64_t> &L2) {
9152 return L1.second > L2.second;
9153 };
9154
9155 auto IsMaskedGatherSupported = [&, TTI = TTI](ArrayRef<LoadInst *> Loads) {
9156 ArrayRef<Value *> Values(reinterpret_cast<Value *const *>(Loads.begin()),
9157 Loads.size());
9159 auto *Ty = cast<VectorType>(
9160 getWidenedType(Loads.front()->getType(), Loads.size()));
9161 return TTI->isLegalMaskedGather(Ty, Alignment) &&
9162 !TTI->forceScalarizeMaskedGather(Ty, Alignment);
9163 };
9164
9165 auto GetVectorizedRanges = [this](ArrayRef<LoadInst *> Loads,
9166 BoUpSLP::ValueSet &VectorizedLoads,
9167 SmallVectorImpl<LoadInst *> &NonVectorized,
9168 bool Final, unsigned MaxVF) {
9170 unsigned StartIdx = 0;
9171 SmallVector<int> CandidateVFs;
9172 if (isAllowedNonPowerOf2VF(MaxVF))
9173 CandidateVFs.push_back(MaxVF);
9174 for (int NumElts = getFloorFullVectorNumberOfElements(
9175 *TTI, Loads.front()->getType(), MaxVF, SLPReVec);
9176 NumElts > 1;
9178 *TTI, Loads.front()->getType(), NumElts - 1, SLPReVec)) {
9179 CandidateVFs.push_back(NumElts);
9180 if (VectorizeNonPowerOf2 && NumElts > 2)
9181 CandidateVFs.push_back(NumElts - 1);
9182 }
9183
9184 if (Final && CandidateVFs.empty())
9185 return Results;
9186
9187 unsigned BestVF = Final ? CandidateVFs.back() : 0;
9188 for (unsigned NumElts : CandidateVFs) {
9189 if (Final && NumElts > BestVF)
9190 continue;
9191 SmallVector<unsigned> MaskedGatherVectorized;
9192 for (unsigned Cnt = StartIdx, E = Loads.size(); Cnt < E;
9193 ++Cnt) {
9194 ArrayRef<LoadInst *> Slice =
9195 ArrayRef(Loads).slice(Cnt, std::min(NumElts, E - Cnt));
9196 if (VectorizedLoads.count(Slice.front()) ||
9197 VectorizedLoads.count(Slice.back()) ||
9199 continue;
9200 // Check if it is profitable to try vectorizing gathered loads. It is
9201 // profitable if we have more than 3 consecutive loads or if we have
9202 // less but all users are vectorized or deleted.
9203 bool AllowToVectorize = false;
9204 // Check if it is profitable to vectorize 2-elements loads.
9205 if (NumElts == 2) {
9206 bool IsLegalBroadcastLoad = TTI->isLegalBroadcastLoad(
9207 Slice.front()->getType(), ElementCount::getFixed(NumElts));
9208 auto CheckIfAllowed = [=](ArrayRef<LoadInst *> Slice) {
9209 for (LoadInst *LI : Slice) {
9210 // If single use/user - allow to vectorize.
9211 if (LI->hasOneUse())
9212 continue;
9213 // 1. Check if number of uses equals number of users.
9214 // 2. All users are deleted.
9215 // 3. The load broadcasts are not allowed or the load is not
9216 // broadcasted.
9217 if (static_cast<unsigned int>(std::distance(
9218 LI->user_begin(), LI->user_end())) != LI->getNumUses())
9219 return false;
9220 if (!IsLegalBroadcastLoad)
9221 continue;
9222 if (LI->hasNUsesOrMore(UsesLimit))
9223 return false;
9224 for (User *U : LI->users()) {
9225 if (auto *UI = dyn_cast<Instruction>(U); UI && isDeleted(UI))
9226 continue;
9227 for (const TreeEntry *UTE : getTreeEntries(U)) {
9228 for (int I : seq<int>(UTE->getNumOperands())) {
9229 if (all_of(UTE->getOperand(I), [LI](Value *V) {
9230 return V == LI || isa<PoisonValue>(V);
9231 }))
9232 // Found legal broadcast - do not vectorize.
9233 return false;
9234 }
9235 }
9236 }
9237 }
9238 return true;
9239 };
9240 AllowToVectorize = CheckIfAllowed(Slice);
9241 } else {
9242 AllowToVectorize =
9243 NumElts >= 3 ||
9244 any_of(ValueToGatherNodes.at(Slice.front()),
9245 [=](const TreeEntry *TE) {
9246 return TE->Scalars.size() == 2 &&
9247 ((TE->Scalars.front() == Slice.front() &&
9248 TE->Scalars.back() == Slice.back()) ||
9249 (TE->Scalars.front() == Slice.back() &&
9250 TE->Scalars.back() == Slice.front()));
9251 });
9252 }
9253 if (AllowToVectorize) {
9254 SmallVector<Value *> PointerOps;
9255 OrdersType CurrentOrder;
9256 // Try to build vector load.
9258 reinterpret_cast<Value *const *>(Slice.begin()), Slice.size());
9259 StridedPtrInfo SPtrInfo;
9260 LoadsState LS = canVectorizeLoads(Values, Slice.front(), CurrentOrder,
9261 PointerOps, SPtrInfo, &BestVF);
9262 if (LS != LoadsState::Gather ||
9263 (BestVF > 1 && static_cast<unsigned>(NumElts) == 2 * BestVF)) {
9264 if (LS == LoadsState::ScatterVectorize) {
9265 if (MaskedGatherVectorized.empty() ||
9266 Cnt >= MaskedGatherVectorized.back() + NumElts)
9267 MaskedGatherVectorized.push_back(Cnt);
9268 continue;
9269 }
9270 if (LS != LoadsState::Gather) {
9271 Results.emplace_back(Values, LS);
9272 VectorizedLoads.insert_range(Slice);
9273 // If we vectorized initial block, no need to try to vectorize it
9274 // again.
9275 if (Cnt == StartIdx)
9276 StartIdx += NumElts;
9277 }
9278 // Check if the whole array was vectorized already - exit.
9279 if (StartIdx >= Loads.size())
9280 break;
9281 // Erase last masked gather candidate, if another candidate within
9282 // the range is found to be better.
9283 if (!MaskedGatherVectorized.empty() &&
9284 Cnt < MaskedGatherVectorized.back() + NumElts)
9285 MaskedGatherVectorized.pop_back();
9286 Cnt += NumElts - 1;
9287 continue;
9288 }
9289 }
9290 if (!AllowToVectorize || BestVF == 0)
9292 }
9293 // Mark masked gathers candidates as vectorized, if any.
9294 for (unsigned Cnt : MaskedGatherVectorized) {
9295 ArrayRef<LoadInst *> Slice = ArrayRef(Loads).slice(
9296 Cnt, std::min<unsigned>(NumElts, Loads.size() - Cnt));
9298 reinterpret_cast<Value *const *>(Slice.begin()), Slice.size());
9300 VectorizedLoads.insert_range(Slice);
9301 // If we vectorized initial block, no need to try to vectorize it again.
9302 if (Cnt == StartIdx)
9303 StartIdx += NumElts;
9304 }
9305 }
9306 for (LoadInst *LI : Loads) {
9307 if (!VectorizedLoads.contains(LI))
9308 NonVectorized.push_back(LI);
9309 }
9310 return Results;
9311 };
9312 auto ProcessGatheredLoads =
9313 [&, &TTI = *TTI](
9315 bool Final = false) {
9316 SmallVector<LoadInst *> NonVectorized;
9317 for (ArrayRef<std::pair<LoadInst *, int64_t>> LoadsDists :
9318 GatheredLoads) {
9319 if (LoadsDists.size() <= 1) {
9320 NonVectorized.push_back(LoadsDists.back().first);
9321 continue;
9322 }
9324 LoadsDists);
9325 SmallVector<LoadInst *> OriginalLoads(make_first_range(LoadsDists));
9326 stable_sort(LocalLoadsDists, LoadSorter);
9328 unsigned MaxConsecutiveDistance = 0;
9329 unsigned CurrentConsecutiveDist = 1;
9330 int64_t LastDist = LocalLoadsDists.front().second;
9331 bool AllowMaskedGather = IsMaskedGatherSupported(OriginalLoads);
9332 for (const std::pair<LoadInst *, int64_t> &L : LocalLoadsDists) {
9333 if (isVectorized(L.first))
9334 continue;
9335 assert(LastDist >= L.second &&
9336 "Expected first distance always not less than second");
9337 if (static_cast<uint64_t>(LastDist - L.second) ==
9338 CurrentConsecutiveDist) {
9339 ++CurrentConsecutiveDist;
9340 MaxConsecutiveDistance =
9341 std::max(MaxConsecutiveDistance, CurrentConsecutiveDist);
9342 Loads.push_back(L.first);
9343 continue;
9344 }
9345 if (!AllowMaskedGather && CurrentConsecutiveDist == 1 &&
9346 !Loads.empty())
9347 Loads.pop_back();
9348 CurrentConsecutiveDist = 1;
9349 LastDist = L.second;
9350 Loads.push_back(L.first);
9351 }
9352 if (Loads.size() <= 1)
9353 continue;
9354 if (AllowMaskedGather)
9355 MaxConsecutiveDistance = Loads.size();
9356 else if (MaxConsecutiveDistance < 2)
9357 continue;
9358 BoUpSLP::ValueSet VectorizedLoads;
9359 SmallVector<LoadInst *> SortedNonVectorized;
9361 GetVectorizedRanges(Loads, VectorizedLoads, SortedNonVectorized,
9362 Final, MaxConsecutiveDistance);
9363 if (!Results.empty() && !SortedNonVectorized.empty() &&
9364 OriginalLoads.size() == Loads.size() &&
9365 MaxConsecutiveDistance == Loads.size() &&
9367 [](const std::pair<ArrayRef<Value *>, LoadsState> &P) {
9368 return P.second == LoadsState::ScatterVectorize;
9369 })) {
9370 VectorizedLoads.clear();
9371 SmallVector<LoadInst *> UnsortedNonVectorized;
9373 UnsortedResults =
9374 GetVectorizedRanges(OriginalLoads, VectorizedLoads,
9375 UnsortedNonVectorized, Final,
9376 OriginalLoads.size());
9377 if (SortedNonVectorized.size() >= UnsortedNonVectorized.size()) {
9378 SortedNonVectorized.swap(UnsortedNonVectorized);
9379 Results.swap(UnsortedResults);
9380 }
9381 }
9382 for (auto [Slice, _] : Results) {
9383 LLVM_DEBUG(dbgs() << "SLP: Trying to vectorize gathered loads ("
9384 << Slice.size() << ")\n");
9385 if (any_of(Slice, [&](Value *V) { return isVectorized(V); })) {
9386 for (Value *L : Slice)
9387 if (!isVectorized(L))
9388 SortedNonVectorized.push_back(cast<LoadInst>(L));
9389 continue;
9390 }
9391
9392 // Select maximum VF as a maximum of user gathered nodes and
9393 // distance between scalar loads in these nodes.
9394 unsigned MaxVF = Slice.size();
9395 unsigned UserMaxVF = 0;
9396 unsigned InterleaveFactor = 0;
9397 if (MaxVF == 2) {
9398 UserMaxVF = MaxVF;
9399 } else {
9400 // Found distance between segments of the interleaved loads.
9401 std::optional<unsigned> InterleavedLoadsDistance = 0;
9402 unsigned Order = 0;
9403 std::optional<unsigned> CommonVF = 0;
9404 DenseMap<const TreeEntry *, unsigned> EntryToPosition;
9405 SmallPtrSet<const TreeEntry *, 8> DeinterleavedNodes;
9406 for (auto [Idx, V] : enumerate(Slice)) {
9407 for (const TreeEntry *E : ValueToGatherNodes.at(V)) {
9408 UserMaxVF = std::max<unsigned>(UserMaxVF, E->Scalars.size());
9409 unsigned Pos =
9410 EntryToPosition.try_emplace(E, Idx).first->second;
9411 UserMaxVF = std::max<unsigned>(UserMaxVF, Idx - Pos + 1);
9412 if (CommonVF) {
9413 if (*CommonVF == 0) {
9414 CommonVF = E->Scalars.size();
9415 continue;
9416 }
9417 if (*CommonVF != E->Scalars.size())
9418 CommonVF.reset();
9419 }
9420 // Check if the load is the part of the interleaved load.
9421 if (Pos != Idx && InterleavedLoadsDistance) {
9422 if (!DeinterleavedNodes.contains(E) &&
9423 any_of(E->Scalars, [&, Slice = Slice](Value *V) {
9424 if (isa<Constant>(V))
9425 return false;
9426 if (isVectorized(V))
9427 return true;
9428 const auto &Nodes = ValueToGatherNodes.at(V);
9429 return (Nodes.size() != 1 || !Nodes.contains(E)) &&
9430 !is_contained(Slice, V);
9431 })) {
9432 InterleavedLoadsDistance.reset();
9433 continue;
9434 }
9435 DeinterleavedNodes.insert(E);
9436 if (*InterleavedLoadsDistance == 0) {
9437 InterleavedLoadsDistance = Idx - Pos;
9438 continue;
9439 }
9440 if ((Idx - Pos) % *InterleavedLoadsDistance != 0 ||
9441 (Idx - Pos) / *InterleavedLoadsDistance < Order)
9442 InterleavedLoadsDistance.reset();
9443 Order = (Idx - Pos) / InterleavedLoadsDistance.value_or(1);
9444 }
9445 }
9446 }
9447 DeinterleavedNodes.clear();
9448 // Check if the large load represents interleaved load operation.
9449 if (InterleavedLoadsDistance.value_or(0) > 1 &&
9450 CommonVF.value_or(0) != 0) {
9451 InterleaveFactor = bit_ceil(*InterleavedLoadsDistance);
9452 unsigned VF = *CommonVF;
9453 OrdersType Order;
9454 SmallVector<Value *> PointerOps;
9455 StridedPtrInfo SPtrInfo;
9456 // Segmented load detected - vectorize at maximum vector factor.
9457 if (InterleaveFactor <= Slice.size() &&
9458 TTI.isLegalInterleavedAccessType(
9460 getWidenedType(Slice.front()->getType(), VF)),
9461 InterleaveFactor,
9462 cast<LoadInst>(Slice.front())->getAlign(),
9463 cast<LoadInst>(Slice.front())
9464 ->getPointerAddressSpace()) &&
9465 canVectorizeLoads(Slice, Slice.front(), Order, PointerOps,
9466 SPtrInfo) == LoadsState::Vectorize) {
9467 UserMaxVF = InterleaveFactor * VF;
9468 } else {
9469 InterleaveFactor = 0;
9470 }
9471 }
9472 // Cannot represent the loads as consecutive vectorizable nodes -
9473 // just exit.
9474 unsigned ConsecutiveNodesSize = 0;
9475 if (!LoadEntriesToVectorize.empty() && InterleaveFactor == 0 &&
9476 any_of(zip(LoadEntriesToVectorize, LoadSetsToVectorize),
9477 [&, Slice = Slice](const auto &P) {
9478 const auto *It = find_if(Slice, [&](Value *V) {
9479 return std::get<1>(P).contains(V);
9480 });
9481 if (It == Slice.end())
9482 return false;
9483 const TreeEntry &TE =
9484 *VectorizableTree[std::get<0>(P)];
9485 ArrayRef<Value *> VL = TE.Scalars;
9486 OrdersType Order;
9487 SmallVector<Value *> PointerOps;
9488 StridedPtrInfo SPtrInfo;
9490 VL, VL.front(), Order, PointerOps, SPtrInfo);
9491 if (State == LoadsState::ScatterVectorize ||
9494 return false;
9495 ConsecutiveNodesSize += VL.size();
9496 size_t Start = std::distance(Slice.begin(), It);
9497 size_t Sz = Slice.size() - Start;
9498 return Sz < VL.size() ||
9499 Slice.slice(Start, VL.size()) != VL;
9500 }))
9501 continue;
9502 // Try to build long masked gather loads.
9503 UserMaxVF = bit_ceil(UserMaxVF);
9504 if (InterleaveFactor == 0 &&
9505 any_of(seq<unsigned>(Slice.size() / UserMaxVF),
9506 [&, Slice = Slice](unsigned Idx) {
9507 OrdersType Order;
9508 SmallVector<Value *> PointerOps;
9509 StridedPtrInfo SPtrInfo;
9510 return canVectorizeLoads(
9511 Slice.slice(Idx * UserMaxVF, UserMaxVF),
9512 Slice[Idx * UserMaxVF], Order, PointerOps,
9513 SPtrInfo) == LoadsState::ScatterVectorize;
9514 }))
9515 UserMaxVF = MaxVF;
9516 if (Slice.size() != ConsecutiveNodesSize)
9517 MaxVF = std::min<unsigned>(MaxVF, UserMaxVF);
9518 }
9519 for (unsigned VF = MaxVF; VF >= 2; VF /= 2) {
9520 bool IsVectorized = true;
9521 for (unsigned I = 0, E = Slice.size(); I < E; I += VF) {
9522 ArrayRef<Value *> SubSlice =
9523 Slice.slice(I, std::min(VF, E - I));
9524 if (isVectorized(SubSlice.front()))
9525 continue;
9526 // Check if the subslice is to be-vectorized entry, which is not
9527 // equal to entry.
9528 if (any_of(zip(LoadEntriesToVectorize, LoadSetsToVectorize),
9529 [&](const auto &P) {
9530 return !SubSlice.equals(
9531 VectorizableTree[std::get<0>(P)]
9532 ->Scalars) &&
9533 set_is_subset(SubSlice, std::get<1>(P));
9534 }))
9535 continue;
9536 unsigned Sz = VectorizableTree.size();
9537 // A chunk smaller than InterleaveFactor cannot form an
9538 // interleave group; keep it non-interleaved instead.
9539 buildTreeRec(
9540 SubSlice, 0, EdgeInfo(),
9541 SubSlice.size() >= InterleaveFactor ? InterleaveFactor : 0);
9542 if (Sz == VectorizableTree.size()) {
9543 IsVectorized = false;
9544 // Try non-interleaved vectorization with smaller vector
9545 // factor.
9546 if (InterleaveFactor > 0) {
9547 VF = 2 * (MaxVF / InterleaveFactor);
9548 InterleaveFactor = 0;
9549 }
9550 continue;
9551 }
9552 }
9553 if (IsVectorized)
9554 break;
9555 }
9556 }
9557 NonVectorized.append(SortedNonVectorized);
9558 }
9559 return NonVectorized;
9560 };
9561 for (const auto &GLs : GatheredLoads) {
9562 const auto &Ref = GLs.second;
9563 SmallVector<LoadInst *> NonVectorized = ProcessGatheredLoads(Ref);
9564 if (!Ref.empty() && !NonVectorized.empty() &&
9565 accumulate(
9566 Ref, 0u,
9567 [](unsigned S, ArrayRef<std::pair<LoadInst *, int64_t>> LoadsDists)
9568 -> unsigned { return S + LoadsDists.size(); }) !=
9569 NonVectorized.size() &&
9570 IsMaskedGatherSupported(NonVectorized)) {
9572 FinalGatheredLoads;
9573 for (LoadInst *LI : NonVectorized) {
9574 // Reinsert non-vectorized loads to other list of loads with the same
9575 // base pointers.
9576 gatherPossiblyVectorizableLoads(*this, LI, *DL, *SE, *TTI,
9577 FinalGatheredLoads,
9578 /*AddNew=*/false);
9579 }
9580 // Final attempt to vectorize non-vectorized loads.
9581 (void)ProcessGatheredLoads(FinalGatheredLoads, /*Final=*/true);
9582 }
9583 }
9584 // Try to vectorize postponed load entries, previously marked as gathered.
9585 for (unsigned Idx : LoadEntriesToVectorize) {
9586 const TreeEntry &E = *VectorizableTree[Idx];
9587 SmallVector<Value *> GatheredScalars(E.Scalars.begin(), E.Scalars.end());
9588 // Avoid reordering, if possible.
9589 if (!E.ReorderIndices.empty()) {
9590 // Build a mask out of the reorder indices and reorder scalars per this
9591 // mask.
9592 SmallVector<int> ReorderMask;
9593 inversePermutation(E.ReorderIndices, ReorderMask);
9594 reorderScalars(GatheredScalars, ReorderMask);
9595 }
9596 buildTreeRec(GatheredScalars, 0, EdgeInfo());
9597 }
9598 // If no new entries created, consider it as no gathered loads entries must be
9599 // handled.
9600 if (static_cast<unsigned>(*GatheredLoadsEntriesFirst) ==
9601 VectorizableTree.size())
9602 GatheredLoadsEntriesFirst.reset();
9603}
9604
9605/// Generates key/subkey pair for the given value to provide effective sorting
9606/// of the values and better detection of the vectorizable values sequences. The
9607/// keys/subkeys can be used for better sorting of the values themselves (keys)
9608/// and in values subgroups (subkeys).
9609static std::pair<size_t, size_t> generateKeySubkey(
9610 Value *V, const TargetLibraryInfo *TLI,
9611 function_ref<hash_code(size_t, LoadInst *)> LoadsSubkeyGenerator,
9612 bool AllowAlternate) {
9613 hash_code Key = hash_value(V->getValueID() + 2);
9614 hash_code SubKey = hash_value(0);
9615 // Sort the loads by the distance between the pointers.
9616 if (auto *LI = dyn_cast<LoadInst>(V)) {
9617 Key = hash_combine(LI->getType(), hash_value(Instruction::Load), Key);
9618 if (LI->isSimple())
9619 SubKey = hash_value(LoadsSubkeyGenerator(Key, LI));
9620 else
9621 Key = SubKey = hash_value(LI);
9622 } else if (isVectorLikeInstWithConstOps(V)) {
9623 // Sort extracts by the vector operands.
9625 Key = hash_value(Value::UndefValueVal + 1);
9626 if (auto *EI = dyn_cast<ExtractElementInst>(V)) {
9627 if (!isUndefVector(EI->getVectorOperand()).all() &&
9628 !isa<UndefValue>(EI->getIndexOperand()))
9629 SubKey = hash_value(EI->getVectorOperand());
9630 }
9631 } else if (auto *I = dyn_cast<Instruction>(V)) {
9632 // Sort other instructions just by the opcodes except for CMPInst.
9633 // For CMP also sort by the predicate kind.
9635 isValidForAlternation(I->getOpcode())) {
9636 if (AllowAlternate)
9637 Key = hash_value(isa<BinaryOperator>(I) ? 1 : 0);
9638 else
9639 Key = hash_combine(hash_value(I->getOpcode()), Key);
9640 SubKey = hash_combine(
9641 hash_value(I->getOpcode()), hash_value(I->getType()),
9643 ? I->getType()
9644 : cast<CastInst>(I)->getOperand(0)->getType()));
9645 // For casts, look through the only operand to improve compile time.
9646 if (isa<CastInst>(I)) {
9647 std::pair<size_t, size_t> OpVals =
9648 generateKeySubkey(I->getOperand(0), TLI, LoadsSubkeyGenerator,
9649 /*AllowAlternate=*/true);
9650 Key = hash_combine(OpVals.first, Key);
9651 SubKey = hash_combine(OpVals.first, SubKey);
9652 }
9653 } else if (auto *CI = dyn_cast<CmpInst>(I)) {
9654 CmpInst::Predicate Pred = CI->getPredicate();
9655 if (CI->isCommutative())
9656 Pred = std::min(Pred, CmpInst::getInversePredicate(Pred));
9658 SubKey = hash_combine(hash_value(I->getOpcode()), hash_value(Pred),
9659 hash_value(SwapPred),
9660 hash_value(CI->getOperand(0)->getType()));
9661 } else if (auto *Call = dyn_cast<CallInst>(I)) {
9663 if (isTriviallyVectorizable(ID)) {
9664 if (ID == Intrinsic::fmuladd)
9665 ID = Intrinsic::fma;
9666 SubKey = hash_combine(hash_value(I->getOpcode()), hash_value(ID),
9667 hash_value(I->getType()));
9668 } else if (!VFDatabase(*Call).getMappings(*Call).empty()) {
9669 SubKey = hash_combine(hash_value(I->getOpcode()),
9670 hash_value(Call->getCalledFunction()),
9671 hash_value(I->getType()));
9672 } else {
9674 SubKey = hash_combine(hash_value(I->getOpcode()), hash_value(Call));
9675 }
9676 for (const CallBase::BundleOpInfo &Op : Call->bundle_op_infos())
9677 SubKey = hash_combine(hash_value(Op.Begin), hash_value(Op.End),
9678 hash_value(Op.Tag), SubKey);
9679 } else if (auto *Gep = dyn_cast<GetElementPtrInst>(I)) {
9680 if (Gep->getNumOperands() == 2 && isa<ConstantInt>(Gep->getOperand(1)))
9681 SubKey = hash_value(Gep->getPointerOperand());
9682 else
9683 SubKey = hash_value(Gep);
9684 } else if (BinaryOperator::isIntDivRem(I->getOpcode()) &&
9685 !isa<ConstantInt>(I->getOperand(1))) {
9686 // Do not try to vectorize instructions with potentially high cost.
9687 SubKey = hash_value(I);
9688 } else {
9689 SubKey =
9690 hash_combine(hash_value(I->getOpcode()), hash_value(I->getType()));
9691 }
9692 Key = hash_combine(hash_value(I->getParent()->getNumber()), Key);
9693 }
9694 return std::make_pair(Key, SubKey);
9695}
9696
9697/// Checks if the specified instruction \p I is an main operation for the given
9698/// \p MainOp and \p AltOp instructions.
9699static bool isMainInstruction(Instruction *I, Instruction *MainOp,
9700 Instruction *AltOp, const TargetLibraryInfo &TLI);
9701
9702/// Builds the arguments types vector for the given call instruction with the
9703/// given \p ID for the specified vector factor.
9706 const unsigned VF, unsigned MinBW,
9707 const TargetTransformInfo *TTI) {
9708 SmallVector<Type *> ArgTys;
9709 for (auto [Idx, Arg] : enumerate(CI->args())) {
9710 if (ID != Intrinsic::not_intrinsic) {
9712 ArgTys.push_back(Arg->getType());
9713 continue;
9714 }
9715 if (MinBW > 0) {
9716 ArgTys.push_back(
9717 getWidenedType(IntegerType::get(CI->getContext(), MinBW), VF));
9718 continue;
9719 }
9720 }
9721 ArgTys.push_back(getWidenedType(Arg->getType(), VF));
9722 }
9723 return ArgTys;
9724}
9725
9726/// Calculates the costs of vectorized intrinsic (if possible) and vectorized
9727/// function (if possible) calls. Returns invalid cost for the corresponding
9728/// calls, if they cannot be vectorized/will be scalarized.
9729static std::pair<InstructionCost, InstructionCost>
9731 const TargetLibraryInfo *TLI, ArrayRef<Type *> ArgTys,
9733 auto Shape = VFShape::get(CI->getFunctionType(),
9735 false /*HasGlobalPred*/);
9736 Function *VecFunc = VFDatabase(*CI).getVectorizedFunction(Shape);
9737 auto LibCost = InstructionCost::getInvalid();
9738 if (!CI->isNoBuiltin() && VecFunc) {
9739 // Calculate the cost of the vector library call.
9740 // If the corresponding vector call is cheaper, return its cost.
9741 LibCost = TTI->getCallInstrCost(nullptr, VecTy, ArgTys, CostKind);
9742 }
9744
9745 // Calculate the cost of the vector intrinsic call.
9746 FastMathFlags FMF;
9747 if (auto *FPCI = dyn_cast<FPMathOperator>(CI))
9748 FMF = FPCI->getFastMathFlags();
9749 const InstructionCost ScalarLimit = 10000;
9750 IntrinsicCostAttributes CostAttrs(ID, VecTy, ArgTys, FMF, nullptr,
9751 LibCost.isValid() ? LibCost : ScalarLimit);
9752 auto IntrinsicCost = TTI->getIntrinsicInstrCost(CostAttrs, CostKind);
9753 if (LibCost.isValid()) {
9754 if (IntrinsicCost > LibCost)
9756 } else if (IntrinsicCost > ScalarLimit) {
9757 // A type-based query always scalarizes struct-returning intrinsics (e.g.
9758 // llvm.sincos), which do not have a VFDatabase name mapping. Retry with an
9759 // argument-aware query (as the loop vectorizer does) so such lowerings are
9760 // taken into account.
9761 SmallVector<const Value *> Args(CI->args());
9762 IntrinsicCostAttributes ArgAwareAttrs(
9763 ID, VecTy, Args, ArgTys, FMF, dyn_cast<IntrinsicInst>(CI), ScalarLimit);
9764 IntrinsicCost = TTI->getIntrinsicInstrCost(ArgAwareAttrs, CostKind);
9765 if (IntrinsicCost > ScalarLimit)
9767 }
9768
9769 return {IntrinsicCost, LibCost};
9770}
9771
9772/// \returns the reciprocal-throughput cost of \p I widened to \p VF lanes (an
9773/// arithmetic op or a vectorizable call).
9775 const TargetTransformInfo &TTI,
9776 const TargetLibraryInfo &TLI,
9779 "getVectorOpCost expects an arithmetic op or a vectorizable call.");
9780 Type *VecTy = getWidenedType(I->getType(), VF);
9781 if (auto *CI = dyn_cast<CallInst>(I)) {
9783 SmallVector<Type *> ArgTys = buildIntrinsicArgTypes(CI, ID, VF, 0, &TTI);
9784 auto [IntrCost, LibCost] =
9785 getVectorCallCosts(CI, VecTy, &TTI, &TLI, ArgTys, CostKind);
9786 return std::min(IntrCost, LibCost);
9787 }
9788 return TTI.getArithmeticInstrCost(I->getOpcode(), VecTy, CostKind);
9789}
9790
9791/// Packs a type's kind and scalar width into one key, so an opcode/intrinsic
9792/// id reused across scalar widths (e.g. fdiv float vs. fdiv double) is cached
9793/// per width instead of sharing one verdict.
9794static unsigned getPoorThroughputTypeKey(Type *Ty) {
9795 return (static_cast<unsigned>(Ty->getTypeID()) << 16) |
9796 Ty->getScalarSizeInBits();
9797}
9798
9799namespace {
9800/// Memoizes opcode / intrinsic / callee kinds already ruled out as seeds.
9801struct PoorThroughputOpCache {
9802 SmallDenseSet<std::pair<unsigned, unsigned>> CheapOpcodes;
9803 SmallDenseSet<std::pair<Intrinsic::ID, unsigned>> CheapIntrinsics;
9804 // Keyed on the callee alone: a Function's signature is fixed, so its type
9805 // never varies between calls.
9806 SmallDenseSet<const Function *> CheapCallees;
9807};
9808
9809/// Groups poor-throughput seeds for tryToVectorizeSequence.
9810struct SeedGroupKey {
9811 unsigned Opcode = 0;
9813 StringRef CalleeName;
9814
9815 bool less(const SeedGroupKey &O) const {
9816 if (Opcode != O.Opcode)
9817 return Opcode < O.Opcode;
9818 if (IntrID != O.IntrID)
9819 return IntrID < O.IntrID;
9820 return CalleeName < O.CalleeName;
9821 }
9822};
9823
9824static SeedGroupKey getSeedGroupKey(const Instruction *I,
9825 const TargetLibraryInfo &TLI) {
9826 SeedGroupKey K;
9827 K.Opcode = I->getOpcode();
9828 if (auto *CI = dyn_cast<CallInst>(I)) {
9829 K.IntrID = getVectorIntrinsicIDForCall(CI, &TLI);
9830 if (const Function *F = CI->getCalledFunction())
9831 K.CalleeName = F->getName();
9832 }
9833 return K;
9834}
9835} // namespace
9836
9837/// Returns true if \p I is an expensive scalar op whose vector form is cheaper
9838/// per lane (e.g. fdiv, frem, fsqrt).
9840 const TargetLibraryInfo &TLI,
9841 PoorThroughputOpCache &Cache,
9844 return false;
9845 Type *Ty = I->getType();
9846 if ((Ty->isVectorTy() && !SLPReVec) || Ty->isAggregateType() ||
9848 return false;
9849 auto Analyze = [&]() {
9850 InstructionCost ScalarCost = TTI.getInstructionCost(I, CostKind);
9851 if (ScalarCost < TTI::TCC_Expensive)
9852 return false;
9853 constexpr unsigned MinVF = 2;
9854 return getVectorOpCost(I, MinVF, TTI, TLI, CostKind) < ScalarCost * MinVF;
9855 };
9856 auto CheckCached = [&](bool IsCheap, llvm::function_ref<void()> MarkCheap) {
9857 if (IsCheap)
9858 return false;
9859 if (Analyze())
9860 return true;
9861 MarkCheap();
9862 return false;
9863 };
9864 if (auto *CI = dyn_cast<CallInst>(I)) {
9865 if (any_of(CI->args(), [](const Value *Arg) {
9866 return !isValidElementType(Arg->getType(), SLPReVec);
9867 }))
9868 return false;
9869 if (Intrinsic::ID ID = getVectorIntrinsicIDForCall(CI, &TLI)) {
9870 auto Key = std::make_pair(ID, getPoorThroughputTypeKey(Ty));
9871 return CheckCached(Cache.CheapIntrinsics.contains(Key),
9872 [&] { Cache.CheapIntrinsics.insert(Key); });
9873 }
9874 const Function *Callee = CI->getCalledFunction();
9875 if (!Callee)
9876 return Analyze();
9877 return CheckCached(Cache.CheapCallees.contains(Callee),
9878 [&] { Cache.CheapCallees.insert(Callee); });
9879 }
9880 auto Key = std::make_pair(I->getOpcode(), getPoorThroughputTypeKey(Ty));
9881 return CheckCached(Cache.CheapOpcodes.contains(Key),
9882 [&] { Cache.CheapOpcodes.insert(Key); });
9883}
9884
9885/// Find the innermost loop starting from \p L, for which at least a single
9886/// value in \p VL is not invariant.
9888 ArrayRef<Value *> VL) {
9889 assert(L && "Expected valid loop");
9890 auto IsLoopInvariant = [&](const Loop *L, ArrayRef<Value *> VL) {
9891 return all_of(VL, [&](Value *V) {
9892 return isa<Constant>(V) || !isa<Instruction>(V) || L->isLoopInvariant(V);
9893 });
9894 };
9895 while (L && IsLoopInvariant(L, VL))
9896 L = L->getParentLoop();
9897 return L;
9898}
9899
9900/// Get the loop nest for the given loop.
9901ArrayRef<const Loop *> BoUpSLP::getLoopNest(const Loop *L) {
9902 assert(L && "Expected valid loop");
9903 if (LoopAwareTripCount == 0)
9904 return {};
9905 SmallVector<const Loop *> &Res =
9906 LoopToLoopNest.try_emplace(L).first->getSecond();
9907 if (!Res.empty())
9908 return Res;
9909 SmallVector<const Loop *> LoopNest;
9910 while (L) {
9911 LoopNest.push_back(L);
9912 L = L->getParentLoop();
9913 }
9914 Res.assign(LoopNest.rbegin(), LoopNest.rend());
9915 return Res;
9916}
9917
9918/// Detects an extractvalue bundle that can be widened by vectorizing the
9919/// underlying struct-returning calls.
9920///
9921/// \p VL is a bundle whose state \p S is Instruction::ExtractValue. The
9922/// bundle is acceptable for widening into one struct-of-vectors call only
9923/// when:
9924/// - every element of \p VL is an ExtractValueInst,
9925/// - every ExtractValueInst extracts the same struct field (its
9926/// getIndices() matches the main op's indices),
9927/// - the aggregate operands form a uniform set of CallInsts (per
9928/// getSameOpcode) that is not an alt-shuffle and whose return type is
9929/// a literal struct, and
9930/// - every user of every such call is itself an ExtractValueInst, so the
9931/// external-use extraction code can rebuild scalars via extractvalue +
9932/// extractelement without needing an insertvalue chain.
9933///
9934/// On success returns true and fills \p Indices with the common field
9935/// index path and \p Calls with the per-lane aggregate calls (in VL order),
9936/// for the caller to feed as the operand of the new tree entry. Otherwise
9937/// returns false and leaves the output parameters untouched.
9939 const InstructionsState &S,
9940 const TargetLibraryInfo &TLI,
9942 SmallVectorImpl<Value *> &Calls) {
9943 assert(S && S.getOpcode() == Instruction::ExtractValue &&
9944 "Expected extractvalue instruction state.");
9946 return false;
9947 auto *VL0 = cast<ExtractValueInst>(S.getMainOp());
9948 ArrayRef<unsigned> VL0Indices = VL0->getIndices();
9950 for (Value *V : VL) {
9951 if (V == VL0) {
9952 Aggregates.push_back(VL0->getAggregateOperand());
9953 continue;
9954 }
9955 auto *IV = cast<ExtractValueInst>(V);
9956 if (IV->getIndices() != VL0Indices ||
9957 isa<ScalableVectorType>(IV->getType()))
9958 return false;
9959 Value *Agg = IV->getAggregateOperand();
9960 Aggregates.push_back(Agg);
9961 }
9962 const InstructionsState AggState = getSameOpcode(Aggregates, TLI);
9963 if (AggState && AggState.getOpcode() == Instruction::Call &&
9964 !AggState.isAltShuffle() &&
9965 isa<StructType>(AggState.getMainOp()->getType()) &&
9967 // The struct-returning call may have non-bundle users too. The external
9968 // extraction code rebuilds scalars by extractvalue + extractelement,
9969 // which only works when every user of the call is an ExtractValueInst.
9970 // Bail out if any aggregate has a different kind of user.
9971 for (Value *Agg : Aggregates) {
9972 if (!all_of(Agg->users(), IsaPred<ExtractValueInst>))
9973 return false;
9974 }
9975 Indices.assign(VL0Indices.begin(), VL0Indices.end());
9976 Calls.swap(Aggregates);
9977 return true;
9978 }
9979 return false;
9980}
9981
9983 return all_of(VL, [](Value *V) {
9984 return !isa<StructType>(V->getType()) ||
9985 all_of(V->users(), IsaPred<ExtractValueInst>);
9986 });
9987}
9988
9989BoUpSLP::TreeEntry::EntryState BoUpSLP::getScalarsVectorizationState(
9990 const InstructionsState &S, ArrayRef<Value *> VL,
9991 bool IsScatterVectorizeUserTE, OrdersType &CurrentOrder,
9992 SmallVectorImpl<Value *> &PointerOps, StridedPtrInfo &SPtrInfo,
9993 SmallVectorImpl<int> &ReuseShuffleIndices) {
9994 assert(S.getMainOp() &&
9995 "Expected instructions with same/alternate opcodes only.");
9996
9997 unsigned ShuffleOrOp =
9998 S.isAltShuffle() ? (unsigned)Instruction::ShuffleVector : S.getOpcode();
9999 Instruction *VL0 = S.getMainOp();
10000 switch (ShuffleOrOp) {
10001 case Instruction::PHI: {
10002 // Too many operands - gather, most probably won't be vectorized.
10003 if (VL0->getNumOperands() > MaxPHINumOperands)
10004 return TreeEntry::NeedToGather;
10005 // Check for terminator values (e.g. invoke).
10006 for (Value *V : VL) {
10007 auto *PHI = dyn_cast<PHINode>(V);
10008 if (!PHI)
10009 continue;
10010 for (Value *Incoming : PHI->incoming_values()) {
10012 if (Term && Term->isTerminator()) {
10014 << "SLP: Need to swizzle PHINodes (terminator use).\n");
10015 return TreeEntry::NeedToGather;
10016 }
10017 }
10018 }
10019
10020 return TreeEntry::Vectorize;
10021 }
10022 case Instruction::ExtractElement:
10023 if (any_of(VL, [&](Value *V) {
10024 if (S.isCopyableElement(V) || isa<PoisonValue>(V))
10025 return false;
10026 auto *EI = dyn_cast<ExtractElementInst>(V);
10027 if (!EI)
10028 return true;
10029 Value *Op = EI->getOperand(0);
10030 if (isVectorized(Op))
10031 return true;
10032 auto *OpI = dyn_cast<Instruction>(Op);
10033 return OpI && OpI->isTerminator();
10034 }))
10035 return TreeEntry::NeedToGather;
10036 [[fallthrough]];
10037 case Instruction::ExtractValue: {
10038 bool Reuse = canReuseExtract(VL, CurrentOrder);
10039 // Copyable lanes are inserted into the reused source vector at their own
10040 // index, which is correct only for the identity extract order (empty
10041 // CurrentOrder) and without a reuse shuffle; other cases fall back to
10042 // gather.
10044 (!Reuse || !ReuseShuffleIndices.empty()))
10045 return TreeEntry::NeedToGather;
10046 if (Reuse || !CurrentOrder.empty())
10047 return TreeEntry::Vectorize;
10048 SmallVector<unsigned> Indices;
10050 if (ShuffleOrOp == Instruction::ExtractValue &&
10051 checkEVsForVecCalls(VL, S, *TLI, Indices, Calls))
10052 return TreeEntry::Vectorize;
10053 LLVM_DEBUG(dbgs() << "SLP: Gather extract sequence.\n");
10054 return TreeEntry::NeedToGather;
10055 }
10056 case Instruction::InsertValue:
10057 // Handle only simple insertvalue building a homogeneous aggregate from
10058 // scalars: exactly one index and an inserted value whose type is a valid
10059 // vector element type. Vectors and aggregates (structs/arrays) are
10060 // rejected, since the inserted operand type is later widened into the
10061 // result FixedVectorType.
10062 // TODO: Support more complex insertvalues.
10063 if (any_of(VL,
10064 [](Value *V) {
10065 auto *IV = dyn_cast<InsertValueInst>(V);
10066 return IV && (IV->getNumIndices() != 1 ||
10068 IV->getOperand(1)->getType(), SLPReVec) ||
10069 IV->getOperand(1)->getType()->isVectorTy());
10070 }) ||
10071 none_of(VL, [](Value *V) {
10072 auto *IV = dyn_cast<InsertValueInst>(V);
10073 return IV && isa<UndefValue>(IV->getAggregateOperand());
10074 }))
10075 return TreeEntry::NeedToGather;
10076 [[fallthrough]];
10077 case Instruction::InsertElement: {
10078 // Check that we have a buildvector and not a shuffle of 2 or more
10079 // different vectors.
10080 ValueSet SourceVectors;
10081 for (Value *V : VL) {
10082 if (isa<PoisonValue>(V)) {
10083 LLVM_DEBUG(
10084 dbgs()
10085 << "SLP: Gather of insertelement/insertvalue/poison vector.\n");
10086 return TreeEntry::NeedToGather;
10087 }
10088 SourceVectors.insert(cast<Instruction>(V)->getOperand(0));
10089 assert(getElementIndex(V) != std::nullopt &&
10090 "Non-constant or undef index?");
10091 }
10092
10093 if (count_if(VL, [&SourceVectors](Value *V) {
10094 return !SourceVectors.contains(V);
10095 }) >= 2) {
10096 // Found 2nd source vector - cancel.
10097 LLVM_DEBUG(
10098 dbgs() << "SLP: Gather of insertelement/insertvalue vectors with "
10099 "different source vectors.\n");
10100 return TreeEntry::NeedToGather;
10101 }
10102
10103 if (any_of(VL, [&SourceVectors](Value *V) {
10104 // The last InsertElement/InsertValue can have multiple uses.
10105 return SourceVectors.contains(V) && !V->hasOneUse();
10106 })) {
10107 assert((SLPReVec || ShuffleOrOp == Instruction::InsertValue) &&
10108 "Only supported by REVEC or InsertValue.");
10109 LLVM_DEBUG(
10110 dbgs() << "SLP: Gather of insertelement/insertvalue vectors with "
10111 "multiple uses.\n");
10112 return TreeEntry::NeedToGather;
10113 }
10114
10115 return TreeEntry::Vectorize;
10116 }
10117 case Instruction::Load: {
10118 // Check that a vectorized load would load the same memory as a scalar
10119 // load. For example, we don't want to vectorize loads that are smaller
10120 // than 8-bit. Even though we have a packed struct {<i2, i2, i2, i2>} LLVM
10121 // treats loading/storing it as an i8 struct. If we vectorize loads/stores
10122 // from such a struct, we read/write packed bits disagreeing with the
10123 // unvectorized version.
10124 auto IsGatheredNode = [&]() {
10125 if (!GatheredLoadsEntriesFirst)
10126 return false;
10127 return all_of(VL, [&](Value *V) {
10128 if (isa<PoisonValue>(V))
10129 return true;
10130 return any_of(getTreeEntries(V), [&](const TreeEntry *TE) {
10131 return TE->Idx >= *GatheredLoadsEntriesFirst;
10132 });
10133 });
10134 };
10135 switch (canVectorizeLoads(VL, VL0, CurrentOrder, PointerOps, SPtrInfo)) {
10137 return TreeEntry::Vectorize;
10139 if (!IsGraphTransformMode && VectorizableTree.size() > 1) {
10140 // Delay slow vectorized nodes for better vectorization attempts.
10141 LoadEntriesToVectorize.insert(VectorizableTree.size());
10142 return TreeEntry::NeedToGather;
10143 }
10144 return IsGatheredNode() ? TreeEntry::NeedToGather
10145 : TreeEntry::CompressVectorize;
10147 if (!IsGraphTransformMode && VectorizableTree.size() > 1) {
10148 // Delay slow vectorized nodes for better vectorization attempts.
10149 LoadEntriesToVectorize.insert(VectorizableTree.size());
10150 return TreeEntry::NeedToGather;
10151 }
10152 return IsGatheredNode() ? TreeEntry::NeedToGather
10153 : TreeEntry::ScatterVectorize;
10155 if (!IsGraphTransformMode && VectorizableTree.size() > 1) {
10156 // Delay slow vectorized nodes for better vectorization attempts.
10157 LoadEntriesToVectorize.insert(VectorizableTree.size());
10158 return TreeEntry::NeedToGather;
10159 }
10160 return IsGatheredNode() ? TreeEntry::NeedToGather
10161 : TreeEntry::StridedVectorize;
10163 if (!IsGraphTransformMode && VectorizableTree.size() > 1) {
10164 // Delay slow vectorized nodes for better vectorization attempts.
10165 LoadEntriesToVectorize.insert(VectorizableTree.size());
10166 return TreeEntry::NeedToGather;
10167 }
10168 return IsGatheredNode() ? TreeEntry::NeedToGather
10169 : TreeEntry::BlendedLoadVectorize;
10170 case LoadsState::Gather:
10171#ifndef NDEBUG
10172 Type *ScalarTy = VL0->getType();
10173 if (DL->getTypeSizeInBits(ScalarTy) !=
10174 DL->getTypeAllocSizeInBits(ScalarTy))
10175 LLVM_DEBUG(dbgs() << "SLP: Gathering loads of non-packed type.\n");
10176 else if (any_of(VL, [](Value *V) {
10177 auto *LI = dyn_cast<LoadInst>(V);
10178 return !LI || !LI->isSimple();
10179 }))
10180 LLVM_DEBUG(dbgs() << "SLP: Gathering non-simple loads.\n");
10181 else
10182 LLVM_DEBUG(dbgs() << "SLP: Gathering non-consecutive loads.\n");
10183#endif // NDEBUG
10185 return TreeEntry::NeedToGather;
10186 }
10187 llvm_unreachable("Unexpected state of loads");
10188 }
10189 case Instruction::ZExt:
10190 case Instruction::SExt:
10191 case Instruction::FPToUI:
10192 case Instruction::FPToSI:
10193 case Instruction::FPExt:
10194 case Instruction::PtrToInt:
10195 case Instruction::PtrToAddr:
10196 case Instruction::IntToPtr:
10197 case Instruction::SIToFP:
10198 case Instruction::UIToFP:
10199 case Instruction::Trunc:
10200 case Instruction::FPTrunc:
10201 case Instruction::BitCast: {
10202 Type *SrcTy = VL0->getOperand(0)->getType();
10203 for (Value *V : VL) {
10204 if (isa<PoisonValue>(V))
10205 continue;
10206 Type *Ty = cast<Instruction>(V)->getOperand(0)->getType();
10207 if (Ty != SrcTy || !isValidElementType(Ty, SLPReVec)) {
10208 LLVM_DEBUG(
10209 dbgs() << "SLP: Gathering casts with different src types.\n");
10210 return TreeEntry::NeedToGather;
10211 }
10212 }
10213 return TreeEntry::Vectorize;
10214 }
10215 case Instruction::ICmp:
10216 case Instruction::FCmp: {
10217 // Check that all of the compares have the same predicate.
10218 CmpInst::Predicate P0 = cast<CmpInst>(VL0)->getPredicate();
10220 Type *ComparedTy = VL0->getOperand(0)->getType();
10221 for (Value *V : VL) {
10222 if (isa<PoisonValue>(V))
10223 continue;
10224 auto *Cmp = cast<CmpInst>(V);
10225 if ((Cmp->getPredicate() != P0 && Cmp->getPredicate() != SwapP0 &&
10227 Cmp->getOperand(0)->getType() != ComparedTy) {
10228 LLVM_DEBUG(dbgs() << "SLP: Gathering cmp with different predicate.\n");
10229 return TreeEntry::NeedToGather;
10230 }
10231 }
10232 return TreeEntry::Vectorize;
10233 }
10234 case Instruction::Select:
10235 if (SLPReVec) {
10236 SmallPtrSet<Type *, 4> CondTypes;
10237 for (Value *V : VL) {
10238 Value *Cond;
10239 if (!match(V, m_Select(m_Value(Cond), m_Value(), m_Value())) &&
10240 !match(V, m_ZExt(m_Value(Cond))))
10241 continue;
10242 CondTypes.insert(Cond->getType());
10243 }
10244 if (CondTypes.size() > 1) {
10245 LLVM_DEBUG(
10246 dbgs()
10247 << "SLP: Gathering select with different condition types.\n");
10248 return TreeEntry::NeedToGather;
10249 }
10250 }
10251 [[fallthrough]];
10252 case Instruction::FNeg:
10253 case Instruction::Add:
10254 case Instruction::FAdd:
10255 case Instruction::Sub:
10256 case Instruction::FSub:
10257 case Instruction::Mul:
10258 case Instruction::FMul:
10259 case Instruction::UDiv:
10260 case Instruction::SDiv:
10261 case Instruction::FDiv:
10262 case Instruction::URem:
10263 case Instruction::SRem:
10264 case Instruction::FRem:
10265 case Instruction::Shl:
10266 case Instruction::LShr:
10267 case Instruction::AShr:
10268 case Instruction::And:
10269 case Instruction::Or:
10270 case Instruction::Xor:
10271 case Instruction::Freeze:
10272 if (S.getMainOp()->getType()->isFloatingPointTy() &&
10273 TTI->isFPVectorizationPotentiallyUnsafe() && any_of(VL, [](Value *V) {
10274 auto *I = dyn_cast<Instruction>(V);
10275 return I && I->isBinaryOp() && !I->isFast();
10276 }))
10277 return TreeEntry::NeedToGather;
10278 return TreeEntry::Vectorize;
10279 case Instruction::GetElementPtr: {
10280 // We don't combine GEPs with complicated (nested) indexing.
10281 for (Value *V : VL) {
10282 auto *I = dyn_cast<GetElementPtrInst>(V);
10283 if (!I)
10284 continue;
10285 if (I->getNumOperands() != 2) {
10286 LLVM_DEBUG(dbgs() << "SLP: not-vectorizable GEP (nested indexes).\n");
10287 return TreeEntry::NeedToGather;
10288 }
10289 }
10290
10291 // We can't combine several GEPs into one vector if they operate on
10292 // different types.
10293 Type *Ty0 = cast<GEPOperator>(VL0)->getSourceElementType();
10294 for (Value *V : VL) {
10295 auto *GEP = dyn_cast<GEPOperator>(V);
10296 if (!GEP)
10297 continue;
10298 Type *CurTy = GEP->getSourceElementType();
10299 if (Ty0 != CurTy) {
10300 LLVM_DEBUG(dbgs() << "SLP: not-vectorizable GEP (different types).\n");
10301 return TreeEntry::NeedToGather;
10302 }
10303 }
10304
10305 // We don't combine GEPs with non-constant indexes.
10306 Type *Ty1 = VL0->getOperand(1)->getType();
10307 for (Value *V : VL) {
10308 auto *I = dyn_cast<GetElementPtrInst>(V);
10309 if (!I)
10310 continue;
10311 auto *Op = I->getOperand(1);
10312 if ((!IsScatterVectorizeUserTE && !isa<ConstantInt>(Op)) ||
10313 (Op->getType() != Ty1 &&
10314 ((IsScatterVectorizeUserTE && !isa<ConstantInt>(Op)) ||
10315 Op->getType()->getScalarSizeInBits() >
10316 DL->getIndexSizeInBits(
10317 V->getType()->getPointerAddressSpace())))) {
10318 LLVM_DEBUG(
10319 dbgs() << "SLP: not-vectorizable GEP (non-constant indexes).\n");
10320 return TreeEntry::NeedToGather;
10321 }
10322 }
10323
10324 return TreeEntry::Vectorize;
10325 }
10326 case Instruction::Store: {
10327 // Check if the stores are consecutive or if we need to swizzle them.
10328 llvm::Type *ScalarTy = cast<StoreInst>(VL0)->getValueOperand()->getType();
10329 // Avoid types that are padded when being allocated as scalars, while
10330 // being packed together in a vector (such as i1).
10331 if (DL->getTypeSizeInBits(ScalarTy) !=
10332 DL->getTypeAllocSizeInBits(ScalarTy)) {
10333 LLVM_DEBUG(dbgs() << "SLP: Gathering stores of non-packed type.\n");
10334 return TreeEntry::NeedToGather;
10335 }
10336 // Make sure all stores in the bundle are simple - we can't vectorize
10337 // atomic or volatile stores.
10338 for (Value *V : VL) {
10339 auto *SI = cast<StoreInst>(V);
10340 if (!SI->isSimple()) {
10341 LLVM_DEBUG(dbgs() << "SLP: Gathering non-simple stores.\n");
10342 return TreeEntry::NeedToGather;
10343 }
10344 PointerOps.push_back(SI->getPointerOperand());
10345 }
10346
10347 // Check the order of pointer operands.
10348 if (llvm::sortPtrAccesses(PointerOps, ScalarTy, *DL, *SE, CurrentOrder)) {
10349 Value *Ptr0;
10350 Value *PtrN;
10351 if (CurrentOrder.empty()) {
10352 Ptr0 = PointerOps.front();
10353 PtrN = PointerOps.back();
10354 } else {
10355 Ptr0 = PointerOps[CurrentOrder.front()];
10356 PtrN = PointerOps[CurrentOrder.back()];
10357 }
10358 Align CommonAlignment = computeCommonAlignment<StoreInst>(VL);
10359 std::optional<int64_t> Dist =
10360 getPointersDiff(ScalarTy, Ptr0, ScalarTy, PtrN, *DL, *SE);
10361 // Check that the sorted pointer operands are consecutive.
10362 if (static_cast<uint64_t>(*Dist) == VL.size() - 1)
10363 return TreeEntry::Vectorize;
10364 if (EnableStridedStores &&
10365 analyzeConstantStrideCandidate(PointerOps, ScalarTy, CommonAlignment,
10366 CurrentOrder, *Dist, Ptr0, SPtrInfo))
10367 return TreeEntry::StridedVectorize;
10368 // If the stores are not consecutive but the target supports masked stores
10369 // for the widened type, lower them as a masked store.
10370 FixedVectorType *StoreVecTy = nullptr;
10371 if (EnableMaskedStores &&
10372 isMaskedStoreCompress(VL, PointerOps, CurrentOrder, *TTI, *DL, *SE,
10373 CommonAlignment, ReuseShuffleIndices,
10374 StoreVecTy)) {
10375 SPtrInfo.Ty = StoreVecTy;
10376 return TreeEntry::ExpandVectorize;
10377 }
10378 }
10379
10380 LLVM_DEBUG(dbgs() << "SLP: Non-consecutive store.\n");
10381 return TreeEntry::NeedToGather;
10382 }
10383 case Instruction::Call: {
10384 if (S.getMainOp()->getType()->isFloatingPointTy() &&
10385 TTI->isFPVectorizationPotentiallyUnsafe() && any_of(VL, [](Value *V) {
10386 auto *FPOp = dyn_cast<FPMathOperator>(V);
10387 return FPOp && !FPOp->isFast();
10388 }))
10389 return TreeEntry::NeedToGather;
10390 // Check if the calls are all to the same vectorizable intrinsic or
10391 // library function.
10392 CallInst *CI = cast<CallInst>(VL0);
10394
10395 VFShape Shape = VFShape::get(
10396 CI->getFunctionType(),
10397 ElementCount::getFixed(static_cast<unsigned int>(VL.size())),
10398 false /*HasGlobalPred*/);
10399 Function *VecFunc = VFDatabase(*CI).getVectorizedFunction(Shape);
10400
10401 if (!VecFunc && !isTriviallyVectorizable(ID)) {
10402 LLVM_DEBUG(dbgs() << "SLP: Non-vectorizable call.\n");
10403 return TreeEntry::NeedToGather;
10404 }
10405 if (isa<StructType>(CI->getType()) &&
10407 LLVM_DEBUG(dbgs() << "SLP: Struct-returning calls have non-extractvalue "
10408 "users.\n");
10409 return TreeEntry::NeedToGather;
10410 }
10411 Function *F = CI->getCalledFunction();
10412 unsigned NumArgs = CI->arg_size();
10413 SmallVector<Value *, 4> ScalarArgs(NumArgs, nullptr);
10414 for (unsigned J = 0; J != NumArgs; ++J)
10415 if (isVectorIntrinsicWithScalarOpAtArg(ID, J, TTI))
10416 ScalarArgs[J] = CI->getArgOperand(J);
10417 for (Value *V : VL) {
10418 // Skip copyables (idempotent stand-ins) and poisons.
10419 if (isa<PoisonValue>(V) || S.isCopyableElement(V))
10420 continue;
10421 CallInst *CI2 = dyn_cast<CallInst>(V);
10422 Intrinsic::ID ID2 = CI2 ? getVectorIntrinsicIDForCall(CI2, TLI)
10424 Intrinsic::ID Equivalent = isEquivalentIntrinsicID(ID, ID2);
10425 if (!CI2 ||
10426 (CI2->getCalledFunction() != F &&
10427 isEquivalentIntrinsicID(Equivalent, Intrinsic::fmuladd) ==
10429 (ID != ID2 && Equivalent == Intrinsic::not_intrinsic) ||
10430 (VecFunc &&
10431 VecFunc != VFDatabase(*CI2).getVectorizedFunction(Shape)) ||
10433 LLVM_DEBUG(dbgs() << "SLP: mismatched calls:" << *CI << "!=" << *V
10434 << "\n");
10435 return TreeEntry::NeedToGather;
10436 }
10437 // Some intrinsics have scalar arguments and should be same in order for
10438 // them to be vectorized.
10439 for (unsigned J = 0; J != NumArgs; ++J) {
10440 if (isVectorIntrinsicWithScalarOpAtArg(ID, J, TTI)) {
10441 Value *A1J = CI2->getArgOperand(J);
10442 if (ScalarArgs[J] != A1J) {
10444 << "SLP: mismatched arguments in call:" << *CI
10445 << " argument " << ScalarArgs[J] << "!=" << A1J << "\n");
10446 return TreeEntry::NeedToGather;
10447 }
10448 }
10449 }
10450 // Verify that the bundle operands are identical between the two calls.
10451 if (CI->hasOperandBundles() &&
10452 !std::equal(CI->op_begin() + CI->getBundleOperandsStartIndex(),
10453 CI->op_begin() + CI->getBundleOperandsEndIndex(),
10454 CI2->op_begin() + CI2->getBundleOperandsStartIndex())) {
10455 LLVM_DEBUG(dbgs() << "SLP: mismatched bundle operands in calls:" << *CI
10456 << "!=" << *V << '\n');
10457 return TreeEntry::NeedToGather;
10458 }
10459 }
10460 SmallVector<Type *> ArgTys =
10461 buildIntrinsicArgTypes(CI, ID, VL.size(), 0, TTI);
10462 auto *VecTy = getWidenedType(S.getMainOp()->getType(), VL.size());
10463 auto VecCallCosts =
10464 getVectorCallCosts(CI, VecTy, TTI, TLI, ArgTys, CostKind);
10465 if (!VecCallCosts.first.isValid() && !VecCallCosts.second.isValid())
10466 return TreeEntry::NeedToGather;
10467
10468 return TreeEntry::Vectorize;
10469 }
10470 case Instruction::ShuffleVector: {
10471 if (!S.isAltShuffle()) {
10472 // REVEC can support non alternate shuffle.
10474 return TreeEntry::Vectorize;
10475 // If this is not an alternate sequence of opcode like add-sub
10476 // then do not vectorize this instruction.
10477 LLVM_DEBUG(dbgs() << "SLP: ShuffleVector are not vectorized.\n");
10478 return TreeEntry::NeedToGather;
10479 }
10480
10481 return TreeEntry::Vectorize;
10482 }
10483 default:
10484 LLVM_DEBUG(dbgs() << "SLP: Gathering unknown instruction.\n");
10485 return TreeEntry::NeedToGather;
10486 }
10487}
10488
10489namespace {
10490/// Allows to correctly handle operands of the phi nodes based on the \p Main
10491/// PHINode order of incoming basic blocks/values.
10492class PHIHandler {
10493 DominatorTree &DT;
10494 PHINode *Main = nullptr;
10497
10498public:
10499 PHIHandler() = delete;
10500 PHIHandler(DominatorTree &DT, PHINode *Main, ArrayRef<Value *> Phis)
10501 : DT(DT), Main(Main), Phis(Phis),
10502 Operands(Main->getNumIncomingValues(),
10503 SmallVector<Value *>(Phis.size(), nullptr)) {}
10504 void buildOperands() {
10505 constexpr unsigned FastLimit = 4;
10506 if (Main->getNumIncomingValues() <= FastLimit) {
10507 for (unsigned I : seq<unsigned>(0, Main->getNumIncomingValues())) {
10508 BasicBlock *InBB = Main->getIncomingBlock(I);
10509 if (!DT.isReachableFromEntry(InBB)) {
10510 Operands[I].assign(Phis.size(), PoisonValue::get(Main->getType()));
10511 continue;
10512 }
10513 // Prepare the operand vector.
10514 for (auto [Idx, V] : enumerate(Phis)) {
10515 auto *P = dyn_cast<PHINode>(V);
10516 if (!P) {
10518 "Expected isa instruction or poison value.");
10519 Operands[I][Idx] = V;
10520 continue;
10521 }
10522 if (P->getIncomingBlock(I) == InBB)
10523 Operands[I][Idx] = P->getIncomingValue(I);
10524 else
10525 Operands[I][Idx] = P->getIncomingValueForBlock(InBB);
10526 }
10527 }
10528 return;
10529 }
10530 SmallMapVector<BasicBlock *, SmallVector<unsigned>, 4>
10531 Blocks;
10532 for (unsigned I : seq<unsigned>(Main->getNumIncomingValues())) {
10533 BasicBlock *InBB = Main->getIncomingBlock(I);
10534 if (!DT.isReachableFromEntry(InBB)) {
10535 Operands[I].assign(Phis.size(), PoisonValue::get(Main->getType()));
10536 continue;
10537 }
10538 Blocks.try_emplace(InBB).first->second.push_back(I);
10539 }
10540 for (auto [Idx, V] : enumerate(Phis)) {
10541 if (isa<PoisonValue>(V)) {
10542 for (unsigned I : seq<unsigned>(Main->getNumIncomingValues()))
10543 Operands[I][Idx] = V;
10544 continue;
10545 }
10546 auto *P = cast<PHINode>(V);
10547 for (unsigned I : seq<unsigned>(P->getNumIncomingValues())) {
10548 BasicBlock *InBB = P->getIncomingBlock(I);
10549 if (InBB == Main->getIncomingBlock(I)) {
10551 continue;
10552 Operands[I][Idx] = P->getIncomingValue(I);
10553 continue;
10554 }
10555 auto *It = Blocks.find(InBB);
10556 if (It == Blocks.end())
10557 continue;
10558 Operands[It->second.front()][Idx] = P->getIncomingValue(I);
10559 }
10560 }
10561 for (const auto &P : Blocks) {
10562 ArrayRef<unsigned> IncomingValues = P.second;
10563 if (IncomingValues.size() <= 1)
10564 continue;
10565 unsigned BasicI = IncomingValues.consume_front();
10566 for (unsigned I : IncomingValues) {
10568 [&](const auto &Data) {
10569 return !Data.value() ||
10570 Data.value() == Operands[BasicI][Data.index()];
10571 }) &&
10572 "Expected empty operands list.");
10573 Operands[I] = Operands[BasicI];
10574 }
10575 }
10576 }
10577 ArrayRef<Value *> getOperands(unsigned I) const { return Operands[I]; }
10578};
10579} // namespace
10580
10581/// Returns main/alternate instructions for the given \p VL. Unlike
10582/// getSameOpcode supports non-compatible instructions for better SplitVectorize
10583/// node support.
10584/// \returns first main/alt instructions, if only poisons and instruction with
10585/// only 2 opcodes exists. Returns pair of nullptr otherwise.
10586static std::pair<Instruction *, Instruction *>
10588 Instruction *MainOp = nullptr;
10589 Instruction *AltOp = nullptr;
10590 for (Value *V : VL) {
10591 if (isa<PoisonValue>(V))
10592 continue;
10593 auto *I = dyn_cast<Instruction>(V);
10594 if (!I)
10595 return {};
10596 if (!MainOp) {
10597 MainOp = I;
10598 continue;
10599 }
10600 if (MainOp->getOpcode() == I->getOpcode()) {
10601 if (I->getParent() != MainOp->getParent())
10602 return {};
10603 continue;
10604 }
10605 if (!AltOp) {
10606 AltOp = I;
10607 continue;
10608 }
10609 if (AltOp->getOpcode() == I->getOpcode()) {
10610 if (I->getParent() != AltOp->getParent())
10611 return {};
10612 continue;
10613 }
10614 return {};
10615 }
10616 if (!AltOp)
10617 return {};
10618 assert(MainOp && AltOp && MainOp->getOpcode() != AltOp->getOpcode() &&
10619 "Expected different main and alt instructions.");
10620 return std::make_pair(MainOp, AltOp);
10621}
10622
10623/// Checks that every instruction appears once in the list and if not, packs
10624/// them, building \p ReuseShuffleIndices mask and mutating \p VL. The list of
10625/// unique scalars is extended by poison values to the whole register size.
10626///
10627/// \returns false if \p VL could not be uniquified, in which case \p VL is
10628/// unchanged and \p ReuseShuffleIndices is empty.
10630 SmallVectorImpl<int> &ReuseShuffleIndices,
10631 const TargetTransformInfo &TTI,
10632 const TargetLibraryInfo &TLI,
10633 const InstructionsState &S,
10634 const BoUpSLP::EdgeInfo &UserTreeIdx,
10635 const BoUpSLP &R, bool BuildGatherOnly = true) {
10636 // TODO: Reordering of struct types is not supported.
10638 LLVM_DEBUG(dbgs() << "SLP: struct type in bundle.\n");
10639 ReuseShuffleIndices.clear();
10640 return true;
10641 }
10642 // Check that every instruction appears once in this bundle.
10643 SmallVector<Value *> UniqueValues;
10644 SmallDenseMap<Value *, unsigned, 16> UniquePositions(VL.size());
10645 for (Value *V : VL) {
10646 if (isConstant(V)) {
10647 // Constants are always considered distinct, even if the same constant
10648 // appears multiple times in VL.
10649 ReuseShuffleIndices.emplace_back(
10650 isa<PoisonValue>(V) ? PoisonMaskElem : UniqueValues.size());
10651 UniqueValues.emplace_back(V);
10652 continue;
10653 }
10654 auto Res = UniquePositions.try_emplace(V, UniqueValues.size());
10655 ReuseShuffleIndices.emplace_back(Res.first->second);
10656 if (Res.second)
10657 UniqueValues.emplace_back(V);
10658 }
10659
10660 // Check if we need to schedule the scalars. If no, can keep original scalars
10661 // and avoid extra shuffles.
10662 bool RequireScheduling = S && S.getOpcode() != Instruction::PHI &&
10665 !doesNotNeedToSchedule(UniqueValues));
10666 // Compute this flag BEFORE the tail-poison erase below - it must reflect
10667 // the state of the original VL (for the InsertsCost call), not the
10668 // potentially-shrunk UniqueValues.
10669 bool AreAllValuesNonConst = UniquePositions.size() == UniqueValues.size();
10670 // Drop tail poisons, if the values can be vectorized.
10671 if (RequireScheduling) {
10672 const auto EndIt =
10673 find_if_not(make_range(UniqueValues.rbegin(), UniqueValues.rend()),
10675 assert(EndIt != UniqueValues.rend() && "Expected at least one non-poison.");
10676 UniqueValues.erase(EndIt.base(), UniqueValues.end());
10677 }
10678 unsigned NumUniqueScalarValues = UniqueValues.size();
10679 if (NumUniqueScalarValues == VL.size()) {
10680 ReuseShuffleIndices.clear();
10681 return true;
10682 }
10683
10684 // For VL=4 with 3 unique values: keep originals. A <3 x T> vector is
10685 // always widened to <4 x T> on hardware, so the packing just adds an
10686 // extra expand shuffle. Does not apply to loads (a <3 x T> load is a
10687 // single memory access) or PHIs (benefit from compact packing in loops).
10688 constexpr unsigned SmallVecWidth = 4;
10689 constexpr unsigned SmallVecUniqueThreshold = 3;
10690 if (VL.size() == SmallVecWidth &&
10691 NumUniqueScalarValues == SmallVecUniqueThreshold && !BuildGatherOnly &&
10692 !(S && (S.getOpcode() == Instruction::Load ||
10693 S.getOpcode() == Instruction::PHI))) {
10694 // Keep originals with identity reuse - no packing, no extra shuffle.
10695 ReuseShuffleIndices.clear();
10696 return true;
10697 }
10698
10699 // Checks if unique inserts + shuffle is more profitable than just inserts or
10700 // vectorized values.
10701 auto EstimatePackPlusShuffleVsInserts = [&]() {
10702 // Single instruction/argument insert - no shuffle.
10703 if (UniquePositions.size() == 1 &&
10704 (NumUniqueScalarValues == 1 ||
10706 return std::make_pair(false, false);
10707 // For large gathers with power-of-2 VL where packing would produce
10708 // non-power-of-2, reject if most scalars are constants - the packing
10709 // overhead (non-power-of-2 split + shuffles) outweighs the benefit.
10710 constexpr unsigned MinVLForConstGatherCheck = 4;
10711 if (BuildGatherOnly && VL.size() > MinVLForConstGatherCheck &&
10712 has_single_bit(static_cast<unsigned>(VL.size())) &&
10713 !has_single_bit(NumUniqueScalarValues) &&
10714 UniquePositions.size() * 2 < NumUniqueScalarValues)
10715 return std::make_pair(false, false);
10716 auto CheckLoads = [&](ArrayRef<Value *> Loads, bool IncludeGather) {
10717 assert(S && S.getOpcode() == Instruction::Load && "Expected load.");
10718 BoUpSLP::OrdersType Order;
10719 SmallVector<Value *> PointerOps;
10720 BoUpSLP::StridedPtrInfo SPtrInfo;
10721 BoUpSLP::LoadsState Res = R.canVectorizeLoads(Loads, S.getMainOp(), Order,
10722 PointerOps, SPtrInfo);
10723 return (IncludeGather && Res == BoUpSLP::LoadsState::Gather) ||
10728 };
10729 // Operand of the root tree entry on the vectorize path: always pack the
10730 // scalars (PackProfitable=true). Choose between keeping the original VL
10731 // and packing the unique values:
10732 // - For loads, prefer the originals only when both the deduplicated and
10733 // the full sequence can be vectorized non-Gather, or when the reuse
10734 // mask is the identity (the shuffle is free).
10735 // - For everything else (including !S, where RequireScheduling is forced
10736 // to false above), keep originals iff no scheduling is required.
10737 bool IsRootOperand =
10738 UserTreeIdx.UserTE && UserTreeIdx.UserTE->Idx == 0 && !BuildGatherOnly;
10739 if (IsRootOperand) {
10740 if (S && S.getOpcode() == Instruction::Load) {
10741 bool UseOrig = (CheckLoads(UniqueValues, /*IncludeGather=*/true) &&
10742 CheckLoads(VL, /*IncludeGather=*/false)) ||
10744 ReuseShuffleIndices, ReuseShuffleIndices.size());
10745 return std::make_pair(true, UseOrig);
10746 }
10747 return std::make_pair(true, !RequireScheduling);
10748 }
10749 APInt DemandedElts = APInt::getZero(VL.size());
10750 for (auto [Idx, Val] : enumerate(ReuseShuffleIndices))
10751 if (Val != PoisonMaskElem && UniquePositions.contains(UniqueValues[Val]))
10752 DemandedElts.setBit(Idx);
10753 Type *ScalarTy = ::getValueType(UniqueValues.front(), SLPReVec);
10754 auto *VecTy = cast<VectorType>(getWidenedType(ScalarTy, VL.size()));
10755 auto *UniquesVecTy =
10756 cast<VectorType>(getWidenedType(ScalarTy, NumUniqueScalarValues));
10757 const unsigned NumParts = ::getNumberOfParts(TTI, VecTy, ScalarTy);
10758 const unsigned UniquesNumParts =
10759 ::getNumberOfParts(TTI, UniquesVecTy, ScalarTy);
10760 // No need to schedule scalars and only single register used? Use original
10761 // scalars, do not pack.
10762 if (!RequireScheduling) {
10763 if (VL.size() / NumUniqueScalarValues == 1 &&
10764 (NumParts <= 1 || UniquesNumParts >= NumParts))
10765 return std::make_pair(true, true);
10766 // For PHI operands, prefer packing with reuse shuffle - the PHI
10767 // carries the vector through the loop cheaply.
10768 if (S && S.getOpcode() == Instruction::PHI && NumUniqueScalarValues > 1 &&
10769 UniquesNumParts <= NumParts)
10770 return std::make_pair(true, false);
10771 }
10772 const TTI::TargetCostKind CostKind = R.getCostKind();
10773 InstructionCost ReusesCost = getShuffleCost(
10775 NumUniqueScalarValues > VL.size() / 2 ? ArrayRef<int>()
10776 : ArrayRef(ReuseShuffleIndices),
10777 /*Index=*/0, UniquesVecTy);
10778 // For vectorizable (non-gather) nodes with low duplication, prefer keeping
10779 // the original values over packing uniques + reshuffling:
10780 // - A single duplicate (non-load) adds negligible overhead.
10781 // - When most values are already unique (>50%), or exactly half are unique
10782 // for some ops (GEPs, non-alt-shuffle casts), the reshuffle cost may
10783 // exceed the savings from a smaller packed vector - check against a
10784 // per-register-part threshold (stricter for wider vectors).
10785 if (S && !BuildGatherOnly) {
10786 bool HasOneDup = S.getOpcode() != Instruction::Load &&
10787 NumUniqueScalarValues + 1 == VL.size();
10788 bool MostlyUnique = NumUniqueScalarValues * 2 > VL.size();
10789 bool IsHalfUniqueValues =
10790 NumUniqueScalarValues * 2 == VL.size() &&
10791 (S.getOpcode() == Instruction::GetElementPtr ||
10792 (isa<CastInst>(S.getMainOp()) && !S.isAltShuffle()));
10794 NumParts * (VL.size() > SmallVecWidth ? 1 : 2);
10795 if (HasOneDup ||
10796 ((MostlyUnique || IsHalfUniqueValues) && ReusesCost > CostThreshold))
10797 return std::make_pair(true, true);
10798 }
10799 // For loads, check if either the deduplicated or the full (with
10800 // duplicates) set can be scatter/compress-vectorized. Prefer the unique
10801 // loads (pack + reshuffle) when possible, otherwise use the originals.
10802 if (S && S.getOpcode() == Instruction::Load) {
10803 bool UniquesVectorized =
10804 CheckLoads(UniqueValues, /*IncludeGather=*/false);
10805 if (UniquesVectorized || CheckLoads(VL, /*IncludeGather=*/false))
10806 return std::make_pair(true, !UniquesVectorized);
10807 }
10808 bool CanSkipBVCost =
10809 (!BuildGatherOnly && !RequireScheduling) || R.hasSameNode(S, VL);
10810 InstructionCost InsertsCost =
10811 CanSkipBVCost
10813 : getScalarizationOverhead(TTI, SLPReVec, ScalarTy, VecTy,
10814 DemandedElts,
10815 /*Insert=*/true, /*Extract=*/false,
10816 CostKind, AreAllValuesNonConst, VL);
10817 APInt UniquesDemandedElts = APInt::getAllOnes(NumUniqueScalarValues);
10818 for (const auto [Idx, V] : enumerate(UniqueValues))
10819 if (isConstant(V))
10820 UniquesDemandedElts.clearBit(Idx);
10821 InstructionCost UniquesCost =
10822 CanSkipBVCost
10824 : getScalarizationOverhead(TTI, SLPReVec, ScalarTy, UniquesVecTy,
10825 UniquesDemandedElts, /*Insert=*/true,
10826 /*Extract=*/false, CostKind,
10827 AreAllValuesNonConst, UniqueValues);
10828 UniquesCost += ReusesCost;
10829 if (UniquesCost <= InsertsCost) {
10830 // Packing to a vector that occupies the same register width as the
10831 // original only adds the reshuffle cost; keep the originals. Loads may
10832 // instead benefit from a wider contiguous load.
10833 if (S && S.getOpcode() != Instruction::Load) {
10834 unsigned EltBits =
10835 S.getMainOp()->getDataLayout().getTypeSizeInBits(ScalarTy);
10836 unsigned MinVF = R.getMinVF(EltBits);
10837 auto RegWidth = [&](unsigned N) {
10838 return std::max(
10839 getFullVectorNumberOfElements(TTI, ScalarTy, N, SLPReVec), MinVF);
10840 };
10841 // Keeping the originals just moves the reshuffle to the operand
10842 // columns with duplicates; keep them only if at most one column has
10843 // duplicates, so the total number of reshuffles does not grow.
10844 auto HasExtraReshuffle = [&]() {
10845 if (BuildGatherOnly)
10846 return false;
10847 unsigned NumDupColumns = 0;
10848 for (unsigned OpIdx :
10851 for (Value *V : VL) {
10852 if (isa<PoisonValue>(V))
10853 continue;
10854 Value *Op;
10855 if (S.isCopyableElement(V)) {
10856 if (OpIdx != 0)
10857 continue;
10858 Op = V;
10859 } else {
10860 auto *I = dyn_cast<Instruction>(V);
10861 if (!I || OpIdx >= I->getNumOperands())
10862 continue;
10863 Op = I->getOperand(OpIdx);
10864 }
10865 if (!isConstant(Op) && !UniqueOps.insert(Op).second) {
10866 ++NumDupColumns;
10867 break;
10868 }
10869 }
10870 if (NumDupColumns > 1)
10871 return true;
10872 }
10873 return false;
10874 };
10875 return std::make_pair(true, RegWidth(NumUniqueScalarValues) >=
10876 RegWidth(VL.size()) &&
10877 !HasExtraReshuffle());
10878 }
10879 return std::make_pair(true, false);
10880 }
10881 InstructionCost CostDiff = UniquesCost - InsertsCost;
10882 if (CostDiff < TTI::TCC_Expensive ||
10883 (R.getTreeSize() == 0 && R.isReductionTree() &&
10884 CostDiff == TTI::TCC_Expensive))
10885 return std::make_pair(S && (!S.isAltShuffle() || !BuildGatherOnly),
10886 false);
10887 // Otherwise, use original values, if values do not require scheduling and
10888 // pass still try to vectorize them.
10889 bool KeepOriginal = !BuildGatherOnly && !RequireScheduling;
10890 return std::make_pair(KeepOriginal, KeepOriginal);
10891 };
10892
10893 const auto [PackProfitable, UseOriginal] = EstimatePackPlusShuffleVsInserts();
10894
10895 if (PackProfitable) {
10896 if (UseOriginal) {
10897 // Prefer original scalars - avoid shuffling.
10898 ReuseShuffleIndices.clear();
10899 } else {
10900 // Better to use uniques + reshuffle.
10901 LLVM_DEBUG(dbgs() << "SLP: Shuffle for reused scalars.\n");
10902 VL = std::move(UniqueValues);
10903 }
10904 return true;
10905 }
10906
10907 // Buildvector/gather of the original scalars.
10908 LLVM_DEBUG(dbgs() << "SLP: Scalar used twice in bundle.\n");
10909 ReuseShuffleIndices.clear();
10910 return false;
10911}
10912
10914 const InstructionsState &LocalState,
10917 OrdersType &ReorderIndices) const {
10918 constexpr unsigned SmallNodeSize = 4;
10919 if (VL.size() <= SmallNodeSize || TTI->preferAlternateOpcodeVectorization() ||
10921 return false;
10922
10923 // Check if this is a duplicate of another split entry.
10924 LLVM_DEBUG(dbgs() << "SLP: \tChecking bundle: " << *LocalState.getMainOp()
10925 << ".\n");
10926 for (TreeEntry *E : getSplitTreeEntries(LocalState.getMainOp())) {
10927 if (E->isSame(VL)) {
10928 LLVM_DEBUG(dbgs() << "SLP: Perfect diamond merge at "
10929 << *LocalState.getMainOp() << ".\n");
10930 return false;
10931 }
10933 if (all_of(VL, [&](Value *V) {
10934 return isa<PoisonValue>(V) || Values.contains(V);
10935 })) {
10936 LLVM_DEBUG(dbgs() << "SLP: Gathering due to full overlap.\n");
10937 return false;
10938 }
10939 }
10940
10941 ReorderIndices.assign(VL.size(), VL.size());
10942 SmallBitVector Op1Indices(VL.size());
10943 for (auto [Idx, V] : enumerate(VL)) {
10944 auto *I = dyn_cast<Instruction>(V);
10945 if (!I) {
10946 Op1.push_back(V);
10947 Op1Indices.set(Idx);
10948 continue;
10949 }
10950 if ((LocalState.getAltOpcode() != LocalState.getOpcode() &&
10951 isMainInstruction(I, LocalState.getMainOp(), LocalState.getAltOp(),
10952 *TLI)) ||
10953 (LocalState.getAltOpcode() == LocalState.getOpcode() &&
10954 !isAlternateInstruction(I, LocalState.getMainOp(),
10955 LocalState.getAltOp(), *TLI))) {
10956 Op1.push_back(V);
10957 Op1Indices.set(Idx);
10958 continue;
10959 }
10960 Op2.push_back(V);
10961 }
10962 Type *ScalarTy = getValueType(VL.front(), SLPReVec);
10963 auto *VecTy = cast<VectorType>(getWidenedType(ScalarTy, VL.size()));
10964 unsigned Opcode0 = LocalState.getOpcode();
10965 unsigned Opcode1 = LocalState.getAltOpcode();
10966 SmallBitVector OpcodeMask(getAltInstrMask(VL, ScalarTy, Opcode0, Opcode1));
10967 // Enable split node, only if all nodes do not form legal alternate
10968 // instruction (like X86 addsub).
10971 if (UOp1.size() <= 1 || UOp2.size() <= 1 ||
10972 TTI->isLegalAltInstr(VecTy, Opcode0, Opcode1, OpcodeMask))
10973 return false;
10974 unsigned Op1Cnt = 0, Op2Cnt = Op1.size();
10975 for (unsigned Idx : seq<unsigned>(VL.size())) {
10976 if (Op1Indices.test(Idx)) {
10977 ReorderIndices[Op1Cnt] = Idx;
10978 ++Op1Cnt;
10979 } else {
10980 ReorderIndices[Op2Cnt] = Idx;
10981 ++Op2Cnt;
10982 }
10983 }
10984 if (isIdentityOrder(ReorderIndices))
10985 ReorderIndices.clear();
10986 // When VL fills a power-of-2 register but the split halves do not, the
10987 // reorder shuffle makes the split unprofitable - reject.
10988 else if (hasFullVectorsOrPowerOf2(*TTI, Op1.front()->getType(), VL.size(),
10989 SLPReVec) &&
10990 (!hasFullVectorsOrPowerOf2(*TTI, Op1.front()->getType(), Op1.size(),
10991 SLPReVec) ||
10992 !hasFullVectorsOrPowerOf2(*TTI, Op2.front()->getType(), Op2.size(),
10993 SLPReVec)))
10994 return false;
10995 SmallVector<int> Mask;
10996 if (!ReorderIndices.empty())
10997 inversePermutation(ReorderIndices, Mask);
10998 unsigned NumParts = TTI->getNumberOfParts(VecTy);
10999 auto *Op1VecTy = cast<VectorType>(getWidenedType(ScalarTy, Op1.size()));
11000 auto *Op2VecTy = cast<VectorType>(getWidenedType(ScalarTy, Op2.size()));
11001 // Check non-profitable single register ops, which better to be represented
11002 // as alternate ops.
11003 if (NumParts >= VL.size())
11004 return false;
11005 InstructionCost InsertCost = getShuffleCost(
11006 *TTI, TTI::SK_InsertSubvector, VecTy, CostKind, {}, Op1.size(), Op2VecTy);
11007 auto *SubVecTy = cast<VectorType>(
11008 getWidenedType(ScalarTy, std::max(Op1.size(), Op2.size())));
11009 InstructionCost NewShuffleCost =
11010 getShuffleCost(*TTI, TTI::SK_PermuteTwoSrc, SubVecTy, CostKind, Mask);
11011 if (!LocalState.isCmpOp() && NumParts <= 1 &&
11012 (Mask.empty() || InsertCost >= NewShuffleCost))
11013 return false;
11014 if ((LocalState.getMainOp()->isBinaryOp() &&
11015 LocalState.getAltOp()->isBinaryOp() &&
11016 (LocalState.isShiftOp() || LocalState.isBitwiseLogicOp() ||
11017 LocalState.isAddSubLikeOp() || LocalState.isMulDivLikeOp())) ||
11018 (LocalState.getMainOp()->isCast() && LocalState.getAltOp()->isCast()) ||
11019 (LocalState.getMainOp()->isUnaryOp() &&
11020 LocalState.getAltOp()->isUnaryOp())) {
11021 InstructionCost OriginalVecOpsCost =
11022 TTI->getArithmeticInstrCost(Opcode0, VecTy, CostKind) +
11023 TTI->getArithmeticInstrCost(Opcode1, VecTy, CostKind);
11024 SmallVector<int> OriginalMask(VL.size(), PoisonMaskElem);
11025 for (unsigned Idx : seq<unsigned>(VL.size())) {
11026 if (isa<PoisonValue>(VL[Idx]))
11027 continue;
11028 OriginalMask[Idx] = Idx + (Op1Indices.test(Idx) ? 0 : VL.size());
11029 }
11030 InstructionCost OriginalCost =
11031 OriginalVecOpsCost + getShuffleCost(*TTI, TTI::SK_PermuteTwoSrc, VecTy,
11032 CostKind, OriginalMask);
11033 InstructionCost NewVecOpsCost =
11034 TTI->getArithmeticInstrCost(Opcode0, Op1VecTy, CostKind) +
11035 TTI->getArithmeticInstrCost(Opcode1, Op2VecTy, CostKind);
11036 InstructionCost NewCost =
11037 NewVecOpsCost + InsertCost +
11038 (!VectorizableTree.empty() && getRootNode().hasState() &&
11039 getRootNode().getOpcode() == Instruction::Store
11040 ? NewShuffleCost
11041 : 0);
11042 // If not profitable to split - exit.
11043 if (NewCost >= OriginalCost)
11044 return false;
11045 }
11046 return true;
11047}
11048
11049namespace {
11050/// Class accepts incoming list of values, checks if it is able to model
11051/// "copyable" values as compatible operations, and generates the list of values
11052/// for scheduling and list of operands doe the new nodes.
11053class InstructionsCompatibilityAnalysis {
11054 DominatorTree &DT;
11055 const DataLayout &DL;
11056 const TargetTransformInfo &TTI;
11057 const TargetLibraryInfo &TLI;
11058 unsigned MainOpcode = 0;
11059 Instruction *MainOp = nullptr;
11060 /// Whether every copyable in the current value list is an absorbable
11061 /// single-use fmul/fadd. Computed once per buildInstructionsState call.
11062 bool AbsorbCopyableFMulOrFAdds = false;
11063
11064 /// Checks if the opcode is supported as the main opcode for copyable
11065 /// elements.
11066 static bool isSupportedOpcode(const unsigned Opcode) {
11067 return Opcode == Instruction::Add || Opcode == Instruction::Sub ||
11068 Opcode == Instruction::Mul || Opcode == Instruction::AShr ||
11069 Opcode == Instruction::LShr || Opcode == Instruction::Shl ||
11070 Opcode == Instruction::SDiv || Opcode == Instruction::UDiv ||
11071 Opcode == Instruction::And || Opcode == Instruction::Or ||
11072 Opcode == Instruction::Xor || Opcode == Instruction::FAdd ||
11073 Opcode == Instruction::FSub || Opcode == Instruction::FMul ||
11074 Opcode == Instruction::FDiv;
11075 }
11076
11077 /// Checks if \p I can be the main op for copyable analysis: a supported
11078 /// binary operator, fmuladd, or an integer min/max intrinsic, the only
11079 /// call with a well-defined idempotent value (FP min/max lacks one because of
11080 /// NaNs). An extractelement with constant index from a fixed vector is also
11081 /// supported: the matching lanes reuse the source vector and the copyable
11082 /// lanes are inserted into it.
11083 static bool isSupportedMainOp(Instruction *I) {
11084 return isSupportedOpcode(I->getOpcode()) || isa<MinMaxIntrinsic>(I) ||
11087 isa<FixedVectorType>(I->getOperand(0)->getType()));
11088 }
11089
11090 /// Identifies the best candidate value, which represents main opcode
11091 /// operation.
11092 /// Currently the best candidate is the Add instruction with the parent
11093 /// block with the highest DFS incoming number (block, that dominates other).
11094 void findAndSetMainInstruction(ArrayRef<Value *> VL, const BoUpSLP &R) {
11095 BasicBlock *Parent = nullptr;
11096 // Checks if the instruction has supported opcode.
11097 auto IsSupportedInstruction = [&](Instruction *I, bool AnyUndef) {
11098 if (AnyUndef && (I->isIntDivRem() || I->isFPDivRem() || isa<CallInst>(I)))
11099 return false;
11100 return I && isSupportedMainOp(I) &&
11101 (!doesNotNeedToBeScheduled(I) || !R.isVectorized(I));
11102 };
11103 // Exclude operands instructions immediately to improve compile time, it
11104 // will be unable to schedule anyway.
11105 SmallDenseSet<Value *, 8> Operands;
11106 SmallMapVector<unsigned, SmallVector<Instruction *>, 4> Candidates;
11107 bool AnyUndef = false;
11108 for (Value *V : VL) {
11109 auto *I = dyn_cast<Instruction>(V);
11110 if (!I) {
11111 AnyUndef |= isa<UndefValue>(V);
11112 continue;
11113 }
11114 if (!DT.isReachableFromEntry(I->getParent()))
11115 continue;
11116 if (Candidates.empty()) {
11117 Candidates.try_emplace(I->getOpcode()).first->second.push_back(I);
11118 Parent = I->getParent();
11119 Operands.insert(I->op_begin(), I->op_end());
11120 continue;
11121 }
11122 if (Parent == I->getParent()) {
11123 Candidates.try_emplace(I->getOpcode()).first->second.push_back(I);
11124 Operands.insert(I->op_begin(), I->op_end());
11125 continue;
11126 }
11127 auto *NodeA = DT.getNode(Parent);
11128 auto *NodeB = DT.getNode(I->getParent());
11129 assert(NodeA && "Should only process reachable instructions");
11130 assert(NodeB && "Should only process reachable instructions");
11131 assert((NodeA == NodeB) ==
11132 (NodeA->getDFSNumIn() == NodeB->getDFSNumIn()) &&
11133 "Different nodes should have different DFS numbers");
11134 if (NodeA->getDFSNumIn() < NodeB->getDFSNumIn()) {
11135 Candidates.clear();
11136 Candidates.try_emplace(I->getOpcode()).first->second.push_back(I);
11137 Parent = I->getParent();
11138 Operands.clear();
11139 Operands.insert(I->op_begin(), I->op_end());
11140 }
11141 }
11142 unsigned BestOpcodeNum = 0;
11143 MainOp = nullptr;
11144 bool UsedOutside = false;
11145 for (const auto &P : Candidates) {
11146 bool PUsedOutside = all_of(P.second, isUsedOutsideBlock);
11147 if (UsedOutside && !PUsedOutside)
11148 continue;
11149 if (!UsedOutside && PUsedOutside)
11150 BestOpcodeNum = 0;
11151 if (P.second.size() < BestOpcodeNum)
11152 continue;
11153 // If have inner dependencies - skip.
11154 if (!PUsedOutside && any_of(P.second, [&](Instruction *I) {
11155 return Operands.contains(I);
11156 }))
11157 continue;
11158 // On a tie, keep the outer binary op as MainOp rather than replacing it
11159 // with an inner op that appears as its direct operand. For example, in
11160 // (2.0f * A) + B the fadd and fmul each appear once in VL; without this
11161 // check the fmul could win and prevent vectorization of the fadd pair.
11162 if (P.second.size() == BestOpcodeNum) {
11163 auto *I = P.second.front();
11164 if (auto *MainBO = dyn_cast<BinaryOperator>(MainOp)) {
11165 auto *MainBOOp0 = dyn_cast<Instruction>(MainBO->getOperand(0));
11166 auto *MainBOOp1 = dyn_cast<Instruction>(MainBO->getOperand(1));
11167 if (MainBOOp0 && MainBOOp0->getOpcode() == I->getOpcode() &&
11168 MainBOOp0->getParent() == I->getParent())
11169 continue;
11170 if (MainBOOp1 && MainBOOp1->getOpcode() == I->getOpcode() &&
11171 MainBOOp1->getParent() == I->getParent())
11172 continue;
11173 }
11174 // Keep fmuladd over fmul/fadd on a tie only when every copyable is
11175 // an absorbed fmul/fadd.
11177 (I->getOpcode() == Instruction::FMul ||
11178 I->getOpcode() == Instruction::FAdd) &&
11179 AbsorbCopyableFMulOrFAdds)
11180 continue;
11181 // Same check when fmuladd replaces fmul/fadd on a tie.
11182 if ((MainOp->getOpcode() == Instruction::FMul ||
11183 MainOp->getOpcode() == Instruction::FAdd) &&
11185 !AbsorbCopyableFMulOrFAdds)
11186 continue;
11187 }
11188 UsedOutside = PUsedOutside;
11189 for (Instruction *I : P.second) {
11190 if (IsSupportedInstruction(I, AnyUndef)) {
11191 MainOp = I;
11192 BestOpcodeNum = P.second.size();
11193 break;
11194 }
11195 }
11196 }
11197 if (MainOp) {
11198 // Do not match, if any copyable is a terminator from the same block as
11199 // the main operation.
11200 if (any_of(VL, [&](Value *V) {
11201 auto *I = dyn_cast<Instruction>(V);
11202 return I && I->getParent() == MainOp->getParent() &&
11203 I->isTerminator();
11204 })) {
11205 MainOp = nullptr;
11206 return;
11207 }
11208 MainOpcode = MainOp->getOpcode();
11209 }
11210 }
11211
11212 /// Returns the idempotent value for MainOp. For Add, returns 0. For Or, it
11213 /// should choose between false and the operand itself, since V or V == V.
11214 /// For the min/max intrinsics, returns the corresponding limit value (e.g. 0
11215 /// for umax, since umax(V, 0) == V).
11216 Value *selectBestIdempotentValue() const {
11217 assert(isSupportedMainOp(MainOp) && "Unsupported opcode");
11218 return ConstantExpr::getIdentity(MainOp, MainOp->getType(),
11219 !MainOp->isCommutative());
11220 }
11221
11222 /// Returns the value and operands for the \p V, considering if it is original
11223 /// instruction and its actual operands should be returned, or it is a
11224 /// copyable element and its should be represented as idempotent instruction.
11225 SmallVector<Value *> getOperands(const InstructionsState &S, Value *V) const {
11226 if (isa<PoisonValue>(V))
11227 return {V, V};
11228 if (!S.isCopyableElement(V))
11229 return convertTo(cast<Instruction>(V), S).second;
11231 Type *Ty = MainOp->getType();
11234 auto *I = cast<Instruction>(V);
11235 // fmuladd(a, b, -0.0) == fmul a, b.
11236 if (I->getOpcode() == Instruction::FMul)
11237 return {I->getOperand(0), I->getOperand(1),
11239 // fmuladd(1.0, a, b) == fadd a, b.
11240 return {ConstantFP::get(Ty, 1.0), I->getOperand(0), I->getOperand(1)};
11241 }
11242 // fmuladd(V, 1.0, -0.0) == V.
11243 if (S.getCopyableOpIdx() == 0)
11244 return {V, ConstantFP::get(Ty, 1.0), ConstantFP::getNegativeZero(Ty)};
11245 // fmuladd(0.0, -0.0, V) == V.
11247 }
11248 assert(isSupportedMainOp(MainOp) && "Unsupported opcode");
11249 return {V, selectBestIdempotentValue()};
11250 }
11251
11252 /// Builds operands for the original instructions.
11253 void
11254 buildOriginalOperands(const InstructionsState &S, ArrayRef<Value *> VL,
11255 SmallVectorImpl<BoUpSLP::ValueList> &Operands) const {
11256
11257 unsigned ShuffleOrOp =
11258 S.isAltShuffle() ? (unsigned)Instruction::ShuffleVector : S.getOpcode();
11259 Instruction *VL0 = S.getMainOp();
11260
11261 switch (ShuffleOrOp) {
11262 case Instruction::PHI: {
11263 auto *PH = cast<PHINode>(VL0);
11264
11265 // Keeps the reordered operands to avoid code duplication.
11266 PHIHandler Handler(DT, PH, VL);
11267 Handler.buildOperands();
11268 Operands.assign(PH->getNumOperands(), {});
11269 for (unsigned I : seq<unsigned>(PH->getNumOperands()))
11270 Operands[I].assign(Handler.getOperands(I).begin(),
11271 Handler.getOperands(I).end());
11272 return;
11273 }
11274 case Instruction::ExtractValue: {
11275 SmallVector<unsigned> Indices;
11277 if (checkEVsForVecCalls(VL, S, TLI, Indices, Calls)) {
11278 Operands.assign(1, {});
11279 Operands[0].swap(Calls);
11280 return;
11281 }
11282 [[fallthrough]];
11283 }
11284 case Instruction::ExtractElement:
11285 // This is a special case, as it does not gather, but at the same time
11286 // we are not extending buildTree_rec() towards the operands.
11287 Operands.assign(1, {VL.size(), VL0->getOperand(0)});
11288 return;
11289 case Instruction::InsertValue:
11290 case Instruction::InsertElement:
11291 Operands.assign(2, {VL.size(), nullptr});
11292 for (auto [Idx, V] : enumerate(VL)) {
11293 auto *IE = cast<Instruction>(V);
11294 for (auto [OpIdx, Ops] : enumerate(Operands))
11295 Ops[Idx] = IE->getOperand(OpIdx);
11296 }
11297 return;
11298 case Instruction::Load:
11299 Operands.assign(
11300 1, {VL.size(),
11301 PoisonValue::get(cast<LoadInst>(VL0)->getPointerOperandType())});
11302 for (auto [V, Op] : zip(VL, Operands.back())) {
11303 auto *LI = dyn_cast<LoadInst>(V);
11304 if (!LI)
11305 continue;
11306 Op = LI->getPointerOperand();
11307 }
11308 return;
11309 case Instruction::ZExt:
11310 case Instruction::SExt:
11311 case Instruction::FPToUI:
11312 case Instruction::FPToSI:
11313 case Instruction::FPExt:
11314 case Instruction::PtrToInt:
11315 case Instruction::PtrToAddr:
11316 case Instruction::IntToPtr:
11317 case Instruction::SIToFP:
11318 case Instruction::UIToFP:
11319 case Instruction::Trunc:
11320 case Instruction::FPTrunc:
11321 case Instruction::BitCast:
11322 case Instruction::ICmp:
11323 case Instruction::FCmp:
11324 case Instruction::FNeg:
11325 case Instruction::Add:
11326 case Instruction::FAdd:
11327 case Instruction::Sub:
11328 case Instruction::FSub:
11329 case Instruction::Mul:
11330 case Instruction::FMul:
11331 case Instruction::UDiv:
11332 case Instruction::SDiv:
11333 case Instruction::FDiv:
11334 case Instruction::URem:
11335 case Instruction::SRem:
11336 case Instruction::FRem:
11337 case Instruction::Shl:
11338 case Instruction::LShr:
11339 case Instruction::AShr:
11340 case Instruction::And:
11341 case Instruction::Or:
11342 case Instruction::Xor:
11343 case Instruction::Freeze:
11344 case Instruction::Store:
11345 case Instruction::ShuffleVector:
11346 Operands.assign(VL0->getNumOperands(), {VL.size(), nullptr});
11347 for (auto [Idx, V] : enumerate(VL)) {
11348 auto *I = dyn_cast<Instruction>(V);
11349 if (!I) {
11350 for (auto [OpIdx, Ops] : enumerate(Operands))
11351 Ops[Idx] = PoisonValue::get(VL0->getOperand(OpIdx)->getType());
11352 continue;
11353 }
11354 auto [Op, ConvertedOps] = convertTo(I, S);
11355 for (auto [OpIdx, Ops] : enumerate(Operands))
11356 Ops[Idx] = ConvertedOps[OpIdx];
11357 }
11358 return;
11359 case Instruction::Select:
11360 Operands.assign(VL0->getNumOperands(), {VL.size(), nullptr});
11361 for (auto [Idx, V] : enumerate(VL)) {
11362 auto *I = dyn_cast<Instruction>(V);
11363 if (!I) {
11364 for (auto [OpIdx, Ops] : enumerate(Operands))
11365 Ops[Idx] = PoisonValue::get(VL0->getOperand(OpIdx)->getType());
11366 continue;
11367 }
11368 if (isa<ZExtInst>(I)) {
11369 // Special case for select + zext i1 to avoid explosion of different
11370 // types. We want to keep the condition as i1 to be able to match
11371 // different selects together and reuse the vectorized condition
11372 // rather than trying to gather it.
11373 Operands[0][Idx] = I->getOperand(0);
11374 Operands[1][Idx] = ConstantInt::get(I->getType(), 1);
11375 Operands[2][Idx] = ConstantInt::getNullValue(I->getType());
11376 continue;
11377 }
11378 auto [Op, ConvertedOps] = convertTo(I, S);
11379 for (auto [OpIdx, Ops] : enumerate(Operands))
11380 Ops[Idx] = ConvertedOps[OpIdx];
11381 }
11382 return;
11383 case Instruction::GetElementPtr: {
11384 Operands.assign(2, {VL.size(), nullptr});
11385 // Need to cast all indices to the same type before vectorization to
11386 // avoid crash.
11387 // Required to be able to find correct matches between different gather
11388 // nodes and reuse the vectorized values rather than trying to gather them
11389 // again.
11390 const unsigned IndexIdx = 1;
11391 Type *VL0Ty = VL0->getOperand(IndexIdx)->getType();
11392 Type *Ty =
11393 all_of(VL,
11394 [&](Value *V) {
11396 return !GEP || VL0Ty == GEP->getOperand(IndexIdx)->getType();
11397 })
11398 ? VL0Ty
11399 : DL.getIndexType(cast<GetElementPtrInst>(VL0)
11400 ->getPointerOperandType()
11401 ->getScalarType());
11402 for (auto [Idx, V] : enumerate(VL)) {
11404 if (!GEP) {
11405 Operands[0][Idx] = V;
11406 Operands[1][Idx] = ConstantInt::getNullValue(Ty);
11407 continue;
11408 }
11409 Operands[0][Idx] = GEP->getPointerOperand();
11410 auto *Op = GEP->getOperand(IndexIdx);
11411 auto *CI = dyn_cast<ConstantInt>(Op);
11412 Operands[1][Idx] = CI ? ConstantFoldIntegerCast(
11413 CI, Ty, CI->getValue().isSignBitSet(), DL)
11414 : Op;
11415 }
11416 return;
11417 }
11418 case Instruction::Call: {
11419 auto *CI = cast<CallInst>(VL0);
11421 for (unsigned Idx : seq<unsigned>(CI->arg_size())) {
11423 continue;
11424 auto &Ops = Operands.emplace_back();
11425 for (Value *V : VL) {
11426 auto *I = dyn_cast<Instruction>(V);
11427 Ops.push_back(I ? I->getOperand(Idx)
11428 : PoisonValue::get(VL0->getOperand(Idx)->getType()));
11429 }
11430 }
11431 return;
11432 }
11433 default:
11434 break;
11435 }
11436 llvm_unreachable("Unexpected vectorization of the instructions.");
11437 }
11438
11439 /// Check if the specified \p VL list of values is better to represent as
11440 /// uniform with copyables, as modeled via \p CopyableS, or as alternate (or
11441 /// uniform with compatible ops), modeled via \p S.
11442 /// Performs the analysis of the operands, choosing the preferred main
11443 /// instruction and checking the matching of the operands for the main
11444 /// instruction and copyable elements.
11445 bool isCopyablePreferable(ArrayRef<Value *> VL, const BoUpSLP &R,
11446 const InstructionsState &S,
11447 const InstructionsState &CopyableS) {
11448 // If all elements are vectorized already - keep as is.
11449 if (all_of(VL, [&](Value *V) {
11450 return isa<PoisonValue>(V) || R.isVectorized(V);
11451 }))
11452 return false;
11453 Instruction *SMain = S.getMainOp();
11454 Instruction *SAlt = S.isAltShuffle() ? S.getAltOp() : nullptr;
11455 const bool IsCommutative = isCommutative(SMain);
11456 const bool IsAltCommutative =
11457 S.isAltShuffle() ? isCommutative(SAlt) : false;
11458 const bool IsMainCommutative = isCommutative(MainOp);
11460 buildOriginalOperands(S, SMain, Ops);
11461 // Support only binary operations for now.
11462 if (Ops.size() != 2)
11463 return false;
11464 // Try to find better candidate for S main instruction, which operands have
11465 // better matching.
11466 auto CheckOperands = [](Value *Op, Value *SMainOp) {
11467 auto *OpI = dyn_cast<BinaryOperator>(Op);
11468 if (!OpI)
11469 return false;
11470 auto *SMainOpI = dyn_cast<BinaryOperator>(SMainOp);
11471 if (!SMainOpI)
11472 return true;
11473 return any_of(OpI->operands(), [&](Value *V) {
11474 auto *I = dyn_cast<Instruction>(V);
11475 return I && I->getOpcode() == SMainOpI->getOpcode();
11476 });
11477 };
11478 SmallPtrSet<Value *, 8> Operands;
11479 for (Value *V : VL) {
11480 auto *I = dyn_cast<Instruction>(V);
11481 if (!I || I == SMain)
11482 continue;
11483 Instruction *MatchingOp = S.getMatchingMainOpOrAltOp(I);
11484 if (MatchingOp != SMain)
11485 continue;
11487 buildOriginalOperands(S, I, VOps);
11488 Operands.insert(I->op_begin(), I->op_end());
11489 assert(VOps.size() == 2 && Ops.size() == 2 &&
11490 "Expected binary operations only.");
11491 if (CheckOperands(VOps[0][0], Ops[0][0]) ||
11492 CheckOperands(VOps[1][0], Ops[1][0]) ||
11493 (IsCommutative && (CheckOperands(VOps[0][0], Ops[1][0]) ||
11494 CheckOperands(VOps[1][0], Ops[0][0])))) {
11495 SMain = I;
11496 Ops.swap(VOps);
11497 break;
11498 }
11499 }
11501 buildOriginalOperands(S, MainOp, MainOps);
11502
11503 auto BuildFirstOperandCandidates =
11504 [&](SmallVectorImpl<std::pair<Value *, Value *>> &Candidates,
11506 bool IsCommutative) {
11507 Candidates.emplace_back(Ops[0][0], Op0);
11508 if (IsCommutative)
11509 Candidates.emplace_back(Ops[0][0], Op1);
11510 };
11511
11512 auto BuildSecondOperandCandidates =
11513 [&](SmallVectorImpl<std::pair<Value *, Value *>> &Candidates,
11514 ArrayRef<BoUpSLP::ValueList> Ops, int PrevBestIdx, Value *Op0,
11515 Value *Op1, bool IsCommutative) {
11516 if (PrevBestIdx != 1)
11517 Candidates.emplace_back(Ops[1][0], Op1);
11518 if (PrevBestIdx != 0 && IsCommutative)
11519 Candidates.emplace_back(Ops[1][0], Op0);
11520 };
11521
11522 auto FindBestCandidate =
11523 [&](ArrayRef<std::pair<Value *, Value *>> Candidates, bool &IsConst,
11524 int &Score) {
11525 auto Res = R.findBestRootPair(Candidates);
11526 Score = Res.second;
11527 IsConst =
11529 isConstant(Candidates[Res.first.value_or(0)].first) &&
11530 isConstant(Candidates[Res.first.value_or(0)].second);
11531 if (IsConst) {
11532 // Check if there are splat candidates and consider them better
11533 // option.
11534 for (const auto [Idx, P] : enumerate(Candidates)) {
11535 if (!isConstant(P.first) && !isConstant(P.second) &&
11536 P.second == P.first) {
11537 Res.first = Idx;
11538 IsConst = false;
11539 Score = isa<LoadInst>(Candidates[Res.first.value_or(0)].first)
11542 break;
11543 }
11544 }
11545 }
11546 return Res.first;
11547 };
11548
11549 for (Value *V : VL) {
11550 auto *I = dyn_cast<Instruction>(V);
11551 if (!I || (I == MainOp && (!S.isAltShuffle() || I == SMain)) ||
11552 (!S.isAltShuffle() && I == SMain))
11553 continue;
11555 buildOriginalOperands(S, I == SMain ? MainOp : I, VOps);
11556 SmallVector<Value *> CopyableOps =
11557 getOperands(CopyableS, I == MainOp ? SMain : I);
11558 if (CopyableOps.size() == VOps.size() &&
11559 all_of(zip(CopyableOps, VOps), [&](const auto &P) {
11560 return std::get<0>(P) == std::get<1>(P)[0];
11561 }))
11562 continue;
11564 BuildFirstOperandCandidates(Candidates, MainOps, CopyableOps[0],
11565 CopyableOps[1], IsMainCommutative);
11566 const unsigned OpSize = Candidates.size();
11567 Instruction *MatchingOp =
11568 S.getMatchingMainOpOrAltOp(I) == S.getMainOp() ? SMain : SAlt;
11569 const bool IsCommutativeInst =
11570 (MatchingOp == SMain ? IsCommutative : IsAltCommutative) ||
11571 isCommutative(I, MatchingOp);
11572 if (S.isAltShuffle() && MatchingOp == SAlt &&
11573 any_of(VOps, [&](const BoUpSLP::ValueList &Ops) {
11574 auto *I = dyn_cast<BinaryOperator>(Ops[0]);
11575 return I && Operands.contains(I);
11576 }))
11577 return false;
11578 if (S.isAltShuffle() && MatchingOp == SMain)
11579 Operands.insert(I->op_begin(), I->op_end());
11580 BuildFirstOperandCandidates(Candidates, Ops, VOps[0][0], VOps[1][0],
11581 IsCommutativeInst);
11582 bool IsBestConst;
11583 int Score;
11584 std::optional<int> BestOp =
11585 FindBestCandidate(Candidates, IsBestConst, Score);
11586 const bool IsOriginalBetter =
11587 static_cast<unsigned>(BestOp.value_or(OpSize)) >= OpSize;
11588 Candidates.clear();
11589 BuildSecondOperandCandidates(
11590 Candidates, MainOps, IsOriginalBetter ? -1 : *BestOp, CopyableOps[0],
11591 CopyableOps[1], IsMainCommutative);
11592 const unsigned SecondOpSize = Candidates.size();
11593 BuildSecondOperandCandidates(
11594 Candidates, Ops,
11595 IsOriginalBetter ? BestOp.value_or(OpSize - 1) - OpSize : -1,
11596 VOps[0][0], VOps[1][0], IsCommutativeInst);
11597 bool IsSecondBestConst;
11598 int SecondScore;
11599 std::optional<int> SecondBestOp =
11600 FindBestCandidate(Candidates, IsSecondBestConst, SecondScore);
11601 // No best candidates.
11602 if (!BestOp && !SecondBestOp)
11603 return false;
11604 // Original better in both ops combinations.
11605 const bool IsSecondOriginalBetter =
11606 static_cast<unsigned>(SecondBestOp.value_or(SecondOpSize)) >=
11607 SecondOpSize;
11608 if (IsOriginalBetter && IsSecondOriginalBetter)
11609 return false;
11610 // Original is better in second combination, but in the first combination
11611 // no best candidates.
11612 if (!BestOp && IsSecondOriginalBetter)
11613 return false;
11614 // Original is better in first combination, but in the second combination
11615 // no best candidates.
11616 if (!SecondBestOp && IsOriginalBetter)
11617 return false;
11618 // Copyable is best in the first combination, but it is constant, but
11619 // original is better in second non-constant combination.
11620 if (!IsOriginalBetter && IsBestConst && IsSecondOriginalBetter &&
11621 !IsSecondBestConst)
11622 return false;
11623 // Copyable is best in the second combination, but it is constant, but
11624 // original is better in the first non-constant combination.
11625 if (BestOp && IsOriginalBetter && !IsBestConst &&
11626 !IsSecondOriginalBetter && IsSecondBestConst)
11627 return false;
11628 // Original combination score is better.
11629 if (((Score > SecondScore ||
11631 Score == SecondScore)) &&
11632 IsOriginalBetter) ||
11633 (IsSecondOriginalBetter &&
11634 (SecondScore > Score ||
11636 Score == SecondScore))))
11637 return false;
11638 }
11639 return true;
11640 }
11641
11642public:
11643 InstructionsCompatibilityAnalysis(DominatorTree &DT, const DataLayout &DL,
11644 const TargetTransformInfo &TTI,
11645 const TargetLibraryInfo &TLI)
11646 : DT(DT), DL(DL), TTI(TTI), TLI(TLI) {}
11647
11648 InstructionsState buildInstructionsState(ArrayRef<Value *> VL,
11649 const BoUpSLP &R,
11650 bool WithProfitabilityCheck = false,
11651 bool SkipSameCodeCheck = false) {
11652 InstructionsState S = (SkipSameCodeCheck || !allSameBlock(VL))
11654 : getSameOpcode(VL, TLI);
11655 // Check if series of selects + zext i1 %x to in can be combined into
11656 // selects + select %x, i32 1, i32 0.
11657 Instruction *SelectOp = nullptr;
11658 if (!S && allSameBlock(VL) && all_of(VL, [&](Value *V) {
11659 if (match(V, m_Select(m_Value(), m_Value(), m_Value()))) {
11660 if (!SelectOp)
11661 SelectOp = cast<Instruction>(V);
11662 return true;
11663 }
11664 auto *ZExt = dyn_cast<ZExtInst>(V);
11665 return (ZExt && ZExt->getSrcTy()->isIntegerTy(1)) ||
11667 })) {
11668 if (SelectOp)
11669 return InstructionsState(SelectOp, SelectOp);
11670 }
11671 if (S && S.isAltShuffle()) {
11672 Type *ScalarTy = S.getMainOp()->getType();
11673 auto *VecTy = cast<VectorType>(getWidenedType(ScalarTy, VL.size()));
11674 unsigned Opcode0 = S.getOpcode();
11675 unsigned Opcode1 = S.getAltOpcode();
11676 SmallBitVector OpcodeMask(
11677 getAltInstrMask(VL, ScalarTy, Opcode0, Opcode1));
11678 // If this pattern is supported by the target then we consider the order.
11679 if (TTI.isLegalAltInstr(VecTy, Opcode0, Opcode1, OpcodeMask))
11680 return S;
11681 } else if (S &&
11683 !isSupportedMainOp(S.getMainOp()) || all_of(VL, [&](Value *V) {
11684 auto *I = dyn_cast<Instruction>(V);
11685 return !I || I->getOpcode() == S.getOpcode() ||
11686 (S.getOpcode() == Instruction::Add &&
11687 I->getOpcode() == Instruction::Shl);
11688 }))) {
11689 return S;
11690 }
11692 return S;
11693 AbsorbCopyableFMulOrFAdds = hasOnlyAbsorbableCopyableFMulOrFAdds(VL);
11694 findAndSetMainInstruction(VL, R);
11695 if (!MainOp)
11696 return S;
11697 InstructionsState OrigS = S;
11698 S = InstructionsState(MainOp, MainOp, /*HasCopyables=*/true);
11699 if (OrigS && !isCopyablePreferable(VL, R, OrigS, S))
11700 return OrigS;
11701 if (!WithProfitabilityCheck)
11702 return S;
11703 // ExtractElement copyable nodes reuse the source vector and insert the
11704 // copyable lanes; the binary-operator operand heuristics below do not
11705 // apply, so defer profitability to the full tree cost.
11706 if (isa<ExtractElementInst>(MainOp)) {
11707 // A load as a copyable lane would be pulled out of the consecutive-load
11708 // vectorization; keep the original state so the node can be split.
11709 if (any_of(VL, [&](Value *V) {
11710 return S.isCopyableElement(V) && isa<LoadInst>(V);
11711 }))
11712 return OrigS;
11713 return S;
11714 }
11715 // Check if it is profitable to vectorize the instruction.
11716 unsigned CopyableNum =
11717 count_if(VL, [&](Value *V) { return S.isCopyableElement(V); });
11718 // Absorb copyable single-use fmuls/fadds as fmuladd(a, b, -0.0) or
11719 // fmuladd(1.0, a, b) when every copyable is such a binop: the binops die
11720 // instead of being computed and gathered.
11722 AbsorbCopyableFMulOrFAdds)
11724 SmallVector<BoUpSLP::ValueList> Operands = buildOperands(S, VL);
11725 auto BuildCandidates =
11726 [](SmallVectorImpl<std::pair<Value *, Value *>> &Candidates, Value *V1,
11727 Value *V2) {
11728 if (V1 != V2 && isa<PHINode>(V1))
11729 return;
11730 auto *I1 = dyn_cast<Instruction>(V1);
11731 auto *I2 = dyn_cast<Instruction>(V2);
11732 if (I1 && I2 && I1->getOpcode() == I2->getOpcode() &&
11733 I1->getParent() != I2->getParent())
11734 return;
11735 Candidates.emplace_back(V1, (I1 || I2) ? V2 : V1);
11736 };
11737 if (VL.size() == 2) {
11738 // The operand-pairing heuristic below does not apply to calls; defer
11739 // to the full tree cost computation instead of pre-rejecting here.
11740 if (MainOpcode == Instruction::Call)
11741 return S;
11742 // Check if the operands allow better vectorization.
11743 SmallVector<std::pair<Value *, Value *>, 4> Candidates1, Candidates2;
11744 BuildCandidates(Candidates1, Operands[0][0], Operands[0][1]);
11745 BuildCandidates(Candidates2, Operands[1][0], Operands[1][1]);
11746 bool Res = !Candidates1.empty() && !Candidates2.empty() &&
11747 R.findBestRootPair(Candidates1).first &&
11748 R.findBestRootPair(Candidates2).first;
11749 if (!Res && isCommutative(MainOp)) {
11750 Candidates1.clear();
11751 Candidates2.clear();
11752 BuildCandidates(Candidates1, Operands[0][0], Operands[1][1]);
11753 BuildCandidates(Candidates2, Operands[1][0], Operands[0][1]);
11754 Res = !Candidates1.empty() && !Candidates2.empty() &&
11755 R.findBestRootPair(Candidates1).first &&
11756 R.findBestRootPair(Candidates2).first;
11757 }
11758 if (!Res)
11759 return OrigS;
11760 const TTI::TargetCostKind Kind = R.getCostKind();
11761 InstructionCost ScalarCost = TTI.getInstructionCost(S.getMainOp(), Kind);
11762 InstructionCost VectorCost;
11763 auto *VecTy = getWidenedType(S.getMainOp()->getType(), VL.size());
11764 switch (MainOpcode) {
11765 case Instruction::Add:
11766 case Instruction::Sub:
11767 case Instruction::Mul:
11768 case Instruction::AShr:
11769 case Instruction::LShr:
11770 case Instruction::Shl:
11771 case Instruction::SDiv:
11772 case Instruction::UDiv:
11773 case Instruction::And:
11774 case Instruction::Or:
11775 case Instruction::Xor:
11776 case Instruction::FAdd:
11777 case Instruction::FMul:
11778 case Instruction::FSub:
11779 case Instruction::FDiv:
11780 VectorCost = TTI.getArithmeticInstrCost(MainOpcode, VecTy, Kind);
11781 break;
11782 default:
11783 // Calls (min/max, fmuladd) return above before reaching this switch.
11784 llvm_unreachable("Unexpected instruction.");
11785 }
11786 if (VectorCost > ScalarCost)
11787 return OrigS;
11788 return S;
11789 }
11790 // fmuladd is the only 3-operand copyable.
11791 assert((Operands.size() == 2 ||
11792 (Operands.size() == 3 &&
11794 "Unexpected number of operands!");
11795 if (CopyableNum < VL.size() / 2)
11796 return S;
11797 // Too many phi copyables - exit.
11798 const unsigned Limit = VL.size() / 24;
11799 if ((CopyableNum >= VL.size() - Limit ||
11800 (CopyableNum >= VL.size() - 1 && VL.size() > 4) ||
11801 CopyableNum >= MaxPHINumOperands) &&
11802 all_of(VL, [&](Value *V) {
11803 return isa<PHINode>(V) || !S.isCopyableElement(V);
11804 }))
11805 return OrigS;
11806 // Check profitability if number of copyables > VL.size() / 2.
11807 // 1. Reorder operands for better matching.
11808 if (Operands.size() == 2 && isCommutative(MainOp)) {
11809 Value *BestFrontOp = nullptr;
11810 for (auto [OpL, OpR] : zip(Operands.front(), Operands.back())) {
11811 // Make instructions the first operands.
11812 if (!isa<Instruction>(OpL) && isa<Instruction>(OpR)) {
11813 BestFrontOp = OpR;
11814 std::swap(OpL, OpR);
11815 continue;
11816 }
11817 // Make constants the second operands.
11818 if ((isa<Constant>(OpL) && !match(OpR, m_Zero())) ||
11819 match(OpL, m_Zero())) {
11820 if (isa<Instruction>(OpR))
11821 BestFrontOp = OpR;
11822 std::swap(OpL, OpR);
11823 continue;
11824 }
11825 if (isa<Instruction>(OpL))
11826 BestFrontOp = OpL;
11827 }
11828 // If some of the RHS operands better match most of LHS - swap such
11829 // operands to increase matching rate.
11830 if (auto *BestLHS = dyn_cast_if_present<Instruction>(BestFrontOp)) {
11831 const unsigned BestOpcode = BestLHS->getOpcode();
11832 for (auto [OpL, OpR] : zip(Operands.front(), Operands.back())) {
11833 auto *OpRI = dyn_cast<Instruction>(OpR);
11834 if (!OpRI)
11835 continue;
11836 if (OpRI->getOpcode() == BestOpcode)
11837 std::swap(OpL, OpR);
11838 }
11839 }
11840 }
11841 // 2. Check, if operands can be vectorized. Skip for fmuladd; the
11842 // copyable operand is checked below and may legitimately hold many
11843 // instructions.
11844 if (Operands.size() == 2 &&
11846 return OrigS;
11847 auto CheckOperand = [&](ArrayRef<Value *> Ops) {
11848 if (allConstant(Ops) || isSplat(Ops))
11849 return true;
11850 // Non-instruction operands of a call (args, constants) are always a
11851 // trivial gather, same as the constant/splat cases above.
11852 if (MainOpcode == Instruction::Call && none_of(Ops, IsaPred<Instruction>))
11853 return true;
11854 // Check if it is "almost" splat, i.e. has >= 4 elements and only single
11855 // one is different.
11856 constexpr unsigned Limit = 4;
11857 if (Operands.front().size() >= Limit) {
11858 SmallDenseMap<const Value *, unsigned> Counters;
11859 for (Value *V : Ops) {
11860 if (isa<UndefValue>(V))
11861 continue;
11862 ++Counters[V];
11863 }
11864 if (Counters.size() == 2 &&
11865 any_of(Counters, [&](const std::pair<const Value *, unsigned> &C) {
11866 return C.second == 1;
11867 }))
11868 return true;
11869 }
11870 // First operand not a constant or splat? Last attempt - check for
11871 // potential vectorization.
11872 InstructionsCompatibilityAnalysis Analysis(DT, DL, TTI, TLI);
11873 InstructionsState OpS = Analysis.buildInstructionsState(Ops, R);
11874 if (!OpS || (OpS.getOpcode() == Instruction::PHI && !allSameBlock(Ops)))
11875 return false;
11876 unsigned CopyableNum =
11877 count_if(Ops, [&](Value *V) { return OpS.isCopyableElement(V); });
11878 return CopyableNum <= VL.size() / 2;
11879 };
11880 // Check the operand holding the copyable values.
11881 if (!CheckOperand(Operands[S.getCopyableOpIdx()])) {
11882 if (Operands.size() == 2)
11883 return OrigS;
11884 // Retry with the copyable modeled as the first multiplicand.
11885 S.setCopyableOpIdx(0);
11886 Operands = buildOperands(S, VL);
11887 if (!CheckOperand(Operands[S.getCopyableOpIdx()]))
11888 return OrigS;
11889 }
11890
11891 return S;
11892 }
11893
11894 SmallVector<BoUpSLP::ValueList> buildOperands(const InstructionsState &S,
11895 ArrayRef<Value *> VL) {
11896 assert(S && "Invalid state!");
11899 MainOp = S.getMainOp();
11900 MainOpcode = S.getOpcode();
11901 // ExtractElement copyable nodes carry a single operand (the shared
11902 // source vector); copyable lanes are inserted during codegen and do
11903 // not contribute an operand column.
11904 if (MainOpcode == Instruction::ExtractElement) {
11905 Operands.assign(1,
11906 BoUpSLP::ValueList(VL.size(), MainOp->getOperand(0)));
11907 return Operands;
11908 }
11909 // Excludes the trailing callee operand (2 for min/max, 3 for fmuladd).
11910 // getNumberOfPotentiallyCommutativeOps collapses fmuladd to 2 and must
11911 // not be used here. Only the 2-operand case is commutative-normalized.
11912 auto *CI = dyn_cast<CallInst>(MainOp);
11913 const unsigned NumMainOpOperands =
11914 CI ? CI->arg_size() : MainOp->getNumOperands();
11915 const bool IsCommutative =
11916 isCommutative(MainOp) && NumMainOpOperands == 2;
11917 Operands.assign(NumMainOpOperands,
11918 BoUpSLP::ValueList(VL.size(), nullptr));
11919 // Populate operands for every lane.
11920 for (auto [Idx, V] : enumerate(VL)) {
11921 SmallVector<Value *> OperandsForValue = getOperands(S, V);
11922 for (auto [OperandIdx, Operand] : enumerate(OperandsForValue))
11923 Operands[OperandIdx][Idx] = Operand;
11924 }
11925 // Operand-order normalization below swaps OpIdx 0 and OpIdx 1
11926 // of non-copyable lanes. That is only safe when the main op is
11927 // commutative (e.g. 0 - X is not X - 0, so `sub` must be
11928 // excluded). With absorbed fmul/fadd copyables the fmuladd
11929 // multiplicands are commutative per lane and get normalized too;
11930 // the 0/1 swaps never touch the addend column.
11931 if (IsCommutative || S.hasAbsorbedCopyableFMulOrFAdd()) {
11932 // IsCommutative can hold for MainOp (e.g. a Sub/FSub feeding only
11933 // fabs/icmp-eq-0) without every lane sharing that property, so
11934 // re-check the specific lane before swapping it. Absorbed fmul/fadd
11935 // lanes are always commutative.
11936 auto CanSwap = [&](Value *V) {
11939 return true;
11941 V);
11942 };
11943 // Absorbed fmul/fadd copyables do not vote for the majority operand
11944 // pattern (their multiplicand order is arbitrary) but take part
11945 // in the swaps.
11946 auto SwappableLane = [&](Value *V) {
11947 return !isa<PoisonValue>(V) &&
11948 (!S.isCopyableElement(V) ||
11951 };
11952 // Count (ID0, ID1) pair frequencies for operand normalization.
11953 // Pairs and their inverses are tracked under a canonical key
11954 // so that (Load, Add) and (Add, Load) contribute to the same
11955 // bucket.
11956 struct PairInfo {
11957 unsigned FwdCount = 0;
11958 unsigned RevCount = 0;
11959 };
11960 SmallMapVector<std::pair<unsigned, unsigned>, PairInfo, 8> PairCounts;
11961 SmallMapVector<unsigned, unsigned, 4> AddendIDCounts;
11962 unsigned MajID0 = 0, MajID1 = 0;
11963 for (auto [Idx, V] : enumerate(VL)) {
11964 if (S.isCopyableElement(V) || isa<PoisonValue>(V))
11965 continue;
11966 unsigned ID0 = Operands[0][Idx]->getValueID();
11967 unsigned ID1 = Operands[1][Idx]->getValueID();
11969 ++AddendIDCounts[Operands[2][Idx]->getValueID()];
11970 if (ID0 == ID1)
11971 continue;
11972 unsigned MinID = std::min(ID0, ID1);
11973 unsigned MaxID = std::max(ID0, ID1);
11974 auto [It, Inserted] =
11975 PairCounts.try_emplace(std::make_pair(MinID, MaxID));
11976 PairInfo &Info = It->second;
11977 if (ID0 < ID1)
11978 ++Info.FwdCount;
11979 else
11980 ++Info.RevCount;
11981 }
11982 // Find the most frequent (ID0, ID1) pair across non-copyable
11983 // lanes. Select the orientation (original or inverse) that
11984 // has more votes as the majority pattern.
11985 unsigned BestCount = 0;
11986 for (const auto &P : PairCounts) {
11987 const PairInfo &Info = P.second;
11988 unsigned Total = Info.FwdCount + Info.RevCount;
11989 if (Total > BestCount) {
11990 BestCount = Total;
11991 if (Info.FwdCount >= Info.RevCount) {
11992 MajID0 = P.first.first;
11993 MajID1 = P.first.second;
11994 } else {
11995 MajID0 = P.first.second;
11996 MajID1 = P.first.first;
11997 }
11998 }
11999 }
12000 // Absorbed fadd copyables are fmuladd(1.0, a, b): pick the
12001 // addend/multiplicand assignment matching the majority operand
12002 // kinds of the non-copyable lanes in the multiplicand (1) and
12003 // addend (2) columns.
12005 unsigned MajID2 = 0, Best2 = 0;
12006 for (const auto &P : AddendIDCounts) {
12007 if (P.second > Best2) {
12008 Best2 = P.second;
12009 MajID2 = P.first;
12010 }
12011 }
12012 for (auto [Idx, V] : enumerate(VL)) {
12013 auto *I = dyn_cast<Instruction>(V);
12014 if (!I || I->getOpcode() != Instruction::FAdd ||
12016 continue;
12017 unsigned ID1 = Operands[1][Idx]->getValueID();
12018 unsigned ID2 = Operands[2][Idx]->getValueID();
12019 unsigned Cur = (ID1 == MajID1) + (ID2 == MajID2);
12020 unsigned Swapped = (ID2 == MajID1) + (ID1 == MajID2);
12021 if (Swapped > Cur)
12022 std::swap(Operands[1][Idx], Operands[2][Idx]);
12023 }
12024 }
12025 // Normalize swappable lanes in two steps:
12026 // 1) Swap lanes whose operand types are the exact inverse of
12027 // the majority pattern, making the non-copyable lanes
12028 // consistent.
12029 // 2) Independently, if a strict majority of swappable lanes
12030 // have loads at OpIdx 1, swap those lanes to put loads at
12031 // OpIdx 0 for better downstream vectorization.
12032 unsigned LAt0 = 0, LAt1 = 0, TotalNC = 0;
12033 for (auto [Idx, V] : enumerate(VL)) {
12034 if (!SwappableLane(V))
12035 continue;
12036 // Step 1: swap exact-inverse lanes.
12037 if (BestCount > 0) {
12038 unsigned ID0 = Operands[0][Idx]->getValueID();
12039 unsigned ID1 = Operands[1][Idx]->getValueID();
12040 if (ID0 == MajID1 && ID1 == MajID0 && CanSwap(V))
12041 std::swap(Operands[0][Idx], Operands[1][Idx]);
12042 }
12043 ++TotalNC;
12044 LAt0 += isa<LoadInst>(Operands[0][Idx]);
12045 LAt1 += isa<LoadInst>(Operands[1][Idx]);
12046 }
12047 // Step 2: if most non-copyable lanes have loads at OpIdx 1,
12048 // swap those lanes to put loads at OpIdx 0.
12049 if (TotalNC > 1 && LAt1 > LAt0 && LAt1 * 2 > TotalNC) {
12050 for (auto [Idx, V] : enumerate(VL)) {
12051 if (!SwappableLane(V))
12052 continue;
12053 if (!isa<LoadInst>(Operands[0][Idx]) &&
12054 isa<LoadInst>(Operands[1][Idx]) && CanSwap(V))
12055 std::swap(Operands[0][Idx], Operands[1][Idx]);
12056 }
12057 }
12058 }
12059 } else {
12060 buildOriginalOperands(S, VL, Operands);
12061 }
12062 return Operands;
12063 }
12064};
12065} // namespace
12066
12067void BoUpSLP::tryToVectorizeSplatGatheredScalars() {
12068 auto LoadsSubkey = [](size_t /*Key*/, LoadInst *LI) {
12069 return hash_value(getUnderlyingObject(LI->getPointerOperand()));
12070 };
12071 // The key includes the value type: the opcode-based key does not always
12072 // distinguish types (e.g. all extractvalue instructions share one key),
12073 // while the tree requires same-typed scalars.
12074 SmallMapVector<std::tuple<size_t, size_t, Type *>, SmallSetVector<Value *, 4>,
12075 4>
12076 Groups;
12077 for (const std::unique_ptr<TreeEntry> &TE : VectorizableTree) {
12078 // Only gathers with vectorized (non-gather) users can reuse the broadcast.
12079 if (!TE->isGather() || !TE->UserTreeIndex ||
12080 TE->UserTreeIndex.UserTE->isGather() || !isSplat(TE->Scalars))
12081 continue;
12082 auto *I = dyn_cast<Instruction>(TE->Scalars.front());
12083 // Skip shuffle-like instructions: their splat gathers are already emitted
12084 // as cheap shuffles of the source vector.
12085 if (!I ||
12087 I->getType()->isVoidTy() || isVectorized(I) || isDeleted(I) ||
12088 (UserIgnoreList && UserIgnoreList->contains(I)))
12089 continue;
12090 // Scheduling new memory bundles in a to-be-versioned tree records extra
12091 // alias-check pairs and can push the region over the versioning limits.
12092 if (isTryingRuntimeAliasChecks() && I->mayReadOrWriteMemory())
12093 continue;
12094 auto [Key, SubKey] =
12095 generateKeySubkey(I, TLI, LoadsSubkey, /*AllowAlternate=*/true);
12096 Groups[std::make_tuple(Key, SubKey, I->getType())].insert(I);
12097 }
12098 // Values left in singleton groups cannot form a bundle on their own;
12099 // regroup them by the opcode-insensitive key so alternate/copyable
12100 // bundles still form.
12101 SmallMapVector<std::pair<size_t, Type *>, SmallSetVector<Value *, 4>, 4>
12102 FallbackGroups;
12103 for (auto &[Key, Group] : Groups) {
12104 if (Group.size() >= 2)
12105 continue;
12106 FallbackGroups[std::make_pair(std::get<0>(Key), Group.front()->getType())]
12107 .insert(Group.front());
12108 }
12109 InstructionsCompatibilityAnalysis Analysis(*DT, *DL, *TTI, *TLI);
12110 auto BuildSubtree = [&](const auto &GroupMap) {
12111 for (const auto &[_, Group] : GroupMap) {
12112 if (Group.size() < 2)
12113 continue;
12114 // Copyable-aware check so bundles with copyable lanes are not skipped.
12115 if (!Analysis.buildInstructionsState(Group.getArrayRef(), *this))
12116 continue;
12117 unsigned PrevSize = VectorizableTree.size();
12118 buildTreeRec(Group.getArrayRef(), 0, EdgeInfo());
12119 if (PrevSize == VectorizableTree.size())
12120 continue;
12121 TreeEntry *NewRoot = VectorizableTree[PrevSize].get();
12122 if (NewRoot->isGather()) {
12123 // Failed to vectorize the bundle: drop the added gather entry, it has
12124 // no users and only adds cost.
12125 for (Value *V : NewRoot->Scalars) {
12126 auto It = ValueToGatherNodes.find(V);
12127 if (It != ValueToGatherNodes.end())
12128 It->second.remove(NewRoot);
12129 }
12130 LoadEntriesToVectorize.remove(PrevSize);
12131 VectorizableTree.pop_back();
12132 continue;
12133 }
12134 SplatGatheredScalarsRoots.push_back(NewRoot);
12135 }
12136 };
12137 BuildSubtree(Groups);
12138 BuildSubtree(FallbackGroups);
12139}
12140
12141BoUpSLP::ScalarsVectorizationLegality
12142BoUpSLP::getScalarsVectorizationLegality(ArrayRef<Value *> VL, unsigned Depth,
12143 const EdgeInfo &UserTreeIdx) const {
12144 assert((allConstant(VL) || allSameType(VL)) && "Invalid types!");
12145
12146 InstructionsCompatibilityAnalysis Analysis(*DT, *DL, *TTI, *TLI);
12147 InstructionsState S = Analysis.buildInstructionsState(
12148 VL, *this, /*WithProfitabilityCheck=*/true);
12149
12150 bool AreScatterAllGEPSameBlock = false;
12151 if (!S) {
12152 SmallVector<unsigned> SortedIndices;
12153 BasicBlock *BB = nullptr;
12154 bool IsScatterVectorizeUserTE =
12155 UserTreeIdx.UserTE &&
12156 UserTreeIdx.UserTE->State == TreeEntry::ScatterVectorize;
12157 AreScatterAllGEPSameBlock =
12158 (IsScatterVectorizeUserTE && VL.front()->getType()->isPointerTy() &&
12159 VL.size() > 2 &&
12160 all_of(VL,
12161 [&BB](Value *V) {
12162 auto *I = dyn_cast<GetElementPtrInst>(V);
12163 if (!I)
12164 return doesNotNeedToBeScheduled(V);
12165 if (!BB)
12166 BB = I->getParent();
12167 return BB == I->getParent() && I->getNumOperands() == 2;
12168 }) &&
12169 BB &&
12170 sortPtrAccesses(VL, UserTreeIdx.UserTE->getMainOp()->getType(), *DL,
12171 *SE, SortedIndices));
12172 if (!AreScatterAllGEPSameBlock) {
12173 LLVM_DEBUG(dbgs() << "SLP: Try split and if failed, gathering due to "
12174 "C,S,B,O, small shuffle. \n";
12175 dbgs() << "[";
12176 interleaveComma(VL, dbgs(), [&](Value *V) { dbgs() << *V; });
12177 dbgs() << "]\n");
12178 return ScalarsVectorizationLegality(S, /*IsLegal=*/false,
12179 /*TryToFindDuplicates=*/true,
12180 /*TrySplitVectorize=*/true);
12181 }
12182 // Reset S to make it GetElementPtr kind of node.
12183 const auto *It = find_if(VL, IsaPred<GetElementPtrInst>);
12184 assert(It != VL.end() && "Expected at least one GEP.");
12185 S = getSameOpcode(*It, *TLI);
12186 }
12187 assert(S && "Must be valid.");
12188
12189 // Gather very wide PHI bundles. Wide PHIs (e.g. produced by
12190 // jump threading) are not profitable to vectorize and make this analysis
12191 // explode, so gather them to keep the compile time bounded.
12192 if (S.getOpcode() == Instruction::PHI) {
12193 unsigned NumIncomingValues =
12194 cast<PHINode>(S.getMainOp())->getNumIncomingValues();
12195 if (static_cast<uint64_t>(VL.size()) * NumIncomingValues >
12197 LLVM_DEBUG(dbgs() << "SLP: Gathering due to wide PHI operand fan-out ("
12198 << VL.size() << " lanes x " << NumIncomingValues
12199 << " incoming values).\n");
12200 return ScalarsVectorizationLegality(S, /*IsLegal=*/false);
12201 }
12202 }
12203
12204 // Don't handle vectors.
12205 if (!SLPReVec && getValueType(VL.front(), SLPReVec)->isVectorTy()) {
12206 LLVM_DEBUG(dbgs() << "SLP: Gathering due to vector type.\n");
12207 // Do not try to pack to avoid extra instructions here.
12208 return ScalarsVectorizationLegality(S, /*IsLegal=*/false,
12209 /*TryToFindDuplicates=*/false);
12210 }
12211
12212 // Check that all of the users of the scalars that we want to vectorize are
12213 // schedulable.
12214 BasicBlock *BB = S.getMainOp()->getParent();
12215
12217 !DT->isReachableFromEntry(BB)) {
12218 // Don't go into unreachable blocks. They may contain instructions with
12219 // dependency cycles which confuse the final scheduling.
12220 // Do not vectorize EH and non-returning blocks, not profitable in most
12221 // cases.
12222 LLVM_DEBUG(dbgs() << "SLP: bundle in unreachable block.\n");
12223 return ScalarsVectorizationLegality(S, /*IsLegal=*/false);
12224 }
12225
12226 // Don't go into catchswitch blocks, which can happen with PHIs.
12227 // Such blocks can only have PHIs and the catchswitch. There is no
12228 // place to insert a shuffle if we need to, so just avoid that issue.
12230 LLVM_DEBUG(dbgs() << "SLP: bundle in catchswitch block.\n");
12231 // Do not try to pack to avoid extra instructions here.
12232 return ScalarsVectorizationLegality(S, /*IsLegal=*/false,
12233 /*TryToFindDuplicates=*/false);
12234 }
12235
12236 // Don't handle scalable vectors
12237 if (S.getOpcode() == Instruction::ExtractElement &&
12239 cast<ExtractElementInst>(S.getMainOp())->getVectorOperandType())) {
12240 LLVM_DEBUG(dbgs() << "SLP: Gathering due to scalable vector type.\n");
12241 return ScalarsVectorizationLegality(S, /*IsLegal=*/false);
12242 }
12243
12244 // Gather if we hit the RecursionMaxDepth, unless this is a load (or z/sext of
12245 // a load), in which case peek through to include it in the tree, without
12246 // ballooning over-budget.
12247 if (Depth >= RecursionMaxDepth &&
12248 (S.isAltShuffle() || VL.size() < 4 ||
12249 !(match(S.getMainOp(), m_Load(m_Value())) ||
12250 all_of(VL, [&S](const Value *I) {
12251 return match(I,
12253 cast<Instruction>(I)->getOpcode() == S.getOpcode();
12254 })))) {
12255 LLVM_DEBUG(dbgs() << "SLP: Gathering due to max recursion depth.\n");
12256 return ScalarsVectorizationLegality(S, /*IsLegal=*/false);
12257 }
12258
12259 // Check if this is a duplicate of another entry.
12260 LLVM_DEBUG(dbgs() << "SLP: \tChecking bundle: " << *S.getMainOp() << ".\n");
12261 // Cache invariants to avoid recomputing for every V in VL (and every E).
12262 const bool IsPHIWithLoop =
12263 S.getOpcode() == Instruction::PHI &&
12264 LI->getLoopFor(S.getMainOp()->getParent()) != nullptr;
12265 for (TreeEntry *E : getTreeEntries(S.getMainOp())) {
12266 if (E->isSame(VL)) {
12267 LLVM_DEBUG(dbgs() << "SLP: Perfect diamond merge at " << *S.getMainOp()
12268 << ".\n");
12269 return ScalarsVectorizationLegality(S, /*IsLegal=*/false);
12270 }
12271 SmallPtrSet<Value *, 8> Values(llvm::from_range, E->Scalars);
12272 if (all_of(VL, [&](Value *V) {
12273 return isa<PoisonValue>(V) || Values.contains(V) ||
12274 (IsPHIWithLoop && isa<PHINode>(V) && isVectorized(V));
12275 })) {
12276 LLVM_DEBUG(dbgs() << "SLP: Gathering due to full overlap.\n");
12277 return ScalarsVectorizationLegality(S, /*IsLegal=*/false);
12278 }
12279 }
12280
12281 bool AreAllSameBlock = !AreScatterAllGEPSameBlock;
12282 bool AreAllSameInsts = AreAllSameBlock || AreScatterAllGEPSameBlock;
12283 if (!AreAllSameInsts || isSplat(VL) ||
12285 S.getMainOp()) &&
12287 LLVM_DEBUG(dbgs() << "SLP: Gathering due to C,S,B,O conditions. \n";
12288 dbgs() << "[";
12289 interleaveComma(VL, dbgs(), [&](Value *V) { dbgs() << *V; });
12290 dbgs() << "]\n");
12291 return ScalarsVectorizationLegality(S, /*IsLegal=*/false);
12292 }
12293
12294 // Don't vectorize ephemeral values.
12295 if (!EphValues.empty()) {
12296 for (Value *V : VL) {
12297 if (EphValues.count(V)) {
12298 LLVM_DEBUG(dbgs() << "SLP: The instruction (" << *V
12299 << ") is ephemeral.\n");
12300 // Do not try to pack to avoid extra instructions here.
12301 return ScalarsVectorizationLegality(S, /*IsLegal=*/false,
12302 /*TryToFindDuplicates=*/false);
12303 }
12304 }
12305 }
12306
12307 // We now know that this is a vector of instructions of the same type from
12308 // the same block.
12309
12310 // Check that none of the instructions in the bundle are already in the tree
12311 // and the node may be not profitable for the vectorization as the small
12312 // alternate node.
12313 if (S.isAltShuffle()) {
12314 auto GetNumVectorizedExtracted = [&]() {
12315 APInt Extracted = APInt::getZero(VL.size());
12316 APInt Vectorized = APInt::getAllOnes(VL.size());
12317 for (auto [Idx, V] : enumerate(VL)) {
12318 auto *I = dyn_cast<Instruction>(V);
12319 if (!I || doesNotNeedToBeScheduled(I) ||
12320 all_of(I->operands(), [&](const Use &U) {
12321 return isa<ExtractElementInst>(U.get());
12322 }))
12323 continue;
12324 if (isVectorized(I))
12325 Vectorized.clearBit(Idx);
12326 else if (!I->hasOneUser() && !areAllUsersVectorized(I, UserIgnoreList))
12327 Extracted.setBit(Idx);
12328 }
12329 return std::make_pair(Vectorized, Extracted);
12330 };
12331 auto [Vectorized, Extracted] = GetNumVectorizedExtracted();
12332 bool PreferScalarize = !Vectorized.isAllOnes() && VL.size() == 2;
12333 if (!Vectorized.isAllOnes() && !PreferScalarize) {
12334 // Rough cost estimation, if the vector code (+ potential extracts) is
12335 // more profitable than the scalar + buildvector.
12336 Type *ScalarTy = VL.front()->getType();
12337 auto *VecTy = cast<VectorType>(getWidenedType(ScalarTy, VL.size()));
12338 InstructionCost VectorizeCostEstimate =
12339 getShuffleCost(*TTI, TTI::SK_PermuteTwoSrc, VecTy, CostKind) +
12340 getScalarizationOverhead(*TTI, SLPReVec, ScalarTy, VecTy, Extracted,
12341 /*Insert=*/false, /*Extract=*/true,
12342 CostKind);
12343 InstructionCost ScalarizeCostEstimate = getScalarizationOverhead(
12344 *TTI, SLPReVec, ScalarTy, VecTy, Vectorized,
12345 /*Insert=*/true, /*Extract=*/false, CostKind, /*ForPoisonSrc=*/false);
12346 PreferScalarize = VectorizeCostEstimate > ScalarizeCostEstimate;
12347 }
12348 if (PreferScalarize) {
12349 LLVM_DEBUG(dbgs() << "SLP: The instructions are in tree and alternate "
12350 "node is not profitable.\n");
12351 return ScalarsVectorizationLegality(S, /*IsLegal=*/false);
12352 }
12353 }
12354
12355 // The reduction nodes (stored in UserIgnoreList) also should stay scalar.
12356 if (UserIgnoreList && !UserIgnoreList->empty()) {
12357 for (Value *V : VL) {
12358 if (UserIgnoreList->contains(V)) {
12359 LLVM_DEBUG(dbgs() << "SLP: Gathering due to gathered scalar.\n");
12360 return ScalarsVectorizationLegality(S, /*IsLegal=*/false);
12361 }
12362 }
12363 }
12364
12365 return ScalarsVectorizationLegality(S, /*IsLegal=*/true);
12366}
12367
12368/// Peel associative single-use binary chains into operand columns. Peeled
12369/// instructions go to \p ReassocScalars; sub-operands are inserted after the
12370/// peeled column so real pairs stay adjacent for flag reuse.
12371/// Poison lanes are allowed through; a lane that is not itself a matching
12372/// real instruction can still be peeled as a copyable identity leaf, as
12373/// long as some other lane anchors the opcode.
12374/// Add/sub (and fadd/fsub) chains peel together: a peeled subtract keeps
12375/// the column sign for its first operand and flips it for the second one,
12376/// recorded per column in \p NegatedColumns, so subtracted leaves stay out
12377/// of the positive total.
12379 const InstructionsState &S, DominatorTree &DT, const DataLayout &DL,
12380 const TargetTransformInfo &TTI, const TargetLibraryInfo &TLI,
12382 SmallBitVector &NegatedColumns, SmallVectorImpl<Value *> &ReassocScalars) {
12383 assert(Operands.size() == 2 && NegatedColumns.empty() &&
12384 "Expected the initial 2 operand columns.");
12385 // The subtract family flips the sign of its second operand column.
12386 auto IsSub = [](unsigned Opcode) {
12387 return Opcode == Instruction::Sub || Opcode == Instruction::FSub;
12388 };
12389 // Signs ride with the columns so the parallel lists cannot drift apart.
12390 struct SignedColumn {
12392 bool Negated;
12393 };
12395 {std::move(Operands[0]), false},
12396 {std::move(Operands[1]), IsSub(S.getOpcode())}};
12397 InstructionsCompatibilityAnalysis Analysis(DT, DL, TTI, TLI);
12398 // The opcode family a column may peel into: subtracts flatten as adds of
12399 // a negated leaf, other opcodes peel only into their own kind.
12400 const unsigned RootFamily = getReassocCombineOpcode(S.getOpcode());
12401 // A lane whose value is itself a single-use chain link; block placement
12402 // does not matter here (buildTreeRec re-checks that later for whatever
12403 // columns end up as real leaves).
12404 auto IsRealLane = [&](Value *V) {
12405 auto *I = dyn_cast<Instruction>(V);
12406 return I && I->hasOneUse() &&
12407 getReassocCombineOpcode(I->getOpcode()) == RootFamily &&
12409 };
12410 // Builds on InstructionsCompatibilityAnalysis's own opcode matching
12411 // (rather than the more permissive getSameOpcode()) so a column that
12412 // falls back to a copyable identity leaf only ever anchors on a MainOp
12413 // that InstructionsCompatibilityAnalysis::isSupportedOpcode() accepts.
12414 auto CanPeel = [&](ArrayRef<Value *> Column) {
12415 InstructionsState ColS = Analysis.buildInstructionsState(Column, R);
12416 if (!ColS || getReassocCombineOpcode(ColS.getOpcode()) != RootFamily ||
12417 ColS.isAltShuffle())
12419 // Every lane must be poison, a genuine matching real lane, or (only for
12420 // a copyable ColS) stand in as a copyable identity leaf
12421 // (Opcode(V, identity) == V).
12422 if (!all_of(Column, [&](Value *V) {
12423 return isa<PoisonValue>(V) || IsRealLane(V) ||
12425 ColS.isCopyableElement(V));
12426 }))
12428 return ColS;
12429 };
12430 for (unsigned Idx = 0; Idx != Columns.size();) {
12431 InstructionsState ColS = CanPeel(Columns[Idx].Col);
12432 if (!ColS) {
12433 ++Idx;
12434 continue;
12435 }
12436 BoUpSLP::ValueList Column = std::move(Columns[Idx].Col);
12438 Analysis.buildOperands(ColS, Column);
12439 assert(SubOperands.size() == 2 && "Expected 2 operand columns.");
12440 // Poison and copyable lanes have no real instruction left to erase
12441 // later: a copyable V is used as-is, not subsumed by the flattened
12442 // combine.
12443 for (Value *V : Column)
12444 if (!isa<PoisonValue>(V) && !ColS.isCopyableElement(V))
12445 ReassocScalars.push_back(V);
12446 // A peeled subtract negates its second operand column.
12447 const bool Negated = Columns[Idx].Negated;
12448 Columns[Idx].Col = std::move(SubOperands.front());
12449 Columns.insert(
12450 std::next(Columns.begin(), Idx + 1),
12451 {std::move(SubOperands.back()), IsSub(ColS.getOpcode()) != Negated});
12452 // Do not advance Idx: re-examine the column that was just placed here.
12453 }
12454 Operands.clear();
12455 for (auto &[Col, Negated] : Columns) {
12456 Operands.push_back(std::move(Col));
12457 NegatedColumns.push_back(Negated);
12458 }
12459}
12460
12461/// Realign flattened operand columns so matching value families share a
12462/// column across lanes. Lane 0 is canonical; other lanes match by key equality
12463/// only (never compare hash values). Columns sharing a key are paired by the
12464/// family of their first operand where available, so e.g. shifts fed by the
12465/// same load family land in one column instead of pairing by encounter order.
12466/// Values move between columns only within the same sign: a subtracted leaf
12467/// never lands in an added column. The sign is queried per lane and column
12468/// with \p IsNegated: alternate add/sub nodes negate only the non-leading
12469/// columns of their subtract lanes.
12472 function_ref<bool(unsigned Lane, unsigned Col)> IsNegated,
12473 const TargetLibraryInfo &TLI) {
12474 const unsigned NumCols = Operands.size();
12475 const unsigned NumLanes = Operands.front().size();
12476 auto LoadsSubkey = [](size_t /*Key*/, LoadInst *LI) {
12477 return hash_value(getUnderlyingObject(LI->getPointerOperand()));
12478 };
12479 auto GetKey = [&](Value *V) {
12480 return generateKeySubkey(V, &TLI, LoadsSubkey, /*AllowAlternate=*/false);
12481 };
12482 const std::pair<size_t, size_t> NoSecondaryKey{0, 0};
12483 // Family of the value's first operand; loads already carry their family in
12484 // the primary key.
12485 auto GetSecondaryKey = [&](Value *V) -> std::pair<size_t, size_t> {
12486 auto *I = dyn_cast<Instruction>(V);
12487 if (!I || isa<LoadInst>(I) || I->getNumOperands() == 0)
12488 return NoSecondaryKey;
12489 return GetKey(I->getOperand(0));
12490 };
12492 Operands, [&](const BoUpSLP::ValueList &Col) { return GetKey(Col[0]); });
12493 SmallVector<std::pair<size_t, size_t>> Lane0SecondaryKeys =
12494 map_to_vector(Operands, [&](const BoUpSLP::ValueList &Col) {
12495 return GetSecondaryKey(Col[0]);
12496 });
12497
12499 BoUpSLP::ValueList(NumLanes));
12500 for (unsigned Col : seq<unsigned>(NumCols))
12501 Aligned[Col][0] = Operands[Col][0];
12502
12503 for (unsigned Lane : seq<unsigned>(1, NumLanes)) {
12504 // Buckets are keyed by the value key and the column sign.
12505 using Key = std::pair<std::pair<size_t, size_t>, unsigned>;
12506 auto Sign = [&](unsigned Col) { return IsNegated(Lane, Col) ? 1U : 0U; };
12508 for (unsigned Col : seq<unsigned>(NumCols))
12509 Buckets[{GetKey(Operands[Col][Lane]), Sign(Col)}].push_back(Col);
12511 SmallVector<unsigned> SlotSrcCol(NumCols, NumCols);
12512 SmallBitVector ColClaimed(NumCols, false);
12513 for (unsigned Slot : seq<unsigned>(NumCols)) {
12514 const auto SlotKey = std::make_pair(Lane0Keys[Slot], Sign(Slot));
12515 auto BucketIt = Buckets.find(SlotKey);
12516 if (BucketIt == Buckets.end())
12517 continue;
12518 unsigned &Cursor = NextInBucket[SlotKey];
12519 if (Cursor >= BucketIt->second.size())
12520 continue;
12521 // Among the remaining same-key columns prefer the one whose operand
12522 // family matches lane 0's; no match keeps the bucket order.
12523 unsigned PickPos = Cursor;
12524 if (Lane0SecondaryKeys[Slot] != NoSecondaryKey)
12525 for (unsigned P = Cursor, E = BucketIt->second.size(); P != E; ++P)
12526 if (GetSecondaryKey(Operands[BucketIt->second[P]][Lane]) ==
12527 Lane0SecondaryKeys[Slot]) {
12528 PickPos = P;
12529 break;
12530 }
12531 std::swap(BucketIt->second[Cursor], BucketIt->second[PickPos]);
12532 unsigned SrcCol = BucketIt->second[Cursor++];
12533 SlotSrcCol[Slot] = SrcCol;
12534 ColClaimed[SrcCol] = true;
12535 }
12536 // Leftover slots take leftover columns of the same sign; per-lane sign
12537 // counts match, so every slot finds one.
12538 for (unsigned Slot : seq<unsigned>(NumCols)) {
12539 if (SlotSrcCol[Slot] != NumCols)
12540 continue;
12541 for (unsigned Col : seq<unsigned>(NumCols)) {
12542 if (!ColClaimed[Col] && IsNegated(Lane, Col) == IsNegated(Lane, Slot)) {
12543 SlotSrcCol[Slot] = Col;
12544 ColClaimed[Col] = true;
12545 break;
12546 }
12547 }
12548 }
12549 for (unsigned Slot : seq<unsigned>(NumCols))
12550 Aligned[Slot][Lane] = Operands[SlotSrcCol[Slot]][Lane];
12551 }
12552 return Aligned;
12553}
12554
12555/// Rank reassociated operand layouts by vectorizable load columns, other load
12556/// patterns, broadcast/constant columns, then fewer unique values per column.
12557/// Identity columns are scored by the opcode of the emitted combines.
12558static std::tuple<unsigned, unsigned, unsigned, int>
12560 unsigned Opcode) {
12561 unsigned NumConsecutiveLoadCols = 0;
12562 unsigned NumOtherVecLoadCols = 0;
12563 unsigned NumBroadcastOrConstCols = 0;
12564 int NumUniqueValues = 0;
12565 const unsigned CombineOpcode = getReassocCombineOpcode(Opcode);
12566 for (ArrayRef<Value *> Col : Columns) {
12567 if (all_of(Col, IsaPred<Constant>)) {
12568 ++NumBroadcastOrConstCols;
12569 continue;
12570 }
12571 // Identity constants are free beyond the base they are inserted into.
12572 SmallPtrSet<Value *, 8> UniqueValues;
12573 for (Value *V : Col)
12574 if (!isBinOpIdentityConstant(V, CombineOpcode))
12575 UniqueValues.insert(V);
12576 NumUniqueValues += UniqueValues.size();
12577 if (UniqueValues.size() <= 1) {
12578 ++NumBroadcastOrConstCols;
12579 continue;
12580 }
12581 if (all_of(Col, IsaPred<LoadInst>)) {
12582 BoUpSLP::OrdersType Order;
12583 SmallVector<Value *> PointerOps;
12584 BoUpSLP::StridedPtrInfo SPtrInfo;
12586 R.canVectorizeLoads(Col, Col.front(), Order, PointerOps, SPtrInfo);
12588 ++NumConsecutiveLoadCols;
12589 else if (LS != BoUpSLP::LoadsState::Gather)
12590 ++NumOtherVecLoadCols;
12591 }
12592 }
12593 // Greater is better; negate unique count as a tie-breaker.
12594 return std::make_tuple(NumConsecutiveLoadCols, NumOtherVecLoadCols,
12595 NumBroadcastOrConstCols, -NumUniqueValues);
12596}
12597
12598void BoUpSLP::buildTreeRec(ArrayRef<Value *> VLRef, unsigned Depth,
12599 const EdgeInfo &UserTreeIdx,
12600 unsigned InterleaveFactor) {
12601 assert((allConstant(VLRef) || allSameType(VLRef)) && "Invalid types!");
12602
12603 SmallVector<int> ReuseShuffleIndices;
12604 SmallVector<Value *> VL(VLRef);
12605
12606 // Tries to build split node.
12607 auto TrySplitNode = [&](const InstructionsState &LocalState) {
12608 SmallVector<Value *> Op1, Op2;
12609 OrdersType ReorderIndices;
12610 if (!canBuildSplitNode(VL, LocalState, Op1, Op2, ReorderIndices))
12611 return false;
12612
12613 auto Invalid = ScheduleBundle::invalid();
12614 auto *TE = newTreeEntry(VL, TreeEntry::SplitVectorize, Invalid, LocalState,
12615 UserTreeIdx, {}, ReorderIndices);
12616 LLVM_DEBUG(dbgs() << "SLP: split alternate node.\n"; TE->dump());
12617 auto AddNode = [&](ArrayRef<Value *> Op, unsigned Idx) {
12618 InstructionsState S = getSameOpcode(Op, *TLI);
12619 if (S && (isa<LoadInst>(S.getMainOp()) ||
12620 getSameValuesTreeEntry(S.getMainOp(), Op, /*SameVF=*/true))) {
12621 // Build gather node for loads, they will be gathered later.
12622 TE->CombinedEntriesWithIndices.emplace_back(VectorizableTree.size(),
12623 Idx == 0 ? 0 : Op1.size());
12624 (void)newTreeEntry(Op, TreeEntry::NeedToGather, Invalid, S, {TE, Idx});
12625 } else {
12626 TE->CombinedEntriesWithIndices.emplace_back(VectorizableTree.size(),
12627 Idx == 0 ? 0 : Op1.size());
12628 buildTreeRec(Op, Depth, {TE, Idx});
12629 }
12630 };
12631 AddNode(Op1, 0);
12632 AddNode(Op2, 1);
12633 return true;
12634 };
12635
12636 auto AreOnlyConstsWithPHIs = [](ArrayRef<Value *> VL) {
12637 bool AreConsts = false;
12638 for (Value *V : VL) {
12639 if (isa<PoisonValue>(V))
12640 continue;
12641 if (isa<Constant>(V)) {
12642 AreConsts = true;
12643 continue;
12644 }
12645 if (!isa<PHINode>(V))
12646 return false;
12647 }
12648 return AreConsts;
12649 };
12650 if (AreOnlyConstsWithPHIs(VL)) {
12651 LLVM_DEBUG(dbgs() << "SLP: Gathering due to all constants and PHIs.\n");
12652 newGatherTreeEntry(VL, InstructionsState::invalid(), UserTreeIdx);
12653 return;
12654 }
12655
12656 ScalarsVectorizationLegality Legality =
12657 getScalarsVectorizationLegality(VL, Depth, UserTreeIdx);
12658 InstructionsState S = Legality.getInstructionsState();
12659 if (!Legality.isLegal()) {
12660 if (Legality.trySplitVectorize()) {
12661 auto [MainOp, AltOp] = getMainAltOpsNoStateVL(VL);
12662 // Last chance to try to vectorize alternate node.
12663 if (MainOp && AltOp && TrySplitNode(InstructionsState(MainOp, AltOp)))
12664 return;
12665 }
12666 if (Legality.tryToFindDuplicates())
12667 (void)tryToFindDuplicates(VL, ReuseShuffleIndices, *TTI, *TLI, S,
12668 UserTreeIdx, *this);
12669
12670 newGatherTreeEntry(VL, S, UserTreeIdx, ReuseShuffleIndices);
12671 return;
12672 }
12673
12674 // FIXME: investigate if there are profitable cases for VL.size() <= 4.
12675 if (S.isAltShuffle() && TrySplitNode(S))
12676 return;
12677
12678 // Cmp nodes with interchangeable lanes (e.g. x == 0 mixed with x <u C)
12679 // try the split by the original predicates, like the alternate nodes.
12680 if (S.getOpcode() == Instruction::ICmp && !S.isAltShuffle()) {
12681 auto SameOrSwapped = [](const ICmpInst *CI, CmpInst::Predicate P) {
12682 return CI->getPredicate() == P ||
12684 };
12685 ICmpInst *MainI = cast<ICmpInst>(*find_if(VL, IsaPred<ICmpInst>));
12686 auto *AltIt = find_if(VL, [&](Value *V) {
12687 auto *CI = dyn_cast<ICmpInst>(V);
12688 return CI && !SameOrSwapped(CI, MainI->getPredicate());
12689 });
12690 ICmpInst *AltI = AltIt == VL.end() ? nullptr : cast<ICmpInst>(*AltIt);
12691 if (AltI &&
12692 all_of(VL,
12693 [&](Value *V) {
12694 auto *CI = dyn_cast<ICmpInst>(V);
12695 return !CI || SameOrSwapped(CI, MainI->getPredicate()) ||
12696 SameOrSwapped(CI, AltI->getPredicate());
12697 }) &&
12698 TrySplitNode(InstructionsState(MainI, AltI)))
12699 return;
12700 }
12701
12702 // Check that every instruction appears once in this bundle.
12703 if (!tryToFindDuplicates(VL, ReuseShuffleIndices, *TTI, *TLI, S, UserTreeIdx,
12704 *this, /*BuildGatherOnly=*/false)) {
12705 newGatherTreeEntry(VL, S, UserTreeIdx, ReuseShuffleIndices);
12706 return;
12707 }
12708
12709 // Perform specific checks for each particular instruction kind.
12710 bool IsScatterVectorizeUserTE =
12711 UserTreeIdx.UserTE &&
12712 UserTreeIdx.UserTE->State == TreeEntry::ScatterVectorize;
12713 OrdersType CurrentOrder;
12714 SmallVector<Value *> PointerOps;
12715 StridedPtrInfo SPtrInfo;
12716 SmallVector<int> ExpandShuffleMask;
12717 TreeEntry::EntryState State = getScalarsVectorizationState(
12718 S, VL, IsScatterVectorizeUserTE, CurrentOrder, PointerOps, SPtrInfo,
12719 ExpandShuffleMask);
12720 if (State == TreeEntry::NeedToGather) {
12721 newGatherTreeEntry(VL, S, UserTreeIdx, ReuseShuffleIndices);
12722 return;
12723 }
12724
12725 // Check the loop nest. We need to be sure we handle a single loop nest at a
12726 // time to avoid incorrect cost estimation because of the loop aware cost
12727 // model.
12728 if (VectorizableTree.empty()) {
12729 assert(CurrentLoopNest.empty() && "Expected empty loop nest");
12730 // Process the first node? Initial fill of the loop nest.
12731 BasicBlock *Parent = S.getMainOp()->getParent();
12732 if (const Loop *L = LI->getLoopFor(Parent)) {
12734 if (L)
12735 CurrentLoopNest.assign(getLoopNest(L));
12736 }
12737 } else if (!UserTreeIdx ||
12738 UserTreeIdx.UserTE->State == TreeEntry::SplitVectorize ||
12739 UserTreeIdx.UserTE->isGather() ||
12740 UserTreeIdx.UserTE->getMainOp()->getParent() !=
12741 S.getMainOp()->getParent()) {
12742 BasicBlock *Parent = S.getMainOp()->getParent();
12743 if (const Loop *L = LI->getLoopFor(Parent)) {
12744 // Check that the new loop nest shares the same outer structure as the
12745 // tree's current loop nest. Completely disjoint nests (different
12746 // outermost loops) are forced to gather because their scales cannot be
12747 // meaningfully combined. Sibling inner loops (inside a common outer
12748 // loop or outside any loops at all) are allowed: the cost model scales
12749 // each entry by its own loop via getScaleToLoopIterations(), so a tree
12750 // that spans sibling inner loops (e.g. a PHI at their merge block) can
12751 // still be costed correctly. Contract CurrentLoopNest to the longest
12752 // common prefix with the new entry's nest so subsequent entries in yet
12753 // another sibling can also be admitted.
12755 if (L) {
12756 SmallVector<const Loop *> NewLoopNest(getLoopNest(L));
12757 unsigned CommonLen = 0;
12758 for (const auto [L1, L2] : zip(CurrentLoopNest, NewLoopNest)) {
12759 if (L1 != L2)
12760 break;
12761 ++CommonLen;
12762 }
12763 auto ValidateMergedBTCs = [&](unsigned StartDepth) -> bool {
12764 unsigned EndDepth =
12765 std::min<unsigned>(NewLoopNest.size(), MergedLoopBTCs.size());
12766 for (unsigned D = StartDepth; D < EndDepth; ++D) {
12767 const SCEV *Constraint = MergedLoopBTCs[D];
12768 if (!Constraint)
12769 continue;
12770 const SCEV *NewBTC = SE->getBackedgeTakenCount(NewLoopNest[D]);
12771 if (isa<SCEVCouldNotCompute>(NewBTC) || NewBTC != Constraint)
12772 return false;
12773 }
12774 return true;
12775 };
12776 auto BailOutToGather = [&]() {
12778 << "SLP: Sibling loops have different trip counts.\n");
12779 newGatherTreeEntry(VL, S, UserTreeIdx, ReuseShuffleIndices);
12780 };
12781 if (CurrentLoopNest.empty()) {
12782 if (!ValidateMergedBTCs(0)) {
12783 BailOutToGather();
12784 return;
12785 }
12786 CurrentLoopNest.assign(NewLoopNest);
12787 } else if (CommonLen < CurrentLoopNest.size() &&
12788 CommonLen < NewLoopNest.size()) {
12789 // Divergence below the common prefix: the tree now spans sibling
12790 // loops at depth CommonLen. Admitting them into one tree makes
12791 // the profitability decision JOINT across both siblings, so a
12792 // very hot sibling could otherwise let an unprofitable cold
12793 // sibling ride along "for free" (per-entry scaling of the cold
12794 // sibling's entries would be dwarfed by the hot one). Require
12795 // SCEV-proven equal backedge-taken counts for the diverging
12796 // siblings before joining; otherwise force gather.
12797 const Loop *SibA = CurrentLoopNest[CommonLen];
12798 const Loop *SibB = NewLoopNest[CommonLen];
12799 const SCEV *BecA = SE->getBackedgeTakenCount(SibA);
12800 const SCEV *BecB = SE->getBackedgeTakenCount(SibB);
12801 if (isa<SCEVCouldNotCompute>(BecA) || BecA != BecB) {
12802 BailOutToGather();
12803 return;
12804 }
12805 if (!ValidateMergedBTCs(CommonLen + 1)) {
12806 BailOutToGather();
12807 return;
12808 }
12809 if (MergedLoopBTCs.size() <= CommonLen)
12810 MergedLoopBTCs.resize(CommonLen + 1, nullptr);
12811 MergedLoopBTCs[CommonLen] = BecA;
12812 CurrentLoopNest.truncate(CommonLen);
12813 } else if (NewLoopNest.size() > CurrentLoopNest.size()) {
12814 if (!ValidateMergedBTCs(CurrentLoopNest.size())) {
12815 BailOutToGather();
12816 return;
12817 }
12818 CurrentLoopNest.append(
12819 std::next(NewLoopNest.begin(), CurrentLoopNest.size()),
12820 NewLoopNest.end());
12821 }
12822 // Otherwise NewLoopNest is a prefix of CurrentLoopNest: keep as-is.
12823 }
12824 }
12825 }
12826
12827 Instruction *VL0 = S.getMainOp();
12828 BasicBlock *BB = VL0->getParent();
12829 auto &BSRef = BlocksSchedules[BB];
12830 if (!BSRef)
12831 BSRef = std::make_unique<BlockScheduling>(BB);
12832
12833 BlockScheduling &BS = *BSRef;
12834
12835 SetVector<Value *> UniqueValues(llvm::from_range, VL);
12836 std::optional<ScheduleBundle *> BundlePtr =
12837 BS.tryScheduleBundle(UniqueValues.getArrayRef(), this, S, UserTreeIdx);
12838#ifdef EXPENSIVE_CHECKS
12839 // Make sure we didn't break any internal invariants
12840 BS.verify();
12841#endif
12842 if (!BundlePtr || (*BundlePtr && !*BundlePtr.value())) {
12843 LLVM_DEBUG(dbgs() << "SLP: We are not able to schedule this bundle!\n");
12844 // Last chance to try to vectorize alternate node.
12845 if (S.isAltShuffle() && ReuseShuffleIndices.empty() && TrySplitNode(S))
12846 return;
12847 // Last chance to try to vectorize copyable node.
12849 ReuseShuffleIndices.empty()) {
12850 InstructionsState AltS = getSameOpcode(VL, *TLI);
12851 if (AltS && AltS.isAltShuffle() && TrySplitNode(AltS))
12852 return;
12853 }
12854 newGatherTreeEntry(VL, S, UserTreeIdx, ReuseShuffleIndices);
12855 NonScheduledFirst.insert(VL.front());
12856 if (S.getOpcode() == Instruction::Load &&
12857 BS.ScheduleRegionSize < BS.ScheduleRegionSizeLimit)
12859 return;
12860 }
12861 InstructionsCompatibilityAnalysis Analysis(*DT, *DL, *TTI, *TLI);
12862 SmallVector<ValueList> Operands = Analysis.buildOperands(S, VL);
12863 // Flatten associative binary chains into operand columns. Only the peeled
12864 // chain links are required to be single-use (they are erased); the root
12865 // being flattened may have other uses. Skip lanes that are neither chain
12866 // links nor copyable identity leaves. Alternate nodes flatten too, but
12867 // each lane keeps its own opcode on every combine level. Restricted to
12868 // BinaryOperator: isAssociative() is also true for associative intrinsics
12869 // (e.g. smax/smin/umax/umin), which are CallInst, not BinaryOperator, and
12870 // are not supported by the copyable-identity machinery used below
12871 // (ConstantExpr::getBinOpIdentity, isSupportedOpcode,
12872 // isBinOpIdentityConstant).
12873 SmallVector<Value *> ReassocScalars;
12874 // Sign of each flattened operand column (a subtracted leaf is negated).
12875 SmallBitVector NegatedColumns;
12876 // Per-lane subtract markers for flattened alternate nodes.
12877 SmallBitVector SubLanes;
12878 // Cached below (when the peel is kept) so the reorder step further down
12879 // does not need to redo the aligning/scoring work.
12880 SmallVector<ValueList> ReassocAlignedOperands;
12881 // Snapshot of the pre-flatten operand columns, used by both revert points.
12882 SmallVector<ValueList> NaturalTwoColumns;
12883 std::tuple<unsigned, unsigned, unsigned, int> ReassocPeeledQuality;
12884 if (VectorizeReassociatedOps && Operands.size() == 2 &&
12885 all_of(VL, [&](Value *V) {
12886 if (!S.isAltShuffle() && S.isCopyableElement(V))
12887 return true;
12888 auto *I = dyn_cast<BinaryOperator>(V);
12889 return I && isReassocChainLink(I);
12890 })) {
12891 NaturalTwoColumns = Operands;
12892 if (S.isAltShuffle()) {
12893 if (SmallVector<SmallVector<Value *>> Flattened =
12894 scanAltAssociativeOperands(S, *TLI, VL, Operands[0], Operands[1],
12895 ReassocScalars, SubLanes);
12896 !Flattened.empty()) {
12897 Operands.clear();
12898 for (auto &Col : Flattened)
12899 Operands.emplace_back(std::move(Col));
12900 }
12901 } else {
12902 scanAssociativeOperands(S, *DT, *DL, *TTI, *TLI, *this, Operands,
12903 NegatedColumns, ReassocScalars);
12904 }
12905 // Drop flattening unless realigning improves load or broadcast column
12906 // structure; an unimproved peel ties and reverts to natural columns.
12907 if (!ReassocScalars.empty()) {
12908 auto IsNegated = [&](unsigned Lane, unsigned Col) {
12909 return S.isAltShuffle() ? Col > 0 && SubLanes.test(Lane)
12910 : NegatedColumns.test(Col);
12911 };
12912 ReassocAlignedOperands =
12913 alignReassociatedOperandsByKey(Operands, IsNegated, *TLI);
12914 // Alternate nodes compare against the natural two-column form rather
12915 // than the raw peel: the natural form pays one lane-select shuffle per
12916 // level, so the flatten is worth keeping whenever the realigned
12917 // columns improve on the natural ones.
12918 ReassocPeeledQuality = getReassocColumnsQuality(
12919 S.isAltShuffle() ? NaturalTwoColumns : Operands, *this,
12920 S.getOpcode());
12921 // The unique-value count (4th field) is only a tie-break for the
12922 // later reorder-or-not decision, not for this one.
12923 auto DropUniqueCount = [](const auto &Quality) {
12924 return std::make_tuple(std::get<0>(Quality), std::get<1>(Quality),
12925 std::get<2>(Quality));
12926 };
12927 if (DropUniqueCount(getReassocColumnsQuality(ReassocAlignedOperands,
12928 *this, S.getOpcode())) <=
12929 DropUniqueCount(ReassocPeeledQuality)) {
12930 Operands = std::move(NaturalTwoColumns);
12931 ReassocScalars.clear();
12932 }
12933 }
12934 }
12935 // Registers peeled chain links on the node so they are erased with it and
12936 // their scheduling deps are released as reassociated operands.
12937 auto RegisterReassocScalars = [&](TreeEntry *TE) {
12938 for (Value *V : ReassocScalars) {
12939 TE->addReassocScalar(V);
12940 SmallVectorImpl<const TreeEntry *> &Owners =
12941 ReassocScalarToTreeEntries.try_emplace(V).first->second;
12942 if (!is_contained(Owners, TE))
12943 Owners.push_back(TE);
12944 }
12945 };
12946 // A value routed into several columns is consumed by several combines;
12947 // that distorts both the cost and the vector structure (duplicated loads,
12948 // partial masked columns), so prefer the natural two-column shape.
12949 auto HasDupColumnValues = [&]() {
12950 SmallPtrSet<const Value *, 16> ColumnValues;
12951 return any_of(Operands, [&](const ValueList &Col) {
12952 return any_of(Col, [&](const Value *V) {
12953 return !isa<Constant>(V) && !ColumnValues.insert(V).second;
12954 });
12955 });
12956 };
12957 ScheduleBundle Empty;
12958 ScheduleBundle &Bundle = BundlePtr.value() ? *BundlePtr.value() : Empty;
12959 LLVM_DEBUG(dbgs() << "SLP: We are able to schedule this bundle.\n");
12960
12961 unsigned ShuffleOrOp =
12962 S.isAltShuffle() ? (unsigned)Instruction::ShuffleVector : S.getOpcode();
12963 auto CreateOperandNodes = [&](TreeEntry *TE, const auto &Operands) {
12964 // Postpone PHI nodes creation
12965 SmallVector<unsigned> PHIOps;
12966 for (unsigned I : seq<unsigned>(Operands.size())) {
12968 if (Op.empty())
12969 continue;
12970 InstructionsState S = getSameOpcode(Op, *TLI);
12971 if ((!S || S.getOpcode() != Instruction::PHI) || S.isAltShuffle())
12972 buildTreeRec(Op, Depth + 1, {TE, I});
12973 else
12974 PHIOps.push_back(I);
12975 }
12976 for (unsigned I : PHIOps)
12977 buildTreeRec(Operands[I], Depth + 1, {TE, I});
12978 };
12979 switch (ShuffleOrOp) {
12980 case Instruction::PHI: {
12981 TreeEntry *TE =
12982 newTreeEntry(VL, Bundle, S, UserTreeIdx, ReuseShuffleIndices);
12983 LLVM_DEBUG(dbgs() << "SLP: added a new TreeEntry (PHINode).\n";
12984 TE->dump());
12985
12986 TE->setOperands(Operands);
12987 CreateOperandNodes(TE, Operands);
12988 return;
12989 }
12990 case Instruction::ExtractValue:
12991 case Instruction::ExtractElement: {
12992 if (CurrentOrder.empty()) {
12993 LLVM_DEBUG(dbgs() << "SLP: Reusing or shuffling extract sequence.\n");
12994 } else {
12995 LLVM_DEBUG({
12996 dbgs() << "SLP: Reusing or shuffling of reordered extract sequence "
12997 "with order";
12998 for (unsigned Idx : CurrentOrder)
12999 dbgs() << " " << Idx;
13000 dbgs() << "\n";
13001 });
13002 fixupOrderingIndices(CurrentOrder);
13003 }
13004 // Insert new order with initial value 0, if it does not exist,
13005 // otherwise return the iterator to the existing one.
13006 TreeEntry *TE = newTreeEntry(VL, Bundle /*vectorized*/, S, UserTreeIdx,
13007 ReuseShuffleIndices, CurrentOrder);
13008 LLVM_DEBUG(dbgs() << "SLP: added a new TreeEntry "
13009 "(ExtractValueInst/ExtractElementInst).\n";
13010 TE->dump());
13011 // This is a special case, as it does not gather, but at the same time
13012 // we are not extending buildTreeRec() towards the operands.
13013 TE->setOperands(Operands);
13014 if (ShuffleOrOp == Instruction::ExtractValue) {
13015 SmallVector<unsigned> Indices;
13017 if (checkEVsForVecCalls(VL, S, *TLI, Indices, Calls)) {
13018 TE->StructEVIndices = std::move(Indices);
13019 buildTreeRec(Operands.front(), Depth + 1, {TE, 0});
13020 }
13021 }
13022 return;
13023 }
13024 case Instruction::InsertValue:
13025 case Instruction::InsertElement: {
13026 assert(ReuseShuffleIndices.empty() && "All inserts should be unique");
13027
13028 auto OrdCompare = [](const std::pair<int, int> &P1,
13029 const std::pair<int, int> &P2) {
13030 return P1.first > P2.first;
13031 };
13032 PriorityQueue<std::pair<int, int>, SmallVector<std::pair<int, int>>,
13033 decltype(OrdCompare)>
13034 Indices(OrdCompare);
13035 for (int I = 0, E = VL.size(); I < E; ++I) {
13036 unsigned Idx = *getElementIndex(VL[I]);
13037 Indices.emplace(Idx, I);
13038 }
13039 OrdersType CurrentOrder(VL.size(), VL.size());
13040 bool IsIdentity = true;
13041 for (int I = 0, E = VL.size(); I < E; ++I) {
13042 CurrentOrder[Indices.top().second] = I;
13043 IsIdentity &= Indices.top().second == I;
13044 Indices.pop();
13045 }
13046 if (IsIdentity)
13047 CurrentOrder.clear();
13048 TreeEntry *TE = newTreeEntry(VL, Bundle /*vectorized*/, S, UserTreeIdx,
13049 {}, CurrentOrder);
13050 LLVM_DEBUG(dbgs() << "SLP: added a new TreeEntry (InsertElementInst).\n";
13051 TE->dump());
13052
13053 TE->setOperands(Operands);
13054 buildTreeRec(TE->getOperand(1), Depth + 1, {TE, 1});
13055 return;
13056 }
13057 case Instruction::Load: {
13058 // Check that a vectorized load would load the same memory as a scalar
13059 // load. For example, we don't want to vectorize loads that are smaller
13060 // than 8-bit. Even though we have a packed struct {<i2, i2, i2, i2>} LLVM
13061 // treats loading/storing it as an i8 struct. If we vectorize loads/stores
13062 // from such a struct, we read/write packed bits disagreeing with the
13063 // unvectorized version.
13064 TreeEntry *TE = nullptr;
13065 fixupOrderingIndices(CurrentOrder);
13066 switch (State) {
13067 case TreeEntry::Vectorize:
13068 TE = newTreeEntry(VL, Bundle /*vectorized*/, S, UserTreeIdx,
13069 ReuseShuffleIndices, CurrentOrder, InterleaveFactor);
13070 if (CurrentOrder.empty())
13071 LLVM_DEBUG(dbgs() << "SLP: added a new TreeEntry (LoadInst).\n";
13072 TE->dump());
13073 else
13075 << "SLP: added a new TreeEntry (jumbled LoadInst).\n";
13076 TE->dump());
13077 break;
13078 case TreeEntry::CompressVectorize:
13079 // Vectorizing non-consecutive loads with (masked)load + compress.
13080 TE = newTreeEntry(VL, TreeEntry::CompressVectorize, Bundle, S,
13081 UserTreeIdx, ReuseShuffleIndices, CurrentOrder);
13082 LLVM_DEBUG(
13083 dbgs()
13084 << "SLP: added a new TreeEntry (masked LoadInst + compress).\n";
13085 TE->dump());
13086 break;
13087 case TreeEntry::StridedVectorize:
13088 // Vectorizing non-consecutive loads with `llvm.masked.gather`.
13089 TE = newTreeEntry(VL, TreeEntry::StridedVectorize, Bundle, S,
13090 UserTreeIdx, ReuseShuffleIndices, CurrentOrder);
13091 TreeEntryToStridedPtrInfoMap[TE] = SPtrInfo;
13092 LLVM_DEBUG(dbgs() << "SLP: added a new TreeEntry (strided LoadInst).\n";
13093 TE->dump());
13094 break;
13095 case TreeEntry::ScatterVectorize:
13096 // Vectorizing non-consecutive loads with `llvm.masked.gather`.
13097 TE = newTreeEntry(VL, TreeEntry::ScatterVectorize, Bundle, S,
13098 UserTreeIdx, ReuseShuffleIndices);
13099 LLVM_DEBUG(
13100 dbgs()
13101 << "SLP: added a new TreeEntry (non-consecutive LoadInst).\n";
13102 TE->dump());
13103 break;
13104 case TreeEntry::BlendedLoadVectorize: {
13105 // Two masked loads from the candidate bases, blended by the per-lane
13106 // select conditions. The conditions are added as the operand node, so
13107 // the blend mask is vectorized through the tree.
13108 TE = newTreeEntry(VL, TreeEntry::BlendedLoadVectorize, Bundle, S,
13109 UserTreeIdx, ReuseShuffleIndices);
13110 LLVM_DEBUG(dbgs() << "SLP: added a new TreeEntry (blended LoadInst).\n";
13111 TE->dump());
13112 Value *TrueBase = nullptr;
13113 Value *FalseBase = nullptr;
13114 SmallVector<Value *> Conditions;
13115 [[maybe_unused]] bool Found = isSelectedBaseLoad(
13116 VL0->getType(), PointerOps, *DL, TrueBase, FalseBase, Conditions);
13117 assert(Found && "Expected a valid blended-load pattern.");
13118 Operands.assign(1, ValueList(Conditions.begin(), Conditions.end()));
13119 TE->setOperands(Operands);
13120 buildTreeRec(TE->getOperand(0), Depth + 1, {TE, 0});
13121 return;
13122 }
13123 case TreeEntry::ExpandVectorize:
13124 case TreeEntry::CombinedVectorize:
13125 case TreeEntry::SplitVectorize:
13126 case TreeEntry::NeedToGather:
13127 llvm_unreachable("Unexpected loads state.");
13128 }
13129 if (!CurrentOrder.empty() && State != TreeEntry::ScatterVectorize) {
13130 assert(Operands.size() == 1 && "Expected a single operand only");
13131 SmallVector<int> Mask;
13132 inversePermutation(CurrentOrder, Mask);
13133 reorderScalars(Operands.front(), Mask);
13134 }
13135 TE->setOperands(Operands);
13136 if (State == TreeEntry::ScatterVectorize)
13137 buildTreeRec(PointerOps, Depth + 1, {TE, 0});
13138 return;
13139 }
13140 case Instruction::ZExt:
13141 case Instruction::SExt:
13142 case Instruction::FPToUI:
13143 case Instruction::FPToSI:
13144 case Instruction::FPExt:
13145 case Instruction::PtrToInt:
13146 case Instruction::PtrToAddr:
13147 case Instruction::IntToPtr:
13148 case Instruction::SIToFP:
13149 case Instruction::UIToFP:
13150 case Instruction::Trunc:
13151 case Instruction::FPTrunc:
13152 case Instruction::BitCast: {
13153 auto [PrevMaxBW, PrevMinBW] = CastMaxMinBWSizes.value_or(
13154 std::make_pair(std::numeric_limits<unsigned>::min(),
13155 std::numeric_limits<unsigned>::max()));
13156 if (ShuffleOrOp == Instruction::ZExt ||
13157 ShuffleOrOp == Instruction::SExt) {
13158 CastMaxMinBWSizes = std::make_pair(
13159 std::max<unsigned>(DL->getTypeSizeInBits(VL0->getType()),
13160 PrevMaxBW),
13161 std::min<unsigned>(
13162 DL->getTypeSizeInBits(VL0->getOperand(0)->getType()),
13163 PrevMinBW));
13164 } else if (ShuffleOrOp == Instruction::Trunc) {
13165 CastMaxMinBWSizes = std::make_pair(
13166 std::max<unsigned>(
13167 DL->getTypeSizeInBits(VL0->getOperand(0)->getType()),
13168 PrevMaxBW),
13169 std::min<unsigned>(DL->getTypeSizeInBits(VL0->getType()),
13170 PrevMinBW));
13171 }
13172 TreeEntry *TE = newTreeEntry(VL, Bundle /*vectorized*/, S, UserTreeIdx,
13173 ReuseShuffleIndices);
13174 LLVM_DEBUG(dbgs() << "SLP: added a new TreeEntry (CastInst).\n";
13175 TE->dump());
13176
13177 TE->setOperands(Operands);
13178 for (unsigned I : seq<unsigned>(VL0->getNumOperands()))
13179 buildTreeRec(TE->getOperand(I), Depth, {TE, I});
13180 if (ShuffleOrOp == Instruction::Trunc) {
13181 ExtraBitWidthNodes.insert(getOperandEntry(TE, 0)->Idx);
13182 } else if (ShuffleOrOp == Instruction::SIToFP ||
13183 ShuffleOrOp == Instruction::UIToFP) {
13184 unsigned NumSignBits =
13185 ComputeNumSignBits(VL0->getOperand(0), *DL, AC, nullptr, DT);
13186 if (auto *OpI = dyn_cast<Instruction>(VL0->getOperand(0))) {
13187 APInt Mask = DB->getDemandedBits(OpI);
13188 NumSignBits = std::max(NumSignBits, Mask.countl_zero());
13189 }
13190 if (NumSignBits * 2 >=
13191 DL->getTypeSizeInBits(VL0->getOperand(0)->getType()))
13192 ExtraBitWidthNodes.insert(getOperandEntry(TE, 0)->Idx);
13193 }
13194 return;
13195 }
13196 case Instruction::ICmp:
13197 case Instruction::FCmp: {
13198 // Check that all of the compares have the same predicate.
13199 CmpInst::Predicate P0 = cast<CmpInst>(VL0)->getPredicate();
13200 TreeEntry *TE = newTreeEntry(VL, Bundle /*vectorized*/, S, UserTreeIdx,
13201 ReuseShuffleIndices);
13202 LLVM_DEBUG(dbgs() << "SLP: added a new TreeEntry (CmpInst).\n";
13203 TE->dump());
13204
13205 VLOperands Ops(VL, Operands, S, *this);
13206 if (cast<CmpInst>(VL0)->isCommutative()) {
13207 // Commutative predicate - collect + sort operands of the instructions
13208 // so that each side is more likely to have the same opcode.
13210 "Commutative Predicate mismatch");
13211 Ops.reorder();
13212 Operands.front() = Ops.getVL(0);
13213 Operands.back() = Ops.getVL(1);
13214 } else {
13215 // Collect operands - commute if it uses the swapped predicate.
13216 // Lanes interchangeable with P0 (e.g. x == 0 in an x <u C bundle)
13217 // already have their operands adjusted, no need to commute them.
13218 for (auto [Idx, V] : enumerate(VL)) {
13219 if (isa<PoisonValue>(V))
13220 continue;
13221 auto *Cmp = cast<CmpInst>(V);
13222 if (Cmp->getPredicate() != P0 &&
13224 std::swap(Operands.front()[Idx], Operands.back()[Idx]);
13225 }
13226 }
13227 TE->setOperands(Operands);
13228 buildTreeRec(Operands.front(), Depth, {TE, 0});
13229 buildTreeRec(Operands.back(), Depth, {TE, 1});
13230 if (ShuffleOrOp == Instruction::ICmp) {
13231 unsigned NumSignBits0 =
13232 ComputeNumSignBits(VL0->getOperand(0), *DL, AC, nullptr, DT);
13233 if (NumSignBits0 * 2 >=
13234 DL->getTypeSizeInBits(VL0->getOperand(0)->getType()))
13235 ExtraBitWidthNodes.insert(getOperandEntry(TE, 0)->Idx);
13236 unsigned NumSignBits1 =
13237 ComputeNumSignBits(VL0->getOperand(1), *DL, AC, nullptr, DT);
13238 if (NumSignBits1 * 2 >=
13239 DL->getTypeSizeInBits(VL0->getOperand(1)->getType()))
13240 ExtraBitWidthNodes.insert(getOperandEntry(TE, 1)->Idx);
13241 }
13242 return;
13243 }
13244 case Instruction::Select:
13245 case Instruction::FNeg:
13246 case Instruction::Add:
13247 case Instruction::FAdd:
13248 case Instruction::Sub:
13249 case Instruction::FSub:
13250 case Instruction::Mul:
13251 case Instruction::FMul:
13252 case Instruction::UDiv:
13253 case Instruction::SDiv:
13254 case Instruction::FDiv:
13255 case Instruction::URem:
13256 case Instruction::SRem:
13257 case Instruction::FRem:
13258 case Instruction::Shl:
13259 case Instruction::LShr:
13260 case Instruction::AShr:
13261 case Instruction::And:
13262 case Instruction::Or:
13263 case Instruction::Xor:
13264 case Instruction::Freeze: {
13265 TreeEntry *TE = newTreeEntry(VL, Bundle /*vectorized*/, S, UserTreeIdx,
13266 ReuseShuffleIndices);
13267 LLVM_DEBUG(
13268 dbgs() << "SLP: added a new TreeEntry "
13269 "(SelectInst/UnaryOperator/BinaryOperator/FreezeInst).\n";
13270 TE->dump());
13271
13272 if (!ReassocScalars.empty()) {
13273 // Realign columns by value family (cached above as
13274 // ReassocAlignedOperands), then let VLOperands polish the order,
13275 // keeping the polish only if the column-quality score does not regress
13276 // vs the peeled order. That polish is quadratic in the column count, so
13277 // past ReassocReorderColumnLimit keep the realigned seed, which already
13278 // groups the vectorizable columns. The polish swaps values between
13279 // columns per lane, which must not mix added and subtracted leaves in
13280 // one column, so signed nodes polish each sign group separately.
13281 if (Operands.size() <= ReassocReorderColumnLimit) {
13282 SmallVector<ValueList> Reordered = ReassocAlignedOperands;
13283 SmallVector<unsigned> GroupIds[2];
13284 for (unsigned I : seq<unsigned>(NegatedColumns.size()))
13285 GroupIds[NegatedColumns[I]].push_back(I);
13286 for (ArrayRef<unsigned> Group : GroupIds) {
13287 if (Group.size() <= 1)
13288 continue;
13290 Group, [&](unsigned I) { return ReassocAlignedOperands[I]; });
13291 VLOperands Ops(GroupCols, VL0->getParent(), *this);
13292 Ops.reorder();
13293 for (unsigned Pos : seq<unsigned>(Group.size()))
13294 Reordered[Group[Pos]] = Ops.getVL(Pos);
13295 }
13296 if (getReassocColumnsQuality(Reordered, *this, S.getOpcode()) >=
13297 ReassocPeeledQuality)
13298 Operands = std::move(Reordered);
13299 else
13300 LLVM_DEBUG(dbgs() << "SLP: reassociation reorder loses column "
13301 "structure, keeping the natural operand "
13302 "order.\n");
13303 } else {
13304 Operands = std::move(ReassocAlignedOperands);
13305 }
13306 if (HasDupColumnValues()) {
13307 Operands = std::move(NaturalTwoColumns);
13308 ReassocScalars.clear();
13309 }
13310 }
13311 if (!ReassocScalars.empty())
13312 RegisterReassocScalars(TE);
13313 else if (isa<BinaryOperator>(VL0) && isCommutative(VL0)) {
13314 VLOperands Ops(VL, Operands, S, *this);
13315 Ops.reorder();
13316 Operands[0] = Ops.getVL(0);
13317 Operands[1] = Ops.getVL(1);
13318 }
13319 TE->setOperands(Operands);
13320 if (!ReassocScalars.empty() && NegatedColumns.any())
13321 TE->setReassocNegatedOps(NegatedColumns);
13322 for (unsigned I : seq<unsigned>(TE->getNumOperands()))
13323 buildTreeRec(TE->getOperand(I), Depth + 1, {TE, I});
13324 return;
13325 }
13326 case Instruction::GetElementPtr: {
13327 TreeEntry *TE = newTreeEntry(VL, Bundle /*vectorized*/, S, UserTreeIdx,
13328 ReuseShuffleIndices);
13329 LLVM_DEBUG(dbgs() << "SLP: added a new TreeEntry (GetElementPtrInst).\n";
13330 TE->dump());
13331 TE->setOperands(Operands);
13332
13333 for (unsigned I = 0, Ops = Operands.size(); I < Ops; ++I)
13334 buildTreeRec(Operands[I], Depth + 1, {TE, I});
13335 return;
13336 }
13337 case Instruction::Store: {
13338 assert(CurrentOrder.empty() &&
13339 "Expected ordered store during tree building");
13340 if (State == TreeEntry::StridedVectorize) {
13341 TreeEntry *TE =
13342 newTreeEntry(VL, TreeEntry::StridedVectorize, Bundle, S,
13343 UserTreeIdx, ReuseShuffleIndices, CurrentOrder);
13344 TreeEntryToStridedPtrInfoMap[TE] = SPtrInfo;
13345 LLVM_DEBUG(
13346 dbgs() << "SLP: added a new TreeEntry (strided StoreInst).\n";
13347 TE->dump());
13348 TE->setOperands(Operands);
13349 buildTreeRec(TE->getOperand(0), Depth + 1, {TE, 0});
13350 return;
13351 }
13352 if (State == TreeEntry::ExpandVectorize) {
13353 assert(ReuseShuffleIndices.empty() &&
13354 "Expected no reuse shuffle for an expanded masked store.");
13355 TreeEntry *TE =
13356 newTreeEntry(VL, TreeEntry::ExpandVectorize, Bundle, S, UserTreeIdx,
13357 ExpandShuffleMask, CurrentOrder);
13358 TreeEntryToStridedPtrInfoMap[TE] = SPtrInfo;
13359 LLVM_DEBUG(
13360 dbgs()
13361 << "SLP: added a new TreeEntry (expanded masked StoreInst).\n";
13362 TE->dump());
13363 TE->setOperands(Operands);
13364 buildTreeRec(TE->getOperand(0), Depth + 1, {TE, 0});
13365 return;
13366 }
13367 TreeEntry *TE = newTreeEntry(VL, Bundle /*vectorized*/, S, UserTreeIdx,
13368 ReuseShuffleIndices, CurrentOrder);
13369 LLVM_DEBUG(dbgs() << "SLP: added a new TreeEntry (StoreInst).\n";
13370 TE->dump());
13371 TE->setOperands(Operands);
13372 buildTreeRec(TE->getOperand(0), Depth + 1, {TE, 0});
13373 return;
13374 }
13375 case Instruction::Call: {
13376 // Check if the calls are all to the same vectorizable intrinsic or
13377 // library function.
13378 CallInst *CI = cast<CallInst>(VL0);
13380
13381 TreeEntry *TE = newTreeEntry(VL, Bundle /*vectorized*/, S, UserTreeIdx,
13382 ReuseShuffleIndices);
13383 LLVM_DEBUG(dbgs() << "SLP: added a new TreeEntry (CallInst).\n";
13384 TE->dump());
13385 if (isCommutative(VL0)) {
13386 VLOperands Ops(VL, Operands, S, *this);
13387 Ops.reorder();
13388 Operands[0] = Ops.getVL(0);
13389 Operands[1] = Ops.getVL(1);
13390 }
13391 TE->setOperands(Operands);
13392 for (unsigned I : seq<unsigned>(CI->arg_size())) {
13393 // For scalar operands no need to create an entry since no need to
13394 // vectorize it.
13396 continue;
13397 buildTreeRec(TE->getOperand(I), Depth + 1, {TE, I});
13398 }
13399 return;
13400 }
13401 case Instruction::ShuffleVector: {
13402 TreeEntry *TE = newTreeEntry(VL, Bundle /*vectorized*/, S, UserTreeIdx,
13403 ReuseShuffleIndices);
13404 if (S.isAltShuffle()) {
13405 LLVM_DEBUG(dbgs() << "SLP: added a new TreeEntry (isAltShuffle).\n";
13406 TE->dump());
13407 } else {
13408 assert(SLPReVec && "Only supported by REVEC.");
13409 LLVM_DEBUG(
13410 dbgs() << "SLP: added a new TreeEntry (ShuffleVectorInst).\n";
13411 TE->dump());
13412 }
13413
13414 // Reorder operands if reordering would enable vectorization.
13415 auto *CI = dyn_cast<CmpInst>(VL0);
13416 if (CI && any_of(VL, [](Value *V) {
13417 return !isa<PoisonValue>(V) && !cast<CmpInst>(V)->isCommutative();
13418 })) {
13419 auto *MainCI = cast<CmpInst>(S.getMainOp());
13420 auto *AltCI = cast<CmpInst>(S.getAltOp());
13421 CmpInst::Predicate MainP = MainCI->getPredicate();
13422 CmpInst::Predicate AltP = AltCI->getPredicate();
13423 assert(MainP != AltP &&
13424 "Expected different main/alternate predicates.");
13425 // Collect operands - commute if it uses the swapped predicate or
13426 // alternate operation.
13427 for (auto [Idx, V] : enumerate(VL)) {
13428 if (isa<PoisonValue>(V))
13429 continue;
13430 auto *Cmp = cast<CmpInst>(V);
13431
13432 if (isAlternateInstruction(Cmp, MainCI, AltCI, *TLI)) {
13433 if (AltP == CmpInst::getSwappedPredicate(Cmp->getPredicate()))
13434 std::swap(Operands.front()[Idx], Operands.back()[Idx]);
13435 } else {
13436 if (MainP == CmpInst::getSwappedPredicate(Cmp->getPredicate()))
13437 std::swap(Operands.front()[Idx], Operands.back()[Idx]);
13438 }
13439 }
13440 TE->setOperands(Operands);
13441 buildTreeRec(Operands.front(), Depth + 1, {TE, 0});
13442 buildTreeRec(Operands.back(), Depth + 1, {TE, 1});
13443 return;
13444 }
13445
13446 if (!ReassocScalars.empty()) {
13447 // Peeled alternate chains take the realigned columns; the operand
13448 // reorder below does not preserve the per-lane sign constraints.
13449 Operands = std::move(ReassocAlignedOperands);
13450 if (HasDupColumnValues()) {
13451 Operands = std::move(NaturalTwoColumns);
13452 ReassocScalars.clear();
13453 }
13454 }
13455 if (ReassocScalars.empty() && (isa<BinaryOperator>(VL0) || CI)) {
13456 VLOperands Ops(VL, Operands, S, *this);
13457 Ops.reorder();
13458 Operands[0] = Ops.getVL(0);
13459 Operands[1] = Ops.getVL(1);
13460 }
13461 if (!ReassocScalars.empty())
13462 RegisterReassocScalars(TE);
13463 TE->setOperands(Operands);
13464 for (unsigned I : seq<unsigned>(TE->getNumOperands()))
13465 buildTreeRec(TE->getOperand(I), Depth + 1, {TE, I});
13466 return;
13467 }
13468 default:
13469 break;
13470 }
13471 llvm_unreachable("Unexpected vectorization of the instructions.");
13472}
13473
13474unsigned BoUpSLP::canMapToVector(Type *T) const {
13475 unsigned N = 1;
13476 Type *EltTy = T;
13477
13479 if (EltTy->isEmptyTy())
13480 return 0;
13481 if (auto *ST = dyn_cast<StructType>(EltTy)) {
13482 // Check that struct is homogeneous.
13483 for (const auto *Ty : ST->elements())
13484 if (Ty != *ST->element_begin())
13485 return 0;
13486 N *= ST->getNumElements();
13487 EltTy = *ST->element_begin();
13488 } else if (auto *AT = dyn_cast<ArrayType>(EltTy)) {
13489 N *= AT->getNumElements();
13490 EltTy = AT->getElementType();
13491 } else {
13492 auto *VT = cast<FixedVectorType>(EltTy);
13493 N *= VT->getNumElements();
13494 EltTy = VT->getElementType();
13495 }
13496 }
13497
13498 if (!isValidElementType(EltTy, SLPReVec))
13499 return 0;
13500 size_t VTSize = DL->getTypeStoreSizeInBits(getWidenedType(EltTy, N));
13501 if (VTSize < MinVecRegSize || VTSize > MaxVecRegSize ||
13502 VTSize != DL->getTypeStoreSizeInBits(T))
13503 return 0;
13504 return N;
13505}
13506
13507bool BoUpSLP::canVectorStoreInsertValue(const TreeEntry *E) const {
13508 if (E->getOpcode() != Instruction::InsertValue ||
13509 E->State != TreeEntry::Vectorize)
13510 return false;
13511
13512 bool HasStore = false;
13513 for (Value *V : E->Scalars) {
13514 auto *IV = dyn_cast<InsertValueInst>(V);
13515 if (!IV || isDeleted(IV))
13516 return false;
13517
13518 bool HasExternalUser = false;
13519 for (User *U : IV->users()) {
13520 if (auto *UI = dyn_cast<Instruction>(U); UI && isDeleted(UI))
13521 continue;
13522 if (is_contained(E->Scalars, U))
13523 continue;
13524 HasExternalUser = true;
13525 // Only a plain (non-volatile, non-atomic) store may consume the vector
13526 // directly. Volatile/atomic stores must keep their original aggregate
13527 // type and access semantics, so fall back to the store + load roundtrip.
13528 auto *SI = dyn_cast<StoreInst>(U);
13529 if (!SI || !SI->isSimple())
13530 return false;
13531 HasStore = true;
13532 }
13533 if (HasExternalUser && !IV->hasOneUse())
13534 return false;
13535 }
13536 return HasStore;
13537}
13538
13540 Value *VL0 = E->getMainOp();
13541 if (E->getOpcode() == Instruction::InsertElement)
13542 return cast<FixedVectorType>(VL0->getType());
13543 assert(E->getOpcode() == Instruction::InsertValue &&
13544 "Expected InsertElement or InsertValue node.");
13545 unsigned MaxIdx = E->Scalars.size() - 1;
13546 for (Value *V : E->Scalars) {
13547 auto *I = dyn_cast<InsertValueInst>(V);
13548 if (!I)
13549 continue;
13550 MaxIdx = std::max(MaxIdx, I->getIndices().front());
13551 }
13552 return cast<FixedVectorType>(
13553 getWidenedType(getValueType(VL0, SLPReVec), MaxIdx + 1));
13554}
13555
13556bool BoUpSLP::canReuseExtract(ArrayRef<Value *> VL,
13557 SmallVectorImpl<unsigned> &CurrentOrder,
13558 bool ResizeAllowed) const {
13560 assert(It != VL.end() && "Expected at least one extract instruction.");
13561 auto *E0 = cast<Instruction>(*It);
13562 // Check if all of the extracts come from the same vector and from the
13563 // correct offset.
13564 Value *Vec = E0->getOperand(0);
13565
13566 CurrentOrder.clear();
13567
13568 // We have to extract from a vector/aggregate with the same number of elements.
13569 unsigned NElts;
13570 if (E0->getOpcode() == Instruction::ExtractValue) {
13571 NElts = canMapToVector(Vec->getType());
13572 if (!NElts)
13573 return false;
13574 // Check if load can be rewritten as load of vector.
13575 LoadInst *LI = dyn_cast<LoadInst>(Vec);
13576 if (!LI || !LI->isSimple() || !LI->hasNUses(VL.size()))
13577 return false;
13578 } else {
13579 NElts = cast<FixedVectorType>(Vec->getType())->getNumElements();
13580 }
13581
13582 unsigned E = VL.size();
13583 if (!ResizeAllowed && NElts != E)
13584 return false;
13585 SmallVector<int> Indices(E, PoisonMaskElem);
13586 unsigned MinIdx = NElts, MaxIdx = 0;
13587 for (auto [I, V] : enumerate(VL)) {
13588 // Non-extract lanes (copyable elements modeled on an extract main op, or
13589 // undefs) are treated as holes.
13591 continue;
13592 auto *Inst = cast<Instruction>(V);
13593 if (Inst->getOperand(0) != Vec)
13594 return false;
13595 if (auto *EE = dyn_cast<ExtractElementInst>(Inst))
13596 if (isa<UndefValue>(EE->getIndexOperand()))
13597 continue;
13598 std::optional<unsigned> Idx = getExtractIndex(Inst);
13599 if (!Idx)
13600 return false;
13601 const unsigned ExtIdx = *Idx;
13602 if (ExtIdx >= NElts)
13603 continue;
13604 Indices[I] = ExtIdx;
13605 if (MinIdx > ExtIdx)
13606 MinIdx = ExtIdx;
13607 if (MaxIdx < ExtIdx)
13608 MaxIdx = ExtIdx;
13609 }
13610 if (MaxIdx - MinIdx + 1 > E)
13611 return false;
13612 if (MaxIdx + 1 <= E)
13613 MinIdx = 0;
13614
13615 // Check that all of the indices extract from the correct offset.
13616 bool ShouldKeepOrder = true;
13617 // Assign to all items the initial value E + 1 so we can check if the extract
13618 // instruction index was used already.
13619 // Also, later we can check that all the indices are used and we have a
13620 // consecutive access in the extract instructions, by checking that no
13621 // element of CurrentOrder still has value E + 1.
13622 CurrentOrder.assign(E, E);
13623 for (unsigned I = 0; I < E; ++I) {
13624 if (Indices[I] == PoisonMaskElem)
13625 continue;
13626 const unsigned ExtIdx = Indices[I] - MinIdx;
13627 if (CurrentOrder[ExtIdx] != E) {
13628 CurrentOrder.clear();
13629 return false;
13630 }
13631 ShouldKeepOrder &= ExtIdx == I;
13632 CurrentOrder[ExtIdx] = I;
13633 }
13634 if (ShouldKeepOrder)
13635 CurrentOrder.clear();
13636
13637 return ShouldKeepOrder;
13638}
13639
13640bool BoUpSLP::areAllUsersVectorized(
13641 Instruction *I, const SmallDenseSet<Value *> *VectorizedVals) const {
13642 return (I->hasOneUse() && (!VectorizedVals || VectorizedVals->contains(I))) ||
13643 all_of(I->users(), [this](User *U) {
13644 return isVectorized(U) || isVectorLikeInstWithConstOps(U) ||
13645 (isa<ExtractElementInst>(U) && MustGather.contains(U));
13646 });
13647}
13648
13650 const InstructionsState &S,
13651 DominatorTree &DT, const DataLayout &DL,
13652 TargetTransformInfo &TTI,
13653 const TargetLibraryInfo &TLI,
13654 const TTI::TargetCostKind CostKind);
13655
13656uint64_t BoUpSLP::getNumScalarInsts(bool HasTreeLoop) {
13657 uint64_t Total = 0;
13658 for (const std::unique_ptr<TreeEntry> &Ptr : VectorizableTree) {
13659 const TreeEntry &TE = *Ptr;
13660 if (DeletedNodes.contains(&TE))
13661 continue;
13662 // CombinedVectorize entries (e.g. the fmul child of an FMulAdd, or the
13663 // cmp child of a MinMax select) are absorbed into the parent on both
13664 // scalar and vector sides. The backend fuses fadd+fmul -> fma and
13665 // select+cmp -> smin/smax even for scalar code, so skip to avoid
13666 // double-counting. Checked before the scale lookup below: some of
13667 // these entries started out as constant-only gather nodes and have no
13668 // valid instruction state to key the loop-nest scale off of.
13669 if (TE.State == TreeEntry::CombinedVectorize)
13670 continue;
13671 uint64_t Scale = getEntryEffectiveScale(TE);
13672 if (HasTreeLoop && Scale <= 1)
13673 continue;
13674 unsigned Count = 0;
13675 if (TE.isGather() || TransformedToGatherNodes.contains(&TE)) {
13676 // Count extractelement scalars in gathers - they exist in the scalar
13677 // code regardless of vectorization. ExtractElement instructions
13678 // become free when the vector input is used directly.
13679 for (Value *V : TE.Scalars)
13681 ++Count;
13683 continue;
13684 }
13685 // Each vectorize entry represents a bundle of scalar instructions.
13686 // Count per-entry without cross-entry deduplication, since shared
13687 // scalars across entries still represent separate work in scalar code.
13688 for (Value *V : TE.Scalars) {
13689 if (!isa<Instruction>(V) ||
13690 (TE.hasCopyableElements() && TE.isCopyableElement(V)))
13691 continue;
13692 ++Count;
13693 // Calculate calls/divs/rems twice, they may cost higher, so better to
13694 // include their count twice to mimic slightly real cost here.
13695 auto *I = dyn_cast<Instruction>(V);
13696 if (I && (I->isIntDivRem() || I->isFPDivRem()))
13697 ++Count;
13698 if (auto *CI = dyn_cast<CallInst>(V)) {
13700 if (!isTriviallyVectorizable(BaseID))
13701 ++Count;
13702 }
13703 }
13704 // Count peeled intermediates in the scalar baseline (not in Scalars).
13705 Count += TE.getReassocScalars().size();
13706 // Even when the whole node is not combined, individual scalar
13707 // instructions may be fused by the backend. Each fused pair (e.g.
13708 // fadd+fmul -> fma, select+cmp -> smin/smax) becomes a single scalar
13709 // instruction, absorbing the operand instruction. Subtract 1 for each
13710 // such match to avoid over-counting the scalar side.
13711 if (TE.CombinedOp == TreeEntry::NotCombinedOp && TE.hasState()) {
13712 unsigned Opcode = TE.getOpcode();
13713 if (Opcode == Instruction::Select) {
13714 for (Value *V : TE.Scalars) {
13715 if (TE.hasCopyableElements() && TE.isCopyableElement(V))
13716 continue;
13717 auto *SI = dyn_cast<SelectInst>(V);
13718 if (!SI)
13719 continue;
13720 auto [ID, _] = canConvertToMinOrMaxIntrinsic({V});
13721 if (ID != Intrinsic::not_intrinsic) {
13722 assert(Count > 0 && "Underflow in scalar inst count (minmax)");
13723 --Count;
13724 }
13725 }
13726 } else if (Opcode == Instruction::FAdd || Opcode == Instruction::FSub) {
13727 for (Value *V : TE.Scalars) {
13728 if (TE.hasCopyableElements() && TE.isCopyableElement(V))
13729 continue;
13730 auto *I = dyn_cast<Instruction>(V);
13731 if (!I || (TE.isAltShuffle() && I->getOpcode() != Instruction::FAdd &&
13732 I->getOpcode() != Instruction::FSub))
13733 continue;
13734 if (canConvertToFMA(I, InstructionsState(I, I), *DT, *DL, *TTI, *TLI,
13735 CostKind)
13736 .isValid()) {
13737 assert(Count > 0 && "Underflow in scalar inst count (fma)");
13738 --Count;
13739 }
13740 }
13741 }
13742 }
13744 }
13745 return Total;
13746}
13747
13748uint64_t BoUpSLP::getNumVectorInsts(bool HasTreeLoop) {
13749 uint64_t Total = 0;
13750 // Source vector -> max scale among the gather entries sharing it, so the
13751 // combined shufflevector is still weighted like an in-loop entry below.
13752 SmallDenseMap<Value *, uint64_t, 4> GatherExtractSourceVecs;
13753 for (const std::unique_ptr<TreeEntry> &Ptr : VectorizableTree) {
13754 const TreeEntry &TE = *Ptr;
13755 if (DeletedNodes.contains(&TE))
13756 continue;
13757 if (TE.State == TreeEntry::CombinedVectorize)
13758 continue;
13759 uint64_t Scale = getEntryEffectiveScale(TE);
13760 if (HasTreeLoop && Scale <= 1)
13761 continue;
13762 unsigned Count = 0;
13763 if (TE.isGather() || TransformedToGatherNodes.contains(&TE)) {
13764 if (TE.hasState()) {
13765 if (const TreeEntry *E =
13766 getSameValuesTreeEntry(TE.getMainOp(), TE.Scalars);
13767 E && E != &TE && E->getVectorFactor() == TE.getVectorFactor())
13768 continue;
13769 SmallVector<Value *> RevScalars(TE.Scalars.rbegin(), TE.Scalars.rend());
13770 if (const TreeEntry *E =
13771 getSameValuesTreeEntry(TE.getMainOp(), RevScalars);
13772 E && E->getVectorFactor() == TE.getVectorFactor()) {
13773 Total = SaturatingAdd(Total, Scale);
13774 continue;
13775 }
13776 }
13777 // ExtractElement gathers from the same source vector become a single
13778 // shufflevector. Collect source vectors globally across all gather
13779 // entries and count once at the end.
13780 if (all_of(TE.Scalars,
13782 for (Value *V : TE.Scalars)
13783 if (auto *EE = dyn_cast<ExtractElementInst>(V)) {
13784 uint64_t &VecScale =
13785 GatherExtractSourceVecs.try_emplace(EE->getVectorOperand(), 0)
13786 .first->second;
13787 VecScale = std::max(VecScale, Scale);
13788 }
13789 } else {
13790 for (Value *V : TE.Scalars) {
13791 if (!isConstant(V))
13792 ++Count;
13793 }
13794 }
13796 continue;
13797 }
13798 // InsertElement/ExtractElement vectorize entries don't produce real
13799 // vector instructions - InsertElement at root IS the result, and
13800 // ExtractElement entries reference the input vector directly.
13801 if (TE.getOpcode() == Instruction::InsertElement ||
13802 TE.getOpcode() == Instruction::ExtractElement)
13803 continue;
13804 if (TE.getOpcode() == Instruction::InsertValue) {
13805 // InsertValue materializes via store + load unless it is stored directly
13806 // as a vector.
13807 if (!canVectorStoreInsertValue(&TE))
13808 Count += 2;
13809 if (!TE.ReorderIndices.empty() || !TE.ReuseShuffleIndices.empty())
13810 ++Count;
13812 continue;
13813 }
13814 if (TE.State == TreeEntry::SplitVectorize)
13815 Count += 2;
13816 else if (TE.hasReassocScalars())
13817 // N operand columns need N-1 binary combines.
13818 Count += TE.getNumOperands() - 1;
13819 else
13820 ++Count;
13821 if (!TE.ReorderIndices.empty() || !TE.ReuseShuffleIndices.empty())
13822 ++Count;
13824 }
13825 for (const auto &VecAndScale : GatherExtractSourceVecs)
13826 Total = SaturatingAdd(Total, VecAndScale.second);
13827 // Count extract instructions from ExternalUses, skipping insertelements
13828 // (those get folded into shuffles, not real extracts).
13829 SmallPtrSet<Value *, 8> CountedExtracts;
13830 for (const ExternalUser &EU : ExternalUses) {
13832 continue;
13833 if (EU.User && EphValues.count(EU.User))
13834 continue;
13835 // Vector-typed scalars are consumed as whole vectors, no extract
13836 // instruction is emitted for them.
13837 if (isVectorizedTy(EU.Scalar->getType()) &&
13838 (!SLPReVec ||
13839 (EU.E.hasState() && EU.E.getOpcode() == Instruction::InsertElement)))
13840 continue;
13841 if (ExternalUsesAsOriginalScalar.contains(EU.Scalar))
13842 continue;
13843 if (!CountedExtracts.insert(EU.Scalar).second)
13844 continue;
13845 ++Total;
13846 }
13847 return Total;
13848}
13849
13850void BoUpSLP::TreeEntry::buildAltOpShuffleMask(
13851 const function_ref<bool(Instruction *)> IsAltOp, SmallVectorImpl<int> &Mask,
13852 SmallVectorImpl<Value *> *OpScalars,
13853 SmallVectorImpl<Value *> *AltScalars) const {
13854 unsigned Sz = Scalars.size();
13855 Mask.assign(Sz, PoisonMaskElem);
13856 SmallVector<int> OrderMask;
13857 if (!ReorderIndices.empty())
13858 inversePermutation(ReorderIndices, OrderMask);
13859 for (unsigned I = 0; I < Sz; ++I) {
13860 unsigned Idx = I;
13861 if (!ReorderIndices.empty())
13862 Idx = OrderMask[I];
13863 if (isa<PoisonValue>(Scalars[Idx]))
13864 continue;
13865 auto *OpInst = cast<Instruction>(Scalars[Idx]);
13866 if (IsAltOp(OpInst)) {
13867 Mask[I] = Sz + Idx;
13868 if (AltScalars)
13869 AltScalars->push_back(OpInst);
13870 } else {
13871 Mask[I] = Idx;
13872 if (OpScalars)
13873 OpScalars->push_back(OpInst);
13874 }
13875 }
13876 if (!ReuseShuffleIndices.empty()) {
13877 SmallVector<int> NewMask(ReuseShuffleIndices.size(), PoisonMaskElem);
13878 transform(ReuseShuffleIndices, NewMask.begin(), [&Mask](int Idx) {
13879 return Idx != PoisonMaskElem ? Mask[Idx] : PoisonMaskElem;
13880 });
13881 Mask.swap(NewMask);
13882 }
13883}
13884
13886 Instruction *AltOp,
13887 const TargetLibraryInfo &TLI) {
13888 return InstructionsState(MainOp, AltOp).getMatchingMainOpOrAltOp(I) == MainOp;
13889}
13890
13891TTI::OperandValueInfo BoUpSLP::getOperandInfo(ArrayRef<Value *> Ops) const {
13892 assert(!Ops.empty());
13893 const auto *Op0 = Ops.front();
13894
13895 const bool IsConstant = all_of(Ops, [](Value *V) {
13896 // TODO: We should allow undef elements here
13897 return isConstant(V) && !isa<UndefValue>(V);
13898 });
13899 const bool IsUniform = all_of(Ops, [=](Value *V) {
13900 // TODO: We should allow undef elements here
13901 return V == Op0;
13902 });
13903 const bool IsPowerOfTwo = all_of(Ops, [](Value *V) {
13904 // TODO: We should allow undef elements here
13905 if (auto *CI = dyn_cast<ConstantInt>(V))
13906 return CI->getValue().isPowerOf2();
13907 return false;
13908 });
13909 const bool IsNegatedPowerOfTwo = all_of(Ops, [](Value *V) {
13910 // TODO: We should allow undef elements here
13911 if (auto *CI = dyn_cast<ConstantInt>(V))
13912 return CI->getValue().isNegatedPowerOf2();
13913 return false;
13914 });
13915
13917 if (IsConstant && IsUniform)
13919 else if (IsConstant)
13921 else if (IsUniform)
13923
13925 VP = IsPowerOfTwo ? TTI::OP_PowerOf2 : VP;
13926 VP = IsNegatedPowerOfTwo ? TTI::OP_NegatedPowerOf2 : VP;
13927
13928 return {VK, VP};
13929}
13930
13931namespace {
13932/// The base class for shuffle instruction emission and shuffle cost estimation.
13933class BaseShuffleAnalysis {
13934protected:
13935 Type *ScalarTy = nullptr;
13936
13937 BaseShuffleAnalysis(Type *ScalarTy) : ScalarTy(ScalarTy) {}
13938
13939 /// V is expected to be a vectorized value.
13940 /// When REVEC is disabled, there is no difference between VF and
13941 /// VNumElements.
13942 /// When REVEC is enabled, VF is VNumElements / ScalarTyNumElements.
13943 /// e.g., if ScalarTy is <4 x Ty> and V1 is <8 x Ty>, 2 is returned instead
13944 /// of 8.
13945 unsigned getVF(Value *V) const {
13946 assert(V && "V cannot be nullptr");
13947 assert(isa<FixedVectorType>(V->getType()) &&
13948 "V does not have FixedVectorType");
13949 assert(ScalarTy && "ScalarTy cannot be nullptr");
13950 unsigned ScalarTyNumElements = getNumElements(ScalarTy);
13951 unsigned VNumElements =
13952 cast<FixedVectorType>(V->getType())->getNumElements();
13953 assert(VNumElements > ScalarTyNumElements &&
13954 "the number of elements of V is not large enough");
13955 assert(VNumElements % ScalarTyNumElements == 0 &&
13956 "the number of elements of V is not a vectorized value");
13957 return VNumElements / ScalarTyNumElements;
13958 }
13959
13960 /// Checks if the mask is an identity mask.
13961 /// \param IsStrict if is true the function returns false if mask size does
13962 /// not match vector size.
13963 static bool isIdentityMask(ArrayRef<int> Mask, const FixedVectorType *VecTy,
13964 bool IsStrict) {
13965 int Limit = Mask.size();
13966 int VF = VecTy->getNumElements();
13967 int Index = -1;
13968 if (VF == Limit && ShuffleVectorInst::isIdentityMask(Mask, Limit))
13969 return true;
13970 if (!IsStrict) {
13971 // Consider extract subvector starting from index 0.
13972 if (ShuffleVectorInst::isExtractSubvectorMask(Mask, VF, Index) &&
13973 Index == 0)
13974 return true;
13975 // All VF-size submasks are identity (e.g.
13976 // <poison,poison,poison,poison,0,1,2,poison,poison,1,2,3> etc. for VF 4).
13977 if (Limit % VF == 0 && all_of(seq<int>(0, Limit / VF), [=](int Idx) {
13978 ArrayRef<int> Slice = Mask.slice(Idx * VF, VF);
13979 return all_of(Slice, equal_to(PoisonMaskElem)) ||
13981 }))
13982 return true;
13983 }
13984 return false;
13985 }
13986
13987 /// Tries to combine 2 different masks into single one.
13988 /// \param LocalVF Vector length of the permuted input vector. \p Mask may
13989 /// change the size of the vector, \p LocalVF is the original size of the
13990 /// shuffled vector.
13991 static void combineMasks(unsigned LocalVF, SmallVectorImpl<int> &Mask,
13992 ArrayRef<int> ExtMask) {
13993 unsigned VF = Mask.size();
13994 SmallVector<int> NewMask(ExtMask.size(), PoisonMaskElem);
13995 for (int I = 0, Sz = ExtMask.size(); I < Sz; ++I) {
13996 if (ExtMask[I] == PoisonMaskElem)
13997 continue;
13998 int MaskedIdx = Mask[ExtMask[I] % VF];
13999 NewMask[I] =
14000 MaskedIdx == PoisonMaskElem ? PoisonMaskElem : MaskedIdx % LocalVF;
14001 }
14002 Mask.swap(NewMask);
14003 }
14004
14005 /// Looks through shuffles trying to reduce final number of shuffles in the
14006 /// code. The function looks through the previously emitted shuffle
14007 /// instructions and properly mark indices in mask as undef.
14008 /// For example, given the code
14009 /// \code
14010 /// %s1 = shufflevector <2 x ty> %0, poison, <1, 0>
14011 /// %s2 = shufflevector <2 x ty> %1, poison, <1, 0>
14012 /// \endcode
14013 /// and if need to emit shuffle of %s1 and %s2 with mask <1, 0, 3, 2>, it will
14014 /// look through %s1 and %s2 and select vectors %0 and %1 with mask
14015 /// <0, 1, 2, 3> for the shuffle.
14016 /// If 2 operands are of different size, the smallest one will be resized and
14017 /// the mask recalculated properly.
14018 /// For example, given the code
14019 /// \code
14020 /// %s1 = shufflevector <2 x ty> %0, poison, <1, 0, 1, 0>
14021 /// %s2 = shufflevector <2 x ty> %1, poison, <1, 0, 1, 0>
14022 /// \endcode
14023 /// and if need to emit shuffle of %s1 and %s2 with mask <1, 0, 5, 4>, it will
14024 /// look through %s1 and %s2 and select vectors %0 and %1 with mask
14025 /// <0, 1, 2, 3> for the shuffle.
14026 /// So, it tries to transform permutations to simple vector merge, if
14027 /// possible.
14028 /// \param V The input vector which must be shuffled using the given \p Mask.
14029 /// If the better candidate is found, \p V is set to this best candidate
14030 /// vector.
14031 /// \param Mask The input mask for the shuffle. If the best candidate is found
14032 /// during looking-through-shuffles attempt, it is updated accordingly.
14033 /// \param SinglePermute true if the shuffle operation is originally a
14034 /// single-value-permutation. In this case the look-through-shuffles procedure
14035 /// may look for resizing shuffles as the best candidates.
14036 /// \return true if the shuffle results in the non-resizing identity shuffle
14037 /// (and thus can be ignored), false - otherwise.
14038 static bool peekThroughShuffles(Value *&V, SmallVectorImpl<int> &Mask,
14039 bool SinglePermute) {
14040 Value *Op = V;
14041 ShuffleVectorInst *IdentityOp = nullptr;
14042 SmallVector<int> IdentityMask;
14043 while (auto *SV = dyn_cast<ShuffleVectorInst>(Op)) {
14044 // Exit if not a fixed vector type or changing size shuffle.
14045 auto *SVTy = dyn_cast<FixedVectorType>(SV->getType());
14046 if (!SVTy)
14047 break;
14048 // Remember the identity or broadcast mask, if it is not a resizing
14049 // shuffle. If no better candidates are found, this Op and Mask will be
14050 // used in the final shuffle.
14051 if (isIdentityMask(Mask, SVTy, /*IsStrict=*/false)) {
14052 if (!IdentityOp || !SinglePermute ||
14053 (isIdentityMask(Mask, SVTy, /*IsStrict=*/true) &&
14055 IdentityMask.size()))) {
14056 IdentityOp = SV;
14057 // Store current mask in the IdentityMask so later we did not lost
14058 // this info if IdentityOp is selected as the best candidate for the
14059 // permutation.
14060 IdentityMask.assign(Mask);
14061 }
14062 }
14063 // Remember the broadcast mask. If no better candidates are found, this Op
14064 // and Mask will be used in the final shuffle.
14065 // Zero splat can be used as identity too, since it might be used with
14066 // mask <0, 1, 2, ...>, i.e. identity mask without extra reshuffling.
14067 // E.g. if need to shuffle the vector with the mask <3, 1, 2, 0>, which is
14068 // expensive, the analysis founds out, that the source vector is just a
14069 // broadcast, this original mask can be transformed to identity mask <0,
14070 // 1, 2, 3>.
14071 // \code
14072 // %0 = shuffle %v, poison, zeroinitalizer
14073 // %res = shuffle %0, poison, <3, 1, 2, 0>
14074 // \endcode
14075 // may be transformed to
14076 // \code
14077 // %0 = shuffle %v, poison, zeroinitalizer
14078 // %res = shuffle %0, poison, <0, 1, 2, 3>
14079 // \endcode
14080 if (SV->isZeroEltSplat()) {
14081 IdentityOp = SV;
14082 IdentityMask.assign(Mask);
14083 }
14084 int LocalVF = Mask.size();
14085 if (auto *SVOpTy =
14086 dyn_cast<FixedVectorType>(SV->getOperand(0)->getType()))
14087 LocalVF = SVOpTy->getNumElements();
14088 SmallVector<int> ExtMask(Mask.size(), PoisonMaskElem);
14089 for (auto [Idx, I] : enumerate(Mask)) {
14090 if (I == PoisonMaskElem ||
14091 static_cast<unsigned>(I) >= SV->getShuffleMask().size())
14092 continue;
14093 ExtMask[Idx] = SV->getMaskValue(I);
14094 }
14095 bool IsOp1Undef = isUndefVector</*isPoisonOnly=*/true>(
14096 SV->getOperand(0),
14097 buildUseMask(LocalVF, ExtMask, UseMask::FirstArg))
14098 .all();
14099 bool IsOp2Undef = isUndefVector</*isPoisonOnly=*/true>(
14100 SV->getOperand(1),
14101 buildUseMask(LocalVF, ExtMask, UseMask::SecondArg))
14102 .all();
14103 if (!IsOp1Undef && !IsOp2Undef) {
14104 // Update mask and mark undef elems.
14105 for (int &I : Mask) {
14106 if (I == PoisonMaskElem)
14107 continue;
14108 if (SV->getMaskValue(I % SV->getShuffleMask().size()) ==
14110 I = PoisonMaskElem;
14111 }
14112 break;
14113 }
14114 SmallVector<int> ShuffleMask(SV->getShuffleMask());
14115 combineMasks(LocalVF, ShuffleMask, Mask);
14116 Mask.swap(ShuffleMask);
14117 if (IsOp2Undef)
14118 Op = SV->getOperand(0);
14119 else
14120 Op = SV->getOperand(1);
14121 }
14122 if (auto *OpTy = dyn_cast<FixedVectorType>(Op->getType());
14123 !OpTy || !isIdentityMask(Mask, OpTy, SinglePermute) ||
14125 if (IdentityOp) {
14126 V = IdentityOp;
14127 assert(Mask.size() == IdentityMask.size() &&
14128 "Expected masks of same sizes.");
14129 // Clear known poison elements.
14130 for (auto [I, Idx] : enumerate(Mask))
14131 if (Idx == PoisonMaskElem)
14132 IdentityMask[I] = PoisonMaskElem;
14133 Mask.swap(IdentityMask);
14134 auto *Shuffle = dyn_cast<ShuffleVectorInst>(V);
14135 return SinglePermute &&
14136 (isIdentityMask(Mask, cast<FixedVectorType>(V->getType()),
14137 /*IsStrict=*/true) ||
14138 (Shuffle && Mask.size() == Shuffle->getShuffleMask().size() &&
14139 Shuffle->isZeroEltSplat() &&
14141 all_of(enumerate(Mask), [&](const auto &P) {
14142 return P.value() == PoisonMaskElem ||
14143 Shuffle->getShuffleMask()[P.index()] == 0;
14144 })));
14145 }
14146 V = Op;
14147 return false;
14148 }
14149 V = Op;
14150 return true;
14151 }
14152
14153 /// Smart shuffle instruction emission, walks through shuffles trees and
14154 /// tries to find the best matching vector for the actual shuffle
14155 /// instruction.
14156 template <typename T, typename ShuffleBuilderTy, typename... Args>
14157 static T createShuffle(Value *V1, Value *V2, ArrayRef<int> Mask,
14158 ShuffleBuilderTy &Builder, Type *ScalarTy,
14159 Args... Arguments) {
14160 assert(V1 && "Expected at least one vector value.");
14161 unsigned ScalarTyNumElements = getNumElements(ScalarTy);
14162 SmallVector<int> NewMask(Mask);
14163 if (ScalarTyNumElements != 1) {
14164 assert(SLPReVec && "FixedVectorType is not expected.");
14165 transformScalarShuffleIndiciesToVector(ScalarTyNumElements, NewMask);
14166 Mask = NewMask;
14167 }
14168 if (V2)
14169 Builder.resizeToMatch(V1, V2);
14170 int VF = Mask.size();
14171 if (auto *FTy = dyn_cast<FixedVectorType>(V1->getType()))
14172 VF = FTy->getNumElements();
14174 V2, buildUseMask(VF, Mask, UseMask::SecondArg))
14175 .all()) {
14176 // Peek through shuffles.
14177 Value *Op1 = V1;
14178 Value *Op2 = V2;
14179 int VF =
14180 cast<VectorType>(V1->getType())->getElementCount().getKnownMinValue();
14181 SmallVector<int> CombinedMask1(Mask.size(), PoisonMaskElem);
14182 SmallVector<int> CombinedMask2(Mask.size(), PoisonMaskElem);
14183 for (int I = 0, E = Mask.size(); I < E; ++I) {
14184 if (Mask[I] < VF)
14185 CombinedMask1[I] = Mask[I];
14186 else
14187 CombinedMask2[I] = Mask[I] - VF;
14188 }
14189 Value *PrevOp1;
14190 Value *PrevOp2;
14191 do {
14192 PrevOp1 = Op1;
14193 PrevOp2 = Op2;
14194 (void)peekThroughShuffles(Op1, CombinedMask1, /*SinglePermute=*/false);
14195 (void)peekThroughShuffles(Op2, CombinedMask2, /*SinglePermute=*/false);
14196 // Check if we have 2 resizing shuffles - need to peek through operands
14197 // again.
14198 if (auto *SV1 = dyn_cast<ShuffleVectorInst>(Op1))
14199 if (auto *SV2 = dyn_cast<ShuffleVectorInst>(Op2)) {
14200 SmallVector<int> ExtMask1(Mask.size(), PoisonMaskElem);
14201 for (auto [Idx, I] : enumerate(CombinedMask1)) {
14202 if (I == PoisonMaskElem)
14203 continue;
14204 ExtMask1[Idx] = SV1->getMaskValue(I);
14205 }
14206 SmallBitVector UseMask1 = buildUseMask(
14207 cast<FixedVectorType>(SV1->getOperand(1)->getType())
14208 ->getNumElements(),
14209 ExtMask1, UseMask::SecondArg);
14210 SmallVector<int> ExtMask2(CombinedMask2.size(), PoisonMaskElem);
14211 for (auto [Idx, I] : enumerate(CombinedMask2)) {
14212 if (I == PoisonMaskElem)
14213 continue;
14214 ExtMask2[Idx] = SV2->getMaskValue(I);
14215 }
14216 SmallBitVector UseMask2 = buildUseMask(
14217 cast<FixedVectorType>(SV2->getOperand(1)->getType())
14218 ->getNumElements(),
14219 ExtMask2, UseMask::SecondArg);
14220 if (SV1->getOperand(0)->getType() ==
14221 SV2->getOperand(0)->getType() &&
14222 SV1->getOperand(0)->getType() != SV1->getType() &&
14223 isUndefVector(SV1->getOperand(1), UseMask1).all() &&
14224 isUndefVector(SV2->getOperand(1), UseMask2).all()) {
14225 Op1 = SV1->getOperand(0);
14226 Op2 = SV2->getOperand(0);
14227 SmallVector<int> ShuffleMask1(SV1->getShuffleMask());
14228 int LocalVF = ShuffleMask1.size();
14229 if (auto *FTy = dyn_cast<FixedVectorType>(Op1->getType()))
14230 LocalVF = FTy->getNumElements();
14231 combineMasks(LocalVF, ShuffleMask1, CombinedMask1);
14232 CombinedMask1.swap(ShuffleMask1);
14233 SmallVector<int> ShuffleMask2(SV2->getShuffleMask());
14234 LocalVF = ShuffleMask2.size();
14235 if (auto *FTy = dyn_cast<FixedVectorType>(Op2->getType()))
14236 LocalVF = FTy->getNumElements();
14237 combineMasks(LocalVF, ShuffleMask2, CombinedMask2);
14238 CombinedMask2.swap(ShuffleMask2);
14239 }
14240 }
14241 } while (PrevOp1 != Op1 || PrevOp2 != Op2);
14242 Builder.resizeToMatch(Op1, Op2);
14243 VF = std::max(cast<VectorType>(Op1->getType())
14244 ->getElementCount()
14245 .getKnownMinValue(),
14247 ->getElementCount()
14248 .getKnownMinValue());
14249 for (int I = 0, E = Mask.size(); I < E; ++I) {
14250 if (CombinedMask2[I] != PoisonMaskElem) {
14251 assert(CombinedMask1[I] == PoisonMaskElem &&
14252 "Expected undefined mask element");
14253 CombinedMask1[I] = CombinedMask2[I] + (Op1 == Op2 ? 0 : VF);
14254 }
14255 }
14256 if (Op1 == Op2 &&
14257 (ShuffleVectorInst::isIdentityMask(CombinedMask1, VF) ||
14258 (ShuffleVectorInst::isZeroEltSplatMask(CombinedMask1, VF) &&
14260 cast<ShuffleVectorInst>(Op1)->getShuffleMask() ==
14261 ArrayRef(CombinedMask1))))
14262 return Builder.createIdentity(Op1);
14263 return Builder.createShuffleVector(
14264 Op1, Op1 == Op2 ? PoisonValue::get(Op1->getType()) : Op2,
14265 CombinedMask1);
14266 }
14267 if (isa<PoisonValue>(V1))
14268 return Builder.createPoison(
14269 cast<VectorType>(V1->getType())->getElementType(), Mask.size());
14270 bool IsIdentity = peekThroughShuffles(V1, NewMask, /*SinglePermute=*/true);
14271 assert(V1 && "Expected non-null value after looking through shuffles.");
14272
14273 if (!IsIdentity)
14274 return Builder.createShuffleVector(V1, NewMask, Arguments...);
14275 return Builder.createIdentity(V1);
14276 }
14277
14278 /// Transforms mask \p CommonMask per given \p Mask to make proper set after
14279 /// shuffle emission.
14280 static void transformMaskAfterShuffle(MutableArrayRef<int> CommonMask,
14281 ArrayRef<int> Mask) {
14282 for (unsigned I : seq<unsigned>(CommonMask.size()))
14283 if (Mask[I] != PoisonMaskElem)
14284 CommonMask[I] = I;
14285 }
14286};
14287} // namespace
14288
14289void BoUpSLP::reorderGatherNode(TreeEntry &TE) {
14290 assert(TE.isGather() && TE.ReorderIndices.empty() &&
14291 "Expected gather node without reordering.");
14292 DenseMap<std::pair<size_t, Value *>, SmallVector<LoadInst *>> LoadsMap;
14293 SmallSet<size_t, 2> LoadKeyUsed;
14294
14295 // Do not reorder nodes if it small (just 2 elements), all-constant or all
14296 // instructions have same opcode already.
14297 if (TE.Scalars.size() == 2 || (TE.hasState() && !TE.isAltShuffle()) ||
14298 all_of(TE.Scalars, isConstant))
14299 return;
14300
14301 if (any_of(seq<unsigned>(TE.Idx), [&](unsigned Idx) {
14302 return VectorizableTree[Idx]->isSame(TE.Scalars);
14303 }))
14304 return;
14305
14306 auto GenerateLoadsSubkey = [&](size_t Key, LoadInst *LI) {
14307 Key = hash_combine(hash_value(LI->getParent()->getNumber()), Key);
14308 Value *Ptr =
14309 getUnderlyingObject(LI->getPointerOperand(), RecursionMaxDepth);
14310 if (LoadKeyUsed.contains(Key)) {
14311 auto LIt = LoadsMap.find(std::make_pair(Key, Ptr));
14312 if (LIt != LoadsMap.end()) {
14313 for (LoadInst *RLI : LIt->second) {
14314 if (getPointersDiff(RLI->getType(), RLI->getPointerOperand(),
14315 LI->getType(), LI->getPointerOperand(), *DL, *SE,
14316 /*StrictCheck=*/true))
14317 return hash_value(RLI->getPointerOperand());
14318 }
14319 for (LoadInst *RLI : LIt->second) {
14321 LI->getPointerOperand(), *TLI)) {
14322 hash_code SubKey = hash_value(RLI->getPointerOperand());
14323 return SubKey;
14324 }
14325 }
14326 if (LIt->second.size() > 2) {
14327 hash_code SubKey =
14328 hash_value(LIt->second.back()->getPointerOperand());
14329 return SubKey;
14330 }
14331 }
14332 }
14333 LoadKeyUsed.insert(Key);
14334 LoadsMap.try_emplace(std::make_pair(Key, Ptr)).first->second.push_back(LI);
14335 return hash_value(LI->getPointerOperand());
14336 };
14337 MapVector<size_t, MapVector<size_t, SmallVector<Value *>>> SortedValues;
14338 SmallDenseMap<Value *, SmallVector<unsigned>, 8> KeyToIndex;
14339 bool IsOrdered = true;
14340 unsigned NumInstructions = 0;
14341 // Try to "cluster" scalar instructions, to be able to build extra vectorized
14342 // nodes.
14343 for (auto [I, V] : enumerate(TE.Scalars)) {
14344 size_t Key = 1, Idx = 1;
14345 if (auto *Inst = dyn_cast<Instruction>(V);
14347 !isDeleted(Inst) && !isVectorized(V)) {
14348 std::tie(Key, Idx) = generateKeySubkey(V, TLI, GenerateLoadsSubkey,
14349 /*AllowAlternate=*/false);
14350 ++NumInstructions;
14351 }
14352 auto &Container = SortedValues[Key];
14353 if (IsOrdered && !KeyToIndex.contains(V) &&
14356 ((Container.contains(Idx) &&
14357 KeyToIndex.at(Container[Idx].back()).back() != I - 1) ||
14358 (!Container.empty() && !Container.contains(Idx) &&
14359 KeyToIndex.at(Container.back().second.back()).back() != I - 1)))
14360 IsOrdered = false;
14361 auto &KTI = KeyToIndex[V];
14362 if (KTI.empty())
14363 Container[Idx].push_back(V);
14364 KTI.push_back(I);
14365 }
14367 APInt DemandedElts = APInt::getAllOnes(TE.Scalars.size());
14368 if (!IsOrdered && NumInstructions > 1) {
14369 unsigned Cnt = 0;
14370 TE.ReorderIndices.resize(TE.Scalars.size(), TE.Scalars.size());
14371 for (const auto &D : SortedValues) {
14372 for (const auto &P : D.second) {
14373 unsigned Sz = 0;
14374 for (Value *V : P.second) {
14375 ArrayRef<unsigned> Indices = KeyToIndex.at(V);
14376 for (auto [K, Idx] : enumerate(Indices)) {
14377 TE.ReorderIndices[Cnt + K] = Idx;
14378 TE.Scalars[Cnt + K] = V;
14379 }
14380 Sz += Indices.size();
14381 Cnt += Indices.size();
14382 }
14383 if (Sz > 1 && isa<Instruction>(P.second.front())) {
14384 const unsigned SubVF = getFloorFullVectorNumberOfElements(
14385 *TTI, TE.Scalars.front()->getType(), Sz, SLPReVec);
14386 SubVectors.emplace_back(Cnt - Sz, SubVF);
14387 for (unsigned I : seq<unsigned>(Cnt - Sz, Cnt - Sz + SubVF))
14388 DemandedElts.clearBit(I);
14389 } else if (!P.second.empty() && isConstant(P.second.front())) {
14390 for (unsigned I : seq<unsigned>(Cnt - Sz, Cnt))
14391 DemandedElts.clearBit(I);
14392 }
14393 }
14394 }
14395 }
14396 // Reuses always require shuffles, so consider it as profitable.
14397 if (!TE.ReuseShuffleIndices.empty() || TE.ReorderIndices.empty())
14398 return;
14399 // Do simple cost estimation.
14401 auto *ScalarTy = TE.Scalars.front()->getType();
14402 auto *VecTy = cast<VectorType>(getWidenedType(ScalarTy, TE.Scalars.size()));
14403 for (auto [Idx, Sz] : SubVectors) {
14404 Cost += getShuffleCost(*TTI, TTI::SK_InsertSubvector, VecTy, CostKind, {},
14405 Idx, cast<VectorType>(getWidenedType(ScalarTy, Sz)));
14406 }
14407 Cost +=
14408 getScalarizationOverhead(*TTI, SLPReVec, ScalarTy, VecTy, DemandedElts,
14409 /*Insert=*/true,
14410 /*Extract=*/false, CostKind);
14411 int Sz = TE.Scalars.size();
14412 SmallVector<int> ReorderMask(TE.ReorderIndices.begin(),
14413 TE.ReorderIndices.end());
14414 for (unsigned I : seq<unsigned>(Sz)) {
14415 Value *V = TE.getOrdered(I);
14416 if (isa<PoisonValue>(V)) {
14417 ReorderMask[I] = PoisonMaskElem;
14418 } else if (isConstant(V) || DemandedElts[I]) {
14419 ReorderMask[I] = I + TE.ReorderIndices.size();
14420 }
14421 }
14422 Cost += getShuffleCost(*TTI,
14423 any_of(ReorderMask, [&](int I) { return I >= Sz; })
14426 VecTy, CostKind, ReorderMask);
14427 DemandedElts = APInt::getAllOnes(TE.Scalars.size());
14428 ReorderMask.assign(Sz, PoisonMaskElem);
14429 for (unsigned I : seq<unsigned>(Sz)) {
14430 Value *V = TE.getOrdered(I);
14431 if (isConstant(V)) {
14432 DemandedElts.clearBit(I);
14433 if (!isa<PoisonValue>(V))
14434 ReorderMask[I] = I;
14435 } else {
14436 ReorderMask[I] = I + Sz;
14437 }
14438 }
14439 InstructionCost BVCost =
14440 getScalarizationOverhead(*TTI, SLPReVec, ScalarTy, VecTy, DemandedElts,
14441 /*Insert=*/true, /*Extract=*/false, CostKind);
14442 if (!DemandedElts.isAllOnes())
14443 BVCost += getShuffleCost(*TTI, TTI::SK_PermuteTwoSrc, VecTy, CostKind,
14444 ReorderMask);
14445 if (Cost >= BVCost) {
14446 SmallVector<int> Mask(TE.ReorderIndices.begin(), TE.ReorderIndices.end());
14447 reorderScalars(TE.Scalars, Mask);
14448 TE.ReorderIndices.clear();
14449 }
14450}
14451
14452/// Check if we can convert fadd/fsub sequence to FMAD.
14453/// \returns Cost of the FMAD, if conversion is possible, invalid cost otherwise.
14455 const InstructionsState &S,
14456 DominatorTree &DT, const DataLayout &DL,
14458 const TargetLibraryInfo &TLI,
14460 assert(all_of(VL,
14461 [](Value *V) {
14462 return V->getType()->getScalarType()->isFloatingPointTy();
14463 }) &&
14464 "Can only convert to FMA for floating point types");
14465 assert(S.isAddSubLikeOp() && "Can only convert to FMA for add/sub");
14466
14467 auto CheckForContractable = [](ArrayRef<Value *> VL,
14468 const InstructionsState &S) {
14469 FastMathFlags FMF;
14470 FMF.set();
14471 for (Value *V : VL) {
14472 auto *I = dyn_cast<Instruction>(V);
14473 if (!I)
14474 continue;
14475 if (S.isCopyableElement(I))
14476 continue;
14477 Instruction *MatchingI = S.getMatchingMainOpOrAltOp(I);
14478 if (S.getMainOp() != MatchingI && S.getAltOp() != MatchingI)
14479 continue;
14480 if (auto *FPCI = dyn_cast<FPMathOperator>(I))
14481 FMF &= FPCI->getFastMathFlags();
14482 }
14483 return FMF.allowContract();
14484 };
14485 if (!CheckForContractable(VL, S))
14487 // fmul also should be contractable
14488 InstructionsCompatibilityAnalysis Analysis(DT, DL, TTI, TLI);
14489 SmallVector<BoUpSLP::ValueList> Operands = Analysis.buildOperands(S, VL);
14490
14491 InstructionsState OpS = getSameOpcode(Operands.front(), TLI);
14492 if (!OpS.valid())
14494
14495 if (OpS.isAltShuffle() || OpS.getOpcode() != Instruction::FMul)
14497 if (!CheckForContractable(Operands.front(), OpS))
14499 // Compare the costs.
14500 InstructionCost FMulPlusFAddCost = 0;
14501 InstructionCost FMACost = 0;
14502 // Price both sides of the fmul+fadd pair as not fused. Passing a context
14503 // instruction would let targets that model the fusion discount the unfused
14504 // side of the comparison as well.
14505 auto GetUnfusedFMulCost = [&](Instruction *I) {
14506 assert(I->getOpcode() == Instruction::FMul && "Expected an fmul");
14507 TTI::OperandValueInfo Op1Info = TTI::getOperandInfo(I->getOperand(0));
14508 TTI::OperandValueInfo Op2Info = TTI::getOperandInfo(I->getOperand(1));
14509 return TTI.getArithmeticInstrCost(I->getOpcode(), I->getType(), CostKind,
14510 Op1Info, Op2Info,
14511 {I->getOperand(0), I->getOperand(1)});
14512 };
14513 FastMathFlags FMF;
14514 FMF.set();
14515 const bool IsArithmeticState = S.isAddSubLikeOp() || S.isMulDivLikeOp() ||
14516 S.isShiftOp() || S.isBitwiseLogicOp();
14517 for (Value *V : VL) {
14518 auto *I = dyn_cast<Instruction>(V);
14519 if (!I)
14520 continue;
14521 const bool IsCopyable = S.isCopyableElement(I);
14522 if (!IsCopyable)
14523 if (auto *FPCI = dyn_cast<FPMathOperator>(I))
14524 FMF &= FPCI->getFastMathFlags();
14525 if (IsCopyable || !IsArithmeticState ||
14526 (I->getOpcode() != S.getOpcode() &&
14527 I->getOpcode() != S.getAltOpcode())) {
14528 FMulPlusFAddCost += TTI.getInstructionCost(I, CostKind);
14529 continue;
14530 }
14531 TTI::OperandValueInfo Op1Info = TTI::getOperandInfo(I->getOperand(0));
14532 TTI::OperandValueInfo Op2Info = TTI::getOperandInfo(I->getOperand(1));
14533 FMulPlusFAddCost += TTI.getArithmeticInstrCost(
14534 I->getOpcode(), I->getType(), CostKind, Op1Info, Op2Info,
14535 {I->getOperand(0), I->getOperand(1)});
14536 }
14537 unsigned NumOps = 0;
14538 for (auto [V, Op] : zip(VL, Operands.front())) {
14539 if (S.isCopyableElement(V))
14540 continue;
14541 auto *I = dyn_cast<Instruction>(Op);
14542 if (!I || !I->hasOneUse() || OpS.isCopyableElement(I)) {
14543 if (auto *OpI = dyn_cast<Instruction>(V))
14544 FMACost += TTI.getInstructionCost(OpI, CostKind);
14545 if (I)
14546 FMACost += TTI.getInstructionCost(I, CostKind);
14547 continue;
14548 }
14549 ++NumOps;
14550 if (auto *FPCI = dyn_cast<FPMathOperator>(I))
14551 FMF &= FPCI->getFastMathFlags();
14552 FMulPlusFAddCost += GetUnfusedFMulCost(I);
14553 }
14554 Type *Ty = VL.front()->getType();
14555 IntrinsicCostAttributes ICA(Intrinsic::fmuladd, Ty, {Ty, Ty, Ty}, FMF);
14556 FMACost += NumOps * TTI.getIntrinsicInstrCost(ICA, CostKind);
14557 return FMACost < FMulPlusFAddCost ? FMACost : InstructionCost::getInvalid();
14558}
14559
14560bool BoUpSLP::matchesShlZExt(const TreeEntry &TE, OrdersType &Order,
14561 bool &IsBSwap, bool &ForLoads) const {
14562 assert(TE.hasState() && TE.getOpcode() == Instruction::Shl &&
14563 "Expected Shl node.");
14564 IsBSwap = false;
14565 ForLoads = false;
14566 if (TE.State != TreeEntry::Vectorize || !TE.ReorderIndices.empty() ||
14567 !TE.ReuseShuffleIndices.empty() || MinBWs.contains(&TE) ||
14568 any_of(TE.Scalars, [](Value *V) { return !V->hasOneUse(); }))
14569 return false;
14570 Type *ScalarTy = TE.getMainOp()->getType();
14571 // TODO: Check if same can be done for the vector types.
14572 if (!ScalarTy->isIntegerTy())
14573 return false;
14574 if (ScalarTy->isVectorTy())
14575 return false;
14576 const unsigned Sz = DL->getTypeSizeInBits(ScalarTy);
14577 const TreeEntry *LhsTE = getOperandEntry(&TE, /*Idx=*/0);
14578 const TreeEntry *RhsTE = getOperandEntry(&TE, /*Idx=*/1);
14579 // Lhs should be zext i<stride> to I<sz>.
14580 if (!(LhsTE->State == TreeEntry::Vectorize &&
14581 LhsTE->getOpcode() == Instruction::ZExt &&
14582 LhsTE->ReorderIndices.empty() && LhsTE->ReuseShuffleIndices.empty() &&
14583 !MinBWs.contains(LhsTE) &&
14584 all_of(LhsTE->Scalars, [](Value *V) { return V->hasOneUse(); })))
14585 return false;
14586 Type *SrcScalarTy = cast<ZExtInst>(LhsTE->getMainOp())->getSrcTy();
14587 unsigned Stride = DL->getTypeSizeInBits(SrcScalarTy);
14588 if (!isPowerOf2_64(Stride) || Stride >= Sz || Sz % Stride != 0 ||
14589 !isPowerOf2_64(LhsTE->getVectorFactor()))
14590 return false;
14591 if (!(RhsTE->isGather() && RhsTE->ReorderIndices.empty() &&
14592 RhsTE->ReuseShuffleIndices.empty() && !MinBWs.contains(RhsTE)))
14593 return false;
14594 Order.clear();
14595 unsigned CurrentValue = 0;
14596 // Rhs should be (0, Stride, 2 * Stride, ..., N-Stride), where N <= Sz.
14597 if (all_of(RhsTE->Scalars,
14598 [&](Value *V) {
14599 CurrentValue += Stride;
14600 if (isa<UndefValue>(V))
14601 return true;
14602 auto *C = dyn_cast<Constant>(V);
14603 if (!C)
14604 return false;
14605 return C->getUniqueInteger() == CurrentValue - Stride;
14606 }) &&
14607 CurrentValue <= Sz) {
14608 Order.clear();
14609 } else {
14610 const unsigned VF = RhsTE->getVectorFactor();
14611 Order.assign(VF, VF);
14612 // Track which logical positions we've seen; reject duplicate shift amounts.
14613 SmallBitVector SeenPositions(VF);
14614 // Check if need to reorder Rhs to make it in form (0, Stride, 2 * Stride,
14615 // ..., N-Stride), where N <= Sz.
14616 if (VF * Stride > Sz)
14617 return false;
14618 for (const auto [Idx, V] : enumerate(RhsTE->Scalars)) {
14619 if (isa<UndefValue>(V))
14620 continue;
14621 auto *C = dyn_cast<Constant>(V);
14622 if (!C)
14623 return false;
14624 const APInt &Val = C->getUniqueInteger();
14625 if (Val.isNegative() || Val.uge(Sz) || Val.getZExtValue() % Stride != 0)
14626 return false;
14627 unsigned Pos = Val.getZExtValue() / Stride;
14628 // TODO: Support Pos >= VF, in this case need to shift the final value.
14629 if (Order[Idx] != VF || Pos >= VF)
14630 return false;
14631 if (SeenPositions.test(Pos))
14632 return false;
14633 SeenPositions.set(Pos);
14634 Order[Idx] = Pos;
14635 }
14636 // One of the indices not set - exit.
14637 if (is_contained(Order, VF))
14638 return false;
14639 }
14640 auto *SrcType = IntegerType::getIntNTy(ScalarTy->getContext(),
14641 Stride * LhsTE->getVectorFactor());
14642 FastMathFlags FMF;
14643 SmallPtrSet<Value *, 4> CheckedExtracts;
14644 auto *VecTy =
14645 cast<VectorType>(getWidenedType(ScalarTy, TE.getVectorFactor()));
14646 auto *SrcVecTy =
14647 cast<VectorType>(getWidenedType(SrcScalarTy, LhsTE->getVectorFactor()));
14648 TTI::CastContextHint CastCtx =
14649 getCastContextHint(*getOperandEntry(LhsTE, /*Idx=*/0));
14650 InstructionCost VecCost =
14651 TTI->getArithmeticReductionCost(Instruction::Or, VecTy, FMF, CostKind) +
14652 TTI->getArithmeticInstrCost(Instruction::Shl, VecTy, CostKind,
14653 getOperandInfo(LhsTE->Scalars)) +
14654 TTI->getCastInstrCost(
14655 Instruction::ZExt, VecTy,
14656 getWidenedType(SrcScalarTy, LhsTE->getVectorFactor()), CastCtx,
14657 CostKind);
14658 InstructionCost BitcastCost = TTI->getCastInstrCost(
14659 Instruction::BitCast, SrcType, SrcVecTy, CastCtx, CostKind);
14660 if (!Order.empty()) {
14661 fixupOrderingIndices(Order);
14662 SmallVector<int> Mask;
14663 inversePermutation(Order, Mask);
14664 BitcastCost += getShuffleCost(*TTI, TTI::SK_PermuteSingleSrc, SrcVecTy,
14665 CostKind, Mask);
14666 }
14667 // Check if the combination can be modeled as a bitcast+byteswap operation.
14668 constexpr unsigned ByteSize = 8;
14669 if (!Order.empty() && isReverseOrder(Order) &&
14670 DL->getTypeSizeInBits(SrcScalarTy) == ByteSize) {
14671 IntrinsicCostAttributes CostAttrs(Intrinsic::bswap, SrcType, {SrcType});
14672 InstructionCost BSwapCost =
14673 TTI->getCastInstrCost(Instruction::BitCast, SrcType, SrcVecTy, CastCtx,
14674 CostKind) +
14675 TTI->getIntrinsicInstrCost(CostAttrs, CostKind);
14676 if (BSwapCost <= BitcastCost) {
14677 BitcastCost = BSwapCost;
14678 IsBSwap = true;
14679 Order.clear();
14680 // Check for loads in the ZExt node.
14681 const TreeEntry *SrcTE = getOperandEntry(LhsTE, /*Idx=*/0);
14682 if (SrcTE->State == TreeEntry::Vectorize &&
14683 SrcTE->ReorderIndices.empty() && SrcTE->ReuseShuffleIndices.empty() &&
14684 SrcTE->getOpcode() == Instruction::Load && !SrcTE->isAltShuffle() &&
14685 all_of(SrcTE->Scalars, [](Value *V) { return V->hasOneUse(); })) {
14686 auto *LI = cast<LoadInst>(SrcTE->getMainOp());
14687 IntrinsicCostAttributes CostAttrs(Intrinsic::bswap, SrcType, {SrcType});
14688 InstructionCost BSwapCost =
14689 TTI->getMemoryOpCost(Instruction::Load, SrcType, LI->getAlign(),
14690 LI->getPointerAddressSpace(), CostKind) +
14691 TTI->getIntrinsicInstrCost(CostAttrs, CostKind);
14692 if (BSwapCost <= BitcastCost) {
14693 VecCost +=
14694 TTI->getMemoryOpCost(Instruction::Load, SrcVecTy, LI->getAlign(),
14695 LI->getPointerAddressSpace(), CostKind);
14696 BitcastCost = BSwapCost;
14697 ForLoads = true;
14698 }
14699 }
14700 }
14701 } else if (Order.empty() && DL->getTypeSizeInBits(SrcScalarTy) == ByteSize) {
14702 // Check for loads in the ZExt node.
14703 const TreeEntry *SrcTE = getOperandEntry(LhsTE, /*Idx=*/0);
14704 if (SrcTE->State == TreeEntry::Vectorize && SrcTE->ReorderIndices.empty() &&
14705 SrcTE->ReuseShuffleIndices.empty() &&
14706 SrcTE->getOpcode() == Instruction::Load && !SrcTE->isAltShuffle() &&
14707 all_of(SrcTE->Scalars, [](Value *V) { return V->hasOneUse(); })) {
14708 auto *LI = cast<LoadInst>(SrcTE->getMainOp());
14709 BitcastCost =
14710 TTI->getMemoryOpCost(Instruction::Load, SrcType, LI->getAlign(),
14711 LI->getPointerAddressSpace(), CostKind);
14712 VecCost +=
14713 TTI->getMemoryOpCost(Instruction::Load, SrcVecTy, LI->getAlign(),
14714 LI->getPointerAddressSpace(), CostKind);
14715 ForLoads = true;
14716 }
14717 }
14718 if (SrcType != ScalarTy) {
14719 BitcastCost += TTI->getCastInstrCost(Instruction::ZExt, ScalarTy, SrcType,
14720 TTI::CastContextHint::None, CostKind);
14721 }
14722 return BitcastCost < VecCost;
14723}
14724
14725bool BoUpSLP::matchesInversedZExtSelect(
14726 const TreeEntry &SelectTE,
14727 SmallVectorImpl<unsigned> &InversedCmpsIndices) const {
14728 assert(SelectTE.hasState() && SelectTE.getOpcode() == Instruction::Select &&
14729 "Expected select node.");
14731 for (auto [Idx, V] : enumerate(SelectTE.Scalars)) {
14732 auto *Inst = dyn_cast<Instruction>(V);
14733 if (!Inst || Inst->getOpcode() != Instruction::ZExt)
14734 continue;
14735 ZExts.emplace_back(Inst, Idx);
14736 }
14737 if (ZExts.empty())
14738 return false;
14739 const auto *CmpTE = getOperandEntry(&SelectTE, 0);
14740 const auto *Op1TE = getOperandEntry(&SelectTE, 1);
14741 const auto *Op2TE = getOperandEntry(&SelectTE, 2);
14742 // Compares must be alternate vectorized, and other operands must be gathers
14743 // or copyables.
14744 // TODO: investigate opportunity for reordered/reused nodes.
14745 if (CmpTE->State != TreeEntry::Vectorize || !CmpTE->isAltShuffle() ||
14746 (CmpTE->getOpcode() != Instruction::ICmp &&
14747 CmpTE->getOpcode() != Instruction::FCmp) ||
14748 !CmpTE->ReorderIndices.empty() || !CmpTE->ReuseShuffleIndices.empty() ||
14749 !Op1TE->ReorderIndices.empty() || !Op1TE->ReuseShuffleIndices.empty() ||
14750 !Op2TE->ReorderIndices.empty() || !Op2TE->ReuseShuffleIndices.empty())
14751 return false;
14752 // The operands must be buildvectors/copyables.
14753 if (!Op1TE->isGather() || !Op2TE->isGather())
14754 return false;
14755 // TODO: investigate opportunity for the vector nodes with copyables.
14756 auto *Cmp = CmpTE->getMainOp();
14757 CmpPredicate Pred;
14758 auto MatchCmp = m_Cmp(Pred, m_Value(), m_Value());
14759 if (!match(Cmp, MatchCmp))
14760 return false;
14761 CmpPredicate MainPred = Pred;
14762 CmpPredicate InversedPred(CmpInst::getInversePredicate(Pred),
14763 Pred.hasSameSign());
14764 for (const auto [Idx, V] : enumerate(CmpTE->Scalars)) {
14765 if (!match(V, MatchCmp))
14766 continue;
14767 if (CmpPredicate::getMatching(MainPred, Pred))
14768 continue;
14769 if (!CmpPredicate::getMatching(InversedPred, Pred))
14770 return false;
14771 if (!V->hasOneUse())
14772 return false;
14773 InversedCmpsIndices.push_back(Idx);
14774 }
14775
14776 if (InversedCmpsIndices.empty())
14777 return false;
14778 Type *VecTy =
14779 getWidenedType(Cmp->getOperand(0)->getType(), CmpTE->getVectorFactor());
14780 Type *CmpTy = CmpInst::makeCmpResultType(VecTy);
14781
14782 InstructionCost VecCost =
14783 TTI->getCmpSelInstrCost(CmpTE->getOpcode(), VecTy, CmpTy, MainPred,
14784 CostKind, getOperandInfo(CmpTE->getOperand(0)),
14785 getOperandInfo(CmpTE->getOperand(1)));
14787 *TTI, SLPReVec, Cmp->getType(), cast<VectorType>(CmpTy),
14788 APInt::getAllOnes(CmpTE->getVectorFactor()),
14789 /*Insert=*/true, /*Extract=*/false, CostKind);
14790 for (Value *V : CmpTE->Scalars) {
14791 auto *I = dyn_cast<Instruction>(V);
14792 if (!I)
14793 continue;
14794 BVCost += TTI->getInstructionCost(I, CostKind);
14795 }
14796 return VecCost < BVCost;
14797}
14798
14799bool BoUpSLP::matchesSelectOfBits(const TreeEntry &SelectTE) const {
14800 assert(SelectTE.hasState() && SelectTE.getOpcode() == Instruction::Select &&
14801 "Expected select node.");
14802 if (DL->isBigEndian())
14803 return false;
14804 if (!SelectTE.ReorderIndices.empty() || !SelectTE.ReuseShuffleIndices.empty())
14805 return false;
14806 if (!UserIgnoreList || SelectTE.Idx != 0)
14807 return false;
14808 if (any_of(SelectTE.Scalars, [](Value *V) { return !V->hasOneUse(); }))
14809 return false;
14810 // Check that all reduction operands are or instructions.
14811 if (any_of(*UserIgnoreList,
14812 [](Value *V) { return !match(V, m_Or(m_Value(), m_Value())); }))
14813 return false;
14814 const TreeEntry *Op1TE = getOperandEntry(&SelectTE, 1);
14815 const TreeEntry *Op2TE = getOperandEntry(&SelectTE, 2);
14816 if (!Op1TE->isGather() || !Op2TE->isGather())
14817 return false;
14818 // No need to check for zeroes reordering.
14819 if (!Op1TE->ReorderIndices.empty() || !Op1TE->ReuseShuffleIndices.empty() ||
14820 !Op2TE->ReuseShuffleIndices.empty())
14821 return false;
14822 Type *ScalarTy = Op1TE->Scalars.front()->getType();
14823 if (!ScalarTy->isIntegerTy())
14824 return false;
14825 // Check that second operand is all zeroes.
14826 if (any_of(Op2TE->Scalars, [](Value *V) { return !match(V, m_ZeroInt()); }))
14827 return false;
14828 // Check that first operand is 1,2,4,...
14829 if (any_of(enumerate(Op1TE->Scalars), [](const auto &P) {
14830 uint64_t V;
14831 return !(match(P.value(), m_ConstantInt(V)) && isPowerOf2_64(V) &&
14832 Log2_64(V) == P.index());
14833 }))
14834 return false;
14835 // Check if bitcast is cheaper than select.
14836 auto *DstTy = IntegerType::getIntNTy(ScalarTy->getContext(),
14837 SelectTE.getVectorFactor());
14838 Type *OpTy = getWidenedType(DstTy, SelectTE.getVectorFactor());
14839 Type *CmpTy = CmpInst::makeCmpResultType(OpTy);
14840 auto *VecTy =
14841 cast<VectorType>(getWidenedType(ScalarTy, SelectTE.getVectorFactor()));
14842 auto It = MinBWs.find(&SelectTE);
14843 if (It != MinBWs.end()) {
14844 auto *EffectiveScalarTy =
14845 IntegerType::get(F->getContext(), It->second.first);
14846 VecTy = cast<VectorType>(
14847 getWidenedType(EffectiveScalarTy, SelectTE.getVectorFactor()));
14848 }
14849 InstructionCost BitcastCost = TTI->getCastInstrCost(
14850 Instruction::BitCast, DstTy, CmpTy, TTI::CastContextHint::None, CostKind);
14851 if (DstTy != ScalarTy) {
14852 BitcastCost += TTI->getCastInstrCost(Instruction::ZExt, ScalarTy, DstTy,
14853 TTI::CastContextHint::None, CostKind);
14854 }
14855 FastMathFlags FMF;
14856 InstructionCost SelectCost =
14857 TTI->getCmpSelInstrCost(Instruction::Select, VecTy, CmpTy,
14859 getOperandInfo(Op1TE->Scalars),
14860 getOperandInfo(Op2TE->Scalars)) +
14861 TTI->getArithmeticReductionCost(Instruction::Or, VecTy, FMF, CostKind);
14862 return BitcastCost <= SelectCost;
14863}
14864
14866 BaseGraphSize = VectorizableTree.size();
14867 // Turn graph transforming mode on and off, when done.
14868 class GraphTransformModeRAAI {
14869 bool &SavedIsGraphTransformMode;
14870
14871 public:
14872 GraphTransformModeRAAI(bool &IsGraphTransformMode)
14873 : SavedIsGraphTransformMode(IsGraphTransformMode) {
14874 IsGraphTransformMode = true;
14875 }
14876 ~GraphTransformModeRAAI() { SavedIsGraphTransformMode = false; }
14877 } TransformContext(IsGraphTransformMode);
14878 // Operands are profitable if they are:
14879 // 1. At least one constant
14880 // or
14881 // 2. Splats
14882 // or
14883 // 3. Results in good vectorization opportunity, i.e. may generate vector
14884 // nodes and reduce cost of the graph.
14885 auto CheckOperandsProfitability = [this](Instruction *I1, Instruction *I2,
14886 const InstructionsState &S) {
14888 for (unsigned Op : seq<unsigned>(S.getMainOp()->getNumOperands()))
14889 Candidates.emplace_back().emplace_back(I1->getOperand(Op),
14890 I2->getOperand(Op));
14891 return all_of(Candidates, [this](
14892 ArrayRef<std::pair<Value *, Value *>> Cand) {
14893 return all_of(Cand,
14894 [](const std::pair<Value *, Value *> &P) {
14895 return isa<Constant>(P.first) ||
14896 isa<Constant>(P.second) || P.first == P.second;
14897 }) ||
14899 });
14900 };
14901
14902 // Try to reorder gather nodes for better vectorization opportunities.
14903 for (unsigned Idx : seq<unsigned>(BaseGraphSize)) {
14904 TreeEntry &E = *VectorizableTree[Idx];
14905 if (E.isGather())
14906 reorderGatherNode(E);
14907 }
14908
14909 // Better to use full gathered loads analysis, if there are only 2 loads
14910 // gathered nodes each having less than 16 elements.
14911 constexpr unsigned VFLimit = 16;
14912 bool ForceLoadGather =
14913 count_if(VectorizableTree, [&](const std::unique_ptr<TreeEntry> &TE) {
14914 return TE->isGather() && TE->hasState() &&
14915 TE->getOpcode() == Instruction::Load &&
14916 TE->getVectorFactor() < VFLimit;
14917 }) == 2;
14918
14919 // Checks if the scalars are used in other node.
14920 auto AreReusedScalars = [&](const TreeEntry *TE, ArrayRef<Value *> VL,
14921 function_ref<bool(Value *)> CheckContainer) {
14922 return TE->isSame(VL) || all_of(VL, [&](Value *V) {
14923 if (isa<PoisonValue>(V))
14924 return true;
14925 auto *I = dyn_cast<Instruction>(V);
14926 if (!I)
14927 return false;
14928 return is_contained(TE->Scalars, I) || CheckContainer(I);
14929 });
14930 };
14931 auto CheckForSameVectorNodes = [&](const TreeEntry &E) {
14932 if (E.hasState()) {
14933 if (ArrayRef<TreeEntry *> TEs = getTreeEntries(E.getMainOp());
14934 !TEs.empty() && any_of(TEs, [&](const TreeEntry *TE) {
14935 return AreReusedScalars(TE, E.Scalars, [&](Value *V) {
14936 ArrayRef<TreeEntry *> VTEs = getTreeEntries(V);
14937 return !VTEs.empty() && any_of(VTEs, [&](const TreeEntry *TE) {
14938 return is_contained(TEs, TE);
14939 });
14940 });
14941 }))
14942 return true;
14943 ;
14944 if (ArrayRef<TreeEntry *> TEs = getSplitTreeEntries(E.getMainOp());
14945 !TEs.empty() && any_of(TEs, [&](const TreeEntry *TE) {
14946 return AreReusedScalars(TE, E.Scalars, [&](Value *V) {
14947 ArrayRef<TreeEntry *> VTEs = getSplitTreeEntries(V);
14948 return !VTEs.empty() && any_of(VTEs, [&](const TreeEntry *TE) {
14949 return is_contained(TEs, TE);
14950 });
14951 });
14952 }))
14953 return true;
14954 } else {
14955 // Check if the gather node full copy of split node.
14956 auto *It = find_if(E.Scalars, IsaPred<Instruction>);
14957 if (It != E.Scalars.end()) {
14958 if (ArrayRef<TreeEntry *> TEs = getSplitTreeEntries(*It);
14959 !TEs.empty() && any_of(TEs, [&](const TreeEntry *TE) {
14960 return AreReusedScalars(TE, E.Scalars, [&](Value *V) {
14961 ArrayRef<TreeEntry *> VTEs = getSplitTreeEntries(V);
14962 return !VTEs.empty() && any_of(VTEs, [&](const TreeEntry *TE) {
14963 return is_contained(TEs, TE);
14964 });
14965 });
14966 }))
14967 return true;
14968 }
14969 }
14970 return false;
14971 };
14972 // The tree may grow here, so iterate over nodes, built before.
14973 for (unsigned Idx : seq<unsigned>(BaseGraphSize)) {
14974 TreeEntry &E = *VectorizableTree[Idx];
14975 if (E.isGather()) {
14976 ArrayRef<Value *> VL = E.Scalars;
14977 const unsigned Sz = getVectorElementSize(VL.front());
14978 unsigned MinVF = getMinVF(2 * Sz);
14979 // Do not try partial vectorization for small nodes (<= 2), nodes with the
14980 // same opcode and same parent block or all constants.
14981 if (VL.size() <= 2 || LoadEntriesToVectorize.contains(Idx) ||
14982 !(!E.hasState() || E.getOpcode() == Instruction::Load ||
14983 // We use allSameOpcode instead of isAltShuffle because we don't
14984 // want to use interchangeable instruction here.
14985 !allSameOpcode(VL) || !allSameBlock(VL)) ||
14986 allConstant(VL) || isSplat(VL))
14987 continue;
14988 if (ForceLoadGather && E.hasState() && E.getOpcode() == Instruction::Load)
14989 continue;
14990 // Check if the node is a copy of other vector nodes.
14991 if (CheckForSameVectorNodes(E))
14992 continue;
14993 // Try to find vectorizable sequences and transform them into a series of
14994 // insertvector instructions.
14995 unsigned StartIdx = 0;
14996 unsigned End = VL.size();
14997 SmallBitVector Processed(End);
14998 for (unsigned VF = getFloorFullVectorNumberOfElements(
14999 *TTI, VL.front()->getType(), VL.size() - 1, SLPReVec);
15000 VF >= MinVF; VF = getFloorFullVectorNumberOfElements(
15001 *TTI, VL.front()->getType(), VF - 1, SLPReVec)) {
15002 if (StartIdx + VF > End)
15003 continue;
15005 bool AllStrided = true;
15006 // Walk the range in steps of VF, but allow the trailing slice to be
15007 // shorter (SliceVF < VF) so non-power-of-2 tails can be vectorized.
15008 // Processed only records slice starts (Cnt), and downstream consumers
15009 // (test(Cnt), AddCombinedNode's range set/StartIdx update) operate on
15010 // start positions, so partial coverage is consistent.
15011 for (unsigned Cnt = StartIdx; Cnt < End; Cnt += VF) {
15012 const unsigned SliceVF = std::min(VF, End - Cnt);
15013 if (SliceVF <= 1)
15014 continue;
15015 ArrayRef<Value *> Slice = VL.slice(Cnt, SliceVF);
15016 // If any instruction is vectorized already - do not try again.
15017 // Reuse the existing node, if it fully matches the slice.
15018 if ((Processed.test(Cnt) || isVectorized(Slice.front())) &&
15019 !getSameValuesTreeEntry(Slice.front(), Slice, /*SameVF=*/true))
15020 continue;
15021 // Constant already handled effectively - skip.
15022 if (allConstant(Slice))
15023 continue;
15024 // Do not try to vectorize small splats (less than vector register and
15025 // only with the single non-undef element).
15026 bool IsSplat = isSplat(Slice);
15027 bool IsTwoRegisterSplat = true;
15028 if (IsSplat && VF == 2) {
15029 unsigned NumRegs2VF = ::getNumberOfParts(
15030 *TTI,
15031 getWidenedType(getValueType(Slice.front(), SLPReVec), 2 * VF),
15032 getValueType(Slice.front(), SLPReVec));
15033 IsTwoRegisterSplat = NumRegs2VF == 2;
15034 }
15035 if (Slices.empty() || !IsSplat || !IsTwoRegisterSplat ||
15036 count(Slice, Slice.front()) ==
15037 static_cast<long>(isa<UndefValue>(Slice.front()) ? SliceVF - 1
15038 : 1)) {
15039 if (IsSplat)
15040 continue;
15041 InstructionsState S = getSameOpcode(Slice, *TLI);
15042 if (!S || !allSameOpcode(Slice) || !allSameBlock(Slice) ||
15043 (S.getOpcode() == Instruction::Load &&
15045 continue;
15046 if (VF == 2) {
15047 // Cache the cost check lazily - both branches below may need it.
15048 std::optional<bool> MainOpIsCheap;
15049 auto IsMainOpCheap = [&] {
15050 if (!MainOpIsCheap)
15051 MainOpIsCheap =
15052 TTI->getInstructionCost(S.getMainOp(), CostKind) <
15054 return *MainOpIsCheap;
15055 };
15056 // Try to vectorize reduced values or if all users are vectorized.
15057 // For expensive instructions extra extracts might be profitable.
15058 if ((!UserIgnoreList || E.Idx != 0) && IsMainOpCheap() &&
15059 !all_of(Slice, [&](Value *V) {
15060 if (isa<PoisonValue>(V))
15061 return true;
15062 return areAllUsersVectorized(cast<Instruction>(V),
15063 UserIgnoreList);
15064 }))
15065 continue;
15066 if (S.getOpcode() == Instruction::Load) {
15067 OrdersType Order;
15068 SmallVector<Value *> PointerOps;
15069 StridedPtrInfo SPtrInfo;
15070 LoadsState Res = canVectorizeLoads(Slice, Slice.front(), Order,
15071 PointerOps, SPtrInfo);
15072 AllStrided &= Res == LoadsState::StridedVectorize ||
15074 Res == LoadsState::Gather;
15075 // Do not vectorize gathers.
15076 if (Res == LoadsState::ScatterVectorize ||
15077 Res == LoadsState::Gather) {
15078 if (Res == LoadsState::Gather) {
15080 // If reductions and the scalars from the root node are
15081 // analyzed - mark as non-vectorizable reduction.
15082 if (UserIgnoreList && E.Idx == 0)
15083 analyzedReductionVals(Slice);
15084 }
15085 continue;
15086 }
15087 } else if (S.getOpcode() == Instruction::ExtractElement ||
15088 (IsMainOpCheap() &&
15089 !CheckOperandsProfitability(
15090 S.getMainOp(),
15093 S))) {
15094 // Do not vectorize extractelements (handled effectively
15095 // alread). Do not vectorize non-profitable instructions (with
15096 // low cost and non-vectorizable operands.)
15097 continue;
15098 }
15099 }
15100 }
15101 Slices.emplace_back(Cnt, Slice.size());
15102 }
15103 // Do not try to vectorize if all slides are strided or gathered with
15104 // vector factor 2 and there are more than 2 slices. Better to handle
15105 // them in gathered loads analysis, may result in better vectorization.
15106 if (VF == 2 && AllStrided && Slices.size() > 2)
15107 continue;
15108 auto AddCombinedNode = [&](unsigned Idx, unsigned Cnt, unsigned Sz) {
15109 E.CombinedEntriesWithIndices.emplace_back(Idx, Cnt);
15110 Processed.set(Cnt, Cnt + Sz);
15111 if (StartIdx == Cnt)
15112 StartIdx = Cnt + Sz;
15113 if (End == Cnt + Sz)
15114 End = Cnt;
15115 };
15116 for (auto [Cnt, Sz] : Slices) {
15117 ArrayRef<Value *> Slice = VL.slice(Cnt, Sz);
15118 const TreeEntry *SameTE = nullptr;
15119 if (const auto *It = find_if(Slice, IsaPred<Instruction>);
15120 It != Slice.end()) {
15121 // If any instruction is vectorized already - do not try again.
15122 SameTE = getSameValuesTreeEntry(*It, Slice);
15123 }
15124 unsigned PrevSize = VectorizableTree.size();
15125 [[maybe_unused]] unsigned PrevEntriesSize =
15126 LoadEntriesToVectorize.size();
15127 buildTreeRec(Slice, 0, EdgeInfo(&E, UINT_MAX));
15128 if (PrevSize + 1 == VectorizableTree.size() && !SameTE &&
15129 VectorizableTree[PrevSize]->isGather() &&
15130 VectorizableTree[PrevSize]->hasState() &&
15131 VectorizableTree[PrevSize]->getOpcode() !=
15132 Instruction::ExtractElement &&
15133 !isSplat(Slice)) {
15134 if (UserIgnoreList && E.Idx == 0 && VF == 2)
15135 analyzedReductionVals(Slice);
15136 VectorizableTree.pop_back();
15137 assert(PrevEntriesSize == LoadEntriesToVectorize.size() &&
15138 "LoadEntriesToVectorize expected to remain the same");
15139 continue;
15140 }
15141 AddCombinedNode(PrevSize, Cnt, Sz);
15142 }
15143 }
15144 // Restore ordering, if no extra vectorization happened.
15145 if (E.CombinedEntriesWithIndices.empty() && !E.ReorderIndices.empty()) {
15146 SmallVector<int> Mask(E.ReorderIndices.begin(), E.ReorderIndices.end());
15147 reorderScalars(E.Scalars, Mask);
15148 E.ReorderIndices.clear();
15149 }
15150 }
15151 if (!E.hasState())
15152 continue;
15153 switch (E.getOpcode()) {
15154 case Instruction::Load: {
15155 // No need to reorder masked gather loads, just reorder the scalar
15156 // operands.
15157 if (E.State != TreeEntry::Vectorize)
15158 break;
15159 Type *ScalarTy = E.getMainOp()->getType();
15160 auto *VecTy =
15161 cast<FixedVectorType>(getWidenedType(ScalarTy, E.Scalars.size()));
15162 Align CommonAlignment = computeCommonAlignment<LoadInst>(E.Scalars);
15163 // Check if profitable to represent consecutive load + reverse as strided
15164 // load with stride -1.
15165 if (!E.ReorderIndices.empty() && isReverseOrder(E.ReorderIndices) &&
15166 TTI->isLegalStridedLoadStore(VecTy, CommonAlignment)) {
15167 SmallVector<int> Mask;
15168 inversePermutation(E.ReorderIndices, Mask);
15169 auto *BaseLI = cast<LoadInst>(E.Scalars.back());
15170 InstructionCost OriginalVecCost =
15171 TTI->getMemoryOpCost(Instruction::Load, VecTy, BaseLI->getAlign(),
15172 BaseLI->getPointerAddressSpace(), CostKind,
15174 getShuffleCost(*TTI, TTI::SK_Reverse, VecTy, CostKind, Mask);
15175 InstructionCost StridedCost = TTI->getMemIntrinsicInstrCost(
15176 MemIntrinsicCostAttributes(Intrinsic::experimental_vp_strided_load,
15177 VecTy, BaseLI->getPointerOperand(),
15178 /*VariableMask=*/false, CommonAlignment,
15179 BaseLI),
15180 CostKind);
15181 if (StridedCost < OriginalVecCost || ForceStridedLoads) {
15182 // Strided load is more profitable than consecutive load + reverse -
15183 // transform the node to strided load.
15184 Type *StrideTy = DL->getIndexType(cast<LoadInst>(E.Scalars.front())
15185 ->getPointerOperand()
15186 ->getType());
15187 StridedPtrInfo SPtrInfo;
15188 SPtrInfo.StrideVal = ConstantInt::get(StrideTy, 1);
15189 SPtrInfo.Ty = VecTy;
15190 TreeEntryToStridedPtrInfoMap[&E] = SPtrInfo;
15191 E.State = TreeEntry::StridedVectorize;
15192 }
15193 }
15194 break;
15195 }
15196 case Instruction::Store: {
15197 if (E.State == TreeEntry::ExpandVectorize)
15198 break;
15199 Type *ScalarTy =
15200 cast<StoreInst>(E.getMainOp())->getValueOperand()->getType();
15201 auto *VecTy =
15202 cast<FixedVectorType>(getWidenedType(ScalarTy, E.Scalars.size()));
15203 Align CommonAlignment = computeCommonAlignment<StoreInst>(E.Scalars);
15204 // Check if profitable to represent consecutive load + reverse as strided
15205 // load with stride -1.
15206 if (!E.ReorderIndices.empty() && isReverseOrder(E.ReorderIndices) &&
15207 TTI->isLegalStridedLoadStore(VecTy, CommonAlignment)) {
15208 SmallVector<int> Mask;
15209 inversePermutation(E.ReorderIndices, Mask);
15210 auto *BaseSI = cast<StoreInst>(E.Scalars.back());
15211 InstructionCost OriginalVecCost =
15212 TTI->getMemoryOpCost(Instruction::Store, VecTy, BaseSI->getAlign(),
15213 BaseSI->getPointerAddressSpace(), CostKind,
15215 getShuffleCost(*TTI, TTI::SK_Reverse, VecTy, CostKind, Mask);
15216 InstructionCost StridedCost = TTI->getMemIntrinsicInstrCost(
15217 MemIntrinsicCostAttributes(Intrinsic::experimental_vp_strided_store,
15218 VecTy, BaseSI->getPointerOperand(),
15219 /*VariableMask=*/false, CommonAlignment,
15220 BaseSI),
15221 CostKind);
15222 if (StridedCost < OriginalVecCost) {
15223 // Strided store is more profitable than reverse + consecutive store -
15224 // transform the node to strided store.
15225 E.State = TreeEntry::StridedVectorize;
15226 Type *StrideTy = DL->getIndexType(cast<StoreInst>(E.Scalars.front())
15227 ->getPointerOperand()
15228 ->getType());
15229 StridedPtrInfo SPtrInfo;
15230 SPtrInfo.StrideVal = ConstantInt::getSigned(StrideTy, -1);
15231 SPtrInfo.Ty = VecTy;
15232 TreeEntryToStridedPtrInfoMap[&E] = SPtrInfo;
15233 }
15234 } else if (!E.ReorderIndices.empty()) {
15235 // Check for interleaved stores.
15236 auto IsInterleaveMask = [&, &TTI = *TTI](ArrayRef<int> Mask) {
15237 auto *BaseSI = cast<StoreInst>(E.Scalars.front());
15238 assert(Mask.size() > 1 && "Expected mask greater than 1 element.");
15239 if (Mask.size() < 4)
15240 return 0u;
15241 for (unsigned Factor : seq<unsigned>(2, Mask.size() / 2 + 1)) {
15243 Mask, Factor, VecTy->getElementCount().getFixedValue()) &&
15244 TTI.isLegalInterleavedAccessType(
15245 VecTy, Factor, BaseSI->getAlign(),
15246 BaseSI->getPointerAddressSpace()))
15247 return Factor;
15248 }
15249
15250 return 0u;
15251 };
15252 SmallVector<int> Mask(E.ReorderIndices.begin(), E.ReorderIndices.end());
15253 unsigned InterleaveFactor = IsInterleaveMask(Mask);
15254 if (InterleaveFactor != 0)
15255 E.setInterleave(InterleaveFactor);
15256 }
15257 break;
15258 }
15259 case Instruction::Select: {
15260 if (E.State != TreeEntry::Vectorize)
15261 break;
15262 auto [MinMaxID, SelectOnly] = canConvertToMinOrMaxIntrinsic(E.Scalars);
15263 if (MinMaxID != Intrinsic::not_intrinsic) {
15264 // This node is a minmax node.
15265 E.CombinedOp = TreeEntry::MinMax;
15266 TreeEntry *CondEntry = getOperandEntry(&E, 0);
15267 if (SelectOnly && CondEntry->UserTreeIndex &&
15268 CondEntry->State == TreeEntry::Vectorize) {
15269 // The condition node is part of the combined minmax node.
15270 CondEntry->State = TreeEntry::CombinedVectorize;
15271 }
15272 break;
15273 }
15274 // Check for zext + selects, which can be reordered.
15275 SmallVector<unsigned> InversedCmpsIndices;
15276 if (matchesInversedZExtSelect(E, InversedCmpsIndices)) {
15277 auto *CmpTE = getOperandEntry(&E, 0);
15278 auto *Op1TE = getOperandEntry(&E, 1);
15279 auto *Op2TE = getOperandEntry(&E, 2);
15280 // State now is uniform, not alternate opcode.
15281 CmpTE->setOperations(
15282 InstructionsState(CmpTE->getMainOp(), CmpTE->getMainOp()));
15283 // Update mapping between the swapped values and their internal matching
15284 // nodes.
15285 auto UpdateGatherEntry = [&](TreeEntry *OldTE, TreeEntry *NewTE,
15286 Value *V) {
15287 if (isConstant(V))
15288 return;
15289 auto It = ValueToGatherNodes.find(V);
15290 assert(It != ValueToGatherNodes.end() &&
15291 "Expected to find the value in the map.");
15292 auto &C = It->getSecond();
15293 if (!is_contained(OldTE->Scalars, V))
15294 C.remove(OldTE);
15295 C.insert(NewTE);
15296 };
15297 ValueList &Op1 = E.getOperand(1);
15298 ValueList &Op2 = E.getOperand(2);
15299 for (const unsigned Idx : InversedCmpsIndices) {
15300 Value *V1 = Op1TE->Scalars[Idx];
15301 Value *V2 = Op2TE->Scalars[Idx];
15302 std::swap(Op1TE->Scalars[Idx], Op2TE->Scalars[Idx]);
15303 std::swap(Op1[Idx], Op2[Idx]);
15304 UpdateGatherEntry(Op1TE, Op2TE, V1);
15305 UpdateGatherEntry(Op2TE, Op1TE, V2);
15306 }
15307 OperandsToTreeEntry.emplace_or_assign(std::make_pair(&E, 1), Op1TE);
15308 OperandsToTreeEntry.emplace_or_assign(std::make_pair(&E, 2), Op2TE);
15309 // NB: Fallback to check if select can be converted to cmp bitcast.
15310 }
15311 if (matchesSelectOfBits(E)) {
15312 // This node is a (reduced or) cmp bitcast node.
15313 const TreeEntry::CombinedOpcode Code = TreeEntry::ReducedCmpBitcast;
15314 E.CombinedOp = Code;
15315 auto *Op1TE = getOperandEntry(&E, 1);
15316 auto *Op2TE = getOperandEntry(&E, 2);
15317 Op1TE->State = TreeEntry::CombinedVectorize;
15318 Op1TE->CombinedOp = Code;
15319 Op2TE->State = TreeEntry::CombinedVectorize;
15320 Op2TE->CombinedOp = Code;
15321 break;
15322 }
15323 break;
15324 }
15325 case Instruction::FSub:
15326 case Instruction::FAdd: {
15327 // Check if possible to convert (a*b)+c to fma; fma takes exactly two
15328 // operands, so bail out on reassociated (>2-operand) nodes.
15329 if (E.State != TreeEntry::Vectorize ||
15330 !E.getOperations().isAddSubLikeOp() ||
15331 E.getOperations().isAltShuffle() || E.getNumOperands() != 2)
15332 break;
15333 const TreeEntry *LHS = getOperandEntry(&E, 0);
15334 const TreeEntry *RHS = getOperandEntry(&E, 1);
15335 auto IsOneUseVectorFMulOperand = [](const TreeEntry *TE) {
15336 return TE->State == TreeEntry::Vectorize &&
15337 TE->ReorderIndices.empty() && TE->ReuseShuffleIndices.empty() &&
15338 TE->getOpcode() == Instruction::FMul && !TE->isAltShuffle() &&
15339 all_of(TE->Scalars, [&](Value *V) {
15340 return (TE->hasCopyableElements() &&
15341 TE->isCopyableElement(V)) ||
15342 V->hasOneUse();
15343 });
15344 };
15345 if (!IsOneUseVectorFMulOperand(LHS) &&
15346 (E.getOpcode() == Instruction::FSub ||
15347 !IsOneUseVectorFMulOperand(RHS)))
15348 break;
15349 if (!canConvertToFMA(E.Scalars, E.getOperations(), *DT, *DL, *TTI, *TLI,
15350 CostKind)
15351 .isValid())
15352 break;
15353 // This node is a fmuladd node.
15354 E.CombinedOp = TreeEntry::FMulAdd;
15355 TreeEntry *FMulEntry = getOperandEntry(&E, 0);
15356 if (FMulEntry->UserTreeIndex &&
15357 FMulEntry->State == TreeEntry::Vectorize) {
15358 // The FMul node is part of the combined fmuladd node.
15359 FMulEntry->State = TreeEntry::CombinedVectorize;
15360 }
15361 break;
15362 }
15363 case Instruction::Shl: {
15364 // Shl is not reassociated; guard since this case indexes operands 0/1.
15365 if (E.getNumOperands() != 2)
15366 break;
15367 if (E.Idx != 0 || DL->isBigEndian())
15368 break;
15369 if (!UserIgnoreList)
15370 break;
15371 // Check that all reduction operands are disjoint or instructions.
15372 if (any_of(*UserIgnoreList, [](Value *V) {
15373 return !match(V, m_DisjointOr(m_Value(), m_Value()));
15374 }))
15375 break;
15376 OrdersType Order;
15377 bool IsBSwap;
15378 bool ForLoads;
15379 if (!matchesShlZExt(E, Order, IsBSwap, ForLoads))
15380 break;
15381 // This node is a (reduced disjoint or) bitcast node.
15382 TreeEntry::CombinedOpcode Code =
15383 IsBSwap ? (ForLoads ? TreeEntry::ReducedBitcastBSwapLoads
15384 : TreeEntry::ReducedBitcastBSwap)
15385 : (ForLoads ? TreeEntry::ReducedBitcastLoads
15386 : TreeEntry::ReducedBitcast);
15387 E.CombinedOp = Code;
15388 E.ReorderIndices = std::move(Order);
15389 TreeEntry *ZExtEntry = getOperandEntry(&E, 0);
15390 assert(ZExtEntry->UserTreeIndex &&
15391 ZExtEntry->State == TreeEntry::Vectorize &&
15392 ZExtEntry->getOpcode() == Instruction::ZExt &&
15393 "Expected ZExt node.");
15394 // The ZExt node is part of the combined node.
15395 ZExtEntry->State = TreeEntry::CombinedVectorize;
15396 ZExtEntry->CombinedOp = Code;
15397 if (ForLoads) {
15398 TreeEntry *LoadsEntry = getOperandEntry(ZExtEntry, 0);
15399 assert(LoadsEntry->UserTreeIndex &&
15400 LoadsEntry->State == TreeEntry::Vectorize &&
15401 LoadsEntry->getOpcode() == Instruction::Load &&
15402 "Expected Load node.");
15403 // The Load node is part of the combined node.
15404 LoadsEntry->State = TreeEntry::CombinedVectorize;
15405 LoadsEntry->CombinedOp = Code;
15406 }
15407 TreeEntry *ConstEntry = getOperandEntry(&E, 1);
15408 assert(ConstEntry->UserTreeIndex && ConstEntry->isGather() &&
15409 "Expected ZExt node.");
15410 // The ConstNode node is part of the combined node.
15411 ConstEntry->State = TreeEntry::CombinedVectorize;
15412 ConstEntry->CombinedOp = Code;
15413 break;
15414 }
15415 default:
15416 break;
15417 }
15418 }
15419
15420 if (LoadEntriesToVectorize.empty()) {
15421 // Single load node - exit.
15422 if (VectorizableTree.size() <= 1 && getRootNode().hasState() &&
15423 getRootNode().getOpcode() == Instruction::Load)
15424 return;
15425 // Small graph with small VF - exit.
15426 constexpr unsigned SmallTree = 3;
15427 constexpr unsigned SmallVF = 2;
15428 if ((VectorizableTree.size() <= SmallTree &&
15429 getRootNodeScalars().size() == SmallVF) ||
15430 (VectorizableTree.size() <= 2 && UserIgnoreList))
15431 return;
15432
15433 if (getRootNode().isNonPowOf2Vec() &&
15434 getCanonicalGraphSize() != getTreeSize() && UserIgnoreList &&
15435 getCanonicalGraphSize() <= SmallTree &&
15436 count_if(ArrayRef(VectorizableTree).drop_front(getCanonicalGraphSize()),
15437 [](const std::unique_ptr<TreeEntry> &TE) {
15438 return TE->isGather() && TE->hasState() &&
15439 TE->getOpcode() == Instruction::Load &&
15440 !allSameBlock(TE->Scalars);
15441 }) == 1)
15442 return;
15443 }
15444
15445 // A list of loads to be gathered during the vectorization process. We can
15446 // try to vectorize them at the end, if profitable.
15447 SmallMapVector<std::tuple<BasicBlock *, Value *, Type *>,
15449 GatheredLoads;
15450
15451 for (std::unique_ptr<TreeEntry> &TE : VectorizableTree) {
15452 TreeEntry &E = *TE;
15453 if (E.isGather() &&
15454 ((E.hasState() && E.getOpcode() == Instruction::Load) ||
15455 (!E.hasState() && any_of(E.Scalars,
15456 [&](Value *V) {
15457 return isa<LoadInst>(V) &&
15458 !isVectorized(V) &&
15459 !isDeleted(cast<Instruction>(V));
15460 }))) &&
15461 !isSplat(E.Scalars)) {
15462 for (Value *V : E.Scalars) {
15463 auto *LI = dyn_cast<LoadInst>(V);
15464 if (!LI)
15465 continue;
15466 if (isDeleted(LI) || isVectorized(LI) || !LI->isSimple())
15467 continue;
15469 *this, V, *DL, *SE, *TTI,
15470 GatheredLoads[std::make_tuple(
15471 LI->getParent(),
15472 getUnderlyingObject(LI->getPointerOperand(), RecursionMaxDepth),
15473 LI->getType())]);
15474 }
15475 }
15476 }
15477 // Try to vectorize gathered loads if this is not just a gather of loads.
15478 if (!GatheredLoads.empty())
15479 tryToVectorizeGatheredLoads(GatheredLoads);
15480}
15481
15482/// Merges shuffle masks and emits final shuffle instruction, if required. It
15483/// supports shuffling of 2 input vectors. It implements lazy shuffles emission,
15484/// when the actual shuffle instruction is generated only if this is actually
15485/// required. Otherwise, the shuffle instruction emission is delayed till the
15486/// end of the process, to reduce the number of emitted instructions and further
15487/// analysis/transformations.
15488class BoUpSLP::ShuffleCostEstimator : public BaseShuffleAnalysis {
15489 bool IsFinalized = false;
15490 SmallVector<int> CommonMask;
15492 /// Captures the original scalar VL of a single, "clean" gather() call so
15493 /// the values can be forwarded as the Args operand to getShuffleCost() for
15494 /// the final permutation in finalize(). This lets the target cost model
15495 /// recognize patterns such as broadcast-of-load (e.g. on X86,
15496 /// vbroadcast{ss,sd} folds the broadcast and the load into one instruction
15497 /// under AVX/AVX2 and is reported as TCC_Free by getShuffleCost). The
15498 /// state machine is:
15499 /// * engaged + empty: tracking active, no qualifying gather seen yet.
15500 /// * engaged + non-empty: exactly one qualifying gather observed and its
15501 /// VL still corresponds to InVectors.front().
15502 /// * disengaged: the cached VL is no longer trustworthy (multiple
15503 /// gather() calls, or a state-mutating add() happened).
15504 std::optional<SmallVector<Value *>> BVValues = SmallVector<Value *>();
15505 const TargetTransformInfo &TTI;
15506 InstructionCost Cost = 0;
15507 SmallDenseSet<Value *> VectorizedVals;
15508 BoUpSLP &R;
15509 SmallPtrSetImpl<Value *> &CheckedExtracts;
15510 const TTI::TargetCostKind CostKind;
15511 /// While set, still trying to estimate the cost for the same nodes and we
15512 /// can delay actual cost estimation (virtual shuffle instruction emission).
15513 /// May help better estimate the cost if same nodes must be permuted + allows
15514 /// to move most of the long shuffles cost estimation to TTI.
15515 bool SameNodesEstimated = true;
15516
15517 static Constant *getAllOnesValue(const DataLayout &DL, Type *Ty) {
15518 if (Ty->getScalarType()->isPointerTy()) {
15521 IntegerType::get(Ty->getContext(),
15522 DL.getTypeStoreSizeInBits(Ty->getScalarType()))),
15523 Ty->getScalarType());
15524 if (auto *VTy = dyn_cast<VectorType>(Ty))
15525 Res = ConstantVector::getSplat(VTy->getElementCount(), Res);
15526 return Res;
15527 }
15528 return Constant::getAllOnesValue(Ty);
15529 }
15530
15531 InstructionCost getBuildVectorCost(ArrayRef<Value *> VL, Value *Root) {
15532 if ((!Root && allConstant(VL)) || all_of(VL, IsaPred<UndefValue>))
15533 return TTI::TCC_Free;
15534 auto *VecTy = cast<VectorType>(getWidenedType(ScalarTy, VL.size()));
15535 InstructionCost GatherCost = 0;
15536 SmallVector<Value *> Gathers(VL);
15537 if (!Root && isSplat(VL)) {
15538 // Found the broadcasting of the single scalar, calculate the cost as
15539 // the broadcast.
15540 const auto *It = find_if_not(VL, IsaPred<UndefValue>);
15541 assert(It != VL.end() && "Expected at least one non-undef value.");
15542 // Add broadcast for non-identity shuffle only.
15543 bool NeedShuffle =
15544 count(VL, *It) > 1 &&
15545 (VL.front() != *It || !all_of(VL.drop_front(), IsaPred<UndefValue>));
15546 if (!NeedShuffle) {
15547 if (isa<FixedVectorType>(ScalarTy)) {
15548 assert(SLPReVec && "FixedVectorType is not expected.");
15549 return TTI.getShuffleCost(
15550 TTI::SK_InsertSubvector, VecTy, VecTy, CostKind, {},
15551 std::distance(VL.begin(), It) * getNumElements(ScalarTy),
15552 cast<FixedVectorType>(ScalarTy));
15553 }
15554 return TTI.getVectorInstrCost(Instruction::InsertElement, VecTy,
15555 CostKind, std::distance(VL.begin(), It),
15556 PoisonValue::get(VecTy), *It);
15557 }
15558
15559 SmallVector<int> ShuffleMask(VL.size(), PoisonMaskElem);
15560 transform(VL, ShuffleMask.begin(), [](Value *V) {
15561 return isa<PoisonValue>(V) ? PoisonMaskElem : 0;
15562 });
15563 InstructionCost InsertCost =
15564 TTI.getVectorInstrCost(Instruction::InsertElement, VecTy, CostKind, 0,
15565 PoisonValue::get(VecTy), *It);
15566 return InsertCost + getShuffleCost(TTI, TargetTransformInfo::SK_Broadcast,
15567 VecTy, CostKind, ShuffleMask,
15568 /*Index=*/0, /*SubTp=*/nullptr,
15569 /*Args=*/*It);
15570 }
15571 return GatherCost +
15572 (all_of(Gathers, IsaPred<UndefValue>)
15574 : R.getGatherCost(Gathers, !Root && VL.equals(Gathers),
15575 ScalarTy));
15576 };
15577
15578 /// Compute the cost of creating a vector containing the extracted values from
15579 /// \p VL.
15581 computeExtractCost(ArrayRef<Value *> VL, ArrayRef<int> Mask,
15582 ArrayRef<std::optional<TTI::ShuffleKind>> ShuffleKinds,
15583 unsigned NumParts) {
15584 assert(VL.size() > NumParts && "Unexpected scalarized shuffle.");
15585 unsigned NumElts = accumulate(VL, 0, [](unsigned Sz, Value *V) {
15586 auto *EE = dyn_cast<ExtractElementInst>(V);
15587 if (!EE)
15588 return Sz;
15589 auto *VecTy = dyn_cast<FixedVectorType>(EE->getVectorOperandType());
15590 if (!VecTy)
15591 return Sz;
15592 return std::max(Sz, VecTy->getNumElements());
15593 });
15594 // FIXME: this must be moved to TTI for better estimation.
15595 unsigned EltsPerVector = getPartNumElems(VL.size(), NumParts);
15596 auto CheckPerRegistersShuffle = [&](MutableArrayRef<int> Mask,
15598 SmallVectorImpl<unsigned> &SubVecSizes)
15599 -> std::optional<TTI::ShuffleKind> {
15600 if (NumElts <= EltsPerVector)
15601 return std::nullopt;
15602 int OffsetReg0 = alignDown(accumulate(Mask, INT_MAX,
15603 [](int S, int I) {
15604 if (I == PoisonMaskElem)
15605 return S;
15606 return std::min(S, I);
15607 }),
15608 EltsPerVector);
15609 int OffsetReg1 = OffsetReg0;
15610 DenseSet<int> RegIndices;
15611 // Check that if trying to permute same single/2 input vectors.
15613 int FirstRegId = -1;
15614 Indices.assign(1, OffsetReg0);
15615 for (auto [Pos, I] : enumerate(Mask)) {
15616 if (I == PoisonMaskElem)
15617 continue;
15618 int Idx = I - OffsetReg0;
15619 int RegId =
15620 (Idx / NumElts) * NumParts + (Idx % NumElts) / EltsPerVector;
15621 if (FirstRegId < 0)
15622 FirstRegId = RegId;
15623 RegIndices.insert(RegId);
15624 if (RegIndices.size() > 2)
15625 return std::nullopt;
15626 if (RegIndices.size() == 2) {
15627 ShuffleKind = TTI::SK_PermuteTwoSrc;
15628 if (Indices.size() == 1) {
15629 OffsetReg1 = alignDown(
15630 std::accumulate(
15631 std::next(Mask.begin(), Pos), Mask.end(), INT_MAX,
15632 [&](int S, int I) {
15633 if (I == PoisonMaskElem)
15634 return S;
15635 int RegId = ((I - OffsetReg0) / NumElts) * NumParts +
15636 ((I - OffsetReg0) % NumElts) / EltsPerVector;
15637 if (RegId == FirstRegId)
15638 return S;
15639 return std::min(S, I);
15640 }),
15641 EltsPerVector);
15642 unsigned Index = OffsetReg1 % NumElts;
15643 Indices.push_back(Index);
15644 SubVecSizes.push_back(std::min(NumElts - Index, EltsPerVector));
15645 }
15646 Idx = I - OffsetReg1;
15647 }
15648 I = (Idx % NumElts) % EltsPerVector +
15649 (RegId == FirstRegId ? 0 : EltsPerVector);
15650 }
15651 return ShuffleKind;
15652 };
15653 InstructionCost Cost = 0;
15654
15655 // Process extracts in blocks of EltsPerVector to check if the source vector
15656 // operand can be re-used directly. If not, add the cost of creating a
15657 // shuffle to extract the values into a vector register.
15658 for (unsigned Part : seq<unsigned>(NumParts)) {
15659 if (!ShuffleKinds[Part])
15660 continue;
15661 ArrayRef<int> MaskSlice = Mask.slice(
15662 Part * EltsPerVector, getNumElems(Mask.size(), EltsPerVector, Part));
15663 SmallVector<int> SubMask(EltsPerVector, PoisonMaskElem);
15664 copy(MaskSlice, SubMask.begin());
15666 SmallVector<unsigned, 2> SubVecSizes;
15667 std::optional<TTI::ShuffleKind> RegShuffleKind =
15668 CheckPerRegistersShuffle(SubMask, Indices, SubVecSizes);
15669 if (!RegShuffleKind) {
15670 if (*ShuffleKinds[Part] != TTI::SK_PermuteSingleSrc ||
15672 MaskSlice, std::max<unsigned>(NumElts, MaskSlice.size())))
15673 Cost += getShuffleCost(
15674 TTI, *ShuffleKinds[Part],
15675 cast<VectorType>(getWidenedType(ScalarTy, NumElts)), CostKind,
15676 MaskSlice);
15677 continue;
15678 }
15679 if (*RegShuffleKind != TTI::SK_PermuteSingleSrc ||
15680 !ShuffleVectorInst::isIdentityMask(SubMask, EltsPerVector)) {
15681 Cost += getShuffleCost(
15682 TTI, *RegShuffleKind,
15683 cast<VectorType>(getWidenedType(ScalarTy, EltsPerVector)), CostKind,
15684 SubMask);
15685 }
15686 const unsigned BaseVF = getFullVectorNumberOfElements(
15687 *R.TTI, VL.front()->getType(), alignTo(NumElts, EltsPerVector),
15688 SLPReVec);
15689 for (const auto [Idx, SubVecSize] : zip(Indices, SubVecSizes)) {
15690 assert((Idx + SubVecSize) <= BaseVF &&
15691 "SK_ExtractSubvector index out of range");
15692 Cost += getShuffleCost(
15694 cast<VectorType>(getWidenedType(ScalarTy, BaseVF)), CostKind, {},
15695 Idx, cast<VectorType>(getWidenedType(ScalarTy, SubVecSize)));
15696 }
15697 // Second attempt to check, if just a permute is better estimated than
15698 // subvector extract.
15699 SubMask.assign(NumElts, PoisonMaskElem);
15700 copy(MaskSlice, SubMask.begin());
15701 InstructionCost OriginalCost =
15702 getShuffleCost(TTI, *ShuffleKinds[Part],
15703 cast<VectorType>(getWidenedType(ScalarTy, NumElts)),
15704 CostKind, SubMask);
15705 if (OriginalCost < Cost)
15706 Cost = OriginalCost;
15707 }
15708 return Cost;
15709 }
15710 /// Adds the cost of reshuffling \p E1 and \p E2 (if present), using given
15711 /// mask \p Mask, register number \p Part, that includes \p SliceSize
15712 /// elements.
15713 void estimateNodesPermuteCost(const TreeEntry &E1, const TreeEntry *E2,
15714 ArrayRef<int> Mask, unsigned Part,
15715 unsigned SliceSize) {
15716 if (SameNodesEstimated) {
15717 // Delay the cost estimation if the same nodes are reshuffling.
15718 // If we already requested the cost of reshuffling of E1 and E2 before, no
15719 // need to estimate another cost with the sub-Mask, instead include this
15720 // sub-Mask into the CommonMask to estimate it later and avoid double cost
15721 // estimation.
15722 if ((InVectors.size() == 2 &&
15723 cast<const TreeEntry *>(InVectors.front()) == &E1 &&
15724 cast<const TreeEntry *>(InVectors.back()) == E2) ||
15725 (!E2 && cast<const TreeEntry *>(InVectors.front()) == &E1)) {
15726 unsigned Limit = getNumElems(Mask.size(), SliceSize, Part);
15727 assert(all_of(ArrayRef(CommonMask).slice(Part * SliceSize, Limit),
15728 [](int Idx) { return Idx == PoisonMaskElem; }) &&
15729 "Expected all poisoned elements.");
15730 ArrayRef<int> SubMask = ArrayRef(Mask).slice(Part * SliceSize, Limit);
15731 copy(SubMask, std::next(CommonMask.begin(), SliceSize * Part));
15732 return;
15733 }
15734 // Found non-matching nodes - need to estimate the cost for the matched
15735 // and transform mask.
15736 Cost += createShuffle(InVectors.front(),
15737 InVectors.size() == 1 ? nullptr : InVectors.back(),
15738 CommonMask);
15739 transformMaskAfterShuffle(CommonMask, CommonMask);
15740 } else if (InVectors.size() == 2) {
15741 Cost += createShuffle(InVectors.front(), InVectors.back(), CommonMask);
15742 transformMaskAfterShuffle(CommonMask, CommonMask);
15743 }
15744 SameNodesEstimated = false;
15745 if (!E2 && InVectors.size() == 1) {
15746 unsigned VF = E1.getVectorFactor();
15747 if (Value *V1 = dyn_cast<Value *>(InVectors.front())) {
15748 VF = std::max(VF, getVF(V1));
15749 } else {
15750 const auto *E = cast<const TreeEntry *>(InVectors.front());
15751 VF = std::max(VF, E->getVectorFactor());
15752 }
15753 for (unsigned Idx = 0, Sz = CommonMask.size(); Idx < Sz; ++Idx)
15754 if (Mask[Idx] != PoisonMaskElem && CommonMask[Idx] == PoisonMaskElem)
15755 CommonMask[Idx] = Mask[Idx] + VF;
15756 Cost += createShuffle(InVectors.front(), &E1, CommonMask);
15757 transformMaskAfterShuffle(CommonMask, CommonMask);
15758 } else {
15759 auto P = InVectors.front();
15760 Cost += createShuffle(&E1, E2, Mask);
15761 unsigned VF = Mask.size();
15762 if (Value *V1 = dyn_cast<Value *>(P)) {
15763 VF = std::max(VF,
15764 getNumElements(V1->getType()));
15765 } else {
15766 const auto *E = cast<const TreeEntry *>(P);
15767 VF = std::max(VF, E->getVectorFactor());
15768 }
15769 for (unsigned Idx = 0, Sz = CommonMask.size(); Idx < Sz; ++Idx)
15770 if (Mask[Idx] != PoisonMaskElem)
15771 CommonMask[Idx] = Idx + (InVectors.empty() ? 0 : VF);
15772 Cost += createShuffle(P, InVectors.front(), CommonMask);
15773 transformMaskAfterShuffle(CommonMask, CommonMask);
15774 }
15775 }
15776
15777 class ShuffleCostBuilder {
15778 const TargetTransformInfo &TTI;
15779 const TTI::TargetCostKind CostKind;
15780
15781 static bool isEmptyOrIdentity(ArrayRef<int> Mask, unsigned VF) {
15782 int Index = -1;
15783 return Mask.empty() ||
15784 (VF == Mask.size() &&
15787 Index == 0);
15788 }
15789
15790 public:
15791 ShuffleCostBuilder(const TargetTransformInfo &TTI,
15792 const TTI::TargetCostKind CostKind)
15793 : TTI(TTI), CostKind(CostKind) {}
15794 ~ShuffleCostBuilder() = default;
15795 InstructionCost createShuffleVector(Value *V1, Value *,
15796 ArrayRef<int> Mask) const {
15797 // Empty mask or identity mask are free.
15798 unsigned VF =
15799 cast<VectorType>(V1->getType())->getElementCount().getKnownMinValue();
15800 if (isEmptyOrIdentity(Mask, VF))
15801 return TTI::TCC_Free;
15803 cast<VectorType>(V1->getType()), CostKind, Mask);
15804 }
15805 InstructionCost createShuffleVector(Value *V1, ArrayRef<int> Mask,
15806 ArrayRef<Value *> VL) const {
15807 // Empty mask or identity mask are free.
15808 unsigned VF =
15809 cast<VectorType>(V1->getType())->getElementCount().getKnownMinValue();
15810 if (isEmptyOrIdentity(Mask, VF))
15811 return TTI::TCC_Free;
15813 cast<VectorType>(V1->getType()), CostKind, Mask,
15814 /*Index=*/0, /*SubTp=*/nullptr, VL);
15815 }
15816 InstructionCost createIdentity(Value *) const { return TTI::TCC_Free; }
15817 InstructionCost createPoison(Type *Ty, unsigned VF) const {
15818 return TTI::TCC_Free;
15819 }
15820 void resizeToMatch(Value *&, Value *&) const {}
15821 };
15822
15823 /// Smart shuffle instruction emission, walks through shuffles trees and
15824 /// tries to find the best matching vector for the actual shuffle
15825 /// instruction.
15827 createShuffle(const PointerUnion<Value *, const TreeEntry *> &P1,
15829 ArrayRef<int> Mask, ArrayRef<Value *> VL = {}) {
15830 ShuffleCostBuilder Builder(TTI, CostKind);
15831 SmallVector<int> CommonMask(Mask);
15832 Value *V1 = P1.dyn_cast<Value *>(), *V2 = P2.dyn_cast<Value *>();
15833 unsigned CommonVF = Mask.size();
15834 InstructionCost ExtraCost = 0;
15835 auto GetNodeMinBWAffectedCost = [&](const TreeEntry &E,
15836 unsigned VF) -> InstructionCost {
15837 if (E.isGather() && allConstant(E.Scalars))
15838 return TTI::TCC_Free;
15839 Type *EScalarTy = E.Scalars.front()->getType();
15840 bool IsSigned = true;
15841 if (auto It = R.MinBWs.find(&E); It != R.MinBWs.end()) {
15842 EScalarTy = IntegerType::get(EScalarTy->getContext(), It->second.first);
15843 IsSigned = It->second.second;
15844 }
15845 if (EScalarTy != ScalarTy) {
15846 unsigned CastOpcode = Instruction::Trunc;
15847 unsigned DstSz = R.DL->getTypeSizeInBits(ScalarTy);
15848 unsigned SrcSz = R.DL->getTypeSizeInBits(EScalarTy);
15849 if (DstSz > SrcSz)
15850 CastOpcode = IsSigned ? Instruction::SExt : Instruction::ZExt;
15851 return TTI.getCastInstrCost(CastOpcode, getWidenedType(ScalarTy, VF),
15852 getWidenedType(EScalarTy, VF),
15853 TTI::CastContextHint::None, CostKind);
15854 }
15855 return TTI::TCC_Free;
15856 };
15857 auto GetValueMinBWAffectedCost = [&](const Value *V) -> InstructionCost {
15858 if (isa<Constant>(V))
15859 return TTI::TCC_Free;
15860 auto *VecTy = cast<VectorType>(V->getType());
15861 Type *EScalarTy = VecTy->getElementType();
15862 if (EScalarTy != ScalarTy) {
15863 bool IsSigned = !isKnownNonNegative(V, SimplifyQuery(*R.DL));
15864 unsigned CastOpcode = Instruction::Trunc;
15865 unsigned DstSz = R.DL->getTypeSizeInBits(ScalarTy);
15866 unsigned SrcSz = R.DL->getTypeSizeInBits(EScalarTy);
15867 if (DstSz > SrcSz)
15868 CastOpcode = IsSigned ? Instruction::SExt : Instruction::ZExt;
15869 return TTI.getCastInstrCost(
15870 CastOpcode, VectorType::get(ScalarTy, VecTy->getElementCount()),
15871 VecTy, TTI::CastContextHint::None, CostKind);
15872 }
15873 return TTI::TCC_Free;
15874 };
15875 if (!V1 && !V2 && !P2.isNull()) {
15876 // Shuffle 2 entry nodes.
15877 const TreeEntry *E = cast<const TreeEntry *>(P1);
15878 unsigned VF = E->getVectorFactor();
15879 const TreeEntry *E2 = cast<const TreeEntry *>(P2);
15880 CommonVF = std::max(VF, E2->getVectorFactor());
15881 assert(all_of(Mask,
15882 [=](int Idx) {
15883 return Idx < 2 * static_cast<int>(CommonVF);
15884 }) &&
15885 "All elements in mask must be less than 2 * CommonVF.");
15886 if (E->Scalars.size() == E2->Scalars.size()) {
15887 SmallVector<int> EMask = E->getCommonMask();
15888 SmallVector<int> E2Mask = E2->getCommonMask();
15889 if (!EMask.empty() || !E2Mask.empty()) {
15890 for (int &Idx : CommonMask) {
15891 if (Idx == PoisonMaskElem)
15892 continue;
15893 if (Idx < static_cast<int>(CommonVF) && !EMask.empty())
15894 Idx = EMask[Idx];
15895 else if (Idx >= static_cast<int>(CommonVF))
15896 Idx = (E2Mask.empty() ? Idx - CommonVF : E2Mask[Idx - CommonVF]) +
15897 E->Scalars.size();
15898 }
15899 }
15900 CommonVF = E->Scalars.size();
15901 ExtraCost += GetNodeMinBWAffectedCost(*E, CommonVF) +
15902 GetNodeMinBWAffectedCost(*E2, CommonVF);
15903 } else {
15904 ExtraCost += GetNodeMinBWAffectedCost(*E, E->getVectorFactor()) +
15905 GetNodeMinBWAffectedCost(*E2, E2->getVectorFactor());
15906 }
15907 V1 = Constant::getNullValue(getWidenedType(ScalarTy, CommonVF));
15908 V2 = getAllOnesValue(*R.DL, getWidenedType(ScalarTy, CommonVF));
15909 } else if (!V1 && P2.isNull()) {
15910 // Shuffle single entry node.
15911 const TreeEntry *E = cast<const TreeEntry *>(P1);
15912 unsigned VF = E->getVectorFactor();
15913 CommonVF = VF;
15914 assert(
15915 all_of(Mask,
15916 [=](int Idx) { return Idx < static_cast<int>(CommonVF); }) &&
15917 "All elements in mask must be less than CommonVF.");
15918 if (E->Scalars.size() == Mask.size() && VF != Mask.size()) {
15919 SmallVector<int> EMask = E->getCommonMask();
15920 assert(!EMask.empty() && "Expected non-empty common mask.");
15921 for (int &Idx : CommonMask) {
15922 if (Idx != PoisonMaskElem)
15923 Idx = EMask[Idx];
15924 }
15925 CommonVF = E->Scalars.size();
15926 } else if (unsigned Factor = E->getInterleaveFactor();
15927 Factor > 0 && E->Scalars.size() != Mask.size() &&
15929 Factor)) {
15930 // Deinterleaved nodes are free.
15931 std::iota(CommonMask.begin(), CommonMask.end(), 0);
15932 }
15933 ExtraCost += GetNodeMinBWAffectedCost(*E, CommonVF);
15934 V1 = Constant::getNullValue(getWidenedType(ScalarTy, CommonVF));
15935 // Not identity/broadcast? Try to see if the original vector is better.
15936 if (!E->ReorderIndices.empty() && CommonVF == E->ReorderIndices.size() &&
15937 CommonVF == CommonMask.size() &&
15938 any_of(enumerate(CommonMask),
15939 [](const auto &&P) {
15940 return P.value() != PoisonMaskElem &&
15941 static_cast<unsigned>(P.value()) != P.index();
15942 }) &&
15943 any_of(CommonMask,
15944 [](int Idx) { return Idx != PoisonMaskElem && Idx != 0; })) {
15945 SmallVector<int> ReorderMask;
15946 inversePermutation(E->ReorderIndices, ReorderMask);
15947 addMask(CommonMask, ReorderMask);
15948 }
15949 } else if (V1 && P2.isNull()) {
15950 // Shuffle single vector.
15951 ExtraCost += GetValueMinBWAffectedCost(V1);
15952 CommonVF = getVF(V1);
15953 assert(
15954 all_of(Mask,
15955 [=](int Idx) { return Idx < static_cast<int>(CommonVF); }) &&
15956 "All elements in mask must be less than CommonVF.");
15957 } else if (V1 && !V2) {
15958 // Shuffle vector and tree node.
15959 unsigned VF = getVF(V1);
15960 const TreeEntry *E2 = cast<const TreeEntry *>(P2);
15961 CommonVF = std::max(VF, E2->getVectorFactor());
15962 assert(all_of(Mask,
15963 [=](int Idx) {
15964 return Idx < 2 * static_cast<int>(CommonVF);
15965 }) &&
15966 "All elements in mask must be less than 2 * CommonVF.");
15967 if (E2->Scalars.size() == VF && VF != CommonVF) {
15968 SmallVector<int> E2Mask = E2->getCommonMask();
15969 assert(!E2Mask.empty() && "Expected non-empty common mask.");
15970 for (int &Idx : CommonMask) {
15971 if (Idx == PoisonMaskElem)
15972 continue;
15973 if (Idx >= static_cast<int>(CommonVF))
15974 Idx = E2Mask[Idx - CommonVF] + VF;
15975 }
15976 CommonVF = VF;
15977 }
15978 ExtraCost += GetValueMinBWAffectedCost(V1);
15979 V1 = Constant::getNullValue(getWidenedType(ScalarTy, CommonVF));
15980 ExtraCost += GetNodeMinBWAffectedCost(
15981 *E2, std::min(CommonVF, E2->getVectorFactor()));
15982 V2 = getAllOnesValue(*R.DL, getWidenedType(ScalarTy, CommonVF));
15983 } else if (!V1 && V2) {
15984 // Shuffle vector and tree node.
15985 unsigned VF = getVF(V2);
15986 const TreeEntry *E1 = cast<const TreeEntry *>(P1);
15987 CommonVF = std::max(VF, E1->getVectorFactor());
15988 assert(all_of(Mask,
15989 [=](int Idx) {
15990 return Idx < 2 * static_cast<int>(CommonVF);
15991 }) &&
15992 "All elements in mask must be less than 2 * CommonVF.");
15993 if (E1->Scalars.size() == VF && VF != CommonVF) {
15994 SmallVector<int> E1Mask = E1->getCommonMask();
15995 assert(!E1Mask.empty() && "Expected non-empty common mask.");
15996 for (int &Idx : CommonMask) {
15997 if (Idx == PoisonMaskElem)
15998 continue;
15999 if (Idx >= static_cast<int>(CommonVF))
16000 Idx = E1Mask[Idx - CommonVF] + VF;
16001 else
16002 Idx = E1Mask[Idx];
16003 }
16004 CommonVF = VF;
16005 }
16006 ExtraCost += GetNodeMinBWAffectedCost(
16007 *E1, std::min(CommonVF, E1->getVectorFactor()));
16008 V1 = Constant::getNullValue(getWidenedType(ScalarTy, CommonVF));
16009 ExtraCost += GetValueMinBWAffectedCost(V2);
16010 V2 = getAllOnesValue(*R.DL, getWidenedType(ScalarTy, CommonVF));
16011 } else {
16012 assert(V1 && V2 && "Expected both vectors.");
16013 unsigned VF = getVF(V1);
16014 CommonVF = std::max(VF, getVF(V2));
16015 assert(all_of(Mask,
16016 [=](int Idx) {
16017 return Idx < 2 * static_cast<int>(CommonVF);
16018 }) &&
16019 "All elements in mask must be less than 2 * CommonVF.");
16020 ExtraCost +=
16021 GetValueMinBWAffectedCost(V1) + GetValueMinBWAffectedCost(V2);
16022 if (V1->getType() != V2->getType()) {
16023 V1 = Constant::getNullValue(getWidenedType(ScalarTy, CommonVF));
16024 V2 = getAllOnesValue(*R.DL, getWidenedType(ScalarTy, CommonVF));
16025 } else {
16026 if (cast<VectorType>(V1->getType())->getElementType() != ScalarTy)
16027 V1 = Constant::getNullValue(getWidenedType(ScalarTy, CommonVF));
16028 if (cast<VectorType>(V2->getType())->getElementType() != ScalarTy)
16029 V2 = getAllOnesValue(*R.DL, getWidenedType(ScalarTy, CommonVF));
16030 }
16031 }
16032 InVectors.front() =
16033 Constant::getNullValue(getWidenedType(ScalarTy, CommonMask.size()));
16034 if (InVectors.size() == 2)
16035 InVectors.pop_back();
16036 return ExtraCost + BaseShuffleAnalysis::createShuffle<InstructionCost>(
16037 V1, V2, CommonMask, Builder, ScalarTy, VL);
16038 }
16039
16040public:
16042 ArrayRef<Value *> VectorizedVals, BoUpSLP &R,
16043 SmallPtrSetImpl<Value *> &CheckedExtracts)
16044 : BaseShuffleAnalysis(ScalarTy), TTI(TTI),
16045 VectorizedVals(VectorizedVals.begin(), VectorizedVals.end()), R(R),
16046 CheckedExtracts(CheckedExtracts), CostKind(R.getCostKind()) {}
16047 Value *adjustExtracts(const TreeEntry *E, MutableArrayRef<int> Mask,
16048 ArrayRef<std::optional<TTI::ShuffleKind>> ShuffleKinds,
16049 unsigned NumParts, bool &UseVecBaseAsInput) {
16050 UseVecBaseAsInput = false;
16051 if (Mask.empty())
16052 return nullptr;
16053 Value *VecBase = nullptr;
16054 SmallVector<Value *> VL(E->Scalars.begin(), E->Scalars.end());
16055 if (!E->ReorderIndices.empty()) {
16056 SmallVector<int> ReorderMask(E->ReorderIndices.begin(),
16057 E->ReorderIndices.end());
16058 reorderScalars(VL, ReorderMask);
16059 }
16060 // Check if it can be considered reused if same extractelements were
16061 // vectorized already.
16062 bool PrevNodeFound = any_of(
16063 ArrayRef(R.VectorizableTree).take_front(E->Idx),
16064 [&](const std::unique_ptr<TreeEntry> &TE) {
16065 return ((TE->hasState() && !TE->isAltShuffle() &&
16066 TE->getOpcode() == Instruction::ExtractElement) ||
16067 TE->isGather()) &&
16068 all_of(enumerate(TE->Scalars), [&](auto &&Data) {
16069 return VL.size() > Data.index() &&
16070 (Mask[Data.index()] == PoisonMaskElem ||
16071 isa<UndefValue>(VL[Data.index()]) ||
16072 Data.value() == VL[Data.index()]);
16073 });
16074 });
16075 SmallPtrSet<Value *, 4> UniqueBases;
16076 unsigned SliceSize = getPartNumElems(VL.size(), NumParts);
16077 SmallDenseMap<Value *, APInt, 4> VectorOpsToExtracts;
16078 for (unsigned Part : seq<unsigned>(NumParts)) {
16079 unsigned Limit = getNumElems(VL.size(), SliceSize, Part);
16080 ArrayRef<int> SubMask = Mask.slice(Part * SliceSize, Limit);
16081 for (auto [I, V] :
16082 enumerate(ArrayRef(VL).slice(Part * SliceSize, Limit))) {
16083 // Ignore non-extractelement scalars.
16084 if (isa<UndefValue>(V) ||
16085 (!SubMask.empty() && SubMask[I] == PoisonMaskElem))
16086 continue;
16087 // If all users of instruction are going to be vectorized and this
16088 // instruction itself is not going to be vectorized, consider this
16089 // instruction as dead and remove its cost from the final cost of the
16090 // vectorized tree.
16091 // Also, avoid adjusting the cost for extractelements with multiple uses
16092 // in different graph entries.
16093 auto *EE = cast<ExtractElementInst>(V);
16094 VecBase = EE->getVectorOperand();
16095 UniqueBases.insert(VecBase);
16096 ArrayRef<TreeEntry *> VEs = R.getTreeEntries(V);
16097 if (!CheckedExtracts.insert(V).second ||
16098 !R.areAllUsersVectorized(cast<Instruction>(V), &VectorizedVals) ||
16099 any_of(VEs,
16100 [&](const TreeEntry *TE) {
16101 return R.DeletedNodes.contains(TE) ||
16102 R.TransformedToGatherNodes.contains(TE);
16103 }) ||
16104 (E->UserTreeIndex && E->UserTreeIndex.EdgeIdx == UINT_MAX &&
16105 !R.isVectorized(EE) &&
16106 count_if(E->Scalars, [&](Value *V) { return V == EE; }) !=
16107 count_if(E->UserTreeIndex.UserTE->Scalars,
16108 [&](Value *V) { return V == EE; })) ||
16109 any_of(EE->users(),
16110 [&](User *U) {
16111 return isa<GetElementPtrInst>(U) &&
16112 !R.areAllUsersVectorized(cast<Instruction>(U),
16113 &VectorizedVals);
16114 }) ||
16115 (!VEs.empty() && !is_contained(VEs, E)))
16116 continue;
16117 std::optional<unsigned> EEIdx = getExtractIndex(EE);
16118 if (!EEIdx)
16119 continue;
16120 unsigned Idx = *EEIdx;
16121 // Take credit for instruction that will become dead.
16122 if (EE->hasOneUse() || !PrevNodeFound) {
16123 Instruction *Ext = EE->user_back();
16124 if (isa<SExtInst, ZExtInst>(Ext) &&
16126 // Use getExtractWithExtendCost() to calculate the cost of
16127 // extractelement/ext pair.
16128 Cost -= TTI.getExtractWithExtendCost(
16129 Ext->getOpcode(), Ext->getType(), EE->getVectorOperandType(),
16130 Idx, CostKind);
16131 // Add back the cost of s|zext which is subtracted separately.
16132 Cost += TTI.getCastInstrCost(
16133 Ext->getOpcode(), Ext->getType(), EE->getType(),
16135 continue;
16136 }
16137 }
16138 APInt &DemandedElts =
16139 VectorOpsToExtracts
16140 .try_emplace(VecBase,
16141 APInt::getZero(getNumElements(VecBase->getType())))
16142 .first->getSecond();
16143 DemandedElts.setBit(Idx);
16144 }
16145 }
16146 for (const auto &[Vec, DemandedElts] : VectorOpsToExtracts)
16148 DemandedElts, /*Insert=*/false,
16149 /*Extract=*/true, CostKind);
16150 // Check that gather of extractelements can be represented as just a
16151 // shuffle of a single/two vectors the scalars are extracted from.
16152 // Found the bunch of extractelement instructions that must be gathered
16153 // into a vector and can be represented as a permutation elements in a
16154 // single input vector or of 2 input vectors.
16155 // Done for reused if same extractelements were vectorized already.
16156 if (!PrevNodeFound)
16157 Cost += computeExtractCost(VL, Mask, ShuffleKinds, NumParts);
16158 InVectors.assign(1, E);
16159 CommonMask.assign(Mask.begin(), Mask.end());
16160 transformMaskAfterShuffle(CommonMask, CommonMask);
16161 SameNodesEstimated = false;
16162 if (NumParts != 1 && UniqueBases.size() != 1) {
16163 UseVecBaseAsInput = true;
16164 VecBase =
16165 Constant::getNullValue(getWidenedType(ScalarTy, CommonMask.size()));
16166 }
16167 return VecBase;
16168 }
16169 /// Checks if the specified entry \p E needs to be delayed because of its
16170 /// dependency nodes.
16171 std::optional<InstructionCost>
16172 needToDelay(const TreeEntry *,
16174 // No need to delay the cost estimation during analysis.
16175 return std::nullopt;
16176 }
16177 /// Reset the builder to handle perfect diamond match.
16179 IsFinalized = false;
16180 CommonMask.clear();
16181 InVectors.clear();
16182 Cost = 0;
16183 VectorizedVals.clear();
16184 SameNodesEstimated = true;
16185 }
16186 void add(const TreeEntry &E1, const TreeEntry &E2, ArrayRef<int> Mask) {
16187 BVValues.reset();
16188 if (&E1 == &E2) {
16189 assert(all_of(Mask,
16190 [&](int Idx) {
16191 return Idx < static_cast<int>(E1.getVectorFactor());
16192 }) &&
16193 "Expected single vector shuffle mask.");
16194 add(E1, Mask);
16195 return;
16196 }
16197 if (InVectors.empty()) {
16198 CommonMask.assign(Mask.begin(), Mask.end());
16199 InVectors.assign({&E1, &E2});
16200 return;
16201 }
16202 assert(!CommonMask.empty() && "Expected non-empty common mask.");
16203 auto *MaskVecTy = getWidenedType(ScalarTy, Mask.size());
16204 unsigned NumParts =
16205 ::getNumberOfParts(TTI, MaskVecTy, ScalarTy, Mask.size());
16206 unsigned SliceSize = getPartNumElems(Mask.size(), NumParts);
16207 const auto *It = find_if(Mask, not_equal_to(PoisonMaskElem));
16208 unsigned Part = std::distance(Mask.begin(), It) / SliceSize;
16209 estimateNodesPermuteCost(E1, &E2, Mask, Part, SliceSize);
16210 }
16211 void add(const TreeEntry &E1, ArrayRef<int> Mask) {
16212 BVValues.reset();
16213 if (InVectors.empty()) {
16214 CommonMask.assign(Mask.begin(), Mask.end());
16215 InVectors.assign(1, &E1);
16216 return;
16217 }
16218 assert(!CommonMask.empty() && "Expected non-empty common mask.");
16219 auto *MaskVecTy = getWidenedType(ScalarTy, Mask.size());
16220 unsigned NumParts =
16221 ::getNumberOfParts(TTI, MaskVecTy, ScalarTy, Mask.size());
16222 unsigned SliceSize = getPartNumElems(Mask.size(), NumParts);
16223 const auto *It = find_if(Mask, not_equal_to(PoisonMaskElem));
16224 unsigned Part = std::distance(Mask.begin(), It) / SliceSize;
16225 estimateNodesPermuteCost(E1, nullptr, Mask, Part, SliceSize);
16226 if (!SameNodesEstimated && InVectors.size() == 1)
16227 InVectors.emplace_back(&E1);
16228 }
16229 /// Adds 2 input vectors and the mask for their shuffling.
16230 void add(Value *V1, Value *V2, ArrayRef<int> Mask) {
16231 // May come only for shuffling of 2 vectors with extractelements, already
16232 // handled in adjustExtracts.
16233 assert(InVectors.size() == 1 &&
16234 all_of(enumerate(CommonMask),
16235 [&](auto P) {
16236 if (P.value() == PoisonMaskElem)
16237 return Mask[P.index()] == PoisonMaskElem;
16238 auto *EI = cast<ExtractElementInst>(
16239 cast<const TreeEntry *>(InVectors.front())
16240 ->getOrdered(P.index()));
16241 return EI->getVectorOperand() == V1 ||
16242 EI->getVectorOperand() == V2;
16243 }) &&
16244 "Expected extractelement vectors.");
16245 }
16246 /// Adds another one input vector and the mask for the shuffling.
16247 void add(Value *V1, ArrayRef<int> Mask, bool ForExtracts = false) {
16248 if (BVValues && !isa<Constant>(V1))
16249 BVValues.reset();
16250 if (InVectors.empty()) {
16251 assert(CommonMask.empty() && !ForExtracts &&
16252 "Expected empty input mask/vectors.");
16253 CommonMask.assign(Mask.begin(), Mask.end());
16254 InVectors.assign(1, V1);
16255 return;
16256 }
16257 if (ForExtracts) {
16258 // No need to add vectors here, already handled them in adjustExtracts.
16259 assert(InVectors.size() == 1 && isa<const TreeEntry *>(InVectors[0]) &&
16260 !CommonMask.empty() &&
16261 all_of(enumerate(CommonMask),
16262 [&](auto P) {
16263 Value *Scalar = cast<const TreeEntry *>(InVectors[0])
16264 ->getOrdered(P.index());
16265 if (P.value() == PoisonMaskElem)
16266 return P.value() == Mask[P.index()] ||
16267 isa<UndefValue>(Scalar);
16268 if (isa<Constant>(V1))
16269 return true;
16270 auto *EI = cast<ExtractElementInst>(Scalar);
16271 return EI->getVectorOperand() == V1;
16272 }) &&
16273 "Expected only tree entry for extractelement vectors.");
16274 return;
16275 }
16276 assert(!InVectors.empty() && !CommonMask.empty() &&
16277 "Expected only tree entries from extracts/reused buildvectors.");
16278 unsigned VF = getVF(V1);
16279 if (InVectors.size() == 2) {
16280 Cost += createShuffle(InVectors.front(), InVectors.back(), CommonMask);
16281 transformMaskAfterShuffle(CommonMask, CommonMask);
16282 VF = std::max<unsigned>(VF, CommonMask.size());
16283 } else if (const auto *InTE =
16284 InVectors.front().dyn_cast<const TreeEntry *>()) {
16285 VF = std::max(VF, InTE->getVectorFactor());
16286 } else {
16287 VF = std::max(
16288 VF, cast<FixedVectorType>(cast<Value *>(InVectors.front())->getType())
16289 ->getNumElements());
16290 }
16291 InVectors.push_back(V1);
16292 for (unsigned Idx = 0, Sz = CommonMask.size(); Idx < Sz; ++Idx)
16293 if (Mask[Idx] != PoisonMaskElem && CommonMask[Idx] == PoisonMaskElem)
16294 CommonMask[Idx] = Mask[Idx] + VF;
16295 }
16296 Value *gather(ArrayRef<Value *> VL, unsigned MaskVF = 0,
16297 Value *Root = nullptr) {
16298 Cost += getBuildVectorCost(VL, Root);
16299 if (BVValues) {
16300 if (BVValues->empty() && InVectors.empty())
16301 BVValues->assign(VL.begin(), VL.end());
16302 else
16303 BVValues.reset();
16304 }
16305 if (!Root) {
16306 // FIXME: Need to find a way to avoid use of getNullValue here.
16308 unsigned VF = VL.size();
16309 if (MaskVF != 0)
16310 VF = std::min(VF, MaskVF);
16311 Type *VLScalarTy = VL.front()->getType();
16312 for (Value *V : VL.take_front(VF)) {
16313 Type *ScalarTy = VLScalarTy->getScalarType();
16314 if (isa<PoisonValue>(V)) {
16315 Vals.push_back(PoisonValue::get(ScalarTy));
16316 continue;
16317 }
16318 if (isa<UndefValue>(V)) {
16319 Vals.push_back(UndefValue::get(ScalarTy));
16320 continue;
16321 }
16322 Vals.push_back(Constant::getNullValue(ScalarTy));
16323 }
16324 if (auto *VecTy = dyn_cast<FixedVectorType>(VLScalarTy)) {
16325 assert(SLPReVec && "FixedVectorType is not expected.");
16326 // When REVEC is enabled, we need to expand vector types into scalar
16327 // types.
16328 Vals = replicateMask(Vals, VecTy->getNumElements());
16329 }
16330 return ConstantVector::get(Vals);
16331 }
16334 cast<FixedVectorType>(Root->getType())->getNumElements()),
16335 getAllOnesValue(*R.DL, ScalarTy->getScalarType()));
16336 }
16338 /// Finalize emission of the shuffles.
16340 ArrayRef<int> ExtMask,
16341 ArrayRef<std::pair<const TreeEntry *, unsigned>> SubVectors,
16342 ArrayRef<int> SubVectorsMask, unsigned VF = 0,
16345 Action = {}) {
16346 IsFinalized = true;
16347 if (Action) {
16348 const PointerUnion<Value *, const TreeEntry *> &Vec = InVectors.front();
16349 if (InVectors.size() == 2)
16350 Cost += createShuffle(Vec, InVectors.back(), CommonMask);
16351 else
16352 Cost += createShuffle(Vec, nullptr, CommonMask);
16353 transformMaskAfterShuffle(CommonMask, CommonMask);
16354 assert(VF > 0 &&
16355 "Expected vector length for the final value before action.");
16356 Value *V = cast<Value *>(Vec);
16357 Action(V, CommonMask, [this](Value *V1, Value *V2, ArrayRef<int> Mask) {
16358 Cost += createShuffle(V1, V2, Mask);
16359 return V1;
16360 });
16361 InVectors.front() = V;
16362 }
16363 if (!SubVectors.empty()) {
16364 const PointerUnion<Value *, const TreeEntry *> &Vec = InVectors.front();
16365 if (InVectors.size() == 2)
16366 Cost += createShuffle(Vec, InVectors.back(), CommonMask);
16367 else
16368 Cost += createShuffle(Vec, nullptr, CommonMask);
16369 transformMaskAfterShuffle(CommonMask, CommonMask);
16370 // Add subvectors permutation cost.
16371 if (!SubVectorsMask.empty()) {
16372 assert(SubVectorsMask.size() <= CommonMask.size() &&
16373 "Expected same size of masks for subvectors and common mask.");
16374 SmallVector<int> SVMask(CommonMask.size(), PoisonMaskElem);
16375 copy(SubVectorsMask, SVMask.begin());
16376 for (auto [I1, I2] : zip(SVMask, CommonMask)) {
16377 if (I2 != PoisonMaskElem) {
16378 assert(I1 == PoisonMaskElem && "Expected unused subvectors mask");
16379 I1 = I2 + CommonMask.size();
16380 }
16381 }
16384 cast<VectorType>(getWidenedType(ScalarTy, CommonMask.size())),
16385 CostKind, SVMask);
16386 }
16387 for (auto [E, Idx] : SubVectors) {
16388 Type *EScalarTy = E->Scalars.front()->getType();
16389 bool IsSigned = true;
16390 if (auto It = R.MinBWs.find(E); It != R.MinBWs.end()) {
16391 EScalarTy =
16392 IntegerType::get(EScalarTy->getContext(), It->second.first);
16393 IsSigned = It->second.second;
16394 }
16395 if (ScalarTy != EScalarTy) {
16396 unsigned CastOpcode = Instruction::Trunc;
16397 unsigned DstSz = R.DL->getTypeSizeInBits(ScalarTy);
16398 unsigned SrcSz = R.DL->getTypeSizeInBits(EScalarTy);
16399 if (DstSz > SrcSz)
16400 CastOpcode = IsSigned ? Instruction::SExt : Instruction::ZExt;
16401 Cost += TTI.getCastInstrCost(
16402 CastOpcode, getWidenedType(ScalarTy, E->getVectorFactor()),
16403 getWidenedType(EScalarTy, E->getVectorFactor()),
16405 }
16408 cast<VectorType>(getWidenedType(ScalarTy, CommonMask.size())),
16409 CostKind, {}, Idx,
16410 cast<VectorType>(getWidenedType(ScalarTy, E->getVectorFactor())));
16411 if (!CommonMask.empty()) {
16412 std::iota(std::next(CommonMask.begin(), Idx),
16413 std::next(CommonMask.begin(), Idx + E->getVectorFactor()),
16414 Idx);
16415 }
16416 }
16417 }
16418
16419 if (!ExtMask.empty()) {
16420 if (CommonMask.empty()) {
16421 CommonMask.assign(ExtMask.begin(), ExtMask.end());
16422 } else {
16423 SmallVector<int> NewMask(ExtMask.size(), PoisonMaskElem);
16424 for (int I = 0, Sz = ExtMask.size(); I < Sz; ++I) {
16425 if (ExtMask[I] == PoisonMaskElem)
16426 continue;
16427 NewMask[I] = CommonMask[ExtMask[I]];
16428 }
16429 CommonMask.swap(NewMask);
16430 }
16431 }
16432 if (CommonMask.empty()) {
16433 assert(InVectors.size() == 1 && "Expected only one vector with no mask");
16434 return Cost;
16435 }
16437 if (BVValues)
16438 VL = *BVValues;
16439 return Cost +
16440 createShuffle(InVectors.front(),
16441 InVectors.size() == 2 ? InVectors.back() : nullptr,
16442 CommonMask, VL);
16443 }
16444
16446 assert((IsFinalized || CommonMask.empty()) &&
16447 "Shuffle construction must be finalized.");
16448 }
16449};
16450
16451const BoUpSLP::TreeEntry *BoUpSLP::getOperandEntry(const TreeEntry *E,
16452 unsigned Idx) const {
16453 TreeEntry *Op = OperandsToTreeEntry.at({E, Idx});
16454 assert(Op->isSame(E->getOperand(Idx)) && "Operands mismatch!");
16455 return Op;
16456}
16457
16458TTI::CastContextHint BoUpSLP::getCastContextHint(const TreeEntry &TE) const {
16459 if (TE.State == TreeEntry::ScatterVectorize ||
16460 TE.State == TreeEntry::StridedVectorize)
16462 if (TE.State == TreeEntry::CompressVectorize ||
16463 TE.State == TreeEntry::BlendedLoadVectorize)
16465 if (TE.State == TreeEntry::Vectorize && TE.getOpcode() == Instruction::Load &&
16466 !TE.isAltShuffle()) {
16467 if (TE.ReorderIndices.empty())
16469 SmallVector<int> Mask;
16470 inversePermutation(TE.ReorderIndices, Mask);
16471 if (ShuffleVectorInst::isReverseMask(Mask, Mask.size()))
16473 }
16475}
16476
16477/// Get the assumed loop trip count for the loop \p L.
16478static unsigned getLoopTripCount(const Loop *L, ScalarEvolution &SE) {
16479 if (LoopAwareTripCount == 0)
16480 return 1;
16481 unsigned Scale = SE.getSmallConstantTripCount(L);
16482 if (Scale == 0)
16483 Scale = getLoopEstimatedTripCount(const_cast<Loop *>(L)).value_or(0);
16484 if (Scale != 0) {
16485 // Multiple exiting blocks - choose the minimum between trip count (scale)
16486 // and LoopAwareTripCount, since the multiple exit loops can be terminated
16487 // early.
16488 if (!L->getExitingBlock())
16489 return std::min<unsigned>(LoopAwareTripCount, Scale);
16490 return Scale;
16491 }
16492 return LoopAwareTripCount;
16493}
16494
16495uint64_t BoUpSLP::getScaleToLoopIterations(const TreeEntry &TE, Value *Scalar,
16496 Instruction *U) {
16497 BasicBlock *Parent = nullptr;
16498 if (U) {
16499 // The extractelement for a PHI-node user is created in the incoming
16500 // block that feeds the matching operand, not in the PHI block itself
16501 // When the PHI is inside a loop that incoming block can belong to a deeper
16502 // loop than the PHI block. Scaling by the PHI block would use
16503 // the outer trip count instead of inner*outer, and because
16504 // ExtractCostCalculated deduplicates by scalar (only the first external
16505 // user fixes the scale) it would also make the cost depend on external-user
16506 // ordering. A PHI outside all loops is a plain loop-exit phi: its live-out
16507 // lanes are normally rebuilt as a vector LCSSA phi in the exit block, which
16508 // hoists the extract out of the loop, so scale = 1 (via U->getParent()
16509 // below) is kept and the adjustment is restricted to in-loop PHIs.
16510 if (auto *PHI = dyn_cast<PHINode>(U); PHI && Scalar) {
16511 if (LI->getLoopFor(PHI->getParent())) {
16512 // Use the deepest incoming block among all slots where Scalar
16513 // appears, to be conservative when the same value appears in
16514 // multiple predecessors.
16515 for (unsigned I : seq<unsigned>(PHI->getNumIncomingValues())) {
16516 if (PHI->getIncomingValue(I) != Scalar)
16517 continue;
16518 BasicBlock *InBB = PHI->getIncomingBlock(I);
16519 if (!Parent || LI->getLoopDepth(InBB) > LI->getLoopDepth(Parent))
16520 Parent = InBB;
16521 }
16522 }
16523 }
16524 if (!Parent)
16525 Parent = U->getParent();
16526 } else if (TE.isGather() || TE.State == TreeEntry::SplitVectorize) {
16527 EdgeInfo EI = TE.UserTreeIndex;
16528 while (EI.UserTE) {
16529 if (EI.UserTE->isGather() ||
16530 EI.UserTE->State == TreeEntry::SplitVectorize) {
16531 EI = EI.UserTE->UserTreeIndex;
16532 continue;
16533 }
16534 if (EI.UserTE->State == TreeEntry::Vectorize &&
16535 EI.UserTE->getOpcode() == Instruction::PHI) {
16536 auto *PH = cast<PHINode>(EI.UserTE->getMainOp());
16537 Parent = PH->getIncomingBlock(EI.EdgeIdx);
16538 } else {
16539 Parent = EI.UserTE->getMainOp()->getParent();
16540 }
16541 break;
16542 }
16543 if (!Parent)
16544 return 1;
16545 } else {
16546 Parent = TE.getMainOp()->getParent();
16547 }
16548 const Loop *L = LI->getLoopFor(Parent);
16549 if (!L)
16550 return 1;
16551 // The entry's cost is paid once per execution of the innermost loop in
16552 // which some of its operands are variant. Operands that are invariant in
16553 // all enclosing loops are executed once (LICM will hoist them out).
16554 return getLoopNestScale(findInnermostNonInvariantLoop(
16555 L, Scalar ? ArrayRef(Scalar) : ArrayRef(TE.Scalars)));
16556}
16557
16558uint64_t BoUpSLP::getLoopNestScale(const Loop *L) {
16559 if (!L || LoopAwareTripCount == 0)
16560 return 1;
16561 if (auto It = LoopNestScaleCache.find(L); It != LoopNestScaleCache.end())
16562 return It->second;
16563 // Collect loops from L outward up to (but not including) the first cached
16564 // ancestor or the function top, then walk back inward multiplying trip
16565 // counts. Use uint64_t to avoid silent overflow on deep/large nests.
16566 SmallVector<const Loop *> Chain;
16567 for (const Loop *Cur = L; Cur; Cur = Cur->getParentLoop()) {
16568 if (LoopNestScaleCache.contains(Cur))
16569 break;
16570 Chain.push_back(Cur);
16571 }
16572 assert(!Chain.empty() && "Early-return above should have handled cache hit.");
16573 uint64_t Scale = 1;
16574 if (const Loop *Parent = Chain.back()->getParentLoop())
16575 Scale = LoopNestScaleCache.lookup(Parent);
16576 // Walk from the outermost uncached loop inward, accumulating trip counts.
16577 // Use SaturatingMultiply to clamp at uint64_t max on deep/large nests
16578 // rather than wrapping around.
16579 for (const Loop *Cur : reverse(Chain)) {
16580 uint64_t TC = std::max<uint64_t>(1, getLoopTripCount(Cur, *SE));
16581 Scale = SaturatingMultiply(Scale, TC);
16582 LoopNestScaleCache.try_emplace(Cur, std::max<uint64_t>(1, Scale));
16583 }
16584 return std::max<uint64_t>(1, Scale);
16585}
16586
16587uint64_t BoUpSLP::getGatherNodeEffectiveScale(const TreeEntry &TE,
16588 Instruction *U) {
16589 // Only meaningful for gather/buildvector-like entries; the per-lane
16590 // insertelements that make up such an entry are LICM-hoistable by
16591 // optimizeGatherSequence() when their operand is loop-invariant.
16592 assert((TE.isGather() || TE.State == TreeEntry::SplitVectorize) &&
16593 "Expected gather/split tree entry.");
16594
16595 uint64_t BaseScale = getScaleToLoopIterations(TE, nullptr, U);
16596 if (!PerLaneGatherScale || LoopAwareTripCount == 0 || BaseScale <= 1)
16597 return BaseScale;
16598
16599 // Average the per-lane execution scales: for each lane, reuse the same
16600 // scale helper the rest of the cost model uses, but ask it about that
16601 // one lane's value. Lanes that are loop-invariant in the current nest
16602 // collapse to their outer-loop scale (or 1 for fully invariant/constant
16603 // lanes), which matches the LICM hoisting performed by
16604 // optimizeGatherSequence(). Cap per-lane contributions by BaseScale so a
16605 // refinement can never raise the cost above the whole-entry scale.
16606 // Each lane contributes at most BaseScale, so Sum is bounded above by
16607 // N * BaseScale. If BaseScale is near uint64_t max (saturated by
16608 // getLoopNestScale on a deep nest) Sum can still overflow uint64_t,
16609 // which would silently wrap and produce a wrong average. Use
16610 // SaturatingAdd and bail out to BaseScale on overflow: the true average
16611 // is bounded above by BaseScale anyway, so this preserves the
16612 // refinement's invariant that it can never raise cost.
16613 uint64_t Sum = 0;
16614 unsigned N = 0;
16615 bool Overflow = false;
16616 for (Value *V : TE.Scalars) {
16617 if (isConstant(V))
16618 continue;
16619 ++N;
16620 uint64_t LaneScale =
16621 std::min(getScaleToLoopIterations(TE, V, U), BaseScale);
16622 Sum = SaturatingAdd(Sum, LaneScale, &Overflow);
16623 if (Overflow)
16624 return BaseScale;
16625 }
16626 if (N == 0)
16627 return BaseScale;
16628 // Ceil-divide so we never round the effective scale down below 1.
16629 uint64_t Numerator = SaturatingAdd(Sum, uint64_t(N - 1), &Overflow);
16630 if (Overflow)
16631 return BaseScale;
16632 uint64_t Avg = Numerator / N;
16633 return std::clamp<uint64_t>(Avg, 1, BaseScale);
16634}
16635
16636uint64_t BoUpSLP::getEntryEffectiveScale(const TreeEntry &TE, Instruction *U) {
16637 if (TE.isGather() || TE.State == TreeEntry::SplitVectorize)
16638 return getGatherNodeEffectiveScale(TE, U);
16639 return getScaleToLoopIterations(TE);
16640}
16641
16643BoUpSLP::getVectorSpillReloadCost(const TreeEntry *E, Type *ScalarTy,
16644 Type *VecTy, Type *FinalVecTy,
16645 const TTI::TargetCostKind CostKind) const {
16646 InstructionCost SpillsReloads = 0;
16647
16648 // Estimate vector register pressure per target register class: operand
16649 // vectors plus the result. The same vector operand is counted once via
16650 // CountedOpEntries deduplication. PHIs take the max operand pressure across
16651 // incoming slots (only one predecessor is live at a time) plus the result.
16652 // All-constant operand bundles are skipped.
16653 if (!E->hasState() || E->getOpcode() == Instruction::Store ||
16654 E->getOpcode() == Instruction::ExtractElement ||
16655 E->getOpcode() == Instruction::ExtractValue ||
16656 E->getOpcode() == Instruction::Freeze ||
16657 (E->getOpcode() == Instruction::Load &&
16658 E->State != TreeEntry::ScatterVectorize))
16659 return SpillsReloads;
16660
16661 const bool IsPHI =
16662 E->State == TreeEntry::Vectorize && E->getOpcode() == Instruction::PHI;
16663 SmallPtrSet<const TreeEntry *, 8> CountedOpEntries;
16664 SmallDenseMap<unsigned, unsigned> PressureByClass;
16665 auto AddPartsToClass = [&](unsigned RegClass, unsigned Parts) {
16666 assert(Parts != 0 && "Expected non-zero number of parts (registers).");
16667 PressureByClass[RegClass] += Parts;
16668 };
16669
16670 auto GetEntryVecTy = [&](const TreeEntry *TE) -> std::pair<Type *, Type *> {
16671 Type *ScalarTy = getValueType(TE->Scalars.front(), SLPReVec);
16672 auto BWIt = MinBWs.find(TE);
16673 if (BWIt != MinBWs.end()) {
16674 auto *VTy = dyn_cast<FixedVectorType>(ScalarTy);
16675 ScalarTy = IntegerType::get(F->getContext(), BWIt->second.first);
16676 if (VTy)
16677 ScalarTy = getWidenedType(ScalarTy, VTy->getNumElements());
16678 }
16679 return std::make_pair(ScalarTy,
16680 getWidenedType(ScalarTy, TE->getVectorFactor()));
16681 };
16682
16683 if (E->State == TreeEntry::SplitVectorize) {
16684 for (const auto &[Idx, _] : E->CombinedEntriesWithIndices) {
16685 const TreeEntry *OpTE = VectorizableTree[Idx].get();
16686
16687 if (!CountedOpEntries.insert(OpTE).second)
16688 continue;
16689 auto [ScalarTy, OpVecTy] = GetEntryVecTy(OpTE);
16690 const unsigned Parts = getNumberOfParts(OpVecTy, ScalarTy);
16691 if (Parts == 0)
16692 continue;
16693 const unsigned RC =
16694 TTI->getRegisterClassForType(/*Vector=*/true, OpVecTy);
16695 AddPartsToClass(RC, Parts);
16696 }
16697 } else if (IsPHI) {
16698 // Only one predecessor is live at a time - take the max operand pressure
16699 // across incoming slots.
16700 SmallDenseMap<unsigned, unsigned> MaxOpPressureByClass;
16701 for (unsigned Idx : seq<unsigned>(E->getNumOperands())) {
16702 const TreeEntry *OpTE = getOperandEntry(E, Idx);
16703 auto [ScalarTy, OpVecTy] = GetEntryVecTy(OpTE);
16704 const unsigned Parts = getNumberOfParts(OpVecTy, ScalarTy);
16705 if (Parts == 0)
16706 continue;
16707 const unsigned RC =
16708 TTI->getRegisterClassForType(/*Vector=*/true, OpVecTy);
16709 MaxOpPressureByClass[RC] = std::max(MaxOpPressureByClass[RC], Parts);
16710 }
16711 for (auto [RC, Parts] : MaxOpPressureByClass)
16712 AddPartsToClass(RC, Parts);
16713 } else {
16714 for (unsigned Idx : seq<unsigned>(E->getNumOperands())) {
16715 // InsertElement operand 0 is the vector being inserted into, which is
16716 // built incrementally and does not occupy an extra register.
16717 if ((E->getOpcode() == Instruction::InsertElement ||
16718 E->getOpcode() == Instruction::InsertValue) &&
16719 Idx == 0)
16720 continue;
16721 ArrayRef<Value *> Ops = E->getOperand(Idx);
16722 if (Ops.empty() || allConstant(Ops) || isSplat(Ops))
16723 continue;
16724 Value *Op = Ops.front();
16725 if (!Op)
16726 continue;
16727 const TreeEntry *OpTE = getOperandEntry(E, Idx);
16728
16729 if (!CountedOpEntries.insert(OpTE).second)
16730 continue;
16731 auto *OpVecTy = getWidenedType(Op->getType(), Ops.size());
16732 const unsigned Parts = getNumberOfParts(OpVecTy, Op->getType());
16733 if (Parts == 0)
16734 continue;
16735 const unsigned RC =
16736 TTI->getRegisterClassForType(/*Vector=*/true, OpVecTy);
16737 AddPartsToClass(RC, Parts);
16738 }
16739 }
16740
16741 if (E->getOpcode() != Instruction::Load) {
16742 const unsigned ResParts = getNumberOfParts(VecTy, ScalarTy);
16743 if (ResParts != 0) {
16744 const unsigned RC = TTI->getRegisterClassForType(/*Vector=*/true, VecTy);
16745 AddPartsToClass(RC, ResParts);
16746 }
16747 if (VecTy != FinalVecTy) {
16748 const unsigned FinalResParts = getNumberOfParts(FinalVecTy, ScalarTy);
16749 if (FinalResParts != 0) {
16750 const unsigned RC =
16751 TTI->getRegisterClassForType(/*Vector=*/true, FinalVecTy);
16752 AddPartsToClass(RC, FinalResParts);
16753 }
16754 }
16755 }
16756
16757 for (auto [RegClass, UsedRegs] : PressureByClass) {
16758 const unsigned NumAvailRegs = TTI->getNumberOfRegisters(RegClass);
16759 if (NumAvailRegs == 0 || UsedRegs <= NumAvailRegs)
16760 continue;
16761 const unsigned SpillCount = UsedRegs - NumAvailRegs;
16762 InstructionCost SingleRegSpillReload =
16763 TTI->getRegisterClassReloadCost(RegClass, CostKind);
16764 // No need to spill cost only for the root entry (Idx == 0), for reduction
16765 // and non-returning instructions, like void calls.
16766 if (E->Idx > 0 || !UserIgnoreList || !E->Scalars[0]->getType()->isVoidTy())
16767 SingleRegSpillReload +=
16768 TTI->getRegisterClassSpillCost(RegClass, CostKind);
16769 SpillsReloads += SingleRegSpillReload * SpillCount;
16770 }
16771 return SpillsReloads;
16772}
16773
16774/// Calculates a VectorInstrContext from the values in \p VL at indices in
16775/// \p DemandedElts.
16779 for (unsigned I : seq(VL.size())) {
16780 if (!DemandedElts[I])
16781 continue;
16782 Value *V = VL[I];
16783 if (isa<UndefValue>(V))
16784 continue;
16785 auto *Inst = dyn_cast<Instruction>(V);
16786 if (!Inst)
16789 if (VIC == TTI::VectorInstrContext::None) {
16790 VIC = IVIC;
16791 continue;
16792 }
16793 if (VIC != IVIC)
16795 }
16796 return VIC;
16797}
16798
16800BoUpSLP::getEntryCost(const TreeEntry *E, ArrayRef<Value *> VectorizedVals,
16801 SmallPtrSetImpl<Value *> &CheckedExtracts) {
16802 ArrayRef<Value *> VL = E->Scalars;
16803
16804 Type *ScalarTy = getValueType(VL[0], SLPReVec);
16805 if (SLPReVec && E->State == TreeEntry::Vectorize &&
16806 E->getOpcode() == Instruction::InsertElement &&
16807 !E->getOperand(1).back()->getType()->isVectorTy())
16808 ScalarTy = ScalarTy->getScalarType();
16809 if (!isValidElementType(ScalarTy, SLPReVec))
16810 return InstructionCost::getInvalid();
16811
16812 // If we have computed a smaller type for the expression, update VecTy so
16813 // that the costs will be accurate.
16814 auto It = MinBWs.find(E);
16815 Type *OrigScalarTy = ScalarTy;
16816 if (It != MinBWs.end()) {
16817 auto *VecTy = dyn_cast<FixedVectorType>(ScalarTy);
16818 ScalarTy = IntegerType::get(F->getContext(), It->second.first);
16819 if (VecTy)
16820 ScalarTy = getWidenedType(ScalarTy, VecTy->getNumElements());
16821 } else if (E->Idx == 0 && isReducedBitcastRoot()) {
16822 const TreeEntry *ZExt = getOperandEntry(E, /*Idx=*/0);
16823 ScalarTy = cast<CastInst>(ZExt->getMainOp())->getSrcTy();
16824 }
16825 auto *VecTy = getWidenedType(ScalarTy, VL.size());
16826 unsigned EntryVF = E->getVectorFactor();
16827 auto *FinalVecTy = getWidenedType(ScalarTy, EntryVF);
16828
16829 const InstructionCost SpillsReloads =
16830 getVectorSpillReloadCost(E, ScalarTy, VecTy, FinalVecTy, CostKind);
16831 if (E->isGather() || TransformedToGatherNodes.contains(E)) {
16832 if (allConstant(VL))
16833 return 0;
16835 return InstructionCost::getInvalid();
16836 return SpillsReloads +
16837 processBuildVector<ShuffleCostEstimator, InstructionCost>(
16838 E, ScalarTy, *TTI, VectorizedVals, *this, CheckedExtracts);
16839 }
16840 if (E->State == TreeEntry::SplitVectorize) {
16841 assert(E->CombinedEntriesWithIndices.size() == 2 &&
16842 "Expected exactly 2 combined entries.");
16843 assert(E->ReuseShuffleIndices.empty() && "Expected empty reuses mask.");
16844 InstructionCost VectorCost = 0;
16845 if (E->ReorderIndices.empty()) {
16846 VectorCost = getShuffleCost(
16847 *TTI, TTI::SK_InsertSubvector, cast<VectorType>(FinalVecTy), CostKind,
16848 {}, E->CombinedEntriesWithIndices.back().second,
16850 ScalarTy,
16851 VectorizableTree[E->CombinedEntriesWithIndices.back().first]
16852 ->getVectorFactor())));
16853 } else {
16854 unsigned CommonVF =
16855 std::max(VectorizableTree[E->CombinedEntriesWithIndices.front().first]
16856 ->getVectorFactor(),
16857 VectorizableTree[E->CombinedEntriesWithIndices.back().first]
16858 ->getVectorFactor());
16859 VectorCost =
16861 cast<VectorType>(getWidenedType(ScalarTy, CommonVF)),
16862 CostKind, E->getSplitMask());
16863 }
16864 VectorCost += SpillsReloads;
16865 LLVM_DEBUG(dumpTreeCosts(E, 0, VectorCost, 0, "Calculated costs for Tree"));
16866 return VectorCost;
16867 }
16868 InstructionCost CommonCost = 0;
16869 SmallVector<int> Mask;
16870 if (!E->ReorderIndices.empty() && E->State != TreeEntry::CompressVectorize &&
16871 (E->State != TreeEntry::StridedVectorize ||
16872 !isReverseOrder(E->ReorderIndices))) {
16873 SmallVector<int> NewMask;
16874 if (E->getOpcode() == Instruction::Store) {
16875 // For stores the order is actually a mask.
16876 NewMask.resize(E->ReorderIndices.size());
16877 copy(E->ReorderIndices, NewMask.begin());
16878 } else {
16879 inversePermutation(E->ReorderIndices, NewMask);
16880 }
16881 addMask(Mask, NewMask);
16882 }
16883 if (!E->ReuseShuffleIndices.empty())
16884 addMask(Mask, E->ReuseShuffleIndices);
16885 if (!Mask.empty() && !ShuffleVectorInst::isIdentityMask(Mask, Mask.size())) {
16886 assert(!isa<StructType>(FinalVecTy) &&
16887 "Expected non-struct vector type for shuffle cost calculation.");
16888 CommonCost = getShuffleCost(*TTI, TTI::SK_PermuteSingleSrc,
16889 cast<VectorType>(FinalVecTy), CostKind, Mask,
16890 /*Index=*/0, cast<VectorType>(VecTy));
16891 }
16892 assert((E->State == TreeEntry::Vectorize ||
16893 E->State == TreeEntry::ScatterVectorize ||
16894 E->State == TreeEntry::StridedVectorize ||
16895 E->State == TreeEntry::ExpandVectorize ||
16896 E->State == TreeEntry::CompressVectorize ||
16897 E->State == TreeEntry::BlendedLoadVectorize) &&
16898 "Unhandled state");
16899 assert(E->getOpcode() &&
16900 ((allSameType(VL) && allSameBlock(VL)) ||
16901 (E->getOpcode() == Instruction::GetElementPtr &&
16902 E->getMainOp()->getType()->isPointerTy()) ||
16903 E->hasCopyableElements()) &&
16904 "Invalid VL");
16905 Instruction *VL0 = E->getMainOp();
16906 unsigned ShuffleOrOp =
16907 E->isAltShuffle() ? (unsigned)Instruction::ShuffleVector : E->getOpcode();
16908 if (E->CombinedOp != TreeEntry::NotCombinedOp)
16909 ShuffleOrOp = E->CombinedOp;
16910 SmallSetVector<Value *, 16> UniqueValues;
16911 SmallVector<unsigned, 16> UniqueIndexes;
16912 for (auto [Idx, V] : enumerate(VL))
16913 if (UniqueValues.insert(V))
16914 UniqueIndexes.push_back(Idx);
16915 const unsigned Sz = UniqueValues.size();
16916 SmallBitVector UsedScalars(Sz, false);
16917 for (unsigned I = 0; I < Sz; ++I) {
16918 if (isa<Instruction>(UniqueValues[I]) &&
16919 !E->isCopyableElement(UniqueValues[I]) &&
16920 getTreeEntries(UniqueValues[I]).front() == E)
16921 continue;
16922 UsedScalars.set(I);
16923 }
16924 auto GetCastContextHint = [&](Value *V) {
16925 if (ArrayRef<TreeEntry *> OpTEs = getTreeEntries(V); OpTEs.size() == 1)
16926 return getCastContextHint(*OpTEs.front());
16927 InstructionsState SrcState = getSameOpcode(E->getOperand(0), *TLI);
16928 if (SrcState && SrcState.getOpcode() == Instruction::Load &&
16929 !SrcState.isAltShuffle())
16932 };
16933 auto GetCostDiff =
16934 [=](function_ref<InstructionCost(unsigned)> ScalarEltCost,
16935 function_ref<InstructionCost(InstructionCost)> VectorCost) {
16936 // Calculate the cost of this instruction.
16937 InstructionCost ScalarCost = 0;
16938 if (isa<CastInst, CallInst>(VL0)) {
16939 // For some of the instructions no need to calculate cost for each
16940 // particular instruction, we can use the cost of the single
16941 // instruction x total number of scalar instructions.
16942 ScalarCost = (Sz - UsedScalars.count()) * ScalarEltCost(0);
16943 } else {
16944 for (unsigned I = 0; I < Sz; ++I) {
16945 if (UsedScalars.test(I))
16946 continue;
16947 ScalarCost += ScalarEltCost(I);
16948 }
16949 }
16950
16951 InstructionCost VecCost = VectorCost(CommonCost);
16952 // Check if the current node must be resized, if the parent node is not
16953 // resized.
16954 if (It != MinBWs.end() && !UnaryInstruction::isCast(E->getOpcode()) &&
16955 E->Idx != 0 &&
16956 (E->getOpcode() != Instruction::Load || E->UserTreeIndex)) {
16957 const EdgeInfo &EI = E->UserTreeIndex;
16958 if (!EI.UserTE->hasState() ||
16959 EI.UserTE->getOpcode() != Instruction::Select ||
16960 EI.EdgeIdx != 0) {
16961 auto UserBWIt = MinBWs.find(EI.UserTE);
16962 Type *UserScalarTy =
16963 (EI.UserTE->isGather() ||
16964 EI.UserTE->State == TreeEntry::SplitVectorize)
16965 ? EI.UserTE->Scalars.front()->getType()
16966 : EI.UserTE->getOperand(EI.EdgeIdx).front()->getType();
16967 if (UserBWIt != MinBWs.end())
16968 UserScalarTy = IntegerType::get(ScalarTy->getContext(),
16969 UserBWIt->second.first);
16970 if (ScalarTy != UserScalarTy) {
16971 unsigned BWSz = DL->getTypeSizeInBits(ScalarTy);
16972 unsigned SrcBWSz = DL->getTypeSizeInBits(UserScalarTy);
16973 unsigned VecOpcode;
16974 auto *UserVecTy = getWidenedType(UserScalarTy, E->Scalars.size());
16975 if (BWSz > SrcBWSz)
16976 VecOpcode = Instruction::Trunc;
16977 else
16978 VecOpcode =
16979 It->second.second ? Instruction::SExt : Instruction::ZExt;
16980 TTI::CastContextHint CCH = GetCastContextHint(VL0);
16981 VecCost += TTI->getCastInstrCost(VecOpcode, UserVecTy, VecTy, CCH,
16982 CostKind);
16983 }
16984 }
16985 }
16986 VecCost += SpillsReloads;
16987 LLVM_DEBUG(dumpTreeCosts(E, CommonCost, VecCost - CommonCost,
16988 ScalarCost, "Calculated costs for Tree"));
16989 return VecCost - ScalarCost;
16990 };
16991 // Price peeled intermediate instructions on the scalar side: they are
16992 // erased when the node vectorizes. The peeled cost is folded into the
16993 // first scalar-cost query so the cost dump reports the full scalar cost.
16994 // Peeled chain links are always 2-operand associative binops, priced per
16995 // instruction so the operand properties (constants, uniformity) apply.
16996 auto GetCostDiffWithPeeled =
16997 [&](function_ref<InstructionCost(unsigned)> ScalarEltCost,
16998 function_ref<InstructionCost(InstructionCost)> VectorCost) {
16999 InstructionCost PeeledScalarCost = 0;
17000 for (Value *V : E->getReassocScalars()) {
17001 auto *I = cast<Instruction>(V);
17002 TTI::OperandValueInfo Op1Info = TTI::getOperandInfo(I->getOperand(0));
17003 TTI::OperandValueInfo Op2Info = TTI::getOperandInfo(I->getOperand(1));
17004 PeeledScalarCost += TTI->getArithmeticInstrCost(
17005 I->getOpcode(), OrigScalarTy, CostKind, Op1Info, Op2Info);
17006 }
17007 bool PeeledCostAdded = false;
17008 InstructionCost CostDiff = GetCostDiff(
17009 [&](unsigned Idx) {
17010 InstructionCost Cost = ScalarEltCost(Idx);
17011 if (!PeeledCostAdded) {
17012 PeeledCostAdded = true;
17013 Cost += PeeledScalarCost;
17014 }
17015 return Cost;
17016 },
17017 VectorCost);
17018 // Every scalar may be marked as used elsewhere, leaving the
17019 // scalar-cost query uncalled and the peeled cost unapplied.
17020 if (!PeeledCostAdded)
17021 CostDiff -= PeeledScalarCost;
17022 return CostDiff;
17023 };
17024 // Calculate cost difference from vectorizing set of GEPs.
17025 // Negative value means vectorizing is profitable.
17026 auto GetGEPCostDiff = [=](ArrayRef<Value *> Ptrs, Value *BasePtr) {
17027 assert((E->State == TreeEntry::Vectorize ||
17028 E->State == TreeEntry::StridedVectorize ||
17029 E->State == TreeEntry::ExpandVectorize ||
17030 E->State == TreeEntry::CompressVectorize) &&
17031 "Entry state expected to be Vectorize, StridedVectorize, "
17032 "ExpandVectorize or CompressVectorize here.");
17033 InstructionCost ScalarCost = 0;
17034 InstructionCost VecCost = 0;
17035 std::tie(ScalarCost, VecCost) =
17036 getGEPCosts(*TTI, Ptrs, BasePtr, E->getOpcode(), CostKind, OrigScalarTy,
17037 cast<VectorType>(VecTy));
17038 LLVM_DEBUG(dumpTreeCosts(E, 0, VecCost, ScalarCost,
17039 "Calculated GEPs cost for Tree"));
17040
17041 return VecCost - ScalarCost + SpillsReloads;
17042 };
17043
17044 auto GetMinMaxCost = [&](Type *Ty, Instruction *VI = nullptr) {
17045 auto [MinMaxID, SelectOnly] = canConvertToMinOrMaxIntrinsic(VI ? VI : VL);
17046 if (MinMaxID == Intrinsic::not_intrinsic)
17047 return InstructionCost::getInvalid();
17048 Type *CanonicalType = Ty;
17049 if (CanonicalType->isPtrOrPtrVectorTy())
17050 CanonicalType = CanonicalType->getWithNewType(IntegerType::get(
17051 CanonicalType->getContext(),
17052 DL->getTypeSizeInBits(CanonicalType->getScalarType())));
17053
17054 IntrinsicCostAttributes CostAttrs(MinMaxID, CanonicalType,
17055 {CanonicalType, CanonicalType});
17057 TTI->getIntrinsicInstrCost(CostAttrs, CostKind);
17058 // If the selects are the only uses of the compares, they will be
17059 // dead and we can adjust the cost by removing their cost.
17060 if (VI && SelectOnly) {
17061 assert((!Ty->isVectorTy() || SLPReVec) &&
17062 "Expected only for scalar type.");
17063 auto *CI = cast<CmpInst>(VI->getOperand(0));
17064 IntrinsicCost -= TTI->getCmpSelInstrCost(
17065 CI->getOpcode(), Ty, Builder.getInt1Ty(), CI->getPredicate(),
17066 CostKind, {TTI::OK_AnyValue, TTI::OP_None},
17067 {TTI::OK_AnyValue, TTI::OP_None}, CI);
17068 }
17069 return IntrinsicCost;
17070 };
17071 auto GetFMulAddCost = [&, &TTI = *TTI](const InstructionsState &S,
17072 Instruction *VI) {
17074 canConvertToFMA(VI, S, *DT, *DL, TTI, *TLI, CostKind);
17075 return Cost;
17076 };
17077 switch (ShuffleOrOp) {
17078 case Instruction::PHI: {
17079 // Count reused scalars.
17080 InstructionCost ScalarCost = 0;
17081 SmallPtrSet<const TreeEntry *, 4> CountedOps;
17082 for (Value *V : UniqueValues) {
17083 auto *PHI = dyn_cast<PHINode>(V);
17084 if (!PHI)
17085 continue;
17086
17087 ValueList Operands(PHI->getNumIncomingValues(), nullptr);
17088 for (unsigned I = 0, N = PHI->getNumIncomingValues(); I < N; ++I) {
17089 Value *Op = PHI->getIncomingValue(I);
17090 Operands[I] = Op;
17091 }
17092 if (const TreeEntry *OpTE =
17093 getSameValuesTreeEntry(Operands.front(), Operands))
17094 if (CountedOps.insert(OpTE).second &&
17095 !OpTE->ReuseShuffleIndices.empty())
17096 ScalarCost += TTI::TCC_Basic * (OpTE->ReuseShuffleIndices.size() -
17097 OpTE->Scalars.size());
17098 }
17099
17100 return CommonCost - ScalarCost + SpillsReloads;
17101 }
17102 case Instruction::ExtractValue:
17103 case Instruction::ExtractElement: {
17104 // For ExtractValue entries vectorized via the struct-call path the scalar
17105 // extractvalue instructions are free (they become extractvalue from a
17106 // struct-of-vectors, which is also free). The cost is fully captured by
17107 // the underlying Call entry and the external-use extraction costs.
17108 if (ShuffleOrOp == Instruction::ExtractValue && !E->StructEVIndices.empty())
17109 return CommonCost;
17110 APInt DemandedElts;
17111 APInt CopyableInsertElts;
17112 VectorType *SrcVecTy = nullptr;
17113 auto GetScalarCost = [&](unsigned Idx) {
17114 if (isa<PoisonValue>(UniqueValues[Idx]))
17116
17117 // Copyable lanes are not extracts; they are inserted into the reused
17118 // source vector, so charge the insert to the vector side only.
17119 if (E->isCopyableElement(UniqueValues[Idx])) {
17120 if (CopyableInsertElts.isZero())
17121 CopyableInsertElts = APInt::getZero(E->getVectorFactor());
17122 CopyableInsertElts.setBit(Idx);
17124 }
17125
17126 auto *I = cast<Instruction>(UniqueValues[Idx]);
17127 if (!SrcVecTy) {
17128 if (ShuffleOrOp == Instruction::ExtractElement) {
17129 auto *EE = cast<ExtractElementInst>(I);
17130 SrcVecTy = EE->getVectorOperandType();
17131 } else {
17132 auto *EV = cast<ExtractValueInst>(I);
17133 Type *AggregateTy = EV->getAggregateOperand()->getType();
17134 unsigned NumElts;
17135 if (auto *ATy = dyn_cast<ArrayType>(AggregateTy))
17136 NumElts = ATy->getNumElements();
17137 else
17138 NumElts = AggregateTy->getStructNumElements();
17139 SrcVecTy = cast<VectorType>(getWidenedType(OrigScalarTy, NumElts));
17140 }
17141 }
17142 if (I->hasOneUse()) {
17143 Instruction *Ext = I->user_back();
17144 if ((isa<SExtInst>(Ext) || isa<ZExtInst>(Ext)) &&
17146 // Use getExtractWithExtendCost() to calculate the cost of
17147 // extractelement/ext pair.
17148 InstructionCost Cost = TTI->getExtractWithExtendCost(
17149 Ext->getOpcode(), Ext->getType(), SrcVecTy, *getExtractIndex(I),
17150 CostKind);
17151 // Subtract the cost of s|zext which is subtracted separately.
17152 Cost -= TTI->getCastInstrCost(
17153 Ext->getOpcode(), Ext->getType(), I->getType(),
17154 TTI::getCastContextHint(Ext), CostKind, Ext);
17155 return Cost;
17156 }
17157 }
17158 if (DemandedElts.isZero())
17159 DemandedElts = APInt::getZero(getNumElements(SrcVecTy));
17160 DemandedElts.setBit(*getExtractIndex(I));
17162 };
17163 auto GetVectorCost = [&, &TTI = *TTI](InstructionCost CommonCost) {
17164 return CommonCost +
17165 (CopyableInsertElts.isZero()
17167 : TTI.getScalarizationOverhead(
17169 getWidenedType(OrigScalarTy, E->getVectorFactor())),
17170 CopyableInsertElts, /*Insert=*/true,
17171 /*Extract=*/false, CostKind)) -
17172 (DemandedElts.isZero()
17174 : TTI.getScalarizationOverhead(SrcVecTy, DemandedElts,
17175 /*Insert=*/false,
17176 /*Extract=*/true, CostKind));
17177 };
17178 return GetCostDiff(GetScalarCost, GetVectorCost);
17179 }
17180 case Instruction::InsertValue:
17181 case Instruction::InsertElement: {
17182 assert(E->ReuseShuffleIndices.empty() &&
17183 "Unique insertelements only are expected.");
17184 FixedVectorType *SrcVecTy = getInsertBuildVectorSrcTy(E);
17185 unsigned const NumElts = getNumElements(SrcVecTy);
17186 unsigned const NumScalars = VL.size();
17187
17188 unsigned NumOfParts =
17189 getNumberOfParts(SrcVecTy, VL0->getOperand(1)->getType());
17190
17191 SmallVector<int> InsertMask(NumElts, PoisonMaskElem);
17192 unsigned OffsetBeg = *getElementIndex(VL.front());
17193 unsigned OffsetEnd = OffsetBeg;
17194 InsertMask[OffsetBeg] = 0;
17195 for (auto [I, V] : enumerate(VL.drop_front())) {
17196 unsigned Idx = *getElementIndex(V);
17197 if (OffsetBeg > Idx)
17198 OffsetBeg = Idx;
17199 else if (OffsetEnd < Idx)
17200 OffsetEnd = Idx;
17201 InsertMask[Idx] = I + 1;
17202 }
17203 unsigned VecScalarsSz = PowerOf2Ceil(NumElts);
17204 if (NumOfParts > 0 && NumOfParts < NumElts)
17205 VecScalarsSz = PowerOf2Ceil((NumElts + NumOfParts - 1) / NumOfParts);
17206 unsigned VecSz = (1 + OffsetEnd / VecScalarsSz - OffsetBeg / VecScalarsSz) *
17207 VecScalarsSz;
17208 unsigned Offset = VecScalarsSz * (OffsetBeg / VecScalarsSz);
17209 unsigned InsertVecSz = std::min<unsigned>(
17210 PowerOf2Ceil(OffsetEnd - OffsetBeg + 1),
17211 ((OffsetEnd - OffsetBeg + VecScalarsSz) / VecScalarsSz) * VecScalarsSz);
17212 bool IsWholeSubvector =
17213 OffsetBeg == Offset && ((OffsetEnd + 1) % VecScalarsSz == 0);
17214 // Check if we can safely insert a subvector. If it is not possible, just
17215 // generate a whole-sized vector and shuffle the source vector and the new
17216 // subvector.
17217 if (OffsetBeg + InsertVecSz > VecSz) {
17218 // Align OffsetBeg to generate correct mask.
17219 OffsetBeg = alignDown(OffsetBeg, VecSz, Offset);
17220 InsertVecSz = VecSz;
17221 }
17222
17223 APInt DemandedElts = APInt::getZero(NumElts);
17224 // TODO: Add support for Instruction::InsertValue.
17225 SmallVector<int> Mask;
17226 if (!E->ReorderIndices.empty()) {
17227 inversePermutation(E->ReorderIndices, Mask);
17228 Mask.append(InsertVecSz - Mask.size(), PoisonMaskElem);
17229 } else {
17230 Mask.assign(VecSz, PoisonMaskElem);
17231 std::iota(Mask.begin(), std::next(Mask.begin(), InsertVecSz), 0);
17232 }
17233 bool IsIdentity = true;
17234 SmallVector<int> PrevMask(InsertVecSz, PoisonMaskElem);
17235 SmallVector<Value *> AdjustedVL(NumElts, PoisonValue::get(ScalarTy));
17236 Mask.swap(PrevMask);
17237 for (unsigned I = 0; I < NumScalars; ++I) {
17238 unsigned InsertIdx = *getElementIndex(VL[PrevMask[I]]);
17239 DemandedElts.setBit(InsertIdx);
17240 AdjustedVL[InsertIdx] = VL[PrevMask[I]];
17241 IsIdentity &= InsertIdx - OffsetBeg == I;
17242 Mask[InsertIdx - OffsetBeg] = I;
17243 }
17244 assert(Offset < NumElts && "Failed to find vector index offset");
17245
17247 // First cost - resize to actual vector size if not identity shuffle or
17248 // need to shift the vector.
17249 // Do not calculate the cost if the actual size is the register size and
17250 // we can merge this shuffle with the following SK_Select.
17251 auto *InsertVecTy = cast<VectorType>(getWidenedType(ScalarTy, InsertVecSz));
17252 if (!IsIdentity)
17254 InsertVecTy, CostKind, Mask);
17255 auto *FirstInsert = cast<Instruction>(*find_if(E->Scalars, [E](Value *V) {
17256 return !is_contained(E->Scalars, cast<Instruction>(V)->getOperand(0));
17257 }));
17258 // Second cost - permutation with subvector, if some elements are from the
17259 // initial vector or inserting a subvector.
17260 // TODO: Implement the analysis of the FirstInsert->getOperand(0)
17261 // subvector of ActualVecTy.
17262 SmallBitVector InMask =
17263 isUndefVector(FirstInsert->getOperand(0),
17264 buildUseMask(NumElts, InsertMask, UseMask::UndefsAsMask));
17266 *TTI, SLPReVec, ScalarTy, SrcVecTy, DemandedElts,
17267 /*Insert=*/true, /*Extract=*/false, CostKind, InMask.all(), AdjustedVL,
17268 getVectorInstrContextHint(AdjustedVL, DemandedElts));
17269 if (!InMask.all() && NumScalars != NumElts && !IsWholeSubvector) {
17270 if (InsertVecSz != VecSz) {
17271 auto *ActualVecTy = cast<VectorType>(getWidenedType(ScalarTy, VecSz));
17272 Cost += getShuffleCost(*TTI, TTI::SK_InsertSubvector, ActualVecTy,
17273 CostKind, {}, OffsetBeg - Offset, InsertVecTy);
17274 } else {
17275 for (unsigned I = 0, End = OffsetBeg - Offset; I < End; ++I)
17276 Mask[I] = InMask.test(I) ? PoisonMaskElem : I;
17277 for (unsigned I = OffsetBeg - Offset, End = OffsetEnd - Offset;
17278 I <= End; ++I)
17279 if (Mask[I] != PoisonMaskElem)
17280 Mask[I] = I + VecSz;
17281 for (unsigned I = OffsetEnd + 1 - Offset; I < VecSz; ++I)
17282 Mask[I] =
17283 ((I >= InMask.size()) || InMask.test(I)) ? PoisonMaskElem : I;
17284 Cost += getShuffleCost(*TTI, TTI::SK_PermuteTwoSrc, InsertVecTy,
17285 CostKind, Mask);
17286 }
17287 }
17288 if (ShuffleOrOp == Instruction::InsertValue &&
17290 // Match the stack slot alignment used during codegen (see the store +
17291 // load roundtrip in vectorizeTree()): the slot holds both the source
17292 // vector and the original aggregate.
17293 Align VecAlign = std::max(DL->getPrefTypeAlign(SrcVecTy),
17294 DL->getPrefTypeAlign(VL0->getType()));
17295 Cost += TTI->getMemoryOpCost(Instruction::Store, SrcVecTy, VecAlign,
17296 /*AddressSpace=*/0, CostKind) +
17297 TTI->getMemoryOpCost(Instruction::Load, VL0->getType(), VecAlign,
17298 /*AddressSpace=*/0, CostKind);
17299 }
17300 return Cost + SpillsReloads;
17301 }
17302 case Instruction::ZExt:
17303 case Instruction::SExt:
17304 case Instruction::FPToUI:
17305 case Instruction::FPToSI:
17306 case Instruction::FPExt:
17307 case Instruction::PtrToInt:
17308 case Instruction::PtrToAddr:
17309 case Instruction::IntToPtr:
17310 case Instruction::SIToFP:
17311 case Instruction::UIToFP:
17312 case Instruction::Trunc:
17313 case Instruction::FPTrunc:
17314 case Instruction::BitCast: {
17315 auto SrcIt = MinBWs.find(getOperandEntry(E, 0));
17316 Type *SrcScalarTy = VL0->getOperand(0)->getType();
17317 auto *SrcVecTy = getWidenedType(SrcScalarTy, VL.size());
17318 unsigned Opcode = ShuffleOrOp;
17319 unsigned VecOpcode = Opcode;
17320 if (!ScalarTy->isFPOrFPVectorTy() && !SrcScalarTy->isFPOrFPVectorTy() &&
17321 (SrcIt != MinBWs.end() || It != MinBWs.end())) {
17322 // Check if the values are candidates to demote.
17323 unsigned SrcBWSz = DL->getTypeSizeInBits(SrcScalarTy->getScalarType());
17324 if (SrcIt != MinBWs.end()) {
17325 SrcBWSz = SrcIt->second.first;
17326 unsigned SrcScalarTyNumElements = getNumElements(SrcScalarTy);
17327 SrcScalarTy = IntegerType::get(F->getContext(), SrcBWSz);
17328 SrcVecTy =
17329 getWidenedType(SrcScalarTy, VL.size() * SrcScalarTyNumElements);
17330 }
17331 unsigned BWSz = DL->getTypeSizeInBits(ScalarTy->getScalarType());
17332 if (BWSz == SrcBWSz) {
17333 VecOpcode = Instruction::BitCast;
17334 } else if (BWSz < SrcBWSz) {
17335 VecOpcode = Instruction::Trunc;
17336 } else if (It != MinBWs.end()) {
17337 assert(BWSz > SrcBWSz && "Invalid cast!");
17338 VecOpcode = It->second.second ? Instruction::SExt : Instruction::ZExt;
17339 } else if (SrcIt != MinBWs.end()) {
17340 assert(BWSz > SrcBWSz && "Invalid cast!");
17341 VecOpcode =
17342 SrcIt->second.second ? Instruction::SExt : Instruction::ZExt;
17343 }
17344 } else if (VecOpcode == Instruction::SIToFP && SrcIt != MinBWs.end() &&
17345 !SrcIt->second.second) {
17346 VecOpcode = Instruction::UIToFP;
17347 }
17348 auto GetScalarCost = [&](unsigned Idx) -> InstructionCost {
17349 assert(Idx == 0 && "Expected 0 index only");
17350 return TTI->getCastInstrCost(Opcode, VL0->getType(),
17351 VL0->getOperand(0)->getType(),
17352 TTI::getCastContextHint(VL0), CostKind, VL0);
17353 };
17354 auto GetVectorCost = [=](InstructionCost CommonCost) {
17355 // Do not count cost here if minimum bitwidth is in effect and it is just
17356 // a bitcast (here it is just a noop).
17357 if (VecOpcode != Opcode && VecOpcode == Instruction::BitCast)
17358 return CommonCost;
17359 auto *VI = VL0->getOpcode() == Opcode ? VL0 : nullptr;
17360 TTI::CastContextHint CCH = GetCastContextHint(VL0->getOperand(0));
17361
17362 bool IsArithmeticExtendedReduction =
17363 E->Idx == 0 && UserIgnoreList &&
17364 all_of(*UserIgnoreList, [](Value *V) {
17365 auto *I = cast<Instruction>(V);
17366 return is_contained({Instruction::Add, Instruction::FAdd,
17367 Instruction::Mul, Instruction::FMul,
17368 Instruction::And, Instruction::Or,
17369 Instruction::Xor},
17370 I->getOpcode());
17371 });
17372 if (IsArithmeticExtendedReduction &&
17373 (VecOpcode == Instruction::ZExt || VecOpcode == Instruction::SExt))
17374 return CommonCost;
17375 return CommonCost +
17376 TTI->getCastInstrCost(VecOpcode, VecTy, SrcVecTy, CCH, CostKind,
17377 VecOpcode == Opcode ? VI : nullptr);
17378 };
17379 return GetCostDiff(GetScalarCost, GetVectorCost);
17380 }
17381 case Instruction::FCmp:
17382 case Instruction::ICmp:
17383 // Override ScalarTy/VecTy with the compared operand type (not i1). The
17384 // cost of a compare instruction is determined by the operand width, and
17385 // getCmpSelInstrCost expects the compared type as its first type arg.
17386 OrigScalarTy = ScalarTy =
17387 getValueType(VL0, SLPReVec, /*LookThroughCmp=*/true);
17388 VecTy = getWidenedType(ScalarTy, VL.size());
17389 [[fallthrough]];
17390 case Instruction::Select: {
17391 CmpPredicate VecPred, SwappedVecPred;
17392 auto MatchCmp = m_Cmp(VecPred, m_Value(), m_Value());
17393 if (match(VL0, m_Select(MatchCmp, m_Value(), m_Value())) ||
17394 match(VL0, MatchCmp))
17395 SwappedVecPred = CmpInst::getSwappedPredicate(VecPred);
17396 else
17397 SwappedVecPred = VecPred = ScalarTy->isFloatingPointTy()
17400 auto GetScalarCost = [&](unsigned Idx) {
17401 if (isa<PoisonValue>(UniqueValues[Idx]))
17403
17404 if (!isa<SelectInst>(UniqueValues[Idx]))
17405 return TTI->getInstructionCost(cast<Instruction>(UniqueValues[Idx]),
17406 CostKind);
17407
17408 auto *VI = cast<Instruction>(UniqueValues[Idx]);
17409 CmpPredicate CurrentPred = ScalarTy->isFloatingPointTy()
17412 Value *LHS = nullptr, *RHS = nullptr;
17413 auto MatchCmp = m_Cmp(CurrentPred, m_Value(), m_Value());
17414 bool IsSelect =
17415 ShuffleOrOp == Instruction::Select &&
17416 (match(VI, m_Select(MatchCmp, m_Value(LHS), m_Value(RHS))) ||
17418 if ((!IsSelect && !match(VI, MatchCmp)) ||
17419 (CurrentPred != static_cast<CmpInst::Predicate>(VecPred) &&
17420 CurrentPred != static_cast<CmpInst::Predicate>(SwappedVecPred)))
17421 VecPred = SwappedVecPred = ScalarTy->isFloatingPointTy()
17424
17425 // Check if operands are of i1 types, like a condition expression.
17426 // TODO: consider implementing this in TTI.
17427 InstructionCost ScalarCost = InstructionCost::getInvalid();
17428 if (IsSelect && LHS->getType() == VI->getOperand(0)->getType()) {
17429 assert(LHS->getType() == RHS->getType() &&
17430 "Expected same type for LHS/RHS");
17431 // select i1 v, i1 true, i1 b -> or i1 v, i1 b
17432 if (match(LHS, m_AllOnes())) {
17433 ScalarCost = TTI->getArithmeticInstrCost(
17434 Instruction::Or, LHS->getType(), CostKind,
17435 getOperandInfo(VI->getOperand(0)), getOperandInfo(RHS));
17436 } else if (match(RHS, m_Zero())) {
17437 // select i1 v, i1 b, i1 false -> and i1 v, i1 b
17438 ScalarCost = TTI->getArithmeticInstrCost(
17439 Instruction::And, LHS->getType(), CostKind,
17440 getOperandInfo(VI->getOperand(0)), getOperandInfo(LHS));
17441 }
17442 }
17443 if (!ScalarCost.isValid()) {
17444 // For selects, the "condition type" arg is the condition operand's
17445 // type; for standalone compares, it is the result type (i1).
17446 ScalarCost = TTI->getCmpSelInstrCost(
17447 E->getOpcode(), OrigScalarTy,
17448 ShuffleOrOp == Instruction::Select ? VL0->getOperand(0)->getType()
17449 : VL0->getType(),
17450 CurrentPred, CostKind,
17451 getOperandInfo(
17452 VI->getOperand(ShuffleOrOp == Instruction::Select ? 1 : 0)),
17453 getOperandInfo(
17454 VI->getOperand(ShuffleOrOp == Instruction::Select ? 2 : 1)),
17455 VI);
17456 }
17457 InstructionCost IntrinsicCost = GetMinMaxCost(OrigScalarTy, VI);
17458 if (IntrinsicCost.isValid())
17459 ScalarCost = IntrinsicCost;
17460
17461 return ScalarCost;
17462 };
17463 auto GetVectorCost = [&](InstructionCost CommonCost) {
17464 // For selects, the condition type may differ from the result type
17465 // (e.g. condition is <N x i1> while result is <N x i32>). For
17466 // compares, the result type IS the mask (i1/vNi1). Construct the
17467 // right type so getCmpSelInstrCost sees the actual mask/result width.
17468 auto *MaskTy = cast<VectorType>(getWidenedType(
17469 ShuffleOrOp == Instruction::Select ? VL0->getOperand(0)->getType()
17470 : VL0->getType(),
17471 VL.size()));
17472
17473 InstructionCost VecCost = InstructionCost::getInvalid();
17474 if (ShuffleOrOp == Instruction::Select) {
17475 ArrayRef<Value *> Cond = E->getOperand(0);
17476 ArrayRef<Value *> LHS = E->getOperand(1);
17477 ArrayRef<Value *> RHS = E->getOperand(2);
17478 // select <VF x i1>, <VF x i1>, <VF x i1>?
17479 // TODO: consider implementing this in TTI.
17480 if (Cond.front()->getType() == LHS.front()->getType()) {
17481 // select <VF x i1> v, <VF x i1> true, <VF x i1> b -> or <VF x i1> v,
17482 // <VF x i1> b
17483 if (all_of(LHS, [&](Value *V) { return match(V, m_AllOnes()); })) {
17484 VecCost = TTI->getArithmeticInstrCost(
17485 Instruction::Or, VecTy, CostKind, getOperandInfo(Cond),
17486 getOperandInfo(RHS));
17487 } else if (all_of(RHS,
17488 [&](Value *V) { return match(V, m_Zero()); })) {
17489 // select <VF x i1> v, <VF x i1> b, <VF x i1> false -> and <VF x i1>
17490 // v, <VF x i1> b
17491 VecCost = TTI->getArithmeticInstrCost(
17492 Instruction::And, VecTy, CostKind, getOperandInfo(Cond),
17493 getOperandInfo(LHS));
17494 }
17495 }
17496 }
17497 if (!VecCost.isValid()) {
17498 VecCost = TTI->getCmpSelInstrCost(
17499 E->getOpcode(), VecTy, MaskTy, VecPred, CostKind,
17500 getOperandInfo(
17501 E->getOperand(ShuffleOrOp == Instruction::Select ? 1 : 0)),
17502 getOperandInfo(
17503 E->getOperand(ShuffleOrOp == Instruction::Select ? 2 : 1)),
17504 VL0);
17505 if (isa<SelectInst>(VL0)) {
17506 unsigned CondNumElements = getNumElements(MaskTy);
17507 unsigned VecTyNumElements = getNumElements(VecTy);
17508 assert(VecTyNumElements >= CondNumElements &&
17509 VecTyNumElements % CondNumElements == 0 &&
17510 "Cannot vectorize Instruction::Select");
17511 if (CondNumElements != VecTyNumElements) {
17512 // When the return type is i1 but the source is fixed vector type,
17513 // we need to duplicate the condition value.
17514 VecCost += getShuffleCost(
17515 *TTI, TTI::SK_PermuteSingleSrc, MaskTy, CostKind,
17516 createReplicatedMask(VecTyNumElements / CondNumElements,
17517 CondNumElements));
17518 }
17519 }
17520 }
17521 return VecCost + CommonCost;
17522 };
17523 return GetCostDiff(GetScalarCost, GetVectorCost);
17524 }
17525 case TreeEntry::MinMax: {
17526 auto GetScalarCost = [&](unsigned Idx) {
17527 return GetMinMaxCost(OrigScalarTy);
17528 };
17529 auto GetVectorCost = [&](InstructionCost CommonCost) {
17530 InstructionCost VecCost = GetMinMaxCost(VecTy);
17531 return VecCost + CommonCost;
17532 };
17533 return GetCostDiff(GetScalarCost, GetVectorCost);
17534 }
17535 case TreeEntry::FMulAdd: {
17536 auto GetScalarCost = [&](unsigned Idx) {
17537 if (isa<PoisonValue>(UniqueValues[Idx]))
17539 return GetFMulAddCost(E->getOperations(),
17540 cast<Instruction>(UniqueValues[Idx]));
17541 };
17542 auto GetVectorCost = [&, &TTI = *TTI](InstructionCost CommonCost) {
17543 FastMathFlags FMF;
17544 FMF.set();
17545 for (Value *V : E->Scalars) {
17546 if (auto *FPCI = dyn_cast<FPMathOperator>(V)) {
17547 FMF &= FPCI->getFastMathFlags();
17548 if (auto *FPCIOp = dyn_cast<FPMathOperator>(FPCI->getOperand(0)))
17549 FMF &= FPCIOp->getFastMathFlags();
17550 }
17551 }
17552 IntrinsicCostAttributes ICA(Intrinsic::fmuladd, VecTy,
17553 {VecTy, VecTy, VecTy}, FMF);
17554 InstructionCost VecCost = TTI.getIntrinsicInstrCost(ICA, CostKind);
17555 return VecCost + CommonCost;
17556 };
17557 return GetCostDiff(GetScalarCost, GetVectorCost);
17558 }
17559 case TreeEntry::ReducedBitcast:
17560 case TreeEntry::ReducedBitcastBSwap: {
17561 auto GetScalarCost = [&, &TTI = *TTI](unsigned Idx) {
17562 if (isa<PoisonValue>(UniqueValues[Idx]))
17564 auto *Shl = dyn_cast<Instruction>(UniqueValues[Idx]);
17565 if (!Shl)
17567 InstructionCost ScalarCost = TTI.getInstructionCost(Shl, CostKind);
17568 auto *ZExt = dyn_cast<Instruction>(Shl->getOperand(0));
17569 if (!ZExt)
17570 return ScalarCost;
17571 ScalarCost += TTI.getInstructionCost(ZExt, CostKind);
17572 return ScalarCost;
17573 };
17574 auto GetVectorCost = [&, &TTI = *TTI](InstructionCost CommonCost) {
17575 const TreeEntry *LhsTE = getOperandEntry(E, /*Idx=*/0);
17576 TTI::CastContextHint CastCtx =
17577 getCastContextHint(*getOperandEntry(LhsTE, /*Idx=*/0));
17578 Type *SrcScalarTy = cast<ZExtInst>(LhsTE->getMainOp())->getSrcTy();
17579 auto *SrcVecTy = getWidenedType(SrcScalarTy, LhsTE->getVectorFactor());
17580 InstructionCost BitcastCost = TTI.getCastInstrCost(
17581 Instruction::BitCast, ScalarTy, SrcVecTy, CastCtx, CostKind);
17582 if (ShuffleOrOp == TreeEntry::ReducedBitcastBSwap) {
17583 auto *SrcType = IntegerType::getIntNTy(
17584 ScalarTy->getContext(),
17585 DL->getTypeSizeInBits(SrcScalarTy) * EntryVF);
17586 IntrinsicCostAttributes CostAttrs(Intrinsic::bswap, SrcType, {SrcType});
17588 TTI.getIntrinsicInstrCost(CostAttrs, CostKind);
17589 BitcastCost += IntrinsicCost;
17590 if (SrcType != ScalarTy) {
17591 BitcastCost +=
17592 TTI.getCastInstrCost(Instruction::ZExt, ScalarTy, SrcType,
17593 TTI::CastContextHint::None, CostKind);
17594 }
17595 }
17596 return BitcastCost + CommonCost;
17597 };
17598 return GetCostDiff(GetScalarCost, GetVectorCost);
17599 }
17600 case TreeEntry::ReducedBitcastLoads:
17601 case TreeEntry::ReducedBitcastBSwapLoads: {
17602 auto GetScalarCost = [&, &TTI = *TTI](unsigned Idx) {
17603 if (isa<PoisonValue>(UniqueValues[Idx]))
17605 auto *Shl = dyn_cast<Instruction>(UniqueValues[Idx]);
17606 if (!Shl)
17608 InstructionCost ScalarCost = TTI.getInstructionCost(Shl, CostKind);
17609 auto *ZExt = dyn_cast<Instruction>(Shl->getOperand(0));
17610 if (!ZExt)
17611 return ScalarCost;
17612 ScalarCost += TTI.getInstructionCost(ZExt, CostKind);
17613 auto *Load = dyn_cast<Instruction>(ZExt->getOperand(0));
17614 if (!Load)
17615 return ScalarCost;
17616 ScalarCost += TTI.getInstructionCost(Load, CostKind);
17617 return ScalarCost;
17618 };
17619 auto GetVectorCost = [&, &TTI = *TTI](InstructionCost CommonCost) {
17620 const TreeEntry *LhsTE = getOperandEntry(E, /*Idx=*/0);
17621 const TreeEntry *LoadTE = getOperandEntry(LhsTE, /*Idx=*/0);
17622 auto *LI0 = cast<LoadInst>(LoadTE->getMainOp());
17623 auto *SrcType = IntegerType::getIntNTy(
17624 ScalarTy->getContext(),
17625 DL->getTypeSizeInBits(LI0->getType()) * EntryVF);
17626 InstructionCost LoadCost =
17627 TTI.getMemoryOpCost(Instruction::Load, SrcType, LI0->getAlign(),
17628 LI0->getPointerAddressSpace(), CostKind);
17629 if (ShuffleOrOp == TreeEntry::ReducedBitcastBSwapLoads) {
17630 IntrinsicCostAttributes CostAttrs(Intrinsic::bswap, SrcType, {SrcType});
17632 TTI.getIntrinsicInstrCost(CostAttrs, CostKind);
17633 LoadCost += IntrinsicCost;
17634 if (SrcType != ScalarTy) {
17635 LoadCost +=
17636 TTI.getCastInstrCost(Instruction::ZExt, ScalarTy, SrcType,
17637 TTI::CastContextHint::None, CostKind);
17638 }
17639 }
17640 return LoadCost + CommonCost;
17641 };
17642 return GetCostDiff(GetScalarCost, GetVectorCost);
17643 }
17644 case TreeEntry::ReducedCmpBitcast: {
17645 auto GetScalarCost = [&, &TTI = *TTI](unsigned Idx) {
17646 if (isa<PoisonValue>(UniqueValues[Idx]))
17648 auto *Sel = dyn_cast<Instruction>(UniqueValues[Idx]);
17649 if (!Sel)
17651 InstructionCost ScalarCost = TTI.getInstructionCost(Sel, CostKind);
17652 return ScalarCost;
17653 };
17654 auto GetVectorCost = [&, &TTI = *TTI](InstructionCost CommonCost) {
17655 Type *CmpTy = CmpInst::makeCmpResultType(VecTy);
17656 auto *DstTy =
17657 IntegerType::getIntNTy(ScalarTy->getContext(), E->getVectorFactor());
17658 InstructionCost BitcastCost =
17659 TTI.getCastInstrCost(Instruction::BitCast, DstTy, CmpTy,
17660 TTI::CastContextHint::None, CostKind);
17661 if (DstTy != ScalarTy) {
17662 BitcastCost +=
17663 TTI.getCastInstrCost(Instruction::ZExt, ScalarTy, DstTy,
17664 TTI::CastContextHint::None, CostKind);
17665 }
17666 return BitcastCost + CommonCost;
17667 };
17668 return GetCostDiff(GetScalarCost, GetVectorCost);
17669 }
17670 case Instruction::FNeg:
17671 case Instruction::Add:
17672 case Instruction::FAdd:
17673 case Instruction::Sub:
17674 case Instruction::FSub:
17675 case Instruction::Mul:
17676 case Instruction::FMul:
17677 case Instruction::UDiv:
17678 case Instruction::SDiv:
17679 case Instruction::FDiv:
17680 case Instruction::URem:
17681 case Instruction::SRem:
17682 case Instruction::FRem:
17683 case Instruction::Shl:
17684 case Instruction::LShr:
17685 case Instruction::AShr:
17686 case Instruction::And:
17687 case Instruction::Or:
17688 case Instruction::Xor: {
17689 auto GetScalarCost = [&](unsigned Idx) {
17690 if (isa<PoisonValue>(UniqueValues[Idx]))
17692
17693 // We cannot retrieve the operand from UniqueValues[Idx] because an
17694 // interchangeable instruction may be used. The order and the actual
17695 // operand might differ from what is retrieved from UniqueValues[Idx].
17696 unsigned Lane = UniqueIndexes[Idx];
17697 Value *Op1 = E->getOperand(0)[Lane];
17698 Value *Op2;
17699 SmallVector<const Value *, 2> Operands(1, Op1);
17700 if (isa<UnaryOperator>(UniqueValues[Idx])) {
17701 Op2 = Op1;
17702 } else {
17703 Op2 = E->getOperand(1)[Lane];
17704 Operands.push_back(Op2);
17705 }
17708 InstructionCost ScalarCost = TTI->getArithmeticInstrCost(
17709 ShuffleOrOp, OrigScalarTy, CostKind, Op1Info, Op2Info, Operands);
17710 if (auto *I = dyn_cast<Instruction>(UniqueValues[Idx]);
17711 I && (ShuffleOrOp == Instruction::FAdd ||
17712 ShuffleOrOp == Instruction::FSub)) {
17713 InstructionCost IntrinsicCost = GetFMulAddCost(E->getOperations(), I);
17714 if (IntrinsicCost.isValid())
17715 ScalarCost = IntrinsicCost;
17716 }
17717 return ScalarCost;
17718 };
17719 auto GetVectorCost = [=](InstructionCost CommonCost) {
17720 // And peephole only applies to plain 2-operand nodes.
17721 if (ShuffleOrOp == Instruction::And && It != MinBWs.end() &&
17722 !E->hasReassocScalars()) {
17723 for (unsigned I : seq<unsigned>(0, E->getNumOperands())) {
17724 ArrayRef<Value *> Ops = E->getOperand(I);
17725 if (all_of(Ops, [&](Value *Op) {
17726 auto *CI = dyn_cast<ConstantInt>(Op);
17727 return CI && CI->getValue().countr_one() >= It->second.first;
17728 }))
17729 return CommonCost;
17730 }
17731 }
17732 // Masked path ignores Op1Info/Op2Info like its codegen does; keep it
17733 // out of the operand-aware cost comparison below.
17734 if (InstructionCost MaskedCost = getMaskedDivRemCost(
17735 *TTI, SLPReVec, ShuffleOrOp, ScalarTy, VL.size(), CostKind);
17736 MaskedCost.isValid())
17737 return MaskedCost + CommonCost;
17738 unsigned OpIdx = isa<UnaryOperator>(VL0) ? 0 : 1;
17739 TTI::OperandValueInfo Op1Info = getOperandInfo(E->getOperand(0));
17740 TTI::OperandValueInfo Op2Info = getOperandInfo(E->getOperand(OpIdx));
17741 InstructionCost Cost = TTI->getArithmeticInstrCost(
17742 ShuffleOrOp, VecTy, CostKind, Op1Info, Op2Info, {}, nullptr, TLI);
17743 // N columns need N-1 vector combines; price extra columns
17744 // conservatively, skipping identity-only columns (not combined by
17745 // codegen).
17746 if (E->hasReassocScalars()) {
17747 const unsigned CombineOpcode = getReassocCombineOpcode(E->getOpcode());
17748 for (unsigned Idx : seq<unsigned>(2, E->getNumOperands())) {
17749 if (all_of(E->getOperand(Idx), [&](Value *V) {
17750 return isBinOpIdentityConstant(V, CombineOpcode);
17751 }))
17752 continue;
17753 Cost += TTI->getArithmeticInstrCost(
17754 ShuffleOrOp, VecTy, CostKind, {},
17755 getOperandInfo(E->getOperand(Idx)), {}, nullptr, TLI);
17756 }
17757 }
17758 return Cost + CommonCost;
17759 };
17760 return GetCostDiffWithPeeled(GetScalarCost, GetVectorCost);
17761 }
17762 case Instruction::GetElementPtr: {
17763 return CommonCost + GetGEPCostDiff(VL, VL0);
17764 }
17765 case Instruction::Load: {
17766 auto GetScalarCost = [&](unsigned Idx) {
17767 auto *VI = cast<LoadInst>(UniqueValues[Idx]);
17768 return TTI->getMemoryOpCost(Instruction::Load, OrigScalarTy,
17769 VI->getAlign(), VI->getPointerAddressSpace(),
17770 CostKind, TTI::OperandValueInfo(), VI);
17771 };
17772 auto *LI0 = cast<LoadInst>(VL0);
17773 auto GetVectorCost = [&](InstructionCost CommonCost) {
17774 InstructionCost VecLdCost;
17775 switch (E->State) {
17776 case TreeEntry::Vectorize:
17777 if (unsigned Factor = E->getInterleaveFactor()) {
17778 VecLdCost = TTI->getInterleavedMemoryOpCost(
17779 Instruction::Load, VecTy, Factor, {}, LI0->getAlign(),
17780 LI0->getPointerAddressSpace(), CostKind);
17781
17782 } else {
17783 VecLdCost = TTI->getMemoryOpCost(
17784 Instruction::Load, VecTy, LI0->getAlign(),
17785 LI0->getPointerAddressSpace(), CostKind, TTI::OperandValueInfo());
17786 }
17787 break;
17788 case TreeEntry::StridedVectorize: {
17789 const StridedPtrInfo &SPtrInfo = TreeEntryToStridedPtrInfoMap.at(E);
17790 FixedVectorType *StridedLoadTy = SPtrInfo.Ty;
17791 assert(StridedLoadTy && "Missing StridedPointerInfo for tree entry.");
17792 Align CommonAlignment =
17793 computeCommonAlignment<LoadInst>(UniqueValues.getArrayRef());
17794 VecLdCost = TTI->getMemIntrinsicInstrCost(
17795 MemIntrinsicCostAttributes(Intrinsic::experimental_vp_strided_load,
17796 StridedLoadTy, LI0->getPointerOperand(),
17797 /*VariableMask=*/false, CommonAlignment),
17798 CostKind);
17799 if (StridedLoadTy != VecTy)
17800 VecLdCost +=
17801 TTI->getCastInstrCost(Instruction::BitCast, VecTy, StridedLoadTy,
17802 getCastContextHint(*E), CostKind);
17803
17804 break;
17805 }
17806 case TreeEntry::CompressVectorize: {
17807 bool IsMasked;
17808 unsigned InterleaveFactor;
17809 SmallVector<int> CompressMask;
17810 VectorType *LoadVecTy;
17811 SmallVector<Value *> Scalars(VL);
17812 if (!E->ReorderIndices.empty()) {
17813 SmallVector<int> Mask(E->ReorderIndices.begin(),
17814 E->ReorderIndices.end());
17815 reorderScalars(Scalars, Mask);
17816 }
17817 SmallVector<Value *> PointerOps(Scalars.size());
17818 for (auto [I, V] : enumerate(Scalars))
17819 PointerOps[I] = cast<LoadInst>(V)->getPointerOperand();
17820 [[maybe_unused]] bool IsVectorized = isMaskedLoadCompress(
17821 Scalars, PointerOps, E->ReorderIndices, *TTI, *DL, *SE, *AC, *DT,
17822 *TLI, CostKind, [](Value *) { return true; }, IsMasked,
17823 InterleaveFactor, CompressMask, LoadVecTy);
17824 CompressEntryToData.try_emplace(E, CompressMask, LoadVecTy,
17825 InterleaveFactor, IsMasked);
17826 Align CommonAlignment = LI0->getAlign();
17827 if (InterleaveFactor) {
17828 VecLdCost = TTI->getInterleavedMemoryOpCost(
17829 Instruction::Load, LoadVecTy, InterleaveFactor, {},
17830 CommonAlignment, LI0->getPointerAddressSpace(), CostKind);
17831 } else if (IsMasked) {
17832 VecLdCost = TTI->getMemIntrinsicInstrCost(
17833 MemIntrinsicCostAttributes(Intrinsic::masked_load, LoadVecTy,
17834 CommonAlignment,
17835 LI0->getPointerAddressSpace()),
17836 CostKind);
17837 // TODO: include this cost into CommonCost.
17838 VecLdCost += getShuffleCost(*TTI, TTI::SK_PermuteSingleSrc, LoadVecTy,
17839 CostKind, CompressMask);
17840 } else {
17841 VecLdCost = TTI->getMemoryOpCost(
17842 Instruction::Load, LoadVecTy, CommonAlignment,
17843 LI0->getPointerAddressSpace(), CostKind, TTI::OperandValueInfo());
17844 // TODO: include this cost into CommonCost.
17845 VecLdCost += getShuffleCost(*TTI, TTI::SK_PermuteSingleSrc, LoadVecTy,
17846 CostKind, CompressMask);
17847 }
17848 break;
17849 }
17850 case TreeEntry::ScatterVectorize: {
17851 Align CommonAlignment =
17852 computeCommonAlignment<LoadInst>(UniqueValues.getArrayRef());
17853 VecLdCost = TTI->getMemIntrinsicInstrCost(
17854 MemIntrinsicCostAttributes(Intrinsic::masked_gather, VecTy,
17855 LI0->getPointerOperand(),
17856 /*VariableMask=*/false, CommonAlignment),
17857 CostKind);
17858 break;
17859 }
17860 case TreeEntry::BlendedLoadVectorize: {
17861 // Two masked loads (one per candidate base) blended by a select.
17862 Align CommonAlignment =
17863 computeCommonAlignment<LoadInst>(UniqueValues.getArrayRef());
17864 VecLdCost = getBlendedLoadCost(*TTI, VecTy, CommonAlignment,
17865 LI0->getPointerAddressSpace(), CostKind);
17866 break;
17867 }
17868 case TreeEntry::ExpandVectorize:
17869 case TreeEntry::CombinedVectorize:
17870 case TreeEntry::SplitVectorize:
17871 case TreeEntry::NeedToGather:
17872 llvm_unreachable("Unexpected vectorization state.");
17873 }
17874 return VecLdCost + CommonCost;
17875 };
17876
17877 InstructionCost Cost = GetCostDiff(GetScalarCost, GetVectorCost);
17878 // Masked gather and blended loads are not terminal nodes: their address
17879 // cost is estimated separately (blended loads have no per-lane address).
17880 if (E->State == TreeEntry::ScatterVectorize ||
17881 E->State == TreeEntry::BlendedLoadVectorize)
17882 return Cost;
17883
17884 // Estimate cost of GEPs since this tree node is a terminator.
17885 SmallVector<Value *> PointerOps(VL.size());
17886 for (auto [I, V] : enumerate(VL))
17887 PointerOps[I] = cast<LoadInst>(V)->getPointerOperand();
17888 return Cost + GetGEPCostDiff(PointerOps, LI0->getPointerOperand());
17889 }
17890 case Instruction::Store: {
17891 bool IsReorder = !E->ReorderIndices.empty();
17892 auto GetScalarCost = [=](unsigned Idx) {
17893 auto *VI = cast<StoreInst>(VL[Idx]);
17894 TTI::OperandValueInfo OpInfo = TTI::getOperandInfo(VI->getValueOperand());
17895 return TTI->getMemoryOpCost(Instruction::Store, OrigScalarTy,
17896 VI->getAlign(), VI->getPointerAddressSpace(),
17897 CostKind, OpInfo, VI);
17898 };
17899 auto *BaseSI =
17900 cast<StoreInst>(IsReorder ? VL[E->ReorderIndices.front()] : VL0);
17901 auto GetVectorCost = [=](InstructionCost CommonCost) {
17902 // We know that we can merge the stores. Calculate the cost.
17903 InstructionCost VecStCost;
17904 if (E->State == TreeEntry::StridedVectorize) {
17905 const StridedPtrInfo &SPtrInfo = TreeEntryToStridedPtrInfoMap.at(E);
17906 FixedVectorType *StridedStoreTy = SPtrInfo.Ty;
17907 assert(StridedStoreTy && "Missing StridedPointerInfo for tree entry.");
17908 Align CommonAlignment =
17909 computeCommonAlignment<StoreInst>(UniqueValues.getArrayRef());
17910 VecStCost = TTI->getMemIntrinsicInstrCost(
17911 MemIntrinsicCostAttributes(Intrinsic::experimental_vp_strided_store,
17912 StridedStoreTy,
17913 BaseSI->getPointerOperand(),
17914 /*VariableMask=*/false, CommonAlignment),
17915 CostKind);
17916 if (StridedStoreTy != VecTy)
17917 VecStCost +=
17918 TTI->getCastInstrCost(Instruction::BitCast, VecTy, StridedStoreTy,
17919 getCastContextHint(*E), CostKind);
17920 } else if (E->State == TreeEntry::ExpandVectorize) {
17921 const StridedPtrInfo &SPtrInfo = TreeEntryToStridedPtrInfoMap.at(E);
17922 FixedVectorType *MaskedStoreTy = SPtrInfo.Ty;
17923 assert(MaskedStoreTy && "Missing StridedPointerInfo for tree entry.");
17924 Align CommonAlignment =
17925 computeCommonAlignment<StoreInst>(UniqueValues.getArrayRef());
17926 // Masked store: the values are expanded into the widened vector and
17927 // stored with a constant mask.
17928 VecStCost = TTI->getMemIntrinsicInstrCost(
17929 MemIntrinsicCostAttributes(Intrinsic::masked_store, MaskedStoreTy,
17930 CommonAlignment,
17931 BaseSI->getPointerAddressSpace()),
17932 CostKind);
17933 } else {
17934 assert(E->State == TreeEntry::Vectorize &&
17935 "Expected either strided, consecutive, or expanded stores.");
17936 if (unsigned Factor = E->getInterleaveFactor()) {
17937 assert(E->ReuseShuffleIndices.empty() && !E->ReorderIndices.empty() &&
17938 "No reused shuffles expected");
17939 CommonCost = 0;
17940 VecStCost = TTI->getInterleavedMemoryOpCost(
17941 Instruction::Store, VecTy, Factor, {}, BaseSI->getAlign(),
17942 BaseSI->getPointerAddressSpace(), CostKind);
17943 } else {
17944 TTI::OperandValueInfo OpInfo = getOperandInfo(E->getOperand(0));
17945 VecStCost = TTI->getMemoryOpCost(
17946 Instruction::Store, VecTy, BaseSI->getAlign(),
17947 BaseSI->getPointerAddressSpace(), CostKind, OpInfo);
17948 }
17949 }
17950 return VecStCost + CommonCost;
17951 };
17952 SmallVector<Value *> PointerOps(VL.size());
17953 for (auto [I, V] : enumerate(VL)) {
17954 unsigned Idx = IsReorder ? E->ReorderIndices[I] : I;
17955 PointerOps[Idx] = cast<StoreInst>(V)->getPointerOperand();
17956 }
17957
17958 return GetCostDiff(GetScalarCost, GetVectorCost) +
17959 GetGEPCostDiff(PointerOps, BaseSI->getPointerOperand());
17960 }
17961 case Instruction::Call: {
17962 auto GetScalarCost = [&](unsigned Idx) {
17963 // A copyable lane has no scalar call of its own; its real cost is
17964 // accounted for wherever it is otherwise computed.
17965 if (isa<PoisonValue>(UniqueValues[Idx]) ||
17966 E->isCopyableElement(UniqueValues[Idx]))
17968 auto *CI = cast<CallInst>(UniqueValues[Idx]);
17970 if (ID != Intrinsic::not_intrinsic) {
17971 IntrinsicCostAttributes CostAttrs(ID, *CI, 1);
17972 return TTI->getIntrinsicInstrCost(CostAttrs, CostKind);
17973 }
17974 return TTI->getCallInstrCost(CI->getCalledFunction(),
17976 CI->getFunctionType()->params(), CostKind);
17977 };
17978 auto GetVectorCost = [=](InstructionCost CommonCost) {
17979 auto *CI = cast<CallInst>(VL0);
17982 CI, ID, getNumElements(VecTy),
17983 It != MinBWs.end() ? It->second.first : 0, TTI);
17984 auto VecCallCosts =
17985 getVectorCallCosts(CI, VecTy, TTI, TLI, ArgTys, CostKind);
17986 return std::min(VecCallCosts.first, VecCallCosts.second) + CommonCost;
17987 };
17988 return GetCostDiff(GetScalarCost, GetVectorCost);
17989 }
17990 case Instruction::ShuffleVector: {
17991 if (!SLPReVec || E->isAltShuffle())
17992 assert(E->isAltShuffle() &&
17993 ((Instruction::isBinaryOp(E->getOpcode()) &&
17994 Instruction::isBinaryOp(E->getAltOpcode())) ||
17995 (Instruction::isCast(E->getOpcode()) &&
17996 Instruction::isCast(E->getAltOpcode())) ||
17997 (isa<CmpInst>(VL0) && isa<CmpInst>(E->getAltOp()))) &&
17998 "Invalid Shuffle Vector Operand");
17999 // Try to find the previous shuffle node with the same operands and same
18000 // main/alternate ops.
18001 auto TryFindNodeWithEqualOperands = [=]() {
18002 for (const std::unique_ptr<TreeEntry> &TE : VectorizableTree) {
18003 if (TE.get() == E)
18004 break;
18005 if (TE->hasState() && TE->isAltShuffle() &&
18006 ((TE->getOpcode() == E->getOpcode() &&
18007 TE->getAltOpcode() == E->getAltOpcode()) ||
18008 (TE->getOpcode() == E->getAltOpcode() &&
18009 TE->getAltOpcode() == E->getOpcode())) &&
18010 TE->hasEqualOperands(*E))
18011 return true;
18012 }
18013 return false;
18014 };
18015 auto GetScalarCost = [&](unsigned Idx) {
18016 if (isa<PoisonValue>(UniqueValues[Idx]))
18018
18019 auto *VI = cast<Instruction>(UniqueValues[Idx]);
18020 assert(E->getMatchingMainOpOrAltOp(VI) &&
18021 "Unexpected main/alternate opcode");
18022 (void)E;
18023 return TTI->getInstructionCost(VI, CostKind);
18024 };
18025 // Need to clear CommonCost since the final shuffle cost is included into
18026 // vector cost.
18027 auto GetVectorCost = [&, &TTIRef = *TTI](InstructionCost) {
18028 // VecCost is equal to sum of the cost of creating 2 vectors
18029 // and the cost of creating shuffle.
18030 InstructionCost VecCost = 0;
18031 if (TryFindNodeWithEqualOperands()) {
18032 LLVM_DEBUG({
18033 dbgs() << "SLP: diamond match for alternate node found.\n";
18034 E->dump();
18035 });
18036 // No need to add new vector costs here since we're going to reuse
18037 // same main/alternate vector ops, just do different shuffling.
18038 } else if (Instruction::isBinaryOp(E->getOpcode())) {
18039 // Peeled alternate chains fold the operand columns into one pure
18040 // main-opcode chain and one pure alt-opcode chain, followed by a
18041 // single lane-select shuffle; a plain alternate node is a single
18042 // combine. Each combine is priced with the properties of the column
18043 // it folds in; the other operand is the running fold, which stays
18044 // constant while every folded column is constant (such combines
18045 // constant-fold away in codegen) and stays uniform while every
18046 // folded column is uniform.
18047 auto ChainCost = [&](unsigned Opcode) {
18049 TTI::OperandValueInfo RunningInfo = getOperandInfo(E->getOperand(0));
18050 for (unsigned Idx : seq<unsigned>(1, E->getNumOperands())) {
18051 TTI::OperandValueInfo ColInfo = getOperandInfo(E->getOperand(Idx));
18052 if (!RunningInfo.isConstant() || !ColInfo.isConstant())
18053 Cost += TTIRef.getArithmeticInstrCost(Opcode, VecTy, CostKind,
18054 RunningInfo, ColInfo, {},
18055 nullptr, TLI);
18057 if (RunningInfo.isConstant() && ColInfo.isConstant())
18058 Kind = RunningInfo.Kind == TTI::OK_UniformConstantValue &&
18062 else if (RunningInfo.isUniform() && ColInfo.isUniform())
18064 RunningInfo = {Kind, TTI::OP_None};
18065 }
18066 return Cost;
18067 };
18068 VecCost = ChainCost(E->getOpcode()) + ChainCost(E->getAltOpcode());
18069 } else if (auto *CI0 = dyn_cast<CmpInst>(VL0)) {
18070 auto *MaskTy = getWidenedType(Builder.getInt1Ty(), VL.size());
18071 VecCost = TTIRef.getCmpSelInstrCost(
18072 E->getOpcode(), VecTy, MaskTy, CI0->getPredicate(), CostKind,
18073 {TTI::OK_AnyValue, TTI::OP_None}, {TTI::OK_AnyValue, TTI::OP_None},
18074 VL0);
18075 VecCost += TTIRef.getCmpSelInstrCost(
18076 E->getOpcode(), VecTy, MaskTy,
18077 cast<CmpInst>(E->getAltOp())->getPredicate(), CostKind,
18078 {TTI::OK_AnyValue, TTI::OP_None}, {TTI::OK_AnyValue, TTI::OP_None},
18079 E->getAltOp());
18080 } else {
18081 Type *SrcSclTy = E->getMainOp()->getOperand(0)->getType();
18082 auto *SrcTy = getWidenedType(SrcSclTy, VL.size());
18083 if (SrcSclTy->isIntegerTy() && ScalarTy->isIntegerTy()) {
18084 auto SrcIt = MinBWs.find(getOperandEntry(E, 0));
18085 unsigned BWSz = DL->getTypeSizeInBits(ScalarTy);
18086 unsigned SrcBWSz =
18087 DL->getTypeSizeInBits(E->getMainOp()->getOperand(0)->getType());
18088 if (SrcIt != MinBWs.end()) {
18089 SrcBWSz = SrcIt->second.first;
18090 SrcSclTy = IntegerType::get(SrcSclTy->getContext(), SrcBWSz);
18091 SrcTy = getWidenedType(SrcSclTy, VL.size());
18092 }
18093 if (BWSz <= SrcBWSz) {
18094 if (BWSz < SrcBWSz)
18095 VecCost =
18096 TTIRef.getCastInstrCost(Instruction::Trunc, VecTy, SrcTy,
18097 TTI::CastContextHint::None, CostKind);
18098 LLVM_DEBUG({
18099 dbgs()
18100 << "SLP: alternate extension, which should be truncated.\n";
18101 E->dump();
18102 });
18103 return VecCost;
18104 }
18105 }
18106 VecCost = TTIRef.getCastInstrCost(E->getOpcode(), VecTy, SrcTy,
18107 TTI::CastContextHint::None, CostKind);
18108 VecCost +=
18109 TTIRef.getCastInstrCost(E->getAltOpcode(), VecTy, SrcTy,
18110 TTI::CastContextHint::None, CostKind);
18111 }
18112 SmallVector<int> Mask;
18113 E->buildAltOpShuffleMask(
18114 [&](Instruction *I) {
18115 assert(E->getMatchingMainOpOrAltOp(I) &&
18116 "Unexpected main/alternate opcode");
18117 return isAlternateInstruction(I, E->getMainOp(), E->getAltOp(),
18118 *TLI);
18119 },
18120 Mask);
18122 cast<VectorType>(FinalVecTy), CostKind, Mask);
18123 // Patterns like [fadd,fsub] can be combined into a single instruction
18124 // in x86. Reordering them into [fsub,fadd] blocks this pattern. So we
18125 // need to take into account their order when looking for the most used
18126 // order. Linearized chains emit no alternate-ops pattern.
18127 if (E->hasReassocScalars())
18128 return VecCost;
18129 unsigned Opcode0 = E->getOpcode();
18130 unsigned Opcode1 = E->getAltOpcode();
18131 SmallBitVector OpcodeMask(
18132 getAltInstrMask(E->Scalars, ScalarTy, Opcode0, Opcode1));
18133 // If this pattern is supported by the target then we consider the
18134 // order.
18135 if (TTIRef.isLegalAltInstr(cast<VectorType>(VecTy), Opcode0, Opcode1,
18136 OpcodeMask)) {
18137 InstructionCost AltVecCost = TTIRef.getAltInstrCost(
18138 cast<VectorType>(VecTy), Opcode0, Opcode1, OpcodeMask, CostKind);
18139 return AltVecCost < VecCost ? AltVecCost : VecCost;
18140 }
18141 // TODO: Check the reverse order too.
18142 return VecCost;
18143 };
18144 if (SLPReVec && !E->isAltShuffle())
18145 return GetCostDiff(
18146 GetScalarCost, [&](InstructionCost) -> InstructionCost {
18147 // If a group uses mask in order, the shufflevector can be
18148 // eliminated by instcombine. Then the cost is 0.
18150 "Not supported shufflevector usage.");
18151 auto *SV = cast<ShuffleVectorInst>(VL.front());
18152 unsigned SVNumElements =
18153 cast<FixedVectorType>(SV->getOperand(0)->getType())
18154 ->getNumElements();
18155 unsigned GroupSize = SVNumElements / SV->getShuffleMask().size();
18156 for (size_t I = 0, End = VL.size(); I != End; I += GroupSize) {
18157 ArrayRef<Value *> Group = VL.slice(I, GroupSize);
18158 int NextIndex = 0;
18159 if (!all_of(Group, [&](Value *V) {
18161 "Not supported shufflevector usage.");
18162 auto *SV = cast<ShuffleVectorInst>(V);
18163 int Index;
18164 [[maybe_unused]] bool IsExtractSubvectorMask =
18165 SV->isExtractSubvectorMask(Index);
18166 assert(IsExtractSubvectorMask &&
18167 "Not supported shufflevector usage.");
18168 if (NextIndex != Index)
18169 return false;
18170 NextIndex += SV->getShuffleMask().size();
18171 return true;
18172 }))
18173 return getShuffleCost(*TTI,
18175 cast<VectorType>(VecTy), CostKind,
18176 calculateShufflevectorMask(E->Scalars));
18177 }
18178 return TTI::TCC_Free;
18179 });
18180 return GetCostDiffWithPeeled(GetScalarCost, GetVectorCost);
18181 }
18182 case Instruction::Freeze:
18183 return CommonCost;
18184 default:
18185 llvm_unreachable("Unknown instruction");
18186 }
18187}
18188
18189bool BoUpSLP::isFullyVectorizableTinyTree(bool ForReduction) const {
18190 LLVM_DEBUG(dbgs() << "SLP: Check whether the tree with height "
18191 << VectorizableTree.size() << " is fully vectorizable .\n");
18192
18193 auto &&AreVectorizableGathers = [this](const TreeEntry *TE, unsigned Limit) {
18194 SmallVector<int> Mask;
18195 return TE->isGather() &&
18196 !any_of(TE->Scalars,
18197 [this](Value *V) { return EphValues.contains(V); }) &&
18198 (allConstant(TE->Scalars) || isSplat(TE->Scalars) ||
18199 TE->Scalars.size() < Limit ||
18200 // Nodes with copyable lanes may mix in non-extract lanes, which
18201 // are not representable as a shuffle of the source vector.
18202 (((TE->hasState() &&
18203 TE->getOpcode() == Instruction::ExtractElement &&
18204 !TE->hasCopyableElements()) ||
18206 isFixedVectorShuffle(TE->Scalars, Mask, AC)) ||
18207 (TE->hasState() && TE->getOpcode() == Instruction::Load &&
18208 !TE->isAltShuffle()) ||
18209 any_of(TE->Scalars, IsaPred<LoadInst>));
18210 };
18211
18212 // We only handle trees of heights 1 and 2.
18213 if (VectorizableTree.size() == 1 &&
18214 (VectorizableTree[0]->State == TreeEntry::Vectorize ||
18215 VectorizableTree[0]->State == TreeEntry::StridedVectorize ||
18216 VectorizableTree[0]->State == TreeEntry::ExpandVectorize ||
18217 VectorizableTree[0]->State == TreeEntry::CompressVectorize ||
18218 VectorizableTree[0]->State == TreeEntry::BlendedLoadVectorize ||
18219 (ForReduction &&
18220 AreVectorizableGathers(VectorizableTree[0].get(),
18221 VectorizableTree[0]->Scalars.size()) &&
18222 VectorizableTree[0]->getVectorFactor() > 2)))
18223 return true;
18224
18225 if (VectorizableTree.size() != 2)
18226 return false;
18227
18228 // Handle splat and all-constants stores. Also try to vectorize tiny trees
18229 // with the second gather nodes if they have less scalar operands rather than
18230 // the initial tree element (may be profitable to shuffle the second gather)
18231 // or they are extractelements, which form shuffle.
18232 if (VectorizableTree[0]->State == TreeEntry::Vectorize &&
18233 AreVectorizableGathers(VectorizableTree[1].get(),
18234 VectorizableTree[0]->Scalars.size()))
18235 return true;
18236
18237 // Gathering cost would be too much for tiny trees.
18238 if (VectorizableTree[0]->isGather() ||
18239 (VectorizableTree[1]->isGather() &&
18240 VectorizableTree[0]->State != TreeEntry::ScatterVectorize &&
18241 VectorizableTree[0]->State != TreeEntry::StridedVectorize &&
18242 VectorizableTree[0]->State != TreeEntry::ExpandVectorize &&
18243 VectorizableTree[0]->State != TreeEntry::CompressVectorize &&
18244 VectorizableTree[0]->State != TreeEntry::BlendedLoadVectorize))
18245 return false;
18246
18247 return true;
18248}
18249
18250bool BoUpSLP::isTreeTinyAndNotFullyVectorizable(bool ForReduction) const {
18251 if (!DebugCounter::shouldExecute(VectorizedGraphs))
18252 return true;
18253
18254 // If we are revectorizing reduction, it may result in same reduction pattern
18255 // with shuffles as leaves of the reduction. Prevent SLP from revectorizing
18256 // that shuffle pattern.
18257 if (SLPReVec && ForReduction && VectorizableTree.size() == 3 &&
18258 VectorizableTree[0]->State == TreeEntry::Vectorize &&
18259 VectorizableTree[0]->getOpcode() == Instruction::ShuffleVector &&
18260 VectorizableTree[1]->isGather() &&
18261 isSplat(VectorizableTree[1]->Scalars) &&
18262 VectorizableTree[2]->isGather() &&
18263 allConstant(VectorizableTree[2]->Scalars)) {
18264 LLVM_DEBUG(dbgs() << "SLP: Rejecting reduction tree with 3 nodes(shuffle "
18265 "as root and remaining are gather nodes).\n");
18266 return true;
18267 }
18268
18269 // Graph is empty - do nothing.
18270 if (VectorizableTree.empty()) {
18271 assert(ExternalUses.empty() && "We shouldn't have any external users");
18272
18273 return true;
18274 }
18275
18276 // FIXME: support buildvector of the gather nodes with struct types.
18277 if (any_of(VectorizableTree, [&](const std::unique_ptr<TreeEntry> &TE) {
18278 return TE->isGather() &&
18279 isa<StructType>(TE->Scalars.front()->getType());
18280 })) {
18281 LLVM_DEBUG(
18282 dbgs() << "SLP: rejecting tree with buildvector struct values of size "
18283 << VectorizableTree.size() << ".\n");
18284 return true;
18285 }
18286
18287 // Cache values from the root node and the cost-threshold options to avoid
18288 // re-querying them inside hot predicates below.
18289 const unsigned TreeSize = VectorizableTree.size();
18290 const TreeEntry &Front = getRootNode();
18291 const bool FrontIsGather = Front.isGather();
18292 const bool FrontHasState = Front.hasState();
18293 const unsigned FrontOpcode = FrontHasState ? Front.getOpcode() : 0u;
18294 const bool ThresholdSet = SLPCostThreshold.getNumOccurrences() > 0;
18295 const bool ThresholdNonNegative = SLPCostThreshold >= 0;
18296
18297 constexpr unsigned Limit = 4;
18298 constexpr unsigned LargeTree = 20;
18299 constexpr unsigned LimitTreeSize = 36;
18300
18301 // The remaining size-1/size-<=MinTreeSize early bail-outs only apply to
18302 // non-reduction trees; group them under a single guard to avoid 3 separate
18303 // !ForReduction short-circuits when reducing.
18304 if (!ForReduction) {
18305 // Single gather node: bail out for ExtractElement or any node containing a
18306 // real Instruction scalar.
18307 if (TreeSize == 1 && FrontIsGather) {
18308 if (FrontHasState && FrontOpcode == Instruction::ExtractElement)
18309 return true;
18310 if (any_of(Front.Scalars, IsaPred<Instruction>))
18311 return true;
18312 }
18313 if (TreeSize <= MinTreeSize &&
18314 all_of(VectorizableTree, [](const std::unique_ptr<TreeEntry> &TE) {
18315 return TE->isGather() || TE->State == TreeEntry::SplitVectorize;
18316 }))
18317 return true;
18318 if (TreeSize == 1 && SLPCostThreshold < 0 && FrontHasState &&
18319 FrontOpcode == Instruction::ExtractElement &&
18320 (Front.getVectorFactor() == 2 ||
18321 all_of(
18322 Front.Scalars,
18323 [&](Value *V) {
18324 auto *I = dyn_cast<Instruction>(V);
18325 return !I || !areAllUsersVectorized(I, UserIgnoreList);
18326 })))
18327 return true;
18328 }
18329 // No need to vectorize inserts of gathered values.
18330 if (TreeSize == 2 && isa<InsertElementInst>(Front.Scalars[0]) &&
18331 VectorizableTree[1]->isGather() &&
18332 (VectorizableTree[1]->getVectorFactor() <= 2 ||
18333 !(isSplat(VectorizableTree[1]->Scalars) ||
18334 allConstant(VectorizableTree[1]->Scalars))))
18335 return true;
18336
18337 // The tree with only 3 nodes, where 2 last are gathers/buildvectors, not
18338 // profitable for vectorization.
18339 if (TreeSize == 3 && SLPCostThreshold == 0 &&
18340 (!ForReduction || Front.getVectorFactor() <= 2) &&
18341 all_of(ArrayRef(VectorizableTree).drop_front(),
18342 [&](const std::unique_ptr<TreeEntry> &TE) {
18343 return TE->isGather() && TE->getVectorFactor() <= Limit &&
18344 !all_of(
18345 TE->Scalars,
18347 }))
18348 return true;
18349
18350 // All remaining bail-out heuristics require !ForReduction. Group them under
18351 // a single guard so reduction trees skip them with one branch instead of one
18352 // per check.
18353 if (!ForReduction) {
18354 // The single vectorized node, fed by the buildvectors, only repacks the
18355 // scalars, the gathers and the extracts are paid for the one vector
18356 // instruction. The vector call replaces the several expensive scalar ones,
18357 // while the store merges the lanes instead of extracting them back.
18358 if (TreeSize > 1 && ThresholdNonNegative &&
18359 (!FrontHasState || (FrontOpcode != Instruction::Call &&
18360 FrontOpcode != Instruction::Store)) &&
18361 count_if(VectorizableTree,
18362 [](const std::unique_ptr<TreeEntry> &TE) {
18363 return TE->State == TreeEntry::Vectorize;
18364 }) == 1 &&
18365 all_of(VectorizableTree, [](const std::unique_ptr<TreeEntry> &TE) {
18366 return TE->State == TreeEntry::Vectorize ||
18367 (TE->isGather() && !isSplat(TE->Scalars) &&
18368 !all_of(TE->Scalars,
18370 }))
18371 return true;
18372
18373 // If the graph includes only PHI nodes and gathers, it is defnitely not
18374 // profitable for the vectorization, we can skip it, if the cost threshold
18375 // is default. The cost of vectorized PHI nodes is almost always 0 + the
18376 // cost of gathers/buildvectors.
18377 if (!ThresholdSet &&
18378 all_of(VectorizableTree, [&](const std::unique_ptr<TreeEntry> &TE) {
18379 const bool IsGather = TE->isGather();
18380 const bool HasState = TE->hasState();
18381 const unsigned Op = HasState ? TE->getOpcode() : 0u;
18382 if (IsGather && (!HasState || Op != Instruction::ExtractElement) &&
18383 static_cast<unsigned>(
18384 count_if(TE->Scalars, IsaPred<ExtractElementInst>)) <= Limit)
18385 return true;
18386 return HasState && Op == Instruction::PHI;
18387 }))
18388 return true;
18389
18390 // Do not vectorize small tree of phis only, if all vector phis are also
18391 // gathered.
18392 if (ThresholdSet && TreeSize <= Limit) {
18393 bool HasVectorPhi = false;
18394 auto Compatible = [&](const std::unique_ptr<TreeEntry> &TE) {
18395 const bool IsGather = TE->isGather();
18396 const bool HasState = TE->hasState();
18397 const unsigned Op = HasState ? TE->getOpcode() : 0u;
18398 if (IsGather && (!HasState || Op != Instruction::ExtractElement) &&
18399 static_cast<unsigned>(
18400 count_if(TE->Scalars, IsaPred<ExtractElementInst>)) <= Limit)
18401 return true;
18402 if (!HasState)
18403 return false;
18404 if (Op == Instruction::InsertElement)
18405 return true;
18406 if (Op != Instruction::PHI)
18407 return false;
18408 if (TE->State == TreeEntry::Vectorize)
18409 HasVectorPhi = true;
18410 return all_of(TE->Scalars, [&](Value *V) {
18411 return isa<PoisonValue>(V) || MustGather.contains(V);
18412 });
18413 };
18414 if (all_of(VectorizableTree, Compatible) && HasVectorPhi)
18415 return true;
18416 }
18417
18418 // PHI nodes only and gathers cannot be vectorized, skip.
18419 if (ThresholdNonNegative) {
18420 const bool IsLargeTree = TreeSize >= LargeTree;
18421 bool HasSingleLoad = false;
18422 if (all_of(VectorizableTree, [&](const std::unique_ptr<TreeEntry> &TE) {
18423 const bool IsGather = TE->isGather();
18424 const bool HasState = TE->hasState();
18425 const unsigned Op = HasState ? TE->getOpcode() : 0u;
18426 // HasSingleLoad/PrevLoad are only consulted in the
18427 // IsLargeTree branch; skip the bookkeeping otherwise.
18428 if (IsLargeTree) {
18429 const bool PrevLoad = HasSingleLoad;
18430 HasSingleLoad |=
18431 HasState && !IsGather &&
18432 (Op == Instruction::Load || TE->hasCopyableElements()) &&
18433 (TE->getVectorFactor() > 2 || TE->ReorderIndices.empty());
18434 if (HasState) {
18435 if (Op == Instruction::PHI)
18436 return true;
18437 if (TE->getVectorFactor() <= Limit &&
18438 (Op == Instruction::Store ||
18439 (Op == Instruction::Load && !PrevLoad)))
18440 return true;
18441 }
18442 } else if (HasState && Op == Instruction::PHI) {
18443 return true;
18444 }
18445 return IsGather && (!HasState || Op != Instruction::ExtractElement);
18446 }))
18447 return true;
18448
18449 // Single non-phi vector node - skip the tree.
18450 if (TreeSize >= 5 && Front.getVectorFactor() <= 2 &&
18451 Front.Scalars.front()->getType()->isIntegerTy()) {
18452 bool VectorNodeFound = false;
18453 bool AnyNonConst = false;
18454 if (all_of(VectorizableTree,
18455 [&](const std::unique_ptr<TreeEntry> &TE) {
18456 if (TE->State == TreeEntry::Vectorize && TE->hasState()) {
18457 const unsigned Op = TE->getOpcode();
18458 if (Op == Instruction::PHI ||
18459 !TE->ReorderIndices.empty())
18460 return true;
18461 if (VectorNodeFound)
18462 return false;
18463 VectorNodeFound = true;
18464 return true;
18465 }
18466 // Once AnyNonConst is true, skip the O(n) allConstant
18467 // walk for subsequent entries.
18468 if (!AnyNonConst)
18469 AnyNonConst = !allConstant(TE->Scalars);
18470 return TE->isGather() ||
18471 TE->State == TreeEntry::SplitVectorize;
18472 }) &&
18473 AnyNonConst)
18474 return true;
18475 }
18476 }
18477
18478 // Common predicate for "phis, buildvectors, split nodes and small nodes
18479 // with reuses" used by the two checks below. Cheap checks are evaluated
18480 // before expensive Scalars walks.
18481 auto IsBenignNode = [&](const TreeEntry &TE) {
18482 if (TE.State == TreeEntry::SplitVectorize)
18483 return true;
18484 const bool IsGather = TE.isGather();
18485 const bool HasState = TE.hasState();
18486 if (HasState) {
18487 const unsigned Op = TE.getOpcode();
18488 if (Op == Instruction::PHI)
18489 return true;
18490 const unsigned ScalarsSize = TE.Scalars.size();
18491 if (TE.Idx == 0 && ScalarsSize == 2 && Op == Instruction::ICmp &&
18492 TreeSize > LimitTreeSize)
18493 return true;
18494 if (ScalarsSize == 2 &&
18495 (!TE.ReuseShuffleIndices.empty() || !TE.ReorderIndices.empty() ||
18496 TE.isAltShuffle()))
18497 return true;
18498 if (TE.hasCopyableElements() &&
18499 static_cast<unsigned>(count_if(
18500 TE.Scalars, IsaPred<PHINode, Constant>)) >= ScalarsSize / 2)
18501 return true;
18502 }
18503 return IsGather && none_of(TE.Scalars, IsaPred<ExtractElementInst>);
18504 };
18505
18506 // If the tree contains only phis, buildvectors, split nodes and
18507 // small nodes with reuses, we can skip it.
18508 if (!ThresholdSet) {
18509 SmallVector<const TreeEntry *> StoreLoadNodes;
18510 unsigned NumGathers = 0;
18511 if (all_of(VectorizableTree,
18512 [&](const std::unique_ptr<TreeEntry> &TE) {
18513 const bool IsGather = TE->isGather();
18514 if (!IsGather && TE->hasState()) {
18515 const unsigned Op = TE->getOpcode();
18516 if (Op == Instruction::Load || Op == Instruction::Store) {
18517 StoreLoadNodes.push_back(TE.get());
18518 return true;
18519 }
18520 }
18521 if (IsGather)
18522 ++NumGathers;
18523 return IsBenignNode(*TE);
18524 }) &&
18525 (StoreLoadNodes.empty() ||
18526 (TreeSize > LimitTreeSize * StoreLoadNodes.size() &&
18527 (NumGathers > 0 ||
18528 none_of(StoreLoadNodes, [&](const TreeEntry *TE) {
18529 return TE->getOpcode() == Instruction::Store ||
18530 all_of(TE->Scalars, [&](Value *V) {
18531 return !isa<LoadInst>(V) ||
18532 areAllUsersVectorized(cast<Instruction>(V));
18533 });
18534 })))))
18535 return true;
18536 }
18537
18538 // If the tree contains only phis, buildvectors, split nodes and
18539 // small nodes with reuses, we can skip it.
18540 if (ThresholdNonNegative && TreeSize > LimitTreeSize) {
18541 const TreeEntry *VectorNode = nullptr;
18542 if (all_of(VectorizableTree, [&](const std::unique_ptr<TreeEntry> &TE) {
18543 if (!TE->isGather() && TE->hasState() &&
18544 TE->State != TreeEntry::SplitVectorize &&
18545 TE->getOpcode() != Instruction::PHI) {
18546 if (VectorNode)
18547 return false;
18548 VectorNode = TE.get();
18549 return true;
18550 }
18551 return IsBenignNode(*TE);
18552 }))
18553 return true;
18554 }
18555
18556 // If the tree contains only buildvector, 2 non-buildvectors (with root
18557 // user tree node) and other buildvectors, we can skip it.
18558 if (ThresholdSet && TreeSize >= Limit &&
18559 Front.State == TreeEntry::SplitVectorize &&
18560 count_if(ArrayRef(VectorizableTree).drop_front(),
18561 [](const std::unique_ptr<TreeEntry> &TE) {
18562 return !TE->isGather() && TE->UserTreeIndex.UserTE &&
18563 TE->UserTreeIndex.UserTE->Idx == 0;
18564 }) == 2)
18565 return true;
18566
18567 // If the tree contains only vectorization of the phi node from the
18568 // buildvector - skip it.
18569 if (ThresholdSet && TreeSize > 2 && Front.State == TreeEntry::Vectorize &&
18570 FrontOpcode == Instruction::InsertElement &&
18571 VectorizableTree[1]->State == TreeEntry::Vectorize &&
18572 VectorizableTree[1]->getOpcode() == Instruction::PHI &&
18573 all_of(ArrayRef(VectorizableTree).drop_front(2),
18574 [](const std::unique_ptr<TreeEntry> &TE) {
18575 return TE->isGather();
18576 }))
18577 return true;
18578 }
18579
18580 // We can vectorize the tree if its size is greater than or equal to the
18581 // minimum size specified by the MinTreeSize command line option.
18582 if (TreeSize >= MinTreeSize)
18583 return false;
18584
18585 // If we have a tiny tree (a tree whose size is less than MinTreeSize), we
18586 // can vectorize it if we can prove it fully vectorizable.
18587 if (isFullyVectorizableTinyTree(ForReduction))
18588 return false;
18589
18590 // Check if any of the gather node forms an insertelement buildvector
18591 // somewhere. TreeSize >= 1 is guaranteed, so the multi-node case reduces to
18592 // a simple TreeSize > 1 short-circuit.
18593 // A gather with copyable lanes is not a real instruction node; do not let
18594 // its state qualify it as a buildvector-forming node.
18595 const bool IsAllowedSingleBVNode =
18596 TreeSize > 1 ||
18597 (FrontHasState && !Front.isAltShuffle() && !Front.hasCopyableElements() &&
18598 FrontOpcode != Instruction::PHI &&
18599 FrontOpcode != Instruction::GetElementPtr &&
18600 allSameBlock(Front.Scalars));
18601 if (any_of(VectorizableTree, [&](const std::unique_ptr<TreeEntry> &TE) {
18602 return TE->isGather() && all_of(TE->Scalars, [&](Value *V) {
18603 return isa<ExtractElementInst, Constant>(V) ||
18604 (IsAllowedSingleBVNode &&
18605 !V->hasNUsesOrMore(UsesLimit) &&
18606 any_of(V->users(), IsaPred<InsertElementInst>));
18607 });
18608 }))
18609 return false;
18610
18611 const TreeEntry &Back = *VectorizableTree.back();
18612 if (Back.isGather() && Back.hasState() && Back.isAltShuffle()) {
18613 const unsigned BackVF = Back.getVectorFactor();
18614 if (BackVF > 2 && allSameBlock(Back.Scalars) &&
18615 !Back.Scalars.front()->getType()->isVectorTy() &&
18616 TTI->getScalarizationOverhead(
18618 getWidenedType(Back.Scalars.front()->getType(), BackVF)),
18619 APInt::getAllOnes(BackVF),
18620 /*Insert=*/true, /*Extract=*/false, CostKind) > -SLPCostThreshold)
18621 return false;
18622 }
18623
18624 // Otherwise, we can't vectorize the tree. It is both tiny and not fully
18625 // vectorizable.
18626 return true;
18627}
18628
18631 constexpr unsigned SmallTree = 3;
18632 if (getRootNode().isNonPowOf2Vec() &&
18633 getCanonicalGraphSize() <= SmallTree &&
18634 count_if(ArrayRef(VectorizableTree).drop_front(getCanonicalGraphSize()),
18635 [](const std::unique_ptr<TreeEntry> &TE) {
18636 return TE->isGather() && TE->hasState() &&
18637 TE->getOpcode() == Instruction::Load &&
18638 !allSameBlock(TE->Scalars);
18639 }) == 1)
18640 return true;
18641 return false;
18642 }
18643 bool Res = false;
18644 for (unsigned Idx : seq<unsigned>(getTreeSize())) {
18645 TreeEntry &E = *VectorizableTree[Idx];
18646 if (E.State == TreeEntry::SplitVectorize)
18647 return false;
18648 if (!E.isGather())
18649 continue;
18650 if ((E.hasState() && E.getOpcode() != Instruction::Load) ||
18651 (!E.hasState() &&
18653 (isa<ExtractElementInst>(E.Scalars.front()) &&
18654 getSameOpcode(ArrayRef(E.Scalars).drop_front(), *TLI).valid()))
18655 return false;
18656 if (isSplat(E.Scalars) || allConstant(E.Scalars))
18657 continue;
18658 Res = true;
18659 }
18660 return Res;
18661}
18662
18664 // Walk the vectorizable tree from the root towards its leaves, tracking
18665 // which vectorized operand values would be live across each tree edge
18666 // (i.e. between the last instruction of an operand entry and the last
18667 // instruction of its user entry). When the live range crosses a call
18668 // instruction that is not part of the vectorized tree, query TTI for the
18669 // cost of keeping the value live across it (for example, if spills and
18670 // fills are required).
18671
18672 const TreeEntry *Root = &getRootNode();
18673 if (Root->isGather())
18674 return 0;
18675
18676 InstructionCost Cost = 0;
18678 EntriesToOperands;
18679 SmallDenseMap<const TreeEntry *, Instruction *> EntriesToLastInstruction;
18680 SmallPtrSet<const Instruction *, 8> LastInstructions;
18681 SmallPtrSet<const TreeEntry *, 8> ScalarOrPseudoEntries;
18682 for (const auto &TEPtr : VectorizableTree) {
18683 if (TEPtr->CombinedOp == TreeEntry::ReducedBitcast ||
18684 TEPtr->CombinedOp == TreeEntry::ReducedBitcastBSwap ||
18685 TEPtr->CombinedOp == TreeEntry::ReducedBitcastLoads ||
18686 TEPtr->CombinedOp == TreeEntry::ReducedBitcastBSwapLoads ||
18687 TEPtr->CombinedOp == TreeEntry::ReducedCmpBitcast) {
18688 ScalarOrPseudoEntries.insert(TEPtr.get());
18689 continue;
18690 }
18691 if (!TEPtr->isGather()) {
18692 Instruction *LastInst = &getLastInstructionInBundle(TEPtr.get());
18693 EntriesToLastInstruction.try_emplace(TEPtr.get(), LastInst);
18694 LastInstructions.insert(LastInst);
18695 }
18696 if (TEPtr->UserTreeIndex)
18697 EntriesToOperands[TEPtr->UserTreeIndex.UserTE].push_back(TEPtr.get());
18698 }
18699
18700 // Cache NoCallIntrinsicOrDoesNotReturn results - the same intrinsic call may
18701 // be queried many times during the spill cost scan, and each computation
18702 // involves two potentially expensive TTI virtual calls.
18703 SmallDenseMap<const IntrinsicInst *, bool> NoCallIntrinsicCache;
18704 auto NoCallIntrinsicOrDoesNotReturn = [this, &NoCallIntrinsicCache](
18705 const Instruction *I) {
18706 const auto *CB = dyn_cast<CallBase>(I);
18707 if (!CB)
18708 return false;
18709 if (CB->doesNotReturn())
18710 return true;
18711 const auto *II = dyn_cast<IntrinsicInst>(CB);
18712 if (!II)
18713 return false;
18714 if (II->isAssumeLikeIntrinsic())
18715 return true;
18716 auto [It, Inserted] = NoCallIntrinsicCache.try_emplace(II);
18717 if (!Inserted)
18718 return It->second;
18719 IntrinsicCostAttributes ICA(II->getIntrinsicID(), *II);
18720 InstructionCost IntrCost = TTI->getIntrinsicInstrCost(ICA, CostKind);
18721 InstructionCost CallCost = TTI->getCallInstrCost(
18722 nullptr, II->getType(), ICA.getArgTypes(), CostKind);
18723 bool Res = IntrCost < CallCost;
18724 It->second = Res;
18725 return Res;
18726 };
18727
18728 // Maps last instruction in the entry to the last instruction for the one of
18729 // operand entries and the flag. If the flag is true, there are no calls in
18730 // between these instructions.
18732 CheckedInstructions;
18733 unsigned Budget = 0;
18734 const unsigned BudgetLimit =
18735 ScheduleRegionSizeBudget / VectorizableTree.size();
18736 auto CheckForNonVecCallsInSameBlock = [&](Instruction *First,
18737 const Instruction *Last) {
18738 assert(First->getParent() == Last->getParent() &&
18739 "Expected instructions in same block.");
18740 if (auto It = CheckedInstructions.find(Last);
18741 It != CheckedInstructions.end()) {
18742 const Instruction *Checked = It->second.getPointer();
18743 const bool NoCallsInCachedRange = It->second.getInt() != 0;
18744 if (Checked == First)
18745 return NoCallsInCachedRange;
18746 if (Checked->comesBefore(First))
18747 // In every cached state (full clean scan, call-found, or
18748 // budget-exhausted) the region strictly above `Checked` up to `Last`
18749 // was inspected and proved call-free. Since `First` is above
18750 // `Checked`, the queried range [First, Last] is contained in that
18751 // call-free region, regardless of whether bit is 0 or 1.
18752 return true;
18753 Last = Checked;
18754 } else if (Last == First || Last->comesBefore(First)) {
18755 // Empty range.
18756 return true;
18757 }
18759 ++First->getIterator().getReverse(),
18760 PrevInstIt =
18761 Last->getIterator().getReverse();
18762 SmallVector<const Instruction *> LastInstsInRange;
18763 while (InstIt != PrevInstIt && Budget <= BudgetLimit) {
18764 // Debug information does not impact spill cost.
18765 // Vectorized calls, represented as vector intrinsics, do not impact spill
18766 // cost.
18767 if (const auto *CB = dyn_cast<CallBase>(&*PrevInstIt);
18768 CB && !NoCallIntrinsicOrDoesNotReturn(CB) && !isVectorized(CB)) {
18769 for (const Instruction *LastInst : LastInstsInRange)
18770 CheckedInstructions.try_emplace(LastInst, &*PrevInstIt, 0);
18771 return false;
18772 }
18773 if (LastInstructions.contains(&*PrevInstIt))
18774 LastInstsInRange.push_back(&*PrevInstIt);
18775
18776 ++PrevInstIt;
18777 ++Budget;
18778 }
18779 // If we reached the scan's lower bound (`PrevInstIt == InstIt`) then the
18780 // whole [First, Last] range was inspected and found call-free, even if
18781 // Budget just overflowed at the very last step; do not mislabel such a
18782 // completed scan as "has call".
18783 const bool Completed = PrevInstIt == InstIt;
18784 const bool NoCallsInRange = Completed || Budget <= BudgetLimit;
18785 for (const Instruction *LastInst : LastInstsInRange)
18786 CheckedInstructions.try_emplace(
18787 LastInst, Completed ? First : &*PrevInstIt, NoCallsInRange ? 1 : 0);
18788 return NoCallsInRange;
18789 };
18790 // The spill/reload is executed once per execution of the call, so the
18791 // cost is scaled by the trip count of the loop containing the call, even
18792 // for hoisted loop-invariant values defined outside of it.
18793 auto GetSpillScale = [&](const BasicBlock *BB) {
18794 return getLoopNestScale(LI->getLoopFor(BB));
18795 };
18796 auto AddCosts = [&](const TreeEntry *Op, uint64_t Scale) {
18797 if (ScalarOrPseudoEntries.contains(Op))
18798 return;
18799 Type *ScalarTy = Op->Scalars.front()->getType();
18800 auto It = MinBWs.find(Op);
18801 if (It != MinBWs.end())
18802 ScalarTy = IntegerType::get(ScalarTy->getContext(), It->second.first);
18803 auto *VecTy = getWidenedType(ScalarTy, Op->getVectorFactor());
18804 InstructionCost KeepLiveCost = TTI->getCostOfKeepingLiveOverCall(VecTy);
18805 KeepLiveCost *= Scale;
18806 Cost += KeepLiveCost;
18807 if (ScalarTy->isVectorTy()) {
18808 // Handle revec dead vector instructions.
18809 Cost -= Op->Scalars.size() * TTI->getCostOfKeepingLiveOverCall(ScalarTy) *
18810 Scale;
18811 }
18812 };
18813 // Memoize the relationship between blocks, i.e. the spill scale if every
18814 // path between the blocks crosses a non-vectorized call, 0 if there is (at
18815 // least one) call-free path. This allows to skip the analysis of the same
18816 // block paths multiple times.
18818 ParentOpParentToPreds;
18819 // Memoize whether a basic block contains a non-terminator no-return call.
18820 // Such blocks are dead-end paths in normal control flow (execution does not
18821 // exit them past the no-return call), so the block is excluded from the
18822 // spill cost analysis. Terminator no-return calls (invoke/callbr) are not
18823 // block-killing because they still have live CFG successors (e.g. the
18824 // unwind destination of an invoke).
18825 SmallDenseMap<const BasicBlock *, bool> BlockHasNoReturnCallCache;
18826 auto BlockHasNoReturnCall = [&](const BasicBlock *BB) {
18827 auto [It, Inserted] = BlockHasNoReturnCallCache.try_emplace(BB, false);
18828 if (!Inserted)
18829 return It->second;
18830 for (const Instruction &I : *BB) {
18831 const auto *CB = dyn_cast<CallBase>(&I);
18832 if (CB && CB->doesNotReturn() && !CB->isTerminator()) {
18833 It->second = true;
18834 return true;
18835 }
18836 }
18837 return false;
18838 };
18839 // Memoize whether a loop's body (all blocks of the loop, including
18840 // sub-loops) contains any non-vec call.
18841 SmallDenseMap<const Loop *, bool> LoopBodyHasNonVecCall;
18842 auto LoopBodyHasCall = [&](const Loop *L) {
18843 if (auto It = LoopBodyHasNonVecCall.find(L);
18844 It != LoopBodyHasNonVecCall.end())
18845 return It->second;
18846 for (BasicBlock *BB : L->blocks()) {
18848 continue;
18849 // Blocks containing a no-return call are dead-end paths and never
18850 // actually flow back through the loop's back-edge, so their calls do
18851 // not keep loop-invariant vector values live across calls.
18852 if (BlockHasNoReturnCall(BB))
18853 continue;
18854 for (const Instruction &I : *BB) {
18855 const auto *CB = dyn_cast<CallBase>(&I);
18856 if (!CB || NoCallIntrinsicOrDoesNotReturn(CB) || isVectorized(CB))
18857 continue;
18858 LoopBodyHasNonVecCall.try_emplace(L, true);
18859 return true;
18860 }
18861 }
18862 LoopBodyHasNonVecCall.try_emplace(L, false);
18863 return false;
18864 };
18865 auto CheckPredecessors = [&](BasicBlock *Root, BasicBlock *Pred,
18866 BasicBlock *OpParent) {
18867 auto Key = std::make_pair(Root, OpParent);
18868 if (auto It = ParentOpParentToPreds.find(Key);
18869 It != ParentOpParentToPreds.end())
18870 return It->second;
18871 uint64_t Res = 0;
18872 scope_exit Cleanup([&]() { ParentOpParentToPreds.try_emplace(Key, Res); });
18873 // If Op is loop-invariant, a call anywhere in the loop body forces a spill,
18874 // even when a call-free forward path from Root back to OpParent exists on
18875 // the first iteration. Find the outermost such enclosing loop and reject if
18876 // its body contains a non-vec call.
18877 const Loop *L = LI->getLoopFor(Root);
18878 const Loop *Outermost = nullptr;
18879 while (L && !L->contains(OpParent)) {
18880 Outermost = L;
18881 L = L->getParentLoop();
18882 }
18883 if (Outermost && LoopBodyHasCall(Outermost)) {
18884 Res = getLoopNestScale(Outermost);
18885 return Res;
18886 }
18888 if (Pred)
18889 Worklist.push_back(Pred);
18890 else
18891 Worklist.append(pred_begin(Root), pred_end(Root));
18893 // With "at least one call-free path" semantics we can only reliably
18894 // memoize the exact (Root, OpParent) query. Pairs for intermediate
18895 // blocks that were visited during the BFS are not necessarily
18896 // call-free-reachable to OpParent themselves - we may have reached
18897 // OpParent through a *sibling* path that bypassed them.
18898 // We return 0 (no spill cost) if at least one backward path from
18899 // some predecessor of Root back to OpParent is call-free. Only when
18900 // *every* such path goes through a non-vec call do we charge the spill
18901 // cost: only then is it actually necessary to keep the vectorized value
18902 // live across a call and therefore spill/reload it.
18903 //
18904 // A BB is only explored further (its predecessors added to the worklist)
18905 // when it is itself call-free and not strictly dominated by Root (blocks
18906 // dominated by Root are only reachable via loop back-edges - they sit
18907 // *after* Root in forward execution and must not be counted).
18908 //
18909 // If we ever pop OpParent from the worklist, we have reached it through
18910 // a chain of call-free, non-dominated blocks: a call-free path exists
18911 // and we return 0. If the worklist is exhausted or the scan budget
18912 // overflows without reaching OpParent, no call-free path was found and
18913 // we return the scale of the loop containing Root, so the caller charges
18914 // the spill cost.
18915 while (!Worklist.empty()) {
18916 BasicBlock *BB = Worklist.pop_back_val();
18917 if (BB == OpParent)
18918 return Res;
18919 if (!Visited.insert(BB).second)
18920 continue;
18921 // Blocks strictly dominated by Root are reached only *after* Root in
18922 // forward execution (via loop back-edges); skip them and their
18923 // dominated predecessors.
18924 if (DT->properlyDominates(Root, BB))
18925 continue;
18926 // A block containing a no-return call cannot reach Root via the
18927 // forward edge being analyzed: execution does not continue past the
18928 // no-return call, so the BB -> ... -> Root path is dead. Drop the
18929 // block from the analysis without following its predecessors.
18930 if (BlockHasNoReturnCall(BB))
18931 continue;
18932 auto Pair = std::make_pair(BB, OpParent);
18933 if (auto It = ParentOpParentToPreds.find(Pair);
18934 It != ParentOpParentToPreds.end()) {
18935 // BB is known to reach OpParent via a call-free path.
18936 if (It->second == 0)
18937 return Res;
18938 // BB is known to be blocked from OpParent by calls; keep checking
18939 // other paths.
18940 continue;
18941 }
18942 unsigned BlockSize = BB->size();
18943 if (BlockSize > static_cast<unsigned>(ScheduleRegionSizeBudget))
18944 continue;
18945 Budget += BlockSize;
18946 if (Budget > BudgetLimit)
18947 break;
18948 if (!isa<CatchSwitchInst>(BB->getTerminator()) &&
18949 !CheckForNonVecCallsInSameBlock(&*BB->getFirstNonPHIOrDbgOrAlloca(),
18950 BB->getTerminator()))
18951 continue;
18952 Worklist.append(pred_begin(BB), pred_end(BB));
18953 }
18954 Res = GetSpillScale(Root);
18955 return Res;
18956 };
18957 SmallVector<const TreeEntry *> LiveEntries(1, Root);
18958 auto FindNonScalarParentEntry = [&](const TreeEntry *E) -> const TreeEntry * {
18959 assert(ScalarOrPseudoEntries.contains(E) &&
18960 "Expected scalar or pseudo entry.");
18961 const TreeEntry *Entry = E;
18962 while (Entry->UserTreeIndex) {
18963 Entry = Entry->UserTreeIndex.UserTE;
18964 if (!ScalarOrPseudoEntries.contains(Entry))
18965 return Entry;
18966 }
18967 return nullptr;
18968 };
18969 while (!LiveEntries.empty()) {
18970 const TreeEntry *Entry = LiveEntries.pop_back_val();
18971 const auto OpIt = EntriesToOperands.find(Entry);
18972 if (OpIt == EntriesToOperands.end())
18973 continue;
18975 if (Operands.empty())
18976 continue;
18977 if (ScalarOrPseudoEntries.contains(Entry)) {
18978 Entry = FindNonScalarParentEntry(Entry);
18979 if (!Entry) {
18980 for (const TreeEntry *Op : Operands) {
18981 if (!Op->isGather())
18982 LiveEntries.push_back(Op);
18983 }
18984 continue;
18985 }
18986 }
18987 Instruction *LastInst = EntriesToLastInstruction.at(Entry);
18988 BasicBlock *Parent = LastInst->getParent();
18989 for (const TreeEntry *Op : Operands) {
18990 if (!Op->isGather())
18991 LiveEntries.push_back(Op);
18992 if (ScalarOrPseudoEntries.contains(Op))
18993 continue;
18994 if (Entry->State == TreeEntry::SplitVectorize ||
18995 (Op->isGather() && allConstant(Op->Scalars)))
18996 continue;
18997 // A gather with all loop-invariant lanes is hoisted to the loop
18998 // preheader by optimizeGatherSequence, so its vector value becomes live
18999 // across any non-vectorized call in the loop body. Charge it like any
19000 // other vectorized value live over a call instead of skipping it.
19001 if (Entry->hasState() && Entry->getOpcode() != Instruction::PHI &&
19002 Op->isGather()) {
19003 if (const Loop *L = LI->getLoopFor(Parent);
19004 L && L->getLoopPreheader() && LoopBodyHasCall(L) &&
19005 all_of(Op->Scalars, [&](Value *V) {
19006 return !isa<Instruction>(V) || L->isLoopInvariant(V);
19007 }))
19008 AddCosts(Op, GetSpillScale(Parent));
19009 continue;
19010 }
19011 Budget = 0;
19012 BasicBlock *Pred = nullptr;
19013 if (auto *Phi = dyn_cast<PHINode>(Entry->getMainOp()))
19014 Pred = Phi->getIncomingBlock(Op->UserTreeIndex.EdgeIdx);
19015 BasicBlock *OpParent;
19016 Instruction *OpLastInst;
19017 if (Op->isGather()) {
19018 assert(Entry->getOpcode() == Instruction::PHI &&
19019 "Expected phi node only.");
19020 OpParent = cast<PHINode>(Entry->getMainOp())
19021 ->getIncomingBlock(Op->UserTreeIndex.EdgeIdx);
19022 OpLastInst = OpParent->getTerminator();
19023 for (Value *V : Op->Scalars) {
19024 auto *Inst = dyn_cast<Instruction>(V);
19025 if (!Inst)
19026 continue;
19027 if (isVectorized(V)) {
19028 OpParent = Inst->getParent();
19029 OpLastInst = Inst;
19030 break;
19031 }
19032 }
19033 } else {
19034 OpLastInst = EntriesToLastInstruction.at(Op);
19035 OpParent = OpLastInst->getParent();
19036 }
19037 // Check the call instructions within the same basic blocks.
19038 if (OpParent == Parent) {
19039 if (Entry->getOpcode() == Instruction::PHI) {
19040 if (!CheckForNonVecCallsInSameBlock(LastInst, OpLastInst))
19041 AddCosts(Op, GetSpillScale(Parent));
19042 continue;
19043 }
19044 if (!CheckForNonVecCallsInSameBlock(OpLastInst, LastInst))
19045 AddCosts(Op, GetSpillScale(Parent));
19046 continue;
19047 }
19048 // Check for call instruction in between blocks.
19049 // 1. Check entry's block to the head.
19050 if (Entry->getOpcode() != Instruction::PHI &&
19051 !CheckForNonVecCallsInSameBlock(
19052 &*Parent->getFirstNonPHIOrDbgOrAlloca(), LastInst)) {
19053 AddCosts(Op, GetSpillScale(Parent));
19054 continue;
19055 }
19056 // 2. Check op's block from the end.
19057 if (!CheckForNonVecCallsInSameBlock(OpLastInst,
19058 OpParent->getTerminator())) {
19059 AddCosts(Op, GetSpillScale(OpParent));
19060 continue;
19061 }
19062 // 3. Check the predecessors of entry's block till op's block.
19063 if (uint64_t Scale = CheckPredecessors(Parent, Pred, OpParent))
19064 AddCosts(Op, Scale);
19065 }
19066 }
19067
19068 return Cost;
19069}
19070
19071/// Checks if the \p IE1 instructions is followed by \p IE2 instruction in the
19072/// buildvector sequence.
19074 const InsertElementInst *IE2) {
19075 if (IE1 == IE2)
19076 return false;
19077 const auto *I1 = IE1;
19078 const auto *I2 = IE2;
19079 const InsertElementInst *PrevI1;
19080 const InsertElementInst *PrevI2;
19081 unsigned Idx1 = *getElementIndex(IE1);
19082 unsigned Idx2 = *getElementIndex(IE2);
19083 do {
19084 if (I2 == IE1)
19085 return true;
19086 if (I1 == IE2)
19087 return false;
19088 PrevI1 = I1;
19089 PrevI2 = I2;
19090 if (I1 && (I1 == IE1 || I1->hasOneUse()) &&
19091 getElementIndex(I1).value_or(Idx2) != Idx2)
19092 I1 = dyn_cast<InsertElementInst>(I1->getOperand(0));
19093 if (I2 && ((I2 == IE2 || I2->hasOneUse())) &&
19094 getElementIndex(I2).value_or(Idx1) != Idx1)
19095 I2 = dyn_cast<InsertElementInst>(I2->getOperand(0));
19096 } while ((I1 && PrevI1 != I1) || (I2 && PrevI2 != I2));
19097 llvm_unreachable("Two different buildvectors not expected.");
19098}
19099
19100namespace {
19101/// Returns incoming Value *, if the requested type is Value * too, or a default
19102/// value, otherwise.
19103struct ValueSelect {
19104 template <typename U>
19105 static std::enable_if_t<std::is_same_v<Value *, U>, Value *> get(Value *V) {
19106 return V;
19107 }
19108 template <typename U>
19109 static std::enable_if_t<!std::is_same_v<Value *, U>, U> get(Value *) {
19110 return U();
19111 }
19112};
19113} // namespace
19114
19115/// Does the analysis of the provided shuffle masks and performs the requested
19116/// actions on the vectors with the given shuffle masks. It tries to do it in
19117/// several steps.
19118/// 1. If the Base vector is not undef vector, resizing the very first mask to
19119/// have common VF and perform action for 2 input vectors (including non-undef
19120/// Base). Other shuffle masks are combined with the resulting after the 1 stage
19121/// and processed as a shuffle of 2 elements.
19122/// 2. If the Base is undef vector and have only 1 shuffle mask, perform the
19123/// action only for 1 vector with the given mask, if it is not the identity
19124/// mask.
19125/// 3. If > 2 masks are used, perform the remaining shuffle actions for 2
19126/// vectors, combing the masks properly between the steps.
19127template <typename T>
19129 MutableArrayRef<std::pair<T *, SmallVector<int>>> ShuffleMask, Value *Base,
19130 function_ref<unsigned(T *)> GetVF,
19131 function_ref<std::pair<T *, bool>(T *, ArrayRef<int>, bool)> ResizeAction,
19133 assert(!ShuffleMask.empty() && "Empty list of shuffles for inserts.");
19134 SmallVector<int> Mask(ShuffleMask.begin()->second);
19135 auto VMIt = std::next(ShuffleMask.begin());
19136 T *Prev = nullptr;
19138 buildUseMask(Mask.size(), Mask, UseMask::UndefsAsMask);
19139 SmallBitVector IsBaseUndef = isUndefVector(Base, UseMask);
19140 if (!IsBaseUndef.all()) {
19141 // Base is not undef, need to combine it with the next subvectors.
19142 std::pair<T *, bool> Res =
19143 ResizeAction(ShuffleMask.begin()->first, Mask, /*ForSingleMask=*/false);
19145 for (unsigned Idx = 0, VF = Mask.size(); Idx < VF; ++Idx) {
19146 if (Mask[Idx] == PoisonMaskElem)
19147 Mask[Idx] = IsBasePoison.test(Idx) ? PoisonMaskElem : Idx;
19148 else
19149 Mask[Idx] = (Res.second ? Idx : Mask[Idx]) + VF;
19150 }
19151 [[maybe_unused]] auto *V = ValueSelect::get<T *>(Base);
19152 assert((!V || GetVF(V) == Mask.size()) &&
19153 "Expected base vector of VF number of elements.");
19154 Prev = Action(Mask, {nullptr, Res.first});
19155 } else if (ShuffleMask.size() == 1) {
19156 // Base is undef and only 1 vector is shuffled - perform the action only for
19157 // single vector, if the mask is not the identity mask.
19158 std::pair<T *, bool> Res = ResizeAction(ShuffleMask.begin()->first, Mask,
19159 /*ForSingleMask=*/true);
19160 if (Res.second)
19161 // Identity mask is found.
19162 Prev = Res.first;
19163 else
19164 Prev = Action(Mask, {ShuffleMask.begin()->first});
19165 } else {
19166 // Base is undef and at least 2 input vectors shuffled - perform 2 vectors
19167 // shuffles step by step, combining shuffle between the steps.
19168 unsigned Vec1VF = GetVF(ShuffleMask.begin()->first);
19169 unsigned Vec2VF = GetVF(VMIt->first);
19170 if (Vec1VF == Vec2VF) {
19171 // No need to resize the input vectors since they are of the same size, we
19172 // can shuffle them directly.
19173 ArrayRef<int> SecMask = VMIt->second;
19174 for (unsigned I = 0, VF = Mask.size(); I < VF; ++I) {
19175 if (SecMask[I] != PoisonMaskElem) {
19176 assert(Mask[I] == PoisonMaskElem && "Multiple uses of scalars.");
19177 Mask[I] = SecMask[I] + Vec1VF;
19178 }
19179 }
19180 Prev = Action(Mask, {ShuffleMask.begin()->first, VMIt->first});
19181 } else {
19182 // Vectors of different sizes - resize and reshuffle.
19183 std::pair<T *, bool> Res1 = ResizeAction(ShuffleMask.begin()->first, Mask,
19184 /*ForSingleMask=*/false);
19185 std::pair<T *, bool> Res2 =
19186 ResizeAction(VMIt->first, VMIt->second, /*ForSingleMask=*/false);
19187 ArrayRef<int> SecMask = VMIt->second;
19188 for (unsigned I = 0, VF = Mask.size(); I < VF; ++I) {
19189 if (Mask[I] != PoisonMaskElem) {
19190 assert(SecMask[I] == PoisonMaskElem && "Multiple uses of scalars.");
19191 if (Res1.second)
19192 Mask[I] = I;
19193 } else if (SecMask[I] != PoisonMaskElem) {
19194 assert(Mask[I] == PoisonMaskElem && "Multiple uses of scalars.");
19195 Mask[I] = (Res2.second ? I : SecMask[I]) + VF;
19196 }
19197 }
19198 Prev = Action(Mask, {Res1.first, Res2.first});
19199 }
19200 VMIt = std::next(VMIt);
19201 }
19202 [[maybe_unused]] bool IsBaseNotUndef = !IsBaseUndef.all();
19203 // Perform requested actions for the remaining masks/vectors.
19204 for (auto E = ShuffleMask.end(); VMIt != E; ++VMIt) {
19205 // Shuffle other input vectors, if any.
19206 std::pair<T *, bool> Res =
19207 ResizeAction(VMIt->first, VMIt->second, /*ForSingleMask=*/false);
19208 ArrayRef<int> SecMask = VMIt->second;
19209 for (unsigned I = 0, VF = Mask.size(); I < VF; ++I) {
19210 if (SecMask[I] != PoisonMaskElem) {
19211 assert((Mask[I] == PoisonMaskElem || IsBaseNotUndef) &&
19212 "Multiple uses of scalars.");
19213 Mask[I] = (Res.second ? I : SecMask[I]) + VF;
19214 } else if (Mask[I] != PoisonMaskElem) {
19215 Mask[I] = I;
19216 }
19217 }
19218 Prev = Action(Mask, {Prev, Res.first});
19219 }
19220 return Prev;
19221}
19222
19225 Instruction *RdxRoot) {
19226 // FIXME: support buildvector of the gather nodes with struct types.
19227 if (any_of(VectorizableTree, [&](const std::unique_ptr<TreeEntry> &TE) {
19228 return TE->isGather() &&
19229 isa<StructType>(TE->Scalars.front()->getType());
19230 })) {
19231 LLVM_DEBUG(
19232 dbgs() << "SLP: rejecting tree with buildvector struct values of size "
19233 << VectorizableTree.size() << ".\n");
19235 }
19236
19237 // The tree is priced, so its minimal vector nodes are analyzed, including the
19238 // ones, trimmed below as non-profitable. The verdict of the tree itself does
19239 // not matter: the retry with the single-user seeds rebuilds the same narrow
19240 // nodes, and their cost without the tree is not better. The wider nodes are
19241 // not registered: their rejection does not prevent the members from forming
19242 // the profitable narrower node. Same for the trees, rejected before the cost
19243 // estimation, and for the buildvector trees, rejected by the insert/extract
19244 // overhead rather than by the members themselves.
19245 const TreeEntry &Root = getRootNode();
19246 if (!Root.hasState() ||
19247 !isa<InsertElementInst, InsertValueInst>(Root.getMainOp())) {
19248 for (const std::unique_ptr<TreeEntry> &TE : VectorizableTree) {
19249 if (TE->isGather() || TE->Scalars.size() > 2)
19250 continue;
19251 for (Value *V : TE->Scalars)
19252 if (isa_and_present<Instruction>(V) && !TE->isCopyableElement(V))
19253 AnalyzedScalars.insert(V);
19254 }
19255 }
19256
19258 SmallPtrSet<Value *, 4> CheckedExtracts;
19259 SmallSetVector<TreeEntry *, 4> GatheredLoadsNodes;
19261 LLVM_DEBUG(dbgs() << "SLP: Calculating cost for tree of size "
19262 << VectorizableTree.size() << ".\n");
19263 // The V-only-dependent part of the predicate. Same V is commonly seen in
19264 // multiple TEs (shared scalars), so cache the result across calls.
19265 // DeletedNodes is read-only during this cost loop, so caching is safe.
19266 const size_t NumVectScalars = ScalarToTreeEntries.size() + 1;
19267 SmallDenseMap<Value *, bool> ExternalUseVCache;
19268 auto IsExternallyUsedV = [&](Value *V) {
19269 auto [It, Inserted] = ExternalUseVCache.try_emplace(V);
19270 if (!Inserted)
19271 return It->second;
19272 bool Res = false;
19273 if (V->hasOneUse() || V->getType()->isVoidTy()) {
19274 // Res stays false.
19275 } else if (V->hasNUsesOrMore(NumVectScalars)) {
19276 Res = true;
19277 } else if (auto *I = dyn_cast<Instruction>(V)) {
19278 Res = any_of(I->users(), [&](const User *U) {
19279 // store/insertelt v, [cast]U will likely be vectorized.
19280 if (match(U,
19281 m_InsertElt(m_Value(), m_OneUse(m_CastOrSelf(m_Specific(I))),
19282 m_ConstantInt())))
19283 return false;
19284 if (match(U, m_InsertElt(m_Value(), m_Specific(I), m_ConstantInt())))
19285 return false;
19286 if (match(U, m_Store(m_OneUse(m_CastOrSelf(m_Specific(I))), m_Value())))
19287 return false;
19288 if (match(U, m_Store(m_Specific(I), m_Value())))
19289 return false;
19290 ArrayRef<TreeEntry *> Entries = getTreeEntries(U);
19291 if (Entries.empty() && !MustGather.contains(U))
19292 return true;
19293 if (any_of(Entries,
19294 [&](TreeEntry *TE) { return DeletedNodes.contains(TE); }))
19295 return true;
19296 return any_of(ValueToGatherNodes.lookup(U), [&](const TreeEntry *TE) {
19297 return DeletedNodes.contains(TE);
19298 });
19299 });
19300 }
19301 It->second = Res;
19302 return Res;
19303 };
19304 auto IsExternallyUsed = [&](const TreeEntry &TE, Value *V) {
19305 assert(TE.hasState() && !TE.isGather() &&
19306 TE.State != TreeEntry::SplitVectorize && "Expected vector node.");
19307 if (TE.hasCopyableElements() && TE.isCopyableElement(V))
19308 return false;
19309 return IsExternallyUsedV(V);
19310 };
19311 InstructionCost Cost = 0;
19313 uint64_t PrevScale = 0;
19314 BasicBlock *PrevVecParent = nullptr;
19315 for (const std::unique_ptr<TreeEntry> &Ptr : VectorizableTree) {
19316 TreeEntry &TE = *Ptr;
19317 // No need to count the cost for combined entries, they are combined and
19318 // just skip their cost.
19319 if (TE.State == TreeEntry::CombinedVectorize) {
19320 LLVM_DEBUG(
19321 dbgs() << "SLP: Skipping cost for combined node that starts with "
19322 << *TE.Scalars[0] << ".\n";
19323 TE.dump(); dbgs() << "SLP: Current total cost = " << Cost << "\n");
19324 NodesCosts.try_emplace(&TE);
19325 continue;
19326 }
19327 if (TE.hasState() &&
19328 (TE.isGather() || TE.State == TreeEntry::SplitVectorize)) {
19329 if (const TreeEntry *E =
19330 getSameValuesTreeEntry(TE.getMainOp(), TE.Scalars);
19331 E && E->getVectorFactor() == TE.getVectorFactor()) {
19332 // Some gather nodes might be absolutely the same as some vectorizable
19333 // nodes after reordering, need to handle it.
19334 LLVM_DEBUG(dbgs() << "SLP: Adding cost 0 for bundle "
19335 << shortBundleName(TE.Scalars, TE.Idx) << ".\n"
19336 << "SLP: Current total cost = " << Cost << "\n");
19337 NodesCosts.try_emplace(&TE);
19338 continue;
19339 }
19340 }
19341
19342 // Exclude cost of gather loads nodes which are not used. These nodes were
19343 // built as part of the final attempt to vectorize gathered loads.
19344 assert((!TE.isGather() || TE.Idx == 0 || TE.UserTreeIndex) &&
19345 "Expected gather nodes with users only.");
19346
19347 InstructionCost C = getEntryCost(&TE, VectorizedVals, CheckedExtracts);
19348 uint64_t Scale = 0;
19349 bool CostIsFree = C == 0;
19350 // For gather/buildvector (and split-vectorize) entries, prefer the
19351 // per-lane refined scale that accounts for LICM-hoistable insertelements
19352 // when an operand is invariant in the current loop nest but defined in
19353 // an outer loop. This prevents over-costing cross-loop-nest buildvectors.
19354 if (!CostIsFree && !TE.isGather() && TE.hasState()) {
19355 if (PrevVecParent == TE.getMainOp()->getParent()) {
19356 Scale = PrevScale;
19357 C *= Scale;
19358 EntryToScale.try_emplace(&TE, Scale);
19359 }
19360 }
19361 if (!CostIsFree && !Scale) {
19362 Scale = getEntryEffectiveScale(TE, TE.Idx == 0 ? RdxRoot : nullptr);
19363 C *= Scale;
19364 EntryToScale.try_emplace(&TE, Scale);
19365 if (!TE.isGather() && TE.hasState()) {
19366 PrevVecParent = TE.getMainOp()->getParent();
19367 PrevScale = Scale;
19368 }
19369 }
19370 Cost += C;
19371 NodesCosts.try_emplace(&TE, C);
19372 LLVM_DEBUG(dbgs() << "SLP: Adding cost " << C << " for bundle "
19373 << shortBundleName(TE.Scalars, TE.Idx) << ".\n"
19374 << "SLP: Current total cost = " << Cost << "\n");
19375 // Add gathered loads nodes to the set for later processing.
19376 if (TE.Idx > 0 && !TE.UserTreeIndex && TE.hasState() &&
19377 TE.getOpcode() == Instruction::Load)
19378 GatheredLoadsNodes.insert(&TE);
19379 if (!TE.isGather() && TE.State != TreeEntry::SplitVectorize &&
19380 !(TE.Idx == 0 && (TE.getOpcode() == Instruction::InsertElement ||
19381 TE.getOpcode() == Instruction::InsertValue ||
19382 TE.getOpcode() == Instruction::Store)) &&
19383 !isa<StructType>(getValueType(TE.Scalars.front(), SLPReVec))) {
19384 // Calculate costs of external uses.
19385 APInt DemandedElts = APInt::getZero(TE.getVectorFactor());
19386 for (Value *V : TE.Scalars) {
19387 if (IsExternallyUsed(TE, V))
19388 DemandedElts.setBit(TE.findLaneForValue(V));
19389 }
19390 if (!DemandedElts.isZero()) {
19391 Type *ScalarTy = TE.Scalars.front()->getType();
19392 auto It = MinBWs.find(&TE);
19393 if (It != MinBWs.end())
19394 ScalarTy = IntegerType::get(ScalarTy->getContext(), It->second.first);
19395 auto *VecTy = getWidenedType(ScalarTy, TE.getVectorFactor());
19397 *TTI, SLPReVec, ScalarTy, cast<VectorType>(VecTy), DemandedElts,
19398 /*Insert=*/false,
19399 /*Extract=*/true, CostKind);
19400 if (ExtCost.isValid() && ExtCost != 0) {
19401 if (!Scale)
19402 Scale = getScaleToLoopIterations(TE);
19403 ExtCost *= Scale;
19404 EntryToScale.try_emplace(&TE, Scale);
19405 }
19406 ExtractCosts.try_emplace(&TE, ExtCost);
19407 }
19408 }
19409 }
19410 // Bail out if the cost threshold is negative and cost already below it.
19411 // The splat subtrees may still force extracts of their scalars on top of
19412 // the node cost and have to be trimmed, so do not bail out if there are
19413 // any.
19414 if (SLPCostThreshold.getNumOccurrences() > 0 && SLPCostThreshold < 0 &&
19415 Cost < -SLPCostThreshold && SplatGatheredScalarsRoots.empty())
19416 return Cost;
19417 // The narrow non-profitable tree in loop? Skip, may cause regressions.
19418 constexpr unsigned PartLimit = 2;
19419 // Measure the narrowness by the width the tree is vectorized at.
19420 const TreeEntry *RootTE = &getRootNode();
19421 unsigned Sz;
19422 if (auto It = MinBWs.find(RootTE); It != MinBWs.end()) {
19423 Sz = It->second.first;
19424 } else {
19425 Sz = std::max<unsigned>(
19426 getVectorElementSize(RootTE->Scalars.front()),
19427 DL->getTypeSizeInBits(
19428 getValueType(RootTE->Scalars.front(), SLPReVec)->getScalarType()));
19429 }
19430 const unsigned MinVF = getMinVF(Sz);
19431 if (Cost >= -SLPCostThreshold &&
19432 getRootNodeScalars().size() * PartLimit <= MinVF &&
19433 (!getRootNode().hasState() ||
19434 (getRootNode().getOpcode() != Instruction::Store &&
19435 LI->getLoopFor(getRootNode().getMainOp()->getParent()))))
19436 return Cost;
19437 // Store the cost + external uses estimation as the first element of the
19438 // tuple, just the cost as the second element of the tuple. Required to return
19439 // correct cost estimation for the tree, extracts are calculated separately.
19440 // Extracts, calculated here, are just quick estimations.
19442 std::tuple<InstructionCost, InstructionCost, SmallVector<unsigned>>>
19443 SubtreeCosts(VectorizableTree.size());
19444 auto UpdateParentNodes =
19445 [&](const TreeEntry *UserTE, const TreeEntry *TE,
19447 SmallDenseSet<std::pair<const TreeEntry *, const TreeEntry *>, 4>
19448 &VisitedUser,
19449 bool AddToList = true) {
19450 while (UserTE &&
19451 VisitedUser.insert(std::make_pair(TE, UserTE)).second) {
19452 std::get<0>(SubtreeCosts[UserTE->Idx]) += TotalCost;
19453 std::get<1>(SubtreeCosts[UserTE->Idx]) += Cost;
19454 if (AddToList)
19455 std::get<2>(SubtreeCosts[UserTE->Idx]).push_back(TE->Idx);
19456 UserTE = UserTE->UserTreeIndex.UserTE;
19457 }
19458 };
19459 for (const std::unique_ptr<TreeEntry> &Ptr : VectorizableTree) {
19460 TreeEntry &TE = *Ptr;
19461 // Combined subnodes are not costed on their own (their cost is 0), but
19462 // must be included into the ancestors' subtree node lists, so that they
19463 // get deleted together with the trimmed combined root.
19464 InstructionCost C = NodesCosts.at(&TE);
19465 InstructionCost ExtractCost = ExtractCosts.lookup(&TE);
19466 std::get<0>(SubtreeCosts[TE.Idx]) += C + ExtractCost;
19467 std::get<1>(SubtreeCosts[TE.Idx]) += C;
19468 if (const TreeEntry *UserTE = TE.UserTreeIndex.UserTE) {
19469 SmallDenseSet<std::pair<const TreeEntry *, const TreeEntry *>, 4>
19470 VisitedUser;
19471 UpdateParentNodes(UserTE, &TE, C + ExtractCost, C, VisitedUser);
19472 }
19473 }
19474 SmallDenseSet<std::pair<const TreeEntry *, const TreeEntry *>, 4> Visited;
19475 for (TreeEntry *TE : GatheredLoadsNodes) {
19476 InstructionCost TotalCost = std::get<0>(SubtreeCosts[TE->Idx]);
19477 InstructionCost Cost = std::get<1>(SubtreeCosts[TE->Idx]);
19478 for (Value *V : TE->Scalars) {
19479 for (const TreeEntry *BVTE : ValueToGatherNodes.lookup(V))
19480 UpdateParentNodes(BVTE, TE, TotalCost, Cost, Visited,
19481 /*AddToList=*/false);
19482 }
19483 }
19484 Visited.clear();
19485 using CostIndicesTy =
19486 std::pair<TreeEntry *, std::tuple<InstructionCost, InstructionCost,
19487 SmallVector<unsigned>>>;
19488 struct FirstGreater {
19489 bool operator()(const CostIndicesTy &LHS, const CostIndicesTy &RHS) const {
19490 return std::get<0>(LHS.second) < std::get<0>(RHS.second) ||
19491 (std::get<0>(LHS.second) == std::get<0>(RHS.second) &&
19492 LHS.first->Idx < RHS.first->Idx);
19493 }
19494 };
19495 PriorityQueue<CostIndicesTy, SmallVector<CostIndicesTy>, FirstGreater>
19496 Worklist;
19497 for (const auto [Idx, P] : enumerate(SubtreeCosts)) {
19498 // Combined subnodes are not trimmed on their own, only as a whole combined
19499 // node, so only the root nodes are checked and included into the worklist.
19500 if (VectorizableTree[Idx]->State == TreeEntry::CombinedVectorize)
19501 continue;
19502 Worklist.emplace(VectorizableTree[Idx].get(), P);
19503 }
19504
19505 // Narrow store trees with non-profitable immediate values - exit.
19506 if (!UserIgnoreList && getRootNode().getVectorFactor() < MinVF &&
19507 getRootNode().hasState() &&
19508 getRootNode().getOpcode() == Instruction::Store &&
19509 (Worklist.top().first->Idx == 0 || Worklist.top().first->Idx == 1))
19510 return Cost;
19511
19512 bool Changed = false;
19513 bool PreferTrimmedTree = false;
19514 while (!Worklist.empty() && std::get<0>(Worklist.top().second) > 0) {
19515 TreeEntry *TE = Worklist.top().first;
19516 if (TE->isGather() || TE->Idx == 0 || DeletedNodes.contains(TE) ||
19517 isa<StructType>(getValueType(TE->Scalars.front(), SLPReVec)) ||
19518 // Exit early if the parent node is split node and any of scalars is
19519 // used in other split nodes.
19520 (TE->UserTreeIndex &&
19521 TE->UserTreeIndex.UserTE->State == TreeEntry::SplitVectorize &&
19522 any_of(TE->Scalars, [&](Value *V) {
19523 ArrayRef<TreeEntry *> Entries = getSplitTreeEntries(V);
19524 return Entries.size() > 1;
19525 }))) {
19526 Worklist.pop();
19527 continue;
19528 }
19529 // Skip inversed compare nodes, they cannot be transformed to buildvectors.
19530 if (TE->State == TreeEntry::Vectorize && !TE->isAltShuffle() &&
19531 (TE->getOpcode() == Instruction::ICmp ||
19532 TE->getOpcode() == Instruction::FCmp) &&
19533 any_of(TE->Scalars, [&](Value *V) {
19534 auto *I = dyn_cast<CmpInst>(V);
19535 if (!I)
19536 return false;
19537 return I->getPredicate() !=
19538 cast<CmpInst>(TE->getMainOp())->getPredicate();
19539 })) {
19540 Worklist.pop();
19541 continue;
19542 }
19543
19544 // Calculate the gather cost of the root node.
19545 InstructionCost TotalSubtreeCost = std::get<0>(Worklist.top().second);
19546 InstructionCost SubtreeCost = std::get<1>(Worklist.top().second);
19547 if (TotalSubtreeCost < TE->Scalars.size()) {
19548 Worklist.pop();
19549 continue;
19550 }
19551 if (!TransformedToGatherNodes.empty()) {
19552 for (unsigned Idx : std::get<2>(Worklist.top().second)) {
19553 auto It = TransformedToGatherNodes.find(VectorizableTree[Idx].get());
19554 if (It != TransformedToGatherNodes.end()) {
19555 TotalSubtreeCost -= std::get<0>(SubtreeCosts[Idx]);
19556 SubtreeCost -= std::get<1>(SubtreeCosts[Idx]);
19557 TotalSubtreeCost += It->second;
19558 SubtreeCost += It->second;
19559 }
19560 }
19561 }
19562 if (TotalSubtreeCost < 0 || TotalSubtreeCost < TE->Scalars.size()) {
19563 Worklist.pop();
19564 continue;
19565 }
19566 const unsigned EntryVF = TE->getVectorFactor();
19567 APInt DemandedElts = APInt::getZero(EntryVF);
19568 for (auto [Idx, V] : enumerate(TE->Scalars)) {
19569 if (!isConstant(V))
19570 DemandedElts.setBit(Idx);
19571 }
19572
19573 Type *ScalarTy = getValueType(TE->Scalars.front(), SLPReVec);
19574 auto It = MinBWs.find(TE);
19575 if (It != MinBWs.end())
19576 ScalarTy = IntegerType::get(ScalarTy->getContext(), It->second.first);
19577 auto *VecTy = getWidenedType(ScalarTy, EntryVF);
19579 *TTI, SLPReVec, ScalarTy, cast<VectorType>(VecTy), DemandedElts,
19580 /*Insert=*/true, /*Extract=*/false, CostKind);
19581 SmallVector<int> Mask;
19582 if (!TE->ReorderIndices.empty() &&
19583 TE->State != TreeEntry::CompressVectorize &&
19584 (TE->State != TreeEntry::StridedVectorize ||
19585 !isReverseOrder(TE->ReorderIndices))) {
19586 SmallVector<int> NewMask;
19587 if (TE->getOpcode() == Instruction::Store) {
19588 // For stores the order is actually a mask.
19589 NewMask.resize(TE->ReorderIndices.size());
19590 copy(TE->ReorderIndices, NewMask.begin());
19591 } else {
19592 inversePermutation(TE->ReorderIndices, NewMask);
19593 }
19594 addMask(Mask, NewMask);
19595 }
19596 if (!TE->ReuseShuffleIndices.empty())
19597 addMask(Mask, TE->ReuseShuffleIndices);
19598 if (!Mask.empty() && !ShuffleVectorInst::isIdentityMask(Mask, EntryVF))
19599 GatherCost += getShuffleCost(*TTI, TTI::SK_PermuteSingleSrc,
19600 cast<VectorType>(VecTy), CostKind, Mask);
19601 // If all scalars are reused in gather node(s) or other vector nodes, there
19602 // might be extra cost for inserting them.
19603 if ((!TE->hasState() || !TE->isAltShuffle()) &&
19604 all_of(TE->Scalars, [&](Value *V) {
19605 return (TE->hasCopyableElements() && TE->isCopyableElement(V)) ||
19606 isConstant(V) || isGathered(V) || getTreeEntries(V).size() > 1;
19607 }))
19608 GatherCost *= 2;
19609 // Erase subtree if it is non-profitable.
19610 ArrayRef<unsigned> Nodes = std::get<2>(Worklist.top().second);
19611 // Prefer trimming equal-cost alternate-shuffle subtrees rooted at binary
19612 // ops: alt-shuffles introduce runtime shuffle overhead that the cost model
19613 // may underestimate. Skip if the subtree contains ExtractElement nodes,
19614 // since those operate on already-materialized vectors where the cost model
19615 // is more accurate.
19616 auto IsEqualCostAltShuffleToTrim = [&]() {
19617 return TotalSubtreeCost == GatherCost && TE->hasState() &&
19618 TE->isAltShuffle() && Instruction::isBinaryOp(TE->getOpcode()) &&
19619 none_of(Nodes, [&](unsigned Idx) {
19620 return VectorizableTree[Idx]->hasState() &&
19621 VectorizableTree[Idx]->getOpcode() ==
19622 Instruction::ExtractElement;
19623 });
19624 };
19625 // Non-power-of-2 entries may have inflated costs - add a margin of 1
19626 // before trimming to avoid over-pruning.
19627 bool HasNonPowerOf2 = any_of(Nodes, [&](unsigned Idx) {
19628 return !has_single_bit(VectorizableTree[Idx]->Scalars.size());
19629 });
19630 InstructionCost TrimMargin = HasNonPowerOf2 ? 1 : 0;
19631 if (TotalSubtreeCost > GatherCost + TrimMargin ||
19632 IsEqualCostAltShuffleToTrim()) {
19633 PreferTrimmedTree |= TotalSubtreeCost == GatherCost;
19634 // If the remaining tree is just a buildvector - exit, it will cause
19635 // endless attempts to vectorize. When the tree is already profitable,
19636 // skip trimming this node and let the post-loop logic (including
19637 // gathered loads processing) decide.
19638 if (getRootNode().hasState() &&
19639 getRootNode().getOpcode() == Instruction::InsertElement &&
19640 TE->Idx == 1) {
19641 if (Cost < -SLPCostThreshold) {
19642 LLVM_DEBUG(dbgs() << "SLP: Skipping trim of node " << TE->Idx
19643 << " - tree already profitable with cost " << Cost
19644 << ".\n");
19645 Worklist.pop();
19646 continue;
19647 }
19648 return InstructionCost::getInvalid();
19649 }
19650
19651 LLVM_DEBUG(dbgs() << "SLP: Trimming unprofitable subtree at node "
19652 << TE->Idx << " with cost "
19653 << std::get<0>(Worklist.top().second)
19654 << " and gather cost " << GatherCost << ".\n");
19655 if (TE->UserTreeIndex) {
19656 TransformedToGatherNodes.try_emplace(TE, GatherCost);
19657 NodesCosts.erase(TE);
19658 } else {
19659 DeletedNodes.insert(TE);
19660 TransformedToGatherNodes.erase(TE);
19661 NodesCosts.erase(TE);
19662 }
19663 for (unsigned Idx : Nodes) {
19664 TreeEntry &ChildTE = *VectorizableTree[Idx];
19665 DeletedNodes.insert(&ChildTE);
19666 TransformedToGatherNodes.erase(&ChildTE);
19667 NodesCosts.erase(&ChildTE);
19668 }
19669 Changed = true;
19670 }
19671 Worklist.pop();
19672 }
19673 if (!Changed) {
19674 // The splat subtrees are not linked to the tree root, so their cost is
19675 // not included in the root's subtree cost; add it explicitly.
19676 InstructionCost TotalCost = std::get<1>(SubtreeCosts.front());
19677 for (const TreeEntry *TE : SplatGatheredScalarsRoots)
19678 TotalCost += std::get<1>(SubtreeCosts[TE->Idx]);
19679 return TotalCost;
19680 }
19681
19682 SmallPtrSet<TreeEntry *, 4> SubtreesToDelete;
19683 SmallPtrSet<TreeEntry *, 4> DroppedSplatSubtrees;
19684 InstructionCost LoadsExtractsCost = 0;
19685 using ValuesToInsertTy =
19686 SmallDenseMap<const TreeEntry *, SmallVector<Value *>>;
19687 auto GetScalarTy = [&](const TreeEntry *TE) {
19688 Type *ScalarTy = TE->Scalars.front()->getType();
19689 auto It = MinBWs.find(TE);
19690 if (It != MinBWs.end())
19691 ScalarTy = IntegerType::get(ScalarTy->getContext(), It->second.first);
19692 return ScalarTy;
19693 };
19694 // Lanes of the subtree scalars used by the surviving gather nodes, and the
19695 // values to materialize in those gathers if the subtree is deleted.
19696 auto FindDemandedElts = [&](TreeEntry *TE, ValuesToInsertTy &ValuesToInsert) {
19697 APInt DemandedElts = APInt::getZero(TE->getVectorFactor());
19698 for (Value *V : TE->Scalars) {
19699 unsigned Pos = TE->findLaneForValue(V);
19700 for (const TreeEntry *BVE : ValueToGatherNodes.lookup(V)) {
19701 if (DeletedNodes.contains(BVE))
19702 continue;
19703 DemandedElts.setBit(Pos);
19704 ValuesToInsert.try_emplace(BVE).first->second.push_back(V);
19705 }
19706 }
19707 return DemandedElts;
19708 };
19709 // Cost of materializing the values directly in the surviving gather nodes
19710 // that use them.
19711 auto GetGatherInsertCost = [&](Type *ScalarTy,
19712 const ValuesToInsertTy &ValuesToInsert) {
19713 InstructionCost BVCost = 0;
19714 for (const auto &[BVE, Values] : ValuesToInsert) {
19715 APInt BVDemandedElts = APInt::getZero(BVE->getVectorFactor());
19716 SmallVector<Value *> BVValues(BVE->getVectorFactor(),
19717 PoisonValue::get(ScalarTy));
19718 for (Value *V : Values) {
19719 unsigned Pos = BVE->findLaneForValue(V);
19720 BVValues[Pos] = V;
19721 BVDemandedElts.setBit(Pos);
19722 }
19723 BVCost += getScalarizationOverhead(
19724 *TTI, SLPReVec, ScalarTy,
19725 cast<VectorType>(getWidenedType(ScalarTy, BVE->getVectorFactor())),
19726 BVDemandedElts, /*Insert=*/true, /*Extract=*/false, CostKind,
19727 BVDemandedElts.isAllOnes(), BVValues);
19728 }
19729 return BVCost;
19730 };
19731 // Check if all loads of gathered loads nodes are marked for deletion. In this
19732 // case the whole gathered loads subtree must be deleted.
19733 // Also, try to account for extracts, which might be required, if only part of
19734 // gathered load must be vectorized. Keep partially vectorized nodes, if
19735 // extracts are cheaper than gathers.
19736 for (TreeEntry *TE : GatheredLoadsNodes) {
19737 if (DeletedNodes.contains(TE) || TransformedToGatherNodes.contains(TE))
19738 continue;
19739 SubtreesToDelete.insert(TE);
19740 // All loads are removed from gathered? Need to delete the subtree.
19741 ValuesToInsertTy ValuesToInsert;
19742 APInt DemandedElts = FindDemandedElts(TE, ValuesToInsert);
19743 if (!DemandedElts.isZero()) {
19744 Type *ScalarTy = GetScalarTy(TE);
19745 auto *VecTy = getWidenedType(ScalarTy, TE->getVectorFactor());
19747 *TTI, SLPReVec, ScalarTy, cast<VectorType>(VecTy), DemandedElts,
19748 /*Insert=*/false, /*Extract=*/true, CostKind);
19749 InstructionCost BVCost = GetGatherInsertCost(ScalarTy, ValuesToInsert);
19750 if (ExtractsCost < BVCost) {
19751 LoadsExtractsCost += ExtractsCost;
19752 SubtreesToDelete.erase(TE);
19753 continue;
19754 }
19755 LoadsExtractsCost += BVCost;
19756 }
19757 NodesCosts.erase(TE);
19758 }
19759
19760 // Check if all gather nodes that reuse the splat subtrees are marked for
19761 // deletion. In this case the whole splat subtree must be deleted. If only
19762 // some of the gathers are trimmed, keeping the subtree still costs its full
19763 // price plus the extracts of the scalars used by the remaining scalar code,
19764 // while the surviving gathers can materialize the splatted scalars
19765 // directly. Drop the subtree if it does not pay off.
19766 for (TreeEntry *TE : SplatGatheredScalarsRoots) {
19767 if (DeletedNodes.contains(TE))
19768 continue;
19769 ValuesToInsertTy ValuesToInsert;
19770 APInt DemandedElts = FindDemandedElts(TE, ValuesToInsert);
19771 if (!DemandedElts.isZero()) {
19772 Type *ScalarTy = GetScalarTy(TE);
19773 // Lanes of the subtree scalars still used by the remaining scalar code
19774 // must be extracted if the subtree is kept.
19775 APInt ExtractElts = APInt::getZero(TE->getVectorFactor());
19776 for (Value *V : TE->Scalars) {
19777 if (!isa<Instruction>(V) || TE->isCopyableElement(V))
19778 continue;
19779 // Too many users - the scalar is extracted anyway.
19780 if (V->hasNUsesOrMore(UsesLimit) || any_of(V->users(), [&](User *U) {
19781 return none_of(getTreeEntries(U), [&](const TreeEntry *UseTE) {
19782 return !DeletedNodes.contains(UseTE) &&
19783 !TransformedToGatherNodes.contains(UseTE);
19784 });
19785 }))
19786 ExtractElts.setBit(TE->findLaneForValue(V));
19787 }
19789 *TTI, SLPReVec, ScalarTy,
19790 cast<VectorType>(getWidenedType(ScalarTy, TE->getVectorFactor())),
19791 ExtractElts, /*Insert=*/false, /*Extract=*/true, CostKind);
19792 // Add the cost of the subtree itself, computed before any trimming:
19793 // trimming of the subtree's own nodes would otherwise make it look
19794 // artificially cheap.
19795 KeepCost += std::get<1>(SubtreeCosts[TE->Idx]);
19796 InstructionCost DropCost = GetGatherInsertCost(ScalarTy, ValuesToInsert);
19797 if (KeepCost <= DropCost)
19798 continue;
19799 // Dropped as unprofitable: exclude its cost from the reference cost, so
19800 // the trimming of the remaining tree is not reverted because of it, and
19801 // keep it deleted even if the trimming is reverted.
19802 DroppedSplatSubtrees.insert(TE);
19803 for (unsigned Idx : std::get<2>(SubtreeCosts[TE->Idx]))
19804 DroppedSplatSubtrees.insert(VectorizableTree[Idx].get());
19805 Cost -= std::get<1>(SubtreeCosts[TE->Idx]);
19806 }
19807 // Not used by the surviving gathers or not profitable to keep.
19808 SubtreesToDelete.insert(TE);
19809 NodesCosts.erase(TE);
19810 }
19811
19812 // Deleted all subtrees rooted at gathered loads nodes or splat subtrees.
19813 for (std::unique_ptr<TreeEntry> &TE : VectorizableTree) {
19814 if (TE->UserTreeIndex &&
19815 SubtreesToDelete.contains(TE->UserTreeIndex.UserTE)) {
19816 DeletedNodes.insert(TE.get());
19817 NodesCosts.erase(TE.get());
19818 SubtreesToDelete.insert(TE.get());
19819 }
19820 if (SubtreesToDelete.contains(TE.get()))
19821 DeletedNodes.insert(TE.get());
19822 }
19823
19824 for (std::unique_ptr<TreeEntry> &TE : VectorizableTree) {
19825 if (!TE->UserTreeIndex && TransformedToGatherNodes.contains(TE.get())) {
19826 assert(TE->getOpcode() == Instruction::Load && "Expected load only.");
19827 continue;
19828 }
19829 if (DeletedNodes.contains(TE.get()))
19830 continue;
19831 // Gather costs depend on the set of vectorized nodes available for
19832 // reuse, which changes during trimming, so recalculate them for all
19833 // gather nodes, not just for the transformed ones.
19834 if (TE->isGather() || !NodesCosts.contains(TE.get())) {
19836 getEntryCost(TE.get(), VectorizedVals, CheckedExtracts);
19837 if (!C.isValid() || C == 0) {
19838 NodesCosts[TE.get()] = C;
19839 continue;
19840 }
19841 uint64_t Scale = EntryToScale.lookup(TE.get());
19842 if (!Scale)
19843 Scale = getEntryEffectiveScale(*TE);
19844 C *= Scale;
19845 NodesCosts[TE.get()] = C;
19846 }
19847 }
19848
19849 LLVM_DEBUG(dbgs() << "SLP: Recalculate costs after tree trimming.\n");
19850 InstructionCost NewCost = 0;
19851 for (const auto &P : NodesCosts) {
19852 NewCost += P.second;
19853 LLVM_DEBUG(dbgs() << "SLP: Adding cost " << P.second << " for bundle "
19854 << shortBundleName(P.first->Scalars, P.first->Idx)
19855 << ".\n"
19856 << "SLP: Current total cost = " << NewCost << "\n");
19857 }
19858 if (NewCost + LoadsExtractsCost > Cost ||
19859 (!PreferTrimmedTree && NewCost + LoadsExtractsCost == Cost)) {
19860 DeletedNodes.clear();
19861 TransformedToGatherNodes.clear();
19862 // The dropped splat subtrees stay deleted: they were excluded from the
19863 // reference cost and must not be resurrected by the revert.
19864 DeletedNodes.insert(DroppedSplatSubtrees.begin(),
19865 DroppedSplatSubtrees.end());
19866 NewCost = Cost;
19867 } else {
19868 // If the remaining tree is just a buildvector - exit, it will cause
19869 // endless attempts to vectorize.
19870 if (VectorizableTree.size() >= 2 && getRootNode().hasState() &&
19871 getRootNode().getOpcode() == Instruction::InsertElement &&
19872 TransformedToGatherNodes.contains(VectorizableTree[1].get()))
19873 return InstructionCost::getInvalid();
19874 if (VectorizableTree.size() >= 3 && getRootNode().hasState() &&
19875 getRootNode().getOpcode() == Instruction::InsertElement &&
19876 VectorizableTree[1]->hasState() &&
19877 VectorizableTree[1]->State == TreeEntry::Vectorize &&
19878 (VectorizableTree[1]->getOpcode() == Instruction::ZExt ||
19879 VectorizableTree[1]->getOpcode() == Instruction::SExt ||
19880 VectorizableTree[1]->getOpcode() == Instruction::Trunc) &&
19881 TransformedToGatherNodes.contains(VectorizableTree[2].get()))
19882 return InstructionCost::getInvalid();
19883 }
19884 return NewCost;
19885}
19886
19887namespace {
19888/// Data type for handling buildvector sequences with the reused scalars from
19889/// other tree entries.
19890template <typename T> struct ShuffledInsertData {
19891 /// List of insertelements to be replaced by shuffles.
19892 SmallVector<InsertElementInst *> InsertElements;
19893 /// The parent vectors and shuffle mask for the given list of inserts.
19894 MapVector<T, SmallVector<int>> ValueMasks;
19895};
19896} // namespace
19897
19899 ArrayRef<Value *> VectorizedVals,
19900 InstructionCost ReductionCost,
19901 Instruction *RdxRoot) {
19902 // A poor-throughput entry's real vector-vs-scalar savings (fdiv/frem/fsqrt)
19903 // are already folded into TreeCost like any other entry, including all
19904 // shuffle/insert/extract overhead elsewhere in the tree. So bypassing the
19905 // instruction-count veto below just has to trust that already-complete
19906 // TreeCost instead of guessing at extra savings: heavy gather/shuffle
19907 // overhead raises TreeCost too, and will still block the bypass.
19908 auto BypassesInstCountCheck = [&]() {
19909 if (!VectorizePoorThroughput || TreeCost >= -SLPCostThreshold)
19910 return false;
19911 PoorThroughputOpCache Cache;
19912 return any_of(VectorizableTree, [&](const std::unique_ptr<TreeEntry> &Ptr) {
19913 const TreeEntry &TE = *Ptr;
19914 return TE.hasState() && !DeletedNodes.contains(&TE) && !TE.isGather() &&
19915 !TransformedToGatherNodes.contains(&TE) &&
19916 TE.State != TreeEntry::CombinedVectorize &&
19917 isPoorThroughputOp(TE.getMainOp(), *TTI, *TLI, Cache, CostKind);
19918 });
19919 };
19920 // Reject vectorization if the vector code would produce more instructions
19921 // than the scalar code. The cost model may underestimate overhead from
19922 // shuffles, inserts, and extracts.
19923 // FIXME: remove this as soon as correct fractional model is landed for all
19924 // targets.
19925 if (CostKind != TTI::TCK_CodeSize && SLPInstCountCheck &&
19926 TTI->preferSLPInstCountCheck() && getRootNode().getVectorFactor() == 2 &&
19927 SLPCostThreshold == 0 &&
19928 (!SLPReVec ||
19929 !isa<VectorType>(getRootNodeScalars().front()->getType()))) {
19930 // Loop containing the tree root; null for flat code or disabled
19931 // loop-aware modeling. Shared by both calls below.
19932 const Loop *TreeLoop = nullptr;
19933 if (LoopAwareTripCount != 0 && getRootNode().hasState())
19934 TreeLoop = LI->getLoopFor(getRootNode().getMainOp()->getParent());
19935 uint64_t NumScalar = getNumScalarInsts(TreeLoop);
19936 uint64_t NumVector = getNumVectorInsts(TreeLoop);
19937 LLVM_DEBUG(dbgs() << "SLP: Inst count check: vector=" << NumVector
19938 << " scalar=" << NumScalar << "\n");
19939 if (NumVector > NumScalar && !BypassesInstCountCheck()) {
19940 LLVM_DEBUG(dbgs() << "SLP: Rejecting tree: vector inst count "
19941 << NumVector << " > scalar inst count " << NumScalar
19942 << ".\n");
19944 }
19945 }
19946 InstructionCost Cost = TreeCost;
19947
19949 EntryToScale;
19950 auto ScaleCost = [&](InstructionCost C, const TreeEntry &TE,
19951 Value *Scalar = nullptr, Instruction *U = nullptr) {
19952 if (!C.isValid() || C == 0)
19953 return C;
19954 uint64_t &Scale =
19955 EntryToScale.try_emplace(std::make_tuple(&TE, Scalar, U), 0)
19956 .first->getSecond();
19957 if (!Scale)
19958 Scale = getScaleToLoopIterations(TE, Scalar, U);
19959 LLVM_DEBUG(dbgs() << "Scale " << Scale << " For entry " << TE.Idx << "\n");
19960 return C * Scale;
19961 };
19962 Instruction *ReductionRoot = RdxRoot;
19963 if (UserIgnoreList) {
19964 // Scale reduction cost to the factor of the loop nest trip count.
19965 ReductionCost = ScaleCost(ReductionCost, getRootNode(), /*Scalar=*/nullptr,
19966 ReductionRoot);
19967 }
19968
19969 // Add the cost for reduction.
19970 Cost += ReductionCost;
19971
19972 if (any_of(ExternalUses, [](const ExternalUser &EU) {
19973 return isa<StructType>(EU.Scalar->getType()) &&
19974 (EU.E.Idx != 0 || EU.E.State != TreeEntry::Vectorize ||
19975 EU.E.getOpcode() != Instruction::InsertValue) &&
19977 }))
19979
19980 // Skip trees, which are non-profitable even if there are insertelements with
19981 // external uses.
19982 constexpr unsigned CostLimit = 100;
19983 if (Cost >= -SLPCostThreshold + CostLimit &&
19984 (VectorizableTree.size() - DeletedNodes.size()) *
19985 getRootNode().getVectorFactor() <
19986 CostLimit)
19987 return Cost;
19988
19989 if (Cost >= -SLPCostThreshold &&
19990 none_of(ExternalUses, [](const ExternalUser &EU) {
19991 return isa_and_nonnull<InsertElementInst>(EU.User);
19992 }))
19993 return Cost;
19994
19996 ExtractCostCalculated;
19997 InstructionCost ExtractCost = 0;
19999 SmallVector<APInt> DemandedElts;
20000 SmallDenseSet<Value *, 4> UsedInserts;
20002 std::optional<DenseMap<Value *, unsigned>> ValueToExtUses;
20004 SmallPtrSet<Value *, 4> ScalarOpsFromCasts;
20005 // Keep track {Scalar, Index, User} tuple.
20006 // On AArch64, this helps in fusing a mov instruction, associated with
20007 // extractelement, with fmul in the backend so that extractelement is free.
20009 // Record every external use: a missing entry is indistinguishable from
20010 // lane 0 and is priced as a free extract by the extract-fusion cost model.
20011 for (ExternalUser &EU : ExternalUses)
20012 ScalarUserAndIdx.emplace_back(EU.Scalar, EU.User, EU.Lane);
20013 // Detect external uses that drive address computations: the scalar (through
20014 // an optional single-use index-promotion cast) is used as a GEP index.
20015 bool AllUsersGEPSWithStoresLoads = true;
20017 Type *UserScalarTy = nullptr;
20018 for (ExternalUser &EU : ExternalUses) {
20019 Value *Usr = EU.User;
20020 if (Usr && match(Usr, m_OneUse(m_ZExtOrSExt(m_Value()))))
20021 Usr = cast<Instruction>(Usr)->user_back();
20023 // Only a GEP that feeds a single load/store of a fixed access type drives
20024 // a real memory address computation.
20025 Type *AccessTy = nullptr;
20026 if (User && User->hasOneUse() &&
20028 AccessTy = getValueType(User->user_back(), SLPReVec);
20029 if (AccessTy && !isa<ScalableVectorType>(AccessTy) &&
20030 (!UserScalarTy || UserScalarTy == AccessTy)) {
20031 UserScalarTy = AccessTy;
20032 Pointers.push_back(User);
20033 } else {
20034 AllUsersGEPSWithStoresLoads = false;
20035 break;
20036 }
20037 }
20038
20039 // Pre-pass: for each externally-used scalar, find the basic block at which
20040 // the extractelement will be placed by codegen. This mirrors what
20041 // vectorizeTree does: the extract is placed at the nearest common dominator
20042 // of all effective use sites. For a non-PHI user the effective site is the
20043 // user's own block; for a PHI user it is the incoming block for the scalar
20044 // operand (the predecessor of the PHI on the edge that carries the scalar).
20045 // Using the NCD of all effective sites rather than the first-encountered
20046 // user's block makes the extract-cost scale order-independent and correct
20047 // even when users live in different loop nests.
20048 SmallDenseMap<Value *, BasicBlock *> ScalarToExtractBlock;
20049 for (const ExternalUser &EU : ExternalUses) {
20050 if (!EU.User || isa<InsertElementInst>(EU.User))
20051 continue;
20052 if (EphValues.count(EU.User))
20053 continue;
20054 BasicBlock *UserParent = cast<Instruction>(EU.User)->getParent();
20055 if (!DT->isReachableFromEntry(UserParent) || UserParent->isEHPad() ||
20057 continue;
20058 BasicBlock *UseBlock = nullptr;
20059 if (auto *PHI = dyn_cast<PHINode>(EU.User)) {
20060 // When the PHI itself is inside a loop, the extractelement is placed
20061 // in the incoming block for the scalar operand (the predecessor edge),
20062 // not in the PHI's own block. This applies to LCSSA phis at an inner-
20063 // loop exit that are still inside an outer loop: the incoming block is
20064 // in the inner loop while the PHI block is in the outer loop.
20065 // When the PHI is outside all loops (a true loop-exit phi), codegen
20066 // uses a vector phi at the exit block and the extract stays there
20067 // (scale = 1), so we keep the PHI's own block as the effective site.
20068 if (LI->getLoopFor(PHI->getParent())) {
20069 for (unsigned Idx : seq<unsigned>(PHI->getNumIncomingValues())) {
20070 if (PHI->getIncomingValue(Idx) != EU.Scalar)
20071 continue;
20072 BasicBlock *InBB = PHI->getIncomingBlock(Idx);
20073 UseBlock =
20074 UseBlock ? DT->findNearestCommonDominator(UseBlock, InBB) : InBB;
20075 }
20076 }
20077 if (!UseBlock)
20078 UseBlock = cast<Instruction>(EU.User)->getParent();
20079 } else {
20080 UseBlock = cast<Instruction>(EU.User)->getParent();
20081 }
20082 auto [It, Inserted] = ScalarToExtractBlock.try_emplace(EU.Scalar, UseBlock);
20083 if (!Inserted && It->second && UseBlock)
20084 It->second = DT->findNearestCommonDominator(It->second, UseBlock);
20085 }
20086
20087 SmallDenseSet<std::pair<Value *, Value *>, 8> CheckedScalarUser;
20088 for (ExternalUser &EU : ExternalUses) {
20089 LLVM_DEBUG(dbgs() << "SLP: Computing cost for external use of TreeEntry "
20090 << EU.E.Idx << " in lane " << EU.Lane << "\n");
20091 LLVM_DEBUG(if (EU.User) dbgs() << " User:" << *EU.User << "\n";
20092 else dbgs() << " User: nullptr\n");
20093 LLVM_DEBUG(dbgs() << " Use: " << EU.Scalar->getNameOrAsOperand() << "\n");
20094
20095 // Uses by ephemeral values are free (because the ephemeral value will be
20096 // removed prior to code generation, and so the extraction will be
20097 // removed as well).
20098 if (EphValues.count(EU.User))
20099 continue;
20100
20101 // Check if the scalar for the given user or all users is accounted already.
20102 if (!CheckedScalarUser.insert(std::make_pair(EU.Scalar, EU.User)).second ||
20103 (EU.User &&
20104 CheckedScalarUser.contains(std::make_pair(EU.Scalar, nullptr))))
20105 continue;
20106
20107 // Used in unreachable blocks or in EH pads (rarely executed) or is
20108 // terminated with unreachable instruction.
20109 if (BasicBlock *UserParent =
20110 EU.User ? cast<Instruction>(EU.User)->getParent() : nullptr;
20111 UserParent &&
20112 (!DT->isReachableFromEntry(UserParent) || UserParent->isEHPad() ||
20113 isa_and_present<UnreachableInst>(UserParent->getTerminator())))
20114 continue;
20115
20116 // No extract cost for vector "scalar" if REVEC is disabled.
20117 if (isVectorizedTy(EU.Scalar->getType()) &&
20118 (!SLPReVec ||
20119 (EU.E.hasState() && EU.E.getOpcode() == Instruction::InsertElement)))
20120 continue;
20121
20122 if (isa<InsertValueInst>(EU.Scalar))
20123 continue;
20124
20125 // If found user is an insertelement, do not calculate extract cost but try
20126 // to detect it as a final shuffled/identity match.
20127 // TODO: what if a user is insertvalue when REVEC is enabled?
20128 if (auto *VU = dyn_cast_or_null<InsertElementInst>(EU.User);
20129 VU && VU->getOperand(1) == EU.Scalar) {
20130 if (auto *FTy = dyn_cast<FixedVectorType>(VU->getType())) {
20131 if (!UsedInserts.insert(VU).second)
20132 continue;
20133 std::optional<unsigned> InsertIdx = getElementIndex(VU);
20134 if (InsertIdx) {
20135 const TreeEntry *ScalarTE = &EU.E;
20136 auto *It = find_if(
20137 ShuffledInserts,
20138 [this, VU](const ShuffledInsertData<const TreeEntry *> &Data) {
20139 // Checks if 2 insertelements are from the same buildvector.
20140 InsertElementInst *VecInsert = Data.InsertElements.front();
20142 VU, VecInsert, [this](InsertElementInst *II) -> Value * {
20143 Value *Op0 = II->getOperand(0);
20144 if (isVectorized(II) && !isVectorized(Op0))
20145 return nullptr;
20146 return Op0;
20147 });
20148 });
20149 int VecId = -1;
20150 if (It == ShuffledInserts.end()) {
20151 auto &Data = ShuffledInserts.emplace_back();
20152 Data.InsertElements.emplace_back(VU);
20153 DemandedElts.push_back(APInt::getZero(FTy->getNumElements()));
20154 VecId = ShuffledInserts.size() - 1;
20155 auto It = MinBWs.find(ScalarTE);
20156 if (It != MinBWs.end() &&
20157 VectorCasts
20158 .insert(std::make_pair(ScalarTE, FTy->getElementType()))
20159 .second) {
20160 unsigned BWSz = It->second.first;
20161 unsigned DstBWSz = DL->getTypeSizeInBits(FTy->getElementType());
20162 unsigned VecOpcode;
20163 if (DstBWSz < BWSz)
20164 VecOpcode = Instruction::Trunc;
20165 else
20166 VecOpcode =
20167 It->second.second ? Instruction::SExt : Instruction::ZExt;
20168 InstructionCost C = TTI->getCastInstrCost(
20169 VecOpcode, FTy,
20170 getWidenedType(IntegerType::get(FTy->getContext(), BWSz),
20171 FTy->getNumElements()),
20172 TTI::CastContextHint::None, CostKind);
20173 LLVM_DEBUG(dbgs() << "SLP: Adding cost " << C
20174 << " for extending externally used vector with "
20175 "non-equal minimum bitwidth.\n");
20176 Cost += C;
20177 }
20178 } else {
20179 if (isFirstInsertElement(VU, It->InsertElements.front()))
20180 It->InsertElements.front() = VU;
20181 VecId = std::distance(ShuffledInserts.begin(), It);
20182 }
20183 int InIdx = *InsertIdx;
20184 SmallVectorImpl<int> &Mask =
20185 ShuffledInserts[VecId].ValueMasks[ScalarTE];
20186 if (Mask.empty())
20187 Mask.assign(FTy->getNumElements(), PoisonMaskElem);
20188 Mask[InIdx] = EU.Lane;
20189 DemandedElts[VecId].setBit(InIdx);
20190 continue;
20191 }
20192 }
20193 }
20194
20195 // If we plan to rewrite the tree in a smaller type, we will need to sign
20196 // extend the extracted value back to the original type. Here, we account
20197 // for the extract and the added cost of the sign extend if needed.
20198 InstructionCost ExtraCost = TTI::TCC_Free;
20199 auto *ScalarTy = EU.Scalar->getType();
20200 const unsigned BundleWidth = EU.E.getVectorFactor();
20201 assert(EU.Lane < BundleWidth && "Extracted lane out of bounds.");
20202 auto *VecTy = getWidenedType(ScalarTy, BundleWidth);
20203 const TreeEntry *Entry = &EU.E;
20204 auto It = MinBWs.find(Entry);
20206 if (isa<StructType>(VecTy)) {
20207 assert(EU.User && "Expected user for struct extract");
20208 const auto *EV = cast<ExtractValueInst>(EU.User);
20209 Indices.assign(EV->getIndices());
20210 }
20211 // We only add extract cost once for the same scalar and struct field.
20212 auto ExtractKey = std::make_pair(EU.Scalar, Indices);
20213 if (!isa_and_nonnull<InsertElementInst>(EU.User) &&
20214 !ExtractCostCalculated.insert(ExtractKey).second)
20215 continue;
20216 if (It != MinBWs.end()) {
20217 Type *MinTy = IntegerType::get(F->getContext(), It->second.first);
20218 if (auto *VecTy = dyn_cast<FixedVectorType>(ScalarTy))
20219 MinTy = getWidenedType(MinTy, VecTy->getNumElements());
20220 unsigned Extend = isKnownNonNegative(EU.Scalar, SimplifyQuery(*DL))
20221 ? Instruction::ZExt
20222 : Instruction::SExt;
20223 VecTy = getWidenedType(MinTy, BundleWidth);
20224 ExtraCost =
20225 getExtractWithExtendCost(*TTI, SLPReVec, Extend, ScalarTy,
20226 cast<VectorType>(VecTy), EU.Lane, CostKind);
20227 LLVM_DEBUG(dbgs() << " ExtractExtend or ExtractSubvec cost: "
20228 << ExtraCost << "\n");
20229 } else {
20230 Type *ExtractTy = VecTy;
20231 if (auto *ST = dyn_cast<StructType>(VecTy)) {
20232 ExtractTy = ExtractValueInst::getIndexedType(ST, Indices);
20233 }
20234 ExtraCost = getVectorInstrCost(
20235 *TTI, SLPReVec, ScalarTy, Instruction::ExtractElement, ExtractTy,
20236 CostKind, EU.Lane, EU.Scalar, ScalarUserAndIdx);
20237 LLVM_DEBUG(dbgs() << " ExtractElement cost for " << *ScalarTy << " from "
20238 << *VecTy << ": " << ExtraCost << "\n");
20239 }
20240 // Leave the scalar instructions as is if they are cheaper than extracts.
20241 if (Entry->Idx != 0 || Entry->getOpcode() == Instruction::GetElementPtr ||
20242 Entry->getOpcode() == Instruction::Load) {
20243 // Checks if the user of the external scalar is phi in loop body.
20244 auto IsPhiInLoop = [&](const ExternalUser &U) {
20245 if (auto *Phi = dyn_cast_if_present<PHINode>(U.User)) {
20246 auto *I = cast<Instruction>(U.Scalar);
20247 const Loop *L = LI->getLoopFor(Phi->getParent());
20248 return L && (Phi->getParent() == I->getParent() ||
20249 L == LI->getLoopFor(I->getParent()));
20250 }
20251 return false;
20252 };
20253 if (!ValueToExtUses) {
20254 ValueToExtUses.emplace();
20255 for (const auto &P : enumerate(ExternalUses)) {
20256 // Ignore phis in loops.
20257 if (IsPhiInLoop(P.value()))
20258 continue;
20259
20260 ValueToExtUses->try_emplace(P.value().Scalar, P.index());
20261 }
20262 }
20263 // Can use original instruction, if no operands vectorized or they are
20264 // marked as externally used already.
20265 auto *Inst = cast<Instruction>(EU.Scalar);
20266 InstructionCost ScalarCost = TTI->getInstructionCost(Inst, CostKind);
20267 auto OperandIsScalar = [&](Value *V) {
20268 if (!isVectorized(V)) {
20269 // Some extractelements might be not vectorized, but
20270 // transformed into shuffle and removed from the function,
20271 // consider it here.
20272 if (auto *EE = dyn_cast<ExtractElementInst>(V))
20273 return !EE->hasOneUse() || !MustGather.contains(EE);
20274 return true;
20275 }
20276 if (isa<StructType>(V->getType()))
20277 return false;
20278 return ValueToExtUses->contains(V);
20279 };
20280 bool CanBeUsedAsScalar = all_of(Inst->operands(), OperandIsScalar);
20281 bool CanBeUsedAsScalarCast = false;
20282 if (auto *CI = dyn_cast<CastInst>(Inst); CI && !CanBeUsedAsScalar) {
20283 if (auto *Op = dyn_cast<Instruction>(CI->getOperand(0));
20284 Op && all_of(Op->operands(), OperandIsScalar)) {
20285 InstructionCost OpCost =
20286 (isVectorized(Op) && !ValueToExtUses->contains(Op))
20287 ? TTI->getInstructionCost(Op, CostKind)
20288 : 0;
20289 if (ScalarCost + OpCost <= ExtraCost) {
20290 CanBeUsedAsScalar = CanBeUsedAsScalarCast = true;
20291 ScalarCost += OpCost;
20292 }
20293 }
20294 }
20295 if (CanBeUsedAsScalar) {
20296 bool KeepScalar = ScalarCost <= ExtraCost;
20297 // Try to keep original scalar if the user is the phi node from the same
20298 // block as the root phis, currently vectorized. It allows to keep
20299 // better ordering info of PHIs, being vectorized currently.
20300 bool IsProfitablePHIUser =
20301 (KeepScalar || (ScalarCost - ExtraCost <= TTI::TCC_Basic &&
20302 getRootNodeScalars().size() > 2)) &&
20303 getRootNode().hasState() &&
20304 getRootNode().getOpcode() == Instruction::PHI &&
20305 !Inst->hasNUsesOrMore(UsesLimit) &&
20306 none_of(Inst->users(),
20307 [&](User *U) {
20308 auto *PHIUser = dyn_cast<PHINode>(U);
20309 return (!PHIUser ||
20310 PHIUser->getParent() !=
20311 getRootNode().getMainOp()->getParent()) &&
20312 !isVectorized(U);
20313 }) &&
20314 count_if(Entry->Scalars, [&](Value *V) {
20315 return ValueToExtUses->contains(V);
20316 }) <= 2;
20317 if (IsProfitablePHIUser) {
20318 KeepScalar = true;
20319 } else if (KeepScalar && ScalarCost != TTI::TCC_Free &&
20320 ExtraCost - ScalarCost <= TTI::TCC_Basic &&
20321 (!GatheredLoadsEntriesFirst.has_value() ||
20322 Entry->Idx < *GatheredLoadsEntriesFirst)) {
20323 unsigned ScalarUsesCount = count_if(Entry->Scalars, [&](Value *V) {
20324 return ValueToExtUses->contains(V);
20325 });
20326 auto It = ExtractsCount.find(Entry);
20327 if (It != ExtractsCount.end()) {
20328 assert(ScalarUsesCount >= It->getSecond().size() &&
20329 "Expected total number of external uses not less than "
20330 "number of scalar uses.");
20331 ScalarUsesCount -= It->getSecond().size();
20332 }
20333 // Keep original scalar if number of externally used instructions in
20334 // the same entry is not power of 2. It may help to do some extra
20335 // vectorization for now.
20336 KeepScalar = ScalarUsesCount <= 1 || !has_single_bit(ScalarUsesCount);
20337 }
20338 if (KeepScalar) {
20339 ExternalUsesAsOriginalScalar.insert(EU.Scalar);
20340 for (Value *V : Inst->operands()) {
20341 // Struct operands cannot be rebuilt by the !User extraction
20342 // path (it has no insertvalue chain), so leave their existing
20343 // ExtractValueInst user in place.
20344 if (isa<StructType>(V->getType()))
20345 continue;
20346 auto It = ValueToExtUses->find(V);
20347 if (It != ValueToExtUses->end()) {
20348 // Replace all uses to avoid compiler crash.
20349 ExternalUses[It->second].User = nullptr;
20350 }
20351 }
20352 ExtraCost = ScalarCost;
20353 if (!IsPhiInLoop(EU))
20354 ExtractsCount[Entry].insert(Inst);
20355 if (CanBeUsedAsScalarCast) {
20356 ScalarOpsFromCasts.insert(Inst->getOperand(0));
20357 // Update the users of the operands of the cast operand to avoid
20358 // compiler crash.
20359 if (auto *IOp = dyn_cast<Instruction>(Inst->getOperand(0))) {
20360 for (Value *V : IOp->operands()) {
20361 if (isa<StructType>(V->getType()))
20362 continue;
20363 auto It = ValueToExtUses->find(V);
20364 if (It != ValueToExtUses->end()) {
20365 // Replace all uses to avoid compiler crash.
20366 ExternalUses[It->second].User = nullptr;
20367 }
20368 }
20369 }
20370 }
20371 }
20372 }
20373 }
20374
20375 // Scale the extract cost by the execution frequency of the block where
20376 // codegen will place the extractelement. That block is the nearest common
20377 // dominator of all effective use sites (precomputed in ScalarToExtractBlock
20378 // above), which is order-independent. For scalars kept as originals the
20379 // existing ScaleCost path (user-block based) remains correct, since the
20380 // scalar instruction executes at its definition site's frequency.
20381 if (!ExternalUsesAsOriginalScalar.contains(EU.Scalar)) {
20382 if (ExtraCost.isValid() && ExtraCost != 0) {
20383 if (!EU.User) {
20384 // No external user instruction is recorded (User == nullptr): the
20385 // scalar stays live in vectorized instructions or is used as an
20386 // extra arg, and is not present in ScalarToExtractBlock (the
20387 // pre-pass only records sites of real users). vectorizeTree() then
20388 // places the extractelement right after the vectorized instruction
20389 // (in the entry's block) and replaces the scalar uses with it, so
20390 // scale by the entry block's execution frequency to match that
20391 // placement.
20392 ExtraCost = ScaleCost(ExtraCost, *Entry, EU.Scalar, /*U=*/nullptr);
20393 } else {
20394 BasicBlock *ExtractBB = ScalarToExtractBlock.lookup(EU.Scalar);
20395 if (const Loop *L = ExtractBB ? LI->getLoopFor(ExtractBB) : nullptr) {
20396 uint64_t Scale = getLoopNestScale(
20399 << "SLP: Extract scale " << Scale << " (NCD block) for "
20400 << EU.Scalar->getNameOrAsOperand() << "\n");
20401 ExtraCost *= Scale;
20402 }
20403 }
20404 }
20405 } else {
20406 ExtraCost = ScaleCost(ExtraCost, *Entry, EU.Scalar,
20407 cast_or_null<Instruction>(EU.User));
20408 }
20409
20410 ExtractCost += ExtraCost;
20411 }
20412 // Charge the pointer-chain cost difference once when every escaped scalar
20413 // is used only to drive an address computation (see the detection loop
20414 // above). Vectorizing the tree in this pattern forces lane extracts (or a
20415 // vector GEP with unknown stride) to drive the address computation, which is
20416 // typically more expensive than keeping the indices scalar in a unit-stride
20417 // address chain. Add the delta once rather than per external use.
20418 if (AllUsersGEPSWithStoresLoads && !Pointers.empty()) {
20419 const TreeEntry &RootEntry = getRootNode();
20420 const Value *CommonBase = getUnderlyingObject(Pointers.front());
20421 if (all_of(Pointers, [CommonBase](const Value *P) {
20422 return getUnderlyingObject(P) == CommonBase;
20423 })) {
20424 auto *VecTy = getWidenedType(UserScalarTy, RootEntry.Scalars.size());
20425 InstructionCost ScalarGEPCost = TTI->getPointersChainCost(
20426 Pointers, CommonBase, TTI::PointersChainInfo::getUnitStride(),
20427 UserScalarTy, CostKind);
20428 InstructionCost VectorGEPCost = TTI->getPointersChainCost(
20429 Pointers, CommonBase, TTI::PointersChainInfo::getUnknownStride(),
20430 VecTy, CostKind);
20431 ExtractCost += ScaleCost(VectorGEPCost - ScalarGEPCost, RootEntry);
20432 }
20433 }
20434 // Insert externals for extract of operands of casts to be emitted as scalars
20435 // instead of extractelement.
20436 for (Value *V : ScalarOpsFromCasts) {
20437 ExternalUsesAsOriginalScalar.insert(V);
20438 if (ArrayRef<TreeEntry *> TEs = getTreeEntries(V); !TEs.empty()) {
20439 const auto *It = find_if_not(TEs, [&](TreeEntry *TE) {
20440 return TransformedToGatherNodes.contains(TE) ||
20441 DeletedNodes.contains(TE);
20442 });
20443 if (It != TEs.end()) {
20444 const TreeEntry *UserTE = *It;
20445 ExternalUses.emplace_back(V, nullptr, *UserTE,
20446 UserTE->findLaneForValue(V));
20447 }
20448 }
20449 }
20450 // Add reduced value cost, if resized.
20451 if (!VectorizedVals.empty()) {
20452 const TreeEntry &Root = getRootNode();
20453 auto BWIt = MinBWs.find(&Root);
20454 if (BWIt != MinBWs.end()) {
20455 Type *DstTy = Root.Scalars.front()->getType();
20456 unsigned OriginalSz = DL->getTypeSizeInBits(DstTy->getScalarType());
20457 unsigned SrcSz =
20458 ReductionBitWidth == 0 ? BWIt->second.first : ReductionBitWidth;
20459 if (OriginalSz != SrcSz) {
20460 unsigned Opcode = Instruction::Trunc;
20461 if (OriginalSz > SrcSz)
20462 Opcode = BWIt->second.second ? Instruction::SExt : Instruction::ZExt;
20463 Type *SrcTy = IntegerType::get(DstTy->getContext(), SrcSz);
20464 if (auto *VecTy = dyn_cast<FixedVectorType>(DstTy)) {
20465 assert(SLPReVec && "Only supported by REVEC.");
20466 SrcTy = getWidenedType(SrcTy, VecTy->getNumElements());
20467 }
20468 InstructionCost CastCost = TTI->getCastInstrCost(
20469 Opcode, DstTy, SrcTy, TTI::CastContextHint::None, CostKind);
20470 CastCost = ScaleCost(CastCost, Root, /*Scalar=*/nullptr, ReductionRoot);
20471 Cost += CastCost;
20472 }
20473 }
20474 }
20475
20476 // Buildvector with externally used scalars, which should remain as scalars,
20477 // should not be vectorized, the compiler may hang.
20478 if (SLPCostThreshold < 0 && VectorizableTree.size() > 1 &&
20479 isa<InsertElementInst>(VectorizableTree[0]->Scalars[0]) &&
20480 VectorizableTree[1]->hasState() &&
20481 VectorizableTree[1]->State == TreeEntry::Vectorize &&
20482 all_of(VectorizableTree[1]->Scalars, [&](Value *V) {
20483 return ExternalUsesAsOriginalScalar.contains(V);
20484 }))
20486
20487 Cost += ExtractCost;
20488 auto &&ResizeToVF = [this, &Cost](const TreeEntry *TE, ArrayRef<int> Mask,
20489 bool ForSingleMask) {
20490 InstructionCost C = 0;
20491 unsigned VF = Mask.size();
20492 unsigned VecVF = TE->getVectorFactor();
20493 bool HasLargeIndex =
20494 any_of(Mask, [VF](int Idx) { return Idx >= static_cast<int>(VF); });
20495 if ((VF != VecVF && HasLargeIndex) ||
20497
20498 if (HasLargeIndex) {
20499 SmallVector<int> OrigMask(VecVF, PoisonMaskElem);
20500 std::copy(Mask.begin(), std::next(Mask.begin(), std::min(VF, VecVF)),
20501 OrigMask.begin());
20502 C = getShuffleCost(
20504 cast<VectorType>(getWidenedType(TE->getMainOp()->getType(), VecVF)),
20505 CostKind, OrigMask);
20506 LLVM_DEBUG(
20507 dbgs() << "SLP: Adding cost " << C
20508 << " for final shuffle of insertelement external users.\n";
20509 TE->dump(); dbgs() << "SLP: Current total cost = " << Cost << "\n");
20510 Cost += C;
20511 return std::make_pair(TE, true);
20512 }
20513
20514 if (!ForSingleMask) {
20515 SmallVector<int> ResizeMask(VF, PoisonMaskElem);
20516 for (unsigned I = 0; I < VF; ++I) {
20517 if (Mask[I] != PoisonMaskElem)
20518 ResizeMask[Mask[I]] = Mask[I];
20519 }
20520 if (!ShuffleVectorInst::isIdentityMask(ResizeMask, VF))
20523 TE->getMainOp()->getType(), VecVF)),
20524 CostKind, ResizeMask);
20525 LLVM_DEBUG(
20526 dbgs() << "SLP: Adding cost " << C
20527 << " for final shuffle of insertelement external users.\n";
20528 TE->dump(); dbgs() << "SLP: Current total cost = " << Cost << "\n");
20529
20530 Cost += C;
20531 }
20532 }
20533 return std::make_pair(TE, false);
20534 };
20535 // Calculate the cost of the reshuffled vectors, if any.
20536 for (int I = 0, E = ShuffledInserts.size(); I < E; ++I) {
20537 Value *Base = ShuffledInserts[I].InsertElements.front()->getOperand(0);
20538 auto Vector = ShuffledInserts[I].ValueMasks.takeVector();
20539 unsigned VF = 0;
20540 auto EstimateShufflesCost = [&](ArrayRef<int> Mask,
20542 assert((TEs.size() == 1 || TEs.size() == 2) &&
20543 "Expected exactly 1 or 2 tree entries.");
20544 if (TEs.size() == 1) {
20545 if (VF == 0)
20546 VF = TEs.front()->getVectorFactor();
20547 auto *FTy = getWidenedType(TEs.back()->Scalars.front()->getType(), VF);
20548 if (!ShuffleVectorInst::isIdentityMask(Mask, VF) &&
20549 !all_of(enumerate(Mask), [=](const auto &Data) {
20550 return Data.value() == PoisonMaskElem ||
20551 (Data.index() < VF &&
20552 static_cast<int>(Data.index()) == Data.value());
20553 })) {
20556 cast<VectorType>(FTy), CostKind, Mask);
20557 C = ScaleCost(C, *TEs.front());
20558 LLVM_DEBUG(dbgs() << "SLP: Adding cost " << C
20559 << " for final shuffle of insertelement "
20560 "external users.\n";
20561 TEs.front()->dump();
20562 dbgs() << "SLP: Current total cost = " << Cost << "\n");
20563 Cost += C;
20564 }
20565 } else {
20566 if (VF == 0) {
20567 if (TEs.front() &&
20568 TEs.front()->getVectorFactor() == TEs.back()->getVectorFactor())
20569 VF = TEs.front()->getVectorFactor();
20570 else
20571 VF = Mask.size();
20572 }
20573 auto *FTy = getWidenedType(TEs.back()->Scalars.front()->getType(), VF);
20575 *TTI, TTI::SK_PermuteTwoSrc, cast<VectorType>(FTy), CostKind, Mask);
20576 C = ScaleCost(C, *TEs.back());
20577 LLVM_DEBUG(dbgs() << "SLP: Adding cost " << C
20578 << " for final shuffle of vector node and external "
20579 "insertelement users.\n";
20580 if (TEs.front()) { TEs.front()->dump(); } TEs.back()->dump();
20581 dbgs() << "SLP: Current total cost = " << Cost << "\n");
20582 Cost += C;
20583 }
20584 VF = Mask.size();
20585 return TEs.back();
20586 };
20588 MutableArrayRef(Vector.data(), Vector.size()), Base,
20589 [](const TreeEntry *E) { return E->getVectorFactor(); }, ResizeToVF,
20590 EstimateShufflesCost);
20591 InstructionCost InsertCost = TTI->getScalarizationOverhead(
20593 ShuffledInserts[I].InsertElements.front()->getType()),
20594 DemandedElts[I],
20595 /*Insert*/ true, /*Extract*/ false, CostKind);
20596 Cost -= InsertCost;
20597 }
20598
20599 // Add the cost for reduced value resize (if required).
20600 if (ReductionBitWidth != 0) {
20601 assert(UserIgnoreList && "Expected reduction tree.");
20602 const TreeEntry &E = getRootNode();
20603 auto It = MinBWs.find(&E);
20604 if (It != MinBWs.end() && It->second.first != ReductionBitWidth) {
20605 unsigned SrcSize = It->second.first;
20606 unsigned DstSize = ReductionBitWidth;
20607 unsigned Opcode = Instruction::Trunc;
20608 if (SrcSize < DstSize) {
20609 bool IsArithmeticExtendedReduction =
20610 all_of(*UserIgnoreList, [](Value *V) {
20611 auto *I = cast<Instruction>(V);
20612 return is_contained({Instruction::Add, Instruction::FAdd,
20613 Instruction::Mul, Instruction::FMul,
20614 Instruction::And, Instruction::Or,
20615 Instruction::Xor},
20616 I->getOpcode());
20617 });
20618 if (IsArithmeticExtendedReduction)
20619 Opcode =
20620 Instruction::BitCast; // Handle it by getExtendedReductionCost
20621 else
20622 Opcode = It->second.second ? Instruction::SExt : Instruction::ZExt;
20623 }
20624 if (Opcode != Instruction::BitCast) {
20625 auto *SrcVecTy =
20626 getWidenedType(Builder.getIntNTy(SrcSize), E.getVectorFactor());
20627 auto *DstVecTy =
20628 getWidenedType(Builder.getIntNTy(DstSize), E.getVectorFactor());
20629 TTI::CastContextHint CCH = getCastContextHint(E);
20630 switch (E.getOpcode()) {
20631 case Instruction::SExt:
20632 case Instruction::ZExt:
20633 case Instruction::Trunc: {
20634 const TreeEntry *OpTE = getOperandEntry(&E, 0);
20635 CCH = getCastContextHint(*OpTE);
20636 break;
20637 }
20638 default:
20639 break;
20640 }
20641 InstructionCost CastCost =
20642 TTI->getCastInstrCost(Opcode, DstVecTy, SrcVecTy, CCH, CostKind);
20643 CastCost = ScaleCost(CastCost, getRootNode(), /*Scalar=*/nullptr,
20644 ReductionRoot);
20645 Cost += CastCost;
20646 LLVM_DEBUG(dbgs() << "SLP: Adding cost " << CastCost
20647 << " for final resize for reduction from " << SrcVecTy
20648 << " to " << DstVecTy << "\n";
20649 dbgs() << "SLP: Current total cost = " << Cost << "\n");
20650 }
20651 }
20652 }
20653
20654 std::optional<InstructionCost> SpillCost;
20655 if (Cost < -SLPCostThreshold) {
20656 SpillCost = getSpillCost();
20657 Cost += *SpillCost;
20658 }
20659#ifndef NDEBUG
20660 SmallString<256> Str;
20661 {
20662 raw_svector_ostream OS(Str);
20663 OS << "SLP: Spill Cost = ";
20664 if (SpillCost)
20665 OS << *SpillCost;
20666 else
20667 OS << "<skipped>";
20668 OS << ".\nSLP: Extract Cost = " << ExtractCost << ".\n";
20669 if (ReductionRoot)
20670 OS << "SLP: Reduction Cost = " << ReductionCost << ".\n";
20671 OS << "SLP: Total Cost = " << Cost << ".\n";
20672 }
20673 LLVM_DEBUG(dbgs() << Str);
20674 if (ViewSLPTree)
20675 ViewGraph(this, "SLP" + F->getName(), false, Str);
20676#endif
20677
20678 return Cost;
20679}
20680
20681/// Tries to find extractelement instructions with constant indices from fixed
20682/// vector type and gather such instructions into a bunch, which highly likely
20683/// might be detected as a shuffle of 1 or 2 input vectors. If this attempt was
20684/// successful, the matched scalars are replaced by poison values in \p VL for
20685/// future analysis.
20686std::optional<TTI::ShuffleKind>
20687BoUpSLP::tryToGatherSingleRegisterExtractElements(
20689 // Scan list of gathered scalars for extractelements that can be represented
20690 // as shuffles.
20692 SmallVector<int> UndefVectorExtracts;
20693 for (int I = 0, E = VL.size(); I < E; ++I) {
20694 auto *EI = dyn_cast<ExtractElementInst>(VL[I]);
20695 if (!EI) {
20696 if (isa<UndefValue>(VL[I]))
20697 UndefVectorExtracts.push_back(I);
20698 continue;
20699 }
20700 auto *VecTy = dyn_cast<FixedVectorType>(EI->getVectorOperandType());
20701 if (!VecTy || !isa<ConstantInt, UndefValue>(EI->getIndexOperand()))
20702 continue;
20703 std::optional<unsigned> Idx = getExtractIndex(EI);
20704 // Undefined index.
20705 if (!Idx) {
20706 UndefVectorExtracts.push_back(I);
20707 continue;
20708 }
20709 if (Idx >= VecTy->getNumElements()) {
20710 UndefVectorExtracts.push_back(I);
20711 continue;
20712 }
20713 SmallBitVector ExtractMask(VecTy->getNumElements(), true);
20714 ExtractMask.reset(*Idx);
20715 if (isUndefVector</*IsPoisonOnly=*/true>(EI->getVectorOperand(),
20716 ExtractMask)
20717 .all()) {
20718 UndefVectorExtracts.push_back(I);
20719 continue;
20720 }
20721 VectorOpToIdx[EI->getVectorOperand()].push_back(I);
20722 }
20723 // Sort the vector operands by the maximum number of uses in extractelements.
20725 VectorOpToIdx.takeVector();
20726 stable_sort(Vectors, [](const auto &P1, const auto &P2) {
20727 return P1.second.size() > P2.second.size();
20728 });
20729 // Find the best pair of the vectors or a single vector.
20730 const int UndefSz = UndefVectorExtracts.size();
20731 unsigned SingleMax = 0;
20732 unsigned PairMax = 0;
20733 if (!Vectors.empty()) {
20734 SingleMax = Vectors.front().second.size() + UndefSz;
20735 if (Vectors.size() > 1) {
20736 auto *ItNext = std::next(Vectors.begin());
20737 PairMax = SingleMax + ItNext->second.size();
20738 }
20739 }
20740 if (SingleMax == 0 && PairMax == 0 && UndefSz == 0)
20741 return std::nullopt;
20742 // Check if better to perform a shuffle of 2 vectors or just of a single
20743 // vector.
20744 SmallVector<Value *> SavedVL(VL.begin(), VL.end());
20745 SmallVector<Value *> GatheredExtracts(
20746 VL.size(), PoisonValue::get(VL.front()->getType()));
20747 if (SingleMax >= PairMax && SingleMax) {
20748 for (int Idx : Vectors.front().second)
20749 std::swap(GatheredExtracts[Idx], VL[Idx]);
20750 } else if (!Vectors.empty()) {
20751 for (unsigned Idx : {0, 1})
20752 for (int Idx : Vectors[Idx].second)
20753 std::swap(GatheredExtracts[Idx], VL[Idx]);
20754 }
20755 // Add extracts from undefs too.
20756 for (int Idx : UndefVectorExtracts)
20757 std::swap(GatheredExtracts[Idx], VL[Idx]);
20758 // Check that gather of extractelements can be represented as just a
20759 // shuffle of a single/two vectors the scalars are extracted from.
20760 std::optional<TTI::ShuffleKind> Res =
20761 isFixedVectorShuffle(GatheredExtracts, Mask, AC);
20762 if (!Res || all_of(Mask, equal_to(PoisonMaskElem))) {
20763 // TODO: try to check other subsets if possible.
20764 // Restore the original VL if attempt was not successful.
20765 copy(SavedVL, VL.begin());
20766 return std::nullopt;
20767 }
20768 // Restore unused scalars from mask, if some of the extractelements were not
20769 // selected for shuffle.
20770 for (int I = 0, E = GatheredExtracts.size(); I < E; ++I) {
20771 if (Mask[I] == PoisonMaskElem && !isa<PoisonValue>(GatheredExtracts[I]) &&
20772 isa<UndefValue>(GatheredExtracts[I])) {
20773 std::swap(VL[I], GatheredExtracts[I]);
20774 continue;
20775 }
20776 auto *EI = dyn_cast<ExtractElementInst>(VL[I]);
20777 if (!EI || !isa<FixedVectorType>(EI->getVectorOperandType()) ||
20778 !isa<ConstantInt, UndefValue>(EI->getIndexOperand()) ||
20779 is_contained(UndefVectorExtracts, I))
20780 continue;
20781 }
20782 return Res;
20783}
20784
20785/// Tries to find extractelement instructions with constant indices from fixed
20786/// vector type and gather such instructions into a bunch, which highly likely
20787/// might be detected as a shuffle of 1 or 2 input vectors. If this attempt was
20788/// successful, the matched scalars are replaced by poison values in \p VL for
20789/// future analysis.
20791BoUpSLP::tryToGatherExtractElements(SmallVectorImpl<Value *> &VL,
20792 SmallVectorImpl<int> &Mask,
20793 unsigned NumParts) const {
20794 assert(NumParts > 0 && "NumParts expected be greater than or equal to 1.");
20795 SmallVector<std::optional<TTI::ShuffleKind>> ShufflesRes(NumParts);
20796 Mask.assign(VL.size(), PoisonMaskElem);
20797 unsigned SliceSize = getPartNumElems(VL.size(), NumParts);
20798 for (unsigned Part : seq<unsigned>(NumParts)) {
20799 // Scan list of gathered scalars for extractelements that can be represented
20800 // as shuffles.
20801 const unsigned PartOffset = Part * SliceSize;
20802 const unsigned PartSize = getNumElems(VL.size(), SliceSize, Part);
20803 // It may happen in case of revec, need to check no access out of bounds.
20804 if (PartOffset + PartSize > VL.size())
20805 break;
20807 MutableArrayRef(VL).slice(PartOffset, PartSize);
20808 SmallVector<int> SubMask;
20809 std::optional<TTI::ShuffleKind> Res =
20810 tryToGatherSingleRegisterExtractElements(SubVL, SubMask);
20811 ShufflesRes[Part] = Res;
20812 copy(SubMask, std::next(Mask.begin(), Part * SliceSize));
20813 if (SubVL.size() != SliceSize)
20814 break;
20815 }
20816 if (none_of(ShufflesRes, [](const std::optional<TTI::ShuffleKind> &Res) {
20817 return Res.has_value();
20818 }))
20819 ShufflesRes.clear();
20820 return ShufflesRes;
20821}
20822
20823std::optional<TargetTransformInfo::ShuffleKind>
20824BoUpSLP::isGatherShuffledSingleRegisterEntry(
20825 const TreeEntry *TE, ArrayRef<Value *> VL, MutableArrayRef<int> Mask,
20826 SmallVectorImpl<const TreeEntry *> &Entries, unsigned Part, bool ForOrder,
20827 unsigned SliceSize) {
20828 Entries.clear();
20829 if (TE->Idx == 0)
20830 return std::nullopt;
20831 const unsigned MaskBase = Part * SliceSize;
20832 // TODO: currently checking only for Scalars in the tree entry, need to count
20833 // reused elements too for better cost estimation.
20834 auto GetUserEntry = [&](const TreeEntry *TE) {
20835 while (TE->UserTreeIndex && TE->UserTreeIndex.EdgeIdx == UINT_MAX)
20836 TE = TE->UserTreeIndex.UserTE;
20837 if (TE == &getRootNode())
20838 return EdgeInfo(const_cast<TreeEntry *>(TE), 0);
20839 return TE->UserTreeIndex;
20840 };
20841 auto HasGatherUser = [&](const TreeEntry *TE) {
20842 while (TE->Idx != 0 && TE->UserTreeIndex) {
20843 if (TE->UserTreeIndex.EdgeIdx == UINT_MAX)
20844 return true;
20845 TE = TE->UserTreeIndex.UserTE;
20846 }
20847 return false;
20848 };
20849 const EdgeInfo TEUseEI = GetUserEntry(TE);
20850 if (!TEUseEI || (TEUseEI.UserTE->Idx == 0 && TEUseEI.UserTE->isGather() &&
20851 !TEUseEI.UserTE->hasState()))
20852 return std::nullopt;
20853 const Instruction *TEInsertPt = &getLastInstructionInBundle(TEUseEI.UserTE);
20854 const BasicBlock *TEInsertBlock = nullptr;
20855 // Main node of PHI entries keeps the correct order of operands/incoming
20856 // blocks.
20857 if (auto *PHI = dyn_cast_or_null<PHINode>(
20858 TEUseEI.UserTE->hasState() ? TEUseEI.UserTE->getMainOp() : nullptr);
20859 PHI && TEUseEI.UserTE->State != TreeEntry::SplitVectorize) {
20860 TEInsertBlock = PHI->getIncomingBlock(TEUseEI.EdgeIdx);
20861 TEInsertPt = TEInsertBlock->getTerminator();
20862 } else {
20863 TEInsertBlock = TEInsertPt->getParent();
20864 }
20865 if (!DT->isReachableFromEntry(TEInsertBlock))
20866 return std::nullopt;
20867 auto *NodeUI = DT->getNode(TEInsertBlock);
20868 assert(NodeUI && "Should only process reachable instructions");
20869 SmallPtrSet<Value *, 4> GatheredScalars(llvm::from_range, VL);
20870 auto CheckOrdering = [&](const Instruction *InsertPt) {
20871 // Argument InsertPt is an instruction where vector code for some other
20872 // tree entry (one that shares one or more scalars with TE) is going to be
20873 // generated. This lambda returns true if insertion point of vector code
20874 // for the TE dominates that point (otherwise dependency is the other way
20875 // around). The other node is not limited to be of a gather kind. Gather
20876 // nodes are not scheduled and their vector code is inserted before their
20877 // first user. If user is PHI, that is supposed to be at the end of a
20878 // predecessor block. Otherwise it is the last instruction among scalars of
20879 // the user node. So, instead of checking dependency between instructions
20880 // themselves, we check dependency between their insertion points for vector
20881 // code (since each scalar instruction ends up as a lane of a vector
20882 // instruction).
20883 const BasicBlock *InsertBlock = InsertPt->getParent();
20884 auto *NodeEUI = DT->getNode(InsertBlock);
20885 if (!NodeEUI)
20886 return false;
20887 assert((NodeUI == NodeEUI) ==
20888 (NodeUI->getDFSNumIn() == NodeEUI->getDFSNumIn()) &&
20889 "Different nodes should have different DFS numbers");
20890 // Check the order of the gather nodes users.
20891 if (TEInsertPt->getParent() != InsertBlock &&
20892 (DT->dominates(NodeUI, NodeEUI) || !DT->dominates(NodeEUI, NodeUI)))
20893 return false;
20894 if (TEInsertPt->getParent() == InsertBlock &&
20895 TEInsertPt->comesBefore(InsertPt))
20896 return false;
20897 return true;
20898 };
20899 // Find all tree entries used by the gathered values. If no common entries
20900 // found - not a shuffle.
20901 // Here we build a set of tree nodes for each gathered value and trying to
20902 // find the intersection between these sets. If we have at least one common
20903 // tree node for each gathered value - we have just a permutation of the
20904 // single vector. If we have 2 different sets, we're in situation where we
20905 // have a permutation of 2 input vectors.
20907 SmallDenseMap<Value *, int> UsedValuesEntry;
20908 SmallPtrSet<const Value *, 16> VisitedValue;
20909 bool IsReusedNodeFound = false;
20910 auto CheckAndUseSameNode = [&](const TreeEntry *TEPtr) {
20911 // The node is reused - exit.
20912 if (IsReusedNodeFound)
20913 return false;
20914 if ((TEPtr->getVectorFactor() != VL.size() &&
20915 TEPtr->Scalars.size() != VL.size()) ||
20916 (!TEPtr->isSame(VL) && !TEPtr->isSame(TE->Scalars)))
20917 return false;
20918 IsReusedNodeFound =
20919 equal(TE->Scalars, TEPtr->Scalars) &&
20920 equal(TE->ReorderIndices, TEPtr->ReorderIndices) &&
20921 equal(TE->ReuseShuffleIndices, TEPtr->ReuseShuffleIndices);
20922 UsedTEs.clear();
20923 UsedTEs.emplace_back().insert(TEPtr);
20924 for (Value *V : VL) {
20925 if (isConstant(V))
20926 continue;
20927 UsedValuesEntry.try_emplace(V, 0);
20928 }
20929 return true;
20930 };
20931 auto CheckParentNodes = [&](const TreeEntry *User1, const TreeEntry *User2,
20932 unsigned EdgeIdx) {
20933 const TreeEntry *Ptr1 = User1;
20934 const TreeEntry *Ptr2 = User2;
20935 SmallDenseMap<const TreeEntry *, unsigned> PtrToIdx;
20936 while (Ptr2) {
20937 PtrToIdx.try_emplace(Ptr2, EdgeIdx);
20938 EdgeIdx = Ptr2->UserTreeIndex.EdgeIdx;
20939 Ptr2 = Ptr2->UserTreeIndex.UserTE;
20940 }
20941 while (Ptr1) {
20942 unsigned Idx = Ptr1->UserTreeIndex.EdgeIdx;
20943 Ptr1 = Ptr1->UserTreeIndex.UserTE;
20944 if (auto It = PtrToIdx.find(Ptr1); It != PtrToIdx.end())
20945 return Idx < It->second;
20946 }
20947 return false;
20948 };
20949 // Cache `isUsedOutsideBlock(TEInsertPt)` - TEInsertPt is loop-invariant and
20950 // the function walks the instruction's user list.
20951 std::optional<bool> TEInsertPtUsedOutsideBlock;
20952 auto IsTEInsertPtUsedOutsideBlock = [&] {
20953 if (!TEInsertPtUsedOutsideBlock)
20954 TEInsertPtUsedOutsideBlock =
20955 isUsedOutsideBlock(const_cast<Instruction *>(TEInsertPt));
20956 return *TEInsertPtUsedOutsideBlock;
20957 };
20958 // Cache the TEUseEI/TEInsertPt-only prefix of the per-call lambda predicate
20959 // below - all of these depend only on outer-scope state, not the lambda's
20960 // arguments.
20961 const bool TEUseEIInsertPtUsedOutside =
20962 TEUseEI && TEUseEI.UserTE && TEUseEI.UserTE->hasCopyableElements() &&
20963 !TEUseEI.UserTE->isCopyableElement(
20964 const_cast<Instruction *>(TEInsertPt)) &&
20965 IsTEInsertPtUsedOutsideBlock();
20966 auto CheckNonSchedulableOrdering = [&](const TreeEntry *E,
20967 Instruction *InsertPt) {
20968 return TEUseEIInsertPtUsedOutside &&
20969 InsertPt->getNextNode() == TEInsertPt &&
20970 (!E->hasCopyableElements() || !E->isCopyableElement(InsertPt) ||
20971 !isUsedOutsideBlock(InsertPt));
20972 };
20973 // Cache the TEUseEI.UserTE-dependent predicate - it is invariant across the
20974 // double loop below. all_of with isUsedOutsideBlock walks each scalar's
20975 // users and is the expensive component.
20976 const bool TEUserNeedsEmitFirst =
20977 TEUseEI.UserTE->State == TreeEntry::Vectorize &&
20978 TEUseEI.UserTE->hasState() &&
20979 (TEUseEI.UserTE->getOpcode() != Instruction::PHI ||
20980 TEUseEI.UserTE->isAltShuffle()) &&
20981 all_of(TEUseEI.UserTE->Scalars, isUsedOutsideBlock);
20982 // Cache `all_of(UserTE->Scalars, isUsedOutsideBlock)` per UserTE - the
20983 // same UserTE may be encountered for many TEPtr values inside the loop.
20984 SmallDenseMap<const TreeEntry *, bool> ScalarsUsedOutsideBlockCache;
20985 auto AllScalarsUsedOutsideBlock = [&](const TreeEntry *UserTE) {
20986 auto [It, Inserted] = ScalarsUsedOutsideBlockCache.try_emplace(UserTE);
20987 if (!Inserted)
20988 return It->second;
20989 bool Res = all_of(UserTE->Scalars, isUsedOutsideBlock);
20990 It->second = Res;
20991 return Res;
20992 };
20993 for (Value *V : VL) {
20994 if (isConstant(V) || !VisitedValue.insert(V).second)
20995 continue;
20996 // Build a list of tree entries where V is used.
20997 SmallPtrSet<const TreeEntry *, 4> VToTEs;
20999 ValueToGatherNodes.lookup(V).takeVector());
21000 if (TransformedToGatherNodes.contains(TE)) {
21001 for (TreeEntry *E : getSplitTreeEntries(V)) {
21002 if (TE == E || !TransformedToGatherNodes.contains(E) ||
21003 !E->UserTreeIndex || E->UserTreeIndex.UserTE->isGather())
21004 continue;
21005 GatherNodes.push_back(E);
21006 }
21007 for (TreeEntry *E : getTreeEntries(V)) {
21008 if (TE == E || !TransformedToGatherNodes.contains(E) ||
21009 !E->UserTreeIndex || E->UserTreeIndex.UserTE->isGather())
21010 continue;
21011 GatherNodes.push_back(E);
21012 }
21013 }
21014 for (const TreeEntry *TEPtr : GatherNodes) {
21015 if (TEPtr == TE || TEPtr->Idx == 0 || DeletedNodes.contains(TEPtr))
21016 continue;
21017 assert(any_of(TEPtr->Scalars,
21018 [&](Value *V) { return GatheredScalars.contains(V); }) &&
21019 "Must contain at least single gathered value.");
21020 assert(TEPtr->UserTreeIndex &&
21021 "Expected only single user of a gather node.");
21022 if (any_of(TEPtr->CombinedEntriesWithIndices,
21023 [&](const auto &P) { return P.first == TE->Idx; }))
21024 continue;
21025 const EdgeInfo &UseEI = TEPtr->UserTreeIndex;
21026
21027 PHINode *UserPHI = (UseEI.UserTE->State != TreeEntry::SplitVectorize &&
21028 UseEI.UserTE->hasState())
21029 ? dyn_cast<PHINode>(UseEI.UserTE->getMainOp())
21030 : nullptr;
21031 Instruction *InsertPt =
21032 UserPHI ? UserPHI->getIncomingBlock(UseEI.EdgeIdx)->getTerminator()
21033 : &getLastInstructionInBundle(UseEI.UserTE);
21034 if (TEInsertPt == InsertPt) {
21035 // Check nodes, which might be emitted first.
21036 if (TEUserNeedsEmitFirst) {
21037 if (UseEI.UserTE->State != TreeEntry::Vectorize ||
21038 (UseEI.UserTE->hasState() &&
21039 UseEI.UserTE->getOpcode() == Instruction::PHI &&
21040 !UseEI.UserTE->isAltShuffle()) ||
21041 !AllScalarsUsedOutsideBlock(UseEI.UserTE))
21042 continue;
21043 }
21044
21045 // If the schedulable insertion point is used in multiple entries - just
21046 // exit, no known ordering at this point, available only after real
21047 // scheduling.
21048 if (!doesNotNeedToBeScheduled(InsertPt) &&
21049 (TEUseEI.UserTE != UseEI.UserTE || TEUseEI.EdgeIdx < UseEI.EdgeIdx))
21050 continue;
21051 // If the users are the PHI nodes with the same incoming blocks - skip.
21052 if (TEUseEI.UserTE->State == TreeEntry::Vectorize &&
21053 TEUseEI.UserTE->getOpcode() == Instruction::PHI &&
21054 UseEI.UserTE->State == TreeEntry::Vectorize &&
21055 UseEI.UserTE->getOpcode() == Instruction::PHI &&
21056 TEUseEI.UserTE != UseEI.UserTE)
21057 continue;
21058 // If 2 gathers are operands of the same entry (regardless of whether
21059 // user is PHI or else), compare operands indices, use the earlier one
21060 // as the base.
21061 if (TEUseEI.UserTE == UseEI.UserTE && TEUseEI.EdgeIdx < UseEI.EdgeIdx)
21062 continue;
21063 // If the user instruction is used for some reason in different
21064 // vectorized nodes - make it depend on index.
21065 if (TEUseEI.UserTE != UseEI.UserTE &&
21066 (TEUseEI.UserTE->Idx < UseEI.UserTE->Idx ||
21067 HasGatherUser(TEUseEI.UserTE)))
21068 continue;
21069 // If the user node is the operand of the other user node - skip.
21070 if (CheckParentNodes(TEUseEI.UserTE, UseEI.UserTE, UseEI.EdgeIdx))
21071 continue;
21072 }
21073
21074 if (!TEUseEI.UserTE->isGather() && !UserPHI &&
21075 TEUseEI.UserTE->doesNotNeedToSchedule() !=
21076 UseEI.UserTE->doesNotNeedToSchedule() &&
21077 is_contained(UseEI.UserTE->Scalars, TEInsertPt))
21078 continue;
21079 // Check if the user node of the TE comes after user node of TEPtr,
21080 // otherwise TEPtr depends on TE.
21081 if ((TEInsertBlock != InsertPt->getParent() ||
21082 TEUseEI.EdgeIdx < UseEI.EdgeIdx || TEUseEI.UserTE != UseEI.UserTE) &&
21083 (!CheckOrdering(InsertPt) ||
21084 (UseEI.UserTE->hasCopyableElements() &&
21085 IsTEInsertPtUsedOutsideBlock() &&
21086 is_contained(UseEI.UserTE->Scalars, TEInsertPt))))
21087 continue;
21088 // The node is reused - exit.
21089 if (CheckAndUseSameNode(TEPtr))
21090 break;
21091 // The parent node is copyable with last inst used outside? And the last
21092 // inst is the next inst for the lastinst of TEPtr? Exit, if yes, to
21093 // preserve def-use chain.
21094 if (CheckNonSchedulableOrdering(UseEI.UserTE, InsertPt))
21095 continue;
21096 VToTEs.insert(TEPtr);
21097 }
21098 if (ArrayRef<TreeEntry *> VTEs = getSplitTreeEntries(V); !VTEs.empty()) {
21099 const auto *It = find_if(VTEs, [&](const TreeEntry *MTE) {
21100 return MTE != TE && MTE != TEUseEI.UserTE &&
21101 !DeletedNodes.contains(MTE) &&
21102 !TransformedToGatherNodes.contains(MTE);
21103 });
21104 if (It != VTEs.end()) {
21105 const TreeEntry *VTE = *It;
21106 if (none_of(TE->CombinedEntriesWithIndices,
21107 [&](const auto &P) { return P.first == VTE->Idx; })) {
21108 Instruction &LastBundleInst = getLastInstructionInBundle(VTE);
21109 if (&LastBundleInst == TEInsertPt || !CheckOrdering(&LastBundleInst))
21110 continue;
21111 }
21112 // The node is reused - exit.
21113 if (CheckAndUseSameNode(VTE))
21114 break;
21115 VToTEs.insert(VTE);
21116 }
21117 }
21118 if (ArrayRef<TreeEntry *> VTEs = getTreeEntries(V); !VTEs.empty()) {
21119 const auto *It = find_if(VTEs, [&, MainTE = TE](const TreeEntry *TE) {
21120 return TE != MainTE && !DeletedNodes.contains(TE) &&
21121 !TransformedToGatherNodes.contains(TE);
21122 });
21123 if (It != VTEs.end()) {
21124 const TreeEntry *VTE = *It;
21125 if (ForOrder && VTE->Idx < GatheredLoadsEntriesFirst.value_or(0) &&
21126 VTEs.size() > 1 && VTE->State != TreeEntry::Vectorize) {
21127 VTEs = VTEs.drop_front();
21128 // Iterate through all vectorized nodes.
21129 const auto *MIt = find_if(VTEs, [](const TreeEntry *MTE) {
21130 return MTE->State == TreeEntry::Vectorize;
21131 });
21132 if (MIt == VTEs.end())
21133 continue;
21134 VTE = *MIt;
21135 }
21136 if (none_of(TE->CombinedEntriesWithIndices,
21137 [&](const auto &P) { return P.first == VTE->Idx; })) {
21138 Instruction &LastBundleInst = getLastInstructionInBundle(VTE);
21139 if (&LastBundleInst == TEInsertPt ||
21140 !CheckOrdering(&LastBundleInst) ||
21141 CheckNonSchedulableOrdering(VTE, &LastBundleInst))
21142 continue;
21143 }
21144 // The node is reused - exit.
21145 if (CheckAndUseSameNode(VTE))
21146 break;
21147 VToTEs.insert(VTE);
21148 }
21149 }
21150 if (IsReusedNodeFound)
21151 break;
21152 if (VToTEs.empty())
21153 continue;
21154 if (UsedTEs.empty()) {
21155 // The first iteration, just insert the list of nodes to vector.
21156 UsedTEs.push_back(VToTEs);
21157 UsedValuesEntry.try_emplace(V, 0);
21158 } else {
21159 // Need to check if there are any previously used tree nodes which use V.
21160 // If there are no such nodes, consider that we have another one input
21161 // vector.
21162 SmallPtrSet<const TreeEntry *, 4> SavedVToTEs(VToTEs);
21163 unsigned Idx = 0;
21164 for (SmallPtrSet<const TreeEntry *, 4> &Set : UsedTEs) {
21165 // Do we have a non-empty intersection of previously listed tree entries
21166 // and tree entries using current V?
21167 set_intersect(VToTEs, Set);
21168 if (!VToTEs.empty()) {
21169 // Yes, write the new subset and continue analysis for the next
21170 // scalar.
21171 Set.swap(VToTEs);
21172 break;
21173 }
21174 VToTEs = SavedVToTEs;
21175 ++Idx;
21176 }
21177 // No non-empty intersection found - need to add a second set of possible
21178 // source vectors.
21179 if (Idx == UsedTEs.size()) {
21180 // If the number of input vectors is greater than 2 - not a permutation,
21181 // fallback to the regular gather.
21182 // TODO: support multiple reshuffled nodes.
21183 if (UsedTEs.size() == 2)
21184 continue;
21185 UsedTEs.push_back(SavedVToTEs);
21186 Idx = UsedTEs.size() - 1;
21187 }
21188 UsedValuesEntry.try_emplace(V, Idx);
21189 }
21190 }
21191
21192 if (UsedTEs.empty()) {
21193 Entries.clear();
21194 return std::nullopt;
21195 }
21196
21197 unsigned VF = 0;
21198 if (UsedTEs.size() == 1) {
21199 // Keep the order to avoid non-determinism.
21200 SmallVector<const TreeEntry *> FirstEntries(UsedTEs.front().begin(),
21201 UsedTEs.front().end());
21202 sort(FirstEntries, [](const TreeEntry *TE1, const TreeEntry *TE2) {
21203 return TE1->Idx < TE2->Idx;
21204 });
21205 // Try to find the perfect match in another gather node at first.
21206 auto *It = find_if(FirstEntries, [=](const TreeEntry *EntryPtr) {
21207 return (EntryPtr->getVectorFactor() == TE->Scalars.size() &&
21208 EntryPtr->isSame(TE->Scalars)) ||
21209 EntryPtr->isSame(VL);
21210 });
21211 if (It != FirstEntries.end() &&
21212 (IsReusedNodeFound || (*It)->getVectorFactor() == VL.size() ||
21213 ((*It)->getVectorFactor() == TE->Scalars.size() &&
21214 TE->ReuseShuffleIndices.size() == VL.size() &&
21215 (*It)->isSame(TE->Scalars)))) {
21216 Entries.push_back(*It);
21217 if (IsReusedNodeFound || (*It)->getVectorFactor() == VL.size()) {
21218 std::iota(std::next(Mask.begin(), MaskBase),
21219 std::next(Mask.begin(), MaskBase + VL.size()), 0);
21220 } else {
21221 SmallVector<int> CommonMask = TE->getCommonMask();
21222 copy(CommonMask, Mask.begin());
21223 }
21224 // Clear undef scalars.
21225 for (unsigned I : seq<unsigned>(VL.size()))
21226 if (isa<PoisonValue>(VL[I]))
21227 Mask[MaskBase + I] = PoisonMaskElem;
21229 }
21230 // No perfect match, just shuffle, so choose the first tree node from the
21231 // tree.
21232 Entries.push_back(FirstEntries.front());
21233 // Update mapping between values and corresponding tree entries.
21234 for (auto &P : UsedValuesEntry)
21235 P.second = 0;
21236 VF = FirstEntries.front()->getVectorFactor();
21237 } else {
21238 // Try to find nodes with the same vector factor.
21239 assert(UsedTEs.size() == 2 && "Expected at max 2 permuted entries.");
21240 // Keep the order of tree nodes to avoid non-determinism.
21241 DenseMap<int, const TreeEntry *> VFToTE;
21242 for (const TreeEntry *TE : UsedTEs.front()) {
21243 unsigned VF = TE->getVectorFactor();
21244 auto It = VFToTE.find(VF);
21245 if (It != VFToTE.end()) {
21246 if (It->second->Idx > TE->Idx)
21247 It->getSecond() = TE;
21248 continue;
21249 }
21250 VFToTE.try_emplace(VF, TE);
21251 }
21252 // Same, keep the order to avoid non-determinism.
21253 SmallVector<const TreeEntry *> SecondEntries(UsedTEs.back().begin(),
21254 UsedTEs.back().end());
21255 sort(SecondEntries, [](const TreeEntry *TE1, const TreeEntry *TE2) {
21256 return TE1->Idx < TE2->Idx;
21257 });
21258 for (const TreeEntry *TE : SecondEntries) {
21259 auto It = VFToTE.find(TE->getVectorFactor());
21260 if (It != VFToTE.end()) {
21261 VF = It->first;
21262 Entries.push_back(It->second);
21263 Entries.push_back(TE);
21264 break;
21265 }
21266 }
21267 // No 2 source vectors with the same vector factor - just choose 2 with max
21268 // index.
21269 if (Entries.empty()) {
21271 UsedTEs.front(), [](const TreeEntry *TE1, const TreeEntry *TE2) {
21272 return TE1->Idx < TE2->Idx;
21273 }));
21274 Entries.push_back(SecondEntries.front());
21275 VF = std::max(Entries.front()->getVectorFactor(),
21276 Entries.back()->getVectorFactor());
21277 } else {
21278 VF = Entries.front()->getVectorFactor();
21279 }
21280 SmallVector<SmallPtrSet<Value *, 8>> ValuesToEntries;
21281 for (const TreeEntry *E : Entries)
21282 ValuesToEntries.emplace_back().insert(E->Scalars.begin(),
21283 E->Scalars.end());
21284 // Update mapping between values and corresponding tree entries.
21285 for (auto &P : UsedValuesEntry) {
21286 for (unsigned Idx : seq<unsigned>(ValuesToEntries.size()))
21287 if (ValuesToEntries[Idx].contains(P.first)) {
21288 P.second = Idx;
21289 break;
21290 }
21291 }
21292 }
21293
21294 bool IsSplatOrUndefs = isSplat(VL) || all_of(VL, IsaPred<UndefValue>);
21295 // Checks if the 2 PHIs are compatible in terms of high possibility to be
21296 // vectorized.
21297 auto AreCompatiblePHIs = [&](Value *V, Value *V1) {
21298 auto *PHI = cast<PHINode>(V);
21299 auto *PHI1 = cast<PHINode>(V1);
21300 // Check that all incoming values are compatible/from same parent (if they
21301 // are instructions).
21302 // The incoming values are compatible if they all are constants, or
21303 // instruction with the same/alternate opcodes from the same basic block.
21304 for (int I = 0, E = PHI->getNumIncomingValues(); I < E; ++I) {
21305 Value *In = PHI->getIncomingValue(I);
21306 Value *In1 = PHI1->getIncomingValue(I);
21307 if (isConstant(In) && isConstant(In1))
21308 continue;
21309 if (!getSameOpcode({In, In1}, *TLI))
21310 return false;
21311 if (cast<Instruction>(In)->getParent() !=
21313 return false;
21314 }
21315 return true;
21316 };
21317 // Check if the value can be ignored during analysis for shuffled gathers.
21318 // We suppose it is better to ignore instruction, which do not form splats,
21319 // are not vectorized/not extractelements (these instructions will be handled
21320 // by extractelements processing) or may form vector node in future.
21321 // Cache results - each V in VL is queried up to 3 times (direct +
21322 // NeighborMightBeIgnored from both neighbors), and areAllUsersVectorized
21323 // walks each instruction's user list.
21324 SmallDenseMap<Value *, bool> MightBeIgnoredCache;
21325 auto MightBeIgnored = [=, &MightBeIgnoredCache](Value *V) {
21326 auto [It, Inserted] = MightBeIgnoredCache.try_emplace(V);
21327 if (!Inserted)
21328 return It->second;
21329 auto *I = dyn_cast<Instruction>(V);
21330 bool Res = I && !IsSplatOrUndefs && !isVectorized(I) &&
21332 !areAllUsersVectorized(I, UserIgnoreList) && isSimple(I);
21333 It->second = Res;
21334 return Res;
21335 };
21336 // Check that the neighbor instruction may form a full vector node with the
21337 // current instruction V. It is possible, if they have same/alternate opcode
21338 // and same parent basic block.
21339 auto NeighborMightBeIgnored = [&](Value *V, int Idx) {
21340 Value *V1 = VL[Idx];
21341 bool UsedInSameVTE = false;
21342 auto It = UsedValuesEntry.find(V1);
21343 if (It != UsedValuesEntry.end())
21344 UsedInSameVTE = It->second == UsedValuesEntry.find(V)->second;
21345 return V != V1 && MightBeIgnored(V1) && !UsedInSameVTE &&
21346 getSameOpcode({V, V1}, *TLI) &&
21347 cast<Instruction>(V)->getParent() ==
21348 cast<Instruction>(V1)->getParent() &&
21349 (!isa<PHINode>(V1) || AreCompatiblePHIs(V, V1));
21350 };
21351 // Build a shuffle mask for better cost estimation and vector emission.
21352 SmallBitVector UsedIdxs(Entries.size());
21354 for (int I = 0, E = VL.size(); I < E; ++I) {
21355 Value *V = VL[I];
21356 auto It = UsedValuesEntry.find(V);
21357 if (It == UsedValuesEntry.end())
21358 continue;
21359 // Do not try to shuffle scalars, if they are constants, or instructions
21360 // that can be vectorized as a result of the following vector build
21361 // vectorization.
21362 if (isConstant(V) || (MightBeIgnored(V) &&
21363 ((I > 0 && NeighborMightBeIgnored(V, I - 1)) ||
21364 (I != E - 1 && NeighborMightBeIgnored(V, I + 1)))))
21365 continue;
21366 unsigned Idx = It->second;
21367 EntryLanes.emplace_back(Idx, I);
21368 UsedIdxs.set(Idx);
21369 }
21370 // Iterate through all shuffled scalars and select entries, which can be used
21371 // for final shuffle.
21373 for (unsigned I = 0, Sz = Entries.size(); I < Sz; ++I) {
21374 if (!UsedIdxs.test(I))
21375 continue;
21376 // Fix the entry number for the given scalar. If it is the first entry, set
21377 // Pair.first to 0, otherwise to 1 (currently select at max 2 nodes).
21378 // These indices are used when calculating final shuffle mask as the vector
21379 // offset.
21380 for (std::pair<unsigned, int> &Pair : EntryLanes)
21381 if (Pair.first == I)
21382 Pair.first = TempEntries.size();
21383 TempEntries.push_back(Entries[I]);
21384 }
21385 Entries.swap(TempEntries);
21386 if (EntryLanes.size() == Entries.size() &&
21387 !VL.equals(ArrayRef(TE->Scalars)
21388 .slice(MaskBase, getNumElems(TE->Scalars.size(), SliceSize,
21389 Part)))) {
21390 // We may have here 1 or 2 entries only. If the number of scalars is equal
21391 // to the number of entries, no need to do the analysis, it is not very
21392 // profitable. Since VL is not the same as TE->Scalars, it means we already
21393 // have some shuffles before. Cut off not profitable case.
21394 Entries.clear();
21395 return std::nullopt;
21396 }
21397 // Build the final mask, check for the identity shuffle, if possible.
21398 bool IsIdentity = Entries.size() == 1;
21399 // Pair.first is the offset to the vector, while Pair.second is the index of
21400 // scalar in the list.
21401 for (const std::pair<unsigned, int> &Pair : EntryLanes) {
21402 unsigned Idx = MaskBase + Pair.second;
21403 Mask[Idx] =
21404 Pair.first * VF +
21405 (ForOrder ? std::distance(
21406 Entries[Pair.first]->Scalars.begin(),
21407 find(Entries[Pair.first]->Scalars, VL[Pair.second]))
21408 : Entries[Pair.first]->findLaneForValue(VL[Pair.second]));
21409 IsIdentity &= Mask[Idx] == Pair.second;
21410 }
21411 if (ForOrder || IsIdentity || Entries.empty()) {
21412 switch (Entries.size()) {
21413 case 1:
21414 if (IsIdentity || EntryLanes.size() > 1 || VL.size() <= 2)
21416 break;
21417 case 2:
21418 if (EntryLanes.size() > 2 || VL.size() <= 2)
21420 break;
21421 default:
21422 break;
21423 }
21424 } else if (!isa<VectorType>(VL.front()->getType()) &&
21425 (EntryLanes.size() > Entries.size() || VL.size() <= 2)) {
21426 // Do the cost estimation if shuffle beneficial than buildvector.
21427 SmallVector<int> SubMask(std::next(Mask.begin(), MaskBase),
21428 std::next(Mask.begin(), MaskBase + VL.size()));
21429 int MinElement = SubMask.front(), MaxElement = SubMask.front();
21430 for (int Idx : SubMask) {
21431 if (Idx == PoisonMaskElem)
21432 continue;
21433 if (MinElement == PoisonMaskElem || MinElement % VF > Idx % VF)
21434 MinElement = Idx;
21435 if (MaxElement == PoisonMaskElem || MaxElement % VF < Idx % VF)
21436 MaxElement = Idx;
21437 }
21438 assert(MaxElement >= 0 && MinElement >= 0 &&
21439 MaxElement % VF >= MinElement % VF &&
21440 "Expected at least single element.");
21441 // If the leading [0, MinIdx) range sits in its own register part(s),
21442 // skip those whole parts when sizing the destination - everything below
21443 // the register-aligned floor is unused and never indexed.
21444 unsigned Offset = 0;
21445 unsigned MinIdx = MinElement % VF;
21446 if (MinIdx > 1) {
21447 unsigned RegFloor = getFloorFullVectorNumberOfElements(
21448 *TTI, VL.front()->getType(), MinIdx, SLPReVec);
21449 auto *RegFloorTy = getWidenedType(VL.front()->getType(), RegFloor);
21450 unsigned RegFloorParts =
21451 getNumberOfParts(RegFloorTy, VL.front()->getType(), RegFloor);
21452 if (RegFloorParts > 1)
21453 Offset = RegFloor;
21454 }
21455 unsigned NewVF =
21456 std::max<unsigned>(VL.size(), (MaxElement % VF) - Offset + 1);
21457 if (NewVF < VF) {
21458 for (int &Idx : SubMask) {
21459 if (Idx == PoisonMaskElem)
21460 continue;
21461 Idx = (Idx % VF) - Offset + (Idx >= static_cast<int>(VF) ? NewVF : 0);
21462 }
21463 } else {
21464 NewVF = VF;
21465 }
21466
21467 auto *VecTy =
21468 cast<VectorType>(getWidenedType(VL.front()->getType(), NewVF));
21469 auto *MaskVecTy =
21470 cast<VectorType>(getWidenedType(VL.front()->getType(), SubMask.size()));
21471 auto GetShuffleCost = [&,
21472 &TTI = *TTI](ArrayRef<int> Mask,
21474 VectorType *VecTy) -> InstructionCost {
21475 if (Entries.size() == 1 && Entries.front()->getInterleaveFactor() > 0 &&
21477 Mask, Entries.front()->getInterleaveFactor()))
21478 return TTI::TCC_Free;
21479 return getShuffleCost(TTI,
21480 Entries.size() > 1 ? TTI::SK_PermuteTwoSrc
21482 VecTy, CostKind, Mask);
21483 };
21484 InstructionCost ShuffleCost = GetShuffleCost(SubMask, Entries, VecTy);
21485 InstructionCost FirstShuffleCost = 0;
21486 SmallVector<int> FirstMask(SubMask.begin(), SubMask.end());
21487 if (Entries.size() == 1 || !Entries[0]->isGather()) {
21488 FirstShuffleCost = ShuffleCost;
21489 } else {
21490 // Transform mask to include only first entry.
21491 APInt DemandedElts = APInt::getAllOnes(SubMask.size());
21492 bool IsIdentity = true;
21493 for (auto [I, Idx] : enumerate(FirstMask)) {
21494 if (Idx >= static_cast<int>(NewVF)) {
21495 Idx = PoisonMaskElem;
21496 } else {
21497 DemandedElts.clearBit(I);
21498 if (Idx != PoisonMaskElem)
21499 IsIdentity &= static_cast<int>(I) == Idx;
21500 }
21501 }
21502 if (!IsIdentity)
21503 FirstShuffleCost = GetShuffleCost(FirstMask, Entries.front(), VecTy);
21504 FirstShuffleCost +=
21505 getScalarizationOverhead(*TTI, SLPReVec, VL.front()->getType(),
21506 MaskVecTy, DemandedElts, /*Insert=*/true,
21507 /*Extract=*/false, CostKind);
21508 }
21509 InstructionCost SecondShuffleCost = 0;
21510 SmallVector<int> SecondMask(SubMask.begin(), SubMask.end());
21511 if (Entries.size() == 1 || !Entries[1]->isGather()) {
21512 SecondShuffleCost = ShuffleCost;
21513 } else {
21514 // Transform mask to include only first entry.
21515 APInt DemandedElts = APInt::getAllOnes(SubMask.size());
21516 bool IsIdentity = true;
21517 for (auto [I, Idx] : enumerate(SecondMask)) {
21518 if (Idx < static_cast<int>(NewVF) && Idx >= 0) {
21519 Idx = PoisonMaskElem;
21520 } else {
21521 DemandedElts.clearBit(I);
21522 if (Idx != PoisonMaskElem) {
21523 Idx -= NewVF;
21524 IsIdentity &= static_cast<int>(I) == Idx;
21525 }
21526 }
21527 }
21528 if (!IsIdentity)
21529 SecondShuffleCost = GetShuffleCost(SecondMask, Entries[1], VecTy);
21530 SecondShuffleCost +=
21531 getScalarizationOverhead(*TTI, SLPReVec, VL.front()->getType(),
21532 MaskVecTy, DemandedElts, /*Insert=*/true,
21533 /*Extract=*/false, CostKind);
21534 }
21535 APInt DemandedElts = APInt::getAllOnes(SubMask.size());
21536 for (auto [I, Idx] : enumerate(SubMask))
21537 if (Idx == PoisonMaskElem)
21538 DemandedElts.clearBit(I);
21539 InstructionCost BuildVectorCost =
21540 getScalarizationOverhead(*TTI, SLPReVec, VL.front()->getType(),
21541 MaskVecTy, DemandedElts, /*Insert=*/true,
21542 /*Extract=*/false, CostKind);
21543 const TreeEntry *BestEntry = nullptr;
21544 auto MaskSlice = MutableArrayRef(Mask).slice(MaskBase, VL.size());
21545 if (FirstShuffleCost < ShuffleCost) {
21546 for (int &Idx : MaskSlice)
21547 if (Idx >= static_cast<int>(VF))
21548 Idx = PoisonMaskElem;
21549 BestEntry = Entries.front();
21550 ShuffleCost = FirstShuffleCost;
21551 }
21552 if (SecondShuffleCost < ShuffleCost) {
21553 for (int &Idx : MaskSlice) {
21554 if (Idx < static_cast<int>(VF))
21555 Idx = PoisonMaskElem;
21556 else
21557 Idx -= VF;
21558 }
21559 BestEntry = Entries[1];
21560 ShuffleCost = SecondShuffleCost;
21561 }
21562 if (BuildVectorCost >= ShuffleCost) {
21563 if (BestEntry) {
21564 Entries.clear();
21565 Entries.push_back(BestEntry);
21566 }
21567 return Entries.size() > 1 ? TargetTransformInfo::SK_PermuteTwoSrc
21569 }
21570 }
21571 Entries.clear();
21572 // Clear the corresponding mask elements.
21573 std::fill(std::next(Mask.begin(), MaskBase),
21574 std::next(Mask.begin(), MaskBase + VL.size()), PoisonMaskElem);
21575 return std::nullopt;
21576}
21577
21579BoUpSLP::isGatherShuffledEntry(
21580 const TreeEntry *TE, ArrayRef<Value *> VL, SmallVectorImpl<int> &Mask,
21581 SmallVectorImpl<SmallVector<const TreeEntry *>> &Entries, unsigned NumParts,
21582 bool ForOrder) {
21583 assert(NumParts > 0 && NumParts < VL.size() &&
21584 "Expected positive number of registers.");
21585 Entries.clear();
21586 // No need to check for the topmost gather node.
21587 if (TE == &getRootNode() &&
21588 (!GatheredLoadsEntriesFirst.has_value() ||
21589 none_of(ArrayRef(VectorizableTree).drop_front(),
21590 [](const std::unique_ptr<TreeEntry> &TE) {
21591 return !TE->isGather();
21592 })))
21593 return {};
21594 Mask.assign(VL.size(), PoisonMaskElem);
21595 assert((TE->UserTreeIndex || TE == &getRootNode()) &&
21596 "Expected only single user of the gather node.");
21597 unsigned PWSz = getFullVectorNumberOfElements(*TTI, VL.front()->getType(),
21598 VL.size(), SLPReVec);
21599 if (TE->UserTreeIndex && TE->UserTreeIndex.UserTE->isGather() &&
21600 TE->UserTreeIndex.EdgeIdx == UINT_MAX &&
21601 (TE->Idx == 0 ||
21602 (TE->hasState() && TE->getOpcode() == Instruction::ExtractElement) ||
21603 isSplat(TE->Scalars) ||
21604 (TE->hasState() &&
21605 getSameValuesTreeEntry(TE->getMainOp(), TE->Scalars))))
21606 return {};
21607 unsigned SliceSize = getPartNumElems(PWSz, NumParts);
21609 for (unsigned Part : seq<unsigned>(NumParts)) {
21610 if (Part * SliceSize >= VL.size())
21611 break;
21612 ArrayRef<Value *> SubVL =
21613 VL.slice(Part * SliceSize, getNumElems(VL.size(), SliceSize, Part));
21614 SmallVectorImpl<const TreeEntry *> &SubEntries = Entries.emplace_back();
21615 std::optional<TTI::ShuffleKind> SubRes =
21616 isGatherShuffledSingleRegisterEntry(TE, SubVL, Mask, SubEntries, Part,
21617 ForOrder, SliceSize);
21618 if (!SubRes)
21619 SubEntries.clear();
21620 Res.push_back(SubRes);
21621 if (SubEntries.size() == 1 && *SubRes == TTI::SK_PermuteSingleSrc &&
21622 SubEntries.front()->getVectorFactor() == VL.size() &&
21623 (SubEntries.front()->isSame(TE->Scalars) ||
21624 SubEntries.front()->isSame(VL))) {
21625 SmallVector<const TreeEntry *> LocalSubEntries;
21626 LocalSubEntries.swap(SubEntries);
21627 Entries.clear();
21628 Res.clear();
21629 std::iota(Mask.begin(), Mask.end(), 0);
21630 // Clear undef scalars.
21631 for (int I = 0, Sz = VL.size(); I < Sz; ++I)
21632 if (isa<PoisonValue>(VL[I]))
21634 Entries.emplace_back(1, LocalSubEntries.front());
21636 return Res;
21637 }
21638 }
21639 if (all_of(Res,
21640 [](const std::optional<TTI::ShuffleKind> &SK) { return !SK; })) {
21641 Entries.clear();
21642 return {};
21643 }
21644 return Res;
21645}
21646
21647InstructionCost BoUpSLP::getGatherCost(ArrayRef<Value *> VL, bool ForPoisonSrc,
21648 Type *ScalarTy) const {
21649 const unsigned VF = VL.size();
21650 auto *VecTy = getWidenedType(ScalarTy, VF);
21651 // Find the cost of inserting/extracting values from the vector.
21652 // Check if the same elements are inserted several times and count them as
21653 // shuffle candidates.
21654 APInt DemandedElements = APInt::getZero(VF);
21656 auto EstimateInsertCost = [&](unsigned I, Value *V) {
21657 DemandedElements.setBit(I);
21658 if (V->getType() != ScalarTy)
21659 Cost += TTI->getCastInstrCost(Instruction::Trunc, ScalarTy, V->getType(),
21660 TTI::CastContextHint::None, CostKind);
21661 };
21662 SmallVector<int> ConstantShuffleMask(VF, PoisonMaskElem);
21663 std::iota(ConstantShuffleMask.begin(), ConstantShuffleMask.end(), 0);
21664 for (auto [I, V] : enumerate(VL)) {
21665 // No need to shuffle duplicates for constants.
21666 if ((ForPoisonSrc && isConstant(V)) || isa<UndefValue>(V))
21667 continue;
21668
21669 if (isConstant(V)) {
21670 ConstantShuffleMask[I] = I + VF;
21671 continue;
21672 }
21673 EstimateInsertCost(I, V);
21674 }
21675 // FIXME: add a cost for constant vector materialization.
21676 bool IsAnyNonUndefConst =
21677 any_of(VL, [](Value *V) { return !isa<UndefValue>(V) && isConstant(V); });
21678 // 1. Shuffle input source vector and constant vector.
21679 if (!ForPoisonSrc && IsAnyNonUndefConst) {
21680 Cost +=
21682 cast<VectorType>(VecTy), CostKind, ConstantShuffleMask);
21683 }
21684
21685 // 2. Insert unique non-constants.
21686 if (!DemandedElements.isZero())
21688 *TTI, SLPReVec, ScalarTy, cast<VectorType>(VecTy), DemandedElements,
21689 /*Insert=*/true,
21690 /*Extract=*/false, CostKind, ForPoisonSrc && !IsAnyNonUndefConst, VL);
21691 return Cost;
21692}
21693
21694Instruction &BoUpSLP::getLastInstructionInBundle(const TreeEntry *E) {
21695 auto It = EntryToLastInstruction.find(E);
21696 if (It != EntryToLastInstruction.end())
21697 return *cast<Instruction>(It->second);
21698 Instruction *Res = nullptr;
21699 // Get the basic block this bundle is in. All instructions in the bundle
21700 // should be in this block (except for extractelement-like instructions with
21701 // constant indices or gathered loads or copyables).
21702 Instruction *Front;
21703 unsigned Opcode;
21704 if (E->hasState()) {
21705 Front = E->getMainOp();
21706 Opcode = E->getOpcode();
21707 } else {
21708 Front = cast<Instruction>(*find_if(E->Scalars, IsaPred<Instruction>));
21709 Opcode = Front->getOpcode();
21710 }
21711 auto *BB = Front->getParent();
21712 assert(
21713 ((GatheredLoadsEntriesFirst.has_value() && Opcode == Instruction::Load &&
21714 E->isGather() && E->Idx < *GatheredLoadsEntriesFirst) ||
21715 E->State == TreeEntry::SplitVectorize || E->hasCopyableElements() ||
21716 all_of(E->Scalars,
21717 [=](Value *V) -> bool {
21718 if (Opcode == Instruction::GetElementPtr &&
21719 !isa<GetElementPtrInst>(V))
21720 return true;
21721 auto *I = dyn_cast<Instruction>(V);
21722 return !I || !E->getMatchingMainOpOrAltOp(I) ||
21723 I->getParent() == BB || isVectorLikeInstWithConstOps(I);
21724 })) &&
21725 "Expected gathered loads or GEPs or instructions from same basic "
21726 "block.");
21727
21728 auto FindLastInst = [&]() {
21729 Instruction *LastInst = Front;
21730 for (Value *V : E->Scalars) {
21731 auto *I = dyn_cast<Instruction>(V);
21732 if (!I)
21733 continue;
21734 if (E->isCopyableElement(I))
21735 continue;
21736 if (LastInst->getParent() == I->getParent()) {
21737 if (LastInst->comesBefore(I))
21738 LastInst = I;
21739 continue;
21740 }
21741 assert(((Opcode == Instruction::GetElementPtr &&
21743 E->State == TreeEntry::SplitVectorize ||
21744 (isVectorLikeInstWithConstOps(LastInst) &&
21746 (GatheredLoadsEntriesFirst.has_value() &&
21747 Opcode == Instruction::Load && E->isGather() &&
21748 E->Idx < *GatheredLoadsEntriesFirst)) &&
21749 "Expected vector-like or non-GEP in GEP node insts only.");
21750 if (!DT->isReachableFromEntry(LastInst->getParent())) {
21751 LastInst = I;
21752 continue;
21753 }
21754 if (!DT->isReachableFromEntry(I->getParent()))
21755 continue;
21756 auto *NodeA = DT->getNode(LastInst->getParent());
21757 auto *NodeB = DT->getNode(I->getParent());
21758 assert(NodeA && "Should only process reachable instructions");
21759 assert(NodeB && "Should only process reachable instructions");
21760 assert((NodeA == NodeB) ==
21761 (NodeA->getDFSNumIn() == NodeB->getDFSNumIn()) &&
21762 "Different nodes should have different DFS numbers");
21763 if (NodeA->getDFSNumIn() < NodeB->getDFSNumIn())
21764 LastInst = I;
21765 }
21766 BB = LastInst->getParent();
21767 return LastInst;
21768 };
21769
21770 auto FindFirstInst = [&]() {
21771 Instruction *FirstInst = Front;
21772 for (Value *V : E->Scalars) {
21773 auto *I = dyn_cast<Instruction>(V);
21774 if (!I)
21775 continue;
21776 if (E->isCopyableElement(I))
21777 continue;
21778 if (FirstInst->getParent() == I->getParent()) {
21779 if (I->comesBefore(FirstInst))
21780 FirstInst = I;
21781 continue;
21782 }
21783 assert(((Opcode == Instruction::GetElementPtr &&
21785 (isVectorLikeInstWithConstOps(FirstInst) &&
21787 "Expected vector-like or non-GEP in GEP node insts only.");
21788 if (!DT->isReachableFromEntry(FirstInst->getParent())) {
21789 FirstInst = I;
21790 continue;
21791 }
21792 if (!DT->isReachableFromEntry(I->getParent()))
21793 continue;
21794 auto *NodeA = DT->getNode(FirstInst->getParent());
21795 auto *NodeB = DT->getNode(I->getParent());
21796 assert(NodeA && "Should only process reachable instructions");
21797 assert(NodeB && "Should only process reachable instructions");
21798 assert((NodeA == NodeB) ==
21799 (NodeA->getDFSNumIn() == NodeB->getDFSNumIn()) &&
21800 "Different nodes should have different DFS numbers");
21801 if (NodeA->getDFSNumIn() > NodeB->getDFSNumIn())
21802 FirstInst = I;
21803 }
21804 return FirstInst;
21805 };
21806
21807 if (E->State == TreeEntry::SplitVectorize) {
21808 Res = FindLastInst();
21809 if (ArrayRef<TreeEntry *> Entries = getTreeEntries(Res); !Entries.empty()) {
21810 for (auto *E : Entries) {
21811 auto *I = dyn_cast_or_null<Instruction>(E->VectorizedValue);
21812 if (!I)
21813 I = &getLastInstructionInBundle(E);
21814 if (Res->getParent() == I->getParent() && Res->comesBefore(I))
21815 Res = I;
21816 }
21817 }
21818 EntryToLastInstruction.try_emplace(E, Res);
21819 return *Res;
21820 }
21821
21822 // Set insertpoint for gathered loads to the very first load.
21823 if (GatheredLoadsEntriesFirst.has_value() &&
21824 E->Idx >= *GatheredLoadsEntriesFirst && !E->isGather() &&
21825 Opcode == Instruction::Load) {
21826 Res = FindFirstInst();
21827 EntryToLastInstruction.try_emplace(E, Res);
21828 return *Res;
21829 }
21830
21831 // Set the insert point to the beginning of the basic block if the entry
21832 // should not be scheduled.
21833 auto FindScheduleBundle = [&](const TreeEntry *E) -> const ScheduleBundle * {
21834 if (E->isGather())
21835 return nullptr;
21836 // Found previously that the instruction do not need to be scheduled.
21837 const auto *It = BlocksSchedules.find(BB);
21838 if (It == BlocksSchedules.end())
21839 return nullptr;
21840 for (Value *V : E->Scalars) {
21841 auto *I = dyn_cast<Instruction>(V);
21842 if (!I || isa<PHINode>(I) ||
21843 (!E->isCopyableElement(I) && doesNotNeedToBeScheduled(I)))
21844 continue;
21845 ArrayRef<ScheduleBundle *> Bundles = It->second->getScheduleBundles(I);
21846 if (Bundles.empty())
21847 continue;
21848 const auto *It = find_if(
21849 Bundles, [&](ScheduleBundle *B) { return B->getTreeEntry() == E; });
21850 if (It != Bundles.end())
21851 return *It;
21852 }
21853 return nullptr;
21854 };
21855 const ScheduleBundle *Bundle = FindScheduleBundle(E);
21856 if (!E->isGather() && !Bundle) {
21857 if ((Opcode == Instruction::GetElementPtr &&
21858 any_of(E->Scalars,
21859 [](Value *V) {
21860 return !isa<GetElementPtrInst>(V) && isa<Instruction>(V);
21861 })) ||
21862 (all_of(E->Scalars,
21863 [&](Value *V) {
21864 return isa<PoisonValue>(V) ||
21865 (E->Idx == 0 &&
21866 isa<InsertElementInst, InsertValueInst>(V)) ||
21867 E->isCopyableElement(V) ||
21868 (!isVectorLikeInstWithConstOps(V) &&
21869 isUsedOutsideBlock(V));
21870 }) &&
21871 (!E->doesNotNeedToSchedule() ||
21872 any_of(E->Scalars,
21873 [&](Value *V) {
21874 if (!isa<Instruction>(V) ||
21875 (E->hasCopyableElements() && E->isCopyableElement(V)))
21876 return false;
21877 return !areAllOperandsNonInsts(V);
21878 }) ||
21879 none_of(E->Scalars, [&](Value *V) {
21880 if (!isa<Instruction>(V) ||
21881 (E->hasCopyableElements() && E->isCopyableElement(V)))
21882 return false;
21883 return MustGather.contains(V);
21884 }))))
21885 Res = FindLastInst();
21886 else
21887 Res = FindFirstInst();
21888 EntryToLastInstruction.try_emplace(E, Res);
21889 return *Res;
21890 }
21891
21892 // Find the last instruction. The common case should be that BB has been
21893 // scheduled, and the last instruction is VL.back(). So we start with
21894 // VL.back() and iterate over schedule data until we reach the end of the
21895 // bundle. The end of the bundle is marked by null ScheduleData.
21896 if (Bundle) {
21897 assert(!E->isGather() && "Gathered instructions should not be scheduled");
21898 Res = Bundle->getBundle().back()->getInst();
21899 EntryToLastInstruction.try_emplace(E, Res);
21900 return *Res;
21901 }
21902
21903 // LastInst can still be null at this point if there's either not an entry
21904 // for BB in BlocksSchedules or there's no ScheduleData available for
21905 // VL.back(). This can be the case if buildTreeRec aborts for various
21906 // reasons (e.g., the maximum recursion depth is reached, the maximum region
21907 // size is reached, etc.). ScheduleData is initialized in the scheduling
21908 // "dry-run".
21909 //
21910 // If this happens, we can still find the last instruction by brute force. We
21911 // iterate forwards from Front (inclusive) until we either see all
21912 // instructions in the bundle or reach the end of the block. If Front is the
21913 // last instruction in program order, LastInst will be set to Front, and we
21914 // will visit all the remaining instructions in the block.
21915 //
21916 // One of the reasons we exit early from buildTreeRec is to place an upper
21917 // bound on compile-time. Thus, taking an additional compile-time hit here is
21918 // not ideal. However, this should be exceedingly rare since it requires that
21919 // we both exit early from buildTreeRec and that the bundle be out-of-order
21920 // (causing us to iterate all the way to the end of the block).
21921 if (!Res)
21922 Res = FindLastInst();
21923 assert(Res && "Failed to find last instruction in bundle");
21924 EntryToLastInstruction.try_emplace(E, Res);
21925 return *Res;
21926}
21927
21928void BoUpSLP::setInsertPointAfterBundle(const TreeEntry *E) {
21929 auto *Front = E->getMainOp();
21930 Instruction *LastInst = &getLastInstructionInBundle(E);
21931 assert(LastInst && "Failed to find last instruction in bundle");
21932 BasicBlock::iterator LastInstIt = LastInst->getIterator();
21933 // If the instruction is PHI, set the insert point after all the PHIs.
21934 bool IsPHI = isa<PHINode>(LastInst);
21935 if (IsPHI) {
21936 LastInstIt = LastInst->getParent()->getFirstNonPHIIt();
21937 if (LastInstIt != LastInst->getParent()->end() &&
21938 LastInstIt->getParent()->isLandingPad())
21939 LastInstIt = std::next(LastInstIt);
21940 }
21941 if (IsPHI ||
21942 (!E->isGather() && E->State != TreeEntry::SplitVectorize &&
21943 (E->doesNotNeedToSchedule() ||
21944 (E->hasCopyableElements() && !E->isCopyableElement(LastInst) &&
21945 isUsedOutsideBlock(LastInst)))) ||
21946 (GatheredLoadsEntriesFirst.has_value() &&
21947 E->Idx >= *GatheredLoadsEntriesFirst && !E->isGather() &&
21948 E->getOpcode() == Instruction::Load)) {
21949 Builder.SetInsertPoint(LastInst->getParent(), LastInstIt);
21950 } else {
21951 // Set the insertion point after the last instruction in the bundle. Set the
21952 // debug location to Front.
21953 Builder.SetInsertPoint(
21954 LastInst->getParent(),
21955 LastInst->getNextNode()->getIterator());
21956 if (Instruction *Res = LastInstructionToPos.lookup(LastInst)) {
21957 Builder.SetInsertPoint(LastInst->getParent(), Res->getIterator());
21958 } else {
21959 Res = Builder.CreateAlignedLoad(Builder.getPtrTy(),
21960 PoisonValue::get(Builder.getPtrTy()),
21961 MaybeAlign());
21962 Builder.SetInsertPoint(LastInst->getParent(), Res->getIterator());
21963 eraseInstruction(Res);
21964 if (E->State != TreeEntry::SplitVectorize)
21965 LastInstructionToPos.try_emplace(LastInst, Res);
21966 }
21967 }
21968 Builder.SetCurrentDebugLocation(Front->getDebugLoc());
21969}
21970
21971Value *BoUpSLP::gather(
21972 ArrayRef<Value *> VL, Value *Root, Type *ScalarTy,
21973 function_ref<Value *(Value *, Value *, ArrayRef<int>)> CreateShuffle) {
21974 // List of instructions/lanes from current block and/or the blocks which are
21975 // part of the current loop. These instructions will be inserted at the end to
21976 // make it possible to optimize loops and hoist invariant instructions out of
21977 // the loops body with better chances for success.
21979 SmallSet<int, 4> PostponedIndices;
21980 Loop *L = LI->getLoopFor(Builder.GetInsertBlock());
21981 auto &&CheckPredecessor = [](BasicBlock *InstBB, BasicBlock *InsertBB) {
21982 SmallPtrSet<BasicBlock *, 4> Visited;
21983 while (InsertBB && InsertBB != InstBB && Visited.insert(InsertBB).second)
21984 InsertBB = InsertBB->getSinglePredecessor();
21985 return InsertBB && InsertBB == InstBB;
21986 };
21987 for (int I = 0, E = VL.size(); I < E; ++I) {
21988 if (auto *Inst = dyn_cast<Instruction>(VL[I]))
21989 if ((CheckPredecessor(Inst->getParent(), Builder.GetInsertBlock()) ||
21990 isVectorized(Inst) ||
21991 (L && (!Root || L->isLoopInvariant(Root)) && L->contains(Inst))) &&
21992 PostponedIndices.insert(I).second)
21993 PostponedInsts.emplace_back(Inst, I);
21994 }
21995
21996 auto &&CreateInsertElement = [this](Value *Vec, Value *V, unsigned Pos,
21997 Type *Ty) {
21998 Value *Scalar = V;
21999 // Drop NUW from trunc to avoid incorrect codegen.
22000 Value *Trunced;
22001 if (match(Scalar, m_NUWTrunc(m_Value(Trunced))))
22002 cast<TruncInst>(Scalar)->setHasNoUnsignedWrap(/*B=*/false);
22003 if (Scalar->getType() != Ty) {
22004 assert(Scalar->getType()->isIntOrIntVectorTy() &&
22005 Ty->isIntOrIntVectorTy() && "Expected integer types only.");
22006 Value *V = Scalar;
22007 if (auto *CI = dyn_cast<CastInst>(Scalar);
22009 Value *Op = CI->getOperand(0);
22010 if (auto *IOp = dyn_cast<Instruction>(Op);
22011 !IOp || !(isDeleted(IOp) || isVectorized(IOp)))
22012 V = Op;
22013 }
22014 Scalar = Builder.CreateIntCast(
22015 V, Ty, !isKnownNonNegative(Scalar, SimplifyQuery(*DL)));
22016 }
22017
22018 Instruction *InsElt;
22019 if (auto *VecTy = dyn_cast<FixedVectorType>(Scalar->getType())) {
22020 assert(SLPReVec && "FixedVectorType is not expected.");
22021 Vec =
22022 createInsertVector(Builder, Vec, Scalar, Pos * getNumElements(VecTy));
22023 auto *II = dyn_cast<Instruction>(Vec);
22024 if (!II)
22025 return Vec;
22026 InsElt = II;
22027 } else {
22028 Vec = Builder.CreateInsertElement(Vec, Scalar, Pos);
22029 InsElt = dyn_cast<InsertElementInst>(Vec);
22030 if (!InsElt)
22031 return Vec;
22032 }
22033 GatherShuffleExtractSeq.insert(InsElt);
22034 CSEBlocks.insert(InsElt->getParent());
22035 // Add to our 'need-to-extract' list.
22036 if (isa<Instruction>(V)) {
22037 ArrayRef<TreeEntry *> Entries = getTreeEntries(V);
22038 const auto *It = find_if(Entries, [&](const TreeEntry *E) {
22039 return !TransformedToGatherNodes.contains(E) &&
22040 !DeletedNodes.contains(E);
22041 });
22042 if (It != Entries.end()) {
22043 // Find which lane we need to extract.
22044 User *UserOp = nullptr;
22045 if (Scalar != V) {
22046 if (auto *SI = dyn_cast<Instruction>(Scalar))
22047 UserOp = SI;
22048 } else {
22049 if (V->getType()->isVectorTy()) {
22050 if (auto *SV = dyn_cast<ShuffleVectorInst>(InsElt);
22051 SV && SV->getOperand(0) != V && SV->getOperand(1) != V) {
22052 // Find shufflevector, caused by resize.
22053 auto FindOperand = [](Value *Vec, Value *V) -> Instruction * {
22054 if (auto *SV = dyn_cast<ShuffleVectorInst>(Vec)) {
22055 if (SV->getOperand(0) == V)
22056 return SV;
22057 if (SV->getOperand(1) == V)
22058 return SV;
22059 }
22060 return nullptr;
22061 };
22062 InsElt = nullptr;
22063 if (Instruction *User = FindOperand(SV->getOperand(0), V))
22064 InsElt = User;
22065 else if (Instruction *User = FindOperand(SV->getOperand(1), V))
22066 InsElt = User;
22067 assert(InsElt &&
22068 "Failed to find shufflevector, caused by resize.");
22069 } else if (SLPReVec && isa<ShuffleVectorInst>(InsElt)) {
22070 // ReVec gather used V directly as a shufflevector operand.
22071 // Register a nullptr-User external use so all remaining
22072 // in-IR uses of V get rewritten via replaceAllUsesWith,
22073 // and track V in ExternalUsesWithNonUsers to match the
22074 // bookkeeping done by buildExternalUses.
22075 unsigned FoundLane = (*It)->findLaneForValue(V);
22076 ExternalUses.emplace_back(V, nullptr, **It, FoundLane);
22077 ExternalUsesWithNonUsers.insert(V);
22078 }
22079 }
22080 UserOp = InsElt;
22081 }
22082 if (UserOp) {
22083 unsigned FoundLane = (*It)->findLaneForValue(V);
22084 ExternalUses.emplace_back(V, UserOp, **It, FoundLane);
22085 }
22086 }
22087 }
22088 return Vec;
22089 };
22090 auto *VecTy = getWidenedType(ScalarTy, VL.size());
22091 Value *Vec = PoisonValue::get(VecTy);
22092 SmallVector<int> NonConsts;
22093 SmallVector<int> Mask(VL.size());
22094 std::iota(Mask.begin(), Mask.end(), 0);
22095 Value *OriginalRoot = Root;
22096 if (auto *SV = dyn_cast_or_null<ShuffleVectorInst>(Root);
22097 SV && isa<PoisonValue>(SV->getOperand(1)) &&
22098 SV->getOperand(0)->getType() == VecTy) {
22099 Root = SV->getOperand(0);
22100 Mask.assign(SV->getShuffleMask().begin(), SV->getShuffleMask().end());
22101 }
22102 // Insert constant values at first.
22103 for (int I = 0, E = VL.size(); I < E; ++I) {
22104 if (PostponedIndices.contains(I))
22105 continue;
22106 if (!isConstant(VL[I])) {
22107 NonConsts.push_back(I);
22108 continue;
22109 }
22110 if (isa<PoisonValue>(VL[I]))
22111 continue;
22112 Vec = CreateInsertElement(Vec, VL[I], I, ScalarTy);
22113 Mask[I] = I + E;
22114 }
22115 if (Root) {
22116 if (isa<PoisonValue>(Vec)) {
22117 Vec = OriginalRoot;
22118 } else {
22119 Vec = CreateShuffle(Root, Vec, Mask);
22120 if (auto *OI = dyn_cast<Instruction>(OriginalRoot);
22121 OI && OI->use_empty() &&
22122 none_of(VectorizableTree, [&](const std::unique_ptr<TreeEntry> &TE) {
22123 return TE->VectorizedValue == OI;
22124 }))
22125 eraseInstruction(OI);
22126 }
22127 }
22128 // Insert non-constant values.
22129 for (int I : NonConsts)
22130 Vec = CreateInsertElement(Vec, VL[I], I, ScalarTy);
22131 // Append instructions, which are/may be part of the loop, in the end to make
22132 // it possible to hoist non-loop-based instructions.
22133 for (const std::pair<Value *, unsigned> &Pair : PostponedInsts)
22134 Vec = CreateInsertElement(Vec, Pair.first, Pair.second, ScalarTy);
22135
22136 return Vec;
22137}
22138
22139/// Merges shuffle masks and emits final shuffle instruction, if required. It
22140/// supports shuffling of 2 input vectors. It implements lazy shuffles emission,
22141/// when the actual shuffle instruction is generated only if this is actually
22142/// required. Otherwise, the shuffle instruction emission is delayed till the
22143/// end of the process, to reduce the number of emitted instructions and further
22144/// analysis/transformations.
22145/// The class also will look through the previously emitted shuffle instructions
22146/// and properly mark indices in mask as undef.
22147/// For example, given the code
22148/// \code
22149/// %s1 = shufflevector <2 x ty> %0, poison, <1, 0>
22150/// %s2 = shufflevector <2 x ty> %1, poison, <1, 0>
22151/// \endcode
22152/// and if need to emit shuffle of %s1 and %s2 with mask <1, 0, 3, 2>, it will
22153/// look through %s1 and %s2 and emit
22154/// \code
22155/// %res = shufflevector <2 x ty> %0, %1, <0, 1, 2, 3>
22156/// \endcode
22157/// instead.
22158/// If 2 operands are of different size, the smallest one will be resized and
22159/// the mask recalculated properly.
22160/// For example, given the code
22161/// \code
22162/// %s1 = shufflevector <2 x ty> %0, poison, <1, 0, 1, 0>
22163/// %s2 = shufflevector <2 x ty> %1, poison, <1, 0, 1, 0>
22164/// \endcode
22165/// and if need to emit shuffle of %s1 and %s2 with mask <1, 0, 5, 4>, it will
22166/// look through %s1 and %s2 and emit
22167/// \code
22168/// %res = shufflevector <2 x ty> %0, %1, <0, 1, 2, 3>
22169/// \endcode
22170/// instead.
22171class BoUpSLP::ShuffleInstructionBuilder final : public BaseShuffleAnalysis {
22172 bool IsFinalized = false;
22173 /// Combined mask for all applied operands and masks. It is built during
22174 /// analysis and actual emission of shuffle vector instructions.
22175 SmallVector<int> CommonMask;
22176 /// List of operands for the shuffle vector instruction. It hold at max 2
22177 /// operands, if the 3rd is going to be added, the first 2 are combined into
22178 /// shuffle with \p CommonMask mask, the first operand sets to be the
22179 /// resulting shuffle and the second operand sets to be the newly added
22180 /// operand. The \p CommonMask is transformed in the proper way after that.
22181 SmallVector<Value *, 2> InVectors;
22182 IRBuilderBase &Builder;
22183 BoUpSLP &R;
22184
22185 class ShuffleIRBuilder {
22186 IRBuilderBase &Builder;
22187 /// Holds all of the instructions that we gathered.
22188 SetVector<Instruction *> &GatherShuffleExtractSeq;
22189 /// A list of blocks that we are going to CSE.
22190 DenseSet<BasicBlock *> &CSEBlocks;
22191 /// Data layout.
22192 const DataLayout &DL;
22193
22194 public:
22195 ShuffleIRBuilder(IRBuilderBase &Builder,
22196 SetVector<Instruction *> &GatherShuffleExtractSeq,
22197 DenseSet<BasicBlock *> &CSEBlocks, const DataLayout &DL)
22198 : Builder(Builder), GatherShuffleExtractSeq(GatherShuffleExtractSeq),
22199 CSEBlocks(CSEBlocks), DL(DL) {}
22200 ~ShuffleIRBuilder() = default;
22201 /// Creates shufflevector for the 2 operands with the given mask.
22202 Value *createShuffleVector(Value *V1, Value *V2, ArrayRef<int> Mask) {
22203 if (V1->getType() != V2->getType()) {
22204 assert(V1->getType()->isIntOrIntVectorTy() &&
22205 V1->getType()->isIntOrIntVectorTy() &&
22206 "Expected integer vector types only.");
22207 if (V1->getType() != V2->getType()) {
22208 if (cast<VectorType>(V2->getType())
22209 ->getElementType()
22210 ->getIntegerBitWidth() < cast<VectorType>(V1->getType())
22211 ->getElementType()
22212 ->getIntegerBitWidth())
22213 V2 = Builder.CreateIntCast(
22214 V2, V1->getType(), !isKnownNonNegative(V2, SimplifyQuery(DL)));
22215 else
22216 V1 = Builder.CreateIntCast(
22218 }
22219 }
22220 Value *Vec = Builder.CreateShuffleVector(V1, V2, Mask);
22221 if (auto *I = dyn_cast<Instruction>(Vec)) {
22222 GatherShuffleExtractSeq.insert(I);
22223 CSEBlocks.insert(I->getParent());
22224 }
22225 return Vec;
22226 }
22227 /// Creates permutation of the single vector operand with the given mask, if
22228 /// it is not identity mask.
22229 Value *createShuffleVector(Value *V1, ArrayRef<int> Mask) {
22230 if (Mask.empty())
22231 return V1;
22232 unsigned VF = Mask.size();
22233 unsigned LocalVF = cast<FixedVectorType>(V1->getType())->getNumElements();
22234 if (VF == LocalVF && ShuffleVectorInst::isIdentityMask(Mask, VF))
22235 return V1;
22236 Value *Vec = Builder.CreateShuffleVector(V1, Mask);
22237 if (auto *I = dyn_cast<Instruction>(Vec)) {
22238 GatherShuffleExtractSeq.insert(I);
22239 CSEBlocks.insert(I->getParent());
22240 }
22241 return Vec;
22242 }
22243 Value *createIdentity(Value *V) { return V; }
22244 Value *createPoison(Type *Ty, unsigned VF) {
22245 return PoisonValue::get(getWidenedType(Ty, VF));
22246 }
22247 /// Resizes 2 input vector to match the sizes, if the they are not equal
22248 /// yet. The smallest vector is resized to the size of the larger vector.
22249 void resizeToMatch(Value *&V1, Value *&V2) {
22250 if (V1->getType() == V2->getType())
22251 return;
22252 int V1VF = cast<FixedVectorType>(V1->getType())->getNumElements();
22253 int V2VF = cast<FixedVectorType>(V2->getType())->getNumElements();
22254 int VF = std::max(V1VF, V2VF);
22255 int MinVF = std::min(V1VF, V2VF);
22256 SmallVector<int> IdentityMask(VF, PoisonMaskElem);
22257 std::iota(IdentityMask.begin(), std::next(IdentityMask.begin(), MinVF),
22258 0);
22259 Value *&Op = MinVF == V1VF ? V1 : V2;
22260 Op = Builder.CreateShuffleVector(Op, IdentityMask);
22261 if (auto *I = dyn_cast<Instruction>(Op)) {
22262 GatherShuffleExtractSeq.insert(I);
22263 CSEBlocks.insert(I->getParent());
22264 }
22265 if (MinVF == V1VF)
22266 V1 = Op;
22267 else
22268 V2 = Op;
22269 }
22270 };
22271
22272 /// Smart shuffle instruction emission, walks through shuffles trees and
22273 /// tries to find the best matching vector for the actual shuffle
22274 /// instruction.
22275 Value *createShuffle(Value *V1, Value *V2, ArrayRef<int> Mask) {
22276 assert(V1 && "Expected at least one vector value.");
22277 ShuffleIRBuilder ShuffleBuilder(Builder, R.GatherShuffleExtractSeq,
22278 R.CSEBlocks, *R.DL);
22279 return BaseShuffleAnalysis::createShuffle<Value *>(
22280 V1, V2, Mask, ShuffleBuilder, ScalarTy);
22281 }
22282
22283 /// Cast value \p V to the vector type with the same number of elements, but
22284 /// the base type \p ScalarTy.
22285 Value *castToScalarTyElem(Value *V,
22286 std::optional<bool> IsSigned = std::nullopt) {
22287 auto *VecTy = cast<VectorType>(V->getType());
22288 assert(getNumElements(VecTy) % getNumElements(ScalarTy) == 0);
22289 if (VecTy->getElementType() == ScalarTy->getScalarType())
22290 return V;
22291 return Builder.CreateIntCast(
22292 V, VectorType::get(ScalarTy->getScalarType(), VecTy->getElementCount()),
22293 IsSigned.value_or(!isKnownNonNegative(V, SimplifyQuery(*R.DL))));
22294 }
22295
22296 Value *getVectorizedValue(const TreeEntry &E) {
22297 Value *Vec = E.VectorizedValue;
22298 if (!Vec->getType()->isIntOrIntVectorTy())
22299 return Vec;
22300 return castToScalarTyElem(Vec, any_of(E.Scalars, [&](Value *V) {
22301 return !isa<PoisonValue>(V) &&
22302 !isKnownNonNegative(
22303 V, SimplifyQuery(*R.DL));
22304 }));
22305 }
22306
22307public:
22309 : BaseShuffleAnalysis(ScalarTy), Builder(Builder), R(R) {}
22310
22311 /// Adjusts extractelements after reusing them.
22312 Value *adjustExtracts(const TreeEntry *E, MutableArrayRef<int> Mask,
22313 ArrayRef<std::optional<TTI::ShuffleKind>> ShuffleKinds,
22314 unsigned NumParts, bool &UseVecBaseAsInput) {
22315 UseVecBaseAsInput = false;
22316 SmallPtrSet<Value *, 4> UniqueBases;
22317 Value *VecBase = nullptr;
22318 SmallVector<Value *> VL(E->Scalars.begin(), E->Scalars.end());
22319 if (!E->ReorderIndices.empty()) {
22320 SmallVector<int> ReorderMask(E->ReorderIndices.begin(),
22321 E->ReorderIndices.end());
22322 reorderScalars(VL, ReorderMask);
22323 }
22324 for (int I = 0, Sz = Mask.size(); I < Sz; ++I) {
22325 int Idx = Mask[I];
22326 if (Idx == PoisonMaskElem)
22327 continue;
22328 auto *EI = cast<ExtractElementInst>(VL[I]);
22329 VecBase = EI->getVectorOperand();
22330 if (ArrayRef<TreeEntry *> TEs = R.getTreeEntries(VecBase); !TEs.empty())
22331 VecBase = TEs.front()->VectorizedValue;
22332 assert(VecBase && "Expected vectorized value.");
22333 UniqueBases.insert(VecBase);
22334 // If the only one use is vectorized - can delete the extractelement
22335 // itself.
22336 if (!EI->hasOneUse() || R.ExternalUsesAsOriginalScalar.contains(EI) ||
22337 (E->UserTreeIndex && E->UserTreeIndex.EdgeIdx == UINT_MAX &&
22338 !R.isVectorized(EI) &&
22339 count_if(E->Scalars, [&](Value *V) { return V == EI; }) !=
22340 count_if(E->UserTreeIndex.UserTE->Scalars,
22341 [&](Value *V) { return V == EI; })) ||
22342 (NumParts != 1 && count(VL, EI) > 1) ||
22343 any_of(EI->users(), [&](User *U) {
22344 ArrayRef<TreeEntry *> UTEs = R.getTreeEntries(U);
22345 return UTEs.empty() || UTEs.size() > 1 ||
22346 any_of(UTEs,
22347 [&](const TreeEntry *TE) {
22348 return R.DeletedNodes.contains(TE) ||
22349 R.TransformedToGatherNodes.contains(TE);
22350 }) ||
22352 !R.areAllUsersVectorized(cast<Instruction>(U))) ||
22353 (!UTEs.empty() &&
22354 count_if(R.VectorizableTree,
22355 [&](const std::unique_ptr<TreeEntry> &TE) {
22356 return TE->UserTreeIndex.UserTE ==
22357 UTEs.front() &&
22358 is_contained(VL, EI);
22359 }) != 1);
22360 }))
22361 continue;
22362 R.eraseInstruction(EI);
22363 }
22364 if (NumParts == 1 || UniqueBases.size() == 1) {
22365 assert(VecBase && "Expected vectorized value.");
22366 return castToScalarTyElem(VecBase);
22367 }
22368 UseVecBaseAsInput = true;
22369 auto TransformToIdentity = [](MutableArrayRef<int> Mask) {
22370 for (auto [I, Idx] : enumerate(Mask))
22371 if (Idx != PoisonMaskElem)
22372 Idx = I;
22373 };
22374 // Perform multi-register vector shuffle, joining them into a single virtual
22375 // long vector.
22376 // Need to shuffle each part independently and then insert all this parts
22377 // into a long virtual vector register, forming the original vector.
22378 Value *Vec = nullptr;
22379 SmallVector<int> VecMask(Mask.size(), PoisonMaskElem);
22380 unsigned SliceSize = getPartNumElems(VL.size(), NumParts);
22381 for (unsigned Part : seq<unsigned>(NumParts)) {
22382 unsigned Limit = getNumElems(VL.size(), SliceSize, Part);
22383 ArrayRef<Value *> SubVL = ArrayRef(VL).slice(Part * SliceSize, Limit);
22384 MutableArrayRef<int> SubMask = Mask.slice(Part * SliceSize, Limit);
22385 constexpr int MaxBases = 2;
22386 SmallVector<Value *, MaxBases> Bases(MaxBases);
22387 auto VLMask = zip(SubVL, SubMask);
22388 const unsigned VF =
22389 accumulate(VLMask, 0U, [&](unsigned S, const auto &D) {
22390 if (std::get<1>(D) == PoisonMaskElem)
22391 return S;
22392 Value *VecOp =
22393 cast<ExtractElementInst>(std::get<0>(D))->getVectorOperand();
22394 if (ArrayRef<TreeEntry *> TEs = R.getTreeEntries(VecOp);
22395 !TEs.empty())
22396 VecOp = TEs.front()->VectorizedValue;
22397 assert(VecOp && "Expected vectorized value.");
22398 const unsigned Size =
22399 cast<FixedVectorType>(VecOp->getType())->getNumElements();
22400 return std::max(S, Size);
22401 });
22402 for (const auto [V, I] : VLMask) {
22403 if (I == PoisonMaskElem)
22404 continue;
22405 Value *VecOp = cast<ExtractElementInst>(V)->getVectorOperand();
22406 if (ArrayRef<TreeEntry *> TEs = R.getTreeEntries(VecOp); !TEs.empty())
22407 VecOp = TEs.front()->VectorizedValue;
22408 assert(VecOp && "Expected vectorized value.");
22409 VecOp = castToScalarTyElem(VecOp);
22410 Bases[I / VF] = VecOp;
22411 }
22412 if (!Bases.front())
22413 continue;
22414 Value *SubVec;
22415 if (Bases.back()) {
22416 SubVec = createShuffle(Bases.front(), Bases.back(), SubMask);
22417 TransformToIdentity(SubMask);
22418 } else {
22419 SubVec = Bases.front();
22420 }
22421 if (!Vec) {
22422 Vec = SubVec;
22423 assert((Part == 0 || all_of(seq<unsigned>(0, Part),
22424 [&](unsigned P) {
22425 ArrayRef<int> SubMask =
22426 Mask.slice(P * SliceSize,
22427 getNumElems(Mask.size(),
22428 SliceSize, P));
22429 return all_of(SubMask, [](int Idx) {
22430 return Idx == PoisonMaskElem;
22431 });
22432 })) &&
22433 "Expected first part or all previous parts masked.");
22434 copy(SubMask, std::next(VecMask.begin(), Part * SliceSize));
22435 } else {
22436 unsigned NewVF =
22437 cast<FixedVectorType>(Vec->getType())->getNumElements();
22438 if (Vec->getType() != SubVec->getType()) {
22439 unsigned SubVecVF =
22440 cast<FixedVectorType>(SubVec->getType())->getNumElements();
22441 NewVF = std::max(NewVF, SubVecVF);
22442 }
22443 // Adjust SubMask.
22444 for (int &Idx : SubMask)
22445 if (Idx != PoisonMaskElem)
22446 Idx += NewVF;
22447 copy(SubMask, std::next(VecMask.begin(), Part * SliceSize));
22448 Vec = createShuffle(Vec, SubVec, VecMask);
22449 TransformToIdentity(VecMask);
22450 }
22451 }
22452 copy(VecMask, Mask.begin());
22453 return Vec;
22454 }
22455 /// Checks if the specified entry \p E needs to be delayed because of its
22456 /// dependency nodes.
22457 std::optional<Value *>
22458 needToDelay(const TreeEntry *E,
22460 // No need to delay emission if all deps are ready.
22461 if (all_of(Deps, [](ArrayRef<const TreeEntry *> TEs) {
22462 return all_of(
22463 TEs, [](const TreeEntry *TE) { return TE->VectorizedValue; });
22464 }))
22465 return std::nullopt;
22466 // Postpone gather emission, will be emitted after the end of the
22467 // process to keep correct order.
22468 auto *ResVecTy = getWidenedType(ScalarTy, E->getVectorFactor());
22469 return Builder.CreateAlignedLoad(
22470 ResVecTy,
22471 PoisonValue::get(PointerType::getUnqual(ScalarTy->getContext())),
22472 MaybeAlign());
22473 }
22474 /// Reset the builder to handle perfect diamond match.
22476 IsFinalized = false;
22477 CommonMask.clear();
22478 InVectors.clear();
22479 }
22480 /// Adds 2 input vectors (in form of tree entries) and the mask for their
22481 /// shuffling.
22482 void add(const TreeEntry &E1, const TreeEntry &E2, ArrayRef<int> Mask) {
22483 Value *V1 = getVectorizedValue(E1);
22484 Value *V2 = getVectorizedValue(E2);
22485 add(V1, V2, Mask);
22486 }
22487 /// Adds single input vector (in form of tree entry) and the mask for its
22488 /// shuffling.
22489 void add(const TreeEntry &E1, ArrayRef<int> Mask) {
22490 Value *V1 = getVectorizedValue(E1);
22491 add(V1, Mask);
22492 }
22493 /// Adds 2 input vectors and the mask for their shuffling.
22494 void add(Value *V1, Value *V2, ArrayRef<int> Mask) {
22495 assert(V1 && V2 && !Mask.empty() && "Expected non-empty input vectors.");
22496 assert(isa<FixedVectorType>(V1->getType()) &&
22498 "castToScalarTyElem expects V1 and V2 to be FixedVectorType");
22499 V1 = castToScalarTyElem(V1);
22500 V2 = castToScalarTyElem(V2);
22501 if (InVectors.empty()) {
22502 InVectors.push_back(V1);
22503 InVectors.push_back(V2);
22504 CommonMask.assign(Mask.begin(), Mask.end());
22505 return;
22506 }
22507 Value *Vec = InVectors.front();
22508 if (InVectors.size() == 2) {
22509 Vec = createShuffle(Vec, InVectors.back(), CommonMask);
22510 transformMaskAfterShuffle(CommonMask, CommonMask);
22511 } else if (cast<FixedVectorType>(Vec->getType())->getNumElements() !=
22512 Mask.size()) {
22513 Vec = createShuffle(Vec, nullptr, CommonMask);
22514 transformMaskAfterShuffle(CommonMask, CommonMask);
22515 }
22516 V1 = createShuffle(V1, V2, Mask);
22517 unsigned VF = std::max(getVF(V1), getVF(Vec));
22518 for (unsigned Idx = 0, Sz = CommonMask.size(); Idx < Sz; ++Idx)
22519 if (Mask[Idx] != PoisonMaskElem)
22520 CommonMask[Idx] = Idx + VF;
22521 InVectors.front() = Vec;
22522 if (InVectors.size() == 2)
22523 InVectors.back() = V1;
22524 else
22525 InVectors.push_back(V1);
22526 }
22527 /// Adds another one input vector and the mask for the shuffling.
22528 void add(Value *V1, ArrayRef<int> Mask, bool = false) {
22529 assert(isa<FixedVectorType>(V1->getType()) &&
22530 "castToScalarTyElem expects V1 to be FixedVectorType");
22531 V1 = castToScalarTyElem(V1);
22532 if (InVectors.empty()) {
22533 InVectors.push_back(V1);
22534 CommonMask.assign(Mask.begin(), Mask.end());
22535 return;
22536 }
22537 const auto *It = find(InVectors, V1);
22538 if (It == InVectors.end()) {
22539 if (InVectors.size() == 2 ||
22540 InVectors.front()->getType() != V1->getType()) {
22541 Value *V = InVectors.front();
22542 if (InVectors.size() == 2) {
22543 V = createShuffle(InVectors.front(), InVectors.back(), CommonMask);
22544 transformMaskAfterShuffle(CommonMask, CommonMask);
22545 } else if (cast<FixedVectorType>(V->getType())->getNumElements() !=
22546 CommonMask.size()) {
22547 V = createShuffle(InVectors.front(), nullptr, CommonMask);
22548 transformMaskAfterShuffle(CommonMask, CommonMask);
22549 }
22550 unsigned VF = std::max(CommonMask.size(), Mask.size());
22551 for (unsigned Idx = 0, Sz = CommonMask.size(); Idx < Sz; ++Idx)
22552 if (CommonMask[Idx] == PoisonMaskElem && Mask[Idx] != PoisonMaskElem)
22553 CommonMask[Idx] = V->getType() != V1->getType()
22554 ? Idx + VF
22555 : Mask[Idx] + getVF(V1);
22556 if (V->getType() != V1->getType())
22557 V1 = createShuffle(V1, nullptr, Mask);
22558 InVectors.front() = V;
22559 if (InVectors.size() == 2)
22560 InVectors.back() = V1;
22561 else
22562 InVectors.push_back(V1);
22563 return;
22564 }
22565 // Check if second vector is required if the used elements are already
22566 // used from the first one.
22567 for (unsigned Idx = 0, Sz = CommonMask.size(); Idx < Sz; ++Idx)
22568 if (Mask[Idx] != PoisonMaskElem && CommonMask[Idx] == PoisonMaskElem) {
22569 InVectors.push_back(V1);
22570 break;
22571 }
22572 }
22573 unsigned VF = 0;
22574 for (Value *V : InVectors)
22575 VF = std::max(VF, getVF(V));
22576 for (unsigned Idx = 0, Sz = CommonMask.size(); Idx < Sz; ++Idx)
22577 if (Mask[Idx] != PoisonMaskElem && CommonMask[Idx] == PoisonMaskElem)
22578 CommonMask[Idx] = Mask[Idx] + (It == InVectors.begin() ? 0 : VF);
22579 }
22580 /// Adds another one input vector and the mask for the shuffling.
22582 SmallVector<int> NewMask;
22583 inversePermutation(Order, NewMask);
22584 add(V1, NewMask);
22585 }
22586 Value *gather(ArrayRef<Value *> VL, unsigned MaskVF = 0,
22587 Value *Root = nullptr) {
22588 return R.gather(VL, Root, ScalarTy,
22589 [&](Value *V1, Value *V2, ArrayRef<int> Mask) {
22590 return createShuffle(V1, V2, Mask);
22591 });
22592 }
22593 Value *createFreeze(Value *V) { return Builder.CreateFreeze(V); }
22594 /// Finalize emission of the shuffles.
22595 /// \param Action the action (if any) to be performed before final applying of
22596 /// the \p ExtMask mask.
22598 ArrayRef<int> ExtMask,
22599 ArrayRef<std::pair<const TreeEntry *, unsigned>> SubVectors,
22600 ArrayRef<int> SubVectorsMask, unsigned VF = 0,
22603 Action = {}) {
22604 IsFinalized = true;
22605 if (Action) {
22606 Value *Vec = InVectors.front();
22607 if (InVectors.size() == 2) {
22608 Vec = createShuffle(Vec, InVectors.back(), CommonMask);
22609 InVectors.pop_back();
22610 } else {
22611 Vec = createShuffle(Vec, nullptr, CommonMask);
22612 }
22613 transformMaskAfterShuffle(CommonMask, CommonMask);
22614 assert(VF > 0 &&
22615 "Expected vector length for the final value before action.");
22616 unsigned VecVF = cast<FixedVectorType>(Vec->getType())->getNumElements();
22617 if (VecVF < VF) {
22618 SmallVector<int> ResizeMask(VF, PoisonMaskElem);
22619 std::iota(ResizeMask.begin(), std::next(ResizeMask.begin(), VecVF), 0);
22620 Vec = createShuffle(Vec, nullptr, ResizeMask);
22621 }
22622 Action(Vec, CommonMask, [this](Value *V1, Value *V2, ArrayRef<int> Mask) {
22623 return createShuffle(V1, V2, Mask);
22624 });
22625 InVectors.front() = Vec;
22626 }
22627 if (!SubVectors.empty()) {
22628 Value *Vec = InVectors.front();
22629 if (InVectors.size() == 2) {
22630 Vec = createShuffle(Vec, InVectors.back(), CommonMask);
22631 InVectors.pop_back();
22632 } else {
22633 Vec = createShuffle(Vec, nullptr, CommonMask);
22634 }
22635 transformMaskAfterShuffle(CommonMask, CommonMask);
22636 auto CreateSubVectors = [&](Value *Vec,
22637 SmallVectorImpl<int> &CommonMask) {
22638 for (auto [E, Idx] : SubVectors) {
22639 Value *V = getVectorizedValue(*E);
22640 unsigned InsertionIndex = Idx * getNumElements(ScalarTy);
22641 // Use scalar version of the SCalarType to correctly handle shuffles
22642 // for revectorization. The revectorization mode operates by the
22643 // vectors, but here we need to operate on the scalars, because the
22644 // masks were already transformed for the vector elements and we don't
22645 // need doing this transformation again.
22646 Type *OrigScalarTy = ScalarTy;
22647 ScalarTy = ScalarTy->getScalarType();
22648 Vec = createInsertVector(
22649 Builder, Vec, V, InsertionIndex,
22650 std::bind(&ShuffleInstructionBuilder::createShuffle, this, _1, _2,
22651 _3));
22652 ScalarTy = OrigScalarTy;
22653 if (!CommonMask.empty()) {
22654 std::iota(std::next(CommonMask.begin(), Idx),
22655 std::next(CommonMask.begin(), Idx + E->getVectorFactor()),
22656 Idx);
22657 }
22658 }
22659 return Vec;
22660 };
22661 if (SubVectorsMask.empty()) {
22662 Vec = CreateSubVectors(Vec, CommonMask);
22663 } else {
22664 SmallVector<int> SVMask(CommonMask.size(), PoisonMaskElem);
22665 copy(SubVectorsMask, SVMask.begin());
22666 for (auto [I1, I2] : zip(SVMask, CommonMask)) {
22667 if (I2 != PoisonMaskElem) {
22668 assert(I1 == PoisonMaskElem && "Expected unused subvectors mask");
22669 I1 = I2 + CommonMask.size();
22670 }
22671 }
22672 Value *InsertVec =
22673 CreateSubVectors(PoisonValue::get(Vec->getType()), CommonMask);
22674 Vec = createShuffle(InsertVec, Vec, SVMask);
22675 transformMaskAfterShuffle(CommonMask, SVMask);
22676 }
22677 InVectors.front() = Vec;
22678 }
22679
22680 if (!ExtMask.empty()) {
22681 if (CommonMask.empty()) {
22682 CommonMask.assign(ExtMask.begin(), ExtMask.end());
22683 } else {
22684 SmallVector<int> NewMask(ExtMask.size(), PoisonMaskElem);
22685 for (int I = 0, Sz = ExtMask.size(); I < Sz; ++I) {
22686 if (ExtMask[I] == PoisonMaskElem)
22687 continue;
22688 NewMask[I] = CommonMask[ExtMask[I]];
22689 }
22690 CommonMask.swap(NewMask);
22691 }
22692 }
22693 if (CommonMask.empty()) {
22694 assert(InVectors.size() == 1 && "Expected only one vector with no mask");
22695 return InVectors.front();
22696 }
22697 if (InVectors.size() == 2)
22698 return createShuffle(InVectors.front(), InVectors.back(), CommonMask);
22699 return createShuffle(InVectors.front(), nullptr, CommonMask);
22700 }
22701
22703 assert((IsFinalized || CommonMask.empty()) &&
22704 "Shuffle construction must be finalized.");
22705 }
22706};
22707
22708Value *BoUpSLP::vectorizeOperand(TreeEntry *E, unsigned NodeIdx) {
22709 return vectorizeTree(getOperandEntry(E, NodeIdx));
22710}
22711
22712template <typename BVTy, typename ResTy, typename... Args>
22713ResTy BoUpSLP::processBuildVector(const TreeEntry *E, Type *ScalarTy,
22714 Args &...Params) {
22715 assert((E->isGather() || TransformedToGatherNodes.contains(E)) &&
22716 "Expected gather node.");
22717 unsigned VF = E->getVectorFactor();
22718
22719 bool NeedFreeze = false;
22720 SmallVector<Value *> GatheredScalars(E->Scalars.begin(), E->Scalars.end());
22721 // Do not process split vectorize node, marked to be gathers/buildvectors.
22723 E->CombinedEntriesWithIndices.size());
22724 if (E->State == TreeEntry::SplitVectorize &&
22725 TransformedToGatherNodes.contains(E)) {
22726 SubVectors.clear();
22727 } else {
22728 // Clear values, to be replaced by insertvector instructions.
22729 for (auto [EIdx, Idx] : E->CombinedEntriesWithIndices)
22730 for_each(MutableArrayRef(GatheredScalars)
22731 .slice(Idx, VectorizableTree[EIdx]->getVectorFactor()),
22732 [&](Value *&V) { V = PoisonValue::get(V->getType()); });
22733 transform(
22734 E->CombinedEntriesWithIndices, SubVectors.begin(), [&](const auto &P) {
22735 return std::make_pair(VectorizableTree[P.first].get(), P.second);
22736 });
22737 }
22738 // Build a mask out of the reorder indices and reorder scalars per this
22739 // mask.
22740 SmallVector<int> ReorderMask(E->ReorderIndices.begin(),
22741 E->ReorderIndices.end());
22742 if (!ReorderMask.empty())
22743 reorderScalars(GatheredScalars, ReorderMask);
22744 SmallVector<int> SubVectorsMask;
22745 inversePermutation(E->ReorderIndices, SubVectorsMask);
22746 // Transform non-clustered elements in the mask to poison (-1).
22747 // "Clustered" operations will be reordered using this mask later.
22748 if (!SubVectors.empty() && !SubVectorsMask.empty()) {
22749 for (unsigned I : seq<unsigned>(GatheredScalars.size()))
22750 if (E->Scalars[I] == GatheredScalars[ReorderMask[I]])
22751 SubVectorsMask[ReorderMask[I]] = PoisonMaskElem;
22752 } else {
22753 SubVectorsMask.clear();
22754 }
22755 SmallVector<Value *> StoredGS(GatheredScalars);
22756 auto FindReusedSplat = [&](MutableArrayRef<int> Mask, unsigned InputVF,
22757 unsigned I, unsigned SliceSize,
22758 bool IsNotPoisonous) {
22759 if (!isSplat(E->Scalars) || none_of(E->Scalars, [](Value *V) {
22760 return isa<UndefValue>(V) && !isa<PoisonValue>(V);
22761 }))
22762 return false;
22763 TreeEntry *UserTE = E->UserTreeIndex.UserTE;
22764 unsigned EdgeIdx = E->UserTreeIndex.EdgeIdx;
22765 if (UserTE->getNumOperands() != 2)
22766 return false;
22767 if (!IsNotPoisonous) {
22768 auto *It = find_if(ArrayRef(VectorizableTree).drop_front(UserTE->Idx + 1),
22769 [=](const std::unique_ptr<TreeEntry> &TE) {
22770 return TE->UserTreeIndex.UserTE == UserTE &&
22771 TE->UserTreeIndex.EdgeIdx != EdgeIdx;
22772 });
22773 if (It == VectorizableTree.end())
22774 return false;
22775 SmallVector<Value *> GS((*It)->Scalars.begin(), (*It)->Scalars.end());
22776 if (!(*It)->ReorderIndices.empty()) {
22777 inversePermutation((*It)->ReorderIndices, ReorderMask);
22778 reorderScalars(GS, ReorderMask);
22779 }
22780 if (!all_of(zip(GatheredScalars, GS), [&](const auto &P) {
22781 Value *V0 = std::get<0>(P);
22782 Value *V1 = std::get<1>(P);
22783 return !isa<UndefValue>(V0) || isa<PoisonValue>(V0) ||
22784 (isa<UndefValue>(V0) && !isa<PoisonValue>(V0) &&
22785 is_contained(E->Scalars, V1));
22786 }))
22787 return false;
22788 }
22789 int Idx;
22790 if ((Mask.size() < InputVF &&
22791 ShuffleVectorInst::isExtractSubvectorMask(Mask, InputVF, Idx) &&
22792 Idx == 0) ||
22793 (Mask.size() == InputVF &&
22794 ShuffleVectorInst::isIdentityMask(Mask, Mask.size()))) {
22795 std::iota(
22796 std::next(Mask.begin(), I * SliceSize),
22797 std::next(Mask.begin(),
22798 I * SliceSize + getNumElems(Mask.size(), SliceSize, I)),
22799 0);
22800 } else {
22801 unsigned IVal =
22802 *find_if_not(Mask, [](int Idx) { return Idx == PoisonMaskElem; });
22803 std::fill(
22804 std::next(Mask.begin(), I * SliceSize),
22805 std::next(Mask.begin(),
22806 I * SliceSize + getNumElems(Mask.size(), SliceSize, I)),
22807 IVal);
22808 }
22809 return true;
22810 };
22811 BVTy ShuffleBuilder(ScalarTy, Params...);
22812 ResTy Res = ResTy();
22813 SmallVector<int> Mask;
22814 SmallVector<int> ExtractMask(GatheredScalars.size(), PoisonMaskElem);
22816 Value *ExtractVecBase = nullptr;
22817 bool UseVecBaseAsInput = false;
22820 Type *OrigScalarTy = GatheredScalars.front()->getType();
22821 auto *VecTy = getWidenedType(ScalarTy, GatheredScalars.size());
22822 unsigned NumParts = getNumberOfParts(VecTy, ScalarTy, GatheredScalars.size());
22823 if (!all_of(GatheredScalars, IsaPred<UndefValue>)) {
22824 // Check for gathered extracts.
22825 bool Resized = false;
22826 ExtractShuffles =
22827 tryToGatherExtractElements(GatheredScalars, ExtractMask, NumParts);
22828 if (!ExtractShuffles.empty()) {
22829 SmallVector<const TreeEntry *> ExtractEntries;
22830 for (auto [Idx, I] : enumerate(ExtractMask)) {
22831 if (I == PoisonMaskElem)
22832 continue;
22833 if (ArrayRef<TreeEntry *> TEs = getTreeEntries(
22834 cast<ExtractElementInst>(StoredGS[Idx])->getVectorOperand());
22835 !TEs.empty())
22836 ExtractEntries.append(TEs.begin(), TEs.end());
22837 }
22838 if (std::optional<ResTy> Delayed =
22839 ShuffleBuilder.needToDelay(E, ExtractEntries)) {
22840 // Delay emission of gathers which are not ready yet.
22841 PostponedGathers.insert(E);
22842 // Postpone gather emission, will be emitted after the end of the
22843 // process to keep correct order.
22844 return *Delayed;
22845 }
22846 if (Value *VecBase = ShuffleBuilder.adjustExtracts(
22847 E, ExtractMask, ExtractShuffles, NumParts, UseVecBaseAsInput)) {
22848 ExtractVecBase = VecBase;
22849 if (auto *VecBaseTy = dyn_cast<FixedVectorType>(VecBase->getType()))
22850 if (VF == VecBaseTy->getNumElements() &&
22851 GatheredScalars.size() != VF) {
22852 Resized = true;
22853 GatheredScalars.append(VF - GatheredScalars.size(),
22854 PoisonValue::get(OrigScalarTy));
22855 NumParts = getNumberOfParts(getWidenedType(OrigScalarTy, VF),
22856 OrigScalarTy, VF);
22857 }
22858 }
22859 }
22860 // Gather extracts after we check for full matched gathers only.
22861 if (!ExtractShuffles.empty() || !E->hasState() ||
22862 E->getOpcode() != Instruction::Load ||
22863 (((E->hasState() && E->getOpcode() == Instruction::Load) ||
22864 any_of(E->Scalars, IsaPred<LoadInst>)) &&
22865 any_of(E->Scalars,
22866 [this](Value *V) {
22867 return isa<LoadInst>(V) && isVectorized(V);
22868 })) ||
22869 (E->hasState() && E->isAltShuffle()) ||
22870 all_of(E->Scalars, [this](Value *V) { return isVectorized(V); }) ||
22871 isSplat(E->Scalars) ||
22872 (E->Scalars != GatheredScalars && GatheredScalars.size() <= 2)) {
22873 GatherShuffles =
22874 isGatherShuffledEntry(E, GatheredScalars, Mask, Entries, NumParts);
22875 }
22876 if (!GatherShuffles.empty()) {
22877 if (std::optional<ResTy> Delayed =
22878 ShuffleBuilder.needToDelay(E, Entries)) {
22879 // Delay emission of gathers which are not ready yet.
22880 PostponedGathers.insert(E);
22881 // Postpone gather emission, will be emitted after the end of the
22882 // process to keep correct order.
22883 return *Delayed;
22884 }
22885 // Match against the expanded vector of the gather node, so that poison
22886 // lanes of the matched entry cannot wildcard-match its real scalars.
22887 auto IsFullVectorMatch = [&](const TreeEntry *FrontTE) {
22888 SmallVector<int> CommonMask = E->getCommonMask();
22889 SmallVector<Value *> Expanded(E->getVectorFactor());
22890 for (unsigned I : seq<unsigned>(E->getVectorFactor()))
22891 Expanded[I] = CommonMask.empty() ? E->Scalars[I]
22892 : CommonMask[I] == PoisonMaskElem
22893 ? PoisonValue::get(OrigScalarTy)
22894 : E->Scalars[CommonMask[I]];
22895 return FrontTE->isSame(Expanded);
22896 };
22897 if (GatherShuffles.size() == 1 &&
22898 *GatherShuffles.front() == TTI::SK_PermuteSingleSrc &&
22899 (Entries.front().front()->isSame(E->Scalars) ||
22900 IsFullVectorMatch(Entries.front().front()))) {
22901 // Perfect match in the graph, will reuse the previously vectorized
22902 // node. Cost is 0.
22903 LLVM_DEBUG(dbgs() << "SLP: perfect diamond match for gather bundle "
22904 << shortBundleName(E->Scalars, E->Idx) << ".\n");
22905 // Restore the mask for previous partially matched values.
22906 Mask.resize(E->Scalars.size());
22907 const TreeEntry *FrontTE = Entries.front().front();
22908 if (FrontTE->ReorderIndices.empty() && E->ReorderIndices.empty() &&
22909 ((FrontTE->ReuseShuffleIndices.empty() &&
22910 E->Scalars.size() == FrontTE->Scalars.size()) ||
22911 (E->Scalars.size() == FrontTE->ReuseShuffleIndices.size()))) {
22912 std::iota(Mask.begin(), Mask.end(), 0);
22913 } else {
22914 for (auto [I, V] : enumerate(E->Scalars)) {
22915 if (isa<PoisonValue>(V)) {
22916 Mask[I] = PoisonMaskElem;
22917 continue;
22918 }
22919 Mask[I] = FrontTE->findLaneForValue(V);
22920 }
22921 }
22922 // Reset the builder(s) to correctly handle perfect diamond matched
22923 // nodes.
22924 ShuffleBuilder.resetForSameNode();
22925 // Full matched entry found, no need to insert subvectors.
22926 if ((IsFullVectorMatch(FrontTE) &&
22927 FrontTE->ReuseShuffleIndices.empty() &&
22928 FrontTE->ReorderIndices.empty() &&
22929 E->getVectorFactor() == FrontTE->getVectorFactor()) ||
22930 (equal(E->Scalars, FrontTE->Scalars) &&
22931 equal(E->ReorderIndices, FrontTE->ReorderIndices) &&
22932 equal(E->ReuseShuffleIndices, FrontTE->ReuseShuffleIndices))) {
22933 Mask.resize(FrontTE->getVectorFactor());
22934 std::iota(Mask.begin(), Mask.end(), 0);
22935 ShuffleBuilder.add(*FrontTE, Mask);
22936 Res = ShuffleBuilder.finalize({}, {}, {});
22937 } else {
22938 ShuffleBuilder.add(*FrontTE, Mask);
22939 Res = ShuffleBuilder.finalize(E->getCommonMask(), {}, {});
22940 }
22941 return Res;
22942 }
22943 if (!Resized) {
22944 if (GatheredScalars.size() != VF &&
22945 any_of(Entries, [&](ArrayRef<const TreeEntry *> TEs) {
22946 return any_of(TEs, [&](const TreeEntry *TE) {
22947 return TE->getVectorFactor() == VF;
22948 });
22949 }))
22950 GatheredScalars.append(VF - GatheredScalars.size(),
22951 PoisonValue::get(OrigScalarTy));
22952 }
22953 // Remove shuffled elements from list of gathers.
22954 for (int I = 0, Sz = Mask.size(); I < Sz; ++I) {
22955 if (Mask[I] != PoisonMaskElem)
22956 GatheredScalars[I] = PoisonValue::get(OrigScalarTy);
22957 }
22958 }
22959 }
22960 auto TryPackScalars = [&](SmallVectorImpl<Value *> &Scalars,
22961 SmallVectorImpl<int> &ReuseMask,
22962 bool IsRootPoison) {
22963 // For splats with can emit broadcasts instead of gathers, so try to find
22964 // such sequences.
22965 bool IsSplat = IsRootPoison && isSplat(Scalars) &&
22966 (Scalars.size() > 2 || Scalars.front() == Scalars.back());
22967 Scalars.append(VF - Scalars.size(), PoisonValue::get(OrigScalarTy));
22968 SmallVector<int> UndefPos;
22969 DenseMap<Value *, unsigned> UniquePositions;
22970 // Gather unique non-const values and all constant values.
22971 // For repeated values, just shuffle them.
22972 int NumNonConsts = 0;
22973 int SinglePos = 0;
22974 for (auto [I, V] : enumerate(Scalars)) {
22975 if (isa<UndefValue>(V)) {
22976 if (!isa<PoisonValue>(V)) {
22977 ReuseMask[I] = I;
22978 UndefPos.push_back(I);
22979 }
22980 continue;
22981 }
22982 if (isConstant(V)) {
22983 ReuseMask[I] = I;
22984 continue;
22985 }
22986 ++NumNonConsts;
22987 SinglePos = I;
22988 Value *OrigV = V;
22989 Scalars[I] = PoisonValue::get(OrigScalarTy);
22990 if (IsSplat) {
22991 Scalars.front() = OrigV;
22992 ReuseMask[I] = 0;
22993 } else {
22994 const auto Res = UniquePositions.try_emplace(OrigV, I);
22995 Scalars[Res.first->second] = OrigV;
22996 ReuseMask[I] = Res.first->second;
22997 }
22998 }
22999 if (NumNonConsts == 1) {
23000 // Restore single insert element.
23001 if (IsSplat) {
23002 ReuseMask.assign(VF, PoisonMaskElem);
23003 std::swap(Scalars.front(), Scalars[SinglePos]);
23004 if (!UndefPos.empty() && UndefPos.front() == 0)
23005 Scalars.front() = UndefValue::get(OrigScalarTy);
23006 }
23007 ReuseMask[SinglePos] = SinglePos;
23008 } else if (!UndefPos.empty() && IsSplat) {
23009 // For undef values, try to replace them with the simple broadcast.
23010 // We can do it if the broadcasted value is guaranteed to be
23011 // non-poisonous, or by freezing the incoming scalar value first.
23012 auto *It = find_if(Scalars, [this, E](Value *V) {
23013 return !isa<UndefValue>(V) &&
23015 (E->UserTreeIndex && any_of(V->uses(), [E](const Use &U) {
23016 // Check if the value already used in the same operation in
23017 // one of the nodes already.
23018 return E->UserTreeIndex.EdgeIdx != U.getOperandNo() &&
23019 is_contained(E->UserTreeIndex.UserTE->Scalars,
23020 U.getUser());
23021 })));
23022 });
23023 if (It != Scalars.end()) {
23024 // Replace undefs by the non-poisoned scalars and emit broadcast.
23025 int Pos = std::distance(Scalars.begin(), It);
23026 for (int I : UndefPos) {
23027 // Set the undef position to the non-poisoned scalar.
23028 ReuseMask[I] = Pos;
23029 // Replace the undef by the poison, in the mask it is replaced by
23030 // non-poisoned scalar already.
23031 if (I != Pos)
23032 Scalars[I] = PoisonValue::get(OrigScalarTy);
23033 }
23034 } else {
23035 // Replace undefs by the poisons, emit broadcast and then emit
23036 // freeze.
23037 for (int I : UndefPos) {
23038 ReuseMask[I] = PoisonMaskElem;
23039 if (isa<UndefValue>(Scalars[I]))
23040 Scalars[I] = PoisonValue::get(OrigScalarTy);
23041 }
23042 NeedFreeze = true;
23043 }
23044 }
23045 };
23046 if (!ExtractShuffles.empty() || !GatherShuffles.empty()) {
23047 bool IsNonPoisoned = true;
23048 bool IsUsedInExpr = true;
23049 Value *Vec1 = nullptr;
23050 if (!ExtractShuffles.empty()) {
23051 // Gather of extractelements can be represented as just a shuffle of
23052 // a single/two vectors the scalars are extracted from.
23053 // Find input vectors.
23054 Value *Vec2 = nullptr;
23055 for (unsigned I = 0, Sz = ExtractMask.size(); I < Sz; ++I) {
23056 if (!Mask.empty() && Mask[I] != PoisonMaskElem)
23057 ExtractMask[I] = PoisonMaskElem;
23058 }
23059 if (UseVecBaseAsInput) {
23060 Vec1 = ExtractVecBase;
23061 } else {
23062 for (unsigned I = 0, Sz = ExtractMask.size(); I < Sz; ++I) {
23063 if (ExtractMask[I] == PoisonMaskElem)
23064 continue;
23065 if (isa<UndefValue>(StoredGS[I]))
23066 continue;
23067 auto *EI = cast<ExtractElementInst>(StoredGS[I]);
23068 Value *VecOp = EI->getVectorOperand();
23069 if (ArrayRef<TreeEntry *> TEs = getTreeEntries(VecOp);
23070 !TEs.empty() && TEs.front()->VectorizedValue)
23071 VecOp = TEs.front()->VectorizedValue;
23072 if (!Vec1) {
23073 Vec1 = VecOp;
23074 } else if (Vec1 != VecOp) {
23075 assert((!Vec2 || Vec2 == VecOp) &&
23076 "Expected only 1 or 2 vectors shuffle.");
23077 Vec2 = VecOp;
23078 }
23079 }
23080 }
23081 if (Vec2) {
23082 IsUsedInExpr = false;
23083 IsNonPoisoned &= isGuaranteedNotToBePoison(Vec1, AC) &&
23084 isGuaranteedNotToBePoison(Vec2, AC);
23085 ShuffleBuilder.add(Vec1, Vec2, ExtractMask);
23086 } else if (Vec1) {
23087 bool IsNotPoisonedVec = isGuaranteedNotToBePoison(Vec1, AC);
23088 IsUsedInExpr &= FindReusedSplat(
23089 ExtractMask,
23090 cast<FixedVectorType>(Vec1->getType())->getNumElements(), 0,
23091 ExtractMask.size(), IsNotPoisonedVec);
23092 ShuffleBuilder.add(Vec1, ExtractMask, /*ForExtracts=*/true);
23093 IsNonPoisoned &= IsNotPoisonedVec;
23094 } else {
23095 IsUsedInExpr = false;
23096 ShuffleBuilder.add(PoisonValue::get(VecTy), ExtractMask,
23097 /*ForExtracts=*/true);
23098 }
23099 }
23100 if (!GatherShuffles.empty()) {
23101 unsigned SliceSize = getPartNumElems(VF, NumParts);
23102 if (Mask.size() == E->Scalars.size())
23103 SliceSize = getPartNumElems(
23104 E->Scalars.size(),
23105 getNumberOfParts(VecTy, ScalarTy, E->Scalars.size()));
23106 SmallVector<int> VecMask(Mask.size(), PoisonMaskElem);
23107 for (const auto [I, TEs] : enumerate(Entries)) {
23108 if (TEs.empty()) {
23109 assert(!GatherShuffles[I] &&
23110 "No shuffles with empty entries list expected.");
23111 continue;
23112 }
23113 assert((TEs.size() == 1 || TEs.size() == 2) &&
23114 "Expected shuffle of 1 or 2 entries.");
23115 unsigned Limit = getNumElems(Mask.size(), SliceSize, I);
23116 auto SubMask = ArrayRef(Mask).slice(I * SliceSize, Limit);
23117 VecMask.assign(VecMask.size(), PoisonMaskElem);
23118 copy(SubMask, std::next(VecMask.begin(), I * SliceSize));
23119 if (TEs.size() == 1) {
23120 bool IsNotPoisonedVec =
23121 TEs.front()->VectorizedValue
23122 ? isGuaranteedNotToBePoison(TEs.front()->VectorizedValue, AC)
23123 : true;
23124 IsUsedInExpr &=
23125 FindReusedSplat(VecMask, TEs.front()->getVectorFactor(), I,
23126 SliceSize, IsNotPoisonedVec);
23127 ShuffleBuilder.add(*TEs.front(), VecMask);
23128 IsNonPoisoned &= IsNotPoisonedVec;
23129 } else {
23130 IsUsedInExpr = false;
23131 ShuffleBuilder.add(*TEs.front(), *TEs.back(), VecMask);
23132 if (TEs.front()->VectorizedValue && TEs.back()->VectorizedValue)
23133 IsNonPoisoned &=
23134 isGuaranteedNotToBePoison(TEs.front()->VectorizedValue, AC) &&
23135 isGuaranteedNotToBePoison(TEs.back()->VectorizedValue, AC);
23136 }
23137 }
23138 }
23139 // Try to figure out best way to combine values: build a shuffle and insert
23140 // elements or just build several shuffles.
23141 // Insert non-constant scalars.
23142 SmallVector<Value *> NonConstants(GatheredScalars);
23143 int EMSz = ExtractMask.size();
23144 int MSz = Mask.size();
23145 // Try to build constant vector and shuffle with it only if currently we
23146 // have a single permutation and more than 1 scalar constants.
23147 bool IsSingleShuffle = ExtractShuffles.empty() || GatherShuffles.empty();
23148 bool IsIdentityShuffle =
23149 ((UseVecBaseAsInput ||
23150 all_of(ExtractShuffles,
23151 [](const std::optional<TTI::ShuffleKind> &SK) {
23152 return SK.value_or(TTI::SK_PermuteTwoSrc) ==
23154 })) &&
23155 none_of(ExtractMask, [&](int I) { return I >= EMSz; }) &&
23156 ShuffleVectorInst::isIdentityMask(ExtractMask, EMSz)) ||
23157 (!GatherShuffles.empty() &&
23158 all_of(GatherShuffles,
23159 [](const std::optional<TTI::ShuffleKind> &SK) {
23160 return SK.value_or(TTI::SK_PermuteTwoSrc) ==
23162 }) &&
23163 none_of(Mask, [&](int I) { return I >= MSz; }) &&
23165 bool EnoughConstsForShuffle =
23166 IsSingleShuffle &&
23167 (none_of(GatheredScalars,
23168 [](Value *V) {
23169 return isa<UndefValue>(V) && !isa<PoisonValue>(V);
23170 }) ||
23171 any_of(GatheredScalars,
23172 [](Value *V) {
23173 return isa<Constant>(V) && !isa<UndefValue>(V);
23174 })) &&
23175 (!IsIdentityShuffle ||
23176 (GatheredScalars.size() == 2 &&
23177 any_of(GatheredScalars,
23178 [](Value *V) { return !isa<UndefValue>(V); })) ||
23179 count_if(GatheredScalars, [](Value *V) {
23180 return isa<Constant>(V) && !isa<PoisonValue>(V);
23181 }) > 1);
23182 // NonConstants array contains just non-constant values, GatheredScalars
23183 // contains only constant to build final vector and then shuffle.
23184 for (int I = 0, Sz = GatheredScalars.size(); I < Sz; ++I) {
23185 if (EnoughConstsForShuffle && isa<Constant>(GatheredScalars[I]))
23186 NonConstants[I] = PoisonValue::get(OrigScalarTy);
23187 else
23188 GatheredScalars[I] = PoisonValue::get(OrigScalarTy);
23189 }
23190 // Generate constants for final shuffle and build a mask for them.
23191 if (!all_of(GatheredScalars, IsaPred<PoisonValue>)) {
23192 SmallVector<int> BVMask(GatheredScalars.size(), PoisonMaskElem);
23193 TryPackScalars(GatheredScalars, BVMask, /*IsRootPoison=*/true);
23194 Value *BV = ShuffleBuilder.gather(GatheredScalars, BVMask.size());
23195 ShuffleBuilder.add(BV, BVMask);
23196 }
23197 if (all_of(NonConstants, [=](Value *V) {
23198 return isa<PoisonValue>(V) ||
23199 (IsSingleShuffle && ((IsIdentityShuffle &&
23200 IsNonPoisoned) || IsUsedInExpr) && isa<UndefValue>(V));
23201 }))
23202 Res = ShuffleBuilder.finalize(E->ReuseShuffleIndices, SubVectors,
23203 SubVectorsMask);
23204 else
23205 Res = ShuffleBuilder.finalize(
23206 E->ReuseShuffleIndices, SubVectors, SubVectorsMask, E->Scalars.size(),
23207 [&](Value *&Vec, SmallVectorImpl<int> &Mask, auto CreateShuffle) {
23208 bool IsSplat = isSplat(NonConstants);
23209 SmallVector<int> BVMask(Mask.size(), PoisonMaskElem);
23210 TryPackScalars(NonConstants, BVMask, /*IsRootPoison=*/false);
23211 auto CheckIfSplatIsProfitable = [&]() {
23212 // Estimate the cost of splatting + shuffle and compare with
23213 // insert + shuffle.
23214 Value *V = *find_if_not(NonConstants, IsaPred<UndefValue>);
23215 if (isa<ExtractElementInst>(V) || isVectorized(V))
23216 return false;
23217 InstructionCost SplatCost = TTI->getVectorInstrCost(
23218 Instruction::InsertElement, VecTy, CostKind, /*Index=*/0,
23219 PoisonValue::get(VecTy), V);
23220 SmallVector<int> NewMask(Mask.begin(), Mask.end());
23221 for (auto [Idx, I] : enumerate(BVMask))
23222 if (I != PoisonMaskElem)
23223 NewMask[Idx] = Mask.size();
23224 SplatCost +=
23225 getShuffleCost(*TTI, TTI::SK_PermuteTwoSrc,
23226 cast<VectorType>(VecTy), CostKind, NewMask);
23227 InstructionCost BVCost = TTI->getVectorInstrCost(
23228 Instruction::InsertElement, VecTy, CostKind,
23229 *find_if(Mask, not_equal_to(PoisonMaskElem)), Vec, V);
23230 // Shuffle required?
23231 if (count(BVMask, PoisonMaskElem) <
23232 static_cast<int>(BVMask.size() - 1)) {
23233 SmallVector<int> NewMask(Mask.begin(), Mask.end());
23234 for (auto [Idx, I] : enumerate(BVMask))
23235 if (I != PoisonMaskElem)
23236 NewMask[Idx] = I;
23237 BVCost +=
23238 getShuffleCost(*TTI, TTI::SK_PermuteSingleSrc,
23239 cast<VectorType>(VecTy), CostKind, NewMask);
23240 }
23241 return SplatCost <= BVCost;
23242 };
23243 if (!IsSplat || Mask.size() <= 2 || !CheckIfSplatIsProfitable()) {
23244 for (auto [Idx, I] : enumerate(BVMask))
23245 if (I != PoisonMaskElem)
23246 Mask[Idx] = I;
23247 Vec = ShuffleBuilder.gather(NonConstants, Mask.size(), Vec);
23248 } else {
23249 Value *V = *find_if_not(NonConstants, IsaPred<UndefValue>);
23250 SmallVector<Value *> Values(NonConstants.size(),
23251 PoisonValue::get(ScalarTy));
23252 Values[0] = V;
23253 Value *BV = ShuffleBuilder.gather(Values, BVMask.size());
23254 SmallVector<int> SplatMask(BVMask.size(), PoisonMaskElem);
23255 transform(BVMask, SplatMask.begin(), [](int I) {
23256 return I == PoisonMaskElem ? PoisonMaskElem : 0;
23257 });
23258 if (!ShuffleVectorInst::isIdentityMask(SplatMask, VF))
23259 BV = CreateShuffle(BV, nullptr, SplatMask);
23260 for (auto [Idx, I] : enumerate(BVMask))
23261 if (I != PoisonMaskElem)
23262 Mask[Idx] = BVMask.size() + Idx;
23263 Vec = CreateShuffle(Vec, BV, Mask);
23264 for (auto [Idx, I] : enumerate(Mask))
23265 if (I != PoisonMaskElem)
23266 Mask[Idx] = Idx;
23267 }
23268 });
23269 } else if (!allConstant(GatheredScalars)) {
23270 // Gather unique scalars and all constants.
23271 SmallVector<int> ReuseMask(GatheredScalars.size(), PoisonMaskElem);
23272 TryPackScalars(GatheredScalars, ReuseMask, /*IsRootPoison=*/true);
23273 Value *BV = ShuffleBuilder.gather(GatheredScalars, ReuseMask.size());
23274 ShuffleBuilder.add(BV, ReuseMask);
23275 Res = ShuffleBuilder.finalize(E->ReuseShuffleIndices, SubVectors,
23276 SubVectorsMask);
23277 } else {
23278 // Gather all constants.
23279 SmallVector<int> Mask(GatheredScalars.size(), PoisonMaskElem);
23280 for (auto [I, V] : enumerate(GatheredScalars)) {
23281 if (!isa<PoisonValue>(V))
23282 Mask[I] = I;
23283 }
23284 Value *BV = ShuffleBuilder.gather(GatheredScalars);
23285 ShuffleBuilder.add(BV, Mask);
23286 Res = ShuffleBuilder.finalize(E->ReuseShuffleIndices, SubVectors,
23287 SubVectorsMask);
23288 }
23289
23290 if (NeedFreeze)
23291 Res = ShuffleBuilder.createFreeze(Res);
23292 return Res;
23293}
23294
23295Value *BoUpSLP::createBuildVector(const TreeEntry *E, Type *ScalarTy) {
23296 // Do not do this for split vectorize node, marked to be gathers/buildvectors.
23297 if (E->State != TreeEntry::SplitVectorize ||
23298 !TransformedToGatherNodes.contains(E)) {
23299 for (auto [EIdx, _] : E->CombinedEntriesWithIndices)
23300 (void)vectorizeTree(VectorizableTree[EIdx].get());
23301 }
23302 return processBuildVector<ShuffleInstructionBuilder, Value *>(E, ScalarTy,
23303 Builder, *this);
23304}
23305
23306/// \returns \p I after propagating metadata from \p VL only for instructions in
23307/// \p VL.
23310 for (Value *V : VL)
23311 if (isa<Instruction>(V))
23312 Insts.push_back(V);
23313 return llvm::propagateMetadata(Inst, Insts);
23314}
23315
23317 if (DebugLoc DL = PN.getDebugLoc())
23318 return DL;
23319 return DebugLoc::getUnknown();
23320}
23321
23322Value *BoUpSLP::vectorizeTree(TreeEntry *E) {
23323 IRBuilderBase::InsertPointGuard Guard(Builder);
23324
23325 Value *V = E->Scalars.front();
23326 Type *ScalarTy = getValueType(V, SLPReVec);
23327 auto It = MinBWs.find(E);
23328 if (It != MinBWs.end()) {
23329 auto *VecTy = dyn_cast<FixedVectorType>(ScalarTy);
23330 ScalarTy = IntegerType::get(F->getContext(), It->second.first);
23331 if (VecTy)
23332 ScalarTy = getWidenedType(ScalarTy, VecTy->getNumElements());
23333 }
23334 if (E->VectorizedValue)
23335 return E->VectorizedValue;
23336 auto *VecTy = getWidenedType(ScalarTy, E->Scalars.size());
23337 if (E->isGather() || TransformedToGatherNodes.contains(E)) {
23338 // Set insert point for non-reduction initial nodes.
23339 if (E->hasState() && E->Idx == 0 && !UserIgnoreList)
23340 setInsertPointAfterBundle(E);
23341 Value *Vec = createBuildVector(E, ScalarTy);
23342 E->VectorizedValue = Vec;
23343 return Vec;
23344 }
23345 if (E->State == TreeEntry::SplitVectorize) {
23346 assert(E->CombinedEntriesWithIndices.size() == 2 &&
23347 "Expected exactly 2 combined entries.");
23348 setInsertPointAfterBundle(E);
23349 TreeEntry &OpTE1 =
23350 *VectorizableTree[E->CombinedEntriesWithIndices.front().first];
23351 assert(OpTE1.isSame(
23352 ArrayRef(E->Scalars).take_front(OpTE1.getVectorFactor())) &&
23353 "Expected same first part of scalars.");
23354 Value *Op1 = vectorizeTree(&OpTE1);
23355 TreeEntry &OpTE2 =
23356 *VectorizableTree[E->CombinedEntriesWithIndices.back().first];
23357 assert(
23358 OpTE2.isSame(ArrayRef(E->Scalars).take_back(OpTE2.getVectorFactor())) &&
23359 "Expected same second part of scalars.");
23360 Value *Op2 = vectorizeTree(&OpTE2);
23361 auto GetOperandSignedness = [&](const TreeEntry *OpE) {
23362 bool IsSigned = false;
23363 auto It = MinBWs.find(OpE);
23364 if (It != MinBWs.end())
23365 IsSigned = It->second.second;
23366 else
23367 IsSigned = any_of(OpE->Scalars, [&](Value *R) {
23368 if (isa<PoisonValue>(V))
23369 return false;
23370 return !isKnownNonNegative(R, SimplifyQuery(*DL));
23371 });
23372 return IsSigned;
23373 };
23374 if (cast<VectorType>(Op1->getType())->getElementType() !=
23375 ScalarTy->getScalarType()) {
23376 assert(ScalarTy->isIntegerTy() && "Expected item in MinBWs.");
23377 Op1 = Builder.CreateIntCast(
23378 Op1,
23380 ScalarTy,
23381 cast<FixedVectorType>(Op1->getType())->getNumElements()),
23382 GetOperandSignedness(&OpTE1));
23383 }
23384 if (cast<VectorType>(Op2->getType())->getElementType() !=
23385 ScalarTy->getScalarType()) {
23386 assert(ScalarTy->isIntegerTy() && "Expected item in MinBWs.");
23387 Op2 = Builder.CreateIntCast(
23388 Op2,
23390 ScalarTy,
23391 cast<FixedVectorType>(Op2->getType())->getNumElements()),
23392 GetOperandSignedness(&OpTE2));
23393 }
23394 if (E->ReorderIndices.empty()) {
23395 SmallVector<int> Mask(E->getVectorFactor(), PoisonMaskElem);
23396 std::iota(
23397 Mask.begin(),
23398 std::next(Mask.begin(), E->CombinedEntriesWithIndices.back().second),
23399 0);
23400 unsigned ScalarTyNumElements = getNumElements(ScalarTy);
23401 if (ScalarTyNumElements != 1) {
23402 assert(SLPReVec && "Only supported by REVEC.");
23403 transformScalarShuffleIndiciesToVector(ScalarTyNumElements, Mask);
23404 }
23405 Value *Vec = Builder.CreateShuffleVector(Op1, Mask);
23406 Vec = createInsertVector(Builder, Vec, Op2,
23407 E->CombinedEntriesWithIndices.back().second *
23408 ScalarTyNumElements);
23409 E->VectorizedValue = Vec;
23410 return Vec;
23411 }
23412 unsigned CommonVF =
23413 std::max(OpTE1.getVectorFactor(), OpTE2.getVectorFactor());
23414 const unsigned Scale = getNumElements(ScalarTy);
23415 CommonVF *= Scale;
23416 if (getNumElements(Op1->getType()) != CommonVF) {
23417 SmallVector<int> Mask(CommonVF, PoisonMaskElem);
23418 copy(createReplicatedMask(Scale, OpTE1.getVectorFactor() * Scale),
23419 Mask.begin());
23420 Op1 = Builder.CreateShuffleVector(Op1, Mask);
23421 }
23422 if (getNumElements(Op2->getType()) != CommonVF) {
23423 SmallVector<int> Mask(CommonVF, PoisonMaskElem);
23424 copy(createReplicatedMask(Scale, OpTE2.getVectorFactor() * Scale),
23425 Mask.begin());
23426 Op2 = Builder.CreateShuffleVector(Op2, Mask);
23427 }
23428 Value *Vec = Builder.CreateShuffleVector(Op1, Op2, E->getSplitMask());
23429 E->VectorizedValue = Vec;
23430 return Vec;
23431 }
23432
23433 bool IsReverseOrder =
23434 !E->ReorderIndices.empty() && isReverseOrder(E->ReorderIndices);
23435 auto FinalShuffle = [&](Value *V, const TreeEntry *E) {
23436 if (isa<StructType>(ScalarTy)) {
23437 // TODO: Reordering of struct types is not supported.
23438 assert(E->ReorderIndices.empty() &&
23439 "Expected no reordering for struct types.");
23440 assert(E->ReuseShuffleIndices.empty() &&
23441 "Expected no reuse shuffle indices for struct types.");
23442 return V;
23443 }
23444 ShuffleInstructionBuilder ShuffleBuilder(ScalarTy, Builder, *this);
23445 if ((E->State == TreeEntry::StridedVectorize && IsReverseOrder) ||
23446 E->State == TreeEntry::CompressVectorize) {
23447 ShuffleBuilder.addOrdered(V, {});
23448 } else if (E->getOpcode() == Instruction::Store &&
23449 (E->State == TreeEntry::Vectorize ||
23450 E->State == TreeEntry::StridedVectorize ||
23451 E->State == TreeEntry::ExpandVectorize)) {
23452 ArrayRef<int> Mask =
23453 ArrayRef(reinterpret_cast<const int *>(E->ReorderIndices.begin()),
23454 E->ReorderIndices.size());
23455 ShuffleBuilder.add(V, Mask);
23456 } else {
23457 ShuffleBuilder.addOrdered(V, E->ReorderIndices);
23458 }
23460 E->CombinedEntriesWithIndices.size());
23461 transform(
23462 E->CombinedEntriesWithIndices, SubVectors.begin(), [&](const auto &P) {
23463 return std::make_pair(VectorizableTree[P.first].get(), P.second);
23464 });
23465 assert(
23466 (E->CombinedEntriesWithIndices.empty() || E->ReorderIndices.empty()) &&
23467 "Expected either combined subnodes or reordering");
23468 return ShuffleBuilder.finalize(E->ReuseShuffleIndices, SubVectors, {});
23469 };
23470
23471 assert(!E->isGather() && "Unhandled state");
23472 unsigned ShuffleOrOp =
23473 E->isAltShuffle() ? (unsigned)Instruction::ShuffleVector : E->getOpcode();
23474 if (!E->isAltShuffle()) {
23475 switch (E->CombinedOp) {
23476 case TreeEntry::ReducedBitcast:
23477 case TreeEntry::ReducedBitcastBSwap:
23478 case TreeEntry::ReducedBitcastLoads:
23479 case TreeEntry::ReducedBitcastBSwapLoads:
23480 case TreeEntry::ReducedCmpBitcast:
23481 ShuffleOrOp = E->CombinedOp;
23482 break;
23483 default:
23484 break;
23485 }
23486 }
23487 Instruction *VL0 = E->getMainOp();
23488 auto GetOperandSignedness = [&](unsigned Idx) {
23489 const TreeEntry *OpE = getOperandEntry(E, Idx);
23490 bool IsSigned = false;
23491 auto It = MinBWs.find(OpE);
23492 if (It != MinBWs.end())
23493 IsSigned = It->second.second;
23494 else
23495 IsSigned = any_of(OpE->Scalars, [&](Value *R) {
23496 if (isa<PoisonValue>(V))
23497 return false;
23498 return !isKnownNonNegative(R, SimplifyQuery(*DL));
23499 });
23500 return IsSigned;
23501 };
23502 auto PropagateIRFlags = [&](Value *V, unsigned Opcode = 0,
23503 ArrayRef<Value *> VL = {}) -> Value * {
23504 ArrayRef<Value *> Scalars = VL.empty() ? E->Scalars : VL;
23505 SmallSetVector<Value *, 4> UniqueInsts;
23506 for (Value *Scalar : Scalars) {
23507 auto *I = dyn_cast<Instruction>(Scalar);
23508 if (!I)
23509 continue;
23510 if (E->hasCopyableElements() && E->isCopyableElement(I))
23511 continue;
23512 UniqueInsts.insert(I);
23513 }
23514 if (!Opcode)
23515 Opcode = E->getOpcode();
23516 propagateIRFlags(V, UniqueInsts.getArrayRef(), nullptr, It == MinBWs.end());
23517 auto *I = dyn_cast<Instruction>(V);
23518 if (!I)
23519 return V;
23520 I = ::propagateMetadata(I, UniqueInsts.getArrayRef());
23521 // For copyable elements the lane is synthesized using a binop identity
23522 // value, so the operand at that lane is the copyable scalar's value.
23523 // fast-math flags that turn defined NaN/Inf inputs into poison (nnan,
23524 // ninf) are only justified if every copyable scalar at the synthesized
23525 // lane is itself provably non-NaN/non-Inf - either an FPMathOperator
23526 // with the matching flag set, or a constant FP that is not NaN/Inf.
23527 if (E->hasCopyableElements() && isa<FPMathOperator>(I)) {
23528 bool AllNoNaNs = true;
23529 bool AllNoInfs = true;
23530 for (Value *Scalar : Scalars) {
23531 if (!E->isCopyableElement(Scalar))
23532 continue;
23533 if (auto *FPMO = dyn_cast<FPMathOperator>(Scalar)) {
23534 AllNoNaNs &= FPMO->hasNoNaNs();
23535 AllNoInfs &= FPMO->hasNoInfs();
23536 continue;
23537 }
23538 if (auto *CFP = dyn_cast<ConstantFP>(Scalar)) {
23539 AllNoNaNs &= !CFP->isNaN();
23540 AllNoInfs &= !CFP->isInfinity();
23541 continue;
23542 }
23543 AllNoNaNs = false;
23544 AllNoInfs = false;
23545 break;
23546 }
23547 if (!AllNoNaNs)
23548 I->setHasNoNaNs(false);
23549 if (!AllNoInfs)
23550 I->setHasNoInfs(false);
23551 }
23552 // Drop nuw flags for abs(sub(commutative), true).
23553 if (!MinBWs.contains(E) && Opcode == Instruction::Sub &&
23554 (E->hasCopyableElements() || any_of(Scalars, [](Value *Scalar) {
23555 auto *SI = dyn_cast<Instruction>(Scalar);
23556 return !SI || isCommutative(SI);
23557 })))
23558 I->setHasNoUnsignedWrap(/*b=*/false);
23559 // A sub feeding icmp eq/ne 0 may have its operands swapped; nsw does not
23560 // survive a - b -> b - a (a - b can be INT_MIN while b - a overflows).
23561 if (!MinBWs.contains(E) && Opcode == Instruction::Sub &&
23562 any_of(Scalars, [](Value *Scalar) {
23563 auto *SI = dyn_cast<Instruction>(Scalar);
23564 if (!SI || SI->getOpcode() != Instruction::Sub || !isCommutative(SI))
23565 return false;
23566 return any_of(SI->uses(), [](const Use &U) {
23567 CmpPredicate Pred;
23568 return match(U.getUser(),
23569 m_ICmp(Pred, m_Specific(U.get()), m_Zero())) &&
23570 ICmpInst::isEquality(Pred);
23571 });
23572 }))
23573 I->setHasNoSignedWrap(/*b=*/false);
23574 // Interchanging add/sub negates the constant: nsw only survives if the
23575 // constant isn't INT_MIN (negating it would overflow); nuw never
23576 // survives a nonzero constant, since that flips the valid range from
23577 // X >= C to X < C.
23578 if (!MinBWs.contains(E) &&
23579 (Opcode == Instruction::Add || Opcode == Instruction::Sub)) {
23580 for (Value *V : UniqueInsts) {
23581 auto *SI = cast<Instruction>(V);
23582 if (SI->getOpcode() == Opcode ||
23583 !is_contained({Instruction::Add, Instruction::Sub},
23584 SI->getOpcode()))
23585 continue;
23586 for (Value *Op : SI->operands()) {
23587 const auto *CI = dyn_cast<ConstantInt>(Op);
23588 if (!CI || CI->isZero())
23589 continue;
23590 I->setHasNoUnsignedWrap(/*b=*/false);
23591 if (CI->getValue().isMinSignedValue())
23592 I->setHasNoSignedWrap(/*b=*/false);
23593 }
23594 }
23595 }
23596 // mul nsw X, INT_MIN is not equivalent to shl nsw X, BW-1, because shl nsw
23597 // poisons when the sign bit is shifted out of a positive value. When a mul
23598 // lane is converted to shl with shift amount BW-1, nsw must be dropped.
23599 if (!MinBWs.contains(E) && Opcode == Instruction::Shl &&
23600 any_of(UniqueInsts, [&](Value *V) {
23601 auto *SI = cast<Instruction>(V);
23602 if (SI->getOpcode() != Instruction::Mul)
23603 return false;
23604 return any_of(SI->operands(), [](Value *Op) {
23605 const auto *CI = dyn_cast<ConstantInt>(Op);
23606 return CI && CI->getValue().isMinSignedValue();
23607 });
23608 }))
23609 I->setHasNoSignedWrap(/*b=*/false);
23610 // shl nsw X, BW-1 is not equivalent to mul nsw X, INT_MIN: shl nsw never
23611 // poisons at X = -1 (shifted-out bits match the sign bit), but mul nsw
23612 // does. A shl lane converted to mul this way must drop nsw.
23613 if (!MinBWs.contains(E) && Opcode == Instruction::Mul &&
23614 any_of(UniqueInsts, [&](Value *V) {
23615 auto *SI = cast<Instruction>(V);
23616 if (SI->getOpcode() != Instruction::Shl)
23617 return false;
23618 const auto *CI = dyn_cast<ConstantInt>(SI->getOperand(1));
23619 return CI && CI->getValue() == CI->getBitWidth() - 1;
23620 }))
23621 I->setHasNoSignedWrap(/*b=*/false);
23622 // Keep the intersected samesign unless narrowing changed the sign of some
23623 // compared operand (it neither sign-extends from the narrow type nor has
23624 // a known-zero narrow sign bit), or a converted lane's adjusted constant
23625 // flips the sign.
23626 if (auto *ICmp = dyn_cast<ICmpInst>(I); ICmp && It == MinBWs.end()) {
23627 bool SignChange =
23628 ICmp->getOperand(0)->getType()->getScalarType() !=
23629 VL0->getOperand(0)->getType()->getScalarType() &&
23630 ((!GetOperandSignedness(0) &&
23631 !isKnownNonNegative(ICmp->getOperand(0), SimplifyQuery(*DL))) ||
23632 (!GetOperandSignedness(1) &&
23633 !isKnownNonNegative(ICmp->getOperand(1), SimplifyQuery(*DL))));
23634 CmpInst::Predicate P0 = cast<CmpInst>(E->getMainOp())->getPredicate();
23635 bool SignFlip = !SignChange && any_of(E->Scalars, [&](Value *Scalar) {
23636 auto *LaneCI = dyn_cast<ICmpInst>(Scalar);
23637 if (!LaneCI)
23638 return false;
23639 auto *OrigC = dyn_cast<ConstantInt>(LaneCI->getOperand(1));
23640 if (!OrigC)
23641 return false;
23642 ConstantInt *AdjC =
23643 CmpSamePredicateHelper::getAdjustedConstant(LaneCI, P0);
23644 return AdjC && AdjC->isNegative() != OrigC->isNegative();
23645 });
23646 if (SignChange || SignFlip)
23647 ICmp->setSameSign(/*B=*/false);
23648 }
23649 return I;
23650 };
23651 switch (ShuffleOrOp) {
23652 case Instruction::PHI: {
23653 assert((E->ReorderIndices.empty() || !E->ReuseShuffleIndices.empty() ||
23654 E != &getRootNode() || E->UserTreeIndex) &&
23655 "PHI reordering is free.");
23656 auto *PH = cast<PHINode>(VL0);
23657 Builder.SetInsertPoint(PH->getParent(),
23658 PH->getParent()->getFirstNonPHIIt());
23659 Builder.SetCurrentDebugLocation(getDebugLocFromPHI(*PH));
23660 PHINode *NewPhi = Builder.CreatePHI(VecTy, PH->getNumIncomingValues());
23661 Value *V = NewPhi;
23662
23663 // Adjust insertion point once all PHI's have been generated.
23664 Builder.SetInsertPoint(PH->getParent(),
23665 PH->getParent()->getFirstInsertionPt());
23666 Builder.SetCurrentDebugLocation(getDebugLocFromPHI(*PH));
23667
23668 V = FinalShuffle(V, E);
23669
23670 E->VectorizedValue = V;
23671 // If phi node is fully emitted - exit.
23672 if (NewPhi->getNumIncomingValues() != 0)
23673 return NewPhi;
23674
23675 // PHINodes may have multiple entries from the same block. We want to
23676 // visit every block once.
23677 SmallDenseMap<BasicBlock *, unsigned, 4> VisitedBBs;
23678 for (unsigned I : seq<unsigned>(PH->getNumIncomingValues())) {
23679 BasicBlock *IBB = PH->getIncomingBlock(I);
23680
23681 // Stop emission if all incoming values are generated.
23682 if (NewPhi->getNumIncomingValues() == PH->getNumIncomingValues()) {
23683 LLVM_DEBUG(dbgs() << "SLP: Diamond merged for " << *VL0 << ".\n");
23684 return NewPhi;
23685 }
23686
23687 auto Res = VisitedBBs.try_emplace(IBB, I);
23688 if (!Res.second) {
23689 TreeEntry *OpTE = getOperandEntry(E, I);
23690 if (OpTE->isGather() || DeletedNodes.contains(OpTE) ||
23691 TransformedToGatherNodes.contains(OpTE)) {
23692 Value *VecOp = NewPhi->getIncomingValue(Res.first->getSecond());
23693 NewPhi->addIncoming(VecOp, IBB);
23694 assert(!OpTE->VectorizedValue && "Expected no vectorized value.");
23695 OpTE->VectorizedValue = VecOp;
23696 continue;
23697 }
23698 }
23699
23700 Builder.SetInsertPoint(IBB->getTerminator());
23701 Builder.SetCurrentDebugLocation(getDebugLocFromPHI(*PH));
23702 Value *Vec = vectorizeOperand(E, I);
23703 if (VecTy != Vec->getType()) {
23704 assert((It != MinBWs.end() || getOperandEntry(E, I)->isGather() ||
23705 MinBWs.contains(getOperandEntry(E, I))) &&
23706 "Expected item in MinBWs.");
23707 Vec = Builder.CreateIntCast(Vec, VecTy, GetOperandSignedness(I));
23708 }
23709 NewPhi->addIncoming(Vec, IBB);
23710 }
23711
23712 assert(NewPhi->getNumIncomingValues() == PH->getNumIncomingValues() &&
23713 "Invalid number of incoming values");
23714 assert(E->VectorizedValue && "Expected vectorized value.");
23715 return E->VectorizedValue;
23716 }
23717
23718 case Instruction::ExtractElement: {
23719 Value *V = E->getSingleOperand(0);
23720 setInsertPointAfterBundle(E);
23721 V = FinalShuffle(V, E);
23722 // Insert the copyable lanes (non-extract scalars modeled on the extract
23723 // main op) into the reused source vector. The identity extract order and
23724 // absence of a reuse shuffle are guaranteed when the node is created, so
23725 // a lane maps to its own index.
23726 if (E->hasCopyableElements()) {
23727 assert(E->ReorderIndices.empty() && E->ReuseShuffleIndices.empty() &&
23728 "Copyable extract lanes require identity order and no reuse.");
23729 for (auto [Idx, Scalar] : enumerate(E->Scalars))
23730 if (E->isCopyableElement(Scalar))
23731 V = Builder.CreateInsertElement(V, Scalar, Builder.getInt32(Idx));
23732 }
23733 E->VectorizedValue = V;
23734 return V;
23735 }
23736 case Instruction::ExtractValue: {
23737 if (!E->StructEVIndices.empty()) {
23738 setInsertPointAfterBundle(E);
23739 Value *V = vectorizeOperand(E, 0);
23740 V = Builder.CreateExtractValue(V, E->StructEVIndices);
23741 if (auto *I = dyn_cast<Instruction>(V))
23742 V = ::propagateMetadata(I, E->Scalars);
23743 V = FinalShuffle(V, E);
23744 E->VectorizedValue = V;
23745 return V;
23746 }
23747 auto *LI = cast<LoadInst>(E->getSingleOperand(0));
23748 Builder.SetInsertPoint(LI);
23749 Value *Ptr = LI->getPointerOperand();
23750 LoadInst *V = Builder.CreateAlignedLoad(VecTy, Ptr, LI->getAlign());
23751 Value *NewV = PropagateIRFlags(V);
23752 NewV = FinalShuffle(NewV, E);
23753 E->VectorizedValue = NewV;
23754 return NewV;
23755 }
23756 case Instruction::InsertValue:
23757 case Instruction::InsertElement: {
23758 assert(E->ReuseShuffleIndices.empty() && "All inserts should be unique");
23759 if (const TreeEntry *OpE = getOperandEntry(E, 1);
23760 OpE && !OpE->isGather() && OpE->hasState() &&
23761 !OpE->hasCopyableElements())
23762 Builder.SetInsertPoint(cast<Instruction>(E->Scalars.back()));
23763 else
23764 setInsertPointAfterBundle(E);
23765 Value *V = vectorizeOperand(E, 1);
23766 ArrayRef<Value *> Op = E->getOperand(1);
23767 Type *ScalarTy = Op.front()->getType();
23768 if (cast<VectorType>(V->getType())->getElementType() != ScalarTy) {
23769 assert(ScalarTy->isIntegerTy() && "Expected item in MinBWs.");
23770 std::pair<unsigned, bool> Res = MinBWs.lookup(getOperandEntry(E, 1));
23771 assert(Res.first > 0 && "Expected item in MinBWs.");
23772 V = Builder.CreateIntCast(
23773 V,
23775 ScalarTy,
23776 cast<FixedVectorType>(V->getType())->getNumElements()),
23777 Res.second);
23778 }
23779
23780 // Create InsertVector shuffle if necessary
23781 auto *FirstInsert = cast<Instruction>(*find_if(E->Scalars, [E](Value *V) {
23782 return !is_contained(E->Scalars, cast<Instruction>(V)->getOperand(0));
23783 }));
23784 const unsigned NumScalars = E->Scalars.size();
23785 FixedVectorType *SrcVecTy = getInsertBuildVectorSrcTy(E);
23786 const unsigned NumElts = getNumElements(SrcVecTy);
23787
23788 unsigned Offset = *getElementIndex(VL0);
23789 assert(Offset < NumElts && "Failed to find vector index offset");
23790
23791 // Create shuffle to resize vector
23792 SmallVector<int> Mask;
23793 if (!E->ReorderIndices.empty()) {
23794 inversePermutation(E->ReorderIndices, Mask);
23795 Mask.append(NumElts - NumScalars, PoisonMaskElem);
23796 } else {
23797 Mask.assign(NumElts, PoisonMaskElem);
23798 std::iota(Mask.begin(), std::next(Mask.begin(), NumScalars), 0);
23799 }
23800 // Create InsertVector shuffle if necessary
23801 bool IsIdentity = true;
23802 SmallVector<int> PrevMask(NumElts, PoisonMaskElem);
23803 Mask.swap(PrevMask);
23804 for (unsigned I = 0; I < NumScalars; ++I) {
23805 Value *Scalar = E->Scalars[PrevMask[I]];
23806 unsigned InsertIdx = *getElementIndex(Scalar);
23807 IsIdentity &= InsertIdx - Offset == I;
23808 Mask[InsertIdx - Offset] = I;
23809 }
23810 if (!IsIdentity || NumElts != NumScalars) {
23811 Value *V2 = nullptr;
23812 bool IsVNonPoisonous =
23814 SmallVector<int> InsertMask(Mask);
23815 if (NumElts != NumScalars && Offset == 0) {
23816 // Follow all insert element instructions from the current buildvector
23817 // sequence.
23818 Instruction *Ins = VL0;
23819 Instruction *Op;
23820 do {
23821 std::optional<unsigned> InsertIdx = getElementIndex(Ins);
23822 if (!InsertIdx)
23823 break;
23824 if (InsertMask[*InsertIdx] == PoisonMaskElem)
23825 InsertMask[*InsertIdx] = *InsertIdx;
23826 if (!Ins->hasOneUse())
23827 break;
23828 Op = Ins;
23829 Ins =
23831 } while (Ins && Ins->getOperand(0) == Op);
23832 SmallBitVector UseMask =
23833 buildUseMask(NumElts, InsertMask, UseMask::UndefsAsMask);
23834 SmallBitVector IsFirstPoison =
23835 isUndefVector<true>(FirstInsert->getOperand(0), UseMask);
23836 SmallBitVector IsFirstUndef =
23837 isUndefVector(FirstInsert->getOperand(0), UseMask);
23838 if (!IsFirstPoison.all()) {
23839 unsigned Idx = 0;
23840 for (unsigned I = 0; I < NumElts; I++) {
23841 if (InsertMask[I] == PoisonMaskElem && !IsFirstPoison.test(I) &&
23842 IsFirstUndef.test(I)) {
23843 if (IsVNonPoisonous) {
23844 InsertMask[I] = I < NumScalars ? I : 0;
23845 continue;
23846 }
23847 if (!V2)
23848 V2 = UndefValue::get(V->getType());
23849 if (Idx >= NumScalars)
23850 Idx = NumScalars - 1;
23851 InsertMask[I] = NumScalars + Idx;
23852 ++Idx;
23853 } else if (InsertMask[I] != PoisonMaskElem &&
23854 Mask[I] == PoisonMaskElem) {
23855 InsertMask[I] = PoisonMaskElem;
23856 }
23857 }
23858 } else {
23859 InsertMask = Mask;
23860 }
23861 }
23862 if (!V2)
23863 V2 = PoisonValue::get(V->getType());
23864 V = Builder.CreateShuffleVector(V, V2, InsertMask);
23865 if (auto *I = dyn_cast<Instruction>(V)) {
23866 GatherShuffleExtractSeq.insert(I);
23867 CSEBlocks.insert(I->getParent());
23868 }
23869 }
23870
23871 SmallVector<int> InsertMask(NumElts, PoisonMaskElem);
23872 for (unsigned I = 0; I < NumElts; I++) {
23873 if (Mask[I] != PoisonMaskElem)
23874 InsertMask[Offset + I] = I;
23875 }
23876 SmallBitVector UseMask =
23877 buildUseMask(NumElts, InsertMask, UseMask::UndefsAsMask);
23878 SmallBitVector IsFirstUndef =
23879 isUndefVector(FirstInsert->getOperand(0), UseMask);
23880 if ((!IsIdentity || Offset != 0 || !IsFirstUndef.all()) &&
23881 NumElts != NumScalars) {
23882 if (IsFirstUndef.all()) {
23883 if (!ShuffleVectorInst::isIdentityMask(InsertMask, NumElts)) {
23884 SmallBitVector IsFirstPoison =
23885 isUndefVector<true>(FirstInsert->getOperand(0), UseMask);
23886 if (!IsFirstPoison.all()) {
23887 for (unsigned I = 0; I < NumElts; I++) {
23888 if (InsertMask[I] == PoisonMaskElem && !IsFirstPoison.test(I))
23889 InsertMask[I] = I + NumElts;
23890 }
23891 }
23892 V = Builder.CreateShuffleVector(
23893 V,
23894 IsFirstPoison.all() ? PoisonValue::get(V->getType())
23895 : FirstInsert->getOperand(0),
23896 InsertMask, cast<Instruction>(E->Scalars.back())->getName());
23897 if (auto *I = dyn_cast<Instruction>(V)) {
23898 GatherShuffleExtractSeq.insert(I);
23899 CSEBlocks.insert(I->getParent());
23900 }
23901 }
23902 } else {
23903 SmallBitVector IsFirstPoison =
23904 isUndefVector<true>(FirstInsert->getOperand(0), UseMask);
23905 for (unsigned I = 0; I < NumElts; I++) {
23906 if (InsertMask[I] == PoisonMaskElem)
23907 InsertMask[I] = IsFirstPoison.test(I) ? PoisonMaskElem : I;
23908 else
23909 InsertMask[I] += NumElts;
23910 }
23911 V = Builder.CreateShuffleVector(
23912 FirstInsert->getOperand(0), V, InsertMask,
23913 cast<Instruction>(E->Scalars.back())->getName());
23914 if (auto *I = dyn_cast<Instruction>(V)) {
23915 GatherShuffleExtractSeq.insert(I);
23916 CSEBlocks.insert(I->getParent());
23917 }
23918 }
23919 }
23920
23921 ++NumVectorInstructions;
23922 if (ShuffleOrOp == Instruction::InsertValue &&
23924 Type *AggTy = E->getMainOp()->getType();
23925 Align SlotAlign = std::max(DL->getPrefTypeAlign(V->getType()),
23926 DL->getPrefTypeAlign(AggTy));
23927 AllocaInst *Slot;
23928 {
23929 // Keep the alloca in the function entry block so it is not executed
23930 // (and does not grow the stack) on every iteration of a loop.
23931 IRBuilderBase::InsertPointGuard Guard(Builder);
23932 Builder.SetInsertPointPastAllocas(F);
23933 Slot = Builder.CreateAlloca(AggTy, /*ArraySize=*/nullptr,
23934 "vec2struct.slot");
23935 Slot->setAlignment(SlotAlign);
23936 }
23937 (void)Builder.CreateAlignedStore(V, Slot, SlotAlign);
23938 V = Builder.CreateAlignedLoad(AggTy, Slot, SlotAlign, "vec2struct");
23939 NumVectorInstructions += 2;
23940 }
23941 E->VectorizedValue = V;
23942 return V;
23943 }
23944 case Instruction::ZExt:
23945 case Instruction::SExt:
23946 case Instruction::FPToUI:
23947 case Instruction::FPToSI:
23948 case Instruction::FPExt:
23949 case Instruction::PtrToInt:
23950 case Instruction::PtrToAddr:
23951 case Instruction::IntToPtr:
23952 case Instruction::SIToFP:
23953 case Instruction::UIToFP:
23954 case Instruction::Trunc:
23955 case Instruction::FPTrunc:
23956 case Instruction::BitCast: {
23957 setInsertPointAfterBundle(E);
23958
23959 Value *InVec = vectorizeOperand(E, 0);
23960
23961 auto *CI = cast<CastInst>(VL0);
23962 Instruction::CastOps VecOpcode = CI->getOpcode();
23963 Type *SrcScalarTy = cast<VectorType>(InVec->getType())->getElementType();
23964 auto SrcIt = MinBWs.find(getOperandEntry(E, 0));
23965 if (!ScalarTy->isFPOrFPVectorTy() && !SrcScalarTy->isFPOrFPVectorTy() &&
23966 (SrcIt != MinBWs.end() || It != MinBWs.end() ||
23967 SrcScalarTy != CI->getOperand(0)->getType()->getScalarType())) {
23968 // Check if the values are candidates to demote.
23969 unsigned SrcBWSz = DL->getTypeSizeInBits(SrcScalarTy);
23970 if (SrcIt != MinBWs.end())
23971 SrcBWSz = SrcIt->second.first;
23972 unsigned BWSz = DL->getTypeSizeInBits(ScalarTy->getScalarType());
23973 if (BWSz == SrcBWSz) {
23974 VecOpcode = Instruction::BitCast;
23975 } else if (BWSz < SrcBWSz) {
23976 VecOpcode = Instruction::Trunc;
23977 } else if (It != MinBWs.end()) {
23978 assert(BWSz > SrcBWSz && "Invalid cast!");
23979 VecOpcode = It->second.second ? Instruction::SExt : Instruction::ZExt;
23980 } else if (SrcIt != MinBWs.end()) {
23981 assert(BWSz > SrcBWSz && "Invalid cast!");
23982 VecOpcode =
23983 SrcIt->second.second ? Instruction::SExt : Instruction::ZExt;
23984 }
23985 } else if (VecOpcode == Instruction::SIToFP && SrcIt != MinBWs.end() &&
23986 !SrcIt->second.second) {
23987 VecOpcode = Instruction::UIToFP;
23988 } else if (VecOpcode == Instruction::BitCast && SrcIt != MinBWs.end() &&
23989 ScalarTy->isFPOrFPVectorTy()) {
23990 Type *OrigSrcScalarTy = CI->getSrcTy();
23991 auto *OrigSrcVectorTy =
23992 getWidenedType(OrigSrcScalarTy, E->Scalars.size());
23993 InVec =
23994 Builder.CreateIntCast(InVec, OrigSrcVectorTy, SrcIt->second.second);
23995 }
23996 Value *V = (VecOpcode != ShuffleOrOp && VecOpcode == Instruction::BitCast)
23997 ? InVec
23998 : Builder.CreateCast(VecOpcode, InVec, VecTy);
23999 V = FinalShuffle(V, E);
24000
24001 E->VectorizedValue = V;
24002 ++NumVectorInstructions;
24003 return V;
24004 }
24005 case Instruction::FCmp:
24006 case Instruction::ICmp: {
24007 setInsertPointAfterBundle(E);
24008
24009 Value *L = vectorizeOperand(E, 0);
24010 Value *R = vectorizeOperand(E, 1);
24011 if (L->getType() != R->getType()) {
24012 assert((getOperandEntry(E, 0)->isGather() ||
24013 getOperandEntry(E, 1)->isGather() ||
24014 MinBWs.contains(getOperandEntry(E, 0)) ||
24015 MinBWs.contains(getOperandEntry(E, 1))) &&
24016 "Expected item in MinBWs.");
24017 const unsigned LBW = cast<VectorType>(L->getType())
24018 ->getElementType()
24019 ->getIntegerBitWidth();
24020 const unsigned RBW = cast<VectorType>(R->getType())
24021 ->getElementType()
24022 ->getIntegerBitWidth();
24023 // A signed comparison needs the sign bit getActiveBits() ignores.
24024 const bool Signed = cast<CmpInst>(VL0)->isSigned();
24025 auto GetRequiredBits = [Signed](const APInt &V) {
24026 return Signed ? V.getSignificantBits() : V.getActiveBits();
24027 };
24028 if ((LBW < RBW && (!allConstant(E->getOperand(1)) ||
24029 any_of(
24030 E->getOperand(1),
24031 [&](Value *V) {
24032 auto *CI = dyn_cast<ConstantInt>(V);
24033 return !CI ||
24034 GetRequiredBits(CI->getValue()) > LBW;
24035 }))) ||
24036 (LBW > RBW && allConstant(E->getOperand(0)) &&
24037 all_of(E->getOperand(1), [&](Value *V) {
24038 auto *CI = dyn_cast<ConstantInt>(V);
24039 return CI && GetRequiredBits(CI->getValue()) <= RBW;
24040 }))) {
24041 Type *CastTy = R->getType();
24042 L = Builder.CreateIntCast(L, CastTy, GetOperandSignedness(0));
24043 } else {
24044 Type *CastTy = L->getType();
24045 R = Builder.CreateIntCast(R, CastTy, GetOperandSignedness(1));
24046 }
24047 }
24048
24049 CmpInst::Predicate P0 = cast<CmpInst>(VL0)->getPredicate();
24050 // A compare with both operands narrowed to the same type preserves the
24051 // result only if the predicate matches the operand signedness: signed
24052 // predicates need both operands sign-extended from the narrow type,
24053 // unsigned predicates need both zero-extended, equality needs the same
24054 // extension on both sides; operands with a known-zero narrow sign bit
24055 // match any predicate. Otherwise, extend the operands back to the
24056 // original compared type.
24057 auto *LTy = cast<FixedVectorType>(L->getType());
24058 auto *OrigOpTy =
24060 if (OrigOpTy && L->getType() == R->getType() &&
24061 LTy->getElementType()->getIntegerBitWidth() <
24062 OrigOpTy->getBitWidth()) {
24063 bool IsSigned0 = GetOperandSignedness(0);
24064 bool IsSigned1 = GetOperandSignedness(1);
24065 bool NonNeg0 = isKnownNonNegative(L, SimplifyQuery(*DL));
24066 bool NonNeg1 = isKnownNonNegative(R, SimplifyQuery(*DL));
24067 bool KeepNarrowTy;
24068 if (ICmpInst::isSigned(P0))
24069 KeepNarrowTy = (IsSigned0 || NonNeg0) && (IsSigned1 || NonNeg1);
24070 else if (ICmpInst::isUnsigned(P0))
24071 KeepNarrowTy = (!IsSigned0 || NonNeg0) && (!IsSigned1 || NonNeg1);
24072 else
24073 KeepNarrowTy = IsSigned0 == IsSigned1 || NonNeg0 || NonNeg1;
24074 if (!KeepNarrowTy) {
24075 Type *CastTy = getWidenedType(OrigOpTy, LTy->getNumElements());
24076 L = Builder.CreateIntCast(L, CastTy, IsSigned0);
24077 R = Builder.CreateIntCast(R, CastTy, IsSigned1);
24078 }
24079 }
24080
24081 Value *V = Builder.CreateCmp(P0, L, R);
24082 V = PropagateIRFlags(V);
24083 // Do not cast for cmps.
24084 VecTy = cast<FixedVectorType>(V->getType());
24085 V = FinalShuffle(V, E);
24086
24087 E->VectorizedValue = V;
24088 ++NumVectorInstructions;
24089 return V;
24090 }
24091 case Instruction::Select: {
24092 setInsertPointAfterBundle(E);
24093
24094 Value *Cond = vectorizeOperand(E, 0);
24095 Value *True = vectorizeOperand(E, 1);
24096 Value *False = vectorizeOperand(E, 2);
24097 if (True->getType() != VecTy || False->getType() != VecTy) {
24098 assert((It != MinBWs.end() || getOperandEntry(E, 1)->isGather() ||
24099 getOperandEntry(E, 2)->isGather() ||
24100 MinBWs.contains(getOperandEntry(E, 1)) ||
24101 MinBWs.contains(getOperandEntry(E, 2))) &&
24102 "Expected item in MinBWs.");
24103 if (True->getType() != VecTy)
24104 True = Builder.CreateIntCast(True, VecTy, GetOperandSignedness(1));
24105 if (False->getType() != VecTy)
24106 False = Builder.CreateIntCast(False, VecTy, GetOperandSignedness(2));
24107 }
24108
24109 unsigned CondNumElements = getNumElements(Cond->getType());
24110 unsigned TrueNumElements = getNumElements(True->getType());
24111 assert(TrueNumElements >= CondNumElements &&
24112 TrueNumElements % CondNumElements == 0 &&
24113 "Cannot vectorize Instruction::Select");
24114 assert(TrueNumElements == getNumElements(False->getType()) &&
24115 "Cannot vectorize Instruction::Select");
24116 if (CondNumElements != TrueNumElements) {
24117 // When the return type is i1 but the source is fixed vector type, we
24118 // need to duplicate the condition value.
24119 Cond = Builder.CreateShuffleVector(
24120 Cond, createReplicatedMask(TrueNumElements / CondNumElements,
24121 CondNumElements));
24122 }
24123 assert(getNumElements(Cond->getType()) == TrueNumElements &&
24124 "Cannot vectorize Instruction::Select");
24125 Value *V =
24126 Builder.CreateSelectWithUnknownProfile(Cond, True, False, DEBUG_TYPE);
24127 V = FinalShuffle(V, E);
24128
24129 E->VectorizedValue = V;
24130 ++NumVectorInstructions;
24131 return V;
24132 }
24133 case Instruction::FNeg: {
24134 setInsertPointAfterBundle(E);
24135
24136 Value *Op = vectorizeOperand(E, 0);
24137
24138 Value *V = Builder.CreateUnOp(
24139 static_cast<Instruction::UnaryOps>(E->getOpcode()), Op);
24140 V = PropagateIRFlags(V);
24141
24142 V = FinalShuffle(V, E);
24143
24144 E->VectorizedValue = V;
24145 ++NumVectorInstructions;
24146
24147 return V;
24148 }
24149 case Instruction::Freeze: {
24150 setInsertPointAfterBundle(E);
24151
24152 Value *Op = vectorizeOperand(E, 0);
24153
24154 if (Op->getType() != VecTy) {
24155 assert((It != MinBWs.end() || getOperandEntry(E, 0)->isGather() ||
24156 MinBWs.contains(getOperandEntry(E, 0))) &&
24157 "Expected item in MinBWs.");
24158 Op = Builder.CreateIntCast(Op, VecTy, GetOperandSignedness(0));
24159 }
24160 Value *V = Builder.CreateFreeze(Op);
24161 V = FinalShuffle(V, E);
24162
24163 E->VectorizedValue = V;
24164 ++NumVectorInstructions;
24165
24166 return V;
24167 }
24168 case Instruction::Add:
24169 case Instruction::FAdd:
24170 case Instruction::Sub:
24171 case Instruction::FSub:
24172 case Instruction::Mul:
24173 case Instruction::FMul:
24174 case Instruction::UDiv:
24175 case Instruction::SDiv:
24176 case Instruction::FDiv:
24177 case Instruction::URem:
24178 case Instruction::SRem:
24179 case Instruction::FRem:
24180 case Instruction::Shl:
24181 case Instruction::LShr:
24182 case Instruction::AShr:
24183 case Instruction::And:
24184 case Instruction::Or:
24185 case Instruction::Xor: {
24186 setInsertPointAfterBundle(E);
24187
24188 if (E->hasReassocScalars()) {
24189 // Vectorize operand columns, then combine pairwise in a balanced
24190 // tree; negated columns (flattened subtracts)