//===- 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/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/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> 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."));

/// True when \p slp-vectorize-non-power-of-2 is enabled and \p NumElts is a
/// supported non-power-of-2 width: \p NumElts + 1 must be a power of two
/// (e.g. 3 or 7 lanes, i.e. almost a full power-of-2 register).
static bool isAllowedNonPowerOf2VF(unsigned NumElts) {
  return VectorizeNonPowerOf2 && has_single_bit(NumElts + 1);
}

/// 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."));

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."));

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

/// Predicate for the element types that the SLP vectorizer supports.
///
/// The most important thing to filter here are types which are invalid in LLVM
/// vectors. We also filter target specific types which have absolutely no
/// meaningful vectorization path such as x86_fp80 and ppc_f128. This just
/// avoids spending time checking the cost model and realizing that they will
/// be inevitably scalarized.
static bool isValidElementType(Type *Ty) {
  // TODO: Support ScalableVectorType.
  if (SLPReVec && isVectorizedTy(Ty) && !getVectorizedTypeVF(Ty).isScalable())
    Ty = toScalarizedTy(Ty);
  return canVectorizeTy(Ty) && !Ty->isX86_FP80Ty() && !Ty->isPPC_FP128Ty() &&
         !Ty->isVoidTy();
}

/// Returns the "element type" of the given value/instruction \p V.
/// For stores, returns the stored value type; for insertelement (when ReVec is
/// off), the inserted operand type. For compares, the default is to return the
/// result type (i1); when \p LookThroughCmp is true, returns the type of the
/// compared operands instead, which is needed for vector width calculations
/// (the width is determined by the operand type, not the i1 result).
static Type *getValueType(Value *V, bool LookThroughCmp = false) {
  if (auto *SI = dyn_cast<StoreInst>(V))
    return SI->getValueOperand()->getType();
  if (LookThroughCmp)
    if (auto *CI = dyn_cast<CmpInst>(V))
      return CI->getOperand(0)->getType();
  if (!SLPReVec)
    if (auto *IE = dyn_cast<InsertElementInst>(V))
      return IE->getOperand(1)->getType();
  if (auto *IV = dyn_cast<InsertValueInst>(V))
    return IV->getOperand(1)->getType();
  return V->getType();
}

/// \returns the vector type of ScalarTy based on vectorization factor.
static Type *getWidenedType(Type *ScalarTy, unsigned VF) {
  if (VF == 1 && !isVectorizedTy(ScalarTy)) {
    // Workaround for 1 x vector types: toVectorizedTy returns the type
    // unchanged when EC is scalar, but BoUpSLP relies on widening to
    // <1 x ScalarTy> (or struct of <1 x ElTy>) to keep the rest of the
    // pipeline operating on vector types.
    if (auto *StructTy = dyn_cast<StructType>(ScalarTy)) {
      assert(isUnpackedStructLiteral(StructTy) &&
             "expected unpacked struct literal");
      assert(all_of(StructTy->elements(), VectorType::isValidElementType) &&
             "expected all element types to be valid vector element types");
      return StructType::get(
          StructTy->getContext(),
          map_to_vector(StructTy->elements(), [&](Type *ElTy) -> Type * {
            return FixedVectorType::get(ElTy, 1);
          }));
    }
    return FixedVectorType::get(ScalarTy, 1);
  }
  return toVectorizedTy(toScalarizedTy(ScalarTy),
                        ElementCount::getFixed(VF * getNumElements(ScalarTy)));
}

/// Returns the number of elements of the given type \p Ty, not less than \p Sz,
/// which forms type, which splits by \p TTI into whole vector types during
/// legalization.
static unsigned getFullVectorNumberOfElements(const TargetTransformInfo &TTI,
                                              Type *Ty, unsigned Sz) {
  if (!isValidElementType(Ty) || isa<StructType>(Ty))
    return bit_ceil(Sz);
  // Find the number of elements, which forms full vectors.
  const unsigned NumParts = TTI.getNumberOfParts(getWidenedType(Ty, Sz));
  if (NumParts == 0 || NumParts >= Sz)
    return bit_ceil(Sz);
  return bit_ceil(divideCeil(Sz, NumParts)) * NumParts;
}

/// Returns the number of elements of the given type \p Ty, not greater than \p
/// Sz, which forms type, which splits by \p TTI into whole vector types during
/// legalization.
static unsigned
getFloorFullVectorNumberOfElements(const TargetTransformInfo &TTI, Type *Ty,
                                   unsigned Sz) {
  if (!isValidElementType(Ty) || isa<StructType>(Ty))
    return bit_floor(Sz);
  // Find the number of elements, which forms full vectors.
  unsigned NumParts = TTI.getNumberOfParts(getWidenedType(Ty, Sz));
  if (NumParts == 0 || NumParts >= Sz)
    return bit_floor(Sz);
  unsigned RegVF = bit_ceil(divideCeil(Sz, NumParts));
  if (RegVF > Sz)
    return bit_floor(Sz);
  return (Sz / RegVF) * RegVF;
}

/// Checks if the vector of instructions can be represented as a shuffle, like:
/// %x0 = extractelement <4 x i8> %x, i32 0
/// %x3 = extractelement <4 x i8> %x, i32 3
/// %y1 = extractelement <4 x i8> %y, i32 1
/// %y2 = extractelement <4 x i8> %y, i32 2
/// %x0x0 = mul i8 %x0, %x0
/// %x3x3 = mul i8 %x3, %x3
/// %y1y1 = mul i8 %y1, %y1
/// %y2y2 = mul i8 %y2, %y2
/// %ins1 = insertelement <4 x i8> poison, i8 %x0x0, i32 0
/// %ins2 = insertelement <4 x i8> %ins1, i8 %x3x3, i32 1
/// %ins3 = insertelement <4 x i8> %ins2, i8 %y1y1, i32 2
/// %ins4 = insertelement <4 x i8> %ins3, i8 %y2y2, i32 3
/// ret <4 x i8> %ins4
/// can be transformed into:
/// %1 = shufflevector <4 x i8> %x, <4 x i8> %y, <4 x i32> <i32 0, i32 3, i32 5,
///                                                         i32 6>
/// %2 = mul <4 x i8> %1, %1
/// ret <4 x i8> %2
/// Mask will return the Shuffle Mask equivalent to the extracted elements.
/// TODO: Can we split off and reuse the shuffle mask detection from
/// ShuffleVectorInst/getShuffleCost?
static std::optional<TargetTransformInfo::ShuffleKind>
isFixedVectorShuffle(ArrayRef<Value *> VL, SmallVectorImpl<int> &Mask,
                     AssumptionCache *AC) {
  const auto *It = find_if(VL, IsaPred<ExtractElementInst>);
  if (It == VL.end())
    return std::nullopt;
  unsigned Size = accumulate(VL, 0u, [](unsigned S, Value *V) {
    auto *EI = dyn_cast<ExtractElementInst>(V);
    if (!EI)
      return S;
    auto *VTy = dyn_cast<FixedVectorType>(EI->getVectorOperandType());
    if (!VTy)
      return S;
    return std::max(S, VTy->getNumElements());
  });

  Value *Vec1 = nullptr;
  Value *Vec2 = nullptr;
  bool HasNonUndefVec = any_of(VL, [&](Value *V) {
    auto *EE = dyn_cast<ExtractElementInst>(V);
    if (!EE)
      return false;
    Value *Vec = EE->getVectorOperand();
    if (isa<UndefValue>(Vec))
      return false;
    return isGuaranteedNotToBePoison(Vec, AC);
  });
  enum ShuffleMode { Unknown, Select, Permute };
  ShuffleMode CommonShuffleMode = Unknown;
  Mask.assign(VL.size(), PoisonMaskElem);
  for (unsigned I = 0, E = VL.size(); I < E; ++I) {
    // Undef can be represented as an undef element in a vector.
    if (isa<UndefValue>(VL[I]))
      continue;
    auto *EI = cast<ExtractElementInst>(VL[I]);
    if (isa<ScalableVectorType>(EI->getVectorOperandType()))
      return std::nullopt;
    auto *Vec = EI->getVectorOperand();
    // We can extractelement from undef or poison vector.
    if (isUndefVector</*isPoisonOnly=*/true>(Vec).all())
      continue;
    // All vector operands must have the same number of vector elements.
    if (isa<UndefValue>(Vec)) {
      Mask[I] = I;
    } else {
      if (isa<UndefValue>(EI->getIndexOperand()))
        continue;
      auto *Idx = dyn_cast<ConstantInt>(EI->getIndexOperand());
      if (!Idx)
        return std::nullopt;
      // Undefined behavior if Idx is negative or >= Size.
      if (Idx->getValue().uge(Size))
        continue;
      unsigned IntIdx = Idx->getValue().getZExtValue();
      Mask[I] = IntIdx;
    }
    if (isUndefVector(Vec).all() && HasNonUndefVec)
      continue;
    // For correct shuffling we have to have at most 2 different vector operands
    // in all extractelement instructions.
    if (!Vec1 || Vec1 == Vec) {
      Vec1 = Vec;
    } else if (!Vec2 || Vec2 == Vec) {
      Vec2 = Vec;
      Mask[I] += Size;
    } else {
      return std::nullopt;
    }
    if (CommonShuffleMode == Permute)
      continue;
    // If the extract index is not the same as the operation number, it is a
    // permutation.
    if (Mask[I] % Size != I) {
      CommonShuffleMode = Permute;
      continue;
    }
    CommonShuffleMode = Select;
  }
  // If we're not crossing lanes in different vectors, consider it as blending.
  if (CommonShuffleMode == Select && Vec2)
    return TargetTransformInfo::SK_Select;
  // If Vec2 was never used, we have a permutation of a single vector, otherwise
  // we have permutation of 2 vectors.
  return Vec2 ? TargetTransformInfo::SK_PermuteTwoSrc
              : TargetTransformInfo::SK_PermuteSingleSrc;
}

/// \returns true if \p Opcode is allowed as part of the main/alternate
/// instruction for SLP vectorization.
///
/// Example of unsupported opcode is SDIV that can potentially cause UB if the
/// "shuffled out" lane would result in division by zero.
static bool isValidForAlternation(unsigned Opcode) {
  return !Instruction::isIntDivRem(Opcode);
}

namespace {

/// Helper class that determines VL can use the same opcode.
/// Alternate instruction is supported. In addition, it supports interchangeable
/// instruction. An interchangeable instruction is an instruction that can be
/// converted to another instruction with same semantics. For example, x << 1 is
/// equal to x * 2. x * 1 is equal to x | 0.
class BinOpSameOpcodeHelper {
  using MaskType = std::uint_fast32_t;
  /// Sort SupportedOp because it is used by binary_search.
  constexpr static unsigned SupportedOp[] = {
      Instruction::Add, Instruction::FAdd, Instruction::Sub,  Instruction::FSub,
      Instruction::Mul, Instruction::Shl,  Instruction::AShr, Instruction::And,
      Instruction::Or,  Instruction::Xor};
  static_assert(llvm::is_sorted_constexpr(SupportedOp) &&
                "SupportedOp is not sorted.");
  enum : MaskType {
    ShlBIT = 1,
    AShrBIT = 1 << 1,
    MulBIT = 1 << 2,
    AddBIT = 1 << 3,
    SubBIT = 1 << 4,
    AndBIT = 1 << 5,
    OrBIT = 1 << 6,
    XorBIT = 1 << 7,
    FAddBIT = 1 << 8,
    FSubBIT = 1 << 9,
    MainOpBIT = 1 << 10,
    LLVM_MARK_AS_BITMASK_ENUM(MainOpBIT)
  };
  /// Return a non-nullptr if either operand of I is a ConstantInt (for the
  /// integer opcodes) or a ConstantFP (for FAdd/FSub).
  /// The second return value represents the operand position. We check the
  /// right-hand side first (1). If the right hand side is not a constant and
  /// the instruction is neither Sub, FSub, Shl, nor AShr, we then check the
  /// left hand side (0).
  static std::pair<Constant *, unsigned>
  isBinOpWithConstant(const Instruction *I) {
    [[maybe_unused]] unsigned Opcode = I->getOpcode();
    assert(binary_search(SupportedOp, Opcode) && "Unsupported opcode.");
    (void)SupportedOp;
    auto *BinOp = cast<BinaryOperator>(I);
    auto GetConstant = [](Value *V) -> Constant * {
      if (auto *CI = dyn_cast<ConstantInt>(V))
        return CI;
      return dyn_cast<ConstantFP>(V);
    };
    if (Constant *C = GetConstant(BinOp->getOperand(1)))
      return {C, 1};
    if (!isCommutative(I))
      return {nullptr, 0};
    if (Constant *C = GetConstant(BinOp->getOperand(0)))
      return {C, 0};
    return {nullptr, 0};
  }
  struct InterchangeableInfo {
    const Instruction *I = nullptr;
    /// The bit it sets represents whether MainOp can be converted to.
    MaskType Mask = MainOpBIT | XorBIT | OrBIT | AndBIT | SubBIT | AddBIT |
                    MulBIT | AShrBIT | ShlBIT | FSubBIT | FAddBIT;
    /// We cannot create an interchangeable instruction that does not exist in
    /// VL. For example, VL [x + 0, y * 1] can be converted to [x << 0, y << 0],
    /// but << does not exist in VL. In the end, we convert VL to [x * 1, y *
    /// 1]. SeenBefore is used to know what operations have been seen before.
    MaskType SeenBefore = 0;
    InterchangeableInfo(const Instruction *I) : I(I) {}
    /// Return false allows BinOpSameOpcodeHelper to find an alternate
    /// instruction. Directly setting the mask will destroy the mask state,
    /// preventing us from determining which instruction it should convert to.
    bool trySet(MaskType OpcodeInMaskForm, MaskType InterchangeableMask) {
      if (Mask & InterchangeableMask) {
        SeenBefore |= OpcodeInMaskForm;
        Mask &= InterchangeableMask;
        return true;
      }
      return false;
    }
    bool equal(unsigned Opcode) {
      return Opcode == I->getOpcode() && trySet(MainOpBIT, MainOpBIT);
    }
    unsigned getOpcode() const {
      MaskType Candidate = Mask & SeenBefore;
      if (Candidate & MainOpBIT)
        return I->getOpcode();
      if (Candidate & ShlBIT)
        return Instruction::Shl;
      if (Candidate & AShrBIT)
        return Instruction::AShr;
      if (Candidate & MulBIT)
        return Instruction::Mul;
      if (Candidate & AddBIT)
        return Instruction::Add;
      if (Candidate & SubBIT)
        return Instruction::Sub;
      if (Candidate & FAddBIT)
        return Instruction::FAdd;
      if (Candidate & FSubBIT)
        return Instruction::FSub;
      if (Candidate & AndBIT)
        return Instruction::And;
      if (Candidate & OrBIT)
        return Instruction::Or;
      if (Candidate & XorBIT)
        return Instruction::Xor;
      llvm_unreachable("Cannot find interchangeable instruction.");
    }

    bool hasDefinedOpcode() const { return (Mask & SeenBefore) > 0; }

    /// Return true if the instruction can be converted to \p Opcode.
    bool hasCandidateOpcode(unsigned Opcode) const {
      MaskType Candidate = Mask & SeenBefore;
      switch (Opcode) {
      case Instruction::Shl:
        return Candidate & ShlBIT;
      case Instruction::AShr:
        return Candidate & AShrBIT;
      case Instruction::Mul:
        return Candidate & MulBIT;
      case Instruction::Add:
        return Candidate & AddBIT;
      case Instruction::Sub:
        return Candidate & SubBIT;
      case Instruction::And:
        return Candidate & AndBIT;
      case Instruction::Or:
        return Candidate & OrBIT;
      case Instruction::Xor:
        return Candidate & XorBIT;
      case Instruction::FAdd:
        return Candidate & FAddBIT;
      case Instruction::FSub:
        return Candidate & FSubBIT;
      case Instruction::LShr:
      case Instruction::FMul:
      case Instruction::SDiv:
      case Instruction::UDiv:
      case Instruction::FDiv:
      case Instruction::SRem:
      case Instruction::URem:
      case Instruction::FRem:
        return false;
      default:
        break;
      }
      llvm_unreachable("Cannot find interchangeable instruction.");
    }

    SmallVector<Value *> getOperand(const Instruction *To) const {
      unsigned ToOpcode = To->getOpcode();
      unsigned FromOpcode = I->getOpcode();
      if (FromOpcode == ToOpcode)
        return SmallVector<Value *>(I->operands());
      assert(binary_search(SupportedOp, ToOpcode) && "Unsupported opcode.");
      auto [C, Pos] = isBinOpWithConstant(I);
      Type *RHSType = I->getOperand(Pos)->getType();
      Constant *RHS;
      if (auto *CFP = dyn_cast<ConstantFP>(C)) {
        // fsub(x, c) == fadd(x, -c) for every FP constant c, since IEEE 754
        // defines subtraction as addition of the negated operand.
        assert(is_contained({Instruction::FAdd, Instruction::FSub}, ToOpcode) &&
               "Cannot convert the instruction.");
        RHS = ConstantFP::get(RHSType, -CFP->getValueAPF());
      } else {
        auto *CI = cast<ConstantInt>(C);
        const APInt &FromCIValue = CI->getValue();
        unsigned FromCIValueBitWidth = FromCIValue.getBitWidth();
        switch (FromOpcode) {
        case Instruction::Shl:
          if (ToOpcode == Instruction::Add && FromCIValue.isOne())
            return {I->getOperand(0), I->getOperand(0)};
          if (ToOpcode == Instruction::Mul) {
            RHS = ConstantInt::get(
                RHSType, APInt::getOneBitSet(FromCIValueBitWidth,
                                             FromCIValue.getZExtValue()));
          } else {
            assert(FromCIValue.isZero() && "Cannot convert the instruction.");
            RHS = ConstantExpr::getBinOpIdentity(ToOpcode, RHSType,
                                                 /*AllowRHSConstant=*/true);
          }
          break;
        case Instruction::Mul:
          assert(FromCIValue.isPowerOf2() && "Cannot convert the instruction.");
          if (ToOpcode == Instruction::Shl) {
            RHS = ConstantInt::get(
                RHSType, APInt(FromCIValueBitWidth, FromCIValue.logBase2()));
          } else {
            assert(FromCIValue.isOne() && "Cannot convert the instruction.");
            RHS = ConstantExpr::getBinOpIdentity(ToOpcode, RHSType,
                                                 /*AllowRHSConstant=*/true);
          }
          break;
        case Instruction::Add:
        case Instruction::Sub:
          if (FromCIValue.isZero()) {
            RHS = ConstantExpr::getBinOpIdentity(ToOpcode, RHSType,
                                                 /*AllowRHSConstant=*/true);
          } else {
            assert(
                is_contained({Instruction::Add, Instruction::Sub}, ToOpcode) &&
                "Cannot convert the instruction.");
            APInt NegatedVal = APInt(FromCIValue);
            NegatedVal.negate();
            RHS = ConstantInt::get(RHSType, NegatedVal);
          }
          break;
        case Instruction::And:
          assert(FromCIValue.isAllOnes() && "Cannot convert the instruction.");
          RHS = ConstantExpr::getBinOpIdentity(ToOpcode, RHSType,
                                               /*AllowRHSConstant=*/true);
          break;
        default:
          assert(FromCIValue.isZero() && "Cannot convert the instruction.");
          RHS = ConstantExpr::getBinOpIdentity(ToOpcode, RHSType,
                                               /*AllowRHSConstant=*/true);
          break;
        }
      }
      Value *LHS = I->getOperand(1 - Pos);
      // If the target opcode is non-commutative (e.g., shl, sub),
      // force the variable to the left and the constant to the right.
      if (Pos == 1 || !Instruction::isCommutative(ToOpcode))
        return SmallVector<Value *>({LHS, RHS});

      return SmallVector<Value *>({RHS, LHS});
    }
  };
  InterchangeableInfo MainOp;
  InterchangeableInfo AltOp;
  bool isValidForAlternation(const Instruction *I) const {
    return ::isValidForAlternation(MainOp.I->getOpcode()) &&
           ::isValidForAlternation(I->getOpcode());
  }
  bool initializeAltOp(const Instruction *I) {
    if (AltOp.I)
      return true;
    if (!isValidForAlternation(I))
      return false;
    AltOp.I = I;
    return true;
  }

public:
  BinOpSameOpcodeHelper(const Instruction *MainOp,
                        const Instruction *AltOp = nullptr)
      : MainOp(MainOp), AltOp(AltOp) {}
  bool add(const Instruction *I) {
    assert(isa<BinaryOperator>(I) &&
           "BinOpSameOpcodeHelper only accepts BinaryOperator.");
    unsigned Opcode = I->getOpcode();
    MaskType OpcodeInMaskForm;
    // Prefer Shl, AShr, Mul, Add, Sub, And, Or, Xor, FAdd and FSub over
    // MainOp.
    switch (Opcode) {
    case Instruction::Shl:
      OpcodeInMaskForm = ShlBIT;
      break;
    case Instruction::AShr:
      OpcodeInMaskForm = AShrBIT;
      break;
    case Instruction::Mul:
      OpcodeInMaskForm = MulBIT;
      break;
    case Instruction::Add:
      OpcodeInMaskForm = AddBIT;
      break;
    case Instruction::Sub:
      OpcodeInMaskForm = SubBIT;
      break;
    case Instruction::And:
      OpcodeInMaskForm = AndBIT;
      break;
    case Instruction::Or:
      OpcodeInMaskForm = OrBIT;
      break;
    case Instruction::Xor:
      OpcodeInMaskForm = XorBIT;
      break;
    case Instruction::FAdd:
      OpcodeInMaskForm = FAddBIT;
      break;
    case Instruction::FSub:
      OpcodeInMaskForm = FSubBIT;
      break;
    default:
      return MainOp.equal(Opcode) ||
             (initializeAltOp(I) && AltOp.equal(Opcode));
    }
    MaskType InterchangeableMask = OpcodeInMaskForm;
    auto [C, Pos] = isBinOpWithConstant(I);
    if (auto *CI = dyn_cast_or_null<ConstantInt>(C)) {
      constexpr MaskType CanBeAll =
          XorBIT | OrBIT | AndBIT | SubBIT | AddBIT | MulBIT | AShrBIT | ShlBIT;
      const APInt &CIValue = CI->getValue();
      switch (Opcode) {
      case Instruction::Shl:
        if (CIValue.ult(CIValue.getBitWidth()))
          InterchangeableMask = CIValue.isZero() ? CanBeAll : MulBIT | ShlBIT;
        if (CIValue.isOne())
          InterchangeableMask |= AddBIT;
        break;
      case Instruction::Mul:
        if (CIValue.isOne()) {
          InterchangeableMask = CanBeAll;
          break;
        }
        if (CIValue.isPowerOf2())
          InterchangeableMask = MulBIT | ShlBIT;
        break;
      case Instruction::Add:
      case Instruction::Sub:
        InterchangeableMask = CIValue.isZero() ? CanBeAll : SubBIT | AddBIT;
        break;
      case Instruction::And:
        if (CIValue.isAllOnes())
          InterchangeableMask = CanBeAll;
        break;
      case Instruction::Xor:
        if (CIValue.isZero())
          InterchangeableMask = XorBIT | OrBIT | SubBIT | AddBIT;
        break;
      default:
        if (CIValue.isZero())
          InterchangeableMask = CanBeAll;
        break;
      }
    } else if (C && Pos == 1) {
      // FAdd/FSub with a constant RHS: negating the constant always
      // converts one into the other, so no value check is needed. A
      // constant LHS (Pos == 0, e.g. "0.0 - x") is excluded: unlike a
      // constant RHS, it cannot be moved to the other opcode without also
      // swapping the variable operand, which would misalign it against
      // lanes that keep their native opcode (their variable operand stays
      // on the other side).
      InterchangeableMask = FSubBIT | FAddBIT;
    }
    return MainOp.trySet(OpcodeInMaskForm, InterchangeableMask) ||
           (initializeAltOp(I) &&
            AltOp.trySet(OpcodeInMaskForm, InterchangeableMask));
  }
  unsigned getMainOpcode() const { return MainOp.getOpcode(); }
  bool hasDefinedMainOpcode() const { return MainOp.hasDefinedOpcode(); }
  /// Checks if the list of potential opcodes includes \p Opcode.
  bool hasCandidateOpcode(unsigned Opcode) const {
    return MainOp.hasCandidateOpcode(Opcode);
  }
  bool hasAltOp() const { return AltOp.I; }
  unsigned getAltOpcode() const {
    return hasAltOp() ? AltOp.getOpcode() : getMainOpcode();
  }
  bool hasDefinedAltOpcode() const {
    return !hasAltOp() || AltOp.hasDefinedOpcode();
  }
  SmallVector<Value *> getOperand(const Instruction *I) const {
    return MainOp.getOperand(I);
  }
};

/// Main data required for vectorization of instructions.
class InstructionsState {
  /// MainOp and AltOp are primarily determined by getSameOpcode. Currently,
  /// only BinaryOperator, CastInst, and CmpInst support alternate instructions
  /// (i.e., AltOp is not equal to MainOp; this can be checked using
  /// isAltShuffle).
  /// A rare exception is TrySplitNode, where the InstructionsState is derived
  /// from getMainAltOpsNoStateVL.
  /// For those InstructionsState that use alternate instructions, the resulting
  /// vectorized output ultimately comes from a shufflevector. For example,
  /// given a vector list (VL):
  /// VL[0] = add i32 a, e
  /// VL[1] = sub i32 b, f
  /// VL[2] = add i32 c, g
  /// VL[3] = sub i32 d, h
  /// The vectorized result would be:
  /// intermediated_0 = add <4 x i32> <a, b, c, d>, <e, f, g, h>
  /// intermediated_1 = sub <4 x i32> <a, b, c, d>, <e, f, g, h>
  /// result = shufflevector <4 x i32> intermediated_0,
  ///                        <4 x i32> intermediated_1,
  ///                        <4 x i32> <i32 0, i32 5, i32 2, i32 7>
  /// Since shufflevector is used in the final result, when calculating the cost
  /// (getEntryCost), we must account for the usage of shufflevector in
  /// GetVectorCost.
  Instruction *MainOp = nullptr;
  Instruction *AltOp = nullptr;
  /// Wether the instruction state represents copyable instructions.
  bool HasCopyables = false;

public:
  Instruction *getMainOp() const {
    assert(valid() && "InstructionsState is invalid.");
    return MainOp;
  }

  Instruction *getAltOp() const {
    assert(valid() && "InstructionsState is invalid.");
    return AltOp;
  }

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

  unsigned getAltOpcode() const { return getAltOp()->getOpcode(); }

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

  /// Checks if the instruction matches either the main or alternate opcode.
  /// \returns
  /// - MainOp if \param I matches MainOp's opcode directly or can be converted
  /// to it
  /// - AltOp if \param I matches AltOp's opcode directly or can be converted to
  /// it
  /// - nullptr if \param I cannot be matched or converted to either opcode
  Instruction *getMatchingMainOpOrAltOp(Instruction *I) const {
    assert(MainOp && "MainOp cannot be nullptr.");
    if (I->getOpcode() == MainOp->getOpcode())
      return MainOp;
    if (MainOp->getOpcode() == Instruction::Select &&
        I->getOpcode() == Instruction::ZExt && !isAltShuffle())
      return MainOp;
    // Prefer AltOp instead of interchangeable instruction of MainOp.
    assert(AltOp && "AltOp cannot be nullptr.");
    if (I->getOpcode() == AltOp->getOpcode())
      return AltOp;
    if (!I->isBinaryOp())
      return nullptr;
    BinOpSameOpcodeHelper Converter(MainOp);
    if (!Converter.add(I) || !Converter.add(MainOp))
      return nullptr;
    if (isAltShuffle() && !Converter.hasCandidateOpcode(MainOp->getOpcode())) {
      BinOpSameOpcodeHelper AltConverter(AltOp);
      if (AltConverter.add(I) && AltConverter.add(AltOp) &&
          AltConverter.hasCandidateOpcode(AltOp->getOpcode()))
        return AltOp;
    }
    if (Converter.hasAltOp() && !isAltShuffle())
      return nullptr;
    return Converter.hasAltOp() ? AltOp : MainOp;
  }

  /// Checks if main/alt instructions are shift operations.
  bool isShiftOp() const {
    return getMainOp()->isShift() && getAltOp()->isShift();
  }

  /// Checks if main/alt instructions are bitwise logic operations.
  bool isBitwiseLogicOp() const {
    return getMainOp()->isBitwiseLogicOp() && getAltOp()->isBitwiseLogicOp();
  }

  /// Checks if main/alt instructions are mul/div/rem/fmul/fdiv/frem operations.
  bool isMulDivLikeOp() const {
    constexpr std::array<unsigned, 8> MulDiv = {
        Instruction::Mul,  Instruction::FMul, Instruction::SDiv,
        Instruction::UDiv, Instruction::FDiv, Instruction::SRem,
        Instruction::URem, Instruction::FRem};
    return is_contained(MulDiv, getOpcode()) &&
           is_contained(MulDiv, getAltOpcode());
  }

  /// Checks if main/alt instructions are add/sub/fadd/fsub operations.
  bool isAddSubLikeOp() const {
    constexpr std::array<unsigned, 4> AddSub = {
        Instruction::Add, Instruction::Sub, Instruction::FAdd,
        Instruction::FSub};
    return is_contained(AddSub, getOpcode()) &&
           is_contained(AddSub, getAltOpcode());
  }

  /// Checks if main/alt instructions are cmp operations.
  bool isCmpOp() const {
    return (getOpcode() == Instruction::ICmp ||
            getOpcode() == Instruction::FCmp) &&
           getAltOpcode() == getOpcode();
  }

  /// Checks if the current state is valid, i.e. has non-null MainOp
  bool valid() const { return MainOp && AltOp; }

  explicit operator bool() const { return valid(); }

  InstructionsState() = delete;
  InstructionsState(Instruction *MainOp, Instruction *AltOp,
                    bool HasCopyables = false)
      : MainOp(MainOp), AltOp(AltOp), HasCopyables(HasCopyables) {}
  static InstructionsState invalid() { return {nullptr, nullptr}; }

  /// Checks if the value is a copyable element.
  bool isCopyableElement(Value *V) const {
    assert(valid() && "InstructionsState is invalid.");
    if (!HasCopyables)
      return false;
    if (isAltShuffle() || getOpcode() == Instruction::GetElementPtr)
      return false;
    auto *I = dyn_cast<Instruction>(V);
    if (!I)
      return !isa<PoisonValue>(V);
    if (I->getParent() != MainOp->getParent() &&
        (!isVectorLikeInstWithConstOps(I) ||
         !isVectorLikeInstWithConstOps(MainOp)))
      return true;
    if (I->getOpcode() == MainOp->getOpcode())
      return false;
    if (!I->isBinaryOp())
      return true;
    BinOpSameOpcodeHelper Converter(MainOp);
    return !Converter.add(I) || !Converter.add(MainOp) ||
           Converter.hasAltOp() || !Converter.hasCandidateOpcode(getOpcode());
  }

  /// Checks if the value \p V is a transformed instruction, compatible either
  /// with main or alternate ops.
  bool isExpandedBinOp(Value *V) const {
    assert(valid() && "InstructionsState is invalid.");
    if (isCopyableElement(V))
      return false;
    auto *ExpandingOp = dyn_cast<Instruction>(V);
    if (!ExpandingOp)
      return false;
    auto CheckForTransformedOpcode = [](const Instruction *RefOp,
                                        const Instruction *ExpandingOp) {
      switch (RefOp->getOpcode()) {
      case Instruction::Add:
        switch (ExpandingOp->getOpcode()) {
        case Instruction::Shl:
          return match(ExpandingOp, m_Shl(m_Value(), m_One()));
        default:
          break;
        }
        break;
      default:
        break;
      }
      return false;
    };
    Instruction *MainOp = getMatchingMainOpOrAltOp(ExpandingOp);
    assert(MainOp &&
           "The instruction should be compatible with either main or alt op.");
    return CheckForTransformedOpcode(MainOp, ExpandingOp);
  }

  /// Checks if the operand at index \p Idx of instruction \p I is an expanded
  /// operand.
  bool isExpandedOperand(Instruction *I, unsigned Idx) const {
    assert(isExpandedBinOp(I) && "Expected an expanded binop.");
    switch (I->getOpcode()) {
    case Instruction::Shl:
      assert(match(I, m_Shl(m_Value(), m_One())) && "Expected shl x, 1 only.");
      return Idx == 1;
    default:
      llvm_unreachable("Unexpected opcode for an expanded operand.");
    }
  }

  /// Checks if the value is non-schedulable.
  bool isNonSchedulable(Value *V) const {
    assert(valid() && "InstructionsState is invalid.");
    auto *I = dyn_cast<Instruction>(V);
    if (!HasCopyables)
      return !I || isa<PHINode>(I) || isVectorLikeInstWithConstOps(I) ||
             doesNotNeedToBeScheduled(V);
    // MainOp for copyables always schedulable to correctly identify
    // non-schedulable copyables.
    if (getMainOp() == V)
      return false;
    if (isCopyableElement(V)) {
      auto IsNonSchedulableCopyableElement = [this](Value *V) {
        auto *I = dyn_cast<Instruction>(V);
        return !I || isa<PHINode>(I) || I->getParent() != MainOp->getParent() ||
               (doesNotNeedToBeScheduled(I) &&
                // If the copyable instructions comes after MainOp
                // (non-schedulable, but used in the block) - cannot vectorize
                // it, will possibly generate use before def.
                !MainOp->comesBefore(I));
      };

      return IsNonSchedulableCopyableElement(V);
    }
    return !I || isa<PHINode>(I) || isVectorLikeInstWithConstOps(I) ||
           doesNotNeedToBeScheduled(V);
  }

  /// Checks if the state represents copyable instructions.
  bool areInstructionsWithCopyableElements() const {
    assert(valid() && "InstructionsState is invalid.");
    return HasCopyables;
  }
};

std::pair<Instruction *, SmallVector<Value *>>
convertTo(Instruction *I, const InstructionsState &S) {
  Instruction *SelectedOp = S.getMatchingMainOpOrAltOp(I);
  assert(SelectedOp && "Cannot convert the instruction.");
  if (I->isBinaryOp()) {
    BinOpSameOpcodeHelper Converter(I);
    return std::make_pair(SelectedOp, Converter.getOperand(SelectedOp));
  }
  return std::make_pair(SelectedOp, SmallVector<Value *>(I->operands()));
}

} // end anonymous namespace

static InstructionsState getSameOpcode(ArrayRef<Value *> VL,
                                       const TargetLibraryInfo &TLI);

/// Find an instruction with a specific opcode in VL.
/// \param VL Array of values to search through. Must contain only Instructions
///           and PoisonValues.
/// \param Opcode The instruction opcode to search for
/// \returns
/// - The first instruction found with matching opcode
/// - nullptr if no matching instruction is found
static Instruction *findInstructionWithOpcode(ArrayRef<Value *> VL,
                                              unsigned Opcode) {
  for (Value *V : VL) {
    if (isa<PoisonValue>(V))
      continue;
    assert(isa<Instruction>(V) && "Only accepts PoisonValue and Instruction.");
    auto *Inst = cast<Instruction>(V);
    if (Inst->getOpcode() == Opcode)
      return Inst;
  }
  return nullptr;
}

/// Checks if the provided operands of 2 cmp instructions are compatible, i.e.
/// compatible instructions or constants, or just some other regular values.
static bool areCompatibleCmpOps(Value *BaseOp0, Value *BaseOp1, Value *Op0,
                                Value *Op1, const TargetLibraryInfo &TLI) {
  return (isConstant(BaseOp0) && isConstant(Op0)) ||
         (isConstant(BaseOp1) && isConstant(Op1)) ||
         (!isa<Instruction>(BaseOp0) && !isa<Instruction>(Op0) &&
          !isa<Instruction>(BaseOp1) && !isa<Instruction>(Op1)) ||
         BaseOp0 == Op0 || BaseOp1 == Op1 ||
         getSameOpcode({BaseOp0, Op0}, TLI) ||
         getSameOpcode({BaseOp1, Op1}, TLI);
}

/// \returns true if a compare instruction \p CI has similar "look" and
/// same predicate as \p BaseCI, "as is" or with its operands and predicate
/// swapped, false otherwise.
static bool isCmpSameOrSwapped(const CmpInst *BaseCI, const CmpInst *CI,
                               const TargetLibraryInfo &TLI) {
  assert(BaseCI->getOperand(0)->getType() == CI->getOperand(0)->getType() &&
         "Assessing comparisons of different types?");
  CmpInst::Predicate BasePred = BaseCI->getPredicate();
  CmpInst::Predicate Pred = CI->getPredicate();
  CmpInst::Predicate SwappedPred = CmpInst::getSwappedPredicate(Pred);

  Value *BaseOp0 = BaseCI->getOperand(0);
  Value *BaseOp1 = BaseCI->getOperand(1);
  Value *Op0 = CI->getOperand(0);
  Value *Op1 = CI->getOperand(1);

  return (BasePred == Pred &&
          areCompatibleCmpOps(BaseOp0, BaseOp1, Op0, Op1, TLI)) ||
         (BasePred == SwappedPred &&
          areCompatibleCmpOps(BaseOp0, BaseOp1, Op1, Op0, TLI));
}

/// \returns analysis of the Instructions in \p VL described in
/// InstructionsState, the Opcode that we suppose the whole list
/// could be vectorized even if its structure is diverse.
static InstructionsState getSameOpcode(ArrayRef<Value *> VL,
                                       const TargetLibraryInfo &TLI) {
  // Make sure these are all Instructions.
  if (!all_of(VL, IsaPred<Instruction, PoisonValue>))
    return InstructionsState::invalid();

  auto *It = find_if(VL, IsaPred<Instruction>);
  if (It == VL.end())
    return InstructionsState::invalid();

  Instruction *MainOp = cast<Instruction>(*It);
  unsigned InstCnt = std::count_if(It, VL.end(), IsaPred<Instruction>);
  if ((VL.size() > 2 && !isa<PHINode>(MainOp) && InstCnt < VL.size() / 2) ||
      (VL.size() == 2 && InstCnt < 2))
    return InstructionsState::invalid();

  bool IsCastOp = isa<CastInst>(MainOp);
  bool IsBinOp = isa<BinaryOperator>(MainOp);
  bool IsCmpOp = isa<CmpInst>(MainOp);
  CmpInst::Predicate BasePred = IsCmpOp ? cast<CmpInst>(MainOp)->getPredicate()
                                        : CmpInst::BAD_ICMP_PREDICATE;
  Instruction *AltOp = MainOp;
  unsigned Opcode = MainOp->getOpcode();
  unsigned AltOpcode = Opcode;

  BinOpSameOpcodeHelper BinOpHelper(MainOp);
  bool SwappedPredsCompatible = IsCmpOp && [&]() {
    SetVector<unsigned> UniquePreds, UniqueNonSwappedPreds;
    UniquePreds.insert(BasePred);
    UniqueNonSwappedPreds.insert(BasePred);
    for (Value *V : VL) {
      auto *I = dyn_cast<CmpInst>(V);
      if (!I)
        return false;
      CmpInst::Predicate CurrentPred = I->getPredicate();
      CmpInst::Predicate SwappedCurrentPred =
          CmpInst::getSwappedPredicate(CurrentPred);
      UniqueNonSwappedPreds.insert(CurrentPred);
      if (!UniquePreds.contains(CurrentPred) &&
          !UniquePreds.contains(SwappedCurrentPred))
        UniquePreds.insert(CurrentPred);
    }
    // Total number of predicates > 2, but if consider swapped predicates
    // compatible only 2, consider swappable predicates as compatible opcodes,
    // not alternate.
    return UniqueNonSwappedPreds.size() > 2 && UniquePreds.size() == 2;
  }();
  // Check for one alternate opcode from another BinaryOperator.
  // TODO - generalize to support all operators (types, calls etc.).
  Intrinsic::ID BaseID = 0;
  SmallVector<VFInfo> BaseMappings;
  if (auto *CallBase = dyn_cast<CallInst>(MainOp)) {
    BaseID = getVectorIntrinsicIDForCall(CallBase, &TLI);
    BaseMappings = VFDatabase(*CallBase).getMappings(*CallBase);
    if (!isTriviallyVectorizable(BaseID) && BaseMappings.empty())
      return InstructionsState::invalid();
  }
  bool AnyPoison = InstCnt != VL.size();
  // Check MainOp too to be sure that it matches the requirements for the
  // instructions.
  for (Value *V : iterator_range(It, VL.end())) {
    auto *I = dyn_cast<Instruction>(V);
    if (!I)
      continue;

    // Cannot combine poison and divisions.
    // TODO: do some smart analysis of the CallInsts to exclude divide-like
    // intrinsics/functions only.
    if (AnyPoison && (I->isIntDivRem() || I->isFPDivRem() || isa<CallInst>(I)))
      return InstructionsState::invalid();
    unsigned InstOpcode = I->getOpcode();
    if (IsBinOp && isa<BinaryOperator>(I)) {
      if (BinOpHelper.add(I))
        continue;
    } else if (IsCastOp && isa<CastInst>(I)) {
      Value *Op0 = MainOp->getOperand(0);
      Type *Ty0 = Op0->getType();
      Value *Op1 = I->getOperand(0);
      Type *Ty1 = Op1->getType();
      if (Ty0 == Ty1) {
        if (InstOpcode == Opcode || InstOpcode == AltOpcode)
          continue;
        if (Opcode == AltOpcode) {
          assert(isValidForAlternation(Opcode) &&
                 isValidForAlternation(InstOpcode) &&
                 "Cast isn't safe for alternation, logic needs to be updated!");
          AltOpcode = InstOpcode;
          AltOp = I;
          continue;
        }
      }
    } else if (auto *Inst = dyn_cast<CmpInst>(I); Inst && IsCmpOp) {
      auto *BaseInst = cast<CmpInst>(MainOp);
      Type *Ty0 = BaseInst->getOperand(0)->getType();
      Type *Ty1 = Inst->getOperand(0)->getType();
      if (Ty0 == Ty1) {
        assert(InstOpcode == Opcode && "Expected same CmpInst opcode.");
        assert(InstOpcode == AltOpcode &&
               "Alternate instructions are only supported by BinaryOperator "
               "and CastInst.");
        // Check for compatible operands. If the corresponding operands are not
        // compatible - need to perform alternate vectorization.
        CmpInst::Predicate CurrentPred = Inst->getPredicate();
        CmpInst::Predicate SwappedCurrentPred =
            CmpInst::getSwappedPredicate(CurrentPred);

        if ((VL.size() == 2 || SwappedPredsCompatible) &&
            (BasePred == CurrentPred || BasePred == SwappedCurrentPred))
          continue;

        if (isCmpSameOrSwapped(BaseInst, Inst, TLI))
          continue;
        auto *AltInst = cast<CmpInst>(AltOp);
        if (MainOp != AltOp) {
          if (isCmpSameOrSwapped(AltInst, Inst, TLI))
            continue;
        } else if (BasePred != CurrentPred) {
          assert(
              isValidForAlternation(InstOpcode) &&
              "CmpInst isn't safe for alternation, logic needs to be updated!");
          AltOp = I;
          continue;
        }
        CmpInst::Predicate AltPred = AltInst->getPredicate();
        if (BasePred == CurrentPred || BasePred == SwappedCurrentPred ||
            AltPred == CurrentPred || AltPred == SwappedCurrentPred)
          continue;
      }
    } else if (InstOpcode == Opcode) {
      assert(InstOpcode == AltOpcode &&
             "Alternate instructions are only supported by BinaryOperator and "
             "CastInst.");
      if (auto *Gep = dyn_cast<GetElementPtrInst>(I)) {
        if (Gep->getNumOperands() != 2 ||
            Gep->getOperand(0)->getType() != MainOp->getOperand(0)->getType())
          return InstructionsState::invalid();
      } else if (auto *EI = dyn_cast<ExtractElementInst>(I)) {
        if (!isVectorLikeInstWithConstOps(EI))
          return InstructionsState::invalid();
      } else if (auto *LI = dyn_cast<LoadInst>(I)) {
        auto *BaseLI = cast<LoadInst>(MainOp);
        if (!LI->isSimple() || !BaseLI->isSimple())
          return InstructionsState::invalid();
      } else if (auto *Call = dyn_cast<CallInst>(I)) {
        auto *CallBase = cast<CallInst>(MainOp);
        if (Call->getCalledFunction() != CallBase->getCalledFunction())
          return InstructionsState::invalid();
        if (Call->hasOperandBundles() &&
            (!CallBase->hasOperandBundles() ||
             !std::equal(Call->op_begin() + Call->getBundleOperandsStartIndex(),
                         Call->op_begin() + Call->getBundleOperandsEndIndex(),
                         CallBase->op_begin() +
                             CallBase->getBundleOperandsStartIndex())))
          return InstructionsState::invalid();
        Intrinsic::ID ID = getVectorIntrinsicIDForCall(Call, &TLI);
        if (ID != BaseID)
          return InstructionsState::invalid();
        if (!ID) {
          SmallVector<VFInfo> Mappings = VFDatabase(*Call).getMappings(*Call);
          if (Mappings.size() != BaseMappings.size() ||
              Mappings.front().ISA != BaseMappings.front().ISA ||
              Mappings.front().ScalarName != BaseMappings.front().ScalarName ||
              Mappings.front().VectorName != BaseMappings.front().VectorName ||
              Mappings.front().Shape.VF != BaseMappings.front().Shape.VF ||
              Mappings.front().Shape.Parameters !=
                  BaseMappings.front().Shape.Parameters)
            return InstructionsState::invalid();
        }
      }
      continue;
    }
    return InstructionsState::invalid();
  }

  if (IsBinOp) {
    if (!BinOpHelper.hasDefinedMainOpcode() ||
        !BinOpHelper.hasDefinedAltOpcode())
      return InstructionsState::invalid();
    MainOp = findInstructionWithOpcode(VL, BinOpHelper.getMainOpcode());
    assert(MainOp && "Cannot find MainOp with Opcode from BinOpHelper.");
    AltOp = findInstructionWithOpcode(VL, BinOpHelper.getAltOpcode());
    assert(AltOp && "Cannot find AltOp with Opcode from BinOpHelper.");
  }
  assert((MainOp == AltOp || !allSameOpcode(VL)) &&
         "Incorrect implementation of allSameOpcode.");
  InstructionsState S(MainOp, AltOp);
  assert(all_of(VL,
                [&](Value *V) {
                  return isa<PoisonValue>(V) ||
                         S.getMatchingMainOpOrAltOp(cast<Instruction>(V));
                }) &&
         "Invalid InstructionsState.");
  return S;
}

/// Returns true if widened type of \p Ty elements with size \p Sz represents
/// full vector type, i.e. adding extra element results in extra parts upon type
/// legalization.
static bool hasFullVectorsOrPowerOf2(const TargetTransformInfo &TTI, Type *Ty,
                                     unsigned Sz) {
  if (Sz <= 1)
    return false;
  if (!isValidElementType(Ty) && !isa<FixedVectorType>(Ty))
    return false;
  if (has_single_bit(Sz))
    return true;
  if (isa<StructType>(Ty))
    return false;
  const unsigned NumParts = TTI.getNumberOfParts(getWidenedType(Ty, Sz));
  return NumParts > 0 && NumParts < Sz && has_single_bit(Sz / NumParts) &&
         Sz % NumParts == 0;
}

/// Returns number of parts, the type \p VecTy will be split at the codegen
/// phase. If the type is going to be scalarized or does not uses whole
/// registers, returns 1.
static unsigned
getNumberOfParts(const TargetTransformInfo &TTI, Type *VecTy, Type *ScalarTy,
                 const unsigned Limit = std::numeric_limits<unsigned>::max()) {
  if (isa<StructType>(VecTy))
    return 1;
  unsigned NumParts = TTI.getNumberOfParts(VecTy);
  if (NumParts == 0 || NumParts >= Limit)
    return 1;
  unsigned Sz = getNumElements(VecTy);
  unsigned ScalarSz = getNumElements(ScalarTy);
  Type *ElementTy = toScalarizedTy(VecTy);
  unsigned PWSz = getFullVectorNumberOfElements(TTI, ElementTy, Sz);
  if (NumParts >= Sz || PWSz % NumParts != 0 ||
      (PWSz / NumParts) % ScalarSz != 0 ||
      !hasFullVectorsOrPowerOf2(TTI, ElementTy, PWSz / NumParts))
    return 1;
  const unsigned NumElts = PWSz / NumParts;
  if (divideCeil(Sz, NumElts) != NumParts)
    return 1;
  return NumParts;
}

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

  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),
        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<std::tuple<WeakTrackingVH, unsigned, bool, bool>>
                    VectorValuesAndScales = {});

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

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

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

  /// 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-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, outside any loop, 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; }

  /// Returns the scalars of the root node.
  ArrayRef<Value *> getRootNodeScalars() const {
    assert(!VectorizableTree.empty() && "No graph to get the first node from");
    return VectorizableTree.front()->Scalars;
  }

  /// Returns the lane the given value is vectorized to in the root node.
  unsigned findRootLaneForValue(Value *V) const {
    assert(!VectorizableTree.empty() && "No graph to get the first node from");
    return VectorizableTree.front()->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 = *VectorizableTree.front();
    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(VectorizableTree.front().get()).second;
  }

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

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

  /// Returns true if the tree results in the reduced cmp bitcast root.
  bool isReducedCmpBitcastRoot() const {
    return VectorizableTree.front()->hasState() &&
           VectorizableTree.front()->CombinedOp ==
               TreeEntry::ReducedCmpBitcast &&
           VectorizableTree.front()->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();
    NonScheduledFirst.clear();
    EntryToLastInstruction.clear();
    LastInstructionToPos.clear();
    LoadEntriesToVectorize.clear();
    IsGraphTransformMode = false;
    GatheredLoadsEntriesFirst.reset();
    CompressEntryToData.clear();
    ExternalUses.clear();
    ExternalUsesAsOriginalScalar.clear();
    ExternalUsesWithNonUsers.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;
    PostponedGathers.clear();
    ValueToGatherNodes.clear();
    TreeEntryToStridedPtrInfoMap.clear();
    CurrentLoopNest.clear();
    MergedLoopBTCs.clear();
  }

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

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

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

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

  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()) ||
          !isValidElementType(V2->getType()))
        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(Ops, [&S](Value *V) {
              return isa<PoisonValue>(V) ||
                     cast<Instruction>(V)->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();
      unsigned NumOperands = MainOp->getNumOperands();
      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>(NumOperands))
            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");
          auto [SelectedOp, Ops] = convertTo(I, S);
          // 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);
    }

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

  /// 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<std::tuple<WeakTrackingVH, unsigned, bool, bool>>
          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) &&
            (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) &&
              (!OpI->getType()->isVectorTy() ||
               none_of(
                   VectorValuesAndScales,
                   [&](const std::tuple<WeakTrackingVH, unsigned, bool, bool>
                           &V) { return std::get<0>(V) == 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));
  }
  /// Clear the list of the analyzed reduction root instructions.
  void clearReductionData() {
    AnalyzedReductionsRoots.clear();
    AnalyzedReductionVals.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 the value is vectorized in the tree.
  bool isVectorized(const Value *V) const {
    assert(V && "V cannot be nullptr.");
    ArrayRef<TreeEntry *> Entries = getTreeEntries(V);
    return any_of(Entries, [&](const TreeEntry *E) {
      return !DeletedNodes.contains(E) && !TransformedToGatherNodes.contains(E);
    });
  }

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

  ~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.
  unsigned getNumScalarInsts() const;

  /// Estimates the number of vector instructions (including buildvectors,
  /// shuffles, and extracts) that the tree will produce.
  unsigned getNumVectorInsts() 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 Cast context for the given graph node.
  TargetTransformInfo::CastContextHint
  getCastContextHint(const TreeEntry &TE) 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);

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

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

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

  /// 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<UndefValue>(V) &&
                                    Idx == PoisonMaskElem) ||
                                   (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.
      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,
      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;

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

    /// Chooses the correct key for scheduling data. If \p Op has the same (or
    /// alternate) opcode as \p OpValue, the key is \p Op. Otherwise the key is
    /// \p OpValue.
    Value *isOneOf(Value *Op) const {
      auto *I = dyn_cast<Instruction>(Op);
      if (I && getMatchingMainOpOrAltOp(I))
        return Op;
      return S.getMainOp();
    }

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

    /// 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();
      for (auto *It = find(Scalars, V), *End = Scalars.end(); It != End;
           std::advance(It, 1)) {
        if (*It != V)
          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 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 (Value *V : VL) {
        auto *I = dyn_cast<Instruction>(V);
        if (!I)
          continue;
        auto It = ScalarsInSplitNodes.find(V);
        if (It == ScalarsInSplitNodes.end()) {
          ScalarsInSplitNodes.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);
        }
      }
    } 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 : VL) {
        if (isa<PoisonValue>(V))
          continue;
        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;

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

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

  /// Values, already been analyzed for mininmal bitwidth and found to be
  /// non-profitable.
  DenseSet<Value *> 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;

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

    /// 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 != 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 *>;

  /// 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 : User->operands()) {
        if (U.get() != Op)
          continue;
        ++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 (Value *V : ParentTE->Scalars) {
              auto *PHI = dyn_cast<PHINode>(V);
              if (!PHI)
                continue;
              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.
          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)) {
            EdgeInfo EI(TE, U.getOperandNo());
            if (CurNumOps != NumOps || 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;
            }
          }
          for (unsigned OpIdx :
               seq<unsigned>(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 std::pair<const TreeEntry *, unsigned> &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;
    }

    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.
          if (In == I) {
            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;
    }

    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);
            for (ScheduleCopyableData *CD : CopyableData)
              DecrUnsched(CD, /*IsControl=*/false);
            if (!CopyableData.empty())
              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;
              }
            }
          }
          // 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) {
                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;
                  }
                }
                auto It = OperandsUses.find(I);
                assert(It != OperandsUses.end() && "Operand not found");
                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)) &&
                  "Missed TreeEntry operands?");

              // 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 =
                    Bundle->getTreeEntry()->UserTreeIndex.UserTE;
                Value *User = ParentTE->Scalars[Lane];
                if (!ParentsUniqueUsers.insert(User).second) {
                  It = std::find(std::next(It),
                                 Bundle->getTreeEntry()->Scalars.end(), In);
                  continue;
                }
              }

              for (unsigned OpIdx :
                   seq<unsigned>(Bundle->getTreeEntry()->getNumOperands()))
                if (auto *I = dyn_cast<Instruction>(
                        Bundle->getTreeEntry()->getOperand(OpIdx)[Lane])) {
                  LLVM_DEBUG(dbgs() << "SLP:   check for readiness (def): "
                                    << *I << "\n");
                  DecrUnschedForInst(
                      I, Bundle->getTreeEntry(), OpIdx, Checked,
                      Bundle->getTreeEntry()->isExpandedOperand(In, OpIdx));
                }
              // 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());
          }
          // 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);
                }
              }
            }
          }
        } 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 : Entries) {
            if (!isa<ExtractValueInst, ExtractElementInst, CallBase>(In) &&
                In->getNumOperands() != TE->getNumOperands())
              continue;
            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);
          if (isa<ScheduleCopyableData>(SD) ||
              ScheduleCopyableDataMap.empty()) {
            ProcessBundleMember(SD, isa<ScheduleCopyableData>(SD) ? &Bundle
                                                                  : SDBundles);
            continue;
          }
          // 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,
          // registered on that non-scheduled parent edge. That copyable would
          // never be decremented when the instruction is scheduled through a
          // different bundle, leaving the copyable's bundle permanently
          // unscheduled and tripping the unscheduled-deps assertion. Add
          // pseudo-bundles for these missing tree entries, so their copyable
          // operand dependencies are decremented here as well. Real operand
          // dependencies are protected against double counting by the
          // per-operand use counter in ProcessBundleMember.
          Instruction *In = SD->getInst();
          SmallVector<std::unique_ptr<ScheduleBundle>> PseudoBundles;
          SmallVector<ScheduleBundle *> AllBundles(SDBundles.begin(),
                                                   SDBundles.end());
          for (TreeEntry *TE : R.getTreeEntries(In)) {
            if (TE->isCopyableElement(In))
              continue;
            if (!isa<ExtractValueInst, ExtractElementInst, CallBase>(In) &&
                In->getNumOperands() != TE->getNumOperands())
              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 : Bundles) {
              if (!Visited.insert(Bundle).second)
                continue;
              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;

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

  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;

  /// 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.VectorizableTree[0].get();
  }

  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)
      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 (Use &U : I->operands()) {
      auto *Op = dyn_cast<Instruction>(U.get());
      if (Op && !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
}

/// Reorders the given \p Reuses mask according to the given \p Mask. \p Reuses
/// contains original mask for the scalars reused in the node. Procedure
/// transform this mask in accordance with the given \p Mask.
static void reorderReuses(SmallVectorImpl<int> &Reuses, ArrayRef<int> Mask) {
  assert(!Mask.empty() && Reuses.size() == Mask.size() &&
         "Expected non-empty mask.");
  SmallVector<int> Prev(Reuses.begin(), Reuses.end());
  Prev.swap(Reuses);
  for (unsigned I = 0, E = Prev.size(); I < E; ++I)
    if (Mask[I] != PoisonMaskElem)
      Reuses[Mask[I]] = Prev[I];
}

/// Reorders the given \p Order according to the given \p Mask. \p Order - is
/// the original order of the scalars. Procedure transforms the provided order
/// in accordance with the given \p Mask. If the resulting \p Order is just an
/// identity order, \p Order is cleared.
static void reorderOrder(SmallVectorImpl<unsigned> &Order, ArrayRef<int> Mask,
                         bool BottomOrder = false) {
  assert(!Mask.empty() && "Expected non-empty mask.");
  unsigned Sz = Mask.size();
  if (BottomOrder) {
    SmallVector<unsigned> PrevOrder;
    if (Order.empty()) {
      PrevOrder.resize(Sz);
      std::iota(PrevOrder.begin(), PrevOrder.end(), 0);
    } else {
      PrevOrder.swap(Order);
    }
    Order.assign(Sz, Sz);
    for (unsigned I = 0; I < Sz; ++I)
      if (Mask[I] != PoisonMaskElem)
        Order[I] = PrevOrder[Mask[I]];
    if (all_of(enumerate(Order), [&](const auto &Data) {
          return Data.value() == Sz || Data.index() == Data.value();
        })) {
      Order.clear();
      return;
    }
    fixupOrderingIndices(Order);
    return;
  }
  SmallVector<int> MaskOrder;
  if (Order.empty()) {
    MaskOrder.resize(Sz);
    std::iota(MaskOrder.begin(), MaskOrder.end(), 0);
  } else {
    inversePermutation(Order, MaskOrder);
  }
  reorderReuses(MaskOrder, Mask);
  if (ShuffleVectorInst::isIdentityMask(MaskOrder, Sz)) {
    Order.clear();
    return;
  }
  Order.assign(Sz, Sz);
  for (unsigned I = 0; I < Sz; ++I)
    if (MaskOrder[I] != PoisonMaskElem)
      Order[MaskOrder[I]] = I;
  fixupOrderingIndices(Order);
}

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))
    return std::nullopt;
  auto *VecTy = getWidenedType(ScalarTy, NumScalars);
  unsigned NumParts = ::getNumberOfParts(*TTI, 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);
  // 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);
}

static bool arePointersCompatible(Value *Ptr1, Value *Ptr2,
                                  const TargetLibraryInfo &TLI,
                                  bool CompareOpcodes = true) {
  if (getUnderlyingObject(Ptr1, RecursionMaxDepth) !=
      getUnderlyingObject(Ptr2, RecursionMaxDepth))
    return false;
  auto *GEP1 = dyn_cast<GetElementPtrInst>(Ptr1);
  auto *GEP2 = dyn_cast<GetElementPtrInst>(Ptr2);
  return (!GEP1 || GEP1->getNumOperands() == 2) &&
         (!GEP2 || GEP2->getNumOperands() == 2) &&
         (((!GEP1 || isConstant(GEP1->getOperand(1))) &&
           (!GEP2 || isConstant(GEP2->getOperand(1)))) ||
          !CompareOpcodes ||
          (GEP1 && GEP2 &&
           getSameOpcode({GEP1->getOperand(1), GEP2->getOperand(1)}, TLI)));
}

/// Calculates minimal alignment as a common alignment.
template <typename T>
static Align computeCommonAlignment(ArrayRef<Value *> VL) {
  Align CommonAlignment = cast<T>(VL.consume_front())->getAlign();
  for (Value *V : VL)
    CommonAlignment = std::min(CommonAlignment, cast<T>(V)->getAlign());
  return CommonAlignment;
}

/// Check if \p Order represents reverse order.
static bool isReverseOrder(ArrayRef<unsigned> Order) {
  assert(!Order.empty() &&
         "Order is empty. Please check it before using isReverseOrder.");
  unsigned Sz = Order.size();
  return all_of(enumerate(Order), [&](const auto &Pair) {
    return Pair.value() == Sz || Sz - Pair.index() - 1 == Pair.value();
  });
}

/// Checks if the provided list of pointers \p Pointers represents the strided
/// pointers for type ElemTy. If they are not, nullptr is returned.
/// Otherwise, SCEV* of the stride value is returned.
/// If `PointerOps` can be rearanged into the following sequence:
/// ```
/// %x + c_0 * stride,
/// %x + c_1 * stride,
/// %x + c_2 * stride
/// ...
/// ```
/// where each `c_i` is constant. The SCEV of the `stride` will be returned.
static const SCEV *calculateRtStride(ArrayRef<Value *> PointerOps, Type *ElemTy,
                                     const DataLayout &DL, ScalarEvolution &SE,
                                     SmallVectorImpl<unsigned> &SortedIndices) {
  SmallVector<const SCEV *> SCEVs;
  const SCEV *PtrSCEVLowest = nullptr;
  const SCEV *PtrSCEVHighest = nullptr;
  // Find lower/upper pointers from the PointerOps (i.e. with lowest and highest
  // addresses).
  for (Value *Ptr : PointerOps) {
    const SCEV *PtrSCEV = SE.getSCEV(Ptr);
    if (!PtrSCEV)
      return nullptr;
    SCEVs.push_back(PtrSCEV);
    if (!PtrSCEVLowest && !PtrSCEVHighest) {
      PtrSCEVLowest = PtrSCEVHighest = PtrSCEV;
      continue;
    }
    const SCEV *Diff = SE.getMinusSCEV(PtrSCEV, PtrSCEVLowest);
    if (isa<SCEVCouldNotCompute>(Diff))
      return nullptr;
    if (Diff->isNonConstantNegative()) {
      PtrSCEVLowest = PtrSCEV;
      continue;
    }
    const SCEV *Diff1 = SE.getMinusSCEV(PtrSCEVHighest, PtrSCEV);
    if (isa<SCEVCouldNotCompute>(Diff1))
      return nullptr;
    if (Diff1->isNonConstantNegative()) {
      PtrSCEVHighest = PtrSCEV;
      continue;
    }
  }
  // Dist = PtrSCEVHighest - PtrSCEVLowest;
  const SCEV *Dist = SE.getMinusSCEV(PtrSCEVHighest, PtrSCEVLowest);
  if (isa<SCEVCouldNotCompute>(Dist))
    return nullptr;
  int Size = DL.getTypeStoreSize(ElemTy);
  auto TryGetStride = [&](const SCEV *Dist,
                          const SCEV *Multiplier) -> const SCEV * {
    if (const auto *M = dyn_cast<SCEVMulExpr>(Dist)) {
      if (M->getOperand(0) == Multiplier)
        return M->getOperand(1);
      if (M->getOperand(1) == Multiplier)
        return M->getOperand(0);
      return nullptr;
    }
    if (Multiplier == Dist)
      return SE.getConstant(Dist->getType(), 1);
    return SE.getUDivExactExpr(Dist, Multiplier);
  };
  // Stride_in_elements = Dist / element_size * (num_elems - 1).
  const SCEV *Stride = nullptr;
  if (Size != 1 || SCEVs.size() > 1) {
    const SCEV *Sz = SE.getConstant(Dist->getType(), Size * (SCEVs.size() - 1));
    Stride = TryGetStride(Dist, Sz);
    if (!Stride)
      return nullptr;
  }
  if (!Stride || isa<SCEVConstant>(Stride))
    return nullptr;
  // Iterate through all pointers and check if all distances are
  // unique multiple of Stride.
  using DistOrdPair = std::pair<int64_t, int>;
  auto Compare = llvm::less_first();
  std::set<DistOrdPair, decltype(Compare)> Offsets(Compare);
  bool IsConsecutive = true;
  for (const auto [Idx, PtrSCEV] : enumerate(SCEVs)) {
    unsigned Dist = 0;
    if (PtrSCEV != PtrSCEVLowest) {
      const SCEV *Diff = SE.getMinusSCEV(PtrSCEV, PtrSCEVLowest);
      const SCEV *Coeff = TryGetStride(Diff, Stride);
      if (!Coeff)
        return nullptr;
      const auto *SC = dyn_cast<SCEVConstant>(Coeff);
      if (!SC || isa<SCEVCouldNotCompute>(SC))
        return nullptr;
      if (!SE.getMinusSCEV(PtrSCEV, SE.getAddExpr(PtrSCEVLowest,
                                                  SE.getMulExpr(Stride, SC)))
               ->isZero())
        return nullptr;
      Dist = SC->getAPInt().getZExtValue();
    }
    // If the strides are not the same or repeated, we can't vectorize.
    if ((Dist / Size) * Size != Dist || (Dist / Size) >= SCEVs.size())
      return nullptr;
    auto Res = Offsets.emplace(Dist, Idx);
    if (!Res.second)
      return nullptr;
    // Consecutive order if the inserted element is the last one.
    IsConsecutive = IsConsecutive && std::next(Res.first) == Offsets.end();
  }
  SortedIndices.clear();
  if (!IsConsecutive) {
    // Fill SortedIndices array only if it is non-consecutive.
    SortedIndices.resize(PointerOps.size());
    for (const auto [Idx, Pair] : enumerate(Offsets))
      SortedIndices[Idx] = Pair.second;
  }
  return Stride;
}

static std::pair<InstructionCost, InstructionCost>
getGEPCosts(const TargetTransformInfo &TTI, ArrayRef<Value *> Ptrs,
            Value *BasePtr, unsigned Opcode, TTI::TargetCostKind CostKind,
            Type *ScalarTy, VectorType *VecTy);

/// Returns the cost of the shuffle instructions with the given \p Kind, vector
/// type \p Tp and optional \p Mask. Adds SLP-specifc cost estimation for insert
/// subvector pattern.
static InstructionCost
getShuffleCost(const TargetTransformInfo &TTI, TTI::ShuffleKind Kind,
               VectorType *Tp, ArrayRef<int> Mask = {},
               TTI::TargetCostKind CostKind = TTI::TCK_RecipThroughput,
               int Index = 0, VectorType *SubTp = nullptr,
               ArrayRef<const Value *> Args = {}) {
  VectorType *DstTy = Tp;
  if (!Mask.empty())
    DstTy = FixedVectorType::get(Tp->getScalarType(), Mask.size());

  if (Kind != TTI::SK_PermuteTwoSrc)
    return TTI.getShuffleCost(Kind, DstTy, Tp, Mask, CostKind, Index, SubTp,
                              Args);
  int NumSrcElts = Tp->getElementCount().getKnownMinValue();
  int NumSubElts;
  if (Mask.size() > 2 && ShuffleVectorInst::isInsertSubvectorMask(
                             Mask, NumSrcElts, NumSubElts, Index)) {
    if (Index + NumSubElts > NumSrcElts &&
        Index + NumSrcElts <= static_cast<int>(Mask.size()))
      return TTI.getShuffleCost(TTI::SK_InsertSubvector, DstTy, Tp, Mask,
                                TTI::TCK_RecipThroughput, Index, Tp);
  }
  return TTI.getShuffleCost(Kind, DstTy, Tp, Mask, CostKind, Index, SubTp,
                            Args);
}

/// This is similar to TargetTransformInfo::getScalarizationOverhead, but if
/// ScalarTy is a FixedVectorType, a vector will be inserted or extracted
/// instead of a scalar.
static InstructionCost getScalarizationOverhead(
    const TargetTransformInfo &TTI, Type *ScalarTy, VectorType *Ty,
    const APInt &DemandedElts, bool Insert, bool Extract,
    TTI::TargetCostKind CostKind, bool ForPoisonSrc = true,
    ArrayRef<Value *> VL = {},
    TTI::VectorInstrContext VIC = TTI::VectorInstrContext::None) {
  assert(!isa<ScalableVectorType>(Ty) &&
         "ScalableVectorType is not supported.");
  assert(getNumElements(ScalarTy) * DemandedElts.getBitWidth() ==
             getNumElements(Ty) &&
         "Incorrect usage.");
  if (auto *VecTy = dyn_cast<FixedVectorType>(ScalarTy)) {
    assert(SLPReVec && "Only supported by REVEC.");
    // If ScalarTy is FixedVectorType, we should use CreateInsertVector instead
    // of CreateInsertElement.
    unsigned ScalarTyNumElements = VecTy->getNumElements();
    InstructionCost Cost = 0;
    for (unsigned I : seq(DemandedElts.getBitWidth())) {
      if (!DemandedElts[I])
        continue;
      if (Insert)
        Cost += getShuffleCost(TTI, TTI::SK_InsertSubvector, Ty, {}, CostKind,
                               I * ScalarTyNumElements, VecTy);
      if (Extract)
        Cost += getShuffleCost(TTI, TTI::SK_ExtractSubvector, Ty, {}, CostKind,
                               I * ScalarTyNumElements, VecTy);
    }
    return Cost;
  }
  return TTI.getScalarizationOverhead(Ty, DemandedElts, Insert, Extract,
                                      CostKind, ForPoisonSrc, VL, VIC);
}

/// This is similar to TargetTransformInfo::getVectorInstrCost, but if ScalarTy
/// is a FixedVectorType, a vector will be extracted instead of a scalar.
static InstructionCost getVectorInstrCost(
    const TargetTransformInfo &TTI, Type *ScalarTy, unsigned Opcode, Type *Val,
    TTI::TargetCostKind CostKind, unsigned Index, Value *Scalar,
    ArrayRef<std::tuple<Value *, User *, int>> ScalarUserAndIdx) {
  if (Opcode == Instruction::ExtractElement) {
    if (auto *VecTy = dyn_cast<FixedVectorType>(ScalarTy)) {
      assert(SLPReVec && "Only supported by REVEC.");
      assert(isa<VectorType>(Val) && "Val must be a vector type.");
      return getShuffleCost(TTI, TTI::SK_ExtractSubvector,
                            cast<VectorType>(Val), {}, CostKind,
                            Index * VecTy->getNumElements(), VecTy);
    }
  }
  return TTI.getVectorInstrCost(Opcode, Val, CostKind, Index, Scalar,
                                ScalarUserAndIdx);
}

/// This is similar to TargetTransformInfo::getExtractWithExtendCost, but if Dst
/// is a FixedVectorType, a vector will be extracted instead of a scalar.
static InstructionCost getExtractWithExtendCost(
    const TargetTransformInfo &TTI, unsigned Opcode, Type *Dst,
    VectorType *VecTy, unsigned Index,
    TTI::TargetCostKind CostKind = TTI::TCK_RecipThroughput) {
  if (isVectorizedTy(Dst)) {
    assert(SLPReVec && "Only supported by REVEC.");
    auto *SubTp = cast<FixedVectorType>(
        getWidenedType(toScalarizedTy(VecTy), getNumElements(Dst)));
    return getShuffleCost(TTI, TTI::SK_ExtractSubvector, VecTy, {}, CostKind,
                          Index * getNumElements(Dst), SubTp) +
           TTI.getCastInstrCost(Opcode, Dst, SubTp, TTI::CastContextHint::None,
                                CostKind);
  }
  return TTI.getExtractWithExtendCost(Opcode, Dst, VecTy, Index, CostKind);
}

/// Creates subvector insert. Generates shuffle using \p Generator or
/// using default shuffle.
static Value *createInsertVector(
    IRBuilderBase &Builder, Value *Vec, Value *V, unsigned Index,
    function_ref<Value *(Value *, Value *, ArrayRef<int>)> Generator = {}) {
  if (isa<PoisonValue>(Vec) && isa<PoisonValue>(V))
    return Vec;
  const unsigned SubVecVF = getNumElements(V->getType());
  // Create shuffle, insertvector requires that index is multiple of
  // the subvector length.
  const unsigned VecVF = getNumElements(Vec->getType());
  SmallVector<int> Mask(VecVF, PoisonMaskElem);
  if (isa<PoisonValue>(Vec)) {
    auto *Begin = std::next(Mask.begin(), Index);
    std::iota(Begin, std::next(Begin, SubVecVF), 0);
    Vec = Builder.CreateShuffleVector(V, Mask);
    return Vec;
  }
  std::iota(Mask.begin(), Mask.end(), 0);
  std::iota(std::next(Mask.begin(), Index),
            std::next(Mask.begin(), Index + SubVecVF), VecVF);
  if (Generator)
    return Generator(Vec, V, Mask);
  // 1. Resize V to the size of Vec.
  SmallVector<int> ResizeMask(VecVF, PoisonMaskElem);
  std::iota(ResizeMask.begin(), std::next(ResizeMask.begin(), SubVecVF), 0);
  V = Builder.CreateShuffleVector(V, ResizeMask);
  // 2. Insert V into Vec.
  return Builder.CreateShuffleVector(Vec, V, Mask);
}

/// Generates subvector extract using \p Generator or using default shuffle.
static Value *createExtractVector(IRBuilderBase &Builder, Value *Vec,
                                  unsigned SubVecVF, unsigned Index) {
  SmallVector<int> Mask(SubVecVF, PoisonMaskElem);
  std::iota(Mask.begin(), Mask.end(), Index);
  return Builder.CreateShuffleVector(Vec, Mask);
}

/// Builds compress-like mask for shuffles for the given \p PointerOps, ordered
/// with \p Order.
/// \return true if the mask represents strided access, false - otherwise.
static bool buildCompressMask(ArrayRef<Value *> PointerOps,
                              ArrayRef<unsigned> Order, Type *ScalarTy,
                              const DataLayout &DL, ScalarEvolution &SE,
                              SmallVectorImpl<int> &CompressMask) {
  const unsigned Sz = PointerOps.size();
  CompressMask.assign(Sz, PoisonMaskElem);
  // The first element always set.
  CompressMask[0] = 0;
  // Check if the mask represents strided access.
  std::optional<unsigned> Stride = 0;
  Value *Ptr0 = Order.empty() ? PointerOps.front() : PointerOps[Order.front()];
  for (unsigned I : seq<unsigned>(1, Sz)) {
    Value *Ptr = Order.empty() ? PointerOps[I] : PointerOps[Order[I]];
    std::optional<int64_t> OptPos =
        getPointersDiff(ScalarTy, Ptr0, ScalarTy, Ptr, DL, SE);
    if (!OptPos || OptPos > std::numeric_limits<unsigned>::max())
      return false;
    unsigned Pos = static_cast<unsigned>(*OptPos);
    CompressMask[I] = Pos;
    if (!Stride)
      continue;
    if (*Stride == 0) {
      *Stride = Pos;
      continue;
    }
    if (Pos != *Stride * I)
      Stride.reset();
  }
  return Stride.has_value();
}

/// Checks if the \p VL can be transformed to a (masked)load + compress or
/// (masked) interleaved load.
static bool isMaskedLoadCompress(
    ArrayRef<Value *> VL, ArrayRef<Value *> PointerOps,
    ArrayRef<unsigned> Order, const TargetTransformInfo &TTI,
    const DataLayout &DL, ScalarEvolution &SE, AssumptionCache &AC,
    const DominatorTree &DT, const TargetLibraryInfo &TLI,
    const function_ref<bool(Value *)> AreAllUsersVectorized, bool &IsMasked,
    unsigned &InterleaveFactor, SmallVectorImpl<int> &CompressMask,
    VectorType *&LoadVecTy) {
  InterleaveFactor = 0;
  Type *ScalarTy = VL.front()->getType();
  const size_t Sz = VL.size();
  auto *VecTy = cast<VectorType>(getWidenedType(ScalarTy, Sz));
  constexpr TTI::TargetCostKind CostKind = TTI::TCK_RecipThroughput;
  SmallVector<int> Mask;
  if (!Order.empty())
    inversePermutation(Order, Mask);
  // Check external uses.
  for (const auto [I, V] : enumerate(VL)) {
    if (AreAllUsersVectorized(V))
      continue;
    InstructionCost ExtractCost =
        TTI.getVectorInstrCost(Instruction::ExtractElement, VecTy, CostKind,
                               Mask.empty() ? I : Mask[I]);
    InstructionCost ScalarCost =
        TTI.getInstructionCost(cast<Instruction>(V), CostKind);
    if (ExtractCost <= ScalarCost)
      return false;
  }
  Value *Ptr0;
  Value *PtrN;
  if (Order.empty()) {
    Ptr0 = PointerOps.front();
    PtrN = PointerOps.back();
  } else {
    Ptr0 = PointerOps[Order.front()];
    PtrN = PointerOps[Order.back()];
  }
  std::optional<int64_t> Diff =
      getPointersDiff(ScalarTy, Ptr0, ScalarTy, PtrN, DL, SE);
  if (!Diff)
    return false;
  const size_t MaxRegSize =
      TTI.getRegisterBitWidth(TargetTransformInfo::RGK_FixedWidthVector)
          .getFixedValue();
  // Check for very large distances between elements.
  if (*Diff / Sz >= MaxRegSize / 8)
    return false;
  LoadVecTy = cast<FixedVectorType>(getWidenedType(ScalarTy, *Diff + 1));
  auto *LI = cast<LoadInst>(Order.empty() ? VL.front() : VL[Order.front()]);
  Align CommonAlignment = LI->getAlign();
  IsMasked = !isSafeToLoadUnconditionally(
      Ptr0, LoadVecTy, CommonAlignment, DL,
      cast<LoadInst>(Order.empty() ? VL.back() : VL[Order.back()]), &AC, &DT,
      &TLI);
  if (IsMasked && !TTI.isLegalMaskedLoad(LoadVecTy, CommonAlignment,
                                         LI->getPointerAddressSpace()))
    return false;
  // TODO: perform the analysis of each scalar load for better
  // safe-load-unconditionally analysis.
  bool IsStrided =
      buildCompressMask(PointerOps, Order, ScalarTy, DL, SE, CompressMask);
  assert(CompressMask.size() >= 2 && "At least two elements are required");
  SmallVector<Value *> OrderedPointerOps(PointerOps);
  if (!Order.empty())
    reorderScalars(OrderedPointerOps, Mask);
  auto [ScalarGEPCost, VectorGEPCost] =
      getGEPCosts(TTI, OrderedPointerOps, OrderedPointerOps.front(),
                  Instruction::Load, CostKind, ScalarTy, LoadVecTy);
  // The cost of scalar loads.
  InstructionCost ScalarLoadsCost =
      accumulate(VL, InstructionCost(),
                 [&](InstructionCost C, Value *V) {
                   return C + TTI.getInstructionCost(cast<Instruction>(V),
                                                     CostKind);
                 }) +
      ScalarGEPCost;
  APInt DemandedElts = APInt::getAllOnes(Sz);
  InstructionCost GatherCost =
      getScalarizationOverhead(TTI, ScalarTy, VecTy, DemandedElts,
                               /*Insert=*/true,
                               /*Extract=*/false, CostKind) +
      ScalarLoadsCost;
  InstructionCost LoadCost = 0;
  if (IsMasked) {
    LoadCost = TTI.getMemIntrinsicInstrCost(
        MemIntrinsicCostAttributes(Intrinsic::masked_load, LoadVecTy,
                                   CommonAlignment,
                                   LI->getPointerAddressSpace()),
        CostKind);
  } else {
    LoadCost =
        TTI.getMemoryOpCost(Instruction::Load, LoadVecTy, CommonAlignment,
                            LI->getPointerAddressSpace(), CostKind);
  }
  if (IsStrided && !IsMasked && Order.empty()) {
    // Check for potential segmented(interleaved) loads.
    VectorType *AlignedLoadVecTy = cast<VectorType>(getWidenedType(
        ScalarTy, getFullVectorNumberOfElements(TTI, ScalarTy, *Diff + 1)));
    if (!isSafeToLoadUnconditionally(Ptr0, AlignedLoadVecTy, CommonAlignment,
                                     DL, cast<LoadInst>(VL.back()), &AC, &DT,
                                     &TLI))
      AlignedLoadVecTy = LoadVecTy;
    if (TTI.isLegalInterleavedAccessType(AlignedLoadVecTy, CompressMask[1],
                                         CommonAlignment,
                                         LI->getPointerAddressSpace())) {
      InstructionCost InterleavedCost =
          VectorGEPCost + TTI.getInterleavedMemoryOpCost(
                              Instruction::Load, AlignedLoadVecTy,
                              CompressMask[1], {}, CommonAlignment,
                              LI->getPointerAddressSpace(), CostKind, IsMasked);
      if (InterleavedCost < GatherCost) {
        InterleaveFactor = CompressMask[1];
        LoadVecTy = AlignedLoadVecTy;
        return true;
      }
    }
  }
  // Estimating the compression shuffle cost below can be extremely expensive
  // for a very wide LoadVecTy, which is split into a large number of vector
  // registers (see processShuffleMasks). The shuffle cost is always
  // non-negative, so if the load cost alone already reaches the gather cost the
  // masked-load-compress cannot be profitable. Bail out before the costly
  // shuffle cost estimation in that case.
  if (VectorGEPCost + LoadCost >= GatherCost)
    return false;
  InstructionCost CompressCost = ::getShuffleCost(
      TTI, TTI::SK_PermuteSingleSrc, LoadVecTy, CompressMask, CostKind);
  if (!Order.empty()) {
    SmallVector<int> NewMask(Sz, PoisonMaskElem);
    for (unsigned I : seq<unsigned>(Sz)) {
      NewMask[I] = CompressMask[Mask[I]];
    }
    CompressMask.swap(NewMask);
  }
  InstructionCost TotalVecCost = VectorGEPCost + LoadCost + CompressCost;
  return TotalVecCost < GatherCost;
}

/// Checks if the \p VL can be transformed to a (masked)load + compress or
/// (masked) interleaved load.
static bool
isMaskedLoadCompress(ArrayRef<Value *> VL, ArrayRef<Value *> PointerOps,
                     ArrayRef<unsigned> Order, const TargetTransformInfo &TTI,
                     const DataLayout &DL, ScalarEvolution &SE,
                     AssumptionCache &AC, const DominatorTree &DT,
                     const TargetLibraryInfo &TLI,
                     const function_ref<bool(Value *)> AreAllUsersVectorized) {
  bool IsMasked;
  unsigned InterleaveFactor;
  SmallVector<int> CompressMask;
  VectorType *LoadVecTy;
  return isMaskedLoadCompress(VL, PointerOps, Order, TTI, DL, SE, AC, DT, TLI,
                              AreAllUsersVectorized, IsMasked, InterleaveFactor,
                              CompressMask, LoadVecTy);
}

/// Checks if the stores \p VL with pointers \p PointerOps can be lowered as a
/// single masked store. On success \p StoreVecTy is the widened store type and
/// \p ReuseShuffleIndices is the expand mask that places each stored value at
/// its element offset from the base (poison in the gaps).
static bool isMaskedStoreCompress(
    ArrayRef<Value *> VL, ArrayRef<Value *> PointerOps,
    ArrayRef<unsigned> Order, const TargetTransformInfo &TTI,
    const DataLayout &DL, ScalarEvolution &SE, Align CommonAlignment,
    SmallVectorImpl<int> &ReuseShuffleIndices, FixedVectorType *&StoreVecTy) {
  Type *ScalarTy = cast<StoreInst>(VL.front())->getValueOperand()->getType();
  const size_t Sz = VL.size();
  // Only simple scalar element types are supported.
  if (Sz < 2 || (!ScalarTy->isIntOrPtrTy() && !ScalarTy->isFloatingPointTy()))
    return false;
  Value *Ptr0 = Order.empty() ? PointerOps.front() : PointerOps[Order.front()];
  Value *PtrN = Order.empty() ? PointerOps.back() : PointerOps[Order.back()];
  std::optional<int64_t> Diff =
      getPointersDiff(ScalarTy, Ptr0, ScalarTy, PtrN, DL, SE);
  if (!Diff || *Diff <= 0)
    return false;
  // Avoid widened vectors with very large gaps between the stored elements.
  const unsigned MaxRegSize =
      TTI.getRegisterBitWidth(TargetTransformInfo::RGK_FixedWidthVector)
          .getFixedValue();
  const unsigned ScalarBits = DL.getTypeSizeInBits(ScalarTy).getFixedValue();
  if (ScalarBits == 0 ||
      static_cast<uint64_t>(*Diff) / Sz >= MaxRegSize / ScalarBits)
    return false;
  StoreVecTy = cast<FixedVectorType>(getWidenedType(ScalarTy, *Diff + 1));
  unsigned AS = cast<StoreInst>(VL.front())->getPointerAddressSpace();
  if (!TTI.isLegalMaskedStore(StoreVecTy, CommonAlignment, AS,
                              TTI::ConstantMask))
    return false;
  // Build the expand mask: store I (in address-sorted order) is placed at its
  // element offset from the base, other widened lanes are poison.
  ReuseShuffleIndices.assign(*Diff + 1, PoisonMaskElem);
  int64_t Prev = -1;
  for (unsigned I : seq<unsigned>(Sz)) {
    Value *Ptr = Order.empty() ? PointerOps[I] : PointerOps[Order[I]];
    std::optional<int64_t> Off =
        getPointersDiff(ScalarTy, Ptr0, ScalarTy, Ptr, DL, SE);
    if (!Off || *Off <= Prev || *Off > *Diff)
      return false;
    ReuseShuffleIndices[*Off] = static_cast<int>(I);
    Prev = *Off;
  }
  return true;
}

/// 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(PointerOps, [&](Value *V) {
    return isa<Instruction>(V) && any_of(V->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 {
  // 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.
  const unsigned Sz = PointerOps.size();
  unsigned VecSz = Sz;
  Type *NewScalarTy = BaseTy;
  if (NumOffsets > 1) {
    if (Sz % NumOffsets != 0)
      return false;
    VecSz = Sz / NumOffsets;
  }

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

  if (NumOffsets > 1 || BaseTy->isVectorTy())
    NewScalarTy = Type::getIntNTy(
        SE->getContext(),
        DL->getTypeSizeInBits(BaseTy).getFixedValue() * NumOffsets);
  auto *StridedLoadTy =
      cast<FixedVectorType>(getWidenedType(NewScalarTy, VecSz));
  unsigned MinProfitableStridedOps =
      IsLoad ? MinProfitableStridedLoads : MinProfitableStridedStores;
  const unsigned BaseTyNumElts = getNumElements(BaseTy);
  if (Sz * BaseTyNumElts < MinProfitableStridedOps ||
      !TTI->isTypeLegal(StridedLoadTy) ||
      !TTI->isLegalStridedLoadStore(StridedLoadTy, CommonAlignment))
    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 = [&] {
    if (!MaskedGatherLegal)
      MaskedGatherLegal =
          TTI->isLegalMaskedGather(VecTy, CommonAlignment) &&
          !TTI->forceScalarizeMaskedGather(VecTy, CommonAlignment);
    return *MaskedGatherLegal;
  };
  if (!IsSorted) {
    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);
        }))
      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, [&](Value *V) {
                               return areAllUsersVectorized(
                                   cast<Instruction>(V), UserIgnoreList);
                             }))
      return LoadsState::CompressVectorize;
    Align Alignment =
        cast<LoadInst>(Order.empty() ? VL.front() : VL[Order.front()])
            ->getAlign();
    if (analyzeConstantStrideCandidate(PointerOps, ScalarTy, Alignment, 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.
    TTI::TargetCostKind CostKind = TTI::TCK_RecipThroughput;
    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, PtrScalarTy, PtrVecTy,
                                                DemandedElts, /*Insert=*/true,
                                                /*Extract=*/false, CostKind);
    else
      VectorGEPCost +=
          getScalarizationOverhead(
              TTI, 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, 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);
         VF >= MinVF;
         VF = getFloorFullVectorNumberOfElements(TTI, ScalarTy, VF - 1)) {
      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, 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, ScalarTy, SubVecTy, APInt::getAllOnes(SliceVF),
                /*Insert=*/true, /*Extract=*/false, CostKind);
          else
            VectorGEPCost +=
                getScalarizationOverhead(
                    TTI, 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::OperandValueInfo()) +
              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::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, ShuffleMask,
                               CostKind, 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;
}

static bool clusterSortPtrAccesses(ArrayRef<Value *> VL,
                                   ArrayRef<BasicBlock *> BBs, Type *ElemTy,
                                   const DataLayout &DL, ScalarEvolution &SE,
                                   SmallVectorImpl<unsigned> &SortedIndices) {
  assert(
      all_of(VL, [](const Value *V) { return V->getType()->isPointerTy(); }) &&
      "Expected list of pointer operands.");
  // Map from bases to a vector of (Ptr, Offset, OrigIdx), which we insert each
  // Ptr into, sort and return the sorted indices with values next to one
  // another.
  SmallMapVector<
      std::pair<BasicBlock *, Value *>,
      SmallVector<SmallVector<std::tuple<Value *, int64_t, unsigned>>>, 8>
      Bases;
  Bases
      .try_emplace(std::make_pair(
          BBs.front(), getUnderlyingObject(VL.front(), RecursionMaxDepth)))
      .first->second.emplace_back().emplace_back(VL.front(), 0U, 0U);

  SortedIndices.clear();
  for (auto [Cnt, Ptr] : enumerate(VL.drop_front())) {
    auto Key = std::make_pair(BBs[Cnt + 1],
                              getUnderlyingObject(Ptr, RecursionMaxDepth));
    bool Found = any_of(Bases.try_emplace(Key).first->second,
                        [&, &Cnt = Cnt, &Ptr = Ptr](auto &Base) {
                          std::optional<int64_t> Diff =
                              getPointersDiff(ElemTy, std::get<0>(Base.front()),
                                              ElemTy, Ptr, DL, SE,
                                              /*StrictCheck=*/true);
                          if (!Diff)
                            return false;

                          Base.emplace_back(Ptr, *Diff, Cnt + 1);
                          return true;
                        });

    if (!Found) {
      // If we haven't found enough to usefully cluster, return early.
      if (Bases.size() > VL.size() / 2 - 1)
        return false;

      // Not found already - add a new Base
      Bases.find(Key)->second.emplace_back().emplace_back(Ptr, 0, Cnt + 1);
    }
  }

  if (Bases.size() == VL.size())
    return false;

  if (Bases.size() == 1 && (Bases.front().second.size() == 1 ||
                            Bases.front().second.size() == VL.size()))
    return false;

  // For each of the bases sort the pointers by Offset and check if any of the
  // base become consecutively allocated.
  auto ComparePointers = [](Value *Ptr1, Value *Ptr2) {
    SmallPtrSet<Value *, 13> FirstPointers;
    SmallPtrSet<Value *, 13> SecondPointers;
    Value *P1 = Ptr1;
    Value *P2 = Ptr2;
    unsigned Depth = 0;
    while (!FirstPointers.contains(P2) && !SecondPointers.contains(P1)) {
      if (P1 == P2 || Depth > RecursionMaxDepth)
        return false;
      FirstPointers.insert(P1);
      SecondPointers.insert(P2);
      P1 = getUnderlyingObject(P1, /*MaxLookup=*/1);
      P2 = getUnderlyingObject(P2, /*MaxLookup=*/1);
      ++Depth;
    }
    assert((FirstPointers.contains(P2) || SecondPointers.contains(P1)) &&
           "Unable to find matching root.");
    return FirstPointers.contains(P2) && !SecondPointers.contains(P1);
  };
  for (auto &Base : Bases) {
    for (auto &Vec : Base.second) {
      if (Vec.size() > 1) {
        stable_sort(Vec, llvm::less_second());
        int64_t InitialOffset = std::get<1>(Vec[0]);
        bool AnyConsecutive =
            all_of(enumerate(Vec), [InitialOffset](const auto &P) {
              return std::get<1>(P.value()) ==
                     int64_t(P.index()) + InitialOffset;
            });
        // Fill SortedIndices array only if it looks worth-while to sort the
        // ptrs.
        if (!AnyConsecutive)
          return false;
      }
    }
    stable_sort(Base.second, [&](const auto &V1, const auto &V2) {
      return ComparePointers(std::get<0>(V1.front()), std::get<0>(V2.front()));
    });
  }

  for (auto &T : Bases)
    for (const auto &Vec : T.second)
      for (const auto &P : Vec)
        SortedIndices.push_back(std::get<2>(P));

  assert(SortedIndices.size() == VL.size() &&
         "Expected SortedIndices to be the size of VL");
  return true;
}

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

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

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(*TTI,
                           getWidenedType(getValueType(TE.Scalars.front()),
                                          2 * TE.getVectorFactor()),
                           getValueType(TE.Scalars.front())) == 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 &&
        all_of(TE.Scalars, [Sz](Value *V) {
          if (isa<PoisonValue>(V))
            return true;
          std::optional<unsigned> Idx = getExtractIndex(cast<Instruction>(V));
          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) &&
       (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] : zip(UserBVHead, TE.Scalars)) {
      if (isa<Constant>(V) || !V->hasNUsesOrMore(1))
        continue;
      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.
    if (((TE.hasState() && TE.getOpcode() == Instruction::ExtractElement) ||
         (all_of(TE.Scalars, IsaPred<UndefValue, ExtractElementInst>) &&
          any_of(TE.Scalars, IsaPred<ExtractElementInst>))) &&
        all_of(TE.Scalars, [](Value *V) {
          auto *EE = dyn_cast<ExtractElementInst>(V);
          return !EE || 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, Mask);
        InstructionCost InsertFirstCost = TTI->getVectorInstrCost(
            Instruction::InsertElement, Ty, TTI::TCK_RecipThroughput, 0,
            PoisonValue::get(Ty), *It);
        InstructionCost InsertIdxCost = TTI->getVectorInstrCost(
            Instruction::InsertElement, Ty, TTI::TCK_RecipThroughput, 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)
        return std::move(CurrentOrder);
    }
    if (std::optional<OrdersType> CurrentOrder =
            findReusedOrderedScalars(TE, TopToBottom, IgnoreReorder))
      return CurrentOrder;
  }
  return std::nullopt;
}

/// Checks if the given mask is a "clustered" mask with the same clusters of
/// size \p Sz, which are not identity submasks.
static bool isRepeatedNonIdentityClusteredMask(ArrayRef<int> Mask,
                                               unsigned Sz) {
  ArrayRef<int> FirstCluster = Mask.slice(0, Sz);
  if (ShuffleVectorInst::isIdentityMask(FirstCluster, Sz))
    return false;
  for (unsigned I = Sz, E = Mask.size(); I < E; I += Sz) {
    ArrayRef<int> Cluster = Mask.slice(I, Sz);
    if (Cluster != FirstCluster)
      return false;
  }
  return true;
}

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

static void combineOrders(MutableArrayRef<unsigned> Order,
                          ArrayRef<unsigned> SecondaryOrder) {
  assert((SecondaryOrder.empty() || Order.size() == SecondaryOrder.size()) &&
         "Expected same size of orders");
  size_t Sz = Order.size();
  SmallBitVector UsedIndices(Sz);
  for (unsigned Idx : seq<unsigned>(0, Sz)) {
    if (Order[Idx] != Sz)
      UsedIndices.set(Order[Idx]);
  }
  if (SecondaryOrder.empty()) {
    for (unsigned Idx : seq<unsigned>(0, Sz))
      if (Order[Idx] == Sz && !UsedIndices.test(Idx))
        Order[Idx] = Idx;
  } else {
    for (unsigned Idx : seq<unsigned>(0, Sz))
      if (SecondaryOrder[Idx] != Sz && Order[Idx] == Sz &&
          !UsedIndices.test(SecondaryOrder[Idx]))
        Order[Idx] = SecondaryOrder[Idx];
  }
}

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 (VectorizableTree.front()->hasState() &&
      !VectorizableTree.front()->isGather() &&
      (VectorizableTree.front()->getOpcode() == Instruction::Store ||
       VectorizableTree.front()->getOpcode() == Instruction::PHI ||
       (VectorizableTree.front()->getVectorFactor() <= TinyVF &&
        (VectorizableTree.front()->getOpcode() == Instruction::PtrToInt ||
         VectorizableTree.front()->getOpcode() == Instruction::ICmp))) &&
      VectorizableTree.front()->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 (VectorizableTree.front()->hasState() &&
        VectorizableTree.front()->getOpcode() == Instruction::PHI &&
        VectorizableTree.front()->Scalars.size() == TinyVF &&
        VectorizableTree.front()->getNumOperands() > PhiOpsLimit)
      return false;
    // Single node, which require reorder - skip.
    if (VectorizableTree.front()->hasState() &&
        VectorizableTree.front()->getOpcode() == Instruction::Store &&
        VectorizableTree.front()->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))) &&
                       (VectorizableTree.front()->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 (VectorizableTree.front()->Scalars.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 (VectorizableTree.front()->Scalars.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::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()));
      }))
    return;
  // Compute IgnoreReorder once - it depends only on UserIgnoreList and
  // VectorizableTree.front(), which do not change during this loop.
  const bool IgnoreReorder =
      !UserIgnoreList && VectorizableTree.front()->hasState() &&
      (VectorizableTree.front()->getOpcode() == Instruction::InsertElement ||
       VectorizableTree.front()->getOpcode() == Instruction::InsertValue ||
       VectorizableTree.front()->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->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 = VectorizableTree.front()->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;
    for (const TreeEntry *OpTE : OrderedEntries) {
      // No need to reorder this nodes, still need to extend and to use shuffle,
      // just need to merge reordering shuffle and the reuse shuffle.
      if (!OpTE->ReuseShuffleIndices.empty() && !GathersToOrders.count(OpTE) &&
          OpTE->State != TreeEntry::SplitVectorize)
        continue;
      // 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.
    for (std::unique_ptr<TreeEntry> &TE : VectorizableTree) {
      // 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) &&
           (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);
      } else {
        // Reorder the node and its operands.
        TE->reorderOperands(Mask);
        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::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))
        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::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::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 : OrderedOps) {
      if (!(TE->State == TreeEntry::Vectorize ||
            TE->State == TreeEntry::StridedVectorize ||
            TE->State == TreeEntry::ExpandVectorize ||
            TE->State == TreeEntry::CompressVectorize ||
            TE->State == TreeEntry::SplitVectorize ||
            (TE->isGather() && GathersToOrders.contains(TE))) ||
          !TE->UserTreeIndex || !TE->ReuseShuffleIndices.empty() ||
          !Visited.insert(TE).second)
        continue;
      // 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())))
        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;
      }
      // 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())))
          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::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 == VectorizableTree.front().get())
          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);
      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 && !VectorizableTree.front()->ReorderIndices.empty() &&
      VectorizableTree.front()->ReuseShuffleIndices.empty())
    VectorizableTree.front()->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;
  // 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;

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

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()))
        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`
  for (ArrayRef<StoreInst *> StoresVec : Stores) {
    // If we have fewer than NumLanes stores, then we can't form a vector.
    if (StoresVec.size() != NumLanes)
      continue;

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

void BoUpSLP::buildTree(ArrayRef<Value *> Roots) {
  deleteTree();
  assert(TreeEntryToStridedPtrInfoMap.empty() &&
         "TreeEntryToStridedPtrInfoMap is not cleared");
  if (!allSameType(Roots))
    return;
  buildTreeRec(Roots, 0, EdgeInfo());
}

/// 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());
  if (!isValidElementType(ScalarTy))
    return;
  SmallVector<SmallVector<std::pair<LoadInst *, int64_t>>> ClusteredLoads;
  SmallVector<DenseMap<int64_t, LoadInst *>> ClusteredDistToLoad;
  for (Value *V : VL) {
    auto *LI = dyn_cast<LoadInst>(V);
    if (!LI)
      continue;
    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] : enumerate(GatheredLoads)) {
          if (Idx < Start)
            continue;
          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))
      CandidateVFs.push_back(MaxVF);
    for (int NumElts = getFloorFullVectorNumberOfElements(
             *TTI, Loads.front()->getType(), MaxVF);
         NumElts > 1; NumElts = getFloorFullVectorNumberOfElements(
                          *TTI, Loads.front()->getType(), NumElts - 1)) {
      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 : CandidateVFs) {
      if (Final && NumElts > BestVF)
        continue;
      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) {
            for (LoadInst *LI : Slice) {
              // If single use/user - allow to vectorize.
              if (LI->hasOneUse())
                continue;
              // 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 : LocalLoadsDists) {
            if (isVectorized(L.first))
              continue;
            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 (auto [Slice, _] : 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)
                             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();
                buildTreeRec(SubSlice, 0, EdgeInfo(), InterleaveFactor);
                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)) {
        SubKey = hash_combine(hash_value(I->getOpcode()), hash_value(ID));
      } else if (!VFDatabase(*Call).getMappings(*Call).empty()) {
        SubKey = hash_combine(hash_value(I->getOpcode()),
                              hash_value(Call->getCalledFunction()));
      } 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_value(I->getOpcode());
    }
    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) {
  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, TTI::TCK_RecipThroughput);
  }
  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, TTI::TCK_RecipThroughput);
  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, TTI::TCK_RecipThroughput);
    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) {
  assert((isa<BinaryOperator, CallInst>(I)) &&
         "getVectorOpCost expects an arithmetic op or a vectorizable call.");
  constexpr TTI::TargetCostKind CostKind = TTI::TCK_RecipThroughput;
  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);
    return std::min(IntrCost, LibCost);
  }
  return TTI.getArithmeticInstrCost(I->getOpcode(), VecTy, CostKind);
}

/// 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 operator==(const SeedGroupKey &O) const {
    return Opcode == O.Opcode && IntrID == O.IntrID &&
           CalleeName == O.CalleeName;
  }
  bool operator!=(const SeedGroupKey &O) const { return !(*this == O); }
  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) {
  if (!isa<BinaryOperator, CallInst>(I))
    return false;
  Type *Ty = I->getType();
  if ((Ty->isVectorTy() && !SLPReVec) || Ty->isAggregateType() ||
      !isValidElementType(Ty))
    return false;
  auto Analyze = [&]() {
    constexpr TTI::TargetCostKind CostKind = TTI::TCK_RecipThroughput;
    InstructionCost ScalarCost = TTI.getInstructionCost(I, CostKind);
    if (ScalarCost < TTI::TCC_Expensive)
      return false;
    constexpr unsigned MinVF = 2;
    return getVectorOpCost(I, MinVF, TTI, TLI) < 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());
        }))
      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(VL, [&](Value *V) {
      return isa<Constant>(V) || !isa<Instruction>(V) || L->isLoopInvariant(V);
    });
  };
  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 (Value *V : VL) {
      auto *PHI = dyn_cast<PHINode>(V);
      if (!PHI)
        continue;
      for (Value *Incoming : PHI->incoming_values()) {
        Instruction *Term = dyn_cast<Instruction>(Incoming);
        if (Term && 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) {
          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);
    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(VL,
               [](Value *V) {
                 auto *IV = dyn_cast<InsertValueInst>(V);
                 return IV &&
                        (IV->getNumIndices() != 1 ||
                         !::isValidElementType(IV->getOperand(1)->getType()) ||
                         IV->getOperand(1)->getType()->isVectorTy());
               }) ||
        none_of(VL, [](Value *V) {
          auto *IV = dyn_cast<InsertValueInst>(V);
          return IV && 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::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::IntToPtr:
  case Instruction::SIToFP:
  case Instruction::UIToFP:
  case Instruction::Trunc:
  case Instruction::FPTrunc:
  case Instruction::BitCast: {
    Type *SrcTy = VL0->getOperand(0)->getType();
    for (Value *V : VL) {
      if (isa<PoisonValue>(V))
        continue;
      Type *Ty = cast<Instruction>(V)->getOperand(0)->getType();
      if (Ty != SrcTy || !isValidElementType(Ty)) {
        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 (Value *V : VL) {
      if (isa<PoisonValue>(V))
        continue;
      auto *Cmp = cast<CmpInst>(V);
      if ((Cmp->getPredicate() != P0 && Cmp->getPredicate() != SwapP0) ||
          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(VL, [](Value *V) {
          auto *I = dyn_cast<Instruction>(V);
          return I && I->isBinaryOp() && !I->isFast();
        }))
      return TreeEntry::NeedToGather;
    return TreeEntry::Vectorize;
  case Instruction::GetElementPtr: {
    // We don't combine GEPs with complicated (nested) indexing.
    for (Value *V : VL) {
      auto *I = dyn_cast<GetElementPtrInst>(V);
      if (!I)
        continue;
      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 (Value *V : VL) {
      auto *GEP = dyn_cast<GEPOperator>(V);
      if (!GEP)
        continue;
      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 (Value *V : VL) {
      auto *I = dyn_cast<GetElementPtrInst>(V);
      if (!I)
        continue;
      auto *Op = I->getOperand(1);
      if ((!IsScatterVectorizeUserTE && !isa<ConstantInt>(Op)) ||
          (Op->getType() != Ty1 &&
           ((IsScatterVectorizeUserTE && !isa<ConstantInt>(Op)) ||
            Op->getType()->getScalarSizeInBits() >
                DL->getIndexSizeInBits(
                    V->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(VL, [](Value *V) {
          auto *I = dyn_cast<Instruction>(V);
          return I && !I->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);
    for (Value *V : VL) {
      CallInst *CI2 = dyn_cast<CallInst>(V);
      if (!CI2 || CI2->getCalledFunction() != F ||
          getVectorIntrinsicIDForCall(CI2, TLI) != ID ||
          (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);
    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 : VL) {
    if (isa<PoisonValue>(V))
      continue;
    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()))) {
    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;
    };
    // 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());
    auto *VecTy = cast<VectorType>(getWidenedType(ScalarTy, VL.size()));
    auto *UniquesVecTy =
        cast<VectorType>(getWidenedType(ScalarTy, NumUniqueScalarValues));
    const unsigned NumParts = ::getNumberOfParts(TTI, VecTy, ScalarTy);
    const unsigned UniquesNumParts =
        ::getNumberOfParts(TTI, 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);
    }
    constexpr TTI::TargetCostKind CostKind = TTI::TCK_RecipThroughput;
    InstructionCost ReusesCost = ::getShuffleCost(
        TTI, TTI::SK_PermuteSingleSrc, VecTy,
        NumUniqueScalarValues > VL.size() / 2 ? ArrayRef<int>()
                                              : ArrayRef(ReuseShuffleIndices),
        CostKind, /*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, 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, ScalarTy, UniquesVecTy,
                                         UniquesDemandedElts, /*Insert=*/true,
                                         /*Extract=*/false, CostKind,
                                         AreAllValuesNonConst, UniqueValues);
    UniquesCost += ReusesCost;
    if (UniquesCost <= InsertsCost)
      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;

  // 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());
  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()) &&
           (!hasFullVectorsOrPowerOf2(*TTI, Op1.front()->getType(),
                                      Op1.size()) ||
            !hasFullVectorsOrPowerOf2(*TTI, Op2.front()->getType(),
                                      Op2.size())))
    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;
  constexpr TTI::TargetCostKind Kind = TTI::TCK_RecipThroughput;
  InstructionCost InsertCost = ::getShuffleCost(
      *TTI, TTI::SK_InsertSubvector, VecTy, {}, Kind, Op1.size(), Op2VecTy);
  auto *SubVecTy = cast<VectorType>(
      getWidenedType(ScalarTy, std::max(Op1.size(), Op2.size())));
  InstructionCost NewShuffleCost =
      ::getShuffleCost(*TTI, TTI::SK_PermuteTwoSrc, SubVecTy, Mask, Kind);
  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())) {
    InstructionCost OriginalVecOpsCost =
        TTI->getArithmeticInstrCost(Opcode0, VecTy, Kind) +
        TTI->getArithmeticInstrCost(Opcode1, VecTy, Kind);
    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, OriginalMask, Kind);
    InstructionCost NewVecOpsCost =
        TTI->getArithmeticInstrCost(Opcode0, Op1VecTy, Kind) +
        TTI->getArithmeticInstrCost(Opcode1, Op2VecTy, Kind);
    InstructionCost NewCost =
        NewVecOpsCost + InsertCost +
        (!VectorizableTree.empty() && VectorizableTree.front()->hasState() &&
                 VectorizableTree.front()->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;

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

  /// 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 && isSupportedOpcode(I->getOpcode()) &&
             (!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;
        }
      }
      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(VL, [&](Value *V) {
            auto *I = dyn_cast<Instruction>(V);
            return I && I->getParent() == MainOp->getParent() &&
                   I->isTerminator();
          })) {
        MainOp = nullptr;
        return;
      }
      MainOpcode = MainOp->getOpcode();
    }
  }

  /// Returns the idempotent value for the \p MainOp with the detected \p
  /// MainOpcode. For Add, returns 0. For Or, it should choose between false and
  /// the operand itself, since V or V == V.
  Value *selectBestIdempotentValue() const {
    assert(isSupportedOpcode(MainOpcode) && "Unsupported opcode");
    return ConstantExpr::getBinOpIdentity(MainOpcode, 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.
  SmallVector<Value *> getOperands(const InstructionsState &S, Value *V) const {
    if (isa<PoisonValue>(V))
      return {V, V};
    if (!S.isCopyableElement(V))
      return convertTo(cast<Instruction>(V), S).second;
    assert(isSupportedOpcode(MainOpcode) && "Unsupported opcode");
    return {V, selectBestIdempotentValue()};
  }

  /// 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::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;
        }
        auto [Op, ConvertedOps] = convertTo(I, S);
        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;
        }
        auto [Op, ConvertedOps] = convertTo(I, S);
        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(VL,
                 [&](Value *V) {
                   auto *GEP = dyn_cast<GetElementPtrInst>(V);
                   return !GEP || 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(OpI->operands(), [&](Value *V) {
        auto *I = dyn_cast<Instruction>(V);
        return I && I->getOpcode() == SMainOpI->getOpcode();
      });
    };
    SmallPtrSet<Value *, 8> Operands;
    for (Value *V : VL) {
      auto *I = dyn_cast<Instruction>(V);
      if (!I || 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 (Value *V : VL) {
      auto *I = dyn_cast<Instruction>(V);
      if (!I || (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);
      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 ||
                     !isa<BinaryOperator>(S.getMainOp()) ||
                     all_of(VL, [&](Value *V) {
                       auto *I = dyn_cast<Instruction>(V);
                       return !I || I->getOpcode() == S.getOpcode() ||
                              (S.getOpcode() == Instruction::Add &&
                               I->getOpcode() == Instruction::Shl);
                     }))) {
      return S;
    }
    if (!VectorizeCopyableElements)
      return S;
    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;
    // Check if it is profitable to vectorize the instruction.
    SmallVector<BoUpSLP::ValueList> Operands = buildOperands(S, VL);
    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) {
      // 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;
      constexpr TTI::TargetCostKind Kind = TTI::TCK_RecipThroughput;
      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);
        break;
      default:
        llvm_unreachable("Unexpected instruction.");
      }
      if (VectorCost > ScalarCost)
        return OrigS;
      return S;
    }
    assert(Operands.size() == 2 && "Unexpected number of operands!");
    unsigned CopyableNum =
        count_if(VL, [&](Value *V) { return S.isCopyableElement(V); });
    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 (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.
    if (count_if(Operands.back(), IsaPred<Instruction>) > 1)
      return OrigS;
    auto CheckOperand = [&](ArrayRef<Value *> Ops) {
      if (allConstant(Ops) || isSplat(Ops))
        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 : Ops) {
          if (isa<UndefValue>(V))
            continue;
          ++Counters[V];
        }
        if (Counters.size() == 2 &&
            any_of(Counters, [&](const std::pair<const Value *, unsigned> &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;
    };
    if (!CheckOperand(Operands.front()))
      return OrigS;

    return S;
  }

  SmallVector<BoUpSLP::ValueList> buildOperands(const InstructionsState &S,
                                                ArrayRef<Value *> VL) {
    assert(S && "Invalid state!");
    SmallVector<BoUpSLP::ValueList> Operands;
    if (S.areInstructionsWithCopyableElements()) {
      MainOp = S.getMainOp();
      MainOpcode = S.getOpcode();
      const bool IsCommutative =
          isCommutative(MainOp) && MainOp->getNumOperands() == 2;
      Operands.assign(MainOp->getNumOperands(),
                      BoUpSLP::ValueList(VL.size(), nullptr));
      // Populate operands for every lane.
      for (auto [Idx, V] : enumerate(VL)) {
        SmallVector<Value *> OperandsForValue = getOperands(S, 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).
      if (IsCommutative) {
        // 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.
        auto CanSwap = [&](Value *V) {
          return isCommutative(S.getMatchingMainOpOrAltOp(cast<Instruction>(V)),
                               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;
        unsigned MajID0 = 0, MajID1 = 0;
        for (auto [Idx, V] : enumerate(VL)) {
          if (S.isCopyableElement(V) || isa<PoisonValue>(V))
            continue;
          unsigned ID0 = Operands[0][Idx]->getValueID();
          unsigned ID1 = Operands[1][Idx]->getValueID();
          if (ID0 == ID1)
            continue;
          unsigned MinID = std::min(ID0, ID1);
          unsigned MaxID = std::max(ID0, ID1);
          auto [It, Inserted] =
              PairCounts.try_emplace(std::make_pair(MinID, MaxID));
          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;
            }
          }
        }
        // Normalize non-copyable 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 non-copyable 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] : enumerate(VL)) {
          if (S.isCopyableElement(V) || isa<PoisonValue>(V))
            continue;
          // 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] : enumerate(VL)) {
            if (S.isCopyableElement(V) || isa<PoisonValue>(V))
              continue;
            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

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())->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();
    constexpr TTI::TargetCostKind Kind = TTI::TCK_RecipThroughput;
    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, {}, Kind) +
          ::getScalarizationOverhead(*TTI, ScalarTy, VecTy, Extracted,
                                     /*Insert=*/false, /*Extract=*/true, Kind);
      InstructionCost ScalarizeCostEstimate = ::getScalarizationOverhead(
          *TTI, ScalarTy, VecTy, Vectorized,
          /*Insert=*/true, /*Extract=*/false, Kind, /*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);
}

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 : VL) {
      if (isa<PoisonValue>(V))
        continue;
      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;

  // 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);
  if (State == TreeEntry::NeedToGather) {
    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);
  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::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::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.
        for (auto [Idx, V] : enumerate(VL)) {
          if (isa<PoisonValue>(V))
            continue;
          auto *Cmp = cast<CmpInst>(V);
          if (Cmp->getPredicate() != 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 (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);
      for (unsigned I : seq<unsigned>(VL0->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(VL, [](Value *V) {
            return !isa<PoisonValue>(V) && !cast<CmpInst>(V)->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] : enumerate(VL)) {
          if (isa<PoisonValue>(V))
            continue;
          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 (isa<BinaryOperator>(VL0) || CI) {
        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>(VL0->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))
    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 (Value *V : E->Scalars) {
    auto *I = dyn_cast<InsertValueInst>(V);
    if (!I)
      continue;
    MaxIdx = std::max(MaxIdx, I->getIndices().front());
  }
  return cast<FixedVectorType>(getWidenedType(getValueType(VL0), 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);
  assert(
      all_of(VL, IsaPred<UndefValue, ExtractElementInst, ExtractValueInst>) &&
      "Invalid opcode");
  // 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;
  for (auto [I, V] : enumerate(VL)) {
    auto *Inst = dyn_cast<Instruction>(V);
    if (!Inst)
      continue;
    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);

unsigned BoUpSLP::getNumScalarInsts() const {
  unsigned Count = 0;
  for (const std::unique_ptr<TreeEntry> &Ptr : VectorizableTree) {
    const TreeEntry &TE = *Ptr;
    if (DeletedNodes.contains(&TE))
      continue;
    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;
      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.
    if (TE.State == TreeEntry::CombinedVectorize)
      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 (Value *V : TE.Scalars) {
      if (!isa<Instruction>(V) ||
          (TE.hasCopyableElements() && TE.isCopyableElement(V)))
        continue;
      ++Count;
      // Calculate calls/divs/rems twice, they may cost higher, so better to
      // include their count twice to mimic slightly real cost here.
      auto *I = dyn_cast<Instruction>(V);
      if (I && (I->isIntDivRem() || I->isFPDivRem()))
        ++Count;
      if (auto *CI = dyn_cast<CallInst>(V)) {
        Intrinsic::ID BaseID = getVectorIntrinsicIDForCall(CI, TLI);
        if (!isTriviallyVectorizable(BaseID))
          ++Count;
      }
    }
    // 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 : TE.Scalars) {
          if (TE.hasCopyableElements() && TE.isCopyableElement(V))
            continue;
          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 if (Opcode == Instruction::FAdd || Opcode == Instruction::FSub) {
        for (Value *V : TE.Scalars) {
          if (TE.hasCopyableElements() && TE.isCopyableElement(V))
            continue;
          auto *I = dyn_cast<Instruction>(V);
          if (!I || (TE.isAltShuffle() && I->getOpcode() != Instruction::FAdd &&
                     I->getOpcode() != Instruction::FSub))
            continue;
          if (canConvertToFMA(I, InstructionsState(I, I), *DT, *DL, *TTI, *TLI)
                  .isValid()) {
            assert(Count > 0 && "Underflow in scalar inst count (fma)");
            --Count;
          }
        }
      }
    }
  }
  return Count;
}

unsigned BoUpSLP::getNumVectorInsts() const {
  unsigned Count = 0;
  SmallPtrSet<Value *, 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;
    bool IsGatherOrTransformed =
        TE.isGather() || TransformedToGatherNodes.contains(&TE);
    if (IsGatherOrTransformed) {
      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()) {
          ++Count;
          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 (Value *V : TE.Scalars)
          if (auto *EE = dyn_cast<ExtractElementInst>(V))
            GatherExtractSourceVecs.insert(EE->getVectorOperand());
      } else {
        for (Value *V : TE.Scalars) {
          if (!isConstant(V))
            ++Count;
        }
      }
      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;
      continue;
    }
    if (TE.State == TreeEntry::SplitVectorize)
      Count += 2;
    else
      ++Count;
    if (!TE.ReorderIndices.empty() || !TE.ReuseShuffleIndices.empty())
      ++Count;
  }
  Count += GatherExtractSourceVecs.size();
  // Count extract instructions from ExternalUses, skipping insertelements
  // (those get folded into shuffles, not real extracts).
  SmallPtrSet<Value *, 8> CountedExtracts;
  for (const ExternalUser &EU : ExternalUses) {
    if (isa_and_nonnull<InsertElementInst>(EU.User))
      continue;
    if (EU.User && EphValues.count(EU.User))
      continue;
    if (ExternalUsesAsOriginalScalar.contains(EU.Scalar))
      continue;
    if (!CountedExtracts.insert(EU.Scalar).second)
      continue;
    ++Count;
  }
  return Count;
}

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

static bool isAlternateInstruction(Instruction *I, Instruction *MainOp,
                                   Instruction *AltOp,
                                   const TargetLibraryInfo &TLI) {
  if (auto *MainCI = dyn_cast<CmpInst>(MainOp)) {
    auto *AltCI = cast<CmpInst>(AltOp);
    CmpInst::Predicate MainP = MainCI->getPredicate();
    [[maybe_unused]] CmpInst::Predicate AltP = AltCI->getPredicate();
    assert(MainP != AltP && "Expected different main/alternate predicates.");
    auto *CI = cast<CmpInst>(I);
    if (isCmpSameOrSwapped(MainCI, CI, TLI))
      return false;
    if (isCmpSameOrSwapped(AltCI, CI, TLI))
      return true;
    CmpInst::Predicate P = CI->getPredicate();
    CmpInst::Predicate SwappedP = CmpInst::getSwappedPredicate(P);

    assert((MainP == P || AltP == P || MainP == SwappedP || AltP == SwappedP) &&
           "CmpInst expected to match either main or alternate predicate or "
           "their swap.");
    return MainP != P && MainP != SwappedP;
  }
  return InstructionsState(MainOp, AltOp).getMatchingMainOpOrAltOp(I) == AltOp;
}

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

namespace {
/// The base class for shuffle instruction emission and shuffle cost estimation.
class BaseShuffleAnalysis {
protected:
  Type *ScalarTy = nullptr;

  BaseShuffleAnalysis(Type *ScalarTy) : ScalarTy(ScalarTy) {}

  /// V is expected to be a vectorized value.
  /// When REVEC is disabled, there is no difference between VF and
  /// VNumElements.
  /// When REVEC is enabled, VF is VNumElements / ScalarTyNumElements.
  /// e.g., if ScalarTy is <4 x Ty> and V1 is <8 x Ty>, 2 is returned instead
  /// of 8.
  unsigned getVF(Value *V) const {
    assert(V && "V cannot be nullptr");
    assert(isa<FixedVectorType>(V->getType()) &&
           "V does not have FixedVectorType");
    assert(ScalarTy && "ScalarTy cannot be nullptr");
    unsigned ScalarTyNumElements = getNumElements(ScalarTy);
    unsigned VNumElements =
        cast<FixedVectorType>(V->getType())->getNumElements();
    assert(VNumElements > ScalarTyNumElements &&
           "the number of elements of V is not large enough");
    assert(VNumElements % ScalarTyNumElements == 0 &&
           "the number of elements of V is not a vectorized value");
    return VNumElements / ScalarTyNumElements;
  }

  /// Checks if the mask is an identity mask.
  /// \param IsStrict if is true the function returns false if mask size does
  /// not match vector size.
  static bool isIdentityMask(ArrayRef<int> Mask, const FixedVectorType *VecTy,
                             bool IsStrict) {
    int Limit = Mask.size();
    int VF = VecTy->getNumElements();
    int Index = -1;
    if (VF == Limit && ShuffleVectorInst::isIdentityMask(Mask, Limit))
      return true;
    if (!IsStrict) {
      // Consider extract subvector starting from index 0.
      if (ShuffleVectorInst::isExtractSubvectorMask(Mask, VF, Index) &&
          Index == 0)
        return true;
      // All VF-size submasks are identity (e.g.
      // <poison,poison,poison,poison,0,1,2,poison,poison,1,2,3> etc. for VF 4).
      if (Limit % VF == 0 && all_of(seq<int>(0, Limit / VF), [=](int Idx) {
            ArrayRef<int> Slice = Mask.slice(Idx * VF, VF);
            return all_of(Slice, equal_to(PoisonMaskElem)) ||
                   ShuffleVectorInst::isIdentityMask(Slice, VF);
          }))
        return true;
    }
    return false;
  }

  /// Tries to combine 2 different masks into single one.
  /// \param LocalVF Vector length of the permuted input vector. \p Mask may
  /// change the size of the vector, \p LocalVF is the original size of the
  /// shuffled vector.
  static void combineMasks(unsigned LocalVF, SmallVectorImpl<int> &Mask,
                           ArrayRef<int> ExtMask) {
    unsigned VF = Mask.size();
    SmallVector<int> NewMask(ExtMask.size(), PoisonMaskElem);
    for (int I = 0, Sz = ExtMask.size(); I < Sz; ++I) {
      if (ExtMask[I] == PoisonMaskElem)
        continue;
      int MaskedIdx = Mask[ExtMask[I] % VF];
      NewMask[I] =
          MaskedIdx == PoisonMaskElem ? PoisonMaskElem : MaskedIdx % LocalVF;
    }
    Mask.swap(NewMask);
  }

  /// Looks through shuffles trying to reduce final number of shuffles in the
  /// code. The function looks 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 select vectors %0 and %1 with mask
  /// <0, 1, 2, 3> for the shuffle.
  /// 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 select vectors %0 and %1 with mask
  /// <0, 1, 2, 3> for the shuffle.
  /// So, it tries to transform permutations to simple vector merge, if
  /// possible.
  /// \param V The input vector which must be shuffled using the given \p Mask.
  /// If the better candidate is found, \p V is set to this best candidate
  /// vector.
  /// \param Mask The input mask for the shuffle. If the best candidate is found
  /// during looking-through-shuffles attempt, it is updated accordingly.
  /// \param SinglePermute true if the shuffle operation is originally a
  /// single-value-permutation. In this case the look-through-shuffles procedure
  /// may look for resizing shuffles as the best candidates.
  /// \return true if the shuffle results in the non-resizing identity shuffle
  /// (and thus can be ignored), false - otherwise.
  static bool peekThroughShuffles(Value *&V, SmallVectorImpl<int> &Mask,
                                  bool SinglePermute) {
    Value *Op = V;
    ShuffleVectorInst *IdentityOp = nullptr;
    SmallVector<int> IdentityMask;
    while (auto *SV = dyn_cast<ShuffleVectorInst>(Op)) {
      // Exit if not a fixed vector type or changing size shuffle.
      auto *SVTy = dyn_cast<FixedVectorType>(SV->getType());
      if (!SVTy)
        break;
      // Remember the identity or broadcast mask, if it is not a resizing
      // shuffle. If no better candidates are found, this Op and Mask will be
      // used in the final shuffle.
      if (isIdentityMask(Mask, SVTy, /*IsStrict=*/false)) {
        if (!IdentityOp || !SinglePermute ||
            (isIdentityMask(Mask, SVTy, /*IsStrict=*/true) &&
             !ShuffleVectorInst::isZeroEltSplatMask(IdentityMask,
                                                    IdentityMask.size()))) {
          IdentityOp = SV;
          // Store current mask in the IdentityMask so later we did not lost
          // this info if IdentityOp is selected as the best candidate for the
          // permutation.
          IdentityMask.assign(Mask);
        }
      }
      // Remember the broadcast mask. If no better candidates are found, this Op
      // and Mask will be used in the final shuffle.
      // Zero splat can be used as identity too, since it might be used with
      // mask <0, 1, 2, ...>, i.e. identity mask without extra reshuffling.
      // E.g. if need to shuffle the vector with the mask <3, 1, 2, 0>, which is
      // expensive, the analysis founds out, that the source vector is just a
      // broadcast, this original mask can be transformed to identity mask <0,
      // 1, 2, 3>.
      // \code
      // %0 = shuffle %v, poison, zeroinitalizer
      // %res = shuffle %0, poison, <3, 1, 2, 0>
      // \endcode
      // may be transformed to
      // \code
      // %0 = shuffle %v, poison, zeroinitalizer
      // %res = shuffle %0, poison, <0, 1, 2, 3>
      // \endcode
      if (SV->isZeroEltSplat()) {
        IdentityOp = SV;
        IdentityMask.assign(Mask);
      }
      int LocalVF = Mask.size();
      if (auto *SVOpTy =
              dyn_cast<FixedVectorType>(SV->getOperand(0)->getType()))
        LocalVF = SVOpTy->getNumElements();
      SmallVector<int> ExtMask(Mask.size(), PoisonMaskElem);
      for (auto [Idx, I] : enumerate(Mask)) {
        if (I == PoisonMaskElem ||
            static_cast<unsigned>(I) >= SV->getShuffleMask().size())
          continue;
        ExtMask[Idx] = SV->getMaskValue(I);
      }
      bool IsOp1Undef = isUndefVector</*isPoisonOnly=*/true>(
                            SV->getOperand(0),
                            buildUseMask(LocalVF, ExtMask, UseMask::FirstArg))
                            .all();
      bool IsOp2Undef = isUndefVector</*isPoisonOnly=*/true>(
                            SV->getOperand(1),
                            buildUseMask(LocalVF, ExtMask, UseMask::SecondArg))
                            .all();
      if (!IsOp1Undef && !IsOp2Undef) {
        // Update mask and mark undef elems.
        for (int &I : Mask) {
          if (I == PoisonMaskElem)
            continue;
          if (SV->getMaskValue(I % SV->getShuffleMask().size()) ==
              PoisonMaskElem)
            I = PoisonMaskElem;
        }
        break;
      }
      SmallVector<int> ShuffleMask(SV->getShuffleMask());
      combineMasks(LocalVF, ShuffleMask, Mask);
      Mask.swap(ShuffleMask);
      if (IsOp2Undef)
        Op = SV->getOperand(0);
      else
        Op = SV->getOperand(1);
    }
    if (auto *OpTy = dyn_cast<FixedVectorType>(Op->getType());
        !OpTy || !isIdentityMask(Mask, OpTy, SinglePermute) ||
        ShuffleVectorInst::isZeroEltSplatMask(Mask, Mask.size())) {
      if (IdentityOp) {
        V = IdentityOp;
        assert(Mask.size() == IdentityMask.size() &&
               "Expected masks of same sizes.");
        // Clear known poison elements.
        for (auto [I, Idx] : enumerate(Mask))
          if (Idx == PoisonMaskElem)
            IdentityMask[I] = PoisonMaskElem;
        Mask.swap(IdentityMask);
        auto *Shuffle = dyn_cast<ShuffleVectorInst>(V);
        return SinglePermute &&
               (isIdentityMask(Mask, cast<FixedVectorType>(V->getType()),
                               /*IsStrict=*/true) ||
                (Shuffle && Mask.size() == Shuffle->getShuffleMask().size() &&
                 Shuffle->isZeroEltSplat() &&
                 ShuffleVectorInst::isZeroEltSplatMask(Mask, Mask.size()) &&
                 all_of(enumerate(Mask), [&](const auto &P) {
                   return P.value() == PoisonMaskElem ||
                          Shuffle->getShuffleMask()[P.index()] == 0;
                 })));
      }
      V = Op;
      return false;
    }
    V = Op;
    return true;
  }

  /// Smart shuffle instruction emission, walks through shuffles trees and
  /// tries to find the best matching vector for the actual shuffle
  /// instruction.
  template <typename T, typename ShuffleBuilderTy, typename... Args>
  static T createShuffle(Value *V1, Value *V2, ArrayRef<int> Mask,
                         ShuffleBuilderTy &Builder, Type *ScalarTy,
                         Args... Arguments) {
    assert(V1 && "Expected at least one vector value.");
    unsigned ScalarTyNumElements = getNumElements(ScalarTy);
    SmallVector<int> NewMask(Mask);
    if (ScalarTyNumElements != 1) {
      assert(SLPReVec && "FixedVectorType is not expected.");
      transformScalarShuffleIndiciesToVector(ScalarTyNumElements, NewMask);
      Mask = NewMask;
    }
    if (V2)
      Builder.resizeToMatch(V1, V2);
    int VF = Mask.size();
    if (auto *FTy = dyn_cast<FixedVectorType>(V1->getType()))
      VF = FTy->getNumElements();
    if (V2 && !isUndefVector</*IsPoisonOnly=*/true>(
                   V2, buildUseMask(VF, Mask, UseMask::SecondArg))
                   .all()) {
      // Peek through shuffles.
      Value *Op1 = V1;
      Value *Op2 = V2;
      int VF =
          cast<VectorType>(V1->getType())->getElementCount().getKnownMinValue();
      SmallVector<int> CombinedMask1(Mask.size(), PoisonMaskElem);
      SmallVector<int> CombinedMask2(Mask.size(), PoisonMaskElem);
      for (int I = 0, E = Mask.size(); I < E; ++I) {
        if (Mask[I] < VF)
          CombinedMask1[I] = Mask[I];
        else
          CombinedMask2[I] = Mask[I] - VF;
      }
      Value *PrevOp1;
      Value *PrevOp2;
      do {
        PrevOp1 = Op1;
        PrevOp2 = Op2;
        (void)peekThroughShuffles(Op1, CombinedMask1, /*SinglePermute=*/false);
        (void)peekThroughShuffles(Op2, CombinedMask2, /*SinglePermute=*/false);
        // Check if we have 2 resizing shuffles - need to peek through operands
        // again.
        if (auto *SV1 = dyn_cast<ShuffleVectorInst>(Op1))
          if (auto *SV2 = dyn_cast<ShuffleVectorInst>(Op2)) {
            SmallVector<int> ExtMask1(Mask.size(), PoisonMaskElem);
            for (auto [Idx, I] : enumerate(CombinedMask1)) {
                if (I == PoisonMaskElem)
                continue;
                ExtMask1[Idx] = SV1->getMaskValue(I);
            }
            SmallBitVector UseMask1 = buildUseMask(
                cast<FixedVectorType>(SV1->getOperand(1)->getType())
                    ->getNumElements(),
                ExtMask1, UseMask::SecondArg);
            SmallVector<int> ExtMask2(CombinedMask2.size(), PoisonMaskElem);
            for (auto [Idx, I] : enumerate(CombinedMask2)) {
                if (I == PoisonMaskElem)
                continue;
                ExtMask2[Idx] = SV2->getMaskValue(I);
            }
            SmallBitVector UseMask2 = buildUseMask(
                cast<FixedVectorType>(SV2->getOperand(1)->getType())
                    ->getNumElements(),
                ExtMask2, UseMask::SecondArg);
            if (SV1->getOperand(0)->getType() ==
                    SV2->getOperand(0)->getType() &&
                SV1->getOperand(0)->getType() != SV1->getType() &&
                isUndefVector(SV1->getOperand(1), UseMask1).all() &&
                isUndefVector(SV2->getOperand(1), UseMask2).all()) {
              Op1 = SV1->getOperand(0);
              Op2 = SV2->getOperand(0);
              SmallVector<int> ShuffleMask1(SV1->getShuffleMask());
              int LocalVF = ShuffleMask1.size();
              if (auto *FTy = dyn_cast<FixedVectorType>(Op1->getType()))
                LocalVF = FTy->getNumElements();
              combineMasks(LocalVF, ShuffleMask1, CombinedMask1);
              CombinedMask1.swap(ShuffleMask1);
              SmallVector<int> ShuffleMask2(SV2->getShuffleMask());
              LocalVF = ShuffleMask2.size();
              if (auto *FTy = dyn_cast<FixedVectorType>(Op2->getType()))
                LocalVF = FTy->getNumElements();
              combineMasks(LocalVF, ShuffleMask2, CombinedMask2);
              CombinedMask2.swap(ShuffleMask2);
            }
          }
      } while (PrevOp1 != Op1 || PrevOp2 != Op2);
      Builder.resizeToMatch(Op1, Op2);
      VF = std::max(cast<VectorType>(Op1->getType())
                        ->getElementCount()
                        .getKnownMinValue(),
                    cast<VectorType>(Op2->getType())
                        ->getElementCount()
                        .getKnownMinValue());
      for (int I = 0, E = Mask.size(); I < E; ++I) {
        if (CombinedMask2[I] != PoisonMaskElem) {
          assert(CombinedMask1[I] == PoisonMaskElem &&
                 "Expected undefined mask element");
          CombinedMask1[I] = CombinedMask2[I] + (Op1 == Op2 ? 0 : VF);
        }
      }
      if (Op1 == Op2 &&
          (ShuffleVectorInst::isIdentityMask(CombinedMask1, VF) ||
           (ShuffleVectorInst::isZeroEltSplatMask(CombinedMask1, VF) &&
            isa<ShuffleVectorInst>(Op1) &&
            cast<ShuffleVectorInst>(Op1)->getShuffleMask() ==
                ArrayRef(CombinedMask1))))
        return Builder.createIdentity(Op1);
      return Builder.createShuffleVector(
          Op1, Op1 == Op2 ? PoisonValue::get(Op1->getType()) : Op2,
          CombinedMask1);
    }
    if (isa<PoisonValue>(V1))
      return Builder.createPoison(
          cast<VectorType>(V1->getType())->getElementType(), Mask.size());
    bool IsIdentity = peekThroughShuffles(V1, NewMask, /*SinglePermute=*/true);
    assert(V1 && "Expected non-null value after looking through shuffles.");

    if (!IsIdentity)
      return Builder.createShuffleVector(V1, NewMask, Arguments...);
    return Builder.createIdentity(V1);
  }

  /// Transforms mask \p CommonMask per given \p Mask to make proper set after
  /// shuffle emission.
  static void transformMaskAfterShuffle(MutableArrayRef<int> CommonMask,
                                        ArrayRef<int> Mask) {
    for (unsigned I : seq<unsigned>(CommonMask.size()))
      if (Mask[I] != PoisonMaskElem)
        CommonMask[I] = I;
  }
};
} // namespace

/// Calculate the scalar and the vector costs from vectorizing set of GEPs.
static std::pair<InstructionCost, InstructionCost>
getGEPCosts(const TargetTransformInfo &TTI, ArrayRef<Value *> Ptrs,
            Value *BasePtr, unsigned Opcode, TTI::TargetCostKind CostKind,
            Type *ScalarTy, VectorType *VecTy) {
  InstructionCost ScalarCost = 0;
  InstructionCost VecCost = 0;
  // Here we differentiate two cases: (1) when Ptrs represent a regular
  // vectorization tree node (as they are pointer arguments of scattered
  // loads) or (2) when Ptrs are the arguments of loads or stores being
  // vectorized as plane wide unit-stride load/store since all the
  // loads/stores are known to be from/to adjacent locations.
  if (Opcode == Instruction::Load || Opcode == Instruction::Store) {
    // Case 2: estimate costs for pointer related costs when vectorizing to
    // a wide load/store.
    // Scalar cost is estimated as a set of pointers with known relationship
    // between them.
    // For vector code we will use BasePtr as argument for the wide load/store
    // but we also need to account all the instructions which are going to
    // stay in vectorized code due to uses outside of these scalar
    // loads/stores.
    ScalarCost = TTI.getPointersChainCost(
        Ptrs, BasePtr, TTI::PointersChainInfo::getUnitStride(), ScalarTy,
        CostKind);

    SmallVector<const Value *> PtrsRetainedInVecCode;
    for (Value *V : Ptrs) {
      if (V == BasePtr) {
        PtrsRetainedInVecCode.push_back(V);
        continue;
      }
      auto *Ptr = dyn_cast<GetElementPtrInst>(V);
      // For simplicity assume Ptr to stay in vectorized code if it's not a
      // GEP instruction. We don't care since it's cost considered free.
      // TODO: We should check for any uses outside of vectorizable tree
      // rather than just single use.
      if (!Ptr || !Ptr->hasOneUse())
        PtrsRetainedInVecCode.push_back(V);
    }

    if (PtrsRetainedInVecCode.size() == Ptrs.size()) {
      // If all pointers stay in vectorized code then we don't have
      // any savings on that.
      return std::make_pair(TTI::TCC_Free, TTI::TCC_Free);
    }
    VecCost = TTI.getPointersChainCost(PtrsRetainedInVecCode, BasePtr,
                                       TTI::PointersChainInfo::getKnownStride(),
                                       VecTy, CostKind);
  } else {
    // Case 1: Ptrs are the arguments of loads that we are going to transform
    // into masked gather load intrinsic.
    // All the scalar GEPs will be removed as a result of vectorization.
    // For any external uses of some lanes extract element instructions will
    // be generated (which cost is estimated separately).
    TTI::PointersChainInfo PtrsInfo =
        all_of(Ptrs,
               [](const Value *V) {
                 auto *Ptr = dyn_cast<GetElementPtrInst>(V);
                 return Ptr && !Ptr->hasAllConstantIndices();
               })
            ? TTI::PointersChainInfo::getUnknownStride()
            : TTI::PointersChainInfo::getKnownStride();

    ScalarCost =
        TTI.getPointersChainCost(Ptrs, BasePtr, PtrsInfo, ScalarTy, CostKind);
    auto *BaseGEP = dyn_cast<GEPOperator>(BasePtr);
    if (!BaseGEP) {
      auto *It = find_if(Ptrs, IsaPred<GEPOperator>);
      if (It != Ptrs.end())
        BaseGEP = cast<GEPOperator>(*It);
    }
    if (BaseGEP) {
      SmallVector<const Value *> Indices(BaseGEP->indices());
      VecCost = TTI.getGEPCost(BaseGEP->getSourceElementType(),
                               BaseGEP->getPointerOperand(), Indices, VecTy,
                               CostKind);
    }
  }

  return std::make_pair(ScalarCost, VecCost);
}

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)) {
            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);
          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.
  constexpr TTI::TargetCostKind CostKind = TTI::TCK_RecipThroughput;
  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, 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, 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, ScalarTy, VecTy, DemandedElts,
                               /*Insert=*/true, /*Extract=*/false, CostKind);
  if (!DemandedElts.isAllOnes())
    BVCost += ::getShuffleCost(*TTI, TTI::SK_PermuteTwoSrc, VecTy, 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) {
  assert(all_of(VL,
                [](Value *V) {
                  return V->getType()->getScalarType()->isFloatingPointTy();
                }) &&
         "Can only convert to FMA for floating point types");
  assert(S.isAddSubLikeOp() && "Can only convert to FMA for add/sub");

  auto CheckForContractable = [&](ArrayRef<Value *> VL) {
    FastMathFlags FMF;
    FMF.set();
    for (Value *V : VL) {
      auto *I = dyn_cast<Instruction>(V);
      if (!I)
        continue;
      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))
    return InstructionCost::getInvalid();
  // fmul also should be contractable
  InstructionsCompatibilityAnalysis Analysis(DT, DL, TTI, TLI);
  SmallVector<BoUpSLP::ValueList> Operands = Analysis.buildOperands(S, VL);

  InstructionsState OpS = getSameOpcode(Operands.front(), TLI);
  if (!OpS.valid())
    return InstructionCost::getInvalid();

  if (OpS.isAltShuffle() || OpS.getOpcode() != Instruction::FMul)
    return InstructionCost::getInvalid();
  if (!CheckForContractable(Operands.front()))
    return InstructionCost::getInvalid();
  // Compare the costs.
  InstructionCost FMulPlusFAddCost = 0;
  InstructionCost FMACost = 0;
  constexpr TTI::TargetCostKind CostKind = TTI::TCK_RecipThroughput;
  FastMathFlags FMF;
  FMF.set();
  for (Value *V : VL) {
    auto *I = dyn_cast<Instruction>(V);
    if (!I)
      continue;
    if (!S.isCopyableElement(I))
      if (auto *FPCI = dyn_cast<FPMathOperator>(I))
        FMF &= FPCI->getFastMathFlags();
    FMulPlusFAddCost += TTI.getInstructionCost(I, CostKind);
  }
  unsigned NumOps = 0;
  for (auto [V, Op] : zip(VL, Operands.front())) {
    if (S.isCopyableElement(V))
      continue;
    auto *I = dyn_cast<Instruction>(Op);
    if (!I || !I->hasOneUse() || OpS.isCopyableElement(I)) {
      if (auto *OpI = dyn_cast<Instruction>(V))
        FMACost += TTI.getInstructionCost(OpI, CostKind);
      if (I)
        FMACost += TTI.getInstructionCost(I, CostKind);
      continue;
    }
    ++NumOps;
    if (auto *FPCI = dyn_cast<FPMathOperator>(I))
      FMF &= FPCI->getFastMathFlags();
    FMulPlusFAddCost += TTI.getInstructionCost(I, 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] : enumerate(RhsTE->Scalars)) {
      if (isa<UndefValue>(V))
        continue;
      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;
  }
  TTI::TargetCostKind CostKind = TTI::TCK_RecipThroughput;
  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)) +
      TTI->getCastInstrCost(
          Instruction::ZExt, VecTy,
          getWidenedType(SrcScalarTy, LhsTE->getVectorFactor()), CastCtx,
          CostKind);
  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,
                                    Mask, CostKind);
  }
  // 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->getIntrinsicInstrCost(CostAttrs, CostKind);
        if (BSwapCost <= BitcastCost) {
          VecCost +=
              TTI->getMemoryOpCost(Instruction::Load, SrcVecTy, LI->getAlign(),
                                   LI->getPointerAddressSpace(), CostKind);
          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);
      VecCost +=
          TTI->getMemoryOpCost(Instruction::Load, SrcVecTy, LI->getAlign(),
                               LI->getPointerAddressSpace(), CostKind);
      ForLoads = true;
    }
  }
  if (SrcType != ScalarTy) {
    BitcastCost += TTI->getCastInstrCost(Instruction::ZExt, ScalarTy, SrcType,
                                         TTI::CastContextHint::None, CostKind);
  }
  return BitcastCost < 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] : enumerate(CmpTE->Scalars)) {
    if (!match(V, MatchCmp))
      continue;
    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);

  constexpr TTI::TargetCostKind CostKind = TTI::TCK_RecipThroughput;
  InstructionCost VecCost =
      TTI->getCmpSelInstrCost(CmpTE->getOpcode(), VecTy, CmpTy, MainPred,
                              CostKind, getOperandInfo(CmpTE->getOperand(0)),
                              getOperandInfo(CmpTE->getOperand(1)));
  InstructionCost BVCost =
      ::getScalarizationOverhead(*TTI, Cmp->getType(), cast<VectorType>(CmpTy),
                                 APInt::getAllOnes(CmpTE->getVectorFactor()),
                                 /*Insert=*/true, /*Extract=*/false, CostKind);
  for (Value *V : CmpTE->Scalars) {
    auto *I = dyn_cast<Instruction>(V);
    if (!I)
      continue;
    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()));
  }
  TTI::TargetCostKind CostKind = TTI::TCK_RecipThroughput;
  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);
  }
  FastMathFlags FMF;
  InstructionCost SelectCost =
      TTI->getCmpSelInstrCost(Instruction::Select, VecTy, CmpTy,
                              CmpInst::BAD_ICMP_PREDICATE, CostKind,
                              getOperandInfo(Op1TE->Scalars),
                              getOperandInfo(Op2TE->Scalars)) +
      TTI->getArithmeticReductionCost(Instruction::Or, VecTy, FMF, CostKind);
  return BitcastCost <= SelectCost;
}

void BoUpSLP::transformNodes() {
  constexpr TTI::TargetCostKind CostKind = TTI::TCK_RecipThroughput;
  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;
    });
  };

  // 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))
        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);
           VF >= MinVF; VF = getFloorFullVectorNumberOfElements(
                            *TTI, VL.front()->getType(), VF - 1)) {
        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(
                *TTI, getWidenedType(getValueType(Slice.front()), 2 * VF),
                getValueType(Slice.front()));
            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 = [&] {
                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(Slice, [&](Value *V) {
                    if (isa<PoisonValue>(V))
                      return true;
                    return areAllUsersVectorized(cast<Instruction>(V),
                                                 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::OperandValueInfo()) +
            ::getShuffleCost(*TTI, TTI::SK_Reverse, VecTy, Mask, CostKind);
        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,
                                 TTI::OperandValueInfo()) +
            ::getShuffleCost(*TTI, TTI::SK_Reverse, VecTy, Mask, CostKind);
        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.
      if (E.State != TreeEntry::Vectorize ||
          !E.getOperations().isAddSubLikeOp() ||
          E.getOperations().isAltShuffle())
        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();
               });
      };
      if (!IsOneUseVectorFMulOperand(LHS) &&
          (E.getOpcode() == Instruction::FSub ||
           !IsOneUseVectorFMulOperand(RHS)))
        break;
      if (!canConvertToFMA(E.Scalars, E.getOperations(), *DT, *DL, *TTI, *TLI)
               .isValid())
        break;
      // This node is a fmuladd node.
      E.CombinedOp = TreeEntry::FMulAdd;
      TreeEntry *FMulEntry = getOperandEntry(&E, 0);
      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: {
      if (E.Idx != 0 || DL->isBigEndian())
        break;
      if (!UserIgnoreList)
        break;
      // Check that all reduction operands are disjoint or instructions.
      if (any_of(*UserIgnoreList, [](Value *V) {
            return !match(V, m_DisjointOr(m_Value(), m_Value()));
          }))
        break;
      OrdersType Order;
      bool IsBSwap;
      bool ForLoads;
      if (!matchesShlZExt(E, Order, IsBSwap, ForLoads))
        break;
      // 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 ZExt node.");
      // The ConstNode node is part of the combined node.
      ConstEntry->State = TreeEntry::CombinedVectorize;
      ConstEntry->CombinedOp = Code;
      break;
    }
    default:
      break;
    }
  }

  if (LoadEntriesToVectorize.empty()) {
    // Single load node - exit.
    if (VectorizableTree.size() <= 1 && VectorizableTree.front()->hasState() &&
        VectorizableTree.front()->getOpcode() == Instruction::Load)
      return;
    // Small graph with small VF - exit.
    constexpr unsigned SmallTree = 3;
    constexpr unsigned SmallVF = 2;
    if ((VectorizableTree.size() <= SmallTree &&
         VectorizableTree.front()->Scalars.size() == SmallVF) ||
        (VectorizableTree.size() <= 2 && UserIgnoreList))
      return;

    if (VectorizableTree.front()->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(E.Scalars,
                                  [&](Value *V) {
                                    return isa<LoadInst>(V) &&
                                           !isVectorized(V) &&
                                           !isDeleted(cast<Instruction>(V));
                                  }))) &&
        !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;
  SmallVector<PointerUnion<Value *, const TreeEntry *>, 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;
  constexpr static TTI::TargetCostKind CostKind = TTI::TCK_RecipThroughput;
  /// 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) {
    if ((!Root && allConstant(VL)) || all_of(VL, IsaPred<UndefValue>))
      return TTI::TCC_Free;
    auto *VecTy = cast<VectorType>(getWidenedType(ScalarTy, VL.size()));
    InstructionCost GatherCost = 0;
    SmallVector<Value *> Gathers(VL);
    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);
      }

      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);
      return InsertCost + ::getShuffleCost(TTI,
                                           TargetTransformInfo::SK_Broadcast,
                                           VecTy, ShuffleMask, CostKind,
                                           /*Index=*/0, /*SubTp=*/nullptr,
                                           /*Args=*/*It);
    }
    return GatherCost +
           (all_of(Gathers, IsaPred<UndefValue>)
                ? TTI::TCC_Free
                : R.getGatherCost(Gathers, !Root && VL.equals(Gathers),
                                  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] : enumerate(Mask)) {
        if (I == PoisonMaskElem)
          continue;
        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)), MaskSlice);
        continue;
      }
      if (*RegShuffleKind != TTI::SK_PermuteSingleSrc ||
          !ShuffleVectorInst::isIdentityMask(SubMask, EltsPerVector)) {
        Cost += ::getShuffleCost(
            TTI, *RegShuffleKind,
            cast<VectorType>(getWidenedType(ScalarTy, EltsPerVector)), SubMask);
      }
      const unsigned BaseVF = getFullVectorNumberOfElements(
          *R.TTI, VL.front()->getType(), alignTo(NumElts, EltsPerVector));
      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)), 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()) == &E1 &&
           cast<const TreeEntry *>(InVectors.back()) == E2) ||
          (!E2 && cast<const TreeEntry *>(InVectors.front()) == &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.
      Cost += createShuffle(InVectors.front(),
                            InVectors.size() == 1 ? nullptr : InVectors.back(),
                            CommonMask);
      transformMaskAfterShuffle(CommonMask, CommonMask);
    } else if (InVectors.size() == 2) {
      Cost += createShuffle(InVectors.front(), InVectors.back(), CommonMask);
      transformMaskAfterShuffle(CommonMask, CommonMask);
    }
    SameNodesEstimated = false;
    if (!E2 && InVectors.size() == 1) {
      unsigned VF = E1.getVectorFactor();
      if (Value *V1 = dyn_cast<Value *>(InVectors.front())) {
        VF = std::max(VF, getVF(V1));
      } else {
        const auto *E = cast<const TreeEntry *>(InVectors.front());
        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(), &E1, CommonMask);
      transformMaskAfterShuffle(CommonMask, CommonMask);
    } else {
      auto P = InVectors.front();
      Cost += createShuffle(&E1, E2, Mask);
      unsigned VF = Mask.size();
      if (Value *V1 = dyn_cast<Value *>(P)) {
        VF = std::max(VF,
                      getNumElements(V1->getType()));
      } else {
        const auto *E = cast<const TreeEntry *>(P);
        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, InVectors.front(), CommonMask);
      transformMaskAfterShuffle(CommonMask, CommonMask);
    }
  }

  class ShuffleCostBuilder {
    const TargetTransformInfo &TTI;

    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) : TTI(TTI) {}
    ~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()), Mask);
    }
    InstructionCost createShuffleVector(Value *V1, ArrayRef<int> Mask,
                                        ArrayRef<Value *> VL) 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()), Mask,
          TTI::TCK_RecipThroughput, /*Index=*/0, /*SubTp=*/nullptr, VL);
    }
    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 = {}) {
    ShuffleCostBuilder Builder(TTI);
    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),
                                    TTI::CastContextHint::None, 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;
        return TTI.getCastInstrCost(
            CastOpcode, VectorType::get(ScalarTy, VecTy->getElementCount()),
            VecTy, TTI::CastContextHint::None, 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 : CommonMask) {
            if (Idx == PoisonMaskElem)
              continue;
            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 : CommonMask) {
          if (Idx == PoisonMaskElem)
            continue;
          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 : CommonMask) {
          if (Idx == PoisonMaskElem)
            continue;
          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();
    return ExtraCost + BaseShuffleAnalysis::createShuffle<InstructionCost>(
                           V1, V2, CommonMask, Builder, ScalarTy, VL);
  }

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) {}
  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 =
        ::getNumberOfParts(TTI, 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 =
        ::getNumberOfParts(TTI, 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())
                            ->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) {
    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, V1);
      return;
    }
    if (ForExtracts) {
      // No need to add vectors here, already handled them in adjustExtracts.
      assert(InVectors.size() == 1 && isa<const TreeEntry *>(InVectors[0]) &&
             !CommonMask.empty() &&
             all_of(enumerate(CommonMask),
                    [&](auto P) {
                      Value *Scalar = cast<const TreeEntry *>(InVectors[0])
                                          ->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(), InVectors.back(), CommonMask);
      transformMaskAfterShuffle(CommonMask, CommonMask);
      VF = std::max<unsigned>(VF, CommonMask.size());
    } else if (const auto *InTE =
                   InVectors.front().dyn_cast<const TreeEntry *>()) {
      VF = std::max(VF, InTE->getVectorFactor());
    } else {
      VF = std::max(
          VF, cast<FixedVectorType>(cast<Value *>(InVectors.front())->getType())
                  ->getNumElements());
    }
    InVectors.push_back(V1);
    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) {
    Cost += getBuildVectorCost(VL, Root);
    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()));
  }
  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();
      if (InVectors.size() == 2)
        Cost += createShuffle(Vec, InVectors.back(), CommonMask);
      else
        Cost += createShuffle(Vec, nullptr, CommonMask);
      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();
      if (InVectors.size() == 2)
        Cost += createShuffle(Vec, InVectors.back(), CommonMask);
      else
        Cost += createShuffle(Vec, nullptr, CommonMask);
      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())),
            SVMask, CostKind);
      }
      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;
    return Cost +
           createShuffle(InVectors.front(),
                         InVectors.size() == 2 ? InVectors.back() : nullptr,
                         CommonMask, VL);
  }

  ~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)
    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;
  }
  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);
      } 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 : TE.Scalars) {
    if (isConstant(V))
      continue;
    ++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);
}

InstructionCost
BoUpSLP::getVectorSpillReloadCost(const TreeEntry *E, Type *ScalarTy,
                                  Type *VecTy, Type *FinalVecTy,
                                  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());
    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(*TTI, 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(*TTI, 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(*TTI, 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(*TTI, VecTy, ScalarTy);
    if (ResParts != 0) {
      const unsigned RC = TTI->getRegisterClassForType(/*Vector=*/true, VecTy);
      AddPartsToClass(RC, ResParts);
    }
    if (VecTy != FinalVecTy) {
      const unsigned FinalResParts =
          ::getNumberOfParts(*TTI, 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]);
  if (SLPReVec && E->State == TreeEntry::Vectorize &&
      E->getOpcode() == Instruction::InsertElement &&
      !E->getOperand(1).back()->getType()->isVectorTy())
    ScalarTy = ScalarTy->getScalarType();
  if (!isValidElementType(ScalarTy))
    return InstructionCost::getInvalid();
  TTI::TargetCostKind CostKind = TTI::TCK_RecipThroughput;

  // 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()) {
    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();
    return SpillsReloads +
           processBuildVector<ShuffleCostEstimator, InstructionCost>(
               E, ScalarTy, *TTI, VectorizedVals, *this, CheckedExtracts);
  }
  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)),
                           E->getSplitMask(), CostKind);
    }
    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), Mask, CostKind,
                                  /*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) &&
         "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.
        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->hasState() ||
              EI.UserTE->getOpcode() != Instruction::Select ||
              EI.EdgeIdx != 0) {
            auto UserBWIt = MinBWs.find(EI.UserTE);
            Type *UserScalarTy =
                (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;
      };
  // 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::OK_AnyValue, TTI::OP_None},
          {TTI::OK_AnyValue, TTI::OP_None}, CI);
    }
    return IntrinsicCost;
  };
  auto GetFMulAddCost = [&, &TTI = *TTI](const InstructionsState &S,
                                         Instruction *VI) {
    InstructionCost Cost = canConvertToFMA(VI, S, *DT, *DL, TTI, *TLI);
    return Cost;
  };
  switch (ShuffleOrOp) {
  case Instruction::PHI: {
    // Count reused scalars.
    InstructionCost ScalarCost = 0;
    SmallPtrSet<const TreeEntry *, 4> CountedOps;
    for (Value *V : UniqueValues) {
      auto *PHI = dyn_cast<PHINode>(V);
      if (!PHI)
        continue;

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

      auto *I = cast<Instruction>(UniqueValues[Idx]);
      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, *getExtractIndex(I),
              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;
        }
      }
      if (DemandedElts.isZero())
        DemandedElts = APInt::getZero(getNumElements(SrcVecTy));
      DemandedElts.setBit(*getExtractIndex(I));
      return InstructionCost(TTI::TCC_Free);
    };
    auto GetVectorCost = [&, &TTI = *TTI](InstructionCost CommonCost) {
      return CommonCost - (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(*TTI, 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, 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, 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, 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()));
      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::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, /*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) {
      // 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,
                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);
      return GetFMulAddCost(E->getOperations(),
                            cast<Instruction>(UniqueValues[Idx]));
    };
    auto GetVectorCost = [&, &TTI = *TTI](InstructionCost CommonCost) {
      FastMathFlags FMF;
      FMF.set();
      for (Value *V : E->Scalars) {
        if (auto *FPCI = dyn_cast<FPMathOperator>(V)) {
          FMF &= FPCI->getFastMathFlags();
          if (auto *FPCIOp = dyn_cast<FPMathOperator>(FPCI->getOperand(0)))
            FMF &= FPCIOp->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,
                                   TTI::CastContextHint::None, 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,
                                   TTI::CastContextHint::None, CostKind);
        }
      }
      return LoadCost + 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);
      InstructionCost ScalarCost = TTI->getArithmeticInstrCost(
          ShuffleOrOp, OrigScalarTy, CostKind, Op1Info, Op2Info, Operands);
      if (auto *I = dyn_cast<Instruction>(UniqueValues[Idx]);
          I && (ShuffleOrOp == Instruction::FAdd ||
                ShuffleOrOp == Instruction::FSub)) {
        InstructionCost IntrinsicCost = GetFMulAddCost(E->getOperations(), I);
        if (IntrinsicCost.isValid())
          ScalarCost = IntrinsicCost;
      }
      return ScalarCost;
    };
    auto GetVectorCost = [=](InstructionCost CommonCost) {
      if (ShuffleOrOp == Instruction::And && It != MinBWs.end()) {
        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;
        }
      }
      unsigned OpIdx = isa<UnaryOperator>(VL0) ? 0 : 1;
      TTI::OperandValueInfo Op1Info = getOperandInfo(E->getOperand(0));
      TTI::OperandValueInfo Op2Info = getOperandInfo(E->getOperand(OpIdx));
      return TTI->getArithmeticInstrCost(ShuffleOrOp, VecTy, CostKind, Op1Info,
                                         Op2Info, {}, nullptr, TLI) +
             CommonCost;
    };
    return GetCostDiff(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::OperandValueInfo(), 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::OperandValueInfo());
        }
        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, [](Value *) { return true; }, 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, CompressMask, CostKind);
        } else {
          VecLdCost = TTI->getMemoryOpCost(
              Instruction::Load, LoadVecTy, CommonAlignment,
              LI0->getPointerAddressSpace(), CostKind, TTI::OperandValueInfo());
          // TODO: include this cost into CommonCost.
          VecLdCost += ::getShuffleCost(*TTI, TTI::SK_PermuteSingleSrc,
                                        LoadVecTy, CompressMask, CostKind);
        }
        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::ExpandVectorize:
      case TreeEntry::CombinedVectorize:
      case TreeEntry::SplitVectorize:
      case TreeEntry::NeedToGather:
        llvm_unreachable("Unexpected vectorization state.");
      }
      return VecLdCost + CommonCost;
    };

    InstructionCost Cost = GetCostDiff(GetScalarCost, GetVectorCost);
    // If this node generates masked gather load then it is not a terminal node.
    // Hence address operand cost is estimated separately.
    if (E->State == TreeEntry::ScatterVectorize)
      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) {
      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);
      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;
      return TTI->getInstructionCost(VI, CostKind);
    };
    // 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())) {
        VecCost =
            TTIRef.getArithmeticInstrCost(E->getOpcode(), VecTy, CostKind);
        VecCost +=
            TTIRef.getArithmeticInstrCost(E->getAltOpcode(), VecTy, CostKind);
      } else if (auto *CI0 = dyn_cast<CmpInst>(VL0)) {
        auto *MaskTy = getWidenedType(Builder.getInt1Ty(), VL.size());
        VecCost = TTIRef.getCmpSelInstrCost(
            E->getOpcode(), VecTy, MaskTy, CI0->getPredicate(), CostKind,
            {TTI::OK_AnyValue, TTI::OP_None}, {TTI::OK_AnyValue, TTI::OP_None},
            VL0);
        VecCost += TTIRef.getCmpSelInstrCost(
            E->getOpcode(), VecTy, MaskTy,
            cast<CmpInst>(E->getAltOp())->getPredicate(), CostKind,
            {TTI::OK_AnyValue, TTI::OP_None}, {TTI::OK_AnyValue, TTI::OP_None},
            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,
                                          TTI::CastContextHint::None, CostKind);
            LLVM_DEBUG({
              dbgs()
                  << "SLP: alternate extension, which should be truncated.\n";
              E->dump();
            });
            return VecCost;
          }
        }
        VecCost = TTIRef.getCastInstrCost(E->getOpcode(), VecTy, SrcTy,
                                          TTI::CastContextHint::None, CostKind);
        VecCost +=
            TTIRef.getCastInstrCost(E->getAltOpcode(), VecTy, SrcTy,
                                    TTI::CastContextHint::None, CostKind);
      }
      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), Mask, CostKind);
      // 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.
      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),
                    calculateShufflevectorMask(E->Scalars));
            }
            return TTI::TCC_Free;
          });
    return GetCostDiff(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 ||
            (((TE->hasState() &&
               TE->getOpcode() == Instruction::ExtractElement) ||
              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 ||
       (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))
    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 = *VectorizableTree.front();
  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(
             Front.Scalars,
             [&](Value *V) {
               auto *I = dyn_cast<Instruction>(V);
               return !I || !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) {
    // 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) &&
              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) &&
            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(TE->Scalars, [&](Value *V) {
                        return !isa<LoadInst>(V) ||
                               areAllUsersVectorized(cast<Instruction>(V));
                      });
             })))))
        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.
  const bool IsAllowedSingleBVNode =
      TreeSize > 1 || (FrontHasState && !Front.isAltShuffle() &&
                       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,
            TTI::TCK_RecipThroughput) > -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 (VectorizableTree.front()->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 = VectorizableTree.front().get();
  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::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, TTI::TCK_RecipThroughput);
    InstructionCost CallCost = TTI->getCallInstrCost(
        nullptr, II->getType(), ICA.getArgTypes(), TTI::TCK_RecipThroughput);
    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;
  };
  auto AddCosts = [&](const TreeEntry *Op) {
    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());
    uint64_t Scale = getScaleToLoopIterations(*Op);
    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. if there is (at least one)
  // non-vectorized call between the blocks. This allows to skip the analysis of
  // the same block paths multiple times.
  SmallDenseMap<std::pair<const BasicBlock *, const BasicBlock *>, bool>
      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 Instruction &I : *BB) {
      const auto *CB = dyn_cast<CallBase>(&I);
      if (CB && 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 : L->blocks()) {
      if (isa<CatchSwitchInst>(BB->getTerminator()))
        continue;
      // 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 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;
    bool Res = false;
    scope_exit Cleanup([&]() { ParentOpParentToPreds.try_emplace(Key, Res); });
    // If Op is loop-invariant, a call anywhere in the loop body forces a spill,
    // even when a call-free forward path from Root back to OpParent exists on
    // the first iteration. Find the outermost such enclosing loop and reject if
    // its body contains a non-vec call.
    const Loop *L = LI->getLoopFor(Root);
    const Loop *Outermost = nullptr;
    while (L && !L->contains(OpParent)) {
      Outermost = L;
      L = L->getParentLoop();
    }
    if (Outermost && LoopBodyHasCall(Outermost))
      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 `true` (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 true. If the worklist is exhausted without reaching
    // OpParent, every admissible path is blocked by a call and we return
    // false so the caller charges the spill cost.
    while (!Worklist.empty()) {
      BasicBlock *BB = Worklist.pop_back_val();
      if (BB == OpParent) {
        Res = true;
        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()) {
        if (It->second) {
          // BB is known to reach OpParent via a call-free path.
          Res = true;
          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)
        return Res;
      if (!isa<CatchSwitchInst>(BB->getTerminator()) &&
          !CheckForNonVecCallsInSameBlock(&*BB->getFirstNonPHIOrDbgOrAlloca(),
                                          BB->getTerminator()))
        continue;
      Worklist.append(pred_begin(BB), pred_end(BB));
    }
    // Worklist drained without ever reaching OpParent: every path between
    // Root and OpParent is blocked by a non-vec call.
    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;
  };
  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 ||
          (Entry->getOpcode() != Instruction::PHI && Op->isGather()) ||
          (Op->isGather() && allConstant(Op->Scalars)))
        continue;
      Budget = 0;
      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 (Value *V : Op->Scalars) {
          auto *Inst = dyn_cast<Instruction>(V);
          if (!Inst)
            continue;
          if (isVectorized(V)) {
            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);
          continue;
        }
        if (!CheckForNonVecCallsInSameBlock(OpLastInst, LastInst))
          AddCosts(Op);
        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);
        continue;
      }
      // 2. Check op's block from the end.
      if (!CheckForNonVecCallsInSameBlock(OpLastInst,
                                          OpParent->getTerminator())) {
        AddCosts(Op);
        continue;
      }
      // 3. Check the predecessors of entry's block till op's block.
      if (!CheckPredecessors(Parent, Pred, OpParent)) {
        AddCosts(Op);
        continue;
      }
    }
  }

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

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

  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);
  };
  constexpr TTI::TargetCostKind CostKind = TTI::TCK_RecipThroughput;
  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.
    const bool IsGatherLike =
        TE.isGather() || TE.State == TreeEntry::SplitVectorize;
    if (!CostIsFree && !TE.isGather() && TE.hasState()) {
      if (PrevVecParent == TE.getMainOp()->getParent()) {
        Scale = PrevScale;
        C *= Scale;
        EntryToScale.try_emplace(&TE, Scale);
      }
    }
    if (!CostIsFree && !Scale) {
      Scale =
          IsGatherLike
              ? getGatherNodeEffectiveScale(TE, TE.Idx == 0 ? RdxRoot : nullptr)
              : getScaleToLoopIterations(TE);
      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()))) {
      // 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, 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.
  if (SLPCostThreshold.getNumOccurrences() > 0 && SLPCostThreshold < 0 &&
      Cost < -SLPCostThreshold)
    return Cost;
  // The narrow non-profitable tree in loop? Skip, may cause regressions.
  constexpr unsigned PartLimit = 2;
  const unsigned Sz =
      getVectorElementSize(VectorizableTree.front()->Scalars.front());
  const unsigned MinVF = getMinVF(Sz);
  if (Cost >= -SLPCostThreshold &&
      VectorizableTree.front()->Scalars.size() * PartLimit <= MinVF &&
      (!VectorizableTree.front()->hasState() ||
       (VectorizableTree.front()->getOpcode() != Instruction::Store &&
        LI->getLoopFor(VectorizableTree.front()->getMainOp()->getParent()))))
    return Cost;
  // Store the cost + external uses estimation as the first element of the
  // tuple, just the cost as the second element of the tuple. Required to return
  // correct cost estimation for the tree, extracts are calculated separately.
  // Extracts, calculated here, are just quick estimations.
  SmallVector<
      std::tuple<InstructionCost, InstructionCost, SmallVector<unsigned>>>
      SubtreeCosts(VectorizableTree.size());
  auto 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;
    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 : GatheredLoadsNodes) {
    InstructionCost TotalCost = std::get<0>(SubtreeCosts[TE->Idx]);
    InstructionCost Cost = std::get<1>(SubtreeCosts[TE->Idx]);
    for (Value *V : TE->Scalars) {
      for (const TreeEntry *BVTE : ValueToGatherNodes.lookup(V))
        UpdateParentNodes(BVTE, TE, TotalCost, Cost, Visited,
                          /*AddToList=*/false);
    }
  }
  Visited.clear();
  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;
  for (const auto [Idx, P] : enumerate(SubtreeCosts))
    Worklist.emplace(VectorizableTree[Idx].get(), P);

  // Narrow store trees with non-profitable immediate values - exit.
  if (!UserIgnoreList && VectorizableTree.front()->getVectorFactor() < MinVF &&
      VectorizableTree.front()->hasState() &&
      VectorizableTree.front()->getOpcode() == Instruction::Store &&
      (Worklist.top().first->Idx == 0 || Worklist.top().first->Idx == 1))
    return Cost;

  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())) ||
        // 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(TE->Scalars, [&](Value *V) {
          auto *I = dyn_cast<CmpInst>(V);
          if (!I)
            return false;
          return I->getPredicate() !=
                 cast<CmpInst>(TE->getMainOp())->getPredicate();
        })) {
      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());
    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, 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), 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;
    // 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 (VectorizableTree.front()->hasState() &&
          VectorizableTree.front()->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();
  }
  if (!Changed)
    return std::get<1>(SubtreeCosts.front());

  SmallPtrSet<TreeEntry *, 4> GatheredLoadsToDelete;
  InstructionCost LoadsExtractsCost = 0;
  // 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 : GatheredLoadsNodes) {
    if (DeletedNodes.contains(TE) || TransformedToGatherNodes.contains(TE))
      continue;
    GatheredLoadsToDelete.insert(TE);
    APInt DemandedElts = APInt::getZero(TE->getVectorFactor());
    // All loads are removed from gathered? Need to delete the subtree.
    SmallDenseMap<const TreeEntry *, SmallVector<Value *>> ValuesToInsert;
    for (Value *V : TE->Scalars) {
      unsigned Pos = TE->findLaneForValue(V);
      for (const TreeEntry *BVE : ValueToGatherNodes.lookup(V)) {
        if (DeletedNodes.contains(BVE))
          continue;
        DemandedElts.setBit(Pos);
        ValuesToInsert.try_emplace(BVE).first->second.push_back(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 ExtractsCost = ::getScalarizationOverhead(
          *TTI, ScalarTy, cast<VectorType>(VecTy), DemandedElts,
          /*Insert=*/false, /*Extract=*/true, CostKind);
      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);
        }
        auto *BVVecTy = getWidenedType(ScalarTy, BVE->getVectorFactor());
        BVCost += ::getScalarizationOverhead(
            *TTI, ScalarTy, cast<VectorType>(BVVecTy), BVDemandedElts,
            /*Insert=*/true, /*Extract=*/false, CostKind,
            BVDemandedElts.isAllOnes(), BVValues);
      }
      if (ExtractsCost < BVCost) {
        LoadsExtractsCost += ExtractsCost;
        GatheredLoadsToDelete.erase(TE);
        continue;
      }
      LoadsExtractsCost += BVCost;
    }
    NodesCosts.erase(TE);
  }

  // Deleted all subtrees rooted at gathered loads nodes.
  for (std::unique_ptr<TreeEntry> &TE : VectorizableTree) {
    if (TE->UserTreeIndex &&
        GatheredLoadsToDelete.contains(TE->UserTreeIndex.UserTE)) {
      DeletedNodes.insert(TE.get());
      NodesCosts.erase(TE.get());
      GatheredLoadsToDelete.insert(TE.get());
    }
    if (GatheredLoadsToDelete.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;
    if (!NodesCosts.contains(TE.get())) {
      InstructionCost C =
          getEntryCost(TE.get(), VectorizedVals, CheckedExtracts);
      if (!C.isValid() || C == 0) {
        NodesCosts.try_emplace(TE.get(), C);
        continue;
      }
      uint64_t Scale = EntryToScale.lookup(TE.get());
      if (!Scale) {
        const bool IsGatherLike =
            TE->isGather() || TE->State == TreeEntry::SplitVectorize;
        Scale = IsGatherLike ? getGatherNodeEffectiveScale(*TE.get())
                             : getScaleToLoopIterations(*TE.get());
      }
      C *= Scale;
      NodesCosts.try_emplace(TE.get(), C);
    }
  }

  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");
  }
  if (NewCost + LoadsExtractsCost > Cost ||
      (!PreferTrimmedTree && NewCost + LoadsExtractsCost == Cost)) {
    DeletedNodes.clear();
    TransformedToGatherNodes.clear();
    NewCost = Cost;
  } else {
    // If the remaining tree is just a buildvector - exit, it will cause
    // endless attempts to vectorize.
    if (VectorizableTree.size() >= 2 && VectorizableTree.front()->hasState() &&
        VectorizableTree.front()->getOpcode() == Instruction::InsertElement &&
        TransformedToGatherNodes.contains(VectorizableTree[1].get()))
      return InstructionCost::getInvalid();
    if (VectorizableTree.size() >= 3 && VectorizableTree.front()->hasState() &&
        VectorizableTree.front()->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();
  }
  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

InstructionCost BoUpSLP::getTreeCost(InstructionCost TreeCost,
                                     ArrayRef<Value *> VectorizedVals,
                                     InstructionCost ReductionCost,
                                     Instruction *RdxRoot) {
  // 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 below 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.
  auto BypassesInstCountCheck = [&]() {
    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);
    });
  };
  // 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 (SLPInstCountCheck && TTI->preferSLPInstCountCheck() &&
      VectorizableTree.front()->getVectorFactor() == 2 &&
      SLPCostThreshold == 0 &&
      (!SLPReVec ||
       !isa<VectorType>(
           VectorizableTree.front()->Scalars.front()->getType()))) {
    unsigned NumScalar = getNumScalarInsts();
    unsigned NumVector = getNumVectorInsts();
    LLVM_DEBUG(dbgs() << "SLP: Inst count check: vector=" << NumVector
                      << " scalar=" << NumScalar << "\n");
    if (NumVector > NumScalar && !BypassesInstCountCheck()) {
      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, *VectorizableTree.front().get(),
                              /*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()) *
              VectorizableTree.front()->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;
  bool AllUsersGEPSWithStoresLoads = true;
  SmallBitVector UsedLanes(VectorizableTree.front()->getVectorFactor());
  SmallVector<const Value *> Pointers;
  Type *UserScalarTy = nullptr;
  for (ExternalUser &EU : ExternalUses) {
    ScalarUserAndIdx.emplace_back(EU.Scalar, EU.User, EU.Lane);
    if (EU.E.Idx == 0) {
      UsedLanes.set(EU.Lane);
      auto *User = dyn_cast_if_present<GetElementPtrInst>(EU.User);
      if (User && User->hasOneUse() &&
          isa<LoadInst, StoreInst>(User->user_back())) {
        Type *LocalTy = getValueType(User->user_back());
        if (!UserScalarTy && !isa<ScalableVectorType>(LocalTy)) {
          UserScalarTy = LocalTy;
        } else if (UserScalarTy != LocalTy) {
          AllUsersGEPSWithStoresLoads = false;
          break;
        }
        Pointers.push_back(User);
      } else {
        AllUsersGEPSWithStoresLoads = false;
        break;
      }
    }
  }
  AllUsersGEPSWithStoresLoads &= UsedLanes.all();

  // 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 : ExternalUses) {
    if (!EU.User || isa<InsertElementInst>(EU.User))
      continue;
    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;
              TTI::TargetCostKind CostKind = TTI::TCK_RecipThroughput;
              InstructionCost C = TTI->getCastInstrCost(
                  VecOpcode, FTy,
                  getWidenedType(IntegerType::get(FTy->getContext(), BWSz),
                                 FTy->getNumElements()),
                  TTI::CastContextHint::None, 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;
        }
      }
    }

    TTI::TargetCostKind CostKind = TTI::TCK_RecipThroughput;
    // 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, Extend, ScalarTy,
                                           cast<VectorType>(VecTy), EU.Lane);
      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, 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();
        for (const auto &P : enumerate(ExternalUses)) {
          // Ignore phis in loops.
          if (IsPhiInLoop(P.value()))
            continue;

          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 &&
                            VectorizableTree.front()->Scalars.size() > 2)) &&
            VectorizableTree.front()->hasState() &&
            VectorizableTree.front()->getOpcode() == Instruction::PHI &&
            !Inst->hasNUsesOrMore(UsesLimit) &&
            none_of(Inst->users(),
                    [&](User *U) {
                      auto *PHIUser = dyn_cast<PHINode>(U);
                      return (!PHIUser ||
                              PHIUser->getParent() != VectorizableTree.front()
                                                          ->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);
          for (Value *V : Inst->operands()) {
            // Struct operands cannot be rebuilt by the !User extraction
            // path (it has no insertvalue chain), so leave their existing
            // ExtractValueInst user in place.
            if (isa<StructType>(V->getType()))
              continue;
            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 : IOp->operands()) {
                if (isa<StructType>(V->getType()))
                  continue;
                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 for the root entry when
  // every external use of its scalars is a GEP feeding a single load/store
  // (see the detection loop above). Vectorizing the root 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 = *VectorizableTree.front();
    const bool AnyRootKeptAsScalar = any_of(RootEntry.Scalars, [&](Value *V) {
      return ExternalUsesAsOriginalScalar.contains(V);
    });
    const Value *CommonBase = nullptr;
    bool HaveCommonBase = true;
    for (const Value *P : Pointers) {
      const Value *Op = getUnderlyingObject(P);
      if (!CommonBase)
        CommonBase = Op;
      else if (CommonBase != Op) {
        HaveCommonBase = false;
        break;
      }
    }
    if (!AnyRootKeptAsScalar && HaveCommonBase) {
      TTI::TargetCostKind CostKind = TTI::TCK_RecipThroughput;
      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 = *VectorizableTree.front();
    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,
                                  TTI::TCK_RecipThroughput);
        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)),
            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)),
                               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), 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), 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, TTI::TCK_RecipThroughput);
    Cost -= InsertCost;
  }

  // Add the cost for reduced value resize (if required).
  if (ReductionBitWidth != 0) {
    assert(UserIgnoreList && "Expected reduction tree.");
    const TreeEntry &E = *VectorizableTree.front();
    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,
                                  TTI::TCK_RecipThroughput);
        CastCost = ScaleCost(CastCost, *VectorizableTree.front().get(),
                             /*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 == VectorizableTree.front().get())
      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 : VL) {
      if (isConstant(V))
        continue;
      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)) {
      for (TreeEntry *E : getSplitTreeEntries(V)) {
        if (TE == E || !TransformedToGatherNodes.contains(E) ||
            !E->UserTreeIndex || E->UserTreeIndex.UserTE->isGather())
          continue;
        GatherNodes.push_back(E);
      }
      for (TreeEntry *E : getTreeEntries(V)) {
        if (TE == E || !TransformedToGatherNodes.contains(E) ||
            !E->UserTreeIndex || E->UserTreeIndex.UserTE->isGather())
          continue;
        GatherNodes.push_back(E);
      }
    }
    for (const TreeEntry *TEPtr : GatherNodes) {
      if (TEPtr == TE || TEPtr->Idx == 0 || DeletedNodes.contains(TEPtr))
        continue;
      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 : SubMask) {
      if (Idx == PoisonMaskElem)
        continue;
      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);
      auto *RegFloorTy = getWidenedType(VL.front()->getType(), RegFloor);
      unsigned RegFloorParts =
          ::getNumberOfParts(*TTI, 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 : SubMask) {
        if (Idx == PoisonMaskElem)
          continue;
        Idx = (Idx % VF) - Offset + (Idx >= static_cast<int>(VF) ? NewVF : 0);
      }
    } else {
      NewVF = VF;
    }

    constexpr TTI::TargetCostKind CostKind = TTI::TCK_RecipThroughput;
    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, Mask, CostKind);
    };
    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, 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, 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, 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 == VectorizableTree.front().get() &&
      (!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 == VectorizableTree.front().get()) &&
         "Expected only single user of the gather node.");
  unsigned PWSz =
      getFullVectorNumberOfElements(*TTI, VL.front()->getType(), VL.size());
  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);
  constexpr TTI::TargetCostKind CostKind = TTI::TCK_RecipThroughput;
  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);
  for (auto [I, V] : enumerate(VL)) {
    // No need to shuffle duplicates for constants.
    if ((ForPoisonSrc && isConstant(V)) || isa<UndefValue>(V))
      continue;

    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), ConstantShuffleMask);
  }

  // 2. Insert unique non-constants.
  if (!DemandedElements.isZero())
    Cost += getScalarizationOverhead(
        *TTI, 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 (Value *V : E->Scalars) {
      auto *I = dyn_cast<Instruction>(V);
      if (!I)
        continue;
      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 (Value *V : E->Scalars) {
      auto *I = dyn_cast<Instruction>(V);
      if (!I)
        continue;
      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 (Value *V : E->Scalars) {
      auto *I = dyn_cast<Instruction>(V);
      if (!I || 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(E->Scalars,
                 [&](Value *V) {
                   if (!isa<Instruction>(V) ||
                       (E->hasCopyableElements() && E->isCopyableElement(V)))
                     return false;
                   return !areAllOperandsNonInsts(V);
                 }) ||
          none_of(E->Scalars, [&](Value *V) {
            if (!isa<Instruction>(V) ||
                (E->hasCopyableElements() && E->isCopyableElement(V)))
              return false;
            return MustGather.contains(V);
          }))))
      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);
  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 &&
       (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);
  }

  /// 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] : VLMask) {
        if (I == PoisonMaskElem)
          continue;
        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) {
    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) {
    return R.gather(VL, Root, ScalarTy,
                    [&](Value *V1, Value *V2, ArrayRef<int> Mask) {
                      return createShuffle(V1, V2, Mask);
                    });
  }
  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 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(*TTI, VecTy, ScalarTy, GatheredScalars.size());
  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 (auto [Idx, I] : enumerate(ExtractMask)) {
        if (I == PoisonMaskElem)
          continue;
        if (ArrayRef<TreeEntry *> TEs = getTreeEntries(
                cast<ExtractElementInst>(StoredGS[Idx])->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(
                *TTI, 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(E->Scalars,
                [this](Value *V) {
                  return isa<LoadInst>(V) && isVectorized(V);
                })) ||
        (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);
    }
    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;
      }
      if (GatherShuffles.size() == 1 &&
          *GatherShuffles.front() == TTI::SK_PermuteSingleSrc &&
          (Entries.front().front()->isSame(E->Scalars) ||
           E->isSame(Entries.front().front()->Scalars))) {
        // 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 ((E->isSame(FrontTE->Scalars) &&
             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(*TTI, 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.
              constexpr TTI::TargetCostKind CostKind = TTI::TCK_RecipThroughput;
              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), NewMask, CostKind);
              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), NewMask,
                                           CostKind);
              }
              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);
    Value *BV = ShuffleBuilder.gather(GatheredScalars, ReuseMask.size());
    ShuffleBuilder.add(BV, ReuseMask);
    Res = ShuffleBuilder.finalize(E->ReuseShuffleIndices, SubVectors,
                                  SubVectorsMask);
  } 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;
  for (Value *V : VL)
    if (isa<Instruction>(V))
      Insts.push_back(V);
  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);
  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::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 (Value *Scalar : Scalars) {
      auto *I = dyn_cast<Instruction>(Scalar);
      if (!I)
        continue;
      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 : Scalars) {
        if (!E->isCopyableElement(Scalar))
          continue;
        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);
    }
    // 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(Scalars, [](Value *Scalar) {
          auto *SI = dyn_cast<Instruction>(Scalar);
          if (!SI || 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 (Value *Op : SI->operands()) {
          const auto *CI = dyn_cast<ConstantInt>(Op);
          if (!CI || 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(SI->operands(), [](Value *Op) {
            const auto *CI = dyn_cast<ConstantInt>(Op);
            return CI && 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);
    if (auto *ICmp = dyn_cast<ICmpInst>(I); ICmp && It == MinBWs.end())
      ICmp->setSameSign(/*B=*/false);
    return I;
  };
  switch (ShuffleOrOp) {
    case Instruction::PHI: {
      assert((E->ReorderIndices.empty() || !E->ReuseShuffleIndices.empty() ||
              E != VectorizableTree.front().get() || 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);
      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;
          do {
            std::optional<unsigned> InsertIdx = getElementIndex(Ins);
            if (!InsertIdx)
              break;
            if (InsertMask[*InsertIdx] == PoisonMaskElem)
              InsertMask[*InsertIdx] = *InsertIdx;
            if (!Ins->hasOneUse())
              break;
            Ins =
                dyn_cast_or_null<Instruction>(Ins->getUniqueUndroppableUser());
          } while (Ins);
          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::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();
      Value *V = Builder.CreateCmp(P0, L, R);
      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);

      Value *LHS = vectorizeOperand(E, 0);
      Value *RHS = vectorizeOperand(E, 1);
      if (ShuffleOrOp == Instruction::And && It != MinBWs.end()) {
        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));
      }

      Value *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 {
        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
                     ? 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);
      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");

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

        // Create shuffle to take alternate operations from the vector.
        // Also, gather up main and alt scalar ops to propagate IR flags to
        // each vector operation.
        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);

        PropagateIRFlags(V0, E->getOpcode(), OpScalars);
        PropagateIRFlags(V1, E->getAltOpcode(), AltScalars);

        if (auto *VecTy = dyn_cast<FixedVectorType>(ScalarTy)) {
          assert(SLPReVec && "FixedVectorType is not expected.");
          transformScalarShuffleIndiciesToVector(VecTy->getNumElements(), Mask);
        }
        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::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) {
  for (Instruction &I : *BB) {
    if (isa<PHINode>(&I) || I.isTerminator())
      continue;
    // A vector-producing instruction (vector load, binop, shuffle, etc.) has a
    // vector result type.
    if (getValueType(&I)->isVectorTy())
      return true;
  }
  return false;
}

void BoUpSLP::captureRuntimeCheckBodySnapshot() {
  RTOrigBodyOrder.clear();
  if (!TryRuntimeAliasChecks || !RTChecks.BB)
    return;
  BasicBlock *BB = RTChecks.BB;
  for (Instruction &I : *BB)
    if (!isa<PHINode>(&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;
  // Versioning duplicates the block body; only straight-line code outside any
  // loop is handled for now, to avoid LoopInfo and region updates.
  if (LI->getLoopFor(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;
  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 : *BB) {
    if (isa<PHINode>(&I) || I.isTerminator())
      continue;
    for (Value *Op : I.operands()) {
      auto *OpI = dyn_cast<Instruction>(Op);
      if (!OpI)
        continue;
      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.
  if (any_of(Bases, [&](const Value *Base) {
        const auto *I = dyn_cast<Instruction>(Base);
        return I && (I->getParent() == BB || !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 : *BB) {
    if (!I.mayReadOrWriteMemory())
      continue;
    // 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());
    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);
    }
  }
  // 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).
  for (const auto &[Base, Off] : OffBounds) {
    const SCEV *BaseSC = SE->getPtrToAddrExpr(SE->getSCEV(Base));
    RTChecks.Bounds.try_emplace(Base, SE->getAddExpr(BaseSC, Off.first),
                                SE->getAddExpr(BaseSC, Off.second));
  }
  // Every involved base must contribute at least one bounded access, and its
  // bounds must be expandable at the guard (so the checks only reference values
  // available in the header).
  SCEVExpander Exp(*SE, "slp.rtcheck");
  // The guard is emitted after the header PHIs, so validate expandability at
  // the first non-PHI: only values available in the header (PHIs, arguments,
  // values defined before the block) dominate that point.
  Instruction *GuardPt = &*BB->getFirstNonPHIIt();
  if (any_of(Bases, [&](const Value *Base) {
        auto *It = RTChecks.Bounds.find(Base);
        return It == RTChecks.Bounds.end() ||
               !Exp.isSafeToExpandAt(It->second.first, GuardPt) ||
               !Exp.isSafeToExpandAt(It->second.second, GuardPt);
      }))
    return false;

  // No SSA value defined in the body may escape the versioned region: that
  // would require a merge PHI in the continuation block, which is not yet
  // supported. A use by the terminator counts as an escape because the
  // terminator is moved into the continuation block.
  for (Instruction &I : *BB) {
    if (isa<PHINode>(&I) || I.isTerminator())
      continue;
    if (any_of(I.users(), [&](User *U) {
          auto *UI = dyn_cast<Instruction>(U);
          return !UI || UI->getParent() != BB || 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.
  constexpr TTI::TargetCostKind CostKind = TTI::TCK_RecipThroughput;
  InstructionCost ScalarCost = 0;
  for (Instruction &I : *BB) {
    if (isa<PHINode>(&I) || I.isTerminator())
      continue;
    ScalarCost += TTI->getInstructionCost(&I, CostKind);
  }
  InstructionCost CheckCost = getRuntimeChecksCost();
  if (!ScalarCost.isValid() || !CheckCost.isValid())
    return false;
  if (CheckCost * 100 >
      ScalarCost * SLPRuntimeAliasChecksMaxScalarCostPercent.getValue())
    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);
  constexpr TTI::TargetCostKind Kind = TTI::TCK_RecipThroughput;
  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, Kind) *
          (2 * NumBases);
  // Two integer compares and one logical and per checked pair.
  InstructionCost CmpCost = TTI->getCmpSelInstrCost(
      Instruction::ICmp, IntTy, I1Ty, CmpInst::ICMP_ULT, Kind);
  InstructionCost AndCost =
      TTI->getArithmeticInstrCost(Instruction::And, I1Ty, Kind);
  Cost += (CmpCost * 2 + AndCost) * NumPairs;
  // Or-reduction of the per-pair conflicts.
  if (NumPairs > 1)
    Cost += TTI->getArithmeticInstrCost(Instruction::Or, I1Ty, Kind) *
            (NumPairs - 1);
  // The guard branch.
  Cost += TTI->getCFInstrCost(Instruction::CondBr, Kind);
  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);

  // 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 body (everything but PHIs and the terminator) into the vector
  // block in the scheduled order.
  for (Instruction &I : make_early_inc_range(*BB)) {
    if (isa<PHINode>(&I) || I.isTerminator())
      continue;
    I.removeFromParent();
    I.insertInto(VecBB, VecBB->end());
  }

  // Emit the runtime alias check before the still-present terminator, so the
  // SCEV bounds are expanded at a valid insertion point.
  IRBuilder<> ChkBuilder(Term);
  ChkBuilder.SetCurrentDebugLocation(Term->getDebugLoc());
  SCEVExpander Exp(*SE, "slp.rtcheck");
  Value *Cond = emitRuntimeAliasCheck(ChkBuilder, Exp);

  // 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. Only annotate profiled functions, to avoid injecting profile
  // data into functions that have none.
  if (!ProfcheckDisableMetadataFixes && Fn->getEntryCount())
    setBranchWeights(*Guard, {1, 127}, /*IsExpected=*/false);

  // The continuation block is the new predecessor of the original successors.
  for (BasicBlock *Succ : successors(Term))
    Succ->replacePhiUsesWith(BB, Tail);

  // 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}};
    for (BasicBlock *Succ : successors(Term)) {
      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();
  }

  // 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<std::tuple<WeakTrackingVH, unsigned, bool, bool>>
        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::CombinedVectorize &&
         (TE->CombinedOp == TreeEntry::ReducedBitcast ||
          TE->CombinedOp == TreeEntry::ReducedBitcastBSwap ||
          ((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 : VectorizableTree) {
    if (DeletedNodes.contains(TE.get()))
      continue;
    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 gathered loads first to emit better code for the users of those
  // gathered loads.
  for (const std::unique_ptr<TreeEntry> &TE : VectorizableTree) {
    if (DeletedNodes.contains(TE.get()))
      continue;
    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(VectorizableTree[0].get());
  // 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) &&
                        any_of(UseEntries, [&, TTI = TTI](TreeEntry *UseEntry) {
                          return (UseEntry->State == TreeEntry::Vectorize ||
                                  UseEntry->State ==
                                      TreeEntry::StridedVectorize ||
                                  UseEntry->State ==
                                      TreeEntry::ExpandVectorize ||
                                  UseEntry->State ==
                                      TreeEntry::CompressVectorize) &&
                                 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.");
        Scalar->replaceAllUsesWith(NewInst);
      }
      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::ReducedCmpBitcast) {
      // Skip constant node
      if (!Entry->hasState()) {
        assert(allConstant(Entry->Scalars) && "Expected constants only.");
        continue;
      }
      for (Value *Scalar : Entry->Scalars) {
        auto *I = dyn_cast<Instruction>(Scalar);

        if (!I || 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);
    }
  }

  // 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 = VectorizableTree.front()->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 (Value *Op : I->operand_values())
        if (auto *OI = dyn_cast<Instruction>(Op))
          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>(VectorizableTree[0]->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 &&
          !(VectorizableTree.front()->isGather() && IE->UserTreeIndex &&
            (ValueToGatherNodes.lookup(I).contains(
                 VectorizableTree.front().get()) ||
             (IE->UserTreeIndex.UserTE == VectorizableTree.front().get() &&
              IE->UserTreeIndex.EdgeIdx == UINT_MAX))) &&
          !(VectorizableTree.front()->State == TreeEntry::SplitVectorize &&
            IE->UserTreeIndex &&
            is_contained(VectorizableTree.front()->Scalars, I)) &&
          !(GatheredLoadsEntriesFirst.has_value() &&
            IE->Idx >= *GatheredLoadsEntriesFirst &&
            VectorizableTree.front()->isGather() &&
            is_contained(VectorizableTree.front()->Scalars, I)) &&
          !(!VectorizableTree.front()->isGather() &&
            VectorizableTree.front()->isCopyableElement(I)))
        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()));
    }
  }
  // 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 = *VectorizableTree.front();
  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 : GatherShuffleExtractSeq) {
    if (isDeleted(I))
      continue;

    // 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(I->operands(), [L](Value *V) {
          auto *OpI = dyn_cast<Instruction>(V);
          return OpI && 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)) {
      assert(DT->isReachableFromEntry(N));
      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 = [TTI = TTI](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(*TTI, SI1->getType(),
                              SI1->getType()->getElementType()) ==
               ::getNumberOfParts(
                   *TTI,
                   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 : VL) {
    if (S.isNonSchedulable(V))
      continue;
    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(VL, [&](Value *V) {
        auto *I = dyn_cast<Instruction>(V);
        if (!I || !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 (Value *Op : cast<Instruction>(V)->operands()) {
            auto *I = dyn_cast<Instruction>(Op);
            if (!I)
              continue;
            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(VL, [&](Value *V) {
        auto *I = dyn_cast<Instruction>(V);
        if (!I || (HasCopyables && S.isCopyableElement(V)))
          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(V);
            });
      }))
    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 (Value *V : VL) {
      auto *I = dyn_cast<Instruction>(V);
      if (!I || (HasCopyables && S.isCopyableElement(V)))
        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 : VL) {
      if (!S.isCopyableElement(V))
        continue;
      if (any_of(EI.UserTE->Scalars, [&](Value *PV) {
            auto *I = dyn_cast<Instruction>(PV);
            return I && EI.UserTE->isExpandedBinOp(I) && I->getOperand(0) == V;
          }))
        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.
    for (ScheduleData *SD : RecalcCopyableOperandDeps) {
      if (!isInSchedulingRegion(*SD))
        continue;
      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) {
      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();
        });
      });
      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 : VL) {
    if (S.isNonSchedulable(V))
      continue;
    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 : VL) {
    if (S.isNonSchedulable(V))
      continue;
    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()) {
    for (ScheduleEntity *BD : Bundle.getBundle()) {
      // Copyable data scheduling is just removed.
      if (isa<ScheduleCopyableData>(BD))
        continue;
      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);
      }
    }
    ScheduledBundlesList.pop_back();
    SmallVector<ScheduleData *> ControlDependentMembers;
    for (Value *V : VL) {
      if (S.isNonSchedulable(V))
        continue;
      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)) {
        // Remove the copyable data from the scheduling region and restore
        // previous mappings.
        auto KV = std::make_pair(EI, I);
        assert(ScheduleCopyableDataMap.contains(KV) &&
               "no ScheduleCopyableData for copyable element");
        ScheduleCopyableData *SD =
            ScheduleCopyableDataMapByInst.find(I)->getSecond().pop_back_val();
        ScheduleCopyableDataMapByUsers[I].remove(SD);
        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);
              break;
            }
            ScheduleCopyableDataMapByInstUser
                [std::make_pair(std::make_pair(In, EI.EdgeIdx), I)]
                    .pop_back();
            It = find(make_range(std::next(It), Op.end()), I);
          } while (It != Op.end());
          EdgeInfo UserEI = EI.UserTE->UserTreeIndex;
          if (ScheduleCopyableData *UserCD = getScheduleCopyableData(UserEI, I))
            ScheduleCopyableDataMapByUsers[I].insert(UserCD);
        }
        if (ScheduleCopyableDataMapByUsers[I].empty())
          ScheduleCopyableDataMapByUsers.erase(I);
        ScheduleCopyableDataMap.erase(KV);
        // Need to recalculate dependencies for the actual schedule data.
        if (ScheduleData *OpSD = getScheduleData(I);
            OpSD && OpSD->hasValidDependencies()) {
          OpSD->clearDirectDependencies();
          if (RegionHasStackSave ||
              !isGuaranteedToTransferExecutionToSuccessor(OpSD->getInst()))
            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);
              }
            }
          }
        }
        continue;
      }
      ScheduledBundles.find(I)->getSecond().pop_back();
    }
    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 : Bundles) {
      if (Bundle->hasValidDependencies() || !Visited.insert(Bundle).second)
        continue;
      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");

  // 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 (ScheduleEntity *SE : Bundle->getBundle())
            if (auto *SD = dyn_cast<ScheduleData>(SE))
              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)) {
      [[maybe_unused]] ArrayRef<TreeEntry *> SDTEs = getTreeEntries(I);
      assert((isVectorLikeInstWithConstOps(SD->getInst()) || SDTEs.empty() ||
              SDTEs.front()->doesNotNeedToSchedule() ||
              doesNotNeedToBeScheduled(I)) &&
             "scheduler and vectorizer bundle mismatch");
      SD->setSchedulingPriority(Idx++);
      if (!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 (Value *V : Bundle->getTreeEntry()->Scalars) {
          auto *I = dyn_cast<Instruction>(V);
          if (!I)
            continue;
          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));

  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 = [&, TTI = TTI]() {
    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 (Value *V : E.Scalars) {
        auto *EE = dyn_cast<ExtractElementInst>(V);
        if (!EE)
          continue;
        UniqueBases.insert(EE->getVectorOperand());
      }
      const unsigned VF = E.Scalars.size();
      Type *OrigScalarTy = E.Scalars.front()->getType();
      if (UniqueBases.size() <= 2 ||
          ::getNumberOfParts(*TTI, getWidenedType(OrigScalarTy, VF),
                             OrigScalarTy) >=
              ::getNumberOfParts(
                  *TTI,
                  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);

  // We can demote certain binary operations if we can demote both of their
  // operands.
  case Instruction::Add:
  case Instruction::Sub:
  case Instruction::Mul:
  case Instruction::And:
  case Instruction::Or:
  case Instruction::Xor: {
    return TryProcessInstruction(
        BitWidth, {getOperandEntry(&E, 0), getOperandEntry(&E, 1)});
  }
  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(E.Scalars, [&](Value *V) {
        if (isa<PoisonValue>(V))
          return true;
        if (E.isCopyableElement(V))
          return true;
        auto *I = cast<Instruction>(V);
        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) {
        auto *I = cast<Instruction>(V);
        if (ID == Intrinsic::umin || ID == Intrinsic::umax) {
          APInt Mask = APInt::getBitsSetFrom(OrigBitWidth, BitWidth);
          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);
        unsigned Op0SignBits =
            ComputeNumSignBits(I->getOperand(0), *DL, AC, nullptr, DT);
        unsigned Op1SignBits =
            ComputeNumSignBits(I->getOperand(1), *DL, AC, nullptr, DT);
        return SignBits <= Op0SignBits &&
               ((SignBits != Op0SignBits &&
                 !isKnownNonNegative(I->getOperand(0), SimplifyQuery(*DL))) ||
                MaskedValueIsZero(I->getOperand(0), Mask,
                                  SimplifyQuery(*DL))) &&
               SignBits <= Op1SignBits &&
               ((SignBits != Op1SignBits &&
                 !isKnownNonNegative(I->getOperand(1), SimplifyQuery(*DL))) ||
                MaskedValueIsZero(I->getOperand(1), Mask, SimplifyQuery(*DL)));
      });
    };
    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);
      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() {
  // We only attempt to truncate integer expressions.
  bool IsStoreOrInsertElt =
      VectorizableTree.front()->hasState() &&
      (VectorizableTree.front()->getOpcode() == Instruction::Store ||
       VectorizableTree.front()->getOpcode() == Instruction::InsertElement ||
       VectorizableTree.front()->getOpcode() == Instruction::InsertValue);
  if ((IsStoreOrInsertElt || UserIgnoreList) &&
      ExtraBitWidthNodes.size() <= 1 &&
      (!CastMaxMinBWSizes || CastMaxMinBWSizes->second == 0 ||
       CastMaxMinBWSizes->first / CastMaxMinBWSizes->second <= 2))
    return;

  unsigned NodeIdx = 0;
  if (IsStoreOrInsertElt && !VectorizableTree.front()->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;
  }

  // Analyzed the reduction already and not profitable - exit.
  if (AnalyzedMinBWVals.contains(VectorizableTree[NodeIdx]->Scalars.front()))
    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;

    if (any_of(E.Scalars,
               [&](Value *V) { return AnalyzedMinBWVals.contains(V); }))
      return 0u;

    unsigned NumParts =
        ::getNumberOfParts(*TTI, 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 : E.Scalars) {
      if (isa<PoisonValue>(Root))
        continue;
      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(
                *TTI,
                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>(VectorizableTree.front()->Scalars.front()->getType())) {
    // Convert vector_reduce_add(ZExt(<n x i1>)) to ZExtOrTrunc(ctpop(bitcast <n
    // x i1> to in)).
    if (all_of(*UserIgnoreList,
               [](Value *V) {
                 return isa<PoisonValue>(V) ||
                        cast<Instruction>(V)->getOpcode() == Instruction::Add;
               }) &&
        VectorizableTree.front()->State == TreeEntry::Vectorize &&
        VectorizableTree.front()->getOpcode() == Instruction::ZExt &&
        cast<CastInst>(VectorizableTree.front()->getMainOp())->getSrcTy() ==
            Builder.getInt1Ty()) {
      ReductionBitWidth = 1;
    } else {
      for (Value *V : *UserIgnoreList) {
        if (isa<PoisonValue>(V))
          continue;
        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(
                VectorizableTree.front()->Scalars.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(
              VectorizableTree[NodeIdx]->UserTreeIndex.UserTE->Scalars,
              [&](Value *V) {
                auto *IC = dyn_cast<ICmpInst>(V);
                return IC && (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)
        AnalyzedMinBWVals.insert_range(TreeRoot);
      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();

  // Scan the blocks in the function in post order.
  for (auto *BB : post_order(&F.getEntryBlock())) {
    if (BB->isEHPad() || isa_and_nonnull<UnreachableInst>(BB->getTerminator()))
      continue;

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

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

  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. it is inside a loop).
  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) ||
      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()) ||
                         isAllowedNonPowerOf2VF(ValOps.size());
    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;
    }
  }
  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();
  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)) {
    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);
  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;
  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;
        }
      }
      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) {
        // Mark the vectorized stores so that we don't vectorize them
        // again.
        VectorizedStores.insert_range(Slice);
        AnyProfitableGraph = RepeatChanged = Changed = true;
        // If we vectorized initial block, no need to try to vectorize
        // it again.
        markRangeVectorized(SliceStartIdx, VF, FirstUnvecStore, MaxSliceEnd);
        SliceStartIdx += VF;
        ++NumStoreChains;
        if (Stride > 1)
          ++NumStridedStoreChains;
        NumVectorizedStores += VF;
        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] : enumerate(Stores)) {
    if (R.isDeleted(SI))
      continue;
    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());
  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()))
        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()))
        continue;
      if (GEP->getType()->isVectorTy())
        continue;
      GEPs[GEP->getPointerOperand()].push_back(GEP);
    }
  }
}

bool SLPVectorizerPass::tryToVectorizeList(ArrayRef<Value *> VL, BoUpSLP &R,
                                           bool MaxVFOnly,
                                           bool LimitToRegisterVF) {
  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)) {
      // 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], /*LookThroughCmp=*/true);
  unsigned Sz = R.getVectorElementSize(I0);
  unsigned MinVF = R.getMinVF(Sz);
  unsigned MaxVF = std::max<unsigned>(
      getFloorFullVectorNumberOfElements(*TTI, ScalarTy, VL.size()), MinVF);
  MaxVF = std::min(R.getMaximumVF(Sz, S.getOpcode()), MaxVF);
  // Standalone poor-throughput seeds only need one register worth of lanes.
  if (LimitToRegisterVF && 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)) {
    // 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 (getNumberOfParts(*TTI, VecTy, ScalarTy) == VF)
      continue;
    for (unsigned I = NextInst; I < MaxInst; ++I) {
      unsigned ActualVF = std::min(MaxInst - I, VF);

      if (!hasFullVectorsOrPowerOf2(*TTI, ScalarTy, ActualVF))
        continue;

      if (MaxVFOnly && ActualVF < MaxVF)
        break;
      if ((VF > MinVF && ActualVF < VF) || (VF == MinVF && ActualVF < 2))
        break;

      SmallVector<Value *> Ops(ActualVF, nullptr);
      unsigned Idx = 0;
      for (Value *V : VL.drop_front(I)) {
        // Check that a previous iteration of this loop did not delete the
        // Value.
        if (auto *Inst = dyn_cast<Instruction>(V);
            !Inst || !R.isDeleted(Inst)) {
          Ops[Idx] = V;
          ++Idx;
          if (Idx == ActualVF)
            break;
        }
      }
      // Not enough vectorizable instructions - exit.
      if (Idx != ActualVF)
        break;

      LLVM_DEBUG(dbgs() << "SLP: Analyzing " << ActualVF << " operations "
                        << "\n");

      R.buildTree(Ops);
      if (R.isTreeTinyAndNotFullyVectorizable())
        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;
      }
    }
  }

  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;
  /// Maps reduced value to the corresponding reduction operation.
  SmallDenseMap<Value *, SmallVector<Instruction *>, 16> ReducedValsToOps;
  WeakTrackingVH ReductionRoot;
  /// 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 and
  /// signedness. The last bool is true, if the value was reduced in-tree.
  SmallVector<std::tuple<WeakTrackingVH, unsigned, bool, bool>>
      VectorValuesAndScales;

  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;

    if (I->isAssociative())
      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::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 : 2;
  }

  /// Checks if the instruction is in basic block \p BB.
  /// For a cmp+sel min/max reduction check that both ops are in \p BB.
  static bool hasSameParent(Instruction *I, BasicBlock *BB) {
    if (isCmpSelMinMax(I) || isBoolLogicOp(I)) {
      auto *Sel = cast<SelectInst>(I);
      auto *Cmp = dyn_cast<Instruction>(Sel->getCondition());
      return Sel->getParent() == BB && Cmp && Cmp->getParent() == BB;
    }
    return I->getParent() == BB;
  }

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

  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();
    RdxKind = getRdxKind(Root);
    // Currently, only ordered fadd reductions are supported.
    if (RdxKind != RecurKind::FAdd)
      return false;
    if (isVectorizable(RdxKind, Root) != ReductionOrdering::Ordered)
      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) || 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;
    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);
      auto *ChainInst = dyn_cast<Instruction>(ChainVal);
      if (!ChainInst || getRdxKind(ChainInst) != RdxKind ||
          !hasRequiredNumberOfUses(/*IsCmpSelMinMax=*/false, ChainInst)) {
        ReducedVals.back().push_back(ChainVal);
        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();
      return false;
    }
    std::reverse(ReducedVals.back().begin(), ReducedVals.back().end());
    return true;
  }

  /// Try to find a reduction tree.
  bool matchAssociativeReduction(BoUpSLP &R, Instruction *Root,
                                 ScalarEvolution &SE, DominatorTree &DT,
                                 const DataLayout &DL,
                                 const TargetTransformInfo &TTI,
                                 const TargetLibraryInfo &TLI) {
    RdxKind = HorizontalReduction::getRdxKind(Root);
    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) || 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);
    SmallVector<std::pair<Instruction *, unsigned>> Worklist(
        1, std::make_pair(Root, 0));
    SmallPtrSet<Value *, 8> Operands;
    SmallVector<std::pair<Instruction *, unsigned>> PossibleOrderedReductionOps;
    // 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<Instruction *> &ReductionOps,
                             unsigned Level) {
      for (int I : reverse(seq<int>(getFirstOperandIndex(TreeN),
                                    getNumberOfOperands(TreeN)))) {
        Value *EdgeVal = getRdxOperand(TreeN, I);
        ReducedValsToOps[EdgeVal].push_back(TreeN);
        auto *EdgeInst = dyn_cast<Instruction>(EdgeVal);
        // 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 ||
                            getRdxKind(EdgeInst) != RdxKind ||
                            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>))) {
          PossibleReducedVals.push_back(EdgeVal);
          if (EdgeInst && !isCmpSelMinMax(EdgeInst))
            Operands.insert_range(EdgeInst->operands());
          continue;
        }
        if (CurrentRK == ReductionOrdering::Ordered)
          RK = ReductionOrdering::Ordered;
        ReductionOps.push_back(EdgeInst);
      }
    };
    // 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;
    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)) {
              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;
    SmallPtrSet<Instruction *, 16> Visited;
    while (!Worklist.empty()) {
      auto [TreeN, Level] = Worklist.pop_back_val();
      if (!Visited.insert(TreeN).second)
        continue;
      SmallVector<Value *> PossibleRedVals;
      SmallVector<Instruction *> PossibleReductionOps;
      CheckOperands(TreeN, PossibleRedVals, PossibleReductionOps, Level);
      addReductionOps(TreeN);
      ReducedValsCandidates.append(PossibleRedVals.begin(),
                                   PossibleRedVals.end());
      for (Instruction *I : reverse(PossibleReductionOps))
        Worklist.emplace_back(I, I->getParent() == BB ? 0 : Level + 1);
      // 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;
        for (const auto &P : PossibleOrderedReductionOps)
          Ops.insert(P.first);
        erase_if(ReducedValsCandidates, [&](Value *V) {
          auto *I = dyn_cast<Instruction>(V);
          return I && Ops.contains(I);
        });
        Worklist.append(PossibleOrderedReductionOps.begin(),
                        PossibleOrderedReductionOps.end());
        PossibleOrderedReductionOps.clear();
      }
    }
    // Too many integer reduced values candidates for the ordered reductions
    // after adjustements - try to switch to unordered reductions instead.
    constexpr unsigned ReducedValsLimit = 1024;
    if (ReducedValsCandidates.size() > ReducedValsLimit && AdjustedToOrdered &&
        ReducedValsCandidates.front()->getType()->isIntOrIntVectorTy())
      return false;
    // Add reduction values. The values are sorted for better vectorization
    // results.
    for (Value *V : ReducedValsCandidates) {
      if (RK == ReductionOrdering::Ordered && !isa<Instruction>(V))
        continue;
      size_t Key, Idx;
      std::tie(Key, Idx) = generateKeySubkey(V, &TLI, GenerateLoadsSubkey,
                                             /*AllowAlternate=*/false);
      ++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.
    stable_sort(ReducedVals, [](ArrayRef<Value *> P1, ArrayRef<Value *> P2) {
      return P1.size() > P2.size();
    });
    return true;
  }

  /// Attempt to vectorize the tree found by matchAssociativeReduction.
  Value *tryToReduce(BoUpSLP &V, const DataLayout &DL, TargetTransformInfo *TTI,
                     const TargetLibraryInfo &TLI, AssumptionCache *AC,
                     DominatorTree &DT) {
    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));

    // 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 : RdxOps) {
        if (!RdxOp)
          continue;
        IgnoreList.insert(RdxOp);
      }
    // Intersect the fast-math-flags from all reduction operations.
    FastMathFlags RdxFMF;
    RdxFMF.set();
    for (Value *U : IgnoreList)
      if (auto *FPMO = dyn_cast<FPMathOperator>(U))
        RdxFMF &= FPMO->getFastMathFlags();
    // 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));

    // 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;
    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) {
      // 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 (!TwoGroupsOfSameSmallSize) {
        SmallVector<Value *> Ops;
        if (!LocalReducedVals.empty())
          Ops = LocalReducedVals.back();
        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.back().swap(Ops);
          States.back() = 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.back().swap(Ops);
            States.back() = OpS;
            continue;
          }
        }
      }
      LocalReducedVals.emplace_back().append(RV.begin(), RV.end());
      States.push_back(getSameOpcode(RV, TLI));
    }
    ReducedVals.swap(LocalReducedVals);
    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);
      }
      bool ShuffledExtracts = false;
      // Try to handle shuffled extractelements.
      if (S && S.getOpcode() == Instruction::ExtractElement &&
          !S.isAltShuffle() && I + 1 < E) {
        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;
        }
      }

      // 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);
        }
        VectorizedTree = GetNewVectorizedTree(VectorizedTree, Res);
        continue;
      }

      unsigned NumReducedVals = Candidates.size();
      if (NumReducedVals < ReductionLimit &&
          (NumReducedVals < 2 || !isSplat(Candidates)))
        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);
          Value *RedVal =
              emitScaleForReusedOps(Candidates.front(), Builder, Cnt);
          VectorizedTree = GetNewVectorizedTree(VectorizedTree, RedVal);
          VectorizedVals.try_emplace(OrigV, Cnt);
          ExternallyUsedValues.insert(OrigV);
          continue;
        }
      }

      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 NumParts, NumRegs;
        Type *ScalarTy = Candidates.front()->getType();
        ReduxWidth =
            getFloorFullVectorNumberOfElements(TTI, ScalarTy, ReduxWidth);
        VectorType *Tp = cast<VectorType>(getWidenedType(ScalarTy, ReduxWidth));
        NumParts = ::getNumberOfParts(TTI, Tp, ScalarTy);
        NumRegs =
            TTI.getNumberOfRegisters(TTI.getRegisterClassForType(true, Tp));
        while (NumParts > NumRegs) {
          assert(ReduxWidth > 0 && "ReduxWidth is unexpectedly 0.");
          ReduxWidth = bit_floor(ReduxWidth - 1);
          VectorType *Tp =
              cast<VectorType>(getWidenedType(ScalarTy, ReduxWidth));
          NumParts = ::getNumberOfParts(TTI, Tp, ScalarTy);
          NumRegs =
              TTI.getNumberOfRegisters(TTI.getRegisterClassForType(true, Tp));
        }
        if (NumParts > NumRegs / 2)
          ReduxWidth = bit_floor(ReduxWidth);
        return ReduxWidth;
      };
      if (!isAllowedNonPowerOf2VF(ReduxWidth))
        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;
      while (Pos < NumReducedVals - ReduxWidth + 1 &&
             ReduxWidth >= ReductionLimit) {
        // 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(VL, [&V](Value *RedVal) {
              auto *RedValI = dyn_cast<Instruction>(RedVal);
              return RedValI && V.isDeleted(RedValI);
            }))
          break;
        if (RK == ReductionOrdering::Ordered)
          V.buildTree(VL);
        else
          V.buildTree(VL, IgnoreList);
        if (V.isTreeTinyAndNotFullyVectorizable(RK ==
                                                ReductionOrdering::Unordered)) {
          constexpr unsigned CandidatesLimit = 64;
          if (!AdjustReducedVals(RK == ReductionOrdering::Ordered &&
                                 Candidates.size() >= CandidatesLimit))
            V.analyzedReductionVals(VL);
          continue;
        }
        V.reorderTopToBottom();
        // No need to reorder the root node at all for reassociative reduction.
        V.reorderBottomToTop(/*IgnoreReorder=*/RdxFMF.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 (Value *V : ReducedVals[Cnt])
            if (isa<Instruction>(V))
              LocalExternallyUsedValues.insert(TrackedVals[V]);
        }
        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);

        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;
          Value *RdxVal = Candidates[Cnt];
          if (auto It = TrackedVals.find(RdxVal); It != TrackedVals.end())
            RdxVal = It->second;
          if (!Visited.insert(RdxVal).second)
            continue;
          // Check if the scalar was vectorized as part of the vectorization
          // tree but not the top node.
          if (!VLScalars.contains(RdxVal) && V.isVectorized(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;
        if (RK == ReductionOrdering::Ordered || V.isReducedBitcastRoot() ||
            V.isReducedCmpBitcastRoot())
          ReductionCost = 0;
        else
          ReductionCost =
              getReductionCost(TTI, VL, SameValuesCounter, IsCmpSelMinMax,
                               RdxFMF, V, DT, DL, TLI);
        // 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);
        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()) {
            V.analyzedReductionVals(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);
                   VF >= ReductionLimit;
                   VF = getFloorFullVectorNumberOfElements(
                       *TTI, VL.front()->getType(), VF - 1)) {
                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);

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

        Type *ScalarTy = VL.front()->getType();
        Type *VecTy = VectorizedRoot->getType();
        Type *RedScalarTy = VecTy->getScalarType();
        VectorValuesAndScales.emplace_back(
            VectorizedRoot,
            OptReusedScalars && SameScaleFactor
                ? SameValuesCounter.front().second
                : 1,
            RedScalarTy != ScalarTy->getScalarType()
                ? V.isSignedMinBitwidthRootNode()
                : true,
            V.isReducedBitcastRoot() || V.isReducedCmpBitcastRoot());

        // 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;
      }
      if (OptReusedScalars && !AnyVectorized) {
        for (const std::pair<Value *, unsigned> &P : SameValuesCounter) {
          Value *RdxVal = TrackedVals.at(P.first);
          Value *RedVal = emitScaleForReusedOps(RdxVal, Builder, P.second);
          VectorizedTree = GetNewVectorizedTree(VectorizedTree, RedVal);
          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)
      return VectorizedTree;

    if (!VectorValuesAndScales.empty())
      VectorizedTree = GetNewVectorizedTree(
          VectorizedTree,
          emitReduction(Builder, *TTI, ReductionRoot->getType()));

    if (!VectorizedTree) {
      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(Ops, [&](Value *Op) {
                     auto *OpI = dyn_cast<Instruction>(Op);
                     return OpI && isBoolLogicOp(OpI) &&
                            getRdxOperand(OpI, 1) == RedOp2;
                   });
                 }))) {
              NeedFreeze = false;
            } else {
              std::swap(LHS, RHS);
              return;
            }
          }
          if (NeedFreeze)
            LHS = Builder.CreateFreeze(LHS);
        };
    // 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;
        // 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;
    ExtraReductions.emplace_back(cast<Instruction>(ReductionRoot),
                                 VectorizedTree);
    SmallPtrSet<Value *, 8> Visited;
    for (ArrayRef<Value *> Candidates : ReducedVals) {
      for (Value *RdxVal : Candidates) {
        if (!Visited.insert(RdxVal).second)
          continue;
        unsigned NumOps = VectorizedVals.lookup(RdxVal);
        for (Instruction *RedOp :
             ArrayRef(ReducedValsToOps.at(RdxVal)).drop_back(NumOps))
          ExtraReductions.emplace_back(RedOp, RdxVal);
      }
    }
    // Iterate through all not-vectorized reduction values/extra arguments.
    bool InitStep = true;
    while (ExtraReductions.size() > 1) {
      SmallVector<std::pair<Instruction *, Value *>> NewReds =
          FinalGen(ExtraReductions, InitStep);
      ExtraReductions.swap(NewReds);
      InitStep = false;
    }
    VectorizedTree = ExtraReductions.front().second;

    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 : RdxOps) {
        if (!Ignore)
          continue;
#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");

    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 (Instruction *Op : ReducedValsToOps.at(RdxVal))
        if (auto *FPMO = dyn_cast<FPMathOperator>(Op))
          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);
      Type *Tp = getWidenedType(ScalarTy, ReduxWidth);
      unsigned NumParts = ::getNumberOfParts(TTI, 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 = ::getNumberOfParts(TTI, 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(VL, [&V](Value *RedVal) {
            auto *RedValI = dyn_cast<Instruction>(RedVal);
            return RedValI && 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 ReductionCost =
          getReductionCost(TTI, VL, EmptySameValuesCounter,
                           /*IsCmpSelMinMax=*/false, RdxFMF, V, DT, DL, TLI);
      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;
    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, 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 : RdxOps) {
        if (!Ignore)
          continue;
#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,
                        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, 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;
  }

  /// Calculate the cost of a reduction.
  InstructionCost getReductionCost(
      TargetTransformInfo *TTI, ArrayRef<Value *> ReducedVals,
      const SmallMapVector<Value *, unsigned, 16> SameValuesCounter,
      bool IsCmpSelMinMax, FastMathFlags FMF, const BoUpSLP &R,
      DominatorTree &DT, const DataLayout &DL, const TargetLibraryInfo &TLI) {
    TTI::TargetCostKind CostKind = TTI::TCK_RecipThroughput;
    Type *ScalarTy = ReducedVals.front()->getType();
    unsigned ReduxWidth = ReducedVals.size();
    FixedVectorType *VectorTy = R.getReductionType();
    InstructionCost VectorCost = 0, ScalarCost;
    // 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())
        if (getRdxKind(U) == RdxKind)
          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 (auto [Idx, RdxVal] : enumerate(ReducedVals)) {
            if (!isa<Instruction>(RdxVal))
              continue;
            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);
              if (hasRequiredNumberOfUses(IsCmpSelMinMax, RdxOp)) {
                if (RdxKind == RecurKind::FAdd) {
                  InstructionCost FMACost = canConvertToFMA(
                      RdxOp, getSameOpcode(RdxOp, TLI), DT, DL, *TTI, TLI);
                  if (FMACost.isValid()) {
                    LLVM_DEBUG(dbgs() << "FMA cost: " << FMACost << "\n");
                    if (auto *I = dyn_cast<Instruction>(RdxVal)) {
                      // Also, exclude scalar fmul cost.
                      InstructionCost FMulCost =
                          TTI->getInstructionCost(I, 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);
      if (!AllConsts) {
        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 (RType == RedTy) {
              VectorCost = TTI->getArithmeticReductionCost(RdxOpcode, VectorTy,
                                                           FMF, CostKind);
            } else {
              VectorCost = TTI->getExtendedReductionCost(
                  RdxOpcode, !IsSigned, RedTy,
                  cast<VectorType>(getWidenedType(RType, ReduxWidth)), FMF,
                  CostKind);
            }
          }
        } 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) {
              if (!RdxVal->hasOneUse()) {
                Ops.clear();
                break;
              }
              if (auto *FPCI = dyn_cast<FPMathOperator>(RdxVal))
                FMF &= FPCI->getFastMathFlags();
              Ops.push_back(RdxVal->user_back());
            }
            if (!Ops.empty()) {
              FMACost = canConvertToFMA(Ops, getSameOpcode(Ops, TLI), DT, DL,
                                        *TTI, TLI);
              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);
          }
        }
      }
      ScalarCost = EvaluateScalarCost([&](Instruction *RdxOp) {
        return TTI->getArithmeticInstrCost(
            RdxOpcode, ScalarTy, CostKind,
            TTI::getOperandInfo(RdxOp->getOperand(0)),
            TTI::getOperandInfo(RdxOp->getOperand(1)), {}, RdxOp);
      });
      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);
        } 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);
          }
        }
      }
      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.
  Value *emitReduction(IRBuilderBase &Builder, const TargetTransformInfo &TTI,
                       Type *DestTy) {
    Value *ReducedSubTree = nullptr;
    // Creates reduction and combines with the previous reduction.
    auto CreateSingleOp = [&](Value *Vec, unsigned Scale, bool IsSigned,
                              bool ReducedInTree) {
      Value *Rdx = createSingleOp(Builder, TTI, Vec, Scale, IsSigned, DestTy,
                                  ReducedInTree);
      if (ReducedSubTree)
        ReducedSubTree = createOp(Builder, RdxKind, ReducedSubTree, Rdx,
                                  "op.rdx", ReductionOps);
      else
        ReducedSubTree = Rdx;
    };
    if (VectorValuesAndScales.size() == 1) {
      const auto &[Vec, Scale, IsSigned, ReducedInTree] =
          VectorValuesAndScales.front();
      CreateSingleOp(Vec, Scale, IsSigned, ReducedInTree);
      return ReducedSubTree;
    }
    // Scales Vec using given Cnt scale factor and then performs vector combine
    // with previous value of VecOp.
    Value *VecRes = nullptr;
    bool VecResSignedness = false;
    auto CreateVecOp = [&](Value *Vec, unsigned Cnt, bool IsSigned,
                           bool ReducedInTree) {
      if (ReducedInTree) {
        CreateSingleOp(Vec, Cnt, IsSigned, ReducedInTree);
        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;
      } 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);
        }
        // extract + op + insert
        Value *Op = VecRes;
        if (VecResVF != VecVF)
          Op = createExtractVector(Builder, VecRes, VecVF, /*Index=*/0);
        Op = createOp(Builder, RdxKind, Op, Vec, "rdx.op", ReductionOps);
        if (VecResVF != VecVF)
          Op = createInsertVector(Builder, VecRes, Op, /*Index=*/0);
        VecRes = Op;
      }
    };
    for (auto [Vec, Scale, IsSigned, ReducedInTree] : VectorValuesAndScales)
      CreateVecOp(Vec, Scale, IsSigned, ReducedInTree);
    CreateSingleOp(VecRes, /*Scale=*/1, /*IsSigned=*/false,
                   /*ReducedInTree=*/false);

    return ReducedSubTree;
  }

  /// 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, 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");

    auto *FTy = cast<FixedVectorType>(VectorizedValue->getType());
    if (!Start && FTy->getScalarType() == Builder.getInt1Ty() &&
        RdxKind == RecurKind::Add &&
        DestTy->getScalarType() != FTy->getScalarType()) {
      // Convert 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;
      return Builder.CreateUnaryIntrinsic(Intrinsic::ctpop, V);
    }
    ++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");
      return Builder.CreateFMul(VectorizedValue, Scale);
    }
    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]);
        Vals.push_back(ConstantInt::get(V->getType(), Cnt, /*IsSigned=*/false));
      }
      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;
}

static bool matchRdxBop(Instruction *I, Value *&V0, Value *&V1) {
  if (match(I, m_BinOp(m_Value(V0), m_Value(V1))))
    return true;
  if (match(I, m_FMaxNum(m_Value(V0), m_Value(V1))))
    return true;
  if (match(I, m_FMinNum(m_Value(V0), m_Value(V1))))
    return true;
  if (match(I, m_FMaximum(m_Value(V0), m_Value(V1))))
    return true;
  if (match(I, m_FMinimum(m_Value(V0), m_Value(V1))))
    return true;
  if (match(I, m_Intrinsic<Intrinsic::smax>(m_Value(V0), m_Value(V1))))
    return true;
  if (match(I, m_Intrinsic<Intrinsic::smin>(m_Value(V0), m_Value(V1))))
    return true;
  if (match(I, m_Intrinsic<Intrinsic::umax>(m_Value(V0), m_Value(V1))))
    return true;
  if (match(I, m_Intrinsic<Intrinsic::umin>(m_Value(V0), m_Value(V1))))
    return true;
  return false;
}

/// We could have an initial reduction that is not an add.
///  r *= v1 + v2 + v3 + v4
/// In such a case start looking for a tree rooted in the first '+'.
/// \Returns the new root if found, which may be nullptr if not an instruction.
static Instruction *tryGetSecondaryReductionRoot(PHINode *Phi,
                                                 Instruction *Root) {
  assert((isa<BinaryOperator>(Root) || isa<SelectInst>(Root) ||
          isa<IntrinsicInst>(Root)) &&
         "Expected binop, select, or intrinsic for reduction matching");
  Value *LHS =
      Root->getOperand(HorizontalReduction::getFirstOperandIndex(Root));
  Value *RHS =
      Root->getOperand(HorizontalReduction::getFirstOperandIndex(Root) + 1);
  if (LHS == Phi)
    return dyn_cast<Instruction>(RHS);
  if (RHS == Phi)
    return dyn_cast<Instruction>(LHS);
  return nullptr;
}

/// \p Returns the first operand of \p I that does not match \p Phi. If
/// operand is not an instruction it returns nullptr.
static Instruction *getNonPhiOperand(Instruction *I, PHINode *Phi) {
  Value *Op0 = nullptr;
  Value *Op1 = nullptr;
  if (!matchRdxBop(I, Op0, Op1))
    return nullptr;
  return dyn_cast<Instruction>(Op0 == Phi ? Op1 : Op0);
}

/// \Returns true if \p I is a candidate instruction for reduction vectorization.
static bool isReductionCandidate(Instruction *I) {
  bool IsSelect = match(I, m_Select(m_Value(), m_Value(), m_Value()));
  Value *B0 = nullptr, *B1 = nullptr;
  bool IsBinop = matchRdxBop(I, B0, B1);
  return IsBinop || IsSelect;
}

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) -> 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))
      if (Value *Red = HorRdx.tryToReduce(R, *DL, TTI, *TLI, AC, *DT)) {
        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;
    if (Value *VectorizedV = TryToReduce(Inst)) {
      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 other
  // instructions in the block have been processed.
  if (!AllowFMACandidates &&
      (I->getOpcode() == Instruction::FAdd ||
       I->getOpcode() == Instruction::FSub) &&
      canConvertToFMA(I, getSameOpcode(I, *TLI), *DT, *DL, *TTI, *TLI)
          .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;
    Type *Ty = Inst->getType();
    if (!isValidElementType(Ty) || 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()));
    constexpr TTI::TargetCostKind CostKind = TTI::TCK_RecipThroughput;
    InstructionCost ScalarCost =
        TTI.getScalarizationOverhead(
            VecTy, APInt::getAllOnes(getNumElements(VecTy)), /*Insert=*/false,
            /*Extract=*/true, CostKind) +
        TTI.getInstructionCost(Inst, CostKind);
    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();
      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) != 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()) &&
      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))) {
      ++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()) &&
         isValidElementType(V2->getType()) &&
         "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 : CmpInsts) {
    if (R.isDeleted(I))
      continue;
    for (Value *Op : I->operands())
      if (auto *RootOp = dyn_cast<Instruction>(Op)) {
        Changed |=
            vectorizeRootInstruction(nullptr, RootOp, BB, R, FMACandidates);
        if (R.isDeleted(I))
          break;
      }
  }
  // Try to vectorize operands as vector bundles.
  for (CmpInst *I : CmpInsts) {
    if (R.isDeleted(I))
      continue;
    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, /*LookThroughCmp=*/true)))
      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(CI->args(), [](const Value *Arg) {
            return !isa<Instruction>(Arg) || 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 : Insts) {
    if (R.isDeleted(I))
      continue;
    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()))
            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 : Insts) {
    if (R.isDeleted(I))
      continue;
    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()) && !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) {
        return tryToVectorizeList(Candidates, R, MaxVFOnly);
      },
      /*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;
  for (auto *I : reverse(Instructions)) {
    // pass1 - try to match and vectorize a buildvector sequence for MaxVF only.
    if (R.isDeleted(I) || isa<CmpInst>(I))
      continue;
    if (auto *LastInsertValue = dyn_cast<InsertValueInst>(I)) {
      OpsChanged |=
          vectorizeInsertValueInst(LastInsertValue, BB, R, /*MaxVFOnly=*/true);
    } else if (auto *LastInsertElem = dyn_cast<InsertElementInst>(I)) {
      OpsChanged |=
          vectorizeInsertElementInst(LastInsertElem, BB, R, /*MaxVFOnly=*/true);
    }
    // pass2 - try to vectorize reductions only
    if (R.isDeleted(I))
      continue;
    OpsChanged |= vectorizeHorReduction(nullptr, I, BB, R, PostponedInsts);
    if (R.isDeleted(I) || isa<CmpInst>(I))
      continue;
    // pass3 - try to match and vectorize a buildvector sequence.
    if (auto *LastInsertValue = dyn_cast<InsertValueInst>(I)) {
      OpsChanged |=
          vectorizeInsertValueInst(LastInsertValue, BB, R, /*MaxVFOnly=*/false);
    } else if (auto *LastInsertElem = dyn_cast<InsertElementInst>(I)) {
      OpsChanged |= vectorizeInsertElementInst(LastInsertElem, BB, R,
                                               /*MaxVFOnly=*/false);
    }
  }
  // Now try to vectorize postponed instructions.
  OpsChanged |= tryToVectorize(PostponedInsts, R, FMACandidates);

  Instructions.clear();
  return OpsChanged;
}

bool SLPVectorizerPass::vectorizeChainsInBlock(BasicBlock *BB, BoUpSLP &R) {
  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()) &&
           isValidElementType(V2->getType()) &&
           "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()))
        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> FMACandidates;
  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;
      }
    }

    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))
      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());
      if (!::isValidElementType(ScalarTy)) {
        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, ScalarTy, VecTy,
              APInt::getAllOnes(PostProcessStores.size()),
              /*Insert=*/false, /*Extract=*/true, TTI::TCK_RecipThroughput,
              /*ForPoisonSrc=*/true, {}, TTI::VectorInstrContext::Store);
          TryVectorize = ExtractsCost <= PostProcessStores.size() + 1;
        }
      }
    }
    if (TryVectorize) {
      Changed |= vectorizeNonVectorizableInsts(reverse(PostProcessStores), BB,
                                               R, FMACandidates);
    }
  }
  SmallSetVector<Instruction *, 8> Empty;
  for (Instruction *I : FMACandidates) {
    if (R.isDeleted(I))
      continue;
    Changed |= tryToVectorize(I, R, Empty, /*AllowFMACandidates=*/true);
  }
  assert(Empty.empty() &&
         "No new FMA candidates expected during AllowFMACandidates retry.");

  if (PoorThroughputSeeds.size() >= 2) {
    SmallVector<Value *> Seeds;
    SmallDenseMap<Value *, SeedGroupKey> SeedKeys;
    for (Instruction *I : PoorThroughputSeeds) {
      if (R.isDeleted(I) || !isValidElementType(getValueType(I)))
        continue;
      // Skip seeds a user already resolved: a deleted user was folded into
      // some other vector by an earlier pass, and I's role there is already
      // decided, so retrying I here is almost always a wasted attempt.
      if (any_of(I->users(), [&](User *U) {
            auto *UI = dyn_cast<Instruction>(U);
            return UI && (R.isDeleted(UI) || R.isVectorized(UI));
          }))
        continue;
      SeedKeys.try_emplace(I, getSeedGroupKey(I, *TLI));
      Seeds.push_back(I);
    }
    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();
      const SeedGroupKey &K1 = SeedKeys.at(V1);
      const SeedGroupKey &K2 = SeedKeys.at(V2);
      if (K1 != K2)
        return K1.less(K2);
      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() &&
             SeedKeys.at(VL.back()) == SeedKeys.at(V);
    };
    if (Seeds.size() >= 2)
      Changed |= tryToVectorizeSequence<Value>(
          Seeds, SeedSorter, AreCompatibleSeeds,
          [this, &R](ArrayRef<Value *> Candidates, bool MaxVFOnly) {
            return tryToVectorizeList(Candidates, R, MaxVFOnly,
                                      /*LimitToRegisterVF=*/true);
          },
          /*MaxVFOnly=*/false, R);
  }

  return Changed;
}

bool SLPVectorizerPass::vectorizeGEPIndices(BasicBlock *BB, BoUpSLP &R) {
  auto Changed = false;
  for (auto &Entry : GEPs) {
    // If the getelementptr list has fewer than two elements, there's nothing
    // to do.
    if (Entry.second.size() < 2)
      continue;

    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;
  for (auto &Pair : Stores) {
    if (Pair.second.size() < 2)
      continue;

    LLVM_DEBUG(dbgs() << "SLP: Analyzing a store chain of length "
                      << Pair.second.size() << ".\n");

    if (!isValidElementType(Pair.second.front()->getValueOperand()->getType()))
      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;
}
