//===- 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)
      : BatchAA(*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->getContext(), 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 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_if_present<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_or_null<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;

  /// Return information about the vector formed for the specified index
  /// of a vector of (the same) instruction.
  TargetTransformInfo::OperandValueInfo
  getOperandInfo(ArrayRef<Value *> Ops) 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;

  // Cache for pointerMayBeCaptured calls inside AA.  This is preserved
  // globally through SLP because we don't perform any action which
  // invalidates capture results.
  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;

    if (!all_of(PointerOps, [&](Value *P) {
          return arePointersCompatible(P, PointerOps.front(), *TLI,
                                       RecursionMaxDepth);
        }))
      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_or_null<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_or_null<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: {
    // We don't combine GEPs with complicated (nested) indexing.
    for (GetElementPtrInst *I : make_isa_range<GetElementPtrInst>(VL)) {
      if (I->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_isa_range<GEPOperator>(VL)) {
      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 *I : make_isa_range<GetElementPtrInst>(VL)) {
      auto *Op = I->getOperand(1);
      if ((!IsScatterVectorizeUserTE && !isa<ConstantInt>(Op)) ||
          (Op->getType() != Ty1 &&
           ((IsScatterVectorizeUserTE && !isa<ConstantInt>(Op)) ||
            Op->getType()->getScalarSizeInBits() >
                DL->getIndexSizeInBits(
                    I->getType()->getPointerAddressSpace())))) {
        LLVM_DEBUG(
            dbgs() << "SLP: not-vectorizable GEP (non-constant indexes).\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 CheckLoads = [&](ArrayRef<Value *> Loads, bool IncludeGather) {
      assert(S && S.getOpcode() == Instruction::Load && "Expected load.");
      BoUpSLP::OrdersType Order;
      SmallVector<Value *> PointerOps;
      BoUpSLP::StridedPtrInfo SPtrInfo;
      BoUpSLP::LoadsState Res = R.canVectorizeLoads(Loads, S.getMainOp(), Order,
                                                    PointerOps, SPtrInfo);
      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))
        return std::make_pair(true, !UniquesVectorized);
    }
    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 = getOperandInfo(Ops0);
    TTI::OperandValueInfo Op1Info =
        Ops1.empty() ? TTI::OperandValueInfo() : 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.
  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()));
  }

  /// 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;
      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 (isa<PoisonValue>(V) || SelfOp)
      return {V, V};
    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};
    }
    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 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});
      // Need to cast all indices to the same type before vectorization to
      // avoid crash.
      // Required to be able to find correct matches between different gather
      // nodes and reuse the vectorized values rather than trying to gather them
      // again.
      const unsigned IndexIdx = 1;
      Type *VL0Ty = VL0->getOperand(IndexIdx)->getType();
      Type *Ty = all_of(make_isa_range<GetElementPtrInst>(VL),
                        [&](GetElementPtrInst *GEP) {
                          return VL0Ty == GEP->getOperand(IndexIdx)->getType();
                        })
                     ? VL0Ty
                     : DL.getIndexType(cast<GetElementPtrInst>(VL0)
                                           ->getPointerOperandType()
                                           ->getScalarType());
      for (auto [Idx, V] : enumerate(VL)) {
        auto *GEP = dyn_cast<GetElementPtrInst>(V);
        if (!GEP) {
          Operands[0][Idx] = V;
          Operands[1][Idx] = ConstantInt::getNullValue(Ty);
          continue;
        }
        Operands[0][Idx] = GEP->getPointerOperand();
        auto *Op = GEP->getOperand(IndexIdx);
        auto *CI = dyn_cast<ConstantInt>(Op);
        Operands[1][Idx] = CI ? ConstantFoldIntegerCast(
                                    CI, Ty, CI->getValue().isSignBitSet(), DL)
                              : Op;
      }
      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);
    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); });
    // 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 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; defer
      // to the full tree cost computation instead of pre-rejecting here.
      if (MainOpcode == Instruction::Call)
        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;
    }
    // fmuladd is the only 3-operand copyable.
    assert((Operands.size() == 2 ||
            (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;
    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;
    };
    // 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;
      }
      // 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;
  // 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 {
        for (Value *V : TE.Scalars) {
          if (!isConstant(V))
            ++Count;
        }
      }
      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 (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;
    ++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;
}

TTI::OperandValueInfo BoUpSLP::getOperandInfo(ArrayRef<Value *> Ops) const {
  assert(!Ops.empty());
  const auto *Op0 = Ops.front();

  const bool IsConstant = all_of(Ops, [](Value *V) {
    // TODO: We should allow undef elements here
    return isConstant(V) && !isa<UndefValue>(V);
  });
  const bool IsUniform = all_of(Ops, [=](Value *V) {
    // TODO: We should allow undef elements here
    return V == Op0;
  });
  const bool IsPowerOfTwo = all_of(Ops, [](Value *V) {
    // TODO: We should allow undef elements here
    if (auto *CI = dyn_cast<ConstantInt>(V))
      return CI->getValue().isPowerOf2();
    return false;
  });
  const bool IsNegatedPowerOfTwo = all_of(Ops, [](Value *V) {
    // TODO: We should allow undef elements here
    if (auto *CI = dyn_cast<ConstantInt>(V))
      return CI->getValue().isNegatedPowerOf2();
    return false;
  });

  TTI::OperandValueKind VK = TTI::OK_AnyValue;
  if (IsConstant && IsUniform)
    VK = TTI::OK_UniformConstantValue;
  else if (IsConstant)
    VK = TTI::OK_NonUniformConstantValue;
  else if (IsUniform)
    VK = TTI::OK_UniformValue;

  TTI::OperandValueProperties VP = TTI::OP_None;
  VP = IsPowerOfTwo ? TTI::OP_PowerOf2 : VP;
  VP = IsNegatedPowerOfTwo ? TTI::OP_NegatedPowerOf2 : VP;

  return {VK, VP};
}

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, getOperandInfo(LhsTE->Scalars),
          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,
                                  getOperandInfo(LhsTE->Scalars),
                                  getOperandInfo(ShiftTE->Scalars), /*Args=*/{},
                                  ShlTE->getMainOp(), TLI);
  if (TE.getOpcode() == Instruction::And)
    VecCost += TTI->getArithmeticInstrCost(
        Instruction::And, VecTy, CostKind, getOperandInfo(ShlTE->Scalars),
        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,
      getOperandInfo(CmpTE->getOperand(0)),
      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, getOperandInfo(Op1TE->Scalars),
                              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);
        InstructionCost StridedCost = TTI->getMemIntrinsicInstrCost(
            MemIntrinsicCostAttributes(Intrinsic::experimental_vp_strided_load,
                                       VecTy, BaseLI->getPointerOperand(),
                                       /*VariableMask=*/false, CommonAlignment,
                                       BaseLI),
            CostKind);
        if (StridedCost < OriginalVecCost || ForceStridedLoads) {
          // Strided load is more profitable than consecutive load + reverse -
          // transform the node to strided load.
          Type *StrideTy = DL->getIndexType(cast<LoadInst>(E.Scalars.front())
                                                ->getPointerOperand()
                                                ->getType());
          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,
                                 getOperandInfo(E.getOperand(0))) +
            getShuffleCost(*TTI, TTI::SK_Reverse, VecTy, CostKind, Mask);
        InstructionCost StridedCost = TTI->getMemIntrinsicInstrCost(
            MemIntrinsicCostAttributes(Intrinsic::experimental_vp_strided_store,
                                       VecTy, BaseSI->getPointerOperand(),
                                       /*VariableMask=*/false, CommonAlignment,
                                       BaseSI),
            CostKind);
        if (StridedCost < OriginalVecCost) {
          // Strided store is more profitable than reverse + consecutive store -
          // transform the node to strided store.
          E.State = TreeEntry::StridedVectorize;
          Type *StrideTy = DL->getIndexType(cast<StoreInst>(E.Scalars.front())
                                                ->getPointerOperand()
                                                ->getType());
          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.
  if (TE.isGather())
    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,
              getOperandInfo(VI->getOperand(0)), 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,
              getOperandInfo(VI->getOperand(0)), 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,
            getOperandInfo(
                VI->getOperand(ShuffleOrOp == Instruction::Select ? 1 : 0)),
            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, getOperandInfo(Cond),
                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, getOperandInfo(Cond),
                getOperandInfo(LHS));
          }
        }
      }
      if (!VecCost.isValid()) {
        VecCost = TTI->getCmpSelInstrCost(
            E->getOpcode(), VecTy, MaskTy, VecPred, CostKind,
            getOperandInfo(
                E->getOperand(ShuffleOrOp == Instruction::Select ? 1 : 0)),
            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 = getOperandInfo(E->getOperand(0));
      TTI::OperandValueInfo Op2Info = 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, {},
              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());
        VecLdCost = TTI->getMemIntrinsicInstrCost(
            MemIntrinsicCostAttributes(Intrinsic::experimental_vp_strided_load,
                                       StridedLoadTy, LI0->getPointerOperand(),
                                       /*VariableMask=*/false, CommonAlignment),
            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());
        VecStCost = TTI->getMemIntrinsicInstrCost(
            MemIntrinsicCostAttributes(Intrinsic::experimental_vp_strided_store,
                                       StridedStoreTy,
                                       BaseSI->getPointerOperand(),
                                       /*VariableMask=*/false, CommonAlignment),
            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 = 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 = getOperandInfo(E->getOperand(0));
          for (unsigned Idx : seq<unsigned>(1, E->getNumOperands())) {
            TTI::OperandValueInfo ColInfo = 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 = getOperandInfo(E->getOperand(0));
        TTI::OperandValueInfo Op1Info = 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)) {
        InstructionCost AltVecCost = TTIRef.getAltInstrCost(
            cast<VectorType>(VecTy), Opcode0, Opcode1, OpcodeMask, CostKind);
        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_or_null<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_or_null<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 = dyn_cast_or_null<PHINode>(
          TEUseEI.UserTE->hasState() ? 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_or_null<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(LastInst->getParent(), LastInstIt);
  } else {
    // Set the insertion point after the last instruction in the bundle. Set the
    // debug location to Front.
    Builder.SetInsertPoint(
        LastInst->getParent(),
        LastInst->getNextNode()->getIterator());
    if (Instruction *Res = LastInstructionToPos.lookup(LastInst)) {
      Builder.SetInsertPoint(LastInst->getParent(), Res->getIterator());
    } else {
      Res = Builder.CreateAlignedLoad(Builder.getPtrTy(),
                                      PoisonValue::get(Builder.getPtrTy()),
                                      MaybeAlign());
      Builder.SetInsertPoint(LastInst->getParent(), 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_or_null<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(),
                             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(),
                             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_or_null<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, 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->getParent(),
                           ReductionRoot->getIterator());
  else
    Builder.SetInsertPoint(&F->getEntryBlock(), 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));
        }
        // 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(
                PHI->getParent(),
                std::next(
                    PHI->getParent()->getLandingPadInst()->getIterator()));
          else
            Builder.SetInsertPoint(PHI->getParent(),
                                   PHI->getParent()->getFirstNonPHIIt());
        } else {
          Builder.SetInsertPoint(VecI->getParent(),
                                 std::next(VecI->getIterator()));
        }
      } else {
        Builder.SetInsertPoint(&F->getEntryBlock(), 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(IVec->getParent(),
                                         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(VecI->getParent(),
                                     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(), 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);

  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->getParent(),
                           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();
  auto IsAssumeLikeIntr = [](const Instruction &I) {
    if (auto *II = dyn_cast<IntrinsicInst>(&I))
      return II->isAssumeLikeIntrinsic();
    return false;
  };
  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;
    for (unsigned I = NextInst; I < MaxInst; ++I) {
      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;
      bool DependentSkipped = false;
      for (Value *V : 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); })) {
          DependentSkipped = true;
          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 (!DependentSkipped)
          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.
        I += VF - 1;
        NextInst = I + 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(ReductionRoot->getContext(),
                                    TargetFolder(DL));
    Builder.SetInsertPoint(cast<Instruction>(ReductionRoot));
    // 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;
          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];
      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");

    IRBuilder<TargetFolder> Builder(ReductionRoot->getContext(),
                                    TargetFolder(DL));
    Instruction *RdxRootInst = cast<Instruction>(ReductionRoot);
    Builder.SetInsertPoint(RdxRootInst);

    // 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);
    };
    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.
              if ((RdxKind == RecurKind::FAdd && RdxOp == ReductionRoot) ||
                  hasRequiredNumberOfUses(IsCmpSelMinMax, RdxOp)) {
                InstructionsState RdxOpS = RdxKind == RecurKind::FAdd
                                               ? getSameOpcode(RdxOp, TLI)
                                               : InstructionsState::invalid();
                // The reduced value itself must be a fusable fmul, whose cost
                // is excluded.
                if (RdxOpS && RdxOpS.isAddSubOrFNegLikeOp() &&
                    isFusableFMulOperand(RdxVal, RdxOp, *TTI)) {
                  InstructionCost FMACost =
                      canConvertToFMA(RdxOp, RdxOpS, DT, DL, *TTI, TLI, R);
                  if (FMACost.isValid()) {
                    LLVM_DEBUG(dbgs() << "FMA cost: " << FMACost << "\n");
                    // Also, exclude scalar fmul cost.
                    InstructionCost FMulCost =
                        TTI->getInstructionCost(RdxVal, CostKind);
                    LLVM_DEBUG(dbgs()
                               << "Minus FMul cost: " << FMulCost << "\n");
                    FMACost -= FMulCost;
                    ScalarCost += FMACost;
                    continue;
                  }
                }
                ScalarCost += TTI->getInstructionCost(RdxOp, CostKind);
                continue;
              }
              ScalarCost = InstructionCost::getInvalid();
              break;
            }
            if (ScalarCost.isValid())
              Cost += ScalarCost;
            else
              Cost += GenCostFn(RdxOp);
          }
          return Cost;
        };
    // Require reduction cost if:
    // 1. This type is not a full register type and no other vectors with the
    // same type in the storage (first vector with small type).
    // 2. The storage does not have any vector with full vector use (first
    // vector with full register use).
    bool DoesRequireReductionOp = !AllConsts && VectorValuesAndScales.empty();
    switch (RdxKind) {
    case RecurKind::Add:
    case RecurKind::Mul:
    case RecurKind::Or:
    case RecurKind::And:
    case RecurKind::Xor:
    case RecurKind::FAdd:
    case RecurKind::FMul: {
      unsigned RdxOpcode = RecurrenceDescriptor::getOpcode(RdxKind);
      Type *BoolReduxWideTy =
          getBoolReduxWideTy(RdxKind, ReductionRoot->getType(), ScalarTy);
      if (!AllConsts) {
        if (!NarrowedLeafShifts.empty()) {
          Type *WideTy = ReductionRoot->getType();
          auto *NarrowVecTy =
              cast<VectorType>(getWidenedType(ScalarTy, ReduxWidth));
          auto *WideVecTy =
              cast<VectorType>(getWidenedType(WideTy, ReduxWidth));
          if (DoesRequireReductionOp) {
            VectorCost = TTI->getExtendedReductionCost(
                RdxOpcode, /*IsUnsigned=*/true, WideTy, NarrowVecTy, FMF,
                CostKind);
          } else {
            VectorCost =
                TTI->getCastInstrCost(Instruction::ZExt, WideVecTy, NarrowVecTy,
                                      TTI::CastContextHint::None, CostKind) +
                TTI->getArithmeticInstrCost(RdxOpcode, WideVecTy, CostKind);
          }
          for (Instruction *I : NarrowedChainInsts)
            VectorCost -= TTI->getInstructionCost(I, CostKind);
          VectorCost += getNarrowedLeafOpsCost(
              *TTI, NarrowedLeafShifts, NarrowVecTy, WideVecTy,
              cast<Instruction>(ReductionRoot), CostKind);
          // The boolean bitmask emission may be cheaper. Restricted to the
          // first vector part, same as in the emission.
          BoolBitmask Match =
              VectorValuesAndScales.empty() &&
                      NarrowedLeafShifts.size() == ReduxWidth &&
                      R.getRootNode().getVectorFactor() == ReduxWidth &&
                      R.getRootNode().ReuseShuffleIndices.empty()
                  ? isBoolBitmaskRdx(RdxKind, NarrowedLeafShifts, DL)
                  : BoolBitmask::None;
          if (Match != BoolBitmask::None) {
            SmallVector<int> PermMask =
                getBoolBitmaskPermMask(ReducedVals, TrackedToOrig, Pos, R);
            InstructionCost BitmaskCost = getBoolBitmaskCost(
                *TTI, Match == BoolBitmask::NeedMask, ScalarTy, WideTy,
                ReduxWidth, PermMask, ReductionRoot, CostKind);
            for (Instruction *I : NarrowedChainInsts)
              BitmaskCost -= TTI->getInstructionCost(I, CostKind);
            VectorCost = std::min(VectorCost, BitmaskCost);
          }
        } else if (DoesRequireReductionOp) {
          if (auto *VecTy = dyn_cast<FixedVectorType>(ScalarTy)) {
            assert(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;
}

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