//===- SLPVectorizer.cpp - A bottom up SLP Vectorizer ---------------------===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
//
// This pass implements the Bottom Up SLP vectorizer. It detects consecutive
// stores that can be put together into vector-stores. Next, it attempts to
// construct vectorizable tree using the use-def chains. If a profitable tree
// was found, the SLP vectorizer performs vectorization on the tree.
//
// The pass is inspired by the work described in the paper:
//  "Loop-Aware SLP in GCC" by Ira Rosen, Dorit Nuzman, Ayal Zaks.
//
//===----------------------------------------------------------------------===//

#include "llvm/Transforms/Vectorize/SLPVectorizer.h"
#include "SLPVectorizer/SLPCompatibilityAnalysis.h"
#include "SLPVectorizer/SLPCostAnalysis.h"
#include "SLPVectorizer/SLPMemoryUtils.h"
#include "SLPVectorizer/SLPReductionUtils.h"
#include "SLPVectorizer/SLPShuffleAnalysis.h"
#include "SLPVectorizer/SLPTypeUtils.h"
#include "SLPVectorizer/SLPUtils.h"
#include "VectorizeOptions.h"
#include "llvm/ADT/DenseMap.h"
#include "llvm/ADT/DenseSet.h"
#include "llvm/ADT/PriorityQueue.h"
#include "llvm/ADT/STLExtras.h"
#include "llvm/ADT/ScopeExit.h"
#include "llvm/ADT/SetVector.h"
#include "llvm/ADT/SmallBitVector.h"
#include "llvm/ADT/SmallPtrSet.h"
#include "llvm/ADT/SmallSet.h"
#include "llvm/ADT/SmallString.h"
#include "llvm/ADT/SmallVectorExtras.h"
#include "llvm/ADT/Statistic.h"
#include "llvm/ADT/iterator.h"
#include "llvm/ADT/iterator_range.h"
#include "llvm/Analysis/AliasAnalysis.h"
#include "llvm/Analysis/AssumptionCache.h"
#include "llvm/Analysis/CodeMetrics.h"
#include "llvm/Analysis/ConstantFolding.h"
#include "llvm/Analysis/DemandedBits.h"
#include "llvm/Analysis/DomTreeUpdater.h"
#include "llvm/Analysis/GlobalsModRef.h"
#include "llvm/Analysis/IVDescriptors.h"
#include "llvm/Analysis/Loads.h"
#include "llvm/Analysis/LoopInfo.h"
#include "llvm/Analysis/MemoryLocation.h"
#include "llvm/Analysis/OptimizationRemarkEmitter.h"
#include "llvm/Analysis/ScalarEvolution.h"
#include "llvm/Analysis/ScalarEvolutionExpressions.h"
#include "llvm/Analysis/TargetLibraryInfo.h"
#include "llvm/Analysis/TargetTransformInfo.h"
#include "llvm/Analysis/ValueTracking.h"
#include "llvm/Analysis/VectorUtils.h"
#include "llvm/IR/Attributes.h"
#include "llvm/IR/BasicBlock.h"
#include "llvm/IR/CFG.h"
#include "llvm/IR/Constant.h"
#include "llvm/IR/Constants.h"
#include "llvm/IR/DataLayout.h"
#include "llvm/IR/DerivedTypes.h"
#include "llvm/IR/Dominators.h"
#include "llvm/IR/Function.h"
#include "llvm/IR/IRBuilder.h"
#include "llvm/IR/InstrTypes.h"
#include "llvm/IR/Instruction.h"
#include "llvm/IR/Instructions.h"
#include "llvm/IR/IntrinsicInst.h"
#include "llvm/IR/Intrinsics.h"
#include "llvm/IR/MDBuilder.h"
#include "llvm/IR/Module.h"
#include "llvm/IR/Operator.h"
#include "llvm/IR/PatternMatch.h"
#include "llvm/IR/ProfDataUtils.h"
#include "llvm/IR/Type.h"
#include "llvm/IR/Use.h"
#include "llvm/IR/User.h"
#include "llvm/IR/Value.h"
#include "llvm/IR/ValueHandle.h"
#include "llvm/IR/VectorTypeUtils.h"
#ifdef EXPENSIVE_CHECKS
#include "llvm/IR/Verifier.h"
#endif
#include "llvm/Pass.h"
#include "llvm/Support/Casting.h"
#include "llvm/Support/Compiler.h"
#include "llvm/Support/DOTGraphTraits.h"
#include "llvm/Support/Debug.h"
#include "llvm/Support/DebugCounter.h"
#include "llvm/Support/ErrorHandling.h"
#include "llvm/Support/GraphWriter.h"
#include "llvm/Support/InstructionCost.h"
#include "llvm/Support/KnownBits.h"
#include "llvm/Support/MathExtras.h"
#include "llvm/Support/SaveAndRestore.h"
#include "llvm/Support/raw_ostream.h"
#include "llvm/Transforms/Utils/InjectTLIMappings.h"
#include "llvm/Transforms/Utils/Local.h"
#include "llvm/Transforms/Utils/LoopUtils.h"
#include "llvm/Transforms/Utils/ScalarEvolutionExpander.h"
#include <algorithm>
#include <cassert>
#include <cstdint>
#include <iterator>
#include <map>
#include <memory>
#include <optional>
#include <string>
#include <tuple>
#include <utility>

using namespace llvm;
using namespace llvm::PatternMatch;
using namespace slpvectorizer;
using namespace std::placeholders;

#define SV_NAME "slp-vectorizer"
#define DEBUG_TYPE "SLP"

STATISTIC(NumVectorInstructions, "Number of vector instructions generated");
STATISTIC(NumStridedStoreChains, "Number of vectorized stride stores");
STATISTIC(NumStoreChains, "Number of vector stores created");
STATISTIC(NumVectorizedStores, "Number of vectorized stores");

DEBUG_COUNTER(VectorizedGraphs, "slp-vectorized",
              "Controls which SLP graphs should be vectorized.");

// Limit the number of alias checks. The limit is chosen so that
// it has no negative effect on the llvm benchmarks.
static const unsigned AliasedCheckLimit = 10;

// Another limit for the alias checks: The maximum distance between load/store
// instructions where alias checks are done.
// This limit is useful for very large basic blocks.
static const unsigned MaxMemDepDistance = 160;

/// If the ScheduleRegionSizeBudget is exhausted, we allow small scheduling
/// regions to be handled.
static const int MinScheduleRegionSize = 16;

/// If the reduction budget is exhausted, we allow small reduction trees to be
/// handled.
static const unsigned MinReductionTreeSize = 2048;

/// Maximum allowed number of operands in the PHI nodes.
static const unsigned MaxPHINumOperands = 128;

namespace {
/// A vectorized part of a split reduction, combined into the final reduction
/// result by the horizontal reduction emitter.
struct ReductionVectorPart {
  /// The vectorized value, tracked in case it is replaced while other parts
  /// are vectorized.
  WeakTrackingVH Vec;
  /// The number of times each lane is repeated in the reduction (emitted as a
  /// multiplication by the scale for add/fadd reductions).
  unsigned Scale = 1;
  /// Signedness of \p Vec for reductions, operating on truncated types.
  bool IsSigned = false;
  /// True if the value was already reduced in-tree.
  bool ReducedInTree = false;
  /// True if the part contribution is subtracted from (rather than added to)
  /// the final reduction result. Used for reassociated fadd reductions,
  /// flattened through fsub/fneg operations.
  bool Negated = false;
};
} // namespace

namespace {
class HorizontalReduction;
} // namespace

/// Bottom Up SLP Vectorizer.
class slpvectorizer::BoUpSLP {
  class TreeEntry;
  class ScheduleEntity;
  class ScheduleData;
  class ScheduleCopyableData;
  class ScheduleBundle;
  class ShuffleCostEstimator;
  class ShuffleInstructionBuilder;

public:
  /// If we decide to generate strided load / store, this struct contains all
  /// the necessary info. It's fields are calculated by analyzeRtStrideCandidate
  /// and analyzeConstantStrideCandidate. Note that Stride can be given either
  /// as a SCEV or as a Value if it already exists. To get the stride in bytes,
  /// StrideVal (or value obtained from StrideSCEV) has to by multiplied by the
  /// size of element of FixedVectorType.
  struct StridedPtrInfo {
    Value *StrideVal = nullptr;
    const SCEV *StrideSCEV = nullptr;
    FixedVectorType *Ty = nullptr;
  };

  /// Tracks the state we can represent the loads in the given sequence.
  enum class LoadsState {
    Gather,
    Vectorize,
    ScatterVectorize,
    StridedVectorize,
    CompressVectorize,
    BlendedLoadVectorize
  };

  using ValueList = SmallVector<Value *, 8>;
  using InstrList = SmallVector<Instruction *, 16>;
  using ValueSet = SmallPtrSet<Value *, 16>;
  using StoreList = SmallVector<StoreInst *, 8>;
  using ExtraValueToDebugLocsMap = SmallDenseSet<Value *, 4>;
  using OrdersType = SmallVector<unsigned, 4>;

  const VectorizeOptions &Opts;

  BoUpSLP(const VectorizeOptions &Opts, Function *Func, ScalarEvolution *Se,
          TargetTransformInfo *Tti, TargetLibraryInfo *TLi, AAResults *Aa,
          LoopInfo *Li, DominatorTree *Dt, AssumptionCache *AC,
          DemandedBits *DB, const DataLayout *DL,
          OptimizationRemarkEmitter *ORE)
      : Opts(Opts), AA(Aa), BatchAA(std::in_place, *Aa), F(Func), SE(Se),
        TTI(Tti), TLI(TLi), LI(Li), DT(Dt), AC(AC), DB(DB), DL(DL), ORE(ORE),
        CostKind(getSLPCostKind(Func)),
        Builder(Se->getModule(), TargetFolder(*DL)) {
    CodeMetrics::collectEphemeralValues(F, AC, EphValues);
    // Use the vector register size specified by the target unless overridden
    // by a command-line option.
    // TODO: It would be better to limit the vectorization factor based on
    //       data type rather than just register size. For example, x86 AVX has
    //       256-bit registers, but it does not support integer operations
    //       at that width (that requires AVX2).
    MaxVecRegSize = Opts.slp_max_reg_size.value_or(
        TTI->getRegisterBitWidth(TargetTransformInfo::RGK_FixedWidthVector)
            .getFixedValue());
    MinVecRegSize =
        Opts.slp_min_reg_size.value_or(TTI->getMinVectorRegisterBitWidth());
  }

  /// Vectorize the tree that starts with the elements in \p VL.
  /// Returns the vectorized root.
  Value *vectorizeTree();

  /// Vectorize the tree but with the list of externally used values \p
  /// ExternallyUsedValues. Values in this MapVector can be replaced but the
  /// generated extractvalue instructions.
  Value *
  vectorizeTree(const ExtraValueToDebugLocsMap &ExternallyUsedValues,
                Instruction *ReductionRoot = nullptr,
                ArrayRef<ReductionVectorPart> VectorValuesAndScales = {});

  /// \returns the cost incurred by unwanted spills and fills, caused by
  /// holding live values over call sites.
  InstructionCost getSpillCost();

  TargetTransformInfo::TargetCostKind getCostKind() const { return CostKind; }

  /// Calculates the cost of the subtrees, trims non-profitable ones and returns
  /// final cost.
  InstructionCost
  calculateTreeCostAndTrimNonProfitable(ArrayRef<Value *> VectorizedVals = {},
                                        Instruction *RdxRoot = nullptr);

  /// Finds i1 and/or nodes whose operand nodes are booleanized wide leaves
  /// (one-use truncs of wide values or zero-tests of values from [0, 1]) and
  /// registers them in MinBWs to be emitted in the wide leaf type.
  void detectBooleanizedNodes();

  /// \returns the vectorization cost of the subtree that starts at \p VL.
  /// A negative number means that this is profitable.
  InstructionCost getTreeCost(InstructionCost TreeCost,
                              ArrayRef<Value *> VectorizedVals = {},
                              InstructionCost ReductionCost = TTI::TCC_Free,
                              Instruction *RdxRoot = nullptr);

  /// Construct a vectorizable tree that starts at \p Roots, ignoring users for
  /// the purpose of scheduling and extraction in the \p UserIgnoreLst.
  void buildTree(ArrayRef<Value *> Roots,
                 const SmallDenseSet<Value *> &UserIgnoreLst);

  /// Construct a vectorizable tree that starts at \p Roots.
  void buildTree(ArrayRef<Value *> Roots);

  /// Sets the narrowed reduction chain instructions, dropped together with
  /// the reduction.
  void setNarrowedChainInsts(ArrayRef<Instruction *> Insts) {
    NarrowedChainInsts.insert(Insts.begin(), Insts.end());
  }

  /// Returns true if the last buildTree() observed a may-alias memory
  /// dependency between two distinct, range-checkable base objects, i.e. a
  /// dependency that could be turned into a runtime alias check.
  bool hasRuntimeCheckableBlockers() const {
    return HasRuntimeCheckableBlockers;
  }

  /// Records whether a may-alias dependency between distinct, range-checkable
  /// base objects has been observed, so the caller can decide to retry with
  /// runtime alias checks enabled.
  void setHasRuntimeCheckableBlockers(bool V) {
    HasRuntimeCheckableBlockers = V;
  }

  /// Returns true if the last buildTree() kept a may-alias memory dependency
  /// that is not runtime-checkable (call or a non-simple mem access). Such a
  /// dependency cannot be dropped, so a runtime-checks retry cannot unblock the
  /// region and would be pure overhead.
  bool hasNonCheckableMemBlocker() const { return HasNonCheckableMemBlocker; }

  /// Records that a non-runtime-checkable may-alias dependency was kept.
  void setHasNonCheckableMemBlocker(bool V) { HasNonCheckableMemBlocker = V; }

  /// Returns true if the current vectorization attempt may drop
  /// runtime-checkable may-alias dependencies and guard the region with
  /// runtime alias checks.
  bool isTryingRuntimeAliasChecks() const { return TryRuntimeAliasChecks; }

  /// Enables or disables dropping runtime-checkable may-alias dependencies in
  /// favor of runtime alias checks for the current vectorization attempt.
  void setTryRuntimeAliasChecks(bool V) { TryRuntimeAliasChecks = V; }

  /// Splits the stored values of the root stores into halves, vectorized as
  /// separate subtrees, while the returned guard is alive.
  [[nodiscard]] SaveAndRestore<bool> splitStoredValues() {
    return SaveAndRestore<bool>(SplitStoredValues, true);
  }

  /// Checks if the graph is built for the \p Stores and their stored values,
  /// looking through the vectorized cast node, are vectorized as the alternate
  /// node with the different opcodes in the halves.
  bool canSplitStoredValues(ArrayRef<Value *> Stores) const {
    if (VectorizableTree.empty() || getRootNode().isGather() ||
        getRootNodeScalars() != Stores)
      return false;
    const TreeEntry *E = getOperandEntry(&getRootNode(), 0);
    bool IsCast = E->State == TreeEntry::Vectorize && !E->isAltShuffle() &&
                  E->getMainOp()->isCast();
    if (IsCast)
      E = getOperandEntry(E, 0);
    if (E->State != TreeEntry::Vectorize || !E->isAltShuffle())
      return false;
    auto GetOpcode = [&](Value *V) -> unsigned {
      V = cast<StoreInst>(V)->getValueOperand();
      if (auto *CI = dyn_cast<CastInst>(V); CI && IsCast)
        V = CI->getOperand(0);
      auto *I = dyn_cast<Instruction>(V);
      return I ? I->getOpcode() : 0;
    };
    unsigned Opcode0 = GetOpcode(Stores.front());
    unsigned Opcode1 = GetOpcode(Stores.back());
    ArrayRef<Value *> Half = Stores.take_front(Stores.size() / 2);
    return Opcode0 != Opcode1 &&
           all_of(Half, [&](Value *V) { return GetOpcode(V) == Opcode0; }) &&
           all_of(Stores.drop_front(Half.size()),
                  [&](Value *V) { return GetOpcode(V) == Opcode1; });
  }

  /// Resets the runtime alias check data.
  void resetRuntimeAliasCheckState() {
    HasRuntimeCheckableBlockers = false;
    HasNonCheckableMemBlocker = false;
    RTChecksFinalized = false;
    RTChecks.clear();
    RTOrigBodyOrder.clear();
  }

  /// Snapshots RTChecks.BB's body (non-PHI, non-alloca, non-terminator) into
  /// RTOrigBodyOrder in program order, for the scalar fallback.
  void captureRuntimeCheckBodySnapshot();

  /// Returns true if \p BB satisfies the block-level preconditions for runtime
  /// alias check versioning (straight-line, duplicable, not a scalar fallback,
  /// function not optimized for size). These checks do not depend on the
  /// collected checks, so they can gate the (expensive) optimistic retry before
  /// any tree is rebuilt.
  bool canVersionBlockForRuntimeChecks(BasicBlock *BB) const;

  /// Returns true if the runtime alias checks can be safely emitted to guard
  /// the vectorized region.
  bool canVersionForRuntimeChecks();

  /// Returns true if \p BB is a scalar fallback block created by runtime alias
  /// check versioning.
  bool isScalarFallbackBlock(BasicBlock *BB) const {
    return ScalarFallbackBlocks.contains(BB);
  }

  /// Returns true if an optimistic runtime-checks versioning attempt already
  /// failed for \p BB, so further retries in the same block can be skipped.
  bool runtimeChecksFailedForBlock(BasicBlock *BB) const {
    return FailedRuntimeChecksBlocks.contains(BB);
  }

  /// Records that an optimistic runtime-checks versioning attempt failed for
  /// \p BB.
  void markRuntimeChecksFailedForBlock(BasicBlock *BB) {
    FailedRuntimeChecksBlocks.insert(BB);
  }

  /// Returns the modeled cost of the runtime alias checks collected during the
  /// last (optimistic) buildTree().
  InstructionCost getRuntimeChecksCost() const;

  /// Returns true if the last (optimistic) buildTree() collected any runtime
  /// alias checks that must guard the vectorized region.
  bool hasRuntimeAliasChecks() const { return !RTChecks.BasePairs.empty(); }

  /// Returns true if vectorization changed the CFG (i.e. a block was versioned
  /// with runtime alias checks). When true, CFG analyses must not be preserved.
  bool isCFGChanged() const { return CFGChanged; }

  TreeEntry &getRootNode() {
    assert(!VectorizableTree.empty() && "No graph to get the first node from");
    return *VectorizableTree.front();
  }

  const TreeEntry &getRootNode() const {
    assert(!VectorizableTree.empty() && "No graph to get the first node from");
    return *VectorizableTree.front();
  }

  /// Returns the scalars of the root node.
  ArrayRef<Value *> getRootNodeScalars() const { return getRootNode().Scalars; }

  /// Returns the lane the given value is vectorized to in the root node.
  unsigned findRootLaneForValue(Value *V) const {
    return getRootNode().findLaneForValue(V);
  }

  /// Returns the type/is-signed info for the root node in the graph without
  /// casting.
  std::optional<std::pair<Type *, bool>> getRootNodeTypeWithNoCast() const {
    const TreeEntry &Root = getRootNode();
    if (Root.State != TreeEntry::Vectorize || Root.isAltShuffle() ||
        !Root.Scalars.front()->getType()->isIntegerTy())
      return std::nullopt;
    auto It = MinBWs.find(&Root);
    if (It != MinBWs.end())
      return std::make_pair(IntegerType::get(Root.Scalars.front()->getContext(),
                                             It->second.first),
                            It->second.second);
    if (Root.getOpcode() == Instruction::ZExt ||
        Root.getOpcode() == Instruction::SExt)
      return std::make_pair(cast<CastInst>(Root.getMainOp())->getSrcTy(),
                            Root.getOpcode() == Instruction::SExt);
    return std::nullopt;
  }

  /// Checks if the root graph node can be emitted with narrower bitwidth at
  /// codegen and returns it signedness, if so.
  bool isSignedMinBitwidthRootNode() const {
    return MinBWs.at(&getRootNode()).second;
  }

  /// Returns reduction type after minbitdth analysis.
  FixedVectorType *getReductionType() const {
    if (ReductionBitWidth == 0 ||
        !getRootNodeScalars().front()->getType()->isIntegerTy() ||
        ReductionBitWidth >=
            DL->getTypeSizeInBits(getRootNodeScalars().front()->getType()))
      return cast<FixedVectorType>(
          getWidenedType(getRootNodeScalars().front()->getType(),
                         getRootNode().getVectorFactor()));
    return cast<FixedVectorType>(getWidenedType(
        IntegerType::get(getRootNodeScalars().front()->getContext(),
                         ReductionBitWidth),
        getRootNode().getVectorFactor()));
  }

  /// Returns true if the tree results in one of the reduced bitcasts variants.
  bool isReducedBitcastRoot() const {
    return getRootNode().hasState() &&
           (getRootNode().CombinedOp == TreeEntry::ReducedBitcast ||
            getRootNode().CombinedOp == TreeEntry::ReducedBitcastBSwap ||
            getRootNode().CombinedOp == TreeEntry::ReducedBitcastLoads ||
            getRootNode().CombinedOp == TreeEntry::ReducedBitcastBSwapLoads ||
            getRootNode().CombinedOp == TreeEntry::ReducedBitPack) &&
           getRootNode().State == TreeEntry::Vectorize;
  }

  /// Returns true if the tree results in the reduced cmp bitcast root.
  bool isReducedCmpBitcastRoot() const {
    return getRootNode().hasState() &&
           getRootNode().CombinedOp == TreeEntry::ReducedCmpBitcast &&
           getRootNode().State == TreeEntry::Vectorize;
  }

  /// Returns true if the tree is a reduction tree.
  bool isReductionTree() const { return UserIgnoreList != nullptr; }

  /// Builds external uses of the vectorized scalars, i.e. the list of
  /// vectorized scalars to be extracted, their lanes and their scalar users. \p
  /// ExternallyUsedValues contains additional list of external uses to handle
  /// vectorization of reductions.
  void
  buildExternalUses(const ExtraValueToDebugLocsMap &ExternallyUsedValues = {});

  /// Transforms graph nodes to target specific representations, if profitable.
  void transformNodes();

  /// Clear the internal data structures that are created by 'buildTree'.
  void deleteTree() {
    VectorizableTree.clear();
    ScalarToTreeEntries.clear();
    DeletedNodes.clear();
    TransformedToGatherNodes.clear();
    OperandsToTreeEntry.clear();
    ScalarsInSplitNodes.clear();
    MustGather.clear();
    ReassocScalarToTreeEntries.clear();
    KeptReassocScalars.clear();
    NonScheduledFirst.clear();
    EntryToLastInstruction.clear();
    LastInstructionToPos.clear();
    LoadEntriesToVectorize.clear();
    IsGraphTransformMode = false;
    GatheredLoadsEntriesFirst.reset();
    SplatGatheredScalarsRoots.clear();
    NumCanonicalSplatSubtreeEntries = 0;
    CompressEntryToData.clear();
    ExternalUses.clear();
    ExternalUsesAsOriginalScalar.clear();
    ExternalUsesWithNonUsers.clear();
    ExternalUseReplacements.clear();
    RTChecks.clear();
    HasRuntimeCheckableBlockers = false;
    HasNonCheckableMemBlocker = false;
    RTChecksFinalized = false;
    for (auto &Iter : BlocksSchedules) {
      BlockScheduling *BS = Iter.second.get();
      BS->clear();
    }
    MinBWs.clear();
    ReductionBitWidth = 0;
    BaseGraphSize = 1;
    CastMaxMinBWSizes.reset();
    ExtraBitWidthNodes.clear();
    InstrElementSize.clear();
    UserIgnoreList = nullptr;
    NarrowedChainInsts.clear();
    PostponedGathers.clear();
    ValueToGatherNodes.clear();
    TreeEntryToStridedPtrInfoMap.clear();
    CurrentLoopNest.clear();
    MergedLoopBTCs.clear();
  }

  unsigned getTreeSize() const { return VectorizableTree.size(); }

  /// Returns the size of the current tree, stopping at gathers
  /// For instance, even though we continue adding tree entries after
  /// a split node, this function stops counting at the split node
  /// since it is a gather. This matches the behavior of MinBWs
  /// computation.
  unsigned getTreeSizeExcludingGathers() const {
    unsigned Cnt = 0;
    SmallBitVector GatherTreeNodes(VectorizableTree.size(), false);
    for (unsigned NodeIdx : seq<unsigned>(VectorizableTree.size())) {
      auto &TE = VectorizableTree[NodeIdx];
      if (DeletedNodes.contains(TE.get()))
        continue;
      auto IsGather = [&](TreeEntry *TE) {
        return TE->isGather() || TransformedToGatherNodes.contains(TE) ||
               GatherTreeNodes.test(TE->Idx);
      };
      if (IsGather(TE.get()) || (!TE->UserTreeIndex.UserTE && NodeIdx != 0) ||
          (TE->UserTreeIndex.UserTE && (IsGather(TE->UserTreeIndex.UserTE)))) {
        GatherTreeNodes.set(NodeIdx);
        continue;
      }
      ++Cnt;
    }
    return Cnt;
  }

  /// Returns true if the tree gathers any scalars other than constants.
  bool hasNonConstantGathers() const {
    return any_of(VectorizableTree, [&](const std::unique_ptr<TreeEntry> &TE) {
      return !DeletedNodes.contains(TE.get()) &&
             (TE->isGather() || TransformedToGatherNodes.contains(TE.get())) &&
             !allConstant(TE->Scalars);
    });
  }

  /// Returns the base graph size, before any transformations.
  unsigned getCanonicalGraphSize() const { return BaseGraphSize; }

  /// Number of tree entries that form the splat gather subtrees.
  unsigned getNumSplatSubtreeEntries() const {
    return NumCanonicalSplatSubtreeEntries;
  }

  /// Perform LICM and CSE on the newly generated gather sequences.
  void optimizeGatherSequence();

  /// Does this non-empty order represent an identity order?  Identity
  /// should be represented as an empty order, so this is used to
  /// decide if we can canonicalize a computed order.  Undef elements
  /// (represented as size) are ignored.
  static bool isIdentityOrder(ArrayRef<unsigned> Order) {
    assert(!Order.empty() && "expected non-empty order");
    const unsigned Sz = Order.size();
    return all_of(enumerate(Order), [&](const auto &P) {
      return P.value() == P.index() || P.value() == Sz;
    });
  }

  /// Checks if the specified gather tree entry \p TE can be represented as a
  /// shuffled vector entry + (possibly) permutation with other gathers. It
  /// implements the checks only for possibly ordered scalars (Loads,
  /// ExtractElement, ExtractValue), which can be part of the graph.
  /// \param TopToBottom If true, used for the whole tree rotation, false - for
  /// sub-tree rotations. \param IgnoreReorder true, if the order of the root
  /// node might be ignored.
  std::optional<OrdersType> findReusedOrderedScalars(const TreeEntry &TE,
                                                     bool TopToBottom,
                                                     bool IgnoreReorder);

  /// Sort loads into increasing pointers offsets to allow greater clustering.
  std::optional<OrdersType> findPartiallyOrderedLoads(const TreeEntry &TE);

  /// Gets reordering data for the given tree entry. If the entry is vectorized
  /// - just return ReorderIndices, otherwise check if the scalars can be
  /// reordered and return the most optimal order.
  /// \return std::nullopt if ordering is not important, empty order, if
  /// identity order is important, or the actual order.
  /// \param TopToBottom If true, include the order of vectorized stores and
  /// insertelement nodes, otherwise skip them.
  /// \param IgnoreReorder true, if the root node order can be ignored.
  std::optional<OrdersType>
  getReorderingData(const TreeEntry &TE, bool TopToBottom, bool IgnoreReorder);

  /// Checks if it is profitable to reorder the current tree.
  /// If the tree does not contain many profitable reordable nodes, better to
  /// skip it to save compile time.
  bool isProfitableToReorder() const;

  /// Reorders the current graph to the most profitable order starting from the
  /// root node to the leaf nodes. The best order is chosen only from the nodes
  /// of the same size (vectorization factor). Smaller nodes are considered
  /// parts of subgraph with smaller VF and they are reordered independently. We
  /// can make it because we still need to extend smaller nodes to the wider VF
  /// and we can merge reordering shuffles with the widening shuffles.
  void reorderTopToBottom();

  /// Reorders the current graph to the most profitable order starting from
  /// leaves to the root. It allows to rotate small subgraphs and reduce the
  /// number of reshuffles if the leaf nodes use the same order. In this case we
  /// can merge the orders and just shuffle user node instead of shuffling its
  /// operands. Plus, even the leaf nodes have different orders, it allows to
  /// sink reordering in the graph closer to the root node and merge it later
  /// during analysis.
  void reorderBottomToTop(bool IgnoreReorder = false);

  /// Marks the schedule data of the copyable-modeled operands of \p TE for
  /// dependency recalculation at the next bundle scheduling.
  void markCopyableDepsForRecalc(TreeEntry &TE);

  /// \return The vector element size in bits to use when vectorizing the
  /// expression tree ending at \p V. If V is a store, the size is the width of
  /// the stored value. Otherwise, the size is the width of the largest loaded
  /// value reaching V. This method is used by the vectorizer to calculate
  /// vectorization factors.
  unsigned getVectorElementSize(Value *V);

  /// Compute the minimum type sizes required to represent the entries in a
  /// vectorizable tree.
  void computeMinimumValueSizes();

  // \returns maximum vector register size as set by TTI or overridden by cl::opt.
  unsigned getMaxVecRegSize() const {
    return MaxVecRegSize;
  }

  /// \returns the -slp-threshold value, 0 if unset.
  int getCostThreshold() const { return Opts.slp_threshold.value_or(0); }

  // \returns minimum vector register size as set by cl::opt.
  unsigned getMinVecRegSize() const {
    return MinVecRegSize;
  }

  /// \returns the number of parts, the type \p VecTy is split at the codegen
  /// phase. The type legalization queries are repeated for the very same types
  /// during the analysis, so the results are cached for the function.
  unsigned getNumberOfParts(
      Type *VecTy, Type *ScalarTy,
      unsigned Limit = std::numeric_limits<unsigned>::max()) const {
    auto [It, Inserted] =
        NumberOfPartsCache.try_emplace(std::make_tuple(VecTy, ScalarTy, Limit));
    if (Inserted)
      It->second = slpvectorizer::getNumberOfPartsOrRegs(
          /*QueryNumParts=*/true, *TTI, VecTy, ScalarTy, Opts.slp_revec, Limit);
    return It->second;
  }

  /// \returns the number of parts, the type \p VecTy is split at the codegen
  /// phase. The type legalization queries are repeated for the very same types
  /// during the analysis, so the results are cached for the function.
  unsigned getRegUsageForType(
      Type *VecTy, Type *ScalarTy,
      unsigned Limit = std::numeric_limits<unsigned>::max()) const {
    auto [It, Inserted] =
        NumberOfRegsCache.try_emplace(std::make_tuple(VecTy, ScalarTy, Limit));
    if (Inserted)
      It->second = slpvectorizer::getNumberOfPartsOrRegs(
          /*QueryNumParts=*/false, *TTI, VecTy, ScalarTy, Opts.slp_revec,
          Limit);
    return It->second;
  }

  unsigned getMinVF(unsigned Sz) const {
    return std::max(2U, getMinVecRegSize() / Sz);
  }

  unsigned getMaximumVF(unsigned ElemWidth, unsigned Opcode) const {
    unsigned MaxVF =
        Opts.slp_max_vf.value_or(TTI->getMaximumVF(ElemWidth, Opcode));
    return MaxVF ? MaxVF : UINT_MAX;
  }

  /// Check if homogeneous aggregate is isomorphic to some VectorType.
  /// Accepts homogeneous multidimensional aggregate of scalars/vectors like
  /// {[4 x i16], [4 x i16]}, { <2 x float>, <2 x float> },
  /// {{{i16, i16}, {i16, i16}}, {{i16, i16}, {i16, i16}}} and so on.
  ///
  /// \returns number of elements in vector if isomorphism exists, 0 otherwise.
  unsigned canMapToVector(Type *T) const;

  /// \returns true if the vectorized insertvalue result can be stored directly
  /// as a vector, i.e. every insertvalue with an external user is consumed by a
  /// single store only.
  bool canVectorStoreInsertValue(const TreeEntry *E) const;

  /// \returns the source vector type for an InsertElement/InsertValue
  /// buildvector node \p E: the inserted vector type for insertelement, or a
  /// vector of the inserted scalar type wide enough to cover the highest
  /// inserted index for insertvalue.
  FixedVectorType *getInsertBuildVectorSrcTy(const TreeEntry *E) const;

  /// \returns True if the VectorizableTree is both tiny and not fully
  /// vectorizable. We do not vectorize such trees.
  bool isTreeTinyAndNotFullyVectorizable(bool ForReduction = false) const;

  /// Checks if the graph and all its subgraphs cannot be better vectorized.
  /// It may happen, if all gather nodes are loads and they cannot be
  /// "clusterized". In this case even subgraphs cannot be vectorized more
  /// effectively than the base graph.
  bool isTreeNotExtendable() const;

  bool isStridedLoad(ArrayRef<Value *> PointerOps, Type *ScalarTy,
                     Align Alignment, const int64_t Diff,
                     const size_t Sz) const;

  /// Returns true for widened strided loads, where each lane of the strided
  /// load covers a group of consecutive scalars. Reversed widened strided
  /// loads must be emitted with a positive stride and a reorder shuffle.
  bool isWidenedStridedLoad(const TreeEntry *E) const;

  /// Return true if an array of scalar loads can be replaced with a strided
  ///  load (with constant stride).
  ///
  ///  It is possible that the load gets "widened". Suppose that originally each
  ///  load loads `k` bytes and `PointerOps` can be arranged as follows (`%s` is
  ///  constant): %b + 0 * %s + 0 %b + 0 * %s + 1 %b + 0 * %s + 2
  ///  ...
  ///  %b + 0 * %s + (w - 1)
  ///
  ///  %b + 1 * %s + 0
  ///  %b + 1 * %s + 1
  ///  %b + 1 * %s + 2
  ///  ...
  ///  %b + 1 * %s + (w - 1)
  ///  ...
  ///
  ///  %b + (n - 1) * %s + 0
  ///  %b + (n - 1) * %s + 1
  ///  %b + (n - 1) * %s + 2
  ///  ...
  ///  %b + (n - 1) * %s + (w - 1)
  ///
  /// In this case we will generate a strided load of type `<n x (k * w)>`.
  ///
  /// \param PointerOps list of pointer arguments of loads.
  /// \param ElemTy original scalar type of loads.
  /// \param Alignment alignment of the first load.
  /// \param SortedIndices is the order of PointerOps as returned by
  /// `sortPtrAccesses`
  /// \param Diff Pointer difference between the lowest and the highes pointer
  /// in `PointerOps` as returned by `getPointersDiff`.
  /// \param Ptr0 first pointer in `PointersOps`.
  /// \param PtrN last pointer in `PointersOps`.
  /// \param SPtrInfo If the function return `true`, it also sets all the fields
  /// of `SPtrInfo` necessary to generate the strided load later.
  bool analyzeConstantStrideCandidate(
      const ArrayRef<Value *> PointerOps, Type *ElemTy, Align Alignment,
      const SmallVectorImpl<unsigned> &SortedIndices, const int64_t Diff,
      Value *Ptr0, StridedPtrInfo &SPtrInfo) const;

  /// Return true if an array of scalar loads can be replaced with a strided
  /// load (with run-time stride).
  /// \param PointerOps list of pointer arguments of loads.
  /// \param ScalarTy type of loads.
  /// \param CommonAlignment common alignement of loads as computed by
  /// `computeCommonAlignment<LoadInst>`.
  /// \param SortedIndicies is a list of indicies computed by this function such
  /// that the sequence `PointerOps[SortedIndices[0]],
  /// PointerOps[SortedIndicies[1]], ..., PointerOps[SortedIndices[n]]` is
  /// ordered by the coefficient of the stride. For example, if PointerOps is
  /// `%base + %stride, %base, %base + 2 * stride` the `SortedIndices` will be
  /// `[1, 0, 2]`. We follow the convention that if `SortedIndices` has to be
  /// `0, 1, 2, 3, ...` we return empty vector for `SortedIndicies`.
  /// \param SPtrInfo If the function return `true`, it also sets all the fields
  /// of `SPtrInfo` necessary to generate the strided load later.
  /// \param IsLoad Is this a strided load (true) or strided store (false)
  bool analyzeRtStrideCandidate(ArrayRef<Value *> PointerOps, Type *ScalarTy,
                                Align CommonAlignment,
                                SmallVectorImpl<unsigned> &SortedIndices,
                                StridedPtrInfo &SPtrInfo, bool IsLoad) const;

  /// Checks if the given array of loads can be represented as a vectorized,
  /// scatter or just simple gather.
  /// \param VL list of loads.
  /// \param VL0 main load value.
  /// \param Order returned order of load instructions.
  /// \param PointerOps returned list of pointer operands.
  /// \param BestVF return best vector factor, if recursive check found better
  /// vectorization sequences rather than masked gather.
  /// \param TryRecursiveCheck used to check if long masked gather can be
  /// represented as a serie of loads/insert subvector, if profitable.
  LoadsState canVectorizeLoads(ArrayRef<Value *> VL, const Value *VL0,
                               SmallVectorImpl<unsigned> &Order,
                               SmallVectorImpl<Value *> &PointerOps,
                               StridedPtrInfo &SPtrInfo,
                               unsigned *BestVF = nullptr,
                               bool TryRecursiveCheck = true) const;

  /// Checks whether some existing tree entry has scalars equal to \p VL.
  /// \p S is the common opcode of \p VL when one exists; an empty \p S means
  /// the values have no common opcode (mixed buildvector/gather candidates).
  bool hasSameNode(const InstructionsState &S, ArrayRef<Value *> VL) const {
    auto IsSame = [&](const TreeEntry *TE) { return TE->isSame(VL); };
    if (S) {
      // Any vectorized or gather entry equal to VL must contain S.getMainOp()
      // (the representative instruction, which is also the recorded scalar
      // for copyable-elements bundles), so probing the MainOp-indexed maps
      // is sufficient and avoids scanning the whole tree.
      return any_of(getTreeEntries(S.getMainOp()), IsSame) ||
             any_of(ValueToGatherNodes.lookup(S.getMainOp()), IsSame);
    }
    // No common opcode: only gather entries can match. Each non-constant
    // value in VL has to be in the gather entry's scalar list and is
    // therefore present in ValueToGatherNodes. Probe by VL members instead
    // of scanning the whole tree (O(tree) -> O(|VL|)).
    SmallPtrSet<const TreeEntry *, 4> Visited;
    for (Value *V : VL) {
      // Constants/poisons are not tracked in ValueToGatherNodes.
      if (isConstant(V))
        continue;
      for (const TreeEntry *TE : ValueToGatherNodes.lookup(V)) {
        if (!Visited.insert(TE).second)
          continue;
        if (IsSame(TE))
          return true;
      }
    }
    return false;
  }

  /// Registers non-vectorizable sequence of loads
  template <typename T> void registerNonVectorizableLoads(ArrayRef<T *> VL) {
    ListOfKnonwnNonVectorizableLoads.insert(hash_value(VL));
  }

  /// Checks if the given loads sequence is known as not vectorizable
  template <typename T>
  bool areKnownNonVectorizableLoads(ArrayRef<T *> VL) const {
    return ListOfKnonwnNonVectorizableLoads.contains(hash_value(VL));
  }

  OptimizationRemarkEmitter *getORE() { return ORE; }

  /// This structure holds any data we need about the edges being traversed
  /// during buildTreeRec(). We keep track of:
  /// (i) the user TreeEntry index, and
  /// (ii) the index of the edge.
  struct EdgeInfo {
    EdgeInfo() = default;
    EdgeInfo(TreeEntry *UserTE, unsigned EdgeIdx)
        : UserTE(UserTE), EdgeIdx(EdgeIdx) {}
    /// The user TreeEntry.
    TreeEntry *UserTE = nullptr;
    /// The operand index of the use.
    unsigned EdgeIdx = UINT_MAX;
#ifndef NDEBUG
    friend inline raw_ostream &operator<<(raw_ostream &OS,
                                          const BoUpSLP::EdgeInfo &EI) {
      EI.dump(OS);
      return OS;
    }
    /// Debug print.
    void dump(raw_ostream &OS) const {
      OS << "{User:" << (UserTE ? std::to_string(UserTE->Idx) : "null")
         << " EdgeIdx:" << EdgeIdx << "}";
    }
    LLVM_DUMP_METHOD void dump() const { dump(dbgs()); }
#endif
    bool operator == (const EdgeInfo &Other) const {
      return UserTE == Other.UserTE && EdgeIdx == Other.EdgeIdx;
    }

    operator bool() const { return UserTE != nullptr; }
  };
  friend struct DenseMapInfo<EdgeInfo>;

  /// A helper class used for scoring candidates for two consecutive lanes.
  class LookAheadHeuristics {
    const TargetLibraryInfo &TLI;
    const DataLayout &DL;
    ScalarEvolution &SE;
    const BoUpSLP &R;
    int NumLanes; // Total number of lanes (aka vectorization factor).
    int MaxLevel; // The maximum recursion depth for accumulating score.

  public:
    LookAheadHeuristics(const TargetLibraryInfo &TLI, const DataLayout &DL,
                        ScalarEvolution &SE, const BoUpSLP &R, int NumLanes,
                        int MaxLevel)
        : TLI(TLI), DL(DL), SE(SE), R(R), NumLanes(NumLanes),
          MaxLevel(MaxLevel) {}

    // The hard-coded scores listed here are not very important, though it shall
    // be higher for better matches to improve the resulting cost. When
    // computing the scores of matching one sub-tree with another, we are
    // basically counting the number of values that are matching. So even if all
    // scores are set to 1, we would still get a decent matching result.
    // However, sometimes we have to break ties. For example we may have to
    // choose between matching loads vs matching opcodes. This is what these
    // scores are helping us with: they provide the order of preference. Also,
    // this is important if the scalar is externally used or used in another
    // tree entry node in the different lane.

    /// Loads from consecutive memory addresses, e.g. load(A[i]), load(A[i+1]).
    static constexpr int ScoreConsecutiveLoads = 40;
    /// The same load multiple times. This should have a better score than
    /// `ScoreSplat` because it in x86 for a 2-lane vector we can represent it
    /// with `movddup (%reg), xmm0` which has a throughput of 0.5 versus 0.5 for
    /// a vector load and 1.0 for a broadcast.
    static constexpr int ScoreSplatLoads = 30;
    /// Loads from reversed memory addresses, e.g. load(A[i+1]), load(A[i]).
    static constexpr int ScoreReversedLoads = 30;
    /// A load candidate for masked gather.
    static constexpr int ScoreMaskedGatherCandidate = 10;
    /// ExtractElementInst from same vector and consecutive indexes.
    static constexpr int ScoreConsecutiveExtracts = 40;
    /// ExtractElementInst from same vector and reversed indices.
    static constexpr int ScoreReversedExtracts = 30;
    /// Constants.
    static constexpr int ScoreConstants = 15;
    /// Same constants.
    static constexpr int ScoreSameConstants = 17;
    /// Instructions with the same opcode.
    static constexpr int ScoreSameOpcode = 20;
    /// Instructions with alt opcodes (e.g, add + sub).
    static constexpr int ScoreAltOpcodes = 10;
    /// Identical instructions (a.k.a. splat or broadcast).
    static constexpr int ScoreSplat = 10;
    /// Matching with an undef is preferable to failing.
    static constexpr int ScoreUndef = 10;
    /// Score for failing to find a decent match.
    static constexpr int ScoreFail = 0;
    /// Score if all users are vectorized.
    static constexpr int ScoreAllUserVectorized = 10;

    /// \returns the score of placing \p V1 and \p V2 in consecutive lanes.
    /// \p U1 and \p U2 are the users of \p V1 and \p V2.
    /// Also, checks if \p V1 and \p V2 are compatible with instructions in \p
    /// MainAltOps.
    int getShallowScore(Value *V1, Value *V2, Instruction *U1, Instruction *U2,
                        ArrayRef<Value *> MainAltOps) const {
      if (!isValidElementType(V1->getType(), R.Opts.slp_revec) ||
          !isValidElementType(V2->getType(), R.Opts.slp_revec))
        return LookAheadHeuristics::ScoreFail;

      if (V1 == V2) {
        if (isa<LoadInst>(V1)) {
          // Retruns true if the users of V1 and V2 won't need to be extracted.
          auto AllUsersAreInternal = [U1, U2, this](Value *V1, Value *V2) {
            // Bail out if we have too many uses to save compilation time.
            if (V1->hasNUsesOrMore(UsesLimit) || V2->hasNUsesOrMore(UsesLimit))
              return false;

            auto AllUsersVectorized = [U1, U2, this](Value *V) {
              return llvm::all_of(V->users(), [U1, U2, this](Value *U) {
                return U == U1 || U == U2 || R.isVectorized(U);
              });
            };
            return AllUsersVectorized(V1) && AllUsersVectorized(V2);
          };
          // A broadcast of a load can be cheaper on some targets.
          if (R.TTI->isLegalBroadcastLoad(V1->getType(),
                                          ElementCount::getFixed(NumLanes)) &&
              ((int)V1->getNumUses() == NumLanes ||
               AllUsersAreInternal(V1, V2)))
            return LookAheadHeuristics::ScoreSplatLoads;
        }
        if (isa<UndefValue>(V1))
          return LookAheadHeuristics::ScoreUndef;
        if (isConstant(V1))
          return LookAheadHeuristics::ScoreSameConstants;
        return LookAheadHeuristics::ScoreSplat;
      }

      auto CheckSameEntryOrFail = [&]() {
        if (ArrayRef<TreeEntry *> TEs1 = R.getTreeEntries(V1); !TEs1.empty()) {
          SmallPtrSet<TreeEntry *, 4> Set(llvm::from_range, TEs1);
          if (ArrayRef<TreeEntry *> TEs2 = R.getTreeEntries(V2);
              !TEs2.empty() &&
              any_of(TEs2, [&](TreeEntry *E) { return Set.contains(E); }))
            return LookAheadHeuristics::ScoreSplatLoads;
        }
        return LookAheadHeuristics::ScoreFail;
      };

      auto *LI1 = dyn_cast<LoadInst>(V1);
      auto *LI2 = dyn_cast<LoadInst>(V2);
      if (LI1 && LI2) {
        if (LI1->getParent() != LI2->getParent() || !LI1->isSimple() ||
            !LI2->isSimple())
          return CheckSameEntryOrFail();

        std::optional<int64_t> Dist = R.getPointersDiff(
            LI1->getType(), LI1->getPointerOperand(), LI2->getType(),
            LI2->getPointerOperand(), DL, SE, /*StrictCheck=*/true);
        if (!Dist || *Dist == 0) {
          if (getUnderlyingObject(LI1->getPointerOperand()) ==
                  getUnderlyingObject(LI2->getPointerOperand()) &&
              R.TTI->isLegalMaskedGather(
                  getWidenedType(LI1->getType(), NumLanes), LI1->getAlign()))
            return LookAheadHeuristics::ScoreMaskedGatherCandidate;
          return CheckSameEntryOrFail();
        }
        // The distance is too large - still may be profitable to use masked
        // loads/gathers.
        if (std::abs(*Dist) > NumLanes / 2)
          return LookAheadHeuristics::ScoreMaskedGatherCandidate;
        // This still will detect consecutive loads, but we might have "holes"
        // in some cases. It is ok for non-power-2 vectorization and may produce
        // better results. It should not affect current vectorization.
        return (*Dist > 0) ? LookAheadHeuristics::ScoreConsecutiveLoads
                           : LookAheadHeuristics::ScoreReversedLoads;
      }

      auto *C1 = dyn_cast<Constant>(V1);
      auto *C2 = dyn_cast<Constant>(V2);
      if (C1 && C2)
        return LookAheadHeuristics::ScoreConstants;

      // Consider constants and buildvector compatible.
      if ((C1 && isa<InsertElementInst>(V2)) ||
          (C2 && isa<InsertElementInst>(V1)))
        return LookAheadHeuristics::ScoreSameOpcode;

      // Extracts from consecutive indexes of the same vector better score as
      // the extracts could be optimized away.
      Value *EV1;
      ConstantInt *Ex1Idx;
      if (match(V1, m_ExtractElt(m_Value(EV1), m_ConstantInt(Ex1Idx)))) {
        // Undefs are always profitable for extractelements.
        // Compiler can easily combine poison and extractelement <non-poison> or
        // undef and extractelement <poison>. But combining undef +
        // extractelement <non-poison-but-may-produce-poison> requires some
        // extra operations.
        if (isa<UndefValue>(V2))
          return (isa<PoisonValue>(V2) || isUndefVector(EV1).all())
                     ? LookAheadHeuristics::ScoreConsecutiveExtracts
                     : LookAheadHeuristics::ScoreSameOpcode;
        Value *EV2 = nullptr;
        ConstantInt *Ex2Idx = nullptr;
        if (match(V2,
                  m_ExtractElt(m_Value(EV2), m_CombineOr(m_ConstantInt(Ex2Idx),
                                                         m_Undef())))) {
          // Undefs are always profitable for extractelements.
          if (!Ex2Idx)
            return LookAheadHeuristics::ScoreConsecutiveExtracts;
          if (isUndefVector(EV2).all() && EV2->getType() == EV1->getType())
            return LookAheadHeuristics::ScoreConsecutiveExtracts;
          if (EV2 == EV1) {
            int Idx1 = Ex1Idx->getZExtValue();
            int Idx2 = Ex2Idx->getZExtValue();
            int Dist = Idx2 - Idx1;
            // The distance is too large - still may be profitable to use
            // shuffles.
            if (std::abs(Dist) == 0)
              return LookAheadHeuristics::ScoreSplat;
            if (std::abs(Dist) > NumLanes / 2)
              return LookAheadHeuristics::ScoreSameOpcode;
            return (Dist > 0) ? LookAheadHeuristics::ScoreConsecutiveExtracts
                              : LookAheadHeuristics::ScoreReversedExtracts;
          }
          return LookAheadHeuristics::ScoreAltOpcodes;
        }
        return CheckSameEntryOrFail();
      }

      auto *I1 = dyn_cast<Instruction>(V1);
      auto *I2 = dyn_cast<Instruction>(V2);
      if (I1 && I2) {
        if (I1->getParent() != I2->getParent())
          return CheckSameEntryOrFail();
        Value *V;
        Value *Cond;
        // ZExt i1 to something must be considered same opcode for select i1
        // cmp, x, y
        // Required to better match the transformation after
        // BoUpSLP::matchesInversedZExtSelect analysis.
        if ((match(I1, m_ZExt(m_Value(V))) &&
             match(I2, m_Select(m_Value(Cond), m_Value(), m_Value())) &&
             V->getType() == Cond->getType()) ||
            (match(I2, m_ZExt(m_Value(V))) &&
             match(I1, m_Select(m_Value(Cond), m_Value(), m_Value())) &&
             V->getType() == Cond->getType()))
          return LookAheadHeuristics::ScoreSameOpcode;
        SmallVector<Value *, 4> Ops(MainAltOps);
        Ops.push_back(I1);
        Ops.push_back(I2);
        InstructionsState S = getSameOpcode(Ops, TLI);
        // Note: Only consider instructions with <= 2 operands to avoid
        // complexity explosion.
        if (S &&
            (S.getMainOp()->getNumOperands() <= 2 || !MainAltOps.empty() ||
             !S.isAltShuffle()) &&
            all_of(make_isa_range<Instruction>(Ops), [&S](Instruction *I) {
              return I->getNumOperands() == S.getMainOp()->getNumOperands() ||
                     (S.getOpcode() == Instruction::ICmp && isa<TruncInst>(I));
            }))
          return S.isAltShuffle() ? LookAheadHeuristics::ScoreAltOpcodes
                                  : LookAheadHeuristics::ScoreSameOpcode;
      }

      if (I1 && isa<PoisonValue>(V2))
        return LookAheadHeuristics::ScoreSameOpcode;

      if (isa<UndefValue>(V2))
        return LookAheadHeuristics::ScoreUndef;

      return CheckSameEntryOrFail();
    }

    /// Go through the operands of \p LHS and \p RHS recursively until
    /// MaxLevel, and return the cummulative score. \p U1 and \p U2 are
    /// the users of \p LHS and \p RHS (that is \p LHS and \p RHS are operands
    /// of \p U1 and \p U2), except at the beginning of the recursion where
    /// these are set to nullptr.
    ///
    /// For example:
    /// \verbatim
    ///  A[0]  B[0]  A[1]  B[1]  C[0] D[0]  B[1] A[1]
    ///     \ /         \ /         \ /        \ /
    ///      +           +           +          +
    ///     G1          G2          G3         G4
    /// \endverbatim
    /// The getScoreAtLevelRec(G1, G2) function will try to match the nodes at
    /// each level recursively, accumulating the score. It starts from matching
    /// the additions at level 0, then moves on to the loads (level 1). The
    /// score of G1 and G2 is higher than G1 and G3, because {A[0],A[1]} and
    /// {B[0],B[1]} match with LookAheadHeuristics::ScoreConsecutiveLoads, while
    /// {A[0],C[0]} has a score of LookAheadHeuristics::ScoreFail.
    /// Please note that the order of the operands does not matter, as we
    /// evaluate the score of all profitable combinations of operands. In
    /// other words the score of G1 and G4 is the same as G1 and G2. This
    /// heuristic is based on ideas described in:
    ///   Look-ahead SLP: Auto-vectorization in the presence of commutative
    ///   operations, CGO 2018 by Vasileios Porpodas, Rodrigo C. O. Rocha,
    ///   Luís F. W. Góes
    int getScoreAtLevelRec(Value *LHS, Value *RHS, Instruction *U1,
                           Instruction *U2, int CurrLevel,
                           ArrayRef<Value *> MainAltOps) const {

      // Get the shallow score of V1 and V2.
      int ShallowScoreAtThisLevel =
          getShallowScore(LHS, RHS, U1, U2, MainAltOps);

      // If reached MaxLevel,
      //  or if V1 and V2 are not instructions,
      //  or if they are SPLAT,
      //  or if they are not consecutive,
      //  or if profitable to vectorize loads or extractelements, early return
      //  the current cost.
      auto *I1 = dyn_cast<Instruction>(LHS);
      auto *I2 = dyn_cast<Instruction>(RHS);
      if (CurrLevel == MaxLevel || !(I1 && I2) || I1 == I2 ||
          ShallowScoreAtThisLevel == LookAheadHeuristics::ScoreFail ||
          (((isa<LoadInst>(I1) && isa<LoadInst>(I2)) ||
            (I1->getNumOperands() > 2 && I2->getNumOperands() > 2) ||
            (isa<ExtractElementInst>(I1) && isa<ExtractElementInst>(I2))) &&
           ShallowScoreAtThisLevel))
        return ShallowScoreAtThisLevel;
      assert(I1 && I2 && "Should have early exited.");

      // Contains the I2 operand indexes that got matched with I1 operands.
      SmallSet<unsigned, 4> Op2Used;

      // Recursion towards the operands of I1 and I2. We are trying all possible
      // operand pairs, and keeping track of the best score.
      if (I1->getNumOperands() != I2->getNumOperands())
        return LookAheadHeuristics::ScoreSameOpcode;
      for (unsigned OpIdx1 = 0, NumOperands1 = I1->getNumOperands();
           OpIdx1 != NumOperands1; ++OpIdx1) {
        // Try to pair op1I with the best operand of I2.
        int MaxTmpScore = 0;
        unsigned MaxOpIdx2 = 0;
        bool FoundBest = false;
        // If I2 is commutative try all combinations.
        unsigned FromIdx = isCommutative(I2) ? 0 : OpIdx1;
        unsigned ToIdx = isCommutative(I2)
                             ? I2->getNumOperands()
                             : std::min(I2->getNumOperands(), OpIdx1 + 1);
        assert(FromIdx <= ToIdx && "Bad index");
        for (unsigned OpIdx2 = FromIdx; OpIdx2 != ToIdx; ++OpIdx2) {
          // Skip operands already paired with OpIdx1.
          if (Op2Used.count(OpIdx2))
            continue;
          // Recursively calculate the cost at each level
          int TmpScore =
              getScoreAtLevelRec(I1->getOperand(OpIdx1), I2->getOperand(OpIdx2),
                                 I1, I2, CurrLevel + 1, {});
          // Look for the best score.
          if (TmpScore > LookAheadHeuristics::ScoreFail &&
              TmpScore > MaxTmpScore) {
            MaxTmpScore = TmpScore;
            MaxOpIdx2 = OpIdx2;
            FoundBest = true;
          }
        }
        if (FoundBest) {
          // Pair {OpIdx1, MaxOpIdx2} was found to be best. Never revisit it.
          Op2Used.insert(MaxOpIdx2);
          ShallowScoreAtThisLevel += MaxTmpScore;
        }
      }
      return ShallowScoreAtThisLevel;
    }
  };
  /// A helper data structure to hold the operands of a vector of instructions.
  /// This supports a fixed vector length for all operand vectors.
  class VLOperands {
    /// For each operand we need (i) the value, and (ii) the opcode that it
    /// would be attached to if the expression was in a left-linearized form.
    /// This is required to avoid illegal operand reordering.
    /// For example:
    /// \verbatim
    ///                         0 Op1
    ///                         |/
    /// Op1 Op2   Linearized    + Op2
    ///   \ /     ---------->   |/
    ///    -                    -
    ///
    /// Op1 - Op2            (0 + Op1) - Op2
    /// \endverbatim
    ///
    /// Value Op1 is attached to a '+' operation, and Op2 to a '-'.
    ///
    /// Another way to think of this is to track all the operations across the
    /// path from the operand all the way to the root of the tree and to
    /// calculate the operation that corresponds to this path. For example, the
    /// path from Op2 to the root crosses the RHS of the '-', therefore the
    /// corresponding operation is a '-' (which matches the one in the
    /// linearized tree, as shown above).
    ///
    /// For lack of a better term, we refer to this operation as Accumulated
    /// Path Operation (APO).
    struct OperandData {
      OperandData() = default;
      OperandData(Value *V, bool APO, bool IsUsed)
          : V(V), APO(APO), IsUsed(IsUsed) {}
      /// The operand value.
      Value *V = nullptr;
      /// TreeEntries only allow a single opcode, or an alternate sequence of
      /// them (e.g, +, -). Therefore, we can safely use a boolean value for the
      /// APO. It is set to 'true' if 'V' is attached to an inverse operation
      /// in the left-linearized form (e.g., Sub/Div), and 'false' otherwise
      /// (e.g., Add/Mul)
      bool APO = false;
      /// Helper data for the reordering function.
      bool IsUsed = false;
    };

    /// During operand reordering, we are trying to select the operand at lane
    /// that matches best with the operand at the neighboring lane. Our
    /// selection is based on the type of value we are looking for. For example,
    /// if the neighboring lane has a load, we need to look for a load that is
    /// accessing a consecutive address. These strategies are summarized in the
    /// 'ReorderingMode' enumerator.
    enum class ReorderingMode {
      Load,     ///< Matching loads to consecutive memory addresses
      Opcode,   ///< Matching instructions based on opcode (same or alternate)
      Constant, ///< Matching constants
      Splat,    ///< Matching the same instruction multiple times (broadcast)
      Failed,   ///< We failed to create a vectorizable group
    };

    using OperandDataVec = SmallVector<OperandData, 2>;

    /// A vector of operand vectors.
    SmallVector<OperandDataVec, 4> OpsVec;
    /// When VL[0] is IntrinsicInst, ArgSize is CallBase::arg_size. When VL[0]
    /// is not IntrinsicInst, ArgSize is User::getNumOperands.
    unsigned ArgSize = 0;

    const TargetLibraryInfo &TLI;
    const DataLayout &DL;
    ScalarEvolution &SE;
    const BoUpSLP &R;
    const Loop *L = nullptr;

    /// \returns the operand data at \p OpIdx and \p Lane.
    OperandData &getData(unsigned OpIdx, unsigned Lane) {
      return OpsVec[OpIdx][Lane];
    }

    /// \returns the operand data at \p OpIdx and \p Lane. Const version.
    const OperandData &getData(unsigned OpIdx, unsigned Lane) const {
      return OpsVec[OpIdx][Lane];
    }

    /// Clears the used flag for all entries.
    void clearUsed() {
      for (unsigned OpIdx = 0, NumOperands = getNumOperands();
           OpIdx != NumOperands; ++OpIdx)
        for (unsigned Lane = 0, NumLanes = getNumLanes(); Lane != NumLanes;
             ++Lane)
          OpsVec[OpIdx][Lane].IsUsed = false;
    }

    /// Swap the operand at \p OpIdx1 with that one at \p OpIdx2.
    void swap(unsigned OpIdx1, unsigned OpIdx2, unsigned Lane) {
      std::swap(OpsVec[OpIdx1][Lane], OpsVec[OpIdx2][Lane]);
    }

    /// \param Lane lane of the operands under analysis.
    /// \param OpIdx operand index in \p Lane lane we're looking the best
    /// candidate for.
    /// \param Idx operand index of the current candidate value.
    /// \returns The additional score due to possible broadcasting of the
    /// elements in the lane. It is more profitable to have power-of-2 unique
    /// elements in the lane, it will be vectorized with higher probability
    /// after removing duplicates. Currently the SLP vectorizer supports only
    /// vectorization of the power-of-2 number of unique scalars.
    int getSplatScore(unsigned Lane, unsigned OpIdx, unsigned Idx,
                      const SmallBitVector &UsedLanes) const {
      Value *IdxLaneV = getData(Idx, Lane).V;
      if (!isa<Instruction>(IdxLaneV) || IdxLaneV == getData(OpIdx, Lane).V ||
          isa<ExtractElementInst>(IdxLaneV))
        return 0;
      SmallDenseMap<Value *, unsigned, 4> Uniques;
      for (unsigned Ln : seq<unsigned>(getNumLanes())) {
        if (Ln == Lane)
          continue;
        Value *OpIdxLnV = getData(OpIdx, Ln).V;
        if (!isa<Instruction>(OpIdxLnV))
          return 0;
        Uniques.try_emplace(OpIdxLnV, Ln);
      }
      unsigned UniquesCount = Uniques.size();
      auto IdxIt = Uniques.find(IdxLaneV);
      unsigned UniquesCntWithIdxLaneV =
          IdxIt != Uniques.end() ? UniquesCount : UniquesCount + 1;
      Value *OpIdxLaneV = getData(OpIdx, Lane).V;
      auto OpIdxIt = Uniques.find(OpIdxLaneV);
      unsigned UniquesCntWithOpIdxLaneV =
          OpIdxIt != Uniques.end() ? UniquesCount : UniquesCount + 1;
      if (UniquesCntWithIdxLaneV == UniquesCntWithOpIdxLaneV)
        return 0;
      return std::min(bit_ceil(UniquesCntWithOpIdxLaneV) -
                          UniquesCntWithOpIdxLaneV,
                      UniquesCntWithOpIdxLaneV -
                          bit_floor(UniquesCntWithOpIdxLaneV)) -
             ((IdxIt != Uniques.end() && UsedLanes.test(IdxIt->second))
                  ? UniquesCntWithIdxLaneV - bit_floor(UniquesCntWithIdxLaneV)
                  : bit_ceil(UniquesCntWithIdxLaneV) - UniquesCntWithIdxLaneV);
    }

    /// \param Lane lane of the operands under analysis.
    /// \param OpIdx operand index in \p Lane lane we're looking the best
    /// candidate for.
    /// \param Idx operand index of the current candidate value.
    /// \returns The additional score for the scalar which users are all
    /// vectorized.
    int getExternalUseScore(unsigned Lane, unsigned OpIdx, unsigned Idx) const {
      Value *IdxLaneV = getData(Idx, Lane).V;
      Value *OpIdxLaneV = getData(OpIdx, Lane).V;
      // Do not care about number of uses for vector-like instructions
      // (extractelement/extractvalue with constant indices), they are extracts
      // themselves and already externally used. Vectorization of such
      // instructions does not add extra extractelement instruction, just may
      // remove it.
      if (isVectorLikeInstWithConstOps(IdxLaneV) &&
          isVectorLikeInstWithConstOps(OpIdxLaneV))
        return LookAheadHeuristics::ScoreAllUserVectorized;
      auto *IdxLaneI = dyn_cast<Instruction>(IdxLaneV);
      if (!IdxLaneI || !isa<Instruction>(OpIdxLaneV))
        return 0;
      return R.areAllUsersVectorized(IdxLaneI)
                 ? LookAheadHeuristics::ScoreAllUserVectorized
                 : 0;
    }

    /// Score scaling factor for fully compatible instructions but with
    /// different number of external uses. Allows better selection of the
    /// instructions with less external uses.
    static constexpr int ScoreScaleFactor = 10;
    /// Scale factor for constants only.
    static constexpr int ScoreConstantScaleFactor = 6;

    /// \Returns the look-ahead score, which tells us how much the sub-trees
    /// rooted at \p LHS and \p RHS match, the more they match the higher the
    /// score. This helps break ties in an informed way when we cannot decide on
    /// the order of the operands by just considering the immediate
    /// predecessors.
    int getLookAheadScore(Value *LHS, Value *RHS, ArrayRef<Value *> MainAltOps,
                          int Lane, unsigned OpIdx, unsigned Idx,
                          bool &IsUsed, const SmallBitVector &UsedLanes) {
      LookAheadHeuristics LookAhead(TLI, DL, SE, R, getNumLanes(),
                                    R.Opts.slp_max_look_ahead_depth);
      // Keep track of the instruction stack as we recurse into the operands
      // during the look-ahead score exploration.
      int Score =
          LookAhead.getScoreAtLevelRec(LHS, RHS, /*U1=*/nullptr, /*U2=*/nullptr,
                                       /*CurrLevel=*/1, MainAltOps);
      if (Score) {
        int SplatScore =
            getSplatScore(Lane, OpIdx, Idx, UsedLanes) * ScoreScaleFactor;
        if (Score <= -SplatScore) {
          // Failed score.
          Score = 0;
        } else {
          Score += SplatScore;
          // Scale score to see the difference between different operands
          // and similar operands but all vectorized/not all vectorized
          // uses. It does not affect actual selection of the best
          // compatible operand in general, just allows to select the
          // operand with all vectorized uses.
          const int SF = (LHS == RHS && isConstant(LHS))
                             ? ScoreConstantScaleFactor
                             : ScoreScaleFactor;
          Score *= SF;
          Score += getExternalUseScore(Lane, OpIdx, Idx);
          IsUsed = true;
        }
      }
      return Score;
    }

    /// Best defined scores per lanes between the passes. Used to choose the
    /// best operand (with the highest score) between the passes.
    /// The key - {Operand Index, Lane}.
    /// The value - the best score between the passes for the lane and the
    /// operand.
    SmallDenseMap<std::pair<unsigned, unsigned>, unsigned, 8>
        BestScoresPerLanes;

    // Search all operands in Ops[*][Lane] for the one that matches best
    // Ops[OpIdx][LastLane] and return its opreand index.
    // If no good match can be found, return std::nullopt.
    std::optional<unsigned>
    getBestOperand(unsigned OpIdx, int Lane, int LastLane,
                   ArrayRef<ReorderingMode> ReorderingModes,
                   ArrayRef<Value *> MainAltOps,
                   const SmallBitVector &UsedLanes) {
      unsigned NumOperands = getNumOperands();

      // The operand of the previous lane at OpIdx.
      Value *OpLastLane = getData(OpIdx, LastLane).V;

      // Our strategy mode for OpIdx.
      ReorderingMode RMode = ReorderingModes[OpIdx];
      if (RMode == ReorderingMode::Failed)
        return std::nullopt;

      // The linearized opcode of the operand at OpIdx, Lane.
      bool OpIdxAPO = getData(OpIdx, Lane).APO;

      // The best operand index and its score.
      // Sometimes we have more than one option (e.g., Opcode and Undefs), so we
      // are using the score to differentiate between the two.
      struct BestOpData {
        std::optional<unsigned> Idx;
        unsigned Score = 0;
      } BestOp;
      BestOp.Score =
          BestScoresPerLanes.try_emplace(std::make_pair(OpIdx, Lane), 0)
              .first->second;

      // Track if the operand must be marked as used. If the operand is set to
      // Score 1 explicitly (because of non power-of-2 unique scalars, we may
      // want to reestimate the operands again on the following iterations).
      bool IsUsed = RMode == ReorderingMode::Splat ||
                    RMode == ReorderingMode::Constant ||
                    RMode == ReorderingMode::Load;
      // Iterate through all unused operands and look for the best.
      for (unsigned Idx = 0; Idx != NumOperands; ++Idx) {
        // Get the operand at Idx and Lane.
        OperandData &OpData = getData(Idx, Lane);
        Value *Op = OpData.V;
        bool OpAPO = OpData.APO;

        // Skip already selected operands.
        if (OpData.IsUsed)
          continue;

        // Skip if we are trying to move the operand to a position with a
        // different opcode in the linearized tree form. This would break the
        // semantics.
        if (OpAPO != OpIdxAPO)
          continue;

        // Look for an operand that matches the current mode.
        switch (RMode) {
        case ReorderingMode::Load:
        case ReorderingMode::Opcode: {
          bool LeftToRight = Lane > LastLane;
          Value *OpLeft = (LeftToRight) ? OpLastLane : Op;
          Value *OpRight = (LeftToRight) ? Op : OpLastLane;
          int Score = getLookAheadScore(OpLeft, OpRight, MainAltOps, Lane,
                                        OpIdx, Idx, IsUsed, UsedLanes);
          if (Score > static_cast<int>(BestOp.Score) ||
              (Score > 0 && Score == static_cast<int>(BestOp.Score) &&
               Idx == OpIdx)) {
            BestOp.Idx = Idx;
            BestOp.Score = Score;
            BestScoresPerLanes[std::make_pair(OpIdx, Lane)] = Score;
          }
          break;
        }
        case ReorderingMode::Constant:
          if (isa<Constant>(Op) ||
              (!BestOp.Score && L && L->isLoopInvariant(Op))) {
            BestOp.Idx = Idx;
            if (isa<Constant>(Op)) {
              BestOp.Score = LookAheadHeuristics::ScoreConstants;
              BestScoresPerLanes[std::make_pair(OpIdx, Lane)] =
                  LookAheadHeuristics::ScoreConstants;
            }
            if (isa<UndefValue>(Op) || !isa<Constant>(Op))
              IsUsed = false;
          }
          break;
        case ReorderingMode::Splat:
          if (Op == OpLastLane || (!BestOp.Score && isa<Constant>(Op))) {
            IsUsed = Op == OpLastLane;
            if (Op == OpLastLane) {
              BestOp.Score = LookAheadHeuristics::ScoreSplat;
              BestScoresPerLanes[std::make_pair(OpIdx, Lane)] =
                  LookAheadHeuristics::ScoreSplat;
            }
            BestOp.Idx = Idx;
          }
          break;
        case ReorderingMode::Failed:
          llvm_unreachable("Not expected Failed reordering mode.");
        }
      }

      if (BestOp.Idx) {
        getData(*BestOp.Idx, Lane).IsUsed = IsUsed;
        return BestOp.Idx;
      }
      // If we could not find a good match return std::nullopt.
      return std::nullopt;
    }

    /// Helper for reorderOperandVecs.
    /// \returns the lane that we should start reordering from. This is the one
    /// which has the least number of operands that can freely move about or
    /// less profitable because it already has the most optimal set of operands.
    unsigned getBestLaneToStartReordering() const {
      unsigned Min = UINT_MAX;
      unsigned SameOpNumber = 0;
      // std::pair<unsigned, unsigned> is used to implement a simple voting
      // algorithm and choose the lane with the least number of operands that
      // can freely move about or less profitable because it already has the
      // most optimal set of operands. The first unsigned is a counter for
      // voting, the second unsigned is the counter of lanes with instructions
      // with same/alternate opcodes and same parent basic block.
      MapVector<unsigned, std::pair<unsigned, unsigned>> HashMap;
      // Try to be closer to the original results, if we have multiple lanes
      // with same cost. If 2 lanes have the same cost, use the one with the
      // highest index.
      for (int I = getNumLanes(); I > 0; --I) {
        unsigned Lane = I - 1;
        OperandsOrderData NumFreeOpsHash =
            getMaxNumOperandsThatCanBeReordered(Lane);
        // Compare the number of operands that can move and choose the one with
        // the least number.
        if (NumFreeOpsHash.NumOfAPOs < Min) {
          Min = NumFreeOpsHash.NumOfAPOs;
          SameOpNumber = NumFreeOpsHash.NumOpsWithSameOpcodeParent;
          HashMap.clear();
          HashMap[NumFreeOpsHash.Hash] = std::make_pair(1, Lane);
        } else if (NumFreeOpsHash.NumOfAPOs == Min &&
                   NumFreeOpsHash.NumOpsWithSameOpcodeParent < SameOpNumber) {
          // Select the most optimal lane in terms of number of operands that
          // should be moved around.
          SameOpNumber = NumFreeOpsHash.NumOpsWithSameOpcodeParent;
          HashMap[NumFreeOpsHash.Hash] = std::make_pair(1, Lane);
        } else if (NumFreeOpsHash.NumOfAPOs == Min &&
                   NumFreeOpsHash.NumOpsWithSameOpcodeParent == SameOpNumber) {
          auto [It, Inserted] =
              HashMap.try_emplace(NumFreeOpsHash.Hash, 1, Lane);
          if (!Inserted)
            ++It->second.first;
        }
      }
      // Select the lane with the minimum counter.
      unsigned BestLane = 0;
      unsigned CntMin = UINT_MAX;
      for (const auto &Data : reverse(HashMap)) {
        if (Data.second.first < CntMin) {
          CntMin = Data.second.first;
          BestLane = Data.second.second;
        }
      }
      return BestLane;
    }

    /// Data structure that helps to reorder operands.
    struct OperandsOrderData {
      /// The best number of operands with the same APOs, which can be
      /// reordered.
      unsigned NumOfAPOs = UINT_MAX;
      /// Number of operands with the same/alternate instruction opcode and
      /// parent.
      unsigned NumOpsWithSameOpcodeParent = 0;
      /// Hash for the actual operands ordering.
      /// Used to count operands, actually their position id and opcode
      /// value. It is used in the voting mechanism to find the lane with the
      /// least number of operands that can freely move about or less profitable
      /// because it already has the most optimal set of operands. Can be
      /// replaced with SmallVector<unsigned> instead but hash code is faster
      /// and requires less memory.
      unsigned Hash = 0;
    };
    /// \returns the maximum number of operands that are allowed to be reordered
    /// for \p Lane and the number of compatible instructions(with the same
    /// parent/opcode). This is used as a heuristic for selecting the first lane
    /// to start operand reordering.
    OperandsOrderData getMaxNumOperandsThatCanBeReordered(unsigned Lane) const {
      unsigned CntTrue = 0;
      unsigned NumOperands = getNumOperands();
      // Operands with the same APO can be reordered. We therefore need to count
      // how many of them we have for each APO, like this: Cnt[APO] = x.
      // Since we only have two APOs, namely true and false, we can avoid using
      // a map. Instead we can simply count the number of operands that
      // correspond to one of them (in this case the 'true' APO), and calculate
      // the other by subtracting it from the total number of operands.
      // Operands with the same instruction opcode and parent are more
      // profitable since we don't need to move them in many cases, with a high
      // probability such lane already can be vectorized effectively.
      bool AllUndefs = true;
      unsigned NumOpsWithSameOpcodeParent = 0;
      Instruction *OpcodeI = nullptr;
      BasicBlock *Parent = nullptr;
      unsigned Hash = 0;
      for (unsigned OpIdx = 0; OpIdx != NumOperands; ++OpIdx) {
        const OperandData &OpData = getData(OpIdx, Lane);
        if (OpData.APO)
          ++CntTrue;
        // Use Boyer-Moore majority voting for finding the majority opcode and
        // the number of times it occurs.
        if (auto *I = dyn_cast<Instruction>(OpData.V)) {
          if (!OpcodeI || !getSameOpcode({OpcodeI, I}, TLI) ||
              I->getParent() != Parent) {
            if (NumOpsWithSameOpcodeParent == 0) {
              NumOpsWithSameOpcodeParent = 1;
              OpcodeI = I;
              Parent = I->getParent();
            } else {
              --NumOpsWithSameOpcodeParent;
            }
          } else {
            ++NumOpsWithSameOpcodeParent;
          }
        }
        Hash = hash_combine(
            Hash, hash_value((OpIdx + 1) * (OpData.V->getValueID() + 1)));
        AllUndefs = AllUndefs && isa<UndefValue>(OpData.V);
      }
      if (AllUndefs)
        return {};
      OperandsOrderData Data;
      Data.NumOfAPOs = std::max(CntTrue, NumOperands - CntTrue);
      Data.NumOpsWithSameOpcodeParent = NumOpsWithSameOpcodeParent;
      Data.Hash = Hash;
      return Data;
    }

    /// Go through the instructions in VL and append their operands.
    void appendOperands(ArrayRef<Value *> VL, ArrayRef<ValueList> Operands,
                        const InstructionsState &S) {
      assert(!Operands.empty() && !VL.empty() && "Bad list of operands");
      assert((empty() || all_of(Operands,
                                [this](const ValueList &VL) {
                                  return VL.size() == getNumLanes();
                                })) &&
             "Expected same number of lanes");
      assert(S.valid() && "InstructionsState is invalid.");
      // IntrinsicInst::isCommutative returns true if swapping the first "two"
      // arguments to the intrinsic produces the same result.
      Instruction *MainOp = S.getMainOp();
      ArgSize = getNumberOfPotentiallyCommutativeOps(MainOp);
      OpsVec.resize(ArgSize);
      unsigned NumLanes = VL.size();
      for (OperandDataVec &Ops : OpsVec)
        Ops.resize(NumLanes);
      for (unsigned Lane : seq<unsigned>(NumLanes)) {
        // Our tree has just 3 nodes: the root and two operands.
        // It is therefore trivial to get the APO. We only need to check the
        // opcode of V and whether the operand at OpIdx is the LHS or RHS
        // operand. The LHS operand of both add and sub is never attached to an
        // inversese operation in the linearized form, therefore its APO is
        // false. The RHS is true only if V is an inverse operation.

        // Since operand reordering is performed on groups of commutative
        // operations or alternating sequences (e.g., +, -), we can safely tell
        // the inverse operations by checking commutativity.
        auto *I = dyn_cast<Instruction>(VL[Lane]);
        if (!I && isa<PoisonValue>(VL[Lane])) {
          for (unsigned OpIdx : seq<unsigned>(ArgSize))
            OpsVec[OpIdx][Lane] = {Operands[OpIdx][Lane], true, false};
          continue;
        }
        bool IsInverseOperation = false;
        if (S.isCopyableElement(VL[Lane])) {
          // The value is a copyable element.
          IsInverseOperation =
              !isCommutative(MainOp, VL[Lane], /*IsCopyable=*/true);
        } else {
          assert(I && "Expected instruction");
          Instruction *SelectedOp = convertTo(I, S).first;
          // We cannot check commutativity by the converted instruction
          // (SelectedOp) because isCommutative also examines def-use
          // relationships.
          IsInverseOperation = !isCommutative(SelectedOp, I);
        }
        for (unsigned OpIdx : seq<unsigned>(ArgSize)) {
          bool APO = (OpIdx == 0) ? false : IsInverseOperation;
          OpsVec[OpIdx][Lane] = {Operands[OpIdx][Lane], APO, false};
        }
      }
    }

    /// \returns the number of operands.
    unsigned getNumOperands() const { return ArgSize; }

    /// \returns the number of lanes.
    unsigned getNumLanes() const { return OpsVec[0].size(); }

    /// \returns the operand value at \p OpIdx and \p Lane.
    Value *getValue(unsigned OpIdx, unsigned Lane) const {
      return getData(OpIdx, Lane).V;
    }

    /// \returns true if the data structure is empty.
    bool empty() const { return OpsVec.empty(); }

    /// Clears the data.
    void clear() { OpsVec.clear(); }

    /// \Returns true if there are enough operands identical to \p Op to fill
    /// the whole vector (it is mixed with constants or loop invariant values).
    /// Note: This modifies the 'IsUsed' flag, so a cleanUsed() must follow.
    bool shouldBroadcast(Value *Op, unsigned OpIdx, unsigned Lane) {
      assert(Op == getValue(OpIdx, Lane) &&
             "Op is expected to be getValue(OpIdx, Lane).");
      // Small number of loads - try load matching.
      if (isa<LoadInst>(Op) && getNumLanes() == 2 && getNumOperands() == 2)
        return false;
      bool OpAPO = getData(OpIdx, Lane).APO;
      bool IsInvariant = L && L->isLoopInvariant(Op);
      unsigned Cnt = 0;
      for (unsigned Ln = 0, Lns = getNumLanes(); Ln != Lns; ++Ln) {
        if (Ln == Lane)
          continue;
        // This is set to true if we found a candidate for broadcast at Lane.
        bool FoundCandidate = false;
        for (unsigned OpI = 0, OpE = getNumOperands(); OpI != OpE; ++OpI) {
          OperandData &Data = getData(OpI, Ln);
          if (Data.APO != OpAPO || Data.IsUsed)
            continue;
          Value *OpILane = getValue(OpI, Lane);
          bool IsConstantOp = isa<Constant>(OpILane);
          // Consider the broadcast candidate if:
          // 1. Same value is found in one of the operands.
          if (Data.V == Op ||
              // 2. The operand in the given lane is not constant but there is a
              // constant operand in another lane (which can be moved to the
              // given lane). In this case we can represent it as a simple
              // permutation of constant and broadcast.
              (!IsConstantOp &&
               ((Lns > 2 && isa<Constant>(Data.V)) ||
                // 2.1. If we have only 2 lanes, need to check that value in the
                // next lane does not build same opcode sequence.
                (Lns == 2 &&
                 !getSameOpcode({Op, getValue((OpI + 1) % OpE, Ln)}, TLI) &&
                 isa<Constant>(Data.V)))) ||
              // 3. The operand in the current lane is loop invariant (can be
              // hoisted out) and another operand is also a loop invariant
              // (though not a constant). In this case the whole vector can be
              // hoisted out.
              // FIXME: need to teach the cost model about this case for better
              // estimation.
              (IsInvariant && !isa<Constant>(Data.V) &&
               !getSameOpcode({Op, Data.V}, TLI) &&
               L->isLoopInvariant(Data.V))) {
            FoundCandidate = true;
            Data.IsUsed = Data.V == Op;
            if (Data.V == Op)
              ++Cnt;
            break;
          }
        }
        if (!FoundCandidate)
          return false;
      }
      return getNumLanes() == 2 || Cnt > 1;
    }

    /// Checks if there is at least single compatible operand in lanes other
    /// than \p Lane, compatible with the operand \p Op.
    bool canBeVectorized(Instruction *Op, unsigned OpIdx, unsigned Lane) const {
      assert(Op == getValue(OpIdx, Lane) &&
             "Op is expected to be getValue(OpIdx, Lane).");
      bool OpAPO = getData(OpIdx, Lane).APO;
      for (unsigned Ln = 0, Lns = getNumLanes(); Ln != Lns; ++Ln) {
        if (Ln == Lane)
          continue;
        if (any_of(seq<unsigned>(getNumOperands()), [&](unsigned OpI) {
              const OperandData &Data = getData(OpI, Ln);
              if (Data.APO != OpAPO || Data.IsUsed)
                return true;
              Value *OpILn = getValue(OpI, Ln);
              return (L && L->isLoopInvariant(OpILn)) ||
                     (getSameOpcode({Op, OpILn}, TLI) &&
                      allSameBlock({Op, OpILn}));
            }))
          return true;
      }
      return false;
    }

  public:
    /// Initialize with all the operands of the instruction vector \p RootVL.
    VLOperands(ArrayRef<Value *> RootVL, ArrayRef<ValueList> Operands,
               const InstructionsState &S, const BoUpSLP &R)
        : TLI(*R.TLI), DL(*R.DL), SE(*R.SE), R(R),
          L(R.LI->getLoopFor(S.getMainOp()->getParent())) {
      // Append all the operands of RootVL.
      appendOperands(RootVL, Operands, S);
    }

    /// Initialize with flattened operand columns of an associative node.
    /// ArgSize is taken from \p Operands, APO is always false.
    VLOperands(ArrayRef<ValueList> Operands, const BasicBlock *BB,
               const BoUpSLP &R)
        : TLI(*R.TLI), DL(*R.DL), SE(*R.SE), R(R), L(R.LI->getLoopFor(BB)) {
      assert(!Operands.empty() && "Expected at least one operand column");
      ArgSize = Operands.size();
      OpsVec.resize(ArgSize);
      unsigned NumLanes = Operands.front().size();
      for (auto [OpIdx, Ops] : enumerate(OpsVec)) {
        Ops.resize(NumLanes);
        for (unsigned Lane : seq<unsigned>(NumLanes))
          Ops[Lane] = OperandData(Operands[OpIdx][Lane], /*APO=*/false,
                                  /*IsUsed=*/false);
      }
    }

    /// \Returns a value vector with the operands across all lanes for the
    /// opearnd at \p OpIdx.
    ValueList getVL(unsigned OpIdx) const {
      ValueList OpVL(OpsVec[OpIdx].size());
      assert(OpsVec[OpIdx].size() == getNumLanes() &&
             "Expected same num of lanes across all operands");
      for (unsigned Lane = 0, Lanes = getNumLanes(); Lane != Lanes; ++Lane)
        OpVL[Lane] = OpsVec[OpIdx][Lane].V;
      return OpVL;
    }

    // Performs operand reordering for 2 or more operands.
    // The original operands are in OrigOps[OpIdx][Lane].
    // The reordered operands are returned in 'SortedOps[OpIdx][Lane]'.
    void reorder() {
      unsigned NumOperands = getNumOperands();
      unsigned NumLanes = getNumLanes();
      // Each operand has its own mode. We are using this mode to help us select
      // the instructions for each lane, so that they match best with the ones
      // we have selected so far.
      SmallVector<ReorderingMode, 2> ReorderingModes(NumOperands);

      // This is a greedy single-pass algorithm. We are going over each lane
      // once and deciding on the best order right away with no back-tracking.
      // However, in order to increase its effectiveness, we start with the lane
      // that has operands that can move the least. For example, given the
      // following lanes:
      //  Lane 0 : A[0] = B[0] + C[0]   // Visited 3rd
      //  Lane 1 : A[1] = C[1] - B[1]   // Visited 1st
      //  Lane 2 : A[2] = B[2] + C[2]   // Visited 2nd
      //  Lane 3 : A[3] = C[3] - B[3]   // Visited 4th
      // we will start at Lane 1, since the operands of the subtraction cannot
      // be reordered. Then we will visit the rest of the lanes in a circular
      // fashion. That is, Lanes 2, then Lane 0, and finally Lane 3.

      // Find the first lane that we will start our search from.
      unsigned FirstLane = getBestLaneToStartReordering();

      // Initialize the modes.
      for (unsigned OpIdx = 0; OpIdx != NumOperands; ++OpIdx) {
        Value *OpLane0 = getValue(OpIdx, FirstLane);
        // Keep track if we have instructions with all the same opcode on one
        // side.
        if (auto *OpILane0 = dyn_cast<Instruction>(OpLane0)) {
          // Check if OpLane0 should be broadcast.
          if (shouldBroadcast(OpLane0, OpIdx, FirstLane) ||
              !canBeVectorized(OpILane0, OpIdx, FirstLane))
            ReorderingModes[OpIdx] = ReorderingMode::Splat;
          else if (isa<LoadInst>(OpILane0))
            ReorderingModes[OpIdx] = ReorderingMode::Load;
          else
            ReorderingModes[OpIdx] = ReorderingMode::Opcode;
        } else if (isa<Constant>(OpLane0)) {
          ReorderingModes[OpIdx] = ReorderingMode::Constant;
        } else if (isa<Argument>(OpLane0)) {
          // Our best hope is a Splat. It may save some cost in some cases.
          ReorderingModes[OpIdx] = ReorderingMode::Splat;
        } else {
          llvm_unreachable("Unexpected value kind.");
        }
      }

      // Check that we don't have same operands. No need to reorder if operands
      // are just perfect diamond or shuffled diamond match. Do not do it only
      // for possible broadcasts.
      auto &&SkipReordering = [this]() {
        SmallPtrSet<Value *, 4> UniqueValues;
        ArrayRef<OperandData> Op0 = OpsVec.front();
        for (const OperandData &Data : Op0)
          UniqueValues.insert(Data.V);
        for (ArrayRef<OperandData> Op :
             ArrayRef(OpsVec).slice(1, getNumOperands() - 1)) {
          if (any_of(Op, [&UniqueValues](const OperandData &Data) {
                return !UniqueValues.contains(Data.V);
              }))
            return false;
        }
        return UniqueValues.size() != 2;
      };

      // If the initial strategy fails for any of the operand indexes, then we
      // perform reordering again in a second pass. This helps avoid assigning
      // high priority to the failed strategy, and should improve reordering for
      // the non-failed operand indexes.
      for (int Pass = 0; Pass != 2; ++Pass) {
        // Check if no need to reorder operands since they're are perfect or
        // shuffled diamond match.
        // Need to do it to avoid extra external use cost counting for
        // shuffled matches, which may cause regressions.
        if (SkipReordering())
          break;
        // Skip the second pass if the first pass did not fail.
        bool StrategyFailed = false;
        // Mark all operand data as free to use.
        clearUsed();
        // We keep the original operand order for the FirstLane, so reorder the
        // rest of the lanes. We are visiting the nodes in a circular fashion,
        // using FirstLane as the center point and increasing the radius
        // distance.
        SmallVector<SmallVector<Value *, 2>> MainAltOps(NumOperands);
        for (unsigned I = 0; I < NumOperands; ++I)
          MainAltOps[I].push_back(getData(I, FirstLane).V);

        SmallBitVector UsedLanes(NumLanes);
        UsedLanes.set(FirstLane);
        for (unsigned Distance = 1; Distance != NumLanes; ++Distance) {
          // Visit the lane on the right and then the lane on the left.
          for (int Direction : {+1, -1}) {
            int Lane = FirstLane + Direction * Distance;
            if (Lane < 0 || Lane >= (int)NumLanes)
              continue;
            UsedLanes.set(Lane);
            int LastLane = Lane - Direction;
            assert(LastLane >= 0 && LastLane < (int)NumLanes &&
                   "Out of bounds");
            // Look for a good match for each operand.
            for (unsigned OpIdx = 0; OpIdx != NumOperands; ++OpIdx) {
              // Search for the operand that matches SortedOps[OpIdx][Lane-1].
              std::optional<unsigned> BestIdx =
                  getBestOperand(OpIdx, Lane, LastLane, ReorderingModes,
                                 MainAltOps[OpIdx], UsedLanes);
              // By not selecting a value, we allow the operands that follow to
              // select a better matching value. We will get a non-null value in
              // the next run of getBestOperand().
              if (BestIdx) {
                // Swap the current operand with the one returned by
                // getBestOperand().
                swap(OpIdx, *BestIdx, Lane);
              } else {
                // Enable the second pass.
                StrategyFailed = true;
              }
              // Try to get the alternate opcode and follow it during analysis.
              if (MainAltOps[OpIdx].size() != 2) {
                OperandData &AltOp = getData(OpIdx, Lane);
                InstructionsState OpS =
                    getSameOpcode({MainAltOps[OpIdx].front(), AltOp.V}, TLI);
                if (OpS && OpS.isAltShuffle())
                  MainAltOps[OpIdx].push_back(AltOp.V);
              }
            }
          }
        }
        // Skip second pass if the strategy did not fail.
        if (!StrategyFailed)
          break;
      }
    }

#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
    LLVM_DUMP_METHOD static StringRef getModeStr(ReorderingMode RMode) {
      switch (RMode) {
      case ReorderingMode::Load:
        return "Load";
      case ReorderingMode::Opcode:
        return "Opcode";
      case ReorderingMode::Constant:
        return "Constant";
      case ReorderingMode::Splat:
        return "Splat";
      case ReorderingMode::Failed:
        return "Failed";
      }
      llvm_unreachable("Unimplemented Reordering Type");
    }

    LLVM_DUMP_METHOD static raw_ostream &printMode(ReorderingMode RMode,
                                                   raw_ostream &OS) {
      return OS << getModeStr(RMode);
    }

    /// Debug print.
    LLVM_DUMP_METHOD static void dumpMode(ReorderingMode RMode) {
      printMode(RMode, dbgs());
    }

    friend raw_ostream &operator<<(raw_ostream &OS, ReorderingMode RMode) {
      return printMode(RMode, OS);
    }

    LLVM_DUMP_METHOD raw_ostream &print(raw_ostream &OS) const {
      const unsigned Indent = 2;
      unsigned Cnt = 0;
      for (const OperandDataVec &OpDataVec : OpsVec) {
        OS << "Operand " << Cnt++ << "\n";
        for (const OperandData &OpData : OpDataVec) {
          OS.indent(Indent) << "{";
          if (Value *V = OpData.V)
            OS << *V;
          else
            OS << "null";
          OS << ", APO:" << OpData.APO << "}\n";
        }
        OS << "\n";
      }
      return OS;
    }

    /// Debug print.
    LLVM_DUMP_METHOD void dump() const { print(dbgs()); }
#endif
  };

  /// Evaluate each pair in \p Candidates and return index into \p Candidates
  /// for a pair which have highest score deemed to have best chance to form
  /// root of profitable tree to vectorize. Return std::nullopt if no candidate
  /// scored above the LookAheadHeuristics::ScoreFail. \param Limit Lower limit
  /// of the cost, considered to be good enough score.
  std::pair<std::optional<int>, int>
  findBestRootPair(ArrayRef<std::pair<Value *, Value *>> Candidates,
                   int Limit = LookAheadHeuristics::ScoreFail) const {
    LookAheadHeuristics LookAhead(*TLI, *DL, *SE, *this, /*NumLanes=*/2,
                                  Opts.slp_max_root_look_ahead_depth);
    int BestScore = Limit;
    std::optional<int> Index;
    for (int I : seq<int>(0, Candidates.size())) {
      int Score = LookAhead.getScoreAtLevelRec(Candidates[I].first,
                                               Candidates[I].second,
                                               /*U1=*/nullptr, /*U2=*/nullptr,
                                               /*CurrLevel=*/1, {});
      if (Score > BestScore) {
        BestScore = Score;
        Index = I;
      }
    }
    return std::make_pair(Index, BestScore);
  }

  /// Checks if the instruction is marked for deletion.
  bool isDeleted(Instruction *I) const { return DeletedInstructions.count(I); }

  /// Cached llvm::getPointersDiff(), see SLPAnalysisCache.
  std::optional<int64_t>
  getPointersDiff(Type *ElemTyA, Value *PtrA, Type *ElemTyB, Value *PtrB,
                  const DataLayout &DL, ScalarEvolution &SE,
                  bool StrictCheck = false, bool CheckType = true) const {
    return Cache.getPointersDiff(ElemTyA, PtrA, ElemTyB, PtrB, DL, SE,
                                 StrictCheck, CheckType);
  }

  /// Returns the cached analyses results, shared by all the trees built for
  /// the function.
  SLPAnalysisCache &getAnalysisCache() const { return Cache; }

  /// Checks if the value is used only by the assume-like intrinsics.
  bool isEphemeralValue(const Value *V) const { return EphValues.contains(V); }

  /// Removes an instruction from its block and eventually deletes it.
  /// It's like Instruction::eraseFromParent() except that the actual deletion
  /// is delayed until BoUpSLP is destructed.
  void eraseInstruction(Instruction *I) {
    DeletedInstructions.insert(I);
  }

  /// Remove instructions from the parent function and clear the operands of \p
  /// DeadVals instructions, marking for deletion trivially dead operands.
  template <typename T>
  void removeInstructionsAndOperands(
      ArrayRef<T *> DeadVals,
      ArrayRef<ReductionVectorPart> VectorValuesAndScales) {
    SmallVector<WeakTrackingVH> DeadInsts;
    for (T *V : DeadVals) {
      auto *I = cast<Instruction>(V);
      eraseInstruction(I);
    }
    DenseSet<Value *> Processed;
    for (T *V : DeadVals) {
      if (!V || !Processed.insert(V).second)
        continue;
      auto *I = cast<Instruction>(V);
      salvageDebugInfo(*I);
      ArrayRef<TreeEntry *> Entries = getTreeEntries(I);
      for (Use &U : I->operands()) {
        if (auto *OpI = dyn_cast<Instruction>(U.get());
            OpI && !DeletedInstructions.contains(OpI) && OpI->hasOneUser() &&
            wouldInstructionBeTriviallyDead(OpI, TLI) &&
            !ExternalUseReplacements.contains(OpI) &&
            (Entries.empty() || none_of(Entries, [&](const TreeEntry *Entry) {
               return Entry->VectorizedValue == OpI;
             })))
          DeadInsts.push_back(OpI);
      }
      I->dropAllReferences();
    }
    for (T *V : DeadVals) {
      auto *I = cast<Instruction>(V);
      if (!I->getParent())
        continue;
      assert((I->use_empty() || all_of(I->uses(),
                                       [&](Use &U) {
                                         return isDeleted(
                                             cast<Instruction>(U.getUser()));
                                       })) &&
             "trying to erase instruction with users.");
      I->removeFromParent();
      SE->forgetValue(I);
    }
    // Process the dead instruction list until empty.
    while (!DeadInsts.empty()) {
      Value *V = DeadInsts.pop_back_val();
      Instruction *VI = cast<Instruction>(V);
      if (!VI || !VI->getParent())
        continue;
      assert(isInstructionTriviallyDead(VI, TLI) &&
             "Live instruction found in dead worklist!");
      assert(VI->use_empty() && "Instructions with uses are not dead.");

      // Don't lose the debug info while deleting the instructions.
      salvageDebugInfo(*VI);

      // Null out all of the instruction's operands to see if any operand
      // becomes dead as we go.
      for (Use &OpU : VI->operands()) {
        Value *OpV = OpU.get();
        if (!OpV)
          continue;
        OpU.set(nullptr);

        if (!OpV->use_empty())
          continue;

        // If the operand is an instruction that became dead as we nulled out
        // the operand, and if it is 'trivially' dead, delete it in a future
        // loop iteration.
        if (auto *OpI = dyn_cast<Instruction>(OpV))
          if (!DeletedInstructions.contains(OpI) &&
              !ExternalUseReplacements.contains(OpI) &&
              (!OpI->getType()->isVectorTy() ||
               none_of(VectorValuesAndScales,
                       [&](const ReductionVectorPart &V) {
                         return V.Vec == OpI;
                       })) &&
              isInstructionTriviallyDead(OpI, TLI))
            DeadInsts.push_back(OpI);
      }

      VI->removeFromParent();
      eraseInstruction(VI);
      SE->forgetValue(VI);
    }
  }

  /// Checks if the instruction was already analyzed for being possible
  /// reduction root.
  bool isAnalyzedReductionRoot(Instruction *I) const {
    return AnalyzedReductionsRoots.count(I);
  }
  /// Register given instruction as already analyzed for being possible
  /// reduction root.
  void analyzedReductionRoot(Instruction *I) {
    AnalyzedReductionsRoots.insert(I);
  }
  /// Checks if the provided list of reduced values was checked already for
  /// vectorization.
  bool areAnalyzedReductionVals(ArrayRef<Value *> VL) const {
    return AnalyzedReductionVals.contains(hash_value(VL));
  }
  /// Adds the list of reduced values to list of already checked values for the
  /// vectorization.
  void analyzedReductionVals(ArrayRef<Value *> VL) {
    AnalyzedReductionVals.insert(hash_value(VL));
  }
  /// Checks if the value was already a part of the analyzed vector node.
  bool isAnalyzedScalar(const Value *V) const {
    return AnalyzedScalars.contains(V);
  }
  /// Checks if the given bundle was already rejected as non-vectorizable.
  bool isAnalyzedBundle(ArrayRef<Value *> VL) const {
    return AnalyzedBundles.contains(hash_value(VL));
  }
  /// Registers the bundle as rejected for the vectorization.
  void analyzedBundle(ArrayRef<Value *> VL) {
    AnalyzedBundles.insert(hash_value(VL));
  }
  /// Clear the list of the analyzed reduction root instructions.
  void clearReductionData() {
    AnalyzedReductionsRoots.clear();
    AnalyzedReductionVals.clear();
    AnalyzedBundles.clear();
    AnalyzedMinBWVals.clear();
  }
  /// Checks if the given value is gathered in one of the nodes.
  bool isAnyGathered(const SmallDenseSet<Value *> &Vals) const {
    return any_of(MustGather, [&](Value *V) { return Vals.contains(V); });
  }
  /// Checks if the given value is gathered in one of the nodes.
  bool isGathered(const Value *V) const {
    return MustGather.contains(V);
  }
  /// Checks if the specified value was not schedule.
  bool isNotScheduled(const Value *V) const {
    return NonScheduledFirst.contains(V);
  }

  /// Check if \p V is a peeled reassociated scalar still owned by a live
  /// (non-deleted, non-gathered) tree entry.
  bool isReassocScalarVectorized(const Value *V) const {
    auto It = ReassocScalarToTreeEntries.find(V);
    return It != ReassocScalarToTreeEntries.end() &&
           any_of(It->second, [&](const TreeEntry *E) {
             return !DeletedNodes.contains(E) &&
                    !TransformedToGatherNodes.contains(E);
           });
  }

  /// Check if the value is vectorized in the tree.
  bool isVectorized(const Value *V) const {
    assert(V && "V cannot be nullptr.");
    if (isReassocScalarVectorized(V))
      return true;
    return any_of(getTreeEntries(V), [&](const TreeEntry *E) {
      return !DeletedNodes.contains(E) && !TransformedToGatherNodes.contains(E);
    });
  }

  /// Returns true if the role of \p I is already decided by its user: a deleted
  /// user was folded into some other vector by an earlier attempt.
  bool hasResolvedUser(Instruction *I) const {
    return any_of(I->users(), [&](User *U) {
      auto *UI = dyn_cast<Instruction>(U);
      return UI && isDeleted(UI);
    });
  }

  /// Checks if it is legal and profitable to build SplitVectorize node for the
  /// given \p VL.
  /// \param Op1 first homogeneous scalars.
  /// \param Op2 second homogeneous scalars.
  /// \param ReorderIndices indices to reorder the scalars.
  /// \returns true if the node was successfully built.
  bool canBuildSplitNode(ArrayRef<Value *> VL,
                         const InstructionsState &LocalState,
                         SmallVectorImpl<Value *> &Op1,
                         SmallVectorImpl<Value *> &Op2,
                         OrdersType &ReorderIndices) const;

  /// \returns Cast context for the given graph node.
  TargetTransformInfo::CastContextHint
  getCastContextHint(const TreeEntry &TE) const;

  ~BoUpSLP();

private:
  /// Determine if a node \p E in can be demoted to a smaller type with a
  /// truncation. We collect the entries that will be demoted in ToDemote.
  /// \param E Node for analysis
  /// \param ToDemote indices of the nodes to be demoted.
  bool collectValuesToDemote(
      const TreeEntry &E, bool IsProfitableToDemoteRoot, unsigned &BitWidth,
      SmallVectorImpl<unsigned> &ToDemote, DenseSet<const TreeEntry *> &Visited,
      const SmallDenseSet<unsigned, 8> &NodesToKeepBWs, unsigned &MaxDepthLevel,
      bool &IsProfitableToDemote, bool IsTruncRoot) const;

  /// Builds the list of reorderable operands on the edges \p Edges of the \p
  /// UserTE, which allow reordering (i.e. the operands can be reordered because
  /// they have only one user and reordarable).
  /// \param ReorderableGathers List of all gather nodes that require reordering
  /// (e.g., gather of extractlements or partially vectorizable loads).
  /// \param GatherOps List of gather operand nodes for \p UserTE that require
  /// reordering, subset of \p NonVectorized.
  void buildReorderableOperands(
      TreeEntry *UserTE,
      SmallVectorImpl<std::pair<unsigned, TreeEntry *>> &Edges,
      const SmallPtrSetImpl<const TreeEntry *> &ReorderableGathers,
      SmallVectorImpl<TreeEntry *> &GatherOps);

  /// Checks if the given \p TE is a gather node with clustered reused scalars
  /// and reorders it per given \p Mask.
  void reorderNodeWithReuses(TreeEntry &TE, ArrayRef<int> Mask) const;

  /// Checks if all users of \p I are the part of the vectorization tree.
  bool areAllUsersVectorized(
      Instruction *I,
      const SmallDenseSet<Value *> *VectorizedVals = nullptr) const;

  /// Estimates the number of scalar instructions in the tree, each weighted by
  /// its loop-nest trip count (nest-invariant entries are dropped when
  /// \p TreeLoop is non-null).
  uint64_t getNumScalarInsts(bool HasTreeLoop);

  /// Estimates the number of vector instructions (including buildvectors,
  /// shuffles, and, if \p CountExtracts is set, extracts) the tree produces,
  /// weighted like getNumScalarInsts().
  uint64_t getNumVectorInsts(bool HasTreeLoop, bool CountExtracts = true);

  /// Returns true if the instruction-count veto is skipped for a tree costed at
  /// \p TreeCost because it contains a poor-throughput operation whose real
  /// vector savings the count check does not model.
  bool bypassesInstCountCheck(InstructionCost TreeCost) const;

  /// Collects into \p UserOps the user operations of the gathers of the scalars
  /// of \p E, for TTI::getBuildVectorContextHint(). Returns false if no user is
  /// found or some user cannot be described.
  bool
  collectGatherUserOps(const TreeEntry &E,
                       SmallVectorImpl<TTI::BuildVectorUseOp> &UserOps) const;

  /// \returns the fadd/fsub user of the single-use fmul \p I, which the
  /// backend fuses with \p I into an fmuladd in the scalar code, and the cost
  /// of that fmuladd, or {nullptr, invalid cost}. If \p InTree is set, the
  /// users, whose fusion is accounted for by the tree, are not returned.
  std::pair<Instruction *, InstructionCost>
  getFMulFusingUser(Instruction *I, bool InTree = true) const;

  /// \returns true if the fadd/fsub \p U, fused with its fmul operand by the
  /// backend, is a vectorized tree scalar whose lane is priced as fmuladd.
  /// Peeled reassociated scalars are priced as plain fadd/fsub.
  bool isFusedVectorizedFAddSub(Instruction *U) const;

  /// \returns the scalar cost of the fmul lanes of \p TE that are priced as
  /// fused into their vectorized fadd/fsub users. If the node is turned into a
  /// gather, these fmuls stay scalar and lose the fusion, so the gather
  /// alternative must pay their full price.
  InstructionCost getUnfusedFMulsPenalty(const TreeEntry &TE) const;

  /// \returns the graph entry for the \p Idx operand of the \p E entry.
  const TreeEntry *getOperandEntry(const TreeEntry *E, unsigned Idx) const;
  TreeEntry *getOperandEntry(TreeEntry *E, unsigned Idx) {
    return const_cast<TreeEntry *>(
        getOperandEntry(const_cast<const TreeEntry *>(E), Idx));
  }

  /// Gets the root instruction for the given node. If the node is a strided
  /// load/store node with the reverse order, the root instruction is the last
  /// one.
  Instruction *getRootEntryInstruction(const TreeEntry &Entry) const;

  /// \returns the scale of the given tree entry to the loop iteration.
  /// \p Scalar is the scalar value from the entry, if using the parent for the
  /// external use.
  /// \p U is the user of the vectorized value from the entry, if using the
  /// parent for the external use.
  uint64_t getScaleToLoopIterations(const TreeEntry &TE,
                                    Value *Scalar = nullptr,
                                    Instruction *U = nullptr);

  /// \returns the product of trip counts of the loop \p L and all of its
  /// enclosing loops. Unlike the state kept by getScaleToLoopIterations(),
  /// this helper depends only on the loop structure and is independent of
  /// per-entry operand invariance. Returns 1 when loop-aware cost modeling
  /// is disabled or \p L is null.
  uint64_t getLoopNestScale(const Loop *L);

  /// \returns a refined execution scale for a gather/buildvector tree entry
  /// \p TE. The scale is computed as the average of per-lane execution
  /// scales: each lane's scale is the loop-nest scale of the loop that
  /// contains the lane's defining instruction (or 1 if the lane is a
  /// constant / loop-invariant non-instruction value). This models the
  /// LICM hoisting that optimizeGatherSequence() performs after vectorization
  /// for inserts with loop-invariant operands. Falls back to the whole-entry
  /// scale when per-lane information is unavailable or the feature is off.
  uint64_t getGatherNodeEffectiveScale(const TreeEntry &TE,
                                       Instruction *U = nullptr);

  /// \returns the loop-nest execution scale of \p TE.
  uint64_t getEntryEffectiveScale(const TreeEntry &TE,
                                  Instruction *U = nullptr);

  /// Get the loop nest for the given loop \p L.
  ArrayRef<const Loop *> getLoopNest(const Loop *L);

  /// \returns the cost of the vectorizable entry.
  InstructionCost getEntryCost(const TreeEntry *E,
                               ArrayRef<Value *> VectorizedVals,
                               SmallPtrSetImpl<Value *> &CheckedExtracts);

  /// Estimates spill/reload cost from vector register pressure for \p E at the
  /// point of emitting its vector result type \p FinalVecTy. \p ScalarTy is the
  /// scalar/slot type used to widen into \p VecTy/\p FinalVecTy and may itself
  /// be a FixedVectorType in ReVec mode or an adjusted type due to MinBWs.
  InstructionCost
  getVectorSpillReloadCost(const TreeEntry *E, Type *ScalarTy, Type *VecTy,
                           Type *FinalVecTy,
                           const TTI::TargetCostKind CostKind) const;

  /// This is the recursive part of buildTree.
  void buildTreeRec(ArrayRef<Value *> Roots, unsigned Depth, const EdgeInfo &EI,
                    unsigned InterleaveFactor = 0);

  /// \returns true if the ExtractElement/ExtractValue instructions in \p VL can
  /// be vectorized to use the original vector (or aggregate "bitcast" to a
  /// vector) and sets \p CurrentOrder to the identity permutation; otherwise
  /// returns false, setting \p CurrentOrder to either an empty vector or a
  /// non-identity permutation that allows to reuse extract instructions.
  /// \param ResizeAllowed indicates whether it is allowed to handle subvector
  /// extract order.
  bool canReuseExtract(ArrayRef<Value *> VL,
                       SmallVectorImpl<unsigned> &CurrentOrder,
                       bool ResizeAllowed = false) const;

  /// Vectorize a single entry in the tree.
  Value *vectorizeTree(TreeEntry *E);

  /// Vectorize a single entry in the tree, the \p Idx-th operand of the entry
  /// \p E.
  Value *vectorizeOperand(TreeEntry *E, unsigned NodeIdx);

  /// Create a new vector from a list of scalar values.  Produces a sequence
  /// which exploits values reused across lanes, and arranges the inserts
  /// for ease of later optimization.
  template <typename BVTy, typename ResTy, typename... Args>
  ResTy processBuildVector(const TreeEntry *E, Type *ScalarTy, Args &...Params);

  /// Handles the gather of zero-extended sub-fields of the same wider integer
  /// scalar, emitted as a bitcast to the field vector plus a permutation and
  /// an extension to the lane type, if the gathered values match.
  template <typename ResTy, typename BVTy>
  std::optional<ResTy> processExtractedFieldsGather(
      BVTy &ShuffleBuilder, const TreeEntry *E, Type *ScalarTy,
      ArrayRef<Value *> VL,
      ArrayRef<std::pair<const TreeEntry *, unsigned>> SubVectors);

  /// Create a new vector from a list of scalar values.  Produces a sequence
  /// which exploits values reused across lanes, and arranges the inserts
  /// for ease of later optimization.
  Value *createBuildVector(const TreeEntry *E, Type *ScalarTy);

  /// Returns the instruction in the bundle, which can be used as a base point
  /// for scheduling. Usually it is the last instruction in the bundle, except
  /// for the case when all operands are external (in this case, it is the first
  /// instruction in the list).
  Instruction &getLastInstructionInBundle(const TreeEntry *E);

  /// Tries to find extractelement instructions with constant indices from fixed
  /// vector type and gather such instructions into a bunch, which highly likely
  /// might be detected as a shuffle of 1 or 2 input vectors. If this attempt
  /// was successful, the matched scalars are replaced by poison values in \p VL
  /// for future analysis.
  std::optional<TargetTransformInfo::ShuffleKind>
  tryToGatherSingleRegisterExtractElements(MutableArrayRef<Value *> VL,
                                           SmallVectorImpl<int> &Mask) const;

  /// Tries to find extractelement instructions with constant indices from fixed
  /// vector type and gather such instructions into a bunch, which highly likely
  /// might be detected as a shuffle of 1 or 2 input vectors. If this attempt
  /// was successful, the matched scalars are replaced by poison values in \p VL
  /// for future analysis.
  SmallVector<std::optional<TargetTransformInfo::ShuffleKind>>
  tryToGatherExtractElements(SmallVectorImpl<Value *> &VL,
                             SmallVectorImpl<int> &Mask,
                             unsigned NumParts) const;

  /// Checks if the gathered \p VL can be represented as a single register
  /// shuffle(s) of previous tree entries.
  /// \param TE Tree entry checked for permutation.
  /// \param VL List of scalars (a subset of the TE scalar), checked for
  /// permutations. Must form single-register vector.
  /// \param ForOrder Tries to fetch the best candidates for ordering info. Also
  /// commands to build the mask using the original vector value, without
  /// relying on the potential reordering.
  /// \returns ShuffleKind, if gathered values can be represented as shuffles of
  /// previous tree entries. \p Part of \p Mask is filled with the shuffle mask.
  std::optional<TargetTransformInfo::ShuffleKind>
  isGatherShuffledSingleRegisterEntry(
      const TreeEntry *TE, ArrayRef<Value *> VL, MutableArrayRef<int> Mask,
      SmallVectorImpl<const TreeEntry *> &Entries, unsigned Part, bool ForOrder,
      unsigned SliceSize);

  /// Checks if the gathered \p VL can be represented as multi-register
  /// shuffle(s) of previous tree entries.
  /// \param TE Tree entry checked for permutation.
  /// \param VL List of scalars (a subset of the TE scalar), checked for
  /// permutations.
  /// \param ForOrder Tries to fetch the best candidates for ordering info. Also
  /// commands to build the mask using the original vector value, without
  /// relying on the potential reordering.
  /// \returns per-register series of ShuffleKind, if gathered values can be
  /// represented as shuffles of previous tree entries. \p Mask is filled with
  /// the shuffle mask (also on per-register base).
  SmallVector<std::optional<TargetTransformInfo::ShuffleKind>>
  isGatherShuffledEntry(
      const TreeEntry *TE, ArrayRef<Value *> VL, SmallVectorImpl<int> &Mask,
      SmallVectorImpl<SmallVector<const TreeEntry *>> &Entries,
      unsigned NumParts, Type *ScalarTy, bool ForOrder = false);

  /// \returns the cost of gathering (inserting) the values in \p VL into a
  /// vector.
  /// \param ForPoisonSrc true if initial vector is poison, false otherwise.
  InstructionCost getGatherCost(ArrayRef<Value *> VL, bool ForPoisonSrc,
                                Type *ScalarTy) const;

  /// Set the Builder insert point to one after the last instruction in
  /// the bundle
  void setInsertPointAfterBundle(const TreeEntry *E);

  /// \returns a vector from a collection of scalars in \p VL. if \p Root is not
  /// specified, the starting vector value is poison.
  Value *
  gather(ArrayRef<Value *> VL, Value *Root, Type *ScalarTy,
         function_ref<Value *(Value *, Value *, ArrayRef<int>)> CreateShuffle);

  /// \returns whether the VectorizableTree is fully vectorizable and will
  /// be beneficial even the tree height is tiny.
  bool isFullyVectorizableTinyTree(bool ForReduction) const;

  /// Run through the list of all gathered loads in the graph and try to find
  /// vector loads/masked gathers instead of regular gathers. Later these loads
  /// are reshufled to build final gathered nodes.
  void tryToVectorizeGatheredLoads(
      const SmallMapVector<
          std::tuple<BasicBlock *, Value *, Type *>,
          SmallVector<SmallVector<std::pair<LoadInst *, int64_t>>>, 8>
          &GatheredLoads);

  /// Run through the gather nodes that are splats of the same instruction and
  /// try to vectorize the unique splatted values together as a separate
  /// subtree. The splat gathers are then emitted as broadcasts of the
  /// vectorized subtree instead of insertion sequences.
  void tryToVectorizeSplatGatheredScalars();

  /// Helper for `findExternalStoreUsersReorderIndices()`. It iterates over the
  /// users of \p TE and collects the stores. It returns the map from the store
  /// pointers to the collected stores.
  SmallVector<SmallVector<StoreInst *>>
  collectUserStores(const BoUpSLP::TreeEntry *TE) const;

  /// Helper for `findExternalStoreUsersReorderIndices()`. It checks if the
  /// stores in \p StoresVec can form a vector instruction. If so it returns
  /// true and populates \p ReorderIndices with the shuffle indices of the
  /// stores when compared to the sorted vector.
  bool canFormVector(ArrayRef<StoreInst *> StoresVec,
                     OrdersType &ReorderIndices) const;

  /// Iterates through the users of \p TE, looking for scalar stores that can be
  /// potentially vectorized in a future SLP-tree. If found, it keeps track of
  /// their order and builds an order index vector for each store bundle. It
  /// returns all these order vectors found.
  /// We run this after the tree has formed, otherwise we may come across user
  /// instructions that are not yet in the tree.
  SmallVector<OrdersType, 1>
  findExternalStoreUsersReorderIndices(TreeEntry *TE) const;

  /// Tries to reorder the gathering node for better vectorization
  /// opportunities.
  void reorderGatherNode(TreeEntry &TE);

  /// Checks if the tree represents disjoint or reduction of shl(zext, (0, 8,
  /// .., 56))-like pattern.
  /// If the int shifts unique, also strided, but not ordered, sets \p Order.
  /// If the node can be represented as a bitcast + bswap, sets \p IsBSwap.
  /// If the root nodes are loads, sets \p ForLoads to true.
  bool matchesShlZExt(const TreeEntry &TE, OrdersType &Order, bool &IsBSwap,
                      bool &ForLoads) const;

  /// Computes the packing layout of an or reduction of masked shifted values
  /// packing per-lane byte fields of the scalar result (and(shl(x, s), m) per
  /// lane). The field analysis proves the disjointness of the fields, so the
  /// reduction operations are not required to be marked disjoint.
  std::optional<BitPackInfo> computeBitPackLayout(const TreeEntry &TE) const;

  /// Returns the node packed for the shl operand \p LhsTE of a bitpack root.
  /// If \p LhsTE is a (zext of) and(lshr/shl(x, C), mask) chain extracting
  /// the same bits of every lane of x, returns the node of x and sets the
  /// shift amounts of \p Info to the field offset in the lanes of x.
  /// Otherwise, returns \p LhsTE.
  const TreeEntry *getBitPackSource(const TreeEntry &LhsTE,
                                    BitPackInfo &Info) const;

  /// Checks if the tree entry is the root of such a reduction, the tree nodes
  /// are in the expected state and it is profitable to model as a bit pack.
  bool matchesBitPack(const TreeEntry &TE) const;

  /// If the node's lanes are a plain zext, returns the source bit width:
  /// compacting the vectorized lanes back to it is free. Copyable lanes force
  /// a blend after the extend, so the vectorized value is not a plain zext.
  unsigned getZExtSrcWidth(const TreeEntry &TE) const;

  /// Checks if the \p SelectTE matches zext+selects, which can be inversed for
  /// better codegen in case like zext (icmp ne), select (icmp eq), ....
  bool matchesInversedZExtSelect(
      const TreeEntry &SelectTE,
      SmallVectorImpl<unsigned> &InversedCmpsIndices) const;

  /// Checks if the tree is reduction or of bit selects, like select %cmp, <1,
  /// 2, 4, 8, ..>, zeroinitializer, which can be reduced just to a bitcast %cmp
  /// to in.
  bool matchesSelectOfBits(const TreeEntry &SelectTE) const;

  class TreeEntry {
  public:
    using VecTreeTy = SmallVector<std::unique_ptr<TreeEntry>, 8>;
    TreeEntry(VecTreeTy &Container) : Container(Container) {}

    /// \returns Common mask for reorder indices and reused scalars.
    SmallVector<int> getCommonMask() const {
      if (State == TreeEntry::SplitVectorize)
        return {};
      SmallVector<int> Mask;
      inversePermutation(ReorderIndices, Mask);
      addMask(Mask, ReuseShuffleIndices);
      return Mask;
    }

    /// \returns The mask for split nodes.
    SmallVector<int> getSplitMask() const {
      assert(State == TreeEntry::SplitVectorize && !ReorderIndices.empty() &&
             "Expected only split vectorize node.");
      unsigned CommonVF = std::max<unsigned>(
          CombinedEntriesWithIndices.back().second,
          Scalars.size() - CombinedEntriesWithIndices.back().second);
      const unsigned Scale = getNumElements(Scalars.front()->getType());
      CommonVF *= Scale;
      SmallVector<int> Mask(getVectorFactor() * Scale, PoisonMaskElem);
      for (auto [Idx, I] : enumerate(ReorderIndices)) {
        for (unsigned K : seq<unsigned>(Scale)) {
          Mask[Scale * I + K] =
              Scale * Idx + K +
              (Idx >= CombinedEntriesWithIndices.back().second
                   ? CommonVF - CombinedEntriesWithIndices.back().second * Scale
                   : 0);
        }
      }
      return Mask;
    }

    /// Updates (reorders) SplitVectorize node according to the given mask \p
    /// Mask and order \p MaskOrder.
    void reorderSplitNode(unsigned Idx, ArrayRef<int> Mask,
                          ArrayRef<int> MaskOrder);

    /// \returns true if the scalars in VL are equal to this entry.
    bool isSame(ArrayRef<Value *> VL) const {
      auto &&IsSame = [VL](ArrayRef<Value *> Scalars, ArrayRef<int> Mask) {
        if (Mask.size() != VL.size() && VL.size() == Scalars.size())
          return std::equal(VL.begin(), VL.end(), Scalars.begin());
        return VL.size() == Mask.size() &&
               std::equal(VL.begin(), VL.end(), Mask.begin(),
                          [Scalars](Value *V, int Idx) {
                            return isa<PoisonValue>(V) ||
                                   (Idx != PoisonMaskElem && V == Scalars[Idx]);
                          });
      };
      if (!ReorderIndices.empty()) {
        // TODO: implement matching if the nodes are just reordered, still can
        // treat the vector as the same if the list of scalars matches VL
        // directly, without reordering.
        SmallVector<int> Mask;
        inversePermutation(ReorderIndices, Mask);
        if (VL.size() == Scalars.size())
          return IsSame(Scalars, Mask);
        if (VL.size() == ReuseShuffleIndices.size()) {
          addMask(Mask, ReuseShuffleIndices);
          return IsSame(Scalars, Mask);
        }
        return false;
      }
      return IsSame(Scalars, ReuseShuffleIndices);
    }

    /// \returns true if current entry has same operands as \p TE.
    bool hasEqualOperands(const TreeEntry &TE) const {
      if (TE.getNumOperands() != getNumOperands())
        return false;
      SmallBitVector Used(getNumOperands());
      for (unsigned I = 0, E = getNumOperands(); I < E; ++I) {
        unsigned PrevCount = Used.count();
        for (unsigned K = 0; K < E; ++K) {
          if (Used.test(K))
            continue;
          if (getOperand(K) == TE.getOperand(I)) {
            Used.set(K);
            break;
          }
        }
        // Check if we actually found the matching operand.
        if (PrevCount == Used.count())
          return false;
      }
      return true;
    }

    /// \return Final vectorization factor for the node. Defined by the total
    /// number of vectorized scalars, including those, used several times in the
    /// entry and counted in the \a ReuseShuffleIndices, if any.
    unsigned getVectorFactor() const {
      if (!ReuseShuffleIndices.empty())
        return ReuseShuffleIndices.size();
      return Scalars.size();
    };

    /// Checks if the current node is a gather node.
    bool isGather() const { return State == NeedToGather; }

    /// Checks if the current node is in reverse order.
    bool isReverse() const {
      return !ReorderIndices.empty() && isReverseOrder(ReorderIndices);
    }

    /// A vector of scalars.
    ValueList Scalars;

    /// The Scalars are vectorized into this value. It is initialized to Null.
    WeakTrackingVH VectorizedValue = nullptr;

    /// Do we need to gather this sequence or vectorize it
    /// (either with vector instruction or with scatter/gather
    /// intrinsics for store/load)?
    enum EntryState {
      Vectorize,            ///< The node is regularly vectorized.
      ScatterVectorize,     ///< Masked scatter/gather node.
      StridedVectorize,     ///< Strided loads (and stores)
      ExpandVectorize,      ///< Masked stores, the values are expanded into
                            ///< a wider vector and vectorized with a mask.
      CompressVectorize,    ///< (Masked) load with compress.
      BlendedLoadVectorize, ///< (Masked) loads blended via `select` from two
                            ///< candidate base pointers.
      NeedToGather,         ///< Gather/buildvector node.
      CombinedVectorize, ///< Vectorized node, combined with its user into more
                         ///< complex node like select/cmp to minmax, mul/add to
                         ///< fma, etc. Must be used for the following nodes in
                         ///< the pattern, not the very first one.
      SplitVectorize,    ///< Splits the node into 2 subnodes, vectorizes them
                         ///< independently and then combines back.
    };
    EntryState State;

    /// List of combined opcodes supported by the vectorizer.
    enum CombinedOpcode {
      NotCombinedOp = -1,
      MinMax = Instruction::OtherOpsEnd + 1,
      FMulAdd,
      ReducedBitcast,
      ReducedBitcastBSwap,
      ReducedBitcastLoads,
      ReducedBitcastBSwapLoads,
      ReducedBitPack,
      ReducedCmpBitcast,
    };
    CombinedOpcode CombinedOp = NotCombinedOp;

    /// Does this sequence require some shuffling?
    SmallVector<int, 4> ReuseShuffleIndices;

    /// Does this entry require reordering?
    SmallVector<unsigned, 4> ReorderIndices;

    /// Points back to the VectorizableTree.
    ///
    /// Only used for Graphviz right now.  Unfortunately GraphTrait::NodeRef has
    /// to be a pointer and needs to be able to initialize the child iterator.
    /// Thus we need a reference back to the container to translate the indices
    /// to entries.
    VecTreeTy &Container;

    /// The TreeEntry index containing the user of this entry.
    EdgeInfo UserTreeIndex;

    /// The index of this treeEntry in VectorizableTree.
    unsigned Idx = 0;

    /// For gather/buildvector/alt opcode nodes, which are combined from
    /// other nodes as a series of insertvector instructions.
    SmallVector<std::pair<unsigned, unsigned>, 2> CombinedEntriesWithIndices;

    /// For ExtractValue entries that are vectorized via the struct-call path
    /// (checkEVsForVecCalls succeeded during tree building), stores the common
    /// field-index path shared by all scalars in the bundle. Empty for all
    /// other entry kinds.
    SmallVector<unsigned, 1> StructEVIndices;

  private:
    /// The operands of each instruction in each lane Operands[op_index][lane].
    /// Note: This helps avoid the replication of the code that performs the
    /// reordering of operands during buildTreeRec() and vectorizeTree().
    SmallVector<ValueList, 2> Operands;

    /// Copyable elements of the entry node.
    SmallPtrSet<const Value *, 4> CopyableElements;

    /// Intermediate instructions peeled from an associative chain (e.g. the
    /// inner add in add(add(v0,x),v1)). Not part of Scalars.
    SmallVector<Value *, 4> ReassocScalars;

    /// Sign of each flattened operand column of a reassociated add/sub
    /// chain, parallel to the operand columns: a negated column is
    /// subtracted from the positive total. Empty when no column is negated.
    SmallBitVector ReassocNegatedOps;

    /// MainOp and AltOp are recorded inside. S should be obtained from
    /// newTreeEntry.
    InstructionsState S = InstructionsState::invalid();

    /// Interleaving factor for interleaved loads Vectorize nodes.
    unsigned InterleaveFactor = 0;

    /// True if the node does not require scheduling.
    bool DoesNotNeedToSchedule = false;

    /// Set this bundle's \p OpIdx'th operand to \p OpVL.
    void setOperand(unsigned OpIdx, ArrayRef<Value *> OpVL) {
      if (Operands.size() < OpIdx + 1)
        Operands.resize(OpIdx + 1);
      assert(Operands[OpIdx].empty() && "Already resized?");
      assert(OpVL.size() <= Scalars.size() &&
             "Number of operands is greater than the number of scalars.");
      Operands[OpIdx].resize(OpVL.size());
      copy(OpVL, Operands[OpIdx].begin());
    }

    /// Maps values to their lanes in the node.
    mutable SmallDenseMap<Value *, unsigned> ValueToLane;

  public:
    /// Returns interleave factor for interleave nodes.
    unsigned getInterleaveFactor() const { return InterleaveFactor; }
    /// Sets interleaving factor for the interleaving nodes.
    void setInterleave(unsigned Factor) { InterleaveFactor = Factor; }

    /// Marks the node as one that does not require scheduling.
    void setDoesNotNeedToSchedule() { DoesNotNeedToSchedule = true; }
    /// Returns true if the node is marked as one that does not require
    /// scheduling.
    bool doesNotNeedToSchedule() const { return DoesNotNeedToSchedule; }

    /// Set this bundle's operands from \p Operands.
    void setOperands(ArrayRef<ValueList> Operands) {
      for (unsigned I : seq<unsigned>(Operands.size()))
        setOperand(I, Operands[I]);
    }

    /// Reorders operands of the node to the given mask \p Mask.
    void reorderOperands(ArrayRef<int> Mask) {
      for (ValueList &Operand : Operands)
        reorderScalars(Operand, Mask);
    }

    /// \returns the \p OpIdx operand of this TreeEntry.
    ValueList &getOperand(unsigned OpIdx) {
      assert(OpIdx < Operands.size() && "Off bounds");
      return Operands[OpIdx];
    }

    /// \returns the \p OpIdx operand of this TreeEntry.
    ArrayRef<Value *> getOperand(unsigned OpIdx) const {
      assert(OpIdx < Operands.size() && "Off bounds");
      return Operands[OpIdx];
    }

    /// \returns the number of operands.
    unsigned getNumOperands() const { return Operands.size(); }

    /// \return the single \p OpIdx operand.
    Value *getSingleOperand(unsigned OpIdx) const {
      assert(OpIdx < Operands.size() && "Off bounds");
      assert(!Operands[OpIdx].empty() && "No operand available");
      return Operands[OpIdx][0];
    }

    /// Some of the instructions in the list have alternate opcodes.
    bool isAltShuffle() const { return S.isAltShuffle(); }

    Instruction *getMatchingMainOpOrAltOp(Instruction *I) const {
      return S.getMatchingMainOpOrAltOp(I);
    }

    void setOperations(const InstructionsState &S) {
      assert(S && "InstructionsState is invalid.");
      this->S = S;
    }

    Instruction *getMainOp() const { return S.getMainOp(); }

    Instruction *getAltOp() const { return S.getAltOp(); }

    /// The main/alternate opcodes for the list of instructions.
    unsigned getOpcode() const { return S.getOpcode(); }

    unsigned getAltOpcode() const { return S.getAltOpcode(); }

    bool hasState() const { return S.valid(); }

    /// Add \p V to the list of copyable elements.
    void addCopyableElement(Value *V) {
      assert(S.isCopyableElement(V) && "Not a copyable element.");
      CopyableElements.insert(V);
    }

    /// Returns true if \p V is a copyable element.
    bool isCopyableElement(Value *V) const {
      return CopyableElements.contains(V);
    }

    /// Checks if the value \p V is a transformed instruction, compatible either
    /// with main or alternate ops.
    bool isExpandedBinOp(Value *V) const {
      assert(hasState() && "InstructionsState is invalid.");
      if (isCopyableElement(V))
        return false;
      return S.isExpandedBinOp(V);
    }

    /// Checks if the operand at index \p Idx of instruction \p I is an expanded
    /// operand.
    bool isExpandedOperand(Instruction *I, unsigned Idx) const {
      assert(hasState() && "InstructionsState is invalid.");
      if (isCopyableElement(I))
        return false;
      if (!isExpandedBinOp(I))
        return false;
      return S.isExpandedOperand(I, Idx);
    }

    /// Returns true if any scalar in the list is a copyable element.
    bool hasCopyableElements() const { return !CopyableElements.empty(); }

    /// Adds \p V to the peeled reassociated scalars.
    void addReassocScalar(Value *V) { ReassocScalars.push_back(V); }

    /// True if operands were gathered from an associative chain.
    bool hasReassocScalars() const { return !ReassocScalars.empty(); }

    /// Returns peeled reassociated scalars.
    ArrayRef<Value *> getReassocScalars() const { return ReassocScalars; }

    /// Records the signs of the flattened operand columns.
    void setReassocNegatedOps(const SmallBitVector &NegatedOps) {
      assert(NegatedOps.size() == getNumOperands() &&
             "Signs must cover all operand columns.");
      ReassocNegatedOps = NegatedOps;
    }

    /// True if operand column \p Idx is subtracted rather than added.
    bool isReassocNegatedOp(unsigned Idx) const {
      return Idx < ReassocNegatedOps.size() && ReassocNegatedOps[Idx];
    }

    /// Returns the state of the operations.
    const InstructionsState &getOperations() const { return S; }

    /// When ReuseReorderShuffleIndices is empty it just returns position of \p
    /// V within vector of Scalars. Otherwise, try to remap on its reuse index.
    unsigned findLaneForValue(Value *V) const {
      auto Res = ValueToLane.try_emplace(V, getVectorFactor());
      if (!Res.second)
        return Res.first->second;
      unsigned &FoundLane = Res.first->getSecond();
      // Poison can take any lane, match it to the lane of the first non-poison
      // scalar.
      auto IsMatch = [V](Value *S) {
        return isa<PoisonValue>(V) ? !isa<PoisonValue>(S) : S == V;
      };
      for (auto *It = find_if(Scalars, IsMatch), *End = Scalars.end();
           It != End; std::advance(It, 1)) {
        if (!IsMatch(*It))
          continue;
        FoundLane = std::distance(Scalars.begin(), It);
        assert(FoundLane < Scalars.size() && "Couldn't find extract lane");
        if (!ReorderIndices.empty())
          FoundLane = ReorderIndices[FoundLane];
        assert(FoundLane < Scalars.size() && "Couldn't find extract lane");
        if (ReuseShuffleIndices.empty())
          break;
        if (auto *RIt = find(ReuseShuffleIndices, FoundLane);
            RIt != ReuseShuffleIndices.end()) {
          FoundLane = std::distance(ReuseShuffleIndices.begin(), RIt);
          break;
        }
      }
      assert(FoundLane < getVectorFactor() && "Unable to find given value.");
      return FoundLane;
    }

    /// Build a shuffle mask for graph entry which represents a merge of main
    /// and alternate operations.
    void
    buildAltOpShuffleMask(const function_ref<bool(Instruction *)> IsAltOp,
                          SmallVectorImpl<int> &Mask,
                          SmallVectorImpl<Value *> *OpScalars = nullptr,
                          SmallVectorImpl<Value *> *AltScalars = nullptr) const;

    /// Return true if this is a non-power-of-2 node.
    bool isNonPowOf2Vec() const {
      bool IsNonPowerOf2 = !has_single_bit(Scalars.size());
      return IsNonPowerOf2;
    }

    Value *getOrdered(unsigned Idx) const {
      if (ReorderIndices.empty())
        return Scalars[Idx];
      SmallVector<int> Mask;
      inversePermutation(ReorderIndices, Mask);
      return Scalars[Mask[Idx]];
    }

#ifndef NDEBUG
    /// Debug printer.
    LLVM_DUMP_METHOD void dump() const {
      dbgs() << Idx << ".\n";
      for (unsigned OpI = 0, OpE = Operands.size(); OpI != OpE; ++OpI) {
        dbgs() << "Operand " << OpI << ":\n";
        for (const Value *V : Operands[OpI])
          dbgs().indent(2) << *V << "\n";
      }
      dbgs() << "Scalars: \n";
      for (Value *V : Scalars) {
        dbgs().indent(2) << *V
                         << ((S && S.isExpandedBinOp(V)) ? " [[Expanded]]\n"
                                                         : "\n");
      }
      dbgs() << "State: ";
      if (S && hasCopyableElements())
        dbgs() << "[[Copyable]] ";
      switch (State) {
      case Vectorize:
        if (InterleaveFactor > 0) {
          dbgs() << "Vectorize with interleave factor " << InterleaveFactor
                 << "\n";
        } else {
          dbgs() << "Vectorize\n";
        }
        break;
      case ScatterVectorize:
        dbgs() << "ScatterVectorize\n";
        break;
      case StridedVectorize:
        dbgs() << "StridedVectorize\n";
        break;
      case ExpandVectorize:
        dbgs() << "ExpandVectorize\n";
        break;
      case CompressVectorize:
        dbgs() << "CompressVectorize\n";
        break;
      case BlendedLoadVectorize:
        dbgs() << "BlendedLoadVectorize\n";
        break;
      case NeedToGather:
        dbgs() << "NeedToGather\n";
        break;
      case CombinedVectorize:
        dbgs() << "CombinedVectorize\n";
        break;
      case SplitVectorize:
        dbgs() << "SplitVectorize\n";
        break;
      }
      if (S) {
        dbgs() << "MainOp: " << *S.getMainOp() << "\n";
        dbgs() << "AltOp: " << *S.getAltOp() << "\n";
      } else {
        dbgs() << "MainOp: NULL\n";
        dbgs() << "AltOp: NULL\n";
      }
      dbgs() << "VectorizedValue: ";
      if (VectorizedValue)
        dbgs() << *VectorizedValue << "\n";
      else
        dbgs() << "NULL\n";
      dbgs() << "ReuseShuffleIndices: ";
      if (ReuseShuffleIndices.empty())
        dbgs() << "Empty";
      else
        for (int ReuseIdx : ReuseShuffleIndices)
          dbgs() << ReuseIdx << ", ";
      dbgs() << "\n";
      dbgs() << "ReorderIndices: ";
      for (unsigned ReorderIdx : ReorderIndices)
        dbgs() << ReorderIdx << ", ";
      dbgs() << "\n";
      dbgs() << "UserTreeIndex: ";
      if (UserTreeIndex)
        dbgs() << UserTreeIndex;
      else
        dbgs() << "<invalid>";
      dbgs() << "\n";
      if (!StructEVIndices.empty()) {
        dbgs() << "StructEVIndices: ";
        interleaveComma(StructEVIndices, dbgs());
        dbgs() << "\n";
      }
      if (!CombinedEntriesWithIndices.empty()) {
        dbgs() << "Combined entries: ";
        interleaveComma(CombinedEntriesWithIndices, dbgs(), [&](const auto &P) {
          dbgs() << "Entry index " << P.first << " with offset " << P.second;
        });
        dbgs() << "\n";
      }
    }
#endif
  };

#ifndef NDEBUG
  void dumpTreeCosts(const TreeEntry *E, InstructionCost ReuseShuffleCost,
                     InstructionCost VecCost, InstructionCost ScalarCost,
                     StringRef Banner) const {
    dbgs() << "SLP: " << Banner << ":\n";
    E->dump();
    dbgs() << "SLP: Costs:\n";
    dbgs() << "SLP:     ReuseShuffleCost = " << ReuseShuffleCost << "\n";
    dbgs() << "SLP:     VectorCost = " << VecCost << "\n";
    dbgs() << "SLP:     ScalarCost = " << ScalarCost << "\n";
    dbgs() << "SLP:     ReuseShuffleCost + VecCost - ScalarCost = "
           << ReuseShuffleCost + VecCost - ScalarCost << "\n";
  }
#endif

  /// Create a new gather TreeEntry
  TreeEntry *newGatherTreeEntry(ArrayRef<Value *> VL,
                                const InstructionsState &S,
                                const EdgeInfo &UserTreeIdx,
                                ArrayRef<int> ReuseShuffleIndices = {}) {
    auto Invalid = ScheduleBundle::invalid();
    return newTreeEntry(VL, Invalid, S, UserTreeIdx, ReuseShuffleIndices);
  }

  /// Create a new VectorizableTree entry.
  TreeEntry *newTreeEntry(ArrayRef<Value *> VL, ScheduleBundle &Bundle,
                          const InstructionsState &S,
                          const EdgeInfo &UserTreeIdx,
                          ArrayRef<int> ReuseShuffleIndices = {},
                          ArrayRef<unsigned> ReorderIndices = {},
                          unsigned InterleaveFactor = 0) {
    TreeEntry::EntryState EntryState =
        Bundle ? TreeEntry::Vectorize : TreeEntry::NeedToGather;
    TreeEntry *E = newTreeEntry(VL, EntryState, Bundle, S, UserTreeIdx,
                                ReuseShuffleIndices, ReorderIndices);
    if (E && InterleaveFactor > 0)
      E->setInterleave(InterleaveFactor);
    return E;
  }

  TreeEntry *newTreeEntry(ArrayRef<Value *> VL,
                          TreeEntry::EntryState EntryState,
                          ScheduleBundle &Bundle, const InstructionsState &S,
                          const EdgeInfo &UserTreeIdx,
                          ArrayRef<int> ReuseShuffleIndices = {},
                          ArrayRef<unsigned> ReorderIndices = {}) {
    assert(((!Bundle && (EntryState == TreeEntry::NeedToGather ||
                         EntryState == TreeEntry::SplitVectorize)) ||
            (Bundle && EntryState != TreeEntry::NeedToGather &&
             EntryState != TreeEntry::SplitVectorize)) &&
           "Need to vectorize gather entry?");
    // Gathered loads still gathered? Do not create entry, use the original one.
    if (GatheredLoadsEntriesFirst.has_value() &&
        EntryState == TreeEntry::NeedToGather && S &&
        S.getOpcode() == Instruction::Load && UserTreeIdx.EdgeIdx == UINT_MAX &&
        !UserTreeIdx.UserTE)
      return nullptr;
    VectorizableTree.push_back(std::make_unique<TreeEntry>(VectorizableTree));
    TreeEntry *Last = VectorizableTree.back().get();
    Last->Idx = VectorizableTree.size() - 1;
    Last->State = EntryState;
    if (UserTreeIdx.UserTE)
      OperandsToTreeEntry.try_emplace(
          std::make_pair(UserTreeIdx.UserTE, UserTreeIdx.EdgeIdx), Last);
    Last->ReuseShuffleIndices.append(ReuseShuffleIndices.begin(),
                                     ReuseShuffleIndices.end());
    if (ReorderIndices.empty()) {
      Last->Scalars.assign(VL.begin(), VL.end());
      if (S)
        Last->setOperations(S);
    } else {
      // Reorder scalars and build final mask.
      Last->Scalars.assign(VL.size(), nullptr);
      transform(ReorderIndices, Last->Scalars.begin(),
                [VL](unsigned Idx) -> Value * {
                  if (Idx >= VL.size())
                    return UndefValue::get(VL.front()->getType());
                  return VL[Idx];
                });
      InstructionsState S = getSameOpcode(Last->Scalars, *TLI);
      if (S)
        Last->setOperations(S);
      Last->ReorderIndices.append(ReorderIndices.begin(), ReorderIndices.end());
    }
    if (EntryState == TreeEntry::SplitVectorize) {
      assert(S && "Split nodes must have operations.");
      Last->setOperations(S);
      SmallPtrSet<Value *, 4> Processed;
      for (Instruction *I : make_isa_range<Instruction>(VL)) {
        auto It = ScalarsInSplitNodes.find(I);
        if (It == ScalarsInSplitNodes.end()) {
          ScalarsInSplitNodes.try_emplace(I).first->getSecond().push_back(Last);
          (void)Processed.insert(I);
        } else if (Processed.insert(I).second) {
          assert(!is_contained(It->getSecond(), Last) &&
                 "Value already associated with the node.");
          It->getSecond().push_back(Last);
        }
      }
    } else if (!Last->isGather()) {
      if (isa<PHINode>(S.getMainOp()) ||
          isVectorLikeInstWithConstOps(S.getMainOp()) ||
          (!S.areInstructionsWithCopyableElements() &&
           doesNotNeedToSchedule(VL)) ||
          all_of(VL, [&](Value *V) { return S.isNonSchedulable(V); }))
        Last->setDoesNotNeedToSchedule();
      SmallPtrSet<Value *, 4> Processed;
      for (Value *V : make_filter_range(
               VL, [](Value *V) { return !isa<PoisonValue>(V); })) {
        if (S.isCopyableElement(V)) {
          Last->addCopyableElement(V);
          continue;
        }
        auto It = ScalarToTreeEntries.find(V);
        if (It == ScalarToTreeEntries.end()) {
          ScalarToTreeEntries.try_emplace(V).first->getSecond().push_back(Last);
          (void)Processed.insert(V);
        } else if (Processed.insert(V).second) {
          assert(!is_contained(It->getSecond(), Last) &&
                 "Value already associated with the node.");
          It->getSecond().push_back(Last);
        }
      }
      // Update the scheduler bundle to point to this TreeEntry.
      assert((!Bundle.getBundle().empty() || Last->doesNotNeedToSchedule()) &&
             "Bundle and VL out of sync");
      if (!Bundle.getBundle().empty()) {
#if !defined(NDEBUG) || defined(EXPENSIVE_CHECKS)
        auto *BundleMember = Bundle.getBundle().begin();
        SmallPtrSet<Value *, 4> Processed;
        for (Value *V : VL) {
          if (S.isNonSchedulable(V) || !Processed.insert(V).second)
            continue;
          ++BundleMember;
        }
        assert(BundleMember == Bundle.getBundle().end() &&
               "Bundle and VL out of sync");
#endif
        Bundle.setTreeEntry(Last);
      }
    } else {
      // Build a map for gathered scalars to the nodes where they are used.
      bool AllConstsOrCasts = true;
      for (Value *V : VL) {
        if (S && S.areInstructionsWithCopyableElements() &&
            S.isCopyableElement(V))
          Last->addCopyableElement(V);
        if (!isConstant(V)) {
          auto *I = dyn_cast<CastInst>(V);
          AllConstsOrCasts &= I && I->getType()->isIntegerTy();
          if (UserTreeIdx.EdgeIdx != UINT_MAX || !UserTreeIdx.UserTE ||
              !UserTreeIdx.UserTE->isGather())
            ValueToGatherNodes.try_emplace(V).first->getSecond().insert(Last);
        }
      }
      if (AllConstsOrCasts)
        CastMaxMinBWSizes =
            std::make_pair(std::numeric_limits<unsigned>::max(), 1);
      MustGather.insert_range(VL);
    }

    if (UserTreeIdx.UserTE)
      Last->UserTreeIndex = UserTreeIdx;
    return Last;
  }

  /// -- Vectorization State --
  /// Holds all of the tree entries.
  TreeEntry::VecTreeTy VectorizableTree;

#ifndef NDEBUG
  /// Debug printer.
  LLVM_DUMP_METHOD void dumpVectorizableTree() const {
    for (unsigned Id = 0, IdE = VectorizableTree.size(); Id != IdE; ++Id) {
      VectorizableTree[Id]->dump();
      if (TransformedToGatherNodes.contains(VectorizableTree[Id].get()))
        dbgs() << "[[TRANSFORMED TO GATHER]]";
      else if (DeletedNodes.contains(VectorizableTree[Id].get()))
        dbgs() << "[[DELETED NODE]]";
      dbgs() << "\n";
    }
  }
#endif

  /// Get list of vector entries, associated with the value \p V.
  ArrayRef<TreeEntry *> getTreeEntries(const Value *V) const {
    assert(V && "V cannot be nullptr.");
    auto It = ScalarToTreeEntries.find(V);
    if (It == ScalarToTreeEntries.end())
      return {};
    return It->getSecond();
  }

  /// Get list of split vector entries, associated with the value \p V.
  ArrayRef<TreeEntry *> getSplitTreeEntries(Value *V) const {
    assert(V && "V cannot be nullptr.");
    auto It = ScalarsInSplitNodes.find(V);
    if (It == ScalarsInSplitNodes.end())
      return {};
    return It->getSecond();
  }

  /// Returns first vector node for value \p V, matching values \p VL.
  TreeEntry *getSameValuesTreeEntry(Value *V, ArrayRef<Value *> VL,
                                    bool SameVF = false) const {
    assert(V && "V cannot be nullptr.");
    for (TreeEntry *TE : ScalarToTreeEntries.lookup(V))
      if ((!SameVF || TE->getVectorFactor() == VL.size()) && TE->isSame(VL))
        return TE;
    return nullptr;
  }

  /// Contains all the outputs of legality analysis for a list of values to
  /// vectorize.
  class ScalarsVectorizationLegality {
    InstructionsState S;
    bool IsLegal;
    bool TryToFindDuplicates;
    bool TrySplitVectorize;

  public:
    ScalarsVectorizationLegality(InstructionsState S, bool IsLegal,
                                 bool TryToFindDuplicates = true,
                                 bool TrySplitVectorize = false)
        : S(S), IsLegal(IsLegal), TryToFindDuplicates(TryToFindDuplicates),
          TrySplitVectorize(TrySplitVectorize) {
      assert((!IsLegal || (S.valid() && TryToFindDuplicates)) &&
             "Inconsistent state");
    }
    const InstructionsState &getInstructionsState() const { return S; };
    bool isLegal() const { return IsLegal; }
    bool tryToFindDuplicates() const { return TryToFindDuplicates; }
    bool trySplitVectorize() const { return TrySplitVectorize; }
  };

  /// Checks if the specified list of the instructions/values can be vectorized
  /// in general.
  ScalarsVectorizationLegality
  getScalarsVectorizationLegality(ArrayRef<Value *> VL, unsigned Depth,
                                  const EdgeInfo &UserTreeIdx) const;

  /// Checks if the specified list of the instructions/values can be vectorized
  /// and fills required data before actual scheduling of the instructions.
  TreeEntry::EntryState getScalarsVectorizationState(
      const InstructionsState &S, ArrayRef<Value *> VL,
      bool IsScatterVectorizeUserTE, OrdersType &CurrentOrder,
      SmallVectorImpl<Value *> &PointerOps, StridedPtrInfo &SPtrInfo,
      SmallVectorImpl<int> &ReuseShuffleIndices);

  /// Maps a specific scalar to its tree entry(ies).
  SmallDenseMap<Value *, SmallVector<TreeEntry *>> ScalarToTreeEntries;

  /// List of deleted non-profitable nodes.
  SmallPtrSet<const TreeEntry *, 8> DeletedNodes;

  /// List of nodes, transformed to gathered, with their conservative
  /// gather/buildvector cost estimation.
  SmallDenseMap<const TreeEntry *, InstructionCost> TransformedToGatherNodes;

  /// Maps the operand index and entry to the corresponding tree entry.
  SmallDenseMap<std::pair<const TreeEntry *, unsigned>, TreeEntry *>
      OperandsToTreeEntry;

  /// Scalars, used in split vectorize nodes.
  SmallDenseMap<Value *, SmallVector<TreeEntry *>> ScalarsInSplitNodes;

  /// Maps a value to the proposed vectorizable size.
  SmallDenseMap<Value *, unsigned> InstrElementSize;

  /// A list of scalars that we found that we need to keep as scalars.
  ValueSet MustGather;

  /// Maps each peeled reassociated scalar to owning entries. Keeps them
  /// treated as vectorized while an owner is live.
  SmallDenseMap<const Value *, SmallVector<const TreeEntry *>>
      ReassocScalarToTreeEntries;

  /// Peeled reassociated scalars that must survive erasure: claimed by a
  /// gather node, listed in some tree entry's scalars, or feeding another
  /// kept scalar.
  SmallPtrSet<const Value *, 8> KeptReassocScalars;

  /// A set of first non-schedulable values.
  ValueSet NonScheduledFirst;

  /// A map between the vectorized entries and the last instructions in the
  /// bundles. The bundles are built in use order, not in the def order of the
  /// instructions. So, we cannot rely directly on the last instruction in the
  /// bundle being the last instruction in the program order during
  /// vectorization process since the basic blocks are affected, need to
  /// pre-gather them before.
  SmallDenseMap<const TreeEntry *, WeakTrackingVH> EntryToLastInstruction;

  /// Keeps the mapping between the last instructions and their insertion
  /// points, which is an instruction-after-the-last-instruction.
  SmallDenseMap<const Instruction *, Instruction *> LastInstructionToPos;

  /// List of gather nodes, depending on other gather/vector nodes, which should
  /// be emitted after the vector instruction emission process to correctly
  /// handle order of the vector instructions and shuffles.
  SetVector<const TreeEntry *> PostponedGathers;

  using ValueToGatherNodesMap =
      DenseMap<Value *, SmallSetVector<const TreeEntry *, 4>>;
  ValueToGatherNodesMap ValueToGatherNodes;

  SmallDenseMap<TreeEntry *, StridedPtrInfo> TreeEntryToStridedPtrInfoMap;

  /// A list of the load entries (node indices), which can be vectorized using
  /// strided or masked gather approach, but attempted to be represented as
  /// contiguous loads.
  SetVector<unsigned> LoadEntriesToVectorize;

  /// true if graph nodes transforming mode is on.
  bool IsGraphTransformMode = false;

  /// The index of the first gathered load entry in the VectorizeTree.
  std::optional<unsigned> GatheredLoadsEntriesFirst;

  /// Root entries of the subtrees built for the splat gather nodes' unique
  /// scalars. They have no users in the tree and must be emitted explicitly
  /// before the root node.
  SmallVector<TreeEntry *> SplatGatheredScalarsRoots;

  /// Checks if any of \p Entries is an internal gather of a splat gather
  /// subtree.
  bool hasSplatSubtreeGather(
      ArrayRef<SmallVector<const TreeEntry *>> Entries) const {
    if (SplatGatheredScalarsRoots.empty())
      return false;
    return any_of(Entries, [&](ArrayRef<const TreeEntry *> TEs) {
      return any_of(TEs, [&](const TreeEntry *TE) {
        if (!TE->isGather())
          return false;
        while (TE->UserTreeIndex)
          TE = TE->UserTreeIndex.UserTE;
        return is_contained(SplatGatheredScalarsRoots, TE);
      });
    });
  }

  /// Number of tree entries added while building the splat gather subtrees.
  /// The subtrees are auxiliary and must not inflate the tree size recorded
  /// for failed store chain attempts.
  unsigned NumCanonicalSplatSubtreeEntries = 0;

  /// Maps compress entries to their mask data for the final codegen.
  SmallDenseMap<const TreeEntry *,
                std::tuple<SmallVector<int>, VectorType *, unsigned, bool>>
      CompressEntryToData;

  /// The loop nest, used to check if only a single loop nest is vectorized, not
  /// multiple, to avoid side-effects from the loop-aware cost model.
  SmallVector<const Loop *> CurrentLoopNest;

  /// Per-depth SCEVs trip counts at every loop level where the tree builder has
  /// joined diverging sibling loops.
  SmallVector<const SCEV *> MergedLoopBTCs;

  /// Maps the loops to their loop nests.
  SmallDenseMap<const Loop *, SmallVector<const Loop *>> LoopToLoopNest;

  /// Per-loop cache of nest scale factors: the product of trip counts of the
  /// loop and all of its ancestors. Shared by getLoopNestScale() and (via it)
  /// by getScaleToLoopIterations() and getGatherNodeEffectiveScale().
  SmallDenseMap<const Loop *, uint64_t> LoopNestScaleCache;

  /// This POD struct describes one external user in the vectorized tree.
  struct ExternalUser {
    ExternalUser(Value *S, llvm::User *U, const TreeEntry &E, unsigned L)
        : Scalar(S), User(U), E(E), Lane(L) {}

    /// Which scalar in our function.
    Value *Scalar = nullptr;

    /// Which user that uses the scalar.
    llvm::User *User = nullptr;

    /// Vector node, the value is part of.
    const TreeEntry &E;

    /// Which lane does the scalar belong to.
    unsigned Lane;
  };
  using UserList = SmallVector<ExternalUser, 16>;

  /// Checks if two instructions may access the same memory.
  ///
  /// \p Loc1 is the location of \p Inst1. It is passed explicitly because it
  /// is invariant in the calling loop.
  bool isAliased(const MemoryLocation &Loc1, Instruction *Inst1,
                 Instruction *Inst2) {
    assert(Loc1.Ptr && isSimple(Inst1) && "Expected simple first instruction.");
    // First check if the result is already in the cache.
    AliasCacheKey Key = std::make_pair(Inst1, Inst2);
    auto Res = AliasCache.try_emplace(Key);
    if (!Res.second)
      return Res.first->second;
    bool Aliased = isModOrRefSet(BatchAA->getModRefInfo(Inst2, Loc1));
    // Store the result in the cache.
    Res.first->getSecond() = Aliased;
    return Aliased;
  }

  /// Returns true if the may-alias dependency between simple load/store
  /// instructions \p Inst1 and \p Inst2 could be disambiguated by a runtime
  /// alias check.
  bool isRuntimeCheckableAliasPair(Instruction *Inst1, Instruction *Inst2);

  /// Records the (distinct base object) pair behind the may-alias dependency
  /// of \p Inst1 and \p Inst2 as a runtime alias check guarding the region in
  /// block \p BB. Returns true if the pair was recorded.
  bool recordRuntimeAliasCheck(BasicBlock *BB, Instruction *Inst1,
                               Instruction *Inst2);

  /// Emits the collected runtime alias checks and versions the affected block,
  /// duplicating its body into a scalar fallback guarded by the checks.
  void versionBlocksForRuntimeChecks();

  /// Builds the i1 value that is true when any pair of checked base objects
  /// overlaps at runtime. The base address bounds are materialized from their
  /// SCEVs with \p Exp.
  Value *emitRuntimeAliasCheck(IRBuilderBase &Builder, SCEVExpander &Exp);

  /// Data to model and emit the runtime alias checks.
  struct RuntimeAliasCheckInfo {
    /// The block whose body is guarded by the checks. Exactly one block is
    /// supported per attempt.
    BasicBlock *BB = nullptr;
    /// Pairs of base objects that must be proven disjoint.
    SmallSetVector<std::pair<const Value *, const Value *>, 4> BasePairs;
    /// Accessed address range [Low, High) for each involved base object.
    SmallMapVector<const Value *, std::pair<const SCEV *, const SCEV *>, 4>
        Bounds;

    void clear() {
      BB = nullptr;
      BasePairs.clear();
      Bounds.clear();
    }
  };

  /// When true, scheduling drops may-alias memory dependencies between
  /// distinct, range-checkable base objects and records them as runtime alias
  /// checks instead.
  bool TryRuntimeAliasChecks = false;

  /// When true, the stored values of the root store node are split into
  /// halves, which are vectorized as separate subtrees.
  bool SplitStoredValues = false;

  /// Runtime alias checks collected during the last optimistic buildTree().
  RuntimeAliasCheckInfo RTChecks;

  /// Base-object pairs already proven disjoint by the block's runtime alias
  /// check.
  SmallDenseMap<BasicBlock *,
                SmallDenseSet<std::pair<const Value *, const Value *>, 4>, 2>
      VersionedBlockCheckedPairs;

  /// Scalar fallback blocks.
  SmallPtrSet<BasicBlock *, 4> ScalarFallbackBlocks;

  /// Blocks for which a runtime-checks versioning attempt was made
  /// and did not produce a profitable versioning.
  SmallPtrSet<BasicBlock *, 8> FailedRuntimeChecksBlocks;

  /// Returns true if a may-alias dependency between the simple load/store
  /// instructions \p Inst1 and \p Inst2 in block \p BB is already covered by a
  /// runtime alias check emitted for \p BB by a previous versioning.
  bool isCoveredByExistingVersionCheck(BasicBlock *BB, Instruction *Inst1,
                                       Instruction *Inst2) const;

  /// True, if a may-alias dependency between distinct, range-checkable base
  /// objects is observed (whether or not it was dropped).
  bool HasRuntimeCheckableBlockers = false;

  /// True, if a kept may-alias dependency is not runtime-checkable (call or a
  /// non-simple memaccess).
  bool HasNonCheckableMemBlocker = false;

  /// Runtime checks are validated and bounded the collected checks.
  bool RTChecksFinalized = false;

  /// Set when a block was versioned with runtime alias checks, which changes
  /// the CFG. Used to drop CFG-analysis preservation for the run.
  bool CFGChanged = false;

  /// Guarded block body (non-PHI, non-alloca, non-terminator) in original
  /// source order.
  SmallVector<Instruction *> RTOrigBodyOrder;

  using AliasCacheKey = std::pair<Instruction *, Instruction *>;

  /// Cache for alias results.
  /// TODO: consider moving this to the AliasAnalysis itself.
  SmallDenseMap<AliasCacheKey, bool> AliasCache;

  AAResults *AA;

  // Cache for pointerMayBeCaptured calls inside AA. Vectorizing a tree can
  // create new captures (e.g. a pointer inserted into a vector of pointers
  // feeding a masked gather), so this is reset after each vectorized tree.
  std::optional<BatchAAResults> BatchAA;

  /// Temporary store for deleted instructions. Instructions will be deleted
  /// eventually when the BoUpSLP is destructed.  The deferral is required to
  /// ensure that there are no incorrect collisions in the AliasCache, which
  /// can happen if a new instruction is allocated at the same address as a
  /// previously deleted instruction.
  DenseSet<Instruction *> DeletedInstructions;

  /// The cached analyses results, cleared after each successful
  /// vectorizeTree().
  mutable SLPAnalysisCache Cache;

  /// Set of the instruction, being analyzed already for reductions.
  SmallPtrSet<Instruction *, 16> AnalyzedReductionsRoots;

  /// Set of hashes for the list of reduction values already being analyzed.
  DenseSet<size_t> AnalyzedReductionVals;

  /// Set of hashes for the bundles, rejected as non-vectorizable.
  SmallDenseSet<size_t, 8> AnalyzedBundles;

  /// Set of the values, which were a part of the analyzed vector nodes.
  SmallPtrSet<const Value *, 32> AnalyzedScalars;

  /// Cache of the number of parts for the types and the parts limit.
  mutable SmallDenseMap<std::tuple<Type *, Type *, unsigned>, unsigned>
      NumberOfPartsCache;

  /// Cache of the number of regs for the types and the parts limit.
  mutable SmallDenseMap<std::tuple<Type *, Type *, unsigned>, unsigned>
      NumberOfRegsCache;

  /// Values already analyzed for minimal bitwidth and found to be
  /// non-profitable, mapped to the size of the tree used for the analysis.
  SmallDenseMap<Value *, unsigned> AnalyzedMinBWVals;

  /// A list of values that need to extracted out of the tree.
  /// This list holds pairs of (Internal Scalar : External User). External User
  /// can be nullptr, it means that this Internal Scalar will be used later,
  /// after vectorization.
  UserList ExternalUses;

  /// A list of GEPs which can be reaplced by scalar GEPs instead of
  /// extractelement instructions.
  SmallPtrSet<Value *, 4> ExternalUsesAsOriginalScalar;

  /// A list of scalar to be extracted without specific user necause of too many
  /// uses.
  SmallPtrSet<Value *, 4> ExternalUsesWithNonUsers;

  /// Externally used values and replacements emitted for the external uses
  /// without users, consumed after the tree vectorization; must not be
  /// collected as dead operands of the erased scalars.
  SmallPtrSet<Value *, 4> ExternalUseReplacements;

  /// Values used only by @llvm.assume calls.
  SmallPtrSet<const Value *, 32> EphValues;

  /// Holds all of the instructions that we gathered, shuffle instructions and
  /// extractelements.
  SetVector<Instruction *> GatherShuffleExtractSeq;

  /// A list of blocks that we are going to CSE.
  DenseSet<BasicBlock *> CSEBlocks;

  /// List of hashes of vector of loads, which are known to be non vectorizable.
  DenseSet<size_t> ListOfKnonwnNonVectorizableLoads;

  /// Represents a scheduling entity, either ScheduleData, ScheduleCopyableData
  /// or ScheduleBundle. ScheduleData used to gather dependecies for a single
  /// instructions, while ScheduleBundle represents a batch of instructions,
  /// going to be groupped together. ScheduleCopyableData models extra user for
  /// "copyable" instructions.
  class ScheduleEntity {
    friend class ScheduleBundle;
    friend class ScheduleData;
    friend class ScheduleCopyableData;

  protected:
    enum class Kind { ScheduleData, ScheduleBundle, ScheduleCopyableData };
    Kind getKind() const { return K; }
    ScheduleEntity(Kind K) : K(K) {}

  private:
    /// Used for getting a "good" final ordering of instructions.
    int SchedulingPriority = 0;
    /// True if this instruction (or bundle) is scheduled (or considered as
    /// scheduled in the dry-run).
    bool IsScheduled = false;
    /// The kind of the ScheduleEntity.
    const Kind K = Kind::ScheduleData;

  public:
    ScheduleEntity() = delete;
    /// Gets/sets the scheduling priority.
    void setSchedulingPriority(int Priority) { SchedulingPriority = Priority; }
    int getSchedulingPriority() const { return SchedulingPriority; }
    bool isReady() const {
      if (const auto *SD = dyn_cast<ScheduleData>(this))
        return SD->isReady();
      if (const auto *CD = dyn_cast<ScheduleCopyableData>(this))
        return CD->isReady();
      return cast<ScheduleBundle>(this)->isReady();
    }
    /// Returns true if the dependency information has been calculated.
    /// Note that depenendency validity can vary between instructions within
    /// a single bundle.
    bool hasValidDependencies() const {
      if (const auto *SD = dyn_cast<ScheduleData>(this))
        return SD->hasValidDependencies();
      if (const auto *CD = dyn_cast<ScheduleCopyableData>(this))
        return CD->hasValidDependencies();
      return cast<ScheduleBundle>(this)->hasValidDependencies();
    }
    /// Gets the number of unscheduled dependencies.
    int getUnscheduledDeps() const {
      if (const auto *SD = dyn_cast<ScheduleData>(this))
        return SD->getUnscheduledDeps();
      if (const auto *CD = dyn_cast<ScheduleCopyableData>(this))
        return CD->getUnscheduledDeps();
      return cast<ScheduleBundle>(this)->unscheduledDepsInBundle();
    }
    /// Increments the number of unscheduled dependencies.
    int incrementUnscheduledDeps(int Incr) {
      if (auto *SD = dyn_cast<ScheduleData>(this))
        return SD->incrementUnscheduledDeps(Incr);
      return cast<ScheduleCopyableData>(this)->incrementUnscheduledDeps(Incr);
    }
    /// Gets the number of dependencies.
    int getDependencies() const {
      if (const auto *SD = dyn_cast<ScheduleData>(this))
        return SD->getDependencies();
      return cast<ScheduleCopyableData>(this)->getDependencies();
    }
    /// Gets the instruction.
    Instruction *getInst() const {
      if (const auto *SD = dyn_cast<ScheduleData>(this))
        return SD->getInst();
      return cast<ScheduleCopyableData>(this)->getInst();
    }

    /// Gets/sets if the bundle is scheduled.
    bool isScheduled() const { return IsScheduled; }
    void setScheduled(bool Scheduled) { IsScheduled = Scheduled; }

    static bool classof(const ScheduleEntity *) { return true; }

#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
    void dump(raw_ostream &OS) const {
      if (const auto *SD = dyn_cast<ScheduleData>(this))
        return SD->dump(OS);
      if (const auto *CD = dyn_cast<ScheduleCopyableData>(this))
        return CD->dump(OS);
      return cast<ScheduleBundle>(this)->dump(OS);
    }

    LLVM_DUMP_METHOD void dump() const {
      dump(dbgs());
      dbgs() << '\n';
    }
#endif // if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
  };

#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
  friend inline raw_ostream &operator<<(raw_ostream &OS,
                                        const BoUpSLP::ScheduleEntity &SE) {
    SE.dump(OS);
    return OS;
  }
#endif

  /// Contains all scheduling relevant data for an instruction.
  /// A ScheduleData either represents a single instruction or a member of an
  /// instruction bundle (= a group of instructions which is combined into a
  /// vector instruction).
  class ScheduleData final : public ScheduleEntity {
  public:
    // The initial value for the dependency counters. It means that the
    // dependencies are not calculated yet.
    enum { InvalidDeps = -1 };

    ScheduleData() : ScheduleEntity(Kind::ScheduleData) {}
    static bool classof(const ScheduleEntity *Entity) {
      return Entity->getKind() == Kind::ScheduleData;
    }

    void init(int BlockSchedulingRegionID, Instruction *I) {
      NextLoadStore = nullptr;
      IsScheduled = false;
      SchedulingRegionID = BlockSchedulingRegionID;
      clearDependencies();
      Inst = I;
    }

    /// Verify basic self consistency properties
    void verify() {
      if (hasValidDependencies()) {
        assert(UnscheduledDeps <= Dependencies && "invariant");
      } else {
        assert(UnscheduledDeps == Dependencies && "invariant");
      }

      if (IsScheduled) {
        assert(hasValidDependencies() && UnscheduledDeps == 0 &&
               "unexpected scheduled state");
      }
    }

    /// Returns true if the dependency information has been calculated.
    /// Note that depenendency validity can vary between instructions within
    /// a single bundle.
    bool hasValidDependencies() const { return Dependencies != InvalidDeps; }

    /// Returns true if it is ready for scheduling, i.e. it has no more
    /// unscheduled depending instructions/bundles.
    bool isReady() const { return UnscheduledDeps == 0 && !IsScheduled; }

    /// Modifies the number of unscheduled dependencies for this instruction,
    /// and returns the number of remaining dependencies for the containing
    /// bundle.
    int incrementUnscheduledDeps(int Incr) {
      assert(hasValidDependencies() &&
             "increment of unscheduled deps would be meaningless");
      UnscheduledDeps += Incr;
      assert(UnscheduledDeps >= 0 &&
             "Expected valid number of unscheduled deps");
      return UnscheduledDeps;
    }

    /// Sets the number of unscheduled dependencies to the number of
    /// dependencies.
    void resetUnscheduledDeps() { UnscheduledDeps = Dependencies; }

    /// Clears all dependency information.
    void clearDependencies() {
      clearDirectDependencies();
      MemoryDependencies.clear();
      ControlDependencies.clear();
    }

    /// Clears all direct dependencies only, except for control and memory
    /// dependencies.
    /// Required for copyable elements to correctly handle control/memory deps
    /// and avoid extra reclaculation of such deps.
    void clearDirectDependencies() {
      Dependencies = InvalidDeps;
      resetUnscheduledDeps();
      IsScheduled = false;
    }

    /// Gets the number of unscheduled dependencies.
    int getUnscheduledDeps() const { return UnscheduledDeps; }
    /// Gets the number of dependencies.
    int getDependencies() const { return Dependencies; }
    /// Initializes the number of dependencies.
    void initDependencies() { Dependencies = 0; }
    /// Increments the number of dependencies.
    void incDependencies() { Dependencies++; }

    /// Gets scheduling region ID.
    int getSchedulingRegionID() const { return SchedulingRegionID; }

    /// Gets the instruction.
    Instruction *getInst() const { return Inst; }

    /// Gets the list of memory dependencies.
    ArrayRef<ScheduleData *> getMemoryDependencies() const {
      return MemoryDependencies;
    }
    /// Adds a memory dependency.
    void addMemoryDependency(ScheduleData *Dep) {
      MemoryDependencies.push_back(Dep);
    }
    /// Gets the list of control dependencies.
    ArrayRef<ScheduleData *> getControlDependencies() const {
      return ControlDependencies;
    }
    /// Adds a control dependency.
    void addControlDependency(ScheduleData *Dep) {
      ControlDependencies.push_back(Dep);
    }
    /// Gets/sets the next load/store instruction in the block.
    ScheduleData *getNextLoadStore() const { return NextLoadStore; }
    void setNextLoadStore(ScheduleData *Next) { NextLoadStore = Next; }

    void dump(raw_ostream &OS) const { OS << *Inst; }

    LLVM_DUMP_METHOD void dump() const {
      dump(dbgs());
      dbgs() << '\n';
    }

  private:
    Instruction *Inst = nullptr;

    /// Single linked list of all memory instructions (e.g. load, store, call)
    /// in the block - until the end of the scheduling region.
    ScheduleData *NextLoadStore = nullptr;

    /// The dependent memory instructions.
    /// This list is derived on demand in calculateDependencies().
    SmallVector<ScheduleData *> MemoryDependencies;

    /// List of instructions which this instruction could be control dependent
    /// on.  Allowing such nodes to be scheduled below this one could introduce
    /// a runtime fault which didn't exist in the original program.
    /// ex: this is a load or udiv following a readonly call which inf loops
    SmallVector<ScheduleData *> ControlDependencies;

    /// This ScheduleData is in the current scheduling region if this matches
    /// the current SchedulingRegionID of BlockScheduling.
    int SchedulingRegionID = 0;

    /// The number of dependencies. Constitutes of the number of users of the
    /// instruction plus the number of dependent memory instructions (if any).
    /// This value is calculated on demand.
    /// If InvalidDeps, the number of dependencies is not calculated yet.
    int Dependencies = InvalidDeps;

    /// The number of dependencies minus the number of dependencies of scheduled
    /// instructions. As soon as this is zero, the instruction/bundle gets ready
    /// for scheduling.
    /// Note that this is negative as long as Dependencies is not calculated.
    int UnscheduledDeps = InvalidDeps;
  };

#ifndef NDEBUG
  friend inline raw_ostream &operator<<(raw_ostream &OS,
                                        const BoUpSLP::ScheduleData &SD) {
    SD.dump(OS);
    return OS;
  }
#endif

  class ScheduleBundle final : public ScheduleEntity {
    /// The schedule data for the instructions in the bundle.
    SmallVector<ScheduleEntity *> Bundle;
    /// True if this bundle is valid.
    bool IsValid = true;
    /// The TreeEntry that this instruction corresponds to.
    TreeEntry *TE = nullptr;
    ScheduleBundle(bool IsValid)
        : ScheduleEntity(Kind::ScheduleBundle), IsValid(IsValid) {}

  public:
    ScheduleBundle() : ScheduleEntity(Kind::ScheduleBundle) {}
    static bool classof(const ScheduleEntity *Entity) {
      return Entity->getKind() == Kind::ScheduleBundle;
    }

    /// Verify basic self consistency properties
    void verify() const {
      for (const ScheduleEntity *SD : Bundle) {
        if (SD->hasValidDependencies()) {
          assert(SD->getUnscheduledDeps() <= SD->getDependencies() &&
                 "invariant");
        } else {
          assert(SD->getUnscheduledDeps() == SD->getDependencies() &&
                 "invariant");
        }

        if (isScheduled()) {
          assert(SD->hasValidDependencies() && SD->getUnscheduledDeps() == 0 &&
                 "unexpected scheduled state");
        }
      }
    }

    /// Returns the number of unscheduled dependencies in the bundle.
    int unscheduledDepsInBundle() const {
      assert(*this && "bundle must not be empty");
      int Sum = 0;
      for (const ScheduleEntity *BundleMember : Bundle) {
        if (BundleMember->getUnscheduledDeps() == ScheduleData::InvalidDeps)
          return ScheduleData::InvalidDeps;
        Sum += BundleMember->getUnscheduledDeps();
      }
      return Sum;
    }

    /// Returns true if the dependency information has been calculated.
    /// Note that depenendency validity can vary between instructions within
    /// a single bundle.
    bool hasValidDependencies() const {
      return all_of(Bundle, [](const ScheduleEntity *SD) {
        return SD->hasValidDependencies();
      });
    }

    /// Returns true if it is ready for scheduling, i.e. it has no more
    /// unscheduled depending instructions/bundles.
    bool isReady() const {
      assert(*this && "bundle must not be empty");
      return unscheduledDepsInBundle() == 0 && !isScheduled();
    }

    /// Returns the bundle of scheduling data, associated with the current
    /// instruction.
    ArrayRef<ScheduleEntity *> getBundle() { return Bundle; }
    ArrayRef<const ScheduleEntity *> getBundle() const { return Bundle; }
    /// Adds an instruction to the bundle.
    void add(ScheduleEntity *SD) { Bundle.push_back(SD); }

    /// Gets/sets the associated tree entry.
    void setTreeEntry(TreeEntry *TE) { this->TE = TE; }
    TreeEntry *getTreeEntry() const { return TE; }

    static ScheduleBundle invalid() { return {false}; }

    operator bool() const { return IsValid; }

#ifndef NDEBUG
    void dump(raw_ostream &OS) const {
      if (!*this) {
        OS << "[]";
        return;
      }
      OS << '[';
      interleaveComma(Bundle, OS, [&](const ScheduleEntity *SD) {
        if (isa<ScheduleCopyableData>(SD))
          OS << "<Copyable>";
        OS << *SD->getInst();
      });
      OS << ']';
    }

    LLVM_DUMP_METHOD void dump() const {
      dump(dbgs());
      dbgs() << '\n';
    }
#endif // NDEBUG
  };

#ifndef NDEBUG
  friend inline raw_ostream &operator<<(raw_ostream &OS,
                                        const BoUpSLP::ScheduleBundle &Bundle) {
    Bundle.dump(OS);
    return OS;
  }
#endif

  /// Contains all scheduling relevant data for the copyable instruction.
  /// It models the virtual instructions, supposed to replace the original
  /// instructions. E.g., if instruction %0 = load is a part of the bundle [%0,
  /// %1], where %1 = add, then the ScheduleCopyableData models virtual
  /// instruction %virt = add %0, 0.
  class ScheduleCopyableData final : public ScheduleEntity {
    /// The source schedule data for the instruction.
    Instruction *Inst = nullptr;
    /// The edge information for the instruction.
    const EdgeInfo EI;
    /// This ScheduleData is in the current scheduling region if this matches
    /// the current SchedulingRegionID of BlockScheduling.
    int SchedulingRegionID = 0;
    /// Bundle, this data is part of.
    ScheduleBundle &Bundle;

  public:
    ScheduleCopyableData(int BlockSchedulingRegionID, Instruction *I,
                         const EdgeInfo &EI, ScheduleBundle &Bundle)
        : ScheduleEntity(Kind::ScheduleCopyableData), Inst(I), EI(EI),
          SchedulingRegionID(BlockSchedulingRegionID), Bundle(Bundle) {}
    static bool classof(const ScheduleEntity *Entity) {
      return Entity->getKind() == Kind::ScheduleCopyableData;
    }

    /// Returns true if the dependency information has been calculated.
    /// Note that depenendency validity can vary between instructions within
    /// a single bundle.
    bool hasValidDependencies() const {
      return Dependencies != ScheduleData::InvalidDeps;
    }

    /// Returns true if it is ready for scheduling, i.e. it has no more
    /// unscheduled depending instructions/bundles.
    bool isReady() const { return UnscheduledDeps == 0 && !IsScheduled; }

    /// Modifies the number of unscheduled dependencies for this instruction,
    /// and returns the number of remaining dependencies for the containing
    /// bundle.
    int incrementUnscheduledDeps(int Incr) {
      assert(hasValidDependencies() &&
             "increment of unscheduled deps would be meaningless");
      UnscheduledDeps += Incr;
      assert(UnscheduledDeps >= 0 && "invariant");
      return UnscheduledDeps;
    }

    /// Sets the number of unscheduled dependencies to the number of
    /// dependencies.
    void resetUnscheduledDeps() { UnscheduledDeps = Dependencies; }

    /// Gets the number of unscheduled dependencies.
    int getUnscheduledDeps() const { return UnscheduledDeps; }
    /// Gets the number of dependencies.
    int getDependencies() const { return Dependencies; }
    /// Initializes the number of dependencies.
    void initDependencies() { Dependencies = 0; }
    /// Increments the number of dependencies.
    void incDependencies() { Dependencies++; }

    /// Gets scheduling region ID.
    int getSchedulingRegionID() const { return SchedulingRegionID; }

    /// Gets the instruction.
    Instruction *getInst() const { return Inst; }

    /// Clears all dependency information.
    void clearDependencies() {
      Dependencies = ScheduleData::InvalidDeps;
      UnscheduledDeps = ScheduleData::InvalidDeps;
      IsScheduled = false;
    }

    /// Gets the edge information.
    const EdgeInfo &getEdgeInfo() const { return EI; }

    /// Gets the bundle.
    ScheduleBundle &getBundle() { return Bundle; }
    const ScheduleBundle &getBundle() const { return Bundle; }

#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
    void dump(raw_ostream &OS) const { OS << "[Copyable]" << *getInst(); }

    LLVM_DUMP_METHOD void dump() const {
      dump(dbgs());
      dbgs() << '\n';
    }
#endif // !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)

  private:
    /// true, if it has valid dependency information. These nodes always have
    /// only single dependency.
    int Dependencies = ScheduleData::InvalidDeps;

    /// The number of dependencies minus the number of dependencies of scheduled
    /// instructions. As soon as this is zero, the instruction/bundle gets ready
    /// for scheduling.
    /// Note that this is negative as long as Dependencies is not calculated.
    int UnscheduledDeps = ScheduleData::InvalidDeps;
  };

#ifndef NDEBUG
  friend inline raw_ostream &
  operator<<(raw_ostream &OS, const BoUpSLP::ScheduleCopyableData &SD) {
    SD.dump(OS);
    return OS;
  }
#endif

  friend struct GraphTraits<BoUpSLP *>;
  friend struct DOTGraphTraits<BoUpSLP *>;
  friend class ::HorizontalReduction;

  /// Contains all scheduling data for a basic block.
  /// It does not schedules instructions, which are not memory read/write
  /// instructions and their operands are either constants, or arguments, or
  /// phis, or instructions from others blocks, or their users are phis or from
  /// the other blocks. The resulting vector instructions can be placed at the
  /// beginning of the basic block without scheduling (if operands does not need
  /// to be scheduled) or at the end of the block (if users are outside of the
  /// block). It allows to save some compile time and memory used by the
  /// compiler.
  /// ScheduleData is assigned for each instruction in between the boundaries of
  /// the tree entry, even for those, which are not part of the graph. It is
  /// required to correctly follow the dependencies between the instructions and
  /// their correct scheduling. The ScheduleData is not allocated for the
  /// instructions, which do not require scheduling, like phis, nodes with
  /// extractelements/insertelements only or nodes with instructions, with
  /// uses/operands outside of the block.
  struct BlockScheduling {
    BlockScheduling(BasicBlock *BB, int ScheduleRegionSizeLimit)
        : BB(BB), ChunkSize(BB->size()), ChunkPos(ChunkSize),
          ScheduleRegionSizeLimit(ScheduleRegionSizeLimit) {}

    void clear() {
      ScheduledBundles.clear();
      ScheduledBundlesList.clear();
      ScheduleCopyableDataMap.clear();
      ScheduleCopyableDataMapByInst.clear();
      ScheduleCopyableDataMapByInstUser.clear();
      ScheduleCopyableDataMapByUsers.clear();
      ReadyInsts.clear();
      RecalcCopyableOperandDeps.clear();
      IgnoredMemDeps.clear();
      ScheduleStart = nullptr;
      ScheduleEnd = nullptr;
      FirstLoadStoreInRegion = nullptr;
      LastLoadStoreInRegion = nullptr;
      RegionHasStackSave = false;
      RegionHasMayThrow = false;

      // Reduce the maximum schedule region size by the size of the
      // previous scheduling run.
      ScheduleRegionSizeLimit -= ScheduleRegionSize;
      if (ScheduleRegionSizeLimit < MinScheduleRegionSize)
        ScheduleRegionSizeLimit = MinScheduleRegionSize;
      ScheduleRegionSize = 0;

      // Make a new scheduling region, i.e. all existing ScheduleData is not
      // in the new region yet.
      ++SchedulingRegionID;
    }

    ScheduleData *getScheduleData(Instruction *I) {
      if (!I)
        return nullptr;
      if (BB != I->getParent())
        // Avoid lookup if can't possibly be in map.
        return nullptr;
      ScheduleData *SD = ScheduleDataMap.lookup(I);
      if (SD && isInSchedulingRegion(*SD))
        return SD;
      return nullptr;
    }

    ScheduleData *getScheduleData(Value *V) {
      return getScheduleData(dyn_cast<Instruction>(V));
    }

    /// Returns the ScheduleCopyableData for the given edge (user tree entry and
    /// operand number) and value.
    ScheduleCopyableData *getScheduleCopyableData(const EdgeInfo &EI,
                                                  const Value *V) const {
      if (ScheduleCopyableDataMap.empty())
        return nullptr;
      auto It = ScheduleCopyableDataMap.find(std::make_pair(EI, V));
      if (It == ScheduleCopyableDataMap.end())
        return nullptr;
      ScheduleCopyableData *SD = It->getSecond().get();
      if (!isInSchedulingRegion(*SD))
        return nullptr;
      return SD;
    }

    /// Returns the ScheduleCopyableData for the given user \p User, operand
    /// number and operand \p V.
    SmallVector<ScheduleCopyableData *>
    getScheduleCopyableData(const Value *User, unsigned OperandIdx,
                            const Value *V) {
      if (ScheduleCopyableDataMapByInstUser.empty())
        return {};
      const auto It = ScheduleCopyableDataMapByInstUser.find(
          std::make_pair(std::make_pair(User, OperandIdx), V));
      if (It == ScheduleCopyableDataMapByInstUser.end())
        return {};
      SmallVector<ScheduleCopyableData *> Res;
      for (ScheduleCopyableData *SD : It->getSecond()) {
        if (isInSchedulingRegion(*SD))
          Res.push_back(SD);
      }
      return Res;
    }

    /// Returns true if all operands of the given instruction \p User are
    /// replaced by copyable data.
    /// \param User The user instruction.
    /// \param Op The operand, which might be replaced by the copyable data.
    /// \param SLP The SLP tree.
    /// \param NumOps The number of operands used. If the instruction uses the
    /// same operand several times, check for the first use, then the second,
    /// etc.
    bool areAllOperandsReplacedByCopyableData(Instruction *User,
                                              Instruction *Op, BoUpSLP &SLP,
                                              unsigned NumOps) const {
      assert(NumOps > 0 && "No operands");
      if (ScheduleCopyableDataMap.empty())
        return false;
      SmallDenseMap<TreeEntry *, unsigned> PotentiallyReorderedEntriesCount;
      ArrayRef<TreeEntry *> Entries = SLP.getTreeEntries(User);
      if (Entries.empty())
        return false;
      unsigned CurNumOps = 0;
      for (const Use &U : make_filter_range(
               User->operands(), [&](const Use &U) { return U.get() == Op; })) {
        ++CurNumOps;
        // Check all tree entries, if they have operands replaced by copyable
        // data.
        for (TreeEntry *TE : Entries) {
          unsigned Inc = 0;
          bool IsNonSchedulableWithParentPhiNode =
              TE->doesNotNeedToSchedule() && TE->UserTreeIndex &&
              TE->UserTreeIndex.UserTE->hasState() &&
              TE->UserTreeIndex.UserTE->State != TreeEntry::SplitVectorize &&
              TE->UserTreeIndex.UserTE->getOpcode() == Instruction::PHI;
          // Count the number of unique phi nodes, which are the parent for
          // parent entry, and exit, if all the unique phis are processed.
          if (IsNonSchedulableWithParentPhiNode) {
            SmallPtrSet<Value *, 4> ParentsUniqueUsers;
            const TreeEntry *ParentTE = TE->UserTreeIndex.UserTE;
            for (PHINode *PHI : make_isa_range<PHINode>(ParentTE->Scalars))
              if (ParentsUniqueUsers.insert(PHI).second &&
                  is_contained(PHI->incoming_values(), User))
                ++Inc;
          } else {
            Inc = count(TE->Scalars, User);
          }

          // Check if the user is commutative.
          // The commutatives are handled later, as their operands can be
          // reordered.
          // Same applies even for non-commutative cmps, because we can invert
          // their predicate potentially and, thus, reorder the operands.
          bool IsCommutativeUser =
              isCommutative(User) &&
              isCommutableOperand(User, User, U.getOperandNo());
          if (!IsCommutativeUser) {
            Instruction *MainOp = TE->getMatchingMainOpOrAltOp(User);
            IsCommutativeUser =
                isCommutative(MainOp, User) &&
                isCommutableOperand(MainOp, User, U.getOperandNo());
          }
          // The commutative user with the same operands can be safely
          // considered as non-commutative, operands reordering does not change
          // the semantics. Same for cmps with the same operands: inverting
          // the predicate does not change the operand columns in this case.
          assert(
              (!IsCommutativeUser ||
               (((isCommutative(User) && isCommutableOperand(User, User, 0) &&
                  isCommutableOperand(User, User, 1)) ||
                 (isCommutative(TE->getMatchingMainOpOrAltOp(User), User) &&
                  isCommutableOperand(TE->getMatchingMainOpOrAltOp(User), User,
                                      0) &&
                  isCommutableOperand(TE->getMatchingMainOpOrAltOp(User), User,
                                      1))))) &&
              "Expected commutative user with 2 first commutable operands");
          bool IsCommutativeWithSameOps =
              IsCommutativeUser && User->getOperand(0) == User->getOperand(1);
          if ((!IsCommutativeUser || IsCommutativeWithSameOps) &&
              (!isa<CmpInst>(User) ||
               User->getOperand(0) == User->getOperand(1))) {
            if (CurNumOps != NumOps)
              continue;
            // A reassociated node flattens the operand chain, so the operand
            // may be placed in any operand column rather than at the
            // instruction's operand number.
            if (TE->hasReassocScalars()) {
              bool ReplacedByCopyable = false;
              for (auto It = find(TE->Scalars, User); It != TE->Scalars.end();
                   It = find(make_range(std::next(It), TE->Scalars.end()),
                             User)) {
                int Lane = std::distance(TE->Scalars.begin(), It);
                for (unsigned OpIdx : seq<unsigned>(TE->getNumOperands()))
                  ReplacedByCopyable |=
                      TE->getOperand(OpIdx)[Lane] == Op &&
                      getScheduleCopyableData(EdgeInfo(TE, OpIdx), Op);
              }
              if (ReplacedByCopyable)
                continue;
              return false;
            }
            EdgeInfo EI(TE, U.getOperandNo());
            if (getScheduleCopyableData(EI, Op))
              continue;
            return false;
          }
          // Only count the occurrence matching this call's NumOps.
          if (CurNumOps != NumOps)
            continue;
          PotentiallyReorderedEntriesCount.try_emplace(TE, 0)
              .first->getSecond() += Inc;
        }
      }
      if (PotentiallyReorderedEntriesCount.empty())
        return true;
      // Check the commutative/cmp entries.
      for (auto &P : PotentiallyReorderedEntriesCount) {
        SmallPtrSet<Value *, 4> ParentsUniqueUsers;
        bool IsNonSchedulableWithParentPhiNode =
            P.first->doesNotNeedToSchedule() && P.first->UserTreeIndex &&
            P.first->UserTreeIndex.UserTE->hasState() &&
            P.first->UserTreeIndex.UserTE->State != TreeEntry::SplitVectorize &&
            P.first->UserTreeIndex.UserTE->getOpcode() == Instruction::PHI;
        auto *It = find(P.first->Scalars, User);
        do {
          assert(It != P.first->Scalars.end() &&
                 "User is not in the tree entry");
          int Lane = std::distance(P.first->Scalars.begin(), It);
          assert(Lane >= 0 && "Lane is not found");
          if (isa<StoreInst, InsertValueInst>(User) &&
              !P.first->ReorderIndices.empty())
            Lane = P.first->ReorderIndices[Lane];
          assert(Lane < static_cast<int>(P.first->Scalars.size()) &&
                 "Couldn't find extract lane");
          // Count the number of unique phi nodes, which are the parent for
          // parent entry, and exit, if all the unique phis are processed.
          if (IsNonSchedulableWithParentPhiNode) {
            const TreeEntry *ParentTE = P.first->UserTreeIndex.UserTE;
            Value *User = ParentTE->Scalars[Lane];
            if (!ParentsUniqueUsers.insert(User).second) {
              It =
                  find(make_range(std::next(It), P.first->Scalars.end()), User);
              continue;
            }
          }
          // Flattened nodes may place an operand in any column; scan all of
          // them so copyable scheduling does not double-count.
          for (unsigned OpIdx :
               seq<unsigned>(P.first->hasReassocScalars()
                                 ? P.first->getNumOperands()
                                 : getNumberOfPotentiallyCommutativeOps(
                                       P.first->getMainOp()))) {
            if (P.first->getOperand(OpIdx)[Lane] == Op &&
                getScheduleCopyableData(EdgeInfo(P.first, OpIdx), Op))
              --P.getSecond();
          }
          // If parent node is schedulable, it will be handled correctly.
          It = find(make_range(std::next(It), P.first->Scalars.end()), User);
        } while (It != P.first->Scalars.end());
      }
      return all_of(PotentiallyReorderedEntriesCount,
                    [&](const auto &P) { return P.second == NumOps - 1; });
    }

    SmallVector<ScheduleCopyableData *>
    getScheduleCopyableData(const Instruction *I) const {
      if (ScheduleCopyableDataMapByInst.empty())
        return {};
      const auto It = ScheduleCopyableDataMapByInst.find(I);
      if (It == ScheduleCopyableDataMapByInst.end())
        return {};
      SmallVector<ScheduleCopyableData *> Res;
      for (ScheduleCopyableData *SD : It->getSecond()) {
        if (isInSchedulingRegion(*SD))
          Res.push_back(SD);
      }
      return Res;
    }

    SmallVector<ScheduleCopyableData *>
    getScheduleCopyableDataUsers(const Instruction *User) const {
      if (ScheduleCopyableDataMapByUsers.empty())
        return {};
      const auto It = ScheduleCopyableDataMapByUsers.find(User);
      if (It == ScheduleCopyableDataMapByUsers.end())
        return {};
      SmallVector<ScheduleCopyableData *> Res;
      for (ScheduleCopyableData *SD : It->getSecond()) {
        if (isInSchedulingRegion(*SD))
          Res.push_back(SD);
      }
      return Res;
    }

    /// Reordering \p TE permutes its operand columns and may move an operand
    /// between the edges covered and not covered by copyable scheduling
    /// data, making the computed dependency counts stale. Mark the schedule
    /// data of \p TE's copyable-modeled operands for recalculation at the
    /// next bundle scheduling.
    void markCopyableDepsForRecalc(const TreeEntry &TE) {
      for (unsigned OpIdx : seq<unsigned>(TE.getNumOperands()))
        for (Instruction *I : make_isa_range<Instruction>(TE.getOperand(OpIdx)))
          if (ScheduleData *SD = getScheduleData(I);
              SD && !getScheduleCopyableData(I).empty())
            RecalcCopyableOperandDeps.insert(SD);
    }

    ScheduleCopyableData &addScheduleCopyableData(const EdgeInfo &EI,
                                                  Instruction *I,
                                                  int SchedulingRegionID,
                                                  ScheduleBundle &Bundle) {
      assert(!getScheduleCopyableData(EI, I) && "already in the map");
      ScheduleCopyableData *CD =
          ScheduleCopyableDataMap
              .try_emplace(std::make_pair(EI, I),
                           std::make_unique<ScheduleCopyableData>(
                               SchedulingRegionID, I, EI, Bundle))
              .first->getSecond()
              .get();
      ScheduleCopyableDataMapByInst[I].push_back(CD);
      if (EI.UserTE) {
        ArrayRef<Value *> Op = EI.UserTE->getOperand(EI.EdgeIdx);
        const auto *It = find(Op, I);
        assert(It != Op.end() && "Lane not set");
        SmallPtrSet<Instruction *, 4> Visited;
        do {
          int Lane = std::distance(Op.begin(), It);
          assert(Lane >= 0 && "Lane not set");
          if (isa<StoreInst, InsertElementInst, InsertValueInst>(
                  EI.UserTE->Scalars[Lane]) &&
              !EI.UserTE->ReorderIndices.empty())
            Lane = std::distance(EI.UserTE->ReorderIndices.begin(),
                                 find(EI.UserTE->ReorderIndices, Lane));
          assert(Lane < static_cast<int>(EI.UserTE->Scalars.size()) &&
                 "Couldn't find extract lane");
          auto *In = cast<Instruction>(EI.UserTE->Scalars[Lane]);
          if (!Visited.insert(In).second) {
            It = find(make_range(std::next(It), Op.end()), I);
            continue;
          }
          ScheduleCopyableDataMapByInstUser
              .try_emplace(std::make_pair(std::make_pair(In, EI.EdgeIdx), I))
              .first->getSecond()
              .push_back(CD);
          ScheduleCopyableDataMapByUsers.try_emplace(I)
              .first->getSecond()
              .insert(CD);
          // Remove extra deps for users, becoming non-immediate users of the
          // instruction. It may happen, if the chain of same copyable elements
          // appears in the tree. With the self-operand modeling (op(V, V)) the
          // user node has the value on more than one operand column, so its
          // copyable data releases the instruction's schedule data directly
          // and must stay a counted user.
          if (In == I) {
            unsigned NumCols = 0;
            for (unsigned OpIdx : seq<unsigned>(EI.UserTE->getNumOperands()))
              NumCols += EI.UserTE->getOperand(OpIdx)[Lane] == I;
            if (NumCols <= 1) {
              EdgeInfo UserEI = EI.UserTE->UserTreeIndex;
              if (ScheduleCopyableData *UserCD =
                      getScheduleCopyableData(UserEI, In))
                ScheduleCopyableDataMapByUsers[I].remove(UserCD);
            }
          }
          It = find(make_range(std::next(It), Op.end()), I);
        } while (It != Op.end());
      } else {
        ScheduleCopyableDataMapByUsers.try_emplace(I).first->getSecond().insert(
            CD);
      }
      return *CD;
    }

    /// Unregisters \p Bundle from its instructions and removes its copyable
    /// data. The caller must destroy the bundle and recalculate the
    /// dependencies.
    void cancelScheduling(ScheduleBundle &Bundle) {
      for (ScheduleEntity *SE : Bundle.getBundle()) {
        Instruction *I = SE->getInst();
        auto *CD = dyn_cast<ScheduleCopyableData>(SE);
        if (!CD) {
          llvm::erase(ScheduledBundles.find(I)->getSecond(), &Bundle);
          continue;
        }
        const EdgeInfo EI = CD->getEdgeInfo();
        llvm::erase(ScheduleCopyableDataMapByInst.find(I)->getSecond(), CD);
        ScheduleCopyableDataMapByUsers[I].remove(CD);
        if (EI.UserTE) {
          ArrayRef<Value *> Op = EI.UserTE->getOperand(EI.EdgeIdx);
          const auto *It = find(Op, I);
          assert(It != Op.end() && "Lane not set");
          SmallPtrSet<Instruction *, 4> Visited;
          bool HadSelfUse = false;
          do {
            int Lane = std::distance(Op.begin(), It);
            assert(Lane >= 0 && "Lane not set");
            if (isa<StoreInst, InsertElementInst, InsertValueInst>(
                    EI.UserTE->Scalars[Lane]) &&
                !EI.UserTE->ReorderIndices.empty())
              Lane = std::distance(EI.UserTE->ReorderIndices.begin(),
                                   find(EI.UserTE->ReorderIndices, Lane));
            assert(Lane < static_cast<int>(EI.UserTE->Scalars.size()) &&
                   "Couldn't find extract lane");
            auto *In = cast<Instruction>(EI.UserTE->Scalars[Lane]);
            if (!Visited.insert(In).second) {
              It = find(make_range(std::next(It), Op.end()), I);
              continue;
            }
            HadSelfUse |= In == I;
            auto ByUserIt = ScheduleCopyableDataMapByInstUser.find(
                std::make_pair(std::make_pair(In, EI.EdgeIdx), I));
            assert(ByUserIt != ScheduleCopyableDataMapByInstUser.end() &&
                   is_contained(ByUserIt->getSecond(), CD) &&
                   "copyable data is not registered for the user");
            llvm::erase(ByUserIt->getSecond(), CD);
            It = find(make_range(std::next(It), Op.end()), I);
          } while (It != Op.end());
          // Restore the parent-edge copyable data as a user of I only if the
          // cancelled data displaced it at creation (chained copyable
          // self-use); otherwise the extra user dependency is never released.
          if (HadSelfUse) {
            EdgeInfo UserEI = EI.UserTE->UserTreeIndex;
            if (ScheduleCopyableData *UserCD =
                    getScheduleCopyableData(UserEI, I))
              ScheduleCopyableDataMapByUsers[I].insert(UserCD);
          }
        }
        if (ScheduleCopyableDataMapByUsers[I].empty())
          ScheduleCopyableDataMapByUsers.erase(I);
        ScheduleCopyableDataMap.erase(std::make_pair(EI, I));
      }
    }

    /// Clears the dependencies of all schedule data in the scheduling region.
    void clearDependencies() {
      for_each(ScheduleDataMap, [&](auto &P) {
        if (BB != P.first->getParent())
          return;
        ScheduleData *SD = P.second;
        if (isInSchedulingRegion(*SD))
          SD->clearDependencies();
      });
      for_each(ScheduleCopyableDataMapByInst, [&](auto &P) {
        for_each(P.second, [&](ScheduleCopyableData *SD) {
          if (isInSchedulingRegion(*SD))
            SD->clearDependencies();
        });
      });
    }

    ArrayRef<ScheduleBundle *> getScheduleBundles(Value *V) const {
      auto *I = dyn_cast<Instruction>(V);
      if (!I)
        return {};
      auto It = ScheduledBundles.find(I);
      if (It == ScheduledBundles.end())
        return {};
      return It->getSecond();
    }

    /// Returns true if the entity is in the scheduling region.
    bool isInSchedulingRegion(const ScheduleEntity &SD) const {
      if (const auto *Data = dyn_cast<ScheduleData>(&SD))
        return Data->getSchedulingRegionID() == SchedulingRegionID;
      if (const auto *CD = dyn_cast<ScheduleCopyableData>(&SD))
        return CD->getSchedulingRegionID() == SchedulingRegionID;
      return all_of(cast<ScheduleBundle>(SD).getBundle(),
                    [&](const ScheduleEntity *BundleMember) {
                      return isInSchedulingRegion(*BundleMember);
                    });
    }

    /// Marks an instruction as scheduled and puts all dependent ready
    /// instructions into the ready-list.
    template <typename ReadyListType>
    void schedule(const BoUpSLP &R, const InstructionsState &S,
                  const EdgeInfo &EI, ScheduleEntity *Data,
                  ReadyListType &ReadyList) {
      auto ProcessBundleMember = [&](ScheduleEntity *BundleMember,
                                     ArrayRef<ScheduleBundle *> Bundles) {
        // Handle the def-use chain dependencies.

        // Decrement the unscheduled counter and insert to ready list if ready.
        auto DecrUnsched = [&](auto *Data, bool IsControl = false) {
          if ((IsControl || Data->hasValidDependencies()) &&
              Data->incrementUnscheduledDeps(-1) == 0) {
            // There are no more unscheduled dependencies after
            // decrementing, so we can put the dependent instruction
            // into the ready list.
            SmallVector<ScheduleBundle *, 1> CopyableBundle;
            ArrayRef<ScheduleBundle *> Bundles;
            if (auto *CD = dyn_cast<ScheduleCopyableData>(Data)) {
              CopyableBundle.push_back(&CD->getBundle());
              Bundles = CopyableBundle;
            } else {
              Bundles = getScheduleBundles(Data->getInst());
            }
            if (!Bundles.empty()) {
              for (ScheduleBundle *Bundle : Bundles) {
                if (Bundle->unscheduledDepsInBundle() == 0) {
                  assert(!Bundle->isScheduled() &&
                         "already scheduled bundle gets ready");
                  ReadyList.insert(Bundle);
                  LLVM_DEBUG(dbgs()
                             << "SLP:    gets ready: " << *Bundle << "\n");
                }
              }
              return;
            }
            assert(!Data->isScheduled() &&
                   "already scheduled bundle gets ready");
            assert(!isa<ScheduleCopyableData>(Data) &&
                   "Expected non-copyable data");
            ReadyList.insert(Data);
            LLVM_DEBUG(dbgs() << "SLP:    gets ready: " << *Data << "\n");
          }
        };

        auto DecrUnschedForInst = [&](Instruction *User, unsigned OpIdx,
                                      Instruction *I) {
          if (!ScheduleCopyableDataMap.empty()) {
            SmallVector<ScheduleCopyableData *> CopyableData =
                getScheduleCopyableData(User, OpIdx, I);
            bool ReleasedAsCopyable = false;
            // Copyable elements modeled on a copyable user lane depend on
            // the user's copyable scheduling data, not on the user itself,
            // and are released when that copyable data is scheduled. The
            // user's own schedule data still carries the def-use dependency
            // in this case, so it must be released below.
            auto IsNotCopyable = [&](ScheduleCopyableData *CD) {
              return !CD->getEdgeInfo().UserTE->isCopyableElement(User);
            };
            for (ScheduleCopyableData *CD :
                 make_filter_range(CopyableData, IsNotCopyable)) {
              DecrUnsched(CD, /*IsControl=*/false);
              ReleasedAsCopyable = true;
            }
            if (ReleasedAsCopyable)
              return;
          }
          if (ScheduleData *OpSD = getScheduleData(I))
            DecrUnsched(OpSD, /*IsControl=*/false);
        };

        // If BundleMember is a vector bundle, its operands may have been
        // reordered during buildTree(). We therefore need to get its operands
        // through the TreeEntry.
        if (!Bundles.empty()) {
          auto *In = BundleMember->getInst();
          // Count uses of each instruction operand.
          SmallDenseMap<const Instruction *, unsigned> OperandsUses;
          unsigned TotalOpCount = 0;
          if (isa<ScheduleCopyableData>(BundleMember)) {
            // Copyable data is used only once (uses itself).
            TotalOpCount = OperandsUses[In] = 1;
          } else {
            for (const Use &U : In->operands()) {
              if (auto *I = dyn_cast<Instruction>(U.get())) {
                auto Res = OperandsUses.try_emplace(I, 0);
                unsigned ExtraDeps = 1;
                // Count all expanded operands in the binops.
                for (ScheduleBundle *Bundle : Bundles) {
                  if (const TreeEntry *TE = Bundle->getTreeEntry()) {
                    if (TE->isExpandedBinOp(In))
                      ++ExtraDeps;
                  } else if (S.isExpandedBinOp(In)) {
                    ++ExtraDeps;
                  }
                }
                Res.first->getSecond() += ExtraDeps;
                TotalOpCount += ExtraDeps;
              }
            }
          }
          // Tracks whether the bundle member instruction itself shows up in
          // some operand column of its node (only copyable elements modeled
          // through their own operands, like absorbed fmuls, do not).
          bool FoundInOpColumns = false;
          // Decrement the unscheduled counter and insert to ready list if
          // ready.
          auto DecrUnschedForInst =
              [&](Instruction *I, TreeEntry *UserTE, unsigned OpIdx,
                  SmallDenseSet<std::pair<const ScheduleEntity *, unsigned>>
                      &Checked,
                  bool IsExpandedOperand = false,
                  bool CopyableDepsOnly = false) {
                if (!ScheduleCopyableDataMap.empty()) {
                  const EdgeInfo EI = {UserTE, OpIdx};
                  if (ScheduleCopyableData *CD =
                          getScheduleCopyableData(EI, I)) {
                    if (!Checked.insert(std::make_pair(CD, OpIdx)).second)
                      return;
                    DecrUnsched(CD, /*IsControl=*/false);
                    return;
                  }
                }
                if (CopyableDepsOnly)
                  return;
                auto It = OperandsUses.find(I);
                if (It == OperandsUses.end()) {
                  // Column value may be a peeled intermediate, not a direct
                  // operand of In; its deps are released when it is scheduled.
                  LLVM_DEBUG(dbgs() << "SLP:   operand " << *I
                                    << " not modeled as a direct operand of "
                                    << *In << ", skipping.\n");
                  return;
                }
                if (It->second > 0) {
                  if (ScheduleData *OpSD = getScheduleData(I)) {
                    if (!IsExpandedOperand &&
                        !Checked.insert(std::make_pair(OpSD, OpIdx)).second)
                      return;
                    --It->getSecond();
                    assert(TotalOpCount > 0 && "No more operands to decrement");
                    --TotalOpCount;
                    DecrUnsched(OpSD, /*IsControl=*/false);
                  } else {
                    --It->getSecond();
                    assert(TotalOpCount > 0 && "No more operands to decrement");
                    --TotalOpCount;
                  }
                }
              };

          SmallDenseSet<std::pair<const ScheduleEntity *, unsigned>> Checked;
          for (ScheduleBundle *Bundle : Bundles) {
            if (ScheduleCopyableDataMap.empty() && TotalOpCount == 0)
              break;
            SmallPtrSet<Value *, 4> ParentsUniqueUsers;
            // Need to search for the lane since the tree entry can be
            // reordered.
            auto *It = find(Bundle->getTreeEntry()->Scalars, In);
            bool IsNonSchedulableWithParentPhiNode =
                Bundle->getTreeEntry()->doesNotNeedToSchedule() &&
                Bundle->getTreeEntry()->UserTreeIndex &&
                Bundle->getTreeEntry()->UserTreeIndex.UserTE->hasState() &&
                Bundle->getTreeEntry()->UserTreeIndex.UserTE->State !=
                    TreeEntry::SplitVectorize &&
                Bundle->getTreeEntry()->UserTreeIndex.UserTE->getOpcode() ==
                    Instruction::PHI;
            do {
              int Lane =
                  std::distance(Bundle->getTreeEntry()->Scalars.begin(), It);
              assert(Lane >= 0 && "Lane not set");
              if (isa<StoreInst, InsertValueInst>(In) &&
                  !Bundle->getTreeEntry()->ReorderIndices.empty())
                Lane = Bundle->getTreeEntry()->ReorderIndices[Lane];
              assert(Lane < static_cast<int>(
                                Bundle->getTreeEntry()->Scalars.size()) &&
                     "Couldn't find extract lane");

              // Since vectorization tree is being built recursively this
              // assertion ensures that the tree entry has all operands set
              // before reaching this code. Couple of exceptions known at the
              // moment are extracts where their second (immediate) operand is
              // not added. Since immediates do not affect scheduler behavior
              // this is considered okay.
              assert(
                  In &&
                  (isa<ExtractValueInst, ExtractElementInst, CallBase>(In) ||
                   In->getNumOperands() ==
                       Bundle->getTreeEntry()->getNumOperands() ||
                   (isa<ZExtInst>(In) && Bundle->getTreeEntry()->getOpcode() ==
                                             Instruction::Select) ||
                   Bundle->getTreeEntry()->isCopyableElement(In) ||
                   Bundle->getTreeEntry()->hasReassocScalars()) &&
                  "Missed TreeEntry operands?");

              // Count the number of unique phi nodes, which are the parent
              // entry, and handle the non-copyable deps only on the first lane
              // for each such phi. Copyable deps are counted per operand column
              // lane and are released on every lane.
              bool CopyableDepsOnly =
                  IsNonSchedulableWithParentPhiNode &&
                  !ParentsUniqueUsers
                       .insert(Bundle->getTreeEntry()
                                   ->UserTreeIndex.UserTE->Scalars[Lane])
                       .second;

              // A blended-load operand node is the synthetic blend mask, not an
              // IR operand of the load. Use the real pointer operand for
              // scheduling so the def-use counters stay balanced; the mask is
              // available earlier through the pointer's select.
              bool IsBlended = Bundle->getTreeEntry()->State ==
                               TreeEntry::BlendedLoadVectorize;
              for (unsigned OpIdx :
                   seq<unsigned>(Bundle->getTreeEntry()->getNumOperands()))
                if (auto *I = dyn_cast<Instruction>(
                        IsBlended ? In->getOperand(OpIdx)
                                  : Bundle->getTreeEntry()->getOperand(
                                        OpIdx)[Lane])) {
                  FoundInOpColumns |= (I == In) && !CopyableDepsOnly;
                  LLVM_DEBUG(dbgs() << "SLP:   check for readiness (def): "
                                    << *I << "\n");
                  DecrUnschedForInst(
                      I, Bundle->getTreeEntry(), OpIdx, Checked,
                      Bundle->getTreeEntry()->isExpandedOperand(In, OpIdx),
                      /*CopyableDepsOnly=*/CopyableDepsOnly);
                }
              // If parent node is schedulable, it will be handled correctly.
              if (Bundle->getTreeEntry()->isCopyableElement(In))
                break;
              It = std::find(std::next(It),
                             Bundle->getTreeEntry()->Scalars.end(), In);
            } while (It != Bundle->getTreeEntry()->Scalars.end());
          }
          // A copyable element absorbed into its user modeling (e.g. a
          // copyable fmul turned into fmuladd(a, b, -0.0)) does not appear in
          // the operand columns of its own node, so the scan above never
          // releases the schedule data of the copyable instruction itself.
          // Release it here to keep the unscheduled-deps counters balanced,
          // consuming its self-use count so the reassociated-operand release
          // below cannot release the same schedule data twice.
          if (isa<ScheduleCopyableData>(BundleMember) && !FoundInOpColumns) {
            auto UseIt = OperandsUses.find(In);
            if (UseIt != OperandsUses.end() && UseIt->second > 0) {
              --UseIt->getSecond();
              --TotalOpCount;
            }
            if (ScheduleData *OpSD = getScheduleData(In))
              DecrUnsched(OpSD, /*IsControl=*/false);
          }
          // Vector intrinsics may keep some arguments scalar (e.g. the
          // exponent of llvm.powi). Such scalar arguments are not modeled as
          // tree-entry operands, so the per-lane loop above never releases the
          // dependency that calculateDependencies() registered for the
          // definition feeding such an argument. Release it here to keep the
          // unscheduled-deps counters balanced; otherwise the operand's bundle
          // may never become ready and scheduling would assert.
          if (TotalOpCount > 0) {
            if (auto *CI = dyn_cast<CallInst>(In)) {
              Intrinsic::ID ID = getVectorIntrinsicIDForCall(CI, R.TLI);
              for (unsigned ArgIdx : seq<unsigned>(CI->arg_size())) {
                if (!isVectorIntrinsicWithScalarOpAtArg(ID, ArgIdx, R.TTI))
                  continue;
                auto *OpI = dyn_cast<Instruction>(CI->getArgOperand(ArgIdx));
                if (!OpI)
                  continue;
                auto UseIt = OperandsUses.find(OpI);
                if (UseIt == OperandsUses.end() || UseIt->second == 0)
                  continue;
                --UseIt->getSecond();
                --TotalOpCount;
                if (ScheduleData *OpSD = getScheduleData(OpI)) {
                  LLVM_DEBUG(dbgs()
                             << "SLP:   check for readiness (scalar arg): "
                             << *OpI << "\n");
                  DecrUnsched(OpSD, /*IsControl=*/false);
                }
              }
            }
            // Peeled intermediates stay as direct operands but drop out of
            // operand columns; release their scheduling deps here.
            for (const ScheduleBundle *Bundle : Bundles) {
              if (TotalOpCount == 0)
                break;
              TreeEntry *TE = Bundle->getTreeEntry();
              if (!TE->hasReassocScalars())
                continue;
              for (Instruction *OpI :
                   make_isa_range<Instruction>(TE->getReassocScalars())) {
                auto UseIt = OperandsUses.find(OpI);
                if (UseIt == OperandsUses.end() || UseIt->second == 0)
                  continue;
                LLVM_DEBUG(dbgs() << "SLP:   check for readiness "
                                     "(reassociated operand): "
                                  << *OpI << "\n");
                // Copyable deps may live on per-edge ScheduleCopyableData.
                bool ReleasedAsCopyable = false;
                if (!ScheduleCopyableDataMap.empty()) {
                  auto MatchesOp = [&](const Use &U) { return U.get() == OpI; };
                  for (const Use &U :
                       make_filter_range(In->operands(), MatchesOp)) {
                    for (ScheduleCopyableData *CD :
                         getScheduleCopyableData(In, U.getOperandNo(), OpI)) {
                      // Deps of reassoc scalars modeled as copyable tree
                      // operands are released by the operand scan above;
                      // release each remaining dep only once.
                      if (Checked.insert(std::make_pair(CD, U.getOperandNo()))
                              .second)
                        DecrUnsched(CD, /*IsControl=*/false);
                    }
                  }
                  // The dep is released through copyable data only if this
                  // very entry models the scalar as a copyable operand on one
                  // of its edges, mirroring the dependency calculation;
                  // copyable data on some other entry's edge does not cover
                  // the dep registered for this entry.
                  for (auto It = find(TE->Scalars, In);
                       It != TE->Scalars.end() && !ReleasedAsCopyable;
                       It = find(make_range(std::next(It), TE->Scalars.end()),
                                 In)) {
                    int Lane = std::distance(TE->Scalars.begin(), It);
                    for (unsigned OpIdx : seq<unsigned>(TE->getNumOperands()))
                      ReleasedAsCopyable |=
                          TE->getOperand(OpIdx)[Lane] == OpI &&
                          getScheduleCopyableData(EdgeInfo(TE, OpIdx), OpI);
                  }
                }
                if (!ReleasedAsCopyable) {
                  if (ScheduleData *OpSD = getScheduleData(OpI))
                    for (unsigned I = 0, E = UseIt->second; I != E; ++I)
                      DecrUnsched(OpSD, /*IsControl=*/false);
                }
                TotalOpCount -= UseIt->second;
                UseIt->second = 0;
              }
            }
          }
        } else {
          // If BundleMember is a stand-alone instruction, no operand reordering
          // has taken place, so we directly access its operands.
          for (Use &U : BundleMember->getInst()->operands()) {
            if (auto *I = dyn_cast<Instruction>(U.get())) {
              LLVM_DEBUG(dbgs()
                         << "SLP:   check for readiness (def): " << *I << "\n");
              DecrUnschedForInst(BundleMember->getInst(), U.getOperandNo(), I);
            }
          }
        }
        // Handle the memory dependencies.
        auto *SD = dyn_cast<ScheduleData>(BundleMember);
        if (!SD)
          return;
        SmallPtrSet<const ScheduleData *, 4> VisitedMemory;
        for (ScheduleData *MemoryDep : SD->getMemoryDependencies()) {
          if (!VisitedMemory.insert(MemoryDep).second)
            continue;
          // There are no more unscheduled dependencies after decrementing,
          // so we can put the dependent instruction into the ready list.
          LLVM_DEBUG(dbgs() << "SLP:   check for readiness (mem): "
                            << *MemoryDep << "\n");
          DecrUnsched(MemoryDep);
        }
        // Handle the control dependencies.
        SmallPtrSet<const ScheduleData *, 4> VisitedControl;
        for (ScheduleData *Dep : SD->getControlDependencies()) {
          if (!VisitedControl.insert(Dep).second)
            continue;
          // There are no more unscheduled dependencies after decrementing,
          // so we can put the dependent instruction into the ready list.
          LLVM_DEBUG(dbgs()
                     << "SLP:   check for readiness (ctrl): " << *Dep << "\n");
          DecrUnsched(Dep, /*IsControl=*/true);
        }
      };
      if (auto *SD = dyn_cast<ScheduleData>(Data)) {
        SD->setScheduled(/*Scheduled=*/true);
        LLVM_DEBUG(dbgs() << "SLP:   schedule " << *SD << "\n");
        SmallVector<std::unique_ptr<ScheduleBundle>> PseudoBundles;
        SmallVector<ScheduleBundle *> Bundles;
        Instruction *In = SD->getInst();
        ArrayRef<TreeEntry *> Entries = R.getTreeEntries(In);
        if (!Entries.empty()) {
          for (TreeEntry *TE : make_filter_range(Entries, [&](TreeEntry *TE) {
                 return isa<ExtractValueInst, ExtractElementInst, CallBase>(
                            In) ||
                        In->getNumOperands() == TE->getNumOperands() ||
                        TE->hasReassocScalars();
               })) {
            auto &BundlePtr =
                PseudoBundles.emplace_back(std::make_unique<ScheduleBundle>());
            BundlePtr->setTreeEntry(TE);
            BundlePtr->add(SD);
            Bundles.push_back(BundlePtr.get());
          }
        }
        ProcessBundleMember(SD, Bundles);
      } else {
        ScheduleBundle &Bundle = *cast<ScheduleBundle>(Data);
        Bundle.setScheduled(/*Scheduled=*/true);
        LLVM_DEBUG(dbgs() << "SLP:   schedule " << Bundle << "\n");
        auto AreAllBundlesScheduled =
            [&](const ScheduleEntity *SD,
                ArrayRef<ScheduleBundle *> SDBundles) {
              if (isa<ScheduleCopyableData>(SD))
                return true;
              return !SDBundles.empty() &&
                     all_of(SDBundles, [&](const ScheduleBundle *SDBundle) {
                       return SDBundle->isScheduled();
                     });
            };
        for (ScheduleEntity *SD : Bundle.getBundle()) {
          ArrayRef<ScheduleBundle *> SDBundles;
          if (!isa<ScheduleCopyableData>(SD))
            SDBundles = getScheduleBundles(SD->getInst());
          if (!AreAllBundlesScheduled(SD, SDBundles))
            continue;
          SD->setScheduled(/*Scheduled=*/true);
          Instruction *In = SD->getInst();
          // The instruction may also belong to tree entries that do not need
          // scheduling (e.g. all their values are used outside the block), so
          // no schedule bundle is registered for them. Such an entry can still
          // model one of this instruction's operands as a copyable element, or
          // model the instruction itself as an expanded binop, registered on
          // that non-scheduled parent edge. That dependency would never be
          // decremented when the instruction is scheduled through a different
          // bundle, leaving the operand's bundle permanently unscheduled and
          // tripping the unscheduled-deps assertion. Add pseudo-bundles for
          // these missing tree entries, so their operand dependencies are
          // decremented here as well. Real operand dependencies are protected
          // against double counting by the per-operand use counter.
          if (isa<ScheduleCopyableData>(SD) ||
              (ScheduleCopyableDataMap.empty() &&
               none_of(R.getTreeEntries(In), [&](const TreeEntry *TE) {
                 return TE->isExpandedBinOp(In);
               }))) {
            ProcessBundleMember(SD, isa<ScheduleCopyableData>(SD) ? &Bundle
                                                                  : SDBundles);
            continue;
          }
          SmallVector<std::unique_ptr<ScheduleBundle>> PseudoBundles;
          SmallVector<ScheduleBundle *> AllBundles(SDBundles.begin(),
                                                   SDBundles.end());
          for (TreeEntry *TE :
               make_filter_range(R.getTreeEntries(In), [&](TreeEntry *TE) {
                 return !TE->isCopyableElement(In);
               })) {
            if (!isa<ExtractValueInst, ExtractElementInst, CallBase>(In) &&
                In->getNumOperands() != TE->getNumOperands() &&
                !TE->hasReassocScalars())
              continue;
            if (any_of(SDBundles, [&](const ScheduleBundle *SDBundle) {
                  return SDBundle->getTreeEntry() == TE;
                }))
              continue;
            ScheduleBundle &PseudoBundle =
                *PseudoBundles.emplace_back(std::make_unique<ScheduleBundle>());
            PseudoBundle.setTreeEntry(TE);
            PseudoBundle.add(SD);
            AllBundles.push_back(&PseudoBundle);
          }
          ProcessBundleMember(SD, AllBundles);
        }
      }
    }

    /// Verify basic self consistency properties of the data structure.
    void verify() {
      if (!ScheduleStart)
        return;

      assert(ScheduleStart->getParent() == ScheduleEnd->getParent() &&
             ScheduleStart->comesBefore(ScheduleEnd) &&
             "Not a valid scheduling region?");

      for (auto *I = ScheduleStart; I != ScheduleEnd; I = I->getNextNode()) {
        ArrayRef<ScheduleBundle *> Bundles = getScheduleBundles(I);
        if (!Bundles.empty()) {
          for (ScheduleBundle *Bundle : Bundles) {
            assert(isInSchedulingRegion(*Bundle) &&
                   "primary schedule data not in window?");
            Bundle->verify();
          }
          continue;
        }
        auto *SD = getScheduleData(I);
        if (!SD)
          continue;
        assert(isInSchedulingRegion(*SD) &&
               "primary schedule data not in window?");
        SD->verify();
      }

      assert(all_of(ReadyInsts,
                    [](const ScheduleEntity *Bundle) {
                      return Bundle->isReady();
                    }) &&
             "item in ready list not ready?");
    }

    /// Put all instructions into the ReadyList which are ready for scheduling.
    template <typename ReadyListType>
    void initialFillReadyList(ReadyListType &ReadyList) {
      SmallPtrSet<ScheduleBundle *, 16> Visited;
      for (auto *I = ScheduleStart; I != ScheduleEnd; I = I->getNextNode()) {
        ScheduleData *SD = getScheduleData(I);
        if (SD && SD->hasValidDependencies() && SD->isReady()) {
          if (ArrayRef<ScheduleBundle *> Bundles = getScheduleBundles(I);
              !Bundles.empty()) {
            for (ScheduleBundle *Bundle :
                 make_filter_range(Bundles, [&](ScheduleBundle *Bundle) {
                   return Visited.insert(Bundle).second;
                 })) {
              if (Bundle->hasValidDependencies() && Bundle->isReady()) {
                ReadyList.insert(Bundle);
                LLVM_DEBUG(dbgs() << "SLP:    initially in ready list: "
                                  << *Bundle << "\n");
              }
            }
            continue;
          }
          ReadyList.insert(SD);
          LLVM_DEBUG(dbgs()
                     << "SLP:    initially in ready list: " << *SD << "\n");
        }
      }
    }

    /// Build a bundle from the ScheduleData nodes corresponding to the
    /// scalar instruction for each lane.
    /// \param VL The list of scalar instructions.
    /// \param S The state of the instructions.
    /// \param EI The edge in the SLP graph or the user node/operand number.
    ScheduleBundle &buildBundle(ArrayRef<Value *> VL,
                                const InstructionsState &S, const EdgeInfo &EI);

    /// Checks if a bundle of instructions can be scheduled, i.e. has no
    /// cyclic dependencies. This is only a dry-run, no instructions are
    /// actually moved at this stage.
    /// \returns the scheduling bundle. The returned Optional value is not
    /// std::nullopt if \p VL is allowed to be scheduled.
    std::optional<ScheduleBundle *>
    tryScheduleBundle(ArrayRef<Value *> VL, BoUpSLP *SLP,
                      const InstructionsState &S, const EdgeInfo &EI);

    /// Allocates schedule data chunk.
    ScheduleData *allocateScheduleDataChunks();

    /// Extends the scheduling region so that V is inside the region.
    /// \returns true if the region size is within the limit.
    bool extendSchedulingRegion(Value *V, const InstructionsState &S);

    /// Initialize the ScheduleData structures for new instructions in the
    /// scheduling region.
    void initScheduleData(Instruction *FromI, Instruction *ToI,
                          ScheduleData *PrevLoadStore,
                          ScheduleData *NextLoadStore);

    /// Updates the dependency information of a bundle and of all instructions/
    /// bundles which depend on the original bundle.
    void calculateDependencies(ScheduleBundle &Bundle, bool InsertInReadyList,
                               BoUpSLP *SLP,
                               const SmallPtrSetImpl<Value *> &ExpandedOps,
                               ArrayRef<ScheduleData *> ControlDeps = {});

    /// Sets all instruction in the scheduling region to un-scheduled.
    void resetSchedule();

    BasicBlock *BB;

    /// Simple memory allocation for ScheduleData.
    SmallVector<std::unique_ptr<ScheduleData[]>> ScheduleDataChunks;

    /// The size of a ScheduleData array in ScheduleDataChunks.
    int ChunkSize;

    /// The allocator position in the current chunk, which is the last entry
    /// of ScheduleDataChunks.
    int ChunkPos;

    /// Attaches ScheduleData to Instruction.
    /// Note that the mapping survives during all vectorization iterations, i.e.
    /// ScheduleData structures are recycled.
    SmallDenseMap<Instruction *, ScheduleData *> ScheduleDataMap;

    /// Attaches ScheduleCopyableData to EdgeInfo (UserTreeEntry + operand
    /// number) and the operand instruction, represented as copyable element.
    SmallDenseMap<std::pair<EdgeInfo, const Value *>,
                  std::unique_ptr<ScheduleCopyableData>>
        ScheduleCopyableDataMap;

    /// Represents mapping between instruction and all related
    /// ScheduleCopyableData (for all uses in the tree, represenedt as copyable
    /// element). The SLP tree may contain several representations of the same
    /// instruction.
    SmallDenseMap<const Instruction *, SmallVector<ScheduleCopyableData *>>
        ScheduleCopyableDataMapByInst;

    /// Represents mapping between user value and operand number, the operand
    /// value and all related ScheduleCopyableData. The relation is 1:n, because
    /// the same user may refernce the same operand in different tree entries
    /// and the operand may be modelled by the different copyable data element.
    SmallDenseMap<std::pair<std::pair<const Value *, unsigned>, const Value *>,
                  SmallVector<ScheduleCopyableData *>>
        ScheduleCopyableDataMapByInstUser;

    /// Represents mapping between instruction and all related
    /// ScheduleCopyableData. It represents the mapping between the actual
    /// instruction and the last copyable data element in the chain. E.g., if
    /// the graph models the following instructions:
    /// %0 = non-add instruction ...
    /// ...
    /// %4 = add %3, 1
    /// %5 = add %4, 1
    /// %6 = insertelement poison, %0, 0
    /// %7 = insertelement %6, %5, 1
    /// And the graph is modeled as:
    /// [%5, %0] -> [%4, copyable %0 <0> ] -> [%3, copyable %0 <1> ]
    ///          -> [1, 0]                 -> [%1, 0]
    ///
    /// this map will map %0 only to the copyable element <1>, which is the last
    /// user (direct user of the actual instruction). <0> uses <1>, so <1> will
    /// keep the map to <0>, not the %0.
    SmallDenseMap<const Instruction *,
                  SmallSetVector<ScheduleCopyableData *, 4>>
        ScheduleCopyableDataMapByUsers;

    /// Attaches ScheduleBundle to Instruction.
    SmallDenseMap<Instruction *, SmallVector<ScheduleBundle *>>
        ScheduledBundles;
    /// The list of ScheduleBundles.
    SmallVector<std::unique_ptr<ScheduleBundle>> ScheduledBundlesList;

    /// The ready-list for scheduling (only used for the dry-run).
    SetVector<ScheduleEntity *> ReadyInsts;

    /// The first instruction of the scheduling region.
    Instruction *ScheduleStart = nullptr;

    /// The first instruction _after_ the scheduling region.
    Instruction *ScheduleEnd = nullptr;

    /// The first memory accessing instruction in the scheduling region
    /// (can be null).
    ScheduleData *FirstLoadStoreInRegion = nullptr;

    /// The last memory accessing instruction in the scheduling region
    /// (can be null).
    ScheduleData *LastLoadStoreInRegion = nullptr;

    /// Is there an llvm.stacksave or llvm.stackrestore in the scheduling
    /// region?  Used to optimize the dependence calculation for the
    /// common case where there isn't.
    bool RegionHasStackSave = false;

    /// Used to skip the dependencies calculation for writes that are visible
    /// after unwinding.
    bool RegionHasMayThrow = false;

    /// Returns true if \p I writes memory that the caller can still see
    /// after an unwind.
    bool isWriteVisibleOnUnwind(Instruction *I) const {
      if (!RegionHasMayThrow || !I->mayWriteToMemory())
        return false;
      MemoryLocation Loc = getLocation(I);
      if (!Loc.Ptr)
        return true;
      bool RequiresNoCaptureBeforeUnwind = false;
      return !isNotVisibleOnUnwind(getUnderlyingObject(Loc.Ptr),
                                   RequiresNoCaptureBeforeUnwind) ||
             RequiresNoCaptureBeforeUnwind;
    }

    /// The current size of the scheduling region.
    int ScheduleRegionSize = 0;

    /// The maximum size allowed for the scheduling region.
    int ScheduleRegionSizeLimit;

    /// Operands that are modeled as copyable elements in a previously built
    /// vectorized node and that are used directly by another,
    /// not-yet-registered node sharing a schedulable instruction with it. Their
    /// direct dependencies must be recomputed at the next bundle scheduling,
    /// when the new node is already registered in the tree, so that the direct
    /// use is accounted for. If the new node is the last scheduled bundle and
    /// no further scheduling consumes this list, the leftover entries are
    /// dropped on the next region reset and the dependencies are recomputed
    /// against the full tree in scheduleBlock instead. A set is used to avoid
    /// recomputing the same operand more than once.
    SmallSetVector<ScheduleData *, 8> RecalcCopyableOperandDeps;

    /// Ordered pairs (Src, Dst) of memory instructions whose may-alias
    /// dependency has been dropped in favor of a runtime alias check.
    SmallDenseSet<std::pair<Instruction *, Instruction *>, 8> IgnoredMemDeps;

    /// The ID of the scheduling region. For a new vectorization iteration this
    /// is incremented which "removes" all ScheduleData from the region.
    /// Make sure that the initial SchedulingRegionID is greater than the
    /// initial SchedulingRegionID in ScheduleData (which is 0).
    int SchedulingRegionID = 1;
  };

  /// Attaches the BlockScheduling structures to basic blocks.
  MapVector<BasicBlock *, std::unique_ptr<BlockScheduling>> BlocksSchedules;

  /// Performs the "real" scheduling. Done before vectorization is actually
  /// performed in a basic block.
  void scheduleBlock(const BoUpSLP &R, BlockScheduling *BS);

  /// List of users to ignore during scheduling and that don't need extracting.
  const SmallDenseSet<Value *> *UserIgnoreList = nullptr;

  /// Narrowed reduction chain instructions, dropped together with the
  /// reduction. Subset of UserIgnoreList.
  SmallPtrSet<Value *, 4> NarrowedChainInsts;

  /// A DenseMapInfo implementation for holding DenseMaps and DenseSets of
  /// sorted SmallVectors of unsigned.
  struct OrdersTypeDenseMapInfo {
    static unsigned getHashValue(const OrdersType &V) {
      return static_cast<unsigned>(hash_combine_range(V));
    }

    static bool isEqual(const OrdersType &LHS, const OrdersType &RHS) {
      return LHS == RHS;
    }
  };

  // Analysis and block reference.
  Function *F;
  ScalarEvolution *SE;
  TargetTransformInfo *TTI;
  TargetLibraryInfo *TLI;
  LoopInfo *LI;
  DominatorTree *DT;
  AssumptionCache *AC;
  DemandedBits *DB;
  const DataLayout *DL;
  OptimizationRemarkEmitter *ORE;
  /// Cached cost-model mode for this function.
  /// If -Os/-Oz, use CodeSize. Otherwise use RecipThroughput.
  const TargetTransformInfo::TargetCostKind CostKind;

  unsigned MaxVecRegSize; // This is set by TTI or overridden by cl::opt.
  unsigned MinVecRegSize; // Set by cl::opt (default: 128).

  /// Instruction builder to construct the vectorized tree.
  IRBuilder<TargetFolder> Builder;

  /// A map of scalar integer values to the smallest bit width with which they
  /// can legally be represented. The values map to (width, signed) pairs,
  /// where "width" indicates the minimum bit width and "signed" is True if the
  /// value must be signed-extended, rather than zero-extended, back to its
  /// original width.
  DenseMap<const TreeEntry *, std::pair<uint64_t, bool>> MinBWs;

  /// A booleanized node is an i1 node registered in MinBWs to be emitted in
  /// the wide leaf type. Genuine demoted nodes never have i1 scalars (i1
  /// cannot be demoted), so an i1 node in MinBWs is always a booleanized one.
  bool isBooleanizedNode(const TreeEntry *E) const {
    auto It = MinBWs.find(E);
    return It != MinBWs.end() && E->Scalars.front()->getType()->isIntegerTy(1);
  }

  /// Final size of the reduced vector, if the current graph represents the
  /// input for the reduction and it was possible to narrow the size of the
  /// reduction.
  unsigned ReductionBitWidth = 0;

  /// Canonical graph size before the transformations.
  unsigned BaseGraphSize = 1;

  /// If the tree contains any zext/sext/trunc nodes, contains max-min pair of
  /// type sizes, used in the tree.
  std::optional<std::pair<unsigned, unsigned>> CastMaxMinBWSizes;

  /// Indices of the vectorized nodes, which supposed to be the roots of the new
  /// bitwidth analysis attempt, like trunc, IToFP or ICmp.
  DenseSet<unsigned> ExtraBitWidthNodes;
};

template <> struct llvm::DenseMapInfo<BoUpSLP::EdgeInfo> {
  using FirstInfo = DenseMapInfo<BoUpSLP::TreeEntry *>;
  using SecondInfo = DenseMapInfo<unsigned>;
  static unsigned getHashValue(const BoUpSLP::EdgeInfo &Val) {
    return detail::combineHashValue(FirstInfo::getHashValue(Val.UserTE),
                                    SecondInfo::getHashValue(Val.EdgeIdx));
  }

  static bool isEqual(const BoUpSLP::EdgeInfo &LHS,
                      const BoUpSLP::EdgeInfo &RHS) {
    return LHS == RHS;
  }
};

template <> struct llvm::GraphTraits<BoUpSLP *> {
  using TreeEntry = BoUpSLP::TreeEntry;

  /// NodeRef has to be a pointer per the GraphWriter.
  using NodeRef = TreeEntry *;

  using ContainerTy = BoUpSLP::TreeEntry::VecTreeTy;

  /// Add the VectorizableTree to the index iterator to be able to return
  /// TreeEntry pointers.
  struct ChildIteratorType
      : public iterator_adaptor_base<
            ChildIteratorType, SmallVector<BoUpSLP::EdgeInfo, 1>::iterator> {
    ContainerTy &VectorizableTree;

    ChildIteratorType(SmallVector<BoUpSLP::EdgeInfo, 1>::iterator W,
                      ContainerTy &VT)
        : ChildIteratorType::iterator_adaptor_base(W), VectorizableTree(VT) {}

    NodeRef operator*() { return I->UserTE; }
  };

  static NodeRef getEntryNode(BoUpSLP &R) { return &R.getRootNode(); }

  static ChildIteratorType child_begin(NodeRef N) {
    return {&N->UserTreeIndex, N->Container};
  }

  static ChildIteratorType child_end(NodeRef N) {
    return {&N->UserTreeIndex + 1, N->Container};
  }

  /// For the node iterator we just need to turn the TreeEntry iterator into a
  /// TreeEntry* iterator so that it dereferences to NodeRef.
  class nodes_iterator {
    using ItTy = ContainerTy::iterator;
    ItTy It;

  public:
    nodes_iterator(const ItTy &It2) : It(It2) {}
    NodeRef operator*() { return It->get(); }
    nodes_iterator operator++() {
      ++It;
      return *this;
    }
    bool operator!=(const nodes_iterator &N2) const { return N2.It != It; }
  };

  static nodes_iterator nodes_begin(BoUpSLP *R) {
    return nodes_iterator(R->VectorizableTree.begin());
  }

  static nodes_iterator nodes_end(BoUpSLP *R) {
    return nodes_iterator(R->VectorizableTree.end());
  }

  static unsigned size(BoUpSLP *R) { return R->VectorizableTree.size(); }
};

template <>
struct llvm::DOTGraphTraits<BoUpSLP *> : public DefaultDOTGraphTraits {
  using TreeEntry = BoUpSLP::TreeEntry;

  DOTGraphTraits(bool IsSimple = false) : DefaultDOTGraphTraits(IsSimple) {}

  std::string getNodeLabel(const TreeEntry *Entry, const BoUpSLP *R) {
    std::string Str;
    raw_string_ostream OS(Str);
    OS << Entry->Idx << ".\n";
    if (isSplat(Entry->Scalars))
      OS << "<splat> ";
    for (auto *V : Entry->Scalars) {
      OS << *V;
      if (llvm::any_of(R->ExternalUses, [&](const BoUpSLP::ExternalUser &EU) {
            return EU.Scalar == V;
          }))
        OS << " <extract>";
      OS << "\n";
    }
    return Str;
  }

  static std::string getNodeAttributes(const TreeEntry *Entry,
                                       const BoUpSLP *) {
    if (Entry->isGather())
      return "color=red";
    if (Entry->State == TreeEntry::ScatterVectorize ||
        Entry->State == TreeEntry::StridedVectorize ||
        Entry->State == TreeEntry::ExpandVectorize ||
        Entry->State == TreeEntry::CompressVectorize ||
        Entry->State == TreeEntry::BlendedLoadVectorize)
      return "color=blue";
    return "";
  }
};

BoUpSLP::~BoUpSLP() {
  SmallVector<WeakTrackingVH> DeadInsts;
  for (auto *I : DeletedInstructions) {
    if (!I->getParent()) {
      // Temporarily insert instruction back to erase them from parent and
      // memory later.
      if (isa<PHINode>(I))
        // Phi nodes must be the very first instructions in the block.
        I->insertBefore(F->getEntryBlock(),
                        F->getEntryBlock().getFirstNonPHIIt());
      else
        I->insertBefore(F->getEntryBlock().getTerminator()->getIterator());
      continue;
    }
    for (Instruction *Op : make_isa_range<Instruction>(I->operands()))
      if (!DeletedInstructions.count(Op) && Op->hasOneUser() &&
          wouldInstructionBeTriviallyDead(Op, TLI))
        DeadInsts.emplace_back(Op);
    I->dropAllReferences();
  }
  for (auto *I : DeletedInstructions) {
    assert(I->use_empty() &&
           "trying to erase instruction with users.");
    I->eraseFromParent();
  }

  // Cleanup any dead scalar code feeding the vectorized instructions
  RecursivelyDeleteTriviallyDeadInstructions(DeadInsts, TLI);

#ifdef EXPENSIVE_CHECKS
  // If we could guarantee that this call is not extremely slow, we could
  // remove the ifdef limitation (see PR47712).
  assert(!verifyFunction(*F, &dbgs()));
#endif
}

std::optional<BoUpSLP::OrdersType>
BoUpSLP::findReusedOrderedScalars(const BoUpSLP::TreeEntry &TE,
                                  bool TopToBottom, bool IgnoreReorder) {
  assert(TE.isGather() && "Expected gather node only.");
  // Try to find subvector extract/insert patterns and reorder only such
  // patterns.
  SmallVector<Value *> GatheredScalars(TE.Scalars.begin(), TE.Scalars.end());
  Type *ScalarTy = GatheredScalars.front()->getType();
  size_t NumScalars = GatheredScalars.size();
  if (!isValidElementType(ScalarTy, Opts.slp_revec))
    return std::nullopt;
  auto *VecTy = getWidenedType(ScalarTy, NumScalars);
  unsigned NumParts = getNumberOfParts(VecTy, ScalarTy, NumScalars);
  SmallVector<int> ExtractMask;
  SmallVector<int> Mask;
  SmallVector<SmallVector<const TreeEntry *>> Entries;
  SmallVector<std::optional<TargetTransformInfo::ShuffleKind>> ExtractShuffles =
      tryToGatherExtractElements(GatheredScalars, ExtractMask, NumParts);
  SmallVector<std::optional<TargetTransformInfo::ShuffleKind>> GatherShuffles =
      isGatherShuffledEntry(&TE, GatheredScalars, Mask, Entries, NumParts,
                            ScalarTy, /*ForOrder=*/true);
  // The internal gathers of the splat gather subtrees are not used as shuffle
  // sources, do not reorder the tree to match them.
  if (hasSplatSubtreeGather(Entries)) {
    GatherShuffles.clear();
    Entries.clear();
  }
  // No shuffled operands - ignore.
  if (GatherShuffles.empty() && ExtractShuffles.empty())
    return std::nullopt;
  OrdersType CurrentOrder(NumScalars, NumScalars);
  if (GatherShuffles.size() == 1 &&
      *GatherShuffles.front() == TTI::SK_PermuteSingleSrc &&
      Entries.front().front()->isSame(TE.Scalars)) {
    // If the full matched node in whole tree rotation - no need to consider the
    // matching order, rotating the whole tree.
    if (TopToBottom)
      return std::nullopt;
    // No need to keep the order for the same user node.
    if (Entries.front().front()->UserTreeIndex.UserTE ==
        TE.UserTreeIndex.UserTE)
      return std::nullopt;
    // No need to keep the order for the matched root node, if it can be freely
    // reordered.
    if (!IgnoreReorder && Entries.front().front()->Idx == 0)
      return std::nullopt;
    // If shuffling 2 elements only and the matching node has reverse reuses -
    // no need to count order, both work fine.
    if (!Entries.front().front()->ReuseShuffleIndices.empty() &&
        TE.getVectorFactor() == 2 && Mask.size() == 2 &&
        any_of(enumerate(Entries.front().front()->ReuseShuffleIndices),
               [](const auto &P) {
                 return P.value() % 2 != static_cast<int>(P.index()) % 2;
               }))
      return std::nullopt;

    // Perfect match in the graph, will reuse the previously vectorized
    // node. Cost is 0.
    std::iota(CurrentOrder.begin(), CurrentOrder.end(), 0);
    return CurrentOrder;
  }
  auto IsSplatMask = [](ArrayRef<int> Mask) {
    int SingleElt = PoisonMaskElem;
    return all_of(Mask, [&](int I) {
      if (SingleElt == PoisonMaskElem && I != PoisonMaskElem)
        SingleElt = I;
      return I == PoisonMaskElem || I == SingleElt;
    });
  };
  // Exclusive broadcast mask - ignore.
  if ((ExtractShuffles.empty() && IsSplatMask(Mask) &&
       (Entries.size() != 1 ||
        Entries.front().front()->ReorderIndices.empty())) ||
      (GatherShuffles.empty() && IsSplatMask(ExtractMask)))
    return std::nullopt;
  SmallBitVector ShuffledSubMasks(NumParts);
  auto TransformMaskToOrder = [&](MutableArrayRef<unsigned> CurrentOrder,
                                  ArrayRef<int> Mask, int PartSz, int NumParts,
                                  function_ref<unsigned(unsigned)> GetVF) {
    for (int I : seq<int>(NumParts)) {
      if (ShuffledSubMasks.test(I))
        continue;
      const int VF = GetVF(I);
      if (VF == 0)
        continue;
      unsigned Limit = getNumElems(CurrentOrder.size(), PartSz, I);
      MutableArrayRef<unsigned> Slice = CurrentOrder.slice(I * PartSz, Limit);
      // Shuffle of at least 2 vectors - ignore.
      if (any_of(Slice, not_equal_to(NumScalars))) {
        llvm::fill(Slice, NumScalars);
        ShuffledSubMasks.set(I);
        continue;
      }
      // Try to include as much elements from the mask as possible.
      int FirstMin = INT_MAX;
      int SecondVecFound = false;
      for (int K : seq<int>(Limit)) {
        int Idx = Mask[I * PartSz + K];
        if (Idx == PoisonMaskElem) {
          Value *V = GatheredScalars[I * PartSz + K];
          if (isConstant(V) && !isa<PoisonValue>(V)) {
            SecondVecFound = true;
            break;
          }
          continue;
        }
        if (Idx < VF) {
          if (FirstMin > Idx)
            FirstMin = Idx;
        } else {
          SecondVecFound = true;
          break;
        }
      }
      FirstMin = (FirstMin / PartSz) * PartSz;
      // Shuffle of at least 2 vectors - ignore.
      if (SecondVecFound) {
        llvm::fill(Slice, NumScalars);
        ShuffledSubMasks.set(I);
        continue;
      }
      for (int K : seq<int>(Limit)) {
        int Idx = Mask[I * PartSz + K];
        if (Idx == PoisonMaskElem)
          continue;
        Idx -= FirstMin;
        if (Idx >= PartSz) {
          // Cross-part / second-vector reference: this slice cannot be
          // ordered as a single first-vector permutation, give up.
          SecondVecFound = true;
          break;
        }
        // For the last partial slice, Limit < PartSz and Idx in [Limit,
        // PartSz) addresses the unused padded tail (no scalar at that
        // position). Skip the write but keep ordering the remaining K's.
        if (static_cast<unsigned>(I * PartSz + Idx) >= CurrentOrder.size())
          continue;
        if (CurrentOrder[I * PartSz + Idx] >
                static_cast<unsigned>(I * PartSz + K) &&
            CurrentOrder[I * PartSz + Idx] !=
                static_cast<unsigned>(I * PartSz + Idx))
          CurrentOrder[I * PartSz + Idx] = I * PartSz + K;
      }
      // Shuffle of at least 2 vectors - ignore.
      if (SecondVecFound) {
        llvm::fill(Slice, NumScalars);
        ShuffledSubMasks.set(I);
        continue;
      }
    }
  };
  int PartSz = getPartNumElems(NumScalars, NumParts);
  if (!ExtractShuffles.empty())
    TransformMaskToOrder(
        CurrentOrder, ExtractMask, PartSz, NumParts, [&](unsigned I) {
          if (I >= ExtractShuffles.size() || !ExtractShuffles[I])
            return 0U;
          unsigned VF = 0;
          unsigned Sz = getNumElems(TE.getVectorFactor(), PartSz, I);
          for (unsigned Idx : seq<unsigned>(Sz)) {
            int K = I * PartSz + Idx;
            if (static_cast<unsigned>(K) >= ExtractMask.size())
              break;
            if (ExtractMask[K] == PoisonMaskElem)
              continue;
            if (!TE.ReuseShuffleIndices.empty())
              K = TE.ReuseShuffleIndices[K];
            if (K == PoisonMaskElem)
              continue;
            if (!TE.ReorderIndices.empty())
              K = std::distance(TE.ReorderIndices.begin(),
                                find(TE.ReorderIndices, K));
            auto *EI = dyn_cast<ExtractElementInst>(TE.Scalars[K]);
            if (!EI)
              continue;
            VF = std::max(VF, EI->getVectorOperandType()
                                  ->getElementCount()
                                  .getKnownMinValue());
          }
          return VF;
        });
  // Check special corner case - single shuffle of the same entry.
  if (GatherShuffles.size() == 1 && NumParts != 1) {
    if (ShuffledSubMasks.any())
      return std::nullopt;
    PartSz = NumScalars;
    NumParts = 1;
  }
  if (!Entries.empty())
    TransformMaskToOrder(CurrentOrder, Mask, PartSz, NumParts, [&](unsigned I) {
      if (I >= GatherShuffles.size() || !GatherShuffles[I])
        return 0U;
      return std::max(Entries[I].front()->getVectorFactor(),
                      Entries[I].back()->getVectorFactor());
    });
  unsigned NumUndefs = count(CurrentOrder, NumScalars);
  if (ShuffledSubMasks.all() || (NumScalars > 2 && NumUndefs >= NumScalars / 2))
    return std::nullopt;
  return std::move(CurrentOrder);
}

/// Checks if strided loads can be generated out of \p VL loads with pointers \p
/// PointerOps:
/// 1. Target with strided load support is detected.
/// 2. The number of loads is greater than MinProfitableStridedLoads, or the
/// potential stride <= MaxProfitableStride and the potential stride is
/// power-of-2 (to avoid perf regressions for the very small number of loads)
/// and max distance > number of loads, or potential stride is -1.
/// 3. The loads are ordered, or number of unordered loads <=
/// MaxProfitableUnorderedLoads, or loads are in reversed order. (this check is
/// to avoid extra costs for very expensive shuffles).
/// 4. Any pointer operand is an instruction with the users outside of the
/// current graph (for masked gathers extra extractelement instructions
/// might be required).
bool BoUpSLP::isStridedLoad(ArrayRef<Value *> PointerOps, Type *ScalarTy,
                            Align Alignment, const int64_t Diff,
                            const size_t Sz) const {
  if (Diff % (Sz - 1) != 0)
    return false;

  // Try to generate strided load node.
  auto IsAnyPointerUsedOutGraph =
      any_of(make_isa_range<Instruction>(PointerOps), [&](Instruction *I) {
        return any_of(I->users(), [&](User *U) {
          return !isVectorized(U) && !MustGather.contains(U);
        });
      });

  const uint64_t AbsoluteDiff = std::abs(Diff);
  auto *VecTy = getWidenedType(ScalarTy, Sz);
  if (IsAnyPointerUsedOutGraph ||
      (AbsoluteDiff > Sz &&
       (Sz > Opts.slp_min_strided_loads ||
        (AbsoluteDiff <= Opts.slp_max_stride * Sz && AbsoluteDiff % Sz == 0 &&
         has_single_bit(AbsoluteDiff / Sz)))) ||
      Diff == -(static_cast<int64_t>(Sz) - 1)) {
    int64_t Stride = Diff / static_cast<int64_t>(Sz - 1);
    if (Diff != Stride * static_cast<int64_t>(Sz - 1))
      return false;
    if (!TTI->isLegalStridedLoadStore(VecTy, Alignment))
      return false;
    return true;
  }
  return false;
}

bool BoUpSLP::isWidenedStridedLoad(const TreeEntry *E) const {
  if (E->State != TreeEntry::StridedVectorize ||
      E->getOpcode() != Instruction::Load)
    return false;
  const StridedPtrInfo &SPtrInfo = TreeEntryToStridedPtrInfoMap.at(E);
  return SPtrInfo.Ty->getNumElements() != E->Scalars.size();
}

bool BoUpSLP::analyzeConstantStrideCandidate(
    const ArrayRef<Value *> PointerOps, Type *ScalarTy, Align Alignment,
    const SmallVectorImpl<unsigned> &SortedIndices, const int64_t Diff,
    Value *Ptr0, StridedPtrInfo &SPtrInfo) const {
  const size_t Sz = PointerOps.size();
  SmallVector<int64_t> SortedOffsetsFromBase(Sz);
  // Go through `PointerOps` in sorted order and record offsets from
  // PointerOps[0]. We use PointerOps[0] rather than Ptr0 because
  // sortPtrAccesses only validates getPointersDiff for pairs relative to
  // PointerOps[0]. This is safe since only offset differences are used below.
  for (unsigned I : seq<unsigned>(Sz)) {
    Value *Ptr =
        SortedIndices.empty() ? PointerOps[I] : PointerOps[SortedIndices[I]];
    std::optional<int64_t> Offset =
        getPointersDiff(ScalarTy, PointerOps[0], ScalarTy, Ptr, *DL, *SE);
    assert(Offset && "sortPtrAccesses should have validated this pointer");
    SortedOffsetsFromBase[I] = *Offset;
  }

  // The code below checks that `SortedOffsetsFromBase` looks as follows:
  // ```
  // [
  //   (e_{0, 0}, e_{0, 1}, ..., e_{0, GroupSize - 1}), // first group
  //   (e_{1, 0}, e_{1, 1}, ..., e_{1, GroupSize - 1}), // secon group
  //   ...
  //   (e_{NumGroups - 1, 0}, e_{NumGroups - 1, 1}, ..., e_{NumGroups - 1,
  //   GroupSize - 1}), // last group
  // ]
  // ```
  // The distance between consecutive elements within each group should all be
  // the same `StrideWithinGroup`. The distance between the first elements of
  // consecutive groups should all be the same `StrideBetweenGroups`.

  int64_t StrideWithinGroup =
      SortedOffsetsFromBase[1] - SortedOffsetsFromBase[0];
  // Determine size of the first group. Later we will check that all other
  // groups have the same size.
  auto IsEndOfGroupIndex = [=, &SortedOffsetsFromBase](unsigned Idx) {
    return SortedOffsetsFromBase[Idx] - SortedOffsetsFromBase[Idx - 1] !=
           StrideWithinGroup;
  };
  auto Indices = seq<unsigned>(1, Sz);
  auto FoundIt = llvm::find_if(Indices, IsEndOfGroupIndex);
  unsigned GroupSize = FoundIt != Indices.end() ? *FoundIt : Sz;

  unsigned VecSz = Sz;
  Type *NewScalarTy = ScalarTy;

  // Quick detour: at this point we can say what the type of strided load would
  // be if all the checks pass. Check if this type is legal for the target.
  bool NeedsWidening = Sz != GroupSize;
  const uint64_t UnitBitWidth = DL->getTypeSizeInBits(ScalarTy).getFixedValue();
  if (NeedsWidening) {
    if (Sz % GroupSize != 0)
      return false;

    if (StrideWithinGroup != 1)
      return false;
    VecSz = Sz / GroupSize;
    NewScalarTy = Type::getIntNTy(SE->getContext(), UnitBitWidth * GroupSize);
  } else if (ScalarTy->isVectorTy()) {
    NewScalarTy = Type::getIntNTy(SE->getContext(), UnitBitWidth);
  }

  if (!isStridedLoad(PointerOps, NewScalarTy, Alignment, Diff, VecSz))
    return false;

  int64_t StrideIntVal = StrideWithinGroup;
  if (NeedsWidening) {
    // Continue with checking the "shape" of `SortedOffsetsFromBase`.
    // Check that the strides between groups are all the same.
    unsigned CurrentGroupStartIdx = GroupSize;
    int64_t StrideBetweenGroups =
        SortedOffsetsFromBase[GroupSize] - SortedOffsetsFromBase[0];
    StrideIntVal = StrideBetweenGroups;
    for (; CurrentGroupStartIdx < Sz; CurrentGroupStartIdx += GroupSize) {
      if (SortedOffsetsFromBase[CurrentGroupStartIdx] -
              SortedOffsetsFromBase[CurrentGroupStartIdx - GroupSize] !=
          StrideBetweenGroups)
        return false;
    }

    auto CheckGroup = [=](const unsigned StartIdx) -> bool {
      auto Indices = seq<unsigned>(StartIdx + 1, Sz);
      auto FoundIt = llvm::find_if(Indices, IsEndOfGroupIndex);
      unsigned GroupEndIdx = FoundIt != Indices.end() ? *FoundIt : Sz;
      return GroupEndIdx - StartIdx == GroupSize;
    };
    for (unsigned I = 0; I < Sz; I += GroupSize) {
      if (!CheckGroup(I))
        return false;
    }
  }

  Type *StrideTy = DL->getIndexType(Ptr0->getType());
  SPtrInfo.StrideVal = ConstantInt::getSigned(StrideTy, StrideIntVal);
  SPtrInfo.Ty = cast<FixedVectorType>(getWidenedType(NewScalarTy, VecSz));
  return true;
}

bool BoUpSLP::analyzeRtStrideCandidate(ArrayRef<Value *> PointerOps,
                                       Type *BaseTy, Align CommonAlignment,
                                       SmallVectorImpl<unsigned> &SortedIndices,
                                       StridedPtrInfo &SPtrInfo,
                                       bool IsLoad) const {
  const unsigned Sz = PointerOps.size();
  const unsigned MinProfitableStridedOps =
      IsLoad ? Opts.slp_min_strided_loads : Opts.slp_min_strided_stores;
  if (Sz * getNumElements(BaseTy) < MinProfitableStridedOps)
    return false;

  // The element type of the strided access is fixed by the number of distinct
  // constant offsets the pointers fall into, which has to divide their number.
  auto GetStridedTy = [&](unsigned NumOffsets) -> FixedVectorType * {
    Type *NewScalarTy = BaseTy;
    if (NumOffsets > 1 || BaseTy->isVectorTy())
      NewScalarTy = Type::getIntNTy(
          SE->getContext(),
          DL->getTypeSizeInBits(BaseTy).getFixedValue() * NumOffsets);
    return dyn_cast<FixedVectorType>(
        getWidenedType(NewScalarTy, Sz / NumOffsets));
  };
  auto IsLegalStridedTy = [&](FixedVectorType *StridedTy) {
    return StridedTy && TTI->isTypeLegal(StridedTy) &&
           TTI->isLegalStridedLoadStore(StridedTy, CommonAlignment);
  };
  // Determining the offsets below builds SCEVs for every pointer, which is
  // expensive. Bail out if the target does not support any strided accesses at
  // all.
  if (none_of(seq<unsigned>(1, Sz), [&](unsigned NumOffsets) {
        return Sz % NumOffsets == 0 &&
               IsLegalStridedTy(GetStridedTy(NumOffsets));
      }))
    return false;

  // If each value in `PointerOps` is of the form `%x + Offset` where `Offset`
  // is constant, we partition `PointerOps` sequence into subsequences of
  // pointers with the same offset. For each offset we record values from
  // `PointerOps` and their indicies in `PointerOps`.
  SmallDenseMap<int64_t, std::pair<SmallVector<Value *>, SmallVector<unsigned>>>
      OffsetToPointerOpIdxMap;
  // Track to make sure that only VecSz different stride multiples are consumed
  // Prevents cases such as:
  // 1, x + 0, x + 1, 2x + 0 from being recognized as legal RT strided as there
  // are 2 "0" and 2 "1" offsets and a stride of "x" between both offsets
  SmallDenseSet<const SCEV *> StrideMultiples;
  for (auto [Idx, Ptr] : enumerate(PointerOps)) {
    const SCEV *PtrSCEV = SE->getSCEV(Ptr);
    if (!PtrSCEV)
      return false;

    const auto *Add = dyn_cast<SCEVAddExpr>(PtrSCEV);
    int64_t Offset = 0;
    const SCEV *StrideMultiple = PtrSCEV;
    if (Add) {
      // `Offset` is non-zero.
      for (int I : seq<int>(Add->getNumOperands())) {
        const auto *SC = dyn_cast<SCEVConstant>(Add->getOperand(I));
        if (!SC)
          continue;
        Offset = SC->getAPInt().getSExtValue();
        if (Offset >= std::numeric_limits<int64_t>::max() - 1) {
          Offset = 0;
          continue;
        }
        StrideMultiple = SE->getMinusSCEV(StrideMultiple, SC);
        break;
      }
    }
    OffsetToPointerOpIdxMap[Offset].first.push_back(Ptr);
    OffsetToPointerOpIdxMap[Offset].second.push_back(Idx);
    StrideMultiples.insert(StrideMultiple);
  }
  unsigned NumOffsets = OffsetToPointerOpIdxMap.size();

  // Quick detour: at this point we can say what the type of strided load would
  // be if all the checks pass. Check if this type is legal for the target.
  unsigned VecSz = Sz;
  if (NumOffsets > 1) {
    if (Sz % NumOffsets != 0)
      return false;
    VecSz = Sz / NumOffsets;
  }

  if (StrideMultiples.size() != VecSz)
    return false;

  auto *StridedLoadTy = GetStridedTy(NumOffsets);
  if (!IsLegalStridedTy(StridedLoadTy))
    return false;

  // Check if the offsets are contiguous and that each group has the required
  // size.
  SmallVector<int64_t> SortedOffsetsV(NumOffsets);
  for (auto [Idx, MapPair] : enumerate(OffsetToPointerOpIdxMap)) {
    if (MapPair.second.first.size() != VecSz)
      return false;
    SortedOffsetsV[Idx] = MapPair.first;
  }
  sort(SortedOffsetsV);

  if (NumOffsets > 1) {
    int64_t BaseBytes = DL->getTypeStoreSize(BaseTy);
    for (int I : seq<int>(1, SortedOffsetsV.size())) {
      if (SortedOffsetsV[I] - SortedOffsetsV[I - 1] != BaseBytes)
        return false;
    }
  }

  // Introduce some notation for the explanations below. Let `PointerOps_j`
  // denote  the subsequence of `PointerOps` with offsets equal to
  // `SortedOffsetsV[j]`. Let `SortedIndices_j` be a such that the sequence
  // ```
  // PointerOps_j[SortedIndices_j[0]],
  // PointerOps_j[SortedIndices_j[1]],
  // PointerOps_j[SortedIndices_j[2]],
  // ...
  // ```
  // is sorted. Also, let `IndicesInAllPointerOps_j` be the vector
  // of indices of the subsequence `PointerOps_j` in all of `PointerOps`,
  // i.e `PointerOps_j[i] = PointerOps[IndicesInAllPointerOps_j[i]]`.
  // The entire sorted `PointerOps` looks like this:
  // ```
  // PointerOps_0[SortedIndices_0[0]] = PointerOps[IndicesInAllPointerOps_0[0]],
  // PointerOps_1[SortedIndices_1[0]] = PointerOps[IndicesInAllPointerOps_1[0]],
  // PointerOps_2[SortedIndices_2[0]] = PointerOps[IndicesInAllPointerOps_2[0]],
  // ...
  // PointerOps_(NumOffsets - 1)[SortedIndices_(NumOffsets - 1)[0]] =
  // PointerOps[IndicesInAllPointerOps_(NumOffsets - 1)[0]],
  //
  // PointerOps_0[SortedIndices_0[1]] = PointerOps[IndicesInAllPointerOps_0[1]],
  // PointerOps_1[SortedIndices_1[1]] = PointerOps[IndicesInAllPointerOps_1[1]],
  // PointerOps_2[SortedIndices_2[1]] = PointerOps[IndicesInAllPointerOps_2[1]],
  // ...
  // PointerOps_(NumOffsets - 1)[SortedIndices_(NumOffsets - 1)[1]] =
  // PointerOps[IndicesInAllPointerOps_(NumOffsets - 1)[1]],
  //
  // PointerOps_0[SortedIndices_0[2]] = PointerOps[IndicesInAllPointerOps_0[2]],
  // PointerOps_1[SortedIndices_1[2]] = PointerOps[IndicesInAllPointerOps_1[2]],
  // PointerOps_2[SortedIndices_2[2]] = PointerOps[IndicesInAllPointerOps_2[2]],
  // ...
  // PointerOps_(NumOffsets - 1)[SortedIndices_(NumOffsets - 1)[2]] =
  // PointerOps[IndicesInAllPointerOps_(NumOffsets - 1)[2]],
  // ...
  // ...
  // ...
  // PointerOps_0[SortedIndices_0[VecSz - 1]] =
  // PointerOps[IndicesInAllPointerOps_0[VecSz - 1]],
  // PointerOps_1[SortedIndices_1[VecSz - 1]] =
  // PointerOps[IndicesInAllPointerOps_1[VecSz - 1]],
  // PointerOps_2[SortedIndices_2[VecSz - 1]] =
  // PointerOps[IndicesInAllPointerOps_2[VecSz - 1]],
  // ...
  // PointerOps_(NumOffsets - 1)[SortedIndices_(NumOffsets - 1)[VecSz - 1]] =
  // PointerOps[IndicesInAllPointerOps_(NumOffsets - 1)[VecSz - 1]],
  // ```
  // In order to be able to generate a strided load, for each `PointerOps_j`
  // check that the distance between adjacent pointers are all equal to the same
  // value (stride).
  //
  // As we do that, also calculate SortedIndices. Since we should not modify
  // `SortedIndices` unless we know that all the checks succeed, record the
  // indicies into `SortedIndicesDraft`.
  SmallVector<unsigned> SortedIndicesDraft(Sz);

  // Given sorted indices for a particular offset (as calculated by
  // calculateRtStride), update the `SortedIndicesDraft` for all of PointerOps.
  // Let `Offset` be `SortedOffsetsV[OffsetNum]`.
  // \param `OffsetNum` the index of `Offset` in `SortedOffsetsV`.
  // \param `IndicesInAllPointerOps` vector of indices of the
  // subsequence `PointerOps_OffsetNum` in `PointerOps`, i.e. using the above
  // notation `IndicesInAllPointerOps = IndicesInAllPointerOps_OffsetNum`.
  // \param `SortedIndicesForOffset = SortedIndices_OffsetNum`
  auto UpdateSortedIndices =
      [&](SmallVectorImpl<unsigned> &SortedIndicesForOffset,
          ArrayRef<unsigned> IndicesInAllPointerOps, const int64_t OffsetNum) {
        if (SortedIndicesForOffset.empty()) {
          SortedIndicesForOffset.resize(IndicesInAllPointerOps.size());
          std::iota(SortedIndicesForOffset.begin(),
                    SortedIndicesForOffset.end(), 0);
        }
        for (const auto [Num, Idx] : enumerate(SortedIndicesForOffset)) {
          SortedIndicesDraft[Num * NumOffsets + OffsetNum] =
              IndicesInAllPointerOps[Idx];
        }
      };

  int64_t LowestOffset = SortedOffsetsV[0];
  ArrayRef<Value *> PointerOps0 = OffsetToPointerOpIdxMap[LowestOffset].first;

  SmallVector<unsigned> SortedIndicesForOffset0;
  const SCEV *Stride0 =
      calculateRtStride(PointerOps0, BaseTy, *DL, *SE, SortedIndicesForOffset0);
  if (!Stride0)
    return false;

  ArrayRef<unsigned> IndicesInAllPointerOps0 =
      OffsetToPointerOpIdxMap[LowestOffset].second;
  UpdateSortedIndices(SortedIndicesForOffset0, IndicesInAllPointerOps0, 0);

  // Now that we know what the common stride and coefficients has to be check
  // the remaining `PointerOps_j`.
  SmallVector<unsigned> SortedIndicesForOffset;
  for (int J : seq<int>(1, NumOffsets)) {
    SortedIndicesForOffset.clear();

    int64_t Offset = SortedOffsetsV[J];
    ArrayRef<Value *> PointerOpsForOffset =
        OffsetToPointerOpIdxMap[Offset].first;
    ArrayRef<unsigned> IndicesInAllPointerOps =
        OffsetToPointerOpIdxMap[Offset].second;
    const SCEV *StrideWithinGroup = calculateRtStride(
        PointerOpsForOffset, BaseTy, *DL, *SE, SortedIndicesForOffset);

    if (!StrideWithinGroup || StrideWithinGroup != Stride0)
      return false;

    UpdateSortedIndices(SortedIndicesForOffset, IndicesInAllPointerOps, J);
  }

  SortedIndices.clear();
  SortedIndices = std::move(SortedIndicesDraft);
  SPtrInfo.StrideSCEV = Stride0;
  SPtrInfo.Ty = StridedLoadTy;
  return true;
}

BoUpSLP::LoadsState BoUpSLP::canVectorizeLoads(
    ArrayRef<Value *> VL, const Value *VL0, SmallVectorImpl<unsigned> &Order,
    SmallVectorImpl<Value *> &PointerOps, StridedPtrInfo &SPtrInfo,
    unsigned *BestVF, bool TryRecursiveCheck) const {
  // Check that a vectorized load would load the same memory as a scalar
  // load. For example, we don't want to vectorize loads that are smaller
  // than 8-bit. Even though we have a packed struct {<i2, i2, i2, i2>} LLVM
  // treats loading/storing it as an i8 struct. If we vectorize loads/stores
  // from such a struct, we read/write packed bits disagreeing with the
  // unvectorized version.
  if (BestVF)
    *BestVF = 0;
  if (areKnownNonVectorizableLoads(VL))
    return LoadsState::Gather;
  Type *ScalarTy = VL0->getType();

  if (DL->getTypeSizeInBits(ScalarTy) != DL->getTypeAllocSizeInBits(ScalarTy))
    return LoadsState::Gather;

  // The undef and poison lanes are covered by a single wide load of the
  // consecutive loads.
  if (any_of(VL, IsaPred<UndefValue>))
    return canWidenLoadsOverUndefLanes(VL, *DL, *SE, *AC, *DT, *TLI)
               ? LoadsState::Vectorize
               : LoadsState::Gather;

  // Make sure all loads in the bundle are simple - we can't vectorize
  // atomic or volatile loads.
  PointerOps.clear();
  const size_t Sz = VL.size();
  PointerOps.resize(Sz);
  auto *POIter = PointerOps.begin();
  for (Value *V : VL) {
    auto *L = dyn_cast<LoadInst>(V);
    if (!L || !L->isSimple())
      return LoadsState::Gather;
    *POIter = L->getPointerOperand();
    ++POIter;
  }

  Order.clear();
  // Check the order of pointer operands or that all pointers are the same.
  bool IsSorted = sortPtrAccesses(PointerOps, ScalarTy, *DL, *SE, Order);

  auto *VecTy = dyn_cast<VectorType>(getWidenedType(ScalarTy, Sz));
  if (!VecTy)
    return LoadsState::Gather;
  Align CommonAlignment = computeCommonAlignment<LoadInst>(VL);
  // Cache masked gather legality - both the !IsSorted path below and the
  // post-branch check use the same VecTy/CommonAlignment, and the underlying
  // TTI calls are virtual.
  std::optional<bool> MaskedGatherLegal;
  auto IsMaskedGatherLegal = [&, TTI = TTI] {
    if (!MaskedGatherLegal)
      MaskedGatherLegal =
          TTI->isLegalMaskedGather(VecTy, CommonAlignment) &&
          !TTI->forceScalarizeMaskedGather(VecTy, CommonAlignment);
    return *MaskedGatherLegal;
  };
  if (!IsSorted) {
    // Check for a group of loads, each selecting its address (directly, or
    // via a constant-offset GEP) between the same two candidate base
    // pointers - the shape if-converted, fully-unrolled loop bodies of the
    // form `x = cond ? A[i] : B[i]` take. If found, model it as two masked
    // loads (one per candidate) blended by the (vectorized) condition,
    // rather than falling back to a gather of the individual scalar loads.
    Value *TrueBase = nullptr;
    Value *FalseBase = nullptr;
    SmallVector<Value *> Conditions;
    if (isSelectedBaseLoad(ScalarTy, PointerOps, *DL, TrueBase, FalseBase,
                           Conditions) &&
        TTI->isLegalMaskedLoad(VecTy, computeBlendedLoadBaseAlignment(VL, *DL),
                               cast<LoadInst>(VL0)->getPointerAddressSpace()))
      return LoadsState::BlendedLoadVectorize;

    if (analyzeRtStrideCandidate(PointerOps, ScalarTy, CommonAlignment, Order,
                                 SPtrInfo, /*isLoad=*/true))
      return LoadsState::StridedVectorize;

    if (!IsMaskedGatherLegal())
      return LoadsState::Gather;

    // The gather address vector requires pointers of the same type.
    Value *FrontPtr = PointerOps.front();
    Type *PtrTy = FrontPtr->getType();
    if (!all_of(PointerOps,
                [&](Value *P) {
                  return P->getType() == PtrTy &&
                         arePointersCompatible(P, FrontPtr, *TLI,
                                               Opts.slp_recursion_max_depth);
                }) &&
        !isCopyableGEPAddressVector(PointerOps))
      return LoadsState::Gather;

  } else {
    Value *Ptr0;
    Value *PtrN;
    if (Order.empty()) {
      Ptr0 = PointerOps.front();
      PtrN = PointerOps.back();
    } else {
      Ptr0 = PointerOps[Order.front()];
      PtrN = PointerOps[Order.back()];
    }
    // sortPtrAccesses validates getPointersDiff for all pointers relative to
    // PointerOps[0], so compute the span using PointerOps[0] as intermediate:
    //   Diff = offset(PtrN) - offset(Ptr0) relative to PointerOps[0]
    std::optional<int64_t> Diff0 =
        getPointersDiff(ScalarTy, PointerOps[0], ScalarTy, Ptr0, *DL, *SE);
    std::optional<int64_t> DiffN =
        getPointersDiff(ScalarTy, PointerOps[0], ScalarTy, PtrN, *DL, *SE);
    assert(Diff0 && DiffN &&
           "sortPtrAccesses should have validated these pointers");
    int64_t Diff = *DiffN - *Diff0;
    // Check that the sorted loads are consecutive.
    if (static_cast<uint64_t>(Diff) == Sz - 1)
      return LoadsState::Vectorize;
    if (isMaskedLoadCompress(
            VL, PointerOps, Order, *TTI, *DL, *SE, *AC, *DT, *TLI, CostKind,
            [&](Value *V) {
              return areAllUsersVectorized(cast<Instruction>(V),
                                           UserIgnoreList);
            },
            Opts.slp_revec, Cache))
      return LoadsState::CompressVectorize;
    // Widened strided loads must be legal for every group, not just the first
    // pointer, which may have a stronger alignment than the remaining loads.
    if (analyzeConstantStrideCandidate(PointerOps, ScalarTy, CommonAlignment,
                                       Order, Diff, Ptr0, SPtrInfo))
      return LoadsState::StridedVectorize;
  }
  if (!IsMaskedGatherLegal())
    return LoadsState::Gather;
  // Correctly identify compare the cost of loads + shuffles rather than
  // strided/masked gather loads. Returns true if vectorized + shuffles
  // representation is better than just gather.
  auto CheckForShuffledLoads = [&, &TTI = *TTI](Align CommonAlignment,
                                                unsigned *BestVF,
                                                bool ProfitableGatherPointers) {
    if (BestVF)
      *BestVF = 0;
    // Compare masked gather cost and loads + insert subvector costs.
    auto [ScalarGEPCost, VectorGEPCost] =
        getGEPCosts(TTI, PointerOps, PointerOps.front(), Instruction::Load,
                    CostKind, ScalarTy, VecTy);
    // Estimate the cost of masked gather GEP. If not a splat, roughly
    // estimate as a buildvector, otherwise estimate as splat.
    APInt DemandedElts = APInt::getAllOnes(Sz);
    Type *PtrScalarTy = PointerOps.front()->getType()->getScalarType();
    auto *PtrVecTy = cast<VectorType>(getWidenedType(PtrScalarTy, Sz));
    // Cache the underlying object of PointerOps.front() - it is invariant
    // across the per-V comparisons below and getUnderlyingObject walks
    // GEP/cast chains.
    const Value *FrontUO = getUnderlyingObject(PointerOps.front());
    if (static_cast<unsigned>(count_if(
            PointerOps, IsaPred<GetElementPtrInst>)) < PointerOps.size() - 1 ||
        any_of(PointerOps,
               [&](Value *V) { return getUnderlyingObject(V) != FrontUO; }))
      VectorGEPCost +=
          getScalarizationOverhead(TTI, Opts.slp_revec, PtrScalarTy, PtrVecTy,
                                   DemandedElts, /*Insert=*/true,
                                   /*Extract=*/false, CostKind);
    else
      VectorGEPCost +=
          getScalarizationOverhead(TTI, Opts.slp_revec, PtrScalarTy, PtrVecTy,
                                   APInt::getOneBitSet(Sz, 0),
                                   /*Insert=*/true, /*Extract=*/false,
                                   CostKind) +
          getShuffleCost(TTI, TTI::SK_Broadcast, PtrVecTy, CostKind);
    // The cost of scalar loads.
    InstructionCost ScalarLoadsCost =
        accumulate(VL, InstructionCost(),
                   [&](InstructionCost C, Value *V) {
                     return C + TTI.getInstructionCost(cast<Instruction>(V),
                                                       CostKind);
                   }) +
        ScalarGEPCost;
    // The cost of masked gather.
    InstructionCost MaskedGatherCost =
        TTI.getMemIntrinsicInstrCost(
            MemIntrinsicCostAttributes(Intrinsic::masked_gather, VecTy,
                                       cast<LoadInst>(VL0)->getPointerOperand(),
                                       /*VariableMask=*/false, CommonAlignment),
            CostKind) +
        (ProfitableGatherPointers ? 0 : VectorGEPCost);
    InstructionCost GatherCost =
        getScalarizationOverhead(TTI, Opts.slp_revec, ScalarTy, VecTy,
                                 DemandedElts,
                                 /*Insert=*/true,
                                 /*Extract=*/false, CostKind) +
        ScalarLoadsCost;
    // The list of loads is small or perform partial check already - directly
    // compare masked gather cost and gather cost.
    constexpr unsigned ListLimit = 4;
    if (!TryRecursiveCheck || VL.size() < ListLimit)
      return MaskedGatherCost - GatherCost >= -getCostThreshold();

    unsigned Sz = DL->getTypeSizeInBits(ScalarTy);
    unsigned MinVF = getMinVF(2 * Sz);
    DemandedElts.clearAllBits();
    // Iterate through possible vectorization factors and check if vectorized +
    // shuffles is better than just gather.
    for (unsigned VF = getFloorFullVectorNumberOfElements(
             TTI, ScalarTy, VL.size() - 1, Opts.slp_revec);
         VF >= MinVF; VF = getFloorFullVectorNumberOfElements(
                          TTI, ScalarTy, VF - 1, Opts.slp_revec)) {
      SmallVector<std::pair<unsigned, LoadsState>> States;
      for (unsigned Cnt = 0, End = VL.size(); Cnt < End; Cnt += VF) {
        const unsigned SliceVF = std::min(VF, End - Cnt);
        ArrayRef<Value *> Slice = VL.slice(Cnt, SliceVF);
        SmallVector<unsigned> Order;
        SmallVector<Value *> PointerOps;
        LoadsState LS = canVectorizeLoads(Slice, Slice.front(), Order,
                                          PointerOps, SPtrInfo, BestVF,
                                          /*TryRecursiveCheck=*/false);
        // Check that the sorted loads are consecutive.
        if (LS == LoadsState::Gather) {
          if (BestVF) {
            DemandedElts.setAllBits();
            break;
          }
          DemandedElts.setBits(Cnt, Cnt + SliceVF);
          continue;
        }
        // If need the reorder - consider as high-cost masked gather for now.
        if ((LS == LoadsState::Vectorize ||
             LS == LoadsState::StridedVectorize ||
             LS == LoadsState::CompressVectorize) &&
            !Order.empty() && !isReverseOrder(Order))
          LS = LoadsState::ScatterVectorize;
        States.emplace_back(Cnt, LS);
      }
      if (DemandedElts.isAllOnes())
        // All loads gathered - try smaller VF.
        continue;
      // Can be vectorized later as a serie of loads/insertelements.
      InstructionCost VecLdCost = 0;
      if (!DemandedElts.isZero()) {
        VecLdCost = getScalarizationOverhead(TTI, Opts.slp_revec, ScalarTy,
                                             VecTy, DemandedElts,
                                             /*Insert=*/true,
                                             /*Extract=*/false, CostKind) +
                    ScalarGEPCost;
        for (unsigned Idx : seq<unsigned>(VL.size()))
          if (DemandedElts[Idx])
            VecLdCost +=
                TTI.getInstructionCost(cast<Instruction>(VL[Idx]), CostKind);
      }
      for (const auto &[SliceStart, LS] : States) {
        const unsigned SliceVF = std::min<unsigned>(VF, VL.size() - SliceStart);
        auto *SubVecTy = cast<VectorType>(getWidenedType(ScalarTy, SliceVF));
        auto *LI0 = cast<LoadInst>(VL[SliceStart]);
        InstructionCost VectorGEPCost =
            (LS == LoadsState::ScatterVectorize && ProfitableGatherPointers)
                ? 0
                : getGEPCosts(TTI,
                              ArrayRef(PointerOps).slice(SliceStart, SliceVF),
                              LI0->getPointerOperand(), Instruction::Load,
                              CostKind, ScalarTy, SubVecTy)
                      .second;
        if (LS == LoadsState::ScatterVectorize) {
          if (static_cast<unsigned>(
                  count_if(PointerOps, IsaPred<GetElementPtrInst>)) <
                  PointerOps.size() - 1 ||
              any_of(PointerOps, [&](Value *V) {
                return getUnderlyingObject(V) != FrontUO;
              }))
            VectorGEPCost += getScalarizationOverhead(
                TTI, Opts.slp_revec, ScalarTy, SubVecTy,
                APInt::getAllOnes(SliceVF),
                /*Insert=*/true, /*Extract=*/false, CostKind);
          else
            VectorGEPCost +=
                getScalarizationOverhead(
                    TTI, Opts.slp_revec, ScalarTy, SubVecTy,
                    APInt::getOneBitSet(SliceVF, 0),
                    /*Insert=*/true, /*Extract=*/false, CostKind) +
                getShuffleCost(TTI, TTI::SK_Broadcast, SubVecTy, CostKind);
        }
        switch (LS) {
        case LoadsState::Vectorize:
          VecLdCost += TTI.getMemoryOpCost(
                           Instruction::Load, SubVecTy, LI0->getAlign(),
                           LI0->getPointerAddressSpace(), CostKind,
                           TTI::getOperandInfo(LI0->getPointerOperand())) +
                       VectorGEPCost;
          break;
        case LoadsState::StridedVectorize:
          VecLdCost += TTI.getMemIntrinsicInstrCost(
                           MemIntrinsicCostAttributes(
                               Intrinsic::experimental_vp_strided_load,
                               SubVecTy, LI0->getPointerOperand(),
                               /*VariableMask=*/false, CommonAlignment),
                           CostKind) +
                       VectorGEPCost;
          break;
        case LoadsState::CompressVectorize:
          VecLdCost +=
              TTI.getMemIntrinsicInstrCost(
                  MemIntrinsicCostAttributes(Intrinsic::masked_load, SubVecTy,
                                             CommonAlignment,
                                             LI0->getPointerAddressSpace()),
                  CostKind) +
              getShuffleCost(TTI, TTI::SK_PermuteSingleSrc, SubVecTy, CostKind);
          break;
        case LoadsState::ScatterVectorize:
          VecLdCost += TTI.getMemIntrinsicInstrCost(
                           MemIntrinsicCostAttributes(
                               Intrinsic::masked_gather, SubVecTy,
                               LI0->getPointerOperand(),
                               /*VariableMask=*/false, CommonAlignment),
                           CostKind) +
                       VectorGEPCost;
          break;
        case LoadsState::BlendedLoadVectorize:
          // Two masked loads (one per candidate base) plus a select; no address
          // vector is materialized, so VectorGEPCost is skipped.
          VecLdCost +=
              getBlendedLoadCost(TTI, SubVecTy,
                                 computeBlendedLoadBaseAlignment(
                                     VL.slice(SliceStart, SliceVF), *DL),
                                 LI0->getPointerAddressSpace(), CostKind);
          break;
        case LoadsState::Gather:
          llvm_unreachable("Gathers are not added to States");
        }
        SmallVector<int> ShuffleMask(VL.size());
        const unsigned SliceIdx = SliceStart / VF;
        for (int Idx : seq<int>(VL.size()))
          ShuffleMask[Idx] = Idx / VF == SliceIdx ? VL.size() + Idx % VF : Idx;
        if (SliceStart > 0)
          VecLdCost +=
              getShuffleCost(TTI, TTI::SK_InsertSubvector, VecTy, CostKind,
                             ShuffleMask, SliceStart, SubVecTy);
      }
      // If masked gather cost is higher - better to vectorize, so
      // consider it as a gather node. It will be better estimated
      // later.
      if (MaskedGatherCost >= VecLdCost &&
          VecLdCost - GatherCost < -getCostThreshold()) {
        if (BestVF)
          *BestVF = VF;
        return true;
      }
    }
    return MaskedGatherCost - GatherCost >= -getCostThreshold();
  };
  // TODO: need to improve analysis of the pointers, if not all of them are
  // GEPs or have > 2 operands, we end up with a gather node, which just
  // increases the cost.
  Loop *L = LI->getLoopFor(cast<LoadInst>(VL0)->getParent());
  bool ProfitableGatherPointers =
      L && Sz > 2 && static_cast<unsigned>(count_if(PointerOps, [L](Value *V) {
                       return L->isLoopInvariant(V);
                     })) <= Sz / 2;
  if (ProfitableGatherPointers || all_of(PointerOps, [](Value *P) {
        auto *GEP = dyn_cast<GetElementPtrInst>(P);
        return (!GEP && doesNotNeedToBeScheduled(P)) ||
               (GEP && GEP->getNumOperands() == 2 &&
                isa<Constant, Instruction>(GEP->getOperand(1)));
      })) {
    // Check if potential masked gather can be represented as series
    // of loads + insertsubvectors.
    // If masked gather cost is higher - better to vectorize, so
    // consider it as a gather node. It will be better estimated
    // later.
    if (!TryRecursiveCheck || !CheckForShuffledLoads(CommonAlignment, BestVF,
                                                     ProfitableGatherPointers))
      return LoadsState::ScatterVectorize;
  }

  return LoadsState::Gather;
}

std::optional<BoUpSLP::OrdersType>
BoUpSLP::findPartiallyOrderedLoads(const BoUpSLP::TreeEntry &TE) {
  assert(TE.isGather() && "Expected gather node only.");
  Type *ScalarTy = TE.Scalars[0]->getType();

  SmallVector<Value *> Ptrs;
  Ptrs.reserve(TE.Scalars.size());
  SmallVector<BasicBlock *> BBs;
  BBs.reserve(TE.Scalars.size());
  for (Value *V : TE.Scalars) {
    auto *L = dyn_cast<LoadInst>(V);
    if (!L || !L->isSimple())
      return std::nullopt;
    Ptrs.push_back(L->getPointerOperand());
    BBs.push_back(L->getParent());
  }

  BoUpSLP::OrdersType Order;
  if (!LoadEntriesToVectorize.contains(TE.Idx) &&
      clusterSortPtrAccesses(Ptrs, BBs, ScalarTy, *DL, *SE,
                             Opts.slp_recursion_max_depth, Order, Cache))
    return std::move(Order);
  return std::nullopt;
}

/// Check if two insertelement instructions are from the same buildvector.
static bool areTwoInsertFromSameBuildVector(
    InsertElementInst *VU, InsertElementInst *V,
    function_ref<Value *(InsertElementInst *)> GetBaseOperand) {
  // Instructions must be from the same basic blocks.
  if (VU->getParent() != V->getParent())
    return false;
  // Checks if 2 insertelements are from the same buildvector.
  if (VU->getType() != V->getType())
    return false;
  // Multiple used inserts are separate nodes.
  if (!VU->hasOneUse() && !V->hasOneUse())
    return false;
  auto *IE1 = VU;
  auto *IE2 = V;
  std::optional<unsigned> Idx1 = getElementIndex(IE1);
  std::optional<unsigned> Idx2 = getElementIndex(IE2);
  if (Idx1 == std::nullopt || Idx2 == std::nullopt)
    return false;
  // Go through the vector operand of insertelement instructions trying to find
  // either VU as the original vector for IE2 or V as the original vector for
  // IE1.
  SmallBitVector ReusedIdx(VU->getType()->getElementCount().getKnownMinValue());
  bool IsReusedIdx = false;
  do {
    if (IE2 == VU && !IE1)
      return VU->hasOneUse();
    if (IE1 == V && !IE2)
      return V->hasOneUse();
    if (IE1 && IE1 != V) {
      unsigned Idx1 = getElementIndex(IE1).value_or(*Idx2);
      IsReusedIdx |= ReusedIdx.test(Idx1);
      ReusedIdx.set(Idx1);
      if ((IE1 != VU && !IE1->hasOneUse()) || IsReusedIdx)
        IE1 = nullptr;
      else
        IE1 = dyn_cast_if_present<InsertElementInst>(GetBaseOperand(IE1));
    }
    if (IE2 && IE2 != VU) {
      unsigned Idx2 = getElementIndex(IE2).value_or(*Idx1);
      IsReusedIdx |= ReusedIdx.test(Idx2);
      ReusedIdx.set(Idx2);
      if ((IE2 != V && !IE2->hasOneUse()) || IsReusedIdx)
        IE2 = nullptr;
      else
        IE2 = dyn_cast_if_present<InsertElementInst>(GetBaseOperand(IE2));
    }
  } while (!IsReusedIdx && (IE1 || IE2));
  return false;
}

std::optional<BoUpSLP::OrdersType>
BoUpSLP::getReorderingData(const TreeEntry &TE, bool TopToBottom,
                           bool IgnoreReorder) {
  // No need to reorder if need to shuffle reuses, still need to shuffle the
  // node.
  if (!TE.ReuseShuffleIndices.empty()) {
    if (isSplat(TE.Scalars))
      return std::nullopt;
    // Check if reuse shuffle indices can be improved by reordering.
    // For this, check that reuse mask is "clustered", i.e. each scalar values
    // is used once in each submask of size <number_of_scalars>.
    // Example: 4 scalar values.
    // ReuseShuffleIndices mask: 0, 1, 2, 3, 3, 2, 0, 1 - clustered.
    //                           0, 1, 2, 3, 3, 3, 1, 0 - not clustered, because
    //                           element 3 is used twice in the second submask.
    unsigned Sz = TE.Scalars.size();
    if (TE.isGather()) {
      if (std::optional<OrdersType> CurrentOrder =
              findReusedOrderedScalars(TE, TopToBottom, IgnoreReorder)) {
        SmallVector<int> Mask;
        fixupOrderingIndices(*CurrentOrder);
        inversePermutation(*CurrentOrder, Mask);
        addMask(Mask, TE.ReuseShuffleIndices);
        OrdersType Res(TE.getVectorFactor(), TE.getVectorFactor());
        unsigned Sz = TE.Scalars.size();
        for (int K = 0, E = TE.getVectorFactor() / Sz; K < E; ++K) {
          for (auto [I, Idx] : enumerate(ArrayRef(Mask).slice(K * Sz, Sz)))
            if (Idx != PoisonMaskElem)
              Res[Idx + K * Sz] = I + K * Sz;
        }
        return std::move(Res);
      }
    }
    if (Sz == 2 && TE.getVectorFactor() == 4 &&
        getNumberOfParts(
            getWidenedType(getValueType(TE.Scalars.front(), Opts.slp_revec),
                           2 * TE.getVectorFactor()),
            getValueType(TE.Scalars.front(), Opts.slp_revec)) == 1)
      return std::nullopt;
    if (TE.ReuseShuffleIndices.size() % Sz != 0)
      return std::nullopt;
    if (!ShuffleVectorInst::isOneUseSingleSourceMask(TE.ReuseShuffleIndices,
                                                     Sz)) {
      SmallVector<int> ReorderMask(Sz, PoisonMaskElem);
      if (TE.ReorderIndices.empty())
        std::iota(ReorderMask.begin(), ReorderMask.end(), 0);
      else
        inversePermutation(TE.ReorderIndices, ReorderMask);
      addMask(ReorderMask, TE.ReuseShuffleIndices);
      unsigned VF = ReorderMask.size();
      OrdersType ResOrder(VF, VF);
      unsigned NumParts = divideCeil(VF, Sz);
      SmallBitVector UsedVals(NumParts);
      for (unsigned I = 0; I < VF; I += Sz) {
        int Val = PoisonMaskElem;
        unsigned UndefCnt = 0;
        unsigned Limit = std::min(Sz, VF - I);
        if (any_of(ArrayRef(ReorderMask).slice(I, Limit),
                   [&](int Idx) {
                     if (Val == PoisonMaskElem && Idx != PoisonMaskElem)
                       Val = Idx;
                     if (Idx == PoisonMaskElem)
                       ++UndefCnt;
                     return Idx != PoisonMaskElem && Idx != Val;
                   }) ||
            Val >= static_cast<int>(NumParts) || Val == PoisonMaskElem ||
            UsedVals.test(Val) || UndefCnt > Sz / 2)
          return std::nullopt;
        UsedVals.set(Val);
        for (unsigned K = 0; K < NumParts; ++K) {
          unsigned Idx = Val + Sz * K;
          if (Idx < VF && I + K < VF)
            ResOrder[Idx] = I + K;
        }
      }
      return std::move(ResOrder);
    }
    unsigned VF = TE.getVectorFactor();
    // Try build correct order for extractelement instructions.
    SmallVector<int> ReusedMask(TE.ReuseShuffleIndices.begin(),
                                TE.ReuseShuffleIndices.end());
    if (TE.hasState() && TE.getOpcode() == Instruction::ExtractElement &&
        !TE.hasCopyableElements() &&
        all_of(make_isa_range<Instruction>(TE.Scalars), [Sz](Instruction *I) {
          std::optional<unsigned> Idx = getExtractIndex(I);
          return Idx && *Idx < Sz;
        })) {
      assert(!TE.isAltShuffle() && "Alternate instructions are only supported "
                                   "by BinaryOperator and CastInst.");
      SmallVector<int> ReorderMask(Sz, PoisonMaskElem);
      if (TE.ReorderIndices.empty())
        std::iota(ReorderMask.begin(), ReorderMask.end(), 0);
      else
        inversePermutation(TE.ReorderIndices, ReorderMask);
      for (unsigned I = 0; I < VF; ++I) {
        int &Idx = ReusedMask[I];
        if (Idx == PoisonMaskElem)
          continue;
        Value *V = TE.Scalars[ReorderMask[Idx]];
        std::optional<unsigned> EI = getExtractIndex(cast<Instruction>(V));
        Idx = std::distance(ReorderMask.begin(), find(ReorderMask, *EI));
      }
    }
    // Build the order of the VF size, need to reorder reuses shuffles, they are
    // always of VF size.
    OrdersType ResOrder(VF);
    std::iota(ResOrder.begin(), ResOrder.end(), 0);
    auto *It = ResOrder.begin();
    for (unsigned K = 0; K < VF; K += Sz) {
      OrdersType CurrentOrder(TE.ReorderIndices);
      SmallVector<int> SubMask{ArrayRef(ReusedMask).slice(K, Sz)};
      if (SubMask.front() == PoisonMaskElem)
        std::iota(SubMask.begin(), SubMask.end(), 0);
      reorderOrder(CurrentOrder, SubMask);
      transform(CurrentOrder, It, [K](unsigned Pos) { return Pos + K; });
      std::advance(It, Sz);
    }
    if (TE.isGather() && all_of(enumerate(ResOrder), [](const auto &Data) {
          return Data.index() == Data.value();
        }))
      return std::nullopt; // No need to reorder.
    return std::move(ResOrder);
  }
  if (TE.State == TreeEntry::StridedVectorize && !TopToBottom &&
      (!TE.UserTreeIndex || !TE.UserTreeIndex.UserTE->hasState() ||
       !Instruction::isBinaryOp(TE.UserTreeIndex.UserTE->getOpcode())) &&
      (TE.ReorderIndices.empty() || TE.isReverse()))
    return std::nullopt;
  if (TE.State == TreeEntry::SplitVectorize ||
      ((TE.State == TreeEntry::Vectorize ||
        TE.State == TreeEntry::StridedVectorize ||
        TE.State == TreeEntry::ExpandVectorize ||
        TE.State == TreeEntry::CompressVectorize ||
        TE.State == TreeEntry::BlendedLoadVectorize) &&
       (isa<LoadInst, ExtractElementInst, ExtractValueInst>(TE.getMainOp()) ||
        (TopToBottom && isa<StoreInst, InsertElementInst, InsertValueInst>(
                            TE.getMainOp()))))) {
    assert((TE.State == TreeEntry::SplitVectorize || !TE.isAltShuffle()) &&
           "Alternate instructions are only supported by "
           "BinaryOperator and CastInst.");
    return TE.ReorderIndices;
  }
  if (!TopToBottom && IgnoreReorder && TE.State == TreeEntry::Vectorize &&
      TE.isAltShuffle()) {
    assert(TE.ReuseShuffleIndices.empty() &&
           "ReuseShuffleIndices should be "
           "empty for alternate instructions.");
    SmallVector<int> Mask;
    TE.buildAltOpShuffleMask(
        [&](Instruction *I) {
          assert(TE.getMatchingMainOpOrAltOp(I) &&
                 "Unexpected main/alternate opcode");
          return isAlternateInstruction(I, TE.getMainOp(), TE.getAltOp(), *TLI);
        },
        Mask);
    const int VF = TE.getVectorFactor();
    OrdersType ResOrder(VF, VF);
    for (unsigned I : seq<unsigned>(VF)) {
      if (Mask[I] == PoisonMaskElem)
        continue;
      ResOrder[Mask[I] % VF] = I;
    }
    return std::move(ResOrder);
  }
  if (!TE.ReorderIndices.empty())
    return TE.ReorderIndices;
  if (TE.State == TreeEntry::Vectorize && TE.getOpcode() == Instruction::PHI) {
    if (!TE.ReorderIndices.empty())
      return TE.ReorderIndices;

    SmallVector<Instruction *> UserBVHead(TE.Scalars.size());
    for (auto [I, V] :
         make_filter_range(zip(UserBVHead, TE.Scalars), [](const auto &P) {
           Value *V = std::get<1>(P);
           return !isa<Constant>(V) && V->hasNUsesOrMore(1);
         })) {
      auto *II = dyn_cast<InsertElementInst>(*V->user_begin());
      if (!II)
        continue;
      Instruction *BVHead = nullptr;
      BasicBlock *BB = II->getParent();
      while (II && II->hasOneUse() && II->getParent() == BB) {
        BVHead = II;
        II = dyn_cast<InsertElementInst>(II->getOperand(0));
      }
      I = BVHead;
    }

    auto CompareByBasicBlocks = [&](BasicBlock *BB1, BasicBlock *BB2) {
      assert(BB1 != BB2 && "Expected different basic blocks.");
      if (!DT->isReachableFromEntry(BB1))
        return false;
      if (!DT->isReachableFromEntry(BB2))
        return true;
      auto *NodeA = DT->getNode(BB1);
      auto *NodeB = DT->getNode(BB2);
      assert(NodeA && "Should only process reachable instructions");
      assert(NodeB && "Should only process reachable instructions");
      assert((NodeA == NodeB) ==
                 (NodeA->getDFSNumIn() == NodeB->getDFSNumIn()) &&
             "Different nodes should have different DFS numbers");
      return NodeA->getDFSNumIn() < NodeB->getDFSNumIn();
    };
    auto PHICompare = [&](unsigned I1, unsigned I2) {
      Value *V1 = TE.Scalars[I1];
      Value *V2 = TE.Scalars[I2];
      if (V1 == V2 || (V1->use_empty() && V2->use_empty()))
        return false;
      if (isa<PoisonValue>(V1))
        return true;
      if (isa<PoisonValue>(V2))
        return false;
      if (V1->getNumUses() < V2->getNumUses())
        return true;
      if (V1->getNumUses() > V2->getNumUses())
        return false;
      auto *FirstUserOfPhi1 = cast<Instruction>(*V1->user_begin());
      auto *FirstUserOfPhi2 = cast<Instruction>(*V2->user_begin());
      if (FirstUserOfPhi1->getParent() != FirstUserOfPhi2->getParent())
        return CompareByBasicBlocks(FirstUserOfPhi1->getParent(),
                                    FirstUserOfPhi2->getParent());
      auto *IE1 = dyn_cast<InsertElementInst>(FirstUserOfPhi1);
      auto *IE2 = dyn_cast<InsertElementInst>(FirstUserOfPhi2);
      auto *EE1 = dyn_cast<ExtractElementInst>(FirstUserOfPhi1);
      auto *EE2 = dyn_cast<ExtractElementInst>(FirstUserOfPhi2);
      if (IE1 && !IE2)
        return true;
      if (!IE1 && IE2)
        return false;
      if (IE1 && IE2) {
        if (UserBVHead[I1] && !UserBVHead[I2])
          return true;
        if (!UserBVHead[I1])
          return false;
        if (UserBVHead[I1] == UserBVHead[I2])
          return getElementIndex(IE1) < getElementIndex(IE2);
        if (UserBVHead[I1]->getParent() != UserBVHead[I2]->getParent())
          return CompareByBasicBlocks(UserBVHead[I1]->getParent(),
                                      UserBVHead[I2]->getParent());
        return UserBVHead[I1]->comesBefore(UserBVHead[I2]);
      }
      if (EE1 && !EE2)
        return true;
      if (!EE1 && EE2)
        return false;
      if (EE1 && EE2) {
        auto *Inst1 = dyn_cast<Instruction>(EE1->getOperand(0));
        auto *Inst2 = dyn_cast<Instruction>(EE2->getOperand(0));
        auto *P1 = dyn_cast<Argument>(EE1->getOperand(0));
        auto *P2 = dyn_cast<Argument>(EE2->getOperand(0));
        if (!Inst2 && !P2)
          return Inst1 || P1;
        if (EE1->getOperand(0) == EE2->getOperand(0))
          return getElementIndex(EE1) < getElementIndex(EE2);
        if (!Inst1 && Inst2)
          return false;
        if (Inst1 && Inst2) {
          if (Inst1->getParent() != Inst2->getParent())
            return CompareByBasicBlocks(Inst1->getParent(), Inst2->getParent());
          return Inst1->comesBefore(Inst2);
        }
        if (!P1 && P2)
          return false;
        assert(P1 && P2 &&
               "Expected either instructions or arguments vector operands.");
        return P1->getArgNo() < P2->getArgNo();
      }
      return false;
    };
    OrdersType Phis(TE.Scalars.size());
    std::iota(Phis.begin(), Phis.end(), 0);
    stable_sort(Phis, PHICompare);
    if (isIdentityOrder(Phis))
      return std::nullopt; // No need to reorder.
    return std::move(Phis);
  }
  if (TE.isGather() &&
      (!TE.hasState() || !TE.isAltShuffle() ||
       ScalarsInSplitNodes.contains(TE.getMainOp())) &&
      allSameType(TE.Scalars)) {
    // TODO: add analysis of other gather nodes with extractelement
    // instructions and other values/instructions, not only undefs.
    // Nodes with copyable lanes may mix in non-extract lanes, for which the
    // extract-index order is not applicable.
    if (((TE.hasState() && TE.getOpcode() == Instruction::ExtractElement &&
          !TE.hasCopyableElements()) ||
         (all_of(TE.Scalars, IsaPred<UndefValue, ExtractElementInst>) &&
          any_of(TE.Scalars, IsaPred<ExtractElementInst>))) &&
        all_of(make_isa_range<ExtractElementInst>(TE.Scalars),
               [](ExtractElementInst *EE) {
                 return isa<FixedVectorType>(EE->getVectorOperandType());
               })) {
      // Check that gather of extractelements can be represented as
      // just a shuffle of a single vector.
      OrdersType CurrentOrder;
      bool Reuse =
          canReuseExtract(TE.Scalars, CurrentOrder, /*ResizeAllowed=*/true);
      if (Reuse || !CurrentOrder.empty())
        return std::move(CurrentOrder);
    }
    // If the gather node is <undef, v, .., poison> and
    // insertelement poison, v, 0 [+ permute]
    // is cheaper than
    // insertelement poison, v, n - try to reorder.
    // If rotating the whole graph, exclude the permute cost, the whole graph
    // might be transformed.
    int Sz = TE.Scalars.size();
    if (isSplat(TE.Scalars) && !allConstant(TE.Scalars) &&
        count_if(TE.Scalars, IsaPred<UndefValue>) == Sz - 1) {
      const auto *It = find_if_not(TE.Scalars, isConstant);
      if (It == TE.Scalars.begin())
        return OrdersType();
      auto *Ty =
          cast<VectorType>(getWidenedType(TE.Scalars.front()->getType(), Sz));
      if (It != TE.Scalars.end()) {
        OrdersType Order(Sz, Sz);
        unsigned Idx = std::distance(TE.Scalars.begin(), It);
        Order[Idx] = 0;
        fixupOrderingIndices(Order);
        SmallVector<int> Mask;
        inversePermutation(Order, Mask);
        InstructionCost PermuteCost =
            TopToBottom ? 0
                        : getShuffleCost(*TTI, TTI::SK_PermuteSingleSrc, Ty,
                                         CostKind, Mask);
        InstructionCost InsertFirstCost =
            TTI->getVectorInstrCost(Instruction::InsertElement, Ty, CostKind, 0,
                                    PoisonValue::get(Ty), *It);
        InstructionCost InsertIdxCost =
            TTI->getVectorInstrCost(Instruction::InsertElement, Ty, CostKind,
                                    Idx, PoisonValue::get(Ty), *It);
        if (InsertFirstCost + PermuteCost < InsertIdxCost) {
          OrdersType Order(Sz, Sz);
          Order[Idx] = 0;
          return std::move(Order);
        }
      }
    }
    if (isSplat(TE.Scalars))
      return std::nullopt;
    if (TE.Scalars.size() >= 3)
      if (std::optional<OrdersType> Order = findPartiallyOrderedLoads(TE))
        return Order;
    // Check if can include the order of vectorized loads. For masked gathers do
    // extra analysis later, so include such nodes into a special list.
    if (TE.hasState() && TE.getOpcode() == Instruction::Load) {
      SmallVector<Value *> PointerOps;
      StridedPtrInfo SPtrInfo;
      OrdersType CurrentOrder;
      LoadsState Res = canVectorizeLoads(TE.Scalars, TE.Scalars.front(),
                                         CurrentOrder, PointerOps, SPtrInfo);
      if (Res == LoadsState::Vectorize || Res == LoadsState::StridedVectorize ||
          Res == LoadsState::CompressVectorize ||
          Res == LoadsState::BlendedLoadVectorize)
        return std::move(CurrentOrder);
    }
    if (std::optional<OrdersType> CurrentOrder =
            findReusedOrderedScalars(TE, TopToBottom, IgnoreReorder))
      return CurrentOrder;
  }
  return std::nullopt;
}

void BoUpSLP::reorderNodeWithReuses(TreeEntry &TE, ArrayRef<int> Mask) const {
  // Reorder reuses mask.
  reorderReuses(TE.ReuseShuffleIndices, Mask);
  const unsigned Sz = TE.Scalars.size();
  // For vectorized and non-clustered reused no need to do anything else.
  if (!TE.isGather() ||
      !ShuffleVectorInst::isOneUseSingleSourceMask(TE.ReuseShuffleIndices,
                                                   Sz) ||
      !isRepeatedNonIdentityClusteredMask(TE.ReuseShuffleIndices, Sz))
    return;
  SmallVector<int> NewMask;
  inversePermutation(TE.ReorderIndices, NewMask);
  addMask(NewMask, TE.ReuseShuffleIndices);
  // Clear reorder since it is going to be applied to the new mask.
  TE.ReorderIndices.clear();
  // Try to improve gathered nodes with clustered reuses, if possible.
  ArrayRef<int> Slice = ArrayRef(NewMask).slice(0, Sz);
  SmallVector<unsigned> NewOrder(Slice);
  inversePermutation(NewOrder, NewMask);
  reorderScalars(TE.Scalars, NewMask);
  // Fill the reuses mask with the identity submasks.
  for (auto *It = TE.ReuseShuffleIndices.begin(),
            *End = TE.ReuseShuffleIndices.end();
       It != End; std::advance(It, Sz))
    std::iota(It, std::next(It, Sz), 0);
}

bool BoUpSLP::isProfitableToReorder() const {
  if (Opts.slp_disable_tree_reorder)
    return false;

  constexpr unsigned TinyVF = 2;
  constexpr unsigned TinyTree = 10;
  constexpr unsigned PhiOpsLimit = 12;
  constexpr unsigned GatherLoadsLimit = 2;
  if (VectorizableTree.size() <= TinyTree)
    return true;
  if (getRootNode().hasState() && !getRootNode().isGather() &&
      (getRootNode().getOpcode() == Instruction::Store ||
       getRootNode().getOpcode() == Instruction::PHI ||
       (getRootNode().getVectorFactor() <= TinyVF &&
        (getRootNode().getOpcode() == Instruction::PtrToInt ||
         getRootNode().getOpcode() == Instruction::PtrToAddr ||
         getRootNode().getOpcode() == Instruction::ICmp))) &&
      getRootNode().ReorderIndices.empty()) {
    // Check if the tree has only single store and single (unordered) load node,
    // other nodes are phis or geps/binops, combined with phis, and/or single
    // gather load node
    if (getRootNode().hasState() &&
        getRootNode().getOpcode() == Instruction::PHI &&
        getRootNodeScalars().size() == TinyVF &&
        getRootNode().getNumOperands() > PhiOpsLimit)
      return false;
    // Single node, which require reorder - skip.
    if (getRootNode().hasState() &&
        getRootNode().getOpcode() == Instruction::Store &&
        getRootNode().ReorderIndices.empty()) {
      const unsigned ReorderedSplitsCnt =
          count_if(VectorizableTree, [&](const std::unique_ptr<TreeEntry> &TE) {
            return TE->State == TreeEntry::SplitVectorize &&
                   !TE->ReorderIndices.empty() && TE->UserTreeIndex.UserTE &&
                   TE->UserTreeIndex.UserTE->State == TreeEntry::Vectorize &&
                   isCommutative(TE->UserTreeIndex.UserTE->getMainOp());
          });
      if (ReorderedSplitsCnt <= 1 &&
          static_cast<unsigned>(count_if(
              VectorizableTree, [&](const std::unique_ptr<TreeEntry> &TE) {
                return ((!TE->isGather() &&
                         (TE->ReorderIndices.empty() ||
                          (TE->UserTreeIndex.UserTE &&
                           TE->UserTreeIndex.UserTE->State ==
                               TreeEntry::Vectorize &&
                           !TE->UserTreeIndex.UserTE->ReuseShuffleIndices
                                .empty()))) ||
                        (TE->isGather() && TE->ReorderIndices.empty() &&
                         (!TE->hasState() || TE->isAltShuffle() ||
                          TE->getOpcode() == Instruction::Load ||
                          TE->getOpcode() == Instruction::ZExt ||
                          TE->getOpcode() == Instruction::SExt))) &&
                       (getRootNode().getVectorFactor() > TinyVF ||
                        !TE->isGather() || none_of(TE->Scalars, [&](Value *V) {
                          return !isConstant(V) && isVectorized(V);
                        }));
              })) >= VectorizableTree.size() - ReorderedSplitsCnt)
        return false;
    }
    bool HasPhis = false;
    bool HasLoad = true;
    unsigned GatherLoads = 0;
    for (const std::unique_ptr<TreeEntry> &TE :
         ArrayRef(VectorizableTree).drop_front()) {
      if (TE->State == TreeEntry::SplitVectorize)
        continue;
      if (!TE->hasState()) {
        if (all_of(TE->Scalars, IsaPred<Constant, PHINode>) ||
            all_of(TE->Scalars, IsaPred<BinaryOperator, PHINode>))
          continue;
        if (getRootNodeScalars().size() == TinyVF &&
            any_of(TE->Scalars, IsaPred<PHINode, GEPOperator>))
          continue;
        return true;
      }
      if (TE->getOpcode() == Instruction::Load && TE->ReorderIndices.empty()) {
        if (!TE->isGather()) {
          HasLoad = false;
          continue;
        }
        if (HasLoad)
          return true;
        ++GatherLoads;
        if (GatherLoads >= GatherLoadsLimit)
          return true;
      }
      if (TE->getOpcode() == Instruction::GetElementPtr ||
          Instruction::isBinaryOp(TE->getOpcode()))
        continue;
      if (TE->getOpcode() != Instruction::PHI &&
          (!TE->hasCopyableElements() ||
           static_cast<unsigned>(count_if(TE->Scalars, IsaPred<PHINode>)) <
               TE->Scalars.size() / 2))
        return true;
      if (getRootNodeScalars().size() == TinyVF &&
          TE->getNumOperands() > PhiOpsLimit)
        return false;
      HasPhis = true;
    }
    return !HasPhis;
  }
  return true;
}

void BoUpSLP::TreeEntry::reorderSplitNode(unsigned Idx, ArrayRef<int> Mask,
                                          ArrayRef<int> MaskOrder) {
  assert(State == TreeEntry::SplitVectorize && "Expected split user node.");
  SmallVector<int> NewMask(getVectorFactor());
  SmallVector<int> NewMaskOrder(getVectorFactor());
  std::iota(NewMask.begin(), NewMask.end(), 0);
  std::iota(NewMaskOrder.begin(), NewMaskOrder.end(), 0);
  if (Idx == 0) {
    copy(Mask, NewMask.begin());
    copy(MaskOrder, NewMaskOrder.begin());
  } else {
    assert(Idx == 1 && "Expected either 0 or 1 index.");
    unsigned Offset = CombinedEntriesWithIndices.back().second;
    for (unsigned I : seq<unsigned>(Mask.size())) {
      NewMask[I + Offset] = Mask[I] + Offset;
      NewMaskOrder[I + Offset] = MaskOrder[I] + Offset;
    }
  }
  reorderScalars(Scalars, NewMask);
  reorderOrder(ReorderIndices, NewMaskOrder, /*BottomOrder=*/true);
  if (!ReorderIndices.empty() && BoUpSLP::isIdentityOrder(ReorderIndices))
    ReorderIndices.clear();
}

void BoUpSLP::markCopyableDepsForRecalc(TreeEntry &TE) {
  if (!TE.hasState())
    return;
  if (auto It = BlocksSchedules.find(TE.getMainOp()->getParent());
      It != BlocksSchedules.end())
    It->second->markCopyableDepsForRecalc(TE);
}

void BoUpSLP::reorderTopToBottom() {
  // Maps VF to the graph nodes.
  DenseMap<unsigned, SetVector<TreeEntry *>> VFToOrderedEntries;
  // ExtractElement gather nodes which can be vectorized and need to handle
  // their ordering.
  DenseMap<const TreeEntry *, OrdersType> GathersToOrders;

  // Phi nodes can have preferred ordering based on their result users
  DenseMap<const TreeEntry *, OrdersType> PhisToOrders;

  // AltShuffles can also have a preferred ordering that leads to fewer
  // instructions, e.g., the addsub instruction in x86.
  DenseMap<const TreeEntry *, OrdersType> AltShufflesToOrders;

  // Maps a TreeEntry to the reorder indices of external users.
  DenseMap<const TreeEntry *, SmallVector<OrdersType, 1>>
      ExternalUserReorderMap;
  // TODO: Reordering of struct types is not supported.
  if (any_of(VectorizableTree, [&](const std::unique_ptr<TreeEntry> &TE) {
        return TE->State == TreeEntry::Vectorize &&
               isa<StructType>(
                   getValueType(TE->Scalars.front(), Opts.slp_revec));
      }))
    return;
  // Compute IgnoreReorder once - it depends only on UserIgnoreList and
  // getRootNode(), which do not change during this loop.
  const bool IgnoreReorder =
      !UserIgnoreList && getRootNode().hasState() &&
      (getRootNode().getOpcode() == Instruction::InsertElement ||
       getRootNode().getOpcode() == Instruction::InsertValue ||
       getRootNode().getOpcode() == Instruction::Store);
  // The operand subtree of a blended load builds the blend mask in the lane
  // order of the load scalars, so it is not reordered with the graph.
  auto IsBlendedLoadOperand = [](const TreeEntry *TE) {
    for (; TE->UserTreeIndex; TE = TE->UserTreeIndex.UserTE)
      if (TE->UserTreeIndex.UserTE->State == TreeEntry::BlendedLoadVectorize)
        return true;
    return false;
  };
  // Find all reorderable nodes with the given VF.
  // Currently the are vectorized stores,loads,extracts + some gathering of
  // extracts.
  for_each(VectorizableTree, [&, &TTIRef = *TTI](
                                 const std::unique_ptr<TreeEntry> &TE) {
    if (IsBlendedLoadOperand(TE.get()))
      return;
    // Look for external users that will probably be vectorized.
    SmallVector<OrdersType, 1> ExternalUserReorderIndices =
        findExternalStoreUsersReorderIndices(TE.get());
    if (!ExternalUserReorderIndices.empty()) {
      VFToOrderedEntries[TE->getVectorFactor()].insert(TE.get());
      ExternalUserReorderMap.try_emplace(TE.get(),
                                         std::move(ExternalUserReorderIndices));
    }

    // Patterns like [fadd,fsub] can be combined into a single instruction in
    // x86. Reordering them into [fsub,fadd] blocks this pattern. So we need
    // to take into account their order when looking for the most used order.
    if (TE->hasState() && TE->isAltShuffle() &&
        TE->State != TreeEntry::SplitVectorize) {
      Type *ScalarTy = TE->Scalars[0]->getType();
      auto *VecTy =
          cast<VectorType>(getWidenedType(ScalarTy, TE->Scalars.size()));
      unsigned Opcode0 = TE->getOpcode();
      unsigned Opcode1 = TE->getAltOpcode();
      SmallBitVector OpcodeMask(
          getAltInstrMask(TE->Scalars, ScalarTy, Opcode0, Opcode1));
      // If this pattern is supported by the target then we consider the order.
      if (TTIRef.isLegalAltInstr(VecTy, Opcode0, Opcode1, OpcodeMask)) {
        VFToOrderedEntries[TE->getVectorFactor()].insert(TE.get());
        AltShufflesToOrders.try_emplace(TE.get(), OrdersType());
      }
      // TODO: Check the reverse order too.
    }

    if (std::optional<OrdersType> CurrentOrder =
            getReorderingData(*TE, /*TopToBottom=*/true, IgnoreReorder)) {
      // Do not include ordering for nodes used in the alt opcode vectorization,
      // better to reorder them during bottom-to-top stage. If follow the order
      // here, it causes reordering of the whole graph though actually it is
      // profitable just to reorder the subgraph that starts from the alternate
      // opcode vectorization node. Such nodes already end-up with the shuffle
      // instruction and it is just enough to change this shuffle rather than
      // rotate the scalars for the whole graph.
      unsigned Cnt = 0;
      const TreeEntry *UserTE = TE.get();
      while (UserTE && Cnt < Opts.slp_recursion_max_depth) {
        if (!UserTE->UserTreeIndex)
          break;
        if (UserTE->UserTreeIndex.UserTE->State == TreeEntry::Vectorize &&
            UserTE->UserTreeIndex.UserTE->isAltShuffle() &&
            UserTE->UserTreeIndex.UserTE->Idx != 0)
          return;
        UserTE = UserTE->UserTreeIndex.UserTE;
        ++Cnt;
      }
      VFToOrderedEntries[TE->getVectorFactor()].insert(TE.get());
      if (!(TE->State == TreeEntry::Vectorize ||
            TE->State == TreeEntry::StridedVectorize ||
            TE->State == TreeEntry::ExpandVectorize ||
            TE->State == TreeEntry::SplitVectorize ||
            TE->State == TreeEntry::CompressVectorize ||
            TE->State == TreeEntry::BlendedLoadVectorize) ||
          !TE->ReuseShuffleIndices.empty())
        GathersToOrders.try_emplace(TE.get(), *CurrentOrder);
      if (TE->State == TreeEntry::Vectorize &&
          TE->getOpcode() == Instruction::PHI)
        PhisToOrders.try_emplace(TE.get(), *CurrentOrder);
    }
  });

  // Reorder the graph nodes according to their vectorization factor.
  for (unsigned VF = getRootNode().getVectorFactor();
       !VFToOrderedEntries.empty() && VF > 1; --VF) {
    auto It = VFToOrderedEntries.find(VF);
    if (It == VFToOrderedEntries.end())
      continue;
    // Try to find the most profitable order. We just are looking for the most
    // used order and reorder scalar elements in the nodes according to this
    // mostly used order.
    ArrayRef<TreeEntry *> OrderedEntries = It->second.getArrayRef();
    // Delete VF entry upon exit.
    llvm::scope_exit Cleanup([&]() { VFToOrderedEntries.erase(It); });

    // All operands are reordered and used only in this node - propagate the
    // most used order to the user node.
    MapVector<OrdersType, unsigned,
              DenseMap<OrdersType, unsigned, OrdersTypeDenseMapInfo>>
        OrdersUses;
    // No need to reorder this nodes, still need to extend and to use shuffle,
    // just need to merge reordering shuffle and the reuse shuffle.
    for (const TreeEntry *OpTE :
         make_filter_range(OrderedEntries, [&](const TreeEntry *OpTE) {
           return OpTE->ReuseShuffleIndices.empty() ||
                  GathersToOrders.count(OpTE) ||
                  OpTE->State == TreeEntry::SplitVectorize;
         })) {
      // Count number of orders uses.
      const auto &Order = [OpTE, &GathersToOrders, &AltShufflesToOrders,
                           &PhisToOrders]() -> const OrdersType & {
        if (OpTE->isGather() || !OpTE->ReuseShuffleIndices.empty()) {
          auto It = GathersToOrders.find(OpTE);
          if (It != GathersToOrders.end())
            return It->second;
        }
        if (OpTE->hasState() && OpTE->isAltShuffle()) {
          auto It = AltShufflesToOrders.find(OpTE);
          if (It != AltShufflesToOrders.end())
            return It->second;
        }
        if (OpTE->State == TreeEntry::Vectorize &&
            OpTE->getOpcode() == Instruction::PHI) {
          auto It = PhisToOrders.find(OpTE);
          if (It != PhisToOrders.end())
            return It->second;
        }
        return OpTE->ReorderIndices;
      }();
      // First consider the order of the external scalar users.
      auto It = ExternalUserReorderMap.find(OpTE);
      if (It != ExternalUserReorderMap.end()) {
        const auto &ExternalUserReorderIndices = It->second;
        // If the OpTE vector factor != number of scalars - use natural order,
        // it is an attempt to reorder node with reused scalars but with
        // external uses.
        if (OpTE->getVectorFactor() != OpTE->Scalars.size()) {
          OrdersUses.try_emplace(OrdersType(), 0).first->second +=
              ExternalUserReorderIndices.size();
        } else {
          for (const OrdersType &ExtOrder : ExternalUserReorderIndices)
            ++OrdersUses.try_emplace(ExtOrder, 0).first->second;
        }
        // No other useful reorder data in this entry.
        if (Order.empty())
          continue;
      }
      // Stores actually store the mask, not the order, need to invert.
      if (OpTE->State == TreeEntry::Vectorize &&
          OpTE->getOpcode() == Instruction::Store && !Order.empty()) {
        assert(!OpTE->isAltShuffle() &&
               "Alternate instructions are only supported by BinaryOperator "
               "and CastInst.");
        SmallVector<int> Mask;
        inversePermutation(Order, Mask);
        unsigned E = Order.size();
        OrdersType CurrentOrder(E, E);
        transform(Mask, CurrentOrder.begin(), [E](int Idx) {
          return Idx == PoisonMaskElem ? E : static_cast<unsigned>(Idx);
        });
        fixupOrderingIndices(CurrentOrder);
        ++OrdersUses.try_emplace(CurrentOrder, 0).first->second;
      } else {
        ++OrdersUses.try_emplace(Order, 0).first->second;
      }
    }
    if (OrdersUses.empty())
      continue;
    // Choose the most used order.
    unsigned IdentityCnt = 0;
    unsigned FilledIdentityCnt = 0;
    OrdersType IdentityOrder(VF, VF);
    for (auto &Pair : OrdersUses) {
      if (Pair.first.empty() || isIdentityOrder(Pair.first)) {
        if (!Pair.first.empty())
          FilledIdentityCnt += Pair.second;
        IdentityCnt += Pair.second;
        combineOrders(IdentityOrder, Pair.first);
      }
    }
    MutableArrayRef<unsigned> BestOrder = IdentityOrder;
    unsigned Cnt = IdentityCnt;
    for (auto &Pair : OrdersUses) {
      // Prefer identity order. But, if filled identity found (non-empty order)
      // with same number of uses, as the new candidate order, we can choose
      // this candidate order.
      if (Cnt < Pair.second ||
          (Cnt == IdentityCnt && IdentityCnt == FilledIdentityCnt &&
           Cnt == Pair.second && !BestOrder.empty() &&
           isIdentityOrder(BestOrder))) {
        combineOrders(Pair.first, BestOrder);
        BestOrder = Pair.first;
        Cnt = Pair.second;
      } else {
        combineOrders(BestOrder, Pair.first);
      }
    }
    // Set order of the user node.
    if (isIdentityOrder(BestOrder))
      continue;
    fixupOrderingIndices(BestOrder);
    SmallVector<int> Mask;
    inversePermutation(BestOrder, Mask);
    SmallVector<int> MaskOrder(BestOrder.size(), PoisonMaskElem);
    unsigned E = BestOrder.size();
    transform(BestOrder, MaskOrder.begin(), [E](unsigned I) {
      return I < E ? static_cast<int>(I) : PoisonMaskElem;
    });
    // Do an actual reordering, if profitable.
    // The splat-gather subtree load roots stay in memory order: the reusing
    // gathers fetch lanes by value.
    for (std::unique_ptr<TreeEntry> &TE : make_filter_range(
             VectorizableTree, [&](std::unique_ptr<TreeEntry> &TE) {
               return (TE->State != TreeEntry::Vectorize ||
                       TE->getOpcode() != Instruction::Load ||
                       !is_contained(SplatGatheredScalarsRoots, TE.get())) &&
                      !IsBlendedLoadOperand(TE.get());
             })) {
      // Just do the reordering for the nodes with the given VF.
      if (TE->Scalars.size() != VF) {
        if (TE->ReuseShuffleIndices.size() == VF &&
            TE->State != TreeEntry::ExpandVectorize) {
          assert(TE->State != TreeEntry::SplitVectorize &&
                 "Split vectorized not expected.");
          // Need to reorder the reuses masks of the operands with smaller VF to
          // be able to find the match between the graph nodes and scalar
          // operands of the given node during vectorization/cost estimation.
          assert(
              (!TE->UserTreeIndex ||
               TE->UserTreeIndex.UserTE->Scalars.size() == VF ||
               TE->UserTreeIndex.UserTE->Scalars.size() == TE->Scalars.size() ||
               TE->UserTreeIndex.UserTE->State == TreeEntry::SplitVectorize) &&
              "All users must be of VF size.");
          if (Opts.slp_revec) {
            assert(Opts.slp_revec && "Only supported by REVEC.");
            // ShuffleVectorInst does not do reorderOperands (and it should not
            // because ShuffleVectorInst supports only a limited set of
            // patterns). Only do reorderNodeWithReuses if the user is not
            // ShuffleVectorInst.
            if (TE->UserTreeIndex && TE->UserTreeIndex.UserTE->hasState() &&
                isa<ShuffleVectorInst>(TE->UserTreeIndex.UserTE->getMainOp()))
              continue;
          }
          // Update ordering of the operands with the smaller VF than the given
          // one.
          reorderNodeWithReuses(*TE, Mask);
          // Update orders in user split vectorize nodes.
          if (TE->UserTreeIndex &&
              TE->UserTreeIndex.UserTE->State == TreeEntry::SplitVectorize)
            TE->UserTreeIndex.UserTE->reorderSplitNode(
                TE->UserTreeIndex.EdgeIdx, Mask, MaskOrder);
        }
        continue;
      }
      if ((TE->State == TreeEntry::SplitVectorize &&
           TE->ReuseShuffleIndices.empty()) ||
          ((TE->State == TreeEntry::Vectorize ||
            TE->State == TreeEntry::StridedVectorize ||
            TE->State == TreeEntry::ExpandVectorize ||
            TE->State == TreeEntry::CompressVectorize ||
            TE->State == TreeEntry::BlendedLoadVectorize) &&
           (isa<ExtractElementInst, ExtractValueInst, LoadInst, StoreInst,
                InsertElementInst, InsertValueInst>(TE->getMainOp()) ||
            (Opts.slp_revec && isa<ShuffleVectorInst>(TE->getMainOp()))))) {
        assert(
            (!TE->isAltShuffle() || (TE->State == TreeEntry::SplitVectorize &&
                                     TE->ReuseShuffleIndices.empty())) &&
            "Alternate instructions are only supported by BinaryOperator "
            "and CastInst.");
        // Build correct orders for extract{element,value}, loads,
        // stores and alternate (split) nodes.
        reorderOrder(TE->ReorderIndices, Mask);
        if (isa<InsertElementInst, InsertValueInst, StoreInst>(
                TE->getMainOp())) {
          TE->reorderOperands(Mask);
          markCopyableDepsForRecalc(*TE);
        }
      } else {
        // Reorder the node and its operands.
        TE->reorderOperands(Mask);
        markCopyableDepsForRecalc(*TE);
        assert(TE->ReorderIndices.empty() &&
               "Expected empty reorder sequence.");
        reorderScalars(TE->Scalars, Mask);
      }
      if (!TE->ReuseShuffleIndices.empty() &&
          TE->State != TreeEntry::ExpandVectorize) {
        // Apply reversed order to keep the original ordering of the reused
        // elements to avoid extra reorder indices shuffling. An ExpandVectorize
        // store keeps its expand mask fixed and carries the reorder in
        // ReorderIndices, so it is excluded here.
        OrdersType CurrentOrder;
        reorderOrder(CurrentOrder, MaskOrder);
        SmallVector<int> NewReuses;
        inversePermutation(CurrentOrder, NewReuses);
        addMask(NewReuses, TE->ReuseShuffleIndices);
        TE->ReuseShuffleIndices.swap(NewReuses);
      } else if (TE->UserTreeIndex &&
                 TE->UserTreeIndex.UserTE->State == TreeEntry::SplitVectorize)
        // Update orders in user split vectorize nodes.
        TE->UserTreeIndex.UserTE->reorderSplitNode(TE->UserTreeIndex.EdgeIdx,
                                                   Mask, MaskOrder);
    }
  }
}

void BoUpSLP::buildReorderableOperands(
    TreeEntry *UserTE, SmallVectorImpl<std::pair<unsigned, TreeEntry *>> &Edges,
    const SmallPtrSetImpl<const TreeEntry *> &ReorderableGathers,
    SmallVectorImpl<TreeEntry *> &GatherOps) {
  for (unsigned I : seq<unsigned>(UserTE->getNumOperands())) {
    if (any_of(Edges, [I](const std::pair<unsigned, TreeEntry *> &OpData) {
          return OpData.first == I &&
                 (OpData.second->State == TreeEntry::Vectorize ||
                  OpData.second->State == TreeEntry::StridedVectorize ||
                  OpData.second->State == TreeEntry::ExpandVectorize ||
                  OpData.second->State == TreeEntry::CompressVectorize ||
                  OpData.second->State == TreeEntry::BlendedLoadVectorize ||
                  OpData.second->State == TreeEntry::SplitVectorize);
        }))
      continue;
    // Do not request operands, if they do not exist.
    if (UserTE->hasState()) {
      if (UserTE->getOpcode() == Instruction::ExtractElement ||
          UserTE->getOpcode() == Instruction::ExtractValue)
        continue;
      if ((UserTE->getOpcode() == Instruction::InsertElement ||
           UserTE->getOpcode() == Instruction::InsertValue) &&
          I == 0)
        continue;
      if (UserTE->getOpcode() == Instruction::Store && I == 1 &&
          (UserTE->State == TreeEntry::Vectorize ||
           UserTE->State == TreeEntry::StridedVectorize ||
           UserTE->State == TreeEntry::ExpandVectorize))
        continue;
      if (UserTE->getOpcode() == Instruction::Load &&
          (UserTE->State == TreeEntry::Vectorize ||
           UserTE->State == TreeEntry::StridedVectorize ||
           UserTE->State == TreeEntry::CompressVectorize ||
           UserTE->State == TreeEntry::BlendedLoadVectorize))
        continue;
    }
    TreeEntry *TE = getOperandEntry(UserTE, I);
    assert(TE && "Expected operand entry.");
    if (!TE->isGather()) {
      // Add the node to the list of the ordered nodes with the identity
      // order.
      Edges.emplace_back(I, TE);
      // Add ScatterVectorize nodes to the list of operands, where just
      // reordering of the scalars is required. Similar to the gathers, so
      // simply add to the list of gathered ops.
      // If there are reused scalars, process this node as a regular vectorize
      // node, just reorder reuses mask.
      if (TE->State == TreeEntry::ScatterVectorize &&
          TE->ReuseShuffleIndices.empty() && TE->ReorderIndices.empty())
        GatherOps.push_back(TE);
      continue;
    }
    if (ReorderableGathers.contains(TE))
      GatherOps.push_back(TE);
  }
}

void BoUpSLP::reorderBottomToTop(bool IgnoreReorder) {
  struct TreeEntryCompare {
    bool operator()(const TreeEntry *LHS, const TreeEntry *RHS) const {
      if (LHS->UserTreeIndex && RHS->UserTreeIndex)
        return LHS->UserTreeIndex.UserTE->Idx < RHS->UserTreeIndex.UserTE->Idx;
      return LHS->Idx < RHS->Idx;
    }
  };
  PriorityQueue<TreeEntry *, SmallVector<TreeEntry *>, TreeEntryCompare> Queue;
  DenseSet<const TreeEntry *> GathersToOrders;
  // Find all reorderable leaf nodes with the given VF.
  // Currently the are vectorized loads,extracts without alternate operands +
  // some gathering of extracts.
  SmallPtrSet<const TreeEntry *, 4> NonVectorized;
  for (const std::unique_ptr<TreeEntry> &TE : VectorizableTree) {
    if (TE->State != TreeEntry::Vectorize &&
        TE->State != TreeEntry::StridedVectorize &&
        TE->State != TreeEntry::ExpandVectorize &&
        TE->State != TreeEntry::CompressVectorize &&
        TE->State != TreeEntry::BlendedLoadVectorize &&
        TE->State != TreeEntry::SplitVectorize)
      NonVectorized.insert(TE.get());
    if (std::optional<OrdersType> CurrentOrder =
            getReorderingData(*TE, /*TopToBottom=*/false, IgnoreReorder)) {
      Queue.push(TE.get());
      if (!(TE->State == TreeEntry::Vectorize ||
            TE->State == TreeEntry::StridedVectorize ||
            TE->State == TreeEntry::ExpandVectorize ||
            TE->State == TreeEntry::CompressVectorize ||
            TE->State == TreeEntry::BlendedLoadVectorize ||
            TE->State == TreeEntry::SplitVectorize) ||
          !TE->ReuseShuffleIndices.empty())
        GathersToOrders.insert(TE.get());
    }
  }

  // 1. Propagate order to the graph nodes, which use only reordered nodes.
  // I.e., if the node has operands, that are reordered, try to make at least
  // one operand order in the natural order and reorder others + reorder the
  // user node itself.
  SmallPtrSet<const TreeEntry *, 4> Visited, RevisitedOps;
  while (!Queue.empty()) {
    // 1. Filter out only reordered nodes.
    std::pair<TreeEntry *, SmallVector<std::pair<unsigned, TreeEntry *>>> Users;
    TreeEntry *TE = Queue.top();
    const TreeEntry *UserTE = TE->UserTreeIndex.UserTE;
    Queue.pop();
    SmallVector<TreeEntry *> OrderedOps(1, TE);
    while (!Queue.empty()) {
      TE = Queue.top();
      if (!UserTE || UserTE != TE->UserTreeIndex.UserTE)
        break;
      Queue.pop();
      OrderedOps.push_back(TE);
    }
    for (TreeEntry *TE : make_filter_range(OrderedOps, [&](TreeEntry *TE) {
           return (TE->State == TreeEntry::Vectorize ||
                   TE->State == TreeEntry::StridedVectorize ||
                   TE->State == TreeEntry::ExpandVectorize ||
                   TE->State == TreeEntry::CompressVectorize ||
                   TE->State == TreeEntry::BlendedLoadVectorize ||
                   TE->State == TreeEntry::SplitVectorize ||
                   (TE->isGather() && GathersToOrders.contains(TE))) &&
                  TE->UserTreeIndex &&
                  TE->UserTreeIndex.UserTE->State !=
                      TreeEntry::BlendedLoadVectorize &&
                  TE->ReuseShuffleIndices.empty() && Visited.insert(TE).second;
         })) {
      // Build a map between user nodes and their operands order to speedup
      // search. The graph currently does not provide this dependency directly.
      Users.first = TE->UserTreeIndex.UserTE;
      Users.second.emplace_back(TE->UserTreeIndex.EdgeIdx, TE);
    }
    if (Users.first) {
      auto &Data = Users;
      // TODO: Reordering of struct types is not supported.
      if (Data.first->State == TreeEntry::Vectorize &&
          isa<StructType>(
              getValueType(Data.first->Scalars.front(), Opts.slp_revec)))
        continue;
      if (Data.first->State == TreeEntry::SplitVectorize) {
        assert(
            Data.second.size() <= 2 &&
            "Expected not greater than 2 operands for split vectorize node.");
        if (any_of(Data.second,
                   [](const auto &Op) { return !Op.second->UserTreeIndex; }))
          continue;
        // Update orders in user split vectorize nodes.
        assert(Data.first->CombinedEntriesWithIndices.size() == 2 &&
               "Expected exactly 2 entries.");
        for (const auto &P : Data.first->CombinedEntriesWithIndices) {
          TreeEntry &OpTE = *VectorizableTree[P.first];
          // The order of an operand that has both reordered and reused scalars
          // cannot be absorbed into the split node cleanly: clearing the
          // reorder indices while keeping the reuse mask (or vice versa)
          // desyncs the split node scalars from the operand effective order.
          // Skip reordering for such operands.
          if (OpTE.State != TreeEntry::SplitVectorize &&
              !OpTE.ReorderIndices.empty() && !OpTE.ReuseShuffleIndices.empty())
            continue;
          OrdersType Order = OpTE.ReorderIndices;
          if (Order.empty() || !OpTE.ReuseShuffleIndices.empty()) {
            if (!OpTE.isGather() && OpTE.ReuseShuffleIndices.empty())
              continue;
            const auto BestOrder =
                getReorderingData(OpTE, /*TopToBottom=*/false, IgnoreReorder);
            if (!BestOrder || BestOrder->empty() || isIdentityOrder(*BestOrder))
              continue;
            Order = *BestOrder;
          }
          fixupOrderingIndices(Order);
          SmallVector<int> Mask;
          inversePermutation(Order, Mask);
          const unsigned E = Order.size();
          SmallVector<int> MaskOrder(E, PoisonMaskElem);
          transform(Order, MaskOrder.begin(), [E](unsigned I) {
            return I < E ? static_cast<int>(I) : PoisonMaskElem;
          });
          Data.first->reorderSplitNode(P.second ? 1 : 0, Mask, MaskOrder);
          // Clear ordering of the operand.
          if (!OpTE.ReorderIndices.empty()) {
            OpTE.ReorderIndices.clear();
          } else if (!OpTE.ReuseShuffleIndices.empty()) {
            reorderReuses(OpTE.ReuseShuffleIndices, Mask);
          } else {
            assert(OpTE.isGather() && "Expected only gather/buildvector node.");
            reorderScalars(OpTE.Scalars, Mask);
          }
        }
        if (Data.first->ReuseShuffleIndices.empty() &&
            !Data.first->ReorderIndices.empty()) {
          // Insert user node to the list to try to sink reordering deeper in
          // the graph.
          Queue.push(Data.first);
        }
        continue;
      }
      // Do not move the operand order to the root PHI node when the root
      // order must be preserved: the root has no user to take over the order
      // and it cannot be dropped at the end of the reordering.
      if (!IgnoreReorder && Data.first == &getRootNode() &&
          !Data.first->UserTreeIndex &&
          Data.first->State == TreeEntry::Vectorize &&
          Data.first->getOpcode() == Instruction::PHI &&
          Data.first->ReuseShuffleIndices.empty())
        continue;
      // Check that operands are used only in the User node.
      SmallVector<TreeEntry *> GatherOps;
      buildReorderableOperands(Data.first, Data.second, NonVectorized,
                               GatherOps);
      // All operands are reordered and used only in this node - propagate the
      // most used order to the user node.
      MapVector<OrdersType, unsigned,
                DenseMap<OrdersType, unsigned, OrdersTypeDenseMapInfo>>
          OrdersUses;
      // Do the analysis for each tree entry only once, otherwise the order of
      // the same node my be considered several times, though might be not
      // profitable.
      SmallPtrSet<const TreeEntry *, 4> VisitedOps;
      SmallPtrSet<const TreeEntry *, 4> VisitedUsers;
      for (const auto &Op : Data.second) {
        TreeEntry *OpTE = Op.second;
        if (!VisitedOps.insert(OpTE).second)
          continue;
        if (!OpTE->ReuseShuffleIndices.empty() && !GathersToOrders.count(OpTE))
          continue;
        const auto Order = [&]() -> const OrdersType {
          if (OpTE->isGather() || !OpTE->ReuseShuffleIndices.empty())
            return getReorderingData(*OpTE, /*TopToBottom=*/false,
                                     IgnoreReorder)
                .value_or(OrdersType(1));
          return OpTE->ReorderIndices;
        }();
        // The order is partially ordered, skip it in favor of fully non-ordered
        // orders.
        if (Order.size() == 1)
          continue;

        // Check that the reordering does not increase number of shuffles, i.e.
        // same-values-nodes has same parents or their parents has same parents.
        if (!Order.empty() && !isIdentityOrder(Order)) {
          Value *Root = OpTE->hasState()
                            ? OpTE->getMainOp()
                            : *find_if_not(OpTE->Scalars, isConstant);
          auto GetSameNodesUsers = [&](Value *Root) {
            SmallSetVector<TreeEntry *, 4> Res;
            for (const TreeEntry *TE : ValueToGatherNodes.lookup(Root)) {
              if (TE != OpTE && TE->UserTreeIndex &&
                  TE->getVectorFactor() == OpTE->getVectorFactor() &&
                  TE->Scalars.size() == OpTE->Scalars.size() &&
                  ((TE->ReorderIndices.empty() && OpTE->isSame(TE->Scalars)) ||
                   (OpTE->ReorderIndices.empty() && TE->isSame(OpTE->Scalars))))
                Res.insert(TE->UserTreeIndex.UserTE);
            }
            for (const TreeEntry *TE : getTreeEntries(Root)) {
              if (TE != OpTE && TE->UserTreeIndex &&
                  TE->getVectorFactor() == OpTE->getVectorFactor() &&
                  TE->Scalars.size() == OpTE->Scalars.size() &&
                  ((TE->ReorderIndices.empty() && OpTE->isSame(TE->Scalars)) ||
                   (OpTE->ReorderIndices.empty() && TE->isSame(OpTE->Scalars))))
                Res.insert(TE->UserTreeIndex.UserTE);
            }
            return Res.takeVector();
          };
          auto GetNumOperands = [](const TreeEntry *TE) {
            if (TE->State == TreeEntry::SplitVectorize)
              return TE->getNumOperands();
            if (auto *CI = dyn_cast<CallInst>(TE->getMainOp()); CI)
              return CI->arg_size();
            return TE->getNumOperands();
          };
          auto NodeShouldBeReorderedWithOperands = [&, TTI = TTI](
                                                       const TreeEntry *TE) {
            Intrinsic::ID ID = Intrinsic::not_intrinsic;
            if (auto *CI = dyn_cast<CallInst>(TE->getMainOp()); CI)
              ID = getVectorIntrinsicIDForCall(CI, TLI);
            for (unsigned Idx : seq<unsigned>(GetNumOperands(TE))) {
              if (ID != Intrinsic::not_intrinsic &&
                  isVectorIntrinsicWithScalarOpAtArg(ID, Idx, TTI))
                continue;
              const TreeEntry *Op = getOperandEntry(TE, Idx);
              if (Op->isGather() && Op->hasState()) {
                const TreeEntry *VecOp =
                    getSameValuesTreeEntry(Op->getMainOp(), Op->Scalars);
                if (VecOp)
                  Op = VecOp;
              }
              if (Op->ReorderIndices.empty() && Op->ReuseShuffleIndices.empty())
                return false;
            }
            return true;
          };
          SmallVector<TreeEntry *> Users = GetSameNodesUsers(Root);
          if (!Users.empty() && !all_of(Users, [&](TreeEntry *UTE) {
                if (!RevisitedOps.insert(UTE).second)
                  return false;
                return UTE == Data.first || !UTE->ReorderIndices.empty() ||
                       !UTE->ReuseShuffleIndices.empty() ||
                       (UTE->UserTreeIndex &&
                        UTE->UserTreeIndex.UserTE == Data.first) ||
                       (Data.first->UserTreeIndex &&
                        Data.first->UserTreeIndex.UserTE == UTE) ||
                       (IgnoreReorder && UTE->UserTreeIndex &&
                        UTE->UserTreeIndex.UserTE->Idx == 0) ||
                       NodeShouldBeReorderedWithOperands(UTE);
              }))
            continue;
          for (TreeEntry *UTE : Users) {
            Intrinsic::ID ID = Intrinsic::not_intrinsic;
            if (auto *CI = dyn_cast<CallInst>(UTE->getMainOp()); CI)
              ID = getVectorIntrinsicIDForCall(CI, TLI);
            for (unsigned Idx : seq<unsigned>(GetNumOperands(UTE))) {
              if (ID != Intrinsic::not_intrinsic &&
                  isVectorIntrinsicWithScalarOpAtArg(ID, Idx, TTI))
                continue;
              const TreeEntry *Op = getOperandEntry(UTE, Idx);
              Visited.erase(Op);
              Queue.push(const_cast<TreeEntry *>(Op));
            }
          }
        }
        unsigned NumOps = count_if(
            Data.second, [OpTE](const std::pair<unsigned, TreeEntry *> &P) {
              return P.second == OpTE;
            });
        // Stores actually store the mask, not the order, need to invert.
        if (OpTE->State == TreeEntry::Vectorize &&
            OpTE->getOpcode() == Instruction::Store && !Order.empty()) {
          assert(!OpTE->isAltShuffle() &&
                 "Alternate instructions are only supported by BinaryOperator "
                 "and CastInst.");
          SmallVector<int> Mask;
          inversePermutation(Order, Mask);
          unsigned E = Order.size();
          OrdersType CurrentOrder(E, E);
          transform(Mask, CurrentOrder.begin(), [E](int Idx) {
            return Idx == PoisonMaskElem ? E : static_cast<unsigned>(Idx);
          });
          fixupOrderingIndices(CurrentOrder);
          OrdersUses.try_emplace(CurrentOrder, 0).first->second += NumOps;
        } else {
          OrdersUses.try_emplace(Order, 0).first->second += NumOps;
        }
        auto Res = OrdersUses.try_emplace(OrdersType(), 0);
        const auto AllowsReordering = [&](const TreeEntry *TE) {
          if (!TE->ReorderIndices.empty() || !TE->ReuseShuffleIndices.empty() ||
              (TE->State == TreeEntry::Vectorize && TE->isAltShuffle()) ||
              (IgnoreReorder && TE->Idx == 0))
            return true;
          if (TE->isGather()) {
            if (GathersToOrders.contains(TE))
              return !getReorderingData(*TE, /*TopToBottom=*/false,
                                        IgnoreReorder)
                          .value_or(OrdersType(1))
                          .empty();
            return true;
          }
          return false;
        };
        if (OpTE->UserTreeIndex) {
          TreeEntry *UserTE = OpTE->UserTreeIndex.UserTE;
          if (!VisitedUsers.insert(UserTE).second)
            continue;
          // May reorder user node if it requires reordering, has reused
          // scalars, is an alternate op vectorize node or its op nodes require
          // reordering.
          if (AllowsReordering(UserTE))
            continue;
          // Check if users allow reordering.
          // Currently look up just 1 level of operands to avoid increase of
          // the compile time.
          // Profitable to reorder if definitely more operands allow
          // reordering rather than those with natural order.
          ArrayRef<std::pair<unsigned, TreeEntry *>> Ops = Users.second;
          if (static_cast<unsigned>(count_if(
                  Ops, [UserTE, &AllowsReordering](
                           const std::pair<unsigned, TreeEntry *> &Op) {
                    return AllowsReordering(Op.second) &&
                           Op.second->UserTreeIndex.UserTE == UserTE;
                  })) <= Ops.size() / 2)
            ++Res.first->second;
        }
      }
      if (OrdersUses.empty()) {
        Visited.insert_range(llvm::make_second_range(Data.second));
        continue;
      }
      // Choose the most used order.
      unsigned IdentityCnt = 0;
      unsigned VF = Data.second.front().second->getVectorFactor();
      OrdersType IdentityOrder(VF, VF);
      for (auto &Pair : OrdersUses) {
        if (Pair.first.empty() || isIdentityOrder(Pair.first)) {
          IdentityCnt += Pair.second;
          combineOrders(IdentityOrder, Pair.first);
        }
      }
      MutableArrayRef<unsigned> BestOrder = IdentityOrder;
      unsigned Cnt = IdentityCnt;
      for (auto &Pair : OrdersUses) {
        // Prefer identity order. But, if filled identity found (non-empty
        // order) with same number of uses, as the new candidate order, we can
        // choose this candidate order.
        if (Cnt < Pair.second) {
          combineOrders(Pair.first, BestOrder);
          BestOrder = Pair.first;
          Cnt = Pair.second;
        } else {
          combineOrders(BestOrder, Pair.first);
        }
      }
      // Set order of the user node.
      if (isIdentityOrder(BestOrder)) {
        Visited.insert_range(llvm::make_second_range(Data.second));
        continue;
      }
      fixupOrderingIndices(BestOrder);
      // Erase operands from OrderedEntries list and adjust their orders.
      VisitedOps.clear();
      SmallVector<int> Mask;
      inversePermutation(BestOrder, Mask);
      SmallVector<int> MaskOrder(BestOrder.size(), PoisonMaskElem);
      unsigned E = BestOrder.size();
      transform(BestOrder, MaskOrder.begin(), [E](unsigned I) {
        return I < E ? static_cast<int>(I) : PoisonMaskElem;
      });
      for (const std::pair<unsigned, TreeEntry *> &Op : Data.second) {
        TreeEntry *TE = Op.second;
        if (!VisitedOps.insert(TE).second)
          continue;
        // TODO: Reordering of struct types is not supported.
        if (TE->State == TreeEntry::Vectorize &&
            isa<StructType>(getValueType(TE->Scalars.front(), Opts.slp_revec)))
          continue;
        if (TE->ReuseShuffleIndices.size() == BestOrder.size()) {
          reorderNodeWithReuses(*TE, Mask);
          continue;
        }
        // Gathers are processed separately.
        if (TE->State != TreeEntry::Vectorize &&
            TE->State != TreeEntry::StridedVectorize &&
            TE->State != TreeEntry::ExpandVectorize &&
            TE->State != TreeEntry::CompressVectorize &&
            TE->State != TreeEntry::BlendedLoadVectorize &&
            TE->State != TreeEntry::SplitVectorize &&
            (TE->State != TreeEntry::ScatterVectorize ||
             TE->ReorderIndices.empty()))
          continue;
        assert((BestOrder.size() == TE->ReorderIndices.size() ||
                TE->ReorderIndices.empty()) &&
               "Non-matching sizes of user/operand entries.");
        reorderOrder(TE->ReorderIndices, Mask);
        if (IgnoreReorder && TE == &getRootNode())
          IgnoreReorder = false;
      }
      // For gathers just need to reorder its scalars.
      for (TreeEntry *Gather : GatherOps) {
        assert(Gather->ReorderIndices.empty() &&
               "Unexpected reordering of gathers.");
        if (!Gather->ReuseShuffleIndices.empty()) {
          // Just reorder reuses indices.
          reorderReuses(Gather->ReuseShuffleIndices, Mask);
          continue;
        }
        // A ScatterVectorize (masked gather) node is scheduled, and the
        // scheduler reads its operand list at the same lane where the scalar
        // load sits, so Scalars and the operand list must stay aligned.
        // Record the reorder in ReorderIndices (applied by the final shuffle)
        // instead of physically permuting the scalars, matching how a scatter
        // node with a non-empty order is reordered above.
        if (Gather->State == TreeEntry::ScatterVectorize) {
          reorderOrder(Gather->ReorderIndices, Mask);
          Visited.insert(Gather);
          continue;
        }
        reorderScalars(Gather->Scalars, Mask);
        Visited.insert(Gather);
      }
      // Reorder operands of the user node and set the ordering for the user
      // node itself.
      auto IsNotProfitableAltCodeNode = [](const TreeEntry &TE) {
        return TE.isAltShuffle() &&
               (!TE.ReuseShuffleIndices.empty() || TE.getVectorFactor() == 2 ||
                TE.ReorderIndices.empty());
      };
      if (Data.first->State != TreeEntry::Vectorize ||
          !isa<ExtractElementInst, ExtractValueInst, LoadInst>(
              Data.first->getMainOp()) ||
          IsNotProfitableAltCodeNode(*Data.first)) {
        Data.first->reorderOperands(Mask);
        markCopyableDepsForRecalc(*Data.first);
      }
      if (!isa<InsertElementInst, InsertValueInst, StoreInst>(
              Data.first->getMainOp()) ||
          IsNotProfitableAltCodeNode(*Data.first) ||
          Data.first->State == TreeEntry::CompressVectorize) {
        reorderScalars(Data.first->Scalars, Mask);
        reorderOrder(Data.first->ReorderIndices, MaskOrder,
                     /*BottomOrder=*/true);
        if (Data.first->ReuseShuffleIndices.empty() &&
            !Data.first->ReorderIndices.empty() &&
            !IsNotProfitableAltCodeNode(*Data.first)) {
          // Insert user node to the list to try to sink reordering deeper in
          // the graph.
          Queue.push(Data.first);
        }
      } else {
        reorderOrder(Data.first->ReorderIndices, Mask);
      }
    }
  }
  // If the reordering is unnecessary, just remove the reorder.
  if (IgnoreReorder && !getRootNode().ReorderIndices.empty() &&
      getRootNode().ReuseShuffleIndices.empty())
    getRootNode().ReorderIndices.clear();
}

Instruction *BoUpSLP::getRootEntryInstruction(const TreeEntry &Entry) const {
  if (Entry.hasState() &&
      (Entry.getOpcode() == Instruction::Store ||
       Entry.getOpcode() == Instruction::Load) &&
      Entry.State == TreeEntry::StridedVectorize && Entry.isReverse())
    return dyn_cast<Instruction>(Entry.Scalars[Entry.ReorderIndices.front()]);
  return dyn_cast<Instruction>(Entry.Scalars.front());
}

void BoUpSLP::buildExternalUses(
    const ExtraValueToDebugLocsMap &ExternallyUsedValues) {
  const size_t NumVectScalars = ScalarToTreeEntries.size() + 1;
  DenseMap<Value *, unsigned> ScalarToExtUses;
  // Peeled scalars still claimed by the tree (gathered, listed in some
  // entry's scalars, or modeled as a copyable element, which is emitted as
  // a scalar) survive as plain code, along with the peeled scalars
  // in their operand chains, which no vector node can rematerialize.
  KeptReassocScalars.clear();
  SmallVector<const Value *, 8> KeptWorklist;
  for (const auto &[V, Owners] : ReassocScalarToTreeEntries)
    if ((isGathered(V) || !getTreeEntries(V).empty() ||
         any_of(Owners,
                [V = V](const TreeEntry *TE) {
                  return TE->isCopyableElement(const_cast<Value *>(V));
                })) &&
        KeptReassocScalars.insert(V).second)
      KeptWorklist.push_back(V);
  while (!KeptWorklist.empty()) {
    const Value *V = KeptWorklist.pop_back_val();
    for (const Value *Op : cast<Instruction>(V)->operand_values())
      if (ReassocScalarToTreeEntries.contains(Op) &&
          KeptReassocScalars.insert(Op).second)
        KeptWorklist.push_back(Op);
  }
  // Collect the values that we need to extract from the tree.
  for (auto &TEPtr : VectorizableTree) {
    TreeEntry *Entry = TEPtr.get();

    // No need to handle users of gathered values.
    if (Entry->isGather() || Entry->State == TreeEntry::SplitVectorize ||
        DeletedNodes.contains(Entry) ||
        TransformedToGatherNodes.contains(Entry))
      continue;

    // For each lane:
    for (int Lane = 0, LE = Entry->Scalars.size(); Lane != LE; ++Lane) {
      Value *Scalar = Entry->Scalars[Lane];
      if (!isa<Instruction>(Scalar) || Entry->isCopyableElement(Scalar))
        continue;
      bool IsStructScalar = isa<StructType>(Scalar->getType());

      // All uses must be replaced already? No need to do it again.
      auto It = ScalarToExtUses.find(Scalar);
      if (It != ScalarToExtUses.end() && !ExternalUses[It->second].User)
        continue;

      if (!IsStructScalar && Scalar->hasNUsesOrMore(NumVectScalars)) {
        unsigned FoundLane = Entry->findLaneForValue(Scalar);
        LLVM_DEBUG(dbgs() << "SLP: Need to extract from lane " << FoundLane
                          << " from " << *Scalar << "for many users.\n");
        It = ScalarToExtUses.try_emplace(Scalar, ExternalUses.size()).first;
        ExternalUses.emplace_back(Scalar, nullptr, *Entry, FoundLane);
        ExternalUsesWithNonUsers.insert(Scalar);
        continue;
      }

      // Check if the scalar is externally used as an extra arg.
      const auto ExtI = ExternallyUsedValues.find(Scalar);
      if (ExtI != ExternallyUsedValues.end()) {
        unsigned FoundLane = Entry->findLaneForValue(Scalar);
        LLVM_DEBUG(dbgs() << "SLP: Need to extract: Extra arg from lane "
                          << FoundLane << " from " << *Scalar << ".\n");
        ScalarToExtUses.try_emplace(Scalar, ExternalUses.size());
        ExternalUses.emplace_back(Scalar, nullptr, *Entry, FoundLane);
        continue;
      }
      for (User *U : Scalar->users()) {
        LLVM_DEBUG(dbgs() << "SLP: Checking user:" << *U << ".\n");

        Instruction *UserInst = dyn_cast<Instruction>(U);
        if (!UserInst || isDeleted(UserInst))
          continue;

        // Ignore users in the user ignore list.
        if (UserIgnoreList && UserIgnoreList->contains(UserInst))
          continue;

        // Peeled reassociated scalars are subsumed by the flattened node and
        // erased during vectorization, not external users. Kept ones survive
        // and their uses of erased scalars become extracts like any other.
        if (isReassocScalarVectorized(UserInst) &&
            !KeptReassocScalars.contains(UserInst)) {
          LLVM_DEBUG(dbgs() << "SLP: \tInternal (reassociated) user will be "
                               "removed:"
                            << *U << ".\n");
          continue;
        }

        // Skip in-tree scalars that become vectors
        if (ArrayRef<TreeEntry *> UseEntries = getTreeEntries(U);
            any_of(UseEntries, [this](const TreeEntry *UseEntry) {
              return !DeletedNodes.contains(UseEntry) &&
                     !TransformedToGatherNodes.contains(UseEntry);
            })) {
          // Some in-tree scalars will remain as scalar in vectorized
          // instructions. If that is the case, the one in FoundLane will
          // be used.
          if (!((Scalar->getType()->getScalarType()->isPointerTy() &&
                 isa<LoadInst, StoreInst>(UserInst)) ||
                isa<CallInst>(UserInst)) ||
              all_of(UseEntries, [&](TreeEntry *UseEntry) {
                if (DeletedNodes.contains(UseEntry) ||
                    TransformedToGatherNodes.contains(UseEntry))
                  return true;
                return UseEntry->State == TreeEntry::ScatterVectorize ||
                       !doesInTreeUserNeedToExtract(
                           Scalar, getRootEntryInstruction(*UseEntry), TLI,
                           TTI);
              })) {
            LLVM_DEBUG(dbgs() << "SLP: \tInternal user will be removed:" << *U
                              << ".\n");
            assert(none_of(UseEntries,
                           [](TreeEntry *UseEntry) {
                             return UseEntry->isGather();
                           }) &&
                   "Bad state");
            continue;
          }
          if (!IsStructScalar) {
            U = nullptr;
            if (It != ScalarToExtUses.end()) {
              ExternalUses[It->second].User = nullptr;
              break;
            }
          }
        }

        if (U && !IsStructScalar && Scalar->hasNUsesOrMore(UsesLimit))
          U = nullptr;
        unsigned FoundLane = Entry->findLaneForValue(Scalar);
        LLVM_DEBUG(dbgs() << "SLP: Need to extract:" << *UserInst
                          << " from lane " << FoundLane << " from " << *Scalar
                          << ".\n");
        It = ScalarToExtUses.try_emplace(Scalar, ExternalUses.size()).first;
        ExternalUses.emplace_back(Scalar, U, *Entry, FoundLane);
        ExternalUsesWithNonUsers.insert(Scalar);
        if (!U)
          break;
      }
    }
  }

  // The expansion of the runtime stride may reuse an in-tree instruction with
  // the matching SCEV, which gets erased upon vectorization. Register an
  // external use for it to replace the stride operand with the extract.
  SmallVector<std::pair<const SCEV *, BasicBlock *>> Strides;
  for (const auto &[StridedTE, SPtrInfo] : TreeEntryToStridedPtrInfoMap)
    if (SPtrInfo.StrideSCEV && !SPtrInfo.StrideVal &&
        !DeletedNodes.contains(StridedTE) &&
        !TransformedToGatherNodes.contains(StridedTE))
      Strides.emplace_back(SPtrInfo.StrideSCEV,
                           StridedTE->getMainOp()->getParent());
  if (Strides.empty())
    return;
  for (const std::unique_ptr<TreeEntry> &TEPtr : VectorizableTree) {
    TreeEntry *Entry = TEPtr.get();
    if (Entry->isGather() || Entry->State == TreeEntry::SplitVectorize ||
        DeletedNodes.contains(Entry) ||
        TransformedToGatherNodes.contains(Entry))
      continue;
    for (Instruction *Scalar : make_isa_range<Instruction>(Entry->Scalars)) {
      if (Entry->isCopyableElement(Scalar) ||
          !SE->isSCEVable(Scalar->getType()))
        continue;
      const SCEV *ScalarSCEV = SE->getSCEV(Scalar);
      if (isa<SCEVConstant>(ScalarSCEV) ||
          none_of(Strides, [&](const auto &Stride) {
            return DT->dominates(Scalar, Stride.second->getTerminator()) &&
                   SCEVExprContains(Stride.first, [ScalarSCEV](const SCEV *S) {
                     return S == ScalarSCEV;
                   });
          }))
        continue;
      auto It = ScalarToExtUses.find(Scalar);
      if (It != ScalarToExtUses.end()) {
        // Replace all uses: the stride operand is emitted later, during the
        // codegen.
        ExternalUses[It->second].User = nullptr;
        continue;
      }
      unsigned FoundLane = Entry->findLaneForValue(Scalar);
      LLVM_DEBUG(dbgs() << "SLP: Need to extract: strided load stride from "
                           "lane "
                        << FoundLane << " from " << *Scalar << ".\n");
      ScalarToExtUses.try_emplace(Scalar, ExternalUses.size());
      ExternalUses.emplace_back(Scalar, nullptr, *Entry, FoundLane);
      ExternalUsesWithNonUsers.insert(Scalar);
    }
  }
}

SmallVector<SmallVector<StoreInst *>>
BoUpSLP::collectUserStores(const BoUpSLP::TreeEntry *TE) const {
  SmallDenseMap<std::tuple<BasicBlock *, Type *, Value *>,
                SmallVector<StoreInst *>, 8>
      PtrToStoresMap;
  for (unsigned Lane : seq<unsigned>(0, TE->Scalars.size())) {
    Value *V = TE->Scalars[Lane];
    // Don't iterate over the users of constant data.
    if (!isa<Instruction>(V))
      continue;
    // To save compilation time we don't visit if we have too many users.
    if (V->hasNUsesOrMore(UsesLimit))
      break;

    // Collect stores per pointer object.
    for (User *U : V->users()) {
      auto *SI = dyn_cast<StoreInst>(U);
      // Test whether we can handle the store. V might be a global, which could
      // be used in a different function.
      if (SI == nullptr || !SI->isSimple() || SI->getFunction() != F ||
          !isValidElementType(SI->getValueOperand()->getType(), Opts.slp_revec))
        continue;
      // Skip entry if already
      if (isVectorized(U))
        continue;

      Value *Ptr = getUnderlyingObject(SI->getPointerOperand(),
                                       Opts.slp_recursion_max_depth);
      auto &StoresVec = PtrToStoresMap[{SI->getParent(),
                                        SI->getValueOperand()->getType(), Ptr}];
      // For now just keep one store per pointer object per lane.
      // TODO: Extend this to support multiple stores per pointer per lane
      if (StoresVec.size() > Lane)
        continue;
      if (!StoresVec.empty()) {
        std::optional<int64_t> Diff = getPointersDiff(
            SI->getValueOperand()->getType(), SI->getPointerOperand(),
            SI->getValueOperand()->getType(),
            StoresVec.front()->getPointerOperand(), *DL, *SE,
            /*StrictCheck=*/true);
        // We failed to compare the pointers so just abandon this store.
        if (!Diff)
          continue;
      }
      StoresVec.push_back(SI);
    }
  }
  SmallVector<SmallVector<StoreInst *>> Res(PtrToStoresMap.size());
  unsigned I = 0;
  for (auto &P : PtrToStoresMap) {
    Res[I].swap(P.second);
    ++I;
  }
  return Res;
}

bool BoUpSLP::canFormVector(ArrayRef<StoreInst *> StoresVec,
                            OrdersType &ReorderIndices) const {
  // We check whether the stores in StoreVec can form a vector by sorting them
  // and checking whether they are consecutive.

  // To avoid calling getPointersDiff() while sorting we create a vector of
  // pairs {store, offset from first} and sort this instead.
  SmallVector<std::pair<int64_t, unsigned>> StoreOffsetVec;
  StoreInst *S0 = StoresVec[0];
  StoreOffsetVec.emplace_back(0, 0);
  Type *S0Ty = S0->getValueOperand()->getType();
  Value *S0Ptr = S0->getPointerOperand();
  for (unsigned Idx : seq<unsigned>(1, StoresVec.size())) {
    StoreInst *SI = StoresVec[Idx];
    std::optional<int64_t> Diff =
        getPointersDiff(S0Ty, S0Ptr, SI->getValueOperand()->getType(),
                        SI->getPointerOperand(), *DL, *SE,
                        /*StrictCheck=*/true);
    StoreOffsetVec.emplace_back(*Diff, Idx);
  }

  // Check if the stores are consecutive by checking if their difference is 1.
  if (StoreOffsetVec.size() != StoresVec.size())
    return false;
  sort(StoreOffsetVec, llvm::less_first());
  unsigned Idx = 0;
  int64_t PrevDist = 0;
  for (const auto &P : StoreOffsetVec) {
    if (Idx > 0 && P.first != PrevDist + 1)
      return false;
    PrevDist = P.first;
    ++Idx;
  }

  // Calculate the shuffle indices according to their offset against the sorted
  // StoreOffsetVec.
  ReorderIndices.assign(StoresVec.size(), 0);
  bool IsIdentity = true;
  for (auto [I, P] : enumerate(StoreOffsetVec)) {
    ReorderIndices[P.second] = I;
    IsIdentity &= P.second == I;
  }
  // Identity order (e.g., {0,1,2,3}) is modeled as an empty OrdersType in
  // reorderTopToBottom() and reorderBottomToTop(), so we are following the
  // same convention here.
  if (IsIdentity)
    ReorderIndices.clear();

  return true;
}

#ifndef NDEBUG
LLVM_DUMP_METHOD static void dumpOrder(const BoUpSLP::OrdersType &Order) {
  for (unsigned Idx : Order)
    dbgs() << Idx << ", ";
  dbgs() << "\n";
}
#endif

SmallVector<BoUpSLP::OrdersType, 1>
BoUpSLP::findExternalStoreUsersReorderIndices(TreeEntry *TE) const {
  unsigned NumLanes = TE->Scalars.size();

  SmallVector<SmallVector<StoreInst *>> Stores = collectUserStores(TE);

  // Holds the reorder indices for each candidate store vector that is a user of
  // the current TreeEntry.
  SmallVector<OrdersType, 1> ExternalReorderIndices;

  // Now inspect the stores collected per pointer and look for vectorization
  // candidates. For each candidate calculate the reorder index vector and push
  // it into `ExternalReorderIndices`
  // If we have fewer than NumLanes stores, then we can't form a vector.
  for (ArrayRef<StoreInst *> StoresVec :
       make_filter_range(Stores, [&](ArrayRef<StoreInst *> StoresVec) {
         return StoresVec.size() == NumLanes;
       })) {
    // If the stores are not consecutive then abandon this StoresVec.
    OrdersType ReorderIndices;
    if (!canFormVector(StoresVec, ReorderIndices))
      continue;

    // We now know that the scalars in StoresVec can form a vector instruction,
    // so set the reorder indices.
    ExternalReorderIndices.push_back(ReorderIndices);
  }
  return ExternalReorderIndices;
}

void BoUpSLP::buildTree(ArrayRef<Value *> Roots,
                        const SmallDenseSet<Value *> &UserIgnoreLst) {
  deleteTree();
  assert(TreeEntryToStridedPtrInfoMap.empty() &&
         "TreeEntryToStridedPtrInfoMap is not cleared");
  UserIgnoreList = &UserIgnoreLst;
  if (!allSameType(Roots))
    return;
  buildTreeRec(Roots, 0, EdgeInfo());
  // Build splat-gather subtrees here so the reordering passes cover them too.
  tryToVectorizeSplatGatheredScalars();
}

void BoUpSLP::buildTree(ArrayRef<Value *> Roots) {
  deleteTree();
  assert(TreeEntryToStridedPtrInfoMap.empty() &&
         "TreeEntryToStridedPtrInfoMap is not cleared");
  if (!allSameType(Roots))
    return;
  buildTreeRec(Roots, 0, EdgeInfo());
  // Build splat-gather subtrees here so the reordering passes cover them too.
  tryToVectorizeSplatGatheredScalars();
}

/// Tries to find subvector of loads and builds new vector of only loads if can
/// be profitable.
static void gatherPossiblyVectorizableLoads(
    const BoUpSLP &R, ArrayRef<Value *> VL, const DataLayout &DL,
    ScalarEvolution &SE, const TargetTransformInfo &TTI,
    SmallVectorImpl<SmallVector<std::pair<LoadInst *, int64_t>>> &GatheredLoads,
    bool AddNew = true) {
  if (VL.empty())
    return;
  Type *ScalarTy = getValueType(VL.front(), R.Opts.slp_revec);
  if (!isValidElementType(ScalarTy, R.Opts.slp_revec))
    return;
  SmallVector<SmallVector<std::pair<LoadInst *, int64_t>>> ClusteredLoads;
  SmallVector<DenseMap<int64_t, LoadInst *>> ClusteredDistToLoad;
  for (LoadInst *LI : make_isa_range<LoadInst>(VL)) {
    if (R.isDeleted(LI) || R.isVectorized(LI) || !LI->isSimple())
      continue;
    bool IsFound = false;
    for (auto [Map, Data] : zip(ClusteredDistToLoad, ClusteredLoads)) {
      assert(LI->getParent() == Data.front().first->getParent() &&
             LI->getType() == Data.front().first->getType() &&
             getUnderlyingObject(LI->getPointerOperand(),
                                 R.Opts.slp_recursion_max_depth) ==
                 getUnderlyingObject(Data.front().first->getPointerOperand(),
                                     R.Opts.slp_recursion_max_depth) &&
             "Expected loads with the same type, same parent and same "
             "underlying pointer.");
      std::optional<int64_t> Dist = R.getPointersDiff(
          LI->getType(), LI->getPointerOperand(), Data.front().first->getType(),
          Data.front().first->getPointerOperand(), DL, SE,
          /*StrictCheck=*/true);
      if (!Dist)
        continue;
      auto It = Map.find(*Dist);
      if (It != Map.end() && It->second != LI)
        continue;
      if (It == Map.end()) {
        Data.emplace_back(LI, *Dist);
        Map.try_emplace(*Dist, LI);
      }
      IsFound = true;
      break;
    }
    if (!IsFound) {
      ClusteredLoads.emplace_back().emplace_back(LI, 0);
      ClusteredDistToLoad.emplace_back().try_emplace(0, LI);
    }
  }
  auto FindMatchingLoads =
      [&](ArrayRef<std::pair<LoadInst *, int64_t>> Loads,
          SmallVectorImpl<SmallVector<std::pair<LoadInst *, int64_t>>>
              &GatheredLoads,
          SetVector<unsigned> &ToAdd, SetVector<unsigned> &Repeated,
          int64_t &Offset, unsigned &Start) {
        if (Loads.empty())
          return GatheredLoads.end();
        LoadInst *LI = Loads.front().first;
        auto IsFromStart = [&](const auto &P) { return P.index() >= Start; };
        for (auto [Idx, Data] :
             make_filter_range(enumerate(GatheredLoads), IsFromStart)) {
          ToAdd.clear();
          if (LI->getParent() != Data.front().first->getParent() ||
              LI->getType() != Data.front().first->getType())
            continue;
          std::optional<int64_t> Dist =
              R.getPointersDiff(LI->getType(), LI->getPointerOperand(),
                                Data.front().first->getType(),
                                Data.front().first->getPointerOperand(), DL, SE,
                                /*StrictCheck=*/true);
          if (!Dist)
            continue;
          SmallSet<int64_t, 4> DataDists;
          SmallPtrSet<LoadInst *, 4> DataLoads;
          for (std::pair<LoadInst *, int64_t> P : Data) {
            DataDists.insert(P.second);
            DataLoads.insert(P.first);
          }
          // Found matching gathered loads - check if all loads are unique or
          // can be effectively vectorized.
          unsigned NumUniques = 0;
          for (auto [Cnt, Pair] : enumerate(Loads)) {
            bool Used = DataLoads.contains(Pair.first);
            if (!Used && !DataDists.contains(*Dist + Pair.second)) {
              ++NumUniques;
              ToAdd.insert(Cnt);
            } else if (Used) {
              Repeated.insert(Cnt);
            }
          }
          if (NumUniques > 0 &&
              (Loads.size() == NumUniques ||
               (Loads.size() - NumUniques >= 2 &&
                Loads.size() - NumUniques >= Loads.size() / 2 &&
                (has_single_bit(Data.size() + NumUniques) ||
                 bit_ceil(Data.size()) <
                     bit_ceil(Data.size() + NumUniques))))) {
            Offset = *Dist;
            Start = Idx + 1;
            return std::next(GatheredLoads.begin(), Idx);
          }
        }
        ToAdd.clear();
        return GatheredLoads.end();
      };
  for (ArrayRef<std::pair<LoadInst *, int64_t>> Data : ClusteredLoads) {
    unsigned Start = 0;
    SetVector<unsigned> ToAdd, LocalToAdd, Repeated;
    int64_t Offset = 0;
    auto *It = FindMatchingLoads(Data, GatheredLoads, LocalToAdd, Repeated,
                                 Offset, Start);
    while (It != GatheredLoads.end()) {
      assert(!LocalToAdd.empty() && "Expected some elements to add.");
      for (unsigned Idx : LocalToAdd)
        It->emplace_back(Data[Idx].first, Data[Idx].second + Offset);
      ToAdd.insert_range(LocalToAdd);
      It = FindMatchingLoads(Data, GatheredLoads, LocalToAdd, Repeated, Offset,
                             Start);
    }
    if (any_of(seq<unsigned>(Data.size()), [&](unsigned Idx) {
          return !ToAdd.contains(Idx) && !Repeated.contains(Idx);
        })) {
      auto AddNewLoads =
          [&](SmallVectorImpl<std::pair<LoadInst *, int64_t>> &Loads) {
            for (unsigned Idx : seq<unsigned>(Data.size())) {
              if (ToAdd.contains(Idx) || Repeated.contains(Idx))
                continue;
              Loads.push_back(Data[Idx]);
            }
          };
      if (!AddNew) {
        LoadInst *LI = Data.front().first;
        It = find_if(
            GatheredLoads, [&](ArrayRef<std::pair<LoadInst *, int64_t>> PD) {
              return PD.front().first->getParent() == LI->getParent() &&
                     PD.front().first->getType() == LI->getType();
            });
        while (It != GatheredLoads.end()) {
          AddNewLoads(*It);
          It = std::find_if(
              std::next(It), GatheredLoads.end(),
              [&](ArrayRef<std::pair<LoadInst *, int64_t>> PD) {
                return PD.front().first->getParent() == LI->getParent() &&
                       PD.front().first->getType() == LI->getType();
              });
        }
      }
      GatheredLoads.emplace_back().append(Data.begin(), Data.end());
      AddNewLoads(GatheredLoads.emplace_back());
    }
  }
}

void BoUpSLP::tryToVectorizeGatheredLoads(
    const SmallMapVector<
        std::tuple<BasicBlock *, Value *, Type *>,
        SmallVector<SmallVector<std::pair<LoadInst *, int64_t>>>, 8>
        &GatheredLoads) {
  GatheredLoadsEntriesFirst = VectorizableTree.size();

  SmallVector<SmallPtrSet<const Value *, 4>> LoadSetsToVectorize(
      LoadEntriesToVectorize.size());
  for (auto [Idx, Set] : zip(LoadEntriesToVectorize, LoadSetsToVectorize))
    Set.insert_range(VectorizableTree[Idx]->Scalars);

  // Sort loads by distance.
  auto LoadSorter = [](const std::pair<LoadInst *, int64_t> &L1,
                       const std::pair<LoadInst *, int64_t> &L2) {
    return L1.second > L2.second;
  };

  auto IsMaskedGatherSupported = [&, TTI = TTI](ArrayRef<LoadInst *> Loads) {
    ArrayRef<Value *> Values(reinterpret_cast<Value *const *>(Loads.begin()),
                             Loads.size());
    Align Alignment = computeCommonAlignment<LoadInst>(Values);
    auto *Ty = cast<VectorType>(
        getWidenedType(Loads.front()->getType(), Loads.size()));
    return TTI->isLegalMaskedGather(Ty, Alignment) &&
           !TTI->forceScalarizeMaskedGather(Ty, Alignment);
  };

  auto GetVectorizedRanges = [this](ArrayRef<LoadInst *> Loads,
                                    BoUpSLP::ValueSet &VectorizedLoads,
                                    SmallVectorImpl<LoadInst *> &NonVectorized,
                                    bool Final, unsigned MaxVF) {
    SmallVector<std::pair<ArrayRef<Value *>, LoadsState>> Results;
    unsigned StartIdx = 0;
    SmallVector<int> CandidateVFs;
    if (isAllowedNonPowerOf2VF(MaxVF, Opts.slp_vectorize_non_power_of_2))
      CandidateVFs.push_back(MaxVF);
    for (int NumElts = getFloorFullVectorNumberOfElements(
             *TTI, Loads.front()->getType(), MaxVF, Opts.slp_revec);
         NumElts > 1;
         NumElts = getFloorFullVectorNumberOfElements(
             *TTI, Loads.front()->getType(), NumElts - 1, Opts.slp_revec)) {
      CandidateVFs.push_back(NumElts);
      if (Opts.slp_vectorize_non_power_of_2 && NumElts > 2)
        CandidateVFs.push_back(NumElts - 1);
    }

    if (Final && CandidateVFs.empty())
      return Results;

    unsigned BestVF = Final ? CandidateVFs.back() : 0;
    auto IsValidVF = [&](unsigned VF) { return !Final || VF <= BestVF; };
    for (unsigned NumElts : make_filter_range(CandidateVFs, IsValidVF)) {
      SmallVector<unsigned> MaskedGatherVectorized;
      for (unsigned Cnt = StartIdx, E = Loads.size(); Cnt < E;
           ++Cnt) {
        ArrayRef<LoadInst *> Slice =
            ArrayRef(Loads).slice(Cnt, std::min(NumElts, E - Cnt));
        if (VectorizedLoads.count(Slice.front()) ||
            VectorizedLoads.count(Slice.back()) ||
            areKnownNonVectorizableLoads(Slice))
          continue;
        // Check if it is profitable to try vectorizing gathered loads. It is
        // profitable if we have more than 3 consecutive loads or if we have
        // less but all users are vectorized or deleted.
        bool AllowToVectorize = false;
        // Check if it is profitable to vectorize 2-elements loads.
        if (NumElts == 2) {
          bool IsLegalBroadcastLoad = TTI->isLegalBroadcastLoad(
              Slice.front()->getType(), ElementCount::getFixed(NumElts));
          auto CheckIfAllowed = [=](ArrayRef<LoadInst *> Slice) {
            // If single use/user - allow to vectorize.
            auto IsNotSingleUse = [](LoadInst *LI) { return !LI->hasOneUse(); };
            for (LoadInst *LI : make_filter_range(Slice, IsNotSingleUse)) {
              // 1. Check if number of uses equals number of users.
              // 2. All users are deleted.
              // 3. The load broadcasts are not allowed or the load is not
              // broadcasted.
              if (static_cast<unsigned int>(std::distance(
                      LI->user_begin(), LI->user_end())) != LI->getNumUses())
                return false;
              if (!IsLegalBroadcastLoad)
                continue;
              if (LI->hasNUsesOrMore(UsesLimit))
                return false;
              for (User *U : LI->users()) {
                if (auto *UI = dyn_cast<Instruction>(U); UI && isDeleted(UI))
                  continue;
                for (const TreeEntry *UTE : getTreeEntries(U)) {
                  for (int I : seq<int>(UTE->getNumOperands())) {
                    if (all_of(UTE->getOperand(I), [LI](Value *V) {
                          return V == LI || isa<PoisonValue>(V);
                        }))
                      // Found legal broadcast - do not vectorize.
                      return false;
                  }
                }
              }
            }
            return true;
          };
          AllowToVectorize = CheckIfAllowed(Slice);
        } else {
          AllowToVectorize =
              NumElts >= 3 ||
              any_of(ValueToGatherNodes.at(Slice.front()),
                     [=](const TreeEntry *TE) {
                       return TE->Scalars.size() == 2 &&
                              ((TE->Scalars.front() == Slice.front() &&
                                TE->Scalars.back() == Slice.back()) ||
                               (TE->Scalars.front() == Slice.back() &&
                                TE->Scalars.back() == Slice.front()));
                     });
        }
        if (AllowToVectorize) {
          SmallVector<Value *> PointerOps;
          OrdersType CurrentOrder;
          // Try to build vector load.
          ArrayRef<Value *> Values(
              reinterpret_cast<Value *const *>(Slice.begin()), Slice.size());
          StridedPtrInfo SPtrInfo;
          LoadsState LS = canVectorizeLoads(Values, Slice.front(), CurrentOrder,
                                            PointerOps, SPtrInfo, &BestVF);
          if (LS != LoadsState::Gather ||
              (BestVF > 1 && static_cast<unsigned>(NumElts) == 2 * BestVF)) {
            if (LS == LoadsState::ScatterVectorize) {
              if (MaskedGatherVectorized.empty() ||
                  Cnt >= MaskedGatherVectorized.back() + NumElts)
                MaskedGatherVectorized.push_back(Cnt);
              continue;
            }
            if (LS != LoadsState::Gather) {
              Results.emplace_back(Values, LS);
              VectorizedLoads.insert_range(Slice);
              // If we vectorized initial block, no need to try to vectorize it
              // again.
              if (Cnt == StartIdx)
                StartIdx += NumElts;
            }
            // Check if the whole array was vectorized already - exit.
            if (StartIdx >= Loads.size())
              break;
            // Erase last masked gather candidate, if another candidate within
            // the range is found to be better.
            if (!MaskedGatherVectorized.empty() &&
                Cnt < MaskedGatherVectorized.back() + NumElts)
              MaskedGatherVectorized.pop_back();
            Cnt += NumElts - 1;
            continue;
          }
        }
        if (!AllowToVectorize || BestVF == 0)
          registerNonVectorizableLoads(Slice);
      }
      // Mark masked gathers candidates as vectorized, if any.
      for (unsigned Cnt : MaskedGatherVectorized) {
        ArrayRef<LoadInst *> Slice = ArrayRef(Loads).slice(
            Cnt, std::min<unsigned>(NumElts, Loads.size() - Cnt));
        ArrayRef<Value *> Values(
            reinterpret_cast<Value *const *>(Slice.begin()), Slice.size());
        Results.emplace_back(Values, LoadsState::ScatterVectorize);
        VectorizedLoads.insert_range(Slice);
        // If we vectorized initial block, no need to try to vectorize it again.
        if (Cnt == StartIdx)
          StartIdx += NumElts;
      }
    }
    for (LoadInst *LI : Loads) {
      if (!VectorizedLoads.contains(LI))
        NonVectorized.push_back(LI);
    }
    return Results;
  };
  auto ProcessGatheredLoads =
      [&, &TTI = *TTI](
          ArrayRef<SmallVector<std::pair<LoadInst *, int64_t>>> GatheredLoads,
          bool Final = false) {
        SmallVector<LoadInst *> NonVectorized;
        for (ArrayRef<std::pair<LoadInst *, int64_t>> LoadsDists :
             GatheredLoads) {
          if (LoadsDists.size() <= 1) {
            NonVectorized.push_back(LoadsDists.back().first);
            continue;
          }
          SmallVector<std::pair<LoadInst *, int64_t>> LocalLoadsDists(
              LoadsDists);
          SmallVector<LoadInst *> OriginalLoads(make_first_range(LoadsDists));
          stable_sort(LocalLoadsDists, LoadSorter);
          SmallVector<LoadInst *> Loads;
          unsigned MaxConsecutiveDistance = 0;
          unsigned CurrentConsecutiveDist = 1;
          int64_t LastDist = LocalLoadsDists.front().second;
          bool AllowMaskedGather = IsMaskedGatherSupported(OriginalLoads);
          auto IsNotVectorized = [&](const std::pair<LoadInst *, int64_t> &L) {
            return !isVectorized(L.first);
          };
          for (const std::pair<LoadInst *, int64_t> &L :
               make_filter_range(LocalLoadsDists, IsNotVectorized)) {
            assert(LastDist >= L.second &&
                   "Expected first distance always not less than second");
            if (static_cast<uint64_t>(LastDist - L.second) ==
                CurrentConsecutiveDist) {
              ++CurrentConsecutiveDist;
              MaxConsecutiveDistance =
                  std::max(MaxConsecutiveDistance, CurrentConsecutiveDist);
              Loads.push_back(L.first);
              continue;
            }
            if (!AllowMaskedGather && CurrentConsecutiveDist == 1 &&
                !Loads.empty())
              Loads.pop_back();
            CurrentConsecutiveDist = 1;
            LastDist = L.second;
            Loads.push_back(L.first);
          }
          if (Loads.size() <= 1)
            continue;
          if (AllowMaskedGather)
            MaxConsecutiveDistance = Loads.size();
          else if (MaxConsecutiveDistance < 2)
            continue;
          BoUpSLP::ValueSet VectorizedLoads;
          SmallVector<LoadInst *> SortedNonVectorized;
          SmallVector<std::pair<ArrayRef<Value *>, LoadsState>> Results =
              GetVectorizedRanges(Loads, VectorizedLoads, SortedNonVectorized,
                                  Final, MaxConsecutiveDistance);
          if (!Results.empty() && !SortedNonVectorized.empty() &&
              OriginalLoads.size() == Loads.size() &&
              MaxConsecutiveDistance == Loads.size() &&
              all_of(Results,
                     [](const std::pair<ArrayRef<Value *>, LoadsState> &P) {
                       return P.second == LoadsState::ScatterVectorize;
                     })) {
            VectorizedLoads.clear();
            SmallVector<LoadInst *> UnsortedNonVectorized;
            SmallVector<std::pair<ArrayRef<Value *>, LoadsState>>
                UnsortedResults =
                    GetVectorizedRanges(OriginalLoads, VectorizedLoads,
                                        UnsortedNonVectorized, Final,
                                        OriginalLoads.size());
            if (SortedNonVectorized.size() >= UnsortedNonVectorized.size()) {
              SortedNonVectorized.swap(UnsortedNonVectorized);
              Results.swap(UnsortedResults);
            }
          }
          for (ArrayRef<Value *> Slice : make_first_range(Results)) {
            LLVM_DEBUG(dbgs() << "SLP: Trying to vectorize gathered loads ("
                              << Slice.size() << ")\n");
            if (any_of(Slice, [&](Value *V) { return isVectorized(V); })) {
              for (Value *L : Slice)
                if (!isVectorized(L))
                  SortedNonVectorized.push_back(cast<LoadInst>(L));
              continue;
            }

            // Select maximum VF as a maximum of user gathered nodes and
            // distance between scalar loads in these nodes.
            unsigned MaxVF = Slice.size();
            unsigned UserMaxVF = 0;
            unsigned InterleaveFactor = 0;
            if (MaxVF == 2) {
              UserMaxVF = MaxVF;
            } else {
              // Found distance between segments of the interleaved loads.
              std::optional<unsigned> InterleavedLoadsDistance = 0;
              unsigned Order = 0;
              std::optional<unsigned> CommonVF = 0;
              DenseMap<const TreeEntry *, unsigned> EntryToPosition;
              SmallPtrSet<const TreeEntry *, 8> DeinterleavedNodes;
              for (auto [Idx, V] : enumerate(Slice)) {
                for (const TreeEntry *E : ValueToGatherNodes.at(V)) {
                  UserMaxVF = std::max<unsigned>(UserMaxVF, E->Scalars.size());
                  unsigned Pos =
                      EntryToPosition.try_emplace(E, Idx).first->second;
                  UserMaxVF = std::max<unsigned>(UserMaxVF, Idx - Pos + 1);
                  if (CommonVF) {
                    if (*CommonVF == 0) {
                      CommonVF = E->Scalars.size();
                      continue;
                    }
                    if (*CommonVF != E->Scalars.size())
                      CommonVF.reset();
                  }
                  // Check if the load is the part of the interleaved load.
                  if (Pos != Idx && InterleavedLoadsDistance) {
                    if (!DeinterleavedNodes.contains(E) &&
                        any_of(E->Scalars, [&, Slice = Slice](Value *V) {
                          if (isa<Constant>(V))
                            return false;
                          if (isVectorized(V))
                            return true;
                          const auto &Nodes = ValueToGatherNodes.at(V);
                          return (Nodes.size() != 1 || !Nodes.contains(E)) &&
                                 !is_contained(Slice, V);
                        })) {
                      InterleavedLoadsDistance.reset();
                      continue;
                    }
                    DeinterleavedNodes.insert(E);
                    if (*InterleavedLoadsDistance == 0) {
                      InterleavedLoadsDistance = Idx - Pos;
                      continue;
                    }
                    if ((Idx - Pos) % *InterleavedLoadsDistance != 0 ||
                        (Idx - Pos) / *InterleavedLoadsDistance < Order)
                      InterleavedLoadsDistance.reset();
                    Order = (Idx - Pos) / InterleavedLoadsDistance.value_or(1);
                  }
                }
              }
              DeinterleavedNodes.clear();
              // Check if the large load represents interleaved load operation.
              if (InterleavedLoadsDistance.value_or(0) > 1 &&
                  CommonVF.value_or(0) != 0) {
                InterleaveFactor = bit_ceil(*InterleavedLoadsDistance);
                unsigned VF = *CommonVF;
                OrdersType Order;
                SmallVector<Value *> PointerOps;
                StridedPtrInfo SPtrInfo;
                // Segmented load detected - vectorize at maximum vector factor.
                if (InterleaveFactor <= Slice.size() &&
                    TTI.isLegalInterleavedAccessType(
                        cast<VectorType>(
                            getWidenedType(Slice.front()->getType(), VF)),
                        InterleaveFactor,
                        cast<LoadInst>(Slice.front())->getAlign(),
                        cast<LoadInst>(Slice.front())
                            ->getPointerAddressSpace()) &&
                    canVectorizeLoads(Slice, Slice.front(), Order, PointerOps,
                                      SPtrInfo) == LoadsState::Vectorize) {
                  UserMaxVF = InterleaveFactor * VF;
                } else {
                  InterleaveFactor = 0;
                }
              }
              // Cannot represent the loads as consecutive vectorizable nodes -
              // just exit.
              unsigned ConsecutiveNodesSize = 0;
              if (!LoadEntriesToVectorize.empty() && InterleaveFactor == 0 &&
                  any_of(zip(LoadEntriesToVectorize, LoadSetsToVectorize),
                         [&, Slice = Slice](const auto &P) {
                           const auto *It = find_if(Slice, [&](Value *V) {
                             return std::get<1>(P).contains(V);
                           });
                           if (It == Slice.end())
                             return false;
                           const TreeEntry &TE =
                               *VectorizableTree[std::get<0>(P)];
                           ArrayRef<Value *> VL = TE.Scalars;
                           OrdersType Order;
                           SmallVector<Value *> PointerOps;
                           StridedPtrInfo SPtrInfo;
                           LoadsState State = canVectorizeLoads(
                               VL, VL.front(), Order, PointerOps, SPtrInfo);
                           if (State == LoadsState::ScatterVectorize ||
                               State == LoadsState::CompressVectorize ||
                               State == LoadsState::BlendedLoadVectorize)
                             return false;
                           ConsecutiveNodesSize += VL.size();
                           size_t Start = std::distance(Slice.begin(), It);
                           size_t Sz = Slice.size() - Start;
                           return Sz < VL.size() ||
                                  Slice.slice(Start, VL.size()) != VL;
                         }))
                continue;
              // Try to build long masked gather loads.
              UserMaxVF = bit_ceil(UserMaxVF);
              if (InterleaveFactor == 0 &&
                  any_of(seq<unsigned>(Slice.size() / UserMaxVF),
                         [&, Slice = Slice](unsigned Idx) {
                           OrdersType Order;
                           SmallVector<Value *> PointerOps;
                           StridedPtrInfo SPtrInfo;
                           return canVectorizeLoads(
                                      Slice.slice(Idx * UserMaxVF, UserMaxVF),
                                      Slice[Idx * UserMaxVF], Order, PointerOps,
                                      SPtrInfo) == LoadsState::ScatterVectorize;
                         }))
                UserMaxVF = MaxVF;
              if (Slice.size() != ConsecutiveNodesSize)
                MaxVF = std::min<unsigned>(MaxVF, UserMaxVF);
            }
            for (unsigned VF = MaxVF; VF >= 2; VF /= 2) {
              bool IsVectorized = true;
              for (unsigned I = 0, E = Slice.size(); I < E; I += VF) {
                ArrayRef<Value *> SubSlice =
                    Slice.slice(I, std::min(VF, E - I));
                if (isVectorized(SubSlice.front()))
                  continue;
                // Check if the subslice is to be-vectorized entry, which is not
                // equal to entry.
                if (any_of(zip(LoadEntriesToVectorize, LoadSetsToVectorize),
                           [&](const auto &P) {
                             return !SubSlice.equals(
                                        VectorizableTree[std::get<0>(P)]
                                            ->Scalars) &&
                                    set_is_subset(SubSlice, std::get<1>(P));
                           }))
                  continue;
                unsigned Sz = VectorizableTree.size();
                // A chunk smaller than InterleaveFactor cannot form an
                // interleave group; keep it non-interleaved instead.
                buildTreeRec(
                    SubSlice, 0, EdgeInfo(),
                    SubSlice.size() >= InterleaveFactor ? InterleaveFactor : 0);
                if (Sz == VectorizableTree.size()) {
                  IsVectorized = false;
                  // Try non-interleaved vectorization with smaller vector
                  // factor.
                  if (InterleaveFactor > 0) {
                    VF = 2 * (MaxVF / InterleaveFactor);
                    InterleaveFactor = 0;
                  }
                  continue;
                }
              }
              if (IsVectorized)
                break;
            }
          }
          NonVectorized.append(SortedNonVectorized);
        }
        return NonVectorized;
      };
  for (const auto &GLs : GatheredLoads) {
    const auto &Ref = GLs.second;
    SmallVector<LoadInst *> NonVectorized = ProcessGatheredLoads(Ref);
    if (!Ref.empty() && !NonVectorized.empty() &&
        accumulate(
            Ref, 0u,
            [](unsigned S, ArrayRef<std::pair<LoadInst *, int64_t>> LoadsDists)
                -> unsigned { return S + LoadsDists.size(); }) !=
            NonVectorized.size() &&
        IsMaskedGatherSupported(NonVectorized)) {
      SmallVector<SmallVector<std::pair<LoadInst *, int64_t>>>
          FinalGatheredLoads;
      for (LoadInst *LI : NonVectorized) {
        // Reinsert non-vectorized loads to other list of loads with the same
        // base pointers.
        gatherPossiblyVectorizableLoads(*this, LI, *DL, *SE, *TTI,
                                        FinalGatheredLoads,
                                        /*AddNew=*/false);
      }
      // Final attempt to vectorize non-vectorized loads.
      (void)ProcessGatheredLoads(FinalGatheredLoads, /*Final=*/true);
    }
  }
  // Try to vectorize postponed load entries, previously marked as gathered.
  for (unsigned Idx : LoadEntriesToVectorize) {
    const TreeEntry &E = *VectorizableTree[Idx];
    SmallVector<Value *> GatheredScalars(E.Scalars.begin(), E.Scalars.end());
    // Avoid reordering, if possible.
    if (!E.ReorderIndices.empty()) {
      // Build a mask out of the reorder indices and reorder scalars per this
      // mask.
      SmallVector<int> ReorderMask;
      inversePermutation(E.ReorderIndices, ReorderMask);
      reorderScalars(GatheredScalars, ReorderMask);
    }
    buildTreeRec(GatheredScalars, 0, EdgeInfo());
  }
  // If no new entries created, consider it as no gathered loads entries must be
  // handled.
  if (static_cast<unsigned>(*GatheredLoadsEntriesFirst) ==
      VectorizableTree.size())
    GatheredLoadsEntriesFirst.reset();
}

/// Generates key/subkey pair for the given value to provide effective sorting
/// of the values and better detection of the vectorizable values sequences. The
/// keys/subkeys can be used for better sorting of the values themselves (keys)
/// and in values subgroups (subkeys).
static std::pair<size_t, size_t> generateKeySubkey(
    Value *V, const TargetLibraryInfo *TLI,
    function_ref<hash_code(size_t, LoadInst *)> LoadsSubkeyGenerator,
    bool AllowAlternate) {
  hash_code Key = hash_value(V->getValueID() + 2);
  hash_code SubKey = hash_value(0);
  // Sort the loads by the distance between the pointers.
  if (auto *LI = dyn_cast<LoadInst>(V)) {
    Key = hash_combine(LI->getType(), hash_value(Instruction::Load), Key);
    if (LI->isSimple())
      SubKey = hash_value(LoadsSubkeyGenerator(Key, LI));
    else
      Key = SubKey = hash_value(LI);
  } else if (isVectorLikeInstWithConstOps(V)) {
    // Sort extracts by the vector operands.
    if (isa<ExtractElementInst, UndefValue>(V))
      Key = hash_value(Value::UndefValueVal + 1);
    if (auto *EI = dyn_cast<ExtractElementInst>(V)) {
      if (!isUndefVector(EI->getVectorOperand()).all() &&
          !isa<UndefValue>(EI->getIndexOperand()))
        SubKey = hash_value(EI->getVectorOperand());
    }
  } else if (auto *I = dyn_cast<Instruction>(V)) {
    // Sort other instructions just by the opcodes except for CMPInst.
    // For CMP also sort by the predicate kind.
    if ((isa<BinaryOperator, CastInst>(I)) &&
        isValidForAlternation(I->getOpcode())) {
      if (AllowAlternate)
        Key = hash_value(isa<BinaryOperator>(I) ? 1 : 0);
      else
        Key = hash_combine(hash_value(I->getOpcode()), Key);
      SubKey = hash_combine(
          hash_value(I->getOpcode()), hash_value(I->getType()),
          hash_value(isa<BinaryOperator>(I)
                         ? I->getType()
                         : cast<CastInst>(I)->getOperand(0)->getType()));
      // For casts, look through the only operand to improve compile time.
      if (isa<CastInst>(I)) {
        std::pair<size_t, size_t> OpVals =
            generateKeySubkey(I->getOperand(0), TLI, LoadsSubkeyGenerator,
                              /*AllowAlternate=*/true);
        Key = hash_combine(OpVals.first, Key);
        SubKey = hash_combine(OpVals.first, SubKey);
      }
    } else if (auto *CI = dyn_cast<CmpInst>(I)) {
      CmpInst::Predicate Pred = CI->getPredicate();
      if (CI->isCommutative())
        Pred = std::min(Pred, CmpInst::getInversePredicate(Pred));
      CmpInst::Predicate SwapPred = CmpInst::getSwappedPredicate(Pred);
      SubKey = hash_combine(hash_value(I->getOpcode()), hash_value(Pred),
                            hash_value(SwapPred),
                            hash_value(CI->getOperand(0)->getType()));
    } else if (auto *Call = dyn_cast<CallInst>(I)) {
      Intrinsic::ID ID = getVectorIntrinsicIDForCall(Call, TLI);
      if (isTriviallyVectorizable(ID)) {
        if (ID == Intrinsic::fmuladd)
          ID = Intrinsic::fma;
        SubKey = hash_combine(hash_value(I->getOpcode()), hash_value(ID),
                              hash_value(I->getType()));
      } else if (!VFDatabase(*Call).getMappings(*Call).empty()) {
        SubKey = hash_combine(hash_value(I->getOpcode()),
                              hash_value(Call->getCalledFunction()),
                              hash_value(I->getType()));
      } else {
        Key = hash_combine(hash_value(Call), Key);
        SubKey = hash_combine(hash_value(I->getOpcode()), hash_value(Call));
      }
      for (const CallBase::BundleOpInfo &Op : Call->bundle_op_infos())
        SubKey = hash_combine(hash_value(Op.Begin), hash_value(Op.End),
                              hash_value(Op.Tag), SubKey);
    } else if (auto *Gep = dyn_cast<GetElementPtrInst>(I)) {
      if (Gep->getNumOperands() == 2 && isa<ConstantInt>(Gep->getOperand(1)))
        SubKey = hash_value(Gep->getPointerOperand());
      else
        SubKey = hash_value(Gep);
    } else if (BinaryOperator::isIntDivRem(I->getOpcode()) &&
               !isa<ConstantInt>(I->getOperand(1))) {
      // Do not try to vectorize instructions with potentially high cost.
      SubKey = hash_value(I);
    } else {
      SubKey =
          hash_combine(hash_value(I->getOpcode()), hash_value(I->getType()));
    }
    Key = hash_combine(hash_value(I->getParent()->getNumber()), Key);
  }
  return std::make_pair(Key, SubKey);
}

/// Checks if the specified instruction \p I is an main operation for the given
/// \p MainOp and \p AltOp instructions.
static bool isMainInstruction(Instruction *I, Instruction *MainOp,
                              Instruction *AltOp, const TargetLibraryInfo &TLI);

/// Builds the arguments types vector for the given call instruction with the
/// given \p ID for the specified vector factor.
static SmallVector<Type *>
buildIntrinsicArgTypes(const CallInst *CI, const Intrinsic::ID ID,
                       const unsigned VF, unsigned MinBW,
                       const TargetTransformInfo *TTI) {
  SmallVector<Type *> ArgTys;
  for (auto [Idx, Arg] : enumerate(CI->args())) {
    if (ID != Intrinsic::not_intrinsic) {
      if (isVectorIntrinsicWithScalarOpAtArg(ID, Idx, TTI)) {
        ArgTys.push_back(Arg->getType());
        continue;
      }
      if (MinBW > 0) {
        ArgTys.push_back(
            getWidenedType(IntegerType::get(CI->getContext(), MinBW), VF));
        continue;
      }
    }
    ArgTys.push_back(getWidenedType(Arg->getType(), VF));
  }
  return ArgTys;
}

/// Calculates the costs of vectorized intrinsic (if possible) and vectorized
/// function (if possible) calls. Returns invalid cost for the corresponding
/// calls, if they cannot be vectorized/will be scalarized.
static std::pair<InstructionCost, InstructionCost>
getVectorCallCosts(CallInst *CI, Type *VecTy, const TargetTransformInfo *TTI,
                   const TargetLibraryInfo *TLI, ArrayRef<Type *> ArgTys,
                   const TTI::TargetCostKind CostKind) {
  auto Shape = VFShape::get(CI->getFunctionType(),
                            ElementCount::getFixed(getNumElements(VecTy)),
                            false /*HasGlobalPred*/);
  Function *VecFunc = VFDatabase(*CI).getVectorizedFunction(Shape);
  auto LibCost = InstructionCost::getInvalid();
  if (!CI->isNoBuiltin() && VecFunc) {
    // Calculate the cost of the vector library call.
    // If the corresponding vector call is cheaper, return its cost.
    LibCost = TTI->getCallInstrCost(nullptr, VecTy, ArgTys, CostKind);
  }
  Intrinsic::ID ID = getVectorIntrinsicIDForCall(CI, TLI);

  // Calculate the cost of the vector intrinsic call.
  FastMathFlags FMF;
  if (auto *FPCI = dyn_cast<FPMathOperator>(CI))
    FMF = FPCI->getFastMathFlags();
  const InstructionCost ScalarLimit = 10000;
  IntrinsicCostAttributes CostAttrs(ID, VecTy, ArgTys, FMF,
                                    dyn_cast<IntrinsicInst>(CI),
                                    LibCost.isValid() ? LibCost : ScalarLimit);
  auto IntrinsicCost = TTI->getIntrinsicInstrCost(CostAttrs, CostKind);
  if (LibCost.isValid()) {
    if (IntrinsicCost > LibCost)
      IntrinsicCost = InstructionCost::getInvalid();
  } else if (IntrinsicCost > ScalarLimit) {
    // A type-based query always scalarizes struct-returning intrinsics (e.g.
    // llvm.sincos), which do not have a VFDatabase name mapping. Retry with an
    // argument-aware query (as the loop vectorizer does) so such lowerings are
    // taken into account.
    SmallVector<const Value *> Args(CI->args());
    IntrinsicCostAttributes ArgAwareAttrs(
        ID, VecTy, Args, ArgTys, FMF, dyn_cast<IntrinsicInst>(CI), ScalarLimit);
    IntrinsicCost = TTI->getIntrinsicInstrCost(ArgAwareAttrs, CostKind);
    if (IntrinsicCost > ScalarLimit)
      IntrinsicCost = InstructionCost::getInvalid();
  }

  return {IntrinsicCost, LibCost};
}

/// \returns the reciprocal-throughput cost of \p I widened to \p VF lanes (an
/// arithmetic op or a vectorizable call).
static InstructionCost getVectorOpCost(Instruction *I, unsigned VF,
                                       const TargetTransformInfo &TTI,
                                       const TargetLibraryInfo &TLI,
                                       const TTI::TargetCostKind CostKind) {
  assert((isa<BinaryOperator, CallInst>(I)) &&
         "getVectorOpCost expects an arithmetic op or a vectorizable call.");
  Type *VecTy = getWidenedType(I->getType(), VF);
  if (auto *CI = dyn_cast<CallInst>(I)) {
    Intrinsic::ID ID = getVectorIntrinsicIDForCall(CI, &TLI);
    SmallVector<Type *> ArgTys = buildIntrinsicArgTypes(CI, ID, VF, 0, &TTI);
    auto [IntrCost, LibCost] =
        getVectorCallCosts(CI, VecTy, &TTI, &TLI, ArgTys, CostKind);
    return std::min(IntrCost, LibCost);
  }
  SmallVector<const Value *, 2> Args{I->getOperand(0), I->getOperand(1)};
  return TTI.getArithmeticInstrCost(
      I->getOpcode(), VecTy, CostKind, TTI::getOperandInfo(I->getOperand(0)),
      TTI::getOperandInfo(I->getOperand(1)), Args, I);
}

/// Packs a type's kind and scalar width into one key, so an opcode/intrinsic
/// id reused across scalar widths (e.g. fdiv float vs. fdiv double) is cached
/// per width instead of sharing one verdict.
static unsigned getPoorThroughputTypeKey(Type *Ty) {
  return (static_cast<unsigned>(Ty->getTypeID()) << 16) |
         Ty->getScalarSizeInBits();
}

namespace {
/// Memoizes opcode / intrinsic / callee kinds already ruled out as seeds.
struct PoorThroughputOpCache {
  SmallDenseSet<std::pair<unsigned, unsigned>> CheapOpcodes;
  SmallDenseSet<std::pair<Intrinsic::ID, unsigned>> CheapIntrinsics;
  // Keyed on the callee alone: a Function's signature is fixed, so its type
  // never varies between calls.
  SmallDenseSet<const Function *> CheapCallees;
};

/// Groups poor-throughput seeds for tryToVectorizeSequence.
struct SeedGroupKey {
  unsigned Opcode = 0;
  Intrinsic::ID IntrID = Intrinsic::not_intrinsic;
  StringRef CalleeName;

  bool less(const SeedGroupKey &O) const {
    if (Opcode != O.Opcode)
      return Opcode < O.Opcode;
    if (IntrID != O.IntrID)
      return IntrID < O.IntrID;
    return CalleeName < O.CalleeName;
  }
};

static SeedGroupKey getSeedGroupKey(const Instruction *I,
                                    const TargetLibraryInfo &TLI) {
  SeedGroupKey K;
  K.Opcode = I->getOpcode();
  if (auto *CI = dyn_cast<CallInst>(I)) {
    K.IntrID = getVectorIntrinsicIDForCall(CI, &TLI);
    if (const Function *F = CI->getCalledFunction())
      K.CalleeName = F->getName();
  }
  return K;
}
} // namespace

/// Returns true if \p I is an expensive scalar op whose vector form is cheaper
/// per lane (e.g. fdiv, frem, fsqrt). If \p MaxVecRegSize is non-zero, the
/// widest vector fitting into it is checked too.
static bool isPoorThroughputOp(const VectorizeOptions &Opts, Instruction *I,
                               const TargetTransformInfo &TTI,
                               const TargetLibraryInfo &TLI,
                               PoorThroughputOpCache &Cache,
                               const TTI::TargetCostKind CostKind,
                               unsigned MaxVecRegSize = 0) {
  if (!isa<BinaryOperator, CallInst>(I))
    return false;
  Type *Ty = I->getType();
  if ((Ty->isVectorTy() && !Opts.slp_revec) || Ty->isAggregateType() ||
      !isValidElementType(Ty, Opts.slp_revec))
    return false;
  auto Analyze = [&]() {
    InstructionCost ScalarCost = TTI.getInstructionCost(I, CostKind);
    if (ScalarCost < TTI::TCC_Expensive)
      return false;
    constexpr unsigned MinVF = 2;
    if (getVectorOpCost(I, MinVF, TTI, TLI, CostKind) < ScalarCost * MinVF)
      return true;
    // Some ops (e.g. div by constant) scalarize at VF=2 but have a cheap
    // vector form at the full register width.
    unsigned TyBits = Ty->getPrimitiveSizeInBits().getFixedValue();
    unsigned MaxVF = TyBits ? llvm::bit_floor(MaxVecRegSize / TyBits) : 0;
    return MaxVF > MinVF &&
           getVectorOpCost(I, MaxVF, TTI, TLI, CostKind) < ScalarCost * MaxVF;
  };
  auto CheckCached = [&](bool IsCheap, llvm::function_ref<void()> MarkCheap) {
    if (IsCheap)
      return false;
    if (Analyze())
      return true;
    MarkCheap();
    return false;
  };
  if (auto *CI = dyn_cast<CallInst>(I)) {
    if (any_of(CI->args(), [&](const Value *Arg) {
          return !isValidElementType(Arg->getType(), Opts.slp_revec);
        }))
      return false;
    // A call, used only as a select operand, may get the values rejected by the
    // select condition, which the vector library call handles on its slow path.
    if (!CI->use_empty() && !CI->hasNUsesOrMore(UsesLimit) &&
        all_of(CI->users(), [&](User *U) {
          return match(
              U, m_Select(m_Unless(m_Specific(CI)), m_Value(), m_Value()));
        }))
      return false;
    if (Intrinsic::ID ID = getVectorIntrinsicIDForCall(CI, &TLI)) {
      auto Key = std::make_pair(ID, getPoorThroughputTypeKey(Ty));
      return CheckCached(Cache.CheapIntrinsics.contains(Key),
                         [&] { Cache.CheapIntrinsics.insert(Key); });
    }
    // A call without the vector variants is never vectorized.
    if (VFDatabase::getMappings(*CI).empty())
      return false;
    const Function *Callee = CI->getCalledFunction();
    if (!Callee)
      return Analyze();
    return CheckCached(Cache.CheapCallees.contains(Callee),
                       [&] { Cache.CheapCallees.insert(Callee); });
  }
  auto Key = std::make_pair(I->getOpcode(), getPoorThroughputTypeKey(Ty));
  return CheckCached(Cache.CheapOpcodes.contains(Key),
                     [&] { Cache.CheapOpcodes.insert(Key); });
}

/// Get the loop nest for the given loop.
ArrayRef<const Loop *> BoUpSLP::getLoopNest(const Loop *L) {
  assert(L && "Expected valid loop");
  if (Opts.slp_cost_loop_trip_count == 0)
    return {};
  SmallVector<const Loop *> &Res =
      LoopToLoopNest.try_emplace(L).first->getSecond();
  if (!Res.empty())
    return Res;
  SmallVector<const Loop *> LoopNest;
  while (L) {
    LoopNest.push_back(L);
    L = L->getParentLoop();
  }
  Res.assign(LoopNest.rbegin(), LoopNest.rend());
  return Res;
}

/// Detects an extractvalue bundle that can be widened by vectorizing the
/// underlying struct-returning calls.
///
/// \p VL is a bundle whose state \p S is Instruction::ExtractValue. The
/// bundle is acceptable for widening into one struct-of-vectors call only
/// when:
///   - every element of \p VL is an ExtractValueInst,
///   - every ExtractValueInst extracts the same struct field (its
///     getIndices() matches the main op's indices),
///   - the aggregate operands form a uniform set of CallInsts (per
///     getSameOpcode) that is not an alt-shuffle and whose return type is
///     a literal struct, and
///   - every user of every such call is itself an ExtractValueInst, so the
///     external-use extraction code can rebuild scalars via extractvalue +
///     extractelement without needing an insertvalue chain.
///
/// On success returns true and fills \p Indices with the common field
/// index path and \p Calls with the per-lane aggregate calls (in VL order),
/// for the caller to feed as the operand of the new tree entry. Otherwise
/// returns false and leaves the output parameters untouched.
static bool checkEVsForVecCalls(ArrayRef<Value *> VL,
                                const InstructionsState &S,
                                const TargetLibraryInfo &TLI,
                                SmallVectorImpl<unsigned> &Indices,
                                SmallVectorImpl<Value *> &Calls) {
  assert(S && S.getOpcode() == Instruction::ExtractValue &&
         "Expected extractvalue instruction state.");
  if (!all_of(VL, IsaPred<ExtractValueInst>))
    return false;
  auto *VL0 = cast<ExtractValueInst>(S.getMainOp());
  ArrayRef<unsigned> VL0Indices = VL0->getIndices();
  SmallVector<Value *> Aggregates;
  for (Value *V : VL) {
    if (V == VL0) {
      Aggregates.push_back(VL0->getAggregateOperand());
      continue;
    }
    auto *IV = cast<ExtractValueInst>(V);
    if (IV->getIndices() != VL0Indices ||
        isa<ScalableVectorType>(IV->getType()))
      return false;
    Value *Agg = IV->getAggregateOperand();
    Aggregates.push_back(Agg);
  }
  const InstructionsState AggState = getSameOpcode(Aggregates, TLI);
  if (AggState && AggState.getOpcode() == Instruction::Call &&
      !AggState.isAltShuffle() &&
      isa<StructType>(AggState.getMainOp()->getType()) &&
      allSameBlock(Aggregates)) {
    // The struct-returning call may have non-bundle users too. The external
    // extraction code rebuilds scalars by extractvalue + extractelement,
    // which only works when every user of the call is an ExtractValueInst.
    // Bail out if any aggregate has a different kind of user.
    for (Value *Agg : Aggregates) {
      if (!all_of(Agg->users(), IsaPred<ExtractValueInst>))
        return false;
    }
    Indices.assign(VL0Indices.begin(), VL0Indices.end());
    Calls.swap(Aggregates);
    return true;
  }
  return false;
}

static bool allStructUsersAreExtractValueInsts(ArrayRef<Value *> VL) {
  return all_of(VL, [](Value *V) {
    return !isa<StructType>(V->getType()) ||
           all_of(V->users(), IsaPred<ExtractValueInst>);
  });
}

BoUpSLP::TreeEntry::EntryState BoUpSLP::getScalarsVectorizationState(
    const InstructionsState &S, ArrayRef<Value *> VL,
    bool IsScatterVectorizeUserTE, OrdersType &CurrentOrder,
    SmallVectorImpl<Value *> &PointerOps, StridedPtrInfo &SPtrInfo,
    SmallVectorImpl<int> &ReuseShuffleIndices) {
  assert(S.getMainOp() &&
         "Expected instructions with same/alternate opcodes only.");

  unsigned ShuffleOrOp =
      S.isAltShuffle() ? (unsigned)Instruction::ShuffleVector : S.getOpcode();
  Instruction *VL0 = S.getMainOp();
  switch (ShuffleOrOp) {
  case Instruction::PHI: {
    // Too many operands - gather, most probably won't be vectorized.
    if (VL0->getNumOperands() > MaxPHINumOperands)
      return TreeEntry::NeedToGather;
    // Check for terminator values (e.g. invoke).
    for (PHINode *PHI : make_isa_range<PHINode>(VL)) {
      for (Instruction *Term :
           make_isa_range<Instruction>(PHI->incoming_values())) {
        if (Term->isTerminator()) {
          LLVM_DEBUG(dbgs()
                     << "SLP: Need to swizzle PHINodes (terminator use).\n");
          return TreeEntry::NeedToGather;
        }
      }
    }

    return TreeEntry::Vectorize;
  }
  case Instruction::ExtractElement:
    if (any_of(VL, [&](Value *V) {
          if (S.isCopyableElement(V) || isa<PoisonValue>(V))
            return false;
          auto *EI = dyn_cast<ExtractElementInst>(V);
          if (!EI)
            return true;
          Value *Op = EI->getOperand(0);
          if (isVectorized(Op))
            return true;
          auto *OpI = dyn_cast<Instruction>(Op);
          return OpI && OpI->isTerminator();
        }))
      return TreeEntry::NeedToGather;
    [[fallthrough]];
  case Instruction::ExtractValue: {
    bool Reuse = canReuseExtract(VL, CurrentOrder);
    // Copyable lanes are inserted into the reused source vector at their own
    // index, which is correct only for the identity extract order (empty
    // CurrentOrder) and without a reuse shuffle; other cases fall back to
    // gather.
    if (S.areInstructionsWithCopyableElements() &&
        (!Reuse || !ReuseShuffleIndices.empty()))
      return TreeEntry::NeedToGather;
    if (Reuse || !CurrentOrder.empty())
      return TreeEntry::Vectorize;
    SmallVector<unsigned> Indices;
    SmallVector<Value *> Calls;
    if (ShuffleOrOp == Instruction::ExtractValue &&
        checkEVsForVecCalls(VL, S, *TLI, Indices, Calls))
      return TreeEntry::Vectorize;
    LLVM_DEBUG(dbgs() << "SLP: Gather extract sequence.\n");
    return TreeEntry::NeedToGather;
  }
  case Instruction::InsertValue:
    // Handle only simple insertvalue building a homogeneous aggregate from
    // scalars: exactly one index and an inserted value whose type is a valid
    // vector element type. Vectors and aggregates (structs/arrays) are
    // rejected, since the inserted operand type is later widened into the
    // result FixedVectorType.
    // TODO: Support more complex insertvalues.
    if (any_of(make_isa_range<InsertValueInst>(VL),
               [&](InsertValueInst *IV) {
                 return IV->getNumIndices() != 1 ||
                        !::isValidElementType(IV->getOperand(1)->getType(),
                                              Opts.slp_revec) ||
                        IV->getOperand(1)->getType()->isVectorTy();
               }) ||
        none_of(make_isa_range<InsertValueInst>(VL), [](InsertValueInst *IV) {
          return isa<UndefValue>(IV->getAggregateOperand());
        }))
      return TreeEntry::NeedToGather;
    [[fallthrough]];
  case Instruction::InsertElement: {
    // Check that we have a buildvector and not a shuffle of 2 or more
    // different vectors.
    ValueSet SourceVectors;
    for (Value *V : VL) {
      if (isa<PoisonValue>(V)) {
        LLVM_DEBUG(
            dbgs()
            << "SLP: Gather of insertelement/insertvalue/poison vector.\n");
        return TreeEntry::NeedToGather;
      }
      SourceVectors.insert(cast<Instruction>(V)->getOperand(0));
      assert(getElementIndex(V) != std::nullopt &&
             "Non-constant or undef index?");
    }

    if (count_if(VL, [&SourceVectors](Value *V) {
          return !SourceVectors.contains(V);
        }) >= 2) {
      // Found 2nd source vector - cancel.
      LLVM_DEBUG(
          dbgs() << "SLP: Gather of insertelement/insertvalue vectors with "
                    "different source vectors.\n");
      return TreeEntry::NeedToGather;
    }

    if (any_of(VL, [&SourceVectors](Value *V) {
          // The last InsertElement/InsertValue can have multiple uses.
          return SourceVectors.contains(V) && !V->hasOneUse();
        })) {
      assert((Opts.slp_revec || ShuffleOrOp == Instruction::InsertValue) &&
             "Only supported by REVEC or InsertValue.");
      LLVM_DEBUG(
          dbgs() << "SLP: Gather of insertelement/insertvalue vectors with "
                    "multiple uses.\n");
      return TreeEntry::NeedToGather;
    }

    return TreeEntry::Vectorize;
  }
  case Instruction::Load: {
    // Check that a vectorized load would load the same memory as a scalar
    // load. For example, we don't want to vectorize loads that are smaller
    // than 8-bit. Even though we have a packed struct {<i2, i2, i2, i2>} LLVM
    // treats loading/storing it as an i8 struct. If we vectorize loads/stores
    // from such a struct, we read/write packed bits disagreeing with the
    // unvectorized version.
    auto IsGatheredNode = [&]() {
      if (!GatheredLoadsEntriesFirst)
        return false;
      return all_of(VL, [&](Value *V) {
        if (isa<PoisonValue>(V))
          return true;
        return any_of(getTreeEntries(V), [&](const TreeEntry *TE) {
          return TE->Idx >= *GatheredLoadsEntriesFirst;
        });
      });
    };
    switch (canVectorizeLoads(VL, VL0, CurrentOrder, PointerOps, SPtrInfo)) {
    case LoadsState::Vectorize:
      return TreeEntry::Vectorize;
    case LoadsState::CompressVectorize:
      if (!IsGraphTransformMode && VectorizableTree.size() > 1) {
        // Delay slow vectorized nodes for better vectorization attempts.
        LoadEntriesToVectorize.insert(VectorizableTree.size());
        return TreeEntry::NeedToGather;
      }
      return IsGatheredNode() ? TreeEntry::NeedToGather
                              : TreeEntry::CompressVectorize;
    case LoadsState::ScatterVectorize:
      if (!IsGraphTransformMode && VectorizableTree.size() > 1) {
        // Delay slow vectorized nodes for better vectorization attempts.
        LoadEntriesToVectorize.insert(VectorizableTree.size());
        return TreeEntry::NeedToGather;
      }
      return IsGatheredNode() ? TreeEntry::NeedToGather
                              : TreeEntry::ScatterVectorize;
    case LoadsState::StridedVectorize:
      if (!IsGraphTransformMode && VectorizableTree.size() > 1) {
        // Delay slow vectorized nodes for better vectorization attempts.
        LoadEntriesToVectorize.insert(VectorizableTree.size());
        return TreeEntry::NeedToGather;
      }
      return IsGatheredNode() ? TreeEntry::NeedToGather
                              : TreeEntry::StridedVectorize;
    case LoadsState::BlendedLoadVectorize:
      if (!IsGraphTransformMode && VectorizableTree.size() > 1) {
        // Delay slow vectorized nodes for better vectorization attempts.
        LoadEntriesToVectorize.insert(VectorizableTree.size());
        return TreeEntry::NeedToGather;
      }
      return IsGatheredNode() ? TreeEntry::NeedToGather
                              : TreeEntry::BlendedLoadVectorize;
    case LoadsState::Gather:
#ifndef NDEBUG
      Type *ScalarTy = VL0->getType();
      if (DL->getTypeSizeInBits(ScalarTy) !=
          DL->getTypeAllocSizeInBits(ScalarTy))
        LLVM_DEBUG(dbgs() << "SLP: Gathering loads of non-packed type.\n");
      else if (any_of(VL, [](Value *V) {
                 auto *LI = dyn_cast<LoadInst>(V);
                 return !LI || !LI->isSimple();
               }))
        LLVM_DEBUG(dbgs() << "SLP: Gathering non-simple loads.\n");
      else
        LLVM_DEBUG(dbgs() << "SLP: Gathering non-consecutive loads.\n");
#endif // NDEBUG
      registerNonVectorizableLoads(VL);
      return TreeEntry::NeedToGather;
    }
    llvm_unreachable("Unexpected state of loads");
  }
  case Instruction::ZExt:
  case Instruction::SExt:
  case Instruction::FPToUI:
  case Instruction::FPToSI:
  case Instruction::FPExt:
  case Instruction::PtrToInt:
  case Instruction::PtrToAddr:
  case Instruction::IntToPtr:
  case Instruction::SIToFP:
  case Instruction::UIToFP:
  case Instruction::Trunc:
  case Instruction::FPTrunc:
  case Instruction::BitCast: {
    Type *SrcTy = VL0->getOperand(0)->getType();
    for (Instruction *I : make_isa_range<Instruction>(VL)) {
      Type *Ty = I->getOperand(0)->getType();
      if (Ty != SrcTy || !isValidElementType(Ty, Opts.slp_revec)) {
        LLVM_DEBUG(
            dbgs() << "SLP: Gathering casts with different src types.\n");
        return TreeEntry::NeedToGather;
      }
    }
    return TreeEntry::Vectorize;
  }
  case Instruction::ICmp:
  case Instruction::FCmp: {
    // Check that all of the compares have the same predicate.
    CmpInst::Predicate P0 = cast<CmpInst>(VL0)->getPredicate();
    CmpInst::Predicate SwapP0 = CmpInst::getSwappedPredicate(P0);
    Type *ComparedTy = VL0->getOperand(0)->getType();
    for (CmpInst *Cmp : make_isa_range<CmpInst>(VL)) {
      if ((Cmp->getPredicate() != P0 && Cmp->getPredicate() != SwapP0 &&
           !CmpSamePredicateHelper::canConvertTo(Cmp, P0)) ||
          Cmp->getOperand(0)->getType() != ComparedTy) {
        LLVM_DEBUG(dbgs() << "SLP: Gathering cmp with different predicate.\n");
        return TreeEntry::NeedToGather;
      }
    }
    return TreeEntry::Vectorize;
  }
  case Instruction::Select:
    if (Opts.slp_revec) {
      SmallPtrSet<Type *, 4> CondTypes;
      for (Value *V : VL) {
        Value *Cond;
        if (!match(V, m_Select(m_Value(Cond), m_Value(), m_Value())) &&
            !match(V, m_ZExt(m_Value(Cond))))
          continue;
        CondTypes.insert(Cond->getType());
      }
      if (CondTypes.size() > 1) {
        LLVM_DEBUG(
            dbgs()
            << "SLP: Gathering select with different condition types.\n");
        return TreeEntry::NeedToGather;
      }
    }
    [[fallthrough]];
  case Instruction::FNeg:
  case Instruction::Add:
  case Instruction::FAdd:
  case Instruction::Sub:
  case Instruction::FSub:
  case Instruction::Mul:
  case Instruction::FMul:
  case Instruction::UDiv:
  case Instruction::SDiv:
  case Instruction::FDiv:
  case Instruction::URem:
  case Instruction::SRem:
  case Instruction::FRem:
  case Instruction::Shl:
  case Instruction::LShr:
  case Instruction::AShr:
  case Instruction::And:
  case Instruction::Or:
  case Instruction::Xor:
  case Instruction::Freeze:
    if (S.getMainOp()->getType()->isFloatingPointTy() &&
        TTI->isFPVectorizationPotentiallyUnsafe() &&
        any_of(make_isa_range<BinaryOperator>(VL),
               [](BinaryOperator *BO) { return !BO->isFast(); }))
      return TreeEntry::NeedToGather;
    return TreeEntry::Vectorize;
  case Instruction::GetElementPtr: {
    auto IsMatchingLane = [&S](Value *V) { return !S.isCopyableElement(V); };
    // We don't combine GEPs with complicated (nested) indexing.
    for (GetElementPtrInst *GEP : make_filter_range(
             make_isa_range<GetElementPtrInst>(VL), IsMatchingLane)) {
      if (GEP->getNumOperands() != 2) {
        LLVM_DEBUG(dbgs() << "SLP: not-vectorizable GEP (nested indexes).\n");
        return TreeEntry::NeedToGather;
      }
    }

    // We can't combine several GEPs into one vector if they operate on
    // different types.
    Type *Ty0 = cast<GEPOperator>(VL0)->getSourceElementType();
    for (GEPOperator *GEP :
         make_filter_range(make_isa_range<GEPOperator>(VL), IsMatchingLane)) {
      Type *CurTy = GEP->getSourceElementType();
      if (Ty0 != CurTy) {
        LLVM_DEBUG(dbgs() << "SLP: not-vectorizable GEP (different types).\n");
        return TreeEntry::NeedToGather;
      }
    }

    // We don't combine GEPs with non-constant indexes.
    Type *Ty1 = VL0->getOperand(1)->getType();
    for (GetElementPtrInst *GEP : make_filter_range(
             make_isa_range<GetElementPtrInst>(VL), IsMatchingLane)) {
      auto *Op = GEP->getOperand(1);
      if ((!IsScatterVectorizeUserTE && !isa<ConstantInt>(Op)) ||
          (Op->getType() != Ty1 &&
           Op->getType()->getScalarSizeInBits() >
               DL->getIndexSizeInBits(
                   GEP->getType()->getPointerAddressSpace()))) {
        LLVM_DEBUG(
            dbgs() << "SLP: not-vectorizable GEP (non-constant indexes).\n");
        return TreeEntry::NeedToGather;
      }
    }
    // The indices must be representable in a single type, the operands
    // builder casts the constants to it.
    if (!getCommonGEPIndexType(
            VL, VL0,
            [&S](Value *V) {
              return isa<GetElementPtrInst>(V) && !S.isCopyableElement(V);
            },
            *DL)) {
      LLVM_DEBUG(dbgs() << "SLP: not-vectorizable GEP (mixed index types).\n");
      return TreeEntry::NeedToGather;
    }

    return TreeEntry::Vectorize;
  }
  case Instruction::Store: {
    // Check if the stores are consecutive or if we need to swizzle them.
    llvm::Type *ScalarTy = cast<StoreInst>(VL0)->getValueOperand()->getType();
    // Avoid types that are padded when being allocated as scalars, while
    // being packed together in a vector (such as i1).
    if (DL->getTypeSizeInBits(ScalarTy) !=
        DL->getTypeAllocSizeInBits(ScalarTy)) {
      LLVM_DEBUG(dbgs() << "SLP: Gathering stores of non-packed type.\n");
      return TreeEntry::NeedToGather;
    }
    // Make sure all stores in the bundle are simple - we can't vectorize
    // atomic or volatile stores.
    for (Value *V : VL) {
      auto *SI = cast<StoreInst>(V);
      if (!SI->isSimple()) {
        LLVM_DEBUG(dbgs() << "SLP: Gathering non-simple stores.\n");
        return TreeEntry::NeedToGather;
      }
      PointerOps.push_back(SI->getPointerOperand());
    }

    // Check the order of pointer operands.
    if (llvm::sortPtrAccesses(PointerOps, ScalarTy, *DL, *SE, CurrentOrder)) {
      Value *Ptr0;
      Value *PtrN;
      if (CurrentOrder.empty()) {
        Ptr0 = PointerOps.front();
        PtrN = PointerOps.back();
      } else {
        Ptr0 = PointerOps[CurrentOrder.front()];
        PtrN = PointerOps[CurrentOrder.back()];
      }
      Align CommonAlignment = computeCommonAlignment<StoreInst>(VL);
      std::optional<int64_t> Dist =
          getPointersDiff(ScalarTy, Ptr0, ScalarTy, PtrN, *DL, *SE);
      // Check that the sorted pointer operands are consecutive.
      if (static_cast<uint64_t>(*Dist) == VL.size() - 1)
        return TreeEntry::Vectorize;
      if (Opts.slp_enable_strided_stores &&
          analyzeConstantStrideCandidate(PointerOps, ScalarTy, CommonAlignment,
                                         CurrentOrder, *Dist, Ptr0, SPtrInfo))
        return TreeEntry::StridedVectorize;
      // If the stores are not consecutive but the target supports masked stores
      // for the widened type, lower them as a masked store.
      FixedVectorType *StoreVecTy = nullptr;
      if (Opts.slp_enable_masked_stores &&
          isMaskedStoreCompress(VL, PointerOps, CurrentOrder, *TTI, *DL, *SE,
                                CommonAlignment, ReuseShuffleIndices,
                                StoreVecTy, Cache)) {
        SPtrInfo.Ty = StoreVecTy;
        return TreeEntry::ExpandVectorize;
      }
    }

    LLVM_DEBUG(dbgs() << "SLP: Non-consecutive store.\n");
    return TreeEntry::NeedToGather;
  }
  case Instruction::Call: {
    if (S.getMainOp()->getType()->isFloatingPointTy() &&
        TTI->isFPVectorizationPotentiallyUnsafe() &&
        any_of(make_isa_range<FPMathOperator>(VL),
               [](FPMathOperator *FPOp) { return !FPOp->isFast(); }))
      return TreeEntry::NeedToGather;
    // Check if the calls are all to the same vectorizable intrinsic or
    // library function.
    CallInst *CI = cast<CallInst>(VL0);
    Intrinsic::ID ID = getVectorIntrinsicIDForCall(CI, TLI);

    VFShape Shape = VFShape::get(
        CI->getFunctionType(),
        ElementCount::getFixed(static_cast<unsigned int>(VL.size())),
        false /*HasGlobalPred*/);
    Function *VecFunc = VFDatabase(*CI).getVectorizedFunction(Shape);

    if (!VecFunc && !isTriviallyVectorizable(ID)) {
      LLVM_DEBUG(dbgs() << "SLP: Non-vectorizable call.\n");
      return TreeEntry::NeedToGather;
    }
    if (isa<StructType>(CI->getType()) &&
        !allStructUsersAreExtractValueInsts(VL)) {
      LLVM_DEBUG(dbgs() << "SLP: Struct-returning calls have non-extractvalue "
                           "users.\n");
      return TreeEntry::NeedToGather;
    }
    Function *F = CI->getCalledFunction();
    unsigned NumArgs = CI->arg_size();
    SmallVector<Value *, 4> ScalarArgs(NumArgs, nullptr);
    for (unsigned J = 0; J != NumArgs; ++J)
      if (isVectorIntrinsicWithScalarOpAtArg(ID, J, TTI))
        ScalarArgs[J] = CI->getArgOperand(J);
    // Skip copyables (idempotent stand-ins) and poisons.
    for (Value *V : make_filter_range(VL, [&](Value *V) {
           return !isa<PoisonValue>(V) && !S.isCopyableElement(V);
         })) {
      CallInst *CI2 = dyn_cast<CallInst>(V);
      Intrinsic::ID ID2 = CI2 ? getVectorIntrinsicIDForCall(CI2, TLI)
                              : Intrinsic::not_intrinsic;
      Intrinsic::ID Equivalent = isEquivalentIntrinsicID(ID, ID2);
      if (!CI2 ||
          (CI2->getCalledFunction() != F &&
           isEquivalentIntrinsicID(Equivalent, Intrinsic::fmuladd) ==
               Intrinsic::not_intrinsic) ||
          (ID != ID2 && Equivalent == Intrinsic::not_intrinsic) ||
          (VecFunc &&
           VecFunc != VFDatabase(*CI2).getVectorizedFunction(Shape)) ||
          !CI->hasIdenticalOperandBundleSchema(*CI2)) {
        LLVM_DEBUG(dbgs() << "SLP: mismatched calls:" << *CI << "!=" << *V
                          << "\n");
        return TreeEntry::NeedToGather;
      }
      // Some intrinsics have scalar arguments and should be same in order for
      // them to be vectorized.
      for (unsigned J = 0; J != NumArgs; ++J) {
        if (isVectorIntrinsicWithScalarOpAtArg(ID, J, TTI)) {
          Value *A1J = CI2->getArgOperand(J);
          if (ScalarArgs[J] != A1J) {
            LLVM_DEBUG(dbgs()
                       << "SLP: mismatched arguments in call:" << *CI
                       << " argument " << ScalarArgs[J] << "!=" << A1J << "\n");
            return TreeEntry::NeedToGather;
          }
        }
      }
      // Verify that the bundle operands are identical between the two calls.
      if (CI->hasOperandBundles() &&
          !std::equal(CI->op_begin() + CI->getBundleOperandsStartIndex(),
                      CI->op_begin() + CI->getBundleOperandsEndIndex(),
                      CI2->op_begin() + CI2->getBundleOperandsStartIndex())) {
        LLVM_DEBUG(dbgs() << "SLP: mismatched bundle operands in calls:" << *CI
                          << "!=" << *V << '\n');
        return TreeEntry::NeedToGather;
      }
    }
    SmallVector<Type *> ArgTys =
        buildIntrinsicArgTypes(CI, ID, VL.size(), 0, TTI);
    auto *VecTy = getWidenedType(S.getMainOp()->getType(), VL.size());
    auto VecCallCosts =
        getVectorCallCosts(CI, VecTy, TTI, TLI, ArgTys, CostKind);
    if (!VecCallCosts.first.isValid() && !VecCallCosts.second.isValid())
      return TreeEntry::NeedToGather;

    return TreeEntry::Vectorize;
  }
  case Instruction::ShuffleVector: {
    if (!S.isAltShuffle()) {
      // REVEC can support non alternate shuffle.
      if (Opts.slp_revec && getShufflevectorNumGroups(VL))
        return TreeEntry::Vectorize;
      // If this is not an alternate sequence of opcode like add-sub
      // then do not vectorize this instruction.
      LLVM_DEBUG(dbgs() << "SLP: ShuffleVector are not vectorized.\n");
      return TreeEntry::NeedToGather;
    }

    return TreeEntry::Vectorize;
  }
  default:
    LLVM_DEBUG(dbgs() << "SLP: Gathering unknown instruction.\n");
    return TreeEntry::NeedToGather;
  }
}

namespace {
/// Allows to correctly handle operands of the phi nodes based on the \p Main
/// PHINode order of incoming basic blocks/values.
class PHIHandler {
  DominatorTree &DT;
  PHINode *Main = nullptr;
  SmallVector<Value *> Phis;
  SmallVector<SmallVector<Value *>> Operands;

public:
  PHIHandler() = delete;
  PHIHandler(DominatorTree &DT, PHINode *Main, ArrayRef<Value *> Phis)
      : DT(DT), Main(Main), Phis(Phis),
        Operands(Main->getNumIncomingValues(),
                 SmallVector<Value *>(Phis.size(), nullptr)) {}
  void buildOperands() {
    constexpr unsigned FastLimit = 4;
    if (Main->getNumIncomingValues() <= FastLimit) {
      for (unsigned I : seq<unsigned>(0, Main->getNumIncomingValues())) {
        BasicBlock *InBB = Main->getIncomingBlock(I);
        if (!DT.isReachableFromEntry(InBB)) {
          Operands[I].assign(Phis.size(), PoisonValue::get(Main->getType()));
          continue;
        }
        // Prepare the operand vector.
        for (auto [Idx, V] : enumerate(Phis)) {
          auto *P = dyn_cast<PHINode>(V);
          if (!P) {
            assert(isa<PoisonValue>(V) &&
                   "Expected isa instruction or poison value.");
            Operands[I][Idx] = V;
            continue;
          }
          if (P->getIncomingBlock(I) == InBB)
            Operands[I][Idx] = P->getIncomingValue(I);
          else
            Operands[I][Idx] = P->getIncomingValueForBlock(InBB);
        }
      }
      return;
    }
    SmallMapVector<BasicBlock *, SmallVector<unsigned>, 4>
        Blocks;
    for (unsigned I : seq<unsigned>(Main->getNumIncomingValues())) {
      BasicBlock *InBB = Main->getIncomingBlock(I);
      if (!DT.isReachableFromEntry(InBB)) {
        Operands[I].assign(Phis.size(), PoisonValue::get(Main->getType()));
        continue;
      }
      Blocks.try_emplace(InBB).first->second.push_back(I);
    }
    for (auto [Idx, V] : enumerate(Phis)) {
      if (isa<PoisonValue>(V)) {
        for (unsigned I : seq<unsigned>(Main->getNumIncomingValues()))
          Operands[I][Idx] = V;
        continue;
      }
      auto *P = cast<PHINode>(V);
      for (unsigned I : seq<unsigned>(P->getNumIncomingValues())) {
        BasicBlock *InBB = P->getIncomingBlock(I);
        if (InBB == Main->getIncomingBlock(I)) {
          if (isa_and_nonnull<PoisonValue>(Operands[I][Idx]))
            continue;
          Operands[I][Idx] = P->getIncomingValue(I);
          continue;
        }
        auto *It = Blocks.find(InBB);
        if (It == Blocks.end())
          continue;
        Operands[It->second.front()][Idx] = P->getIncomingValue(I);
      }
    }
    for (const auto &P : Blocks) {
      ArrayRef<unsigned> IncomingValues = P.second;
      if (IncomingValues.size() <= 1)
        continue;
      unsigned BasicI = IncomingValues.consume_front();
      for (unsigned I : IncomingValues) {
        assert(all_of(enumerate(Operands[I]),
                      [&](const auto &Data) {
                        return !Data.value() ||
                               Data.value() == Operands[BasicI][Data.index()];
                      }) &&
               "Expected empty operands list.");
        Operands[I] = Operands[BasicI];
      }
    }
  }
  ArrayRef<Value *> getOperands(unsigned I) const { return Operands[I]; }
};
} // namespace

/// Returns main/alternate instructions for the given \p VL. Unlike
/// getSameOpcode supports non-compatible instructions for better SplitVectorize
/// node support.
/// \returns first main/alt instructions, if only poisons and instruction with
/// only 2 opcodes exists. Returns pair of nullptr otherwise.
static std::pair<Instruction *, Instruction *>
getMainAltOpsNoStateVL(ArrayRef<Value *> VL) {
  Instruction *MainOp = nullptr;
  Instruction *AltOp = nullptr;
  for (Value *V :
       make_filter_range(VL, [](Value *V) { return !isa<PoisonValue>(V); })) {
    auto *I = dyn_cast<Instruction>(V);
    if (!I)
      return {};
    if (!MainOp) {
      MainOp = I;
      continue;
    }
    if (MainOp->getOpcode() == I->getOpcode()) {
      if (I->getParent() != MainOp->getParent())
        return {};
      continue;
    }
    if (!AltOp) {
      AltOp = I;
      continue;
    }
    if (AltOp->getOpcode() == I->getOpcode()) {
      if (I->getParent() != AltOp->getParent())
        return {};
      continue;
    }
    return {};
  }
  if (!AltOp)
    return {};
  assert(MainOp && AltOp && MainOp->getOpcode() != AltOp->getOpcode() &&
         "Expected different main and alt instructions.");
  return std::make_pair(MainOp, AltOp);
}

/// Checks that every instruction appears once in the list and if not, packs
/// them, building \p ReuseShuffleIndices mask and mutating \p VL. The list of
/// unique scalars is extended by poison values to the whole register size.
///
/// \returns false if \p VL could not be uniquified, in which case \p VL is
/// unchanged and \p ReuseShuffleIndices is empty.
static bool tryToFindDuplicates(const VectorizeOptions &Opts,
                                SmallVectorImpl<Value *> &VL,
                                SmallVectorImpl<int> &ReuseShuffleIndices,
                                const TargetTransformInfo &TTI,
                                const TargetLibraryInfo &TLI,
                                const InstructionsState &S,
                                const BoUpSLP::EdgeInfo &UserTreeIdx,
                                const BoUpSLP &R, bool BuildGatherOnly = true) {
  // TODO: Reordering of struct types is not supported.
  if (isa<StructType>(getValueType(VL.front(), Opts.slp_revec))) {
    LLVM_DEBUG(dbgs() << "SLP: struct type in bundle.\n");
    ReuseShuffleIndices.clear();
    return true;
  }
  // Check that every instruction appears once in this bundle.
  SmallVector<Value *> UniqueValues;
  SmallDenseMap<Value *, unsigned, 16> UniquePositions(VL.size());
  for (Value *V : VL) {
    if (isConstant(V)) {
      // Constants are always considered distinct, even if the same constant
      // appears multiple times in VL.
      ReuseShuffleIndices.emplace_back(
          isa<PoisonValue>(V) ? PoisonMaskElem : UniqueValues.size());
      UniqueValues.emplace_back(V);
      continue;
    }
    auto Res = UniquePositions.try_emplace(V, UniqueValues.size());
    ReuseShuffleIndices.emplace_back(Res.first->second);
    if (Res.second)
      UniqueValues.emplace_back(V);
  }

  // Check if we need to schedule the scalars. If no, can keep original scalars
  // and avoid extra shuffles.
  bool RequireScheduling = S && S.getOpcode() != Instruction::PHI &&
                           !isVectorLikeInstWithConstOps(S.getMainOp()) &&
                           (S.areInstructionsWithCopyableElements() ||
                            !doesNotNeedToSchedule(UniqueValues));
  // Compute this flag BEFORE the tail-poison erase below - it must reflect
  // the state of the original VL (for the InsertsCost call), not the
  // potentially-shrunk UniqueValues.
  bool AreAllValuesNonConst = UniquePositions.size() == UniqueValues.size();
  // Drop tail poisons, if the values can be vectorized.
  if (RequireScheduling) {
    const auto EndIt =
        find_if_not(make_range(UniqueValues.rbegin(), UniqueValues.rend()),
                    IsaPred<PoisonValue>);
    assert(EndIt != UniqueValues.rend() && "Expected at least one non-poison.");
    UniqueValues.erase(EndIt.base(), UniqueValues.end());
  }
  unsigned NumUniqueScalarValues = UniqueValues.size();
  if (NumUniqueScalarValues == VL.size()) {
    ReuseShuffleIndices.clear();
    return true;
  }

  // For VL=4 with 3 unique values: keep originals. A <3 x T> vector is
  // always widened to <4 x T> on hardware, so the packing just adds an
  // extra expand shuffle. Does not apply to loads (a <3 x T> load is a
  // single memory access) or PHIs (benefit from compact packing in loops).
  constexpr unsigned SmallVecWidth = 4;
  constexpr unsigned SmallVecUniqueThreshold = 3;
  if (VL.size() == SmallVecWidth &&
      NumUniqueScalarValues == SmallVecUniqueThreshold && !BuildGatherOnly &&
      !(S && (S.getOpcode() == Instruction::Load ||
              S.getOpcode() == Instruction::PHI))) {
    // Keep originals with identity reuse - no packing, no extra shuffle.
    ReuseShuffleIndices.clear();
    return true;
  }

  // Checks if unique inserts + shuffle is more profitable than just inserts or
  // vectorized values.
  auto EstimatePackPlusShuffleVsInserts = [&]() {
    // Single instruction/argument insert - no shuffle.
    if (UniquePositions.size() == 1 &&
        (NumUniqueScalarValues == 1 ||
         all_of(UniqueValues, IsaPred<UndefValue, Instruction, Argument>)))
      return std::make_pair(false, false);
    // For large gathers with power-of-2 VL where packing would produce
    // non-power-of-2, reject if most scalars are constants - the packing
    // overhead (non-power-of-2 split + shuffles) outweighs the benefit.
    constexpr unsigned MinVLForConstGatherCheck = 4;
    if (BuildGatherOnly && VL.size() > MinVLForConstGatherCheck &&
        has_single_bit(static_cast<unsigned>(VL.size())) &&
        !has_single_bit(NumUniqueScalarValues) &&
        UniquePositions.size() * 2 < NumUniqueScalarValues)
      return std::make_pair(false, false);
    auto GetLoadsState = [&](ArrayRef<Value *> Loads) {
      assert(S && S.getOpcode() == Instruction::Load && "Expected load.");
      BoUpSLP::OrdersType Order;
      SmallVector<Value *> PointerOps;
      BoUpSLP::StridedPtrInfo SPtrInfo;
      return R.canVectorizeLoads(Loads, S.getMainOp(), Order, PointerOps,
                                 SPtrInfo);
    };
    auto CheckLoads = [&](ArrayRef<Value *> Loads, bool IncludeGather) {
      BoUpSLP::LoadsState Res = GetLoadsState(Loads);
      return (IncludeGather && Res == BoUpSLP::LoadsState::Gather) ||
             Res == BoUpSLP::LoadsState::ScatterVectorize ||
             Res == BoUpSLP::LoadsState::StridedVectorize ||
             Res == BoUpSLP::LoadsState::CompressVectorize ||
             Res == BoUpSLP::LoadsState::BlendedLoadVectorize;
    };
    // Operand of the root tree entry on the vectorize path: always pack the
    // scalars (PackProfitable=true). Choose between keeping the original VL
    // and packing the unique values:
    // - For loads, prefer the originals only when both the deduplicated and
    //   the full sequence can be vectorized non-Gather, or when the reuse
    //   mask is the identity (the shuffle is free).
    // - For everything else (including !S, where RequireScheduling is forced
    //   to false above), keep originals iff no scheduling is required.
    bool IsRootOperand =
        UserTreeIdx.UserTE && UserTreeIdx.UserTE->Idx == 0 && !BuildGatherOnly;
    if (IsRootOperand) {
      if (S && S.getOpcode() == Instruction::Load) {
        bool UseOrig = (CheckLoads(UniqueValues, /*IncludeGather=*/true) &&
                        CheckLoads(VL, /*IncludeGather=*/false)) ||
                       ShuffleVectorInst::isIdentityMask(
                           ReuseShuffleIndices, ReuseShuffleIndices.size());
        return std::make_pair(true, UseOrig);
      }
      return std::make_pair(true, !RequireScheduling);
    }
    APInt DemandedElts = APInt::getZero(VL.size());
    for (auto [Idx, Val] : enumerate(ReuseShuffleIndices))
      if (Val != PoisonMaskElem && UniquePositions.contains(UniqueValues[Val]))
        DemandedElts.setBit(Idx);
    Type *ScalarTy = ::getValueType(UniqueValues.front(), Opts.slp_revec);
    auto *VecTy = cast<VectorType>(getWidenedType(ScalarTy, VL.size()));
    auto *UniquesVecTy =
        cast<VectorType>(getWidenedType(ScalarTy, NumUniqueScalarValues));
    const unsigned NumParts = R.getNumberOfParts(VecTy, ScalarTy);
    const unsigned UniquesNumParts = R.getNumberOfParts(UniquesVecTy, ScalarTy);
    // No need to schedule scalars and only single register used? Use original
    // scalars, do not pack.
    if (!RequireScheduling) {
      if (VL.size() / NumUniqueScalarValues == 1 &&
          (NumParts <= 1 || UniquesNumParts >= NumParts))
        return std::make_pair(true, true);
      // For PHI operands, prefer packing with reuse shuffle - the PHI
      // carries the vector through the loop cheaply.
      if (S && S.getOpcode() == Instruction::PHI && NumUniqueScalarValues > 1 &&
          UniquesNumParts <= NumParts)
        return std::make_pair(true, false);
    }
    const TTI::TargetCostKind CostKind = R.getCostKind();
    InstructionCost ReusesCost = getShuffleCost(
        TTI, TTI::SK_PermuteSingleSrc, VecTy, CostKind,
        NumUniqueScalarValues > VL.size() / 2 ? ArrayRef<int>()
                                              : ArrayRef(ReuseShuffleIndices),
        /*Index=*/0, UniquesVecTy);
    // For vectorizable (non-gather) nodes with low duplication, prefer keeping
    // the original values over packing uniques + reshuffling:
    // - A single duplicate (non-load) adds negligible overhead.
    // - When most values are already unique (>50%), or exactly half are unique
    //   for some ops (GEPs, non-alt-shuffle casts), the reshuffle cost may
    //   exceed the savings from a smaller packed vector - check against a
    //   per-register-part threshold (stricter for wider vectors).
    if (S && !BuildGatherOnly) {
      bool HasOneDup = S.getOpcode() != Instruction::Load &&
                       NumUniqueScalarValues + 1 == VL.size();
      bool MostlyUnique = NumUniqueScalarValues * 2 > VL.size();
      bool IsHalfUniqueValues =
          NumUniqueScalarValues * 2 == VL.size() &&
          (S.getOpcode() == Instruction::GetElementPtr ||
           (isa<CastInst>(S.getMainOp()) && !S.isAltShuffle()));
      InstructionCost CostThreshold =
          NumParts * (VL.size() > SmallVecWidth ? 1 : 2);
      if (HasOneDup ||
          ((MostlyUnique || IsHalfUniqueValues) && ReusesCost > CostThreshold))
        return std::make_pair(true, true);
    }
    // For loads, check if either the deduplicated or the full (with
    // duplicates) set can be scatter/compress-vectorized. Prefer the unique
    // loads (pack + reshuffle) when possible, otherwise use the originals.
    if (S && S.getOpcode() == Instruction::Load) {
      // The poison lanes are covered by a single wide load, nothing to pack.
      if (any_of(VL, IsaPred<PoisonValue>) &&
          GetLoadsState(VL) == BoUpSLP::LoadsState::Vectorize)
        return std::make_pair(true, true);
      bool UniquesVectorized =
          CheckLoads(UniqueValues, /*IncludeGather=*/false);
      if (UniquesVectorized || CheckLoads(VL, /*IncludeGather=*/false)) {
        bool UseOriginal = !UniquesVectorized;
        // The unique loads are consecutive: pack them unless the masked
        // gather of the originals is cheaper than the wide load + reshuffle.
        if (UseOriginal &&
            GetLoadsState(UniqueValues) == BoUpSLP::LoadsState::Vectorize) {
          auto *LI0 = cast<LoadInst>(S.getMainOp());
          InstructionCost PackCost =
              ReusesCost + TTI.getMemoryOpCost(
                               Instruction::Load, UniquesVecTy, LI0->getAlign(),
                               LI0->getPointerAddressSpace(), CostKind,
                               TTI::getOperandInfo(LI0->getPointerOperand()));
          InstructionCost GatherCost = TTI.getMemIntrinsicInstrCost(
              MemIntrinsicCostAttributes(
                  Intrinsic::masked_gather, VecTy, LI0->getPointerOperand(),
                  /*VariableMask=*/false, computeCommonAlignment<LoadInst>(VL)),
              CostKind);
          UseOriginal = GatherCost < PackCost;
        }
        return std::make_pair(true, UseOriginal);
      }
    }
    bool CanSkipBVCost =
        (!BuildGatherOnly && !RequireScheduling) || R.hasSameNode(S, VL);
    InstructionCost InsertsCost =
        CanSkipBVCost
            ? InstructionCost(TTI::TCC_Free)
            : getScalarizationOverhead(TTI, Opts.slp_revec, ScalarTy, VecTy,
                                       DemandedElts,
                                       /*Insert=*/true, /*Extract=*/false,
                                       CostKind, AreAllValuesNonConst, VL);
    APInt UniquesDemandedElts = APInt::getAllOnes(NumUniqueScalarValues);
    for (const auto [Idx, V] : enumerate(UniqueValues))
      if (isConstant(V))
        UniquesDemandedElts.clearBit(Idx);
    InstructionCost UniquesCost =
        CanSkipBVCost
            ? InstructionCost(TTI::TCC_Free)
            : getScalarizationOverhead(TTI, Opts.slp_revec, ScalarTy,
                                       UniquesVecTy, UniquesDemandedElts,
                                       /*Insert=*/true,
                                       /*Extract=*/false, CostKind,
                                       AreAllValuesNonConst, UniqueValues);
    UniquesCost += ReusesCost;
    if (UniquesCost <= InsertsCost) {
      // Packing to a vector that occupies the same register width as the
      // original only adds the reshuffle cost; keep the originals. Loads may
      // instead benefit from a wider contiguous load.
      if (S && S.getOpcode() != Instruction::Load) {
        unsigned EltBits =
            S.getMainOp()->getDataLayout().getTypeSizeInBits(ScalarTy);
        unsigned MinVF = R.getMinVF(EltBits);
        auto RegWidth = [&](unsigned N) {
          return std::max(
              getFullVectorNumberOfElements(TTI, ScalarTy, N, Opts.slp_revec),
              MinVF);
        };
        // Keeping the originals just moves the reshuffle to the operand
        // columns with duplicates; keep them only if at most one column has
        // duplicates, so the total number of reshuffles does not grow.
        auto HasExtraReshuffle = [&]() {
          if (BuildGatherOnly)
            return false;
          unsigned NumDupColumns = 0;
          for (unsigned OpIdx :
               seq<unsigned>(S.getMainOp()->getNumOperands())) {
            SmallPtrSet<const Value *, 16> UniqueOps;
            auto IsNotPoison = [](Value *V) { return !isa<PoisonValue>(V); };
            for (Value *V : make_filter_range(VL, IsNotPoison)) {
              Value *Op;
              if (S.isCopyableElement(V)) {
                if (OpIdx != 0)
                  continue;
                Op = V;
              } else {
                auto *I = dyn_cast<Instruction>(V);
                if (!I || OpIdx >= I->getNumOperands())
                  continue;
                Op = I->getOperand(OpIdx);
              }
              if (!isConstant(Op) && !UniqueOps.insert(Op).second) {
                ++NumDupColumns;
                break;
              }
            }
            if (NumDupColumns > 1)
              return true;
          }
          return false;
        };
        return std::make_pair(true, RegWidth(NumUniqueScalarValues) >=
                                            RegWidth(VL.size()) &&
                                        !HasExtraReshuffle());
      }
      return std::make_pair(true, false);
    }
    InstructionCost CostDiff = UniquesCost - InsertsCost;
    if (CostDiff < TTI::TCC_Expensive ||
        (R.getTreeSize() == 0 && R.isReductionTree() &&
         CostDiff == TTI::TCC_Expensive))
      return std::make_pair(S && (!S.isAltShuffle() || !BuildGatherOnly),
                            false);
    // Otherwise, use original values, if values do not require scheduling and
    // pass still try to vectorize them.
    bool KeepOriginal = !BuildGatherOnly && !RequireScheduling;
    return std::make_pair(KeepOriginal, KeepOriginal);
  };

  const auto [PackProfitable, UseOriginal] = EstimatePackPlusShuffleVsInserts();

  if (PackProfitable) {
    if (UseOriginal) {
      // Prefer original scalars - avoid shuffling.
      ReuseShuffleIndices.clear();
    } else {
      // Better to use uniques + reshuffle.
      LLVM_DEBUG(dbgs() << "SLP: Shuffle for reused scalars.\n");
      VL = std::move(UniqueValues);
    }
    return true;
  }

  // Buildvector/gather of the original scalars.
  LLVM_DEBUG(dbgs() << "SLP: Scalar used twice in bundle.\n");
  ReuseShuffleIndices.clear();
  return false;
}

/// The nodes with no more than this number of elements are not split.
static constexpr unsigned SmallNodeSize = 4;

bool BoUpSLP::canBuildSplitNode(ArrayRef<Value *> VL,
                                const InstructionsState &LocalState,
                                SmallVectorImpl<Value *> &Op1,
                                SmallVectorImpl<Value *> &Op2,
                                OrdersType &ReorderIndices) const {
  if (VL.size() <= SmallNodeSize || TTI->preferAlternateOpcodeVectorization() ||
      !Opts.slp_split_alternate_instructions)
    return false;
  // Split vectorization of struct types is not supported.
  if (isa<StructType>(getValueType(VL.front(), Opts.slp_revec)))
    return false;

  // Check if this is a duplicate of another split entry.
  LLVM_DEBUG(dbgs() << "SLP: \tChecking bundle: " << *LocalState.getMainOp()
                    << ".\n");
  for (TreeEntry *E : getSplitTreeEntries(LocalState.getMainOp())) {
    if (E->isSame(VL)) {
      LLVM_DEBUG(dbgs() << "SLP: Perfect diamond merge at "
                        << *LocalState.getMainOp() << ".\n");
      return false;
    }
    SmallPtrSet<Value *, 8> Values(llvm::from_range, E->Scalars);
    if (all_of(VL, [&](Value *V) {
          return isa<PoisonValue>(V) || Values.contains(V);
        })) {
      LLVM_DEBUG(dbgs() << "SLP: Gathering due to full overlap.\n");
      return false;
    }
  }

  ReorderIndices.assign(VL.size(), VL.size());
  SmallBitVector Op1Indices(VL.size());
  for (auto [Idx, V] : enumerate(VL)) {
    auto *I = dyn_cast<Instruction>(V);
    if (!I) {
      Op1.push_back(V);
      Op1Indices.set(Idx);
      continue;
    }
    if ((LocalState.getAltOpcode() != LocalState.getOpcode() &&
         isMainInstruction(I, LocalState.getMainOp(), LocalState.getAltOp(),
                           *TLI)) ||
        (LocalState.getAltOpcode() == LocalState.getOpcode() &&
         !isAlternateInstruction(I, LocalState.getMainOp(),
                                 LocalState.getAltOp(), *TLI))) {
      Op1.push_back(V);
      Op1Indices.set(Idx);
      continue;
    }
    Op2.push_back(V);
  }
  Type *ScalarTy = getValueType(VL.front(), Opts.slp_revec);
  auto *VecTy = cast<VectorType>(getWidenedType(ScalarTy, VL.size()));
  unsigned Opcode0 = LocalState.getOpcode();
  unsigned Opcode1 = LocalState.getAltOpcode();
  SmallBitVector OpcodeMask(getAltInstrMask(VL, ScalarTy, Opcode0, Opcode1));
  // Enable split node, only if all nodes do not form legal alternate
  // instruction (like X86 addsub).
  SmallPtrSet<Value *, 4> UOp1(llvm::from_range, Op1);
  SmallPtrSet<Value *, 4> UOp2(llvm::from_range, Op2);
  if (UOp1.size() <= 1 || UOp2.size() <= 1 ||
      TTI->isLegalAltInstr(VecTy, Opcode0, Opcode1, OpcodeMask))
    return false;
  unsigned Op1Cnt = 0, Op2Cnt = Op1.size();
  for (unsigned Idx : seq<unsigned>(VL.size())) {
    if (Op1Indices.test(Idx)) {
      ReorderIndices[Op1Cnt] = Idx;
      ++Op1Cnt;
    } else {
      ReorderIndices[Op2Cnt] = Idx;
      ++Op2Cnt;
    }
  }
  if (isIdentityOrder(ReorderIndices))
    ReorderIndices.clear();
  // When VL fills a power-of-2 register but the split halves do not, the
  // reorder shuffle makes the split unprofitable - reject.
  else if (hasFullVectorsOrPowerOf2(*TTI, Op1.front()->getType(), VL.size(),
                                    Opts.slp_revec) &&
           (!hasFullVectorsOrPowerOf2(*TTI, Op1.front()->getType(), Op1.size(),
                                      Opts.slp_revec) ||
            !hasFullVectorsOrPowerOf2(*TTI, Op2.front()->getType(), Op2.size(),
                                      Opts.slp_revec)))
    return false;
  SmallVector<int> Mask;
  if (!ReorderIndices.empty())
    inversePermutation(ReorderIndices, Mask);
  unsigned NumParts = TTI->getNumberOfParts(VecTy);
  auto *Op1VecTy = cast<VectorType>(getWidenedType(ScalarTy, Op1.size()));
  auto *Op2VecTy = cast<VectorType>(getWidenedType(ScalarTy, Op2.size()));
  // Check non-profitable single register ops, which better to be represented
  // as alternate ops.
  if (NumParts >= VL.size())
    return false;
  InstructionCost InsertCost = getShuffleCost(
      *TTI, TTI::SK_InsertSubvector, VecTy, CostKind, {}, Op1.size(), Op2VecTy);
  auto *SubVecTy = cast<VectorType>(
      getWidenedType(ScalarTy, std::max(Op1.size(), Op2.size())));
  InstructionCost NewShuffleCost =
      getShuffleCost(*TTI, TTI::SK_PermuteTwoSrc, SubVecTy, CostKind, Mask);
  if (!LocalState.isCmpOp() && NumParts <= 1 &&
      (Mask.empty() || InsertCost >= NewShuffleCost))
    return false;
  if ((LocalState.getMainOp()->isBinaryOp() &&
       LocalState.getAltOp()->isBinaryOp() &&
       (LocalState.isShiftOp() || LocalState.isBitwiseLogicOp() ||
        LocalState.isAddSubLikeOp() || LocalState.isMulDivLikeOp())) ||
      (LocalState.getMainOp()->isCast() && LocalState.getAltOp()->isCast()) ||
      (LocalState.getMainOp()->isUnaryOp() &&
       LocalState.getAltOp()->isUnaryOp())) {
    SmallVector<Value *> Ops0, Ops1;
    for (Instruction *I : make_isa_range<Instruction>(VL)) {
      Ops0.push_back(I->getOperand(0));
      if (I->isBinaryOp())
        Ops1.push_back(I->getOperand(1));
    }
    TTI::OperandValueInfo Op0Info = TTI::getOperandInfo(Ops0);
    TTI::OperandValueInfo Op1Info =
        Ops1.empty() ? TTI::OperandValueInfo() : TTI::getOperandInfo(Ops1);
    InstructionCost OriginalVecOpsCost =
        TTI->getArithmeticInstrCost(Opcode0, VecTy, CostKind, Op0Info, Op1Info,
                                    {}, LocalState.getMainOp()) +
        TTI->getArithmeticInstrCost(Opcode1, VecTy, CostKind, Op0Info, Op1Info,
                                    {}, LocalState.getAltOp());
    SmallVector<int> OriginalMask(VL.size(), PoisonMaskElem);
    for (unsigned Idx : seq<unsigned>(VL.size())) {
      if (isa<PoisonValue>(VL[Idx]))
        continue;
      OriginalMask[Idx] = Idx + (Op1Indices.test(Idx) ? 0 : VL.size());
    }
    InstructionCost OriginalCost =
        OriginalVecOpsCost + getShuffleCost(*TTI, TTI::SK_PermuteTwoSrc, VecTy,
                                            CostKind, OriginalMask);
    InstructionCost NewVecOpsCost =
        TTI->getArithmeticInstrCost(Opcode0, Op1VecTy, CostKind, Op0Info,
                                    Op1Info, {}, LocalState.getMainOp()) +
        TTI->getArithmeticInstrCost(Opcode1, Op2VecTy, CostKind, Op0Info,
                                    Op1Info, {}, LocalState.getAltOp());
    InstructionCost NewCost =
        NewVecOpsCost + InsertCost +
        (!VectorizableTree.empty() && getRootNode().hasState() &&
                 getRootNode().getOpcode() == Instruction::Store
             ? NewShuffleCost
             : 0);
    // If not profitable to split - exit.
    if (NewCost >= OriginalCost)
      return false;
  }
  return true;
}

namespace {
/// Class accepts incoming list of values, checks if it is able to model
/// "copyable" values as compatible operations, and generates the list of values
/// for scheduling and list of operands doe the new nodes.
class InstructionsCompatibilityAnalysis {
  DominatorTree &DT;
  const DataLayout &DL;
  const TargetTransformInfo &TTI;
  const TargetLibraryInfo &TLI;
  unsigned MainOpcode = 0;
  Instruction *MainOp = nullptr;
  /// Whether every copyable in the current value list is an absorbable
  /// single-use fmul/fadd. Computed once per buildInstructionsState call.
  bool AbsorbCopyableFMulOrFAdds = false;

  /// Checks if the opcode is supported as the main opcode for copyable
  /// elements.
  static bool isSupportedOpcode(const unsigned Opcode) {
    return Opcode == Instruction::Add || Opcode == Instruction::Sub ||
           Opcode == Instruction::Mul || Opcode == Instruction::AShr ||
           Opcode == Instruction::LShr || Opcode == Instruction::Shl ||
           Opcode == Instruction::SDiv || Opcode == Instruction::UDiv ||
           Opcode == Instruction::And || Opcode == Instruction::Or ||
           Opcode == Instruction::Xor || Opcode == Instruction::FAdd ||
           Opcode == Instruction::FSub || Opcode == Instruction::FMul ||
           Opcode == Instruction::FDiv;
  }

  /// Checks if \p I can be the main op for copyable analysis: a supported
  /// binary operator, fmuladd, or an integer min/max intrinsic, the only
  /// call with a well-defined idempotent value (FP min/max lacks one because of
  /// NaNs). An extractelement with constant index from a fixed vector is also
  /// supported: the matching lanes reuse the source vector and the copyable
  /// lanes are inserted into it. A single-index scalar GEP is supported: the
  /// copyable lanes are modeled as zero-index GEPs of the lane values
  /// themselves. A scalar zext is supported: the copyable lanes are constants
  /// modeled as zexts of truncated constants.
  static bool isSupportedMainOp(Instruction *I) {
    return isSupportedOpcode(I->getOpcode()) || isa<MinMaxIntrinsic>(I) ||
           RecurrenceDescriptor::isFMulAddIntrinsic(I) ||
           (isa<ExtractElementInst>(I) && isVectorLikeInstWithConstOps(I) &&
            isa<FixedVectorType>(I->getOperand(0)->getType())) ||
           (isa<GetElementPtrInst>(I) && I->getNumOperands() == 2 &&
            !I->getType()->isVectorTy()) ||
           (isa<ZExtInst>(I) && !I->getType()->isVectorTy() &&
            !isa<Constant>(I->getOperand(0)));
  }

  /// Identifies the best candidate value, which represents main opcode
  /// operation.
  /// Currently the best candidate is the Add instruction with the parent
  /// block with the highest DFS incoming number (block, that dominates other).
  void findAndSetMainInstruction(ArrayRef<Value *> VL, const BoUpSLP &R) {
    BasicBlock *Parent = nullptr;
    // Checks if the instruction has supported opcode.
    auto IsSupportedInstruction = [&](Instruction *I, bool AnyUndef) {
      if (AnyUndef && (I->isIntDivRem() || I->isFPDivRem() || isa<CallInst>(I)))
        return false;
      return I && isSupportedMainOp(I) &&
             (!doesNotNeedToBeScheduled(I) || !R.isVectorized(I));
    };
    // Exclude operands instructions immediately to improve compile time, it
    // will be unable to schedule anyway.
    SmallDenseSet<Value *, 8> Operands;
    SmallMapVector<unsigned, SmallVector<Instruction *>, 4> Candidates;
    bool AnyUndef = false;
    for (Value *V : VL) {
      auto *I = dyn_cast<Instruction>(V);
      if (!I) {
        AnyUndef |= isa<UndefValue>(V);
        continue;
      }
      if (!DT.isReachableFromEntry(I->getParent()))
        continue;
      if (Candidates.empty()) {
        Candidates.try_emplace(I->getOpcode()).first->second.push_back(I);
        Parent = I->getParent();
        Operands.insert(I->op_begin(), I->op_end());
        continue;
      }
      if (Parent == I->getParent()) {
        Candidates.try_emplace(I->getOpcode()).first->second.push_back(I);
        Operands.insert(I->op_begin(), I->op_end());
        continue;
      }
      auto *NodeA = DT.getNode(Parent);
      auto *NodeB = DT.getNode(I->getParent());
      assert(NodeA && "Should only process reachable instructions");
      assert(NodeB && "Should only process reachable instructions");
      assert((NodeA == NodeB) ==
                 (NodeA->getDFSNumIn() == NodeB->getDFSNumIn()) &&
             "Different nodes should have different DFS numbers");
      if (NodeA->getDFSNumIn() < NodeB->getDFSNumIn()) {
        Candidates.clear();
        Candidates.try_emplace(I->getOpcode()).first->second.push_back(I);
        Parent = I->getParent();
        Operands.clear();
        Operands.insert(I->op_begin(), I->op_end());
      }
    }
    unsigned BestOpcodeNum = 0;
    MainOp = nullptr;
    bool UsedOutside = false;
    for (const auto &P : Candidates) {
      bool PUsedOutside = all_of(P.second, isUsedOutsideBlock);
      if (UsedOutside && !PUsedOutside)
        continue;
      if (!UsedOutside && PUsedOutside)
        BestOpcodeNum = 0;
      if (P.second.size() < BestOpcodeNum)
        continue;
      // If have inner dependencies - skip.
      if (!PUsedOutside && any_of(P.second, [&](Instruction *I) {
            return Operands.contains(I);
          }))
        continue;
      // On a tie, keep the outer binary op as MainOp rather than replacing it
      // with an inner op that appears as its direct operand. For example, in
      // (2.0f * A) + B the fadd and fmul each appear once in VL; without this
      // check the fmul could win and prevent vectorization of the fadd pair.
      if (P.second.size() == BestOpcodeNum) {
        auto *I = P.second.front();
        if (auto *MainBO = dyn_cast<BinaryOperator>(MainOp)) {
          auto *MainBOOp0 = dyn_cast<Instruction>(MainBO->getOperand(0));
          auto *MainBOOp1 = dyn_cast<Instruction>(MainBO->getOperand(1));
          if (MainBOOp0 && MainBOOp0->getOpcode() == I->getOpcode() &&
              MainBOOp0->getParent() == I->getParent())
            continue;
          if (MainBOOp1 && MainBOOp1->getOpcode() == I->getOpcode() &&
              MainBOOp1->getParent() == I->getParent())
            continue;
        }
        // Keep fmuladd over fmul/fadd on a tie only when every copyable is
        // an absorbed fmul/fadd.
        if (RecurrenceDescriptor::isFMulAddIntrinsic(MainOp) &&
            (I->getOpcode() == Instruction::FMul ||
             I->getOpcode() == Instruction::FAdd) &&
            AbsorbCopyableFMulOrFAdds)
          continue;
        // Same check when fmuladd replaces fmul/fadd on a tie.
        if ((MainOp->getOpcode() == Instruction::FMul ||
             MainOp->getOpcode() == Instruction::FAdd) &&
            RecurrenceDescriptor::isFMulAddIntrinsic(I) &&
            !AbsorbCopyableFMulOrFAdds)
          continue;
      }
      UsedOutside = PUsedOutside;
      if (P.first == Instruction::GetElementPtr) {
        // Only the GEPs of the main op shape (source element type and index
        // type) are matching lanes, the others are copyable. Select the most
        // frequent shape to minimize the number of copyable lanes.
        SmallDenseMap<std::pair<Type *, Type *>, unsigned, 4> ShapeCounts;
        auto GetShape = [](Instruction *I) {
          return std::make_pair(cast<GEPOperator>(I)->getSourceElementType(),
                                I->getOperand(1)->getType());
        };
        for (Instruction *I : P.second)
          if (IsSupportedInstruction(I, AnyUndef))
            ++ShapeCounts[GetShape(I)];
        unsigned BestShapeNum = 0;
        for (Instruction *I : P.second) {
          if (!IsSupportedInstruction(I, AnyUndef))
            continue;
          unsigned ShapeNum = ShapeCounts.lookup(GetShape(I));
          if (ShapeNum > BestShapeNum) {
            MainOp = I;
            BestOpcodeNum = P.second.size();
            BestShapeNum = ShapeNum;
          }
        }
        continue;
      }
      for (Instruction *I : P.second) {
        if (IsSupportedInstruction(I, AnyUndef)) {
          MainOp = I;
          BestOpcodeNum = P.second.size();
          break;
        }
      }
    }
    if (MainOp) {
      // Do not match, if any copyable is a terminator from the same block as
      // the main operation.
      if (any_of(make_isa_range<Instruction>(VL), [&](Instruction *I) {
            return I->getParent() == MainOp->getParent() && I->isTerminator();
          })) {
        MainOp = nullptr;
        return;
      }
      // fma lanes match the fmuladd main op; use an fma as the main op so the
      // fused form is not weakened to fmuladd.
      if (RecurrenceDescriptor::isFMulAddIntrinsic(MainOp)) {
        auto *It = find_if(VL, [&](Value *V) {
          return match(V, m_Intrinsic<Intrinsic::fma>()) &&
                 cast<Instruction>(V)->getParent() == MainOp->getParent();
        });
        if (It != VL.end())
          MainOp = cast<Instruction>(*It);
        if (doesNotNeedToBeScheduled(MainOp) && R.isVectorized(MainOp)) {
          MainOp = nullptr;
          return;
        }
      }
      MainOpcode = MainOp->getOpcode();
    }
  }

  /// Returns the idempotent value for MainOp. For Add, returns 0. For Or, it
  /// should choose between false and the operand itself, since V or V == V.
  /// For the min/max intrinsics, returns the corresponding limit value (e.g. 0
  /// for umax, since umax(V, 0) == V). For smin and smax the type limit is
  /// kept when it stays same after narrowing, otherwise the limit is deduced
  /// from the signed width of V.
  Value *selectBestIdempotentValue(Value *V) const {
    assert(isSupportedMainOp(MainOp) && "Unsupported opcode");
    if (auto *MinMax = dyn_cast<MinMaxIntrinsic>(MainOp);
        MinMax && MinMax->isSigned() &&
        !isTypeLimitNeutral(V, MinMax->getIntrinsicID() == Intrinsic::smax,
                            DL)) {
      // TODO: add AC to both width queries once the analysis has one.
      unsigned Width = ComputeMaxSignificantBits(V, DL, nullptr, nullptr, &DT);
      APInt Limit = MinMax->getIntrinsicID() == Intrinsic::smax
                        ? APInt::getSignedMinValue(Width)
                        : APInt::getSignedMaxValue(Width);
      return Constant::getIntegerValue(
          MainOp->getType(),
          Limit.sext(MainOp->getType()->getScalarSizeInBits()));
    }
    return ConstantExpr::getIdentity(MainOp, MainOp->getType(),
                                     !MainOp->isCommutative());
  }

  /// Returns the value and operands for the \p V, considering if it is original
  /// instruction and its actual operands should be returned, or it is a
  /// copyable element and its should be represented as idempotent instruction.
  /// \p SelfOp selects the op(V, V) modeling for a copyable lane instead of
  /// op(V, identity). \p PoisonPlaceholder selects op(V, poison) for the
  /// absorbing constant V.
  SmallVector<Value *> getOperands(const InstructionsState &S, Value *V,
                                   bool SelfOp,
                                   bool PoisonPlaceholder = false) const {
    if (SelfOp)
      return {V, V};
    if (isa<PoisonValue>(V)) {
      // Poison operands of the main op operand types: a GEP index or a cast
      // source has a type, different from the lane type. Excludes the
      // trailing callee operand of a call.
      auto *CI = dyn_cast<CallInst>(MainOp);
      return map_to_vector(
          seq<unsigned>(CI ? CI->arg_size() : MainOp->getNumOperands()),
          [&](unsigned Idx) -> Value * {
            return PoisonValue::get(MainOp->getOperand(Idx)->getType());
          });
    }
    if (!S.isCopyableElement(V))
      return convertTo(cast<Instruction>(V), S).second;
    if (isFMAOrFMulAdd(MainOp)) {
      Type *Ty = MainOp->getType();
      if (S.hasAbsorbedCopyableFMulOrFAdd() &&
          isAbsorbableCopyableFMulOrFAdd(S, V)) {
        auto *I = cast<Instruction>(V);
        // fmuladd(a, b, -0.0) == fmul a, b.
        if (I->getOpcode() == Instruction::FMul)
          return {I->getOperand(0), I->getOperand(1),
                  ConstantFP::getNegativeZero(Ty)};
        // fmuladd(1.0, a, b) == fadd a, b.
        return {ConstantFP::get(Ty, 1.0), I->getOperand(0), I->getOperand(1)};
      }
      // fmuladd(V, 1.0, -0.0) == V.
      if (S.getCopyableOpIdx() == 0)
        return {V, ConstantFP::get(Ty, 1.0), ConstantFP::getNegativeZero(Ty)};
      // fmuladd(0.0, -0.0, V) == V.
      return {ConstantFP::getZero(Ty), ConstantFP::getNegativeZero(Ty), V};
    }
    // gep V, 0 == V.
    if (MainOpcode == Instruction::GetElementPtr)
      return {V, ConstantInt::get(MainOp->getOperand(1)->getType(), 0)};
    // zext(trunc(V)) == V for the round-trippable constant lanes.
    if (MainOpcode == Instruction::ZExt)
      return {ConstantExpr::getTrunc(cast<Constant>(V),
                                     cast<CastInst>(MainOp)->getSrcTy())};
    assert(isSupportedMainOp(MainOp) && "Unsupported opcode");
    Type *Ty = V->getType();
    if (PoisonPlaceholder &&
        V == ConstantExpr::getBinOpAbsorber(MainOpcode, Ty))
      return {V, PoisonValue::get(Ty)};
    if (isa<UndefValue>(V) && isUndefTolerantBinOp(MainOp))
      return {V, V};
    return {V, selectBestIdempotentValue(V)};
  }

  /// Checks if the lanes with the absorbing constant may use poison as the
  /// other operand: every other non-poison lane must be a binary operator with
  /// one constant operand and an undef-tolerant binary operator of a distinct
  /// load as the other operand.
  bool canUsePoisonPlaceholders(const InstructionsState &S,
                                ArrayRef<Value *> VL) const {
    Constant *Absorber =
        ConstantExpr::getBinOpAbsorber(MainOpcode, VL.front()->getType());
    if (!Absorber || !is_contained(VL, Absorber))
      return false;
    SmallPtrSet<const LoadInst *, 8> Loads;
    return all_of(VL, [&](Value *V) {
      if (isa<PoisonValue>(V) || S.isCopyableElement(V))
        return true;
      SmallVector<Value *> Ops = convertTo(cast<Instruction>(V), S).second;
      return count_if(Ops, IsaPred<Constant>) == 1 &&
             any_of(Ops, [&](Value *Op) {
               const LoadInst *LI = getLoadOfUndefTolerantBinOp(Op);
               return LI && Loads.insert(LI).second;
             });
    });
  }

  /// Returns the copyable lanes of an idempotent binop to be modeled as
  /// op(V, V) == V instead of op(V, identity): when the operand column the
  /// lane joins also holds a constant lane, the reorder would align that
  /// column as constants and move the lane out, breaking the opcode-peer
  /// node, while the symmetric form is reorder-proof. The other column must
  /// be an instruction node so the lane is absorbed there as a copyable
  /// rather than breaking a constant column. A lane is modeled this way only
  /// when it has a strong opcode-peer pair of its own.
  SmallPtrSet<const Value *, 4> findSelfOpLanes(const InstructionsState &S,
                                                ArrayRef<Value *> VL,
                                                const BoUpSLP &R) const {
    SmallPtrSet<const Value *, 4> SelfOpLanes;
    if (!Instruction::isIdempotent(MainOpcode) ||
        !S.areInstructionsWithCopyableElements() || none_of(VL, [&](Value *V) {
          if (isa<PoisonValue>(V))
            return false;
          if (S.isCopyableElement(V))
            return isa<Constant>(V);
          return isa<Constant>(cast<Instruction>(V)->getOperand(0));
        }))
      return SelfOpLanes;
    // Index the instruction operands of the non-copyable lanes by opcode
    // and block, so the copyable lanes find their opcode peers without a
    // quadratic scan.
    SmallDenseMap<std::pair<unsigned, BasicBlock *>, SmallVector<Value *>>
        PeerOps;
    for (Instruction *RI : make_isa_range<Instruction>(VL)) {
      if (S.isCopyableElement(RI))
        continue;
      assert(RI->getNumOperands() == 2 && "Expected binary operation.");
      for (unsigned OpIdx : seq<unsigned>(RI->getNumOperands())) {
        auto *OpI = dyn_cast<Instruction>(RI->getOperand(OpIdx));
        if (OpI &&
            isa<Instruction>(RI->getOperand(RI->getNumOperands() - 1 - OpIdx)))
          PeerOps[{OpI->getOpcode(), OpI->getParent()}].push_back(OpI);
      }
    }
    for (Instruction *I : make_isa_range<Instruction>(VL)) {
      if (!S.isCopyableElement(I))
        continue;
      auto It = PeerOps.find({I->getOpcode(), I->getParent()});
      if (It == PeerOps.end())
        continue;
      SmallVector<std::pair<Value *, Value *>> Candidates;
      for (Value *OpI : It->second)
        Candidates.emplace_back(I, OpI);
      if (R.findBestRootPair(Candidates).first)
        SelfOpLanes.insert(I);
    }
    return SelfOpLanes;
  }

  /// Builds the index operands of a GEP node with the main op \p VL0. The
  /// indices of the matching GEP lanes (for which \p IsGEPLane returns true)
  /// are cast to the common index type, all other lanes (non-GEP pointers,
  /// copyable and poison lanes, modeled as gep V, 0) get a zero index of that
  /// type. Required to be able to find correct matches between different
  /// gather nodes and reuse the vectorized values rather than trying to
  /// gather them again. The vectorized nodes always have the common index
  /// type (a legality invariant); the operands built for the profitability
  /// analysis before that check may have none, the constants are cast to the
  /// pointer index type then.
  void buildGEPIndexOperands(ArrayRef<Value *> VL, Instruction *VL0,
                             function_ref<bool(Value *)> IsGEPLane,
                             BoUpSLP::ValueList &Indices) const {
    constexpr unsigned IndexIdx = 1;
    Type *Ty = getCommonGEPIndexType(VL, VL0, IsGEPLane, DL);
    if (!Ty)
      Ty = DL.getIndexType(VL0->getOperand(0)->getType()->getScalarType());
    for (auto [Idx, V] : enumerate(VL)) {
      if (!IsGEPLane(V)) {
        Indices[Idx] = ConstantInt::getNullValue(Ty);
        continue;
      }
      auto *Op = cast<GetElementPtrInst>(V)->getOperand(IndexIdx);
      auto *CI = dyn_cast<ConstantInt>(Op);
      Indices[Idx] = CI ? ConstantFoldIntegerCast(
                              CI, Ty, CI->getValue().isSignBitSet(), DL)
                        : Op;
    }
  }

  /// Builds operands for the original instructions.
  void
  buildOriginalOperands(const InstructionsState &S, ArrayRef<Value *> VL,
                        SmallVectorImpl<BoUpSLP::ValueList> &Operands) const {

    unsigned ShuffleOrOp =
        S.isAltShuffle() ? (unsigned)Instruction::ShuffleVector : S.getOpcode();
    Instruction *VL0 = S.getMainOp();

    switch (ShuffleOrOp) {
    case Instruction::PHI: {
      auto *PH = cast<PHINode>(VL0);

      // Keeps the reordered operands to avoid code duplication.
      PHIHandler Handler(DT, PH, VL);
      Handler.buildOperands();
      Operands.assign(PH->getNumOperands(), {});
      for (unsigned I : seq<unsigned>(PH->getNumOperands()))
        Operands[I].assign(Handler.getOperands(I).begin(),
                           Handler.getOperands(I).end());
      return;
    }
    case Instruction::ExtractValue: {
      SmallVector<unsigned> Indices;
      SmallVector<Value *> Calls;
      if (checkEVsForVecCalls(VL, S, TLI, Indices, Calls)) {
        Operands.assign(1, {});
        Operands[0].swap(Calls);
        return;
      }
      [[fallthrough]];
    }
    case Instruction::ExtractElement:
      // This is a special case, as it does not gather, but at the same time
      // we are not extending buildTree_rec() towards the operands.
      Operands.assign(1, {VL.size(), VL0->getOperand(0)});
      return;
    case Instruction::InsertValue:
    case Instruction::InsertElement:
      Operands.assign(2, {VL.size(), nullptr});
      for (auto [Idx, V] : enumerate(VL)) {
        auto *IE = cast<Instruction>(V);
        for (auto [OpIdx, Ops] : enumerate(Operands))
          Ops[Idx] = IE->getOperand(OpIdx);
      }
      return;
    case Instruction::Load:
      Operands.assign(
          1, {VL.size(),
              PoisonValue::get(cast<LoadInst>(VL0)->getPointerOperandType())});
      for (auto [V, Op] : zip(VL, Operands.back())) {
        auto *LI = dyn_cast<LoadInst>(V);
        if (!LI)
          continue;
        Op = LI->getPointerOperand();
      }
      return;
    case Instruction::ICmp:
      // With trunc X to i1 lanes the node is the bit tests of and A, B: the
      // compares give the operands of their ands, trunc X gives X and 1.
      if (any_of(VL, IsaPred<TruncInst>)) {
        Type *Ty = VL0->getOperand(0)->getType();
        Operands.assign(2, {VL.size(), PoisonValue::get(Ty)});
        for (auto [Idx, V] : enumerate(VL)) {
          if (auto *TI = dyn_cast<TruncInst>(V)) {
            Operands[0][Idx] = TI->getOperand(0);
            Operands[1][Idx] = ConstantInt::get(Ty, 1);
          } else if (auto *CI = dyn_cast<ICmpInst>(V)) {
            auto *And = cast<BinaryOperator>(CI->getOperand(0));
            Operands[0][Idx] = And->getOperand(0);
            Operands[1][Idx] = And->getOperand(1);
          }
        }
        return;
      }
      [[fallthrough]];
    case Instruction::ZExt:
    case Instruction::SExt:
    case Instruction::FPToUI:
    case Instruction::FPToSI:
    case Instruction::FPExt:
    case Instruction::PtrToInt:
    case Instruction::PtrToAddr:
    case Instruction::IntToPtr:
    case Instruction::SIToFP:
    case Instruction::UIToFP:
    case Instruction::Trunc:
    case Instruction::FPTrunc:
    case Instruction::BitCast:
    case Instruction::FCmp:
    case Instruction::FNeg:
    case Instruction::Add:
    case Instruction::FAdd:
    case Instruction::Sub:
    case Instruction::FSub:
    case Instruction::Mul:
    case Instruction::FMul:
    case Instruction::UDiv:
    case Instruction::SDiv:
    case Instruction::FDiv:
    case Instruction::URem:
    case Instruction::SRem:
    case Instruction::FRem:
    case Instruction::Shl:
    case Instruction::LShr:
    case Instruction::AShr:
    case Instruction::And:
    case Instruction::Or:
    case Instruction::Xor:
    case Instruction::Freeze:
    case Instruction::Store:
    case Instruction::ShuffleVector:
      Operands.assign(VL0->getNumOperands(), {VL.size(), nullptr});
      for (auto [Idx, V] : enumerate(VL)) {
        auto *I = dyn_cast<Instruction>(V);
        if (!I) {
          for (auto [OpIdx, Ops] : enumerate(Operands))
            Ops[Idx] = PoisonValue::get(VL0->getOperand(OpIdx)->getType());
          continue;
        }
        SmallVector<Value *> ConvertedOps = convertTo(I, S).second;
        for (auto [OpIdx, Ops] : enumerate(Operands))
          Ops[Idx] = ConvertedOps[OpIdx];
      }
      return;
    case Instruction::Select:
      Operands.assign(VL0->getNumOperands(), {VL.size(), nullptr});
      for (auto [Idx, V] : enumerate(VL)) {
        auto *I = dyn_cast<Instruction>(V);
        if (!I) {
          for (auto [OpIdx, Ops] : enumerate(Operands))
            Ops[Idx] = PoisonValue::get(VL0->getOperand(OpIdx)->getType());
          continue;
        }
        if (isa<ZExtInst>(I)) {
          // Special case for select + zext i1 to avoid explosion of different
          // types. We want to keep the condition as i1 to be able to match
          // different selects together and reuse the vectorized condition
          // rather than trying to gather it.
          Operands[0][Idx] = I->getOperand(0);
          Operands[1][Idx] = ConstantInt::get(I->getType(), 1);
          Operands[2][Idx] = ConstantInt::getNullValue(I->getType());
          continue;
        }
        SmallVector<Value *> ConvertedOps = convertTo(I, S).second;
        for (auto [OpIdx, Ops] : enumerate(Operands))
          Ops[Idx] = ConvertedOps[OpIdx];
      }
      return;
    case Instruction::GetElementPtr: {
      Operands.assign(2, {VL.size(), nullptr});
      for (auto [Idx, V] : enumerate(VL)) {
        auto *GEP = dyn_cast<GetElementPtrInst>(V);
        Operands[0][Idx] = GEP ? GEP->getPointerOperand() : V;
      }
      buildGEPIndexOperands(VL, VL0, IsaPred<GetElementPtrInst>, Operands[1]);
      return;
    }
    case Instruction::Call: {
      auto *CI = cast<CallInst>(VL0);
      Intrinsic::ID ID = getVectorIntrinsicIDForCall(CI, &TLI);
      for (unsigned Idx : seq<unsigned>(CI->arg_size())) {
        if (isVectorIntrinsicWithScalarOpAtArg(ID, Idx, &TTI))
          continue;
        auto &Ops = Operands.emplace_back();
        for (Value *V : VL) {
          auto *I = dyn_cast<Instruction>(V);
          Ops.push_back(I ? I->getOperand(Idx)
                          : PoisonValue::get(VL0->getOperand(Idx)->getType()));
        }
      }
      return;
    }
    default:
      break;
    }
    llvm_unreachable("Unexpected vectorization of the instructions.");
  }

  /// Check if the specified \p VL list of values is better to represent as
  /// uniform with copyables, as modeled via \p CopyableS, or as alternate (or
  /// uniform with compatible ops), modeled via \p S.
  /// Performs the analysis of the operands, choosing the preferred main
  /// instruction and checking the matching of the operands for the main
  /// instruction and copyable elements.
  bool isCopyablePreferable(ArrayRef<Value *> VL, const BoUpSLP &R,
                            const InstructionsState &S,
                            const InstructionsState &CopyableS) {
    // If all elements are vectorized already - keep as is.
    if (all_of(VL, [&](Value *V) {
          return isa<PoisonValue>(V) || R.isVectorized(V);
        }))
      return false;
    Instruction *SMain = S.getMainOp();
    Instruction *SAlt = S.isAltShuffle() ? S.getAltOp() : nullptr;
    const bool IsCommutative = isCommutative(SMain);
    const bool IsAltCommutative =
        S.isAltShuffle() ? isCommutative(SAlt) : false;
    const bool IsMainCommutative = isCommutative(MainOp);
    SmallVector<BoUpSLP::ValueList> Ops;
    buildOriginalOperands(S, SMain, Ops);
    // Support only binary operations for now.
    if (Ops.size() != 2)
      return false;
    // Try to find better candidate for S main instruction, which operands have
    // better matching.
    auto CheckOperands = [](Value *Op, Value *SMainOp) {
      auto *OpI = dyn_cast<BinaryOperator>(Op);
      if (!OpI)
        return false;
      auto *SMainOpI = dyn_cast<BinaryOperator>(SMainOp);
      if (!SMainOpI)
        return true;
      return any_of(make_isa_range<Instruction>(OpI->operands()),
                    [&](Instruction *I) {
                      return I->getOpcode() == SMainOpI->getOpcode();
                    });
    };
    SmallPtrSet<Value *, 8> Operands;
    for (Instruction *I : make_isa_range<Instruction>(VL)) {
      if (I == SMain)
        continue;
      Instruction *MatchingOp = S.getMatchingMainOpOrAltOp(I);
      if (MatchingOp != SMain)
        continue;
      SmallVector<BoUpSLP::ValueList> VOps;
      buildOriginalOperands(S, I, VOps);
      Operands.insert(I->op_begin(), I->op_end());
      assert(VOps.size() == 2 && Ops.size() == 2 &&
             "Expected binary operations only.");
      if (CheckOperands(VOps[0][0], Ops[0][0]) ||
          CheckOperands(VOps[1][0], Ops[1][0]) ||
          (IsCommutative && (CheckOperands(VOps[0][0], Ops[1][0]) ||
                             CheckOperands(VOps[1][0], Ops[0][0])))) {
        SMain = I;
        Ops.swap(VOps);
        break;
      }
    }
    SmallVector<BoUpSLP::ValueList> MainOps;
    buildOriginalOperands(S, MainOp, MainOps);

    auto BuildFirstOperandCandidates =
        [&](SmallVectorImpl<std::pair<Value *, Value *>> &Candidates,
            ArrayRef<BoUpSLP::ValueList> Ops, Value *Op0, Value *Op1,
            bool IsCommutative) {
          Candidates.emplace_back(Ops[0][0], Op0);
          if (IsCommutative)
            Candidates.emplace_back(Ops[0][0], Op1);
        };

    auto BuildSecondOperandCandidates =
        [&](SmallVectorImpl<std::pair<Value *, Value *>> &Candidates,
            ArrayRef<BoUpSLP::ValueList> Ops, int PrevBestIdx, Value *Op0,
            Value *Op1, bool IsCommutative) {
          if (PrevBestIdx != 1)
            Candidates.emplace_back(Ops[1][0], Op1);
          if (PrevBestIdx != 0 && IsCommutative)
            Candidates.emplace_back(Ops[1][0], Op0);
        };

    auto FindBestCandidate =
        [&](ArrayRef<std::pair<Value *, Value *>> Candidates, bool &IsConst,
            int &Score) {
          auto Res = R.findBestRootPair(Candidates);
          Score = Res.second;
          IsConst =
              Res.second == BoUpSLP::LookAheadHeuristics::ScoreConstants &&
              isConstant(Candidates[Res.first.value_or(0)].first) &&
              isConstant(Candidates[Res.first.value_or(0)].second);
          if (IsConst) {
            // Check if there are splat candidates and consider them better
            // option.
            for (const auto [Idx, P] : enumerate(Candidates)) {
              if (!isConstant(P.first) && !isConstant(P.second) &&
                  P.second == P.first) {
                Res.first = Idx;
                IsConst = false;
                Score = isa<LoadInst>(Candidates[Res.first.value_or(0)].first)
                            ? BoUpSLP::LookAheadHeuristics::ScoreSplatLoads
                            : BoUpSLP::LookAheadHeuristics::ScoreSplat;
                break;
              }
            }
          }
          return Res.first;
        };

    for (Instruction *I : make_isa_range<Instruction>(VL)) {
      if (I == SMain && (I == MainOp || !S.isAltShuffle()))
        continue;
      SmallVector<BoUpSLP::ValueList> VOps;
      buildOriginalOperands(S, I == SMain ? MainOp : I, VOps);
      SmallVector<Value *> CopyableOps =
          getOperands(CopyableS, I == MainOp ? SMain : I, /*SelfOp=*/false);
      if (CopyableOps.size() == VOps.size() &&
          all_of(zip(CopyableOps, VOps), [&](const auto &P) {
            return std::get<0>(P) == std::get<1>(P)[0];
          }))
        continue;
      SmallVector<std::pair<Value *, Value *>> Candidates;
      BuildFirstOperandCandidates(Candidates, MainOps, CopyableOps[0],
                                  CopyableOps[1], IsMainCommutative);
      const unsigned OpSize = Candidates.size();
      Instruction *MatchingOp =
          S.getMatchingMainOpOrAltOp(I) == S.getMainOp() ? SMain : SAlt;
      const bool IsCommutativeInst =
          (MatchingOp == SMain ? IsCommutative : IsAltCommutative) ||
          isCommutative(I, MatchingOp);
      if (S.isAltShuffle() && MatchingOp == SAlt &&
          any_of(VOps, [&](const BoUpSLP::ValueList &Ops) {
            auto *I = dyn_cast<BinaryOperator>(Ops[0]);
            return I && Operands.contains(I);
          }))
        return false;
      if (S.isAltShuffle() && MatchingOp == SMain)
        Operands.insert(I->op_begin(), I->op_end());
      BuildFirstOperandCandidates(Candidates, Ops, VOps[0][0], VOps[1][0],
                                  IsCommutativeInst);
      bool IsBestConst;
      int Score;
      std::optional<int> BestOp =
          FindBestCandidate(Candidates, IsBestConst, Score);
      const bool IsOriginalBetter =
          static_cast<unsigned>(BestOp.value_or(OpSize)) >= OpSize;
      Candidates.clear();
      BuildSecondOperandCandidates(
          Candidates, MainOps, IsOriginalBetter ? -1 : *BestOp, CopyableOps[0],
          CopyableOps[1], IsMainCommutative);
      const unsigned SecondOpSize = Candidates.size();
      BuildSecondOperandCandidates(
          Candidates, Ops,
          IsOriginalBetter ? BestOp.value_or(OpSize - 1) - OpSize : -1,
          VOps[0][0], VOps[1][0], IsCommutativeInst);
      bool IsSecondBestConst;
      int SecondScore;
      std::optional<int> SecondBestOp =
          FindBestCandidate(Candidates, IsSecondBestConst, SecondScore);
      // No best candidates.
      if (!BestOp && !SecondBestOp)
        return false;
      // Original better in both ops combinations.
      const bool IsSecondOriginalBetter =
          static_cast<unsigned>(SecondBestOp.value_or(SecondOpSize)) >=
          SecondOpSize;
      if (IsOriginalBetter && IsSecondOriginalBetter)
        return false;
      // Original is better in second combination, but in the first combination
      // no best candidates.
      if (!BestOp && IsSecondOriginalBetter)
        return false;
      // Original is better in first combination, but in the second combination
      // no best candidates.
      if (!SecondBestOp && IsOriginalBetter)
        return false;
      // Copyable is best in the first combination, but it is constant, but
      // original is better in second non-constant combination.
      if (!IsOriginalBetter && IsBestConst && IsSecondOriginalBetter &&
          !IsSecondBestConst)
        return false;
      // Copyable is best in the second combination, but it is constant, but
      // original is better in the first non-constant combination.
      if (BestOp && IsOriginalBetter && !IsBestConst &&
          !IsSecondOriginalBetter && IsSecondBestConst)
        return false;
      // Original combination score is better.
      if (((Score > SecondScore ||
            (Score <= BoUpSLP::LookAheadHeuristics::ScoreAltOpcodes &&
             Score == SecondScore)) &&
           IsOriginalBetter) ||
          (IsSecondOriginalBetter &&
           (SecondScore > Score ||
            (Score <= BoUpSLP::LookAheadHeuristics::ScoreAltOpcodes &&
             Score == SecondScore))))
        return false;
    }
    return true;
  }

public:
  InstructionsCompatibilityAnalysis(DominatorTree &DT, const DataLayout &DL,
                                    const TargetTransformInfo &TTI,
                                    const TargetLibraryInfo &TLI)
      : DT(DT), DL(DL), TTI(TTI), TLI(TLI) {}

  InstructionsState buildInstructionsState(ArrayRef<Value *> VL,
                                           const BoUpSLP &R,
                                           bool WithProfitabilityCheck = false,
                                           bool SkipSameCodeCheck = false) {
    InstructionsState S = (SkipSameCodeCheck || !allSameBlock(VL))
                              ? InstructionsState::invalid()
                              : getSameOpcode(VL, TLI);
    // Check if series of selects + zext i1 %x to in can be combined into
    // selects + select %x, i32 1, i32 0.
    Instruction *SelectOp = nullptr;
    if (!S && allSameBlock(VL) && all_of(VL, [&](Value *V) {
          if (match(V, m_Select(m_Value(), m_Value(), m_Value()))) {
            if (!SelectOp)
              SelectOp = cast<Instruction>(V);
            return true;
          }
          auto *ZExt = dyn_cast<ZExtInst>(V);
          return (ZExt && ZExt->getSrcTy()->isIntegerTy(1)) ||
                 isa<PoisonValue>(V);
        })) {
      if (SelectOp)
        return InstructionsState(SelectOp, SelectOp);
    }
    // The undef lanes among the loads are the copyable elements, covered by a
    // single wide load.
    if (!S && R.Opts.slp_copyable_elements &&
        all_of(VL, IsaPred<LoadInst, UndefValue>) && any_of(VL, [](Value *V) {
          return isa<UndefValue>(V) && !isa<PoisonValue>(V);
        })) {
      SmallVector<Value *> Loads(make_isa_range<LoadInst>(VL));
      if (Loads.size() > 1 && allSameBlock(Loads)) {
        auto *LI = cast<LoadInst>(Loads.front());
        return InstructionsState(LI, LI, /*HasCopyables=*/true);
      }
    }
    if (S && S.isAltShuffle()) {
      Type *ScalarTy = S.getMainOp()->getType();
      auto *VecTy = cast<VectorType>(getWidenedType(ScalarTy, VL.size()));
      unsigned Opcode0 = S.getOpcode();
      unsigned Opcode1 = S.getAltOpcode();
      SmallBitVector OpcodeMask(
          getAltInstrMask(VL, ScalarTy, Opcode0, Opcode1));
      // If this pattern is supported by the target then we consider the order.
      if (TTI.isLegalAltInstr(VecTy, Opcode0, Opcode1, OpcodeMask))
        return S;
    } else if (S &&
               (!R.Opts.slp_copyable_elements ||
                !isSupportedMainOp(S.getMainOp()) ||
                all_of(make_isa_range<Instruction>(VL), [&](Instruction *I) {
                  return I->getOpcode() == S.getOpcode() ||
                         (S.getOpcode() == Instruction::Add &&
                          I->getOpcode() == Instruction::Shl);
                }))) {
      return S;
    }
    if (!R.Opts.slp_copyable_elements)
      return S;
    AbsorbCopyableFMulOrFAdds = hasOnlyAbsorbableCopyableFMulOrFAdds(VL);
    findAndSetMainInstruction(VL, R);
    if (!MainOp)
      return S;
    InstructionsState OrigS = S;
    S = InstructionsState(MainOp, MainOp, /*HasCopyables=*/true);
    // Cast nodes support only matching lanes from the main op block and
    // copyable (round-trippable constant) lanes.
    if (isa<CastInst>(MainOp) && any_of(VL, [&](Value *V) {
          auto *I = dyn_cast<Instruction>(V);
          return !isa<PoisonValue>(V) &&
                 !(I && I->getOpcode() == MainOpcode &&
                   I->getParent() == MainOp->getParent()) &&
                 !S.isCopyableElement(V);
        }))
      return OrigS;
    if (OrigS && !isCopyablePreferable(VL, R, OrigS, S))
      return OrigS;
    if (!WithProfitabilityCheck)
      return S;
    // ExtractElement copyable nodes reuse the source vector and insert the
    // copyable lanes; the binary-operator operand heuristics below do not
    // apply, so defer profitability to the full tree cost.
    if (isa<ExtractElementInst>(MainOp)) {
      // A load as a copyable lane would be pulled out of the consecutive-load
      // vectorization; keep the original state so the node can be split.
      if (any_of(VL, [&](Value *V) {
            return S.isCopyableElement(V) && isa<LoadInst>(V);
          }))
        return OrigS;
      return S;
    }
    // Check if it is profitable to vectorize the instruction.
    unsigned CopyableNum =
        count_if(VL, [&](Value *V) { return S.isCopyableElement(V); });
    // A cast copyable node just extends the sources of the matching lanes:
    // the constant lanes are free in a gather of the original values, so it
    // cannot be better unless the matching lanes are the majority and are not
    // vectorized already (the gather reuses the vector otherwise).
    if (isa<CastInst>(MainOp) &&
        (CopyableNum * 2 >= VL.size() || none_of(VL, [&](Value *V) {
           return !S.isCopyableElement(V) && !isa<PoisonValue>(V) &&
                  !R.isVectorized(V);
         })))
      return OrigS;
    // Absorb copyable single-use fmuls/fadds as fmuladd(a, b, -0.0) or
    // fmuladd(1.0, a, b) when every copyable is such a binop: the binops die
    // instead of being computed and gathered.
    if (RecurrenceDescriptor::isFMulAddIntrinsic(MainOp) &&
        AbsorbCopyableFMulOrFAdds)
      S.setAbsorbCopyableFMulOrFAdd(true);
    SmallVector<BoUpSLP::ValueList> Operands = buildOperands(S, VL, R);
    auto CheckOperand = [&](ArrayRef<Value *> Ops) {
      if (allConstant(Ops) || isSplat(Ops))
        return true;
      // Non-instruction operands of a call (args, constants) are always a
      // trivial gather, same as the constant/splat cases above.
      if (MainOpcode == Instruction::Call && none_of(Ops, IsaPred<Instruction>))
        return true;
      // Check if it is "almost" splat, i.e. has >= 4 elements and only single
      // one is different.
      constexpr unsigned Limit = 4;
      if (Operands.front().size() >= Limit) {
        SmallDenseMap<const Value *, unsigned> Counters;
        auto IsNotUndef = [](Value *V) { return !isa<UndefValue>(V); };
        for (Value *V : make_filter_range(Ops, IsNotUndef))
          ++Counters[V];
        if (Counters.size() == 2 &&
            any_of(Counters, [&](const auto &C) { return C.second == 1; }))
          return true;
      }
      // First operand not a constant or splat? Last attempt - check for
      // potential vectorization.
      InstructionsCompatibilityAnalysis Analysis(DT, DL, TTI, TLI);
      InstructionsState OpS = Analysis.buildInstructionsState(Ops, R);
      if (!OpS || (OpS.getOpcode() == Instruction::PHI && !allSameBlock(Ops)))
        return false;
      unsigned CopyableNum =
          count_if(Ops, [&](Value *V) { return OpS.isCopyableElement(V); });
      return CopyableNum <= VL.size() / 2;
    };
    // A copyable GEP node is a vector GEP over the base pointers of the
    // matching lanes and the values of the copyable lanes. It is profitable
    // only if that base vector is cheap (a splat, constants or vectorizable),
    // otherwise it is a gather not cheaper than the gather of the pointers.
    if (MainOpcode == Instruction::GetElementPtr &&
        !CheckOperand(Operands.front()))
      return OrigS;
    auto BuildCandidates =
        [](SmallVectorImpl<std::pair<Value *, Value *>> &Candidates, Value *V1,
           Value *V2) {
          if (V1 != V2 && isa<PHINode>(V1))
            return;
          auto *I1 = dyn_cast<Instruction>(V1);
          auto *I2 = dyn_cast<Instruction>(V2);
          if (I1 && I2 && I1->getOpcode() == I2->getOpcode() &&
              I1->getParent() != I2->getParent())
            return;
          Candidates.emplace_back(V1, (I1 || I2) ? V2 : V1);
        };
    if (VL.size() == 2) {
      // The operand-pairing heuristic below does not apply to calls, GEPs
      // and casts; defer to the full tree cost computation instead of
      // pre-rejecting here.
      if (MainOpcode == Instruction::Call ||
          MainOpcode == Instruction::GetElementPtr || isa<CastInst>(MainOp))
        return S;
      // Check if the operands allow better vectorization.
      SmallVector<std::pair<Value *, Value *>, 4> Candidates1, Candidates2;
      BuildCandidates(Candidates1, Operands[0][0], Operands[0][1]);
      BuildCandidates(Candidates2, Operands[1][0], Operands[1][1]);
      bool Res = !Candidates1.empty() && !Candidates2.empty() &&
                 R.findBestRootPair(Candidates1).first &&
                 R.findBestRootPair(Candidates2).first;
      if (!Res && isCommutative(MainOp)) {
        Candidates1.clear();
        Candidates2.clear();
        BuildCandidates(Candidates1, Operands[0][0], Operands[1][1]);
        BuildCandidates(Candidates2, Operands[1][0], Operands[0][1]);
        Res = !Candidates1.empty() && !Candidates2.empty() &&
              R.findBestRootPair(Candidates1).first &&
              R.findBestRootPair(Candidates2).first;
      }
      if (!Res)
        return OrigS;
      const TTI::TargetCostKind Kind = R.getCostKind();
      InstructionCost ScalarCost = TTI.getInstructionCost(S.getMainOp(), Kind);
      InstructionCost VectorCost;
      auto *VecTy = getWidenedType(S.getMainOp()->getType(), VL.size());
      switch (MainOpcode) {
      case Instruction::Add:
      case Instruction::Sub:
      case Instruction::Mul:
      case Instruction::AShr:
      case Instruction::LShr:
      case Instruction::Shl:
      case Instruction::SDiv:
      case Instruction::UDiv:
      case Instruction::And:
      case Instruction::Or:
      case Instruction::Xor:
      case Instruction::FAdd:
      case Instruction::FMul:
      case Instruction::FSub:
      case Instruction::FDiv:
        VectorCost = TTI.getArithmeticInstrCost(
            MainOpcode, VecTy, Kind,
            TTI::commonOperandInfo(Operands[0][0], Operands[0][1]),
            TTI::commonOperandInfo(Operands[1][0], Operands[1][1]), {},
            S.getMainOp(), &TLI);
        break;
      default:
        // Calls (min/max, fmuladd) return above before reaching this switch.
        llvm_unreachable("Unexpected instruction.");
      }
      if (VectorCost > ScalarCost)
        return OrigS;
      return S;
    }
    // Casts are the only 1-operand and fma/fmuladd are the only 3-operand
    // copyables.
    assert((Operands.size() == 2 ||
            (Operands.size() == 1 && isa<CastInst>(MainOp)) ||
            (Operands.size() == 3 && isFMAOrFMulAdd(MainOp))) &&
           "Unexpected number of operands!");
    if (CopyableNum < VL.size() / 2)
      return S;
    // Too many phi copyables - exit.
    const unsigned Limit = VL.size() / 24;
    if ((CopyableNum >= VL.size() - Limit ||
         (CopyableNum >= VL.size() - 1 && VL.size() > 4) ||
         CopyableNum >= MaxPHINumOperands) &&
        all_of(VL, [&](Value *V) {
          return isa<PHINode>(V) || !S.isCopyableElement(V);
        }))
      return OrigS;
    // Check profitability if number of copyables > VL.size() / 2.
    // 1. Reorder operands for better matching.
    if (Operands.size() == 2 && isCommutative(MainOp)) {
      Value *BestFrontOp = nullptr;
      for (auto [OpL, OpR] : zip(Operands.front(), Operands.back())) {
        // Make instructions the first operands.
        if (!isa<Instruction>(OpL) && isa<Instruction>(OpR)) {
          BestFrontOp = OpR;
          std::swap(OpL, OpR);
          continue;
        }
        // Make constants the second operands.
        if ((isa<Constant>(OpL) && !match(OpR, m_Zero())) ||
            match(OpL, m_Zero())) {
          if (isa<Instruction>(OpR))
            BestFrontOp = OpR;
          std::swap(OpL, OpR);
          continue;
        }
        if (isa<Instruction>(OpL))
          BestFrontOp = OpL;
      }
      // If some of the RHS operands better match most of LHS - swap such
      // operands to increase matching rate.
      if (auto *BestLHS = dyn_cast_if_present<Instruction>(BestFrontOp)) {
        const unsigned BestOpcode = BestLHS->getOpcode();
        for (auto [OpL, OpR] : zip(Operands.front(), Operands.back())) {
          auto *OpRI = dyn_cast<Instruction>(OpR);
          if (!OpRI)
            continue;
          if (OpRI->getOpcode() == BestOpcode)
            std::swap(OpL, OpR);
        }
      }
    }
    // 2. Check, if operands can be vectorized. Skip for fmuladd; the
    // copyable operand is checked below and may legitimately hold many
    // instructions.
    if (Operands.size() == 2 &&
        count_if(Operands.back(), IsaPred<Instruction>) > 1)
      return OrigS;
    // Check the operand holding the copyable values.
    if (!CheckOperand(Operands[S.getCopyableOpIdx()])) {
      if (Operands.size() == 2)
        return OrigS;
      // Retry with the copyable modeled as the first multiplicand.
      S.setCopyableOpIdx(0);
      Operands = buildOperands(S, VL, R);
      if (!CheckOperand(Operands[S.getCopyableOpIdx()]))
        return OrigS;
    }

    return S;
  }

  SmallVector<BoUpSLP::ValueList>
  buildOperands(const InstructionsState &S, ArrayRef<Value *> VL,
                const BoUpSLP &R, bool AllowPoisonPlaceholders = true) {
    assert(S && "Invalid state!");
    SmallVector<BoUpSLP::ValueList> Operands;
    if (S.areInstructionsWithCopyableElements()) {
      MainOp = S.getMainOp();
      MainOpcode = S.getOpcode();
      // ExtractElement copyable nodes carry a single operand (the shared
      // source vector); copyable lanes are inserted during codegen and do
      // not contribute an operand column.
      if (MainOpcode == Instruction::ExtractElement) {
        Operands.assign(1,
                        BoUpSLP::ValueList(VL.size(), MainOp->getOperand(0)));
        return Operands;
      }
      // The undef lanes of the loads have no pointer operands.
      if (MainOpcode == Instruction::Load) {
        buildOriginalOperands(S, VL, Operands);
        return Operands;
      }
      // Excludes the trailing callee operand (2 for min/max, 3 for fmuladd).
      // getNumberOfPotentiallyCommutativeOps collapses fmuladd to 2 and must
      // not be used here. Only the 2-operand case is commutative-normalized.
      auto *CI = dyn_cast<CallInst>(MainOp);
      const unsigned NumMainOpOperands =
          CI ? CI->arg_size() : MainOp->getNumOperands();
      const bool IsCommutative =
          isCommutative(MainOp) && NumMainOpOperands == 2;
      Operands.assign(NumMainOpOperands,
                      BoUpSLP::ValueList(VL.size(), nullptr));
      SmallPtrSet<const Value *, 4> SelfOpLanes = findSelfOpLanes(S, VL, R);
      const bool PoisonPlaceholders =
          AllowPoisonPlaceholders && canUsePoisonPlaceholders(S, VL);
      // Populate operands for every lane.
      for (auto [Idx, V] : enumerate(VL)) {
        SmallVector<Value *> OperandsForValue =
            getOperands(S, V, SelfOpLanes.contains(V), PoisonPlaceholders);
        for (auto [OperandIdx, Operand] : enumerate(OperandsForValue))
          Operands[OperandIdx][Idx] = Operand;
      }
      // The copyable lanes of a GEP node are gep V, 0; cast the indices of
      // the matching lanes and the zeroes to the common index type.
      if (MainOpcode == Instruction::GetElementPtr)
        buildGEPIndexOperands(
            VL, MainOp,
            [&](Value *V) {
              return isa<GetElementPtrInst>(V) && !S.isCopyableElement(V);
            },
            Operands[1]);
      // Operand-order normalization below swaps OpIdx 0 and OpIdx 1
      // of non-copyable lanes. That is only safe when the main op is
      // commutative (e.g. 0 - X is not X - 0, so `sub` must be
      // excluded). With absorbed fmul/fadd copyables the fmuladd
      // multiplicands are commutative per lane and get normalized too;
      // the 0/1 swaps never touch the addend column.
      if (IsCommutative || S.hasAbsorbedCopyableFMulOrFAdd()) {
        // IsCommutative can hold for MainOp (e.g. a Sub/FSub feeding only
        // fabs/icmp-eq-0) without every lane sharing that property, so
        // re-check the specific lane before swapping it. Absorbed fmul/fadd
        // lanes are always commutative.
        auto CanSwap = [&](Value *V) {
          if (S.hasAbsorbedCopyableFMulOrFAdd() &&
              isAbsorbableCopyableFMulOrFAdd(S, V))
            return true;
          return isCommutative(S.getMatchingMainOpOrAltOp(cast<Instruction>(V)),
                               V);
        };
        // Absorbed fmul/fadd copyables do not vote for the majority operand
        // pattern (their multiplicand order is arbitrary) but take part
        // in the swaps.
        auto SwappableLane = [&](Value *V) {
          return !isa<PoisonValue>(V) &&
                 (!S.isCopyableElement(V) ||
                  (S.hasAbsorbedCopyableFMulOrFAdd() &&
                   isAbsorbableCopyableFMulOrFAdd(S, V)));
        };
        // Count (ID0, ID1) pair frequencies for operand normalization.
        // Pairs and their inverses are tracked under a canonical key
        // so that (Load, Add) and (Add, Load) contribute to the same
        // bucket.
        struct PairInfo {
          unsigned FwdCount = 0;
          unsigned RevCount = 0;
        };
        SmallMapVector<std::pair<unsigned, unsigned>, PairInfo, 8> PairCounts;
        SmallMapVector<unsigned, unsigned, 4> AddendIDCounts;
        unsigned MajID0 = 0, MajID1 = 0;
        for (const auto &P :
             make_filter_range(enumerate(VL), [&](const auto &P) {
               return !S.isCopyableElement(P.value()) &&
                      !isa<PoisonValue>(P.value());
             })) {
          size_t Idx = P.index();
          unsigned ID0 = Operands[0][Idx]->getValueID();
          unsigned ID1 = Operands[1][Idx]->getValueID();
          if (S.hasAbsorbedCopyableFMulOrFAdd())
            ++AddendIDCounts[Operands[2][Idx]->getValueID()];
          if (ID0 == ID1)
            continue;
          unsigned MinID = std::min(ID0, ID1);
          unsigned MaxID = std::max(ID0, ID1);
          auto *It = PairCounts.try_emplace(std::make_pair(MinID, MaxID)).first;
          PairInfo &Info = It->second;
          if (ID0 < ID1)
            ++Info.FwdCount;
          else
            ++Info.RevCount;
        }
        // Find the most frequent (ID0, ID1) pair across non-copyable
        // lanes. Select the orientation (original or inverse) that
        // has more votes as the majority pattern.
        unsigned BestCount = 0;
        for (const auto &P : PairCounts) {
          const PairInfo &Info = P.second;
          unsigned Total = Info.FwdCount + Info.RevCount;
          if (Total > BestCount) {
            BestCount = Total;
            if (Info.FwdCount >= Info.RevCount) {
              MajID0 = P.first.first;
              MajID1 = P.first.second;
            } else {
              MajID0 = P.first.second;
              MajID1 = P.first.first;
            }
          }
        }
        // Absorbed fadd copyables are fmuladd(1.0, a, b): pick the
        // addend/multiplicand assignment matching the majority operand
        // kinds of the non-copyable lanes in the multiplicand (1) and
        // addend (2) columns.
        if (S.hasAbsorbedCopyableFMulOrFAdd()) {
          unsigned MajID2 = 0, Best2 = 0;
          for (const auto &P : AddendIDCounts) {
            if (P.second > Best2) {
              Best2 = P.second;
              MajID2 = P.first;
            }
          }
          for (auto [Idx, V] : enumerate(VL)) {
            auto *I = dyn_cast<Instruction>(V);
            if (!I || I->getOpcode() != Instruction::FAdd ||
                !isAbsorbableCopyableFMulOrFAdd(S, I))
              continue;
            unsigned ID1 = Operands[1][Idx]->getValueID();
            unsigned ID2 = Operands[2][Idx]->getValueID();
            unsigned Cur = (ID1 == MajID1) + (ID2 == MajID2);
            unsigned Swapped = (ID2 == MajID1) + (ID1 == MajID2);
            if (Swapped > Cur)
              std::swap(Operands[1][Idx], Operands[2][Idx]);
          }
        }
        // Normalize swappable lanes in two steps:
        // 1) Swap lanes whose operand types are the exact inverse of
        //    the majority pattern, making the non-copyable lanes
        //    consistent.
        // 2) Independently, if a strict majority of swappable lanes
        //    have loads at OpIdx 1, swap those lanes to put loads at
        //    OpIdx 0 for better downstream vectorization.
        unsigned LAt0 = 0, LAt1 = 0, TotalNC = 0;
        for (auto [Idx, V] :
             make_filter_range(enumerate(VL), [&](const auto &P) {
               return SwappableLane(P.value());
             })) {
          // Step 1: swap exact-inverse lanes.
          if (BestCount > 0) {
            unsigned ID0 = Operands[0][Idx]->getValueID();
            unsigned ID1 = Operands[1][Idx]->getValueID();
            if (ID0 == MajID1 && ID1 == MajID0 && CanSwap(V))
              std::swap(Operands[0][Idx], Operands[1][Idx]);
          }
          ++TotalNC;
          LAt0 += isa<LoadInst>(Operands[0][Idx]);
          LAt1 += isa<LoadInst>(Operands[1][Idx]);
        }
        // Step 2: if most non-copyable lanes have loads at OpIdx 1,
        // swap those lanes to put loads at OpIdx 0.
        if (TotalNC > 1 && LAt1 > LAt0 && LAt1 * 2 > TotalNC) {
          for (auto [Idx, V] :
               make_filter_range(enumerate(VL), [&](const auto &P) {
                 return SwappableLane(P.value());
               })) {
            if (!isa<LoadInst>(Operands[0][Idx]) &&
                isa<LoadInst>(Operands[1][Idx]) && CanSwap(V))
              std::swap(Operands[0][Idx], Operands[1][Idx]);
          }
        }
      }
    } else {
      buildOriginalOperands(S, VL, Operands);
    }
    return Operands;
  }
};
} // namespace

void BoUpSLP::tryToVectorizeSplatGatheredScalars() {
  unsigned PrevTreeSize = VectorizableTree.size();
  auto LoadsSubkey = [](size_t /*Key*/, LoadInst *LI) {
    return hash_value(getUnderlyingObject(LI->getPointerOperand()));
  };
  // The key includes the value type: the opcode-based key does not always
  // distinguish types (e.g. all extractvalue instructions share one key),
  // while the tree requires same-typed scalars.
  SmallMapVector<std::tuple<size_t, size_t, Type *>, SmallSetVector<Value *, 4>,
                 4>
      Groups;
  // Only gathers with vectorized (non-gather) users can reuse the broadcast.
  for (const std::unique_ptr<TreeEntry> &TE : make_filter_range(
           VectorizableTree, [&](const std::unique_ptr<TreeEntry> &TE) {
             return TE->isGather() && TE->UserTreeIndex &&
                    !TE->UserTreeIndex.UserTE->isGather() &&
                    isSplat(TE->Scalars);
           })) {
    auto *I = dyn_cast<Instruction>(TE->Scalars.front());
    // Skip shuffle-like instructions: their splat gathers are already emitted
    // as cheap shuffles of the source vector.
    if (!I ||
        isa<ExtractElementInst, InsertElementInst, ShuffleVectorInst>(I) ||
        I->getType()->isVoidTy() || isVectorized(I) || isDeleted(I) ||
        (UserIgnoreList && UserIgnoreList->contains(I)))
      continue;
    // Scheduling new memory bundles in a to-be-versioned tree records extra
    // alias-check pairs and can push the region over the versioning limits.
    if (isTryingRuntimeAliasChecks() && I->mayReadOrWriteMemory())
      continue;
    auto [Key, SubKey] =
        generateKeySubkey(I, TLI, LoadsSubkey, /*AllowAlternate=*/true);
    Groups[std::make_tuple(Key, SubKey, I->getType())].insert(I);
  }
  // Values left in singleton groups cannot form a bundle on their own;
  // regroup them by the opcode-insensitive key so alternate/copyable
  // bundles still form.
  SmallMapVector<std::pair<size_t, Type *>, SmallSetVector<Value *, 4>, 4>
      FallbackGroups;
  for (auto &[Key, Group] : make_filter_range(
           Groups, [](const auto &P) { return P.second.size() < 2; })) {
    FallbackGroups[std::make_pair(std::get<0>(Key), Group.front()->getType())]
        .insert(Group.front());
  }
  InstructionsCompatibilityAnalysis Analysis(*DT, *DL, *TTI, *TLI);
  auto BuildSubtree = [&](const auto &GroupMap) {
    auto IsMultiElement = [](const auto &P) { return P.second.size() >= 2; };
    for (const auto &Entry : make_filter_range(GroupMap, IsMultiElement)) {
      const auto &Group = Entry.second;
      // Copyable-aware check so bundles with copyable lanes are not skipped.
      if (!Analysis.buildInstructionsState(Group.getArrayRef(), *this))
        continue;
      unsigned PrevSize = VectorizableTree.size();
      buildTreeRec(Group.getArrayRef(), 0, EdgeInfo());
      if (PrevSize == VectorizableTree.size())
        continue;
      TreeEntry *NewRoot = VectorizableTree[PrevSize].get();
      if (NewRoot->isGather()) {
        // Failed to vectorize the bundle: drop the added gather entry, it has
        // no users and only adds cost.
        for (Value *V : NewRoot->Scalars) {
          auto It = ValueToGatherNodes.find(V);
          if (It != ValueToGatherNodes.end())
            It->second.remove(NewRoot);
        }
        LoadEntriesToVectorize.remove(PrevSize);
        VectorizableTree.pop_back();
        continue;
      }
      // The root has no users, the gathers reuse its lanes by value: keep the
      // loads in memory order instead of permuting them into the group order.
      if (NewRoot->State == TreeEntry::Vectorize &&
          NewRoot->getOpcode() == Instruction::Load)
        NewRoot->ReorderIndices.clear();
      SplatGatheredScalarsRoots.push_back(NewRoot);
    }
  };
  BuildSubtree(Groups);
  BuildSubtree(FallbackGroups);
  NumCanonicalSplatSubtreeEntries = VectorizableTree.size() - PrevTreeSize;
}

BoUpSLP::ScalarsVectorizationLegality
BoUpSLP::getScalarsVectorizationLegality(ArrayRef<Value *> VL, unsigned Depth,
                                         const EdgeInfo &UserTreeIdx) const {
  assert((allConstant(VL) || allSameType(VL)) && "Invalid types!");

  InstructionsCompatibilityAnalysis Analysis(*DT, *DL, *TTI, *TLI);
  InstructionsState S = Analysis.buildInstructionsState(
      VL, *this, /*WithProfitabilityCheck=*/true);

  bool AreScatterAllGEPSameBlock = false;
  if (!S) {
    SmallVector<unsigned> SortedIndices;
    BasicBlock *BB = nullptr;
    bool IsScatterVectorizeUserTE =
        UserTreeIdx.UserTE &&
        UserTreeIdx.UserTE->State == TreeEntry::ScatterVectorize;
    AreScatterAllGEPSameBlock =
        (IsScatterVectorizeUserTE && VL.front()->getType()->isPointerTy() &&
         VL.size() > 2 &&
         all_of(VL,
                [&BB](Value *V) {
                  auto *I = dyn_cast<GetElementPtrInst>(V);
                  if (!I)
                    return doesNotNeedToBeScheduled(V);
                  if (!BB)
                    BB = I->getParent();
                  return BB == I->getParent() && I->getNumOperands() == 2;
                }) &&
         BB &&
         sortPtrAccesses(VL, UserTreeIdx.UserTE->getMainOp()->getType(), *DL,
                         *SE, SortedIndices));
    if (!AreScatterAllGEPSameBlock) {
      LLVM_DEBUG(dbgs() << "SLP: Try split and if failed, gathering due to "
                           "C,S,B,O, small shuffle. \n";
                 dbgs() << "[";
                 interleaveComma(VL, dbgs(), [&](Value *V) { dbgs() << *V; });
                 dbgs() << "]\n");
      return ScalarsVectorizationLegality(S, /*IsLegal=*/false,
                                          /*TryToFindDuplicates=*/true,
                                          /*TrySplitVectorize=*/true);
    }
    // Reset S to make it GetElementPtr kind of node.
    const auto *It = find_if(VL, IsaPred<GetElementPtrInst>);
    assert(It != VL.end() && "Expected at least one GEP.");
    S = getSameOpcode(*It, *TLI);
  }
  assert(S && "Must be valid.");

  // Gather very wide PHI bundles. Wide PHIs (e.g. produced by
  // jump threading) are not profitable to vectorize and make this analysis
  // explode, so gather them to keep the compile time bounded.
  if (S.getOpcode() == Instruction::PHI) {
    unsigned NumIncomingValues =
        cast<PHINode>(S.getMainOp())->getNumIncomingValues();
    if (static_cast<uint64_t>(VL.size()) * NumIncomingValues >
        Opts.slp_phi_vectorization_budget) {
      LLVM_DEBUG(dbgs() << "SLP: Gathering due to wide PHI operand fan-out ("
                        << VL.size() << " lanes x " << NumIncomingValues
                        << " incoming values).\n");
      return ScalarsVectorizationLegality(S, /*IsLegal=*/false);
    }
  }

  // Don't handle vectors.
  if (!Opts.slp_revec &&
      getValueType(VL.front(), Opts.slp_revec)->isVectorTy()) {
    LLVM_DEBUG(dbgs() << "SLP: Gathering due to vector type.\n");
    // Do not try to pack to avoid extra instructions here.
    return ScalarsVectorizationLegality(S, /*IsLegal=*/false,
                                        /*TryToFindDuplicates=*/false);
  }

  // Check that all of the users of the scalars that we want to vectorize are
  // schedulable.
  BasicBlock *BB = S.getMainOp()->getParent();

  if (BB->isEHPad() || isa<UnreachableInst>(BB->getTerminator()) ||
      !DT->isReachableFromEntry(BB)) {
    // Don't go into unreachable blocks. They may contain instructions with
    // dependency cycles which confuse the final scheduling.
    // Do not vectorize EH and non-returning blocks, not profitable in most
    // cases.
    LLVM_DEBUG(dbgs() << "SLP: bundle in unreachable block.\n");
    return ScalarsVectorizationLegality(S, /*IsLegal=*/false);
  }

  // Don't go into catchswitch blocks, which can happen with PHIs.
  // Such blocks can only have PHIs and the catchswitch.  There is no
  // place to insert a shuffle if we need to, so just avoid that issue.
  if (isa<CatchSwitchInst>(BB->getTerminator())) {
    LLVM_DEBUG(dbgs() << "SLP: bundle in catchswitch block.\n");
    // Do not try to pack to avoid extra instructions here.
    return ScalarsVectorizationLegality(S, /*IsLegal=*/false,
                                        /*TryToFindDuplicates=*/false);
  }

  // Don't handle scalable vectors
  if (S.getOpcode() == Instruction::ExtractElement &&
      isa<ScalableVectorType>(
          cast<ExtractElementInst>(S.getMainOp())->getVectorOperandType())) {
    LLVM_DEBUG(dbgs() << "SLP: Gathering due to scalable vector type.\n");
    return ScalarsVectorizationLegality(S, /*IsLegal=*/false);
  }

  // Gather if we hit the RecursionMaxDepth, unless this is a load (or z/sext of
  // a load), in which case peek through to include it in the tree, without
  // ballooning over-budget.
  if (Depth >= Opts.slp_recursion_max_depth &&
      (S.isAltShuffle() || VL.size() < 4 ||
       !(match(S.getMainOp(), m_Load(m_Value())) ||
         all_of(VL, [&S](const Value *I) {
           return match(I,
                        m_OneUse(m_ZExtOrSExt(m_OneUse(m_Load(m_Value()))))) &&
                  cast<Instruction>(I)->getOpcode() == S.getOpcode();
         })))) {
    LLVM_DEBUG(dbgs() << "SLP: Gathering due to max recursion depth.\n");
    return ScalarsVectorizationLegality(S, /*IsLegal=*/false);
  }

  // Check if this is a duplicate of another entry.
  LLVM_DEBUG(dbgs() << "SLP: \tChecking bundle: " << *S.getMainOp() << ".\n");
  // Cache invariants to avoid recomputing for every V in VL (and every E).
  const bool IsPHIWithLoop =
      S.getOpcode() == Instruction::PHI &&
      LI->getLoopFor(S.getMainOp()->getParent()) != nullptr;
  for (TreeEntry *E : getTreeEntries(S.getMainOp())) {
    if (E->isSame(VL)) {
      LLVM_DEBUG(dbgs() << "SLP: Perfect diamond merge at " << *S.getMainOp()
                        << ".\n");
      return ScalarsVectorizationLegality(S, /*IsLegal=*/false);
    }
    SmallPtrSet<Value *, 8> Values(llvm::from_range, E->Scalars);
    if (all_of(VL, [&](Value *V) {
          return isa<PoisonValue>(V) || Values.contains(V) ||
                 (IsPHIWithLoop && isa<PHINode>(V) && isVectorized(V));
        })) {
      LLVM_DEBUG(dbgs() << "SLP: Gathering due to full overlap.\n");
      return ScalarsVectorizationLegality(S, /*IsLegal=*/false);
    }
  }

  bool AreAllSameBlock = !AreScatterAllGEPSameBlock;
  bool AreAllSameInsts = AreAllSameBlock || AreScatterAllGEPSameBlock;
  if (!AreAllSameInsts || isSplat(VL) ||
      (isa<InsertElementInst, ExtractValueInst, ExtractElementInst>(
           S.getMainOp()) &&
       !all_of(VL, isVectorLikeInstWithConstOps))) {
    LLVM_DEBUG(dbgs() << "SLP: Gathering due to C,S,B,O conditions. \n";
               dbgs() << "[";
               interleaveComma(VL, dbgs(), [&](Value *V) { dbgs() << *V; });
               dbgs() << "]\n");
    return ScalarsVectorizationLegality(S, /*IsLegal=*/false);
  }

  // Don't vectorize ephemeral values.
  if (!EphValues.empty()) {
    for (Value *V : VL) {
      if (EphValues.count(V)) {
        LLVM_DEBUG(dbgs() << "SLP: The instruction (" << *V
                          << ") is ephemeral.\n");
        // Do not try to pack to avoid extra instructions here.
        return ScalarsVectorizationLegality(S, /*IsLegal=*/false,
                                            /*TryToFindDuplicates=*/false);
      }
    }
  }

  // We now know that this is a vector of instructions of the same type from
  // the same block.

  // Check that none of the instructions in the bundle are already in the tree
  // and the node may be not profitable for the vectorization as the small
  // alternate node.
  if (S.isAltShuffle()) {
    auto GetNumVectorizedExtracted = [&]() {
      APInt Extracted = APInt::getZero(VL.size());
      APInt Vectorized = APInt::getAllOnes(VL.size());
      for (auto [Idx, V] : enumerate(VL)) {
        auto *I = dyn_cast<Instruction>(V);
        if (!I || doesNotNeedToBeScheduled(I) ||
            all_of(I->operands(), [&](const Use &U) {
              return isa<ExtractElementInst>(U.get());
            }))
          continue;
        if (isVectorized(I))
          Vectorized.clearBit(Idx);
        else if (!I->hasOneUser() && !areAllUsersVectorized(I, UserIgnoreList))
          Extracted.setBit(Idx);
      }
      return std::make_pair(Vectorized, Extracted);
    };
    auto [Vectorized, Extracted] = GetNumVectorizedExtracted();
    bool PreferScalarize = !Vectorized.isAllOnes() && VL.size() == 2;
    if (!Vectorized.isAllOnes() && !PreferScalarize) {
      // Rough cost estimation, if the vector code (+ potential extracts) is
      // more profitable than the scalar + buildvector.
      Type *ScalarTy = VL.front()->getType();
      auto *VecTy = cast<VectorType>(getWidenedType(ScalarTy, VL.size()));
      InstructionCost VectorizeCostEstimate =
          getShuffleCost(*TTI, TTI::SK_PermuteTwoSrc, VecTy, CostKind) +
          getScalarizationOverhead(
              *TTI, Opts.slp_revec, ScalarTy, VecTy, Extracted,
              /*Insert=*/false, /*Extract=*/true, CostKind);
      InstructionCost ScalarizeCostEstimate = getScalarizationOverhead(
          *TTI, Opts.slp_revec, ScalarTy, VecTy, Vectorized,
          /*Insert=*/true, /*Extract=*/false, CostKind, /*ForPoisonSrc=*/false);
      PreferScalarize = VectorizeCostEstimate > ScalarizeCostEstimate;
    }
    if (PreferScalarize) {
      LLVM_DEBUG(dbgs() << "SLP: The instructions are in tree and alternate "
                           "node is not profitable.\n");
      return ScalarsVectorizationLegality(S, /*IsLegal=*/false);
    }
  }

  // The reduction nodes (stored in UserIgnoreList) also should stay scalar.
  if (UserIgnoreList && !UserIgnoreList->empty()) {
    for (Value *V : VL) {
      if (UserIgnoreList->contains(V)) {
        LLVM_DEBUG(dbgs() << "SLP: Gathering due to gathered scalar.\n");
        return ScalarsVectorizationLegality(S, /*IsLegal=*/false);
      }
    }
  }

  return ScalarsVectorizationLegality(S, /*IsLegal=*/true);
}

/// Peel associative single-use binary chains into operand columns. Peeled
/// instructions go to \p ReassocScalars; sub-operands are inserted after the
/// peeled column so real pairs stay adjacent for flag reuse.
/// Poison lanes are allowed through; a lane that is not itself a matching
/// real instruction can still be peeled as a copyable identity leaf, as
/// long as some other lane anchors the opcode.
/// Add/sub (and fadd/fsub) chains peel together: a peeled subtract keeps
/// the column sign for its first operand and flips it for the second one,
/// recorded per column in \p NegatedColumns, so subtracted leaves stay out
/// of the positive total.
static void scanAssociativeOperands(
    const InstructionsState &S, DominatorTree &DT, const DataLayout &DL,
    const TargetTransformInfo &TTI, const TargetLibraryInfo &TLI,
    const BoUpSLP &R, SmallVectorImpl<BoUpSLP::ValueList> &Operands,
    SmallBitVector &NegatedColumns, SmallVectorImpl<Value *> &ReassocScalars) {
  assert(Operands.size() == 2 && NegatedColumns.empty() &&
         "Expected the initial 2 operand columns.");
  // The subtract family flips the sign of its second operand column.
  auto IsSub = [](unsigned Opcode) {
    return Opcode == Instruction::Sub || Opcode == Instruction::FSub;
  };
  // Signs ride with the columns so the parallel lists cannot drift apart.
  struct SignedColumn {
    BoUpSLP::ValueList Col;
    bool Negated;
  };
  SmallVector<SignedColumn, 4> Columns = {
      {std::move(Operands[0]), false},
      {std::move(Operands[1]), IsSub(S.getOpcode())}};
  InstructionsCompatibilityAnalysis Analysis(DT, DL, TTI, TLI);
  // The opcode family a column may peel into: subtracts flatten as adds of
  // a negated leaf, other opcodes peel only into their own kind.
  const unsigned RootFamily = getReassocCombineOpcode(S.getOpcode());
  // A lane whose value is itself a single-use chain link; block placement
  // does not matter here (buildTreeRec re-checks that later for whatever
  // columns end up as real leaves).
  auto IsRealLane = [&](Value *V) {
    auto *I = dyn_cast<Instruction>(V);
    return I && I->hasOneUse() &&
           getReassocCombineOpcode(I->getOpcode()) == RootFamily &&
           isReassocChainLink(I);
  };
  // Builds on InstructionsCompatibilityAnalysis's own opcode matching
  // (rather than the more permissive getSameOpcode()) so a column that
  // falls back to a copyable identity leaf only ever anchors on a MainOp
  // that InstructionsCompatibilityAnalysis::isSupportedOpcode() accepts.
  auto CanPeel = [&](ArrayRef<Value *> Column) {
    InstructionsState ColS = Analysis.buildInstructionsState(Column, R);
    if (!ColS || getReassocCombineOpcode(ColS.getOpcode()) != RootFamily ||
        ColS.isAltShuffle())
      return InstructionsState::invalid();
    // Every lane must be poison, a genuine matching real lane, or (only for
    // a copyable ColS) stand in as a copyable identity leaf
    // (Opcode(V, identity) == V).
    if (!all_of(Column, [&](Value *V) {
          return isa<PoisonValue>(V) || IsRealLane(V) ||
                 (ColS.areInstructionsWithCopyableElements() &&
                  ColS.isCopyableElement(V));
        }))
      return InstructionsState::invalid();
    return ColS;
  };
  for (unsigned Idx = 0; Idx != Columns.size();) {
    InstructionsState ColS = CanPeel(Columns[Idx].Col);
    if (!ColS) {
      ++Idx;
      continue;
    }
    BoUpSLP::ValueList Column = std::move(Columns[Idx].Col);
    // The absorbing constants of the peeled lanes keep the identity as the
    // other operand: the poison operand is not frozen in the flattened node.
    SmallVector<BoUpSLP::ValueList> SubOperands = Analysis.buildOperands(
        ColS, Column, R, /*AllowPoisonPlaceholders=*/false);
    assert(SubOperands.size() == 2 && "Expected 2 operand columns.");
    // Poison and copyable lanes have no real instruction left to erase
    // later: a copyable V is used as-is, not subsumed by the flattened
    // combine.
    for (Value *V : Column)
      if (!isa<PoisonValue>(V) && !ColS.isCopyableElement(V))
        ReassocScalars.push_back(V);
    // A peeled subtract negates its second operand column.
    const bool Negated = Columns[Idx].Negated;
    Columns[Idx].Col = std::move(SubOperands.front());
    Columns.insert(
        std::next(Columns.begin(), Idx + 1),
        {std::move(SubOperands.back()), IsSub(ColS.getOpcode()) != Negated});
    // Do not advance Idx: re-examine the column that was just placed here.
  }
  Operands.clear();
  for (auto &[Col, Negated] : Columns) {
    Operands.push_back(std::move(Col));
    NegatedColumns.push_back(Negated);
  }
}

/// Realign flattened operand columns so matching value families share a
/// column across lanes. Lane 0 is canonical; other lanes match by key equality
/// only (never compare hash values). Columns sharing a key are paired by the
/// family of their first operand where available, so e.g. shifts fed by the
/// same load family land in one column instead of pairing by encounter order.
/// Values move between columns only within the same sign: a subtracted leaf
/// never lands in an added column. The sign is queried per lane and column
/// with \p IsNegated: alternate add/sub nodes negate only the non-leading
/// columns of their subtract lanes.
static SmallVector<BoUpSLP::ValueList> alignReassociatedOperandsByKey(
    ArrayRef<BoUpSLP::ValueList> Operands,
    function_ref<bool(unsigned Lane, unsigned Col)> IsNegated,
    const TargetLibraryInfo &TLI) {
  const unsigned NumCols = Operands.size();
  const unsigned NumLanes = Operands.front().size();
  auto LoadsSubkey = [](size_t /*Key*/, LoadInst *LI) {
    return hash_value(getUnderlyingObject(LI->getPointerOperand()));
  };
  auto GetKey = [&](Value *V) {
    return generateKeySubkey(V, &TLI, LoadsSubkey, /*AllowAlternate=*/false);
  };
  const std::pair<size_t, size_t> NoSecondaryKey{0, 0};
  // Family of the value's first operand; loads already carry their family in
  // the primary key.
  auto GetSecondaryKey = [&](Value *V) -> std::pair<size_t, size_t> {
    auto *I = dyn_cast<Instruction>(V);
    if (!I || isa<LoadInst>(I) || I->getNumOperands() == 0)
      return NoSecondaryKey;
    return GetKey(I->getOperand(0));
  };
  SmallVector<std::pair<size_t, size_t>> Lane0Keys = map_to_vector(
      Operands, [&](const BoUpSLP::ValueList &Col) { return GetKey(Col[0]); });
  SmallVector<std::pair<size_t, size_t>> Lane0SecondaryKeys =
      map_to_vector(Operands, [&](const BoUpSLP::ValueList &Col) {
        return GetSecondaryKey(Col[0]);
      });

  SmallVector<BoUpSLP::ValueList> Aligned(NumCols,
                                          BoUpSLP::ValueList(NumLanes));
  for (unsigned Col : seq<unsigned>(NumCols))
    Aligned[Col][0] = Operands[Col][0];

  for (unsigned Lane : seq<unsigned>(1, NumLanes)) {
    // Buckets are keyed by the value key and the column sign.
    using Key = std::pair<std::pair<size_t, size_t>, unsigned>;
    auto Sign = [&](unsigned Col) { return IsNegated(Lane, Col) ? 1U : 0U; };
    SmallDenseMap<Key, SmallVector<unsigned, 2>, 8> Buckets;
    for (unsigned Col : seq<unsigned>(NumCols))
      Buckets[{GetKey(Operands[Col][Lane]), Sign(Col)}].push_back(Col);
    SmallDenseMap<Key, unsigned, 8> NextInBucket;
    SmallVector<unsigned> SlotSrcCol(NumCols, NumCols);
    SmallBitVector ColClaimed(NumCols, false);
    for (unsigned Slot : seq<unsigned>(NumCols)) {
      const auto SlotKey = std::make_pair(Lane0Keys[Slot], Sign(Slot));
      auto BucketIt = Buckets.find(SlotKey);
      if (BucketIt == Buckets.end())
        continue;
      unsigned &Cursor = NextInBucket[SlotKey];
      if (Cursor >= BucketIt->second.size())
        continue;
      // Among the remaining same-key columns prefer the one whose operand
      // family matches lane 0's; no match keeps the bucket order.
      unsigned PickPos = Cursor;
      if (Lane0SecondaryKeys[Slot] != NoSecondaryKey)
        for (unsigned P = Cursor, E = BucketIt->second.size(); P != E; ++P)
          if (GetSecondaryKey(Operands[BucketIt->second[P]][Lane]) ==
              Lane0SecondaryKeys[Slot]) {
            PickPos = P;
            break;
          }
      std::swap(BucketIt->second[Cursor], BucketIt->second[PickPos]);
      unsigned SrcCol = BucketIt->second[Cursor++];
      SlotSrcCol[Slot] = SrcCol;
      ColClaimed[SrcCol] = true;
    }
    // Leftover slots take leftover columns of the same sign; per-lane sign
    // counts match, so every slot finds one.
    for (unsigned Slot : seq<unsigned>(NumCols)) {
      if (SlotSrcCol[Slot] != NumCols)
        continue;
      for (unsigned Col : seq<unsigned>(NumCols)) {
        if (!ColClaimed[Col] && IsNegated(Lane, Col) == IsNegated(Lane, Slot)) {
          SlotSrcCol[Slot] = Col;
          ColClaimed[Col] = true;
          break;
        }
      }
    }
    for (unsigned Slot : seq<unsigned>(NumCols))
      Aligned[Slot][Lane] = Operands[SlotSrcCol[Slot]][Lane];
  }
  return Aligned;
}

/// Rank reassociated operand layouts by vectorizable load columns, other load
/// patterns, broadcast/constant columns, then fewer unique values per column.
/// Identity columns are scored by the opcode of the emitted combines.
static std::tuple<unsigned, unsigned, unsigned, int>
getReassocColumnsQuality(ArrayRef<BoUpSLP::ValueList> Columns, const BoUpSLP &R,
                         unsigned Opcode) {
  unsigned NumConsecutiveLoadCols = 0;
  unsigned NumOtherVecLoadCols = 0;
  unsigned NumBroadcastOrConstCols = 0;
  int NumUniqueValues = 0;
  const unsigned CombineOpcode = getReassocCombineOpcode(Opcode);
  for (ArrayRef<Value *> Col : Columns) {
    if (all_of(Col, IsaPred<Constant>)) {
      ++NumBroadcastOrConstCols;
      continue;
    }
    // Identity constants are free beyond the base they are inserted into.
    SmallPtrSet<Value *, 8> UniqueValues;
    for (Value *V : Col)
      if (!isBinOpIdentityConstant(V, CombineOpcode))
        UniqueValues.insert(V);
    NumUniqueValues += UniqueValues.size();
    if (UniqueValues.size() <= 1) {
      ++NumBroadcastOrConstCols;
      continue;
    }
    if (all_of(Col, IsaPred<LoadInst>)) {
      BoUpSLP::OrdersType Order;
      SmallVector<Value *> PointerOps;
      BoUpSLP::StridedPtrInfo SPtrInfo;
      BoUpSLP::LoadsState LS =
          R.canVectorizeLoads(Col, Col.front(), Order, PointerOps, SPtrInfo);
      if (LS == BoUpSLP::LoadsState::Vectorize)
        ++NumConsecutiveLoadCols;
      else if (LS != BoUpSLP::LoadsState::Gather)
        ++NumOtherVecLoadCols;
    }
  }
  // Greater is better; negate unique count as a tie-breaker.
  return std::make_tuple(NumConsecutiveLoadCols, NumOtherVecLoadCols,
                         NumBroadcastOrConstCols, -NumUniqueValues);
}

void BoUpSLP::buildTreeRec(ArrayRef<Value *> VLRef, unsigned Depth,
                           const EdgeInfo &UserTreeIdx,
                           unsigned InterleaveFactor) {
  assert((allConstant(VLRef) || allSameType(VLRef)) && "Invalid types!");

  SmallVector<int> ReuseShuffleIndices;
  SmallVector<Value *> VL(VLRef);

  // Tries to build split node.
  auto TrySplitNode = [&](const InstructionsState &LocalState,
                          bool SplitInHalves = false) {
    SmallVector<Value *> Op1, Op2;
    OrdersType ReorderIndices;
    if (SplitInHalves) {
      auto *Mid = std::next(VL.begin(), VL.size() / 2);
      Op1.assign(VL.begin(), Mid);
      Op2.assign(Mid, VL.end());
    } else if (!canBuildSplitNode(VL, LocalState, Op1, Op2, ReorderIndices)) {
      return false;
    }

    auto Invalid = ScheduleBundle::invalid();
    auto *TE = newTreeEntry(VL, TreeEntry::SplitVectorize, Invalid, LocalState,
                            UserTreeIdx, {}, ReorderIndices);
    LLVM_DEBUG(dbgs() << "SLP: split alternate node.\n"; TE->dump());
    auto AddNode = [&](ArrayRef<Value *> Op, unsigned Idx) {
      InstructionsState S = getSameOpcode(Op, *TLI);
      if (S && (isa<LoadInst>(S.getMainOp()) ||
                getSameValuesTreeEntry(S.getMainOp(), Op, /*SameVF=*/true))) {
        // Build gather node for loads, they will be gathered later.
        TE->CombinedEntriesWithIndices.emplace_back(VectorizableTree.size(),
                                                    Idx == 0 ? 0 : Op1.size());
        (void)newTreeEntry(Op, TreeEntry::NeedToGather, Invalid, S, {TE, Idx});
      } else {
        TE->CombinedEntriesWithIndices.emplace_back(VectorizableTree.size(),
                                                    Idx == 0 ? 0 : Op1.size());
        buildTreeRec(Op, Depth, {TE, Idx});
      }
    };
    AddNode(Op1, 0);
    AddNode(Op2, 1);
    return true;
  };

  auto AreOnlyConstsWithPHIs = [](ArrayRef<Value *> VL) {
    bool AreConsts = false;
    auto IsNotPoison = [](Value *V) { return !isa<PoisonValue>(V); };
    for (Value *V : make_filter_range(VL, IsNotPoison)) {
      if (isa<Constant>(V)) {
        AreConsts = true;
        continue;
      }
      if (!isa<PHINode>(V))
        return false;
    }
    return AreConsts;
  };
  if (AreOnlyConstsWithPHIs(VL)) {
    LLVM_DEBUG(dbgs() << "SLP: Gathering due to all constants and PHIs.\n");
    newGatherTreeEntry(VL, InstructionsState::invalid(), UserTreeIdx);
    return;
  }

  ScalarsVectorizationLegality Legality =
      getScalarsVectorizationLegality(VL, Depth, UserTreeIdx);
  InstructionsState S = Legality.getInstructionsState();
  if (!Legality.isLegal()) {
    if (Legality.trySplitVectorize()) {
      auto [MainOp, AltOp] = getMainAltOpsNoStateVL(VL);
      // Last chance to try to vectorize alternate node.
      if (MainOp && AltOp && TrySplitNode(InstructionsState(MainOp, AltOp)))
        return;
    }
    if (Legality.tryToFindDuplicates())
      (void)tryToFindDuplicates(Opts, VL, ReuseShuffleIndices, *TTI, *TLI, S,
                                UserTreeIdx, *this);

    newGatherTreeEntry(VL, S, UserTreeIdx, ReuseShuffleIndices);
    return;
  }

  if (SplitStoredValues && S && UserTreeIdx.UserTE &&
      UserTreeIdx.UserTE->Idx == 0 && TrySplitNode(S, /*SplitInHalves=*/true))
    return;

  // FIXME: investigate if there are profitable cases for VL.size() <= 4.
  if (S.isAltShuffle() && TrySplitNode(S))
    return;

  // Cmp nodes with interchangeable lanes (e.g. x == 0 mixed with x <u C)
  // try the split by the original predicates, like the alternate nodes. The
  // trunc X to i1 lanes have no original predicate.
  if (S.getOpcode() == Instruction::ICmp && !S.isAltShuffle() &&
      none_of(VL, IsaPred<TruncInst>)) {
    auto SameOrSwapped = [](const ICmpInst *CI, CmpInst::Predicate P) {
      return CI->getPredicate() == P ||
             CI->getPredicate() == CmpInst::getSwappedPredicate(P);
    };
    ICmpInst *MainI = cast<ICmpInst>(*find_if(VL, IsaPred<ICmpInst>));
    auto *AltIt = find_if(VL, [&](Value *V) {
      auto *CI = dyn_cast<ICmpInst>(V);
      return CI && !SameOrSwapped(CI, MainI->getPredicate());
    });
    ICmpInst *AltI = AltIt == VL.end() ? nullptr : cast<ICmpInst>(*AltIt);
    if (AltI &&
        all_of(make_isa_range<ICmpInst>(VL),
               [&](ICmpInst *CI) {
                 return SameOrSwapped(CI, MainI->getPredicate()) ||
                        SameOrSwapped(CI, AltI->getPredicate());
               }) &&
        TrySplitNode(InstructionsState(MainI, AltI)))
      return;
  }

  // Check that every instruction appears once in this bundle.
  if (!tryToFindDuplicates(Opts, VL, ReuseShuffleIndices, *TTI, *TLI, S,
                           UserTreeIdx, *this, /*BuildGatherOnly=*/false)) {
    newGatherTreeEntry(VL, S, UserTreeIdx, ReuseShuffleIndices);
    return;
  }

  // Perform specific checks for each particular instruction kind.
  bool IsScatterVectorizeUserTE =
      UserTreeIdx.UserTE &&
      UserTreeIdx.UserTE->State == TreeEntry::ScatterVectorize;
  OrdersType CurrentOrder;
  SmallVector<Value *> PointerOps;
  StridedPtrInfo SPtrInfo;
  SmallVector<int> ExpandShuffleMask;
  TreeEntry::EntryState State = getScalarsVectorizationState(
      S, VL, IsScatterVectorizeUserTE, CurrentOrder, PointerOps, SPtrInfo,
      ExpandShuffleMask);
  // The zero-extended sub-fields of the same wider integer scalar are
  // gathered and emitted as a bitcast to the field vector plus a permutation.
  // For 2 lanes the emission is not cheaper than the insertelement chain.
  if (State == TreeEntry::NeedToGather ||
      (VL.size() > 2 && ReuseShuffleIndices.empty() &&
       matchGatheredExtractedFields(VL, *DL))) {
    newGatherTreeEntry(VL, S, UserTreeIdx, ReuseShuffleIndices);
    return;
  }

  // Check the loop nest. We need to be sure we handle a single loop nest at a
  // time to avoid incorrect cost estimation because of the loop aware cost
  // model.
  if (VectorizableTree.empty()) {
    assert(CurrentLoopNest.empty() && "Expected empty loop nest");
    // Process the first node? Initial fill of the loop nest.
    BasicBlock *Parent = S.getMainOp()->getParent();
    if (const Loop *L = LI->getLoopFor(Parent)) {
      L = findInnermostNonInvariantLoop(L, VL);
      if (L)
        CurrentLoopNest.assign(getLoopNest(L));
    }
  } else if (!UserTreeIdx ||
             UserTreeIdx.UserTE->State == TreeEntry::SplitVectorize ||
             UserTreeIdx.UserTE->isGather() ||
             UserTreeIdx.UserTE->getMainOp()->getParent() !=
                 S.getMainOp()->getParent()) {
    BasicBlock *Parent = S.getMainOp()->getParent();
    if (const Loop *L = LI->getLoopFor(Parent)) {
      // Check that the new loop nest shares the same outer structure as the
      // tree's current loop nest. Completely disjoint nests (different
      // outermost loops) are forced to gather because their scales cannot be
      // meaningfully combined. Sibling inner loops (inside a common outer
      // loop or outside any loops at all) are allowed: the cost model scales
      // each entry by its own loop via getScaleToLoopIterations(), so a tree
      // that spans sibling inner loops (e.g. a PHI at their merge block) can
      // still be costed correctly. Contract CurrentLoopNest to the longest
      // common prefix with the new entry's nest so subsequent entries in yet
      // another sibling can also be admitted.
      L = findInnermostNonInvariantLoop(L, VL);
      if (L) {
        SmallVector<const Loop *> NewLoopNest(getLoopNest(L));
        unsigned CommonLen = 0;
        for (const auto [L1, L2] : zip(CurrentLoopNest, NewLoopNest)) {
          if (L1 != L2)
            break;
          ++CommonLen;
        }
        auto ValidateMergedBTCs = [&](unsigned StartDepth) -> bool {
          unsigned EndDepth =
              std::min<unsigned>(NewLoopNest.size(), MergedLoopBTCs.size());
          for (unsigned D = StartDepth; D < EndDepth; ++D) {
            const SCEV *Constraint = MergedLoopBTCs[D];
            if (!Constraint)
              continue;
            const SCEV *NewBTC = SE->getBackedgeTakenCount(NewLoopNest[D]);
            if (isa<SCEVCouldNotCompute>(NewBTC) || NewBTC != Constraint)
              return false;
          }
          return true;
        };
        auto BailOutToGather = [&]() {
          LLVM_DEBUG(dbgs()
                     << "SLP: Sibling loops have different trip counts.\n");
          newGatherTreeEntry(VL, S, UserTreeIdx, ReuseShuffleIndices);
        };
        if (CurrentLoopNest.empty()) {
          if (!ValidateMergedBTCs(0)) {
            BailOutToGather();
            return;
          }
          CurrentLoopNest.assign(NewLoopNest);
        } else if (CommonLen < CurrentLoopNest.size() &&
                   CommonLen < NewLoopNest.size()) {
          // Divergence below the common prefix: the tree now spans sibling
          // loops at depth CommonLen. Admitting them into one tree makes
          // the profitability decision JOINT across both siblings, so a
          // very hot sibling could otherwise let an unprofitable cold
          // sibling ride along "for free" (per-entry scaling of the cold
          // sibling's entries would be dwarfed by the hot one). Require
          // SCEV-proven equal backedge-taken counts for the diverging
          // siblings before joining; otherwise force gather.
          const Loop *SibA = CurrentLoopNest[CommonLen];
          const Loop *SibB = NewLoopNest[CommonLen];
          const SCEV *BecA = SE->getBackedgeTakenCount(SibA);
          const SCEV *BecB = SE->getBackedgeTakenCount(SibB);
          if (isa<SCEVCouldNotCompute>(BecA) || BecA != BecB) {
            BailOutToGather();
            return;
          }
          if (!ValidateMergedBTCs(CommonLen + 1)) {
            BailOutToGather();
            return;
          }
          if (MergedLoopBTCs.size() <= CommonLen)
            MergedLoopBTCs.resize(CommonLen + 1, nullptr);
          MergedLoopBTCs[CommonLen] = BecA;
          CurrentLoopNest.truncate(CommonLen);
        } else if (NewLoopNest.size() > CurrentLoopNest.size()) {
          if (!ValidateMergedBTCs(CurrentLoopNest.size())) {
            BailOutToGather();
            return;
          }
          CurrentLoopNest.append(
              std::next(NewLoopNest.begin(), CurrentLoopNest.size()),
              NewLoopNest.end());
        }
        // Otherwise NewLoopNest is a prefix of CurrentLoopNest: keep as-is.
      }
    }
  }

  Instruction *VL0 = S.getMainOp();
  BasicBlock *BB = VL0->getParent();
  auto &BSRef = BlocksSchedules[BB];
  if (!BSRef)
    BSRef = std::make_unique<BlockScheduling>(BB, Opts.slp_schedule_budget);

  BlockScheduling &BS = *BSRef;

  SetVector<Value *> UniqueValues(llvm::from_range, VL);
  std::optional<ScheduleBundle *> BundlePtr =
      BS.tryScheduleBundle(UniqueValues.getArrayRef(), this, S, UserTreeIdx);
#ifdef EXPENSIVE_CHECKS
  // Make sure we didn't break any internal invariants
  BS.verify();
#endif
  if (!BundlePtr || (*BundlePtr && !*BundlePtr.value())) {
    LLVM_DEBUG(dbgs() << "SLP: We are not able to schedule this bundle!\n");
    // Last chance to try to vectorize alternate node.
    if (S.isAltShuffle() && ReuseShuffleIndices.empty() && TrySplitNode(S))
      return;
    // Last chance to try to vectorize copyable node.
    if (S.areInstructionsWithCopyableElements() &&
        ReuseShuffleIndices.empty()) {
      InstructionsState AltS = getSameOpcode(VL, *TLI);
      if (AltS && AltS.isAltShuffle() && TrySplitNode(AltS))
        return;
    }
    newGatherTreeEntry(VL, S, UserTreeIdx, ReuseShuffleIndices);
    NonScheduledFirst.insert(VL.front());
    if (S.getOpcode() == Instruction::Load &&
        BS.ScheduleRegionSize < BS.ScheduleRegionSizeLimit)
      registerNonVectorizableLoads(ArrayRef(VL));
    return;
  }
  InstructionsCompatibilityAnalysis Analysis(*DT, *DL, *TTI, *TLI);
  SmallVector<ValueList> Operands = Analysis.buildOperands(S, VL, *this);
  // Flatten associative binary chains into operand columns. Only the peeled
  // chain links are required to be single-use (they are erased); the root
  // being flattened may have other uses. Skip lanes that are neither chain
  // links nor copyable identity leaves. Alternate nodes flatten too, but
  // each lane keeps its own opcode on every combine level. Restricted to
  // BinaryOperator: isAssociative() is also true for associative intrinsics
  // (e.g. smax/smin/umax/umin), which are CallInst, not BinaryOperator, and
  // are not supported by the copyable-identity machinery used below
  // (ConstantExpr::getBinOpIdentity, isSupportedOpcode,
  // isBinOpIdentityConstant).
  SmallVector<Value *> ReassocScalars;
  // Sign of each flattened operand column (a subtracted leaf is negated).
  SmallBitVector NegatedColumns;
  // Per-lane subtract markers for flattened alternate nodes.
  SmallBitVector SubLanes;
  // Cached below (when the peel is kept) so the reorder step further down
  // does not need to redo the aligning/scoring work.
  SmallVector<ValueList> ReassocAlignedOperands;
  // Snapshot of the pre-flatten operand columns, used by both revert points.
  SmallVector<ValueList> NaturalTwoColumns;
  std::tuple<unsigned, unsigned, unsigned, int> ReassocPeeledQuality;
  if (Opts.slp_reassociate_ops && Operands.size() == 2 &&
      all_of(VL, [&](Value *V) {
        if (!S.isAltShuffle() && S.isCopyableElement(V))
          return true;
        auto *I = dyn_cast<BinaryOperator>(V);
        return I && isReassocChainLink(I);
      })) {
    NaturalTwoColumns = Operands;
    if (S.isAltShuffle()) {
      if (SmallVector<SmallVector<Value *>> Flattened =
              scanAltAssociativeOperands(S, *TLI, VL, Operands[0], Operands[1],
                                         ReassocScalars, SubLanes);
          !Flattened.empty()) {
        Operands.clear();
        for (auto &Col : Flattened)
          Operands.emplace_back(std::move(Col));
      }
    } else {
      scanAssociativeOperands(S, *DT, *DL, *TTI, *TLI, *this, Operands,
                              NegatedColumns, ReassocScalars);
    }
    // Drop flattening unless realigning improves load or broadcast column
    // structure; an unimproved peel ties and reverts to natural columns.
    if (!ReassocScalars.empty()) {
      auto IsNegated = [&](unsigned Lane, unsigned Col) {
        return S.isAltShuffle() ? Col > 0 && SubLanes.test(Lane)
                                : NegatedColumns.test(Col);
      };
      ReassocAlignedOperands =
          alignReassociatedOperandsByKey(Operands, IsNegated, *TLI);
      // Alternate nodes compare against the natural two-column form rather
      // than the raw peel: the natural form pays one lane-select shuffle per
      // level, so the flatten is worth keeping whenever the realigned
      // columns improve on the natural ones.
      ReassocPeeledQuality = getReassocColumnsQuality(
          S.isAltShuffle() ? NaturalTwoColumns : Operands, *this,
          S.getOpcode());
      // The unique-value count (4th field) is only a tie-break for the
      // later reorder-or-not decision, not for this one.
      auto DropUniqueCount = [](const auto &Quality) {
        return std::make_tuple(std::get<0>(Quality), std::get<1>(Quality),
                               std::get<2>(Quality));
      };
      if (DropUniqueCount(getReassocColumnsQuality(ReassocAlignedOperands,
                                                   *this, S.getOpcode())) <=
          DropUniqueCount(ReassocPeeledQuality)) {
        Operands = std::move(NaturalTwoColumns);
        ReassocScalars.clear();
      }
    }
  }
  // Registers peeled chain links on the node so they are erased with it and
  // their scheduling deps are released as reassociated operands.
  auto RegisterReassocScalars = [&](TreeEntry *TE) {
    for (Value *V : ReassocScalars) {
      TE->addReassocScalar(V);
      SmallVectorImpl<const TreeEntry *> &Owners =
          ReassocScalarToTreeEntries.try_emplace(V).first->second;
      if (!is_contained(Owners, TE))
        Owners.push_back(TE);
    }
  };
  // A value routed into several columns is consumed by several combines;
  // that distorts both the cost and the vector structure (duplicated loads,
  // partial masked columns), so prefer the natural two-column shape.
  auto HasDupColumnValues = [&]() {
    SmallPtrSet<const Value *, 16> ColumnValues;
    return any_of(Operands, [&](const ValueList &Col) {
      return any_of(Col, [&](const Value *V) {
        return !isa<Constant>(V) && !ColumnValues.insert(V).second;
      });
    });
  };
  ScheduleBundle Empty;
  ScheduleBundle &Bundle = BundlePtr.value() ? *BundlePtr.value() : Empty;
  LLVM_DEBUG(dbgs() << "SLP: We are able to schedule this bundle.\n");

  unsigned ShuffleOrOp =
      S.isAltShuffle() ? (unsigned)Instruction::ShuffleVector : S.getOpcode();
  auto CreateOperandNodes = [&](TreeEntry *TE, const auto &Operands) {
    // Postpone PHI nodes creation
    SmallVector<unsigned> PHIOps;
    for (unsigned I : seq<unsigned>(Operands.size())) {
      ArrayRef<Value *> Op = Operands[I];
      if (Op.empty())
        continue;
      InstructionsState S = getSameOpcode(Op, *TLI);
      if ((!S || S.getOpcode() != Instruction::PHI) || S.isAltShuffle())
        buildTreeRec(Op, Depth + 1, {TE, I});
      else
        PHIOps.push_back(I);
    }
    for (unsigned I : PHIOps)
      buildTreeRec(Operands[I], Depth + 1, {TE, I});
  };
  switch (ShuffleOrOp) {
    case Instruction::PHI: {
      TreeEntry *TE =
          newTreeEntry(VL, Bundle, S, UserTreeIdx, ReuseShuffleIndices);
      LLVM_DEBUG(dbgs() << "SLP: added a new TreeEntry (PHINode).\n";
                 TE->dump());

      TE->setOperands(Operands);
      CreateOperandNodes(TE, Operands);
      return;
    }
    case Instruction::ExtractValue:
    case Instruction::ExtractElement: {
      if (CurrentOrder.empty()) {
        LLVM_DEBUG(dbgs() << "SLP: Reusing or shuffling extract sequence.\n");
      } else {
        LLVM_DEBUG({
          dbgs() << "SLP: Reusing or shuffling of reordered extract sequence "
                    "with order";
          for (unsigned Idx : CurrentOrder)
            dbgs() << " " << Idx;
          dbgs() << "\n";
        });
        fixupOrderingIndices(CurrentOrder);
      }
      // Insert new order with initial value 0, if it does not exist,
      // otherwise return the iterator to the existing one.
      TreeEntry *TE = newTreeEntry(VL, Bundle /*vectorized*/, S, UserTreeIdx,
                                   ReuseShuffleIndices, CurrentOrder);
      LLVM_DEBUG(dbgs() << "SLP: added a new TreeEntry "
                           "(ExtractValueInst/ExtractElementInst).\n";
                 TE->dump());
      // This is a special case, as it does not gather, but at the same time
      // we are not extending buildTreeRec() towards the operands.
      TE->setOperands(Operands);
      if (ShuffleOrOp == Instruction::ExtractValue) {
        SmallVector<unsigned> Indices;
        SmallVector<Value *> Calls;
        if (checkEVsForVecCalls(VL, S, *TLI, Indices, Calls)) {
          TE->StructEVIndices = std::move(Indices);
          buildTreeRec(Operands.front(), Depth + 1, {TE, 0});
        }
      }
      return;
    }
    case Instruction::InsertValue:
    case Instruction::InsertElement: {
      assert(ReuseShuffleIndices.empty() && "All inserts should be unique");

      auto OrdCompare = [](const std::pair<int, int> &P1,
                           const std::pair<int, int> &P2) {
        return P1.first > P2.first;
      };
      PriorityQueue<std::pair<int, int>, SmallVector<std::pair<int, int>>,
                    decltype(OrdCompare)>
          Indices(OrdCompare);
      for (int I = 0, E = VL.size(); I < E; ++I) {
        unsigned Idx = *getElementIndex(VL[I]);
        Indices.emplace(Idx, I);
      }
      OrdersType CurrentOrder(VL.size(), VL.size());
      bool IsIdentity = true;
      for (int I = 0, E = VL.size(); I < E; ++I) {
        CurrentOrder[Indices.top().second] = I;
        IsIdentity &= Indices.top().second == I;
        Indices.pop();
      }
      if (IsIdentity)
        CurrentOrder.clear();
      TreeEntry *TE = newTreeEntry(VL, Bundle /*vectorized*/, S, UserTreeIdx,
                                   {}, CurrentOrder);
      LLVM_DEBUG(dbgs() << "SLP: added a new TreeEntry (InsertElementInst).\n";
                 TE->dump());

      TE->setOperands(Operands);
      buildTreeRec(TE->getOperand(1), Depth + 1, {TE, 1});
      return;
    }
    case Instruction::Load: {
      // Check that a vectorized load would load the same memory as a scalar
      // load. For example, we don't want to vectorize loads that are smaller
      // than 8-bit. Even though we have a packed struct {<i2, i2, i2, i2>} LLVM
      // treats loading/storing it as an i8 struct. If we vectorize loads/stores
      // from such a struct, we read/write packed bits disagreeing with the
      // unvectorized version.
      TreeEntry *TE = nullptr;
      fixupOrderingIndices(CurrentOrder);
      switch (State) {
      case TreeEntry::Vectorize:
        TE = newTreeEntry(VL, Bundle /*vectorized*/, S, UserTreeIdx,
                          ReuseShuffleIndices, CurrentOrder, InterleaveFactor);
        if (CurrentOrder.empty())
          LLVM_DEBUG(dbgs() << "SLP: added a new TreeEntry (LoadInst).\n";
                     TE->dump());
        else
          LLVM_DEBUG(dbgs()
                         << "SLP: added a new TreeEntry (jumbled LoadInst).\n";
                     TE->dump());
        break;
      case TreeEntry::CompressVectorize:
        // Vectorizing non-consecutive loads with (masked)load + compress.
        TE = newTreeEntry(VL, TreeEntry::CompressVectorize, Bundle, S,
                          UserTreeIdx, ReuseShuffleIndices, CurrentOrder);
        LLVM_DEBUG(
            dbgs()
                << "SLP: added a new TreeEntry (masked LoadInst + compress).\n";
            TE->dump());
        break;
      case TreeEntry::StridedVectorize:
        // Vectorizing non-consecutive loads with `llvm.masked.gather`.
        TE = newTreeEntry(VL, TreeEntry::StridedVectorize, Bundle, S,
                          UserTreeIdx, ReuseShuffleIndices, CurrentOrder);
        TreeEntryToStridedPtrInfoMap[TE] = SPtrInfo;
        LLVM_DEBUG(dbgs() << "SLP: added a new TreeEntry (strided LoadInst).\n";
                   TE->dump());
        break;
      case TreeEntry::ScatterVectorize:
        // Vectorizing non-consecutive loads with `llvm.masked.gather`.
        TE = newTreeEntry(VL, TreeEntry::ScatterVectorize, Bundle, S,
                          UserTreeIdx, ReuseShuffleIndices);
        LLVM_DEBUG(
            dbgs()
                << "SLP: added a new TreeEntry (non-consecutive LoadInst).\n";
            TE->dump());
        break;
      case TreeEntry::BlendedLoadVectorize: {
        // Two masked loads from the candidate bases, blended by the per-lane
        // select conditions. The conditions are added as the operand node, so
        // the blend mask is vectorized through the tree.
        TE = newTreeEntry(VL, TreeEntry::BlendedLoadVectorize, Bundle, S,
                          UserTreeIdx, ReuseShuffleIndices);
        LLVM_DEBUG(dbgs() << "SLP: added a new TreeEntry (blended LoadInst).\n";
                   TE->dump());
        Value *TrueBase = nullptr;
        Value *FalseBase = nullptr;
        SmallVector<Value *> Conditions;
        [[maybe_unused]] bool Found = isSelectedBaseLoad(
            VL0->getType(), PointerOps, *DL, TrueBase, FalseBase, Conditions);
        assert(Found && "Expected a valid blended-load pattern.");
        Operands.assign(1, ValueList(Conditions.begin(), Conditions.end()));
        TE->setOperands(Operands);
        buildTreeRec(TE->getOperand(0), Depth + 1, {TE, 0});
        return;
      }
      case TreeEntry::ExpandVectorize:
      case TreeEntry::CombinedVectorize:
      case TreeEntry::SplitVectorize:
      case TreeEntry::NeedToGather:
        llvm_unreachable("Unexpected loads state.");
      }
      if (!CurrentOrder.empty() && State != TreeEntry::ScatterVectorize) {
        assert(Operands.size() == 1 && "Expected a single operand only");
        SmallVector<int> Mask;
        inversePermutation(CurrentOrder, Mask);
        reorderScalars(Operands.front(), Mask);
      }
      TE->setOperands(Operands);
      if (State == TreeEntry::ScatterVectorize)
        buildTreeRec(PointerOps, Depth + 1, {TE, 0});
      return;
    }
    case Instruction::ZExt:
    case Instruction::SExt:
    case Instruction::FPToUI:
    case Instruction::FPToSI:
    case Instruction::FPExt:
    case Instruction::PtrToInt:
    case Instruction::PtrToAddr:
    case Instruction::IntToPtr:
    case Instruction::SIToFP:
    case Instruction::UIToFP:
    case Instruction::Trunc:
    case Instruction::FPTrunc:
    case Instruction::BitCast: {
      auto [PrevMaxBW, PrevMinBW] = CastMaxMinBWSizes.value_or(
          std::make_pair(std::numeric_limits<unsigned>::min(),
                         std::numeric_limits<unsigned>::max()));
      if (ShuffleOrOp == Instruction::ZExt ||
          ShuffleOrOp == Instruction::SExt) {
        CastMaxMinBWSizes = std::make_pair(
            std::max<unsigned>(DL->getTypeSizeInBits(VL0->getType()),
                               PrevMaxBW),
            std::min<unsigned>(
                DL->getTypeSizeInBits(VL0->getOperand(0)->getType()),
                PrevMinBW));
      } else if (ShuffleOrOp == Instruction::Trunc) {
        CastMaxMinBWSizes = std::make_pair(
            std::max<unsigned>(
                DL->getTypeSizeInBits(VL0->getOperand(0)->getType()),
                PrevMaxBW),
            std::min<unsigned>(DL->getTypeSizeInBits(VL0->getType()),
                               PrevMinBW));
      }
      TreeEntry *TE = newTreeEntry(VL, Bundle /*vectorized*/, S, UserTreeIdx,
                                   ReuseShuffleIndices);
      LLVM_DEBUG(dbgs() << "SLP: added a new TreeEntry (CastInst).\n";
                 TE->dump());

      TE->setOperands(Operands);
      for (unsigned I : seq<unsigned>(VL0->getNumOperands()))
        buildTreeRec(TE->getOperand(I), Depth, {TE, I});
      if (ShuffleOrOp == Instruction::Trunc) {
        ExtraBitWidthNodes.insert(getOperandEntry(TE, 0)->Idx);
      } else if (ShuffleOrOp == Instruction::SIToFP ||
                 ShuffleOrOp == Instruction::UIToFP) {
        unsigned NumSignBits =
            ComputeNumSignBits(VL0->getOperand(0), *DL, AC, nullptr, DT);
        if (auto *OpI = dyn_cast<Instruction>(VL0->getOperand(0))) {
          APInt Mask = DB->getDemandedBits(OpI);
          NumSignBits = std::max(NumSignBits, Mask.countl_zero());
        }
        if (NumSignBits * 2 >=
            DL->getTypeSizeInBits(VL0->getOperand(0)->getType()))
          ExtraBitWidthNodes.insert(getOperandEntry(TE, 0)->Idx);
      }
      return;
    }
    case Instruction::ICmp:
    case Instruction::FCmp: {
      // Check that all of the compares have the same predicate.
      CmpInst::Predicate P0 = cast<CmpInst>(VL0)->getPredicate();
      TreeEntry *TE = newTreeEntry(VL, Bundle /*vectorized*/, S, UserTreeIdx,
                                   ReuseShuffleIndices);
      LLVM_DEBUG(dbgs() << "SLP: added a new TreeEntry (CmpInst).\n";
                 TE->dump());
      // The ands of the bit tests are peeled into the operands of the node.
      if (any_of(VL, IsaPred<TruncInst>)) {
        for (ICmpInst *CI : make_isa_range<ICmpInst>(VL))
          ReassocScalars.push_back(CI->getOperand(0));
        RegisterReassocScalars(TE);
      }

      VLOperands Ops(VL, Operands, S, *this);
      if (cast<CmpInst>(VL0)->isCommutative()) {
        // Commutative predicate - collect + sort operands of the instructions
        // so that each side is more likely to have the same opcode.
        assert(P0 == CmpInst::getSwappedPredicate(P0) &&
               "Commutative Predicate mismatch");
        Ops.reorder();
        Operands.front() = Ops.getVL(0);
        Operands.back() = Ops.getVL(1);
      } else {
        // Collect operands - commute if it uses the swapped predicate.
        // Lanes interchangeable with P0 (e.g. x == 0 in an x <u C bundle)
        // already have their operands adjusted, no need to commute them.
        for (auto [Idx, V] :
             make_filter_range(enumerate(VL), [](const auto &P) {
               return isa<CmpInst>(P.value());
             })) {
          auto *Cmp = cast<CmpInst>(V);
          if (Cmp->getPredicate() != P0 &&
              !CmpSamePredicateHelper::canConvertTo(Cmp, P0))
            std::swap(Operands.front()[Idx], Operands.back()[Idx]);
        }
      }
      TE->setOperands(Operands);
      buildTreeRec(Operands.front(), Depth, {TE, 0});
      buildTreeRec(Operands.back(), Depth, {TE, 1});
      if (ShuffleOrOp == Instruction::ICmp) {
        unsigned NumSignBits0 =
            ComputeNumSignBits(VL0->getOperand(0), *DL, AC, nullptr, DT);
        if (NumSignBits0 * 2 >=
            DL->getTypeSizeInBits(VL0->getOperand(0)->getType()))
          ExtraBitWidthNodes.insert(getOperandEntry(TE, 0)->Idx);
        unsigned NumSignBits1 =
            ComputeNumSignBits(VL0->getOperand(1), *DL, AC, nullptr, DT);
        if (NumSignBits1 * 2 >=
            DL->getTypeSizeInBits(VL0->getOperand(1)->getType()))
          ExtraBitWidthNodes.insert(getOperandEntry(TE, 1)->Idx);
      }
      return;
    }
    case Instruction::Select:
    case Instruction::FNeg:
    case Instruction::Add:
    case Instruction::FAdd:
    case Instruction::Sub:
    case Instruction::FSub:
    case Instruction::Mul:
    case Instruction::FMul:
    case Instruction::UDiv:
    case Instruction::SDiv:
    case Instruction::FDiv:
    case Instruction::URem:
    case Instruction::SRem:
    case Instruction::FRem:
    case Instruction::Shl:
    case Instruction::LShr:
    case Instruction::AShr:
    case Instruction::And:
    case Instruction::Or:
    case Instruction::Xor:
    case Instruction::Freeze: {
      TreeEntry *TE = newTreeEntry(VL, Bundle /*vectorized*/, S, UserTreeIdx,
                                   ReuseShuffleIndices);
      LLVM_DEBUG(
          dbgs() << "SLP: added a new TreeEntry "
                    "(SelectInst/UnaryOperator/BinaryOperator/FreezeInst).\n";
          TE->dump());

      if (!ReassocScalars.empty()) {
        // Realign columns by value family (cached above as
        // ReassocAlignedOperands), then let VLOperands polish the order,
        // keeping the polish only if the column-quality score does not regress
        // vs the peeled order. That polish is quadratic in the column count, so
        // past ReassocReorderColumnLimit keep the realigned seed, which already
        // groups the vectorizable columns. The polish swaps values between
        // columns per lane, which must not mix added and subtracted leaves in
        // one column, so signed nodes polish each sign group separately.
        if (Operands.size() <= Opts.slp_reassociate_reorder_limit) {
          SmallVector<ValueList> Reordered = ReassocAlignedOperands;
          SmallVector<unsigned> GroupIds[2];
          for (unsigned I : seq<unsigned>(NegatedColumns.size()))
            GroupIds[NegatedColumns[I]].push_back(I);
          for (ArrayRef<unsigned> Group :
               make_filter_range(GroupIds, [](ArrayRef<unsigned> Group) {
                 return Group.size() > 1;
               })) {
            SmallVector<ValueList> GroupCols = map_to_vector(
                Group, [&](unsigned I) { return ReassocAlignedOperands[I]; });
            VLOperands Ops(GroupCols, VL0->getParent(), *this);
            Ops.reorder();
            for (unsigned Pos : seq<unsigned>(Group.size()))
              Reordered[Group[Pos]] = Ops.getVL(Pos);
          }
          if (getReassocColumnsQuality(Reordered, *this, S.getOpcode()) >=
              ReassocPeeledQuality)
            Operands = std::move(Reordered);
          else
            LLVM_DEBUG(dbgs() << "SLP: reassociation reorder loses column "
                                 "structure, keeping the natural operand "
                                 "order.\n");
        } else {
          Operands = std::move(ReassocAlignedOperands);
        }
        if (HasDupColumnValues()) {
          Operands = std::move(NaturalTwoColumns);
          ReassocScalars.clear();
        }
      }
      if (!ReassocScalars.empty())
        RegisterReassocScalars(TE);
      else if (isa<BinaryOperator>(VL0) && isCommutative(VL0)) {
        VLOperands Ops(VL, Operands, S, *this);
        Ops.reorder();
        Operands[0] = Ops.getVL(0);
        Operands[1] = Ops.getVL(1);
      }
      TE->setOperands(Operands);
      if (!ReassocScalars.empty() && NegatedColumns.any())
        TE->setReassocNegatedOps(NegatedColumns);
      for (unsigned I : seq<unsigned>(TE->getNumOperands()))
        buildTreeRec(TE->getOperand(I), Depth + 1, {TE, I});
      return;
    }
    case Instruction::GetElementPtr: {
      TreeEntry *TE = newTreeEntry(VL, Bundle /*vectorized*/, S, UserTreeIdx,
                                   ReuseShuffleIndices);
      LLVM_DEBUG(dbgs() << "SLP: added a new TreeEntry (GetElementPtrInst).\n";
                 TE->dump());
      TE->setOperands(Operands);

      for (unsigned I = 0, Ops = Operands.size(); I < Ops; ++I)
        buildTreeRec(Operands[I], Depth + 1, {TE, I});
      return;
    }
    case Instruction::Store: {
      assert(CurrentOrder.empty() &&
             "Expected ordered store during tree building");
      if (State == TreeEntry::StridedVectorize) {
        TreeEntry *TE =
            newTreeEntry(VL, TreeEntry::StridedVectorize, Bundle, S,
                         UserTreeIdx, ReuseShuffleIndices, CurrentOrder);
        TreeEntryToStridedPtrInfoMap[TE] = SPtrInfo;
        LLVM_DEBUG(
            dbgs() << "SLP: added a new TreeEntry (strided StoreInst).\n";
            TE->dump());
        TE->setOperands(Operands);
        buildTreeRec(TE->getOperand(0), Depth + 1, {TE, 0});
        return;
      }
      if (State == TreeEntry::ExpandVectorize) {
        assert(ReuseShuffleIndices.empty() &&
               "Expected no reuse shuffle for an expanded masked store.");
        TreeEntry *TE =
            newTreeEntry(VL, TreeEntry::ExpandVectorize, Bundle, S, UserTreeIdx,
                         ExpandShuffleMask, CurrentOrder);
        TreeEntryToStridedPtrInfoMap[TE] = SPtrInfo;
        LLVM_DEBUG(
            dbgs()
                << "SLP: added a new TreeEntry (expanded masked StoreInst).\n";
            TE->dump());
        TE->setOperands(Operands);
        buildTreeRec(TE->getOperand(0), Depth + 1, {TE, 0});
        return;
      }
      TreeEntry *TE = newTreeEntry(VL, Bundle /*vectorized*/, S, UserTreeIdx,
                                   ReuseShuffleIndices, CurrentOrder);
      LLVM_DEBUG(dbgs() << "SLP: added a new TreeEntry (StoreInst).\n";
                 TE->dump());
      TE->setOperands(Operands);
      buildTreeRec(TE->getOperand(0), Depth + 1, {TE, 0});
      return;
    }
    case Instruction::Call: {
      // Check if the calls are all to the same vectorizable intrinsic or
      // library function.
      CallInst *CI = cast<CallInst>(VL0);
      Intrinsic::ID ID = getVectorIntrinsicIDForCall(CI, TLI);

      TreeEntry *TE = newTreeEntry(VL, Bundle /*vectorized*/, S, UserTreeIdx,
                                   ReuseShuffleIndices);
      LLVM_DEBUG(dbgs() << "SLP: added a new TreeEntry (CallInst).\n";
                 TE->dump());
      if (isCommutative(VL0)) {
        VLOperands Ops(VL, Operands, S, *this);
        Ops.reorder();
        Operands[0] = Ops.getVL(0);
        Operands[1] = Ops.getVL(1);
      }
      TE->setOperands(Operands);
      for (unsigned I : seq<unsigned>(CI->arg_size())) {
        // For scalar operands no need to create an entry since no need to
        // vectorize it.
        if (isVectorIntrinsicWithScalarOpAtArg(ID, I, TTI))
          continue;
        buildTreeRec(TE->getOperand(I), Depth + 1, {TE, I});
      }
      return;
    }
    case Instruction::ShuffleVector: {
      TreeEntry *TE = newTreeEntry(VL, Bundle /*vectorized*/, S, UserTreeIdx,
                                   ReuseShuffleIndices);
      if (S.isAltShuffle()) {
        LLVM_DEBUG(dbgs() << "SLP: added a new TreeEntry (isAltShuffle).\n";
                   TE->dump());
      } else {
        assert(Opts.slp_revec && "Only supported by REVEC.");
        LLVM_DEBUG(
            dbgs() << "SLP: added a new TreeEntry (ShuffleVectorInst).\n";
            TE->dump());
      }

      // Reorder operands if reordering would enable vectorization.
      auto *CI = dyn_cast<CmpInst>(VL0);
      if (CI && any_of(make_isa_range<CmpInst>(VL),
                       [](CmpInst *Cmp) { return !Cmp->isCommutative(); })) {
        auto *MainCI = cast<CmpInst>(S.getMainOp());
        auto *AltCI = cast<CmpInst>(S.getAltOp());
        CmpInst::Predicate MainP = MainCI->getPredicate();
        CmpInst::Predicate AltP = AltCI->getPredicate();
        assert(MainP != AltP &&
               "Expected different main/alternate predicates.");
        // Collect operands - commute if it uses the swapped predicate or
        // alternate operation.
        for (auto [Idx, V] :
             make_filter_range(enumerate(VL), [](const auto &P) {
               return !isa<PoisonValue>(P.value());
             })) {
          auto *Cmp = cast<CmpInst>(V);

          if (isAlternateInstruction(Cmp, MainCI, AltCI, *TLI)) {
            if (AltP == CmpInst::getSwappedPredicate(Cmp->getPredicate()))
              std::swap(Operands.front()[Idx], Operands.back()[Idx]);
          } else {
            if (MainP == CmpInst::getSwappedPredicate(Cmp->getPredicate()))
              std::swap(Operands.front()[Idx], Operands.back()[Idx]);
          }
        }
        TE->setOperands(Operands);
        buildTreeRec(Operands.front(), Depth + 1, {TE, 0});
        buildTreeRec(Operands.back(), Depth + 1, {TE, 1});
        return;
      }

      if (!ReassocScalars.empty()) {
        // Peeled alternate chains take the realigned columns; the operand
        // reorder below does not preserve the per-lane sign constraints.
        Operands = std::move(ReassocAlignedOperands);
        if (HasDupColumnValues()) {
          Operands = std::move(NaturalTwoColumns);
          ReassocScalars.clear();
        }
      }
      if (ReassocScalars.empty() && (isa<BinaryOperator>(VL0) || CI)) {
        VLOperands Ops(VL, Operands, S, *this);
        Ops.reorder();
        Operands[0] = Ops.getVL(0);
        Operands[1] = Ops.getVL(1);
      }
      if (!ReassocScalars.empty())
        RegisterReassocScalars(TE);
      TE->setOperands(Operands);
      for (unsigned I : seq<unsigned>(TE->getNumOperands()))
        buildTreeRec(TE->getOperand(I), Depth + 1, {TE, I});
      return;
    }
    default:
      break;
  }
  llvm_unreachable("Unexpected vectorization of the instructions.");
}

unsigned BoUpSLP::canMapToVector(Type *T) const {
  unsigned N = 1;
  Type *EltTy = T;

  while (isa<StructType, ArrayType, FixedVectorType>(EltTy)) {
    if (EltTy->isEmptyTy())
      return 0;
    if (auto *ST = dyn_cast<StructType>(EltTy)) {
      // Check that struct is homogeneous.
      for (const auto *Ty : ST->elements())
        if (Ty != *ST->element_begin())
          return 0;
      N *= ST->getNumElements();
      EltTy = *ST->element_begin();
    } else if (auto *AT = dyn_cast<ArrayType>(EltTy)) {
      N *= AT->getNumElements();
      EltTy = AT->getElementType();
    } else {
      auto *VT = cast<FixedVectorType>(EltTy);
      N *= VT->getNumElements();
      EltTy = VT->getElementType();
    }
  }

  if (!isValidElementType(EltTy, Opts.slp_revec))
    return 0;
  size_t VTSize = DL->getTypeStoreSizeInBits(getWidenedType(EltTy, N));
  if (VTSize < MinVecRegSize || VTSize > MaxVecRegSize ||
      VTSize != DL->getTypeStoreSizeInBits(T))
    return 0;
  return N;
}

bool BoUpSLP::canVectorStoreInsertValue(const TreeEntry *E) const {
  if (E->getOpcode() != Instruction::InsertValue ||
      E->State != TreeEntry::Vectorize)
    return false;

  bool HasStore = false;
  for (Value *V : E->Scalars) {
    auto *IV = dyn_cast<InsertValueInst>(V);
    if (!IV || isDeleted(IV))
      return false;

    bool HasExternalUser = false;
    for (User *U : IV->users()) {
      if (auto *UI = dyn_cast<Instruction>(U); UI && isDeleted(UI))
        continue;
      if (is_contained(E->Scalars, U))
        continue;
      HasExternalUser = true;
      // Only a plain (non-volatile, non-atomic) store may consume the vector
      // directly. Volatile/atomic stores must keep their original aggregate
      // type and access semantics, so fall back to the store + load roundtrip.
      auto *SI = dyn_cast<StoreInst>(U);
      if (!SI || !SI->isSimple())
        return false;
      HasStore = true;
    }
    if (HasExternalUser && !IV->hasOneUse())
      return false;
  }
  return HasStore;
}

FixedVectorType *BoUpSLP::getInsertBuildVectorSrcTy(const TreeEntry *E) const {
  Value *VL0 = E->getMainOp();
  if (E->getOpcode() == Instruction::InsertElement)
    return cast<FixedVectorType>(VL0->getType());
  assert(E->getOpcode() == Instruction::InsertValue &&
         "Expected InsertElement or InsertValue node.");
  unsigned MaxIdx = E->Scalars.size() - 1;
  for (InsertValueInst *I : make_isa_range<InsertValueInst>(E->Scalars))
    MaxIdx = std::max(MaxIdx, I->getIndices().front());
  return cast<FixedVectorType>(
      getWidenedType(getValueType(VL0, Opts.slp_revec), MaxIdx + 1));
}

bool BoUpSLP::canReuseExtract(ArrayRef<Value *> VL,
                              SmallVectorImpl<unsigned> &CurrentOrder,
                              bool ResizeAllowed) const {
  const auto *It = find_if(VL, IsaPred<ExtractElementInst, ExtractValueInst>);
  assert(It != VL.end() && "Expected at least one extract instruction.");
  auto *E0 = cast<Instruction>(*It);
  // Check if all of the extracts come from the same vector and from the
  // correct offset.
  Value *Vec = E0->getOperand(0);

  CurrentOrder.clear();

  // We have to extract from a vector/aggregate with the same number of elements.
  unsigned NElts;
  if (E0->getOpcode() == Instruction::ExtractValue) {
    NElts = canMapToVector(Vec->getType());
    if (!NElts)
      return false;
    // Check if load can be rewritten as load of vector.
    LoadInst *LI = dyn_cast<LoadInst>(Vec);
    if (!LI || !LI->isSimple() || !LI->hasNUses(VL.size()))
      return false;
  } else {
    NElts = cast<FixedVectorType>(Vec->getType())->getNumElements();
  }

  unsigned E = VL.size();
  if (!ResizeAllowed && NElts != E)
    return false;
  SmallVector<int> Indices(E, PoisonMaskElem);
  unsigned MinIdx = NElts, MaxIdx = 0;
  // Non-extract lanes (copyable elements modeled on an extract main op, or
  // undefs) are treated as holes.
  for (auto [I, V] : make_filter_range(enumerate(VL), [](const auto &P) {
         return isa<ExtractElementInst, ExtractValueInst>(P.value());
       })) {
    auto *Inst = cast<Instruction>(V);
    if (Inst->getOperand(0) != Vec)
      return false;
    if (auto *EE = dyn_cast<ExtractElementInst>(Inst))
      if (isa<UndefValue>(EE->getIndexOperand()))
        continue;
    std::optional<unsigned> Idx = getExtractIndex(Inst);
    if (!Idx)
      return false;
    const unsigned ExtIdx = *Idx;
    if (ExtIdx >= NElts)
      continue;
    Indices[I] = ExtIdx;
    if (MinIdx > ExtIdx)
      MinIdx = ExtIdx;
    if (MaxIdx < ExtIdx)
      MaxIdx = ExtIdx;
  }
  if (MaxIdx - MinIdx + 1 > E)
    return false;
  if (MaxIdx + 1 <= E)
    MinIdx = 0;

  // Check that all of the indices extract from the correct offset.
  bool ShouldKeepOrder = true;
  // Assign to all items the initial value E + 1 so we can check if the extract
  // instruction index was used already.
  // Also, later we can check that all the indices are used and we have a
  // consecutive access in the extract instructions, by checking that no
  // element of CurrentOrder still has value E + 1.
  CurrentOrder.assign(E, E);
  for (unsigned I = 0; I < E; ++I) {
    if (Indices[I] == PoisonMaskElem)
      continue;
    const unsigned ExtIdx = Indices[I] - MinIdx;
    if (CurrentOrder[ExtIdx] != E) {
      CurrentOrder.clear();
      return false;
    }
    ShouldKeepOrder &= ExtIdx == I;
    CurrentOrder[ExtIdx] = I;
  }
  if (ShouldKeepOrder)
    CurrentOrder.clear();

  return ShouldKeepOrder;
}

bool BoUpSLP::areAllUsersVectorized(
    Instruction *I, const SmallDenseSet<Value *> *VectorizedVals) const {
  return (I->hasOneUse() && (!VectorizedVals || VectorizedVals->contains(I))) ||
         all_of(I->users(), [this](User *U) {
           return isVectorized(U) || isVectorLikeInstWithConstOps(U) ||
                  (isa<ExtractElementInst>(U) && MustGather.contains(U));
         });
}

static InstructionCost canConvertToFMA(ArrayRef<Value *> VL,
                                       const InstructionsState &S,
                                       DominatorTree &DT, const DataLayout &DL,
                                       TargetTransformInfo &TTI,
                                       const TargetLibraryInfo &TLI,
                                       const BoUpSLP &R);

/// \returns true if \p Op is a contractable single-use fmul, which the backend
/// fuses with its fadd/fsub user \p I: \p Op is in the block of \p I or the
/// target sinks it there.
static bool isFusableFMulOperand(Value *Op, Instruction *I,
                                 const TargetTransformInfo &TTI) {
  Instruction *FMul;
  if (!match(Op, m_Instruction(FMul, m_OneUse(m_AllowContract(
                                         m_FMul(m_Value(), m_Value()))))))
    return false;
  if (FMul->getParent() == I->getParent())
    return true;
  SmallVector<Use *> OpsToSink;
  return TTI.isProfitableToSinkOperands(I, OpsToSink) &&
         any_of(OpsToSink, [&](const Use *U) { return U->get() == FMul; });
}

/// \returns the fmul operand of the fadd/fsub \p I that the backend fuses with
/// \p I into an fmuladd: the first fusable one from either operand, c - a*b
/// included. \p I must allow contraction.
static Instruction *getFusableFMulOperand(Instruction *I,
                                          const TargetTransformInfo &TTI) {
  if (!match(I, m_AllowContract(m_CombineOr(m_FAdd(m_Value(), m_Value()),
                                            m_FSub(m_Value(), m_Value())))))
    return nullptr;
  for (Value *Op : I->operands())
    if (isFusableFMulOperand(Op, I, TTI))
      return cast<Instruction>(Op);
  return nullptr;
}

/// \returns the cost of the binary operator \p I, priced as not fused. No
/// context instruction is passed: targets that model the fmuladd fusion would
/// discount the unfused side of the comparison as well.
static InstructionCost getUnfusedBinOpCost(Instruction *I,
                                           TargetTransformInfo &TTI,
                                           const TargetLibraryInfo &TLI,
                                           TTI::TargetCostKind CostKind) {
  assert(match(I, m_BinOp()) && "Expected a binary operator.");
  TTI::OperandValueInfo Op1Info = TTI::getOperandInfo(I->getOperand(0));
  TTI::OperandValueInfo Op2Info = TTI::getOperandInfo(I->getOperand(1));
  return TTI.getArithmeticInstrCost(
      I->getOpcode(), I->getType(), CostKind, Op1Info, Op2Info,
      {I->getOperand(0), I->getOperand(1)}, /*CxtI=*/nullptr, &TLI);
}

std::pair<Instruction *, InstructionCost>
BoUpSLP::getFMulFusingUser(Instruction *I, bool InTree) const {
  if (!match(I, m_OneUse(m_FMul(m_Value(), m_Value()))))
    return {nullptr, InstructionCost::getInvalid()};
  auto *U = cast<Instruction>(I->user_back());
  // The reduction cost accounts for the fusion of the reduced values into the
  // reduction operations itself. The lanes of the combined fmuladd node are
  // fused with its own fmul operand node, not with the other operand.
  if (getFusableFMulOperand(U, *TTI) != I ||
      (InTree && ((UserIgnoreList && UserIgnoreList->contains(U)) ||
                  any_of(getTreeEntries(U), [](const TreeEntry *TE) {
                    return TE->CombinedOp == TreeEntry::FMulAdd;
                  }))))
    return {nullptr, InstructionCost::getInvalid()};
  // The target must actually prefer the fused form.
  InstructionCost FMACost =
      canConvertToFMA(U, InstructionsState(U, U), *DT, *DL, *TTI, *TLI, *this);
  return {FMACost.isValid() ? U : nullptr, FMACost};
}

bool BoUpSLP::isFusedVectorizedFAddSub(Instruction *U) const {
  return any_of(getTreeEntries(U), [&](const TreeEntry *TE) {
    return !DeletedNodes.contains(TE) && !TransformedToGatherNodes.contains(TE);
  });
}

InstructionCost BoUpSLP::getUnfusedFMulsPenalty(const TreeEntry &TE) const {
  if (!TE.hasState() || TE.isGather() ||
      (TE.getOpcode() != Instruction::FMul &&
       TE.getAltOpcode() != Instruction::FMul))
    return TTI::TCC_Free;
  InstructionCost Penalty = TTI::TCC_Free;
  for (Value *V : TE.Scalars) {
    Instruction *I;
    if (!match(V, m_Instruction(I, m_FMul(m_Value(), m_Value()))) ||
        (TE.hasCopyableElements() && TE.isCopyableElement(I)))
      continue;
    if (Instruction *U = getFMulFusingUser(I).first;
        U && isFusedVectorizedFAddSub(U))
      Penalty += getUnfusedBinOpCost(I, *TTI, *TLI, CostKind);
  }
  return Penalty;
}

// A poor-throughput entry's real vector-vs-scalar savings (fdiv/frem/fsqrt)
// are already folded into TreeCost like any other entry, including all
// shuffle/insert/extract overhead elsewhere in the tree. So bypassing the
// instruction-count veto just has to trust that already-complete TreeCost
// instead of guessing at extra savings: heavy gather/shuffle overhead raises
// TreeCost too, and will still block the bypass.
bool BoUpSLP::bypassesInstCountCheck(InstructionCost TreeCost) const {
  if (!Opts.slp_vectorize_poor_throughput || TreeCost >= -getCostThreshold())
    return false;
  PoorThroughputOpCache Cache;
  return any_of(VectorizableTree, [&](const std::unique_ptr<TreeEntry> &Ptr) {
    const TreeEntry &TE = *Ptr;
    return TE.hasState() && !DeletedNodes.contains(&TE) && !TE.isGather() &&
           !TransformedToGatherNodes.contains(&TE) &&
           TE.State != TreeEntry::CombinedVectorize &&
           isPoorThroughputOp(Opts, TE.getMainOp(), *TTI, *TLI, Cache,
                              CostKind);
  });
}

bool BoUpSLP::collectGatherUserOps(
    const TreeEntry &E, SmallVectorImpl<TTI::BuildVectorUseOp> &UserOps) const {
  UserOps.clear();
  for (const auto &TE :
       make_filter_range(VectorizableTree, [&](const auto &TE) {
         return !DeletedNodes.contains(TE.get());
       })) {
    if (!(TE->isGather() || TransformedToGatherNodes.contains(TE.get())) ||
        !E.isSame(TE->Scalars))
      continue;
    const TreeEntry *UserTE = TE->UserTreeIndex.UserTE;
    if (!UserTE || !UserTE->hasState() || UserTE->isAltShuffle() ||
        TransformedToGatherNodes.contains(UserTE))
      return false;

    Intrinsic::ID IntrinsicID = Intrinsic::not_intrinsic;
    if (auto *II = dyn_cast<IntrinsicInst>(UserTE->getMainOp()))
      IntrinsicID = II->getIntrinsicID();
    UserOps.emplace_back(UserTE->getOpcode(), IntrinsicID,
                         TE->UserTreeIndex.EdgeIdx);
  }
  return !UserOps.empty();
}

uint64_t BoUpSLP::getNumScalarInsts(bool HasTreeLoop) {
  uint64_t Total = 0;
  for (const std::unique_ptr<TreeEntry> &Ptr : VectorizableTree) {
    const TreeEntry &TE = *Ptr;
    if (DeletedNodes.contains(&TE))
      continue;
    // CombinedVectorize entries (e.g. the fmul child of an FMulAdd, or the
    // cmp child of a MinMax select) are absorbed into the parent on both
    // scalar and vector sides. The backend fuses fadd+fmul -> fma and
    // select+cmp -> smin/smax even for scalar code, so skip to avoid
    // double-counting. Checked before the scale lookup below: some of
    // these entries started out as constant-only gather nodes and have no
    // valid instruction state to key the loop-nest scale off of.
    if (TE.State == TreeEntry::CombinedVectorize)
      continue;
    uint64_t Scale = getEntryEffectiveScale(TE);
    if (HasTreeLoop && Scale <= 1)
      continue;
    unsigned Count = 0;
    if (TE.isGather() || TransformedToGatherNodes.contains(&TE)) {
      // Count extractelement scalars in gathers - they exist in the scalar
      // code regardless of vectorization. ExtractElement instructions
      // become free when the vector input is used directly.
      for (Value *V : TE.Scalars)
        if (isa<ExtractElementInst>(V))
          ++Count;
      Total = SaturatingMultiplyAdd<uint64_t>(Count, Scale, Total);
      continue;
    }
    // Each vectorize entry represents a bundle of scalar instructions.
    // Count per-entry without cross-entry deduplication, since shared
    // scalars across entries still represent separate work in scalar code.
    for (Instruction *I : make_isa_range<Instruction>(TE.Scalars)) {
      if (TE.hasCopyableElements() && TE.isCopyableElement(I))
        continue;
      ++Count;
      // Calculate calls/divs/rems twice, they may cost higher, so better to
      // include their count twice to mimic slightly real cost here.
      if (I->isIntDivRem() || I->isFPDivRem())
        ++Count;
      if (auto *CI = dyn_cast<CallInst>(I)) {
        Intrinsic::ID BaseID = getVectorIntrinsicIDForCall(CI, TLI);
        if (!isTriviallyVectorizable(BaseID))
          ++Count;
      }
    }
    // Count peeled intermediates in the scalar baseline (not in Scalars).
    Count += TE.getReassocScalars().size();
    // Even when the whole node is not combined, individual scalar
    // instructions may be fused by the backend. Each fused pair (e.g.
    // fadd+fmul -> fma, select+cmp -> smin/smax) becomes a single scalar
    // instruction, absorbing the operand instruction. Subtract 1 for each
    // such match to avoid over-counting the scalar side.
    if (TE.CombinedOp == TreeEntry::NotCombinedOp && TE.hasState()) {
      unsigned Opcode = TE.getOpcode();
      if (Opcode == Instruction::Select) {
        for (Value *V : make_filter_range(TE.Scalars, [&](Value *V) {
               return !TE.hasCopyableElements() || !TE.isCopyableElement(V);
             })) {
          auto *SI = dyn_cast<SelectInst>(V);
          if (!SI)
            continue;
          auto [ID, _] = canConvertToMinOrMaxIntrinsic({V});
          if (ID != Intrinsic::not_intrinsic) {
            assert(Count > 0 && "Underflow in scalar inst count (minmax)");
            --Count;
          }
        }
      } else {
        for (Instruction *I : make_filter_range(
                 make_isa_range<Instruction>(TE.Scalars), [&](Instruction *V) {
                   return !TE.hasCopyableElements() || !TE.isCopyableElement(V);
                 })) {
          if (match(I, m_CombineOr(m_FAdd(m_Value(), m_Value()),
                                   m_FSub(m_Value(), m_Value())))) {
            if (canConvertToFMA(I, InstructionsState(I, I), *DT, *DL, *TTI,
                                *TLI, *this)
                    .isValid()) {
              assert(Count > 0 && "Underflow in scalar inst count (fma)");
              --Count;
            }
          } else if (match(I, m_FMul(m_Value(), m_Value()))) {
            // The fmul, fused into a scalar user, disappears into the user's
            // fmuladd. A vectorized fadd/fsub user lane already accounts for
            // the fusion.
            Instruction *U = getFMulFusingUser(I).first;
            if (U && !isFusedVectorizedFAddSub(U)) {
              assert(Count > 0 && "Underflow in scalar inst count (fma)");
              --Count;
            }
          }
        }
      }
    }
    Total = SaturatingMultiplyAdd<uint64_t>(Count, Scale, Total);
  }
  return Total;
}

uint64_t BoUpSLP::getNumVectorInsts(bool HasTreeLoop, bool CountExtracts) {
  uint64_t Total = 0;
  // The alternate op, fused with the multiplication by the target, is counted
  // with the multiplication node, the same way as the scalar fmas.
  auto IsFusedAlt = [&](const TreeEntry &TE) {
    if (!TE.hasState() || TE.State != TreeEntry::Vectorize ||
        DeletedNodes.contains(&TE) || TransformedToGatherNodes.contains(&TE) ||
        !TE.isAltShuffle() || TE.hasReassocScalars() ||
        !TE.getMainOp()->getType()->isFloatingPointTy() ||
        !TE.getOperations().isAddSubLikeOp())
      return false;
    Type *ScalarTy = TE.getMainOp()->getType();
    auto *VecTy = cast<VectorType>(getWidenedType(ScalarTy, TE.Scalars.size()));
    SmallBitVector OpcodeMask(getAltInstrMask(
        TE.Scalars, ScalarTy, TE.getOpcode(), TE.getAltOpcode()));
    return TTI->isLegalAltInstr(VecTy, TE.getOpcode(), TE.getAltOpcode(),
                                OpcodeMask, TE.Scalars) &&
           canConvertToFMA(TE.Scalars, TE.getOperations(), *DT, *DL, *TTI, *TLI,
                           *this)
               .isValid();
  };
  // The scalar count already credits the fused scalars as fmas, so only a tree
  // with the fused alternate op is counted at the level of the machine
  // instructions. Doing the same for the other trees changes their VF=2
  // decisions.
  const bool HasFusedAlt =
      any_of(VectorizableTree, [&](const std::unique_ptr<TreeEntry> &Ptr) {
        return IsFusedAlt(*Ptr);
      });
  // Source vector -> max scale among the gather entries sharing it, so the
  // combined shufflevector is still weighted like an in-loop entry below.
  SmallDenseMap<Value *, uint64_t, 4> GatherExtractSourceVecs;
  for (const std::unique_ptr<TreeEntry> &Ptr : VectorizableTree) {
    const TreeEntry &TE = *Ptr;
    if (DeletedNodes.contains(&TE))
      continue;
    if (TE.State == TreeEntry::CombinedVectorize)
      continue;
    uint64_t Scale = getEntryEffectiveScale(TE);
    if (HasTreeLoop && Scale <= 1)
      continue;
    unsigned Count = 0;
    if (TE.isGather() || TransformedToGatherNodes.contains(&TE)) {
      if (TE.hasState()) {
        if (const TreeEntry *E =
                getSameValuesTreeEntry(TE.getMainOp(), TE.Scalars);
            E && E != &TE && E->getVectorFactor() == TE.getVectorFactor())
          continue;
        SmallVector<Value *> RevScalars(TE.Scalars.rbegin(), TE.Scalars.rend());
        if (const TreeEntry *E =
                getSameValuesTreeEntry(TE.getMainOp(), RevScalars);
            E && E->getVectorFactor() == TE.getVectorFactor()) {
          Total = SaturatingAdd(Total, Scale);
          continue;
        }
      }
      // ExtractElement gathers from the same source vector become a single
      // shufflevector. Collect source vectors globally across all gather
      // entries and count once at the end.
      if (all_of(TE.Scalars,
                 IsaPred<ExtractElementInst, UndefValue, Constant>)) {
        for (ExtractElementInst *EE :
             make_isa_range<ExtractElementInst>(TE.Scalars)) {
          uint64_t &VecScale =
              GatherExtractSourceVecs.try_emplace(EE->getVectorOperand(), 0)
                  .first->second;
          VecScale = std::max(VecScale, Scale);
        }
      } else {
        // A splat is a single broadcast. In loops, its per-lane count, scaled
        // by the trip count, rejects the profitable trees.
        if ((HasFusedAlt || HasTreeLoop) && isSplat(TE.Scalars))
          Count = !isConstant(TE.Scalars.front());
        else
          Count = TE.Scalars.size() - count_if(TE.Scalars, isConstant);
      }
      Total = SaturatingMultiplyAdd<uint64_t>(Count, Scale, Total);
      continue;
    }
    // InsertElement/ExtractElement vectorize entries don't produce real
    // vector instructions - InsertElement at root IS the result, and
    // ExtractElement entries reference the input vector directly.
    if (TE.getOpcode() == Instruction::InsertElement ||
        TE.getOpcode() == Instruction::ExtractElement)
      continue;
    if (TE.getOpcode() == Instruction::InsertValue) {
      // InsertValue materializes via store + load unless it is stored directly
      // as a vector.
      if (!canVectorStoreInsertValue(&TE))
        Count += 2;
      if (!TE.ReorderIndices.empty() || !TE.ReuseShuffleIndices.empty())
        ++Count;
      Total = SaturatingMultiplyAdd<uint64_t>(Count, Scale, Total);
      continue;
    }
    if (IsFusedAlt(TE))
      continue;
    if (TE.State == TreeEntry::SplitVectorize)
      Count += 2;
    else if (TE.hasReassocScalars())
      // N operand columns need N-1 binary combines.
      Count += TE.getNumOperands() - 1;
    else
      ++Count;
    if (!TE.ReorderIndices.empty() || !TE.ReuseShuffleIndices.empty())
      ++Count;
    Total = SaturatingMultiplyAdd<uint64_t>(Count, Scale, Total);
  }
  for (const auto &VecAndScale : GatherExtractSourceVecs)
    Total = SaturatingAdd(Total, VecAndScale.second);
  if (!CountExtracts)
    return Total;
  // Count extract instructions from ExternalUses, skipping insertelements
  // (those get folded into shuffles, not real extracts).
  SmallPtrSet<Value *, 8> CountedExtracts;
  for (const ExternalUser &EU :
       make_filter_range(ExternalUses, [](const ExternalUser &EU) {
         return !isa_and_nonnull<InsertElementInst>(EU.User);
       })) {
    if (EU.User && EphValues.count(EU.User))
      continue;
    // Vector-typed scalars are consumed as whole vectors, no extract
    // instruction is emitted for them.
    if (isVectorizedTy(EU.Scalar->getType()) &&
        (!Opts.slp_revec ||
         (EU.E.hasState() && EU.E.getOpcode() == Instruction::InsertElement)))
      continue;
    if (ExternalUsesAsOriginalScalar.contains(EU.Scalar))
      continue;
    if (!CountedExtracts.insert(EU.Scalar).second)
      continue;
    // The extract of the lane, which is free in the target, is not emitted.
    Type *ScalarTy = EU.Scalar->getType();
    if (HasFusedAlt && !MinBWs.contains(&EU.E) &&
        VectorType::isValidElementType(ScalarTy) &&
        TTI->getVectorInstrCost(
            Instruction::ExtractElement,
            getWidenedType(ScalarTy, EU.E.getVectorFactor()), CostKind,
            EU.Lane) == TTI::TCC_Free)
      continue;
    ++Total;
  }
  return Total;
}

void BoUpSLP::TreeEntry::buildAltOpShuffleMask(
    const function_ref<bool(Instruction *)> IsAltOp, SmallVectorImpl<int> &Mask,
    SmallVectorImpl<Value *> *OpScalars,
    SmallVectorImpl<Value *> *AltScalars) const {
  unsigned Sz = Scalars.size();
  Mask.assign(Sz, PoisonMaskElem);
  SmallVector<int> OrderMask;
  if (!ReorderIndices.empty())
    inversePermutation(ReorderIndices, OrderMask);
  for (unsigned I = 0; I < Sz; ++I) {
    unsigned Idx = I;
    if (!ReorderIndices.empty())
      Idx = OrderMask[I];
    if (isa<PoisonValue>(Scalars[Idx]))
      continue;
    auto *OpInst = cast<Instruction>(Scalars[Idx]);
    if (IsAltOp(OpInst)) {
      Mask[I] = Sz + Idx;
      if (AltScalars)
        AltScalars->push_back(OpInst);
    } else {
      Mask[I] = Idx;
      if (OpScalars)
        OpScalars->push_back(OpInst);
    }
  }
  if (!ReuseShuffleIndices.empty()) {
    SmallVector<int> NewMask(ReuseShuffleIndices.size(), PoisonMaskElem);
    transform(ReuseShuffleIndices, NewMask.begin(), [&Mask](int Idx) {
      return Idx != PoisonMaskElem ? Mask[Idx] : PoisonMaskElem;
    });
    Mask.swap(NewMask);
  }
}

static bool isMainInstruction(Instruction *I, Instruction *MainOp,
                              Instruction *AltOp,
                              const TargetLibraryInfo &TLI) {
  return InstructionsState(MainOp, AltOp).getMatchingMainOpOrAltOp(I) == MainOp;
}

void BoUpSLP::reorderGatherNode(TreeEntry &TE) {
  assert(TE.isGather() && TE.ReorderIndices.empty() &&
         "Expected gather node without reordering.");
  DenseMap<std::pair<size_t, Value *>, SmallVector<LoadInst *>> LoadsMap;
  SmallSet<size_t, 2> LoadKeyUsed;

  // Do not reorder nodes if it small (just 2 elements), all-constant or all
  // instructions have same opcode already.
  if (TE.Scalars.size() == 2 || (TE.hasState() && !TE.isAltShuffle()) ||
      all_of(TE.Scalars, isConstant))
    return;

  if (any_of(seq<unsigned>(TE.Idx), [&](unsigned Idx) {
        return VectorizableTree[Idx]->isSame(TE.Scalars);
      }))
    return;

  auto GenerateLoadsSubkey = [&](size_t Key, LoadInst *LI) {
    Key = hash_combine(hash_value(LI->getParent()->getNumber()), Key);
    Value *Ptr = getUnderlyingObject(LI->getPointerOperand(),
                                     Opts.slp_recursion_max_depth);
    if (LoadKeyUsed.contains(Key)) {
      auto LIt = LoadsMap.find(std::make_pair(Key, Ptr));
      if (LIt != LoadsMap.end()) {
        for (LoadInst *RLI : LIt->second) {
          if (getPointersDiff(RLI->getType(), RLI->getPointerOperand(),
                              LI->getType(), LI->getPointerOperand(), *DL, *SE,
                              /*StrictCheck=*/true))
            return hash_value(RLI->getPointerOperand());
        }
        for (LoadInst *RLI : LIt->second) {
          if (arePointersCompatible(RLI->getPointerOperand(),
                                    LI->getPointerOperand(), *TLI,
                                    Opts.slp_recursion_max_depth)) {
            hash_code SubKey = hash_value(RLI->getPointerOperand());
            return SubKey;
          }
        }
        if (LIt->second.size() > 2) {
          hash_code SubKey =
              hash_value(LIt->second.back()->getPointerOperand());
          return SubKey;
        }
      }
    }
    LoadKeyUsed.insert(Key);
    LoadsMap.try_emplace(std::make_pair(Key, Ptr)).first->second.push_back(LI);
    return hash_value(LI->getPointerOperand());
  };
  MapVector<size_t, MapVector<size_t, SmallVector<Value *>>> SortedValues;
  SmallDenseMap<Value *, SmallVector<unsigned>, 8> KeyToIndex;
  bool IsOrdered = true;
  unsigned NumInstructions = 0;
  // Try to "cluster" scalar instructions, to be able to build extra vectorized
  // nodes.
  for (auto [I, V] : enumerate(TE.Scalars)) {
    size_t Key = 1, Idx = 1;
    if (auto *Inst = dyn_cast<Instruction>(V);
        Inst && !isa<ExtractElementInst, LoadInst, CastInst>(V) &&
        !isDeleted(Inst) && !isVectorized(V)) {
      std::tie(Key, Idx) = generateKeySubkey(V, TLI, GenerateLoadsSubkey,
                                             /*AllowAlternate=*/false);
      ++NumInstructions;
    }
    auto &Container = SortedValues[Key];
    if (IsOrdered && !KeyToIndex.contains(V) &&
        !(isa<Constant, ExtractElementInst>(V) ||
          isVectorLikeInstWithConstOps(V)) &&
        ((Container.contains(Idx) &&
          KeyToIndex.at(Container[Idx].back()).back() != I - 1) ||
         (!Container.empty() && !Container.contains(Idx) &&
          KeyToIndex.at(Container.back().second.back()).back() != I - 1)))
      IsOrdered = false;
    auto &KTI = KeyToIndex[V];
    if (KTI.empty())
      Container[Idx].push_back(V);
    KTI.push_back(I);
  }
  SmallVector<std::pair<unsigned, unsigned>> SubVectors;
  APInt DemandedElts = APInt::getAllOnes(TE.Scalars.size());
  if (!IsOrdered && NumInstructions > 1) {
    unsigned Cnt = 0;
    TE.ReorderIndices.resize(TE.Scalars.size(), TE.Scalars.size());
    for (const auto &D : SortedValues) {
      for (const auto &P : D.second) {
        unsigned Sz = 0;
        for (Value *V : P.second) {
          ArrayRef<unsigned> Indices = KeyToIndex.at(V);
          for (auto [K, Idx] : enumerate(Indices)) {
            TE.ReorderIndices[Cnt + K] = Idx;
            TE.Scalars[Cnt + K] = V;
          }
          Sz += Indices.size();
          Cnt += Indices.size();
        }
        if (Sz > 1 && isa<Instruction>(P.second.front())) {
          const unsigned SubVF = getFloorFullVectorNumberOfElements(
              *TTI, TE.Scalars.front()->getType(), Sz, Opts.slp_revec);
          SubVectors.emplace_back(Cnt - Sz, SubVF);
          for (unsigned I : seq<unsigned>(Cnt - Sz, Cnt - Sz + SubVF))
            DemandedElts.clearBit(I);
        } else if (!P.second.empty() && isConstant(P.second.front())) {
          for (unsigned I : seq<unsigned>(Cnt - Sz, Cnt))
            DemandedElts.clearBit(I);
        }
      }
    }
  }
  // Reuses always require shuffles, so consider it as profitable.
  if (!TE.ReuseShuffleIndices.empty() || TE.ReorderIndices.empty())
    return;
  // Do simple cost estimation.
  InstructionCost Cost = 0;
  auto *ScalarTy = TE.Scalars.front()->getType();
  auto *VecTy = cast<VectorType>(getWidenedType(ScalarTy, TE.Scalars.size()));
  for (auto [Idx, Sz] : SubVectors) {
    Cost += getShuffleCost(*TTI, TTI::SK_InsertSubvector, VecTy, CostKind, {},
                           Idx, cast<VectorType>(getWidenedType(ScalarTy, Sz)));
  }
  Cost += getScalarizationOverhead(*TTI, Opts.slp_revec, ScalarTy, VecTy,
                                   DemandedElts,
                                   /*Insert=*/true,
                                   /*Extract=*/false, CostKind);
  int Sz = TE.Scalars.size();
  SmallVector<int> ReorderMask(TE.ReorderIndices.begin(),
                               TE.ReorderIndices.end());
  for (unsigned I : seq<unsigned>(Sz)) {
    Value *V = TE.getOrdered(I);
    if (isa<PoisonValue>(V)) {
      ReorderMask[I] = PoisonMaskElem;
    } else if (isConstant(V) || DemandedElts[I]) {
      ReorderMask[I] = I + TE.ReorderIndices.size();
    }
  }
  Cost += getShuffleCost(*TTI,
                         any_of(ReorderMask, [&](int I) { return I >= Sz; })
                             ? TTI::SK_PermuteTwoSrc
                             : TTI::SK_PermuteSingleSrc,
                         VecTy, CostKind, ReorderMask);
  DemandedElts = APInt::getAllOnes(TE.Scalars.size());
  ReorderMask.assign(Sz, PoisonMaskElem);
  for (unsigned I : seq<unsigned>(Sz)) {
    Value *V = TE.getOrdered(I);
    if (isConstant(V)) {
      DemandedElts.clearBit(I);
      if (!isa<PoisonValue>(V))
        ReorderMask[I] = I;
    } else {
      ReorderMask[I] = I + Sz;
    }
  }
  InstructionCost BVCost = getScalarizationOverhead(
      *TTI, Opts.slp_revec, ScalarTy, VecTy, DemandedElts,
      /*Insert=*/true, /*Extract=*/false, CostKind);
  if (!DemandedElts.isAllOnes())
    BVCost += getShuffleCost(*TTI, TTI::SK_PermuteTwoSrc, VecTy, CostKind,
                             ReorderMask);
  if (Cost >= BVCost) {
    SmallVector<int> Mask(TE.ReorderIndices.begin(), TE.ReorderIndices.end());
    reorderScalars(TE.Scalars, Mask);
    TE.ReorderIndices.clear();
  }
}

/// Check if we can convert fadd/fsub sequence to FMAD.
/// \returns Cost of the FMAD, if conversion is possible, invalid cost
/// otherwise.
static InstructionCost canConvertToFMA(ArrayRef<Value *> VL,
                                       const InstructionsState &S,
                                       DominatorTree &DT, const DataLayout &DL,
                                       TargetTransformInfo &TTI,
                                       const TargetLibraryInfo &TLI,
                                       const BoUpSLP &R) {
  assert(all_of(VL,
                [](Value *V) {
                  return V->getType()->getScalarType()->isFloatingPointTy();
                }) &&
         "Can only convert to FMA for floating point types");
  assert(S.isAddSubOrFNegLikeOp() &&
         "Can only convert to FMA for add/sub or fneg chain links");
  const TTI::TargetCostKind CostKind = R.getCostKind();

  auto CheckForContractable = [](ArrayRef<Value *> VL,
                                 const InstructionsState &S) {
    FastMathFlags FMF;
    FMF.set();
    for (Instruction *I : make_isa_range<Instruction>(VL)) {
      if (S.isCopyableElement(I))
        continue;
      Instruction *MatchingI = S.getMatchingMainOpOrAltOp(I);
      if (S.getMainOp() != MatchingI && S.getAltOp() != MatchingI)
        continue;
      if (auto *FPCI = dyn_cast<FPMathOperator>(I))
        FMF &= FPCI->getFastMathFlags();
    }
    return FMF.allowContract();
  };
  if (!CheckForContractable(VL, S))
    return InstructionCost::getInvalid();
  // fmul also should be contractable
  InstructionsCompatibilityAnalysis Analysis(DT, DL, TTI, TLI);
  SmallVector<BoUpSLP::ValueList> Operands = Analysis.buildOperands(S, VL, R);
  // The operands follow the majority pattern of the lanes, while the backend
  // fuses the fmul from either operand (c - a*b included); move it to the
  // first column.
  if (Operands.size() == 2) {
    for (auto [Idx, V] : enumerate(VL)) {
      auto *I = dyn_cast<Instruction>(V);
      if (!I || S.isCopyableElement(I))
        continue;
      if (Instruction *FMul = getFusableFMulOperand(I, TTI);
          FMul && Operands[1][Idx] == FMul)
        std::swap(Operands[0][Idx], Operands[1][Idx]);
    }
  }

  // The lanes without the fmul, e.g. the constant lanes of the copyable nodes,
  // are the copyable lanes of the fmul column.
  InstructionsState OpS = Analysis.buildInstructionsState(Operands.front(), R);
  if (!OpS.valid())
    return InstructionCost::getInvalid();

  if (OpS.isAltShuffle() || OpS.getOpcode() != Instruction::FMul)
    return InstructionCost::getInvalid();
  if (!CheckForContractable(Operands.front(), OpS))
    return InstructionCost::getInvalid();
  // Compare the costs.
  InstructionCost FMulPlusFAddCost = 0;
  InstructionCost FMACost = 0;
  FastMathFlags FMF;
  FMF.set();
  const bool IsArithmeticState = S.isAddSubLikeOp() || S.isMulDivLikeOp() ||
                                 S.isShiftOp() || S.isBitwiseLogicOp();
  // A dropped fneg link stands in for the sign-flipped combine its operand
  // joins and is costed as an fadd plus the fneg itself (both are removed).
  auto GetLinkCost = [&](Instruction *I, bool IsCopyable = false) {
    if (S.getOpcode() != Instruction::FNeg) {
      if (IsCopyable || !IsArithmeticState ||
          (I->getOpcode() != S.getOpcode() &&
           I->getOpcode() != S.getAltOpcode()))
        return TTI.getInstructionCost(I, CostKind);
      return getUnfusedBinOpCost(I, TTI, TLI, CostKind);
    }
    return TTI.getArithmeticInstrCost(Instruction::FAdd, I->getType(), CostKind,
                                      {},
                                      TTI::getOperandInfo(I->getOperand(0))) +
           TTI.getArithmeticInstrCost(Instruction::FNeg, I->getType(), CostKind,
                                      TTI::getOperandInfo(I->getOperand(0)));
  };
  for (Instruction *I : make_isa_range<Instruction>(VL)) {
    const bool IsCopyable = S.isCopyableElement(I);
    if (!IsCopyable)
      if (auto *FPCI = dyn_cast<FPMathOperator>(I))
        FMF &= FPCI->getFastMathFlags();
    FMulPlusFAddCost += GetLinkCost(I, IsCopyable);
  }
  unsigned NumOps = 0;
  for (auto [V, Op] :
       make_filter_range(zip(VL, Operands.front()), [&](const auto &P) {
         return !S.isCopyableElement(std::get<0>(P));
       })) {
    auto *I = dyn_cast<Instruction>(Op);
    if (!I || OpS.isCopyableElement(I) ||
        !isFusableFMulOperand(I, cast<Instruction>(V), TTI)) {
      if (auto *OpI = dyn_cast<Instruction>(V))
        FMACost += GetLinkCost(OpI);
      if (I)
        FMACost += TTI.getInstructionCost(I, CostKind);
      continue;
    }
    ++NumOps;
    if (auto *FPCI = dyn_cast<FPMathOperator>(I))
      FMF &= FPCI->getFastMathFlags();
    FMulPlusFAddCost += getUnfusedBinOpCost(I, TTI, TLI, CostKind);
  }
  Type *Ty = VL.front()->getType();
  IntrinsicCostAttributes ICA(Intrinsic::fmuladd, Ty, {Ty, Ty, Ty}, FMF);
  FMACost += NumOps * TTI.getIntrinsicInstrCost(ICA, CostKind);
  return FMACost < FMulPlusFAddCost ? FMACost : InstructionCost::getInvalid();
}

bool BoUpSLP::matchesShlZExt(const TreeEntry &TE, OrdersType &Order,
                             bool &IsBSwap, bool &ForLoads) const {
  assert(TE.hasState() && TE.getOpcode() == Instruction::Shl &&
         "Expected Shl node.");
  IsBSwap = false;
  ForLoads = false;
  if (TE.State != TreeEntry::Vectorize || TE.isAltShuffle() ||
      !TE.ReorderIndices.empty() || !TE.ReuseShuffleIndices.empty() ||
      MinBWs.contains(&TE) ||
      any_of(TE.Scalars, [](Value *V) { return !V->hasOneUse(); }))
    return false;
  Type *ScalarTy = TE.getMainOp()->getType();
  // TODO: Check if same can be done for the vector types.
  if (!ScalarTy->isIntegerTy())
    return false;
  if (ScalarTy->isVectorTy())
    return false;
  const unsigned Sz = DL->getTypeSizeInBits(ScalarTy);
  const TreeEntry *LhsTE = getOperandEntry(&TE, /*Idx=*/0);
  const TreeEntry *RhsTE = getOperandEntry(&TE, /*Idx=*/1);
  // Lhs should be zext i<stride> to I<sz>.
  if (!(LhsTE->State == TreeEntry::Vectorize &&
        LhsTE->getOpcode() == Instruction::ZExt && !LhsTE->isAltShuffle() &&
        LhsTE->ReorderIndices.empty() && LhsTE->ReuseShuffleIndices.empty() &&
        !MinBWs.contains(LhsTE) &&
        all_of(LhsTE->Scalars, [](Value *V) { return V->hasOneUse(); })))
    return false;
  Type *SrcScalarTy = cast<ZExtInst>(LhsTE->getMainOp())->getSrcTy();
  unsigned Stride = DL->getTypeSizeInBits(SrcScalarTy);
  if (!isPowerOf2_64(Stride) || Stride >= Sz || Sz % Stride != 0 ||
      !isPowerOf2_64(LhsTE->getVectorFactor()))
    return false;
  if (!(RhsTE->isGather() && RhsTE->ReorderIndices.empty() &&
        RhsTE->ReuseShuffleIndices.empty() && !MinBWs.contains(RhsTE)))
    return false;
  Order.clear();
  unsigned CurrentValue = 0;
  // Rhs should be (0, Stride, 2 * Stride, ..., N-Stride), where N <= Sz.
  if (all_of(RhsTE->Scalars,
             [&](Value *V) {
               CurrentValue += Stride;
               if (isa<UndefValue>(V))
                 return true;
               auto *C = dyn_cast<Constant>(V);
               if (!C)
                 return false;
               return C->getUniqueInteger() == CurrentValue - Stride;
             }) &&
      CurrentValue <= Sz) {
    Order.clear();
  } else {
    const unsigned VF = RhsTE->getVectorFactor();
    Order.assign(VF, VF);
    // Track which logical positions we've seen; reject duplicate shift amounts.
    SmallBitVector SeenPositions(VF);
    // Check if need to reorder Rhs to make it in form (0, Stride, 2 * Stride,
    // ..., N-Stride), where N <= Sz.
    if (VF * Stride > Sz)
      return false;
    for (const auto [Idx, V] :
         make_filter_range(enumerate(RhsTE->Scalars), [](const auto &P) {
           return !isa<UndefValue>(P.value());
         })) {
      auto *C = dyn_cast<Constant>(V);
      if (!C)
        return false;
      const APInt &Val = C->getUniqueInteger();
      if (Val.isNegative() || Val.uge(Sz) || Val.getZExtValue() % Stride != 0)
        return false;
      unsigned Pos = Val.getZExtValue() / Stride;
      // TODO: Support Pos >= VF, in this case need to shift the final value.
      if (Order[Idx] != VF || Pos >= VF)
        return false;
      if (SeenPositions.test(Pos))
        return false;
      SeenPositions.set(Pos);
      Order[Idx] = Pos;
    }
    // One of the indices not set - exit.
    if (is_contained(Order, VF))
      return false;
  }
  auto *SrcType = IntegerType::getIntNTy(ScalarTy->getContext(),
                                         Stride * LhsTE->getVectorFactor());
  FastMathFlags FMF;
  SmallPtrSet<Value *, 4> CheckedExtracts;
  auto *VecTy =
      cast<VectorType>(getWidenedType(ScalarTy, TE.getVectorFactor()));
  auto *SrcVecTy =
      cast<VectorType>(getWidenedType(SrcScalarTy, LhsTE->getVectorFactor()));
  TTI::CastContextHint CastCtx =
      getCastContextHint(*getOperandEntry(LhsTE, /*Idx=*/0));
  InstructionCost VecCost =
      TTI->getArithmeticReductionCost(Instruction::Or, VecTy, FMF, CostKind) +
      TTI->getArithmeticInstrCost(Instruction::Shl, VecTy, CostKind,
                                  TTI::getOperandInfo(LhsTE->Scalars),
                                  TTI::getOperandInfo(RhsTE->Scalars), {},
                                  TE.getMainOp()) +
      TTI->getCastInstrCost(
          Instruction::ZExt, VecTy,
          getWidenedType(SrcScalarTy, LhsTE->getVectorFactor()), CastCtx,
          CostKind, LhsTE->getMainOp());
  InstructionCost BitcastCost = TTI->getCastInstrCost(
      Instruction::BitCast, SrcType, SrcVecTy, CastCtx, CostKind);
  if (!Order.empty()) {
    fixupOrderingIndices(Order);
    SmallVector<int> Mask;
    inversePermutation(Order, Mask);
    BitcastCost += getShuffleCost(*TTI, TTI::SK_PermuteSingleSrc, SrcVecTy,
                                  CostKind, Mask);
  }
  // Check if the combination can be modeled as a bitcast+byteswap operation.
  constexpr unsigned ByteSize = 8;
  if (!Order.empty() && isReverseOrder(Order) &&
      DL->getTypeSizeInBits(SrcScalarTy) == ByteSize) {
    IntrinsicCostAttributes CostAttrs(Intrinsic::bswap, SrcType, {SrcType});
    InstructionCost BSwapCost =
        TTI->getCastInstrCost(Instruction::BitCast, SrcType, SrcVecTy, CastCtx,
                              CostKind) +
        TTI->getIntrinsicInstrCost(CostAttrs, CostKind);
    if (BSwapCost <= BitcastCost) {
      BitcastCost = BSwapCost;
      IsBSwap = true;
      Order.clear();
      // Check for loads in the ZExt node.
      const TreeEntry *SrcTE = getOperandEntry(LhsTE, /*Idx=*/0);
      if (SrcTE->State == TreeEntry::Vectorize &&
          SrcTE->ReorderIndices.empty() && SrcTE->ReuseShuffleIndices.empty() &&
          SrcTE->getOpcode() == Instruction::Load && !SrcTE->isAltShuffle() &&
          all_of(SrcTE->Scalars, [](Value *V) { return V->hasOneUse(); })) {
        auto *LI = cast<LoadInst>(SrcTE->getMainOp());
        IntrinsicCostAttributes CostAttrs(Intrinsic::bswap, SrcType, {SrcType});
        InstructionCost BSwapCost =
            TTI->getMemoryOpCost(Instruction::Load, SrcType, LI->getAlign(),
                                 LI->getPointerAddressSpace(), CostKind,
                                 TTI::getOperandInfo(LI->getPointerOperand())) +
            TTI->getIntrinsicInstrCost(CostAttrs, CostKind);
        if (BSwapCost <= BitcastCost) {
          VecCost += TTI->getMemoryOpCost(
              Instruction::Load, SrcVecTy, LI->getAlign(),
              LI->getPointerAddressSpace(), CostKind,
              TTI::getOperandInfo(LI->getPointerOperand()));
          BitcastCost = BSwapCost;
          ForLoads = true;
        }
      }
    }
  } else if (Order.empty() && DL->getTypeSizeInBits(SrcScalarTy) == ByteSize) {
    // Check for loads in the ZExt node.
    const TreeEntry *SrcTE = getOperandEntry(LhsTE, /*Idx=*/0);
    if (SrcTE->State == TreeEntry::Vectorize && SrcTE->ReorderIndices.empty() &&
        SrcTE->ReuseShuffleIndices.empty() &&
        SrcTE->getOpcode() == Instruction::Load && !SrcTE->isAltShuffle() &&
        all_of(SrcTE->Scalars, [](Value *V) { return V->hasOneUse(); })) {
      auto *LI = cast<LoadInst>(SrcTE->getMainOp());
      BitcastCost =
          TTI->getMemoryOpCost(Instruction::Load, SrcType, LI->getAlign(),
                               LI->getPointerAddressSpace(), CostKind,
                               TTI::getOperandInfo(LI->getPointerOperand()));
      VecCost +=
          TTI->getMemoryOpCost(Instruction::Load, SrcVecTy, LI->getAlign(),
                               LI->getPointerAddressSpace(), CostKind,
                               TTI::getOperandInfo(LI->getPointerOperand()));
      ForLoads = true;
    }
  }
  if (SrcType != ScalarTy) {
    BitcastCost += TTI->getCastInstrCost(Instruction::ZExt, ScalarTy, SrcType,
                                         CastCtx, CostKind);
  }
  return BitcastCost < VecCost;
}

std::optional<BitPackInfo>
BoUpSLP::computeBitPackLayout(const TreeEntry &TE) const {
  assert(TE.hasState() &&
         (TE.getOpcode() == Instruction::And ||
          TE.getOpcode() == Instruction::Shl) &&
         "Expected And or Shl node.");
  const unsigned BitWidth = DL->getTypeSizeInBits(TE.getMainOp()->getType());
  const TreeEntry *ShlTE = &TE;
  const TreeEntry *MaskTE = nullptr;
  if (TE.getOpcode() == Instruction::And) {
    MaskTE = getOperandEntry(&TE, 1);
    ShlTE = getOperandEntry(&TE, 0);
  }
  const TreeEntry *ShiftTE = getOperandEntry(ShlTE, 1);
  const TreeEntry *LhsTE = getOperandEntry(ShlTE, 0);

  const unsigned VF = TE.getVectorFactor();
  SmallVector<APInt> PossibleBits(VF), Masks(VF);
  SmallVector<uint64_t> ShlAmts(VF);
  auto IsCopyable = [](const TreeEntry *TE, unsigned Idx) {
    return TE->hasCopyableElements() && TE->isCopyableElement(TE->Scalars[Idx]);
  };
  for (unsigned Idx : seq(VF)) {
    uint64_t ShlAmt = 0;
    const APInt *C;
    if (!IsCopyable(ShlTE, Idx)) {
      if (!match(ShiftTE->Scalars[Idx], m_APInt(C)) || C->uge(BitWidth))
        return std::nullopt;
      ShlAmt = C->getZExtValue();
    }
    APInt Mask = APInt::getAllOnes(BitWidth);
    if (MaskTE && !IsCopyable(&TE, Idx)) {
      if (!match(MaskTE->Scalars[Idx], m_APInt(C)))
        return std::nullopt;
      Mask = *C;
    }
    Value *X = LhsTE->Scalars[Idx];
    if (isa<PoisonValue>(X)) {
      PossibleBits[Idx] = APInt(BitWidth, 0);
    } else {
      PossibleBits[Idx] =
          APInt::getLowBitsSet(BitWidth, getScalarMaxValue(X).getActiveBits()) &
          ~computeKnownBits(X, SimplifyQuery(*DL)).Zero;
    }
    ShlAmts[Idx] = ShlAmt;
    Masks[Idx] = Mask;
  }
  return computeBitPackInfo(BitWidth, PossibleBits, ShlAmts, Masks);
}

const BoUpSLP::TreeEntry *BoUpSLP::getBitPackSource(const TreeEntry &LhsTE,
                                                    BitPackInfo &Info) const {
  // The chain nodes are checked both before and after being combined into the
  // root.
  auto IsChainNode = [](const TreeEntry &TE) {
    return (TE.State == TreeEntry::Vectorize ||
            TE.CombinedOp == TreeEntry::ReducedBitPack) &&
           TE.ReorderIndices.empty() && TE.ReuseShuffleIndices.empty() &&
           !TE.hasCopyableElements() &&
           all_of(TE.Scalars, [](Value *V) { return V->hasOneUse(); });
  };
  const TreeEntry *AndTE = &LhsTE;
  if (AndTE->hasState() && AndTE->getOpcode() == Instruction::ZExt &&
      IsChainNode(*AndTE))
    AndTE = getOperandEntry(AndTE, /*Idx=*/0);
  if (!AndTE->hasState() || AndTE->getOpcode() != Instruction::And ||
      !IsChainNode(*AndTE))
    return &LhsTE;
  const TreeEntry *ShiftTE = getOperandEntry(AndTE, /*Idx=*/0);
  if (!ShiftTE->hasState() ||
      (ShiftTE->getOpcode() != Instruction::LShr &&
       ShiftTE->getOpcode() != Instruction::Shl) ||
      !IsChainNode(*ShiftTE))
    return &LhsTE;
  const TreeEntry *SrcTE = getOperandEntry(ShiftTE, /*Idx=*/0);
  if (SrcTE->State != TreeEntry::Vectorize || !SrcTE->ReorderIndices.empty() ||
      !SrcTE->ReuseShuffleIndices.empty())
    return &LhsTE;
  const unsigned SrcBW = SrcTE->getMainOp()->getType()->getScalarSizeInBits();
  const unsigned FieldWidth = Info.FieldWidth;
  std::optional<uint64_t> UniformOff;
  for (auto [Idx, FieldOff] : enumerate(Info.LShrAmts)) {
    // The and-mask keeps the field bits, which are shifted from the same bits
    // of every source lane.
    Value *Sh;
    const APInt *Mask, *Amt;
    if (FieldOff + FieldWidth > SrcBW ||
        !match(AndTE->Scalars[Idx], m_c_And(m_Value(Sh), m_APInt(Mask))) ||
        !Mask->extractBits(FieldWidth, FieldOff).isAllOnes())
      return &LhsTE;
    uint64_t Off = FieldOff;
    if (match(Sh, m_LShr(m_Specific(SrcTE->Scalars[Idx]), m_APInt(Amt))))
      Off += Amt->getZExtValue();
    else if (match(Sh, m_Shl(m_Specific(SrcTE->Scalars[Idx]), m_APInt(Amt))) &&
             Amt->ule(FieldOff))
      Off -= Amt->getZExtValue();
    else
      return &LhsTE;
    if (Off + FieldWidth > SrcBW || (UniformOff && *UniformOff != Off))
      return &LhsTE;
    UniformOff = Off;
  }
  fill(Info.LShrAmts, *UniformOff);
  return SrcTE;
}

unsigned BoUpSLP::getZExtSrcWidth(const TreeEntry &TE) const {
  if (!TE.hasState() || TE.hasCopyableElements() ||
      TE.getOpcode() != Instruction::ZExt)
    return 0;
  return cast<ZExtInst>(TE.getMainOp())->getSrcTy()->getScalarSizeInBits();
}

bool BoUpSLP::matchesBitPack(const TreeEntry &TE) const {
  assert(TE.hasState() &&
         (TE.getOpcode() == Instruction::And ||
          TE.getOpcode() == Instruction::Shl) &&
         "Expected And or Shl node.");
  auto IsVectorizedOneUseNode = [&](const TreeEntry *N) {
    return N->State == TreeEntry::Vectorize && !N->isAltShuffle() &&
           N->ReorderIndices.empty() && N->ReuseShuffleIndices.empty() &&
           !MinBWs.contains(N) && all_of(N->Scalars, [&](Value *V) {
             return (N->hasCopyableElements() && N->isCopyableElement(V)) ||
                    V->hasOneUse();
           });
  };
  if (!IsVectorizedOneUseNode(&TE))
    return false;
  Type *ScalarTy = TE.getMainOp()->getType();
  if (!ScalarTy->isIntegerTy())
    return false;
  const unsigned BitWidth = DL->getTypeSizeInBits(ScalarTy);
  if (!isPowerOf2_64(BitWidth))
    return false;

  const TreeEntry *ShlTE = &TE;
  const TreeEntry *MaskTE = nullptr;
  if (TE.getOpcode() == Instruction::And) {
    MaskTE = getOperandEntry(&TE, 1);
    ShlTE = getOperandEntry(&TE, 0);
    if (!ShlTE->hasState() || ShlTE->getOpcode() != Instruction::Shl)
      return false;
  }
  if (!IsVectorizedOneUseNode(ShlTE))
    return false;
  const TreeEntry *ShiftTE = getOperandEntry(ShlTE, 1);
  const TreeEntry *LhsTE = getOperandEntry(ShlTE, 0);
  if (!ShiftTE->isGather() || (MaskTE && !MaskTE->isGather()))
    return false;
  // The operand must be emitted as a plain vector in lane order: a vectorized
  // node or a simple gather.
  if ((!LhsTE->isGather() && LhsTE->State != TreeEntry::Vectorize) ||
      (LhsTE->hasState() && LhsTE->isAltShuffle()) ||
      !LhsTE->ReorderIndices.empty() || !LhsTE->ReuseShuffleIndices.empty() ||
      MinBWs.contains(LhsTE))
    return false;
  std::optional<BitPackInfo> Info = computeBitPackLayout(TE);
  if (!Info)
    return false;
  auto *VecTy =
      cast<FixedVectorType>(getWidenedType(ScalarTy, TE.getVectorFactor()));
  FastMathFlags FMF;
  InstructionCost VecCost =
      TTI->getArithmeticReductionCost(Instruction::Or, VecTy, FMF, CostKind) +
      TTI->getArithmeticInstrCost(Instruction::Shl, VecTy, CostKind,
                                  TTI::getOperandInfo(LhsTE->Scalars),
                                  TTI::getOperandInfo(ShiftTE->Scalars),
                                  /*Args=*/{}, ShlTE->getMainOp(), TLI);
  if (TE.getOpcode() == Instruction::And)
    VecCost += TTI->getArithmeticInstrCost(
        Instruction::And, VecTy, CostKind, TTI::getOperandInfo(ShlTE->Scalars),
        TTI::getOperandInfo(MaskTE->Scalars), /*Args=*/{}, TE.getMainOp(), TLI);
  const TreeEntry *SrcTE = getBitPackSource(*LhsTE, *Info);
  auto *SrcTy = cast<FixedVectorType>(
      getWidenedType(SrcTE->Scalars.front()->getType(), TE.getVectorFactor()));
  unsigned ShiftWidth;
  InstructionCost PackCost = getBitPackCost(
      *TTI, SrcTy, ScalarTy, *Info, getZExtSrcWidth(*SrcTE),
      getCastContextHint(*SrcTE), CostKind, TLI, TE.getMainOp(), ShiftWidth);
  return PackCost.isValid() && PackCost <= VecCost;
}

bool BoUpSLP::matchesInversedZExtSelect(
    const TreeEntry &SelectTE,
    SmallVectorImpl<unsigned> &InversedCmpsIndices) const {
  assert(SelectTE.hasState() && SelectTE.getOpcode() == Instruction::Select &&
         "Expected select node.");
  SmallVector<std::pair<Instruction *, unsigned>> ZExts;
  for (auto [Idx, V] : enumerate(SelectTE.Scalars)) {
    auto *Inst = dyn_cast<Instruction>(V);
    if (!Inst || Inst->getOpcode() != Instruction::ZExt)
      continue;
    ZExts.emplace_back(Inst, Idx);
  }
  if (ZExts.empty())
    return false;
  const auto *CmpTE = getOperandEntry(&SelectTE, 0);
  const auto *Op1TE = getOperandEntry(&SelectTE, 1);
  const auto *Op2TE = getOperandEntry(&SelectTE, 2);
  // Compares must be alternate vectorized, and other operands must be gathers
  // or copyables.
  // TODO: investigate opportunity for reordered/reused nodes.
  if (CmpTE->State != TreeEntry::Vectorize || !CmpTE->isAltShuffle() ||
      (CmpTE->getOpcode() != Instruction::ICmp &&
       CmpTE->getOpcode() != Instruction::FCmp) ||
      !CmpTE->ReorderIndices.empty() || !CmpTE->ReuseShuffleIndices.empty() ||
      !Op1TE->ReorderIndices.empty() || !Op1TE->ReuseShuffleIndices.empty() ||
      !Op2TE->ReorderIndices.empty() || !Op2TE->ReuseShuffleIndices.empty())
    return false;
  // The operands must be buildvectors/copyables.
  if (!Op1TE->isGather() || !Op2TE->isGather())
    return false;
  // TODO: investigate opportunity for the vector nodes with copyables.
  auto *Cmp = CmpTE->getMainOp();
  CmpPredicate Pred;
  auto MatchCmp = m_Cmp(Pred, m_Value(), m_Value());
  if (!match(Cmp, MatchCmp))
    return false;
  // The vector compare keeps the main predicate, so only the lanes with
  // samesign may match it with the flipped signedness.
  CmpPredicate MainPred = Pred.dropSameSign();
  CmpPredicate InversedPred = CmpInst::getInversePredicate(Pred);
  for (const auto [Idx, V] :
       make_filter_range(enumerate(CmpTE->Scalars), [&](const auto &P) {
         return match(P.value(), MatchCmp);
       })) {
    if (CmpPredicate::getMatching(MainPred, Pred))
      continue;
    if (!CmpPredicate::getMatching(InversedPred, Pred))
      return false;
    if (!V->hasOneUse())
      return false;
    InversedCmpsIndices.push_back(Idx);
  }

  if (InversedCmpsIndices.empty())
    return false;
  Type *VecTy =
      getWidenedType(Cmp->getOperand(0)->getType(), CmpTE->getVectorFactor());
  Type *CmpTy = CmpInst::makeCmpResultType(VecTy);

  InstructionCost VecCost = TTI->getCmpSelInstrCost(
      CmpTE->getOpcode(), VecTy, CmpTy, MainPred, CostKind,
      TTI::getOperandInfo(CmpTE->getOperand(0)),
      TTI::getOperandInfo(CmpTE->getOperand(1)), CmpTE->getMainOp());
  InstructionCost BVCost = getScalarizationOverhead(
      *TTI, Opts.slp_revec, Cmp->getType(), cast<VectorType>(CmpTy),
      APInt::getAllOnes(CmpTE->getVectorFactor()),
      /*Insert=*/true, /*Extract=*/false, CostKind);
  for (Instruction *I : make_isa_range<Instruction>(CmpTE->Scalars))
    BVCost += TTI->getInstructionCost(I, CostKind);
  return VecCost < BVCost;
}

bool BoUpSLP::matchesSelectOfBits(const TreeEntry &SelectTE) const {
  assert(SelectTE.hasState() && SelectTE.getOpcode() == Instruction::Select &&
         "Expected select node.");
  if (DL->isBigEndian())
    return false;
  if (!SelectTE.ReorderIndices.empty() || !SelectTE.ReuseShuffleIndices.empty())
    return false;
  if (!UserIgnoreList || SelectTE.Idx != 0)
    return false;
  if (any_of(SelectTE.Scalars, [](Value *V) { return !V->hasOneUse(); }))
    return false;
  // Check that all reduction operands are or instructions.
  if (any_of(*UserIgnoreList,
             [](Value *V) { return !match(V, m_Or(m_Value(), m_Value())); }))
    return false;
  const TreeEntry *Op1TE = getOperandEntry(&SelectTE, 1);
  const TreeEntry *Op2TE = getOperandEntry(&SelectTE, 2);
  if (!Op1TE->isGather() || !Op2TE->isGather())
    return false;
  // No need to check for zeroes reordering.
  if (!Op1TE->ReorderIndices.empty() || !Op1TE->ReuseShuffleIndices.empty() ||
      !Op2TE->ReuseShuffleIndices.empty())
    return false;
  Type *ScalarTy = Op1TE->Scalars.front()->getType();
  if (!ScalarTy->isIntegerTy())
    return false;
  // Check that second operand is all zeroes.
  if (any_of(Op2TE->Scalars, [](Value *V) { return !match(V, m_ZeroInt()); }))
    return false;
  // Check that first operand is 1,2,4,...
  if (any_of(enumerate(Op1TE->Scalars), [](const auto &P) {
        uint64_t V;
        return !(match(P.value(), m_ConstantInt(V)) && isPowerOf2_64(V) &&
                 Log2_64(V) == P.index());
      }))
    return false;
  // Check if bitcast is cheaper than select.
  auto *DstTy = IntegerType::getIntNTy(ScalarTy->getContext(),
                                       SelectTE.getVectorFactor());
  Type *OpTy = getWidenedType(DstTy, SelectTE.getVectorFactor());
  Type *CmpTy = CmpInst::makeCmpResultType(OpTy);
  auto *VecTy =
      cast<VectorType>(getWidenedType(ScalarTy, SelectTE.getVectorFactor()));
  auto It = MinBWs.find(&SelectTE);
  if (It != MinBWs.end()) {
    auto *EffectiveScalarTy =
        IntegerType::get(F->getContext(), It->second.first);
    VecTy = cast<VectorType>(
        getWidenedType(EffectiveScalarTy, SelectTE.getVectorFactor()));
  }
  InstructionCost BitcastCost = TTI->getCastInstrCost(
      Instruction::BitCast, DstTy, CmpTy, TTI::CastContextHint::None, CostKind);
  if (DstTy != ScalarTy) {
    BitcastCost += TTI->getCastInstrCost(Instruction::ZExt, ScalarTy, DstTy,
                                         TTI::CastContextHint::None, CostKind);
  }
  // Use the condition predicate shared by all lanes, if there is one.
  CmpPredicate SelPred = CmpInst::BAD_ICMP_PREDICATE;
  CmpPredicate P;
  if (match(SelectTE.getMainOp(),
            m_Select(m_ICmp(P, m_Value(), m_Value()), m_Value(), m_Value())) &&
      all_of(SelectTE.Scalars, [&](Value *V) {
        CmpPredicate LaneP;
        return match(V, m_Select(m_ICmp(LaneP, m_Value(), m_Value()), m_Value(),
                                 m_Value())) &&
               LaneP == P.dropSameSign();
      }))
    SelPred = P;

  FastMathFlags FMF;
  InstructionCost SelectCost =
      TTI->getCmpSelInstrCost(Instruction::Select, VecTy, CmpTy, SelPred,
                              CostKind, TTI::getOperandInfo(Op1TE->Scalars),
                              TTI::getOperandInfo(Op2TE->Scalars),
                              SelectTE.getMainOp()) +
      TTI->getArithmeticReductionCost(Instruction::Or, VecTy, FMF, CostKind);
  return BitcastCost <= SelectCost;
}

void BoUpSLP::transformNodes() {
  BaseGraphSize = VectorizableTree.size();
  // Turn graph transforming mode on and off, when done.
  class GraphTransformModeRAAI {
    bool &SavedIsGraphTransformMode;

  public:
    GraphTransformModeRAAI(bool &IsGraphTransformMode)
        : SavedIsGraphTransformMode(IsGraphTransformMode) {
      IsGraphTransformMode = true;
    }
    ~GraphTransformModeRAAI() { SavedIsGraphTransformMode = false; }
  } TransformContext(IsGraphTransformMode);
  // Operands are profitable if they are:
  // 1. At least one constant
  // or
  // 2. Splats
  // or
  // 3. Results in good vectorization opportunity, i.e. may generate vector
  // nodes and reduce cost of the graph.
  auto CheckOperandsProfitability = [this](Instruction *I1, Instruction *I2,
                                           const InstructionsState &S) {
    SmallVector<SmallVector<std::pair<Value *, Value *>>> Candidates;
    for (unsigned Op : seq<unsigned>(S.getMainOp()->getNumOperands()))
      Candidates.emplace_back().emplace_back(I1->getOperand(Op),
                                             I2->getOperand(Op));
    return all_of(Candidates, [this](
                                  ArrayRef<std::pair<Value *, Value *>> Cand) {
      return all_of(Cand,
                    [](const std::pair<Value *, Value *> &P) {
                      return isa<Constant>(P.first) ||
                             isa<Constant>(P.second) || P.first == P.second;
                    }) ||
             findBestRootPair(Cand, LookAheadHeuristics::ScoreSplatLoads).first;
    });
  };

  // The reduction root gather feeds only the commutative reduction, which
  // maps the reduced values to the lanes by the root scalars. Put the distinct
  // sub-fields of the same wider scalar in the natural order to emit them
  // without a permutation.
  if (UserIgnoreList && getRootNode().isGather() &&
      getRootNode().ReuseShuffleIndices.empty())
    if (std::optional<std::tuple<Value *, unsigned, SmallVector<int>>> Fields =
            matchGatheredExtractedFields(getRootNode().Scalars, *DL)) {
      auto &[Src, FieldWidth, Mask] = *Fields;
      SmallVector<int> SortedMask(Mask);
      sort(SortedMask);
      if (equal(SortedMask,
                seq<int>(Src->getType()->getIntegerBitWidth() / FieldWidth)))
        reorderScalars(getRootNode().Scalars, Mask);
    }

  // Try to reorder gather nodes for better vectorization opportunities.
  for (unsigned Idx : seq<unsigned>(BaseGraphSize)) {
    TreeEntry &E = *VectorizableTree[Idx];
    if (E.isGather())
      reorderGatherNode(E);
  }

  // Better to use full gathered loads analysis, if there are only 2 loads
  // gathered nodes each having less than 16 elements.
  constexpr unsigned VFLimit = 16;
  bool ForceLoadGather =
      count_if(VectorizableTree, [&](const std::unique_ptr<TreeEntry> &TE) {
        return TE->isGather() && TE->hasState() &&
               TE->getOpcode() == Instruction::Load &&
               TE->getVectorFactor() < VFLimit;
      }) == 2;

  // Checks if the scalars are used in other node.
  auto AreReusedScalars = [&](const TreeEntry *TE, ArrayRef<Value *> VL,
                              function_ref<bool(Value *)> CheckContainer) {
    return TE->isSame(VL) || all_of(VL, [&](Value *V) {
             if (isa<PoisonValue>(V))
               return true;
             auto *I = dyn_cast<Instruction>(V);
             if (!I)
               return false;
             return is_contained(TE->Scalars, I) || CheckContainer(I);
           });
  };
  auto CheckForSameVectorNodes = [&](const TreeEntry &E) {
    if (E.hasState()) {
      if (ArrayRef<TreeEntry *> TEs = getTreeEntries(E.getMainOp());
          !TEs.empty() && any_of(TEs, [&](const TreeEntry *TE) {
            return AreReusedScalars(TE, E.Scalars, [&](Value *V) {
              ArrayRef<TreeEntry *> VTEs = getTreeEntries(V);
              return !VTEs.empty() && any_of(VTEs, [&](const TreeEntry *TE) {
                return is_contained(TEs, TE);
              });
            });
          }))
        return true;
      ;
      if (ArrayRef<TreeEntry *> TEs = getSplitTreeEntries(E.getMainOp());
          !TEs.empty() && any_of(TEs, [&](const TreeEntry *TE) {
            return AreReusedScalars(TE, E.Scalars, [&](Value *V) {
              ArrayRef<TreeEntry *> VTEs = getSplitTreeEntries(V);
              return !VTEs.empty() && any_of(VTEs, [&](const TreeEntry *TE) {
                return is_contained(TEs, TE);
              });
            });
          }))
        return true;
    } else {
      // Check if the gather node full copy of split node.
      auto *It = find_if(E.Scalars, IsaPred<Instruction>);
      if (It != E.Scalars.end()) {
        if (ArrayRef<TreeEntry *> TEs = getSplitTreeEntries(*It);
            !TEs.empty() && any_of(TEs, [&](const TreeEntry *TE) {
              return AreReusedScalars(TE, E.Scalars, [&](Value *V) {
                ArrayRef<TreeEntry *> VTEs = getSplitTreeEntries(V);
                return !VTEs.empty() && any_of(VTEs, [&](const TreeEntry *TE) {
                  return is_contained(TEs, TE);
                });
              });
            }))
          return true;
      }
    }
    return false;
  };
  // Marks the fadd/fsub node \p E as fmuladd, if its fmul operand is fused
  // into it.
  auto CombineFMulAdd = [&](TreeEntry &E) {
    // Check if possible to convert (a*b)+c to fma; fma takes exactly two
    // operands, so bail out on reassociated (>2-operand) nodes.
    if (E.State != TreeEntry::Vectorize ||
        !E.getOperations().isAddSubLikeOp() ||
        E.getOperations().isAltShuffle() || E.getNumOperands() != 2)
      return;
    const TreeEntry *LHS = getOperandEntry(&E, 0);
    const TreeEntry *RHS = getOperandEntry(&E, 1);
    auto IsOneUseVectorFMulOperand = [](const TreeEntry *TE) {
      return TE->State == TreeEntry::Vectorize && TE->ReorderIndices.empty() &&
             TE->ReuseShuffleIndices.empty() &&
             TE->getOpcode() == Instruction::FMul && !TE->isAltShuffle() &&
             all_of(TE->Scalars, [&](Value *V) {
               return (TE->hasCopyableElements() && TE->isCopyableElement(V)) ||
                      V->hasOneUse();
             });
    };
    // Both a*b - c and c - a*b are fused.
    const bool IsLHSFMul = IsOneUseVectorFMulOperand(LHS);
    if (!IsLHSFMul && !IsOneUseVectorFMulOperand(RHS))
      return;
    if (!canConvertToFMA(E.Scalars, E.getOperations(), *DT, *DL, *TTI, *TLI,
                         *this)
             .isValid())
      return;
    // This node is a fmuladd node.
    E.CombinedOp = TreeEntry::FMulAdd;
    TreeEntry *FMulEntry = getOperandEntry(&E, IsLHSFMul ? 0 : 1);
    if (FMulEntry->UserTreeIndex && FMulEntry->State == TreeEntry::Vectorize) {
      // The FMul node is part of the combined fmuladd node.
      FMulEntry->State = TreeEntry::CombinedVectorize;
    }
  };
  // The tree may grow here, so iterate over nodes, built before.
  for (unsigned Idx : seq<unsigned>(BaseGraphSize)) {
    TreeEntry &E = *VectorizableTree[Idx];
    if (E.isGather()) {
      ArrayRef<Value *> VL = E.Scalars;
      const unsigned Sz = getVectorElementSize(VL.front());
      unsigned MinVF = getMinVF(2 * Sz);
      // Do not try partial vectorization for small nodes (<= 2), nodes with the
      // same opcode and same parent block or all constants.
      if (VL.size() <= 2 || LoadEntriesToVectorize.contains(Idx) ||
          !(!E.hasState() || E.getOpcode() == Instruction::Load ||
            // We use allSameOpcode instead of isAltShuffle because we don't
            // want to use interchangeable instruction here.
            !allSameOpcode(VL) || !allSameBlock(VL)) ||
          allConstant(VL) || isSplat(VL) ||
          (E.ReuseShuffleIndices.empty() &&
           matchGatheredExtractedFields(VL, *DL)))
        continue;
      if (ForceLoadGather && E.hasState() && E.getOpcode() == Instruction::Load)
        continue;
      // Check if the node is a copy of other vector nodes.
      if (CheckForSameVectorNodes(E))
        continue;
      // Try to find vectorizable sequences and transform them into a series of
      // insertvector instructions.
      unsigned StartIdx = 0;
      unsigned End = VL.size();
      SmallBitVector Processed(End);
      for (unsigned VF = getFloorFullVectorNumberOfElements(
               *TTI, VL.front()->getType(), VL.size() - 1, Opts.slp_revec);
           VF >= MinVF;
           VF = getFloorFullVectorNumberOfElements(*TTI, VL.front()->getType(),
                                                   VF - 1, Opts.slp_revec)) {
        if (StartIdx + VF > End)
          continue;
        SmallVector<std::pair<unsigned, unsigned>> Slices;
        bool AllStrided = true;
        // Walk the range in steps of VF, but allow the trailing slice to be
        // shorter (SliceVF < VF) so non-power-of-2 tails can be vectorized.
        // Processed only records slice starts (Cnt), and downstream consumers
        // (test(Cnt), AddCombinedNode's range set/StartIdx update) operate on
        // start positions, so partial coverage is consistent.
        for (unsigned Cnt = StartIdx; Cnt < End; Cnt += VF) {
          const unsigned SliceVF = std::min(VF, End - Cnt);
          if (SliceVF <= 1)
            continue;
          ArrayRef<Value *> Slice = VL.slice(Cnt, SliceVF);
          // If any instruction is vectorized already - do not try again.
          // Reuse the existing node, if it fully matches the slice.
          if ((Processed.test(Cnt) || isVectorized(Slice.front())) &&
              !getSameValuesTreeEntry(Slice.front(), Slice, /*SameVF=*/true))
            continue;
          // Constant already handled effectively - skip.
          if (allConstant(Slice))
            continue;
          // Do not try to vectorize small splats (less than vector register and
          // only with the single non-undef element).
          bool IsSplat = isSplat(Slice);
          bool IsTwoRegisterSplat = true;
          if (IsSplat && VF == 2) {
            unsigned NumRegs2VF = getNumberOfParts(
                getWidenedType(getValueType(Slice.front(), Opts.slp_revec),
                               2 * VF),
                getValueType(Slice.front(), Opts.slp_revec));
            IsTwoRegisterSplat = NumRegs2VF == 2;
          }
          if (Slices.empty() || !IsSplat || !IsTwoRegisterSplat ||
              count(Slice, Slice.front()) ==
                  static_cast<long>(isa<UndefValue>(Slice.front()) ? SliceVF - 1
                                                                   : 1)) {
            if (IsSplat)
              continue;
            InstructionsState S = getSameOpcode(Slice, *TLI);
            if (!S || !allSameOpcode(Slice) || !allSameBlock(Slice) ||
                (S.getOpcode() == Instruction::Load &&
                 areKnownNonVectorizableLoads(Slice)))
              continue;
            if (VF == 2) {
              // Cache the cost check lazily - both branches below may need it.
              std::optional<bool> MainOpIsCheap;
              auto IsMainOpCheap = [&, TTI = TTI] {
                if (!MainOpIsCheap)
                  MainOpIsCheap =
                      TTI->getInstructionCost(S.getMainOp(), CostKind) <
                      TTI::TCC_Expensive;
                return *MainOpIsCheap;
              };
              // Try to vectorize reduced values or if all users are vectorized.
              // For expensive instructions extra extracts might be profitable.
              if ((!UserIgnoreList || E.Idx != 0) && IsMainOpCheap() &&
                  !all_of(make_isa_range<Instruction>(Slice),
                          [&](Instruction *I) {
                            return areAllUsersVectorized(I, UserIgnoreList);
                          }))
                continue;
              if (S.getOpcode() == Instruction::Load) {
                OrdersType Order;
                SmallVector<Value *> PointerOps;
                StridedPtrInfo SPtrInfo;
                LoadsState Res = canVectorizeLoads(Slice, Slice.front(), Order,
                                                   PointerOps, SPtrInfo);
                AllStrided &= Res == LoadsState::StridedVectorize ||
                              Res == LoadsState::ScatterVectorize ||
                              Res == LoadsState::Gather;
                // Do not vectorize gathers.
                if (Res == LoadsState::ScatterVectorize ||
                    Res == LoadsState::Gather) {
                  if (Res == LoadsState::Gather) {
                    registerNonVectorizableLoads(Slice);
                    // If reductions and the scalars from the root node are
                    // analyzed - mark as non-vectorizable reduction.
                    if (UserIgnoreList && E.Idx == 0)
                      analyzedReductionVals(Slice);
                  }
                  continue;
                }
              } else if (S.getOpcode() == Instruction::ExtractElement ||
                         (IsMainOpCheap() &&
                          !CheckOperandsProfitability(
                              S.getMainOp(),
                              cast<Instruction>(*find_if(reverse(Slice),
                                                         IsaPred<Instruction>)),
                              S))) {
                // Do not vectorize extractelements (handled effectively
                // alread). Do not vectorize non-profitable instructions (with
                // low cost and non-vectorizable operands.)
                continue;
              }
            }
          }
          Slices.emplace_back(Cnt, Slice.size());
        }
        // Do not try to vectorize if all slides are strided or gathered with
        // vector factor 2 and there are more than 2 slices. Better to handle
        // them in gathered loads analysis, may result in better vectorization.
        if (VF == 2 && AllStrided && Slices.size() > 2)
          continue;
        auto AddCombinedNode = [&](unsigned Idx, unsigned Cnt, unsigned Sz) {
          E.CombinedEntriesWithIndices.emplace_back(Idx, Cnt);
          Processed.set(Cnt, Cnt + Sz);
          if (StartIdx == Cnt)
            StartIdx = Cnt + Sz;
          if (End == Cnt + Sz)
            End = Cnt;
        };
        for (auto [Cnt, Sz] : Slices) {
          ArrayRef<Value *> Slice = VL.slice(Cnt, Sz);
          const TreeEntry *SameTE = nullptr;
          if (const auto *It = find_if(Slice, IsaPred<Instruction>);
              It != Slice.end()) {
            // If any instruction is vectorized already - do not try again.
            SameTE = getSameValuesTreeEntry(*It, Slice);
          }
          unsigned PrevSize = VectorizableTree.size();
          [[maybe_unused]] unsigned PrevEntriesSize =
              LoadEntriesToVectorize.size();
          buildTreeRec(Slice, 0, EdgeInfo(&E, UINT_MAX));
          if (PrevSize + 1 == VectorizableTree.size() && !SameTE &&
              VectorizableTree[PrevSize]->isGather() &&
              VectorizableTree[PrevSize]->hasState() &&
              VectorizableTree[PrevSize]->getOpcode() !=
                  Instruction::ExtractElement &&
              !isSplat(Slice)) {
            if (UserIgnoreList && E.Idx == 0 && VF == 2)
              analyzedReductionVals(Slice);
            VectorizableTree.pop_back();
            assert(PrevEntriesSize == LoadEntriesToVectorize.size() &&
                   "LoadEntriesToVectorize expected to remain the same");
            continue;
          }
          AddCombinedNode(PrevSize, Cnt, Sz);
        }
      }
      // Restore ordering, if no extra vectorization happened.
      if (E.CombinedEntriesWithIndices.empty() && !E.ReorderIndices.empty()) {
        SmallVector<int> Mask(E.ReorderIndices.begin(), E.ReorderIndices.end());
        reorderScalars(E.Scalars, Mask);
        E.ReorderIndices.clear();
      }
    }
    if (!E.hasState())
      continue;
    switch (E.getOpcode()) {
    case Instruction::Load: {
      // No need to reorder masked gather loads, just reorder the scalar
      // operands.
      // Lanes without a load would break the common alignment below.
      if (E.State != TreeEntry::Vectorize ||
          any_of(E.Scalars, IsaPred<UndefValue>))
        break;
      Type *ScalarTy = E.getMainOp()->getType();
      auto *VecTy =
          cast<FixedVectorType>(getWidenedType(ScalarTy, E.Scalars.size()));
      Align CommonAlignment = computeCommonAlignment<LoadInst>(E.Scalars);
      // Check if profitable to represent consecutive load + reverse as strided
      // load with stride -1.
      if (E.isReverse() &&
          TTI->isLegalStridedLoadStore(VecTy, CommonAlignment)) {
        SmallVector<int> Mask;
        inversePermutation(E.ReorderIndices, Mask);
        auto *BaseLI = cast<LoadInst>(E.Scalars.back());
        InstructionCost OriginalVecCost =
            TTI->getMemoryOpCost(
                Instruction::Load, VecTy, BaseLI->getAlign(),
                BaseLI->getPointerAddressSpace(), CostKind,
                TTI::getOperandInfo(BaseLI->getPointerOperand())) +
            getShuffleCost(*TTI, TTI::SK_Reverse, VecTy, CostKind, Mask);
        Type *StrideTy = DL->getIndexType(BaseLI->getPointerOperandType());
        InstructionCost StridedCost = TTI->getMemIntrinsicInstrCost(
            MemIntrinsicCostAttributes(
                Intrinsic::experimental_vp_strided_load, VecTy,
                BaseLI->getPointerOperand(),
                /*VariableMask=*/false, CommonAlignment, BaseLI,
                ConstantInt::getSigned(
                    StrideTy,
                    -static_cast<int64_t>(DL->getTypeAllocSize(ScalarTy)))),
            CostKind);
        if (StridedCost < OriginalVecCost || Opts.slp_force_strided_loads) {
          // Strided load is more profitable than consecutive load + reverse -
          // transform the node to strided load.
          StridedPtrInfo SPtrInfo;
          SPtrInfo.StrideVal = ConstantInt::get(StrideTy, 1);
          SPtrInfo.Ty = VecTy;
          TreeEntryToStridedPtrInfoMap[&E] = SPtrInfo;
          E.State = TreeEntry::StridedVectorize;
        }
      }
      break;
    }
    case Instruction::Store: {
      if (E.State == TreeEntry::ExpandVectorize)
        break;
      Type *ScalarTy =
          cast<StoreInst>(E.getMainOp())->getValueOperand()->getType();
      auto *VecTy =
          cast<FixedVectorType>(getWidenedType(ScalarTy, E.Scalars.size()));
      Align CommonAlignment = computeCommonAlignment<StoreInst>(E.Scalars);
      // Check if profitable to represent consecutive load + reverse as strided
      // load with stride -1.
      if (E.isReverse() &&
          TTI->isLegalStridedLoadStore(VecTy, CommonAlignment)) {
        SmallVector<int> Mask;
        inversePermutation(E.ReorderIndices, Mask);
        auto *BaseSI = cast<StoreInst>(E.Scalars.back());
        InstructionCost OriginalVecCost =
            TTI->getMemoryOpCost(Instruction::Store, VecTy, BaseSI->getAlign(),
                                 BaseSI->getPointerAddressSpace(), CostKind,
                                 TTI::getOperandInfo(E.getOperand(0))) +
            getShuffleCost(*TTI, TTI::SK_Reverse, VecTy, CostKind, Mask);
        Type *StrideTy = DL->getIndexType(BaseSI->getPointerOperandType());
        InstructionCost StridedCost = TTI->getMemIntrinsicInstrCost(
            MemIntrinsicCostAttributes(
                Intrinsic::experimental_vp_strided_store, VecTy,
                BaseSI->getPointerOperand(),
                /*VariableMask=*/false, CommonAlignment, BaseSI,
                ConstantInt::getSigned(
                    StrideTy,
                    -static_cast<int64_t>(DL->getTypeAllocSize(ScalarTy)))),
            CostKind);
        if (StridedCost < OriginalVecCost) {
          // Strided store is more profitable than reverse + consecutive store -
          // transform the node to strided store.
          E.State = TreeEntry::StridedVectorize;
          StridedPtrInfo SPtrInfo;
          SPtrInfo.StrideVal = ConstantInt::getSigned(StrideTy, -1);
          SPtrInfo.Ty = VecTy;
          TreeEntryToStridedPtrInfoMap[&E] = SPtrInfo;
        }
      } else if (!E.ReorderIndices.empty()) {
        // Check for interleaved stores.
        auto IsInterleaveMask = [&, &TTI = *TTI](ArrayRef<int> Mask) {
          auto *BaseSI = cast<StoreInst>(E.Scalars.front());
          assert(Mask.size() > 1 && "Expected mask greater than 1 element.");
          if (Mask.size() < 4)
            return 0u;
          for (unsigned Factor : seq<unsigned>(2, Mask.size() / 2 + 1)) {
            if (ShuffleVectorInst::isInterleaveMask(
                    Mask, Factor, VecTy->getElementCount().getFixedValue()) &&
                TTI.isLegalInterleavedAccessType(
                    VecTy, Factor, BaseSI->getAlign(),
                    BaseSI->getPointerAddressSpace()))
              return Factor;
          }

          return 0u;
        };
        SmallVector<int> Mask(E.ReorderIndices.begin(), E.ReorderIndices.end());
        unsigned InterleaveFactor = IsInterleaveMask(Mask);
        if (InterleaveFactor != 0)
          E.setInterleave(InterleaveFactor);
      }
      break;
    }
    case Instruction::Select: {
      if (E.State != TreeEntry::Vectorize)
        break;
      auto [MinMaxID, SelectOnly] = canConvertToMinOrMaxIntrinsic(E.Scalars);
      if (MinMaxID != Intrinsic::not_intrinsic) {
        // This node is a minmax node.
        E.CombinedOp = TreeEntry::MinMax;
        TreeEntry *CondEntry = getOperandEntry(&E, 0);
        if (SelectOnly && CondEntry->UserTreeIndex &&
            CondEntry->State == TreeEntry::Vectorize) {
          // The condition node is part of the combined minmax node.
          CondEntry->State = TreeEntry::CombinedVectorize;
        }
        break;
      }
      // Check for zext + selects, which can be reordered.
      SmallVector<unsigned> InversedCmpsIndices;
      if (matchesInversedZExtSelect(E, InversedCmpsIndices)) {
        auto *CmpTE = getOperandEntry(&E, 0);
        auto *Op1TE = getOperandEntry(&E, 1);
        auto *Op2TE = getOperandEntry(&E, 2);
        // State now is uniform, not alternate opcode.
        CmpTE->setOperations(
            InstructionsState(CmpTE->getMainOp(), CmpTE->getMainOp()));
        // Update mapping between the swapped values and their internal matching
        // nodes.
        auto UpdateGatherEntry = [&](TreeEntry *OldTE, TreeEntry *NewTE,
                                     Value *V) {
          if (isConstant(V))
            return;
          auto It = ValueToGatherNodes.find(V);
          assert(It != ValueToGatherNodes.end() &&
                 "Expected to find the value in the map.");
          auto &C = It->getSecond();
          if (!is_contained(OldTE->Scalars, V))
            C.remove(OldTE);
          C.insert(NewTE);
        };
        ValueList &Op1 = E.getOperand(1);
        ValueList &Op2 = E.getOperand(2);
        for (const unsigned Idx : InversedCmpsIndices) {
          Value *V1 = Op1TE->Scalars[Idx];
          Value *V2 = Op2TE->Scalars[Idx];
          std::swap(Op1TE->Scalars[Idx], Op2TE->Scalars[Idx]);
          std::swap(Op1[Idx], Op2[Idx]);
          UpdateGatherEntry(Op1TE, Op2TE, V1);
          UpdateGatherEntry(Op2TE, Op1TE, V2);
        }
        OperandsToTreeEntry.emplace_or_assign(std::make_pair(&E, 1), Op1TE);
        OperandsToTreeEntry.emplace_or_assign(std::make_pair(&E, 2), Op2TE);
        // NB: Fallback to check if select can be converted to cmp bitcast.
      }
      if (matchesSelectOfBits(E)) {
        // This node is a (reduced or) cmp bitcast node.
        const TreeEntry::CombinedOpcode Code = TreeEntry::ReducedCmpBitcast;
        E.CombinedOp = Code;
        auto *Op1TE = getOperandEntry(&E, 1);
        auto *Op2TE = getOperandEntry(&E, 2);
        Op1TE->State = TreeEntry::CombinedVectorize;
        Op1TE->CombinedOp = Code;
        Op2TE->State = TreeEntry::CombinedVectorize;
        Op2TE->CombinedOp = Code;
        break;
      }
      break;
    }
    case Instruction::FSub:
    case Instruction::FAdd:
      CombineFMulAdd(E);
      break;
    case Instruction::Shl:
    case Instruction::And: {
      // Shl/And are not reassociated; guard since this case indexes operands
      // 0/1.
      if (E.getNumOperands() != 2)
        break;
      if (E.Idx != 0 || DL->isBigEndian())
        break;
      if (!UserIgnoreList)
        break;
      // Check that all reduction operands are disjoint or instructions.
      if (E.getOpcode() == Instruction::Shl &&
          all_of(*UserIgnoreList, [](Value *V) {
            return match(V, m_DisjointOr(m_Value(), m_Value()));
          })) {
        OrdersType Order;
        bool IsBSwap;
        bool ForLoads;
        if (matchesShlZExt(E, Order, IsBSwap, ForLoads)) {
          // This node is a (reduced disjoint or) bitcast node.
          TreeEntry::CombinedOpcode Code =
              IsBSwap ? (ForLoads ? TreeEntry::ReducedBitcastBSwapLoads
                                  : TreeEntry::ReducedBitcastBSwap)
                      : (ForLoads ? TreeEntry::ReducedBitcastLoads
                                  : TreeEntry::ReducedBitcast);
          E.CombinedOp = Code;
          E.ReorderIndices = std::move(Order);
          TreeEntry *ZExtEntry = getOperandEntry(&E, 0);
          assert(ZExtEntry->UserTreeIndex &&
                 ZExtEntry->State == TreeEntry::Vectorize &&
                 ZExtEntry->getOpcode() == Instruction::ZExt &&
                 "Expected ZExt node.");
          // The ZExt node is part of the combined node.
          ZExtEntry->State = TreeEntry::CombinedVectorize;
          ZExtEntry->CombinedOp = Code;
          if (ForLoads) {
            TreeEntry *LoadsEntry = getOperandEntry(ZExtEntry, 0);
            assert(LoadsEntry->UserTreeIndex &&
                   LoadsEntry->State == TreeEntry::Vectorize &&
                   LoadsEntry->getOpcode() == Instruction::Load &&
                   "Expected Load node.");
            // The Load node is part of the combined node.
            LoadsEntry->State = TreeEntry::CombinedVectorize;
            LoadsEntry->CombinedOp = Code;
          }
          TreeEntry *ConstEntry = getOperandEntry(&E, 1);
          assert(ConstEntry->UserTreeIndex && ConstEntry->isGather() &&
                 "Expected constants only.");
          // The ConstNode node is part of the combined node.
          ConstEntry->State = TreeEntry::CombinedVectorize;
          ConstEntry->CombinedOp = Code;
          break;
        }
      }
      // Check that all reduction operands are or instructions.
      if (any_of(*UserIgnoreList, [](Value *V) {
            return !match(V, m_Or(m_Value(), m_Value()));
          }))
        break;
      if (!matchesBitPack(E))
        break;
      // This node is a (reduced or) bit pack node.
      E.CombinedOp = TreeEntry::ReducedBitPack;
      TreeEntry *ShlEntry = &E;
      if (E.getOpcode() == Instruction::And) {
        ShlEntry = getOperandEntry(&E, 0);
        assert(ShlEntry->UserTreeIndex &&
               ShlEntry->State == TreeEntry::Vectorize &&
               ShlEntry->getOpcode() == Instruction::Shl &&
               "Expected Shl node.");
        // The Shl node is part of the combined node.
        ShlEntry->State = TreeEntry::CombinedVectorize;
        ShlEntry->CombinedOp = TreeEntry::ReducedBitPack;
        TreeEntry *MaskEntry = getOperandEntry(&E, 1);
        assert(MaskEntry->UserTreeIndex && MaskEntry->isGather() &&
               "Expected constants only.");
        MaskEntry->State = TreeEntry::CombinedVectorize;
        MaskEntry->CombinedOp = TreeEntry::ReducedBitPack;
      }
      TreeEntry *ShiftEntry = getOperandEntry(ShlEntry, 1);
      assert(ShiftEntry->UserTreeIndex && ShiftEntry->isGather() &&
             "Expected constants only.");
      ShiftEntry->State = TreeEntry::CombinedVectorize;
      ShiftEntry->CombinedOp = TreeEntry::ReducedBitPack;
      // The chain of a uniform field extract and its constant operands are
      // part of the combined node.
      std::optional<BitPackInfo> Info = computeBitPackLayout(E);
      TreeEntry *LhsTE = getOperandEntry(ShlEntry, /*Idx=*/0);
      const TreeEntry *SrcTE = getBitPackSource(*LhsTE, *Info);
      for (TreeEntry *ChainTE = LhsTE; ChainTE != SrcTE;
           ChainTE = getOperandEntry(ChainTE, /*Idx=*/0)) {
        ChainTE->State = TreeEntry::CombinedVectorize;
        ChainTE->CombinedOp = TreeEntry::ReducedBitPack;
        for (unsigned Idx : seq<unsigned>(1, ChainTE->getNumOperands())) {
          TreeEntry *ConstTE = getOperandEntry(ChainTE, Idx);
          ConstTE->State = TreeEntry::CombinedVectorize;
          ConstTE->CombinedOp = TreeEntry::ReducedBitPack;
        }
      }
      break;
    }
    default:
      break;
    }
  }
  // The nodes, built for the slices of the gathered nodes, are fused with their
  // fmul operands in the vector code too.
  for (std::unique_ptr<TreeEntry> &TE :
       drop_begin(VectorizableTree, BaseGraphSize))
    if (TE->hasState() &&
        is_contained({Instruction::FAdd, Instruction::FSub}, TE->getOpcode()))
      CombineFMulAdd(*TE);

  if (LoadEntriesToVectorize.empty()) {
    // Single load node - exit.
    if (VectorizableTree.size() <= 1 && getRootNode().hasState() &&
        getRootNode().getOpcode() == Instruction::Load)
      return;
    // Small graph with small VF - exit.
    constexpr unsigned SmallTree = 3;
    constexpr unsigned SmallVF = 2;
    if ((VectorizableTree.size() <= SmallTree &&
         getRootNodeScalars().size() == SmallVF) ||
        (VectorizableTree.size() <= 2 && UserIgnoreList))
      return;

    if (getRootNode().isNonPowOf2Vec() &&
        getCanonicalGraphSize() != getTreeSize() && UserIgnoreList &&
        getCanonicalGraphSize() <= SmallTree &&
        count_if(ArrayRef(VectorizableTree).drop_front(getCanonicalGraphSize()),
                 [](const std::unique_ptr<TreeEntry> &TE) {
                   return TE->isGather() && TE->hasState() &&
                          TE->getOpcode() == Instruction::Load &&
                          !allSameBlock(TE->Scalars);
                 }) == 1)
      return;
  }

  // A list of loads to be gathered during the vectorization process. We can
  // try to vectorize them at the end, if profitable.
  SmallMapVector<std::tuple<BasicBlock *, Value *, Type *>,
                 SmallVector<SmallVector<std::pair<LoadInst *, int64_t>>>, 8>
      GatheredLoads;

  for (std::unique_ptr<TreeEntry> &TE : VectorizableTree) {
    TreeEntry &E = *TE;
    if (E.isGather() &&
        ((E.hasState() && E.getOpcode() == Instruction::Load) ||
         (!E.hasState() && any_of(make_isa_range<LoadInst>(E.Scalars),
                                  [&](LoadInst *LI) {
                                    return !isVectorized(LI) && !isDeleted(LI);
                                  }))) &&
        !isSplat(E.Scalars)) {
      for (Value *V : E.Scalars) {
        auto *LI = dyn_cast<LoadInst>(V);
        if (!LI)
          continue;
        if (isDeleted(LI) || isVectorized(LI) || !LI->isSimple())
          continue;
        gatherPossiblyVectorizableLoads(
            *this, V, *DL, *SE, *TTI,
            GatheredLoads[std::make_tuple(
                LI->getParent(),
                getUnderlyingObject(LI->getPointerOperand(),
                                    Opts.slp_recursion_max_depth),
                LI->getType())]);
      }
    }
  }
  // Try to vectorize gathered loads if this is not just a gather of loads.
  if (!GatheredLoads.empty())
    tryToVectorizeGatheredLoads(GatheredLoads);
}

/// Merges shuffle masks and emits final shuffle instruction, if required. It
/// supports shuffling of 2 input vectors. It implements lazy shuffles emission,
/// when the actual shuffle instruction is generated only if this is actually
/// required. Otherwise, the shuffle instruction emission is delayed till the
/// end of the process, to reduce the number of emitted instructions and further
/// analysis/transformations.
class BoUpSLP::ShuffleCostEstimator : public BaseShuffleAnalysis {
  bool IsFinalized = false;
  SmallVector<int> CommonMask;

  // Each input vector can be tagged with extra context information
  struct InVector {
    PointerUnion<Value *, const TreeEntry *> Vec = nullptr;
    TargetTransformInfo::VectorInstrContext Ctx =
        TargetTransformInfo::VectorInstrContext::None;

    InVector(Value *Vec, TargetTransformInfo::VectorInstrContext Ctx =
                             TargetTransformInfo::VectorInstrContext::None)
        : Vec(Vec), Ctx(Ctx) {}
    InVector(const TreeEntry *Vec,
             TargetTransformInfo::VectorInstrContext Ctx =
                 TargetTransformInfo::VectorInstrContext::None)
        : Vec(Vec), Ctx(Ctx) {}
  };
  SmallVector<InVector, 2> InVectors;
  /// Captures the original scalar VL of a single, "clean" gather() call so
  /// the values can be forwarded as the Args operand to getShuffleCost() for
  /// the final permutation in finalize(). This lets the target cost model
  /// recognize patterns such as broadcast-of-load (e.g. on X86,
  /// vbroadcast{ss,sd} folds the broadcast and the load into one instruction
  /// under AVX/AVX2 and is reported as TCC_Free by getShuffleCost). The
  /// state machine is:
  ///   * engaged + empty: tracking active, no qualifying gather seen yet.
  ///   * engaged + non-empty: exactly one qualifying gather observed and its
  ///     VL still corresponds to InVectors.front().
  ///   * disengaged: the cached VL is no longer trustworthy (multiple
  ///     gather() calls, or a state-mutating add() happened).
  std::optional<SmallVector<Value *>> BVValues = SmallVector<Value *>();
  const TargetTransformInfo &TTI;
  InstructionCost Cost = 0;
  SmallDenseSet<Value *> VectorizedVals;
  BoUpSLP &R;
  SmallPtrSetImpl<Value *> &CheckedExtracts;
  const TTI::TargetCostKind CostKind;
  /// While set, still trying to estimate the cost for the same nodes and we
  /// can delay actual cost estimation (virtual shuffle instruction emission).
  /// May help better estimate the cost if same nodes must be permuted + allows
  /// to move most of the long shuffles cost estimation to TTI.
  bool SameNodesEstimated = true;

  static Constant *getAllOnesValue(const DataLayout &DL, Type *Ty) {
    if (Ty->getScalarType()->isPointerTy()) {
      Constant *Res = ConstantExpr::getIntToPtr(
          ConstantInt::getAllOnesValue(
              IntegerType::get(Ty->getContext(),
                               DL.getTypeStoreSizeInBits(Ty->getScalarType()))),
          Ty->getScalarType());
      if (auto *VTy = dyn_cast<VectorType>(Ty))
        Res = ConstantVector::getSplat(VTy->getElementCount(), Res);
      return Res;
    }
    return Constant::getAllOnesValue(Ty);
  }

  InstructionCost getBuildVectorCost(ArrayRef<Value *> VL, Value *Root,
                                     TTI::VectorInstrContext ContextHint) {
    if ((!Root && allConstant(VL)) || all_of(VL, IsaPred<UndefValue>))
      return TTI::TCC_Free;
    auto *VecTy = cast<VectorType>(getWidenedType(ScalarTy, VL.size()));
    InstructionCost GatherCost = 0;
    if (!Root && isSplat(VL)) {
      // Found the broadcasting of the single scalar, calculate the cost as
      // the broadcast.
      const auto *It = find_if_not(VL, IsaPred<UndefValue>);
      assert(It != VL.end() && "Expected at least one non-undef value.");
      // Add broadcast for non-identity shuffle only.
      bool NeedShuffle =
          count(VL, *It) > 1 &&
          (VL.front() != *It || !all_of(VL.drop_front(), IsaPred<UndefValue>));
      if (!NeedShuffle) {
        if (isa<FixedVectorType>(ScalarTy)) {
          assert(R.Opts.slp_revec && "FixedVectorType is not expected.");
          return TTI.getShuffleCost(
              TTI::SK_InsertSubvector, VecTy, VecTy, CostKind, {},
              std::distance(VL.begin(), It) * getNumElements(ScalarTy),
              cast<FixedVectorType>(ScalarTy));
        }
        return TTI.getVectorInstrCost(Instruction::InsertElement, VecTy,
                                      CostKind, std::distance(VL.begin(), It),
                                      PoisonValue::get(VecTy), *It,
                                      ContextHint);
      }

      SmallVector<int> ShuffleMask(VL.size(), PoisonMaskElem);
      transform(VL, ShuffleMask.begin(), [](Value *V) {
        return isa<PoisonValue>(V) ? PoisonMaskElem : 0;
      });
      InstructionCost InsertCost =
          TTI.getVectorInstrCost(Instruction::InsertElement, VecTy, CostKind, 0,
                                 PoisonValue::get(VecTy), *It, ContextHint);
      return InsertCost + getShuffleCost(TTI, TargetTransformInfo::SK_Broadcast,
                                         VecTy, CostKind, ShuffleMask,
                                         /*Index=*/0, /*SubTp=*/nullptr,
                                         /*Args=*/*It, ContextHint);
    }
    assert(ContextHint != TTI::VectorInstrContext::SplatOpFolded &&
           "Expected SplatOpFolded to be a splat");
    return GatherCost + (all_of(VL, IsaPred<UndefValue>)
                             ? TTI::TCC_Free
                             : R.getGatherCost(VL, !Root, ScalarTy));
  };

  /// Compute the cost of creating a vector containing the extracted values from
  /// \p VL.
  InstructionCost
  computeExtractCost(ArrayRef<Value *> VL, ArrayRef<int> Mask,
                     ArrayRef<std::optional<TTI::ShuffleKind>> ShuffleKinds,
                     unsigned NumParts) {
    assert(VL.size() > NumParts && "Unexpected scalarized shuffle.");
    unsigned NumElts = accumulate(VL, 0, [](unsigned Sz, Value *V) {
      auto *EE = dyn_cast<ExtractElementInst>(V);
      if (!EE)
        return Sz;
      auto *VecTy = dyn_cast<FixedVectorType>(EE->getVectorOperandType());
      if (!VecTy)
        return Sz;
      return std::max(Sz, VecTy->getNumElements());
    });
    // FIXME: this must be moved to TTI for better estimation.
    unsigned EltsPerVector = getPartNumElems(VL.size(), NumParts);
    auto CheckPerRegistersShuffle = [&](MutableArrayRef<int> Mask,
                                        SmallVectorImpl<unsigned> &Indices,
                                        SmallVectorImpl<unsigned> &SubVecSizes)
        -> std::optional<TTI::ShuffleKind> {
      if (NumElts <= EltsPerVector)
        return std::nullopt;
      int OffsetReg0 = alignDown(accumulate(Mask, INT_MAX,
                                            [](int S, int I) {
                                              if (I == PoisonMaskElem)
                                                return S;
                                              return std::min(S, I);
                                            }),
                                 EltsPerVector);
      int OffsetReg1 = OffsetReg0;
      DenseSet<int> RegIndices;
      // Check that if trying to permute same single/2 input vectors.
      TTI::ShuffleKind ShuffleKind = TTI::SK_PermuteSingleSrc;
      int FirstRegId = -1;
      Indices.assign(1, OffsetReg0);
      auto HasLane = [](const auto &P) { return P.value() != PoisonMaskElem; };
      for (auto [Pos, I] : make_filter_range(enumerate(Mask), HasLane)) {
        int Idx = I - OffsetReg0;
        int RegId =
            (Idx / NumElts) * NumParts + (Idx % NumElts) / EltsPerVector;
        if (FirstRegId < 0)
          FirstRegId = RegId;
        RegIndices.insert(RegId);
        if (RegIndices.size() > 2)
          return std::nullopt;
        if (RegIndices.size() == 2) {
          ShuffleKind = TTI::SK_PermuteTwoSrc;
          if (Indices.size() == 1) {
            OffsetReg1 = alignDown(
                std::accumulate(
                    std::next(Mask.begin(), Pos), Mask.end(), INT_MAX,
                    [&](int S, int I) {
                      if (I == PoisonMaskElem)
                        return S;
                      int RegId = ((I - OffsetReg0) / NumElts) * NumParts +
                                  ((I - OffsetReg0) % NumElts) / EltsPerVector;
                      if (RegId == FirstRegId)
                        return S;
                      return std::min(S, I);
                    }),
                EltsPerVector);
            unsigned Index = OffsetReg1 % NumElts;
            Indices.push_back(Index);
            SubVecSizes.push_back(std::min(NumElts - Index, EltsPerVector));
          }
          Idx = I - OffsetReg1;
        }
        I = (Idx % NumElts) % EltsPerVector +
            (RegId == FirstRegId ? 0 : EltsPerVector);
      }
      return ShuffleKind;
    };
    InstructionCost Cost = 0;

    // Process extracts in blocks of EltsPerVector to check if the source vector
    // operand can be re-used directly. If not, add the cost of creating a
    // shuffle to extract the values into a vector register.
    for (unsigned Part : seq<unsigned>(NumParts)) {
      if (!ShuffleKinds[Part])
        continue;
      ArrayRef<int> MaskSlice = Mask.slice(
          Part * EltsPerVector, getNumElems(Mask.size(), EltsPerVector, Part));
      SmallVector<int> SubMask(EltsPerVector, PoisonMaskElem);
      copy(MaskSlice, SubMask.begin());
      SmallVector<unsigned, 2> Indices;
      SmallVector<unsigned, 2> SubVecSizes;
      std::optional<TTI::ShuffleKind> RegShuffleKind =
          CheckPerRegistersShuffle(SubMask, Indices, SubVecSizes);
      if (!RegShuffleKind) {
        if (*ShuffleKinds[Part] != TTI::SK_PermuteSingleSrc ||
            !ShuffleVectorInst::isIdentityMask(
                MaskSlice, std::max<unsigned>(NumElts, MaskSlice.size())))
          Cost += getShuffleCost(
              TTI, *ShuffleKinds[Part],
              cast<VectorType>(getWidenedType(ScalarTy, NumElts)), CostKind,
              MaskSlice);
        continue;
      }
      if (*RegShuffleKind != TTI::SK_PermuteSingleSrc ||
          !ShuffleVectorInst::isIdentityMask(SubMask, EltsPerVector)) {
        Cost += getShuffleCost(
            TTI, *RegShuffleKind,
            cast<VectorType>(getWidenedType(ScalarTy, EltsPerVector)), CostKind,
            SubMask);
      }
      const unsigned BaseVF = getFullVectorNumberOfElements(
          *R.TTI, VL.front()->getType(), alignTo(NumElts, EltsPerVector),
          R.Opts.slp_revec);
      for (const auto [Idx, SubVecSize] : zip(Indices, SubVecSizes)) {
        assert((Idx + SubVecSize) <= BaseVF &&
               "SK_ExtractSubvector index out of range");
        Cost += getShuffleCost(
            TTI, TTI::SK_ExtractSubvector,
            cast<VectorType>(getWidenedType(ScalarTy, BaseVF)), CostKind, {},
            Idx, cast<VectorType>(getWidenedType(ScalarTy, SubVecSize)));
      }
      // Second attempt to check, if just a permute is better estimated than
      // subvector extract.
      SubMask.assign(NumElts, PoisonMaskElem);
      copy(MaskSlice, SubMask.begin());
      InstructionCost OriginalCost =
          getShuffleCost(TTI, *ShuffleKinds[Part],
                         cast<VectorType>(getWidenedType(ScalarTy, NumElts)),
                         CostKind, SubMask);
      if (OriginalCost < Cost)
        Cost = OriginalCost;
    }
    return Cost;
  }
  /// Adds the cost of reshuffling \p E1 and \p E2 (if present), using given
  /// mask \p Mask, register number \p Part, that includes \p SliceSize
  /// elements.
  void estimateNodesPermuteCost(const TreeEntry &E1, const TreeEntry *E2,
                                ArrayRef<int> Mask, unsigned Part,
                                unsigned SliceSize) {
    if (SameNodesEstimated) {
      // Delay the cost estimation if the same nodes are reshuffling.
      // If we already requested the cost of reshuffling of E1 and E2 before, no
      // need to estimate another cost with the sub-Mask, instead include this
      // sub-Mask into the CommonMask to estimate it later and avoid double cost
      // estimation.
      if ((InVectors.size() == 2 &&
           cast<const TreeEntry *>(InVectors.front().Vec) == &E1 &&
           cast<const TreeEntry *>(InVectors.back().Vec) == E2) ||
          (!E2 && cast<const TreeEntry *>(InVectors.front().Vec) == &E1)) {
        unsigned Limit = getNumElems(Mask.size(), SliceSize, Part);
        assert(all_of(ArrayRef(CommonMask).slice(Part * SliceSize, Limit),
                      [](int Idx) { return Idx == PoisonMaskElem; }) &&
               "Expected all poisoned elements.");
        ArrayRef<int> SubMask = ArrayRef(Mask).slice(Part * SliceSize, Limit);
        copy(SubMask, std::next(CommonMask.begin(), SliceSize * Part));
        return;
      }
      // Found non-matching nodes - need to estimate the cost for the matched
      // and transform mask.
      if (InVectors.size() == 1)
        Cost += createShuffle(InVectors.front().Vec, nullptr, CommonMask, {},
                              InVectors.front().Ctx);
      else
        Cost += createShuffle(InVectors.front().Vec, InVectors.back().Vec,
                              CommonMask, {}, InVectors.front().Ctx,
                              InVectors.back().Ctx);
      transformMaskAfterShuffle(CommonMask, CommonMask);
    } else if (InVectors.size() == 2) {
      Cost +=
          createShuffle(InVectors.front().Vec, InVectors.back().Vec, CommonMask,
                        {}, InVectors.front().Ctx, InVectors.back().Ctx);
      transformMaskAfterShuffle(CommonMask, CommonMask);
    }
    SameNodesEstimated = false;
    if (!E2 && InVectors.size() == 1) {
      unsigned VF = E1.getVectorFactor();
      if (Value *V1 = dyn_cast<Value *>(InVectors.front().Vec)) {
        VF = std::max(VF, getVF(V1));
      } else {
        const auto *E = cast<const TreeEntry *>(InVectors.front().Vec);
        VF = std::max(VF, E->getVectorFactor());
      }
      for (unsigned Idx = 0, Sz = CommonMask.size(); Idx < Sz; ++Idx)
        if (Mask[Idx] != PoisonMaskElem && CommonMask[Idx] == PoisonMaskElem)
          CommonMask[Idx] = Mask[Idx] + VF;
      Cost += createShuffle(InVectors.front().Vec, &E1, CommonMask, {},
                            InVectors.front().Ctx);
      transformMaskAfterShuffle(CommonMask, CommonMask);
    } else {
      auto P = InVectors.front();
      Cost += createShuffle(&E1, E2, Mask, {}, TTI::VectorInstrContext::None);
      unsigned VF = Mask.size();
      if (Value *V1 = dyn_cast<Value *>(P.Vec)) {
        VF = std::max(VF,
                      getNumElements(V1->getType()));
      } else {
        const auto *E = cast<const TreeEntry *>(P.Vec);
        VF = std::max(VF, E->getVectorFactor());
      }
      for (unsigned Idx = 0, Sz = CommonMask.size(); Idx < Sz; ++Idx)
        if (Mask[Idx] != PoisonMaskElem)
          CommonMask[Idx] = Idx + (InVectors.empty() ? 0 : VF);
      Cost += createShuffle(P.Vec, InVectors.front().Vec, CommonMask, {}, P.Ctx,
                            InVectors.front().Ctx);
      transformMaskAfterShuffle(CommonMask, CommonMask);
    }
  }

  class ShuffleCostBuilder {
    const TargetTransformInfo &TTI;
    const TTI::TargetCostKind CostKind;

    static bool isEmptyOrIdentity(ArrayRef<int> Mask, unsigned VF) {
      int Index = -1;
      return Mask.empty() ||
             (VF == Mask.size() &&
              ShuffleVectorInst::isIdentityMask(Mask, VF)) ||
             (ShuffleVectorInst::isExtractSubvectorMask(Mask, VF, Index) &&
              Index == 0);
    }

  public:
    ShuffleCostBuilder(const TargetTransformInfo &TTI,
                       const TTI::TargetCostKind CostKind)
        : TTI(TTI), CostKind(CostKind) {}
    ~ShuffleCostBuilder() = default;
    InstructionCost createShuffleVector(Value *V1, Value *,
                                        ArrayRef<int> Mask) const {
      // Empty mask or identity mask are free.
      unsigned VF =
          cast<VectorType>(V1->getType())->getElementCount().getKnownMinValue();
      if (isEmptyOrIdentity(Mask, VF))
        return TTI::TCC_Free;
      return getShuffleCost(TTI, TTI::SK_PermuteTwoSrc,
                            cast<VectorType>(V1->getType()), CostKind, Mask);
    }
    InstructionCost
    createShuffleVector(Value *V1, ArrayRef<int> Mask, ArrayRef<Value *> VL,
                        TTI::VectorInstrContext ContextHint =
                            TTI::VectorInstrContext::None) const {
      // Empty mask or identity mask are free.
      unsigned VF =
          cast<VectorType>(V1->getType())->getElementCount().getKnownMinValue();
      if (isEmptyOrIdentity(Mask, VF))
        return TTI::TCC_Free;
      return getShuffleCost(TTI, TTI::SK_PermuteSingleSrc,
                            cast<VectorType>(V1->getType()), CostKind, Mask,
                            /*Index=*/0, /*SubTp=*/nullptr, VL, ContextHint);
    }
    InstructionCost createIdentity(Value *) const { return TTI::TCC_Free; }
    InstructionCost createPoison(Type *Ty, unsigned VF) const {
      return TTI::TCC_Free;
    }
    void resizeToMatch(Value *&, Value *&) const {}
  };

  /// Smart shuffle instruction emission, walks through shuffles trees and
  /// tries to find the best matching vector for the actual shuffle
  /// instruction.
  InstructionCost
  createShuffle(const PointerUnion<Value *, const TreeEntry *> &P1,
                const PointerUnion<Value *, const TreeEntry *> &P2,
                ArrayRef<int> Mask, ArrayRef<Value *> VL = {},
                TTI::VectorInstrContext Ctx1 = TTI::VectorInstrContext::None,
                TTI::VectorInstrContext Ctx2 = TTI::VectorInstrContext::None) {
    ShuffleCostBuilder Builder(TTI, CostKind);
    SmallVector<int> CommonMask(Mask);
    Value *V1 = dyn_cast<Value *>(P1), *V2 = dyn_cast_if_present<Value *>(P2);
    unsigned CommonVF = Mask.size();
    InstructionCost ExtraCost = 0;
    auto GetNodeMinBWAffectedCost = [&](const TreeEntry &E,
                                        unsigned VF) -> InstructionCost {
      if (E.isGather() && allConstant(E.Scalars))
        return TTI::TCC_Free;
      Type *EScalarTy = E.Scalars.front()->getType();
      bool IsSigned = true;
      if (auto It = R.MinBWs.find(&E); It != R.MinBWs.end()) {
        EScalarTy = IntegerType::get(EScalarTy->getContext(), It->second.first);
        IsSigned = It->second.second;
      }
      if (EScalarTy != ScalarTy) {
        unsigned CastOpcode = Instruction::Trunc;
        unsigned DstSz = R.DL->getTypeSizeInBits(ScalarTy);
        unsigned SrcSz = R.DL->getTypeSizeInBits(EScalarTy);
        if (DstSz > SrcSz)
          CastOpcode = IsSigned ? Instruction::SExt : Instruction::ZExt;
        return TTI.getCastInstrCost(CastOpcode, getWidenedType(ScalarTy, VF),
                                    getWidenedType(EScalarTy, VF),
                                    R.getCastContextHint(E), CostKind);
      }
      return TTI::TCC_Free;
    };
    auto GetValueMinBWAffectedCost = [&](const Value *V) -> InstructionCost {
      if (isa<Constant>(V))
        return TTI::TCC_Free;
      auto *VecTy = cast<VectorType>(V->getType());
      Type *EScalarTy = VecTy->getElementType();
      if (EScalarTy != ScalarTy) {
        bool IsSigned = !isKnownNonNegative(V, SimplifyQuery(*R.DL));
        unsigned CastOpcode = Instruction::Trunc;
        unsigned DstSz = R.DL->getTypeSizeInBits(ScalarTy);
        unsigned SrcSz = R.DL->getTypeSizeInBits(EScalarTy);
        if (DstSz > SrcSz)
          CastOpcode = IsSigned ? Instruction::SExt : Instruction::ZExt;
        TTI::CastContextHint CCH = TTI::CastContextHint::None;
        if (ArrayRef<TreeEntry *> TEs = R.getTreeEntries(V); TEs.size() == 1)
          CCH = R.getCastContextHint(*TEs.front());
        return TTI.getCastInstrCost(
            CastOpcode, VectorType::get(ScalarTy, VecTy->getElementCount()),
            VecTy, CCH, CostKind);
      }
      return TTI::TCC_Free;
    };
    if (!V1 && !V2 && !P2.isNull()) {
      // Shuffle 2 entry nodes.
      const TreeEntry *E = cast<const TreeEntry *>(P1);
      unsigned VF = E->getVectorFactor();
      const TreeEntry *E2 = cast<const TreeEntry *>(P2);
      CommonVF = std::max(VF, E2->getVectorFactor());
      assert(all_of(Mask,
                    [=](int Idx) {
                      return Idx < 2 * static_cast<int>(CommonVF);
                    }) &&
             "All elements in mask must be less than 2 * CommonVF.");
      if (E->Scalars.size() == E2->Scalars.size()) {
        SmallVector<int> EMask = E->getCommonMask();
        SmallVector<int> E2Mask = E2->getCommonMask();
        if (!EMask.empty() || !E2Mask.empty()) {
          for (int &Idx : make_filter_range(
                   CommonMask, [](int Idx) { return Idx != PoisonMaskElem; })) {
            if (Idx < static_cast<int>(CommonVF) && !EMask.empty())
              Idx = EMask[Idx];
            else if (Idx >= static_cast<int>(CommonVF))
              Idx = (E2Mask.empty() ? Idx - CommonVF : E2Mask[Idx - CommonVF]) +
                    E->Scalars.size();
          }
        }
        CommonVF = E->Scalars.size();
        ExtraCost += GetNodeMinBWAffectedCost(*E, CommonVF) +
                     GetNodeMinBWAffectedCost(*E2, CommonVF);
      } else {
        ExtraCost += GetNodeMinBWAffectedCost(*E, E->getVectorFactor()) +
                     GetNodeMinBWAffectedCost(*E2, E2->getVectorFactor());
      }
      V1 = Constant::getNullValue(getWidenedType(ScalarTy, CommonVF));
      V2 = getAllOnesValue(*R.DL, getWidenedType(ScalarTy, CommonVF));
    } else if (!V1 && P2.isNull()) {
      // Shuffle single entry node.
      const TreeEntry *E = cast<const TreeEntry *>(P1);
      unsigned VF = E->getVectorFactor();
      CommonVF = VF;
      assert(
          all_of(Mask,
                 [=](int Idx) { return Idx < static_cast<int>(CommonVF); }) &&
          "All elements in mask must be less than CommonVF.");
      if (E->Scalars.size() == Mask.size() && VF != Mask.size()) {
        SmallVector<int> EMask = E->getCommonMask();
        assert(!EMask.empty() && "Expected non-empty common mask.");
        for (int &Idx : CommonMask) {
          if (Idx != PoisonMaskElem)
            Idx = EMask[Idx];
        }
        CommonVF = E->Scalars.size();
      } else if (unsigned Factor = E->getInterleaveFactor();
                 Factor > 0 && E->Scalars.size() != Mask.size() &&
                 ShuffleVectorInst::isDeInterleaveMaskOfFactor(CommonMask,
                                                               Factor)) {
        // Deinterleaved nodes are free.
        std::iota(CommonMask.begin(), CommonMask.end(), 0);
      }
      ExtraCost += GetNodeMinBWAffectedCost(*E, CommonVF);
      V1 = Constant::getNullValue(getWidenedType(ScalarTy, CommonVF));
      // Not identity/broadcast? Try to see if the original vector is better.
      if (!E->ReorderIndices.empty() && CommonVF == E->ReorderIndices.size() &&
          CommonVF == CommonMask.size() &&
          any_of(enumerate(CommonMask),
                 [](const auto &&P) {
                   return P.value() != PoisonMaskElem &&
                          static_cast<unsigned>(P.value()) != P.index();
                 }) &&
          any_of(CommonMask,
                 [](int Idx) { return Idx != PoisonMaskElem && Idx != 0; })) {
        SmallVector<int> ReorderMask;
        inversePermutation(E->ReorderIndices, ReorderMask);
        addMask(CommonMask, ReorderMask);
      }
    } else if (V1 && P2.isNull()) {
      // Shuffle single vector.
      ExtraCost += GetValueMinBWAffectedCost(V1);
      CommonVF = getVF(V1);
      assert(
          all_of(Mask,
                 [=](int Idx) { return Idx < static_cast<int>(CommonVF); }) &&
          "All elements in mask must be less than CommonVF.");
    } else if (V1 && !V2) {
      // Shuffle vector and tree node.
      unsigned VF = getVF(V1);
      const TreeEntry *E2 = cast<const TreeEntry *>(P2);
      CommonVF = std::max(VF, E2->getVectorFactor());
      assert(all_of(Mask,
                    [=](int Idx) {
                      return Idx < 2 * static_cast<int>(CommonVF);
                    }) &&
             "All elements in mask must be less than 2 * CommonVF.");
      if (E2->Scalars.size() == VF && VF != CommonVF) {
        SmallVector<int> E2Mask = E2->getCommonMask();
        assert(!E2Mask.empty() && "Expected non-empty common mask.");
        for (int &Idx : make_filter_range(
                 CommonMask, [](int Idx) { return Idx != PoisonMaskElem; })) {
          if (Idx >= static_cast<int>(CommonVF))
            Idx = E2Mask[Idx - CommonVF] + VF;
        }
        CommonVF = VF;
      }
      ExtraCost += GetValueMinBWAffectedCost(V1);
      V1 = Constant::getNullValue(getWidenedType(ScalarTy, CommonVF));
      ExtraCost += GetNodeMinBWAffectedCost(
          *E2, std::min(CommonVF, E2->getVectorFactor()));
      V2 = getAllOnesValue(*R.DL, getWidenedType(ScalarTy, CommonVF));
    } else if (!V1 && V2) {
      // Shuffle vector and tree node.
      unsigned VF = getVF(V2);
      const TreeEntry *E1 = cast<const TreeEntry *>(P1);
      CommonVF = std::max(VF, E1->getVectorFactor());
      assert(all_of(Mask,
                    [=](int Idx) {
                      return Idx < 2 * static_cast<int>(CommonVF);
                    }) &&
             "All elements in mask must be less than 2 * CommonVF.");
      if (E1->Scalars.size() == VF && VF != CommonVF) {
        SmallVector<int> E1Mask = E1->getCommonMask();
        assert(!E1Mask.empty() && "Expected non-empty common mask.");
        for (int &Idx : make_filter_range(
                 CommonMask, [](int Idx) { return Idx != PoisonMaskElem; })) {
          if (Idx >= static_cast<int>(CommonVF))
            Idx = E1Mask[Idx - CommonVF] + VF;
          else
            Idx = E1Mask[Idx];
        }
        CommonVF = VF;
      }
      ExtraCost += GetNodeMinBWAffectedCost(
          *E1, std::min(CommonVF, E1->getVectorFactor()));
      V1 = Constant::getNullValue(getWidenedType(ScalarTy, CommonVF));
      ExtraCost += GetValueMinBWAffectedCost(V2);
      V2 = getAllOnesValue(*R.DL, getWidenedType(ScalarTy, CommonVF));
    } else {
      assert(V1 && V2 && "Expected both vectors.");
      unsigned VF = getVF(V1);
      CommonVF = std::max(VF, getVF(V2));
      assert(all_of(Mask,
                    [=](int Idx) {
                      return Idx < 2 * static_cast<int>(CommonVF);
                    }) &&
             "All elements in mask must be less than 2 * CommonVF.");
      ExtraCost +=
          GetValueMinBWAffectedCost(V1) + GetValueMinBWAffectedCost(V2);
      if (V1->getType() != V2->getType()) {
        V1 = Constant::getNullValue(getWidenedType(ScalarTy, CommonVF));
        V2 = getAllOnesValue(*R.DL, getWidenedType(ScalarTy, CommonVF));
      } else {
        if (cast<VectorType>(V1->getType())->getElementType() != ScalarTy)
          V1 = Constant::getNullValue(getWidenedType(ScalarTy, CommonVF));
        if (cast<VectorType>(V2->getType())->getElementType() != ScalarTy)
          V2 = getAllOnesValue(*R.DL, getWidenedType(ScalarTy, CommonVF));
      }
    }
    InVectors.front() =
        Constant::getNullValue(getWidenedType(ScalarTy, CommonMask.size()));
    if (InVectors.size() == 2)
      InVectors.pop_back();
    TTI::VectorInstrContext Ctx =
        P2.isNull() ? Ctx1 : TTI::combineVectorInstrContexts(Ctx1, Ctx2);
    return ExtraCost + BaseShuffleAnalysis::createShuffle<InstructionCost>(
                           V1, V2, CommonMask, Builder, ScalarTy,
                           R.Opts.slp_revec, VL, Ctx);
  }

public:
  ShuffleCostEstimator(Type *ScalarTy, TargetTransformInfo &TTI,
                       ArrayRef<Value *> VectorizedVals, BoUpSLP &R,
                       SmallPtrSetImpl<Value *> &CheckedExtracts)
      : BaseShuffleAnalysis(ScalarTy), TTI(TTI),
        VectorizedVals(VectorizedVals.begin(), VectorizedVals.end()), R(R),
        CheckedExtracts(CheckedExtracts), CostKind(R.getCostKind()) {}
  Value *adjustExtracts(const TreeEntry *E, MutableArrayRef<int> Mask,
                        ArrayRef<std::optional<TTI::ShuffleKind>> ShuffleKinds,
                        unsigned NumParts, bool &UseVecBaseAsInput) {
    UseVecBaseAsInput = false;
    if (Mask.empty())
      return nullptr;
    Value *VecBase = nullptr;
    SmallVector<Value *> VL(E->Scalars.begin(), E->Scalars.end());
    if (!E->ReorderIndices.empty()) {
      SmallVector<int> ReorderMask(E->ReorderIndices.begin(),
                                   E->ReorderIndices.end());
      reorderScalars(VL, ReorderMask);
    }
    // Check if it can be considered reused if same extractelements were
    // vectorized already.
    bool PrevNodeFound = any_of(
        ArrayRef(R.VectorizableTree).take_front(E->Idx),
        [&](const std::unique_ptr<TreeEntry> &TE) {
          return ((TE->hasState() && !TE->isAltShuffle() &&
                   TE->getOpcode() == Instruction::ExtractElement) ||
                  TE->isGather()) &&
                 all_of(enumerate(TE->Scalars), [&](auto &&Data) {
                   return VL.size() > Data.index() &&
                          (Mask[Data.index()] == PoisonMaskElem ||
                           isa<UndefValue>(VL[Data.index()]) ||
                           Data.value() == VL[Data.index()]);
                 });
        });
    SmallPtrSet<Value *, 4> UniqueBases;
    unsigned SliceSize = getPartNumElems(VL.size(), NumParts);
    SmallDenseMap<Value *, APInt, 4> VectorOpsToExtracts;
    for (unsigned Part : seq<unsigned>(NumParts)) {
      unsigned Limit = getNumElems(VL.size(), SliceSize, Part);
      ArrayRef<int> SubMask = Mask.slice(Part * SliceSize, Limit);
      for (auto [I, V] :
           enumerate(ArrayRef(VL).slice(Part * SliceSize, Limit))) {
        // Ignore non-extractelement scalars.
        if (isa<UndefValue>(V) ||
            (!SubMask.empty() && SubMask[I] == PoisonMaskElem))
          continue;
        // If all users of instruction are going to be vectorized and this
        // instruction itself is not going to be vectorized, consider this
        // instruction as dead and remove its cost from the final cost of the
        // vectorized tree.
        // Also, avoid adjusting the cost for extractelements with multiple uses
        // in different graph entries.
        auto *EE = cast<ExtractElementInst>(V);
        VecBase = EE->getVectorOperand();
        UniqueBases.insert(VecBase);
        ArrayRef<TreeEntry *> VEs = R.getTreeEntries(V);
        if (!CheckedExtracts.insert(V).second ||
            !R.areAllUsersVectorized(cast<Instruction>(V), &VectorizedVals) ||
            any_of(VEs,
                   [&](const TreeEntry *TE) {
                     return R.DeletedNodes.contains(TE) ||
                            R.TransformedToGatherNodes.contains(TE);
                   }) ||
            (E->UserTreeIndex && E->UserTreeIndex.EdgeIdx == UINT_MAX &&
             !R.isVectorized(EE) &&
             count_if(E->Scalars, [&](Value *V) { return V == EE; }) !=
                 count_if(E->UserTreeIndex.UserTE->Scalars,
                          [&](Value *V) { return V == EE; })) ||
            any_of(EE->users(),
                   [&](User *U) {
                     return isa<GetElementPtrInst>(U) &&
                            !R.areAllUsersVectorized(cast<Instruction>(U),
                                                     &VectorizedVals);
                   }) ||
            (!VEs.empty() && !is_contained(VEs, E)))
          continue;
        std::optional<unsigned> EEIdx = getExtractIndex(EE);
        if (!EEIdx)
          continue;
        unsigned Idx = *EEIdx;
        // Take credit for instruction that will become dead.
        if (EE->hasOneUse() || !PrevNodeFound) {
          Instruction *Ext = EE->user_back();
          if (isa<SExtInst, ZExtInst>(Ext) &&
              all_of(Ext->users(), IsaPred<GetElementPtrInst>)) {
            // Use getExtractWithExtendCost() to calculate the cost of
            // extractelement/ext pair.
            Cost -= TTI.getExtractWithExtendCost(
                Ext->getOpcode(), Ext->getType(), EE->getVectorOperandType(),
                Idx, CostKind);
            // Add back the cost of s|zext which is subtracted separately.
            Cost += TTI.getCastInstrCost(
                Ext->getOpcode(), Ext->getType(), EE->getType(),
                TTI::getCastContextHint(Ext), CostKind, Ext);
            continue;
          }
        }
        APInt &DemandedElts =
            VectorOpsToExtracts
                .try_emplace(VecBase,
                             APInt::getZero(getNumElements(VecBase->getType())))
                .first->getSecond();
        DemandedElts.setBit(Idx);
      }
    }
    for (const auto &[Vec, DemandedElts] : VectorOpsToExtracts)
      Cost -= TTI.getScalarizationOverhead(cast<VectorType>(Vec->getType()),
                                           DemandedElts, /*Insert=*/false,
                                           /*Extract=*/true, CostKind);
    // Check that gather of extractelements can be represented as just a
    // shuffle of a single/two vectors the scalars are extracted from.
    // Found the bunch of extractelement instructions that must be gathered
    // into a vector and can be represented as a permutation elements in a
    // single input vector or of 2 input vectors.
    // Done for reused if same extractelements were vectorized already.
    if (!PrevNodeFound)
      Cost += computeExtractCost(VL, Mask, ShuffleKinds, NumParts);
    InVectors.assign(1, E);
    CommonMask.assign(Mask.begin(), Mask.end());
    transformMaskAfterShuffle(CommonMask, CommonMask);
    SameNodesEstimated = false;
    if (NumParts != 1 && UniqueBases.size() != 1) {
      UseVecBaseAsInput = true;
      VecBase =
          Constant::getNullValue(getWidenedType(ScalarTy, CommonMask.size()));
    }
    return VecBase;
  }
  /// Checks if the specified entry \p E needs to be delayed because of its
  /// dependency nodes.
  std::optional<InstructionCost>
  needToDelay(const TreeEntry *,
              ArrayRef<SmallVector<const TreeEntry *>>) const {
    // No need to delay the cost estimation during analysis.
    return std::nullopt;
  }
  /// Reset the builder to handle perfect diamond match.
  void resetForSameNode() {
    IsFinalized = false;
    CommonMask.clear();
    InVectors.clear();
    Cost = 0;
    VectorizedVals.clear();
    SameNodesEstimated = true;
  }
  void add(const TreeEntry &E1, const TreeEntry &E2, ArrayRef<int> Mask) {
    BVValues.reset();
    if (&E1 == &E2) {
      assert(all_of(Mask,
                    [&](int Idx) {
                      return Idx < static_cast<int>(E1.getVectorFactor());
                    }) &&
             "Expected single vector shuffle mask.");
      add(E1, Mask);
      return;
    }
    if (InVectors.empty()) {
      CommonMask.assign(Mask.begin(), Mask.end());
      InVectors.assign({&E1, &E2});
      return;
    }
    assert(!CommonMask.empty() && "Expected non-empty common mask.");
    auto *MaskVecTy = getWidenedType(ScalarTy, Mask.size());
    unsigned NumParts = R.getNumberOfParts(MaskVecTy, ScalarTy, Mask.size());
    unsigned SliceSize = getPartNumElems(Mask.size(), NumParts);
    const auto *It = find_if(Mask, not_equal_to(PoisonMaskElem));
    unsigned Part = std::distance(Mask.begin(), It) / SliceSize;
    estimateNodesPermuteCost(E1, &E2, Mask, Part, SliceSize);
  }
  void add(const TreeEntry &E1, ArrayRef<int> Mask) {
    BVValues.reset();
    if (InVectors.empty()) {
      CommonMask.assign(Mask.begin(), Mask.end());
      InVectors.assign(1, &E1);
      return;
    }
    assert(!CommonMask.empty() && "Expected non-empty common mask.");
    auto *MaskVecTy = getWidenedType(ScalarTy, Mask.size());
    unsigned NumParts = R.getNumberOfParts(MaskVecTy, ScalarTy, Mask.size());
    unsigned SliceSize = getPartNumElems(Mask.size(), NumParts);
    const auto *It = find_if(Mask, not_equal_to(PoisonMaskElem));
    unsigned Part = std::distance(Mask.begin(), It) / SliceSize;
    estimateNodesPermuteCost(E1, nullptr, Mask, Part, SliceSize);
    if (!SameNodesEstimated && InVectors.size() == 1)
      InVectors.emplace_back(&E1);
  }
  /// Adds 2 input vectors and the mask for their shuffling.
  void add(Value *V1, Value *V2, ArrayRef<int> Mask) {
    // May come only for shuffling of 2 vectors with extractelements, already
    // handled in adjustExtracts.
    assert(InVectors.size() == 1 &&
           all_of(enumerate(CommonMask),
                  [&](auto P) {
                    if (P.value() == PoisonMaskElem)
                      return Mask[P.index()] == PoisonMaskElem;
                    auto *EI = cast<ExtractElementInst>(
                        cast<const TreeEntry *>(InVectors.front().Vec)
                            ->getOrdered(P.index()));
                    return EI->getVectorOperand() == V1 ||
                           EI->getVectorOperand() == V2;
                  }) &&
           "Expected extractelement vectors.");
  }
  /// Adds another one input vector and the mask for the shuffling.
  void
  add(Value *V1, ArrayRef<int> Mask, bool ForExtracts = false,
      TTI::VectorInstrContext ContextHint = TTI::VectorInstrContext::None) {
    if (BVValues && !isa<Constant>(V1))
      BVValues.reset();
    if (InVectors.empty()) {
      assert(CommonMask.empty() && !ForExtracts &&
             "Expected empty input mask/vectors.");
      CommonMask.assign(Mask.begin(), Mask.end());
      InVectors.assign(1, InVector(V1, ContextHint));
      return;
    }
    if (ForExtracts) {
      // No need to add vectors here, already handled them in adjustExtracts.
      assert(InVectors.size() == 1 &&
             isa<const TreeEntry *>(InVectors[0].Vec) && !CommonMask.empty() &&
             all_of(enumerate(CommonMask),
                    [&](auto P) {
                      Value *Scalar = cast<const TreeEntry *>(InVectors[0].Vec)
                                          ->getOrdered(P.index());
                      if (P.value() == PoisonMaskElem)
                        return P.value() == Mask[P.index()] ||
                               isa<UndefValue>(Scalar);
                      if (isa<Constant>(V1))
                        return true;
                      auto *EI = cast<ExtractElementInst>(Scalar);
                      return EI->getVectorOperand() == V1;
                    }) &&
             "Expected only tree entry for extractelement vectors.");
      return;
    }
    assert(!InVectors.empty() && !CommonMask.empty() &&
           "Expected only tree entries from extracts/reused buildvectors.");
    unsigned VF = getVF(V1);
    if (InVectors.size() == 2) {
      Cost +=
          createShuffle(InVectors.front().Vec, InVectors.back().Vec, CommonMask,
                        {}, InVectors.front().Ctx, InVectors.back().Ctx);
      transformMaskAfterShuffle(CommonMask, CommonMask);
      VF = std::max<unsigned>(VF, CommonMask.size());
    } else if (const auto *InTE =
                   dyn_cast<const TreeEntry *>(InVectors.front().Vec)) {
      VF = std::max(VF, InTE->getVectorFactor());
    } else {
      VF = std::max(VF, cast<FixedVectorType>(
                            cast<Value *>(InVectors.front().Vec)->getType())
                            ->getNumElements());
    }
    InVectors.emplace_back(V1, ContextHint);
    for (unsigned Idx = 0, Sz = CommonMask.size(); Idx < Sz; ++Idx)
      if (Mask[Idx] != PoisonMaskElem && CommonMask[Idx] == PoisonMaskElem)
        CommonMask[Idx] = Mask[Idx] + VF;
  }
  Value *
  gather(ArrayRef<Value *> VL, unsigned MaskVF = 0, Value *Root = nullptr,
         TTI::VectorInstrContext ContextHint = TTI::VectorInstrContext::None) {
    Cost += getBuildVectorCost(VL, Root, ContextHint);
    if (BVValues) {
      if (BVValues->empty() && InVectors.empty())
        BVValues->assign(VL.begin(), VL.end());
      else
        BVValues.reset();
    }
    if (!Root) {
      // FIXME: Need to find a way to avoid use of getNullValue here.
      SmallVector<Constant *> Vals;
      unsigned VF = VL.size();
      if (MaskVF != 0)
        VF = std::min(VF, MaskVF);
      Type *VLScalarTy = VL.front()->getType();
      for (Value *V : VL.take_front(VF)) {
        Type *ScalarTy = VLScalarTy->getScalarType();
        if (isa<PoisonValue>(V)) {
          Vals.push_back(PoisonValue::get(ScalarTy));
          continue;
        }
        if (isa<UndefValue>(V)) {
          Vals.push_back(UndefValue::get(ScalarTy));
          continue;
        }
        Vals.push_back(Constant::getNullValue(ScalarTy));
      }
      if (auto *VecTy = dyn_cast<FixedVectorType>(VLScalarTy)) {
        assert(R.Opts.slp_revec && "FixedVectorType is not expected.");
        // When REVEC is enabled, we need to expand vector types into scalar
        // types.
        Vals = replicateMask(Vals, VecTy->getNumElements());
      }
      return ConstantVector::get(Vals);
    }
    return ConstantVector::getSplat(
        ElementCount::getFixed(
            cast<FixedVectorType>(Root->getType())->getNumElements()),
        getAllOnesValue(*R.DL, ScalarTy->getScalarType()));
  }
  /// Estimates the cost of the gather of zero-extended sub-fields of width
  /// \p FieldWidth of the same wider integer scalar \p Src, permuted by
  /// \p Mask, as a bitcast to the field vector plus a permutation and an
  /// extension to the lane type.
  InstructionCost createExtractedFieldsVector(Value *Src, unsigned FieldWidth,
                                              ArrayRef<int> Mask,
                                              const TreeEntry &E) {
    auto *FieldTy = IntegerType::get(Src->getContext(), FieldWidth);
    unsigned SrcWidth = Src->getType()->getIntegerBitWidth();
    assert(SrcWidth % FieldWidth == 0 &&
           "Expected the field width to divide the source width.");
    unsigned NumFields = SrcWidth / FieldWidth;
    auto *FieldVecTy = cast<VectorType>(getWidenedType(FieldTy, NumFields));
    TTI::CastContextHint CCH = R.getCastContextHint(E);
    InstructionCost Cost = TTI.getCastInstrCost(
        Instruction::BitCast, FieldVecTy, Src->getType(), CCH, CostKind);
    // The permutation is elided only for the full-length identity mask.
    if (Mask.size() != NumFields ||
        !ShuffleVectorInst::isIdentityMask(Mask, NumFields))
      Cost += getShuffleCost(TTI, TTI::SK_PermuteSingleSrc, FieldVecTy,
                             CostKind, Mask);
    if (!ScalarTy->isIntegerTy(FieldWidth))
      Cost += TTI.getCastInstrCost(
          Instruction::ZExt, getWidenedType(ScalarTy, Mask.size()),
          getWidenedType(FieldTy, Mask.size()), CCH, CostKind);
    // The extraction instructions die once the fields are emitted from the
    // source scalar; their scalar cost is credited back for the gathers
    // directly feeding the reduction. Instructions vectorized elsewhere are
    // skipped: their scalar cost is already a part of the scalar baseline.
    if (R.UserIgnoreList &&
        (!E.UserTreeIndex || E.UserTreeIndex.UserTE->Idx == 0))
      for (Instruction *I : make_isa_range<Instruction>(E.Scalars))
        if (CheckedExtracts.insert(I).second && !R.isVectorized(I) &&
            R.areAllUsersVectorized(I, &VectorizedVals))
          Cost -= isa<CastInst>(I)
                      ? TTI.getCastInstrCost(I->getOpcode(), I->getType(),
                                             I->getOperand(0)->getType(),
                                             TTI::getCastContextHint(I),
                                             CostKind, I)
                      : TTI.getArithmeticInstrCost(
                            I->getOpcode(), I->getType(), CostKind,
                            TTI::getOperandInfo(I->getOperand(0)),
                            TTI::getOperandInfo(I->getOperand(1)),
                            {I->getOperand(0), I->getOperand(1)}, I);
    return Cost;
  }
  InstructionCost createFreeze(InstructionCost Cost) { return Cost; }
  /// Finalize emission of the shuffles.
  InstructionCost finalize(
      ArrayRef<int> ExtMask,
      ArrayRef<std::pair<const TreeEntry *, unsigned>> SubVectors,
      ArrayRef<int> SubVectorsMask, unsigned VF = 0,
      function_ref<void(Value *&, SmallVectorImpl<int> &,
                        function_ref<Value *(Value *, Value *, ArrayRef<int>)>)>
          Action = {}) {
    IsFinalized = true;
    if (Action) {
      const PointerUnion<Value *, const TreeEntry *> &Vec =
          InVectors.front().Vec;
      if (InVectors.size() == 2)
        Cost += createShuffle(Vec, InVectors.back().Vec, CommonMask, {},
                              InVectors.front().Ctx, InVectors.back().Ctx);
      else
        Cost +=
            createShuffle(Vec, nullptr, CommonMask, {}, InVectors.front().Ctx);
      transformMaskAfterShuffle(CommonMask, CommonMask);
      assert(VF > 0 &&
             "Expected vector length for the final value before action.");
      Value *V = cast<Value *>(Vec);
      Action(V, CommonMask, [this](Value *V1, Value *V2, ArrayRef<int> Mask) {
        Cost += createShuffle(V1, V2, Mask);
        return V1;
      });
      InVectors.front() = V;
    }
    if (!SubVectors.empty()) {
      const PointerUnion<Value *, const TreeEntry *> &Vec =
          InVectors.front().Vec;
      if (InVectors.size() == 2)
        Cost += createShuffle(Vec, InVectors.back().Vec, CommonMask, {},
                              InVectors.front().Ctx, InVectors.back().Ctx);
      else
        Cost +=
            createShuffle(Vec, nullptr, CommonMask, {}, InVectors.front().Ctx);
      transformMaskAfterShuffle(CommonMask, CommonMask);
      // Add subvectors permutation cost.
      if (!SubVectorsMask.empty()) {
        assert(SubVectorsMask.size() <= CommonMask.size() &&
               "Expected same size of masks for subvectors and common mask.");
        SmallVector<int> SVMask(CommonMask.size(), PoisonMaskElem);
        copy(SubVectorsMask, SVMask.begin());
        for (auto [I1, I2] : zip(SVMask, CommonMask)) {
          if (I2 != PoisonMaskElem) {
            assert(I1 == PoisonMaskElem && "Expected unused subvectors mask");
            I1 = I2 + CommonMask.size();
          }
        }
        Cost += getShuffleCost(
            TTI, TTI::SK_PermuteTwoSrc,
            cast<VectorType>(getWidenedType(ScalarTy, CommonMask.size())),
            CostKind, SVMask);
      }
      for (auto [E, Idx] : SubVectors) {
        Type *EScalarTy = E->Scalars.front()->getType();
        bool IsSigned = true;
        if (auto It = R.MinBWs.find(E); It != R.MinBWs.end()) {
          EScalarTy =
              IntegerType::get(EScalarTy->getContext(), It->second.first);
          IsSigned = It->second.second;
        }
        if (ScalarTy != EScalarTy) {
          unsigned CastOpcode = Instruction::Trunc;
          unsigned DstSz = R.DL->getTypeSizeInBits(ScalarTy);
          unsigned SrcSz = R.DL->getTypeSizeInBits(EScalarTy);
          if (DstSz > SrcSz)
            CastOpcode = IsSigned ? Instruction::SExt : Instruction::ZExt;
          Cost += TTI.getCastInstrCost(
              CastOpcode, getWidenedType(ScalarTy, E->getVectorFactor()),
              getWidenedType(EScalarTy, E->getVectorFactor()),
              TTI::CastContextHint::Normal, CostKind);
        }
        Cost += getShuffleCost(
            TTI, TTI::SK_InsertSubvector,
            cast<VectorType>(getWidenedType(ScalarTy, CommonMask.size())),
            CostKind, {}, Idx,
            cast<VectorType>(getWidenedType(ScalarTy, E->getVectorFactor())));
        if (!CommonMask.empty()) {
          std::iota(std::next(CommonMask.begin(), Idx),
                    std::next(CommonMask.begin(), Idx + E->getVectorFactor()),
                    Idx);
        }
      }
    }

    if (!ExtMask.empty()) {
      if (CommonMask.empty()) {
        CommonMask.assign(ExtMask.begin(), ExtMask.end());
      } else {
        SmallVector<int> NewMask(ExtMask.size(), PoisonMaskElem);
        for (int I = 0, Sz = ExtMask.size(); I < Sz; ++I) {
          if (ExtMask[I] == PoisonMaskElem)
            continue;
          NewMask[I] = CommonMask[ExtMask[I]];
        }
        CommonMask.swap(NewMask);
      }
    }
    if (CommonMask.empty()) {
      assert(InVectors.size() == 1 && "Expected only one vector with no mask");
      return Cost;
    }
    ArrayRef<Value *> VL;
    if (BVValues)
      VL = *BVValues;
    if (InVectors.size() == 2)
      return Cost + createShuffle(InVectors.front().Vec, InVectors.back().Vec,
                                  CommonMask, VL, InVectors.front().Ctx,
                                  InVectors.back().Ctx);
    return Cost + createShuffle(InVectors.front().Vec, nullptr, CommonMask, VL,
                                InVectors.front().Ctx);
  }

  ~ShuffleCostEstimator() {
    assert((IsFinalized || CommonMask.empty()) &&
           "Shuffle construction must be finalized.");
  }
};

const BoUpSLP::TreeEntry *BoUpSLP::getOperandEntry(const TreeEntry *E,
                                                   unsigned Idx) const {
  TreeEntry *Op = OperandsToTreeEntry.at({E, Idx});
  assert(Op->isSame(E->getOperand(Idx)) && "Operands mismatch!");
  return Op;
}

TTI::CastContextHint BoUpSLP::getCastContextHint(const TreeEntry &TE) const {
  if (TE.State == TreeEntry::ScatterVectorize ||
      TE.State == TreeEntry::StridedVectorize)
    return TTI::CastContextHint::GatherScatter;
  if (TE.State == TreeEntry::CompressVectorize ||
      TE.State == TreeEntry::BlendedLoadVectorize)
    return TTI::CastContextHint::Masked;
  if (TE.State == TreeEntry::Vectorize && TE.getOpcode() == Instruction::Load &&
      !TE.isAltShuffle()) {
    if (TE.ReorderIndices.empty())
      return TTI::CastContextHint::Normal;
    SmallVector<int> Mask;
    inversePermutation(TE.ReorderIndices, Mask);
    if (ShuffleVectorInst::isReverseMask(Mask, Mask.size()))
      return TTI::CastContextHint::Reversed;
  }
  // A gather of extracted sub-fields inherits the context of the entry
  // vectorizing the common source scalar, or of the source scalar load. The
  // scalars erased by the vectorization have no operands to match.
  if (TE.isGather() && none_of(make_isa_range<Instruction>(TE.Scalars),
                               [&](Instruction *I) { return isDeleted(I); }))
    if (std::optional<std::tuple<Value *, unsigned, SmallVector<int>>> Fields =
            matchGatheredExtractedFields(TE.Scalars, *DL)) {
      Value *Src = std::get<0>(*Fields);
      if (ArrayRef<TreeEntry *> TEs = getTreeEntries(Src); !TEs.empty())
        return getCastContextHint(*TEs.front());
      if (isa<LoadInst>(Src))
        return TTI::CastContextHint::Normal;
    }
  return TTI::CastContextHint::None;
}

uint64_t BoUpSLP::getScaleToLoopIterations(const TreeEntry &TE, Value *Scalar,
                                           Instruction *U) {
  BasicBlock *Parent = nullptr;
  if (U) {
    // The extractelement for a PHI-node user is created in the incoming
    // block that feeds the matching operand, not in the PHI block itself
    // When the PHI is inside a loop that incoming block can belong to a deeper
    // loop than the PHI block. Scaling by the PHI block would use
    // the outer trip count instead of inner*outer, and because
    // ExtractCostCalculated deduplicates by scalar (only the first external
    // user fixes the scale) it would also make the cost depend on external-user
    // ordering. A PHI outside all loops is a plain loop-exit phi: its live-out
    // lanes are normally rebuilt as a vector LCSSA phi in the exit block, which
    // hoists the extract out of the loop, so scale = 1 (via U->getParent()
    // below) is kept and the adjustment is restricted to in-loop PHIs.
    if (auto *PHI = dyn_cast<PHINode>(U); PHI && Scalar) {
      if (LI->getLoopFor(PHI->getParent())) {
        // Use the deepest incoming block among all slots where Scalar
        // appears, to be conservative when the same value appears in
        // multiple predecessors.
        for (unsigned I : seq<unsigned>(PHI->getNumIncomingValues())) {
          if (PHI->getIncomingValue(I) != Scalar)
            continue;
          BasicBlock *InBB = PHI->getIncomingBlock(I);
          if (!Parent || LI->getLoopDepth(InBB) > LI->getLoopDepth(Parent))
            Parent = InBB;
        }
      }
    }
    if (!Parent)
      Parent = U->getParent();
  } else if (TE.isGather() || TE.State == TreeEntry::SplitVectorize) {
    EdgeInfo EI = TE.UserTreeIndex;
    while (EI.UserTE) {
      if (EI.UserTE->isGather() ||
          EI.UserTE->State == TreeEntry::SplitVectorize) {
        EI = EI.UserTE->UserTreeIndex;
        continue;
      }
      if (EI.UserTE->State == TreeEntry::Vectorize &&
          EI.UserTE->getOpcode() == Instruction::PHI) {
        auto *PH = cast<PHINode>(EI.UserTE->getMainOp());
        Parent = PH->getIncomingBlock(EI.EdgeIdx);
        const Loop *PhiL = LI->getLoopFor(PH->getParent());
        const Loop *InL = LI->getLoopFor(Parent);
        if (PhiL && InL && !PhiL->contains(InL) && !InL->contains(PhiL)) {
          const SCEV *PhiBTC = SE->getBackedgeTakenCount(PhiL);
          const SCEV *InBTC = SE->getBackedgeTakenCount(InL);
          if (isa<SCEVCouldNotCompute>(PhiBTC) || PhiBTC != InBTC) {
            // If all gathered elements are invariant in the phi's nest below
            // the common ancestor of the two nests, the gather is a pure
            // nest-crossing transfer, paid once per crossing: scale it by
            // the common parent nest.
            const Loop *FirstVariantL =
                findInnermostNonInvariantLoop(PhiL, TE.Scalars);
            if (FirstVariantL && FirstVariantL->contains(InL))
              Parent = FirstVariantL->getHeader();
          }
        }
      } else {
        Parent = EI.UserTE->getMainOp()->getParent();
      }
      break;
    }
    if (!Parent)
      return 1;
  } else {
    Parent = TE.getMainOp()->getParent();
  }
  const Loop *L = LI->getLoopFor(Parent);
  if (!L)
    return 1;
  // The entry's cost is paid once per execution of the innermost loop in
  // which some of its operands are variant. Operands that are invariant in
  // all enclosing loops are executed once (LICM will hoist them out).
  return getLoopNestScale(findInnermostNonInvariantLoop(
      L, Scalar ? ArrayRef(Scalar) : ArrayRef(TE.Scalars)));
}

uint64_t BoUpSLP::getLoopNestScale(const Loop *L) {
  if (!L || Opts.slp_cost_loop_trip_count == 0)
    return 1;
  if (auto It = LoopNestScaleCache.find(L); It != LoopNestScaleCache.end())
    return It->second;
  // Collect loops from L outward up to (but not including) the first cached
  // ancestor or the function top, then walk back inward multiplying trip
  // counts. Use uint64_t to avoid silent overflow on deep/large nests.
  SmallVector<const Loop *> Chain;
  for (const Loop *Cur = L; Cur; Cur = Cur->getParentLoop()) {
    if (LoopNestScaleCache.contains(Cur))
      break;
    Chain.push_back(Cur);
  }
  assert(!Chain.empty() && "Early-return above should have handled cache hit.");
  uint64_t Scale = 1;
  if (const Loop *Parent = Chain.back()->getParentLoop())
    Scale = LoopNestScaleCache.lookup(Parent);
  // Walk from the outermost uncached loop inward, accumulating trip counts.
  // Use SaturatingMultiply to clamp at uint64_t max on deep/large nests
  // rather than wrapping around.
  for (const Loop *Cur : reverse(Chain)) {
    uint64_t TC = std::max<uint64_t>(
        1, getLoopTripCount(Cur, *SE, Opts.slp_cost_loop_trip_count));
    Scale = SaturatingMultiply(Scale, TC);
    LoopNestScaleCache.try_emplace(Cur, std::max<uint64_t>(1, Scale));
  }
  return std::max<uint64_t>(1, Scale);
}

uint64_t BoUpSLP::getGatherNodeEffectiveScale(const TreeEntry &TE,
                                              Instruction *U) {
  // Only meaningful for gather/buildvector-like entries; the per-lane
  // insertelements that make up such an entry are LICM-hoistable by
  // optimizeGatherSequence() when their operand is loop-invariant.
  assert((TE.isGather() || TE.State == TreeEntry::SplitVectorize) &&
         "Expected gather/split tree entry.");

  uint64_t BaseScale = getScaleToLoopIterations(TE, nullptr, U);
  if (!Opts.slp_per_lane_gather_scale || Opts.slp_cost_loop_trip_count == 0 ||
      BaseScale <= 1)
    return BaseScale;

  // Average the per-lane execution scales: for each lane, reuse the same
  // scale helper the rest of the cost model uses, but ask it about that
  // one lane's value. Lanes that are loop-invariant in the current nest
  // collapse to their outer-loop scale (or 1 for fully invariant/constant
  // lanes), which matches the LICM hoisting performed by
  // optimizeGatherSequence(). Cap per-lane contributions by BaseScale so a
  // refinement can never raise the cost above the whole-entry scale.
  // Each lane contributes at most BaseScale, so Sum is bounded above by
  // N * BaseScale. If BaseScale is near uint64_t max (saturated by
  // getLoopNestScale on a deep nest) Sum can still overflow uint64_t,
  // which would silently wrap and produce a wrong average. Use
  // SaturatingAdd and bail out to BaseScale on overflow: the true average
  // is bounded above by BaseScale anyway, so this preserves the
  // refinement's invariant that it can never raise cost.
  uint64_t Sum = 0;
  unsigned N = 0;
  bool Overflow = false;
  for (Value *V :
       make_filter_range(TE.Scalars, [](Value *V) { return !isConstant(V); })) {
    ++N;
    uint64_t LaneScale =
        std::min(getScaleToLoopIterations(TE, V, U), BaseScale);
    Sum = SaturatingAdd(Sum, LaneScale, &Overflow);
    if (Overflow)
      return BaseScale;
  }
  if (N == 0)
    return BaseScale;
  // Ceil-divide so we never round the effective scale down below 1.
  uint64_t Numerator = SaturatingAdd(Sum, uint64_t(N - 1), &Overflow);
  if (Overflow)
    return BaseScale;
  uint64_t Avg = Numerator / N;
  return std::clamp<uint64_t>(Avg, 1, BaseScale);
}

uint64_t BoUpSLP::getEntryEffectiveScale(const TreeEntry &TE, Instruction *U) {
  if (TE.isGather() || TE.State == TreeEntry::SplitVectorize)
    return getGatherNodeEffectiveScale(TE, U);
  return getScaleToLoopIterations(TE);
}

InstructionCost
BoUpSLP::getVectorSpillReloadCost(const TreeEntry *E, Type *ScalarTy,
                                  Type *VecTy, Type *FinalVecTy,
                                  const TTI::TargetCostKind CostKind) const {
  InstructionCost SpillsReloads = 0;

  // Estimate vector register pressure per target register class: operand
  // vectors plus the result. The same vector operand is counted once via
  // CountedOpEntries deduplication. PHIs take the max operand pressure across
  // incoming slots (only one predecessor is live at a time) plus the result.
  // All-constant operand bundles are skipped.
  if (!E->hasState() || E->getOpcode() == Instruction::Store ||
      E->getOpcode() == Instruction::ExtractElement ||
      E->getOpcode() == Instruction::ExtractValue ||
      E->getOpcode() == Instruction::Freeze ||
      (E->getOpcode() == Instruction::Load &&
       E->State != TreeEntry::ScatterVectorize))
    return SpillsReloads;

  const bool IsPHI =
      E->State == TreeEntry::Vectorize && E->getOpcode() == Instruction::PHI;
  SmallPtrSet<const TreeEntry *, 8> CountedOpEntries;
  SmallDenseMap<unsigned, unsigned> PressureByClass;
  auto AddPartsToClass = [&](unsigned RegClass, unsigned Parts) {
    assert(Parts != 0 && "Expected non-zero number of parts (registers).");
    PressureByClass[RegClass] += Parts;
  };

  auto GetEntryVecTy = [&](const TreeEntry *TE) -> std::pair<Type *, Type *> {
    Type *ScalarTy = getValueType(TE->Scalars.front(), Opts.slp_revec);
    auto BWIt = MinBWs.find(TE);
    if (BWIt != MinBWs.end()) {
      auto *VTy = dyn_cast<FixedVectorType>(ScalarTy);
      ScalarTy = IntegerType::get(F->getContext(), BWIt->second.first);
      if (VTy)
        ScalarTy = getWidenedType(ScalarTy, VTy->getNumElements());
    }
    return std::make_pair(ScalarTy,
                          getWidenedType(ScalarTy, TE->getVectorFactor()));
  };

  if (E->State == TreeEntry::SplitVectorize) {
    for (const auto &[Idx, _] : E->CombinedEntriesWithIndices) {
      const TreeEntry *OpTE = VectorizableTree[Idx].get();

      if (!CountedOpEntries.insert(OpTE).second)
        continue;
      auto [ScalarTy, OpVecTy] = GetEntryVecTy(OpTE);
      const unsigned Parts = getNumberOfParts(OpVecTy, ScalarTy);
      if (Parts == 0)
        continue;
      const unsigned RC =
          TTI->getRegisterClassForType(/*Vector=*/true, OpVecTy);
      AddPartsToClass(RC, Parts);
    }
  } else if (IsPHI) {
    // Only one predecessor is live at a time - take the max operand pressure
    // across incoming slots.
    SmallDenseMap<unsigned, unsigned> MaxOpPressureByClass;
    for (unsigned Idx : seq<unsigned>(E->getNumOperands())) {
      const TreeEntry *OpTE = getOperandEntry(E, Idx);
      auto [ScalarTy, OpVecTy] = GetEntryVecTy(OpTE);
      const unsigned Parts = getNumberOfParts(OpVecTy, ScalarTy);
      if (Parts == 0)
        continue;
      const unsigned RC =
          TTI->getRegisterClassForType(/*Vector=*/true, OpVecTy);
      MaxOpPressureByClass[RC] = std::max(MaxOpPressureByClass[RC], Parts);
    }
    for (auto [RC, Parts] : MaxOpPressureByClass)
      AddPartsToClass(RC, Parts);
  } else {
    for (unsigned Idx : seq<unsigned>(E->getNumOperands())) {
      // InsertElement operand 0 is the vector being inserted into, which is
      // built incrementally and does not occupy an extra register.
      if ((E->getOpcode() == Instruction::InsertElement ||
           E->getOpcode() == Instruction::InsertValue) &&
          Idx == 0)
        continue;
      ArrayRef<Value *> Ops = E->getOperand(Idx);
      if (Ops.empty() || allConstant(Ops) || isSplat(Ops))
        continue;
      Value *Op = Ops.front();
      if (!Op)
        continue;
      const TreeEntry *OpTE = getOperandEntry(E, Idx);

      if (!CountedOpEntries.insert(OpTE).second)
        continue;
      auto *OpVecTy = getWidenedType(Op->getType(), Ops.size());
      const unsigned Parts = getNumberOfParts(OpVecTy, Op->getType());
      if (Parts == 0)
        continue;
      const unsigned RC =
          TTI->getRegisterClassForType(/*Vector=*/true, OpVecTy);
      AddPartsToClass(RC, Parts);
    }
  }

  if (E->getOpcode() != Instruction::Load) {
    const unsigned ResParts = getNumberOfParts(VecTy, ScalarTy);
    if (ResParts != 0) {
      const unsigned RC = TTI->getRegisterClassForType(/*Vector=*/true, VecTy);
      AddPartsToClass(RC, ResParts);
    }
    if (VecTy != FinalVecTy) {
      const unsigned FinalResParts = getNumberOfParts(FinalVecTy, ScalarTy);
      if (FinalResParts != 0) {
        const unsigned RC =
            TTI->getRegisterClassForType(/*Vector=*/true, FinalVecTy);
        AddPartsToClass(RC, FinalResParts);
      }
    }
  }

  for (auto [RegClass, UsedRegs] : PressureByClass) {
    const unsigned NumAvailRegs = TTI->getNumberOfRegisters(RegClass);
    if (NumAvailRegs == 0 || UsedRegs <= NumAvailRegs)
      continue;
    const unsigned SpillCount = UsedRegs - NumAvailRegs;
    InstructionCost SingleRegSpillReload =
        TTI->getRegisterClassReloadCost(RegClass, CostKind);
    // No need to spill cost only for the root entry (Idx == 0), for reduction
    // and non-returning instructions, like void calls.
    if (E->Idx > 0 || !UserIgnoreList || !E->Scalars[0]->getType()->isVoidTy())
      SingleRegSpillReload +=
          TTI->getRegisterClassSpillCost(RegClass, CostKind);
    SpillsReloads += SingleRegSpillReload * SpillCount;
  }
  return SpillsReloads;
}

/// Calculates a VectorInstrContext from the values in \p VL at indices in
/// \p DemandedElts.
static TTI::VectorInstrContext
getVectorInstrContextHint(ArrayRef<Value *> VL, const APInt &DemandedElts) {
  TTI::VectorInstrContext VIC = TTI::VectorInstrContext::None;
  for (unsigned I : seq(VL.size())) {
    if (!DemandedElts[I])
      continue;
    Value *V = VL[I];
    if (isa<UndefValue>(V))
      continue;
    auto *Inst = dyn_cast<Instruction>(V);
    if (!Inst)
      return TTI::VectorInstrContext::None;
    TTI::VectorInstrContext IVIC = TTI::getVectorInstrContextHint(Inst);
    if (VIC == TTI::VectorInstrContext::None) {
      VIC = IVIC;
      continue;
    }
    if (VIC != IVIC)
      return TTI::VectorInstrContext::None;
  }
  return VIC;
}

InstructionCost
BoUpSLP::getEntryCost(const TreeEntry *E, ArrayRef<Value *> VectorizedVals,
                      SmallPtrSetImpl<Value *> &CheckedExtracts) {
  ArrayRef<Value *> VL = E->Scalars;

  Type *ScalarTy = getValueType(VL[0], Opts.slp_revec);
  if (Opts.slp_revec && E->State == TreeEntry::Vectorize &&
      E->getOpcode() == Instruction::InsertElement &&
      !E->getOperand(1).back()->getType()->isVectorTy())
    ScalarTy = ScalarTy->getScalarType();
  if (!isValidElementType(ScalarTy, Opts.slp_revec))
    return InstructionCost::getInvalid();

  // If we have computed a smaller type for the expression, update VecTy so
  // that the costs will be accurate.
  auto It = MinBWs.find(E);
  Type *OrigScalarTy = ScalarTy;
  if (It != MinBWs.end()) {
    auto *VecTy = dyn_cast<FixedVectorType>(ScalarTy);
    ScalarTy = IntegerType::get(F->getContext(), It->second.first);
    if (VecTy)
      ScalarTy = getWidenedType(ScalarTy, VecTy->getNumElements());
  } else if (E->Idx == 0 && isReducedBitcastRoot() &&
             getRootNode().CombinedOp != TreeEntry::ReducedBitPack) {
    const TreeEntry *ZExt = getOperandEntry(E, /*Idx=*/0);
    ScalarTy = cast<CastInst>(ZExt->getMainOp())->getSrcTy();
  }
  auto *VecTy = getWidenedType(ScalarTy, VL.size());
  unsigned EntryVF = E->getVectorFactor();
  auto *FinalVecTy = getWidenedType(ScalarTy, EntryVF);

  const InstructionCost SpillsReloads =
      getVectorSpillReloadCost(E, ScalarTy, VecTy, FinalVecTy, CostKind);
  if (E->isGather() || TransformedToGatherNodes.contains(E)) {
    if (allConstant(VL))
      return 0;
    if (isa<InsertElementInst, InsertValueInst>(VL[0]))
      return InstructionCost::getInvalid();
    // The fmuls of the node turned into a gather stay scalar and lose the
    // fusion with their vectorized fadd/fsub users.
    return SpillsReloads +
           processBuildVector<ShuffleCostEstimator, InstructionCost>(
               E, ScalarTy, *TTI, VectorizedVals, *this, CheckedExtracts) +
           getUnfusedFMulsPenalty(*E);
  }
  if (E->State == TreeEntry::SplitVectorize) {
    assert(E->CombinedEntriesWithIndices.size() == 2 &&
           "Expected exactly 2 combined entries.");
    assert(E->ReuseShuffleIndices.empty() && "Expected empty reuses mask.");
    InstructionCost VectorCost = 0;
    if (E->ReorderIndices.empty()) {
      VectorCost = getShuffleCost(
          *TTI, TTI::SK_InsertSubvector, cast<VectorType>(FinalVecTy), CostKind,
          {}, E->CombinedEntriesWithIndices.back().second,
          cast<VectorType>(getWidenedType(
              ScalarTy,
              VectorizableTree[E->CombinedEntriesWithIndices.back().first]
                  ->getVectorFactor())));
    } else {
      unsigned CommonVF =
          std::max(VectorizableTree[E->CombinedEntriesWithIndices.front().first]
                       ->getVectorFactor(),
                   VectorizableTree[E->CombinedEntriesWithIndices.back().first]
                       ->getVectorFactor());
      VectorCost =
          getShuffleCost(*TTI, TTI::SK_PermuteTwoSrc,
                         cast<VectorType>(getWidenedType(ScalarTy, CommonVF)),
                         CostKind, E->getSplitMask());
    }
    VectorCost += SpillsReloads;
    LLVM_DEBUG(dumpTreeCosts(E, 0, VectorCost, 0, "Calculated costs for Tree"));
    return VectorCost;
  }
  InstructionCost CommonCost = 0;
  SmallVector<int> Mask;
  if (!E->ReorderIndices.empty() && E->State != TreeEntry::CompressVectorize &&
      (E->State != TreeEntry::StridedVectorize || !E->isReverse() ||
       isWidenedStridedLoad(E))) {
    SmallVector<int> NewMask;
    if (E->getOpcode() == Instruction::Store) {
      // For stores the order is actually a mask.
      NewMask.resize(E->ReorderIndices.size());
      copy(E->ReorderIndices, NewMask.begin());
    } else {
      inversePermutation(E->ReorderIndices, NewMask);
    }
    addMask(Mask, NewMask);
  }
  if (!E->ReuseShuffleIndices.empty())
    addMask(Mask, E->ReuseShuffleIndices);
  if (!Mask.empty() && !ShuffleVectorInst::isIdentityMask(Mask, Mask.size())) {
    assert(!isa<StructType>(FinalVecTy) &&
           "Expected non-struct vector type for shuffle cost calculation.");
    CommonCost = getShuffleCost(*TTI, TTI::SK_PermuteSingleSrc,
                                cast<VectorType>(FinalVecTy), CostKind, Mask,
                                /*Index=*/0, cast<VectorType>(VecTy));
  }
  assert((E->State == TreeEntry::Vectorize ||
          E->State == TreeEntry::ScatterVectorize ||
          E->State == TreeEntry::StridedVectorize ||
          E->State == TreeEntry::ExpandVectorize ||
          E->State == TreeEntry::CompressVectorize ||
          E->State == TreeEntry::BlendedLoadVectorize) &&
         "Unhandled state");
  assert(E->getOpcode() &&
         ((allSameType(VL) && allSameBlock(VL)) ||
          (E->getOpcode() == Instruction::GetElementPtr &&
           E->getMainOp()->getType()->isPointerTy()) ||
          E->hasCopyableElements()) &&
         "Invalid VL");
  Instruction *VL0 = E->getMainOp();
  unsigned ShuffleOrOp =
      E->isAltShuffle() ? (unsigned)Instruction::ShuffleVector : E->getOpcode();
  if (E->CombinedOp != TreeEntry::NotCombinedOp)
    ShuffleOrOp = E->CombinedOp;
  SmallSetVector<Value *, 16> UniqueValues;
  SmallVector<unsigned, 16> UniqueIndexes;
  for (auto [Idx, V] : enumerate(VL))
    if (UniqueValues.insert(V))
      UniqueIndexes.push_back(Idx);
  const unsigned Sz = UniqueValues.size();
  SmallBitVector UsedScalars(Sz, false);
  for (unsigned I = 0; I < Sz; ++I) {
    if (isa<Instruction>(UniqueValues[I]) &&
        !E->isCopyableElement(UniqueValues[I]) &&
        getTreeEntries(UniqueValues[I]).front() == E)
      continue;
    UsedScalars.set(I);
  }
  auto GetCastContextHint = [&](Value *V) {
    if (ArrayRef<TreeEntry *> OpTEs = getTreeEntries(V); OpTEs.size() == 1)
      return getCastContextHint(*OpTEs.front());
    InstructionsState SrcState = getSameOpcode(E->getOperand(0), *TLI);
    if (SrcState && SrcState.getOpcode() == Instruction::Load &&
        !SrcState.isAltShuffle())
      return TTI::CastContextHint::GatherScatter;
    return TTI::CastContextHint::None;
  };
  auto GetCostDiff =
      [=](function_ref<InstructionCost(unsigned)> ScalarEltCost,
          function_ref<InstructionCost(InstructionCost)> VectorCost) {
        // Calculate the cost of this instruction.
        InstructionCost ScalarCost = 0;
        if (isa<CastInst, CallInst>(VL0)) {
          // For some of the instructions no need to calculate cost for each
          // particular instruction, we can use the cost of the single
          // instruction x total number of scalar instructions.
          ScalarCost = (Sz - UsedScalars.count()) * ScalarEltCost(0);
        } else {
          for (unsigned I = 0; I < Sz; ++I) {
            if (UsedScalars.test(I))
              continue;
            ScalarCost += ScalarEltCost(I);
          }
        }

        InstructionCost VecCost = VectorCost(CommonCost);
        // Check if the current node must be resized, if the parent node is not
        // resized. Nodes without a parent (roots of the splat gather
        // subtrees) are resized back to their original type when the reusing
        // gather nodes are emitted.
        if (It != MinBWs.end() && !UnaryInstruction::isCast(E->getOpcode()) &&
            E->Idx != 0 &&
            (E->getOpcode() != Instruction::Load || E->UserTreeIndex)) {
          const EdgeInfo &EI = E->UserTreeIndex;
          if (!EI.UserTE || !EI.UserTE->hasState() ||
              EI.UserTE->getOpcode() != Instruction::Select ||
              EI.EdgeIdx != 0) {
            auto UserBWIt = MinBWs.find(EI.UserTE);
            Type *UserScalarTy =
                !EI.UserTE ? OrigScalarTy
                : (EI.UserTE->isGather() ||
                   EI.UserTE->State == TreeEntry::SplitVectorize)
                    ? EI.UserTE->Scalars.front()->getType()
                    : EI.UserTE->getOperand(EI.EdgeIdx).front()->getType();
            if (UserBWIt != MinBWs.end())
              UserScalarTy = IntegerType::get(ScalarTy->getContext(),
                                              UserBWIt->second.first);
            if (ScalarTy != UserScalarTy) {
              unsigned BWSz = DL->getTypeSizeInBits(ScalarTy);
              unsigned SrcBWSz = DL->getTypeSizeInBits(UserScalarTy);
              unsigned VecOpcode;
              auto *UserVecTy = getWidenedType(UserScalarTy, E->Scalars.size());
              if (BWSz > SrcBWSz)
                VecOpcode = Instruction::Trunc;
              else
                VecOpcode =
                    It->second.second ? Instruction::SExt : Instruction::ZExt;
              TTI::CastContextHint CCH = GetCastContextHint(VL0);
              VecCost += TTI->getCastInstrCost(VecOpcode, UserVecTy, VecTy, CCH,
                                               CostKind);
            }
          }
        }
        VecCost += SpillsReloads;
        LLVM_DEBUG(dumpTreeCosts(E, CommonCost, VecCost - CommonCost,
                                 ScalarCost, "Calculated costs for Tree"));
        return VecCost - ScalarCost;
      };
  // Price peeled intermediate instructions on the scalar side: they are
  // erased when the node vectorizes. The peeled cost is folded into the
  // first scalar-cost query so the cost dump reports the full scalar cost.
  // Peeled chain links are always 2-operand associative binops, priced per
  // instruction so the operand properties (constants, uniformity) apply.
  auto GetCostDiffWithPeeled =
      [&](function_ref<InstructionCost(unsigned)> ScalarEltCost,
          function_ref<InstructionCost(InstructionCost)> VectorCost) {
        InstructionCost PeeledScalarCost = 0;
        for (Value *V : E->getReassocScalars()) {
          auto *I = cast<Instruction>(V);
          TTI::OperandValueInfo Op1Info = TTI::getOperandInfo(I->getOperand(0));
          TTI::OperandValueInfo Op2Info = TTI::getOperandInfo(I->getOperand(1));
          PeeledScalarCost += TTI->getArithmeticInstrCost(
              I->getOpcode(), OrigScalarTy, CostKind, Op1Info, Op2Info, {}, I);
        }
        bool PeeledCostAdded = false;
        InstructionCost CostDiff = GetCostDiff(
            [&](unsigned Idx) {
              InstructionCost Cost = ScalarEltCost(Idx);
              if (!PeeledCostAdded) {
                PeeledCostAdded = true;
                Cost += PeeledScalarCost;
              }
              return Cost;
            },
            VectorCost);
        // Every scalar may be marked as used elsewhere, leaving the
        // scalar-cost query uncalled and the peeled cost unapplied.
        if (!PeeledCostAdded)
          CostDiff -= PeeledScalarCost;
        return CostDiff;
      };
  // Calculate cost difference from vectorizing set of GEPs.
  // Negative value means vectorizing is profitable.
  auto GetGEPCostDiff = [=](ArrayRef<Value *> Ptrs, Value *BasePtr) {
    assert((E->State == TreeEntry::Vectorize ||
            E->State == TreeEntry::StridedVectorize ||
            E->State == TreeEntry::ExpandVectorize ||
            E->State == TreeEntry::CompressVectorize) &&
           "Entry state expected to be Vectorize, StridedVectorize, "
           "ExpandVectorize or CompressVectorize here.");
    InstructionCost ScalarCost = 0;
    InstructionCost VecCost = 0;
    std::tie(ScalarCost, VecCost) =
        getGEPCosts(*TTI, Ptrs, BasePtr, E->getOpcode(), CostKind, OrigScalarTy,
                    cast<VectorType>(VecTy));
    LLVM_DEBUG(dumpTreeCosts(E, 0, VecCost, ScalarCost,
                             "Calculated GEPs cost for Tree"));

    return VecCost - ScalarCost + SpillsReloads;
  };

  auto GetMinMaxCost = [&](Type *Ty, Instruction *VI = nullptr) {
    auto [MinMaxID, SelectOnly] = canConvertToMinOrMaxIntrinsic(VI ? VI : VL);
    if (MinMaxID == Intrinsic::not_intrinsic)
      return InstructionCost::getInvalid();
    Type *CanonicalType = Ty;
    if (CanonicalType->isPtrOrPtrVectorTy())
      CanonicalType = CanonicalType->getWithNewType(IntegerType::get(
          CanonicalType->getContext(),
          DL->getTypeSizeInBits(CanonicalType->getScalarType())));

    IntrinsicCostAttributes CostAttrs(MinMaxID, CanonicalType,
                                      {CanonicalType, CanonicalType});
    InstructionCost IntrinsicCost =
        TTI->getIntrinsicInstrCost(CostAttrs, CostKind);
    // If the selects are the only uses of the compares, they will be
    // dead and we can adjust the cost by removing their cost.
    if (VI && SelectOnly) {
      assert((!Ty->isVectorTy() || Opts.slp_revec) &&
             "Expected only for scalar type.");
      auto *CI = cast<CmpInst>(VI->getOperand(0));
      IntrinsicCost -= TTI->getCmpSelInstrCost(
          CI->getOpcode(), Ty, Builder.getInt1Ty(), CI->getPredicate(),
          CostKind, TTI::getOperandInfo(CI->getOperand(0)),
          TTI::getOperandInfo(CI->getOperand(1)), CI);
    }
    return IntrinsicCost;
  };
  // The fadd/fsub, fused with its fmul operand into an fmuladd in the scalar
  // code. If the fmul is not vectorized, the vector code still emits it, so
  // only the fusion delta is attributed to the fadd/fsub.
  auto GetFMulAddCost = [&, &TTI = *TTI](const InstructionsState &S,
                                         Instruction *VI) {
    InstructionCost Cost = canConvertToFMA(VI, S, *DT, *DL, TTI, *TLI, *this);
    Instruction *FMul = getFusableFMulOperand(VI, TTI);
    if (!Cost.isValid() || !FMul || isVectorized(FMul))
      return Cost;
    InstructionCost FMulCost = getUnfusedBinOpCost(FMul, TTI, *TLI, CostKind);
    return Cost > FMulCost ? Cost - FMulCost : InstructionCost(TTI::TCC_Free);
  };
  // The fmul, fused into its fadd/fsub user, is free if the user lane is
  // priced as fmuladd, otherwise the user stays scalar and only the fusion
  // delta is attributed to the fmul.
  auto GetFusedFMulCost = [&, &TTI = *TTI](Instruction *VI) {
    auto [U, FMACost] = getFMulFusingUser(VI);
    if (!U)
      return InstructionCost::getInvalid();
    if (isFusedVectorizedFAddSub(U))
      return InstructionCost(TTI::TCC_Free);
    InstructionCost FAddCost = getUnfusedBinOpCost(U, TTI, *TLI, CostKind);
    return FMACost > FAddCost ? FMACost - FAddCost
                              : InstructionCost(TTI::TCC_Free);
  };
  switch (ShuffleOrOp) {
  case Instruction::PHI: {
    // Count reused scalars.
    InstructionCost ScalarCost = 0;
    SmallPtrSet<const TreeEntry *, 4> CountedOps;
    for (PHINode *PHI : make_isa_range<PHINode>(UniqueValues)) {
      ValueList Operands(PHI->getNumIncomingValues(), nullptr);
      for (unsigned I = 0, N = PHI->getNumIncomingValues(); I < N; ++I) {
        Value *Op = PHI->getIncomingValue(I);
        Operands[I] = Op;
      }
      if (const TreeEntry *OpTE =
              getSameValuesTreeEntry(Operands.front(), Operands))
        if (CountedOps.insert(OpTE).second &&
            !OpTE->ReuseShuffleIndices.empty())
          ScalarCost += TTI::TCC_Basic * (OpTE->ReuseShuffleIndices.size() -
                                          OpTE->Scalars.size());
    }

    return CommonCost - ScalarCost + SpillsReloads;
  }
  case Instruction::ExtractValue:
  case Instruction::ExtractElement: {
    // For ExtractValue entries vectorized via the struct-call path the scalar
    // extractvalue instructions are free (they become extractvalue from a
    // struct-of-vectors, which is also free). The cost is fully captured by
    // the underlying Call entry and the external-use extraction costs.
    if (ShuffleOrOp == Instruction::ExtractValue && !E->StructEVIndices.empty())
      return CommonCost;
    APInt DemandedElts;
    APInt CopyableInsertElts;
    VectorType *SrcVecTy = nullptr;
    auto GetScalarCost = [&](unsigned Idx) {
      if (isa<PoisonValue>(UniqueValues[Idx]))
        return InstructionCost(TTI::TCC_Free);

      // Copyable lanes are not extracts; they are inserted into the reused
      // source vector, so charge the insert to the vector side only.
      if (E->isCopyableElement(UniqueValues[Idx])) {
        if (CopyableInsertElts.isZero())
          CopyableInsertElts = APInt::getZero(E->getVectorFactor());
        CopyableInsertElts.setBit(Idx);
        return InstructionCost(TTI::TCC_Free);
      }

      auto *I = cast<Instruction>(UniqueValues[Idx]);
      // Undef/poison extract indices form holes in the reused source vector,
      // such lanes are free.
      std::optional<unsigned> ExtIdx = getExtractIndex(I);
      if (!ExtIdx)
        return InstructionCost(TTI::TCC_Free);
      if (!SrcVecTy) {
        if (ShuffleOrOp == Instruction::ExtractElement) {
          auto *EE = cast<ExtractElementInst>(I);
          SrcVecTy = EE->getVectorOperandType();
        } else {
          auto *EV = cast<ExtractValueInst>(I);
          Type *AggregateTy = EV->getAggregateOperand()->getType();
          unsigned NumElts;
          if (auto *ATy = dyn_cast<ArrayType>(AggregateTy))
            NumElts = ATy->getNumElements();
          else
            NumElts = AggregateTy->getStructNumElements();
          SrcVecTy = cast<VectorType>(getWidenedType(OrigScalarTy, NumElts));
        }
      }
      if (I->hasOneUse()) {
        Instruction *Ext = I->user_back();
        if ((isa<SExtInst>(Ext) || isa<ZExtInst>(Ext)) &&
            all_of(Ext->users(), IsaPred<GetElementPtrInst>)) {
          // Use getExtractWithExtendCost() to calculate the cost of
          // extractelement/ext pair.
          InstructionCost Cost = TTI->getExtractWithExtendCost(
              Ext->getOpcode(), Ext->getType(), SrcVecTy, *ExtIdx, CostKind);
          // Subtract the cost of s|zext which is subtracted separately.
          Cost -= TTI->getCastInstrCost(
              Ext->getOpcode(), Ext->getType(), I->getType(),
              TTI::getCastContextHint(Ext), CostKind, Ext);
          return Cost;
        }
      }
      // The extract, which the target folds into its users (e.g. the lane
      // operand of a by-element fmul on AArch64), costs nothing in the scalar
      // code; its removal saves nothing.
      if (ShuffleOrOp == Instruction::ExtractElement &&
          TTI->getVectorInstrCost(*I, SrcVecTy, CostKind, *ExtIdx,
                                  TTI::getVectorInstrContextHint(I)) == 0)
        return InstructionCost(TTI::TCC_Free);
      if (DemandedElts.isZero())
        DemandedElts = APInt::getZero(getNumElements(SrcVecTy));
      DemandedElts.setBit(*ExtIdx);
      return InstructionCost(TTI::TCC_Free);
    };
    auto GetVectorCost = [&, &TTI = *TTI](InstructionCost CommonCost) {
      return CommonCost +
             (CopyableInsertElts.isZero()
                  ? TTI::TCC_Free
                  : TTI.getScalarizationOverhead(
                        cast<VectorType>(
                            getWidenedType(OrigScalarTy, E->getVectorFactor())),
                        CopyableInsertElts, /*Insert=*/true,
                        /*Extract=*/false, CostKind)) -
             (DemandedElts.isZero()
                  ? TTI::TCC_Free
                  : TTI.getScalarizationOverhead(SrcVecTy, DemandedElts,
                                                 /*Insert=*/false,
                                                 /*Extract=*/true, CostKind));
    };
    return GetCostDiff(GetScalarCost, GetVectorCost);
  }
  case Instruction::InsertValue:
  case Instruction::InsertElement: {
    assert(E->ReuseShuffleIndices.empty() &&
           "Unique insertelements only are expected.");
    FixedVectorType *SrcVecTy = getInsertBuildVectorSrcTy(E);
    unsigned const NumElts = getNumElements(SrcVecTy);
    unsigned const NumScalars = VL.size();

    unsigned NumOfParts =
        getNumberOfParts(SrcVecTy, VL0->getOperand(1)->getType());

    SmallVector<int> InsertMask(NumElts, PoisonMaskElem);
    unsigned OffsetBeg = *getElementIndex(VL.front());
    unsigned OffsetEnd = OffsetBeg;
    InsertMask[OffsetBeg] = 0;
    for (auto [I, V] : enumerate(VL.drop_front())) {
      unsigned Idx = *getElementIndex(V);
      if (OffsetBeg > Idx)
        OffsetBeg = Idx;
      else if (OffsetEnd < Idx)
        OffsetEnd = Idx;
      InsertMask[Idx] = I + 1;
    }
    unsigned VecScalarsSz = PowerOf2Ceil(NumElts);
    if (NumOfParts > 0 && NumOfParts < NumElts)
      VecScalarsSz = PowerOf2Ceil((NumElts + NumOfParts - 1) / NumOfParts);
    unsigned VecSz = (1 + OffsetEnd / VecScalarsSz - OffsetBeg / VecScalarsSz) *
                     VecScalarsSz;
    unsigned Offset = VecScalarsSz * (OffsetBeg / VecScalarsSz);
    unsigned InsertVecSz = std::min<unsigned>(
        PowerOf2Ceil(OffsetEnd - OffsetBeg + 1),
        ((OffsetEnd - OffsetBeg + VecScalarsSz) / VecScalarsSz) * VecScalarsSz);
    bool IsWholeSubvector =
        OffsetBeg == Offset && ((OffsetEnd + 1) % VecScalarsSz == 0);
    // Check if we can safely insert a subvector. If it is not possible, just
    // generate a whole-sized vector and shuffle the source vector and the new
    // subvector.
    if (OffsetBeg + InsertVecSz > VecSz) {
      // Align OffsetBeg to generate correct mask.
      OffsetBeg = alignDown(OffsetBeg, VecSz, Offset);
      InsertVecSz = VecSz;
    }

    APInt DemandedElts = APInt::getZero(NumElts);
    // TODO: Add support for Instruction::InsertValue.
    SmallVector<int> Mask;
    if (!E->ReorderIndices.empty()) {
      inversePermutation(E->ReorderIndices, Mask);
      Mask.append(InsertVecSz - Mask.size(), PoisonMaskElem);
    } else {
      Mask.assign(VecSz, PoisonMaskElem);
      std::iota(Mask.begin(), std::next(Mask.begin(), InsertVecSz), 0);
    }
    bool IsIdentity = true;
    SmallVector<int> PrevMask(InsertVecSz, PoisonMaskElem);
    SmallVector<Value *> AdjustedVL(NumElts, PoisonValue::get(ScalarTy));
    Mask.swap(PrevMask);
    for (unsigned I = 0; I < NumScalars; ++I) {
      unsigned InsertIdx = *getElementIndex(VL[PrevMask[I]]);
      DemandedElts.setBit(InsertIdx);
      AdjustedVL[InsertIdx] = VL[PrevMask[I]];
      IsIdentity &= InsertIdx - OffsetBeg == I;
      Mask[InsertIdx - OffsetBeg] = I;
    }
    assert(Offset < NumElts && "Failed to find vector index offset");

    InstructionCost Cost = 0;
    // First cost - resize to actual vector size if not identity shuffle or
    // need to shift the vector.
    // Do not calculate the cost if the actual size is the register size and
    // we can merge this shuffle with the following SK_Select.
    auto *InsertVecTy = cast<VectorType>(getWidenedType(ScalarTy, InsertVecSz));
    if (!IsIdentity)
      Cost += getShuffleCost(*TTI, TargetTransformInfo::SK_PermuteSingleSrc,
                             InsertVecTy, CostKind, Mask);
    auto *FirstInsert = cast<Instruction>(*find_if(E->Scalars, [E](Value *V) {
      return !is_contained(E->Scalars, cast<Instruction>(V)->getOperand(0));
    }));
    // Second cost - permutation with subvector, if some elements are from the
    // initial vector or inserting a subvector.
    // TODO: Implement the analysis of the FirstInsert->getOperand(0)
    // subvector of ActualVecTy.
    SmallBitVector InMask =
        isUndefVector(FirstInsert->getOperand(0),
                      buildUseMask(NumElts, InsertMask, UseMask::UndefsAsMask));
    Cost -= getScalarizationOverhead(
        *TTI, Opts.slp_revec, ScalarTy, SrcVecTy, DemandedElts,
        /*Insert=*/true, /*Extract=*/false, CostKind, InMask.all(), AdjustedVL,
        getVectorInstrContextHint(AdjustedVL, DemandedElts));
    if (!InMask.all() && NumScalars != NumElts && !IsWholeSubvector) {
      if (InsertVecSz != VecSz) {
        auto *ActualVecTy = cast<VectorType>(getWidenedType(ScalarTy, VecSz));
        Cost += getShuffleCost(*TTI, TTI::SK_InsertSubvector, ActualVecTy,
                               CostKind, {}, OffsetBeg - Offset, InsertVecTy);
      } else {
        for (unsigned I = 0, End = OffsetBeg - Offset; I < End; ++I)
          Mask[I] = InMask.test(I) ? PoisonMaskElem : I;
        for (unsigned I = OffsetBeg - Offset, End = OffsetEnd - Offset;
             I <= End; ++I)
          if (Mask[I] != PoisonMaskElem)
            Mask[I] = I + VecSz;
        for (unsigned I = OffsetEnd + 1 - Offset; I < VecSz; ++I)
          Mask[I] =
              ((I >= InMask.size()) || InMask.test(I)) ? PoisonMaskElem : I;
        Cost += getShuffleCost(*TTI, TTI::SK_PermuteTwoSrc, InsertVecTy,
                               CostKind, Mask);
      }
    }
    if (ShuffleOrOp == Instruction::InsertValue &&
        !canVectorStoreInsertValue(E)) {
      // Match the stack slot alignment used during codegen (see the store +
      // load roundtrip in vectorizeTree()): the slot holds both the source
      // vector and the original aggregate.
      Align VecAlign = std::max(DL->getPrefTypeAlign(SrcVecTy),
                                DL->getPrefTypeAlign(VL0->getType()));
      // The stack slot roundtrip is synthesized by codegen; there is no IR
      // value or pointer to take operand info from.
      Cost += TTI->getMemoryOpCost(Instruction::Store, SrcVecTy, VecAlign,
                                   /*AddressSpace=*/0, CostKind) +
              TTI->getMemoryOpCost(Instruction::Load, VL0->getType(), VecAlign,
                                   /*AddressSpace=*/0, CostKind);
    }
    return Cost + SpillsReloads;
  }
  case Instruction::ZExt:
  case Instruction::SExt:
  case Instruction::FPToUI:
  case Instruction::FPToSI:
  case Instruction::FPExt:
  case Instruction::PtrToInt:
  case Instruction::PtrToAddr:
  case Instruction::IntToPtr:
  case Instruction::SIToFP:
  case Instruction::UIToFP:
  case Instruction::Trunc:
  case Instruction::FPTrunc:
  case Instruction::BitCast: {
    auto SrcIt = MinBWs.find(getOperandEntry(E, 0));
    Type *SrcScalarTy = VL0->getOperand(0)->getType();
    auto *SrcVecTy = getWidenedType(SrcScalarTy, VL.size());
    unsigned Opcode = ShuffleOrOp;
    unsigned VecOpcode = Opcode;
    // zext and uitofp cannot absorb the sign extension of a signed demoted
    // operand and inttoptr needs the original type, so extend it back first.
    std::optional<std::pair<uint64_t, bool>> ExtBackBW;
    if (SrcIt != MinBWs.end() &&
        (Opcode == Instruction::IntToPtr ||
         (SrcIt->second.second &&
          (Opcode == Instruction::UIToFP || Opcode == Instruction::ZExt)))) {
      ExtBackBW = SrcIt->second;
      SrcIt = MinBWs.end();
    }
    if (!ScalarTy->isFPOrFPVectorTy() && !SrcScalarTy->isFPOrFPVectorTy() &&
        (SrcIt != MinBWs.end() || It != MinBWs.end())) {
      // Check if the values are candidates to demote.
      unsigned SrcBWSz = DL->getTypeSizeInBits(SrcScalarTy->getScalarType());
      if (SrcIt != MinBWs.end()) {
        SrcBWSz = SrcIt->second.first;
        unsigned SrcScalarTyNumElements = getNumElements(SrcScalarTy);
        SrcScalarTy = IntegerType::get(F->getContext(), SrcBWSz);
        SrcVecTy =
            getWidenedType(SrcScalarTy, VL.size() * SrcScalarTyNumElements);
      }
      unsigned BWSz = DL->getTypeSizeInBits(ScalarTy->getScalarType());
      if (BWSz == SrcBWSz) {
        VecOpcode = Instruction::BitCast;
      } else if (BWSz < SrcBWSz) {
        VecOpcode = Instruction::Trunc;
      } else if (It != MinBWs.end()) {
        assert(BWSz > SrcBWSz && "Invalid cast!");
        VecOpcode = It->second.second ? Instruction::SExt : Instruction::ZExt;
      } else if (SrcIt != MinBWs.end()) {
        assert(BWSz > SrcBWSz && "Invalid cast!");
        VecOpcode =
            SrcIt->second.second ? Instruction::SExt : Instruction::ZExt;
      }
    } else if (VecOpcode == Instruction::SIToFP && SrcIt != MinBWs.end() &&
               !SrcIt->second.second) {
      VecOpcode = Instruction::UIToFP;
    }
    auto GetScalarCost = [&](unsigned Idx) -> InstructionCost {
      assert(Idx == 0 && "Expected 0 index only");
      return TTI->getCastInstrCost(Opcode, VL0->getType(),
                                   VL0->getOperand(0)->getType(),
                                   TTI::getCastContextHint(VL0), CostKind, VL0);
    };
    auto GetVectorCost = [=](InstructionCost CommonCost) {
      TTI::CastContextHint CCH = GetCastContextHint(VL0->getOperand(0));
      if (ExtBackBW)
        CommonCost += TTI->getCastInstrCost(
            ExtBackBW->second ? Instruction::SExt : Instruction::ZExt, SrcVecTy,
            SrcVecTy->getWithNewBitWidth(ExtBackBW->first), CCH, CostKind);
      // Do not count cost here if minimum bitwidth is in effect and it is just
      // a bitcast (here it is just a noop).
      if (VecOpcode != Opcode && VecOpcode == Instruction::BitCast)
        return CommonCost;
      auto *VI = VL0->getOpcode() == Opcode ? VL0 : nullptr;

      bool IsArithmeticExtendedReduction =
          E->Idx == 0 && UserIgnoreList &&
          all_of(*UserIgnoreList, [](Value *V) {
            auto *I = cast<Instruction>(V);
            return is_contained({Instruction::Add, Instruction::FAdd,
                                 Instruction::Mul, Instruction::FMul,
                                 Instruction::And, Instruction::Or,
                                 Instruction::Xor},
                                I->getOpcode());
          });
      if (IsArithmeticExtendedReduction &&
          (VecOpcode == Instruction::ZExt || VecOpcode == Instruction::SExt))
        return CommonCost;
      return CommonCost +
             TTI->getCastInstrCost(VecOpcode, VecTy, SrcVecTy, CCH, CostKind,
                                   VecOpcode == Opcode ? VI : nullptr);
    };
    return GetCostDiff(GetScalarCost, GetVectorCost);
  }
  case Instruction::FCmp:
  case Instruction::ICmp:
    // Override ScalarTy/VecTy with the compared operand type (not i1). The
    // cost of a compare instruction is determined by the operand width, and
    // getCmpSelInstrCost expects the compared type as its first type arg.
    OrigScalarTy = ScalarTy =
        getValueType(VL0, Opts.slp_revec, /*LookThroughCmp=*/true);
    VecTy = getWidenedType(ScalarTy, VL.size());
    [[fallthrough]];
  case Instruction::Select: {
    CmpPredicate VecPred, SwappedVecPred;
    auto MatchCmp = m_Cmp(VecPred, m_Value(), m_Value());
    if (match(VL0, m_Select(MatchCmp, m_Value(), m_Value())) ||
        match(VL0, MatchCmp))
      SwappedVecPred = CmpInst::getSwappedPredicate(VecPred);
    else
      SwappedVecPred = VecPred = ScalarTy->isFloatingPointTy()
                                     ? CmpInst::BAD_FCMP_PREDICATE
                                     : CmpInst::BAD_ICMP_PREDICATE;
    // The bit tests of trunc X to i1 lanes compare and A, B with a constant.
    const bool IsBitTest = any_of(E->Scalars, IsaPred<TruncInst>);
    auto GetScalarCost = [&](unsigned Idx) {
      if (isa<PoisonValue>(UniqueValues[Idx]))
        return InstructionCost(TTI::TCC_Free);

      if (!isa<SelectInst>(UniqueValues[Idx])) {
        auto *I = cast<Instruction>(UniqueValues[Idx]);
        InstructionCost Cost = TTI->getInstructionCost(I, CostKind);
        // The and of the bit test is erased with the compare.
        if (IsBitTest && isa<ICmpInst>(I))
          Cost += TTI->getInstructionCost(cast<Instruction>(I->getOperand(0)),
                                          CostKind);
        return Cost;
      }

      auto *VI = cast<Instruction>(UniqueValues[Idx]);
      CmpPredicate CurrentPred = ScalarTy->isFloatingPointTy()
                                     ? CmpInst::BAD_FCMP_PREDICATE
                                     : CmpInst::BAD_ICMP_PREDICATE;
      Value *LHS = nullptr, *RHS = nullptr;
      auto MatchCmp = m_Cmp(CurrentPred, m_Value(), m_Value());
      bool IsSelect =
          ShuffleOrOp == Instruction::Select &&
          (match(VI, m_Select(MatchCmp, m_Value(LHS), m_Value(RHS))) ||
           match(VI, m_Select(m_Value(), m_Value(LHS), m_Value(RHS))));
      if ((!IsSelect && !match(VI, MatchCmp)) ||
          (CurrentPred != static_cast<CmpInst::Predicate>(VecPred) &&
           CurrentPred != static_cast<CmpInst::Predicate>(SwappedVecPred)))
        VecPred = SwappedVecPred = ScalarTy->isFloatingPointTy()
                                       ? CmpInst::BAD_FCMP_PREDICATE
                                       : CmpInst::BAD_ICMP_PREDICATE;

      // Check if operands are of i1 types, like a condition expression.
      // TODO: consider implementing this in TTI.
      InstructionCost ScalarCost = InstructionCost::getInvalid();
      if (IsSelect && LHS->getType() == VI->getOperand(0)->getType()) {
        assert(LHS->getType() == RHS->getType() &&
               "Expected same type for LHS/RHS");
        // select i1 v, i1 true, i1 b -> or i1 v, i1 b
        if (match(LHS, m_AllOnes())) {
          ScalarCost = TTI->getArithmeticInstrCost(
              Instruction::Or, LHS->getType(), CostKind,
              TTI::getOperandInfo(VI->getOperand(0)), TTI::getOperandInfo(RHS));
        } else if (match(RHS, m_Zero())) {
          // select i1 v, i1 b, i1 false -> and i1 v, i1 b
          ScalarCost = TTI->getArithmeticInstrCost(
              Instruction::And, LHS->getType(), CostKind,
              TTI::getOperandInfo(VI->getOperand(0)), TTI::getOperandInfo(LHS));
        }
      }
      if (!ScalarCost.isValid()) {
        // For selects, the "condition type" arg is the condition operand's
        // type; for standalone compares, it is the result type (i1).
        ScalarCost = TTI->getCmpSelInstrCost(
            E->getOpcode(), OrigScalarTy,
            ShuffleOrOp == Instruction::Select ? VL0->getOperand(0)->getType()
                                               : VL0->getType(),
            CurrentPred, CostKind,
            TTI::getOperandInfo(
                VI->getOperand(ShuffleOrOp == Instruction::Select ? 1 : 0)),
            TTI::getOperandInfo(
                VI->getOperand(ShuffleOrOp == Instruction::Select ? 2 : 1)),
            VI);
      }
      InstructionCost IntrinsicCost = GetMinMaxCost(OrigScalarTy, VI);
      if (IntrinsicCost.isValid())
        ScalarCost = IntrinsicCost;

      return ScalarCost;
    };
    auto GetVectorCost = [&](InstructionCost CommonCost) {
      // An absorbed boolean zero-test leaf emits no conversion; only the
      // reorder shuffle (in CommonCost) may remain.
      if (isBooleanizedNode(E))
        return CommonCost;
      // For selects, the condition type may differ from the result type
      // (e.g. condition is <N x i1> while result is <N x i32>). For
      // compares, the result type IS the mask (i1/vNi1). Construct the
      // right type so getCmpSelInstrCost sees the actual mask/result width.
      auto *MaskTy = cast<VectorType>(getWidenedType(
          ShuffleOrOp == Instruction::Select ? VL0->getOperand(0)->getType()
                                             : VL0->getType(),
          VL.size()));

      InstructionCost VecCost = InstructionCost::getInvalid();
      if (ShuffleOrOp == Instruction::Select) {
        ArrayRef<Value *> Cond = E->getOperand(0);
        ArrayRef<Value *> LHS = E->getOperand(1);
        ArrayRef<Value *> RHS = E->getOperand(2);
        // select <VF x i1>, <VF x i1>, <VF x i1>?
        // TODO: consider implementing this in TTI.
        if (Cond.front()->getType() == LHS.front()->getType()) {
          // select <VF x i1> v, <VF x i1> true, <VF x i1> b -> or <VF x i1> v,
          // <VF x i1> b
          if (all_of(LHS, [&](Value *V) { return match(V, m_AllOnes()); })) {
            VecCost = TTI->getArithmeticInstrCost(
                Instruction::Or, VecTy, CostKind, TTI::getOperandInfo(Cond),
                TTI::getOperandInfo(RHS));
          } else if (all_of(RHS,
                            [&](Value *V) { return match(V, m_Zero()); })) {
            // select <VF x i1> v, <VF x i1> b, <VF x i1> false -> and <VF x i1>
            // v, <VF x i1> b
            VecCost = TTI->getArithmeticInstrCost(
                Instruction::And, VecTy, CostKind, TTI::getOperandInfo(Cond),
                TTI::getOperandInfo(LHS));
          }
        }
      }
      if (!VecCost.isValid()) {
        VecCost = TTI->getCmpSelInstrCost(
            E->getOpcode(), VecTy, MaskTy, VecPred, CostKind,
            TTI::getOperandInfo(
                E->getOperand(ShuffleOrOp == Instruction::Select ? 1 : 0)),
            TTI::getOperandInfo(
                E->getOperand(ShuffleOrOp == Instruction::Select ? 2 : 1)),
            VL0);
        if (IsBitTest)
          VecCost +=
              TTI->getArithmeticInstrCost(Instruction::And, VecTy, CostKind);
        if (isa<SelectInst>(VL0)) {
          unsigned CondNumElements = getNumElements(MaskTy);
          unsigned VecTyNumElements = getNumElements(VecTy);
          assert(VecTyNumElements >= CondNumElements &&
                 VecTyNumElements % CondNumElements == 0 &&
                 "Cannot vectorize Instruction::Select");
          if (CondNumElements != VecTyNumElements) {
            // When the return type is i1 but the source is fixed vector type,
            // we need to duplicate the condition value.
            VecCost += getShuffleCost(
                *TTI, TTI::SK_PermuteSingleSrc, MaskTy, CostKind,
                createReplicatedMask(VecTyNumElements / CondNumElements,
                                     CondNumElements));
          }
        }
      }
      return VecCost + CommonCost;
    };
    return GetCostDiff(GetScalarCost, GetVectorCost);
  }
  case TreeEntry::MinMax: {
    auto GetScalarCost = [&](unsigned Idx) {
      return GetMinMaxCost(OrigScalarTy);
    };
    auto GetVectorCost = [&](InstructionCost CommonCost) {
      InstructionCost VecCost = GetMinMaxCost(VecTy);
      return VecCost + CommonCost;
    };
    return GetCostDiff(GetScalarCost, GetVectorCost);
  }
  case TreeEntry::FMulAdd: {
    auto GetScalarCost = [&](unsigned Idx) {
      if (isa<PoisonValue>(UniqueValues[Idx]))
        return InstructionCost(TTI::TCC_Free);
      auto *I = cast<Instruction>(UniqueValues[Idx]);
      InstructionCost Cost = GetFMulAddCost(E->getOperations(), I);
      if (Cost.isValid())
        return Cost;
      // The lanes without the fmul, e.g. the constant lanes of the fmul node,
      // stay plain fadd/fsub.
      unsigned Lane = UniqueIndexes[Idx];
      Value *Op1 = E->getOperand(0)[Lane];
      Value *Op2 = E->getOperand(1)[Lane];
      return TTI->getArithmeticInstrCost(
          E->getOpcode(), OrigScalarTy, CostKind, TTI::getOperandInfo(Op1),
          TTI::getOperandInfo(Op2), {Op1, Op2}, I, TLI);
    };
    auto GetVectorCost = [&, &TTI = *TTI](InstructionCost CommonCost) {
      FastMathFlags FMF;
      FMF.set();
      for (FPMathOperator *FPCI : make_isa_range<FPMathOperator>(E->Scalars)) {
        FMF &= FPCI->getFastMathFlags();
        // The fused fmul may sit in either operand (c - a*b included).
        if (Instruction *FMul =
                getFusableFMulOperand(cast<Instruction>(FPCI), TTI))
          FMF &= FMul->getFastMathFlags();
      }
      IntrinsicCostAttributes ICA(Intrinsic::fmuladd, VecTy,
                                  {VecTy, VecTy, VecTy}, FMF);
      InstructionCost VecCost = TTI.getIntrinsicInstrCost(ICA, CostKind);
      return VecCost + CommonCost;
    };
    return GetCostDiff(GetScalarCost, GetVectorCost);
  }
  case TreeEntry::ReducedBitcast:
  case TreeEntry::ReducedBitcastBSwap: {
    auto GetScalarCost = [&, &TTI = *TTI](unsigned Idx) {
      if (isa<PoisonValue>(UniqueValues[Idx]))
        return InstructionCost(TTI::TCC_Free);
      auto *Shl = dyn_cast<Instruction>(UniqueValues[Idx]);
      if (!Shl)
        return InstructionCost(TTI::TCC_Free);
      InstructionCost ScalarCost = TTI.getInstructionCost(Shl, CostKind);
      auto *ZExt = dyn_cast<Instruction>(Shl->getOperand(0));
      if (!ZExt)
        return ScalarCost;
      ScalarCost += TTI.getInstructionCost(ZExt, CostKind);
      return ScalarCost;
    };
    auto GetVectorCost = [&, &TTI = *TTI](InstructionCost CommonCost) {
      const TreeEntry *LhsTE = getOperandEntry(E, /*Idx=*/0);
      TTI::CastContextHint CastCtx =
          getCastContextHint(*getOperandEntry(LhsTE, /*Idx=*/0));
      Type *SrcScalarTy = cast<ZExtInst>(LhsTE->getMainOp())->getSrcTy();
      auto *SrcVecTy = getWidenedType(SrcScalarTy, LhsTE->getVectorFactor());
      InstructionCost BitcastCost = TTI.getCastInstrCost(
          Instruction::BitCast, ScalarTy, SrcVecTy, CastCtx, CostKind);
      if (ShuffleOrOp == TreeEntry::ReducedBitcastBSwap) {
        auto *SrcType = IntegerType::getIntNTy(
            ScalarTy->getContext(),
            DL->getTypeSizeInBits(SrcScalarTy) * EntryVF);
        IntrinsicCostAttributes CostAttrs(Intrinsic::bswap, SrcType, {SrcType});
        InstructionCost IntrinsicCost =
            TTI.getIntrinsicInstrCost(CostAttrs, CostKind);
        BitcastCost += IntrinsicCost;
        if (SrcType != ScalarTy) {
          BitcastCost += TTI.getCastInstrCost(Instruction::ZExt, ScalarTy,
                                              SrcType, CastCtx, CostKind);
        }
      }
      return BitcastCost + CommonCost;
    };
    return GetCostDiff(GetScalarCost, GetVectorCost);
  }
  case TreeEntry::ReducedBitcastLoads:
  case TreeEntry::ReducedBitcastBSwapLoads: {
    auto GetScalarCost = [&, &TTI = *TTI](unsigned Idx) {
      if (isa<PoisonValue>(UniqueValues[Idx]))
        return InstructionCost(TTI::TCC_Free);
      auto *Shl = dyn_cast<Instruction>(UniqueValues[Idx]);
      if (!Shl)
        return InstructionCost(TTI::TCC_Free);
      InstructionCost ScalarCost = TTI.getInstructionCost(Shl, CostKind);
      auto *ZExt = dyn_cast<Instruction>(Shl->getOperand(0));
      if (!ZExt)
        return ScalarCost;
      ScalarCost += TTI.getInstructionCost(ZExt, CostKind);
      auto *Load = dyn_cast<Instruction>(ZExt->getOperand(0));
      if (!Load)
        return ScalarCost;
      ScalarCost += TTI.getInstructionCost(Load, CostKind);
      return ScalarCost;
    };
    auto GetVectorCost = [&, &TTI = *TTI](InstructionCost CommonCost) {
      const TreeEntry *LhsTE = getOperandEntry(E, /*Idx=*/0);
      const TreeEntry *LoadTE = getOperandEntry(LhsTE, /*Idx=*/0);
      auto *LI0 = cast<LoadInst>(LoadTE->getMainOp());
      auto *SrcType = IntegerType::getIntNTy(
          ScalarTy->getContext(),
          DL->getTypeSizeInBits(LI0->getType()) * EntryVF);
      InstructionCost LoadCost =
          TTI.getMemoryOpCost(Instruction::Load, SrcType, LI0->getAlign(),
                              LI0->getPointerAddressSpace(), CostKind);
      if (ShuffleOrOp == TreeEntry::ReducedBitcastBSwapLoads) {
        IntrinsicCostAttributes CostAttrs(Intrinsic::bswap, SrcType, {SrcType});
        InstructionCost IntrinsicCost =
            TTI.getIntrinsicInstrCost(CostAttrs, CostKind);
        LoadCost += IntrinsicCost;
        if (SrcType != ScalarTy) {
          LoadCost +=
              TTI.getCastInstrCost(Instruction::ZExt, ScalarTy, SrcType,
                                   getCastContextHint(*LoadTE), CostKind);
        }
      }
      return LoadCost + CommonCost;
    };
    return GetCostDiff(GetScalarCost, GetVectorCost);
  }
  case TreeEntry::ReducedBitPack: {
    const TreeEntry *ShlTE =
        E->getOpcode() == Instruction::And ? getOperandEntry(E, /*Idx=*/0) : E;
    const TreeEntry *LhsTE = getOperandEntry(ShlTE, /*Idx=*/0);
    std::optional<BitPackInfo> Info = computeBitPackLayout(*E);
    const TreeEntry *SrcTE = Info ? getBitPackSource(*LhsTE, *Info) : LhsTE;
    // The scalars of the root, the shl and the combined chain are removed.
    SmallVector<const TreeEntry *> CombinedTEs = {E};
    if (ShlTE != E)
      CombinedTEs.push_back(ShlTE);
    for (const TreeEntry *TE = LhsTE; TE != SrcTE;
         TE = getOperandEntry(TE, /*Idx=*/0))
      CombinedTEs.push_back(TE);
    auto GetLaneCost = [&, &TTI = *TTI](unsigned Lane) {
      InstructionCost ScalarCost = 0;
      for (const TreeEntry *TE : CombinedTEs) {
        auto *I = dyn_cast<Instruction>(TE->Scalars[Lane]);
        // A copyable lane is the operand of the node, costed with its node.
        if (!I || TE->isCopyableElement(I))
          continue;
        if (I->isCast()) {
          ScalarCost += TTI.getCastInstrCost(
              I->getOpcode(), I->getType(), I->getOperand(0)->getType(),
              TTI::getCastContextHint(I), CostKind, I);
          continue;
        }
        assert(is_contained(
                   {Instruction::And, Instruction::LShr, Instruction::Shl},
                   I->getOpcode()) &&
               "Expected and/shift in the bit pack.");
        ScalarCost += TTI.getArithmeticInstrCost(
            I->getOpcode(), I->getType(), CostKind,
            TTI::getOperandInfo(I->getOperand(0)),
            TTI::getOperandInfo(I->getOperand(1)),
            {I->getOperand(0), I->getOperand(1)}, I, TLI);
      }
      return ScalarCost;
    };
    auto GetScalarCost = [&](unsigned Idx) {
      return GetLaneCost(UniqueIndexes[Idx]);
    };
    auto GetVectorCost = [&, &TTI = *TTI](InstructionCost CommonCost) {
      if (!Info)
        return InstructionCost::getInvalid();
      unsigned ShiftWidth;
      // The pack works on the vectorized operand in its own (possibly
      // demoted) type.
      Type *SrcScalarTy = SrcTE->Scalars.front()->getType();
      if (auto It = MinBWs.find(SrcTE); It != MinBWs.end())
        SrcScalarTy = IntegerType::get(F->getContext(), It->second.first);
      // The source lanes are packed into the node type.
      Type *DstScalarTy = SrcTE == LhsTE ? SrcScalarTy : ScalarTy;
      InstructionCost PackCost =
          getBitPackCost(TTI,
                         cast<FixedVectorType>(getWidenedType(
                             SrcScalarTy, SrcTE->getVectorFactor())),
                         DstScalarTy, *Info, getZExtSrcWidth(*SrcTE),
                         getCastContextHint(*SrcTE), CostKind, TLI,
                         E->getMainOp(), ShiftWidth);
      // A demoted result is re-extended to the reduction type.
      if (DstScalarTy != OrigScalarTy) {
        auto It = MinBWs.find(E);
        PackCost += TTI.getCastInstrCost(
            It != MinBWs.end() && It->second.second ? Instruction::SExt
                                                    : Instruction::ZExt,
            OrigScalarTy, DstScalarTy, getCastContextHint(*LhsTE), CostKind);
      }
      // The copyable lanes are not the scalars of the node, but their scalars
      // in the shl and the combined chain are removed too.
      for (auto [Lane, V] : enumerate(E->Scalars))
        if (E->isCopyableElement(V))
          PackCost -= GetLaneCost(Lane);
      return PackCost + CommonCost;
    };
    return GetCostDiff(GetScalarCost, GetVectorCost);
  }
  case TreeEntry::ReducedCmpBitcast: {
    auto GetScalarCost = [&, &TTI = *TTI](unsigned Idx) {
      if (isa<PoisonValue>(UniqueValues[Idx]))
        return InstructionCost(TTI::TCC_Free);
      auto *Sel = dyn_cast<Instruction>(UniqueValues[Idx]);
      if (!Sel)
        return InstructionCost(TTI::TCC_Free);
      InstructionCost ScalarCost = TTI.getInstructionCost(Sel, CostKind);
      return ScalarCost;
    };
    auto GetVectorCost = [&, &TTI = *TTI](InstructionCost CommonCost) {
      Type *CmpTy = CmpInst::makeCmpResultType(VecTy);
      auto *DstTy =
          IntegerType::getIntNTy(ScalarTy->getContext(), E->getVectorFactor());
      InstructionCost BitcastCost =
          TTI.getCastInstrCost(Instruction::BitCast, DstTy, CmpTy,
                               TTI::CastContextHint::None, CostKind);
      if (DstTy != ScalarTy) {
        BitcastCost +=
            TTI.getCastInstrCost(Instruction::ZExt, ScalarTy, DstTy,
                                 TTI::CastContextHint::None, CostKind);
      }
      return BitcastCost + CommonCost;
    };
    return GetCostDiff(GetScalarCost, GetVectorCost);
  }
  case Instruction::FNeg:
  case Instruction::Add:
  case Instruction::FAdd:
  case Instruction::Sub:
  case Instruction::FSub:
  case Instruction::Mul:
  case Instruction::FMul:
  case Instruction::UDiv:
  case Instruction::SDiv:
  case Instruction::FDiv:
  case Instruction::URem:
  case Instruction::SRem:
  case Instruction::FRem:
  case Instruction::Shl:
  case Instruction::LShr:
  case Instruction::AShr:
  case Instruction::And:
  case Instruction::Or:
  case Instruction::Xor: {
    auto GetScalarCost = [&](unsigned Idx) {
      if (isa<PoisonValue>(UniqueValues[Idx]))
        return InstructionCost(TTI::TCC_Free);

      // We cannot retrieve the operand from UniqueValues[Idx] because an
      // interchangeable instruction may be used. The order and the actual
      // operand might differ from what is retrieved from UniqueValues[Idx].
      unsigned Lane = UniqueIndexes[Idx];
      Value *Op1 = E->getOperand(0)[Lane];
      Value *Op2;
      SmallVector<const Value *, 2> Operands(1, Op1);
      if (isa<UnaryOperator>(UniqueValues[Idx])) {
        Op2 = Op1;
      } else {
        Op2 = E->getOperand(1)[Lane];
        Operands.push_back(Op2);
      }
      TTI::OperandValueInfo Op1Info = TTI::getOperandInfo(Op1);
      TTI::OperandValueInfo Op2Info = TTI::getOperandInfo(Op2);
      auto *I = dyn_cast<Instruction>(UniqueValues[Idx]);
      InstructionCost ScalarCost = TTI->getArithmeticInstrCost(
          ShuffleOrOp, OrigScalarTy, CostKind, Op1Info, Op2Info, Operands,
          I && I->getOpcode() == ShuffleOrOp ? I : nullptr);
      if (I && (ShuffleOrOp == Instruction::FAdd ||
                ShuffleOrOp == Instruction::FSub)) {
        InstructionCost IntrinsicCost = GetFMulAddCost(E->getOperations(), I);
        if (IntrinsicCost.isValid())
          ScalarCost = IntrinsicCost;
      } else if (I && ShuffleOrOp == Instruction::FMul) {
        InstructionCost FusedCost = GetFusedFMulCost(I);
        if (FusedCost.isValid())
          ScalarCost = FusedCost;
      }
      return ScalarCost;
    };
    auto GetVectorCost = [=](InstructionCost CommonCost) {
      // And peephole only applies to plain 2-operand nodes.
      if (ShuffleOrOp == Instruction::And && It != MinBWs.end() &&
          !E->hasReassocScalars()) {
        for (unsigned I : seq<unsigned>(0, E->getNumOperands())) {
          ArrayRef<Value *> Ops = E->getOperand(I);
          if (all_of(Ops, [&](Value *Op) {
                auto *CI = dyn_cast<ConstantInt>(Op);
                return CI && CI->getValue().countr_one() >= It->second.first;
              }))
            return CommonCost;
        }
      }
      // Masked path ignores Op1Info/Op2Info like its codegen does; keep it
      // out of the operand-aware cost comparison below.
      if (InstructionCost MaskedCost = getMaskedDivRemCost(
              *TTI, Opts.slp_revec, ShuffleOrOp, ScalarTy, VL.size(), CostKind);
          MaskedCost.isValid())
        return MaskedCost + CommonCost;
      unsigned OpIdx = isa<UnaryOperator>(VL0) ? 0 : 1;
      TTI::OperandValueInfo Op1Info = TTI::getOperandInfo(E->getOperand(0));
      TTI::OperandValueInfo Op2Info = TTI::getOperandInfo(E->getOperand(OpIdx));
      InstructionCost Cost = TTI->getArithmeticInstrCost(
          ShuffleOrOp, VecTy, CostKind, Op1Info, Op2Info, {},
          VL0->getOpcode() == ShuffleOrOp ? VL0 : nullptr, TLI);
      // N columns need N-1 vector combines; price extra columns
      // conservatively, skipping identity-only columns (not combined by
      // codegen).
      if (E->hasReassocScalars()) {
        const unsigned CombineOpcode = getReassocCombineOpcode(E->getOpcode());
        for (unsigned Idx : seq<unsigned>(2, E->getNumOperands())) {
          if (all_of(E->getOperand(Idx), [&](Value *V) {
                return isBinOpIdentityConstant(V, CombineOpcode);
              }))
            continue;
          // The first operand is the running fold, a computed value with no
          // static properties to model.
          Cost += TTI->getArithmeticInstrCost(
              ShuffleOrOp, VecTy, CostKind, {},
              TTI::getOperandInfo(E->getOperand(Idx)), {},
              VL0->getOpcode() == ShuffleOrOp ? VL0 : nullptr, TLI);
        }
      }
      return Cost + CommonCost;
    };
    return GetCostDiffWithPeeled(GetScalarCost, GetVectorCost);
  }
  case Instruction::GetElementPtr: {
    return CommonCost + GetGEPCostDiff(VL, VL0);
  }
  case Instruction::Load: {
    auto GetScalarCost = [&](unsigned Idx) {
      auto *VI = cast<LoadInst>(UniqueValues[Idx]);
      return TTI->getMemoryOpCost(
          Instruction::Load, OrigScalarTy, VI->getAlign(),
          VI->getPointerAddressSpace(), CostKind,
          TTI::getOperandInfo(VI->getPointerOperand()), VI);
    };
    auto *LI0 = cast<LoadInst>(VL0);
    auto GetVectorCost = [&](InstructionCost CommonCost) {
      InstructionCost VecLdCost;
      switch (E->State) {
      case TreeEntry::Vectorize:
        if (unsigned Factor = E->getInterleaveFactor()) {
          VecLdCost = TTI->getInterleavedMemoryOpCost(
              Instruction::Load, VecTy, Factor, {}, LI0->getAlign(),
              LI0->getPointerAddressSpace(), CostKind);

        } else {
          VecLdCost = TTI->getMemoryOpCost(
              Instruction::Load, VecTy,
              commonAlignment(LI0->getAlign(), getVectorLoadShift(E->Scalars)),
              LI0->getPointerAddressSpace(), CostKind,
              TTI::getOperandInfo(LI0->getPointerOperand()));
        }
        break;
      case TreeEntry::StridedVectorize: {
        const StridedPtrInfo &SPtrInfo = TreeEntryToStridedPtrInfoMap.at(E);
        FixedVectorType *StridedLoadTy = SPtrInfo.Ty;
        assert(StridedLoadTy && "Missing StridedPointerInfo for tree entry.");
        Align CommonAlignment =
            computeCommonAlignment<LoadInst>(UniqueValues.getArrayRef());
        bool IsReverse = E->isReverse() && !isWidenedStridedLoad(E);
        Value *Stride = getStrideBytesIfConstant(SPtrInfo.StrideVal, ScalarTy,
                                                 *DL, IsReverse);
        VecLdCost = TTI->getMemIntrinsicInstrCost(
            MemIntrinsicCostAttributes(Intrinsic::experimental_vp_strided_load,
                                       StridedLoadTy, LI0->getPointerOperand(),
                                       /*VariableMask=*/false, CommonAlignment,
                                       /*I=*/nullptr, Stride),
            CostKind);
        if (StridedLoadTy != VecTy)
          VecLdCost +=
              getWidenedStridedCastCost(*TTI, StridedLoadTy, VecTy, *DL,
                                        getCastContextHint(*E), CostKind);

        break;
      }
      case TreeEntry::CompressVectorize: {
        bool IsMasked;
        unsigned InterleaveFactor;
        SmallVector<int> CompressMask;
        VectorType *LoadVecTy;
        SmallVector<Value *> Scalars(VL);
        if (!E->ReorderIndices.empty()) {
          SmallVector<int> Mask(E->ReorderIndices.begin(),
                                E->ReorderIndices.end());
          reorderScalars(Scalars, Mask);
        }
        SmallVector<Value *> PointerOps(Scalars.size());
        for (auto [I, V] : enumerate(Scalars))
          PointerOps[I] = cast<LoadInst>(V)->getPointerOperand();
        [[maybe_unused]] bool IsVectorized = isMaskedLoadCompress(
            Scalars, PointerOps, E->ReorderIndices, *TTI, *DL, *SE, *AC, *DT,
            *TLI, CostKind, [](Value *) { return true; }, Opts.slp_revec,
            IsMasked, InterleaveFactor, CompressMask, LoadVecTy, Cache);
        CompressEntryToData.try_emplace(E, CompressMask, LoadVecTy,
                                        InterleaveFactor, IsMasked);
        Align CommonAlignment = LI0->getAlign();
        // For REVEC the emitted shuffle uses the compress mask expanded to the
        // individual elements of the vector scalars.
        SmallVector<int> CompressCostMask(CompressMask);
        transformScalarShuffleIndiciesToVector(getNumElements(LI0->getType()),
                                               CompressCostMask);
        if (InterleaveFactor) {
          VecLdCost = TTI->getInterleavedMemoryOpCost(
              Instruction::Load, LoadVecTy, InterleaveFactor, {},
              CommonAlignment, LI0->getPointerAddressSpace(), CostKind);
        } else if (IsMasked) {
          VecLdCost = TTI->getMemIntrinsicInstrCost(
              MemIntrinsicCostAttributes(Intrinsic::masked_load, LoadVecTy,
                                         CommonAlignment,
                                         LI0->getPointerAddressSpace()),
              CostKind);
          // TODO: include this cost into CommonCost.
          VecLdCost += getShuffleCost(*TTI, TTI::SK_PermuteSingleSrc, LoadVecTy,
                                      CostKind, CompressCostMask);
        } else {
          VecLdCost = TTI->getMemoryOpCost(
              Instruction::Load, LoadVecTy, CommonAlignment,
              LI0->getPointerAddressSpace(), CostKind,
              TTI::getOperandInfo(LI0->getPointerOperand()));
          // TODO: include this cost into CommonCost.
          VecLdCost += getShuffleCost(*TTI, TTI::SK_PermuteSingleSrc, LoadVecTy,
                                      CostKind, CompressCostMask);
        }
        break;
      }
      case TreeEntry::ScatterVectorize: {
        Align CommonAlignment =
            computeCommonAlignment<LoadInst>(UniqueValues.getArrayRef());
        VecLdCost = TTI->getMemIntrinsicInstrCost(
            MemIntrinsicCostAttributes(Intrinsic::masked_gather, VecTy,
                                       LI0->getPointerOperand(),
                                       /*VariableMask=*/false, CommonAlignment),
            CostKind);
        break;
      }
      case TreeEntry::BlendedLoadVectorize: {
        // Two masked loads (one per candidate base) blended by a select.
        Align CommonAlignment =
            computeBlendedLoadBaseAlignment(UniqueValues.getArrayRef(), *DL);
        VecLdCost = getBlendedLoadCost(*TTI, VecTy, CommonAlignment,
                                       LI0->getPointerAddressSpace(), CostKind);
        break;
      }
      case TreeEntry::ExpandVectorize:
      case TreeEntry::CombinedVectorize:
      case TreeEntry::SplitVectorize:
      case TreeEntry::NeedToGather:
        llvm_unreachable("Unexpected vectorization state.");
      }
      return VecLdCost + CommonCost;
    };

    InstructionCost Cost = GetCostDiff(GetScalarCost, GetVectorCost);
    // Masked gather and blended loads are not terminal nodes: their address
    // cost is estimated separately (blended loads have no per-lane address).
    if (E->State == TreeEntry::ScatterVectorize ||
        E->State == TreeEntry::BlendedLoadVectorize)
      return Cost;

    // Estimate cost of GEPs since this tree node is a terminator.
    SmallVector<Value *> PointerOps;
    for (LoadInst *LI : make_isa_range<LoadInst>(VL))
      PointerOps.push_back(LI->getPointerOperand());
    return Cost + GetGEPCostDiff(PointerOps, LI0->getPointerOperand());
  }
  case Instruction::Store: {
    bool IsReorder = !E->ReorderIndices.empty();
    auto GetScalarCost = [=](unsigned Idx) {
      auto *VI = cast<StoreInst>(VL[Idx]);
      TTI::OperandValueInfo OpInfo = TTI::getOperandInfo(VI->getValueOperand());
      return TTI->getMemoryOpCost(Instruction::Store, OrigScalarTy,
                                  VI->getAlign(), VI->getPointerAddressSpace(),
                                  CostKind, OpInfo, VI);
    };
    auto *BaseSI =
        cast<StoreInst>(IsReorder ? VL[E->ReorderIndices.front()] : VL0);
    auto GetVectorCost = [=](InstructionCost CommonCost) {
      // We know that we can merge the stores. Calculate the cost.
      InstructionCost VecStCost;
      if (E->State == TreeEntry::StridedVectorize) {
        const StridedPtrInfo &SPtrInfo = TreeEntryToStridedPtrInfoMap.at(E);
        FixedVectorType *StridedStoreTy = SPtrInfo.Ty;
        assert(StridedStoreTy && "Missing StridedPointerInfo for tree entry.");
        Align CommonAlignment =
            computeCommonAlignment<StoreInst>(UniqueValues.getArrayRef());
        Value *Stride =
            getStrideBytesIfConstant(SPtrInfo.StrideVal, ScalarTy, *DL);
        VecStCost = TTI->getMemIntrinsicInstrCost(
            MemIntrinsicCostAttributes(Intrinsic::experimental_vp_strided_store,
                                       StridedStoreTy,
                                       BaseSI->getPointerOperand(),
                                       /*VariableMask=*/false, CommonAlignment,
                                       /*I=*/nullptr, Stride),
            CostKind);
        if (StridedStoreTy != VecTy)
          VecStCost +=
              getWidenedStridedCastCost(*TTI, VecTy, StridedStoreTy, *DL,
                                        getCastContextHint(*E), CostKind);
      } else if (E->State == TreeEntry::ExpandVectorize) {
        const StridedPtrInfo &SPtrInfo = TreeEntryToStridedPtrInfoMap.at(E);
        FixedVectorType *MaskedStoreTy = SPtrInfo.Ty;
        assert(MaskedStoreTy && "Missing StridedPointerInfo for tree entry.");
        Align CommonAlignment =
            computeCommonAlignment<StoreInst>(UniqueValues.getArrayRef());
        // Masked store: the values are expanded into the widened vector and
        // stored with a constant mask.
        VecStCost = TTI->getMemIntrinsicInstrCost(
            MemIntrinsicCostAttributes(Intrinsic::masked_store, MaskedStoreTy,
                                       CommonAlignment,
                                       BaseSI->getPointerAddressSpace()),
            CostKind);
      } else {
        assert(E->State == TreeEntry::Vectorize &&
               "Expected either strided, consecutive, or expanded stores.");
        if (unsigned Factor = E->getInterleaveFactor()) {
          assert(E->ReuseShuffleIndices.empty() && !E->ReorderIndices.empty() &&
                 "No reused shuffles expected");
          CommonCost = 0;
          VecStCost = TTI->getInterleavedMemoryOpCost(
              Instruction::Store, VecTy, Factor, {}, BaseSI->getAlign(),
              BaseSI->getPointerAddressSpace(), CostKind);
        } else {
          TTI::OperandValueInfo OpInfo = TTI::getOperandInfo(E->getOperand(0));
          VecStCost = TTI->getMemoryOpCost(
              Instruction::Store, VecTy, BaseSI->getAlign(),
              BaseSI->getPointerAddressSpace(), CostKind, OpInfo);
        }
      }
      return VecStCost + CommonCost;
    };
    SmallVector<Value *> PointerOps(VL.size());
    for (auto [I, V] : enumerate(VL)) {
      unsigned Idx = IsReorder ? E->ReorderIndices[I] : I;
      PointerOps[Idx] = cast<StoreInst>(V)->getPointerOperand();
    }

    return GetCostDiff(GetScalarCost, GetVectorCost) +
           GetGEPCostDiff(PointerOps, BaseSI->getPointerOperand());
  }
  case Instruction::Call: {
    auto GetScalarCost = [&](unsigned Idx) {
      // A copyable lane has no scalar call of its own; its real cost is
      // accounted for wherever it is otherwise computed.
      if (isa<PoisonValue>(UniqueValues[Idx]) ||
          E->isCopyableElement(UniqueValues[Idx]))
        return InstructionCost(TTI::TCC_Free);
      auto *CI = cast<CallInst>(UniqueValues[Idx]);
      Intrinsic::ID ID = getVectorIntrinsicIDForCall(CI, TLI);
      if (ID != Intrinsic::not_intrinsic) {
        IntrinsicCostAttributes CostAttrs(ID, *CI, 1);
        return TTI->getIntrinsicInstrCost(CostAttrs, CostKind);
      }
      return TTI->getCallInstrCost(CI->getCalledFunction(),
                                   CI->getFunctionType()->getReturnType(),
                                   CI->getFunctionType()->params(), CostKind);
    };
    auto GetVectorCost = [=](InstructionCost CommonCost) {
      auto *CI = cast<CallInst>(VL0);
      Intrinsic::ID ID = getVectorIntrinsicIDForCall(CI, TLI);
      SmallVector<Type *> ArgTys = buildIntrinsicArgTypes(
          CI, ID, getNumElements(VecTy),
          It != MinBWs.end() ? It->second.first : 0, TTI);
      auto VecCallCosts =
          getVectorCallCosts(CI, VecTy, TTI, TLI, ArgTys, CostKind);
      return std::min(VecCallCosts.first, VecCallCosts.second) + CommonCost;
    };
    return GetCostDiff(GetScalarCost, GetVectorCost);
  }
  case Instruction::ShuffleVector: {
    if (!Opts.slp_revec || E->isAltShuffle())
      assert(E->isAltShuffle() &&
             ((Instruction::isBinaryOp(E->getOpcode()) &&
               Instruction::isBinaryOp(E->getAltOpcode())) ||
              (Instruction::isCast(E->getOpcode()) &&
               Instruction::isCast(E->getAltOpcode())) ||
              (isa<CmpInst>(VL0) && isa<CmpInst>(E->getAltOp()))) &&
             "Invalid Shuffle Vector Operand");
    // Try to find the previous shuffle node with the same operands and same
    // main/alternate ops.
    auto TryFindNodeWithEqualOperands = [=]() {
      for (const std::unique_ptr<TreeEntry> &TE : VectorizableTree) {
        if (TE.get() == E)
          break;
        if (TE->hasState() && TE->isAltShuffle() &&
            ((TE->getOpcode() == E->getOpcode() &&
              TE->getAltOpcode() == E->getAltOpcode()) ||
             (TE->getOpcode() == E->getAltOpcode() &&
              TE->getAltOpcode() == E->getOpcode())) &&
            TE->hasEqualOperands(*E))
          return true;
      }
      return false;
    };
    auto GetScalarCost = [&](unsigned Idx) {
      if (isa<PoisonValue>(UniqueValues[Idx]))
        return InstructionCost(TTI::TCC_Free);

      auto *VI = cast<Instruction>(UniqueValues[Idx]);
      assert(E->getMatchingMainOpOrAltOp(VI) &&
             "Unexpected main/alternate opcode");
      (void)E;
      if (auto *CI = dyn_cast<CmpInst>(VI))
        return TTI->getCmpSelInstrCost(
            CI->getOpcode(), CI->getOperand(0)->getType(), CI->getType(),
            CI->getPredicate(), CostKind,
            TTI::getOperandInfo(CI->getOperand(0)),
            TTI::getOperandInfo(CI->getOperand(1)), CI);
      if (auto *CI = dyn_cast<CastInst>(VI))
        return TTI->getCastInstrCost(CI->getOpcode(), CI->getDestTy(),
                                     CI->getSrcTy(),
                                     TTI::getCastContextHint(CI), CostKind, CI);
      if (auto *SV = dyn_cast<ShuffleVectorInst>(VI)) {
        int Index;
        [[maybe_unused]] bool IsExtractSubvectorMask =
            SV->isExtractSubvectorMask(Index);
        assert(IsExtractSubvectorMask && "Not supported shufflevector usage.");
        auto *SubTy = cast<VectorType>(SV->getType());
        return TTI->getShuffleCost(
            TTI::SK_ExtractSubvector, SubTy,
            cast<VectorType>(SV->getOperand(0)->getType()), CostKind,
            SV->getShuffleMask(), Index, SubTy,
            {SV->getOperand(0), SV->getOperand(1)}, SV,
            TTI::getVectorInstrContextHint(SV));
      }
      // The backend fuses fmul+fadd/fsub pairs in the scalar code.
      InstructionCost FusedCost = InstructionCost::getInvalid();
      if (match(VI, m_CombineOr(m_FAdd(m_Value(), m_Value()),
                                m_FSub(m_Value(), m_Value()))))
        FusedCost = GetFMulAddCost(InstructionsState(VI, VI), VI);
      else if (match(VI, m_FMul(m_Value(), m_Value())))
        FusedCost = GetFusedFMulCost(VI);
      if (FusedCost.isValid())
        return FusedCost;
      return TTI->getArithmeticInstrCost(
          VI->getOpcode(), VI->getType(), CostKind,
          TTI::getOperandInfo(VI->getOperand(0)),
          TTI::getOperandInfo(VI->getOperand(1)),
          {VI->getOperand(0), VI->getOperand(1)}, VI, TLI);
    };
    // Need to clear CommonCost since the final shuffle cost is included into
    // vector cost.
    auto GetVectorCost = [&, &TTIRef = *TTI](InstructionCost) {
      // VecCost is equal to sum of the cost of creating 2 vectors
      // and the cost of creating shuffle.
      InstructionCost VecCost = 0;
      if (TryFindNodeWithEqualOperands()) {
        LLVM_DEBUG({
          dbgs() << "SLP: diamond match for alternate node found.\n";
          E->dump();
        });
        // No need to add new vector costs here since we're going to reuse
        // same main/alternate vector ops, just do different shuffling.
      } else if (Instruction::isBinaryOp(E->getOpcode())) {
        // Peeled alternate chains fold the operand columns into one pure
        // main-opcode chain and one pure alt-opcode chain, followed by a
        // single lane-select shuffle; a plain alternate node is a single
        // combine. Each combine is priced with the properties of the column
        // it folds in; the other operand is the running fold, which stays
        // constant while every folded column is constant (such combines
        // constant-fold away in codegen) and stays uniform while every
        // folded column is uniform.
        auto ChainCost = [&](unsigned Opcode) {
          InstructionCost Cost = 0;
          TTI::OperandValueInfo RunningInfo =
              TTI::getOperandInfo(E->getOperand(0));
          for (unsigned Idx : seq<unsigned>(1, E->getNumOperands())) {
            TTI::OperandValueInfo ColInfo =
                TTI::getOperandInfo(E->getOperand(Idx));
            if (!RunningInfo.isConstant() || !ColInfo.isConstant())
              Cost += TTIRef.getArithmeticInstrCost(
                  Opcode, VecTy, CostKind, RunningInfo, ColInfo, {},
                  Opcode == E->getOpcode() ? E->getMainOp() : E->getAltOp(),
                  TLI);
            TTI::OperandValueKind Kind = TTI::OK_AnyValue;
            if (RunningInfo.isConstant() && ColInfo.isConstant())
              Kind = RunningInfo.Kind == TTI::OK_UniformConstantValue &&
                             ColInfo.Kind == TTI::OK_UniformConstantValue
                         ? TTI::OK_UniformConstantValue
                         : TTI::OK_NonUniformConstantValue;
            else if (RunningInfo.isUniform() && ColInfo.isUniform())
              Kind = TTI::OK_UniformValue;
            RunningInfo = {Kind, TTI::OP_None};
          }
          return Cost;
        };
        VecCost = ChainCost(E->getOpcode()) + ChainCost(E->getAltOpcode());
      } else if (auto *CI0 = dyn_cast<CmpInst>(VL0)) {
        auto *MaskTy = getWidenedType(Builder.getInt1Ty(), VL.size());
        TTI::OperandValueInfo Op0Info = TTI::getOperandInfo(E->getOperand(0));
        TTI::OperandValueInfo Op1Info = TTI::getOperandInfo(E->getOperand(1));
        VecCost = TTIRef.getCmpSelInstrCost(E->getOpcode(), VecTy, MaskTy,
                                            CI0->getPredicate(), CostKind,
                                            Op0Info, Op1Info, VL0);
        VecCost += TTIRef.getCmpSelInstrCost(
            E->getOpcode(), VecTy, MaskTy,
            cast<CmpInst>(E->getAltOp())->getPredicate(), CostKind, Op0Info,
            Op1Info, E->getAltOp());
      } else {
        Type *SrcSclTy = E->getMainOp()->getOperand(0)->getType();
        auto *SrcTy = getWidenedType(SrcSclTy, VL.size());
        if (SrcSclTy->isIntegerTy() && ScalarTy->isIntegerTy()) {
          auto SrcIt = MinBWs.find(getOperandEntry(E, 0));
          unsigned BWSz = DL->getTypeSizeInBits(ScalarTy);
          unsigned SrcBWSz =
              DL->getTypeSizeInBits(E->getMainOp()->getOperand(0)->getType());
          if (SrcIt != MinBWs.end()) {
            SrcBWSz = SrcIt->second.first;
            SrcSclTy = IntegerType::get(SrcSclTy->getContext(), SrcBWSz);
            SrcTy = getWidenedType(SrcSclTy, VL.size());
          }
          if (BWSz <= SrcBWSz) {
            if (BWSz < SrcBWSz)
              VecCost = TTIRef.getCastInstrCost(
                  Instruction::Trunc, VecTy, SrcTy,
                  GetCastContextHint(E->getMainOp()->getOperand(0)), CostKind);
            LLVM_DEBUG({
              dbgs()
                  << "SLP: alternate extension, which should be truncated.\n";
              E->dump();
            });
            return VecCost;
          }
        }
        VecCost = TTIRef.getCastInstrCost(
            E->getOpcode(), VecTy, SrcTy,
            GetCastContextHint(E->getMainOp()->getOperand(0)), CostKind,
            E->getMainOp());
        VecCost += TTIRef.getCastInstrCost(
            E->getAltOpcode(), VecTy, SrcTy,
            GetCastContextHint(E->getMainOp()->getOperand(0)), CostKind,
            E->getAltOp());
      }
      SmallVector<int> Mask;
      E->buildAltOpShuffleMask(
          [&](Instruction *I) {
            assert(E->getMatchingMainOpOrAltOp(I) &&
                   "Unexpected main/alternate opcode");
            return isAlternateInstruction(I, E->getMainOp(), E->getAltOp(),
                                          *TLI);
          },
          Mask);
      VecCost += getShuffleCost(TTIRef, TargetTransformInfo::SK_PermuteTwoSrc,
                                cast<VectorType>(FinalVecTy), CostKind, Mask);
      // Patterns like [fadd,fsub] can be combined into a single instruction
      // in x86. Reordering them into [fsub,fadd] blocks this pattern. So we
      // need to take into account their order when looking for the most used
      // order. Linearized chains emit no alternate-ops pattern.
      if (E->hasReassocScalars())
        return VecCost;
      unsigned Opcode0 = E->getOpcode();
      unsigned Opcode1 = E->getAltOpcode();
      SmallBitVector OpcodeMask(
          getAltInstrMask(E->Scalars, ScalarTy, Opcode0, Opcode1));
      // If this pattern is supported by the target then we consider the
      // order.
      if (TTIRef.isLegalAltInstr(cast<VectorType>(VecTy), Opcode0, Opcode1,
                                 OpcodeMask, E->Scalars)) {
        InstructionCost AltVecCost =
            TTIRef.getAltInstrCost(cast<VectorType>(VecTy), Opcode0, Opcode1,
                                   OpcodeMask, CostKind, E->Scalars);
        return AltVecCost < VecCost ? AltVecCost : VecCost;
      }
      // TODO: Check the reverse order too.
      return VecCost;
    };
    if (Opts.slp_revec && !E->isAltShuffle())
      return GetCostDiff(
          GetScalarCost, [&](InstructionCost) -> InstructionCost {
            // If a group uses mask in order, the shufflevector can be
            // eliminated by instcombine. Then the cost is 0.
            assert(isa<ShuffleVectorInst>(VL.front()) &&
                   "Not supported shufflevector usage.");
            auto *SV = cast<ShuffleVectorInst>(VL.front());
            unsigned SVNumElements =
                cast<FixedVectorType>(SV->getOperand(0)->getType())
                    ->getNumElements();
            unsigned GroupSize = SVNumElements / SV->getShuffleMask().size();
            for (size_t I = 0, End = VL.size(); I != End; I += GroupSize) {
              ArrayRef<Value *> Group = VL.slice(I, GroupSize);
              int NextIndex = 0;
              if (!all_of(Group, [&](Value *V) {
                    assert(isa<ShuffleVectorInst>(V) &&
                           "Not supported shufflevector usage.");
                    auto *SV = cast<ShuffleVectorInst>(V);
                    int Index;
                    [[maybe_unused]] bool IsExtractSubvectorMask =
                        SV->isExtractSubvectorMask(Index);
                    assert(IsExtractSubvectorMask &&
                           "Not supported shufflevector usage.");
                    if (NextIndex != Index)
                      return false;
                    NextIndex += SV->getShuffleMask().size();
                    return true;
                  }))
                return getShuffleCost(*TTI,
                                      TargetTransformInfo::SK_PermuteSingleSrc,
                                      cast<VectorType>(VecTy), CostKind,
                                      calculateShufflevectorMask(E->Scalars));
            }
            return TTI::TCC_Free;
          });
    return GetCostDiffWithPeeled(GetScalarCost, GetVectorCost);
  }
  case Instruction::Freeze:
    return CommonCost;
  default:
    llvm_unreachable("Unknown instruction");
  }
}

bool BoUpSLP::isFullyVectorizableTinyTree(bool ForReduction) const {
  LLVM_DEBUG(dbgs() << "SLP: Check whether the tree with height "
                    << VectorizableTree.size() << " is fully vectorizable .\n");

  auto &&AreVectorizableGathers = [this](const TreeEntry *TE, unsigned Limit) {
    SmallVector<int> Mask;
    return TE->isGather() &&
           !any_of(TE->Scalars,
                   [this](Value *V) { return EphValues.contains(V); }) &&
           (allConstant(TE->Scalars) || isSplat(TE->Scalars) ||
            TE->Scalars.size() < Limit ||
            matchGatheredExtractedFields(TE->Scalars, *DL) ||
            // Nodes with copyable lanes may mix in non-extract lanes, which
            // are not representable as a shuffle of the source vector.
            (((TE->hasState() &&
               TE->getOpcode() == Instruction::ExtractElement &&
               !TE->hasCopyableElements()) ||
              all_of(TE->Scalars, IsaPred<ExtractElementInst, UndefValue>)) &&
             isFixedVectorShuffle(TE->Scalars, Mask, AC, Cache)) ||
            (TE->hasState() && TE->getOpcode() == Instruction::Load &&
             !TE->isAltShuffle()) ||
            any_of(TE->Scalars, IsaPred<LoadInst>));
  };

  // We only handle trees of heights 1 and 2.
  if (VectorizableTree.size() == 1 &&
      (VectorizableTree[0]->State == TreeEntry::Vectorize ||
       VectorizableTree[0]->State == TreeEntry::StridedVectorize ||
       VectorizableTree[0]->State == TreeEntry::ExpandVectorize ||
       VectorizableTree[0]->State == TreeEntry::CompressVectorize ||
       VectorizableTree[0]->State == TreeEntry::BlendedLoadVectorize ||
       (ForReduction &&
        AreVectorizableGathers(VectorizableTree[0].get(),
                               VectorizableTree[0]->Scalars.size()) &&
        VectorizableTree[0]->getVectorFactor() > 2)))
    return true;

  if (VectorizableTree.size() != 2)
    return false;

  // Handle splat and all-constants stores. Also try to vectorize tiny trees
  // with the second gather nodes if they have less scalar operands rather than
  // the initial tree element (may be profitable to shuffle the second gather)
  // or they are extractelements, which form shuffle.
  if (VectorizableTree[0]->State == TreeEntry::Vectorize &&
      AreVectorizableGathers(VectorizableTree[1].get(),
                             VectorizableTree[0]->Scalars.size()))
    return true;

  // Gathering cost would be too much for tiny trees.
  if (VectorizableTree[0]->isGather() ||
      (VectorizableTree[1]->isGather() &&
       VectorizableTree[0]->State != TreeEntry::ScatterVectorize &&
       VectorizableTree[0]->State != TreeEntry::StridedVectorize &&
       VectorizableTree[0]->State != TreeEntry::ExpandVectorize &&
       VectorizableTree[0]->State != TreeEntry::CompressVectorize &&
       VectorizableTree[0]->State != TreeEntry::BlendedLoadVectorize))
    return false;

  return true;
}

bool BoUpSLP::isTreeTinyAndNotFullyVectorizable(bool ForReduction) const {
  if (!DebugCounter::shouldExecute(VectorizedGraphs))
    return true;

  // If we are revectorizing reduction, it may result in same reduction pattern
  // with shuffles as leaves of the reduction. Prevent SLP from revectorizing
  // that shuffle pattern.
  if (Opts.slp_revec && ForReduction && VectorizableTree.size() == 3 &&
      VectorizableTree[0]->State == TreeEntry::Vectorize &&
      VectorizableTree[0]->getOpcode() == Instruction::ShuffleVector &&
      VectorizableTree[1]->isGather() &&
      isSplat(VectorizableTree[1]->Scalars) &&
      VectorizableTree[2]->isGather() &&
      allConstant(VectorizableTree[2]->Scalars)) {
    LLVM_DEBUG(dbgs() << "SLP: Rejecting reduction tree with 3 nodes(shuffle "
                         "as root and remaining are gather nodes).\n");
    return true;
  }

  // Graph is empty - do nothing.
  if (VectorizableTree.empty()) {
    assert(ExternalUses.empty() && "We shouldn't have any external users");

    return true;
  }

  // FIXME: support buildvector of the gather nodes with struct types.
  if (any_of(VectorizableTree, [&](const std::unique_ptr<TreeEntry> &TE) {
        return TE->isGather() &&
               isa<StructType>(TE->Scalars.front()->getType());
      })) {
    LLVM_DEBUG(
        dbgs() << "SLP: rejecting tree with buildvector struct values of size "
               << VectorizableTree.size() << ".\n");
    return true;
  }

  // Cache values from the root node and the cost-threshold options to avoid
  // re-querying them inside hot predicates below.
  const unsigned TreeSize = VectorizableTree.size();
  const TreeEntry &Front = getRootNode();
  const bool FrontIsGather = Front.isGather();
  const bool FrontHasState = Front.hasState();
  const unsigned FrontOpcode = FrontHasState ? Front.getOpcode() : 0u;
  const bool ThresholdSet = Opts.slp_threshold.has_value();
  const bool ThresholdNonNegative = getCostThreshold() >= 0;

  constexpr unsigned Limit = 4;
  constexpr unsigned LargeTree = 20;
  constexpr unsigned LimitTreeSize = 36;

  // The remaining size-1/size-<=MinTreeSize early bail-outs only apply to
  // non-reduction trees; group them under a single guard to avoid 3 separate
  // !ForReduction short-circuits when reducing.
  if (!ForReduction) {
    // Single gather node: bail out for ExtractElement or any node containing a
    // real Instruction scalar.
    if (TreeSize == 1 && FrontIsGather) {
      if (FrontHasState && FrontOpcode == Instruction::ExtractElement)
        return true;
      if (any_of(Front.Scalars, IsaPred<Instruction>))
        return true;
    }
    if (TreeSize <= Opts.slp_min_tree_size &&
        all_of(VectorizableTree, [](const std::unique_ptr<TreeEntry> &TE) {
          return TE->isGather() || TE->State == TreeEntry::SplitVectorize;
        }))
      return true;
    if (TreeSize == 1 && getCostThreshold() < 0 && FrontHasState &&
        FrontOpcode == Instruction::ExtractElement &&
        (Front.getVectorFactor() == 2 ||
         all_of(make_isa_range<Instruction>(Front.Scalars),
                [&](Instruction *I) {
                  return !areAllUsersVectorized(I, UserIgnoreList);
                })))
      return true;
  }
  // No need to vectorize inserts of gathered values.
  if (TreeSize == 2 && isa<InsertElementInst>(Front.Scalars[0]) &&
      VectorizableTree[1]->isGather() &&
      (VectorizableTree[1]->getVectorFactor() <= 2 ||
       !(isSplat(VectorizableTree[1]->Scalars) ||
         allConstant(VectorizableTree[1]->Scalars))))
    return true;

  // The tree with only 3 nodes, where 2 last are gathers/buildvectors, not
  // profitable for vectorization.
  if (TreeSize == 3 && getCostThreshold() == 0 &&
      (!ForReduction || Front.getVectorFactor() <= 2) &&
      all_of(ArrayRef(VectorizableTree).drop_front(),
             [&](const std::unique_ptr<TreeEntry> &TE) {
               return TE->isGather() && TE->getVectorFactor() <= Limit &&
                      !all_of(
                          TE->Scalars,
                          IsaPred<ExtractElementInst, UndefValue, Constant>);
             }))
    return true;

  // All remaining bail-out heuristics require !ForReduction. Group them under
  // a single guard so reduction trees skip them with one branch instead of one
  // per check.
  if (!ForReduction) {
    // The single vectorized node, fed by the buildvectors, only repacks the
    // scalars, the gathers and the extracts are paid for the one vector
    // instruction. The vector call replaces the several expensive scalar ones,
    // while the store merges the lanes instead of extracting them back.
    if (TreeSize > 1 && ThresholdNonNegative &&
        (!FrontHasState || (FrontOpcode != Instruction::Call &&
                            FrontOpcode != Instruction::Store)) &&
        count_if(VectorizableTree,
                 [](const std::unique_ptr<TreeEntry> &TE) {
                   return TE->State == TreeEntry::Vectorize;
                 }) == 1 &&
        all_of(VectorizableTree, [](const std::unique_ptr<TreeEntry> &TE) {
          return TE->State == TreeEntry::Vectorize ||
                 (TE->isGather() && !isSplat(TE->Scalars) &&
                  !all_of(TE->Scalars,
                          IsaPred<ExtractElementInst, UndefValue, Constant>));
        }))
      return true;

    // If the graph includes only PHI nodes and gathers, it is defnitely not
    // profitable for the vectorization, we can skip it, if the cost threshold
    // is default. The cost of vectorized PHI nodes is almost always 0 + the
    // cost of gathers/buildvectors.
    if (!ThresholdSet &&
        all_of(VectorizableTree, [&](const std::unique_ptr<TreeEntry> &TE) {
          const bool IsGather = TE->isGather();
          const bool HasState = TE->hasState();
          const unsigned Op = HasState ? TE->getOpcode() : 0u;
          if (IsGather && (!HasState || Op != Instruction::ExtractElement) &&
              static_cast<unsigned>(
                  count_if(TE->Scalars, IsaPred<ExtractElementInst>)) <= Limit)
            return true;
          return HasState && Op == Instruction::PHI;
        }))
      return true;

    // Do not vectorize small tree of phis only, if all vector phis are also
    // gathered.
    if (ThresholdSet && TreeSize <= Limit) {
      bool HasVectorPhi = false;
      auto Compatible = [&](const std::unique_ptr<TreeEntry> &TE) {
        const bool IsGather = TE->isGather();
        const bool HasState = TE->hasState();
        const unsigned Op = HasState ? TE->getOpcode() : 0u;
        if (IsGather && (!HasState || Op != Instruction::ExtractElement) &&
            static_cast<unsigned>(
                count_if(TE->Scalars, IsaPred<ExtractElementInst>)) <= Limit)
          return true;
        if (!HasState)
          return false;
        if (Op == Instruction::InsertElement)
          return true;
        if (Op != Instruction::PHI)
          return false;
        if (TE->State == TreeEntry::Vectorize)
          HasVectorPhi = true;
        return all_of(TE->Scalars, [&](Value *V) {
          return isa<PoisonValue>(V) || MustGather.contains(V);
        });
      };
      if (all_of(VectorizableTree, Compatible) && HasVectorPhi)
        return true;
    }

    // PHI nodes only and gathers cannot be vectorized, skip.
    if (ThresholdNonNegative) {
      const bool IsLargeTree = TreeSize >= LargeTree;
      bool HasSingleLoad = false;
      if (all_of(VectorizableTree, [&](const std::unique_ptr<TreeEntry> &TE) {
            const bool IsGather = TE->isGather();
            const bool HasState = TE->hasState();
            const unsigned Op = HasState ? TE->getOpcode() : 0u;
            // HasSingleLoad/PrevLoad are only consulted in the
            // IsLargeTree branch; skip the bookkeeping otherwise.
            if (IsLargeTree) {
              const bool PrevLoad = HasSingleLoad;
              HasSingleLoad |=
                  HasState && !IsGather &&
                  (Op == Instruction::Load || TE->hasCopyableElements()) &&
                  (TE->getVectorFactor() > 2 || TE->ReorderIndices.empty());
              if (HasState) {
                if (Op == Instruction::PHI)
                  return true;
                if (TE->getVectorFactor() <= Limit &&
                    (Op == Instruction::Store ||
                     (Op == Instruction::Load && !PrevLoad)))
                  return true;
              }
            } else if (HasState && Op == Instruction::PHI) {
              return true;
            }
            return IsGather && (!HasState || Op != Instruction::ExtractElement);
          }))
        return true;

      // Single non-phi vector node - skip the tree.
      if (TreeSize >= 5 && Front.getVectorFactor() <= 2 &&
          Front.Scalars.front()->getType()->isIntegerTy()) {
        bool VectorNodeFound = false;
        bool AnyNonConst = false;
        if (all_of(VectorizableTree,
                   [&](const std::unique_ptr<TreeEntry> &TE) {
                     if (TE->State == TreeEntry::Vectorize && TE->hasState()) {
                       const unsigned Op = TE->getOpcode();
                       if (Op == Instruction::PHI ||
                           !TE->ReorderIndices.empty())
                         return true;
                       if (VectorNodeFound)
                         return false;
                       VectorNodeFound = true;
                       return true;
                     }
                     // Once AnyNonConst is true, skip the O(n) allConstant
                     // walk for subsequent entries.
                     if (!AnyNonConst)
                       AnyNonConst = !allConstant(TE->Scalars);
                     return TE->isGather() ||
                            TE->State == TreeEntry::SplitVectorize;
                   }) &&
            AnyNonConst)
          return true;
      }
    }

    // Common predicate for "phis, buildvectors, split nodes and small nodes
    // with reuses" used by the two checks below. Cheap checks are evaluated
    // before expensive Scalars walks.
    auto IsBenignNode = [&](const TreeEntry &TE) {
      if (TE.State == TreeEntry::SplitVectorize)
        return true;
      const bool IsGather = TE.isGather();
      const bool HasState = TE.hasState();
      if (HasState) {
        const unsigned Op = TE.getOpcode();
        if (Op == Instruction::PHI)
          return true;
        const unsigned ScalarsSize = TE.Scalars.size();
        if (TE.Idx == 0 && ScalarsSize == 2 && Op == Instruction::ICmp &&
            TreeSize > LimitTreeSize)
          return true;
        if (ScalarsSize == 2 &&
            (!TE.ReuseShuffleIndices.empty() || !TE.ReorderIndices.empty() ||
             TE.isAltShuffle()))
          return true;
        if (TE.hasCopyableElements() &&
            static_cast<unsigned>(count_if(
                TE.Scalars, IsaPred<PHINode, Constant>)) >= ScalarsSize / 2)
          return true;
      }
      return IsGather && none_of(TE.Scalars, IsaPred<ExtractElementInst>);
    };

    // If the tree contains only phis, buildvectors, split nodes and
    // small nodes with reuses, we can skip it.
    if (!ThresholdSet) {
      SmallVector<const TreeEntry *> StoreLoadNodes;
      unsigned NumGathers = 0;
      if (all_of(VectorizableTree,
                 [&](const std::unique_ptr<TreeEntry> &TE) {
                   const bool IsGather = TE->isGather();
                   if (!IsGather && TE->hasState()) {
                     const unsigned Op = TE->getOpcode();
                     if (Op == Instruction::Load || Op == Instruction::Store) {
                       StoreLoadNodes.push_back(TE.get());
                       return true;
                     }
                   }
                   if (IsGather)
                     ++NumGathers;
                   return IsBenignNode(*TE);
                 }) &&
          (StoreLoadNodes.empty() ||
           (TreeSize > LimitTreeSize * StoreLoadNodes.size() &&
            (NumGathers > 0 ||
             none_of(StoreLoadNodes, [&](const TreeEntry *TE) {
               return TE->getOpcode() == Instruction::Store ||
                      all_of(make_isa_range<LoadInst>(TE->Scalars),
                             [&](LoadInst *LI) {
                               return areAllUsersVectorized(LI);
                             });
             })))))
        return true;
    }

    // If the tree contains only phis, buildvectors, split nodes and
    // small nodes with reuses, we can skip it.
    if (ThresholdNonNegative && TreeSize > LimitTreeSize) {
      const TreeEntry *VectorNode = nullptr;
      if (all_of(VectorizableTree, [&](const std::unique_ptr<TreeEntry> &TE) {
            if (!TE->isGather() && TE->hasState() &&
                TE->State != TreeEntry::SplitVectorize &&
                TE->getOpcode() != Instruction::PHI) {
              if (VectorNode)
                return false;
              VectorNode = TE.get();
              return true;
            }
            return IsBenignNode(*TE);
          }))
        return true;
    }

    // If the tree contains only buildvector, 2 non-buildvectors (with root
    // user tree node) and other buildvectors, we can skip it.
    if (ThresholdSet && TreeSize >= Limit &&
        Front.State == TreeEntry::SplitVectorize &&
        count_if(ArrayRef(VectorizableTree).drop_front(),
                 [](const std::unique_ptr<TreeEntry> &TE) {
                   return !TE->isGather() && TE->UserTreeIndex.UserTE &&
                          TE->UserTreeIndex.UserTE->Idx == 0;
                 }) == 2)
      return true;

    // If the tree contains only vectorization of the phi node from the
    // buildvector - skip it.
    if (ThresholdSet && TreeSize > 2 && Front.State == TreeEntry::Vectorize &&
        FrontOpcode == Instruction::InsertElement &&
        VectorizableTree[1]->State == TreeEntry::Vectorize &&
        VectorizableTree[1]->getOpcode() == Instruction::PHI &&
        all_of(ArrayRef(VectorizableTree).drop_front(2),
               [](const std::unique_ptr<TreeEntry> &TE) {
                 return TE->isGather();
               }))
      return true;
  }

  // We can vectorize the tree if its size is greater than or equal to the
  // minimum size specified by the MinTreeSize command line option.
  if (TreeSize >= Opts.slp_min_tree_size)
    return false;

  // If we have a tiny tree (a tree whose size is less than MinTreeSize), we
  // can vectorize it if we can prove it fully vectorizable.
  if (isFullyVectorizableTinyTree(ForReduction))
    return false;

  // Check if any of the gather node forms an insertelement buildvector
  // somewhere. TreeSize >= 1 is guaranteed, so the multi-node case reduces to
  // a simple TreeSize > 1 short-circuit.
  // A gather with copyable lanes is not a real instruction node; do not let
  // its state qualify it as a buildvector-forming node.
  const bool IsAllowedSingleBVNode =
      TreeSize > 1 ||
      (FrontHasState && !Front.isAltShuffle() && !Front.hasCopyableElements() &&
       FrontOpcode != Instruction::PHI &&
       FrontOpcode != Instruction::GetElementPtr &&
       allSameBlock(Front.Scalars));
  if (any_of(VectorizableTree, [&](const std::unique_ptr<TreeEntry> &TE) {
        return TE->isGather() && all_of(TE->Scalars, [&](Value *V) {
                 return isa<ExtractElementInst, Constant>(V) ||
                        (IsAllowedSingleBVNode &&
                         !V->hasNUsesOrMore(UsesLimit) &&
                         any_of(V->users(), IsaPred<InsertElementInst>));
               });
      }))
    return false;

  const TreeEntry &Back = *VectorizableTree.back();
  if (Back.isGather() && Back.hasState() && Back.isAltShuffle()) {
    const unsigned BackVF = Back.getVectorFactor();
    if (BackVF > 2 && allSameBlock(Back.Scalars) &&
        !Back.Scalars.front()->getType()->isVectorTy() &&
        TTI->getScalarizationOverhead(
            cast<VectorType>(
                getWidenedType(Back.Scalars.front()->getType(), BackVF)),
            APInt::getAllOnes(BackVF),
            /*Insert=*/true, /*Extract=*/false, CostKind) > -getCostThreshold())
      return false;
  }

  // Otherwise, we can't vectorize the tree. It is both tiny and not fully
  // vectorizable.
  return true;
}

bool BoUpSLP::isTreeNotExtendable() const {
  if (getCanonicalGraphSize() != getTreeSize()) {
    constexpr unsigned SmallTree = 3;
    if (getRootNode().isNonPowOf2Vec() &&
        getCanonicalGraphSize() <= SmallTree &&
        count_if(ArrayRef(VectorizableTree).drop_front(getCanonicalGraphSize()),
                 [](const std::unique_ptr<TreeEntry> &TE) {
                   return TE->isGather() && TE->hasState() &&
                          TE->getOpcode() == Instruction::Load &&
                          !allSameBlock(TE->Scalars);
                 }) == 1)
      return true;
    return false;
  }
  bool Res = false;
  for (unsigned Idx : seq<unsigned>(getTreeSize())) {
    TreeEntry &E = *VectorizableTree[Idx];
    if (E.State == TreeEntry::SplitVectorize)
      return false;
    if (!E.isGather())
      continue;
    if ((E.hasState() && E.getOpcode() != Instruction::Load) ||
        (!E.hasState() &&
         all_of(E.Scalars, IsaPred<ExtractElementInst, LoadInst>)) ||
        (isa<ExtractElementInst>(E.Scalars.front()) &&
         getSameOpcode(ArrayRef(E.Scalars).drop_front(), *TLI).valid()))
      return false;
    if (isSplat(E.Scalars) || allConstant(E.Scalars))
      continue;
    Res = true;
  }
  return Res;
}

InstructionCost BoUpSLP::getSpillCost() {
  // Walk the vectorizable tree from the root towards its leaves, tracking
  // which vectorized operand values would be live across each tree edge
  // (i.e. between the last instruction of an operand entry and the last
  // instruction of its user entry). When the live range crosses a call
  // instruction that is not part of the vectorized tree, query TTI for the
  // cost of keeping the value live across it (for example, if spills and
  // fills are required).

  const TreeEntry *Root = &getRootNode();
  if (Root->isGather())
    return 0;

  InstructionCost Cost = 0;
  SmallDenseMap<const TreeEntry *, SmallVector<const TreeEntry *>>
      EntriesToOperands;
  SmallDenseMap<const TreeEntry *, Instruction *> EntriesToLastInstruction;
  SmallPtrSet<const Instruction *, 8> LastInstructions;
  SmallPtrSet<const TreeEntry *, 8> ScalarOrPseudoEntries;
  for (const auto &TEPtr : VectorizableTree) {
    if (TEPtr->CombinedOp == TreeEntry::ReducedBitcast ||
        TEPtr->CombinedOp == TreeEntry::ReducedBitcastBSwap ||
        TEPtr->CombinedOp == TreeEntry::ReducedBitcastLoads ||
        TEPtr->CombinedOp == TreeEntry::ReducedBitcastBSwapLoads ||
        TEPtr->CombinedOp == TreeEntry::ReducedBitPack ||
        TEPtr->CombinedOp == TreeEntry::ReducedCmpBitcast) {
      ScalarOrPseudoEntries.insert(TEPtr.get());
      continue;
    }
    if (!TEPtr->isGather()) {
      Instruction *LastInst = &getLastInstructionInBundle(TEPtr.get());
      EntriesToLastInstruction.try_emplace(TEPtr.get(), LastInst);
      LastInstructions.insert(LastInst);
    }
    if (TEPtr->UserTreeIndex)
      EntriesToOperands[TEPtr->UserTreeIndex.UserTE].push_back(TEPtr.get());
  }

  // Cache NoCallIntrinsicOrDoesNotReturn results - the same intrinsic call may
  // be queried many times during the spill cost scan, and each computation
  // involves two potentially expensive TTI virtual calls.
  SmallDenseMap<const IntrinsicInst *, bool> NoCallIntrinsicCache;
  auto NoCallIntrinsicOrDoesNotReturn =
      [this, &NoCallIntrinsicCache](const Instruction *I) {
        const auto *CB = dyn_cast<CallBase>(I);
        if (!CB)
          return false;
        if (CB->doesNotReturn())
          return true;
        const auto *II = dyn_cast<IntrinsicInst>(CB);
        if (!II)
          return false;
        if (II->isAssumeLikeIntrinsic())
          return true;
        auto [It, Inserted] = NoCallIntrinsicCache.try_emplace(II);
        if (!Inserted)
          return It->second;
        IntrinsicCostAttributes ICA(II->getIntrinsicID(), *II);
        InstructionCost IntrCost = TTI->getIntrinsicInstrCost(ICA, CostKind);
        InstructionCost CallCost = TTI->getCallInstrCost(
            nullptr, II->getType(), ICA.getArgTypes(), CostKind);
        bool Res = IntrCost < CallCost;
        It->second = Res;
        return Res;
      };

  // Maps last instruction in the entry to the last instruction for the one of
  // operand entries and the flag. If the flag is true, there are no calls in
  // between these instructions.
  SmallDenseMap<const Instruction *, PointerIntPair<const Instruction *, 1>>
      CheckedInstructions;
  unsigned Budget = 0;
  const unsigned BudgetLimit =
      Opts.slp_schedule_budget / VectorizableTree.size();
  auto CheckForNonVecCallsInSameBlock = [&](Instruction *First,
                                            const Instruction *Last) {
    assert(First->getParent() == Last->getParent() &&
           "Expected instructions in same block.");
    if (auto It = CheckedInstructions.find(Last);
        It != CheckedInstructions.end()) {
      const Instruction *Checked = It->second.getPointer();
      const bool NoCallsInCachedRange = It->second.getInt() != 0;
      if (Checked == First)
        return NoCallsInCachedRange;
      if (Checked->comesBefore(First))
        // In every cached state (full clean scan, call-found, or
        // budget-exhausted) the region strictly above `Checked` up to `Last`
        // was inspected and proved call-free. Since `First` is above
        // `Checked`, the queried range [First, Last] is contained in that
        // call-free region, regardless of whether bit is 0 or 1.
        return true;
      Last = Checked;
    } else if (Last == First || Last->comesBefore(First)) {
      // Empty range.
      return true;
    }
    BasicBlock::const_reverse_iterator InstIt =
                                           ++First->getIterator().getReverse(),
                                       PrevInstIt =
                                           Last->getIterator().getReverse();
    SmallVector<const Instruction *> LastInstsInRange;
    while (InstIt != PrevInstIt && Budget <= BudgetLimit) {
      // Debug information does not impact spill cost.
      // Vectorized calls, represented as vector intrinsics, do not impact spill
      // cost.
      if (const auto *CB = dyn_cast<CallBase>(&*PrevInstIt);
          CB && !NoCallIntrinsicOrDoesNotReturn(CB) && !isVectorized(CB)) {
        for (const Instruction *LastInst : LastInstsInRange)
          CheckedInstructions.try_emplace(LastInst, &*PrevInstIt, 0);
        return false;
      }
      if (LastInstructions.contains(&*PrevInstIt))
        LastInstsInRange.push_back(&*PrevInstIt);

      ++PrevInstIt;
      ++Budget;
    }
    // If we reached the scan's lower bound (`PrevInstIt == InstIt`) then the
    // whole [First, Last] range was inspected and found call-free, even if
    // Budget just overflowed at the very last step; do not mislabel such a
    // completed scan as "has call".
    const bool Completed = PrevInstIt == InstIt;
    const bool NoCallsInRange = Completed || Budget <= BudgetLimit;
    for (const Instruction *LastInst : LastInstsInRange)
      CheckedInstructions.try_emplace(
          LastInst, Completed ? First : &*PrevInstIt, NoCallsInRange ? 1 : 0);
    return NoCallsInRange;
  };
  // The spill/reload is executed once per execution of the call, so the
  // cost is scaled by the trip count of the loop containing the call, even
  // for hoisted loop-invariant values defined outside of it.
  auto GetSpillScale = [&](const BasicBlock *BB) {
    return getLoopNestScale(LI->getLoopFor(BB));
  };
  auto AddCosts = [&](const TreeEntry *Op, uint64_t Scale) {
    if (ScalarOrPseudoEntries.contains(Op))
      return;
    Type *ScalarTy = Op->Scalars.front()->getType();
    auto It = MinBWs.find(Op);
    if (It != MinBWs.end())
      ScalarTy = IntegerType::get(ScalarTy->getContext(), It->second.first);
    auto *VecTy = getWidenedType(ScalarTy, Op->getVectorFactor());
    InstructionCost KeepLiveCost = TTI->getCostOfKeepingLiveOverCall(VecTy);
    KeepLiveCost *= Scale;
    Cost += KeepLiveCost;
    if (ScalarTy->isVectorTy()) {
      // Handle revec dead vector instructions.
      Cost -= Op->Scalars.size() * TTI->getCostOfKeepingLiveOverCall(ScalarTy) *
              Scale;
    }
  };
  // Memoize the relationship between blocks, i.e. the spill scale if every
  // path between the blocks crosses a non-vectorized call, 0 if there is (at
  // least one) call-free path. This allows to skip the analysis of the same
  // block paths multiple times.
  SmallDenseMap<std::pair<const BasicBlock *, const BasicBlock *>, uint64_t>
      ParentOpParentToPreds;
  // Memoize whether a basic block contains a non-terminator no-return call.
  // Such blocks are dead-end paths in normal control flow (execution does not
  // exit them past the no-return call), so the block is excluded from the
  // spill cost analysis. Terminator no-return calls (invoke/callbr) are not
  // block-killing because they still have live CFG successors (e.g. the
  // unwind destination of an invoke).
  SmallDenseMap<const BasicBlock *, bool> BlockHasNoReturnCallCache;
  auto BlockHasNoReturnCall = [&](const BasicBlock *BB) {
    auto [It, Inserted] = BlockHasNoReturnCallCache.try_emplace(BB, false);
    if (!Inserted)
      return It->second;
    for (const CallBase &CB : make_isa_range<CallBase>(*BB)) {
      if (CB.doesNotReturn() && !CB.isTerminator()) {
        It->second = true;
        return true;
      }
    }
    return false;
  };
  // Memoize whether a loop's body (all blocks of the loop, including
  // sub-loops) contains any non-vec call.
  SmallDenseMap<const Loop *, bool> LoopBodyHasNonVecCall;
  auto LoopBodyHasCall = [&](const Loop *L) {
    if (auto It = LoopBodyHasNonVecCall.find(L);
        It != LoopBodyHasNonVecCall.end())
      return It->second;
    auto IsNotCatchSwitch = [](BasicBlock *BB) {
      return !isa<CatchSwitchInst>(BB->getTerminator());
    };
    for (BasicBlock *BB : make_filter_range(L->blocks(), IsNotCatchSwitch)) {
      // Blocks containing a no-return call are dead-end paths and never
      // actually flow back through the loop's back-edge, so their calls do
      // not keep loop-invariant vector values live across calls.
      if (BlockHasNoReturnCall(BB))
        continue;
      for (const Instruction &I : *BB) {
        const auto *CB = dyn_cast<CallBase>(&I);
        if (!CB || NoCallIntrinsicOrDoesNotReturn(CB) || isVectorized(CB))
          continue;
        LoopBodyHasNonVecCall.try_emplace(L, true);
        return true;
      }
    }
    LoopBodyHasNonVecCall.try_emplace(L, false);
    return false;
  };
  auto GetLoopInvariantSpillRegion = [&](BasicBlock *UseBB,
                                         BasicBlock *DefBB) -> const Loop * {
    // If DefBB is outside a loop containing UseBB, the value is live across
    // iterations of that loop. A non-vectorized call in the loop may therefore
    // require a spill even when the entry path from DefBB to UseBB is
    // call-free. Return the outermost such loop containing a relevant call so
    // its execution scale can be used to cost the spill.
    const Loop *L = LI->getLoopFor(UseBB);
    const Loop *Outermost = nullptr;
    while (L && !L->contains(DefBB)) {
      Outermost = L;
      L = L->getParentLoop();
    }
    return (Outermost && LoopBodyHasCall(Outermost)) ? Outermost : nullptr;
  };
  auto CheckPredecessors = [&](BasicBlock *Root, BasicBlock *Pred,
                               BasicBlock *OpParent) {
    auto Key = std::make_pair(Root, OpParent);
    if (auto It = ParentOpParentToPreds.find(Key);
        It != ParentOpParentToPreds.end())
      return It->second;
    uint64_t Res = 0;
    scope_exit Cleanup([&]() { ParentOpParentToPreds.try_emplace(Key, Res); });
    if (const auto *L = GetLoopInvariantSpillRegion(Root, OpParent)) {
      Res = getLoopNestScale(L);
      return Res;
    }
    SmallVector<BasicBlock *> Worklist;
    if (Pred)
      Worklist.push_back(Pred);
    else
      Worklist.append(pred_begin(Root), pred_end(Root));
    SmallPtrSet<const BasicBlock *, 16> Visited;
    // With "at least one call-free path" semantics we can only reliably
    // memoize the exact (Root, OpParent) query. Pairs for intermediate
    // blocks that were visited during the BFS are not necessarily
    // call-free-reachable to OpParent themselves - we may have reached
    // OpParent through a *sibling* path that bypassed them.
    // We return 0 (no spill cost) if at least one backward path from
    // some predecessor of Root back to OpParent is call-free. Only when
    // *every* such path goes through a non-vec call do we charge the spill
    // cost: only then is it actually necessary to keep the vectorized value
    // live across a call and therefore spill/reload it.
    //
    // A BB is only explored further (its predecessors added to the worklist)
    // when it is itself call-free and not strictly dominated by Root (blocks
    // dominated by Root are only reachable via loop back-edges - they sit
    // *after* Root in forward execution and must not be counted).
    //
    // If we ever pop OpParent from the worklist, we have reached it through
    // a chain of call-free, non-dominated blocks: a call-free path exists
    // and we return 0. If the worklist is exhausted or the scan budget
    // overflows without reaching OpParent, no call-free path was found and
    // we return the scale of the loop containing Root, so the caller charges
    // the spill cost.
    while (!Worklist.empty()) {
      BasicBlock *BB = Worklist.pop_back_val();
      if (BB == OpParent)
        return Res;
      if (!Visited.insert(BB).second)
        continue;
      // Blocks strictly dominated by Root are reached only *after* Root in
      // forward execution (via loop back-edges); skip them and their
      // dominated predecessors.
      if (DT->properlyDominates(Root, BB))
        continue;
      // A block containing a no-return call cannot reach Root via the
      // forward edge being analyzed: execution does not continue past the
      // no-return call, so the BB -> ... -> Root path is dead. Drop the
      // block from the analysis without following its predecessors.
      if (BlockHasNoReturnCall(BB))
        continue;
      auto Pair = std::make_pair(BB, OpParent);
      if (auto It = ParentOpParentToPreds.find(Pair);
          It != ParentOpParentToPreds.end()) {
        // BB is known to reach OpParent via a call-free path.
        if (It->second == 0)
          return Res;
        // BB is known to be blocked from OpParent by calls; keep checking
        // other paths.
        continue;
      }
      unsigned BlockSize = BB->size();
      if (BlockSize > static_cast<unsigned>(Opts.slp_schedule_budget))
        continue;
      Budget += BlockSize;
      if (Budget > BudgetLimit)
        break;
      if (!isa<CatchSwitchInst>(BB->getTerminator()) &&
          !CheckForNonVecCallsInSameBlock(&*BB->getFirstNonPHIOrAlloca(),
                                          BB->getTerminator()))
        continue;
      Worklist.append(pred_begin(BB), pred_end(BB));
    }
    Res = GetSpillScale(Root);
    return Res;
  };
  SmallVector<const TreeEntry *> LiveEntries(1, Root);
  auto FindNonScalarParentEntry = [&](const TreeEntry *E) -> const TreeEntry * {
    assert(ScalarOrPseudoEntries.contains(E) &&
           "Expected scalar or pseudo entry.");
    const TreeEntry *Entry = E;
    while (Entry->UserTreeIndex) {
      Entry = Entry->UserTreeIndex.UserTE;
      if (!ScalarOrPseudoEntries.contains(Entry))
        return Entry;
    }
    return nullptr;
  };
  auto IsCoveredByMatchingVectorEntry = [&](const TreeEntry *Gather,
                                            const Loop *SpillLoop) -> bool {
    assert(Gather->isGather() && "Expected a gather/buildvector entry.");

    Value *LookupValue = nullptr;
    if (Gather->hasState()) {
      LookupValue = Gather->getMainOp();
    } else {
      auto *It = find_if_not(Gather->Scalars, IsaPred<UndefValue>);
      if (It == Gather->Scalars.end())
        return false;
      LookupValue = *It;
    }

    // Find the real vector entry reused by this perfect-diamond gather.
    const TreeEntry *SameTE =
        getSameValuesTreeEntry(LookupValue, Gather->Scalars, /*SameVF=*/true);
    if (!SameTE || SameTE == Gather || SameTE->State != TreeEntry::Vectorize ||
        ScalarOrPseudoEntries.contains(SameTE) || !SameTE->UserTreeIndex)
      return false;

    // A reordered or reuse-shuffled match materializes a separate shuffled
    // vector that is itself live across the call; only an exact match reuses
    // the same vector value.
    if (!SameTE->ReorderIndices.empty() || !SameTE->ReuseShuffleIndices.empty())
      return false;

    // Only permit an ordinary vectorized user.
    const TreeEntry *UserTE = SameTE->UserTreeIndex.UserTE;
    assert(UserTE && "Expected a user tree entry.");
    if (UserTE->State != TreeEntry::Vectorize ||
        ScalarOrPseudoEntries.contains(UserTE) ||
        UserTE->getOpcode() == Instruction::PHI)
      return false;

    // Different demoted bitwidth would make the two edge costs unequal.
    if (MinBWs.lookup(SameTE).first != MinBWs.lookup(Gather).first)
      return false;

    // The spill walk does not descend through gather entries; if any ancestor
    // of the matching entry's user is a gather or a combined scalar/pseudo
    // entry, the matching edge is never charged and de-duplicating would lose
    // the spill cost entirely.
    for (const TreeEntry *E = UserTE; E != Root;) {
      if (!E->UserTreeIndex)
        return false;
      E = E->UserTreeIndex.UserTE;
      if (E->isGather() || ScalarOrPseudoEntries.contains(E))
        return false;
    }

    Instruction *Def = EntriesToLastInstruction.at(SameTE);
    Instruction *Use = EntriesToLastInstruction.at(UserTE);

    // Require the matching entry to be defined outside the loop and its use to
    // execute directly in the same loop as the gather user.
    if (SpillLoop->contains(Def->getParent()) ||
        LI->getLoopFor(Use->getParent()) != SpillLoop)
      return false;

    // Ensure that the matching entry is also loop invariant.
    if (!all_of(make_isa_range<Instruction>(SameTE->Scalars),
                [&](Instruction *I) { return SpillLoop->isLoopInvariant(I); }))
      return false;

    // A non-vec call between Def and the end of its block preempts the
    // loop-invariant charge for the matching entry's edge with a smaller
    // scale, so de-duplicating would drop the in-loop spill cost.
    if (!CheckForNonVecCallsInSameBlock(Def, Def->getParent()->getTerminator()))
      return false;

    return GetLoopInvariantSpillRegion(Use->getParent(), Def->getParent()) ==
           SpillLoop;
  };
  while (!LiveEntries.empty()) {
    const TreeEntry *Entry = LiveEntries.pop_back_val();
    const auto OpIt = EntriesToOperands.find(Entry);
    if (OpIt == EntriesToOperands.end())
      continue;
    ArrayRef<const TreeEntry *> Operands = OpIt->second;
    if (Operands.empty())
      continue;
    if (ScalarOrPseudoEntries.contains(Entry)) {
      Entry = FindNonScalarParentEntry(Entry);
      if (!Entry) {
        for (const TreeEntry *Op : Operands) {
          if (!Op->isGather())
            LiveEntries.push_back(Op);
        }
        continue;
      }
    }
    Instruction *LastInst = EntriesToLastInstruction.at(Entry);
    BasicBlock *Parent = LastInst->getParent();
    for (const TreeEntry *Op : Operands) {
      if (!Op->isGather())
        LiveEntries.push_back(Op);
      if (ScalarOrPseudoEntries.contains(Op))
        continue;
      if (Entry->State == TreeEntry::SplitVectorize ||
          (Op->isGather() && allConstant(Op->Scalars)))
        continue;

      // Reset the scan budget for analysis of each edge.
      Budget = 0;

      // A gather with all loop-invariant lanes is hoisted to the loop
      // preheader by optimizeGatherSequence, so its vector value becomes live
      // across any non-vectorized call in the loop body. Charge it like any
      // other vectorized value live over a call instead of skipping it.
      if (Entry->hasState() && Entry->getOpcode() != Instruction::PHI &&
          Op->isGather()) {
        if (const Loop *L = LI->getLoopFor(Parent);
            L && L->getLoopPreheader() && LoopBodyHasCall(L) &&
            all_of(make_isa_range<Instruction>(Op->Scalars),
                   [&](Instruction *I) { return L->isLoopInvariant(I); }))
          if (!IsCoveredByMatchingVectorEntry(Op, L))
            AddCosts(Op, GetSpillScale(Parent));
        continue;
      }
      BasicBlock *Pred = nullptr;
      if (auto *Phi = dyn_cast<PHINode>(Entry->getMainOp()))
        Pred = Phi->getIncomingBlock(Op->UserTreeIndex.EdgeIdx);
      BasicBlock *OpParent;
      Instruction *OpLastInst;
      if (Op->isGather()) {
        assert(Entry->getOpcode() == Instruction::PHI &&
               "Expected phi node only.");
        OpParent = cast<PHINode>(Entry->getMainOp())
                       ->getIncomingBlock(Op->UserTreeIndex.EdgeIdx);
        OpLastInst = OpParent->getTerminator();
        for (Instruction *Inst : make_isa_range<Instruction>(Op->Scalars)) {
          if (isVectorized(Inst)) {
            OpParent = Inst->getParent();
            OpLastInst = Inst;
            break;
          }
        }
      } else {
        OpLastInst = EntriesToLastInstruction.at(Op);
        OpParent = OpLastInst->getParent();
      }
      // Check the call instructions within the same basic blocks.
      if (OpParent == Parent) {
        if (Entry->getOpcode() == Instruction::PHI) {
          if (!CheckForNonVecCallsInSameBlock(LastInst, OpLastInst))
            AddCosts(Op, GetSpillScale(Parent));
          continue;
        }
        if (!CheckForNonVecCallsInSameBlock(OpLastInst, LastInst))
          AddCosts(Op, GetSpillScale(Parent));
        continue;
      }
      // Check for call instruction in between blocks.
      // 1. Check entry's block to the head.
      if (Entry->getOpcode() != Instruction::PHI &&
          !CheckForNonVecCallsInSameBlock(&*Parent->getFirstNonPHIOrAlloca(),
                                          LastInst)) {
        AddCosts(Op, GetSpillScale(Parent));
        continue;
      }
      // 2. Check op's block from the end.
      if (!CheckForNonVecCallsInSameBlock(OpLastInst,
                                          OpParent->getTerminator())) {
        AddCosts(Op, GetSpillScale(OpParent));
        continue;
      }
      // 3. Check the predecessors of entry's block till op's block.
      if (uint64_t Scale = CheckPredecessors(Parent, Pred, OpParent))
        AddCosts(Op, Scale);
    }
  }

  return Cost;
}

namespace {
/// Returns incoming Value *, if the requested type is Value * too, or a default
/// value, otherwise.
struct ValueSelect {
  template <typename U>
  static std::enable_if_t<std::is_same_v<Value *, U>, Value *> get(Value *V) {
    return V;
  }
  template <typename U>
  static std::enable_if_t<!std::is_same_v<Value *, U>, U> get(Value *) {
    return U();
  }
};
} // namespace

/// Does the analysis of the provided shuffle masks and performs the requested
/// actions on the vectors with the given shuffle masks. It tries to do it in
/// several steps.
/// 1. If the Base vector is not poison vector, resizing the very first mask to
/// have common VF and perform action for 2 input vectors (including non-poison
/// Base). Other shuffle masks are combined with the resulting after the 1 stage
/// and processed as a shuffle of 2 elements.
/// 2. If the Base is poison vector and have only 1 shuffle mask, perform the
/// action only for 1 vector with the given mask, if it is not the identity
/// mask.
/// 3. If > 2 masks are used, perform the remaining shuffle actions for 2
/// vectors, combing the masks properly between the steps.
template <typename T>
static T *performExtractsShuffleAction(
    MutableArrayRef<std::pair<T *, SmallVector<int>>> ShuffleMask, Value *Base,
    function_ref<unsigned(T *)> GetVF,
    function_ref<std::pair<T *, bool>(T *, ArrayRef<int>, bool)> ResizeAction,
    function_ref<T *(ArrayRef<int>, ArrayRef<T *>)> Action) {
  assert(!ShuffleMask.empty() && "Empty list of shuffles for inserts.");
  SmallVector<int> Mask(ShuffleMask.begin()->second);
  auto VMIt = std::next(ShuffleMask.begin());
  T *Prev = nullptr;
  SmallBitVector UseMask =
      buildUseMask(Mask.size(), Mask, UseMask::UndefsAsMask);
  // The undef elements of the base must be preserved, only the poison base can
  // be dropped.
  SmallBitVector IsBasePoison = isUndefVector<true>(Base, UseMask);
  if (!IsBasePoison.all()) {
    // Base is not poison, need to combine it with the next subvectors.
    std::pair<T *, bool> Res =
        ResizeAction(ShuffleMask.begin()->first, Mask, /*ForSingleMask=*/false);
    for (unsigned Idx = 0, VF = Mask.size(); Idx < VF; ++Idx) {
      if (Mask[Idx] == PoisonMaskElem)
        Mask[Idx] = IsBasePoison.test(Idx) ? PoisonMaskElem : Idx;
      else
        Mask[Idx] = (Res.second ? Idx : Mask[Idx]) + VF;
    }
    [[maybe_unused]] auto *V = ValueSelect::get<T *>(Base);
    assert((!V || GetVF(V) == Mask.size()) &&
           "Expected base vector of VF number of elements.");
    Prev = Action(Mask, {nullptr, Res.first});
  } else if (ShuffleMask.size() == 1) {
    // Base is poison and only 1 vector is shuffled - perform the action only
    // for single vector, if the mask is not the identity mask.
    std::pair<T *, bool> Res = ResizeAction(ShuffleMask.begin()->first, Mask,
                                            /*ForSingleMask=*/true);
    if (Res.second)
      // Identity mask is found.
      Prev = Res.first;
    else
      Prev = Action(Mask, {ShuffleMask.begin()->first});
  } else {
    // Base is poison and at least 2 input vectors shuffled - perform 2 vectors
    // shuffles step by step, combining shuffle between the steps.
    unsigned Vec1VF = GetVF(ShuffleMask.begin()->first);
    unsigned Vec2VF = GetVF(VMIt->first);
    if (Vec1VF == Vec2VF) {
      // No need to resize the input vectors since they are of the same size, we
      // can shuffle them directly.
      ArrayRef<int> SecMask = VMIt->second;
      for (unsigned I = 0, VF = Mask.size(); I < VF; ++I) {
        if (SecMask[I] != PoisonMaskElem) {
          assert(Mask[I] == PoisonMaskElem && "Multiple uses of scalars.");
          Mask[I] = SecMask[I] + Vec1VF;
        }
      }
      Prev = Action(Mask, {ShuffleMask.begin()->first, VMIt->first});
    } else {
      // Vectors of different sizes - resize and reshuffle.
      std::pair<T *, bool> Res1 = ResizeAction(ShuffleMask.begin()->first, Mask,
                                               /*ForSingleMask=*/false);
      std::pair<T *, bool> Res2 =
          ResizeAction(VMIt->first, VMIt->second, /*ForSingleMask=*/false);
      ArrayRef<int> SecMask = VMIt->second;
      for (unsigned I = 0, VF = Mask.size(); I < VF; ++I) {
        if (Mask[I] != PoisonMaskElem) {
          assert(SecMask[I] == PoisonMaskElem && "Multiple uses of scalars.");
          if (Res1.second)
            Mask[I] = I;
        } else if (SecMask[I] != PoisonMaskElem) {
          assert(Mask[I] == PoisonMaskElem && "Multiple uses of scalars.");
          Mask[I] = (Res2.second ? I : SecMask[I]) + VF;
        }
      }
      Prev = Action(Mask, {Res1.first, Res2.first});
    }
    VMIt = std::next(VMIt);
  }
  [[maybe_unused]] bool IsBaseNotPoison = !IsBasePoison.all();
  // Perform requested actions for the remaining masks/vectors.
  for (auto E = ShuffleMask.end(); VMIt != E; ++VMIt) {
    // Shuffle other input vectors, if any.
    std::pair<T *, bool> Res =
        ResizeAction(VMIt->first, VMIt->second, /*ForSingleMask=*/false);
    ArrayRef<int> SecMask = VMIt->second;
    for (unsigned I = 0, VF = Mask.size(); I < VF; ++I) {
      if (SecMask[I] != PoisonMaskElem) {
        assert((Mask[I] == PoisonMaskElem || IsBaseNotPoison) &&
               "Multiple uses of scalars.");
        Mask[I] = (Res.second ? I : SecMask[I]) + VF;
      } else if (Mask[I] != PoisonMaskElem) {
        Mask[I] = I;
      }
    }
    Prev = Action(Mask, {Prev, Res.first});
  }
  return Prev;
}

void BoUpSLP::detectBooleanizedNodes() {
  // An absorbable boolean leaf is a one-use trunc of a wide value or a
  // one-use zero-test of a value from [0, 1]; bit 0 of the wide value is the
  // i1 lane value in both cases.
  auto GetBoolLeafWideTy = [&](const TreeEntry *OpE) -> Type * {
    if (OpE->State != TreeEntry::Vectorize || OpE->isAltShuffle() ||
        OpE->hasCopyableElements() || !OpE->ReuseShuffleIndices.empty() ||
        OpE->CombinedOp != TreeEntry::NotCombinedOp)
      return nullptr;
    unsigned WideOpIdx;
    bool IsZeroTest = OpE->getOpcode() == Instruction::ICmp;
    if (OpE->getOpcode() == Instruction::Trunc) {
      if (!all_of(OpE->Scalars, [](Value *V) {
            return match(V, m_OneUse(m_Trunc(m_Value())));
          }))
        return nullptr;
      WideOpIdx = 0;
    } else if (IsZeroTest) {
      if (!all_of(OpE->Scalars, [](Value *V) {
            auto *CI = dyn_cast<ICmpInst>(V);
            return CI && CI->hasOneUse() &&
                   CI->getPredicate() == ICmpInst::ICMP_NE;
          }))
        return nullptr;
      if (all_of(OpE->getOperand(0),
                 [](Value *V) { return match(V, m_Zero()); }))
        WideOpIdx = 1;
      else if (all_of(OpE->getOperand(1),
                      [](Value *V) { return match(V, m_Zero()); }))
        WideOpIdx = 0;
      else
        return nullptr;
    } else {
      return nullptr;
    }
    Type *WideTy = OpE->getOperand(WideOpIdx).front()->getType();
    if (!WideTy->isIntegerTy())
      return nullptr;
    for (Value *W : OpE->getOperand(WideOpIdx)) {
      if (W->getType() != WideTy || !isGuaranteedNotToBePoison(W) ||
          (IsZeroTest && computeKnownBits(W, *DL).getMaxValue() != 1))
        return nullptr;
    }
    return WideTy;
  };
  // The wide value of a booleanized node is valid only in bit 0, so every
  // tree user must consume it as an i1 vector: either a booleanized and/or
  // node (which uses the wide value directly) or a node whose emission
  // truncates the operand back to the i1 vector type.
  auto IsSafeBoolUser = [&](const TreeEntry *UserTE, unsigned EdgeIdx) {
    if (!UserTE->hasState() || UserTE->isAltShuffle())
      return false;
    if (Instruction::isBinaryOp(UserTE->getOpcode()))
      return true;
    switch (UserTE->getOpcode()) {
    case Instruction::Store:
      return EdgeIdx == 0;
    case Instruction::InsertElement:
      return EdgeIdx == 1;
    case Instruction::Select:
      return EdgeIdx != 0;
    case Instruction::Freeze:
    case Instruction::PHI:
      return true;
    default:
      return false;
    }
  };
  // Visit operand nodes before their users so that booleanized and/or nodes
  // chain: an and/or node whose operand is itself a booleanized and/or node
  // consumes the wide value directly.
  for (const std::unique_ptr<TreeEntry> &TE : reverse(VectorizableTree)) {
    // Logical and/or on i1 with booleanized wide leaves is emitted in the
    // wide type: bit 0 of a bitwise and/or is the and/or of the operands'
    // bit 0. The leaf conversions are absorbed and a single trunc of the
    // wide vector result restores the i1 lanes. Wide leaves must be
    // non-poison: and/or may mask poison in the i1 type, which the wide ops
    // would propagate instead.
    if (TE->State != TreeEntry::Vectorize || TE->isAltShuffle() ||
        (TE->getOpcode() != Instruction::And &&
         TE->getOpcode() != Instruction::Or) ||
        !TE->getMainOp()->getType()->isIntegerTy(1) ||
        !TE->ReuseShuffleIndices.empty() || TE->hasCopyableElements() ||
        TE->CombinedOp != TreeEntry::NotCombinedOp ||
        // The i1 flags (e.g. disjoint) do not apply to the wide op.
        any_of(TE->Scalars,
               [](Value *V) {
                 auto *I = dyn_cast<Instruction>(V);
                 return !I || I->hasPoisonGeneratingFlags();
               }) ||
        any_of(TE->getReassocScalars(),
               [](Value *V) {
                 return cast<Instruction>(V)->hasPoisonGeneratingFlags();
               }) ||
        // Reduction trees are handled by the reduction's own booleanization.
        UserIgnoreList ||
        (TE->UserTreeIndex.UserTE &&
         !IsSafeBoolUser(TE->UserTreeIndex.UserTE,
                         TE->UserTreeIndex.EdgeIdx)) ||
        !all_of(TE->Scalars,
                [&](Value *V) { return getTreeEntries(V).size() == 1; }))
      continue;
    Type *WideTy = nullptr;
    bool Bail = false;
    for (unsigned I : seq<unsigned>(TE->getNumOperands())) {
      const TreeEntry *OpE = getOperandEntry(TE.get(), I);
      Type *ColTy = GetBoolLeafWideTy(OpE);
      if (!ColTy && isBooleanizedNode(OpE) &&
          (OpE->getOpcode() == Instruction::And ||
           OpE->getOpcode() == Instruction::Or))
        ColTy = IntegerType::get(F->getContext(), MinBWs.lookup(OpE).first);
      if (!ColTy || (WideTy && ColTy != WideTy)) {
        Bail = true;
        break;
      }
      WideTy = ColTy;
    }
    if (Bail || !WideTy)
      continue;
    unsigned WideBW = WideTy->getIntegerBitWidth();
    MinBWs.try_emplace(TE.get(), WideBW, /*IsSigned=*/false);
    for (unsigned I : seq<unsigned>(TE->getNumOperands()))
      MinBWs.try_emplace(getOperandEntry(TE.get(), I), WideBW,
                         /*IsSigned=*/false);
  }
}

InstructionCost
BoUpSLP::calculateTreeCostAndTrimNonProfitable(ArrayRef<Value *> VectorizedVals,
                                               Instruction *RdxRoot) {
  // FIXME: support buildvector of the gather nodes with struct types.
  if (any_of(VectorizableTree, [&](const std::unique_ptr<TreeEntry> &TE) {
        return TE->isGather() &&
               isa<StructType>(TE->Scalars.front()->getType());
      })) {
    LLVM_DEBUG(
        dbgs() << "SLP: rejecting tree with buildvector struct values of size "
               << VectorizableTree.size() << ".\n");
    return InstructionCost::getInvalid();
  }

  // The tree is priced, so its minimal vector nodes are analyzed, including the
  // ones, trimmed below as non-profitable. The verdict of the tree itself does
  // not matter: the retry with the single-user seeds rebuilds the same narrow
  // nodes, and their cost without the tree is not better. The wider nodes are
  // not registered: their rejection does not prevent the members from forming
  // the profitable narrower node. Same for the trees, rejected before the cost
  // estimation, and for the buildvector trees, rejected by the insert/extract
  // overhead rather than by the members themselves.
  const TreeEntry &Root = getRootNode();
  if (!Root.hasState() ||
      !isa<InsertElementInst, InsertValueInst>(Root.getMainOp())) {
    for (const std::unique_ptr<TreeEntry> &TE : make_filter_range(
             VectorizableTree, [](const std::unique_ptr<TreeEntry> &TE) {
               return !TE->isGather() && TE->Scalars.size() <= 2;
             })) {
      for (Value *V : TE->Scalars)
        if (isa_and_present<Instruction>(V) && !TE->isCopyableElement(V))
          AnalyzedScalars.insert(V);
    }
  }

  SmallDenseMap<const TreeEntry *, InstructionCost> NodesCosts;
  SmallPtrSet<Value *, 4> CheckedExtracts;
  SmallSetVector<TreeEntry *, 4> GatheredLoadsNodes;
  SmallDenseMap<const TreeEntry *, InstructionCost> ExtractCosts;
  LLVM_DEBUG(dbgs() << "SLP: Calculating cost for tree of size "
                    << VectorizableTree.size() << ".\n");
  // The V-only-dependent part of the predicate. Same V is commonly seen in
  // multiple TEs (shared scalars), so cache the result across calls.
  // DeletedNodes is read-only during this cost loop, so caching is safe.
  const size_t NumVectScalars = ScalarToTreeEntries.size() + 1;
  SmallDenseMap<Value *, bool> ExternalUseVCache;
  auto IsExternallyUsedV = [&](Value *V) {
    auto [It, Inserted] = ExternalUseVCache.try_emplace(V);
    if (!Inserted)
      return It->second;
    bool Res = false;
    if (V->hasOneUse() || V->getType()->isVoidTy()) {
      // Res stays false.
    } else if (V->hasNUsesOrMore(NumVectScalars)) {
      Res = true;
    } else if (auto *I = dyn_cast<Instruction>(V)) {
      Res = any_of(I->users(), [&](const User *U) {
        // store/insertelt v, [cast]U will likely be vectorized.
        if (match(U,
                  m_InsertElt(m_Value(), m_OneUse(m_CastOrSelf(m_Specific(I))),
                              m_ConstantInt())))
          return false;
        if (match(U, m_InsertElt(m_Value(), m_Specific(I), m_ConstantInt())))
          return false;
        if (match(U, m_Store(m_OneUse(m_CastOrSelf(m_Specific(I))), m_Value())))
          return false;
        if (match(U, m_Store(m_Specific(I), m_Value())))
          return false;
        ArrayRef<TreeEntry *> Entries = getTreeEntries(U);
        if (Entries.empty() && !MustGather.contains(U))
          return true;
        if (any_of(Entries,
                   [&](TreeEntry *TE) { return DeletedNodes.contains(TE); }))
          return true;
        return any_of(ValueToGatherNodes.lookup(U), [&](const TreeEntry *TE) {
          return DeletedNodes.contains(TE);
        });
      });
    }
    It->second = Res;
    return Res;
  };
  auto IsExternallyUsed = [&](const TreeEntry &TE, Value *V) {
    assert(TE.hasState() && !TE.isGather() &&
           TE.State != TreeEntry::SplitVectorize && "Expected vector node.");
    if (TE.hasCopyableElements() && TE.isCopyableElement(V))
      return false;
    return IsExternallyUsedV(V);
  };
  InstructionCost Cost = 0;
  SmallDenseMap<const TreeEntry *, uint64_t> EntryToScale;
  uint64_t PrevScale = 0;
  BasicBlock *PrevVecParent = nullptr;
  for (const std::unique_ptr<TreeEntry> &Ptr : VectorizableTree) {
    TreeEntry &TE = *Ptr;
    // No need to count the cost for combined entries, they are combined and
    // just skip their cost.
    if (TE.State == TreeEntry::CombinedVectorize) {
      LLVM_DEBUG(
          dbgs() << "SLP: Skipping cost for combined node that starts with "
                 << *TE.Scalars[0] << ".\n";
          TE.dump(); dbgs() << "SLP: Current total cost = " << Cost << "\n");
      NodesCosts.try_emplace(&TE);
      continue;
    }
    if (TE.hasState() &&
        (TE.isGather() || TE.State == TreeEntry::SplitVectorize)) {
      if (const TreeEntry *E =
              getSameValuesTreeEntry(TE.getMainOp(), TE.Scalars);
          E && E->getVectorFactor() == TE.getVectorFactor()) {
        // Some gather nodes might be absolutely the same as some vectorizable
        // nodes after reordering, need to handle it.
        LLVM_DEBUG(dbgs() << "SLP: Adding cost 0 for bundle "
                          << shortBundleName(TE.Scalars, TE.Idx) << ".\n"
                          << "SLP: Current total cost = " << Cost << "\n");
        NodesCosts.try_emplace(&TE);
        continue;
      }
    }

    // Exclude cost of gather loads nodes which are not used. These nodes were
    // built as part of the final attempt to vectorize gathered loads.
    assert((!TE.isGather() || TE.Idx == 0 || TE.UserTreeIndex) &&
           "Expected gather nodes with users only.");

    InstructionCost C = getEntryCost(&TE, VectorizedVals, CheckedExtracts);
    uint64_t Scale = 0;
    bool CostIsFree = C == 0;
    // For gather/buildvector (and split-vectorize) entries, prefer the
    // per-lane refined scale that accounts for LICM-hoistable insertelements
    // when an operand is invariant in the current loop nest but defined in
    // an outer loop. This prevents over-costing cross-loop-nest buildvectors.
    if (!CostIsFree && !TE.isGather() && TE.hasState()) {
      if (PrevVecParent == TE.getMainOp()->getParent()) {
        Scale = PrevScale;
        C *= Scale;
        EntryToScale.try_emplace(&TE, Scale);
      }
    }
    if (!CostIsFree && !Scale) {
      Scale = getEntryEffectiveScale(TE, TE.Idx == 0 ? RdxRoot : nullptr);
      C *= Scale;
      EntryToScale.try_emplace(&TE, Scale);
      if (!TE.isGather() && TE.hasState()) {
        PrevVecParent = TE.getMainOp()->getParent();
        PrevScale = Scale;
      }
    }
    Cost += C;
    NodesCosts.try_emplace(&TE, C);
    LLVM_DEBUG(dbgs() << "SLP: Adding cost " << C << " for bundle "
                      << shortBundleName(TE.Scalars, TE.Idx) << ".\n"
                      << "SLP: Current total cost = " << Cost << "\n");
    // Add gathered loads nodes to the set for later processing.
    if (TE.Idx > 0 && !TE.UserTreeIndex && TE.hasState() &&
        TE.getOpcode() == Instruction::Load)
      GatheredLoadsNodes.insert(&TE);
    if (!TE.isGather() && TE.State != TreeEntry::SplitVectorize &&
        !(TE.Idx == 0 && (TE.getOpcode() == Instruction::InsertElement ||
                          TE.getOpcode() == Instruction::InsertValue ||
                          TE.getOpcode() == Instruction::Store)) &&
        !isa<StructType>(getValueType(TE.Scalars.front(), Opts.slp_revec))) {
      // Calculate costs of external uses.
      APInt DemandedElts = APInt::getZero(TE.getVectorFactor());
      for (Value *V : TE.Scalars) {
        if (IsExternallyUsed(TE, V))
          DemandedElts.setBit(TE.findLaneForValue(V));
      }
      if (!DemandedElts.isZero()) {
        Type *ScalarTy = TE.Scalars.front()->getType();
        auto It = MinBWs.find(&TE);
        if (It != MinBWs.end())
          ScalarTy = IntegerType::get(ScalarTy->getContext(), It->second.first);
        auto *VecTy = getWidenedType(ScalarTy, TE.getVectorFactor());
        InstructionCost ExtCost =
            getScalarizationOverhead(*TTI, Opts.slp_revec, ScalarTy,
                                     cast<VectorType>(VecTy), DemandedElts,
                                     /*Insert=*/false,
                                     /*Extract=*/true, CostKind);
        if (ExtCost.isValid() && ExtCost != 0) {
          if (!Scale)
            Scale = getScaleToLoopIterations(TE);
          ExtCost *= Scale;
          EntryToScale.try_emplace(&TE, Scale);
        }
        ExtractCosts.try_emplace(&TE, ExtCost);
      }
    }
  }
  // Bail out if the cost threshold is negative and cost already below it.
  // The splat subtrees may still force extracts of their scalars on top of
  // the node cost and have to be trimmed, so do not bail out if there are
  // any.
  if (getCostThreshold() < 0 && Cost < -getCostThreshold() &&
      SplatGatheredScalarsRoots.empty())
    return Cost;
  // The narrow non-profitable tree in loop? Skip, may cause regressions.
  constexpr unsigned PartLimit = 2;
  // Measure the narrowness by the width the tree is vectorized at.
  const TreeEntry *RootTE = &getRootNode();
  unsigned Sz;
  if (auto It = MinBWs.find(RootTE); It != MinBWs.end()) {
    Sz = It->second.first;
  } else {
    Sz = std::max<unsigned>(
        getVectorElementSize(RootTE->Scalars.front()),
        DL->getTypeSizeInBits(
            getValueType(RootTE->Scalars.front(), Opts.slp_revec)
                ->getScalarType()));
  }
  const unsigned MinVF = getMinVF(Sz);
  if (Cost >= -getCostThreshold() &&
      getRootNodeScalars().size() * PartLimit <= MinVF &&
      (!getRootNode().hasState() ||
       (getRootNode().getOpcode() != Instruction::Store &&
        LI->getLoopFor(getRootNode().getMainOp()->getParent()))))
    return Cost;
  // Store the cost + external uses estimation as the first element of the
  // tuple, just the cost as the second element of the tuple. Required to return
  // correct cost estimation for the tree, extracts are calculated separately.
  // Extracts, calculated here, are just quick estimations.
  SmallVector<
      std::tuple<InstructionCost, InstructionCost, SmallVector<unsigned>>>
      SubtreeCosts(VectorizableTree.size());
  auto IsNotDeleted = [&](const TreeEntry *TE) {
    return !DeletedNodes.contains(TE);
  };
  // (Re)computes the subtree costs for the nodes that are not deleted.
  auto ComputeSubtreeCosts = [&]() {
    SubtreeCosts.assign(
        VectorizableTree.size(),
        std::tuple<InstructionCost, InstructionCost, SmallVector<unsigned>>());
    auto UpdateParentNodes =
        [&](const TreeEntry *UserTE, const TreeEntry *TE,
            InstructionCost TotalCost, InstructionCost Cost,
            SmallDenseSet<std::pair<const TreeEntry *, const TreeEntry *>, 4>
                &VisitedUser,
            bool AddToList = true) {
          while (UserTE &&
                 VisitedUser.insert(std::make_pair(TE, UserTE)).second) {
            std::get<0>(SubtreeCosts[UserTE->Idx]) += TotalCost;
            std::get<1>(SubtreeCosts[UserTE->Idx]) += Cost;
            if (AddToList)
              std::get<2>(SubtreeCosts[UserTE->Idx]).push_back(TE->Idx);
            UserTE = UserTE->UserTreeIndex.UserTE;
          }
        };
    for (const std::unique_ptr<TreeEntry> &Ptr : VectorizableTree) {
      TreeEntry &TE = *Ptr;
      if (DeletedNodes.contains(&TE))
        continue;
      // Combined subnodes are not costed on their own (their cost is 0), but
      // must be included into the ancestors' subtree node lists, so that they
      // get deleted together with the trimmed combined root.
      InstructionCost C = NodesCosts.at(&TE);
      InstructionCost ExtractCost = ExtractCosts.lookup(&TE);
      std::get<0>(SubtreeCosts[TE.Idx]) += C + ExtractCost;
      std::get<1>(SubtreeCosts[TE.Idx]) += C;
      if (const TreeEntry *UserTE = TE.UserTreeIndex.UserTE) {
        SmallDenseSet<std::pair<const TreeEntry *, const TreeEntry *>, 4>
            VisitedUser;
        UpdateParentNodes(UserTE, &TE, C + ExtractCost, C, VisitedUser);
      }
    }
    SmallDenseSet<std::pair<const TreeEntry *, const TreeEntry *>, 4> Visited;
    for (TreeEntry *TE : make_filter_range(GatheredLoadsNodes, IsNotDeleted)) {
      InstructionCost TotalCost = std::get<0>(SubtreeCosts[TE->Idx]);
      InstructionCost Cost = std::get<1>(SubtreeCosts[TE->Idx]);
      for (Value *V : TE->Scalars) {
        const auto Nodes = ValueToGatherNodes.lookup(V);
        for (const TreeEntry *BVTE : make_filter_range(Nodes, IsNotDeleted))
          UpdateParentNodes(BVTE, TE, TotalCost, Cost, Visited,
                            /*AddToList=*/false);
      }
    }
  };
  ComputeSubtreeCosts();
  using ValuesToInsertTy =
      SmallDenseMap<const TreeEntry *, SmallVector<Value *>>;
  auto GetScalarTy = [&](const TreeEntry *TE) {
    Type *ScalarTy = TE->Scalars.front()->getType();
    auto It = MinBWs.find(TE);
    if (It != MinBWs.end())
      ScalarTy = IntegerType::get(ScalarTy->getContext(), It->second.first);
    return ScalarTy;
  };
  // Lanes of the subtree scalars used by the surviving gather nodes, and the
  // values to materialize in those gathers if the subtree is deleted.
  auto FindDemandedElts = [&](TreeEntry *TE, ValuesToInsertTy &ValuesToInsert) {
    APInt DemandedElts = APInt::getZero(TE->getVectorFactor());
    for (Value *V : TE->Scalars) {
      unsigned Pos = TE->findLaneForValue(V);
      const auto Nodes = ValueToGatherNodes.lookup(V);
      for (const TreeEntry *BVE : make_filter_range(Nodes, IsNotDeleted)) {
        DemandedElts.setBit(Pos);
        ValuesToInsert.try_emplace(BVE).first->second.push_back(V);
      }
    }
    return DemandedElts;
  };
  // Cost of materializing the values directly in the surviving gather nodes
  // that use them.
  auto GetGatherInsertCost = [&](Type *ScalarTy,
                                 const ValuesToInsertTy &ValuesToInsert) {
    InstructionCost BVCost = 0;
    for (const auto &[BVE, Values] : ValuesToInsert) {
      APInt BVDemandedElts = APInt::getZero(BVE->getVectorFactor());
      SmallVector<Value *> BVValues(BVE->getVectorFactor(),
                                    PoisonValue::get(ScalarTy));
      for (Value *V : Values) {
        unsigned Pos = BVE->findLaneForValue(V);
        BVValues[Pos] = V;
        BVDemandedElts.setBit(Pos);
      }
      BVCost += getScalarizationOverhead(
          *TTI, Opts.slp_revec, ScalarTy,
          cast<VectorType>(getWidenedType(ScalarTy, BVE->getVectorFactor())),
          BVDemandedElts, /*Insert=*/true, /*Extract=*/false, CostKind,
          BVDemandedElts.isAllOnes(), BVValues);
    }
    return BVCost;
  };
  auto RecostEntry = [&](const TreeEntry *TE) {
    InstructionCost C = getEntryCost(TE, VectorizedVals, CheckedExtracts);
    if (!C.isValid() || C == 0)
      return C;
    uint64_t Scale = EntryToScale.lookup(TE);
    if (!Scale)
      Scale = getEntryEffectiveScale(*TE, TE->Idx == 0 ? RdxRoot : nullptr);
    return C * Scale;
  };
  // A splat subtree pays off only if some surviving gather node reuses it and
  // its price plus the extracts of its scalars used by the remaining scalar
  // code plus the current cost of the gather nodes that reuse it is not worse
  // than re-emitting those gathers without the subtree.
  auto IsSplatSubtreeProfitable = [&](TreeEntry *TE,
                                      ValuesToInsertTy &ValuesToInsert,
                                      InstructionCost &CurrentGathersCost,
                                      InstructionCost &DroppedGathersCost) {
    if (FindDemandedElts(TE, ValuesToInsert).isZero())
      return false;
    APInt ExtractElts = APInt::getZero(TE->getVectorFactor());
    for (Instruction *I : make_isa_range<Instruction>(TE->Scalars)) {
      if (TE->isCopyableElement(I))
        continue;
      // Too many users - the scalar is extracted anyway.
      if (I->hasNUsesOrMore(UsesLimit) || any_of(I->users(), [&](User *U) {
            return none_of(getTreeEntries(U), [&](const TreeEntry *UseTE) {
              return !DeletedNodes.contains(UseTE) &&
                     !TransformedToGatherNodes.contains(UseTE);
            });
          }))
        ExtractElts.setBit(TE->findLaneForValue(I));
    }
    Type *ScalarTy = GetScalarTy(TE);
    InstructionCost KeepCost = getScalarizationOverhead(
        *TTI, Opts.slp_revec, ScalarTy,
        cast<VectorType>(getWidenedType(ScalarTy, TE->getVectorFactor())),
        ExtractElts, /*Insert=*/false, /*Extract=*/true, CostKind);
    // Scale the extract cost to the subtree's execution frequency: the
    // subtree and gather costs it is compared against are already loop-scaled.
    if (KeepCost.isValid() && KeepCost != 0)
      KeepCost *= getEntryEffectiveScale(*TE);
    // Add the cost of the subtree itself, computed before any trimming:
    // trimming of the subtree's own nodes would otherwise make it look
    // artificially cheap. The inner nodes of the subtree keep their external
    // scalar users too, so their extracts are part of the price as well.
    KeepCost += std::get<1>(SubtreeCosts[TE->Idx]);
    for (unsigned Idx : std::get<2>(SubtreeCosts[TE->Idx]))
      KeepCost += ExtractCosts.lookup(VectorizableTree[Idx].get());
    // The reusing gather nodes currently pay the broadcast cost; without
    // the subtree they fall back to plain insertion sequences. Gather
    // nodes already erased from NodesCosts are being deleted and do not
    // count on either side.
    CurrentGathersCost = 0;
    for (const auto &[BVE, _] : ValuesToInsert)
      CurrentGathersCost += NodesCosts.lookup(BVE);
    KeepCost += CurrentGathersCost;
    // Re-cost the gather nodes with the subtree tentatively deleted.
    DeletedNodes.insert(TE);
    SmallVector<TreeEntry *> TempDeleted;
    for (unsigned Idx : std::get<2>(SubtreeCosts[TE->Idx])) {
      TreeEntry *Child = VectorizableTree[Idx].get();
      if (DeletedNodes.insert(Child).second)
        TempDeleted.push_back(Child);
    }
    DroppedGathersCost = 0;
    auto HasCost = [&](const auto &P) { return NodesCosts.contains(P.first); };
    for (const auto &[BVE, _] : make_filter_range(ValuesToInsert, HasCost))
      DroppedGathersCost += RecostEntry(BVE);
    DeletedNodes.erase(TE);
    for (TreeEntry *Child : TempDeleted)
      DeletedNodes.erase(Child);
    // On a cost tie prefer dropping the subtree: the reusing gathers
    // materialize the scalars at the same price with fewer instructions.
    return KeepCost < DroppedGathersCost;
  };
  // Re-price the gathers that reused a dropped splat subtree, so the
  // remaining subtrees are checked against the costs with it deleted.
  auto SyncGatherCosts = [&](const ValuesToInsertTy &ValuesToInsert) {
    for (const auto &[BVE, _] : ValuesToInsert)
      if (!DeletedNodes.contains(BVE))
        NodesCosts[BVE] = RecostEntry(BVE);
  };
  // Deletes the subtree. The per-node costs are erased eagerly only where the
  // total is recomputed from them right after the deletion.
  auto DeleteSubtree = [&](TreeEntry *TE, bool EraseCosts) {
    DeletedNodes.insert(TE);
    if (EraseCosts)
      NodesCosts.erase(TE);
    for (unsigned Idx : std::get<2>(SubtreeCosts[TE->Idx])) {
      TreeEntry *Child = VectorizableTree[Idx].get();
      DeletedNodes.insert(Child);
      if (EraseCosts)
        NodesCosts.erase(Child);
    }
  };
  // Gathered loads subtrees left without surviving gather users are dead.
  auto DropDeadGatheredLoads = [&](bool EraseCosts) {
    for (TreeEntry *TE : make_filter_range(GatheredLoadsNodes, IsNotDeleted)) {
      ValuesToInsertTy ValuesToInsert;
      if (!FindDemandedElts(TE, ValuesToInsert).isZero())
        continue;
      DeleteSubtree(TE, EraseCosts);
    }
  };
  // Drops the splat subtrees that are unused by the surviving gathers or do
  // not pay off; returns true if anything was dropped.
  auto DropUnprofitableSplatSubtrees = [&](bool EraseCosts) {
    bool Dropped = false;
    for (TreeEntry *TE :
         make_filter_range(SplatGatheredScalarsRoots, IsNotDeleted)) {
      ValuesToInsertTy ValuesToInsert;
      InstructionCost CurrentGathersCost = 0, DroppedGathersCost = 0;
      if (IsSplatSubtreeProfitable(TE, ValuesToInsert, CurrentGathersCost,
                                   DroppedGathersCost))
        continue;
      DeleteSubtree(TE, EraseCosts);
      SyncGatherCosts(ValuesToInsert);
      Dropped = true;
    }
    return Dropped;
  };
  auto SumNodesCosts = [&]() {
    InstructionCost C = 0;
    for (const auto &P : NodesCosts)
      C += P.second;
    return C;
  };
  // The splat subtrees are speculative. The ones that do not pay off even in
  // the full tree are dropped before the trimming: the reusing gathers are
  // priced for the broadcast from the subtree vector while the subtree is
  // around, which distorts the trimming decisions of the main tree, and fewer
  // surviving gathers after the trimming can only make keeping a subtree less
  // profitable.
  if (DropUnprofitableSplatSubtrees(/*EraseCosts=*/true)) {
    DropDeadGatheredLoads(/*EraseCosts=*/true);
    ComputeSubtreeCosts();
    Cost = SumNodesCosts();
  }
  using CostIndicesTy =
      std::pair<TreeEntry *, std::tuple<InstructionCost, InstructionCost,
                                        SmallVector<unsigned>>>;
  struct FirstGreater {
    bool operator()(const CostIndicesTy &LHS, const CostIndicesTy &RHS) const {
      return std::get<0>(LHS.second) < std::get<0>(RHS.second) ||
             (std::get<0>(LHS.second) == std::get<0>(RHS.second) &&
              LHS.first->Idx < RHS.first->Idx);
    }
  };
  PriorityQueue<CostIndicesTy, SmallVector<CostIndicesTy>, FirstGreater>
      Worklist;
  // Combined subnodes are not trimmed on their own, only as a whole combined
  // node, so only the root nodes are checked and included into the worklist.
  for (const auto [Idx, P] :
       make_filter_range(enumerate(SubtreeCosts), [&](const auto &Elem) {
         return VectorizableTree[Elem.index()]->State !=
                TreeEntry::CombinedVectorize;
       }))
    Worklist.emplace(VectorizableTree[Idx].get(), P);

  // Narrow store trees with non-profitable immediate values - exit.
  if (!UserIgnoreList && getRootNode().getVectorFactor() < MinVF &&
      getRootNode().hasState() &&
      getRootNode().getOpcode() == Instruction::Store &&
      (Worklist.top().first->Idx == 0 || Worklist.top().first->Idx == 1))
    return Cost;

  // Node costs and deleted nodes before any trimming; the restored tree is
  // priced from them if the trimming is reverted.
  const SmallDenseMap<const TreeEntry *, InstructionCost> OrigNodesCosts =
      NodesCosts;
  const SmallPtrSet<const TreeEntry *, 8> OrigDeletedNodes = DeletedNodes;
  bool Changed = false;
  bool PreferTrimmedTree = false;
  while (!Worklist.empty() && std::get<0>(Worklist.top().second) > 0) {
    TreeEntry *TE = Worklist.top().first;
    if (TE->isGather() || TE->Idx == 0 || DeletedNodes.contains(TE) ||
        isa<StructType>(getValueType(TE->Scalars.front(), Opts.slp_revec)) ||
        // Splat subtree roots are decided by the keep/drop check below: their
        // scalars are materialized in the reusing splat gathers, not in a
        // gather of the root's own scalars.
        is_contained(SplatGatheredScalarsRoots, TE) ||
        // Exit early if the parent node is split node and any of scalars is
        // used in other split nodes.
        (TE->UserTreeIndex &&
         TE->UserTreeIndex.UserTE->State == TreeEntry::SplitVectorize &&
         any_of(TE->Scalars, [&](Value *V) {
           ArrayRef<TreeEntry *> Entries = getSplitTreeEntries(V);
           return Entries.size() > 1;
         }))) {
      Worklist.pop();
      continue;
    }
    // Skip inversed compare nodes, they cannot be transformed to buildvectors.
    if (TE->State == TreeEntry::Vectorize && !TE->isAltShuffle() &&
        (TE->getOpcode() == Instruction::ICmp ||
         TE->getOpcode() == Instruction::FCmp) &&
        any_of(make_isa_range<CmpInst>(TE->Scalars), [&](CmpInst *I) {
          return I->getPredicate() !=
                 cast<CmpInst>(TE->getMainOp())->getPredicate();
        })) {
      Worklist.pop();
      continue;
    }
    // A zext feeding a bit pack is priced as part of the pack: its vectorized
    // form makes the compaction back to the source width free, so keep it.
    if (TE->UserTreeIndex && TE->UserTreeIndex.EdgeIdx == 0 &&
        TE->UserTreeIndex.UserTE->CombinedOp == TreeEntry::ReducedBitPack &&
        getZExtSrcWidth(*TE) != 0) {
      Worklist.pop();
      continue;
    }

    // Calculate the gather cost of the root node.
    InstructionCost TotalSubtreeCost = std::get<0>(Worklist.top().second);
    InstructionCost SubtreeCost = std::get<1>(Worklist.top().second);
    if (TotalSubtreeCost < TE->Scalars.size()) {
      Worklist.pop();
      continue;
    }
    if (!TransformedToGatherNodes.empty()) {
      for (unsigned Idx : std::get<2>(Worklist.top().second)) {
        auto It = TransformedToGatherNodes.find(VectorizableTree[Idx].get());
        if (It != TransformedToGatherNodes.end()) {
          TotalSubtreeCost -= std::get<0>(SubtreeCosts[Idx]);
          SubtreeCost -= std::get<1>(SubtreeCosts[Idx]);
          TotalSubtreeCost += It->second;
          SubtreeCost += It->second;
        }
      }
    }
    if (TotalSubtreeCost < 0 || TotalSubtreeCost < TE->Scalars.size()) {
      Worklist.pop();
      continue;
    }
    const unsigned EntryVF = TE->getVectorFactor();
    APInt DemandedElts = APInt::getZero(EntryVF);
    for (auto [Idx, V] : enumerate(TE->Scalars)) {
      if (!isConstant(V))
        DemandedElts.setBit(Idx);
    }

    Type *ScalarTy = getValueType(TE->Scalars.front(), Opts.slp_revec);
    auto It = MinBWs.find(TE);
    if (It != MinBWs.end())
      ScalarTy = IntegerType::get(ScalarTy->getContext(), It->second.first);
    auto *VecTy = getWidenedType(ScalarTy, EntryVF);
    InstructionCost GatherCost = getScalarizationOverhead(
        *TTI, Opts.slp_revec, ScalarTy, cast<VectorType>(VecTy), DemandedElts,
        /*Insert=*/true, /*Extract=*/false, CostKind);
    SmallVector<int> Mask;
    if (!TE->ReorderIndices.empty() &&
        TE->State != TreeEntry::CompressVectorize &&
        (TE->State != TreeEntry::StridedVectorize || !TE->isReverse() ||
         isWidenedStridedLoad(TE))) {
      SmallVector<int> NewMask;
      if (TE->getOpcode() == Instruction::Store) {
        // For stores the order is actually a mask.
        NewMask.resize(TE->ReorderIndices.size());
        copy(TE->ReorderIndices, NewMask.begin());
      } else {
        inversePermutation(TE->ReorderIndices, NewMask);
      }
      addMask(Mask, NewMask);
    }
    if (!TE->ReuseShuffleIndices.empty())
      addMask(Mask, TE->ReuseShuffleIndices);
    if (!Mask.empty() && !ShuffleVectorInst::isIdentityMask(Mask, EntryVF))
      GatherCost += getShuffleCost(*TTI, TTI::SK_PermuteSingleSrc,
                                   cast<VectorType>(VecTy), CostKind, Mask);
    // If all scalars are reused in gather node(s) or other vector nodes, there
    // might be extra cost for inserting them.
    if ((!TE->hasState() || !TE->isAltShuffle()) &&
        all_of(TE->Scalars, [&](Value *V) {
          return (TE->hasCopyableElements() && TE->isCopyableElement(V)) ||
                 isConstant(V) || isGathered(V) || getTreeEntries(V).size() > 1;
        }))
      GatherCost *= 2;
    // The fmuls, priced as fused into their vectorized fadd/fsub users, stay
    // scalar and unfused in the gathered form.
    GatherCost += getUnfusedFMulsPenalty(*TE);
    // Erase subtree if it is non-profitable.
    ArrayRef<unsigned> Nodes = std::get<2>(Worklist.top().second);
    // Prefer trimming equal-cost alternate-shuffle subtrees rooted at binary
    // ops: alt-shuffles introduce runtime shuffle overhead that the cost model
    // may underestimate. Skip if the subtree contains ExtractElement nodes,
    // since those operate on already-materialized vectors where the cost model
    // is more accurate.
    auto IsEqualCostAltShuffleToTrim = [&]() {
      return TotalSubtreeCost == GatherCost && TE->hasState() &&
             TE->isAltShuffle() && Instruction::isBinaryOp(TE->getOpcode()) &&
             none_of(Nodes, [&](unsigned Idx) {
               return VectorizableTree[Idx]->hasState() &&
                      VectorizableTree[Idx]->getOpcode() ==
                          Instruction::ExtractElement;
             });
    };
    // Non-power-of-2 entries may have inflated costs - add a margin of 1
    // before trimming to avoid over-pruning.
    bool HasNonPowerOf2 = any_of(Nodes, [&](unsigned Idx) {
      return !has_single_bit(VectorizableTree[Idx]->Scalars.size());
    });
    InstructionCost TrimMargin = HasNonPowerOf2 ? 1 : 0;
    if (TotalSubtreeCost > GatherCost + TrimMargin ||
        IsEqualCostAltShuffleToTrim()) {
      PreferTrimmedTree |= TotalSubtreeCost == GatherCost;
      // If the remaining tree is just a buildvector - exit, it will cause
      // endless attempts to vectorize. When the tree is already profitable,
      // skip trimming this node and let the post-loop logic (including
      // gathered loads processing) decide.
      if (getRootNode().hasState() &&
          getRootNode().getOpcode() == Instruction::InsertElement &&
          TE->Idx == 1) {
        if (Cost < -getCostThreshold()) {
          LLVM_DEBUG(dbgs() << "SLP: Skipping trim of node " << TE->Idx
                            << " - tree already profitable with cost " << Cost
                            << ".\n");
          Worklist.pop();
          continue;
        }
        return InstructionCost::getInvalid();
      }

      LLVM_DEBUG(dbgs() << "SLP: Trimming unprofitable subtree at node "
                        << TE->Idx << " with cost "
                        << std::get<0>(Worklist.top().second)
                        << " and gather cost " << GatherCost << ".\n");
      if (TE->UserTreeIndex) {
        TransformedToGatherNodes.try_emplace(TE, GatherCost);
        NodesCosts.erase(TE);
      } else {
        DeletedNodes.insert(TE);
        TransformedToGatherNodes.erase(TE);
        NodesCosts.erase(TE);
      }
      for (unsigned Idx : Nodes) {
        TreeEntry &ChildTE = *VectorizableTree[Idx];
        DeletedNodes.insert(&ChildTE);
        TransformedToGatherNodes.erase(&ChildTE);
        NodesCosts.erase(&ChildTE);
      }
      Changed = true;
    }
    Worklist.pop();
  }
  // The VF=2 instruction-count veto rejects the whole tree when the vector code
  // has more instructions than the scalar code. The auxiliary subtrees - splat
  // gather roots and gathered loads - are optional: the surviving gathers can
  // re-materialize their scalars. Drop the reused ones while the tree exceeds
  // the budget so a kept subtree cannot reject the main tree. The gate mirrors
  // the veto conditions.
  const bool ApplyInstCountVeto =
      (!SplatGatheredScalarsRoots.empty() || !GatheredLoadsNodes.empty()) &&
      CostKind != TTI::TCK_CodeSize && Opts.slp_inst_count_check &&
      TTI->preferSLPInstCountCheck() && getRootNode().getVectorFactor() == 2 &&
      getCostThreshold() == 0 &&
      (!Opts.slp_revec ||
       !isa<VectorType>(getRootNodeScalars().front()->getType()));
  const Loop *InstCountLoop = nullptr;
  if (ApplyInstCountVeto && Opts.slp_cost_loop_trip_count != 0 &&
      getRootNode().hasState())
    InstCountLoop = LI->getLoopFor(getRootNode().getMainOp()->getParent());
  auto TrimAuxSubtreesForInstCount = [&](InstructionCost &Cost,
                                         bool UseCurrentNodeCosts) {
    if (!ApplyInstCountVeto || bypassesInstCountCheck(Cost))
      return;
    // Current cost of the subtree rooted at TE from the per-node costs.
    auto GetCurrentSubtreeCost = [&](const TreeEntry *TE) {
      InstructionCost C = NodesCosts.lookup(TE);
      for (unsigned Idx : std::get<2>(SubtreeCosts[TE->Idx]))
        C += NodesCosts.lookup(VectorizableTree[Idx].get());
      return C;
    };
    auto DropReusedSubtree = [&](TreeEntry *TE, bool DeadOnly) {
      if (DeletedNodes.contains(TE) || TransformedToGatherNodes.contains(TE))
        return false;
      ValuesToInsertTy ValuesToInsert;
      const bool IsDead = FindDemandedElts(TE, ValuesToInsert).isZero();
      if (!IsDead && DeadOnly)
        return false;
      InstructionCost CurrentGathersCost = 0;
      for (const auto &[BVE, _] : ValuesToInsert)
        CurrentGathersCost += NodesCosts.lookup(BVE);
      DeleteSubtree(TE, /*EraseCosts=*/false);
      // All reusers were dropped: the subtree is dead. Without current node
      // costs the total conservatively keeps the subtree cost.
      if (IsDead) {
        if (UseCurrentNodeCosts)
          Cost -= GetCurrentSubtreeCost(TE);
        return true;
      }
      InstructionCost DroppedGathersCost = 0;
      for (const auto &[BVE, _] : ValuesToInsert)
        if (NodesCosts.contains(BVE))
          DroppedGathersCost += RecostEntry(BVE);
      // The pre-trimming subtree cost matches the total only while the tree
      // is intact or restored; an accepted trimming leaves the total holding
      // just the current costs of the surviving subtree nodes.
      InstructionCost SubtreeCost = UseCurrentNodeCosts
                                        ? GetCurrentSubtreeCost(TE)
                                        : std::get<1>(SubtreeCosts[TE->Idx]);
      Cost += DroppedGathersCost - CurrentGathersCost - SubtreeCost;
      SyncGatherCosts(ValuesToInsert);
      return true;
    };
    // Recompute the counts only after an actual drop. Dropping a root can
    // kill the reusers of a root from the other list, so repeat until no more
    // drops; dead subtrees are removed even under the budget.
    uint64_t NumScalar = getNumScalarInsts(InstCountLoop);
    uint64_t NumVector = getNumVectorInsts(InstCountLoop);
    bool Retry;
    do {
      Retry = false;
      for (ArrayRef<TreeEntry *> Roots :
           {ArrayRef<TreeEntry *>(SplatGatheredScalarsRoots),
            GatheredLoadsNodes.getArrayRef()})
        for (TreeEntry *TE : Roots)
          if (DropReusedSubtree(TE, /*DeadOnly=*/NumVector <= NumScalar)) {
            NumScalar = getNumScalarInsts(InstCountLoop);
            NumVector = getNumVectorInsts(InstCountLoop);
            Retry = true;
          }
    } while (Retry);
  };
  if (!Changed) {
    // The splat subtrees are not linked to the tree root, so their cost is
    // not included in the root's subtree cost; add it explicitly. Drop the
    // unprofitable ones instead of letting them reject the whole tree.
    InstructionCost TotalCost = std::get<1>(SubtreeCosts.front());
    for (TreeEntry *TE :
         make_filter_range(SplatGatheredScalarsRoots, [&](TreeEntry *TE) {
           return !DeletedNodes.contains(TE);
         })) {
      ValuesToInsertTy ValuesToInsert;
      InstructionCost CurrentGathersCost = 0, DroppedGathersCost = 0;
      if (IsSplatSubtreeProfitable(TE, ValuesToInsert, CurrentGathersCost,
                                   DroppedGathersCost)) {
        TotalCost += std::get<1>(SubtreeCosts[TE->Idx]);
        continue;
      }
      DeleteSubtree(TE, /*EraseCosts=*/false);
      // The gather nodes that reused the subtree are re-emitted without it.
      TotalCost += DroppedGathersCost - CurrentGathersCost;
      SyncGatherCosts(ValuesToInsert);
    }
    DropDeadGatheredLoads(/*EraseCosts=*/false);
    TrimAuxSubtreesForInstCount(TotalCost, /*UseCurrentNodeCosts=*/false);
    return TotalCost;
  }

  SmallPtrSet<TreeEntry *, 4> SubtreesToDelete;
  InstructionCost LoadsExtractsCost = 0;
  // Check if all gather nodes that reuse the splat subtrees are marked for
  // deletion. In this case the whole splat subtree must be deleted. If only
  // some of the gathers are trimmed, keeping the subtree still costs its full
  // price plus the extracts of the scalars used by the remaining scalar code,
  // while the surviving gathers can materialize the splatted scalars
  // directly. Drop the subtree if it does not pay off.
  for (TreeEntry *TE :
       make_filter_range(SplatGatheredScalarsRoots, [&](TreeEntry *TE) {
         return !DeletedNodes.contains(TE);
       })) {
    ValuesToInsertTy ValuesToInsert;
    InstructionCost CurrentGathersCost, DroppedGathersCost;
    if (IsSplatSubtreeProfitable(TE, ValuesToInsert, CurrentGathersCost,
                                 DroppedGathersCost))
      continue;
    SubtreesToDelete.insert(TE);
    NodesCosts.erase(TE);
  }

  // Check if all loads of gathered loads nodes are marked for deletion. In this
  // case the whole gathered loads subtree must be deleted.
  // Also, try to account for extracts, which might be required, if only part of
  // gathered load must be vectorized. Keep partially vectorized nodes, if
  // extracts are cheaper than gathers.
  for (TreeEntry *TE :
       make_filter_range(GatheredLoadsNodes, [&](TreeEntry *TE) {
         return !DeletedNodes.contains(TE) &&
                !TransformedToGatherNodes.contains(TE);
       })) {
    SubtreesToDelete.insert(TE);
    // All loads are removed from gathered? Need to delete the subtree.
    ValuesToInsertTy ValuesToInsert;
    APInt DemandedElts = FindDemandedElts(TE, ValuesToInsert);
    if (!DemandedElts.isZero()) {
      Type *ScalarTy = GetScalarTy(TE);
      auto *VecTy = getWidenedType(ScalarTy, TE->getVectorFactor());
      InstructionCost ExtractsCost = getScalarizationOverhead(
          *TTI, Opts.slp_revec, ScalarTy, cast<VectorType>(VecTy), DemandedElts,
          /*Insert=*/false, /*Extract=*/true, CostKind);
      InstructionCost BVCost = GetGatherInsertCost(ScalarTy, ValuesToInsert);
      if (ExtractsCost < BVCost) {
        LoadsExtractsCost += ExtractsCost;
        SubtreesToDelete.erase(TE);
        continue;
      }
      LoadsExtractsCost += BVCost;
    }
    NodesCosts.erase(TE);
  }

  // Deleted all subtrees rooted at gathered loads nodes or splat subtrees.
  for (std::unique_ptr<TreeEntry> &TE : VectorizableTree) {
    if (TE->UserTreeIndex &&
        SubtreesToDelete.contains(TE->UserTreeIndex.UserTE)) {
      DeletedNodes.insert(TE.get());
      NodesCosts.erase(TE.get());
      SubtreesToDelete.insert(TE.get());
    }
    if (SubtreesToDelete.contains(TE.get()))
      DeletedNodes.insert(TE.get());
  }

  for (std::unique_ptr<TreeEntry> &TE : VectorizableTree) {
    if (!TE->UserTreeIndex && TransformedToGatherNodes.contains(TE.get())) {
      assert(TE->getOpcode() == Instruction::Load && "Expected load only.");
      continue;
    }
    if (DeletedNodes.contains(TE.get()))
      continue;
    // Gather costs depend on the set of vectorized nodes available for
    // reuse, which changes during trimming, so recalculate them for all
    // gather nodes, not just for the transformed ones.
    if (TE->isGather() || !NodesCosts.contains(TE.get()))
      NodesCosts[TE.get()] = RecostEntry(TE.get());
  }

  LLVM_DEBUG(dbgs() << "SLP: Recalculate costs after tree trimming.\n");
  InstructionCost NewCost = 0;
  for (const auto &P : NodesCosts) {
    NewCost += P.second;
    LLVM_DEBUG(dbgs() << "SLP: Adding cost " << P.second << " for bundle "
                      << shortBundleName(P.first->Scalars, P.first->Idx)
                      << ".\n"
                      << "SLP: Current total cost = " << NewCost << "\n");
  }
  // The trimming is reverted if the restored tree is not more expensive. The
  // restored tree is priced the same way as the trimmed one, from the per-node
  // costs: adjusting the pre-trimming total incrementally is not exact with
  // the auxiliary subtrees around, since the subtree costs recorded before the
  // trimming fold in the gathered loads they reuse, and the gathers inside a
  // subtree change their price once their reuse sources are dropped.
  auto ComputeRestoredCost = [&]() {
    DeletedNodes = OrigDeletedNodes;
    TransformedToGatherNodes.clear();
    NodesCosts = OrigNodesCosts;
    if (!SplatGatheredScalarsRoots.empty()) {
      for (const std::unique_ptr<TreeEntry> &TE : VectorizableTree)
        if (TE->isGather() && !DeletedNodes.contains(TE.get()))
          NodesCosts[TE.get()] = RecostEntry(TE.get());
      DropUnprofitableSplatSubtrees(/*EraseCosts=*/false);
      // Dropping the splat subtrees may leave the gathered loads subtrees
      // built for them without surviving gather users.
      DropDeadGatheredLoads(/*EraseCosts=*/false);
      for (const TreeEntry *TE : DeletedNodes)
        NodesCosts.erase(TE);
    }
    return SumNodesCosts();
  };
  const InstructionCost TrimmedCost = NewCost + LoadsExtractsCost;
  auto TrimmedDeletedNodes = DeletedNodes;
  auto TrimmedTransformedNodes = TransformedToGatherNodes;
  auto TrimmedNodesCosts = NodesCosts;
  const InstructionCost RestoredCost = ComputeRestoredCost();
  LLVM_DEBUG(dbgs() << "SLP: Trimmed tree cost = " << TrimmedCost
                    << ", restored tree cost = " << RestoredCost << ".\n");
  const bool Reverted = TrimmedCost > RestoredCost ||
                        (!PreferTrimmedTree && TrimmedCost == RestoredCost);
  if (Reverted) {
    NewCost = RestoredCost;
  } else {
    DeletedNodes = std::move(TrimmedDeletedNodes);
    TransformedToGatherNodes = std::move(TrimmedTransformedNodes);
    NodesCosts = std::move(TrimmedNodesCosts);
    // If the remaining tree is just a buildvector - exit, it will cause
    // endless attempts to vectorize.
    if (VectorizableTree.size() >= 2 && getRootNode().hasState() &&
        getRootNode().getOpcode() == Instruction::InsertElement &&
        TransformedToGatherNodes.contains(VectorizableTree[1].get()))
      return InstructionCost::getInvalid();
    if (VectorizableTree.size() >= 3 && getRootNode().hasState() &&
        getRootNode().getOpcode() == Instruction::InsertElement &&
        VectorizableTree[1]->hasState() &&
        VectorizableTree[1]->State == TreeEntry::Vectorize &&
        (VectorizableTree[1]->getOpcode() == Instruction::ZExt ||
         VectorizableTree[1]->getOpcode() == Instruction::SExt ||
         VectorizableTree[1]->getOpcode() == Instruction::Trunc) &&
        TransformedToGatherNodes.contains(VectorizableTree[2].get()))
      return InstructionCost::getInvalid();
  }
  TrimAuxSubtreesForInstCount(NewCost, /*UseCurrentNodeCosts=*/true);
  return NewCost;
}

namespace {
/// Data type for handling buildvector sequences with the reused scalars from
/// other tree entries.
template <typename T> struct ShuffledInsertData {
  /// List of insertelements to be replaced by shuffles.
  SmallVector<InsertElementInst *> InsertElements;
  /// The parent vectors and shuffle mask for the given list of inserts.
  MapVector<T, SmallVector<int>> ValueMasks;
};
} // namespace

/// \returns true if more values with the scalar type \p Ty than registers are
/// live at some point of the block \p BB. The blocks larger than the scheduling
/// budget are skipped to save compile time.
static bool hasHighRegisterPressure(const VectorizeOptions &Opts,
                                    const BasicBlock &BB, Type *Ty,
                                    const TargetTransformInfo &TTI) {
  if (hasNItemsOrMore(BB, Opts.slp_schedule_budget))
    return false;
  const unsigned NumRegs = TTI.getNumberOfRegisters(
      TTI.getRegisterClassForType(/*Vector=*/false, Ty));
  auto IsLiveCandidate = [&](const Value *V) {
    return isa<Instruction, Argument>(V) && V->getType()->getScalarType() == Ty;
  };
  SmallPtrSet<const Value *, 32> Live;
  for (const Instruction &I : reverse(BB)) {
    // The operands of the PHIs are live in the predecessors.
    if (isa<PHINode>(I))
      break;
    Live.erase(&I);
    Live.insert_range(make_filter_range(I.operand_values(), IsLiveCandidate));
    if (Live.size() > NumRegs)
      return true;
  }
  return false;
}

InstructionCost BoUpSLP::getTreeCost(InstructionCost TreeCost,
                                     ArrayRef<Value *> VectorizedVals,
                                     InstructionCost ReductionCost,
                                     Instruction *RdxRoot) {
  // Reject vectorization if the vector code would produce more instructions
  // than the scalar code. The cost model may underestimate overhead from
  // shuffles, inserts, and extracts.
  // FIXME: remove this as soon as correct fractional model is landed for all
  // targets.
  if (CostKind != TTI::TCK_CodeSize && Opts.slp_inst_count_check &&
      TTI->preferSLPInstCountCheck() && getRootNode().getVectorFactor() == 2 &&
      getCostThreshold() == 0 &&
      (!Opts.slp_revec ||
       !isa<VectorType>(getRootNodeScalars().front()->getType()))) {
    // Loop containing the tree root; null for flat code or disabled
    // loop-aware modeling. Shared by both calls below.
    const Loop *TreeLoop = nullptr;
    if (Opts.slp_cost_loop_trip_count != 0 && getRootNode().hasState())
      TreeLoop = LI->getLoopFor(getRootNode().getMainOp()->getParent());
    uint64_t NumScalar = getNumScalarInsts(TreeLoop);
    uint64_t NumVector = getNumVectorInsts(TreeLoop);
    // In loops, the extracts are not scaled by the trip count and just break
    // the ties of the scaled counts. Ignore them under the high register
    // pressure: the vector code holds several lanes per register.
    if (NumVector > NumScalar && TreeLoop && !ExternalUses.empty()) {
      const uint64_t NumNoExtracts =
          getNumVectorInsts(TreeLoop, /*CountExtracts=*/false);
      Instruction *Root = getRootNode().getMainOp();
      if (NumNoExtracts <= NumScalar &&
          hasHighRegisterPressure(Opts, *Root->getParent(),
                                  getValueType(Root, Opts.slp_revec), *TTI))
        NumVector = NumNoExtracts;
    }
    LLVM_DEBUG(dbgs() << "SLP: Inst count check: vector=" << NumVector
                      << " scalar=" << NumScalar << "\n");
    if (NumVector > NumScalar && !bypassesInstCountCheck(TreeCost)) {
      LLVM_DEBUG(dbgs() << "SLP: Rejecting tree: vector inst count "
                        << NumVector << " > scalar inst count " << NumScalar
                        << ".\n");
      return InstructionCost::getInvalid();
    }
  }
  InstructionCost Cost = TreeCost;

  SmallDenseMap<std::tuple<const TreeEntry *, Value *, Instruction *>, uint64_t>
      EntryToScale;
  auto ScaleCost = [&](InstructionCost C, const TreeEntry &TE,
                       Value *Scalar = nullptr, Instruction *U = nullptr) {
    if (!C.isValid() || C == 0)
      return C;
    uint64_t &Scale =
        EntryToScale.try_emplace(std::make_tuple(&TE, Scalar, U), 0)
            .first->getSecond();
    if (!Scale)
      Scale = getScaleToLoopIterations(TE, Scalar, U);
    LLVM_DEBUG(dbgs() << "Scale " << Scale << " For entry " << TE.Idx << "\n");
    return C * Scale;
  };
  Instruction *ReductionRoot = RdxRoot;
  if (UserIgnoreList) {
    // Scale reduction cost to the factor of the loop nest trip count.
    ReductionCost = ScaleCost(ReductionCost, getRootNode(), /*Scalar=*/nullptr,
                              ReductionRoot);
  }

  // Add the cost for reduction.
  Cost += ReductionCost;

  if (any_of(ExternalUses, [](const ExternalUser &EU) {
        return isa<StructType>(EU.Scalar->getType()) &&
               (EU.E.Idx != 0 || EU.E.State != TreeEntry::Vectorize ||
                EU.E.getOpcode() != Instruction::InsertValue) &&
               !isa_and_nonnull<ExtractValueInst>(EU.User);
      }))
    return InstructionCost::getInvalid();

  // Skip trees, which are non-profitable even if there are insertelements with
  // external uses.
  constexpr unsigned CostLimit = 100;
  if (Cost >= -getCostThreshold() + CostLimit &&
      (VectorizableTree.size() - DeletedNodes.size()) *
              getRootNode().getVectorFactor() <
          CostLimit)
    return Cost;

  if (Cost >= -getCostThreshold() &&
      none_of(ExternalUses, [](const ExternalUser &EU) {
        return isa_and_nonnull<InsertElementInst>(EU.User);
      }))
    return Cost;

  SmallDenseSet<std::pair<Value *, SmallVector<unsigned, 1>>, 16>
      ExtractCostCalculated;
  InstructionCost ExtractCost = 0;
  SmallVector<ShuffledInsertData<const TreeEntry *>> ShuffledInserts;
  SmallVector<APInt> DemandedElts;
  SmallDenseSet<Value *, 4> UsedInserts;
  DenseSet<std::pair<const TreeEntry *, Type *>> VectorCasts;
  std::optional<DenseMap<Value *, unsigned>> ValueToExtUses;
  DenseMap<const TreeEntry *, DenseSet<Value *>> ExtractsCount;
  SmallPtrSet<Value *, 4> ScalarOpsFromCasts;
  // Keep track {Scalar, Index, User} tuple.
  // On AArch64, this helps in fusing a mov instruction, associated with
  // extractelement, with fmul in the backend so that extractelement is free.
  SmallVector<std::tuple<Value *, User *, int>, 4> ScalarUserAndIdx;
  // Record every external use: a missing entry is indistinguishable from
  // lane 0 and is priced as a free extract by the extract-fusion cost model.
  for (ExternalUser &EU : ExternalUses)
    ScalarUserAndIdx.emplace_back(EU.Scalar, EU.User, EU.Lane);
  // Detect external uses that drive address computations: the scalar (through
  // an optional single-use index-promotion cast) is used as a GEP index.
  bool AllUsersGEPSWithStoresLoads = true;
  SmallVector<const Value *> Pointers;
  Type *UserScalarTy = nullptr;
  for (ExternalUser &EU : ExternalUses) {
    Value *Usr = EU.User;
    if (Usr && match(Usr, m_OneUse(m_ZExtOrSExt(m_Value()))))
      Usr = cast<Instruction>(Usr)->user_back();
    auto *User = dyn_cast_if_present<GetElementPtrInst>(Usr);
    // Only a GEP that feeds a single load/store of a fixed access type drives
    // a real memory address computation.
    Type *AccessTy = nullptr;
    if (User && User->hasOneUse() &&
        isa<LoadInst, StoreInst>(User->user_back()))
      AccessTy = getValueType(User->user_back(), Opts.slp_revec);
    if (AccessTy && !isa<ScalableVectorType>(AccessTy) &&
        (!UserScalarTy || UserScalarTy == AccessTy)) {
      UserScalarTy = AccessTy;
      Pointers.push_back(User);
    } else {
      AllUsersGEPSWithStoresLoads = false;
      break;
    }
  }

  // Pre-pass: for each externally-used scalar, find the basic block at which
  // the extractelement will be placed by codegen. This mirrors what
  // vectorizeTree does: the extract is placed at the nearest common dominator
  // of all effective use sites. For a non-PHI user the effective site is the
  // user's own block; for a PHI user it is the incoming block for the scalar
  // operand (the predecessor of the PHI on the edge that carries the scalar).
  // Using the NCD of all effective sites rather than the first-encountered
  // user's block makes the extract-cost scale order-independent and correct
  // even when users live in different loop nests.
  SmallDenseMap<Value *, BasicBlock *> ScalarToExtractBlock;
  for (const ExternalUser &EU :
       make_filter_range(ExternalUses, [](const ExternalUser &EU) {
         return EU.User && !isa<InsertElementInst>(EU.User);
       })) {
    if (EphValues.count(EU.User))
      continue;
    BasicBlock *UserParent = cast<Instruction>(EU.User)->getParent();
    if (!DT->isReachableFromEntry(UserParent) || UserParent->isEHPad() ||
        isa<UnreachableInst>(UserParent->getTerminator()))
      continue;
    BasicBlock *UseBlock = nullptr;
    if (auto *PHI = dyn_cast<PHINode>(EU.User)) {
      // When the PHI itself is inside a loop, the extractelement is placed
      // in the incoming block for the scalar operand (the predecessor edge),
      // not in the PHI's own block.  This applies to LCSSA phis at an inner-
      // loop exit that are still inside an outer loop: the incoming block is
      // in the inner loop while the PHI block is in the outer loop.
      // When the PHI is outside all loops (a true loop-exit phi), codegen
      // uses a vector phi at the exit block and the extract stays there
      // (scale = 1), so we keep the PHI's own block as the effective site.
      if (LI->getLoopFor(PHI->getParent())) {
        for (unsigned Idx : seq<unsigned>(PHI->getNumIncomingValues())) {
          if (PHI->getIncomingValue(Idx) != EU.Scalar)
            continue;
          BasicBlock *InBB = PHI->getIncomingBlock(Idx);
          UseBlock =
              UseBlock ? DT->findNearestCommonDominator(UseBlock, InBB) : InBB;
        }
      }
      if (!UseBlock)
        UseBlock = cast<Instruction>(EU.User)->getParent();
    } else {
      UseBlock = cast<Instruction>(EU.User)->getParent();
    }
    auto [It, Inserted] = ScalarToExtractBlock.try_emplace(EU.Scalar, UseBlock);
    if (!Inserted && It->second && UseBlock)
      It->second = DT->findNearestCommonDominator(It->second, UseBlock);
  }

  SmallDenseSet<std::pair<Value *, Value *>, 8> CheckedScalarUser;
  for (ExternalUser &EU : ExternalUses) {
    LLVM_DEBUG(dbgs() << "SLP: Computing cost for external use of TreeEntry "
                      << EU.E.Idx << " in lane " << EU.Lane << "\n");
    LLVM_DEBUG(if (EU.User) dbgs() << "  User:" << *EU.User << "\n";
               else dbgs() << "  User: nullptr\n");
    LLVM_DEBUG(dbgs() << "  Use: " << EU.Scalar->getNameOrAsOperand() << "\n");

    // Uses by ephemeral values are free (because the ephemeral value will be
    // removed prior to code generation, and so the extraction will be
    // removed as well).
    if (EphValues.count(EU.User))
      continue;

    // Check if the scalar for the given user or all users is accounted already.
    if (!CheckedScalarUser.insert(std::make_pair(EU.Scalar, EU.User)).second ||
        (EU.User &&
         CheckedScalarUser.contains(std::make_pair(EU.Scalar, nullptr))))
      continue;

    // Used in unreachable blocks or in EH pads (rarely executed) or is
    // terminated with unreachable instruction.
    if (BasicBlock *UserParent =
            EU.User ? cast<Instruction>(EU.User)->getParent() : nullptr;
        UserParent &&
        (!DT->isReachableFromEntry(UserParent) || UserParent->isEHPad() ||
         isa<UnreachableInst>(UserParent->getTerminator())))
      continue;

    // No extract cost for vector "scalar" if REVEC is disabled.
    if (isVectorizedTy(EU.Scalar->getType()) &&
        (!Opts.slp_revec ||
         (EU.E.hasState() && EU.E.getOpcode() == Instruction::InsertElement)))
      continue;

    if (isa<InsertValueInst>(EU.Scalar))
      continue;

    // If found user is an insertelement, do not calculate extract cost but try
    // to detect it as a final shuffled/identity match.
    // TODO: what if a user is insertvalue when REVEC is enabled?
    if (auto *VU = dyn_cast_if_present<InsertElementInst>(EU.User);
        VU && VU->getOperand(1) == EU.Scalar) {
      if (auto *FTy = dyn_cast<FixedVectorType>(VU->getType())) {
        if (!UsedInserts.insert(VU).second)
          continue;
        std::optional<unsigned> InsertIdx = getElementIndex(VU);
        if (InsertIdx) {
          const TreeEntry *ScalarTE = &EU.E;
          auto *It = find_if(
              ShuffledInserts,
              [this, VU](const ShuffledInsertData<const TreeEntry *> &Data) {
                // Checks if 2 insertelements are from the same buildvector.
                InsertElementInst *VecInsert = Data.InsertElements.front();
                return areTwoInsertFromSameBuildVector(
                    VU, VecInsert, [this](InsertElementInst *II) -> Value * {
                      Value *Op0 = II->getOperand(0);
                      if (isVectorized(II) && !isVectorized(Op0))
                        return nullptr;
                      return Op0;
                    });
              });
          int VecId = -1;
          if (It == ShuffledInserts.end()) {
            auto &Data = ShuffledInserts.emplace_back();
            Data.InsertElements.emplace_back(VU);
            DemandedElts.push_back(APInt::getZero(FTy->getNumElements()));
            VecId = ShuffledInserts.size() - 1;
            auto It = MinBWs.find(ScalarTE);
            if (It != MinBWs.end() &&
                VectorCasts
                    .insert(std::make_pair(ScalarTE, FTy->getElementType()))
                    .second) {
              unsigned BWSz = It->second.first;
              unsigned DstBWSz = DL->getTypeSizeInBits(FTy->getElementType());
              unsigned VecOpcode;
              if (DstBWSz < BWSz)
                VecOpcode = Instruction::Trunc;
              else
                VecOpcode =
                    It->second.second ? Instruction::SExt : Instruction::ZExt;
              InstructionCost C = TTI->getCastInstrCost(
                  VecOpcode, FTy,
                  getWidenedType(IntegerType::get(FTy->getContext(), BWSz),
                                 FTy->getNumElements()),
                  getCastContextHint(*ScalarTE), CostKind);
              LLVM_DEBUG(dbgs() << "SLP: Adding cost " << C
                                << " for extending externally used vector with "
                                   "non-equal minimum bitwidth.\n");
              Cost += C;
            }
          } else {
            if (isFirstInsertElement(VU, It->InsertElements.front()))
              It->InsertElements.front() = VU;
            VecId = std::distance(ShuffledInserts.begin(), It);
          }
          int InIdx = *InsertIdx;
          SmallVectorImpl<int> &Mask =
              ShuffledInserts[VecId].ValueMasks[ScalarTE];
          if (Mask.empty())
            Mask.assign(FTy->getNumElements(), PoisonMaskElem);
          Mask[InIdx] = EU.Lane;
          DemandedElts[VecId].setBit(InIdx);
          continue;
        }
      }
    }

    // If we plan to rewrite the tree in a smaller type, we will need to sign
    // extend the extracted value back to the original type. Here, we account
    // for the extract and the added cost of the sign extend if needed.
    InstructionCost ExtraCost = TTI::TCC_Free;
    auto *ScalarTy = EU.Scalar->getType();
    const unsigned BundleWidth = EU.E.getVectorFactor();
    assert(EU.Lane < BundleWidth && "Extracted lane out of bounds.");
    auto *VecTy = getWidenedType(ScalarTy, BundleWidth);
    const TreeEntry *Entry = &EU.E;
    auto It = MinBWs.find(Entry);
    SmallVector<unsigned, 1> Indices;
    if (isa<StructType>(VecTy)) {
      assert(EU.User && "Expected user for struct extract");
      const auto *EV = cast<ExtractValueInst>(EU.User);
      Indices.assign(EV->getIndices());
    }
    // We only add extract cost once for the same scalar and struct field.
    auto ExtractKey = std::make_pair(EU.Scalar, Indices);
    if (!isa_and_nonnull<InsertElementInst>(EU.User) &&
        !ExtractCostCalculated.insert(ExtractKey).second)
      continue;
    if (It != MinBWs.end()) {
      Type *MinTy = IntegerType::get(F->getContext(), It->second.first);
      if (auto *VecTy = dyn_cast<FixedVectorType>(ScalarTy))
        MinTy = getWidenedType(MinTy, VecTy->getNumElements());
      unsigned Extend = isKnownNonNegative(EU.Scalar, SimplifyQuery(*DL))
                            ? Instruction::ZExt
                            : Instruction::SExt;
      VecTy = getWidenedType(MinTy, BundleWidth);
      ExtraCost =
          getExtractWithExtendCost(*TTI, Opts.slp_revec, Extend, ScalarTy,
                                   cast<VectorType>(VecTy), EU.Lane, CostKind);
      LLVM_DEBUG(dbgs() << "  ExtractExtend or ExtractSubvec cost: "
                        << ExtraCost << "\n");
    } else {
      Type *ExtractTy = VecTy;
      if (auto *ST = dyn_cast<StructType>(VecTy)) {
        ExtractTy = ExtractValueInst::getIndexedType(ST, Indices);
      }
      ExtraCost = getVectorInstrCost(
          *TTI, Opts.slp_revec, ScalarTy, Instruction::ExtractElement,
          ExtractTy, CostKind, EU.Lane, EU.Scalar, ScalarUserAndIdx);
      LLVM_DEBUG(dbgs() << "  ExtractElement cost for " << *ScalarTy << " from "
                        << *VecTy << ": " << ExtraCost << "\n");
    }
    // Leave the scalar instructions as is if they are cheaper than extracts.
    if (Entry->Idx != 0 || Entry->getOpcode() == Instruction::GetElementPtr ||
        Entry->getOpcode() == Instruction::Load) {
      // Checks if the user of the external scalar is phi in loop body.
      auto IsPhiInLoop = [&](const ExternalUser &U) {
        if (auto *Phi = dyn_cast_if_present<PHINode>(U.User)) {
          auto *I = cast<Instruction>(U.Scalar);
          const Loop *L = LI->getLoopFor(Phi->getParent());
          return L && (Phi->getParent() == I->getParent() ||
                       L == LI->getLoopFor(I->getParent()));
        }
        return false;
      };
      if (!ValueToExtUses) {
        ValueToExtUses.emplace();
        // Ignore phis in loops.
        for (const auto &P :
             make_filter_range(enumerate(ExternalUses), [&](const auto &P) {
               return !IsPhiInLoop(P.value());
             }))
          ValueToExtUses->try_emplace(P.value().Scalar, P.index());
      }
      // Can use original instruction, if no operands vectorized or they are
      // marked as externally used already.
      auto *Inst = cast<Instruction>(EU.Scalar);
      InstructionCost ScalarCost = TTI->getInstructionCost(Inst, CostKind);
      auto OperandIsScalar = [&](Value *V) {
        if (!isVectorized(V)) {
          // Some extractelements might be not vectorized, but
          // transformed into shuffle and removed from the function,
          // consider it here.
          if (auto *EE = dyn_cast<ExtractElementInst>(V))
            return !EE->hasOneUse() || !MustGather.contains(EE);
          return true;
        }
        if (isa<StructType>(V->getType()))
          return false;
        return ValueToExtUses->contains(V);
      };
      bool CanBeUsedAsScalar = all_of(Inst->operands(), OperandIsScalar);
      bool CanBeUsedAsScalarCast = false;
      if (auto *CI = dyn_cast<CastInst>(Inst); CI && !CanBeUsedAsScalar) {
        if (auto *Op = dyn_cast<Instruction>(CI->getOperand(0));
            Op && all_of(Op->operands(), OperandIsScalar)) {
          InstructionCost OpCost =
              (isVectorized(Op) && !ValueToExtUses->contains(Op))
                  ? TTI->getInstructionCost(Op, CostKind)
                  : 0;
          if (ScalarCost + OpCost <= ExtraCost) {
            CanBeUsedAsScalar = CanBeUsedAsScalarCast = true;
            ScalarCost += OpCost;
          }
        }
      }
      if (CanBeUsedAsScalar) {
        bool KeepScalar = ScalarCost <= ExtraCost;
        // Try to keep original scalar if the user is the phi node from the same
        // block as the root phis, currently vectorized. It allows to keep
        // better ordering info of PHIs, being vectorized currently.
        bool IsProfitablePHIUser =
            (KeepScalar || (ScalarCost - ExtraCost <= TTI::TCC_Basic &&
                            getRootNodeScalars().size() > 2)) &&
            getRootNode().hasState() &&
            getRootNode().getOpcode() == Instruction::PHI &&
            !Inst->hasNUsesOrMore(UsesLimit) &&
            none_of(Inst->users(),
                    [&](User *U) {
                      auto *PHIUser = dyn_cast<PHINode>(U);
                      return (!PHIUser ||
                              PHIUser->getParent() !=
                                  getRootNode().getMainOp()->getParent()) &&
                             !isVectorized(U);
                    }) &&
            count_if(Entry->Scalars, [&](Value *V) {
              return ValueToExtUses->contains(V);
            }) <= 2;
        // The extracted address index hides the consecutive accesses of the
        // users from the later trees.
        auto *GEPUser = dyn_cast_if_present<GetElementPtrInst>(EU.User);
        const bool IsAddressIndex =
            GEPUser && GEPUser->getPointerOperand() != EU.Scalar;
        if (IsProfitablePHIUser) {
          KeepScalar = true;
        } else if (KeepScalar && ScalarCost != TTI::TCC_Free &&
                   ExtraCost - ScalarCost <= TTI::TCC_Basic &&
                   !IsAddressIndex &&
                   (!GatheredLoadsEntriesFirst.has_value() ||
                    Entry->Idx < *GatheredLoadsEntriesFirst)) {
          unsigned ScalarUsesCount = count_if(Entry->Scalars, [&](Value *V) {
            return ValueToExtUses->contains(V);
          });
          auto It = ExtractsCount.find(Entry);
          if (It != ExtractsCount.end()) {
            assert(ScalarUsesCount >= It->getSecond().size() &&
                   "Expected total number of external uses not less than "
                   "number of scalar uses.");
            ScalarUsesCount -= It->getSecond().size();
          }
          // Keep original scalar if number of externally used instructions in
          // the same entry is not power of 2. It may help to do some extra
          // vectorization for now.
          KeepScalar = ScalarUsesCount <= 1 || !has_single_bit(ScalarUsesCount);
        }
        if (KeepScalar) {
          ExternalUsesAsOriginalScalar.insert(EU.Scalar);
          // Struct operands cannot be rebuilt by the !User extraction
          // path (it has no insertvalue chain), so leave their existing
          // ExtractValueInst user in place.
          for (Value *V : make_filter_range(Inst->operands(), [](Value *V) {
                 return !isa<StructType>(V->getType());
               })) {
            auto It = ValueToExtUses->find(V);
            if (It != ValueToExtUses->end()) {
              // Replace all uses to avoid compiler crash.
              ExternalUses[It->second].User = nullptr;
            }
          }
          ExtraCost = ScalarCost;
          if (!IsPhiInLoop(EU))
            ExtractsCount[Entry].insert(Inst);
          if (CanBeUsedAsScalarCast) {
            ScalarOpsFromCasts.insert(Inst->getOperand(0));
            // Update the users of the operands of the cast operand to avoid
            // compiler crash.
            if (auto *IOp = dyn_cast<Instruction>(Inst->getOperand(0))) {
              for (Value *V : make_filter_range(IOp->operands(), [](Value *V) {
                     return !isa<StructType>(V->getType());
                   })) {
                auto It = ValueToExtUses->find(V);
                if (It != ValueToExtUses->end()) {
                  // Replace all uses to avoid compiler crash.
                  ExternalUses[It->second].User = nullptr;
                }
              }
            }
          }
        }
      }
    }

    // Scale the extract cost by the execution frequency of the block where
    // codegen will place the extractelement. That block is the nearest common
    // dominator of all effective use sites (precomputed in ScalarToExtractBlock
    // above), which is order-independent. For scalars kept as originals the
    // existing ScaleCost path (user-block based) remains correct, since the
    // scalar instruction executes at its definition site's frequency.
    if (!ExternalUsesAsOriginalScalar.contains(EU.Scalar)) {
      if (ExtraCost.isValid() && ExtraCost != 0) {
        if (!EU.User) {
          // No external user instruction is recorded (User == nullptr): the
          // scalar stays live in vectorized instructions or is used as an
          // extra arg, and is not present in ScalarToExtractBlock (the
          // pre-pass only records sites of real users). vectorizeTree() then
          // places the extractelement right after the vectorized instruction
          // (in the entry's block) and replaces the scalar uses with it, so
          // scale by the entry block's execution frequency to match that
          // placement.
          ExtraCost = ScaleCost(ExtraCost, *Entry, EU.Scalar, /*U=*/nullptr);
        } else {
          BasicBlock *ExtractBB = ScalarToExtractBlock.lookup(EU.Scalar);
          if (const Loop *L = ExtractBB ? LI->getLoopFor(ExtractBB) : nullptr) {
            uint64_t Scale = getLoopNestScale(
                findInnermostNonInvariantLoop(L, ArrayRef<Value *>(EU.Scalar)));
            LLVM_DEBUG(dbgs()
                       << "SLP: Extract scale " << Scale << " (NCD block) for "
                       << EU.Scalar->getNameOrAsOperand() << "\n");
            ExtraCost *= Scale;
          }
        }
      }
    } else {
      ExtraCost = ScaleCost(ExtraCost, *Entry, EU.Scalar,
                            cast_if_present<Instruction>(EU.User));
    }

    ExtractCost += ExtraCost;
  }
  // Charge the pointer-chain cost difference once when every escaped scalar
  // is used only to drive an address computation (see the detection loop
  // above). Vectorizing the tree in this pattern forces lane extracts (or a
  // vector GEP with unknown stride) to drive the address computation, which is
  // typically more expensive than keeping the indices scalar in a unit-stride
  // address chain. Add the delta once rather than per external use.
  if (AllUsersGEPSWithStoresLoads && !Pointers.empty()) {
    const TreeEntry &RootEntry = getRootNode();
    const Value *CommonBase = getUnderlyingObject(Pointers.front());
    if (all_of(Pointers, [CommonBase](const Value *P) {
          return getUnderlyingObject(P) == CommonBase;
        })) {
      auto *VecTy = getWidenedType(UserScalarTy, RootEntry.Scalars.size());
      InstructionCost ScalarGEPCost = TTI->getPointersChainCost(
          Pointers, CommonBase, TTI::PointersChainInfo::getUnitStride(),
          UserScalarTy, CostKind);
      InstructionCost VectorGEPCost = TTI->getPointersChainCost(
          Pointers, CommonBase, TTI::PointersChainInfo::getUnknownStride(),
          VecTy, CostKind);
      ExtractCost += ScaleCost(VectorGEPCost - ScalarGEPCost, RootEntry);
    }
  }
  // Insert externals for extract of operands of casts to be emitted as scalars
  // instead of extractelement.
  for (Value *V : ScalarOpsFromCasts) {
    ExternalUsesAsOriginalScalar.insert(V);
    if (ArrayRef<TreeEntry *> TEs = getTreeEntries(V); !TEs.empty()) {
      const auto *It = find_if_not(TEs, [&](TreeEntry *TE) {
        return TransformedToGatherNodes.contains(TE) ||
               DeletedNodes.contains(TE);
      });
      if (It != TEs.end()) {
        const TreeEntry *UserTE = *It;
        ExternalUses.emplace_back(V, nullptr, *UserTE,
                                  UserTE->findLaneForValue(V));
      }
    }
  }
  // Add reduced value cost, if resized.
  if (!VectorizedVals.empty()) {
    const TreeEntry &Root = getRootNode();
    auto BWIt = MinBWs.find(&Root);
    if (BWIt != MinBWs.end()) {
      Type *DstTy = Root.Scalars.front()->getType();
      unsigned OriginalSz = DL->getTypeSizeInBits(DstTy->getScalarType());
      unsigned SrcSz =
          ReductionBitWidth == 0 ? BWIt->second.first : ReductionBitWidth;
      if (OriginalSz != SrcSz) {
        unsigned Opcode = Instruction::Trunc;
        if (OriginalSz > SrcSz)
          Opcode = BWIt->second.second ? Instruction::SExt : Instruction::ZExt;
        Type *SrcTy = IntegerType::get(DstTy->getContext(), SrcSz);
        if (auto *VecTy = dyn_cast<FixedVectorType>(DstTy)) {
          assert(Opts.slp_revec && "Only supported by REVEC.");
          SrcTy = getWidenedType(SrcTy, VecTy->getNumElements());
        }
        InstructionCost CastCost = TTI->getCastInstrCost(
            Opcode, DstTy, SrcTy, TTI::CastContextHint::None, CostKind);
        CastCost = ScaleCost(CastCost, Root, /*Scalar=*/nullptr, ReductionRoot);
        Cost += CastCost;
      }
    }
  }

  // Buildvector with externally used scalars, which should remain as scalars,
  // should not be vectorized, the compiler may hang.
  if (getCostThreshold() < 0 && VectorizableTree.size() > 1 &&
      isa<InsertElementInst>(VectorizableTree[0]->Scalars[0]) &&
      VectorizableTree[1]->hasState() &&
      VectorizableTree[1]->State == TreeEntry::Vectorize &&
      all_of(VectorizableTree[1]->Scalars, [&](Value *V) {
        return ExternalUsesAsOriginalScalar.contains(V);
      }))
    return InstructionCost::getInvalid();

  Cost += ExtractCost;
  auto &&ResizeToVF = [this, &Cost](const TreeEntry *TE, ArrayRef<int> Mask,
                                    bool ForSingleMask) {
    InstructionCost C = 0;
    unsigned VF = Mask.size();
    unsigned VecVF = TE->getVectorFactor();
    bool HasLargeIndex =
        any_of(Mask, [VF](int Idx) { return Idx >= static_cast<int>(VF); });
    if ((VF != VecVF && HasLargeIndex) ||
        !ShuffleVectorInst::isIdentityMask(Mask, VF)) {

      if (HasLargeIndex) {
        SmallVector<int> OrigMask(VecVF, PoisonMaskElem);
        std::copy(Mask.begin(), std::next(Mask.begin(), std::min(VF, VecVF)),
                  OrigMask.begin());
        C = getShuffleCost(
            *TTI, TTI::SK_PermuteSingleSrc,
            cast<VectorType>(getWidenedType(TE->getMainOp()->getType(), VecVF)),
            CostKind, OrigMask);
        LLVM_DEBUG(
            dbgs() << "SLP: Adding cost " << C
                   << " for final shuffle of insertelement external users.\n";
            TE->dump(); dbgs() << "SLP: Current total cost = " << Cost << "\n");
        Cost += C;
        return std::make_pair(TE, true);
      }

      if (!ForSingleMask) {
        SmallVector<int> ResizeMask(VF, PoisonMaskElem);
        for (unsigned I = 0; I < VF; ++I) {
          if (Mask[I] != PoisonMaskElem)
            ResizeMask[Mask[I]] = Mask[I];
        }
        if (!ShuffleVectorInst::isIdentityMask(ResizeMask, VF))
          C = getShuffleCost(*TTI, TTI::SK_PermuteSingleSrc,
                             cast<VectorType>(getWidenedType(
                                 TE->getMainOp()->getType(), VecVF)),
                             CostKind, ResizeMask);
        LLVM_DEBUG(
            dbgs() << "SLP: Adding cost " << C
                   << " for final shuffle of insertelement external users.\n";
            TE->dump(); dbgs() << "SLP: Current total cost = " << Cost << "\n");

        Cost += C;
      }
    }
    return std::make_pair(TE, false);
  };
  // Calculate the cost of the reshuffled vectors, if any.
  for (int I = 0, E = ShuffledInserts.size(); I < E; ++I) {
    Value *Base = ShuffledInserts[I].InsertElements.front()->getOperand(0);
    auto Vector = ShuffledInserts[I].ValueMasks.takeVector();
    unsigned VF = 0;
    auto EstimateShufflesCost = [&](ArrayRef<int> Mask,
                                    ArrayRef<const TreeEntry *> TEs) {
      assert((TEs.size() == 1 || TEs.size() == 2) &&
             "Expected exactly 1 or 2 tree entries.");
      if (TEs.size() == 1) {
        if (VF == 0)
          VF = TEs.front()->getVectorFactor();
        auto *FTy = getWidenedType(TEs.back()->Scalars.front()->getType(), VF);
        if (!ShuffleVectorInst::isIdentityMask(Mask, VF) &&
            !all_of(enumerate(Mask), [=](const auto &Data) {
              return Data.value() == PoisonMaskElem ||
                     (Data.index() < VF &&
                      static_cast<int>(Data.index()) == Data.value());
            })) {
          InstructionCost C =
              getShuffleCost(*TTI, TTI::SK_PermuteSingleSrc,
                             cast<VectorType>(FTy), CostKind, Mask);
          C = ScaleCost(C, *TEs.front());
          LLVM_DEBUG(dbgs() << "SLP: Adding cost " << C
                            << " for final shuffle of insertelement "
                               "external users.\n";
                     TEs.front()->dump();
                     dbgs() << "SLP: Current total cost = " << Cost << "\n");
          Cost += C;
        }
      } else {
        if (VF == 0) {
          if (TEs.front() &&
              TEs.front()->getVectorFactor() == TEs.back()->getVectorFactor())
            VF = TEs.front()->getVectorFactor();
          else
            VF = Mask.size();
        }
        auto *FTy = getWidenedType(TEs.back()->Scalars.front()->getType(), VF);
        InstructionCost C = getShuffleCost(
            *TTI, TTI::SK_PermuteTwoSrc, cast<VectorType>(FTy), CostKind, Mask);
        C = ScaleCost(C, *TEs.back());
        LLVM_DEBUG(dbgs() << "SLP: Adding cost " << C
                          << " for final shuffle of vector node and external "
                             "insertelement users.\n";
                   if (TEs.front()) { TEs.front()->dump(); } TEs.back()->dump();
                   dbgs() << "SLP: Current total cost = " << Cost << "\n");
        Cost += C;
      }
      VF = Mask.size();
      return TEs.back();
    };
    (void)performExtractsShuffleAction<const TreeEntry>(
        MutableArrayRef(Vector.data(), Vector.size()), Base,
        [](const TreeEntry *E) { return E->getVectorFactor(); }, ResizeToVF,
        EstimateShufflesCost);
    InstructionCost InsertCost = TTI->getScalarizationOverhead(
        cast<FixedVectorType>(
            ShuffledInserts[I].InsertElements.front()->getType()),
        DemandedElts[I],
        /*Insert*/ true, /*Extract*/ false, CostKind);
    Cost -= InsertCost;
  }

  // Add the cost for reduced value resize (if required).
  if (ReductionBitWidth != 0) {
    assert(UserIgnoreList && "Expected reduction tree.");
    const TreeEntry &E = getRootNode();
    auto It = MinBWs.find(&E);
    if (It != MinBWs.end() && It->second.first != ReductionBitWidth) {
      unsigned SrcSize = It->second.first;
      unsigned DstSize = ReductionBitWidth;
      unsigned Opcode = Instruction::Trunc;
      if (SrcSize < DstSize) {
        bool IsArithmeticExtendedReduction =
            all_of(*UserIgnoreList, [](Value *V) {
              auto *I = cast<Instruction>(V);
              return is_contained({Instruction::Add, Instruction::FAdd,
                                   Instruction::Mul, Instruction::FMul,
                                   Instruction::And, Instruction::Or,
                                   Instruction::Xor},
                                  I->getOpcode());
            });
        if (IsArithmeticExtendedReduction)
          Opcode =
              Instruction::BitCast; // Handle it by getExtendedReductionCost
        else
          Opcode = It->second.second ? Instruction::SExt : Instruction::ZExt;
      }
      if (Opcode != Instruction::BitCast) {
        auto *SrcVecTy =
            getWidenedType(Builder.getIntNTy(SrcSize), E.getVectorFactor());
        auto *DstVecTy =
            getWidenedType(Builder.getIntNTy(DstSize), E.getVectorFactor());
        TTI::CastContextHint CCH = getCastContextHint(E);
        switch (E.getOpcode()) {
        case Instruction::SExt:
        case Instruction::ZExt:
        case Instruction::Trunc: {
          // Split and gather roots have no operand entry to take the context
          // hint from.
          if (E.isGather() || E.State == TreeEntry::SplitVectorize)
            break;
          const TreeEntry *OpTE = getOperandEntry(&E, 0);
          CCH = getCastContextHint(*OpTE);
          break;
        }
        default:
          break;
        }
        InstructionCost CastCost =
            TTI->getCastInstrCost(Opcode, DstVecTy, SrcVecTy, CCH, CostKind);
        CastCost = ScaleCost(CastCost, getRootNode(), /*Scalar=*/nullptr,
                             ReductionRoot);
        Cost += CastCost;
        LLVM_DEBUG(dbgs() << "SLP: Adding cost " << CastCost
                          << " for final resize for reduction from " << SrcVecTy
                          << " to " << DstVecTy << "\n";
                   dbgs() << "SLP: Current total cost = " << Cost << "\n");
      }
    }
  }

  std::optional<InstructionCost> SpillCost;
  if (Cost < -getCostThreshold()) {
    SpillCost = getSpillCost();
    Cost += *SpillCost;
  }
#ifndef NDEBUG
  SmallString<256> Str;
  {
    raw_svector_ostream OS(Str);
    OS << "SLP: Spill Cost = ";
    if (SpillCost)
      OS << *SpillCost;
    else
      OS << "<skipped>";
    OS << ".\nSLP: Extract Cost = " << ExtractCost << ".\n";
    if (ReductionRoot)
      OS << "SLP:  Reduction Cost = " << ReductionCost << ".\n";
    OS << "SLP: Total Cost = " << Cost << ".\n";
  }
  LLVM_DEBUG(dbgs() << Str);
  if (Opts.view_slp_tree)
    ViewGraph(this, "SLP" + F->getName(), false, Str);
#endif

  return Cost;
}

/// Tries to find extractelement instructions with constant indices from fixed
/// vector type and gather such instructions into a bunch, which highly likely
/// might be detected as a shuffle of 1 or 2 input vectors. If this attempt was
/// successful, the matched scalars are replaced by poison values in \p VL for
/// future analysis.
std::optional<TTI::ShuffleKind>
BoUpSLP::tryToGatherSingleRegisterExtractElements(
    MutableArrayRef<Value *> VL, SmallVectorImpl<int> &Mask) const {
  // Scan list of gathered scalars for extractelements that can be represented
  // as shuffles.
  MapVector<Value *, SmallVector<int>> VectorOpToIdx;
  SmallVector<int> UndefVectorExtracts;
  for (int I = 0, E = VL.size(); I < E; ++I) {
    auto *EI = dyn_cast<ExtractElementInst>(VL[I]);
    if (!EI) {
      if (isa<UndefValue>(VL[I]))
        UndefVectorExtracts.push_back(I);
      continue;
    }
    auto *VecTy = dyn_cast<FixedVectorType>(EI->getVectorOperandType());
    if (!VecTy || !isa<ConstantInt, UndefValue>(EI->getIndexOperand()))
      continue;
    std::optional<unsigned> Idx = getExtractIndex(EI);
    // Undefined index.
    if (!Idx) {
      UndefVectorExtracts.push_back(I);
      continue;
    }
    if (Idx >= VecTy->getNumElements()) {
      UndefVectorExtracts.push_back(I);
      continue;
    }
    SmallBitVector ExtractMask(VecTy->getNumElements(), true);
    ExtractMask.reset(*Idx);
    if (isUndefVector</*IsPoisonOnly=*/true>(EI->getVectorOperand(),
                                             ExtractMask)
            .all()) {
      UndefVectorExtracts.push_back(I);
      continue;
    }
    VectorOpToIdx[EI->getVectorOperand()].push_back(I);
  }
  // Sort the vector operands by the maximum number of uses in extractelements.
  SmallVector<std::pair<Value *, SmallVector<int>>> Vectors =
      VectorOpToIdx.takeVector();
  stable_sort(Vectors, [](const auto &P1, const auto &P2) {
    return P1.second.size() > P2.second.size();
  });
  // Find the best pair of the vectors or a single vector.
  const int UndefSz = UndefVectorExtracts.size();
  unsigned SingleMax = 0;
  unsigned PairMax = 0;
  if (!Vectors.empty()) {
    SingleMax = Vectors.front().second.size() + UndefSz;
    if (Vectors.size() > 1) {
      auto *ItNext = std::next(Vectors.begin());
      PairMax = SingleMax + ItNext->second.size();
    }
  }
  if (SingleMax == 0 && PairMax == 0 && UndefSz == 0)
    return std::nullopt;
  // Check if better to perform a shuffle of 2 vectors or just of a single
  // vector.
  SmallVector<Value *> SavedVL(VL.begin(), VL.end());
  SmallVector<Value *> GatheredExtracts(
      VL.size(), PoisonValue::get(VL.front()->getType()));
  if (SingleMax >= PairMax && SingleMax) {
    for (int Idx : Vectors.front().second)
      std::swap(GatheredExtracts[Idx], VL[Idx]);
  } else if (!Vectors.empty()) {
    for (unsigned Idx : {0, 1})
      for (int Idx : Vectors[Idx].second)
        std::swap(GatheredExtracts[Idx], VL[Idx]);
  }
  // Add extracts from undefs too.
  for (int Idx : UndefVectorExtracts)
    std::swap(GatheredExtracts[Idx], VL[Idx]);
  // Check that gather of extractelements can be represented as just a
  // shuffle of a single/two vectors the scalars are extracted from.
  std::optional<TTI::ShuffleKind> Res =
      isFixedVectorShuffle(GatheredExtracts, Mask, AC, Cache);
  if (!Res || all_of(Mask, equal_to(PoisonMaskElem))) {
    // TODO: try to check other subsets if possible.
    // Restore the original VL and mask if attempt was not successful.
    copy(SavedVL, VL.begin());
    Mask.assign(VL.size(), PoisonMaskElem);
    return std::nullopt;
  }
  // Restore unused scalars from mask, if some of the extractelements were not
  // selected for shuffle.
  for (int I = 0, E = GatheredExtracts.size(); I < E; ++I) {
    if (Mask[I] == PoisonMaskElem && !isa<PoisonValue>(GatheredExtracts[I]) &&
        isa<UndefValue>(GatheredExtracts[I])) {
      std::swap(VL[I], GatheredExtracts[I]);
      continue;
    }
    auto *EI = dyn_cast<ExtractElementInst>(VL[I]);
    if (!EI || !isa<FixedVectorType>(EI->getVectorOperandType()) ||
        !isa<ConstantInt, UndefValue>(EI->getIndexOperand()) ||
        is_contained(UndefVectorExtracts, I))
      continue;
  }
  return Res;
}

/// Tries to find extractelement instructions with constant indices from fixed
/// vector type and gather such instructions into a bunch, which highly likely
/// might be detected as a shuffle of 1 or 2 input vectors. If this attempt was
/// successful, the matched scalars are replaced by poison values in \p VL for
/// future analysis.
SmallVector<std::optional<TTI::ShuffleKind>>
BoUpSLP::tryToGatherExtractElements(SmallVectorImpl<Value *> &VL,
                                    SmallVectorImpl<int> &Mask,
                                    unsigned NumParts) const {
  assert(NumParts > 0 && "NumParts expected be greater than or equal to 1.");
  SmallVector<std::optional<TTI::ShuffleKind>> ShufflesRes(NumParts);
  Mask.assign(VL.size(), PoisonMaskElem);
  unsigned SliceSize = getPartNumElems(VL.size(), NumParts);
  for (unsigned Part : seq<unsigned>(NumParts)) {
    // Scan list of gathered scalars for extractelements that can be represented
    // as shuffles.
    const unsigned PartOffset = Part * SliceSize;
    const unsigned PartSize = getNumElems(VL.size(), SliceSize, Part);
    // It may happen in case of revec, need to check no access out of bounds.
    if (PartOffset + PartSize > VL.size())
      break;
    MutableArrayRef<Value *> SubVL =
        MutableArrayRef(VL).slice(PartOffset, PartSize);
    SmallVector<int> SubMask;
    std::optional<TTI::ShuffleKind> Res =
        tryToGatherSingleRegisterExtractElements(SubVL, SubMask);
    ShufflesRes[Part] = Res;
    copy(SubMask, std::next(Mask.begin(), Part * SliceSize));
    if (SubVL.size() != SliceSize)
      break;
  }
  if (none_of(ShufflesRes, [](const std::optional<TTI::ShuffleKind> &Res) {
        return Res.has_value();
      }))
    ShufflesRes.clear();
  return ShufflesRes;
}

std::optional<TargetTransformInfo::ShuffleKind>
BoUpSLP::isGatherShuffledSingleRegisterEntry(
    const TreeEntry *TE, ArrayRef<Value *> VL, MutableArrayRef<int> Mask,
    SmallVectorImpl<const TreeEntry *> &Entries, unsigned Part, bool ForOrder,
    unsigned SliceSize) {
  Entries.clear();
  if (TE->Idx == 0)
    return std::nullopt;
  const unsigned MaskBase = Part * SliceSize;
  // TODO: currently checking only for Scalars in the tree entry, need to count
  // reused elements too for better cost estimation.
  auto GetUserEntry = [&](const TreeEntry *TE) {
    while (TE->UserTreeIndex && TE->UserTreeIndex.EdgeIdx == UINT_MAX)
      TE = TE->UserTreeIndex.UserTE;
    if (TE == &getRootNode())
      return EdgeInfo(const_cast<TreeEntry *>(TE), 0);
    return TE->UserTreeIndex;
  };
  auto HasGatherUser = [&](const TreeEntry *TE) {
    while (TE->Idx != 0 && TE->UserTreeIndex) {
      if (TE->UserTreeIndex.EdgeIdx == UINT_MAX)
        return true;
      TE = TE->UserTreeIndex.UserTE;
    }
    return false;
  };
  const EdgeInfo TEUseEI = GetUserEntry(TE);
  if (!TEUseEI || (TEUseEI.UserTE->Idx == 0 && TEUseEI.UserTE->isGather() &&
                   !TEUseEI.UserTE->hasState()))
    return std::nullopt;
  const Instruction *TEInsertPt = &getLastInstructionInBundle(TEUseEI.UserTE);
  const BasicBlock *TEInsertBlock = nullptr;
  // Main node of PHI entries keeps the correct order of operands/incoming
  // blocks.
  if (auto *PHI = TEUseEI.UserTE->hasState()
                      ? dyn_cast<PHINode>(TEUseEI.UserTE->getMainOp())
                      : nullptr;
      PHI && TEUseEI.UserTE->State != TreeEntry::SplitVectorize) {
    TEInsertBlock = PHI->getIncomingBlock(TEUseEI.EdgeIdx);
    TEInsertPt = TEInsertBlock->getTerminator();
  } else {
    TEInsertBlock = TEInsertPt->getParent();
  }
  if (!DT->isReachableFromEntry(TEInsertBlock))
    return std::nullopt;
  auto *NodeUI = DT->getNode(TEInsertBlock);
  assert(NodeUI && "Should only process reachable instructions");
  SmallPtrSet<Value *, 4> GatheredScalars(llvm::from_range, VL);
  auto CheckOrdering = [&](const Instruction *InsertPt) {
    // Argument InsertPt is an instruction where vector code for some other
    // tree entry (one that shares one or more scalars with TE) is going to be
    // generated. This lambda returns true if insertion point of vector code
    // for the TE dominates that point (otherwise dependency is the other way
    // around). The other node is not limited to be of a gather kind. Gather
    // nodes are not scheduled and their vector code is inserted before their
    // first user. If user is PHI, that is supposed to be at the end of a
    // predecessor block. Otherwise it is the last instruction among scalars of
    // the user node. So, instead of checking dependency between instructions
    // themselves, we check dependency between their insertion points for vector
    // code (since each scalar instruction ends up as a lane of a vector
    // instruction).
    const BasicBlock *InsertBlock = InsertPt->getParent();
    auto *NodeEUI = DT->getNode(InsertBlock);
    if (!NodeEUI)
      return false;
    assert((NodeUI == NodeEUI) ==
               (NodeUI->getDFSNumIn() == NodeEUI->getDFSNumIn()) &&
           "Different nodes should have different DFS numbers");
    // Check the order of the gather nodes users.
    if (TEInsertPt->getParent() != InsertBlock &&
        (DT->dominates(NodeUI, NodeEUI) || !DT->dominates(NodeEUI, NodeUI)))
      return false;
    if (TEInsertPt->getParent() == InsertBlock &&
        TEInsertPt->comesBefore(InsertPt))
      return false;
    return true;
  };
  // Find all tree entries used by the gathered values. If no common entries
  // found - not a shuffle.
  // Here we build a set of tree nodes for each gathered value and trying to
  // find the intersection between these sets. If we have at least one common
  // tree node for each gathered value - we have just a permutation of the
  // single vector. If we have 2 different sets, we're in situation where we
  // have a permutation of 2 input vectors.
  SmallVector<SmallPtrSet<const TreeEntry *, 4>> UsedTEs;
  SmallDenseMap<Value *, int> UsedValuesEntry;
  SmallPtrSet<const Value *, 16> VisitedValue;
  bool IsReusedNodeFound = false;
  auto CheckAndUseSameNode = [&](const TreeEntry *TEPtr) {
    // The node is reused - exit.
    if (IsReusedNodeFound)
      return false;
    if ((TEPtr->getVectorFactor() != VL.size() &&
         TEPtr->Scalars.size() != VL.size()) ||
        (!TEPtr->isSame(VL) && !TEPtr->isSame(TE->Scalars)))
      return false;
    IsReusedNodeFound =
        equal(TE->Scalars, TEPtr->Scalars) &&
        equal(TE->ReorderIndices, TEPtr->ReorderIndices) &&
        equal(TE->ReuseShuffleIndices, TEPtr->ReuseShuffleIndices);
    UsedTEs.clear();
    UsedTEs.emplace_back().insert(TEPtr);
    auto IsNotConstant = [](Value *V) { return !isConstant(V); };
    for (Value *V : make_filter_range(VL, IsNotConstant))
      UsedValuesEntry.try_emplace(V, 0);
    return true;
  };
  auto CheckParentNodes = [&](const TreeEntry *User1, const TreeEntry *User2,
                              unsigned EdgeIdx) {
    const TreeEntry *Ptr1 = User1;
    const TreeEntry *Ptr2 = User2;
    SmallDenseMap<const TreeEntry *, unsigned> PtrToIdx;
    while (Ptr2) {
      PtrToIdx.try_emplace(Ptr2, EdgeIdx);
      EdgeIdx = Ptr2->UserTreeIndex.EdgeIdx;
      Ptr2 = Ptr2->UserTreeIndex.UserTE;
    }
    while (Ptr1) {
      unsigned Idx = Ptr1->UserTreeIndex.EdgeIdx;
      Ptr1 = Ptr1->UserTreeIndex.UserTE;
      if (auto It = PtrToIdx.find(Ptr1); It != PtrToIdx.end())
        return Idx < It->second;
    }
    return false;
  };
  // Cache `isUsedOutsideBlock(TEInsertPt)` - TEInsertPt is loop-invariant and
  // the function walks the instruction's user list.
  std::optional<bool> TEInsertPtUsedOutsideBlock;
  auto IsTEInsertPtUsedOutsideBlock = [&] {
    if (!TEInsertPtUsedOutsideBlock)
      TEInsertPtUsedOutsideBlock =
          isUsedOutsideBlock(const_cast<Instruction *>(TEInsertPt));
    return *TEInsertPtUsedOutsideBlock;
  };
  // Cache the TEUseEI/TEInsertPt-only prefix of the per-call lambda predicate
  // below - all of these depend only on outer-scope state, not the lambda's
  // arguments.
  const bool TEUseEIInsertPtUsedOutside =
      TEUseEI && TEUseEI.UserTE && TEUseEI.UserTE->hasCopyableElements() &&
      !TEUseEI.UserTE->isCopyableElement(
          const_cast<Instruction *>(TEInsertPt)) &&
      IsTEInsertPtUsedOutsideBlock();
  auto CheckNonSchedulableOrdering = [&](const TreeEntry *E,
                                         Instruction *InsertPt) {
    return TEUseEIInsertPtUsedOutside &&
           InsertPt->getNextNode() == TEInsertPt &&
           (!E->hasCopyableElements() || !E->isCopyableElement(InsertPt) ||
            !isUsedOutsideBlock(InsertPt));
  };
  // Cache the TEUseEI.UserTE-dependent predicate - it is invariant across the
  // double loop below. all_of with isUsedOutsideBlock walks each scalar's
  // users and is the expensive component.
  const bool TEUserNeedsEmitFirst =
      TEUseEI.UserTE->State == TreeEntry::Vectorize &&
      TEUseEI.UserTE->hasState() &&
      (TEUseEI.UserTE->getOpcode() != Instruction::PHI ||
       TEUseEI.UserTE->isAltShuffle()) &&
      all_of(TEUseEI.UserTE->Scalars, isUsedOutsideBlock);
  // Cache `all_of(UserTE->Scalars, isUsedOutsideBlock)` per UserTE - the
  // same UserTE may be encountered for many TEPtr values inside the loop.
  SmallDenseMap<const TreeEntry *, bool> ScalarsUsedOutsideBlockCache;
  auto AllScalarsUsedOutsideBlock = [&](const TreeEntry *UserTE) {
    auto [It, Inserted] = ScalarsUsedOutsideBlockCache.try_emplace(UserTE);
    if (!Inserted)
      return It->second;
    bool Res = all_of(UserTE->Scalars, isUsedOutsideBlock);
    It->second = Res;
    return Res;
  };
  for (Value *V : VL) {
    if (isConstant(V) || !VisitedValue.insert(V).second)
      continue;
    // Build a list of tree entries where V is used.
    SmallPtrSet<const TreeEntry *, 4> VToTEs;
    SmallVector<const TreeEntry *> GatherNodes(
        ValueToGatherNodes.lookup(V).takeVector());
    if (TransformedToGatherNodes.contains(TE)) {
      auto IsLiveUserGather = [&](TreeEntry *E) {
        return TE != E && TransformedToGatherNodes.contains(E) &&
               E->UserTreeIndex && !E->UserTreeIndex.UserTE->isGather();
      };
      for (TreeEntry *E :
           make_filter_range(getSplitTreeEntries(V), IsLiveUserGather))
        GatherNodes.push_back(E);
      for (TreeEntry *E :
           make_filter_range(getTreeEntries(V), IsLiveUserGather))
        GatherNodes.push_back(E);
    } else if (const TreeEntry *E = getSameValuesTreeEntry(V, TE->Scalars);
               E && !TEUserNeedsEmitFirst &&
               TransformedToGatherNodes.contains(E) && E->UserTreeIndex &&
               E->UserTreeIndex.UserTE == TE->UserTreeIndex.UserTE &&
               !E->UserTreeIndex.UserTE->isGather()) {
      // Regular gathers reuse only perfectly matched transformed nodes of the
      // same user. Gathers, emitted before their user, cannot reuse transformed
      // nodes, which are emitted with the user.
      GatherNodes.push_back(E);
    }
    for (const TreeEntry *TEPtr :
         make_filter_range(GatherNodes, [&](const TreeEntry *TEPtr) {
           return TEPtr != TE && TEPtr->Idx != 0 &&
                  !DeletedNodes.contains(TEPtr);
         })) {
      assert(any_of(TEPtr->Scalars,
                    [&](Value *V) { return GatheredScalars.contains(V); }) &&
             "Must contain at least single gathered value.");
      assert(TEPtr->UserTreeIndex &&
             "Expected only single user of a gather node.");
      if (any_of(TEPtr->CombinedEntriesWithIndices,
                 [&](const auto &P) { return P.first == TE->Idx; }))
        continue;
      const EdgeInfo &UseEI = TEPtr->UserTreeIndex;

      PHINode *UserPHI = (UseEI.UserTE->State != TreeEntry::SplitVectorize &&
                          UseEI.UserTE->hasState())
                             ? dyn_cast<PHINode>(UseEI.UserTE->getMainOp())
                             : nullptr;
      Instruction *InsertPt =
          UserPHI ? UserPHI->getIncomingBlock(UseEI.EdgeIdx)->getTerminator()
                  : &getLastInstructionInBundle(UseEI.UserTE);
      if (TEInsertPt == InsertPt) {
        // Check nodes, which might be emitted first.
        if (TEUserNeedsEmitFirst) {
          if (UseEI.UserTE->State != TreeEntry::Vectorize ||
              (UseEI.UserTE->hasState() &&
               UseEI.UserTE->getOpcode() == Instruction::PHI &&
               !UseEI.UserTE->isAltShuffle()) ||
              !AllScalarsUsedOutsideBlock(UseEI.UserTE))
            continue;
        }

        // If the schedulable insertion point is used in multiple entries - just
        // exit, no known ordering at this point, available only after real
        // scheduling.
        if (!doesNotNeedToBeScheduled(InsertPt) &&
            (TEUseEI.UserTE != UseEI.UserTE || TEUseEI.EdgeIdx < UseEI.EdgeIdx))
          continue;
        // If the users are the PHI nodes with the same incoming blocks - skip.
        if (TEUseEI.UserTE->State == TreeEntry::Vectorize &&
            TEUseEI.UserTE->getOpcode() == Instruction::PHI &&
            UseEI.UserTE->State == TreeEntry::Vectorize &&
            UseEI.UserTE->getOpcode() == Instruction::PHI &&
            TEUseEI.UserTE != UseEI.UserTE)
          continue;
        // If 2 gathers are operands of the same entry (regardless of whether
        // user is PHI or else), compare operands indices, use the earlier one
        // as the base.
        if (TEUseEI.UserTE == UseEI.UserTE && TEUseEI.EdgeIdx < UseEI.EdgeIdx)
          continue;
        // If the user instruction is used for some reason in different
        // vectorized nodes - make it depend on index.
        if (TEUseEI.UserTE != UseEI.UserTE &&
            (TEUseEI.UserTE->Idx < UseEI.UserTE->Idx ||
             HasGatherUser(TEUseEI.UserTE)))
          continue;
        // If the user node is the operand of the other user node - skip.
        if (CheckParentNodes(TEUseEI.UserTE, UseEI.UserTE, UseEI.EdgeIdx))
          continue;
      }

      if (!TEUseEI.UserTE->isGather() && !UserPHI &&
          TEUseEI.UserTE->doesNotNeedToSchedule() !=
              UseEI.UserTE->doesNotNeedToSchedule() &&
          is_contained(UseEI.UserTE->Scalars, TEInsertPt))
        continue;
      // Check if the user node of the TE comes after user node of TEPtr,
      // otherwise TEPtr depends on TE.
      if ((TEInsertBlock != InsertPt->getParent() ||
           TEUseEI.EdgeIdx < UseEI.EdgeIdx || TEUseEI.UserTE != UseEI.UserTE) &&
          (!CheckOrdering(InsertPt) ||
           (UseEI.UserTE->hasCopyableElements() &&
            IsTEInsertPtUsedOutsideBlock() &&
            is_contained(UseEI.UserTE->Scalars, TEInsertPt))))
        continue;
      // The node is reused - exit.
      if (CheckAndUseSameNode(TEPtr))
        break;
      // The parent node is copyable with last inst used outside? And the last
      // inst is the next inst for the lastinst of TEPtr? Exit, if yes, to
      // preserve def-use chain.
      if (CheckNonSchedulableOrdering(UseEI.UserTE, InsertPt))
        continue;
      VToTEs.insert(TEPtr);
    }
    if (ArrayRef<TreeEntry *> VTEs = getSplitTreeEntries(V); !VTEs.empty()) {
      const auto *It = find_if(VTEs, [&](const TreeEntry *MTE) {
        return MTE != TE && MTE != TEUseEI.UserTE &&
               !DeletedNodes.contains(MTE) &&
               !TransformedToGatherNodes.contains(MTE);
      });
      if (It != VTEs.end()) {
        const TreeEntry *VTE = *It;
        if (none_of(TE->CombinedEntriesWithIndices,
                    [&](const auto &P) { return P.first == VTE->Idx; })) {
          Instruction &LastBundleInst = getLastInstructionInBundle(VTE);
          if (&LastBundleInst == TEInsertPt || !CheckOrdering(&LastBundleInst))
            continue;
        }
        // The node is reused - exit.
        if (CheckAndUseSameNode(VTE))
          break;
        VToTEs.insert(VTE);
      }
    }
    if (ArrayRef<TreeEntry *> VTEs = getTreeEntries(V); !VTEs.empty()) {
      const auto *It = find_if(VTEs, [&, MainTE = TE](const TreeEntry *TE) {
        return TE != MainTE && !DeletedNodes.contains(TE) &&
               !TransformedToGatherNodes.contains(TE);
      });
      if (It != VTEs.end()) {
        const TreeEntry *VTE = *It;
        if (ForOrder && VTE->Idx < GatheredLoadsEntriesFirst.value_or(0) &&
            VTEs.size() > 1 && VTE->State != TreeEntry::Vectorize) {
          VTEs = VTEs.drop_front();
          // Iterate through all vectorized nodes.
          const auto *MIt = find_if(VTEs, [](const TreeEntry *MTE) {
            return MTE->State == TreeEntry::Vectorize;
          });
          if (MIt == VTEs.end())
            continue;
          VTE = *MIt;
        }
        if (none_of(TE->CombinedEntriesWithIndices,
                    [&](const auto &P) { return P.first == VTE->Idx; })) {
          Instruction &LastBundleInst = getLastInstructionInBundle(VTE);
          if (&LastBundleInst == TEInsertPt ||
              !CheckOrdering(&LastBundleInst) ||
              CheckNonSchedulableOrdering(VTE, &LastBundleInst))
            continue;
        }
        // The node is reused - exit.
        if (CheckAndUseSameNode(VTE))
          break;
        VToTEs.insert(VTE);
      }
    }
    if (IsReusedNodeFound)
      break;
    if (VToTEs.empty())
      continue;
    if (UsedTEs.empty()) {
      // The first iteration, just insert the list of nodes to vector.
      UsedTEs.push_back(VToTEs);
      UsedValuesEntry.try_emplace(V, 0);
    } else {
      // Need to check if there are any previously used tree nodes which use V.
      // If there are no such nodes, consider that we have another one input
      // vector.
      SmallPtrSet<const TreeEntry *, 4> SavedVToTEs(VToTEs);
      unsigned Idx = 0;
      for (SmallPtrSet<const TreeEntry *, 4> &Set : UsedTEs) {
        // Do we have a non-empty intersection of previously listed tree entries
        // and tree entries using current V?
        set_intersect(VToTEs, Set);
        if (!VToTEs.empty()) {
          // Yes, write the new subset and continue analysis for the next
          // scalar.
          Set.swap(VToTEs);
          break;
        }
        VToTEs = SavedVToTEs;
        ++Idx;
      }
      // No non-empty intersection found - need to add a second set of possible
      // source vectors.
      if (Idx == UsedTEs.size()) {
        // If the number of input vectors is greater than 2 - not a permutation,
        // fallback to the regular gather.
        // TODO: support multiple reshuffled nodes.
        if (UsedTEs.size() == 2)
          continue;
        UsedTEs.push_back(SavedVToTEs);
        Idx = UsedTEs.size() - 1;
      }
      UsedValuesEntry.try_emplace(V, Idx);
    }
  }

  if (UsedTEs.empty()) {
    Entries.clear();
    return std::nullopt;
  }

  unsigned VF = 0;
  if (UsedTEs.size() == 1) {
    // Keep the order to avoid non-determinism.
    SmallVector<const TreeEntry *> FirstEntries(UsedTEs.front().begin(),
                                                UsedTEs.front().end());
    sort(FirstEntries, [](const TreeEntry *TE1, const TreeEntry *TE2) {
      return TE1->Idx < TE2->Idx;
    });
    // Try to find the perfect match in another gather node at first.
    auto *It = find_if(FirstEntries, [=](const TreeEntry *EntryPtr) {
      return (EntryPtr->getVectorFactor() == TE->Scalars.size() &&
              EntryPtr->isSame(TE->Scalars)) ||
             EntryPtr->isSame(VL);
    });
    if (It != FirstEntries.end() &&
        (IsReusedNodeFound || (*It)->getVectorFactor() == VL.size() ||
         ((*It)->getVectorFactor() == TE->Scalars.size() &&
          TE->ReuseShuffleIndices.size() == VL.size() &&
          (*It)->isSame(TE->Scalars)))) {
      Entries.push_back(*It);
      if (IsReusedNodeFound || (*It)->getVectorFactor() == VL.size()) {
        std::iota(std::next(Mask.begin(), MaskBase),
                  std::next(Mask.begin(), MaskBase + VL.size()), 0);
      } else {
        SmallVector<int> CommonMask = TE->getCommonMask();
        copy(CommonMask, Mask.begin());
      }
      // Clear undef scalars.
      for (unsigned I : seq<unsigned>(VL.size()))
        if (isa<PoisonValue>(VL[I]))
          Mask[MaskBase + I] = PoisonMaskElem;
      return TargetTransformInfo::SK_PermuteSingleSrc;
    }
    // No perfect match, just shuffle, so choose the first tree node from the
    // tree.
    Entries.push_back(FirstEntries.front());
    // Update mapping between values and corresponding tree entries.
    for (auto &P : UsedValuesEntry)
      P.second = 0;
    VF = FirstEntries.front()->getVectorFactor();
  } else {
    // Try to find nodes with the same vector factor.
    assert(UsedTEs.size() == 2 && "Expected at max 2 permuted entries.");
    // Keep the order of tree nodes to avoid non-determinism.
    DenseMap<int, const TreeEntry *> VFToTE;
    for (const TreeEntry *TE : UsedTEs.front()) {
      unsigned VF = TE->getVectorFactor();
      auto It = VFToTE.find(VF);
      if (It != VFToTE.end()) {
        if (It->second->Idx > TE->Idx)
          It->getSecond() = TE;
        continue;
      }
      VFToTE.try_emplace(VF, TE);
    }
    // Same, keep the order to avoid non-determinism.
    SmallVector<const TreeEntry *> SecondEntries(UsedTEs.back().begin(),
                                                 UsedTEs.back().end());
    sort(SecondEntries, [](const TreeEntry *TE1, const TreeEntry *TE2) {
      return TE1->Idx < TE2->Idx;
    });
    for (const TreeEntry *TE : SecondEntries) {
      auto It = VFToTE.find(TE->getVectorFactor());
      if (It != VFToTE.end()) {
        VF = It->first;
        Entries.push_back(It->second);
        Entries.push_back(TE);
        break;
      }
    }
    // No 2 source vectors with the same vector factor - just choose 2 with max
    // index.
    if (Entries.empty()) {
      Entries.push_back(*llvm::max_element(
          UsedTEs.front(), [](const TreeEntry *TE1, const TreeEntry *TE2) {
            return TE1->Idx < TE2->Idx;
          }));
      Entries.push_back(SecondEntries.front());
      VF = std::max(Entries.front()->getVectorFactor(),
                    Entries.back()->getVectorFactor());
    } else {
      VF = Entries.front()->getVectorFactor();
    }
    SmallVector<SmallPtrSet<Value *, 8>> ValuesToEntries;
    for (const TreeEntry *E : Entries)
      ValuesToEntries.emplace_back().insert(E->Scalars.begin(),
                                            E->Scalars.end());
    // Update mapping between values and corresponding tree entries.
    for (auto &P : UsedValuesEntry) {
      for (unsigned Idx : seq<unsigned>(ValuesToEntries.size()))
        if (ValuesToEntries[Idx].contains(P.first)) {
          P.second = Idx;
          break;
        }
    }
  }

  bool IsSplatOrUndefs = isSplat(VL) || all_of(VL, IsaPred<UndefValue>);
  // Checks if the 2 PHIs are compatible in terms of high possibility to be
  // vectorized.
  auto AreCompatiblePHIs = [&](Value *V, Value *V1) {
    auto *PHI = cast<PHINode>(V);
    auto *PHI1 = cast<PHINode>(V1);
    // Check that all incoming values are compatible/from same parent (if they
    // are instructions).
    // The incoming values are compatible if they all are constants, or
    // instruction with the same/alternate opcodes from the same basic block.
    for (int I = 0, E = PHI->getNumIncomingValues(); I < E; ++I) {
      Value *In = PHI->getIncomingValue(I);
      Value *In1 = PHI1->getIncomingValue(I);
      if (isConstant(In) && isConstant(In1))
        continue;
      if (!getSameOpcode({In, In1}, *TLI))
        return false;
      if (cast<Instruction>(In)->getParent() !=
          cast<Instruction>(In1)->getParent())
        return false;
    }
    return true;
  };
  // Check if the value can be ignored during analysis for shuffled gathers.
  // We suppose it is better to ignore instruction, which do not form splats,
  // are not vectorized/not extractelements (these instructions will be handled
  // by extractelements processing) or may form vector node in future.
  // Cache results - each V in VL is queried up to 3 times (direct +
  // NeighborMightBeIgnored from both neighbors), and areAllUsersVectorized
  // walks each instruction's user list.
  SmallDenseMap<Value *, bool> MightBeIgnoredCache;
  auto MightBeIgnored = [=, &MightBeIgnoredCache](Value *V) {
    auto [It, Inserted] = MightBeIgnoredCache.try_emplace(V);
    if (!Inserted)
      return It->second;
    auto *I = dyn_cast<Instruction>(V);
    bool Res = I && !IsSplatOrUndefs && !isVectorized(I) &&
               !isVectorLikeInstWithConstOps(I) &&
               !areAllUsersVectorized(I, UserIgnoreList) && isSimple(I);
    It->second = Res;
    return Res;
  };
  // Check that the neighbor instruction may form a full vector node with the
  // current instruction V. It is possible, if they have same/alternate opcode
  // and same parent basic block.
  auto NeighborMightBeIgnored = [&](Value *V, int Idx) {
    Value *V1 = VL[Idx];
    bool UsedInSameVTE = false;
    auto It = UsedValuesEntry.find(V1);
    if (It != UsedValuesEntry.end())
      UsedInSameVTE = It->second == UsedValuesEntry.find(V)->second;
    return V != V1 && MightBeIgnored(V1) && !UsedInSameVTE &&
           getSameOpcode({V, V1}, *TLI) &&
           cast<Instruction>(V)->getParent() ==
               cast<Instruction>(V1)->getParent() &&
           (!isa<PHINode>(V1) || AreCompatiblePHIs(V, V1));
  };
  // Build a shuffle mask for better cost estimation and vector emission.
  SmallBitVector UsedIdxs(Entries.size());
  SmallVector<std::pair<unsigned, int>> EntryLanes;
  for (int I = 0, E = VL.size(); I < E; ++I) {
    Value *V = VL[I];
    auto It = UsedValuesEntry.find(V);
    if (It == UsedValuesEntry.end())
      continue;
    // Do not try to shuffle scalars, if they are constants, or instructions
    // that can be vectorized as a result of the following vector build
    // vectorization.
    if (isConstant(V) || (MightBeIgnored(V) &&
                          ((I > 0 && NeighborMightBeIgnored(V, I - 1)) ||
                           (I != E - 1 && NeighborMightBeIgnored(V, I + 1)))))
      continue;
    unsigned Idx = It->second;
    EntryLanes.emplace_back(Idx, I);
    UsedIdxs.set(Idx);
  }
  // Iterate through all shuffled scalars and select entries, which can be used
  // for final shuffle.
  SmallVector<const TreeEntry *> TempEntries;
  for (unsigned I = 0, Sz = Entries.size(); I < Sz; ++I) {
    if (!UsedIdxs.test(I))
      continue;
    // Fix the entry number for the given scalar. If it is the first entry, set
    // Pair.first to 0, otherwise to 1 (currently select at max 2 nodes).
    // These indices are used when calculating final shuffle mask as the vector
    // offset.
    for (std::pair<unsigned, int> &Pair : EntryLanes)
      if (Pair.first == I)
        Pair.first = TempEntries.size();
    TempEntries.push_back(Entries[I]);
  }
  Entries.swap(TempEntries);
  if (EntryLanes.size() == Entries.size() &&
      !VL.equals(ArrayRef(TE->Scalars)
                     .slice(MaskBase, getNumElems(TE->Scalars.size(), SliceSize,
                                                  Part)))) {
    // We may have here 1 or 2 entries only. If the number of scalars is equal
    // to the number of entries, no need to do the analysis, it is not very
    // profitable. Since VL is not the same as TE->Scalars, it means we already
    // have some shuffles before. Cut off not profitable case.
    Entries.clear();
    return std::nullopt;
  }
  // Build the final mask, check for the identity shuffle, if possible.
  bool IsIdentity = Entries.size() == 1;
  // Pair.first is the offset to the vector, while Pair.second is the index of
  // scalar in the list.
  for (const std::pair<unsigned, int> &Pair : EntryLanes) {
    unsigned Idx = MaskBase + Pair.second;
    Mask[Idx] =
        Pair.first * VF +
        (ForOrder ? std::distance(
                        Entries[Pair.first]->Scalars.begin(),
                        find(Entries[Pair.first]->Scalars, VL[Pair.second]))
                  : Entries[Pair.first]->findLaneForValue(VL[Pair.second]));
    IsIdentity &= Mask[Idx] == Pair.second;
  }
  if (ForOrder || IsIdentity || Entries.empty()) {
    switch (Entries.size()) {
    case 1:
      if (IsIdentity || EntryLanes.size() > 1 || VL.size() <= 2)
        return TargetTransformInfo::SK_PermuteSingleSrc;
      break;
    case 2:
      if (EntryLanes.size() > 2 || VL.size() <= 2)
        return TargetTransformInfo::SK_PermuteTwoSrc;
      break;
    default:
      break;
    }
  } else if (!isa<VectorType>(VL.front()->getType()) &&
             (EntryLanes.size() > Entries.size() || VL.size() <= 2)) {
    // Do the cost estimation if shuffle beneficial than buildvector.
    SmallVector<int> SubMask(std::next(Mask.begin(), MaskBase),
                             std::next(Mask.begin(), MaskBase + VL.size()));
    int MinElement = SubMask.front(), MaxElement = SubMask.front();
    for (int Idx : make_filter_range(
             SubMask, [](int Idx) { return Idx != PoisonMaskElem; })) {
      if (MinElement == PoisonMaskElem || MinElement % VF > Idx % VF)
        MinElement = Idx;
      if (MaxElement == PoisonMaskElem || MaxElement % VF < Idx % VF)
        MaxElement = Idx;
    }
    assert(MaxElement >= 0 && MinElement >= 0 &&
           MaxElement % VF >= MinElement % VF &&
           "Expected at least single element.");
    // If the leading [0, MinIdx) range sits in its own register part(s),
    // skip those whole parts when sizing the destination - everything below
    // the register-aligned floor is unused and never indexed.
    unsigned Offset = 0;
    unsigned MinIdx = MinElement % VF;
    if (MinIdx > 1) {
      unsigned RegFloor = getFloorFullVectorNumberOfElements(
          *TTI, VL.front()->getType(), MinIdx, Opts.slp_revec);
      auto *RegFloorTy = getWidenedType(VL.front()->getType(), RegFloor);
      unsigned RegFloorParts =
          getNumberOfParts(RegFloorTy, VL.front()->getType(), RegFloor);
      if (RegFloorParts > 1)
        Offset = RegFloor;
    }
    unsigned NewVF =
        std::max<unsigned>(VL.size(), (MaxElement % VF) - Offset + 1);
    if (NewVF < VF) {
      for (int &Idx : make_filter_range(
               SubMask, [](int Idx) { return Idx != PoisonMaskElem; }))
        Idx = (Idx % VF) - Offset + (Idx >= static_cast<int>(VF) ? NewVF : 0);
    } else {
      NewVF = VF;
    }

    auto *VecTy =
        cast<VectorType>(getWidenedType(VL.front()->getType(), NewVF));
    auto *MaskVecTy =
        cast<VectorType>(getWidenedType(VL.front()->getType(), SubMask.size()));
    auto GetShuffleCost = [&,
                           &TTI = *TTI](ArrayRef<int> Mask,
                                        ArrayRef<const TreeEntry *> Entries,
                                        VectorType *VecTy) -> InstructionCost {
      if (Entries.size() == 1 && Entries.front()->getInterleaveFactor() > 0 &&
          ShuffleVectorInst::isDeInterleaveMaskOfFactor(
              Mask, Entries.front()->getInterleaveFactor()))
        return TTI::TCC_Free;
      return getShuffleCost(TTI,
                            Entries.size() > 1 ? TTI::SK_PermuteTwoSrc
                                               : TTI::SK_PermuteSingleSrc,
                            VecTy, CostKind, Mask);
    };
    InstructionCost ShuffleCost = GetShuffleCost(SubMask, Entries, VecTy);
    InstructionCost FirstShuffleCost = 0;
    SmallVector<int> FirstMask(SubMask.begin(), SubMask.end());
    if (Entries.size() == 1 || !Entries[0]->isGather()) {
      FirstShuffleCost = ShuffleCost;
    } else {
      // Transform mask to include only first entry.
      APInt DemandedElts = APInt::getAllOnes(SubMask.size());
      bool IsIdentity = true;
      for (auto [I, Idx] : enumerate(FirstMask)) {
        if (Idx >= static_cast<int>(NewVF)) {
          Idx = PoisonMaskElem;
        } else {
          DemandedElts.clearBit(I);
          if (Idx != PoisonMaskElem)
            IsIdentity &= static_cast<int>(I) == Idx;
        }
      }
      if (!IsIdentity)
        FirstShuffleCost = GetShuffleCost(FirstMask, Entries.front(), VecTy);
      FirstShuffleCost +=
          getScalarizationOverhead(*TTI, Opts.slp_revec, VL.front()->getType(),
                                   MaskVecTy, DemandedElts, /*Insert=*/true,
                                   /*Extract=*/false, CostKind);
    }
    InstructionCost SecondShuffleCost = 0;
    SmallVector<int> SecondMask(SubMask.begin(), SubMask.end());
    if (Entries.size() == 1 || !Entries[1]->isGather()) {
      SecondShuffleCost = ShuffleCost;
    } else {
      // Transform mask to include only first entry.
      APInt DemandedElts = APInt::getAllOnes(SubMask.size());
      bool IsIdentity = true;
      for (auto [I, Idx] : enumerate(SecondMask)) {
        if (Idx < static_cast<int>(NewVF) && Idx >= 0) {
          Idx = PoisonMaskElem;
        } else {
          DemandedElts.clearBit(I);
          if (Idx != PoisonMaskElem) {
            Idx -= NewVF;
            IsIdentity &= static_cast<int>(I) == Idx;
          }
        }
      }
      if (!IsIdentity)
        SecondShuffleCost = GetShuffleCost(SecondMask, Entries[1], VecTy);
      SecondShuffleCost +=
          getScalarizationOverhead(*TTI, Opts.slp_revec, VL.front()->getType(),
                                   MaskVecTy, DemandedElts, /*Insert=*/true,
                                   /*Extract=*/false, CostKind);
    }
    APInt DemandedElts = APInt::getAllOnes(SubMask.size());
    for (auto [I, Idx] : enumerate(SubMask))
      if (Idx == PoisonMaskElem)
        DemandedElts.clearBit(I);
    InstructionCost BuildVectorCost =
        getScalarizationOverhead(*TTI, Opts.slp_revec, VL.front()->getType(),
                                 MaskVecTy, DemandedElts, /*Insert=*/true,
                                 /*Extract=*/false, CostKind);
    const TreeEntry *BestEntry = nullptr;
    auto MaskSlice = MutableArrayRef(Mask).slice(MaskBase, VL.size());
    if (FirstShuffleCost < ShuffleCost) {
      for (int &Idx : MaskSlice)
        if (Idx >= static_cast<int>(VF))
          Idx = PoisonMaskElem;
      BestEntry = Entries.front();
      ShuffleCost = FirstShuffleCost;
    }
    if (SecondShuffleCost < ShuffleCost) {
      for (int &Idx : MaskSlice) {
        if (Idx < static_cast<int>(VF))
          Idx = PoisonMaskElem;
        else
          Idx -= VF;
      }
      BestEntry = Entries[1];
      ShuffleCost = SecondShuffleCost;
    }
    if (BuildVectorCost >= ShuffleCost) {
      if (BestEntry) {
        Entries.clear();
        Entries.push_back(BestEntry);
      }
      return Entries.size() > 1 ? TargetTransformInfo::SK_PermuteTwoSrc
                                : TargetTransformInfo::SK_PermuteSingleSrc;
    }
  }
  Entries.clear();
  // Clear the corresponding mask elements.
  std::fill(std::next(Mask.begin(), MaskBase),
            std::next(Mask.begin(), MaskBase + VL.size()), PoisonMaskElem);
  return std::nullopt;
}

SmallVector<std::optional<TargetTransformInfo::ShuffleKind>>
BoUpSLP::isGatherShuffledEntry(
    const TreeEntry *TE, ArrayRef<Value *> VL, SmallVectorImpl<int> &Mask,
    SmallVectorImpl<SmallVector<const TreeEntry *>> &Entries, unsigned NumParts,
    Type *ScalarTy, bool ForOrder) {
  assert(NumParts > 0 && NumParts < VL.size() &&
         "Expected positive number of registers.");
  Entries.clear();
  // No need to check for the topmost gather node.
  if (TE == &getRootNode() &&
      (!GatheredLoadsEntriesFirst.has_value() ||
       none_of(ArrayRef(VectorizableTree).drop_front(),
               [](const std::unique_ptr<TreeEntry> &TE) {
                 return !TE->isGather();
               })))
    return {};
  Mask.assign(VL.size(), PoisonMaskElem);
  assert((TE->UserTreeIndex || TE == &getRootNode()) &&
         "Expected only single user of the gather node.");
  unsigned PWSz =
      getFullVectorNumberOfElements(*TTI, ScalarTy, VL.size(), Opts.slp_revec);
  if (TE->UserTreeIndex && TE->UserTreeIndex.UserTE->isGather() &&
      TE->UserTreeIndex.EdgeIdx == UINT_MAX &&
      (TE->Idx == 0 ||
       (TE->hasState() && TE->getOpcode() == Instruction::ExtractElement) ||
       isSplat(TE->Scalars) ||
       (TE->hasState() &&
        getSameValuesTreeEntry(TE->getMainOp(), TE->Scalars))))
    return {};
  unsigned SliceSize = getPartNumElems(PWSz, NumParts);
  SmallVector<std::optional<TTI::ShuffleKind>> Res;
  for (unsigned Part : seq<unsigned>(NumParts)) {
    if (Part * SliceSize >= VL.size())
      break;
    ArrayRef<Value *> SubVL =
        VL.slice(Part * SliceSize, getNumElems(VL.size(), SliceSize, Part));
    SmallVectorImpl<const TreeEntry *> &SubEntries = Entries.emplace_back();
    std::optional<TTI::ShuffleKind> SubRes =
        isGatherShuffledSingleRegisterEntry(TE, SubVL, Mask, SubEntries, Part,
                                            ForOrder, SliceSize);
    if (!SubRes)
      SubEntries.clear();
    Res.push_back(SubRes);
    if (SubEntries.size() == 1 && *SubRes == TTI::SK_PermuteSingleSrc &&
        SubEntries.front()->getVectorFactor() == VL.size() &&
        (SubEntries.front()->isSame(TE->Scalars) ||
         SubEntries.front()->isSame(VL))) {
      SmallVector<const TreeEntry *> LocalSubEntries;
      LocalSubEntries.swap(SubEntries);
      Entries.clear();
      Res.clear();
      std::iota(Mask.begin(), Mask.end(), 0);
      // Clear undef scalars.
      for (int I = 0, Sz = VL.size(); I < Sz; ++I)
        if (isa<PoisonValue>(VL[I]))
          Mask[I] = PoisonMaskElem;
      Entries.emplace_back(1, LocalSubEntries.front());
      Res.push_back(TargetTransformInfo::SK_PermuteSingleSrc);
      return Res;
    }
  }
  if (all_of(Res,
             [](const std::optional<TTI::ShuffleKind> &SK) { return !SK; })) {
    Entries.clear();
    return {};
  }
  return Res;
}

InstructionCost BoUpSLP::getGatherCost(ArrayRef<Value *> VL, bool ForPoisonSrc,
                                       Type *ScalarTy) const {
  const unsigned VF = VL.size();
  auto *VecTy = getWidenedType(ScalarTy, VF);
  // Find the cost of inserting/extracting values from the vector.
  // Check if the same elements are inserted several times and count them as
  // shuffle candidates.
  APInt DemandedElements = APInt::getZero(VF);
  InstructionCost Cost;
  auto EstimateInsertCost = [&](unsigned I, Value *V) {
    DemandedElements.setBit(I);
    if (V->getType() != ScalarTy)
      Cost += TTI->getCastInstrCost(Instruction::Trunc, ScalarTy, V->getType(),
                                    TTI::CastContextHint::None, CostKind);
  };
  SmallVector<int> ConstantShuffleMask(VF, PoisonMaskElem);
  std::iota(ConstantShuffleMask.begin(), ConstantShuffleMask.end(), 0);
  // No need to shuffle duplicates for constants.
  for (auto [I, V] : make_filter_range(enumerate(VL), [&](const auto &P) {
         return !(ForPoisonSrc && isConstant(P.value())) &&
                !isa<UndefValue>(P.value());
       })) {
    if (isConstant(V)) {
      ConstantShuffleMask[I] = I + VF;
      continue;
    }
    EstimateInsertCost(I, V);
  }
  // FIXME: add a cost for constant vector materialization.
  bool IsAnyNonUndefConst =
      any_of(VL, [](Value *V) { return !isa<UndefValue>(V) && isConstant(V); });
  // 1. Shuffle input source vector and constant vector.
  if (!ForPoisonSrc && IsAnyNonUndefConst) {
    Cost +=
        getShuffleCost(*TTI, TargetTransformInfo::SK_PermuteTwoSrc,
                       cast<VectorType>(VecTy), CostKind, ConstantShuffleMask);
  }

  // 2. Insert unique non-constants.
  if (!DemandedElements.isZero())
    Cost += getScalarizationOverhead(*TTI, Opts.slp_revec, ScalarTy,
                                     cast<VectorType>(VecTy), DemandedElements,
                                     /*Insert=*/true,
                                     /*Extract=*/false, CostKind,
                                     ForPoisonSrc && !IsAnyNonUndefConst, VL);
  return Cost;
}

Instruction &BoUpSLP::getLastInstructionInBundle(const TreeEntry *E) {
  auto It = EntryToLastInstruction.find(E);
  if (It != EntryToLastInstruction.end())
    return *cast<Instruction>(It->second);
  Instruction *Res = nullptr;
  // Get the basic block this bundle is in. All instructions in the bundle
  // should be in this block (except for extractelement-like instructions with
  // constant indices or gathered loads or copyables).
  Instruction *Front;
  unsigned Opcode;
  if (E->hasState()) {
    Front = E->getMainOp();
    Opcode = E->getOpcode();
  } else {
    Front = cast<Instruction>(*find_if(E->Scalars, IsaPred<Instruction>));
    Opcode = Front->getOpcode();
  }
  auto *BB = Front->getParent();
  assert(
      ((GatheredLoadsEntriesFirst.has_value() && Opcode == Instruction::Load &&
        E->isGather() && E->Idx < *GatheredLoadsEntriesFirst) ||
       E->State == TreeEntry::SplitVectorize || E->hasCopyableElements() ||
       all_of(E->Scalars,
              [=](Value *V) -> bool {
                if (Opcode == Instruction::GetElementPtr &&
                    !isa<GetElementPtrInst>(V))
                  return true;
                auto *I = dyn_cast<Instruction>(V);
                return !I || !E->getMatchingMainOpOrAltOp(I) ||
                       I->getParent() == BB || isVectorLikeInstWithConstOps(I);
              })) &&
      "Expected gathered loads or GEPs or instructions from same basic "
      "block.");

  auto FindLastInst = [&]() {
    Instruction *LastInst = Front;
    for (Instruction *I : make_isa_range<Instruction>(E->Scalars)) {
      if (E->isCopyableElement(I))
        continue;
      if (LastInst->getParent() == I->getParent()) {
        if (LastInst->comesBefore(I))
          LastInst = I;
        continue;
      }
      assert(((Opcode == Instruction::GetElementPtr &&
               !isa<GetElementPtrInst>(I)) ||
              E->State == TreeEntry::SplitVectorize ||
              (isVectorLikeInstWithConstOps(LastInst) &&
               isVectorLikeInstWithConstOps(I)) ||
              (GatheredLoadsEntriesFirst.has_value() &&
               Opcode == Instruction::Load && E->isGather() &&
               E->Idx < *GatheredLoadsEntriesFirst)) &&
             "Expected vector-like or non-GEP in GEP node insts only.");
      if (!DT->isReachableFromEntry(LastInst->getParent())) {
        LastInst = I;
        continue;
      }
      if (!DT->isReachableFromEntry(I->getParent()))
        continue;
      auto *NodeA = DT->getNode(LastInst->getParent());
      auto *NodeB = DT->getNode(I->getParent());
      assert(NodeA && "Should only process reachable instructions");
      assert(NodeB && "Should only process reachable instructions");
      assert((NodeA == NodeB) ==
                 (NodeA->getDFSNumIn() == NodeB->getDFSNumIn()) &&
             "Different nodes should have different DFS numbers");
      if (NodeA->getDFSNumIn() < NodeB->getDFSNumIn())
        LastInst = I;
    }
    BB = LastInst->getParent();
    return LastInst;
  };

  auto FindFirstInst = [&]() {
    Instruction *FirstInst = Front;
    for (Instruction *I : make_isa_range<Instruction>(E->Scalars)) {
      if (E->isCopyableElement(I))
        continue;
      if (FirstInst->getParent() == I->getParent()) {
        if (I->comesBefore(FirstInst))
          FirstInst = I;
        continue;
      }
      assert(((Opcode == Instruction::GetElementPtr &&
               !isa<GetElementPtrInst>(I)) ||
              (isVectorLikeInstWithConstOps(FirstInst) &&
               isVectorLikeInstWithConstOps(I))) &&
             "Expected vector-like or non-GEP in GEP node insts only.");
      if (!DT->isReachableFromEntry(FirstInst->getParent())) {
        FirstInst = I;
        continue;
      }
      if (!DT->isReachableFromEntry(I->getParent()))
        continue;
      auto *NodeA = DT->getNode(FirstInst->getParent());
      auto *NodeB = DT->getNode(I->getParent());
      assert(NodeA && "Should only process reachable instructions");
      assert(NodeB && "Should only process reachable instructions");
      assert((NodeA == NodeB) ==
                 (NodeA->getDFSNumIn() == NodeB->getDFSNumIn()) &&
             "Different nodes should have different DFS numbers");
      if (NodeA->getDFSNumIn() > NodeB->getDFSNumIn())
        FirstInst = I;
    }
    return FirstInst;
  };

  if (E->State == TreeEntry::SplitVectorize) {
    Res = FindLastInst();
    if (ArrayRef<TreeEntry *> Entries = getTreeEntries(Res); !Entries.empty()) {
      for (auto *E : Entries) {
        auto *I = dyn_cast_if_present<Instruction>(E->VectorizedValue);
        if (!I)
          I = &getLastInstructionInBundle(E);
        if (Res->getParent() == I->getParent() && Res->comesBefore(I))
          Res = I;
      }
    }
    EntryToLastInstruction.try_emplace(E, Res);
    return *Res;
  }

  // Set insertpoint for gathered loads to the very first load.
  if (GatheredLoadsEntriesFirst.has_value() &&
      E->Idx >= *GatheredLoadsEntriesFirst && !E->isGather() &&
      Opcode == Instruction::Load) {
    Res = FindFirstInst();
    EntryToLastInstruction.try_emplace(E, Res);
    return *Res;
  }

  // Set the insert point to the beginning of the basic block if the entry
  // should not be scheduled.
  auto FindScheduleBundle = [&](const TreeEntry *E) -> const ScheduleBundle * {
    if (E->isGather())
      return nullptr;
    // Found previously that the instruction do not need to be scheduled.
    const auto *It = BlocksSchedules.find(BB);
    if (It == BlocksSchedules.end())
      return nullptr;
    for (Instruction *I : make_isa_range<Instruction>(E->Scalars)) {
      if (isa<PHINode>(I) ||
          (!E->isCopyableElement(I) && doesNotNeedToBeScheduled(I)))
        continue;
      ArrayRef<ScheduleBundle *> Bundles = It->second->getScheduleBundles(I);
      if (Bundles.empty())
        continue;
      const auto *It = find_if(
          Bundles, [&](ScheduleBundle *B) { return B->getTreeEntry() == E; });
      if (It != Bundles.end())
        return *It;
    }
    return nullptr;
  };
  const ScheduleBundle *Bundle = FindScheduleBundle(E);
  if (!E->isGather() && !Bundle) {
    if ((Opcode == Instruction::GetElementPtr &&
         any_of(E->Scalars,
                [](Value *V) {
                  return !isa<GetElementPtrInst>(V) && isa<Instruction>(V);
                })) ||
        (all_of(E->Scalars,
                [&](Value *V) {
                  return isa<PoisonValue>(V) ||
                         (E->Idx == 0 &&
                          isa<InsertElementInst, InsertValueInst>(V)) ||
                         E->isCopyableElement(V) ||
                         (!isVectorLikeInstWithConstOps(V) &&
                          isUsedOutsideBlock(V));
                }) &&
         (!E->doesNotNeedToSchedule() ||
          any_of(make_isa_range<Instruction>(E->Scalars),
                 [&](Instruction *I) {
                   if (E->hasCopyableElements() && E->isCopyableElement(I))
                     return false;
                   return !areAllOperandsNonInsts(I);
                 }) ||
          none_of(make_isa_range<Instruction>(E->Scalars), [&](Instruction *I) {
            if (E->hasCopyableElements() && E->isCopyableElement(I))
              return false;
            return MustGather.contains(I);
          }))))
      Res = FindLastInst();
    else
      Res = FindFirstInst();
    EntryToLastInstruction.try_emplace(E, Res);
    return *Res;
  }

  // Find the last instruction. The common case should be that BB has been
  // scheduled, and the last instruction is VL.back(). So we start with
  // VL.back() and iterate over schedule data until we reach the end of the
  // bundle. The end of the bundle is marked by null ScheduleData.
  if (Bundle) {
    assert(!E->isGather() && "Gathered instructions should not be scheduled");
    Res = Bundle->getBundle().back()->getInst();
    EntryToLastInstruction.try_emplace(E, Res);
    return *Res;
  }

  // LastInst can still be null at this point if there's either not an entry
  // for BB in BlocksSchedules or there's no ScheduleData available for
  // VL.back(). This can be the case if buildTreeRec aborts for various
  // reasons (e.g., the maximum recursion depth is reached, the maximum region
  // size is reached, etc.). ScheduleData is initialized in the scheduling
  // "dry-run".
  //
  // If this happens, we can still find the last instruction by brute force. We
  // iterate forwards from Front (inclusive) until we either see all
  // instructions in the bundle or reach the end of the block. If Front is the
  // last instruction in program order, LastInst will be set to Front, and we
  // will visit all the remaining instructions in the block.
  //
  // One of the reasons we exit early from buildTreeRec is to place an upper
  // bound on compile-time. Thus, taking an additional compile-time hit here is
  // not ideal. However, this should be exceedingly rare since it requires that
  // we both exit early from buildTreeRec and that the bundle be out-of-order
  // (causing us to iterate all the way to the end of the block).
  if (!Res)
    Res = FindLastInst();
  assert(Res && "Failed to find last instruction in bundle");
  EntryToLastInstruction.try_emplace(E, Res);
  return *Res;
}

void BoUpSLP::setInsertPointAfterBundle(const TreeEntry *E) {
  auto *Front = E->getMainOp();
  Instruction *LastInst = &getLastInstructionInBundle(E);
  // Struct-call extractvalue entries may have scalars in different basic
  // blocks. The vector extractvalue depends only on the vectorized call, so
  // use the call bundle to set the insert point and dominate all uses.
  const bool UseCallBundleInsertPoint =
      E->getOpcode() == Instruction::ExtractValue &&
      !E->StructEVIndices.empty() &&
      any_of(E->Scalars, [BB = Front->getParent()](Value *V) {
        return cast<Instruction>(V)->getParent() != BB;
      });
  if (UseCallBundleInsertPoint)
    LastInst = &getLastInstructionInBundle(getOperandEntry(E, 0));
  assert(LastInst && "Failed to find last instruction in bundle");
  BasicBlock::iterator LastInstIt = LastInst->getIterator();
  // If the instruction is PHI, set the insert point after all the PHIs.
  bool IsPHI = isa<PHINode>(LastInst);
  if (IsPHI) {
    LastInstIt = LastInst->getParent()->getFirstNonPHIIt();
    if (LastInstIt != LastInst->getParent()->end() &&
        LastInstIt->getParent()->isLandingPad())
      LastInstIt = std::next(LastInstIt);
  }
  if (IsPHI ||
      (!E->isGather() && E->State != TreeEntry::SplitVectorize &&
       !UseCallBundleInsertPoint &&
       (E->doesNotNeedToSchedule() ||
        (E->hasCopyableElements() && !E->isCopyableElement(LastInst) &&
         isUsedOutsideBlock(LastInst)))) ||
      (GatheredLoadsEntriesFirst.has_value() &&
       E->Idx >= *GatheredLoadsEntriesFirst && !E->isGather() &&
       E->getOpcode() == Instruction::Load)) {
    Builder.SetInsertPoint(LastInstIt);
  } else {
    // Set the insertion point after the last instruction in the bundle. Set the
    // debug location to Front.
    Builder.SetInsertPoint(LastInst->getNextNode()->getIterator());
    if (Instruction *Res = LastInstructionToPos.lookup(LastInst)) {
      Builder.SetInsertPoint(Res->getIterator());
    } else {
      Res = Builder.CreateAlignedLoad(Builder.getPtrTy(),
                                      PoisonValue::get(Builder.getPtrTy()),
                                      MaybeAlign());
      Builder.SetInsertPoint(Res->getIterator());
      eraseInstruction(Res);
      if (E->State != TreeEntry::SplitVectorize)
        LastInstructionToPos.try_emplace(LastInst, Res);
    }
  }
  Builder.SetCurrentDebugLocation(Front->getDebugLoc());
}

Value *BoUpSLP::gather(
    ArrayRef<Value *> VL, Value *Root, Type *ScalarTy,
    function_ref<Value *(Value *, Value *, ArrayRef<int>)> CreateShuffle) {
  // List of instructions/lanes from current block and/or the blocks which are
  // part of the current loop. These instructions will be inserted at the end to
  // make it possible to optimize loops and hoist invariant instructions out of
  // the loops body with better chances for success.
  SmallVector<std::pair<Value *, unsigned>, 4> PostponedInsts;
  SmallSet<int, 4> PostponedIndices;
  Loop *L = LI->getLoopFor(Builder.GetInsertBlock());
  auto &&CheckPredecessor = [](BasicBlock *InstBB, BasicBlock *InsertBB) {
    SmallPtrSet<BasicBlock *, 4> Visited;
    while (InsertBB && InsertBB != InstBB && Visited.insert(InsertBB).second)
      InsertBB = InsertBB->getSinglePredecessor();
    return InsertBB && InsertBB == InstBB;
  };
  for (int I = 0, E = VL.size(); I < E; ++I) {
    if (auto *Inst = dyn_cast<Instruction>(VL[I]))
      if ((CheckPredecessor(Inst->getParent(), Builder.GetInsertBlock()) ||
           isVectorized(Inst) ||
           (L && (!Root || L->isLoopInvariant(Root)) && L->contains(Inst))) &&
          PostponedIndices.insert(I).second)
        PostponedInsts.emplace_back(Inst, I);
  }

  auto &&CreateInsertElement = [this](Value *Vec, Value *V, unsigned Pos,
                                      Type *Ty) {
    Value *Scalar = V;
    // Drop NUW from trunc to avoid incorrect codegen.
    Value *Trunced;
    if (match(Scalar, m_NUWTrunc(m_Value(Trunced))))
      cast<TruncInst>(Scalar)->setHasNoUnsignedWrap(/*B=*/false);
    if (Scalar->getType() != Ty) {
      assert(Scalar->getType()->isIntOrIntVectorTy() &&
             Ty->isIntOrIntVectorTy() && "Expected integer types only.");
      Value *V = Scalar;
      if (auto *CI = dyn_cast<CastInst>(Scalar);
          isa_and_nonnull<SExtInst, ZExtInst>(CI)) {
        Value *Op = CI->getOperand(0);
        if (auto *IOp = dyn_cast<Instruction>(Op);
            !IOp || !(isDeleted(IOp) || isVectorized(IOp)))
          V = Op;
      }
      Scalar = Builder.CreateIntCast(
          V, Ty, !isKnownNonNegative(Scalar, SimplifyQuery(*DL)));
    }

    Instruction *InsElt;
    if (auto *VecTy = dyn_cast<FixedVectorType>(Scalar->getType())) {
      assert(Opts.slp_revec && "FixedVectorType is not expected.");
      Vec =
          createInsertVector(Builder, Vec, Scalar, Pos * getNumElements(VecTy));
      auto *II = dyn_cast<Instruction>(Vec);
      if (!II)
        return Vec;
      InsElt = II;
    } else {
      Vec = Builder.CreateInsertElement(Vec, Scalar, Pos);
      InsElt = dyn_cast<InsertElementInst>(Vec);
      if (!InsElt)
        return Vec;
    }
    GatherShuffleExtractSeq.insert(InsElt);
    CSEBlocks.insert(InsElt->getParent());
    // Add to our 'need-to-extract' list.
    if (isa<Instruction>(V)) {
      ArrayRef<TreeEntry *> Entries = getTreeEntries(V);
      const auto *It = find_if(Entries, [&](const TreeEntry *E) {
        return !TransformedToGatherNodes.contains(E) &&
               !DeletedNodes.contains(E);
      });
      if (It != Entries.end()) {
        // Find which lane we need to extract.
        User *UserOp = nullptr;
        if (Scalar != V) {
          if (auto *SI = dyn_cast<Instruction>(Scalar))
            UserOp = SI;
        } else {
          if (V->getType()->isVectorTy()) {
            if (auto *SV = dyn_cast<ShuffleVectorInst>(InsElt);
                SV && SV->getOperand(0) != V && SV->getOperand(1) != V) {
              // Find shufflevector, caused by resize.
              auto FindOperand = [](Value *Vec, Value *V) -> Instruction * {
                if (auto *SV = dyn_cast<ShuffleVectorInst>(Vec)) {
                  if (SV->getOperand(0) == V)
                    return SV;
                  if (SV->getOperand(1) == V)
                    return SV;
                }
                return nullptr;
              };
              InsElt = nullptr;
              if (Instruction *User = FindOperand(SV->getOperand(0), V))
                InsElt = User;
              else if (Instruction *User = FindOperand(SV->getOperand(1), V))
                InsElt = User;
              assert(InsElt &&
                     "Failed to find shufflevector, caused by resize.");
            } else if (Opts.slp_revec && isa<ShuffleVectorInst>(InsElt)) {
              // ReVec gather used V directly as a shufflevector operand.
              // Register a nullptr-User external use so all remaining
              // in-IR uses of V get rewritten via replaceAllUsesWith,
              // and track V in ExternalUsesWithNonUsers to match the
              // bookkeeping done by buildExternalUses.
              unsigned FoundLane = (*It)->findLaneForValue(V);
              ExternalUses.emplace_back(V, nullptr, **It, FoundLane);
              ExternalUsesWithNonUsers.insert(V);
            }
          }
          UserOp = InsElt;
        }
        if (UserOp) {
          unsigned FoundLane = (*It)->findLaneForValue(V);
          ExternalUses.emplace_back(V, UserOp, **It, FoundLane);
        }
      }
    }
    return Vec;
  };
  auto *VecTy = getWidenedType(ScalarTy, VL.size());
  Value *Vec = PoisonValue::get(VecTy);
  SmallVector<int> NonConsts;
  SmallVector<int> Mask(VL.size());
  std::iota(Mask.begin(), Mask.end(), 0);
  Value *OriginalRoot = Root;
  if (auto *SV = dyn_cast_if_present<ShuffleVectorInst>(Root);
      SV && isa<PoisonValue>(SV->getOperand(1)) &&
      SV->getOperand(0)->getType() == VecTy) {
    Root = SV->getOperand(0);
    Mask.assign(SV->getShuffleMask().begin(), SV->getShuffleMask().end());
  }
  // Insert constant values at first.
  for (int I = 0, E = VL.size(); I < E; ++I) {
    if (PostponedIndices.contains(I))
      continue;
    if (!isConstant(VL[I])) {
      NonConsts.push_back(I);
      continue;
    }
    if (isa<PoisonValue>(VL[I]))
      continue;
    Vec = CreateInsertElement(Vec, VL[I], I, ScalarTy);
    Mask[I] = I + E;
  }
  if (Root) {
    if (isa<PoisonValue>(Vec)) {
      Vec = OriginalRoot;
    } else {
      Vec = CreateShuffle(Root, Vec, Mask);
      if (auto *OI = dyn_cast<Instruction>(OriginalRoot);
          OI && OI->use_empty() &&
          none_of(VectorizableTree, [&](const std::unique_ptr<TreeEntry> &TE) {
            return TE->VectorizedValue == OI;
          }))
        eraseInstruction(OI);
    }
  }
  // Insert non-constant values.
  for (int I : NonConsts)
    Vec = CreateInsertElement(Vec, VL[I], I, ScalarTy);
  // Append instructions, which are/may be part of the loop, in the end to make
  // it possible to hoist non-loop-based instructions.
  for (const std::pair<Value *, unsigned> &Pair : PostponedInsts)
    Vec = CreateInsertElement(Vec, Pair.first, Pair.second, ScalarTy);

  return Vec;
}

/// Merges shuffle masks and emits final shuffle instruction, if required. It
/// supports shuffling of 2 input vectors. It implements lazy shuffles emission,
/// when the actual shuffle instruction is generated only if this is actually
/// required. Otherwise, the shuffle instruction emission is delayed till the
/// end of the process, to reduce the number of emitted instructions and further
/// analysis/transformations.
/// The class also will look through the previously emitted shuffle instructions
/// and properly mark indices in mask as undef.
/// For example, given the code
/// \code
/// %s1 = shufflevector <2 x ty> %0, poison, <1, 0>
/// %s2 = shufflevector <2 x ty> %1, poison, <1, 0>
/// \endcode
/// and if need to emit shuffle of %s1 and %s2 with mask <1, 0, 3, 2>, it will
/// look through %s1 and %s2 and emit
/// \code
/// %res = shufflevector <2 x ty> %0, %1, <0, 1, 2, 3>
/// \endcode
/// instead.
/// If 2 operands are of different size, the smallest one will be resized and
/// the mask recalculated properly.
/// For example, given the code
/// \code
/// %s1 = shufflevector <2 x ty> %0, poison, <1, 0, 1, 0>
/// %s2 = shufflevector <2 x ty> %1, poison, <1, 0, 1, 0>
/// \endcode
/// and if need to emit shuffle of %s1 and %s2 with mask <1, 0, 5, 4>, it will
/// look through %s1 and %s2 and emit
/// \code
/// %res = shufflevector <2 x ty> %0, %1, <0, 1, 2, 3>
/// \endcode
/// instead.
class BoUpSLP::ShuffleInstructionBuilder final : public BaseShuffleAnalysis {
  bool IsFinalized = false;
  /// Combined mask for all applied operands and masks. It is built during
  /// analysis and actual emission of shuffle vector instructions.
  SmallVector<int> CommonMask;
  /// List of operands for the shuffle vector instruction. It hold at max 2
  /// operands, if the 3rd is going to be added, the first 2 are combined into
  /// shuffle with \p CommonMask mask, the first operand sets to be the
  /// resulting shuffle and the second operand sets to be the newly added
  /// operand. The \p CommonMask is transformed in the proper way after that.
  SmallVector<Value *, 2> InVectors;
  IRBuilderBase &Builder;
  BoUpSLP &R;

  class ShuffleIRBuilder {
    IRBuilderBase &Builder;
    /// Holds all of the instructions that we gathered.
    SetVector<Instruction *> &GatherShuffleExtractSeq;
    /// A list of blocks that we are going to CSE.
    DenseSet<BasicBlock *> &CSEBlocks;
    /// Data layout.
    const DataLayout &DL;

  public:
    ShuffleIRBuilder(IRBuilderBase &Builder,
                     SetVector<Instruction *> &GatherShuffleExtractSeq,
                     DenseSet<BasicBlock *> &CSEBlocks, const DataLayout &DL)
        : Builder(Builder), GatherShuffleExtractSeq(GatherShuffleExtractSeq),
          CSEBlocks(CSEBlocks), DL(DL) {}
    ~ShuffleIRBuilder() = default;
    /// Creates shufflevector for the 2 operands with the given mask.
    Value *createShuffleVector(Value *V1, Value *V2, ArrayRef<int> Mask) {
      if (V1->getType() != V2->getType()) {
        assert(V1->getType()->isIntOrIntVectorTy() &&
               V1->getType()->isIntOrIntVectorTy() &&
               "Expected integer vector types only.");
        if (V1->getType() != V2->getType()) {
          if (cast<VectorType>(V2->getType())
                  ->getElementType()
                  ->getIntegerBitWidth() < cast<VectorType>(V1->getType())
                                               ->getElementType()
                                               ->getIntegerBitWidth())
            V2 = Builder.CreateIntCast(
                V2, V1->getType(), !isKnownNonNegative(V2, SimplifyQuery(DL)));
          else
            V1 = Builder.CreateIntCast(
                V1, V2->getType(), !isKnownNonNegative(V1, SimplifyQuery(DL)));
        }
      }
      Value *Vec = Builder.CreateShuffleVector(V1, V2, Mask);
      if (auto *I = dyn_cast<Instruction>(Vec)) {
        GatherShuffleExtractSeq.insert(I);
        CSEBlocks.insert(I->getParent());
      }
      return Vec;
    }
    /// Creates permutation of the single vector operand with the given mask, if
    /// it is not identity mask.
    Value *createShuffleVector(Value *V1, ArrayRef<int> Mask) {
      if (Mask.empty())
        return V1;
      unsigned VF = Mask.size();
      unsigned LocalVF = cast<FixedVectorType>(V1->getType())->getNumElements();
      if (VF == LocalVF && ShuffleVectorInst::isIdentityMask(Mask, VF))
        return V1;
      Value *Vec = Builder.CreateShuffleVector(V1, Mask);
      if (auto *I = dyn_cast<Instruction>(Vec)) {
        GatherShuffleExtractSeq.insert(I);
        CSEBlocks.insert(I->getParent());
      }
      return Vec;
    }
    Value *createIdentity(Value *V) { return V; }
    Value *createPoison(Type *Ty, unsigned VF) {
      return PoisonValue::get(getWidenedType(Ty, VF));
    }
    /// Resizes 2 input vector to match the sizes, if the they are not equal
    /// yet. The smallest vector is resized to the size of the larger vector.
    void resizeToMatch(Value *&V1, Value *&V2) {
      if (V1->getType() == V2->getType())
        return;
      int V1VF = cast<FixedVectorType>(V1->getType())->getNumElements();
      int V2VF = cast<FixedVectorType>(V2->getType())->getNumElements();
      int VF = std::max(V1VF, V2VF);
      int MinVF = std::min(V1VF, V2VF);
      SmallVector<int> IdentityMask(VF, PoisonMaskElem);
      std::iota(IdentityMask.begin(), std::next(IdentityMask.begin(), MinVF),
                0);
      Value *&Op = MinVF == V1VF ? V1 : V2;
      Op = Builder.CreateShuffleVector(Op, IdentityMask);
      if (auto *I = dyn_cast<Instruction>(Op)) {
        GatherShuffleExtractSeq.insert(I);
        CSEBlocks.insert(I->getParent());
      }
      if (MinVF == V1VF)
        V1 = Op;
      else
        V2 = Op;
    }
  };

  /// Smart shuffle instruction emission, walks through shuffles trees and
  /// tries to find the best matching vector for the actual shuffle
  /// instruction.
  Value *createShuffle(Value *V1, Value *V2, ArrayRef<int> Mask) {
    assert(V1 && "Expected at least one vector value.");
    ShuffleIRBuilder ShuffleBuilder(Builder, R.GatherShuffleExtractSeq,
                                    R.CSEBlocks, *R.DL);
    return BaseShuffleAnalysis::createShuffle<Value *>(
        V1, V2, Mask, ShuffleBuilder, ScalarTy, R.Opts.slp_revec);
  }

  /// Cast value \p V to the vector type with the same number of elements, but
  /// the base type \p ScalarTy.
  Value *castToScalarTyElem(Value *V,
                            std::optional<bool> IsSigned = std::nullopt) {
    auto *VecTy = cast<VectorType>(V->getType());
    assert(getNumElements(VecTy) % getNumElements(ScalarTy) == 0);
    if (VecTy->getElementType() == ScalarTy->getScalarType())
      return V;
    return Builder.CreateIntCast(
        V, VectorType::get(ScalarTy->getScalarType(), VecTy->getElementCount()),
        IsSigned.value_or(!isKnownNonNegative(V, SimplifyQuery(*R.DL))));
  }

  Value *getVectorizedValue(const TreeEntry &E) {
    Value *Vec = E.VectorizedValue;
    if (!Vec->getType()->isIntOrIntVectorTy())
      return Vec;
    return castToScalarTyElem(Vec, any_of(E.Scalars, [&](Value *V) {
                                return !isa<PoisonValue>(V) &&
                                       !isKnownNonNegative(
                                           V, SimplifyQuery(*R.DL));
                              }));
  }

public:
  ShuffleInstructionBuilder(Type *ScalarTy, IRBuilderBase &Builder, BoUpSLP &R)
      : BaseShuffleAnalysis(ScalarTy), Builder(Builder), R(R) {}

  /// Adjusts extractelements after reusing them.
  Value *adjustExtracts(const TreeEntry *E, MutableArrayRef<int> Mask,
                        ArrayRef<std::optional<TTI::ShuffleKind>> ShuffleKinds,
                        unsigned NumParts, bool &UseVecBaseAsInput) {
    UseVecBaseAsInput = false;
    SmallPtrSet<Value *, 4> UniqueBases;
    Value *VecBase = nullptr;
    SmallVector<Value *> VL(E->Scalars.begin(), E->Scalars.end());
    if (!E->ReorderIndices.empty()) {
      SmallVector<int> ReorderMask(E->ReorderIndices.begin(),
                                   E->ReorderIndices.end());
      reorderScalars(VL, ReorderMask);
    }
    for (int I = 0, Sz = Mask.size(); I < Sz; ++I) {
      int Idx = Mask[I];
      if (Idx == PoisonMaskElem)
        continue;
      auto *EI = cast<ExtractElementInst>(VL[I]);
      VecBase = EI->getVectorOperand();
      if (ArrayRef<TreeEntry *> TEs = R.getTreeEntries(VecBase); !TEs.empty())
        VecBase = TEs.front()->VectorizedValue;
      assert(VecBase && "Expected vectorized value.");
      UniqueBases.insert(VecBase);
      // If the only one use is vectorized - can delete the extractelement
      // itself.
      if (!EI->hasOneUse() || R.ExternalUsesAsOriginalScalar.contains(EI) ||
          (E->UserTreeIndex && E->UserTreeIndex.EdgeIdx == UINT_MAX &&
           !R.isVectorized(EI) &&
           count_if(E->Scalars, [&](Value *V) { return V == EI; }) !=
               count_if(E->UserTreeIndex.UserTE->Scalars,
                        [&](Value *V) { return V == EI; })) ||
          (NumParts != 1 && count(VL, EI) > 1) ||
          any_of(EI->users(), [&](User *U) {
            ArrayRef<TreeEntry *> UTEs = R.getTreeEntries(U);
            return UTEs.empty() || UTEs.size() > 1 ||
                   any_of(UTEs,
                          [&](const TreeEntry *TE) {
                            return R.DeletedNodes.contains(TE) ||
                                   R.TransformedToGatherNodes.contains(TE);
                          }) ||
                   (isa<GetElementPtrInst>(U) &&
                    !R.areAllUsersVectorized(cast<Instruction>(U))) ||
                   (!UTEs.empty() &&
                    count_if(R.VectorizableTree,
                             [&](const std::unique_ptr<TreeEntry> &TE) {
                               return TE->UserTreeIndex.UserTE ==
                                          UTEs.front() &&
                                      is_contained(VL, EI);
                             }) != 1);
          }))
        continue;
      R.eraseInstruction(EI);
    }
    if (NumParts == 1 || UniqueBases.size() == 1) {
      assert(VecBase && "Expected vectorized value.");
      return castToScalarTyElem(VecBase);
    }
    UseVecBaseAsInput = true;
    auto TransformToIdentity = [](MutableArrayRef<int> Mask) {
      for (auto [I, Idx] : enumerate(Mask))
        if (Idx != PoisonMaskElem)
          Idx = I;
    };
    // Perform multi-register vector shuffle, joining them into a single virtual
    // long vector.
    // Need to shuffle each part independently and then insert all this parts
    // into a long virtual vector register, forming the original vector.
    Value *Vec = nullptr;
    SmallVector<int> VecMask(Mask.size(), PoisonMaskElem);
    unsigned SliceSize = getPartNumElems(VL.size(), NumParts);
    for (unsigned Part : seq<unsigned>(NumParts)) {
      unsigned Limit = getNumElems(VL.size(), SliceSize, Part);
      ArrayRef<Value *> SubVL = ArrayRef(VL).slice(Part * SliceSize, Limit);
      MutableArrayRef<int> SubMask = Mask.slice(Part * SliceSize, Limit);
      constexpr int MaxBases = 2;
      SmallVector<Value *, MaxBases> Bases(MaxBases);
      auto VLMask = zip(SubVL, SubMask);
      const unsigned VF =
          accumulate(VLMask, 0U, [&](unsigned S, const auto &D) {
            if (std::get<1>(D) == PoisonMaskElem)
              return S;
            Value *VecOp =
                cast<ExtractElementInst>(std::get<0>(D))->getVectorOperand();
            if (ArrayRef<TreeEntry *> TEs = R.getTreeEntries(VecOp);
                !TEs.empty())
              VecOp = TEs.front()->VectorizedValue;
            assert(VecOp && "Expected vectorized value.");
            const unsigned Size =
                cast<FixedVectorType>(VecOp->getType())->getNumElements();
            return std::max(S, Size);
          });
      for (const auto [V, I] : make_filter_range(VLMask, [](const auto &P) {
             return std::get<1>(P) != PoisonMaskElem;
           })) {
        Value *VecOp = cast<ExtractElementInst>(V)->getVectorOperand();
        if (ArrayRef<TreeEntry *> TEs = R.getTreeEntries(VecOp); !TEs.empty())
          VecOp = TEs.front()->VectorizedValue;
        assert(VecOp && "Expected vectorized value.");
        VecOp = castToScalarTyElem(VecOp);
        Bases[I / VF] = VecOp;
      }
      if (!Bases.front())
        continue;
      Value *SubVec;
      if (Bases.back()) {
        SubVec = createShuffle(Bases.front(), Bases.back(), SubMask);
        TransformToIdentity(SubMask);
      } else {
        SubVec = Bases.front();
      }
      if (!Vec) {
        Vec = SubVec;
        assert((Part == 0 || all_of(seq<unsigned>(0, Part),
                                    [&](unsigned P) {
                                      ArrayRef<int> SubMask =
                                          Mask.slice(P * SliceSize,
                                                     getNumElems(Mask.size(),
                                                                 SliceSize, P));
                                      return all_of(SubMask, [](int Idx) {
                                        return Idx == PoisonMaskElem;
                                      });
                                    })) &&
               "Expected first part or all previous parts masked.");
        copy(SubMask, std::next(VecMask.begin(), Part * SliceSize));
      } else {
        unsigned NewVF =
            cast<FixedVectorType>(Vec->getType())->getNumElements();
        if (Vec->getType() != SubVec->getType()) {
          unsigned SubVecVF =
              cast<FixedVectorType>(SubVec->getType())->getNumElements();
          NewVF = std::max(NewVF, SubVecVF);
        }
        // Adjust SubMask.
        for (int &Idx : SubMask)
          if (Idx != PoisonMaskElem)
            Idx += NewVF;
        copy(SubMask, std::next(VecMask.begin(), Part * SliceSize));
        Vec = createShuffle(Vec, SubVec, VecMask);
        TransformToIdentity(VecMask);
      }
    }
    copy(VecMask, Mask.begin());
    return Vec;
  }
  /// Checks if the specified entry \p E needs to be delayed because of its
  /// dependency nodes.
  std::optional<Value *>
  needToDelay(const TreeEntry *E,
              ArrayRef<SmallVector<const TreeEntry *>> Deps) const {
    // No need to delay emission if all deps are ready.
    if (all_of(Deps, [](ArrayRef<const TreeEntry *> TEs) {
          return all_of(
              TEs, [](const TreeEntry *TE) { return TE->VectorizedValue; });
        }))
      return std::nullopt;
    // Postpone gather emission, will be emitted after the end of the
    // process to keep correct order.
    auto *ResVecTy = getWidenedType(ScalarTy, E->getVectorFactor());
    return Builder.CreateAlignedLoad(
        ResVecTy,
        PoisonValue::get(PointerType::getUnqual(ScalarTy->getContext())),
        MaybeAlign());
  }
  /// Reset the builder to handle perfect diamond match.
  void resetForSameNode() {
    IsFinalized = false;
    CommonMask.clear();
    InVectors.clear();
  }
  /// Adds 2 input vectors (in form of tree entries) and the mask for their
  /// shuffling.
  void add(const TreeEntry &E1, const TreeEntry &E2, ArrayRef<int> Mask) {
    Value *V1 = getVectorizedValue(E1);
    Value *V2 = getVectorizedValue(E2);
    add(V1, V2, Mask);
  }
  /// Adds single input vector (in form of tree entry) and the mask for its
  /// shuffling.
  void add(const TreeEntry &E1, ArrayRef<int> Mask) {
    Value *V1 = getVectorizedValue(E1);
    add(V1, Mask);
  }
  /// Adds 2 input vectors and the mask for their shuffling.
  void add(Value *V1, Value *V2, ArrayRef<int> Mask) {
    assert(V1 && V2 && !Mask.empty() && "Expected non-empty input vectors.");
    assert(isa<FixedVectorType>(V1->getType()) &&
           isa<FixedVectorType>(V2->getType()) &&
           "castToScalarTyElem expects V1 and V2 to be FixedVectorType");
    V1 = castToScalarTyElem(V1);
    V2 = castToScalarTyElem(V2);
    if (InVectors.empty()) {
      InVectors.push_back(V1);
      InVectors.push_back(V2);
      CommonMask.assign(Mask.begin(), Mask.end());
      return;
    }
    Value *Vec = InVectors.front();
    if (InVectors.size() == 2) {
      Vec = createShuffle(Vec, InVectors.back(), CommonMask);
      transformMaskAfterShuffle(CommonMask, CommonMask);
    } else if (cast<FixedVectorType>(Vec->getType())->getNumElements() !=
               Mask.size()) {
      Vec = createShuffle(Vec, nullptr, CommonMask);
      transformMaskAfterShuffle(CommonMask, CommonMask);
    }
    V1 = createShuffle(V1, V2, Mask);
    unsigned VF = std::max(getVF(V1), getVF(Vec));
    for (unsigned Idx = 0, Sz = CommonMask.size(); Idx < Sz; ++Idx)
      if (Mask[Idx] != PoisonMaskElem)
        CommonMask[Idx] = Idx + VF;
    InVectors.front() = Vec;
    if (InVectors.size() == 2)
      InVectors.back() = V1;
    else
      InVectors.push_back(V1);
  }
  /// Adds another one input vector and the mask for the shuffling.
  void add(Value *V1, ArrayRef<int> Mask, bool = false,
           TTI::VectorInstrContext = TTI::VectorInstrContext::None) {
    assert(isa<FixedVectorType>(V1->getType()) &&
           "castToScalarTyElem expects V1 to be FixedVectorType");
    V1 = castToScalarTyElem(V1);
    if (InVectors.empty()) {
      InVectors.push_back(V1);
      CommonMask.assign(Mask.begin(), Mask.end());
      return;
    }
    const auto *It = find(InVectors, V1);
    if (It == InVectors.end()) {
      if (InVectors.size() == 2 ||
          InVectors.front()->getType() != V1->getType()) {
        Value *V = InVectors.front();
        if (InVectors.size() == 2) {
          V = createShuffle(InVectors.front(), InVectors.back(), CommonMask);
          transformMaskAfterShuffle(CommonMask, CommonMask);
        } else if (cast<FixedVectorType>(V->getType())->getNumElements() !=
                   CommonMask.size()) {
          V = createShuffle(InVectors.front(), nullptr, CommonMask);
          transformMaskAfterShuffle(CommonMask, CommonMask);
        }
        unsigned VF = std::max(CommonMask.size(), Mask.size());
        for (unsigned Idx = 0, Sz = CommonMask.size(); Idx < Sz; ++Idx)
          if (CommonMask[Idx] == PoisonMaskElem && Mask[Idx] != PoisonMaskElem)
            CommonMask[Idx] = V->getType() != V1->getType()
                                  ? Idx + VF
                                  : Mask[Idx] + getVF(V1);
        if (V->getType() != V1->getType())
          V1 = createShuffle(V1, nullptr, Mask);
        InVectors.front() = V;
        if (InVectors.size() == 2)
          InVectors.back() = V1;
        else
          InVectors.push_back(V1);
        return;
      }
      // Check if second vector is required if the used elements are already
      // used from the first one.
      for (unsigned Idx = 0, Sz = CommonMask.size(); Idx < Sz; ++Idx)
        if (Mask[Idx] != PoisonMaskElem && CommonMask[Idx] == PoisonMaskElem) {
          InVectors.push_back(V1);
          break;
        }
    }
    unsigned VF = 0;
    for (Value *V : InVectors)
      VF = std::max(VF, getVF(V));
    for (unsigned Idx = 0, Sz = CommonMask.size(); Idx < Sz; ++Idx)
      if (Mask[Idx] != PoisonMaskElem && CommonMask[Idx] == PoisonMaskElem)
        CommonMask[Idx] = Mask[Idx] + (It == InVectors.begin() ? 0 : VF);
  }
  /// Adds another one input vector and the mask for the shuffling.
  void addOrdered(Value *V1, ArrayRef<unsigned> Order) {
    SmallVector<int> NewMask;
    inversePermutation(Order, NewMask);
    add(V1, NewMask);
  }
  Value *gather(ArrayRef<Value *> VL, unsigned MaskVF = 0,
                Value *Root = nullptr,
                TTI::VectorInstrContext = TTI::VectorInstrContext::None) {
    return R.gather(VL, Root, ScalarTy,
                    [&](Value *V1, Value *V2, ArrayRef<int> Mask) {
                      return createShuffle(V1, V2, Mask);
                    });
  }
  /// Emits the gather of zero-extended sub-fields of width \p FieldWidth of
  /// the same wider integer scalar \p Src, permuted by \p Mask, as a bitcast
  /// to the field vector plus a permutation and an extension to the lane type.
  Value *createExtractedFieldsVector(Value *Src, unsigned FieldWidth,
                                     ArrayRef<int> Mask, const TreeEntry &) {
    auto *FieldTy = IntegerType::get(Src->getContext(), FieldWidth);
    unsigned SrcWidth = Src->getType()->getIntegerBitWidth();
    assert(SrcWidth % FieldWidth == 0 &&
           "Expected the field width to divide the source width.");
    Value *Vec = Builder.CreateBitCast(
        Src, getWidenedType(FieldTy, SrcWidth / FieldWidth));
    if (auto *I = dyn_cast<Instruction>(Vec)) {
      R.GatherShuffleExtractSeq.insert(I);
      R.CSEBlocks.insert(I->getParent());
      // A vectorized source scalar is erased; extract it for the bitcast.
      ArrayRef<TreeEntry *> TEs = R.getTreeEntries(Src);
      const auto *It = find_if_not(TEs, [&](const TreeEntry *TE) {
        return R.TransformedToGatherNodes.contains(TE) ||
               R.DeletedNodes.contains(TE);
      });
      if (It != TEs.end())
        R.ExternalUses.emplace_back(Src, I, **It, (*It)->findLaneForValue(Src));
    }
    Vec = createShuffle(Vec, /*V2=*/nullptr, Mask);
    // The extracted fields are unsigned.
    Vec = castToScalarTyElem(Vec, /*IsSigned=*/false);
    return Vec;
  }
  Value *createFreeze(Value *V) { return Builder.CreateFreeze(V); }
  /// Finalize emission of the shuffles.
  /// \param Action the action (if any) to be performed before final applying of
  /// the \p ExtMask mask.
  Value *finalize(
      ArrayRef<int> ExtMask,
      ArrayRef<std::pair<const TreeEntry *, unsigned>> SubVectors,
      ArrayRef<int> SubVectorsMask, unsigned VF = 0,
      function_ref<void(Value *&, SmallVectorImpl<int> &,
                        function_ref<Value *(Value *, Value *, ArrayRef<int>)>)>
          Action = {}) {
    IsFinalized = true;
    if (Action) {
      Value *Vec = InVectors.front();
      if (InVectors.size() == 2) {
        Vec = createShuffle(Vec, InVectors.back(), CommonMask);
        InVectors.pop_back();
      } else {
        Vec = createShuffle(Vec, nullptr, CommonMask);
      }
      transformMaskAfterShuffle(CommonMask, CommonMask);
      assert(VF > 0 &&
             "Expected vector length for the final value before action.");
      unsigned VecVF = cast<FixedVectorType>(Vec->getType())->getNumElements();
      if (VecVF < VF) {
        SmallVector<int> ResizeMask(VF, PoisonMaskElem);
        std::iota(ResizeMask.begin(), std::next(ResizeMask.begin(), VecVF), 0);
        Vec = createShuffle(Vec, nullptr, ResizeMask);
      }
      Action(Vec, CommonMask, [this](Value *V1, Value *V2, ArrayRef<int> Mask) {
        return createShuffle(V1, V2, Mask);
      });
      InVectors.front() = Vec;
    }
    if (!SubVectors.empty()) {
      Value *Vec = InVectors.front();
      if (InVectors.size() == 2) {
        Vec = createShuffle(Vec, InVectors.back(), CommonMask);
        InVectors.pop_back();
      } else {
        Vec = createShuffle(Vec, nullptr, CommonMask);
      }
      transformMaskAfterShuffle(CommonMask, CommonMask);
      auto CreateSubVectors = [&](Value *Vec,
                                  SmallVectorImpl<int> &CommonMask) {
        for (auto [E, Idx] : SubVectors) {
          Value *V = getVectorizedValue(*E);
          unsigned InsertionIndex = Idx * getNumElements(ScalarTy);
          // Use scalar version of the SCalarType to correctly handle shuffles
          // for revectorization. The revectorization mode operates by the
          // vectors, but here we need to operate on the scalars, because the
          // masks were already transformed for the vector elements and we don't
          // need doing this transformation again.
          Type *OrigScalarTy = ScalarTy;
          ScalarTy = ScalarTy->getScalarType();
          Vec = createInsertVector(
              Builder, Vec, V, InsertionIndex,
              std::bind(&ShuffleInstructionBuilder::createShuffle, this, _1, _2,
                        _3));
          ScalarTy = OrigScalarTy;
          if (!CommonMask.empty()) {
            std::iota(std::next(CommonMask.begin(), Idx),
                      std::next(CommonMask.begin(), Idx + E->getVectorFactor()),
                      Idx);
          }
        }
        return Vec;
      };
      if (SubVectorsMask.empty()) {
        Vec = CreateSubVectors(Vec, CommonMask);
      } else {
        SmallVector<int> SVMask(CommonMask.size(), PoisonMaskElem);
        copy(SubVectorsMask, SVMask.begin());
        for (auto [I1, I2] : zip(SVMask, CommonMask)) {
          if (I2 != PoisonMaskElem) {
            assert(I1 == PoisonMaskElem && "Expected unused subvectors mask");
            I1 = I2 + CommonMask.size();
          }
        }
        Value *InsertVec =
            CreateSubVectors(PoisonValue::get(Vec->getType()), CommonMask);
        Vec = createShuffle(InsertVec, Vec, SVMask);
        transformMaskAfterShuffle(CommonMask, SVMask);
      }
      InVectors.front() = Vec;
    }

    if (!ExtMask.empty()) {
      if (CommonMask.empty()) {
        CommonMask.assign(ExtMask.begin(), ExtMask.end());
      } else {
        SmallVector<int> NewMask(ExtMask.size(), PoisonMaskElem);
        for (int I = 0, Sz = ExtMask.size(); I < Sz; ++I) {
          if (ExtMask[I] == PoisonMaskElem)
            continue;
          NewMask[I] = CommonMask[ExtMask[I]];
        }
        CommonMask.swap(NewMask);
      }
    }
    if (CommonMask.empty()) {
      assert(InVectors.size() == 1 && "Expected only one vector with no mask");
      return InVectors.front();
    }
    if (InVectors.size() == 2)
      return createShuffle(InVectors.front(), InVectors.back(), CommonMask);
    return createShuffle(InVectors.front(), nullptr, CommonMask);
  }

  ~ShuffleInstructionBuilder() {
    assert((IsFinalized || CommonMask.empty()) &&
           "Shuffle construction must be finalized.");
  }
};

Value *BoUpSLP::vectorizeOperand(TreeEntry *E, unsigned NodeIdx) {
  return vectorizeTree(getOperandEntry(E, NodeIdx));
}

template <typename ResTy, typename BVTy>
std::optional<ResTy> BoUpSLP::processExtractedFieldsGather(
    BVTy &ShuffleBuilder, const TreeEntry *E, Type *ScalarTy,
    ArrayRef<Value *> VL,
    ArrayRef<std::pair<const TreeEntry *, unsigned>> SubVectors) {
  if (!SubVectors.empty() || !E->ReuseShuffleIndices.empty() ||
      !ScalarTy->isIntegerTy())
    return std::nullopt;
  std::optional<std::tuple<Value *, unsigned, SmallVector<int>>>
      ExtractedFields = matchGatheredExtractedFields(VL, *DL);
  if (!ExtractedFields ||
      ScalarTy->getIntegerBitWidth() < std::get<1>(*ExtractedFields))
    return std::nullopt;
  Value *Src = std::get<0>(*ExtractedFields);
  unsigned FieldWidth = std::get<1>(*ExtractedFields);
  SmallVector<int> &Mask = std::get<2>(*ExtractedFields);
  return ShuffleBuilder.createExtractedFieldsVector(Src, FieldWidth, Mask, *E);
}

template <typename BVTy, typename ResTy, typename... Args>
ResTy BoUpSLP::processBuildVector(const TreeEntry *E, Type *ScalarTy,
                                  Args &...Params) {
  assert((E->isGather() || TransformedToGatherNodes.contains(E)) &&
         "Expected gather node.");
  unsigned VF = E->getVectorFactor();

  bool NeedFreeze = false;
  SmallVector<Value *> GatheredScalars(E->Scalars.begin(), E->Scalars.end());
  // Do not process split vectorize node, marked to be gathers/buildvectors.
  SmallVector<std::pair<const TreeEntry *, unsigned>> SubVectors(
      E->CombinedEntriesWithIndices.size());
  if (E->State == TreeEntry::SplitVectorize &&
      TransformedToGatherNodes.contains(E)) {
    SubVectors.clear();
  } else {
    // Clear values, to be replaced by insertvector instructions.
    for (auto [EIdx, Idx] : E->CombinedEntriesWithIndices)
      for_each(MutableArrayRef(GatheredScalars)
                   .slice(Idx, VectorizableTree[EIdx]->getVectorFactor()),
               [&](Value *&V) { V = PoisonValue::get(V->getType()); });
    transform(
        E->CombinedEntriesWithIndices, SubVectors.begin(), [&](const auto &P) {
          return std::make_pair(VectorizableTree[P.first].get(), P.second);
        });
  }
  // Build a mask out of the reorder indices and reorder scalars per this
  // mask.
  SmallVector<int> ReorderMask(E->ReorderIndices.begin(),
                               E->ReorderIndices.end());
  if (!ReorderMask.empty())
    reorderScalars(GatheredScalars, ReorderMask);
  SmallVector<int> SubVectorsMask;
  inversePermutation(E->ReorderIndices, SubVectorsMask);
  // Transform non-clustered elements in the mask to poison (-1).
  // "Clustered" operations will be reordered using this mask later.
  if (!SubVectors.empty() && !SubVectorsMask.empty()) {
    for (unsigned I : seq<unsigned>(GatheredScalars.size()))
      if (E->Scalars[I] == GatheredScalars[ReorderMask[I]])
        SubVectorsMask[ReorderMask[I]] = PoisonMaskElem;
  } else {
    SubVectorsMask.clear();
  }
  SmallVector<Value *> StoredGS(GatheredScalars);
  auto FindReusedSplat = [&](MutableArrayRef<int> Mask, unsigned InputVF,
                             unsigned I, unsigned SliceSize,
                             bool IsNotPoisonous) {
    if (!isSplat(E->Scalars) || none_of(E->Scalars, [](Value *V) {
          return isa<UndefValue>(V) && !isa<PoisonValue>(V);
        }))
      return false;
    TreeEntry *UserTE = E->UserTreeIndex.UserTE;
    unsigned EdgeIdx = E->UserTreeIndex.EdgeIdx;
    if (UserTE->getNumOperands() != 2)
      return false;
    if (!IsNotPoisonous) {
      auto *It = find_if(ArrayRef(VectorizableTree).drop_front(UserTE->Idx + 1),
                         [=](const std::unique_ptr<TreeEntry> &TE) {
                           return TE->UserTreeIndex.UserTE == UserTE &&
                                  TE->UserTreeIndex.EdgeIdx != EdgeIdx;
                         });
      if (It == VectorizableTree.end())
        return false;
      SmallVector<Value *> GS((*It)->Scalars.begin(), (*It)->Scalars.end());
      if (!(*It)->ReorderIndices.empty()) {
        inversePermutation((*It)->ReorderIndices, ReorderMask);
        reorderScalars(GS, ReorderMask);
      }
      if (!all_of(zip(GatheredScalars, GS), [&](const auto &P) {
            Value *V0 = std::get<0>(P);
            Value *V1 = std::get<1>(P);
            return !isa<UndefValue>(V0) || isa<PoisonValue>(V0) ||
                   (isa<UndefValue>(V0) && !isa<PoisonValue>(V0) &&
                    is_contained(E->Scalars, V1));
          }))
        return false;
    }
    int Idx;
    if ((Mask.size() < InputVF &&
         ShuffleVectorInst::isExtractSubvectorMask(Mask, InputVF, Idx) &&
         Idx == 0) ||
        (Mask.size() == InputVF &&
         ShuffleVectorInst::isIdentityMask(Mask, Mask.size()))) {
      std::iota(
          std::next(Mask.begin(), I * SliceSize),
          std::next(Mask.begin(),
                    I * SliceSize + getNumElems(Mask.size(), SliceSize, I)),
          0);
    } else {
      unsigned IVal =
          *find_if_not(Mask, [](int Idx) { return Idx == PoisonMaskElem; });
      std::fill(
          std::next(Mask.begin(), I * SliceSize),
          std::next(Mask.begin(),
                    I * SliceSize + getNumElems(Mask.size(), SliceSize, I)),
          IVal);
    }
    return true;
  };
  BVTy ShuffleBuilder(ScalarTy, Params...);
  ResTy Res = ResTy();
  SmallVector<int> Mask;
  SmallVector<int> ExtractMask(GatheredScalars.size(), PoisonMaskElem);
  SmallVector<std::optional<TTI::ShuffleKind>> ExtractShuffles;
  Value *ExtractVecBase = nullptr;
  bool UseVecBaseAsInput = false;
  SmallVector<std::optional<TargetTransformInfo::ShuffleKind>> GatherShuffles;
  SmallVector<SmallVector<const TreeEntry *>> Entries;
  Type *OrigScalarTy = GatheredScalars.front()->getType();
  auto *VecTy = getWidenedType(ScalarTy, GatheredScalars.size());
  unsigned NumParts = getNumberOfParts(VecTy, ScalarTy, GatheredScalars.size());
  if (std::optional<ResTy> Res = processExtractedFieldsGather<ResTy>(
          ShuffleBuilder, E, ScalarTy, GatheredScalars, SubVectors))
    return *Res;
  if (!all_of(GatheredScalars, IsaPred<UndefValue>)) {
    // Check for gathered extracts.
    bool Resized = false;
    ExtractShuffles =
        tryToGatherExtractElements(GatheredScalars, ExtractMask, NumParts);
    if (!ExtractShuffles.empty()) {
      SmallVector<const TreeEntry *> ExtractEntries;
      for (const auto &P :
           make_filter_range(enumerate(ExtractMask), [](const auto &P) {
             return P.value() != PoisonMaskElem;
           })) {
        if (ArrayRef<TreeEntry *> TEs =
                getTreeEntries(cast<ExtractElementInst>(StoredGS[P.index()])
                                   ->getVectorOperand());
            !TEs.empty())
          ExtractEntries.append(TEs.begin(), TEs.end());
      }
      if (std::optional<ResTy> Delayed =
              ShuffleBuilder.needToDelay(E, ExtractEntries)) {
        // Delay emission of gathers which are not ready yet.
        PostponedGathers.insert(E);
        // Postpone gather emission, will be emitted after the end of the
        // process to keep correct order.
        return *Delayed;
      }
      if (Value *VecBase = ShuffleBuilder.adjustExtracts(
              E, ExtractMask, ExtractShuffles, NumParts, UseVecBaseAsInput)) {
        ExtractVecBase = VecBase;
        if (auto *VecBaseTy = dyn_cast<FixedVectorType>(VecBase->getType()))
          if (VF == VecBaseTy->getNumElements() &&
              GatheredScalars.size() != VF) {
            Resized = true;
            GatheredScalars.append(VF - GatheredScalars.size(),
                                   PoisonValue::get(OrigScalarTy));
            NumParts = getNumberOfParts(getWidenedType(OrigScalarTy, VF),
                                        OrigScalarTy, VF);
          }
      }
    }
    // Gather extracts after we check for full matched gathers only.
    if (!ExtractShuffles.empty() || !E->hasState() ||
        E->getOpcode() != Instruction::Load ||
        (((E->hasState() && E->getOpcode() == Instruction::Load) ||
          any_of(E->Scalars, IsaPred<LoadInst>)) &&
         any_of(make_isa_range<LoadInst>(E->Scalars),
                [this](LoadInst *LI) { return isVectorized(LI); })) ||
        (E->hasState() && E->isAltShuffle()) ||
        all_of(E->Scalars, [this](Value *V) { return isVectorized(V); }) ||
        isSplat(E->Scalars) ||
        (E->Scalars != GatheredScalars && GatheredScalars.size() <= 2)) {
      GatherShuffles = isGatherShuffledEntry(E, GatheredScalars, Mask, Entries,
                                             NumParts, ScalarTy);
    }
    // The splat gather subtrees are speculative: the keep/drop check may
    // delete them and does not track reuse of their internal gathers by other
    // gathers.
    if (hasSplatSubtreeGather(Entries)) {
      GatherShuffles.clear();
      Entries.clear();
      std::fill(Mask.begin(), Mask.end(), PoisonMaskElem);
    }
    if (!GatherShuffles.empty()) {
      if (std::optional<ResTy> Delayed =
              ShuffleBuilder.needToDelay(E, Entries)) {
        // Delay emission of gathers which are not ready yet.
        PostponedGathers.insert(E);
        // Postpone gather emission, will be emitted after the end of the
        // process to keep correct order.
        return *Delayed;
      }
      // Match against the expanded vector of the gather node, so that poison
      // lanes of the matched entry cannot wildcard-match its real scalars.
      auto IsFullVectorMatch = [&](const TreeEntry *FrontTE) {
        SmallVector<int> CommonMask = E->getCommonMask();
        SmallVector<Value *> Expanded(E->getVectorFactor());
        for (unsigned I : seq<unsigned>(E->getVectorFactor()))
          Expanded[I] = CommonMask.empty() ? E->Scalars[I]
                        : CommonMask[I] == PoisonMaskElem
                            ? PoisonValue::get(OrigScalarTy)
                            : E->Scalars[CommonMask[I]];
        return FrontTE->isSame(Expanded);
      };
      if (GatherShuffles.size() == 1 &&
          *GatherShuffles.front() == TTI::SK_PermuteSingleSrc &&
          (Entries.front().front()->isSame(E->Scalars) ||
           IsFullVectorMatch(Entries.front().front()))) {
        // Perfect match in the graph, will reuse the previously vectorized
        // node. Cost is 0.
        LLVM_DEBUG(dbgs() << "SLP: perfect diamond match for gather bundle "
                          << shortBundleName(E->Scalars, E->Idx) << ".\n");
        // Restore the mask for previous partially matched values.
        Mask.resize(E->Scalars.size());
        const TreeEntry *FrontTE = Entries.front().front();
        if (FrontTE->ReorderIndices.empty() && E->ReorderIndices.empty() &&
            ((FrontTE->ReuseShuffleIndices.empty() &&
              E->Scalars.size() == FrontTE->Scalars.size()) ||
             (E->Scalars.size() == FrontTE->ReuseShuffleIndices.size()))) {
          std::iota(Mask.begin(), Mask.end(), 0);
        } else {
          for (auto [I, V] : enumerate(E->Scalars)) {
            if (isa<PoisonValue>(V)) {
              Mask[I] = PoisonMaskElem;
              continue;
            }
            Mask[I] = FrontTE->findLaneForValue(V);
          }
        }
        // Reset the builder(s) to correctly handle perfect diamond matched
        // nodes.
        ShuffleBuilder.resetForSameNode();
        // Full matched entry found, no need to insert subvectors.
        if ((IsFullVectorMatch(FrontTE) &&
             FrontTE->ReuseShuffleIndices.empty() &&
             FrontTE->ReorderIndices.empty() &&
             E->getVectorFactor() == FrontTE->getVectorFactor()) ||
            (equal(E->Scalars, FrontTE->Scalars) &&
             equal(E->ReorderIndices, FrontTE->ReorderIndices) &&
             equal(E->ReuseShuffleIndices, FrontTE->ReuseShuffleIndices))) {
          Mask.resize(FrontTE->getVectorFactor());
          std::iota(Mask.begin(), Mask.end(), 0);
          ShuffleBuilder.add(*FrontTE, Mask);
          Res = ShuffleBuilder.finalize({}, {}, {});
        } else {
          ShuffleBuilder.add(*FrontTE, Mask);
          Res = ShuffleBuilder.finalize(E->getCommonMask(), {}, {});
        }
        return Res;
      }
      if (!Resized) {
        if (GatheredScalars.size() != VF &&
            any_of(Entries, [&](ArrayRef<const TreeEntry *> TEs) {
              return any_of(TEs, [&](const TreeEntry *TE) {
                return TE->getVectorFactor() == VF;
              });
            }))
          GatheredScalars.append(VF - GatheredScalars.size(),
                                 PoisonValue::get(OrigScalarTy));
      }
      // Remove shuffled elements from list of gathers.
      for (int I = 0, Sz = Mask.size(); I < Sz; ++I) {
        if (Mask[I] != PoisonMaskElem)
          GatheredScalars[I] = PoisonValue::get(OrigScalarTy);
      }
    }
  }
  auto TryPackScalars = [&](SmallVectorImpl<Value *> &Scalars,
                            SmallVectorImpl<int> &ReuseMask,
                            bool IsRootPoison) {
    // For splats with can emit broadcasts instead of gathers, so try to find
    // such sequences.
    bool IsSplat = IsRootPoison && isSplat(Scalars) &&
                   (Scalars.size() > 2 || Scalars.front() == Scalars.back());
    Scalars.append(VF - Scalars.size(), PoisonValue::get(OrigScalarTy));
    SmallVector<int> UndefPos;
    DenseMap<Value *, unsigned> UniquePositions;
    // Gather unique non-const values and all constant values.
    // For repeated values, just shuffle them.
    int NumNonConsts = 0;
    int SinglePos = 0;
    for (auto [I, V] : enumerate(Scalars)) {
      if (isa<UndefValue>(V)) {
        if (!isa<PoisonValue>(V)) {
          ReuseMask[I] = I;
          UndefPos.push_back(I);
        }
        continue;
      }
      if (isConstant(V)) {
        ReuseMask[I] = I;
        continue;
      }
      ++NumNonConsts;
      SinglePos = I;
      Value *OrigV = V;
      Scalars[I] = PoisonValue::get(OrigScalarTy);
      if (IsSplat) {
        Scalars.front() = OrigV;
        ReuseMask[I] = 0;
      } else {
        const auto Res = UniquePositions.try_emplace(OrigV, I);
        Scalars[Res.first->second] = OrigV;
        ReuseMask[I] = Res.first->second;
      }
    }
    if (NumNonConsts == 1) {
      // Restore single insert element.
      if (IsSplat) {
        ReuseMask.assign(VF, PoisonMaskElem);
        std::swap(Scalars.front(), Scalars[SinglePos]);
        if (!UndefPos.empty() && UndefPos.front() == 0)
          Scalars.front() = UndefValue::get(OrigScalarTy);
      }
      ReuseMask[SinglePos] = SinglePos;
    } else if (!UndefPos.empty() && IsSplat) {
      // For undef values, try to replace them with the simple broadcast.
      // We can do it if the broadcasted value is guaranteed to be
      // non-poisonous, or by freezing the incoming scalar value first.
      auto *It = find_if(Scalars, [this, E](Value *V) {
        return !isa<UndefValue>(V) &&
               (isVectorized(V) || isGuaranteedNotToBePoison(V, AC) ||
                (E->UserTreeIndex && any_of(V->uses(), [E](const Use &U) {
                   // Check if the value already used in the same operation in
                   // one of the nodes already.
                   return E->UserTreeIndex.EdgeIdx != U.getOperandNo() &&
                          is_contained(E->UserTreeIndex.UserTE->Scalars,
                                       U.getUser());
                 })));
      });
      if (It != Scalars.end()) {
        // Replace undefs by the non-poisoned scalars and emit broadcast.
        int Pos = std::distance(Scalars.begin(), It);
        for (int I : UndefPos) {
          // Set the undef position to the non-poisoned scalar.
          ReuseMask[I] = Pos;
          // Replace the undef by the poison, in the mask it is replaced by
          // non-poisoned scalar already.
          if (I != Pos)
            Scalars[I] = PoisonValue::get(OrigScalarTy);
        }
      } else {
        // Replace undefs by the poisons, emit broadcast and then emit
        // freeze.
        for (int I : UndefPos) {
          ReuseMask[I] = PoisonMaskElem;
          if (isa<UndefValue>(Scalars[I]))
            Scalars[I] = PoisonValue::get(OrigScalarTy);
        }
        NeedFreeze = true;
      }
    }
  };
  if (!ExtractShuffles.empty() || !GatherShuffles.empty()) {
    bool IsNonPoisoned = true;
    bool IsUsedInExpr = true;
    Value *Vec1 = nullptr;
    if (!ExtractShuffles.empty()) {
      // Gather of extractelements can be represented as just a shuffle of
      // a single/two vectors the scalars are extracted from.
      // Find input vectors.
      Value *Vec2 = nullptr;
      for (unsigned I = 0, Sz = ExtractMask.size(); I < Sz; ++I) {
        if (!Mask.empty() && Mask[I] != PoisonMaskElem)
          ExtractMask[I] = PoisonMaskElem;
      }
      if (UseVecBaseAsInput) {
        Vec1 = ExtractVecBase;
      } else {
        for (unsigned I = 0, Sz = ExtractMask.size(); I < Sz; ++I) {
          if (ExtractMask[I] == PoisonMaskElem)
            continue;
          if (isa<UndefValue>(StoredGS[I]))
            continue;
          auto *EI = cast<ExtractElementInst>(StoredGS[I]);
          Value *VecOp = EI->getVectorOperand();
          if (ArrayRef<TreeEntry *> TEs = getTreeEntries(VecOp);
              !TEs.empty() && TEs.front()->VectorizedValue)
            VecOp = TEs.front()->VectorizedValue;
          if (!Vec1) {
            Vec1 = VecOp;
          } else if (Vec1 != VecOp) {
            assert((!Vec2 || Vec2 == VecOp) &&
                   "Expected only 1 or 2 vectors shuffle.");
            Vec2 = VecOp;
          }
        }
      }
      if (Vec2) {
        IsUsedInExpr = false;
        IsNonPoisoned &= isGuaranteedNotToBePoison(Vec1, AC) &&
                         isGuaranteedNotToBePoison(Vec2, AC);
        ShuffleBuilder.add(Vec1, Vec2, ExtractMask);
      } else if (Vec1) {
        bool IsNotPoisonedVec = isGuaranteedNotToBePoison(Vec1, AC);
        IsUsedInExpr &= FindReusedSplat(
            ExtractMask,
            cast<FixedVectorType>(Vec1->getType())->getNumElements(), 0,
            ExtractMask.size(), IsNotPoisonedVec);
        ShuffleBuilder.add(Vec1, ExtractMask, /*ForExtracts=*/true);
        IsNonPoisoned &= IsNotPoisonedVec;
      } else {
        IsUsedInExpr = false;
        ShuffleBuilder.add(PoisonValue::get(VecTy), ExtractMask,
                           /*ForExtracts=*/true);
      }
    }
    if (!GatherShuffles.empty()) {
      unsigned SliceSize = getPartNumElems(VF, NumParts);
      if (Mask.size() == E->Scalars.size())
        SliceSize = getPartNumElems(
            E->Scalars.size(),
            getNumberOfParts(VecTy, ScalarTy, E->Scalars.size()));
      SmallVector<int> VecMask(Mask.size(), PoisonMaskElem);
      for (const auto [I, TEs] : enumerate(Entries)) {
        if (TEs.empty()) {
          assert(!GatherShuffles[I] &&
                 "No shuffles with empty entries list expected.");
          continue;
        }
        assert((TEs.size() == 1 || TEs.size() == 2) &&
               "Expected shuffle of 1 or 2 entries.");
        unsigned Limit = getNumElems(Mask.size(), SliceSize, I);
        auto SubMask = ArrayRef(Mask).slice(I * SliceSize, Limit);
        VecMask.assign(VecMask.size(), PoisonMaskElem);
        copy(SubMask, std::next(VecMask.begin(), I * SliceSize));
        if (TEs.size() == 1) {
          bool IsNotPoisonedVec =
              TEs.front()->VectorizedValue
                  ? isGuaranteedNotToBePoison(TEs.front()->VectorizedValue, AC)
                  : true;
          IsUsedInExpr &=
              FindReusedSplat(VecMask, TEs.front()->getVectorFactor(), I,
                              SliceSize, IsNotPoisonedVec);
          ShuffleBuilder.add(*TEs.front(), VecMask);
          IsNonPoisoned &= IsNotPoisonedVec;
        } else {
          IsUsedInExpr = false;
          ShuffleBuilder.add(*TEs.front(), *TEs.back(), VecMask);
          if (TEs.front()->VectorizedValue && TEs.back()->VectorizedValue)
            IsNonPoisoned &=
                isGuaranteedNotToBePoison(TEs.front()->VectorizedValue, AC) &&
                isGuaranteedNotToBePoison(TEs.back()->VectorizedValue, AC);
        }
      }
    }
    // Try to figure out best way to combine values: build a shuffle and insert
    // elements or just build several shuffles.
    // Insert non-constant scalars.
    SmallVector<Value *> NonConstants(GatheredScalars);
    int EMSz = ExtractMask.size();
    int MSz = Mask.size();
    // Try to build constant vector and shuffle with it only if currently we
    // have a single permutation and more than 1 scalar constants.
    bool IsSingleShuffle = ExtractShuffles.empty() || GatherShuffles.empty();
    bool IsIdentityShuffle =
        ((UseVecBaseAsInput ||
          all_of(ExtractShuffles,
                 [](const std::optional<TTI::ShuffleKind> &SK) {
                   return SK.value_or(TTI::SK_PermuteTwoSrc) ==
                          TTI::SK_PermuteSingleSrc;
                 })) &&
         none_of(ExtractMask, [&](int I) { return I >= EMSz; }) &&
         ShuffleVectorInst::isIdentityMask(ExtractMask, EMSz)) ||
        (!GatherShuffles.empty() &&
         all_of(GatherShuffles,
                [](const std::optional<TTI::ShuffleKind> &SK) {
                  return SK.value_or(TTI::SK_PermuteTwoSrc) ==
                         TTI::SK_PermuteSingleSrc;
                }) &&
         none_of(Mask, [&](int I) { return I >= MSz; }) &&
         ShuffleVectorInst::isIdentityMask(Mask, MSz));
    bool EnoughConstsForShuffle =
        IsSingleShuffle &&
        (none_of(GatheredScalars,
                 [](Value *V) {
                   return isa<UndefValue>(V) && !isa<PoisonValue>(V);
                 }) ||
         any_of(GatheredScalars,
                [](Value *V) {
                  return isa<Constant>(V) && !isa<UndefValue>(V);
                })) &&
        (!IsIdentityShuffle ||
         (GatheredScalars.size() == 2 &&
          any_of(GatheredScalars,
                 [](Value *V) { return !isa<UndefValue>(V); })) ||
         count_if(GatheredScalars, [](Value *V) {
           return isa<Constant>(V) && !isa<PoisonValue>(V);
         }) > 1);
    // NonConstants array contains just non-constant values, GatheredScalars
    // contains only constant to build final vector and then shuffle.
    for (int I = 0, Sz = GatheredScalars.size(); I < Sz; ++I) {
      if (EnoughConstsForShuffle && isa<Constant>(GatheredScalars[I]))
        NonConstants[I] = PoisonValue::get(OrigScalarTy);
      else
        GatheredScalars[I] = PoisonValue::get(OrigScalarTy);
    }
    // Generate constants for final shuffle and build a mask for them.
    if (!all_of(GatheredScalars, IsaPred<PoisonValue>)) {
      SmallVector<int> BVMask(GatheredScalars.size(), PoisonMaskElem);
      TryPackScalars(GatheredScalars, BVMask, /*IsRootPoison=*/true);
      Value *BV = ShuffleBuilder.gather(GatheredScalars, BVMask.size());
      ShuffleBuilder.add(BV, BVMask);
    }
    if (all_of(NonConstants, [=](Value *V) {
          return isa<PoisonValue>(V) ||
                 (IsSingleShuffle && ((IsIdentityShuffle &&
                  IsNonPoisoned) || IsUsedInExpr) && isa<UndefValue>(V));
        }))
      Res = ShuffleBuilder.finalize(E->ReuseShuffleIndices, SubVectors,
                                    SubVectorsMask);
    else
      Res = ShuffleBuilder.finalize(
          E->ReuseShuffleIndices, SubVectors, SubVectorsMask, E->Scalars.size(),
          [&](Value *&Vec, SmallVectorImpl<int> &Mask, auto CreateShuffle) {
            bool IsSplat = isSplat(NonConstants);
            SmallVector<int> BVMask(Mask.size(), PoisonMaskElem);
            TryPackScalars(NonConstants, BVMask, /*IsRootPoison=*/false);
            auto CheckIfSplatIsProfitable = [&]() {
              // Estimate the cost of splatting + shuffle and compare with
              // insert + shuffle.
              Value *V = *find_if_not(NonConstants, IsaPred<UndefValue>);
              if (isa<ExtractElementInst>(V) || isVectorized(V))
                return false;
              InstructionCost SplatCost = TTI->getVectorInstrCost(
                  Instruction::InsertElement, VecTy, CostKind, /*Index=*/0,
                  PoisonValue::get(VecTy), V);
              SmallVector<int> NewMask(Mask.begin(), Mask.end());
              for (auto [Idx, I] : enumerate(BVMask))
                if (I != PoisonMaskElem)
                  NewMask[Idx] = Mask.size();
              SplatCost +=
                  getShuffleCost(*TTI, TTI::SK_PermuteTwoSrc,
                                 cast<VectorType>(VecTy), CostKind, NewMask);
              InstructionCost BVCost = TTI->getVectorInstrCost(
                  Instruction::InsertElement, VecTy, CostKind,
                  *find_if(Mask, not_equal_to(PoisonMaskElem)), Vec, V);
              // Shuffle required?
              if (count(BVMask, PoisonMaskElem) <
                  static_cast<int>(BVMask.size() - 1)) {
                SmallVector<int> NewMask(Mask.begin(), Mask.end());
                for (auto [Idx, I] : enumerate(BVMask))
                  if (I != PoisonMaskElem)
                    NewMask[Idx] = I;
                BVCost +=
                    getShuffleCost(*TTI, TTI::SK_PermuteSingleSrc,
                                   cast<VectorType>(VecTy), CostKind, NewMask);
              }
              return SplatCost <= BVCost;
            };
            if (!IsSplat || Mask.size() <= 2 || !CheckIfSplatIsProfitable()) {
              for (auto [Idx, I] : enumerate(BVMask))
                if (I != PoisonMaskElem)
                  Mask[Idx] = I;
              Vec = ShuffleBuilder.gather(NonConstants, Mask.size(), Vec);
            } else {
              Value *V = *find_if_not(NonConstants, IsaPred<UndefValue>);
              SmallVector<Value *> Values(NonConstants.size(),
                                          PoisonValue::get(ScalarTy));
              Values[0] = V;
              Value *BV = ShuffleBuilder.gather(Values, BVMask.size());
              SmallVector<int> SplatMask(BVMask.size(), PoisonMaskElem);
              transform(BVMask, SplatMask.begin(), [](int I) {
                return I == PoisonMaskElem ? PoisonMaskElem : 0;
              });
              if (!ShuffleVectorInst::isIdentityMask(SplatMask, VF))
                BV = CreateShuffle(BV, nullptr, SplatMask);
              for (auto [Idx, I] : enumerate(BVMask))
                if (I != PoisonMaskElem)
                  Mask[Idx] = BVMask.size() + Idx;
              Vec = CreateShuffle(Vec, BV, Mask);
              for (auto [Idx, I] : enumerate(Mask))
                if (I != PoisonMaskElem)
                  Mask[Idx] = Idx;
            }
          });
  } else if (!allConstant(GatheredScalars)) {
    // Gather unique scalars and all constants.
    SmallVector<int> ReuseMask(GatheredScalars.size(), PoisonMaskElem);
    TryPackScalars(GatheredScalars, ReuseMask, /*IsRootPoison=*/true);
    TTI::VectorInstrContext ContextHint = TTI::VectorInstrContext::None;
    if constexpr (std::is_same_v<ResTy, InstructionCost>) {
      auto GatherUserOps =
          [&](SmallVectorImpl<TTI::BuildVectorUseOp> &UserOps) {
            UserOps.clear();
            return !NeedFreeze && collectGatherUserOps(*E, UserOps);
          };
      ContextHint =
          TTI->getBuildVectorContextHint(ReuseMask, E->Scalars, GatherUserOps);
    }
    Value *BV = ShuffleBuilder.gather(GatheredScalars, ReuseMask.size(),
                                      /*Root*/ nullptr, ContextHint);
    ShuffleBuilder.add(BV, ReuseMask, /*ForExtract*/ false, ContextHint);
    Res = ShuffleBuilder.finalize(E->ReuseShuffleIndices, SubVectors,
                                  SubVectorsMask, /*VF*/ 0, /*Action*/ {});
  } else {
    // Gather all constants.
    SmallVector<int> Mask(GatheredScalars.size(), PoisonMaskElem);
    for (auto [I, V] : enumerate(GatheredScalars)) {
      if (!isa<PoisonValue>(V))
        Mask[I] = I;
    }
    Value *BV = ShuffleBuilder.gather(GatheredScalars);
    ShuffleBuilder.add(BV, Mask);
    Res = ShuffleBuilder.finalize(E->ReuseShuffleIndices, SubVectors,
                                  SubVectorsMask);
  }

  if (NeedFreeze)
    Res = ShuffleBuilder.createFreeze(Res);
  return Res;
}

Value *BoUpSLP::createBuildVector(const TreeEntry *E, Type *ScalarTy) {
  // Do not do this for split vectorize node, marked to be gathers/buildvectors.
  if (E->State != TreeEntry::SplitVectorize ||
      !TransformedToGatherNodes.contains(E)) {
    for (auto [EIdx, _] : E->CombinedEntriesWithIndices)
      (void)vectorizeTree(VectorizableTree[EIdx].get());
  }
  return processBuildVector<ShuffleInstructionBuilder, Value *>(E, ScalarTy,
                                                                Builder, *this);
}

/// \returns \p I after propagating metadata from \p VL only for instructions in
/// \p VL.
static Instruction *propagateMetadata(Instruction *Inst, ArrayRef<Value *> VL) {
  SmallVector<Value *> Insts(make_isa_range<Instruction>(VL));
  return llvm::propagateMetadata(Inst, Insts);
}

Value *BoUpSLP::vectorizeTree(TreeEntry *E) {
  IRBuilderBase::InsertPointGuard Guard(Builder);

  Value *V = E->Scalars.front();
  Type *ScalarTy = getValueType(V, Opts.slp_revec);
  auto It = MinBWs.find(E);
  if (It != MinBWs.end()) {
    auto *VecTy = dyn_cast<FixedVectorType>(ScalarTy);
    ScalarTy = IntegerType::get(F->getContext(), It->second.first);
    if (VecTy)
      ScalarTy = getWidenedType(ScalarTy, VecTy->getNumElements());
  }
  if (E->VectorizedValue)
    return E->VectorizedValue;
  auto *VecTy = getWidenedType(ScalarTy, E->Scalars.size());
  if (E->isGather() || TransformedToGatherNodes.contains(E)) {
    // Set insert point for non-reduction initial nodes.
    if (E->hasState() && E->Idx == 0 && !UserIgnoreList)
      setInsertPointAfterBundle(E);
    Value *Vec = createBuildVector(E, ScalarTy);
    E->VectorizedValue = Vec;
    return Vec;
  }
  if (E->State == TreeEntry::SplitVectorize) {
    assert(E->CombinedEntriesWithIndices.size() == 2 &&
           "Expected exactly 2 combined entries.");
    setInsertPointAfterBundle(E);
    TreeEntry &OpTE1 =
        *VectorizableTree[E->CombinedEntriesWithIndices.front().first];
    assert(OpTE1.isSame(
               ArrayRef(E->Scalars).take_front(OpTE1.getVectorFactor())) &&
           "Expected same first part of scalars.");
    Value *Op1 = vectorizeTree(&OpTE1);
    TreeEntry &OpTE2 =
        *VectorizableTree[E->CombinedEntriesWithIndices.back().first];
    assert(
        OpTE2.isSame(ArrayRef(E->Scalars).take_back(OpTE2.getVectorFactor())) &&
        "Expected same second part of scalars.");
    Value *Op2 = vectorizeTree(&OpTE2);
    auto GetOperandSignedness = [&](const TreeEntry *OpE) {
      bool IsSigned = false;
      auto It = MinBWs.find(OpE);
      if (It != MinBWs.end())
        IsSigned = It->second.second;
      else
        IsSigned = any_of(OpE->Scalars, [&](Value *R) {
          if (isa<PoisonValue>(V))
            return false;
          return !isKnownNonNegative(R, SimplifyQuery(*DL));
        });
      return IsSigned;
    };
    if (cast<VectorType>(Op1->getType())->getElementType() !=
        ScalarTy->getScalarType()) {
      assert(ScalarTy->isIntegerTy() && "Expected item in MinBWs.");
      Op1 = Builder.CreateIntCast(
          Op1,
          getWidenedType(
              ScalarTy,
              cast<FixedVectorType>(Op1->getType())->getNumElements()),
          GetOperandSignedness(&OpTE1));
    }
    if (cast<VectorType>(Op2->getType())->getElementType() !=
        ScalarTy->getScalarType()) {
      assert(ScalarTy->isIntegerTy() && "Expected item in MinBWs.");
      Op2 = Builder.CreateIntCast(
          Op2,
          getWidenedType(
              ScalarTy,
              cast<FixedVectorType>(Op2->getType())->getNumElements()),
          GetOperandSignedness(&OpTE2));
    }
    if (E->ReorderIndices.empty()) {
      SmallVector<int> Mask(E->getVectorFactor(), PoisonMaskElem);
      std::iota(
          Mask.begin(),
          std::next(Mask.begin(), E->CombinedEntriesWithIndices.back().second),
          0);
      unsigned ScalarTyNumElements = getNumElements(ScalarTy);
      if (ScalarTyNumElements != 1) {
        assert(Opts.slp_revec && "Only supported by REVEC.");
        transformScalarShuffleIndiciesToVector(ScalarTyNumElements, Mask);
      }
      Value *Vec = Builder.CreateShuffleVector(Op1, Mask);
      Vec = createInsertVector(Builder, Vec, Op2,
                               E->CombinedEntriesWithIndices.back().second *
                                   ScalarTyNumElements);
      E->VectorizedValue = Vec;
      return Vec;
    }
    unsigned CommonVF =
        std::max(OpTE1.getVectorFactor(), OpTE2.getVectorFactor());
    const unsigned Scale = getNumElements(ScalarTy);
    CommonVF *= Scale;
    if (getNumElements(Op1->getType()) != CommonVF) {
      SmallVector<int> Mask(CommonVF, PoisonMaskElem);
      copy(createReplicatedMask(Scale, OpTE1.getVectorFactor() * Scale),
           Mask.begin());
      Op1 = Builder.CreateShuffleVector(Op1, Mask);
    }
    if (getNumElements(Op2->getType()) != CommonVF) {
      SmallVector<int> Mask(CommonVF, PoisonMaskElem);
      copy(createReplicatedMask(Scale, OpTE2.getVectorFactor() * Scale),
           Mask.begin());
      Op2 = Builder.CreateShuffleVector(Op2, Mask);
    }
    Value *Vec = Builder.CreateShuffleVector(Op1, Op2, E->getSplitMask());
    E->VectorizedValue = Vec;
    return Vec;
  }

  bool IsReverseOrder = E->isReverse() && !isWidenedStridedLoad(E);
  auto FinalShuffle = [&](Value *V, const TreeEntry *E) {
    if (isa<StructType>(ScalarTy)) {
      // TODO: Reordering of struct types is not supported.
      assert(E->ReorderIndices.empty() &&
             "Expected no reordering for struct types.");
      assert(E->ReuseShuffleIndices.empty() &&
             "Expected no reuse shuffle indices for struct types.");
      return V;
    }
    ShuffleInstructionBuilder ShuffleBuilder(ScalarTy, Builder, *this);
    if ((E->State == TreeEntry::StridedVectorize && IsReverseOrder) ||
        E->State == TreeEntry::CompressVectorize) {
      ShuffleBuilder.addOrdered(V, {});
    } else if (E->getOpcode() == Instruction::Store &&
               (E->State == TreeEntry::Vectorize ||
                E->State == TreeEntry::StridedVectorize ||
                E->State == TreeEntry::ExpandVectorize)) {
      ArrayRef<int> Mask =
          ArrayRef(reinterpret_cast<const int *>(E->ReorderIndices.begin()),
                   E->ReorderIndices.size());
      ShuffleBuilder.add(V, Mask);
    } else {
      ShuffleBuilder.addOrdered(V, E->ReorderIndices);
    }
    SmallVector<std::pair<const TreeEntry *, unsigned>> SubVectors(
        E->CombinedEntriesWithIndices.size());
    transform(
        E->CombinedEntriesWithIndices, SubVectors.begin(), [&](const auto &P) {
          return std::make_pair(VectorizableTree[P.first].get(), P.second);
        });
    assert(
        (E->CombinedEntriesWithIndices.empty() || E->ReorderIndices.empty()) &&
        "Expected either combined subnodes or reordering");
    return ShuffleBuilder.finalize(E->ReuseShuffleIndices, SubVectors, {});
  };

  assert(!E->isGather() && "Unhandled state");
  unsigned ShuffleOrOp =
      E->isAltShuffle() ? (unsigned)Instruction::ShuffleVector : E->getOpcode();
  if (!E->isAltShuffle()) {
    switch (E->CombinedOp) {
    case TreeEntry::ReducedBitcast:
    case TreeEntry::ReducedBitcastBSwap:
    case TreeEntry::ReducedBitcastLoads:
    case TreeEntry::ReducedBitcastBSwapLoads:
    case TreeEntry::ReducedBitPack:
    case TreeEntry::ReducedCmpBitcast:
      ShuffleOrOp = E->CombinedOp;
      break;
    default:
      break;
    }
  }
  Instruction *VL0 = E->getMainOp();
  auto GetOperandSignedness = [&](unsigned Idx) {
    const TreeEntry *OpE = getOperandEntry(E, Idx);
    bool IsSigned = false;
    auto It = MinBWs.find(OpE);
    if (It != MinBWs.end())
      IsSigned = It->second.second;
    else
      IsSigned = any_of(OpE->Scalars, [&](Value *R) {
        if (isa<PoisonValue>(V))
          return false;
        return !isKnownNonNegative(R, SimplifyQuery(*DL));
      });
    return IsSigned;
  };
  auto PropagateIRFlags = [&](Value *V, unsigned Opcode = 0,
                              ArrayRef<Value *> VL = {}) -> Value * {
    ArrayRef<Value *> Scalars = VL.empty() ? E->Scalars : VL;
    SmallSetVector<Value *, 4> UniqueInsts;
    for (Instruction *I : make_isa_range<Instruction>(Scalars)) {
      if (E->hasCopyableElements() && E->isCopyableElement(I))
        continue;
      UniqueInsts.insert(I);
    }
    if (!Opcode)
      Opcode = E->getOpcode();
    propagateIRFlags(V, UniqueInsts.getArrayRef(), nullptr, It == MinBWs.end());
    auto *I = dyn_cast<Instruction>(V);
    if (!I)
      return V;
    // Drop nneg propagated from the original cast.
    Value *Op;
    if (auto *CI = dyn_cast<CastInst>(VL0);
        CI && match(I, m_NNegZExt(m_Value(Op))) &&
        Op->getType()->getScalarType() != CI->getSrcTy())
      cast<ZExtInst>(I)->setNonNeg(false);
    // A lane may be emitted in negated form (sub C, x as add x, -C, or an
    // add/sub lane with swapped operands) when all its uses are
    // sign-insensitive (icmp eq/ne 0 or abs). The value stays correct for
    // such uses, but nsw/nuw of the original instruction do not cover the
    // negated overflow conditions.
    if (E->State == TreeEntry::Vectorize && E->getNumOperands() == 2 &&
        I->getType()->isIntOrIntVectorTy() &&
        (Opcode == Instruction::Add || Opcode == Instruction::Sub)) {
      auto IsNegatedLane = [&](Instruction *LaneI, unsigned Lane) {
        unsigned LaneOpcode = LaneI->getOpcode();
        if (LaneOpcode != Instruction::Add && LaneOpcode != Instruction::Sub)
          return false;
        Value *L = E->getOperand(0)[Lane];
        Value *R = E->getOperand(1)[Lane];
        if (LaneOpcode == Opcode)
          // Only a sub lane emitted with swapped operands is negated.
          return Opcode == Instruction::Sub && L == LaneI->getOperand(1) &&
                 R == LaneI->getOperand(0) && L != R;
        if (Opcode == Instruction::Add)
          // sub C, x emitted as x + -C.
          return isa<ConstantInt>(LaneI->getOperand(0)) &&
                 !isa<ConstantInt>(LaneI->getOperand(1));
        // add x, C emitted as -C - x.
        return isa<ConstantInt>(L) && !isa<ConstantInt>(R);
      };
      if (any_of(enumerate(E->Scalars), [&](const auto &P) {
            auto *LaneI = dyn_cast<Instruction>(P.value());
            return LaneI &&
                   (!E->hasCopyableElements() ||
                    !E->isCopyableElement(LaneI)) &&
                   (VL.empty() || is_contained(VL, LaneI)) &&
                   IsNegatedLane(LaneI, P.index());
          }))
        I->dropPoisonGeneratingFlags();
    }
    I = ::propagateMetadata(I, UniqueInsts.getArrayRef());
    // A copyable lane is emitted as a synthesized operation - an absorbed
    // fmul becomes fmuladd(a, b, -0.0), other scalars are combined with a
    // binop identity value - so every fast-math flag must be justified by
    // each copyable scalar: an FP operator justifies only its own flags, a
    // constant FP the flags its value cannot violate, and any other value
    // only the transform permissions, which cannot change an identity
    // lane. An unjustified flag poisons NaN/Inf inputs, flushes a -0.0
    // result, or changes the rounding of an absorbed lane.
    if (E->hasCopyableElements() && isa<FPMathOperator>(I)) {
      FastMathFlags CopyableFMF;
      CopyableFMF.set();
      auto IsCopyable = [&](Value *V) { return E->isCopyableElement(V); };
      for (Value *Scalar : make_filter_range(Scalars, IsCopyable)) {
        if (auto *FPMO = dyn_cast<FPMathOperator>(Scalar)) {
          CopyableFMF &= FPMO->getFastMathFlags();
          continue;
        }
        auto *CFP = dyn_cast<ConstantFP>(Scalar);
        if (!CFP || CFP->isNaN())
          CopyableFMF.setNoNaNs(false);
        if (!CFP || CFP->isInfinity())
          CopyableFMF.setNoInfs(false);
        if (!CFP || CFP->isNegZero())
          CopyableFMF.setNoSignedZeros(false);
      }
      I->copyFastMathFlags(I->getFastMathFlags() & CopyableFMF);
    }
    // Copyable lanes modeled as op(V, V) or with an undef or poison operand do
    // not preserve the disjoint flag: or disjoint(V, V) is poison unless V is
    // zero, and such an operand may be any value. Matched by value, so operand
    // reordering does not affect the detection.
    auto *PDI = dyn_cast<PossiblyDisjointInst>(I);
    if (E->hasCopyableElements() && PDI &&
        any_of(enumerate(E->Scalars), [&](const auto &P) {
          Value *Scalar = P.value();
          auto IsScalarOrUndef = [Scalar](Value *Op) {
            return Op == Scalar || isa<UndefValue>(Op);
          };
          return E->isCopyableElement(Scalar) && !match(Scalar, m_Zero()) &&
                 IsScalarOrUndef(E->getOperand(0)[P.index()]) &&
                 IsScalarOrUndef(E->getOperand(1)[P.index()]);
        }))
      PDI->setIsDisjoint(false);
    // The undef copyable lanes are modeled as op(undef, undef), which must not
    // overflow into poison.
    if (E->hasCopyableElements() && isUndefTolerantBinOp(I) &&
        any_of(E->Scalars, [&](Value *Scalar) {
          return isa<UndefValue>(Scalar) && !isa<PoisonValue>(Scalar) &&
                 E->isCopyableElement(Scalar);
        }))
      I->dropPoisonGeneratingFlags();
    // Drop nuw flags for abs(sub(commutative), true).
    if (!MinBWs.contains(E) && Opcode == Instruction::Sub &&
        (E->hasCopyableElements() || any_of(Scalars, [](Value *Scalar) {
           auto *SI = dyn_cast<Instruction>(Scalar);
           return !SI || isCommutative(SI);
         })))
      I->setHasNoUnsignedWrap(/*b=*/false);
    // A sub feeding icmp eq/ne 0 may have its operands swapped; nsw does not
    // survive a - b -> b - a (a - b can be INT_MIN while b - a overflows).
    if (!MinBWs.contains(E) && Opcode == Instruction::Sub &&
        any_of(make_isa_range<Instruction>(Scalars), [](Instruction *SI) {
          if (SI->getOpcode() != Instruction::Sub || !isCommutative(SI))
            return false;
          return any_of(SI->uses(), [](const Use &U) {
            CmpPredicate Pred;
            return match(U.getUser(),
                         m_ICmp(Pred, m_Specific(U.get()), m_Zero())) &&
                   ICmpInst::isEquality(Pred);
          });
        }))
      I->setHasNoSignedWrap(/*b=*/false);
    // Interchanging add/sub negates the constant: nsw only survives if the
    // constant isn't INT_MIN (negating it would overflow); nuw never
    // survives a nonzero constant, since that flips the valid range from
    // X >= C to X < C.
    if (!MinBWs.contains(E) &&
        (Opcode == Instruction::Add || Opcode == Instruction::Sub)) {
      for (Value *V : UniqueInsts) {
        auto *SI = cast<Instruction>(V);
        if (SI->getOpcode() == Opcode ||
            !is_contained({Instruction::Add, Instruction::Sub},
                          SI->getOpcode()))
          continue;
        for (const ConstantInt *CI :
             make_isa_range<ConstantInt>(SI->operands())) {
          if (CI->isZero())
            continue;
          I->setHasNoUnsignedWrap(/*b=*/false);
          if (CI->getValue().isMinSignedValue())
            I->setHasNoSignedWrap(/*b=*/false);
        }
      }
    }
    // mul nsw X, INT_MIN is not equivalent to shl nsw X, BW-1, because shl nsw
    // poisons when the sign bit is shifted out of a positive value. When a mul
    // lane is converted to shl with shift amount BW-1, nsw must be dropped.
    if (!MinBWs.contains(E) && Opcode == Instruction::Shl &&
        any_of(UniqueInsts, [&](Value *V) {
          auto *SI = cast<Instruction>(V);
          if (SI->getOpcode() != Instruction::Mul)
            return false;
          return any_of(make_isa_range<ConstantInt>(SI->operands()),
                        [](const ConstantInt *CI) {
                          return CI->getValue().isMinSignedValue();
                        });
        }))
      I->setHasNoSignedWrap(/*b=*/false);
    // shl nsw X, BW-1 is not equivalent to mul nsw X, INT_MIN: shl nsw never
    // poisons at X = -1 (shifted-out bits match the sign bit), but mul nsw
    // does. A shl lane converted to mul this way must drop nsw.
    if (!MinBWs.contains(E) && Opcode == Instruction::Mul &&
        any_of(UniqueInsts, [&](Value *V) {
          auto *SI = cast<Instruction>(V);
          if (SI->getOpcode() != Instruction::Shl)
            return false;
          const auto *CI = dyn_cast<ConstantInt>(SI->getOperand(1));
          return CI && CI->getValue() == CI->getBitWidth() - 1;
        }))
      I->setHasNoSignedWrap(/*b=*/false);
    // Keep the intersected samesign unless narrowing changed the sign of some
    // compared operand (it neither sign-extends from the narrow type nor has
    // a known-zero narrow sign bit), or a converted lane's adjusted constant
    // flips the sign.
    if (auto *ICmp = dyn_cast<ICmpInst>(I); ICmp && It == MinBWs.end()) {
      bool SignChange =
          ICmp->getOperand(0)->getType()->getScalarType() !=
              VL0->getOperand(0)->getType()->getScalarType() &&
          ((!GetOperandSignedness(0) &&
            !isKnownNonNegative(ICmp->getOperand(0), SimplifyQuery(*DL))) ||
           (!GetOperandSignedness(1) &&
            !isKnownNonNegative(ICmp->getOperand(1), SimplifyQuery(*DL))));
      CmpInst::Predicate P0 = cast<CmpInst>(E->getMainOp())->getPredicate();
      bool SignFlip =
          !SignChange &&
          any_of(make_isa_range<ICmpInst>(E->Scalars), [&](ICmpInst *LaneCI) {
            const APInt *OrigC, *AdjC;
            Constant *Adj =
                CmpSamePredicateHelper::getAdjustedConstant(LaneCI, P0);
            return Adj && match(LaneCI->getOperand(1), m_APInt(OrigC)) &&
                   match(Adj, m_APInt(AdjC)) &&
                   AdjC->isNegative() != OrigC->isNegative();
          });
      if (SignChange || SignFlip)
        ICmp->setSameSign(/*B=*/false);
    }
    return I;
  };
  switch (ShuffleOrOp) {
    case Instruction::PHI: {
      assert((E->ReorderIndices.empty() || !E->ReuseShuffleIndices.empty() ||
              E != &getRootNode() || E->UserTreeIndex) &&
             "PHI reordering is free.");
      auto *PH = cast<PHINode>(VL0);
      Builder.SetInsertPoint(PH->getParent()->getFirstNonPHIIt());
      Builder.SetCurrentDebugLocation(getDebugLocFromPHI(*PH));
      PHINode *NewPhi = Builder.CreatePHI(VecTy, PH->getNumIncomingValues());
      Value *V = NewPhi;

      // Adjust insertion point once all PHI's have been generated.
      Builder.SetInsertPoint(PH->getParent()->getFirstInsertionPt());
      Builder.SetCurrentDebugLocation(getDebugLocFromPHI(*PH));

      V = FinalShuffle(V, E);

      E->VectorizedValue = V;
      // If phi node is fully emitted - exit.
      if (NewPhi->getNumIncomingValues() != 0)
        return NewPhi;

      // PHINodes may have multiple entries from the same block. We want to
      // visit every block once.
      SmallDenseMap<BasicBlock *, unsigned, 4> VisitedBBs;
      for (unsigned I : seq<unsigned>(PH->getNumIncomingValues())) {
        BasicBlock *IBB = PH->getIncomingBlock(I);

        // Stop emission if all incoming values are generated.
        if (NewPhi->getNumIncomingValues() == PH->getNumIncomingValues()) {
          LLVM_DEBUG(dbgs() << "SLP: Diamond merged for " << *VL0 << ".\n");
          return NewPhi;
        }

        Builder.SetInsertPoint(IBB->getTerminator());
        Builder.SetCurrentDebugLocation(getDebugLocFromPHI(*PH));
        auto Res = VisitedBBs.try_emplace(IBB, I);
        if (!Res.second) {
          TreeEntry *OpTE = getOperandEntry(E, I);
          if (OpTE->isGather() || DeletedNodes.contains(OpTE) ||
              TransformedToGatherNodes.contains(OpTE)) {
            Value *VecOp = NewPhi->getIncomingValue(Res.first->getSecond());
            NewPhi->addIncoming(VecOp, IBB);
            assert(!OpTE->VectorizedValue && "Expected no vectorized value.");
            OpTE->VectorizedValue = VecOp;
            // The combined nodes of the reused gather node still must be
            // emitted.
            if (OpTE->isGather() && !DeletedNodes.contains(OpTE))
              for (auto [EIdx, _] : OpTE->CombinedEntriesWithIndices)
                (void)vectorizeTree(VectorizableTree[EIdx].get());
            continue;
          }
        }

        Value *Vec = vectorizeOperand(E, I);
        if (VecTy != Vec->getType()) {
          assert((It != MinBWs.end() || getOperandEntry(E, I)->isGather() ||
                  MinBWs.contains(getOperandEntry(E, I))) &&
                 "Expected item in MinBWs.");
          Vec = Builder.CreateIntCast(Vec, VecTy, GetOperandSignedness(I));
        }
        NewPhi->addIncoming(Vec, IBB);
      }

      assert(NewPhi->getNumIncomingValues() == PH->getNumIncomingValues() &&
             "Invalid number of incoming values");
      assert(E->VectorizedValue && "Expected vectorized value.");
      return E->VectorizedValue;
    }

    case Instruction::ExtractElement: {
      Value *V = E->getSingleOperand(0);
      setInsertPointAfterBundle(E);
      V = FinalShuffle(V, E);
      // Insert the copyable lanes (non-extract scalars modeled on the extract
      // main op) into the reused source vector. The identity extract order and
      // absence of a reuse shuffle are guaranteed when the node is created, so
      // a lane maps to its own index.
      if (E->hasCopyableElements()) {
        assert(E->ReorderIndices.empty() && E->ReuseShuffleIndices.empty() &&
               "Copyable extract lanes require identity order and no reuse.");
        for (auto [Idx, Scalar] : enumerate(E->Scalars))
          if (E->isCopyableElement(Scalar))
            V = Builder.CreateInsertElement(V, Scalar, Builder.getInt32(Idx));
      }
      E->VectorizedValue = V;
      return V;
    }
    case Instruction::ExtractValue: {
      if (!E->StructEVIndices.empty()) {
        setInsertPointAfterBundle(E);
        Value *V = vectorizeOperand(E, 0);
        V = Builder.CreateExtractValue(V, E->StructEVIndices);
        if (auto *I = dyn_cast<Instruction>(V))
          V = ::propagateMetadata(I, E->Scalars);
        V = FinalShuffle(V, E);
        E->VectorizedValue = V;
        return V;
      }
      auto *LI = cast<LoadInst>(E->getSingleOperand(0));
      Builder.SetInsertPoint(LI);
      Value *Ptr = LI->getPointerOperand();
      LoadInst *V = Builder.CreateAlignedLoad(VecTy, Ptr, LI->getAlign());
      Value *NewV = PropagateIRFlags(V);
      NewV = FinalShuffle(NewV, E);
      E->VectorizedValue = NewV;
      return NewV;
    }
    case Instruction::InsertValue:
    case Instruction::InsertElement: {
      assert(E->ReuseShuffleIndices.empty() && "All inserts should be unique");
      if (const TreeEntry *OpE = getOperandEntry(E, 1);
          OpE && !OpE->isGather() && OpE->hasState() &&
          !OpE->hasCopyableElements())
        Builder.SetInsertPoint(cast<Instruction>(E->Scalars.back()));
      else
        setInsertPointAfterBundle(E);
      Value *V = vectorizeOperand(E, 1);
      ArrayRef<Value *> Op = E->getOperand(1);
      Type *ScalarTy = Op.front()->getType();
      if (cast<VectorType>(V->getType())->getElementType() != ScalarTy) {
        assert(ScalarTy->isIntegerTy() && "Expected item in MinBWs.");
        std::pair<unsigned, bool> Res = MinBWs.lookup(getOperandEntry(E, 1));
        assert(Res.first > 0 && "Expected item in MinBWs.");
        V = Builder.CreateIntCast(
            V,
            getWidenedType(
                ScalarTy,
                cast<FixedVectorType>(V->getType())->getNumElements()),
            Res.second);
      }

      // Create InsertVector shuffle if necessary
      auto *FirstInsert = cast<Instruction>(*find_if(E->Scalars, [E](Value *V) {
        return !is_contained(E->Scalars, cast<Instruction>(V)->getOperand(0));
      }));
      const unsigned NumScalars = E->Scalars.size();
      FixedVectorType *SrcVecTy = getInsertBuildVectorSrcTy(E);
      const unsigned NumElts = getNumElements(SrcVecTy);

      unsigned Offset = *getElementIndex(VL0);
      assert(Offset < NumElts && "Failed to find vector index offset");

      // Create shuffle to resize vector
      SmallVector<int> Mask;
      if (!E->ReorderIndices.empty()) {
        inversePermutation(E->ReorderIndices, Mask);
        Mask.append(NumElts - NumScalars, PoisonMaskElem);
      } else {
        Mask.assign(NumElts, PoisonMaskElem);
        std::iota(Mask.begin(), std::next(Mask.begin(), NumScalars), 0);
      }
      // Create InsertVector shuffle if necessary
      bool IsIdentity = true;
      SmallVector<int> PrevMask(NumElts, PoisonMaskElem);
      Mask.swap(PrevMask);
      for (unsigned I = 0; I < NumScalars; ++I) {
        Value *Scalar = E->Scalars[PrevMask[I]];
        unsigned InsertIdx = *getElementIndex(Scalar);
        IsIdentity &= InsertIdx - Offset == I;
        Mask[InsertIdx - Offset] = I;
      }
      if (!IsIdentity || NumElts != NumScalars) {
        Value *V2 = nullptr;
        bool IsVNonPoisonous =
            !isConstant(V) && isGuaranteedNotToBePoison(V, AC);
        SmallVector<int> InsertMask(Mask);
        if (NumElts != NumScalars && Offset == 0) {
          // Follow all insert element instructions from the current buildvector
          // sequence.
          Instruction *Ins = VL0;
          Instruction *Op;
          do {
            std::optional<unsigned> InsertIdx = getElementIndex(Ins);
            if (!InsertIdx)
              break;
            if (InsertMask[*InsertIdx] == PoisonMaskElem)
              InsertMask[*InsertIdx] = *InsertIdx;
            if (!Ins->hasOneUse())
              break;
            Op = Ins;
            Ins = dyn_cast_if_present<Instruction>(
                Ins->getUniqueUndroppableUser());
          } while (Ins && Ins->getOperand(0) == Op);
          SmallBitVector UseMask =
              buildUseMask(NumElts, InsertMask, UseMask::UndefsAsMask);
          SmallBitVector IsFirstPoison =
              isUndefVector<true>(FirstInsert->getOperand(0), UseMask);
          SmallBitVector IsFirstUndef =
              isUndefVector(FirstInsert->getOperand(0), UseMask);
          if (!IsFirstPoison.all()) {
            unsigned Idx = 0;
            for (unsigned I = 0; I < NumElts; I++) {
              if (InsertMask[I] == PoisonMaskElem && !IsFirstPoison.test(I) &&
                  IsFirstUndef.test(I)) {
                if (IsVNonPoisonous) {
                  InsertMask[I] = I < NumScalars ? I : 0;
                  continue;
                }
                if (!V2)
                  V2 = UndefValue::get(V->getType());
                if (Idx >= NumScalars)
                  Idx = NumScalars - 1;
                InsertMask[I] = NumScalars + Idx;
                ++Idx;
              } else if (InsertMask[I] != PoisonMaskElem &&
                         Mask[I] == PoisonMaskElem) {
                InsertMask[I] = PoisonMaskElem;
              }
            }
          } else {
            InsertMask = Mask;
          }
        }
        if (!V2)
          V2 = PoisonValue::get(V->getType());
        V = Builder.CreateShuffleVector(V, V2, InsertMask);
        if (auto *I = dyn_cast<Instruction>(V)) {
          GatherShuffleExtractSeq.insert(I);
          CSEBlocks.insert(I->getParent());
        }
      }

      SmallVector<int> InsertMask(NumElts, PoisonMaskElem);
      for (unsigned I = 0; I < NumElts; I++) {
        if (Mask[I] != PoisonMaskElem)
          InsertMask[Offset + I] = I;
      }
      SmallBitVector UseMask =
          buildUseMask(NumElts, InsertMask, UseMask::UndefsAsMask);
      SmallBitVector IsFirstUndef =
          isUndefVector(FirstInsert->getOperand(0), UseMask);
      if ((!IsIdentity || Offset != 0 || !IsFirstUndef.all()) &&
          NumElts != NumScalars) {
        if (IsFirstUndef.all()) {
          if (!ShuffleVectorInst::isIdentityMask(InsertMask, NumElts)) {
            SmallBitVector IsFirstPoison =
                isUndefVector<true>(FirstInsert->getOperand(0), UseMask);
            if (!IsFirstPoison.all()) {
              for (unsigned I = 0; I < NumElts; I++) {
                if (InsertMask[I] == PoisonMaskElem && !IsFirstPoison.test(I))
                  InsertMask[I] = I + NumElts;
              }
            }
            V = Builder.CreateShuffleVector(
                V,
                IsFirstPoison.all() ? PoisonValue::get(V->getType())
                                    : FirstInsert->getOperand(0),
                InsertMask, cast<Instruction>(E->Scalars.back())->getName());
            if (auto *I = dyn_cast<Instruction>(V)) {
              GatherShuffleExtractSeq.insert(I);
              CSEBlocks.insert(I->getParent());
            }
          }
        } else {
          SmallBitVector IsFirstPoison =
              isUndefVector<true>(FirstInsert->getOperand(0), UseMask);
          for (unsigned I = 0; I < NumElts; I++) {
            if (InsertMask[I] == PoisonMaskElem)
              InsertMask[I] = IsFirstPoison.test(I) ? PoisonMaskElem : I;
            else
              InsertMask[I] += NumElts;
          }
          V = Builder.CreateShuffleVector(
              FirstInsert->getOperand(0), V, InsertMask,
              cast<Instruction>(E->Scalars.back())->getName());
          if (auto *I = dyn_cast<Instruction>(V)) {
            GatherShuffleExtractSeq.insert(I);
            CSEBlocks.insert(I->getParent());
          }
        }
      }

      ++NumVectorInstructions;
      if (ShuffleOrOp == Instruction::InsertValue &&
          !canVectorStoreInsertValue(E)) {
        Type *AggTy = E->getMainOp()->getType();
        Align SlotAlign = std::max(DL->getPrefTypeAlign(V->getType()),
                                   DL->getPrefTypeAlign(AggTy));
        AllocaInst *Slot;
        {
          // Keep the alloca in the function entry block so it is not executed
          // (and does not grow the stack) on every iteration of a loop.
          IRBuilderBase::InsertPointGuard Guard(Builder);
          Builder.SetInsertPointPastAllocas(F);
          Slot = Builder.CreateAlloca(AggTy, /*ArraySize=*/nullptr,
                                      "vec2struct.slot");
          Slot->setAlignment(SlotAlign);
        }
        (void)Builder.CreateAlignedStore(V, Slot, SlotAlign);
        V = Builder.CreateAlignedLoad(AggTy, Slot, SlotAlign, "vec2struct");
        NumVectorInstructions += 2;
      }
      E->VectorizedValue = V;
      return V;
    }
    case Instruction::ZExt:
    case Instruction::SExt:
    case Instruction::FPToUI:
    case Instruction::FPToSI:
    case Instruction::FPExt:
    case Instruction::PtrToInt:
    case Instruction::PtrToAddr:
    case Instruction::IntToPtr:
    case Instruction::SIToFP:
    case Instruction::UIToFP:
    case Instruction::Trunc:
    case Instruction::FPTrunc:
    case Instruction::BitCast: {
      setInsertPointAfterBundle(E);

      Value *InVec = vectorizeOperand(E, 0);

      auto *CI = cast<CastInst>(VL0);
      Instruction::CastOps VecOpcode = CI->getOpcode();
      Type *SrcScalarTy = cast<VectorType>(InVec->getType())->getElementType();
      auto SrcIt = MinBWs.find(getOperandEntry(E, 0));
      if (SrcIt != MinBWs.end() &&
          (VecOpcode == Instruction::IntToPtr ||
           (SrcIt->second.second && (VecOpcode == Instruction::UIToFP ||
                                     VecOpcode == Instruction::ZExt)))) {
        InVec = Builder.CreateIntCast(
            InVec, getWidenedType(CI->getSrcTy(), E->Scalars.size()),
            SrcIt->second.second);
        SrcScalarTy = CI->getSrcTy()->getScalarType();
        SrcIt = MinBWs.end();
      }
      if (!ScalarTy->isFPOrFPVectorTy() && !SrcScalarTy->isFPOrFPVectorTy() &&
          (SrcIt != MinBWs.end() || It != MinBWs.end() ||
           SrcScalarTy != CI->getOperand(0)->getType()->getScalarType())) {
        // Check if the values are candidates to demote.
        unsigned SrcBWSz = DL->getTypeSizeInBits(SrcScalarTy);
        if (SrcIt != MinBWs.end())
          SrcBWSz = SrcIt->second.first;
        unsigned BWSz = DL->getTypeSizeInBits(ScalarTy->getScalarType());
        if (BWSz == SrcBWSz) {
          VecOpcode = Instruction::BitCast;
        } else if (BWSz < SrcBWSz) {
          VecOpcode = Instruction::Trunc;
        } else if (It != MinBWs.end()) {
          assert(BWSz > SrcBWSz && "Invalid cast!");
          VecOpcode = It->second.second ? Instruction::SExt : Instruction::ZExt;
        } else if (SrcIt != MinBWs.end()) {
          assert(BWSz > SrcBWSz && "Invalid cast!");
          VecOpcode =
              SrcIt->second.second ? Instruction::SExt : Instruction::ZExt;
        }
      } else if (VecOpcode == Instruction::SIToFP && SrcIt != MinBWs.end() &&
                 !SrcIt->second.second) {
        VecOpcode = Instruction::UIToFP;
      } else if (VecOpcode == Instruction::BitCast && SrcIt != MinBWs.end() &&
                 ScalarTy->isFPOrFPVectorTy()) {
        Type *OrigSrcScalarTy = CI->getSrcTy();
        auto *OrigSrcVectorTy =
            getWidenedType(OrigSrcScalarTy, E->Scalars.size());
        InVec =
            Builder.CreateIntCast(InVec, OrigSrcVectorTy, SrcIt->second.second);
      }
      Value *V = (VecOpcode != ShuffleOrOp && VecOpcode == Instruction::BitCast)
                     ? InVec
                     : Builder.CreateCast(VecOpcode, InVec, VecTy);
      V = FinalShuffle(V, E);

      E->VectorizedValue = V;
      ++NumVectorInstructions;
      return V;
    }
    case Instruction::FCmp:
    case Instruction::ICmp: {
      setInsertPointAfterBundle(E);

      Value *L = vectorizeOperand(E, 0);
      Value *R = vectorizeOperand(E, 1);
      if (L->getType() != R->getType()) {
        assert((getOperandEntry(E, 0)->isGather() ||
                getOperandEntry(E, 1)->isGather() ||
                MinBWs.contains(getOperandEntry(E, 0)) ||
                MinBWs.contains(getOperandEntry(E, 1))) &&
               "Expected item in MinBWs.");
        const unsigned LBW = cast<VectorType>(L->getType())
                                 ->getElementType()
                                 ->getIntegerBitWidth();
        const unsigned RBW = cast<VectorType>(R->getType())
                                 ->getElementType()
                                 ->getIntegerBitWidth();
        // A signed comparison needs the sign bit getActiveBits() ignores.
        const bool Signed = cast<CmpInst>(VL0)->isSigned();
        auto GetRequiredBits = [Signed](const APInt &V) {
          return Signed ? V.getSignificantBits() : V.getActiveBits();
        };
        if ((LBW < RBW && (!allConstant(E->getOperand(1)) ||
                           any_of(
                               E->getOperand(1),
                               [&](Value *V) {
                                 auto *CI = dyn_cast<ConstantInt>(V);
                                 return !CI ||
                                        GetRequiredBits(CI->getValue()) > LBW;
                               }))) ||
            (LBW > RBW && allConstant(E->getOperand(0)) &&
             all_of(E->getOperand(1), [&](Value *V) {
               auto *CI = dyn_cast<ConstantInt>(V);
               return CI && GetRequiredBits(CI->getValue()) <= RBW;
             }))) {
          Type *CastTy = R->getType();
          L = Builder.CreateIntCast(L, CastTy, GetOperandSignedness(0));
        } else {
          Type *CastTy = L->getType();
          R = Builder.CreateIntCast(R, CastTy, GetOperandSignedness(1));
        }
      }

      CmpInst::Predicate P0 = cast<CmpInst>(VL0)->getPredicate();
      // The bit tests compare and L, R with 0, the eq bit tests compare the
      // trunc X to i1 lanes with 1, exactly in the narrowed type.
      const bool IsBitTest = any_of(E->Scalars, IsaPred<TruncInst>);
      if (IsBitTest) {
        L = Builder.CreateAnd(L, R);
        const bool IsEq =
            CmpSamePredicateHelper::canConvertTo(VL0, CmpInst::ICMP_EQ);
        P0 = IsEq ? CmpInst::ICMP_EQ : CmpInst::ICMP_NE;
        Type *EltTy = L->getType()->getScalarType();
        SmallVector<Constant *> Consts;
        for (Value *V : E->Scalars)
          Consts.append(getNumElements(VL0->getType()),
                        ConstantInt::get(EltTy, IsEq && isa<TruncInst>(V)));
        R = ConstantVector::get(Consts);
      }
      // A compare with both operands narrowed to the same type preserves the
      // result only if the predicate matches the operand signedness: signed
      // predicates need both operands sign-extended from the narrow type,
      // unsigned predicates need both zero-extended, equality needs the same
      // extension on both sides; operands with a known-zero narrow sign bit
      // match any predicate. Otherwise, extend the operands back to the
      // original compared type.
      auto *LTy = cast<FixedVectorType>(L->getType());
      auto *OrigOpTy =
          dyn_cast<IntegerType>(VL0->getOperand(0)->getType()->getScalarType());
      if (!IsBitTest && OrigOpTy && L->getType() == R->getType() &&
          LTy->getElementType()->getIntegerBitWidth() <
              OrigOpTy->getBitWidth()) {
        bool IsSigned0 = GetOperandSignedness(0);
        bool IsSigned1 = GetOperandSignedness(1);
        bool NonNeg0 = isKnownNonNegative(L, SimplifyQuery(*DL));
        bool NonNeg1 = isKnownNonNegative(R, SimplifyQuery(*DL));
        bool KeepNarrowTy;
        if (ICmpInst::isSigned(P0))
          KeepNarrowTy = (IsSigned0 || NonNeg0) && (IsSigned1 || NonNeg1);
        else if (ICmpInst::isUnsigned(P0))
          KeepNarrowTy = (!IsSigned0 || NonNeg0) && (!IsSigned1 || NonNeg1);
        else
          KeepNarrowTy = IsSigned0 == IsSigned1 || NonNeg0 || NonNeg1;
        if (!KeepNarrowTy) {
          Type *CastTy = getWidenedType(OrigOpTy, LTy->getNumElements());
          L = Builder.CreateIntCast(L, CastTy, IsSigned0);
          R = Builder.CreateIntCast(R, CastTy, IsSigned1);
        }
      }

      // A booleanized zero-test leaf emits no comparison: its value is the
      // wide operand vector, and the i1 lanes are restored by the trunc at
      // the booleanized user node. (Trunc leaves are no-ops after the generic
      // MinBWs cast processing.)
      bool IsBooleanized = isBooleanizedNode(E);
      Value *V = IsBooleanized
                     ? (all_of(E->getOperand(0),
                               [](Value *V) { return match(V, m_Zero()); })
                            ? R
                            : L)
                     : Builder.CreateCmp(P0, L, R);
      if (!IsBooleanized)
        V = PropagateIRFlags(V);
      // Do not cast for cmps.
      VecTy = cast<FixedVectorType>(V->getType());
      V = FinalShuffle(V, E);

      E->VectorizedValue = V;
      ++NumVectorInstructions;
      return V;
    }
    case Instruction::Select: {
      setInsertPointAfterBundle(E);

      Value *Cond = vectorizeOperand(E, 0);
      Value *True = vectorizeOperand(E, 1);
      Value *False = vectorizeOperand(E, 2);
      if (True->getType() != VecTy || False->getType() != VecTy) {
        assert((It != MinBWs.end() || getOperandEntry(E, 1)->isGather() ||
                getOperandEntry(E, 2)->isGather() ||
                MinBWs.contains(getOperandEntry(E, 1)) ||
                MinBWs.contains(getOperandEntry(E, 2))) &&
               "Expected item in MinBWs.");
        if (True->getType() != VecTy)
          True = Builder.CreateIntCast(True, VecTy, GetOperandSignedness(1));
        if (False->getType() != VecTy)
          False = Builder.CreateIntCast(False, VecTy, GetOperandSignedness(2));
      }

      unsigned CondNumElements = getNumElements(Cond->getType());
      unsigned TrueNumElements = getNumElements(True->getType());
      assert(TrueNumElements >= CondNumElements &&
             TrueNumElements % CondNumElements == 0 &&
             "Cannot vectorize Instruction::Select");
      assert(TrueNumElements == getNumElements(False->getType()) &&
             "Cannot vectorize Instruction::Select");
      if (CondNumElements != TrueNumElements) {
        // When the return type is i1 but the source is fixed vector type, we
        // need to duplicate the condition value.
        Cond = Builder.CreateShuffleVector(
            Cond, createReplicatedMask(TrueNumElements / CondNumElements,
                                       CondNumElements));
      }
      assert(getNumElements(Cond->getType()) == TrueNumElements &&
             "Cannot vectorize Instruction::Select");
      Value *V =
          Builder.CreateSelectWithUnknownProfile(Cond, True, False, DEBUG_TYPE);
      V = FinalShuffle(V, E);

      E->VectorizedValue = V;
      ++NumVectorInstructions;
      return V;
    }
    case Instruction::FNeg: {
      setInsertPointAfterBundle(E);

      Value *Op = vectorizeOperand(E, 0);

      Value *V = Builder.CreateUnOp(
          static_cast<Instruction::UnaryOps>(E->getOpcode()), Op);
      V = PropagateIRFlags(V);

      V = FinalShuffle(V, E);

      E->VectorizedValue = V;
      ++NumVectorInstructions;

      return V;
    }
    case Instruction::Freeze: {
      setInsertPointAfterBundle(E);

      Value *Op = vectorizeOperand(E, 0);

      if (Op->getType() != VecTy) {
        assert((It != MinBWs.end() || getOperandEntry(E, 0)->isGather() ||
                MinBWs.contains(getOperandEntry(E, 0))) &&
               "Expected item in MinBWs.");
        Op = Builder.CreateIntCast(Op, VecTy, GetOperandSignedness(0));
      }
      Value *V = Builder.CreateFreeze(Op);
      V = FinalShuffle(V, E);

      E->VectorizedValue = V;
      ++NumVectorInstructions;

      return V;
    }
    case Instruction::Add:
    case Instruction::FAdd:
    case Instruction::Sub:
    case Instruction::FSub:
    case Instruction::Mul:
    case Instruction::FMul:
    case Instruction::UDiv:
    case Instruction::SDiv:
    case Instruction::FDiv:
    case Instruction::URem:
    case Instruction::SRem:
    case Instruction::FRem:
    case Instruction::Shl:
    case Instruction::LShr:
    case Instruction::AShr:
    case Instruction::And:
    case Instruction::Or:
    case Instruction::Xor: {
      setInsertPointAfterBundle(E);

      // The lanes with the absorbing constant use poison as the other operand.
      // Freeze the operand, if it may be poison, to keep these lanes equal to
      // the constant.
      auto FreezePlaceholders = [&](Value *Op, unsigned OpIdx) {
        if (!E->hasCopyableElements() ||
            none_of(zip(E->Scalars, E->getOperand(OpIdx)),
                    [&](const auto &P) {
                      auto [Scalar, OpScalar] = P;
                      return E->isCopyableElement(Scalar) &&
                             !isa<UndefValue>(Scalar) &&
                             isa<UndefValue>(OpScalar);
                    }) ||
            isGuaranteedNotToBePoison(Op, AC))
          return Op;
        return Builder.CreateFreeze(Op);
      };

      if (E->hasReassocScalars()) {
        // Vectorize operand columns, then combine pairwise in a balanced
        // tree; negated columns (flattened subtracts) are subtracted from
        // the positive total at the end.
        SmallVector<Value *> CombinedScalars = to_vector(E->Scalars);
        append_range(CombinedScalars, E->getReassocScalars());
        // Reuse flags when a combine exactly matches a subsumed scalar pair.
        // Commutative scalars are keyed operand-order independently,
        // subtracts keep their operand order.
        auto MakeOperandKey = [](Value *A, Value *B, unsigned Opcode) {
          return Instruction::isCommutative(Opcode) && B < A
                     ? std::make_pair(B, A)
                     : std::make_pair(A, B);
        };
        SmallDenseMap<std::pair<std::pair<Value *, Value *>, unsigned>,
                      SmallVector<Instruction *, 1>>
            ByOperands;
        // Copyable leaves are used as-is, they are never combine targets.
        for (Value *V : make_filter_range(CombinedScalars, [&](Value *V) {
               return !E->isCopyableElement(V);
             })) {
          auto *I = cast<Instruction>(V);
          const unsigned Opcode = I->getOpcode();
          ByOperands[{MakeOperandKey(I->getOperand(0), I->getOperand(1),
                                     Opcode),
                      Opcode}]
              .push_back(I);
        }
        const unsigned CombineOpcode = getReassocCombineOpcode(E->getOpcode());
        // Cast operand columns to VecTy when bit-width demotion changed types.
        auto GetCastOperand = [&](unsigned Idx, Value *Op) {
          if (Op->getType() == VecTy)
            return Op;
          return Builder.CreateIntCast(Op, VecTy, GetOperandSignedness(Idx));
        };
        SmallVector<Value *> Ops;
        SmallVector<Value *> NegOps;
        // Track which scalar each partial result still represents for flag
        // reuse.
        SmallVector<SmallVector<Value *>> ScalarOps;
        SmallVector<SmallVector<Value *>> NegScalarOps;
        for (unsigned Idx : seq<unsigned>(E->getNumOperands())) {
          // Identity-only columns combine to a no-op; skip them rather than
          // emitting a real binop against an identity vector.
          if (all_of(E->getOperand(Idx), [&](Value *V) {
                return isBinOpIdentityConstant(V, CombineOpcode);
              }))
            continue;
          const bool Negated = E->isReassocNegatedOp(Idx);
          (Negated ? NegOps : Ops)
              .push_back(GetCastOperand(
                  Idx, FreezePlaceholders(vectorizeOperand(E, Idx), Idx)));
          (Negated ? NegScalarOps : ScalarOps)
              .emplace_back(E->getOperand(Idx).begin(),
                            E->getOperand(Idx).end());
        }
        const bool HasNegatedOps = !NegOps.empty();
        // Check whether combining the partial results of \p LHSScalars and
        // \p RHSScalars reproduces a subsumed scalar pair lane by lane, so
        // the matched scalars' flags can be reused. Fills per-lane
        // representatives for the next combine round on an exact match.
        auto TryExactCombine =
            [&](Value *Combined, unsigned Opcode, ArrayRef<Value *> LHSScalars,
                ArrayRef<Value *> RHSScalars,
                SmallVectorImpl<Value *> &Representatives) -> Value * {
          // Either side may be empty after a non-exact combine.
          if (LHSScalars.empty() || LHSScalars.size() != RHSScalars.size())
            return nullptr;
          SmallVector<Value *> ExactMatches;
          Representatives.resize(LHSScalars.size());
          bool IsExact =
              all_of(seq<unsigned>(LHSScalars.size()), [&](unsigned Lane) {
                if (!LHSScalars[Lane] || !RHSScalars[Lane])
                  return false;
                auto It = ByOperands.find(
                    {MakeOperandKey(LHSScalars[Lane], RHSScalars[Lane], Opcode),
                     Opcode});
                if (It == ByOperands.end())
                  return false;
                append_range(ExactMatches, It->second);
                Representatives[Lane] = It->second.front();
                return true;
              });
          if (!IsExact)
            return nullptr;
          return PropagateIRFlags(Combined, Opcode, ExactMatches);
        };
        auto CombineFallback = [&](Value *Combined, unsigned Opcode) {
          Value *V = PropagateIRFlags(Combined, Opcode, CombinedScalars);
          // Drop overflow/fast-math flags not proven exact; regrouping can
          // invalidate nsw/nuw and nnan/ninf even when each step was safe.
          // nuw is kept for pure add trees only: a negated leaf can make a
          // re-paired partial sum exceed the original running total.
          auto *CombinedI = dyn_cast<Instruction>(V);
          if (!CombinedI)
            return V;
          if (isa<FPBinaryOperator>(CombinedI)) {
            CombinedI->setHasNoNaNs(false);
            CombinedI->setHasNoInfs(false);
          } else if (isa<OverflowingBinaryOperator>(CombinedI)) {
            CombinedI->setHasNoSignedWrap(false);
            if (Opcode != Instruction::Add || HasNegatedOps)
              CombinedI->setHasNoUnsignedWrap(false);
          }
          return V;
        };
        // Combine the group columns pairwise in a balanced tree and return
        // the total with the per-lane scalars it still represents.
        auto CombineColumns =
            [&](SmallVector<Value *> GroupOps,
                SmallVector<SmallVector<Value *>> GroupScalarOps,
                unsigned Opcode) -> std::pair<Value *, SmallVector<Value *>> {
          while (GroupOps.size() > 1) {
            SmallVector<Value *> NextOps((GroupOps.size() + 1) / 2);
            SmallVector<SmallVector<Value *>> NextScalarOps(NextOps.size());
            for (unsigned Idx : seq<unsigned>(NextOps.size())) {
              if (2 * Idx + 1 == GroupOps.size()) {
                // Odd one out this round: carry it over unpaired.
                NextOps[Idx] = GroupOps[2 * Idx];
                NextScalarOps[Idx] = std::move(GroupScalarOps[2 * Idx]);
                continue;
              }
              Value *Combined = Builder.CreateBinOp(
                  static_cast<Instruction::BinaryOps>(Opcode),
                  GroupOps[2 * Idx], GroupOps[2 * Idx + 1]);
              // Check whether this combine exactly matches a subsumed
              // scalar.
              SmallVector<Value *> Representatives;
              if (Value *Exact = TryExactCombine(
                      Combined, Opcode, GroupScalarOps[2 * Idx],
                      GroupScalarOps[2 * Idx + 1], Representatives)) {
                NextOps[Idx] = Exact;
                NextScalarOps[Idx] = std::move(Representatives);
                continue;
              }
              NextOps[Idx] = CombineFallback(Combined, Opcode);
              // No scalar match: deeper combines from this result cannot be
              // exact.
            }
            GroupOps = std::move(NextOps);
            GroupScalarOps = std::move(NextScalarOps);
          }
          return {GroupOps.front(), GroupScalarOps.front()};
        };
        // -(a+b) differs from -a + -b in the sign of a zero result, so the
        // negated columns are summed only for integers or with nsz on every
        // link; without it each is subtracted in turn.
        const bool CanSumNegated =
            CombineOpcode != Instruction::FAdd ||
            all_of(make_isa_range<Instruction>(CombinedScalars),
                   [&](Instruction *I) {
                     return E->isCopyableElement(I) || I->hasNoSignedZeros();
                   });
        const unsigned SubOpcode = CombineOpcode == Instruction::FAdd
                                       ? Instruction::FSub
                                       : Instruction::Sub;
        Value *V;
        SmallVector<Value *> PosReps;
        if (Ops.empty()) {
          // Every positive column was an identity: the total is the identity.
          V = ConstantExpr::getBinOpIdentity(CombineOpcode, VecTy);
        } else {
          std::tie(V, PosReps) = CombineColumns(
              std::move(Ops), std::move(ScalarOps), CombineOpcode);
        }
        if (CanSumNegated && !NegOps.empty()) {
          auto [NegTotal, NegReps] = CombineColumns(
              std::move(NegOps), std::move(NegScalarOps), CombineOpcode);
          NegOps = {NegTotal};
          NegScalarOps.clear();
          NegScalarOps.push_back(std::move(NegReps));
        }
        for (auto [NegOp, NegScalars] : zip(NegOps, NegScalarOps)) {
          Value *Combined = Builder.CreateBinOp(
              static_cast<Instruction::BinaryOps>(SubOpcode), V, NegOp);
          SmallVector<Value *> NextReps;
          if (Value *Exact = TryExactCombine(Combined, SubOpcode, PosReps,
                                             NegScalars, NextReps)) {
            V = Exact;
            PosReps = std::move(NextReps);
            continue;
          }
          V = CombineFallback(Combined, SubOpcode);
          PosReps.clear();
        }
        V = FinalShuffle(V, E);
        E->VectorizedValue = V;
        ++NumVectorInstructions;
        return V;
      }

      Value *LHS = vectorizeOperand(E, 0);
      Value *RHS = vectorizeOperand(E, 1);
      if (ShuffleOrOp == Instruction::And && It != MinBWs.end()) {
        assert(E->getNumOperands() == 2 && "Expected exactly 2 operands.");
        for (unsigned I : seq<unsigned>(0, E->getNumOperands())) {
          ArrayRef<Value *> Ops = E->getOperand(I);
          if (all_of(Ops, [&](Value *Op) {
                auto *CI = dyn_cast<ConstantInt>(Op);
                return CI && CI->getValue().countr_one() >= It->second.first;
              })) {
            V = FinalShuffle(I == 0 ? RHS : LHS, E);
            E->VectorizedValue = V;
            ++NumVectorInstructions;
            return V;
          }
        }
      }
      LHS = FreezePlaceholders(LHS, 0);
      RHS = FreezePlaceholders(RHS, 1);
      if (LHS->getType() != VecTy || RHS->getType() != VecTy) {
        assert((It != MinBWs.end() || getOperandEntry(E, 0)->isGather() ||
                getOperandEntry(E, 1)->isGather() ||
                MinBWs.contains(getOperandEntry(E, 0)) ||
                MinBWs.contains(getOperandEntry(E, 1))) &&
               "Expected item in MinBWs.");
        if (LHS->getType() != VecTy)
          LHS = Builder.CreateIntCast(LHS, VecTy, GetOperandSignedness(0));
        if (RHS->getType() != VecTy)
          RHS = Builder.CreateIntCast(RHS, VecTy, GetOperandSignedness(1));
      }

      // Structural padding does not imply profitability; re-check the cost
      // here so codegen matches the earlier cost-based decision.
      Value *V = nullptr;
      unsigned NumElts = E->Scalars.size();
      FixedVectorType *PaddedVecTy = nullptr;
      if (getMaskedDivRemCost(*TTI, Opts.slp_revec, ShuffleOrOp, ScalarTy,
                              NumElts, CostKind, &PaddedVecTy)
              .isValid()) {
        assert(PaddedVecTy && "Expected padded type for masked div/rem.");
        // Scale the lane count up to elements for REVEC, where each lane
        // is itself a vector.
        unsigned NumActiveElts = NumElts * getNumElements(ScalarTy);
        Value *WidenedLHS =
            createInsertVector(Builder, PoisonValue::get(PaddedVecTy), LHS, 0);
        Value *WidenedRHS =
            createInsertVector(Builder, PoisonValue::get(PaddedVecTy), RHS, 0);
        SmallVector<Constant *> MaskValues(
            PaddedVecTy->getNumElements(),
            ConstantInt::getFalse(Builder.getContext()));
        std::fill_n(MaskValues.begin(), NumActiveElts,
                    ConstantInt::getTrue(Builder.getContext()));
        Value *DivRemMask = ConstantVector::get(MaskValues);
        Value *MaskedV = Builder.CreateIntrinsic(
            getMaskedDivRemIntrinsic(ShuffleOrOp), {PaddedVecTy},
            {WidenedLHS, WidenedRHS, DivRemMask});
        V = createExtractVector(Builder, MaskedV, NumActiveElts, 0);
      }
      if (!V)
        V = Builder.CreateBinOp(
            static_cast<Instruction::BinaryOps>(E->getOpcode()), LHS, RHS);
      V = PropagateIRFlags(V);

      V = FinalShuffle(V, E);

      E->VectorizedValue = V;
      ++NumVectorInstructions;

      return V;
    }
    case Instruction::Load: {
      // Loads are inserted at the head of the tree because we don't want to
      // sink them all the way down past store instructions.
      setInsertPointAfterBundle(E);

      LoadInst *LI = cast<LoadInst>(VL0);
      Instruction *NewLI;
      FixedVectorType *StridedLoadTy = nullptr;
      Value *PO = LI->getPointerOperand();
      if (E->State == TreeEntry::Vectorize) {
        const uint64_t Shift = getVectorLoadShift(E->Scalars);
        if (Shift)
          PO = Builder.CreatePtrAdd(
              PO, ConstantInt::getSigned(DL->getIndexType(PO->getType()),
                                         -static_cast<int64_t>(Shift)));
        NewLI = Builder.CreateAlignedLoad(
            VecTy, PO, commonAlignment(LI->getAlign(), Shift));
      } else if (E->State == TreeEntry::CompressVectorize) {
        auto [CompressMask, LoadVecTy, InterleaveFactor, IsMasked] =
            CompressEntryToData.at(E);
        Align CommonAlignment = LI->getAlign();
        if (IsMasked) {
          unsigned VF = getNumElements(LoadVecTy);
          SmallVector<Constant *> MaskValues(
              VF / getNumElements(LI->getType()),
              ConstantInt::getFalse(VecTy->getContext()));
          for (int I : CompressMask)
            MaskValues[I] = ConstantInt::getTrue(VecTy->getContext());
          if (auto *VecTy = dyn_cast<FixedVectorType>(LI->getType())) {
            assert(Opts.slp_revec && "Only supported by REVEC.");
            MaskValues = replicateMask(MaskValues, VecTy->getNumElements());
          }
          Constant *MaskValue = ConstantVector::get(MaskValues);
          NewLI = Builder.CreateMaskedLoad(LoadVecTy, PO, CommonAlignment,
                                           MaskValue);
        } else {
          NewLI = Builder.CreateAlignedLoad(LoadVecTy, PO, CommonAlignment);
        }
        NewLI = cast<Instruction>(PropagateIRFlags(NewLI));
        // TODO: include this cost into CommonCost.
        if (auto *VecTy = dyn_cast<FixedVectorType>(LI->getType())) {
          assert(Opts.slp_revec && "FixedVectorType is not expected.");
          transformScalarShuffleIndiciesToVector(VecTy->getNumElements(),
                                                 CompressMask);
        }
        NewLI =
            cast<Instruction>(Builder.CreateShuffleVector(NewLI, CompressMask));
      } else if (E->State == TreeEntry::StridedVectorize) {
        Value *Ptr0 = cast<LoadInst>(E->Scalars.front())->getPointerOperand();
        Value *PtrN = cast<LoadInst>(E->Scalars.back())->getPointerOperand();
        PO = IsReverseOrder ? PtrN : Ptr0;
        Type *StrideTy = DL->getIndexType(PO->getType());
        Value *StrideVal;
        const StridedPtrInfo &SPtrInfo = TreeEntryToStridedPtrInfoMap.at(E);
        StridedLoadTy = SPtrInfo.Ty;
        assert(StridedLoadTy && "Missing StridedPointerInfo for tree entry.");
        unsigned StridedLoadEC =
            StridedLoadTy->getElementCount().getKnownMinValue();

        Value *Stride = SPtrInfo.StrideVal;
        if (!Stride) {
          const SCEV *StrideSCEV = SPtrInfo.StrideSCEV;
          assert(StrideSCEV && "Neither StrideVal nor StrideSCEV were set.");
          SCEVExpander Expander(*SE, "strided-load-vec");
          Stride = Expander.expandCodeFor(StrideSCEV, StrideSCEV->getType(),
                                          &*Builder.GetInsertPoint());
        }
        Value *NewStride =
            Builder.CreateIntCast(Stride, StrideTy, /*isSigned=*/true);
        StrideVal = Builder.CreateMul(
            NewStride, ConstantInt::getSigned(
                           StrideTy, (IsReverseOrder ? -1 : 1) *
                                         static_cast<int>(
                                             DL->getTypeAllocSize(ScalarTy))));
        Align CommonAlignment = computeCommonAlignment<LoadInst>(E->Scalars);
        auto *Inst = Builder.CreateIntrinsicWithoutFolding(
            Intrinsic::experimental_vp_strided_load,
            {StridedLoadTy, PO->getType(), StrideTy},
            {PO, StrideVal,
             Builder.getAllOnesMask(ElementCount::getFixed(StridedLoadEC)),
             Builder.getInt32(StridedLoadEC)});
        Inst->addParamAttr(
            /*ArgNo=*/0,
            Attribute::getWithAlignment(Inst->getContext(), CommonAlignment));
        NewLI = Inst;
      } else if (E->State == TreeEntry::BlendedLoadVectorize) {
        // Two masked loads from the candidate bases, blended by the vectorized
        // per-lane condition operand. E->Scalars stays in natural lane order,
        // so the contiguous loads line up with the mask; ReorderIndices, if
        // any, is applied below by the shared FinalShuffle.
        Value *P0 = cast<LoadInst>(E->Scalars.front())->getPointerOperand();
        if (auto *GEP = dyn_cast<GetElementPtrInst>(P0))
          P0 = GEP->getPointerOperand();
        auto *Sel = cast<SelectInst>(P0);
        Align CommonAlignment =
            computeBlendedLoadBaseAlignment(E->Scalars, *DL);
        Value *BlendMask = vectorizeOperand(E, 0);
        // Place the loads at the bundle head, not at the mask, so they are not
        // hoisted above an aliasing store.
        setInsertPointAfterBundle(E);
        Value *NotMask = Builder.CreateNot(BlendMask);
        Value *VecPoison = PoisonValue::get(VecTy);
        Value *TrueVal = Builder.CreateMaskedLoad(
            VecTy, Sel->getTrueValue(), CommonAlignment, BlendMask, VecPoison);
        Value *FalseVal = Builder.CreateMaskedLoad(
            VecTy, Sel->getFalseValue(), CommonAlignment, NotMask, VecPoison);
        NewLI = cast<Instruction>(
            Builder.CreateSelect(BlendMask, TrueVal, FalseVal));
      } else {
        assert(E->State == TreeEntry::ScatterVectorize && "Unhandled state");
        Value *VecPtr = vectorizeOperand(E, 0);
        if (isa<FixedVectorType>(ScalarTy)) {
          assert(Opts.slp_revec && "FixedVectorType is not expected.");
          // CreateMaskedGather expects VecTy and VecPtr have same size. We need
          // to expand VecPtr if ScalarTy is a vector type.
          unsigned ScalarTyNumElements = getNumElements(ScalarTy);
          unsigned VecTyNumElements = getNumElements(VecTy);
          assert(VecTyNumElements % ScalarTyNumElements == 0 &&
                 "Cannot expand getelementptr.");
          unsigned VF = VecTyNumElements / ScalarTyNumElements;
          SmallVector<Constant *> Indices(VecTyNumElements);
          transform(seq(VecTyNumElements), Indices.begin(), [=](unsigned I) {
            return Builder.getInt64(I % ScalarTyNumElements);
          });
          VecPtr = Builder.CreateGEP(
              toScalarizedTy(VecTy),
              Builder.CreateShuffleVector(
                  VecPtr, createReplicatedMask(ScalarTyNumElements, VF)),
              ConstantVector::get(Indices));
        }
        // Use the minimum alignment of the gathered loads.
        Align CommonAlignment = computeCommonAlignment<LoadInst>(E->Scalars);
        NewLI = Builder.CreateMaskedGather(VecTy, VecPtr, CommonAlignment);
      }
      // The wide load also reads the memory of the undef and poison lanes, so
      // the metadata of the scalar loads does not apply.
      const bool HasUndefLanes = any_of(E->Scalars, IsaPred<UndefValue>);
      Value *V = (E->State == TreeEntry::CompressVectorize ||
                  E->State == TreeEntry::BlendedLoadVectorize || HasUndefLanes)
                     ? NewLI
                     : PropagateIRFlags(NewLI);

      if (StridedLoadTy != VecTy)
        V = createWidenedStridedCast(Builder, V, VecTy, *DL);
      // The memory of the undef and poison lanes may hold poison, but these
      // lanes may be used, so they must not be poison.
      if (HasUndefLanes)
        V = Builder.CreateFreeze(V);
      V = FinalShuffle(V, E);
      E->VectorizedValue = V;
      ++NumVectorInstructions;
      return V;
    }
    case Instruction::Store: {
      auto *SI = cast<StoreInst>(VL0);

      setInsertPointAfterBundle(E);

      Value *VecValue = vectorizeOperand(E, 0);
      if (VecValue->getType() != VecTy)
        VecValue =
            Builder.CreateIntCast(VecValue, VecTy, GetOperandSignedness(0));
      VecValue = FinalShuffle(VecValue, E);

      Value *Ptr = SI->getPointerOperand();
      Instruction *ST;
      if (E->State == TreeEntry::Vectorize) {
        ST = Builder.CreateAlignedStore(VecValue, Ptr, SI->getAlign());
      } else if (E->State == TreeEntry::ExpandVectorize) {
        const StridedPtrInfo &SPtrInfo = TreeEntryToStridedPtrInfoMap.at(E);
        FixedVectorType *StridedStoreTy = SPtrInfo.Ty;
        assert(StridedStoreTy && "Missing StridedPointerInfo for tree entry.");
        Align CommonAlignment = computeCommonAlignment<StoreInst>(E->Scalars);
        ArrayRef<int> ExpandMask = E->ReuseShuffleIndices;
        unsigned VecNumElts = getNumElements(StridedStoreTy);
        assert(VecValue->getType() == StridedStoreTy &&
               "FinalShuffle must expand the value to the masked store type.");
        assert(ExpandMask.size() == VecNumElts &&
               "Reuse mask must match the masked store type.");
        Value *BasePtr =
            cast<StoreInst>(E->Scalars.front())->getPointerOperand();
        SmallVector<Constant *> MaskValues(
            VecNumElts, ConstantInt::getFalse(VecTy->getContext()));
        for (unsigned I : seq<unsigned>(VecNumElts))
          if (ExpandMask[I] != PoisonMaskElem)
            MaskValues[I] = ConstantInt::getTrue(VecTy->getContext());
        ST = Builder.CreateMaskedStore(VecValue, BasePtr, CommonAlignment,
                                       ConstantVector::get(MaskValues));
      } else {
        assert(E->State == TreeEntry::StridedVectorize &&
               "Expected either strided, masked or consecutive stores.");
        bool IsReverseOrder = E->isReverse();
        if (IsReverseOrder) {
          SI = cast<StoreInst>(E->Scalars[E->ReorderIndices.front()]);
          Ptr = SI->getPointerOperand();
        }
        Align CommonAlignment = computeCommonAlignment<StoreInst>(E->Scalars);
        Type *StrideTy = DL->getIndexType(SI->getPointerOperandType());

        const StridedPtrInfo &SPtrInfo = TreeEntryToStridedPtrInfoMap.at(E);
        FixedVectorType *StridedStoreTy = SPtrInfo.Ty;
        assert(StridedStoreTy && "Missing StridedPointerInfo for tree entry.");
        unsigned StridedStoreEC = getNumElements(StridedStoreTy);
        Value *Stride = SPtrInfo.StrideVal;
        assert(Stride && "Missing StridedPointerInfo for tree entry.");
        Value *StrideVal =
            Builder.CreateIntCast(Stride, StrideTy, /*isSigned=*/true);
        // vp_strided_store::stride is defined in bytes
        StrideVal = Builder.CreateMul(
            StrideVal,
            ConstantInt::getSigned(
                StrideTy, static_cast<int>(DL->getTypeAllocSize(ScalarTy))));
        if (StridedStoreTy != VecTy)
          VecValue =
              createWidenedStridedCast(Builder, VecValue, StridedStoreTy, *DL);
        auto *Inst = Builder.CreateIntrinsicWithoutFolding(
            Intrinsic::experimental_vp_strided_store,
            {StridedStoreTy, Ptr->getType(), StrideTy},
            {VecValue, Ptr, StrideVal,
             Builder.getAllOnesMask(ElementCount::getFixed(StridedStoreEC)),
             Builder.getInt32(StridedStoreEC)});
        Inst->addParamAttr(
            /*ArgNo=*/1,
            Attribute::getWithAlignment(Inst->getContext(), CommonAlignment));
        ST = Inst;
      }

      Value *V = PropagateIRFlags(ST);

      E->VectorizedValue = V;
      ++NumVectorInstructions;
      return V;
    }
    case Instruction::GetElementPtr: {
      auto *GEP0 = cast<GetElementPtrInst>(VL0);
      setInsertPointAfterBundle(E);

      Value *Op0 = vectorizeOperand(E, 0);

      SmallVector<Value *> OpVecs;
      for (int J = 1, N = GEP0->getNumOperands(); J < N; ++J) {
        Value *OpVec = vectorizeOperand(E, J);
        OpVecs.push_back(OpVec);
      }

      Value *V = Builder.CreateGEP(GEP0->getSourceElementType(), Op0, OpVecs);
      if (Instruction *I = dyn_cast<GetElementPtrInst>(V)) {
        SmallVector<Value *> GEPs;
        for (Value *V : E->Scalars) {
          if (isa<GetElementPtrInst>(V))
            GEPs.push_back(V);
        }
        V = PropagateIRFlags(I);
      }

      V = FinalShuffle(V, E);

      E->VectorizedValue = V;
      ++NumVectorInstructions;

      return V;
    }
    case Instruction::Call: {
      CallInst *CI = cast<CallInst>(VL0);
      setInsertPointAfterBundle(E);

      Intrinsic::ID ID = getVectorIntrinsicIDForCall(CI, TLI);

      SmallVector<Type *> ArgTys = buildIntrinsicArgTypes(
          CI, ID, getNumElements(VecTy),
          It != MinBWs.end() ? It->second.first : 0, TTI);
      auto VecCallCosts =
          getVectorCallCosts(CI, VecTy, TTI, TLI, ArgTys, CostKind);
      bool UseIntrinsic = ID != Intrinsic::not_intrinsic &&
                          VecCallCosts.first <= VecCallCosts.second;

      Value *ScalarArg = nullptr;
      SmallVector<Value *> OpVecs;
      SmallVector<Type *, 2> TysForDecl;
      // Add return type if intrinsic is overloaded on it.
      if (UseIntrinsic && isVectorIntrinsicWithOverloadTypeAtArg(ID, -1, TTI)) {
        ArrayRef<Type *> ContainedTys = getContainedTypes(VecTy);
        for (auto [Idx, Ty] : enumerate(ContainedTys)) {
          if (isVectorIntrinsicWithStructReturnOverloadAtField(ID, Idx, TTI))
            TysForDecl.push_back(Ty);
        }
      }
      auto *CEI = cast<CallInst>(VL0);
      for (unsigned I : seq<unsigned>(0, CI->arg_size())) {
        // Some intrinsics have scalar arguments. This argument should not be
        // vectorized.
        if (UseIntrinsic && isVectorIntrinsicWithScalarOpAtArg(ID, I, TTI)) {
          ScalarArg = CEI->getArgOperand(I);
          // if decided to reduce bitwidth of abs intrinsic, it second argument
          // must be set false (do not return poison, if value issigned min).
          if (ID == Intrinsic::abs && It != MinBWs.end() &&
              It->second.first < DL->getTypeSizeInBits(CEI->getType()))
            ScalarArg = Builder.getFalse();
          OpVecs.push_back(ScalarArg);
          if (isVectorIntrinsicWithOverloadTypeAtArg(ID, I, TTI))
            TysForDecl.push_back(ScalarArg->getType());
          continue;
        }

        Value *OpVec = vectorizeOperand(E, I);
        ScalarArg = CEI->getArgOperand(I);
        if (cast<VectorType>(OpVec->getType())->getElementType() !=
                ScalarArg->getType()->getScalarType() &&
            It == MinBWs.end()) {
          auto *CastTy =
              getWidenedType(ScalarArg->getType(), getNumElements(VecTy));
          OpVec = Builder.CreateIntCast(OpVec, CastTy, GetOperandSignedness(I));
        } else if (It != MinBWs.end()) {
          OpVec = Builder.CreateIntCast(OpVec, VecTy, GetOperandSignedness(I));
        }
        LLVM_DEBUG(dbgs() << "SLP: OpVec[" << I << "]: " << *OpVec << "\n");
        OpVecs.push_back(OpVec);
        if (UseIntrinsic && isVectorIntrinsicWithOverloadTypeAtArg(ID, I, TTI))
          TysForDecl.push_back(OpVec->getType());
      }

      Function *CF;
      if (!UseIntrinsic) {
        VFShape Shape =
            VFShape::get(CI->getFunctionType(),
                         ElementCount::getFixed(getNumElements(VecTy)),
                         false /*HasGlobalPred*/);
        CF = VFDatabase(*CI).getVectorizedFunction(Shape);
      } else {
        CF = Intrinsic::getOrInsertDeclaration(F->getParent(), ID, TysForDecl);
      }

      SmallVector<OperandBundleDef, 1> OpBundles;
      CI->getOperandBundlesAsDefs(OpBundles);
      Value *V = Builder.CreateCall(CF, OpVecs, OpBundles);

      V = PropagateIRFlags(V);
      cast<CallInst>(V)->setCallingConv(CF->getCallingConv());
      V = FinalShuffle(V, E);

      E->VectorizedValue = V;
      ++NumVectorInstructions;
      return V;
    }
    case Instruction::ShuffleVector: {
      Value *V;
      if (Opts.slp_revec && !E->isAltShuffle()) {
        setInsertPointAfterBundle(E);
        Value *Src = vectorizeOperand(E, 0);
        SmallVector<int> ThisMask(calculateShufflevectorMask(E->Scalars));
        if (auto *SVSrc = dyn_cast<ShuffleVectorInst>(Src)) {
          SmallVector<int> NewMask(ThisMask.size());
          transform(ThisMask, NewMask.begin(), [&SVSrc](int Mask) {
            return SVSrc->getShuffleMask()[Mask];
          });
          V = Builder.CreateShuffleVector(SVSrc->getOperand(0),
                                          SVSrc->getOperand(1), NewMask);
        } else {
          V = Builder.CreateShuffleVector(Src, ThisMask);
        }
        V = PropagateIRFlags(V);
        V = FinalShuffle(V, E);
      } else {
        assert(E->isAltShuffle() &&
               ((Instruction::isBinaryOp(E->getOpcode()) &&
                 Instruction::isBinaryOp(E->getAltOpcode())) ||
                (Instruction::isCast(E->getOpcode()) &&
                 Instruction::isCast(E->getAltOpcode())) ||
                (isa<CmpInst>(VL0) && isa<CmpInst>(E->getAltOp()))) &&
               "Invalid Shuffle Vector Operand");

        // Gather up main and alt scalar ops to propagate IR flags to each
        // vector operation and build the lane-select mask.
        ValueList OpScalars, AltScalars;
        SmallVector<int> Mask;
        E->buildAltOpShuffleMask(
            [E, this](Instruction *I) {
              assert(E->getMatchingMainOpOrAltOp(I) &&
                     "Unexpected main/alternate opcode");
              return isAlternateInstruction(I, E->getMainOp(), E->getAltOp(),
                                            *TLI);
            },
            Mask, &OpScalars, &AltScalars);
        if (auto *VecTy = dyn_cast<FixedVectorType>(ScalarTy)) {
          assert(Opts.slp_revec && "FixedVectorType is not expected.");
          transformScalarShuffleIndiciesToVector(VecTy->getNumElements(), Mask);
        }

        if (E->hasReassocScalars() && Instruction::isBinaryOp(E->getOpcode())) {
          // Peeled alternate chains are linearized completely: the operand
          // columns fold into one pure main-opcode chain and one pure
          // alt-opcode chain, followed by a single lane-select shuffle. Every
          // lane keeps one opcode on all levels, so its value is exact in one
          // of the chains.
          setInsertPointAfterBundle(E);
          for (Value *V : E->getReassocScalars()) {
            auto *I = cast<Instruction>(V);
            (isAlternateInstruction(I, E->getMainOp(), E->getAltOp(), *TLI)
                 ? AltScalars
                 : OpScalars)
                .push_back(I);
          }
          auto FoldColumns = [&](unsigned Opcode,
                                 const ValueList &FlagScalars) {
            Value *R = nullptr;
            for (unsigned Idx : seq<unsigned>(E->getNumOperands())) {
              Value *Column = vectorizeOperand(E, Idx);
              if (Column->getType() != VecTy)
                Column = Builder.CreateIntCast(Column, VecTy,
                                               GetOperandSignedness(Idx));
              if (!R) {
                R = Column;
                continue;
              }
              R = Builder.CreateBinOp(
                  static_cast<Instruction::BinaryOps>(Opcode), R, Column);
              PropagateIRFlags(R, Opcode, FlagScalars);
              auto *I = dyn_cast<Instruction>(R);
              if (!I)
                continue;
              // Regrouping can invalidate flags even when each original
              // step was safe.
              I->dropPoisonGeneratingFlags();
              GatherShuffleExtractSeq.insert(I);
              CSEBlocks.insert(I->getParent());
            }
            return R;
          };
          Value *V0 = FoldColumns(E->getOpcode(), OpScalars);
          Value *V1 = FoldColumns(E->getAltOpcode(), AltScalars);
          V = Builder.CreateShuffleVector(V0, V1, Mask);
          if (auto *I = dyn_cast<Instruction>(V)) {
            GatherShuffleExtractSeq.insert(I);
            CSEBlocks.insert(I->getParent());
          }
          E->VectorizedValue = V;
          ++NumVectorInstructions;
          return V;
        }

        Value *LHS = nullptr, *RHS = nullptr;
        if (Instruction::isBinaryOp(E->getOpcode()) || isa<CmpInst>(VL0)) {
          setInsertPointAfterBundle(E);
          LHS = vectorizeOperand(E, 0);
          RHS = vectorizeOperand(E, 1);
        } else {
          setInsertPointAfterBundle(E);
          LHS = vectorizeOperand(E, 0);
        }
        if (LHS && RHS &&
            ((Instruction::isBinaryOp(E->getOpcode()) &&
              (LHS->getType() != VecTy || RHS->getType() != VecTy)) ||
             (isa<CmpInst>(VL0) && LHS->getType() != RHS->getType()))) {
          assert((It != MinBWs.end() ||
                  getOperandEntry(E, 0)->State == TreeEntry::NeedToGather ||
                  getOperandEntry(E, 1)->State == TreeEntry::NeedToGather ||
                  MinBWs.contains(getOperandEntry(E, 0)) ||
                  MinBWs.contains(getOperandEntry(E, 1))) &&
                 "Expected item in MinBWs.");
          Type *CastTy = VecTy;
          if (isa<CmpInst>(VL0) && LHS->getType() != RHS->getType()) {
            if (cast<VectorType>(LHS->getType())
                    ->getElementType()
                    ->getIntegerBitWidth() < cast<VectorType>(RHS->getType())
                                                 ->getElementType()
                                                 ->getIntegerBitWidth())
              CastTy = RHS->getType();
            else
              CastTy = LHS->getType();
          }
          if (LHS->getType() != CastTy)
            LHS = Builder.CreateIntCast(LHS, CastTy, GetOperandSignedness(0));
          if (RHS->getType() != CastTy)
            RHS = Builder.CreateIntCast(RHS, CastTy, GetOperandSignedness(1));
        }

        Value *V0, *V1;
        if (Instruction::isBinaryOp(E->getOpcode())) {
          V0 = Builder.CreateBinOp(
              static_cast<Instruction::BinaryOps>(E->getOpcode()), LHS, RHS);
          V1 = Builder.CreateBinOp(
              static_cast<Instruction::BinaryOps>(E->getAltOpcode()), LHS, RHS);
        } else if (auto *CI0 = dyn_cast<CmpInst>(VL0)) {
          V0 = Builder.CreateCmp(CI0->getPredicate(), LHS, RHS);
          auto *AltCI = cast<CmpInst>(E->getAltOp());
          CmpInst::Predicate AltPred = AltCI->getPredicate();
          V1 = Builder.CreateCmp(AltPred, LHS, RHS);
        } else {
          if (LHS->getType()->isIntOrIntVectorTy() && ScalarTy->isIntegerTy()) {
            unsigned SrcBWSz = DL->getTypeSizeInBits(
                cast<VectorType>(LHS->getType())->getElementType());
            unsigned BWSz = DL->getTypeSizeInBits(ScalarTy);
            if (BWSz <= SrcBWSz) {
              if (BWSz < SrcBWSz)
                LHS = Builder.CreateIntCast(LHS, VecTy, It->second.first);
              assert(LHS->getType() == VecTy &&
                     "Expected same type as operand.");
              LHS = PropagateIRFlags(LHS);
              LHS = FinalShuffle(LHS, E);
              E->VectorizedValue = LHS;
              ++NumVectorInstructions;
              return LHS;
            }
          }
          V0 = Builder.CreateCast(
              static_cast<Instruction::CastOps>(E->getOpcode()), LHS, VecTy);
          V1 = Builder.CreateCast(
              static_cast<Instruction::CastOps>(E->getAltOpcode()), LHS, VecTy);
        }
        // Add V0 and V1 to later analysis to try to find and remove matching
        // instruction, if any.
        for (Value *V : {V0, V1}) {
          if (auto *I = dyn_cast<Instruction>(V)) {
            GatherShuffleExtractSeq.insert(I);
            CSEBlocks.insert(I->getParent());
          }
        }

        PropagateIRFlags(V0, E->getOpcode(), OpScalars);
        PropagateIRFlags(V1, E->getAltOpcode(), AltScalars);

        // Create shuffle to take alternate operations from the vector.
        V = Builder.CreateShuffleVector(V0, V1, Mask);
        if (auto *I = dyn_cast<Instruction>(V)) {
          GatherShuffleExtractSeq.insert(I);
          CSEBlocks.insert(I->getParent());
        }
      }

      E->VectorizedValue = V;
      ++NumVectorInstructions;

      return V;
    }
    case TreeEntry::ReducedBitcast:
    case TreeEntry::ReducedBitcastBSwap: {
      assert(UserIgnoreList && "Expected reduction operations only.");
      setInsertPointAfterBundle(E);
      TreeEntry *ZExt = getOperandEntry(E, /*Idx=*/0);
      ZExt->VectorizedValue = PoisonValue::get(getWidenedType(
          ZExt->getMainOp()->getType(), ZExt->getVectorFactor()));
      TreeEntry *Const = getOperandEntry(E, /*Idx=*/1);
      Const->VectorizedValue = PoisonValue::get(getWidenedType(
          Const->Scalars.front()->getType(), Const->getVectorFactor()));
      Value *Op = vectorizeOperand(ZExt, 0);
      auto *SrcType = IntegerType::get(
          Op->getContext(),
          DL->getTypeSizeInBits(cast<CastInst>(ZExt->getMainOp())->getSrcTy()) *
              E->getVectorFactor());
      auto *OrigScalarTy = ScalarTy;
      // Set the scalar type properly to avoid casting to the extending type.
      ScalarTy = cast<CastInst>(ZExt->getMainOp())->getSrcTy();
      Op = FinalShuffle(Op, E);
      auto *V = Builder.CreateBitCast(Op, SrcType);
      ++NumVectorInstructions;
      if (ShuffleOrOp == TreeEntry::ReducedBitcastBSwap) {
        V = Builder.CreateUnaryIntrinsic(Intrinsic::bswap, V);
        ++NumVectorInstructions;
      }
      if (SrcType != OrigScalarTy) {
        V = Builder.CreateIntCast(V, OrigScalarTy, /*isSigned=*/false);
        ++NumVectorInstructions;
      }
      E->VectorizedValue = V;
      return V;
    }
    case TreeEntry::ReducedBitcastLoads:
    case TreeEntry::ReducedBitcastBSwapLoads: {
      assert(UserIgnoreList && "Expected reduction operations only.");
      TreeEntry *ZExt = getOperandEntry(E, /*Idx=*/0);
      TreeEntry *Load = getOperandEntry(ZExt, /*Idx=*/0);
      setInsertPointAfterBundle(Load);
      ZExt->VectorizedValue = PoisonValue::get(getWidenedType(
          ZExt->getMainOp()->getType(), ZExt->getVectorFactor()));
      TreeEntry *Const = getOperandEntry(E, /*Idx=*/1);
      Const->VectorizedValue = PoisonValue::get(getWidenedType(
          Const->Scalars.front()->getType(), Const->getVectorFactor()));
      Load->VectorizedValue = PoisonValue::get(getWidenedType(
          Load->getMainOp()->getType(), Load->getVectorFactor()));
      LoadInst *LI = cast<LoadInst>(Load->getMainOp());
      Value *PO = LI->getPointerOperand();
      auto *SrcTy = IntegerType::get(
          ScalarTy->getContext(),
          DL->getTypeSizeInBits(cast<CastInst>(ZExt->getMainOp())->getSrcTy()) *
              E->getVectorFactor());
      auto *OrigScalarTy = ScalarTy;
      ScalarTy = ZExt->getMainOp()->getType();
      Value *V = Builder.CreateAlignedLoad(SrcTy, PO, LI->getAlign());
      ++NumVectorInstructions;
      if (ShuffleOrOp == TreeEntry::ReducedBitcastBSwapLoads) {
        V = Builder.CreateUnaryIntrinsic(Intrinsic::bswap, V);
        ++NumVectorInstructions;
      }
      if (SrcTy != OrigScalarTy) {
        V = Builder.CreateIntCast(V, OrigScalarTy, /*isSigned=*/false);
        ++NumVectorInstructions;
      }
      E->VectorizedValue = V;
      return V;
    }
    case TreeEntry::ReducedBitPack: {
      assert(UserIgnoreList && "Expected reduction operations only.");
      setInsertPointAfterBundle(E);
      TreeEntry *ShlTE = E->getOpcode() == Instruction::And
                             ? getOperandEntry(E, /*Idx=*/0)
                             : E;
      std::optional<BitPackInfo> Info = computeBitPackLayout(*E);
      assert(Info && "Expected bit pack info.");
      TreeEntry *LhsTE = getOperandEntry(ShlTE, /*Idx=*/0);
      const TreeEntry *SrcTE = getBitPackSource(*LhsTE, *Info);
      SmallVector<TreeEntry *> CombinedTEs;
      if (ShlTE != E)
        CombinedTEs.append({ShlTE, getOperandEntry(E, /*Idx=*/1)});
      CombinedTEs.push_back(getOperandEntry(ShlTE, /*Idx=*/1));
      TreeEntry *OpTE = LhsTE;
      for (; OpTE != SrcTE; OpTE = getOperandEntry(OpTE, /*Idx=*/0)) {
        CombinedTEs.push_back(OpTE);
        for (unsigned Idx : seq<unsigned>(1, OpTE->getNumOperands()))
          CombinedTEs.push_back(getOperandEntry(OpTE, Idx));
      }
      for (TreeEntry *TE : CombinedTEs)
        TE->VectorizedValue = PoisonValue::get(getWidenedType(
            TE->Scalars.front()->getType(), TE->getVectorFactor()));
      Value *X = vectorizeTree(OpTE);
      unsigned ShiftWidth;
      Type *DstScalarTy =
          SrcTE == LhsTE ? X->getType()->getScalarType() : ScalarTy;
      [[maybe_unused]] InstructionCost PackCost = getBitPackCost(
          *TTI, cast<FixedVectorType>(X->getType()), DstScalarTy, *Info,
          getZExtSrcWidth(*SrcTE), getCastContextHint(*SrcTE), CostKind, TLI,
          E->getMainOp(), ShiftWidth);
      assert(PackCost.isValid() && "Expected valid cost.");
      unsigned NumInsts;
      Value *V =
          buildBitPack(Builder, X, *Info, DstScalarTy, ShiftWidth, NumInsts);
      NumVectorInstructions += NumInsts;
      E->VectorizedValue = V;
      return V;
    }
    case TreeEntry::ReducedCmpBitcast: {
      assert(UserIgnoreList && "Expected reduction operations only.");
      setInsertPointAfterBundle(E);
      TreeEntry *Op1TE = getOperandEntry(E, /*Idx=*/1);
      TreeEntry *Op2TE = getOperandEntry(E, /*Idx=*/2);
      Op1TE->VectorizedValue =
          PoisonValue::get(getWidenedType(ScalarTy, Op1TE->getVectorFactor()));
      Op2TE->VectorizedValue =
          PoisonValue::get(getWidenedType(ScalarTy, Op2TE->getVectorFactor()));
      Value *Cmp = vectorizeOperand(E, /*NodeIdx=*/0);
      // Set the scalar type properly to avoid casting to the extending type.
      auto *DstTy =
          IntegerType::getIntNTy(ScalarTy->getContext(), E->getVectorFactor());
      auto *V = Builder.CreateBitCast(Cmp, DstTy);
      ++NumVectorInstructions;
      if (DstTy != ScalarTy) {
        V = Builder.CreateIntCast(V, ScalarTy, /*isSigned=*/false);
        ++NumVectorInstructions;
      }
      E->VectorizedValue = V;
      return V;
    }
    default:
      llvm_unreachable("unknown inst");
  }
  return nullptr;
}

bool BoUpSLP::isRuntimeCheckableAliasPair(Instruction *Inst1,
                                          Instruction *Inst2) {
  // Only simple (non-volatile, non-atomic) accesses may be reordered once
  // aliasing is ruled out at runtime; volatile/atomic ordering must be kept.
  if (!isSimple(Inst1) || !isSimple(Inst2))
    return false;
  Value *Ptr1 = getLoadStorePointerOperand(Inst1);
  Value *Ptr2 = getLoadStorePointerOperand(Inst2);
  // Only simple load/store accesses have a single pointer operand whose
  // accessed range can be bounded and compared at runtime.
  if (!Ptr1 || !Ptr2)
    return false;
  if (Ptr1->getType()->getPointerAddressSpace() !=
      Ptr2->getType()->getPointerAddressSpace())
    return false;
  const Value *Base1 = getUnderlyingObject(Ptr1);
  const Value *Base2 = getUnderlyingObject(Ptr2);
  // A runtime range check is only meaningful between two distinct, identifiable
  // objects: two accesses to the same base differ by a compile-time offset, so
  // they are resolved statically and a base-range check would fold to a
  // constant predicate rather than a useful runtime guard.
  if (Base1 == Base2 || isa<UndefValue>(Base1) || isa<UndefValue>(Base2))
    return false;
  return true;
}

bool BoUpSLP::isCoveredByExistingVersionCheck(BasicBlock *BB,
                                              Instruction *Inst1,
                                              Instruction *Inst2) const {
  const auto It = VersionedBlockCheckedPairs.find(BB);
  if (It == VersionedBlockCheckedPairs.end())
    return false;
  Value *Ptr1 = getLoadStorePointerOperand(Inst1);
  Value *Ptr2 = getLoadStorePointerOperand(Inst2);
  if (!Ptr1 || !Ptr2)
    return false;
  const Value *Base1 = getUnderlyingObject(Ptr1);
  const Value *Base2 = getUnderlyingObject(Ptr2);
  if (Base1 == Base2)
    return false;
  // The recorded pairs keep their discovery order (see
  // recordRuntimeAliasCheck), so accept either orientation.
  return It->second.contains({Base1, Base2}) ||
         It->second.contains({Base2, Base1});
}

/// Returns true if \p BB's body already contains vector instructions, e.g.
/// from an earlier SLP vectorization in the same pass.
static bool blockBodyHasVectorInstructions(const VectorizeOptions &Opts,
                                           BasicBlock *BB) {
  // A vector-producing instruction (vector load, binop, shuffle, etc.) has a
  // vector result type.
  return any_of(*BB, [&](Instruction &I) {
    return !isa<PHINode>(&I) && !I.isTerminator() &&
           getValueType(&I, Opts.slp_revec)->isVectorTy();
  });
}

void BoUpSLP::captureRuntimeCheckBodySnapshot() {
  RTOrigBodyOrder.clear();
  if (!TryRuntimeAliasChecks || !RTChecks.BB)
    return;
  BasicBlock *BB = RTChecks.BB;
  // Allocas are not duplicated, keep them in the header block.
  for (Instruction &I : *BB)
    if (!isa<PHINode, AllocaInst>(&I) && !I.isTerminator())
      RTOrigBodyOrder.push_back(&I);
}

bool BoUpSLP::recordRuntimeAliasCheck(BasicBlock *BB, Instruction *Inst1,
                                      Instruction *Inst2) {
  Value *Ptr1 = getLoadStorePointerOperand(Inst1);
  Value *Ptr2 = getLoadStorePointerOperand(Inst2);
  if (!Ptr1 || !Ptr2)
    return false;
  const Value *Base1 = getUnderlyingObject(Ptr1);
  const Value *Base2 = getUnderlyingObject(Ptr2);
  if (Base1 == Base2)
    return false;
  // Only a single block can be versioned per attempt.
  if (RTChecks.BB && RTChecks.BB != BB)
    return false;
  // A base-object pair is unordered: (Base1, Base2) and (Base2, Base1) are the
  // same check. Keep it in discovery (program) order and drop the reverse as a
  // duplicate, rather than ordering by pointer value, which would make the
  // emitted checks depend on allocation addresses.
  auto Pair = std::make_pair(Base1, Base2);
  bool Present = RTChecks.BasePairs.contains(Pair) ||
                 RTChecks.BasePairs.contains({Base2, Base1});
  // After the checks have been validated and bounded, do not introduce new
  // pairs.
  if (RTChecksFinalized)
    return Present;
  RTChecks.BB = BB;
  if (!Present)
    RTChecks.BasePairs.insert(Pair);
  return true;
}

bool BoUpSLP::canVersionBlockForRuntimeChecks(BasicBlock *BB) const {
  assert(BB && "Expected a block to version for runtime checks.");
  // Versioning duplicates the block body, increasing code size on the guarded
  // path; do not version when the function is optimized for size (-Os/-Oz).
  if (F->hasOptSize())
    return false;
  if (!DT || !LI)
    return false;
  if (!DT->isReachableFromEntry(BB))
    return false;
  // Never version a scalar fallback block: it is the safe, original-order copy
  // taken when aliasing is detected and must stay scalar.
  if (ScalarFallbackBlocks.contains(BB))
    return false;
  // The scalar fallback must be a faithful copy of the original scalar body.
  // Reject blocks that were already partially vectorized earlier in this pass.
  if (blockBodyHasVectorInstructions(Opts, BB))
    return false;
  // Versioning duplicates the original block body into a scalar fallback.
  // Calls that cannot be duplicated or whose semantics depend on the call being
  // immediately followed by a return cannot be cloned into the diamond.
  if (BB->getTerminatingMustTailCall())
    return false;
  if (any_of(*BB, [](Instruction &I) {
        auto *CB = dyn_cast<CallBase>(&I);
        return CB && (CB->cannotDuplicate() || CB->isConvergent());
      }))
    return false;
  // Only static allocas at the start of the entry block can stay in the header
  // block, any other alloca would have to be duplicated with the body.
  if (any_of(make_range(BB->getFirstNonPHIOrAlloca(), BB->end()),
             IsaPred<AllocaInst>))
    return false;
  return true;
}

bool BoUpSLP::canVersionForRuntimeChecks() {
  if (RTChecks.BasePairs.empty() || !RTChecks.BB)
    return false;
  if (RTChecks.BasePairs.size() > Opts.slp_max_runtime_alias_checks)
    return false;
  BasicBlock *BB = RTChecks.BB;
  // Block-level preconditions (loop/optsize/duplicability/...) are the same
  // ones used to gate the optimistic retry, so reuse them here.
  if (!canVersionBlockForRuntimeChecks(BB))
    return false;

  // The scalar fallback is a clone of the body. Operands defined inside the
  // body are remapped to their clones, but operands defined outside the body
  // (header PHIs, dominating definitions) are reused as-is by the clone. If
  // such an outside operand is itself vectorized by this tree, vectorizeTree()
  // will delete its scalar, leaving the clone with a dangling, out-of-tree use.
  // Versioning cannot model that, so bail out.
  for (Instruction &I : make_filter_range(*BB, [](Instruction &I) {
         return !isa<PHINode>(&I) && !I.isTerminator();
       })) {
    for (Instruction *OpI : make_isa_range<Instruction>(I.operands())) {
      bool DefinedInBody =
          OpI->getParent() == BB && !isa<PHINode>(OpI) && !OpI->isTerminator();
      if (!DefinedInBody && isVectorized(OpI))
        return false;
    }
  }

  SmallPtrSet<const Value *, 8> Bases;
  for (const auto &P : RTChecks.BasePairs) {
    Bases.insert(P.first);
    Bases.insert(P.second);
  }
  // Every base object must be available in the (PHI-only) header where the
  // guard branch is emitted, i.e. be one of its PHIs or dominate it.
  if (any_of(make_isa_range<Instruction>(Bases), [&](const Instruction *I) {
        return I->getParent() == BB ? !isa<PHINode>(I) : !DT->dominates(I, BB);
      }))
    return false;

  // Compute the accessed address range [Low, High) for every involved base.
  RTChecks.Bounds.clear();
  SmallMapVector<Value *, std::pair<const SCEV *, const SCEV *>, 4> OffBounds;
  unsigned NumMemInsts = 0;
  for (Instruction &I : make_filter_range(
           *BB, [](Instruction &I) { return I.mayReadOrWriteMemory(); })) {
    // The dependency scan truncates beyond MaxMemDepDistance. Only version
    // blocks small enough that the scan is never truncated, so every
    // conflicting base pair is guaranteed to be recorded.
    if (++NumMemInsts > MaxMemDepDistance)
      return false;
    Value *Ptr = getLoadStorePointerOperand(&I);
    // A non-simple memory access (e.g. a call) keeps its dependencies, so its
    // relative order with kept-dependency partners is preserved inside the
    // duplicated body and it does not need a bound.
    if (!Ptr)
      continue;
    Value *Base = const_cast<Value *>(getUnderlyingObject(Ptr));
    if (!Bases.contains(Base))
      continue;
    TypeSize TS = DL->getTypeStoreSize(getLoadStoreType(&I));
    if (TS.isScalable())
      return false;
    Type *IntTy = DL->getAddressType(Base->getType());
    // All bounds are computed and compared in a single address type, so an
    // access that reaches its base object through an addrspacecast between
    // differently-sized address spaces cannot be bounded and the block
    // cannot be versioned.
    if (DL->getAddressType(Ptr->getType()) != IntTy)
      return false;
    const SCEV *PtrSC = SE->getPtrToAddrExpr(SE->getSCEV(Ptr));
    const SCEV *BaseSC = SE->getPtrToAddrExpr(SE->getSCEV(Base));
    if (isa<SCEVCouldNotCompute>(PtrSC) || isa<SCEVCouldNotCompute>(BaseSC))
      return false;
    // Byte offset of this access from its base. Require a constant so the bound
    // stays base-plus-constant, and non-negative so the unsigned [Low, High)
    // range below actually covers the access.
    // TODO: Support variable offsets (e.g. base + %idx) which would need
    // runtime umin/umax bounds and a proof that the offset range cannot wrap,
    // plus a richer cost model.
    const auto *Off = dyn_cast<SCEVConstant>(SE->getMinusSCEV(PtrSC, BaseSC));
    if (!Off || Off->getAPInt().isNegative())
      return false;
    const SCEV *EndOff =
        SE->getAddExpr(Off, SE->getConstant(IntTy, TS.getFixedValue()));
    auto [It, Inserted] = OffBounds.try_emplace(Base, Off, EndOff);
    if (!Inserted) {
      // Constant operands, so these fold to a constant min/max offset rather
      // than emitting a runtime umin/umax.
      It->second.first = SE->getUMinExpr(It->second.first, Off);
      It->second.second = SE->getUMaxExpr(It->second.second, EndOff);
    }
  }
  // Every involved base must contribute at least one bounded access.
  if (OffBounds.size() != Bases.size())
    return false;
  // Materialize the absolute [Low, High) = base + [minOff, maxEndOff). The
  // offsets are constants, so each bound is a base-plus-constant expression
  // that expands to a single add off the base address (no runtime umin/umax).
  // The base is used as an opaque value, so the bounds only reference the base
  // itself, available at the guard, and a loop-variant base (e.g. a header PHI)
  // is reused rather than recomputed from its recurrence.
  for (const auto &[Base, Off] : OffBounds) {
    const SCEV *BaseSC = SE->getPtrToAddrExpr(SE->getUnknown(Base));
    RTChecks.Bounds.try_emplace(Base, SE->getAddExpr(BaseSC, Off.first),
                                SE->getAddExpr(BaseSC, Off.second));
  }

  // SSA values defined in the body and used outside of it are merged from both
  // paths in the continuation block, so they must stay scalar. Uses by the
  // terminator (moved into the continuation block) and by the block's PHIs
  // (via the loop latch) count as outside.
  for (Instruction &I : make_filter_range(*BB, [&](Instruction &I) {
         return !isa<PHINode>(&I) && !I.isTerminator() && isVectorized(&I);
       })) {
    if (any_of(I.users(), [&](User *U) {
          auto *UI = dyn_cast<Instruction>(U);
          return !UI || UI->getParent() != BB || isa<PHINode>(UI) ||
                 UI->isTerminator();
        }))
      return false;
  }

  // The runtime checks and the guard branch run on both the vector and the
  // scalar fallback path. When aliasing is detected at runtime the scalar code
  // executes unchanged plus the check overhead, so bound the check cost
  // relative to the guarded scalar region to avoid pessimizing that path too
  // much. The scalar region cost is the cost of the (current, still scalar)
  // block body; no IR is emitted here.
  InstructionCost ScalarCost = 0;
  for (Instruction &I : make_filter_range(*BB, [](Instruction &I) {
         return !isa<PHINode>(&I) && !I.isTerminator();
       })) {
    // The backend fuses the fmul into its fadd/fsub user, so the pair costs as
    // the fmuladd.
    auto [U, FMACost] = getFMulFusingUser(&I, /*InTree=*/false);
    ScalarCost += U && U->getParent() == BB
                      ? FMACost - TTI->getInstructionCost(U, CostKind)
                      : TTI->getInstructionCost(&I, CostKind);
  }
  InstructionCost CheckCost = getRuntimeChecksCost();
  if (!ScalarCost.isValid() || !CheckCost.isValid())
    return false;
  const Loop *L = LI->getLoopFor(BB);
  unsigned MaxPercent =
      L && getBooleanLoopAttribute(L, "llvm.loop.isvectorized")
          ? Opts.slp_vec_loop_rt_checks_cost_percent
          : Opts.slp_runtime_alias_checks_max_scalar_cost_percent;
  if (CheckCost * 100 > ScalarCost * MaxPercent)
    return false;

  // Freeze the check set so the final scheduleBlock() keeps the same dropped
  // dependencies the bounds were just computed for.
  RTChecksFinalized = true;
  return true;
}

InstructionCost BoUpSLP::getRuntimeChecksCost() const {
  if (RTChecks.BasePairs.empty())
    return 0;
  LLVMContext &Ctx = F->getContext();
  Type *IntTy = DL->getIntPtrType(Ctx);
  Type *I1Ty = Type::getInt1Ty(Ctx);
  unsigned NumBases = RTChecks.Bounds.size();
  unsigned NumPairs = RTChecks.BasePairs.size();
  InstructionCost Cost = 0;
  // Per base: a [Low, High) address pair. canVersionForRuntimeChecks() folds
  // each bound to a base-plus-constant offset, so it expands to two integer
  // adds (one per bound) with no runtime umin/umax reduction.
  Cost += TTI->getArithmeticInstrCost(Instruction::Add, IntTy, CostKind) *
          (2 * NumBases);
  // Two integer compares and one logical and per checked pair.
  InstructionCost CmpCost = TTI->getCmpSelInstrCost(
      Instruction::ICmp, IntTy, I1Ty, CmpInst::ICMP_ULT, CostKind);
  InstructionCost AndCost =
      TTI->getArithmeticInstrCost(Instruction::And, I1Ty, CostKind);
  Cost += (CmpCost * 2 + AndCost) * NumPairs;
  // Or-reduction of the per-pair conflicts.
  if (NumPairs > 1)
    Cost += TTI->getArithmeticInstrCost(Instruction::Or, I1Ty, CostKind) *
            (NumPairs - 1);
  // The guard branch.
  Cost += TTI->getCFInstrCost(Instruction::CondBr, CostKind);
  return Cost;
}

Value *BoUpSLP::emitRuntimeAliasCheck(IRBuilderBase &Builder,
                                      SCEVExpander &Exp) {
  // Materialize the [Low, High) address bounds for every involved base from
  // their SCEVs at the builder's insertion point.
  SmallDenseMap<const Value *, std::pair<Value *, Value *>, 4> Range;
  for (const auto &[Base, Bound] : RTChecks.Bounds) {
    Type *IntTy = DL->getAddressType(Base->getType());
    Value *Low =
        Exp.expandCodeFor(Bound.first, IntTy, Builder.GetInsertPoint());
    Value *High =
        Exp.expandCodeFor(Bound.second, IntTy, Builder.GetInsertPoint());
    Range[Base] = {Low, High};
  }
  Value *Cond = nullptr;
  for (const auto &P : RTChecks.BasePairs) {
    std::pair<Value *, Value *> A = Range.lookup(P.first);
    std::pair<Value *, Value *> B = Range.lookup(P.second);
    assert(A.first && A.second && B.first && B.second &&
           "Missing bounds for a checked base object");
    // The objects overlap iff (A.Low < B.High) && (B.Low < A.High).
    Value *C0 = Builder.CreateICmpULT(A.first, B.second, "rt.bound0");
    Value *C1 = Builder.CreateICmpULT(B.first, A.second, "rt.bound1");
    Value *Conflict = Builder.CreateAnd(C0, C1, "rt.conflict");
    Cond =
        Cond ? Builder.CreateOr(Cond, Conflict, "rt.conflict.all") : Conflict;
  }
  return Builder.CreateFreeze(Cond, "rt.guard");
}

void BoUpSLP::versionBlocksForRuntimeChecks() {
  // Only version when this is the optimistic attempt that collected the checks.
  if (!TryRuntimeAliasChecks || RTChecks.BasePairs.empty() || !RTChecks.BB ||
      RTOrigBodyOrder.empty())
    return;
  BasicBlock *BB = RTChecks.BB;
  Function *Fn = BB->getParent();
  LLVMContext &Ctx = BB->getContext();
  Instruction *Term = BB->getTerminator();

  // Build the diamond:
  //   BB (header: PHIs + guard) -> {VecBB, ScalarBB} -> Tail (terminator).
  BasicBlock *VecBB = BasicBlock::Create(Ctx, BB->getName() + ".rtvec", Fn);
  BasicBlock *ScalarBB =
      BasicBlock::Create(Ctx, BB->getName() + ".rtscalar", Fn);
  BasicBlock *Tail = BasicBlock::Create(Ctx, BB->getName() + ".rtcont", Fn);

  // Emit the runtime alias check while the block is still fully connected:
  // LCSSA-preserving SCEV expansion rewrites out-of-loop uses of
  // loop-defined bases to poison in predecessor-less blocks. Expand at the
  // first insertion point, where no body instruction dominates, so the check
  // cannot reuse scalars that are moved into the vector block and deleted.
  IRBuilder<> ChkBuilder(BB->getFirstInsertionPt());
  ChkBuilder.SetCurrentDebugLocation(Term->getDebugLoc());
  SCEVExpander Exp(*SE, "slp.rtcheck");
  Value *Cond = emitRuntimeAliasCheck(ChkBuilder, Exp);

  // Clone the body into the scalar fallback block, in the original program
  // order (RTOrigBodyOrder).
  SmallDenseMap<Value *, Value *, 16> VMap;
  for (Instruction *I : RTOrigBodyOrder) {
    assert(I->getParent() == BB &&
           "RTOrigBodyOrder entry no longer in the versioned block");
    Instruction *C = I->clone();
    if (I->hasName())
      C->setName(I->getName() + ".scalar");
    C->insertInto(ScalarBB, ScalarBB->end());
    VMap[I] = C;
  }
  // Remap the clones to use the cloned definitions; references to values
  // defined outside the body (header or function arguments) are unchanged.
  for (Instruction &I : *ScalarBB)
    for (Use &U : I.operands())
      if (Value *V = VMap.lookup(U.get()))
        U.set(V);

  // Move the original body into the vector block in the current (scheduled)
  // order, keeping the emitted check instructions in the header block.
  SmallPtrSet<Instruction *, 16> BodyInsts(llvm::from_range, RTOrigBodyOrder);
  for (Instruction &I : make_early_inc_range(*BB))
    if (BodyInsts.contains(&I))
      I.moveBefore(*VecBB, VecBB->end());

  // Move the original terminator into the continuation block and replace it
  // with the guard branch.
  Term->removeFromParent();
  Term->insertInto(Tail, Tail->end());
  UncondBrInst::Create(Tail, VecBB);
  UncondBrInst::Create(Tail, ScalarBB);
  ChkBuilder.SetInsertPoint(BB);
  CondBrInst *Guard = ChkBuilder.CreateCondBr(Cond, ScalarBB, VecBB);
  // The scalar fallback is taken only when the runtime alias check detects a
  // conflict, which is expected to be rare, so bias the guard towards the
  // vector path.
  if (!ProfcheckDisableMetadataFixes)
    setBranchWeights(
        *Guard,
        {MDBuilder::kUnlikelyBranchWeight, MDBuilder::kLikelyBranchWeight},
        /*IsExpected=*/false);

  // The continuation block is the new predecessor of the original successors.
  for (BasicBlock *Succ : successors(Term))
    Succ->replacePhiUsesWith(BB, Tail);

  // Merge the body values used outside of the versioned region (by the
  // terminator, across the loop latch or in other blocks) from both paths. The
  // SCEVs cached for the outside users refer to the body values, which no
  // longer dominate them.
  for (Instruction *I : RTOrigBodyOrder) {
    if (!I->isUsedOutsideOfBlock(VecBB))
      continue;
    SE->forgetValue(I);
    PHINode *Merge = PHINode::Create(I->getType(), 2, I->getName() + ".rtmerge",
                                     Tail->getFirstNonPHIIt());
    I->replaceUsesOutsideBlock(Merge, VecBB);
    Merge->addIncoming(I, VecBB);
    Merge->addIncoming(VMap.lookup(I), ScalarBB);
  }

  // Keep the dominator tree valid for the remainder of the run.
  if (DT) {
    DomTreeUpdater DTU(*DT, DomTreeUpdater::UpdateStrategy::Eager);
    SmallVector<DominatorTree::UpdateType> Updates = {
        {DominatorTree::Insert, BB, VecBB},
        {DominatorTree::Insert, BB, ScalarBB},
        {DominatorTree::Insert, VecBB, Tail},
        {DominatorTree::Insert, ScalarBB, Tail}};
    // Term (e.g. a switch) may have multiple edges to the same successor;
    // dedupe so each distinct successor gets exactly one Insert/Delete pair.
    SmallPtrSet<BasicBlock *, 4> UniqueSuccs;
    for (BasicBlock *Succ : successors(Term)) {
      if (!UniqueSuccs.insert(Succ).second)
        continue;
      Updates.push_back({DominatorTree::Insert, Tail, Succ});
      Updates.push_back({DominatorTree::Delete, BB, Succ});
    }
    DTU.applyUpdates(Updates);
    // Refresh DFS numbers: getLastInstructionInBundle() may use them to order
    // instructions across blocks for nodes emitted after versioning.
    DT->updateDFSNumbers();
  }
  // Keep the loop info valid for the remainder of the run: the new blocks
  // belong to the loop of the versioned block.
  if (Loop *L = LI->getLoopFor(BB))
    for (BasicBlock *NewBB : {VecBB, ScalarBB, Tail})
      L->addBasicBlockToLoop(NewBB, *LI);

  // Record the checked base pairs for the fast-path block so that subsequent
  // vectorization there can reuse this guard instead of versioning again.
  SmallDenseSet<std::pair<const Value *, const Value *>, 4> &Covered =
      VersionedBlockCheckedPairs[VecBB];
  Covered.insert_range(RTChecks.BasePairs);
  // The scalar fallback must never be vectorized or versioned again.
  // TODO: check that scalar fallback does not miss vectorization opportunity
  // without runtime checks.
  ScalarFallbackBlocks.insert(ScalarBB);

  // The checks have been emitted; clear so any later vectorizeTree() in the
  // same attempt does not version again.
  RTChecks.clear();
  RTChecksFinalized = false;
  RTOrigBodyOrder.clear();
  // The CFG was modified; CFG analyses can no longer be preserved.
  CFGChanged = true;
}

Value *BoUpSLP::vectorizeTree() {
  ExtraValueToDebugLocsMap ExternallyUsedValues;
  return vectorizeTree(ExternallyUsedValues);
}

Value *
BoUpSLP::vectorizeTree(const ExtraValueToDebugLocsMap &ExternallyUsedValues,
                       Instruction *ReductionRoot,
                       ArrayRef<ReductionVectorPart> VectorValuesAndScales) {
  // Clean Entry-to-LastInstruction table. It can be affected after scheduling,
  // need to rebuild it.
  EntryToLastInstruction.clear();
  // All blocks must be scheduled before any instructions are inserted.
  for (auto &BSIter : BlocksSchedules)
    scheduleBlock(*this, BSIter.second.get());
  // Cache last instructions for the nodes to avoid side effects, which may
  // appear during vectorization, like extra uses, etc.
  for (const std::unique_ptr<TreeEntry> &TE : VectorizableTree) {
    // Need to generate insertion point for loads nodes of the bitcast/bswap
    // ops.
    if (TE->isGather() || DeletedNodes.contains(TE.get()) ||
        TE->State == TreeEntry::SplitVectorize ||
        (TE->State == TreeEntry::CombinedVectorize &&
         (TE->CombinedOp == TreeEntry::ReducedBitcast ||
          TE->CombinedOp == TreeEntry::ReducedBitcastBSwap ||
          TE->CombinedOp == TreeEntry::ReducedBitPack ||
          ((TE->CombinedOp == TreeEntry::ReducedBitcastLoads ||
            TE->CombinedOp == TreeEntry::ReducedBitcastBSwapLoads ||
            TE->CombinedOp == TreeEntry::ReducedCmpBitcast) &&
           (!TE->hasState() || TE->getOpcode() != Instruction::Load)))))
      continue;
    (void)getLastInstructionInBundle(TE.get());
  }

  // If this tree was scheduled by dropping may-alias memory dependencies in
  // favor of runtime alias checks, materialize the checks and version the
  // affected block before emitting the vector code. Scheduling has already
  // run, so moving the body into the fast-path block is safe, and the
  // dominator tree is updated for the rest of the run.
  versionBlocksForRuntimeChecks();

  if (ReductionRoot)
    Builder.SetInsertPoint(ReductionRoot->getIterator());
  else
    Builder.SetInsertPoint(F->getEntryBlock().begin());

  // Vectorize gather operands of the nodes with the external uses only.
  SmallVector<std::pair<TreeEntry *, Instruction *>> GatherEntries;
  // Multiple gather TEs may share the same UserTE - cache the per-UserTE
  // all_of-isUsedOutsideBlock result to avoid re-walking each scalar's
  // user list.
  SmallDenseMap<const TreeEntry *, bool> UserTEScalarsUsedOutsideBlockCache;
  for (const std::unique_ptr<TreeEntry> &TE : make_filter_range(
           VectorizableTree, [&](const std::unique_ptr<TreeEntry> &TE) {
             return !DeletedNodes.contains(TE.get());
           })) {
    if (TE->isGather() && !TE->VectorizedValue && TE->UserTreeIndex.UserTE &&
        TE->UserTreeIndex.UserTE->hasState() &&
        TE->UserTreeIndex.UserTE->State == TreeEntry::Vectorize &&
        (TE->UserTreeIndex.UserTE->getOpcode() != Instruction::PHI ||
         TE->UserTreeIndex.UserTE->isAltShuffle()) &&
        !TE->UserTreeIndex.UserTE->hasCopyableElements()) {
      const TreeEntry *UserTE = TE->UserTreeIndex.UserTE;
      auto [It, Inserted] =
          UserTEScalarsUsedOutsideBlockCache.try_emplace(UserTE);
      if (Inserted)
        It->second = all_of(UserTE->Scalars,
                            [](Value *V) { return isUsedOutsideBlock(V); });
      if (!It->second)
        continue;
      Instruction &LastInst = getLastInstructionInBundle(UserTE);
      GatherEntries.emplace_back(TE.get(), &LastInst);
    }
  }
  for (auto &Entry : GatherEntries) {
    IRBuilderBase::InsertPointGuard Guard(Builder);
    Builder.SetInsertPoint(Entry.second);
    Builder.SetCurrentDebugLocation(Entry.second->getDebugLoc());
    (void)vectorizeTree(Entry.first);
  }
  // Emit the subtrees built for the splat gather nodes' unique scalars, so
  // the splat gathers can be emitted as their broadcasts. They go before the
  // gathered loads, which skip entries that already have a vector value.
  for (TreeEntry *TE :
       make_filter_range(SplatGatheredScalarsRoots, [&](TreeEntry *TE) {
         return !DeletedNodes.contains(TE) && !TE->VectorizedValue;
       }))
    (void)vectorizeTree(TE);
  // Emit gathered loads first to emit better code for the users of those
  // gathered loads.
  for (const std::unique_ptr<TreeEntry> &TE : make_filter_range(
           VectorizableTree, [&](const std::unique_ptr<TreeEntry> &TE) {
             return !DeletedNodes.contains(TE.get());
           })) {
    if (GatheredLoadsEntriesFirst.has_value() &&
        TE->Idx >= *GatheredLoadsEntriesFirst && !TE->VectorizedValue &&
        (!TE->isGather() || TE->UserTreeIndex)) {
      assert((TE->UserTreeIndex ||
              (TE->getOpcode() == Instruction::Load && !TE->isGather())) &&
             "Expected gathered load node.");
      (void)vectorizeTree(TE.get());
    }
  }
  (void)vectorizeTree(&getRootNode());
  // Run through the list of postponed gathers and emit them, replacing the temp
  // emitted allocas with actual vector instructions.
  ArrayRef<const TreeEntry *> PostponedNodes = PostponedGathers.getArrayRef();
  DenseMap<Value *, SmallVector<TreeEntry *>> PostponedValues;
  for (const TreeEntry *E : PostponedNodes) {
    auto *TE = const_cast<TreeEntry *>(E);
    auto *PrevVec = cast<Instruction>(TE->VectorizedValue);
    TE->VectorizedValue = nullptr;
    auto *UserI = cast<Instruction>(TE->UserTreeIndex.UserTE->VectorizedValue);
    // If user is a PHI node, its vector code have to be inserted right before
    // block terminator. Since the node was delayed, there were some unresolved
    // dependencies at the moment when stab instruction was emitted. In a case
    // when any of these dependencies turn out an operand of another PHI, coming
    // from this same block, position of a stab instruction will become invalid.
    // The is because source vector that supposed to feed this gather node was
    // inserted at the end of the block [after stab instruction]. So we need
    // to adjust insertion point again to the end of block.
    if (isa<PHINode>(UserI) ||
        (TE->UserTreeIndex.UserTE->hasState() &&
         TE->UserTreeIndex.UserTE->State != TreeEntry::SplitVectorize &&
         TE->UserTreeIndex.UserTE->getOpcode() == Instruction::PHI)) {
      // Insert before all users.
      Instruction *InsertPt = PrevVec->getParent()->getTerminator();
      for (User *U : PrevVec->users()) {
        if (U == UserI)
          continue;
        auto *UI = dyn_cast<Instruction>(U);
        if (!UI || isa<PHINode>(UI) || UI->getParent() != InsertPt->getParent())
          continue;
        if (UI->comesBefore(InsertPt))
          InsertPt = UI;
      }
      Builder.SetInsertPoint(InsertPt);
    } else {
      Builder.SetInsertPoint(PrevVec);
    }
    Builder.SetCurrentDebugLocation(UserI->getDebugLoc());
    Value *Vec = vectorizeTree(TE);
    if (auto *VecI = dyn_cast<Instruction>(Vec);
        VecI && VecI->getParent() == Builder.GetInsertBlock() &&
        Builder.GetInsertPoint()->comesBefore(VecI))
      VecI->moveBeforePreserving(*Builder.GetInsertBlock(),
                                 Builder.GetInsertPoint());
    if (Vec->getType() != PrevVec->getType()) {
      assert(Vec->getType()->isIntOrIntVectorTy() &&
             PrevVec->getType()->isIntOrIntVectorTy() &&
             "Expected integer vector types only.");
      std::optional<bool> IsSigned;
      for (Value *V : TE->Scalars) {
        if (isVectorized(V)) {
          for (const TreeEntry *MNTE : getTreeEntries(V)) {
            auto It = MinBWs.find(MNTE);
            if (It != MinBWs.end()) {
              IsSigned = IsSigned.value_or(false) || It->second.second;
              if (*IsSigned)
                break;
            }
          }
          if (IsSigned.value_or(false))
            break;
          // Scan through gather nodes.
          for (const TreeEntry *BVE : ValueToGatherNodes.lookup(V)) {
            auto It = MinBWs.find(BVE);
            if (It != MinBWs.end()) {
              IsSigned = IsSigned.value_or(false) || It->second.second;
              if (*IsSigned)
                break;
            }
          }
          if (IsSigned.value_or(false))
            break;
          if (auto *EE = dyn_cast<ExtractElementInst>(V)) {
            IsSigned =
                IsSigned.value_or(false) ||
                !isKnownNonNegative(EE->getVectorOperand(), SimplifyQuery(*DL));
            continue;
          }
          if (IsSigned.value_or(false))
            break;
        }
      }
      if (IsSigned.value_or(false)) {
        // Final attempt - check user node.
        auto It = MinBWs.find(TE->UserTreeIndex.UserTE);
        if (It != MinBWs.end())
          IsSigned = It->second.second;
      }
      assert(IsSigned &&
             "Expected user node or perfect diamond match in MinBWs.");
      Vec = Builder.CreateIntCast(Vec, PrevVec->getType(), *IsSigned);
    }
    PrevVec->replaceAllUsesWith(Vec);
    PostponedValues.try_emplace(Vec).first->second.push_back(TE);
    // Replace the stub vector node, if it was used before for one of the
    // buildvector nodes already.
    auto It = PostponedValues.find(PrevVec);
    if (It != PostponedValues.end()) {
      for (TreeEntry *VTE : It->getSecond())
        VTE->VectorizedValue = Vec;
    }
    eraseInstruction(PrevVec);
  }

  LLVM_DEBUG(dbgs() << "SLP: Extracting " << ExternalUses.size()
                    << " values .\n");

  SmallVector<ShuffledInsertData<Value *>> ShuffledInserts;
  // Maps vector instruction to original insertelement instruction
  DenseMap<Value *, InsertElementInst *> VectorToInsertElement;
  // Maps extract Scalar (plus the struct-field index path, when extracting
  // from a struct of vectors) to the corresponding extractelement instruction
  // in the basic block. Only one extractelement per block should be emitted.
  // The index path is stored in an owning SmallVector so the key remains
  // valid after the per-lane ExtractValueInst (whose Indices buffer it was
  // copied from) is erased later in this loop.
  SmallDenseMap<std::pair<Value *, SmallVector<unsigned, 1>>,
                DenseMap<BasicBlock *, std::pair<Value *, Value *>>>
      ScalarToEEs;
  // Maps (struct-of-vectors Vec, field-index path) to the corresponding
  // per-block extractvalue, so different external lanes that need the same
  // struct field of the same vectorized call share a single extractvalue.
  SmallDenseMap<std::pair<Value *, SmallVector<unsigned, 1>>,
                DenseMap<BasicBlock *, Value *>>
      StructFieldExtracts;
  SmallDenseSet<Value *, 4> UsedInserts;
  DenseMap<std::pair<Value *, Type *>, Value *> VectorCasts;
  SmallDenseSet<Value *, 4> ScalarsWithNullptrUser;
  SmallDenseSet<ExtractElementInst *, 4> IgnoredExtracts;
  // Extract all of the elements with the external uses.
  for (const auto &ExternalUse : ExternalUses) {
    Value *Scalar = ExternalUse.Scalar;
    llvm::User *User = ExternalUse.User;

    // Skip users that we already RAUW. This happens when one instruction
    // has multiple uses of the same value.
    if (User && !is_contained(Scalar->users(), User))
      continue;
    const TreeEntry *E = &ExternalUse.E;
    assert(E && "Invalid scalar");
    assert(!E->isGather() && "Extracting from a gather list");
    // Non-instruction pointers are not deleted, just skip them.
    if (E->getOpcode() == Instruction::GetElementPtr &&
        !isa<GetElementPtrInst>(Scalar))
      continue;

    Value *Vec = E->VectorizedValue;
    assert(Vec && "Can't find vectorizable value");

    auto ExtractAndExtendIfNeeded = [&](Value *Vec) {
      if (isa<InsertValueInst>(Scalar))
        return Vec;
      if (Scalar->getType() != Vec->getType()) {
        Value *Ex = nullptr;
        Value *ExV = nullptr;
        auto *Inst = dyn_cast<Instruction>(Scalar);
        bool ReplaceInst = Inst && ExternalUsesAsOriginalScalar.contains(Inst);
        // For struct-typed scalars, the User must be an ExtractValueInst that
        // describes which struct field is being extracted. Copy its indices
        // into an owning SmallVector so the cache key survives erasure of the
        // ExtractValueInst.
        SmallVector<unsigned, 1> Indices;
        if (isa<StructType>(Scalar->getType())) {
          assert(User && "User expected for StructType extract.");
          const auto *EV = cast<ExtractValueInst>(User);
          Indices.assign(EV->getIndices());
        }
        auto Key = std::make_pair(Scalar, Indices);
        auto It = ScalarToEEs.find(Key);
        if (It != ScalarToEEs.end()) {
          // No need to emit many extracts, just move the only one in the
          // current block.
          auto EEIt = It->second.find(ReplaceInst ? Inst->getParent()
                                                  : Builder.GetInsertBlock());
          if (EEIt != It->second.end()) {
            Value *PrevV = EEIt->second.first;
            if (auto *I = dyn_cast<Instruction>(PrevV);
                I && !ReplaceInst &&
                Builder.GetInsertPoint() != Builder.GetInsertBlock()->end() &&
                Builder.GetInsertPoint()->comesBefore(I)) {
              // For struct extracts the cached extractelement depends on a
              // cached extractvalue (FieldVec). Move FieldVec up first so it
              // still dominates the relocated extractelement after the move.
              if (isa<StructType>(Scalar->getType())) {
                auto FieldKey = std::make_pair(Vec, Indices);
                auto FieldIt = StructFieldExtracts.find(FieldKey);
                if (FieldIt != StructFieldExtracts.end()) {
                  auto BBIt = FieldIt->second.find(Builder.GetInsertBlock());
                  if (BBIt != FieldIt->second.end()) {
                    if (auto *FieldI = dyn_cast<Instruction>(BBIt->second);
                        FieldI &&
                        FieldI->getParent() == Builder.GetInsertBlock() &&
                        Builder.GetInsertPoint()->comesBefore(FieldI))
                      FieldI->moveBefore(*Builder.GetInsertBlock(),
                                         Builder.GetInsertPoint());
                  }
                }
              }
              I->moveBefore(*Builder.GetInsertPoint()->getParent(),
                            Builder.GetInsertPoint());
              if (auto *CI = dyn_cast<Instruction>(EEIt->second.second))
                CI->moveAfter(I);
            }
            Ex = PrevV;
            ExV = EEIt->second.second ? EEIt->second.second : Ex;
          }
        }
        if (!Ex) {
          // "Reuse" the existing extract to improve final codegen.
          if (ReplaceInst) {
            // Leave the instruction as is, if it cheaper extracts and all
            // operands are scalar.
            if (auto *EE = dyn_cast<ExtractElementInst>(Inst)) {
              IgnoredExtracts.insert(EE);
              Ex = EE;
            } else {
              auto *CloneInst = Inst->clone();
              CloneInst->insertBefore(Inst->getIterator());
              if (Inst->hasName())
                CloneInst->takeName(Inst);
              Ex = CloneInst;
            }
          } else if (auto *ES = dyn_cast<ExtractElementInst>(Scalar);
                     ES && isa<Instruction>(Vec)) {
            Value *V = ES->getVectorOperand();
            auto *IVec = cast<Instruction>(Vec);
            if (ArrayRef<TreeEntry *> ETEs = getTreeEntries(V); !ETEs.empty())
              V = ETEs.front()->VectorizedValue;
            if (auto *IV = dyn_cast<Instruction>(V);
                !IV || IV == Vec || IV->getParent() != IVec->getParent() ||
                IV->comesBefore(IVec))
              Ex = Builder.CreateExtractElement(V, ES->getIndexOperand());
            else
              Ex = Builder.CreateExtractElement(Vec, ExternalUse.Lane);
          } else if (auto *VecTy =
                         dyn_cast<FixedVectorType>(Scalar->getType())) {
            assert(Opts.slp_revec && "FixedVectorType is not expected.");
            unsigned VecTyNumElements = VecTy->getNumElements();
            // When REVEC is enabled, we need to extract a vector.
            // Note: The element size of Scalar may be different from the
            // element size of Vec.
            Ex = createExtractVector(Builder, Vec, VecTyNumElements,
                                     ExternalUse.Lane * VecTyNumElements);
          } else {
            if (isa<StructType>(Vec->getType())) {
              assert(isa<StructType>(Scalar->getType()) &&
                     "Vec is struct of vectors only when Scalar is struct.");
              auto FieldKey = std::make_pair(Vec, Indices);
              BasicBlock *EVBB = Builder.GetInsertBlock();
              Value *FieldVec = nullptr;
              auto FieldIt = StructFieldExtracts.find(FieldKey);
              if (FieldIt != StructFieldExtracts.end()) {
                auto BBIt = FieldIt->second.find(EVBB);
                if (BBIt != FieldIt->second.end())
                  FieldVec = BBIt->second;
              }
              if (!FieldVec) {
                FieldVec = Builder.CreateExtractValue(Vec, Indices);
                StructFieldExtracts[FieldKey][EVBB] = FieldVec;
              } else if (auto *FieldI = dyn_cast<Instruction>(FieldVec);
                         FieldI && Builder.GetInsertPoint() != EVBB->end() &&
                         Builder.GetInsertPoint()->comesBefore(FieldI)) {
                // Cached extractvalue is below the current insertion point;
                // move it up so the extractelement we are about to emit can
                // use it.
                FieldI->moveBefore(*EVBB, Builder.GetInsertPoint());
              }
              Vec = FieldVec;
            }
            if (Opts.slp_revec && isVectorizedTy(Scalar->getType())) {
              unsigned VecTyNumElements = getNumElements(Scalar->getType());
              // When REVEC is enabled, we need to extract a vector.
              // Note: The element size of Scalar may be different from the
              // element size of Vec.
              Ex = createExtractVector(Builder, Vec, VecTyNumElements,
                                       ExternalUse.Lane * VecTyNumElements);
            } else {
              Ex = Builder.CreateExtractElement(Vec, ExternalUse.Lane);
            }
          }
          // If necessary, sign-extend or zero-extend ScalarRoot
          // to the larger type.
          ExV = Ex;
          if (!isa<StructType>(Scalar->getType()) &&
              Scalar->getType() != Ex->getType())
            ExV = Builder.CreateIntCast(
                Ex, Scalar->getType(),
                !isKnownNonNegative(Scalar, SimplifyQuery(*DL)));
          auto *I = dyn_cast<Instruction>(Ex);
          ScalarToEEs[Key].try_emplace(I ? I->getParent() : &F->getEntryBlock(),
                                       std::make_pair(Ex, ExV));
          if (Inst && ExV != Inst && ExV->getType() == Inst->getType())
            redirectDbgValues(*Inst, *ExV);
        }
        // The then branch of the previous if may produce constants, since 0
        // operand might be a constant.
        if (auto *ExI = dyn_cast<Instruction>(Ex);
            ExI && !isa<PHINode>(ExI) && !mayHaveNonDefUseDependency(*ExI)) {
          GatherShuffleExtractSeq.insert(ExI);
          CSEBlocks.insert(ExI->getParent());
        }
        return ExV;
      }
      assert(isa<FixedVectorType>(Scalar->getType()) &&
             isa<InsertElementInst>(Scalar) &&
             "In-tree scalar of vector type is not insertelement?");
      auto *IE = cast<InsertElementInst>(Scalar);
      VectorToInsertElement.try_emplace(Vec, IE);
      return Vec;
    };
    // If User == nullptr, the Scalar remains as scalar in vectorized
    // instructions or is used as extra arg. Generate ExtractElement instruction
    // and update the record for this scalar in ExternallyUsedValues.
    if (!User) {
      if (!ScalarsWithNullptrUser.insert(Scalar).second)
        continue;
      assert(
          (ExternallyUsedValues.count(Scalar) ||
          ExternalUsesWithNonUsers.count(Scalar) ||
           ExternalUsesAsOriginalScalar.contains(Scalar) ||
           any_of(
               Scalar->users(),
               [&, TTI = TTI](llvm::User *U) {
                 if (ExternalUsesAsOriginalScalar.contains(U))
                   return true;
                 ArrayRef<TreeEntry *> UseEntries = getTreeEntries(U);
                 return !UseEntries.empty() &&
                        (E->State == TreeEntry::Vectorize ||
                         E->State == TreeEntry::StridedVectorize ||
                         E->State == TreeEntry::ExpandVectorize ||
                         E->State == TreeEntry::CompressVectorize ||
                         E->State == TreeEntry::BlendedLoadVectorize) &&
                        any_of(UseEntries, [&, TTI = TTI](TreeEntry *UseEntry) {
                          return (UseEntry->State == TreeEntry::Vectorize ||
                                  UseEntry->State ==
                                      TreeEntry::StridedVectorize ||
                                  UseEntry->State ==
                                      TreeEntry::ExpandVectorize ||
                                  UseEntry->State ==
                                      TreeEntry::CompressVectorize ||
                                  UseEntry->State ==
                                      TreeEntry::BlendedLoadVectorize) &&
                                 doesInTreeUserNeedToExtract(
                                     Scalar, getRootEntryInstruction(*UseEntry),
                                     TLI, TTI);
                        });
               })) &&
          "Scalar with nullptr User must be registered in "
          "ExternallyUsedValues map or remain as scalar in vectorized "
          "instructions");
      if (auto *VecI = dyn_cast<Instruction>(Vec)) {
        if (auto *PHI = dyn_cast<PHINode>(VecI)) {
          if (PHI->getParent()->isLandingPad())
            Builder.SetInsertPoint(std::next(
                PHI->getParent()->getLandingPadInst()->getIterator()));
          else
            Builder.SetInsertPoint(PHI->getParent()->getFirstNonPHIIt());
        } else {
          Builder.SetInsertPoint(std::next(VecI->getIterator()));
        }
      } else {
        Builder.SetInsertPoint(F->getEntryBlock().begin());
      }
      Value *NewInst = ExtractAndExtendIfNeeded(Vec);
      // Required to update internally referenced instructions.
      if (Scalar != NewInst) {
        assert((!isa<ExtractElementInst>(Scalar) ||
                !IgnoredExtracts.contains(cast<ExtractElementInst>(Scalar))) &&
               "Extractelements should not be replaced.");
        // Reduced values that are not operands of the reduction ops (e.g.
        // narrowed reduction leaves) lose all users once the tree scalars are
        // erased; keep the replacement alive for the reduction epilogue.
        bool NeedsProtection =
            UserIgnoreList && none_of(Scalar->users(), [&](llvm::User *U) {
              return UserIgnoreList->contains(U);
            });
        Scalar->replaceAllUsesWith(NewInst);
        if (NeedsProtection)
          if (auto *I = dyn_cast<Instruction>(NewInst))
            ExternalUseReplacements.insert(I);
      }
      continue;
    }

    if (auto *VU = dyn_cast<InsertElementInst>(User);
        VU && VU->getOperand(1) == Scalar) {
      // Skip if the scalar is another vector op or Vec is not an instruction.
      if (!Scalar->getType()->isVectorTy() && isa<Instruction>(Vec)) {
        if (auto *FTy = dyn_cast<FixedVectorType>(User->getType())) {
          if (!UsedInserts.insert(VU).second)
            continue;
          // Need to use original vector, if the root is truncated.
          auto BWIt = MinBWs.find(E);
          if (BWIt != MinBWs.end() && Vec->getType() != VU->getType()) {
            auto *ScalarTy = FTy->getElementType();
            auto Key = std::make_pair(Vec, ScalarTy);
            auto VecIt = VectorCasts.find(Key);
            if (VecIt == VectorCasts.end()) {
              IRBuilderBase::InsertPointGuard Guard(Builder);
              if (auto *IVec = dyn_cast<PHINode>(Vec)) {
                if (IVec->getParent()->isLandingPad())
                  Builder.SetInsertPoint(std::next(
                      IVec->getParent()->getLandingPadInst()->getIterator()));
                else
                  Builder.SetInsertPoint(
                      IVec->getParent()->getFirstNonPHIOrLifetime());
              } else if (auto *IVec = dyn_cast<Instruction>(Vec)) {
                Builder.SetInsertPoint(IVec->getNextNode());
              }
              Vec = Builder.CreateIntCast(
                  Vec,
                  getWidenedType(
                      ScalarTy,
                      cast<FixedVectorType>(Vec->getType())->getNumElements()),
                  BWIt->second.second);
              VectorCasts.try_emplace(Key, Vec);
            } else {
              Vec = VecIt->second;
            }
          }

          std::optional<unsigned> InsertIdx = getElementIndex(VU);
          if (InsertIdx) {
            auto *It = find_if(
                ShuffledInserts, [VU](const ShuffledInsertData<Value *> &Data) {
                  // Checks if 2 insertelements are from the same buildvector.
                  InsertElementInst *VecInsert = Data.InsertElements.front();
                  return areTwoInsertFromSameBuildVector(
                      VU, VecInsert,
                      [](InsertElementInst *II) { return II->getOperand(0); });
                });
            unsigned Idx = *InsertIdx;
            if (It == ShuffledInserts.end()) {
              (void)ShuffledInserts.emplace_back();
              It = std::next(ShuffledInserts.begin(),
                             ShuffledInserts.size() - 1);
            }
            SmallVectorImpl<int> &Mask = It->ValueMasks[Vec];
            if (Mask.empty())
              Mask.assign(FTy->getNumElements(), PoisonMaskElem);
            Mask[Idx] = ExternalUse.Lane;
            It->InsertElements.push_back(cast<InsertElementInst>(User));
            continue;
          }
        }
      }
    }

    // Generate extracts for out-of-tree users.
    // Find the insertion point for the extractelement lane.
    if (auto *VecI = dyn_cast<Instruction>(Vec)) {
      if (PHINode *PH = dyn_cast<PHINode>(User)) {
        for (unsigned I : seq<unsigned>(0, PH->getNumIncomingValues())) {
          if (PH->getIncomingValue(I) == Scalar) {
            Instruction *IncomingTerminator =
                PH->getIncomingBlock(I)->getTerminator();
            if (isa<CatchSwitchInst>(IncomingTerminator)) {
              Builder.SetInsertPoint(std::next(VecI->getIterator()));
            } else {
              Builder.SetInsertPoint(PH->getIncomingBlock(I)->getTerminator());
            }
            Value *NewInst = ExtractAndExtendIfNeeded(Vec);
            PH->setOperand(I, NewInst);
          }
        }
      } else {
        Builder.SetInsertPoint(cast<Instruction>(User));
        Value *NewInst = ExtractAndExtendIfNeeded(Vec);
        if (isa<StructType>(Scalar->getType()) &&
            isa_and_nonnull<ExtractValueInst>(User) &&
            !isa<StructType>(NewInst->getType())) {
          User->replaceAllUsesWith(NewInst);
          eraseInstruction(cast<Instruction>(User));
        } else {
          User->replaceUsesOfWith(Scalar, NewInst);
        }
      }
    } else {
      Builder.SetInsertPoint(F->getEntryBlock().begin());
      Value *NewInst = ExtractAndExtendIfNeeded(Vec);
      User->replaceUsesOfWith(Scalar, NewInst);
    }

    LLVM_DEBUG(dbgs() << "SLP: Replaced:" << *User << ".\n");
  }

  auto CreateShuffle = [&](Value *V1, Value *V2, ArrayRef<int> Mask) {
    SmallVector<int> CombinedMask1(Mask.size(), PoisonMaskElem);
    SmallVector<int> CombinedMask2(Mask.size(), PoisonMaskElem);
    int VF = cast<FixedVectorType>(V1->getType())->getNumElements();
    for (int I = 0, E = Mask.size(); I < E; ++I) {
      if (Mask[I] < VF)
        CombinedMask1[I] = Mask[I];
      else
        CombinedMask2[I] = Mask[I] - VF;
    }
    ShuffleInstructionBuilder ShuffleBuilder(
        cast<VectorType>(V1->getType())->getElementType(), Builder, *this);
    ShuffleBuilder.add(V1, CombinedMask1);
    if (V2)
      ShuffleBuilder.add(V2, CombinedMask2);
    return ShuffleBuilder.finalize({}, {}, {});
  };

  auto &&ResizeToVF = [&CreateShuffle](Value *Vec, ArrayRef<int> Mask,
                                       bool ForSingleMask) {
    unsigned VF = Mask.size();
    unsigned VecVF = cast<FixedVectorType>(Vec->getType())->getNumElements();
    if (VF != VecVF) {
      if (any_of(Mask, [VF](int Idx) { return Idx >= static_cast<int>(VF); })) {
        Vec = CreateShuffle(Vec, nullptr, Mask);
        return std::make_pair(Vec, true);
      }
      if (!ForSingleMask) {
        SmallVector<int> ResizeMask(VF, PoisonMaskElem);
        for (unsigned I = 0; I < VF; ++I) {
          if (Mask[I] != PoisonMaskElem)
            ResizeMask[Mask[I]] = Mask[I];
        }
        Vec = CreateShuffle(Vec, nullptr, ResizeMask);
      }
    }

    return std::make_pair(Vec, false);
  };
  // Perform shuffling of the vectorize tree entries for better handling of
  // external extracts.
  for (int I = 0, E = ShuffledInserts.size(); I < E; ++I) {
    // Find the first and the last instruction in the list of insertelements.
    sort(ShuffledInserts[I].InsertElements, isFirstInsertElement);
    InsertElementInst *FirstInsert = ShuffledInserts[I].InsertElements.front();
    InsertElementInst *LastInsert = ShuffledInserts[I].InsertElements.back();
    Builder.SetInsertPoint(LastInsert);
    auto Vector = ShuffledInserts[I].ValueMasks.takeVector();
    Value *NewInst = performExtractsShuffleAction<Value>(
        MutableArrayRef(Vector.data(), Vector.size()),
        FirstInsert->getOperand(0),
        [](Value *Vec) {
          return cast<VectorType>(Vec->getType())
              ->getElementCount()
              .getKnownMinValue();
        },
        ResizeToVF,
        [FirstInsert, &CreateShuffle](ArrayRef<int> Mask,
                                      ArrayRef<Value *> Vals) {
          assert((Vals.size() == 1 || Vals.size() == 2) &&
                 "Expected exactly 1 or 2 input values.");
          if (Vals.size() == 1) {
            // Do not create shuffle if the mask is a simple identity
            // non-resizing mask.
            if (Mask.size() != cast<FixedVectorType>(Vals.front()->getType())
                                   ->getNumElements() ||
                !ShuffleVectorInst::isIdentityMask(Mask, Mask.size()))
              return CreateShuffle(Vals.front(), nullptr, Mask);
            return Vals.front();
          }
          return CreateShuffle(Vals.front() ? Vals.front()
                                            : FirstInsert->getOperand(0),
                               Vals.back(), Mask);
        });
    auto It = ShuffledInserts[I].InsertElements.rbegin();
    // Rebuild buildvector chain.
    InsertElementInst *II = nullptr;
    if (It != ShuffledInserts[I].InsertElements.rend())
      II = *It;
    SmallVector<Instruction *> Inserts;
    while (It != ShuffledInserts[I].InsertElements.rend()) {
      assert(II && "Must be an insertelement instruction.");
      if (*It == II)
        ++It;
      else
        Inserts.push_back(II);
      II = dyn_cast<InsertElementInst>(II->getOperand(0));
    }
    for (Instruction *II : reverse(Inserts)) {
      II->replaceUsesOfWith(II->getOperand(0), NewInst);
      if (auto *NewI = dyn_cast<Instruction>(NewInst))
        if (II->getParent() == NewI->getParent() && II->comesBefore(NewI))
          II->moveAfter(NewI);
      NewInst = II;
    }
    LastInsert->replaceAllUsesWith(NewInst);
    for (InsertElementInst *IE : reverse(ShuffledInserts[I].InsertElements)) {
      IE->replaceUsesOfWith(IE->getOperand(0),
                            PoisonValue::get(IE->getOperand(0)->getType()));
      IE->replaceUsesOfWith(IE->getOperand(1),
                            PoisonValue::get(IE->getOperand(1)->getType()));
      eraseInstruction(IE);
    }
    CSEBlocks.insert(LastInsert->getParent());
  }

  SmallVector<Instruction *> RemovedInsts;
  // For each vectorized value:
  for (auto &TEPtr : VectorizableTree) {
    TreeEntry *Entry = TEPtr.get();

    // No need to handle users of gathered values.
    if (Entry->isGather() || Entry->State == TreeEntry::SplitVectorize ||
        DeletedNodes.contains(Entry) ||
        TransformedToGatherNodes.contains(Entry))
      continue;

    if (Entry->CombinedOp == TreeEntry::ReducedBitcast ||
        Entry->CombinedOp == TreeEntry::ReducedBitcastBSwap ||
        Entry->CombinedOp == TreeEntry::ReducedBitcastLoads ||
        Entry->CombinedOp == TreeEntry::ReducedBitcastBSwapLoads ||
        Entry->CombinedOp == TreeEntry::ReducedBitPack ||
        Entry->CombinedOp == TreeEntry::ReducedCmpBitcast) {
      // Skip constant node
      if (!Entry->hasState()) {
        assert(allConstant(Entry->Scalars) && "Expected constants only.");
        continue;
      }
      for (Instruction *I : make_isa_range<Instruction>(Entry->Scalars)) {
        if (Entry->isCopyableElement(I))
          continue;
        LLVM_DEBUG(dbgs() << "SLP: \tErasing scalar:" << *I << ".\n");
        RemovedInsts.push_back(I);
      }
      continue;
    }

    assert(Entry->VectorizedValue && "Can't find vectorizable value");

    // For each lane:
    for (int Lane = 0, LE = Entry->Scalars.size(); Lane != LE; ++Lane) {
      Value *Scalar = Entry->Scalars[Lane];

      if (Entry->getOpcode() == Instruction::GetElementPtr &&
          !isa<GetElementPtrInst>(Scalar))
        continue;
      if (auto *EE = dyn_cast<ExtractElementInst>(Scalar);
          EE && IgnoredExtracts.contains(EE))
        continue;
      if (!isa<Instruction>(Scalar) || Entry->isCopyableElement(Scalar))
        continue;
#ifndef NDEBUG
      Type *Ty = Scalar->getType();
      if (!Ty->isVoidTy()) {
        for (User *U : Scalar->users()) {
          LLVM_DEBUG(dbgs() << "SLP: \tvalidating user:" << *U << ".\n");

          // It is legal to delete users in the ignorelist.
          assert((isVectorized(U) ||
                  (UserIgnoreList && UserIgnoreList->contains(U)) ||
                  (isa_and_nonnull<Instruction>(U) &&
                   isDeleted(cast<Instruction>(U)))) &&
                 "Deleting out-of-tree value");
        }
      }
#endif
      LLVM_DEBUG(dbgs() << "SLP: \tErasing scalar:" << *Scalar << ".\n");
      auto *I = cast<Instruction>(Scalar);
      RemovedInsts.push_back(I);
    }

    // Erase peeled intermediates (not listed in Scalars), except the ones
    // kept because the tree still claims them.
    for (Value *V :
         make_filter_range(Entry->getReassocScalars(), [&](Value *V) {
           return !KeptReassocScalars.contains(V);
         })) {
#ifndef NDEBUG
      for (User *U : V->users()) {
        LLVM_DEBUG(dbgs() << "SLP: \tvalidating user:" << *U << ".\n");
        // Single-use peeled scalars are consumed by this entry or a sibling
        // in the same chain.
        assert((isVectorized(U) ||
                (UserIgnoreList && UserIgnoreList->contains(U)) ||
                (isa_and_nonnull<Instruction>(U) &&
                 isDeleted(cast<Instruction>(U)))) &&
               "Deleting out-of-tree value");
      }
#endif
      LLVM_DEBUG(dbgs() << "SLP: \tErasing scalar:" << *V << ".\n");
      RemovedInsts.push_back(cast<Instruction>(V));
    }
  }

  // Collect tree-entry vector instructions that ended up without any non-dead
  // uses (can happen with the non-power-of-2 paths, where intermediate vectors
  // get replaced but the original node still holds a reference).
  // FIXME: track and clear those references at replacement time instead of
  // sweeping after the fact. Done BEFORE mergeDIAssignID so any DIAssignID
  // from intermediate vectors is folded into the root vector instead of being
  // dropped on erase.
  {
    Value *RootVec = getRootNode().VectorizedValue;
    // Seed with the scalars already queued for removal - a vector whose only
    // user is a scalar-to-be-removed is also dead.
    SmallPtrSet<Value *, 16> DeadSet(RemovedInsts.begin(), RemovedInsts.end());
    auto AllUsesAreDead = [&](const Value *V) {
      return all_of(V->users(),
                    [&](const User *U) { return DeadSet.contains(U); });
    };
    SmallPtrSet<const Value *, 16> Candidates;
    SmallVector<Instruction *, 16> Worklist;
    for (const auto &TEPtr : VectorizableTree) {
      Value *VV = TEPtr->VectorizedValue;
      if (!VV || VV == RootVec || VV->getType()->isVoidTy() ||
          DeadSet.contains(VV))
        continue;
      auto *I = dyn_cast<Instruction>(VV);
      if (!I)
        continue;
      if (Candidates.insert(I).second)
        Worklist.push_back(I);
    }
    // Worklist sweep: when a vector becomes dead, its operand candidates
    // may have lost their last live user, so re-enqueue them. Cascaded dead
    // chains converge in O(N + total uses) instead of O(depth * N * uses).
    while (!Worklist.empty()) {
      Instruction *I = Worklist.pop_back_val();
      if (DeadSet.contains(I))
        continue;
      if (!I->use_empty() && !AllUsesAreDead(I))
        continue;
      DeadSet.insert(I);
      RemovedInsts.push_back(I);
      for (Instruction *OI : make_isa_range<Instruction>(I->operand_values()))
        if (Candidates.contains(OI) && !DeadSet.contains(OI))
          Worklist.push_back(OI);
    }
  }

  // Merge the DIAssignIDs from the about-to-be-deleted instructions into the
  // new vector instruction.
  if (auto *V = dyn_cast<Instruction>(getRootNode().VectorizedValue))
    V->mergeDIAssignID(RemovedInsts);

  // Clear up reduction references, if any.
  if (UserIgnoreList) {
    for (Instruction *I : RemovedInsts) {
      ArrayRef<TreeEntry *> Entries = getTreeEntries(I);
      // Dead intermediate vector instructions collected above have no tree
      // entry - nothing to unlink here.
      if (Entries.empty())
        continue;
      const TreeEntry *IE = Entries.front();
      if (ArrayRef<TreeEntry *> SplitEntries = getSplitTreeEntries(I);
          !SplitEntries.empty() && SplitEntries.front()->Idx < IE->Idx)
        IE = SplitEntries.front();
      if (IE->Idx != 0 &&
          !(getRootNode().isGather() && IE->UserTreeIndex &&
            (ValueToGatherNodes.lookup(I).contains(&getRootNode()) ||
             (IE->UserTreeIndex.UserTE == &getRootNode() &&
              IE->UserTreeIndex.EdgeIdx == UINT_MAX))) &&
          !(getRootNode().State == TreeEntry::SplitVectorize &&
            IE->UserTreeIndex && is_contained(getRootNodeScalars(), I)) &&
          !(GatheredLoadsEntriesFirst.has_value() &&
            IE->Idx >= *GatheredLoadsEntriesFirst && getRootNode().isGather() &&
            is_contained(getRootNodeScalars(), I)) &&
          !(!getRootNode().isGather() && getRootNode().isCopyableElement(I)) &&
          // Dropped narrowed reduction chain instructions may still use
          // non-root scalars; such uses must be cleared as well.
          none_of(I->users(),
                  [&](User *U) { return NarrowedChainInsts.contains(U); }))
        continue;
      SmallVector<SelectInst *> LogicalOpSelects;
      I->replaceUsesWithIf(PoisonValue::get(I->getType()), [&](Use &U) {
        // Do not replace condition of the logical op in form select <cond>.
        bool IsPoisoningLogicalOp = isa<SelectInst>(U.getUser()) &&
                                    (match(U.getUser(), m_LogicalAnd()) ||
                                     match(U.getUser(), m_LogicalOr())) &&
                                    U.getOperandNo() == 0;
        if (IsPoisoningLogicalOp) {
          LogicalOpSelects.push_back(cast<SelectInst>(U.getUser()));
          return false;
        }
        return UserIgnoreList->contains(U.getUser());
      });
      // Replace conditions of the poisoning logical ops with the non-poison
      // constant value.
      for (SelectInst *SI : LogicalOpSelects)
        SI->setCondition(Constant::getNullValue(SI->getCondition()->getType()));
    }
  }
  // Externally used values, which are not operands of the reduction ops (e.g.
  // gathered narrowed reduction leaves), may lose all users once the tree
  // scalars are erased; keep them alive for the reduction epilogue. Too many
  // users - keep conservatively.
  if (UserIgnoreList)
    for (Instruction *I : make_isa_range<Instruction>(ExternallyUsedValues))
      if (I->hasNUsesOrMore(UsesLimit) || none_of(I->users(), [&](User *U) {
            return UserIgnoreList->contains(U);
          }))
        ExternalUseReplacements.insert(I);
  // Retain to-be-deleted instructions for some debug-info bookkeeping and alias
  // cache correctness.
  // NOTE: removeInstructionAndOperands only marks the instruction for deletion
  // - instructions are not deleted until later.
  removeInstructionsAndOperands(ArrayRef(RemovedInsts), VectorValuesAndScales);
  // The emitted vectorized code and the erased scalars may invalidate the
  // cached analyses results.
  Cache.clear();

  // The new vector code may capture pointers that were previously not captured
  // (e.g. the pointer operands of a masked gather), so the capture results
  // cached in BatchAA are stale. Alias queries against the new instructions
  // would otherwise treat such pointers as inaccessible to them.
  BatchAA.emplace(*AA);

  Builder.ClearInsertionPoint();
  InstrElementSize.clear();

  const TreeEntry &RootTE = getRootNode();
  Value *Vec = RootTE.VectorizedValue;
  if (auto It = MinBWs.find(&RootTE); ReductionBitWidth != 0 &&
                                      It != MinBWs.end() &&
                                      ReductionBitWidth != It->second.first) {
    IRBuilder<>::InsertPointGuard Guard(Builder);
    Builder.SetInsertPoint(ReductionRoot->getIterator());
    if (isReducedBitcastRoot() || isReducedCmpBitcastRoot()) {
      Vec = Builder.CreateIntCast(Vec, Builder.getIntNTy(ReductionBitWidth),
                                  It->second.second);

    } else {
      Vec = Builder.CreateIntCast(
          Vec,
          VectorType::get(Builder.getIntNTy(ReductionBitWidth),
                          cast<VectorType>(Vec->getType())->getElementCount()),
          It->second.second);
    }
  }
  return Vec;
}

void BoUpSLP::optimizeGatherSequence() {
  LLVM_DEBUG(dbgs() << "SLP: Optimizing " << GatherShuffleExtractSeq.size()
                    << " gather sequences instructions.\n");
  // LICM InsertElementInst sequences.
  for (Instruction *I :
       make_filter_range(GatherShuffleExtractSeq,
                         [&](Instruction *I) { return !isDeleted(I); })) {
    // Check if this block is inside a loop.
    Loop *L = LI->getLoopFor(I->getParent());
    if (!L)
      continue;

    // Check if it has a preheader.
    BasicBlock *PreHeader = L->getLoopPreheader();
    if (!PreHeader)
      continue;

    // If the vector or the element that we insert into it are
    // instructions that are defined in this basic block then we can't
    // hoist this instruction.
    if (any_of(make_isa_range<Instruction>(I->operands()),
               [L](Instruction *OpI) { return L->contains(OpI); }))
      continue;

    // We can hoist this instruction. Move it to the pre-header.
    I->moveBefore(PreHeader->getTerminator()->getIterator());
    CSEBlocks.insert(PreHeader);
  }

  // Make a list of all reachable blocks in our CSE queue.
  SmallVector<const DomTreeNode *, 8> CSEWorkList;
  CSEWorkList.reserve(CSEBlocks.size());
  for (BasicBlock *BB : CSEBlocks)
    if (DomTreeNode *N = DT->getNode(BB))
      CSEWorkList.push_back(N);

  // Sort blocks by domination. This ensures we visit a block after all blocks
  // dominating it are visited.
  llvm::sort(CSEWorkList, [](const DomTreeNode *A, const DomTreeNode *B) {
    assert((A == B) == (A->getDFSNumIn() == B->getDFSNumIn()) &&
           "Different nodes should have different DFS numbers");
    return A->getDFSNumIn() < B->getDFSNumIn();
  });

  // Less defined shuffles can be replaced by the more defined copies.
  // Between two shuffles one is less defined if it has the same vector operands
  // and its mask indeces are the same as in the first one or undefs. E.g.
  // shuffle %0, poison, <0, 0, 0, undef> is less defined than shuffle %0,
  // poison, <0, 0, 0, 0>.
  auto &&IsIdenticalOrLessDefined = [this](Instruction *I1, Instruction *I2,
                                           SmallVectorImpl<int> &NewMask) {
    if (I1->getType() != I2->getType())
      return false;
    auto *SI1 = dyn_cast<ShuffleVectorInst>(I1);
    auto *SI2 = dyn_cast<ShuffleVectorInst>(I2);
    if (!SI1 || !SI2)
      return I1->isIdenticalTo(I2);
    if (SI1->isIdenticalTo(SI2))
      return true;
    for (int I = 0, E = SI1->getNumOperands(); I < E; ++I)
      if (SI1->getOperand(I) != SI2->getOperand(I))
        return false;
    // Check if the second instruction is more defined than the first one.
    NewMask.assign(SI2->getShuffleMask().begin(), SI2->getShuffleMask().end());
    ArrayRef<int> SM1 = SI1->getShuffleMask();
    // Count trailing undefs in the mask to check the final number of used
    // registers.
    unsigned LastUndefsCnt = 0;
    for (int I = 0, E = NewMask.size(); I < E; ++I) {
      if (SM1[I] == PoisonMaskElem)
        ++LastUndefsCnt;
      else
        LastUndefsCnt = 0;
      if (NewMask[I] != PoisonMaskElem && SM1[I] != PoisonMaskElem &&
          NewMask[I] != SM1[I])
        return false;
      if (NewMask[I] == PoisonMaskElem)
        NewMask[I] = SM1[I];
    }
    // Check if the last undefs actually change the final number of used vector
    // registers.
    return SM1.size() - LastUndefsCnt > 1 &&
           getNumberOfParts(SI1->getType(), SI1->getType()->getElementType()) ==
               getNumberOfParts(getWidenedType(SI1->getType()->getElementType(),
                                               SM1.size() - LastUndefsCnt),
                                SI1->getType()->getElementType());
  };
  // Perform O(N^2) search over the gather/shuffle sequences and merge identical
  // instructions. TODO: We can further optimize this scan if we split the
  // instructions into different buckets based on the insert lane.
  SmallVector<Instruction *, 16> Visited;
  for (auto I = CSEWorkList.begin(), E = CSEWorkList.end(); I != E; ++I) {
    assert(*I &&
           (I == CSEWorkList.begin() || !DT->dominates(*I, *std::prev(I))) &&
           "Worklist not sorted properly!");
    BasicBlock *BB = (*I)->getBlock();
    // For all instructions in blocks containing gather sequences:
    for (Instruction &In : llvm::make_early_inc_range(*BB)) {
      if (isDeleted(&In))
        continue;
      if (!isa<InsertElementInst, ExtractElementInst, ShuffleVectorInst>(&In) &&
          !GatherShuffleExtractSeq.contains(&In))
        continue;

      // Check if we can replace this instruction with any of the
      // visited instructions.
      bool Replaced = false;
      for (Instruction *&V : Visited) {
        SmallVector<int> NewMask;
        if (IsIdenticalOrLessDefined(&In, V, NewMask) &&
            DT->dominates(V->getParent(), In.getParent())) {
          In.replaceAllUsesWith(V);
          eraseInstruction(&In);
          if (auto *SI = dyn_cast<ShuffleVectorInst>(V))
            if (!NewMask.empty())
              SI->setShuffleMask(NewMask);
          Replaced = true;
          break;
        }
        if (isa<ShuffleVectorInst>(In) && isa<ShuffleVectorInst>(V) &&
            GatherShuffleExtractSeq.contains(V) &&
            IsIdenticalOrLessDefined(V, &In, NewMask) &&
            DT->dominates(In.getParent(), V->getParent())) {
          In.moveAfter(V);
          V->replaceAllUsesWith(&In);
          eraseInstruction(V);
          if (auto *SI = dyn_cast<ShuffleVectorInst>(&In))
            if (!NewMask.empty())
              SI->setShuffleMask(NewMask);
          V = &In;
          Replaced = true;
          break;
        }
      }
      if (!Replaced) {
        assert(!is_contained(Visited, &In));
        Visited.push_back(&In);
      }
    }
  }
  CSEBlocks.clear();
  GatherShuffleExtractSeq.clear();
}

BoUpSLP::ScheduleBundle &BoUpSLP::BlockScheduling::buildBundle(
    ArrayRef<Value *> VL, const InstructionsState &S, const EdgeInfo &EI) {
  auto &BundlePtr =
      ScheduledBundlesList.emplace_back(std::make_unique<ScheduleBundle>());
  for (Value *V : make_filter_range(
           VL, [&](Value *V) { return !S.isNonSchedulable(V); })) {
    auto *I = cast<Instruction>(V);
    if (S.isCopyableElement(V)) {
      // Add a copyable element model.
      ScheduleCopyableData &SD =
          addScheduleCopyableData(EI, I, SchedulingRegionID, *BundlePtr);
      // Group the instructions to a bundle.
      BundlePtr->add(&SD);
      continue;
    }
    ScheduleData *BundleMember = getScheduleData(V);
    assert(BundleMember && "no ScheduleData for bundle member "
                           "(maybe not in same basic block)");
    // Group the instructions to a bundle.
    BundlePtr->add(BundleMember);
    ScheduledBundles.try_emplace(I).first->getSecond().push_back(
        BundlePtr.get());
  }
  assert(BundlePtr && *BundlePtr && "Failed to find schedule bundle");
  return *BundlePtr;
}

// Groups the instructions to a bundle (which is then a single scheduling entity)
// and schedules instructions until the bundle gets ready.
std::optional<BoUpSLP::ScheduleBundle *>
BoUpSLP::BlockScheduling::tryScheduleBundle(ArrayRef<Value *> VL, BoUpSLP *SLP,
                                            const InstructionsState &S,
                                            const EdgeInfo &EI) {
  // No need to schedule PHIs, insertelement, extractelement and extractvalue
  // instructions.
  if (isa<PHINode>(S.getMainOp()) ||
      isVectorLikeInstWithConstOps(S.getMainOp()))
    return nullptr;
  bool HasCopyables = S.areInstructionsWithCopyableElements();
  bool DoesNotRequireScheduling =
      (!HasCopyables && doesNotNeedToSchedule(VL)) ||
      all_of(VL, [&](Value *V) { return S.isNonSchedulable(V); });
  if (S.areInstructionsWithCopyableElements() && EI && EI.UserTE->hasState() &&
      EI.UserTE->hasCopyableElements() &&
      EI.UserTE->getMainOp()->getParent() == S.getMainOp()->getParent() &&
      all_of(VL, [&](Value *V) {
        if (S.isCopyableElement(V))
          return true;
        return isUsedOutsideBlock(V);
      }))
    return std::nullopt;
  // Drop a copyable scalar if it has a same-block, non-PHI, non-schedulable
  // user that is reused outside this block via a non-PHI use. Dependency
  // tracking across multiple nodes may then be incorrect.
  if (S.areInstructionsWithCopyableElements() && EI && EI.UserTE->hasState() &&
      any_of(make_isa_range<Instruction>(VL), [&](Instruction *I) {
        if (!S.isCopyableElement(I))
          return false;
        return any_of(I->users(), [&](User *U) {
          auto *IU = dyn_cast<Instruction>(U);
          if (!IU || IU->getParent() != I->getParent())
            return false;
          return !isa<PHINode>(IU) && !IU->hasOneUse() &&
                 isUsedOutsideBlock(IU) &&
                 !all_of(IU->users(), IsaPred<PHINode>);
        });
      }))
    return std::nullopt;
  // If any instruction is used outside block only and its operand is placed
  // immediately before it, do not schedule, it may cause wrong def-use chain.
  if (S.areInstructionsWithCopyableElements() && any_of(VL, [&](Value *V) {
        if (isa<PoisonValue>(V) || S.isCopyableElement(V))
          return false;
        if (isUsedOutsideBlock(V)) {
          for (Instruction *I :
               make_isa_range<Instruction>(cast<Instruction>(V)->operands()))
            return SLP->isVectorized(I) && I->getNextNode() == V;
        }
        return false;
      }))
    return std::nullopt;
  if (S.areInstructionsWithCopyableElements() && EI) {
    bool IsNonSchedulableWithParentPhiNode =
        EI.UserTE->doesNotNeedToSchedule() && EI.UserTE->UserTreeIndex &&
        EI.UserTE->UserTreeIndex.UserTE->hasState() &&
        EI.UserTE->UserTreeIndex.UserTE->State != TreeEntry::SplitVectorize &&
        EI.UserTE->UserTreeIndex.UserTE->getOpcode() == Instruction::PHI;
    if (IsNonSchedulableWithParentPhiNode) {
      ArrayRef<Value *> PhiScalars = EI.UserTE->UserTreeIndex.UserTE->Scalars;
      for (const auto [Idx, V] : enumerate(PhiScalars)) {
        Value *Op = EI.UserTE->UserTreeIndex.UserTE->getOperand(
            EI.UserTE->UserTreeIndex.EdgeIdx)[Idx];
        auto *I = dyn_cast<Instruction>(Op);
        if (!I || !isCommutative(I))
          continue;
        // Bail out only when I has a user that is an instruction outside the
        // grandparent PHI's Scalars. Multiple uses that all land in the same
        // vectorized PHI are tracked by the existing dependency machinery;
        // uses outside it (e.g. a scalar PHI in a different block) break the
        // scheduler's dep accounting for non-schedulable copyable bundles.
        if (I->hasOneUse())
          continue;
        if (any_of(I->users(), [&](User *U) {
              auto *UI = dyn_cast<Instruction>(U);
              return UI && !is_contained(PhiScalars, UI);
            }))
          return std::nullopt;
      }
    } else {
      // If any of the parent requires scheduling - exit, complex dep between
      // schedulable/non-schedulable parents.
      if (any_of(EI.UserTE->Scalars, [&](Value *V) {
            if (EI.UserTE->hasCopyableElements() &&
                EI.UserTE->isCopyableElement(V))
              return false;
            ArrayRef<TreeEntry *> Entries = SLP->getTreeEntries(V);
            return any_of(Entries, [](const TreeEntry *TE) {
              return TE->doesNotNeedToSchedule() && TE->UserTreeIndex &&
                     TE->UserTreeIndex.UserTE->hasState() &&
                     TE->UserTreeIndex.UserTE->State !=
                         TreeEntry::SplitVectorize &&
                     TE->UserTreeIndex.UserTE->getOpcode() == Instruction::PHI;
            });
          }))
        return std::nullopt;
    }
  }
  // A scalar that is a non-copyable (i.e. really vectorized) element in this
  // PHI-operand node, but a copyable element in another PHI-operand node, is
  // vectorized here and only gathered/reused there. Both nodes feed different
  // incoming values of the same vectorized PHI and may be emitted in different
  // predecessor blocks, so the gathered reuse can end up not dominated by the
  // vectorized value, producing broken IR. Bail out of scheduling to avoid it.
  if (EI && EI.UserTE->State == TreeEntry::Vectorize &&
      EI.UserTE->getOpcode() == Instruction::PHI &&
      any_of(make_isa_range<Instruction>(VL), [&](Instruction *I) {
        if (HasCopyables && S.isCopyableElement(I))
          return false;
        return any_of(
            SLP->VectorizableTree, [&](const std::unique_ptr<TreeEntry> &TE) {
              return TE->UserTreeIndex &&
                     TE->UserTreeIndex.UserTE->State == TreeEntry::Vectorize &&
                     TE->UserTreeIndex.UserTE->getOpcode() ==
                         Instruction::PHI &&
                     TE->hasCopyableElements() && TE->isCopyableElement(I);
            });
      }))
    return std::nullopt;
  // A scalar that is a non-schedulable copyable element of another node in the
  // same block (not the user of this node) is reused at the insertion point of
  // that node, which does not depend on this node in the schedule. The
  // vectorized value of this node may be emitted after the reuse, producing
  // broken IR. Bail out of scheduling to avoid it.
  if (any_of(make_isa_range<Instruction>(VL), [&](Instruction *I) {
        if ((HasCopyables && S.isCopyableElement(I)) ||
            !doesNotNeedToBeScheduled(I))
          return false;
        return any_of(
            SLP->VectorizableTree, [&](const std::unique_ptr<TreeEntry> &TE) {
              return TE.get() != EI.UserTE && !TE->isGather() &&
                     TE->hasCopyableElements() && TE->isCopyableElement(I) &&
                     TE->getMainOp()->getParent() == I->getParent() &&
                     TE->getOperations().isNonSchedulable(I);
            });
      }))
    return std::nullopt;
  // The same conflict when the node with the real element is built first: a
  // non-schedulable copyable element of this node whose scalar is already
  // vectorized in another node of the block, or belongs to a split node, would
  // be reused from that node's vector, which may be emitted after this node.
  if (HasCopyables &&
      any_of(make_isa_range<Instruction>(VL), [&](Instruction *I) {
        return I->getParent() == BB && !isa<PHINode>(I) &&
               S.isCopyableElement(I) && S.isNonSchedulable(I) &&
               (SLP->isVectorized(I) || !SLP->getSplitTreeEntries(I).empty());
      }))
    return std::nullopt;
  if (DoesNotRequireScheduling) {
    // If all operands were replaced by copyables, the operands of this node
    // might be not, so need to recalculate dependencies for schedule data,
    // replaced by copyable schedule data.
    for (Instruction *I : make_isa_range<Instruction>(VL)) {
      if (HasCopyables && S.isCopyableElement(I))
        continue;
      // Expanded binops (e.g. shl X, 1 modeled as add X, X) double the
      // dependency count of the duplicated operand. This non-schedulable
      // path does not clear operand ScheduleData dependencies the way the
      // regular scheduling path does (see CheckIfNeedToClearDeps below), so
      // when that operand has more uses than this bundle member, or its
      // ScheduleData already has computed dependencies that did not see
      // the expanded duplicate use, the schedule's decrement count exceeds
      // calculateDependencies' increment count and UnscheduledDeps goes
      // negative. Bail out instead of producing an inconsistent schedule.
      if (S.isExpandedBinOp(I) &&
          any_of(enumerate(I->operands()), [&](const auto &P) {
            if (S.isExpandedOperand(I, P.index()))
              return false;
            auto *OpI = dyn_cast<Instruction>(P.value());
            if (!OpI)
              return false;
            if (!OpI->hasOneUse())
              return true;
            ScheduleData *SD = getScheduleData(OpI);
            return SD && SD->hasValidDependencies();
          }))
        return std::nullopt;
      SmallDenseMap<std::pair<Instruction *, Value *>, unsigned> UserOpToNumOps;
      for (const Use &U : I->operands()) {
        unsigned &NumOps =
            UserOpToNumOps.try_emplace(std::make_pair(I, U.get()), 0)
                .first->getSecond();
        ++NumOps;
        if (auto *Op = dyn_cast<Instruction>(U.get());
            Op && areAllOperandsReplacedByCopyableData(I, Op, *SLP, NumOps)) {
          if (ScheduleData *OpSD = getScheduleData(Op);
              OpSD && OpSD->hasValidDependencies())
            // TODO: investigate how to improve it instead of early exiting.
            return std::nullopt;
        }
      }
    }
    return nullptr;
  }

  // Any schedulable copyable with split vectorize parent - skip, not supported
  // currently.
  // TODO: investigate fix for this early exit.
  if (S.areInstructionsWithCopyableElements() && EI.UserTE &&
      EI.UserTE->State == TreeEntry::SplitVectorize &&
      any_of(VL, [&](Value *V) {
        return !S.isNonSchedulable(V) && S.isCopyableElement(V);
      }))
    return std::nullopt;

  // Reject modeling the duplicated source operand of an expanded binop as a
  // copyable element. shl X, 1 is represented as add X, X, so the parent uses X
  // on a second operand edge that stays a plain (gathered) operand. At schedule
  // time that duplicated use is decremented against X's own ScheduleData, which
  // calculateDependencies attributed to the copyable instead, so X's
  // unscheduled-deps counter goes negative and trips the assertion. Only the
  // values this bundle models as copyable that are the expanded binop source
  // operand are checked, matched by value so the detection is unaffected by the
  // parent node's operand reordering or reuse shuffle mask.
  // TODO: investigate modeling such operands correctly.
  if (S.areInstructionsWithCopyableElements() && EI.UserTE &&
      EI.UserTE->hasState()) {
    for (Value *V : make_filter_range(
             VL, [&](Value *V) { return S.isCopyableElement(V); })) {
      if (any_of(make_isa_range<Instruction>(EI.UserTE->Scalars),
                 [&](Instruction *I) {
                   return EI.UserTE->isExpandedBinOp(I) &&
                          I->getOperand(0) == V;
                 }))
        return std::nullopt;
    }
  }

  // The lanes cannot depend on each other, so the bundle with the operand of
  // another member is never scheduled.
  if (!HasCopyables &&
      any_of(make_isa_range<Instruction>(VL), [&](Instruction *I) {
        return any_of(I->operand_values(),
                      [&](const Value *Op) { return is_contained(VL, Op); });
      }))
    return std::nullopt;

  // Initialize the instruction bundle.
  Instruction *OldScheduleEnd = ScheduleEnd;
  LLVM_DEBUG(dbgs() << "SLP:  bundle: " << *S.getMainOp() << "\n");

  auto TryScheduleBundleImpl = [=](bool ReSchedule, ScheduleBundle &Bundle) {
    // Clear deps or recalculate the region, if the memory instruction is a
    // copyable. It may have memory deps, which must be recalculated.
    SmallVector<ScheduleData *> ControlDependentMembers;
    // Recompute the direct dependencies of copyable operands deferred by a
    // previously scheduled bundle. The node that introduced the extra direct
    // use is now part of the tree, so clearing and recalculating the
    // dependencies here accounts for that use.
    // If the schedule is not reset in this round, skip already scheduled
    // operands: clearing their dependencies also resets the scheduled flag,
    // so they would enter the ready list and be scheduled twice, decrementing
    // the dependency counts of their operands once too many.
    const bool WillReSchedule =
        ReSchedule || (OldScheduleEnd && ScheduleEnd != OldScheduleEnd);
    auto NeedsDependencyUpdate = [&](ScheduleData *SD) {
      return isInSchedulingRegion(*SD) &&
             (WillReSchedule || !SD->isScheduled());
    };
    for (ScheduleData *SD :
         make_filter_range(RecalcCopyableOperandDeps, NeedsDependencyUpdate)) {
      if (SD->hasValidDependencies())
        SD->clearDirectDependencies();
      ControlDependentMembers.push_back(SD);
    }
    RecalcCopyableOperandDeps.clear();
    auto CheckIfNeedToClearDeps = [&](ScheduleBundle &Bundle) {
      SmallDenseMap<std::pair<Instruction *, Value *>, unsigned> UserOpToNumOps;
      for (ScheduleEntity *SE : Bundle.getBundle()) {
        if (ScheduleCopyableData *SD = dyn_cast<ScheduleCopyableData>(SE)) {
          if (ScheduleData *BundleMember = getScheduleData(SD->getInst());
              BundleMember && BundleMember->hasValidDependencies()) {
            BundleMember->clearDirectDependencies();
            if (RegionHasStackSave ||
                !isGuaranteedToTransferExecutionToSuccessor(
                    BundleMember->getInst()) ||
                isWriteVisibleOnUnwind(BundleMember->getInst()))
              ControlDependentMembers.push_back(BundleMember);
          }
          continue;
        }
        auto *SD = cast<ScheduleData>(SE);
        if (SD->hasValidDependencies() &&
            (!S.areInstructionsWithCopyableElements() ||
             !S.isCopyableElement(SD->getInst())) &&
            !getScheduleCopyableData(SD->getInst()).empty() && EI.UserTE &&
            EI.UserTE->hasState() &&
            (!EI.UserTE->hasCopyableElements() ||
             !EI.UserTE->isCopyableElement(SD->getInst())))
          SD->clearDirectDependencies();
        const bool IsExpandedBinOp = S.isExpandedBinOp(SD->getInst());
        for (const Use &U : SD->getInst()->operands()) {
          unsigned &NumOps =
              UserOpToNumOps
                  .try_emplace(std::make_pair(SD->getInst(), U.get()), 0)
                  .first->getSecond();
          ++NumOps;
          auto *Op = dyn_cast<Instruction>(U.get());
          if (Op && areAllOperandsReplacedByCopyableData(SD->getInst(), Op,
                                                         *SLP, NumOps)) {
            if (ScheduleData *OpSD = getScheduleData(Op);
                OpSD && OpSD->hasValidDependencies()) {
              OpSD->clearDirectDependencies();
              if (RegionHasStackSave ||
                  !isGuaranteedToTransferExecutionToSuccessor(
                      OpSD->getInst()) ||
                  isWriteVisibleOnUnwind(OpSD->getInst()))
                ControlDependentMembers.push_back(OpSD);
              // areAllOperandsReplacedByCopyableData() returned true, so every
              // tree entry that currently contains this instruction models Op
              // as a copyable element and Op's recomputed dependencies do not
              // count this def-use edge. The bundle being scheduled is a new
              // node for the same instruction that is not registered in the
              // tree yet and that uses Op directly (Op is a real operand here).
              // Once that node is added to the tree the direct use must be
              // counted, otherwise the scheduler decrements Op more times than
              // its dependency count and trips the unscheduled-deps assertion.
              // Defer the operand's dependency recomputation to the next bundle
              // scheduling, when the new node is part of the tree and the
              // direct use is accounted for.
              RecalcCopyableOperandDeps.insert(OpSD);
              continue;
            }
          }
          if (IsExpandedBinOp) {
            if (ScheduleData *OpSD = getScheduleData(U.get());
                OpSD && OpSD->hasValidDependencies()) {
              OpSD->clearDirectDependencies();
              ControlDependentMembers.push_back(OpSD);
              continue;
            }
          }
          // areAllOperandsReplacedByCopyableData() can be false while Op is
          // still modeled as a copyable element in one or more already built
          // nodes (e.g. when another node that shares an instruction with this
          // one uses Op directly). This newly built node, not registered in the
          // tree yet, also uses Op directly, so Op's real ScheduleData
          // dependency count - which mixes direct def-use edges with copyable
          // uses - does not yet account for this direct use. Defer its
          // recomputation to the next bundle scheduling, when this node is part
          // of the tree, so the direct use is counted; otherwise the scheduler
          // decrements Op more times than its dependency count and trips the
          // unscheduled-deps assertion. Op's current dependencies are kept (not
          // cleared) so it stays schedulable for this bundle's dependency
          // calculation.
          if (Op) {
            if (ScheduleData *OpSD = getScheduleData(Op);
                OpSD && !getScheduleCopyableData(Op).empty())
              RecalcCopyableOperandDeps.insert(OpSD);
          }
        }
      }
    };
    // The scheduling region got new instructions at the lower end (or it is a
    // new region for the first bundle). This makes it necessary to
    // recalculate all dependencies.
    // It is seldom that this needs to be done a second time after adding the
    // initial bundle to the region.
    if (OldScheduleEnd && ScheduleEnd != OldScheduleEnd) {
      clearDependencies();
      ReSchedule = true;
    }
    SmallPtrSet<Value *, 4> ExpandedOps;
    for (Value *V : VL) {
      if (S.isExpandedBinOp(V))
        ExpandedOps.insert(V);
    }
    // Check if the bundle data has deps for copyable elements already. In
    // this case need to reset deps and recalculate it.
    if (Bundle && !Bundle.getBundle().empty()) {
      if (!ScheduleCopyableDataMap.empty() || !ExpandedOps.empty())
        CheckIfNeedToClearDeps(Bundle);
      LLVM_DEBUG(dbgs() << "SLP: try schedule bundle " << Bundle << " in block "
                        << BB->getName() << "\n");
      calculateDependencies(Bundle, /*InsertInReadyList=*/!ReSchedule, SLP,
                            ExpandedOps, ControlDependentMembers);
    } else if (!ControlDependentMembers.empty()) {
      ScheduleBundle Invalid = ScheduleBundle::invalid();
      calculateDependencies(Invalid, /*InsertInReadyList=*/!ReSchedule, SLP,
                            ExpandedOps, ControlDependentMembers);
    }

    if (ReSchedule) {
      resetSchedule();
      initialFillReadyList(ReadyInsts);
    }

    // Now try to schedule the new bundle or (if no bundle) just calculate
    // dependencies. As soon as the bundle is "ready" it means that there are no
    // cyclic dependencies and we can schedule it. Note that's important that we
    // don't "schedule" the bundle yet.
    while (((!Bundle && ReSchedule) || (Bundle && !Bundle.isReady())) &&
           !ReadyInsts.empty()) {
      ScheduleEntity *Picked = ReadyInsts.pop_back_val();
      assert(Picked->isReady() && "must be ready to schedule");
      schedule(*SLP, S, EI, Picked, ReadyInsts);
      if (Picked == &Bundle)
        break;
    }
  };

  // Make sure that the scheduling region contains all
  // instructions of the bundle.
  for (Value *V : make_filter_range(
           VL, [&](Value *V) { return !S.isNonSchedulable(V); })) {
    if (!extendSchedulingRegion(V, S)) {
      // If the scheduling region got new instructions at the lower end (or it
      // is a new region for the first bundle). This makes it necessary to
      // recalculate all dependencies.
      // Otherwise the compiler may crash trying to incorrectly calculate
      // dependencies and emit instruction in the wrong order at the actual
      // scheduling.
      ScheduleBundle Invalid = ScheduleBundle::invalid();
      TryScheduleBundleImpl(/*ReSchedule=*/false, Invalid);
      return std::nullopt;
    }
  }

  bool ReSchedule = false;
  for (Value *V : make_filter_range(
           VL, [&](Value *V) { return !S.isNonSchedulable(V); })) {
    SmallVector<ScheduleCopyableData *> CopyableData =
        getScheduleCopyableData(cast<Instruction>(V));
    if (!CopyableData.empty()) {
      for (ScheduleCopyableData *SD : CopyableData)
        ReadyInsts.remove(SD);
    }
    ScheduleData *BundleMember = getScheduleData(V);
    assert((BundleMember || S.isCopyableElement(V)) &&
           "no ScheduleData for bundle member (maybe not in same basic block)");
    if (!BundleMember)
      continue;

    // Make sure we don't leave the pieces of the bundle in the ready list when
    // whole bundle might not be ready.
    ReadyInsts.remove(BundleMember);
    if (ArrayRef<ScheduleBundle *> Bundles = getScheduleBundles(V);
        !Bundles.empty()) {
      for (ScheduleBundle *B : Bundles)
        ReadyInsts.remove(B);
    }

    if (!S.isCopyableElement(V) && !S.isExpandedBinOp(V) &&
        !BundleMember->isScheduled())
      continue;
    // A bundle member was scheduled as single instruction before and now
    // needs to be scheduled as part of the bundle. We just get rid of the
    // existing schedule.
    // A bundle member has deps calculated before it was copyable element - need
    // to reschedule.
    LLVM_DEBUG(dbgs() << "SLP:  reset schedule because " << *BundleMember
                      << " was already scheduled\n");
    ReSchedule = true;
  }

  ScheduleBundle &Bundle = buildBundle(VL, S, EI);
  TryScheduleBundleImpl(ReSchedule, Bundle);
  if (!Bundle.isReady()) {
    // Copyable data scheduling is just removed.
    for (ScheduleEntity *BD :
         make_filter_range(Bundle.getBundle(), [](ScheduleEntity *BD) {
           return !isa<ScheduleCopyableData>(BD);
         })) {
      if (BD->isReady()) {
        ArrayRef<ScheduleBundle *> Bundles = getScheduleBundles(BD->getInst());
        if (Bundles.empty()) {
          ReadyInsts.insert(BD);
          continue;
        }
        for (ScheduleBundle *B : Bundles)
          if (B->isReady())
            ReadyInsts.insert(B);
      }
    }
    cancelScheduling(Bundle);
    ScheduledBundlesList.pop_back();
    SmallVector<ScheduleData *> ControlDependentMembers;
    for (Value *V : make_filter_range(
             VL, [&](Value *V) { return !S.isNonSchedulable(V); })) {
      auto *I = cast<Instruction>(V);
      if (S.isExpandedBinOp(I)) {
        for (Value *Op : I->operands()) {
          if (ScheduleData *OpSD = getScheduleData(Op);
              OpSD && OpSD->hasValidDependencies()) {
            OpSD->clearDirectDependencies();
            ControlDependentMembers.push_back(OpSD);
          }
        }
      }
      if (S.isCopyableElement(I)) {
        // Need to recalculate dependencies for the actual schedule data, even
        // if they were already cleared by the failed bundle scheduling attempt.
        if (ScheduleData *OpSD = getScheduleData(I)) {
          OpSD->clearDirectDependencies();
          ControlDependentMembers.push_back(OpSD);
          if (any_of(VL, [&](Value *V) { return S.isExpandedBinOp(V); })) {
            // Clear scheduling data for all operands, if this node is operand
            // of the expanded instruction.
            for (Value *Op : I->operands()) {
              if (ScheduleData *OpSD = getScheduleData(Op);
                  OpSD && OpSD->hasValidDependencies()) {
                OpSD->clearDirectDependencies();
                ControlDependentMembers.push_back(OpSD);
              }
            }
          }
        }
      }
    }
    if (!ControlDependentMembers.empty()) {
      ScheduleBundle Invalid = ScheduleBundle::invalid();
      SmallPtrSet<Value *, 4> ExpandedOps;
      calculateDependencies(Invalid, /*InsertInReadyList=*/false, SLP,
                            ExpandedOps, ControlDependentMembers);
    }
    return std::nullopt;
  }
  return &Bundle;
}

BoUpSLP::ScheduleData *BoUpSLP::BlockScheduling::allocateScheduleDataChunks() {
  // Allocate a new ScheduleData for the instruction.
  if (ChunkPos >= ChunkSize) {
    ScheduleDataChunks.push_back(std::make_unique<ScheduleData[]>(ChunkSize));
    ChunkPos = 0;
  }
  return &(ScheduleDataChunks.back()[ChunkPos++]);
}

bool BoUpSLP::BlockScheduling::extendSchedulingRegion(
    Value *V, const InstructionsState &S) {
  Instruction *I = dyn_cast<Instruction>(V);
  assert(I && "bundle member must be an instruction");
  if (getScheduleData(I))
    return true;
  if (!ScheduleStart) {
    // It's the first instruction in the new region.
    initScheduleData(I, I->getNextNode(), nullptr, nullptr);
    ScheduleStart = I;
    ScheduleEnd = I->getNextNode();
    assert(ScheduleEnd && "tried to vectorize a terminator?");
    LLVM_DEBUG(dbgs() << "SLP:  initialize schedule region to " << *I << "\n");
    return true;
  }
  // Search up and down at the same time, because we don't know if the new
  // instruction is above or below the existing scheduling region.
  // Ignore debug info (and other "AssumeLike" intrinsics) so that's not counted
  // against the budget. Otherwise debug info could affect codegen.
  BasicBlock::reverse_iterator UpIter =
      ++ScheduleStart->getIterator().getReverse();
  BasicBlock::reverse_iterator UpperEnd = BB->rend();
  BasicBlock::iterator DownIter = ScheduleEnd->getIterator();
  BasicBlock::iterator LowerEnd = BB->end();
  // Never skip the looked-for instruction itself: a bundle member may be an
  // assume-like intrinsic (e.g. a copyable lane), and skipping it makes the
  // scan miss it and extend the region in the wrong direction.
  auto IsAssumeLikeIntr = [I](const Instruction &Cur) {
    auto *II = dyn_cast<IntrinsicInst>(&Cur);
    return &Cur != I && II && II->isAssumeLikeIntrinsic();
  };
  UpIter = std::find_if_not(UpIter, UpperEnd, IsAssumeLikeIntr);
  DownIter = std::find_if_not(DownIter, LowerEnd, IsAssumeLikeIntr);
  while (UpIter != UpperEnd && DownIter != LowerEnd && &*UpIter != I &&
         &*DownIter != I) {
    if (++ScheduleRegionSize > ScheduleRegionSizeLimit) {
      LLVM_DEBUG(dbgs() << "SLP:  exceeded schedule region size limit\n");
      return false;
    }

    ++UpIter;
    ++DownIter;

    UpIter = std::find_if_not(UpIter, UpperEnd, IsAssumeLikeIntr);
    DownIter = std::find_if_not(DownIter, LowerEnd, IsAssumeLikeIntr);
  }
  if (DownIter == LowerEnd || (UpIter != UpperEnd && &*UpIter == I)) {
    assert(I->getParent() == ScheduleStart->getParent() &&
           "Instruction is in wrong basic block.");
    initScheduleData(I, ScheduleStart, nullptr, FirstLoadStoreInRegion);
    ScheduleStart = I;
    LLVM_DEBUG(dbgs() << "SLP:  extend schedule region start to " << *I
                      << "\n");
    return true;
  }
  assert((UpIter == UpperEnd || (DownIter != LowerEnd && &*DownIter == I)) &&
         "Expected to reach top of the basic block or instruction down the "
         "lower end.");
  assert(I->getParent() == ScheduleEnd->getParent() &&
         "Instruction is in wrong basic block.");
  initScheduleData(ScheduleEnd, I->getNextNode(), LastLoadStoreInRegion,
                   nullptr);
  ScheduleEnd = I->getNextNode();
  assert(ScheduleEnd && "tried to vectorize a terminator?");
  LLVM_DEBUG(dbgs() << "SLP:  extend schedule region end to " << *I << "\n");
  return true;
}

void BoUpSLP::BlockScheduling::initScheduleData(Instruction *FromI,
                                                Instruction *ToI,
                                                ScheduleData *PrevLoadStore,
                                                ScheduleData *NextLoadStore) {
  ScheduleData *CurrentLoadStore = PrevLoadStore;
  for (Instruction *I = FromI; I != ToI; I = I->getNextNode()) {
    // No need to allocate data for non-schedulable instructions.
    if (isa<PHINode>(I))
      continue;
    ScheduleData *SD = ScheduleDataMap.lookup(I);
    if (!SD) {
      SD = allocateScheduleDataChunks();
      ScheduleDataMap[I] = SD;
    }
    assert(!isInSchedulingRegion(*SD) &&
           "new ScheduleData already in scheduling region");
    SD->init(SchedulingRegionID, I);

    auto CanIgnoreLoad = [](const Instruction *I) {
      const auto *LI = dyn_cast<LoadInst>(I);
      // If there is a simple load marked as invariant, we can ignore it.
      // But, in the (unlikely) case of non-simple invariant load,
      // we should not ignore it.
      return LI && LI->isSimple() &&
             LI->getMetadata(LLVMContext::MD_invariant_load);
    };

    if (I->mayReadOrWriteMemory() &&
        // Simple InvariantLoad does not depend on other memory accesses.
        !CanIgnoreLoad(I) &&
        (!isa<IntrinsicInst>(I) ||
         (cast<IntrinsicInst>(I)->getIntrinsicID() != Intrinsic::sideeffect &&
          cast<IntrinsicInst>(I)->getIntrinsicID() !=
              Intrinsic::pseudoprobe))) {
      // Update the linked list of memory accessing instructions.
      if (CurrentLoadStore) {
        CurrentLoadStore->setNextLoadStore(SD);
      } else {
        FirstLoadStoreInRegion = SD;
      }
      CurrentLoadStore = SD;
    }

    if (match(I, m_Intrinsic<Intrinsic::stacksave>()) ||
        match(I, m_Intrinsic<Intrinsic::stackrestore>()))
      RegionHasStackSave = true;
    if (I->mayThrow())
      RegionHasMayThrow = true;
  }
  if (NextLoadStore) {
    if (CurrentLoadStore)
      CurrentLoadStore->setNextLoadStore(NextLoadStore);
  } else {
    LastLoadStoreInRegion = CurrentLoadStore;
  }
}

void BoUpSLP::BlockScheduling::calculateDependencies(
    ScheduleBundle &Bundle, bool InsertInReadyList, BoUpSLP *SLP,
    const SmallPtrSetImpl<Value *> &ExpandedOps,
    ArrayRef<ScheduleData *> ControlDeps) {
  SmallVector<ScheduleEntity *> WorkList;
  auto ProcessNode = [&](ScheduleEntity *SE) {
    if (auto *CD = dyn_cast<ScheduleCopyableData>(SE)) {
      if (CD->hasValidDependencies())
        return;
      LLVM_DEBUG(dbgs() << "SLP:       update deps of " << *CD << "\n");
      CD->initDependencies();
      CD->resetUnscheduledDeps();
      const EdgeInfo &EI = CD->getEdgeInfo();
      if (EI.UserTE) {
        ArrayRef<Value *> Op = EI.UserTE->getOperand(EI.EdgeIdx);
        const auto *It = find(Op, CD->getInst());
        assert(It != Op.end() && "Lane not set");
        SmallPtrSet<Instruction *, 4> Visited;
        do {
          int Lane = std::distance(Op.begin(), It);
          assert(Lane >= 0 && "Lane not set");
          if (isa<StoreInst, InsertElementInst, InsertValueInst>(
                  EI.UserTE->Scalars[Lane]) &&
              !EI.UserTE->ReorderIndices.empty())
            Lane = std::distance(EI.UserTE->ReorderIndices.begin(),
                                 find(EI.UserTE->ReorderIndices, Lane));
          assert(Lane < static_cast<int>(EI.UserTE->Scalars.size()) &&
                 "Couldn't find extract lane");
          auto *In = cast<Instruction>(EI.UserTE->Scalars[Lane]);
          if (EI.UserTE->isCopyableElement(In)) {
            // We may have not have related copyable scheduling data, if the
            // instruction is non-schedulable.
            if (ScheduleCopyableData *UseSD =
                    getScheduleCopyableData(EI.UserTE->UserTreeIndex, In)) {
              CD->incDependencies();
              if (!UseSD->isScheduled())
                CD->incrementUnscheduledDeps(1);
              if (!UseSD->hasValidDependencies() ||
                  (InsertInReadyList && UseSD->isReady()))
                WorkList.push_back(UseSD);
            }
          } else if (Visited.insert(In).second) {
            if (ScheduleData *UseSD = getScheduleData(In)) {
              unsigned ExtraDeps = 1;
              // Increment twice, since the operand was expanded in binop.
              if (EI.UserTE->isExpandedBinOp(In))
                ExtraDeps = 2;
              for_each(seq(ExtraDeps),
                       [&](unsigned) { CD->incDependencies(); });
              if (!UseSD->isScheduled())
                CD->incrementUnscheduledDeps(ExtraDeps);
              if (!UseSD->hasValidDependencies() ||
                  (InsertInReadyList && UseSD->isReady()))
                WorkList.push_back(UseSD);
            }
          }
          It = find(make_range(std::next(It), Op.end()), CD->getInst());
        } while (It != Op.end());
        if (CD->isReady() && CD->getDependencies() == 0 &&
            (EI.UserTE->hasState() &&
             (EI.UserTE->getMainOp()->getParent() !=
                  CD->getInst()->getParent() ||
              (isa<PHINode>(EI.UserTE->getMainOp()) &&
               (EI.UserTE->getMainOp()->hasNUsesOrMore(UsesLimit) ||
                any_of(EI.UserTE->getMainOp()->users(), [&](User *U) {
                  auto *IU = dyn_cast<Instruction>(U);
                  if (!IU)
                    return true;
                  return IU->getParent() == EI.UserTE->getMainOp()->getParent();
                })))))) {
          // If no uses in the block - mark as having pseudo-use, which cannot
          // be scheduled.
          // Prevents incorrect def-use tracking between external user and
          // actual instruction.
          CD->incDependencies();
          CD->incrementUnscheduledDeps(1);
        }
      }
      return;
    }
    auto *BundleMember = cast<ScheduleData>(SE);
    if (BundleMember->hasValidDependencies())
      return;
    LLVM_DEBUG(dbgs() << "SLP:       update deps of " << *BundleMember << "\n");
    BundleMember->initDependencies();
    BundleMember->resetUnscheduledDeps();
    // Handle def-use chain dependencies.
    SmallDenseMap<Value *, unsigned> UserToNumOps;
    for (User *U : BundleMember->getInst()->users()) {
      if (isa<PHINode>(U))
        continue;
      if (ScheduleData *UseSD = getScheduleData(U)) {
        // The operand is a copyable element - skip.
        unsigned &NumOps = UserToNumOps.try_emplace(U, 0).first->getSecond();
        ++NumOps;
        if (areAllOperandsReplacedByCopyableData(
                cast<Instruction>(U), BundleMember->getInst(), *SLP, NumOps))
          continue;
        unsigned ExtraDeps = 1;
        // Increment twice, since the operand was expanded in binop.
        for (const TreeEntry *UserTE : SLP->getTreeEntries(U)) {
          if (UserTE->isExpandedBinOp(U))
            ++ExtraDeps;
        }
        if (ExpandedOps.contains(U))
          ++ExtraDeps;
        for_each(seq(ExtraDeps),
                 [&](unsigned) { BundleMember->incDependencies(); });
        if (!UseSD->isScheduled())
          BundleMember->incrementUnscheduledDeps(ExtraDeps);
        if (!UseSD->hasValidDependencies() ||
            (InsertInReadyList && UseSD->isReady()))
          WorkList.push_back(UseSD);
      }
    }
    for (ScheduleCopyableData *UseSD :
         getScheduleCopyableDataUsers(BundleMember->getInst())) {
      BundleMember->incDependencies();
      if (!UseSD->isScheduled())
        BundleMember->incrementUnscheduledDeps(1);
      if (!UseSD->hasValidDependencies() ||
          (InsertInReadyList && UseSD->isReady()))
        WorkList.push_back(UseSD);
    }

    SmallPtrSet<const Instruction *, 4> Visited;
    auto MakeControlDependent = [&](Instruction *I) {
      // Do not mark control dependent twice.
      if (!Visited.insert(I).second)
        return;
      auto *DepDest = getScheduleData(I);
      assert(DepDest && "must be in schedule window");
      DepDest->addControlDependency(BundleMember);
      BundleMember->incDependencies();
      if (!DepDest->isScheduled())
        BundleMember->incrementUnscheduledDeps(1);
      if (!DepDest->hasValidDependencies() ||
          (InsertInReadyList && DepDest->isReady()))
        WorkList.push_back(DepDest);
    };

    // Any instruction which isn't safe to speculate at the beginning of the
    // block is control depend on any early exit or non-willreturn call
    // which proceeds it.
    if (!isGuaranteedToTransferExecutionToSuccessor(BundleMember->getInst())) {
      for (Instruction *I = BundleMember->getInst()->getNextNode();
           I != ScheduleEnd; I = I->getNextNode()) {
        if (isSafeToSpeculativelyExecute(I, &*BB->begin(), SLP->AC))
          continue;

        // Add the dependency
        MakeControlDependent(I);

        if (!isGuaranteedToTransferExecutionToSuccessor(I))
          // Everything past here must be control dependent on I.
          break;
      }
    }

    // A write visible after unwinding must precede the next instruction that
    // may throw.
    if (isWriteVisibleOnUnwind(BundleMember->getInst())) {
      for (Instruction *I = BundleMember->getInst()->getNextNode();
           I != ScheduleEnd; I = I->getNextNode()) {
        if (!I->mayThrow())
          continue;

        // Add the dependency
        MakeControlDependent(I);
        break;
      }
    }

    if (RegionHasStackSave) {
      // If we have an inalloc alloca instruction, it needs to be scheduled
      // after any preceeding stacksave.  We also need to prevent any alloca
      // from reordering above a preceeding stackrestore.
      if (match(BundleMember->getInst(), m_Intrinsic<Intrinsic::stacksave>()) ||
          match(BundleMember->getInst(),
                m_Intrinsic<Intrinsic::stackrestore>())) {
        for (Instruction *I = BundleMember->getInst()->getNextNode();
             I != ScheduleEnd; I = I->getNextNode()) {
          if (match(I, m_Intrinsic<Intrinsic::stacksave>()) ||
              match(I, m_Intrinsic<Intrinsic::stackrestore>()))
            // Any allocas past here must be control dependent on I, and I
            // must be memory dependend on BundleMember->Inst.
            break;

          if (!isa<AllocaInst>(I))
            continue;

          // Add the dependency
          MakeControlDependent(I);
        }
      }

      // In addition to the cases handle just above, we need to prevent
      // allocas and loads/stores from moving below a stacksave or a
      // stackrestore. Avoiding moving allocas below stackrestore is currently
      // thought to be conservatism. Moving loads/stores below a stackrestore
      // can lead to incorrect code.
      if (isa<AllocaInst>(BundleMember->getInst()) ||
          BundleMember->getInst()->mayReadOrWriteMemory()) {
        for (Instruction *I = BundleMember->getInst()->getNextNode();
             I != ScheduleEnd; I = I->getNextNode()) {
          if (!match(I, m_Intrinsic<Intrinsic::stacksave>()) &&
              !match(I, m_Intrinsic<Intrinsic::stackrestore>()))
            continue;

          // Add the dependency
          MakeControlDependent(I);
          break;
        }
      }
    }

    // Handle the memory dependencies (if any).
    ScheduleData *NextLoadStore = BundleMember->getNextLoadStore();
    if (!NextLoadStore)
      return;
    Instruction *SrcInst = BundleMember->getInst();
    assert(SrcInst->mayReadOrWriteMemory() &&
           "NextLoadStore list for non memory effecting bundle?");
    MemoryLocation SrcLoc = getLocation(SrcInst);
    bool SrcMayWrite = SrcInst->mayWriteToMemory();
    unsigned NumAliased = 0;
    unsigned DistToSrc = 1;
    bool IsNonSimpleSrc = !SrcLoc.Ptr || !isSimple(SrcInst);

    for (ScheduleData *DepDest = NextLoadStore; DepDest;
         DepDest = DepDest->getNextLoadStore()) {
      assert(isInSchedulingRegion(*DepDest) && "Expected to be in region");

      // We have two limits to reduce the complexity:
      // 1) AliasedCheckLimit: It's a small limit to reduce calls to
      //    SLP->isAliased (which is the expensive part in this loop).
      // 2) MaxMemDepDistance: It's for very large blocks and it aborts
      //    the whole loop (even if the loop is fast, it's quadratic).
      //    It's important for the loop break condition (see below) to
      //    check this limit even between two read-only instructions.
      Instruction *DepInst = DepDest->getInst();
      bool MayConflict = SrcMayWrite || DepInst->mayWriteToMemory();
      if (DistToSrc >= MaxMemDepDistance ||
          (MayConflict && (IsNonSimpleSrc || NumAliased >= AliasedCheckLimit ||
                           SLP->isAliased(SrcLoc, SrcInst, DepInst)))) {
        // Try to turn a may-alias dependency between distinct, range-checkable
        // base objects into a runtime alias check. This covers both concrete
        // aliases and the conservative dependencies added once the
        // per-instruction alias-check limit is reached, so that a high alias
        // count cannot block a region that is otherwise versionable. The
        // dropped dependency is recorded so the final scheduleBlock()
        // recomputation keeps it dropped consistently.
        bool Dropped = false;
        if (MayConflict && SLP->Opts.slp_vectorize_with_runtime_alias_checks) {
          auto Key = std::make_pair(SrcInst, DepInst);
          // A dependency dropped during buildTree() must stay dropped on every
          // later recomputation (e.g. the final scheduleBlock()), independent
          // of the current mode, so the schedule remains consistent.
          if (IgnoredMemDeps.contains(Key)) {
            Dropped = true;
          } else if (SLP->isCoveredByExistingVersionCheck(BB, SrcInst,
                                                          DepInst)) {
            // This block is the fast path of an earlier versioning whose
            // runtime check already proved these bases disjoint, so the
            // dependency can be dropped without emitting a new check.
            Dropped = true;
          } else if (SLP->isTryingRuntimeAliasChecks()) {
            if (SLP->isRuntimeCheckableAliasPair(SrcInst, DepInst) &&
                SLP->recordRuntimeAliasCheck(BB, SrcInst, DepInst)) {
              IgnoredMemDeps.insert(Key);
              Dropped = true;
            }
          } else if (!SLP->hasNonCheckableMemBlocker()) {
            // A dependency on a non-simple access (call, a volatile/atomic, or
            // anything without a single load/store pointer) cannot be
            // range-checked, so it is a hard blocker a retry cannot drop. A
            // simple runtime-checkable may-alias pair could instead be dropped
            // by a runtime check. Other simple pairs (e.g. same base) are
            // resolved statically and are not blockers.
            if (IsNonSimpleSrc || !getLoadStorePointerOperand(DepInst) ||
                !isSimple(DepInst))
              SLP->setHasNonCheckableMemBlocker(true);
            else if (!SLP->hasRuntimeCheckableBlockers() &&
                     SLP->isRuntimeCheckableAliasPair(SrcInst, DepInst))
              SLP->setHasRuntimeCheckableBlockers(true);
          }
        }

        if (!Dropped) {
          // Count only kept dependencies toward the alias-check limit. Counting
          // dropped ones could prematurely trigger the conservative
          // (limit-based) dependencies above and add spurious dependencies
          // (e.g. between non-overlapping stores to the same base) that would
          // block scheduling of an otherwise versionable region.
          NumAliased++;
          DepDest->addMemoryDependency(BundleMember);
          BundleMember->incDependencies();
          if (!DepDest->isScheduled())
            BundleMember->incrementUnscheduledDeps(1);
          if (!DepDest->hasValidDependencies() ||
              (InsertInReadyList && DepDest->isReady()))
            WorkList.push_back(DepDest);
        }
      }

      // Example, explaining the loop break condition: Let's assume our
      // starting instruction is i0 and MaxMemDepDistance = 3.
      //
      //                      +--------v--v--v
      //             i0,i1,i2,i3,i4,i5,i6,i7,i8
      //             +--------^--^--^
      //
      // MaxMemDepDistance let us stop alias-checking at i3 and we add
      // dependencies from i0 to i3,i4,.. (even if they are not aliased).
      // Previously we already added dependencies from i3 to i6,i7,i8
      // (because of MaxMemDepDistance). As we added a dependency from
      // i0 to i3, we have transitive dependencies from i0 to i6,i7,i8
      // and we can abort this loop at i6.
      if (DistToSrc >= 2 * MaxMemDepDistance)
        break;
      DistToSrc++;
    }
  };

  assert((Bundle || !ControlDeps.empty()) &&
         "expected at least one instruction to schedule");
  if (Bundle)
    WorkList.push_back(Bundle.getBundle().front());
  WorkList.append(ControlDeps.begin(), ControlDeps.end());
  SmallPtrSet<ScheduleBundle *, 16> Visited;
  while (!WorkList.empty()) {
    ScheduleEntity *SD = WorkList.pop_back_val();
    SmallVector<ScheduleBundle *, 1> CopyableBundle;
    ArrayRef<ScheduleBundle *> Bundles;
    if (auto *CD = dyn_cast<ScheduleCopyableData>(SD)) {
      CopyableBundle.push_back(&CD->getBundle());
      Bundles = CopyableBundle;
    } else {
      Bundles = getScheduleBundles(SD->getInst());
    }
    if (Bundles.empty()) {
      if (!SD->hasValidDependencies())
        ProcessNode(SD);
      if (InsertInReadyList && SD->isReady()) {
        ReadyInsts.insert(SD);
        LLVM_DEBUG(dbgs() << "SLP:     gets ready on update: " << *SD << "\n");
      }
      continue;
    }
    for (ScheduleBundle *Bundle :
         make_filter_range(Bundles, [&](ScheduleBundle *Bundle) {
           return !Bundle->hasValidDependencies() &&
                  Visited.insert(Bundle).second;
         })) {
      assert(isInSchedulingRegion(*Bundle) &&
             "ScheduleData not in scheduling region");
      for_each(Bundle->getBundle(), ProcessNode);
    }
    if (InsertInReadyList && SD->isReady()) {
      for (ScheduleBundle *Bundle : Bundles) {
        assert(isInSchedulingRegion(*Bundle) &&
               "ScheduleData not in scheduling region");
        if (!Bundle->isReady())
          continue;
        ReadyInsts.insert(Bundle);
        LLVM_DEBUG(dbgs() << "SLP:     gets ready on update: " << *Bundle
                          << "\n");
      }
    }
  }
}

void BoUpSLP::BlockScheduling::resetSchedule() {
  assert(ScheduleStart &&
         "tried to reset schedule on block which has not been scheduled");
  for_each(ScheduleDataMap, [&](auto &P) {
    if (BB != P.first->getParent())
      return;
    ScheduleData *SD = P.second;
    if (isInSchedulingRegion(*SD)) {
      SD->setScheduled(/*Scheduled=*/false);
      SD->resetUnscheduledDeps();
    }
  });
  for_each(ScheduleCopyableDataMapByInst, [&](auto &P) {
    for_each(P.second, [&](ScheduleCopyableData *SD) {
      if (isInSchedulingRegion(*SD)) {
        SD->setScheduled(/*Scheduled=*/false);
        SD->resetUnscheduledDeps();
      }
    });
  });
  for_each(ScheduledBundles, [&](auto &P) {
    for_each(P.second, [&](ScheduleBundle *Bundle) {
      if (isInSchedulingRegion(*Bundle))
        Bundle->setScheduled(/*Scheduled=*/false);
    });
  });
  // Reset schedule data for copyable elements.
  for (auto &P : ScheduleCopyableDataMap) {
    if (isInSchedulingRegion(*P.second)) {
      P.second->setScheduled(/*Scheduled=*/false);
      P.second->resetUnscheduledDeps();
    }
  }
  ReadyInsts.clear();
}

void BoUpSLP::scheduleBlock(const BoUpSLP &R, BlockScheduling *BS) {
  if (!BS->ScheduleStart)
    return;

  LLVM_DEBUG(dbgs() << "SLP: schedule block " << BS->BB->getName() << "\n");

  // The scalars of the trimmed nodes are not vectorized and must not be
  // grouped as bundles. Cancel their bundles, recalculate all the dependencies
  // and schedule the scalars as separate instructions: they keep their
  // original order and stay close to their users.
  auto IsTrimmed = [&](const TreeEntry *TE) {
    return DeletedNodes.contains(TE) || TransformedToGatherNodes.contains(TE);
  };
  const size_t NumBundles = BS->ScheduledBundlesList.size();
  SmallPtrSet<const ScheduleData *, 16> ClearedSDs;
  erase_if(BS->ScheduledBundlesList,
           [&](const std::unique_ptr<ScheduleBundle> &Bundle) {
             const TreeEntry *TE = Bundle->getTreeEntry();
             if (!IsTrimmed(TE))
               return false;
             LLVM_DEBUG(dbgs() << "SLP: cancel scheduling of the trimmed node "
                               << TE->Idx << " bundle " << *Bundle << "\n");
             for (ScheduleEntity *SE : Bundle->getBundle())
               if (ScheduleData *SD = BS->getScheduleData(SE->getInst()))
                 ClearedSDs.insert(SD);
             BS->cancelScheduling(*Bundle);
             return true;
           });
  if (BS->ScheduledBundlesList.size() != NumBundles) {
    // Need to schedule all the instructions with the calculated dependencies,
    // not only the users of the remaining bundles, otherwise they are moved
    // above all the scheduled instructions.
    for (Instruction &I : make_range(BS->ScheduleStart->getIterator(),
                                     BS->ScheduleEnd->getIterator()))
      if (ScheduleData *SD = BS->getScheduleData(&I);
          SD && SD->hasValidDependencies())
        ClearedSDs.insert(SD);
    BS->clearDependencies();
  }

  // A key point - if we got here, pre-scheduling was able to find a valid
  // scheduling of the sub-graph of the scheduling window which consists
  // of all vector bundles and their transitive users.  As such, we do not
  // need to reschedule anything *outside of* that subgraph.

  BS->resetSchedule();

  // For the real scheduling we use a more sophisticated ready-list: it is
  // sorted by the original instruction location. This lets the final schedule
  // be as  close as possible to the original instruction order.
  // WARNING: If changing this order causes a correctness issue, that means
  // there is some missing dependence edge in the schedule data graph.
  struct ScheduleDataCompare {
    bool operator()(const ScheduleEntity *SD1,
                    const ScheduleEntity *SD2) const {
      return SD2->getSchedulingPriority() < SD1->getSchedulingPriority();
    }
  };
  std::set<ScheduleEntity *, ScheduleDataCompare> ReadyInsts;

  // Ensure that all dependency data is updated (for nodes in the sub-graph)
  // and fill the ready-list with initial instructions.
  int Idx = 0;
  for (auto *I = BS->ScheduleStart; I != BS->ScheduleEnd;
       I = I->getNextNode()) {
    ArrayRef<ScheduleBundle *> Bundles = BS->getScheduleBundles(I);
    if (!Bundles.empty()) {
      // An instruction that is modeled as a copyable element in some node may
      // also be used directly by another node that was registered only after
      // this instruction's dependencies were last computed. The deferred
      // copyable-operand recomputation (RecalcCopyableOperandDeps) is consumed
      // at the next bundle scheduling, which clears the operand's dependencies
      // before that node joins the tree, so the recomputation misses the
      // direct def-use edge and the count stays too low. The scheduler would
      // then decrement the instruction more times than its dependency count,
      // tripping the unscheduled-deps assertion. The whole tree is registered
      // now, so clear and recompute such dependencies against the full tree.
      if (ScheduleData *SD = BS->getScheduleData(I);
          SD && SD->hasValidDependencies() &&
          !BS->getScheduleCopyableData(I).empty())
        SD->clearDirectDependencies();
      for (ScheduleBundle *Bundle : Bundles) {
        Bundle->setSchedulingPriority(Idx++);
        if (const TreeEntry *TE = Bundle->getTreeEntry();
            TE && Bundle->hasValidDependencies() && TE->UserTreeIndex &&
            ((TE->UserTreeIndex.UserTE->State == TreeEntry::Vectorize &&
              TE->UserTreeIndex.UserTE->doesNotNeedToSchedule() &&
              any_of(TE->UserTreeIndex.UserTE->Scalars,
                     [&](Value *V) {
                       return TE->UserTreeIndex.UserTE->isExpandedBinOp(V);
                     })) ||
             (TE->UserTreeIndex.EdgeIdx == UINT_MAX &&
              TE->UserTreeIndex.UserTE->isGather()))) {
          for (ScheduleData *SD :
               make_isa_range<ScheduleData>(Bundle->getBundle()))
            SD->clearDirectDependencies();
        }
        if (!Bundle->hasValidDependencies()) {
          SmallPtrSet<Value *, 4> ExpandedOps;
          BS->calculateDependencies(*Bundle, /*InsertInReadyList=*/false, this,
                                    ExpandedOps);
        }
      }
      SmallVector<ScheduleCopyableData *> SDs = BS->getScheduleCopyableData(I);
      for (ScheduleCopyableData *SD : reverse(SDs)) {
        ScheduleBundle &Bundle = SD->getBundle();
        Bundle.setSchedulingPriority(Idx++);
        if (!Bundle.hasValidDependencies()) {
          SmallPtrSet<Value *, 4> ExpandedOps;
          BS->calculateDependencies(Bundle, /*InsertInReadyList=*/false, this,
                                    ExpandedOps);
        }
      }
      continue;
    }
    SmallVector<ScheduleCopyableData *> CopyableData =
        BS->getScheduleCopyableDataUsers(I);
    if (ScheduleData *SD = BS->getScheduleData(I)) {
      // The bundles of the trimmed nodes are cancelled, check the first
      // remaining node only.
      [[maybe_unused]] ArrayRef<TreeEntry *> SDTEs = getTreeEntries(I);
      [[maybe_unused]] const auto *SDTEIt = find_if_not(SDTEs, IsTrimmed);
      assert((isVectorLikeInstWithConstOps(SD->getInst()) ||
              SDTEIt == SDTEs.end() || (*SDTEIt)->doesNotNeedToSchedule() ||
              doesNotNeedToBeScheduled(I)) &&
             "scheduler and vectorizer bundle mismatch");
      SD->setSchedulingPriority(Idx++);
      if ((!SD->hasValidDependencies() && ClearedSDs.contains(SD)) ||
          !CopyableData.empty() ||
          any_of(R.ValueToGatherNodes.lookup(I), [&](const TreeEntry *TE) {
            assert(TE->isGather() && "expected gather node");
            return TE->hasState() && TE->hasCopyableElements() &&
                   TE->isCopyableElement(I);
          })) {
        SD->clearDirectDependencies();
        // Need to calculate deps for these nodes to correctly handle copyable
        // dependencies, even if they were cancelled.
        // If copyables bundle was cancelled, the deps are cleared and need to
        // recalculate them.
        ScheduleBundle Bundle;
        Bundle.add(SD);
        SmallPtrSet<Value *, 4> ExpandedOps;
        BS->calculateDependencies(Bundle, /*InsertInReadyList=*/false, this,
                                  ExpandedOps);
      }
    }
    for (ScheduleCopyableData *SD : reverse(CopyableData)) {
      ScheduleBundle &Bundle = SD->getBundle();
      Bundle.setSchedulingPriority(Idx++);
      if (!Bundle.hasValidDependencies()) {
        SmallPtrSet<Value *, 4> ExpandedOps;
        BS->calculateDependencies(Bundle, /*InsertInReadyList=*/false, this,
                                  ExpandedOps);
      }
    }
  }
  BS->initialFillReadyList(ReadyInsts);

  Instruction *LastScheduledInst = BS->ScheduleEnd;

  // Do the "real" scheduling.
  SmallPtrSet<Instruction *, 16> Scheduled;
  while (!ReadyInsts.empty()) {
    auto *Picked = *ReadyInsts.begin();
    ReadyInsts.erase(ReadyInsts.begin());

    // Move the scheduled instruction(s) to their dedicated places, if not
    // there yet.
    if (auto *Bundle = dyn_cast<ScheduleBundle>(Picked)) {
      for (const ScheduleEntity *BundleMember : Bundle->getBundle()) {
        Instruction *PickedInst = BundleMember->getInst();
        // If copyable must be schedule as part of something else, skip it.
        bool IsCopyable = Bundle->getTreeEntry()->isCopyableElement(PickedInst);
        if ((IsCopyable && BS->getScheduleData(PickedInst)) ||
            (!IsCopyable && !Scheduled.insert(PickedInst).second))
          continue;
        if (PickedInst->getNextNode() != LastScheduledInst)
          PickedInst->moveAfter(LastScheduledInst->getPrevNode());
        LastScheduledInst = PickedInst;
      }
      if (Bundle->getTreeEntry()->hasCopyableElements()) {
        Instruction *MainOp = Bundle->getTreeEntry()->getMainOp();
        for (Instruction *I :
             make_isa_range<Instruction>(Bundle->getTreeEntry()->Scalars))
          if (!I->hasOneUse() && Bundle->getTreeEntry()->isCopyableElement(I) &&
              I->getParent() == MainOp->getParent() &&
              doesNotNeedToBeScheduled(I) &&
              !Bundle->getTreeEntry()->getOperations().isNonSchedulable(I))
            I->moveBeforePreserving(LastScheduledInst->getIterator());
      }
      EntryToLastInstruction.try_emplace(Bundle->getTreeEntry(),
                                         LastScheduledInst);
    } else {
      auto *SD = cast<ScheduleData>(Picked);
      Instruction *PickedInst = SD->getInst();
      if (PickedInst->getNextNode() != LastScheduledInst)
        PickedInst->moveAfter(LastScheduledInst->getPrevNode());
      LastScheduledInst = PickedInst;
    }
    auto Invalid = InstructionsState::invalid();
    BS->schedule(R, Invalid, EdgeInfo(), Picked, ReadyInsts);
  }

  // Check that we didn't break any of our invariants.
#ifdef EXPENSIVE_CHECKS
  BS->verify();
#endif

#if !defined(NDEBUG) || defined(EXPENSIVE_CHECKS)
  // Check that all schedulable entities got scheduled
  for (auto *I = BS->ScheduleStart; I != BS->ScheduleEnd;
       I = I->getNextNode()) {
    ArrayRef<ScheduleBundle *> Bundles = BS->getScheduleBundles(I);
    assert(all_of(Bundles,
                  [](const ScheduleBundle *Bundle) {
                    return Bundle->isScheduled();
                  }) &&
           "must be scheduled at this point");
  }
#endif

  // Avoid duplicate scheduling of the block.
  BS->ScheduleStart = nullptr;
}

unsigned BoUpSLP::getVectorElementSize(Value *V) {
  // If V is a store, just return the width of the stored value (or value
  // truncated just before storing) without traversing the expression tree.
  // This is the common case.
  if (auto *Store = dyn_cast<StoreInst>(V))
    return DL->getTypeSizeInBits(Store->getValueOperand()->getType());

  if (auto *IEI = dyn_cast<InsertElementInst>(V))
    return getVectorElementSize(IEI->getOperand(1));

  if (auto *IVI = dyn_cast<InsertValueInst>(V))
    return getVectorElementSize(IVI->getOperand(1));

  auto E = InstrElementSize.find(V);
  if (E != InstrElementSize.end())
    return E->second;

  // If V is not a store, we can traverse the expression tree to find loads
  // that feed it. The type of the loaded value may indicate a more suitable
  // width than V's type. We want to base the vector element size on the width
  // of memory operations where possible.
  SmallVector<std::tuple<Instruction *, BasicBlock *, unsigned>> Worklist;
  SmallPtrSet<Instruction *, 16> Visited;
  if (auto *I = dyn_cast<Instruction>(V)) {
    Worklist.emplace_back(I, I->getParent(), 0);
    Visited.insert(I);
  }

  // Traverse the expression tree in bottom-up order looking for loads. If we
  // encounter an instruction we don't yet handle, we give up.
  auto Width = 0u;
  Value *FirstNonBool = nullptr;
  while (!Worklist.empty()) {
    auto [I, Parent, Level] = Worklist.pop_back_val();

    // We should only be looking at scalar instructions here. If the current
    // instruction has a vector type, skip.
    auto *Ty = I->getType();
    if (isa<VectorType>(Ty))
      continue;
    if (Ty != Builder.getInt1Ty() && !FirstNonBool)
      FirstNonBool = I;
    if (Level > Opts.slp_recursion_max_depth)
      continue;

    // Can we propagate widths through a call instruction
    // We can for simple intrinsics
    auto IsCompatibleIntrinsic = [](const Instruction *I) -> bool {
      const auto *CI = dyn_cast<IntrinsicInst>(I);
      if (!CI)
        return false;
      switch (CI->getIntrinsicID()) {
      case Intrinsic::abs:
      case Intrinsic::fabs:
      case Intrinsic::fma:
      case Intrinsic::fmuladd:
        return true;
      default:
        return false;
      }
    };
    // If the current instruction is a load, update MaxWidth to reflect the
    // width of the loaded value.
    if (isa<LoadInst, ExtractElementInst, ExtractValueInst>(I))
      Width = std::max<unsigned>(Width, DL->getTypeSizeInBits(Ty));

    // Otherwise, we need to visit the operands of the instruction. We only
    // handle the interesting cases from buildTree here. If an operand is an
    // instruction we haven't yet visited and from the same basic block as the
    // user or the use is a PHI node, we add it to the worklist.
    else if (isa<PHINode, CastInst, GetElementPtrInst, CmpInst, SelectInst,
                 BinaryOperator, UnaryOperator>(I) ||
             IsCompatibleIntrinsic(I)) {
      for (Use &U : I->operands()) {
        if (auto *J = dyn_cast<Instruction>(U.get()))
          if (Visited.insert(J).second &&
              (isa<PHINode>(I) || J->getParent() == Parent)) {
            Worklist.emplace_back(J, J->getParent(), Level + 1);
            continue;
          }
        if (!FirstNonBool && U.get()->getType() != Builder.getInt1Ty())
          FirstNonBool = U.get();
      }
    } else {
      break;
    }
  }

  // If we didn't encounter a memory access in the expression tree, or if we
  // gave up for some reason, just return the width of V. Otherwise, return the
  // maximum width we found.
  if (!Width) {
    if (V->getType() == Builder.getInt1Ty() && FirstNonBool)
      V = FirstNonBool;
    Width = DL->getTypeSizeInBits(V->getType());
  }

  for (Instruction *I : Visited)
    InstrElementSize[I] = Width;

  return Width;
}

bool BoUpSLP::collectValuesToDemote(
    const TreeEntry &E, bool IsProfitableToDemoteRoot, unsigned &BitWidth,
    SmallVectorImpl<unsigned> &ToDemote, DenseSet<const TreeEntry *> &Visited,
    const SmallDenseSet<unsigned, 8> &NodesToKeepBWs, unsigned &MaxDepthLevel,
    bool &IsProfitableToDemote, bool IsTruncRoot) const {
  // We can always demote constants.
  if (all_of(E.Scalars, IsaPred<Constant>))
    return true;

  unsigned OrigBitWidth =
      DL->getTypeSizeInBits(E.Scalars.front()->getType()->getScalarType());
  if (OrigBitWidth == BitWidth) {
    MaxDepthLevel = 1;
    return true;
  }

  // Check if the node was analyzed already and must keep its original bitwidth.
  if (NodesToKeepBWs.contains(E.Idx))
    return false;

  // If the value is not a vectorized instruction in the expression and not used
  // by the insertelement instruction and not used in multiple vector nodes, it
  // cannot be demoted.
  bool IsSignedNode = any_of(E.Scalars, [&](Value *R) {
    if (isa<PoisonValue>(R))
      return false;
    return !isKnownNonNegative(R, SimplifyQuery(*DL));
  });
  auto IsPotentiallyTruncated = [&](Value *V, unsigned &BitWidth) -> bool {
    if (isa<PoisonValue>(V))
      return true;
    if (getTreeEntries(V).size() > 1)
      return false;
    // For lat shuffle of sext/zext with many uses need to check the extra bit
    // for unsigned values, otherwise may have incorrect casting for reused
    // scalars.
    bool IsSignedVal = !isKnownNonNegative(V, SimplifyQuery(*DL));
    if ((!IsSignedNode || IsSignedVal) && OrigBitWidth > BitWidth) {
      APInt Mask = APInt::getBitsSetFrom(OrigBitWidth, BitWidth);
      if (MaskedValueIsZero(V, Mask, SimplifyQuery(*DL)))
        return true;
    }
    unsigned NumSignBits = ComputeNumSignBits(V, *DL, AC, nullptr, DT);
    unsigned BitWidth1 = OrigBitWidth - NumSignBits;
    if (IsSignedNode)
      ++BitWidth1;
    if (auto *I = dyn_cast<Instruction>(V)) {
      APInt Mask = DB->getDemandedBits(I);
      unsigned BitWidth2 =
          std::max<unsigned>(1, Mask.getBitWidth() - Mask.countl_zero());
      while (!IsSignedNode && BitWidth2 < OrigBitWidth) {
        APInt Mask = APInt::getBitsSetFrom(OrigBitWidth, BitWidth2 - 1);
        if (MaskedValueIsZero(V, Mask, SimplifyQuery(*DL)))
          break;
        BitWidth2 *= 2;
      }
      BitWidth1 = std::min(BitWidth1, BitWidth2);
    }
    BitWidth = std::max(BitWidth, BitWidth1);
    return BitWidth > 0 && OrigBitWidth >= (BitWidth * 2);
  };
  auto FinalAnalysis = [&]() {
    if (!IsProfitableToDemote)
      return false;
    bool Res = all_of(
        E.Scalars, std::bind(IsPotentiallyTruncated, _1, std::ref(BitWidth)));
    // Demote gathers.
    if (Res && E.isGather()) {
      if (E.hasState()) {
        if (const TreeEntry *SameTE =
                getSameValuesTreeEntry(E.getMainOp(), E.Scalars))
          if (collectValuesToDemote(*SameTE, IsProfitableToDemoteRoot, BitWidth,
                                    ToDemote, Visited, NodesToKeepBWs,
                                    MaxDepthLevel, IsProfitableToDemote,
                                    IsTruncRoot)) {
            ToDemote.push_back(E.Idx);
            return true;
          }
      }
      // Check possible extractelement instructions bases and final vector
      // length.
      SmallPtrSet<Value *, 4> UniqueBases;
      for (ExtractElementInst *EE :
           make_isa_range<ExtractElementInst>(E.Scalars))
        UniqueBases.insert(EE->getVectorOperand());
      const unsigned VF = E.Scalars.size();
      Type *OrigScalarTy = E.Scalars.front()->getType();
      if (UniqueBases.size() <= 2 ||
          getNumberOfParts(getWidenedType(OrigScalarTy, VF), OrigScalarTy) >=
              getNumberOfParts(
                  getWidenedType(
                      IntegerType::get(OrigScalarTy->getContext(), BitWidth),
                      VF),
                  IntegerType::get(OrigScalarTy->getContext(), BitWidth))) {
        ToDemote.push_back(E.Idx);
        return true;
      }
    }
    return Res;
  };
  if (E.isGather() || !Visited.insert(&E).second ||
      any_of(E.Scalars, [&](Value *V) {
        return !isa<Constant>(V) && all_of(V->users(), [&](User *U) {
          return isa<InsertElementInst>(U) && !isVectorized(U);
        });
      }))
    return FinalAnalysis();

  if (any_of(E.Scalars, [&](Value *V) {
        return !isa<Constant>(V) && !all_of(V->users(), [=](User *U) {
          return isVectorized(U) ||
                 (E.Idx == 0 && UserIgnoreList &&
                  UserIgnoreList->contains(U)) ||
                 (!isa<CmpInst>(U) && U->getType()->isSized() &&
                  !U->getType()->isScalableTy() &&
                  DL->getTypeSizeInBits(U->getType()) <= BitWidth);
        }) && !IsPotentiallyTruncated(V, BitWidth);
      }))
    return false;

  auto ProcessOperands = [&](ArrayRef<const TreeEntry *> Operands,
                             bool &NeedToExit) {
    NeedToExit = false;
    unsigned InitLevel = MaxDepthLevel;
    for (const TreeEntry *Op : Operands) {
      unsigned Level = InitLevel;
      if (!collectValuesToDemote(*Op, IsProfitableToDemoteRoot, BitWidth,
                                 ToDemote, Visited, NodesToKeepBWs, Level,
                                 IsProfitableToDemote, IsTruncRoot)) {
        if (!IsProfitableToDemote)
          return false;
        NeedToExit = true;
        if (!FinalAnalysis())
          return false;
        continue;
      }
      MaxDepthLevel = std::max(MaxDepthLevel, Level);
    }
    return true;
  };
  auto AttemptCheckBitwidth =
      [&](function_ref<bool(unsigned, unsigned)> Checker, bool &NeedToExit) {
        // Try all bitwidth < OrigBitWidth.
        NeedToExit = false;
        unsigned BestFailBitwidth = 0;
        for (; BitWidth < OrigBitWidth; BitWidth *= 2) {
          if (Checker(BitWidth, OrigBitWidth))
            return true;
          if (BestFailBitwidth == 0 && FinalAnalysis())
            BestFailBitwidth = BitWidth;
        }
        if (BitWidth >= OrigBitWidth) {
          if (BestFailBitwidth == 0) {
            BitWidth = OrigBitWidth;
            return false;
          }
          MaxDepthLevel = 1;
          BitWidth = BestFailBitwidth;
          NeedToExit = true;
          return true;
        }
        return false;
      };
  auto TryProcessInstruction =
      [&](unsigned &BitWidth, ArrayRef<const TreeEntry *> Operands = {},
          function_ref<bool(unsigned, unsigned)> Checker = {}) {
        if (Operands.empty()) {
          if (!IsTruncRoot)
            MaxDepthLevel = 1;
          for (Value *V : E.Scalars)
            (void)IsPotentiallyTruncated(V, BitWidth);
        } else {
          // Several vectorized uses? Check if we can truncate it, otherwise -
          // exit.
          if (any_of(E.Scalars, [&](Value *V) {
                return !V->hasOneUse() && !IsPotentiallyTruncated(V, BitWidth);
              }))
            return false;
          bool NeedToExit = false;
          if (Checker && !AttemptCheckBitwidth(Checker, NeedToExit))
            return false;
          if (NeedToExit)
            return true;
          if (!ProcessOperands(Operands, NeedToExit))
            return false;
          if (NeedToExit)
            return true;
        }

        ++MaxDepthLevel;
        // Record the entry that we can demote.
        ToDemote.push_back(E.Idx);
        return IsProfitableToDemote;
      };
  // The operand count is not always two: a flattened node has one entry per
  // reassociated column. Collect the entries by the actual number of operand
  // columns.
  auto GetOperandEntries = [&]() {
    return map_to_vector(seq<unsigned>(E.getNumOperands()),
                         [&](unsigned Idx) -> const TreeEntry * {
                           return getOperandEntry(&E, Idx);
                         });
  };

  if (E.State == TreeEntry::SplitVectorize)
    return TryProcessInstruction(
        BitWidth,
        {VectorizableTree[E.CombinedEntriesWithIndices.front().first].get(),
         VectorizableTree[E.CombinedEntriesWithIndices.back().first].get()});

  if (E.isAltShuffle()) {
    // Combining these opcodes may lead to incorrect analysis, skip for now.
    auto IsDangerousOpcode = [](unsigned Opcode) {
      switch (Opcode) {
      case Instruction::Shl:
      case Instruction::AShr:
      case Instruction::LShr:
      case Instruction::UDiv:
      case Instruction::SDiv:
      case Instruction::URem:
      case Instruction::SRem:
        return true;
      default:
        break;
      }
      return false;
    };
    if (IsDangerousOpcode(E.getAltOpcode()))
      return FinalAnalysis();
  }

  switch (E.getOpcode()) {

  // We can always demote truncations and extensions. Since truncations can
  // seed additional demotion, we save the truncated value.
  case Instruction::Trunc:
    if (IsProfitableToDemoteRoot)
      IsProfitableToDemote = true;
    return TryProcessInstruction(BitWidth);
  case Instruction::ZExt:
  case Instruction::SExt:
    if (E.UserTreeIndex.UserTE && E.UserTreeIndex.UserTE->hasState() &&
        E.UserTreeIndex.UserTE->getOpcode() == Instruction::BitCast &&
        E.UserTreeIndex.UserTE->getMainOp()->getType()->isFPOrFPVectorTy())
      return false;
    IsProfitableToDemote = true;
    return TryProcessInstruction(BitWidth);

  // Demote binary ops when all operands can be demoted (may be >2 operands).
  case Instruction::Add:
  case Instruction::Sub:
  case Instruction::Mul:
  case Instruction::And:
  case Instruction::Or:
  case Instruction::Xor: {
    return TryProcessInstruction(BitWidth, GetOperandEntries());
  }
  case Instruction::Freeze:
    return TryProcessInstruction(BitWidth, getOperandEntry(&E, 0));
  case Instruction::Shl: {
    // If we are truncating the result of this SHL, and if it's a shift of an
    // inrange amount, we can always perform a SHL in a smaller type.
    auto ShlChecker = [&](unsigned BitWidth, unsigned) {
      // Check the node operands rather than the scalar instructions: lanes
      // converted from another opcode (e.g. mul by a power of 2) are emitted
      // with the converted shift amounts.
      return all_of(E.getOperand(1), [&](Value *V) {
        if (isa<PoisonValue>(V))
          return true;
        KnownBits AmtKnownBits = computeKnownBits(V, *DL);
        return AmtKnownBits.getMaxValue().ult(BitWidth);
      });
    };
    return TryProcessInstruction(BitWidth, GetOperandEntries(), ShlChecker);
  }
  case Instruction::LShr: {
    // If this is a truncate of a logical shr, we can truncate it to a smaller
    // lshr iff we know that the bits we would otherwise be shifting in are
    // already zeros.
    auto LShrChecker = [&](unsigned BitWidth, unsigned OrigBitWidth) {
      return all_of(E.Scalars, [&](Value *V) {
        if (isa<PoisonValue>(V))
          return true;
        APInt ShiftedBits = APInt::getBitsSetFrom(OrigBitWidth, BitWidth);
        if (E.isCopyableElement(V))
          return MaskedValueIsZero(V, ShiftedBits, SimplifyQuery(*DL));
        auto *I = cast<Instruction>(V);
        KnownBits AmtKnownBits = computeKnownBits(I->getOperand(1), *DL);
        return AmtKnownBits.getMaxValue().ult(BitWidth) &&
               MaskedValueIsZero(I->getOperand(0), ShiftedBits,
                                 SimplifyQuery(*DL));
      });
    };
    return TryProcessInstruction(BitWidth, GetOperandEntries(), LShrChecker);
  }
  case Instruction::AShr: {
    // If this is a truncate of an arithmetic shr, we can truncate it to a
    // smaller ashr iff we know that all the bits from the sign bit of the
    // original type and the sign bit of the truncate type are similar.
    auto AShrChecker = [&](unsigned BitWidth, unsigned OrigBitWidth) {
      return all_of(E.Scalars, [&](Value *V) {
        if (isa<PoisonValue>(V))
          return true;
        unsigned ShiftedBits = OrigBitWidth - BitWidth;
        if (E.isCopyableElement(V))
          return ShiftedBits < ComputeNumSignBits(V, *DL, AC, nullptr, DT);
        auto *I = cast<Instruction>(V);
        KnownBits AmtKnownBits = computeKnownBits(I->getOperand(1), *DL);
        return AmtKnownBits.getMaxValue().ult(BitWidth) &&
               ShiftedBits <
                   ComputeNumSignBits(I->getOperand(0), *DL, AC, nullptr, DT);
      });
    };
    return TryProcessInstruction(BitWidth, GetOperandEntries(), AShrChecker);
  }
  case Instruction::UDiv:
  case Instruction::URem: {
    // UDiv and URem can be truncated if all the truncated bits are zero.
    auto Checker = [&](unsigned BitWidth, unsigned OrigBitWidth) {
      assert(BitWidth <= OrigBitWidth && "Unexpected bitwidths!");
      return all_of(E.Scalars, [&](Value *V) {
        APInt Mask = APInt::getBitsSetFrom(OrigBitWidth, BitWidth);
        if (E.hasCopyableElements() && E.isCopyableElement(V))
          return MaskedValueIsZero(V, Mask, SimplifyQuery(*DL));
        auto *I = cast<Instruction>(V);
        return MaskedValueIsZero(I->getOperand(0), Mask, SimplifyQuery(*DL)) &&
               MaskedValueIsZero(I->getOperand(1), Mask, SimplifyQuery(*DL));
      });
    };
    return TryProcessInstruction(BitWidth, GetOperandEntries(), Checker);
  }

  // We can demote selects if we can demote their true and false values.
  case Instruction::Select: {
    return TryProcessInstruction(
        BitWidth, {getOperandEntry(&E, 1), getOperandEntry(&E, 2)});
  }

  // We can demote phis if we can demote all their incoming operands.
  case Instruction::PHI: {
    const unsigned NumOps = E.getNumOperands();
    SmallVector<const TreeEntry *> Ops(NumOps);
    transform(seq<unsigned>(0, NumOps), Ops.begin(),
              [&](unsigned Idx) { return getOperandEntry(&E, Idx); });

    return TryProcessInstruction(BitWidth, Ops);
  }

  case Instruction::Call: {
    auto *IC = dyn_cast<IntrinsicInst>(E.getMainOp());
    if (!IC)
      break;
    Intrinsic::ID ID = getVectorIntrinsicIDForCall(IC, TLI);
    if (ID != Intrinsic::abs && ID != Intrinsic::smin &&
        ID != Intrinsic::smax && ID != Intrinsic::umin && ID != Intrinsic::umax)
      break;
    SmallVector<const TreeEntry *, 2> Operands(1, getOperandEntry(&E, 0));
    function_ref<bool(unsigned, unsigned)> CallChecker;
    auto CompChecker = [&](unsigned BitWidth, unsigned OrigBitWidth) {
      assert(BitWidth <= OrigBitWidth && "Unexpected bitwidths!");
      return all_of(E.Scalars, [&](Value *V) {
        if (ID == Intrinsic::umin || ID == Intrinsic::umax) {
          APInt Mask = APInt::getBitsSetFrom(OrigBitWidth, BitWidth);
          // A copyable V stands for umax/umin(V, identity), which equals V.
          if (E.isCopyableElement(V))
            return MaskedValueIsZero(V, Mask, SimplifyQuery(*DL));
          auto *I = cast<Instruction>(V);
          return MaskedValueIsZero(I->getOperand(0), Mask,
                                   SimplifyQuery(*DL)) &&
                 MaskedValueIsZero(I->getOperand(1), Mask, SimplifyQuery(*DL));
        }
        assert((ID == Intrinsic::smin || ID == Intrinsic::smax) &&
               "Expected min/max intrinsics only.");
        unsigned SignBits = OrigBitWidth - BitWidth;
        APInt Mask = APInt::getBitsSetFrom(OrigBitWidth, BitWidth - 1);
        auto CheckOp = [&](Value *Op) {
          unsigned OpSignBits = ComputeNumSignBits(Op, *DL, AC, nullptr, DT);
          return SignBits <= OpSignBits &&
                 ((SignBits != OpSignBits &&
                   !isKnownNonNegative(Op, SimplifyQuery(*DL))) ||
                  MaskedValueIsZero(Op, Mask, SimplifyQuery(*DL)));
        };
        // A copyable V stands for smax/smin(V, identity), which equals V.
        if (E.isCopyableElement(V))
          return CheckOp(V) &&
                 (isTypeLimitNeutral(V, ID == Intrinsic::smax, *DL) ||
                  ComputeMaxSignificantBits(V, *DL, nullptr, nullptr, DT) <=
                      BitWidth);
        auto *I = cast<Instruction>(V);
        return CheckOp(I->getOperand(0)) && CheckOp(I->getOperand(1));
      });
    };
    auto AbsChecker = [&](unsigned BitWidth, unsigned OrigBitWidth) {
      assert(BitWidth <= OrigBitWidth && "Unexpected bitwidths!");
      return all_of(E.Scalars, [&](Value *V) {
        auto *I = cast<Instruction>(V);
        unsigned SignBits = OrigBitWidth - BitWidth;
        APInt Mask = APInt::getBitsSetFrom(OrigBitWidth, BitWidth - 1);
        unsigned Op0SignBits =
            ComputeNumSignBits(I->getOperand(0), *DL, AC, nullptr, DT);
        return SignBits <= Op0SignBits &&
               ((SignBits != Op0SignBits &&
                 !isKnownNonNegative(I->getOperand(0), SimplifyQuery(*DL))) ||
                MaskedValueIsZero(I->getOperand(0), Mask, SimplifyQuery(*DL)));
      });
    };
    if (ID != Intrinsic::abs) {
      Operands.push_back(getOperandEntry(&E, 1));
      CallChecker = CompChecker;
    } else {
      CallChecker = AbsChecker;
    }
    InstructionCost BestCost =
        std::numeric_limits<InstructionCost::CostType>::max();
    unsigned BestBitWidth = BitWidth;
    unsigned VF = E.Scalars.size();
    // Choose the best bitwidth based on cost estimations.
    auto Checker = [&](unsigned BitWidth, unsigned) {
      unsigned MinBW = PowerOf2Ceil(BitWidth);
      SmallVector<Type *> ArgTys =
          buildIntrinsicArgTypes(IC, ID, VF, MinBW, TTI);
      auto VecCallCosts = getVectorCallCosts(
          IC, getWidenedType(IntegerType::get(IC->getContext(), MinBW), VF),
          TTI, TLI, ArgTys, CostKind);
      InstructionCost Cost = std::min(VecCallCosts.first, VecCallCosts.second);
      if (Cost < BestCost) {
        BestCost = Cost;
        BestBitWidth = BitWidth;
      }
      return false;
    };
    [[maybe_unused]] bool NeedToExit;
    (void)AttemptCheckBitwidth(Checker, NeedToExit);
    BitWidth = BestBitWidth;
    return TryProcessInstruction(BitWidth, Operands, CallChecker);
  }

  // Otherwise, conservatively give up.
  default:
    break;
  }
  MaxDepthLevel = 1;
  return FinalAnalysis();
}

static RecurKind getRdxKind(Value *V);

void BoUpSLP::computeMinimumValueSizes() {
  // Detect booleanized i1 and/or nodes first: they are registered in MinBWs
  // like the demoted nodes and processed the same way.
  detectBooleanizedNodes();

  // We only attempt to truncate integer expressions.
  bool IsStoreOrInsertElt =
      getRootNode().hasState() &&
      (getRootNode().getOpcode() == Instruction::Store ||
       getRootNode().getOpcode() == Instruction::InsertElement ||
       getRootNode().getOpcode() == Instruction::InsertValue);
  if ((IsStoreOrInsertElt || UserIgnoreList) &&
      ExtraBitWidthNodes.size() <= 1 &&
      (!CastMaxMinBWSizes || CastMaxMinBWSizes->second == 0 ||
       CastMaxMinBWSizes->first / CastMaxMinBWSizes->second <= 2))
    return;

  unsigned NodeIdx = 0;
  if (IsStoreOrInsertElt && !getRootNode().isGather())
    NodeIdx = 1;

  // Ensure the roots of the vectorizable tree don't form a cycle.
  assert((VectorizableTree[NodeIdx]->isGather() || NodeIdx != 0 ||
          !VectorizableTree[NodeIdx]->UserTreeIndex) &&
         "Unexpected tree is graph.");

  // The first value node for store/insertelement is sext/zext/trunc? Skip it,
  // resize to the final type.
  bool IsTruncRoot = false;
  bool IsProfitableToDemoteRoot = !IsStoreOrInsertElt;
  SmallVector<unsigned> RootDemotes;
  SmallDenseSet<unsigned, 8> NodesToKeepBWs;
  if (NodeIdx != 0 &&
      VectorizableTree[NodeIdx]->State == TreeEntry::Vectorize &&
      VectorizableTree[NodeIdx]->getOpcode() == Instruction::Trunc) {
    assert(IsStoreOrInsertElt && "Expected store/insertelement seeded graph.");
    IsTruncRoot = true;
    RootDemotes.push_back(NodeIdx);
    IsProfitableToDemoteRoot = true;
    ++NodeIdx;
  }

  auto IsAnalyzedMinBWVal = [&](Value *V, unsigned SizeExGathers) {
    auto It = AnalyzedMinBWVals.find(V);
    return It != AnalyzedMinBWVals.end() && It->second >= SizeExGathers;
  };

  // Analyzed the reduction already and not profitable - exit.
  if (IsAnalyzedMinBWVal(VectorizableTree[NodeIdx]->Scalars.front(),
                         getTreeSizeExcludingGathers()))
    return;

  SmallVector<unsigned> ToDemote;
  auto ComputeMaxBitWidth =
      [&](const TreeEntry &E, bool IsTopRoot, bool IsProfitableToDemoteRoot,
          unsigned Limit, bool IsTruncRoot, bool IsSignedCmp) -> unsigned {
    ToDemote.clear();
    // Check if the root is trunc and the next node is gather/buildvector, then
    // keep trunc in scalars, which is free in most cases.
    if (E.isGather() && IsTruncRoot && E.UserTreeIndex &&
        !NodesToKeepBWs.contains(E.Idx) &&
        E.Idx > (IsStoreOrInsertElt ? 2u : 1u) &&
        all_of(E.Scalars, [&](Value *V) {
          return V->hasOneUse() || isa<Constant>(V) ||
                 (!V->hasNUsesOrMore(UsesLimit) &&
                  none_of(V->users(), [&](User *U) {
                    ArrayRef<TreeEntry *> TEs = getTreeEntries(U);
                    const TreeEntry *UserTE = E.UserTreeIndex.UserTE;
                    if (TEs.empty() || is_contained(TEs, UserTE))
                      return false;
                    if (!isa<CastInst, BinaryOperator, FreezeInst, PHINode,
                             SelectInst>(U) ||
                        isa<SIToFPInst, UIToFPInst>(U) ||
                        (UserTE->hasState() &&
                         (!isa<CastInst, BinaryOperator, FreezeInst, PHINode,
                               SelectInst>(UserTE->getMainOp()) ||
                          isa<SIToFPInst, UIToFPInst>(UserTE->getMainOp()))))
                      return true;
                    unsigned UserTESz = DL->getTypeSizeInBits(
                        UserTE->Scalars.front()->getType());
                    if (all_of(TEs, [&](const TreeEntry *TE) {
                          auto It = MinBWs.find(TE);
                          return It != MinBWs.end() &&
                                 It->second.first > UserTESz;
                        }))
                      return true;
                    return DL->getTypeSizeInBits(U->getType()) > UserTESz;
                  }));
        })) {
      ToDemote.push_back(E.Idx);
      const TreeEntry *UserTE = E.UserTreeIndex.UserTE;
      auto It = MinBWs.find(UserTE);
      if (It != MinBWs.end())
        return It->second.first;
      unsigned MaxBitWidth =
          DL->getTypeSizeInBits(UserTE->Scalars.front()->getType());
      MaxBitWidth = bit_ceil(MaxBitWidth);
      if (MaxBitWidth < 8 && MaxBitWidth > 1)
        MaxBitWidth = 8;
      return MaxBitWidth;
    }

    if (!E.hasState())
      return 0u;

    unsigned VF = E.getVectorFactor();
    Type *ScalarTy = E.Scalars.front()->getType();
    auto *TreeRootIT = dyn_cast<IntegerType>(ScalarTy->getScalarType());
    if (!TreeRootIT)
      return 0u;

    unsigned SizeExGathers = getTreeSizeExcludingGathers();
    if (any_of(E.Scalars,
               [&](Value *V) { return IsAnalyzedMinBWVal(V, SizeExGathers); }))
      return 0u;

    unsigned NumParts =
        getNumberOfParts(getWidenedType(ScalarTy, VF), ScalarTy);

    // The maximum bit width required to represent all the values that can be
    // demoted without loss of precision. It would be safe to truncate the roots
    // of the expression to this width.
    unsigned MaxBitWidth = 1u;

    // True if the roots can be zero-extended back to their original type,
    // rather than sign-extended. We know that if the leading bits are not
    // demanded, we can safely zero-extend. So we initialize IsKnownPositive to
    // True.
    // Determine if the sign bit of all the roots is known to be zero. If not,
    // IsKnownPositive is set to False.
    bool IsKnownPositive = !IsSignedCmp && all_of(E.Scalars, [&](Value *R) {
      if (isa<PoisonValue>(R))
        return true;
      KnownBits Known = computeKnownBits(R, *DL);
      return Known.isNonNegative();
    });

    if (!IsKnownPositive && !IsTopRoot && E.UserTreeIndex &&
        E.UserTreeIndex.UserTE->hasState() &&
        E.UserTreeIndex.UserTE->getOpcode() == Instruction::UIToFP)
      MaxBitWidth =
          std::min(DL->getTypeSizeInBits(
                       E.UserTreeIndex.UserTE->Scalars.front()->getType()),
                   DL->getTypeSizeInBits(ScalarTy));

    // We first check if all the bits of the roots are demanded. If they're not,
    // we can truncate the roots to this narrower type.
    auto IsNotPoison = [](Value *Root) { return !isa<PoisonValue>(Root); };
    for (Value *Root : make_filter_range(E.Scalars, IsNotPoison)) {
      unsigned NumSignBits = ComputeNumSignBits(Root, *DL, AC, nullptr, DT);
      TypeSize NumTypeBits =
          DL->getTypeSizeInBits(Root->getType()->getScalarType());
      unsigned BitWidth1 = NumTypeBits - NumSignBits;
      // If we can't prove that the sign bit is zero, we must add one to the
      // maximum bit width to account for the unknown sign bit. This preserves
      // the existing sign bit so we can safely sign-extend the root back to the
      // original type. Otherwise, if we know the sign bit is zero, we will
      // zero-extend the root instead.
      //
      // FIXME: This is somewhat suboptimal, as there will be cases where adding
      //        one to the maximum bit width will yield a larger-than-necessary
      //        type. In general, we need to add an extra bit only if we can't
      //        prove that the upper bit of the original type is equal to the
      //        upper bit of the proposed smaller type. If these two bits are
      //        the same (either zero or one) we know that sign-extending from
      //        the smaller type will result in the same value. Here, since we
      //        can't yet prove this, we are just making the proposed smaller
      //        type larger to ensure correctness.
      if (!IsKnownPositive)
        ++BitWidth1;

      auto *I = dyn_cast<Instruction>(Root);
      if (!I) {
        MaxBitWidth = std::max(BitWidth1, MaxBitWidth);
        continue;
      }
      APInt Mask = DB->getDemandedBits(I);
      unsigned BitWidth2 = Mask.getBitWidth() - Mask.countl_zero();
      MaxBitWidth =
          std::max<unsigned>(std::min(BitWidth1, BitWidth2), MaxBitWidth);
    }

    if (MaxBitWidth < 8 && MaxBitWidth > 1)
      MaxBitWidth = 8;

    // If the original type is large, but reduced type does not improve the reg
    // use - ignore it.
    if (NumParts > 1 &&
        NumParts ==
            getNumberOfParts(
                getWidenedType(
                    IntegerType::get(F->getContext(), bit_ceil(MaxBitWidth)),
                    VF),
                IntegerType::get(F->getContext(), bit_ceil(MaxBitWidth))))
      return 0u;

    unsigned Opcode = E.getOpcode();
    bool IsProfitableToDemote = Opcode == Instruction::Trunc ||
                                Opcode == Instruction::SExt ||
                                Opcode == Instruction::ZExt || NumParts > 1;
    // Conservatively determine if we can actually truncate the roots of the
    // expression. Collect the values that can be demoted in ToDemote and
    // additional roots that require investigating in Roots.
    DenseSet<const TreeEntry *> Visited;
    unsigned MaxDepthLevel = IsTruncRoot ? Limit : 1;
    bool NeedToDemote = IsProfitableToDemote;

    if (!collectValuesToDemote(E, IsProfitableToDemoteRoot, MaxBitWidth,
                               ToDemote, Visited, NodesToKeepBWs, MaxDepthLevel,
                               NeedToDemote, IsTruncRoot) ||
        (MaxDepthLevel <= Limit &&
         !(((Opcode == Instruction::SExt || Opcode == Instruction::ZExt) &&
            (!IsTopRoot || !(IsStoreOrInsertElt || UserIgnoreList) ||
             DL->getTypeSizeInBits(TreeRootIT) /
                     DL->getTypeSizeInBits(
                         E.getMainOp()->getOperand(0)->getType()) >
                 2)))))
      return 0u;
    // Round MaxBitWidth up to the next power-of-two.
    MaxBitWidth = bit_ceil(MaxBitWidth);

    return MaxBitWidth;
  };

  // If we can truncate the root, we must collect additional values that might
  // be demoted as a result. That is, those seeded by truncations we will
  // modify.
  // Add reduction ops sizes, if any.
  if (UserIgnoreList &&
      isa<IntegerType>(getRootNodeScalars().front()->getType())) {
    // Convert vector_reduce_add(ZExt(<n x i1>)) to ZExtOrTrunc(ctpop(bitcast <n
    // x i1> to in)).
    if (all_of(make_isa_range<Instruction>(*UserIgnoreList),
               [](Instruction *I) {
                 return I->getOpcode() == Instruction::Add;
               }) &&
        getRootNode().State == TreeEntry::Vectorize &&
        getRootNode().getOpcode() == Instruction::ZExt &&
        cast<CastInst>(getRootNode().getMainOp())->getSrcTy() ==
            Builder.getInt1Ty()) {
      ReductionBitWidth = 1;
    } else {
      for (Value *V : make_filter_range(*UserIgnoreList, [](Value *V) {
             return !isa<PoisonValue>(V);
           })) {
        unsigned NumSignBits = ComputeNumSignBits(V, *DL, AC, nullptr, DT);
        TypeSize NumTypeBits = DL->getTypeSizeInBits(V->getType());
        unsigned BitWidth1 = NumTypeBits - NumSignBits;
        if (!isKnownNonNegative(V, SimplifyQuery(*DL)))
          ++BitWidth1;
        unsigned BitWidth2 = BitWidth1;
        if (!RecurrenceDescriptor::isIntMinMaxRecurrenceKind(::getRdxKind(V))) {
          APInt Mask = DB->getDemandedBits(cast<Instruction>(V));
          BitWidth2 = Mask.getBitWidth() - Mask.countl_zero();
        }
        ReductionBitWidth =
            std::max(std::min(BitWidth1, BitWidth2), ReductionBitWidth);
      }
      if (ReductionBitWidth < 8 && ReductionBitWidth > 1)
        ReductionBitWidth = 8;

      ReductionBitWidth = bit_ceil(ReductionBitWidth);
    }
  }
  bool IsTopRoot = NodeIdx == 0;
  while (NodeIdx < VectorizableTree.size() &&
         VectorizableTree[NodeIdx]->State == TreeEntry::Vectorize &&
         VectorizableTree[NodeIdx]->getOpcode() == Instruction::Trunc) {
    RootDemotes.push_back(NodeIdx);
    ++NodeIdx;
    IsTruncRoot = true;
  }
  bool IsSignedCmp = false;
  if (UserIgnoreList &&
      all_of(*UserIgnoreList,
             match_fn(m_CombineOr(m_SMin(m_Value(), m_Value()),
                                  m_SMax(m_Value(), m_Value())))))
    IsSignedCmp = true;
  while (NodeIdx < VectorizableTree.size()) {
    ArrayRef<Value *> TreeRoot = VectorizableTree[NodeIdx]->Scalars;
    unsigned Limit = 2;
    if (IsTopRoot &&
        ReductionBitWidth ==
            DL->getTypeSizeInBits(getRootNodeScalars().front()->getType()))
      Limit = 3;
    unsigned MaxBitWidth = ComputeMaxBitWidth(
        *VectorizableTree[NodeIdx], IsTopRoot, IsProfitableToDemoteRoot, Limit,
        IsTruncRoot, IsSignedCmp);
    // The extension of a demoted scalar, which does not fit into the demoted
    // type, restores only its demanded bits. Keep the original bitwidth if the
    // scalar users may depend on the other bits via poison-generating
    // annotations or there are too many users to check.
    auto HasUnsafeScalarUsers = [&](Value *V) {
      auto *I = dyn_cast<Instruction>(V);
      if (!I)
        return false;
      unsigned NumBits =
          isKnownNonNegative(I, SimplifyQuery(*DL))
              ? computeKnownBits(I, *DL, AC, nullptr, DT).countMaxActiveBits()
              : ComputeMaxSignificantBits(I, *DL, AC, nullptr, DT);
      if (NumBits <= MaxBitWidth)
        return false;
      SmallVector<Instruction *> Worklist(1, I);
      SmallPtrSet<Instruction *, 8> Visited;
      int NumUsers = 0;
      while (!Worklist.empty()) {
        for (User *U : Worklist.pop_back_val()->users()) {
          if (++NumUsers > UsesLimit)
            return true;
          auto *UI = cast<Instruction>(U);
          if (isVectorized(UI) ||
              (UserIgnoreList && UserIgnoreList->contains(UI)) ||
              !UI->getType()->isIntOrIntVectorTy() ||
              !Visited.insert(UI).second)
            continue;
          if (UI->hasPoisonGeneratingAnnotations())
            return true;
          if (!DB->getDemandedBits(UI).isAllOnes())
            Worklist.push_back(UI);
        }
      }
      return false;
    };
    if (MaxBitWidth != 0 && any_of(ToDemote, [&](unsigned Idx) {
          const TreeEntry &TE = *VectorizableTree[Idx];
          return !TE.isGather() && !MinBWs.contains(&TE) &&
                 any_of(TE.Scalars, HasUnsafeScalarUsers);
        }))
      MaxBitWidth = 0;
    if (ReductionBitWidth != 0 && (IsTopRoot || !RootDemotes.empty())) {
      if (MaxBitWidth != 0 && ReductionBitWidth < MaxBitWidth)
        ReductionBitWidth = bit_ceil(MaxBitWidth);
      else if (MaxBitWidth == 0)
        ReductionBitWidth = 0;
    }

    for (unsigned Idx : RootDemotes) {
      if (all_of(VectorizableTree[Idx]->Scalars, [&](Value *V) {
            uint32_t OrigBitWidth =
                DL->getTypeSizeInBits(V->getType()->getScalarType());
            if (OrigBitWidth > MaxBitWidth) {
              APInt Mask = APInt::getBitsSetFrom(OrigBitWidth, MaxBitWidth);
              return MaskedValueIsZero(V, Mask, SimplifyQuery(*DL));
            }
            return false;
          }))
        ToDemote.push_back(Idx);
    }
    RootDemotes.clear();
    IsTopRoot = false;
    IsProfitableToDemoteRoot = true;

    if (ExtraBitWidthNodes.empty()) {
      NodeIdx = VectorizableTree.size();
    } else {
      unsigned NewIdx = 0;
      do {
        NewIdx = *ExtraBitWidthNodes.begin();
        ExtraBitWidthNodes.erase(ExtraBitWidthNodes.begin());
      } while (NewIdx <= NodeIdx && !ExtraBitWidthNodes.empty());
      NodeIdx = NewIdx;
      IsTruncRoot =
          NodeIdx < VectorizableTree.size() &&
          VectorizableTree[NodeIdx]->UserTreeIndex &&
          VectorizableTree[NodeIdx]->UserTreeIndex.EdgeIdx == 0 &&
          VectorizableTree[NodeIdx]->UserTreeIndex.UserTE->hasState() &&
          VectorizableTree[NodeIdx]->UserTreeIndex.UserTE->getOpcode() ==
              Instruction::Trunc &&
          !VectorizableTree[NodeIdx]->UserTreeIndex.UserTE->isAltShuffle();
      IsSignedCmp =
          NodeIdx < VectorizableTree.size() &&
          VectorizableTree[NodeIdx]->UserTreeIndex &&
          VectorizableTree[NodeIdx]->UserTreeIndex.UserTE->hasState() &&
          VectorizableTree[NodeIdx]->UserTreeIndex.UserTE->getOpcode() ==
              Instruction::ICmp &&
          any_of(
              make_isa_range<ICmpInst>(
                  VectorizableTree[NodeIdx]->UserTreeIndex.UserTE->Scalars),
              [&](ICmpInst *IC) {
                return IC->isSigned() ||
                       !isKnownNonNegative(IC->getOperand(0),
                                           SimplifyQuery(*DL)) ||
                       !isKnownNonNegative(IC->getOperand(1),
                                           SimplifyQuery(*DL));
              });
    }

    // If the maximum bit width we compute is less than the width of the roots'
    // type, we can proceed with the narrowing. Otherwise, do nothing.
    if (MaxBitWidth == 0 ||
        MaxBitWidth >=
            cast<IntegerType>(TreeRoot.front()->getType()->getScalarType())
                ->getBitWidth()) {
      if (UserIgnoreList) {
        unsigned Sz = getTreeSizeExcludingGathers();
        for (Value *V : TreeRoot)
          AnalyzedMinBWVals.insert_or_assign(V, Sz);
      }
      NodesToKeepBWs.insert_range(ToDemote);
      continue;
    }

    // Finally, map the values we can demote to the maximum bit with we
    // computed.
    for (unsigned Idx : ToDemote) {
      TreeEntry *TE = VectorizableTree[Idx].get();
      if (MinBWs.contains(TE))
        continue;
      bool IsSigned = any_of(TE->Scalars, [&](Value *R) {
        if (isa<PoisonValue>(R))
          return false;
        return !isKnownNonNegative(R, SimplifyQuery(*DL));
      });
      MinBWs.try_emplace(TE, MaxBitWidth, IsSigned);
    }
  }
}

PreservedAnalyses SLPVectorizerPass::run(Function &F, FunctionAnalysisManager &AM) {
  auto *SE = &AM.getResult<ScalarEvolutionAnalysis>(F);
  auto *TTI = &AM.getResult<TargetIRAnalysis>(F);
  auto *TLI = AM.getCachedResult<TargetLibraryAnalysis>(F);
  auto *AA = &AM.getResult<AAManager>(F);
  auto *LI = &AM.getResult<LoopAnalysis>(F);
  auto *DT = &AM.getResult<DominatorTreeAnalysis>(F);
  auto *AC = &AM.getResult<AssumptionAnalysis>(F);
  auto *DB = &AM.getResult<DemandedBitsAnalysis>(F);
  auto *ORE = &AM.getResult<OptimizationRemarkEmitterAnalysis>(F);

  bool Changed = runImpl(F, SE, TTI, TLI, AA, LI, DT, AC, DB, ORE);
  if (!Changed)
    return PreservedAnalyses::all();

  PreservedAnalyses PA;
  // Runtime alias check versioning changes the CFG. In that case only the
  // dominator tree is kept up to date (via DomTreeUpdater); other CFG analyses
  // must be recomputed. Otherwise SLP leaves the CFG intact.
  if (CFGChanged)
    PA.preserve<DominatorTreeAnalysis>();
  else
    PA.preserveSet<CFGAnalyses>();
  return PA;
}

bool SLPVectorizerPass::runImpl(Function &F, ScalarEvolution *SE_,
                                TargetTransformInfo *TTI_,
                                TargetLibraryInfo *TLI_, AAResults *AA_,
                                LoopInfo *LI_, DominatorTree *DT_,
                                AssumptionCache *AC_, DemandedBits *DB_,
                                OptimizationRemarkEmitter *ORE_) {
  Opts = &getVectorizeOptions(F);
  if (!Opts->vectorize_slp)
    return false;
  SE = SE_;
  TTI = TTI_;
  TLI = TLI_;
  AA = AA_;
  LI = LI_;
  DT = DT_;
  AC = AC_;
  DB = DB_;
  DL = &F.getDataLayout();

  Stores.clear();
  GEPs.clear();
  bool Changed = false;

  // If the target claims to have no vector registers don't attempt
  // vectorization.
  if (!TTI->getNumberOfRegisters(TTI->getRegisterClassForType(true))) {
    LLVM_DEBUG(
        dbgs() << "SLP: Didn't find any vector registers for target, abort.\n");
    return false;
  }

  // Don't vectorize when the attribute NoImplicitFloat is used.
  if (F.hasFnAttribute(Attribute::NoImplicitFloat))
    return false;

  LLVM_DEBUG(dbgs() << "SLP: Analyzing blocks in " << F.getName() << ".\n");

  // Use the bottom up slp vectorizer to construct chains that start with
  // store instructions.
  BoUpSLP R(*Opts, &F, SE, TTI, TLI, AA, LI, DT, AC, DB, DL, ORE_);

  // A general note: the vectorizer must use BoUpSLP::eraseInstruction() to
  // delete instructions.

  // Update DFS numbers now so that we can use them for ordering.
  DT->updateDFSNumbers();

  SmallSetVector<Instruction *, 8> FMACandidates;
  // Scan the blocks in the function in post order.
  auto POT = post_order(&F.getEntryBlock());
  for (auto *BB : make_filter_range(POT, [](auto *BB) {
         return !BB->isEHPad() && !isa<UnreachableInst>(BB->getTerminator());
       })) {
    // Skip scalar fallback blocks created by runtime alias check versioning:
    // they duplicate the original scalar code and must not be vectorized again.
    if (R.isScalarFallbackBlock(BB))
      continue;

    // Start new block - clear the list of reduction roots.
    R.clearReductionData();
    collectSeedInstructions(BB);

    Changed |= vectorizeSplitStorePoorThroughputSeeds(BB, R);

    // Vectorize trees that end at stores.
    if (!Stores.empty()) {
      LLVM_DEBUG(dbgs() << "SLP: Found stores for " << Stores.size()
                        << " underlying objects.\n");
      Changed |= vectorizeStoreChains(R);
    }

    // Vectorize trees that end at reductions.
    Changed |= vectorizeChainsInBlock(BB, R, FMACandidates);

    // Vectorize the index computations of getelementptr instructions. This
    // is primarily intended to catch gather-like idioms ending at
    // non-consecutive loads.
    if (!GEPs.empty()) {
      LLVM_DEBUG(dbgs() << "SLP: Found GEPs for " << GEPs.size()
                        << " underlying objects.\n");
      Changed |= vectorizeGEPIndices(BB, R);
    }
  }

  // Vectorized on their own, the FMA candidates lose the fusion with their fmul
  // operands. They are retried after all the blocks, not to preempt the trees
  // of the blocks processed later, e.g. the store chains of a loop body,
  // processed after the latch PHIs reaching the same instructions.
  R.clearReductionData();
  SmallSetVector<Instruction *, 8> Empty;
  for (Instruction *I : make_filter_range(
           FMACandidates, [&](Instruction *I) { return !R.isDeleted(I); }))
    Changed |= tryToVectorize(I, R, Empty, /*AllowFMACandidates=*/true);
  assert(Empty.empty() &&
         "No new FMA candidates expected during AllowFMACandidates retry.");

  // Instructions with the single user require just one extract per lane, so
  // they are used as the seeds for the very last attempt, after all the other
  // roots in the function are exhausted.
  if (Opts->slp_vectorize_once_used) {
    auto OnceUsedPOT = post_order(&F.getEntryBlock());
    for (auto *BB : make_filter_range(OnceUsedPOT, [&](auto *BB) {
           return !BB->isEHPad() &&
                  !isa<UnreachableInst>(BB->getTerminator()) &&
                  !R.isScalarFallbackBlock(BB);
         })) {
      R.clearReductionData();
      Changed |= vectorizeOnceUsedSeeds(BB, R);
    }
  }

  if (Changed) {
    R.optimizeGatherSequence();
    LLVM_DEBUG(dbgs() << "SLP: vectorized \"" << F.getName() << "\"\n");
  }
  // Propagate whether runtime alias check versioning changed the CFG, so the
  // caller can drop CFG-analysis preservation only when necessary.
  CFGChanged = R.isCFGChanged();
  return Changed;
}

std::optional<bool>
SLPVectorizerPass::vectorizeStoreChain(ArrayRef<Value *> Chain, BoUpSLP &R,
                                       unsigned Idx, unsigned MinVF,
                                       unsigned &Size) {
  std::optional<bool> Res = vectorizeStoreChainImpl(Chain, R, Idx, MinVF, Size);
  // Retry the non-profitable tree, wider than the vector register, with the
  // alternate stored values (looking through the cast) split into halves. The
  // halves share the common operands instead of extracting them for the scalar
  // stores of the other half.
  if (Res && !*Res && Chain.size() > SmallNodeSize && Chain.size() % 2 == 0 &&
      Chain.size() * R.getVectorElementSize(Chain.front()) >
          R.getMaxVecRegSize() &&
      R.canSplitStoredValues(Chain)) {
    SaveAndRestore<bool> SplitGuard = R.splitStoredValues();
    unsigned SplitSize;
    std::optional<bool> SplitRes =
        vectorizeStoreChainImpl(Chain, R, Idx, MinVF, SplitSize);
    if (SplitRes.value_or(false)) {
      Size = SplitSize;
      return SplitRes;
    }
  }
  assert(!R.isTryingRuntimeAliasChecks() &&
         "Unexpected nested runtime alias check attempt");
  // Retry once with runtime alias checks, but only when the normal attempt
  // could not even schedule the bundle, i.e. it was blocked by
  // a memory dependency, and that dependency is runtime-checkable. If the
  // region also kept a non-checkable blocker, dropping the checkable deps
  // cannot unblock it.
  if (Res.has_value() || !Opts->slp_vectorize_with_runtime_alias_checks ||
      !R.hasRuntimeCheckableBlockers() || R.hasNonCheckableMemBlocker())
    return Res;
  // getTreeCost() unconditionally rejects a VF=2 tree whose vector
  // instruction count exceeds its scalar instruction count (the
  // SLPInstCountCheck heuristic), because the cost model is known to
  // underestimate shuffle/insert/extract overhead at that width. That check
  // returns an invalid cost that no threshold, including the runtime-checks
  // one, can outweigh. Retrying such a chain would pay the full tree rebuild
  // cost for the one width the cost model is least trusted for, on top of
  // the extra guard overhead, so skip it instead of wasting the attempt.
  if (Chain.size() == 2)
    return Res;
  // Only retry when scheduling blocked the chain (a store or its value bundle
  // could not be scheduled), which dropping may-alias deps can fix. A chain
  // gathered for structural reasons (e.g. non-consecutive addresses) would
  // gather again, so the second buildTree() would be pure overhead with no
  // vectorization benefit.
  Value *FirstStore = Chain.front();
  if (!R.isNotScheduled(FirstStore) &&
      !R.isNotScheduled(cast<StoreInst>(FirstStore)->getValueOperand()))
    return Res;
  BasicBlock *BB = cast<Instruction>(FirstStore)->getParent();
  // If an earlier optimistic attempt already failed for this block, do not
  // retry for other chains or smaller VFs in the same block.
  if (R.runtimeChecksFailedForBlock(BB))
    return Res;
  // The retry rebuilds the whole tree; also skip it when the chain's block can
  // never be versioned (e.g. the function is optimized for size).
  if (!R.canVersionBlockForRuntimeChecks(BB)) {
    R.markRuntimeChecksFailedForBlock(BB);
    return Res;
  }
  R.setTryRuntimeAliasChecks(true);
  unsigned RTSize = Size;
  std::optional<bool> RTRes =
      vectorizeStoreChainImpl(Chain, R, Idx, MinVF, RTSize);
  R.setTryRuntimeAliasChecks(false);
  if (RTRes && *RTRes) {
    Size = RTSize;
    return RTRes;
  }
  // The versioning attempt failed for this block, skip the (expensive) retry.
  R.markRuntimeChecksFailedForBlock(BB);
  return Res;
}

std::optional<bool>
SLPVectorizerPass::vectorizeStoreChainImpl(ArrayRef<Value *> Chain, BoUpSLP &R,
                                           unsigned Idx, unsigned MinVF,
                                           unsigned &Size) {
  Size = 0;
  R.resetRuntimeAliasCheckState();
  LLVM_DEBUG(dbgs() << "SLP: Analyzing a store chain of length " << Chain.size()
                    << "\n");
  const unsigned Sz = R.getVectorElementSize(Chain[0]);
  unsigned VF = Chain.size();

  if (!has_single_bit(Sz) ||
      !hasFullVectorsOrPowerOf2(
          *TTI, cast<StoreInst>(Chain.front())->getValueOperand()->getType(),
          VF, Opts->slp_revec) ||
      VF < 2 || VF < MinVF) {
    // Check if vectorizing with a non-power-of-2 VF should be considered; see
    // isAllowedNonPowerOf2VF for supported widths.
    if (!Opts->slp_vectorize_non_power_of_2 || (VF < MinVF && VF + 1 != MinVF))
      return false;
  }

  LLVM_DEBUG(dbgs() << "SLP: Analyzing " << VF << " stores at offset " << Idx
                    << "\n");

  SetVector<Value *> ValOps;
  for (Value *V : Chain)
    ValOps.insert(cast<StoreInst>(V)->getValueOperand());
  // Operands are not same/alt opcodes or non-power-of-2 uniques - exit.
  InstructionsCompatibilityAnalysis Analysis(*DT, *DL, *TTI, *TLI);
  InstructionsState S =
      Analysis.buildInstructionsState(ValOps.getArrayRef(), R);
  if (all_of(ValOps, IsaPred<Instruction>) && ValOps.size() > 1) {
    DenseSet<Value *> Stores(Chain.begin(), Chain.end());
    bool IsAllowedSize =
        hasFullVectorsOrPowerOf2(*TTI, ValOps.front()->getType(), ValOps.size(),
                                 Opts->slp_revec) ||
        isAllowedNonPowerOf2VF(ValOps.size(),
                               Opts->slp_vectorize_non_power_of_2);
    if ((!IsAllowedSize && S && S.getOpcode() != Instruction::Load &&
         (!S.getMainOp()->isSafeToRemove() ||
          any_of(ValOps.getArrayRef(),
                 [&](Value *V) {
                   return !isa<ExtractElementInst>(V) &&
                          (V->getNumUses() > Chain.size() ||
                           any_of(V->users(), [&](User *U) {
                             return !Stores.contains(U);
                           }));
                 }))) ||
        (ValOps.size() > Chain.size() / 2 && !S)) {
      Size = (!IsAllowedSize && S) ? 1 : 2;
      return false;
    }
    // Every value is reused several times outside of the chain: such a chain
    // only merges the stores, while the scalars remain live for the other users
    // and all the lanes are gathered back. A single outside use may still be a
    // part of the larger vectorizable graph, same for the values, fed by the
    // loads, where the vector loads may pay off the gathering. Two outside
    // uses may still be part of the same profitable tree when they look like
    // carry deps (cmp, select, non-div/rem binop, or a two-incoming phi);
    // reject 3+ outside users, or exactly 2 when at least one is not benign.
    auto IsBenignOutsideUser = [](Instruction *UI) {
      assert(UI && "Expected instruction.");
      if (auto *PN = dyn_cast<PHINode>(UI))
        return PN->getNumIncomingValues() == 2;
      if (auto *BO = dyn_cast<BinaryOperator>(UI))
        return !BO->isIntDivRem() && !BO->isFPDivRem();
      return isa<CmpInst, SelectInst>(UI);
    };
    auto HasTooManyOutsideUsers = [&](Instruction *I) {
      // To save compilation time, bail out if the use list is huge.
      if (I->hasNUsesOrMore(UsesLimit))
        return true;
      unsigned Outside = 0;
      bool HasNonBenign = false;
      for (User *U : I->users()) {
        if (Stores.contains(U))
          continue;
        ++Outside;
        if (Outside > 2)
          return true;
        if (!IsBenignOutsideUser(cast<Instruction>(U)))
          HasNonBenign = true;
        if (Outside == 2 && HasNonBenign)
          return true;
      }
      return false;
    };
    if (S && S.getOpcode() != Instruction::Load &&
        all_of(ValOps.getArrayRef(), [&](Value *V) {
          auto *I = cast<Instruction>(V);
          return none_of(I->operand_values(), IsaPred<LoadInst>) &&
                 HasTooManyOutsideUsers(I);
        })) {
      Size = 1;
      return false;
    }
  }
  R.buildTree(Chain);
  // Check if tree tiny and store itself or its value is not vectorized.
  if (R.isTreeTinyAndNotFullyVectorizable()) {
    if (R.isGathered(Chain.front()) ||
        R.isNotScheduled(cast<StoreInst>(Chain.front())->getValueOperand()))
      return std::nullopt;
    Size = R.getCanonicalGraphSize();
    return false;
  }
  if (R.isProfitableToReorder()) {
    R.reorderTopToBottom();
    R.reorderBottomToTop();
  }
  if (R.isTryingRuntimeAliasChecks())
    R.captureRuntimeCheckBodySnapshot();
  R.transformNodes();
  R.computeMinimumValueSizes();

  InstructionCost TreeCost = R.calculateTreeCostAndTrimNonProfitable();
  R.buildExternalUses();

  Size = R.getCanonicalGraphSize() - R.getNumSplatSubtreeEntries();
  if (S && S.getOpcode() == Instruction::Load)
    Size = 2; // cut off masked gather small trees
  InstructionCost Cost = R.getTreeCost(TreeCost);

  // When the tree was scheduled by dropping may-alias dependencies, account
  // for the runtime alias checks in the cost and make sure the region can
  // actually be versioned. If it cannot, abandon this attempt: the dropped
  // dependencies are unused because the tree is not vectorized.
  // The full check cost is charged against the vector-path benefit here; the
  // scalar-path overhead is bounded separately in canVersionForRuntimeChecks()
  // (a fraction of the scalar body cost).
  if (R.isTryingRuntimeAliasChecks() && R.hasRuntimeAliasChecks()) {
    // getRuntimeChecksCost() only ever sums non-negative per-instruction
    // throughput costs (address adds, compares, and/or, the guard branch), so
    // adding it can only push Cost up, never down, and an already-invalid
    // Cost (e.g. rejected by one of getTreeCost()'s own heuristics) stays
    // invalid either way. So if Cost already fails the threshold below, no
    // checks cost can rescue it: skip the (expensive) SCEV/dominance/escape
    // analysis in canVersionForRuntimeChecks() instead of running it on a
    // tree that is already rejected.
    if (Cost >= -R.getCostThreshold())
      return false;
    if (!R.canVersionForRuntimeChecks())
      return false;
    // TODO: Add probability-weighted model (benefit scaled by the expected
    // non-alias odds) would be more precise but needs
    // branch-probability/profile data.
    Cost += R.getRuntimeChecksCost();
  }

  LLVM_DEBUG(dbgs() << "SLP: Found cost = " << Cost << " for VF=" << VF << "\n");
  if (Cost < -R.getCostThreshold()) {
    LLVM_DEBUG(dbgs() << "SLP: Decided to vectorize cost = " << Cost << "\n");

    using namespace ore;

    R.getORE()->emit(OptimizationRemark(SV_NAME, "StoresVectorized",
                                        cast<StoreInst>(Chain[0]))
                     << "Stores SLP vectorized with cost " << NV("Cost", Cost)
                     << " and with tree size "
                     << NV("TreeSize", R.getTreeSize()));

    R.vectorizeTree();
    return true;
  }

  return false;
}

namespace {
/// A group of related stores which we are in the process of vectorizing,
/// a subset of which may already be vectorized. Stores context information
/// about the group as a whole as well as information about what VFs need
/// to be attempted still.
class StoreChainContext {
public:
  using SizePair = std::pair<unsigned, unsigned>;

  explicit StoreChainContext(const VectorizeOptions &Opts,
                             ArrayRef<Value *> Ops,
                             ArrayRef<SizePair> RangeSizes,
                             SmallVector<unsigned> &RangeSizesByIdx,
                             unsigned Stride)
      : Opts(Opts), Operands(Ops), RangeSizesStorage(RangeSizes),
        RangeSizesByIdx(RangeSizesByIdx), Stride(Stride) {}

  /// Set up initial values using the already set Operands
  bool initializeContext(
      BoUpSLP &R, const DataLayout &DL, const TargetTransformInfo &TTI,
      DenseSet<std::tuple<Value *, Value *, Value *, Value *, unsigned>>
          &Visited);
  /// Get the current VF
  std::optional<unsigned> getCurrentVF() const;
  /// Return the maximum VF for the context
  unsigned getMaxVF() const { return MaxVF; }
  /// Return the stride of the context
  unsigned getStride() const { return Stride; }
  /// Attempt to vectorize Operands for the given VF
  /// Returns false if no more attempts should be made for the context
  bool vectorizeOneVF(const TargetTransformInfo &TTI, unsigned VF,
                      BoUpSLP::ValueSet &VectorizedStores, bool &Changed,
                      llvm::function_ref<std::optional<bool>(
                          ArrayRef<Value *>, unsigned, unsigned, unsigned &)>
                          VectorizeStoreChain);
  /// Add an additional store to the chain
  /// \p Store store too append to Operands
  /// \p Idx position within VectorizeStores::Stores
  void addOperand(Value *Store, unsigned Idx);

private:
  bool isNotVectorized(const SizePair &P) const {
    return P.first != LocallyUnvectorizable && RangeSizesByIdx[P.first] > 0;
  }

  bool isVectorized(const SizePair &P) const {
    return P.first == LocallyUnvectorizable || RangeSizesByIdx[P.first] == 0;
  }

  bool isVFProfitable(unsigned Size, const SizePair &P) const {
    assert(P.first != LocallyUnvectorizable && RangeSizesByIdx[P.first] &&
           "Cannot check profitability of vectorized element");
    return Size >= RangeSizesByIdx[P.first];
  }

  bool firstSizeSame(unsigned Size, const SizePair &P) const {
    assert(P.first != LocallyUnvectorizable && RangeSizesByIdx[P.first] &&
           "Cannot check profitability of vectorized element");
    return Size == RangeSizesByIdx[P.first];
  }

  /// Return the index of the first unvectorized store after \p StartIdx
  unsigned getFirstUnvecStore(unsigned StartIdx = 0) const;
  /// Return the index of the first vectorized store after \p StartIdx
  unsigned getFirstVecStoreAfter(unsigned StartIdx) const;
  /// Return true if all stores have been vectorized
  bool allVectorized() const;
  /// Return true if all elements in the given range match \p TreeSize
  bool isFirstSizeSameRange(unsigned StartIdx, unsigned Length,
                            unsigned TreeSize) const;
  /// Return true if the \p TreeSize is profitable for all elements in the range
  bool allOfRangeProfitable(unsigned StartIdx, unsigned Length,
                            unsigned TreeSize) const;
  /// Update the live (first) range sizes from the cached values (second)
  void updateRangeSizesFromCache();
  /// Update the cached (second) range sizes with the given \p TreeSize
  void updateCachedRangeSizes(unsigned StartIdx, unsigned Length,
                              unsigned TreeSize);
  /// Update CandidateVFs for secondary iterations
  bool updateCandidateVFs(const TargetTransformInfo &TTI);
  /// Remove the current VF from the queue
  void incrementVF() {
    if (!CandidateVFs.empty())
      CandidateVFs.pop();
  }
  /// Record vectorization of the provided range
  void markRangeVectorized(unsigned StartIdx, unsigned Length,
                           unsigned &FirstUnvecStore, unsigned &MaxSliceEnd);
  /// Checks if the quadratic mean deviation is less than 90% of the mean size.
  bool checkTreeSizes(const unsigned SliceStartIdx, const unsigned VF) const;

  /// In RangeSizes, element has not been vectorized, but due to the elements
  /// around it being vectorized, it does not have enough neighboring elements
  /// to make a chain longer than MinVF as part of the current Context
  static constexpr unsigned LocallyUnvectorizable =
      std::numeric_limits<unsigned>::max();
  /// Maximum number of iterations through CandidateVFs
  static constexpr unsigned MaxAttempts = 4;

  const VectorizeOptions &Opts;
  /// For the StoreTy/Stride in the given group, what is the smallest VF
  /// that can be used
  unsigned MinVF = 0;
  /// Maximum number of instructions that can be vectorized, either
  /// constrained by register width or operands size.
  unsigned MaxVF = 0;
  /// MaxRegVF represents the number of instructions (scalar, or vector in
  /// case of revec) that can be vectorized to naturally fit in a vector
  /// register.
  unsigned MaxRegVF = 0;
  /// The largest VF checked in the current Repeat
  unsigned ProbeVF = 0;
  /// Type of the Stores in `Operands`
  Type *StoreTy = nullptr;
  /// Which VFs do we want to attempt for this chain
  std::queue<unsigned> CandidateVFs;
  /// Stores that compose this chain
  BoUpSLP::ValueList Operands;
  /// Track the TreeSizes of prior vectorization attempts using each element,
  /// to help us find early exit cases
  /// - first: contains pointer into RangeSizesByIdx to help us track
  /// vectorization of elements that belong to multiple chains
  /// - second: contains cached TreeSize value for that element
  SmallVector<SizePair> RangeSizesStorage;
  MutableArrayRef<SizePair> RangeSizes;
  /// RangeSize information for all elements in any chain
  /// Needed since may be overlap between chains
  SmallVector<unsigned> &RangeSizesByIdx;
  /// What element index is the end of the to be vectorized Operands
  /// i.e. Operands.size() == 16, and 12-15 were vectorized, then End == 12
  unsigned End = 0;
  /// How many times has CandidateVFs been refilled, prevents excessive
  /// attempts at vectorizing large VFs
  unsigned Repeat = 1;
  /// Did any vectorization occur for the current iteration over CandidateVFs
  bool RepeatChanged = false;
  /// For constant strided stores, what is the stride amount
  const unsigned Stride = 0;
  /// Store information about failed vectorization attempts due to scheduling
  SmallDenseMap<Value *, SizePair> NonSchedulable;
};

void StoreChainContext::addOperand(Value *Store, unsigned Idx) {
  Operands.push_back(Store);
  RangeSizesStorage.push_back({Idx, 1});
}

void StoreChainContext::markRangeVectorized(unsigned StartIdx, unsigned Length,
                                            unsigned &FirstUnvecStore,
                                            unsigned &MaxSliceEnd) {
  for (SizePair &P : RangeSizes.slice(StartIdx, Length))
    RangeSizesByIdx[P.first] = P.second = 0;
  if (StartIdx < FirstUnvecStore + MinVF) {
    for (SizePair &P :
         RangeSizes.slice(FirstUnvecStore, StartIdx - FirstUnvecStore)) {
      P.first = LocallyUnvectorizable;
      P.second = 0;
    }
    FirstUnvecStore = StartIdx + Length;
  }
  if (StartIdx + Length > MaxSliceEnd - MinVF) {
    for (SizePair &P : RangeSizes.slice(StartIdx + Length,
                                        MaxSliceEnd - (StartIdx + Length))) {
      P.first = LocallyUnvectorizable;
      P.second = 0;
    }
    if (MaxSliceEnd == End)
      End = StartIdx;
    MaxSliceEnd = StartIdx;
  }
}

bool StoreChainContext::initializeContext(
    BoUpSLP &R, const DataLayout &DL, const TargetTransformInfo &TTI,
    DenseSet<std::tuple<Value *, Value *, Value *, Value *, unsigned>>
        &Visited) {
  if (!Visited
           .insert({Operands.front(),
                    cast<StoreInst>(Operands.front())->getValueOperand(),
                    Operands.back(),
                    cast<StoreInst>(Operands.back())->getValueOperand(),
                    Operands.size()})
           .second)
    return false;

  // Initialize range tracking in context.
  RangeSizes = MutableArrayRef(RangeSizesStorage);

  unsigned MaxVecRegSize = R.getMaxVecRegSize();
  unsigned EltSize = R.getVectorElementSize(Operands[0]);
  unsigned MaxElts = llvm::bit_floor(MaxVecRegSize / EltSize);

  MaxVF = std::min(R.getMaximumVF(EltSize, Instruction::Store), MaxElts);
  auto *Store = cast<StoreInst>(Operands[0]);
  StoreTy = Store->getValueOperand()->getType();
  Type *ValueTy = StoreTy;
  if (auto *Trunc = dyn_cast<TruncInst>(Store->getValueOperand()))
    ValueTy = Trunc->getSrcTy();
  // When REVEC is enabled, StoreTy and ValueTy may be FixedVectorType. But
  // getStoreMinimumVF only support scalar type as arguments. As a result,
  // we need to use the element type of StoreTy and ValueTy to retrieve the
  // VF and then transform it back.
  // Remember: VF is defined as the number we want to vectorize, not the
  // number of elements in the final vector.
  Type *StoreScalarTy = StoreTy->getScalarType();
  MinVF = PowerOf2Ceil(TTI.getStoreMinimumVF(
      R.getMinVF(DL.getTypeStoreSizeInBits(StoreScalarTy)), StoreScalarTy,
      ValueTy->getScalarType(), Store->getAlign(),
      Store->getPointerAddressSpace()));
  MinVF /= getNumElements(StoreTy);
  MinVF = std::max<unsigned>(2, MinVF);
  if (Stride > 1)
    MinVF = std::max(MinVF, Opts.slp_min_strided_stores);

  if (MaxVF < MinVF) {
    LLVM_DEBUG(dbgs() << "SLP: Vectorization infeasible as MaxVF (" << MaxVF
                      << ") < "
                      << "MinVF (" << MinVF << ")\n");
    return false;
  }

  // First try a supported non-power-of-2 VF (see isAllowedNonPowerOf2VF).
  unsigned NonPowerOf2VF = 0;
  unsigned CandVF = std::clamp<unsigned>(Operands.size(), MinVF, MaxVF);
  if (isAllowedNonPowerOf2VF(CandVF, Opts.slp_vectorize_non_power_of_2)) {
    NonPowerOf2VF = CandVF;
    assert(NonPowerOf2VF != MaxVF &&
           "Non-power-of-2 VF should not be equal to MaxVF");
  }

  MaxRegVF = MaxVF;

  MaxVF = std::min<unsigned>(MaxVF, bit_floor(Operands.size()));
  if (MaxVF < MinVF) {
    LLVM_DEBUG(dbgs() << "SLP: Vectorization infeasible as MaxVF (" << MaxVF
                      << ") < "
                      << "MinVF (" << MinVF << ")\n");
    return false;
  }

  for (unsigned VF = std::max(MaxVF, NonPowerOf2VF); VF >= MinVF;
       VF = divideCeil(VF, 2))
    CandidateVFs.push(VF);

  End = Operands.size();
  ProbeVF = MaxVF;
  return true;
}

// Return the index of the first unvectorized store after \p StartIdx
unsigned StoreChainContext::getFirstUnvecStore(unsigned StartIdx) const {
  return std::distance(
      RangeSizes.begin(),
      find_if(RangeSizes.drop_front(StartIdx),
              [this](const SizePair &P) { return this->isNotVectorized(P); }));
}

// Return the index of the first vectorized store after \p StartIdx
unsigned StoreChainContext::getFirstVecStoreAfter(unsigned StartIdx) const {
  return std::distance(
      RangeSizes.begin(),
      find_if(RangeSizes.drop_front(StartIdx),
              [this](const SizePair &P) { return this->isVectorized(P); }));
}

// Return true if all stores have been vectorized
bool StoreChainContext::allVectorized() const {
  return all_of(RangeSizes,
                [this](const SizePair &P) { return this->isVectorized(P); });
}

// Return true if all elements in the given range match \p TreeSize
bool StoreChainContext::isFirstSizeSameRange(unsigned StartIdx, unsigned Length,
                                             unsigned TreeSize) const {
  return all_of(RangeSizes.slice(StartIdx, Length),
                [TreeSize, this](const SizePair &P) {
                  return firstSizeSame(TreeSize, P);
                });
}

// Return true if the \p TreeSize is profitable for all elements in the range
bool StoreChainContext::allOfRangeProfitable(unsigned StartIdx, unsigned Length,
                                             unsigned TreeSize) const {
  return all_of(RangeSizes.slice(StartIdx, Length),
                [TreeSize, this](const SizePair &P) {
                  return isVFProfitable(TreeSize, P);
                });
}

// Update the live (first) range sizes from the cached values (second)
void StoreChainContext::updateRangeSizesFromCache() {
  for (SizePair &P : RangeSizes) {
    if (P.first != LocallyUnvectorizable && RangeSizesByIdx[P.first] != 0)
      RangeSizesByIdx[P.first] = std::max(P.second, RangeSizesByIdx[P.first]);
  }
}

// Update the cached (second) range sizes with the given \p TreeSize
void StoreChainContext::updateCachedRangeSizes(unsigned StartIdx,
                                               unsigned Length,
                                               unsigned TreeSize) {
  for (SizePair &P : RangeSizes.slice(StartIdx, Length))
    P.second = std::max(P.second, TreeSize);
}

bool StoreChainContext::updateCandidateVFs(const TargetTransformInfo &TTI) {
  assert(CandidateVFs.empty() && "Did not use all VFs before refilling");
  constexpr unsigned StoresLimit = 64;
  const unsigned MaxTotalNum = std::min<unsigned>(
      Operands.size(), static_cast<unsigned>(End - getFirstUnvecStore()));
  unsigned VF = bit_ceil(ProbeVF) * 2;
  if (VF > MaxTotalNum || VF >= StoresLimit)
    return false;
  // Attempt again to vectorize even larger chains if all previous
  // attempts were unsuccessful because of the cost issues.
  unsigned Limit = getFloorFullVectorNumberOfElements(TTI, StoreTy, MaxTotalNum,
                                                      Opts.slp_revec);
  if (bit_floor(Limit) == VF && Limit != VF)
    CandidateVFs.push(Limit);
  CandidateVFs.push(VF);
  ProbeVF = CandidateVFs.front();
  ++Repeat;
  RepeatChanged = false;
  return true;
}

// Get the current VF
std::optional<unsigned> StoreChainContext::getCurrentVF() const {
  if (CandidateVFs.empty())
    return std::nullopt;
  return CandidateVFs.front();
}

bool StoreChainContext::checkTreeSizes(const unsigned SliceStartIdx,
                                       const unsigned VF) const {
  auto Sizes = RangeSizes.slice(SliceStartIdx, VF);
  unsigned Num = 0;
  uint64_t Sum = std::accumulate(
      Sizes.begin(), Sizes.end(), static_cast<uint64_t>(0),
      [&](uint64_t V, const std::pair<unsigned, unsigned> &Val) {
        unsigned Size = Val.first == StoreChainContext::LocallyUnvectorizable
                            ? 0
                            : RangeSizesByIdx[Val.first];
        if (Size == 1)
          return V;
        ++Num;
        return V + Size;
      });
  if (Num == 0)
    return true;
  uint64_t Mean = Sum / Num;
  if (Mean == 0)
    return true;
  uint64_t Dev =
      accumulate(Sizes, static_cast<uint64_t>(0),
                 [&](uint64_t V, const std::pair<unsigned, unsigned> &Val) {
                   unsigned P =
                       Val.first == StoreChainContext::LocallyUnvectorizable
                           ? 0
                           : RangeSizesByIdx[Val.first];
                   if (P == 1)
                     return V;
                   return V + (P - Mean) * (P - Mean);
                 }) /
      Num;
  return Dev * 96 / (Mean * Mean) == 0;
}

bool StoreChainContext::vectorizeOneVF(
    const TargetTransformInfo &TTI, unsigned VF,
    BoUpSLP::ValueSet &VectorizedStores, bool &Changed,
    llvm::function_ref<std::optional<bool>(ArrayRef<Value *>, unsigned,
                                           unsigned, unsigned &)>
        VectorizeStoreChain) {
  bool AnyProfitableGraph = false;
  bool PreferWideSlices = false;
  unsigned FirstUnvecStore = getFirstUnvecStore();

  // Form slices of size VF starting from FirstUnvecStore and try to
  // vectorize them.
  while (FirstUnvecStore < End) {
    unsigned FirstVecStore = getFirstVecStoreAfter(FirstUnvecStore);
    unsigned MaxSliceEnd = FirstVecStore >= End ? End : FirstVecStore;
    for (unsigned SliceStartIdx = FirstUnvecStore;
         SliceStartIdx + VF <= MaxSliceEnd;) {
      if (!checkTreeSizes(SliceStartIdx, VF)) {
        ++SliceStartIdx;
        continue;
      }
      ArrayRef<Value *> Slice = ArrayRef(Operands).slice(SliceStartIdx, VF);
      assert(all_of(Slice,
                    [&](Value *V) {
                      return cast<StoreInst>(V)->getValueOperand()->getType() ==
                             cast<StoreInst>(Slice.front())
                                 ->getValueOperand()
                                 ->getType();
                    }) &&
             "Expected all operands of same type.");
      if (!NonSchedulable.empty()) {
        auto [NonSchedSizeMax, NonSchedSizeMin] =
            NonSchedulable.lookup(Slice.front());
        if (NonSchedSizeMax > 0 && NonSchedSizeMin <= VF) {
          // VF is too ambitious. Try to vectorize another slice before
          // trying a smaller VF.
          SliceStartIdx += NonSchedSizeMax;
          continue;
        }
      }
      auto MarkVectorized = [&](unsigned Len) {
        // Mark the vectorized stores so that we don't vectorize them
        // again.
        VectorizedStores.insert_range(
            ArrayRef(Operands).slice(SliceStartIdx, Len));
        AnyProfitableGraph = RepeatChanged = Changed = true;
        // If we vectorized initial block, no need to try to vectorize
        // it again.
        markRangeVectorized(SliceStartIdx, Len, FirstUnvecStore, MaxSliceEnd);
        SliceStartIdx += Len;
        ++NumStoreChains;
        if (Stride > 1)
          ++NumStridedStoreChains;
        NumVectorizedStores += Len;
      };
      // With the register VF 2 the instruction count check may reject the
      // leading slice, shifting it strands its stores and the wider VFs are
      // tried only if nothing is vectorized: try the wider slice at the same
      // position. Once the chain took the wider slices, try them first.
      auto TryWideSlice = [&]() {
        if (MaxRegVF != 2 || VF != MaxRegVF ||
            SliceStartIdx != FirstUnvecStore ||
            SliceStartIdx + 2 * VF > MaxSliceEnd)
          return false;
        unsigned WideTreeSize;
        if (!VectorizeStoreChain(
                 ArrayRef(Operands).slice(SliceStartIdx, 2 * VF), SliceStartIdx,
                 MinVF, WideTreeSize)
                 .value_or(false))
          return false;
        MarkVectorized(2 * VF);
        return true;
      };
      const bool WideFirst = PreferWideSlices;
      if (WideFirst && TryWideSlice())
        continue;
      PreferWideSlices = false;
      unsigned TreeSize;
      std::optional<bool> Res =
          VectorizeStoreChain(Slice, SliceStartIdx, MinVF, TreeSize);
      if (!Res) {
        // Update the range of non schedulable VFs for slices starting
        // at SliceStartIdx.
        NonSchedulable.try_emplace(Slice.front(), std::make_pair(VF, VF))
            .first->getSecond()
            .second = VF;
      } else if (*Res) {
        MarkVectorized(VF);
        continue;
      }
      if (Res && !WideFirst && TryWideSlice()) {
        PreferWideSlices = true;
        continue;
      }
      if (VF > 2 && Res && !allOfRangeProfitable(SliceStartIdx, VF, TreeSize)) {
        SliceStartIdx += VF;
        continue;
      }
      // Check for the very big VFs that we're not rebuilding same
      // trees, just with larger number of elements.
      if (VF > MaxRegVF && TreeSize > 1 &&
          isFirstSizeSameRange(SliceStartIdx, VF, TreeSize)) {
        SliceStartIdx += VF;
        while (SliceStartIdx != MaxSliceEnd &&
               isFirstSizeSameRange(SliceStartIdx, 1, TreeSize))
          ++SliceStartIdx;
        continue;
      }
      if (TreeSize > 1)
        updateCachedRangeSizes(SliceStartIdx, VF, TreeSize);
      ++SliceStartIdx;
      AnyProfitableGraph = true;
    }
    if (FirstUnvecStore >= End)
      break;
    if (MaxSliceEnd - FirstUnvecStore < VF &&
        MaxSliceEnd - FirstUnvecStore >= MinVF)
      AnyProfitableGraph = true;
    FirstUnvecStore = getFirstUnvecStore(MaxSliceEnd);
  }
  if (!AnyProfitableGraph && VF >= MaxRegVF && has_single_bit(VF))
    while (!CandidateVFs.empty())
      CandidateVFs.pop();

  // For the MaxRegVF case, save RangeSizes to limit compile time
  if (VF == MaxRegVF)
    updateRangeSizesFromCache();

  incrementVF();
  if (!getCurrentVF()) {
    // All values vectorized - exit.
    if (allVectorized())
      return false;
    // Check if tried all attempts or no need for the last attempts at
    // all.
    if (Repeat >= MaxAttempts ||
        (Repeat > 1 && (RepeatChanged || !AnyProfitableGraph)))
      return false;

    if (!updateCandidateVFs(TTI))
      return false;
    // Avoid double update of cache sizes
    if (VF != MaxRegVF)
      updateRangeSizesFromCache();
  }
  return true;
}

/// A group of stores that we'll try to bundle together using vector ops.
/// They are ordered using the signed distance of their address operand to the
/// address of this group's BaseInstr.
class RelatedStoreInsts {
public:
  RelatedStoreInsts(unsigned BaseInstrIdx, ArrayRef<StoreInst *> AllStores)
      : AllStores(AllStores) {
    reset(BaseInstrIdx);
  }

  void reset(unsigned NewBaseInstr) {
    assert(NewBaseInstr < AllStores.size() &&
           "Instruction index out of bounds");
    BaseInstrIdx = NewBaseInstr;
    Instrs.clear();
    insertOrLookup(NewBaseInstr, 0);
  }

  /// Tries to insert \p InstrIdx as the store with a pointer distance of
  /// \p PtrDist.
  /// Does nothing if there is already a store with that \p PtrDist.
  /// \returns The previously associated Instruction index, or std::nullopt
  std::optional<unsigned> insertOrLookup(unsigned InstrIdx, int64_t PtrDist) {
    auto [It, Inserted] = Instrs.emplace(PtrDist, InstrIdx);
    return Inserted ? std::nullopt : std::make_optional(It->second);
  }

  using DistToInstMap = std::map<int64_t, unsigned>;
  const DistToInstMap &getStores() const { return Instrs; }

  /// If \p SI is related to this group of stores, return the distance of its
  /// pointer operand to the one the group's BaseInstr.
  std::optional<int64_t> getPointerDiff(StoreInst &SI, const DataLayout &DL,
                                        ScalarEvolution &SE) const {
    StoreInst &BaseStore = *AllStores[BaseInstrIdx];
    return getPointersDiff(
        BaseStore.getValueOperand()->getType(), BaseStore.getPointerOperand(),
        SI.getValueOperand()->getType(), SI.getPointerOperand(), DL, SE,
        /*StrictCheck=*/true);
  }

  /// Recompute the pointer distances to be based on \p NewBaseInstIdx.
  /// Stores whose index is less than \p MinSafeIdx will be dropped.
  void rebase(unsigned MinSafeIdx, unsigned NewBaseInstIdx,
              int64_t DistFromCurBase) {
    DistToInstMap PrevSet = std::move(Instrs);
    reset(NewBaseInstIdx);

    // Re-insert stores that come after MinSafeIdx to try and vectorize them
    // again. Their distance will be "rebased" to use NewBaseInstIdx as
    // reference.
    for (auto [Dist, InstIdx] : PrevSet) {
      if (InstIdx >= MinSafeIdx)
        insertOrLookup(InstIdx, Dist - DistFromCurBase);
    }
  }

private:
  /// The index of the Base instruction, i.e. the one with a 0 pointer distance.
  unsigned BaseInstrIdx;

  /// Maps a pointer distance from \p BaseInstrIdx to an instruction index.
  DistToInstMap Instrs;

  /// Reference to all the stores in the BB being analyzed.
  ArrayRef<StoreInst *> AllStores;
};

} // end anonymous namespace

bool SLPVectorizerPass::vectorizeStores(
    ArrayRef<StoreInst *> Stores, BoUpSLP &R,
    DenseSet<std::tuple<Value *, Value *, Value *, Value *, unsigned>> &Visited,
    bool AllowMaskedStores) {
  // We may run into multiple chains that merge into a single chain. We mark the
  // stores that we vectorized so that we don't visit the same store twice.
  BoUpSLP::ValueSet VectorizedStores;
  bool Changed = false;
  SmallVector<std::unique_ptr<StoreChainContext>> AllContexts;
  SmallVector<unsigned> RangeSizesByIdx(Stores.size(), 1);

  auto ExtendContexts = [&](const RelatedStoreInsts::DistToInstMap &StoreSeq) {
    BoUpSLP::ValueList Operands;
    const unsigned MaxStride =
        Opts->slp_enable_strided_stores ? Opts->slp_max_stride : 1;

    // All chains that we're still building
    struct PartialChainStatus {
      // Has been added to AllContexts
      // Wait to add to AllContexts until at least two stores are found
      bool AddedToAllContexts;
      union {
        // If added, index into AllContexts
        unsigned AllContextsIdx;
        // Index into Stores if not added to AllContexts yet
        unsigned StoresIdx;
      };
      // If not added to AllContexts, what is the single store in the chain
      Value *FirstStore;
      // What is the Stride of this chain
      unsigned Stride;
    };
    SmallVector<SmallVector<PartialChainStatus, 1>> Chains(MaxStride + 1);
    auto GetChainsKey = [&](int64_t Query) -> unsigned {
      // Just modulo function, get the index into Chains for a given query
      int64_t Rem = (Query % (int64_t)Chains.size());
      if (Rem < 0)
        Rem += (int64_t)Chains.size();
      return (unsigned)Rem;
    };
    int64_t LastDist;
    for (auto [Idx, Data] : enumerate(StoreSeq)) {
      auto &[Dist, InstIdx] = Data;
      // Clean up chains that can't be continued
      if (Idx > 0)
        for (int64_t D = LastDist;
             D < std::min(Dist, LastDist + (int64_t)Chains.size()); ++D)
          Chains[GetChainsKey(D)].clear();
      LastDist = Dist;

      // Track which stride lengths we found existing chains for
      // Don't have to add new entries for these
      SmallVector<bool> FoundStrides(Opts->slp_max_stride + 1, false);
      for (auto &Status : Chains[GetChainsKey(Dist)]) {
        if (Status.AddedToAllContexts) {
          // Chain already in AllContexts()
          AllContexts[Status.AllContextsIdx]->addOperand(Stores[InstIdx],
                                                         InstIdx);
        } else {
          // Chain just a single element, not yet in AllContexts()
          SmallVector<StoreChainContext::SizePair> RS = {{Status.StoresIdx, 1},
                                                         {InstIdx, 1}};
          BoUpSLP::ValueList Ops = {Status.FirstStore, Stores[InstIdx]};
          AllContexts.emplace_back(std::make_unique<StoreChainContext>(
              *Opts, Ops, RS, RangeSizesByIdx, Status.Stride));
          Status.AllContextsIdx = AllContexts.size() - 1;
        }
        unsigned Key = GetChainsKey(Status.Stride + Dist);
        Chains[Key].push_back({/*AddedToAllContexts=*/true,
                               {Status.AllContextsIdx},
                               /*FirstStore=*/nullptr,
                               Status.Stride});
        FoundStrides[Status.Stride] = true;
      }
      Chains[GetChainsKey(Dist)].clear();
      // For any stride lengths that we didn't append to a chain for,
      // instead start a new chain
      for (auto Stride : seq<unsigned>(1, MaxStride + 1)) {
        if (FoundStrides[Stride])
          continue;
        unsigned Key = GetChainsKey(Dist + Stride);
        Chains[Key].push_back({/*AddedToAllContexts=*/false,
                               {/*StoresIdx=*/(unsigned)InstIdx},
                               Stores[InstIdx],
                               Stride});
      }
    }
  };

  auto ActuallyVectorizeContexts = [&]() {
    unsigned GlobalMaxVF = 0;
    for (auto &CtxPtr : AllContexts)
      if (CtxPtr->initializeContext(R, *DL, *TTI, Visited))
        GlobalMaxVF = std::max(GlobalMaxVF, CtxPtr->getMaxVF());
      else
        CtxPtr.reset();

    // Prioritize non-strided chains (Stride = 1)
    llvm::stable_sort(AllContexts,
                      [](const std::unique_ptr<StoreChainContext> &A,
                         const std::unique_ptr<StoreChainContext> &B) {
                        return A && (!B || A->getStride() < B->getStride());
                      });

    for (unsigned LimitVF = GlobalMaxVF; LimitVF > 0;
         LimitVF = bit_ceil(LimitVF) / 2) {
      for (auto &CtxPtr : AllContexts) {
        if (!CtxPtr)
          break;
        StoreChainContext &Context = *CtxPtr;
        for (std::optional<unsigned> VFUnval = Context.getCurrentVF();
             VFUnval && *VFUnval >= LimitVF; VFUnval = Context.getCurrentVF()) {
          unsigned VF = *VFUnval;
          if (!Context.vectorizeOneVF(
                  *TTI, VF, VectorizedStores, Changed,
                  [this, &R](ArrayRef<Value *> Chain, unsigned Idx,
                             unsigned MinVF, unsigned &Size) {
                    return vectorizeStoreChain(Chain, R, Idx, MinVF, Size);
                  })) {
            CtxPtr.reset();
            break;
          }
        }
      }
    }
  };

  /// Groups of stores to vectorize
  SmallVector<RelatedStoreInsts> SortedStores;

  // Inserts the specified store SI with the given index Idx to the set of the
  // stores. If the store with the same distance is found already - stop
  // insertion, try to vectorize already found stores. If some stores from this
  // sequence were not vectorized - try to vectorize them with the new store
  // later. But this logic is applied only to the stores, that come before the
  // previous store with the same distance.
  // Example:
  // 1. store x, %p
  // 2. store y, %p+1
  // 3. store z, %p+2
  // 4. store a, %p
  // 5. store b, %p+3
  // - Scan this from the last to first store. The very first bunch of stores is
  // {5, {{4, -3}, {2, -2}, {3, -1}, {5, 0}}} (the element in SortedStores
  // vector).
  // - The next store in the list - #1 - has the same distance from store #5 as
  // the store #4.
  // - Try to vectorize sequence of stores 4,2,3,5.
  // - If all these stores are vectorized - just drop them.
  // - If some of them are not vectorized (say, #3 and #5), do extra analysis.
  // - Start new stores sequence.
  // The new bunch of stores is {1, {1, 0}}.
  // - Add the stores from previous sequence, that were not vectorized.
  // Here we consider the stores in the reversed order, rather they are used in
  // the IR (Stores are reversed already, see vectorizeStoreChains() function).
  // Store #3 can be added -> comes after store #4 with the same distance as
  // store #1.
  // Store #5 cannot be added - comes before store #4.
  // This logic allows to improve the compile time, we assume that the stores
  // after previous store with the same distance most likely have memory
  // dependencies and no need to waste compile time to try to vectorize them.
  // - Try to vectorize the sequence {1, {1, 0}, {3, 2}}.
  auto FillStoresSet = [&](unsigned Idx, StoreInst *SI) {
    std::optional<int64_t> PtrDist;
    auto *RelatedStores = find_if(
        SortedStores, [&PtrDist, SI, this](const RelatedStoreInsts &StoreSeq) {
          PtrDist = StoreSeq.getPointerDiff(*SI, *DL, *SE);
          return PtrDist.has_value();
        });

    // We did not find a comparable store, start a new group.
    if (RelatedStores == SortedStores.end()) {
      SortedStores.emplace_back(Idx, Stores);
      return;
    }

    // If there is already a store in the group with the same PtrDiff, try to
    // vectorize the existing instructions before adding the current store.
    // Otherwise, insert this store and keep collecting.
    if (std::optional<unsigned> PrevInst =
            RelatedStores->insertOrLookup(Idx, *PtrDist)) {
      ExtendContexts(RelatedStores->getStores());
      RelatedStores->rebase(/*MinSafeIdx=*/*PrevInst + 1,
                            /*NewBaseInstIdx=*/Idx,
                            /*DistFromCurBase=*/*PtrDist);
    }
  };
  Type *PrevValTy = nullptr;
  for (auto [I, SI] : make_filter_range(enumerate(Stores), [&](const auto &P) {
         return !R.isDeleted(P.value());
       })) {
    if (!PrevValTy)
      PrevValTy = SI->getValueOperand()->getType();
    // Check that we do not try to vectorize stores of different types.
    if (PrevValTy != SI->getValueOperand()->getType()) {
      for (RelatedStoreInsts &StoreSeq : SortedStores)
        ExtendContexts(StoreSeq.getStores());
      SortedStores.clear();
      PrevValTy = SI->getValueOperand()->getType();
    }
    FillStoresSet(I, SI);
  }

  // Final vectorization attempt.
  for (RelatedStoreInsts &StoreSeq : SortedStores)
    ExtendContexts(StoreSeq.getStores());

  ActuallyVectorizeContexts();

  // When some stores are still not vectorized, try to lower them together as a
  // single masked store (expand + masked.store).
  if (!AllowMaskedStores)
    return Changed;

  SmallVector<Value *> Remaining;
  for (StoreInst *SI : Stores)
    if (!R.isDeleted(SI) && !VectorizedStores.contains(SI))
      Remaining.push_back(SI);
  if (Remaining.size() < 2)
    return Changed;

  Type *ValTy = getValueType(Remaining.front(), Opts->slp_revec);
  if (any_of(Remaining, [&](Value *V) {
        return cast<StoreInst>(V)->getValueOperand()->getType() != ValTy;
      }))
    return Changed;

  SmallVector<Value *> PointerOps;
  PointerOps.reserve(Remaining.size());
  for (Value *V : Remaining)
    PointerOps.push_back(cast<StoreInst>(V)->getPointerOperand());
  SmallVector<unsigned> Order;
  if (!sortPtrAccesses(PointerOps, ValTy, *DL, *SE, Order))
    return Changed;

  SmallVector<Value *> Sorted(Remaining.size());
  for (unsigned I : seq<unsigned>(Remaining.size()))
    Sorted[I] = Remaining[Order.empty() ? I : Order[I]];

  // No need to re-check for consecutive (stride-1) pairs here: the caller
  // already disables masked stores for the whole base-object group when any
  // consecutive pair exists, so this subset cannot contain one.
  if (!Visited
           .insert({Sorted.front(),
                    cast<StoreInst>(Sorted.front())->getValueOperand(),
                    Sorted.back(),
                    cast<StoreInst>(Sorted.back())->getValueOperand(),
                    Sorted.size()})
           .second)
    return Changed;

  unsigned Size = 0;
  if (vectorizeStoreChain(Sorted, R, /*Idx=*/0, /*MinVF=*/2, Size)
          .value_or(false)) {
    VectorizedStores.insert_range(Sorted);
    Changed = true;
  }
  return Changed;
}

void SLPVectorizerPass::collectSeedInstructions(BasicBlock *BB) {
  // Initialize the collections. We will make a single pass over the block.
  Stores.clear();
  GEPs.clear();

  // Visit the store and getelementptr instructions in BB and organize them in
  // Stores and GEPs according to the underlying objects of their pointer
  // operands.
  for (Instruction &I : *BB) {
    // Ignore store instructions that are volatile or have a pointer operand
    // that doesn't point to a scalar type.
    if (auto *SI = dyn_cast<StoreInst>(&I)) {
      if (!SI->isSimple())
        continue;
      Type *ValTy = SI->getValueOperand()->getType();
      if (isa<StructType>(ValTy) || !isValidElementType(ValTy, Opts->slp_revec))
        continue;
      Stores[getUnderlyingObject(SI->getPointerOperand())].push_back(SI);
    }

    // Ignore getelementptr instructions that have more than one index, a
    // constant index, or a pointer operand that doesn't point to a scalar
    // type.
    else if (auto *GEP = dyn_cast<GetElementPtrInst>(&I)) {
      if (GEP->getNumIndices() != 1)
        continue;
      Value *Idx = GEP->idx_begin()->get();
      if (isa<Constant>(Idx))
        continue;
      if (!isValidElementType(Idx->getType(), Opts->slp_revec))
        continue;
      if (GEP->getType()->isVectorTy())
        continue;
      GEPs[GEP->getPointerOperand()].push_back(GEP);
    }
  }
}

bool SLPVectorizerPass::tryToVectorizeList(ArrayRef<Value *> VL, BoUpSLP &R,
                                           bool MaxVFOnly,
                                           bool StandaloneSeeds) {
  if (VL.size() < 2)
    return false;

  LLVM_DEBUG(dbgs() << "SLP: Trying to vectorize a list of length = "
                    << VL.size() << ".\n");

  // Check that all of the parts are instructions of the same type,
  // we permit an alternate opcode via InstructionsState.
  InstructionsState S = getSameOpcode(VL, *TLI);
  if (!S)
    return false;

  Instruction *I0 = S.getMainOp();
  // Make sure invalid types (including vector type) are rejected before
  // determining vectorization factor for scalar instructions.
  for (Value *V : VL) {
    Type *Ty = V->getType();
    if (!isa<InsertElementInst, InsertValueInst>(V) &&
        !isValidElementType(Ty, Opts->slp_revec)) {
      // NOTE: the following will give user internal llvm type name, which may
      // not be useful.
      R.getORE()->emit([&]() {
        std::string TypeStr;
        llvm::raw_string_ostream OS(TypeStr);
        Ty->print(OS);
        return OptimizationRemarkMissed(SV_NAME, "UnsupportedType", I0)
               << "Cannot SLP vectorize list: type "
               << TypeStr + " is unsupported by vectorizer";
      });
      return false;
    }
  }

  Type *ScalarTy =
      getValueType(VL[0], Opts->slp_revec, /*LookThroughCmp=*/true);
  unsigned Sz = R.getVectorElementSize(I0);
  unsigned MinVF = R.getMinVF(Sz);
  // The buildvector, not filling the whole registers, is vectorized as a whole,
  // not as the power-of-2 part plus the scalar remainder.
  auto *IE = dyn_cast<InsertElementInst>(I0);
  const bool AllowNonPowerOf2 =
      Opts->slp_vectorize_non_power_of_2 ||
      (IE && getNumElements(IE->getType()) <
                 getFullVectorNumberOfElements(
                     *TTI, IE->getType()->getScalarType(),
                     getNumElements(IE->getType()), Opts->slp_revec));
  unsigned MaxVF =
      std::max<unsigned>(isAllowedNonPowerOf2VF(VL.size(), AllowNonPowerOf2)
                             ? VL.size()
                             : getFloorFullVectorNumberOfElements(
                                   *TTI, ScalarTy, VL.size(), Opts->slp_revec),
                         MinVF);
  MaxVF = std::min(R.getMaximumVF(Sz, S.getOpcode()), MaxVF);
  // Standalone seeds only need one register worth of lanes.
  if (StandaloneSeeds && Sz != 0)
    MaxVF = std::min(MaxVF, std::max(MinVF, R.getMaxVecRegSize() / Sz));
  if (MaxVF < 2) {
    R.getORE()->emit([&]() {
      return OptimizationRemarkMissed(SV_NAME, "SmallVF", I0)
             << "Cannot SLP vectorize list: vectorization factor "
             << "less than 2 is not supported";
    });
    return false;
  }

  bool Changed = false;
  bool CandidateFound = false;
  InstructionCost MinCost = R.getCostThreshold();
  // The trees of the PHI nodes may walk the loop-carried chains, so the
  // overlapping windows of a long list rebuild almost the same large trees.
  // Limit total size to avoid compile time blow up.
  const unsigned RejectedTreesBudget =
      isa<PHINode>(I0) ? Opts->slp_phi_list_budget
                       : std::numeric_limits<unsigned>::max();
  unsigned RejectedTreesSize = 0;

  unsigned NextInst = 0, MaxInst = VL.size();
  for (unsigned VF = MaxVF; NextInst + 1 < MaxInst && VF >= MinVF;
       VF = getFloorFullVectorNumberOfElements(*TTI, I0->getType(), VF - 1,
                                               Opts->slp_revec)) {
    // No actual vectorization should happen, if number of parts is the same as
    // provided vectorization factor (i.e. the scalar type is used for vector
    // code during codegen).
    auto *VecTy = getWidenedType(ScalarTy, VF);
    if (R.getNumberOfParts(VecTy, ScalarTy) == VF)
      continue;
    // The window revisiting the dependent seeds skipped by the last vectorized
    // window, 0 if there is none.
    unsigned RevisitI = 0;
    for (unsigned I = NextInst;
         I < MaxInst && RejectedTreesSize <= RejectedTreesBudget; ++I) {
      // The skipped seeds are revisited, continue as if they were not skipped.
      if (RevisitI && I > RevisitI) {
        I = NextInst - 1;
        RevisitI = 0;
        continue;
      }
      unsigned ActualVF = std::min(MaxInst - I, VF);

      if (!hasFullVectorsOrPowerOf2(*TTI, ScalarTy, ActualVF,
                                    Opts->slp_revec) &&
          (ActualVF != VL.size() ||
           !isAllowedNonPowerOf2VF(ActualVF, AllowNonPowerOf2)))
        continue;

      if (MaxVFOnly && ActualVF < MaxVF)
        break;
      if ((VF > MinVF && ActualVF < VF) || (VF == MinVF && ActualVF < 2))
        break;

      SmallVector<Value *> Ops(ActualVF, nullptr);
      unsigned Idx = 0;
      SmallPtrSet<const Value *, 8> Taken;
      std::optional<unsigned> FirstSkipped;
      for (auto [Off, V] : enumerate(VL.drop_front(I))) {
        // Check that a previous iteration of this loop did not delete the
        // Value.
        auto *Inst = dyn_cast<Instruction>(V);
        if (Inst && R.isDeleted(Inst))
          continue;
        // The lanes cannot depend on each other, so the seed, fed by the
        // already taken one, is left for the next window.
        if (StandaloneSeeds && Inst &&
            any_of(Inst->operand_values(),
                   [&](const Value *Op) { return Taken.contains(Op); })) {
          if (!FirstSkipped)
            FirstSkipped = I + Off;
          continue;
        }
        Ops[Idx] = V;
        if (StandaloneSeeds)
          Taken.insert(V);
        ++Idx;
        if (Idx == ActualVF)
          break;
      }
      // Not enough vectorizable instructions - exit. A skipped dependent seed
      // may start the next window, so the scan must not stop because of it.
      if (Idx != ActualVF) {
        if (!FirstSkipped)
          break;
        continue;
      }

      // The identical lanes compute the very same value, so the vector node
      // only duplicates it, and the window, rejected by another attempt in the
      // block, is not analyzed again.
      if (R.isAnalyzedBundle(Ops) ||
          (StandaloneSeeds && all_of(drop_begin(Ops), [&](Value *V) {
             return cast<Instruction>(Ops.front())
                 ->isIdenticalTo(cast<Instruction>(V));
           }))) {
        if (StandaloneSeeds)
          I += ActualVF - 1;
        continue;
      }

      LLVM_DEBUG(dbgs() << "SLP: Analyzing " << ActualVF << " operations "
                        << "\n");

      R.buildTree(Ops);
      if (R.isTreeTinyAndNotFullyVectorizable()) {
        RejectedTreesSize += R.getTreeSize();
        R.analyzedBundle(Ops);
        if (StandaloneSeeds)
          I += ActualVF - 1;
        continue;
      }
      if (R.isProfitableToReorder()) {
        R.reorderTopToBottom();
        R.reorderBottomToTop(
            !isa<InsertElementInst, InsertValueInst>(Ops.front()));
      }
      R.transformNodes();
      R.computeMinimumValueSizes();
      InstructionCost TreeCost = R.calculateTreeCostAndTrimNonProfitable();
      R.buildExternalUses();

      InstructionCost Cost = R.getTreeCost(TreeCost);
      CandidateFound = true;
      MinCost = std::min(MinCost, Cost);

      LLVM_DEBUG(dbgs() << "SLP: Found cost = " << Cost
                        << " for VF=" << ActualVF << "\n");
      if (Cost < -R.getCostThreshold()) {
        LLVM_DEBUG(dbgs() << "SLP: Vectorizing list at cost:" << Cost << ".\n");
        R.getORE()->emit(OptimizationRemark(SV_NAME, "VectorizedList",
                                            cast<Instruction>(Ops[0]))
                         << "SLP vectorized with cost " << ore::NV("Cost", Cost)
                         << " and with tree size "
                         << ore::NV("TreeSize", R.getTreeSize()));

        R.vectorizeTree();
        // Move to the next bundle. The skipped dependent seeds are fed by the
        // vectorized lanes now, revisit them first.
        NextInst = I + VF;
        RevisitI = FirstSkipped.value_or(0);
        I = FirstSkipped.value_or(NextInst) - 1;
        Changed = true;
      } else {
        RejectedTreesSize += R.getTreeSize();
        R.analyzedBundle(Ops);
        if (StandaloneSeeds)
          I += ActualVF - 1;
      }
    }
  }

  if (!Changed && CandidateFound) {
    R.getORE()->emit([&]() {
      return OptimizationRemarkMissed(SV_NAME, "NotBeneficial", I0)
             << "List vectorization was possible but not beneficial with cost "
             << ore::NV("Cost", MinCost)
             << " >= " << ore::NV("Treshold", -R.getCostThreshold());
    });
  } else if (!Changed) {
    R.getORE()->emit([&]() {
      return OptimizationRemarkMissed(SV_NAME, "NotPossible", I0)
             << "Cannot SLP vectorize list: vectorization was impossible"
             << " with available vectorization factors";
    });
  }
  return Changed;
}

namespace {

/// Model horizontal reductions.
///
/// A horizontal reduction is a tree of reduction instructions that has values
/// that can be put into a vector as its leaves. For example:
///
/// mul mul mul mul
///  \  /    \  /
///   +       +
///    \     /
///       +
/// This tree has "mul" as its leaf values and "+" as its reduction
/// instructions. A reduction can feed into a store or a binary operation
/// feeding a phi.
///    ...
///    \  /
///     +
///     |
///  phi +=
///
///  Or:
///    ...
///    \  /
///     +
///     |
///   *p =
///
class HorizontalReduction {
  using ReductionOpsType = SmallVector<Value *, 16>;
  using ReductionOpsListType = SmallVector<ReductionOpsType, 2>;
  const VectorizeOptions &Opts;
  ReductionOpsListType ReductionOps;
  /// List of possibly reduced values.
  SmallVector<SmallVector<Value *>> ReducedVals;
  /// Reduced values that enter the reduction with a flipped sign (from an
  /// fsub/fneg chain link), subtracted in the final combine.
  SmallPtrSet<Value *, 8> NegatedReducedVals;
  /// Maps reduced value to the corresponding reduction operation.
  SmallDenseMap<Value *, SmallVector<Instruction *>, 16> ReducedValsToOps;
  WeakTrackingVH ReductionRoot;
  /// The narrowing cast of the cast round-trip following the reduction
  /// operation that consumes the reduced value at the same index (in
  /// collection order, before the reversal to accumulation order), or null.
  /// Ordered reductions with cast-interleaved links only.
  SmallVector<Instruction *> RoundedLinks;
  /// The type of reduction operation.
  RecurKind RdxKind;
  /// Checks if the optimization of original scalar identity operations on
  /// matched horizontal reductions is enabled and allowed.
  bool IsSupportedHorRdxIdentityOp = false;
  /// The minimum number of the reduced values.
  const unsigned ReductionLimit = Opts.slp_vectorize_non_power_of_2 ? 3 : 4;
  /// Contains vector values for reduction including their scale factor,
  /// signedness and sign of their contribution to the reduction result.
  SmallVector<ReductionVectorPart> VectorValuesAndScales;

  /// Narrow reduced values mapped to the shift and the mask applied after
  /// widening.
  SmallDenseMap<Value *, NarrowedLeafInfo> NarrowedLeafShifts;
  /// zext/shl/and/packed-binop chain dropped with the reduction.
  SmallVector<Instruction *> NarrowedChainInsts;

  static bool isCmpSelMinMax(Instruction *I) {
    return match(I, m_Select(m_Cmp(), m_Value(), m_Value())) &&
           RecurrenceDescriptor::isMinMaxRecurrenceKind(getRdxKind(I));
  }

  // And/or are potentially poison-safe logical patterns like:
  // select x, y, false
  // select x, true, y
  static bool isBoolLogicOp(Instruction *I) {
    return isa<SelectInst>(I) &&
           (match(I, m_LogicalAnd()) || match(I, m_LogicalOr()));
  }

  /// Checks if instruction is associative and can be vectorized.
  enum class ReductionOrdering { Unordered, Ordered, None };
  ReductionOrdering RK = ReductionOrdering::None;
  static ReductionOrdering isVectorizable(RecurKind Kind, Instruction *I,
                                          bool TwoElementReduction = false) {
    if (Kind == RecurKind::None)
      return ReductionOrdering::None;

    // Integer ops that map to select instructions or intrinsics are fine.
    if (RecurrenceDescriptor::isIntMinMaxRecurrenceKind(Kind) ||
        isBoolLogicOp(I))
      return ReductionOrdering::Unordered;

    // No need to check for associativity, if 2 reduced values.
    if (TwoElementReduction)
      return ReductionOrdering::Unordered;

    if (Kind == RecurKind::FMax || Kind == RecurKind::FMin) {
      // FP min/max are associative except for NaN and -0.0. We do not
      // have to rule out -0.0 here because the intrinsic semantics do not
      // specify a fixed result for it.
      return I->getFastMathFlags().noNaNs() ? ReductionOrdering::Unordered
                                            : ReductionOrdering::Ordered;
    }

    if (Kind == RecurKind::FMaximum || Kind == RecurKind::FMinimum)
      return ReductionOrdering::Unordered;

    // Reassociation alone cannot change the sign of a zero result, so nsz
    // is not required for fadd reductions.
    if (I->isAssociative() || (Kind == RecurKind::FAdd && I->hasAllowReassoc()))
      return ReductionOrdering::Unordered;

    return isCommutative(I) ? ReductionOrdering::Ordered
                            : ReductionOrdering::None;
  }

  static Value *getRdxOperand(Instruction *I, unsigned Index) {
    // Poison-safe 'or' takes the form: select X, true, Y
    // To make that work with the normal operand processing, we skip the
    // true value operand.
    // TODO: Change the code and data structures to handle this without a hack.
    if (getRdxKind(I) == RecurKind::Or && isa<SelectInst>(I) && Index == 1)
      return I->getOperand(2);
    return I->getOperand(Index);
  }

  /// Creates reduction operation with the current opcode.
  static Value *createOp(IRBuilderBase &Builder, RecurKind Kind, Value *LHS,
                         Value *RHS, const Twine &Name, bool UseSelect) {
    Type *OpTy = LHS->getType();
    assert(OpTy == RHS->getType() && "Expected LHS and RHS of same type");
    switch (Kind) {
    case RecurKind::Or: {
      if (UseSelect && OpTy == CmpInst::makeCmpResultType(OpTy))
        return Builder.CreateSelectWithUnknownProfile(
            LHS, ConstantInt::getAllOnesValue(CmpInst::makeCmpResultType(OpTy)),
            RHS, DEBUG_TYPE, Name);
      unsigned RdxOpcode = RecurrenceDescriptor::getOpcode(Kind);
      return Builder.CreateBinOp((Instruction::BinaryOps)RdxOpcode, LHS, RHS,
                                 Name);
    }
    case RecurKind::And: {
      if (UseSelect && OpTy == CmpInst::makeCmpResultType(OpTy))
        return Builder.CreateSelectWithUnknownProfile(
            LHS, RHS,
            ConstantInt::getNullValue(CmpInst::makeCmpResultType(OpTy)),
            DEBUG_TYPE, Name);
      unsigned RdxOpcode = RecurrenceDescriptor::getOpcode(Kind);
      return Builder.CreateBinOp((Instruction::BinaryOps)RdxOpcode, LHS, RHS,
                                 Name);
    }
    case RecurKind::Add:
    case RecurKind::Mul:
    case RecurKind::Xor:
    case RecurKind::FAdd:
    case RecurKind::FSub:
    case RecurKind::FMul: {
      unsigned RdxOpcode = RecurrenceDescriptor::getOpcode(Kind);
      return Builder.CreateBinOp((Instruction::BinaryOps)RdxOpcode, LHS, RHS,
                                 Name);
    }
    case RecurKind::SMax:
    case RecurKind::SMin:
    case RecurKind::UMax:
    case RecurKind::UMin:
      if (UseSelect) {
        CmpInst::Predicate Pred = llvm::getMinMaxReductionPredicate(Kind);
        Value *Cmp = Builder.CreateICmp(Pred, LHS, RHS, Name);
        return Builder.CreateSelectWithUnknownProfile(Cmp, LHS, RHS, DEBUG_TYPE,
                                                      Name);
      }
      [[fallthrough]];
    case RecurKind::FMax:
    case RecurKind::FMin:
    case RecurKind::FMaximum:
    case RecurKind::FMinimum:
    case RecurKind::FMaximumNum:
    case RecurKind::FMinimumNum: {
      Intrinsic::ID Id = llvm::getMinMaxReductionIntrinsicOp(Kind);
      return Builder.CreateBinaryIntrinsic(Id, LHS, RHS);
    }
    default:
      llvm_unreachable("Unknown reduction operation.");
    }
  }

  /// \returns true if the disjoint flag of the reduction ops is kept for the
  /// emitted ops.
  bool keepDisjoint() const {
    if (getBoolReduxWideTy(RdxKind, ReductionRoot->getType(),
                           ReducedVals.front().front()->getType()))
      return false;
    return all_of(make_second_range(NarrowedLeafShifts),
                  [](const NarrowedLeafInfo &L) { return L.Disjoint; });
  }

  /// Creates reduction operation with the current opcode with the IR flags
  /// from \p ReductionOps, dropping nuw/nsw flags, and disjoint flag if \p
  /// KeepDisjoint is false.
  static Value *createOpWithFlags(IRBuilderBase &Builder, RecurKind RdxKind,
                                  Value *LHS, Value *RHS, const Twine &Name,
                                  const ReductionOpsListType &ReductionOps,
                                  bool KeepDisjoint) {
    bool UseSelect = ReductionOps.size() == 2 ||
                     // Logical or/and.
                     (ReductionOps.size() == 1 &&
                      any_of(ReductionOps.front(), IsaPred<SelectInst>));
    assert((!UseSelect || ReductionOps.size() != 2 ||
            isa<SelectInst>(ReductionOps[1][0])) &&
           "Expected cmp + select pairs for reduction");
    Value *Op = createOp(Builder, RdxKind, LHS, RHS, Name, UseSelect);
    if (RecurrenceDescriptor::isIntMinMaxRecurrenceKind(RdxKind)) {
      if (auto *Sel = dyn_cast<SelectInst>(Op)) {
        propagateIRFlags(Sel->getCondition(), ReductionOps[0], nullptr,
                         /*IncludeWrapFlags=*/false);
        propagateIRFlags(Op, ReductionOps[1], nullptr,
                         /*IncludeWrapFlags=*/false);
        return Op;
      }
    }
    propagateIRFlags(Op, ReductionOps[0], nullptr, /*IncludeWrapFlags=*/false);
    if (!KeepDisjoint && match(Op, m_DisjointOr(m_Value(), m_Value())))
      cast<PossiblyDisjointInst>(Op)->setIsDisjoint(false);
    return Op;
  }

  /// Creates reduction operation with the current opcode with the IR flags
  /// from \p ReductionOps, dropping nuw/nsw flags.
  Value *createOp(IRBuilderBase &Builder, RecurKind Kind, Value *LHS,
                  Value *RHS, const Twine &Name,
                  const ReductionOpsListType &ReductionOps) const {
    return createOpWithFlags(Builder, Kind, LHS, RHS, Name, ReductionOps,
                             keepDisjoint());
  }

public:
  /// \returns true if \p V has an opcode that could form an ordered reduction.
  static bool isSupportedOrderedReductionOp(Instruction *I) {
    return I->getOpcode() == Instruction::FAdd;
  }

  static RecurKind getRdxKind(Value *V) {
    auto *I = dyn_cast<Instruction>(V);
    if (!I)
      return RecurKind::None;
    if (match(I, m_Add(m_Value(), m_Value())))
      return RecurKind::Add;
    if (match(I, m_Mul(m_Value(), m_Value())))
      return RecurKind::Mul;
    if (match(I, m_And(m_Value(), m_Value())) ||
        match(I, m_LogicalAnd(m_Value(), m_Value())))
      return RecurKind::And;
    if (match(I, m_Or(m_Value(), m_Value())) ||
        match(I, m_LogicalOr(m_Value(), m_Value())))
      return RecurKind::Or;
    if (match(I, m_Xor(m_Value(), m_Value())))
      return RecurKind::Xor;
    if (match(I, m_FAdd(m_Value(), m_Value())))
      return RecurKind::FAdd;
    if (match(I, m_FMul(m_Value(), m_Value())))
      return RecurKind::FMul;

    if (match(I, m_Intrinsic<Intrinsic::maxnum>(m_Value(), m_Value())))
      return RecurKind::FMax;
    if (match(I, m_Intrinsic<Intrinsic::minnum>(m_Value(), m_Value())))
      return RecurKind::FMin;

    if (match(I, m_FMaximum(m_Value(), m_Value())))
      return RecurKind::FMaximum;
    if (match(I, m_FMinimum(m_Value(), m_Value())))
      return RecurKind::FMinimum;
    // TODO: remove several special-case paths that deal with selects.
    if (match(I, m_SMax(m_Value(), m_Value())))
      return RecurKind::SMax;
    if (match(I, m_SMin(m_Value(), m_Value())))
      return RecurKind::SMin;
    if (match(I, m_UMax(m_Value(), m_Value())))
      return RecurKind::UMax;
    if (match(I, m_UMin(m_Value(), m_Value())))
      return RecurKind::UMin;

    if (auto *Select = dyn_cast<SelectInst>(I)) {
      // Try harder: look for min/max pattern based on instructions producing
      // same values such as: select ((cmp Inst1, Inst2), Inst1, Inst2).
      // During the intermediate stages of SLP, it's very common to have
      // pattern like this (since optimizeGatherSequence is run only once
      // at the end):
      // %1 = extractelement <2 x i32> %a, i32 0
      // %2 = extractelement <2 x i32> %a, i32 1
      // %cond = icmp sgt i32 %1, %2
      // %3 = extractelement <2 x i32> %a, i32 0
      // %4 = extractelement <2 x i32> %a, i32 1
      // %select = select i1 %cond, i32 %3, i32 %4
      CmpPredicate Pred;
      Instruction *L1;
      Instruction *L2;

      Value *LHS = Select->getTrueValue();
      Value *RHS = Select->getFalseValue();
      Value *Cond = Select->getCondition();

      // TODO: Support inverse predicates.
      if (match(Cond, m_Cmp(Pred, m_Specific(LHS), m_Instruction(L2)))) {
        if (!isa<ExtractElementInst>(RHS) ||
            !L2->isIdenticalTo(cast<Instruction>(RHS)))
          return RecurKind::None;
      } else if (match(Cond, m_Cmp(Pred, m_Instruction(L1), m_Specific(RHS)))) {
        if (!isa<ExtractElementInst>(LHS) ||
            !L1->isIdenticalTo(cast<Instruction>(LHS)))
          return RecurKind::None;
      } else {
        if (!isa<ExtractElementInst>(LHS) || !isa<ExtractElementInst>(RHS))
          return RecurKind::None;
        if (!match(Cond, m_Cmp(Pred, m_Instruction(L1), m_Instruction(L2))) ||
            !L1->isIdenticalTo(cast<Instruction>(LHS)) ||
            !L2->isIdenticalTo(cast<Instruction>(RHS)))
          return RecurKind::None;
      }

      switch (Pred) {
      default:
        return RecurKind::None;
      case CmpInst::ICMP_SGT:
      case CmpInst::ICMP_SGE:
        return RecurKind::SMax;
      case CmpInst::ICMP_SLT:
      case CmpInst::ICMP_SLE:
        return RecurKind::SMin;
      case CmpInst::ICMP_UGT:
      case CmpInst::ICMP_UGE:
        return RecurKind::UMax;
      case CmpInst::ICMP_ULT:
      case CmpInst::ICMP_ULE:
        return RecurKind::UMin;
      }
    }
    return RecurKind::None;
  }

  /// Get the index of the first operand.
  static unsigned getFirstOperandIndex(Instruction *I) {
    return isCmpSelMinMax(I) ? 1 : 0;
  }

private:
  /// Total number of operands in the reduction operation.
  static unsigned getNumberOfOperands(Instruction *I) {
    return isCmpSelMinMax(I) ? 3 : (I->isUnaryOp() ? 1 : 2);
  }

  /// Expected number of uses for reduction operations/reduced values.
  static bool hasRequiredNumberOfUses(bool IsCmpSelMinMax, Instruction *I) {
    if (IsCmpSelMinMax) {
      // SelectInst must be used twice while the condition op must have single
      // use only.
      if (auto *Sel = dyn_cast<SelectInst>(I))
        return Sel->hasNUses(2) && Sel->getCondition()->hasOneUse();
      return I->hasNUses(2);
    }

    // Arithmetic reduction operation must be used once only.
    return I->hasOneUse();
  }

  /// Initializes the list of reduction operations.
  void initReductionOps(Instruction *I) {
    if (isCmpSelMinMax(I))
      ReductionOps.assign(2, ReductionOpsType());
    else
      ReductionOps.assign(1, ReductionOpsType());
  }

  /// Add all reduction operations for the reduction instruction \p I.
  void addReductionOps(Instruction *I) {
    if (isCmpSelMinMax(I)) {
      ReductionOps[0].emplace_back(cast<SelectInst>(I)->getCondition());
      ReductionOps[1].emplace_back(I);
    } else {
      ReductionOps[0].emplace_back(I);
    }
  }

  static bool isGoodForReduction(ArrayRef<Value *> Data) {
    int Sz = Data.size();
    auto *I = dyn_cast<Instruction>(Data.front());
    return Sz > 1 || isConstant(Data.front()) ||
           (I && !isa<LoadInst>(I) && isValidForAlternation(I->getOpcode()));
  }

  /// Optimizes original placement of the reduced values for the reduction tree.
  /// For example, if there is a zext i1 + selects, we can merge select
  /// into zext and improve emission of the reductions.
  void optimizeReducedVals(BoUpSLP &R, DominatorTree &DT, const DataLayout &DL,
                           const TargetTransformInfo &TTI,
                           const TargetLibraryInfo &TLI) {
    SmallDenseMap<unsigned, unsigned> UsedReductionOpIds;
    for (const auto [Idx, Vals] : enumerate(ReducedVals)) {
      if (auto *I = dyn_cast<Instruction>(Vals.front()))
        UsedReductionOpIds.try_emplace(I->getOpcode(), Idx);
    }
    // Check if zext i1 can be merged with select.
    auto ZExtIt = UsedReductionOpIds.find(Instruction::ZExt);
    auto SelectIt = UsedReductionOpIds.find(Instruction::Select);
    if (ZExtIt != UsedReductionOpIds.end() &&
        SelectIt != UsedReductionOpIds.end()) {
      unsigned ZExtIdx = ZExtIt->second;
      unsigned SelectIdx = SelectIt->second;
      auto *ZExt = cast<ZExtInst>(ReducedVals[ZExtIdx].front());
      // ZExt is compatible with Select? Merge select to zext, if so.
      if (ZExt->getSrcTy()->isIntegerTy(1) &&
          ZExt->getType() == ReducedVals[SelectIdx].front()->getType()) {
        ReducedVals[ZExtIdx].append(ReducedVals[SelectIdx]);
        ReducedVals.erase(std::next(ReducedVals.begin(), SelectIdx));
      }
    }
    // Merge 1 element reduced value groups into larger group of shl, if only 2
    // groups available. May trigger extra vectorization with the copyables.
    if (ReducedVals.size() == 2 &&
        (ReducedVals.front().size() == 1 || ReducedVals.back().size() == 1)) {
      SmallVector<Value *> Ops(ReducedVals.front().size() +
                               ReducedVals.back().size());
      copy(ReducedVals.front(), Ops.begin());
      copy(ReducedVals.back(),
           std::next(Ops.begin(), ReducedVals.front().size()));
      InstructionsCompatibilityAnalysis Analysis(DT, DL, TTI, TLI);
      InstructionsState OpS = Analysis.buildInstructionsState(
          Ops, R, /*TryCopyableElementsVectorization=*/true,
          /*WithProfitabilityCheck=*/true);
      if (OpS && OpS.areInstructionsWithCopyableElements() &&
          OpS.getOpcode() == Instruction::Shl) {
        // The smallest reduced values group should be the first.
        if (ReducedVals.back().size() == 1 && ReducedVals.front().size() != 1)
          std::swap(ReducedVals.front(), ReducedVals.back());
        // Check if the largest reduced values group are shl and sort them by
        // the constant shift amount to improve chances of vectorization with
        // the copyables.
        auto Comparator = [](Value *V1, Value *V2) {
          ConstantInt *C1, *C2;
          if (!match(V1, m_Shl(m_Value(), m_ConstantInt(C1))))
            return false;
          if (!match(V2, m_Shl(m_Value(), m_ConstantInt(C2))))
            return true;
          return C1->getZExtValue() < C2->getZExtValue();
        };
        stable_sort(ReducedVals.back(), Comparator);
        ReducedVals.front().append(ReducedVals.back());
        ReducedVals.pop_back();
      }
    }
  }

public:
  explicit HorizontalReduction(const VectorizeOptions &Opts) : Opts(Opts) {}
  HorizontalReduction(const VectorizeOptions &Opts, Instruction *I,
                      ArrayRef<Value *> Ops)
      : Opts(Opts), ReductionRoot(I), ReductionLimit(2) {
    RdxKind = HorizontalReduction::getRdxKind(I);
    ReductionOps.emplace_back().push_back(I);
    ReducedVals.emplace_back().assign(Ops.begin(), Ops.end());
    for (Value *V : Ops)
      ReducedValsToOps[V].push_back(I);
  }

  /// Returns true if the matched reduction chain has flattened fsub/fneg
  /// links (the leaves behind them may all be positive, e.g. with double
  /// negations).
  bool hasFlattenedNegations() const {
    return any_of(ReductionOps, [](ArrayRef<Value *> Ops) {
      return any_of(Ops, [](Value *Op) {
        return Op && isFlattenableNegation(cast<Instruction>(Op));
      });
    });
  }

  bool matchReductionForOperands() {
    // Analyze "regular" integer/FP types for reductions - no target-specific
    // types or pointers.
    assert(ReductionRoot && "Reduction root is not set!");
    RK = isVectorizable(RdxKind, cast<Instruction>(ReductionRoot),
                        all_of(ReducedVals, [](ArrayRef<Value *> Ops) {
                          return Ops.size() == 2;
                        }));
    return RK != ReductionOrdering::None;
  }

  /// Analyze whether \p Root forms a linearized ordered reduction chain.
  /// If \p MatchLHS is true, analyzes LHS-associated (left-linearized) chains
  /// where the chain recurses on the LHS and the RHS at each level is a leaf:
  ///   ((((v0 op v1) op v2) op v3) op v4)
  /// If \p MatchLHS is false, analyzes RHS-associated (right-linearized) chains
  /// where the chain recurses on the RHS and the LHS at each level is a leaf:
  ///   (v0 op (v1 op (v2 op (v3 op v4))))
  /// Leaf values are stored in ReducedVals.back() in accumulation order
  /// (innermost pair first, outermost last), e.g. [v0,v1,v2,v3,v4] for
  /// LHS-associated and [v4,v3,v2,v1,v0] for RHS-associated chains.
  /// \returns true if the chain is a valid ordered reduction.
  bool matchOrderedReduction(BoUpSLP &R, Instruction *Root, bool MatchLHS) {
    ReducedVals.clear();
    ReducedValsToOps.clear();
    ReductionOps.clear();
    RoundedLinks.clear();
    NarrowedLeafShifts.clear();
    NarrowedChainInsts.clear();
    NegatedReducedVals.clear();
    RdxKind = getRdxKind(Root);
    // Currently, only ordered fadd reductions are supported.
    if (RdxKind != RecurKind::FAdd)
      return false;
    // Reassociable chains with non-elidable cast round-trip links are
    // handled here as well: the emission keeps the original order.
    if (isVectorizable(RdxKind, Root) == ReductionOrdering::None)
      return false;

    // Ordered reductions only support simple binary ops, not min/max
    // select(cmp) patterns or poison-safe bool logic ops.
    if (isCmpSelMinMax(Root) || isBoolLogicOp(Root))
      return false;

    Type *Ty = Root->getType();
    if (!isValidElementType(Ty, Opts.slp_revec) || Ty->isPointerTy())
      return false;

    // This is an ordered (linearized) reduction regardless of whether the
    // individual operations are associative.
    RK = ReductionOrdering::Ordered;
    ReductionRoot = Root;
    BasicBlock *BB = Root->getParent();
    unsigned FirstOpIdx = getFirstOperandIndex(Root);
    unsigned ChainOpIdx = MatchLHS ? FirstOpIdx : FirstOpIdx + 1;
    unsigned LeafOpIdx = MatchLHS ? FirstOpIdx + 1 : FirstOpIdx;
    initReductionOps(Root);
    ReducedVals.emplace_back();
    SmallPtrSet<Instruction *, 16> Visited;
    Instruction *TreeN = Root;
    unsigned Depth = 0;
    bool ChainComplete = false;
    constexpr unsigned MaxReducedVals = 1024;
    Instruction *PendingCast = nullptr;
    while (TreeN) {
      if (Depth++ > Opts.slp_recursion_max_depth)
        break;
      if (ReducedVals.back().size() >= MaxReducedVals)
        break;
      if (!Visited.insert(TreeN).second)
        break;
      if (getRdxKind(TreeN) != RdxKind)
        break;
      if (TreeN->getParent() != BB)
        break;
      addReductionOps(TreeN);
      Value *LeafVal = getRdxOperand(TreeN, LeafOpIdx);
      Value *ChainVal = getRdxOperand(TreeN, ChainOpIdx);
      ReducedValsToOps[LeafVal].push_back(TreeN);
      ReducedValsToOps[ChainVal].push_back(TreeN);
      ReducedVals.back().push_back(LeafVal);
      RoundedLinks.push_back(PendingCast);
      PendingCast = nullptr;
      auto *ChainInst = dyn_cast<Instruction>(ChainVal);
      // The link may round the accumulator to a narrower type and extend it
      // back; look through the cast pair, the rounding is re-emitted later.
      if (ChainInst && getRdxKind(ChainInst) != RdxKind) {
        if (Instruction *NarrowCast =
                lookThroughCastRoundTrip(ChainVal, /*MustBeElidable=*/false)) {
          auto *I = cast<Instruction>(NarrowCast->getOperand(0));
          if (getRdxKind(I) == RdxKind &&
              hasRequiredNumberOfUses(/*IsCmpSelMinMax=*/false, I)) {
            ReductionOps[0].push_back(ChainVal);
            ReductionOps[0].push_back(NarrowCast);
            PendingCast = NarrowCast;
            ChainInst = I;
          }
        }
      }
      if (!ChainInst || getRdxKind(ChainInst) != RdxKind ||
          !hasRequiredNumberOfUses(/*IsCmpSelMinMax=*/false, ChainInst)) {
        ReducedVals.back().push_back(ChainVal);
        RoundedLinks.push_back(nullptr);
        ChainComplete = true;
        break;
      }
      TreeN = ChainInst;
    }
    // Leaves are collected outer-to-inner (top-down).  Reverse to get the
    // accumulation order (innermost first) needed by ordered reduction
    // intrinsics.  This is correct for both LHS- and RHS-associated chains
    // because fadd is commutative — each step only relies on a+b == b+a,
    // never on associativity.
    if (!ChainComplete || ReducedVals.back().size() < ReductionLimit) {
      for (ReductionOpsType &RdxOps : ReductionOps)
        for (Value *RdxOp : RdxOps)
          R.analyzedReductionRoot(cast<Instruction>(RdxOp));
      ReducedVals.pop_back();
      ReducedValsToOps.clear();
      ReductionOps.clear();
      RoundedLinks.clear();
      return false;
    }
    std::reverse(ReducedVals.back().begin(), ReducedVals.back().end());
    return true;
  }

  /// Checks if \p I is an fsub/fneg, which can be flattened into an fadd
  /// reduction chain with a flipped sign of its subtracted operand. nsz is
  /// required: subtracted leaves are regrouped and negated as a whole, and
  /// -a + -b == -(a + b) may flip the sign of a zero result.
  static bool isFlattenableNegation(Instruction *I) {
    return (I->getOpcode() == Instruction::FSub ||
            I->getOpcode() == Instruction::FNeg) &&
           I->hasAllowReassoc() && I->hasNoSignedZeros();
  }

  /// A group of loads or non-instructions rarely amortizes on its own the
  /// cost of the reduction operation, charged to the first vectorized group.
  static bool isCheapReductionGroup(ArrayRef<Value *> P) {
    return !isa<Instruction>(P.front()) || isa<LoadInst>(P.front());
  }

  /// Try to find a reduction tree. If \p FlattenNegations is false, the
  /// reassociable fsub/fneg links of an fadd chain are not flattened (they are
  /// leaves of the reduction).
  bool matchAssociativeReduction(BoUpSLP &R, Instruction *Root,
                                 ScalarEvolution &SE, DominatorTree &DT,
                                 const DataLayout &DL,
                                 const TargetTransformInfo &TTI,
                                 const TargetLibraryInfo &TLI,
                                 bool FlattenNegations = true) {
    RdxKind = HorizontalReduction::getRdxKind(Root);
    // A reassociable fsub root is a flattened link of an fadd reduction: its
    // subtracted operand enters with a flipped sign. Without the flattening
    // there is no reduction to match. (An fneg is not a reduction candidate.)
    const bool IsNegatedRoot = RdxKind == RecurKind::None &&
                               Root->getOpcode() == Instruction::FSub &&
                               isFlattenableNegation(Root);
    if (IsNegatedRoot)
      RdxKind = RecurKind::FAdd;
    RK = isVectorizable(RdxKind, Root);
    if (RK == ReductionOrdering::None)
      return false;

    // Analyze "regular" integer/FP types for reductions - no target-specific
    // types or pointers.
    Type *Ty = Root->getType();
    if (!isValidElementType(Ty, Opts.slp_revec) || Ty->isPointerTy())
      return false;

    // Though the ultimate reduction may have multiple uses, its condition must
    // have only single use.
    if (auto *Sel = dyn_cast<SelectInst>(Root))
      if (!Sel->getCondition()->hasOneUse())
        RK = ReductionOrdering::Ordered;

    ReductionRoot = Root;

    // Iterate through all the operands of the possible reduction tree and
    // gather all the reduced values, sorting them by their value id.
    BasicBlock *BB = Root->getParent();
    bool IsCmpSelMinMax = isCmpSelMinMax(Root);
    const ReductionOrdering InitialRK = RK;
    // For unordered fadd reductions, reassociable fsub/fneg chain links are
    // flattened with a flipped sign on the subtracted operand: the leaves,
    // reduced through such links, are subtracted in the final combine.
    // Ordered reductions keep their accumulation order and are excluded.
    bool TrackSign = FlattenNegations && RdxKind == RecurKind::FAdd &&
                     RK == ReductionOrdering::Unordered;
    // The leaf signs are modeled per value. If they cannot be modeled this way
    // (the same value occurs both added and subtracted, or the reduction
    // switches to ordered after some fsub/fneg links have been flattened
    // already), the analysis restarts without the fsub/fneg flattening.
    bool Restart = false;
    do {
      if (Restart) {
        assert(TrackSign && "Expected a sign-tracking analysis to restart");
        TrackSign = false;
      }
      // The root itself is a flattened link - there is no reduction without
      // the flattening.
      if (IsNegatedRoot && !TrackSign)
        return false;
      Restart = false;
      RK = InitialRK;
      ReducedVals.clear();
      ReducedValsToOps.clear();
      NegatedReducedVals.clear();
      bool FlattenedNegations = false;
      initReductionOps(Root);
      DenseMap<std::pair<size_t, Value *>, SmallVector<LoadInst *>> LoadsMap;
      SmallSet<size_t, 2> LoadKeyUsed;
      auto GenerateLoadsSubkey = [&](size_t Key, LoadInst *LI) {
        Key = hash_combine(hash_value(LI->getParent()->getNumber()), Key);
        Value *Ptr = getUnderlyingObject(LI->getPointerOperand(),
                                         Opts.slp_recursion_max_depth);
        if (!LoadKeyUsed.insert(Key).second) {
          auto LIt = LoadsMap.find(std::make_pair(Key, Ptr));
          if (LIt != LoadsMap.end()) {
            for (LoadInst *RLI : LIt->second) {
              if (getPointersDiff(RLI->getType(), RLI->getPointerOperand(),
                                  LI->getType(), LI->getPointerOperand(), DL,
                                  SE, /*StrictCheck=*/true))
                return hash_value(RLI->getPointerOperand());
            }
            for (LoadInst *RLI : LIt->second) {
              if (arePointersCompatible(RLI->getPointerOperand(),
                                        LI->getPointerOperand(), TLI,
                                        Opts.slp_recursion_max_depth)) {
                hash_code SubKey = hash_value(RLI->getPointerOperand());
                return SubKey;
              }
            }
            if (LIt->second.size() > 2) {
              hash_code SubKey =
                  hash_value(LIt->second.back()->getPointerOperand());
              return SubKey;
            }
          }
        }
        LoadsMap.try_emplace(std::make_pair(Key, Ptr))
            .first->second.push_back(LI);
        return hash_value(LI->getPointerOperand());
      };
      SmallVector<Value *> ReducedValsCandidates;
      bool AdjustedToOrdered = false;
      // True if the chain has an opaque fsub/fneg leaf (not reassociable, extra
      // uses, too deep).
      bool HasOpaqueNegationLeaf = false;
      SmallVector<std::tuple<Instruction *, unsigned, bool>> Worklist(
          1, std::make_tuple(Root, 0, /*Negated=*/false));
      SmallPtrSet<Value *, 8> Operands;
      SmallVector<std::pair<Instruction *, unsigned>>
          PossibleOrderedReductionOps;
      // Leaves that (also) occur with a non-flipped sign.
      SmallPtrSet<Value *, 8> PositiveReducedVals;
      // Checks if the instruction continues the reduction chain. An fsub/fneg
      // chain link in an fadd reduction is recursed into like an fadd, but its
      // subtracted operand enters with a flipped sign. Only reassociable links
      // qualify.
      auto IsChainLink = [&](Instruction *I) {
        if (getRdxKind(I) == RdxKind)
          return true;
        return TrackSign && isFlattenableNegation(I);
      };
      // Checks if the operands of the \p TreeN instruction are also reduction
      // operations or should be treated as reduced values or an extra
      // argument, which is not part of the reduction.
      auto CheckOperands =
          [&](Instruction *TreeN, SmallVectorImpl<Value *> &PossibleReducedVals,
              SmallVectorImpl<std::pair<Instruction *, bool>> &ReductionOps,
              ReductionOpsType &AllReductionOps, unsigned Level, bool Negated) {
            for (int I : reverse(seq<int>(getFirstOperandIndex(TreeN),
                                          getNumberOfOperands(TreeN)))) {
              Value *EdgeVal = getRdxOperand(TreeN, I);
              auto *EdgeInst = dyn_cast<Instruction>(EdgeVal);
              // The link may be an elidable cast round-trip; look through it to
              // continue the chain. It is dropped when the reduction is folded.
              if (EdgeInst && getRdxKind(EdgeInst) != RdxKind) {
                if (Instruction *NarrowCast = lookThroughCastRoundTrip(
                        EdgeVal, /*MustBeElidable=*/true)) {
                  auto *SrcI = cast<Instruction>(NarrowCast->getOperand(0));
                  if (getRdxKind(SrcI) == RdxKind &&
                      hasRequiredNumberOfUses(IsCmpSelMinMax, SrcI)) {
                    AllReductionOps.push_back(EdgeVal);
                    AllReductionOps.push_back(NarrowCast);
                    EdgeVal = SrcI;
                    EdgeInst = SrcI;
                  }
                }
              }
              ReducedValsToOps[EdgeVal].push_back(TreeN);
              // fsub flips its second operand's sign, fneg its only
              // operand's.
              bool EdgeNegated =
                  Negated !=
                  (TreeN->getOpcode() == Instruction::FNeg ||
                   (TreeN->getOpcode() == Instruction::FSub && I == 1));
              // If the edge is not an instruction, or it is different from
              // the main reduction opcode or has too many uses - possible
              // reduced value. Also, do not try to reduce const values, if
              // the operation is not foldable.
              bool IsReducedVal = !EdgeInst ||
                                  Level > Opts.slp_recursion_max_depth ||
                                  !IsChainLink(EdgeInst) ||
                                  IsCmpSelMinMax != isCmpSelMinMax(EdgeInst);
              ReductionOrdering CurrentRK =
                  IsReducedVal ? ReductionOrdering::None
                               : isVectorizable(RdxKind, EdgeInst);
              if (!IsReducedVal && CurrentRK == ReductionOrdering::Unordered &&
                  RK == ReductionOrdering::Unordered &&
                  !hasRequiredNumberOfUses(IsCmpSelMinMax, EdgeInst)) {
                IsReducedVal = true;
                CurrentRK = ReductionOrdering::None;
                if (PossibleReducedVals.size() < ReductionLimit &&
                    !Operands.contains(EdgeInst))
                  PossibleOrderedReductionOps.emplace_back(EdgeInst, Level);
              }
              if (CurrentRK == ReductionOrdering::None ||
                  Operands.contains(EdgeInst) ||
                  (R.isAnalyzedReductionRoot(EdgeInst) &&
                   all_of(EdgeInst->operands(), IsaPred<Constant>))) {
                // Keep the sign of the leaf. A leaf, occurring with both
                // signs, cannot be modeled with a per-value sign - restart
                // without sign tracking.
                if (TrackSign) {
                  auto &Same =
                      EdgeNegated ? NegatedReducedVals : PositiveReducedVals;
                  auto &Other =
                      EdgeNegated ? PositiveReducedVals : NegatedReducedVals;
                  Same.insert(EdgeVal);
                  Restart |= Other.contains(EdgeVal);
                  HasOpaqueNegationLeaf |=
                      EdgeInst && (EdgeInst->getOpcode() == Instruction::FSub ||
                                   EdgeInst->getOpcode() == Instruction::FNeg);
                }
                PossibleReducedVals.push_back(EdgeVal);
                if (EdgeInst && !isCmpSelMinMax(EdgeInst))
                  Operands.insert_range(EdgeInst->operands());
                continue;
              }
              if (CurrentRK == ReductionOrdering::Ordered)
                RK = ReductionOrdering::Ordered;
              ReductionOps.emplace_back(EdgeInst, EdgeNegated);
            }
          };
      SmallPtrSet<Instruction *, 16> Visited;
      while (!Worklist.empty()) {
        auto [TreeN, Level, Negated] = Worklist.pop_back_val();
        if (!Visited.insert(TreeN).second)
          continue;
        // A chain link other than the reduction operation is a flattened
        // fsub/fneg.
        if (getRdxKind(TreeN) != RdxKind)
          FlattenedNegations = true;
        SmallVector<Value *> PossibleRedVals;
        SmallVector<std::pair<Instruction *, bool>> PossibleReductionOps;
        CheckOperands(TreeN, PossibleRedVals, PossibleReductionOps,
                      ReductionOps[0], Level, Negated);
        // A leaf occurred with both signs - stop, the analysis restarts
        // without the fsub/fneg flattening.
        if (Restart)
          break;
        addReductionOps(TreeN);
        ReducedValsCandidates.append(PossibleRedVals.begin(),
                                     PossibleRedVals.end());
        for (auto [I, OpNegated] : reverse(PossibleReductionOps))
          Worklist.emplace_back(I, I->getParent() == BB ? 0 : Level + 1,
                                OpNegated);
        // If not enough elements for unordered vectorization, check if there
        // are potential candidates for the ordered vectorization and try to
        // add them to the worklist.
        if (Worklist.empty() && ReducedValsCandidates.size() < ReductionLimit &&
            !PossibleOrderedReductionOps.empty() &&
            RK == ReductionOrdering::Unordered) {
          RK = ReductionOrdering::Ordered;
          AdjustedToOrdered = true;
          SmallPtrSet<const Instruction *, 4> Ops;
          // The ordered switch discards the tracked signs (the analysis
          // restarts without the fsub/fneg flattening, if any occurred), so
          // the candidates re-enter the walk with the non-flipped sign.
          for (const auto &[I, Level] : PossibleOrderedReductionOps) {
            Ops.insert(I);
            Worklist.emplace_back(I, Level, /*Negated=*/false);
          }
          erase_if(ReducedValsCandidates, [&](Value *V) {
            auto *I = dyn_cast<Instruction>(V);
            return I && Ops.contains(I);
          });
          PossibleOrderedReductionOps.clear();
        }
      }
      // The flattening reassociates the chain, which the ordered reduction
      // must not do, and negating the regrouped subtracted leaves as a whole
      // is not sign-of-zero-safe unless the whole flattened chain is nsz (this
      // conservatively includes the elidable cast round-trips, collected into
      // the reduction operations) - restart without the fsub/fneg flattening,
      // if any occurred. Also, an opaque fsub/fneg leaf forms a homogeneous
      // group with the flattened links when not flattened, which the
      // sign-uniform regrouping of their operands may only fragment - keep the
      // unflattened form.
      if (FlattenedNegations &&
          (RK == ReductionOrdering::Ordered || HasOpaqueNegationLeaf ||
           (!NegatedReducedVals.empty() &&
            any_of(ReductionOps.front(), [](Value *Op) {
              return !cast<Instruction>(Op)->hasNoSignedZeros();
            }))))
        Restart = true;
      if (Restart)
        continue;
      // InstCombine may pack same-kind binops under a zext, hiding the
      // leaves. Analyze them in the narrow type; the vectorized result is
      // widened back, shifted and masked per lane before the reduction.
      if (Instruction::isBitwiseLogicOp(
              RecurrenceDescriptor::getOpcode(RdxKind)) &&
          RK == ReductionOrdering::Unordered && !IsCmpSelMinMax &&
          Ty->isIntegerTy() && !Ty->isIntegerTy(1) &&
          any_of(ReducedValsCandidates, [](Value *V) {
            return isa<ZExtInst>(V) ||
                   match(V, m_Shl(m_ZExt(m_Value()), m_ConstantInt()));
          })) {
        unsigned WideBW = Ty->getIntegerBitWidth();
        SmallVector<SmallVector<NarrowedLeafInfo>> AllLeaves;
        SmallVector<Instruction *> ChainInsts;
        Type *NarrowTy = nullptr;
        bool Bail = false;
        unsigned NumLeaves = 0;
        SmallPtrSet<Value *, 8> UniqueLeaves;
        for (Value *Cand : ReducedValsCandidates) {
          SmallVector<NarrowedLeafInfo> &Leaves = AllLeaves.emplace_back();
          collectNarrowedLeaves(Cand, RecurrenceDescriptor::getOpcode(RdxKind),
                                WideBW, Opts.slp_recursion_max_depth, Leaves,
                                ChainInsts);
          for (const NarrowedLeafInfo &L : Leaves) {
            if (isa<Constant>(L.V) || !L.V->getType()->isIntegerTy() ||
                (NarrowTy && L.V->getType() != NarrowTy) ||
                !UniqueLeaves.insert(L.V).second) {
              Bail = true;
              break;
            }
            if (!NarrowTy)
              NarrowTy = L.V->getType();
          }
          if (Bail)
            break;
          NumLeaves += Leaves.size();
        }
        if (!Bail && NumLeaves > ReducedValsCandidates.size() &&
            NarrowTy != Ty) {
          // Collected user-first; dies with the reduction iff all users die.
          SmallPtrSet<Value *, 8> Ignorable;
          for (ArrayRef<Value *> RdxOps : ReductionOps)
            Ignorable.insert_range(RdxOps);
          for (Instruction *I : ChainInsts)
            if (all_of(I->users(),
                       [&](User *U) { return Ignorable.contains(U); })) {
              Ignorable.insert(I);
              NarrowedChainInsts.push_back(I);
            }
          const bool AllDisjoint =
              all_of(make_isa_range<PossiblyDisjointInst>(ChainInsts),
                     [](PossiblyDisjointInst *I) { return I->isDisjoint(); });
          SmallVector<Value *> NewCandidates;
          for (const auto &[Cand, Leaves] :
               zip(ReducedValsCandidates, AllLeaves)) {
            SmallVector<Instruction *> RdxOps = ReducedValsToOps.lookup(Cand);
            for (NarrowedLeafInfo &L : Leaves) {
              L.Disjoint = AllDisjoint;
              NarrowedLeafShifts.try_emplace(L.V, L);
              NewCandidates.push_back(L.V);
              ReducedValsToOps[L.V].append(RdxOps);
            }
          }
          ReducedValsCandidates = std::move(NewCandidates);
        }
      }
      // Cap on the number of reduced values, including booleanized leaves.
      constexpr unsigned ReducedValsLimit = 1024;
      // Logical and/or reductions on i1 may have booleanized wide leaves:
      // truncs of same-op chains or zero-tests of values from [0, 1].
      // Reducing in the wide type and taking bit 0 of the result is
      // equivalent, since trunc of a bitwise and/or is the bitwise and/or of
      // the truncs, and it exposes the underlying (usually consecutive) wide
      // values to the tree. All final leaves must be non-poison: the logical
      // select/and/or ops may mask poison, which the wide reduction would
      // propagate instead.
      if ((RdxKind == RecurKind::And || RdxKind == RecurKind::Or) &&
          RK == ReductionOrdering::Unordered && !IsCmpSelMinMax &&
          Ty->isIntegerTy(1) && any_of(ReducedValsCandidates, [](Value *V) {
            return isa<TruncInst, ICmpInst>(V);
          })) {
        unsigned RdxOpcode = RecurrenceDescriptor::getOpcode(RdxKind);
        auto BooleanizeLeaves = [&]() {
          Type *WideTy = nullptr;
          SmallVector<Value *> NewCandidates;
          SmallVector<Instruction *> ChainInsts;
          for (Value *Cand : ReducedValsCandidates) {
            SmallVector<Instruction *> RdxOps = ReducedValsToOps.lookup(Cand);
            SmallVector<Value *> Worklist(1, Cand);
            while (!Worklist.empty()) {
              Value *V = Worklist.pop_back_val();
              if (V->getType()->isIntegerTy(1)) {
                Value *X;
                // trunc iN to i1: bit 0 of the wide value.
                if (match(V, m_OneUse(m_Trunc(m_Value(X))))) {
                  ChainInsts.push_back(cast<Instruction>(V));
                  Worklist.push_back(X);
                  continue;
                }
                // Zero-test of a value from [0, 1]: same as bit 0 of the
                // value.
                CmpPredicate Pred;
                if (match(V, m_OneUse(m_c_ICmp(Pred, m_Value(X), m_Zero()))) &&
                    Pred == ICmpInst::ICMP_NE && X->getType()->isIntegerTy() &&
                    computeKnownBits(X, DL).getMaxValue() == 1) {
                  ChainInsts.push_back(cast<Instruction>(V));
                  Worklist.push_back(X);
                  continue;
                }
                return;
              }
              if (!V->getType()->isIntegerTy())
                return;
              // Same-op chain node: bit 0 of a bitwise and/or is the and/or
              // of the operands' bit 0.
              if (auto *BO = dyn_cast<BinaryOperator>(V);
                  BO && BO->getOpcode() == RdxOpcode && BO->hasOneUse() &&
                  !BO->hasPoisonGeneratingFlags()) {
                ChainInsts.push_back(BO);
                Worklist.push_back(BO->getOperand(1));
                Worklist.push_back(BO->getOperand(0));
                continue;
              }
              if (!isGuaranteedNotToBePoison(V) ||
                  (WideTy && V->getType() != WideTy))
                return;
              if (!WideTy)
                WideTy = V->getType();
              NewCandidates.push_back(V);
              ReducedValsToOps[V].append(RdxOps);
              if (NewCandidates.size() > ReducedValsLimit)
                return;
            }
          }
          if (WideTy) {
            NarrowedChainInsts.append(ChainInsts);
            ReducedValsCandidates = std::move(NewCandidates);
          }
        };
        BooleanizeLeaves();
      }
      // Too many integer reduced values candidates for the ordered
      // reductions after adjustements - try to switch to unordered
      // reductions instead.
      if (ReducedValsCandidates.size() > ReducedValsLimit &&
          AdjustedToOrdered &&
          ReducedValsCandidates.front()->getType()->isIntOrIntVectorTy())
        return false;
      // Try to regroup reduced values so that it gets more profitable to try
      // to reduce them. Values are grouped by their value ids, instructions -
      // by instruction op id and/or alternate op id, plus do extra analysis
      // for loads (grouping them by the distance between pointers) and cmp
      // instructions (grouping them by the predicate).
      SmallMapVector<
          size_t,
          SmallMapVector<size_t, SmallMapVector<Value *, unsigned, 2>, 2>, 8>
          PossibleReducedVals;
      // Add reduction values. The values are sorted for better vectorization
      // results.
      for (Value *V : make_filter_range(ReducedValsCandidates, [&](Value *V) {
             return RK != ReductionOrdering::Ordered || isa<Instruction>(V);
           })) {
        size_t Key, Idx;
        std::tie(Key, Idx) = generateKeySubkey(V, &TLI, GenerateLoadsSubkey,
                                               /*AllowAlternate=*/false);
        // The sign of the contribution is a part of the grouping key: a
        // mixed-sign group cannot be negated as a whole.
        Key = hash_combine(Key, NegatedReducedVals.contains(V));
        ++PossibleReducedVals[Key][Idx].try_emplace(V, 0).first->second;
      }
      auto PossibleReducedValsVect = PossibleReducedVals.takeVector();
      // Sort values by the total number of values kinds to start the
      // reduction from the longest possible reduced values sequences.
      for (auto &PossibleReducedVals : PossibleReducedValsVect) {
        auto PossibleRedVals = PossibleReducedVals.second.takeVector();
        SmallVector<SmallVector<Value *>> PossibleRedValsVect;
        for (auto &Slice : PossibleRedVals) {
          PossibleRedValsVect.emplace_back();
          auto RedValsVect = Slice.second.takeVector();
          stable_sort(RedValsVect, llvm::less_second());
          for (const std::pair<Value *, unsigned> &Data : RedValsVect)
            PossibleRedValsVect.back().append(Data.second, Data.first);
        }
        stable_sort(PossibleRedValsVect, [](const auto &P1, const auto &P2) {
          return P1.size() > P2.size();
        });
        bool First = true;
        for (ArrayRef<Value *> Data : PossibleRedValsVect) {
          if (First) {
            First = false;
            ReducedVals.emplace_back();
          } else if (!isGoodForReduction(Data)) {
            auto *LI = dyn_cast<LoadInst>(Data.front());
            auto *LastLI = dyn_cast<LoadInst>(ReducedVals.back().front());
            if (!LI || !LastLI ||
                getUnderlyingObject(LI->getPointerOperand()) !=
                    getUnderlyingObject(LastLI->getPointerOperand()))
              ReducedVals.emplace_back();
          }
          ReducedVals.back().append(Data.rbegin(), Data.rend());
        }
      }
      // Post optimize reduced values to get better reduction sequences and
      // sort them by size.
      optimizeReducedVals(R, DT, DL, TTI, TLI);
      // Sort the reduced values by number of same/alternate opcode and/or
      // pointer operand. For the sign-aware reductions, same-size groups are
      // ordered by their expected profitability: the first vectorized group
      // is charged the cost of the reduction operation itself, which a group
      // of loads or non-instructions rarely amortizes on its own, while it is
      // a cheap addition (a single vector operation) to an already
      // vectorized group - such groups go last. Among the rest, non-negated
      // groups go first.
      stable_sort(ReducedVals, [&](ArrayRef<Value *> P1, ArrayRef<Value *> P2) {
        if (P1.size() != P2.size())
          return P1.size() > P2.size();
        if (NegatedReducedVals.empty())
          return false;
        bool Cheap1 = isCheapReductionGroup(P1);
        bool Cheap2 = isCheapReductionGroup(P2);
        if (Cheap1 != Cheap2)
          return Cheap2;
        return NegatedReducedVals.contains(P1.front()) <
               NegatedReducedVals.contains(P2.front());
      });
      // A group of subtracted loads, which are not consecutive (a gather):
      // the flattening splits the fsub leaves over them into separate load
      // groups of their operands, which the unflattened form vectorizes as a
      // whole (a vector fsub with shuffled operands).
      auto IsGatheredNegatedLoads = [&](ArrayRef<Value *> Vals) {
        auto *LI0 = dyn_cast<LoadInst>(Vals.front());
        if (!LI0 || Vals.size() < 2 || !NegatedReducedVals.contains(LI0))
          return false;
        SmallVector<int64_t> Diffs;
        for (Value *V : Vals) {
          auto *LI = dyn_cast<LoadInst>(V);
          if (!LI)
            return false;
          std::optional<int64_t> Diff = getPointersDiff(
              LI0->getType(), LI0->getPointerOperand(), LI->getType(),
              LI->getPointerOperand(), DL, SE, /*StrictCheck=*/true);
          if (!Diff)
            return true;
          Diffs.push_back(*Diff);
        }
        sort(Diffs);
        Diffs.erase(llvm::unique(Diffs), Diffs.end());
        return Diffs.back() - Diffs.front() + 1 !=
               static_cast<int64_t>(Diffs.size());
      };
      // The flattening must not make the reduction unviable: the leaves,
      // hidden behind the flattened fsub/fneg operations, may split into
      // too small sign-uniform groups, while the unflattened form may
      // still be vectorizable (e.g. with alternate fadd/fsub opcodes).
      if (FlattenedNegations &&
          (accumulate(ReducedVals, 0u,
                      [](unsigned Num, ArrayRef<Value *> Vals) -> unsigned {
                        if (!isGoodForReduction(Vals))
                          return Num;
                        return Num + Vals.size();
                      }) < ReductionLimit ||
           any_of(ReducedVals, IsGatheredNegatedLoads)))
        Restart = true;
    } while (Restart);
    return true;
  }

  /// Loop accumulator emission mode of the reduction: a reduction that
  /// accumulates a loop phi (the phi is one of the reduced values and the
  /// root is its backedge value) can be emitted as a vector accumulator in
  /// the loop plus a single reduction after the loop instead of a horizontal
  /// reduction on every iteration.
  class LoopAccumulator {
    /// The reduction root and the reduction operation kind and ordering.
    Instruction *Root = nullptr;
    RecurKind RdxKind = RecurKind::None;
    ReductionOrdering RK = ReductionOrdering::None;
    /// The vectorizer state and the analyses the accumulator cost and
    /// emission are computed with.
    BoUpSLP &R;
    const TargetTransformInfo &TTI;
    LoopInfo &LI;
    /// The accumulated phi and the identity constant that replaced it in the
    /// reduced values. The identity is never folded as a leftover: it does
    /// not change the result.
    PHINode *Phi = nullptr;
    Constant *Identity = nullptr;
    /// The number of calls in the loop, across which the vector accumulator
    /// is kept live.
    unsigned NumCalls = 0;
    /// Exit phis consuming the reduction result outside the loop.
    SmallSetVector<PHINode *, 2> ExitPhis;

    /// \returns the identity constant of the reduction operation for \p Ty
    /// under the fast-math flags \p FMF.
    Constant *getIdentity(Type *Ty, FastMathFlags FMF) const {
      Intrinsic::ID Id;
      switch (RdxKind) {
      case RecurKind::FMax:
      case RecurKind::FMaxNum:
        Id = Intrinsic::vector_reduce_fmax;
        break;
      case RecurKind::FMin:
      case RecurKind::FMinNum:
        Id = Intrinsic::vector_reduce_fmin;
        break;
      case RecurKind::FMaximum:
        Id = Intrinsic::vector_reduce_fmaximum;
        break;
      case RecurKind::FMinimum:
        Id = Intrinsic::vector_reduce_fminimum;
        break;
      default:
        Id = RecurrenceDescriptor::isIntMinMaxRecurrenceKind(RdxKind)
                 ? getMinMaxReductionIntrinsicID(
                       getMinMaxReductionIntrinsicOp(RdxKind))
                 : getReductionForBinop(static_cast<Instruction::BinaryOps>(
                       RecurrenceDescriptor::getOpcode(RdxKind)));
        break;
      }
      return cast<Constant>(getReductionIdentity(Id, Ty, FMF));
    }

    /// \returns the extra cost of accumulating the slice lane-wise into the
    /// vector accumulator instead of reducing it on every iteration: the
    /// lane-wise operation, the spill and reload on every iteration of the
    /// values live beyond the register file and keeping the vector
    /// accumulator live across the calls of the loop.
    InstructionCost getAccumulationCost(FastMathFlags FMF, VectorType *VectorTy,
                                        Type *ScalarTy) const {
      const TTI::TargetCostKind CostKind = R.getCostKind();
      auto GetOpCost = [&](Type *OpTy) {
        if (RecurrenceDescriptor::isMinMaxRecurrenceKind(RdxKind)) {
          IntrinsicCostAttributes ICA(getMinMaxReductionIntrinsicOp(RdxKind),
                                      OpTy, {OpTy, OpTy}, FMF);
          return TTI.getIntrinsicInstrCost(ICA, CostKind);
        }
        return TTI.getArithmeticInstrCost(
            RecurrenceDescriptor::getOpcode(RdxKind), OpTy, CostKind);
      };
      // The lane-wise operation; also replaces the scalar operation folding
      // the accumulator phi on top of the horizontal reduction (the scalar
      // cost of the slice credits it neither, the slice lacks the phi).
      InstructionCost Cost = GetOpCost(VectorTy) - GetOpCost(ScalarTy);
      // The vector accumulator and the reduced vector are live at the same
      // time; the registers they need beyond the register file are spilled
      // and reloaded on every iteration.
      constexpr unsigned NumLiveVectors = 2;
      unsigned Regs = TTI.getRegUsageForType(VectorTy);
      unsigned RC = TTI.getRegisterClassForType(/*Vector=*/true, VectorTy);
      unsigned NumRegs = TTI.getNumberOfRegisters(RC);
      InstructionCost SpillReload =
          TTI.getRegisterClassSpillCost(RC, CostKind) +
          TTI.getRegisterClassReloadCost(RC, CostKind);
      InstructionCost Spilled = 0;
      if (NumRegs != 0 && NumLiveVectors * Regs > NumRegs)
        Spilled = SpillReload * (NumLiveVectors * Regs - NumRegs);
      Cost += Spilled;
      // The vector accumulator replaces the scalar one across the calls of
      // the loop: without callee-saved registers of the class it is spilled
      // and reloaded around every call, like the scalar one. The accumulator
      // registers already spilled on every iteration stay in memory across
      // the calls and are not spilled again.
      if (NumCalls != 0) {
        InstructionCost VecLive =
            std::max(TTI.getCostOfKeepingLiveOverCall(VectorTy),
                     SpillReload * Regs) -
            std::min(Spilled, SpillReload * Regs);
        unsigned SRC = TTI.getRegisterClassForType(/*Vector=*/false, ScalarTy);
        InstructionCost ScalarLive =
            std::max(TTI.getCostOfKeepingLiveOverCall(ScalarTy),
                     TTI.getRegisterClassSpillCost(SRC, CostKind) +
                         TTI.getRegisterClassReloadCost(SRC, CostKind));
        Cost += (VecLive - ScalarLive) * NumCalls;
      }
      return Cost;
    }

  public:
    LoopAccumulator(Instruction *Root, RecurKind RdxKind, ReductionOrdering RK,
                    BoUpSLP &R, const TargetTransformInfo &TTI, LoopInfo &LI)
        : Root(Root), RdxKind(RdxKind), RK(RK), R(R), TTI(TTI), LI(LI) {}

    /// If the reduction accumulates a loop phi (the phi is one of the reduced
    /// values and the root is its backedge value), replaces the phi by the
    /// reduction identity in the reduced values, so that the emitted tree
    /// does not reference the phi. The identity does not change the result,
    /// so if the accumulator emission does not apply, the phi is just folded
    /// back on top of the emitted reduction. All unordered reduction kinds
    /// have an identity constant.
    void prepare(FastMathFlags RdxFMF,
                 SmallVectorImpl<SmallVector<Value *>> &ReducedVals,
                 SmallDenseMap<Value *, SmallVector<Instruction *>, 16>
                     &ReducedValsToOps,
                 const SmallPtrSetImpl<Value *> &NegatedReducedVals,
                 bool HasNarrowedLeafShifts) {
      // A two-value reduction is unordered by commutativity alone; the
      // accumulator reassociates the reduction across the loop iterations,
      // which requires a genuinely associative operation.
      if (!R.Opts.slp_vectorize_loop_acc_rdx ||
          RK != ReductionOrdering::Unordered ||
          isVectorizable(RdxKind, Root) != ReductionOrdering::Unordered ||
          Root->getType()->isIntegerTy(1) || Root->getType()->isVectorTy() ||
          HasNarrowedLeafShifts || isCmpSelMinMax(Root) ||
          Root->hasNUsesOrMore(UsesLimit))
        return;
      Loop *L = LI.getLoopFor(Root->getParent());
      if (!L)
        return;
      BasicBlock *Latch = L->getLoopLatch();
      if (!Latch)
        return;
      // Only a single accumulated phi, used by the reduction operations
      // only, is supported.
      auto FindAccPhi = [&]() -> PHINode * {
        PHINode *AccPhi = nullptr;
        for (ArrayRef<Value *> Candidates : ReducedVals)
          for (PHINode *P : make_isa_range<PHINode>(Candidates)) {
            if (P->getParent() != L->getHeader() ||
                P->getNumIncomingValues() > MaxPHINumOperands ||
                P->getIncomingValueForBlock(Latch) != Root)
              continue;
            if (AccPhi || P->hasNUsesOrMore(UsesLimit) ||
                P->getNumUses() != ReducedValsToOps.at(P).size())
              return nullptr;
            AccPhi = P;
          }
        return AccPhi;
      };
      PHINode *AccPhi = FindAccPhi();
      // A negated phi is subtracted from the reduction result, not
      // accumulated.
      if (!AccPhi || NegatedReducedVals.contains(AccPhi))
        return;
      Constant *IdC = getIdentity(AccPhi->getType(), RdxFMF);
      if (ReducedValsToOps.contains(IdC))
        return;
      // The root may be used only by the accumulator phi and by phis outside
      // the loop (the exit phis). The initial values are inserted into the
      // identity vector at the end of their incoming blocks, so they must not
      // be defined by the terminators; the final reduction is emitted at the
      // beginning of the exit blocks, which must not be EH pads. Neither may
      // land in a loop not containing the reduction loop, which would execute
      // them repeatedly.
      auto IsExecutedOncePerLoop = [&](BasicBlock *BB) {
        Loop *BBL = LI.getLoopFor(BB);
        return !BBL || BBL->contains(L);
      };
      if (any_of(zip(AccPhi->incoming_values(), AccPhi->blocks()),
                 [&](const auto &P) {
                   auto [IncV, B] = P;
                   return IncV != Root && (IncV == B->getTerminator() ||
                                           !IsExecutedOncePerLoop(B));
                 }))
        return;
      auto IsValidExitPhi = [&](User *U) {
        auto *ExitPhi = dyn_cast<PHINode>(U);
        return ExitPhi &&
               ExitPhi->getNumIncomingValues() <= MaxPHINumOperands &&
               !ExitPhi->getParent()->isEHPad() &&
               !L->contains(ExitPhi->getParent()) &&
               IsExecutedOncePerLoop(ExitPhi->getParent());
      };
      auto CollectExitPhis = [&] {
        for (User *U : Root->users()) {
          if (U == AccPhi)
            continue;
          if (!IsValidExitPhi(U))
            return false;
          ExitPhis.insert(cast<PHINode>(U));
        }
        return true;
      };
      if (!CollectExitPhis())
        return;
      // The final reduction and the insert of the initial value would be on
      // the loop-carried chain of an enclosing loop if the reduction result
      // feeds the initial value of the accumulator through it: keep the
      // horizontal reduction, whose chain is the scalar accumulator only.
      auto IsFedByExitPhi = [&](Value *InitV) {
        auto *InitPhi = dyn_cast<PHINode>(InitV);
        if (InitV == Root || !InitPhi)
          return false;
        // Too many incoming values to scan: keep the horizontal reduction.
        if (InitPhi->getNumIncomingValues() > MaxPHINumOperands)
          return true;
        return ExitPhis.contains(InitPhi) ||
               any_of(make_isa_range<PHINode>(InitPhi->incoming_values()),
                      [&](PHINode *P) { return ExitPhis.contains(P); });
      };
      if (any_of(AccPhi->incoming_values(), IsFedByExitPhi))
        return;
      // Calls clobber the vector registers: the vector accumulator has to be
      // kept live across them. Intrinsics cheaper than a call are not calls.
      for (BasicBlock *BB : L->blocks())
        NumCalls += count_if(*BB, [&](const Instruction &I) {
          auto *CB = dyn_cast<CallBase>(&I);
          if (!CB || CB->doesNotReturn())
            return false;
          auto *II = dyn_cast<IntrinsicInst>(CB);
          if (!II)
            return true;
          if (II->isAssumeLikeIntrinsic())
            return false;
          IntrinsicCostAttributes ICA(II->getIntrinsicID(), *II);
          return TTI.getIntrinsicInstrCost(ICA, R.getCostKind()) >=
                 TTI.getCallInstrCost(nullptr, II->getType(), ICA.getArgTypes(),
                                      R.getCostKind());
        });
      for (SmallVector<Value *> &Candidates : ReducedVals)
        for (Value *&RdxVal : Candidates)
          if (RdxVal == AccPhi)
            RdxVal = IdC;
      ReducedValsToOps.try_emplace(IdC, ReducedValsToOps.lookup(AccPhi));
      ReducedValsToOps.erase(AccPhi);
      Phi = AccPhi;
      Identity = IdC;
    }

    /// Collects the reduced values that were not vectorized; they are folded
    /// into the reduction on top of the vectorized part. The accumulator
    /// identity constant is never folded. The operation list of a value has
    /// one entry per occurrence of the value in the reduction, all reducing
    /// the same value, so the vectorized occurrences are accounted for by
    /// count only.
    void collectLeftovers(
        const DenseMap<Value *, unsigned> &VectorizedVals,
        ArrayRef<SmallVector<Value *>> ReducedVals,
        const SmallDenseMap<Value *, SmallVector<Instruction *>, 16>
            &ReducedValsToOps,
        SmallVectorImpl<std::pair<Instruction *, Value *>> &LeftoverReductions)
        const {
      SmallPtrSet<Value *, 8> Visited;
      for (ArrayRef<Value *> Candidates : ReducedVals)
        for (Value *RdxVal : make_filter_range(Candidates, [&](Value *RdxVal) {
               return RdxVal != Identity && Visited.insert(RdxVal).second;
             })) {
          unsigned NumOps = VectorizedVals.lookup(RdxVal);
          for (Instruction *RedOp :
               ArrayRef(ReducedValsToOps.at(RdxVal)).drop_back(NumOps))
            LeftoverReductions.emplace_back(RedOp, RdxVal);
        }
    }

    /// \returns the cost of the code the vector accumulator emits outside the
    /// loop: the final reductions in the exit blocks and the insert of the
    /// initial value, scaled by the enclosing loop nest.
    InstructionCost getExitCost(FastMathFlags FMF, const Loop *L) const {
      assert(
          (RecurrenceDescriptor::isMinMaxRecurrenceKind(RdxKind) ||
           Instruction::isBinaryOp(RecurrenceDescriptor::getOpcode(RdxKind))) &&
          "Expected arithmetic or min/max reduction operation");
      FixedVectorType *VecTy = R.getReductionType();
      TTI::TargetCostKind CostKind = R.getCostKind();
      InstructionCost RdxCost =
          RecurrenceDescriptor::isMinMaxRecurrenceKind(RdxKind)
              ? TTI.getMinMaxReductionCost(
                    getMinMaxReductionIntrinsicOp(RdxKind), VecTy, FMF,
                    CostKind)
              : TTI.getArithmeticReductionCost(
                    RecurrenceDescriptor::getOpcode(RdxKind), VecTy, FMF,
                    CostKind);
      // One exit block is executed per loop execution: charge the final
      // reductions of the largest one. Code size counts all of them.
      unsigned MaxExitRdx = 0;
      SmallDenseMap<BasicBlock *, unsigned> ExitBlockPhis;
      for (PHINode *ExitPhi : ExitPhis)
        MaxExitRdx =
            std::max(MaxExitRdx, ++ExitBlockPhis[ExitPhi->getParent()]);
      InstructionCost Cost =
          RdxCost *
              (CostKind == TTI::TCK_CodeSize ? ExitPhis.size() : MaxExitRdx) +
          TTI.getVectorInstrCost(Instruction::InsertElement, VecTy, CostKind,
                                 /*Index=*/0);
      return Cost * R.getLoopNestScale(L->getParentLoop());
    }

    /// Checks that the slice can be emitted as the vector accumulator: it is
    /// the only one (all other reduced values are the identity), not scaled,
    /// not reduced in-tree, of the root type and fully vectorized. An integer
    /// accumulator stays in a callee-saved register across the calls of the
    /// loop, the vector one would be spilled around every call on the
    /// loop-carried chain.
    bool isCandidate(const Value *VectorizedTree, bool HasVectorizedSlices,
                     bool IsSupportedHorRdxIdentityOp,
                     ArrayRef<SmallVector<Value *>> ReducedVals,
                     ArrayRef<Value *> Candidates, unsigned CandidatesIdx,
                     unsigned Pos, unsigned ReduxWidth, bool OptReusedScalars,
                     bool SameScaleFactor) const {
      if (!Phi || VectorizedTree || HasVectorizedSlices || Pos != 0 ||
          (OptReusedScalars && SameScaleFactor) || R.isReducedBitcastRoot() ||
          R.isReducedCmpBitcastRoot() ||
          (NumCalls != 0 && !Root->getType()->isFloatingPointTy()))
        return false;
      if (!all_of(ArrayRef(Candidates).drop_front(ReduxWidth),
                  [&](Value *RdxVal) { return RdxVal == Identity; }))
        return false;
      if (!all_of(enumerate(ReducedVals), [&](const auto &P) {
            auto [Idx, RV] = P;
            return Idx == CandidatesIdx ||
                   (RV.size() == 1 && RV.front() == Identity);
          }))
        return false;
      if (R.getReductionType()->getElementType() != Root->getType())
        return false;
      return IsSupportedHorRdxIdentityOp ||
             all_of(Candidates.slice(Pos, ReduxWidth),
                    [&](Value *RdxVal) { return R.isVectorized(RdxVal); });
    }

    /// \returns the cost delta of the vector accumulator form vs the
    /// horizontal reduction on every iteration. Both remove the same scalar
    /// operations, so only the vector code is compared: the lane-wise
    /// operation is executed on every iteration of the loop, the horizontal
    /// reduction as often as the tree cost model assumes (once, if the
    /// reduced values are loop-invariant), the final reduction and the
    /// initial insert once, outside the loop.
    InstructionCost getCostDelta(InstructionCost HorVecCost,
                                 InstructionCost RdxOpCost, FastMathFlags FMF,
                                 VectorType *VectorTy, Type *ScalarTy) const {
      // The lane-wise accumulation replaces the reduction operation in the
      // vector code.
      InstructionCost AccVecCost =
          HorVecCost - RdxOpCost + getAccumulationCost(FMF, VectorTy, ScalarTy);
      Loop *L = LI.getLoopFor(Phi->getParent());
      InstructionCost Delta = AccVecCost * R.getLoopNestScale(L) -
                              HorVecCost * R.getScaleToLoopIterations(
                                               R.getRootNode(), nullptr, Root) +
                              getExitCost(FMF, L);
      LLVM_DEBUG(dbgs() << "SLP: Loop accumulator cost delta " << Delta
                        << "\n");
      return Delta;
    }

    /// Emits the reduction as a vector accumulator if the accumulator form
    /// applies; otherwise folds the accumulator phi back on top of the
    /// reduction like a leftover and returns null.
    Value *tryEmit(
        IRBuilderBase &Builder, FastMathFlags RdxFMF, bool Vectorized,
        const Value *VectorizedTree,
        SmallVectorImpl<std::pair<Instruction *, Value *>> &LeftoverReductions,
        ArrayRef<ReductionVectorPart> VectorValuesAndScales,
        const SmallPtrSetImpl<Value *> &RequiredExtract,
        const SmallDenseMap<Value *, SmallVector<Instruction *>, 16>
            &ReducedValsToOps,
        const ReductionOpsListType &ReductionOps,
        function_ref<Value *(Value *, IRBuilderBase &, Type *)> EmitReduction) {
      if (!shouldEmit(Vectorized, VectorizedTree, LeftoverReductions,
                      VectorValuesAndScales, RequiredExtract)) {
        // The accumulator phi is folded back on top of the reduction like a
        // leftover: the identity replaced it in the reduced values and does
        // not change the result.
        if (Phi)
          LeftoverReductions.emplace_back(ReducedValsToOps.at(Identity).front(),
                                          Phi);
        return nullptr;
      }
      return emit(Builder, RdxFMF, VectorValuesAndScales.front().Vec,
                  ReductionOps, EmitReduction);
    }

  private:
    /// Checks that the accumulator form applies: the slice was vectorized as
    /// the accumulator and no other vectorized value or leftover reduced
    /// values remain to fold; the slice is of the root type, not scaled, not
    /// reduced in-tree and without extracts.
    bool
    shouldEmit(bool Vectorized, const Value *VectorizedTree,
               ArrayRef<std::pair<Instruction *, Value *>> LeftoverReductions,
               ArrayRef<ReductionVectorPart> VectorValuesAndScales,
               const SmallPtrSetImpl<Value *> &RequiredExtract) const {
      if (!Vectorized || VectorizedTree || !LeftoverReductions.empty() ||
          VectorValuesAndScales.size() != 1 || !RequiredExtract.empty())
        return false;
      const ReductionVectorPart &P = VectorValuesAndScales.front();
      return P.Scale == 1 && !P.ReducedInTree &&
             cast<VectorType>(P.Vec->getType())->getElementType() ==
                 Root->getType();
    }

    /// Emits the reduction as a vector accumulator: the vectorized reduced
    /// values are accumulated lane-wise into a vector phi in the loop and
    /// reduced once in the exit blocks.
    Value *emit(
        IRBuilderBase &Builder, FastMathFlags RdxFMF, Value *Vec,
        const ReductionOpsListType &ReductionOps,
        function_ref<Value *(Value *, IRBuilderBase &, Type *)> EmitReduction) {
      auto *VecTy = cast<FixedVectorType>(Vec->getType());
      // The initial values are placed in lane 0 of the identity splat at the
      // end of their incoming blocks; multiple edges from a block carry the
      // same value and share the insert.
      Constant *IdVec =
          ConstantVector::getSplat(VecTy->getElementCount(), Identity);
      auto *VAcc = PHINode::Create(VecTy, Phi->getNumIncomingValues(),
                                   "slprdx.acc", Phi->getIterator());
      SmallDenseMap<BasicBlock *, Value *> InitVecs;
      for (auto [IncV, B] : make_filter_range(
               zip(Phi->incoming_values(), Phi->blocks()),
               [&](const auto &P) { return std::get<0>(P) != Root; })) {
        Value *&InitVec = InitVecs[B];
        if (!InitVec) {
          IRBuilder<> EB(B->getTerminator());
          InitVec = EB.CreateInsertElement(IdVec, IncV, EB.getInt32(0),
                                           "slprdx.init");
        }
        VAcc->addIncoming(InitVec, B);
      }
      Builder.SetInsertPoint(Root);
      Value *VAdd = createOpWithFlags(Builder, RdxKind, VAcc, Vec, "slprdx.acc",
                                      ReductionOps, /*KeepDisjoint=*/true);
      // The accumulation is on the loop-carried chain: do not let it be
      // contracted into an FMA with the reduced multiplication, which would
      // lengthen the chain.
      if (auto *FPOp = dyn_cast<FPMathOperator>(VAdd)) {
        FastMathFlags FMF = FPOp->getFastMathFlags();
        FMF.setAllowContract(false);
        cast<Instruction>(VAdd)->copyFastMathFlags(FMF);
      }
      // The accumulator is the backedge value.
      for (auto [IncV, B] : zip(Phi->incoming_values(), Phi->blocks()))
        if (IncV == Root)
          VAcc->addIncoming(VAdd, B);
      LLVM_DEBUG(dbgs() << "SLP: Emitting loop accumulator reduction for "
                           "reduction with root "
                        << *Root << "\n");
      // The root is tracked by a weak handle: break its uses on the phi side.
      Value *Poison = PoisonValue::get(Root->getType());
      for (PHINode *ExitPhi : ExitPhis) {
        // The accumulator replaces the root on the edges carrying it and is
        // reduced once in the exit block. The values bypassing the loop never
        // went through the reduction operations and must stay exact: the
        // scalar phi keeps them and they are selected past the reduction
        // without its fast-math flags.
        unsigned NumIncoming = ExitPhi->getNumIncomingValues();
        auto *VExit = PHINode::Create(VecTy, NumIncoming, "slprdx.exit",
                                      ExitPhi->getIterator());
        PHINode *FromLoop = nullptr;
        if (any_of(ExitPhi->incoming_values(),
                   [this](Value *V) { return V != Root; }))
          FromLoop = PHINode::Create(Builder.getInt1Ty(), NumIncoming,
                                     "slprdx.fromloop", ExitPhi->getIterator());
        Value *VecPoison = PoisonValue::get(VecTy);
        for (auto [V, B] : zip(ExitPhi->incoming_values(), ExitPhi->blocks())) {
          bool IsRoot = V == Root;
          VExit->addIncoming(IsRoot ? VAdd : VecPoison, B);
          if (FromLoop)
            FromLoop->addIncoming(Builder.getInt1(IsRoot), B);
        }
        ExitPhi->replaceUsesOfWith(Root, Poison);
        IRBuilder<> XB(&*ExitPhi->getParent()->getFirstInsertionPt());
        XB.SetCurrentDebugLocation(ExitPhi->getDebugLoc());
        XB.setFastMathFlags(RdxFMF);
        Value *Res = EmitReduction(VExit, XB, ExitPhi->getType());
        if (!FromLoop) {
          ExitPhi->replaceAllUsesWith(Res);
          // The erasure is deferred: the block iteration is still in progress.
          R.eraseInstruction(ExitPhi);
          continue;
        }
        Value *Sel = XB.CreateSelectFMFWithUnknownProfile(
            FromLoop, Res, ExitPhi, FastMathFlags(), DEBUG_TYPE, "slprdx.sel");
        ExitPhi->replaceUsesWithIf(
            Sel, [Sel](Use &U) { return U.getUser() != Sel; });
      }
      Phi->replaceUsesOfWith(Root, Poison);
      R.eraseInstruction(Phi);
      // Do not let the caller re-analyze the emitted vector operation as a new
      // reduction seed.
      R.analyzedReductionRoot(cast<Instruction>(VAdd));
      return VAdd;
    }
  };

  /// Attempt to vectorize the tree found by matchAssociativeReduction.
  /// \p IsSeedRoot allows vectorizing the groups at the minimum vector
  /// factor. Set for single-use seed-level roots only.
  Value *tryToReduce(BoUpSLP &V, const DataLayout &DL, TargetTransformInfo *TTI,
                     const TargetLibraryInfo &TLI, AssumptionCache *AC,
                     DominatorTree &DT, LoopInfo &LI, bool IsSeedRoot = false) {
    constexpr unsigned RegMaxNumber = 4;
    const unsigned RedValsMaxNumber =
        (RK == ReductionOrdering::Ordered &&
         ReductionRoot->getType()->isIntOrIntVectorTy())
            ? 48
            : 128;
    // If there are a sufficient number of reduction values, reduce
    // to a nearby power-of-2. We can safely generate oversized
    // vectors and rely on the backend to split them to legal sizes.
    if (unsigned NumReducedVals =
            accumulate(ReducedVals, 0,
                       [](unsigned Num, ArrayRef<Value *> Vals) -> unsigned {
                         if (!isGoodForReduction(Vals))
                           return Num;
                         return Num + Vals.size();
                       });
        NumReducedVals < ReductionLimit &&
        all_of(
            ReducedVals,
            [](ArrayRef<Value *> RedV) {
              return RedV.size() < 2 || !allConstant(RedV) || !isSplat(RedV);
            })) {
      // For ordered reductions the leaves are pulled in via the fallback in
      // matchAssociativeReduction and may still be valid reduction roots on
      // their own; only the root is a dead end. For unordered reductions keep
      // marking every reduction op as analyzed.
      if (RK == ReductionOrdering::Ordered) {
        V.analyzedReductionRoot(cast<Instruction>(ReductionRoot));
      } else {
        for (ReductionOpsType &RdxOps : ReductionOps)
          for (Value *RdxOp : RdxOps)
            V.analyzedReductionRoot(cast<Instruction>(RdxOp));
      }
      return nullptr;
    }

    IRBuilder<TargetFolder> Builder(
        cast<Instruction>(ReductionRoot)->getIterator(), TargetFolder(DL));
    // The scalar parts (scaled reused values, their combines) are emitted right
    // before the root; the instruction preceding them is remembered to drop
    // them, if the sign-aware reduction is abandoned.
    Instruction *InstBeforeRoot =
        cast<Instruction>(ReductionRoot)->getPrevNode();

    // Track the reduced values in case if they are replaced by extractelement
    // because of the vectorization.
    DenseMap<Value *, WeakTrackingVH> TrackedVals(ReducedVals.size() *
                                                  ReducedVals.front().size());

    // The compare instruction of a min/max is the insertion point for new
    // instructions and may be replaced with a new compare instruction.
    auto &&GetCmpForMinMaxReduction = [](Instruction *RdxRootInst) {
      assert(isa<SelectInst>(RdxRootInst) &&
             "Expected min/max reduction to have select root instruction");
      Value *ScalarCond = cast<SelectInst>(RdxRootInst)->getCondition();
      assert(isa<Instruction>(ScalarCond) &&
             "Expected min/max reduction to have compare condition");
      return cast<Instruction>(ScalarCond);
    };

    bool AnyBoolLogicOp = any_of(ReductionOps.back(), [](Value *V) {
      return isBoolLogicOp(cast<Instruction>(V));
    });
    // Return new VectorizedTree, based on previous value.
    auto GetNewVectorizedTree = [&](Value *VectorizedTree, Value *Res) {
      if (VectorizedTree) {
        // Update the final value in the reduction.
        Builder.SetCurrentDebugLocation(
            cast<Instruction>(ReductionOps.front().front())->getDebugLoc());
        if (AnyBoolLogicOp) {
          auto It = ReducedValsToOps.find(VectorizedTree);
          auto It1 = ReducedValsToOps.find(Res);
          if ((It == ReducedValsToOps.end() && It1 == ReducedValsToOps.end()) ||
              isGuaranteedNotToBePoison(VectorizedTree, AC) ||
              (It != ReducedValsToOps.end() &&
               any_of(It->getSecond(), [&](Instruction *I) {
                 return isBoolLogicOp(I) &&
                        getRdxOperand(I, 0) == VectorizedTree;
               }))) {
            ;
          } else if (isGuaranteedNotToBePoison(Res, AC) ||
                     (It1 != ReducedValsToOps.end() &&
                     any_of(It1->getSecond(), [&](Instruction *I) {
                       return isBoolLogicOp(I) && getRdxOperand(I, 0) == Res;
                     }))) {
            std::swap(VectorizedTree, Res);
          } else {
            VectorizedTree = Builder.CreateFreeze(VectorizedTree);
          }
        }

        return createOp(Builder, RdxKind, VectorizedTree, Res, "op.rdx",
                        ReductionOps);
      }
      // Initialize the final value in the reduction.
      return Res;
    };
    SmallDenseSet<Value *> IgnoreList(ReductionOps.size() *
                                      ReductionOps.front().size());
    for (ReductionOpsType &RdxOps : ReductionOps)
      for (Value *RdxOp :
           make_filter_range(RdxOps, [](Value *RdxOp) { return RdxOp; }))
        IgnoreList.insert(RdxOp);
    // Dropped with the reduction; do not treat as external uses.
    IgnoreList.insert_range(NarrowedChainInsts);
    // Intersect the fast-math-flags from all reduction operations.
    FastMathFlags RdxFMF;
    RdxFMF.set();
    for (FPMathOperator *FPMO : make_isa_range<FPMathOperator>(IgnoreList))
      RdxFMF &= FPMO->getFastMathFlags();
    // Returns true if the original reduced value \p V is subtracted from the
    // reduction result.
    auto IsNegated = [&](Value *V) { return NegatedReducedVals.contains(V); };
    // Scalar values subtracted from the reduction result: combined pairwise
    // like the positive ones and subtracted in the final combine, so no
    // extra negations are emitted.
    SmallVector<std::pair<Instruction *, Value *>> NegExtraReductions;
    // For ordered reductions here we need to generate extractelement
    // instructions, so clear IgnoreList.
    if (RK == ReductionOrdering::Ordered)
      IgnoreList.clear();
    bool IsCmpSelMinMax = isCmpSelMinMax(cast<Instruction>(ReductionRoot));

    // A reduction that accumulates a loop phi can be emitted as a vector
    // accumulator in the loop plus a single reduction after it.
    LoopAccumulator LoopAcc(cast<Instruction>(ReductionRoot), RdxKind, RK, V,
                            *TTI, LI);
    LoopAcc.prepare(RdxFMF, ReducedVals, ReducedValsToOps, NegatedReducedVals,
                    !NarrowedLeafShifts.empty());
    // Set when the slice costed as the vector accumulator was vectorized.
    bool LoopAccVectorized = false;

    // Need to track reduced vals, they may be changed during vectorization of
    // subvectors.
    for (ArrayRef<Value *> Candidates : ReducedVals)
      for (Value *V : Candidates)
        TrackedVals.try_emplace(V, V);

    auto At = [](SmallMapVector<Value *, unsigned, 16> &MV,
                 Value *V) -> unsigned & {
      auto *It = MV.find(V);
      assert(It != MV.end() && "Unable to find given key.");
      return It->second;
    };

    DenseMap<Value *, unsigned> VectorizedVals(ReducedVals.size());
    // List of the values that were reduced in other trees as part of gather
    // nodes and thus requiring extract if fully vectorized in other trees.
    SmallPtrSet<Value *, 4> RequiredExtract;
    WeakTrackingVH VectorizedTree = nullptr;
    // The flattened reduction may be abandoned and retried without the
    // fsub/fneg flattening, where the same lists of reduced values may be
    // profitable - they are not marked as analyzed.
    auto MarkAnalyzedVals = [&](ArrayRef<Value *> VL) {
      if (!hasFlattenedNegations())
        V.analyzedReductionVals(VL);
    };
    // Routes the emitted value by the sign of its group: negated parts are
    // combined separately and subtracted in the final combine. \p OrigV is
    // the original reduced value (null for the combined vector reduction
    // result); its reduction operation provides the debug location.
    auto AddReducedPart = [&](Value *OrigV, Value *Res, bool Negated) {
      if (Negated) {
        NegExtraReductions.emplace_back(OrigV
                                            ? ReducedValsToOps.at(OrigV).front()
                                            : cast<Instruction>(ReductionRoot),
                                        Res);
        return;
      }
      VectorizedTree = GetNewVectorizedTree(VectorizedTree, Res);
    };
    bool CheckForReusedReductionOps = false;
    // Try to vectorize elements based on their type.
    SmallVector<InstructionsState> States;
    SmallVector<SmallVector<Value *>> LocalReducedVals;
    // Try merge consecutive reduced values into a single vectorizable group and
    // check, if they can be vectorized as copyables.
    const bool TwoGroupsOnly = ReducedVals.size() == 2;
    const bool TwoGroupsOfSameSmallSize =
        TwoGroupsOnly &&
        ReducedVals.front().size() == ReducedVals.back().size() &&
        ReducedVals.front().size() < ReductionLimit;
    for (ArrayRef<Value *> RV : ReducedVals) {
      // Groups with different signs of their contribution cannot be merged:
      // the mixed group cannot be added/subtracted as a whole. The merge
      // candidate is the last group of the same sign.
      int MergeIdx = LocalReducedVals.size() - 1;
      while (MergeIdx >= 0 && IsNegated(LocalReducedVals[MergeIdx].front()) !=
                                  IsNegated(RV.front()))
        --MergeIdx;
      const bool SameSign = LocalReducedVals.empty() || MergeIdx >= 0;
      // Loads are not very compatible with undefs.
      if (isa<UndefValue>(RV.front()) &&
          (States.empty() || !States.back() ||
           States.back().getOpcode() == Instruction::Load)) {
        LocalReducedVals.emplace_back().append(RV.begin(), RV.end());
        States.push_back(InstructionsState::invalid());
        continue;
      }
      if (!LocalReducedVals.empty() &&
          isa<UndefValue>(LocalReducedVals.back().front()) &&
          isa<LoadInst>(RV.front())) {
        LocalReducedVals.emplace_back().append(RV.begin(), RV.end());
        States.push_back(getSameOpcode(RV, TLI));
        continue;
      }
      // Do some copyables analysis only if more than 2 groups exist or they
      // are large enough.
      if (SameSign && !TwoGroupsOfSameSmallSize) {
        SmallVector<Value *> Ops;
        if (!LocalReducedVals.empty())
          Ops = LocalReducedVals[MergeIdx];
        Ops.append(RV.begin(), RV.end());
        InstructionsCompatibilityAnalysis Analysis(DT, DL, *TTI, TLI);
        InstructionsState OpS = Analysis.buildInstructionsState(
            Ops, V, /*WithProfitabilityCheck=*/true);
        if (OpS) {
          if (LocalReducedVals.empty()) {
            LocalReducedVals.push_back(Ops);
            States.push_back(OpS);
            continue;
          }
          LocalReducedVals[MergeIdx].swap(Ops);
          States[MergeIdx] = OpS;
          continue;
        }
        // For safety, allow split vectorization only if 2 groups are available
        // overall.
        if (TwoGroupsOnly) {
          auto [MainOp, AltOp] = getMainAltOpsNoStateVL(Ops);
          OpS = InstructionsState(MainOp, AltOp);
          // Last chance to try to vectorize alternate node.
          SmallVector<Value *> Op1, Op2;
          BoUpSLP::OrdersType ReorderIndices;
          // canBuildSplitNode() relies on VectorizableTree(), make sure to
          // clear here since it may contain leftover state from prior attempts.
          V.deleteTree();
          if (MainOp && AltOp &&
              V.canBuildSplitNode(Ops, OpS, Op1, Op2, ReorderIndices)) {
            if (LocalReducedVals.empty()) {
              LocalReducedVals.push_back(Ops);
              States.push_back(OpS);
              continue;
            }
            LocalReducedVals[MergeIdx].swap(Ops);
            States[MergeIdx] = OpS;
            continue;
          }
        }
      }
      LocalReducedVals.emplace_back().append(RV.begin(), RV.end());
      States.push_back(getSameOpcode(RV, TLI));
    }
    ReducedVals.swap(LocalReducedVals);
    FastMathFlags GroupRdxFMF = RdxFMF;
    // The minimum vector factor pays off only when it covers the whole
    // reduction: every group must be either a pair of distinct values or
    // large enough for the regular vector factor.
    const bool NoScalarLeftovers =
        all_of(ReducedVals, [this](ArrayRef<Value *> Vals) {
          return Vals.size() >= ReductionLimit ||
                 (Vals.size() == 2 && Vals.front() != Vals.back());
        });
    // Small sign-aware groups pay off only when paired via the vector fsub:
    // each sign must have a group of at least 2 values.
    auto HasGroupOfSign = [&](bool Negated) {
      return any_of(ReducedVals, [&](ArrayRef<Value *> Vals) {
        return Vals.size() >= 2 && IsNegated(Vals.front()) == Negated;
      });
    };
    const bool CanPairSigns =
        HasGroupOfSign(/*Negated=*/false) && HasGroupOfSign(/*Negated=*/true);
    // Same-size groups of the seed-level reduction get the profitability
    // ordering (cheap groups go last) when the minimum vector factor covers
    // the whole reduction.
    if (IsSeedRoot && NegatedReducedVals.empty() && NoScalarLeftovers &&
        any_of(ReducedVals,
               [](ArrayRef<Value *> Vals) { return Vals.size() == 2; })) {
      SmallVector<unsigned> GroupOrder(ReducedVals.size());
      std::iota(GroupOrder.begin(), GroupOrder.end(), 0);
      stable_sort(GroupOrder, [&](unsigned L, unsigned R) {
        ArrayRef<Value *> P1 = ReducedVals[L], P2 = ReducedVals[R];
        if (P1.size() != P2.size())
          return P1.size() > P2.size();
        return !isCheapReductionGroup(P1) && isCheapReductionGroup(P2);
      });
      SmallVector<SmallVector<Value *>> SortedVals;
      SmallVector<InstructionsState> SortedStates;
      SortedVals.reserve(ReducedVals.size());
      SortedStates.reserve(States.size());
      for (unsigned Idx : GroupOrder) {
        SortedVals.emplace_back(std::move(ReducedVals[Idx]));
        SortedStates.push_back(States[Idx]);
      }
      ReducedVals = std::move(SortedVals);
      States = std::move(SortedStates);
    }
    for (unsigned I = 0, E = ReducedVals.size(); I < E; ++I) {
      ArrayRef<Value *> OrigReducedVals = ReducedVals[I];
      InstructionsState S = States[I];
      // The main operation of a state with copyable elements may be deleted
      // during previous vectorization attempts, the state is not usable then.
      if (S && S.areInstructionsWithCopyableElements() &&
          V.isDeleted(S.getMainOp()))
        S = InstructionsState::invalid();
      SmallVector<Value *> Candidates;
      Candidates.reserve(2 * OrigReducedVals.size());
      SmallVector<Value *> TrackedToOrig;
      // Reduced values that were replaced by an extractelement (because they
      // were vectorized in another reduction subset or operand cone) and are
      // not compatible with this group. They are not vectorized again here, but
      // they are still live and consumed by the final reduction, so they must
      // be kept externally used to avoid erasing them while vectorizing this
      // group, which may use them as operands.
      SmallVector<Value *> ExcludedVectorizedReducedVals;
      for (Value *ReducedVal : OrigReducedVals) {
        Value *RdxVal = TrackedVals.at(ReducedVal);
        // Check if the reduction value was not overriden by the extractelement
        // instruction because of the vectorization and exclude it, if it is not
        // compatible with other values.
        // Also check if the instruction was folded to constant/other value.
        auto *Inst = dyn_cast<Instruction>(RdxVal);
        if (Inst && V.isDeleted(Inst))
          continue;
        if (Inst && isVectorLikeInstWithConstOps(Inst) &&
            (!S || (!S.getMatchingMainOpOrAltOp(Inst) &&
                    !S.isCopyableElement(Inst)))) {
          ExcludedVectorizedReducedVals.push_back(RdxVal);
          continue;
        }
        if (S && !Inst && !isa<UndefValue>(RdxVal) &&
            !S.isCopyableElement(RdxVal))
          continue;
        Candidates.push_back(RdxVal);
        TrackedToOrig.push_back(ReducedVal);
      }
      // The groups are sign-uniform by matching, so the first original
      // value's sign applies to all of them.
      const bool GroupNegated =
          !TrackedToOrig.empty() && IsNegated(TrackedToOrig.front());
      bool ShuffledExtracts = false;
      // Try to handle shuffled extractelements. Only pure extractelement
      // groups can be merged: merged groups are skipped for external uses,
      // and other values would be erased while still used by reduction ops.
      if (S && S.getOpcode() == Instruction::ExtractElement &&
          !S.isAltShuffle() && I + 1 < E &&
          all_of(ReducedVals[I + 1],
                 [&](Value *RV) {
                   return isa<ExtractElementInst>(TrackedVals.at(RV));
                 }) &&
          GroupNegated == IsNegated(ReducedVals[I + 1].front())) {
        SmallVector<Value *> CommonCandidates(Candidates);
        for (Value *RV : ReducedVals[I + 1]) {
          Value *RdxVal = TrackedVals.at(RV);
          // Check if the reduction value was not overriden by the
          // extractelement instruction because of the vectorization and
          // exclude it, if it is not compatible with other values.
          auto *Inst = dyn_cast<ExtractElementInst>(RdxVal);
          if (!Inst)
            continue;
          CommonCandidates.push_back(RdxVal);
          TrackedToOrig.push_back(RV);
        }
        SmallVector<int> Mask;
        if (isFixedVectorShuffle(CommonCandidates, Mask, AC,
                                 V.getAnalysisCache())) {
          ++I;
          Candidates.swap(CommonCandidates);
          ShuffledExtracts = true;
        }
      }
      assert(all_of(TrackedToOrig,
                    [&](Value *V) { return IsNegated(V) == GroupNegated; }) &&
             "Expected sign-uniform group of reduced values");

      // Emit code for constant values.
      if (Candidates.size() > 1 && allConstant(Candidates)) {
        if (RK == ReductionOrdering::Ordered)
          continue;
        Value *Res = Candidates.front();
        Value *OrigV = TrackedToOrig.front();
        ++VectorizedVals.try_emplace(OrigV).first->getSecond();
        for (const auto [Idx, VC] :
             enumerate(ArrayRef(Candidates).drop_front())) {
          Res = createOp(Builder, RdxKind, Res, VC, "const.rdx", ReductionOps);
          Value *OrigV = TrackedToOrig[Idx + 1];
          ++VectorizedVals.try_emplace(OrigV).first->getSecond();
          if (auto *ResI = dyn_cast<Instruction>(Res))
            V.analyzedReductionRoot(ResI);
        }
        AddReducedPart(TrackedToOrig.front(), Res, GroupNegated);
        continue;
      }

      unsigned NumReducedVals = Candidates.size();
      auto UsedByReductionOnly = [&](Value *V) {
        if (!V->hasUseList())
          return true;
        // Bail out if we have too many uses to save compilation time.
        if (V->hasNUsesOrMore(UsesLimit))
          return false;
        return all_of(V->users(),
                      [&](User *U) { return IgnoreList.contains(U); });
      };
      // Sign-aware reductions pair small positive/negative groups: allow
      // non-splat groups down to 2 elements. Seed-level reductions get the
      // same for groups whose values are used by the reduction operations
      // only, if the minimum vector factor covers the whole reduction.
      const bool MinVFAllowed = IsSeedRoot && NoScalarLeftovers &&
                                all_of(Candidates, UsedByReductionOnly);
      if (NumReducedVals < ReductionLimit &&
          (NumReducedVals < 2 ||
           (!isSplat(Candidates) && !CanPairSigns && !MinVFAllowed)))
        continue;

      // Check if we support repeated scalar values processing (optimization of
      // original scalar identity operations on matched horizontal reductions).
      IsSupportedHorRdxIdentityOp =
          RK == ReductionOrdering::Unordered && RdxKind != RecurKind::Mul &&
          RdxKind != RecurKind::FMul && RdxKind != RecurKind::FMulAdd &&
          (!Opts.slp_revec || !Candidates.front()->getType()->isVectorTy());
      // Gather same values.
      SmallMapVector<Value *, unsigned, 16> SameValuesCounter;
      if (IsSupportedHorRdxIdentityOp)
        for (const auto [Idx, V] : enumerate(Candidates)) {
          Value *OrigV = TrackedToOrig[Idx];
          ++SameValuesCounter.try_emplace(OrigV).first->second;
        }
      // Used to check if the reduced values used same number of times. In this
      // case the compiler may produce better code. E.g. if reduced values are
      // aabbccdd (8 x values), then the first node of the tree will have a node
      // for 4 x abcd + shuffle <4 x abcd>, <0, 0, 1, 1, 2, 2, 3, 3>.
      // Plus, the final reduction will be performed on <8 x aabbccdd>.
      // Instead compiler may build <4 x abcd> tree immediately, + reduction (4
      // x abcd) * 2.
      // Currently it only handles add/fadd/xor. and/or/min/max do not require
      // this analysis, other operations may require an extra estimation of
      // the profitability.
      bool SameScaleFactor = false;
      bool OptReusedScalars = IsSupportedHorRdxIdentityOp &&
                              SameValuesCounter.size() != Candidates.size();
      BoUpSLP::ExtraValueToDebugLocsMap ExternallyUsedValues;
      for (Value *RdxVal : ExcludedVectorizedReducedVals)
        ExternallyUsedValues.insert(RdxVal);
      if (OptReusedScalars) {
        SameScaleFactor =
            (RdxKind == RecurKind::Add || RdxKind == RecurKind::FAdd ||
             RdxKind == RecurKind::Xor) &&
            all_of(drop_begin(SameValuesCounter),
                   [&SameValuesCounter](const std::pair<Value *, unsigned> &P) {
                     return P.second == SameValuesCounter.front().second;
                   });
        Candidates.resize(SameValuesCounter.size());
        TrackedToOrig.resize(SameValuesCounter.size());
        transform(SameValuesCounter, Candidates.begin(),
                  [&](const auto &P) { return TrackedVals.at(P.first); });
        transform(SameValuesCounter, TrackedToOrig.begin(),
                  [](const auto &P) { return P.first; });
        NumReducedVals = Candidates.size();
        // Have a reduction of the same element.
        if (NumReducedVals == 1) {
          Value *OrigV = TrackedToOrig.front();
          unsigned Cnt = At(SameValuesCounter, OrigV);
          // A negated repeated value joins an already vectorized part of the
          // same width as a splat operand of the vector fsub (a per-lane fnma
          // with a multiply part) instead of the scalar scale and subtract.
          if (GroupNegated &&
              any_of(VectorValuesAndScales, [&](const ReductionVectorPart &P) {
                return P.Vec && !P.ReducedInTree &&
                       getNumElements(P.Vec->getType()) == Cnt;
              })) {
            Value *Splat = Builder.CreateVectorSplat(Cnt, Candidates.front());
            VectorValuesAndScales.push_back({Splat, /*Scale=*/1,
                                             /*IsSigned=*/true,
                                             /*ReducedInTree=*/false,
                                             GroupNegated});
          } else {
            Value *RedVal =
                emitScaleForReusedOps(Candidates.front(), Builder, Cnt);
            AddReducedPart(OrigV, RedVal, GroupNegated);
          }
          VectorizedVals.try_emplace(OrigV, Cnt);
          ExternallyUsedValues.insert(OrigV);
          continue;
        }
      }

      GroupRdxFMF = RdxFMF;
      // No need to check for associativity, if 2 reduced values.
      if (NumReducedVals == 2 &&
          (RdxKind == RecurKind::FAdd || RdxKind == RecurKind::FMul))
        GroupRdxFMF.setAllowReassoc(true);

      unsigned MaxVecRegSize = V.getMaxVecRegSize();
      unsigned EltSize = V.getVectorElementSize(Candidates[0]);
      const unsigned MaxElts = std::clamp<unsigned>(
          llvm::bit_floor(MaxVecRegSize / EltSize), RedValsMaxNumber,
          RegMaxNumber * RedValsMaxNumber);

      unsigned ReduxWidth = NumReducedVals;
      auto GetVectorFactor = [&, &TTI = *TTI](unsigned ReduxWidth) {
        unsigned NumRegs, NumAvailRegs;
        Type *ScalarTy = Candidates.front()->getType();
        ReduxWidth = getFloorFullVectorNumberOfElements(
            TTI, ScalarTy, ReduxWidth, Opts.slp_revec);
        VectorType *Tp = cast<VectorType>(getWidenedType(ScalarTy, ReduxWidth));
        NumRegs = V.getRegUsageForType(Tp, ScalarTy);
        NumAvailRegs =
            TTI.getNumberOfRegisters(TTI.getRegisterClassForType(true, Tp));
        while (NumRegs > NumAvailRegs) {
          assert(ReduxWidth > 0 && "ReduxWidth is unexpectedly 0.");
          ReduxWidth = bit_floor(ReduxWidth - 1);
          VectorType *Tp =
              cast<VectorType>(getWidenedType(ScalarTy, ReduxWidth));
          NumRegs = V.getRegUsageForType(Tp, ScalarTy);
          NumAvailRegs =
              TTI.getNumberOfRegisters(TTI.getRegisterClassForType(true, Tp));
        }
        if (NumRegs > NumAvailRegs / 2)
          ReduxWidth = bit_floor(ReduxWidth);
        return ReduxWidth;
      };
      if (!isAllowedNonPowerOf2VF(ReduxWidth,
                                  Opts.slp_vectorize_non_power_of_2))
        ReduxWidth = GetVectorFactor(ReduxWidth);
      ReduxWidth = std::min(ReduxWidth, MaxElts);

      unsigned Start = 0;
      unsigned Pos = Start;
      // Restarts vectorization attempt with lower vector factor.
      unsigned PrevReduxWidth = ReduxWidth;
      bool CheckForReusedReductionOpsLocal = false;
      auto AdjustReducedVals = [&](bool IgnoreVL = false) {
        bool IsAnyRedOpGathered =
            !IgnoreVL &&
            (RK == ReductionOrdering::Ordered || V.isAnyGathered(IgnoreList));
        if (!CheckForReusedReductionOpsLocal && PrevReduxWidth == ReduxWidth) {
          // Check if any of the reduction ops are gathered. If so, worth
          // trying again with less number of reduction ops.
          CheckForReusedReductionOpsLocal |= IsAnyRedOpGathered;
        }
        ++Pos;
        if (Pos < NumReducedVals - ReduxWidth + 1)
          return IsAnyRedOpGathered;
        Pos = Start;
        --ReduxWidth;
        if (ReduxWidth > 1)
          ReduxWidth = GetVectorFactor(ReduxWidth);
        return IsAnyRedOpGathered;
      };
      bool AnyVectorized = false;
      SmallDenseSet<std::pair<unsigned, unsigned>, 8> IgnoredCandidates;
      // The overlapping windows rebuild almost the same trees. Like the
      // scheduling region, the size of the next tree, estimated by the last
      // rejected one, is limited by the budget, reduced by the sizes of the
      // rejected trees, but not below the minimal size. The non-power-of-2
      // widths get only the minimal size for the rejected trees. The budget
      // limits only the series of the rejected trees, the vectorized tree
      // starts a new series.
      unsigned ReductionBudget = Opts.slp_reduction_budget;
      unsigned LastRejectedTreeSize = 1;
      unsigned NonPowerOf2RejectedSize = 0;
      auto RejectTree = [&]() {
        LastRejectedTreeSize = V.getTreeSize();
        const unsigned Size = ReduxWidth * LastRejectedTreeSize;
        ReductionBudget -= std::min(ReductionBudget, Size);
        ReductionBudget = std::max(ReductionBudget, MinReductionTreeSize);
        if (!has_single_bit(ReduxWidth))
          NonPowerOf2RejectedSize += Size;
      };
      // Same small-group allowance for the vector width, if it covers the
      // whole group.
      const unsigned MinReduxWidth =
          CanPairSigns || (MinVFAllowed && NumReducedVals == 2)
              ? 2
              : ReductionLimit;
      while (Pos < NumReducedVals - ReduxWidth + 1 &&
             ReduxWidth >= MinReduxWidth) {
        // Dependency in tree of the reduction ops - drop this attempt, try
        // later.
        if (CheckForReusedReductionOpsLocal && PrevReduxWidth != ReduxWidth &&
            Start == 0) {
          CheckForReusedReductionOps = true;
          break;
        }
        PrevReduxWidth = ReduxWidth;
        ArrayRef<Value *> VL(std::next(Candidates.begin(), Pos), ReduxWidth);
        // Been analyzed already or out of budget - skip.
        if (ReduxWidth * LastRejectedTreeSize > ReductionBudget ||
            IgnoredCandidates.contains(std::make_pair(Pos, ReduxWidth)) ||
            (!has_single_bit(ReduxWidth) &&
             (NonPowerOf2RejectedSize > MinReductionTreeSize ||
              IgnoredCandidates.contains(
                  std::make_pair(Pos, bit_floor(ReduxWidth))) ||
              IgnoredCandidates.contains(
                  std::make_pair(Pos + (ReduxWidth - bit_floor(ReduxWidth)),
                                 bit_floor(ReduxWidth))))) ||
            V.areAnalyzedReductionVals(VL)) {
          (void)AdjustReducedVals(/*IgnoreVL=*/true);
          continue;
        }
        // Early exit if any of the reduction values were deleted during
        // previous vectorization attempts.
        if (any_of(make_isa_range<Instruction>(VL),
                   [&V](Instruction *RedValI) { return V.isDeleted(RedValI); }))
          break;
        if (RK == ReductionOrdering::Ordered) {
          V.buildTree(VL);
        } else {
          V.buildTree(VL, IgnoreList);
          V.setNarrowedChainInsts(NarrowedChainInsts);
        }
        if (V.isTreeTinyAndNotFullyVectorizable(RK ==
                                                ReductionOrdering::Unordered)) {
          RejectTree();
          constexpr unsigned CandidatesLimit = 64;
          if (!AdjustReducedVals(RK == ReductionOrdering::Ordered &&
                                 Candidates.size() >= CandidatesLimit))
            MarkAnalyzedVals(VL);
          continue;
        }
        V.reorderTopToBottom();
        // No need to reorder the root node at all for reassociative reduction.
        V.reorderBottomToTop(/*IgnoreReorder=*/GroupRdxFMF.allowReassoc() ||
                             VL.front()->getType()->isIntOrIntVectorTy() ||
                             ReductionLimit > 2 ||
                             RK == ReductionOrdering::Ordered);
        // Keep extracted other reduction values, if they are used in the
        // vectorization trees.
        BoUpSLP::ExtraValueToDebugLocsMap LocalExternallyUsedValues(
            ExternallyUsedValues);
        // The reduction root is used as the insertion point for new
        // instructions, so set it as externally used to prevent it from being
        // deleted.
        LocalExternallyUsedValues.insert(ReductionRoot);
        for (unsigned Cnt = 0, Sz = ReducedVals.size(); Cnt < Sz; ++Cnt) {
          if (Cnt == I || (ShuffledExtracts && Cnt == I - 1))
            continue;
          for (Instruction *Inst :
               make_isa_range<Instruction>(ReducedVals[Cnt]))
            LocalExternallyUsedValues.insert(TrackedVals[Inst]);
        }
        if (!IsSupportedHorRdxIdentityOp) {
          // Number of uses of the candidates in the vector of values.
          assert(SameValuesCounter.empty() &&
                 "Reused values counter map is not empty");
          for (unsigned Cnt = 0; Cnt < NumReducedVals; ++Cnt) {
            if (Cnt >= Pos && Cnt < Pos + ReduxWidth)
              continue;
            Value *OrigV = TrackedToOrig[Cnt];
            ++SameValuesCounter.try_emplace(OrigV).first->second;
          }
        }
        V.transformNodes();
        V.computeMinimumValueSizes();
        InstructionCost TreeCost = V.calculateTreeCostAndTrimNonProfitable(
            VL, cast<Instruction>(ReductionRoot));
        // A negated slice is subtracted in the final combine, it cannot be
        // accumulated lane-wise.
        const bool LoopAccCandidate =
            !GroupNegated &&
            LoopAcc.isCandidate(VectorizedTree, !VectorValuesAndScales.empty(),
                                IsSupportedHorRdxIdentityOp, ReducedVals,
                                Candidates, I, Pos, ReduxWidth,
                                OptReusedScalars, SameScaleFactor);

        SmallPtrSet<Value *, 4> VLScalars(llvm::from_range, VL);
        // Gather externally used values.
        SmallPtrSet<Value *, 4> Visited;
        for (unsigned Cnt = 0; Cnt < NumReducedVals; ++Cnt) {
          if (Cnt >= Pos && Cnt < Pos + ReduxWidth)
            continue;
          // The candidate may be replaced by the previous vectorization
          // attempts, use the currently tracked value.
          Value *RdxVal = TrackedVals.at(TrackedToOrig[Cnt]);
          if (!Visited.insert(RdxVal).second)
            continue;
          // Scalars not reduced by the top node may be used by the reduction
          // epilogue, even if not vectorized as part of the tree.
          if (!VLScalars.contains(RdxVal)) {
            LocalExternallyUsedValues.insert(RdxVal);
            continue;
          }
          Value *OrigV = TrackedToOrig[Cnt];
          unsigned NumOps =
              VectorizedVals.lookup(OrigV) + At(SameValuesCounter, OrigV);
          if (NumOps != ReducedValsToOps.at(OrigV).size())
            LocalExternallyUsedValues.insert(RdxVal);
        }
        // Do not need the list of reused scalars in regular mode anymore.
        if (!IsSupportedHorRdxIdentityOp)
          SameValuesCounter.clear();
        for (Value *RdxVal : VL)
          if (RequiredExtract.contains(RdxVal))
            LocalExternallyUsedValues.insert(RdxVal);
        V.buildExternalUses(LocalExternallyUsedValues);

        // Estimate cost.
        InstructionCost ReductionCost, HorVecCost = 0, RdxOpCost = 0;
        if (RK == ReductionOrdering::Ordered || V.isReducedBitcastRoot() ||
            V.isReducedCmpBitcastRoot())
          ReductionCost = 0;
        else
          ReductionCost = getReductionCost(
              TTI, VL, TrackedToOrig, Pos, SameValuesCounter, IsCmpSelMinMax,
              GroupRdxFMF, V, DT, DL, TLI, HorVecCost, RdxOpCost);
        // The vector accumulator form is used if it is not more expensive than
        // the horizontal reduction on every iteration.
        InstructionCost LoopAccDelta = 0;
        if (LoopAccCandidate && ReductionCost.isValid())
          LoopAccDelta =
              LoopAcc.getCostDelta(HorVecCost, RdxOpCost, RdxFMF,
                                   V.getReductionType(), VL.front()->getType());
        // On a tie the accumulator wins: it also replaces the loop-carried
        // scalar dependency through the horizontal reduction by a lane-wise
        // one. An invalid reduction cost rejects the tree below anyway.
        const bool UseLoopAccForm =
            LoopAccCandidate && ReductionCost.isValid() && LoopAccDelta <= 0;
        // If the root is a select (min/max idiom), the insert point is the
        // compare condition of that select.
        Instruction *RdxRootInst = cast<Instruction>(ReductionRoot);
        Instruction *InsertPt = RdxRootInst;
        if (IsCmpSelMinMax)
          InsertPt = GetCmpForMinMaxReduction(RdxRootInst);
        InstructionCost Cost =
            V.getTreeCost(TreeCost, VL, ReductionCost, InsertPt);
        if (UseLoopAccForm)
          Cost += LoopAccDelta;
        LLVM_DEBUG(dbgs() << "SLP: Found cost = " << Cost
                          << " for reduction\n");
        if (!Cost.isValid())
          break;
        if (Cost >= -V.getCostThreshold()) {
          V.getORE()->emit([&]() {
            return OptimizationRemarkMissed(SV_NAME, "HorSLPNotBeneficial",
                                            ReducedValsToOps.at(VL[0]).front())
                   << "Vectorizing horizontal reduction is possible "
                   << "but not beneficial with cost " << ore::NV("Cost", Cost)
                   << " and threshold "
                   << ore::NV("Threshold", -V.getCostThreshold());
          });
          RejectTree();
          if (!AdjustReducedVals()) {
            MarkAnalyzedVals(VL);
            unsigned Offset = Pos == Start ? Pos : Pos - 1;
            if (ReduxWidth > ReductionLimit && V.isTreeNotExtendable()) {
              // Add subvectors of VL to the list of the analyzed values.
              for (unsigned VF = getFloorFullVectorNumberOfElements(
                       *TTI, VL.front()->getType(), ReduxWidth - 1,
                       Opts.slp_revec);
                   VF >= ReductionLimit;
                   VF = getFloorFullVectorNumberOfElements(
                       *TTI, VL.front()->getType(), VF - 1, Opts.slp_revec)) {
                if (has_single_bit(VF) &&
                    V.getCanonicalGraphSize() != V.getTreeSize())
                  continue;
                for (unsigned Idx : seq<unsigned>(ReduxWidth - VF))
                  IgnoredCandidates.insert(std::make_pair(Offset + Idx, VF));
              }
            }
          }
          continue;
        }

        LLVM_DEBUG(dbgs() << "SLP: Vectorizing horizontal reduction at cost:"
                          << Cost << ". (HorRdx)\n");
        ReductionBudget = Opts.slp_reduction_budget;
        LastRejectedTreeSize = 1;
        NonPowerOf2RejectedSize = 0;
        V.getORE()->emit([&]() {
          return OptimizationRemark(SV_NAME, "VectorizedHorizontalReduction",
                                    ReducedValsToOps.at(VL[0]).front())
                 << "Vectorized horizontal reduction with cost "
                 << ore::NV("Cost", Cost) << " and with tree size "
                 << ore::NV("TreeSize", V.getTreeSize());
        });

        Builder.setFastMathFlags(RdxFMF);

        // Match the bitmask form of the first vector part before the
        // vectorization, which drops the operands of the vectorized leaves.
        BoolBitmask BitmaskMatch =
            VectorValuesAndScales.empty()
                ? isBoolBitmaskRdx(RdxKind, NarrowedLeafShifts, DL)
                : BoolBitmask::None;

        // Vectorize a tree.
        Value *VectorizedRoot = V.vectorizeTree(
            LocalExternallyUsedValues, InsertPt, VectorValuesAndScales);

        if (RK == ReductionOrdering::Ordered) {
          // No need to generate reduction here, emit extractelements instead in
          // the tree vectorizer.
          assert(VectorizedRoot && "Expected vectorized tree");
          // Count vectorized reduced values to exclude them from final
          // reduction.
          for (Value *RdxVal : VL)
            ++VectorizedVals.try_emplace(RdxVal).first->getSecond();
          Pos += ReduxWidth;
          Start = Pos;
          ReduxWidth = NumReducedVals - Pos;
          if (ReduxWidth > 1)
            ReduxWidth = GetVectorFactor(NumReducedVals - Pos);
          AnyVectorized = true;
          VectorizedTree = ReductionRoot;
          continue;
        }
        Builder.SetInsertPoint(InsertPt);

        // To prevent poison from leaking across what used to be sequential,
        // safe, scalar boolean logic operations, the reduction operand must be
        // frozen.
        if (AnyBoolLogicOp && !isGuaranteedNotToBePoison(VectorizedRoot, AC))
          VectorizedRoot = Builder.CreateFreeze(VectorizedRoot);

        // Emit code to correctly handle reused reduced values, if required.
        if (OptReusedScalars && !SameScaleFactor) {
          // The reuse counters are stored in the deduplicated candidates
          // order, but the emitted reduction vector lane order is defined by
          // the root node, which may be reordered, split or have copyable
          // elements. Place each counter at the lane the matching candidate is
          // vectorized to, so the counter is applied to the correct lane.
          ArrayRef<Value *> CandSlice(Candidates.begin() + Pos, ReduxWidth);
          // The lanes, which are not matched to any candidate (e.g. padding),
          // remain nullptr.
          SmallVector<Value *> RootTrackedToOrig(
              getNumElements(VectorizedRoot->getType()));
          for (auto [Idx, Val] : enumerate(CandSlice))
            RootTrackedToOrig[V.findRootLaneForValue(Val)] =
                TrackedToOrig[Pos + Idx];
          VectorizedRoot = emitReusedOps(VectorizedRoot, Builder, V,
                                         SameValuesCounter, RootTrackedToOrig);
        }

        // Mask in the narrow type, then widen and shift per lane. Map back
        // from extractelements to the original reduced values for the shift
        // amounts. The absorbed narrow and-masks and the bits truncated by
        // the absorbed narrow shls are masked off before the widening.
        if (!NarrowedLeafShifts.empty()) {
          Type *WideTy = ReductionRoot->getType();
          Type *NarrowTy = VL.front()->getType();
          unsigned VF = getNumElements(VectorizedRoot->getType());
          // The root may be demoted and resized to the reduction bitwidth,
          // which is computed for the wide reduction operations.
          if (VectorizedRoot->getType()->getScalarType() != NarrowTy) {
            VectorizedRoot = Builder.CreateIntCast(
                VectorizedRoot, getWidenedType(NarrowTy, VF),
                V.isSignedMinBitwidthRootNode());
            ++NumVectorInstructions;
          }
          SmallVector<Constant *> ShiftConsts(VF, ConstantInt::get(WideTy, 0));
          SmallVector<Constant *> MaskConsts(
              VF, Constant::getAllOnesValue(NarrowTy));
          bool AnyShift = false;
          bool AnyMask = false;
          for (auto [Idx, Val] : enumerate(VL)) {
            const NarrowedLeafInfo &L =
                NarrowedLeafShifts.at(TrackedToOrig[Pos + Idx]);
            unsigned Lane = V.findRootLaneForValue(Val);
            ShiftConsts[Lane] = ConstantInt::get(WideTy, L.Shift);
            AnyShift |= L.Shift != 0;
            if (!L.Mask.isAllOnes()) {
              MaskConsts[Lane] = ConstantInt::get(NarrowTy, L.Mask);
              AnyMask = true;
            }
          }
          if (Value *Bitmask = tryEmitBoolBitmaskRdx(
                  Builder, V, *TTI, BitmaskMatch, VectorizedRoot, VL,
                  TrackedToOrig, Pos, MaskConsts, GroupRdxFMF)) {
            VectorizedRoot = Bitmask;
          } else {
            if (AnyMask) {
              VectorizedRoot = Builder.CreateAnd(
                  VectorizedRoot, ConstantVector::get(MaskConsts));
              ++NumVectorInstructions;
            }
            VectorizedRoot =
                Builder.CreateZExt(VectorizedRoot, getWidenedType(WideTy, VF));
            ++NumVectorInstructions;
            if (AnyShift) {
              VectorizedRoot = Builder.CreateShl(
                  VectorizedRoot, ConstantVector::get(ShiftConsts));
              ++NumVectorInstructions;
            }
          }
        }

        Type *ScalarTy = VL.front()->getType();
        Type *VecTy = VectorizedRoot->getType();
        Type *RedScalarTy = VecTy->getScalarType();
        // A group of negated reduced values (from an fsub/fneg in the chain)
        // is subtracted in the final combine.
        VectorValuesAndScales.push_back(
            {VectorizedRoot,
             OptReusedScalars && SameScaleFactor
                 ? SameValuesCounter.front().second
                 : 1,
             RedScalarTy != ScalarTy->getScalarType()
                 ? NarrowedLeafShifts.empty() && V.isSignedMinBitwidthRootNode()
                 : true,
             V.isReducedBitcastRoot() || V.isReducedCmpBitcastRoot() ||
                 !VectorizedRoot->getType()->isVectorTy(),
             GroupNegated});
        LoopAccVectorized = UseLoopAccForm;

        // Count vectorized reduced values to exclude them from final reduction.
        for (const auto [Idx, RdxVal] : enumerate(VL)) {
          Value *OrigV = TrackedToOrig[Pos + Idx];
          if (IsSupportedHorRdxIdentityOp) {
            VectorizedVals.try_emplace(OrigV, At(SameValuesCounter, OrigV));
            continue;
          }
          ++VectorizedVals.try_emplace(OrigV).first->getSecond();
          if (!V.isVectorized(RdxVal))
            RequiredExtract.insert(RdxVal);
        }
        Pos += ReduxWidth;
        Start = Pos;
        ReduxWidth = NumReducedVals - Pos;
        if (ReduxWidth > 1)
          ReduxWidth = GetVectorFactor(NumReducedVals - Pos);
        AnyVectorized = true;
        // All remaining reduced values are the identity: nothing left to
        // vectorize for the accumulator form.
        if (UseLoopAccForm)
          break;
      }
      if (OptReusedScalars && !AnyVectorized) {
        for (const std::pair<Value *, unsigned> &P : SameValuesCounter) {
          Value *RdxVal = TrackedVals.at(P.first);
          Value *RedVal = emitScaleForReusedOps(RdxVal, Builder, P.second);
          AddReducedPart(P.first, RedVal, GroupNegated);
          VectorizedVals.try_emplace(P.first, P.second);
        }
        continue;
      }
    }
    // Early exit for the ordered reductions.
    // No need to do anything else here, so we can just exit.
    if (RK == ReductionOrdering::Ordered) {
      assert(NegatedReducedVals.empty() &&
             "Unexpected negated reduced values in the ordered reduction");
      // Only the root is a dead end, the leaves may still be the roots of the
      // other reductions.
      if (!VectorizedTree)
        V.analyzedReductionRoot(cast<Instruction>(ReductionRoot));
      return VectorizedTree;
    }

    // A booleanized logical and/or reduction has an i1 root and wide integer
    // reduced values; it is performed in the wide type and bit 0 of the
    // result is the final value.
    Type *BoolReduxWideTy =
        getBoolReduxWideTy(RdxKind, ReductionRoot->getType(),
                           ReducedVals.front().front()->getType());
    SmallVector<std::pair<Instruction *, Value *>> LeftoverReductions;
    LoopAcc.collectLeftovers(VectorizedVals, ReducedVals, ReducedValsToOps,
                             LeftoverReductions);

    // The accumulator form requires a single vectorized slice and no
    // leftover reduced values; the latter would have to be folded into the
    // scalar accumulator on every iteration. Otherwise the accumulator phi is
    // folded back on top of the reduction like a leftover.
    Value *AccV = LoopAcc.tryEmit(
        Builder, RdxFMF, LoopAccVectorized, VectorizedTree, LeftoverReductions,
        VectorValuesAndScales, RequiredExtract, ReducedValsToOps, ReductionOps,
        [this, TTI = TTI, &V](Value *Vec, IRBuilderBase &B, Type *Ty) {
          return emitReduction(Vec, B, TTI,
                               V.getCastContextHint(V.getRootNode()), Ty);
        });
    if (AccV)
      VectorizedTree = AccV;
    else if (!VectorValuesAndScales.empty()) {
      Builder.setFastMathFlags(GroupRdxFMF);
      Value *Res = nullptr;
      bool ResNegated = false;
      const ReductionVectorPart &P = VectorValuesAndScales.front();
      // A single fully vectorized booleanized reduction without scalar
      // remainders can be emitted as trunc+bitcast+cmp, if cheaper.
      if (BoolReduxWideTy && !VectorizedTree &&
          VectorValuesAndScales.size() == 1 && !P.ReducedInTree && !P.Negated &&
          isa<FixedVectorType>(P.Vec->getType()) &&
          none_of(ReducedVals, [&](ArrayRef<Value *> Candidates) {
            return any_of(Candidates, [&](Value *RdxVal) {
              return VectorizedVals.lookup(RdxVal) <
                     ReducedValsToOps.at(RdxVal).size();
            });
          }))
        Res = tryEmitBoolReduxBitcastCmp(Builder, *TTI, RdxKind, P.Vec,
                                         ReductionRoot, GroupRdxFMF,
                                         V.getCostKind());
      if (!Res)
        std::tie(Res, ResNegated) = emitReduction(
            Builder, *TTI, V.getCastContextHint(V.getRootNode()),
            BoolReduxWideTy ? BoolReduxWideTy : ReductionRoot->getType());
      Builder.setFastMathFlags(RdxFMF);
      // The reduction result of the all-negated parts is subtracted in the
      // final combine.
      AddReducedPart(/*OrigV=*/nullptr, Res, ResNegated);
    } else if (hasFlattenedNegations()) {
      // The flattened reduction pays off only with a vector part. Without one
      // the scalar chain is merely reshuffled (which may also break the scalar
      // fma formation), while the original code may still be vectorizable as
      // an operand tree - drop the scalar parts emitted so far and give up.
      auto *Root = cast<Instruction>(ReductionRoot);
      for (Instruction *I = Root->getPrevNode(); I && I != InstBeforeRoot;) {
        Instruction *Prev = I->getPrevNode();
        if (I->use_empty() && !V.isAnalyzedReductionRoot(I))
          I->eraseFromParent();
        I = Prev;
      }
      // The fsub/fneg leaves themselves may still form vectorizable groups
      // and the chains behind them are matched as separate reductions - leave
      // the reduction operations unmarked for the retry.
      return nullptr;
    }

    if (!VectorizedTree && NegExtraReductions.empty()) {
      if (!CheckForReusedReductionOps) {
        for (ReductionOpsType &RdxOps : ReductionOps)
          for (Value *RdxOp : RdxOps)
            V.analyzedReductionRoot(cast<Instruction>(RdxOp));
      }
      return nullptr;
    }

    // Reorder operands of bool logical op in the natural order to avoid
    // possible problem with poison propagation. If not possible to reorder
    // (both operands are originally RHS), emit an extra freeze instruction
    // for the LHS operand.
    // I.e., if we have original code like this:
    // RedOp1 = select i1 ?, i1 LHS, i1 false
    // RedOp2 = select i1 RHS, i1 ?, i1 false

    // Then, we swap LHS/RHS to create a new op that matches the poison
    // semantics of the original code.

    // If we have original code like this and both values could be poison:
    // RedOp1 = select i1 ?, i1 LHS, i1 false
    // RedOp2 = select i1 ?, i1 RHS, i1 false

    // Then, we must freeze LHS in the new op.
    auto FixBoolLogicalOps =
        [&, VectorizedTree](Value *&LHS, Value *&RHS, Instruction *RedOp1,
                            Instruction *RedOp2, bool InitStep) {
          if (!AnyBoolLogicOp)
            return;
          if (isBoolLogicOp(RedOp1) && ((!InitStep && LHS == VectorizedTree) ||
                                        getRdxOperand(RedOp1, 0) == LHS ||
                                        isGuaranteedNotToBePoison(LHS, AC)))
            return;
          bool NeedFreeze = LHS != VectorizedTree;
          if (isBoolLogicOp(RedOp2) && ((!InitStep && RHS == VectorizedTree) ||
                                        getRdxOperand(RedOp2, 0) == RHS ||
                                        isGuaranteedNotToBePoison(RHS, AC))) {
            // If RedOp2 was used as a second operand - do not swap.
            if ((InitStep || RHS != VectorizedTree) &&
                getRdxOperand(RedOp2, 0) == RHS &&
                ((isBoolLogicOp(RedOp1) &&
                  getRdxOperand(RedOp1, 1) == RedOp2) ||
                 any_of(ReductionOps, [&](ArrayRef<Value *> Ops) {
                   return any_of(make_isa_range<Instruction>(Ops),
                                 [&](Instruction *OpI) {
                                   return isBoolLogicOp(OpI) &&
                                          getRdxOperand(OpI, 1) == RedOp2;
                                 });
                 }))) {
              NeedFreeze = false;
            } else {
              std::swap(LHS, RHS);
              return;
            }
          }
          if (NeedFreeze)
            LHS = Builder.CreateFreeze(LHS);
        };
    // Leftover narrow values need the same mask/zext/shift as the vectorized
    // ones.
    auto WidenNarrowedVal = [&](Value *OrigV, Value *&V) {
      auto It = NarrowedLeafShifts.find(OrigV);
      if (It == NarrowedLeafShifts.end())
        return;
      if (!It->second.Mask.isAllOnes())
        V = Builder.CreateAnd(V, It->second.Mask);
      V = Builder.CreateZExt(V, ReductionRoot->getType());
      if (It->second.Shift != 0)
        V = Builder.CreateShl(V, It->second.Shift);
    };
    // Finish the reduction.
    // Need to add extra arguments and not vectorized possible reduction values.
    // Try to avoid dependencies between the scalar remainders after reductions.
    auto FinalGen = [&](ArrayRef<std::pair<Instruction *, Value *>> InstVals,
                        bool InitStep) {
      unsigned Sz = InstVals.size();
      SmallVector<std::pair<Instruction *, Value *>> ExtraReds(Sz / 2 + Sz % 2);
      for (unsigned I = 0, E = (Sz / 2) * 2; I < E; I += 2) {
        Instruction *RedOp = InstVals[I + 1].first;
        Builder.SetCurrentDebugLocation(RedOp->getDebugLoc());
        Value *RdxVal1 = InstVals[I].second;
        Value *StableRdxVal1 = RdxVal1;
        auto It1 = TrackedVals.find(RdxVal1);
        if (It1 != TrackedVals.end())
          StableRdxVal1 = It1->second;
        Value *RdxVal2 = InstVals[I + 1].second;
        Value *StableRdxVal2 = RdxVal2;
        auto It2 = TrackedVals.find(RdxVal2);
        if (It2 != TrackedVals.end())
          StableRdxVal2 = It2->second;
        WidenNarrowedVal(RdxVal1, StableRdxVal1);
        WidenNarrowedVal(RdxVal2, StableRdxVal2);
        // To prevent poison from leaking across what used to be sequential,
        // safe, scalar boolean logic operations, the reduction operand must be
        // frozen.
        FixBoolLogicalOps(StableRdxVal1, StableRdxVal2, InstVals[I].first,
                          RedOp, InitStep);
        Value *ExtraRed = createOp(Builder, RdxKind, StableRdxVal1,
                                   StableRdxVal2, "op.rdx", ReductionOps);
        ExtraReds[I / 2] = std::make_pair(InstVals[I].first, ExtraRed);
      }
      if (Sz % 2 == 1)
        ExtraReds[Sz / 2] = InstVals.back();
      return ExtraReds;
    };
    SmallVector<std::pair<Instruction *, Value *>> ExtraReductions;
    if (VectorizedTree)
      ExtraReductions.emplace_back(cast<Instruction>(ReductionRoot),
                                   VectorizedTree);
    for (const auto &[RedOp, RdxVal] : LeftoverReductions)
      (IsNegated(RdxVal) ? NegExtraReductions : ExtraReductions)
          .emplace_back(RedOp, RdxVal);
    // Iterate through all not-vectorized reduction values/extra arguments,
    // combining them pairwise.
    auto CombineReds =
        [&](SmallVectorImpl<std::pair<Instruction *, Value *>> &Reds) {
          bool InitStep = true;
          while (Reds.size() > 1) {
            SmallVector<std::pair<Instruction *, Value *>> NewReds =
                FinalGen(Reds, InitStep);
            Reds.swap(NewReds);
            InitStep = false;
          }
          Value *RdxVal = Reds.front().second;
          auto It = TrackedVals.find(RdxVal);
          if (It != TrackedVals.end())
            RdxVal = It->second;
          return RdxVal;
        };
    VectorizedTree = nullptr;
    if (!ExtraReductions.empty())
      VectorizedTree = CombineReds(ExtraReductions);
    // Combine the subtracted values pairwise as well and subtract the combined
    // value from the positive part of the reduction (or just negate it, if
    // there is no positive part).
    if (!NegExtraReductions.empty()) {
      Value *NegTree = CombineReds(NegExtraReductions);
      Builder.SetCurrentDebugLocation(
          cast<Instruction>(ReductionOps.front().front())->getDebugLoc());
      Value *Op = VectorizedTree
                      ? Builder.CreateFSub(VectorizedTree, NegTree, "op.rdx")
                      : Builder.CreateFNeg(NegTree, "op.rdx");
      propagateIRFlags(Op, ReductionOps.front(), nullptr,
                       /*IncludeWrapFlags=*/false);
      VectorizedTree = Op;
    }

    if (BoolReduxWideTy &&
        VectorizedTree->getType() != ReductionRoot->getType())
      VectorizedTree =
          Builder.CreateTrunc(VectorizedTree, ReductionRoot->getType());
    // The accumulator emission already replaced all uses of the root.
    if (!AccV)
      ReductionRoot->replaceAllUsesWith(VectorizedTree);

    // The original scalar reduction is expected to have no remaining
    // uses outside the reduction tree itself.  Assert that we got this
    // correct, replace internal uses with undef, and mark for eventual
    // deletion.
#ifndef NDEBUG
    SmallPtrSet<Value *, 4> IgnoreSet;
    for (ArrayRef<Value *> RdxOps : ReductionOps)
      IgnoreSet.insert_range(RdxOps);
#endif
    for (ArrayRef<Value *> RdxOps : ReductionOps) {
      for (Value *Ignore :
           make_filter_range(RdxOps, [](Value *Ignore) { return Ignore; })) {
#ifndef NDEBUG
        for (auto *U : Ignore->users()) {
          assert(IgnoreSet.count(U) &&
                 "All users must be either in the reduction ops list.");
        }
#endif
        if (!Ignore->use_empty()) {
          Value *P = PoisonValue::get(Ignore->getType());
          Ignore->replaceAllUsesWith(P);
        }
      }
      V.removeInstructionsAndOperands(RdxOps, VectorValuesAndScales);
    }
    return VectorizedTree;
  }

  /// Attempt to vectorize an ordered (linearized) reduction chain.
  /// Reduced values from matchOrderedReduction() are in accumulation order.
  /// Vectorized subsets are immediately reduced via ordered reduction
  /// intrinsics; non-vectorized values are folded linearly.
  Value *tryToReduceOrdered(BoUpSLP &V, const DataLayout &DL,
                            TargetTransformInfo *TTI,
                            const TargetLibraryInfo &TLI, AssumptionCache *AC,
                            DominatorTree &DT) {
    constexpr unsigned RegMaxNumber = 4;
    constexpr unsigned RedValsMaxNumber = 128;

    assert(RK == ReductionOrdering::Ordered && "Expected ordered reduction");
    assert(ReducedVals.size() == 1 &&
           "Expected single group from matchOrderedReduction");
    assert(NegatedReducedVals.empty() &&
           "Unexpected negated reduced values in the ordered reduction");

    Instruction *RdxRootInst = cast<Instruction>(ReductionRoot);
    IRBuilder<TargetFolder> Builder(RdxRootInst->getIterator(),
                                    TargetFolder(DL));

    // Track the reduced values in case if they are replaced by extractelement
    // because of the vectorization.
    SmallDenseMap<Value *, WeakTrackingVH> TrackedVals(
        ReducedVals.size() * ReducedVals.front().size());
    // Need to track reduced vals, they may be changed during vectorization of
    // subvectors.
    for (ArrayRef<Value *> Candidates : ReducedVals)
      for (Value *V : Candidates)
        TrackedVals.try_emplace(V, V);
    SmallVector<Value *> Candidates(ReducedVals.back());

    // Intersect the fast-math-flags from all reduction operations.
    FastMathFlags RdxFMF;
    RdxFMF.set();
    for (Value *RdxVal : Candidates)
      for (FPMathOperator *FPMO :
           make_isa_range<FPMathOperator>(ReducedValsToOps.at(RdxVal)))
        RdxFMF &= FPMO->getFastMathFlags();
    // This is an ordered reduction, selected because the reduction operations
    // are not associative (e.g. an fadd without nsz). The accumulation order
    // must be preserved, so the generated llvm.vector.reduce.fadd has to stay
    // ordered. Drop 'reassoc' from the flags used to emit and cost the
    // reduction.
    RdxFMF.setAllowReassoc(/*B=*/false);

    unsigned MaxVecRegSize = V.getMaxVecRegSize();
    unsigned EltSize = V.getVectorElementSize(Candidates[0]);
    const unsigned MaxElts =
        std::clamp<unsigned>(llvm::bit_floor(MaxVecRegSize / EltSize),
                             RedValsMaxNumber, RegMaxNumber * RedValsMaxNumber);

    unsigned ReduxWidth = 0;
    auto GetVectorFactor = [&, &TTI = *TTI](unsigned ReduxWidth) {
      Type *ScalarTy = Candidates.front()->getType();
      ReduxWidth = getFloorFullVectorNumberOfElements(TTI, ScalarTy, ReduxWidth,
                                                      Opts.slp_revec);
      Type *Tp = getWidenedType(ScalarTy, ReduxWidth);
      unsigned NumParts = V.getNumberOfParts(Tp, ScalarTy);
      unsigned NumRegs =
          TTI.getNumberOfRegisters(TTI.getRegisterClassForType(true, Tp));
      while (NumParts > NumRegs) {
        assert(ReduxWidth > 0 && "ReduxWidth is unexpectedly 0.");
        ReduxWidth = bit_floor(ReduxWidth - 1);
        Type *Tp = getWidenedType(ScalarTy, ReduxWidth);
        NumParts = V.getNumberOfParts(Tp, ScalarTy);
        NumRegs =
            TTI.getNumberOfRegisters(TTI.getRegisterClassForType(true, Tp));
      }
      if (NumParts > NumRegs / 2)
        ReduxWidth = bit_floor(ReduxWidth);
      return ReduxWidth;
    };
    auto ShrinkReduxWidth = [&]() {
      --ReduxWidth;
      if (ReduxWidth > 1)
        ReduxWidth = GetVectorFactor(ReduxWidth);
    };

    // Try to build, cost-check, and vectorize a window [Start, Start+Width).
    unsigned SuccessStart = 0, SuccessWidth = 0;
    Value *SuccessRoot = nullptr;
    SmallMapVector<Value *, unsigned, 16> EmptySameValuesCounter;
    auto TryWindow = [&](unsigned Start, unsigned Width) -> bool {
      ArrayRef<Value *> VL = ArrayRef(Candidates).slice(Start, Width);
      if (V.areAnalyzedReductionVals(VL))
        return false;
      if (any_of(make_isa_range<Instruction>(VL),
                 [&V](Instruction *RedValI) { return V.isDeleted(RedValI); }))
        return false;

      // Ignore the whole reduction operation chain, not only the ops tied to
      // the current window.
      SmallDenseSet<Value *> IgnoreList;
      for (ReductionOpsType &RdxOps : ReductionOps)
        for (Value *RdxOp : RdxOps)
          if (RdxOp)
            IgnoreList.insert(RdxOp);

      V.buildTree(VL, IgnoreList);
      if (V.isTreeTinyAndNotFullyVectorizable(/*ForReduction=*/true)) {
        V.analyzedReductionVals(VL);
        return false;
      }
      // Do not reorder whole tree to preserve the original order of the ordered
      // reduction.
      V.reorderBottomToTop();

      BoUpSLP::ExtraValueToDebugLocsMap LocalExternallyUsedValues;
      LocalExternallyUsedValues.insert(ReductionRoot);
      for (unsigned Cnt : seq<unsigned>(Candidates.size())) {
        if (Cnt >= Start && Cnt < Start + Width)
          continue;
        if (isa<Instruction>(Candidates[Cnt]))
          LocalExternallyUsedValues.insert(Candidates[Cnt]);
      }

      V.transformNodes();
      V.computeMinimumValueSizes();
      InstructionCost TreeCost =
          V.calculateTreeCostAndTrimNonProfitable(VL, RdxRootInst);
      V.buildExternalUses(LocalExternallyUsedValues);

      InstructionCost VectorCost, RdxOpCost;
      InstructionCost ReductionCost = getReductionCost(
          TTI, VL, /*TrackedToOrig=*/{}, /*Pos=*/0, EmptySameValuesCounter,
          /*IsCmpSelMinMax=*/false, RdxFMF, V, DT, DL, TLI, VectorCost,
          RdxOpCost);
      InstructionCost Cost =
          V.getTreeCost(TreeCost, VL, ReductionCost, RdxRootInst);
      LLVM_DEBUG(dbgs() << "SLP: Found cost = " << Cost
                        << " for ordered reduction\n");
      if (Cost > -V.getCostThreshold() ||
          (Cost == -V.getCostThreshold() && V.getTreeSize() > 1)) {
        if (Cost.isValid())
          V.getORE()->emit([&]() {
            return OptimizationRemarkMissed(SV_NAME, "HorSLPNotBeneficial",
                                            ReducedValsToOps.at(VL[0]).front())
                   << "Vectorizing ordered reduction is possible "
                   << "but not beneficial with cost " << ore::NV("Cost", Cost)
                   << " and threshold "
                   << ore::NV("Threshold", -V.getCostThreshold());
          });
        V.analyzedReductionVals(VL);
        return false;
      }

      LLVM_DEBUG(dbgs() << "SLP: Vectorizing ordered reduction at cost:" << Cost
                        << ". (HorRdx)\n");
      V.getORE()->emit([&]() {
        return OptimizationRemark(SV_NAME, "VectorizedHorizontalReduction",
                                  ReducedValsToOps.at(VL[0]).front())
               << "Vectorized ordered reduction with cost "
               << ore::NV("Cost", Cost) << " and with tree size "
               << ore::NV("TreeSize", V.getTreeSize());
      });

      Builder.setFastMathFlags(RdxFMF);
      SuccessRoot = V.vectorizeTree(LocalExternallyUsedValues, RdxRootInst);
      assert(SuccessRoot && "Expected vectorized tree");
      SuccessStart = Start;
      SuccessWidth = Width;
      return true;
    };

    // Interleaved window search - for each width W (shrinking),
    // try front-anchored [0, W) then back-anchored [N-W, N).
    unsigned N = Candidates.size();
    ReduxWidth = N;
    if (!Opts.slp_vectorize_non_power_of_2 || !has_single_bit(ReduxWidth + 1))
      ReduxWidth = GetVectorFactor(ReduxWidth);
    ReduxWidth = std::min(ReduxWidth, MaxElts);

    while (ReduxWidth >= ReductionLimit) {
      if (TryWindow(0, ReduxWidth))
        break;
      unsigned BackStart = N - ReduxWidth;
      if (BackStart != 0 && TryWindow(BackStart, ReduxWidth))
        break;
      ShrinkReduxWidth();
    }

    if (!SuccessRoot) {
      for (ReductionOpsType &RdxOps : ReductionOps)
        for (Value *RdxOp : RdxOps)
          V.analyzedReductionRoot(cast<Instruction>(RdxOp));
      return nullptr;
    }

    // Fold leading scalars [0, SuccessStart) into an accumulator.
    Type *DestTy = ReductionRoot->getType();
    WeakTrackingVH VectorizedTree = nullptr;
    if (!all_of(RoundedLinks, equal_to(nullptr))) {
      // The round-trip links cannot be expressed by the reduction intrinsic:
      // fold the values into a scalar chain in the original order, extracting
      // the vectorized ones, and re-emit the round-trips between the folded
      // operations. The emitted chain matches the same pattern again, so its
      // operations are marked as analyzed to prevent repeated vectorization.
      for (unsigned Idx : seq<unsigned>(N)) {
        Value *RdxVal = Candidates[Idx];
        Builder.SetCurrentDebugLocation(
            ReducedValsToOps.at(RdxVal).front()->getDebugLoc());
        Value *NextVal = TrackedVals.at(RdxVal);
        if (Idx >= SuccessStart && Idx < SuccessStart + SuccessWidth)
          NextVal =
              Builder.CreateExtractElement(SuccessRoot, Idx - SuccessStart);
        if (!VectorizedTree) {
          VectorizedTree = NextVal;
          continue;
        }
        auto *Op = cast<Instruction>(createOp(Builder, RdxKind, VectorizedTree,
                                              NextVal, "op.rdx", ReductionOps));
        V.analyzedReductionRoot(Op);
        VectorizedTree = Op;
        Instruction *Narrow = RoundedLinks[N - 1 - Idx];
        if (!Narrow)
          continue;
        Instruction *NewNarrow = Narrow->clone();
        NewNarrow->setOperand(0, VectorizedTree);
        Builder.Insert(NewNarrow);
        Instruction *NewWide =
            cast<Instruction>(*Narrow->user_begin())->clone();
        NewWide->setOperand(0, NewNarrow);
        VectorizedTree = Builder.Insert(NewWide);
      }
    } else {
      for (Value *RdxVal : ArrayRef(Candidates).take_front(SuccessStart)) {
        Builder.SetCurrentDebugLocation(
            ReducedValsToOps.at(RdxVal).front()->getDebugLoc());
        if (!VectorizedTree)
          VectorizedTree = TrackedVals.at(RdxVal);
        else
          VectorizedTree =
              createOp(Builder, RdxKind, VectorizedTree, TrackedVals.at(RdxVal),
                       "op.rdx", ReductionOps);
      }

      // Emit ordered reduction for the vectorized window. The reduction only
      // applies to floating point types.
      assert(DestTy->isFPOrFPVectorTy() &&
             SuccessRoot->getType()->isFPOrFPVectorTy() &&
             "Expected floating point types for ordered reduction");
      Builder.SetCurrentDebugLocation(
          cast<Instruction>(ReductionRoot)->getDebugLoc());
      VectorizedTree =
          createSingleOp(Builder, *TTI, V.getCastContextHint(V.getRootNode()),
                         SuccessRoot, /*Scale=*/1,
                         /*IsSigned=*/false, DestTy,
                         /*ReducedInTree=*/false, VectorizedTree);

      // Fold trailing scalars [SuccessStart+SuccessWidth, N).
      for (Value *RdxVal :
           ArrayRef(Candidates).drop_front(SuccessStart + SuccessWidth)) {
        Builder.SetCurrentDebugLocation(
            ReducedValsToOps.at(RdxVal).front()->getDebugLoc());
        VectorizedTree =
            createOp(Builder, RdxKind, VectorizedTree, TrackedVals.at(RdxVal),
                     "op.rdx", ReductionOps);
      }
    }

    ReductionRoot->replaceAllUsesWith(VectorizedTree);

#ifndef NDEBUG
    SmallPtrSet<Value *, 4> IgnoreSet;
    for (ArrayRef<Value *> RdxOps : ReductionOps)
      IgnoreSet.insert_range(RdxOps);
#endif
    for (ArrayRef<Value *> RdxOps : ReductionOps) {
      for (Value *Ignore :
           make_filter_range(RdxOps, [](Value *Ignore) { return Ignore; })) {
#ifndef NDEBUG
        for (auto *U : Ignore->users()) {
          assert(IgnoreSet.count(U) &&
                 "All users must be either in the reduction ops list.");
        }
#endif
        if (!Ignore->use_empty()) {
          Value *P = PoisonValue::get(Ignore->getType());
          Ignore->replaceAllUsesWith(P);
        }
      }
      V.removeInstructionsAndOperands(RdxOps, {});
    }
    return VectorizedTree;
  }

private:
  /// Creates the reduction from the given \p Vec vector value with the given
  /// scale \p Scale and signedness \p IsSigned.
  Value *createSingleOp(IRBuilderBase &Builder, const TargetTransformInfo &TTI,
                        TTI::CastContextHint Ctx, Value *Vec, unsigned Scale,
                        bool IsSigned, Type *DestTy, bool ReducedInTree,
                        Value *Start = nullptr) {
    Value *Rdx;
    if (ReducedInTree) {
      Rdx = Vec;
    } else if (auto *VecTy = dyn_cast<FixedVectorType>(DestTy);
               VecTy && Opts.slp_revec) {
      unsigned DestTyNumElements = getNumElements(VecTy);
      unsigned VF = getNumElements(Vec->getType()) / DestTyNumElements;
      assert(getNumElements(Vec->getType()) % DestTyNumElements == 0 &&
             "Vec element count must be a multiple of DestTy element count");
      // e.g. Consider vector reduce add.
      // Initial reduction is
      // clang-format off
      // %add0 = add <4 x i32> zeroinitializer, %A
      // %add1 = add <4 x i32> %add0, %B
      //
      // where,
      // %A = <a, b, c, d>
      // %B = <e, f, g, h>
      // %add1 = A + B = <a + e, b + f, c + g, d + h>
      //
      // After revectorization with VF=2 and Vec = <a, b, c, d, e, f, g, h>,
      // the reduction can be expressed as:
      // %A = shufflevector <8 x i32> %Vec, <8 x i32> poison, <4 x i32> <i32 0, i32 1, i32 2, i32 3>
      // %B = shufflevector <8 x i32> %Vec, <8 x i32> poison, <4 x i32> <i32 4, i32 5, i32 6, i32 7>
      // %add0 = add <4 x i32> zeroinitializer, %A
      // %add1 = add <4 x i32> %add0, %B
      // clang-format on
      Rdx = Start;
      for (auto I : seq<unsigned>(VF)) {
        auto Position = I * DestTyNumElements;
        Value *SubVec =
            createExtractVector(Builder, Vec, DestTyNumElements, Position);
        if (!Rdx)
          Rdx = SubVec;
        else
          Rdx = createOp(Builder, RdxKind, Rdx, SubVec, "rdx.op", ReductionOps);
      }
    } else {
      Rdx = emitReduction(Vec, Builder, &TTI, Ctx, DestTy, Start);
    }
    if (Rdx->getType() != DestTy)
      Rdx = Builder.CreateIntCast(Rdx, DestTy, IsSigned);
    // Improved analysis for add/fadd/xor reductions with same scale
    // factor for all operands of reductions. We can emit scalar ops for
    // them instead.
    if (Scale > 1)
      Rdx = emitScaleForReusedOps(Rdx, Builder, Scale);
    return Rdx;
  }

  /// The lane order of the zero tests by their bit position, shared between
  /// the cost evaluation and the emission of the boolean bitmask reduction.
  SmallVector<int> getBoolBitmaskPermMask(ArrayRef<Value *> VL,
                                          ArrayRef<Value *> TrackedToOrig,
                                          unsigned Pos,
                                          const BoUpSLP &R) const {
    // Narrowed leaves exist for unordered reductions only, where the tracked
    // original values are always available.
    assert(TrackedToOrig.size() >= Pos + VL.size() &&
           "tracked original values must be available for all reduced values");
    SmallVector<int> PermMask(VL.size(), PoisonMaskElem);
    for (auto [Idx, Val] : enumerate(VL))
      PermMask[NarrowedLeafShifts.at(TrackedToOrig[Pos + Idx]).Shift] =
          R.findRootLaneForValue(Val);
    return PermMask;
  }

  /// Emits the boolean bitmask form of the narrowed-leaf or-reduction (a
  /// bitcast of the per-lane zero tests to an integer) if it covers the whole
  /// reduction in a single vector part and is cheaper than the shift and
  /// reduction sequence. Returns nullptr otherwise.
  Value *tryEmitBoolBitmaskRdx(IRBuilderBase &Builder, const BoUpSLP &R,
                               const TargetTransformInfo &TTI,
                               BoolBitmask Match, Value *VectorizedRoot,
                               ArrayRef<Value *> VL,
                               ArrayRef<Value *> TrackedToOrig, unsigned Pos,
                               ArrayRef<Constant *> MaskConsts,
                               FastMathFlags FMF) const {
    Type *WideTy = ReductionRoot->getType();
    auto *NarrowVecTy = dyn_cast<VectorType>(VectorizedRoot->getType());
    if (!NarrowVecTy)
      return nullptr;
    Type *NarrowTy = NarrowVecTy->getScalarType();
    unsigned VF = getNumElements(NarrowVecTy);
    // Applies only when the whole reduction is a single vector part.
    if (NarrowedLeafShifts.size() != VL.size() || VF != VL.size() ||
        !VectorValuesAndScales.empty() ||
        !R.getRootNode().ReuseShuffleIndices.empty())
      return nullptr;
    if (Match == BoolBitmask::None)
      return nullptr;
    SmallVector<int> PermMask =
        getBoolBitmaskPermMask(VL, TrackedToOrig, Pos, R);
    // Emit the bitmask form only if it is cheaper than the shift and
    // reduction sequence.
    const TTI::TargetCostKind CostKind = R.getCostKind();
    auto *WideVecTy = cast<VectorType>(getWidenedType(WideTy, VF));
    InstructionCost GenericCost =
        TTI.getExtendedReductionCost(Instruction::Or, /*IsUnsigned=*/true,
                                     WideTy, NarrowVecTy, FMF, CostKind) +
        getNarrowedLeafOpsCost(TTI, NarrowedLeafShifts, NarrowVecTy, WideVecTy,
                               cast<Instruction>(ReductionRoot), CostKind);
    if (getBoolBitmaskCost(TTI, Match == BoolBitmask::NeedMask, NarrowTy,
                           WideTy, VF, PermMask, ReductionRoot,
                           CostKind) >= GenericCost)
      return nullptr;
    Value *Vec = VectorizedRoot;
    if (Match == BoolBitmask::NeedMask) {
      Vec = Builder.CreateAnd(Vec, ConstantVector::get(MaskConsts));
      ++NumVectorInstructions;
    }
    // Reorder the lanes by their bit position and pack the zero tests into an
    // integer.
    if (!ShuffleVectorInst::isIdentityMask(PermMask, VF)) {
      Vec = Builder.CreateShuffleVector(Vec, PermMask);
      ++NumVectorInstructions;
    }
    if (!NarrowTy->isIntegerTy(1)) {
      Vec = Builder.CreateICmpNE(Vec, Constant::getNullValue(Vec->getType()));
      ++NumVectorInstructions;
    }
    Vec = Builder.CreateBitCast(Vec, Builder.getIntNTy(VF));
    ++NumVectorInstructions;
    if (Vec->getType() != WideTy) {
      Vec = Builder.CreateIntCast(Vec, WideTy, /*isSigned=*/false);
      ++NumVectorInstructions;
    }
    return Vec;
  }

  /// Calculate the cost of a reduction.
  /// \p VectorCost receives the cost of the emitted vector code alone and
  /// \p RdxOpCost the cost of the reduction operation in it.
  InstructionCost getReductionCost(
      TargetTransformInfo *TTI, ArrayRef<Value *> ReducedVals,
      ArrayRef<Value *> TrackedToOrig, unsigned Pos,
      const SmallMapVector<Value *, unsigned, 16> SameValuesCounter,
      bool IsCmpSelMinMax, FastMathFlags FMF, const BoUpSLP &R,
      DominatorTree &DT, const DataLayout &DL, const TargetLibraryInfo &TLI,
      InstructionCost &VectorCost, InstructionCost &RdxOpCost) {
    const TTI::TargetCostKind CostKind = R.getCostKind();
    Type *ScalarTy = ReducedVals.front()->getType();
    unsigned ReduxWidth = ReducedVals.size();
    FixedVectorType *VectorTy = R.getReductionType();
    InstructionCost ScalarCost;
    VectorCost = 0;
    RdxOpCost = 0;
    // If all of the reduced values are constant, the vector cost is 0, since
    // the reduction value can be calculated at the compile time.
    bool AllConsts = allConstant(ReducedVals);
    // A reduced value may have been replaced by an extractelement while
    // vectorizing a previous subvector of the reduction. Such tracked values
    // are not present in ReducedValsToOps, so look through them to the
    // reduction operation that uses the replaced value.
    auto GetReductionOp = [&](Value *RdxVal) -> Instruction * {
      auto It = ReducedValsToOps.find(RdxVal);
      if (It != ReducedValsToOps.end())
        return It->second.front();
      for (User *U : RdxVal->users())
        // For flattened fadd reductions the reduced value may be consumed by
        // an fsub/fneg chain link instead of an fadd. No reassoc/nsz gating
        // is needed: the result is only a cost context.
        if (getRdxKind(U) == RdxKind ||
            (RdxKind == RecurKind::FAdd &&
             (match(U, m_FSub(m_Value(), m_Value())) ||
              match(U, m_FNeg(m_Value())))))
          return cast<Instruction>(U);
      return cast<Instruction>(RdxVal);
    };
    // The root is accumulated through the phi of its loop.
    const bool IsLoopCarriedRoot =
        RdxKind == RecurKind::FAdd &&
        any_of(ReductionRoot->users(), [&](User *U) {
          auto *Phi = dyn_cast<PHINode>(U);
          return Phi &&
                 DT.dominates(Phi->getParent(),
                              cast<Instruction>(ReductionRoot)->getParent());
        });
    auto EvaluateScalarCost =
        [&](function_ref<InstructionCost(Instruction *)> GenCostFn) {
          InstructionCost Cost = 0;
          // Scalar cost is repeated for N-1 elements.
          int Cnt = ReducedVals.size();
          for (Instruction *RdxVal : make_isa_range<Instruction>(ReducedVals)) {
            Instruction *RdxOp = GetReductionOp(RdxVal);
            if (Cnt == 1) {
              unsigned SameValueCount = SameValuesCounter.lookup(RdxVal);
              // A loop-carried chain removes one operation per reduced value;
              // its last operation, the reduction root, folds the accumulator
              // phi back and is credited by the accumulation cost instead.
              unsigned NumRemoved = SameValueCount ? SameValueCount - 1 : 0;
              if (RdxKind == RecurKind::FAdd && IsLoopCarriedRoot &&
                  RdxOp != ReductionRoot)
                NumRemoved = SameValueCount ? SameValueCount : 1;
              Cost += NumRemoved * GenCostFn(RdxOp);
              break;
            }
            --Cnt;
            if (RdxVal->hasNUsesOrMore(IsCmpSelMinMax ? 3 : 2)) {
              unsigned SameValueCount = SameValuesCounter.lookup(RdxVal);
              Cost += (SameValueCount ? SameValueCount : 1) * GenCostFn(RdxOp);
              continue;
            }
            InstructionCost ScalarCost = 0;
            for (User *U : RdxVal->users()) {
              auto *RdxOp = cast<Instruction>(U);
              // The loop-carried root is not removed: the horizontal form
              // folds the accumulator phi back through it, the accumulator
              // form replaces it with the lane-wise operation, costed by
              // the accumulation cost.
              if (RdxKind == RecurKind::FAdd && RdxOp == ReductionRoot &&
                  IsLoopCarriedRoot)
                continue;
              // The reduction root is used outside of the reduction any
              // number of times, its fmul operand is still fused into it.
              if ((RdxKind == RecurKind::FAdd && RdxOp == ReductionRoot) ||
                  hasRequiredNumberOfUses(IsCmpSelMinMax, RdxOp)) {
                InstructionsState RdxOpS = RdxKind == RecurKind::FAdd
                                               ? getSameOpcode(RdxOp, TLI)
                                               : InstructionsState::invalid();
                // The reduced value itself must be a fusable fmul, whose cost
                // is excluded.
                if (RdxOpS && RdxOpS.isAddSubOrFNegLikeOp() &&
                    isFusableFMulOperand(RdxVal, RdxOp, *TTI)) {
                  InstructionCost FMACost =
                      canConvertToFMA(RdxOp, RdxOpS, DT, DL, *TTI, TLI, R);
                  if (FMACost.isValid()) {
                    LLVM_DEBUG(dbgs() << "FMA cost: " << FMACost << "\n");
                    // Also, exclude scalar fmul cost.
                    InstructionCost FMulCost =
                        TTI->getInstructionCost(RdxVal, CostKind);
                    LLVM_DEBUG(dbgs()
                               << "Minus FMul cost: " << FMulCost << "\n");
                    FMACost -= FMulCost;
                    ScalarCost += FMACost;
                    continue;
                  }
                }
                ScalarCost += TTI->getInstructionCost(RdxOp, CostKind);
                continue;
              }
              ScalarCost = InstructionCost::getInvalid();
              break;
            }
            if (ScalarCost.isValid())
              Cost += ScalarCost;
            else
              Cost += GenCostFn(RdxOp);
          }
          return Cost;
        };
    // Require reduction cost if:
    // 1. This type is not a full register type and no other vectors with the
    // same type in the storage (first vector with small type).
    // 2. The storage does not have any vector with full vector use (first
    // vector with full register use).
    bool DoesRequireReductionOp = !AllConsts && VectorValuesAndScales.empty();
    switch (RdxKind) {
    case RecurKind::Add:
    case RecurKind::Mul:
    case RecurKind::Or:
    case RecurKind::And:
    case RecurKind::Xor:
    case RecurKind::FAdd:
    case RecurKind::FMul: {
      unsigned RdxOpcode = RecurrenceDescriptor::getOpcode(RdxKind);
      Type *BoolReduxWideTy =
          getBoolReduxWideTy(RdxKind, ReductionRoot->getType(), ScalarTy);
      if (!AllConsts) {
        if (!NarrowedLeafShifts.empty()) {
          Type *WideTy = ReductionRoot->getType();
          auto *NarrowVecTy =
              cast<VectorType>(getWidenedType(ScalarTy, ReduxWidth));
          auto *WideVecTy =
              cast<VectorType>(getWidenedType(WideTy, ReduxWidth));
          if (DoesRequireReductionOp) {
            VectorCost = TTI->getExtendedReductionCost(
                RdxOpcode, /*IsUnsigned=*/true, WideTy, NarrowVecTy, FMF,
                CostKind);
          } else {
            VectorCost =
                TTI->getCastInstrCost(Instruction::ZExt, WideVecTy, NarrowVecTy,
                                      TTI::CastContextHint::None, CostKind) +
                TTI->getArithmeticInstrCost(RdxOpcode, WideVecTy, CostKind);
          }
          for (Instruction *I : NarrowedChainInsts)
            VectorCost -= TTI->getInstructionCost(I, CostKind);
          VectorCost += getNarrowedLeafOpsCost(
              *TTI, NarrowedLeafShifts, NarrowVecTy, WideVecTy,
              cast<Instruction>(ReductionRoot), CostKind);
          // The boolean bitmask emission may be cheaper. Restricted to the
          // first vector part, same as in the emission.
          BoolBitmask Match =
              VectorValuesAndScales.empty() &&
                      NarrowedLeafShifts.size() == ReduxWidth &&
                      R.getRootNode().getVectorFactor() == ReduxWidth &&
                      R.getRootNode().ReuseShuffleIndices.empty()
                  ? isBoolBitmaskRdx(RdxKind, NarrowedLeafShifts, DL)
                  : BoolBitmask::None;
          if (Match != BoolBitmask::None) {
            SmallVector<int> PermMask =
                getBoolBitmaskPermMask(ReducedVals, TrackedToOrig, Pos, R);
            InstructionCost BitmaskCost = getBoolBitmaskCost(
                *TTI, Match == BoolBitmask::NeedMask, ScalarTy, WideTy,
                ReduxWidth, PermMask, ReductionRoot, CostKind);
            for (Instruction *I : NarrowedChainInsts)
              BitmaskCost -= TTI->getInstructionCost(I, CostKind);
            VectorCost = std::min(VectorCost, BitmaskCost);
          }
        } else if (DoesRequireReductionOp) {
          if (auto *VecTy = dyn_cast<FixedVectorType>(ScalarTy)) {
            assert(Opts.slp_revec && "FixedVectorType is not expected.");
            unsigned ScalarTyNumElements = VecTy->getNumElements();
            for (unsigned I : seq<unsigned>(ReducedVals.size())) {
              VectorCost +=
                  getShuffleCost(*TTI, TTI::SK_ExtractSubvector, VectorTy,
                                 CostKind, {}, I * ScalarTyNumElements, VecTy);
            }
            // We get one less arithmetic instruction compared to number of
            // reduced values. We are also passing CtxI so that the backend can
            // synthesize FMF from the respective reduction instruction.
            for (unsigned I : seq<unsigned>(ReducedVals.size() - 1)) {
              VectorCost += TTI->getArithmeticInstrCost(
                  RdxOpcode, VecTy, CostKind,
                  TTI::getOperandInfo(ReducedVals[I]),
                  TTI::getOperandInfo(ReducedVals[I + 1]), {},
                  GetReductionOp(ReducedVals[I]));
            }
          } else {
            Type *RedTy = VectorTy->getElementType();
            auto [RType, IsSigned] = R.getRootNodeTypeWithNoCast().value_or(
                std::make_pair(RedTy, true));
            if (BoolReduxWideTy) {
              auto *WideVecTy = cast<FixedVectorType>(
                  getWidenedType(BoolReduxWideTy, ReduxWidth));
              VectorCost = getBoolReduxWideRdxCost(
                  *TTI, RdxKind, WideVecTy, ReductionRoot, FMF, CostKind);
              // The trunc+bitcast+cmp form applies only when the whole
              // reduction is a single vector part, without scalar remainders.
              if (this->ReducedVals.size() == 1 &&
                  ReducedVals.size() == this->ReducedVals.front().size())
                VectorCost = std::min(
                    VectorCost, getBoolReduxBitcastCmpCost(
                                    *TTI, RdxKind, WideVecTy, ReductionRoot,
                                    NarrowedChainInsts, CostKind));
            } else if (RType == RedTy) {
              if (VectorTy->getElementType()->isIntegerTy(1) &&
                  ((ScalarTy->isIntegerTy(1) &&
                    (RdxKind == RecurKind::And || RdxKind == RecurKind::Or)) ||
                   (RdxKind == RecurKind::Add && !ScalarTy->isIntegerTy(1)))) {
                VectorCost =
                    getI1ReductionCost(RdxKind, *TTI, VectorTy, ScalarTy,
                                       R.getCastContextHint(R.getRootNode()),
                                       CostKind)
                        .first;
              } else {
                VectorCost = TTI->getArithmeticReductionCost(
                    RdxOpcode, VectorTy, FMF, CostKind);
              }
            } else {
              VectorCost = TTI->getExtendedReductionCost(
                  RdxOpcode, !IsSigned, RedTy,
                  cast<VectorType>(getWidenedType(RType, ReduxWidth)), FMF,
                  CostKind);
            }
            RdxOpCost = VectorCost;
          }
        } else {
          Type *RedTy = VectorTy->getElementType();
          auto [RType, IsSigned] = R.getRootNodeTypeWithNoCast().value_or(
              std::make_pair(RedTy, true));
          VectorType *RVecTy =
              cast<VectorType>(getWidenedType(RType, ReduxWidth));
          InstructionCost FMACost = InstructionCost::getInvalid();
          if (RdxKind == RecurKind::FAdd) {
            // Check if the reduction operands can be converted to FMA.
            SmallVector<Value *> Ops;
            FastMathFlags FMF;
            FMF.set();
            for (Value *RdxVal : ReducedVals) {
              // The vector fmul fuses only if all the reduced values are
              // fusable fmuls.
              if (!RdxVal->hasOneUse() ||
                  !isFusableFMulOperand(
                      RdxVal, cast<Instruction>(RdxVal->user_back()), *TTI)) {
                Ops.clear();
                break;
              }
              if (auto *FPCI = dyn_cast<FPMathOperator>(RdxVal))
                FMF &= FPCI->getFastMathFlags();
              Ops.push_back(RdxVal->user_back());
            }
            if (!Ops.empty()) {
              InstructionsState S = getSameOpcode(Ops, TLI);
              if (S && S.isAddSubOrFNegLikeOp())
                FMACost = canConvertToFMA(Ops, S, DT, DL, *TTI, TLI, R);
              if (FMACost.isValid()) {
                // Calculate actual FMAD cost.
                IntrinsicCostAttributes ICA(Intrinsic::fmuladd, RVecTy,
                                            {RVecTy, RVecTy, RVecTy}, FMF);
                FMACost = TTI->getIntrinsicInstrCost(ICA, CostKind);

                LLVM_DEBUG(dbgs() << "Vector FMA cost: " << FMACost << "\n");
                // Also, exclude vector fmul cost.
                InstructionCost FMulCost = TTI->getArithmeticInstrCost(
                    Instruction::FMul, RVecTy, CostKind);
                LLVM_DEBUG(dbgs()
                           << "Minus vector FMul cost: " << FMulCost << "\n");
                FMACost -= FMulCost;
              }
            }
          }
          if (FMACost.isValid())
            VectorCost += FMACost;
          else
            VectorCost +=
                TTI->getArithmeticInstrCost(RdxOpcode, RVecTy, CostKind);
          if (RType != RedTy) {
            unsigned Opcode = Instruction::Trunc;
            if (RedTy->getScalarSizeInBits() > RType->getScalarSizeInBits())
              Opcode = IsSigned ? Instruction::SExt : Instruction::ZExt;
            VectorCost += TTI->getCastInstrCost(
                Opcode, VectorTy, RVecTy, TTI::CastContextHint::None, CostKind);
          }
        }
      }
      Type *ScalarCostTy =
          !NarrowedLeafShifts.empty() ? ReductionRoot->getType() : ScalarTy;
      ScalarCost = EvaluateScalarCost([&](Instruction *RdxOp) {
        // A flattened fneg chain link is removed together with the fadd/fsub
        // consuming it - cost both. Also, RdxOp may be the reduced value
        // itself, if the actual reduction operation was not found - guard the
        // second operand access.
        if (RdxOp->isUnaryOp())
          return TTI->getArithmeticInstrCost(
                     RdxOp->getOpcode(), ScalarCostTy, CostKind,
                     TTI::getOperandInfo(RdxOp->getOperand(0)), {}, {}, RdxOp) +
                 TTI->getArithmeticInstrCost(RdxOpcode, ScalarCostTy, CostKind);
        TTI::OperandValueInfo Op2Info;
        if (RdxOp->getNumOperands() > 1)
          Op2Info = TTI::getOperandInfo(RdxOp->getOperand(1));
        return TTI->getArithmeticInstrCost(
            RdxOpcode, ScalarCostTy, CostKind,
            TTI::getOperandInfo(RdxOp->getOperand(0)), Op2Info, {}, RdxOp);
      });
      // Sign-flipped combines are emitted as fsubs but costed as fadds:
      // same op count as the unflattened chain, same cost.
      break;
    }
    case RecurKind::FMax:
    case RecurKind::FMin:
    case RecurKind::FMaximum:
    case RecurKind::FMinimum:
    case RecurKind::SMax:
    case RecurKind::SMin:
    case RecurKind::UMax:
    case RecurKind::UMin: {
      Intrinsic::ID Id = getMinMaxReductionIntrinsicOp(RdxKind);
      if (!AllConsts) {
        if (DoesRequireReductionOp) {
          VectorCost = TTI->getMinMaxReductionCost(Id, VectorTy, FMF, CostKind);
          RdxOpCost = VectorCost;
        } else {
          // Check if the previous reduction already exists and account it as
          // series of operations + single reduction.
          Type *RedTy = VectorTy->getElementType();
          auto [RType, IsSigned] = R.getRootNodeTypeWithNoCast().value_or(
              std::make_pair(RedTy, true));
          VectorType *RVecTy =
              cast<VectorType>(getWidenedType(RType, ReduxWidth));
          IntrinsicCostAttributes ICA(Id, RVecTy, {RVecTy, RVecTy}, FMF);
          VectorCost += TTI->getIntrinsicInstrCost(ICA, CostKind);
          if (RType != RedTy) {
            unsigned Opcode = Instruction::Trunc;
            if (RedTy->getScalarSizeInBits() > RType->getScalarSizeInBits())
              Opcode = IsSigned ? Instruction::SExt : Instruction::ZExt;
            VectorCost += TTI->getCastInstrCost(
                Opcode, VectorTy, RVecTy, TTI::CastContextHint::None, CostKind);
          }
          RdxOpCost = VectorCost;
        }
      }
      ScalarCost = EvaluateScalarCost([&](Instruction *RdxOp) {
        IntrinsicCostAttributes ICA(Id, ScalarTy, {ScalarTy, ScalarTy}, FMF);
        return TTI->getIntrinsicInstrCost(ICA, CostKind);
      });
      break;
    }
    default:
      llvm_unreachable("Expected arithmetic or min/max reduction operation");
    }

    LLVM_DEBUG(dbgs() << "SLP: Adding cost " << VectorCost - ScalarCost
                      << " for reduction of " << shortBundleName(ReducedVals)
                      << " (It is a splitting reduction)\n");
    return VectorCost - ScalarCost;
  }

  /// Splits the values, stored in VectorValuesAndScales, into registers/free
  /// sub-registers, combines them with the given reduction operation as a
  /// vector operation and then performs single (small enough) reduction.
  /// The parts, marked as negated, are combined with the vector fsub operation
  /// (which may form per-lane fma with the multiplications in the reduced
  /// values). \returns the combined value and a flag set if it represents a
  /// negated result (all parts negated) and must be subtracted in the final
  /// combine.
  std::pair<Value *, bool> emitReduction(IRBuilderBase &Builder,
                                         const TargetTransformInfo &TTI,
                                         TTI::CastContextHint Ctx,
                                         Type *DestTy) {
    Value *ReducedSubTree = nullptr;
    bool ResNegated = false;
    // Combines the accumulated value \p Acc (with the sign \p AccNegated)
    // with \p V (with the sign \p VNegated). Values with different signs are
    // combined via fsub, subtracting the negated one from the positive one, so
    // the result is positive. If \p KeepAccSign is set (the result is inserted
    // back into the wider \p Acc), the result keeps the sign of \p Acc
    // instead: with the negated Acc it is Acc - V == -(V - Acc).
    // \returns the combined value and its sign.
    auto CombineOps = [&](Value *Acc, bool AccNegated, Value *V, bool VNegated,
                          const Twine &Name,
                          bool KeepAccSign) -> std::pair<Value *, bool> {
      if (AccNegated == VNegated)
        return {createOp(Builder, RdxKind, Acc, V, Name, ReductionOps),
                AccNegated};
      assert(RdxKind == RecurKind::FAdd &&
             "Negated parts expected in the fadd reductions only");
      if (AccNegated && !KeepAccSign)
        std::swap(Acc, V);
      return {createOp(Builder, RecurKind::FSub, Acc, V, Name, ReductionOps),
              AccNegated && KeepAccSign};
    };
    // Creates reduction and combines with the previous reduction, respecting
    // the signs of the operands.
    auto CreateSingleOp = [&](Value *Vec, unsigned Scale, bool IsSigned,
                              bool ReducedInTree, bool Negated) {
      Value *Rdx = createSingleOp(Builder, TTI, Ctx, Vec, Scale, IsSigned,
                                  DestTy, ReducedInTree);
      if (!ReducedSubTree) {
        ReducedSubTree = Rdx;
        ResNegated = Negated;
        return;
      }
      std::tie(ReducedSubTree, ResNegated) =
          CombineOps(ReducedSubTree, ResNegated, Rdx, Negated, "op.rdx",
                     /*KeepAccSign=*/false);
    };
    if (VectorValuesAndScales.size() == 1) {
      const ReductionVectorPart &P = VectorValuesAndScales.front();
      CreateSingleOp(P.Vec, P.Scale, P.IsSigned, P.ReducedInTree, P.Negated);
      return {ReducedSubTree, ResNegated};
    }
    // Scales Vec using given Cnt scale factor and then performs vector combine
    // with previous value of VecOp.
    Value *VecRes = nullptr;
    bool VecResSignedness = false;
    bool VecResNegated = false;
    auto CreateVecOp = [&](Value *Vec, unsigned Cnt, bool IsSigned,
                           bool ReducedInTree, bool Negated) {
      if (ReducedInTree) {
        CreateSingleOp(Vec, Cnt, IsSigned, ReducedInTree, Negated);
        return;
      }
      Type *ScalarTy = Vec->getType()->getScalarType();
      // Scale Vec using given Cnt scale factor.
      if (Cnt > 1) {
        ElementCount EC = cast<VectorType>(Vec->getType())->getElementCount();
        switch (RdxKind) {
        case RecurKind::Add: {
          if (ScalarTy == Builder.getInt1Ty() && ScalarTy != DestTy) {
            unsigned VF = getNumElements(Vec->getType());
            LLVM_DEBUG(dbgs() << "SLP: ctpop " << Cnt << "of " << Vec
                              << ". (HorRdx)\n");
            SmallVector<int> Mask(Cnt * VF, PoisonMaskElem);
            for (unsigned I : seq<unsigned>(Cnt))
              std::iota(std::next(Mask.begin(), VF * I),
                        std::next(Mask.begin(), VF * (I + 1)), 0);
            ++NumVectorInstructions;
            Vec = Builder.CreateShuffleVector(Vec, Mask);
            break;
          }
          // res = mul vv, n
          if (ScalarTy != DestTy->getScalarType())
            Vec = Builder.CreateIntCast(
                Vec, getWidenedType(DestTy, getNumElements(Vec->getType())),
                IsSigned);
          Value *Scale = ConstantVector::getSplat(
              EC, ConstantInt::get(DestTy->getScalarType(), Cnt));
          LLVM_DEBUG(dbgs() << "SLP: Add (to-mul) " << Cnt << "of " << Vec
                            << ". (HorRdx)\n");
          ++NumVectorInstructions;
          Vec = Builder.CreateMul(Vec, Scale);
          break;
        }
        case RecurKind::Xor: {
          // res = n % 2 ? 0 : vv
          LLVM_DEBUG(dbgs()
                     << "SLP: Xor " << Cnt << "of " << Vec << ". (HorRdx)\n");
          if (Cnt % 2 == 0)
            Vec = Constant::getNullValue(Vec->getType());
          break;
        }
        case RecurKind::FAdd: {
          // res = fmul v, n
          Value *Scale =
              ConstantVector::getSplat(EC, ConstantFP::get(ScalarTy, Cnt));
          LLVM_DEBUG(dbgs() << "SLP: FAdd (to-fmul) " << Cnt << "of " << Vec
                            << ". (HorRdx)\n");
          ++NumVectorInstructions;
          Vec = Builder.CreateFMul(Vec, Scale);
          break;
        }
        case RecurKind::And:
        case RecurKind::Or:
        case RecurKind::SMax:
        case RecurKind::SMin:
        case RecurKind::UMax:
        case RecurKind::UMin:
        case RecurKind::FMax:
        case RecurKind::FMin:
        case RecurKind::FMaximum:
        case RecurKind::FMinimum:
          // res = vv
          break;
        case RecurKind::Sub:
        case RecurKind::FSub:
        case RecurKind::FAddChainWithSubs:
        case RecurKind::AddChainWithSubs:
        case RecurKind::Mul:
        case RecurKind::FMul:
        case RecurKind::FMulAdd:
        case RecurKind::AnyOf:
        case RecurKind::FindIV:
        case RecurKind::FindLast:
        case RecurKind::FMaxNum:
        case RecurKind::FMinNum:
        case RecurKind::FMaximumNum:
        case RecurKind::FMinimumNum:
        case RecurKind::None:
          llvm_unreachable("Unexpected reduction kind for repeated scalar.");
        }
      }
      // Combine Vec with the previous VecOp.
      if (!VecRes) {
        VecRes = Vec;
        VecResSignedness = IsSigned;
        VecResNegated = Negated;
      } else {
        ++NumVectorInstructions;
        if (ScalarTy == Builder.getInt1Ty() && ScalarTy != DestTy &&
            VecRes->getType()->getScalarType() == Builder.getInt1Ty()) {
          // Handle ctpop.
          unsigned VecResVF = getNumElements(VecRes->getType());
          unsigned VecVF = getNumElements(Vec->getType());
          SmallVector<int> Mask(VecResVF + VecVF, PoisonMaskElem);
          std::iota(Mask.begin(), Mask.end(), 0);
          // Ensure that VecRes is always larger than Vec
          if (VecResVF < VecVF) {
            std::swap(VecRes, Vec);
            std::swap(VecResVF, VecVF);
          }
          if (VecResVF != VecVF) {
            SmallVector<int> ResizeMask(VecResVF, PoisonMaskElem);
            std::iota(ResizeMask.begin(), std::next(ResizeMask.begin(), VecVF), 0);
            Vec = Builder.CreateShuffleVector(Vec, ResizeMask);
          }
          VecRes = Builder.CreateShuffleVector(VecRes, Vec, Mask, "rdx.op");
          return;
        }
        if (VecRes->getType()->getScalarType() != DestTy->getScalarType()) {
          assert(getNumElements(VecRes->getType()) % getNumElements(DestTy) ==
                     0 &&
                 "Expected the number of elements in VecRes to be a multiple "
                 "of the number of elements in DestTy");
          VecRes = Builder.CreateIntCast(
              VecRes,
              getWidenedType(DestTy->getScalarType(),
                             getNumElements(VecRes->getType())),
              VecResSignedness);
        }
        if (ScalarTy != DestTy->getScalarType())
          Vec = Builder.CreateIntCast(
              Vec,
              getWidenedType(DestTy->getScalarType(),
                             getNumElements(Vec->getType())),
              IsSigned);
        unsigned VecResVF = getNumElements(VecRes->getType());
        unsigned VecVF = getNumElements(Vec->getType());
        // Ensure that VecRes is always larger than Vec
        if (VecResVF < VecVF) {
          std::swap(VecRes, Vec);
          std::swap(VecResVF, VecVF);
          std::swap(VecResNegated, Negated);
        }
        // extract + op + insert
        Value *Op = VecRes;
        if (VecResVF != VecVF)
          Op = createExtractVector(Builder, VecRes, VecVF, /*Index=*/0);
        std::tie(Op, VecResNegated) =
            CombineOps(Op, VecResNegated, Vec, Negated, "rdx.op",
                       /*KeepAccSign=*/VecResVF != VecVF);
        if (VecResVF != VecVF)
          Op = createInsertVector(Builder, VecRes, Op, /*Index=*/0);
        VecRes = Op;
      }
    };
    // Emit the positive parts first, so the combined vector value stays
    // positive when there is at least one positive part.
    for (bool Negated : {false, true})
      for (const ReductionVectorPart &P : VectorValuesAndScales)
        if (P.Negated == Negated)
          CreateVecOp(P.Vec, P.Scale, P.IsSigned, P.ReducedInTree, P.Negated);
    // All parts may be reduced in the tree already, leaving no vector value
    // to reduce.
    if (VecRes)
      CreateSingleOp(VecRes, /*Scale=*/1, /*IsSigned=*/false,
                     /*ReducedInTree=*/false, VecResNegated);

    return {ReducedSubTree, ResNegated};
  }

  /// Emits an i1 reduction in the cheaper of the plain and the bitcast-based
  /// form. Returns nullptr if not an i1 reduction handled here.
  Value *emitI1Reduction(Value *VectorizedValue, IRBuilderBase &Builder,
                         const TargetTransformInfo &TTI,
                         TTI::CastContextHint Ctx, Type *DestTy, Value *Start) {
    auto *FTy = cast<FixedVectorType>(VectorizedValue->getType());
    bool IsAdd = RdxKind == RecurKind::Add &&
                 DestTy->getScalarType() != FTy->getScalarType();
    bool IsBoolLogic =
        (RdxKind == RecurKind::And || RdxKind == RecurKind::Or) &&
        DestTy->getScalarType() == FTy->getScalarType();
    if (Start || !FTy->getScalarType()->isIntegerTy(1) ||
        (!IsAdd && !IsBoolLogic))
      return nullptr;
    if (getI1ReductionCost(
            RdxKind, TTI, FTy, DestTy->getScalarType(), Ctx,
            getSLPCostKind(Builder.GetInsertBlock()->getParent()))
            .second) {
      // Convert vector_reduce_and/or(<n x i1>) to icmp eq/ne(bitcast <n x i1>
      // to in) and vector_reduce_add(ZExt(<n x i1>)) to
      // ZExtOrTrunc(ctpop(bitcast <n x i1> to in)).
      Value *V = Builder.CreateBitCast(
          VectorizedValue, Builder.getIntNTy(FTy->getNumElements()));
      ++NumVectorInstructions;
      switch (RdxKind) {
      case RecurKind::And:
        return Builder.CreateICmpEQ(V,
                                    ConstantInt::getAllOnesValue(V->getType()));
      case RecurKind::Or:
        return Builder.CreateIsNotNull(V);
      case RecurKind::Add:
        return Builder.CreateUnaryIntrinsic(Intrinsic::ctpop, V);
      default:
        llvm_unreachable("Unexpected reduction kind for the i1 bitcast form");
      }
    }
    if (IsAdd) {
      // Keep the extended vector_reduce_add form.
      VectorizedValue = Builder.CreateZExt(
          VectorizedValue,
          getWidenedType(DestTy->getScalarType(), FTy->getNumElements()));
      ++NumVectorInstructions;
    }
    ++NumVectorInstructions;
    return createSimpleReduction(Builder, VectorizedValue, RdxKind);
  }

  /// Emit a horizontal reduction of the vectorized value.
  /// If \p Start is non-null, emit an ordered reduction intrinsic that
  /// sequentially accumulates into \p Start (only valid for FAdd/FMulAdd).
  Value *emitReduction(Value *VectorizedValue, IRBuilderBase &Builder,
                       const TargetTransformInfo *TTI, TTI::CastContextHint Ctx,
                       Type *DestTy, Value *Start = nullptr) {
    assert(VectorizedValue && "Need to have a vectorized tree node");
    assert(RdxKind != RecurKind::FMulAdd &&
           "A call to the llvm.fmuladd intrinsic is not handled yet");

    if (Value *Rdx =
            emitI1Reduction(VectorizedValue, Builder, *TTI, Ctx, DestTy, Start))
      return Rdx;
    ++NumVectorInstructions;
    if (Start)
      return createOrderedReduction(Builder, RdxKind, VectorizedValue, Start);
    return createSimpleReduction(Builder, VectorizedValue, RdxKind);
  }

  /// Emits optimized code for unique scalar value reused \p Cnt times.
  Value *emitScaleForReusedOps(Value *VectorizedValue, IRBuilderBase &Builder,
                               unsigned Cnt) {
    assert(IsSupportedHorRdxIdentityOp &&
           "The optimization of matched scalar identity horizontal reductions "
           "must be supported.");
    if (Cnt == 1)
      return VectorizedValue;
    switch (RdxKind) {
    case RecurKind::Add: {
      // res = mul vv, n
      Value *Scale =
          ConstantInt::get(VectorizedValue->getType(), Cnt,
                           /*IsSigned=*/false, /*ImplicitTrunc=*/true);
      LLVM_DEBUG(dbgs() << "SLP: Add (to-mul) " << Cnt << "of "
                        << VectorizedValue << ". (HorRdx)\n");
      return Builder.CreateMul(VectorizedValue, Scale);
    }
    case RecurKind::Xor: {
      // res = n % 2 ? 0 : vv
      LLVM_DEBUG(dbgs() << "SLP: Xor " << Cnt << "of " << VectorizedValue
                        << ". (HorRdx)\n");
      if (Cnt % 2 == 0)
        return Constant::getNullValue(VectorizedValue->getType());
      return VectorizedValue;
    }
    case RecurKind::FAdd: {
      // res = fmul v, n
      Value *Scale = ConstantFP::get(VectorizedValue->getType(), Cnt);
      LLVM_DEBUG(dbgs() << "SLP: FAdd (to-fmul) " << Cnt << "of "
                        << VectorizedValue << ". (HorRdx)\n");
      // The mul stands in for a run of the chain operations and joins the
      // same combines, so it carries the flags of the whole chain, except
      // contract: an fma candidate would only block the later vectorization
      // of the scaled value's operands (fma candidates are deferred).
      Value *Mul = createOp(Builder, RecurKind::FMul, VectorizedValue, Scale,
                            "", ReductionOps);
      if (auto *MulI = dyn_cast<Instruction>(Mul))
        MulI->setHasAllowContract(false);
      return Mul;
    }
    case RecurKind::And:
    case RecurKind::Or:
    case RecurKind::SMax:
    case RecurKind::SMin:
    case RecurKind::UMax:
    case RecurKind::UMin:
    case RecurKind::FMax:
    case RecurKind::FMin:
    case RecurKind::FMaximum:
    case RecurKind::FMinimum:
      // res = vv
      return VectorizedValue;
    case RecurKind::Sub:
    case RecurKind::FSub:
    case RecurKind::FAddChainWithSubs:
    case RecurKind::AddChainWithSubs:
    case RecurKind::Mul:
    case RecurKind::FMul:
    case RecurKind::FMulAdd:
    case RecurKind::AnyOf:
    case RecurKind::FindIV:
    case RecurKind::FindLast:
    case RecurKind::FMaxNum:
    case RecurKind::FMinNum:
    case RecurKind::FMaximumNum:
    case RecurKind::FMinimumNum:
    case RecurKind::None:
      llvm_unreachable("Unexpected reduction kind for repeated scalar.");
    }
    return nullptr;
  }

  /// Emits actual operation for the scalar identity values, found during
  /// horizontal reduction analysis.
  Value *
  emitReusedOps(Value *VectorizedValue, IRBuilderBase &Builder, BoUpSLP &R,
                const SmallMapVector<Value *, unsigned, 16> &SameValuesCounter,
                ArrayRef<Value *> TrackedToOrig) {
    assert(IsSupportedHorRdxIdentityOp &&
           "The optimization of matched scalar identity horizontal reductions "
           "must be supported.");
    Type *ScalarTy = R.getRootNodeScalars().front()->getType();
    auto *VTy = cast<FixedVectorType>(VectorizedValue->getType());
    if (VTy->getElementType() != ScalarTy) {
      VectorizedValue = Builder.CreateIntCast(
          VectorizedValue, getWidenedType(ScalarTy, VTy->getNumElements()),
          R.isSignedMinBitwidthRootNode());
    }
    assert(TrackedToOrig.size() == VTy->getNumElements() &&
           "Expected the original value for each lane.");
    // The lanes without the original value (e.g. padding) are kept as is.
    auto GetCount = [&](Value *OrigV) -> unsigned {
      return OrigV ? SameValuesCounter.lookup(OrigV) : 1;
    };
    switch (RdxKind) {
    case RecurKind::Add: {
      // root = mul prev_root, <1, 1, n, 1>
      SmallVector<Constant *> Vals;
      for (Value *OrigV : TrackedToOrig) {
        // The repeat count may not fit the element type (e.g. i1); the
        // modular reduction arithmetic keeps the truncated count equivalent.
        Vals.push_back(ConstantInt::get(
            ScalarTy, APInt(ScalarTy->getIntegerBitWidth(), GetCount(OrigV),
                            /*isSigned=*/false, /*implicitTrunc=*/true)));
      }
      auto *Scale = ConstantVector::get(Vals);
      LLVM_DEBUG(dbgs() << "SLP: Add (to-mul) " << Scale << "of "
                        << VectorizedValue << ". (HorRdx)\n");
      return Builder.CreateMul(VectorizedValue, Scale);
    }
    case RecurKind::And:
    case RecurKind::Or:
      // No need for multiple or/and(s).
      LLVM_DEBUG(dbgs() << "SLP: And/or of same " << VectorizedValue
                        << ". (HorRdx)\n");
      return VectorizedValue;
    case RecurKind::SMax:
    case RecurKind::SMin:
    case RecurKind::UMax:
    case RecurKind::UMin:
    case RecurKind::FMax:
    case RecurKind::FMin:
    case RecurKind::FMaximum:
    case RecurKind::FMinimum:
      // No need for multiple min/max(s) of the same value.
      LLVM_DEBUG(dbgs() << "SLP: Max/min of same " << VectorizedValue
                        << ". (HorRdx)\n");
      return VectorizedValue;
    case RecurKind::Xor: {
      // Replace values with even number of repeats with 0, since
      // x xor x = 0.
      // root = shuffle prev_root, zeroinitalizer, <0, 1, 2, vf, 4, vf, 5, 6,
      // 7>, if elements 4th and 6th elements have even number of repeats.
      SmallVector<int> Mask(
          cast<FixedVectorType>(VectorizedValue->getType())->getNumElements(),
          PoisonMaskElem);
      std::iota(Mask.begin(), Mask.end(), 0);
      bool NeedShuffle = false;
      for (auto [Lane, OrigV] : enumerate(TrackedToOrig)) {
        if (GetCount(OrigV) % 2 == 0) {
          Mask[Lane] = Mask.size();
          NeedShuffle = true;
        }
      }
      LLVM_DEBUG(dbgs() << "SLP: Xor <"; for (int I
                                              : Mask) dbgs()
                                         << I << " ";
                 dbgs() << "> of " << VectorizedValue << ". (HorRdx)\n");
      if (NeedShuffle)
        VectorizedValue = Builder.CreateShuffleVector(
            VectorizedValue,
            ConstantVector::getNullValue(VectorizedValue->getType()), Mask);
      return VectorizedValue;
    }
    case RecurKind::FAdd: {
      // root = fmul prev_root, <1.0, 1.0, n.0, 1.0>
      SmallVector<Constant *> Vals;
      for (Value *OrigV : TrackedToOrig)
        Vals.push_back(ConstantFP::get(ScalarTy, GetCount(OrigV)));
      auto *Scale = ConstantVector::get(Vals);
      return Builder.CreateFMul(VectorizedValue, Scale);
    }
    case RecurKind::Sub:
    case RecurKind::FSub:
    case RecurKind::FAddChainWithSubs:
    case RecurKind::AddChainWithSubs:
    case RecurKind::Mul:
    case RecurKind::FMul:
    case RecurKind::FMulAdd:
    case RecurKind::AnyOf:
    case RecurKind::FindIV:
    case RecurKind::FindLast:
    case RecurKind::FMaxNum:
    case RecurKind::FMinNum:
    case RecurKind::FMaximumNum:
    case RecurKind::FMinimumNum:
    case RecurKind::None:
      llvm_unreachable("Unexpected reduction kind for reused scalars.");
    }
    return nullptr;
  }
};
} // end anonymous namespace

/// Gets recurrence kind from the specified value.
static RecurKind getRdxKind(Value *V) {
  return HorizontalReduction::getRdxKind(V);
}
static void findBuildAggregateRec(Instruction *LastInsertInst,
                                  TargetTransformInfo *TTI,
                                  SmallVectorImpl<Value *> &BuildVectorOpds,
                                  SmallVectorImpl<Value *> &InsertElts,
                                  unsigned OperandOffset, const BoUpSLP &R) {
  do {
    Value *InsertedOperand = LastInsertInst->getOperand(1);
    std::optional<unsigned> OperandIndex =
        getElementIndex(LastInsertInst, OperandOffset);
    if (!OperandIndex || R.isDeleted(LastInsertInst))
      return;
    if (isa<InsertElementInst, InsertValueInst>(InsertedOperand)) {
      findBuildAggregateRec(cast<Instruction>(InsertedOperand), TTI,
                            BuildVectorOpds, InsertElts, *OperandIndex, R);

    } else {
      BuildVectorOpds[*OperandIndex] = InsertedOperand;
      InsertElts[*OperandIndex] = LastInsertInst;
    }
    LastInsertInst = dyn_cast<Instruction>(LastInsertInst->getOperand(0));
  } while (LastInsertInst != nullptr &&
           isa<InsertValueInst, InsertElementInst>(LastInsertInst) &&
           LastInsertInst->hasOneUse());
}

/// Recognize construction of vectors like
///  %ra = insertelement <4 x float> poison, float %s0, i32 0
///  %rb = insertelement <4 x float> %ra, float %s1, i32 1
///  %rc = insertelement <4 x float> %rb, float %s2, i32 2
///  %rd = insertelement <4 x float> %rc, float %s3, i32 3
///  starting from the last insertelement or insertvalue instruction.
///
/// Also recognize homogeneous aggregates like {<2 x float>, <2 x float>},
/// {{float, float}, {float, float}}, [2 x {float, float}] and so on.
/// See llvm/test/Transforms/SLPVectorizer/X86/pr42022.ll for examples.
///
/// Assume LastInsertInst is of InsertElementInst or InsertValueInst type.
///
/// \return true if it matches.
static bool findBuildAggregate(Instruction *LastInsertInst,
                               TargetTransformInfo *TTI,
                               SmallVectorImpl<Value *> &BuildVectorOpds,
                               SmallVectorImpl<Value *> &InsertElts,
                               const BoUpSLP &R) {

  assert((isa<InsertElementInst>(LastInsertInst) ||
          isa<InsertValueInst>(LastInsertInst)) &&
         "Expected insertelement or insertvalue instruction!");

  assert((BuildVectorOpds.empty() && InsertElts.empty()) &&
         "Expected empty result vectors!");

  std::optional<unsigned> AggregateSize = getAggregateSize(LastInsertInst);
  if (!AggregateSize)
    return false;
  BuildVectorOpds.resize(*AggregateSize);
  InsertElts.resize(*AggregateSize);

  findBuildAggregateRec(LastInsertInst, TTI, BuildVectorOpds, InsertElts, 0, R);
  llvm::erase(BuildVectorOpds, nullptr);
  llvm::erase(InsertElts, nullptr);
  if (BuildVectorOpds.size() >= 2)
    return true;

  return false;
}

/// We could have an initial reduction that is not an add.
///  r *= v1 + v2 + v3 + v4
/// In such a case start looking for a tree rooted in the first '+'.
/// \Returns the new root if found, which may be nullptr if not an instruction.
static Instruction *tryGetSecondaryReductionRoot(PHINode *Phi,
                                                 Instruction *Root) {
  assert((isa<BinaryOperator>(Root) || isa<SelectInst>(Root) ||
          isa<IntrinsicInst>(Root)) &&
         "Expected binop, select, or intrinsic for reduction matching");
  Value *LHS =
      Root->getOperand(HorizontalReduction::getFirstOperandIndex(Root));
  Value *RHS =
      Root->getOperand(HorizontalReduction::getFirstOperandIndex(Root) + 1);
  if (LHS == Phi)
    return dyn_cast<Instruction>(RHS);
  if (RHS == Phi)
    return dyn_cast<Instruction>(LHS);
  return nullptr;
}

bool SLPVectorizerPass::vectorizeHorReduction(
    PHINode *P, Instruction *Root, BasicBlock *BB, BoUpSLP &R,
    SmallVectorImpl<WeakTrackingVH> &PostponedInsts) {
  if (!Opts->slp_vectorize_hor)
    return false;
  bool TryOperandsAsNewSeeds = P && isa<BinaryOperator>(Root);

  if (Root->getParent() != BB || isa<PHINode>(Root))
    return false;

  // If we can find a secondary reduction root, use that instead.
  auto SelectRoot = [&]() {
    if (TryOperandsAsNewSeeds && isReductionCandidate(Root) &&
        HorizontalReduction::getRdxKind(Root) != RecurKind::None)
      if (Instruction *NewRoot = tryGetSecondaryReductionRoot(P, Root))
        return NewRoot;
    return Root;
  };

  // Start analysis starting from Root instruction. If horizontal reduction is
  // found, try to vectorize it. If it is not a horizontal reduction or
  // vectorization is not possible or not effective, and currently analyzed
  // instruction is a binary operation, try to vectorize the operands, using
  // pre-order DFS traversal order. If the operands were not vectorized, repeat
  // the same procedure considering each operand as a possible root of the
  // horizontal reduction.
  // Interrupt the process if the Root instruction itself was vectorized or all
  // sub-trees not higher that RecursionMaxDepth were analyzed/vectorized.
  // If a horizintal reduction was not matched or vectorized we collect
  // instructions for possible later attempts for vectorization.
  std::queue<std::pair<Instruction *, unsigned>> Stack;
  Stack.emplace(SelectRoot(), 0);
  SmallPtrSet<Value *, 8> VisitedInstrs;
  bool Res = false;
  auto TryToReduce = [this, &R, TTI = TTI](Instruction *Inst,
                                           bool IsSeedRoot) -> Value * {
    if (R.isAnalyzedReductionRoot(Inst))
      return nullptr;
    if (!isReductionCandidate(Inst))
      return nullptr;
    HorizontalReduction HorRdx(*Opts);
    Value *Res = nullptr;
    if (HorRdx.matchAssociativeReduction(R, Inst, *SE, *DT, *DL, *TTI, *TLI)) {
      Value *Red =
          HorRdx.tryToReduce(R, *DL, TTI, *TLI, AC, *DT, *LI, IsSeedRoot);
      // The chain with the flattened fsub/fneg links produced no vector part:
      // retry with the fsub/fneg links as leaves, they may be vectorizable on
      // their own.
      if (!Red && HorRdx.hasFlattenedNegations()) {
        HorizontalReduction UnflattenedHorRdx(*Opts);
        if (UnflattenedHorRdx.matchAssociativeReduction(
                R, Inst, *SE, *DT, *DL, *TTI, *TLI, /*FlattenNegations=*/false))
          Red = UnflattenedHorRdx.tryToReduce(R, *DL, TTI, *TLI, AC, *DT, *LI,
                                              IsSeedRoot);
      }
      if (Red) {
        if (Red != Inst)
          return Red;
        Res = Red;
      }
    }
    if (HorizontalReduction::isSupportedOrderedReductionOp(Inst)) {
      if (HorRdx.matchOrderedReduction(R, Inst, /*MatchLHS=*/true))
        if (Value *Red =
                HorRdx.tryToReduceOrdered(R, *DL, TTI, *TLI, AC, *DT)) {
          if (Red != Inst)
            return Red;
          Res = Red;
        }
      if (HorRdx.matchOrderedReduction(R, Inst, /*MatchLHS=*/false))
        if (Value *Red = HorRdx.tryToReduceOrdered(R, *DL, TTI, *TLI, AC, *DT))
          return Red;
    }
    return Res;
  };
  auto TryAppendToPostponedInsts = [&](Instruction *FutureSeed) {
    if (TryOperandsAsNewSeeds && FutureSeed == Root) {
      FutureSeed = getNonPhiOperand(Root, P);
      if (!FutureSeed)
        return false;
    }
    // Do not collect CmpInst or InsertElementInst/InsertValueInst as their
    // analysis is done separately.
    if (!isa<CmpInst, InsertElementInst, InsertValueInst>(FutureSeed))
      PostponedInsts.push_back(FutureSeed);
    return true;
  };

  while (!Stack.empty()) {
    Instruction *Inst;
    unsigned Level;
    std::tie(Inst, Level) = Stack.front();
    Stack.pop();
    // Do not try to analyze instruction that has already been vectorized.
    // This may happen when we vectorize instruction operands on a previous
    // iteration while stack was populated before that happened.
    if (R.isDeleted(Inst))
      continue;
    // The minimum-vector-factor allowance applies to single-use seed-level
    // roots only.
    if (Value *VectorizedV =
            TryToReduce(Inst, /*IsSeedRoot=*/Level == 0 && Inst->hasOneUse())) {
      Res = true;
      if (auto *I = dyn_cast<Instruction>(VectorizedV); I && I != Inst) {
        // Try to find another reduction.
        Stack.emplace(I, Level);
        continue;
      }
      if (R.isDeleted(Inst))
        continue;
    } else {
      // We could not vectorize `Inst` so try to use it as a future seed.
      if (!TryAppendToPostponedInsts(Inst)) {
        assert(Stack.empty() && "Expected empty stack");
        break;
      }
    }

    // Try to vectorize operands.
    // Continue analysis for the instruction from the same basic block only to
    // save compile time.
    if (++Level < Opts->slp_recursion_max_depth)
      for (auto *Op : Inst->operand_values())
        if (VisitedInstrs.insert(Op).second)
          if (auto *I = dyn_cast<Instruction>(Op))
            // Do not try to vectorize CmpInst operands,  this is done
            // separately.
            if (!isa<PHINode, CmpInst, InsertElementInst, InsertValueInst>(I) &&
                !R.isDeleted(I) && I->getParent() == BB)
              Stack.emplace(I, Level);
  }
  return Res;
}

bool SLPVectorizerPass::tryToVectorize(
    Instruction *I, BoUpSLP &R, SmallSetVector<Instruction *, 8> &FMACandidates,
    bool AllowFMACandidates) {
  if (!I)
    return false;

  if (!isa<BinaryOperator, CmpInst>(I) || isa<VectorType>(I->getType()))
    return false;
  // Skip potential FMA candidates and collect them for a retry after all
  // blocks of the function have been processed.
  if (!AllowFMACandidates &&
      (I->getOpcode() == Instruction::FAdd ||
       I->getOpcode() == Instruction::FSub) &&
      canConvertToFMA(I, getSameOpcode(I, *TLI), *DT, *DL, *TTI, *TLI, R)
          .isValid()) {
    FMACandidates.insert(I);
    return false;
  }

  Value *P = I->getParent();

  // Vectorize in current basic block only.
  auto *Op0 = dyn_cast<Instruction>(I->getOperand(0));
  auto *Op1 = dyn_cast<Instruction>(I->getOperand(1));
  if (!Op0 || !Op1 || Op0->getParent() != P || Op1->getParent() != P ||
      R.isDeleted(Op0) || R.isDeleted(Op1))
    return false;

  // First collect all possible candidates
  SmallVector<std::pair<Value *, Value *>, 4> Candidates;
  Candidates.emplace_back(Op0, Op1);

  auto *A = dyn_cast<BinaryOperator>(Op0);
  auto *B = dyn_cast<BinaryOperator>(Op1);
  // Try to skip B.
  if (A && B && B->hasOneUse()) {
    auto *B0 = dyn_cast<BinaryOperator>(B->getOperand(0));
    auto *B1 = dyn_cast<BinaryOperator>(B->getOperand(1));
    if (B0 && B0->getParent() == P && !R.isDeleted(B0))
      Candidates.emplace_back(A, B0);
    if (B1 && B1->getParent() == P && !R.isDeleted(B1))
      Candidates.emplace_back(A, B1);
  }
  // Try to skip A.
  if (B && A && A->hasOneUse()) {
    auto *A0 = dyn_cast<BinaryOperator>(A->getOperand(0));
    auto *A1 = dyn_cast<BinaryOperator>(A->getOperand(1));
    if (A0 && A0->getParent() == P && !R.isDeleted(A0))
      Candidates.emplace_back(A0, B);
    if (A1 && A1->getParent() == P && !R.isDeleted(A1))
      Candidates.emplace_back(A1, B);
  }

  auto TryToReduce = [this, &R, &TTI = *TTI](Instruction *Inst,
                                             ArrayRef<Value *> Ops) {
    if (!isReductionCandidate(Inst))
      return false;
    // A 2-element reduction that is just a link in a larger reduction chain
    // or feeds a buildvector is better handled by the whole-chain reduction
    // or buildvector analysis.
    RecurKind Kind = getRdxKind(Inst);
    auto *FPMO = dyn_cast<FPMathOperator>(Inst);
    if (FPMO && !FPMO->hasAllowReassoc() &&
        (any_of(Inst->users(),
                [Kind](User *U) {
                  return getRdxKind(U) == Kind || isa<InsertElementInst>(U);
                }) ||
         any_of(Inst->operands(),
                [Kind](Value *Op) { return getRdxKind(Op) == Kind; })))
      return false;
    Type *Ty = Inst->getType();
    if (!isValidElementType(Ty, Opts->slp_revec) || Ty->isPointerTy())
      return false;
    HorizontalReduction HorRdx(*Opts, Inst, Ops);
    if (!HorRdx.matchReductionForOperands())
      return false;
    // Check the cost of operations.
    auto *VecTy = cast<VectorType>(getWidenedType(Ty, Ops.size()));
    const TTI::TargetCostKind CostKind = R.getCostKind();
    InstructionCost ScalarCost =
        TTI.getScalarizationOverhead(
            VecTy, APInt::getAllOnes(getNumElements(VecTy)), /*Insert=*/false,
            /*Extract=*/true, CostKind) +
        TTI.getInstructionCost(Inst, CostKind);
    // The reduction-only cost cannot price the compared-values tree of i1
    // and/or reductions, so ties are left to the full analysis.
    if (Ty->isIntegerTy(1) &&
        (Kind == RecurKind::And || Kind == RecurKind::Or)) {
      TTI::CastContextHint Ctx =
          all_of(Ops, [](Value *Op) { return isa<LoadInst>(Op); })
              ? TTI::CastContextHint::Normal
              : TTI::CastContextHint::None;
      if (getI1ReductionCost(Kind, TTI, cast<FixedVectorType>(VecTy), Ty, Ctx,
                             CostKind)
              .first > ScalarCost)
        return false;
      return HorRdx.tryToReduce(R, *DL, &TTI, *TLI, AC, *DT, *LI) != nullptr;
    }
    InstructionCost RedCost;
    switch (::getRdxKind(Inst)) {
    case RecurKind::Add:
    case RecurKind::Mul:
    case RecurKind::Or:
    case RecurKind::And:
    case RecurKind::Xor:
    case RecurKind::FAdd:
    case RecurKind::FMul: {
      FastMathFlags FMF;
      if (auto *FPCI = dyn_cast<FPMathOperator>(Inst)) {
        FMF = FPCI->getFastMathFlags();
        // No need to check for associativity, if 2 reduced values.
        if (Ops.size() == 2)
          FMF.setAllowReassoc(true);
      }
      RedCost = TTI.getArithmeticReductionCost(Inst->getOpcode(), VecTy, FMF,
                                               CostKind);
      break;
    }
    default:
      return false;
    }
    if (RedCost >= ScalarCost)
      return false;

    return HorRdx.tryToReduce(R, *DL, &TTI, *TLI, AC, *DT, *LI) != nullptr;
  };
  if (Candidates.size() == 1)
    return TryToReduce(I, {Op0, Op1}) ||
           (!AllowFMACandidates && tryToVectorizeList({Op0, Op1}, R));

  // We have multiple options. Try to pick the single best.
  std::optional<int> BestCandidate = R.findBestRootPair(Candidates).first;
  if (!BestCandidate)
    return false;
  return (*BestCandidate == 0 &&
          TryToReduce(I, {Candidates[*BestCandidate].first,
                          Candidates[*BestCandidate].second})) ||
         (!AllowFMACandidates &&
          tryToVectorizeList({Candidates[*BestCandidate].first,
                              Candidates[*BestCandidate].second},
                             R));
}

bool SLPVectorizerPass::vectorizeRootInstruction(
    PHINode *P, Instruction *Root, BasicBlock *BB, BoUpSLP &R,
    SmallSetVector<Instruction *, 8> &FMACandidates) {
  SmallVector<WeakTrackingVH> PostponedInsts;
  bool Res = vectorizeHorReduction(P, Root, BB, R, PostponedInsts);
  Res |= tryToVectorize(PostponedInsts, R, FMACandidates);
  return Res;
}

bool SLPVectorizerPass::tryToVectorize(
    ArrayRef<WeakTrackingVH> Insts, BoUpSLP &R,
    SmallSetVector<Instruction *, 8> &FMACandidates) {
  bool Res = false;
  for (Value *V : Insts)
    if (auto *Inst = dyn_cast<Instruction>(V); Inst && !R.isDeleted(Inst))
      Res |= tryToVectorize(Inst, R, FMACandidates);
  return Res;
}

/// Vectorizes the aggregate \p IVI, built of the packs of the same layout, as
/// the single vector of all the fields, bitcasted to the vector of the packs.
/// The packs vectorized alone would leave the vectors narrower than possible.
static bool vectorizePackedAggregate(InsertValueInst *IVI, BoUpSLP &R,
                                     TargetTransformInfo &TTI,
                                     const DataLayout &DL) {
  if (!R.Opts.slp_vectorize_hor || R.Opts.slp_revec || DL.isBigEndian() ||
      !R.canMapToVector(IVI->getType()))
    return false;
  SmallVector<Value *, 16> Packs;
  SmallVector<Value *, 16> Inserts;
  if (!findBuildAggregate(IVI, &TTI, Packs, Inserts, R))
    return false;
  // The inserts must form the plain chain, which is moved after the vector.
  BasicBlock *BB = IVI->getParent();
  if (!all_of(Inserts, [&](Value *V) {
        auto *Insert = dyn_cast<InsertValueInst>(V);
        if (!Insert || Insert->getParent() != BB ||
            (Insert != IVI && !(Insert->hasOneUse() &&
                                is_contained(Inserts, Insert->user_back()))))
          return false;
        Value *Agg = Insert->getAggregateOperand();
        return !isa<InsertValueInst>(Agg) || is_contained(Inserts, Agg);
      }))
    return false;

  SmallVector<Value *> Fields;
  SmallVector<Instruction *> Chain;
  for (Value *Pack : Packs) {
    auto *Root = dyn_cast<Instruction>(Pack);
    if (!Root || Root->getParent() != BB ||
        !matchPackedFields(Root, R.Opts.slp_recursion_max_depth, Fields, Chain))
      return false;
  }
  // The pack instructions are dropped, so they must be used by the packs only.
  SmallDenseSet<Value *> IgnoreList;
  IgnoreList.insert_range(Chain);
  if (!all_of(Chain, [&](Instruction *I) {
        return I->getParent() == BB && all_of(I->users(), [&](User *U) {
                 return IgnoreList.contains(U) || is_contained(Inserts, U);
               });
      }))
    return false;
  // Merging the loads into the wider load is better done for each pack.
  if (all_of(Fields, IsaPred<LoadInst>))
    return false;

  // The fields of different types are not vectorized, the tree is empty.
  R.buildTree(Fields, IgnoreList);
  if (R.isTreeTinyAndNotFullyVectorizable(/*ForReduction=*/true))
    return false;
  if (R.isProfitableToReorder()) {
    R.reorderTopToBottom();
    // The root is shuffled back to the order of the fields, its order can be
    // ignored.
    R.reorderBottomToTop(/*IgnoreReorder=*/true);
  }
  R.transformNodes();
  // The fields are not demoted, the bitcast depends on their width.
  InstructionCost TreeCost = R.calculateTreeCostAndTrimNonProfitable(Fields);
  R.buildExternalUses();
  // The gathered operands of the fields are unpacked better for each pack.
  if (R.hasNonConstantGathers())
    return false;
  // The packs take the lanes in the order of the fields.
  SmallVector<int> OrderMask(Fields.size());
  SmallBitVector Seen(Fields.size());
  for (auto [Idx, F] : enumerate(Fields)) {
    unsigned Lane = R.findRootLaneForValue(F);
    if (Lane >= Fields.size() || Seen.test(Lane))
      return false;
    Seen.set(Lane);
    OrderMask[Idx] = Lane;
  }
  const bool IsIdentity =
      ShuffleVectorInst::isIdentityMask(OrderMask, OrderMask.size());

  const TTI::TargetCostKind CostKind = R.getCostKind();
  const unsigned NumPacks = Packs.size();
  Type *FieldsTy = getWidenedType(Fields.front()->getType(), Fields.size());
  Type *PacksTy = getWidenedType(Packs.front()->getType(), NumPacks);
  InstructionCost PackCost =
      TTI.getCastInstrCost(Instruction::BitCast, PacksTy, FieldsTy,
                           TTI::CastContextHint::None, CostKind);
  if (!IsIdentity)
    PackCost += getShuffleCost(TTI, TTI::SK_PermuteSingleSrc,
                               cast<VectorType>(FieldsTy), CostKind, OrderMask);
  PackCost += TTI.getScalarizationOverhead(
      cast<VectorType>(PacksTy), APInt::getAllOnes(NumPacks),
      /*Insert=*/false, /*Extract=*/true, CostKind);
  for (Instruction *I : Chain)
    PackCost -= TTI.getInstructionCost(I, CostKind);
  InstructionCost Cost = R.getTreeCost(TreeCost, Fields, PackCost, IVI);
  LLVM_DEBUG(dbgs() << "SLP: Found cost = " << Cost
                    << " for packed aggregate\n");
  if (!Cost.isValid() || Cost >= -R.getCostThreshold())
    return false;

  Value *Vec = R.vectorizeTree({}, IVI);
  assert(Vec->getType() == FieldsTy && "Expected the vector of the fields.");
  IRBuilder<TargetFolder> Builder(IVI->getIterator(), TargetFolder(DL));
  if (!IsIdentity)
    Vec = Builder.CreateShuffleVector(Vec, OrderMask);
  Value *Packed = Builder.CreateBitCast(Vec, PacksTy);
  for (auto [Idx, Insert] : enumerate(Inserts))
    cast<InsertValueInst>(Insert)->setOperand(
        1, Builder.CreateExtractElement(Packed, Idx));
  // The inserts may precede the vector, move them after the extracts.
  InsertValueInst *Next = IVI;
  while (auto *Prev = dyn_cast<InsertValueInst>(Next->getAggregateOperand())) {
    if (!is_contained(Inserts, Prev))
      break;
    Prev->moveBefore(Next->getIterator());
    Next = Prev;
  }

  R.removeInstructionsAndOperands(ArrayRef(Chain), {});
  return true;
}

bool SLPVectorizerPass::vectorizeInsertValueInst(InsertValueInst *IVI,
                                                 BasicBlock *BB, BoUpSLP &R,
                                                 bool MaxVFOnly) {
  if (!R.canMapToVector(IVI->getType()))
    return false;

  SmallVector<Value *, 16> BuildVectorOpds;
  SmallVector<Value *, 16> BuildVectorInsts;
  if (!findBuildAggregate(IVI, TTI, BuildVectorOpds, BuildVectorInsts, R))
    return false;

  if (MaxVFOnly && BuildVectorOpds.size() == 2) {
    R.getORE()->emit([&]() {
      return OptimizationRemarkMissed(SV_NAME, "NotPossible", IVI)
             << "Cannot SLP vectorize list: only 2 elements of buildvalue, "
                "trying reduction first.";
    });
    return false;
  }
  LLVM_DEBUG(dbgs() << "SLP: array mappable to vector: " << *IVI << "\n");
  // Aggregate value is unlikely to be processed in vector register.
  // Try to vectorize the insertvalue chain itself (rebuilding the aggregate
  // from a vector) only for struct aggregates: getContainedTypes() returns the
  // per-field types for a struct, but returns the aggregate type itself as a
  // single element for arrays and other aggregates, so the size check below
  // fails for them and they fall back to vectorizing the scalar operands.
  // TODO: Extend the vectorized-store path to array aggregates.
  Type *BVType = BuildVectorInsts.front()->getType();
  ArrayRef<Type *> ContainedTypes = getContainedTypes(BVType);
  if (ContainedTypes.size() == BuildVectorInsts.size() &&
      isValidElementType(ContainedTypes.front(), Opts->slp_revec) &&
      all_of(ContainedTypes,
             [&](Type *Ty) { return Ty == ContainedTypes.front(); }))
    if (tryToVectorizeList(BuildVectorInsts, R, MaxVFOnly))
      return true;
  return tryToVectorizeList(BuildVectorOpds, R, MaxVFOnly);
}

bool SLPVectorizerPass::vectorizeInsertElementInst(InsertElementInst *IEI,
                                                   BasicBlock *BB, BoUpSLP &R,
                                                   bool MaxVFOnly) {
  SmallVector<Value *, 16> BuildVectorInsts;
  SmallVector<Value *, 16> BuildVectorOpds;
  SmallVector<int> Mask;
  if (!findBuildAggregate(IEI, TTI, BuildVectorOpds, BuildVectorInsts, R) ||
      (all_of(BuildVectorOpds, IsaPred<ExtractElementInst, UndefValue>) &&
       isFixedVectorShuffle(BuildVectorOpds, Mask, AC, R.getAnalysisCache())))
    return false;

  if (MaxVFOnly && BuildVectorInsts.size() == 2) {
    R.getORE()->emit([&]() {
      return OptimizationRemarkMissed(SV_NAME, "NotPossible", IEI)
             << "Cannot SLP vectorize list: only 2 elements of buildvector, "
                "trying reduction first.";
    });
    return false;
  }
  LLVM_DEBUG(dbgs() << "SLP: array mappable to vector: " << *IEI << "\n");
  return tryToVectorizeList(BuildVectorInsts, R, MaxVFOnly);
}

template <typename T>
static bool tryToVectorizeSequence(
    const VectorizeOptions &Opts, SmallVectorImpl<T *> &Incoming,
    function_ref<bool(T *, T *)> Comparator,
    function_ref<bool(ArrayRef<T *>, T *)> AreCompatible,
    function_ref<bool(ArrayRef<T *>, bool)> TryToVectorizeHelper,
    bool MaxVFOnly, BoUpSLP &R,
    function_ref<bool(ArrayRef<T *>)> Filter = nullptr) {
  bool Changed = false;
  // Sort by type, parent, operands.
  stable_sort(Incoming, Comparator);

  // Try to vectorize elements base on their type.
  SmallVector<T *> Candidates;
  SmallVector<T *> VL;
  for (auto *IncIt = Incoming.begin(), *E = Incoming.end(); IncIt != E;
       VL.clear()) {
    // Look for the next elements with the same type, parent and operand
    // kinds.
    auto *I = dyn_cast<Instruction>(*IncIt);
    if (!I || R.isDeleted(I) ||
        !isValidElementType(getValueType(I, Opts.slp_revec), Opts.slp_revec)) {
      ++IncIt;
      continue;
    }
    auto *SameTypeIt = IncIt;
    while (SameTypeIt != E && (!isa<Instruction>(*SameTypeIt) ||
                               R.isDeleted(cast<Instruction>(*SameTypeIt)) ||
                               AreCompatible(VL, *SameTypeIt))) {
      auto *I = dyn_cast<Instruction>(*SameTypeIt);
      ++SameTypeIt;
      if (I && !R.isDeleted(I))
        VL.push_back(cast<T>(I));
    }

    // Rejected groups are dropped, not left among the candidates.
    if (Filter && !Filter(ArrayRef(VL)))
      VL.clear();

    // Try to vectorize them.
    unsigned NumElts = VL.size();
    LLVM_DEBUG(dbgs() << "SLP: Trying to vectorize starting at nodes ("
                      << NumElts << ")\n");
    // The vectorization is a 3-state attempt:
    // 1. Try to vectorize instructions with the same/alternate opcodes with the
    // size of maximal register at first.
    // 2. Try to vectorize remaining instructions with the same type, if
    // possible. This may result in the better vectorization results rather than
    // if we try just to vectorize instructions with the same/alternate opcodes.
    // 3. Final attempt to try to vectorize all instructions with the
    // same/alternate ops only, this may result in some extra final
    // vectorization.
    if (NumElts > 1 && TryToVectorizeHelper(ArrayRef(VL), MaxVFOnly)) {
      // Success start over because instructions might have been changed.
      Changed = true;
      VL.swap(Candidates);
      Candidates.clear();
      for (T *V : VL) {
        if (auto *I = dyn_cast<Instruction>(V); I && !R.isDeleted(I))
          Candidates.push_back(V);
      }
    } else {
      /// \Returns the minimum number of elements that we will attempt to
      /// vectorize.
      auto GetMinNumElements = [&R](Value *V) {
        unsigned EltSize = R.getVectorElementSize(V);
        return std::max(2U, R.getMaxVecRegSize() / EltSize);
      };
      if (NumElts < GetMinNumElements(*IncIt) &&
          (Candidates.empty() ||
           Candidates.front()->getType() == (*IncIt)->getType())) {
        for (T *V : VL) {
          if (auto *I = dyn_cast<Instruction>(V); I && !R.isDeleted(I))
            Candidates.push_back(V);
        }
      }
    }
    // Final attempt to vectorize instructions with the same types.
    if (Candidates.size() > 1 &&
        (SameTypeIt == E || (*SameTypeIt)->getType() != (*IncIt)->getType())) {
      if (TryToVectorizeHelper(Candidates, /*MaxVFOnly=*/false)) {
        // Success start over because instructions might have been changed.
        Changed = true;
      } else if (MaxVFOnly) {
        // Try to vectorize using small vectors.
        SmallVector<T *> VL;
        for (auto *It = Candidates.begin(), *End = Candidates.end(); It != End;
             VL.clear()) {
          auto *I = dyn_cast<Instruction>(*It);
          if (!I || R.isDeleted(I)) {
            ++It;
            continue;
          }
          auto *SameTypeIt = It;
          while (SameTypeIt != End &&
                 (!isa<Instruction>(*SameTypeIt) ||
                  R.isDeleted(cast<Instruction>(*SameTypeIt)) ||
                  AreCompatible(*SameTypeIt, *It))) {
            auto *I = dyn_cast<Instruction>(*SameTypeIt);
            ++SameTypeIt;
            if (I && !R.isDeleted(I))
              VL.push_back(cast<T>(I));
          }
          unsigned NumElts = VL.size();
          if (NumElts > 1 && TryToVectorizeHelper(ArrayRef(VL),
                                                  /*MaxVFOnly=*/false))
            Changed = true;
          It = SameTypeIt;
        }
      }
      Candidates.clear();
    }

    // Start over at the next instruction of a different type (or the end).
    IncIt = SameTypeIt;
  }
  return Changed;
}

/// Compare two cmp instructions. If IsCompatibility is true, function returns
/// true if 2 cmps have same/swapped predicates and mos compatible corresponding
/// operands. If IsCompatibility is false, function implements strict weak
/// ordering relation between two cmp instructions, returning true if the first
/// instruction is "less" than the second, i.e. its predicate is less than the
/// predicate of the second or the operands IDs are less than the operands IDs
/// of the second cmp instruction.
template <bool IsCompatibility>
static bool compareCmp(const VectorizeOptions &Opts, Value *V, Value *V2,
                       TargetLibraryInfo &TLI, const DominatorTree &DT) {
  assert(isValidElementType(V->getType(), Opts.slp_revec) &&
         isValidElementType(V2->getType(), Opts.slp_revec) &&
         "Expected valid element types only.");
  if (V == V2)
    return IsCompatibility;
  auto *CI1 = cast<CmpInst>(V);
  auto *CI2 = cast<CmpInst>(V2);
  if (CI1->getOperand(0)->getType()->getTypeID() <
      CI2->getOperand(0)->getType()->getTypeID())
    return !IsCompatibility;
  if (CI1->getOperand(0)->getType()->getTypeID() >
      CI2->getOperand(0)->getType()->getTypeID())
    return false;
  if (CI1->getOperand(0)->getType()->getScalarSizeInBits() <
      CI2->getOperand(0)->getType()->getScalarSizeInBits())
    return !IsCompatibility;
  if (CI1->getOperand(0)->getType()->getScalarSizeInBits() >
      CI2->getOperand(0)->getType()->getScalarSizeInBits())
    return false;
  CmpInst::Predicate Pred1 = CI1->getPredicate();
  CmpInst::Predicate Pred2 = CI2->getPredicate();
  CmpInst::Predicate SwapPred1 = CmpInst::getSwappedPredicate(Pred1);
  CmpInst::Predicate SwapPred2 = CmpInst::getSwappedPredicate(Pred2);
  CmpInst::Predicate BasePred1 = std::min(Pred1, SwapPred1);
  CmpInst::Predicate BasePred2 = std::min(Pred2, SwapPred2);
  if (BasePred1 < BasePred2)
    return !IsCompatibility;
  if (BasePred1 > BasePred2)
    return false;
  // Compare operands.
  bool CI1Preds = Pred1 == BasePred1;
  bool CI2Preds = Pred2 == BasePred1;
  for (int I = 0, E = CI1->getNumOperands(); I < E; ++I) {
    auto *Op1 = CI1->getOperand(CI1Preds ? I : E - I - 1);
    auto *Op2 = CI2->getOperand(CI2Preds ? I : E - I - 1);
    if (Op1 == Op2)
      continue;
    if (Op1->getValueID() < Op2->getValueID())
      return !IsCompatibility;
    if (Op1->getValueID() > Op2->getValueID())
      return false;
    if (auto *I1 = dyn_cast<Instruction>(Op1))
      if (auto *I2 = dyn_cast<Instruction>(Op2)) {
        if (IsCompatibility) {
          if (I1->getParent() != I2->getParent())
            return false;
        } else {
          // Try to compare nodes with same parent.
          DomTreeNodeBase<BasicBlock> *NodeI1 = DT.getNode(I1->getParent());
          DomTreeNodeBase<BasicBlock> *NodeI2 = DT.getNode(I2->getParent());
          if (!NodeI1)
            return NodeI2 != nullptr;
          if (!NodeI2)
            return false;
          assert((NodeI1 == NodeI2) ==
                     (NodeI1->getDFSNumIn() == NodeI2->getDFSNumIn()) &&
                 "Different nodes should have different DFS numbers");
          if (NodeI1 != NodeI2)
            return NodeI1->getDFSNumIn() < NodeI2->getDFSNumIn();
        }
        InstructionsState S = getSameOpcode({I1, I2}, TLI);
        if (S && (IsCompatibility || !S.isAltShuffle()))
          continue;
        if (IsCompatibility)
          return false;
        if (I1->getOpcode() != I2->getOpcode())
          return I1->getOpcode() < I2->getOpcode();
      }
  }
  return IsCompatibility;
}

template <typename ItT>
bool SLPVectorizerPass::vectorizeCmpInsts(
    iterator_range<ItT> CmpInsts, BasicBlock *BB, BoUpSLP &R,
    SmallSetVector<Instruction *, 8> &FMACandidates) {
  bool Changed = false;
  // Try to find reductions first.
  for (CmpInst *I : make_filter_range(
           CmpInsts, [&](CmpInst *I) { return !R.isDeleted(I); })) {
    for (Instruction *RootOp : make_isa_range<Instruction>(I->operands())) {
      Changed |=
          vectorizeRootInstruction(nullptr, RootOp, BB, R, FMACandidates);
      if (R.isDeleted(I))
        break;
    }
  }
  // Try to vectorize operands as vector bundles.
  for (CmpInst *I :
       make_filter_range(CmpInsts, [&](CmpInst *I) { return !R.isDeleted(I); }))
    Changed |= tryToVectorize(I, R, FMACandidates);
  // Try to vectorize list of compares.
  // Sort by type, compare predicate, etc.
  auto CompareSorter = [&](Value *V, Value *V2) {
    if (V == V2)
      return false;
    return compareCmp<false>(*Opts, V, V2, *TLI, *DT);
  };

  auto AreCompatibleCompares = [&](ArrayRef<Value *> VL, Value *V1) {
    if (VL.empty() || VL.back() == V1)
      return true;
    return compareCmp<true>(*Opts, V1, VL.back(), *TLI, *DT);
  };

  SmallVector<Value *> Vals;
  for (Instruction *V : CmpInsts)
    if (!R.isDeleted(V) &&
        isValidElementType(
            getValueType(V, Opts->slp_revec, /*LookThroughCmp=*/true),
            Opts->slp_revec))
      Vals.push_back(V);
  if (Vals.size() <= 1)
    return Changed;
  Changed |= tryToVectorizeSequence<Value>(
      *Opts, Vals, CompareSorter, AreCompatibleCompares,
      [this, &R](ArrayRef<Value *> Candidates, bool MaxVFOnly) {
        // Exclude possible reductions from other blocks.
        bool ArePossiblyReducedInOtherBlock = any_of(Candidates, [](Value *V) {
          return any_of(V->users(), [V](User *U) {
            auto *Select = dyn_cast<SelectInst>(U);
            return Select &&
                   Select->getParent() != cast<Instruction>(V)->getParent();
          });
        });
        if (ArePossiblyReducedInOtherBlock)
          return false;
        return tryToVectorizeList(Candidates, R, MaxVFOnly);
      },
      /*MaxVFOnly=*/true, R);
  return Changed;
}

/// Returns true if \p I is an instruction whose result the SLP vectorizer
/// cannot turn into a vector instruction directly, but whose operand chains
/// may still be worth vectorizing as bundle seeds.
static bool isNonVectorizableInst(const VectorizeOptions &Opts,
                                  const Instruction *I,
                                  const TargetLibraryInfo *TLI) {
  if (const auto *CB = dyn_cast<CallBase>(I)) {
    if (CB->isInlineAsm())
      return false;
    if (const auto *II = dyn_cast<IntrinsicInst>(CB)) {
      if (II->isAssumeLikeIntrinsic())
        return false;
      if (isa<AnyMemIntrinsic>(II))
        return false;
    }
    if (const auto *CI = dyn_cast<CallInst>(CB)) {
      Intrinsic::ID ID = getVectorIntrinsicIDForCall(CI, TLI);
      if (isTriviallyVectorizable(ID))
        return false;
      if (!VFDatabase::getMappings(*CI).empty())
        return false;
      if (all_of(make_isa_range<Instruction>(CI->args()),
                 [](const Instruction *Arg) {
                   return Arg->getType()->isPointerTy();
                 }))
        return false;
      if (any_of(CI->args(), [](const Value *Arg) {
            return Arg->getType()->isPointerTy();
          }))
        return false;
    }
    // Skip vector-returning calls in non-revec mode - we cannot turn their
    // results into wider vectors here.
    return Opts.slp_revec || !CB->getType()->isVectorTy();
  }
  if (isa<AtomicRMWInst, AtomicCmpXchgInst>(I))
    return true;
  if (const auto *EV = dyn_cast<ExtractValueInst>(I)) {
    const auto *Arg = EV->getAggregateOperand();
    if (const auto *CI = dyn_cast<CallInst>(Arg)) {
      Intrinsic::ID ID = getVectorIntrinsicIDForCall(CI, TLI);
      if (isTriviallyVectorizable(ID))
        return true;
      if (!VFDatabase::getMappings(*CI).empty())
        return true;
      return false;
    }
  }
  if (const auto *RI = dyn_cast<ReturnInst>(I))
    return RI->getNumOperands() > 0 &&
           (Opts.slp_revec || !I->getOperand(0)->getType()->isVectorTy()) &&
           isa<Instruction>(I->getOperand(0));
  return false;
}

/// Visits the value operands of \p I that are candidates for operand-chain
/// vectorization.
template <typename Func>
static void forEachOperandChainCandidate(const VectorizeOptions &Opts,
                                         Instruction *I, Func F,
                                         bool ForReduction) {
  if (auto *CB = dyn_cast<CallBase>(I)) {
    if (ForReduction && !Opts.slp_non_vectorizables_as_reductions &&
        CB->arg_size() > 1)
      return;
    for (auto [Idx, U] : enumerate(CB->args()))
      F(U.get(), Idx);
    return;
  }
  if (auto *AI = dyn_cast<AtomicRMWInst>(I)) {
    F(AI->getValOperand(), 0);
    return;
  }
  if (auto *AI = dyn_cast<AtomicCmpXchgInst>(I)) {
    F(AI->getCompareOperand(), 0);
    F(AI->getNewValOperand(), 1);
    return;
  }
  if (auto *EV = dyn_cast<ExtractValueInst>(I)) {
    F(EV->getAggregateOperand(), 0);
    return;
  }
  if (ForReduction && !Opts.slp_non_vectorizables_as_reductions)
    return;
  if (auto *SI = dyn_cast<StoreInst>(I)) {
    F(SI->getValueOperand(), 0);
    return;
  }
  if (auto *RI = dyn_cast<ReturnInst>(I)) {
    if (RI->getNumOperands() > 0)
      F(RI->getReturnValue(), 0);
    return;
  }
  llvm_unreachable("Unexpected instruction kind for operand-chain seeding");
}

template <typename ItT>
bool SLPVectorizerPass::vectorizeNonVectorizableInsts(
    iterator_range<ItT> InstRange, BasicBlock *BB, BoUpSLP &R,
    SmallSetVector<Instruction *, 8> &FMACandidates) {
  SmallVector<Instruction *> Insts(InstRange);
  if (Insts.empty())
    return false;
  stable_sort(Insts, [](const Instruction *A, const Instruction *B) {
    return A->getOpcode() < B->getOpcode();
  });

  bool Changed = false;
  // Pass 1 - try to find horizontal reductions feeding the root operands.
  SmallPtrSet<Value *, 8> RootSeen;
  for (Instruction *I : make_filter_range(
           Insts, [&](Instruction *I) { return !R.isDeleted(I); })) {
    bool RootDeleted = false;
    forEachOperandChainCandidate(
        *Opts, I,
        [&](Value *Op, unsigned /*Position*/) {
          if (RootDeleted)
            return;
          auto *RootOp = dyn_cast<Instruction>(Op);
          if (!RootOp || RootOp->getParent() != BB || R.isDeleted(RootOp) ||
              isa<ShuffleVectorInst>(RootOp) ||
              !isValidElementType(RootOp->getType(), Opts->slp_revec))
            return;
          if (!RootSeen.insert(RootOp).second)
            return;
          Changed |=
              vectorizeRootInstruction(nullptr, RootOp, BB, R, FMACandidates);
          if (R.isDeleted(I))
            RootDeleted = true;
        },
        /*ForReduction=*/true);
  }
  // Pass 2 - collect the operand instructions across all roots and try to
  // vectorize them as bundles.
  if (Insts.size() < 2)
    return Changed;
  struct OperandGroupKey {
    enum class Kind : unsigned {
      NonCall = 0,
      Intrinsic,
      NamedFunction,
      IndirectCall,
    };
    Kind RootKind;
    unsigned KindID;    // Intrinsic ID for Intrinsic, opcode for NonCall,
                        // callee value-kind for IndirectCall, 0 for
                        // NamedFunction.
    unsigned SubOp;     // AtomicRMW operation; 0 otherwise.
    StringRef FuncName; // Non-empty only for NamedFunction.
    unsigned Position;  // Operand slot within the root.

    bool operator==(const OperandGroupKey &O) const {
      return RootKind == O.RootKind && KindID == O.KindID && SubOp == O.SubOp &&
             FuncName == O.FuncName && Position == O.Position;
    }
    bool operator!=(const OperandGroupKey &O) const { return !(*this == O); }
    bool less(const OperandGroupKey &O) const {
      if (RootKind != O.RootKind)
        return static_cast<unsigned>(RootKind) <
               static_cast<unsigned>(O.RootKind);
      if (KindID != O.KindID)
        return KindID < O.KindID;
      if (SubOp != O.SubOp)
        return SubOp < O.SubOp;
      if (int C = FuncName.compare(O.FuncName))
        return C < 0;
      return Position < O.Position;
    }
  };
  SmallDenseMap<Value *, OperandGroupKey> OpKeys;

  auto BuildKey = [](Instruction *I, unsigned Position) -> OperandGroupKey {
    if (auto *CB = dyn_cast<CallBase>(I)) {
      if (auto *II = dyn_cast<IntrinsicInst>(CB))
        return {OperandGroupKey::Kind::Intrinsic,
                II->getIntrinsicID(),
                0,
                {},
                Position};
      if (Function *F = CB->getCalledFunction())
        return {OperandGroupKey::Kind::NamedFunction, 0, 0, F->getName(),
                Position};
      return {OperandGroupKey::Kind::IndirectCall,
              CB->getCalledOperand()->getValueID(),
              0,
              {},
              Position};
    }
    unsigned SubOp = 0;
    if (auto *AI = dyn_cast<AtomicRMWInst>(I))
      SubOp = static_cast<unsigned>(AI->getOperation());
    return {
        OperandGroupKey::Kind::NonCall, I->getOpcode(), SubOp, {}, Position};
  };

  auto OperandSorter = [&OpKeys](Value *V1, Value *V2) -> bool {
    if (V1 == V2)
      return false;
    const OperandGroupKey &K1 = OpKeys.at(V1);
    const OperandGroupKey &K2 = OpKeys.at(V2);
    if (K1 != K2)
      return K1.less(K2);
    auto *I1 = cast<Instruction>(V1);
    auto *I2 = cast<Instruction>(V2);
    if (I1->getType()->getTypeID() != I2->getType()->getTypeID())
      return I1->getType()->getTypeID() < I2->getType()->getTypeID();
    if (I1->getType()->getScalarSizeInBits() !=
        I2->getType()->getScalarSizeInBits())
      return I1->getType()->getScalarSizeInBits() <
             I2->getType()->getScalarSizeInBits();
    if (I1->getOpcode() != I2->getOpcode())
      return I1->getOpcode() < I2->getOpcode();
    return I1->comesBefore(I2);
  };

  auto AreCompatibleOperands = [&OpKeys](ArrayRef<Value *> VL,
                                         Value *V) -> bool {
    if (VL.empty() || VL.back() == V)
      return true;
    const OperandGroupKey &KBack = OpKeys.at(VL.back());
    const OperandGroupKey &K = OpKeys.at(V);
    if (KBack != K)
      return false;
    auto *I1 = cast<Instruction>(VL.back());
    auto *I2 = cast<Instruction>(V);
    return I1->getType() == I2->getType() && I1->getOpcode() == I2->getOpcode();
  };

  SmallVector<Value *> Operands;
  SmallPtrSet<Value *, 8> Seen;
  for (Instruction *I : make_filter_range(
           Insts, [&](Instruction *I) { return !R.isDeleted(I); })) {
    forEachOperandChainCandidate(
        *Opts, I,
        [&](Value *Op, unsigned Position) {
          auto *OpI = dyn_cast<Instruction>(Op);
          if (!OpI || OpI->getParent() != BB || R.isDeleted(OpI) ||
              isa<ShuffleVectorInst>(OpI) ||
              (!isValidElementType(OpI->getType(), Opts->slp_revec) &&
               !isa<IntrinsicInst>(OpI)))
            return;
          if (!Seen.insert(OpI).second)
            return;
          OpKeys.try_emplace(OpI, BuildKey(I, Position));
          Operands.push_back(OpI);
        },
        /*ForReduction=*/false);
  }
  if (Operands.size() <= 1)
    return Changed;
  Changed |= tryToVectorizeSequence<Value>(
      *Opts, Operands, OperandSorter, AreCompatibleOperands,
      [this, &R](ArrayRef<Value *> Candidates, bool MaxVFOnly) {
        constexpr unsigned Limit = 32;
        // Limit to StandaloneSeeds if !MaxVFOnly to avoid quadratic scan for
        // large set of candidates.
        return tryToVectorizeList(Candidates, R, MaxVFOnly,
                                  /*StandaloneSeeds=*/!MaxVFOnly &&
                                      Candidates.size() >= Limit);
      },
      /*MaxVFOnly=*/true, R);
  return Changed;
}

bool SLPVectorizerPass::vectorizeInserts(
    InstSetVector &Instructions, BasicBlock *BB, BoUpSLP &R,
    SmallSetVector<Instruction *, 8> &FMACandidates) {
  assert(all_of(Instructions, IsaPred<InsertElementInst, InsertValueInst>) &&
         "This function only accepts Insert instructions");
  bool OpsChanged = false;
  SmallVector<WeakTrackingVH> PostponedInsts;
  // pass1 - try to match and vectorize a buildvector sequence for MaxVF only.
  for (auto *I : make_filter_range(reverse(Instructions), [&](auto *I) {
         return !R.isDeleted(I) && !isa<CmpInst>(I);
       })) {
    // The packs of the aggregate are vectorized together, not each alone.
    if (auto *IVI = dyn_cast<InsertValueInst>(I);
        IVI && vectorizePackedAggregate(IVI, R, *TTI, *DL)) {
      OpsChanged = true;
      continue;
    }
    if (auto *LastInsertValue = dyn_cast<InsertValueInst>(I)) {
      OpsChanged |=
          vectorizeInsertValueInst(LastInsertValue, BB, R, /*MaxVFOnly=*/true);
    } else if (auto *LastInsertElem = dyn_cast<InsertElementInst>(I)) {
      OpsChanged |=
          vectorizeInsertElementInst(LastInsertElem, BB, R, /*MaxVFOnly=*/true);
    }
    // pass2 - try to vectorize reductions only
    if (R.isDeleted(I))
      continue;
    OpsChanged |= vectorizeHorReduction(nullptr, I, BB, R, PostponedInsts);
    if (R.isDeleted(I) || isa<CmpInst>(I))
      continue;
    // pass3 - try to match and vectorize a buildvector sequence.
    if (auto *LastInsertValue = dyn_cast<InsertValueInst>(I)) {
      OpsChanged |=
          vectorizeInsertValueInst(LastInsertValue, BB, R, /*MaxVFOnly=*/false);
    } else if (auto *LastInsertElem = dyn_cast<InsertElementInst>(I)) {
      OpsChanged |= vectorizeInsertElementInst(LastInsertElem, BB, R,
                                               /*MaxVFOnly=*/false);
    }
  }
  // Now try to vectorize postponed instructions.
  OpsChanged |= tryToVectorize(PostponedInsts, R, FMACandidates);

  Instructions.clear();
  return OpsChanged;
}

bool SLPVectorizerPass::vectorizeChainsInBlock(
    BasicBlock *BB, BoUpSLP &R,
    SmallSetVector<Instruction *, 8> &FMACandidates) {
  bool Changed = false;
  SmallVector<Value *, 4> Incoming;
  SmallPtrSet<Value *, 16> VisitedInstrs;
  // Only the original compares are the seeds. With revec the vectorized
  // alternate compares are the pairs of compares of the same operands, which
  // otherwise are vectorized again and again.
  SmallPtrSet<const CmpInst *, 16> OrigCmps;
  for (const CmpInst &CI : make_isa_range<CmpInst>(*BB))
    OrigCmps.insert(&CI);
  // Maps phi nodes to the non-phi nodes found in the use tree for each phi
  // node. Allows better to identify the chains that can be vectorized in the
  // better way.
  DenseMap<Value *, SmallVector<Value *, 4>> PHIToOpcodes;
  auto PHICompare = [this, &PHIToOpcodes](Value *V1, Value *V2) {
    assert(isValidElementType(V1->getType(), Opts->slp_revec) &&
           isValidElementType(V2->getType(), Opts->slp_revec) &&
           "Expected vectorizable types only.");
    if (V1 == V2)
      return false;
    // It is fine to compare type IDs here, since we expect only vectorizable
    // types, like ints, floats and pointers, we don't care about other type.
    if (V1->getType()->getTypeID() < V2->getType()->getTypeID())
      return true;
    if (V1->getType()->getTypeID() > V2->getType()->getTypeID())
      return false;
    if (V1->getType()->getScalarSizeInBits() <
        V2->getType()->getScalarSizeInBits())
      return true;
    if (V1->getType()->getScalarSizeInBits() >
        V2->getType()->getScalarSizeInBits())
      return false;
    ArrayRef<Value *> Opcodes1 = PHIToOpcodes[V1];
    ArrayRef<Value *> Opcodes2 = PHIToOpcodes[V2];
    if (Opcodes1.size() < Opcodes2.size())
      return true;
    if (Opcodes1.size() > Opcodes2.size())
      return false;
    for (int I = 0, E = Opcodes1.size(); I < E; ++I) {
      {
        // Instructions come first.
        auto *I1 = dyn_cast<Instruction>(Opcodes1[I]);
        auto *I2 = dyn_cast<Instruction>(Opcodes2[I]);
        if (I1 && I2) {
          DomTreeNodeBase<BasicBlock> *NodeI1 = DT->getNode(I1->getParent());
          DomTreeNodeBase<BasicBlock> *NodeI2 = DT->getNode(I2->getParent());
          if (!NodeI1)
            return NodeI2 != nullptr;
          if (!NodeI2)
            return false;
          assert((NodeI1 == NodeI2) ==
                     (NodeI1->getDFSNumIn() == NodeI2->getDFSNumIn()) &&
                 "Different nodes should have different DFS numbers");
          if (NodeI1 != NodeI2)
            return NodeI1->getDFSNumIn() < NodeI2->getDFSNumIn();
          InstructionsState S = getSameOpcode({I1, I2}, *TLI);
          if (S && !S.isAltShuffle() && I1->getOpcode() == I2->getOpcode()) {
            const auto *E1 = dyn_cast<ExtractElementInst>(I1);
            const auto *E2 = dyn_cast<ExtractElementInst>(I2);
            if (!E1 || !E2)
              continue;

            // Sort on ExtractElementInsts primarily by vector operands. Prefer
            // program order of the vector operands.
            const auto *V1 = dyn_cast<Instruction>(E1->getVectorOperand());
            const auto *V2 = dyn_cast<Instruction>(E2->getVectorOperand());
            if (V1 != V2) {
              if (V1 && !V2)
                return true;
              if (!V1 && V2)
                return false;
              DomTreeNodeBase<BasicBlock> *NodeI1 =
                  DT->getNode(V1->getParent());
              DomTreeNodeBase<BasicBlock> *NodeI2 =
                  DT->getNode(V2->getParent());
              if (!NodeI1)
                return NodeI2 != nullptr;
              if (!NodeI2)
                return false;
              assert((NodeI1 == NodeI2) ==
                         (NodeI1->getDFSNumIn() == NodeI2->getDFSNumIn()) &&
                     "Different nodes should have different DFS numbers");
              if (NodeI1 != NodeI2)
                return NodeI1->getDFSNumIn() < NodeI2->getDFSNumIn();
              return V1->comesBefore(V2);
            }
            // If we have the same vector operand, try to sort by constant
            // index.
            std::optional<unsigned> Id1 = getExtractIndex(E1);
            std::optional<unsigned> Id2 = getExtractIndex(E2);
            // Bring constants to the top
            if (Id1 && !Id2)
              return true;
            if (!Id1 && Id2)
              return false;
            // First elements come first.
            if (Id1 && Id2)
              return *Id1 < *Id2;

            continue;
          }
          if (I1->getOpcode() == I2->getOpcode())
            continue;
          return I1->getOpcode() < I2->getOpcode();
        }
        if (I1)
          return true;
        if (I2)
          return false;
      }
      {
        // Non-undef constants come next.
        bool C1 = isa<Constant>(Opcodes1[I]) && !isa<UndefValue>(Opcodes1[I]);
        bool C2 = isa<Constant>(Opcodes2[I]) && !isa<UndefValue>(Opcodes2[I]);
        if (C1 && C2)
          continue;
        if (C1)
          return true;
        if (C2)
          return false;
      }
      bool U1 = isa<UndefValue>(Opcodes1[I]);
      bool U2 = isa<UndefValue>(Opcodes2[I]);
      {
        // Non-constant non-instructions come next.
        if (!U1 && !U2) {
          auto ValID1 = Opcodes1[I]->getValueID();
          auto ValID2 = Opcodes2[I]->getValueID();
          if (ValID1 == ValID2)
            continue;
          if (ValID1 < ValID2)
            return true;
          if (ValID1 > ValID2)
            return false;
        }
        if (!U1)
          return true;
        if (!U2)
          return false;
      }
      // Undefs come last.
      assert(U1 && U2 && "The only thing left should be undef & undef.");
    }
    return false;
  };
  auto AreCompatiblePHIs = [&PHIToOpcodes, this, &R](ArrayRef<Value *> VL,
                                                     Value *V1) {
    if (VL.empty() || V1 == VL.back())
      return true;
    Value *V2 = VL.back();
    if (V1->getType() != V2->getType())
      return false;
    ArrayRef<Value *> Opcodes1 = PHIToOpcodes[V1];
    ArrayRef<Value *> Opcodes2 = PHIToOpcodes[V2];
    if (Opcodes1.size() != Opcodes2.size())
      return false;
    for (int I = 0, E = Opcodes1.size(); I < E; ++I) {
      // Undefs are compatible with any other value.
      if (isa<UndefValue>(Opcodes1[I]) || isa<UndefValue>(Opcodes2[I]))
        continue;
      if (auto *I1 = dyn_cast<Instruction>(Opcodes1[I]))
        if (auto *I2 = dyn_cast<Instruction>(Opcodes2[I])) {
          if (R.isDeleted(I1) || R.isDeleted(I2))
            return false;
          if (I1->getParent() != I2->getParent())
            return false;
          if (getSameOpcode({I1, I2}, *TLI))
            continue;
          return false;
        }
      if (isa<Constant>(Opcodes1[I]) && isa<Constant>(Opcodes2[I]))
        continue;
      if (Opcodes1[I]->getValueID() != Opcodes2[I]->getValueID())
        return false;
    }
    return true;
  };

  bool HaveVectorizedPhiNodes = false;
  do {
    // Collect the incoming values from the PHIs.
    Incoming.clear();
    for (Instruction &I : *BB) {
      auto *P = dyn_cast<PHINode>(&I);
      if (!P || P->getNumIncomingValues() > MaxPHINumOperands)
        break;

      // No need to analyze deleted, vectorized and non-vectorizable
      // instructions.
      if (!VisitedInstrs.count(P) && !R.isDeleted(P) &&
          isValidElementType(P->getType(), Opts->slp_revec))
        Incoming.push_back(P);
    }

    if (Incoming.size() <= 1)
      break;

    // Find the corresponding non-phi nodes for better matching when trying to
    // build the tree.
    for (Value *V : Incoming) {
      SmallVectorImpl<Value *> &Opcodes =
          PHIToOpcodes.try_emplace(V).first->getSecond();
      if (!Opcodes.empty())
        continue;
      SmallVector<Value *, 4> Nodes(1, V);
      SmallPtrSet<Value *, 4> Visited;
      while (!Nodes.empty()) {
        auto *PHI = cast<PHINode>(Nodes.pop_back_val());
        if (!Visited.insert(PHI).second)
          continue;
        for (Value *V : PHI->incoming_values()) {
          if (auto *PHI1 = dyn_cast<PHINode>((V))) {
            Nodes.push_back(PHI1);
            continue;
          }
          Opcodes.emplace_back(V);
        }
      }
    }

    HaveVectorizedPhiNodes = tryToVectorizeSequence<Value>(
        *Opts, Incoming, PHICompare, AreCompatiblePHIs,
        [this, &R](ArrayRef<Value *> Candidates, bool MaxVFOnly) {
          return tryToVectorizeList(Candidates, R, MaxVFOnly);
        },
        /*MaxVFOnly=*/true, R);
    Changed |= HaveVectorizedPhiNodes;
    if (HaveVectorizedPhiNodes && any_of(PHIToOpcodes, [&](const auto &P) {
          auto *PHI = dyn_cast<PHINode>(P.first);
          return !PHI || R.isDeleted(PHI);
        }))
      PHIToOpcodes.clear();
    VisitedInstrs.insert_range(Incoming);
  } while (HaveVectorizedPhiNodes);

  VisitedInstrs.clear();

  InstSetVector PostProcessInserts;
  SmallSetVector<CmpInst *, 8> PostProcessCmps;
  // Non-vectorizable root instructions other than stores: calls
  // (regular and intrinsic), invokes, callbrs, atomic RMW/cmpxchg, and
  // returns.
  SmallSetVector<Instruction *, 8> PostProcessInsts;
  // Stores are processed after all other instructions/roots.
  SmallSetVector<StoreInst *, 8> PostProcessStores;
  SmallSetVector<Instruction *, 8> PoorThroughputSeeds;
  PoorThroughputOpCache PoorThroughputCache;
  auto VectorizeInsertsAndCmps = [&](bool AtTerminator) {
    bool Changed = vectorizeInserts(PostProcessInserts, BB, R, FMACandidates);
    if (AtTerminator) {
      Changed |=
          vectorizeCmpInsts(reverse(PostProcessCmps), BB, R, FMACandidates);
      PostProcessCmps.clear();
      if (!PostProcessInsts.empty())
        Changed |= vectorizeNonVectorizableInsts(reverse(PostProcessInsts), BB,
                                                 R, FMACandidates);
      PostProcessInsts.clear();
    }
    PostProcessInserts.clear();
    return Changed;
  };
  // Returns true if `I` is in any of the post-process sets.
  auto IsInPostProcessInstrs = [&](Instruction *I) {
    if (auto *Cmp = dyn_cast<CmpInst>(I))
      return PostProcessCmps.contains(Cmp);
    if (PostProcessInsts.contains(I))
      return true;
    if (auto *SI = dyn_cast<StoreInst>(I))
      return PostProcessStores.contains(SI);
    return isa<InsertElementInst, InsertValueInst>(I) &&
           PostProcessInserts.contains(I);
  };
  // Returns true if `I` is an instruction without users, like terminator, or
  // function call with ignored return value, store. Ignore unused instructions
  // (basing on instruction type, except for CallInst and InvokeInst).
  auto HasNoUsers = [](Instruction *I) {
    return I->use_empty() &&
           (I->getType()->isVoidTy() || isa<CallInst, InvokeInst>(I));
  };
  // The number of the stores to each underlying object, which may start the
  // reduction. Vectorized stores and stores of loads or non-instruction values
  // never start it.
  SmallDenseMap<Value *, unsigned> NumRdxRootStores;
  for (const auto &[Obj, SIs] : Stores)
    NumRdxRootStores[Obj] = count_if(SIs, [&](StoreInst *SI) {
      return !R.isDeleted(SI) && isa<Instruction>(SI->getValueOperand()) &&
             !isa<LoadInst>(SI->getValueOperand());
    });
  for (BasicBlock::iterator It = BB->begin(), E = BB->end(); It != E; ++It) {
    // Skip instructions with scalable type. The num of elements is unknown at
    // compile-time for scalable type.
    if (isa<ScalableVectorType>(It->getType()))
      continue;

    // Skip instructions marked for the deletion.
    if (R.isDeleted(&*It))
      continue;
    // We may go through BB multiple times so skip the one we have checked.
    if (!VisitedInstrs.insert(&*It).second) {
      if (HasNoUsers(&*It) &&
          VectorizeInsertsAndCmps(/*AtTerminator=*/It->isTerminator())) {
        // We would like to start over since some instructions are deleted
        // and the iterator may become invalid value.
        Changed = true;
        It = BB->begin();
        E = BB->end();
      }
      continue;
    }

    // Try to vectorize reductions that use PHINodes.
    if (PHINode *P = dyn_cast<PHINode>(It)) {
      // Check that the PHI is a reduction PHI.
      if (P->getNumIncomingValues() == 2) {
        // Try to match and vectorize a horizontal reduction.
        Instruction *Root = getReductionInstr(DT, P, BB, LI);
        if (Root && vectorizeRootInstruction(P, Root, BB, R, FMACandidates)) {
          Changed = true;
          It = BB->begin();
          E = BB->end();
          continue;
        }
      }
      // Try to vectorize the incoming values of the PHI, to catch reductions
      // that feed into PHIs.
      for (unsigned I : seq<unsigned>(P->getNumIncomingValues())) {
        // Skip if the incoming block is the current BB for now. Also, bypass
        // unreachable IR for efficiency and to avoid crashing.
        // TODO: Collect the skipped incoming values and try to vectorize them
        // after processing BB.
        if (BB == P->getIncomingBlock(I) ||
            !DT->isReachableFromEntry(P->getIncomingBlock(I)))
          continue;

        // Postponed instructions should not be vectorized here, delay their
        // vectorization.
        if (auto *PI = dyn_cast<Instruction>(P->getIncomingValue(I));
            PI && !IsInPostProcessInstrs(PI)) {
          bool Res = vectorizeRootInstruction(
              nullptr, PI, P->getIncomingBlock(I), R, FMACandidates);
          Changed |= Res;
          if (Res && R.isDeleted(P)) {
            It = BB->begin();
            E = BB->end();
            break;
          }
        }
      }
      continue;
    }

    if (HasNoUsers(&*It)) {
      bool OpsChanged = false;
      auto *SI = dyn_cast<StoreInst>(It);
      bool TryToVectorizeRoot = Opts->slp_vectorize_hor_store || !SI;
      if (SI) {
        // Try to vectorize chain in store, if at most one store to the address
        // in the block may start the reduction.
        // TODO: This is just a temporarily solution to save compile time. Need
        // to investigate if we can safely turn on slp-vectorize-hor-store
        // instead to allow lookup for reduction chains in all non-vectorized
        // stores (need to check side effects and compile time).
        TryToVectorizeRoot |= NumRdxRootStores.lookup(getUnderlyingObject(
                                  SI->getPointerOperand())) <= 1 &&
                              SI->getValueOperand()->hasOneUse();
      }
      if (TryToVectorizeRoot) {
        for (auto *V : It->operand_values()) {
          // Postponed instructions should not be vectorized here, delay their
          // vectorization.
          if (auto *VI = dyn_cast<Instruction>(V);
              VI && !IsInPostProcessInstrs(VI))
            // Try to match and vectorize a horizontal reduction.
            OpsChanged |=
                vectorizeRootInstruction(nullptr, VI, BB, R, FMACandidates);
        }
      }
      // Start vectorization of post-process list of instructions from the
      // top-tree instructions to try to vectorize as many instructions as
      // possible.
      OpsChanged |=
          VectorizeInsertsAndCmps(/*AtTerminator=*/It->isTerminator());
      if (OpsChanged) {
        // We would like to start over since some instructions are deleted
        // and the iterator may become invalid value.
        Changed = true;
        It = BB->begin();
        E = BB->end();
        continue;
      }
    }

    // The values, feeding only the assumes, and the instructions, producing no
    // code, are dropped before the codegen, the tree is rejected for them
    // anyway.
    if (isAssumeLikeIntrinsic(&*It) || isa<PseudoProbeInst>(It) ||
        R.isEphemeralValue(&*It))
      continue;

    if (isa<InsertElementInst, InsertValueInst>(It))
      PostProcessInserts.insert(&*It);
    else if (auto *CI = dyn_cast<CmpInst>(It)) {
      if (OrigCmps.contains(CI))
        PostProcessCmps.insert(CI);
    } else if (auto *SI = dyn_cast<StoreInst>(It);
               SI &&
               (Opts->slp_revec ||
                !SI->getValueOperand()->getType()->isVectorTy()) &&
               isa<Instruction>(SI->getValueOperand()))
      PostProcessStores.insert(SI);
    else if (isNonVectorizableInst(*Opts, &*It, TLI))
      PostProcessInsts.insert(&*It);
    else if (Opts->slp_vectorize_poor_throughput &&
             isPoorThroughputOp(*Opts, &*It, *TTI, *TLI, PoorThroughputCache,
                                R.getCostKind(), R.getMaxVecRegSize()))
      PoorThroughputSeeds.insert(&*It);
  }

  // Late post-process: run operand-chain vectorization for stores.
  if (!PostProcessStores.empty() &&
      (Opts->slp_non_vectorizables_as_reductions ||
       PostProcessStores.size() >= 2)) {
    bool TryVectorize = true;
    if (!Opts->slp_postprocess_stores_operands && R.getCostThreshold() >= 0) {
      // Use pessimistic cost estimation to avoid long compile time when there
      // are many stores in the list.
      Type *ScalarTy = getValueType(PostProcessStores.front(), Opts->slp_revec);
      if (!::isValidElementType(ScalarTy, Opts->slp_revec)) {
        TryVectorize = false;
      } else {
        auto *IF =
            dyn_cast<Instruction>(PostProcessStores.front()->getValueOperand());
        auto *IB =
            dyn_cast<Instruction>(PostProcessStores.back()->getValueOperand());
        if (!Opts->slp_non_vectorizables_as_reductions &&
            PostProcessStores.size() == 2 &&
            (!IF || !IB || IF->getOpcode() != IB->getOpcode())) {
          TryVectorize = false;
        } else {
          ScalarTy = IntegerType::get(
              ScalarTy->getContext(),
              DL->getTypeSizeInBits(ScalarTy->getScalarType()));
          if (auto *ValTy = dyn_cast<VectorType>(
                  PostProcessStores.front()->getValueOperand()->getType()))
            ScalarTy = ::getWidenedType(ScalarTy, getNumElements(ValTy));
          auto *VecTy = cast<VectorType>(
              ::getWidenedType(ScalarTy, PostProcessStores.size()));
          InstructionCost ExtractsCost = getScalarizationOverhead(
              *TTI, Opts->slp_revec, ScalarTy, VecTy,
              APInt::getAllOnes(PostProcessStores.size()),
              /*Insert=*/false, /*Extract=*/true, R.getCostKind(),
              /*ForPoisonSrc=*/true, {}, TTI::VectorInstrContext::Store);
          TryVectorize = ExtractsCost <= PostProcessStores.size() + 1;
        }
      }
    }
    if (TryVectorize) {
      Changed |= vectorizeNonVectorizableInsts(reverse(PostProcessStores), BB,
                                               R, FMACandidates);
    }
  }

  Changed |= vectorizePoorThroughputSeeds(PoorThroughputSeeds.getArrayRef(), R);

  return Changed;
}

bool SLPVectorizerPass::vectorizePoorThroughputSeeds(
    ArrayRef<Instruction *> Candidates, BoUpSLP &R,
    function_ref<bool(ArrayRef<Value *>)> Filter) {
  if (Candidates.size() < 2)
    return false;
  SmallVector<Value *> Seeds;
  SmallDenseMap<Value *, SeedGroupKey> SeedKeys;
  for (Instruction *I : make_filter_range(Candidates, [&](Instruction *I) {
         return !R.isDeleted(I) &&
                isValidElementType(getValueType(I, Opts->slp_revec),
                                   Opts->slp_revec) &&
                !R.hasResolvedUser(I);
       })) {
    SeedKeys.try_emplace(I, getSeedGroupKey(I, *TLI));
    Seeds.push_back(I);
  }
  return vectorizeSeeds(
      Seeds,
      [&](Value *V1, Value *V2) {
        return SeedKeys.at(V1).less(SeedKeys.at(V2));
      },
      R, Filter);
}

// Seed the groups with scalars not stored locally (e.g. the store is sunk to
// the join block) before the store chains split them into a remainder too
// small to vectorize.
bool SLPVectorizerPass::vectorizeSplitStorePoorThroughputSeeds(BasicBlock *BB,
                                                               BoUpSLP &R) {
  if (!Opts->slp_vectorize_poor_throughput || Stores.empty())
    return false;
  auto HasLocalStoreUser = [&](Value *V) {
    return any_of(V->users(), [&](User *U) {
      auto *SI = dyn_cast<StoreInst>(U);
      return SI && SI->isSimple() && SI->getParent() == BB &&
             SI->getValueOperand() == V;
    });
  };
  auto IsCandidate = [&](Instruction &I, PoorThroughputOpCache &Cache) {
    return !R.isDeleted(&I) && !isAssumeLikeIntrinsic(&I) &&
           !isa<PseudoProbeInst>(I) && !R.isEphemeralValue(&I) &&
           !isNonVectorizableInst(*Opts, &I, TLI) &&
           isPoorThroughputOp(*Opts, &I, *TTI, *TLI, Cache, R.getCostKind(),
                              R.getMaxVecRegSize());
  };
  // The groups without the stored scalars are rejected, so the block is
  // skipped if no stored scalar is a candidate. The stored scalars are checked
  // in the block order, a scalar rejected here is rejected by the full scan.
  PoorThroughputOpCache StoredCache;
  if (none_of(*BB, [&](Instruction &I) {
        return HasLocalStoreUser(&I) && IsCandidate(I, StoredCache);
      }))
    return false;
  PoorThroughputOpCache PoorThroughputCache;
  SmallVector<Instruction *> Candidates;
  for (Instruction &I : *BB)
    if (IsCandidate(I, PoorThroughputCache))
      Candidates.push_back(&I);
  return vectorizePoorThroughputSeeds(Candidates, R, [&](ArrayRef<Value *> VL) {
    // The scalars not stored locally must widen the stored scalars, left by
    // the store chains after the full vectors.
    unsigned MaxVF = bit_floor(R.getMaxVecRegSize() /
                               DL->getTypeSizeInBits(VL.front()->getType()));
    unsigned NumStored = count_if(VL, HasLocalStoreUser);
    unsigned Rem = MaxVF ? NumStored % MaxVF : 0;
    return Rem != 0 && bit_floor(Rem) < bit_floor(VL.size() - NumStored + Rem);
  });
}

bool SLPVectorizerPass::vectorizeSeeds(
    SmallVectorImpl<Value *> &Seeds,
    function_ref<bool(Value *, Value *)> IsLessGroup, BoUpSLP &R,
    function_ref<bool(ArrayRef<Value *>)> Filter) {
  if (Seeds.size() < 2)
    return false;
  auto SeedSorter = [&](Value *V1, Value *V2) {
    if (V1 == V2)
      return false;
    auto *I1 = cast<Instruction>(V1);
    auto *I2 = cast<Instruction>(V2);
    Type *T1 = I1->getType();
    Type *T2 = I2->getType();
    if (T1->getTypeID() != T2->getTypeID())
      return T1->getTypeID() < T2->getTypeID();
    if (T1->getScalarSizeInBits() != T2->getScalarSizeInBits())
      return T1->getScalarSizeInBits() < T2->getScalarSizeInBits();
    if (IsLessGroup(V1, V2))
      return true;
    if (IsLessGroup(V2, V1))
      return false;
    return I1->comesBefore(I2);
  };
  auto AreCompatibleSeeds = [&](ArrayRef<Value *> VL, Value *V) {
    if (VL.empty() || VL.back() == V)
      return true;
    return cast<Instruction>(VL.back())->getType() ==
               cast<Instruction>(V)->getType() &&
           !IsLessGroup(VL.back(), V) && !IsLessGroup(V, VL.back());
  };
  return tryToVectorizeSequence<Value>(
      *Opts, Seeds, SeedSorter, AreCompatibleSeeds,
      [this, &R](ArrayRef<Value *> Candidates, bool MaxVFOnly) {
        // The same list may be retried for the different groups of the same
        // type, the earlier rejection is still valid for the block.
        if (R.isAnalyzedBundle(Candidates))
          return false;
        if (tryToVectorizeList(Candidates, R, MaxVFOnly,
                               /*StandaloneSeeds=*/true))
          return true;
        R.analyzedBundle(Candidates);
        return false;
      },
      /*MaxVFOnly=*/false, R, Filter);
}

bool SLPVectorizerPass::vectorizeOnceUsedSeeds(BasicBlock *BB, BoUpSLP &R) {
  // Loads are not seeds, their subkeys do not affect the grouping.
  auto GenerateLoadsSubkey = [](size_t, LoadInst *LI) {
    return hash_value(LI->getPointerOperand());
  };
  SmallVector<Value *> Seeds;
  SmallDenseMap<std::pair<size_t, size_t>, unsigned> KeyToGroup;
  SmallDenseMap<Value *, unsigned> SeedGroups;
  PoorThroughputOpCache PoorThroughputCache;
  for (Instruction &I : make_filter_range(*BB, [&](Instruction &I) {
         return !R.isDeleted(&I) && I.hasOneUse() && !R.isEphemeralValue(&I) &&
                !R.isVectorized(&I) && !R.isAnalyzedScalar(&I) &&
                isValidElementType(getValueType(&I, Opts->slp_revec),
                                   Opts->slp_revec) &&
                isOnceUsedSeed(&I) && !isNonVectorizableInst(*Opts, &I, TLI) &&
                !R.hasResolvedUser(&I);
       })) {
    // The poor-throughput ops are seeded on their own, with the different
    // grouping.
    if (Opts->slp_vectorize_poor_throughput &&
        isPoorThroughputOp(*Opts, &I, *TTI, *TLI, PoorThroughputCache,
                           R.getCostKind(), R.getMaxVecRegSize()))
      continue;
    // The multiplication is contracted into the scalar FMA with its user, the
    // vector node breaks the contraction.
    if (I.getOpcode() == Instruction::FMul) {
      auto *U = cast<Instruction>(I.user_back());
      if (InstructionsState S = getSameOpcode(U, *TLI);
          S && S.isAddSubLikeOp() &&
          canConvertToFMA(U, S, *DT, *DL, *TTI, *TLI, R).isValid())
        continue;
    }
    // The keys are hashes, so the groups are numbered by the first seed to
    // keep the order deterministic.
    std::pair<size_t, size_t> Key = generateKeySubkey(
        &I, TLI, GenerateLoadsSubkey, /*AllowAlternate=*/false);
    SeedGroups.try_emplace(
        &I, KeyToGroup.try_emplace(Key, KeyToGroup.size()).first->second);
    Seeds.push_back(&I);
  }
  return vectorizeSeeds(
      Seeds,
      [&](Value *V1, Value *V2) {
        return SeedGroups.at(V1) < SeedGroups.at(V2);
      },
      R);
}

bool SLPVectorizerPass::vectorizeGEPIndices(BasicBlock *BB, BoUpSLP &R) {
  auto Changed = false;
  const Loop *L = LI->getLoopFor(BB);
  auto IsAffineInLoop = [L](const SCEV *S) {
    const auto *AddRec = dyn_cast<SCEVAddRecExpr>(S);
    return AddRec && AddRec->getLoop() == L && AddRec->isAffine();
  };
  // If the getelementptr list has fewer than two elements, there's nothing
  // to do.
  for (auto &Entry : make_filter_range(
           GEPs, [](auto &Entry) { return Entry.second.size() >= 2; })) {
    LLVM_DEBUG(dbgs() << "SLP: Analyzing a getelementptr list of length "
                      << Entry.second.size() << ".\n");

    // Process the GEP list in chunks suitable for the target's supported
    // vector size. If a vector register can't hold 1 element, we are done. We
    // are trying to vectorize the index computations, so the maximum number of
    // elements is based on the size of the index expression, rather than the
    // size of the GEP itself (the target's pointer size).
    auto *It = find_if(Entry.second, [&](GetElementPtrInst *GEP) {
      return !R.isDeleted(GEP);
    });
    if (It == Entry.second.end())
      continue;
    unsigned MaxVecRegSize = R.getMaxVecRegSize();
    unsigned EltSize = R.getVectorElementSize(*(*It)->idx_begin());
    if (MaxVecRegSize < EltSize)
      continue;

    unsigned MaxElts = MaxVecRegSize / EltSize;
    for (unsigned BI = 0, BE = Entry.second.size(); BI < BE; BI += MaxElts) {
      auto Len = std::min<unsigned>(BE - BI, MaxElts);
      ArrayRef<GetElementPtrInst *> GEPList(&Entry.second[BI], Len);

      // Initialize a set a candidate getelementptrs. Note that we use a
      // SetVector here to preserve program order. If the index computations
      // are vectorizable and begin with loads, we want to minimize the chance
      // of having to reorder them later.
      SetVector<Value *> Candidates(llvm::from_range, GEPList);

      // Some of the candidates may have already been vectorized after we
      // initially collected them or their index is optimized to constant value.
      // If so, they are marked as deleted, so remove them from the set of
      // candidates.
      Candidates.remove_if([&R](Value *I) {
        return R.isDeleted(cast<Instruction>(I)) ||
               isa<Constant>(cast<GetElementPtrInst>(I)->idx_begin()->get());
      });

      // Remove from the set of candidates all pairs of getelementptrs with
      // constant differences. Such getelementptrs are likely not good
      // candidates for vectorization in a bottom-up phase since one can be
      // computed from the other. The same holds for affine recurrences of the
      // enclosing loop that differ by a loop-invariant amount: loop strength
      // reduction turns them into pointer increments. We also ensure all
      // candidate getelementptr indices are unique.
      for (int I = 0, E = GEPList.size(); I < E && Candidates.size() > 1; ++I) {
        auto *GEPI = GEPList[I];
        if (!Candidates.count(GEPI))
          continue;
        const SCEV *SCEVI = SE->getSCEV(GEPList[I]);
        bool IsAffineI = IsAffineInLoop(SCEVI);
        for (int J = I + 1; J < E && Candidates.size() > 1; ++J) {
          auto *GEPJ = GEPList[J];
          if (!Candidates.count(GEPJ))
            continue;
          const SCEV *SCEVJ = SE->getSCEV(GEPList[J]);
          const SCEV *Diff = SE->getMinusSCEV(SCEVI, SCEVJ);
          if (isa<SCEVConstant>(Diff) || (IsAffineI && IsAffineInLoop(SCEVJ) &&
                                          SE->isLoopInvariant(Diff, L))) {
            Candidates.remove(GEPI);
            Candidates.remove(GEPJ);
          } else if (GEPI->idx_begin()->get() == GEPJ->idx_begin()->get()) {
            Candidates.remove(GEPJ);
          }
        }
      }

      // We break out of the above computation as soon as we know there are
      // fewer than two candidates remaining.
      if (Candidates.size() < 2)
        continue;

      // Add the single, non-constant index of each candidate to the bundle. We
      // ensured the indices met these constraints when we originally collected
      // the getelementptrs.
      SmallVector<Value *, 16> Bundle(Candidates.size());
      auto BundleIndex = 0u;
      for (auto *V : Candidates) {
        auto *GEP = cast<GetElementPtrInst>(V);
        auto *GEPIdx = GEP->idx_begin()->get();
        assert(GEP->getNumIndices() == 1 && !isa<Constant>(GEPIdx));
        Bundle[BundleIndex++] = GEPIdx;
      }

      // Try and vectorize the indices. We are currently only interested in
      // gather-like cases of the form:
      //
      // ... = g[a[0] - b[0]] + g[a[1] - b[1]] + ...
      //
      // where the loads of "a", the loads of "b", and the subtractions can be
      // performed in parallel. It's likely that detecting this pattern in a
      // bottom-up phase will be simpler and less costly than building a
      // full-blown top-down phase beginning at the consecutive loads.
      Changed |= tryToVectorizeList(Bundle, R);
    }
  }
  return Changed;
}

bool SLPVectorizerPass::vectorizeStoreChains(BoUpSLP &R) {
  bool Changed = false;
  // Sort by type, base pointers and values operand. Value operands must be
  // compatible (have the same opcode, same parent), otherwise it is
  // definitely not profitable to try to vectorize them.
  auto &&StoreSorter = [this](StoreInst *V, StoreInst *V2) {
    if (V->getValueOperand()->getType()->getTypeID() <
        V2->getValueOperand()->getType()->getTypeID())
      return true;
    if (V->getValueOperand()->getType()->getTypeID() >
        V2->getValueOperand()->getType()->getTypeID())
      return false;
    if (V->getPointerOperandType()->getTypeID() <
        V2->getPointerOperandType()->getTypeID())
      return true;
    if (V->getPointerOperandType()->getTypeID() >
        V2->getPointerOperandType()->getTypeID())
      return false;
    if (V->getValueOperand()->getType()->getScalarSizeInBits() <
        V2->getValueOperand()->getType()->getScalarSizeInBits())
      return true;
    if (V->getValueOperand()->getType()->getScalarSizeInBits() >
        V2->getValueOperand()->getType()->getScalarSizeInBits())
      return false;
    // UndefValues are compatible with all other values.
    auto *I1 = dyn_cast<Instruction>(V->getValueOperand());
    auto *I2 = dyn_cast<Instruction>(V2->getValueOperand());
    if (I1 && I2) {
      DomTreeNodeBase<llvm::BasicBlock> *NodeI1 = DT->getNode(I1->getParent());
      DomTreeNodeBase<llvm::BasicBlock> *NodeI2 = DT->getNode(I2->getParent());
      assert(NodeI1 && "Should only process reachable instructions");
      assert(NodeI2 && "Should only process reachable instructions");
      assert((NodeI1 == NodeI2) ==
                 (NodeI1->getDFSNumIn() == NodeI2->getDFSNumIn()) &&
             "Different nodes should have different DFS numbers");
      if (NodeI1 != NodeI2)
        return NodeI1->getDFSNumIn() < NodeI2->getDFSNumIn();
      return I1->getOpcode() < I2->getOpcode();
    }
    if (I1 && !I2)
      return true;
    if (!I1 && I2)
      return false;
    return V->getValueOperand()->getValueID() <
           V2->getValueOperand()->getValueID();
  };

  bool SameParent = true;
  auto AreCompatibleStores = [&](ArrayRef<StoreInst *> VL, StoreInst *V1) {
    if (VL.empty()) {
      SameParent = true;
      return true;
    }
    StoreInst *V2 = VL.back();
    if (V1 == V2)
      return true;
    if (V1->getValueOperand()->getType() != V2->getValueOperand()->getType())
      return false;
    if (V1->getPointerOperandType() != V2->getPointerOperandType())
      return false;
    // Undefs are compatible with any other value.
    if (isa<UndefValue>(V1->getValueOperand()) ||
        isa<UndefValue>(V2->getValueOperand()))
      return true;
    if (isa<Constant>(V1->getValueOperand()) &&
        isa<Constant>(V2->getValueOperand()))
      return true;
    // Check if the operands of the stores can be vectorized. They can be
    // vectorized, if they have compatible operands or have operands, which can
    // be vectorized as copyables.
    auto *I1 = dyn_cast<Instruction>(V1->getValueOperand());
    auto *I2 = dyn_cast<Instruction>(V2->getValueOperand());
    if (I1 || I2) {
      // Accept only tail-following non-compatible values for now.
      // TODO: investigate if it is possible to vectorize incompatible values,
      // if the copyables are first in the list.
      if (I1 && !I2)
        return false;
      SameParent &= I1 && I2 && I1->getParent() == I2->getParent();
      SmallVector<Value *> NewVL(VL.size() + 1);
      for (auto [SI, V] : zip(VL, NewVL))
        V = SI->getValueOperand();
      NewVL.back() = V1->getValueOperand();
      InstructionsCompatibilityAnalysis Analysis(*DT, *DL, *TTI, *TLI);
      InstructionsState S = Analysis.buildInstructionsState(
          NewVL, R, /*WithProfitabilityCheck=*/true,
          /*SkipSameCodeCheck=*/!SameParent);
      // A copyable GEP node with non-constant indices is vectorizable only as
      // the address vector of a masked gather, not as a stored value.
      if (S && S.getOpcode() == Instruction::GetElementPtr &&
          S.areInstructionsWithCopyableElements() &&
          any_of(NewVL, [&](Value *V) {
            auto *GEP = dyn_cast<GetElementPtrInst>(V);
            return GEP && !S.isCopyableElement(V) &&
                   !isa<ConstantInt>(GEP->getOperand(1));
          }))
        return false;
      if (S)
        return true;
      if (!SameParent)
        return false;
    }
    return V1->getValueOperand()->getValueID() ==
           V2->getValueOperand()->getValueID();
  };

  // Returns true if any two stores in the group are at consecutive (stride-1)
  // addresses. Masked stores are disabled for the entire base-object group when
  // this is true - consecutive vectorization is always preferred.
  auto HasConsecutiveStoresOrSameAddress = [&](ArrayRef<StoreInst *> SIs) {
    if (SIs.size() < 2)
      return false;
    Type *Ty = SIs.front()->getValueOperand()->getType();
    Value *Base = SIs.front()->getPointerOperand();
    SmallVector<int64_t> Offsets;
    Offsets.reserve(SIs.size());
    for (StoreInst *SI : SIs) {
      if (std::optional<int64_t> Off =
              getPointersDiff(Ty, Base, Ty, SI->getPointerOperand(), *DL, *SE))
        Offsets.push_back(*Off);
    }
    sort(Offsets);
    return any_of(seq<size_t>(1, Offsets.size()), [&](size_t I) {
      return Offsets[I] - Offsets[I - 1] == 1 || Offsets[I] == Offsets[I - 1];
    });
  };

  // Attempt to sort and vectorize each of the store-groups.
  DenseSet<std::tuple<Value *, Value *, Value *, Value *, unsigned>> Attempted;
  // The longer groups go first: the shorter ones sharing the scalars with them
  // then reuse their vectors instead of splitting the longer chains.
  SmallVector<StoreListMap::value_type *> Groups(make_pointer_range(Stores));
  stable_sort(Groups, [](const auto *A, const auto *B) {
    return A->second.size() > B->second.size();
  });
  auto TryToVectorizeGroup = [&](StoreListMap::value_type &Pair) {
    LLVM_DEBUG(dbgs() << "SLP: Analyzing a store chain of length "
                      << Pair.second.size() << ".\n");

    if (!isValidElementType(Pair.second.front()->getValueOperand()->getType(),
                            Opts->slp_revec))
      return false;

    // Masked stores are only attempted when no consecutive pair exists in the
    // full base-object group.
    const bool AllowMaskedStores =
        Opts->slp_enable_masked_stores &&
        !HasConsecutiveStoresOrSameAddress(Pair.second);

    // Reverse stores to do bottom-to-top analysis. This is important if the
    // values are stores to the same addresses several times, in this case need
    // to follow the stores order (reversed to meet the memory dependecies).
    SmallVector<StoreInst *> ReversedStores(Pair.second.rbegin(),
                                            Pair.second.rend());
    return tryToVectorizeSequence<StoreInst>(
        *Opts, ReversedStores, StoreSorter, AreCompatibleStores,
        [&](ArrayRef<StoreInst *> Candidates, bool) {
          return vectorizeStores(Candidates, R, Attempted, AllowMaskedStores);
        },
        /*MaxVFOnly=*/false, R);
  };
  // The groups, rejected before the vectorized one, were analyzed for the
  // original scalars and may become profitable now, so they are retried once.
  SmallVector<StoreListMap::value_type *> Rejected;
  unsigned NumToRetry = 0;
  for (auto &Pair :
       make_filter_range(make_pointee_range(Groups),
                         [](auto &Pair) { return Pair.second.size() >= 2; })) {
    if (TryToVectorizeGroup(Pair)) {
      Changed = true;
      NumToRetry = Rejected.size();
    } else {
      Rejected.push_back(&Pair);
    }
  }
  Attempted.clear();
  for (auto *Pair : ArrayRef(Rejected).take_front(NumToRetry))
    Changed |= TryToVectorizeGroup(*Pair);
  return Changed;
}
