//===- 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 "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/SetOperations.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/CommandLine.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/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 <set>
#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.");

static cl::opt<bool>
    RunSLPVectorization("vectorize-slp", cl::init(true), cl::Hidden,
                        cl::desc("Run the SLP vectorization passes"));

static cl::opt<bool>
    SLPReVec("slp-revec", cl::init(false), cl::Hidden,
             cl::desc("Enable vectorization for wider vector utilization"));

static cl::opt<int>
    SLPCostThreshold("slp-threshold", cl::init(0), cl::Hidden,
                     cl::desc("Only vectorize if you gain more than this "
                              "number "));

static cl::opt<bool>
ShouldVectorizeHor("slp-vectorize-hor", cl::init(true), cl::Hidden,
                   cl::desc("Attempt to vectorize horizontal reductions"));

static cl::opt<bool> VectorizeLoopAccRdx(
    "slp-vectorize-loop-acc-rdx", cl::init(true), cl::Hidden,
    cl::desc("Emit loop-carried horizontal reductions as a vector "
             "accumulator in the loop plus a single reduction after it"));

static cl::opt<bool> ShouldStartVectorizeHorAtStore(
    "slp-vectorize-hor-store", cl::init(false), cl::Hidden,
    cl::desc(
        "Attempt to vectorize horizontal reductions feeding into a store"));

static cl::opt<bool> SplitAlternateInstructions(
    "slp-split-alternate-instructions", cl::init(true), cl::Hidden,
    cl::desc("Improve the code quality by splitting alternate instructions"));

static cl::opt<bool> SLPInstCountCheck(
    "slp-inst-count-check", cl::init(true), cl::Hidden,
    cl::desc("Reject vectorization if vector instruction count exceeds "
             "scalar instruction count"));

static cl::opt<int>
MaxVectorRegSizeOption("slp-max-reg-size", cl::init(128), cl::Hidden,
    cl::desc("Attempt to vectorize for this register size in bits"));

static cl::opt<unsigned>
MaxVFOption("slp-max-vf", cl::init(0), cl::Hidden,
    cl::desc("Maximum SLP vectorization factor (0=unlimited)"));

/// Limits the size of scheduling regions in a block.
/// It avoid long compile times for _very_ large blocks where vector
/// instructions are spread over a wide range.
/// This limit is way higher than needed by real-world functions.
static cl::opt<int>
ScheduleRegionSizeBudget("slp-schedule-budget", cl::init(100000), cl::Hidden,
    cl::desc("Limit the size of the SLP scheduling region per block"));

static cl::opt<int> MinVectorRegSizeOption(
    "slp-min-reg-size", cl::init(128), cl::Hidden,
    cl::desc("Attempt to vectorize for this register size in bits"));

static cl::opt<unsigned> RecursionMaxDepth(
    "slp-recursion-max-depth", cl::init(12), cl::Hidden,
    cl::desc("Limit the recursion depth when building a vectorizable tree"));

static cl::opt<unsigned> MinTreeSize(
    "slp-min-tree-size", cl::init(3), cl::Hidden,
    cl::desc("Only vectorize small trees if they are fully vectorizable"));

static cl::opt<unsigned> PHINodeVectorizationBudget(
    "slp-phi-vectorization-budget", cl::init(1024), cl::Hidden,
    cl::desc("Do not vectorize a bundle of PHI nodes if the product of the "
             "bundle size and the number of incoming values exceeds this "
             "value, to limit the compile time spent on wide PHIs"));

// The maximum depth that the look-ahead score heuristic will explore.
// The higher this value, the higher the compilation time overhead.
static cl::opt<int> LookAheadMaxDepth(
    "slp-max-look-ahead-depth", cl::init(2), cl::Hidden,
    cl::desc("The maximum look-ahead depth for operand reordering scores"));

// The maximum depth that the look-ahead score heuristic will explore
// when it probing among candidates for vectorization tree roots.
// The higher this value, the higher the compilation time overhead but unlike
// similar limit for operands ordering this is less frequently used, hence
// impact of higher value is less noticeable.
static cl::opt<int> RootLookAheadMaxDepth(
    "slp-max-root-look-ahead-depth", cl::init(2), cl::Hidden,
    cl::desc("The maximum look-ahead depth for searching best rooting option"));

static cl::opt<unsigned> MinProfitableStridedLoads(
    "slp-min-strided-loads", cl::init(2), cl::Hidden,
    cl::desc("The minimum number of loads, which should be considered strided, "
             "if the stride is > 1 or is runtime value"));

static cl::opt<unsigned> MinProfitableStridedStores(
    "slp-min-strided-stores", cl::init(2), cl::Hidden,
    cl::desc(
        "The minimum number of stores, which should be considered strided, "
        "if the stride is > 1 or is runtime value"));

static cl::opt<unsigned> MaxProfitableStride(
    "slp-max-stride", cl::init(8), cl::Hidden,
    cl::desc("The maximum stride, considered to be profitable."));

static cl::opt<bool>
    EnableStridedStores("slp-enable-strided-stores", cl::init(false),
                        cl::Hidden,
                        cl::desc("Enable SLP trees to be built from strided "
                                 "store chains."));

static cl::opt<bool> EnableMaskedStores(
    "slp-enable-masked-stores", cl::init(true), cl::Hidden,
    cl::desc("Enable vectorization of non-consecutive stores as a single "
             "masked store, when the target supports masked stores."));

static cl::opt<bool>
    DisableTreeReorder("slp-disable-tree-reorder", cl::init(false), cl::Hidden,
                       cl::desc("Disable tree reordering even if it is "
                                "profitable. Used for testing only."));

static cl::opt<bool>
    ForceStridedLoads("slp-force-strided-loads", cl::init(false), cl::Hidden,
                      cl::desc("Generate strided loads even if they are not "
                               "profitable. Used for testing only."));

static cl::opt<bool>
    ViewSLPTree("view-slp-tree", cl::Hidden,
                cl::desc("Display the SLP trees with Graphviz"));

static cl::opt<bool> VectorizeNonPowerOf2(
    "slp-vectorize-non-power-of-2", cl::init(false), cl::Hidden,
    cl::desc("Try to vectorize with non-power-of-2 number of elements."));

static cl::opt<bool> ForcePostProcessStoresOperands(
    "slp-postprocess-stores-operands", cl::init(false), cl::Hidden,
    cl::desc("Force vectorization of non-vectorizable stores operands."));

static cl::opt<bool> NonVectReductions(
    "slp-non-vectorizables-as-reductions", cl::init(false), cl::Hidden,
    cl::desc(
        "Use  non-vectorizable instructions as potential reduction roots."));

static cl::opt<bool> VectorizePoorThroughput(
    "slp-vectorize-poor-throughput", cl::init(true), cl::Hidden,
    cl::desc("Use poor-throughput instructions (e.g. fdiv, frem, fsqrt) as "
             "standalone vectorization seeds."));

static cl::opt<bool> VectorizeOnceUsed(
    "slp-vectorize-once-used", cl::init(true), cl::Hidden,
    cl::desc("Use instructions with the single user as standalone "
             "vectorization seeds."));

/// Enables vectorization of copyable elements.
static cl::opt<bool> VectorizeCopyableElements(
    "slp-copyable-elements", cl::init(true), cl::Hidden,
    cl::desc("Try to replace values with the idempotent instructions for "
             "better vectorization."));

/// Gather operands of associative single-use binary chains into one node.
static cl::opt<bool> VectorizeReassociatedOps(
    "slp-reassociate-ops", cl::init(true), cl::Hidden,
    cl::desc("Gather operands of associative binary chains into one node."));

/// The family-realigned seed already groups the vectorizable columns; the
/// VLOperands polish on top is quadratic in the column count, so past this
/// many columns keep the seed instead.
static cl::opt<unsigned> ReassocReorderColumnLimit(
    "slp-reassociate-reorder-limit", cl::init(32), cl::Hidden,
    cl::desc("Max flattened operand columns for which associative-chain "
             "reordering runs the full operand reorder."));

static cl::opt<unsigned> LoopAwareTripCount(
    "slp-cost-loop-trip-count", cl::init(2), cl::Hidden,
    cl::desc("Loop trip count, considered by the cost model during "
             "modeling (0=loops are ignored and considered flat code)"));

/// Refine the loop-aware cost scaling of gather/buildvector tree entries by
/// using the per-lane execution scale of the operand that feeds each lane,
/// instead of a single whole-entry scale. This matches the LICM hoisting
/// performed by optimizeGatherSequence() at codegen time: lanes whose
/// operands are loop-invariant in an inner loop contribute the outer loop's
/// execution scale rather than the inner loop's, which avoids over-costing
/// buildvectors that bridge values from outer loop nests into an inner loop.
static cl::opt<bool> PerLaneGatherScale(
    "slp-per-lane-gather-scale", cl::init(true), cl::Hidden,
    cl::desc("Use per-lane execution scale for gather/buildvector tree "
             "entries to model LICM-hoistable buildvector sequences."));

/// Enable versioning of a basic block with runtime alias checks.
static cl::opt<bool> SLPEnableRuntimeAliasChecks(
    "slp-vectorize-with-runtime-alias-checks", cl::init(true), cl::Hidden,
    cl::desc("Allow SLP to version a block with runtime alias checks to "
             "vectorize trees blocked by may-alias memory dependencies."));

/// Maximum number of runtime alias checks (one per pair of base objects) that
/// may guard a single versioned region.
static cl::opt<unsigned> SLPMaxRuntimeAliasChecks(
    "slp-max-runtime-alias-checks", cl::init(8), cl::Hidden,
    cl::desc("The maximum number of runtime alias checks generated to guard a "
             "single SLP-vectorized region."));

/// The runtime checks and the guard branch execute on both the vector and the
/// scalar fallback path, so they add overhead to the scalar code.
static cl::opt<unsigned> SLPRuntimeAliasChecksMaxScalarCostPercent(
    "slp-runtime-alias-checks-max-scalar-cost-percent", cl::init(25),
    cl::Hidden,
    cl::desc("Maximum SLP runtime alias check cost, as a percentage of the "
             "guarded scalar region cost, before versioning is rejected to "
             "avoid pessimizing the scalar fallback path."));

/// The scalar loop left by the loop vectorizer runs only a few iterations or
/// the ranges its runtime checks found overlapping, where the checks executed
/// on each iteration are unlikely to pay off, so they get a tighter bound.
static cl::opt<unsigned> SLPVecLoopRTChecksCostPercent(
    "slp-vec-loop-rt-checks-cost-percent", cl::init(10), cl::Hidden,
    cl::desc("Maximum SLP runtime alias check cost, as a percentage of the "
             "guarded scalar region cost, for blocks of loops already "
             "vectorized by the loop vectorizer."));

// 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;

/// 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>;

  BoUpSLP(Function *Func, ScalarEvolution *Se, TargetTransformInfo *Tti,
          TargetLibraryInfo *TLi, AAResults *Aa, LoopInfo *Li,
          DominatorTree *Dt, AssumptionCache *AC, DemandedBits *DB,
          const DataLayout *DL, OptimizationRemarkEmitter *ORE)
      : 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).
    if (MaxVectorRegSizeOption.getNumOccurrences())
      MaxVecRegSize = MaxVectorRegSizeOption;
    else
      MaxVecRegSize =
          TTI->getRegisterBitWidth(TargetTransformInfo::RGK_FixedWidthVector)
              .getFixedValue();

    if (MinVectorRegSizeOption.getNumOccurrences())
      MinVecRegSize = MinVectorRegSizeOption;
    else
      MinVecRegSize = 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; }

  /// 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 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, SLPReVec, 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, SLPReVec, Limit);
    return It->second;
  }

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

  unsigned getMaximumVF(unsigned ElemWidth, unsigned Opcode) const {
    unsigned MaxVF = MaxVFOption.getNumOccurrences() ?
      MaxVFOption : 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;

  /// 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(), SLPReVec) ||
          !isValidElementType(V2->getType(), SLPReVec))
        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 = 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();
            }))
          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(),
                                    LookAheadMaxDepth);
      // 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,
                                  RootLookAheadMaxDepth);
    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); }

  /// 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;

  /// \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, 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;

  /// 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; }

    /// 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;

  /// 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;

  /// 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)
        : BB(BB), ChunkSize(BB->size()), ChunkPos(ChunkSize) {}

    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;

      // 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, InsertValueInst>(EI.UserTE->Scalars[Lane]) &&
              !EI.UserTE->ReorderIndices.empty())
            Lane = 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, InsertValueInst>(EI.UserTE->Scalars[Lane]) &&
                !EI.UserTE->ReorderIndices.empty())
              Lane = 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.
            for (ScheduleCopyableData *CD :
                 make_filter_range(CopyableData, [&](ScheduleCopyableData *CD) {
                   return !CD->getEdgeInfo().UserTE->isCopyableElement(User);
                 })) {
              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()) {
                  for (const Use &U :
                       make_filter_range(In->operands(), [&](const Use &U) {
                         return U.get() == OpI;
                       })) {
                    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;

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

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

    /// 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, SLPReVec))
    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,
                            /*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 > MinProfitableStridedLoads ||
        (AbsoluteDiff <= MaxProfitableStride * 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::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 ? MinProfitableStridedLoads : MinProfitableStridedStores;
  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;

  // 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, CommonAlignment,
                               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,
                                               RecursionMaxDepth);
                }) &&
        !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);
            },
            SLPReVec))
      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, SLPReVec, PtrScalarTy, PtrVecTy, DemandedElts, /*Insert=*/true,
          /*Extract=*/false, CostKind);
    else
      VectorGEPCost +=
          getScalarizationOverhead(
              TTI, SLPReVec, 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, SLPReVec, 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 >= -SLPCostThreshold;

    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, SLPReVec);
         VF >= MinVF; VF = getFloorFullVectorNumberOfElements(
                          TTI, ScalarTy, VF - 1, SLPReVec)) {
      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, SLPReVec, 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, SLPReVec, ScalarTy, SubVecTy, APInt::getAllOnes(SliceVF),
                /*Insert=*/true, /*Extract=*/false, CostKind);
          else
            VectorGEPCost +=
                getScalarizationOverhead(TTI, SLPReVec, 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, CommonAlignment,
                                 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 < -SLPCostThreshold) {
        if (BestVF)
          *BestVF = VF;
        return true;
      }
    }
    return MaskedGatherCost - GatherCost >= -SLPCostThreshold;
  };
  // 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, RecursionMaxDepth,
                             Order))
    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(), SLPReVec),
                           2 * TE.getVectorFactor()),
            getValueType(TE.Scalars.front(), SLPReVec)) == 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() || isReverseOrder(TE.ReorderIndices)))
    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 (DisableTreeReorder)
    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(), SLPReVec));
      }))
    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);
  // 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) {
    // 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 < RecursionMaxDepth) {
        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());
             })) {
      // 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 (SLPReVec) {
            assert(SLPReVec && "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()) ||
            (SLPReVec && 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(), SLPReVec)))
        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(), SLPReVec)))
          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.ReorderIndices.empty() && isReverseOrder(Entry.ReorderIndices))
    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(), SLPReVec))
        continue;
      // Skip entry if already
      if (isVectorized(U))
        continue;

      Value *Ptr =
          getUnderlyingObject(SI->getPointerOperand(), RecursionMaxDepth);
      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(), SLPReVec);
  if (!isValidElementType(ScalarTy, SLPReVec))
    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(), RecursionMaxDepth) ==
                 getUnderlyingObject(Data.front().first->getPointerOperand(),
                                     RecursionMaxDepth) &&
             "Expected loads with the same type, same parent and same "
             "underlying pointer.");
      std::optional<int64_t> Dist = 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;
        for (auto [Idx, Data] :
             make_filter_range(enumerate(GatheredLoads), [&](const auto &P) {
               return P.index() >= Start;
             })) {
          ToAdd.clear();
          if (LI->getParent() != Data.front().first->getParent() ||
              LI->getType() != Data.front().first->getType())
            continue;
          std::optional<int64_t> Dist =
              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, VectorizeNonPowerOf2))
      CandidateVFs.push_back(MaxVF);
    for (int NumElts = getFloorFullVectorNumberOfElements(
             *TTI, Loads.front()->getType(), MaxVF, SLPReVec);
         NumElts > 1;
         NumElts = getFloorFullVectorNumberOfElements(
             *TTI, Loads.front()->getType(), NumElts - 1, SLPReVec)) {
      CandidateVFs.push_back(NumElts);
      if (VectorizeNonPowerOf2 && NumElts > 2)
        CandidateVFs.push_back(NumElts - 1);
    }

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

    unsigned BestVF = Final ? CandidateVFs.back() : 0;
    for (unsigned NumElts :
         make_filter_range(CandidateVFs, [&](unsigned NumElts) {
           return !Final || NumElts <= BestVF;
         })) {
      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.
            for (LoadInst *LI : make_filter_range(
                     Slice, [](LoadInst *LI) { return !LI->hasOneUse(); })) {
              // 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);
          for (const std::pair<LoadInst *, int64_t> &L :
               make_filter_range(LocalLoadsDists,
                                 [&](const std::pair<LoadInst *, int64_t> &L) {
                                   return !isVectorized(L.first);
                                 })) {
            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, nullptr,
                                    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).
static bool isPoorThroughputOp(Instruction *I, const TargetTransformInfo &TTI,
                               const TargetLibraryInfo &TLI,
                               PoorThroughputOpCache &Cache,
                               const TTI::TargetCostKind CostKind) {
  if (!isa<BinaryOperator, CallInst>(I))
    return false;
  Type *Ty = I->getType();
  if ((Ty->isVectorTy() && !SLPReVec) || Ty->isAggregateType() ||
      !isValidElementType(Ty, SLPReVec))
    return false;
  auto Analyze = [&]() {
    InstructionCost ScalarCost = TTI.getInstructionCost(I, CostKind);
    if (ScalarCost < TTI::TCC_Expensive)
      return false;
    constexpr unsigned MinVF = 2;
    return getVectorOpCost(I, MinVF, TTI, TLI, CostKind) < ScalarCost * MinVF;
  };
  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(), SLPReVec);
        }))
      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); });
    }
    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); });
}

/// Find the innermost loop starting from \p L, for which at least a single
/// value in \p VL is not invariant.
static const Loop *findInnermostNonInvariantLoop(const Loop *L,
                                                 ArrayRef<Value *> VL) {
  assert(L && "Expected valid loop");
  auto IsLoopInvariant = [&](const Loop *L, ArrayRef<Value *> VL) {
    return all_of(make_isa_range<Instruction>(VL),
                  [L](Instruction *I) { return L->isLoopInvariant(I); });
  };
  while (L && IsLoopInvariant(L, VL))
    L = L->getParentLoop();
  return L;
}

/// Get the loop nest for the given loop.
ArrayRef<const Loop *> BoUpSLP::getLoopNest(const Loop *L) {
  assert(L && "Expected valid loop");
  if (LoopAwareTripCount == 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(),
                                              SLPReVec) ||
                        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((SLPReVec || 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, SLPReVec)) {
        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 (SLPReVec) {
      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 (EnableStridedStores &&
          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 (EnableMaskedStores &&
          isMaskedStoreCompress(VL, PointerOps, CurrentOrder, *TTI, *DL, *SE,
                                CommonAlignment, ReuseShuffleIndices,
                                StoreVecTy)) {
        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 (SLPReVec && 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(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(), SLPReVec))) {
    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(), SLPReVec);
    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) {
      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, SLPReVec, 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, SLPReVec, 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, SLPReVec), 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;
            for (Value *V : make_filter_range(
                     VL, [](Value *V) { return !isa<PoisonValue>(V); })) {
              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;
}

bool BoUpSLP::canBuildSplitNode(ArrayRef<Value *> VL,
                                const InstructionsState &LocalState,
                                SmallVectorImpl<Value *> &Op1,
                                SmallVectorImpl<Value *> &Op2,
                                OrdersType &ReorderIndices) const {
  constexpr unsigned SmallNodeSize = 4;
  if (VL.size() <= SmallNodeSize || TTI->preferAlternateOpcodeVectorization() ||
      !SplitAlternateInstructions)
    return false;
  // Split vectorization of struct types is not supported.
  if (isa<StructType>(getValueType(VL.front(), SLPReVec)))
    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(), SLPReVec);
  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(),
                                    SLPReVec) &&
           (!hasFullVectorsOrPowerOf2(*TTI, Op1.front()->getType(), Op1.size(),
                                      SLPReVec) ||
            !hasFullVectorsOrPowerOf2(*TTI, Op2.front()->getType(), Op2.size(),
                                      SLPReVec)))
    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;
      }
      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).
  Value *selectBestIdempotentValue() const {
    assert(isSupportedMainOp(MainOp) && "Unsupported opcode");
    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).
  SmallVector<Value *> getOperands(const InstructionsState &S, Value *V,
                                   bool SelfOp) 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 (RecurrenceDescriptor::isFMulAddIntrinsic(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");
    return {V, selectBestIdempotentValue()};
  }

  /// 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::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::ICmp:
    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 == MainOp && (!S.isAltShuffle() || I == SMain)) ||
          (!S.isAltShuffle() && I == SMain))
        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);
    }
    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 &&
               (!VectorizeCopyableElements ||
                !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 (!VectorizeCopyableElements)
      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;
        for (Value *V : make_filter_range(
                 Ops, [](Value *V) { return !isa<UndefValue>(V); }))
          ++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 fmuladd is the only 3-operand
    // copyable.
    assert((Operands.size() == 2 ||
            (Operands.size() == 1 && isa<CastInst>(MainOp)) ||
            (Operands.size() == 3 &&
             RecurrenceDescriptor::isFMulAddIntrinsic(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) {
    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;
      }
      // 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);
      // Populate operands for every lane.
      for (auto [Idx, V] : enumerate(VL)) {
        SmallVector<Value *> OperandsForValue =
            getOperands(S, V, SelfOpLanes.contains(V));
        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) {
    for (const auto &Entry : make_filter_range(
             GroupMap, [](const auto &P) { return P.second.size() >= 2; })) {
      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 >
        PHINodeVectorizationBudget) {
      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 (!SLPReVec && getValueType(VL.front(), SLPReVec)->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_and_nonnull<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 >= RecursionMaxDepth &&
      (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, SLPReVec, ScalarTy, VecTy, Extracted,
                                   /*Insert=*/false, /*Extract=*/true,
                                   CostKind);
      InstructionCost ScalarizeCostEstimate = getScalarizationOverhead(
          *TTI, SLPReVec, 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);
    SmallVector<BoUpSLP::ValueList> SubOperands =
        Analysis.buildOperands(ColS, Column, R);
    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) {
    SmallVector<Value *> Op1, Op2;
    OrdersType ReorderIndices;
    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;
    for (Value *V :
         make_filter_range(VL, [](Value *V) { return !isa<PoisonValue>(V); })) {
      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(VL, ReuseShuffleIndices, *TTI, *TLI, S,
                                UserTreeIdx, *this);

    newGatherTreeEntry(VL, S, UserTreeIdx, ReuseShuffleIndices);
    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.
  if (S.getOpcode() == Instruction::ICmp && !S.isAltShuffle()) {
    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(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);

  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 (VectorizeReassociatedOps && 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());

      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<PoisonValue>(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() <= ReassocReorderColumnLimit) {
          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(SLPReVec && "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, SLPReVec))
    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, SLPReVec), 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 (!VectorizePoorThroughput || TreeCost >= -SLPCostThreshold)
    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(TE.getMainOp(), *TTI, *TLI, Cache, CostKind);
  });
}

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.getVectorFactor()));
    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.
        if (HasFusedAlt && 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()) &&
        (!SLPReVec ||
         (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(), RecursionMaxDepth);
    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,
                                    RecursionMaxDepth)) {
            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, SLPReVec);
          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, SLPReVec, 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, SLPReVec, 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.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->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);
}

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);
  unsigned ShiftWidth;
  InstructionCost PackCost = getBitPackCost(
      *TTI, VecTy, ScalarTy, *Info, getZExtSrcWidth(*LhsTE),
      getCastContextHint(*LhsTE), 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;
  CmpPredicate MainPred = Pred;
  CmpPredicate InversedPred(CmpInst::getInversePredicate(Pred),
                            Pred.hasSameSign());
  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, SLPReVec, 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;
  };
  // 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, SLPReVec);
           VF >= MinVF; VF = getFloorFullVectorNumberOfElements(
                            *TTI, VL.front()->getType(), VF - 1, SLPReVec)) {
        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(), SLPReVec), 2 * VF),
                getValueType(Slice.front(), SLPReVec));
            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.
      if (E.State != TreeEntry::Vectorize)
        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.ReorderIndices.empty() && isReverseOrder(E.ReorderIndices) &&
          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 || ForceStridedLoads) {
          // 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.ReorderIndices.empty() && isReverseOrder(E.ReorderIndices) &&
          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: {
      // 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)
        break;
      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))
        break;
      if (!canConvertToFMA(E.Scalars, E.getOperations(), *DT, *DL, *TTI, *TLI,
                           *this)
               .isValid())
        break;
      // 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;
      }
      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;
      break;
    }
    default:
      break;
    }
  }

  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(), RecursionMaxDepth),
                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(SLPReVec && "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);
      for (auto [Pos, I] :
           make_filter_range(enumerate(Mask), [](const auto &P) {
             return P.value() != PoisonMaskElem;
           })) {
        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),
          SLPReVec);
      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 = InVectors.front().Vec.dyn_cast<Value *>()) {
        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 = P1.dyn_cast<Value *>(), *V2 = P2.dyn_cast<Value *>();
    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, SLPReVec, 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 =
                   InVectors.front().Vec.dyn_cast<const TreeEntry *>()) {
      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(SLPReVec && "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;
}

/// Get the assumed loop trip count for the loop \p L.
static unsigned getLoopTripCount(const Loop *L, ScalarEvolution &SE) {
  if (LoopAwareTripCount == 0)
    return 1;
  unsigned Scale = SE.getSmallConstantTripCount(L);
  if (Scale == 0)
    Scale = getLoopEstimatedTripCount(const_cast<Loop *>(L)).value_or(0);
  if (Scale != 0) {
    // Multiple exiting blocks - choose the minimum between trip count (scale)
    // and LoopAwareTripCount, since the multiple exit loops can be terminated
    // early.
    if (!L->getExitingBlock())
      return std::min<unsigned>(LoopAwareTripCount, Scale);
    return Scale;
  }
  return LoopAwareTripCount;
}

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 || LoopAwareTripCount == 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));
    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 (!PerLaneGatherScale || LoopAwareTripCount == 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(), SLPReVec);
    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], SLPReVec);
  if (SLPReVec && E->State == TreeEntry::Vectorize &&
      E->getOpcode() == Instruction::InsertElement &&
      !E->getOperand(1).back()->getType()->isVectorTy())
    ScalarTy = ScalarTy->getScalarType();
  if (!isValidElementType(ScalarTy, SLPReVec))
    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 ||
       !isReverseOrder(E->ReorderIndices))) {
    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() || SLPReVec) &&
             "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, SLPReVec, 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;
    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) {
      // 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;
      TTI::CastContextHint CCH = GetCastContextHint(VL0->getOperand(0));

      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, SLPReVec, /*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;
    auto GetScalarCost = [&](unsigned Idx) {
      if (isa<PoisonValue>(UniqueValues[Idx]))
        return InstructionCost(TTI::TCC_Free);

      if (!isa<SelectInst>(UniqueValues[Idx]))
        return TTI->getInstructionCost(cast<Instruction>(UniqueValues[Idx]),
                                       CostKind);

      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 (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: {
    auto GetScalarCost = [&, &TTI = *TTI](unsigned Idx) {
      Instruction *I;
      if (!match(UniqueValues[Idx], m_Instruction(I)))
        return InstructionCost(TTI::TCC_Free);
      InstructionCost ScalarCost = TTI.getInstructionCost(I, CostKind);
      if (match(I, m_And(m_Shl(m_Value(), m_Value()), m_Value())))
        ScalarCost += TTI.getInstructionCost(
            cast<Instruction>(I->getOperand(0)), CostKind);
      return ScalarCost;
    };
    auto GetVectorCost = [&, &TTI = *TTI](InstructionCost CommonCost) {
      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);
      if (!Info)
        return InstructionCost::getInvalid();
      unsigned ShiftWidth;
      // The pack works on the vectorized operand in its own (possibly
      // demoted) type.
      Type *SrcScalarTy = LhsTE->Scalars.front()->getType();
      if (auto It = MinBWs.find(LhsTE); It != MinBWs.end())
        SrcScalarTy = IntegerType::get(F->getContext(), It->second.first);
      InstructionCost PackCost =
          getBitPackCost(TTI,
                         cast<FixedVectorType>(getWidenedType(
                             SrcScalarTy, LhsTE->getVectorFactor())),
                         SrcScalarTy, *Info, getZExtSrcWidth(*LhsTE),
                         getCastContextHint(*LhsTE), CostKind, TLI,
                         E->getMainOp(), ShiftWidth);
      // A demoted result is re-extended to the reduction type.
      if (SrcScalarTy != OrigScalarTy) {
        auto It = MinBWs.find(E);
        PackCost += TTI.getCastInstrCost(
            It != MinBWs.end() && It->second.second ? Instruction::SExt
                                                    : Instruction::ZExt,
            OrigScalarTy, SrcScalarTy, getCastContextHint(*LhsTE), CostKind);
      }
      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, SLPReVec, 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, LI0->getAlign(),
              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->ReorderIndices.empty() && isReverseOrder(E->ReorderIndices);
        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 +=
              TTI->getCastInstrCost(Instruction::BitCast, VecTy, StridedLoadTy,
                                    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; }, SLPReVec, IsMasked,
            InterleaveFactor, CompressMask, LoadVecTy);
        CompressEntryToData.try_emplace(E, CompressMask, LoadVecTy,
                                        InterleaveFactor, IsMasked);
        Align CommonAlignment = LI0->getAlign();
        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, CompressMask);
        } 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, CompressMask);
        }
        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 =
            computeCommonAlignment<LoadInst>(UniqueValues.getArrayRef());
        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(VL.size());
    for (auto [I, V] : enumerate(VL))
      PointerOps[I] = cast<LoadInst>(V)->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 +=
              TTI->getCastInstrCost(Instruction::BitCast, VecTy, StridedStoreTy,
                                    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 (!SLPReVec || 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 (SLPReVec && !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)) ||
            (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 (SLPReVec && 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 = SLPCostThreshold.getNumOccurrences() > 0;
  const bool ThresholdNonNegative = SLPCostThreshold >= 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 <= MinTreeSize &&
        all_of(VectorizableTree, [](const std::unique_ptr<TreeEntry> &TE) {
          return TE->isGather() || TE->State == TreeEntry::SplitVectorize;
        }))
      return true;
    if (TreeSize == 1 && SLPCostThreshold < 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 && SLPCostThreshold == 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 >= MinTreeSize)
    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) > -SLPCostThreshold)
      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 =
      ScheduleRegionSizeBudget / 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;
    for (BasicBlock *BB : make_filter_range(L->blocks(), [](BasicBlock *BB) {
           return !isa<CatchSwitchInst>(BB->getTerminator());
         })) {
      // 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>(ScheduleRegionSizeBudget))
        continue;
      Budget += BlockSize;
      if (Budget > BudgetLimit)
        break;
      if (!isa<CatchSwitchInst>(BB->getTerminator()) &&
          !CheckForNonVecCallsInSameBlock(&*BB->getFirstNonPHIOrDbgOrAlloca(),
                                          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->getFirstNonPHIOrDbgOrAlloca(), 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;
}

/// Checks if the \p IE1 instructions is followed by \p IE2 instruction in the
/// buildvector sequence.
static bool isFirstInsertElement(const InsertElementInst *IE1,
                                 const InsertElementInst *IE2) {
  if (IE1 == IE2)
    return false;
  const auto *I1 = IE1;
  const auto *I2 = IE2;
  const InsertElementInst *PrevI1;
  const InsertElementInst *PrevI2;
  unsigned Idx1 = *getElementIndex(IE1);
  unsigned Idx2 = *getElementIndex(IE2);
  do {
    if (I2 == IE1)
      return true;
    if (I1 == IE2)
      return false;
    PrevI1 = I1;
    PrevI2 = I2;
    if (I1 && (I1 == IE1 || I1->hasOneUse()) &&
        getElementIndex(I1).value_or(Idx2) != Idx2)
      I1 = dyn_cast<InsertElementInst>(I1->getOperand(0));
    if (I2 && ((I2 == IE2 || I2->hasOneUse())) &&
        getElementIndex(I2).value_or(Idx1) != Idx1)
      I2 = dyn_cast<InsertElementInst>(I2->getOperand(0));
  } while ((I1 && PrevI1 != I1) || (I2 && PrevI2 != I2));
  llvm_unreachable("Two different buildvectors not expected.");
}

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 undef vector, resizing the very first mask to
/// have common VF and perform action for 2 input vectors (including non-undef
/// 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 undef 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);
  SmallBitVector IsBaseUndef = isUndefVector(Base, UseMask);
  if (!IsBaseUndef.all()) {
    // Base is not undef, need to combine it with the next subvectors.
    std::pair<T *, bool> Res =
        ResizeAction(ShuffleMask.begin()->first, Mask, /*ForSingleMask=*/false);
    SmallBitVector IsBasePoison = isUndefVector<true>(Base, UseMask);
    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 undef 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 undef 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 IsBaseNotUndef = !IsBaseUndef.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 || IsBaseNotUndef) &&
               "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(), SLPReVec))) {
      // 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, SLPReVec, 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 (SLPCostThreshold.getNumOccurrences() > 0 && SLPCostThreshold < 0 &&
      Cost < -SLPCostThreshold && 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(), SLPReVec)->getScalarType()));
  }
  const unsigned MinVF = getMinVF(Sz);
  if (Cost >= -SLPCostThreshold &&
      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());
  // (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, [&](TreeEntry *TE) {
           return !DeletedNodes.contains(TE);
         })) {
      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, [&](const TreeEntry *BVTE) {
               return !DeletedNodes.contains(BVTE);
             }))
          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, [&](const TreeEntry *BVE) {
             return !DeletedNodes.contains(BVE);
           })) {
        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, SLPReVec, 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);
    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, SLPReVec, 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;
    for (const auto &[BVE, _] :
         make_filter_range(ValuesToInsert, [&](const auto &P) {
           return NodesCosts.contains(P.first);
         }))
      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, [&](TreeEntry *TE) {
           return !DeletedNodes.contains(TE);
         })) {
      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, [&](TreeEntry *TE) {
           return !DeletedNodes.contains(TE);
         })) {
      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(), SLPReVec)) ||
        // 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(), SLPReVec);
    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, SLPReVec, 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 ||
         !isReverseOrder(TE->ReorderIndices))) {
      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 < -SLPCostThreshold) {
          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 && SLPInstCountCheck &&
      TTI->preferSLPInstCountCheck() && getRootNode().getVectorFactor() == 2 &&
      SLPCostThreshold == 0 &&
      (!SLPReVec || !isa<VectorType>(getRootNodeScalars().front()->getType()));
  const Loop *InstCountLoop = nullptr;
  if (ApplyInstCountVeto && LoopAwareTripCount != 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, SLPReVec, 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 BasicBlock &BB, Type *Ty,
                                    const TargetTransformInfo &TTI) {
  if (hasNItemsOrMore(BB, ScheduleRegionSizeBudget))
    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 && SLPInstCountCheck &&
      TTI->preferSLPInstCountCheck() && getRootNode().getVectorFactor() == 2 &&
      SLPCostThreshold == 0 &&
      (!SLPReVec ||
       !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 (LoopAwareTripCount != 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(*Root->getParent(),
                                  getValueType(Root, SLPReVec), *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 >= -SLPCostThreshold + CostLimit &&
      (VectorizableTree.size() - DeletedNodes.size()) *
              getRootNode().getVectorFactor() <
          CostLimit)
    return Cost;

  if (Cost >= -SLPCostThreshold &&
      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(), SLPReVec);
    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_and_present<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_and_present<UnreachableInst>(UserParent->getTerminator())))
      continue;

    // No extract cost for vector "scalar" if REVEC is disabled.
    if (isVectorizedTy(EU.Scalar->getType()) &&
        (!SLPReVec ||
         (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, SLPReVec, 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, SLPReVec, 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;
        if (IsProfitablePHIUser) {
          KeepScalar = true;
        } else if (KeepScalar && ScalarCost != TTI::TCC_Free &&
                   ExtraCost - ScalarCost <= TTI::TCC_Basic &&
                   (!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(SLPReVec && "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 (SLPCostThreshold < 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: {
          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 < -SLPCostThreshold) {
    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 (ViewSLPTree)
    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);
  if (!Res || all_of(Mask, equal_to(PoisonMaskElem))) {
    // TODO: try to check other subsets if possible.
    // Restore the original VL if attempt was not successful.
    copy(SavedVL, VL.begin());
    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);
    for (Value *V :
         make_filter_range(VL, [](Value *V) { return !isConstant(V); }))
      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, SLPReVec);
      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, SLPReVec, 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, SLPReVec, 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, SLPReVec, 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,
    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, VL.front()->getType(),
                                                VL.size(), SLPReVec);
  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, SLPReVec, 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(SLPReVec && "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 (SLPReVec && 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, SLPReVec);
  }

  /// 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);
    }
    // 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();
            if (NeedFreeze)
              return false;
            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;
              auto *UserTE = TE->UserTreeIndex.UserTE;
              if (!UserTE || !UserTE->hasState() || UserTE->isAltShuffle() ||
                  TransformedToGatherNodes.contains(UserTE))
                return false;
              UserOps.emplace_back(UserTE->getOpcode(),
                                   TE->UserTreeIndex.EdgeIdx);
            }
            return !UserOps.empty();
          };
      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);
}

static DebugLoc getDebugLocFromPHI(PHINode &PN) {
  if (DebugLoc DL = PN.getDebugLoc())
    return DL;
  return DebugLoc::getUnknown();
}

Value *BoUpSLP::vectorizeTree(TreeEntry *E) {
  IRBuilderBase::InsertPointGuard Guard(Builder);

  Value *V = E->Scalars.front();
  Type *ScalarTy = getValueType(V, SLPReVec);
  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(SLPReVec && "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->ReorderIndices.empty() && isReverseOrder(E->ReorderIndices);
  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;
    I = ::propagateMetadata(I, UniqueInsts.getArrayRef());
    // For copyable elements the lane is synthesized using a binop identity
    // value, so the operand at that lane is the copyable scalar's value.
    // fast-math flags that turn defined NaN/Inf inputs into poison (nnan,
    // ninf) are only justified if every copyable scalar at the synthesized
    // lane is itself provably non-NaN/non-Inf - either an FPMathOperator
    // with the matching flag set, or a constant FP that is not NaN/Inf.
    if (E->hasCopyableElements() && isa<FPMathOperator>(I)) {
      bool AllNoNaNs = true;
      bool AllNoInfs = true;
      for (Value *Scalar : make_filter_range(Scalars, [&](Value *Scalar) {
             return E->isCopyableElement(Scalar);
           })) {
        if (auto *FPMO = dyn_cast<FPMathOperator>(Scalar)) {
          AllNoNaNs &= FPMO->hasNoNaNs();
          AllNoInfs &= FPMO->hasNoInfs();
          continue;
        }
        if (auto *CFP = dyn_cast<ConstantFP>(Scalar)) {
          AllNoNaNs &= !CFP->isNaN();
          AllNoInfs &= !CFP->isInfinity();
          continue;
        }
        AllNoNaNs = false;
        AllNoInfs = false;
        break;
      }
      if (!AllNoNaNs)
        I->setHasNoNaNs(false);
      if (!AllNoInfs)
        I->setHasNoInfs(false);
    }
    // Copyable lanes modeled as op(V, V) do not preserve the disjoint flag:
    // or disjoint(V, V) is poison unless V is zero. 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();
          return E->isCopyableElement(Scalar) && !match(Scalar, m_Zero()) &&
                 E->getOperand(0)[P.index()] == Scalar &&
                 E->getOperand(1)[P.index()] == Scalar;
        }))
      PDI->setIsDisjoint(false);
    // 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) {
            auto *OrigC = dyn_cast<ConstantInt>(LaneCI->getOperand(1));
            if (!OrigC)
              return false;
            ConstantInt *AdjC =
                CmpSamePredicateHelper::getAdjustedConstant(LaneCI, P0);
            return 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;
        }

        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;
            continue;
          }
        }

        Builder.SetInsertPoint(IBB->getTerminator());
        Builder.SetCurrentDebugLocation(getDebugLocFromPHI(*PH));
        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 (!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();
      // 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 (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);

      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, vectorizeOperand(E, 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;
          }
        }
      }
      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, SLPReVec, 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) {
        NewLI = Builder.CreateAlignedLoad(VecTy, PO, LI->getAlign());
      } 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(SLPReVec && "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(SLPReVec && "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 = computeCommonAlignment<LoadInst>(E->Scalars);
        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(SLPReVec && "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);
      }
      Value *V = (E->State == TreeEntry::CompressVectorize ||
                  E->State == TreeEntry::BlendedLoadVectorize)
                     ? NewLI
                     : PropagateIRFlags(NewLI);

      if (StridedLoadTy != VecTy)
        V = Builder.CreateBitOrPointerCast(V, VecTy);
      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->ReorderIndices.empty() && isReverseOrder(E->ReorderIndices);
        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 = Builder.CreateBitOrPointerCast(VecValue, StridedStoreTy);
        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 (SLPReVec && !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(SLPReVec && "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;
      SmallVector<TreeEntry *> CombinedTEs;
      if (ShlTE != E)
        CombinedTEs.append({ShlTE, getOperandEntry(E, /*Idx=*/1)});
      CombinedTEs.push_back(getOperandEntry(ShlTE, /*Idx=*/1));
      for (TreeEntry *TE : CombinedTEs)
        TE->VectorizedValue = PoisonValue::get(getWidenedType(
            TE->Scalars.front()->getType(), TE->getVectorFactor()));
      Value *X = vectorizeOperand(ShlTE, /*NodeIdx=*/0);
      std::optional<BitPackInfo> Info = computeBitPackLayout(*E);
      assert(Info && "Expected bit pack info.");
      unsigned ShiftWidth;
      const TreeEntry *LhsTE = getOperandEntry(ShlTE, /*Idx=*/0);
      [[maybe_unused]] InstructionCost PackCost =
          getBitPackCost(*TTI, cast<FixedVectorType>(X->getType()),
                         X->getType()->getScalarType(), *Info,
                         getZExtSrcWidth(*LhsTE), getCastContextHint(*LhsTE),
                         CostKind, TLI, E->getMainOp(), ShiftWidth);
      assert(PackCost.isValid() && "Expected valid cost.");
      unsigned NumInsts;
      Value *V = buildBitPack(Builder, X, *Info, 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(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, SLPReVec)->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.");
  if (!BB->getTerminator())
    return false;
  // 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(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->getFirstNonPHIOrDbgOrAlloca(), BB->end()),
             IsaPred<AllocaInst>))
    return false;
  return true;
}

bool BoUpSLP::canVersionForRuntimeChecks() {
  if (RTChecks.BasePairs.empty() || !RTChecks.BB)
    return false;
  if (RTChecks.BasePairs.size() > SLPMaxRuntimeAliasChecks)
    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")
          ? SLPVecLoopRTChecksCostPercent
          : SLPRuntimeAliasChecksMaxScalarCostPercent;
  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();
  assert(Term && "Versioned block must have a terminator");

  // 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(SLPReVec && "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 (SLPReVec && 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()->getFirstNonPHIOrDbgOrLifetime());
              } 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 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;
  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);
    for (ScheduleData *SD :
         make_filter_range(RecalcCopyableOperandDeps, [&](ScheduleData *SD) {
           return isInSchedulingRegion(*SD) &&
                  (WillReSchedule || !SD->isScheduled());
         })) {
      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()))
              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()))
                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 (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, InsertValueInst>(EI.UserTE->Scalars[Lane]) &&
              !EI.UserTE->ReorderIndices.empty())
            Lane = 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;
      }
    }

    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 && SLPEnableRuntimeAliasChecks) {
          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 (ScheduleData *SD :
                  make_isa_range<ScheduleData>(Bundle->getBundle()))
               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 > RecursionMaxDepth)
      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;
      };

  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, map_to_vector(seq<unsigned>(E.getNumOperands()),
                                [&](unsigned Idx) -> const TreeEntry * {
                                  return getOperandEntry(&E, Idx);
                                }));
  }
  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) {
      return all_of(
          make_isa_range<Instruction>(E.Scalars), [&](Instruction *I) {
            if (E.isCopyableElement(I))
              return true;
            KnownBits AmtKnownBits = computeKnownBits(I->getOperand(1), *DL);
            return AmtKnownBits.getMaxValue().ult(BitWidth);
          });
    };
    return TryProcessInstruction(
        BitWidth, {getOperandEntry(&E, 0), getOperandEntry(&E, 1)}, 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, {getOperandEntry(&E, 0), getOperandEntry(&E, 1)},
        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, {getOperandEntry(&E, 0), getOperandEntry(&E, 1)},
        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, {getOperandEntry(&E, 0), getOperandEntry(&E, 1)}, 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);
        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.
    for (Value *Root : make_filter_range(
             E.Scalars, [](Value *Root) { return !isa<PoisonValue>(Root); })) {
      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);
    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_) {
  if (!RunSLPVectorization)
    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(&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_and_nonnull<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);

    // 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 (VectorizeOnceUsed) {
    auto OnceUsedPOT = post_order(&F.getEntryBlock());
    for (auto *BB : make_filter_range(OnceUsedPOT, [&](auto *BB) {
           return !BB->isEHPad() &&
                  !isa_and_nonnull<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);
  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() || !SLPEnableRuntimeAliasChecks ||
      !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, SLPReVec) ||
      VF < 2 || VF < MinVF) {
    // Check if vectorizing with a non-power-of-2 VF should be considered; see
    // isAllowedNonPowerOf2VF for supported widths.
    if (!VectorizeNonPowerOf2 || (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(),
                                 SLPReVec) ||
        isAllowedNonPowerOf2VF(ValOps.size(), VectorizeNonPowerOf2);
    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 >= -SLPCostThreshold)
      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 < -SLPCostThreshold) {
    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(ArrayRef<Value *> Ops,
                             ArrayRef<SizePair> RangeSizes,
                             SmallVector<unsigned> &RangeSizesByIdx,
                             unsigned Stride)
      : 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;

  /// 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<unsigned>(MinVF, MinProfitableStridedStores);

  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, VectorizeNonPowerOf2)) {
    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, SLPReVec);
  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 = EnableStridedStores ? MaxProfitableStride : 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(MaxProfitableStride + 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>(
              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(), SLPReVec);
  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;
      if (!isValidElementType(SI->getValueOperand()->getType(), SLPReVec))
        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(), SLPReVec))
        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, SLPReVec)) {
      // 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], SLPReVec, /*LookThroughCmp=*/true);
  unsigned Sz = R.getVectorElementSize(I0);
  unsigned MinVF = R.getMinVF(Sz);
  unsigned MaxVF =
      std::max<unsigned>(isAllowedNonPowerOf2VF(VL.size(), VectorizeNonPowerOf2)
                             ? VL.size()
                             : getFloorFullVectorNumberOfElements(
                                   *TTI, ScalarTy, VL.size(), SLPReVec),
                         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 = SLPCostThreshold.getValue();

  unsigned NextInst = 0, MaxInst = VL.size();
  for (unsigned VF = MaxVF; NextInst + 1 < MaxInst && VF >= MinVF;
       VF = getFloorFullVectorNumberOfElements(*TTI, I0->getType(), VF - 1,
                                               SLPReVec)) {
    // 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; ++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, SLPReVec) &&
          (ActualVF != VL.size() ||
           !isAllowedNonPowerOf2VF(ActualVF, VectorizeNonPowerOf2)))
        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()) {
        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 < -SLPCostThreshold) {
        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 {
        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", -SLPCostThreshold);
    });
  } 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>;
  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 = VectorizeNonPowerOf2 ? 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.");
    }
  }

  /// Creates reduction operation with the current opcode with the IR flags
  /// from \p ReductionOps, dropping nuw/nsw flags.
  static Value *createOp(IRBuilderBase &Builder, RecurKind RdxKind, Value *LHS,
                         Value *RHS, const Twine &Name,
                         const ReductionOpsListType &ReductionOps) {
    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);
    return Op;
  }

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:
  HorizontalReduction() = default;
  HorizontalReduction(Instruction *I, ArrayRef<Value *> Ops)
      : 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, SLPReVec) || 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++ > RecursionMaxDepth)
        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, SLPReVec) || 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(), RecursionMaxDepth);
        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,
                                        RecursionMaxDepth)) {
                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 > RecursionMaxDepth ||
                                  !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, RecursionMaxDepth, 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);
            }
          SmallVector<Value *> NewCandidates;
          for (const auto &[Cand, Leaves] :
               zip(ReducedValsCandidates, AllLeaves)) {
            SmallVector<Instruction *> RdxOps = ReducedValsToOps.lookup(Cand);
            for (const NarrowedLeafInfo &L : Leaves) {
              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) {
      if (!VectorizeLoopAccRdx || RK != 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 =
          createOp(Builder, RdxKind, VAcc, Vec, "slprdx.acc", ReductionOps);
      // 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)) {
          ++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 &&
          (!SLPReVec || !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, SLPReVec);
        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, VectorizeNonPowerOf2))
        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;
      // 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 - skip.
        if (IgnoredCandidates.contains(std::make_pair(Pos, ReduxWidth)) ||
            (!has_single_bit(ReduxWidth) &&
             (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)) {
          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);
        // 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 >= -SLPCostThreshold) {
          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", -SLPCostThreshold);
          });
          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, SLPReVec);
                   VF >= ReductionLimit;
                   VF = getFloorFullVectorNumberOfElements(
                       *TTI, VL.front()->getType(), VF - 1, SLPReVec)) {
                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");
        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 *> RootVL = V.getRootNodeScalars();
          ArrayRef<Value *> CandSlice(Candidates.begin() + Pos, ReduxWidth);
          SmallVector<Value *> RootTrackedToOrig(RootVL.size());
          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");
      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,
                                                      SLPReVec);
      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 > -SLPCostThreshold ||
          (Cost == -SLPCostThreshold && 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", -SLPCostThreshold);
          });
        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 (!VectorizeNonPowerOf2 || !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 && SLPReVec) {
      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);
              Cost +=
                  (SameValueCount ? SameValueCount - 1 : 0) * 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 reduction root is used outside of the reduction any
              // number of times, its fmul operand is still fused into it. The
              // loop-carried chain is bound by its latency, so the fusion does
              // not make it cheaper than the vector code, which cuts the chain.
              if ((RdxKind == RecurKind::FAdd && RdxOp == ReductionRoot &&
                   !IsLoopCarriedRoot) ||
                  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(SLPReVec && "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.");
    ArrayRef<Value *> VL = R.getRootNodeScalars();
    auto *VTy = cast<FixedVectorType>(VectorizedValue->getType());
    if (VTy->getElementType() != VL.front()->getType()) {
      VectorizedValue = Builder.CreateIntCast(
          VectorizedValue,
          getWidenedType(VL.front()->getType(), VTy->getNumElements()),
          R.isSignedMinBitwidthRootNode());
    }
    switch (RdxKind) {
    case RecurKind::Add: {
      // root = mul prev_root, <1, 1, n, 1>
      SmallVector<Constant *> Vals;
      for (const auto [Idx, V] : enumerate(VL)) {
        unsigned Cnt = SameValuesCounter.lookup(TrackedToOrig[Idx]);
        // 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(
            V->getType(), APInt(V->getType()->getIntegerBitWidth(), Cnt,
                                /*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 (const auto [Idx, V] : enumerate(VL)) {
        unsigned Cnt = SameValuesCounter.lookup(TrackedToOrig[Idx]);
        if (Cnt % 2 == 0) {
          Mask[Idx] = VL.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 (const auto [Idx, V] : enumerate(VL)) {
        unsigned Cnt = SameValuesCounter.lookup(TrackedToOrig[Idx]);
        Vals.push_back(ConstantFP::get(V->getType(), Cnt));
      }
      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 std::optional<unsigned> getAggregateSize(Instruction *InsertInst) {
  if (auto *IE = dyn_cast<InsertElementInst>(InsertInst))
    return cast<FixedVectorType>(IE->getType())->getNumElements();

  unsigned AggregateSize = 1;
  auto *IV = cast<InsertValueInst>(InsertInst);
  Type *CurrentType = IV->getType();
  do {
    if (auto *ST = dyn_cast<StructType>(CurrentType)) {
      for (auto *Elt : ST->elements())
        if (Elt != ST->getElementType(0)) // check homogeneity
          return std::nullopt;
      AggregateSize *= ST->getNumElements();
      CurrentType = ST->getElementType(0);
    } else if (auto *AT = dyn_cast<ArrayType>(CurrentType)) {
      AggregateSize *= AT->getNumElements();
      CurrentType = AT->getElementType();
    } else if (auto *VT = dyn_cast<FixedVectorType>(CurrentType)) {
      AggregateSize *= VT->getNumElements();
      return AggregateSize;
    } else if (CurrentType->isSingleValueType()) {
      return AggregateSize;
    } else {
      return std::nullopt;
    }
  } while (true);
}

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;
}

/// Try and get a reduction instruction from a phi node.
///
/// Given a phi node \p P in a block \p ParentBB, consider possible reductions
/// if they come from either \p ParentBB or a containing loop latch.
///
/// \returns A candidate reduction value if possible, or \code nullptr \endcode
/// if not possible.
static Instruction *getReductionInstr(const DominatorTree *DT, PHINode *P,
                                      BasicBlock *ParentBB, LoopInfo *LI) {
  // There are situations where the reduction value is not dominated by the
  // reduction phi. Vectorizing such cases has been reported to cause
  // miscompiles. See PR25787.
  auto DominatedReduxValue = [&](Value *R) {
    return isa<Instruction>(R) &&
           DT->dominates(P->getParent(), cast<Instruction>(R)->getParent());
  };

  Instruction *Rdx = nullptr;

  // Return the incoming value if it comes from the same BB as the phi node.
  if (P->getIncomingBlock(0) == ParentBB) {
    Rdx = dyn_cast<Instruction>(P->getIncomingValue(0));
  } else if (P->getIncomingBlock(1) == ParentBB) {
    Rdx = dyn_cast<Instruction>(P->getIncomingValue(1));
  }

  if (Rdx && DominatedReduxValue(Rdx))
    return Rdx;

  // Otherwise, check whether we have a loop latch to look at.
  Loop *BBL = LI->getLoopFor(ParentBB);
  if (!BBL)
    return nullptr;
  BasicBlock *BBLatch = BBL->getLoopLatch();
  if (!BBLatch)
    return nullptr;

  // There is a loop latch, return the incoming value if it comes from
  // that. This reduction pattern occasionally turns up.
  if (P->getIncomingBlock(0) == BBLatch) {
    Rdx = dyn_cast<Instruction>(P->getIncomingValue(0));
  } else if (P->getIncomingBlock(1) == BBLatch) {
    Rdx = dyn_cast<Instruction>(P->getIncomingValue(1));
  }

  if (Rdx && DominatedReduxValue(Rdx))
    return Rdx;

  return nullptr;
}

/// 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 (!ShouldVectorizeHor)
    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;
    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;
        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 < RecursionMaxDepth)
      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, SLPReVec) || Ty->isPointerTy())
      return false;
    HorizontalReduction HorRdx(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 (!ShouldVectorizeHor || SLPReVec || 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, RecursionMaxDepth, 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 >= -SLPCostThreshold)
    return false;

  Value *Vec = R.vectorizeTree({}, IVI);
  assert(Vec->getType() == FieldsTy && "Expected the vector of the fields.");
  IRBuilder<TargetFolder> Builder(IVI->getContext(), TargetFolder(DL));
  Builder.SetInsertPoint(IVI);
  Builder.SetCurrentDebugLocation(IVI->getDebugLoc());
  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(), SLPReVec) &&
      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)))
    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(
    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) {
  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, SLPReVec), SLPReVec)) {
      ++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));
    }

    // 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(Value *V, Value *V2, TargetLibraryInfo &TLI,
                       const DominatorTree &DT) {
  assert(isValidElementType(V->getType(), SLPReVec) &&
         isValidElementType(V2->getType(), SLPReVec) &&
         "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>(V, V2, *TLI, *DT);
  };

  auto AreCompatibleCompares = [&](ArrayRef<Value *> VL, Value *V1) {
    if (VL.empty() || VL.back() == V1)
      return true;
    return compareCmp<true>(V1, VL.back(), *TLI, *DT);
  };

  SmallVector<Value *> Vals;
  for (Instruction *V : CmpInsts)
    if (!R.isDeleted(V) &&
        isValidElementType(getValueType(V, SLPReVec, /*LookThroughCmp=*/true),
                           SLPReVec))
      Vals.push_back(V);
  if (Vals.size() <= 1)
    return Changed;
  Changed |= tryToVectorizeSequence<Value>(
      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 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 SLPReVec || !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 &&
           (SLPReVec || !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(Instruction *I, Func F,
                                         bool ForReduction) {
  if (auto *CB = dyn_cast<CallBase>(I)) {
    if (ForReduction && !NonVectReductions && 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 && !NonVectReductions)
    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(
        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(), SLPReVec))
            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(
        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(), SLPReVec) &&
               !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>(
      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;
  // 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(), SLPReVec) &&
           isValidElementType(V2->getType(), SLPReVec) &&
           "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(), SLPReVec))
        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>(
        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));
  };
  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 = ShouldStartVectorizeHorAtStore || !SI;
      if (SI) {
        auto *I = Stores.find(getUnderlyingObject(SI->getPointerOperand()));
        // Try to vectorize chain in store, if this is the only store to the
        // address in the block.
        // 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 |= (I == Stores.end() || I->second.size() == 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) || It->isDebugOrPseudoInst() ||
        R.isEphemeralValue(&*It))
      continue;

    if (isa<InsertElementInst, InsertValueInst>(It))
      PostProcessInserts.insert(&*It);
    else if (auto *CI = dyn_cast<CmpInst>(It))
      PostProcessCmps.insert(CI);
    else if (auto *SI = dyn_cast<StoreInst>(It);
             SI &&
             (SLPReVec || !SI->getValueOperand()->getType()->isVectorTy()) &&
             isa<Instruction>(SI->getValueOperand()))
      PostProcessStores.insert(SI);
    else if (isNonVectorizableInst(&*It, TLI))
      PostProcessInsts.insert(&*It);
    else if (VectorizePoorThroughput &&
             isPoorThroughputOp(&*It, *TTI, *TLI, PoorThroughputCache,
                                R.getCostKind()))
      PoorThroughputSeeds.insert(&*It);
  }

  // Late post-process: run operand-chain vectorization for stores.
  if (!PostProcessStores.empty() &&
      (NonVectReductions || PostProcessStores.size() >= 2)) {
    bool TryVectorize = true;
    if (!ForcePostProcessStoresOperands && SLPCostThreshold >= 0) {
      // Use pessimistic cost estimation to avoid long compile time when there
      // are many stores in the list.
      Type *ScalarTy = getValueType(PostProcessStores.front(), SLPReVec);
      if (!::isValidElementType(ScalarTy, SLPReVec)) {
        TryVectorize = false;
      } else {
        auto *IF =
            dyn_cast<Instruction>(PostProcessStores.front()->getValueOperand());
        auto *IB =
            dyn_cast<Instruction>(PostProcessStores.back()->getValueOperand());
        if (!NonVectReductions && 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, SLPReVec, 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);
    }
  }

  if (PoorThroughputSeeds.size() >= 2) {
    SmallVector<Value *> Seeds;
    SmallDenseMap<Value *, SeedGroupKey> SeedKeys;
    for (Instruction *I :
         make_filter_range(PoorThroughputSeeds, [&](Instruction *I) {
           return !R.isDeleted(I) &&
                  isValidElementType(getValueType(I, SLPReVec), SLPReVec) &&
                  !R.hasResolvedUser(I);
         })) {
      SeedKeys.try_emplace(I, getSeedGroupKey(I, *TLI));
      Seeds.push_back(I);
    }
    Changed |= vectorizeSeeds(
        Seeds,
        [&](Value *V1, Value *V2) {
          return SeedKeys.at(V1).less(SeedKeys.at(V2));
        },
        R);
  }

  return Changed;
}

bool SLPVectorizerPass::vectorizeSeeds(
    SmallVectorImpl<Value *> &Seeds,
    function_ref<bool(Value *, Value *)> IsLessGroup, BoUpSLP &R) {
  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>(
      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);
}

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, SLPReVec), SLPReVec) &&
                isOnceUsedSeed(&I) && !isNonVectorizableInst(&I, TLI) &&
                !R.hasResolvedUser(&I);
       })) {
    // The poor-throughput ops are seeded on their own, with the different
    // grouping.
    if (VectorizePoorThroughput &&
        isPoorThroughputOp(&I, *TTI, *TLI, PoorThroughputCache,
                           R.getCostKind()))
      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;
  // 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. 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]);
        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]);
          if (isa<SCEVConstant>(SE->getMinusSCEV(SCEVI, SCEVJ))) {
            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();
  });
  for (auto &Pair :
       make_filter_range(make_pointee_range(Groups),
                         [](auto &Pair) { return Pair.second.size() >= 2; })) {
    LLVM_DEBUG(dbgs() << "SLP: Analyzing a store chain of length "
                      << Pair.second.size() << ".\n");

    if (!isValidElementType(Pair.second.front()->getValueOperand()->getType(),
                            SLPReVec))
      continue;

    // Masked stores are only attempted when no consecutive pair exists in the
    // full base-object group.
    const bool AllowMaskedStores =
        EnableMaskedStores && !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());
    Changed |= tryToVectorizeSequence<StoreInst>(
        ReversedStores, StoreSorter, AreCompatibleStores,
        [&](ArrayRef<StoreInst *> Candidates, bool) {
          return vectorizeStores(Candidates, R, Attempted, AllowMaskedStores);
        },
        /*MaxVFOnly=*/false, R);
  }
  return Changed;
}
