//===- SelectionDAG.cpp - Implement the SelectionDAG data structures ------===//
//
// 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 implements the SelectionDAG class.
//
//===----------------------------------------------------------------------===//

#include "llvm/CodeGen/SelectionDAG.h"
#include "SDNodeDbgValue.h"
#include "llvm/ADT/APFloat.h"
#include "llvm/ADT/APInt.h"
#include "llvm/ADT/APSInt.h"
#include "llvm/ADT/ArrayRef.h"
#include "llvm/ADT/BitVector.h"
#include "llvm/ADT/DenseSet.h"
#include "llvm/ADT/FoldingSet.h"
#include "llvm/ADT/STLExtras.h"
#include "llvm/ADT/SmallPtrSet.h"
#include "llvm/ADT/SmallVector.h"
#include "llvm/ADT/Twine.h"
#include "llvm/Analysis/AliasAnalysis.h"
#include "llvm/Analysis/MemoryLocation.h"
#include "llvm/Analysis/TargetLibraryInfo.h"
#include "llvm/Analysis/ValueTracking.h"
#include "llvm/Analysis/VectorUtils.h"
#include "llvm/BinaryFormat/Dwarf.h"
#include "llvm/CodeGen/Analysis.h"
#include "llvm/CodeGen/FunctionLoweringInfo.h"
#include "llvm/CodeGen/ISDOpcodes.h"
#include "llvm/CodeGen/MachineBasicBlock.h"
#include "llvm/CodeGen/MachineConstantPool.h"
#include "llvm/CodeGen/MachineFrameInfo.h"
#include "llvm/CodeGen/MachineFunction.h"
#include "llvm/CodeGen/MachineMemOperand.h"
#include "llvm/CodeGen/RuntimeLibcallUtil.h"
#include "llvm/CodeGen/SDPatternMatch.h"
#include "llvm/CodeGen/SelectionDAGAddressAnalysis.h"
#include "llvm/CodeGen/SelectionDAGNodes.h"
#include "llvm/CodeGen/SelectionDAGTargetInfo.h"
#include "llvm/CodeGen/TargetFrameLowering.h"
#include "llvm/CodeGen/TargetLowering.h"
#include "llvm/CodeGen/TargetRegisterInfo.h"
#include "llvm/CodeGen/TargetSubtargetInfo.h"
#include "llvm/CodeGen/ValueTypes.h"
#include "llvm/CodeGenTypes/MachineValueType.h"
#include "llvm/IR/Constant.h"
#include "llvm/IR/Constants.h"
#include "llvm/IR/DataLayout.h"
#include "llvm/IR/DebugInfoMetadata.h"
#include "llvm/IR/DebugLoc.h"
#include "llvm/IR/DerivedTypes.h"
#include "llvm/IR/Function.h"
#include "llvm/IR/GlobalValue.h"
#include "llvm/IR/Metadata.h"
#include "llvm/IR/Type.h"
#include "llvm/Support/Casting.h"
#include "llvm/Support/CodeGen.h"
#include "llvm/Support/Compiler.h"
#include "llvm/Support/Debug.h"
#include "llvm/Support/ErrorHandling.h"
#include "llvm/Support/KnownBits.h"
#include "llvm/Support/MathExtras.h"
#include "llvm/Support/raw_ostream.h"
#include "llvm/Target/TargetMachine.h"
#include "llvm/Target/TargetOptions.h"
#include "llvm/TargetParser/Triple.h"
#include "llvm/Transforms/Utils/SizeOpts.h"
#include <algorithm>
#include <cassert>
#include <cstdint>
#include <cstdlib>
#include <limits>
#include <optional>
#include <set>
#include <string>
#include <utility>
#include <vector>

using namespace llvm;
using namespace llvm::SDPatternMatch;

/// makeVTList - Return an instance of the SDVTList struct initialized with the
/// specified members.
static SDVTList makeVTList(const EVT *VTs, unsigned NumVTs) {
  SDVTList Res = {VTs, NumVTs};
  return Res;
}

// Default null implementations of the callbacks.
void SelectionDAG::DAGUpdateListener::NodeDeleted(SDNode*, SDNode*) {}
void SelectionDAG::DAGUpdateListener::NodeUpdated(SDNode*) {}
void SelectionDAG::DAGUpdateListener::NodeInserted(SDNode *) {}

void SelectionDAG::DAGNodeDeletedListener::anchor() {}
void SelectionDAG::DAGNodeInsertedListener::anchor() {}

#define DEBUG_TYPE "selectiondag"

static cl::opt<bool> EnableMemCpyDAGOpt("enable-memcpy-dag-opt",
       cl::Hidden, cl::init(true),
       cl::desc("Gang up loads and stores generated by inlining of memcpy"));

static cl::opt<int> MaxLdStGlue("ldstmemcpy-glue-max",
       cl::desc("Number limit for gluing ld/st of memcpy."),
       cl::Hidden, cl::init(0));

static cl::opt<unsigned>
    MaxSteps("has-predecessor-max-steps", cl::Hidden, cl::init(8192),
             cl::desc("DAG combiner limit number of steps when searching DAG "
                      "for predecessor nodes"));

static void NewSDValueDbgMsg(SDValue V, StringRef Msg, SelectionDAG *G) {
  LLVM_DEBUG(dbgs() << Msg; V.getNode()->dump(G););
}

unsigned SelectionDAG::getHasPredecessorMaxSteps() { return MaxSteps; }

//===----------------------------------------------------------------------===//
//                              ConstantFPSDNode Class
//===----------------------------------------------------------------------===//

/// isExactlyValue - We don't rely on operator== working on double values, as
/// it returns true for things that are clearly not equal, like -0.0 and 0.0.
/// As such, this method can be used to do an exact bit-for-bit comparison of
/// two floating point values.
bool ConstantFPSDNode::isExactlyValue(const APFloat& V) const {
  return getValueAPF().bitwiseIsEqual(V);
}

bool ConstantFPSDNode::isValueValidForType(EVT VT,
                                           const APFloat& Val) {
  assert(VT.isFloatingPoint() && "Can only convert between FP types");

  // convert modifies in place, so make a copy.
  APFloat Val2 = APFloat(Val);
  bool losesInfo;
  (void)Val2.convert(VT.getFltSemantics(), APFloat::rmNearestTiesToEven,
                     &losesInfo);
  return !losesInfo;
}

//===----------------------------------------------------------------------===//
//                              ISD Namespace
//===----------------------------------------------------------------------===//

bool ISD::isConstantSplatVector(const SDNode *N, APInt &SplatVal) {
  if (N->getOpcode() == ISD::SPLAT_VECTOR) {
    if (auto OptAPInt = N->getOperand(0)->bitcastToAPInt()) {
      unsigned EltSize =
          N->getValueType(0).getVectorElementType().getSizeInBits();
      SplatVal = OptAPInt->trunc(EltSize);
      return true;
    }
  }

  auto *BV = dyn_cast<BuildVectorSDNode>(N);
  if (!BV)
    return false;

  APInt SplatUndef;
  unsigned SplatBitSize;
  bool HasUndefs;
  unsigned EltSize = N->getValueType(0).getVectorElementType().getSizeInBits();
  // Endianness does not matter here. We are checking for a splat given the
  // element size of the vector, and if we find such a splat for little endian
  // layout, then that should be valid also for big endian (as the full vector
  // size is known to be a multiple of the element size).
  const bool IsBigEndian = false;
  return BV->isConstantSplat(SplatVal, SplatUndef, SplatBitSize, HasUndefs,
                             EltSize, IsBigEndian) &&
         EltSize == SplatBitSize;
}

// FIXME: AllOnes and AllZeros duplicate a lot of code. Could these be
// specializations of the more general isConstantSplatVector()?

bool ISD::isConstantSplatVectorAllOnes(const SDNode *N, bool BuildVectorOnly) {
  // Look through a bit convert.
  while (N->getOpcode() == ISD::BITCAST)
    N = N->getOperand(0).getNode();

  if (!BuildVectorOnly && N->getOpcode() == ISD::SPLAT_VECTOR) {
    APInt SplatVal;
    return isConstantSplatVector(N, SplatVal) && SplatVal.isAllOnes();
  }

  if (N->getOpcode() != ISD::BUILD_VECTOR) return false;

  unsigned i = 0, e = N->getNumOperands();

  // Skip over all of the undef values.
  while (i != e && N->getOperand(i).isUndef())
    ++i;

  // Do not accept an all-undef vector.
  if (i == e) return false;

  // Do not accept build_vectors that aren't all constants or which have non-~0
  // elements. We have to be a bit careful here, as the type of the constant
  // may not be the same as the type of the vector elements due to type
  // legalization (the elements are promoted to a legal type for the target and
  // a vector of a type may be legal when the base element type is not).
  // We only want to check enough bits to cover the vector elements, because
  // we care if the resultant vector is all ones, not whether the individual
  // constants are.
  SDValue NotZero = N->getOperand(i);
  if (auto OptAPInt = NotZero->bitcastToAPInt()) {
    unsigned EltSize = N->getValueType(0).getScalarSizeInBits();
    if (OptAPInt->countr_one() < EltSize)
      return false;
  } else
    return false;

  // Okay, we have at least one ~0 value, check to see if the rest match or are
  // undefs. Even with the above element type twiddling, this should be OK, as
  // the same type legalization should have applied to all the elements.
  for (++i; i != e; ++i)
    if (N->getOperand(i) != NotZero && !N->getOperand(i).isUndef())
      return false;
  return true;
}

bool ISD::isConstantSplatVectorAllZeros(const SDNode *N, bool BuildVectorOnly) {
  // Look through a bit convert.
  while (N->getOpcode() == ISD::BITCAST)
    N = N->getOperand(0).getNode();

  if (!BuildVectorOnly && N->getOpcode() == ISD::SPLAT_VECTOR) {
    APInt SplatVal;
    return isConstantSplatVector(N, SplatVal) && SplatVal.isZero();
  }

  if (N->getOpcode() != ISD::BUILD_VECTOR) return false;

  bool IsAllUndef = true;
  for (const SDValue &Op : N->op_values()) {
    if (Op.isUndef())
      continue;
    IsAllUndef = false;
    // Do not accept build_vectors that aren't all constants or which have non-0
    // elements. We have to be a bit careful here, as the type of the constant
    // may not be the same as the type of the vector elements due to type
    // legalization (the elements are promoted to a legal type for the target
    // and a vector of a type may be legal when the base element type is not).
    // We only want to check enough bits to cover the vector elements, because
    // we care if the resultant vector is all zeros, not whether the individual
    // constants are.
    if (auto OptAPInt = Op->bitcastToAPInt()) {
      unsigned EltSize = N->getValueType(0).getScalarSizeInBits();
      if (OptAPInt->countr_zero() < EltSize)
        return false;
    } else
      return false;
  }

  // Do not accept an all-undef vector.
  if (IsAllUndef)
    return false;
  return true;
}

bool ISD::isBuildVectorAllOnes(const SDNode *N) {
  return isConstantSplatVectorAllOnes(N, /*BuildVectorOnly*/ true);
}

bool ISD::isBuildVectorAllZeros(const SDNode *N) {
  return isConstantSplatVectorAllZeros(N, /*BuildVectorOnly*/ true);
}

bool ISD::isBuildVectorOfConstantSDNodes(const SDNode *N) {
  if (N->getOpcode() != ISD::BUILD_VECTOR)
    return false;

  for (const SDValue &Op : N->op_values()) {
    if (Op.isUndef())
      continue;
    if (!isa<ConstantSDNode>(Op))
      return false;
  }
  return true;
}

bool ISD::isBuildVectorOfConstantFPSDNodes(const SDNode *N) {
  if (N->getOpcode() != ISD::BUILD_VECTOR)
    return false;

  for (const SDValue &Op : N->op_values()) {
    if (Op.isUndef())
      continue;
    if (!isa<ConstantFPSDNode>(Op))
      return false;
  }
  return true;
}

bool ISD::isVectorShrinkable(const SDNode *N, unsigned NewEltSize,
                             bool Signed) {
  assert(N->getValueType(0).isVector() && "Expected a vector!");

  unsigned EltSize = N->getValueType(0).getScalarSizeInBits();
  if (EltSize <= NewEltSize)
    return false;

  if (N->getOpcode() == ISD::ZERO_EXTEND) {
    return (N->getOperand(0).getValueType().getScalarSizeInBits() <=
            NewEltSize) &&
           !Signed;
  }
  if (N->getOpcode() == ISD::SIGN_EXTEND) {
    return (N->getOperand(0).getValueType().getScalarSizeInBits() <=
            NewEltSize) &&
           Signed;
  }
  if (N->getOpcode() != ISD::BUILD_VECTOR)
    return false;

  for (const SDValue &Op : N->op_values()) {
    if (Op.isUndef())
      continue;
    if (!isa<ConstantSDNode>(Op))
      return false;

    APInt C = Op->getAsAPIntVal().trunc(EltSize);
    if (Signed && C.trunc(NewEltSize).sext(EltSize) != C)
      return false;
    if (!Signed && C.trunc(NewEltSize).zext(EltSize) != C)
      return false;
  }

  return true;
}

bool ISD::allOperandsUndef(const SDNode *N) {
  // Return false if the node has no operands.
  // This is "logically inconsistent" with the definition of "all" but
  // is probably the desired behavior.
  if (N->getNumOperands() == 0)
    return false;
  return all_of(N->op_values(), [](SDValue Op) { return Op.isUndef(); });
}

bool ISD::isFreezeUndef(const SDNode *N) {
  return N->getOpcode() == ISD::FREEZE && N->getOperand(0).isUndef();
}

template <typename ConstNodeType>
bool ISD::matchUnaryPredicateImpl(SDValue Op,
                                  std::function<bool(ConstNodeType *)> Match,
                                  bool AllowUndefs, bool AllowTruncation) {
  // FIXME: Add support for scalar UNDEF cases?
  if (auto *C = dyn_cast<ConstNodeType>(Op))
    return Match(C);

  // FIXME: Add support for vector UNDEF cases?
  if (ISD::BUILD_VECTOR != Op.getOpcode() &&
      ISD::SPLAT_VECTOR != Op.getOpcode())
    return false;

  EVT SVT = Op.getValueType().getScalarType();
  for (unsigned i = 0, e = Op.getNumOperands(); i != e; ++i) {
    if (AllowUndefs && Op.getOperand(i).isUndef()) {
      if (!Match(nullptr))
        return false;
      continue;
    }

    auto *Cst = dyn_cast<ConstNodeType>(Op.getOperand(i));
    if (!Cst || (!AllowTruncation && Cst->getValueType(0) != SVT) ||
        !Match(Cst))
      return false;
  }
  return true;
}
// Build used template types.
template bool ISD::matchUnaryPredicateImpl<ConstantSDNode>(
    SDValue, std::function<bool(ConstantSDNode *)>, bool, bool);
template bool ISD::matchUnaryPredicateImpl<ConstantFPSDNode>(
    SDValue, std::function<bool(ConstantFPSDNode *)>, bool, bool);

bool ISD::matchBinaryPredicate(
    SDValue LHS, SDValue RHS,
    std::function<bool(ConstantSDNode *, ConstantSDNode *)> Match,
    bool AllowUndefs, bool AllowTypeMismatch) {
  if (!AllowTypeMismatch && LHS.getValueType() != RHS.getValueType())
    return false;

  // TODO: Add support for scalar UNDEF cases?
  if (auto *LHSCst = dyn_cast<ConstantSDNode>(LHS))
    if (auto *RHSCst = dyn_cast<ConstantSDNode>(RHS))
      return Match(LHSCst, RHSCst);

  // TODO: Add support for vector UNDEF cases?
  if (LHS.getOpcode() != RHS.getOpcode() ||
      (LHS.getOpcode() != ISD::BUILD_VECTOR &&
       LHS.getOpcode() != ISD::SPLAT_VECTOR))
    return false;

  EVT SVT = LHS.getValueType().getScalarType();
  for (unsigned i = 0, e = LHS.getNumOperands(); i != e; ++i) {
    SDValue LHSOp = LHS.getOperand(i);
    SDValue RHSOp = RHS.getOperand(i);
    bool LHSUndef = AllowUndefs && LHSOp.isUndef();
    bool RHSUndef = AllowUndefs && RHSOp.isUndef();
    auto *LHSCst = dyn_cast<ConstantSDNode>(LHSOp);
    auto *RHSCst = dyn_cast<ConstantSDNode>(RHSOp);
    if ((!LHSCst && !LHSUndef) || (!RHSCst && !RHSUndef))
      return false;
    if (!AllowTypeMismatch && (LHSOp.getValueType() != SVT ||
                               LHSOp.getValueType() != RHSOp.getValueType()))
      return false;
    if (!Match(LHSCst, RHSCst))
      return false;
  }
  return true;
}

ISD::NodeType ISD::getInverseMinMaxOpcode(unsigned MinMaxOpc) {
  switch (MinMaxOpc) {
  default:
    llvm_unreachable("unrecognized opcode");
  case ISD::UMIN:
    return ISD::UMAX;
  case ISD::UMAX:
    return ISD::UMIN;
  case ISD::SMIN:
    return ISD::SMAX;
  case ISD::SMAX:
    return ISD::SMIN;
  }
}

ISD::NodeType ISD::getVecReduceBaseOpcode(unsigned VecReduceOpcode) {
  switch (VecReduceOpcode) {
  default:
    llvm_unreachable("Expected VECREDUCE opcode");
  case ISD::VECREDUCE_FADD:
  case ISD::VECREDUCE_SEQ_FADD:
  case ISD::VP_REDUCE_FADD:
  case ISD::VP_REDUCE_SEQ_FADD:
    return ISD::FADD;
  case ISD::VECREDUCE_FMUL:
  case ISD::VECREDUCE_SEQ_FMUL:
  case ISD::VP_REDUCE_FMUL:
  case ISD::VP_REDUCE_SEQ_FMUL:
    return ISD::FMUL;
  case ISD::VECREDUCE_ADD:
  case ISD::VP_REDUCE_ADD:
    return ISD::ADD;
  case ISD::VECREDUCE_MUL:
  case ISD::VP_REDUCE_MUL:
    return ISD::MUL;
  case ISD::VECREDUCE_AND:
  case ISD::VP_REDUCE_AND:
    return ISD::AND;
  case ISD::VECREDUCE_OR:
  case ISD::VP_REDUCE_OR:
    return ISD::OR;
  case ISD::VECREDUCE_XOR:
  case ISD::VP_REDUCE_XOR:
    return ISD::XOR;
  case ISD::VECREDUCE_SMAX:
  case ISD::VP_REDUCE_SMAX:
    return ISD::SMAX;
  case ISD::VECREDUCE_SMIN:
  case ISD::VP_REDUCE_SMIN:
    return ISD::SMIN;
  case ISD::VECREDUCE_UMAX:
  case ISD::VP_REDUCE_UMAX:
    return ISD::UMAX;
  case ISD::VECREDUCE_UMIN:
  case ISD::VP_REDUCE_UMIN:
    return ISD::UMIN;
  case ISD::VECREDUCE_FMAX:
  case ISD::VP_REDUCE_FMAX:
    return ISD::FMAXNUM;
  case ISD::VECREDUCE_FMIN:
  case ISD::VP_REDUCE_FMIN:
    return ISD::FMINNUM;
  case ISD::VECREDUCE_FMAXIMUM:
  case ISD::VP_REDUCE_FMAXIMUM:
    return ISD::FMAXIMUM;
  case ISD::VECREDUCE_FMINIMUM:
  case ISD::VP_REDUCE_FMINIMUM:
    return ISD::FMINIMUM;
  }
}

bool ISD::isVPOpcode(unsigned Opcode) {
  switch (Opcode) {
  default:
    return false;
#define BEGIN_REGISTER_VP_SDNODE(VPSD, ...)                                    \
  case ISD::VPSD:                                                              \
    return true;
#include "llvm/IR/VPIntrinsics.def"
  }
}

bool ISD::isVPBinaryOp(unsigned Opcode) {
  switch (Opcode) {
  default:
    break;
#define BEGIN_REGISTER_VP_SDNODE(VPSD, ...) case ISD::VPSD:
#define VP_PROPERTY_BINARYOP return true;
#define END_REGISTER_VP_SDNODE(VPSD) break;
#include "llvm/IR/VPIntrinsics.def"
  }
  return false;
}

bool ISD::isVPReduction(unsigned Opcode) {
  switch (Opcode) {
  default:
    return false;
  case ISD::VP_REDUCE_ADD:
  case ISD::VP_REDUCE_MUL:
  case ISD::VP_REDUCE_AND:
  case ISD::VP_REDUCE_OR:
  case ISD::VP_REDUCE_XOR:
  case ISD::VP_REDUCE_SMAX:
  case ISD::VP_REDUCE_SMIN:
  case ISD::VP_REDUCE_UMAX:
  case ISD::VP_REDUCE_UMIN:
  case ISD::VP_REDUCE_FMAX:
  case ISD::VP_REDUCE_FMIN:
  case ISD::VP_REDUCE_FMAXIMUM:
  case ISD::VP_REDUCE_FMINIMUM:
  case ISD::VP_REDUCE_FADD:
  case ISD::VP_REDUCE_FMUL:
  case ISD::VP_REDUCE_SEQ_FADD:
  case ISD::VP_REDUCE_SEQ_FMUL:
    return true;
  }
}

/// The operand position of the vector mask.
std::optional<unsigned> ISD::getVPMaskIdx(unsigned Opcode) {
  switch (Opcode) {
  default:
    return std::nullopt;
#define BEGIN_REGISTER_VP_SDNODE(VPSD, LEGALPOS, TDNAME, MASKPOS, ...)         \
  case ISD::VPSD:                                                              \
    return MASKPOS;
#include "llvm/IR/VPIntrinsics.def"
  }
}

/// The operand position of the explicit vector length parameter.
std::optional<unsigned> ISD::getVPExplicitVectorLengthIdx(unsigned Opcode) {
  switch (Opcode) {
  default:
    return std::nullopt;
#define BEGIN_REGISTER_VP_SDNODE(VPSD, LEGALPOS, TDNAME, MASKPOS, EVLPOS)      \
  case ISD::VPSD:                                                              \
    return EVLPOS;
#include "llvm/IR/VPIntrinsics.def"
  }
}

std::optional<unsigned> ISD::getBaseOpcodeForVP(unsigned VPOpcode,
                                                bool hasFPExcept) {
  // FIXME: Return strict opcodes in case of fp exceptions.
  switch (VPOpcode) {
  default:
    return std::nullopt;
#define BEGIN_REGISTER_VP_SDNODE(VPOPC, ...) case ISD::VPOPC:
#define VP_PROPERTY_FUNCTIONAL_SDOPC(SDOPC) return ISD::SDOPC;
#define END_REGISTER_VP_SDNODE(VPOPC) break;
#include "llvm/IR/VPIntrinsics.def"
  }
  return std::nullopt;
}

std::optional<unsigned> ISD::getVPForBaseOpcode(unsigned Opcode) {
  switch (Opcode) {
  default:
    return std::nullopt;
#define BEGIN_REGISTER_VP_SDNODE(VPOPC, ...) break;
#define VP_PROPERTY_FUNCTIONAL_SDOPC(SDOPC) case ISD::SDOPC:
#define END_REGISTER_VP_SDNODE(VPOPC) return ISD::VPOPC;
#include "llvm/IR/VPIntrinsics.def"
  }
}

ISD::NodeType ISD::getExtForLoadExtType(bool IsFP, ISD::LoadExtType ExtType) {
  switch (ExtType) {
  case ISD::EXTLOAD:
    return IsFP ? ISD::FP_EXTEND : ISD::ANY_EXTEND;
  case ISD::SEXTLOAD:
    return ISD::SIGN_EXTEND;
  case ISD::ZEXTLOAD:
    return ISD::ZERO_EXTEND;
  default:
    break;
  }

  llvm_unreachable("Invalid LoadExtType");
}

ISD::CondCode ISD::getSetCCSwappedOperands(ISD::CondCode Operation) {
  // To perform this operation, we just need to swap the L and G bits of the
  // operation.
  unsigned OldL = (Operation >> 2) & 1;
  unsigned OldG = (Operation >> 1) & 1;
  return ISD::CondCode((Operation & ~6) |  // Keep the N, U, E bits
                       (OldL << 1) |       // New G bit
                       (OldG << 2));       // New L bit.
}

static ISD::CondCode getSetCCInverseImpl(ISD::CondCode Op, bool isIntegerLike) {
  unsigned Operation = Op;
  if (isIntegerLike)
    Operation ^= 7;   // Flip L, G, E bits, but not U.
  else
    Operation ^= 15;  // Flip all of the condition bits.

  if (Operation > ISD::SETTRUE2)
    Operation &= ~8;  // Don't let N and U bits get set.

  return ISD::CondCode(Operation);
}

ISD::CondCode ISD::getSetCCInverse(ISD::CondCode Op, EVT Type) {
  return getSetCCInverseImpl(Op, Type.isInteger());
}

ISD::CondCode ISD::GlobalISel::getSetCCInverse(ISD::CondCode Op,
                                               bool isIntegerLike) {
  return getSetCCInverseImpl(Op, isIntegerLike);
}

/// For an integer comparison, return 1 if the comparison is a signed operation
/// and 2 if the result is an unsigned comparison. Return zero if the operation
/// does not depend on the sign of the input (setne and seteq).
static int isSignedOp(ISD::CondCode Opcode) {
  switch (Opcode) {
  default: llvm_unreachable("Illegal integer setcc operation!");
  case ISD::SETEQ:
  case ISD::SETNE: return 0;
  case ISD::SETLT:
  case ISD::SETLE:
  case ISD::SETGT:
  case ISD::SETGE: return 1;
  case ISD::SETULT:
  case ISD::SETULE:
  case ISD::SETUGT:
  case ISD::SETUGE: return 2;
  }
}

ISD::CondCode ISD::getSetCCOrOperation(ISD::CondCode Op1, ISD::CondCode Op2,
                                       EVT Type) {
  bool IsInteger = Type.isInteger();
  if (IsInteger && (isSignedOp(Op1) | isSignedOp(Op2)) == 3)
    // Cannot fold a signed integer setcc with an unsigned integer setcc.
    return ISD::SETCC_INVALID;

  unsigned Op = Op1 | Op2;  // Combine all of the condition bits.

  // If the N and U bits get set, then the resultant comparison DOES suddenly
  // care about orderedness, and it is true when ordered.
  if (Op > ISD::SETTRUE2)
    Op &= ~16;     // Clear the U bit if the N bit is set.

  // Canonicalize illegal integer setcc's.
  if (IsInteger && Op == ISD::SETUNE)  // e.g. SETUGT | SETULT
    Op = ISD::SETNE;

  return ISD::CondCode(Op);
}

ISD::CondCode ISD::getSetCCAndOperation(ISD::CondCode Op1, ISD::CondCode Op2,
                                        EVT Type) {
  bool IsInteger = Type.isInteger();
  if (IsInteger && (isSignedOp(Op1) | isSignedOp(Op2)) == 3)
    // Cannot fold a signed setcc with an unsigned setcc.
    return ISD::SETCC_INVALID;

  // Combine all of the condition bits.
  ISD::CondCode Result = ISD::CondCode(Op1 & Op2);

  // Canonicalize illegal integer setcc's.
  if (IsInteger) {
    switch (Result) {
    default: break;
    case ISD::SETUO : Result = ISD::SETFALSE; break;  // SETUGT & SETULT
    case ISD::SETOEQ:                                 // SETEQ  & SETU[LG]E
    case ISD::SETUEQ: Result = ISD::SETEQ   ; break;  // SETUGE & SETULE
    case ISD::SETOLT: Result = ISD::SETULT  ; break;  // SETULT & SETNE
    case ISD::SETOGT: Result = ISD::SETUGT  ; break;  // SETUGT & SETNE
    }
  }

  return Result;
}

//===----------------------------------------------------------------------===//
//                           SDNode Profile Support
//===----------------------------------------------------------------------===//

/// AddNodeIDOpcode - Add the node opcode to the NodeID data.
static void AddNodeIDOpcode(FoldingSetNodeID &ID, unsigned OpC)  {
  ID.AddInteger(OpC);
}

/// AddNodeIDValueTypes - Value type lists are intern'd so we can represent them
/// solely with their pointer.
static void AddNodeIDValueTypes(FoldingSetNodeID &ID, SDVTList VTList) {
  ID.AddPointer(VTList.VTs);
}

/// AddNodeIDOperands - Various routines for adding operands to the NodeID data.
static void AddNodeIDOperands(FoldingSetNodeID &ID,
                              ArrayRef<SDValue> Ops) {
  for (const auto &Op : Ops) {
    ID.AddPointer(Op.getNode());
    ID.AddInteger(Op.getResNo());
  }
}

/// AddNodeIDOperands - Various routines for adding operands to the NodeID data.
static void AddNodeIDOperands(FoldingSetNodeID &ID,
                              ArrayRef<SDUse> Ops) {
  for (const auto &Op : Ops) {
    ID.AddPointer(Op.getNode());
    ID.AddInteger(Op.getResNo());
  }
}

static void AddNodeIDNode(FoldingSetNodeID &ID, unsigned OpC,
                          SDVTList VTList, ArrayRef<SDValue> OpList) {
  AddNodeIDOpcode(ID, OpC);
  AddNodeIDValueTypes(ID, VTList);
  AddNodeIDOperands(ID, OpList);
}

/// If this is an SDNode with special info, add this info to the NodeID data.
static void AddNodeIDCustom(FoldingSetNodeID &ID, const SDNode *N) {
  switch (N->getOpcode()) {
  case ISD::TargetExternalSymbol:
  case ISD::ExternalSymbol:
  case ISD::MCSymbol:
    llvm_unreachable("Should only be used on nodes with operands");
  default: break;  // Normal nodes don't need extra info.
  case ISD::TargetConstant:
  case ISD::Constant: {
    const ConstantSDNode *C = cast<ConstantSDNode>(N);
    ID.AddPointer(C->getConstantIntValue());
    ID.AddBoolean(C->isOpaque());
    break;
  }
  case ISD::TargetConstantFP:
  case ISD::ConstantFP:
    ID.AddPointer(cast<ConstantFPSDNode>(N)->getConstantFPValue());
    break;
  case ISD::TargetGlobalAddress:
  case ISD::GlobalAddress:
  case ISD::TargetGlobalTLSAddress:
  case ISD::GlobalTLSAddress: {
    const GlobalAddressSDNode *GA = cast<GlobalAddressSDNode>(N);
    ID.AddPointer(GA->getGlobal());
    ID.AddInteger(GA->getOffset());
    ID.AddInteger(GA->getTargetFlags());
    break;
  }
  case ISD::BasicBlock:
    ID.AddPointer(cast<BasicBlockSDNode>(N)->getBasicBlock());
    break;
  case ISD::Register:
    ID.AddInteger(cast<RegisterSDNode>(N)->getReg().id());
    break;
  case ISD::RegisterMask:
    ID.AddPointer(cast<RegisterMaskSDNode>(N)->getRegMask());
    break;
  case ISD::SRCVALUE:
    ID.AddPointer(cast<SrcValueSDNode>(N)->getValue());
    break;
  case ISD::FrameIndex:
  case ISD::TargetFrameIndex:
    ID.AddInteger(cast<FrameIndexSDNode>(N)->getIndex());
    break;
  case ISD::PSEUDO_PROBE:
    ID.AddInteger(cast<PseudoProbeSDNode>(N)->getGuid());
    ID.AddInteger(cast<PseudoProbeSDNode>(N)->getIndex());
    ID.AddInteger(cast<PseudoProbeSDNode>(N)->getAttributes());
    break;
  case ISD::JumpTable:
  case ISD::TargetJumpTable:
    ID.AddInteger(cast<JumpTableSDNode>(N)->getIndex());
    ID.AddInteger(cast<JumpTableSDNode>(N)->getTargetFlags());
    break;
  case ISD::ConstantPool:
  case ISD::TargetConstantPool: {
    const ConstantPoolSDNode *CP = cast<ConstantPoolSDNode>(N);
    ID.AddInteger(CP->getAlign().value());
    ID.AddInteger(CP->getOffset());
    if (CP->isMachineConstantPoolEntry())
      CP->getMachineCPVal()->addSelectionDAGCSEId(ID);
    else
      ID.AddPointer(CP->getConstVal());
    ID.AddInteger(CP->getTargetFlags());
    break;
  }
  case ISD::TargetIndex: {
    const TargetIndexSDNode *TI = cast<TargetIndexSDNode>(N);
    ID.AddInteger(TI->getIndex());
    ID.AddInteger(TI->getOffset());
    ID.AddInteger(TI->getTargetFlags());
    break;
  }
  case ISD::LOAD: {
    const LoadSDNode *LD = cast<LoadSDNode>(N);
    ID.AddInteger(LD->getMemoryVT().getRawBits());
    ID.AddInteger(LD->getRawSubclassData());
    ID.AddInteger(LD->getPointerInfo().getAddrSpace());
    ID.AddInteger(LD->getMemOperand()->getFlags());
    break;
  }
  case ISD::STORE: {
    const StoreSDNode *ST = cast<StoreSDNode>(N);
    ID.AddInteger(ST->getMemoryVT().getRawBits());
    ID.AddInteger(ST->getRawSubclassData());
    ID.AddInteger(ST->getPointerInfo().getAddrSpace());
    ID.AddInteger(ST->getMemOperand()->getFlags());
    break;
  }
  case ISD::VP_LOAD: {
    const VPLoadSDNode *ELD = cast<VPLoadSDNode>(N);
    ID.AddInteger(ELD->getMemoryVT().getRawBits());
    ID.AddInteger(ELD->getRawSubclassData());
    ID.AddInteger(ELD->getPointerInfo().getAddrSpace());
    ID.AddInteger(ELD->getMemOperand()->getFlags());
    break;
  }
  case ISD::VP_STORE: {
    const VPStoreSDNode *EST = cast<VPStoreSDNode>(N);
    ID.AddInteger(EST->getMemoryVT().getRawBits());
    ID.AddInteger(EST->getRawSubclassData());
    ID.AddInteger(EST->getPointerInfo().getAddrSpace());
    ID.AddInteger(EST->getMemOperand()->getFlags());
    break;
  }
  case ISD::EXPERIMENTAL_VP_STRIDED_LOAD: {
    const VPStridedLoadSDNode *SLD = cast<VPStridedLoadSDNode>(N);
    ID.AddInteger(SLD->getMemoryVT().getRawBits());
    ID.AddInteger(SLD->getRawSubclassData());
    ID.AddInteger(SLD->getPointerInfo().getAddrSpace());
    break;
  }
  case ISD::EXPERIMENTAL_VP_STRIDED_STORE: {
    const VPStridedStoreSDNode *SST = cast<VPStridedStoreSDNode>(N);
    ID.AddInteger(SST->getMemoryVT().getRawBits());
    ID.AddInteger(SST->getRawSubclassData());
    ID.AddInteger(SST->getPointerInfo().getAddrSpace());
    break;
  }
  case ISD::VP_GATHER: {
    const VPGatherSDNode *EG = cast<VPGatherSDNode>(N);
    ID.AddInteger(EG->getMemoryVT().getRawBits());
    ID.AddInteger(EG->getRawSubclassData());
    ID.AddInteger(EG->getPointerInfo().getAddrSpace());
    ID.AddInteger(EG->getMemOperand()->getFlags());
    break;
  }
  case ISD::VP_SCATTER: {
    const VPScatterSDNode *ES = cast<VPScatterSDNode>(N);
    ID.AddInteger(ES->getMemoryVT().getRawBits());
    ID.AddInteger(ES->getRawSubclassData());
    ID.AddInteger(ES->getPointerInfo().getAddrSpace());
    ID.AddInteger(ES->getMemOperand()->getFlags());
    break;
  }
  case ISD::MLOAD: {
    const MaskedLoadSDNode *MLD = cast<MaskedLoadSDNode>(N);
    ID.AddInteger(MLD->getMemoryVT().getRawBits());
    ID.AddInteger(MLD->getRawSubclassData());
    ID.AddInteger(MLD->getPointerInfo().getAddrSpace());
    ID.AddInteger(MLD->getMemOperand()->getFlags());
    break;
  }
  case ISD::MSTORE: {
    const MaskedStoreSDNode *MST = cast<MaskedStoreSDNode>(N);
    ID.AddInteger(MST->getMemoryVT().getRawBits());
    ID.AddInteger(MST->getRawSubclassData());
    ID.AddInteger(MST->getPointerInfo().getAddrSpace());
    ID.AddInteger(MST->getMemOperand()->getFlags());
    break;
  }
  case ISD::MGATHER: {
    const MaskedGatherSDNode *MG = cast<MaskedGatherSDNode>(N);
    ID.AddInteger(MG->getMemoryVT().getRawBits());
    ID.AddInteger(MG->getRawSubclassData());
    ID.AddInteger(MG->getPointerInfo().getAddrSpace());
    ID.AddInteger(MG->getMemOperand()->getFlags());
    break;
  }
  case ISD::MSCATTER: {
    const MaskedScatterSDNode *MS = cast<MaskedScatterSDNode>(N);
    ID.AddInteger(MS->getMemoryVT().getRawBits());
    ID.AddInteger(MS->getRawSubclassData());
    ID.AddInteger(MS->getPointerInfo().getAddrSpace());
    ID.AddInteger(MS->getMemOperand()->getFlags());
    break;
  }
  case ISD::ATOMIC_CMP_SWAP:
  case ISD::ATOMIC_CMP_SWAP_WITH_SUCCESS:
  case ISD::ATOMIC_SWAP:
  case ISD::ATOMIC_LOAD_ADD:
  case ISD::ATOMIC_LOAD_SUB:
  case ISD::ATOMIC_LOAD_AND:
  case ISD::ATOMIC_LOAD_CLR:
  case ISD::ATOMIC_LOAD_OR:
  case ISD::ATOMIC_LOAD_XOR:
  case ISD::ATOMIC_LOAD_NAND:
  case ISD::ATOMIC_LOAD_MIN:
  case ISD::ATOMIC_LOAD_MAX:
  case ISD::ATOMIC_LOAD_UMIN:
  case ISD::ATOMIC_LOAD_UMAX:
  case ISD::ATOMIC_LOAD:
  case ISD::ATOMIC_STORE: {
    const AtomicSDNode *AT = cast<AtomicSDNode>(N);
    ID.AddInteger(AT->getMemoryVT().getRawBits());
    ID.AddInteger(AT->getRawSubclassData());
    ID.AddInteger(AT->getPointerInfo().getAddrSpace());
    ID.AddInteger(AT->getMemOperand()->getFlags());
    break;
  }
  case ISD::VECTOR_SHUFFLE: {
    ArrayRef<int> Mask = cast<ShuffleVectorSDNode>(N)->getMask();
    for (int M : Mask)
      ID.AddInteger(M);
    break;
  }
  case ISD::ADDRSPACECAST: {
    const AddrSpaceCastSDNode *ASC = cast<AddrSpaceCastSDNode>(N);
    ID.AddInteger(ASC->getSrcAddressSpace());
    ID.AddInteger(ASC->getDestAddressSpace());
    break;
  }
  case ISD::TargetBlockAddress:
  case ISD::BlockAddress: {
    const BlockAddressSDNode *BA = cast<BlockAddressSDNode>(N);
    ID.AddPointer(BA->getBlockAddress());
    ID.AddInteger(BA->getOffset());
    ID.AddInteger(BA->getTargetFlags());
    break;
  }
  case ISD::AssertAlign:
    ID.AddInteger(cast<AssertAlignSDNode>(N)->getAlign().value());
    break;
  case ISD::PREFETCH:
  case ISD::INTRINSIC_VOID:
  case ISD::INTRINSIC_W_CHAIN:
    // Handled by MemIntrinsicSDNode check after the switch.
    break;
  case ISD::MDNODE_SDNODE:
    ID.AddPointer(cast<MDNodeSDNode>(N)->getMD());
    break;
  } // end switch (N->getOpcode())

  // MemIntrinsic nodes could also have subclass data, address spaces, and flags
  // to check.
  if (auto *MN = dyn_cast<MemIntrinsicSDNode>(N)) {
    ID.AddInteger(MN->getRawSubclassData());
    ID.AddInteger(MN->getPointerInfo().getAddrSpace());
    ID.AddInteger(MN->getMemOperand()->getFlags());
    ID.AddInteger(MN->getMemoryVT().getRawBits());
  }
}

/// AddNodeIDNode - Generic routine for adding a nodes info to the NodeID
/// data.
static void AddNodeIDNode(FoldingSetNodeID &ID, const SDNode *N) {
  AddNodeIDOpcode(ID, N->getOpcode());
  // Add the return value info.
  AddNodeIDValueTypes(ID, N->getVTList());
  // Add the operand info.
  AddNodeIDOperands(ID, N->ops());

  // Handle SDNode leafs with special info.
  AddNodeIDCustom(ID, N);
}

//===----------------------------------------------------------------------===//
//                              SelectionDAG Class
//===----------------------------------------------------------------------===//

/// doNotCSE - Return true if CSE should not be performed for this node.
static bool doNotCSE(SDNode *N) {
  if (N->getValueType(0) == MVT::Glue)
    return true; // Never CSE anything that produces a glue result.

  switch (N->getOpcode()) {
  default: break;
  case ISD::HANDLENODE:
  case ISD::EH_LABEL:
    return true;   // Never CSE these nodes.
  }

  // Check that remaining values produced are not flags.
  for (unsigned i = 1, e = N->getNumValues(); i != e; ++i)
    if (N->getValueType(i) == MVT::Glue)
      return true; // Never CSE anything that produces a glue result.

  return false;
}

/// RemoveDeadNodes - This method deletes all unreachable nodes in the
/// SelectionDAG.
void SelectionDAG::RemoveDeadNodes() {
  // Create a dummy node (which is not added to allnodes), that adds a reference
  // to the root node, preventing it from being deleted.
  HandleSDNode Dummy(getRoot());

  SmallVector<SDNode*, 128> DeadNodes;

  // Add all obviously-dead nodes to the DeadNodes worklist.
  for (SDNode &Node : allnodes())
    if (Node.use_empty())
      DeadNodes.push_back(&Node);

  RemoveDeadNodes(DeadNodes);

  // If the root changed (e.g. it was a dead load, update the root).
  setRoot(Dummy.getValue());
}

/// RemoveDeadNodes - This method deletes the unreachable nodes in the
/// given list, and any nodes that become unreachable as a result.
void SelectionDAG::RemoveDeadNodes(SmallVectorImpl<SDNode *> &DeadNodes) {

  // Process the worklist, deleting the nodes and adding their uses to the
  // worklist.
  while (!DeadNodes.empty()) {
    SDNode *N = DeadNodes.pop_back_val();
    // Skip to next node if we've already managed to delete the node. This could
    // happen if replacing a node causes a node previously added to the node to
    // be deleted.
    if (N->getOpcode() == ISD::DELETED_NODE)
      continue;

    for (DAGUpdateListener *DUL = UpdateListeners; DUL; DUL = DUL->Next)
      DUL->NodeDeleted(N, nullptr);

    // Take the node out of the appropriate CSE map.
    RemoveNodeFromCSEMaps(N);

    // Next, brutally remove the operand list.  This is safe to do, as there are
    // no cycles in the graph.
    for (SDNode::op_iterator I = N->op_begin(), E = N->op_end(); I != E; ) {
      SDUse &Use = *I++;
      SDNode *Operand = Use.getNode();
      Use.set(SDValue());

      // Now that we removed this operand, see if there are no uses of it left.
      if (Operand->use_empty())
        DeadNodes.push_back(Operand);
    }

    DeallocateNode(N);
  }
}

void SelectionDAG::RemoveDeadNode(SDNode *N){
  SmallVector<SDNode*, 16> DeadNodes(1, N);

  // Create a dummy node that adds a reference to the root node, preventing
  // it from being deleted.  (This matters if the root is an operand of the
  // dead node.)
  HandleSDNode Dummy(getRoot());

  RemoveDeadNodes(DeadNodes);
}

void SelectionDAG::DeleteNode(SDNode *N) {
  // First take this out of the appropriate CSE map.
  RemoveNodeFromCSEMaps(N);

  // Finally, remove uses due to operands of this node, remove from the
  // AllNodes list, and delete the node.
  DeleteNodeNotInCSEMaps(N);
}

void SelectionDAG::DeleteNodeNotInCSEMaps(SDNode *N) {
  assert(N->getIterator() != AllNodes.begin() &&
         "Cannot delete the entry node!");
  assert(N->use_empty() && "Cannot delete a node that is not dead!");

  // Drop all of the operands and decrement used node's use counts.
  N->DropOperands();

  DeallocateNode(N);
}

void SDDbgInfo::add(SDDbgValue *V, bool isParameter) {
  assert(!(V->isVariadic() && isParameter));
  if (isParameter)
    ByvalParmDbgValues.push_back(V);
  else
    DbgValues.push_back(V);
  for (const SDNode *Node : V->getSDNodes())
    if (Node)
      DbgValMap[Node].push_back(V);
}

void SDDbgInfo::erase(const SDNode *Node) {
  DbgValMapType::iterator I = DbgValMap.find(Node);
  if (I == DbgValMap.end())
    return;
  for (auto &Val: I->second)
    Val->setIsInvalidated();
  DbgValMap.erase(I);
}

void SelectionDAG::DeallocateNode(SDNode *N) {
  // If we have operands, deallocate them.
  removeOperands(N);

  NodeAllocator.Deallocate(AllNodes.remove(N));

  // Set the opcode to DELETED_NODE to help catch bugs when node
  // memory is reallocated.
  // FIXME: There are places in SDag that have grown a dependency on the opcode
  // value in the released node.
  __asan_unpoison_memory_region(&N->NodeType, sizeof(N->NodeType));
  N->NodeType = ISD::DELETED_NODE;

  // If any of the SDDbgValue nodes refer to this SDNode, invalidate
  // them and forget about that node.
  DbgInfo->erase(N);

  // Invalidate extra info.
  SDEI.erase(N);
}

#ifndef NDEBUG
/// VerifySDNode - Check the given SDNode.  Aborts if it is invalid.
void SelectionDAG::verifyNode(SDNode *N) const {
  switch (N->getOpcode()) {
  default:
    if (N->isTargetOpcode())
      getSelectionDAGInfo().verifyTargetNode(*this, N);
    break;
  case ISD::BUILD_PAIR: {
    EVT VT = N->getValueType(0);
    assert(N->getNumValues() == 1 && "Too many results!");
    assert(!VT.isVector() && (VT.isInteger() || VT.isFloatingPoint()) &&
           "Wrong return type!");
    assert(N->getNumOperands() == 2 && "Wrong number of operands!");
    assert(N->getOperand(0).getValueType() == N->getOperand(1).getValueType() &&
           "Mismatched operand types!");
    assert(N->getOperand(0).getValueType().isInteger() == VT.isInteger() &&
           "Wrong operand type!");
    assert(VT.getSizeInBits() == 2 * N->getOperand(0).getValueSizeInBits() &&
           "Wrong return type size");
    break;
  }
  case ISD::BUILD_VECTOR: {
    assert(N->getNumValues() == 1 && "Too many results!");
    assert(N->getValueType(0).isVector() && "Wrong return type!");
    assert(N->getNumOperands() == N->getValueType(0).getVectorNumElements() &&
           "Wrong number of operands!");
    EVT EltVT = N->getValueType(0).getVectorElementType();
    for (const SDUse &Op : N->ops()) {
      assert((Op.getValueType() == EltVT ||
              (EltVT.isInteger() && Op.getValueType().isInteger() &&
               EltVT.bitsLE(Op.getValueType()))) &&
             "Wrong operand type!");
      assert(Op.getValueType() == N->getOperand(0).getValueType() &&
             "Operands must all have the same type");
    }
    break;
  }
  }
}
#endif // NDEBUG

/// Insert a newly allocated node into the DAG.
///
/// Handles insertion into the all nodes list and CSE map, as well as
/// verification and other common operations when a new node is allocated.
void SelectionDAG::InsertNode(SDNode *N) {
  AllNodes.push_back(N);
#ifndef NDEBUG
  N->PersistentId = NextPersistentId++;
  verifyNode(N);
#endif
  for (DAGUpdateListener *DUL = UpdateListeners; DUL; DUL = DUL->Next)
    DUL->NodeInserted(N);
}

/// RemoveNodeFromCSEMaps - Take the specified node out of the CSE map that
/// correspond to it.  This is useful when we're about to delete or repurpose
/// the node.  We don't want future request for structurally identical nodes
/// to return N anymore.
bool SelectionDAG::RemoveNodeFromCSEMaps(SDNode *N) {
  bool Erased = false;
  switch (N->getOpcode()) {
  case ISD::HANDLENODE: return false;  // noop.
  case ISD::CONDCODE:
    assert(CondCodeNodes[cast<CondCodeSDNode>(N)->get()] &&
           "Cond code doesn't exist!");
    Erased = CondCodeNodes[cast<CondCodeSDNode>(N)->get()] != nullptr;
    CondCodeNodes[cast<CondCodeSDNode>(N)->get()] = nullptr;
    break;
  case ISD::ExternalSymbol:
    Erased = ExternalSymbols.erase(cast<ExternalSymbolSDNode>(N)->getSymbol());
    break;
  case ISD::TargetExternalSymbol: {
    ExternalSymbolSDNode *ESN = cast<ExternalSymbolSDNode>(N);
    Erased = TargetExternalSymbols.erase(std::pair<std::string, unsigned>(
        ESN->getSymbol(), ESN->getTargetFlags()));
    break;
  }
  case ISD::MCSymbol: {
    auto *MCSN = cast<MCSymbolSDNode>(N);
    Erased = MCSymbols.erase(MCSN->getMCSymbol());
    break;
  }
  case ISD::VALUETYPE: {
    EVT VT = cast<VTSDNode>(N)->getVT();
    if (VT.isExtended()) {
      Erased = ExtendedValueTypeNodes.erase(VT);
    } else {
      Erased = ValueTypeNodes[VT.getSimpleVT().SimpleTy] != nullptr;
      ValueTypeNodes[VT.getSimpleVT().SimpleTy] = nullptr;
    }
    break;
  }
  default:
    // Remove it from the CSE Map.
    assert(N->getOpcode() != ISD::DELETED_NODE && "DELETED_NODE in CSEMap!");
    assert(N->getOpcode() != ISD::EntryToken && "EntryToken in CSEMap!");
    Erased = CSEMap.RemoveNode(N);
    break;
  }
#ifndef NDEBUG
  // Verify that the node was actually in one of the CSE maps, unless it has a
  // glue result (which cannot be CSE'd) or is one of the special cases that are
  // not subject to CSE.
  if (!Erased && N->getValueType(N->getNumValues()-1) != MVT::Glue &&
      !N->isMachineOpcode() && !doNotCSE(N)) {
    N->dump(this);
    dbgs() << "\n";
    llvm_unreachable("Node is not in map!");
  }
#endif
  return Erased;
}

/// AddModifiedNodeToCSEMaps - The specified node has been removed from the CSE
/// maps and modified in place. Add it back to the CSE maps, unless an identical
/// node already exists, in which case transfer all its users to the existing
/// node. This transfer can potentially trigger recursive merging.
void
SelectionDAG::AddModifiedNodeToCSEMaps(SDNode *N) {
  // For node types that aren't CSE'd, just act as if no identical node
  // already exists.
  if (!doNotCSE(N)) {
    SDNode *Existing = CSEMap.GetOrInsertNode(N);
    if (Existing != N) {
      // If there was already an existing matching node, use ReplaceAllUsesWith
      // to replace the dead one with the existing one.  This can cause
      // recursive merging of other unrelated nodes down the line.
      Existing->intersectFlagsWith(N->getFlags());
      if (auto *MemNode = dyn_cast<MemSDNode>(Existing))
        MemNode->refineRanges(cast<MemSDNode>(N)->getMemOperand());
      ReplaceAllUsesWith(N, Existing);

      // N is now dead. Inform the listeners and delete it.
      for (DAGUpdateListener *DUL = UpdateListeners; DUL; DUL = DUL->Next)
        DUL->NodeDeleted(N, Existing);
      DeleteNodeNotInCSEMaps(N);
      return;
    }
  }

  // If the node doesn't already exist, we updated it.  Inform listeners.
  for (DAGUpdateListener *DUL = UpdateListeners; DUL; DUL = DUL->Next)
    DUL->NodeUpdated(N);
}

/// FindModifiedNodeSlot - Find a slot for the specified node if its operands
/// were replaced with those specified.  If this node is never memoized,
/// return null, otherwise return a pointer to the slot it would take.  If a
/// node already exists with these operands, the slot will be non-null.
SDNode *SelectionDAG::FindModifiedNodeSlot(SDNode *N, SDValue Op,
                                           void *&InsertPos) {
  if (doNotCSE(N))
    return nullptr;

  SDValue Ops[] = { Op };
  FoldingSetNodeID ID;
  AddNodeIDNode(ID, N->getOpcode(), N->getVTList(), Ops);
  AddNodeIDCustom(ID, N);
  SDNode *Node = FindNodeOrInsertPos(ID, SDLoc(N), InsertPos);
  if (Node)
    Node->intersectFlagsWith(N->getFlags());
  return Node;
}

/// FindModifiedNodeSlot - Find a slot for the specified node if its operands
/// were replaced with those specified.  If this node is never memoized,
/// return null, otherwise return a pointer to the slot it would take.  If a
/// node already exists with these operands, the slot will be non-null.
SDNode *SelectionDAG::FindModifiedNodeSlot(SDNode *N,
                                           SDValue Op1, SDValue Op2,
                                           void *&InsertPos) {
  if (doNotCSE(N))
    return nullptr;

  SDValue Ops[] = { Op1, Op2 };
  FoldingSetNodeID ID;
  AddNodeIDNode(ID, N->getOpcode(), N->getVTList(), Ops);
  AddNodeIDCustom(ID, N);
  SDNode *Node = FindNodeOrInsertPos(ID, SDLoc(N), InsertPos);
  if (Node)
    Node->intersectFlagsWith(N->getFlags());
  return Node;
}

/// FindModifiedNodeSlot - Find a slot for the specified node if its operands
/// were replaced with those specified.  If this node is never memoized,
/// return null, otherwise return a pointer to the slot it would take.  If a
/// node already exists with these operands, the slot will be non-null.
SDNode *SelectionDAG::FindModifiedNodeSlot(SDNode *N, ArrayRef<SDValue> Ops,
                                           void *&InsertPos) {
  if (doNotCSE(N))
    return nullptr;

  FoldingSetNodeID ID;
  AddNodeIDNode(ID, N->getOpcode(), N->getVTList(), Ops);
  AddNodeIDCustom(ID, N);
  SDNode *Node = FindNodeOrInsertPos(ID, SDLoc(N), InsertPos);
  if (Node)
    Node->intersectFlagsWith(N->getFlags());
  return Node;
}

Align SelectionDAG::getEVTAlign(EVT VT) const {
  Type *Ty = VT == MVT::iPTR ? PointerType::get(*getContext(), 0)
                             : VT.getTypeForEVT(*getContext());

  return getDataLayout().getABITypeAlign(Ty);
}

// EntryNode could meaningfully have debug info if we can find it...
SelectionDAG::SelectionDAG(const TargetMachine &tm, CodeGenOptLevel OL)
    : TM(tm), OptLevel(OL), EntryNode(ISD::EntryToken, 0, DebugLoc(),
                                      getVTList(MVT::Other, MVT::Glue)),
      Root(getEntryNode()) {
  InsertNode(&EntryNode);
  DbgInfo = new SDDbgInfo();
}

void SelectionDAG::init(MachineFunction &NewMF,
                        OptimizationRemarkEmitter &NewORE, Pass *PassPtr,
                        const TargetLibraryInfo *LibraryInfo,
                        UniformityInfo *NewUA, ProfileSummaryInfo *PSIin,
                        BlockFrequencyInfo *BFIin, MachineModuleInfo &MMIin,
                        FunctionVarLocs const *VarLocs, bool HasDivergency) {
  MF = &NewMF;
  SDAGISelPass = PassPtr;
  ORE = &NewORE;
  TLI = getSubtarget().getTargetLowering();
  TSI = getSubtarget().getSelectionDAGInfo();
  LibInfo = LibraryInfo;
  Context = &MF->getFunction().getContext();
  UA = NewUA;
  PSI = PSIin;
  BFI = BFIin;
  MMI = &MMIin;
  FnVarLocs = VarLocs;
  DivergentTarget = HasDivergency;
}

SelectionDAG::~SelectionDAG() {
  assert(!UpdateListeners && "Dangling registered DAGUpdateListeners");
  allnodes_clear();
  OperandRecycler.clear(OperandAllocator);
  delete DbgInfo;
}

bool SelectionDAG::shouldOptForSize() const {
  return llvm::shouldOptimizeForSize(FLI->MBB->getBasicBlock(), PSI, BFI);
}

void SelectionDAG::allnodes_clear() {
  assert(&*AllNodes.begin() == &EntryNode);
  AllNodes.remove(AllNodes.begin());
  while (!AllNodes.empty())
    DeallocateNode(&AllNodes.front());
#ifndef NDEBUG
  NextPersistentId = 0;
#endif
}

SDNode *SelectionDAG::FindNodeOrInsertPos(const FoldingSetNodeID &ID,
                                          void *&InsertPos) {
  SDNode *N = CSEMap.FindNodeOrInsertPos(ID, InsertPos);
  if (N) {
    switch (N->getOpcode()) {
    default: break;
    case ISD::Constant:
    case ISD::ConstantFP:
      llvm_unreachable("Querying for Constant and ConstantFP nodes requires "
                       "debug location.  Use another overload.");
    }
  }
  return N;
}

SDNode *SelectionDAG::FindNodeOrInsertPos(const FoldingSetNodeID &ID,
                                          const SDLoc &DL, void *&InsertPos) {
  SDNode *N = CSEMap.FindNodeOrInsertPos(ID, InsertPos);
  if (N) {
    switch (N->getOpcode()) {
    case ISD::Constant:
    case ISD::ConstantFP:
      // Erase debug location from the node if the node is used at several
      // different places. Do not propagate one location to all uses as it
      // will cause a worse single stepping debugging experience.
      if (N->getDebugLoc() != DL.getDebugLoc())
        N->setDebugLoc(DebugLoc());
      break;
    default:
      // When the node's point of use is located earlier in the instruction
      // sequence than its prior point of use, update its debug info to the
      // earlier location.
      if (DL.getIROrder() && DL.getIROrder() < N->getIROrder())
        N->setDebugLoc(DL.getDebugLoc());
      break;
    }
  }
  return N;
}

void SelectionDAG::clear() {
  allnodes_clear();
  OperandRecycler.clear(OperandAllocator);
  OperandAllocator.Reset();
  CSEMap.clear();

  ExtendedValueTypeNodes.clear();
  ExternalSymbols.clear();
  TargetExternalSymbols.clear();
  MCSymbols.clear();
  SDEI.clear();
  llvm::fill(CondCodeNodes, nullptr);
  llvm::fill(ValueTypeNodes, nullptr);

  EntryNode.UseList = nullptr;
  InsertNode(&EntryNode);
  Root = getEntryNode();
  DbgInfo->clear();
}

SDValue SelectionDAG::getFPExtendOrRound(SDValue Op, const SDLoc &DL, EVT VT) {
  return VT.bitsGT(Op.getValueType())
             ? getNode(ISD::FP_EXTEND, DL, VT, Op)
             : getNode(ISD::FP_ROUND, DL, VT, Op,
                       getIntPtrConstant(0, DL, /*isTarget=*/true));
}

std::pair<SDValue, SDValue>
SelectionDAG::getStrictFPExtendOrRound(SDValue Op, SDValue Chain,
                                       const SDLoc &DL, EVT VT) {
  assert(!VT.bitsEq(Op.getValueType()) &&
         "Strict no-op FP extend/round not allowed.");
  SDValue Res =
      VT.bitsGT(Op.getValueType())
          ? getNode(ISD::STRICT_FP_EXTEND, DL, {VT, MVT::Other}, {Chain, Op})
          : getNode(ISD::STRICT_FP_ROUND, DL, {VT, MVT::Other},
                    {Chain, Op, getIntPtrConstant(0, DL, /*isTarget=*/true)});

  return std::pair<SDValue, SDValue>(Res, SDValue(Res.getNode(), 1));
}

SDValue SelectionDAG::getAnyExtOrTrunc(SDValue Op, const SDLoc &DL, EVT VT) {
  return VT.bitsGT(Op.getValueType()) ?
    getNode(ISD::ANY_EXTEND, DL, VT, Op) :
    getNode(ISD::TRUNCATE, DL, VT, Op);
}

SDValue SelectionDAG::getSExtOrTrunc(SDValue Op, const SDLoc &DL, EVT VT) {
  return VT.bitsGT(Op.getValueType()) ?
    getNode(ISD::SIGN_EXTEND, DL, VT, Op) :
    getNode(ISD::TRUNCATE, DL, VT, Op);
}

SDValue SelectionDAG::getZExtOrTrunc(SDValue Op, const SDLoc &DL, EVT VT) {
  return VT.bitsGT(Op.getValueType()) ?
    getNode(ISD::ZERO_EXTEND, DL, VT, Op) :
    getNode(ISD::TRUNCATE, DL, VT, Op);
}

SDValue SelectionDAG::getBitcastedAnyExtOrTrunc(SDValue Op, const SDLoc &DL,
                                                EVT VT) {
  assert(!VT.isVector());
  auto Type = Op.getValueType();
  SDValue DestOp;
  if (Type == VT)
    return Op;
  auto Size = Op.getValueSizeInBits();
  DestOp = getBitcast(EVT::getIntegerVT(*Context, Size), Op);
  if (DestOp.getValueType() == VT)
    return DestOp;

  return getAnyExtOrTrunc(DestOp, DL, VT);
}

SDValue SelectionDAG::getBitcastedSExtOrTrunc(SDValue Op, const SDLoc &DL,
                                               EVT VT) {
  assert(!VT.isVector());
  auto Type = Op.getValueType();
  SDValue DestOp;
  if (Type == VT)
    return Op;
  auto Size = Op.getValueSizeInBits();
  DestOp = getBitcast(MVT::getIntegerVT(Size), Op);
  if (DestOp.getValueType() == VT)
    return DestOp;

  return getSExtOrTrunc(DestOp, DL, VT);
}

SDValue SelectionDAG::getBitcastedZExtOrTrunc(SDValue Op, const SDLoc &DL,
                                               EVT VT) {
  assert(!VT.isVector());
  auto Type = Op.getValueType();
  SDValue DestOp;
  if (Type == VT)
    return Op;
  auto Size = Op.getValueSizeInBits();
  DestOp = getBitcast(MVT::getIntegerVT(Size), Op);
  if (DestOp.getValueType() == VT)
    return DestOp;

  return getZExtOrTrunc(DestOp, DL, VT);
}

SDValue SelectionDAG::getBoolExtOrTrunc(SDValue Op, const SDLoc &SL, EVT VT,
                                        EVT OpVT) {
  if (VT.bitsLE(Op.getValueType()))
    return getNode(ISD::TRUNCATE, SL, VT, Op);

  TargetLowering::BooleanContent BType = TLI->getBooleanContents(OpVT);
  return getNode(TLI->getExtendForContent(BType), SL, VT, Op);
}

SDValue SelectionDAG::getZeroExtendInReg(SDValue Op, const SDLoc &DL, EVT VT) {
  EVT OpVT = Op.getValueType();
  assert(VT.isInteger() && OpVT.isInteger() &&
         "Cannot getZeroExtendInReg FP types");
  assert(VT.isVector() == OpVT.isVector() &&
         "getZeroExtendInReg type should be vector iff the operand "
         "type is vector!");
  assert((!VT.isVector() ||
          VT.getVectorElementCount() == OpVT.getVectorElementCount()) &&
         "Vector element counts must match in getZeroExtendInReg");
  assert(VT.bitsLE(OpVT) && "Not extending!");
  if (OpVT == VT)
    return Op;
  APInt Imm = APInt::getLowBitsSet(OpVT.getScalarSizeInBits(),
                                   VT.getScalarSizeInBits());
  return getNode(ISD::AND, DL, OpVT, Op, getConstant(Imm, DL, OpVT));
}

SDValue SelectionDAG::getVPZeroExtendInReg(SDValue Op, SDValue Mask,
                                           SDValue EVL, const SDLoc &DL,
                                           EVT VT) {
  EVT OpVT = Op.getValueType();
  assert(VT.isInteger() && OpVT.isInteger() &&
         "Cannot getVPZeroExtendInReg FP types");
  assert(VT.isVector() && OpVT.isVector() &&
         "getVPZeroExtendInReg type and operand type should be vector!");
  assert(VT.getVectorElementCount() == OpVT.getVectorElementCount() &&
         "Vector element counts must match in getZeroExtendInReg");
  assert(VT.bitsLE(OpVT) && "Not extending!");
  if (OpVT == VT)
    return Op;
  APInt Imm = APInt::getLowBitsSet(OpVT.getScalarSizeInBits(),
                                   VT.getScalarSizeInBits());
  return getNode(ISD::VP_AND, DL, OpVT, Op, getConstant(Imm, DL, OpVT), Mask,
                 EVL);
}

SDValue SelectionDAG::getPtrExtOrTrunc(SDValue Op, const SDLoc &DL, EVT VT) {
  // Only unsigned pointer semantics are supported right now. In the future this
  // might delegate to TLI to check pointer signedness.
  return getZExtOrTrunc(Op, DL, VT);
}

SDValue SelectionDAG::getPtrExtendInReg(SDValue Op, const SDLoc &DL, EVT VT) {
  // Only unsigned pointer semantics are supported right now. In the future this
  // might delegate to TLI to check pointer signedness.
  return getZeroExtendInReg(Op, DL, VT);
}

SDValue SelectionDAG::getNegative(SDValue Val, const SDLoc &DL, EVT VT) {
  return getNode(ISD::SUB, DL, VT, getConstant(0, DL, VT), Val);
}

/// getNOT - Create a bitwise NOT operation as (XOR Val, -1).
SDValue SelectionDAG::getNOT(const SDLoc &DL, SDValue Val, EVT VT) {
  return getNode(ISD::XOR, DL, VT, Val, getAllOnesConstant(DL, VT));
}

SDValue SelectionDAG::getLogicalNOT(const SDLoc &DL, SDValue Val, EVT VT) {
  SDValue TrueValue = getBoolConstant(true, DL, VT, VT);
  return getNode(ISD::XOR, DL, VT, Val, TrueValue);
}

SDValue SelectionDAG::getVPLogicalNOT(const SDLoc &DL, SDValue Val,
                                      SDValue Mask, SDValue EVL, EVT VT) {
  SDValue TrueValue = getBoolConstant(true, DL, VT, VT);
  return getNode(ISD::VP_XOR, DL, VT, Val, TrueValue, Mask, EVL);
}

SDValue SelectionDAG::getVPPtrExtOrTrunc(const SDLoc &DL, EVT VT, SDValue Op,
                                         SDValue Mask, SDValue EVL) {
  return getVPZExtOrTrunc(DL, VT, Op, Mask, EVL);
}

SDValue SelectionDAG::getVPZExtOrTrunc(const SDLoc &DL, EVT VT, SDValue Op,
                                       SDValue Mask, SDValue EVL) {
  if (VT.bitsGT(Op.getValueType()))
    return getNode(ISD::VP_ZERO_EXTEND, DL, VT, Op, Mask, EVL);
  if (VT.bitsLT(Op.getValueType()))
    return getNode(ISD::VP_TRUNCATE, DL, VT, Op, Mask, EVL);
  return Op;
}

SDValue SelectionDAG::getBoolConstant(bool V, const SDLoc &DL, EVT VT,
                                      EVT OpVT) {
  if (!V)
    return getConstant(0, DL, VT);

  switch (TLI->getBooleanContents(OpVT)) {
  case TargetLowering::ZeroOrOneBooleanContent:
  case TargetLowering::UndefinedBooleanContent:
    return getConstant(1, DL, VT);
  case TargetLowering::ZeroOrNegativeOneBooleanContent:
    return getAllOnesConstant(DL, VT);
  }
  llvm_unreachable("Unexpected boolean content enum!");
}

SDValue SelectionDAG::getConstant(uint64_t Val, const SDLoc &DL, EVT VT,
                                  bool isT, bool isO) {
  return getConstant(APInt(VT.getScalarSizeInBits(), Val, /*isSigned=*/false),
                     DL, VT, isT, isO);
}

SDValue SelectionDAG::getConstant(const APInt &Val, const SDLoc &DL, EVT VT,
                                  bool isT, bool isO) {
  return getConstant(*ConstantInt::get(*Context, Val), DL, VT, isT, isO);
}

SDValue SelectionDAG::getConstant(const ConstantInt &Val, const SDLoc &DL,
                                  EVT VT, bool isT, bool isO) {
  assert(VT.isInteger() && "Cannot create FP integer constant!");

  EVT EltVT = VT.getScalarType();
  const ConstantInt *Elt = &Val;

  // Vector splats are explicit within the DAG, with ConstantSDNode holding the
  // to-be-splatted scalar ConstantInt.
  if (isa<VectorType>(Elt->getType()))
    Elt = ConstantInt::get(*getContext(), Elt->getValue());

  // In some cases the vector type is legal but the element type is illegal and
  // needs to be promoted, for example v8i8 on ARM.  In this case, promote the
  // inserted value (the type does not need to match the vector element type).
  // Any extra bits introduced will be truncated away.
  if (VT.isVector() && TLI->getTypeAction(*getContext(), EltVT) ==
                           TargetLowering::TypePromoteInteger) {
    EltVT = TLI->getTypeToTransformTo(*getContext(), EltVT);
    APInt NewVal;
    if (TLI->isSExtCheaperThanZExt(VT.getScalarType(), EltVT))
      NewVal = Elt->getValue().sextOrTrunc(EltVT.getSizeInBits());
    else
      NewVal = Elt->getValue().zextOrTrunc(EltVT.getSizeInBits());
    Elt = ConstantInt::get(*getContext(), NewVal);
  }
  // In other cases the element type is illegal and needs to be expanded, for
  // example v2i64 on MIPS32. In this case, find the nearest legal type, split
  // the value into n parts and use a vector type with n-times the elements.
  // Then bitcast to the type requested.
  // Legalizing constants too early makes the DAGCombiner's job harder so we
  // only legalize if the DAG tells us we must produce legal types.
  else if (NewNodesMustHaveLegalTypes && VT.isVector() &&
           TLI->getTypeAction(*getContext(), EltVT) ==
               TargetLowering::TypeExpandInteger) {
    const APInt &NewVal = Elt->getValue();
    EVT ViaEltVT = TLI->getTypeToTransformTo(*getContext(), EltVT);
    unsigned ViaEltSizeInBits = ViaEltVT.getSizeInBits();

    // For scalable vectors, try to use a SPLAT_VECTOR_PARTS node.
    if (VT.isScalableVector() ||
        TLI->isOperationLegal(ISD::SPLAT_VECTOR, VT)) {
      assert(EltVT.getSizeInBits() % ViaEltSizeInBits == 0 &&
             "Can only handle an even split!");
      unsigned Parts = EltVT.getSizeInBits() / ViaEltSizeInBits;

      SmallVector<SDValue, 2> ScalarParts;
      for (unsigned i = 0; i != Parts; ++i)
        ScalarParts.push_back(getConstant(
            NewVal.extractBits(ViaEltSizeInBits, i * ViaEltSizeInBits), DL,
            ViaEltVT, isT, isO));

      return getNode(ISD::SPLAT_VECTOR_PARTS, DL, VT, ScalarParts);
    }

    unsigned ViaVecNumElts = VT.getSizeInBits() / ViaEltSizeInBits;
    EVT ViaVecVT = EVT::getVectorVT(*getContext(), ViaEltVT, ViaVecNumElts);

    // Check the temporary vector is the correct size. If this fails then
    // getTypeToTransformTo() probably returned a type whose size (in bits)
    // isn't a power-of-2 factor of the requested type size.
    assert(ViaVecVT.getSizeInBits() == VT.getSizeInBits());

    SmallVector<SDValue, 2> EltParts;
    for (unsigned i = 0; i < ViaVecNumElts / VT.getVectorNumElements(); ++i)
      EltParts.push_back(getConstant(
          NewVal.extractBits(ViaEltSizeInBits, i * ViaEltSizeInBits), DL,
          ViaEltVT, isT, isO));

    // EltParts is currently in little endian order. If we actually want
    // big-endian order then reverse it now.
    if (getDataLayout().isBigEndian())
      std::reverse(EltParts.begin(), EltParts.end());

    // The elements must be reversed when the element order is different
    // to the endianness of the elements (because the BITCAST is itself a
    // vector shuffle in this situation). However, we do not need any code to
    // perform this reversal because getConstant() is producing a vector
    // splat.
    // This situation occurs in MIPS MSA.

    SmallVector<SDValue, 8> Ops;
    for (unsigned i = 0, e = VT.getVectorNumElements(); i != e; ++i)
      llvm::append_range(Ops, EltParts);

    SDValue V =
        getNode(ISD::BITCAST, DL, VT, getBuildVector(ViaVecVT, DL, Ops));
    return V;
  }

  assert(Elt->getBitWidth() == EltVT.getSizeInBits() &&
         "APInt size does not match type size!");
  unsigned Opc = isT ? ISD::TargetConstant : ISD::Constant;
  SDVTList VTs = getVTList(EltVT);
  FoldingSetNodeID ID;
  AddNodeIDNode(ID, Opc, VTs, {});
  ID.AddPointer(Elt);
  ID.AddBoolean(isO);
  void *IP = nullptr;
  SDNode *N = nullptr;
  if ((N = FindNodeOrInsertPos(ID, DL, IP)))
    if (!VT.isVector())
      return SDValue(N, 0);

  if (!N) {
    N = newSDNode<ConstantSDNode>(isT, isO, Elt, VTs);
    CSEMap.InsertNode(N, IP);
    InsertNode(N);
    NewSDValueDbgMsg(SDValue(N, 0), "Creating constant: ", this);
  }

  SDValue Result(N, 0);
  if (VT.isVector())
    Result = getSplat(VT, DL, Result);
  return Result;
}

SDValue SelectionDAG::getSignedConstant(int64_t Val, const SDLoc &DL, EVT VT,
                                        bool isT, bool isO) {
  unsigned Size = VT.getScalarSizeInBits();
  return getConstant(APInt(Size, Val, /*isSigned=*/true), DL, VT, isT, isO);
}

SDValue SelectionDAG::getAllOnesConstant(const SDLoc &DL, EVT VT, bool IsTarget,
                                         bool IsOpaque) {
  return getConstant(APInt::getAllOnes(VT.getScalarSizeInBits()), DL, VT,
                     IsTarget, IsOpaque);
}

SDValue SelectionDAG::getIntPtrConstant(uint64_t Val, const SDLoc &DL,
                                        bool isTarget) {
  return getConstant(Val, DL, TLI->getPointerTy(getDataLayout()), isTarget);
}

SDValue SelectionDAG::getShiftAmountConstant(uint64_t Val, EVT VT,
                                             const SDLoc &DL) {
  assert(VT.isInteger() && "Shift amount is not an integer type!");
  EVT ShiftVT = TLI->getShiftAmountTy(VT, getDataLayout());
  return getConstant(Val, DL, ShiftVT);
}

SDValue SelectionDAG::getShiftAmountConstant(const APInt &Val, EVT VT,
                                             const SDLoc &DL) {
  assert(Val.ult(VT.getScalarSizeInBits()) && "Out of range shift");
  return getShiftAmountConstant(Val.getZExtValue(), VT, DL);
}

SDValue SelectionDAG::getVectorIdxConstant(uint64_t Val, const SDLoc &DL,
                                           bool isTarget) {
  return getConstant(Val, DL, TLI->getVectorIdxTy(getDataLayout()), isTarget);
}

SDValue SelectionDAG::getConstantFP(const APFloat &V, const SDLoc &DL, EVT VT,
                                    bool isTarget) {
  return getConstantFP(*ConstantFP::get(*getContext(), V), DL, VT, isTarget);
}

SDValue SelectionDAG::getConstantFP(const ConstantFP &V, const SDLoc &DL,
                                    EVT VT, bool isTarget) {
  assert(VT.isFloatingPoint() && "Cannot create integer FP constant!");

  EVT EltVT = VT.getScalarType();
  const ConstantFP *Elt = &V;

  // Vector splats are explicit within the DAG, with ConstantFPSDNode holding
  // the to-be-splatted scalar ConstantFP.
  if (isa<VectorType>(Elt->getType()))
    Elt = ConstantFP::get(*getContext(), Elt->getValue());

  // Do the map lookup using the actual bit pattern for the floating point
  // value, so that we don't have problems with 0.0 comparing equal to -0.0, and
  // we don't have issues with SNANs.
  unsigned Opc = isTarget ? ISD::TargetConstantFP : ISD::ConstantFP;
  SDVTList VTs = getVTList(EltVT);
  FoldingSetNodeID ID;
  AddNodeIDNode(ID, Opc, VTs, {});
  ID.AddPointer(Elt);
  void *IP = nullptr;
  SDNode *N = nullptr;
  if ((N = FindNodeOrInsertPos(ID, DL, IP)))
    if (!VT.isVector())
      return SDValue(N, 0);

  if (!N) {
    N = newSDNode<ConstantFPSDNode>(isTarget, Elt, VTs);
    CSEMap.InsertNode(N, IP);
    InsertNode(N);
  }

  SDValue Result(N, 0);
  if (VT.isVector())
    Result = getSplat(VT, DL, Result);
  NewSDValueDbgMsg(Result, "Creating fp constant: ", this);
  return Result;
}

SDValue SelectionDAG::getConstantFP(double Val, const SDLoc &DL, EVT VT,
                                    bool isTarget) {
  EVT EltVT = VT.getScalarType();
  if (EltVT == MVT::f32)
    return getConstantFP(APFloat((float)Val), DL, VT, isTarget);
  if (EltVT == MVT::f64)
    return getConstantFP(APFloat(Val), DL, VT, isTarget);
  if (EltVT == MVT::f80 || EltVT == MVT::f128 || EltVT == MVT::ppcf128 ||
      EltVT == MVT::f16 || EltVT == MVT::bf16) {
    bool Ignored;
    APFloat APF = APFloat(Val);
    APF.convert(EltVT.getFltSemantics(), APFloat::rmNearestTiesToEven,
                &Ignored);
    return getConstantFP(APF, DL, VT, isTarget);
  }
  llvm_unreachable("Unsupported type in getConstantFP");
}

SDValue SelectionDAG::getGlobalAddress(const GlobalValue *GV, const SDLoc &DL,
                                       EVT VT, int64_t Offset, bool isTargetGA,
                                       unsigned TargetFlags) {
  assert((TargetFlags == 0 || isTargetGA) &&
         "Cannot set target flags on target-independent globals");

  // Truncate (with sign-extension) the offset value to the pointer size.
  unsigned BitWidth = getDataLayout().getPointerTypeSizeInBits(GV->getType());
  if (BitWidth < 64)
    Offset = SignExtend64(Offset, BitWidth);

  unsigned Opc;
  if (GV->isThreadLocal())
    Opc = isTargetGA ? ISD::TargetGlobalTLSAddress : ISD::GlobalTLSAddress;
  else
    Opc = isTargetGA ? ISD::TargetGlobalAddress : ISD::GlobalAddress;

  SDVTList VTs = getVTList(VT);
  FoldingSetNodeID ID;
  AddNodeIDNode(ID, Opc, VTs, {});
  ID.AddPointer(GV);
  ID.AddInteger(Offset);
  ID.AddInteger(TargetFlags);
  void *IP = nullptr;
  if (SDNode *E = FindNodeOrInsertPos(ID, DL, IP))
    return SDValue(E, 0);

  auto *N = newSDNode<GlobalAddressSDNode>(
      Opc, DL.getIROrder(), DL.getDebugLoc(), GV, VTs, Offset, TargetFlags);
  CSEMap.InsertNode(N, IP);
    InsertNode(N);
  return SDValue(N, 0);
}

SDValue SelectionDAG::getFrameIndex(int FI, EVT VT, bool isTarget) {
  unsigned Opc = isTarget ? ISD::TargetFrameIndex : ISD::FrameIndex;
  SDVTList VTs = getVTList(VT);
  FoldingSetNodeID ID;
  AddNodeIDNode(ID, Opc, VTs, {});
  ID.AddInteger(FI);
  void *IP = nullptr;
  if (SDNode *E = FindNodeOrInsertPos(ID, IP))
    return SDValue(E, 0);

  auto *N = newSDNode<FrameIndexSDNode>(FI, VTs, isTarget);
  CSEMap.InsertNode(N, IP);
  InsertNode(N);
  return SDValue(N, 0);
}

SDValue SelectionDAG::getJumpTable(int JTI, EVT VT, bool isTarget,
                                   unsigned TargetFlags) {
  assert((TargetFlags == 0 || isTarget) &&
         "Cannot set target flags on target-independent jump tables");
  unsigned Opc = isTarget ? ISD::TargetJumpTable : ISD::JumpTable;
  SDVTList VTs = getVTList(VT);
  FoldingSetNodeID ID;
  AddNodeIDNode(ID, Opc, VTs, {});
  ID.AddInteger(JTI);
  ID.AddInteger(TargetFlags);
  void *IP = nullptr;
  if (SDNode *E = FindNodeOrInsertPos(ID, IP))
    return SDValue(E, 0);

  auto *N = newSDNode<JumpTableSDNode>(JTI, VTs, isTarget, TargetFlags);
  CSEMap.InsertNode(N, IP);
  InsertNode(N);
  return SDValue(N, 0);
}

SDValue SelectionDAG::getJumpTableDebugInfo(int JTI, SDValue Chain,
                                            const SDLoc &DL) {
  EVT PTy = getTargetLoweringInfo().getPointerTy(getDataLayout());
  return getNode(ISD::JUMP_TABLE_DEBUG_INFO, DL, MVT::Glue, Chain,
                 getTargetConstant(static_cast<uint64_t>(JTI), DL, PTy, true));
}

SDValue SelectionDAG::getConstantPool(const Constant *C, EVT VT,
                                      MaybeAlign Alignment, int Offset,
                                      bool isTarget, unsigned TargetFlags) {
  assert((TargetFlags == 0 || isTarget) &&
         "Cannot set target flags on target-independent globals");
  if (!Alignment)
    Alignment = shouldOptForSize()
                    ? getDataLayout().getABITypeAlign(C->getType())
                    : getDataLayout().getPrefTypeAlign(C->getType());
  unsigned Opc = isTarget ? ISD::TargetConstantPool : ISD::ConstantPool;
  SDVTList VTs = getVTList(VT);
  FoldingSetNodeID ID;
  AddNodeIDNode(ID, Opc, VTs, {});
  ID.AddInteger(Alignment->value());
  ID.AddInteger(Offset);
  ID.AddPointer(C);
  ID.AddInteger(TargetFlags);
  void *IP = nullptr;
  if (SDNode *E = FindNodeOrInsertPos(ID, IP))
    return SDValue(E, 0);

  auto *N = newSDNode<ConstantPoolSDNode>(isTarget, C, VTs, Offset, *Alignment,
                                          TargetFlags);
  CSEMap.InsertNode(N, IP);
  InsertNode(N);
  SDValue V = SDValue(N, 0);
  NewSDValueDbgMsg(V, "Creating new constant pool: ", this);
  return V;
}

SDValue SelectionDAG::getConstantPool(MachineConstantPoolValue *C, EVT VT,
                                      MaybeAlign Alignment, int Offset,
                                      bool isTarget, unsigned TargetFlags) {
  assert((TargetFlags == 0 || isTarget) &&
         "Cannot set target flags on target-independent globals");
  if (!Alignment)
    Alignment = getDataLayout().getPrefTypeAlign(C->getType());
  unsigned Opc = isTarget ? ISD::TargetConstantPool : ISD::ConstantPool;
  SDVTList VTs = getVTList(VT);
  FoldingSetNodeID ID;
  AddNodeIDNode(ID, Opc, VTs, {});
  ID.AddInteger(Alignment->value());
  ID.AddInteger(Offset);
  C->addSelectionDAGCSEId(ID);
  ID.AddInteger(TargetFlags);
  void *IP = nullptr;
  if (SDNode *E = FindNodeOrInsertPos(ID, IP))
    return SDValue(E, 0);

  auto *N = newSDNode<ConstantPoolSDNode>(isTarget, C, VTs, Offset, *Alignment,
                                          TargetFlags);
  CSEMap.InsertNode(N, IP);
  InsertNode(N);
  return SDValue(N, 0);
}

SDValue SelectionDAG::getBasicBlock(MachineBasicBlock *MBB) {
  FoldingSetNodeID ID;
  AddNodeIDNode(ID, ISD::BasicBlock, getVTList(MVT::Other), {});
  ID.AddPointer(MBB);
  void *IP = nullptr;
  if (SDNode *E = FindNodeOrInsertPos(ID, IP))
    return SDValue(E, 0);

  auto *N = newSDNode<BasicBlockSDNode>(MBB);
  CSEMap.InsertNode(N, IP);
  InsertNode(N);
  return SDValue(N, 0);
}

SDValue SelectionDAG::getValueType(EVT VT) {
  if (VT.isSimple() && (unsigned)VT.getSimpleVT().SimpleTy >=
      ValueTypeNodes.size())
    ValueTypeNodes.resize(VT.getSimpleVT().SimpleTy+1);

  SDNode *&N = VT.isExtended() ?
    ExtendedValueTypeNodes[VT] : ValueTypeNodes[VT.getSimpleVT().SimpleTy];

  if (N) return SDValue(N, 0);
  N = newSDNode<VTSDNode>(VT);
  InsertNode(N);
  return SDValue(N, 0);
}

SDValue SelectionDAG::getExternalSymbol(const char *Sym, EVT VT) {
  SDNode *&N = ExternalSymbols[Sym];
  if (N) return SDValue(N, 0);
  N = newSDNode<ExternalSymbolSDNode>(false, Sym, 0, getVTList(VT));
  InsertNode(N);
  return SDValue(N, 0);
}

SDValue SelectionDAG::getMCSymbol(MCSymbol *Sym, EVT VT) {
  SDNode *&N = MCSymbols[Sym];
  if (N)
    return SDValue(N, 0);
  N = newSDNode<MCSymbolSDNode>(Sym, getVTList(VT));
  InsertNode(N);
  return SDValue(N, 0);
}

SDValue SelectionDAG::getTargetExternalSymbol(const char *Sym, EVT VT,
                                              unsigned TargetFlags) {
  SDNode *&N =
      TargetExternalSymbols[std::pair<std::string, unsigned>(Sym, TargetFlags)];
  if (N) return SDValue(N, 0);
  N = newSDNode<ExternalSymbolSDNode>(true, Sym, TargetFlags, getVTList(VT));
  InsertNode(N);
  return SDValue(N, 0);
}

SDValue SelectionDAG::getCondCode(ISD::CondCode Cond) {
  if ((unsigned)Cond >= CondCodeNodes.size())
    CondCodeNodes.resize(Cond+1);

  if (!CondCodeNodes[Cond]) {
    auto *N = newSDNode<CondCodeSDNode>(Cond);
    CondCodeNodes[Cond] = N;
    InsertNode(N);
  }

  return SDValue(CondCodeNodes[Cond], 0);
}

SDValue SelectionDAG::getVScale(const SDLoc &DL, EVT VT, APInt MulImm,
                                bool ConstantFold) {
  assert(MulImm.getBitWidth() == VT.getSizeInBits() &&
         "APInt size does not match type size!");

  if (MulImm == 0)
    return getConstant(0, DL, VT);

  if (ConstantFold) {
    const MachineFunction &MF = getMachineFunction();
    const Function &F = MF.getFunction();
    ConstantRange CR = getVScaleRange(&F, 64);
    if (const APInt *C = CR.getSingleElement())
      return getConstant(MulImm * C->getZExtValue(), DL, VT);
  }

  return getNode(ISD::VSCALE, DL, VT, getConstant(MulImm, DL, VT));
}

SDValue SelectionDAG::getElementCount(const SDLoc &DL, EVT VT, ElementCount EC,
                                      bool ConstantFold) {
  if (EC.isScalable())
    return getVScale(DL, VT,
                     APInt(VT.getSizeInBits(), EC.getKnownMinValue()));

  return getConstant(EC.getKnownMinValue(), DL, VT);
}

SDValue SelectionDAG::getStepVector(const SDLoc &DL, EVT ResVT) {
  APInt One(ResVT.getScalarSizeInBits(), 1);
  return getStepVector(DL, ResVT, One);
}

SDValue SelectionDAG::getStepVector(const SDLoc &DL, EVT ResVT,
                                    const APInt &StepVal) {
  assert(ResVT.getScalarSizeInBits() == StepVal.getBitWidth());
  if (ResVT.isScalableVector())
    return getNode(
        ISD::STEP_VECTOR, DL, ResVT,
        getTargetConstant(StepVal, DL, ResVT.getVectorElementType()));

  SmallVector<SDValue, 16> OpsStepConstants;
  for (uint64_t i = 0; i < ResVT.getVectorNumElements(); i++)
    OpsStepConstants.push_back(
        getConstant(StepVal * i, DL, ResVT.getVectorElementType()));
  return getBuildVector(ResVT, DL, OpsStepConstants);
}

/// Swaps the values of N1 and N2. Swaps all indices in the shuffle mask M that
/// point at N1 to point at N2 and indices that point at N2 to point at N1.
static void commuteShuffle(SDValue &N1, SDValue &N2, MutableArrayRef<int> M) {
  std::swap(N1, N2);
  ShuffleVectorSDNode::commuteMask(M);
}

SDValue SelectionDAG::getVectorShuffle(EVT VT, const SDLoc &dl, SDValue N1,
                                       SDValue N2, ArrayRef<int> Mask) {
  assert(VT.getVectorNumElements() == Mask.size() &&
         "Must have the same number of vector elements as mask elements!");
  assert(VT == N1.getValueType() && VT == N2.getValueType() &&
         "Invalid VECTOR_SHUFFLE");

  // Canonicalize shuffle undef, undef -> undef
  if (N1.isUndef() && N2.isUndef())
    return getUNDEF(VT);

  // Validate that all indices in Mask are within the range of the elements
  // input to the shuffle.
  int NElts = Mask.size();
  assert(llvm::all_of(Mask,
                      [&](int M) { return M < (NElts * 2) && M >= -1; }) &&
         "Index out of range");

  // Copy the mask so we can do any needed cleanup.
  SmallVector<int, 8> MaskVec(Mask);

  // Canonicalize shuffle v, v -> v, undef
  if (N1 == N2) {
    N2 = getUNDEF(VT);
    for (int i = 0; i != NElts; ++i)
      if (MaskVec[i] >= NElts) MaskVec[i] -= NElts;
  }

  // Canonicalize shuffle undef, v -> v, undef.  Commute the shuffle mask.
  if (N1.isUndef())
    commuteShuffle(N1, N2, MaskVec);

  if (TLI->hasVectorBlend()) {
    // If shuffling a splat, try to blend the splat instead. We do this here so
    // that even when this arises during lowering we don't have to re-handle it.
    auto BlendSplat = [&](BuildVectorSDNode *BV, int Offset) {
      BitVector UndefElements;
      SDValue Splat = BV->getSplatValue(&UndefElements);
      if (!Splat)
        return;

      for (int i = 0; i < NElts; ++i) {
        if (MaskVec[i] < Offset || MaskVec[i] >= (Offset + NElts))
          continue;

        // If this input comes from undef, mark it as such.
        if (UndefElements[MaskVec[i] - Offset]) {
          MaskVec[i] = -1;
          continue;
        }

        // If we can blend a non-undef lane, use that instead.
        if (!UndefElements[i])
          MaskVec[i] = i + Offset;
      }
    };
    if (auto *N1BV = dyn_cast<BuildVectorSDNode>(N1))
      BlendSplat(N1BV, 0);
    if (auto *N2BV = dyn_cast<BuildVectorSDNode>(N2))
      BlendSplat(N2BV, NElts);
  }

  // Canonicalize all index into lhs, -> shuffle lhs, undef
  // Canonicalize all index into rhs, -> shuffle rhs, undef
  bool AllLHS = true, AllRHS = true;
  bool N2Undef = N2.isUndef();
  for (int i = 0; i != NElts; ++i) {
    if (MaskVec[i] >= NElts) {
      if (N2Undef)
        MaskVec[i] = -1;
      else
        AllLHS = false;
    } else if (MaskVec[i] >= 0) {
      AllRHS = false;
    }
  }
  if (AllLHS && AllRHS)
    return getUNDEF(VT);
  if (AllLHS && !N2Undef)
    N2 = getUNDEF(VT);
  if (AllRHS) {
    N1 = getUNDEF(VT);
    commuteShuffle(N1, N2, MaskVec);
  }
  // Reset our undef status after accounting for the mask.
  N2Undef = N2.isUndef();
  // Re-check whether both sides ended up undef.
  if (N1.isUndef() && N2Undef)
    return getUNDEF(VT);

  // If Identity shuffle return that node.
  bool Identity = true, AllSame = true;
  for (int i = 0; i != NElts; ++i) {
    if (MaskVec[i] >= 0 && MaskVec[i] != i) Identity = false;
    if (MaskVec[i] != MaskVec[0]) AllSame = false;
  }
  if (Identity && NElts)
    return N1;

  // Shuffling a constant splat doesn't change the result.
  if (N2Undef) {
    SDValue V = N1;

    // Look through any bitcasts. We check that these don't change the number
    // (and size) of elements and just changes their types.
    while (V.getOpcode() == ISD::BITCAST)
      V = V->getOperand(0);

    // A splat should always show up as a build vector node.
    if (auto *BV = dyn_cast<BuildVectorSDNode>(V)) {
      BitVector UndefElements;
      SDValue Splat = BV->getSplatValue(&UndefElements);
      // If this is a splat of an undef, shuffling it is also undef.
      if (Splat && Splat.isUndef())
        return getUNDEF(VT);

      bool SameNumElts =
          V.getValueType().getVectorNumElements() == VT.getVectorNumElements();

      // We only have a splat which can skip shuffles if there is a splatted
      // value and no undef lanes rearranged by the shuffle.
      if (Splat && UndefElements.none()) {
        // Splat of <x, x, ..., x>, return <x, x, ..., x>, provided that the
        // number of elements match or the value splatted is a zero constant.
        if (SameNumElts || isNullConstant(Splat))
          return N1;
      }

      // If the shuffle itself creates a splat, build the vector directly.
      if (AllSame && SameNumElts) {
        EVT BuildVT = BV->getValueType(0);
        const SDValue &Splatted = BV->getOperand(MaskVec[0]);
        SDValue NewBV = getSplatBuildVector(BuildVT, dl, Splatted);

        // We may have jumped through bitcasts, so the type of the
        // BUILD_VECTOR may not match the type of the shuffle.
        if (BuildVT != VT)
          NewBV = getNode(ISD::BITCAST, dl, VT, NewBV);
        return NewBV;
      }
    }
  }

  SDVTList VTs = getVTList(VT);
  FoldingSetNodeID ID;
  SDValue Ops[2] = { N1, N2 };
  AddNodeIDNode(ID, ISD::VECTOR_SHUFFLE, VTs, Ops);
  for (int i = 0; i != NElts; ++i)
    ID.AddInteger(MaskVec[i]);

  void* IP = nullptr;
  if (SDNode *E = FindNodeOrInsertPos(ID, dl, IP))
    return SDValue(E, 0);

  // Allocate the mask array for the node out of the BumpPtrAllocator, since
  // SDNode doesn't have access to it.  This memory will be "leaked" when
  // the node is deallocated, but recovered when the NodeAllocator is released.
  int *MaskAlloc = OperandAllocator.Allocate<int>(NElts);
  llvm::copy(MaskVec, MaskAlloc);

  auto *N = newSDNode<ShuffleVectorSDNode>(VTs, dl.getIROrder(),
                                           dl.getDebugLoc(), MaskAlloc);
  createOperands(N, Ops);

  CSEMap.InsertNode(N, IP);
  InsertNode(N);
  SDValue V = SDValue(N, 0);
  NewSDValueDbgMsg(V, "Creating new node: ", this);
  return V;
}

SDValue SelectionDAG::getCommutedVectorShuffle(const ShuffleVectorSDNode &SV) {
  EVT VT = SV.getValueType(0);
  SmallVector<int, 8> MaskVec(SV.getMask());
  ShuffleVectorSDNode::commuteMask(MaskVec);

  SDValue Op0 = SV.getOperand(0);
  SDValue Op1 = SV.getOperand(1);
  return getVectorShuffle(VT, SDLoc(&SV), Op1, Op0, MaskVec);
}

SDValue SelectionDAG::getRegister(Register Reg, EVT VT) {
  SDVTList VTs = getVTList(VT);
  FoldingSetNodeID ID;
  AddNodeIDNode(ID, ISD::Register, VTs, {});
  ID.AddInteger(Reg.id());
  void *IP = nullptr;
  if (SDNode *E = FindNodeOrInsertPos(ID, IP))
    return SDValue(E, 0);

  auto *N = newSDNode<RegisterSDNode>(Reg, VTs);
  N->SDNodeBits.IsDivergent =
      DivergentTarget && TLI->isSDNodeSourceOfDivergence(N, FLI, UA);
  CSEMap.InsertNode(N, IP);
  InsertNode(N);
  return SDValue(N, 0);
}

SDValue SelectionDAG::getRegisterMask(const uint32_t *RegMask) {
  FoldingSetNodeID ID;
  AddNodeIDNode(ID, ISD::RegisterMask, getVTList(MVT::Untyped), {});
  ID.AddPointer(RegMask);
  void *IP = nullptr;
  if (SDNode *E = FindNodeOrInsertPos(ID, IP))
    return SDValue(E, 0);

  auto *N = newSDNode<RegisterMaskSDNode>(RegMask);
  CSEMap.InsertNode(N, IP);
  InsertNode(N);
  return SDValue(N, 0);
}

SDValue SelectionDAG::getEHLabel(const SDLoc &dl, SDValue Root,
                                 MCSymbol *Label) {
  return getLabelNode(ISD::EH_LABEL, dl, Root, Label);
}

SDValue SelectionDAG::getLabelNode(unsigned Opcode, const SDLoc &dl,
                                   SDValue Root, MCSymbol *Label) {
  FoldingSetNodeID ID;
  SDValue Ops[] = { Root };
  AddNodeIDNode(ID, Opcode, getVTList(MVT::Other), Ops);
  ID.AddPointer(Label);
  void *IP = nullptr;
  if (SDNode *E = FindNodeOrInsertPos(ID, IP))
    return SDValue(E, 0);

  auto *N =
      newSDNode<LabelSDNode>(Opcode, dl.getIROrder(), dl.getDebugLoc(), Label);
  createOperands(N, Ops);

  CSEMap.InsertNode(N, IP);
  InsertNode(N);
  return SDValue(N, 0);
}

SDValue SelectionDAG::getBlockAddress(const BlockAddress *BA, EVT VT,
                                      int64_t Offset, bool isTarget,
                                      unsigned TargetFlags) {
  unsigned Opc = isTarget ? ISD::TargetBlockAddress : ISD::BlockAddress;
  SDVTList VTs = getVTList(VT);

  FoldingSetNodeID ID;
  AddNodeIDNode(ID, Opc, VTs, {});
  ID.AddPointer(BA);
  ID.AddInteger(Offset);
  ID.AddInteger(TargetFlags);
  void *IP = nullptr;
  if (SDNode *E = FindNodeOrInsertPos(ID, IP))
    return SDValue(E, 0);

  auto *N = newSDNode<BlockAddressSDNode>(Opc, VTs, BA, Offset, TargetFlags);
  CSEMap.InsertNode(N, IP);
  InsertNode(N);
  return SDValue(N, 0);
}

SDValue SelectionDAG::getSrcValue(const Value *V) {
  FoldingSetNodeID ID;
  AddNodeIDNode(ID, ISD::SRCVALUE, getVTList(MVT::Other), {});
  ID.AddPointer(V);

  void *IP = nullptr;
  if (SDNode *E = FindNodeOrInsertPos(ID, IP))
    return SDValue(E, 0);

  auto *N = newSDNode<SrcValueSDNode>(V);
  CSEMap.InsertNode(N, IP);
  InsertNode(N);
  return SDValue(N, 0);
}

SDValue SelectionDAG::getMDNode(const MDNode *MD) {
  FoldingSetNodeID ID;
  AddNodeIDNode(ID, ISD::MDNODE_SDNODE, getVTList(MVT::Other), {});
  ID.AddPointer(MD);

  void *IP = nullptr;
  if (SDNode *E = FindNodeOrInsertPos(ID, IP))
    return SDValue(E, 0);

  auto *N = newSDNode<MDNodeSDNode>(MD);
  CSEMap.InsertNode(N, IP);
  InsertNode(N);
  return SDValue(N, 0);
}

SDValue SelectionDAG::getBitcast(EVT VT, SDValue V) {
  if (VT == V.getValueType())
    return V;

  return getNode(ISD::BITCAST, SDLoc(V), VT, V);
}

SDValue SelectionDAG::getAddrSpaceCast(const SDLoc &dl, EVT VT, SDValue Ptr,
                                       unsigned SrcAS, unsigned DestAS) {
  SDVTList VTs = getVTList(VT);
  SDValue Ops[] = {Ptr};
  FoldingSetNodeID ID;
  AddNodeIDNode(ID, ISD::ADDRSPACECAST, VTs, Ops);
  ID.AddInteger(SrcAS);
  ID.AddInteger(DestAS);

  void *IP = nullptr;
  if (SDNode *E = FindNodeOrInsertPos(ID, dl, IP))
    return SDValue(E, 0);

  auto *N = newSDNode<AddrSpaceCastSDNode>(dl.getIROrder(), dl.getDebugLoc(),
                                           VTs, SrcAS, DestAS);
  createOperands(N, Ops);

  CSEMap.InsertNode(N, IP);
  InsertNode(N);
  return SDValue(N, 0);
}

SDValue SelectionDAG::getFreeze(SDValue V) {
  return getNode(ISD::FREEZE, SDLoc(V), V.getValueType(), V);
}

/// getShiftAmountOperand - Return the specified value casted to
/// the target's desired shift amount type.
SDValue SelectionDAG::getShiftAmountOperand(EVT LHSTy, SDValue Op) {
  EVT OpTy = Op.getValueType();
  EVT ShTy = TLI->getShiftAmountTy(LHSTy, getDataLayout());
  if (OpTy == ShTy || OpTy.isVector()) return Op;

  return getZExtOrTrunc(Op, SDLoc(Op), ShTy);
}

/// Given a store node \p StoreNode, return true if it is safe to fold that node
/// into \p FPNode, which expands to a library call with output pointers.
static bool canFoldStoreIntoLibCallOutputPointers(StoreSDNode *StoreNode,
                                                  SDNode *FPNode) {
  SmallVector<const SDNode *, 8> Worklist;
  SmallVector<const SDNode *, 8> DeferredNodes;
  SmallPtrSet<const SDNode *, 16> Visited;

  // Skip FPNode use by StoreNode (that's the use we want to fold into FPNode).
  for (SDValue Op : StoreNode->ops())
    if (Op.getNode() != FPNode)
      Worklist.push_back(Op.getNode());

  unsigned MaxSteps = SelectionDAG::getHasPredecessorMaxSteps();
  while (!Worklist.empty()) {
    const SDNode *Node = Worklist.pop_back_val();
    auto [_, Inserted] = Visited.insert(Node);
    if (!Inserted)
      continue;

    if (MaxSteps > 0 && Visited.size() >= MaxSteps)
      return false;

    // Reached the FPNode (would result in a cycle).
    // OR Reached CALLSEQ_START (would result in nested call sequences).
    if (Node == FPNode || Node->getOpcode() == ISD::CALLSEQ_START)
      return false;

    if (Node->getOpcode() == ISD::CALLSEQ_END) {
      // Defer looking into call sequences (so we can check we're outside one).
      // We still need to look through these for the predecessor check.
      DeferredNodes.push_back(Node);
      continue;
    }

    for (SDValue Op : Node->ops())
      Worklist.push_back(Op.getNode());
  }

  // True if we're outside a call sequence and don't have the FPNode as a
  // predecessor. No cycles or nested call sequences possible.
  return !SDNode::hasPredecessorHelper(FPNode, Visited, DeferredNodes,
                                       MaxSteps);
}

bool SelectionDAG::expandMultipleResultFPLibCall(
    RTLIB::Libcall LC, SDNode *Node, SmallVectorImpl<SDValue> &Results,
    std::optional<unsigned> CallRetResNo) {
  LLVMContext &Ctx = *getContext();
  EVT VT = Node->getValueType(0);
  unsigned NumResults = Node->getNumValues();

  if (LC == RTLIB::UNKNOWN_LIBCALL)
    return false;

  const char *LCName = TLI->getLibcallName(LC);
  if (!LCName)
    return false;

  auto getVecDesc = [&]() -> VecDesc const * {
    for (bool Masked : {false, true}) {
      if (VecDesc const *VD = getLibInfo().getVectorMappingInfo(
              LCName, VT.getVectorElementCount(), Masked)) {
        return VD;
      }
    }
    return nullptr;
  };

  // For vector types, we must find a vector mapping for the libcall.
  VecDesc const *VD = nullptr;
  if (VT.isVector() && !(VD = getVecDesc()))
    return false;

  // Find users of the node that store the results (and share input chains). The
  // destination pointers can be used instead of creating stack allocations.
  SDValue StoresInChain;
  SmallVector<StoreSDNode *, 2> ResultStores(NumResults);
  for (SDNode *User : Node->users()) {
    if (!ISD::isNormalStore(User))
      continue;
    auto *ST = cast<StoreSDNode>(User);
    SDValue StoreValue = ST->getValue();
    unsigned ResNo = StoreValue.getResNo();
    // Ensure the store corresponds to an output pointer.
    if (CallRetResNo == ResNo)
      continue;
    // Ensure the store to the default address space and not atomic or volatile.
    if (!ST->isSimple() || ST->getAddressSpace() != 0)
      continue;
    // Ensure all store chains are the same (so they don't alias).
    if (StoresInChain && ST->getChain() != StoresInChain)
      continue;
    // Ensure the store is properly aligned.
    Type *StoreType = StoreValue.getValueType().getTypeForEVT(Ctx);
    if (ST->getAlign() <
        getDataLayout().getABITypeAlign(StoreType->getScalarType()))
      continue;
    // Avoid:
    //  1. Creating cyclic dependencies.
    //  2. Expanding the node to a call within a call sequence.
    if (!canFoldStoreIntoLibCallOutputPointers(ST, Node))
      continue;
    ResultStores[ResNo] = ST;
    StoresInChain = ST->getChain();
  }

  TargetLowering::ArgListTy Args;
  auto AddArgListEntry = [&](SDValue Node, Type *Ty) {
    TargetLowering::ArgListEntry Entry{};
    Entry.Ty = Ty;
    Entry.Node = Node;
    Args.push_back(Entry);
  };

  // Pass the arguments.
  for (const SDValue &Op : Node->op_values()) {
    EVT ArgVT = Op.getValueType();
    Type *ArgTy = ArgVT.getTypeForEVT(Ctx);
    AddArgListEntry(Op, ArgTy);
  }

  // Pass the output pointers.
  SmallVector<SDValue, 2> ResultPtrs(NumResults);
  Type *PointerTy = PointerType::getUnqual(Ctx);
  for (auto [ResNo, ST] : llvm::enumerate(ResultStores)) {
    if (ResNo == CallRetResNo)
      continue;
    EVT ResVT = Node->getValueType(ResNo);
    SDValue ResultPtr = ST ? ST->getBasePtr() : CreateStackTemporary(ResVT);
    ResultPtrs[ResNo] = ResultPtr;
    AddArgListEntry(ResultPtr, PointerTy);
  }

  SDLoc DL(Node);

  // Pass the vector mask (if required).
  if (VD && VD->isMasked()) {
    EVT MaskVT = TLI->getSetCCResultType(getDataLayout(), Ctx, VT);
    SDValue Mask = getBoolConstant(true, DL, MaskVT, VT);
    AddArgListEntry(Mask, MaskVT.getTypeForEVT(Ctx));
  }

  Type *RetType = CallRetResNo.has_value()
                      ? Node->getValueType(*CallRetResNo).getTypeForEVT(Ctx)
                      : Type::getVoidTy(Ctx);
  SDValue InChain = StoresInChain ? StoresInChain : getEntryNode();
  SDValue Callee = getExternalSymbol(VD ? VD->getVectorFnName().data() : LCName,
                                     TLI->getPointerTy(getDataLayout()));
  TargetLowering::CallLoweringInfo CLI(*this);
  CLI.setDebugLoc(DL).setChain(InChain).setLibCallee(
      TLI->getLibcallCallingConv(LC), RetType, Callee, std::move(Args));

  auto [Call, CallChain] = TLI->LowerCallTo(CLI);

  for (auto [ResNo, ResultPtr] : llvm::enumerate(ResultPtrs)) {
    if (ResNo == CallRetResNo) {
      Results.push_back(Call);
      continue;
    }
    MachinePointerInfo PtrInfo;
    SDValue LoadResult =
        getLoad(Node->getValueType(ResNo), DL, CallChain, ResultPtr, PtrInfo);
    SDValue OutChain = LoadResult.getValue(1);

    if (StoreSDNode *ST = ResultStores[ResNo]) {
      // Replace store with the library call.
      ReplaceAllUsesOfValueWith(SDValue(ST, 0), OutChain);
      PtrInfo = ST->getPointerInfo();
    } else {
      PtrInfo = MachinePointerInfo::getFixedStack(
          getMachineFunction(), cast<FrameIndexSDNode>(ResultPtr)->getIndex());
    }

    Results.push_back(LoadResult);
  }

  return true;
}

SDValue SelectionDAG::expandVAArg(SDNode *Node) {
  SDLoc dl(Node);
  const TargetLowering &TLI = getTargetLoweringInfo();
  const Value *V = cast<SrcValueSDNode>(Node->getOperand(2))->getValue();
  EVT VT = Node->getValueType(0);
  SDValue Tmp1 = Node->getOperand(0);
  SDValue Tmp2 = Node->getOperand(1);
  const MaybeAlign MA(Node->getConstantOperandVal(3));

  SDValue VAListLoad = getLoad(TLI.getPointerTy(getDataLayout()), dl, Tmp1,
                               Tmp2, MachinePointerInfo(V));
  SDValue VAList = VAListLoad;

  if (MA && *MA > TLI.getMinStackArgumentAlignment()) {
    VAList = getNode(ISD::ADD, dl, VAList.getValueType(), VAList,
                     getConstant(MA->value() - 1, dl, VAList.getValueType()));

    VAList = getNode(
        ISD::AND, dl, VAList.getValueType(), VAList,
        getSignedConstant(-(int64_t)MA->value(), dl, VAList.getValueType()));
  }

  // Increment the pointer, VAList, to the next vaarg
  Tmp1 = getNode(ISD::ADD, dl, VAList.getValueType(), VAList,
                 getConstant(getDataLayout().getTypeAllocSize(
                                               VT.getTypeForEVT(*getContext())),
                             dl, VAList.getValueType()));
  // Store the incremented VAList to the legalized pointer
  Tmp1 =
      getStore(VAListLoad.getValue(1), dl, Tmp1, Tmp2, MachinePointerInfo(V));
  // Load the actual argument out of the pointer VAList
  return getLoad(VT, dl, Tmp1, VAList, MachinePointerInfo());
}

SDValue SelectionDAG::expandVACopy(SDNode *Node) {
  SDLoc dl(Node);
  const TargetLowering &TLI = getTargetLoweringInfo();
  // This defaults to loading a pointer from the input and storing it to the
  // output, returning the chain.
  const Value *VD = cast<SrcValueSDNode>(Node->getOperand(3))->getValue();
  const Value *VS = cast<SrcValueSDNode>(Node->getOperand(4))->getValue();
  SDValue Tmp1 =
      getLoad(TLI.getPointerTy(getDataLayout()), dl, Node->getOperand(0),
              Node->getOperand(2), MachinePointerInfo(VS));
  return getStore(Tmp1.getValue(1), dl, Tmp1, Node->getOperand(1),
                  MachinePointerInfo(VD));
}

Align SelectionDAG::getReducedAlign(EVT VT, bool UseABI) {
  const DataLayout &DL = getDataLayout();
  Type *Ty = VT.getTypeForEVT(*getContext());
  Align RedAlign = UseABI ? DL.getABITypeAlign(Ty) : DL.getPrefTypeAlign(Ty);

  if (TLI->isTypeLegal(VT) || !VT.isVector())
    return RedAlign;

  const TargetFrameLowering *TFI = MF->getSubtarget().getFrameLowering();
  const Align StackAlign = TFI->getStackAlign();

  // See if we can choose a smaller ABI alignment in cases where it's an
  // illegal vector type that will get broken down.
  if (RedAlign > StackAlign) {
    EVT IntermediateVT;
    MVT RegisterVT;
    unsigned NumIntermediates;
    TLI->getVectorTypeBreakdown(*getContext(), VT, IntermediateVT,
                                NumIntermediates, RegisterVT);
    Ty = IntermediateVT.getTypeForEVT(*getContext());
    Align RedAlign2 = UseABI ? DL.getABITypeAlign(Ty) : DL.getPrefTypeAlign(Ty);
    if (RedAlign2 < RedAlign)
      RedAlign = RedAlign2;

    if (!getMachineFunction().getFrameInfo().isStackRealignable())
      // If the stack is not realignable, the alignment should be limited to the
      // StackAlignment
      RedAlign = std::min(RedAlign, StackAlign);
  }

  return RedAlign;
}

SDValue SelectionDAG::CreateStackTemporary(TypeSize Bytes, Align Alignment) {
  MachineFrameInfo &MFI = MF->getFrameInfo();
  const TargetFrameLowering *TFI = MF->getSubtarget().getFrameLowering();
  int StackID = 0;
  if (Bytes.isScalable())
    StackID = TFI->getStackIDForScalableVectors();
  // The stack id gives an indication of whether the object is scalable or
  // not, so it's safe to pass in the minimum size here.
  int FrameIdx = MFI.CreateStackObject(Bytes.getKnownMinValue(), Alignment,
                                       false, nullptr, StackID);
  return getFrameIndex(FrameIdx, TLI->getFrameIndexTy(getDataLayout()));
}

SDValue SelectionDAG::CreateStackTemporary(EVT VT, unsigned minAlign) {
  Type *Ty = VT.getTypeForEVT(*getContext());
  Align StackAlign =
      std::max(getDataLayout().getPrefTypeAlign(Ty), Align(minAlign));
  return CreateStackTemporary(VT.getStoreSize(), StackAlign);
}

SDValue SelectionDAG::CreateStackTemporary(EVT VT1, EVT VT2) {
  TypeSize VT1Size = VT1.getStoreSize();
  TypeSize VT2Size = VT2.getStoreSize();
  assert(VT1Size.isScalable() == VT2Size.isScalable() &&
         "Don't know how to choose the maximum size when creating a stack "
         "temporary");
  TypeSize Bytes = VT1Size.getKnownMinValue() > VT2Size.getKnownMinValue()
                       ? VT1Size
                       : VT2Size;

  Type *Ty1 = VT1.getTypeForEVT(*getContext());
  Type *Ty2 = VT2.getTypeForEVT(*getContext());
  const DataLayout &DL = getDataLayout();
  Align Align = std::max(DL.getPrefTypeAlign(Ty1), DL.getPrefTypeAlign(Ty2));
  return CreateStackTemporary(Bytes, Align);
}

SDValue SelectionDAG::FoldSetCC(EVT VT, SDValue N1, SDValue N2,
                                ISD::CondCode Cond, const SDLoc &dl) {
  EVT OpVT = N1.getValueType();

  auto GetUndefBooleanConstant = [&]() {
    if (VT.getScalarType() == MVT::i1 ||
        TLI->getBooleanContents(OpVT) ==
            TargetLowering::UndefinedBooleanContent)
      return getUNDEF(VT);
    // ZeroOrOne / ZeroOrNegative require specific values for the high bits,
    // so we cannot use getUNDEF(). Return zero instead.
    return getConstant(0, dl, VT);
  };

  // These setcc operations always fold.
  switch (Cond) {
  default: break;
  case ISD::SETFALSE:
  case ISD::SETFALSE2: return getBoolConstant(false, dl, VT, OpVT);
  case ISD::SETTRUE:
  case ISD::SETTRUE2: return getBoolConstant(true, dl, VT, OpVT);

  case ISD::SETOEQ:
  case ISD::SETOGT:
  case ISD::SETOGE:
  case ISD::SETOLT:
  case ISD::SETOLE:
  case ISD::SETONE:
  case ISD::SETO:
  case ISD::SETUO:
  case ISD::SETUEQ:
  case ISD::SETUNE:
    assert(!OpVT.isInteger() && "Illegal setcc for integer!");
    break;
  }

  if (OpVT.isInteger()) {
    // For EQ and NE, we can always pick a value for the undef to make the
    // predicate pass or fail, so we can return undef.
    // Matches behavior in llvm::ConstantFoldCompareInstruction.
    // icmp eq/ne X, undef -> undef.
    if ((N1.isUndef() || N2.isUndef()) &&
        (Cond == ISD::SETEQ || Cond == ISD::SETNE))
      return GetUndefBooleanConstant();

    // If both operands are undef, we can return undef for int comparison.
    // icmp undef, undef -> undef.
    if (N1.isUndef() && N2.isUndef())
      return GetUndefBooleanConstant();

    // icmp X, X -> true/false
    // icmp X, undef -> true/false because undef could be X.
    if (N1.isUndef() || N2.isUndef() || N1 == N2)
      return getBoolConstant(ISD::isTrueWhenEqual(Cond), dl, VT, OpVT);
  }

  if (ConstantSDNode *N2C = dyn_cast<ConstantSDNode>(N2)) {
    const APInt &C2 = N2C->getAPIntValue();
    if (ConstantSDNode *N1C = dyn_cast<ConstantSDNode>(N1)) {
      const APInt &C1 = N1C->getAPIntValue();

      return getBoolConstant(ICmpInst::compare(C1, C2, getICmpCondCode(Cond)),
                             dl, VT, OpVT);
    }
  }

  auto *N1CFP = dyn_cast<ConstantFPSDNode>(N1);
  auto *N2CFP = dyn_cast<ConstantFPSDNode>(N2);

  if (N1CFP && N2CFP) {
    APFloat::cmpResult R = N1CFP->getValueAPF().compare(N2CFP->getValueAPF());
    switch (Cond) {
    default: break;
    case ISD::SETEQ:  if (R==APFloat::cmpUnordered)
                        return GetUndefBooleanConstant();
                      [[fallthrough]];
    case ISD::SETOEQ: return getBoolConstant(R==APFloat::cmpEqual, dl, VT,
                                             OpVT);
    case ISD::SETNE:  if (R==APFloat::cmpUnordered)
                        return GetUndefBooleanConstant();
                      [[fallthrough]];
    case ISD::SETONE: return getBoolConstant(R==APFloat::cmpGreaterThan ||
                                             R==APFloat::cmpLessThan, dl, VT,
                                             OpVT);
    case ISD::SETLT:  if (R==APFloat::cmpUnordered)
                        return GetUndefBooleanConstant();
                      [[fallthrough]];
    case ISD::SETOLT: return getBoolConstant(R==APFloat::cmpLessThan, dl, VT,
                                             OpVT);
    case ISD::SETGT:  if (R==APFloat::cmpUnordered)
                        return GetUndefBooleanConstant();
                      [[fallthrough]];
    case ISD::SETOGT: return getBoolConstant(R==APFloat::cmpGreaterThan, dl,
                                             VT, OpVT);
    case ISD::SETLE:  if (R==APFloat::cmpUnordered)
                        return GetUndefBooleanConstant();
                      [[fallthrough]];
    case ISD::SETOLE: return getBoolConstant(R==APFloat::cmpLessThan ||
                                             R==APFloat::cmpEqual, dl, VT,
                                             OpVT);
    case ISD::SETGE:  if (R==APFloat::cmpUnordered)
                        return GetUndefBooleanConstant();
                      [[fallthrough]];
    case ISD::SETOGE: return getBoolConstant(R==APFloat::cmpGreaterThan ||
                                         R==APFloat::cmpEqual, dl, VT, OpVT);
    case ISD::SETO:   return getBoolConstant(R!=APFloat::cmpUnordered, dl, VT,
                                             OpVT);
    case ISD::SETUO:  return getBoolConstant(R==APFloat::cmpUnordered, dl, VT,
                                             OpVT);
    case ISD::SETUEQ: return getBoolConstant(R==APFloat::cmpUnordered ||
                                             R==APFloat::cmpEqual, dl, VT,
                                             OpVT);
    case ISD::SETUNE: return getBoolConstant(R!=APFloat::cmpEqual, dl, VT,
                                             OpVT);
    case ISD::SETULT: return getBoolConstant(R==APFloat::cmpUnordered ||
                                             R==APFloat::cmpLessThan, dl, VT,
                                             OpVT);
    case ISD::SETUGT: return getBoolConstant(R==APFloat::cmpGreaterThan ||
                                             R==APFloat::cmpUnordered, dl, VT,
                                             OpVT);
    case ISD::SETULE: return getBoolConstant(R!=APFloat::cmpGreaterThan, dl,
                                             VT, OpVT);
    case ISD::SETUGE: return getBoolConstant(R!=APFloat::cmpLessThan, dl, VT,
                                             OpVT);
    }
  } else if (N1CFP && OpVT.isSimple() && !N2.isUndef()) {
    // Ensure that the constant occurs on the RHS.
    ISD::CondCode SwappedCond = ISD::getSetCCSwappedOperands(Cond);
    if (!TLI->isCondCodeLegal(SwappedCond, OpVT.getSimpleVT()))
      return SDValue();
    return getSetCC(dl, VT, N2, N1, SwappedCond);
  } else if ((N2CFP && N2CFP->getValueAPF().isNaN()) ||
             (OpVT.isFloatingPoint() && (N1.isUndef() || N2.isUndef()))) {
    // If an operand is known to be a nan (or undef that could be a nan), we can
    // fold it.
    // Choosing NaN for the undef will always make unordered comparison succeed
    // and ordered comparison fails.
    // Matches behavior in llvm::ConstantFoldCompareInstruction.
    switch (ISD::getUnorderedFlavor(Cond)) {
    default:
      llvm_unreachable("Unknown flavor!");
    case 0: // Known false.
      return getBoolConstant(false, dl, VT, OpVT);
    case 1: // Known true.
      return getBoolConstant(true, dl, VT, OpVT);
    case 2: // Undefined.
      return GetUndefBooleanConstant();
    }
  }

  // Could not fold it.
  return SDValue();
}

/// SignBitIsZero - Return true if the sign bit of Op is known to be zero.  We
/// use this predicate to simplify operations downstream.
bool SelectionDAG::SignBitIsZero(SDValue Op, unsigned Depth) const {
  unsigned BitWidth = Op.getScalarValueSizeInBits();
  return MaskedValueIsZero(Op, APInt::getSignMask(BitWidth), Depth);
}

/// MaskedValueIsZero - Return true if 'V & Mask' is known to be zero.  We use
/// this predicate to simplify operations downstream.  Mask is known to be zero
/// for bits that V cannot have.
bool SelectionDAG::MaskedValueIsZero(SDValue V, const APInt &Mask,
                                     unsigned Depth) const {
  return Mask.isSubsetOf(computeKnownBits(V, Depth).Zero);
}

/// MaskedValueIsZero - Return true if 'V & Mask' is known to be zero in
/// DemandedElts.  We use this predicate to simplify operations downstream.
/// Mask is known to be zero for bits that V cannot have.
bool SelectionDAG::MaskedValueIsZero(SDValue V, const APInt &Mask,
                                     const APInt &DemandedElts,
                                     unsigned Depth) const {
  return Mask.isSubsetOf(computeKnownBits(V, DemandedElts, Depth).Zero);
}

/// MaskedVectorIsZero - Return true if 'Op' is known to be zero in
/// DemandedElts.  We use this predicate to simplify operations downstream.
bool SelectionDAG::MaskedVectorIsZero(SDValue V, const APInt &DemandedElts,
                                      unsigned Depth /* = 0 */) const {
  return computeKnownBits(V, DemandedElts, Depth).isZero();
}

/// MaskedValueIsAllOnes - Return true if '(Op & Mask) == Mask'.
bool SelectionDAG::MaskedValueIsAllOnes(SDValue V, const APInt &Mask,
                                        unsigned Depth) const {
  return Mask.isSubsetOf(computeKnownBits(V, Depth).One);
}

APInt SelectionDAG::computeVectorKnownZeroElements(SDValue Op,
                                                   const APInt &DemandedElts,
                                                   unsigned Depth) const {
  EVT VT = Op.getValueType();
  assert(VT.isVector() && !VT.isScalableVector() && "Only for fixed vectors!");

  unsigned NumElts = VT.getVectorNumElements();
  assert(DemandedElts.getBitWidth() == NumElts && "Unexpected demanded mask.");

  APInt KnownZeroElements = APInt::getZero(NumElts);
  for (unsigned EltIdx = 0; EltIdx != NumElts; ++EltIdx) {
    if (!DemandedElts[EltIdx])
      continue; // Don't query elements that are not demanded.
    APInt Mask = APInt::getOneBitSet(NumElts, EltIdx);
    if (MaskedVectorIsZero(Op, Mask, Depth))
      KnownZeroElements.setBit(EltIdx);
  }
  return KnownZeroElements;
}

/// isSplatValue - Return true if the vector V has the same value
/// across all DemandedElts. For scalable vectors, we don't know the
/// number of lanes at compile time.  Instead, we use a 1 bit APInt
/// to represent a conservative value for all lanes; that is, that
/// one bit value is implicitly splatted across all lanes.
bool SelectionDAG::isSplatValue(SDValue V, const APInt &DemandedElts,
                                APInt &UndefElts, unsigned Depth) const {
  unsigned Opcode = V.getOpcode();
  EVT VT = V.getValueType();
  assert(VT.isVector() && "Vector type expected");
  assert((!VT.isScalableVector() || DemandedElts.getBitWidth() == 1) &&
         "scalable demanded bits are ignored");

  if (!DemandedElts)
    return false; // No demanded elts, better to assume we don't know anything.

  if (Depth >= MaxRecursionDepth)
    return false; // Limit search depth.

  // Deal with some common cases here that work for both fixed and scalable
  // vector types.
  switch (Opcode) {
  case ISD::SPLAT_VECTOR:
    UndefElts = V.getOperand(0).isUndef()
                    ? APInt::getAllOnes(DemandedElts.getBitWidth())
                    : APInt(DemandedElts.getBitWidth(), 0);
    return true;
  case ISD::ADD:
  case ISD::SUB:
  case ISD::AND:
  case ISD::XOR:
  case ISD::OR: {
    APInt UndefLHS, UndefRHS;
    SDValue LHS = V.getOperand(0);
    SDValue RHS = V.getOperand(1);
    // Only recognize splats with the same demanded undef elements for both
    // operands, otherwise we might fail to handle binop-specific undef
    // handling.
    // e.g. (and undef, 0) -> 0 etc.
    if (isSplatValue(LHS, DemandedElts, UndefLHS, Depth + 1) &&
        isSplatValue(RHS, DemandedElts, UndefRHS, Depth + 1) &&
        (DemandedElts & UndefLHS) == (DemandedElts & UndefRHS)) {
      UndefElts = UndefLHS | UndefRHS;
      return true;
    }
    return false;
  }
  case ISD::ABS:
  case ISD::TRUNCATE:
  case ISD::SIGN_EXTEND:
  case ISD::ZERO_EXTEND:
    return isSplatValue(V.getOperand(0), DemandedElts, UndefElts, Depth + 1);
  default:
    if (Opcode >= ISD::BUILTIN_OP_END || Opcode == ISD::INTRINSIC_WO_CHAIN ||
        Opcode == ISD::INTRINSIC_W_CHAIN || Opcode == ISD::INTRINSIC_VOID)
      return TLI->isSplatValueForTargetNode(V, DemandedElts, UndefElts, *this,
                                            Depth);
    break;
  }

  // We don't support other cases than those above for scalable vectors at
  // the moment.
  if (VT.isScalableVector())
    return false;

  unsigned NumElts = VT.getVectorNumElements();
  assert(NumElts == DemandedElts.getBitWidth() && "Vector size mismatch");
  UndefElts = APInt::getZero(NumElts);

  switch (Opcode) {
  case ISD::BUILD_VECTOR: {
    SDValue Scl;
    for (unsigned i = 0; i != NumElts; ++i) {
      SDValue Op = V.getOperand(i);
      if (Op.isUndef()) {
        UndefElts.setBit(i);
        continue;
      }
      if (!DemandedElts[i])
        continue;
      if (Scl && Scl != Op)
        return false;
      Scl = Op;
    }
    return true;
  }
  case ISD::VECTOR_SHUFFLE: {
    // Check if this is a shuffle node doing a splat or a shuffle of a splat.
    APInt DemandedLHS = APInt::getZero(NumElts);
    APInt DemandedRHS = APInt::getZero(NumElts);
    ArrayRef<int> Mask = cast<ShuffleVectorSDNode>(V)->getMask();
    for (int i = 0; i != (int)NumElts; ++i) {
      int M = Mask[i];
      if (M < 0) {
        UndefElts.setBit(i);
        continue;
      }
      if (!DemandedElts[i])
        continue;
      if (M < (int)NumElts)
        DemandedLHS.setBit(M);
      else
        DemandedRHS.setBit(M - NumElts);
    }

    // If we aren't demanding either op, assume there's no splat.
    // If we are demanding both ops, assume there's no splat.
    if ((DemandedLHS.isZero() && DemandedRHS.isZero()) ||
        (!DemandedLHS.isZero() && !DemandedRHS.isZero()))
      return false;

    // See if the demanded elts of the source op is a splat or we only demand
    // one element, which should always be a splat.
    // TODO: Handle source ops splats with undefs.
    auto CheckSplatSrc = [&](SDValue Src, const APInt &SrcElts) {
      APInt SrcUndefs;
      return (SrcElts.popcount() == 1) ||
             (isSplatValue(Src, SrcElts, SrcUndefs, Depth + 1) &&
              (SrcElts & SrcUndefs).isZero());
    };
    if (!DemandedLHS.isZero())
      return CheckSplatSrc(V.getOperand(0), DemandedLHS);
    return CheckSplatSrc(V.getOperand(1), DemandedRHS);
  }
  case ISD::EXTRACT_SUBVECTOR: {
    // Offset the demanded elts by the subvector index.
    SDValue Src = V.getOperand(0);
    // We don't support scalable vectors at the moment.
    if (Src.getValueType().isScalableVector())
      return false;
    uint64_t Idx = V.getConstantOperandVal(1);
    unsigned NumSrcElts = Src.getValueType().getVectorNumElements();
    APInt UndefSrcElts;
    APInt DemandedSrcElts = DemandedElts.zext(NumSrcElts).shl(Idx);
    if (isSplatValue(Src, DemandedSrcElts, UndefSrcElts, Depth + 1)) {
      UndefElts = UndefSrcElts.extractBits(NumElts, Idx);
      return true;
    }
    break;
  }
  case ISD::ANY_EXTEND_VECTOR_INREG:
  case ISD::SIGN_EXTEND_VECTOR_INREG:
  case ISD::ZERO_EXTEND_VECTOR_INREG: {
    // Widen the demanded elts by the src element count.
    SDValue Src = V.getOperand(0);
    // We don't support scalable vectors at the moment.
    if (Src.getValueType().isScalableVector())
      return false;
    unsigned NumSrcElts = Src.getValueType().getVectorNumElements();
    APInt UndefSrcElts;
    APInt DemandedSrcElts = DemandedElts.zext(NumSrcElts);
    if (isSplatValue(Src, DemandedSrcElts, UndefSrcElts, Depth + 1)) {
      UndefElts = UndefSrcElts.trunc(NumElts);
      return true;
    }
    break;
  }
  case ISD::BITCAST: {
    SDValue Src = V.getOperand(0);
    EVT SrcVT = Src.getValueType();
    unsigned SrcBitWidth = SrcVT.getScalarSizeInBits();
    unsigned BitWidth = VT.getScalarSizeInBits();

    // Ignore bitcasts from unsupported types.
    // TODO: Add fp support?
    if (!SrcVT.isVector() || !SrcVT.isInteger() || !VT.isInteger())
      break;

    // Bitcast 'small element' vector to 'large element' vector.
    if ((BitWidth % SrcBitWidth) == 0) {
      // See if each sub element is a splat.
      unsigned Scale = BitWidth / SrcBitWidth;
      unsigned NumSrcElts = SrcVT.getVectorNumElements();
      APInt ScaledDemandedElts =
          APIntOps::ScaleBitMask(DemandedElts, NumSrcElts);
      for (unsigned I = 0; I != Scale; ++I) {
        APInt SubUndefElts;
        APInt SubDemandedElt = APInt::getOneBitSet(Scale, I);
        APInt SubDemandedElts = APInt::getSplat(NumSrcElts, SubDemandedElt);
        SubDemandedElts &= ScaledDemandedElts;
        if (!isSplatValue(Src, SubDemandedElts, SubUndefElts, Depth + 1))
          return false;
        // TODO: Add support for merging sub undef elements.
        if (!SubUndefElts.isZero())
          return false;
      }
      return true;
    }
    break;
  }
  }

  return false;
}

/// Helper wrapper to main isSplatValue function.
bool SelectionDAG::isSplatValue(SDValue V, bool AllowUndefs) const {
  EVT VT = V.getValueType();
  assert(VT.isVector() && "Vector type expected");

  APInt UndefElts;
  // Since the number of lanes in a scalable vector is unknown at compile time,
  // we track one bit which is implicitly broadcast to all lanes.  This means
  // that all lanes in a scalable vector are considered demanded.
  APInt DemandedElts
    = APInt::getAllOnes(VT.isScalableVector() ? 1 : VT.getVectorNumElements());
  return isSplatValue(V, DemandedElts, UndefElts) &&
         (AllowUndefs || !UndefElts);
}

SDValue SelectionDAG::getSplatSourceVector(SDValue V, int &SplatIdx) {
  V = peekThroughExtractSubvectors(V);

  EVT VT = V.getValueType();
  unsigned Opcode = V.getOpcode();
  switch (Opcode) {
  default: {
    APInt UndefElts;
    // Since the number of lanes in a scalable vector is unknown at compile time,
    // we track one bit which is implicitly broadcast to all lanes.  This means
    // that all lanes in a scalable vector are considered demanded.
    APInt DemandedElts
      = APInt::getAllOnes(VT.isScalableVector() ? 1 : VT.getVectorNumElements());

    if (isSplatValue(V, DemandedElts, UndefElts)) {
      if (VT.isScalableVector()) {
        // DemandedElts and UndefElts are ignored for scalable vectors, since
        // the only supported cases are SPLAT_VECTOR nodes.
        SplatIdx = 0;
      } else {
        // Handle case where all demanded elements are UNDEF.
        if (DemandedElts.isSubsetOf(UndefElts)) {
          SplatIdx = 0;
          return getUNDEF(VT);
        }
        SplatIdx = (UndefElts & DemandedElts).countr_one();
      }
      return V;
    }
    break;
  }
  case ISD::SPLAT_VECTOR:
    SplatIdx = 0;
    return V;
  case ISD::VECTOR_SHUFFLE: {
    assert(!VT.isScalableVector());
    // Check if this is a shuffle node doing a splat.
    // TODO - remove this and rely purely on SelectionDAG::isSplatValue,
    // getTargetVShiftNode currently struggles without the splat source.
    auto *SVN = cast<ShuffleVectorSDNode>(V);
    if (!SVN->isSplat())
      break;
    int Idx = SVN->getSplatIndex();
    int NumElts = V.getValueType().getVectorNumElements();
    SplatIdx = Idx % NumElts;
    return V.getOperand(Idx / NumElts);
  }
  }

  return SDValue();
}

SDValue SelectionDAG::getSplatValue(SDValue V, bool LegalTypes) {
  int SplatIdx;
  if (SDValue SrcVector = getSplatSourceVector(V, SplatIdx)) {
    EVT SVT = SrcVector.getValueType().getScalarType();
    EVT LegalSVT = SVT;
    if (LegalTypes && !TLI->isTypeLegal(SVT)) {
      if (!SVT.isInteger())
        return SDValue();
      LegalSVT = TLI->getTypeToTransformTo(*getContext(), LegalSVT);
      if (LegalSVT.bitsLT(SVT))
        return SDValue();
    }
    return getExtractVectorElt(SDLoc(V), LegalSVT, SrcVector, SplatIdx);
  }
  return SDValue();
}

std::optional<ConstantRange>
SelectionDAG::getValidShiftAmountRange(SDValue V, const APInt &DemandedElts,
                                       unsigned Depth) const {
  assert((V.getOpcode() == ISD::SHL || V.getOpcode() == ISD::SRL ||
          V.getOpcode() == ISD::SRA) &&
         "Unknown shift node");
  // Shifting more than the bitwidth is not valid.
  unsigned BitWidth = V.getScalarValueSizeInBits();

  if (auto *Cst = dyn_cast<ConstantSDNode>(V.getOperand(1))) {
    const APInt &ShAmt = Cst->getAPIntValue();
    if (ShAmt.uge(BitWidth))
      return std::nullopt;
    return ConstantRange(ShAmt);
  }

  if (auto *BV = dyn_cast<BuildVectorSDNode>(V.getOperand(1))) {
    const APInt *MinAmt = nullptr, *MaxAmt = nullptr;
    for (unsigned i = 0, e = BV->getNumOperands(); i != e; ++i) {
      if (!DemandedElts[i])
        continue;
      auto *SA = dyn_cast<ConstantSDNode>(BV->getOperand(i));
      if (!SA) {
        MinAmt = MaxAmt = nullptr;
        break;
      }
      const APInt &ShAmt = SA->getAPIntValue();
      if (ShAmt.uge(BitWidth))
        return std::nullopt;
      if (!MinAmt || MinAmt->ugt(ShAmt))
        MinAmt = &ShAmt;
      if (!MaxAmt || MaxAmt->ult(ShAmt))
        MaxAmt = &ShAmt;
    }
    assert(((!MinAmt && !MaxAmt) || (MinAmt && MaxAmt)) &&
           "Failed to find matching min/max shift amounts");
    if (MinAmt && MaxAmt)
      return ConstantRange(*MinAmt, *MaxAmt + 1);
  }

  // Use computeKnownBits to find a hidden constant/knownbits (usually type
  // legalized). e.g. Hidden behind multiple bitcasts/build_vector/casts etc.
  KnownBits KnownAmt = computeKnownBits(V.getOperand(1), DemandedElts, Depth);
  if (KnownAmt.getMaxValue().ult(BitWidth))
    return ConstantRange::fromKnownBits(KnownAmt, /*IsSigned=*/false);

  return std::nullopt;
}

std::optional<uint64_t>
SelectionDAG::getValidShiftAmount(SDValue V, const APInt &DemandedElts,
                                  unsigned Depth) const {
  assert((V.getOpcode() == ISD::SHL || V.getOpcode() == ISD::SRL ||
          V.getOpcode() == ISD::SRA) &&
         "Unknown shift node");
  if (std::optional<ConstantRange> AmtRange =
          getValidShiftAmountRange(V, DemandedElts, Depth))
    if (const APInt *ShAmt = AmtRange->getSingleElement())
      return ShAmt->getZExtValue();
  return std::nullopt;
}

std::optional<uint64_t>
SelectionDAG::getValidShiftAmount(SDValue V, unsigned Depth) const {
  EVT VT = V.getValueType();
  APInt DemandedElts = VT.isFixedLengthVector()
                           ? APInt::getAllOnes(VT.getVectorNumElements())
                           : APInt(1, 1);
  return getValidShiftAmount(V, DemandedElts, Depth);
}

std::optional<uint64_t>
SelectionDAG::getValidMinimumShiftAmount(SDValue V, const APInt &DemandedElts,
                                         unsigned Depth) const {
  assert((V.getOpcode() == ISD::SHL || V.getOpcode() == ISD::SRL ||
          V.getOpcode() == ISD::SRA) &&
         "Unknown shift node");
  if (std::optional<ConstantRange> AmtRange =
          getValidShiftAmountRange(V, DemandedElts, Depth))
    return AmtRange->getUnsignedMin().getZExtValue();
  return std::nullopt;
}

std::optional<uint64_t>
SelectionDAG::getValidMinimumShiftAmount(SDValue V, unsigned Depth) const {
  EVT VT = V.getValueType();
  APInt DemandedElts = VT.isFixedLengthVector()
                           ? APInt::getAllOnes(VT.getVectorNumElements())
                           : APInt(1, 1);
  return getValidMinimumShiftAmount(V, DemandedElts, Depth);
}

std::optional<uint64_t>
SelectionDAG::getValidMaximumShiftAmount(SDValue V, const APInt &DemandedElts,
                                         unsigned Depth) const {
  assert((V.getOpcode() == ISD::SHL || V.getOpcode() == ISD::SRL ||
          V.getOpcode() == ISD::SRA) &&
         "Unknown shift node");
  if (std::optional<ConstantRange> AmtRange =
          getValidShiftAmountRange(V, DemandedElts, Depth))
    return AmtRange->getUnsignedMax().getZExtValue();
  return std::nullopt;
}

std::optional<uint64_t>
SelectionDAG::getValidMaximumShiftAmount(SDValue V, unsigned Depth) const {
  EVT VT = V.getValueType();
  APInt DemandedElts = VT.isFixedLengthVector()
                           ? APInt::getAllOnes(VT.getVectorNumElements())
                           : APInt(1, 1);
  return getValidMaximumShiftAmount(V, DemandedElts, Depth);
}

/// Determine which bits of Op are known to be either zero or one and return
/// them in Known. For vectors, the known bits are those that are shared by
/// every vector element.
KnownBits SelectionDAG::computeKnownBits(SDValue Op, unsigned Depth) const {
  EVT VT = Op.getValueType();

  // Since the number of lanes in a scalable vector is unknown at compile time,
  // we track one bit which is implicitly broadcast to all lanes.  This means
  // that all lanes in a scalable vector are considered demanded.
  APInt DemandedElts = VT.isFixedLengthVector()
                           ? APInt::getAllOnes(VT.getVectorNumElements())
                           : APInt(1, 1);
  return computeKnownBits(Op, DemandedElts, Depth);
}

/// Determine which bits of Op are known to be either zero or one and return
/// them in Known. The DemandedElts argument allows us to only collect the known
/// bits that are shared by the requested vector elements.
KnownBits SelectionDAG::computeKnownBits(SDValue Op, const APInt &DemandedElts,
                                         unsigned Depth) const {
  unsigned BitWidth = Op.getScalarValueSizeInBits();

  KnownBits Known(BitWidth);   // Don't know anything.

  if (auto OptAPInt = Op->bitcastToAPInt()) {
    // We know all of the bits for a constant!
    return KnownBits::makeConstant(*std::move(OptAPInt));
  }

  if (Depth >= MaxRecursionDepth)
    return Known;  // Limit search depth.

  KnownBits Known2;
  unsigned NumElts = DemandedElts.getBitWidth();
  assert((!Op.getValueType().isFixedLengthVector() ||
          NumElts == Op.getValueType().getVectorNumElements()) &&
         "Unexpected vector size");

  if (!DemandedElts)
    return Known;  // No demanded elts, better to assume we don't know anything.

  unsigned Opcode = Op.getOpcode();
  switch (Opcode) {
  case ISD::MERGE_VALUES:
    return computeKnownBits(Op.getOperand(Op.getResNo()), DemandedElts,
                            Depth + 1);
  case ISD::SPLAT_VECTOR: {
    SDValue SrcOp = Op.getOperand(0);
    assert(SrcOp.getValueSizeInBits() >= BitWidth &&
           "Expected SPLAT_VECTOR implicit truncation");
    // Implicitly truncate the bits to match the official semantics of
    // SPLAT_VECTOR.
    Known = computeKnownBits(SrcOp, Depth + 1).trunc(BitWidth);
    break;
  }
  case ISD::SPLAT_VECTOR_PARTS: {
    unsigned ScalarSize = Op.getOperand(0).getScalarValueSizeInBits();
    assert(ScalarSize * Op.getNumOperands() == BitWidth &&
           "Expected SPLAT_VECTOR_PARTS scalars to cover element width");
    for (auto [I, SrcOp] : enumerate(Op->ops())) {
      Known.insertBits(computeKnownBits(SrcOp, Depth + 1), ScalarSize * I);
    }
    break;
  }
  case ISD::STEP_VECTOR: {
    const APInt &Step = Op.getConstantOperandAPInt(0);

    if (Step.isPowerOf2())
      Known.Zero.setLowBits(Step.logBase2());

    const Function &F = getMachineFunction().getFunction();

    if (!isUIntN(BitWidth, Op.getValueType().getVectorMinNumElements()))
      break;
    const APInt MinNumElts =
        APInt(BitWidth, Op.getValueType().getVectorMinNumElements());

    bool Overflow;
    const APInt MaxNumElts = getVScaleRange(&F, BitWidth)
                                 .getUnsignedMax()
                                 .umul_ov(MinNumElts, Overflow);
    if (Overflow)
      break;

    const APInt MaxValue = (MaxNumElts - 1).umul_ov(Step, Overflow);
    if (Overflow)
      break;

    Known.Zero.setHighBits(MaxValue.countl_zero());
    break;
  }
  case ISD::BUILD_VECTOR:
    assert(!Op.getValueType().isScalableVector());
    // Collect the known bits that are shared by every demanded vector element.
    Known.Zero.setAllBits(); Known.One.setAllBits();
    for (unsigned i = 0, e = Op.getNumOperands(); i != e; ++i) {
      if (!DemandedElts[i])
        continue;

      SDValue SrcOp = Op.getOperand(i);
      Known2 = computeKnownBits(SrcOp, Depth + 1);

      // BUILD_VECTOR can implicitly truncate sources, we must handle this.
      if (SrcOp.getValueSizeInBits() != BitWidth) {
        assert(SrcOp.getValueSizeInBits() > BitWidth &&
               "Expected BUILD_VECTOR implicit truncation");
        Known2 = Known2.trunc(BitWidth);
      }

      // Known bits are the values that are shared by every demanded element.
      Known = Known.intersectWith(Known2);

      // If we don't know any bits, early out.
      if (Known.isUnknown())
        break;
    }
    break;
  case ISD::VECTOR_SHUFFLE: {
    assert(!Op.getValueType().isScalableVector());
    // Collect the known bits that are shared by every vector element referenced
    // by the shuffle.
    APInt DemandedLHS, DemandedRHS;
    const ShuffleVectorSDNode *SVN = cast<ShuffleVectorSDNode>(Op);
    assert(NumElts == SVN->getMask().size() && "Unexpected vector size");
    if (!getShuffleDemandedElts(NumElts, SVN->getMask(), DemandedElts,
                                DemandedLHS, DemandedRHS))
      break;

    // Known bits are the values that are shared by every demanded element.
    Known.Zero.setAllBits(); Known.One.setAllBits();
    if (!!DemandedLHS) {
      SDValue LHS = Op.getOperand(0);
      Known2 = computeKnownBits(LHS, DemandedLHS, Depth + 1);
      Known = Known.intersectWith(Known2);
    }
    // If we don't know any bits, early out.
    if (Known.isUnknown())
      break;
    if (!!DemandedRHS) {
      SDValue RHS = Op.getOperand(1);
      Known2 = computeKnownBits(RHS, DemandedRHS, Depth + 1);
      Known = Known.intersectWith(Known2);
    }
    break;
  }
  case ISD::VSCALE: {
    const Function &F = getMachineFunction().getFunction();
    const APInt &Multiplier = Op.getConstantOperandAPInt(0);
    Known = getVScaleRange(&F, BitWidth).multiply(Multiplier).toKnownBits();
    break;
  }
  case ISD::CONCAT_VECTORS: {
    if (Op.getValueType().isScalableVector())
      break;
    // Split DemandedElts and test each of the demanded subvectors.
    Known.Zero.setAllBits(); Known.One.setAllBits();
    EVT SubVectorVT = Op.getOperand(0).getValueType();
    unsigned NumSubVectorElts = SubVectorVT.getVectorNumElements();
    unsigned NumSubVectors = Op.getNumOperands();
    for (unsigned i = 0; i != NumSubVectors; ++i) {
      APInt DemandedSub =
          DemandedElts.extractBits(NumSubVectorElts, i * NumSubVectorElts);
      if (!!DemandedSub) {
        SDValue Sub = Op.getOperand(i);
        Known2 = computeKnownBits(Sub, DemandedSub, Depth + 1);
        Known = Known.intersectWith(Known2);
      }
      // If we don't know any bits, early out.
      if (Known.isUnknown())
        break;
    }
    break;
  }
  case ISD::INSERT_SUBVECTOR: {
    if (Op.getValueType().isScalableVector())
      break;
    // Demand any elements from the subvector and the remainder from the src its
    // inserted into.
    SDValue Src = Op.getOperand(0);
    SDValue Sub = Op.getOperand(1);
    uint64_t Idx = Op.getConstantOperandVal(2);
    unsigned NumSubElts = Sub.getValueType().getVectorNumElements();
    APInt DemandedSubElts = DemandedElts.extractBits(NumSubElts, Idx);
    APInt DemandedSrcElts = DemandedElts;
    DemandedSrcElts.clearBits(Idx, Idx + NumSubElts);

    Known.One.setAllBits();
    Known.Zero.setAllBits();
    if (!!DemandedSubElts) {
      Known = computeKnownBits(Sub, DemandedSubElts, Depth + 1);
      if (Known.isUnknown())
        break; // early-out.
    }
    if (!!DemandedSrcElts) {
      Known2 = computeKnownBits(Src, DemandedSrcElts, Depth + 1);
      Known = Known.intersectWith(Known2);
    }
    break;
  }
  case ISD::EXTRACT_SUBVECTOR: {
    // Offset the demanded elts by the subvector index.
    SDValue Src = Op.getOperand(0);
    // Bail until we can represent demanded elements for scalable vectors.
    if (Op.getValueType().isScalableVector() || Src.getValueType().isScalableVector())
      break;
    uint64_t Idx = Op.getConstantOperandVal(1);
    unsigned NumSrcElts = Src.getValueType().getVectorNumElements();
    APInt DemandedSrcElts = DemandedElts.zext(NumSrcElts).shl(Idx);
    Known = computeKnownBits(Src, DemandedSrcElts, Depth + 1);
    break;
  }
  case ISD::SCALAR_TO_VECTOR: {
    if (Op.getValueType().isScalableVector())
      break;
    // We know about scalar_to_vector as much as we know about it source,
    // which becomes the first element of otherwise unknown vector.
    if (DemandedElts != 1)
      break;

    SDValue N0 = Op.getOperand(0);
    Known = computeKnownBits(N0, Depth + 1);
    if (N0.getValueSizeInBits() != BitWidth)
      Known = Known.trunc(BitWidth);

    break;
  }
  case ISD::BITCAST: {
    if (Op.getValueType().isScalableVector())
      break;

    SDValue N0 = Op.getOperand(0);
    EVT SubVT = N0.getValueType();
    unsigned SubBitWidth = SubVT.getScalarSizeInBits();

    // Ignore bitcasts from unsupported types.
    if (!(SubVT.isInteger() || SubVT.isFloatingPoint()))
      break;

    // Fast handling of 'identity' bitcasts.
    if (BitWidth == SubBitWidth) {
      Known = computeKnownBits(N0, DemandedElts, Depth + 1);
      break;
    }

    bool IsLE = getDataLayout().isLittleEndian();

    // Bitcast 'small element' vector to 'large element' scalar/vector.
    if ((BitWidth % SubBitWidth) == 0) {
      assert(N0.getValueType().isVector() && "Expected bitcast from vector");

      // Collect known bits for the (larger) output by collecting the known
      // bits from each set of sub elements and shift these into place.
      // We need to separately call computeKnownBits for each set of
      // sub elements as the knownbits for each is likely to be different.
      unsigned SubScale = BitWidth / SubBitWidth;
      APInt SubDemandedElts(NumElts * SubScale, 0);
      for (unsigned i = 0; i != NumElts; ++i)
        if (DemandedElts[i])
          SubDemandedElts.setBit(i * SubScale);

      for (unsigned i = 0; i != SubScale; ++i) {
        Known2 = computeKnownBits(N0, SubDemandedElts.shl(i),
                         Depth + 1);
        unsigned Shifts = IsLE ? i : SubScale - 1 - i;
        Known.insertBits(Known2, SubBitWidth * Shifts);
      }
    }

    // Bitcast 'large element' scalar/vector to 'small element' vector.
    if ((SubBitWidth % BitWidth) == 0) {
      assert(Op.getValueType().isVector() && "Expected bitcast to vector");

      // Collect known bits for the (smaller) output by collecting the known
      // bits from the overlapping larger input elements and extracting the
      // sub sections we actually care about.
      unsigned SubScale = SubBitWidth / BitWidth;
      APInt SubDemandedElts =
          APIntOps::ScaleBitMask(DemandedElts, NumElts / SubScale);
      Known2 = computeKnownBits(N0, SubDemandedElts, Depth + 1);

      Known.Zero.setAllBits(); Known.One.setAllBits();
      for (unsigned i = 0; i != NumElts; ++i)
        if (DemandedElts[i]) {
          unsigned Shifts = IsLE ? i : NumElts - 1 - i;
          unsigned Offset = (Shifts % SubScale) * BitWidth;
          Known = Known.intersectWith(Known2.extractBits(BitWidth, Offset));
          // If we don't know any bits, early out.
          if (Known.isUnknown())
            break;
        }
    }
    break;
  }
  case ISD::AND:
    Known = computeKnownBits(Op.getOperand(1), DemandedElts, Depth + 1);
    Known2 = computeKnownBits(Op.getOperand(0), DemandedElts, Depth + 1);

    Known &= Known2;
    break;
  case ISD::OR:
    Known = computeKnownBits(Op.getOperand(1), DemandedElts, Depth + 1);
    Known2 = computeKnownBits(Op.getOperand(0), DemandedElts, Depth + 1);

    Known |= Known2;
    break;
  case ISD::XOR:
    Known = computeKnownBits(Op.getOperand(1), DemandedElts, Depth + 1);
    Known2 = computeKnownBits(Op.getOperand(0), DemandedElts, Depth + 1);

    Known ^= Known2;
    break;
  case ISD::MUL: {
    Known = computeKnownBits(Op.getOperand(1), DemandedElts, Depth + 1);
    Known2 = computeKnownBits(Op.getOperand(0), DemandedElts, Depth + 1);
    bool SelfMultiply = Op.getOperand(0) == Op.getOperand(1);
    // TODO: SelfMultiply can be poison, but not undef.
    if (SelfMultiply)
      SelfMultiply &= isGuaranteedNotToBeUndefOrPoison(
          Op.getOperand(0), DemandedElts, false, Depth + 1);
    Known = KnownBits::mul(Known, Known2, SelfMultiply);

    // If the multiplication is known not to overflow, the product of a number
    // with itself is non-negative. Only do this if we didn't already computed
    // the opposite value for the sign bit.
    if (Op->getFlags().hasNoSignedWrap() &&
        Op.getOperand(0) == Op.getOperand(1) &&
        !Known.isNegative())
      Known.makeNonNegative();
    break;
  }
  case ISD::MULHU: {
    Known = computeKnownBits(Op.getOperand(1), DemandedElts, Depth + 1);
    Known2 = computeKnownBits(Op.getOperand(0), DemandedElts, Depth + 1);
    Known = KnownBits::mulhu(Known, Known2);
    break;
  }
  case ISD::MULHS: {
    Known = computeKnownBits(Op.getOperand(1), DemandedElts, Depth + 1);
    Known2 = computeKnownBits(Op.getOperand(0), DemandedElts, Depth + 1);
    Known = KnownBits::mulhs(Known, Known2);
    break;
  }
  case ISD::ABDU: {
    Known = computeKnownBits(Op.getOperand(1), DemandedElts, Depth + 1);
    Known2 = computeKnownBits(Op.getOperand(0), DemandedElts, Depth + 1);
    Known = KnownBits::abdu(Known, Known2);
    break;
  }
  case ISD::ABDS: {
    Known = computeKnownBits(Op.getOperand(1), DemandedElts, Depth + 1);
    Known2 = computeKnownBits(Op.getOperand(0), DemandedElts, Depth + 1);
    Known = KnownBits::abds(Known, Known2);
    unsigned SignBits1 =
        ComputeNumSignBits(Op.getOperand(1), DemandedElts, Depth + 1);
    if (SignBits1 == 1)
      break;
    unsigned SignBits0 =
        ComputeNumSignBits(Op.getOperand(0), DemandedElts, Depth + 1);
    Known.Zero.setHighBits(std::min(SignBits0, SignBits1) - 1);
    break;
  }
  case ISD::UMUL_LOHI: {
    assert((Op.getResNo() == 0 || Op.getResNo() == 1) && "Unknown result");
    Known = computeKnownBits(Op.getOperand(1), DemandedElts, Depth + 1);
    Known2 = computeKnownBits(Op.getOperand(0), DemandedElts, Depth + 1);
    bool SelfMultiply = Op.getOperand(0) == Op.getOperand(1);
    if (Op.getResNo() == 0)
      Known = KnownBits::mul(Known, Known2, SelfMultiply);
    else
      Known = KnownBits::mulhu(Known, Known2);
    break;
  }
  case ISD::SMUL_LOHI: {
    assert((Op.getResNo() == 0 || Op.getResNo() == 1) && "Unknown result");
    Known = computeKnownBits(Op.getOperand(1), DemandedElts, Depth + 1);
    Known2 = computeKnownBits(Op.getOperand(0), DemandedElts, Depth + 1);
    bool SelfMultiply = Op.getOperand(0) == Op.getOperand(1);
    if (Op.getResNo() == 0)
      Known = KnownBits::mul(Known, Known2, SelfMultiply);
    else
      Known = KnownBits::mulhs(Known, Known2);
    break;
  }
  case ISD::AVGFLOORU: {
    Known = computeKnownBits(Op.getOperand(0), DemandedElts, Depth + 1);
    Known2 = computeKnownBits(Op.getOperand(1), DemandedElts, Depth + 1);
    Known = KnownBits::avgFloorU(Known, Known2);
    break;
  }
  case ISD::AVGCEILU: {
    Known = computeKnownBits(Op.getOperand(0), DemandedElts, Depth + 1);
    Known2 = computeKnownBits(Op.getOperand(1), DemandedElts, Depth + 1);
    Known = KnownBits::avgCeilU(Known, Known2);
    break;
  }
  case ISD::AVGFLOORS: {
    Known = computeKnownBits(Op.getOperand(0), DemandedElts, Depth + 1);
    Known2 = computeKnownBits(Op.getOperand(1), DemandedElts, Depth + 1);
    Known = KnownBits::avgFloorS(Known, Known2);
    break;
  }
  case ISD::AVGCEILS: {
    Known = computeKnownBits(Op.getOperand(0), DemandedElts, Depth + 1);
    Known2 = computeKnownBits(Op.getOperand(1), DemandedElts, Depth + 1);
    Known = KnownBits::avgCeilS(Known, Known2);
    break;
  }
  case ISD::SELECT:
  case ISD::VSELECT:
    Known = computeKnownBits(Op.getOperand(2), DemandedElts, Depth+1);
    // If we don't know any bits, early out.
    if (Known.isUnknown())
      break;
    Known2 = computeKnownBits(Op.getOperand(1), DemandedElts, Depth+1);

    // Only known if known in both the LHS and RHS.
    Known = Known.intersectWith(Known2);
    break;
  case ISD::SELECT_CC:
    Known = computeKnownBits(Op.getOperand(3), DemandedElts, Depth+1);
    // If we don't know any bits, early out.
    if (Known.isUnknown())
      break;
    Known2 = computeKnownBits(Op.getOperand(2), DemandedElts, Depth+1);

    // Only known if known in both the LHS and RHS.
    Known = Known.intersectWith(Known2);
    break;
  case ISD::SMULO:
  case ISD::UMULO:
    if (Op.getResNo() != 1)
      break;
    // The boolean result conforms to getBooleanContents.
    // If we know the result of a setcc has the top bits zero, use this info.
    // We know that we have an integer-based boolean since these operations
    // are only available for integer.
    if (TLI->getBooleanContents(Op.getValueType().isVector(), false) ==
            TargetLowering::ZeroOrOneBooleanContent &&
        BitWidth > 1)
      Known.Zero.setBitsFrom(1);
    break;
  case ISD::SETCC:
  case ISD::SETCCCARRY:
  case ISD::STRICT_FSETCC:
  case ISD::STRICT_FSETCCS: {
    unsigned OpNo = Op->isStrictFPOpcode() ? 1 : 0;
    // If we know the result of a setcc has the top bits zero, use this info.
    if (TLI->getBooleanContents(Op.getOperand(OpNo).getValueType()) ==
            TargetLowering::ZeroOrOneBooleanContent &&
        BitWidth > 1)
      Known.Zero.setBitsFrom(1);
    break;
  }
  case ISD::SHL: {
    Known = computeKnownBits(Op.getOperand(0), DemandedElts, Depth + 1);
    Known2 = computeKnownBits(Op.getOperand(1), DemandedElts, Depth + 1);

    bool NUW = Op->getFlags().hasNoUnsignedWrap();
    bool NSW = Op->getFlags().hasNoSignedWrap();

    bool ShAmtNonZero = Known2.isNonZero();

    Known = KnownBits::shl(Known, Known2, NUW, NSW, ShAmtNonZero);

    // Minimum shift low bits are known zero.
    if (std::optional<uint64_t> ShMinAmt =
            getValidMinimumShiftAmount(Op, DemandedElts, Depth + 1))
      Known.Zero.setLowBits(*ShMinAmt);
    break;
  }
  case ISD::SRL:
    Known = computeKnownBits(Op.getOperand(0), DemandedElts, Depth + 1);
    Known2 = computeKnownBits(Op.getOperand(1), DemandedElts, Depth + 1);
    Known = KnownBits::lshr(Known, Known2, /*ShAmtNonZero=*/false,
                            Op->getFlags().hasExact());

    // Minimum shift high bits are known zero.
    if (std::optional<uint64_t> ShMinAmt =
            getValidMinimumShiftAmount(Op, DemandedElts, Depth + 1))
      Known.Zero.setHighBits(*ShMinAmt);
    break;
  case ISD::SRA:
    Known = computeKnownBits(Op.getOperand(0), DemandedElts, Depth + 1);
    Known2 = computeKnownBits(Op.getOperand(1), DemandedElts, Depth + 1);
    Known = KnownBits::ashr(Known, Known2, /*ShAmtNonZero=*/false,
                            Op->getFlags().hasExact());
    break;
  case ISD::FSHL:
  case ISD::FSHR:
    if (ConstantSDNode *C = isConstOrConstSplat(Op.getOperand(2), DemandedElts)) {
      unsigned Amt = C->getAPIntValue().urem(BitWidth);

      // For fshl, 0-shift returns the 1st arg.
      // For fshr, 0-shift returns the 2nd arg.
      if (Amt == 0) {
        Known = computeKnownBits(Op.getOperand(Opcode == ISD::FSHL ? 0 : 1),
                                 DemandedElts, Depth + 1);
        break;
      }

      // fshl: (X << (Z % BW)) | (Y >> (BW - (Z % BW)))
      // fshr: (X << (BW - (Z % BW))) | (Y >> (Z % BW))
      Known = computeKnownBits(Op.getOperand(0), DemandedElts, Depth + 1);
      Known2 = computeKnownBits(Op.getOperand(1), DemandedElts, Depth + 1);
      if (Opcode == ISD::FSHL) {
        Known.One <<= Amt;
        Known.Zero <<= Amt;
        Known2.One.lshrInPlace(BitWidth - Amt);
        Known2.Zero.lshrInPlace(BitWidth - Amt);
      } else {
        Known.One <<= BitWidth - Amt;
        Known.Zero <<= BitWidth - Amt;
        Known2.One.lshrInPlace(Amt);
        Known2.Zero.lshrInPlace(Amt);
      }
      Known = Known.unionWith(Known2);
    }
    break;
  case ISD::SHL_PARTS:
  case ISD::SRA_PARTS:
  case ISD::SRL_PARTS: {
    assert((Op.getResNo() == 0 || Op.getResNo() == 1) && "Unknown result");

    // Collect lo/hi source values and concatenate.
    unsigned LoBits = Op.getOperand(0).getScalarValueSizeInBits();
    unsigned HiBits = Op.getOperand(1).getScalarValueSizeInBits();
    Known = computeKnownBits(Op.getOperand(0), DemandedElts, Depth + 1);
    Known2 = computeKnownBits(Op.getOperand(1), DemandedElts, Depth + 1);
    Known = Known2.concat(Known);

    // Collect shift amount.
    Known2 = computeKnownBits(Op.getOperand(2), DemandedElts, Depth + 1);

    if (Opcode == ISD::SHL_PARTS)
      Known = KnownBits::shl(Known, Known2);
    else if (Opcode == ISD::SRA_PARTS)
      Known = KnownBits::ashr(Known, Known2);
    else // if (Opcode == ISD::SRL_PARTS)
      Known = KnownBits::lshr(Known, Known2);

    // TODO: Minimum shift low/high bits are known zero.

    if (Op.getResNo() == 0)
      Known = Known.extractBits(LoBits, 0);
    else
      Known = Known.extractBits(HiBits, LoBits);
    break;
  }
  case ISD::SIGN_EXTEND_INREG: {
    Known = computeKnownBits(Op.getOperand(0), DemandedElts, Depth + 1);
    EVT EVT = cast<VTSDNode>(Op.getOperand(1))->getVT();
    Known = Known.sextInReg(EVT.getScalarSizeInBits());
    break;
  }
  case ISD::CTTZ:
  case ISD::CTTZ_ZERO_UNDEF: {
    Known2 = computeKnownBits(Op.getOperand(0), DemandedElts, Depth + 1);
    // If we have a known 1, its position is our upper bound.
    unsigned PossibleTZ = Known2.countMaxTrailingZeros();
    unsigned LowBits = llvm::bit_width(PossibleTZ);
    Known.Zero.setBitsFrom(LowBits);
    break;
  }
  case ISD::CTLZ:
  case ISD::CTLZ_ZERO_UNDEF: {
    Known2 = computeKnownBits(Op.getOperand(0), DemandedElts, Depth + 1);
    // If we have a known 1, its position is our upper bound.
    unsigned PossibleLZ = Known2.countMaxLeadingZeros();
    unsigned LowBits = llvm::bit_width(PossibleLZ);
    Known.Zero.setBitsFrom(LowBits);
    break;
  }
  case ISD::CTPOP: {
    Known2 = computeKnownBits(Op.getOperand(0), DemandedElts, Depth + 1);
    // If we know some of the bits are zero, they can't be one.
    unsigned PossibleOnes = Known2.countMaxPopulation();
    Known.Zero.setBitsFrom(llvm::bit_width(PossibleOnes));
    break;
  }
  case ISD::PARITY: {
    // Parity returns 0 everywhere but the LSB.
    Known.Zero.setBitsFrom(1);
    break;
  }
  case ISD::MGATHER:
  case ISD::MLOAD: {
    ISD::LoadExtType ETy =
        (Opcode == ISD::MGATHER)
            ? cast<MaskedGatherSDNode>(Op)->getExtensionType()
            : cast<MaskedLoadSDNode>(Op)->getExtensionType();
    if (ETy == ISD::ZEXTLOAD) {
      EVT MemVT = cast<MemSDNode>(Op)->getMemoryVT();
      KnownBits Known0(MemVT.getScalarSizeInBits());
      return Known0.zext(BitWidth);
    }
    break;
  }
  case ISD::LOAD: {
    LoadSDNode *LD = cast<LoadSDNode>(Op);
    const Constant *Cst = TLI->getTargetConstantFromLoad(LD);
    if (ISD::isNON_EXTLoad(LD) && Cst) {
      // Determine any common known bits from the loaded constant pool value.
      Type *CstTy = Cst->getType();
      if ((NumElts * BitWidth) == CstTy->getPrimitiveSizeInBits() &&
          !Op.getValueType().isScalableVector()) {
        // If its a vector splat, then we can (quickly) reuse the scalar path.
        // NOTE: We assume all elements match and none are UNDEF.
        if (CstTy->isVectorTy()) {
          if (const Constant *Splat = Cst->getSplatValue()) {
            Cst = Splat;
            CstTy = Cst->getType();
          }
        }
        // TODO - do we need to handle different bitwidths?
        if (CstTy->isVectorTy() && BitWidth == CstTy->getScalarSizeInBits()) {
          // Iterate across all vector elements finding common known bits.
          Known.One.setAllBits();
          Known.Zero.setAllBits();
          for (unsigned i = 0; i != NumElts; ++i) {
            if (!DemandedElts[i])
              continue;
            if (Constant *Elt = Cst->getAggregateElement(i)) {
              if (auto *CInt = dyn_cast<ConstantInt>(Elt)) {
                const APInt &Value = CInt->getValue();
                Known.One &= Value;
                Known.Zero &= ~Value;
                continue;
              }
              if (auto *CFP = dyn_cast<ConstantFP>(Elt)) {
                APInt Value = CFP->getValueAPF().bitcastToAPInt();
                Known.One &= Value;
                Known.Zero &= ~Value;
                continue;
              }
            }
            Known.One.clearAllBits();
            Known.Zero.clearAllBits();
            break;
          }
        } else if (BitWidth == CstTy->getPrimitiveSizeInBits()) {
          if (auto *CInt = dyn_cast<ConstantInt>(Cst)) {
            Known = KnownBits::makeConstant(CInt->getValue());
          } else if (auto *CFP = dyn_cast<ConstantFP>(Cst)) {
            Known =
                KnownBits::makeConstant(CFP->getValueAPF().bitcastToAPInt());
          }
        }
      }
    } else if (Op.getResNo() == 0) {
      unsigned ScalarMemorySize = LD->getMemoryVT().getScalarSizeInBits();
      KnownBits KnownScalarMemory(ScalarMemorySize);
      if (const MDNode *MD = LD->getRanges())
        computeKnownBitsFromRangeMetadata(*MD, KnownScalarMemory);

      // Extend the Known bits from memory to the size of the scalar result.
      if (ISD::isZEXTLoad(Op.getNode()))
        Known = KnownScalarMemory.zext(BitWidth);
      else if (ISD::isSEXTLoad(Op.getNode()))
        Known = KnownScalarMemory.sext(BitWidth);
      else if (ISD::isEXTLoad(Op.getNode()))
        Known = KnownScalarMemory.anyext(BitWidth);
      else
        Known = KnownScalarMemory;
      assert(Known.getBitWidth() == BitWidth);
      return Known;
    }
    break;
  }
  case ISD::ZERO_EXTEND_VECTOR_INREG: {
    if (Op.getValueType().isScalableVector())
      break;
    EVT InVT = Op.getOperand(0).getValueType();
    APInt InDemandedElts = DemandedElts.zext(InVT.getVectorNumElements());
    Known = computeKnownBits(Op.getOperand(0), InDemandedElts, Depth + 1);
    Known = Known.zext(BitWidth);
    break;
  }
  case ISD::ZERO_EXTEND: {
    Known = computeKnownBits(Op.getOperand(0), DemandedElts, Depth + 1);
    Known = Known.zext(BitWidth);
    break;
  }
  case ISD::SIGN_EXTEND_VECTOR_INREG: {
    if (Op.getValueType().isScalableVector())
      break;
    EVT InVT = Op.getOperand(0).getValueType();
    APInt InDemandedElts = DemandedElts.zext(InVT.getVectorNumElements());
    Known = computeKnownBits(Op.getOperand(0), InDemandedElts, Depth + 1);
    // If the sign bit is known to be zero or one, then sext will extend
    // it to the top bits, else it will just zext.
    Known = Known.sext(BitWidth);
    break;
  }
  case ISD::SIGN_EXTEND: {
    Known = computeKnownBits(Op.getOperand(0), DemandedElts, Depth + 1);
    // If the sign bit is known to be zero or one, then sext will extend
    // it to the top bits, else it will just zext.
    Known = Known.sext(BitWidth);
    break;
  }
  case ISD::ANY_EXTEND_VECTOR_INREG: {
    if (Op.getValueType().isScalableVector())
      break;
    EVT InVT = Op.getOperand(0).getValueType();
    APInt InDemandedElts = DemandedElts.zext(InVT.getVectorNumElements());
    Known = computeKnownBits(Op.getOperand(0), InDemandedElts, Depth + 1);
    Known = Known.anyext(BitWidth);
    break;
  }
  case ISD::ANY_EXTEND: {
    Known = computeKnownBits(Op.getOperand(0), DemandedElts, Depth + 1);
    Known = Known.anyext(BitWidth);
    break;
  }
  case ISD::TRUNCATE: {
    Known = computeKnownBits(Op.getOperand(0), DemandedElts, Depth + 1);
    Known = Known.trunc(BitWidth);
    break;
  }
  case ISD::AssertZext: {
    EVT VT = cast<VTSDNode>(Op.getOperand(1))->getVT();
    APInt InMask = APInt::getLowBitsSet(BitWidth, VT.getSizeInBits());
    Known = computeKnownBits(Op.getOperand(0), DemandedElts, Depth + 1);
    Known.Zero |= (~InMask);
    Known.One  &= (~Known.Zero);
    break;
  }
  case ISD::AssertAlign: {
    unsigned LogOfAlign = Log2(cast<AssertAlignSDNode>(Op)->getAlign());
    assert(LogOfAlign != 0);

    // TODO: Should use maximum with source
    // If a node is guaranteed to be aligned, set low zero bits accordingly as
    // well as clearing one bits.
    Known.Zero.setLowBits(LogOfAlign);
    Known.One.clearLowBits(LogOfAlign);
    break;
  }
  case ISD::FGETSIGN:
    // All bits are zero except the low bit.
    Known.Zero.setBitsFrom(1);
    break;
  case ISD::ADD:
  case ISD::SUB: {
    SDNodeFlags Flags = Op.getNode()->getFlags();
    Known = computeKnownBits(Op.getOperand(0), DemandedElts, Depth + 1);
    Known2 = computeKnownBits(Op.getOperand(1), DemandedElts, Depth + 1);
    Known = KnownBits::computeForAddSub(
        Op.getOpcode() == ISD::ADD, Flags.hasNoSignedWrap(),
        Flags.hasNoUnsignedWrap(), Known, Known2);
    break;
  }
  case ISD::USUBO:
  case ISD::SSUBO:
  case ISD::USUBO_CARRY:
  case ISD::SSUBO_CARRY:
    if (Op.getResNo() == 1) {
      // If we know the result of a setcc has the top bits zero, use this info.
      if (TLI->getBooleanContents(Op.getOperand(0).getValueType()) ==
              TargetLowering::ZeroOrOneBooleanContent &&
          BitWidth > 1)
        Known.Zero.setBitsFrom(1);
      break;
    }
    [[fallthrough]];
  case ISD::SUBC: {
    assert(Op.getResNo() == 0 &&
           "We only compute knownbits for the difference here.");

    // With USUBO_CARRY and SSUBO_CARRY a borrow bit may be added in.
    KnownBits Borrow(1);
    if (Opcode == ISD::USUBO_CARRY || Opcode == ISD::SSUBO_CARRY) {
      Borrow = computeKnownBits(Op.getOperand(2), DemandedElts, Depth + 1);
      // Borrow has bit width 1
      Borrow = Borrow.trunc(1);
    } else {
      Borrow.setAllZero();
    }

    Known = computeKnownBits(Op.getOperand(0), DemandedElts, Depth + 1);
    Known2 = computeKnownBits(Op.getOperand(1), DemandedElts, Depth + 1);
    Known = KnownBits::computeForSubBorrow(Known, Known2, Borrow);
    break;
  }
  case ISD::UADDO:
  case ISD::SADDO:
  case ISD::UADDO_CARRY:
  case ISD::SADDO_CARRY:
    if (Op.getResNo() == 1) {
      // If we know the result of a setcc has the top bits zero, use this info.
      if (TLI->getBooleanContents(Op.getOperand(0).getValueType()) ==
              TargetLowering::ZeroOrOneBooleanContent &&
          BitWidth > 1)
        Known.Zero.setBitsFrom(1);
      break;
    }
    [[fallthrough]];
  case ISD::ADDC:
  case ISD::ADDE: {
    assert(Op.getResNo() == 0 && "We only compute knownbits for the sum here.");

    // With ADDE and UADDO_CARRY, a carry bit may be added in.
    KnownBits Carry(1);
    if (Opcode == ISD::ADDE)
      // Can't track carry from glue, set carry to unknown.
      Carry.resetAll();
    else if (Opcode == ISD::UADDO_CARRY || Opcode == ISD::SADDO_CARRY) {
      Carry = computeKnownBits(Op.getOperand(2), DemandedElts, Depth + 1);
      // Carry has bit width 1
      Carry = Carry.trunc(1);
    } else {
      Carry.setAllZero();
    }

    Known = computeKnownBits(Op.getOperand(0), DemandedElts, Depth + 1);
    Known2 = computeKnownBits(Op.getOperand(1), DemandedElts, Depth + 1);
    Known = KnownBits::computeForAddCarry(Known, Known2, Carry);
    break;
  }
  case ISD::UDIV: {
    Known = computeKnownBits(Op.getOperand(0), DemandedElts, Depth + 1);
    Known2 = computeKnownBits(Op.getOperand(1), DemandedElts, Depth + 1);
    Known = KnownBits::udiv(Known, Known2, Op->getFlags().hasExact());
    break;
  }
  case ISD::SDIV: {
    Known = computeKnownBits(Op.getOperand(0), DemandedElts, Depth + 1);
    Known2 = computeKnownBits(Op.getOperand(1), DemandedElts, Depth + 1);
    Known = KnownBits::sdiv(Known, Known2, Op->getFlags().hasExact());
    break;
  }
  case ISD::SREM: {
    Known = computeKnownBits(Op.getOperand(0), DemandedElts, Depth + 1);
    Known2 = computeKnownBits(Op.getOperand(1), DemandedElts, Depth + 1);
    Known = KnownBits::srem(Known, Known2);
    break;
  }
  case ISD::UREM: {
    Known = computeKnownBits(Op.getOperand(0), DemandedElts, Depth + 1);
    Known2 = computeKnownBits(Op.getOperand(1), DemandedElts, Depth + 1);
    Known = KnownBits::urem(Known, Known2);
    break;
  }
  case ISD::EXTRACT_ELEMENT: {
    Known = computeKnownBits(Op.getOperand(0), Depth+1);
    const unsigned Index = Op.getConstantOperandVal(1);
    const unsigned EltBitWidth = Op.getValueSizeInBits();

    // Remove low part of known bits mask
    Known.Zero = Known.Zero.getHiBits(Known.getBitWidth() - Index * EltBitWidth);
    Known.One = Known.One.getHiBits(Known.getBitWidth() - Index * EltBitWidth);

    // Remove high part of known bit mask
    Known = Known.trunc(EltBitWidth);
    break;
  }
  case ISD::EXTRACT_VECTOR_ELT: {
    SDValue InVec = Op.getOperand(0);
    SDValue EltNo = Op.getOperand(1);
    EVT VecVT = InVec.getValueType();
    // computeKnownBits not yet implemented for scalable vectors.
    if (VecVT.isScalableVector())
      break;
    const unsigned EltBitWidth = VecVT.getScalarSizeInBits();
    const unsigned NumSrcElts = VecVT.getVectorNumElements();

    // If BitWidth > EltBitWidth the value is anyext:ed. So we do not know
    // anything about the extended bits.
    if (BitWidth > EltBitWidth)
      Known = Known.trunc(EltBitWidth);

    // If we know the element index, just demand that vector element, else for
    // an unknown element index, ignore DemandedElts and demand them all.
    APInt DemandedSrcElts = APInt::getAllOnes(NumSrcElts);
    auto *ConstEltNo = dyn_cast<ConstantSDNode>(EltNo);
    if (ConstEltNo && ConstEltNo->getAPIntValue().ult(NumSrcElts))
      DemandedSrcElts =
          APInt::getOneBitSet(NumSrcElts, ConstEltNo->getZExtValue());

    Known = computeKnownBits(InVec, DemandedSrcElts, Depth + 1);
    if (BitWidth > EltBitWidth)
      Known = Known.anyext(BitWidth);
    break;
  }
  case ISD::INSERT_VECTOR_ELT: {
    if (Op.getValueType().isScalableVector())
      break;

    // If we know the element index, split the demand between the
    // source vector and the inserted element, otherwise assume we need
    // the original demanded vector elements and the value.
    SDValue InVec = Op.getOperand(0);
    SDValue InVal = Op.getOperand(1);
    SDValue EltNo = Op.getOperand(2);
    bool DemandedVal = true;
    APInt DemandedVecElts = DemandedElts;
    auto *CEltNo = dyn_cast<ConstantSDNode>(EltNo);
    if (CEltNo && CEltNo->getAPIntValue().ult(NumElts)) {
      unsigned EltIdx = CEltNo->getZExtValue();
      DemandedVal = !!DemandedElts[EltIdx];
      DemandedVecElts.clearBit(EltIdx);
    }
    Known.One.setAllBits();
    Known.Zero.setAllBits();
    if (DemandedVal) {
      Known2 = computeKnownBits(InVal, Depth + 1);
      Known = Known.intersectWith(Known2.zextOrTrunc(BitWidth));
    }
    if (!!DemandedVecElts) {
      Known2 = computeKnownBits(InVec, DemandedVecElts, Depth + 1);
      Known = Known.intersectWith(Known2);
    }
    break;
  }
  case ISD::BITREVERSE: {
    Known2 = computeKnownBits(Op.getOperand(0), DemandedElts, Depth + 1);
    Known = Known2.reverseBits();
    break;
  }
  case ISD::BSWAP: {
    Known2 = computeKnownBits(Op.getOperand(0), DemandedElts, Depth + 1);
    Known = Known2.byteSwap();
    break;
  }
  case ISD::ABS: {
    Known2 = computeKnownBits(Op.getOperand(0), DemandedElts, Depth + 1);
    Known = Known2.abs();
    Known.Zero.setHighBits(
        ComputeNumSignBits(Op.getOperand(0), DemandedElts, Depth + 1) - 1);
    break;
  }
  case ISD::USUBSAT: {
    Known = computeKnownBits(Op.getOperand(0), DemandedElts, Depth + 1);
    Known2 = computeKnownBits(Op.getOperand(1), DemandedElts, Depth + 1);
    Known = KnownBits::usub_sat(Known, Known2);
    break;
  }
  case ISD::UMIN: {
    Known = computeKnownBits(Op.getOperand(0), DemandedElts, Depth + 1);
    Known2 = computeKnownBits(Op.getOperand(1), DemandedElts, Depth + 1);
    Known = KnownBits::umin(Known, Known2);
    break;
  }
  case ISD::UMAX: {
    Known = computeKnownBits(Op.getOperand(0), DemandedElts, Depth + 1);
    Known2 = computeKnownBits(Op.getOperand(1), DemandedElts, Depth + 1);
    Known = KnownBits::umax(Known, Known2);
    break;
  }
  case ISD::SMIN:
  case ISD::SMAX: {
    // If we have a clamp pattern, we know that the number of sign bits will be
    // the minimum of the clamp min/max range.
    bool IsMax = (Opcode == ISD::SMAX);
    ConstantSDNode *CstLow = nullptr, *CstHigh = nullptr;
    if ((CstLow = isConstOrConstSplat(Op.getOperand(1), DemandedElts)))
      if (Op.getOperand(0).getOpcode() == (IsMax ? ISD::SMIN : ISD::SMAX))
        CstHigh =
            isConstOrConstSplat(Op.getOperand(0).getOperand(1), DemandedElts);
    if (CstLow && CstHigh) {
      if (!IsMax)
        std::swap(CstLow, CstHigh);

      const APInt &ValueLow = CstLow->getAPIntValue();
      const APInt &ValueHigh = CstHigh->getAPIntValue();
      if (ValueLow.sle(ValueHigh)) {
        unsigned LowSignBits = ValueLow.getNumSignBits();
        unsigned HighSignBits = ValueHigh.getNumSignBits();
        unsigned MinSignBits = std::min(LowSignBits, HighSignBits);
        if (ValueLow.isNegative() && ValueHigh.isNegative()) {
          Known.One.setHighBits(MinSignBits);
          break;
        }
        if (ValueLow.isNonNegative() && ValueHigh.isNonNegative()) {
          Known.Zero.setHighBits(MinSignBits);
          break;
        }
      }
    }

    Known = computeKnownBits(Op.getOperand(0), DemandedElts, Depth + 1);
    Known2 = computeKnownBits(Op.getOperand(1), DemandedElts, Depth + 1);
    if (IsMax)
      Known = KnownBits::smax(Known, Known2);
    else
      Known = KnownBits::smin(Known, Known2);

    // For SMAX, if CstLow is non-negative we know the result will be
    // non-negative and thus all sign bits are 0.
    // TODO: There's an equivalent of this for smin with negative constant for
    // known ones.
    if (IsMax && CstLow) {
      const APInt &ValueLow = CstLow->getAPIntValue();
      if (ValueLow.isNonNegative()) {
        unsigned SignBits = ComputeNumSignBits(Op.getOperand(0), Depth + 1);
        Known.Zero.setHighBits(std::min(SignBits, ValueLow.getNumSignBits()));
      }
    }

    break;
  }
  case ISD::UINT_TO_FP: {
    Known.makeNonNegative();
    break;
  }
  case ISD::SINT_TO_FP: {
    Known2 = computeKnownBits(Op.getOperand(0), DemandedElts, Depth + 1);
    if (Known2.isNonNegative())
      Known.makeNonNegative();
    else if (Known2.isNegative())
      Known.makeNegative();
    break;
  }
  case ISD::FP_TO_UINT_SAT: {
    // FP_TO_UINT_SAT produces an unsigned value that fits in the saturating VT.
    EVT VT = cast<VTSDNode>(Op.getOperand(1))->getVT();
    Known.Zero |= APInt::getBitsSetFrom(BitWidth, VT.getScalarSizeInBits());
    break;
  }
  case ISD::ATOMIC_LOAD: {
    // If we are looking at the loaded value.
    if (Op.getResNo() == 0) {
      auto *AT = cast<AtomicSDNode>(Op);
      unsigned ScalarMemorySize = AT->getMemoryVT().getScalarSizeInBits();
      KnownBits KnownScalarMemory(ScalarMemorySize);
      if (const MDNode *MD = AT->getRanges())
        computeKnownBitsFromRangeMetadata(*MD, KnownScalarMemory);

      switch (AT->getExtensionType()) {
      case ISD::ZEXTLOAD:
        Known = KnownScalarMemory.zext(BitWidth);
        break;
      case ISD::SEXTLOAD:
        Known = KnownScalarMemory.sext(BitWidth);
        break;
      case ISD::EXTLOAD:
        switch (TLI->getExtendForAtomicOps()) {
        case ISD::ZERO_EXTEND:
          Known = KnownScalarMemory.zext(BitWidth);
          break;
        case ISD::SIGN_EXTEND:
          Known = KnownScalarMemory.sext(BitWidth);
          break;
        default:
          Known = KnownScalarMemory.anyext(BitWidth);
          break;
        }
        break;
      case ISD::NON_EXTLOAD:
        Known = KnownScalarMemory;
        break;
      }
      assert(Known.getBitWidth() == BitWidth);
    }
    break;
  }
  case ISD::ATOMIC_CMP_SWAP_WITH_SUCCESS:
    if (Op.getResNo() == 1) {
      // The boolean result conforms to getBooleanContents.
      // If we know the result of a setcc has the top bits zero, use this info.
      // We know that we have an integer-based boolean since these operations
      // are only available for integer.
      if (TLI->getBooleanContents(Op.getValueType().isVector(), false) ==
              TargetLowering::ZeroOrOneBooleanContent &&
          BitWidth > 1)
        Known.Zero.setBitsFrom(1);
      break;
    }
    [[fallthrough]];
  case ISD::ATOMIC_CMP_SWAP:
  case ISD::ATOMIC_SWAP:
  case ISD::ATOMIC_LOAD_ADD:
  case ISD::ATOMIC_LOAD_SUB:
  case ISD::ATOMIC_LOAD_AND:
  case ISD::ATOMIC_LOAD_CLR:
  case ISD::ATOMIC_LOAD_OR:
  case ISD::ATOMIC_LOAD_XOR:
  case ISD::ATOMIC_LOAD_NAND:
  case ISD::ATOMIC_LOAD_MIN:
  case ISD::ATOMIC_LOAD_MAX:
  case ISD::ATOMIC_LOAD_UMIN:
  case ISD::ATOMIC_LOAD_UMAX: {
    // If we are looking at the loaded value.
    if (Op.getResNo() == 0) {
      auto *AT = cast<AtomicSDNode>(Op);
      unsigned MemBits = AT->getMemoryVT().getScalarSizeInBits();

      if (TLI->getExtendForAtomicOps() == ISD::ZERO_EXTEND)
        Known.Zero.setBitsFrom(MemBits);
    }
    break;
  }
  case ISD::FrameIndex:
  case ISD::TargetFrameIndex:
    TLI->computeKnownBitsForFrameIndex(cast<FrameIndexSDNode>(Op)->getIndex(),
                                       Known, getMachineFunction());
    break;

  default:
    if (Opcode < ISD::BUILTIN_OP_END)
      break;
    [[fallthrough]];
  case ISD::INTRINSIC_WO_CHAIN:
  case ISD::INTRINSIC_W_CHAIN:
  case ISD::INTRINSIC_VOID:
    // TODO: Probably okay to remove after audit; here to reduce change size
    // in initial enablement patch for scalable vectors
    if (Op.getValueType().isScalableVector())
      break;

    // Allow the target to implement this method for its nodes.
    TLI->computeKnownBitsForTargetNode(Op, Known, DemandedElts, *this, Depth);
    break;
  }

  return Known;
}

/// Convert ConstantRange OverflowResult into SelectionDAG::OverflowKind.
static SelectionDAG::OverflowKind mapOverflowResult(ConstantRange::OverflowResult OR) {
  switch (OR) {
  case ConstantRange::OverflowResult::MayOverflow:
    return SelectionDAG::OFK_Sometime;
  case ConstantRange::OverflowResult::AlwaysOverflowsLow:
  case ConstantRange::OverflowResult::AlwaysOverflowsHigh:
    return SelectionDAG::OFK_Always;
  case ConstantRange::OverflowResult::NeverOverflows:
    return SelectionDAG::OFK_Never;
  }
  llvm_unreachable("Unknown OverflowResult");
}

SelectionDAG::OverflowKind
SelectionDAG::computeOverflowForSignedAdd(SDValue N0, SDValue N1) const {
  // X + 0 never overflow
  if (isNullConstant(N1))
    return OFK_Never;

  // If both operands each have at least two sign bits, the addition
  // cannot overflow.
  if (ComputeNumSignBits(N0) > 1 && ComputeNumSignBits(N1) > 1)
    return OFK_Never;

  // TODO: Add ConstantRange::signedAddMayOverflow handling.
  return OFK_Sometime;
}

SelectionDAG::OverflowKind
SelectionDAG::computeOverflowForUnsignedAdd(SDValue N0, SDValue N1) const {
  // X + 0 never overflow
  if (isNullConstant(N1))
    return OFK_Never;

  // mulhi + 1 never overflow
  KnownBits N1Known = computeKnownBits(N1);
  if (N0.getOpcode() == ISD::UMUL_LOHI && N0.getResNo() == 1 &&
      N1Known.getMaxValue().ult(2))
    return OFK_Never;

  KnownBits N0Known = computeKnownBits(N0);
  if (N1.getOpcode() == ISD::UMUL_LOHI && N1.getResNo() == 1 &&
      N0Known.getMaxValue().ult(2))
    return OFK_Never;

  // Fallback to ConstantRange::unsignedAddMayOverflow handling.
  ConstantRange N0Range = ConstantRange::fromKnownBits(N0Known, false);
  ConstantRange N1Range = ConstantRange::fromKnownBits(N1Known, false);
  return mapOverflowResult(N0Range.unsignedAddMayOverflow(N1Range));
}

SelectionDAG::OverflowKind
SelectionDAG::computeOverflowForSignedSub(SDValue N0, SDValue N1) const {
  // X - 0 never overflow
  if (isNullConstant(N1))
    return OFK_Never;

  // If both operands each have at least two sign bits, the subtraction
  // cannot overflow.
  if (ComputeNumSignBits(N0) > 1 && ComputeNumSignBits(N1) > 1)
    return OFK_Never;

  KnownBits N0Known = computeKnownBits(N0);
  KnownBits N1Known = computeKnownBits(N1);
  ConstantRange N0Range = ConstantRange::fromKnownBits(N0Known, true);
  ConstantRange N1Range = ConstantRange::fromKnownBits(N1Known, true);
  return mapOverflowResult(N0Range.signedSubMayOverflow(N1Range));
}

SelectionDAG::OverflowKind
SelectionDAG::computeOverflowForUnsignedSub(SDValue N0, SDValue N1) const {
  // X - 0 never overflow
  if (isNullConstant(N1))
    return OFK_Never;

  KnownBits N0Known = computeKnownBits(N0);
  KnownBits N1Known = computeKnownBits(N1);
  ConstantRange N0Range = ConstantRange::fromKnownBits(N0Known, false);
  ConstantRange N1Range = ConstantRange::fromKnownBits(N1Known, false);
  return mapOverflowResult(N0Range.unsignedSubMayOverflow(N1Range));
}

SelectionDAG::OverflowKind
SelectionDAG::computeOverflowForUnsignedMul(SDValue N0, SDValue N1) const {
  // X * 0 and X * 1 never overflow.
  if (isNullConstant(N1) || isOneConstant(N1))
    return OFK_Never;

  KnownBits N0Known = computeKnownBits(N0);
  KnownBits N1Known = computeKnownBits(N1);
  ConstantRange N0Range = ConstantRange::fromKnownBits(N0Known, false);
  ConstantRange N1Range = ConstantRange::fromKnownBits(N1Known, false);
  return mapOverflowResult(N0Range.unsignedMulMayOverflow(N1Range));
}

SelectionDAG::OverflowKind
SelectionDAG::computeOverflowForSignedMul(SDValue N0, SDValue N1) const {
  // X * 0 and X * 1 never overflow.
  if (isNullConstant(N1) || isOneConstant(N1))
    return OFK_Never;

  // Get the size of the result.
  unsigned BitWidth = N0.getScalarValueSizeInBits();

  // Sum of the sign bits.
  unsigned SignBits = ComputeNumSignBits(N0) + ComputeNumSignBits(N1);

  // If we have enough sign bits, then there's no overflow.
  if (SignBits > BitWidth + 1)
    return OFK_Never;

  if (SignBits == BitWidth + 1) {
    // The overflow occurs when the true multiplication of the
    // the operands is the minimum negative number.
    KnownBits N0Known = computeKnownBits(N0);
    KnownBits N1Known = computeKnownBits(N1);
    // If one of the operands is non-negative, then there's no
    // overflow.
    if (N0Known.isNonNegative() || N1Known.isNonNegative())
      return OFK_Never;
  }

  return OFK_Sometime;
}

bool SelectionDAG::isKnownToBeAPowerOfTwo(SDValue Val, unsigned Depth) const {
  if (Depth >= MaxRecursionDepth)
    return false; // Limit search depth.

  EVT OpVT = Val.getValueType();
  unsigned BitWidth = OpVT.getScalarSizeInBits();

  // Is the constant a known power of 2?
  if (ISD::matchUnaryPredicate(Val, [BitWidth](ConstantSDNode *C) {
        return C->getAPIntValue().zextOrTrunc(BitWidth).isPowerOf2();
      }))
    return true;

  // A left-shift of a constant one will have exactly one bit set because
  // shifting the bit off the end is undefined.
  if (Val.getOpcode() == ISD::SHL) {
    auto *C = isConstOrConstSplat(Val.getOperand(0));
    if (C && C->getAPIntValue() == 1)
      return true;
    return isKnownToBeAPowerOfTwo(Val.getOperand(0), Depth + 1) &&
           isKnownNeverZero(Val, Depth);
  }

  // Similarly, a logical right-shift of a constant sign-bit will have exactly
  // one bit set.
  if (Val.getOpcode() == ISD::SRL) {
    auto *C = isConstOrConstSplat(Val.getOperand(0));
    if (C && C->getAPIntValue().isSignMask())
      return true;
    return isKnownToBeAPowerOfTwo(Val.getOperand(0), Depth + 1) &&
           isKnownNeverZero(Val, Depth);
  }

  if (Val.getOpcode() == ISD::ROTL || Val.getOpcode() == ISD::ROTR)
    return isKnownToBeAPowerOfTwo(Val.getOperand(0), Depth + 1);

  // Are all operands of a build vector constant powers of two?
  if (Val.getOpcode() == ISD::BUILD_VECTOR)
    if (llvm::all_of(Val->ops(), [BitWidth](SDValue E) {
          if (ConstantSDNode *C = dyn_cast<ConstantSDNode>(E))
            return C->getAPIntValue().zextOrTrunc(BitWidth).isPowerOf2();
          return false;
        }))
      return true;

  // Is the operand of a splat vector a constant power of two?
  if (Val.getOpcode() == ISD::SPLAT_VECTOR)
    if (ConstantSDNode *C = dyn_cast<ConstantSDNode>(Val->getOperand(0)))
      if (C->getAPIntValue().zextOrTrunc(BitWidth).isPowerOf2())
        return true;

  // vscale(power-of-two) is a power-of-two for some targets
  if (Val.getOpcode() == ISD::VSCALE &&
      getTargetLoweringInfo().isVScaleKnownToBeAPowerOfTwo() &&
      isKnownToBeAPowerOfTwo(Val.getOperand(0), Depth + 1))
    return true;

  if (Val.getOpcode() == ISD::SMIN || Val.getOpcode() == ISD::SMAX ||
      Val.getOpcode() == ISD::UMIN || Val.getOpcode() == ISD::UMAX)
    return isKnownToBeAPowerOfTwo(Val.getOperand(1), Depth + 1) &&
           isKnownToBeAPowerOfTwo(Val.getOperand(0), Depth + 1);

  if (Val.getOpcode() == ISD::SELECT || Val.getOpcode() == ISD::VSELECT)
    return isKnownToBeAPowerOfTwo(Val.getOperand(2), Depth + 1) &&
           isKnownToBeAPowerOfTwo(Val.getOperand(1), Depth + 1);

  // Looking for `x & -x` pattern:
  // If x == 0:
  //    x & -x -> 0
  // If x != 0:
  //    x & -x -> non-zero pow2
  // so if we find the pattern return whether we know `x` is non-zero.
  SDValue X;
  if (sd_match(Val, m_And(m_Value(X), m_Neg(m_Deferred(X)))))
    return isKnownNeverZero(X, Depth);

  if (Val.getOpcode() == ISD::ZERO_EXTEND)
    return isKnownToBeAPowerOfTwo(Val.getOperand(0), Depth + 1);

  // More could be done here, though the above checks are enough
  // to handle some common cases.
  return false;
}

bool SelectionDAG::isKnownToBeAPowerOfTwoFP(SDValue Val, unsigned Depth) const {
  if (ConstantFPSDNode *C1 = isConstOrConstSplatFP(Val, true))
    return C1->getValueAPF().getExactLog2Abs() >= 0;

  if (Val.getOpcode() == ISD::UINT_TO_FP || Val.getOpcode() == ISD::SINT_TO_FP)
    return isKnownToBeAPowerOfTwo(Val.getOperand(0), Depth + 1);

  return false;
}

unsigned SelectionDAG::ComputeNumSignBits(SDValue Op, unsigned Depth) const {
  EVT VT = Op.getValueType();

  // Since the number of lanes in a scalable vector is unknown at compile time,
  // we track one bit which is implicitly broadcast to all lanes.  This means
  // that all lanes in a scalable vector are considered demanded.
  APInt DemandedElts = VT.isFixedLengthVector()
                           ? APInt::getAllOnes(VT.getVectorNumElements())
                           : APInt(1, 1);
  return ComputeNumSignBits(Op, DemandedElts, Depth);
}

unsigned SelectionDAG::ComputeNumSignBits(SDValue Op, const APInt &DemandedElts,
                                          unsigned Depth) const {
  EVT VT = Op.getValueType();
  assert((VT.isInteger() || VT.isFloatingPoint()) && "Invalid VT!");
  unsigned VTBits = VT.getScalarSizeInBits();
  unsigned NumElts = DemandedElts.getBitWidth();
  unsigned Tmp, Tmp2;
  unsigned FirstAnswer = 1;

  if (auto *C = dyn_cast<ConstantSDNode>(Op)) {
    const APInt &Val = C->getAPIntValue();
    return Val.getNumSignBits();
  }

  if (Depth >= MaxRecursionDepth)
    return 1;  // Limit search depth.

  if (!DemandedElts)
    return 1;  // No demanded elts, better to assume we don't know anything.

  unsigned Opcode = Op.getOpcode();
  switch (Opcode) {
  default: break;
  case ISD::AssertSext:
    Tmp = cast<VTSDNode>(Op.getOperand(1))->getVT().getSizeInBits();
    return VTBits-Tmp+1;
  case ISD::AssertZext:
    Tmp = cast<VTSDNode>(Op.getOperand(1))->getVT().getSizeInBits();
    return VTBits-Tmp;
  case ISD::MERGE_VALUES:
    return ComputeNumSignBits(Op.getOperand(Op.getResNo()), DemandedElts,
                              Depth + 1);
  case ISD::SPLAT_VECTOR: {
    // Check if the sign bits of source go down as far as the truncated value.
    unsigned NumSrcBits = Op.getOperand(0).getValueSizeInBits();
    unsigned NumSrcSignBits = ComputeNumSignBits(Op.getOperand(0), Depth + 1);
    if (NumSrcSignBits > (NumSrcBits - VTBits))
      return NumSrcSignBits - (NumSrcBits - VTBits);
    break;
  }
  case ISD::BUILD_VECTOR:
    assert(!VT.isScalableVector());
    Tmp = VTBits;
    for (unsigned i = 0, e = Op.getNumOperands(); (i < e) && (Tmp > 1); ++i) {
      if (!DemandedElts[i])
        continue;

      SDValue SrcOp = Op.getOperand(i);
      // BUILD_VECTOR can implicitly truncate sources, we handle this specially
      // for constant nodes to ensure we only look at the sign bits.
      if (ConstantSDNode *C = dyn_cast<ConstantSDNode>(SrcOp)) {
        APInt T = C->getAPIntValue().trunc(VTBits);
        Tmp2 = T.getNumSignBits();
      } else {
        Tmp2 = ComputeNumSignBits(SrcOp, Depth + 1);

        if (SrcOp.getValueSizeInBits() != VTBits) {
          assert(SrcOp.getValueSizeInBits() > VTBits &&
                 "Expected BUILD_VECTOR implicit truncation");
          unsigned ExtraBits = SrcOp.getValueSizeInBits() - VTBits;
          Tmp2 = (Tmp2 > ExtraBits ? Tmp2 - ExtraBits : 1);
        }
      }
      Tmp = std::min(Tmp, Tmp2);
    }
    return Tmp;

  case ISD::VECTOR_SHUFFLE: {
    // Collect the minimum number of sign bits that are shared by every vector
    // element referenced by the shuffle.
    APInt DemandedLHS, DemandedRHS;
    const ShuffleVectorSDNode *SVN = cast<ShuffleVectorSDNode>(Op);
    assert(NumElts == SVN->getMask().size() && "Unexpected vector size");
    if (!getShuffleDemandedElts(NumElts, SVN->getMask(), DemandedElts,
                                DemandedLHS, DemandedRHS))
      return 1;

    Tmp = std::numeric_limits<unsigned>::max();
    if (!!DemandedLHS)
      Tmp = ComputeNumSignBits(Op.getOperand(0), DemandedLHS, Depth + 1);
    if (!!DemandedRHS) {
      Tmp2 = ComputeNumSignBits(Op.getOperand(1), DemandedRHS, Depth + 1);
      Tmp = std::min(Tmp, Tmp2);
    }
    // If we don't know anything, early out and try computeKnownBits fall-back.
    if (Tmp == 1)
      break;
    assert(Tmp <= VTBits && "Failed to determine minimum sign bits");
    return Tmp;
  }

  case ISD::BITCAST: {
    if (VT.isScalableVector())
      break;
    SDValue N0 = Op.getOperand(0);
    EVT SrcVT = N0.getValueType();
    unsigned SrcBits = SrcVT.getScalarSizeInBits();

    // Ignore bitcasts from unsupported types..
    if (!(SrcVT.isInteger() || SrcVT.isFloatingPoint()))
      break;

    // Fast handling of 'identity' bitcasts.
    if (VTBits == SrcBits)
      return ComputeNumSignBits(N0, DemandedElts, Depth + 1);

    bool IsLE = getDataLayout().isLittleEndian();

    // Bitcast 'large element' scalar/vector to 'small element' vector.
    if ((SrcBits % VTBits) == 0) {
      assert(VT.isVector() && "Expected bitcast to vector");

      unsigned Scale = SrcBits / VTBits;
      APInt SrcDemandedElts =
          APIntOps::ScaleBitMask(DemandedElts, NumElts / Scale);

      // Fast case - sign splat can be simply split across the small elements.
      Tmp = ComputeNumSignBits(N0, SrcDemandedElts, Depth + 1);
      if (Tmp == SrcBits)
        return VTBits;

      // Slow case - determine how far the sign extends into each sub-element.
      Tmp2 = VTBits;
      for (unsigned i = 0; i != NumElts; ++i)
        if (DemandedElts[i]) {
          unsigned SubOffset = i % Scale;
          SubOffset = (IsLE ? ((Scale - 1) - SubOffset) : SubOffset);
          SubOffset = SubOffset * VTBits;
          if (Tmp <= SubOffset)
            return 1;
          Tmp2 = std::min(Tmp2, Tmp - SubOffset);
        }
      return Tmp2;
    }
    break;
  }

  case ISD::FP_TO_SINT_SAT:
    // FP_TO_SINT_SAT produces a signed value that fits in the saturating VT.
    Tmp = cast<VTSDNode>(Op.getOperand(1))->getVT().getScalarSizeInBits();
    return VTBits - Tmp + 1;
  case ISD::SIGN_EXTEND:
    Tmp = VTBits - Op.getOperand(0).getScalarValueSizeInBits();
    return ComputeNumSignBits(Op.getOperand(0), DemandedElts, Depth+1) + Tmp;
  case ISD::SIGN_EXTEND_INREG:
    // Max of the input and what this extends.
    Tmp = cast<VTSDNode>(Op.getOperand(1))->getVT().getScalarSizeInBits();
    Tmp = VTBits-Tmp+1;
    Tmp2 = ComputeNumSignBits(Op.getOperand(0), DemandedElts, Depth+1);
    return std::max(Tmp, Tmp2);
  case ISD::SIGN_EXTEND_VECTOR_INREG: {
    if (VT.isScalableVector())
      break;
    SDValue Src = Op.getOperand(0);
    EVT SrcVT = Src.getValueType();
    APInt DemandedSrcElts = DemandedElts.zext(SrcVT.getVectorNumElements());
    Tmp = VTBits - SrcVT.getScalarSizeInBits();
    return ComputeNumSignBits(Src, DemandedSrcElts, Depth+1) + Tmp;
  }
  case ISD::SRA:
    Tmp = ComputeNumSignBits(Op.getOperand(0), DemandedElts, Depth + 1);
    // SRA X, C -> adds C sign bits.
    if (std::optional<uint64_t> ShAmt =
            getValidMinimumShiftAmount(Op, DemandedElts, Depth + 1))
      Tmp = std::min<uint64_t>(Tmp + *ShAmt, VTBits);
    return Tmp;
  case ISD::SHL:
    if (std::optional<ConstantRange> ShAmtRange =
            getValidShiftAmountRange(Op, DemandedElts, Depth + 1)) {
      uint64_t MaxShAmt = ShAmtRange->getUnsignedMax().getZExtValue();
      uint64_t MinShAmt = ShAmtRange->getUnsignedMin().getZExtValue();
      // Try to look through ZERO/SIGN/ANY_EXTEND. If all extended bits are
      // shifted out, then we can compute the number of sign bits for the
      // operand being extended. A future improvement could be to pass along the
      // "shifted left by" information in the recursive calls to
      // ComputeKnownSignBits. Allowing us to handle this more generically.
      if (ISD::isExtOpcode(Op.getOperand(0).getOpcode())) {
        SDValue Ext = Op.getOperand(0);
        EVT ExtVT = Ext.getValueType();
        SDValue Extendee = Ext.getOperand(0);
        EVT ExtendeeVT = Extendee.getValueType();
        uint64_t SizeDifference =
            ExtVT.getScalarSizeInBits() - ExtendeeVT.getScalarSizeInBits();
        if (SizeDifference <= MinShAmt) {
          Tmp = SizeDifference +
                ComputeNumSignBits(Extendee, DemandedElts, Depth + 1);
          if (MaxShAmt < Tmp)
            return Tmp - MaxShAmt;
        }
      }
      // shl destroys sign bits, ensure it doesn't shift out all sign bits.
      Tmp = ComputeNumSignBits(Op.getOperand(0), DemandedElts, Depth + 1);
      if (MaxShAmt < Tmp)
        return Tmp - MaxShAmt;
    }
    break;
  case ISD::AND:
  case ISD::OR:
  case ISD::XOR:    // NOT is handled here.
    // Logical binary ops preserve the number of sign bits at the worst.
    Tmp = ComputeNumSignBits(Op.getOperand(0), DemandedElts, Depth+1);
    if (Tmp != 1) {
      Tmp2 = ComputeNumSignBits(Op.getOperand(1), DemandedElts, Depth+1);
      FirstAnswer = std::min(Tmp, Tmp2);
      // We computed what we know about the sign bits as our first
      // answer. Now proceed to the generic code that uses
      // computeKnownBits, and pick whichever answer is better.
    }
    break;

  case ISD::SELECT:
  case ISD::VSELECT:
    Tmp = ComputeNumSignBits(Op.getOperand(1), DemandedElts, Depth+1);
    if (Tmp == 1) return 1;  // Early out.
    Tmp2 = ComputeNumSignBits(Op.getOperand(2), DemandedElts, Depth+1);
    return std::min(Tmp, Tmp2);
  case ISD::SELECT_CC:
    Tmp = ComputeNumSignBits(Op.getOperand(2), DemandedElts, Depth+1);
    if (Tmp == 1) return 1;  // Early out.
    Tmp2 = ComputeNumSignBits(Op.getOperand(3), DemandedElts, Depth+1);
    return std::min(Tmp, Tmp2);

  case ISD::SMIN:
  case ISD::SMAX: {
    // If we have a clamp pattern, we know that the number of sign bits will be
    // the minimum of the clamp min/max range.
    bool IsMax = (Opcode == ISD::SMAX);
    ConstantSDNode *CstLow = nullptr, *CstHigh = nullptr;
    if ((CstLow = isConstOrConstSplat(Op.getOperand(1), DemandedElts)))
      if (Op.getOperand(0).getOpcode() == (IsMax ? ISD::SMIN : ISD::SMAX))
        CstHigh =
            isConstOrConstSplat(Op.getOperand(0).getOperand(1), DemandedElts);
    if (CstLow && CstHigh) {
      if (!IsMax)
        std::swap(CstLow, CstHigh);
      if (CstLow->getAPIntValue().sle(CstHigh->getAPIntValue())) {
        Tmp = CstLow->getAPIntValue().getNumSignBits();
        Tmp2 = CstHigh->getAPIntValue().getNumSignBits();
        return std::min(Tmp, Tmp2);
      }
    }

    // Fallback - just get the minimum number of sign bits of the operands.
    Tmp = ComputeNumSignBits(Op.getOperand(0), DemandedElts, Depth + 1);
    if (Tmp == 1)
      return 1;  // Early out.
    Tmp2 = ComputeNumSignBits(Op.getOperand(1), DemandedElts, Depth + 1);
    return std::min(Tmp, Tmp2);
  }
  case ISD::UMIN:
  case ISD::UMAX:
    Tmp = ComputeNumSignBits(Op.getOperand(0), DemandedElts, Depth + 1);
    if (Tmp == 1)
      return 1;  // Early out.
    Tmp2 = ComputeNumSignBits(Op.getOperand(1), DemandedElts, Depth + 1);
    return std::min(Tmp, Tmp2);
  case ISD::SSUBO_CARRY:
  case ISD::USUBO_CARRY:
    // sub_carry(x,x,c) -> 0/-1 (sext carry)
    if (Op.getResNo() == 0 && Op.getOperand(0) == Op.getOperand(1))
      return VTBits;
    [[fallthrough]];
  case ISD::SADDO:
  case ISD::UADDO:
  case ISD::SADDO_CARRY:
  case ISD::UADDO_CARRY:
  case ISD::SSUBO:
  case ISD::USUBO:
  case ISD::SMULO:
  case ISD::UMULO:
    if (Op.getResNo() != 1)
      break;
    // The boolean result conforms to getBooleanContents.  Fall through.
    // If setcc returns 0/-1, all bits are sign bits.
    // We know that we have an integer-based boolean since these operations
    // are only available for integer.
    if (TLI->getBooleanContents(VT.isVector(), false) ==
        TargetLowering::ZeroOrNegativeOneBooleanContent)
      return VTBits;
    break;
  case ISD::SETCC:
  case ISD::SETCCCARRY:
  case ISD::STRICT_FSETCC:
  case ISD::STRICT_FSETCCS: {
    unsigned OpNo = Op->isStrictFPOpcode() ? 1 : 0;
    // If setcc returns 0/-1, all bits are sign bits.
    if (TLI->getBooleanContents(Op.getOperand(OpNo).getValueType()) ==
        TargetLowering::ZeroOrNegativeOneBooleanContent)
      return VTBits;
    break;
  }
  case ISD::ROTL:
  case ISD::ROTR:
    Tmp = ComputeNumSignBits(Op.getOperand(0), DemandedElts, Depth + 1);

    // If we're rotating an 0/-1 value, then it stays an 0/-1 value.
    if (Tmp == VTBits)
      return VTBits;

    if (ConstantSDNode *C =
            isConstOrConstSplat(Op.getOperand(1), DemandedElts)) {
      unsigned RotAmt = C->getAPIntValue().urem(VTBits);

      // Handle rotate right by N like a rotate left by 32-N.
      if (Opcode == ISD::ROTR)
        RotAmt = (VTBits - RotAmt) % VTBits;

      // If we aren't rotating out all of the known-in sign bits, return the
      // number that are left.  This handles rotl(sext(x), 1) for example.
      if (Tmp > (RotAmt + 1)) return (Tmp - RotAmt);
    }
    break;
  case ISD::ADD:
  case ISD::ADDC:
    // Add can have at most one carry bit.  Thus we know that the output
    // is, at worst, one more bit than the inputs.
    Tmp = ComputeNumSignBits(Op.getOperand(0), DemandedElts, Depth + 1);
    if (Tmp == 1) return 1; // Early out.

    // Special case decrementing a value (ADD X, -1):
    if (ConstantSDNode *CRHS =
            isConstOrConstSplat(Op.getOperand(1), DemandedElts))
      if (CRHS->isAllOnes()) {
        KnownBits Known =
            computeKnownBits(Op.getOperand(0), DemandedElts, Depth + 1);

        // If the input is known to be 0 or 1, the output is 0/-1, which is all
        // sign bits set.
        if ((Known.Zero | 1).isAllOnes())
          return VTBits;

        // If we are subtracting one from a positive number, there is no carry
        // out of the result.
        if (Known.isNonNegative())
          return Tmp;
      }

    Tmp2 = ComputeNumSignBits(Op.getOperand(1), DemandedElts, Depth + 1);
    if (Tmp2 == 1) return 1; // Early out.
    return std::min(Tmp, Tmp2) - 1;
  case ISD::SUB:
    Tmp2 = ComputeNumSignBits(Op.getOperand(1), DemandedElts, Depth + 1);
    if (Tmp2 == 1) return 1; // Early out.

    // Handle NEG.
    if (ConstantSDNode *CLHS =
            isConstOrConstSplat(Op.getOperand(0), DemandedElts))
      if (CLHS->isZero()) {
        KnownBits Known =
            computeKnownBits(Op.getOperand(1), DemandedElts, Depth + 1);
        // If the input is known to be 0 or 1, the output is 0/-1, which is all
        // sign bits set.
        if ((Known.Zero | 1).isAllOnes())
          return VTBits;

        // If the input is known to be positive (the sign bit is known clear),
        // the output of the NEG has the same number of sign bits as the input.
        if (Known.isNonNegative())
          return Tmp2;

        // Otherwise, we treat this like a SUB.
      }

    // Sub can have at most one carry bit.  Thus we know that the output
    // is, at worst, one more bit than the inputs.
    Tmp = ComputeNumSignBits(Op.getOperand(0), DemandedElts, Depth + 1);
    if (Tmp == 1) return 1; // Early out.
    return std::min(Tmp, Tmp2) - 1;
  case ISD::MUL: {
    // The output of the Mul can be at most twice the valid bits in the inputs.
    unsigned SignBitsOp0 = ComputeNumSignBits(Op.getOperand(0), Depth + 1);
    if (SignBitsOp0 == 1)
      break;
    unsigned SignBitsOp1 = ComputeNumSignBits(Op.getOperand(1), Depth + 1);
    if (SignBitsOp1 == 1)
      break;
    unsigned OutValidBits =
        (VTBits - SignBitsOp0 + 1) + (VTBits - SignBitsOp1 + 1);
    return OutValidBits > VTBits ? 1 : VTBits - OutValidBits + 1;
  }
  case ISD::AVGCEILS:
  case ISD::AVGFLOORS:
    Tmp = ComputeNumSignBits(Op.getOperand(0), DemandedElts, Depth + 1);
    if (Tmp == 1)
      return 1; // Early out.
    Tmp2 = ComputeNumSignBits(Op.getOperand(1), DemandedElts, Depth + 1);
    return std::min(Tmp, Tmp2);
  case ISD::SREM:
    // The sign bit is the LHS's sign bit, except when the result of the
    // remainder is zero. The magnitude of the result should be less than or
    // equal to the magnitude of the LHS. Therefore, the result should have
    // at least as many sign bits as the left hand side.
    return ComputeNumSignBits(Op.getOperand(0), DemandedElts, Depth + 1);
  case ISD::TRUNCATE: {
    // Check if the sign bits of source go down as far as the truncated value.
    unsigned NumSrcBits = Op.getOperand(0).getScalarValueSizeInBits();
    unsigned NumSrcSignBits = ComputeNumSignBits(Op.getOperand(0), Depth + 1);
    if (NumSrcSignBits > (NumSrcBits - VTBits))
      return NumSrcSignBits - (NumSrcBits - VTBits);
    break;
  }
  case ISD::EXTRACT_ELEMENT: {
    if (VT.isScalableVector())
      break;
    const int KnownSign = ComputeNumSignBits(Op.getOperand(0), Depth+1);
    const int BitWidth = Op.getValueSizeInBits();
    const int Items = Op.getOperand(0).getValueSizeInBits() / BitWidth;

    // Get reverse index (starting from 1), Op1 value indexes elements from
    // little end. Sign starts at big end.
    const int rIndex = Items - 1 - Op.getConstantOperandVal(1);

    // If the sign portion ends in our element the subtraction gives correct
    // result. Otherwise it gives either negative or > bitwidth result
    return std::clamp(KnownSign - rIndex * BitWidth, 0, BitWidth);
  }
  case ISD::INSERT_VECTOR_ELT: {
    if (VT.isScalableVector())
      break;
    // If we know the element index, split the demand between the
    // source vector and the inserted element, otherwise assume we need
    // the original demanded vector elements and the value.
    SDValue InVec = Op.getOperand(0);
    SDValue InVal = Op.getOperand(1);
    SDValue EltNo = Op.getOperand(2);
    bool DemandedVal = true;
    APInt DemandedVecElts = DemandedElts;
    auto *CEltNo = dyn_cast<ConstantSDNode>(EltNo);
    if (CEltNo && CEltNo->getAPIntValue().ult(NumElts)) {
      unsigned EltIdx = CEltNo->getZExtValue();
      DemandedVal = !!DemandedElts[EltIdx];
      DemandedVecElts.clearBit(EltIdx);
    }
    Tmp = std::numeric_limits<unsigned>::max();
    if (DemandedVal) {
      // TODO - handle implicit truncation of inserted elements.
      if (InVal.getScalarValueSizeInBits() != VTBits)
        break;
      Tmp2 = ComputeNumSignBits(InVal, Depth + 1);
      Tmp = std::min(Tmp, Tmp2);
    }
    if (!!DemandedVecElts) {
      Tmp2 = ComputeNumSignBits(InVec, DemandedVecElts, Depth + 1);
      Tmp = std::min(Tmp, Tmp2);
    }
    assert(Tmp <= VTBits && "Failed to determine minimum sign bits");
    return Tmp;
  }
  case ISD::EXTRACT_VECTOR_ELT: {
    assert(!VT.isScalableVector());
    SDValue InVec = Op.getOperand(0);
    SDValue EltNo = Op.getOperand(1);
    EVT VecVT = InVec.getValueType();
    // ComputeNumSignBits not yet implemented for scalable vectors.
    if (VecVT.isScalableVector())
      break;
    const unsigned BitWidth = Op.getValueSizeInBits();
    const unsigned EltBitWidth = Op.getOperand(0).getScalarValueSizeInBits();
    const unsigned NumSrcElts = VecVT.getVectorNumElements();

    // If BitWidth > EltBitWidth the value is anyext:ed, and we do not know
    // anything about sign bits. But if the sizes match we can derive knowledge
    // about sign bits from the vector operand.
    if (BitWidth != EltBitWidth)
      break;

    // If we know the element index, just demand that vector element, else for
    // an unknown element index, ignore DemandedElts and demand them all.
    APInt DemandedSrcElts = APInt::getAllOnes(NumSrcElts);
    auto *ConstEltNo = dyn_cast<ConstantSDNode>(EltNo);
    if (ConstEltNo && ConstEltNo->getAPIntValue().ult(NumSrcElts))
      DemandedSrcElts =
          APInt::getOneBitSet(NumSrcElts, ConstEltNo->getZExtValue());

    return ComputeNumSignBits(InVec, DemandedSrcElts, Depth + 1);
  }
  case ISD::EXTRACT_SUBVECTOR: {
    // Offset the demanded elts by the subvector index.
    SDValue Src = Op.getOperand(0);
    // Bail until we can represent demanded elements for scalable vectors.
    if (Src.getValueType().isScalableVector())
      break;
    uint64_t Idx = Op.getConstantOperandVal(1);
    unsigned NumSrcElts = Src.getValueType().getVectorNumElements();
    APInt DemandedSrcElts = DemandedElts.zext(NumSrcElts).shl(Idx);
    return ComputeNumSignBits(Src, DemandedSrcElts, Depth + 1);
  }
  case ISD::CONCAT_VECTORS: {
    if (VT.isScalableVector())
      break;
    // Determine the minimum number of sign bits across all demanded
    // elts of the input vectors. Early out if the result is already 1.
    Tmp = std::numeric_limits<unsigned>::max();
    EVT SubVectorVT = Op.getOperand(0).getValueType();
    unsigned NumSubVectorElts = SubVectorVT.getVectorNumElements();
    unsigned NumSubVectors = Op.getNumOperands();
    for (unsigned i = 0; (i < NumSubVectors) && (Tmp > 1); ++i) {
      APInt DemandedSub =
          DemandedElts.extractBits(NumSubVectorElts, i * NumSubVectorElts);
      if (!DemandedSub)
        continue;
      Tmp2 = ComputeNumSignBits(Op.getOperand(i), DemandedSub, Depth + 1);
      Tmp = std::min(Tmp, Tmp2);
    }
    assert(Tmp <= VTBits && "Failed to determine minimum sign bits");
    return Tmp;
  }
  case ISD::INSERT_SUBVECTOR: {
    if (VT.isScalableVector())
      break;
    // Demand any elements from the subvector and the remainder from the src its
    // inserted into.
    SDValue Src = Op.getOperand(0);
    SDValue Sub = Op.getOperand(1);
    uint64_t Idx = Op.getConstantOperandVal(2);
    unsigned NumSubElts = Sub.getValueType().getVectorNumElements();
    APInt DemandedSubElts = DemandedElts.extractBits(NumSubElts, Idx);
    APInt DemandedSrcElts = DemandedElts;
    DemandedSrcElts.clearBits(Idx, Idx + NumSubElts);

    Tmp = std::numeric_limits<unsigned>::max();
    if (!!DemandedSubElts) {
      Tmp = ComputeNumSignBits(Sub, DemandedSubElts, Depth + 1);
      if (Tmp == 1)
        return 1; // early-out
    }
    if (!!DemandedSrcElts) {
      Tmp2 = ComputeNumSignBits(Src, DemandedSrcElts, Depth + 1);
      Tmp = std::min(Tmp, Tmp2);
    }
    assert(Tmp <= VTBits && "Failed to determine minimum sign bits");
    return Tmp;
  }
  case ISD::LOAD: {
    LoadSDNode *LD = cast<LoadSDNode>(Op);
    if (const MDNode *Ranges = LD->getRanges()) {
      if (DemandedElts != 1)
        break;

      ConstantRange CR = getConstantRangeFromMetadata(*Ranges);
      if (VTBits > CR.getBitWidth()) {
        switch (LD->getExtensionType()) {
        case ISD::SEXTLOAD:
          CR = CR.signExtend(VTBits);
          break;
        case ISD::ZEXTLOAD:
          CR = CR.zeroExtend(VTBits);
          break;
        default:
          break;
        }
      }

      if (VTBits != CR.getBitWidth())
        break;
      return std::min(CR.getSignedMin().getNumSignBits(),
                      CR.getSignedMax().getNumSignBits());
    }

    break;
  }
  case ISD::ATOMIC_CMP_SWAP:
  case ISD::ATOMIC_CMP_SWAP_WITH_SUCCESS:
  case ISD::ATOMIC_SWAP:
  case ISD::ATOMIC_LOAD_ADD:
  case ISD::ATOMIC_LOAD_SUB:
  case ISD::ATOMIC_LOAD_AND:
  case ISD::ATOMIC_LOAD_CLR:
  case ISD::ATOMIC_LOAD_OR:
  case ISD::ATOMIC_LOAD_XOR:
  case ISD::ATOMIC_LOAD_NAND:
  case ISD::ATOMIC_LOAD_MIN:
  case ISD::ATOMIC_LOAD_MAX:
  case ISD::ATOMIC_LOAD_UMIN:
  case ISD::ATOMIC_LOAD_UMAX:
  case ISD::ATOMIC_LOAD: {
    auto *AT = cast<AtomicSDNode>(Op);
    // If we are looking at the loaded value.
    if (Op.getResNo() == 0) {
      Tmp = AT->getMemoryVT().getScalarSizeInBits();
      if (Tmp == VTBits)
        return 1; // early-out

      // For atomic_load, prefer to use the extension type.
      if (Op->getOpcode() == ISD::ATOMIC_LOAD) {
        switch (AT->getExtensionType()) {
        default:
          break;
        case ISD::SEXTLOAD:
          return VTBits - Tmp + 1;
        case ISD::ZEXTLOAD:
          return VTBits - Tmp;
        }
      }

      if (TLI->getExtendForAtomicOps() == ISD::SIGN_EXTEND)
        return VTBits - Tmp + 1;
      if (TLI->getExtendForAtomicOps() == ISD::ZERO_EXTEND)
        return VTBits - Tmp;
    }
    break;
  }
  }

  // If we are looking at the loaded value of the SDNode.
  if (Op.getResNo() == 0) {
    // Handle LOADX separately here. EXTLOAD case will fallthrough.
    if (LoadSDNode *LD = dyn_cast<LoadSDNode>(Op)) {
      unsigned ExtType = LD->getExtensionType();
      switch (ExtType) {
      default: break;
      case ISD::SEXTLOAD: // e.g. i16->i32 = '17' bits known.
        Tmp = LD->getMemoryVT().getScalarSizeInBits();
        return VTBits - Tmp + 1;
      case ISD::ZEXTLOAD: // e.g. i16->i32 = '16' bits known.
        Tmp = LD->getMemoryVT().getScalarSizeInBits();
        return VTBits - Tmp;
      case ISD::NON_EXTLOAD:
        if (const Constant *Cst = TLI->getTargetConstantFromLoad(LD)) {
          // We only need to handle vectors - computeKnownBits should handle
          // scalar cases.
          Type *CstTy = Cst->getType();
          if (CstTy->isVectorTy() && !VT.isScalableVector() &&
              (NumElts * VTBits) == CstTy->getPrimitiveSizeInBits() &&
              VTBits == CstTy->getScalarSizeInBits()) {
            Tmp = VTBits;
            for (unsigned i = 0; i != NumElts; ++i) {
              if (!DemandedElts[i])
                continue;
              if (Constant *Elt = Cst->getAggregateElement(i)) {
                if (auto *CInt = dyn_cast<ConstantInt>(Elt)) {
                  const APInt &Value = CInt->getValue();
                  Tmp = std::min(Tmp, Value.getNumSignBits());
                  continue;
                }
                if (auto *CFP = dyn_cast<ConstantFP>(Elt)) {
                  APInt Value = CFP->getValueAPF().bitcastToAPInt();
                  Tmp = std::min(Tmp, Value.getNumSignBits());
                  continue;
                }
              }
              // Unknown type. Conservatively assume no bits match sign bit.
              return 1;
            }
            return Tmp;
          }
        }
        break;
      }
    }
  }

  // Allow the target to implement this method for its nodes.
  if (Opcode >= ISD::BUILTIN_OP_END ||
      Opcode == ISD::INTRINSIC_WO_CHAIN ||
      Opcode == ISD::INTRINSIC_W_CHAIN ||
      Opcode == ISD::INTRINSIC_VOID) {
    // TODO: This can probably be removed once target code is audited.  This
    // is here purely to reduce patch size and review complexity.
    if (!VT.isScalableVector()) {
      unsigned NumBits =
        TLI->ComputeNumSignBitsForTargetNode(Op, DemandedElts, *this, Depth);
      if (NumBits > 1)
        FirstAnswer = std::max(FirstAnswer, NumBits);
    }
  }

  // Finally, if we can prove that the top bits of the result are 0's or 1's,
  // use this information.
  KnownBits Known = computeKnownBits(Op, DemandedElts, Depth);
  return std::max(FirstAnswer, Known.countMinSignBits());
}

unsigned SelectionDAG::ComputeMaxSignificantBits(SDValue Op,
                                                 unsigned Depth) const {
  unsigned SignBits = ComputeNumSignBits(Op, Depth);
  return Op.getScalarValueSizeInBits() - SignBits + 1;
}

unsigned SelectionDAG::ComputeMaxSignificantBits(SDValue Op,
                                                 const APInt &DemandedElts,
                                                 unsigned Depth) const {
  unsigned SignBits = ComputeNumSignBits(Op, DemandedElts, Depth);
  return Op.getScalarValueSizeInBits() - SignBits + 1;
}

bool SelectionDAG::isGuaranteedNotToBeUndefOrPoison(SDValue Op, bool PoisonOnly,
                                                    unsigned Depth) const {
  // Early out for FREEZE.
  if (Op.getOpcode() == ISD::FREEZE)
    return true;

  EVT VT = Op.getValueType();
  APInt DemandedElts = VT.isFixedLengthVector()
                           ? APInt::getAllOnes(VT.getVectorNumElements())
                           : APInt(1, 1);
  return isGuaranteedNotToBeUndefOrPoison(Op, DemandedElts, PoisonOnly, Depth);
}

bool SelectionDAG::isGuaranteedNotToBeUndefOrPoison(SDValue Op,
                                                    const APInt &DemandedElts,
                                                    bool PoisonOnly,
                                                    unsigned Depth) const {
  unsigned Opcode = Op.getOpcode();

  // Early out for FREEZE.
  if (Opcode == ISD::FREEZE)
    return true;

  if (Depth >= MaxRecursionDepth)
    return false; // Limit search depth.

  if (isIntOrFPConstant(Op))
    return true;

  switch (Opcode) {
  case ISD::CONDCODE:
  case ISD::VALUETYPE:
  case ISD::FrameIndex:
  case ISD::TargetFrameIndex:
  case ISD::CopyFromReg:
    return true;

  case ISD::POISON:
    return false;

  case ISD::UNDEF:
    return PoisonOnly;

  case ISD::BUILD_VECTOR:
    // NOTE: BUILD_VECTOR has implicit truncation of wider scalar elements -
    // this shouldn't affect the result.
    for (unsigned i = 0, e = Op.getNumOperands(); i < e; ++i) {
      if (!DemandedElts[i])
        continue;
      if (!isGuaranteedNotToBeUndefOrPoison(Op.getOperand(i), PoisonOnly,
                                            Depth + 1))
        return false;
    }
    return true;

  case ISD::SPLAT_VECTOR:
    return isGuaranteedNotToBeUndefOrPoison(Op.getOperand(0), PoisonOnly,
                                            Depth + 1);

  case ISD::VECTOR_SHUFFLE: {
    APInt DemandedLHS, DemandedRHS;
    auto *SVN = cast<ShuffleVectorSDNode>(Op);
    if (!getShuffleDemandedElts(DemandedElts.getBitWidth(), SVN->getMask(),
                                DemandedElts, DemandedLHS, DemandedRHS,
                                /*AllowUndefElts=*/false))
      return false;
    if (!DemandedLHS.isZero() &&
        !isGuaranteedNotToBeUndefOrPoison(Op.getOperand(0), DemandedLHS,
                                          PoisonOnly, Depth + 1))
      return false;
    if (!DemandedRHS.isZero() &&
        !isGuaranteedNotToBeUndefOrPoison(Op.getOperand(1), DemandedRHS,
                                          PoisonOnly, Depth + 1))
      return false;
    return true;
  }

    // TODO: Search for noundef attributes from library functions.

    // TODO: Pointers dereferenced by ISD::LOAD/STORE ops are noundef.

  default:
    // Allow the target to implement this method for its nodes.
    if (Opcode >= ISD::BUILTIN_OP_END || Opcode == ISD::INTRINSIC_WO_CHAIN ||
        Opcode == ISD::INTRINSIC_W_CHAIN || Opcode == ISD::INTRINSIC_VOID)
      return TLI->isGuaranteedNotToBeUndefOrPoisonForTargetNode(
          Op, DemandedElts, *this, PoisonOnly, Depth);
    break;
  }

  // If Op can't create undef/poison and none of its operands are undef/poison
  // then Op is never undef/poison.
  // NOTE: TargetNodes can handle this in themselves in
  // isGuaranteedNotToBeUndefOrPoisonForTargetNode or let
  // TargetLowering::isGuaranteedNotToBeUndefOrPoisonForTargetNode handle it.
  return !canCreateUndefOrPoison(Op, PoisonOnly, /*ConsiderFlags*/ true,
                                 Depth) &&
         all_of(Op->ops(), [&](SDValue V) {
           return isGuaranteedNotToBeUndefOrPoison(V, PoisonOnly, Depth + 1);
         });
}

bool SelectionDAG::canCreateUndefOrPoison(SDValue Op, bool PoisonOnly,
                                          bool ConsiderFlags,
                                          unsigned Depth) const {
  EVT VT = Op.getValueType();
  APInt DemandedElts = VT.isFixedLengthVector()
                           ? APInt::getAllOnes(VT.getVectorNumElements())
                           : APInt(1, 1);
  return canCreateUndefOrPoison(Op, DemandedElts, PoisonOnly, ConsiderFlags,
                                Depth);
}

bool SelectionDAG::canCreateUndefOrPoison(SDValue Op, const APInt &DemandedElts,
                                          bool PoisonOnly, bool ConsiderFlags,
                                          unsigned Depth) const {
  if (ConsiderFlags && Op->hasPoisonGeneratingFlags())
    return true;

  unsigned Opcode = Op.getOpcode();
  switch (Opcode) {
  case ISD::AssertSext:
  case ISD::AssertZext:
  case ISD::AssertAlign:
  case ISD::AssertNoFPClass:
    // Assertion nodes can create poison if the assertion fails.
    return true;

  case ISD::FREEZE:
  case ISD::CONCAT_VECTORS:
  case ISD::INSERT_SUBVECTOR:
  case ISD::EXTRACT_SUBVECTOR:
  case ISD::SADDSAT:
  case ISD::UADDSAT:
  case ISD::SSUBSAT:
  case ISD::USUBSAT:
  case ISD::MULHU:
  case ISD::MULHS:
  case ISD::ABDU:
  case ISD::ABDS:
  case ISD::SMIN:
  case ISD::SMAX:
  case ISD::UMIN:
  case ISD::UMAX:
  case ISD::AND:
  case ISD::XOR:
  case ISD::ROTL:
  case ISD::ROTR:
  case ISD::FSHL:
  case ISD::FSHR:
  case ISD::BSWAP:
  case ISD::CTTZ:
  case ISD::CTLZ:
  case ISD::CTPOP:
  case ISD::BITREVERSE:
  case ISD::PARITY:
  case ISD::SIGN_EXTEND:
  case ISD::TRUNCATE:
  case ISD::SIGN_EXTEND_INREG:
  case ISD::SIGN_EXTEND_VECTOR_INREG:
  case ISD::ZERO_EXTEND_VECTOR_INREG:
  case ISD::BITCAST:
  case ISD::BUILD_VECTOR:
  case ISD::BUILD_PAIR:
  case ISD::SPLAT_VECTOR:
  case ISD::FABS:
    return false;

  case ISD::ABS:
    // ISD::ABS defines abs(INT_MIN) -> INT_MIN and never generates poison.
    // Different to Intrinsic::abs.
    return false;

  case ISD::ADDC:
  case ISD::SUBC:
  case ISD::ADDE:
  case ISD::SUBE:
  case ISD::SADDO:
  case ISD::SSUBO:
  case ISD::SMULO:
  case ISD::SADDO_CARRY:
  case ISD::SSUBO_CARRY:
  case ISD::UADDO:
  case ISD::USUBO:
  case ISD::UMULO:
  case ISD::UADDO_CARRY:
  case ISD::USUBO_CARRY:
    // No poison on result or overflow flags.
    return false;

  case ISD::SELECT_CC:
  case ISD::SETCC: {
    // Integer setcc cannot create undef or poison.
    if (Op.getOperand(0).getValueType().isInteger())
      return false;

    // FP compares are more complicated. They can create poison for nan/infinity
    // based on options and flags. The options and flags also cause special
    // nonan condition codes to be used. Those condition codes may be preserved
    // even if the nonan flag is dropped somewhere.
    unsigned CCOp = Opcode == ISD::SETCC ? 2 : 4;
    ISD::CondCode CCCode = cast<CondCodeSDNode>(Op.getOperand(CCOp))->get();
    if (((unsigned)CCCode & 0x10U))
      return true;

    const TargetOptions &Options = getTarget().Options;
    return Options.NoNaNsFPMath || Options.NoInfsFPMath;
  }

  case ISD::OR:
  case ISD::ZERO_EXTEND:
  case ISD::SELECT:
  case ISD::VSELECT:
  case ISD::ADD:
  case ISD::SUB:
  case ISD::MUL:
  case ISD::FNEG:
  case ISD::FADD:
  case ISD::FSUB:
  case ISD::FMUL:
  case ISD::FDIV:
  case ISD::FREM:
  case ISD::FCOPYSIGN:
    // No poison except from flags (which is handled above)
    return false;

  case ISD::SHL:
  case ISD::SRL:
  case ISD::SRA:
    // If the max shift amount isn't in range, then the shift can
    // create poison.
    return !getValidMaximumShiftAmount(Op, DemandedElts, Depth + 1);

  case ISD::CTTZ_ZERO_UNDEF:
  case ISD::CTLZ_ZERO_UNDEF:
    // If the amount is zero then the result will be poison.
    // TODO: Add isKnownNeverZero DemandedElts handling.
    return !isKnownNeverZero(Op.getOperand(0), Depth + 1);

  case ISD::SCALAR_TO_VECTOR:
    // Check if we demand any upper (undef) elements.
    return !PoisonOnly && DemandedElts.ugt(1);

  case ISD::INSERT_VECTOR_ELT:
  case ISD::EXTRACT_VECTOR_ELT: {
    // Ensure that the element index is in bounds.
    EVT VecVT = Op.getOperand(0).getValueType();
    SDValue Idx = Op.getOperand(Opcode == ISD::INSERT_VECTOR_ELT ? 2 : 1);
    KnownBits KnownIdx = computeKnownBits(Idx, Depth + 1);
    return KnownIdx.getMaxValue().uge(VecVT.getVectorMinNumElements());
  }

  case ISD::VECTOR_SHUFFLE: {
    // Check for any demanded shuffle element that is undef.
    auto *SVN = cast<ShuffleVectorSDNode>(Op);
    for (auto [Idx, Elt] : enumerate(SVN->getMask()))
      if (Elt < 0 && DemandedElts[Idx])
        return true;
    return false;
  }

  default:
    // Allow the target to implement this method for its nodes.
    if (Opcode >= ISD::BUILTIN_OP_END || Opcode == ISD::INTRINSIC_WO_CHAIN ||
        Opcode == ISD::INTRINSIC_W_CHAIN || Opcode == ISD::INTRINSIC_VOID)
      return TLI->canCreateUndefOrPoisonForTargetNode(
          Op, DemandedElts, *this, PoisonOnly, ConsiderFlags, Depth);
    break;
  }

  // Be conservative and return true.
  return true;
}

bool SelectionDAG::isADDLike(SDValue Op, bool NoWrap) const {
  unsigned Opcode = Op.getOpcode();
  if (Opcode == ISD::OR)
    return Op->getFlags().hasDisjoint() ||
           haveNoCommonBitsSet(Op.getOperand(0), Op.getOperand(1));
  if (Opcode == ISD::XOR)
    return !NoWrap && isMinSignedConstant(Op.getOperand(1));
  return false;
}

bool SelectionDAG::isBaseWithConstantOffset(SDValue Op) const {
  return Op.getNumOperands() == 2 && isa<ConstantSDNode>(Op.getOperand(1)) &&
         (Op.isAnyAdd() || isADDLike(Op));
}

bool SelectionDAG::isKnownNeverNaN(SDValue Op, bool SNaN,
                                   unsigned Depth) const {
  EVT VT = Op.getValueType();

  // Since the number of lanes in a scalable vector is unknown at compile time,
  // we track one bit which is implicitly broadcast to all lanes.  This means
  // that all lanes in a scalable vector are considered demanded.
  APInt DemandedElts = VT.isFixedLengthVector()
                           ? APInt::getAllOnes(VT.getVectorNumElements())
                           : APInt(1, 1);

  return isKnownNeverNaN(Op, DemandedElts, SNaN, Depth);
}

bool SelectionDAG::isKnownNeverNaN(SDValue Op, const APInt &DemandedElts,
                                   bool SNaN, unsigned Depth) const {
  assert(!DemandedElts.isZero() && "No demanded elements");

  // If we're told that NaNs won't happen, assume they won't.
  if (getTarget().Options.NoNaNsFPMath || Op->getFlags().hasNoNaNs())
    return true;

  if (Depth >= MaxRecursionDepth)
    return false; // Limit search depth.

  // If the value is a constant, we can obviously see if it is a NaN or not.
  if (const ConstantFPSDNode *C = dyn_cast<ConstantFPSDNode>(Op)) {
    return !C->getValueAPF().isNaN() ||
           (SNaN && !C->getValueAPF().isSignaling());
  }

  unsigned Opcode = Op.getOpcode();
  switch (Opcode) {
  case ISD::FADD:
  case ISD::FSUB:
  case ISD::FMUL:
  case ISD::FDIV:
  case ISD::FREM:
  case ISD::FSIN:
  case ISD::FCOS:
  case ISD::FTAN:
  case ISD::FASIN:
  case ISD::FACOS:
  case ISD::FATAN:
  case ISD::FATAN2:
  case ISD::FSINH:
  case ISD::FCOSH:
  case ISD::FTANH:
  case ISD::FMA:
  case ISD::FMAD: {
    if (SNaN)
      return true;
    // TODO: Need isKnownNeverInfinity
    return false;
  }
  case ISD::FCANONICALIZE:
  case ISD::FEXP:
  case ISD::FEXP2:
  case ISD::FEXP10:
  case ISD::FTRUNC:
  case ISD::FFLOOR:
  case ISD::FCEIL:
  case ISD::FROUND:
  case ISD::FROUNDEVEN:
  case ISD::LROUND:
  case ISD::LLROUND:
  case ISD::FRINT:
  case ISD::LRINT:
  case ISD::LLRINT:
  case ISD::FNEARBYINT:
  case ISD::FLDEXP: {
    if (SNaN)
      return true;
    return isKnownNeverNaN(Op.getOperand(0), DemandedElts, SNaN, Depth + 1);
  }
  case ISD::FABS:
  case ISD::FNEG:
  case ISD::FCOPYSIGN: {
    return isKnownNeverNaN(Op.getOperand(0), DemandedElts, SNaN, Depth + 1);
  }
  case ISD::SELECT:
    return isKnownNeverNaN(Op.getOperand(1), DemandedElts, SNaN, Depth + 1) &&
           isKnownNeverNaN(Op.getOperand(2), DemandedElts, SNaN, Depth + 1);
  case ISD::FP_EXTEND:
  case ISD::FP_ROUND: {
    if (SNaN)
      return true;
    return isKnownNeverNaN(Op.getOperand(0), DemandedElts, SNaN, Depth + 1);
  }
  case ISD::SINT_TO_FP:
  case ISD::UINT_TO_FP:
    return true;
  case ISD::FSQRT: // Need is known positive
  case ISD::FLOG:
  case ISD::FLOG2:
  case ISD::FLOG10:
  case ISD::FPOWI:
  case ISD::FPOW: {
    if (SNaN)
      return true;
    // TODO: Refine on operand
    return false;
  }
  case ISD::FMINNUM:
  case ISD::FMAXNUM:
  case ISD::FMINIMUMNUM:
  case ISD::FMAXIMUMNUM: {
    // Only one needs to be known not-nan, since it will be returned if the
    // other ends up being one.
    return isKnownNeverNaN(Op.getOperand(0), DemandedElts, SNaN, Depth + 1) ||
           isKnownNeverNaN(Op.getOperand(1), DemandedElts, SNaN, Depth + 1);
  }
  case ISD::FMINNUM_IEEE:
  case ISD::FMAXNUM_IEEE: {
    if (SNaN)
      return true;
    // This can return a NaN if either operand is an sNaN, or if both operands
    // are NaN.
    return (isKnownNeverNaN(Op.getOperand(0), DemandedElts, false, Depth + 1) &&
            isKnownNeverSNaN(Op.getOperand(1), DemandedElts, Depth + 1)) ||
           (isKnownNeverNaN(Op.getOperand(1), DemandedElts, false, Depth + 1) &&
            isKnownNeverSNaN(Op.getOperand(0), DemandedElts, Depth + 1));
  }
  case ISD::FMINIMUM:
  case ISD::FMAXIMUM: {
    // TODO: Does this quiet or return the origina NaN as-is?
    return isKnownNeverNaN(Op.getOperand(0), DemandedElts, SNaN, Depth + 1) &&
           isKnownNeverNaN(Op.getOperand(1), DemandedElts, SNaN, Depth + 1);
  }
  case ISD::EXTRACT_VECTOR_ELT: {
    SDValue Src = Op.getOperand(0);
    auto *Idx = dyn_cast<ConstantSDNode>(Op.getOperand(1));
    EVT SrcVT = Src.getValueType();
    if (SrcVT.isFixedLengthVector() && Idx &&
        Idx->getAPIntValue().ult(SrcVT.getVectorNumElements())) {
      APInt DemandedSrcElts = APInt::getOneBitSet(SrcVT.getVectorNumElements(),
                                                  Idx->getZExtValue());
      return isKnownNeverNaN(Src, DemandedSrcElts, SNaN, Depth + 1);
    }
    return isKnownNeverNaN(Src, SNaN, Depth + 1);
  }
  case ISD::EXTRACT_SUBVECTOR: {
    SDValue Src = Op.getOperand(0);
    if (Src.getValueType().isFixedLengthVector()) {
      unsigned Idx = Op.getConstantOperandVal(1);
      unsigned NumSrcElts = Src.getValueType().getVectorNumElements();
      APInt DemandedSrcElts = DemandedElts.zext(NumSrcElts).shl(Idx);
      return isKnownNeverNaN(Src, DemandedSrcElts, SNaN, Depth + 1);
    }
    return isKnownNeverNaN(Src, SNaN, Depth + 1);
  }
  case ISD::INSERT_SUBVECTOR: {
    SDValue BaseVector = Op.getOperand(0);
    SDValue SubVector = Op.getOperand(1);
    EVT BaseVectorVT = BaseVector.getValueType();
    if (BaseVectorVT.isFixedLengthVector()) {
      unsigned Idx = Op.getConstantOperandVal(2);
      unsigned NumBaseElts = BaseVectorVT.getVectorNumElements();
      unsigned NumSubElts = SubVector.getValueType().getVectorNumElements();

      // Clear/Extract the bits at the position where the subvector will be
      // inserted.
      APInt DemandedMask =
          APInt::getBitsSet(NumBaseElts, Idx, Idx + NumSubElts);
      APInt DemandedSrcElts = DemandedElts & ~DemandedMask;
      APInt DemandedSubElts = DemandedElts.extractBits(NumSubElts, Idx);

      bool NeverNaN = true;
      if (!DemandedSrcElts.isZero())
        NeverNaN &=
            isKnownNeverNaN(BaseVector, DemandedSrcElts, SNaN, Depth + 1);
      if (NeverNaN && !DemandedSubElts.isZero())
        NeverNaN &=
            isKnownNeverNaN(SubVector, DemandedSubElts, SNaN, Depth + 1);
      return NeverNaN;
    }
    return isKnownNeverNaN(BaseVector, SNaN, Depth + 1) &&
           isKnownNeverNaN(SubVector, SNaN, Depth + 1);
  }
  case ISD::BUILD_VECTOR: {
    unsigned NumElts = Op.getNumOperands();
    for (unsigned I = 0; I != NumElts; ++I)
      if (DemandedElts[I] &&
          !isKnownNeverNaN(Op.getOperand(I), SNaN, Depth + 1))
        return false;
    return true;
  }
  case ISD::AssertNoFPClass: {
    FPClassTest NoFPClass =
        static_cast<FPClassTest>(Op.getConstantOperandVal(1));
    if ((NoFPClass & fcNan) == fcNan)
      return true;
    if (SNaN && (NoFPClass & fcSNan) == fcSNan)
      return true;
    return isKnownNeverNaN(Op.getOperand(0), DemandedElts, SNaN, Depth + 1);
  }
  default:
    if (Opcode >= ISD::BUILTIN_OP_END || Opcode == ISD::INTRINSIC_WO_CHAIN ||
        Opcode == ISD::INTRINSIC_W_CHAIN || Opcode == ISD::INTRINSIC_VOID) {
      return TLI->isKnownNeverNaNForTargetNode(Op, DemandedElts, *this, SNaN,
                                               Depth);
    }

    return false;
  }
}

bool SelectionDAG::isKnownNeverZeroFloat(SDValue Op) const {
  assert(Op.getValueType().isFloatingPoint() &&
         "Floating point type expected");

  // If the value is a constant, we can obviously see if it is a zero or not.
  return ISD::matchUnaryFpPredicate(
      Op, [](ConstantFPSDNode *C) { return !C->isZero(); });
}

bool SelectionDAG::isKnownNeverZero(SDValue Op, unsigned Depth) const {
  if (Depth >= MaxRecursionDepth)
    return false; // Limit search depth.

  assert(!Op.getValueType().isFloatingPoint() &&
         "Floating point types unsupported - use isKnownNeverZeroFloat");

  // If the value is a constant, we can obviously see if it is a zero or not.
  if (ISD::matchUnaryPredicate(Op,
                               [](ConstantSDNode *C) { return !C->isZero(); }))
    return true;

  // TODO: Recognize more cases here. Most of the cases are also incomplete to
  // some degree.
  switch (Op.getOpcode()) {
  default:
    break;

  case ISD::OR:
    return isKnownNeverZero(Op.getOperand(1), Depth + 1) ||
           isKnownNeverZero(Op.getOperand(0), Depth + 1);

  case ISD::VSELECT:
  case ISD::SELECT:
    return isKnownNeverZero(Op.getOperand(1), Depth + 1) &&
           isKnownNeverZero(Op.getOperand(2), Depth + 1);

  case ISD::SHL: {
    if (Op->getFlags().hasNoSignedWrap() || Op->getFlags().hasNoUnsignedWrap())
      return isKnownNeverZero(Op.getOperand(0), Depth + 1);
    KnownBits ValKnown = computeKnownBits(Op.getOperand(0), Depth + 1);
    // 1 << X is never zero.
    if (ValKnown.One[0])
      return true;
    // If max shift cnt of known ones is non-zero, result is non-zero.
    APInt MaxCnt = computeKnownBits(Op.getOperand(1), Depth + 1).getMaxValue();
    if (MaxCnt.ult(ValKnown.getBitWidth()) &&
        !ValKnown.One.shl(MaxCnt).isZero())
      return true;
    break;
  }
  case ISD::UADDSAT:
  case ISD::UMAX:
    return isKnownNeverZero(Op.getOperand(1), Depth + 1) ||
           isKnownNeverZero(Op.getOperand(0), Depth + 1);

    // For smin/smax: If either operand is known negative/positive
    // respectively we don't need the other to be known at all.
  case ISD::SMAX: {
    KnownBits Op1 = computeKnownBits(Op.getOperand(1), Depth + 1);
    if (Op1.isStrictlyPositive())
      return true;

    KnownBits Op0 = computeKnownBits(Op.getOperand(0), Depth + 1);
    if (Op0.isStrictlyPositive())
      return true;

    if (Op1.isNonZero() && Op0.isNonZero())
      return true;

    return isKnownNeverZero(Op.getOperand(1), Depth + 1) &&
           isKnownNeverZero(Op.getOperand(0), Depth + 1);
  }
  case ISD::SMIN: {
    KnownBits Op1 = computeKnownBits(Op.getOperand(1), Depth + 1);
    if (Op1.isNegative())
      return true;

    KnownBits Op0 = computeKnownBits(Op.getOperand(0), Depth + 1);
    if (Op0.isNegative())
      return true;

    if (Op1.isNonZero() && Op0.isNonZero())
      return true;

    return isKnownNeverZero(Op.getOperand(1), Depth + 1) &&
           isKnownNeverZero(Op.getOperand(0), Depth + 1);
  }
  case ISD::UMIN:
    return isKnownNeverZero(Op.getOperand(1), Depth + 1) &&
           isKnownNeverZero(Op.getOperand(0), Depth + 1);

  case ISD::ROTL:
  case ISD::ROTR:
  case ISD::BITREVERSE:
  case ISD::BSWAP:
  case ISD::CTPOP:
  case ISD::ABS:
    return isKnownNeverZero(Op.getOperand(0), Depth + 1);

  case ISD::SRA:
  case ISD::SRL: {
    if (Op->getFlags().hasExact())
      return isKnownNeverZero(Op.getOperand(0), Depth + 1);
    KnownBits ValKnown = computeKnownBits(Op.getOperand(0), Depth + 1);
    if (ValKnown.isNegative())
      return true;
    // If max shift cnt of known ones is non-zero, result is non-zero.
    APInt MaxCnt = computeKnownBits(Op.getOperand(1), Depth + 1).getMaxValue();
    if (MaxCnt.ult(ValKnown.getBitWidth()) &&
        !ValKnown.One.lshr(MaxCnt).isZero())
      return true;
    break;
  }
  case ISD::UDIV:
  case ISD::SDIV:
    // div exact can only produce a zero if the dividend is zero.
    // TODO: For udiv this is also true if Op1 u<= Op0
    if (Op->getFlags().hasExact())
      return isKnownNeverZero(Op.getOperand(0), Depth + 1);
    break;

  case ISD::ADD:
    if (Op->getFlags().hasNoUnsignedWrap())
      if (isKnownNeverZero(Op.getOperand(1), Depth + 1) ||
          isKnownNeverZero(Op.getOperand(0), Depth + 1))
        return true;
    // TODO: There are a lot more cases we can prove for add.
    break;

  case ISD::SUB: {
    if (isNullConstant(Op.getOperand(0)))
      return isKnownNeverZero(Op.getOperand(1), Depth + 1);

    std::optional<bool> ne =
        KnownBits::ne(computeKnownBits(Op.getOperand(0), Depth + 1),
                      computeKnownBits(Op.getOperand(1), Depth + 1));
    return ne && *ne;
  }

  case ISD::MUL:
    if (Op->getFlags().hasNoSignedWrap() || Op->getFlags().hasNoUnsignedWrap())
      if (isKnownNeverZero(Op.getOperand(1), Depth + 1) &&
          isKnownNeverZero(Op.getOperand(0), Depth + 1))
        return true;
    break;

  case ISD::ZERO_EXTEND:
  case ISD::SIGN_EXTEND:
    return isKnownNeverZero(Op.getOperand(0), Depth + 1);
  case ISD::VSCALE: {
    const Function &F = getMachineFunction().getFunction();
    const APInt &Multiplier = Op.getConstantOperandAPInt(0);
    ConstantRange CR =
        getVScaleRange(&F, Op.getScalarValueSizeInBits()).multiply(Multiplier);
    if (!CR.contains(APInt(CR.getBitWidth(), 0)))
      return true;
    break;
  }
  }

  return computeKnownBits(Op, Depth).isNonZero();
}

bool SelectionDAG::cannotBeOrderedNegativeFP(SDValue Op) const {
  if (ConstantFPSDNode *C1 = isConstOrConstSplatFP(Op, true))
    return !C1->isNegative();

  return Op.getOpcode() == ISD::FABS;
}

bool SelectionDAG::isEqualTo(SDValue A, SDValue B) const {
  // Check the obvious case.
  if (A == B) return true;

  // For negative and positive zero.
  if (const ConstantFPSDNode *CA = dyn_cast<ConstantFPSDNode>(A))
    if (const ConstantFPSDNode *CB = dyn_cast<ConstantFPSDNode>(B))
      if (CA->isZero() && CB->isZero()) return true;

  // Otherwise they may not be equal.
  return false;
}

// Only bits set in Mask must be negated, other bits may be arbitrary.
SDValue llvm::getBitwiseNotOperand(SDValue V, SDValue Mask, bool AllowUndefs) {
  if (isBitwiseNot(V, AllowUndefs))
    return V.getOperand(0);

  // Handle any_extend (not (truncate X)) pattern, where Mask only sets
  // bits in the non-extended part.
  ConstantSDNode *MaskC = isConstOrConstSplat(Mask);
  if (!MaskC || V.getOpcode() != ISD::ANY_EXTEND)
    return SDValue();
  SDValue ExtArg = V.getOperand(0);
  if (ExtArg.getScalarValueSizeInBits() >=
          MaskC->getAPIntValue().getActiveBits() &&
      isBitwiseNot(ExtArg, AllowUndefs) &&
      ExtArg.getOperand(0).getOpcode() == ISD::TRUNCATE &&
      ExtArg.getOperand(0).getOperand(0).getValueType() == V.getValueType())
    return ExtArg.getOperand(0).getOperand(0);
  return SDValue();
}

static bool haveNoCommonBitsSetCommutative(SDValue A, SDValue B) {
  // Match masked merge pattern (X & ~M) op (Y & M)
  // Including degenerate case (X & ~M) op M
  auto MatchNoCommonBitsPattern = [&](SDValue Not, SDValue Mask,
                                      SDValue Other) {
    if (SDValue NotOperand =
            getBitwiseNotOperand(Not, Mask, /* AllowUndefs */ true)) {
      if (NotOperand->getOpcode() == ISD::ZERO_EXTEND ||
          NotOperand->getOpcode() == ISD::TRUNCATE)
        NotOperand = NotOperand->getOperand(0);

      if (Other == NotOperand)
        return true;
      if (Other->getOpcode() == ISD::AND)
        return NotOperand == Other->getOperand(0) ||
               NotOperand == Other->getOperand(1);
    }
    return false;
  };

  if (A->getOpcode() == ISD::ZERO_EXTEND || A->getOpcode() == ISD::TRUNCATE)
    A = A->getOperand(0);

  if (B->getOpcode() == ISD::ZERO_EXTEND || B->getOpcode() == ISD::TRUNCATE)
    B = B->getOperand(0);

  if (A->getOpcode() == ISD::AND)
    return MatchNoCommonBitsPattern(A->getOperand(0), A->getOperand(1), B) ||
           MatchNoCommonBitsPattern(A->getOperand(1), A->getOperand(0), B);
  return false;
}

// FIXME: unify with llvm::haveNoCommonBitsSet.
bool SelectionDAG::haveNoCommonBitsSet(SDValue A, SDValue B) const {
  assert(A.getValueType() == B.getValueType() &&
         "Values must have the same type");
  if (haveNoCommonBitsSetCommutative(A, B) ||
      haveNoCommonBitsSetCommutative(B, A))
    return true;
  return KnownBits::haveNoCommonBitsSet(computeKnownBits(A),
                                        computeKnownBits(B));
}

static SDValue FoldSTEP_VECTOR(const SDLoc &DL, EVT VT, SDValue Step,
                               SelectionDAG &DAG) {
  if (cast<ConstantSDNode>(Step)->isZero())
    return DAG.getConstant(0, DL, VT);

  return SDValue();
}

static SDValue FoldBUILD_VECTOR(const SDLoc &DL, EVT VT,
                                ArrayRef<SDValue> Ops,
                                SelectionDAG &DAG) {
  int NumOps = Ops.size();
  assert(NumOps != 0 && "Can't build an empty vector!");
  assert(!VT.isScalableVector() &&
         "BUILD_VECTOR cannot be used with scalable types");
  assert(VT.getVectorNumElements() == (unsigned)NumOps &&
         "Incorrect element count in BUILD_VECTOR!");

  // BUILD_VECTOR of UNDEFs is UNDEF.
  if (llvm::all_of(Ops, [](SDValue Op) { return Op.isUndef(); }))
    return DAG.getUNDEF(VT);

  // BUILD_VECTOR of seq extract/insert from the same vector + type is Identity.
  SDValue IdentitySrc;
  bool IsIdentity = true;
  for (int i = 0; i != NumOps; ++i) {
    if (Ops[i].getOpcode() != ISD::EXTRACT_VECTOR_ELT ||
        Ops[i].getOperand(0).getValueType() != VT ||
        (IdentitySrc && Ops[i].getOperand(0) != IdentitySrc) ||
        !isa<ConstantSDNode>(Ops[i].getOperand(1)) ||
        Ops[i].getConstantOperandAPInt(1) != i) {
      IsIdentity = false;
      break;
    }
    IdentitySrc = Ops[i].getOperand(0);
  }
  if (IsIdentity)
    return IdentitySrc;

  return SDValue();
}

/// Try to simplify vector concatenation to an input value, undef, or build
/// vector.
static SDValue foldCONCAT_VECTORS(const SDLoc &DL, EVT VT,
                                  ArrayRef<SDValue> Ops,
                                  SelectionDAG &DAG) {
  assert(!Ops.empty() && "Can't concatenate an empty list of vectors!");
  assert(llvm::all_of(Ops,
                      [Ops](SDValue Op) {
                        return Ops[0].getValueType() == Op.getValueType();
                      }) &&
         "Concatenation of vectors with inconsistent value types!");
  assert((Ops[0].getValueType().getVectorElementCount() * Ops.size()) ==
             VT.getVectorElementCount() &&
         "Incorrect element count in vector concatenation!");

  if (Ops.size() == 1)
    return Ops[0];

  // Concat of UNDEFs is UNDEF.
  if (llvm::all_of(Ops, [](SDValue Op) { return Op.isUndef(); }))
    return DAG.getUNDEF(VT);

  // Scan the operands and look for extract operations from a single source
  // that correspond to insertion at the same location via this concatenation:
  // concat (extract X, 0*subvec_elts), (extract X, 1*subvec_elts), ...
  SDValue IdentitySrc;
  bool IsIdentity = true;
  for (unsigned i = 0, e = Ops.size(); i != e; ++i) {
    SDValue Op = Ops[i];
    unsigned IdentityIndex = i * Op.getValueType().getVectorMinNumElements();
    if (Op.getOpcode() != ISD::EXTRACT_SUBVECTOR ||
        Op.getOperand(0).getValueType() != VT ||
        (IdentitySrc && Op.getOperand(0) != IdentitySrc) ||
        Op.getConstantOperandVal(1) != IdentityIndex) {
      IsIdentity = false;
      break;
    }
    assert((!IdentitySrc || IdentitySrc == Op.getOperand(0)) &&
           "Unexpected identity source vector for concat of extracts");
    IdentitySrc = Op.getOperand(0);
  }
  if (IsIdentity) {
    assert(IdentitySrc && "Failed to set source vector of extracts");
    return IdentitySrc;
  }

  // The code below this point is only designed to work for fixed width
  // vectors, so we bail out for now.
  if (VT.isScalableVector())
    return SDValue();

  // A CONCAT_VECTOR with all UNDEF/BUILD_VECTOR operands can be
  // simplified to one big BUILD_VECTOR.
  // FIXME: Add support for SCALAR_TO_VECTOR as well.
  EVT SVT = VT.getScalarType();
  SmallVector<SDValue, 16> Elts;
  for (SDValue Op : Ops) {
    EVT OpVT = Op.getValueType();
    if (Op.isUndef())
      Elts.append(OpVT.getVectorNumElements(), DAG.getUNDEF(SVT));
    else if (Op.getOpcode() == ISD::BUILD_VECTOR)
      Elts.append(Op->op_begin(), Op->op_end());
    else
      return SDValue();
  }

  // BUILD_VECTOR requires all inputs to be of the same type, find the
  // maximum type and extend them all.
  for (SDValue Op : Elts)
    SVT = (SVT.bitsLT(Op.getValueType()) ? Op.getValueType() : SVT);

  if (SVT.bitsGT(VT.getScalarType())) {
    for (SDValue &Op : Elts) {
      if (Op.isUndef())
        Op = DAG.getUNDEF(SVT);
      else
        Op = DAG.getTargetLoweringInfo().isZExtFree(Op.getValueType(), SVT)
                 ? DAG.getZExtOrTrunc(Op, DL, SVT)
                 : DAG.getSExtOrTrunc(Op, DL, SVT);
    }
  }

  SDValue V = DAG.getBuildVector(VT, DL, Elts);
  NewSDValueDbgMsg(V, "New node fold concat vectors: ", &DAG);
  return V;
}

/// Gets or creates the specified node.
SDValue SelectionDAG::getNode(unsigned Opcode, const SDLoc &DL, EVT VT) {
  SDVTList VTs = getVTList(VT);
  FoldingSetNodeID ID;
  AddNodeIDNode(ID, Opcode, VTs, {});
  void *IP = nullptr;
  if (SDNode *E = FindNodeOrInsertPos(ID, DL, IP))
    return SDValue(E, 0);

  auto *N = newSDNode<SDNode>(Opcode, DL.getIROrder(), DL.getDebugLoc(), VTs);
  CSEMap.InsertNode(N, IP);

  InsertNode(N);
  SDValue V = SDValue(N, 0);
  NewSDValueDbgMsg(V, "Creating new node: ", this);
  return V;
}

SDValue SelectionDAG::getNode(unsigned Opcode, const SDLoc &DL, EVT VT,
                              SDValue N1) {
  SDNodeFlags Flags;
  if (Inserter)
    Flags = Inserter->getFlags();
  return getNode(Opcode, DL, VT, N1, Flags);
}

SDValue SelectionDAG::getNode(unsigned Opcode, const SDLoc &DL, EVT VT,
                              SDValue N1, const SDNodeFlags Flags) {
  assert(N1.getOpcode() != ISD::DELETED_NODE && "Operand is DELETED_NODE!");

  // Constant fold unary operations with a vector integer or float operand.
  switch (Opcode) {
  default:
    // FIXME: Entirely reasonable to perform folding of other unary
    // operations here as the need arises.
    break;
  case ISD::FNEG:
  case ISD::FABS:
  case ISD::FCEIL:
  case ISD::FTRUNC:
  case ISD::FFLOOR:
  case ISD::FP_EXTEND:
  case ISD::FP_TO_SINT:
  case ISD::FP_TO_UINT:
  case ISD::FP_TO_FP16:
  case ISD::FP_TO_BF16:
  case ISD::TRUNCATE:
  case ISD::ANY_EXTEND:
  case ISD::ZERO_EXTEND:
  case ISD::SIGN_EXTEND:
  case ISD::UINT_TO_FP:
  case ISD::SINT_TO_FP:
  case ISD::FP16_TO_FP:
  case ISD::BF16_TO_FP:
  case ISD::BITCAST:
  case ISD::ABS:
  case ISD::BITREVERSE:
  case ISD::BSWAP:
  case ISD::CTLZ:
  case ISD::CTLZ_ZERO_UNDEF:
  case ISD::CTTZ:
  case ISD::CTTZ_ZERO_UNDEF:
  case ISD::CTPOP:
  case ISD::STEP_VECTOR: {
    SDValue Ops = {N1};
    if (SDValue Fold = FoldConstantArithmetic(Opcode, DL, VT, Ops))
      return Fold;
  }
  }

  unsigned OpOpcode = N1.getNode()->getOpcode();
  switch (Opcode) {
  case ISD::STEP_VECTOR:
    assert(VT.isScalableVector() &&
           "STEP_VECTOR can only be used with scalable types");
    assert(OpOpcode == ISD::TargetConstant &&
           VT.getVectorElementType() == N1.getValueType() &&
           "Unexpected step operand");
    break;
  case ISD::FREEZE:
    assert(VT == N1.getValueType() && "Unexpected VT!");
    if (isGuaranteedNotToBeUndefOrPoison(N1, /*PoisonOnly*/ false,
                                         /*Depth*/ 1))
      return N1;
    break;
  case ISD::TokenFactor:
  case ISD::MERGE_VALUES:
  case ISD::CONCAT_VECTORS:
    return N1;         // Factor, merge or concat of one node?  No need.
  case ISD::BUILD_VECTOR: {
    // Attempt to simplify BUILD_VECTOR.
    SDValue Ops[] = {N1};
    if (SDValue V = FoldBUILD_VECTOR(DL, VT, Ops, *this))
      return V;
    break;
  }
  case ISD::FP_ROUND: llvm_unreachable("Invalid method to make FP_ROUND node");
  case ISD::FP_EXTEND:
    assert(VT.isFloatingPoint() && N1.getValueType().isFloatingPoint() &&
           "Invalid FP cast!");
    if (N1.getValueType() == VT) return N1;  // noop conversion.
    assert((!VT.isVector() || VT.getVectorElementCount() ==
                                  N1.getValueType().getVectorElementCount()) &&
           "Vector element count mismatch!");
    assert(N1.getValueType().bitsLT(VT) && "Invalid fpext node, dst < src!");
    if (N1.isUndef())
      return getUNDEF(VT);
    break;
  case ISD::FP_TO_SINT:
  case ISD::FP_TO_UINT:
    if (N1.isUndef())
      return getUNDEF(VT);
    break;
  case ISD::SINT_TO_FP:
  case ISD::UINT_TO_FP:
    // [us]itofp(undef) = 0, because the result value is bounded.
    if (N1.isUndef())
      return getConstantFP(0.0, DL, VT);
    break;
  case ISD::SIGN_EXTEND:
    assert(VT.isInteger() && N1.getValueType().isInteger() &&
           "Invalid SIGN_EXTEND!");
    assert(VT.isVector() == N1.getValueType().isVector() &&
           "SIGN_EXTEND result type type should be vector iff the operand "
           "type is vector!");
    if (N1.getValueType() == VT) return N1;   // noop extension
    assert((!VT.isVector() || VT.getVectorElementCount() ==
                                  N1.getValueType().getVectorElementCount()) &&
           "Vector element count mismatch!");
    assert(N1.getValueType().bitsLT(VT) && "Invalid sext node, dst < src!");
    if (OpOpcode == ISD::SIGN_EXTEND || OpOpcode == ISD::ZERO_EXTEND) {
      SDNodeFlags Flags;
      if (OpOpcode == ISD::ZERO_EXTEND)
        Flags.setNonNeg(N1->getFlags().hasNonNeg());
      SDValue NewVal = getNode(OpOpcode, DL, VT, N1.getOperand(0), Flags);
      transferDbgValues(N1, NewVal);
      return NewVal;
    }

    if (OpOpcode == ISD::POISON)
      return getPOISON(VT);

    if (N1.isUndef())
      // sext(undef) = 0, because the top bits will all be the same.
      return getConstant(0, DL, VT);
    break;
  case ISD::ZERO_EXTEND:
    assert(VT.isInteger() && N1.getValueType().isInteger() &&
           "Invalid ZERO_EXTEND!");
    assert(VT.isVector() == N1.getValueType().isVector() &&
           "ZERO_EXTEND result type type should be vector iff the operand "
           "type is vector!");
    if (N1.getValueType() == VT) return N1;   // noop extension
    assert((!VT.isVector() || VT.getVectorElementCount() ==
                                  N1.getValueType().getVectorElementCount()) &&
           "Vector element count mismatch!");
    assert(N1.getValueType().bitsLT(VT) && "Invalid zext node, dst < src!");
    if (OpOpcode == ISD::ZERO_EXTEND) { // (zext (zext x)) -> (zext x)
      SDNodeFlags Flags;
      Flags.setNonNeg(N1->getFlags().hasNonNeg());
      SDValue NewVal =
          getNode(ISD::ZERO_EXTEND, DL, VT, N1.getOperand(0), Flags);
      transferDbgValues(N1, NewVal);
      return NewVal;
    }

    if (OpOpcode == ISD::POISON)
      return getPOISON(VT);

    if (N1.isUndef())
      // zext(undef) = 0, because the top bits will be zero.
      return getConstant(0, DL, VT);

    // Skip unnecessary zext_inreg pattern:
    // (zext (trunc x)) -> x iff the upper bits are known zero.
    // TODO: Remove (zext (trunc (and x, c))) exception which some targets
    // use to recognise zext_inreg patterns.
    if (OpOpcode == ISD::TRUNCATE) {
      SDValue OpOp = N1.getOperand(0);
      if (OpOp.getValueType() == VT) {
        if (OpOp.getOpcode() != ISD::AND) {
          APInt HiBits = APInt::getBitsSetFrom(VT.getScalarSizeInBits(),
                                               N1.getScalarValueSizeInBits());
          if (MaskedValueIsZero(OpOp, HiBits)) {
            transferDbgValues(N1, OpOp);
            return OpOp;
          }
        }
      }
    }
    break;
  case ISD::ANY_EXTEND:
    assert(VT.isInteger() && N1.getValueType().isInteger() &&
           "Invalid ANY_EXTEND!");
    assert(VT.isVector() == N1.getValueType().isVector() &&
           "ANY_EXTEND result type type should be vector iff the operand "
           "type is vector!");
    if (N1.getValueType() == VT) return N1;   // noop extension
    assert((!VT.isVector() || VT.getVectorElementCount() ==
                                  N1.getValueType().getVectorElementCount()) &&
           "Vector element count mismatch!");
    assert(N1.getValueType().bitsLT(VT) && "Invalid anyext node, dst < src!");

    if (OpOpcode == ISD::ZERO_EXTEND || OpOpcode == ISD::SIGN_EXTEND ||
        OpOpcode == ISD::ANY_EXTEND) {
      SDNodeFlags Flags;
      if (OpOpcode == ISD::ZERO_EXTEND)
        Flags.setNonNeg(N1->getFlags().hasNonNeg());
      // (ext (zext x)) -> (zext x)  and  (ext (sext x)) -> (sext x)
      return getNode(OpOpcode, DL, VT, N1.getOperand(0), Flags);
    }
    if (N1.isUndef())
      return getUNDEF(VT);

    // (ext (trunc x)) -> x
    if (OpOpcode == ISD::TRUNCATE) {
      SDValue OpOp = N1.getOperand(0);
      if (OpOp.getValueType() == VT) {
        transferDbgValues(N1, OpOp);
        return OpOp;
      }
    }
    break;
  case ISD::TRUNCATE:
    assert(VT.isInteger() && N1.getValueType().isInteger() &&
           "Invalid TRUNCATE!");
    assert(VT.isVector() == N1.getValueType().isVector() &&
           "TRUNCATE result type type should be vector iff the operand "
           "type is vector!");
    if (N1.getValueType() == VT) return N1;   // noop truncate
    assert((!VT.isVector() || VT.getVectorElementCount() ==
                                  N1.getValueType().getVectorElementCount()) &&
           "Vector element count mismatch!");
    assert(N1.getValueType().bitsGT(VT) && "Invalid truncate node, src < dst!");
    if (OpOpcode == ISD::TRUNCATE)
      return getNode(ISD::TRUNCATE, DL, VT, N1.getOperand(0));
    if (OpOpcode == ISD::ZERO_EXTEND || OpOpcode == ISD::SIGN_EXTEND ||
        OpOpcode == ISD::ANY_EXTEND) {
      // If the source is smaller than the dest, we still need an extend.
      if (N1.getOperand(0).getValueType().getScalarType().bitsLT(
              VT.getScalarType())) {
        SDNodeFlags Flags;
        if (OpOpcode == ISD::ZERO_EXTEND)
          Flags.setNonNeg(N1->getFlags().hasNonNeg());
        return getNode(OpOpcode, DL, VT, N1.getOperand(0), Flags);
      }
      if (N1.getOperand(0).getValueType().bitsGT(VT))
        return getNode(ISD::TRUNCATE, DL, VT, N1.getOperand(0));
      return N1.getOperand(0);
    }
    if (N1.isUndef())
      return getUNDEF(VT);
    if (OpOpcode == ISD::VSCALE && !NewNodesMustHaveLegalTypes)
      return getVScale(DL, VT,
                       N1.getConstantOperandAPInt(0).trunc(VT.getSizeInBits()));
    break;
  case ISD::ANY_EXTEND_VECTOR_INREG:
  case ISD::ZERO_EXTEND_VECTOR_INREG:
  case ISD::SIGN_EXTEND_VECTOR_INREG:
    assert(VT.isVector() && "This DAG node is restricted to vector types.");
    assert(N1.getValueType().bitsLE(VT) &&
           "The input must be the same size or smaller than the result.");
    assert(VT.getVectorMinNumElements() <
               N1.getValueType().getVectorMinNumElements() &&
           "The destination vector type must have fewer lanes than the input.");
    break;
  case ISD::ABS:
    assert(VT.isInteger() && VT == N1.getValueType() && "Invalid ABS!");
    if (N1.isUndef())
      return getConstant(0, DL, VT);
    break;
  case ISD::BSWAP:
    assert(VT.isInteger() && VT == N1.getValueType() && "Invalid BSWAP!");
    assert((VT.getScalarSizeInBits() % 16 == 0) &&
           "BSWAP types must be a multiple of 16 bits!");
    if (N1.isUndef())
      return getUNDEF(VT);
    // bswap(bswap(X)) -> X.
    if (OpOpcode == ISD::BSWAP)
      return N1.getOperand(0);
    break;
  case ISD::BITREVERSE:
    assert(VT.isInteger() && VT == N1.getValueType() && "Invalid BITREVERSE!");
    if (N1.isUndef())
      return getUNDEF(VT);
    break;
  case ISD::BITCAST:
    assert(VT.getSizeInBits() == N1.getValueSizeInBits() &&
           "Cannot BITCAST between types of different sizes!");
    if (VT == N1.getValueType()) return N1;   // noop conversion.
    if (OpOpcode == ISD::BITCAST) // bitconv(bitconv(x)) -> bitconv(x)
      return getNode(ISD::BITCAST, DL, VT, N1.getOperand(0));
    if (N1.isUndef())
      return getUNDEF(VT);
    break;
  case ISD::SCALAR_TO_VECTOR:
    assert(VT.isVector() && !N1.getValueType().isVector() &&
           (VT.getVectorElementType() == N1.getValueType() ||
            (VT.getVectorElementType().isInteger() &&
             N1.getValueType().isInteger() &&
             VT.getVectorElementType().bitsLE(N1.getValueType()))) &&
           "Illegal SCALAR_TO_VECTOR node!");
    if (N1.isUndef())
      return getUNDEF(VT);
    // scalar_to_vector(extract_vector_elt V, 0) -> V, top bits are undefined.
    if (OpOpcode == ISD::EXTRACT_VECTOR_ELT &&
        isa<ConstantSDNode>(N1.getOperand(1)) &&
        N1.getConstantOperandVal(1) == 0 &&
        N1.getOperand(0).getValueType() == VT)
      return N1.getOperand(0);
    break;
  case ISD::FNEG:
    // Negation of an unknown bag of bits is still completely undefined.
    if (N1.isUndef())
      return getUNDEF(VT);

    if (OpOpcode == ISD::FNEG) // --X -> X
      return N1.getOperand(0);
    break;
  case ISD::FABS:
    if (OpOpcode == ISD::FNEG) // abs(-X) -> abs(X)
      return getNode(ISD::FABS, DL, VT, N1.getOperand(0));
    break;
  case ISD::VSCALE:
    assert(VT == N1.getValueType() && "Unexpected VT!");
    break;
  case ISD::CTPOP:
    if (N1.getValueType().getScalarType() == MVT::i1)
      return N1;
    break;
  case ISD::CTLZ:
  case ISD::CTTZ:
    if (N1.getValueType().getScalarType() == MVT::i1)
      return getNOT(DL, N1, N1.getValueType());
    break;
  case ISD::VECREDUCE_ADD:
    if (N1.getValueType().getScalarType() == MVT::i1)
      return getNode(ISD::VECREDUCE_XOR, DL, VT, N1);
    break;
  case ISD::VECREDUCE_SMIN:
  case ISD::VECREDUCE_UMAX:
    if (N1.getValueType().getScalarType() == MVT::i1)
      return getNode(ISD::VECREDUCE_OR, DL, VT, N1);
    break;
  case ISD::VECREDUCE_SMAX:
  case ISD::VECREDUCE_UMIN:
    if (N1.getValueType().getScalarType() == MVT::i1)
      return getNode(ISD::VECREDUCE_AND, DL, VT, N1);
    break;
  case ISD::SPLAT_VECTOR:
    assert(VT.isVector() && "Wrong return type!");
    // FIXME: Hexagon uses i32 scalar for a floating point zero vector so allow
    // that for now.
    assert((VT.getVectorElementType() == N1.getValueType() ||
            (VT.isFloatingPoint() && N1.getValueType() == MVT::i32) ||
            (VT.getVectorElementType().isInteger() &&
             N1.getValueType().isInteger() &&
             VT.getVectorElementType().bitsLE(N1.getValueType()))) &&
           "Wrong operand type!");
    break;
  }

  SDNode *N;
  SDVTList VTs = getVTList(VT);
  SDValue Ops[] = {N1};
  if (VT != MVT::Glue) { // Don't CSE glue producing nodes
    FoldingSetNodeID ID;
    AddNodeIDNode(ID, Opcode, VTs, Ops);
    void *IP = nullptr;
    if (SDNode *E = FindNodeOrInsertPos(ID, DL, IP)) {
      E->intersectFlagsWith(Flags);
      return SDValue(E, 0);
    }

    N = newSDNode<SDNode>(Opcode, DL.getIROrder(), DL.getDebugLoc(), VTs);
    N->setFlags(Flags);
    createOperands(N, Ops);
    CSEMap.InsertNode(N, IP);
  } else {
    N = newSDNode<SDNode>(Opcode, DL.getIROrder(), DL.getDebugLoc(), VTs);
    createOperands(N, Ops);
  }

  InsertNode(N);
  SDValue V = SDValue(N, 0);
  NewSDValueDbgMsg(V, "Creating new node: ", this);
  return V;
}

static std::optional<APInt> FoldValue(unsigned Opcode, const APInt &C1,
                                      const APInt &C2) {
  switch (Opcode) {
  case ISD::ADD:  return C1 + C2;
  case ISD::SUB:  return C1 - C2;
  case ISD::MUL:  return C1 * C2;
  case ISD::AND:  return C1 & C2;
  case ISD::OR:   return C1 | C2;
  case ISD::XOR:  return C1 ^ C2;
  case ISD::SHL:  return C1 << C2;
  case ISD::SRL:  return C1.lshr(C2);
  case ISD::SRA:  return C1.ashr(C2);
  case ISD::ROTL: return C1.rotl(C2);
  case ISD::ROTR: return C1.rotr(C2);
  case ISD::SMIN: return C1.sle(C2) ? C1 : C2;
  case ISD::SMAX: return C1.sge(C2) ? C1 : C2;
  case ISD::UMIN: return C1.ule(C2) ? C1 : C2;
  case ISD::UMAX: return C1.uge(C2) ? C1 : C2;
  case ISD::SADDSAT: return C1.sadd_sat(C2);
  case ISD::UADDSAT: return C1.uadd_sat(C2);
  case ISD::SSUBSAT: return C1.ssub_sat(C2);
  case ISD::USUBSAT: return C1.usub_sat(C2);
  case ISD::SSHLSAT: return C1.sshl_sat(C2);
  case ISD::USHLSAT: return C1.ushl_sat(C2);
  case ISD::UDIV:
    if (!C2.getBoolValue())
      break;
    return C1.udiv(C2);
  case ISD::UREM:
    if (!C2.getBoolValue())
      break;
    return C1.urem(C2);
  case ISD::SDIV:
    if (!C2.getBoolValue())
      break;
    return C1.sdiv(C2);
  case ISD::SREM:
    if (!C2.getBoolValue())
      break;
    return C1.srem(C2);
  case ISD::AVGFLOORS:
    return APIntOps::avgFloorS(C1, C2);
  case ISD::AVGFLOORU:
    return APIntOps::avgFloorU(C1, C2);
  case ISD::AVGCEILS:
    return APIntOps::avgCeilS(C1, C2);
  case ISD::AVGCEILU:
    return APIntOps::avgCeilU(C1, C2);
  case ISD::ABDS:
    return APIntOps::abds(C1, C2);
  case ISD::ABDU:
    return APIntOps::abdu(C1, C2);
  case ISD::MULHS:
    return APIntOps::mulhs(C1, C2);
  case ISD::MULHU:
    return APIntOps::mulhu(C1, C2);
  }
  return std::nullopt;
}
// Handle constant folding with UNDEF.
// TODO: Handle more cases.
static std::optional<APInt> FoldValueWithUndef(unsigned Opcode, const APInt &C1,
                                               bool IsUndef1, const APInt &C2,
                                               bool IsUndef2) {
  if (!(IsUndef1 || IsUndef2))
    return FoldValue(Opcode, C1, C2);

  // Fold and(x, undef) -> 0
  // Fold mul(x, undef) -> 0
  if (Opcode == ISD::AND || Opcode == ISD::MUL)
    return APInt::getZero(C1.getBitWidth());

  return std::nullopt;
}

SDValue SelectionDAG::FoldSymbolOffset(unsigned Opcode, EVT VT,
                                       const GlobalAddressSDNode *GA,
                                       const SDNode *N2) {
  if (GA->getOpcode() != ISD::GlobalAddress)
    return SDValue();
  if (!TLI->isOffsetFoldingLegal(GA))
    return SDValue();
  auto *C2 = dyn_cast<ConstantSDNode>(N2);
  if (!C2)
    return SDValue();
  int64_t Offset = C2->getSExtValue();
  switch (Opcode) {
  case ISD::ADD:
  case ISD::PTRADD:
    break;
  case ISD::SUB: Offset = -uint64_t(Offset); break;
  default: return SDValue();
  }
  return getGlobalAddress(GA->getGlobal(), SDLoc(C2), VT,
                          GA->getOffset() + uint64_t(Offset));
}

bool SelectionDAG::isUndef(unsigned Opcode, ArrayRef<SDValue> Ops) {
  switch (Opcode) {
  case ISD::SDIV:
  case ISD::UDIV:
  case ISD::SREM:
  case ISD::UREM: {
    // If a divisor is zero/undef or any element of a divisor vector is
    // zero/undef, the whole op is undef.
    assert(Ops.size() == 2 && "Div/rem should have 2 operands");
    SDValue Divisor = Ops[1];
    if (Divisor.isUndef() || isNullConstant(Divisor))
      return true;

    return ISD::isBuildVectorOfConstantSDNodes(Divisor.getNode()) &&
           llvm::any_of(Divisor->op_values(),
                        [](SDValue V) { return V.isUndef() ||
                                        isNullConstant(V); });
    // TODO: Handle signed overflow.
  }
  // TODO: Handle oversized shifts.
  default:
    return false;
  }
}

SDValue SelectionDAG::FoldConstantArithmetic(unsigned Opcode, const SDLoc &DL,
                                             EVT VT, ArrayRef<SDValue> Ops,
                                             SDNodeFlags Flags) {
  // If the opcode is a target-specific ISD node, there's nothing we can
  // do here and the operand rules may not line up with the below, so
  // bail early.
  // We can't create a scalar CONCAT_VECTORS so skip it. It will break
  // for concats involving SPLAT_VECTOR. Concats of BUILD_VECTORS are handled by
  // foldCONCAT_VECTORS in getNode before this is called.
  if (Opcode >= ISD::BUILTIN_OP_END || Opcode == ISD::CONCAT_VECTORS)
    return SDValue();

  unsigned NumOps = Ops.size();
  if (NumOps == 0)
    return SDValue();

  if (isUndef(Opcode, Ops))
    return getUNDEF(VT);

  // Handle unary special cases.
  if (NumOps == 1) {
    SDValue N1 = Ops[0];

    // Constant fold unary operations with an integer constant operand. Even
    // opaque constant will be folded, because the folding of unary operations
    // doesn't create new constants with different values. Nevertheless, the
    // opaque flag is preserved during folding to prevent future folding with
    // other constants.
    if (auto *C = dyn_cast<ConstantSDNode>(N1)) {
      const APInt &Val = C->getAPIntValue();
      switch (Opcode) {
      case ISD::SIGN_EXTEND:
        return getConstant(Val.sextOrTrunc(VT.getSizeInBits()), DL, VT,
                           C->isTargetOpcode(), C->isOpaque());
      case ISD::TRUNCATE:
        if (C->isOpaque())
          break;
        [[fallthrough]];
      case ISD::ZERO_EXTEND:
        return getConstant(Val.zextOrTrunc(VT.getSizeInBits()), DL, VT,
                           C->isTargetOpcode(), C->isOpaque());
      case ISD::ANY_EXTEND:
        // Some targets like RISCV prefer to sign extend some types.
        if (TLI->isSExtCheaperThanZExt(N1.getValueType(), VT))
          return getConstant(Val.sextOrTrunc(VT.getSizeInBits()), DL, VT,
                             C->isTargetOpcode(), C->isOpaque());
        return getConstant(Val.zextOrTrunc(VT.getSizeInBits()), DL, VT,
                           C->isTargetOpcode(), C->isOpaque());
      case ISD::ABS:
        return getConstant(Val.abs(), DL, VT, C->isTargetOpcode(),
                           C->isOpaque());
      case ISD::BITREVERSE:
        return getConstant(Val.reverseBits(), DL, VT, C->isTargetOpcode(),
                           C->isOpaque());
      case ISD::BSWAP:
        return getConstant(Val.byteSwap(), DL, VT, C->isTargetOpcode(),
                           C->isOpaque());
      case ISD::CTPOP:
        return getConstant(Val.popcount(), DL, VT, C->isTargetOpcode(),
                           C->isOpaque());
      case ISD::CTLZ:
      case ISD::CTLZ_ZERO_UNDEF:
        return getConstant(Val.countl_zero(), DL, VT, C->isTargetOpcode(),
                           C->isOpaque());
      case ISD::CTTZ:
      case ISD::CTTZ_ZERO_UNDEF:
        return getConstant(Val.countr_zero(), DL, VT, C->isTargetOpcode(),
                           C->isOpaque());
      case ISD::UINT_TO_FP:
      case ISD::SINT_TO_FP: {
        APFloat FPV(VT.getFltSemantics(), APInt::getZero(VT.getSizeInBits()));
        (void)FPV.convertFromAPInt(Val, Opcode == ISD::SINT_TO_FP,
                                   APFloat::rmNearestTiesToEven);
        return getConstantFP(FPV, DL, VT);
      }
      case ISD::FP16_TO_FP:
      case ISD::BF16_TO_FP: {
        bool Ignored;
        APFloat FPV(Opcode == ISD::FP16_TO_FP ? APFloat::IEEEhalf()
                                              : APFloat::BFloat(),
                    (Val.getBitWidth() == 16) ? Val : Val.trunc(16));

        // This can return overflow, underflow, or inexact; we don't care.
        // FIXME need to be more flexible about rounding mode.
        (void)FPV.convert(VT.getFltSemantics(), APFloat::rmNearestTiesToEven,
                          &Ignored);
        return getConstantFP(FPV, DL, VT);
      }
      case ISD::STEP_VECTOR:
        if (SDValue V = FoldSTEP_VECTOR(DL, VT, N1, *this))
          return V;
        break;
      case ISD::BITCAST:
        if (VT == MVT::f16 && C->getValueType(0) == MVT::i16)
          return getConstantFP(APFloat(APFloat::IEEEhalf(), Val), DL, VT);
        if (VT == MVT::f32 && C->getValueType(0) == MVT::i32)
          return getConstantFP(APFloat(APFloat::IEEEsingle(), Val), DL, VT);
        if (VT == MVT::f64 && C->getValueType(0) == MVT::i64)
          return getConstantFP(APFloat(APFloat::IEEEdouble(), Val), DL, VT);
        if (VT == MVT::f128 && C->getValueType(0) == MVT::i128)
          return getConstantFP(APFloat(APFloat::IEEEquad(), Val), DL, VT);
        break;
      }
    }

    // Constant fold unary operations with a floating point constant operand.
    if (auto *C = dyn_cast<ConstantFPSDNode>(N1)) {
      APFloat V = C->getValueAPF(); // make copy
      switch (Opcode) {
      case ISD::FNEG:
        V.changeSign();
        return getConstantFP(V, DL, VT);
      case ISD::FABS:
        V.clearSign();
        return getConstantFP(V, DL, VT);
      case ISD::FCEIL: {
        APFloat::opStatus fs = V.roundToIntegral(APFloat::rmTowardPositive);
        if (fs == APFloat::opOK || fs == APFloat::opInexact)
          return getConstantFP(V, DL, VT);
        return SDValue();
      }
      case ISD::FTRUNC: {
        APFloat::opStatus fs = V.roundToIntegral(APFloat::rmTowardZero);
        if (fs == APFloat::opOK || fs == APFloat::opInexact)
          return getConstantFP(V, DL, VT);
        return SDValue();
      }
      case ISD::FFLOOR: {
        APFloat::opStatus fs = V.roundToIntegral(APFloat::rmTowardNegative);
        if (fs == APFloat::opOK || fs == APFloat::opInexact)
          return getConstantFP(V, DL, VT);
        return SDValue();
      }
      case ISD::FP_EXTEND: {
        bool ignored;
        // This can return overflow, underflow, or inexact; we don't care.
        // FIXME need to be more flexible about rounding mode.
        (void)V.convert(VT.getFltSemantics(), APFloat::rmNearestTiesToEven,
                        &ignored);
        return getConstantFP(V, DL, VT);
      }
      case ISD::FP_TO_SINT:
      case ISD::FP_TO_UINT: {
        bool ignored;
        APSInt IntVal(VT.getSizeInBits(), Opcode == ISD::FP_TO_UINT);
        // FIXME need to be more flexible about rounding mode.
        APFloat::opStatus s =
            V.convertToInteger(IntVal, APFloat::rmTowardZero, &ignored);
        if (s == APFloat::opInvalidOp) // inexact is OK, in fact usual
          break;
        return getConstant(IntVal, DL, VT);
      }
      case ISD::FP_TO_FP16:
      case ISD::FP_TO_BF16: {
        bool Ignored;
        // This can return overflow, underflow, or inexact; we don't care.
        // FIXME need to be more flexible about rounding mode.
        (void)V.convert(Opcode == ISD::FP_TO_FP16 ? APFloat::IEEEhalf()
                                                  : APFloat::BFloat(),
                        APFloat::rmNearestTiesToEven, &Ignored);
        return getConstant(V.bitcastToAPInt().getZExtValue(), DL, VT);
      }
      case ISD::BITCAST:
        if (VT == MVT::i16 && C->getValueType(0) == MVT::f16)
          return getConstant((uint16_t)V.bitcastToAPInt().getZExtValue(), DL,
                             VT);
        if (VT == MVT::i16 && C->getValueType(0) == MVT::bf16)
          return getConstant((uint16_t)V.bitcastToAPInt().getZExtValue(), DL,
                             VT);
        if (VT == MVT::i32 && C->getValueType(0) == MVT::f32)
          return getConstant((uint32_t)V.bitcastToAPInt().getZExtValue(), DL,
                             VT);
        if (VT == MVT::i64 && C->getValueType(0) == MVT::f64)
          return getConstant(V.bitcastToAPInt().getZExtValue(), DL, VT);
        break;
      }
    }

    // Early-out if we failed to constant fold a bitcast.
    if (Opcode == ISD::BITCAST)
      return SDValue();
  }

  // Handle binops special cases.
  if (NumOps == 2) {
    if (SDValue CFP = foldConstantFPMath(Opcode, DL, VT, Ops))
      return CFP;

    if (auto *C1 = dyn_cast<ConstantSDNode>(Ops[0])) {
      if (auto *C2 = dyn_cast<ConstantSDNode>(Ops[1])) {
        if (C1->isOpaque() || C2->isOpaque())
          return SDValue();

        std::optional<APInt> FoldAttempt =
            FoldValue(Opcode, C1->getAPIntValue(), C2->getAPIntValue());
        if (!FoldAttempt)
          return SDValue();

        SDValue Folded = getConstant(*FoldAttempt, DL, VT);
        assert((!Folded || !VT.isVector()) &&
               "Can't fold vectors ops with scalar operands");
        return Folded;
      }
    }

    // fold (add Sym, c) -> Sym+c
    if (GlobalAddressSDNode *GA = dyn_cast<GlobalAddressSDNode>(Ops[0]))
      return FoldSymbolOffset(Opcode, VT, GA, Ops[1].getNode());
    if (TLI->isCommutativeBinOp(Opcode))
      if (GlobalAddressSDNode *GA = dyn_cast<GlobalAddressSDNode>(Ops[1]))
        return FoldSymbolOffset(Opcode, VT, GA, Ops[0].getNode());

    // fold (sext_in_reg c1) -> c2
    if (Opcode == ISD::SIGN_EXTEND_INREG) {
      EVT EVT = cast<VTSDNode>(Ops[1])->getVT();

      auto SignExtendInReg = [&](APInt Val, llvm::EVT ConstantVT) {
        unsigned FromBits = EVT.getScalarSizeInBits();
        Val <<= Val.getBitWidth() - FromBits;
        Val.ashrInPlace(Val.getBitWidth() - FromBits);
        return getConstant(Val, DL, ConstantVT);
      };

      if (auto *C1 = dyn_cast<ConstantSDNode>(Ops[0])) {
        const APInt &Val = C1->getAPIntValue();
        return SignExtendInReg(Val, VT);
      }

      if (ISD::isBuildVectorOfConstantSDNodes(Ops[0].getNode())) {
        SmallVector<SDValue, 8> ScalarOps;
        llvm::EVT OpVT = Ops[0].getOperand(0).getValueType();
        for (int I = 0, E = VT.getVectorNumElements(); I != E; ++I) {
          SDValue Op = Ops[0].getOperand(I);
          if (Op.isUndef()) {
            ScalarOps.push_back(getUNDEF(OpVT));
            continue;
          }
          const APInt &Val = cast<ConstantSDNode>(Op)->getAPIntValue();
          ScalarOps.push_back(SignExtendInReg(Val, OpVT));
        }
        return getBuildVector(VT, DL, ScalarOps);
      }

      if (Ops[0].getOpcode() == ISD::SPLAT_VECTOR &&
          isa<ConstantSDNode>(Ops[0].getOperand(0)))
        return getNode(ISD::SPLAT_VECTOR, DL, VT,
                       SignExtendInReg(Ops[0].getConstantOperandAPInt(0),
                                       Ops[0].getOperand(0).getValueType()));
    }
  }

  // This is for vector folding only from here on.
  if (!VT.isVector())
    return SDValue();

  ElementCount NumElts = VT.getVectorElementCount();

  // See if we can fold through any bitcasted integer ops.
  if (NumOps == 2 && VT.isFixedLengthVector() && VT.isInteger() &&
      Ops[0].getValueType() == VT && Ops[1].getValueType() == VT &&
      (Ops[0].getOpcode() == ISD::BITCAST ||
       Ops[1].getOpcode() == ISD::BITCAST)) {
    SDValue N1 = peekThroughBitcasts(Ops[0]);
    SDValue N2 = peekThroughBitcasts(Ops[1]);
    auto *BV1 = dyn_cast<BuildVectorSDNode>(N1);
    auto *BV2 = dyn_cast<BuildVectorSDNode>(N2);
    if (BV1 && BV2 && N1.getValueType().isInteger() &&
        N2.getValueType().isInteger()) {
      bool IsLE = getDataLayout().isLittleEndian();
      unsigned EltBits = VT.getScalarSizeInBits();
      SmallVector<APInt> RawBits1, RawBits2;
      BitVector UndefElts1, UndefElts2;
      if (BV1->getConstantRawBits(IsLE, EltBits, RawBits1, UndefElts1) &&
          BV2->getConstantRawBits(IsLE, EltBits, RawBits2, UndefElts2)) {
        SmallVector<APInt> RawBits;
        for (unsigned I = 0, E = NumElts.getFixedValue(); I != E; ++I) {
          std::optional<APInt> Fold = FoldValueWithUndef(
              Opcode, RawBits1[I], UndefElts1[I], RawBits2[I], UndefElts2[I]);
          if (!Fold)
            break;
          RawBits.push_back(*Fold);
        }
        if (RawBits.size() == NumElts.getFixedValue()) {
          // We have constant folded, but we might need to cast this again back
          // to the original (possibly legalized) type.
          EVT BVVT, BVEltVT;
          if (N1.getValueType() == VT) {
            BVVT = N1.getValueType();
            BVEltVT = BV1->getOperand(0).getValueType();
          } else {
            BVVT = N2.getValueType();
            BVEltVT = BV2->getOperand(0).getValueType();
          }
          unsigned BVEltBits = BVEltVT.getSizeInBits();
          SmallVector<APInt> DstBits;
          BitVector DstUndefs;
          BuildVectorSDNode::recastRawBits(IsLE, BVVT.getScalarSizeInBits(),
                                           DstBits, RawBits, DstUndefs,
                                           BitVector(RawBits.size(), false));
          SmallVector<SDValue> Ops(DstBits.size(), getUNDEF(BVEltVT));
          for (unsigned I = 0, E = DstBits.size(); I != E; ++I) {
            if (DstUndefs[I])
              continue;
            Ops[I] = getConstant(DstBits[I].sext(BVEltBits), DL, BVEltVT);
          }
          return getBitcast(VT, getBuildVector(BVVT, DL, Ops));
        }
      }
    }
  }

  // Fold (mul step_vector(C0), C1) to (step_vector(C0 * C1)).
  //      (shl step_vector(C0), C1) -> (step_vector(C0 << C1))
  if ((Opcode == ISD::MUL || Opcode == ISD::SHL) &&
      Ops[0].getOpcode() == ISD::STEP_VECTOR) {
    APInt RHSVal;
    if (ISD::isConstantSplatVector(Ops[1].getNode(), RHSVal)) {
      APInt NewStep = Opcode == ISD::MUL
                          ? Ops[0].getConstantOperandAPInt(0) * RHSVal
                          : Ops[0].getConstantOperandAPInt(0) << RHSVal;
      return getStepVector(DL, VT, NewStep);
    }
  }

  auto IsScalarOrSameVectorSize = [NumElts](const SDValue &Op) {
    return !Op.getValueType().isVector() ||
           Op.getValueType().getVectorElementCount() == NumElts;
  };

  auto IsBuildVectorSplatVectorOrUndef = [](const SDValue &Op) {
    return Op.isUndef() || Op.getOpcode() == ISD::CONDCODE ||
           Op.getOpcode() == ISD::BUILD_VECTOR ||
           Op.getOpcode() == ISD::SPLAT_VECTOR;
  };

  // All operands must be vector types with the same number of elements as
  // the result type and must be either UNDEF or a build/splat vector
  // or UNDEF scalars.
  if (!llvm::all_of(Ops, IsBuildVectorSplatVectorOrUndef) ||
      !llvm::all_of(Ops, IsScalarOrSameVectorSize))
    return SDValue();

  // If we are comparing vectors, then the result needs to be a i1 boolean that
  // is then extended back to the legal result type depending on how booleans
  // are represented.
  EVT SVT = (Opcode == ISD::SETCC ? MVT::i1 : VT.getScalarType());
  ISD::NodeType ExtendCode =
      (Opcode == ISD::SETCC && SVT != VT.getScalarType())
          ? TargetLowering::getExtendForContent(TLI->getBooleanContents(VT))
          : ISD::SIGN_EXTEND;

  // Find legal integer scalar type for constant promotion and
  // ensure that its scalar size is at least as large as source.
  EVT LegalSVT = VT.getScalarType();
  if (NewNodesMustHaveLegalTypes && LegalSVT.isInteger()) {
    LegalSVT = TLI->getTypeToTransformTo(*getContext(), LegalSVT);
    if (LegalSVT.bitsLT(VT.getScalarType()))
      return SDValue();
  }

  // For scalable vector types we know we're dealing with SPLAT_VECTORs. We
  // only have one operand to check. For fixed-length vector types we may have
  // a combination of BUILD_VECTOR and SPLAT_VECTOR.
  unsigned NumVectorElts = NumElts.isScalable() ? 1 : NumElts.getFixedValue();

  // Constant fold each scalar lane separately.
  SmallVector<SDValue, 4> ScalarResults;
  for (unsigned I = 0; I != NumVectorElts; I++) {
    SmallVector<SDValue, 4> ScalarOps;
    for (SDValue Op : Ops) {
      EVT InSVT = Op.getValueType().getScalarType();
      if (Op.getOpcode() != ISD::BUILD_VECTOR &&
          Op.getOpcode() != ISD::SPLAT_VECTOR) {
        if (Op.isUndef())
          ScalarOps.push_back(getUNDEF(InSVT));
        else
          ScalarOps.push_back(Op);
        continue;
      }

      SDValue ScalarOp =
          Op.getOperand(Op.getOpcode() == ISD::SPLAT_VECTOR ? 0 : I);
      EVT ScalarVT = ScalarOp.getValueType();

      // Build vector (integer) scalar operands may need implicit
      // truncation - do this before constant folding.
      if (ScalarVT.isInteger() && ScalarVT.bitsGT(InSVT)) {
        // Don't create illegally-typed nodes unless they're constants or undef
        // - if we fail to constant fold we can't guarantee the (dead) nodes
        // we're creating will be cleaned up before being visited for
        // legalization.
        if (NewNodesMustHaveLegalTypes && !ScalarOp.isUndef() &&
            !isa<ConstantSDNode>(ScalarOp) &&
            TLI->getTypeAction(*getContext(), InSVT) !=
                TargetLowering::TypeLegal)
          return SDValue();
        ScalarOp = getNode(ISD::TRUNCATE, DL, InSVT, ScalarOp);
      }

      ScalarOps.push_back(ScalarOp);
    }

    // Constant fold the scalar operands.
    SDValue ScalarResult = getNode(Opcode, DL, SVT, ScalarOps, Flags);

    // Scalar folding only succeeded if the result is a constant or UNDEF.
    if (!ScalarResult.isUndef() && ScalarResult.getOpcode() != ISD::Constant &&
        ScalarResult.getOpcode() != ISD::ConstantFP)
      return SDValue();

    // Legalize the (integer) scalar constant if necessary. We only do
    // this once we know the folding succeeded, since otherwise we would
    // get a node with illegal type which has a user.
    if (LegalSVT != SVT)
      ScalarResult = getNode(ExtendCode, DL, LegalSVT, ScalarResult);

    ScalarResults.push_back(ScalarResult);
  }

  SDValue V = NumElts.isScalable() ? getSplatVector(VT, DL, ScalarResults[0])
                                   : getBuildVector(VT, DL, ScalarResults);
  NewSDValueDbgMsg(V, "New node fold constant vector: ", this);
  return V;
}

SDValue SelectionDAG::foldConstantFPMath(unsigned Opcode, const SDLoc &DL,
                                         EVT VT, ArrayRef<SDValue> Ops) {
  // TODO: Add support for unary/ternary fp opcodes.
  if (Ops.size() != 2)
    return SDValue();

  // TODO: We don't do any constant folding for strict FP opcodes here, but we
  //       should. That will require dealing with a potentially non-default
  //       rounding mode, checking the "opStatus" return value from the APFloat
  //       math calculations, and possibly other variations.
  SDValue N1 = Ops[0];
  SDValue N2 = Ops[1];
  ConstantFPSDNode *N1CFP = isConstOrConstSplatFP(N1, /*AllowUndefs*/ false);
  ConstantFPSDNode *N2CFP = isConstOrConstSplatFP(N2, /*AllowUndefs*/ false);
  if (N1CFP && N2CFP) {
    APFloat C1 = N1CFP->getValueAPF(); // make copy
    const APFloat &C2 = N2CFP->getValueAPF();
    switch (Opcode) {
    case ISD::FADD:
      C1.add(C2, APFloat::rmNearestTiesToEven);
      return getConstantFP(C1, DL, VT);
    case ISD::FSUB:
      C1.subtract(C2, APFloat::rmNearestTiesToEven);
      return getConstantFP(C1, DL, VT);
    case ISD::FMUL:
      C1.multiply(C2, APFloat::rmNearestTiesToEven);
      return getConstantFP(C1, DL, VT);
    case ISD::FDIV:
      C1.divide(C2, APFloat::rmNearestTiesToEven);
      return getConstantFP(C1, DL, VT);
    case ISD::FREM:
      C1.mod(C2);
      return getConstantFP(C1, DL, VT);
    case ISD::FCOPYSIGN:
      C1.copySign(C2);
      return getConstantFP(C1, DL, VT);
    case ISD::FMINNUM:
      return getConstantFP(minnum(C1, C2), DL, VT);
    case ISD::FMAXNUM:
      return getConstantFP(maxnum(C1, C2), DL, VT);
    case ISD::FMINIMUM:
      return getConstantFP(minimum(C1, C2), DL, VT);
    case ISD::FMAXIMUM:
      return getConstantFP(maximum(C1, C2), DL, VT);
    case ISD::FMINIMUMNUM:
      return getConstantFP(minimumnum(C1, C2), DL, VT);
    case ISD::FMAXIMUMNUM:
      return getConstantFP(maximumnum(C1, C2), DL, VT);
    default: break;
    }
  }
  if (N1CFP && Opcode == ISD::FP_ROUND) {
    APFloat C1 = N1CFP->getValueAPF();    // make copy
    bool Unused;
    // This can return overflow, underflow, or inexact; we don't care.
    // FIXME need to be more flexible about rounding mode.
    (void)C1.convert(VT.getFltSemantics(), APFloat::rmNearestTiesToEven,
                     &Unused);
    return getConstantFP(C1, DL, VT);
  }

  switch (Opcode) {
  case ISD::FSUB:
    // -0.0 - undef --> undef (consistent with "fneg undef")
    if (ConstantFPSDNode *N1C = isConstOrConstSplatFP(N1, /*AllowUndefs*/ true))
      if (N1C && N1C->getValueAPF().isNegZero() && N2.isUndef())
        return getUNDEF(VT);
    [[fallthrough]];

  case ISD::FADD:
  case ISD::FMUL:
  case ISD::FDIV:
  case ISD::FREM:
    // If both operands are undef, the result is undef. If 1 operand is undef,
    // the result is NaN. This should match the behavior of the IR optimizer.
    if (N1.isUndef() && N2.isUndef())
      return getUNDEF(VT);
    if (N1.isUndef() || N2.isUndef())
      return getConstantFP(APFloat::getNaN(VT.getFltSemantics()), DL, VT);
  }
  return SDValue();
}

SDValue SelectionDAG::FoldConstantBuildVector(BuildVectorSDNode *BV,
                                              const SDLoc &DL, EVT DstEltVT) {
  EVT SrcEltVT = BV->getValueType(0).getVectorElementType();

  // If this is already the right type, we're done.
  if (SrcEltVT == DstEltVT)
    return SDValue(BV, 0);

  unsigned SrcBitSize = SrcEltVT.getSizeInBits();
  unsigned DstBitSize = DstEltVT.getSizeInBits();

  // If this is a conversion of N elements of one type to N elements of another
  // type, convert each element.  This handles FP<->INT cases.
  if (SrcBitSize == DstBitSize) {
    SmallVector<SDValue, 8> Ops;
    for (SDValue Op : BV->op_values()) {
      // If the vector element type is not legal, the BUILD_VECTOR operands
      // are promoted and implicitly truncated.  Make that explicit here.
      if (Op.getValueType() != SrcEltVT)
        Op = getNode(ISD::TRUNCATE, DL, SrcEltVT, Op);
      Ops.push_back(getBitcast(DstEltVT, Op));
    }
    EVT VT = EVT::getVectorVT(*getContext(), DstEltVT,
                              BV->getValueType(0).getVectorNumElements());
    return getBuildVector(VT, DL, Ops);
  }

  // Otherwise, we're growing or shrinking the elements.  To avoid having to
  // handle annoying details of growing/shrinking FP values, we convert them to
  // int first.
  if (SrcEltVT.isFloatingPoint()) {
    // Convert the input float vector to a int vector where the elements are the
    // same sizes.
    EVT IntEltVT = EVT::getIntegerVT(*getContext(), SrcEltVT.getSizeInBits());
    if (SDValue Tmp = FoldConstantBuildVector(BV, DL, IntEltVT))
      return FoldConstantBuildVector(cast<BuildVectorSDNode>(Tmp), DL,
                                     DstEltVT);
    return SDValue();
  }

  // Now we know the input is an integer vector.  If the output is a FP type,
  // convert to integer first, then to FP of the right size.
  if (DstEltVT.isFloatingPoint()) {
    EVT IntEltVT = EVT::getIntegerVT(*getContext(), DstEltVT.getSizeInBits());
    if (SDValue Tmp = FoldConstantBuildVector(BV, DL, IntEltVT))
      return FoldConstantBuildVector(cast<BuildVectorSDNode>(Tmp), DL,
                                     DstEltVT);
    return SDValue();
  }

  // Okay, we know the src/dst types are both integers of differing types.
  assert(SrcEltVT.isInteger() && DstEltVT.isInteger());

  // Extract the constant raw bit data.
  BitVector UndefElements;
  SmallVector<APInt> RawBits;
  bool IsLE = getDataLayout().isLittleEndian();
  if (!BV->getConstantRawBits(IsLE, DstBitSize, RawBits, UndefElements))
    return SDValue();

  SmallVector<SDValue, 8> Ops;
  for (unsigned I = 0, E = RawBits.size(); I != E; ++I) {
    if (UndefElements[I])
      Ops.push_back(getUNDEF(DstEltVT));
    else
      Ops.push_back(getConstant(RawBits[I], DL, DstEltVT));
  }

  EVT VT = EVT::getVectorVT(*getContext(), DstEltVT, Ops.size());
  return getBuildVector(VT, DL, Ops);
}

SDValue SelectionDAG::getAssertAlign(const SDLoc &DL, SDValue Val, Align A) {
  assert(Val.getValueType().isInteger() && "Invalid AssertAlign!");

  // There's no need to assert on a byte-aligned pointer. All pointers are at
  // least byte aligned.
  if (A == Align(1))
    return Val;

  SDVTList VTs = getVTList(Val.getValueType());
  FoldingSetNodeID ID;
  AddNodeIDNode(ID, ISD::AssertAlign, VTs, {Val});
  ID.AddInteger(A.value());

  void *IP = nullptr;
  if (SDNode *E = FindNodeOrInsertPos(ID, DL, IP))
    return SDValue(E, 0);

  auto *N =
      newSDNode<AssertAlignSDNode>(DL.getIROrder(), DL.getDebugLoc(), VTs, A);
  createOperands(N, {Val});

  CSEMap.InsertNode(N, IP);
  InsertNode(N);

  SDValue V(N, 0);
  NewSDValueDbgMsg(V, "Creating new node: ", this);
  return V;
}

SDValue SelectionDAG::getNode(unsigned Opcode, const SDLoc &DL, EVT VT,
                              SDValue N1, SDValue N2) {
  SDNodeFlags Flags;
  if (Inserter)
    Flags = Inserter->getFlags();
  return getNode(Opcode, DL, VT, N1, N2, Flags);
}

void SelectionDAG::canonicalizeCommutativeBinop(unsigned Opcode, SDValue &N1,
                                                SDValue &N2) const {
  if (!TLI->isCommutativeBinOp(Opcode))
    return;

  // Canonicalize:
  //   binop(const, nonconst) -> binop(nonconst, const)
  bool N1C = isConstantIntBuildVectorOrConstantInt(N1);
  bool N2C = isConstantIntBuildVectorOrConstantInt(N2);
  bool N1CFP = isConstantFPBuildVectorOrConstantFP(N1);
  bool N2CFP = isConstantFPBuildVectorOrConstantFP(N2);
  if ((N1C && !N2C) || (N1CFP && !N2CFP))
    std::swap(N1, N2);

  // Canonicalize:
  //  binop(splat(x), step_vector) -> binop(step_vector, splat(x))
  else if (N1.getOpcode() == ISD::SPLAT_VECTOR &&
           N2.getOpcode() == ISD::STEP_VECTOR)
    std::swap(N1, N2);
}

SDValue SelectionDAG::getNode(unsigned Opcode, const SDLoc &DL, EVT VT,
                              SDValue N1, SDValue N2, const SDNodeFlags Flags) {
  assert(N1.getOpcode() != ISD::DELETED_NODE &&
         N2.getOpcode() != ISD::DELETED_NODE &&
         "Operand is DELETED_NODE!");

  canonicalizeCommutativeBinop(Opcode, N1, N2);

  auto *N1C = dyn_cast<ConstantSDNode>(N1);
  auto *N2C = dyn_cast<ConstantSDNode>(N2);

  // Don't allow undefs in vector splats - we might be returning N2 when folding
  // to zero etc.
  ConstantSDNode *N2CV =
      isConstOrConstSplat(N2, /*AllowUndefs*/ false, /*AllowTruncation*/ true);

  switch (Opcode) {
  default: break;
  case ISD::TokenFactor:
    assert(VT == MVT::Other && N1.getValueType() == MVT::Other &&
           N2.getValueType() == MVT::Other && "Invalid token factor!");
    // Fold trivial token factors.
    if (N1.getOpcode() == ISD::EntryToken) return N2;
    if (N2.getOpcode() == ISD::EntryToken) return N1;
    if (N1 == N2) return N1;
    break;
  case ISD::BUILD_VECTOR: {
    // Attempt to simplify BUILD_VECTOR.
    SDValue Ops[] = {N1, N2};
    if (SDValue V = FoldBUILD_VECTOR(DL, VT, Ops, *this))
      return V;
    break;
  }
  case ISD::CONCAT_VECTORS: {
    SDValue Ops[] = {N1, N2};
    if (SDValue V = foldCONCAT_VECTORS(DL, VT, Ops, *this))
      return V;
    break;
  }
  case ISD::AND:
    assert(VT.isInteger() && "This operator does not apply to FP types!");
    assert(N1.getValueType() == N2.getValueType() &&
           N1.getValueType() == VT && "Binary operator types must match!");
    // (X & 0) -> 0.  This commonly occurs when legalizing i64 values, so it's
    // worth handling here.
    if (N2CV && N2CV->isZero())
      return N2;
    if (N2CV && N2CV->isAllOnes()) // X & -1 -> X
      return N1;
    break;
  case ISD::OR:
  case ISD::XOR:
  case ISD::ADD:
  case ISD::PTRADD:
  case ISD::SUB:
    assert(VT.isInteger() && "This operator does not apply to FP types!");
    assert(N1.getValueType() == N2.getValueType() &&
           N1.getValueType() == VT && "Binary operator types must match!");
    // The equal operand types requirement is unnecessarily strong for PTRADD.
    // However, the SelectionDAGBuilder does not generate PTRADDs with different
    // operand types, and we'd need to re-implement GEP's non-standard wrapping
    // logic everywhere where PTRADDs may be folded or combined to properly
    // support them. If/when we introduce pointer types to the SDAG, we will
    // need to relax this constraint.

    // (X ^|+- 0) -> X.  This commonly occurs when legalizing i64 values, so
    // it's worth handling here.
    if (N2CV && N2CV->isZero())
      return N1;
    if ((Opcode == ISD::ADD || Opcode == ISD::SUB) &&
        VT.getScalarType() == MVT::i1)
      return getNode(ISD::XOR, DL, VT, N1, N2);
    // Fold (add (vscale * C0), (vscale * C1)) to (vscale * (C0 + C1)).
    if (Opcode == ISD::ADD && N1.getOpcode() == ISD::VSCALE &&
        N2.getOpcode() == ISD::VSCALE) {
      const APInt &C1 = N1->getConstantOperandAPInt(0);
      const APInt &C2 = N2->getConstantOperandAPInt(0);
      return getVScale(DL, VT, C1 + C2);
    }
    break;
  case ISD::MUL:
    assert(VT.isInteger() && "This operator does not apply to FP types!");
    assert(N1.getValueType() == N2.getValueType() &&
           N1.getValueType() == VT && "Binary operator types must match!");
    if (VT.getScalarType() == MVT::i1)
      return getNode(ISD::AND, DL, VT, N1, N2);
    if (N2C && (N1.getOpcode() == ISD::VSCALE) && Flags.hasNoSignedWrap()) {
      const APInt &MulImm = N1->getConstantOperandAPInt(0);
      const APInt &N2CImm = N2C->getAPIntValue();
      return getVScale(DL, VT, MulImm * N2CImm);
    }
    break;
  case ISD::UDIV:
  case ISD::UREM:
  case ISD::MULHU:
  case ISD::MULHS:
  case ISD::SDIV:
  case ISD::SREM:
  case ISD::SADDSAT:
  case ISD::SSUBSAT:
  case ISD::UADDSAT:
  case ISD::USUBSAT:
    assert(VT.isInteger() && "This operator does not apply to FP types!");
    assert(N1.getValueType() == N2.getValueType() &&
           N1.getValueType() == VT && "Binary operator types must match!");
    if (VT.getScalarType() == MVT::i1) {
      // fold (add_sat x, y) -> (or x, y) for bool types.
      if (Opcode == ISD::SADDSAT || Opcode == ISD::UADDSAT)
        return getNode(ISD::OR, DL, VT, N1, N2);
      // fold (sub_sat x, y) -> (and x, ~y) for bool types.
      if (Opcode == ISD::SSUBSAT || Opcode == ISD::USUBSAT)
        return getNode(ISD::AND, DL, VT, N1, getNOT(DL, N2, VT));
    }
    break;
  case ISD::SCMP:
  case ISD::UCMP:
    assert(N1.getValueType() == N2.getValueType() &&
           "Types of operands of UCMP/SCMP must match");
    assert(N1.getValueType().isVector() == VT.isVector() &&
           "Operands and return type of must both be scalars or vectors");
    if (VT.isVector())
      assert(VT.getVectorElementCount() ==
                 N1.getValueType().getVectorElementCount() &&
             "Result and operands must have the same number of elements");
    break;
  case ISD::AVGFLOORS:
  case ISD::AVGFLOORU:
  case ISD::AVGCEILS:
  case ISD::AVGCEILU:
    assert(VT.isInteger() && "This operator does not apply to FP types!");
    assert(N1.getValueType() == N2.getValueType() &&
           N1.getValueType() == VT && "Binary operator types must match!");
    break;
  case ISD::ABDS:
  case ISD::ABDU:
    assert(VT.isInteger() && "This operator does not apply to FP types!");
    assert(N1.getValueType() == N2.getValueType() &&
           N1.getValueType() == VT && "Binary operator types must match!");
    if (VT.getScalarType() == MVT::i1)
      return getNode(ISD::XOR, DL, VT, N1, N2);
    break;
  case ISD::SMIN:
  case ISD::UMAX:
    assert(VT.isInteger() && "This operator does not apply to FP types!");
    assert(N1.getValueType() == N2.getValueType() &&
           N1.getValueType() == VT && "Binary operator types must match!");
    if (VT.getScalarType() == MVT::i1)
      return getNode(ISD::OR, DL, VT, N1, N2);
    break;
  case ISD::SMAX:
  case ISD::UMIN:
    assert(VT.isInteger() && "This operator does not apply to FP types!");
    assert(N1.getValueType() == N2.getValueType() &&
           N1.getValueType() == VT && "Binary operator types must match!");
    if (VT.getScalarType() == MVT::i1)
      return getNode(ISD::AND, DL, VT, N1, N2);
    break;
  case ISD::FADD:
  case ISD::FSUB:
  case ISD::FMUL:
  case ISD::FDIV:
  case ISD::FREM:
    assert(VT.isFloatingPoint() && "This operator only applies to FP types!");
    assert(N1.getValueType() == N2.getValueType() &&
           N1.getValueType() == VT && "Binary operator types must match!");
    if (SDValue V = simplifyFPBinop(Opcode, N1, N2, Flags))
      return V;
    break;
  case ISD::FCOPYSIGN:   // N1 and result must match.  N1/N2 need not match.
    assert(N1.getValueType() == VT &&
           N1.getValueType().isFloatingPoint() &&
           N2.getValueType().isFloatingPoint() &&
           "Invalid FCOPYSIGN!");
    break;
  case ISD::SHL:
    if (N2C && (N1.getOpcode() == ISD::VSCALE) && Flags.hasNoSignedWrap()) {
      const APInt &MulImm = N1->getConstantOperandAPInt(0);
      const APInt &ShiftImm = N2C->getAPIntValue();
      return getVScale(DL, VT, MulImm << ShiftImm);
    }
    [[fallthrough]];
  case ISD::SRA:
  case ISD::SRL:
    if (SDValue V = simplifyShift(N1, N2))
      return V;
    [[fallthrough]];
  case ISD::ROTL:
  case ISD::ROTR:
    assert(VT == N1.getValueType() &&
           "Shift operators return type must be the same as their first arg");
    assert(VT.isInteger() && N2.getValueType().isInteger() &&
           "Shifts only work on integers");
    assert((!VT.isVector() || VT == N2.getValueType()) &&
           "Vector shift amounts must be in the same as their first arg");
    // Verify that the shift amount VT is big enough to hold valid shift
    // amounts.  This catches things like trying to shift an i1024 value by an
    // i8, which is easy to fall into in generic code that uses
    // TLI.getShiftAmount().
    assert(N2.getValueType().getScalarSizeInBits() >=
               Log2_32_Ceil(VT.getScalarSizeInBits()) &&
           "Invalid use of small shift amount with oversized value!");

    // Always fold shifts of i1 values so the code generator doesn't need to
    // handle them.  Since we know the size of the shift has to be less than the
    // size of the value, the shift/rotate count is guaranteed to be zero.
    if (VT == MVT::i1)
      return N1;
    if (N2CV && N2CV->isZero())
      return N1;
    break;
  case ISD::FP_ROUND:
    assert(VT.isFloatingPoint() && N1.getValueType().isFloatingPoint() &&
           VT.bitsLE(N1.getValueType()) && N2C &&
           (N2C->getZExtValue() == 0 || N2C->getZExtValue() == 1) &&
           N2.getOpcode() == ISD::TargetConstant && "Invalid FP_ROUND!");
    if (N1.getValueType() == VT) return N1;  // noop conversion.
    break;
  case ISD::AssertNoFPClass: {
    assert(N1.getValueType().isFloatingPoint() &&
           "AssertNoFPClass is used for a non-floating type");
    assert(isa<ConstantSDNode>(N2) && "NoFPClass is not Constant");
    FPClassTest NoFPClass = static_cast<FPClassTest>(N2->getAsZExtVal());
    assert(llvm::to_underlying(NoFPClass) <=
               BitmaskEnumDetail::Mask<FPClassTest>() &&
           "FPClassTest value too large");
    (void)NoFPClass;
    break;
  }
  case ISD::AssertSext:
  case ISD::AssertZext: {
    EVT EVT = cast<VTSDNode>(N2)->getVT();
    assert(VT == N1.getValueType() && "Not an inreg extend!");
    assert(VT.isInteger() && EVT.isInteger() &&
           "Cannot *_EXTEND_INREG FP types");
    assert(!EVT.isVector() &&
           "AssertSExt/AssertZExt type should be the vector element type "
           "rather than the vector type!");
    assert(EVT.bitsLE(VT.getScalarType()) && "Not extending!");
    if (VT.getScalarType() == EVT) return N1; // noop assertion.
    break;
  }
  case ISD::SIGN_EXTEND_INREG: {
    EVT EVT = cast<VTSDNode>(N2)->getVT();
    assert(VT == N1.getValueType() && "Not an inreg extend!");
    assert(VT.isInteger() && EVT.isInteger() &&
           "Cannot *_EXTEND_INREG FP types");
    assert(EVT.isVector() == VT.isVector() &&
           "SIGN_EXTEND_INREG type should be vector iff the operand "
           "type is vector!");
    assert((!EVT.isVector() ||
            EVT.getVectorElementCount() == VT.getVectorElementCount()) &&
           "Vector element counts must match in SIGN_EXTEND_INREG");
    assert(EVT.bitsLE(VT) && "Not extending!");
    if (EVT == VT) return N1;  // Not actually extending
    break;
  }
  case ISD::FP_TO_SINT_SAT:
  case ISD::FP_TO_UINT_SAT: {
    assert(VT.isInteger() && cast<VTSDNode>(N2)->getVT().isInteger() &&
           N1.getValueType().isFloatingPoint() && "Invalid FP_TO_*INT_SAT");
    assert(N1.getValueType().isVector() == VT.isVector() &&
           "FP_TO_*INT_SAT type should be vector iff the operand type is "
           "vector!");
    assert((!VT.isVector() || VT.getVectorElementCount() ==
                                  N1.getValueType().getVectorElementCount()) &&
           "Vector element counts must match in FP_TO_*INT_SAT");
    assert(!cast<VTSDNode>(N2)->getVT().isVector() &&
           "Type to saturate to must be a scalar.");
    assert(cast<VTSDNode>(N2)->getVT().bitsLE(VT.getScalarType()) &&
           "Not extending!");
    break;
  }
  case ISD::EXTRACT_VECTOR_ELT:
    assert(VT.getSizeInBits() >= N1.getValueType().getScalarSizeInBits() &&
           "The result of EXTRACT_VECTOR_ELT must be at least as wide as the \
             element type of the vector.");

    // Extract from an undefined value or using an undefined index is undefined.
    if (N1.isUndef() || N2.isUndef())
      return getUNDEF(VT);

    // EXTRACT_VECTOR_ELT of out-of-bounds element is an UNDEF for fixed length
    // vectors. For scalable vectors we will provide appropriate support for
    // dealing with arbitrary indices.
    if (N2C && N1.getValueType().isFixedLengthVector() &&
        N2C->getAPIntValue().uge(N1.getValueType().getVectorNumElements()))
      return getUNDEF(VT);

    // EXTRACT_VECTOR_ELT of CONCAT_VECTORS is often formed while lowering is
    // expanding copies of large vectors from registers. This only works for
    // fixed length vectors, since we need to know the exact number of
    // elements.
    if (N2C && N1.getOpcode() == ISD::CONCAT_VECTORS &&
        N1.getOperand(0).getValueType().isFixedLengthVector()) {
      unsigned Factor = N1.getOperand(0).getValueType().getVectorNumElements();
      return getExtractVectorElt(DL, VT,
                                 N1.getOperand(N2C->getZExtValue() / Factor),
                                 N2C->getZExtValue() % Factor);
    }

    // EXTRACT_VECTOR_ELT of BUILD_VECTOR or SPLAT_VECTOR is often formed while
    // lowering is expanding large vector constants.
    if (N2C && (N1.getOpcode() == ISD::BUILD_VECTOR ||
                N1.getOpcode() == ISD::SPLAT_VECTOR)) {
      assert((N1.getOpcode() != ISD::BUILD_VECTOR ||
              N1.getValueType().isFixedLengthVector()) &&
             "BUILD_VECTOR used for scalable vectors");
      unsigned Index =
          N1.getOpcode() == ISD::BUILD_VECTOR ? N2C->getZExtValue() : 0;
      SDValue Elt = N1.getOperand(Index);

      if (VT != Elt.getValueType())
        // If the vector element type is not legal, the BUILD_VECTOR operands
        // are promoted and implicitly truncated, and the result implicitly
        // extended. Make that explicit here.
        Elt = getAnyExtOrTrunc(Elt, DL, VT);

      return Elt;
    }

    // EXTRACT_VECTOR_ELT of INSERT_VECTOR_ELT is often formed when vector
    // operations are lowered to scalars.
    if (N1.getOpcode() == ISD::INSERT_VECTOR_ELT) {
      // If the indices are the same, return the inserted element else
      // if the indices are known different, extract the element from
      // the original vector.
      SDValue N1Op2 = N1.getOperand(2);
      ConstantSDNode *N1Op2C = dyn_cast<ConstantSDNode>(N1Op2);

      if (N1Op2C && N2C) {
        if (N1Op2C->getZExtValue() == N2C->getZExtValue()) {
          if (VT == N1.getOperand(1).getValueType())
            return N1.getOperand(1);
          if (VT.isFloatingPoint()) {
            assert(VT.getSizeInBits() > N1.getOperand(1).getValueType().getSizeInBits());
            return getFPExtendOrRound(N1.getOperand(1), DL, VT);
          }
          return getSExtOrTrunc(N1.getOperand(1), DL, VT);
        }
        return getNode(ISD::EXTRACT_VECTOR_ELT, DL, VT, N1.getOperand(0), N2);
      }
    }

    // EXTRACT_VECTOR_ELT of v1iX EXTRACT_SUBVECTOR could be formed
    // when vector types are scalarized and v1iX is legal.
    // vextract (v1iX extract_subvector(vNiX, Idx)) -> vextract(vNiX,Idx).
    // Here we are completely ignoring the extract element index (N2),
    // which is fine for fixed width vectors, since any index other than 0
    // is undefined anyway. However, this cannot be ignored for scalable
    // vectors - in theory we could support this, but we don't want to do this
    // without a profitability check.
    if (N1.getOpcode() == ISD::EXTRACT_SUBVECTOR &&
        N1.getValueType().isFixedLengthVector() &&
        N1.getValueType().getVectorNumElements() == 1) {
      return getNode(ISD::EXTRACT_VECTOR_ELT, DL, VT, N1.getOperand(0),
                     N1.getOperand(1));
    }
    break;
  case ISD::EXTRACT_ELEMENT:
    assert(N2C && (unsigned)N2C->getZExtValue() < 2 && "Bad EXTRACT_ELEMENT!");
    assert(!N1.getValueType().isVector() && !VT.isVector() &&
           (N1.getValueType().isInteger() == VT.isInteger()) &&
           N1.getValueType() != VT &&
           "Wrong types for EXTRACT_ELEMENT!");

    // EXTRACT_ELEMENT of BUILD_PAIR is often formed while legalize is expanding
    // 64-bit integers into 32-bit parts.  Instead of building the extract of
    // the BUILD_PAIR, only to have legalize rip it apart, just do it now.
    if (N1.getOpcode() == ISD::BUILD_PAIR)
      return N1.getOperand(N2C->getZExtValue());

    // EXTRACT_ELEMENT of a constant int is also very common.
    if (N1C) {
      unsigned ElementSize = VT.getSizeInBits();
      unsigned Shift = ElementSize * N2C->getZExtValue();
      const APInt &Val = N1C->getAPIntValue();
      return getConstant(Val.extractBits(ElementSize, Shift), DL, VT);
    }
    break;
  case ISD::EXTRACT_SUBVECTOR: {
    EVT N1VT = N1.getValueType();
    assert(VT.isVector() && N1VT.isVector() &&
           "Extract subvector VTs must be vectors!");
    assert(VT.getVectorElementType() == N1VT.getVectorElementType() &&
           "Extract subvector VTs must have the same element type!");
    assert((VT.isFixedLengthVector() || N1VT.isScalableVector()) &&
           "Cannot extract a scalable vector from a fixed length vector!");
    assert((VT.isScalableVector() != N1VT.isScalableVector() ||
            VT.getVectorMinNumElements() <= N1VT.getVectorMinNumElements()) &&
           "Extract subvector must be from larger vector to smaller vector!");
    assert(N2C && "Extract subvector index must be a constant");
    assert((VT.isScalableVector() != N1VT.isScalableVector() ||
            (VT.getVectorMinNumElements() + N2C->getZExtValue()) <=
                N1VT.getVectorMinNumElements()) &&
           "Extract subvector overflow!");
    assert(N2C->getAPIntValue().getBitWidth() ==
               TLI->getVectorIdxWidth(getDataLayout()) &&
           "Constant index for EXTRACT_SUBVECTOR has an invalid size");

    // Trivial extraction.
    if (VT == N1VT)
      return N1;

    // EXTRACT_SUBVECTOR of an UNDEF is an UNDEF.
    if (N1.isUndef())
      return getUNDEF(VT);

    // EXTRACT_SUBVECTOR of CONCAT_VECTOR can be simplified if the pieces of
    // the concat have the same type as the extract.
    if (N1.getOpcode() == ISD::CONCAT_VECTORS &&
        VT == N1.getOperand(0).getValueType()) {
      unsigned Factor = VT.getVectorMinNumElements();
      return N1.getOperand(N2C->getZExtValue() / Factor);
    }

    // EXTRACT_SUBVECTOR of INSERT_SUBVECTOR is often created
    // during shuffle legalization.
    if (N1.getOpcode() == ISD::INSERT_SUBVECTOR && N2 == N1.getOperand(2) &&
        VT == N1.getOperand(1).getValueType())
      return N1.getOperand(1);
    break;
  }
  }

  if (N1.getOpcode() == ISD::POISON || N2.getOpcode() == ISD::POISON) {
    switch (Opcode) {
    case ISD::XOR:
    case ISD::ADD:
    case ISD::PTRADD:
    case ISD::SUB:
    case ISD::SIGN_EXTEND_INREG:
    case ISD::UDIV:
    case ISD::SDIV:
    case ISD::UREM:
    case ISD::SREM:
    case ISD::MUL:
    case ISD::AND:
    case ISD::SSUBSAT:
    case ISD::USUBSAT:
    case ISD::UMIN:
    case ISD::OR:
    case ISD::SADDSAT:
    case ISD::UADDSAT:
    case ISD::UMAX:
    case ISD::SMAX:
    case ISD::SMIN:
      // fold op(arg1, poison) -> poison, fold op(poison, arg2) -> poison.
      return N2.getOpcode() == ISD::POISON ? N2 : N1;
    }
  }

  // Canonicalize an UNDEF to the RHS, even over a constant.
  if (N1.getOpcode() == ISD::UNDEF && N2.getOpcode() != ISD::UNDEF) {
    if (TLI->isCommutativeBinOp(Opcode)) {
      std::swap(N1, N2);
    } else {
      switch (Opcode) {
      case ISD::PTRADD:
      case ISD::SUB:
        // fold op(undef, non_undef_arg2) -> undef.
        return N1;
      case ISD::SIGN_EXTEND_INREG:
      case ISD::UDIV:
      case ISD::SDIV:
      case ISD::UREM:
      case ISD::SREM:
      case ISD::SSUBSAT:
      case ISD::USUBSAT:
        // fold op(undef, non_undef_arg2) -> 0.
        return getConstant(0, DL, VT);
      }
    }
  }

  // Fold a bunch of operators when the RHS is undef.
  if (N2.getOpcode() == ISD::UNDEF) {
    switch (Opcode) {
    case ISD::XOR:
      if (N1.getOpcode() == ISD::UNDEF)
        // Handle undef ^ undef -> 0 special case. This is a common
        // idiom (misuse).
        return getConstant(0, DL, VT);
      [[fallthrough]];
    case ISD::ADD:
    case ISD::PTRADD:
    case ISD::SUB:
      // fold op(arg1, undef) -> undef.
      return N2;
    case ISD::UDIV:
    case ISD::SDIV:
    case ISD::UREM:
    case ISD::SREM:
      // fold op(arg1, undef) -> poison.
      return getPOISON(VT);
    case ISD::MUL:
    case ISD::AND:
    case ISD::SSUBSAT:
    case ISD::USUBSAT:
    case ISD::UMIN:
      // fold op(undef, undef) -> undef, fold op(arg1, undef) -> 0.
      return N1.getOpcode() == ISD::UNDEF ? N2 : getConstant(0, DL, VT);
    case ISD::OR:
    case ISD::SADDSAT:
    case ISD::UADDSAT:
    case ISD::UMAX:
      // fold op(undef, undef) -> undef, fold op(arg1, undef) -> -1.
      return N1.getOpcode() == ISD::UNDEF ? N2 : getAllOnesConstant(DL, VT);
    case ISD::SMAX:
      // fold op(undef, undef) -> undef, fold op(arg1, undef) -> MAX_INT.
      return N1.getOpcode() == ISD::UNDEF
                 ? N2
                 : getConstant(
                       APInt::getSignedMaxValue(VT.getScalarSizeInBits()), DL,
                       VT);
    case ISD::SMIN:
      // fold op(undef, undef) -> undef, fold op(arg1, undef) -> MIN_INT.
      return N1.getOpcode() == ISD::UNDEF
                 ? N2
                 : getConstant(
                       APInt::getSignedMinValue(VT.getScalarSizeInBits()), DL,
                       VT);
    }
  }

  // Perform trivial constant folding.
  if (SDValue SV = FoldConstantArithmetic(Opcode, DL, VT, {N1, N2}, Flags))
    return SV;

  // Memoize this node if possible.
  SDNode *N;
  SDVTList VTs = getVTList(VT);
  SDValue Ops[] = {N1, N2};
  if (VT != MVT::Glue) {
    FoldingSetNodeID ID;
    AddNodeIDNode(ID, Opcode, VTs, Ops);
    void *IP = nullptr;
    if (SDNode *E = FindNodeOrInsertPos(ID, DL, IP)) {
      E->intersectFlagsWith(Flags);
      return SDValue(E, 0);
    }

    N = newSDNode<SDNode>(Opcode, DL.getIROrder(), DL.getDebugLoc(), VTs);
    N->setFlags(Flags);
    createOperands(N, Ops);
    CSEMap.InsertNode(N, IP);
  } else {
    N = newSDNode<SDNode>(Opcode, DL.getIROrder(), DL.getDebugLoc(), VTs);
    createOperands(N, Ops);
  }

  InsertNode(N);
  SDValue V = SDValue(N, 0);
  NewSDValueDbgMsg(V, "Creating new node: ", this);
  return V;
}

SDValue SelectionDAG::getNode(unsigned Opcode, const SDLoc &DL, EVT VT,
                              SDValue N1, SDValue N2, SDValue N3) {
  SDNodeFlags Flags;
  if (Inserter)
    Flags = Inserter->getFlags();
  return getNode(Opcode, DL, VT, N1, N2, N3, Flags);
}

SDValue SelectionDAG::getNode(unsigned Opcode, const SDLoc &DL, EVT VT,
                              SDValue N1, SDValue N2, SDValue N3,
                              const SDNodeFlags Flags) {
  assert(N1.getOpcode() != ISD::DELETED_NODE &&
         N2.getOpcode() != ISD::DELETED_NODE &&
         N3.getOpcode() != ISD::DELETED_NODE &&
         "Operand is DELETED_NODE!");
  // Perform various simplifications.
  switch (Opcode) {
  case ISD::FMA:
  case ISD::FMAD: {
    assert(VT.isFloatingPoint() && "This operator only applies to FP types!");
    assert(N1.getValueType() == VT && N2.getValueType() == VT &&
           N3.getValueType() == VT && "FMA types must match!");
    ConstantFPSDNode *N1CFP = dyn_cast<ConstantFPSDNode>(N1);
    ConstantFPSDNode *N2CFP = dyn_cast<ConstantFPSDNode>(N2);
    ConstantFPSDNode *N3CFP = dyn_cast<ConstantFPSDNode>(N3);
    if (N1CFP && N2CFP && N3CFP) {
      APFloat  V1 = N1CFP->getValueAPF();
      const APFloat &V2 = N2CFP->getValueAPF();
      const APFloat &V3 = N3CFP->getValueAPF();
      if (Opcode == ISD::FMAD) {
        V1.multiply(V2, APFloat::rmNearestTiesToEven);
        V1.add(V3, APFloat::rmNearestTiesToEven);
      } else
        V1.fusedMultiplyAdd(V2, V3, APFloat::rmNearestTiesToEven);
      return getConstantFP(V1, DL, VT);
    }
    break;
  }
  case ISD::BUILD_VECTOR: {
    // Attempt to simplify BUILD_VECTOR.
    SDValue Ops[] = {N1, N2, N3};
    if (SDValue V = FoldBUILD_VECTOR(DL, VT, Ops, *this))
      return V;
    break;
  }
  case ISD::CONCAT_VECTORS: {
    SDValue Ops[] = {N1, N2, N3};
    if (SDValue V = foldCONCAT_VECTORS(DL, VT, Ops, *this))
      return V;
    break;
  }
  case ISD::SETCC: {
    assert(VT.isInteger() && "SETCC result type must be an integer!");
    assert(N1.getValueType() == N2.getValueType() &&
           "SETCC operands must have the same type!");
    assert(VT.isVector() == N1.getValueType().isVector() &&
           "SETCC type should be vector iff the operand type is vector!");
    assert((!VT.isVector() || VT.getVectorElementCount() ==
                                  N1.getValueType().getVectorElementCount()) &&
           "SETCC vector element counts must match!");
    // Use FoldSetCC to simplify SETCC's.
    if (SDValue V = FoldSetCC(VT, N1, N2, cast<CondCodeSDNode>(N3)->get(), DL))
      return V;
    // Vector constant folding.
    SDValue Ops[] = {N1, N2, N3};
    if (SDValue V = FoldConstantArithmetic(Opcode, DL, VT, Ops)) {
      NewSDValueDbgMsg(V, "New node vector constant folding: ", this);
      return V;
    }
    break;
  }
  case ISD::SELECT:
  case ISD::VSELECT:
    if (SDValue V = simplifySelect(N1, N2, N3))
      return V;
    break;
  case ISD::VECTOR_SHUFFLE:
    llvm_unreachable("should use getVectorShuffle constructor!");
  case ISD::VECTOR_SPLICE: {
    if (cast<ConstantSDNode>(N3)->isZero())
      return N1;
    break;
  }
  case ISD::INSERT_VECTOR_ELT: {
    assert(VT.isVector() && VT == N1.getValueType() &&
           "INSERT_VECTOR_ELT vector type mismatch");
    assert(VT.isFloatingPoint() == N2.getValueType().isFloatingPoint() &&
           "INSERT_VECTOR_ELT scalar fp/int mismatch");
    assert((!VT.isFloatingPoint() ||
            VT.getVectorElementType() == N2.getValueType()) &&
           "INSERT_VECTOR_ELT fp scalar type mismatch");
    assert((!VT.isInteger() ||
            VT.getScalarSizeInBits() <= N2.getScalarValueSizeInBits()) &&
           "INSERT_VECTOR_ELT int scalar size mismatch");

    auto *N3C = dyn_cast<ConstantSDNode>(N3);
    // INSERT_VECTOR_ELT into out-of-bounds element is an UNDEF, except
    // for scalable vectors where we will generate appropriate code to
    // deal with out-of-bounds cases correctly.
    if (N3C && N1.getValueType().isFixedLengthVector() &&
        N3C->getZExtValue() >= N1.getValueType().getVectorNumElements())
      return getUNDEF(VT);

    // Undefined index can be assumed out-of-bounds, so that's UNDEF too.
    if (N3.isUndef())
      return getUNDEF(VT);

    // If the inserted element is an UNDEF, just use the input vector.
    if (N2.isUndef())
      return N1;

    break;
  }
  case ISD::INSERT_SUBVECTOR: {
    // Inserting undef into undef is still undef.
    if (N1.isUndef() && N2.isUndef())
      return getUNDEF(VT);

    EVT N2VT = N2.getValueType();
    assert(VT == N1.getValueType() &&
           "Dest and insert subvector source types must match!");
    assert(VT.isVector() && N2VT.isVector() &&
           "Insert subvector VTs must be vectors!");
    assert(VT.getVectorElementType() == N2VT.getVectorElementType() &&
           "Insert subvector VTs must have the same element type!");
    assert((VT.isScalableVector() || N2VT.isFixedLengthVector()) &&
           "Cannot insert a scalable vector into a fixed length vector!");
    assert((VT.isScalableVector() != N2VT.isScalableVector() ||
            VT.getVectorMinNumElements() >= N2VT.getVectorMinNumElements()) &&
           "Insert subvector must be from smaller vector to larger vector!");
    assert(isa<ConstantSDNode>(N3) &&
           "Insert subvector index must be constant");
    assert((VT.isScalableVector() != N2VT.isScalableVector() ||
            (N2VT.getVectorMinNumElements() + N3->getAsZExtVal()) <=
                VT.getVectorMinNumElements()) &&
           "Insert subvector overflow!");
    assert(N3->getAsAPIntVal().getBitWidth() ==
               TLI->getVectorIdxWidth(getDataLayout()) &&
           "Constant index for INSERT_SUBVECTOR has an invalid size");

    // Trivial insertion.
    if (VT == N2VT)
      return N2;

    // If this is an insert of an extracted vector into an undef vector, we
    // can just use the input to the extract.
    if (N1.isUndef() && N2.getOpcode() == ISD::EXTRACT_SUBVECTOR &&
        N2.getOperand(1) == N3 && N2.getOperand(0).getValueType() == VT)
      return N2.getOperand(0);
    break;
  }
  case ISD::BITCAST:
    // Fold bit_convert nodes from a type to themselves.
    if (N1.getValueType() == VT)
      return N1;
    break;
  case ISD::VP_TRUNCATE:
  case ISD::VP_SIGN_EXTEND:
  case ISD::VP_ZERO_EXTEND:
    // Don't create noop casts.
    if (N1.getValueType() == VT)
      return N1;
    break;
  case ISD::VECTOR_COMPRESS: {
    [[maybe_unused]] EVT VecVT = N1.getValueType();
    [[maybe_unused]] EVT MaskVT = N2.getValueType();
    [[maybe_unused]] EVT PassthruVT = N3.getValueType();
    assert(VT == VecVT && "Vector and result type don't match.");
    assert(VecVT.isVector() && MaskVT.isVector() && PassthruVT.isVector() &&
           "All inputs must be vectors.");
    assert(VecVT == PassthruVT && "Vector and passthru types don't match.");
    assert(VecVT.getVectorElementCount() == MaskVT.getVectorElementCount() &&
           "Vector and mask must have same number of elements.");

    if (N1.isUndef() || N2.isUndef())
      return N3;

    break;
  }
  case ISD::PARTIAL_REDUCE_UMLA:
  case ISD::PARTIAL_REDUCE_SMLA:
  case ISD::PARTIAL_REDUCE_SUMLA: {
    [[maybe_unused]] EVT AccVT = N1.getValueType();
    [[maybe_unused]] EVT Input1VT = N2.getValueType();
    [[maybe_unused]] EVT Input2VT = N3.getValueType();
    assert(Input1VT.isVector() && Input1VT == Input2VT &&
           "Expected the second and third operands of the PARTIAL_REDUCE_MLA "
           "node to have the same type!");
    assert(VT.isVector() && VT == AccVT &&
           "Expected the first operand of the PARTIAL_REDUCE_MLA node to have "
           "the same type as its result!");
    assert(Input1VT.getVectorElementCount().hasKnownScalarFactor(
               AccVT.getVectorElementCount()) &&
           "Expected the element count of the second and third operands of the "
           "PARTIAL_REDUCE_MLA node to be a positive integer multiple of the "
           "element count of the first operand and the result!");
    assert(N2.getScalarValueSizeInBits() <= N1.getScalarValueSizeInBits() &&
           "Expected the second and third operands of the PARTIAL_REDUCE_MLA "
           "node to have an element type which is the same as or smaller than "
           "the element type of the first operand and result!");
    break;
  }
  }

  // Memoize node if it doesn't produce a glue result.
  SDNode *N;
  SDVTList VTs = getVTList(VT);
  SDValue Ops[] = {N1, N2, N3};
  if (VT != MVT::Glue) {
    FoldingSetNodeID ID;
    AddNodeIDNode(ID, Opcode, VTs, Ops);
    void *IP = nullptr;
    if (SDNode *E = FindNodeOrInsertPos(ID, DL, IP)) {
      E->intersectFlagsWith(Flags);
      return SDValue(E, 0);
    }

    N = newSDNode<SDNode>(Opcode, DL.getIROrder(), DL.getDebugLoc(), VTs);
    N->setFlags(Flags);
    createOperands(N, Ops);
    CSEMap.InsertNode(N, IP);
  } else {
    N = newSDNode<SDNode>(Opcode, DL.getIROrder(), DL.getDebugLoc(), VTs);
    createOperands(N, Ops);
  }

  InsertNode(N);
  SDValue V = SDValue(N, 0);
  NewSDValueDbgMsg(V, "Creating new node: ", this);
  return V;
}

SDValue SelectionDAG::getNode(unsigned Opcode, const SDLoc &DL, EVT VT,
                              SDValue N1, SDValue N2, SDValue N3, SDValue N4,
                              const SDNodeFlags Flags) {
  SDValue Ops[] = { N1, N2, N3, N4 };
  return getNode(Opcode, DL, VT, Ops, Flags);
}

SDValue SelectionDAG::getNode(unsigned Opcode, const SDLoc &DL, EVT VT,
                              SDValue N1, SDValue N2, SDValue N3, SDValue N4) {
  SDNodeFlags Flags;
  if (Inserter)
    Flags = Inserter->getFlags();
  return getNode(Opcode, DL, VT, N1, N2, N3, N4, Flags);
}

SDValue SelectionDAG::getNode(unsigned Opcode, const SDLoc &DL, EVT VT,
                              SDValue N1, SDValue N2, SDValue N3, SDValue N4,
                              SDValue N5, const SDNodeFlags Flags) {
  SDValue Ops[] = { N1, N2, N3, N4, N5 };
  return getNode(Opcode, DL, VT, Ops, Flags);
}

SDValue SelectionDAG::getNode(unsigned Opcode, const SDLoc &DL, EVT VT,
                              SDValue N1, SDValue N2, SDValue N3, SDValue N4,
                              SDValue N5) {
  SDNodeFlags Flags;
  if (Inserter)
    Flags = Inserter->getFlags();
  return getNode(Opcode, DL, VT, N1, N2, N3, N4, N5, Flags);
}

/// getStackArgumentTokenFactor - Compute a TokenFactor to force all
/// the incoming stack arguments to be loaded from the stack.
SDValue SelectionDAG::getStackArgumentTokenFactor(SDValue Chain) {
  SmallVector<SDValue, 8> ArgChains;

  // Include the original chain at the beginning of the list. When this is
  // used by target LowerCall hooks, this helps legalize find the
  // CALLSEQ_BEGIN node.
  ArgChains.push_back(Chain);

  // Add a chain value for each stack argument.
  for (SDNode *U : getEntryNode().getNode()->users())
    if (LoadSDNode *L = dyn_cast<LoadSDNode>(U))
      if (FrameIndexSDNode *FI = dyn_cast<FrameIndexSDNode>(L->getBasePtr()))
        if (FI->getIndex() < 0)
          ArgChains.push_back(SDValue(L, 1));

  // Build a tokenfactor for all the chains.
  return getNode(ISD::TokenFactor, SDLoc(Chain), MVT::Other, ArgChains);
}

/// getMemsetValue - Vectorized representation of the memset value
/// operand.
static SDValue getMemsetValue(SDValue Value, EVT VT, SelectionDAG &DAG,
                              const SDLoc &dl) {
  assert(!Value.isUndef());

  unsigned NumBits = VT.getScalarSizeInBits();
  if (ConstantSDNode *C = dyn_cast<ConstantSDNode>(Value)) {
    assert(C->getAPIntValue().getBitWidth() == 8);
    APInt Val = APInt::getSplat(NumBits, C->getAPIntValue());
    if (VT.isInteger()) {
      bool IsOpaque = VT.getSizeInBits() > 64 ||
          !DAG.getTargetLoweringInfo().isLegalStoreImmediate(C->getSExtValue());
      return DAG.getConstant(Val, dl, VT, false, IsOpaque);
    }
    return DAG.getConstantFP(APFloat(VT.getFltSemantics(), Val), dl, VT);
  }

  assert(Value.getValueType() == MVT::i8 && "memset with non-byte fill value?");
  EVT IntVT = VT.getScalarType();
  if (!IntVT.isInteger())
    IntVT = EVT::getIntegerVT(*DAG.getContext(), IntVT.getSizeInBits());

  Value = DAG.getNode(ISD::ZERO_EXTEND, dl, IntVT, Value);
  if (NumBits > 8) {
    // Use a multiplication with 0x010101... to extend the input to the
    // required length.
    APInt Magic = APInt::getSplat(NumBits, APInt(8, 0x01));
    Value = DAG.getNode(ISD::MUL, dl, IntVT, Value,
                        DAG.getConstant(Magic, dl, IntVT));
  }

  if (VT != Value.getValueType() && !VT.isInteger())
    Value = DAG.getBitcast(VT.getScalarType(), Value);
  if (VT != Value.getValueType())
    Value = DAG.getSplatBuildVector(VT, dl, Value);

  return Value;
}

/// getMemsetStringVal - Similar to getMemsetValue. Except this is only
/// used when a memcpy is turned into a memset when the source is a constant
/// string ptr.
static SDValue getMemsetStringVal(EVT VT, const SDLoc &dl, SelectionDAG &DAG,
                                  const TargetLowering &TLI,
                                  const ConstantDataArraySlice &Slice) {
  // Handle vector with all elements zero.
  if (Slice.Array == nullptr) {
    if (VT.isInteger())
      return DAG.getConstant(0, dl, VT);
    return DAG.getNode(ISD::BITCAST, dl, VT,
                       DAG.getConstant(0, dl, VT.changeTypeToInteger()));
  }

  assert(!VT.isVector() && "Can't handle vector type here!");
  unsigned NumVTBits = VT.getSizeInBits();
  unsigned NumVTBytes = NumVTBits / 8;
  unsigned NumBytes = std::min(NumVTBytes, unsigned(Slice.Length));

  APInt Val(NumVTBits, 0);
  if (DAG.getDataLayout().isLittleEndian()) {
    for (unsigned i = 0; i != NumBytes; ++i)
      Val |= (uint64_t)(unsigned char)Slice[i] << i*8;
  } else {
    for (unsigned i = 0; i != NumBytes; ++i)
      Val |= (uint64_t)(unsigned char)Slice[i] << (NumVTBytes-i-1)*8;
  }

  // If the "cost" of materializing the integer immediate is less than the cost
  // of a load, then it is cost effective to turn the load into the immediate.
  Type *Ty = VT.getTypeForEVT(*DAG.getContext());
  if (TLI.shouldConvertConstantLoadToIntImm(Val, Ty))
    return DAG.getConstant(Val, dl, VT);
  return SDValue();
}

SDValue SelectionDAG::getMemBasePlusOffset(SDValue Base, TypeSize Offset,
                                           const SDLoc &DL,
                                           const SDNodeFlags Flags) {
  EVT VT = Base.getValueType();
  SDValue Index;

  if (Offset.isScalable())
    Index = getVScale(DL, Base.getValueType(),
                      APInt(Base.getValueSizeInBits().getFixedValue(),
                            Offset.getKnownMinValue()));
  else
    Index = getConstant(Offset.getFixedValue(), DL, VT);

  return getMemBasePlusOffset(Base, Index, DL, Flags);
}

SDValue SelectionDAG::getMemBasePlusOffset(SDValue Ptr, SDValue Offset,
                                           const SDLoc &DL,
                                           const SDNodeFlags Flags) {
  assert(Offset.getValueType().isInteger());
  EVT BasePtrVT = Ptr.getValueType();
  if (TLI->shouldPreservePtrArith(this->getMachineFunction().getFunction(),
                                  BasePtrVT))
    return getNode(ISD::PTRADD, DL, BasePtrVT, Ptr, Offset, Flags);
  return getNode(ISD::ADD, DL, BasePtrVT, Ptr, Offset, Flags);
}

/// Returns true if memcpy source is constant data.
static bool isMemSrcFromConstant(SDValue Src, ConstantDataArraySlice &Slice) {
  uint64_t SrcDelta = 0;
  GlobalAddressSDNode *G = nullptr;
  if (Src.getOpcode() == ISD::GlobalAddress)
    G = cast<GlobalAddressSDNode>(Src);
  else if (Src.getOpcode() == ISD::ADD &&
           Src.getOperand(0).getOpcode() == ISD::GlobalAddress &&
           Src.getOperand(1).getOpcode() == ISD::Constant) {
    G = cast<GlobalAddressSDNode>(Src.getOperand(0));
    SrcDelta = Src.getConstantOperandVal(1);
  }
  if (!G)
    return false;

  return getConstantDataArrayInfo(G->getGlobal(), Slice, 8,
                                  SrcDelta + G->getOffset());
}

static bool shouldLowerMemFuncForSize(const MachineFunction &MF,
                                      SelectionDAG &DAG) {
  // On Darwin, -Os means optimize for size without hurting performance, so
  // only really optimize for size when -Oz (MinSize) is used.
  if (MF.getTarget().getTargetTriple().isOSDarwin())
    return MF.getFunction().hasMinSize();
  return DAG.shouldOptForSize();
}

static void chainLoadsAndStoresForMemcpy(SelectionDAG &DAG, const SDLoc &dl,
                          SmallVector<SDValue, 32> &OutChains, unsigned From,
                          unsigned To, SmallVector<SDValue, 16> &OutLoadChains,
                          SmallVector<SDValue, 16> &OutStoreChains) {
  assert(OutLoadChains.size() && "Missing loads in memcpy inlining");
  assert(OutStoreChains.size() && "Missing stores in memcpy inlining");
  SmallVector<SDValue, 16> GluedLoadChains;
  for (unsigned i = From; i < To; ++i) {
    OutChains.push_back(OutLoadChains[i]);
    GluedLoadChains.push_back(OutLoadChains[i]);
  }

  // Chain for all loads.
  SDValue LoadToken = DAG.getNode(ISD::TokenFactor, dl, MVT::Other,
                                  GluedLoadChains);

  for (unsigned i = From; i < To; ++i) {
    StoreSDNode *ST = dyn_cast<StoreSDNode>(OutStoreChains[i]);
    SDValue NewStore = DAG.getTruncStore(LoadToken, dl, ST->getValue(),
                                  ST->getBasePtr(), ST->getMemoryVT(),
                                  ST->getMemOperand());
    OutChains.push_back(NewStore);
  }
}

static SDValue getMemcpyLoadsAndStores(
    SelectionDAG &DAG, const SDLoc &dl, SDValue Chain, SDValue Dst, SDValue Src,
    uint64_t Size, Align Alignment, bool isVol, bool AlwaysInline,
    MachinePointerInfo DstPtrInfo, MachinePointerInfo SrcPtrInfo,
    const AAMDNodes &AAInfo, BatchAAResults *BatchAA) {
  // Turn a memcpy of undef to nop.
  // FIXME: We need to honor volatile even is Src is undef.
  if (Src.isUndef())
    return Chain;

  // Expand memcpy to a series of load and store ops if the size operand falls
  // below a certain threshold.
  // TODO: In the AlwaysInline case, if the size is big then generate a loop
  // rather than maybe a humongous number of loads and stores.
  const TargetLowering &TLI = DAG.getTargetLoweringInfo();
  const DataLayout &DL = DAG.getDataLayout();
  LLVMContext &C = *DAG.getContext();
  std::vector<EVT> MemOps;
  bool DstAlignCanChange = false;
  MachineFunction &MF = DAG.getMachineFunction();
  MachineFrameInfo &MFI = MF.getFrameInfo();
  bool OptSize = shouldLowerMemFuncForSize(MF, DAG);
  FrameIndexSDNode *FI = dyn_cast<FrameIndexSDNode>(Dst);
  if (FI && !MFI.isFixedObjectIndex(FI->getIndex()))
    DstAlignCanChange = true;
  MaybeAlign SrcAlign = DAG.InferPtrAlign(Src);
  if (!SrcAlign || Alignment > *SrcAlign)
    SrcAlign = Alignment;
  assert(SrcAlign && "SrcAlign must be set");
  ConstantDataArraySlice Slice;
  // If marked as volatile, perform a copy even when marked as constant.
  bool CopyFromConstant = !isVol && isMemSrcFromConstant(Src, Slice);
  bool isZeroConstant = CopyFromConstant && Slice.Array == nullptr;
  unsigned Limit = AlwaysInline ? ~0U : TLI.getMaxStoresPerMemcpy(OptSize);
  const MemOp Op = isZeroConstant
                       ? MemOp::Set(Size, DstAlignCanChange, Alignment,
                                    /*IsZeroMemset*/ true, isVol)
                       : MemOp::Copy(Size, DstAlignCanChange, Alignment,
                                     *SrcAlign, isVol, CopyFromConstant);
  if (!TLI.findOptimalMemOpLowering(
          C, MemOps, Limit, Op, DstPtrInfo.getAddrSpace(),
          SrcPtrInfo.getAddrSpace(), MF.getFunction().getAttributes()))
    return SDValue();

  if (DstAlignCanChange) {
    Type *Ty = MemOps[0].getTypeForEVT(C);
    Align NewAlign = DL.getABITypeAlign(Ty);

    // Don't promote to an alignment that would require dynamic stack
    // realignment which may conflict with optimizations such as tail call
    // optimization.
    const TargetRegisterInfo *TRI = MF.getSubtarget().getRegisterInfo();
    if (!TRI->hasStackRealignment(MF))
      if (MaybeAlign StackAlign = DL.getStackAlignment())
        NewAlign = std::min(NewAlign, *StackAlign);

    if (NewAlign > Alignment) {
      // Give the stack frame object a larger alignment if needed.
      if (MFI.getObjectAlign(FI->getIndex()) < NewAlign)
        MFI.setObjectAlignment(FI->getIndex(), NewAlign);
      Alignment = NewAlign;
    }
  }

  // Prepare AAInfo for loads/stores after lowering this memcpy.
  AAMDNodes NewAAInfo = AAInfo;
  NewAAInfo.TBAA = NewAAInfo.TBAAStruct = nullptr;

  const Value *SrcVal = dyn_cast_if_present<const Value *>(SrcPtrInfo.V);
  bool isConstant =
      BatchAA && SrcVal &&
      BatchAA->pointsToConstantMemory(MemoryLocation(SrcVal, Size, AAInfo));

  MachineMemOperand::Flags MMOFlags =
      isVol ? MachineMemOperand::MOVolatile : MachineMemOperand::MONone;
  SmallVector<SDValue, 16> OutLoadChains;
  SmallVector<SDValue, 16> OutStoreChains;
  SmallVector<SDValue, 32> OutChains;
  unsigned NumMemOps = MemOps.size();
  uint64_t SrcOff = 0, DstOff = 0;
  for (unsigned i = 0; i != NumMemOps; ++i) {
    EVT VT = MemOps[i];
    unsigned VTSize = VT.getSizeInBits() / 8;
    SDValue Value, Store;

    if (VTSize > Size) {
      // Issuing an unaligned load / store pair  that overlaps with the previous
      // pair. Adjust the offset accordingly.
      assert(i == NumMemOps-1 && i != 0);
      SrcOff -= VTSize - Size;
      DstOff -= VTSize - Size;
    }

    if (CopyFromConstant &&
        (isZeroConstant || (VT.isInteger() && !VT.isVector()))) {
      // It's unlikely a store of a vector immediate can be done in a single
      // instruction. It would require a load from a constantpool first.
      // We only handle zero vectors here.
      // FIXME: Handle other cases where store of vector immediate is done in
      // a single instruction.
      ConstantDataArraySlice SubSlice;
      if (SrcOff < Slice.Length) {
        SubSlice = Slice;
        SubSlice.move(SrcOff);
      } else {
        // This is an out-of-bounds access and hence UB. Pretend we read zero.
        SubSlice.Array = nullptr;
        SubSlice.Offset = 0;
        SubSlice.Length = VTSize;
      }
      Value = getMemsetStringVal(VT, dl, DAG, TLI, SubSlice);
      if (Value.getNode()) {
        Store = DAG.getStore(
            Chain, dl, Value,
            DAG.getMemBasePlusOffset(Dst, TypeSize::getFixed(DstOff), dl),
            DstPtrInfo.getWithOffset(DstOff), Alignment, MMOFlags, NewAAInfo);
        OutChains.push_back(Store);
      }
    }

    if (!Store.getNode()) {
      // The type might not be legal for the target.  This should only happen
      // if the type is smaller than a legal type, as on PPC, so the right
      // thing to do is generate a LoadExt/StoreTrunc pair.  These simplify
      // to Load/Store if NVT==VT.
      // FIXME does the case above also need this?
      EVT NVT = TLI.getTypeToTransformTo(C, VT);
      assert(NVT.bitsGE(VT));

      bool isDereferenceable =
        SrcPtrInfo.getWithOffset(SrcOff).isDereferenceable(VTSize, C, DL);
      MachineMemOperand::Flags SrcMMOFlags = MMOFlags;
      if (isDereferenceable)
        SrcMMOFlags |= MachineMemOperand::MODereferenceable;
      if (isConstant)
        SrcMMOFlags |= MachineMemOperand::MOInvariant;

      Value = DAG.getExtLoad(
          ISD::EXTLOAD, dl, NVT, Chain,
          DAG.getMemBasePlusOffset(Src, TypeSize::getFixed(SrcOff), dl),
          SrcPtrInfo.getWithOffset(SrcOff), VT,
          commonAlignment(*SrcAlign, SrcOff), SrcMMOFlags, NewAAInfo);
      OutLoadChains.push_back(Value.getValue(1));

      Store = DAG.getTruncStore(
          Chain, dl, Value,
          DAG.getMemBasePlusOffset(Dst, TypeSize::getFixed(DstOff), dl),
          DstPtrInfo.getWithOffset(DstOff), VT, Alignment, MMOFlags, NewAAInfo);
      OutStoreChains.push_back(Store);
    }
    SrcOff += VTSize;
    DstOff += VTSize;
    Size -= VTSize;
  }

  unsigned GluedLdStLimit = MaxLdStGlue == 0 ?
                                TLI.getMaxGluedStoresPerMemcpy() : MaxLdStGlue;
  unsigned NumLdStInMemcpy = OutStoreChains.size();

  if (NumLdStInMemcpy) {
    // It may be that memcpy might be converted to memset if it's memcpy
    // of constants. In such a case, we won't have loads and stores, but
    // just stores. In the absence of loads, there is nothing to gang up.
    if ((GluedLdStLimit <= 1) || !EnableMemCpyDAGOpt) {
      // If target does not care, just leave as it.
      for (unsigned i = 0; i < NumLdStInMemcpy; ++i) {
        OutChains.push_back(OutLoadChains[i]);
        OutChains.push_back(OutStoreChains[i]);
      }
    } else {
      // Ld/St less than/equal limit set by target.
      if (NumLdStInMemcpy <= GluedLdStLimit) {
          chainLoadsAndStoresForMemcpy(DAG, dl, OutChains, 0,
                                        NumLdStInMemcpy, OutLoadChains,
                                        OutStoreChains);
      } else {
        unsigned NumberLdChain =  NumLdStInMemcpy / GluedLdStLimit;
        unsigned RemainingLdStInMemcpy = NumLdStInMemcpy % GluedLdStLimit;
        unsigned GlueIter = 0;

        for (unsigned cnt = 0; cnt < NumberLdChain; ++cnt) {
          unsigned IndexFrom = NumLdStInMemcpy - GlueIter - GluedLdStLimit;
          unsigned IndexTo   = NumLdStInMemcpy - GlueIter;

          chainLoadsAndStoresForMemcpy(DAG, dl, OutChains, IndexFrom, IndexTo,
                                       OutLoadChains, OutStoreChains);
          GlueIter += GluedLdStLimit;
        }

        // Residual ld/st.
        if (RemainingLdStInMemcpy) {
          chainLoadsAndStoresForMemcpy(DAG, dl, OutChains, 0,
                                        RemainingLdStInMemcpy, OutLoadChains,
                                        OutStoreChains);
        }
      }
    }
  }
  return DAG.getNode(ISD::TokenFactor, dl, MVT::Other, OutChains);
}

static SDValue getMemmoveLoadsAndStores(SelectionDAG &DAG, const SDLoc &dl,
                                        SDValue Chain, SDValue Dst, SDValue Src,
                                        uint64_t Size, Align Alignment,
                                        bool isVol, bool AlwaysInline,
                                        MachinePointerInfo DstPtrInfo,
                                        MachinePointerInfo SrcPtrInfo,
                                        const AAMDNodes &AAInfo) {
  // Turn a memmove of undef to nop.
  // FIXME: We need to honor volatile even is Src is undef.
  if (Src.isUndef())
    return Chain;

  // Expand memmove to a series of load and store ops if the size operand falls
  // below a certain threshold.
  const TargetLowering &TLI = DAG.getTargetLoweringInfo();
  const DataLayout &DL = DAG.getDataLayout();
  LLVMContext &C = *DAG.getContext();
  std::vector<EVT> MemOps;
  bool DstAlignCanChange = false;
  MachineFunction &MF = DAG.getMachineFunction();
  MachineFrameInfo &MFI = MF.getFrameInfo();
  bool OptSize = shouldLowerMemFuncForSize(MF, DAG);
  FrameIndexSDNode *FI = dyn_cast<FrameIndexSDNode>(Dst);
  if (FI && !MFI.isFixedObjectIndex(FI->getIndex()))
    DstAlignCanChange = true;
  MaybeAlign SrcAlign = DAG.InferPtrAlign(Src);
  if (!SrcAlign || Alignment > *SrcAlign)
    SrcAlign = Alignment;
  assert(SrcAlign && "SrcAlign must be set");
  unsigned Limit = AlwaysInline ? ~0U : TLI.getMaxStoresPerMemmove(OptSize);
  if (!TLI.findOptimalMemOpLowering(
          C, MemOps, Limit,
          MemOp::Copy(Size, DstAlignCanChange, Alignment, *SrcAlign,
                      /*IsVolatile*/ true),
          DstPtrInfo.getAddrSpace(), SrcPtrInfo.getAddrSpace(),
          MF.getFunction().getAttributes()))
    return SDValue();

  if (DstAlignCanChange) {
    Type *Ty = MemOps[0].getTypeForEVT(C);
    Align NewAlign = DL.getABITypeAlign(Ty);

    // Don't promote to an alignment that would require dynamic stack
    // realignment which may conflict with optimizations such as tail call
    // optimization.
    const TargetRegisterInfo *TRI = MF.getSubtarget().getRegisterInfo();
    if (!TRI->hasStackRealignment(MF))
      if (MaybeAlign StackAlign = DL.getStackAlignment())
        NewAlign = std::min(NewAlign, *StackAlign);

    if (NewAlign > Alignment) {
      // Give the stack frame object a larger alignment if needed.
      if (MFI.getObjectAlign(FI->getIndex()) < NewAlign)
        MFI.setObjectAlignment(FI->getIndex(), NewAlign);
      Alignment = NewAlign;
    }
  }

  // Prepare AAInfo for loads/stores after lowering this memmove.
  AAMDNodes NewAAInfo = AAInfo;
  NewAAInfo.TBAA = NewAAInfo.TBAAStruct = nullptr;

  MachineMemOperand::Flags MMOFlags =
      isVol ? MachineMemOperand::MOVolatile : MachineMemOperand::MONone;
  uint64_t SrcOff = 0, DstOff = 0;
  SmallVector<SDValue, 8> LoadValues;
  SmallVector<SDValue, 8> LoadChains;
  SmallVector<SDValue, 8> OutChains;
  unsigned NumMemOps = MemOps.size();
  for (unsigned i = 0; i < NumMemOps; i++) {
    EVT VT = MemOps[i];
    unsigned VTSize = VT.getSizeInBits() / 8;
    SDValue Value;

    bool isDereferenceable =
      SrcPtrInfo.getWithOffset(SrcOff).isDereferenceable(VTSize, C, DL);
    MachineMemOperand::Flags SrcMMOFlags = MMOFlags;
    if (isDereferenceable)
      SrcMMOFlags |= MachineMemOperand::MODereferenceable;

    Value = DAG.getLoad(
        VT, dl, Chain,
        DAG.getMemBasePlusOffset(Src, TypeSize::getFixed(SrcOff), dl),
        SrcPtrInfo.getWithOffset(SrcOff), *SrcAlign, SrcMMOFlags, NewAAInfo);
    LoadValues.push_back(Value);
    LoadChains.push_back(Value.getValue(1));
    SrcOff += VTSize;
  }
  Chain = DAG.getNode(ISD::TokenFactor, dl, MVT::Other, LoadChains);
  OutChains.clear();
  for (unsigned i = 0; i < NumMemOps; i++) {
    EVT VT = MemOps[i];
    unsigned VTSize = VT.getSizeInBits() / 8;
    SDValue Store;

    Store = DAG.getStore(
        Chain, dl, LoadValues[i],
        DAG.getMemBasePlusOffset(Dst, TypeSize::getFixed(DstOff), dl),
        DstPtrInfo.getWithOffset(DstOff), Alignment, MMOFlags, NewAAInfo);
    OutChains.push_back(Store);
    DstOff += VTSize;
  }

  return DAG.getNode(ISD::TokenFactor, dl, MVT::Other, OutChains);
}

/// Lower the call to 'memset' intrinsic function into a series of store
/// operations.
///
/// \param DAG Selection DAG where lowered code is placed.
/// \param dl Link to corresponding IR location.
/// \param Chain Control flow dependency.
/// \param Dst Pointer to destination memory location.
/// \param Src Value of byte to write into the memory.
/// \param Size Number of bytes to write.
/// \param Alignment Alignment of the destination in bytes.
/// \param isVol True if destination is volatile.
/// \param AlwaysInline Makes sure no function call is generated.
/// \param DstPtrInfo IR information on the memory pointer.
/// \returns New head in the control flow, if lowering was successful, empty
/// SDValue otherwise.
///
/// The function tries to replace 'llvm.memset' intrinsic with several store
/// operations and value calculation code. This is usually profitable for small
/// memory size or when the semantic requires inlining.
static SDValue getMemsetStores(SelectionDAG &DAG, const SDLoc &dl,
                               SDValue Chain, SDValue Dst, SDValue Src,
                               uint64_t Size, Align Alignment, bool isVol,
                               bool AlwaysInline, MachinePointerInfo DstPtrInfo,
                               const AAMDNodes &AAInfo) {
  // Turn a memset of undef to nop.
  // FIXME: We need to honor volatile even is Src is undef.
  if (Src.isUndef())
    return Chain;

  // Expand memset to a series of load/store ops if the size operand
  // falls below a certain threshold.
  const TargetLowering &TLI = DAG.getTargetLoweringInfo();
  std::vector<EVT> MemOps;
  bool DstAlignCanChange = false;
  LLVMContext &C = *DAG.getContext();
  MachineFunction &MF = DAG.getMachineFunction();
  MachineFrameInfo &MFI = MF.getFrameInfo();
  bool OptSize = shouldLowerMemFuncForSize(MF, DAG);
  FrameIndexSDNode *FI = dyn_cast<FrameIndexSDNode>(Dst);
  if (FI && !MFI.isFixedObjectIndex(FI->getIndex()))
    DstAlignCanChange = true;
  bool IsZeroVal = isNullConstant(Src);
  unsigned Limit = AlwaysInline ? ~0 : TLI.getMaxStoresPerMemset(OptSize);

  if (!TLI.findOptimalMemOpLowering(
          C, MemOps, Limit,
          MemOp::Set(Size, DstAlignCanChange, Alignment, IsZeroVal, isVol),
          DstPtrInfo.getAddrSpace(), ~0u, MF.getFunction().getAttributes()))
    return SDValue();

  if (DstAlignCanChange) {
    Type *Ty = MemOps[0].getTypeForEVT(*DAG.getContext());
    const DataLayout &DL = DAG.getDataLayout();
    Align NewAlign = DL.getABITypeAlign(Ty);

    // Don't promote to an alignment that would require dynamic stack
    // realignment which may conflict with optimizations such as tail call
    // optimization.
    const TargetRegisterInfo *TRI = MF.getSubtarget().getRegisterInfo();
    if (!TRI->hasStackRealignment(MF))
      if (MaybeAlign StackAlign = DL.getStackAlignment())
        NewAlign = std::min(NewAlign, *StackAlign);

    if (NewAlign > Alignment) {
      // Give the stack frame object a larger alignment if needed.
      if (MFI.getObjectAlign(FI->getIndex()) < NewAlign)
        MFI.setObjectAlignment(FI->getIndex(), NewAlign);
      Alignment = NewAlign;
    }
  }

  SmallVector<SDValue, 8> OutChains;
  uint64_t DstOff = 0;
  unsigned NumMemOps = MemOps.size();

  // Find the largest store and generate the bit pattern for it.
  EVT LargestVT = MemOps[0];
  for (unsigned i = 1; i < NumMemOps; i++)
    if (MemOps[i].bitsGT(LargestVT))
      LargestVT = MemOps[i];
  SDValue MemSetValue = getMemsetValue(Src, LargestVT, DAG, dl);

  // Prepare AAInfo for loads/stores after lowering this memset.
  AAMDNodes NewAAInfo = AAInfo;
  NewAAInfo.TBAA = NewAAInfo.TBAAStruct = nullptr;

  for (unsigned i = 0; i < NumMemOps; i++) {
    EVT VT = MemOps[i];
    unsigned VTSize = VT.getSizeInBits() / 8;
    if (VTSize > Size) {
      // Issuing an unaligned load / store pair  that overlaps with the previous
      // pair. Adjust the offset accordingly.
      assert(i == NumMemOps-1 && i != 0);
      DstOff -= VTSize - Size;
    }

    // If this store is smaller than the largest store see whether we can get
    // the smaller value for free with a truncate or extract vector element and
    // then store.
    SDValue Value = MemSetValue;
    if (VT.bitsLT(LargestVT)) {
      unsigned Index;
      unsigned NElts = LargestVT.getSizeInBits() / VT.getSizeInBits();
      EVT SVT = EVT::getVectorVT(*DAG.getContext(), VT.getScalarType(), NElts);
      if (!LargestVT.isVector() && !VT.isVector() &&
          TLI.isTruncateFree(LargestVT, VT))
        Value = DAG.getNode(ISD::TRUNCATE, dl, VT, MemSetValue);
      else if (LargestVT.isVector() && !VT.isVector() &&
               TLI.shallExtractConstSplatVectorElementToStore(
                   LargestVT.getTypeForEVT(*DAG.getContext()),
                   VT.getSizeInBits(), Index) &&
               TLI.isTypeLegal(SVT) &&
               LargestVT.getSizeInBits() == SVT.getSizeInBits()) {
        // Target which can combine store(extractelement VectorTy, Idx) can get
        // the smaller value for free.
        SDValue TailValue = DAG.getNode(ISD::BITCAST, dl, SVT, MemSetValue);
        Value = DAG.getExtractVectorElt(dl, VT, TailValue, Index);
      } else
        Value = getMemsetValue(Src, VT, DAG, dl);
    }
    assert(Value.getValueType() == VT && "Value with wrong type.");
    SDValue Store = DAG.getStore(
        Chain, dl, Value,
        DAG.getMemBasePlusOffset(Dst, TypeSize::getFixed(DstOff), dl),
        DstPtrInfo.getWithOffset(DstOff), Alignment,
        isVol ? MachineMemOperand::MOVolatile : MachineMemOperand::MONone,
        NewAAInfo);
    OutChains.push_back(Store);
    DstOff += VT.getSizeInBits() / 8;
    Size -= VTSize;
  }

  return DAG.getNode(ISD::TokenFactor, dl, MVT::Other, OutChains);
}

static void checkAddrSpaceIsValidForLibcall(const TargetLowering *TLI,
                                            unsigned AS) {
  // Lowering memcpy / memset / memmove intrinsics to calls is only valid if all
  // pointer operands can be losslessly bitcasted to pointers of address space 0
  if (AS != 0 && !TLI->getTargetMachine().isNoopAddrSpaceCast(AS, 0)) {
    report_fatal_error("cannot lower memory intrinsic in address space " +
                       Twine(AS));
  }
}

SDValue SelectionDAG::getMemcpy(
    SDValue Chain, const SDLoc &dl, SDValue Dst, SDValue Src, SDValue Size,
    Align Alignment, bool isVol, bool AlwaysInline, const CallInst *CI,
    std::optional<bool> OverrideTailCall, MachinePointerInfo DstPtrInfo,
    MachinePointerInfo SrcPtrInfo, const AAMDNodes &AAInfo,
    BatchAAResults *BatchAA) {
  // Check to see if we should lower the memcpy to loads and stores first.
  // For cases within the target-specified limits, this is the best choice.
  ConstantSDNode *ConstantSize = dyn_cast<ConstantSDNode>(Size);
  if (ConstantSize) {
    // Memcpy with size zero? Just return the original chain.
    if (ConstantSize->isZero())
      return Chain;

    SDValue Result = getMemcpyLoadsAndStores(
        *this, dl, Chain, Dst, Src, ConstantSize->getZExtValue(), Alignment,
        isVol, false, DstPtrInfo, SrcPtrInfo, AAInfo, BatchAA);
    if (Result.getNode())
      return Result;
  }

  // Then check to see if we should lower the memcpy with target-specific
  // code. If the target chooses to do this, this is the next best.
  if (TSI) {
    SDValue Result = TSI->EmitTargetCodeForMemcpy(
        *this, dl, Chain, Dst, Src, Size, Alignment, isVol, AlwaysInline,
        DstPtrInfo, SrcPtrInfo);
    if (Result.getNode())
      return Result;
  }

  // If we really need inline code and the target declined to provide it,
  // use a (potentially long) sequence of loads and stores.
  if (AlwaysInline) {
    assert(ConstantSize && "AlwaysInline requires a constant size!");
    return getMemcpyLoadsAndStores(
        *this, dl, Chain, Dst, Src, ConstantSize->getZExtValue(), Alignment,
        isVol, true, DstPtrInfo, SrcPtrInfo, AAInfo, BatchAA);
  }

  checkAddrSpaceIsValidForLibcall(TLI, DstPtrInfo.getAddrSpace());
  checkAddrSpaceIsValidForLibcall(TLI, SrcPtrInfo.getAddrSpace());

  // FIXME: If the memcpy is volatile (isVol), lowering it to a plain libc
  // memcpy is not guaranteed to be safe. libc memcpys aren't required to
  // respect volatile, so they may do things like read or write memory
  // beyond the given memory regions. But fixing this isn't easy, and most
  // people don't care.

  // Emit a library call.
  TargetLowering::ArgListTy Args;
  TargetLowering::ArgListEntry Entry;
  Entry.Ty = PointerType::getUnqual(*getContext());
  Entry.Node = Dst; Args.push_back(Entry);
  Entry.Node = Src; Args.push_back(Entry);

  Entry.Ty = getDataLayout().getIntPtrType(*getContext());
  Entry.Node = Size; Args.push_back(Entry);
  // FIXME: pass in SDLoc
  TargetLowering::CallLoweringInfo CLI(*this);
  bool IsTailCall = false;
  const char *MemCpyName = TLI->getMemcpyName();

  if (OverrideTailCall.has_value()) {
    IsTailCall = *OverrideTailCall;
  } else {
    bool LowersToMemcpy = StringRef(MemCpyName) == StringRef("memcpy");
    bool ReturnsFirstArg = CI && funcReturnsFirstArgOfCall(*CI);
    IsTailCall = CI && CI->isTailCall() &&
                 isInTailCallPosition(*CI, getTarget(),
                                      ReturnsFirstArg && LowersToMemcpy);
  }

  CLI.setDebugLoc(dl)
      .setChain(Chain)
      .setLibCallee(
          TLI->getLibcallCallingConv(RTLIB::MEMCPY),
          Dst.getValueType().getTypeForEVT(*getContext()),
          getExternalSymbol(MemCpyName, TLI->getPointerTy(getDataLayout())),
          std::move(Args))
      .setDiscardResult()
      .setTailCall(IsTailCall);

  std::pair<SDValue,SDValue> CallResult = TLI->LowerCallTo(CLI);
  return CallResult.second;
}

SDValue SelectionDAG::getAtomicMemcpy(SDValue Chain, const SDLoc &dl,
                                      SDValue Dst, SDValue Src, SDValue Size,
                                      Type *SizeTy, unsigned ElemSz,
                                      bool isTailCall,
                                      MachinePointerInfo DstPtrInfo,
                                      MachinePointerInfo SrcPtrInfo) {
  // Emit a library call.
  TargetLowering::ArgListTy Args;
  TargetLowering::ArgListEntry Entry;
  Entry.Ty = getDataLayout().getIntPtrType(*getContext());
  Entry.Node = Dst;
  Args.push_back(Entry);

  Entry.Node = Src;
  Args.push_back(Entry);

  Entry.Ty = SizeTy;
  Entry.Node = Size;
  Args.push_back(Entry);

  RTLIB::Libcall LibraryCall =
      RTLIB::getMEMCPY_ELEMENT_UNORDERED_ATOMIC(ElemSz);
  if (LibraryCall == RTLIB::UNKNOWN_LIBCALL)
    report_fatal_error("Unsupported element size");

  TargetLowering::CallLoweringInfo CLI(*this);
  CLI.setDebugLoc(dl)
      .setChain(Chain)
      .setLibCallee(TLI->getLibcallCallingConv(LibraryCall),
                    Type::getVoidTy(*getContext()),
                    getExternalSymbol(TLI->getLibcallName(LibraryCall),
                                      TLI->getPointerTy(getDataLayout())),
                    std::move(Args))
      .setDiscardResult()
      .setTailCall(isTailCall);

  std::pair<SDValue, SDValue> CallResult = TLI->LowerCallTo(CLI);
  return CallResult.second;
}

SDValue SelectionDAG::getMemmove(SDValue Chain, const SDLoc &dl, SDValue Dst,
                                 SDValue Src, SDValue Size, Align Alignment,
                                 bool isVol, const CallInst *CI,
                                 std::optional<bool> OverrideTailCall,
                                 MachinePointerInfo DstPtrInfo,
                                 MachinePointerInfo SrcPtrInfo,
                                 const AAMDNodes &AAInfo,
                                 BatchAAResults *BatchAA) {
  // Check to see if we should lower the memmove to loads and stores first.
  // For cases within the target-specified limits, this is the best choice.
  ConstantSDNode *ConstantSize = dyn_cast<ConstantSDNode>(Size);
  if (ConstantSize) {
    // Memmove with size zero? Just return the original chain.
    if (ConstantSize->isZero())
      return Chain;

    SDValue Result = getMemmoveLoadsAndStores(
        *this, dl, Chain, Dst, Src, ConstantSize->getZExtValue(), Alignment,
        isVol, false, DstPtrInfo, SrcPtrInfo, AAInfo);
    if (Result.getNode())
      return Result;
  }

  // Then check to see if we should lower the memmove with target-specific
  // code. If the target chooses to do this, this is the next best.
  if (TSI) {
    SDValue Result =
        TSI->EmitTargetCodeForMemmove(*this, dl, Chain, Dst, Src, Size,
                                      Alignment, isVol, DstPtrInfo, SrcPtrInfo);
    if (Result.getNode())
      return Result;
  }

  checkAddrSpaceIsValidForLibcall(TLI, DstPtrInfo.getAddrSpace());
  checkAddrSpaceIsValidForLibcall(TLI, SrcPtrInfo.getAddrSpace());

  // FIXME: If the memmove is volatile, lowering it to plain libc memmove may
  // not be safe.  See memcpy above for more details.

  // Emit a library call.
  TargetLowering::ArgListTy Args;
  TargetLowering::ArgListEntry Entry;
  Entry.Ty = PointerType::getUnqual(*getContext());
  Entry.Node = Dst; Args.push_back(Entry);
  Entry.Node = Src; Args.push_back(Entry);

  Entry.Ty = getDataLayout().getIntPtrType(*getContext());
  Entry.Node = Size; Args.push_back(Entry);
  // FIXME:  pass in SDLoc
  TargetLowering::CallLoweringInfo CLI(*this);

  bool IsTailCall = false;
  if (OverrideTailCall.has_value()) {
    IsTailCall = *OverrideTailCall;
  } else {
    bool LowersToMemmove =
        TLI->getLibcallName(RTLIB::MEMMOVE) == StringRef("memmove");
    bool ReturnsFirstArg = CI && funcReturnsFirstArgOfCall(*CI);
    IsTailCall = CI && CI->isTailCall() &&
                 isInTailCallPosition(*CI, getTarget(),
                                      ReturnsFirstArg && LowersToMemmove);
  }

  CLI.setDebugLoc(dl)
      .setChain(Chain)
      .setLibCallee(TLI->getLibcallCallingConv(RTLIB::MEMMOVE),
                    Dst.getValueType().getTypeForEVT(*getContext()),
                    getExternalSymbol(TLI->getLibcallName(RTLIB::MEMMOVE),
                                      TLI->getPointerTy(getDataLayout())),
                    std::move(Args))
      .setDiscardResult()
      .setTailCall(IsTailCall);

  std::pair<SDValue,SDValue> CallResult = TLI->LowerCallTo(CLI);
  return CallResult.second;
}

SDValue SelectionDAG::getAtomicMemmove(SDValue Chain, const SDLoc &dl,
                                       SDValue Dst, SDValue Src, SDValue Size,
                                       Type *SizeTy, unsigned ElemSz,
                                       bool isTailCall,
                                       MachinePointerInfo DstPtrInfo,
                                       MachinePointerInfo SrcPtrInfo) {
  // Emit a library call.
  TargetLowering::ArgListTy Args;
  TargetLowering::ArgListEntry Entry;
  Entry.Ty = getDataLayout().getIntPtrType(*getContext());
  Entry.Node = Dst;
  Args.push_back(Entry);

  Entry.Node = Src;
  Args.push_back(Entry);

  Entry.Ty = SizeTy;
  Entry.Node = Size;
  Args.push_back(Entry);

  RTLIB::Libcall LibraryCall =
      RTLIB::getMEMMOVE_ELEMENT_UNORDERED_ATOMIC(ElemSz);
  if (LibraryCall == RTLIB::UNKNOWN_LIBCALL)
    report_fatal_error("Unsupported element size");

  TargetLowering::CallLoweringInfo CLI(*this);
  CLI.setDebugLoc(dl)
      .setChain(Chain)
      .setLibCallee(TLI->getLibcallCallingConv(LibraryCall),
                    Type::getVoidTy(*getContext()),
                    getExternalSymbol(TLI->getLibcallName(LibraryCall),
                                      TLI->getPointerTy(getDataLayout())),
                    std::move(Args))
      .setDiscardResult()
      .setTailCall(isTailCall);

  std::pair<SDValue, SDValue> CallResult = TLI->LowerCallTo(CLI);
  return CallResult.second;
}

SDValue SelectionDAG::getMemset(SDValue Chain, const SDLoc &dl, SDValue Dst,
                                SDValue Src, SDValue Size, Align Alignment,
                                bool isVol, bool AlwaysInline,
                                const CallInst *CI,
                                MachinePointerInfo DstPtrInfo,
                                const AAMDNodes &AAInfo) {
  // Check to see if we should lower the memset to stores first.
  // For cases within the target-specified limits, this is the best choice.
  ConstantSDNode *ConstantSize = dyn_cast<ConstantSDNode>(Size);
  if (ConstantSize) {
    // Memset with size zero? Just return the original chain.
    if (ConstantSize->isZero())
      return Chain;

    SDValue Result = getMemsetStores(*this, dl, Chain, Dst, Src,
                                     ConstantSize->getZExtValue(), Alignment,
                                     isVol, false, DstPtrInfo, AAInfo);

    if (Result.getNode())
      return Result;
  }

  // Then check to see if we should lower the memset with target-specific
  // code. If the target chooses to do this, this is the next best.
  if (TSI) {
    SDValue Result = TSI->EmitTargetCodeForMemset(
        *this, dl, Chain, Dst, Src, Size, Alignment, isVol, AlwaysInline, DstPtrInfo);
    if (Result.getNode())
      return Result;
  }

  // If we really need inline code and the target declined to provide it,
  // use a (potentially long) sequence of loads and stores.
  if (AlwaysInline) {
    assert(ConstantSize && "AlwaysInline requires a constant size!");
    SDValue Result = getMemsetStores(*this, dl, Chain, Dst, Src,
                                     ConstantSize->getZExtValue(), Alignment,
                                     isVol, true, DstPtrInfo, AAInfo);
    assert(Result &&
           "getMemsetStores must return a valid sequence when AlwaysInline");
    return Result;
  }

  checkAddrSpaceIsValidForLibcall(TLI, DstPtrInfo.getAddrSpace());

  // Emit a library call.
  auto &Ctx = *getContext();
  const auto& DL = getDataLayout();

  TargetLowering::CallLoweringInfo CLI(*this);
  // FIXME: pass in SDLoc
  CLI.setDebugLoc(dl).setChain(Chain);

  const char *BzeroName = getTargetLoweringInfo().getLibcallName(RTLIB::BZERO);

  // Helper function to create an Entry from Node and Type.
  const auto CreateEntry = [](SDValue Node, Type *Ty) {
    TargetLowering::ArgListEntry Entry;
    Entry.Node = Node;
    Entry.Ty = Ty;
    return Entry;
  };

  bool UseBZero = isNullConstant(Src) && BzeroName;
  // If zeroing out and bzero is present, use it.
  if (UseBZero) {
    TargetLowering::ArgListTy Args;
    Args.push_back(CreateEntry(Dst, PointerType::getUnqual(Ctx)));
    Args.push_back(CreateEntry(Size, DL.getIntPtrType(Ctx)));
    CLI.setLibCallee(
        TLI->getLibcallCallingConv(RTLIB::BZERO), Type::getVoidTy(Ctx),
        getExternalSymbol(BzeroName, TLI->getPointerTy(DL)), std::move(Args));
  } else {
    TargetLowering::ArgListTy Args;
    Args.push_back(CreateEntry(Dst, PointerType::getUnqual(Ctx)));
    Args.push_back(CreateEntry(Src, Src.getValueType().getTypeForEVT(Ctx)));
    Args.push_back(CreateEntry(Size, DL.getIntPtrType(Ctx)));
    CLI.setLibCallee(TLI->getLibcallCallingConv(RTLIB::MEMSET),
                     Dst.getValueType().getTypeForEVT(Ctx),
                     getExternalSymbol(TLI->getLibcallName(RTLIB::MEMSET),
                                       TLI->getPointerTy(DL)),
                     std::move(Args));
  }
  bool LowersToMemset =
      TLI->getLibcallName(RTLIB::MEMSET) == StringRef("memset");
  // If we're going to use bzero, make sure not to tail call unless the
  // subsequent return doesn't need a value, as bzero doesn't return the first
  // arg unlike memset.
  bool ReturnsFirstArg = CI && funcReturnsFirstArgOfCall(*CI) && !UseBZero;
  bool IsTailCall =
      CI && CI->isTailCall() &&
      isInTailCallPosition(*CI, getTarget(), ReturnsFirstArg && LowersToMemset);
  CLI.setDiscardResult().setTailCall(IsTailCall);

  std::pair<SDValue, SDValue> CallResult = TLI->LowerCallTo(CLI);
  return CallResult.second;
}

SDValue SelectionDAG::getAtomicMemset(SDValue Chain, const SDLoc &dl,
                                      SDValue Dst, SDValue Value, SDValue Size,
                                      Type *SizeTy, unsigned ElemSz,
                                      bool isTailCall,
                                      MachinePointerInfo DstPtrInfo) {
  // Emit a library call.
  TargetLowering::ArgListTy Args;
  TargetLowering::ArgListEntry Entry;
  Entry.Ty = getDataLayout().getIntPtrType(*getContext());
  Entry.Node = Dst;
  Args.push_back(Entry);

  Entry.Ty = Type::getInt8Ty(*getContext());
  Entry.Node = Value;
  Args.push_back(Entry);

  Entry.Ty = SizeTy;
  Entry.Node = Size;
  Args.push_back(Entry);

  RTLIB::Libcall LibraryCall =
      RTLIB::getMEMSET_ELEMENT_UNORDERED_ATOMIC(ElemSz);
  if (LibraryCall == RTLIB::UNKNOWN_LIBCALL)
    report_fatal_error("Unsupported element size");

  TargetLowering::CallLoweringInfo CLI(*this);
  CLI.setDebugLoc(dl)
      .setChain(Chain)
      .setLibCallee(TLI->getLibcallCallingConv(LibraryCall),
                    Type::getVoidTy(*getContext()),
                    getExternalSymbol(TLI->getLibcallName(LibraryCall),
                                      TLI->getPointerTy(getDataLayout())),
                    std::move(Args))
      .setDiscardResult()
      .setTailCall(isTailCall);

  std::pair<SDValue, SDValue> CallResult = TLI->LowerCallTo(CLI);
  return CallResult.second;
}

SDValue SelectionDAG::getAtomic(unsigned Opcode, const SDLoc &dl, EVT MemVT,
                                SDVTList VTList, ArrayRef<SDValue> Ops,
                                MachineMemOperand *MMO,
                                ISD::LoadExtType ExtType) {
  FoldingSetNodeID ID;
  AddNodeIDNode(ID, Opcode, VTList, Ops);
  ID.AddInteger(MemVT.getRawBits());
  ID.AddInteger(getSyntheticNodeSubclassData<AtomicSDNode>(
      dl.getIROrder(), Opcode, VTList, MemVT, MMO, ExtType));
  ID.AddInteger(MMO->getPointerInfo().getAddrSpace());
  ID.AddInteger(MMO->getFlags());
  void* IP = nullptr;
  if (auto *E = cast_or_null<AtomicSDNode>(FindNodeOrInsertPos(ID, dl, IP))) {
    E->refineAlignment(MMO);
    E->refineRanges(MMO);
    return SDValue(E, 0);
  }

  auto *N = newSDNode<AtomicSDNode>(dl.getIROrder(), dl.getDebugLoc(), Opcode,
                                    VTList, MemVT, MMO, ExtType);
  createOperands(N, Ops);

  CSEMap.InsertNode(N, IP);
  InsertNode(N);
  SDValue V(N, 0);
  NewSDValueDbgMsg(V, "Creating new node: ", this);
  return V;
}

SDValue SelectionDAG::getAtomicCmpSwap(unsigned Opcode, const SDLoc &dl,
                                       EVT MemVT, SDVTList VTs, SDValue Chain,
                                       SDValue Ptr, SDValue Cmp, SDValue Swp,
                                       MachineMemOperand *MMO) {
  assert(Opcode == ISD::ATOMIC_CMP_SWAP ||
         Opcode == ISD::ATOMIC_CMP_SWAP_WITH_SUCCESS);
  assert(Cmp.getValueType() == Swp.getValueType() && "Invalid Atomic Op Types");

  SDValue Ops[] = {Chain, Ptr, Cmp, Swp};
  return getAtomic(Opcode, dl, MemVT, VTs, Ops, MMO);
}

SDValue SelectionDAG::getAtomic(unsigned Opcode, const SDLoc &dl, EVT MemVT,
                                SDValue Chain, SDValue Ptr, SDValue Val,
                                MachineMemOperand *MMO) {
  assert((Opcode == ISD::ATOMIC_LOAD_ADD || Opcode == ISD::ATOMIC_LOAD_SUB ||
          Opcode == ISD::ATOMIC_LOAD_AND || Opcode == ISD::ATOMIC_LOAD_CLR ||
          Opcode == ISD::ATOMIC_LOAD_OR || Opcode == ISD::ATOMIC_LOAD_XOR ||
          Opcode == ISD::ATOMIC_LOAD_NAND || Opcode == ISD::ATOMIC_LOAD_MIN ||
          Opcode == ISD::ATOMIC_LOAD_MAX || Opcode == ISD::ATOMIC_LOAD_UMIN ||
          Opcode == ISD::ATOMIC_LOAD_UMAX || Opcode == ISD::ATOMIC_LOAD_FADD ||
          Opcode == ISD::ATOMIC_LOAD_FSUB || Opcode == ISD::ATOMIC_LOAD_FMAX ||
          Opcode == ISD::ATOMIC_LOAD_FMIN ||
          Opcode == ISD::ATOMIC_LOAD_FMINIMUM ||
          Opcode == ISD::ATOMIC_LOAD_FMAXIMUM ||
          Opcode == ISD::ATOMIC_LOAD_UINC_WRAP ||
          Opcode == ISD::ATOMIC_LOAD_UDEC_WRAP ||
          Opcode == ISD::ATOMIC_LOAD_USUB_COND ||
          Opcode == ISD::ATOMIC_LOAD_USUB_SAT || Opcode == ISD::ATOMIC_SWAP ||
          Opcode == ISD::ATOMIC_STORE) &&
         "Invalid Atomic Op");

  EVT VT = Val.getValueType();

  SDVTList VTs = Opcode == ISD::ATOMIC_STORE ? getVTList(MVT::Other) :
                                               getVTList(VT, MVT::Other);
  SDValue Ops[] = {Chain, Ptr, Val};
  return getAtomic(Opcode, dl, MemVT, VTs, Ops, MMO);
}

SDValue SelectionDAG::getAtomicLoad(ISD::LoadExtType ExtType, const SDLoc &dl,
                                    EVT MemVT, EVT VT, SDValue Chain,
                                    SDValue Ptr, MachineMemOperand *MMO) {
  SDVTList VTs = getVTList(VT, MVT::Other);
  SDValue Ops[] = {Chain, Ptr};
  return getAtomic(ISD::ATOMIC_LOAD, dl, MemVT, VTs, Ops, MMO, ExtType);
}

/// getMergeValues - Create a MERGE_VALUES node from the given operands.
SDValue SelectionDAG::getMergeValues(ArrayRef<SDValue> Ops, const SDLoc &dl) {
  if (Ops.size() == 1)
    return Ops[0];

  SmallVector<EVT, 4> VTs;
  VTs.reserve(Ops.size());
  for (const SDValue &Op : Ops)
    VTs.push_back(Op.getValueType());
  return getNode(ISD::MERGE_VALUES, dl, getVTList(VTs), Ops);
}

SDValue SelectionDAG::getMemIntrinsicNode(
    unsigned Opcode, const SDLoc &dl, SDVTList VTList, ArrayRef<SDValue> Ops,
    EVT MemVT, MachinePointerInfo PtrInfo, Align Alignment,
    MachineMemOperand::Flags Flags, LocationSize Size,
    const AAMDNodes &AAInfo) {
  if (Size.hasValue() && !Size.getValue())
    Size = LocationSize::precise(MemVT.getStoreSize());

  MachineFunction &MF = getMachineFunction();
  MachineMemOperand *MMO =
      MF.getMachineMemOperand(PtrInfo, Flags, Size, Alignment, AAInfo);

  return getMemIntrinsicNode(Opcode, dl, VTList, Ops, MemVT, MMO);
}

SDValue SelectionDAG::getMemIntrinsicNode(unsigned Opcode, const SDLoc &dl,
                                          SDVTList VTList,
                                          ArrayRef<SDValue> Ops, EVT MemVT,
                                          MachineMemOperand *MMO) {
  assert(
      (Opcode == ISD::INTRINSIC_VOID || Opcode == ISD::INTRINSIC_W_CHAIN ||
       Opcode == ISD::PREFETCH ||
       (Opcode <= (unsigned)std::numeric_limits<int>::max() &&
        Opcode >= ISD::BUILTIN_OP_END && TSI->isTargetMemoryOpcode(Opcode))) &&
      "Opcode is not a memory-accessing opcode!");

  // Memoize the node unless it returns a glue result.
  MemIntrinsicSDNode *N;
  if (VTList.VTs[VTList.NumVTs-1] != MVT::Glue) {
    FoldingSetNodeID ID;
    AddNodeIDNode(ID, Opcode, VTList, Ops);
    ID.AddInteger(getSyntheticNodeSubclassData<MemIntrinsicSDNode>(
        Opcode, dl.getIROrder(), VTList, MemVT, MMO));
    ID.AddInteger(MMO->getPointerInfo().getAddrSpace());
    ID.AddInteger(MMO->getFlags());
    ID.AddInteger(MemVT.getRawBits());
    void *IP = nullptr;
    if (SDNode *E = FindNodeOrInsertPos(ID, dl, IP)) {
      cast<MemIntrinsicSDNode>(E)->refineAlignment(MMO);
      return SDValue(E, 0);
    }

    N = newSDNode<MemIntrinsicSDNode>(Opcode, dl.getIROrder(), dl.getDebugLoc(),
                                      VTList, MemVT, MMO);
    createOperands(N, Ops);

  CSEMap.InsertNode(N, IP);
  } else {
    N = newSDNode<MemIntrinsicSDNode>(Opcode, dl.getIROrder(), dl.getDebugLoc(),
                                      VTList, MemVT, MMO);
    createOperands(N, Ops);
  }
  InsertNode(N);
  SDValue V(N, 0);
  NewSDValueDbgMsg(V, "Creating new node: ", this);
  return V;
}

SDValue SelectionDAG::getLifetimeNode(bool IsStart, const SDLoc &dl,
                                      SDValue Chain, int FrameIndex) {
  const unsigned Opcode = IsStart ? ISD::LIFETIME_START : ISD::LIFETIME_END;
  const auto VTs = getVTList(MVT::Other);
  SDValue Ops[2] = {
      Chain,
      getFrameIndex(FrameIndex,
                    getTargetLoweringInfo().getFrameIndexTy(getDataLayout()),
                    true)};

  FoldingSetNodeID ID;
  AddNodeIDNode(ID, Opcode, VTs, Ops);
  ID.AddInteger(FrameIndex);
  void *IP = nullptr;
  if (SDNode *E = FindNodeOrInsertPos(ID, dl, IP))
    return SDValue(E, 0);

  LifetimeSDNode *N =
      newSDNode<LifetimeSDNode>(Opcode, dl.getIROrder(), dl.getDebugLoc(), VTs);
  createOperands(N, Ops);
  CSEMap.InsertNode(N, IP);
  InsertNode(N);
  SDValue V(N, 0);
  NewSDValueDbgMsg(V, "Creating new node: ", this);
  return V;
}

SDValue SelectionDAG::getPseudoProbeNode(const SDLoc &Dl, SDValue Chain,
                                         uint64_t Guid, uint64_t Index,
                                         uint32_t Attr) {
  const unsigned Opcode = ISD::PSEUDO_PROBE;
  const auto VTs = getVTList(MVT::Other);
  SDValue Ops[] = {Chain};
  FoldingSetNodeID ID;
  AddNodeIDNode(ID, Opcode, VTs, Ops);
  ID.AddInteger(Guid);
  ID.AddInteger(Index);
  void *IP = nullptr;
  if (SDNode *E = FindNodeOrInsertPos(ID, Dl, IP))
    return SDValue(E, 0);

  auto *N = newSDNode<PseudoProbeSDNode>(
      Opcode, Dl.getIROrder(), Dl.getDebugLoc(), VTs, Guid, Index, Attr);
  createOperands(N, Ops);
  CSEMap.InsertNode(N, IP);
  InsertNode(N);
  SDValue V(N, 0);
  NewSDValueDbgMsg(V, "Creating new node: ", this);
  return V;
}

/// InferPointerInfo - If the specified ptr/offset is a frame index, infer a
/// MachinePointerInfo record from it.  This is particularly useful because the
/// code generator has many cases where it doesn't bother passing in a
/// MachinePointerInfo to getLoad or getStore when it has "FI+Cst".
static MachinePointerInfo InferPointerInfo(const MachinePointerInfo &Info,
                                           SelectionDAG &DAG, SDValue Ptr,
                                           int64_t Offset = 0) {
  // If this is FI+Offset, we can model it.
  if (const FrameIndexSDNode *FI = dyn_cast<FrameIndexSDNode>(Ptr))
    return MachinePointerInfo::getFixedStack(DAG.getMachineFunction(),
                                             FI->getIndex(), Offset);

  // If this is (FI+Offset1)+Offset2, we can model it.
  if (Ptr.getOpcode() != ISD::ADD ||
      !isa<ConstantSDNode>(Ptr.getOperand(1)) ||
      !isa<FrameIndexSDNode>(Ptr.getOperand(0)))
    return Info;

  int FI = cast<FrameIndexSDNode>(Ptr.getOperand(0))->getIndex();
  return MachinePointerInfo::getFixedStack(
      DAG.getMachineFunction(), FI,
      Offset + cast<ConstantSDNode>(Ptr.getOperand(1))->getSExtValue());
}

/// InferPointerInfo - If the specified ptr/offset is a frame index, infer a
/// MachinePointerInfo record from it.  This is particularly useful because the
/// code generator has many cases where it doesn't bother passing in a
/// MachinePointerInfo to getLoad or getStore when it has "FI+Cst".
static MachinePointerInfo InferPointerInfo(const MachinePointerInfo &Info,
                                           SelectionDAG &DAG, SDValue Ptr,
                                           SDValue OffsetOp) {
  // If the 'Offset' value isn't a constant, we can't handle this.
  if (ConstantSDNode *OffsetNode = dyn_cast<ConstantSDNode>(OffsetOp))
    return InferPointerInfo(Info, DAG, Ptr, OffsetNode->getSExtValue());
  if (OffsetOp.isUndef())
    return InferPointerInfo(Info, DAG, Ptr);
  return Info;
}

SDValue SelectionDAG::getLoad(ISD::MemIndexedMode AM, ISD::LoadExtType ExtType,
                              EVT VT, const SDLoc &dl, SDValue Chain,
                              SDValue Ptr, SDValue Offset,
                              MachinePointerInfo PtrInfo, EVT MemVT,
                              Align Alignment,
                              MachineMemOperand::Flags MMOFlags,
                              const AAMDNodes &AAInfo, const MDNode *Ranges) {
  assert(Chain.getValueType() == MVT::Other &&
        "Invalid chain type");

  MMOFlags |= MachineMemOperand::MOLoad;
  assert((MMOFlags & MachineMemOperand::MOStore) == 0);
  // If we don't have a PtrInfo, infer the trivial frame index case to simplify
  // clients.
  if (PtrInfo.V.isNull())
    PtrInfo = InferPointerInfo(PtrInfo, *this, Ptr, Offset);

  TypeSize Size = MemVT.getStoreSize();
  MachineFunction &MF = getMachineFunction();
  MachineMemOperand *MMO = MF.getMachineMemOperand(PtrInfo, MMOFlags, Size,
                                                   Alignment, AAInfo, Ranges);
  return getLoad(AM, ExtType, VT, dl, Chain, Ptr, Offset, MemVT, MMO);
}

SDValue SelectionDAG::getLoad(ISD::MemIndexedMode AM, ISD::LoadExtType ExtType,
                              EVT VT, const SDLoc &dl, SDValue Chain,
                              SDValue Ptr, SDValue Offset, EVT MemVT,
                              MachineMemOperand *MMO) {
  if (VT == MemVT) {
    ExtType = ISD::NON_EXTLOAD;
  } else if (ExtType == ISD::NON_EXTLOAD) {
    assert(VT == MemVT && "Non-extending load from different memory type!");
  } else {
    // Extending load.
    assert(MemVT.getScalarType().bitsLT(VT.getScalarType()) &&
           "Should only be an extending load, not truncating!");
    assert(VT.isInteger() == MemVT.isInteger() &&
           "Cannot convert from FP to Int or Int -> FP!");
    assert(VT.isVector() == MemVT.isVector() &&
           "Cannot use an ext load to convert to or from a vector!");
    assert((!VT.isVector() ||
            VT.getVectorElementCount() == MemVT.getVectorElementCount()) &&
           "Cannot use an ext load to change the number of vector elements!");
  }

  assert((!MMO->getRanges() ||
          (mdconst::extract<ConstantInt>(MMO->getRanges()->getOperand(0))
                   ->getBitWidth() == MemVT.getScalarSizeInBits() &&
           MemVT.isInteger())) &&
         "Range metadata and load type must match!");

  bool Indexed = AM != ISD::UNINDEXED;
  assert((Indexed || Offset.isUndef()) && "Unindexed load with an offset!");

  SDVTList VTs = Indexed ?
    getVTList(VT, Ptr.getValueType(), MVT::Other) : getVTList(VT, MVT::Other);
  SDValue Ops[] = { Chain, Ptr, Offset };
  FoldingSetNodeID ID;
  AddNodeIDNode(ID, ISD::LOAD, VTs, Ops);
  ID.AddInteger(MemVT.getRawBits());
  ID.AddInteger(getSyntheticNodeSubclassData<LoadSDNode>(
      dl.getIROrder(), VTs, AM, ExtType, MemVT, MMO));
  ID.AddInteger(MMO->getPointerInfo().getAddrSpace());
  ID.AddInteger(MMO->getFlags());
  void *IP = nullptr;
  if (auto *E = cast_or_null<LoadSDNode>(FindNodeOrInsertPos(ID, dl, IP))) {
    E->refineAlignment(MMO);
    E->refineRanges(MMO);
    return SDValue(E, 0);
  }
  auto *N = newSDNode<LoadSDNode>(dl.getIROrder(), dl.getDebugLoc(), VTs, AM,
                                  ExtType, MemVT, MMO);
  createOperands(N, Ops);

  CSEMap.InsertNode(N, IP);
  InsertNode(N);
  SDValue V(N, 0);
  NewSDValueDbgMsg(V, "Creating new node: ", this);
  return V;
}

SDValue SelectionDAG::getLoad(EVT VT, const SDLoc &dl, SDValue Chain,
                              SDValue Ptr, MachinePointerInfo PtrInfo,
                              MaybeAlign Alignment,
                              MachineMemOperand::Flags MMOFlags,
                              const AAMDNodes &AAInfo, const MDNode *Ranges) {
  SDValue Undef = getUNDEF(Ptr.getValueType());
  return getLoad(ISD::UNINDEXED, ISD::NON_EXTLOAD, VT, dl, Chain, Ptr, Undef,
                 PtrInfo, VT, Alignment, MMOFlags, AAInfo, Ranges);
}

SDValue SelectionDAG::getLoad(EVT VT, const SDLoc &dl, SDValue Chain,
                              SDValue Ptr, MachineMemOperand *MMO) {
  SDValue Undef = getUNDEF(Ptr.getValueType());
  return getLoad(ISD::UNINDEXED, ISD::NON_EXTLOAD, VT, dl, Chain, Ptr, Undef,
                 VT, MMO);
}

SDValue SelectionDAG::getExtLoad(ISD::LoadExtType ExtType, const SDLoc &dl,
                                 EVT VT, SDValue Chain, SDValue Ptr,
                                 MachinePointerInfo PtrInfo, EVT MemVT,
                                 MaybeAlign Alignment,
                                 MachineMemOperand::Flags MMOFlags,
                                 const AAMDNodes &AAInfo) {
  SDValue Undef = getUNDEF(Ptr.getValueType());
  return getLoad(ISD::UNINDEXED, ExtType, VT, dl, Chain, Ptr, Undef, PtrInfo,
                 MemVT, Alignment, MMOFlags, AAInfo);
}

SDValue SelectionDAG::getExtLoad(ISD::LoadExtType ExtType, const SDLoc &dl,
                                 EVT VT, SDValue Chain, SDValue Ptr, EVT MemVT,
                                 MachineMemOperand *MMO) {
  SDValue Undef = getUNDEF(Ptr.getValueType());
  return getLoad(ISD::UNINDEXED, ExtType, VT, dl, Chain, Ptr, Undef,
                 MemVT, MMO);
}

SDValue SelectionDAG::getIndexedLoad(SDValue OrigLoad, const SDLoc &dl,
                                     SDValue Base, SDValue Offset,
                                     ISD::MemIndexedMode AM) {
  LoadSDNode *LD = cast<LoadSDNode>(OrigLoad);
  assert(LD->getOffset().isUndef() && "Load is already a indexed load!");
  // Don't propagate the invariant or dereferenceable flags.
  auto MMOFlags =
      LD->getMemOperand()->getFlags() &
      ~(MachineMemOperand::MOInvariant | MachineMemOperand::MODereferenceable);
  return getLoad(AM, LD->getExtensionType(), OrigLoad.getValueType(), dl,
                 LD->getChain(), Base, Offset, LD->getPointerInfo(),
                 LD->getMemoryVT(), LD->getAlign(), MMOFlags, LD->getAAInfo());
}

SDValue SelectionDAG::getStore(SDValue Chain, const SDLoc &dl, SDValue Val,
                               SDValue Ptr, MachinePointerInfo PtrInfo,
                               Align Alignment,
                               MachineMemOperand::Flags MMOFlags,
                               const AAMDNodes &AAInfo) {
  assert(Chain.getValueType() == MVT::Other && "Invalid chain type");

  MMOFlags |= MachineMemOperand::MOStore;
  assert((MMOFlags & MachineMemOperand::MOLoad) == 0);

  if (PtrInfo.V.isNull())
    PtrInfo = InferPointerInfo(PtrInfo, *this, Ptr);

  MachineFunction &MF = getMachineFunction();
  TypeSize Size = Val.getValueType().getStoreSize();
  MachineMemOperand *MMO =
      MF.getMachineMemOperand(PtrInfo, MMOFlags, Size, Alignment, AAInfo);
  return getStore(Chain, dl, Val, Ptr, MMO);
}

SDValue SelectionDAG::getStore(SDValue Chain, const SDLoc &dl, SDValue Val,
                               SDValue Ptr, MachineMemOperand *MMO) {
  SDValue Undef = getUNDEF(Ptr.getValueType());
  return getStore(Chain, dl, Val, Ptr, Undef, Val.getValueType(), MMO,
                  ISD::UNINDEXED);
}

SDValue SelectionDAG::getStore(SDValue Chain, const SDLoc &dl, SDValue Val,
                               SDValue Ptr, SDValue Offset, EVT SVT,
                               MachineMemOperand *MMO, ISD::MemIndexedMode AM,
                               bool IsTruncating) {
  assert(Chain.getValueType() == MVT::Other && "Invalid chain type");
  EVT VT = Val.getValueType();
  if (VT == SVT) {
    IsTruncating = false;
  } else if (!IsTruncating) {
    assert(VT == SVT && "No-truncating store from different memory type!");
  } else {
    assert(SVT.getScalarType().bitsLT(VT.getScalarType()) &&
           "Should only be a truncating store, not extending!");
    assert(VT.isInteger() == SVT.isInteger() && "Can't do FP-INT conversion!");
    assert(VT.isVector() == SVT.isVector() &&
           "Cannot use trunc store to convert to or from a vector!");
    assert((!VT.isVector() ||
            VT.getVectorElementCount() == SVT.getVectorElementCount()) &&
           "Cannot use trunc store to change the number of vector elements!");
  }

  bool Indexed = AM != ISD::UNINDEXED;
  assert((Indexed || Offset.isUndef()) && "Unindexed store with an offset!");
  SDVTList VTs = Indexed ? getVTList(Ptr.getValueType(), MVT::Other)
                         : getVTList(MVT::Other);
  SDValue Ops[] = {Chain, Val, Ptr, Offset};
  FoldingSetNodeID ID;
  AddNodeIDNode(ID, ISD::STORE, VTs, Ops);
  ID.AddInteger(SVT.getRawBits());
  ID.AddInteger(getSyntheticNodeSubclassData<StoreSDNode>(
      dl.getIROrder(), VTs, AM, IsTruncating, SVT, MMO));
  ID.AddInteger(MMO->getPointerInfo().getAddrSpace());
  ID.AddInteger(MMO->getFlags());
  void *IP = nullptr;
  if (SDNode *E = FindNodeOrInsertPos(ID, dl, IP)) {
    cast<StoreSDNode>(E)->refineAlignment(MMO);
    return SDValue(E, 0);
  }
  auto *N = newSDNode<StoreSDNode>(dl.getIROrder(), dl.getDebugLoc(), VTs, AM,
                                   IsTruncating, SVT, MMO);
  createOperands(N, Ops);

  CSEMap.InsertNode(N, IP);
  InsertNode(N);
  SDValue V(N, 0);
  NewSDValueDbgMsg(V, "Creating new node: ", this);
  return V;
}

SDValue SelectionDAG::getTruncStore(SDValue Chain, const SDLoc &dl, SDValue Val,
                                    SDValue Ptr, MachinePointerInfo PtrInfo,
                                    EVT SVT, Align Alignment,
                                    MachineMemOperand::Flags MMOFlags,
                                    const AAMDNodes &AAInfo) {
  assert(Chain.getValueType() == MVT::Other &&
        "Invalid chain type");

  MMOFlags |= MachineMemOperand::MOStore;
  assert((MMOFlags & MachineMemOperand::MOLoad) == 0);

  if (PtrInfo.V.isNull())
    PtrInfo = InferPointerInfo(PtrInfo, *this, Ptr);

  MachineFunction &MF = getMachineFunction();
  MachineMemOperand *MMO = MF.getMachineMemOperand(
      PtrInfo, MMOFlags, SVT.getStoreSize(), Alignment, AAInfo);
  return getTruncStore(Chain, dl, Val, Ptr, SVT, MMO);
}

SDValue SelectionDAG::getTruncStore(SDValue Chain, const SDLoc &dl, SDValue Val,
                                    SDValue Ptr, EVT SVT,
                                    MachineMemOperand *MMO) {
  SDValue Undef = getUNDEF(Ptr.getValueType());
  return getStore(Chain, dl, Val, Ptr, Undef, SVT, MMO, ISD::UNINDEXED, true);
}

SDValue SelectionDAG::getIndexedStore(SDValue OrigStore, const SDLoc &dl,
                                      SDValue Base, SDValue Offset,
                                      ISD::MemIndexedMode AM) {
  StoreSDNode *ST = cast<StoreSDNode>(OrigStore);
  assert(ST->getOffset().isUndef() && "Store is already a indexed store!");
  return getStore(ST->getChain(), dl, ST->getValue(), Base, Offset,
                  ST->getMemoryVT(), ST->getMemOperand(), AM,
                  ST->isTruncatingStore());
}

SDValue SelectionDAG::getLoadVP(
    ISD::MemIndexedMode AM, ISD::LoadExtType ExtType, EVT VT, const SDLoc &dl,
    SDValue Chain, SDValue Ptr, SDValue Offset, SDValue Mask, SDValue EVL,
    MachinePointerInfo PtrInfo, EVT MemVT, Align Alignment,
    MachineMemOperand::Flags MMOFlags, const AAMDNodes &AAInfo,
    const MDNode *Ranges, bool IsExpanding) {
  assert(Chain.getValueType() == MVT::Other && "Invalid chain type");

  MMOFlags |= MachineMemOperand::MOLoad;
  assert((MMOFlags & MachineMemOperand::MOStore) == 0);
  // If we don't have a PtrInfo, infer the trivial frame index case to simplify
  // clients.
  if (PtrInfo.V.isNull())
    PtrInfo = InferPointerInfo(PtrInfo, *this, Ptr, Offset);

  TypeSize Size = MemVT.getStoreSize();
  MachineFunction &MF = getMachineFunction();
  MachineMemOperand *MMO = MF.getMachineMemOperand(PtrInfo, MMOFlags, Size,
                                                   Alignment, AAInfo, Ranges);
  return getLoadVP(AM, ExtType, VT, dl, Chain, Ptr, Offset, Mask, EVL, MemVT,
                   MMO, IsExpanding);
}

SDValue SelectionDAG::getLoadVP(ISD::MemIndexedMode AM,
                                ISD::LoadExtType ExtType, EVT VT,
                                const SDLoc &dl, SDValue Chain, SDValue Ptr,
                                SDValue Offset, SDValue Mask, SDValue EVL,
                                EVT MemVT, MachineMemOperand *MMO,
                                bool IsExpanding) {
  bool Indexed = AM != ISD::UNINDEXED;
  assert((Indexed || Offset.isUndef()) && "Unindexed load with an offset!");

  SDVTList VTs = Indexed ? getVTList(VT, Ptr.getValueType(), MVT::Other)
                         : getVTList(VT, MVT::Other);
  SDValue Ops[] = {Chain, Ptr, Offset, Mask, EVL};
  FoldingSetNodeID ID;
  AddNodeIDNode(ID, ISD::VP_LOAD, VTs, Ops);
  ID.AddInteger(MemVT.getRawBits());
  ID.AddInteger(getSyntheticNodeSubclassData<VPLoadSDNode>(
      dl.getIROrder(), VTs, AM, ExtType, IsExpanding, MemVT, MMO));
  ID.AddInteger(MMO->getPointerInfo().getAddrSpace());
  ID.AddInteger(MMO->getFlags());
  void *IP = nullptr;
  if (auto *E = cast_or_null<VPLoadSDNode>(FindNodeOrInsertPos(ID, dl, IP))) {
    E->refineAlignment(MMO);
    E->refineRanges(MMO);
    return SDValue(E, 0);
  }
  auto *N = newSDNode<VPLoadSDNode>(dl.getIROrder(), dl.getDebugLoc(), VTs, AM,
                                    ExtType, IsExpanding, MemVT, MMO);
  createOperands(N, Ops);

  CSEMap.InsertNode(N, IP);
  InsertNode(N);
  SDValue V(N, 0);
  NewSDValueDbgMsg(V, "Creating new node: ", this);
  return V;
}

SDValue SelectionDAG::getLoadVP(EVT VT, const SDLoc &dl, SDValue Chain,
                                SDValue Ptr, SDValue Mask, SDValue EVL,
                                MachinePointerInfo PtrInfo,
                                MaybeAlign Alignment,
                                MachineMemOperand::Flags MMOFlags,
                                const AAMDNodes &AAInfo, const MDNode *Ranges,
                                bool IsExpanding) {
  SDValue Undef = getUNDEF(Ptr.getValueType());
  return getLoadVP(ISD::UNINDEXED, ISD::NON_EXTLOAD, VT, dl, Chain, Ptr, Undef,
                   Mask, EVL, PtrInfo, VT, Alignment, MMOFlags, AAInfo, Ranges,
                   IsExpanding);
}

SDValue SelectionDAG::getLoadVP(EVT VT, const SDLoc &dl, SDValue Chain,
                                SDValue Ptr, SDValue Mask, SDValue EVL,
                                MachineMemOperand *MMO, bool IsExpanding) {
  SDValue Undef = getUNDEF(Ptr.getValueType());
  return getLoadVP(ISD::UNINDEXED, ISD::NON_EXTLOAD, VT, dl, Chain, Ptr, Undef,
                   Mask, EVL, VT, MMO, IsExpanding);
}

SDValue SelectionDAG::getExtLoadVP(ISD::LoadExtType ExtType, const SDLoc &dl,
                                   EVT VT, SDValue Chain, SDValue Ptr,
                                   SDValue Mask, SDValue EVL,
                                   MachinePointerInfo PtrInfo, EVT MemVT,
                                   MaybeAlign Alignment,
                                   MachineMemOperand::Flags MMOFlags,
                                   const AAMDNodes &AAInfo, bool IsExpanding) {
  SDValue Undef = getUNDEF(Ptr.getValueType());
  return getLoadVP(ISD::UNINDEXED, ExtType, VT, dl, Chain, Ptr, Undef, Mask,
                   EVL, PtrInfo, MemVT, Alignment, MMOFlags, AAInfo, nullptr,
                   IsExpanding);
}

SDValue SelectionDAG::getExtLoadVP(ISD::LoadExtType ExtType, const SDLoc &dl,
                                   EVT VT, SDValue Chain, SDValue Ptr,
                                   SDValue Mask, SDValue EVL, EVT MemVT,
                                   MachineMemOperand *MMO, bool IsExpanding) {
  SDValue Undef = getUNDEF(Ptr.getValueType());
  return getLoadVP(ISD::UNINDEXED, ExtType, VT, dl, Chain, Ptr, Undef, Mask,
                   EVL, MemVT, MMO, IsExpanding);
}

SDValue SelectionDAG::getIndexedLoadVP(SDValue OrigLoad, const SDLoc &dl,
                                       SDValue Base, SDValue Offset,
                                       ISD::MemIndexedMode AM) {
  auto *LD = cast<VPLoadSDNode>(OrigLoad);
  assert(LD->getOffset().isUndef() && "Load is already a indexed load!");
  // Don't propagate the invariant or dereferenceable flags.
  auto MMOFlags =
      LD->getMemOperand()->getFlags() &
      ~(MachineMemOperand::MOInvariant | MachineMemOperand::MODereferenceable);
  return getLoadVP(AM, LD->getExtensionType(), OrigLoad.getValueType(), dl,
                   LD->getChain(), Base, Offset, LD->getMask(),
                   LD->getVectorLength(), LD->getPointerInfo(),
                   LD->getMemoryVT(), LD->getAlign(), MMOFlags, LD->getAAInfo(),
                   nullptr, LD->isExpandingLoad());
}

SDValue SelectionDAG::getStoreVP(SDValue Chain, const SDLoc &dl, SDValue Val,
                                 SDValue Ptr, SDValue Offset, SDValue Mask,
                                 SDValue EVL, EVT MemVT, MachineMemOperand *MMO,
                                 ISD::MemIndexedMode AM, bool IsTruncating,
                                 bool IsCompressing) {
  assert(Chain.getValueType() == MVT::Other && "Invalid chain type");
  bool Indexed = AM != ISD::UNINDEXED;
  assert((Indexed || Offset.isUndef()) && "Unindexed vp_store with an offset!");
  SDVTList VTs = Indexed ? getVTList(Ptr.getValueType(), MVT::Other)
                         : getVTList(MVT::Other);
  SDValue Ops[] = {Chain, Val, Ptr, Offset, Mask, EVL};
  FoldingSetNodeID ID;
  AddNodeIDNode(ID, ISD::VP_STORE, VTs, Ops);
  ID.AddInteger(MemVT.getRawBits());
  ID.AddInteger(getSyntheticNodeSubclassData<VPStoreSDNode>(
      dl.getIROrder(), VTs, AM, IsTruncating, IsCompressing, MemVT, MMO));
  ID.AddInteger(MMO->getPointerInfo().getAddrSpace());
  ID.AddInteger(MMO->getFlags());
  void *IP = nullptr;
  if (SDNode *E = FindNodeOrInsertPos(ID, dl, IP)) {
    cast<VPStoreSDNode>(E)->refineAlignment(MMO);
    return SDValue(E, 0);
  }
  auto *N = newSDNode<VPStoreSDNode>(dl.getIROrder(), dl.getDebugLoc(), VTs, AM,
                                     IsTruncating, IsCompressing, MemVT, MMO);
  createOperands(N, Ops);

  CSEMap.InsertNode(N, IP);
  InsertNode(N);
  SDValue V(N, 0);
  NewSDValueDbgMsg(V, "Creating new node: ", this);
  return V;
}

SDValue SelectionDAG::getTruncStoreVP(SDValue Chain, const SDLoc &dl,
                                      SDValue Val, SDValue Ptr, SDValue Mask,
                                      SDValue EVL, MachinePointerInfo PtrInfo,
                                      EVT SVT, Align Alignment,
                                      MachineMemOperand::Flags MMOFlags,
                                      const AAMDNodes &AAInfo,
                                      bool IsCompressing) {
  assert(Chain.getValueType() == MVT::Other && "Invalid chain type");

  MMOFlags |= MachineMemOperand::MOStore;
  assert((MMOFlags & MachineMemOperand::MOLoad) == 0);

  if (PtrInfo.V.isNull())
    PtrInfo = InferPointerInfo(PtrInfo, *this, Ptr);

  MachineFunction &MF = getMachineFunction();
  MachineMemOperand *MMO = MF.getMachineMemOperand(
      PtrInfo, MMOFlags, SVT.getStoreSize(), Alignment, AAInfo);
  return getTruncStoreVP(Chain, dl, Val, Ptr, Mask, EVL, SVT, MMO,
                         IsCompressing);
}

SDValue SelectionDAG::getTruncStoreVP(SDValue Chain, const SDLoc &dl,
                                      SDValue Val, SDValue Ptr, SDValue Mask,
                                      SDValue EVL, EVT SVT,
                                      MachineMemOperand *MMO,
                                      bool IsCompressing) {
  EVT VT = Val.getValueType();

  assert(Chain.getValueType() == MVT::Other && "Invalid chain type");
  if (VT == SVT)
    return getStoreVP(Chain, dl, Val, Ptr, getUNDEF(Ptr.getValueType()), Mask,
                      EVL, VT, MMO, ISD::UNINDEXED,
                      /*IsTruncating*/ false, IsCompressing);

  assert(SVT.getScalarType().bitsLT(VT.getScalarType()) &&
         "Should only be a truncating store, not extending!");
  assert(VT.isInteger() == SVT.isInteger() && "Can't do FP-INT conversion!");
  assert(VT.isVector() == SVT.isVector() &&
         "Cannot use trunc store to convert to or from a vector!");
  assert((!VT.isVector() ||
          VT.getVectorElementCount() == SVT.getVectorElementCount()) &&
         "Cannot use trunc store to change the number of vector elements!");

  SDVTList VTs = getVTList(MVT::Other);
  SDValue Undef = getUNDEF(Ptr.getValueType());
  SDValue Ops[] = {Chain, Val, Ptr, Undef, Mask, EVL};
  FoldingSetNodeID ID;
  AddNodeIDNode(ID, ISD::VP_STORE, VTs, Ops);
  ID.AddInteger(SVT.getRawBits());
  ID.AddInteger(getSyntheticNodeSubclassData<VPStoreSDNode>(
      dl.getIROrder(), VTs, ISD::UNINDEXED, true, IsCompressing, SVT, MMO));
  ID.AddInteger(MMO->getPointerInfo().getAddrSpace());
  ID.AddInteger(MMO->getFlags());
  void *IP = nullptr;
  if (SDNode *E = FindNodeOrInsertPos(ID, dl, IP)) {
    cast<VPStoreSDNode>(E)->refineAlignment(MMO);
    return SDValue(E, 0);
  }
  auto *N =
      newSDNode<VPStoreSDNode>(dl.getIROrder(), dl.getDebugLoc(), VTs,
                               ISD::UNINDEXED, true, IsCompressing, SVT, MMO);
  createOperands(N, Ops);

  CSEMap.InsertNode(N, IP);
  InsertNode(N);
  SDValue V(N, 0);
  NewSDValueDbgMsg(V, "Creating new node: ", this);
  return V;
}

SDValue SelectionDAG::getIndexedStoreVP(SDValue OrigStore, const SDLoc &dl,
                                        SDValue Base, SDValue Offset,
                                        ISD::MemIndexedMode AM) {
  auto *ST = cast<VPStoreSDNode>(OrigStore);
  assert(ST->getOffset().isUndef() && "Store is already an indexed store!");
  SDVTList VTs = getVTList(Base.getValueType(), MVT::Other);
  SDValue Ops[] = {ST->getChain(), ST->getValue(), Base,
                   Offset,         ST->getMask(),  ST->getVectorLength()};
  FoldingSetNodeID ID;
  AddNodeIDNode(ID, ISD::VP_STORE, VTs, Ops);
  ID.AddInteger(ST->getMemoryVT().getRawBits());
  ID.AddInteger(ST->getRawSubclassData());
  ID.AddInteger(ST->getPointerInfo().getAddrSpace());
  ID.AddInteger(ST->getMemOperand()->getFlags());
  void *IP = nullptr;
  if (SDNode *E = FindNodeOrInsertPos(ID, dl, IP))
    return SDValue(E, 0);

  auto *N = newSDNode<VPStoreSDNode>(
      dl.getIROrder(), dl.getDebugLoc(), VTs, AM, ST->isTruncatingStore(),
      ST->isCompressingStore(), ST->getMemoryVT(), ST->getMemOperand());
  createOperands(N, Ops);

  CSEMap.InsertNode(N, IP);
  InsertNode(N);
  SDValue V(N, 0);
  NewSDValueDbgMsg(V, "Creating new node: ", this);
  return V;
}

SDValue SelectionDAG::getStridedLoadVP(
    ISD::MemIndexedMode AM, ISD::LoadExtType ExtType, EVT VT, const SDLoc &DL,
    SDValue Chain, SDValue Ptr, SDValue Offset, SDValue Stride, SDValue Mask,
    SDValue EVL, EVT MemVT, MachineMemOperand *MMO, bool IsExpanding) {
  bool Indexed = AM != ISD::UNINDEXED;
  assert((Indexed || Offset.isUndef()) && "Unindexed load with an offset!");

  SDValue Ops[] = {Chain, Ptr, Offset, Stride, Mask, EVL};
  SDVTList VTs = Indexed ? getVTList(VT, Ptr.getValueType(), MVT::Other)
                         : getVTList(VT, MVT::Other);
  FoldingSetNodeID ID;
  AddNodeIDNode(ID, ISD::EXPERIMENTAL_VP_STRIDED_LOAD, VTs, Ops);
  ID.AddInteger(VT.getRawBits());
  ID.AddInteger(getSyntheticNodeSubclassData<VPStridedLoadSDNode>(
      DL.getIROrder(), VTs, AM, ExtType, IsExpanding, MemVT, MMO));
  ID.AddInteger(MMO->getPointerInfo().getAddrSpace());

  void *IP = nullptr;
  if (SDNode *E = FindNodeOrInsertPos(ID, DL, IP)) {
    cast<VPStridedLoadSDNode>(E)->refineAlignment(MMO);
    return SDValue(E, 0);
  }

  auto *N =
      newSDNode<VPStridedLoadSDNode>(DL.getIROrder(), DL.getDebugLoc(), VTs, AM,
                                     ExtType, IsExpanding, MemVT, MMO);
  createOperands(N, Ops);
  CSEMap.InsertNode(N, IP);
  InsertNode(N);
  SDValue V(N, 0);
  NewSDValueDbgMsg(V, "Creating new node: ", this);
  return V;
}

SDValue SelectionDAG::getStridedLoadVP(EVT VT, const SDLoc &DL, SDValue Chain,
                                       SDValue Ptr, SDValue Stride,
                                       SDValue Mask, SDValue EVL,
                                       MachineMemOperand *MMO,
                                       bool IsExpanding) {
  SDValue Undef = getUNDEF(Ptr.getValueType());
  return getStridedLoadVP(ISD::UNINDEXED, ISD::NON_EXTLOAD, VT, DL, Chain, Ptr,
                          Undef, Stride, Mask, EVL, VT, MMO, IsExpanding);
}

SDValue SelectionDAG::getExtStridedLoadVP(
    ISD::LoadExtType ExtType, const SDLoc &DL, EVT VT, SDValue Chain,
    SDValue Ptr, SDValue Stride, SDValue Mask, SDValue EVL, EVT MemVT,
    MachineMemOperand *MMO, bool IsExpanding) {
  SDValue Undef = getUNDEF(Ptr.getValueType());
  return getStridedLoadVP(ISD::UNINDEXED, ExtType, VT, DL, Chain, Ptr, Undef,
                          Stride, Mask, EVL, MemVT, MMO, IsExpanding);
}

SDValue SelectionDAG::getStridedStoreVP(SDValue Chain, const SDLoc &DL,
                                        SDValue Val, SDValue Ptr,
                                        SDValue Offset, SDValue Stride,
                                        SDValue Mask, SDValue EVL, EVT MemVT,
                                        MachineMemOperand *MMO,
                                        ISD::MemIndexedMode AM,
                                        bool IsTruncating, bool IsCompressing) {
  assert(Chain.getValueType() == MVT::Other && "Invalid chain type");
  bool Indexed = AM != ISD::UNINDEXED;
  assert((Indexed || Offset.isUndef()) && "Unindexed vp_store with an offset!");
  SDVTList VTs = Indexed ? getVTList(Ptr.getValueType(), MVT::Other)
                         : getVTList(MVT::Other);
  SDValue Ops[] = {Chain, Val, Ptr, Offset, Stride, Mask, EVL};
  FoldingSetNodeID ID;
  AddNodeIDNode(ID, ISD::EXPERIMENTAL_VP_STRIDED_STORE, VTs, Ops);
  ID.AddInteger(MemVT.getRawBits());
  ID.AddInteger(getSyntheticNodeSubclassData<VPStridedStoreSDNode>(
      DL.getIROrder(), VTs, AM, IsTruncating, IsCompressing, MemVT, MMO));
  ID.AddInteger(MMO->getPointerInfo().getAddrSpace());
  void *IP = nullptr;
  if (SDNode *E = FindNodeOrInsertPos(ID, DL, IP)) {
    cast<VPStridedStoreSDNode>(E)->refineAlignment(MMO);
    return SDValue(E, 0);
  }
  auto *N = newSDNode<VPStridedStoreSDNode>(DL.getIROrder(), DL.getDebugLoc(),
                                            VTs, AM, IsTruncating,
                                            IsCompressing, MemVT, MMO);
  createOperands(N, Ops);

  CSEMap.InsertNode(N, IP);
  InsertNode(N);
  SDValue V(N, 0);
  NewSDValueDbgMsg(V, "Creating new node: ", this);
  return V;
}

SDValue SelectionDAG::getTruncStridedStoreVP(SDValue Chain, const SDLoc &DL,
                                             SDValue Val, SDValue Ptr,
                                             SDValue Stride, SDValue Mask,
                                             SDValue EVL, EVT SVT,
                                             MachineMemOperand *MMO,
                                             bool IsCompressing) {
  EVT VT = Val.getValueType();

  assert(Chain.getValueType() == MVT::Other && "Invalid chain type");
  if (VT == SVT)
    return getStridedStoreVP(Chain, DL, Val, Ptr, getUNDEF(Ptr.getValueType()),
                             Stride, Mask, EVL, VT, MMO, ISD::UNINDEXED,
                             /*IsTruncating*/ false, IsCompressing);

  assert(SVT.getScalarType().bitsLT(VT.getScalarType()) &&
         "Should only be a truncating store, not extending!");
  assert(VT.isInteger() == SVT.isInteger() && "Can't do FP-INT conversion!");
  assert(VT.isVector() == SVT.isVector() &&
         "Cannot use trunc store to convert to or from a vector!");
  assert((!VT.isVector() ||
          VT.getVectorElementCount() == SVT.getVectorElementCount()) &&
         "Cannot use trunc store to change the number of vector elements!");

  SDVTList VTs = getVTList(MVT::Other);
  SDValue Undef = getUNDEF(Ptr.getValueType());
  SDValue Ops[] = {Chain, Val, Ptr, Undef, Stride, Mask, EVL};
  FoldingSetNodeID ID;
  AddNodeIDNode(ID, ISD::EXPERIMENTAL_VP_STRIDED_STORE, VTs, Ops);
  ID.AddInteger(SVT.getRawBits());
  ID.AddInteger(getSyntheticNodeSubclassData<VPStridedStoreSDNode>(
      DL.getIROrder(), VTs, ISD::UNINDEXED, true, IsCompressing, SVT, MMO));
  ID.AddInteger(MMO->getPointerInfo().getAddrSpace());
  void *IP = nullptr;
  if (SDNode *E = FindNodeOrInsertPos(ID, DL, IP)) {
    cast<VPStridedStoreSDNode>(E)->refineAlignment(MMO);
    return SDValue(E, 0);
  }
  auto *N = newSDNode<VPStridedStoreSDNode>(DL.getIROrder(), DL.getDebugLoc(),
                                            VTs, ISD::UNINDEXED, true,
                                            IsCompressing, SVT, MMO);
  createOperands(N, Ops);

  CSEMap.InsertNode(N, IP);
  InsertNode(N);
  SDValue V(N, 0);
  NewSDValueDbgMsg(V, "Creating new node: ", this);
  return V;
}

SDValue SelectionDAG::getGatherVP(SDVTList VTs, EVT VT, const SDLoc &dl,
                                  ArrayRef<SDValue> Ops, MachineMemOperand *MMO,
                                  ISD::MemIndexType IndexType) {
  assert(Ops.size() == 6 && "Incompatible number of operands");

  FoldingSetNodeID ID;
  AddNodeIDNode(ID, ISD::VP_GATHER, VTs, Ops);
  ID.AddInteger(VT.getRawBits());
  ID.AddInteger(getSyntheticNodeSubclassData<VPGatherSDNode>(
      dl.getIROrder(), VTs, VT, MMO, IndexType));
  ID.AddInteger(MMO->getPointerInfo().getAddrSpace());
  ID.AddInteger(MMO->getFlags());
  void *IP = nullptr;
  if (SDNode *E = FindNodeOrInsertPos(ID, dl, IP)) {
    cast<VPGatherSDNode>(E)->refineAlignment(MMO);
    return SDValue(E, 0);
  }

  auto *N = newSDNode<VPGatherSDNode>(dl.getIROrder(), dl.getDebugLoc(), VTs,
                                      VT, MMO, IndexType);
  createOperands(N, Ops);

  assert(N->getMask().getValueType().getVectorElementCount() ==
             N->getValueType(0).getVectorElementCount() &&
         "Vector width mismatch between mask and data");
  assert(N->getIndex().getValueType().getVectorElementCount().isScalable() ==
             N->getValueType(0).getVectorElementCount().isScalable() &&
         "Scalable flags of index and data do not match");
  assert(ElementCount::isKnownGE(
             N->getIndex().getValueType().getVectorElementCount(),
             N->getValueType(0).getVectorElementCount()) &&
         "Vector width mismatch between index and data");
  assert(isa<ConstantSDNode>(N->getScale()) &&
         N->getScale()->getAsAPIntVal().isPowerOf2() &&
         "Scale should be a constant power of 2");

  CSEMap.InsertNode(N, IP);
  InsertNode(N);
  SDValue V(N, 0);
  NewSDValueDbgMsg(V, "Creating new node: ", this);
  return V;
}

SDValue SelectionDAG::getScatterVP(SDVTList VTs, EVT VT, const SDLoc &dl,
                                   ArrayRef<SDValue> Ops,
                                   MachineMemOperand *MMO,
                                   ISD::MemIndexType IndexType) {
  assert(Ops.size() == 7 && "Incompatible number of operands");

  FoldingSetNodeID ID;
  AddNodeIDNode(ID, ISD::VP_SCATTER, VTs, Ops);
  ID.AddInteger(VT.getRawBits());
  ID.AddInteger(getSyntheticNodeSubclassData<VPScatterSDNode>(
      dl.getIROrder(), VTs, VT, MMO, IndexType));
  ID.AddInteger(MMO->getPointerInfo().getAddrSpace());
  ID.AddInteger(MMO->getFlags());
  void *IP = nullptr;
  if (SDNode *E = FindNodeOrInsertPos(ID, dl, IP)) {
    cast<VPScatterSDNode>(E)->refineAlignment(MMO);
    return SDValue(E, 0);
  }
  auto *N = newSDNode<VPScatterSDNode>(dl.getIROrder(), dl.getDebugLoc(), VTs,
                                       VT, MMO, IndexType);
  createOperands(N, Ops);

  assert(N->getMask().getValueType().getVectorElementCount() ==
             N->getValue().getValueType().getVectorElementCount() &&
         "Vector width mismatch between mask and data");
  assert(
      N->getIndex().getValueType().getVectorElementCount().isScalable() ==
          N->getValue().getValueType().getVectorElementCount().isScalable() &&
      "Scalable flags of index and data do not match");
  assert(ElementCount::isKnownGE(
             N->getIndex().getValueType().getVectorElementCount(),
             N->getValue().getValueType().getVectorElementCount()) &&
         "Vector width mismatch between index and data");
  assert(isa<ConstantSDNode>(N->getScale()) &&
         N->getScale()->getAsAPIntVal().isPowerOf2() &&
         "Scale should be a constant power of 2");

  CSEMap.InsertNode(N, IP);
  InsertNode(N);
  SDValue V(N, 0);
  NewSDValueDbgMsg(V, "Creating new node: ", this);
  return V;
}

SDValue SelectionDAG::getMaskedLoad(EVT VT, const SDLoc &dl, SDValue Chain,
                                    SDValue Base, SDValue Offset, SDValue Mask,
                                    SDValue PassThru, EVT MemVT,
                                    MachineMemOperand *MMO,
                                    ISD::MemIndexedMode AM,
                                    ISD::LoadExtType ExtTy, bool isExpanding) {
  bool Indexed = AM != ISD::UNINDEXED;
  assert((Indexed || Offset.isUndef()) &&
         "Unindexed masked load with an offset!");
  SDVTList VTs = Indexed ? getVTList(VT, Base.getValueType(), MVT::Other)
                         : getVTList(VT, MVT::Other);
  SDValue Ops[] = {Chain, Base, Offset, Mask, PassThru};
  FoldingSetNodeID ID;
  AddNodeIDNode(ID, ISD::MLOAD, VTs, Ops);
  ID.AddInteger(MemVT.getRawBits());
  ID.AddInteger(getSyntheticNodeSubclassData<MaskedLoadSDNode>(
      dl.getIROrder(), VTs, AM, ExtTy, isExpanding, MemVT, MMO));
  ID.AddInteger(MMO->getPointerInfo().getAddrSpace());
  ID.AddInteger(MMO->getFlags());
  void *IP = nullptr;
  if (SDNode *E = FindNodeOrInsertPos(ID, dl, IP)) {
    cast<MaskedLoadSDNode>(E)->refineAlignment(MMO);
    return SDValue(E, 0);
  }
  auto *N = newSDNode<MaskedLoadSDNode>(dl.getIROrder(), dl.getDebugLoc(), VTs,
                                        AM, ExtTy, isExpanding, MemVT, MMO);
  createOperands(N, Ops);

  CSEMap.InsertNode(N, IP);
  InsertNode(N);
  SDValue V(N, 0);
  NewSDValueDbgMsg(V, "Creating new node: ", this);
  return V;
}

SDValue SelectionDAG::getIndexedMaskedLoad(SDValue OrigLoad, const SDLoc &dl,
                                           SDValue Base, SDValue Offset,
                                           ISD::MemIndexedMode AM) {
  MaskedLoadSDNode *LD = cast<MaskedLoadSDNode>(OrigLoad);
  assert(LD->getOffset().isUndef() && "Masked load is already a indexed load!");
  return getMaskedLoad(OrigLoad.getValueType(), dl, LD->getChain(), Base,
                       Offset, LD->getMask(), LD->getPassThru(),
                       LD->getMemoryVT(), LD->getMemOperand(), AM,
                       LD->getExtensionType(), LD->isExpandingLoad());
}

SDValue SelectionDAG::getMaskedStore(SDValue Chain, const SDLoc &dl,
                                     SDValue Val, SDValue Base, SDValue Offset,
                                     SDValue Mask, EVT MemVT,
                                     MachineMemOperand *MMO,
                                     ISD::MemIndexedMode AM, bool IsTruncating,
                                     bool IsCompressing) {
  assert(Chain.getValueType() == MVT::Other &&
        "Invalid chain type");
  bool Indexed = AM != ISD::UNINDEXED;
  assert((Indexed || Offset.isUndef()) &&
         "Unindexed masked store with an offset!");
  SDVTList VTs = Indexed ? getVTList(Base.getValueType(), MVT::Other)
                         : getVTList(MVT::Other);
  SDValue Ops[] = {Chain, Val, Base, Offset, Mask};
  FoldingSetNodeID ID;
  AddNodeIDNode(ID, ISD::MSTORE, VTs, Ops);
  ID.AddInteger(MemVT.getRawBits());
  ID.AddInteger(getSyntheticNodeSubclassData<MaskedStoreSDNode>(
      dl.getIROrder(), VTs, AM, IsTruncating, IsCompressing, MemVT, MMO));
  ID.AddInteger(MMO->getPointerInfo().getAddrSpace());
  ID.AddInteger(MMO->getFlags());
  void *IP = nullptr;
  if (SDNode *E = FindNodeOrInsertPos(ID, dl, IP)) {
    cast<MaskedStoreSDNode>(E)->refineAlignment(MMO);
    return SDValue(E, 0);
  }
  auto *N =
      newSDNode<MaskedStoreSDNode>(dl.getIROrder(), dl.getDebugLoc(), VTs, AM,
                                   IsTruncating, IsCompressing, MemVT, MMO);
  createOperands(N, Ops);

  CSEMap.InsertNode(N, IP);
  InsertNode(N);
  SDValue V(N, 0);
  NewSDValueDbgMsg(V, "Creating new node: ", this);
  return V;
}

SDValue SelectionDAG::getIndexedMaskedStore(SDValue OrigStore, const SDLoc &dl,
                                            SDValue Base, SDValue Offset,
                                            ISD::MemIndexedMode AM) {
  MaskedStoreSDNode *ST = cast<MaskedStoreSDNode>(OrigStore);
  assert(ST->getOffset().isUndef() &&
         "Masked store is already a indexed store!");
  return getMaskedStore(ST->getChain(), dl, ST->getValue(), Base, Offset,
                        ST->getMask(), ST->getMemoryVT(), ST->getMemOperand(),
                        AM, ST->isTruncatingStore(), ST->isCompressingStore());
}

SDValue SelectionDAG::getMaskedGather(SDVTList VTs, EVT MemVT, const SDLoc &dl,
                                      ArrayRef<SDValue> Ops,
                                      MachineMemOperand *MMO,
                                      ISD::MemIndexType IndexType,
                                      ISD::LoadExtType ExtTy) {
  assert(Ops.size() == 6 && "Incompatible number of operands");

  FoldingSetNodeID ID;
  AddNodeIDNode(ID, ISD::MGATHER, VTs, Ops);
  ID.AddInteger(MemVT.getRawBits());
  ID.AddInteger(getSyntheticNodeSubclassData<MaskedGatherSDNode>(
      dl.getIROrder(), VTs, MemVT, MMO, IndexType, ExtTy));
  ID.AddInteger(MMO->getPointerInfo().getAddrSpace());
  ID.AddInteger(MMO->getFlags());
  void *IP = nullptr;
  if (SDNode *E = FindNodeOrInsertPos(ID, dl, IP)) {
    cast<MaskedGatherSDNode>(E)->refineAlignment(MMO);
    return SDValue(E, 0);
  }

  auto *N = newSDNode<MaskedGatherSDNode>(dl.getIROrder(), dl.getDebugLoc(),
                                          VTs, MemVT, MMO, IndexType, ExtTy);
  createOperands(N, Ops);

  assert(N->getPassThru().getValueType() == N->getValueType(0) &&
         "Incompatible type of the PassThru value in MaskedGatherSDNode");
  assert(N->getMask().getValueType().getVectorElementCount() ==
             N->getValueType(0).getVectorElementCount() &&
         "Vector width mismatch between mask and data");
  assert(N->getIndex().getValueType().getVectorElementCount().isScalable() ==
             N->getValueType(0).getVectorElementCount().isScalable() &&
         "Scalable flags of index and data do not match");
  assert(ElementCount::isKnownGE(
             N->getIndex().getValueType().getVectorElementCount(),
             N->getValueType(0).getVectorElementCount()) &&
         "Vector width mismatch between index and data");
  assert(isa<ConstantSDNode>(N->getScale()) &&
         N->getScale()->getAsAPIntVal().isPowerOf2() &&
         "Scale should be a constant power of 2");

  CSEMap.InsertNode(N, IP);
  InsertNode(N);
  SDValue V(N, 0);
  NewSDValueDbgMsg(V, "Creating new node: ", this);
  return V;
}

SDValue SelectionDAG::getMaskedScatter(SDVTList VTs, EVT MemVT, const SDLoc &dl,
                                       ArrayRef<SDValue> Ops,
                                       MachineMemOperand *MMO,
                                       ISD::MemIndexType IndexType,
                                       bool IsTrunc) {
  assert(Ops.size() == 6 && "Incompatible number of operands");

  FoldingSetNodeID ID;
  AddNodeIDNode(ID, ISD::MSCATTER, VTs, Ops);
  ID.AddInteger(MemVT.getRawBits());
  ID.AddInteger(getSyntheticNodeSubclassData<MaskedScatterSDNode>(
      dl.getIROrder(), VTs, MemVT, MMO, IndexType, IsTrunc));
  ID.AddInteger(MMO->getPointerInfo().getAddrSpace());
  ID.AddInteger(MMO->getFlags());
  void *IP = nullptr;
  if (SDNode *E = FindNodeOrInsertPos(ID, dl, IP)) {
    cast<MaskedScatterSDNode>(E)->refineAlignment(MMO);
    return SDValue(E, 0);
  }

  auto *N = newSDNode<MaskedScatterSDNode>(dl.getIROrder(), dl.getDebugLoc(),
                                           VTs, MemVT, MMO, IndexType, IsTrunc);
  createOperands(N, Ops);

  assert(N->getMask().getValueType().getVectorElementCount() ==
             N->getValue().getValueType().getVectorElementCount() &&
         "Vector width mismatch between mask and data");
  assert(
      N->getIndex().getValueType().getVectorElementCount().isScalable() ==
          N->getValue().getValueType().getVectorElementCount().isScalable() &&
      "Scalable flags of index and data do not match");
  assert(ElementCount::isKnownGE(
             N->getIndex().getValueType().getVectorElementCount(),
             N->getValue().getValueType().getVectorElementCount()) &&
         "Vector width mismatch between index and data");
  assert(isa<ConstantSDNode>(N->getScale()) &&
         N->getScale()->getAsAPIntVal().isPowerOf2() &&
         "Scale should be a constant power of 2");

  CSEMap.InsertNode(N, IP);
  InsertNode(N);
  SDValue V(N, 0);
  NewSDValueDbgMsg(V, "Creating new node: ", this);
  return V;
}

SDValue SelectionDAG::getMaskedHistogram(SDVTList VTs, EVT MemVT,
                                         const SDLoc &dl, ArrayRef<SDValue> Ops,
                                         MachineMemOperand *MMO,
                                         ISD::MemIndexType IndexType) {
  assert(Ops.size() == 7 && "Incompatible number of operands");

  FoldingSetNodeID ID;
  AddNodeIDNode(ID, ISD::EXPERIMENTAL_VECTOR_HISTOGRAM, VTs, Ops);
  ID.AddInteger(MemVT.getRawBits());
  ID.AddInteger(getSyntheticNodeSubclassData<MaskedHistogramSDNode>(
      dl.getIROrder(), VTs, MemVT, MMO, IndexType));
  ID.AddInteger(MMO->getPointerInfo().getAddrSpace());
  ID.AddInteger(MMO->getFlags());
  void *IP = nullptr;
  if (SDNode *E = FindNodeOrInsertPos(ID, dl, IP)) {
    cast<MaskedGatherSDNode>(E)->refineAlignment(MMO);
    return SDValue(E, 0);
  }

  auto *N = newSDNode<MaskedHistogramSDNode>(dl.getIROrder(), dl.getDebugLoc(),
                                             VTs, MemVT, MMO, IndexType);
  createOperands(N, Ops);

  assert(N->getMask().getValueType().getVectorElementCount() ==
             N->getIndex().getValueType().getVectorElementCount() &&
         "Vector width mismatch between mask and data");
  assert(isa<ConstantSDNode>(N->getScale()) &&
         N->getScale()->getAsAPIntVal().isPowerOf2() &&
         "Scale should be a constant power of 2");
  assert(N->getInc().getValueType().isInteger() && "Non integer update value");

  CSEMap.InsertNode(N, IP);
  InsertNode(N);
  SDValue V(N, 0);
  NewSDValueDbgMsg(V, "Creating new node: ", this);
  return V;
}

SDValue SelectionDAG::getGetFPEnv(SDValue Chain, const SDLoc &dl, SDValue Ptr,
                                  EVT MemVT, MachineMemOperand *MMO) {
  assert(Chain.getValueType() == MVT::Other && "Invalid chain type");
  SDVTList VTs = getVTList(MVT::Other);
  SDValue Ops[] = {Chain, Ptr};
  FoldingSetNodeID ID;
  AddNodeIDNode(ID, ISD::GET_FPENV_MEM, VTs, Ops);
  ID.AddInteger(MemVT.getRawBits());
  ID.AddInteger(getSyntheticNodeSubclassData<FPStateAccessSDNode>(
      ISD::GET_FPENV_MEM, dl.getIROrder(), VTs, MemVT, MMO));
  ID.AddInteger(MMO->getPointerInfo().getAddrSpace());
  ID.AddInteger(MMO->getFlags());
  void *IP = nullptr;
  if (SDNode *E = FindNodeOrInsertPos(ID, dl, IP))
    return SDValue(E, 0);

  auto *N = newSDNode<FPStateAccessSDNode>(ISD::GET_FPENV_MEM, dl.getIROrder(),
                                           dl.getDebugLoc(), VTs, MemVT, MMO);
  createOperands(N, Ops);

  CSEMap.InsertNode(N, IP);
  InsertNode(N);
  SDValue V(N, 0);
  NewSDValueDbgMsg(V, "Creating new node: ", this);
  return V;
}

SDValue SelectionDAG::getSetFPEnv(SDValue Chain, const SDLoc &dl, SDValue Ptr,
                                  EVT MemVT, MachineMemOperand *MMO) {
  assert(Chain.getValueType() == MVT::Other && "Invalid chain type");
  SDVTList VTs = getVTList(MVT::Other);
  SDValue Ops[] = {Chain, Ptr};
  FoldingSetNodeID ID;
  AddNodeIDNode(ID, ISD::SET_FPENV_MEM, VTs, Ops);
  ID.AddInteger(MemVT.getRawBits());
  ID.AddInteger(getSyntheticNodeSubclassData<FPStateAccessSDNode>(
      ISD::SET_FPENV_MEM, dl.getIROrder(), VTs, MemVT, MMO));
  ID.AddInteger(MMO->getPointerInfo().getAddrSpace());
  ID.AddInteger(MMO->getFlags());
  void *IP = nullptr;
  if (SDNode *E = FindNodeOrInsertPos(ID, dl, IP))
    return SDValue(E, 0);

  auto *N = newSDNode<FPStateAccessSDNode>(ISD::SET_FPENV_MEM, dl.getIROrder(),
                                           dl.getDebugLoc(), VTs, MemVT, MMO);
  createOperands(N, Ops);

  CSEMap.InsertNode(N, IP);
  InsertNode(N);
  SDValue V(N, 0);
  NewSDValueDbgMsg(V, "Creating new node: ", this);
  return V;
}

SDValue SelectionDAG::simplifySelect(SDValue Cond, SDValue T, SDValue F) {
  // select undef, T, F --> T (if T is a constant), otherwise F
  // select, ?, undef, F --> F
  // select, ?, T, undef --> T
  if (Cond.isUndef())
    return isConstantValueOfAnyType(T) ? T : F;
  if (T.isUndef())
    return F;
  if (F.isUndef())
    return T;

  // select true, T, F --> T
  // select false, T, F --> F
  if (auto C = isBoolConstant(Cond))
    return *C ? T : F;

  // select ?, T, T --> T
  if (T == F)
    return T;

  return SDValue();
}

SDValue SelectionDAG::simplifyShift(SDValue X, SDValue Y) {
  // shift undef, Y --> 0 (can always assume that the undef value is 0)
  if (X.isUndef())
    return getConstant(0, SDLoc(X.getNode()), X.getValueType());
  // shift X, undef --> undef (because it may shift by the bitwidth)
  if (Y.isUndef())
    return getUNDEF(X.getValueType());

  // shift 0, Y --> 0
  // shift X, 0 --> X
  if (isNullOrNullSplat(X) || isNullOrNullSplat(Y))
    return X;

  // shift X, C >= bitwidth(X) --> undef
  // All vector elements must be too big (or undef) to avoid partial undefs.
  auto isShiftTooBig = [X](ConstantSDNode *Val) {
    return !Val || Val->getAPIntValue().uge(X.getScalarValueSizeInBits());
  };
  if (ISD::matchUnaryPredicate(Y, isShiftTooBig, true))
    return getUNDEF(X.getValueType());

  // shift i1/vXi1 X, Y --> X (any non-zero shift amount is undefined).
  if (X.getValueType().getScalarType() == MVT::i1)
    return X;

  return SDValue();
}

SDValue SelectionDAG::simplifyFPBinop(unsigned Opcode, SDValue X, SDValue Y,
                                      SDNodeFlags Flags) {
  // If this operation has 'nnan' or 'ninf' and at least 1 disallowed operand
  // (an undef operand can be chosen to be Nan/Inf), then the result of this
  // operation is poison. That result can be relaxed to undef.
  ConstantFPSDNode *XC = isConstOrConstSplatFP(X, /* AllowUndefs */ true);
  ConstantFPSDNode *YC = isConstOrConstSplatFP(Y, /* AllowUndefs */ true);
  bool HasNan = (XC && XC->getValueAPF().isNaN()) ||
                (YC && YC->getValueAPF().isNaN());
  bool HasInf = (XC && XC->getValueAPF().isInfinity()) ||
                (YC && YC->getValueAPF().isInfinity());

  if (Flags.hasNoNaNs() && (HasNan || X.isUndef() || Y.isUndef()))
    return getUNDEF(X.getValueType());

  if (Flags.hasNoInfs() && (HasInf || X.isUndef() || Y.isUndef()))
    return getUNDEF(X.getValueType());

  if (!YC)
    return SDValue();

  // X + -0.0 --> X
  if (Opcode == ISD::FADD)
    if (YC->getValueAPF().isNegZero())
      return X;

  // X - +0.0 --> X
  if (Opcode == ISD::FSUB)
    if (YC->getValueAPF().isPosZero())
      return X;

  // X * 1.0 --> X
  // X / 1.0 --> X
  if (Opcode == ISD::FMUL || Opcode == ISD::FDIV)
    if (YC->getValueAPF().isExactlyValue(1.0))
      return X;

  // X * 0.0 --> 0.0
  if (Opcode == ISD::FMUL && Flags.hasNoNaNs() && Flags.hasNoSignedZeros())
    if (YC->getValueAPF().isZero())
      return getConstantFP(0.0, SDLoc(Y), Y.getValueType());

  return SDValue();
}

SDValue SelectionDAG::getVAArg(EVT VT, const SDLoc &dl, SDValue Chain,
                               SDValue Ptr, SDValue SV, unsigned Align) {
  SDValue Ops[] = { Chain, Ptr, SV, getTargetConstant(Align, dl, MVT::i32) };
  return getNode(ISD::VAARG, dl, getVTList(VT, MVT::Other), Ops);
}

SDValue SelectionDAG::getNode(unsigned Opcode, const SDLoc &DL, EVT VT,
                              ArrayRef<SDUse> Ops) {
  switch (Ops.size()) {
  case 0: return getNode(Opcode, DL, VT);
  case 1: return getNode(Opcode, DL, VT, Ops[0].get());
  case 2: return getNode(Opcode, DL, VT, Ops[0], Ops[1]);
  case 3: return getNode(Opcode, DL, VT, Ops[0], Ops[1], Ops[2]);
  default: break;
  }

  // Copy from an SDUse array into an SDValue array for use with
  // the regular getNode logic.
  SmallVector<SDValue, 8> NewOps(Ops);
  return getNode(Opcode, DL, VT, NewOps);
}

SDValue SelectionDAG::getNode(unsigned Opcode, const SDLoc &DL, EVT VT,
                              ArrayRef<SDValue> Ops) {
  SDNodeFlags Flags;
  if (Inserter)
    Flags = Inserter->getFlags();
  return getNode(Opcode, DL, VT, Ops, Flags);
}

SDValue SelectionDAG::getNode(unsigned Opcode, const SDLoc &DL, EVT VT,
                              ArrayRef<SDValue> Ops, const SDNodeFlags Flags) {
  unsigned NumOps = Ops.size();
  switch (NumOps) {
  case 0: return getNode(Opcode, DL, VT);
  case 1: return getNode(Opcode, DL, VT, Ops[0], Flags);
  case 2: return getNode(Opcode, DL, VT, Ops[0], Ops[1], Flags);
  case 3: return getNode(Opcode, DL, VT, Ops[0], Ops[1], Ops[2], Flags);
  default: break;
  }

#ifndef NDEBUG
  for (const auto &Op : Ops)
    assert(Op.getOpcode() != ISD::DELETED_NODE &&
           "Operand is DELETED_NODE!");
#endif

  switch (Opcode) {
  default: break;
  case ISD::BUILD_VECTOR:
    // Attempt to simplify BUILD_VECTOR.
    if (SDValue V = FoldBUILD_VECTOR(DL, VT, Ops, *this))
      return V;
    break;
  case ISD::CONCAT_VECTORS:
    if (SDValue V = foldCONCAT_VECTORS(DL, VT, Ops, *this))
      return V;
    break;
  case ISD::SELECT_CC:
    assert(NumOps == 5 && "SELECT_CC takes 5 operands!");
    assert(Ops[0].getValueType() == Ops[1].getValueType() &&
           "LHS and RHS of condition must have same type!");
    assert(Ops[2].getValueType() == Ops[3].getValueType() &&
           "True and False arms of SelectCC must have same type!");
    assert(Ops[2].getValueType() == VT &&
           "select_cc node must be of same type as true and false value!");
    assert((!Ops[0].getValueType().isVector() ||
            Ops[0].getValueType().getVectorElementCount() ==
                VT.getVectorElementCount()) &&
           "Expected select_cc with vector result to have the same sized "
           "comparison type!");
    break;
  case ISD::BR_CC:
    assert(NumOps == 5 && "BR_CC takes 5 operands!");
    assert(Ops[2].getValueType() == Ops[3].getValueType() &&
           "LHS/RHS of comparison should match types!");
    break;
  case ISD::VP_ADD:
  case ISD::VP_SUB:
    // If it is VP_ADD/VP_SUB mask operation then turn it to VP_XOR
    if (VT.getScalarType() == MVT::i1)
      Opcode = ISD::VP_XOR;
    break;
  case ISD::VP_MUL:
    // If it is VP_MUL mask operation then turn it to VP_AND
    if (VT.getScalarType() == MVT::i1)
      Opcode = ISD::VP_AND;
    break;
  case ISD::VP_REDUCE_MUL:
    // If it is VP_REDUCE_MUL mask operation then turn it to VP_REDUCE_AND
    if (VT == MVT::i1)
      Opcode = ISD::VP_REDUCE_AND;
    break;
  case ISD::VP_REDUCE_ADD:
    // If it is VP_REDUCE_ADD mask operation then turn it to VP_REDUCE_XOR
    if (VT == MVT::i1)
      Opcode = ISD::VP_REDUCE_XOR;
    break;
  case ISD::VP_REDUCE_SMAX:
  case ISD::VP_REDUCE_UMIN:
    // If it is VP_REDUCE_SMAX/VP_REDUCE_UMIN mask operation then turn it to
    // VP_REDUCE_AND.
    if (VT == MVT::i1)
      Opcode = ISD::VP_REDUCE_AND;
    break;
  case ISD::VP_REDUCE_SMIN:
  case ISD::VP_REDUCE_UMAX:
    // If it is VP_REDUCE_SMIN/VP_REDUCE_UMAX mask operation then turn it to
    // VP_REDUCE_OR.
    if (VT == MVT::i1)
      Opcode = ISD::VP_REDUCE_OR;
    break;
  }

  // Memoize nodes.
  SDNode *N;
  SDVTList VTs = getVTList(VT);

  if (VT != MVT::Glue) {
    FoldingSetNodeID ID;
    AddNodeIDNode(ID, Opcode, VTs, Ops);
    void *IP = nullptr;

    if (SDNode *E = FindNodeOrInsertPos(ID, DL, IP)) {
      E->intersectFlagsWith(Flags);
      return SDValue(E, 0);
    }

    N = newSDNode<SDNode>(Opcode, DL.getIROrder(), DL.getDebugLoc(), VTs);
    createOperands(N, Ops);

    CSEMap.InsertNode(N, IP);
  } else {
    N = newSDNode<SDNode>(Opcode, DL.getIROrder(), DL.getDebugLoc(), VTs);
    createOperands(N, Ops);
  }

  N->setFlags(Flags);
  InsertNode(N);
  SDValue V(N, 0);
  NewSDValueDbgMsg(V, "Creating new node: ", this);
  return V;
}

SDValue SelectionDAG::getNode(unsigned Opcode, const SDLoc &DL,
                              ArrayRef<EVT> ResultTys, ArrayRef<SDValue> Ops) {
  SDNodeFlags Flags;
  if (Inserter)
    Flags = Inserter->getFlags();
  return getNode(Opcode, DL, getVTList(ResultTys), Ops, Flags);
}

SDValue SelectionDAG::getNode(unsigned Opcode, const SDLoc &DL,
                              ArrayRef<EVT> ResultTys, ArrayRef<SDValue> Ops,
                              const SDNodeFlags Flags) {
  return getNode(Opcode, DL, getVTList(ResultTys), Ops, Flags);
}

SDValue SelectionDAG::getNode(unsigned Opcode, const SDLoc &DL, SDVTList VTList,
                              ArrayRef<SDValue> Ops) {
  SDNodeFlags Flags;
  if (Inserter)
    Flags = Inserter->getFlags();
  return getNode(Opcode, DL, VTList, Ops, Flags);
}

SDValue SelectionDAG::getNode(unsigned Opcode, const SDLoc &DL, SDVTList VTList,
                              ArrayRef<SDValue> Ops, const SDNodeFlags Flags) {
  if (VTList.NumVTs == 1)
    return getNode(Opcode, DL, VTList.VTs[0], Ops, Flags);

#ifndef NDEBUG
  for (const auto &Op : Ops)
    assert(Op.getOpcode() != ISD::DELETED_NODE &&
           "Operand is DELETED_NODE!");
#endif

  switch (Opcode) {
  case ISD::SADDO:
  case ISD::UADDO:
  case ISD::SSUBO:
  case ISD::USUBO: {
    assert(VTList.NumVTs == 2 && Ops.size() == 2 &&
           "Invalid add/sub overflow op!");
    assert(VTList.VTs[0].isInteger() && VTList.VTs[1].isInteger() &&
           Ops[0].getValueType() == Ops[1].getValueType() &&
           Ops[0].getValueType() == VTList.VTs[0] &&
           "Binary operator types must match!");
    SDValue N1 = Ops[0], N2 = Ops[1];
    canonicalizeCommutativeBinop(Opcode, N1, N2);

    // (X +- 0) -> X with zero-overflow.
    ConstantSDNode *N2CV = isConstOrConstSplat(N2, /*AllowUndefs*/ false,
                                               /*AllowTruncation*/ true);
    if (N2CV && N2CV->isZero()) {
      SDValue ZeroOverFlow = getConstant(0, DL, VTList.VTs[1]);
      return getNode(ISD::MERGE_VALUES, DL, VTList, {N1, ZeroOverFlow}, Flags);
    }

    if (VTList.VTs[0].getScalarType() == MVT::i1 &&
        VTList.VTs[1].getScalarType() == MVT::i1) {
      SDValue F1 = getFreeze(N1);
      SDValue F2 = getFreeze(N2);
      // {vXi1,vXi1} (u/s)addo(vXi1 x, vXi1y) -> {xor(x,y),and(x,y)}
      if (Opcode == ISD::UADDO || Opcode == ISD::SADDO)
        return getNode(ISD::MERGE_VALUES, DL, VTList,
                       {getNode(ISD::XOR, DL, VTList.VTs[0], F1, F2),
                        getNode(ISD::AND, DL, VTList.VTs[1], F1, F2)},
                       Flags);
      // {vXi1,vXi1} (u/s)subo(vXi1 x, vXi1y) -> {xor(x,y),and(~x,y)}
      if (Opcode == ISD::USUBO || Opcode == ISD::SSUBO) {
        SDValue NotF1 = getNOT(DL, F1, VTList.VTs[0]);
        return getNode(ISD::MERGE_VALUES, DL, VTList,
                       {getNode(ISD::XOR, DL, VTList.VTs[0], F1, F2),
                        getNode(ISD::AND, DL, VTList.VTs[1], NotF1, F2)},
                       Flags);
      }
    }
    break;
  }
  case ISD::SADDO_CARRY:
  case ISD::UADDO_CARRY:
  case ISD::SSUBO_CARRY:
  case ISD::USUBO_CARRY:
    assert(VTList.NumVTs == 2 && Ops.size() == 3 &&
           "Invalid add/sub overflow op!");
    assert(VTList.VTs[0].isInteger() && VTList.VTs[1].isInteger() &&
           Ops[0].getValueType() == Ops[1].getValueType() &&
           Ops[0].getValueType() == VTList.VTs[0] &&
           Ops[2].getValueType() == VTList.VTs[1] &&
           "Binary operator types must match!");
    break;
  case ISD::SMUL_LOHI:
  case ISD::UMUL_LOHI: {
    assert(VTList.NumVTs == 2 && Ops.size() == 2 && "Invalid mul lo/hi op!");
    assert(VTList.VTs[0].isInteger() && VTList.VTs[0] == VTList.VTs[1] &&
           VTList.VTs[0] == Ops[0].getValueType() &&
           VTList.VTs[0] == Ops[1].getValueType() &&
           "Binary operator types must match!");
    // Constant fold.
    ConstantSDNode *LHS = dyn_cast<ConstantSDNode>(Ops[0]);
    ConstantSDNode *RHS = dyn_cast<ConstantSDNode>(Ops[1]);
    if (LHS && RHS) {
      unsigned Width = VTList.VTs[0].getScalarSizeInBits();
      unsigned OutWidth = Width * 2;
      APInt Val = LHS->getAPIntValue();
      APInt Mul = RHS->getAPIntValue();
      if (Opcode == ISD::SMUL_LOHI) {
        Val = Val.sext(OutWidth);
        Mul = Mul.sext(OutWidth);
      } else {
        Val = Val.zext(OutWidth);
        Mul = Mul.zext(OutWidth);
      }
      Val *= Mul;

      SDValue Hi =
          getConstant(Val.extractBits(Width, Width), DL, VTList.VTs[0]);
      SDValue Lo = getConstant(Val.trunc(Width), DL, VTList.VTs[0]);
      return getNode(ISD::MERGE_VALUES, DL, VTList, {Lo, Hi}, Flags);
    }
    break;
  }
  case ISD::FFREXP: {
    assert(VTList.NumVTs == 2 && Ops.size() == 1 && "Invalid ffrexp op!");
    assert(VTList.VTs[0].isFloatingPoint() && VTList.VTs[1].isInteger() &&
           VTList.VTs[0] == Ops[0].getValueType() && "frexp type mismatch");

    if (const ConstantFPSDNode *C = dyn_cast<ConstantFPSDNode>(Ops[0])) {
      int FrexpExp;
      APFloat FrexpMant =
          frexp(C->getValueAPF(), FrexpExp, APFloat::rmNearestTiesToEven);
      SDValue Result0 = getConstantFP(FrexpMant, DL, VTList.VTs[0]);
      SDValue Result1 =
          getConstant(FrexpMant.isFinite() ? FrexpExp : 0, DL, VTList.VTs[1]);
      return getNode(ISD::MERGE_VALUES, DL, VTList, {Result0, Result1}, Flags);
    }

    break;
  }
  case ISD::STRICT_FP_EXTEND:
    assert(VTList.NumVTs == 2 && Ops.size() == 2 &&
           "Invalid STRICT_FP_EXTEND!");
    assert(VTList.VTs[0].isFloatingPoint() &&
           Ops[1].getValueType().isFloatingPoint() && "Invalid FP cast!");
    assert(VTList.VTs[0].isVector() == Ops[1].getValueType().isVector() &&
           "STRICT_FP_EXTEND result type should be vector iff the operand "
           "type is vector!");
    assert((!VTList.VTs[0].isVector() ||
            VTList.VTs[0].getVectorElementCount() ==
                Ops[1].getValueType().getVectorElementCount()) &&
           "Vector element count mismatch!");
    assert(Ops[1].getValueType().bitsLT(VTList.VTs[0]) &&
           "Invalid fpext node, dst <= src!");
    break;
  case ISD::STRICT_FP_ROUND:
    assert(VTList.NumVTs == 2 && Ops.size() == 3 && "Invalid STRICT_FP_ROUND!");
    assert(VTList.VTs[0].isVector() == Ops[1].getValueType().isVector() &&
           "STRICT_FP_ROUND result type should be vector iff the operand "
           "type is vector!");
    assert((!VTList.VTs[0].isVector() ||
            VTList.VTs[0].getVectorElementCount() ==
                Ops[1].getValueType().getVectorElementCount()) &&
           "Vector element count mismatch!");
    assert(VTList.VTs[0].isFloatingPoint() &&
           Ops[1].getValueType().isFloatingPoint() &&
           VTList.VTs[0].bitsLT(Ops[1].getValueType()) &&
           Ops[2].getOpcode() == ISD::TargetConstant &&
           (Ops[2]->getAsZExtVal() == 0 || Ops[2]->getAsZExtVal() == 1) &&
           "Invalid STRICT_FP_ROUND!");
    break;
  }

  // Memoize the node unless it returns a glue result.
  SDNode *N;
  if (VTList.VTs[VTList.NumVTs-1] != MVT::Glue) {
    FoldingSetNodeID ID;
    AddNodeIDNode(ID, Opcode, VTList, Ops);
    void *IP = nullptr;
    if (SDNode *E = FindNodeOrInsertPos(ID, DL, IP)) {
      E->intersectFlagsWith(Flags);
      return SDValue(E, 0);
    }

    N = newSDNode<SDNode>(Opcode, DL.getIROrder(), DL.getDebugLoc(), VTList);
    createOperands(N, Ops);
    CSEMap.InsertNode(N, IP);
  } else {
    N = newSDNode<SDNode>(Opcode, DL.getIROrder(), DL.getDebugLoc(), VTList);
    createOperands(N, Ops);
  }

  N->setFlags(Flags);
  InsertNode(N);
  SDValue V(N, 0);
  NewSDValueDbgMsg(V, "Creating new node: ", this);
  return V;
}

SDValue SelectionDAG::getNode(unsigned Opcode, const SDLoc &DL,
                              SDVTList VTList) {
  return getNode(Opcode, DL, VTList, ArrayRef<SDValue>());
}

SDValue SelectionDAG::getNode(unsigned Opcode, const SDLoc &DL, SDVTList VTList,
                              SDValue N1) {
  SDValue Ops[] = { N1 };
  return getNode(Opcode, DL, VTList, Ops);
}

SDValue SelectionDAG::getNode(unsigned Opcode, const SDLoc &DL, SDVTList VTList,
                              SDValue N1, SDValue N2) {
  SDValue Ops[] = { N1, N2 };
  return getNode(Opcode, DL, VTList, Ops);
}

SDValue SelectionDAG::getNode(unsigned Opcode, const SDLoc &DL, SDVTList VTList,
                              SDValue N1, SDValue N2, SDValue N3) {
  SDValue Ops[] = { N1, N2, N3 };
  return getNode(Opcode, DL, VTList, Ops);
}

SDValue SelectionDAG::getNode(unsigned Opcode, const SDLoc &DL, SDVTList VTList,
                              SDValue N1, SDValue N2, SDValue N3, SDValue N4) {
  SDValue Ops[] = { N1, N2, N3, N4 };
  return getNode(Opcode, DL, VTList, Ops);
}

SDValue SelectionDAG::getNode(unsigned Opcode, const SDLoc &DL, SDVTList VTList,
                              SDValue N1, SDValue N2, SDValue N3, SDValue N4,
                              SDValue N5) {
  SDValue Ops[] = { N1, N2, N3, N4, N5 };
  return getNode(Opcode, DL, VTList, Ops);
}

SDVTList SelectionDAG::getVTList(EVT VT) {
  if (!VT.isExtended())
    return makeVTList(SDNode::getValueTypeList(VT.getSimpleVT()), 1);

  return makeVTList(&(*EVTs.insert(VT).first), 1);
}

SDVTList SelectionDAG::getVTList(EVT VT1, EVT VT2) {
  FoldingSetNodeID ID;
  ID.AddInteger(2U);
  ID.AddInteger(VT1.getRawBits());
  ID.AddInteger(VT2.getRawBits());

  void *IP = nullptr;
  SDVTListNode *Result = VTListMap.FindNodeOrInsertPos(ID, IP);
  if (!Result) {
    EVT *Array = Allocator.Allocate<EVT>(2);
    Array[0] = VT1;
    Array[1] = VT2;
    Result = new (Allocator) SDVTListNode(ID.Intern(Allocator), Array, 2);
    VTListMap.InsertNode(Result, IP);
  }
  return Result->getSDVTList();
}

SDVTList SelectionDAG::getVTList(EVT VT1, EVT VT2, EVT VT3) {
  FoldingSetNodeID ID;
  ID.AddInteger(3U);
  ID.AddInteger(VT1.getRawBits());
  ID.AddInteger(VT2.getRawBits());
  ID.AddInteger(VT3.getRawBits());

  void *IP = nullptr;
  SDVTListNode *Result = VTListMap.FindNodeOrInsertPos(ID, IP);
  if (!Result) {
    EVT *Array = Allocator.Allocate<EVT>(3);
    Array[0] = VT1;
    Array[1] = VT2;
    Array[2] = VT3;
    Result = new (Allocator) SDVTListNode(ID.Intern(Allocator), Array, 3);
    VTListMap.InsertNode(Result, IP);
  }
  return Result->getSDVTList();
}

SDVTList SelectionDAG::getVTList(EVT VT1, EVT VT2, EVT VT3, EVT VT4) {
  FoldingSetNodeID ID;
  ID.AddInteger(4U);
  ID.AddInteger(VT1.getRawBits());
  ID.AddInteger(VT2.getRawBits());
  ID.AddInteger(VT3.getRawBits());
  ID.AddInteger(VT4.getRawBits());

  void *IP = nullptr;
  SDVTListNode *Result = VTListMap.FindNodeOrInsertPos(ID, IP);
  if (!Result) {
    EVT *Array = Allocator.Allocate<EVT>(4);
    Array[0] = VT1;
    Array[1] = VT2;
    Array[2] = VT3;
    Array[3] = VT4;
    Result = new (Allocator) SDVTListNode(ID.Intern(Allocator), Array, 4);
    VTListMap.InsertNode(Result, IP);
  }
  return Result->getSDVTList();
}

SDVTList SelectionDAG::getVTList(ArrayRef<EVT> VTs) {
  unsigned NumVTs = VTs.size();
  FoldingSetNodeID ID;
  ID.AddInteger(NumVTs);
  for (unsigned index = 0; index < NumVTs; index++) {
    ID.AddInteger(VTs[index].getRawBits());
  }

  void *IP = nullptr;
  SDVTListNode *Result = VTListMap.FindNodeOrInsertPos(ID, IP);
  if (!Result) {
    EVT *Array = Allocator.Allocate<EVT>(NumVTs);
    llvm::copy(VTs, Array);
    Result = new (Allocator) SDVTListNode(ID.Intern(Allocator), Array, NumVTs);
    VTListMap.InsertNode(Result, IP);
  }
  return Result->getSDVTList();
}


/// UpdateNodeOperands - *Mutate* the specified node in-place to have the
/// specified operands.  If the resultant node already exists in the DAG,
/// this does not modify the specified node, instead it returns the node that
/// already exists.  If the resultant node does not exist in the DAG, the
/// input node is returned.  As a degenerate case, if you specify the same
/// input operands as the node already has, the input node is returned.
SDNode *SelectionDAG::UpdateNodeOperands(SDNode *N, SDValue Op) {
  assert(N->getNumOperands() == 1 && "Update with wrong number of operands");

  // Check to see if there is no change.
  if (Op == N->getOperand(0)) return N;

  // See if the modified node already exists.
  void *InsertPos = nullptr;
  if (SDNode *Existing = FindModifiedNodeSlot(N, Op, InsertPos))
    return Existing;

  // Nope it doesn't.  Remove the node from its current place in the maps.
  if (InsertPos)
    if (!RemoveNodeFromCSEMaps(N))
      InsertPos = nullptr;

  // Now we update the operands.
  N->OperandList[0].set(Op);

  updateDivergence(N);
  // If this gets put into a CSE map, add it.
  if (InsertPos) CSEMap.InsertNode(N, InsertPos);
  return N;
}

SDNode *SelectionDAG::UpdateNodeOperands(SDNode *N, SDValue Op1, SDValue Op2) {
  assert(N->getNumOperands() == 2 && "Update with wrong number of operands");

  // Check to see if there is no change.
  if (Op1 == N->getOperand(0) && Op2 == N->getOperand(1))
    return N;   // No operands changed, just return the input node.

  // See if the modified node already exists.
  void *InsertPos = nullptr;
  if (SDNode *Existing = FindModifiedNodeSlot(N, Op1, Op2, InsertPos))
    return Existing;

  // Nope it doesn't.  Remove the node from its current place in the maps.
  if (InsertPos)
    if (!RemoveNodeFromCSEMaps(N))
      InsertPos = nullptr;

  // Now we update the operands.
  if (N->OperandList[0] != Op1)
    N->OperandList[0].set(Op1);
  if (N->OperandList[1] != Op2)
    N->OperandList[1].set(Op2);

  updateDivergence(N);
  // If this gets put into a CSE map, add it.
  if (InsertPos) CSEMap.InsertNode(N, InsertPos);
  return N;
}

SDNode *SelectionDAG::
UpdateNodeOperands(SDNode *N, SDValue Op1, SDValue Op2, SDValue Op3) {
  SDValue Ops[] = { Op1, Op2, Op3 };
  return UpdateNodeOperands(N, Ops);
}

SDNode *SelectionDAG::
UpdateNodeOperands(SDNode *N, SDValue Op1, SDValue Op2,
                   SDValue Op3, SDValue Op4) {
  SDValue Ops[] = { Op1, Op2, Op3, Op4 };
  return UpdateNodeOperands(N, Ops);
}

SDNode *SelectionDAG::
UpdateNodeOperands(SDNode *N, SDValue Op1, SDValue Op2,
                   SDValue Op3, SDValue Op4, SDValue Op5) {
  SDValue Ops[] = { Op1, Op2, Op3, Op4, Op5 };
  return UpdateNodeOperands(N, Ops);
}

SDNode *SelectionDAG::
UpdateNodeOperands(SDNode *N, ArrayRef<SDValue> Ops) {
  unsigned NumOps = Ops.size();
  assert(N->getNumOperands() == NumOps &&
         "Update with wrong number of operands");

  // If no operands changed just return the input node.
  if (std::equal(Ops.begin(), Ops.end(), N->op_begin()))
    return N;

  // See if the modified node already exists.
  void *InsertPos = nullptr;
  if (SDNode *Existing = FindModifiedNodeSlot(N, Ops, InsertPos))
    return Existing;

  // Nope it doesn't.  Remove the node from its current place in the maps.
  if (InsertPos)
    if (!RemoveNodeFromCSEMaps(N))
      InsertPos = nullptr;

  // Now we update the operands.
  for (unsigned i = 0; i != NumOps; ++i)
    if (N->OperandList[i] != Ops[i])
      N->OperandList[i].set(Ops[i]);

  updateDivergence(N);
  // If this gets put into a CSE map, add it.
  if (InsertPos) CSEMap.InsertNode(N, InsertPos);
  return N;
}

/// DropOperands - Release the operands and set this node to have
/// zero operands.
void SDNode::DropOperands() {
  // Unlike the code in MorphNodeTo that does this, we don't need to
  // watch for dead nodes here.
  for (op_iterator I = op_begin(), E = op_end(); I != E; ) {
    SDUse &Use = *I++;
    Use.set(SDValue());
  }
}

void SelectionDAG::setNodeMemRefs(MachineSDNode *N,
                                  ArrayRef<MachineMemOperand *> NewMemRefs) {
  if (NewMemRefs.empty()) {
    N->clearMemRefs();
    return;
  }

  // Check if we can avoid allocating by storing a single reference directly.
  if (NewMemRefs.size() == 1) {
    N->MemRefs = NewMemRefs[0];
    N->NumMemRefs = 1;
    return;
  }

  MachineMemOperand **MemRefsBuffer =
      Allocator.template Allocate<MachineMemOperand *>(NewMemRefs.size());
  llvm::copy(NewMemRefs, MemRefsBuffer);
  N->MemRefs = MemRefsBuffer;
  N->NumMemRefs = static_cast<int>(NewMemRefs.size());
}

/// SelectNodeTo - These are wrappers around MorphNodeTo that accept a
/// machine opcode.
///
SDNode *SelectionDAG::SelectNodeTo(SDNode *N, unsigned MachineOpc,
                                   EVT VT) {
  SDVTList VTs = getVTList(VT);
  return SelectNodeTo(N, MachineOpc, VTs, {});
}

SDNode *SelectionDAG::SelectNodeTo(SDNode *N, unsigned MachineOpc,
                                   EVT VT, SDValue Op1) {
  SDVTList VTs = getVTList(VT);
  SDValue Ops[] = { Op1 };
  return SelectNodeTo(N, MachineOpc, VTs, Ops);
}

SDNode *SelectionDAG::SelectNodeTo(SDNode *N, unsigned MachineOpc,
                                   EVT VT, SDValue Op1,
                                   SDValue Op2) {
  SDVTList VTs = getVTList(VT);
  SDValue Ops[] = { Op1, Op2 };
  return SelectNodeTo(N, MachineOpc, VTs, Ops);
}

SDNode *SelectionDAG::SelectNodeTo(SDNode *N, unsigned MachineOpc,
                                   EVT VT, SDValue Op1,
                                   SDValue Op2, SDValue Op3) {
  SDVTList VTs = getVTList(VT);
  SDValue Ops[] = { Op1, Op2, Op3 };
  return SelectNodeTo(N, MachineOpc, VTs, Ops);
}

SDNode *SelectionDAG::SelectNodeTo(SDNode *N, unsigned MachineOpc,
                                   EVT VT, ArrayRef<SDValue> Ops) {
  SDVTList VTs = getVTList(VT);
  return SelectNodeTo(N, MachineOpc, VTs, Ops);
}

SDNode *SelectionDAG::SelectNodeTo(SDNode *N, unsigned MachineOpc,
                                   EVT VT1, EVT VT2, ArrayRef<SDValue> Ops) {
  SDVTList VTs = getVTList(VT1, VT2);
  return SelectNodeTo(N, MachineOpc, VTs, Ops);
}

SDNode *SelectionDAG::SelectNodeTo(SDNode *N, unsigned MachineOpc,
                                   EVT VT1, EVT VT2) {
  SDVTList VTs = getVTList(VT1, VT2);
  return SelectNodeTo(N, MachineOpc, VTs, {});
}

SDNode *SelectionDAG::SelectNodeTo(SDNode *N, unsigned MachineOpc,
                                   EVT VT1, EVT VT2, EVT VT3,
                                   ArrayRef<SDValue> Ops) {
  SDVTList VTs = getVTList(VT1, VT2, VT3);
  return SelectNodeTo(N, MachineOpc, VTs, Ops);
}

SDNode *SelectionDAG::SelectNodeTo(SDNode *N, unsigned MachineOpc,
                                   EVT VT1, EVT VT2,
                                   SDValue Op1, SDValue Op2) {
  SDVTList VTs = getVTList(VT1, VT2);
  SDValue Ops[] = { Op1, Op2 };
  return SelectNodeTo(N, MachineOpc, VTs, Ops);
}

SDNode *SelectionDAG::SelectNodeTo(SDNode *N, unsigned MachineOpc,
                                   SDVTList VTs,ArrayRef<SDValue> Ops) {
  SDNode *New = MorphNodeTo(N, ~MachineOpc, VTs, Ops);
  // Reset the NodeID to -1.
  New->setNodeId(-1);
  if (New != N) {
    ReplaceAllUsesWith(N, New);
    RemoveDeadNode(N);
  }
  return New;
}

/// UpdateSDLocOnMergeSDNode - If the opt level is -O0 then it throws away
/// the line number information on the merged node since it is not possible to
/// preserve the information that operation is associated with multiple lines.
/// This will make the debugger working better at -O0, were there is a higher
/// probability having other instructions associated with that line.
///
/// For IROrder, we keep the smaller of the two
SDNode *SelectionDAG::UpdateSDLocOnMergeSDNode(SDNode *N, const SDLoc &OLoc) {
  DebugLoc NLoc = N->getDebugLoc();
  if (NLoc && OptLevel == CodeGenOptLevel::None && OLoc.getDebugLoc() != NLoc) {
    N->setDebugLoc(DebugLoc());
  }
  unsigned Order = std::min(N->getIROrder(), OLoc.getIROrder());
  N->setIROrder(Order);
  return N;
}

/// MorphNodeTo - This *mutates* the specified node to have the specified
/// return type, opcode, and operands.
///
/// Note that MorphNodeTo returns the resultant node.  If there is already a
/// node of the specified opcode and operands, it returns that node instead of
/// the current one.  Note that the SDLoc need not be the same.
///
/// Using MorphNodeTo is faster than creating a new node and swapping it in
/// with ReplaceAllUsesWith both because it often avoids allocating a new
/// node, and because it doesn't require CSE recalculation for any of
/// the node's users.
///
/// However, note that MorphNodeTo recursively deletes dead nodes from the DAG.
/// As a consequence it isn't appropriate to use from within the DAG combiner or
/// the legalizer which maintain worklists that would need to be updated when
/// deleting things.
SDNode *SelectionDAG::MorphNodeTo(SDNode *N, unsigned Opc,
                                  SDVTList VTs, ArrayRef<SDValue> Ops) {
  // If an identical node already exists, use it.
  void *IP = nullptr;
  if (VTs.VTs[VTs.NumVTs-1] != MVT::Glue) {
    FoldingSetNodeID ID;
    AddNodeIDNode(ID, Opc, VTs, Ops);
    if (SDNode *ON = FindNodeOrInsertPos(ID, SDLoc(N), IP))
      return UpdateSDLocOnMergeSDNode(ON, SDLoc(N));
  }

  if (!RemoveNodeFromCSEMaps(N))
    IP = nullptr;

  // Start the morphing.
  N->NodeType = Opc;
  N->ValueList = VTs.VTs;
  N->NumValues = VTs.NumVTs;

  // Clear the operands list, updating used nodes to remove this from their
  // use list.  Keep track of any operands that become dead as a result.
  SmallPtrSet<SDNode*, 16> DeadNodeSet;
  for (SDNode::op_iterator I = N->op_begin(), E = N->op_end(); I != E; ) {
    SDUse &Use = *I++;
    SDNode *Used = Use.getNode();
    Use.set(SDValue());
    if (Used->use_empty())
      DeadNodeSet.insert(Used);
  }

  // For MachineNode, initialize the memory references information.
  if (MachineSDNode *MN = dyn_cast<MachineSDNode>(N))
    MN->clearMemRefs();

  // Swap for an appropriately sized array from the recycler.
  removeOperands(N);
  createOperands(N, Ops);

  // Delete any nodes that are still dead after adding the uses for the
  // new operands.
  if (!DeadNodeSet.empty()) {
    SmallVector<SDNode *, 16> DeadNodes;
    for (SDNode *N : DeadNodeSet)
      if (N->use_empty())
        DeadNodes.push_back(N);
    RemoveDeadNodes(DeadNodes);
  }

  if (IP)
    CSEMap.InsertNode(N, IP);   // Memoize the new node.
  return N;
}

SDNode* SelectionDAG::mutateStrictFPToFP(SDNode *Node) {
  unsigned OrigOpc = Node->getOpcode();
  unsigned NewOpc;
  switch (OrigOpc) {
  default:
    llvm_unreachable("mutateStrictFPToFP called with unexpected opcode!");
#define DAG_INSTRUCTION(NAME, NARG, ROUND_MODE, INTRINSIC, DAGN)               \
  case ISD::STRICT_##DAGN: NewOpc = ISD::DAGN; break;
#define CMP_INSTRUCTION(NAME, NARG, ROUND_MODE, INTRINSIC, DAGN)               \
  case ISD::STRICT_##DAGN: NewOpc = ISD::SETCC; break;
#include "llvm/IR/ConstrainedOps.def"
  }

  assert(Node->getNumValues() == 2 && "Unexpected number of results!");

  // We're taking this node out of the chain, so we need to re-link things.
  SDValue InputChain = Node->getOperand(0);
  SDValue OutputChain = SDValue(Node, 1);
  ReplaceAllUsesOfValueWith(OutputChain, InputChain);

  SmallVector<SDValue, 3> Ops;
  for (unsigned i = 1, e = Node->getNumOperands(); i != e; ++i)
    Ops.push_back(Node->getOperand(i));

  SDVTList VTs = getVTList(Node->getValueType(0));
  SDNode *Res = MorphNodeTo(Node, NewOpc, VTs, Ops);

  // MorphNodeTo can operate in two ways: if an existing node with the
  // specified operands exists, it can just return it.  Otherwise, it
  // updates the node in place to have the requested operands.
  if (Res == Node) {
    // If we updated the node in place, reset the node ID.  To the isel,
    // this should be just like a newly allocated machine node.
    Res->setNodeId(-1);
  } else {
    ReplaceAllUsesWith(Node, Res);
    RemoveDeadNode(Node);
  }

  return Res;
}

/// getMachineNode - These are used for target selectors to create a new node
/// with specified return type(s), MachineInstr opcode, and operands.
///
/// Note that getMachineNode returns the resultant node.  If there is already a
/// node of the specified opcode and operands, it returns that node instead of
/// the current one.
MachineSDNode *SelectionDAG::getMachineNode(unsigned Opcode, const SDLoc &dl,
                                            EVT VT) {
  SDVTList VTs = getVTList(VT);
  return getMachineNode(Opcode, dl, VTs, {});
}

MachineSDNode *SelectionDAG::getMachineNode(unsigned Opcode, const SDLoc &dl,
                                            EVT VT, SDValue Op1) {
  SDVTList VTs = getVTList(VT);
  SDValue Ops[] = { Op1 };
  return getMachineNode(Opcode, dl, VTs, Ops);
}

MachineSDNode *SelectionDAG::getMachineNode(unsigned Opcode, const SDLoc &dl,
                                            EVT VT, SDValue Op1, SDValue Op2) {
  SDVTList VTs = getVTList(VT);
  SDValue Ops[] = { Op1, Op2 };
  return getMachineNode(Opcode, dl, VTs, Ops);
}

MachineSDNode *SelectionDAG::getMachineNode(unsigned Opcode, const SDLoc &dl,
                                            EVT VT, SDValue Op1, SDValue Op2,
                                            SDValue Op3) {
  SDVTList VTs = getVTList(VT);
  SDValue Ops[] = { Op1, Op2, Op3 };
  return getMachineNode(Opcode, dl, VTs, Ops);
}

MachineSDNode *SelectionDAG::getMachineNode(unsigned Opcode, const SDLoc &dl,
                                            EVT VT, ArrayRef<SDValue> Ops) {
  SDVTList VTs = getVTList(VT);
  return getMachineNode(Opcode, dl, VTs, Ops);
}

MachineSDNode *SelectionDAG::getMachineNode(unsigned Opcode, const SDLoc &dl,
                                            EVT VT1, EVT VT2, SDValue Op1,
                                            SDValue Op2) {
  SDVTList VTs = getVTList(VT1, VT2);
  SDValue Ops[] = { Op1, Op2 };
  return getMachineNode(Opcode, dl, VTs, Ops);
}

MachineSDNode *SelectionDAG::getMachineNode(unsigned Opcode, const SDLoc &dl,
                                            EVT VT1, EVT VT2, SDValue Op1,
                                            SDValue Op2, SDValue Op3) {
  SDVTList VTs = getVTList(VT1, VT2);
  SDValue Ops[] = { Op1, Op2, Op3 };
  return getMachineNode(Opcode, dl, VTs, Ops);
}

MachineSDNode *SelectionDAG::getMachineNode(unsigned Opcode, const SDLoc &dl,
                                            EVT VT1, EVT VT2,
                                            ArrayRef<SDValue> Ops) {
  SDVTList VTs = getVTList(VT1, VT2);
  return getMachineNode(Opcode, dl, VTs, Ops);
}

MachineSDNode *SelectionDAG::getMachineNode(unsigned Opcode, const SDLoc &dl,
                                            EVT VT1, EVT VT2, EVT VT3,
                                            SDValue Op1, SDValue Op2) {
  SDVTList VTs = getVTList(VT1, VT2, VT3);
  SDValue Ops[] = { Op1, Op2 };
  return getMachineNode(Opcode, dl, VTs, Ops);
}

MachineSDNode *SelectionDAG::getMachineNode(unsigned Opcode, const SDLoc &dl,
                                            EVT VT1, EVT VT2, EVT VT3,
                                            SDValue Op1, SDValue Op2,
                                            SDValue Op3) {
  SDVTList VTs = getVTList(VT1, VT2, VT3);
  SDValue Ops[] = { Op1, Op2, Op3 };
  return getMachineNode(Opcode, dl, VTs, Ops);
}

MachineSDNode *SelectionDAG::getMachineNode(unsigned Opcode, const SDLoc &dl,
                                            EVT VT1, EVT VT2, EVT VT3,
                                            ArrayRef<SDValue> Ops) {
  SDVTList VTs = getVTList(VT1, VT2, VT3);
  return getMachineNode(Opcode, dl, VTs, Ops);
}

MachineSDNode *SelectionDAG::getMachineNode(unsigned Opcode, const SDLoc &dl,
                                            ArrayRef<EVT> ResultTys,
                                            ArrayRef<SDValue> Ops) {
  SDVTList VTs = getVTList(ResultTys);
  return getMachineNode(Opcode, dl, VTs, Ops);
}

MachineSDNode *SelectionDAG::getMachineNode(unsigned Opcode, const SDLoc &DL,
                                            SDVTList VTs,
                                            ArrayRef<SDValue> Ops) {
  bool DoCSE = VTs.VTs[VTs.NumVTs-1] != MVT::Glue;
  MachineSDNode *N;
  void *IP = nullptr;

  if (DoCSE) {
    FoldingSetNodeID ID;
    AddNodeIDNode(ID, ~Opcode, VTs, Ops);
    IP = nullptr;
    if (SDNode *E = FindNodeOrInsertPos(ID, DL, IP)) {
      return cast<MachineSDNode>(UpdateSDLocOnMergeSDNode(E, DL));
    }
  }

  // Allocate a new MachineSDNode.
  N = newSDNode<MachineSDNode>(~Opcode, DL.getIROrder(), DL.getDebugLoc(), VTs);
  createOperands(N, Ops);

  if (DoCSE)
    CSEMap.InsertNode(N, IP);

  InsertNode(N);
  NewSDValueDbgMsg(SDValue(N, 0), "Creating new machine node: ", this);
  return N;
}

/// getTargetExtractSubreg - A convenience function for creating
/// TargetOpcode::EXTRACT_SUBREG nodes.
SDValue SelectionDAG::getTargetExtractSubreg(int SRIdx, const SDLoc &DL, EVT VT,
                                             SDValue Operand) {
  SDValue SRIdxVal = getTargetConstant(SRIdx, DL, MVT::i32);
  SDNode *Subreg = getMachineNode(TargetOpcode::EXTRACT_SUBREG, DL,
                                  VT, Operand, SRIdxVal);
  return SDValue(Subreg, 0);
}

/// getTargetInsertSubreg - A convenience function for creating
/// TargetOpcode::INSERT_SUBREG nodes.
SDValue SelectionDAG::getTargetInsertSubreg(int SRIdx, const SDLoc &DL, EVT VT,
                                            SDValue Operand, SDValue Subreg) {
  SDValue SRIdxVal = getTargetConstant(SRIdx, DL, MVT::i32);
  SDNode *Result = getMachineNode(TargetOpcode::INSERT_SUBREG, DL,
                                  VT, Operand, Subreg, SRIdxVal);
  return SDValue(Result, 0);
}

/// getNodeIfExists - Get the specified node if it's already available, or
/// else return NULL.
SDNode *SelectionDAG::getNodeIfExists(unsigned Opcode, SDVTList VTList,
                                      ArrayRef<SDValue> Ops) {
  SDNodeFlags Flags;
  if (Inserter)
    Flags = Inserter->getFlags();
  return getNodeIfExists(Opcode, VTList, Ops, Flags);
}

SDNode *SelectionDAG::getNodeIfExists(unsigned Opcode, SDVTList VTList,
                                      ArrayRef<SDValue> Ops,
                                      const SDNodeFlags Flags) {
  if (VTList.VTs[VTList.NumVTs - 1] != MVT::Glue) {
    FoldingSetNodeID ID;
    AddNodeIDNode(ID, Opcode, VTList, Ops);
    void *IP = nullptr;
    if (SDNode *E = FindNodeOrInsertPos(ID, SDLoc(), IP)) {
      E->intersectFlagsWith(Flags);
      return E;
    }
  }
  return nullptr;
}

/// doesNodeExist - Check if a node exists without modifying its flags.
bool SelectionDAG::doesNodeExist(unsigned Opcode, SDVTList VTList,
                                 ArrayRef<SDValue> Ops) {
  if (VTList.VTs[VTList.NumVTs - 1] != MVT::Glue) {
    FoldingSetNodeID ID;
    AddNodeIDNode(ID, Opcode, VTList, Ops);
    void *IP = nullptr;
    if (FindNodeOrInsertPos(ID, SDLoc(), IP))
      return true;
  }
  return false;
}

/// getDbgValue - Creates a SDDbgValue node.
///
/// SDNode
SDDbgValue *SelectionDAG::getDbgValue(DIVariable *Var, DIExpression *Expr,
                                      SDNode *N, unsigned R, bool IsIndirect,
                                      const DebugLoc &DL, unsigned O) {
  assert(cast<DILocalVariable>(Var)->isValidLocationForIntrinsic(DL) &&
         "Expected inlined-at fields to agree");
  return new (DbgInfo->getAlloc())
      SDDbgValue(DbgInfo->getAlloc(), Var, Expr, SDDbgOperand::fromNode(N, R),
                 {}, IsIndirect, DL, O,
                 /*IsVariadic=*/false);
}

/// Constant
SDDbgValue *SelectionDAG::getConstantDbgValue(DIVariable *Var,
                                              DIExpression *Expr,
                                              const Value *C,
                                              const DebugLoc &DL, unsigned O) {
  assert(cast<DILocalVariable>(Var)->isValidLocationForIntrinsic(DL) &&
         "Expected inlined-at fields to agree");
  return new (DbgInfo->getAlloc())
      SDDbgValue(DbgInfo->getAlloc(), Var, Expr, SDDbgOperand::fromConst(C), {},
                 /*IsIndirect=*/false, DL, O,
                 /*IsVariadic=*/false);
}

/// FrameIndex
SDDbgValue *SelectionDAG::getFrameIndexDbgValue(DIVariable *Var,
                                                DIExpression *Expr, unsigned FI,
                                                bool IsIndirect,
                                                const DebugLoc &DL,
                                                unsigned O) {
  assert(cast<DILocalVariable>(Var)->isValidLocationForIntrinsic(DL) &&
         "Expected inlined-at fields to agree");
  return getFrameIndexDbgValue(Var, Expr, FI, {}, IsIndirect, DL, O);
}

/// FrameIndex with dependencies
SDDbgValue *SelectionDAG::getFrameIndexDbgValue(DIVariable *Var,
                                                DIExpression *Expr, unsigned FI,
                                                ArrayRef<SDNode *> Dependencies,
                                                bool IsIndirect,
                                                const DebugLoc &DL,
                                                unsigned O) {
  assert(cast<DILocalVariable>(Var)->isValidLocationForIntrinsic(DL) &&
         "Expected inlined-at fields to agree");
  return new (DbgInfo->getAlloc())
      SDDbgValue(DbgInfo->getAlloc(), Var, Expr, SDDbgOperand::fromFrameIdx(FI),
                 Dependencies, IsIndirect, DL, O,
                 /*IsVariadic=*/false);
}

/// VReg
SDDbgValue *SelectionDAG::getVRegDbgValue(DIVariable *Var, DIExpression *Expr,
                                          Register VReg, bool IsIndirect,
                                          const DebugLoc &DL, unsigned O) {
  assert(cast<DILocalVariable>(Var)->isValidLocationForIntrinsic(DL) &&
         "Expected inlined-at fields to agree");
  return new (DbgInfo->getAlloc())
      SDDbgValue(DbgInfo->getAlloc(), Var, Expr, SDDbgOperand::fromVReg(VReg),
                 {}, IsIndirect, DL, O,
                 /*IsVariadic=*/false);
}

SDDbgValue *SelectionDAG::getDbgValueList(DIVariable *Var, DIExpression *Expr,
                                          ArrayRef<SDDbgOperand> Locs,
                                          ArrayRef<SDNode *> Dependencies,
                                          bool IsIndirect, const DebugLoc &DL,
                                          unsigned O, bool IsVariadic) {
  assert(cast<DILocalVariable>(Var)->isValidLocationForIntrinsic(DL) &&
         "Expected inlined-at fields to agree");
  return new (DbgInfo->getAlloc())
      SDDbgValue(DbgInfo->getAlloc(), Var, Expr, Locs, Dependencies, IsIndirect,
                 DL, O, IsVariadic);
}

void SelectionDAG::transferDbgValues(SDValue From, SDValue To,
                                     unsigned OffsetInBits, unsigned SizeInBits,
                                     bool InvalidateDbg) {
  SDNode *FromNode = From.getNode();
  SDNode *ToNode = To.getNode();
  assert(FromNode && ToNode && "Can't modify dbg values");

  // PR35338
  // TODO: assert(From != To && "Redundant dbg value transfer");
  // TODO: assert(FromNode != ToNode && "Intranode dbg value transfer");
  if (From == To || FromNode == ToNode)
    return;

  if (!FromNode->getHasDebugValue())
    return;

  SDDbgOperand FromLocOp =
      SDDbgOperand::fromNode(From.getNode(), From.getResNo());
  SDDbgOperand ToLocOp = SDDbgOperand::fromNode(To.getNode(), To.getResNo());

  SmallVector<SDDbgValue *, 2> ClonedDVs;
  for (SDDbgValue *Dbg : GetDbgValues(FromNode)) {
    if (Dbg->isInvalidated())
      continue;

    // TODO: assert(!Dbg->isInvalidated() && "Transfer of invalid dbg value");

    // Create a new location ops vector that is equal to the old vector, but
    // with each instance of FromLocOp replaced with ToLocOp.
    bool Changed = false;
    auto NewLocOps = Dbg->copyLocationOps();
    std::replace_if(
        NewLocOps.begin(), NewLocOps.end(),
        [&Changed, FromLocOp](const SDDbgOperand &Op) {
          bool Match = Op == FromLocOp;
          Changed |= Match;
          return Match;
        },
        ToLocOp);
    // Ignore this SDDbgValue if we didn't find a matching location.
    if (!Changed)
      continue;

    DIVariable *Var = Dbg->getVariable();
    auto *Expr = Dbg->getExpression();
    // If a fragment is requested, update the expression.
    if (SizeInBits) {
      // When splitting a larger (e.g., sign-extended) value whose
      // lower bits are described with an SDDbgValue, do not attempt
      // to transfer the SDDbgValue to the upper bits.
      if (auto FI = Expr->getFragmentInfo())
        if (OffsetInBits + SizeInBits > FI->SizeInBits)
          continue;
      auto Fragment = DIExpression::createFragmentExpression(Expr, OffsetInBits,
                                                             SizeInBits);
      if (!Fragment)
        continue;
      Expr = *Fragment;
    }

    auto AdditionalDependencies = Dbg->getAdditionalDependencies();
    // Clone the SDDbgValue and move it to To.
    SDDbgValue *Clone = getDbgValueList(
        Var, Expr, NewLocOps, AdditionalDependencies, Dbg->isIndirect(),
        Dbg->getDebugLoc(), std::max(ToNode->getIROrder(), Dbg->getOrder()),
        Dbg->isVariadic());
    ClonedDVs.push_back(Clone);

    if (InvalidateDbg) {
      // Invalidate value and indicate the SDDbgValue should not be emitted.
      Dbg->setIsInvalidated();
      Dbg->setIsEmitted();
    }
  }

  for (SDDbgValue *Dbg : ClonedDVs) {
    assert(is_contained(Dbg->getSDNodes(), ToNode) &&
           "Transferred DbgValues should depend on the new SDNode");
    AddDbgValue(Dbg, false);
  }
}

void SelectionDAG::salvageDebugInfo(SDNode &N) {
  if (!N.getHasDebugValue())
    return;

  auto GetLocationOperand = [](SDNode *Node, unsigned ResNo) {
    if (auto *FISDN = dyn_cast<FrameIndexSDNode>(Node))
      return SDDbgOperand::fromFrameIdx(FISDN->getIndex());
    return SDDbgOperand::fromNode(Node, ResNo);
  };

  SmallVector<SDDbgValue *, 2> ClonedDVs;
  for (auto *DV : GetDbgValues(&N)) {
    if (DV->isInvalidated())
      continue;
    switch (N.getOpcode()) {
    default:
      break;
    case ISD::ADD: {
      SDValue N0 = N.getOperand(0);
      SDValue N1 = N.getOperand(1);
      if (!isa<ConstantSDNode>(N0)) {
        bool RHSConstant = isa<ConstantSDNode>(N1);
        uint64_t Offset;
        if (RHSConstant)
          Offset = N.getConstantOperandVal(1);
        // We are not allowed to turn indirect debug values variadic, so
        // don't salvage those.
        if (!RHSConstant && DV->isIndirect())
          continue;

        // Rewrite an ADD constant node into a DIExpression. Since we are
        // performing arithmetic to compute the variable's *value* in the
        // DIExpression, we need to mark the expression with a
        // DW_OP_stack_value.
        auto *DIExpr = DV->getExpression();
        auto NewLocOps = DV->copyLocationOps();
        bool Changed = false;
        size_t OrigLocOpsSize = NewLocOps.size();
        for (size_t i = 0; i < OrigLocOpsSize; ++i) {
          // We're not given a ResNo to compare against because the whole
          // node is going away. We know that any ISD::ADD only has one
          // result, so we can assume any node match is using the result.
          if (NewLocOps[i].getKind() != SDDbgOperand::SDNODE ||
              NewLocOps[i].getSDNode() != &N)
            continue;
          NewLocOps[i] = GetLocationOperand(N0.getNode(), N0.getResNo());
          if (RHSConstant) {
            SmallVector<uint64_t, 3> ExprOps;
            DIExpression::appendOffset(ExprOps, Offset);
            DIExpr = DIExpression::appendOpsToArg(DIExpr, ExprOps, i, true);
          } else {
            // Convert to a variadic expression (if not already).
            // convertToVariadicExpression() returns a const pointer, so we use
            // a temporary const variable here.
            const auto *TmpDIExpr =
                DIExpression::convertToVariadicExpression(DIExpr);
            SmallVector<uint64_t, 3> ExprOps;
            ExprOps.push_back(dwarf::DW_OP_LLVM_arg);
            ExprOps.push_back(NewLocOps.size());
            ExprOps.push_back(dwarf::DW_OP_plus);
            SDDbgOperand RHS =
                SDDbgOperand::fromNode(N1.getNode(), N1.getResNo());
            NewLocOps.push_back(RHS);
            DIExpr = DIExpression::appendOpsToArg(TmpDIExpr, ExprOps, i, true);
          }
          Changed = true;
        }
        (void)Changed;
        assert(Changed && "Salvage target doesn't use N");

        bool IsVariadic =
            DV->isVariadic() || OrigLocOpsSize != NewLocOps.size();

        auto AdditionalDependencies = DV->getAdditionalDependencies();
        SDDbgValue *Clone = getDbgValueList(
            DV->getVariable(), DIExpr, NewLocOps, AdditionalDependencies,
            DV->isIndirect(), DV->getDebugLoc(), DV->getOrder(), IsVariadic);
        ClonedDVs.push_back(Clone);
        DV->setIsInvalidated();
        DV->setIsEmitted();
        LLVM_DEBUG(dbgs() << "SALVAGE: Rewriting";
                   N0.getNode()->dumprFull(this);
                   dbgs() << " into " << *DIExpr << '\n');
      }
      break;
    }
    case ISD::TRUNCATE: {
      SDValue N0 = N.getOperand(0);
      TypeSize FromSize = N0.getValueSizeInBits();
      TypeSize ToSize = N.getValueSizeInBits(0);

      DIExpression *DbgExpression = DV->getExpression();
      auto ExtOps = DIExpression::getExtOps(FromSize, ToSize, false);
      auto NewLocOps = DV->copyLocationOps();
      bool Changed = false;
      for (size_t i = 0; i < NewLocOps.size(); ++i) {
        if (NewLocOps[i].getKind() != SDDbgOperand::SDNODE ||
            NewLocOps[i].getSDNode() != &N)
          continue;

        NewLocOps[i] = GetLocationOperand(N0.getNode(), N0.getResNo());
        DbgExpression = DIExpression::appendOpsToArg(DbgExpression, ExtOps, i);
        Changed = true;
      }
      assert(Changed && "Salvage target doesn't use N");
      (void)Changed;

      SDDbgValue *Clone =
          getDbgValueList(DV->getVariable(), DbgExpression, NewLocOps,
                          DV->getAdditionalDependencies(), DV->isIndirect(),
                          DV->getDebugLoc(), DV->getOrder(), DV->isVariadic());

      ClonedDVs.push_back(Clone);
      DV->setIsInvalidated();
      DV->setIsEmitted();
      LLVM_DEBUG(dbgs() << "SALVAGE: Rewriting"; N0.getNode()->dumprFull(this);
                 dbgs() << " into " << *DbgExpression << '\n');
      break;
    }
    }
  }

  for (SDDbgValue *Dbg : ClonedDVs) {
    assert((!Dbg->getSDNodes().empty() ||
            llvm::any_of(Dbg->getLocationOps(),
                         [&](const SDDbgOperand &Op) {
                           return Op.getKind() == SDDbgOperand::FRAMEIX;
                         })) &&
           "Salvaged DbgValue should depend on a new SDNode");
    AddDbgValue(Dbg, false);
  }
}

/// Creates a SDDbgLabel node.
SDDbgLabel *SelectionDAG::getDbgLabel(DILabel *Label,
                                      const DebugLoc &DL, unsigned O) {
  assert(cast<DILabel>(Label)->isValidLocationForIntrinsic(DL) &&
         "Expected inlined-at fields to agree");
  return new (DbgInfo->getAlloc()) SDDbgLabel(Label, DL, O);
}

namespace {

/// RAUWUpdateListener - Helper for ReplaceAllUsesWith - When the node
/// pointed to by a use iterator is deleted, increment the use iterator
/// so that it doesn't dangle.
///
class RAUWUpdateListener : public SelectionDAG::DAGUpdateListener {
  SDNode::use_iterator &UI;
  SDNode::use_iterator &UE;

  void NodeDeleted(SDNode *N, SDNode *E) override {
    // Increment the iterator as needed.
    while (UI != UE && N == UI->getUser())
      ++UI;
  }

public:
  RAUWUpdateListener(SelectionDAG &d,
                     SDNode::use_iterator &ui,
                     SDNode::use_iterator &ue)
    : SelectionDAG::DAGUpdateListener(d), UI(ui), UE(ue) {}
};

} // end anonymous namespace

/// ReplaceAllUsesWith - Modify anything using 'From' to use 'To' instead.
/// This can cause recursive merging of nodes in the DAG.
///
/// This version assumes From has a single result value.
///
void SelectionDAG::ReplaceAllUsesWith(SDValue FromN, SDValue To) {
  SDNode *From = FromN.getNode();
  assert(From->getNumValues() == 1 && FromN.getResNo() == 0 &&
         "Cannot replace with this method!");
  assert(From != To.getNode() && "Cannot replace uses of with self");

  // Preserve Debug Values
  transferDbgValues(FromN, To);
  // Preserve extra info.
  copyExtraInfo(From, To.getNode());

  // Iterate over all the existing uses of From. New uses will be added
  // to the beginning of the use list, which we avoid visiting.
  // This specifically avoids visiting uses of From that arise while the
  // replacement is happening, because any such uses would be the result
  // of CSE: If an existing node looks like From after one of its operands
  // is replaced by To, we don't want to replace of all its users with To
  // too. See PR3018 for more info.
  SDNode::use_iterator UI = From->use_begin(), UE = From->use_end();
  RAUWUpdateListener Listener(*this, UI, UE);
  while (UI != UE) {
    SDNode *User = UI->getUser();

    // This node is about to morph, remove its old self from the CSE maps.
    RemoveNodeFromCSEMaps(User);

    // A user can appear in a use list multiple times, and when this
    // happens the uses are usually next to each other in the list.
    // To help reduce the number of CSE recomputations, process all
    // the uses of this user that we can find this way.
    do {
      SDUse &Use = *UI;
      ++UI;
      Use.set(To);
      if (To->isDivergent() != From->isDivergent())
        updateDivergence(User);
    } while (UI != UE && UI->getUser() == User);
    // Now that we have modified User, add it back to the CSE maps.  If it
    // already exists there, recursively merge the results together.
    AddModifiedNodeToCSEMaps(User);
  }

  // If we just RAUW'd the root, take note.
  if (FromN == getRoot())
    setRoot(To);
}

/// ReplaceAllUsesWith - Modify anything using 'From' to use 'To' instead.
/// This can cause recursive merging of nodes in the DAG.
///
/// This version assumes that for each value of From, there is a
/// corresponding value in To in the same position with the same type.
///
void SelectionDAG::ReplaceAllUsesWith(SDNode *From, SDNode *To) {
#ifndef NDEBUG
  for (unsigned i = 0, e = From->getNumValues(); i != e; ++i)
    assert((!From->hasAnyUseOfValue(i) ||
            From->getValueType(i) == To->getValueType(i)) &&
           "Cannot use this version of ReplaceAllUsesWith!");
#endif

  // Handle the trivial case.
  if (From == To)
    return;

  // Preserve Debug Info. Only do this if there's a use.
  for (unsigned i = 0, e = From->getNumValues(); i != e; ++i)
    if (From->hasAnyUseOfValue(i)) {
      assert((i < To->getNumValues()) && "Invalid To location");
      transferDbgValues(SDValue(From, i), SDValue(To, i));
    }
  // Preserve extra info.
  copyExtraInfo(From, To);

  // Iterate over just the existing users of From. See the comments in
  // the ReplaceAllUsesWith above.
  SDNode::use_iterator UI = From->use_begin(), UE = From->use_end();
  RAUWUpdateListener Listener(*this, UI, UE);
  while (UI != UE) {
    SDNode *User = UI->getUser();

    // This node is about to morph, remove its old self from the CSE maps.
    RemoveNodeFromCSEMaps(User);

    // A user can appear in a use list multiple times, and when this
    // happens the uses are usually next to each other in the list.
    // To help reduce the number of CSE recomputations, process all
    // the uses of this user that we can find this way.
    do {
      SDUse &Use = *UI;
      ++UI;
      Use.setNode(To);
      if (To->isDivergent() != From->isDivergent())
        updateDivergence(User);
    } while (UI != UE && UI->getUser() == User);

    // Now that we have modified User, add it back to the CSE maps.  If it
    // already exists there, recursively merge the results together.
    AddModifiedNodeToCSEMaps(User);
  }

  // If we just RAUW'd the root, take note.
  if (From == getRoot().getNode())
    setRoot(SDValue(To, getRoot().getResNo()));
}

/// ReplaceAllUsesWith - Modify anything using 'From' to use 'To' instead.
/// This can cause recursive merging of nodes in the DAG.
///
/// This version can replace From with any result values.  To must match the
/// number and types of values returned by From.
void SelectionDAG::ReplaceAllUsesWith(SDNode *From, const SDValue *To) {
  if (From->getNumValues() == 1)  // Handle the simple case efficiently.
    return ReplaceAllUsesWith(SDValue(From, 0), To[0]);

  for (unsigned i = 0, e = From->getNumValues(); i != e; ++i) {
    // Preserve Debug Info.
    transferDbgValues(SDValue(From, i), To[i]);
    // Preserve extra info.
    copyExtraInfo(From, To[i].getNode());
  }

  // Iterate over just the existing users of From. See the comments in
  // the ReplaceAllUsesWith above.
  SDNode::use_iterator UI = From->use_begin(), UE = From->use_end();
  RAUWUpdateListener Listener(*this, UI, UE);
  while (UI != UE) {
    SDNode *User = UI->getUser();

    // This node is about to morph, remove its old self from the CSE maps.
    RemoveNodeFromCSEMaps(User);

    // A user can appear in a use list multiple times, and when this happens the
    // uses are usually next to each other in the list.  To help reduce the
    // number of CSE and divergence recomputations, process all the uses of this
    // user that we can find this way.
    bool To_IsDivergent = false;
    do {
      SDUse &Use = *UI;
      const SDValue &ToOp = To[Use.getResNo()];
      ++UI;
      Use.set(ToOp);
      To_IsDivergent |= ToOp->isDivergent();
    } while (UI != UE && UI->getUser() == User);

    if (To_IsDivergent != From->isDivergent())
      updateDivergence(User);

    // Now that we have modified User, add it back to the CSE maps.  If it
    // already exists there, recursively merge the results together.
    AddModifiedNodeToCSEMaps(User);
  }

  // If we just RAUW'd the root, take note.
  if (From == getRoot().getNode())
    setRoot(SDValue(To[getRoot().getResNo()]));
}

/// ReplaceAllUsesOfValueWith - Replace any uses of From with To, leaving
/// uses of other values produced by From.getNode() alone.  The Deleted
/// vector is handled the same way as for ReplaceAllUsesWith.
void SelectionDAG::ReplaceAllUsesOfValueWith(SDValue From, SDValue To){
  // Handle the really simple, really trivial case efficiently.
  if (From == To) return;

  // Handle the simple, trivial, case efficiently.
  if (From.getNode()->getNumValues() == 1) {
    ReplaceAllUsesWith(From, To);
    return;
  }

  // Preserve Debug Info.
  transferDbgValues(From, To);
  copyExtraInfo(From.getNode(), To.getNode());

  // Iterate over just the existing users of From. See the comments in
  // the ReplaceAllUsesWith above.
  SDNode::use_iterator UI = From.getNode()->use_begin(),
                       UE = From.getNode()->use_end();
  RAUWUpdateListener Listener(*this, UI, UE);
  while (UI != UE) {
    SDNode *User = UI->getUser();
    bool UserRemovedFromCSEMaps = false;

    // A user can appear in a use list multiple times, and when this
    // happens the uses are usually next to each other in the list.
    // To help reduce the number of CSE recomputations, process all
    // the uses of this user that we can find this way.
    do {
      SDUse &Use = *UI;

      // Skip uses of different values from the same node.
      if (Use.getResNo() != From.getResNo()) {
        ++UI;
        continue;
      }

      // If this node hasn't been modified yet, it's still in the CSE maps,
      // so remove its old self from the CSE maps.
      if (!UserRemovedFromCSEMaps) {
        RemoveNodeFromCSEMaps(User);
        UserRemovedFromCSEMaps = true;
      }

      ++UI;
      Use.set(To);
      if (To->isDivergent() != From->isDivergent())
        updateDivergence(User);
    } while (UI != UE && UI->getUser() == User);
    // We are iterating over all uses of the From node, so if a use
    // doesn't use the specific value, no changes are made.
    if (!UserRemovedFromCSEMaps)
      continue;

    // Now that we have modified User, add it back to the CSE maps.  If it
    // already exists there, recursively merge the results together.
    AddModifiedNodeToCSEMaps(User);
  }

  // If we just RAUW'd the root, take note.
  if (From == getRoot())
    setRoot(To);
}

namespace {

/// UseMemo - This class is used by SelectionDAG::ReplaceAllUsesOfValuesWith
/// to record information about a use.
struct UseMemo {
  SDNode *User;
  unsigned Index;
  SDUse *Use;
};

/// operator< - Sort Memos by User.
bool operator<(const UseMemo &L, const UseMemo &R) {
  return (intptr_t)L.User < (intptr_t)R.User;
}

/// RAUOVWUpdateListener - Helper for ReplaceAllUsesOfValuesWith - When the node
/// pointed to by a UseMemo is deleted, set the User to nullptr to indicate that
/// the node already has been taken care of recursively.
class RAUOVWUpdateListener : public SelectionDAG::DAGUpdateListener {
  SmallVectorImpl<UseMemo> &Uses;

  void NodeDeleted(SDNode *N, SDNode *E) override {
    for (UseMemo &Memo : Uses)
      if (Memo.User == N)
        Memo.User = nullptr;
  }

public:
  RAUOVWUpdateListener(SelectionDAG &d, SmallVectorImpl<UseMemo> &uses)
      : SelectionDAG::DAGUpdateListener(d), Uses(uses) {}
};

} // end anonymous namespace

/// Return true if a glue output should propagate divergence information.
static bool gluePropagatesDivergence(const SDNode *Node) {
  switch (Node->getOpcode()) {
  case ISD::CopyFromReg:
  case ISD::CopyToReg:
    return false;
  default:
    return true;
  }

  llvm_unreachable("covered opcode switch");
}

bool SelectionDAG::calculateDivergence(SDNode *N) {
  if (!DivergentTarget)
    return false;
  if (TLI->isSDNodeAlwaysUniform(N)) {
    assert(!TLI->isSDNodeSourceOfDivergence(N, FLI, UA) &&
           "Conflicting divergence information!");
    return false;
  }
  if (TLI->isSDNodeSourceOfDivergence(N, FLI, UA))
    return true;
  for (const auto &Op : N->ops()) {
    EVT VT = Op.getValueType();

    // Skip Chain. It does not carry divergence.
    if (VT != MVT::Other && Op.getNode()->isDivergent() &&
        (VT != MVT::Glue || gluePropagatesDivergence(Op.getNode())))
      return true;
  }
  return false;
}

void SelectionDAG::updateDivergence(SDNode *N) {
  if (!DivergentTarget)
    return;
  SmallVector<SDNode *, 16> Worklist(1, N);
  do {
    N = Worklist.pop_back_val();
    bool IsDivergent = calculateDivergence(N);
    if (N->SDNodeBits.IsDivergent != IsDivergent) {
      N->SDNodeBits.IsDivergent = IsDivergent;
      llvm::append_range(Worklist, N->users());
    }
  } while (!Worklist.empty());
}

void SelectionDAG::CreateTopologicalOrder(std::vector<SDNode *> &Order) {
  DenseMap<SDNode *, unsigned> Degree;
  Order.reserve(AllNodes.size());
  for (auto &N : allnodes()) {
    unsigned NOps = N.getNumOperands();
    Degree[&N] = NOps;
    if (0 == NOps)
      Order.push_back(&N);
  }
  for (size_t I = 0; I != Order.size(); ++I) {
    SDNode *N = Order[I];
    for (auto *U : N->users()) {
      unsigned &UnsortedOps = Degree[U];
      if (0 == --UnsortedOps)
        Order.push_back(U);
    }
  }
}

#if !defined(NDEBUG) && LLVM_ENABLE_ABI_BREAKING_CHECKS
void SelectionDAG::VerifyDAGDivergence() {
  std::vector<SDNode *> TopoOrder;
  CreateTopologicalOrder(TopoOrder);
  for (auto *N : TopoOrder) {
    assert(calculateDivergence(N) == N->isDivergent() &&
           "Divergence bit inconsistency detected");
  }
}
#endif

/// ReplaceAllUsesOfValuesWith - Replace any uses of From with To, leaving
/// uses of other values produced by From.getNode() alone.  The same value
/// may appear in both the From and To list.  The Deleted vector is
/// handled the same way as for ReplaceAllUsesWith.
void SelectionDAG::ReplaceAllUsesOfValuesWith(const SDValue *From,
                                              const SDValue *To,
                                              unsigned Num){
  // Handle the simple, trivial case efficiently.
  if (Num == 1)
    return ReplaceAllUsesOfValueWith(*From, *To);

  transferDbgValues(*From, *To);
  copyExtraInfo(From->getNode(), To->getNode());

  // Read up all the uses and make records of them. This helps
  // processing new uses that are introduced during the
  // replacement process.
  SmallVector<UseMemo, 4> Uses;
  for (unsigned i = 0; i != Num; ++i) {
    unsigned FromResNo = From[i].getResNo();
    SDNode *FromNode = From[i].getNode();
    for (SDUse &Use : FromNode->uses()) {
      if (Use.getResNo() == FromResNo) {
        UseMemo Memo = {Use.getUser(), i, &Use};
        Uses.push_back(Memo);
      }
    }
  }

  // Sort the uses, so that all the uses from a given User are together.
  llvm::sort(Uses);
  RAUOVWUpdateListener Listener(*this, Uses);

  for (unsigned UseIndex = 0, UseIndexEnd = Uses.size();
       UseIndex != UseIndexEnd; ) {
    // We know that this user uses some value of From.  If it is the right
    // value, update it.
    SDNode *User = Uses[UseIndex].User;
    // If the node has been deleted by recursive CSE updates when updating
    // another node, then just skip this entry.
    if (User == nullptr) {
      ++UseIndex;
      continue;
    }

    // This node is about to morph, remove its old self from the CSE maps.
    RemoveNodeFromCSEMaps(User);

    // The Uses array is sorted, so all the uses for a given User
    // are next to each other in the list.
    // To help reduce the number of CSE recomputations, process all
    // the uses of this user that we can find this way.
    do {
      unsigned i = Uses[UseIndex].Index;
      SDUse &Use = *Uses[UseIndex].Use;
      ++UseIndex;

      Use.set(To[i]);
    } while (UseIndex != UseIndexEnd && Uses[UseIndex].User == User);

    // Now that we have modified User, add it back to the CSE maps.  If it
    // already exists there, recursively merge the results together.
    AddModifiedNodeToCSEMaps(User);
  }
}

/// AssignTopologicalOrder - Assign a unique node id for each node in the DAG
/// based on their topological order. It returns the maximum id and a vector
/// of the SDNodes* in assigned order by reference.
unsigned SelectionDAG::AssignTopologicalOrder() {
  unsigned DAGSize = 0;

  // SortedPos tracks the progress of the algorithm. Nodes before it are
  // sorted, nodes after it are unsorted. When the algorithm completes
  // it is at the end of the list.
  allnodes_iterator SortedPos = allnodes_begin();

  // Visit all the nodes. Move nodes with no operands to the front of
  // the list immediately. Annotate nodes that do have operands with their
  // operand count. Before we do this, the Node Id fields of the nodes
  // may contain arbitrary values. After, the Node Id fields for nodes
  // before SortedPos will contain the topological sort index, and the
  // Node Id fields for nodes At SortedPos and after will contain the
  // count of outstanding operands.
  for (SDNode &N : llvm::make_early_inc_range(allnodes())) {
    checkForCycles(&N, this);
    unsigned Degree = N.getNumOperands();
    if (Degree == 0) {
      // A node with no uses, add it to the result array immediately.
      N.setNodeId(DAGSize++);
      allnodes_iterator Q(&N);
      if (Q != SortedPos)
        SortedPos = AllNodes.insert(SortedPos, AllNodes.remove(Q));
      assert(SortedPos != AllNodes.end() && "Overran node list");
      ++SortedPos;
    } else {
      // Temporarily use the Node Id as scratch space for the degree count.
      N.setNodeId(Degree);
    }
  }

  // Visit all the nodes. As we iterate, move nodes into sorted order,
  // such that by the time the end is reached all nodes will be sorted.
  for (SDNode &Node : allnodes()) {
    SDNode *N = &Node;
    checkForCycles(N, this);
    // N is in sorted position, so all its uses have one less operand
    // that needs to be sorted.
    for (SDNode *P : N->users()) {
      unsigned Degree = P->getNodeId();
      assert(Degree != 0 && "Invalid node degree");
      --Degree;
      if (Degree == 0) {
        // All of P's operands are sorted, so P may sorted now.
        P->setNodeId(DAGSize++);
        if (P->getIterator() != SortedPos)
          SortedPos = AllNodes.insert(SortedPos, AllNodes.remove(P));
        assert(SortedPos != AllNodes.end() && "Overran node list");
        ++SortedPos;
      } else {
        // Update P's outstanding operand count.
        P->setNodeId(Degree);
      }
    }
    if (Node.getIterator() == SortedPos) {
#ifndef NDEBUG
      allnodes_iterator I(N);
      SDNode *S = &*++I;
      dbgs() << "Overran sorted position:\n";
      S->dumprFull(this); dbgs() << "\n";
      dbgs() << "Checking if this is due to cycles\n";
      checkForCycles(this, true);
#endif
      llvm_unreachable(nullptr);
    }
  }

  assert(SortedPos == AllNodes.end() &&
         "Topological sort incomplete!");
  assert(AllNodes.front().getOpcode() == ISD::EntryToken &&
         "First node in topological sort is not the entry token!");
  assert(AllNodes.front().getNodeId() == 0 &&
         "First node in topological sort has non-zero id!");
  assert(AllNodes.front().getNumOperands() == 0 &&
         "First node in topological sort has operands!");
  assert(AllNodes.back().getNodeId() == (int)DAGSize-1 &&
         "Last node in topologic sort has unexpected id!");
  assert(AllNodes.back().use_empty() &&
         "Last node in topologic sort has users!");
  assert(DAGSize == allnodes_size() && "Node count mismatch!");
  return DAGSize;
}

/// AddDbgValue - Add a dbg_value SDNode. If SD is non-null that means the
/// value is produced by SD.
void SelectionDAG::AddDbgValue(SDDbgValue *DB, bool isParameter) {
  for (SDNode *SD : DB->getSDNodes()) {
    if (!SD)
      continue;
    assert(DbgInfo->getSDDbgValues(SD).empty() || SD->getHasDebugValue());
    SD->setHasDebugValue(true);
  }
  DbgInfo->add(DB, isParameter);
}

void SelectionDAG::AddDbgLabel(SDDbgLabel *DB) { DbgInfo->add(DB); }

SDValue SelectionDAG::makeEquivalentMemoryOrdering(SDValue OldChain,
                                                   SDValue NewMemOpChain) {
  assert(isa<MemSDNode>(NewMemOpChain) && "Expected a memop node");
  assert(NewMemOpChain.getValueType() == MVT::Other && "Expected a token VT");
  // The new memory operation must have the same position as the old load in
  // terms of memory dependency. Create a TokenFactor for the old load and new
  // memory operation and update uses of the old load's output chain to use that
  // TokenFactor.
  if (OldChain == NewMemOpChain || OldChain.use_empty())
    return NewMemOpChain;

  SDValue TokenFactor = getNode(ISD::TokenFactor, SDLoc(OldChain), MVT::Other,
                                OldChain, NewMemOpChain);
  ReplaceAllUsesOfValueWith(OldChain, TokenFactor);
  UpdateNodeOperands(TokenFactor.getNode(), OldChain, NewMemOpChain);
  return TokenFactor;
}

SDValue SelectionDAG::makeEquivalentMemoryOrdering(LoadSDNode *OldLoad,
                                                   SDValue NewMemOp) {
  assert(isa<MemSDNode>(NewMemOp.getNode()) && "Expected a memop node");
  SDValue OldChain = SDValue(OldLoad, 1);
  SDValue NewMemOpChain = NewMemOp.getValue(1);
  return makeEquivalentMemoryOrdering(OldChain, NewMemOpChain);
}

SDValue SelectionDAG::getSymbolFunctionGlobalAddress(SDValue Op,
                                                     Function **OutFunction) {
  assert(isa<ExternalSymbolSDNode>(Op) && "Node should be an ExternalSymbol");

  auto *Symbol = cast<ExternalSymbolSDNode>(Op)->getSymbol();
  auto *Module = MF->getFunction().getParent();
  auto *Function = Module->getFunction(Symbol);

  if (OutFunction != nullptr)
      *OutFunction = Function;

  if (Function != nullptr) {
    auto PtrTy = TLI->getPointerTy(getDataLayout(), Function->getAddressSpace());
    return getGlobalAddress(Function, SDLoc(Op), PtrTy);
  }

  std::string ErrorStr;
  raw_string_ostream ErrorFormatter(ErrorStr);
  ErrorFormatter << "Undefined external symbol ";
  ErrorFormatter << '"' << Symbol << '"';
  report_fatal_error(Twine(ErrorStr));
}

//===----------------------------------------------------------------------===//
//                              SDNode Class
//===----------------------------------------------------------------------===//

bool llvm::isNullConstant(SDValue V) {
  ConstantSDNode *Const = dyn_cast<ConstantSDNode>(V);
  return Const != nullptr && Const->isZero();
}

bool llvm::isNullConstantOrUndef(SDValue V) {
  return V.isUndef() || isNullConstant(V);
}

bool llvm::isNullFPConstant(SDValue V) {
  ConstantFPSDNode *Const = dyn_cast<ConstantFPSDNode>(V);
  return Const != nullptr && Const->isZero() && !Const->isNegative();
}

bool llvm::isAllOnesConstant(SDValue V) {
  ConstantSDNode *Const = dyn_cast<ConstantSDNode>(V);
  return Const != nullptr && Const->isAllOnes();
}

bool llvm::isOneConstant(SDValue V) {
  ConstantSDNode *Const = dyn_cast<ConstantSDNode>(V);
  return Const != nullptr && Const->isOne();
}

bool llvm::isMinSignedConstant(SDValue V) {
  ConstantSDNode *Const = dyn_cast<ConstantSDNode>(V);
  return Const != nullptr && Const->isMinSignedValue();
}

bool llvm::isNeutralConstant(unsigned Opcode, SDNodeFlags Flags, SDValue V,
                             unsigned OperandNo) {
  // NOTE: The cases should match with IR's ConstantExpr::getBinOpIdentity().
  // TODO: Target-specific opcodes could be added.
  if (auto *ConstV = isConstOrConstSplat(V, /*AllowUndefs*/ false,
                                         /*AllowTruncation*/ true)) {
    APInt Const = ConstV->getAPIntValue().trunc(V.getScalarValueSizeInBits());
    switch (Opcode) {
    case ISD::ADD:
    case ISD::OR:
    case ISD::XOR:
    case ISD::UMAX:
      return Const.isZero();
    case ISD::MUL:
      return Const.isOne();
    case ISD::AND:
    case ISD::UMIN:
      return Const.isAllOnes();
    case ISD::SMAX:
      return Const.isMinSignedValue();
    case ISD::SMIN:
      return Const.isMaxSignedValue();
    case ISD::SUB:
    case ISD::SHL:
    case ISD::SRA:
    case ISD::SRL:
      return OperandNo == 1 && Const.isZero();
    case ISD::UDIV:
    case ISD::SDIV:
      return OperandNo == 1 && Const.isOne();
    }
  } else if (auto *ConstFP = isConstOrConstSplatFP(V)) {
    switch (Opcode) {
    case ISD::FADD:
      return ConstFP->isZero() &&
             (Flags.hasNoSignedZeros() || ConstFP->isNegative());
    case ISD::FSUB:
      return OperandNo == 1 && ConstFP->isZero() &&
             (Flags.hasNoSignedZeros() || !ConstFP->isNegative());
    case ISD::FMUL:
      return ConstFP->isExactlyValue(1.0);
    case ISD::FDIV:
      return OperandNo == 1 && ConstFP->isExactlyValue(1.0);
    case ISD::FMINNUM:
    case ISD::FMAXNUM: {
      // Neutral element for fminnum is NaN, Inf or FLT_MAX, depending on FMF.
      EVT VT = V.getValueType();
      const fltSemantics &Semantics = VT.getFltSemantics();
      APFloat NeutralAF = !Flags.hasNoNaNs()
                              ? APFloat::getQNaN(Semantics)
                              : !Flags.hasNoInfs()
                                    ? APFloat::getInf(Semantics)
                                    : APFloat::getLargest(Semantics);
      if (Opcode == ISD::FMAXNUM)
        NeutralAF.changeSign();

      return ConstFP->isExactlyValue(NeutralAF);
    }
    }
  }
  return false;
}

SDValue llvm::peekThroughBitcasts(SDValue V) {
  while (V.getOpcode() == ISD::BITCAST)
    V = V.getOperand(0);
  return V;
}

SDValue llvm::peekThroughOneUseBitcasts(SDValue V) {
  while (V.getOpcode() == ISD::BITCAST && V.getOperand(0).hasOneUse())
    V = V.getOperand(0);
  return V;
}

SDValue llvm::peekThroughExtractSubvectors(SDValue V) {
  while (V.getOpcode() == ISD::EXTRACT_SUBVECTOR)
    V = V.getOperand(0);
  return V;
}

SDValue llvm::peekThroughTruncates(SDValue V) {
  while (V.getOpcode() == ISD::TRUNCATE)
    V = V.getOperand(0);
  return V;
}

bool llvm::isBitwiseNot(SDValue V, bool AllowUndefs) {
  if (V.getOpcode() != ISD::XOR)
    return false;
  V = peekThroughBitcasts(V.getOperand(1));
  unsigned NumBits = V.getScalarValueSizeInBits();
  ConstantSDNode *C =
      isConstOrConstSplat(V, AllowUndefs, /*AllowTruncation*/ true);
  return C && (C->getAPIntValue().countr_one() >= NumBits);
}

ConstantSDNode *llvm::isConstOrConstSplat(SDValue N, bool AllowUndefs,
                                          bool AllowTruncation) {
  EVT VT = N.getValueType();
  APInt DemandedElts = VT.isFixedLengthVector()
                           ? APInt::getAllOnes(VT.getVectorMinNumElements())
                           : APInt(1, 1);
  return isConstOrConstSplat(N, DemandedElts, AllowUndefs, AllowTruncation);
}

ConstantSDNode *llvm::isConstOrConstSplat(SDValue N, const APInt &DemandedElts,
                                          bool AllowUndefs,
                                          bool AllowTruncation) {
  if (ConstantSDNode *CN = dyn_cast<ConstantSDNode>(N))
    return CN;

  // SplatVectors can truncate their operands. Ignore that case here unless
  // AllowTruncation is set.
  if (N->getOpcode() == ISD::SPLAT_VECTOR) {
    EVT VecEltVT = N->getValueType(0).getVectorElementType();
    if (auto *CN = dyn_cast<ConstantSDNode>(N->getOperand(0))) {
      EVT CVT = CN->getValueType(0);
      assert(CVT.bitsGE(VecEltVT) && "Illegal splat_vector element extension");
      if (AllowTruncation || CVT == VecEltVT)
        return CN;
    }
  }

  if (BuildVectorSDNode *BV = dyn_cast<BuildVectorSDNode>(N)) {
    BitVector UndefElements;
    ConstantSDNode *CN = BV->getConstantSplatNode(DemandedElts, &UndefElements);

    // BuildVectors can truncate their operands. Ignore that case here unless
    // AllowTruncation is set.
    // TODO: Look into whether we should allow UndefElements in non-DemandedElts
    if (CN && (UndefElements.none() || AllowUndefs)) {
      EVT CVT = CN->getValueType(0);
      EVT NSVT = N.getValueType().getScalarType();
      assert(CVT.bitsGE(NSVT) && "Illegal build vector element extension");
      if (AllowTruncation || (CVT == NSVT))
        return CN;
    }
  }

  return nullptr;
}

ConstantFPSDNode *llvm::isConstOrConstSplatFP(SDValue N, bool AllowUndefs) {
  EVT VT = N.getValueType();
  APInt DemandedElts = VT.isFixedLengthVector()
                           ? APInt::getAllOnes(VT.getVectorMinNumElements())
                           : APInt(1, 1);
  return isConstOrConstSplatFP(N, DemandedElts, AllowUndefs);
}

ConstantFPSDNode *llvm::isConstOrConstSplatFP(SDValue N,
                                              const APInt &DemandedElts,
                                              bool AllowUndefs) {
  if (ConstantFPSDNode *CN = dyn_cast<ConstantFPSDNode>(N))
    return CN;

  if (BuildVectorSDNode *BV = dyn_cast<BuildVectorSDNode>(N)) {
    BitVector UndefElements;
    ConstantFPSDNode *CN =
        BV->getConstantFPSplatNode(DemandedElts, &UndefElements);
    // TODO: Look into whether we should allow UndefElements in non-DemandedElts
    if (CN && (UndefElements.none() || AllowUndefs))
      return CN;
  }

  if (N.getOpcode() == ISD::SPLAT_VECTOR)
    if (ConstantFPSDNode *CN = dyn_cast<ConstantFPSDNode>(N.getOperand(0)))
      return CN;

  return nullptr;
}

bool llvm::isNullOrNullSplat(SDValue N, bool AllowUndefs) {
  // TODO: may want to use peekThroughBitcast() here.
  ConstantSDNode *C =
      isConstOrConstSplat(N, AllowUndefs, /*AllowTruncation=*/true);
  return C && C->isZero();
}

bool llvm::isOneOrOneSplat(SDValue N, bool AllowUndefs) {
  ConstantSDNode *C =
      isConstOrConstSplat(N, AllowUndefs, /*AllowTruncation*/ true);
  return C && C->isOne();
}

bool llvm::isAllOnesOrAllOnesSplat(SDValue N, bool AllowUndefs) {
  N = peekThroughBitcasts(N);
  unsigned BitWidth = N.getScalarValueSizeInBits();
  ConstantSDNode *C = isConstOrConstSplat(N, AllowUndefs);
  return C && C->isAllOnes() && C->getValueSizeInBits(0) == BitWidth;
}

bool llvm::isOnesOrOnesSplat(SDValue N, bool AllowUndefs) {
  ConstantSDNode *C = isConstOrConstSplat(N, AllowUndefs);
  return C && APInt::isSameValue(C->getAPIntValue(),
                                 APInt(C->getAPIntValue().getBitWidth(), 1));
}

bool llvm::isZeroOrZeroSplat(SDValue N, bool AllowUndefs) {
  N = peekThroughBitcasts(N);
  ConstantSDNode *C = isConstOrConstSplat(N, AllowUndefs, true);
  return C && C->isZero();
}

HandleSDNode::~HandleSDNode() {
  DropOperands();
}

MemSDNode::MemSDNode(unsigned Opc, unsigned Order, const DebugLoc &dl,
                     SDVTList VTs, EVT memvt, MachineMemOperand *mmo)
    : SDNode(Opc, Order, dl, VTs), MemoryVT(memvt), MMO(mmo) {
  MemSDNodeBits.IsVolatile = MMO->isVolatile();
  MemSDNodeBits.IsNonTemporal = MMO->isNonTemporal();
  MemSDNodeBits.IsDereferenceable = MMO->isDereferenceable();
  MemSDNodeBits.IsInvariant = MMO->isInvariant();

  // We check here that the size of the memory operand fits within the size of
  // the MMO. This is because the MMO might indicate only a possible address
  // range instead of specifying the affected memory addresses precisely.
  assert(
      (!MMO->getType().isValid() ||
       TypeSize::isKnownLE(memvt.getStoreSize(), MMO->getSize().getValue())) &&
      "Size mismatch!");
}

/// Profile - Gather unique data for the node.
///
void SDNode::Profile(FoldingSetNodeID &ID) const {
  AddNodeIDNode(ID, this);
}

namespace {

  struct EVTArray {
    std::vector<EVT> VTs;

    EVTArray() {
      VTs.reserve(MVT::VALUETYPE_SIZE);
      for (unsigned i = 0; i < MVT::VALUETYPE_SIZE; ++i)
        VTs.push_back(MVT((MVT::SimpleValueType)i));
    }
  };

} // end anonymous namespace

/// getValueTypeList - Return a pointer to the specified value type.
///
const EVT *SDNode::getValueTypeList(MVT VT) {
  static EVTArray SimpleVTArray;

  assert(VT < MVT::VALUETYPE_SIZE && "Value type out of range!");
  return &SimpleVTArray.VTs[VT.SimpleTy];
}

/// hasAnyUseOfValue - Return true if there are any use of the indicated
/// value. This method ignores uses of other values defined by this operation.
bool SDNode::hasAnyUseOfValue(unsigned Value) const {
  assert(Value < getNumValues() && "Bad value!");

  for (SDUse &U : uses())
    if (U.getResNo() == Value)
      return true;

  return false;
}

/// isOnlyUserOf - Return true if this node is the only use of N.
bool SDNode::isOnlyUserOf(const SDNode *N) const {
  bool Seen = false;
  for (const SDNode *User : N->users()) {
    if (User == this)
      Seen = true;
    else
      return false;
  }

  return Seen;
}

/// Return true if the only users of N are contained in Nodes.
bool SDNode::areOnlyUsersOf(ArrayRef<const SDNode *> Nodes, const SDNode *N) {
  bool Seen = false;
  for (const SDNode *User : N->users()) {
    if (llvm::is_contained(Nodes, User))
      Seen = true;
    else
      return false;
  }

  return Seen;
}

/// Return true if the referenced return value is an operand of N.
bool SDValue::isOperandOf(const SDNode *N) const {
  return is_contained(N->op_values(), *this);
}

bool SDNode::isOperandOf(const SDNode *N) const {
  return any_of(N->op_values(),
                [this](SDValue Op) { return this == Op.getNode(); });
}

/// reachesChainWithoutSideEffects - Return true if this operand (which must
/// be a chain) reaches the specified operand without crossing any
/// side-effecting instructions on any chain path.  In practice, this looks
/// through token factors and non-volatile loads.  In order to remain efficient,
/// this only looks a couple of nodes in, it does not do an exhaustive search.
///
/// Note that we only need to examine chains when we're searching for
/// side-effects; SelectionDAG requires that all side-effects are represented
/// by chains, even if another operand would force a specific ordering. This
/// constraint is necessary to allow transformations like splitting loads.
bool SDValue::reachesChainWithoutSideEffects(SDValue Dest,
                                             unsigned Depth) const {
  if (*this == Dest) return true;

  // Don't search too deeply, we just want to be able to see through
  // TokenFactor's etc.
  if (Depth == 0) return false;

  // If this is a token factor, all inputs to the TF happen in parallel.
  if (getOpcode() == ISD::TokenFactor) {
    // First, try a shallow search.
    if (is_contained((*this)->ops(), Dest)) {
      // We found the chain we want as an operand of this TokenFactor.
      // Essentially, we reach the chain without side-effects if we could
      // serialize the TokenFactor into a simple chain of operations with
      // Dest as the last operation. This is automatically true if the
      // chain has one use: there are no other ordering constraints.
      // If the chain has more than one use, we give up: some other
      // use of Dest might force a side-effect between Dest and the current
      // node.
      if (Dest.hasOneUse())
        return true;
    }
    // Next, try a deep search: check whether every operand of the TokenFactor
    // reaches Dest.
    return llvm::all_of((*this)->ops(), [=](SDValue Op) {
      return Op.reachesChainWithoutSideEffects(Dest, Depth - 1);
    });
  }

  // Loads don't have side effects, look through them.
  if (LoadSDNode *Ld = dyn_cast<LoadSDNode>(*this)) {
    if (Ld->isUnordered())
      return Ld->getChain().reachesChainWithoutSideEffects(Dest, Depth-1);
  }
  return false;
}

bool SDNode::hasPredecessor(const SDNode *N) const {
  SmallPtrSet<const SDNode *, 32> Visited;
  SmallVector<const SDNode *, 16> Worklist;
  Worklist.push_back(this);
  return hasPredecessorHelper(N, Visited, Worklist);
}

void SDNode::intersectFlagsWith(const SDNodeFlags Flags) {
  this->Flags &= Flags;
}

SDValue
SelectionDAG::matchBinOpReduction(SDNode *Extract, ISD::NodeType &BinOp,
                                  ArrayRef<ISD::NodeType> CandidateBinOps,
                                  bool AllowPartials) {
  // The pattern must end in an extract from index 0.
  if (Extract->getOpcode() != ISD::EXTRACT_VECTOR_ELT ||
      !isNullConstant(Extract->getOperand(1)))
    return SDValue();

  // Match against one of the candidate binary ops.
  SDValue Op = Extract->getOperand(0);
  if (llvm::none_of(CandidateBinOps, [Op](ISD::NodeType BinOp) {
        return Op.getOpcode() == unsigned(BinOp);
      }))
    return SDValue();

  // Floating-point reductions may require relaxed constraints on the final step
  // of the reduction because they may reorder intermediate operations.
  unsigned CandidateBinOp = Op.getOpcode();
  if (Op.getValueType().isFloatingPoint()) {
    SDNodeFlags Flags = Op->getFlags();
    switch (CandidateBinOp) {
    case ISD::FADD:
      if (!Flags.hasNoSignedZeros() || !Flags.hasAllowReassociation())
        return SDValue();
      break;
    default:
      llvm_unreachable("Unhandled FP opcode for binop reduction");
    }
  }

  // Matching failed - attempt to see if we did enough stages that a partial
  // reduction from a subvector is possible.
  auto PartialReduction = [&](SDValue Op, unsigned NumSubElts) {
    if (!AllowPartials || !Op)
      return SDValue();
    EVT OpVT = Op.getValueType();
    EVT OpSVT = OpVT.getScalarType();
    EVT SubVT = EVT::getVectorVT(*getContext(), OpSVT, NumSubElts);
    if (!TLI->isExtractSubvectorCheap(SubVT, OpVT, 0))
      return SDValue();
    BinOp = (ISD::NodeType)CandidateBinOp;
    return getExtractSubvector(SDLoc(Op), SubVT, Op, 0);
  };

  // At each stage, we're looking for something that looks like:
  // %s = shufflevector <8 x i32> %op, <8 x i32> undef,
  //                    <8 x i32> <i32 2, i32 3, i32 undef, i32 undef,
  //                               i32 undef, i32 undef, i32 undef, i32 undef>
  // %a = binop <8 x i32> %op, %s
  // Where the mask changes according to the stage. E.g. for a 3-stage pyramid,
  // we expect something like:
  // <4,5,6,7,u,u,u,u>
  // <2,3,u,u,u,u,u,u>
  // <1,u,u,u,u,u,u,u>
  // While a partial reduction match would be:
  // <2,3,u,u,u,u,u,u>
  // <1,u,u,u,u,u,u,u>
  unsigned Stages = Log2_32(Op.getValueType().getVectorNumElements());
  SDValue PrevOp;
  for (unsigned i = 0; i < Stages; ++i) {
    unsigned MaskEnd = (1 << i);

    if (Op.getOpcode() != CandidateBinOp)
      return PartialReduction(PrevOp, MaskEnd);

    SDValue Op0 = Op.getOperand(0);
    SDValue Op1 = Op.getOperand(1);

    ShuffleVectorSDNode *Shuffle = dyn_cast<ShuffleVectorSDNode>(Op0);
    if (Shuffle) {
      Op = Op1;
    } else {
      Shuffle = dyn_cast<ShuffleVectorSDNode>(Op1);
      Op = Op0;
    }

    // The first operand of the shuffle should be the same as the other operand
    // of the binop.
    if (!Shuffle || Shuffle->getOperand(0) != Op)
      return PartialReduction(PrevOp, MaskEnd);

    // Verify the shuffle has the expected (at this stage of the pyramid) mask.
    for (int Index = 0; Index < (int)MaskEnd; ++Index)
      if (Shuffle->getMaskElt(Index) != (int)(MaskEnd + Index))
        return PartialReduction(PrevOp, MaskEnd);

    PrevOp = Op;
  }

  // Handle subvector reductions, which tend to appear after the shuffle
  // reduction stages.
  while (Op.getOpcode() == CandidateBinOp) {
    unsigned NumElts = Op.getValueType().getVectorNumElements();
    SDValue Op0 = Op.getOperand(0);
    SDValue Op1 = Op.getOperand(1);
    if (Op0.getOpcode() != ISD::EXTRACT_SUBVECTOR ||
        Op1.getOpcode() != ISD::EXTRACT_SUBVECTOR ||
        Op0.getOperand(0) != Op1.getOperand(0))
      break;
    SDValue Src = Op0.getOperand(0);
    unsigned NumSrcElts = Src.getValueType().getVectorNumElements();
    if (NumSrcElts != (2 * NumElts))
      break;
    if (!(Op0.getConstantOperandAPInt(1) == 0 &&
          Op1.getConstantOperandAPInt(1) == NumElts) &&
        !(Op1.getConstantOperandAPInt(1) == 0 &&
          Op0.getConstantOperandAPInt(1) == NumElts))
      break;
    Op = Src;
  }

  BinOp = (ISD::NodeType)CandidateBinOp;
  return Op;
}

SDValue SelectionDAG::UnrollVectorOp(SDNode *N, unsigned ResNE) {
  EVT VT = N->getValueType(0);
  EVT EltVT = VT.getVectorElementType();
  unsigned NE = VT.getVectorNumElements();

  SDLoc dl(N);

  // If ResNE is 0, fully unroll the vector op.
  if (ResNE == 0)
    ResNE = NE;
  else if (NE > ResNE)
    NE = ResNE;

  if (N->getNumValues() == 2) {
    SmallVector<SDValue, 8> Scalars0, Scalars1;
    SmallVector<SDValue, 4> Operands(N->getNumOperands());
    EVT VT1 = N->getValueType(1);
    EVT EltVT1 = VT1.getVectorElementType();

    unsigned i;
    for (i = 0; i != NE; ++i) {
      for (unsigned j = 0, e = N->getNumOperands(); j != e; ++j) {
        SDValue Operand = N->getOperand(j);
        EVT OperandVT = Operand.getValueType();

        // A vector operand; extract a single element.
        EVT OperandEltVT = OperandVT.getVectorElementType();
        Operands[j] = getExtractVectorElt(dl, OperandEltVT, Operand, i);
      }

      SDValue EltOp = getNode(N->getOpcode(), dl, {EltVT, EltVT1}, Operands);
      Scalars0.push_back(EltOp);
      Scalars1.push_back(EltOp.getValue(1));
    }

    for (; i < ResNE; ++i) {
      Scalars0.push_back(getUNDEF(EltVT));
      Scalars1.push_back(getUNDEF(EltVT1));
    }

    EVT VecVT = EVT::getVectorVT(*getContext(), EltVT, ResNE);
    EVT VecVT1 = EVT::getVectorVT(*getContext(), EltVT1, ResNE);
    SDValue Vec0 = getBuildVector(VecVT, dl, Scalars0);
    SDValue Vec1 = getBuildVector(VecVT1, dl, Scalars1);
    return getMergeValues({Vec0, Vec1}, dl);
  }

  assert(N->getNumValues() == 1 &&
         "Can't unroll a vector with multiple results!");

  SmallVector<SDValue, 8> Scalars;
  SmallVector<SDValue, 4> Operands(N->getNumOperands());

  unsigned i;
  for (i= 0; i != NE; ++i) {
    for (unsigned j = 0, e = N->getNumOperands(); j != e; ++j) {
      SDValue Operand = N->getOperand(j);
      EVT OperandVT = Operand.getValueType();
      if (OperandVT.isVector()) {
        // A vector operand; extract a single element.
        EVT OperandEltVT = OperandVT.getVectorElementType();
        Operands[j] = getExtractVectorElt(dl, OperandEltVT, Operand, i);
      } else {
        // A scalar operand; just use it as is.
        Operands[j] = Operand;
      }
    }

    switch (N->getOpcode()) {
    default: {
      Scalars.push_back(getNode(N->getOpcode(), dl, EltVT, Operands,
                                N->getFlags()));
      break;
    }
    case ISD::VSELECT:
      Scalars.push_back(getNode(ISD::SELECT, dl, EltVT, Operands));
      break;
    case ISD::SHL:
    case ISD::SRA:
    case ISD::SRL:
    case ISD::ROTL:
    case ISD::ROTR:
      Scalars.push_back(getNode(N->getOpcode(), dl, EltVT, Operands[0],
                               getShiftAmountOperand(Operands[0].getValueType(),
                                                     Operands[1])));
      break;
    case ISD::SIGN_EXTEND_INREG: {
      EVT ExtVT = cast<VTSDNode>(Operands[1])->getVT().getVectorElementType();
      Scalars.push_back(getNode(N->getOpcode(), dl, EltVT,
                                Operands[0],
                                getValueType(ExtVT)));
      break;
    }
    case ISD::ADDRSPACECAST: {
      const auto *ASC = cast<AddrSpaceCastSDNode>(N);
      Scalars.push_back(getAddrSpaceCast(dl, EltVT, Operands[0],
                                         ASC->getSrcAddressSpace(),
                                         ASC->getDestAddressSpace()));
      break;
    }
    }
  }

  for (; i < ResNE; ++i)
    Scalars.push_back(getUNDEF(EltVT));

  EVT VecVT = EVT::getVectorVT(*getContext(), EltVT, ResNE);
  return getBuildVector(VecVT, dl, Scalars);
}

std::pair<SDValue, SDValue> SelectionDAG::UnrollVectorOverflowOp(
    SDNode *N, unsigned ResNE) {
  unsigned Opcode = N->getOpcode();
  assert((Opcode == ISD::UADDO || Opcode == ISD::SADDO ||
          Opcode == ISD::USUBO || Opcode == ISD::SSUBO ||
          Opcode == ISD::UMULO || Opcode == ISD::SMULO) &&
         "Expected an overflow opcode");

  EVT ResVT = N->getValueType(0);
  EVT OvVT = N->getValueType(1);
  EVT ResEltVT = ResVT.getVectorElementType();
  EVT OvEltVT = OvVT.getVectorElementType();
  SDLoc dl(N);

  // If ResNE is 0, fully unroll the vector op.
  unsigned NE = ResVT.getVectorNumElements();
  if (ResNE == 0)
    ResNE = NE;
  else if (NE > ResNE)
    NE = ResNE;

  SmallVector<SDValue, 8> LHSScalars;
  SmallVector<SDValue, 8> RHSScalars;
  ExtractVectorElements(N->getOperand(0), LHSScalars, 0, NE);
  ExtractVectorElements(N->getOperand(1), RHSScalars, 0, NE);

  EVT SVT = TLI->getSetCCResultType(getDataLayout(), *getContext(), ResEltVT);
  SDVTList VTs = getVTList(ResEltVT, SVT);
  SmallVector<SDValue, 8> ResScalars;
  SmallVector<SDValue, 8> OvScalars;
  for (unsigned i = 0; i < NE; ++i) {
    SDValue Res = getNode(Opcode, dl, VTs, LHSScalars[i], RHSScalars[i]);
    SDValue Ov =
        getSelect(dl, OvEltVT, Res.getValue(1),
                  getBoolConstant(true, dl, OvEltVT, ResVT),
                  getConstant(0, dl, OvEltVT));

    ResScalars.push_back(Res);
    OvScalars.push_back(Ov);
  }

  ResScalars.append(ResNE - NE, getUNDEF(ResEltVT));
  OvScalars.append(ResNE - NE, getUNDEF(OvEltVT));

  EVT NewResVT = EVT::getVectorVT(*getContext(), ResEltVT, ResNE);
  EVT NewOvVT = EVT::getVectorVT(*getContext(), OvEltVT, ResNE);
  return std::make_pair(getBuildVector(NewResVT, dl, ResScalars),
                        getBuildVector(NewOvVT, dl, OvScalars));
}

bool SelectionDAG::areNonVolatileConsecutiveLoads(LoadSDNode *LD,
                                                  LoadSDNode *Base,
                                                  unsigned Bytes,
                                                  int Dist) const {
  if (LD->isVolatile() || Base->isVolatile())
    return false;
  // TODO: probably too restrictive for atomics, revisit
  if (!LD->isSimple())
    return false;
  if (LD->isIndexed() || Base->isIndexed())
    return false;
  if (LD->getChain() != Base->getChain())
    return false;
  EVT VT = LD->getMemoryVT();
  if (VT.getSizeInBits() / 8 != Bytes)
    return false;

  auto BaseLocDecomp = BaseIndexOffset::match(Base, *this);
  auto LocDecomp = BaseIndexOffset::match(LD, *this);

  int64_t Offset = 0;
  if (BaseLocDecomp.equalBaseIndex(LocDecomp, *this, Offset))
    return (Dist * (int64_t)Bytes == Offset);
  return false;
}

/// InferPtrAlignment - Infer alignment of a load / store address. Return
/// std::nullopt if it cannot be inferred.
MaybeAlign SelectionDAG::InferPtrAlign(SDValue Ptr) const {
  // If this is a GlobalAddress + cst, return the alignment.
  const GlobalValue *GV = nullptr;
  int64_t GVOffset = 0;
  if (TLI->isGAPlusOffset(Ptr.getNode(), GV, GVOffset)) {
    unsigned PtrWidth = getDataLayout().getPointerTypeSizeInBits(GV->getType());
    KnownBits Known(PtrWidth);
    llvm::computeKnownBits(GV, Known, getDataLayout());
    unsigned AlignBits = Known.countMinTrailingZeros();
    if (AlignBits)
      return commonAlignment(Align(1ull << std::min(31U, AlignBits)), GVOffset);
  }

  // If this is a direct reference to a stack slot, use information about the
  // stack slot's alignment.
  int FrameIdx = INT_MIN;
  int64_t FrameOffset = 0;
  if (FrameIndexSDNode *FI = dyn_cast<FrameIndexSDNode>(Ptr)) {
    FrameIdx = FI->getIndex();
  } else if (isBaseWithConstantOffset(Ptr) &&
             isa<FrameIndexSDNode>(Ptr.getOperand(0))) {
    // Handle FI+Cst
    FrameIdx = cast<FrameIndexSDNode>(Ptr.getOperand(0))->getIndex();
    FrameOffset = Ptr.getConstantOperandVal(1);
  }

  if (FrameIdx != INT_MIN) {
    const MachineFrameInfo &MFI = getMachineFunction().getFrameInfo();
    return commonAlignment(MFI.getObjectAlign(FrameIdx), FrameOffset);
  }

  return std::nullopt;
}

/// Split the scalar node with EXTRACT_ELEMENT using the provided
/// VTs and return the low/high part.
std::pair<SDValue, SDValue> SelectionDAG::SplitScalar(const SDValue &N,
                                                      const SDLoc &DL,
                                                      const EVT &LoVT,
                                                      const EVT &HiVT) {
  assert(!LoVT.isVector() && !HiVT.isVector() && !N.getValueType().isVector() &&
         "Split node must be a scalar type");
  SDValue Lo =
      getNode(ISD::EXTRACT_ELEMENT, DL, LoVT, N, getIntPtrConstant(0, DL));
  SDValue Hi =
      getNode(ISD::EXTRACT_ELEMENT, DL, HiVT, N, getIntPtrConstant(1, DL));
  return std::make_pair(Lo, Hi);
}

/// GetSplitDestVTs - Compute the VTs needed for the low/hi parts of a type
/// which is split (or expanded) into two not necessarily identical pieces.
std::pair<EVT, EVT> SelectionDAG::GetSplitDestVTs(const EVT &VT) const {
  // Currently all types are split in half.
  EVT LoVT, HiVT;
  if (!VT.isVector())
    LoVT = HiVT = TLI->getTypeToTransformTo(*getContext(), VT);
  else
    LoVT = HiVT = VT.getHalfNumVectorElementsVT(*getContext());

  return std::make_pair(LoVT, HiVT);
}

/// GetDependentSplitDestVTs - Compute the VTs needed for the low/hi parts of a
/// type, dependent on an enveloping VT that has been split into two identical
/// pieces. Sets the HiIsEmpty flag when hi type has zero storage size.
std::pair<EVT, EVT>
SelectionDAG::GetDependentSplitDestVTs(const EVT &VT, const EVT &EnvVT,
                                       bool *HiIsEmpty) const {
  EVT EltTp = VT.getVectorElementType();
  // Examples:
  //   custom VL=8  with enveloping VL=8/8 yields 8/0 (hi empty)
  //   custom VL=9  with enveloping VL=8/8 yields 8/1
  //   custom VL=10 with enveloping VL=8/8 yields 8/2
  //   etc.
  ElementCount VTNumElts = VT.getVectorElementCount();
  ElementCount EnvNumElts = EnvVT.getVectorElementCount();
  assert(VTNumElts.isScalable() == EnvNumElts.isScalable() &&
         "Mixing fixed width and scalable vectors when enveloping a type");
  EVT LoVT, HiVT;
  if (VTNumElts.getKnownMinValue() > EnvNumElts.getKnownMinValue()) {
    LoVT = EVT::getVectorVT(*getContext(), EltTp, EnvNumElts);
    HiVT = EVT::getVectorVT(*getContext(), EltTp, VTNumElts - EnvNumElts);
    *HiIsEmpty = false;
  } else {
    // Flag that hi type has zero storage size, but return split envelop type
    // (this would be easier if vector types with zero elements were allowed).
    LoVT = EVT::getVectorVT(*getContext(), EltTp, VTNumElts);
    HiVT = EVT::getVectorVT(*getContext(), EltTp, EnvNumElts);
    *HiIsEmpty = true;
  }
  return std::make_pair(LoVT, HiVT);
}

/// SplitVector - Split the vector with EXTRACT_SUBVECTOR and return the
/// low/high part.
std::pair<SDValue, SDValue>
SelectionDAG::SplitVector(const SDValue &N, const SDLoc &DL, const EVT &LoVT,
                          const EVT &HiVT) {
  assert(LoVT.isScalableVector() == HiVT.isScalableVector() &&
         LoVT.isScalableVector() == N.getValueType().isScalableVector() &&
         "Splitting vector with an invalid mixture of fixed and scalable "
         "vector types");
  assert(LoVT.getVectorMinNumElements() + HiVT.getVectorMinNumElements() <=
             N.getValueType().getVectorMinNumElements() &&
         "More vector elements requested than available!");
  SDValue Lo, Hi;
  Lo = getExtractSubvector(DL, LoVT, N, 0);
  // For scalable vectors it is safe to use LoVT.getVectorMinNumElements()
  // (rather than having to use ElementCount), because EXTRACT_SUBVECTOR scales
  // IDX with the runtime scaling factor of the result vector type. For
  // fixed-width result vectors, that runtime scaling factor is 1.
  Hi = getNode(ISD::EXTRACT_SUBVECTOR, DL, HiVT, N,
               getVectorIdxConstant(LoVT.getVectorMinNumElements(), DL));
  return std::make_pair(Lo, Hi);
}

std::pair<SDValue, SDValue> SelectionDAG::SplitEVL(SDValue N, EVT VecVT,
                                                   const SDLoc &DL) {
  // Split the vector length parameter.
  // %evl -> umin(%evl, %halfnumelts) and usubsat(%evl - %halfnumelts).
  EVT VT = N.getValueType();
  assert(VecVT.getVectorElementCount().isKnownEven() &&
         "Expecting the mask to be an evenly-sized vector");
  unsigned HalfMinNumElts = VecVT.getVectorMinNumElements() / 2;
  SDValue HalfNumElts =
      VecVT.isFixedLengthVector()
          ? getConstant(HalfMinNumElts, DL, VT)
          : getVScale(DL, VT, APInt(VT.getScalarSizeInBits(), HalfMinNumElts));
  SDValue Lo = getNode(ISD::UMIN, DL, VT, N, HalfNumElts);
  SDValue Hi = getNode(ISD::USUBSAT, DL, VT, N, HalfNumElts);
  return std::make_pair(Lo, Hi);
}

/// Widen the vector up to the next power of two using INSERT_SUBVECTOR.
SDValue SelectionDAG::WidenVector(const SDValue &N, const SDLoc &DL) {
  EVT VT = N.getValueType();
  EVT WideVT = EVT::getVectorVT(*getContext(), VT.getVectorElementType(),
                                NextPowerOf2(VT.getVectorNumElements()));
  return getInsertSubvector(DL, getUNDEF(WideVT), N, 0);
}

void SelectionDAG::ExtractVectorElements(SDValue Op,
                                         SmallVectorImpl<SDValue> &Args,
                                         unsigned Start, unsigned Count,
                                         EVT EltVT) {
  EVT VT = Op.getValueType();
  if (Count == 0)
    Count = VT.getVectorNumElements();
  if (EltVT == EVT())
    EltVT = VT.getVectorElementType();
  SDLoc SL(Op);
  for (unsigned i = Start, e = Start + Count; i != e; ++i) {
    Args.push_back(getExtractVectorElt(SL, EltVT, Op, i));
  }
}

// getAddressSpace - Return the address space this GlobalAddress belongs to.
unsigned GlobalAddressSDNode::getAddressSpace() const {
  return getGlobal()->getType()->getAddressSpace();
}

Type *ConstantPoolSDNode::getType() const {
  if (isMachineConstantPoolEntry())
    return Val.MachineCPVal->getType();
  return Val.ConstVal->getType();
}

bool BuildVectorSDNode::isConstantSplat(APInt &SplatValue, APInt &SplatUndef,
                                        unsigned &SplatBitSize,
                                        bool &HasAnyUndefs,
                                        unsigned MinSplatBits,
                                        bool IsBigEndian) const {
  EVT VT = getValueType(0);
  assert(VT.isVector() && "Expected a vector type");
  unsigned VecWidth = VT.getSizeInBits();
  if (MinSplatBits > VecWidth)
    return false;

  // FIXME: The widths are based on this node's type, but build vectors can
  // truncate their operands.
  SplatValue = APInt(VecWidth, 0);
  SplatUndef = APInt(VecWidth, 0);

  // Get the bits. Bits with undefined values (when the corresponding element
  // of the vector is an ISD::UNDEF value) are set in SplatUndef and cleared
  // in SplatValue. If any of the values are not constant, give up and return
  // false.
  unsigned int NumOps = getNumOperands();
  assert(NumOps > 0 && "isConstantSplat has 0-size build vector");
  unsigned EltWidth = VT.getScalarSizeInBits();

  for (unsigned j = 0; j < NumOps; ++j) {
    unsigned i = IsBigEndian ? NumOps - 1 - j : j;
    SDValue OpVal = getOperand(i);
    unsigned BitPos = j * EltWidth;

    if (OpVal.isUndef())
      SplatUndef.setBits(BitPos, BitPos + EltWidth);
    else if (auto *CN = dyn_cast<ConstantSDNode>(OpVal))
      SplatValue.insertBits(CN->getAPIntValue().zextOrTrunc(EltWidth), BitPos);
    else if (auto *CN = dyn_cast<ConstantFPSDNode>(OpVal))
      SplatValue.insertBits(CN->getValueAPF().bitcastToAPInt(), BitPos);
    else
      return false;
  }

  // The build_vector is all constants or undefs. Find the smallest element
  // size that splats the vector.
  HasAnyUndefs = (SplatUndef != 0);

  // FIXME: This does not work for vectors with elements less than 8 bits.
  while (VecWidth > 8) {
    // If we can't split in half, stop here.
    if (VecWidth & 1)
      break;

    unsigned HalfSize = VecWidth / 2;
    APInt HighValue = SplatValue.extractBits(HalfSize, HalfSize);
    APInt LowValue = SplatValue.extractBits(HalfSize, 0);
    APInt HighUndef = SplatUndef.extractBits(HalfSize, HalfSize);
    APInt LowUndef = SplatUndef.extractBits(HalfSize, 0);

    // If the two halves do not match (ignoring undef bits), stop here.
    if ((HighValue & ~LowUndef) != (LowValue & ~HighUndef) ||
        MinSplatBits > HalfSize)
      break;

    SplatValue = HighValue | LowValue;
    SplatUndef = HighUndef & LowUndef;

    VecWidth = HalfSize;
  }

  // FIXME: The loop above only tries to split in halves. But if the input
  // vector for example is <3 x i16> it wouldn't be able to detect a
  // SplatBitSize of 16. No idea if that is a design flaw currently limiting
  // optimizations. I guess that back in the days when this helper was created
  // vectors normally was power-of-2 sized.

  SplatBitSize = VecWidth;
  return true;
}

SDValue BuildVectorSDNode::getSplatValue(const APInt &DemandedElts,
                                         BitVector *UndefElements) const {
  unsigned NumOps = getNumOperands();
  if (UndefElements) {
    UndefElements->clear();
    UndefElements->resize(NumOps);
  }
  assert(NumOps == DemandedElts.getBitWidth() && "Unexpected vector size");
  if (!DemandedElts)
    return SDValue();
  SDValue Splatted;
  for (unsigned i = 0; i != NumOps; ++i) {
    if (!DemandedElts[i])
      continue;
    SDValue Op = getOperand(i);
    if (Op.isUndef()) {
      if (UndefElements)
        (*UndefElements)[i] = true;
    } else if (!Splatted) {
      Splatted = Op;
    } else if (Splatted != Op) {
      return SDValue();
    }
  }

  if (!Splatted) {
    unsigned FirstDemandedIdx = DemandedElts.countr_zero();
    assert(getOperand(FirstDemandedIdx).isUndef() &&
           "Can only have a splat without a constant for all undefs.");
    return getOperand(FirstDemandedIdx);
  }

  return Splatted;
}

SDValue BuildVectorSDNode::getSplatValue(BitVector *UndefElements) const {
  APInt DemandedElts = APInt::getAllOnes(getNumOperands());
  return getSplatValue(DemandedElts, UndefElements);
}

bool BuildVectorSDNode::getRepeatedSequence(const APInt &DemandedElts,
                                            SmallVectorImpl<SDValue> &Sequence,
                                            BitVector *UndefElements) const {
  unsigned NumOps = getNumOperands();
  Sequence.clear();
  if (UndefElements) {
    UndefElements->clear();
    UndefElements->resize(NumOps);
  }
  assert(NumOps == DemandedElts.getBitWidth() && "Unexpected vector size");
  if (!DemandedElts || NumOps < 2 || !isPowerOf2_32(NumOps))
    return false;

  // Set the undefs even if we don't find a sequence (like getSplatValue).
  if (UndefElements)
    for (unsigned I = 0; I != NumOps; ++I)
      if (DemandedElts[I] && getOperand(I).isUndef())
        (*UndefElements)[I] = true;

  // Iteratively widen the sequence length looking for repetitions.
  for (unsigned SeqLen = 1; SeqLen < NumOps; SeqLen *= 2) {
    Sequence.append(SeqLen, SDValue());
    for (unsigned I = 0; I != NumOps; ++I) {
      if (!DemandedElts[I])
        continue;
      SDValue &SeqOp = Sequence[I % SeqLen];
      SDValue Op = getOperand(I);
      if (Op.isUndef()) {
        if (!SeqOp)
          SeqOp = Op;
        continue;
      }
      if (SeqOp && !SeqOp.isUndef() && SeqOp != Op) {
        Sequence.clear();
        break;
      }
      SeqOp = Op;
    }
    if (!Sequence.empty())
      return true;
  }

  assert(Sequence.empty() && "Failed to empty non-repeating sequence pattern");
  return false;
}

bool BuildVectorSDNode::getRepeatedSequence(SmallVectorImpl<SDValue> &Sequence,
                                            BitVector *UndefElements) const {
  APInt DemandedElts = APInt::getAllOnes(getNumOperands());
  return getRepeatedSequence(DemandedElts, Sequence, UndefElements);
}

ConstantSDNode *
BuildVectorSDNode::getConstantSplatNode(const APInt &DemandedElts,
                                        BitVector *UndefElements) const {
  return dyn_cast_or_null<ConstantSDNode>(
      getSplatValue(DemandedElts, UndefElements));
}

ConstantSDNode *
BuildVectorSDNode::getConstantSplatNode(BitVector *UndefElements) const {
  return dyn_cast_or_null<ConstantSDNode>(getSplatValue(UndefElements));
}

ConstantFPSDNode *
BuildVectorSDNode::getConstantFPSplatNode(const APInt &DemandedElts,
                                          BitVector *UndefElements) const {
  return dyn_cast_or_null<ConstantFPSDNode>(
      getSplatValue(DemandedElts, UndefElements));
}

ConstantFPSDNode *
BuildVectorSDNode::getConstantFPSplatNode(BitVector *UndefElements) const {
  return dyn_cast_or_null<ConstantFPSDNode>(getSplatValue(UndefElements));
}

int32_t
BuildVectorSDNode::getConstantFPSplatPow2ToLog2Int(BitVector *UndefElements,
                                                   uint32_t BitWidth) const {
  if (ConstantFPSDNode *CN =
          dyn_cast_or_null<ConstantFPSDNode>(getSplatValue(UndefElements))) {
    bool IsExact;
    APSInt IntVal(BitWidth);
    const APFloat &APF = CN->getValueAPF();
    if (APF.convertToInteger(IntVal, APFloat::rmTowardZero, &IsExact) !=
            APFloat::opOK ||
        !IsExact)
      return -1;

    return IntVal.exactLogBase2();
  }
  return -1;
}

bool BuildVectorSDNode::getConstantRawBits(
    bool IsLittleEndian, unsigned DstEltSizeInBits,
    SmallVectorImpl<APInt> &RawBitElements, BitVector &UndefElements) const {
  // Early-out if this contains anything but Undef/Constant/ConstantFP.
  if (!isConstant())
    return false;

  unsigned NumSrcOps = getNumOperands();
  unsigned SrcEltSizeInBits = getValueType(0).getScalarSizeInBits();
  assert(((NumSrcOps * SrcEltSizeInBits) % DstEltSizeInBits) == 0 &&
         "Invalid bitcast scale");

  // Extract raw src bits.
  SmallVector<APInt> SrcBitElements(NumSrcOps,
                                    APInt::getZero(SrcEltSizeInBits));
  BitVector SrcUndeElements(NumSrcOps, false);

  for (unsigned I = 0; I != NumSrcOps; ++I) {
    SDValue Op = getOperand(I);
    if (Op.isUndef()) {
      SrcUndeElements.set(I);
      continue;
    }
    auto *CInt = dyn_cast<ConstantSDNode>(Op);
    auto *CFP = dyn_cast<ConstantFPSDNode>(Op);
    assert((CInt || CFP) && "Unknown constant");
    SrcBitElements[I] = CInt ? CInt->getAPIntValue().trunc(SrcEltSizeInBits)
                             : CFP->getValueAPF().bitcastToAPInt();
  }

  // Recast to dst width.
  recastRawBits(IsLittleEndian, DstEltSizeInBits, RawBitElements,
                SrcBitElements, UndefElements, SrcUndeElements);
  return true;
}

void BuildVectorSDNode::recastRawBits(bool IsLittleEndian,
                                      unsigned DstEltSizeInBits,
                                      SmallVectorImpl<APInt> &DstBitElements,
                                      ArrayRef<APInt> SrcBitElements,
                                      BitVector &DstUndefElements,
                                      const BitVector &SrcUndefElements) {
  unsigned NumSrcOps = SrcBitElements.size();
  unsigned SrcEltSizeInBits = SrcBitElements[0].getBitWidth();
  assert(((NumSrcOps * SrcEltSizeInBits) % DstEltSizeInBits) == 0 &&
         "Invalid bitcast scale");
  assert(NumSrcOps == SrcUndefElements.size() &&
         "Vector size mismatch");

  unsigned NumDstOps = (NumSrcOps * SrcEltSizeInBits) / DstEltSizeInBits;
  DstUndefElements.clear();
  DstUndefElements.resize(NumDstOps, false);
  DstBitElements.assign(NumDstOps, APInt::getZero(DstEltSizeInBits));

  // Concatenate src elements constant bits together into dst element.
  if (SrcEltSizeInBits <= DstEltSizeInBits) {
    unsigned Scale = DstEltSizeInBits / SrcEltSizeInBits;
    for (unsigned I = 0; I != NumDstOps; ++I) {
      DstUndefElements.set(I);
      APInt &DstBits = DstBitElements[I];
      for (unsigned J = 0; J != Scale; ++J) {
        unsigned Idx = (I * Scale) + (IsLittleEndian ? J : (Scale - J - 1));
        if (SrcUndefElements[Idx])
          continue;
        DstUndefElements.reset(I);
        const APInt &SrcBits = SrcBitElements[Idx];
        assert(SrcBits.getBitWidth() == SrcEltSizeInBits &&
               "Illegal constant bitwidths");
        DstBits.insertBits(SrcBits, J * SrcEltSizeInBits);
      }
    }
    return;
  }

  // Split src element constant bits into dst elements.
  unsigned Scale = SrcEltSizeInBits / DstEltSizeInBits;
  for (unsigned I = 0; I != NumSrcOps; ++I) {
    if (SrcUndefElements[I]) {
      DstUndefElements.set(I * Scale, (I + 1) * Scale);
      continue;
    }
    const APInt &SrcBits = SrcBitElements[I];
    for (unsigned J = 0; J != Scale; ++J) {
      unsigned Idx = (I * Scale) + (IsLittleEndian ? J : (Scale - J - 1));
      APInt &DstBits = DstBitElements[Idx];
      DstBits = SrcBits.extractBits(DstEltSizeInBits, J * DstEltSizeInBits);
    }
  }
}

bool BuildVectorSDNode::isConstant() const {
  for (const SDValue &Op : op_values()) {
    unsigned Opc = Op.getOpcode();
    if (!Op.isUndef() && Opc != ISD::Constant && Opc != ISD::ConstantFP)
      return false;
  }
  return true;
}

std::optional<std::pair<APInt, APInt>>
BuildVectorSDNode::isConstantSequence() const {
  unsigned NumOps = getNumOperands();
  if (NumOps < 2)
    return std::nullopt;

  if (!isa<ConstantSDNode>(getOperand(0)) ||
      !isa<ConstantSDNode>(getOperand(1)))
    return std::nullopt;

  unsigned EltSize = getValueType(0).getScalarSizeInBits();
  APInt Start = getConstantOperandAPInt(0).trunc(EltSize);
  APInt Stride = getConstantOperandAPInt(1).trunc(EltSize) - Start;

  if (Stride.isZero())
    return std::nullopt;

  for (unsigned i = 2; i < NumOps; ++i) {
    if (!isa<ConstantSDNode>(getOperand(i)))
      return std::nullopt;

    APInt Val = getConstantOperandAPInt(i).trunc(EltSize);
    if (Val != (Start + (Stride * i)))
      return std::nullopt;
  }

  return std::make_pair(Start, Stride);
}

bool ShuffleVectorSDNode::isSplatMask(ArrayRef<int> Mask) {
  // Find the first non-undef value in the shuffle mask.
  unsigned i, e;
  for (i = 0, e = Mask.size(); i != e && Mask[i] < 0; ++i)
    /* search */;

  // If all elements are undefined, this shuffle can be considered a splat
  // (although it should eventually get simplified away completely).
  if (i == e)
    return true;

  // Make sure all remaining elements are either undef or the same as the first
  // non-undef value.
  for (int Idx = Mask[i]; i != e; ++i)
    if (Mask[i] >= 0 && Mask[i] != Idx)
      return false;
  return true;
}

// Returns true if it is a constant integer BuildVector or constant integer,
// possibly hidden by a bitcast.
bool SelectionDAG::isConstantIntBuildVectorOrConstantInt(
    SDValue N, bool AllowOpaques) const {
  N = peekThroughBitcasts(N);

  if (auto *C = dyn_cast<ConstantSDNode>(N))
    return AllowOpaques || !C->isOpaque();

  if (ISD::isBuildVectorOfConstantSDNodes(N.getNode()))
    return true;

  // Treat a GlobalAddress supporting constant offset folding as a
  // constant integer.
  if (auto *GA = dyn_cast<GlobalAddressSDNode>(N))
    if (GA->getOpcode() == ISD::GlobalAddress &&
        TLI->isOffsetFoldingLegal(GA))
      return true;

  if ((N.getOpcode() == ISD::SPLAT_VECTOR) &&
      isa<ConstantSDNode>(N.getOperand(0)))
    return true;
  return false;
}

// Returns true if it is a constant float BuildVector or constant float.
bool SelectionDAG::isConstantFPBuildVectorOrConstantFP(SDValue N) const {
  if (isa<ConstantFPSDNode>(N))
    return true;

  if (ISD::isBuildVectorOfConstantFPSDNodes(N.getNode()))
    return true;

  if ((N.getOpcode() == ISD::SPLAT_VECTOR) &&
      isa<ConstantFPSDNode>(N.getOperand(0)))
    return true;

  return false;
}

std::optional<bool> SelectionDAG::isBoolConstant(SDValue N) const {
  ConstantSDNode *Const =
      isConstOrConstSplat(N, false, /*AllowTruncation=*/true);
  if (!Const)
    return std::nullopt;

  EVT VT = N->getValueType(0);
  const APInt CVal = Const->getAPIntValue().trunc(VT.getScalarSizeInBits());
  switch (TLI->getBooleanContents(N.getValueType())) {
  case TargetLowering::ZeroOrOneBooleanContent:
    if (CVal.isOne())
      return true;
    if (CVal.isZero())
      return false;
    return std::nullopt;
  case TargetLowering::ZeroOrNegativeOneBooleanContent:
    if (CVal.isAllOnes())
      return true;
    if (CVal.isZero())
      return false;
    return std::nullopt;
  case TargetLowering::UndefinedBooleanContent:
    return CVal[0];
  }
  llvm_unreachable("Unknown BooleanContent enum");
}

void SelectionDAG::createOperands(SDNode *Node, ArrayRef<SDValue> Vals) {
  assert(!Node->OperandList && "Node already has operands");
  assert(SDNode::getMaxNumOperands() >= Vals.size() &&
         "too many operands to fit into SDNode");
  SDUse *Ops = OperandRecycler.allocate(
      ArrayRecycler<SDUse>::Capacity::get(Vals.size()), OperandAllocator);

  bool IsDivergent = false;
  for (unsigned I = 0; I != Vals.size(); ++I) {
    Ops[I].setUser(Node);
    Ops[I].setInitial(Vals[I]);
    EVT VT = Ops[I].getValueType();

    // Take care of the Node's operands iff target has divergence
    // Skip Chain. It does not carry divergence.
    if (DivergentTarget && VT != MVT::Other &&
        (VT != MVT::Glue || gluePropagatesDivergence(Ops[I].getNode())) &&
        Ops[I].getNode()->isDivergent()) {
      // Node is going to be divergent if at least one of its operand is
      // divergent, unless it belongs to the "AlwaysUniform" exemptions.
      IsDivergent = true;
    }
  }
  Node->NumOperands = Vals.size();
  Node->OperandList = Ops;
  // Check the divergence of the Node itself.
  if (DivergentTarget && !TLI->isSDNodeAlwaysUniform(Node)) {
    IsDivergent |= TLI->isSDNodeSourceOfDivergence(Node, FLI, UA);
    Node->SDNodeBits.IsDivergent = IsDivergent;
  }
  checkForCycles(Node);
}

SDValue SelectionDAG::getTokenFactor(const SDLoc &DL,
                                     SmallVectorImpl<SDValue> &Vals) {
  size_t Limit = SDNode::getMaxNumOperands();
  while (Vals.size() > Limit) {
    unsigned SliceIdx = Vals.size() - Limit;
    auto ExtractedTFs = ArrayRef<SDValue>(Vals).slice(SliceIdx, Limit);
    SDValue NewTF = getNode(ISD::TokenFactor, DL, MVT::Other, ExtractedTFs);
    Vals.erase(Vals.begin() + SliceIdx, Vals.end());
    Vals.emplace_back(NewTF);
  }
  return getNode(ISD::TokenFactor, DL, MVT::Other, Vals);
}

SDValue SelectionDAG::getNeutralElement(unsigned Opcode, const SDLoc &DL,
                                        EVT VT, SDNodeFlags Flags) {
  switch (Opcode) {
  default:
    return SDValue();
  case ISD::ADD:
  case ISD::OR:
  case ISD::XOR:
  case ISD::UMAX:
    return getConstant(0, DL, VT);
  case ISD::MUL:
    return getConstant(1, DL, VT);
  case ISD::AND:
  case ISD::UMIN:
    return getAllOnesConstant(DL, VT);
  case ISD::SMAX:
    return getConstant(APInt::getSignedMinValue(VT.getSizeInBits()), DL, VT);
  case ISD::SMIN:
    return getConstant(APInt::getSignedMaxValue(VT.getSizeInBits()), DL, VT);
  case ISD::FADD:
    // If flags allow, prefer positive zero since it's generally cheaper
    // to materialize on most targets.
    return getConstantFP(Flags.hasNoSignedZeros() ? 0.0 : -0.0, DL, VT);
  case ISD::FMUL:
    return getConstantFP(1.0, DL, VT);
  case ISD::FMINNUM:
  case ISD::FMAXNUM: {
    // Neutral element for fminnum is NaN, Inf or FLT_MAX, depending on FMF.
    const fltSemantics &Semantics = VT.getFltSemantics();
    APFloat NeutralAF = !Flags.hasNoNaNs() ? APFloat::getQNaN(Semantics) :
                        !Flags.hasNoInfs() ? APFloat::getInf(Semantics) :
                        APFloat::getLargest(Semantics);
    if (Opcode == ISD::FMAXNUM)
      NeutralAF.changeSign();

    return getConstantFP(NeutralAF, DL, VT);
  }
  case ISD::FMINIMUM:
  case ISD::FMAXIMUM: {
    // Neutral element for fminimum is Inf or FLT_MAX, depending on FMF.
    const fltSemantics &Semantics = VT.getFltSemantics();
    APFloat NeutralAF = !Flags.hasNoInfs() ? APFloat::getInf(Semantics)
                                           : APFloat::getLargest(Semantics);
    if (Opcode == ISD::FMAXIMUM)
      NeutralAF.changeSign();

    return getConstantFP(NeutralAF, DL, VT);
  }

  }
}

/// Helper used to make a call to a library function that has one argument of
/// pointer type.
///
/// Such functions include 'fegetmode', 'fesetenv' and some others, which are
/// used to get or set floating-point state. They have one argument of pointer
/// type, which points to the memory region containing bits of the
/// floating-point state. The value returned by such function is ignored in the
/// created call.
///
/// \param LibFunc Reference to library function (value of RTLIB::Libcall).
/// \param Ptr Pointer used to save/load state.
/// \param InChain Ingoing token chain.
/// \returns Outgoing chain token.
SDValue SelectionDAG::makeStateFunctionCall(unsigned LibFunc, SDValue Ptr,
                                            SDValue InChain,
                                            const SDLoc &DLoc) {
  assert(InChain.getValueType() == MVT::Other && "Expected token chain");
  TargetLowering::ArgListTy Args;
  TargetLowering::ArgListEntry Entry;
  Entry.Node = Ptr;
  Entry.Ty = Ptr.getValueType().getTypeForEVT(*getContext());
  Args.push_back(Entry);
  RTLIB::Libcall LC = static_cast<RTLIB::Libcall>(LibFunc);
  SDValue Callee = getExternalSymbol(TLI->getLibcallName(LC),
                                     TLI->getPointerTy(getDataLayout()));
  TargetLowering::CallLoweringInfo CLI(*this);
  CLI.setDebugLoc(DLoc).setChain(InChain).setLibCallee(
      TLI->getLibcallCallingConv(LC), Type::getVoidTy(*getContext()), Callee,
      std::move(Args));
  return TLI->LowerCallTo(CLI).second;
}

void SelectionDAG::copyExtraInfo(SDNode *From, SDNode *To) {
  assert(From && To && "Invalid SDNode; empty source SDValue?");
  auto I = SDEI.find(From);
  if (I == SDEI.end())
    return;

  // Use of operator[] on the DenseMap may cause an insertion, which invalidates
  // the iterator, hence the need to make a copy to prevent a use-after-free.
  NodeExtraInfo NEI = I->second;
  if (LLVM_LIKELY(!NEI.PCSections)) {
    // No deep copy required for the types of extra info set.
    //
    // FIXME: Investigate if other types of extra info also need deep copy. This
    // depends on the types of nodes they can be attached to: if some extra info
    // is only ever attached to nodes where a replacement To node is always the
    // node where later use and propagation of the extra info has the intended
    // semantics, no deep copy is required.
    SDEI[To] = std::move(NEI);
    return;
  }

  const SDNode *EntrySDN = getEntryNode().getNode();

  // We need to copy NodeExtraInfo to all _new_ nodes that are being introduced
  // through the replacement of From with To. Otherwise, replacements of a node
  // (From) with more complex nodes (To and its operands) may result in lost
  // extra info where the root node (To) is insignificant in further propagating
  // and using extra info when further lowering to MIR.
  //
  // In the first step pre-populate the visited set with the nodes reachable
  // from the old From node. This avoids copying NodeExtraInfo to parts of the
  // DAG that is not new and should be left untouched.
  SmallVector<const SDNode *> Leafs{From}; // Leafs reachable with VisitFrom.
  DenseSet<const SDNode *> FromReach; // The set of nodes reachable from From.
  auto VisitFrom = [&](auto &&Self, const SDNode *N, int MaxDepth) {
    if (MaxDepth == 0) {
      // Remember this node in case we need to increase MaxDepth and continue
      // populating FromReach from this node.
      Leafs.emplace_back(N);
      return;
    }
    if (!FromReach.insert(N).second)
      return;
    for (const SDValue &Op : N->op_values())
      Self(Self, Op.getNode(), MaxDepth - 1);
  };

  // Copy extra info to To and all its transitive operands (that are new).
  SmallPtrSet<const SDNode *, 8> Visited;
  auto DeepCopyTo = [&](auto &&Self, const SDNode *N) {
    if (FromReach.contains(N))
      return true;
    if (!Visited.insert(N).second)
      return true;
    if (EntrySDN == N)
      return false;
    for (const SDValue &Op : N->op_values()) {
      if (N == To && Op.getNode() == EntrySDN) {
        // Special case: New node's operand is the entry node; just need to
        // copy extra info to new node.
        break;
      }
      if (!Self(Self, Op.getNode()))
        return false;
    }
    // Copy only if entry node was not reached.
    SDEI[N] = NEI;
    return true;
  };

  // We first try with a lower MaxDepth, assuming that the path to common
  // operands between From and To is relatively short. This significantly
  // improves performance in the common case. The initial MaxDepth is big
  // enough to avoid retry in the common case; the last MaxDepth is large
  // enough to avoid having to use the fallback below (and protects from
  // potential stack exhaustion from recursion).
  for (int PrevDepth = 0, MaxDepth = 16; MaxDepth <= 1024;
       PrevDepth = MaxDepth, MaxDepth *= 2, Visited.clear()) {
    // StartFrom is the previous (or initial) set of leafs reachable at the
    // previous maximum depth.
    SmallVector<const SDNode *> StartFrom;
    std::swap(StartFrom, Leafs);
    for (const SDNode *N : StartFrom)
      VisitFrom(VisitFrom, N, MaxDepth - PrevDepth);
    if (LLVM_LIKELY(DeepCopyTo(DeepCopyTo, To)))
      return;
    // This should happen very rarely (reached the entry node).
    LLVM_DEBUG(dbgs() << __func__ << ": MaxDepth=" << MaxDepth << " too low\n");
    assert(!Leafs.empty());
  }

  // This should not happen - but if it did, that means the subgraph reachable
  // from From has depth greater or equal to maximum MaxDepth, and VisitFrom()
  // could not visit all reachable common operands. Consequently, we were able
  // to reach the entry node.
  errs() << "warning: incomplete propagation of SelectionDAG::NodeExtraInfo\n";
  assert(false && "From subgraph too complex - increase max. MaxDepth?");
  // Best-effort fallback if assertions disabled.
  SDEI[To] = std::move(NEI);
}

#ifndef NDEBUG
static void checkForCyclesHelper(const SDNode *N,
                                 SmallPtrSetImpl<const SDNode*> &Visited,
                                 SmallPtrSetImpl<const SDNode*> &Checked,
                                 const llvm::SelectionDAG *DAG) {
  // If this node has already been checked, don't check it again.
  if (Checked.count(N))
    return;

  // If a node has already been visited on this depth-first walk, reject it as
  // a cycle.
  if (!Visited.insert(N).second) {
    errs() << "Detected cycle in SelectionDAG\n";
    dbgs() << "Offending node:\n";
    N->dumprFull(DAG); dbgs() << "\n";
    abort();
  }

  for (const SDValue &Op : N->op_values())
    checkForCyclesHelper(Op.getNode(), Visited, Checked, DAG);

  Checked.insert(N);
  Visited.erase(N);
}
#endif

void llvm::checkForCycles(const llvm::SDNode *N,
                          const llvm::SelectionDAG *DAG,
                          bool force) {
#ifndef NDEBUG
  bool check = force;
#ifdef EXPENSIVE_CHECKS
  check = true;
#endif  // EXPENSIVE_CHECKS
  if (check) {
    assert(N && "Checking nonexistent SDNode");
    SmallPtrSet<const SDNode*, 32> visited;
    SmallPtrSet<const SDNode*, 32> checked;
    checkForCyclesHelper(N, visited, checked, DAG);
  }
#endif  // !NDEBUG
}

void llvm::checkForCycles(const llvm::SelectionDAG *DAG, bool force) {
  checkForCycles(DAG->getRoot().getNode(), DAG, force);
}
