//===- 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/FoldingSet.h"
#include "llvm/ADT/None.h"
#include "llvm/ADT/STLExtras.h"
#include "llvm/ADT/SmallPtrSet.h"
#include "llvm/ADT/SmallVector.h"
#include "llvm/ADT/Triple.h"
#include "llvm/ADT/Twine.h"
#include "llvm/Analysis/ValueTracking.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/RuntimeLibcalls.h"
#include "llvm/CodeGen/SelectionDAGAddressAnalysis.h"
#include "llvm/CodeGen/SelectionDAGNodes.h"
#include "llvm/CodeGen/SelectionDAGTargetInfo.h"
#include "llvm/CodeGen/TargetLowering.h"
#include "llvm/CodeGen/TargetRegisterInfo.h"
#include "llvm/CodeGen/TargetSubtargetInfo.h"
#include "llvm/CodeGen/ValueTypes.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/IR/Value.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/MachineValueType.h"
#include "llvm/Support/ManagedStatic.h"
#include "llvm/Support/MathExtras.h"
#include "llvm/Support/Mutex.h"
#include "llvm/Support/raw_ostream.h"
#include "llvm/Target/TargetMachine.h"
#include "llvm/Target/TargetOptions.h"
#include <algorithm>
#include <cassert>
#include <cstdint>
#include <cstdlib>
#include <limits>
#include <set>
#include <string>
#include <utility>
#include <vector>

using namespace llvm;

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

#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 void NewSDValueDbgMsg(SDValue V, StringRef Msg, SelectionDAG *G) {
  LLVM_DEBUG(dbgs() << Msg; V.getNode()->dump(G););
}

//===----------------------------------------------------------------------===//
//                              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(SelectionDAG::EVTToAPFloatSemantics(VT),
                      APFloat::rmNearestTiesToEven,
                      &losesInfo);
  return !losesInfo;
}

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

bool ISD::isConstantSplatVector(const SDNode *N, APInt &SplatVal) {
  auto *BV = dyn_cast<BuildVectorSDNode>(N);
  if (!BV)
    return false;

  APInt SplatUndef;
  unsigned SplatBitSize;
  bool HasUndefs;
  unsigned EltSize = N->getValueType(0).getVectorElementType().getSizeInBits();
  return BV->isConstantSplat(SplatVal, SplatUndef, SplatBitSize, HasUndefs,
                             EltSize) &&
         EltSize == SplatBitSize;
}

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

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

  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);
  unsigned EltSize = N->getValueType(0).getScalarSizeInBits();
  if (ConstantSDNode *CN = dyn_cast<ConstantSDNode>(NotZero)) {
    if (CN->getAPIntValue().countTrailingOnes() < EltSize)
      return false;
  } else if (ConstantFPSDNode *CFPN = dyn_cast<ConstantFPSDNode>(NotZero)) {
    if (CFPN->getValueAPF().bitcastToAPInt().countTrailingOnes() < 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::isBuildVectorAllZeros(const SDNode *N) {
  // Look through a bit convert.
  while (N->getOpcode() == ISD::BITCAST)
    N = N->getOperand(0).getNode();

  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.
    unsigned EltSize = N->getValueType(0).getScalarSizeInBits();
    if (ConstantSDNode *CN = dyn_cast<ConstantSDNode>(Op)) {
      if (CN->getAPIntValue().countTrailingZeros() < EltSize)
        return false;
    } else if (ConstantFPSDNode *CFPN = dyn_cast<ConstantFPSDNode>(Op)) {
      if (CFPN->getValueAPF().bitcastToAPInt().countTrailingZeros() < EltSize)
        return false;
    } else
      return false;
  }

  // Do not accept an all-undef vector.
  if (IsAllUndef)
    return false;
  return 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::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;

  for (const SDValue &Op : N->op_values())
    if (!Op.isUndef())
      return false;

  return true;
}

bool ISD::matchUnaryPredicate(SDValue Op,
                              std::function<bool(ConstantSDNode *)> Match,
                              bool AllowUndefs) {
  // FIXME: Add support for scalar UNDEF cases?
  if (auto *Cst = dyn_cast<ConstantSDNode>(Op))
    return Match(Cst);

  // FIXME: Add support for vector UNDEF cases?
  if (ISD::BUILD_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<ConstantSDNode>(Op.getOperand(i));
    if (!Cst || Cst->getValueType(0) != SVT || !Match(Cst))
      return false;
  }
  return true;
}

bool ISD::matchBinaryPredicate(
    SDValue LHS, SDValue RHS,
    std::function<bool(ConstantSDNode *, ConstantSDNode *)> Match,
    bool AllowUndefs) {
  if (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 (ISD::BUILD_VECTOR != LHS.getOpcode() ||
      ISD::BUILD_VECTOR != RHS.getOpcode())
    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 (LHSOp.getValueType() != SVT ||
        LHSOp.getValueType() != RHSOp.getValueType())
      return false;
    if (!Match(LHSCst, RHSCst))
      return false;
  }
  return true;
}

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

ISD::CondCode ISD::getSetCCInverse(ISD::CondCode Op, bool isInteger) {
  unsigned Operation = Op;
  if (isInteger)
    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);
}

/// 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,
                                       bool 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,
                                        bool 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 (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 (auto& Op : Ops) {
    ID.AddPointer(Op.getNode());
    ID.AddInteger(Op.getResNo());
  }
}

static void AddNodeIDNode(FoldingSetNodeID &ID, unsigned short 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());
    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::LIFETIME_START:
  case ISD::LIFETIME_END:
    if (cast<LifetimeSDNode>(N)->hasOffset()) {
      ID.AddInteger(cast<LifetimeSDNode>(N)->getSize());
      ID.AddInteger(cast<LifetimeSDNode>(N)->getOffset());
    }
    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->getAlignment());
    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());
    break;
  }
  case ISD::STORE: {
    const StoreSDNode *ST = cast<StoreSDNode>(N);
    ID.AddInteger(ST->getMemoryVT().getRawBits());
    ID.AddInteger(ST->getRawSubclassData());
    ID.AddInteger(ST->getPointerInfo().getAddrSpace());
    break;
  }
  case ISD::MLOAD: {
    const MaskedLoadSDNode *MLD = cast<MaskedLoadSDNode>(N);
    ID.AddInteger(MLD->getMemoryVT().getRawBits());
    ID.AddInteger(MLD->getRawSubclassData());
    ID.AddInteger(MLD->getPointerInfo().getAddrSpace());
    break;
  }
  case ISD::MSTORE: {
    const MaskedStoreSDNode *MST = cast<MaskedStoreSDNode>(N);
    ID.AddInteger(MST->getMemoryVT().getRawBits());
    ID.AddInteger(MST->getRawSubclassData());
    ID.AddInteger(MST->getPointerInfo().getAddrSpace());
    break;
  }
  case ISD::MGATHER: {
    const MaskedGatherSDNode *MG = cast<MaskedGatherSDNode>(N);
    ID.AddInteger(MG->getMemoryVT().getRawBits());
    ID.AddInteger(MG->getRawSubclassData());
    ID.AddInteger(MG->getPointerInfo().getAddrSpace());
    break;
  }
  case ISD::MSCATTER: {
    const MaskedScatterSDNode *MS = cast<MaskedScatterSDNode>(N);
    ID.AddInteger(MS->getMemoryVT().getRawBits());
    ID.AddInteger(MS->getRawSubclassData());
    ID.AddInteger(MS->getPointerInfo().getAddrSpace());
    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());
    break;
  }
  case ISD::PREFETCH: {
    const MemSDNode *PF = cast<MemSDNode>(N);
    ID.AddInteger(PF->getPointerInfo().getAddrSpace());
    break;
  }
  case ISD::VECTOR_SHUFFLE: {
    const ShuffleVectorSDNode *SVN = cast<ShuffleVectorSDNode>(N);
    for (unsigned i = 0, e = N->getValueType(0).getVectorNumElements();
         i != e; ++i)
      ID.AddInteger(SVN->getMaskElt(i));
    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;
  }
  } // end switch (N->getOpcode())

  // Target specific memory nodes could also have address spaces to check.
  if (N->isTargetMemoryOpcode())
    ID.AddInteger(cast<MemSDNode>(N)->getPointerInfo().getAddrSpace());
}

/// 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 flag.

  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 flag.

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

#ifndef NDEBUG
/// VerifySDNode - Sanity check the given SDNode.  Aborts if it is invalid.
static void VerifySDNode(SDNode *N) {
  switch (N->getOpcode()) {
  default:
    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 (SDNode::op_iterator I = N->op_begin(), E = N->op_end(); I != E; ++I) {
      assert((I->getValueType() == EltVT ||
             (EltVT.isInteger() && I->getValueType().isInteger() &&
              EltVT.bitsLE(I->getValueType()))) &&
            "Wrong operand type!");
      assert(I->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++;
  VerifySDNode(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 char>(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
  // flag 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.
      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;
}

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

  return getDataLayout().getABITypeAlignment(Ty);
}

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

void SelectionDAG::init(MachineFunction &NewMF,
                        OptimizationRemarkEmitter &NewORE,
                        Pass *PassPtr, const TargetLibraryInfo *LibraryInfo,
                        LegacyDivergenceAnalysis * Divergence) {
  MF = &NewMF;
  SDAGISelPass = PassPtr;
  ORE = &NewORE;
  TLI = getSubtarget().getTargetLowering();
  TSI = getSubtarget().getSelectionDAGInfo();
  LibInfo = LibraryInfo;
  Context = &MF->getFunction().getContext();
  DA = Divergence;
}

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

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();
  std::fill(CondCodeNodes.begin(), CondCodeNodes.end(),
            static_cast<CondCodeSDNode*>(nullptr));
  std::fill(ValueTypeNodes.begin(), ValueTypeNodes.end(),
            static_cast<SDNode*>(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));
}

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::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) {
  assert(!VT.isVector() &&
         "getZeroExtendInReg should use the vector element type instead of "
         "the vector type!");
  if (Op.getValueType().getScalarType() == VT) return Op;
  unsigned BitWidth = Op.getScalarValueSizeInBits();
  APInt Imm = APInt::getLowBitsSet(BitWidth,
                                   VT.getSizeInBits());
  return getNode(ISD::AND, DL, Op.getValueType(), Op,
                 getConstant(Imm, DL, Op.getValueType()));
}

/// getNOT - Create a bitwise NOT operation as (XOR Val, -1).
SDValue SelectionDAG::getNOT(const SDLoc &DL, SDValue Val, EVT VT) {
  EVT EltVT = VT.getScalarType();
  SDValue NegOne =
    getConstant(APInt::getAllOnesValue(EltVT.getSizeInBits()), DL, VT);
  return getNode(ISD::XOR, DL, VT, Val, NegOne);
}

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::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) {
  EVT EltVT = VT.getScalarType();
  assert((EltVT.getSizeInBits() >= 64 ||
         (uint64_t)((int64_t)Val >> EltVT.getSizeInBits()) + 1 < 2) &&
         "getConstant with a uint64_t value that doesn't fit in the type!");
  return getConstant(APInt(EltVT.getSizeInBits(), Val), 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;

  // 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 = 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();
    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.lshr(i * ViaEltSizeInBits)
                                           .zextOrTrunc(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)
      Ops.insert(Ops.end(), EltParts.begin(), EltParts.end());

    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;
  FoldingSetNodeID ID;
  AddNodeIDNode(ID, Opc, getVTList(EltVT), None);
  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, EltVT);
    CSEMap.InsertNode(N, IP);
    InsertNode(N);
    NewSDValueDbgMsg(SDValue(N, 0), "Creating constant: ", this);
  }

  SDValue Result(N, 0);
  if (VT.isVector())
    Result = getSplatBuildVector(VT, DL, Result);

  return Result;
}

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, bool LegalTypes) {
  EVT ShiftVT = TLI->getShiftAmountTy(VT, getDataLayout(), LegalTypes);
  return getConstant(Val, DL, ShiftVT);
}

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

  // 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;
  FoldingSetNodeID ID;
  AddNodeIDNode(ID, Opc, getVTList(EltVT), None);
  ID.AddPointer(&V);
  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, &V, EltVT);
    CSEMap.InsertNode(N, IP);
    InsertNode(N);
  }

  SDValue Result(N, 0);
  if (VT.isVector())
    Result = getSplatBuildVector(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);
  else if (EltVT == MVT::f64)
    return getConstantFP(APFloat(Val), DL, VT, isTarget);
  else if (EltVT == MVT::f80 || EltVT == MVT::f128 || EltVT == MVT::ppcf128 ||
           EltVT == MVT::f16) {
    bool Ignored;
    APFloat APF = APFloat(Val);
    APF.convert(EVTToAPFloatSemantics(EltVT), APFloat::rmNearestTiesToEven,
                &Ignored);
    return getConstantFP(APF, DL, VT, isTarget);
  } else
    llvm_unreachable("Unsupported type in getConstantFP");
}

SDValue SelectionDAG::getGlobalAddress(const GlobalValue *GV, const SDLoc &DL,
                                       EVT VT, int64_t Offset, bool isTargetGA,
                                       unsigned char 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;

  FoldingSetNodeID ID;
  AddNodeIDNode(ID, Opc, getVTList(VT), None);
  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, VT, 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;
  FoldingSetNodeID ID;
  AddNodeIDNode(ID, Opc, getVTList(VT), None);
  ID.AddInteger(FI);
  void *IP = nullptr;
  if (SDNode *E = FindNodeOrInsertPos(ID, IP))
    return SDValue(E, 0);

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

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

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

SDValue SelectionDAG::getConstantPool(const Constant *C, EVT VT,
                                      unsigned Alignment, int Offset,
                                      bool isTarget,
                                      unsigned char TargetFlags) {
  assert((TargetFlags == 0 || isTarget) &&
         "Cannot set target flags on target-independent globals");
  if (Alignment == 0)
    Alignment = MF->getFunction().hasOptSize()
                    ? getDataLayout().getABITypeAlignment(C->getType())
                    : getDataLayout().getPrefTypeAlignment(C->getType());
  unsigned Opc = isTarget ? ISD::TargetConstantPool : ISD::ConstantPool;
  FoldingSetNodeID ID;
  AddNodeIDNode(ID, Opc, getVTList(VT), None);
  ID.AddInteger(Alignment);
  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, VT, Offset, Alignment,
                                          TargetFlags);
  CSEMap.InsertNode(N, IP);
  InsertNode(N);
  return SDValue(N, 0);
}

SDValue SelectionDAG::getConstantPool(MachineConstantPoolValue *C, EVT VT,
                                      unsigned Alignment, int Offset,
                                      bool isTarget,
                                      unsigned char TargetFlags) {
  assert((TargetFlags == 0 || isTarget) &&
         "Cannot set target flags on target-independent globals");
  if (Alignment == 0)
    Alignment = getDataLayout().getPrefTypeAlignment(C->getType());
  unsigned Opc = isTarget ? ISD::TargetConstantPool : ISD::ConstantPool;
  FoldingSetNodeID ID;
  AddNodeIDNode(ID, Opc, getVTList(VT), None);
  ID.AddInteger(Alignment);
  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, VT, Offset, Alignment,
                                          TargetFlags);
  CSEMap.InsertNode(N, IP);
  InsertNode(N);
  return SDValue(N, 0);
}

SDValue SelectionDAG::getTargetIndex(int Index, EVT VT, int64_t Offset,
                                     unsigned char TargetFlags) {
  FoldingSetNodeID ID;
  AddNodeIDNode(ID, ISD::TargetIndex, getVTList(VT), None);
  ID.AddInteger(Index);
  ID.AddInteger(Offset);
  ID.AddInteger(TargetFlags);
  void *IP = nullptr;
  if (SDNode *E = FindNodeOrInsertPos(ID, IP))
    return SDValue(E, 0);

  auto *N = newSDNode<TargetIndexSDNode>(Index, VT, Offset, 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), None);
  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, 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, VT);
  InsertNode(N);
  return SDValue(N, 0);
}

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

/// 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.begin(), Mask.end());

  // 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)
          return N1;
        if (auto *C = dyn_cast<ConstantSDNode>(Splat))
          if (C->isNullValue())
            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;
      }
    }
  }

  FoldingSetNodeID ID;
  SDValue Ops[2] = { N1, N2 };
  AddNodeIDNode(ID, ISD::VECTOR_SHUFFLE, getVTList(VT), 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>(VT, 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().begin(), SV.getMask().end());
  ShuffleVectorSDNode::commuteMask(MaskVec);

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

SDValue SelectionDAG::getRegister(unsigned RegNo, EVT VT) {
  FoldingSetNodeID ID;
  AddNodeIDNode(ID, ISD::Register, getVTList(VT), None);
  ID.AddInteger(RegNo);
  void *IP = nullptr;
  if (SDNode *E = FindNodeOrInsertPos(ID, IP))
    return SDValue(E, 0);

  auto *N = newSDNode<RegisterSDNode>(RegNo, VT);
  N->SDNodeBits.IsDivergent = TLI->isSDNodeSourceOfDivergence(N, FLI, DA);
  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), None);
  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>(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 char TargetFlags) {
  unsigned Opc = isTarget ? ISD::TargetBlockAddress : ISD::BlockAddress;

  FoldingSetNodeID ID;
  AddNodeIDNode(ID, Opc, getVTList(VT), None);
  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, VT, BA, Offset, TargetFlags);
  CSEMap.InsertNode(N, IP);
  InsertNode(N);
  return SDValue(N, 0);
}

SDValue SelectionDAG::getSrcValue(const Value *V) {
  assert((!V || V->getType()->isPointerTy()) &&
         "SrcValue is not a pointer?");

  FoldingSetNodeID ID;
  AddNodeIDNode(ID, ISD::SRCVALUE, getVTList(MVT::Other), None);
  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), None);
  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) {
  SDValue Ops[] = {Ptr};
  FoldingSetNodeID ID;
  AddNodeIDNode(ID, ISD::ADDRSPACECAST, getVTList(VT), 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(),
                                           VT, SrcAS, DestAS);
  createOperands(N, Ops);

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

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

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);
  unsigned Align = Node->getConstantOperandVal(3);

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

  if (Align > TLI.getMinStackArgumentAlignment()) {
    assert(((Align & (Align-1)) == 0) && "Expected Align to be a power of 2");

    VAList = getNode(ISD::ADD, dl, VAList.getValueType(), VAList,
                     getConstant(Align - 1, dl, VAList.getValueType()));

    VAList = getNode(ISD::AND, dl, VAList.getValueType(), VAList,
                     getConstant(-(int64_t)Align, 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));
}

SDValue SelectionDAG::CreateStackTemporary(EVT VT, unsigned minAlign) {
  MachineFrameInfo &MFI = getMachineFunction().getFrameInfo();
  unsigned ByteSize = VT.getStoreSize();
  Type *Ty = VT.getTypeForEVT(*getContext());
  unsigned StackAlign =
      std::max((unsigned)getDataLayout().getPrefTypeAlignment(Ty), minAlign);

  int FrameIdx = MFI.CreateStackObject(ByteSize, StackAlign, false);
  return getFrameIndex(FrameIdx, TLI->getFrameIndexTy(getDataLayout()));
}

SDValue SelectionDAG::CreateStackTemporary(EVT VT1, EVT VT2) {
  unsigned Bytes = std::max(VT1.getStoreSize(), VT2.getStoreSize());
  Type *Ty1 = VT1.getTypeForEVT(*getContext());
  Type *Ty2 = VT2.getTypeForEVT(*getContext());
  const DataLayout &DL = getDataLayout();
  unsigned Align =
      std::max(DL.getPrefTypeAlignment(Ty1), DL.getPrefTypeAlignment(Ty2));

  MachineFrameInfo &MFI = getMachineFunction().getFrameInfo();
  int FrameIdx = MFI.CreateStackObject(Bytes, Align, false);
  return getFrameIndex(FrameIdx, TLI->getFrameIndexTy(getDataLayout()));
}

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

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

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

    // icmp X, X -> true/false
    // icmp X, undef -> true/false because undef could be X.
    if (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();

      switch (Cond) {
      default: llvm_unreachable("Unknown integer setcc!");
      case ISD::SETEQ:  return getBoolConstant(C1 == C2, dl, VT, OpVT);
      case ISD::SETNE:  return getBoolConstant(C1 != C2, dl, VT, OpVT);
      case ISD::SETULT: return getBoolConstant(C1.ult(C2), dl, VT, OpVT);
      case ISD::SETUGT: return getBoolConstant(C1.ugt(C2), dl, VT, OpVT);
      case ISD::SETULE: return getBoolConstant(C1.ule(C2), dl, VT, OpVT);
      case ISD::SETUGE: return getBoolConstant(C1.uge(C2), dl, VT, OpVT);
      case ISD::SETLT:  return getBoolConstant(C1.slt(C2), dl, VT, OpVT);
      case ISD::SETGT:  return getBoolConstant(C1.sgt(C2), dl, VT, OpVT);
      case ISD::SETLE:  return getBoolConstant(C1.sle(C2), dl, VT, OpVT);
      case ISD::SETGE:  return getBoolConstant(C1.sge(C2), 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 getUNDEF(VT);
                      LLVM_FALLTHROUGH;
    case ISD::SETOEQ: return getBoolConstant(R==APFloat::cmpEqual, dl, VT,
                                             OpVT);
    case ISD::SETNE:  if (R==APFloat::cmpUnordered)
                        return getUNDEF(VT);
                      LLVM_FALLTHROUGH;
    case ISD::SETONE: return getBoolConstant(R==APFloat::cmpGreaterThan ||
                                             R==APFloat::cmpLessThan, dl, VT,
                                             OpVT);
    case ISD::SETLT:  if (R==APFloat::cmpUnordered)
                        return getUNDEF(VT);
                      LLVM_FALLTHROUGH;
    case ISD::SETOLT: return getBoolConstant(R==APFloat::cmpLessThan, dl, VT,
                                             OpVT);
    case ISD::SETGT:  if (R==APFloat::cmpUnordered)
                        return getUNDEF(VT);
                      LLVM_FALLTHROUGH;
    case ISD::SETOGT: return getBoolConstant(R==APFloat::cmpGreaterThan, dl,
                                             VT, OpVT);
    case ISD::SETLE:  if (R==APFloat::cmpUnordered)
                        return getUNDEF(VT);
                      LLVM_FALLTHROUGH;
    case ISD::SETOLE: return getBoolConstant(R==APFloat::cmpLessThan ||
                                             R==APFloat::cmpEqual, dl, VT,
                                             OpVT);
    case ISD::SETGE:  if (R==APFloat::cmpUnordered)
                        return getUNDEF(VT);
                      LLVM_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 getUNDEF(VT);
    }
  }

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

/// See if the specified operand can be simplified with the knowledge that only
/// the bits specified by Mask are used.
SDValue SelectionDAG::GetDemandedBits(SDValue V, const APInt &Mask) {
  switch (V.getOpcode()) {
  default:
    break;
  case ISD::Constant: {
    const ConstantSDNode *CV = cast<ConstantSDNode>(V.getNode());
    assert(CV && "Const value should be ConstSDNode.");
    const APInt &CVal = CV->getAPIntValue();
    APInt NewVal = CVal & Mask;
    if (NewVal != CVal)
      return getConstant(NewVal, SDLoc(V), V.getValueType());
    break;
  }
  case ISD::OR:
  case ISD::XOR:
    // If the LHS or RHS don't contribute bits to the or, drop them.
    if (MaskedValueIsZero(V.getOperand(0), Mask))
      return V.getOperand(1);
    if (MaskedValueIsZero(V.getOperand(1), Mask))
      return V.getOperand(0);
    break;
  case ISD::SRL:
    // Only look at single-use SRLs.
    if (!V.getNode()->hasOneUse())
      break;
    if (ConstantSDNode *RHSC = dyn_cast<ConstantSDNode>(V.getOperand(1))) {
      // See if we can recursively simplify the LHS.
      unsigned Amt = RHSC->getZExtValue();

      // Watch out for shift count overflow though.
      if (Amt >= Mask.getBitWidth())
        break;
      APInt NewMask = Mask << Amt;
      if (SDValue SimplifyLHS = GetDemandedBits(V.getOperand(0), NewMask))
        return getNode(ISD::SRL, SDLoc(V), V.getValueType(), SimplifyLHS,
                       V.getOperand(1));
    }
    break;
  case ISD::AND: {
    // X & -1 -> X (ignoring bits which aren't demanded).
    // Also handle the case where masked out bits in X are known to be zero.
    if (ConstantSDNode *RHSC = isConstOrConstSplat(V.getOperand(1))) {
      const APInt &AndVal = RHSC->getAPIntValue();
      if (Mask.isSubsetOf(AndVal) ||
          Mask.isSubsetOf(computeKnownBits(V.getOperand(0)).Zero | AndVal))
        return V.getOperand(0);
    }
    break;
  }
  case ISD::ANY_EXTEND: {
    SDValue Src = V.getOperand(0);
    unsigned SrcBitWidth = Src.getScalarValueSizeInBits();
    // Being conservative here - only peek through if we only demand bits in the
    // non-extended source (even though the extended bits are technically undef).
    if (Mask.getActiveBits() > SrcBitWidth)
      break;
    APInt SrcMask = Mask.trunc(SrcBitWidth);
    if (SDValue DemandedSrc = GetDemandedBits(Src, SrcMask))
      return getNode(ISD::ANY_EXTEND, SDLoc(V), V.getValueType(), DemandedSrc);
    break;
  }
  case ISD::SIGN_EXTEND_INREG:
    EVT ExVT = cast<VTSDNode>(V.getOperand(1))->getVT();
    unsigned ExVTBits = ExVT.getScalarSizeInBits();

    // If none of the extended bits are demanded, eliminate the sextinreg.
    if (Mask.getActiveBits() <= ExVTBits)
      return V.getOperand(0);

    break;
  }
  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 Op, const APInt &Mask,
                                     unsigned Depth) const {
  return Mask.isSubsetOf(computeKnownBits(Op, Depth).Zero);
}

/// isSplatValue - Return true if the vector V has the same value
/// across all DemandedElts.
bool SelectionDAG::isSplatValue(SDValue V, const APInt &DemandedElts,
                                APInt &UndefElts) {
  if (!DemandedElts)
    return false; // No demanded elts, better to assume we don't know anything.

  EVT VT = V.getValueType();
  assert(VT.isVector() && "Vector type expected");

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

  switch (V.getOpcode()) {
  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.
    // TODO: Do we need to handle shuffle(splat, undef, mask)?
    int SplatIndex = -1;
    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 (0 <= SplatIndex && SplatIndex != M)
        return false;
      SplatIndex = M;
    }
    return true;
  }
  case ISD::EXTRACT_SUBVECTOR: {
    SDValue Src = V.getOperand(0);
    ConstantSDNode *SubIdx = dyn_cast<ConstantSDNode>(V.getOperand(1));
    unsigned NumSrcElts = Src.getValueType().getVectorNumElements();
    if (SubIdx && SubIdx->getAPIntValue().ule(NumSrcElts - NumElts)) {
      // Offset the demanded elts by the subvector index.
      uint64_t Idx = SubIdx->getZExtValue();
      APInt UndefSrcElts;
      APInt DemandedSrc = DemandedElts.zextOrSelf(NumSrcElts).shl(Idx);
      if (isSplatValue(Src, DemandedSrc, UndefSrcElts)) {
        UndefElts = UndefSrcElts.extractBits(NumElts, Idx);
        return true;
      }
    }
    break;
  }
  case ISD::ADD:
  case ISD::SUB:
  case ISD::AND: {
    APInt UndefLHS, UndefRHS;
    SDValue LHS = V.getOperand(0);
    SDValue RHS = V.getOperand(1);
    if (isSplatValue(LHS, DemandedElts, UndefLHS) &&
        isSplatValue(RHS, DemandedElts, UndefRHS)) {
      UndefElts = UndefLHS | UndefRHS;
      return true;
    }
    break;
  }
  }

  return false;
}

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

  APInt UndefElts;
  APInt DemandedElts = APInt::getAllOnesValue(NumElts);
  return isSplatValue(V, DemandedElts, UndefElts) &&
         (AllowUndefs || !UndefElts);
}

/// If a SHL/SRA/SRL node has a constant or splat constant shift amount that
/// is less than the element bit-width of the shift node, return it.
static const APInt *getValidShiftAmountConstant(SDValue V) {
  if (ConstantSDNode *SA = isConstOrConstSplat(V.getOperand(1))) {
    // Shifting more than the bitwidth is not valid.
    const APInt &ShAmt = SA->getAPIntValue();
    if (ShAmt.ult(V.getScalarValueSizeInBits()))
      return &ShAmt;
  }
  return nullptr;
}

/// 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();
  APInt DemandedElts = VT.isVector()
                           ? APInt::getAllOnesValue(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 *C = dyn_cast<ConstantSDNode>(Op)) {
    // We know all of the bits for a constant!
    Known.One = C->getAPIntValue();
    Known.Zero = ~Known.One;
    return Known;
  }
  if (auto *C = dyn_cast<ConstantFPSDNode>(Op)) {
    // We know all of the bits for a constant fp!
    Known.One = C->getValueAPF().bitcastToAPInt();
    Known.Zero = ~Known.One;
    return Known;
  }

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

  KnownBits Known2;
  unsigned NumElts = DemandedElts.getBitWidth();
  assert((!Op.getValueType().isVector() ||
          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::BUILD_VECTOR:
    // 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.One &= Known2.One;
      Known.Zero &= Known2.Zero;

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

      int M = SVN->getMaskElt(i);
      if (M < 0) {
        // For UNDEF elements, we don't know anything about the common state of
        // the shuffle result.
        Known.resetAll();
        DemandedLHS.clearAllBits();
        DemandedRHS.clearAllBits();
        break;
      }

      if ((unsigned)M < NumElts)
        DemandedLHS.setBit((unsigned)M % NumElts);
      else
        DemandedRHS.setBit((unsigned)M % NumElts);
    }
    // Known bits are the values that are shared by every demanded element.
    if (!!DemandedLHS) {
      SDValue LHS = Op.getOperand(0);
      Known2 = computeKnownBits(LHS, DemandedLHS, Depth + 1);
      Known.One &= Known2.One;
      Known.Zero &= Known2.Zero;
    }
    // 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.One &= Known2.One;
      Known.Zero &= Known2.Zero;
    }
    break;
  }
  case ISD::CONCAT_VECTORS: {
    // 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.lshr(i * NumSubVectorElts);
      DemandedSub = DemandedSub.trunc(NumSubVectorElts);
      if (!!DemandedSub) {
        SDValue Sub = Op.getOperand(i);
        Known2 = computeKnownBits(Sub, DemandedSub, Depth + 1);
        Known.One &= Known2.One;
        Known.Zero &= Known2.Zero;
      }
      // If we don't know any bits, early out.
      if (Known.isUnknown())
        break;
    }
    break;
  }
  case ISD::INSERT_SUBVECTOR: {
    // If we know the element index, demand any elements from the subvector and
    // the remainder from the src its inserted into, otherwise demand them all.
    SDValue Src = Op.getOperand(0);
    SDValue Sub = Op.getOperand(1);
    ConstantSDNode *SubIdx = dyn_cast<ConstantSDNode>(Op.getOperand(2));
    unsigned NumSubElts = Sub.getValueType().getVectorNumElements();
    if (SubIdx && SubIdx->getAPIntValue().ule(NumElts - NumSubElts)) {
      Known.One.setAllBits();
      Known.Zero.setAllBits();
      uint64_t Idx = SubIdx->getZExtValue();
      APInt DemandedSubElts = DemandedElts.extractBits(NumSubElts, Idx);
      if (!!DemandedSubElts) {
        Known = computeKnownBits(Sub, DemandedSubElts, Depth + 1);
        if (Known.isUnknown())
          break; // early-out.
      }
      APInt SubMask = APInt::getBitsSet(NumElts, Idx, Idx + NumSubElts);
      APInt DemandedSrcElts = DemandedElts & ~SubMask;
      if (!!DemandedSrcElts) {
        Known2 = computeKnownBits(Src, DemandedSrcElts, Depth + 1);
        Known.One &= Known2.One;
        Known.Zero &= Known2.Zero;
      }
    } else {
      Known = computeKnownBits(Sub, Depth + 1);
      if (Known.isUnknown())
        break; // early-out.
      Known2 = computeKnownBits(Src, Depth + 1);
      Known.One &= Known2.One;
      Known.Zero &= Known2.Zero;
    }
    break;
  }
  case ISD::EXTRACT_SUBVECTOR: {
    // If we know the element index, just demand that subvector elements,
    // otherwise demand them all.
    SDValue Src = Op.getOperand(0);
    ConstantSDNode *SubIdx = dyn_cast<ConstantSDNode>(Op.getOperand(1));
    unsigned NumSrcElts = Src.getValueType().getVectorNumElements();
    if (SubIdx && SubIdx->getAPIntValue().ule(NumSrcElts - NumElts)) {
      // Offset the demanded elts by the subvector index.
      uint64_t Idx = SubIdx->getZExtValue();
      APInt DemandedSrc = DemandedElts.zextOrSelf(NumSrcElts).shl(Idx);
      Known = computeKnownBits(Src, DemandedSrc, Depth + 1);
    } else {
      Known = computeKnownBits(Src, Depth + 1);
    }
    break;
  }
  case ISD::SCALAR_TO_VECTOR: {
    // 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: {
    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.One |= Known2.One.zext(BitWidth).shl(SubBitWidth * Shifts);
        Known.Zero |= Known2.Zero.zext(BitWidth).shl(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(NumElts / SubScale, 0);
      for (unsigned i = 0; i != NumElts; ++i)
        if (DemandedElts[i])
          SubDemandedElts.setBit(i / 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.One &= Known2.One.lshr(Offset).trunc(BitWidth);
          Known.Zero &= Known2.Zero.lshr(Offset).trunc(BitWidth);
          // If we don't know any bits, early out.
          if (Known.isUnknown())
            break;
        }
    }
    break;
  }
  case ISD::AND:
    // If either the LHS or the RHS are Zero, the result is zero.
    Known = computeKnownBits(Op.getOperand(1), DemandedElts, Depth + 1);
    Known2 = computeKnownBits(Op.getOperand(0), DemandedElts, Depth + 1);

    // Output known-1 bits are only known if set in both the LHS & RHS.
    Known.One &= Known2.One;
    // Output known-0 are known to be clear if zero in either the LHS | RHS.
    Known.Zero |= Known2.Zero;
    break;
  case ISD::OR:
    Known = computeKnownBits(Op.getOperand(1), DemandedElts, Depth + 1);
    Known2 = computeKnownBits(Op.getOperand(0), DemandedElts, Depth + 1);

    // Output known-0 bits are only known if clear in both the LHS & RHS.
    Known.Zero &= Known2.Zero;
    // Output known-1 are known to be set if set in either the LHS | RHS.
    Known.One |= Known2.One;
    break;
  case ISD::XOR: {
    Known = computeKnownBits(Op.getOperand(1), DemandedElts, Depth + 1);
    Known2 = computeKnownBits(Op.getOperand(0), DemandedElts, Depth + 1);

    // Output known-0 bits are known if clear or set in both the LHS & RHS.
    APInt KnownZeroOut = (Known.Zero & Known2.Zero) | (Known.One & Known2.One);
    // Output known-1 are known to be set if set in only one of the LHS, RHS.
    Known.One = (Known.Zero & Known2.One) | (Known.One & Known2.Zero);
    Known.Zero = KnownZeroOut;
    break;
  }
  case ISD::MUL: {
    Known = computeKnownBits(Op.getOperand(1), DemandedElts, Depth + 1);
    Known2 = computeKnownBits(Op.getOperand(0), DemandedElts, Depth + 1);

    // If low bits are zero in either operand, output low known-0 bits.
    // Also compute a conservative estimate for high known-0 bits.
    // More trickiness is possible, but this is sufficient for the
    // interesting case of alignment computation.
    unsigned TrailZ = Known.countMinTrailingZeros() +
                      Known2.countMinTrailingZeros();
    unsigned LeadZ =  std::max(Known.countMinLeadingZeros() +
                               Known2.countMinLeadingZeros(),
                               BitWidth) - BitWidth;

    Known.resetAll();
    Known.Zero.setLowBits(std::min(TrailZ, BitWidth));
    Known.Zero.setHighBits(std::min(LeadZ, BitWidth));
    break;
  }
  case ISD::UDIV: {
    // For the purposes of computing leading zeros we can conservatively
    // treat a udiv as a logical right shift by the power of 2 known to
    // be less than the denominator.
    Known2 = computeKnownBits(Op.getOperand(0), DemandedElts, Depth + 1);
    unsigned LeadZ = Known2.countMinLeadingZeros();

    Known2 = computeKnownBits(Op.getOperand(1), DemandedElts, Depth + 1);
    unsigned RHSMaxLeadingZeros = Known2.countMaxLeadingZeros();
    if (RHSMaxLeadingZeros != BitWidth)
      LeadZ = std::min(BitWidth, LeadZ + BitWidth - RHSMaxLeadingZeros - 1);

    Known.Zero.setHighBits(LeadZ);
    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.One &= Known2.One;
    Known.Zero &= Known2.Zero;
    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.One &= Known2.One;
    Known.Zero &= Known2.Zero;
    break;
  case ISD::SMULO:
  case ISD::UMULO:
  case ISD::ATOMIC_CMP_SWAP_WITH_SUCCESS:
    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:
    // 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;
  case ISD::SHL:
    if (const APInt *ShAmt = getValidShiftAmountConstant(Op)) {
      Known = computeKnownBits(Op.getOperand(0), DemandedElts, Depth + 1);
      unsigned Shift = ShAmt->getZExtValue();
      Known.Zero <<= Shift;
      Known.One <<= Shift;
      // Low bits are known zero.
      Known.Zero.setLowBits(Shift);
    }
    break;
  case ISD::SRL:
    if (const APInt *ShAmt = getValidShiftAmountConstant(Op)) {
      Known = computeKnownBits(Op.getOperand(0), DemandedElts, Depth + 1);
      unsigned Shift = ShAmt->getZExtValue();
      Known.Zero.lshrInPlace(Shift);
      Known.One.lshrInPlace(Shift);
      // High bits are known zero.
      Known.Zero.setHighBits(Shift);
    } else if (auto *BV = dyn_cast<BuildVectorSDNode>(Op.getOperand(1))) {
      // If the shift amount is a vector of constants see if we can bound
      // the number of upper zero bits.
      unsigned ShiftAmountMin = BitWidth;
      for (unsigned i = 0; i != BV->getNumOperands(); ++i) {
        if (auto *C = dyn_cast<ConstantSDNode>(BV->getOperand(i))) {
          const APInt &ShAmt = C->getAPIntValue();
          if (ShAmt.ult(BitWidth)) {
            ShiftAmountMin = std::min<unsigned>(ShiftAmountMin,
                                                ShAmt.getZExtValue());
            continue;
          }
        }
        // Don't know anything.
        ShiftAmountMin = 0;
        break;
      }

      Known.Zero.setHighBits(ShiftAmountMin);
    }
    break;
  case ISD::SRA:
    if (const APInt *ShAmt = getValidShiftAmountConstant(Op)) {
      Known = computeKnownBits(Op.getOperand(0), DemandedElts, Depth + 1);
      unsigned Shift = ShAmt->getZExtValue();
      // Sign extend known zero/one bit (else is unknown).
      Known.Zero.ashrInPlace(Shift);
      Known.One.ashrInPlace(Shift);
    }
    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.One |= Known2.One;
      Known.Zero |= Known2.Zero;
    }
    break;
  case ISD::SIGN_EXTEND_INREG: {
    EVT EVT = cast<VTSDNode>(Op.getOperand(1))->getVT();
    unsigned EBits = EVT.getScalarSizeInBits();

    // Sign extension.  Compute the demanded bits in the result that are not
    // present in the input.
    APInt NewBits = APInt::getHighBitsSet(BitWidth, BitWidth - EBits);

    APInt InSignMask = APInt::getSignMask(EBits);
    APInt InputDemandedBits = APInt::getLowBitsSet(BitWidth, EBits);

    // If the sign extended bits are demanded, we know that the sign
    // bit is demanded.
    InSignMask = InSignMask.zext(BitWidth);
    if (NewBits.getBoolValue())
      InputDemandedBits |= InSignMask;

    Known = computeKnownBits(Op.getOperand(0), DemandedElts, Depth + 1);
    Known.One &= InputDemandedBits;
    Known.Zero &= InputDemandedBits;

    // If the sign bit of the input is known set or clear, then we know the
    // top bits of the result.
    if (Known.Zero.intersects(InSignMask)) {        // Input sign bit known clear
      Known.Zero |= NewBits;
      Known.One  &= ~NewBits;
    } else if (Known.One.intersects(InSignMask)) {  // Input sign bit known set
      Known.One  |= NewBits;
      Known.Zero &= ~NewBits;
    } else {                              // Input sign bit unknown
      Known.Zero &= ~NewBits;
      Known.One  &= ~NewBits;
    }
    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 = Log2_32(PossibleTZ) + 1;
    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 = Log2_32(PossibleLZ) + 1;
    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(Log2_32(PossibleOnes) + 1);
    break;
  }
  case ISD::LOAD: {
    LoadSDNode *LD = cast<LoadSDNode>(Op);
    // If this is a ZEXTLoad and we are looking at the loaded value.
    if (ISD::isZEXTLoad(Op.getNode()) && Op.getResNo() == 0) {
      EVT VT = LD->getMemoryVT();
      unsigned MemBits = VT.getScalarSizeInBits();
      Known.Zero.setBitsFrom(MemBits);
    } else if (const MDNode *Ranges = LD->getRanges()) {
      if (LD->getExtensionType() == ISD::NON_EXTLOAD)
        computeKnownBitsFromRangeMetadata(*Ranges, Known);
    }
    break;
  }
  case ISD::ZERO_EXTEND_VECTOR_INREG: {
    EVT InVT = Op.getOperand(0).getValueType();
    APInt InDemandedElts = DemandedElts.zextOrSelf(InVT.getVectorNumElements());
    Known = computeKnownBits(Op.getOperand(0), InDemandedElts, Depth + 1);
    Known = Known.zext(BitWidth, true /* ExtendedBitsAreKnownZero */);
    break;
  }
  case ISD::ZERO_EXTEND: {
    Known = computeKnownBits(Op.getOperand(0), DemandedElts, Depth + 1);
    Known = Known.zext(BitWidth, true /* ExtendedBitsAreKnownZero */);
    break;
  }
  case ISD::SIGN_EXTEND_VECTOR_INREG: {
    EVT InVT = Op.getOperand(0).getValueType();
    APInt InDemandedElts = DemandedElts.zextOrSelf(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: {
    Known = computeKnownBits(Op.getOperand(0), Depth+1);
    Known = Known.zext(BitWidth, false /* ExtendedBitsAreKnownZero */);
    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), Depth+1);
    Known.Zero |= (~InMask);
    Known.One  &= (~Known.Zero);
    break;
  }
  case ISD::FGETSIGN:
    // All bits are zero except the low bit.
    Known.Zero.setBitsFrom(1);
    break;
  case ISD::USUBO:
  case ISD::SSUBO:
    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;
    }
    LLVM_FALLTHROUGH;
  case ISD::SUB:
  case ISD::SUBC: {
    Known = computeKnownBits(Op.getOperand(0), DemandedElts, Depth + 1);
    Known2 = computeKnownBits(Op.getOperand(1), DemandedElts, Depth + 1);
    Known = KnownBits::computeForAddSub(/* Add */ false, /* NSW */ false,
                                        Known, Known2);
    break;
  }
  case ISD::UADDO:
  case ISD::SADDO:
  case ISD::ADDCARRY:
    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;
    }
    LLVM_FALLTHROUGH;
  case ISD::ADD:
  case ISD::ADDC:
  case ISD::ADDE: {
    assert(Op.getResNo() == 0 && "We only compute knownbits for the sum here.");

    // With ADDE and ADDCARRY, 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::ADDCARRY)
      // TODO: Compute known bits for the carry operand. Not sure if it is worth
      // the trouble (how often will we find a known carry bit). And I haven't
      // tested this very much yet, but something like this might work:
      //   Carry = computeKnownBits(Op.getOperand(2), DemandedElts, Depth + 1);
      //   Carry = Carry.zextOrTrunc(1, false);
      Carry.resetAll();
    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::SREM:
    if (ConstantSDNode *Rem = isConstOrConstSplat(Op.getOperand(1))) {
      const APInt &RA = Rem->getAPIntValue().abs();
      if (RA.isPowerOf2()) {
        APInt LowBits = RA - 1;
        Known2 = computeKnownBits(Op.getOperand(0), DemandedElts, Depth + 1);

        // The low bits of the first operand are unchanged by the srem.
        Known.Zero = Known2.Zero & LowBits;
        Known.One = Known2.One & LowBits;

        // If the first operand is non-negative or has all low bits zero, then
        // the upper bits are all zero.
        if (Known2.Zero[BitWidth-1] || ((Known2.Zero & LowBits) == LowBits))
          Known.Zero |= ~LowBits;

        // If the first operand is negative and not all low bits are zero, then
        // the upper bits are all one.
        if (Known2.One[BitWidth-1] && ((Known2.One & LowBits) != 0))
          Known.One |= ~LowBits;
        assert((Known.Zero & Known.One) == 0&&"Bits known to be one AND zero?");
      }
    }
    break;
  case ISD::UREM: {
    if (ConstantSDNode *Rem = isConstOrConstSplat(Op.getOperand(1))) {
      const APInt &RA = Rem->getAPIntValue();
      if (RA.isPowerOf2()) {
        APInt LowBits = (RA - 1);
        Known2 = computeKnownBits(Op.getOperand(0), DemandedElts, Depth + 1);

        // The upper bits are all zero, the lower ones are unchanged.
        Known.Zero = Known2.Zero | ~LowBits;
        Known.One = Known2.One & LowBits;
        break;
      }
    }

    // Since the result is less than or equal to either operand, any leading
    // zero bits in either operand must also exist in the result.
    Known = computeKnownBits(Op.getOperand(0), DemandedElts, Depth + 1);
    Known2 = computeKnownBits(Op.getOperand(1), DemandedElts, Depth + 1);

    uint32_t Leaders =
        std::max(Known.countMinLeadingZeros(), Known2.countMinLeadingZeros());
    Known.resetAll();
    Known.Zero.setHighBits(Leaders);
    break;
  }
  case ISD::EXTRACT_ELEMENT: {
    Known = computeKnownBits(Op.getOperand(0), Depth+1);
    const unsigned Index = Op.getConstantOperandVal(1);
    const unsigned BitWidth = Op.getValueSizeInBits();

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

    // Remove high part of known bit mask
    Known = Known.trunc(BitWidth);
    break;
  }
  case ISD::EXTRACT_VECTOR_ELT: {
    SDValue InVec = Op.getOperand(0);
    SDValue EltNo = Op.getOperand(1);
    EVT VecVT = InVec.getValueType();
    const unsigned BitWidth = Op.getValueSizeInBits();
    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);
    ConstantSDNode *ConstEltNo = dyn_cast<ConstantSDNode>(EltNo);
    if (ConstEltNo && ConstEltNo->getAPIntValue().ult(NumSrcElts)) {
      // If we know the element index, just demand that vector element.
      unsigned Idx = ConstEltNo->getZExtValue();
      APInt DemandedElt = APInt::getOneBitSet(NumSrcElts, Idx);
      Known = computeKnownBits(InVec, DemandedElt, Depth + 1);
    } else {
      // Unknown element index, so ignore DemandedElts and demand them all.
      Known = computeKnownBits(InVec, Depth + 1);
    }
    if (BitWidth > EltBitWidth)
      Known = Known.zext(BitWidth, false /* => any extend */);
    break;
  }
  case ISD::INSERT_VECTOR_ELT: {
    SDValue InVec = Op.getOperand(0);
    SDValue InVal = Op.getOperand(1);
    SDValue EltNo = Op.getOperand(2);

    ConstantSDNode *CEltNo = dyn_cast<ConstantSDNode>(EltNo);
    if (CEltNo && CEltNo->getAPIntValue().ult(NumElts)) {
      // If we know the element index, split the demand between the
      // source vector and the inserted element.
      Known.Zero = Known.One = APInt::getAllOnesValue(BitWidth);
      unsigned EltIdx = CEltNo->getZExtValue();

      // If we demand the inserted element then add its common known bits.
      if (DemandedElts[EltIdx]) {
        Known2 = computeKnownBits(InVal, Depth + 1);
        Known.One &= Known2.One.zextOrTrunc(Known.One.getBitWidth());
        Known.Zero &= Known2.Zero.zextOrTrunc(Known.Zero.getBitWidth());
      }

      // If we demand the source vector then add its common known bits, ensuring
      // that we don't demand the inserted element.
      APInt VectorElts = DemandedElts & ~(APInt::getOneBitSet(NumElts, EltIdx));
      if (!!VectorElts) {
        Known2 = computeKnownBits(InVec, VectorElts, Depth + 1);
        Known.One &= Known2.One;
        Known.Zero &= Known2.Zero;
      }
    } else {
      // Unknown element index, so ignore DemandedElts and demand them all.
      Known = computeKnownBits(InVec, Depth + 1);
      Known2 = computeKnownBits(InVal, Depth + 1);
      Known.One &= Known2.One.zextOrTrunc(Known.One.getBitWidth());
      Known.Zero &= Known2.Zero.zextOrTrunc(Known.Zero.getBitWidth());
    }
    break;
  }
  case ISD::BITREVERSE: {
    Known2 = computeKnownBits(Op.getOperand(0), DemandedElts, Depth + 1);
    Known.Zero = Known2.Zero.reverseBits();
    Known.One = Known2.One.reverseBits();
    break;
  }
  case ISD::BSWAP: {
    Known2 = computeKnownBits(Op.getOperand(0), DemandedElts, Depth + 1);
    Known.Zero = Known2.Zero.byteSwap();
    Known.One = Known2.One.byteSwap();
    break;
  }
  case ISD::ABS: {
    Known2 = computeKnownBits(Op.getOperand(0), DemandedElts, Depth + 1);

    // If the source's MSB is zero then we know the rest of the bits already.
    if (Known2.isNonNegative()) {
      Known.Zero = Known2.Zero;
      Known.One = Known2.One;
      break;
    }

    // We only know that the absolute values's MSB will be zero iff there is
    // a set bit that isn't the sign bit (otherwise it could be INT_MIN).
    Known2.One.clearSignBit();
    if (Known2.One.getBoolValue()) {
      Known.Zero = APInt::getSignMask(BitWidth);
      break;
    }
    break;
  }
  case ISD::UMIN: {
    Known = computeKnownBits(Op.getOperand(0), DemandedElts, Depth + 1);
    Known2 = computeKnownBits(Op.getOperand(1), DemandedElts, Depth + 1);

    // UMIN - we know that the result will have the maximum of the
    // known zero leading bits of the inputs.
    unsigned LeadZero = Known.countMinLeadingZeros();
    LeadZero = std::max(LeadZero, Known2.countMinLeadingZeros());

    Known.Zero &= Known2.Zero;
    Known.One &= Known2.One;
    Known.Zero.setHighBits(LeadZero);
    break;
  }
  case ISD::UMAX: {
    Known = computeKnownBits(Op.getOperand(0), DemandedElts, Depth + 1);
    Known2 = computeKnownBits(Op.getOperand(1), DemandedElts, Depth + 1);

    // UMAX - we know that the result will have the maximum of the
    // known one leading bits of the inputs.
    unsigned LeadOne = Known.countMinLeadingOnes();
    LeadOne = std::max(LeadOne, Known2.countMinLeadingOnes());

    Known.Zero &= Known2.Zero;
    Known.One &= Known2.One;
    Known.One.setHighBits(LeadOne);
    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;
        }
      }
    }

    // Fallback - just get the shared known bits of the operands.
    Known = computeKnownBits(Op.getOperand(0), DemandedElts, Depth + 1);
    if (Known.isUnknown()) break; // Early-out
    Known2 = computeKnownBits(Op.getOperand(1), DemandedElts, Depth + 1);
    Known.Zero &= Known2.Zero;
    Known.One &= Known2.One;
    break;
  }
  case ISD::FrameIndex:
  case ISD::TargetFrameIndex:
    TLI->computeKnownBitsForFrameIndex(Op, Known, DemandedElts, *this, Depth);
    break;

  default:
    if (Opcode < ISD::BUILTIN_OP_END)
      break;
    LLVM_FALLTHROUGH;
  case ISD::INTRINSIC_WO_CHAIN:
  case ISD::INTRINSIC_W_CHAIN:
  case ISD::INTRINSIC_VOID:
    // Allow the target to implement this method for its nodes.
    TLI->computeKnownBitsForTargetNode(Op, Known, DemandedElts, *this, Depth);
    break;
  }

  assert(!Known.hasConflict() && "Bits known to be one AND zero?");
  return Known;
}

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

  KnownBits N1Known = computeKnownBits(N1);
  if (N1Known.Zero.getBoolValue()) {
    KnownBits N0Known = computeKnownBits(N0);

    bool overflow;
    (void)(~N0Known.Zero).uadd_ov(~N1Known.Zero, overflow);
    if (!overflow)
      return OFK_Never;
  }

  // mulhi + 1 never overflow
  if (N0.getOpcode() == ISD::UMUL_LOHI && N0.getResNo() == 1 &&
      (~N1Known.Zero & 0x01) == ~N1Known.Zero)
    return OFK_Never;

  if (N1.getOpcode() == ISD::UMUL_LOHI && N1.getResNo() == 1) {
    KnownBits N0Known = computeKnownBits(N0);

    if ((~N0Known.Zero & 0x01) == ~N0Known.Zero)
      return OFK_Never;
  }

  return OFK_Sometime;
}

bool SelectionDAG::isKnownToBeAPowerOfTwo(SDValue Val) const {
  EVT OpVT = Val.getValueType();
  unsigned BitWidth = OpVT.getScalarSizeInBits();

  // Is the constant a known power of 2?
  if (ConstantSDNode *Const = dyn_cast<ConstantSDNode>(Val))
    return Const->getAPIntValue().zextOrTrunc(BitWidth).isPowerOf2();

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

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

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

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

  // Fall back to computeKnownBits to catch other known cases.
  KnownBits Known = computeKnownBits(Val);
  return (Known.countMaxPopulation() == 1) && (Known.countMinPopulation() == 1);
}

unsigned SelectionDAG::ComputeNumSignBits(SDValue Op, unsigned Depth) const {
  EVT VT = Op.getValueType();
  APInt DemandedElts = VT.isVector()
                           ? APInt::getAllOnesValue(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 == 6)
    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::BUILD_VECTOR:
    Tmp = VTBits;
    for (unsigned i = 0, e = Op.getNumOperands(); (i < e) && (Tmp > 1); ++i) {
      if (!DemandedElts[i])
        continue;

      SDValue SrcOp = Op.getOperand(i);
      Tmp2 = ComputeNumSignBits(Op.getOperand(i), Depth + 1);

      // BUILD_VECTOR can implicitly truncate sources, we must handle this.
      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(NumElts, 0), DemandedRHS(NumElts, 0);
    const ShuffleVectorSDNode *SVN = cast<ShuffleVectorSDNode>(Op);
    assert(NumElts == SVN->getMask().size() && "Unexpected vector size");
    for (unsigned i = 0; i != NumElts; ++i) {
      int M = SVN->getMaskElt(i);
      if (!DemandedElts[i])
        continue;
      // For UNDEF elements, we don't know anything about the common state of
      // the shuffle result.
      if (M < 0)
        return 1;
      if ((unsigned)M < NumElts)
        DemandedLHS.setBit((unsigned)M % NumElts);
      else
        DemandedRHS.setBit((unsigned)M % NumElts);
    }
    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: {
    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(NumElts / Scale, 0);
      for (unsigned i = 0; i != NumElts; ++i)
        if (DemandedElts[i])
          SrcDemandedElts.setBit(i / 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::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: {
    SDValue Src = Op.getOperand(0);
    EVT SrcVT = Src.getValueType();
    APInt DemandedSrcElts = DemandedElts.zextOrSelf(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 (ConstantSDNode *C =
            isConstOrConstSplat(Op.getOperand(1), DemandedElts)) {
      APInt ShiftVal = C->getAPIntValue();
      ShiftVal += Tmp;
      Tmp = ShiftVal.uge(VTBits) ? VTBits : ShiftVal.getZExtValue();
    }
    return Tmp;
  case ISD::SHL:
    if (ConstantSDNode *C =
            isConstOrConstSplat(Op.getOperand(1), DemandedElts)) {
      // shl destroys sign bits.
      Tmp = ComputeNumSignBits(Op.getOperand(0), DemandedElts, Depth+1);
      if (C->getAPIntValue().uge(VTBits) ||      // Bad shift.
          C->getAPIntValue().uge(Tmp)) break;    // Shifted all sign bits out.
      return Tmp - C->getZExtValue();
    }
    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), Depth + 1);
    if (Tmp == 1)
      return 1;  // Early out.
    Tmp2 = ComputeNumSignBits(Op.getOperand(1), Depth + 1);
    return std::min(Tmp, Tmp2);
  }
  case ISD::UMIN:
  case ISD::UMAX:
    Tmp = ComputeNumSignBits(Op.getOperand(0), Depth + 1);
    if (Tmp == 1)
      return 1;  // Early out.
    Tmp2 = ComputeNumSignBits(Op.getOperand(1), Depth + 1);
    return std::min(Tmp, Tmp2);
  case ISD::SADDO:
  case ISD::UADDO:
  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:
    // If setcc returns 0/-1, all bits are sign bits.
    if (TLI->getBooleanContents(Op.getOperand(0).getValueType()) ==
        TargetLowering::ZeroOrNegativeOneBooleanContent)
      return VTBits;
    break;
  case ISD::ROTL:
  case ISD::ROTR:
    if (ConstantSDNode *C = dyn_cast<ConstantSDNode>(Op.getOperand(1))) {
      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.
      Tmp = ComputeNumSignBits(Op.getOperand(0), Depth+1);
      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), Depth+1);
    if (Tmp == 1) return 1;  // Early out.

    // Special case decrementing a value (ADD X, -1):
    if (ConstantSDNode *CRHS = dyn_cast<ConstantSDNode>(Op.getOperand(1)))
      if (CRHS->isAllOnesValue()) {
        KnownBits Known = computeKnownBits(Op.getOperand(0), 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).isAllOnesValue())
          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), Depth+1);
    if (Tmp2 == 1) return 1;
    return std::min(Tmp, Tmp2)-1;

  case ISD::SUB:
    Tmp2 = ComputeNumSignBits(Op.getOperand(1), Depth+1);
    if (Tmp2 == 1) return 1;

    // Handle NEG.
    if (ConstantSDNode *CLHS = isConstOrConstSplat(Op.getOperand(0)))
      if (CLHS->isNullValue()) {
        KnownBits Known = computeKnownBits(Op.getOperand(1), 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).isAllOnesValue())
          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), Depth+1);
    if (Tmp == 1) return 1;  // Early out.
    return std::min(Tmp, Tmp2)-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: {
    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::max(std::min(KnownSign - rIndex * BitWidth, BitWidth), 0);
  }
  case ISD::INSERT_VECTOR_ELT: {
    SDValue InVec = Op.getOperand(0);
    SDValue InVal = Op.getOperand(1);
    SDValue EltNo = Op.getOperand(2);
    unsigned NumElts = InVec.getValueType().getVectorNumElements();

    ConstantSDNode *CEltNo = dyn_cast<ConstantSDNode>(EltNo);
    if (CEltNo && CEltNo->getAPIntValue().ult(NumElts)) {
      // If we know the element index, split the demand between the
      // source vector and the inserted element.
      unsigned EltIdx = CEltNo->getZExtValue();

      // If we demand the inserted element then get its sign bits.
      Tmp = std::numeric_limits<unsigned>::max();
      if (DemandedElts[EltIdx]) {
        // TODO - handle implicit truncation of inserted elements.
        if (InVal.getScalarValueSizeInBits() != VTBits)
          break;
        Tmp = ComputeNumSignBits(InVal, Depth + 1);
      }

      // If we demand the source vector then get its sign bits, and determine
      // the minimum.
      APInt VectorElts = DemandedElts;
      VectorElts.clearBit(EltIdx);
      if (!!VectorElts) {
        Tmp2 = ComputeNumSignBits(InVec, VectorElts, Depth + 1);
        Tmp = std::min(Tmp, Tmp2);
      }
    } else {
      // Unknown element index, so ignore DemandedElts and demand them all.
      Tmp = ComputeNumSignBits(InVec, Depth + 1);
      Tmp2 = ComputeNumSignBits(InVal, Depth + 1);
      Tmp = std::min(Tmp, Tmp2);
    }
    assert(Tmp <= VTBits && "Failed to determine minimum sign bits");
    return Tmp;
  }
  case ISD::EXTRACT_VECTOR_ELT: {
    SDValue InVec = Op.getOperand(0);
    SDValue EltNo = Op.getOperand(1);
    EVT VecVT = InVec.getValueType();
    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::getAllOnesValue(NumSrcElts);
    ConstantSDNode *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: {
    // If we know the element index, just demand that subvector elements,
    // otherwise demand them all.
    SDValue Src = Op.getOperand(0);
    ConstantSDNode *SubIdx = dyn_cast<ConstantSDNode>(Op.getOperand(1));
    unsigned NumSrcElts = Src.getValueType().getVectorNumElements();
    if (SubIdx && SubIdx->getAPIntValue().ule(NumSrcElts - NumElts)) {
      // Offset the demanded elts by the subvector index.
      uint64_t Idx = SubIdx->getZExtValue();
      APInt DemandedSrc = DemandedElts.zextOrSelf(NumSrcElts).shl(Idx);
      return ComputeNumSignBits(Src, DemandedSrc, Depth + 1);
    }
    return ComputeNumSignBits(Src, Depth + 1);
  }
  case ISD::CONCAT_VECTORS: {
    // 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.lshr(i * NumSubVectorElts);
      DemandedSub = DemandedSub.trunc(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 we know the element index, demand any elements from the subvector and
    // the remainder from the src its inserted into, otherwise demand them all.
    SDValue Src = Op.getOperand(0);
    SDValue Sub = Op.getOperand(1);
    auto *SubIdx = dyn_cast<ConstantSDNode>(Op.getOperand(2));
    unsigned NumSubElts = Sub.getValueType().getVectorNumElements();
    if (SubIdx && SubIdx->getAPIntValue().ule(NumElts - NumSubElts)) {
      Tmp = std::numeric_limits<unsigned>::max();
      uint64_t Idx = SubIdx->getZExtValue();
      APInt DemandedSubElts = DemandedElts.extractBits(NumSubElts, Idx);
      if (!!DemandedSubElts) {
        Tmp = ComputeNumSignBits(Sub, DemandedSubElts, Depth + 1);
        if (Tmp == 1) return 1; // early-out
      }
      APInt SubMask = APInt::getBitsSet(NumElts, Idx, Idx + NumSubElts);
      APInt DemandedSrcElts = DemandedElts & ~SubMask;
      if (!!DemandedSrcElts) {
        Tmp2 = ComputeNumSignBits(Src, DemandedSrcElts, Depth + 1);
        Tmp = std::min(Tmp, Tmp2);
      }
      assert(Tmp <= VTBits && "Failed to determine minimum sign bits");
      return Tmp;
    }

    // Not able to determine the index so just assume worst case.
    Tmp = ComputeNumSignBits(Sub, Depth + 1);
    if (Tmp == 1) return 1; // early-out
    Tmp2 = ComputeNumSignBits(Src, Depth + 1);
    Tmp = std::min(Tmp, Tmp2);
    assert(Tmp <= VTBits && "Failed to determine minimum sign bits");
    return Tmp;
  }
  }

  // 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:    // '17' bits known
          Tmp = LD->getMemoryVT().getScalarSizeInBits();
          return VTBits-Tmp+1;
        case ISD::ZEXTLOAD:    // '16' bits known
          Tmp = LD->getMemoryVT().getScalarSizeInBits();
          return VTBits-Tmp;
      }
    }
  }

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

  APInt Mask;
  if (Known.isNonNegative()) {        // sign bit is 0
    Mask = Known.Zero;
  } else if (Known.isNegative()) {  // sign bit is 1;
    Mask = Known.One;
  } else {
    // Nothing known.
    return FirstAnswer;
  }

  // Okay, we know that the sign bit in Mask is set.  Use CLZ to determine
  // the number of identical bits in the top of the input value.
  Mask = ~Mask;
  Mask <<= Mask.getBitWidth()-VTBits;
  // Return # leading zeros.  We use 'min' here in case Val was zero before
  // shifting.  We don't want to return '64' as for an i32 "0".
  return std::max(FirstAnswer, std::min(VTBits, Mask.countLeadingZeros()));
}

bool SelectionDAG::isBaseWithConstantOffset(SDValue Op) const {
  if ((Op.getOpcode() != ISD::ADD && Op.getOpcode() != ISD::OR) ||
      !isa<ConstantSDNode>(Op.getOperand(1)))
    return false;

  if (Op.getOpcode() == ISD::OR &&
      !MaskedValueIsZero(Op.getOperand(0), Op.getConstantOperandAPInt(1)))
    return false;

  return true;
}

bool SelectionDAG::isKnownNeverNaN(SDValue Op, bool SNaN, unsigned Depth) const {
  // If we're told that NaNs won't happen, assume they won't.
  if (getTarget().Options.NoNaNsFPMath || Op->getFlags().hasNoNaNs())
    return true;

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

  // TODO: Handle vectors.
  // 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: {
    if (SNaN)
      return true;
    // TODO: Need isKnownNeverInfinity
    return false;
  }
  case ISD::FCANONICALIZE:
  case ISD::FEXP:
  case ISD::FEXP2:
  case ISD::FTRUNC:
  case ISD::FFLOOR:
  case ISD::FCEIL:
  case ISD::FROUND:
  case ISD::FRINT:
  case ISD::FNEARBYINT: {
    if (SNaN)
      return true;
    return isKnownNeverNaN(Op.getOperand(0), SNaN, Depth + 1);
  }
  case ISD::FABS:
  case ISD::FNEG:
  case ISD::FCOPYSIGN: {
    return isKnownNeverNaN(Op.getOperand(0), SNaN, Depth + 1);
  }
  case ISD::SELECT:
    return isKnownNeverNaN(Op.getOperand(1), SNaN, Depth + 1) &&
           isKnownNeverNaN(Op.getOperand(2), SNaN, Depth + 1);
  case ISD::FP_EXTEND:
  case ISD::FP_ROUND: {
    if (SNaN)
      return true;
    return isKnownNeverNaN(Op.getOperand(0), SNaN, Depth + 1);
  }
  case ISD::SINT_TO_FP:
  case ISD::UINT_TO_FP:
    return true;
  case ISD::FMA:
  case ISD::FMAD: {
    if (SNaN)
      return true;
    return isKnownNeverNaN(Op.getOperand(0), SNaN, Depth + 1) &&
           isKnownNeverNaN(Op.getOperand(1), SNaN, Depth + 1) &&
           isKnownNeverNaN(Op.getOperand(2), SNaN, Depth + 1);
  }
  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: {
    // 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), SNaN, Depth + 1) ||
           isKnownNeverNaN(Op.getOperand(1), 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), false, Depth + 1) &&
            isKnownNeverSNaN(Op.getOperand(1), Depth + 1)) ||
           (isKnownNeverNaN(Op.getOperand(1), false, Depth + 1) &&
            isKnownNeverSNaN(Op.getOperand(0), Depth + 1));
  }
  case ISD::FMINIMUM:
  case ISD::FMAXIMUM: {
    // TODO: Does this quiet or return the origina NaN as-is?
    return isKnownNeverNaN(Op.getOperand(0), SNaN, Depth + 1) &&
           isKnownNeverNaN(Op.getOperand(1), SNaN, Depth + 1);
  }
  case ISD::EXTRACT_VECTOR_ELT: {
    return isKnownNeverNaN(Op.getOperand(0), 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, *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.
  // TODO: Add BuildVector support.
  if (const ConstantFPSDNode *C = dyn_cast<ConstantFPSDNode>(Op))
    return !C->isZero();
  return false;
}

bool SelectionDAG::isKnownNeverZero(SDValue Op) const {
  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->isNullValue(); }))
    return true;

  // TODO: Recognize more cases here.
  switch (Op.getOpcode()) {
  default: break;
  case ISD::OR:
    if (isKnownNeverZero(Op.getOperand(1)) ||
        isKnownNeverZero(Op.getOperand(0)))
      return true;
    break;
  }

  return false;
}

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

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

// FIXME: unify with llvm::haveNoCommonBitsSet.
// FIXME: could also handle masked merge pattern (X & ~M) op (Y & M)
bool SelectionDAG::haveNoCommonBitsSet(SDValue A, SDValue B) const {
  assert(A.getValueType() == B.getValueType() &&
         "Values must have the same type");
  return (computeKnownBits(A).Zero | computeKnownBits(B).Zero).isAllOnesValue();
}

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.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)) ||
        cast<ConstantSDNode>(Ops[i].getOperand(1))->getAPIntValue() != i) {
      IsIdentity = false;
      break;
    }
    IdentitySrc = Ops[i].getOperand(0);
  }
  if (IsIdentity)
    return IdentitySrc;

  return SDValue();
}

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.size() * Ops[0].getValueType().getVectorNumElements()) ==
             VT.getVectorNumElements() &&
         "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);

  // 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)
      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) {
  FoldingSetNodeID ID;
  AddNodeIDNode(ID, Opcode, getVTList(VT), None);
  void *IP = nullptr;
  if (SDNode *E = FindNodeOrInsertPos(ID, DL, IP))
    return SDValue(E, 0);

  auto *N = newSDNode<SDNode>(Opcode, DL.getIROrder(), DL.getDebugLoc(),
                              getVTList(VT));
  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 Operand, const SDNodeFlags Flags) {
  // 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 (ConstantSDNode *C = dyn_cast<ConstantSDNode>(Operand)) {
    const APInt &Val = C->getAPIntValue();
    switch (Opcode) {
    default: break;
    case ISD::SIGN_EXTEND:
      return getConstant(Val.sextOrTrunc(VT.getSizeInBits()), DL, VT,
                         C->isTargetOpcode(), C->isOpaque());
    case ISD::TRUNCATE:
      if (C->isOpaque())
        break;
      LLVM_FALLTHROUGH;
    case ISD::ANY_EXTEND:
    case ISD::ZERO_EXTEND:
      return getConstant(Val.zextOrTrunc(VT.getSizeInBits()), DL, VT,
                         C->isTargetOpcode(), C->isOpaque());
    case ISD::UINT_TO_FP:
    case ISD::SINT_TO_FP: {
      APFloat apf(EVTToAPFloatSemantics(VT),
                  APInt::getNullValue(VT.getSizeInBits()));
      (void)apf.convertFromAPInt(Val,
                                 Opcode==ISD::SINT_TO_FP,
                                 APFloat::rmNearestTiesToEven);
      return getConstantFP(apf, DL, VT);
    }
    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;
    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.countPopulation(), DL, VT, C->isTargetOpcode(),
                         C->isOpaque());
    case ISD::CTLZ:
    case ISD::CTLZ_ZERO_UNDEF:
      return getConstant(Val.countLeadingZeros(), DL, VT, C->isTargetOpcode(),
                         C->isOpaque());
    case ISD::CTTZ:
    case ISD::CTTZ_ZERO_UNDEF:
      return getConstant(Val.countTrailingZeros(), DL, VT, C->isTargetOpcode(),
                         C->isOpaque());
    case ISD::FP16_TO_FP: {
      bool Ignored;
      APFloat FPV(APFloat::IEEEhalf(),
                  (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(EVTToAPFloatSemantics(VT),
                        APFloat::rmNearestTiesToEven, &Ignored);
      return getConstantFP(FPV, DL, VT);
    }
    }
  }

  // Constant fold unary operations with a floating point constant operand.
  if (ConstantFPSDNode *C = dyn_cast<ConstantFPSDNode>(Operand)) {
    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);
      break;
    }
    case ISD::FTRUNC: {
      APFloat::opStatus fs = V.roundToIntegral(APFloat::rmTowardZero);
      if (fs == APFloat::opOK || fs == APFloat::opInexact)
        return getConstantFP(V, DL, VT);
      break;
    }
    case ISD::FFLOOR: {
      APFloat::opStatus fs = V.roundToIntegral(APFloat::rmTowardNegative);
      if (fs == APFloat::opOK || fs == APFloat::opInexact)
        return getConstantFP(V, DL, VT);
      break;
    }
    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(EVTToAPFloatSemantics(VT),
                      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::BITCAST:
      if (VT == MVT::i16 && C->getValueType(0) == MVT::f16)
        return getConstant((uint16_t)V.bitcastToAPInt().getZExtValue(), DL, VT);
      else if (VT == MVT::i32 && C->getValueType(0) == MVT::f32)
        return getConstant((uint32_t)V.bitcastToAPInt().getZExtValue(), DL, VT);
      else if (VT == MVT::i64 && C->getValueType(0) == MVT::f64)
        return getConstant(V.bitcastToAPInt().getZExtValue(), DL, VT);
      break;
    case ISD::FP_TO_FP16: {
      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(APFloat::IEEEhalf(),
                      APFloat::rmNearestTiesToEven, &Ignored);
      return getConstant(V.bitcastToAPInt(), DL, VT);
    }
    }
  }

  // Constant fold unary operations with a vector integer or float operand.
  if (BuildVectorSDNode *BV = dyn_cast<BuildVectorSDNode>(Operand)) {
    if (BV->isConstant()) {
      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::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::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: {
        SDValue Ops = { Operand };
        if (SDValue Fold = FoldConstantVectorArithmetic(Opcode, DL, VT, Ops))
          return Fold;
      }
      }
    }
  }

  unsigned OpOpcode = Operand.getNode()->getOpcode();
  switch (Opcode) {
  case ISD::TokenFactor:
  case ISD::MERGE_VALUES:
  case ISD::CONCAT_VECTORS:
    return Operand;         // Factor, merge or concat of one node?  No need.
  case ISD::BUILD_VECTOR: {
    // Attempt to simplify BUILD_VECTOR.
    SDValue Ops[] = {Operand};
    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() &&
           Operand.getValueType().isFloatingPoint() && "Invalid FP cast!");
    if (Operand.getValueType() == VT) return Operand;  // noop conversion.
    assert((!VT.isVector() ||
            VT.getVectorNumElements() ==
            Operand.getValueType().getVectorNumElements()) &&
           "Vector element count mismatch!");
    assert(Operand.getValueType().bitsLT(VT) &&
           "Invalid fpext node, dst < src!");
    if (Operand.isUndef())
      return getUNDEF(VT);
    break;
  case ISD::SIGN_EXTEND:
    assert(VT.isInteger() && Operand.getValueType().isInteger() &&
           "Invalid SIGN_EXTEND!");
    if (Operand.getValueType() == VT) return Operand;   // noop extension
    assert((!VT.isVector() ||
            VT.getVectorNumElements() ==
            Operand.getValueType().getVectorNumElements()) &&
           "Vector element count mismatch!");
    assert(Operand.getValueType().bitsLT(VT) &&
           "Invalid sext node, dst < src!");
    if (OpOpcode == ISD::SIGN_EXTEND || OpOpcode == ISD::ZERO_EXTEND)
      return getNode(OpOpcode, DL, VT, Operand.getOperand(0));
    else if (OpOpcode == ISD::UNDEF)
      // 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() && Operand.getValueType().isInteger() &&
           "Invalid ZERO_EXTEND!");
    if (Operand.getValueType() == VT) return Operand;   // noop extension
    assert((!VT.isVector() ||
            VT.getVectorNumElements() ==
            Operand.getValueType().getVectorNumElements()) &&
           "Vector element count mismatch!");
    assert(Operand.getValueType().bitsLT(VT) &&
           "Invalid zext node, dst < src!");
    if (OpOpcode == ISD::ZERO_EXTEND)   // (zext (zext x)) -> (zext x)
      return getNode(ISD::ZERO_EXTEND, DL, VT, Operand.getOperand(0));
    else if (OpOpcode == ISD::UNDEF)
      // zext(undef) = 0, because the top bits will be zero.
      return getConstant(0, DL, VT);
    break;
  case ISD::ANY_EXTEND:
    assert(VT.isInteger() && Operand.getValueType().isInteger() &&
           "Invalid ANY_EXTEND!");
    if (Operand.getValueType() == VT) return Operand;   // noop extension
    assert((!VT.isVector() ||
            VT.getVectorNumElements() ==
            Operand.getValueType().getVectorNumElements()) &&
           "Vector element count mismatch!");
    assert(Operand.getValueType().bitsLT(VT) &&
           "Invalid anyext node, dst < src!");

    if (OpOpcode == ISD::ZERO_EXTEND || OpOpcode == ISD::SIGN_EXTEND ||
        OpOpcode == ISD::ANY_EXTEND)
      // (ext (zext x)) -> (zext x)  and  (ext (sext x)) -> (sext x)
      return getNode(OpOpcode, DL, VT, Operand.getOperand(0));
    else if (OpOpcode == ISD::UNDEF)
      return getUNDEF(VT);

    // (ext (trunc x)) -> x
    if (OpOpcode == ISD::TRUNCATE) {
      SDValue OpOp = Operand.getOperand(0);
      if (OpOp.getValueType() == VT) {
        transferDbgValues(Operand, OpOp);
        return OpOp;
      }
    }
    break;
  case ISD::TRUNCATE:
    assert(VT.isInteger() && Operand.getValueType().isInteger() &&
           "Invalid TRUNCATE!");
    if (Operand.getValueType() == VT) return Operand;   // noop truncate
    assert((!VT.isVector() ||
            VT.getVectorNumElements() ==
            Operand.getValueType().getVectorNumElements()) &&
           "Vector element count mismatch!");
    assert(Operand.getValueType().bitsGT(VT) &&
           "Invalid truncate node, src < dst!");
    if (OpOpcode == ISD::TRUNCATE)
      return getNode(ISD::TRUNCATE, DL, VT, Operand.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 (Operand.getOperand(0).getValueType().getScalarType()
            .bitsLT(VT.getScalarType()))
        return getNode(OpOpcode, DL, VT, Operand.getOperand(0));
      if (Operand.getOperand(0).getValueType().bitsGT(VT))
        return getNode(ISD::TRUNCATE, DL, VT, Operand.getOperand(0));
      return Operand.getOperand(0);
    }
    if (OpOpcode == ISD::UNDEF)
      return getUNDEF(VT);
    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(Operand.getValueType().bitsLE(VT) &&
           "The input must be the same size or smaller than the result.");
    assert(VT.getVectorNumElements() <
             Operand.getValueType().getVectorNumElements() &&
           "The destination vector type must have fewer lanes than the input.");
    break;
  case ISD::ABS:
    assert(VT.isInteger() && VT == Operand.getValueType() &&
           "Invalid ABS!");
    if (OpOpcode == ISD::UNDEF)
      return getUNDEF(VT);
    break;
  case ISD::BSWAP:
    assert(VT.isInteger() && VT == Operand.getValueType() &&
           "Invalid BSWAP!");
    assert((VT.getScalarSizeInBits() % 16 == 0) &&
           "BSWAP types must be a multiple of 16 bits!");
    if (OpOpcode == ISD::UNDEF)
      return getUNDEF(VT);
    break;
  case ISD::BITREVERSE:
    assert(VT.isInteger() && VT == Operand.getValueType() &&
           "Invalid BITREVERSE!");
    if (OpOpcode == ISD::UNDEF)
      return getUNDEF(VT);
    break;
  case ISD::BITCAST:
    // Basic sanity checking.
    assert(VT.getSizeInBits() == Operand.getValueSizeInBits() &&
           "Cannot BITCAST between types of different sizes!");
    if (VT == Operand.getValueType()) return Operand;  // noop conversion.
    if (OpOpcode == ISD::BITCAST)  // bitconv(bitconv(x)) -> bitconv(x)
      return getNode(ISD::BITCAST, DL, VT, Operand.getOperand(0));
    if (OpOpcode == ISD::UNDEF)
      return getUNDEF(VT);
    break;
  case ISD::SCALAR_TO_VECTOR:
    assert(VT.isVector() && !Operand.getValueType().isVector() &&
           (VT.getVectorElementType() == Operand.getValueType() ||
            (VT.getVectorElementType().isInteger() &&
             Operand.getValueType().isInteger() &&
             VT.getVectorElementType().bitsLE(Operand.getValueType()))) &&
           "Illegal SCALAR_TO_VECTOR node!");
    if (OpOpcode == ISD::UNDEF)
      return getUNDEF(VT);
    // scalar_to_vector(extract_vector_elt V, 0) -> V, top bits are undefined.
    if (OpOpcode == ISD::EXTRACT_VECTOR_ELT &&
        isa<ConstantSDNode>(Operand.getOperand(1)) &&
        Operand.getConstantOperandVal(1) == 0 &&
        Operand.getOperand(0).getValueType() == VT)
      return Operand.getOperand(0);
    break;
  case ISD::FNEG:
    // -(X-Y) -> (Y-X) is unsafe because when X==Y, -0.0 != +0.0
    if ((getTarget().Options.UnsafeFPMath || Flags.hasNoSignedZeros()) &&
        OpOpcode == ISD::FSUB)
      return getNode(ISD::FSUB, DL, VT, Operand.getOperand(1),
                     Operand.getOperand(0), Flags);
    if (OpOpcode == ISD::FNEG)  // --X -> X
      return Operand.getOperand(0);
    break;
  case ISD::FABS:
    if (OpOpcode == ISD::FNEG)  // abs(-X) -> abs(X)
      return getNode(ISD::FABS, DL, VT, Operand.getOperand(0));
    break;
  }

  SDNode *N;
  SDVTList VTs = getVTList(VT);
  SDValue Ops[] = {Operand};
  if (VT != MVT::Glue) { // Don't CSE flag 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::pair<APInt, bool> FoldValue(unsigned Opcode, const APInt &C1,
                                        const APInt &C2) {
  switch (Opcode) {
  case ISD::ADD:  return std::make_pair(C1 + C2, true);
  case ISD::SUB:  return std::make_pair(C1 - C2, true);
  case ISD::MUL:  return std::make_pair(C1 * C2, true);
  case ISD::AND:  return std::make_pair(C1 & C2, true);
  case ISD::OR:   return std::make_pair(C1 | C2, true);
  case ISD::XOR:  return std::make_pair(C1 ^ C2, true);
  case ISD::SHL:  return std::make_pair(C1 << C2, true);
  case ISD::SRL:  return std::make_pair(C1.lshr(C2), true);
  case ISD::SRA:  return std::make_pair(C1.ashr(C2), true);
  case ISD::ROTL: return std::make_pair(C1.rotl(C2), true);
  case ISD::ROTR: return std::make_pair(C1.rotr(C2), true);
  case ISD::SMIN: return std::make_pair(C1.sle(C2) ? C1 : C2, true);
  case ISD::SMAX: return std::make_pair(C1.sge(C2) ? C1 : C2, true);
  case ISD::UMIN: return std::make_pair(C1.ule(C2) ? C1 : C2, true);
  case ISD::UMAX: return std::make_pair(C1.uge(C2) ? C1 : C2, true);
  case ISD::SADDSAT: return std::make_pair(C1.sadd_sat(C2), true);
  case ISD::UADDSAT: return std::make_pair(C1.uadd_sat(C2), true);
  case ISD::SSUBSAT: return std::make_pair(C1.ssub_sat(C2), true);
  case ISD::USUBSAT: return std::make_pair(C1.usub_sat(C2), true);
  case ISD::UDIV:
    if (!C2.getBoolValue())
      break;
    return std::make_pair(C1.udiv(C2), true);
  case ISD::UREM:
    if (!C2.getBoolValue())
      break;
    return std::make_pair(C1.urem(C2), true);
  case ISD::SDIV:
    if (!C2.getBoolValue())
      break;
    return std::make_pair(C1.sdiv(C2), true);
  case ISD::SREM:
    if (!C2.getBoolValue())
      break;
    return std::make_pair(C1.srem(C2), true);
  }
  return std::make_pair(APInt(1, 0), false);
}

SDValue SelectionDAG::FoldConstantArithmetic(unsigned Opcode, const SDLoc &DL,
                                             EVT VT, const ConstantSDNode *C1,
                                             const ConstantSDNode *C2) {
  if (C1->isOpaque() || C2->isOpaque())
    return SDValue();

  std::pair<APInt, bool> Folded = FoldValue(Opcode, C1->getAPIntValue(),
                                            C2->getAPIntValue());
  if (!Folded.second)
    return SDValue();
  return getConstant(Folded.first, DL, VT);
}

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: 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, SDNode *N1, SDNode *N2) {
  // 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.
  if (Opcode >= ISD::BUILTIN_OP_END)
    return SDValue();

  if (isUndef(Opcode, {SDValue(N1, 0), SDValue(N2, 0)}))
    return getUNDEF(VT);

  // Handle the case of two scalars.
  if (auto *C1 = dyn_cast<ConstantSDNode>(N1)) {
    if (auto *C2 = dyn_cast<ConstantSDNode>(N2)) {
      SDValue Folded = FoldConstantArithmetic(Opcode, DL, VT, C1, C2);
      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>(N1))
    return FoldSymbolOffset(Opcode, VT, GA, N2);
  if (TLI->isCommutativeBinOp(Opcode))
    if (GlobalAddressSDNode *GA = dyn_cast<GlobalAddressSDNode>(N2))
      return FoldSymbolOffset(Opcode, VT, GA, N1);

  // For vectors, extract each constant element and fold them individually.
  // Either input may be an undef value.
  auto *BV1 = dyn_cast<BuildVectorSDNode>(N1);
  if (!BV1 && !N1->isUndef())
    return SDValue();
  auto *BV2 = dyn_cast<BuildVectorSDNode>(N2);
  if (!BV2 && !N2->isUndef())
    return SDValue();
  // If both operands are undef, that's handled the same way as scalars.
  if (!BV1 && !BV2)
    return SDValue();

  assert((!BV1 || !BV2 || BV1->getNumOperands() == BV2->getNumOperands()) &&
         "Vector binop with different number of elements in operands?");

  EVT SVT = VT.getScalarType();
  EVT LegalSVT = SVT;
  if (NewNodesMustHaveLegalTypes && LegalSVT.isInteger()) {
    LegalSVT = TLI->getTypeToTransformTo(*getContext(), LegalSVT);
    if (LegalSVT.bitsLT(SVT))
      return SDValue();
  }
  SmallVector<SDValue, 4> Outputs;
  unsigned NumOps = BV1 ? BV1->getNumOperands() : BV2->getNumOperands();
  for (unsigned I = 0; I != NumOps; ++I) {
    SDValue V1 = BV1 ? BV1->getOperand(I) : getUNDEF(SVT);
    SDValue V2 = BV2 ? BV2->getOperand(I) : getUNDEF(SVT);
    if (SVT.isInteger()) {
      if (V1->getValueType(0).bitsGT(SVT))
        V1 = getNode(ISD::TRUNCATE, DL, SVT, V1);
      if (V2->getValueType(0).bitsGT(SVT))
        V2 = getNode(ISD::TRUNCATE, DL, SVT, V2);
    }

    if (V1->getValueType(0) != SVT || V2->getValueType(0) != SVT)
      return SDValue();

    // Fold one vector element.
    SDValue ScalarResult = getNode(Opcode, DL, SVT, V1, V2);
    if (LegalSVT != SVT)
      ScalarResult = getNode(ISD::SIGN_EXTEND, DL, LegalSVT, ScalarResult);

    // 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();
    Outputs.push_back(ScalarResult);
  }

  assert(VT.getVectorNumElements() == Outputs.size() &&
         "Vector size mismatch!");

  // We may have a vector type but a scalar result. Create a splat.
  Outputs.resize(VT.getVectorNumElements(), Outputs.back());

  // Build a big vector out of the scalar elements we generated.
  return getBuildVector(VT, SDLoc(), Outputs);
}

// TODO: Merge with FoldConstantArithmetic
SDValue SelectionDAG::FoldConstantVectorArithmetic(unsigned Opcode,
                                                   const SDLoc &DL, EVT VT,
                                                   ArrayRef<SDValue> Ops,
                                                   const 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.
  if (Opcode >= ISD::BUILTIN_OP_END)
    return SDValue();

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

  // We can only fold vectors - maybe merge with FoldConstantArithmetic someday?
  if (!VT.isVector())
    return SDValue();

  unsigned NumElts = VT.getVectorNumElements();

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

  auto IsConstantBuildVectorOrUndef = [&](const SDValue &Op) {
    BuildVectorSDNode *BV = dyn_cast<BuildVectorSDNode>(Op);
    return (Op.isUndef()) || (Op.getOpcode() == ISD::CONDCODE) ||
           (BV && BV->isConstant());
  };

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

  // If we are comparing vectors, then the result needs to be a i1 boolean
  // that is then sign-extended back to the legal result type.
  EVT SVT = (Opcode == ISD::SETCC ? MVT::i1 : VT.getScalarType());

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

  // Constant fold each scalar lane separately.
  SmallVector<SDValue, 4> ScalarResults;
  for (unsigned i = 0; i != NumElts; i++) {
    SmallVector<SDValue, 4> ScalarOps;
    for (SDValue Op : Ops) {
      EVT InSVT = Op.getValueType().getScalarType();
      BuildVectorSDNode *InBV = dyn_cast<BuildVectorSDNode>(Op);
      if (!InBV) {
        // We've checked that this is UNDEF or a constant of some kind.
        if (Op.isUndef())
          ScalarOps.push_back(getUNDEF(InSVT));
        else
          ScalarOps.push_back(Op);
        continue;
      }

      SDValue ScalarOp = InBV->getOperand(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))
        ScalarOp = getNode(ISD::TRUNCATE, DL, InSVT, ScalarOp);

      ScalarOps.push_back(ScalarOp);
    }

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

    // Legalize the (integer) scalar constant if necessary.
    if (LegalSVT != SVT)
      ScalarResult = getNode(ISD::SIGN_EXTEND, DL, LegalSVT, ScalarResult);

    // 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();
    ScalarResults.push_back(ScalarResult);
  }

  SDValue V = getBuildVector(VT, DL, ScalarResults);
  NewSDValueDbgMsg(V, "New node fold constant vector: ", this);
  return V;
}

SDValue SelectionDAG::foldConstantFPMath(unsigned Opcode, const SDLoc &DL,
                                         EVT VT, SDValue N1, SDValue N2) {
  auto *N1CFP = dyn_cast<ConstantFPSDNode>(N1.getNode());
  auto *N2CFP = dyn_cast<ConstantFPSDNode>(N2.getNode());
  bool HasFPExceptions = TLI->hasFloatingPointExceptions();
  if (N1CFP && N2CFP) {
    APFloat C1 = N1CFP->getValueAPF(), C2 = N2CFP->getValueAPF();
    APFloat::opStatus Status;
    switch (Opcode) {
    case ISD::FADD:
      Status = C1.add(C2, APFloat::rmNearestTiesToEven);
      if (!HasFPExceptions || Status != APFloat::opInvalidOp)
        return getConstantFP(C1, DL, VT);
      break;
    case ISD::FSUB:
      Status = C1.subtract(C2, APFloat::rmNearestTiesToEven);
      if (!HasFPExceptions || Status != APFloat::opInvalidOp)
        return getConstantFP(C1, DL, VT);
      break;
    case ISD::FMUL:
      Status = C1.multiply(C2, APFloat::rmNearestTiesToEven);
      if (!HasFPExceptions || Status != APFloat::opInvalidOp)
        return getConstantFP(C1, DL, VT);
      break;
    case ISD::FDIV:
      Status = C1.divide(C2, APFloat::rmNearestTiesToEven);
      if (!HasFPExceptions || (Status != APFloat::opInvalidOp &&
                               Status != APFloat::opDivByZero)) {
        return getConstantFP(C1, DL, VT);
      }
      break;
    case ISD::FREM:
      Status = C1.mod(C2);
      if (!HasFPExceptions || (Status != APFloat::opInvalidOp &&
                               Status != APFloat::opDivByZero)) {
        return getConstantFP(C1, DL, VT);
      }
      break;
    case ISD::FCOPYSIGN:
      C1.copySign(C2);
      return getConstantFP(C1, 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(EVTToAPFloatSemantics(VT), APFloat::rmNearestTiesToEven,
                     &Unused);
    return getConstantFP(C1, DL, VT);
  }

  switch (Opcode) {
  case ISD::FADD:
  case ISD::FSUB:
  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(EVTToAPFloatSemantics(VT)), DL, VT);
  }
  return SDValue();
}

SDValue SelectionDAG::getNode(unsigned Opcode, const SDLoc &DL, EVT VT,
                              SDValue N1, SDValue N2, const SDNodeFlags Flags) {
  ConstantSDNode *N1C = dyn_cast<ConstantSDNode>(N1);
  ConstantSDNode *N2C = dyn_cast<ConstantSDNode>(N2);
  ConstantFPSDNode *N1CFP = dyn_cast<ConstantFPSDNode>(N1);
  ConstantFPSDNode *N2CFP = dyn_cast<ConstantFPSDNode>(N2);

  // Canonicalize constant to RHS if commutative.
  if (TLI->isCommutativeBinOp(Opcode)) {
    if (N1C && !N2C) {
      std::swap(N1C, N2C);
      std::swap(N1, N2);
    } else if (N1CFP && !N2CFP) {
      std::swap(N1CFP, N2CFP);
      std::swap(N1, N2);
    }
  }

  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: {
    // Attempt to fold CONCAT_VECTORS into BUILD_VECTOR or UNDEF.
    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 (N2C && N2C->isNullValue())
      return N2;
    if (N2C && N2C->isAllOnesValue())  // X & -1 -> X
      return N1;
    break;
  case ISD::OR:
  case ISD::XOR:
  case ISD::ADD:
  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!");
    // (X ^|+- 0) -> X.  This commonly occurs when legalizing i64 values, so
    // it's worth handling here.
    if (N2C && N2C->isNullValue())
      return N1;
    break;
  case ISD::UDIV:
  case ISD::UREM:
  case ISD::MULHU:
  case ISD::MULHS:
  case ISD::MUL:
  case ISD::SDIV:
  case ISD::SREM:
  case ISD::SMIN:
  case ISD::SMAX:
  case ISD::UMIN:
  case ISD::UMAX:
  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!");
    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))
      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:
  case ISD::SRA:
  case ISD::SRL:
    if (SDValue V = simplifyShift(N1, N2))
      return V;
    LLVM_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.getValueSizeInBits() >= Log2_32_Ceil(N1.getValueSizeInBits()) &&
           "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 (N2C && N2C->isNullValue())
      return N1;
    break;
  case ISD::FP_ROUND_INREG: {
    EVT EVT = cast<VTSDNode>(N2)->getVT();
    assert(VT == N1.getValueType() && "Not an inreg round!");
    assert(VT.isFloatingPoint() && EVT.isFloatingPoint() &&
           "Cannot FP_ROUND_INREG integer types");
    assert(EVT.isVector() == VT.isVector() &&
           "FP_ROUND_INREG type should be vector iff the operand "
           "type is vector!");
    assert((!EVT.isVector() ||
            EVT.getVectorNumElements() == VT.getVectorNumElements()) &&
           "Vector element counts must match in FP_ROUND_INREG");
    assert(EVT.bitsLE(VT) && "Not rounding down!");
    (void)EVT;
    if (cast<VTSDNode>(N2)->getVT() == VT) return N1;  // Not actually rounding.
    break;
  }
  case ISD::FP_ROUND:
    assert(VT.isFloatingPoint() &&
           N1.getValueType().isFloatingPoint() &&
           VT.bitsLE(N1.getValueType()) &&
           N2C && (N2C->getZExtValue() == 0 || N2C->getZExtValue() == 1) &&
           "Invalid FP_ROUND!");
    if (N1.getValueType() == VT) return N1;  // noop conversion.
    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.getVectorNumElements() == VT.getVectorNumElements()) &&
           "Vector element counts must match in SIGN_EXTEND_INREG");
    assert(EVT.bitsLE(VT) && "Not extending!");
    if (EVT == VT) return N1;  // Not actually extending

    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 (N1C) {
      const APInt &Val = N1C->getAPIntValue();
      return SignExtendInReg(Val, VT);
    }
    if (ISD::isBuildVectorOfConstantSDNodes(N1.getNode())) {
      SmallVector<SDValue, 8> Ops;
      llvm::EVT OpVT = N1.getOperand(0).getValueType();
      for (int i = 0, e = VT.getVectorNumElements(); i != e; ++i) {
        SDValue Op = N1.getOperand(i);
        if (Op.isUndef()) {
          Ops.push_back(getUNDEF(OpVT));
          continue;
        }
        ConstantSDNode *C = cast<ConstantSDNode>(Op);
        APInt Val = C->getAPIntValue();
        Ops.push_back(SignExtendInReg(Val, OpVT));
      }
      return getBuildVector(VT, DL, Ops);
    }
    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_VECTOR_ELT of an UNDEF is an UNDEF.
    if (N1.isUndef())
      return getUNDEF(VT);

    // EXTRACT_VECTOR_ELT of out-of-bounds element is an UNDEF
    if (N2C && 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.
    if (N2C &&
        N1.getOpcode() == ISD::CONCAT_VECTORS &&
        N1.getNumOperands() > 0) {
      unsigned Factor =
        N1.getOperand(0).getValueType().getVectorNumElements();
      return getNode(ISD::EXTRACT_VECTOR_ELT, DL, VT,
                     N1.getOperand(N2C->getZExtValue() / Factor),
                     getConstant(N2C->getZExtValue() % Factor, DL,
                                 N2.getValueType()));
    }

    // EXTRACT_VECTOR_ELT of BUILD_VECTOR is often formed while lowering is
    // expanding large vector constants.
    if (N2C && N1.getOpcode() == ISD::BUILD_VECTOR) {
      SDValue Elt = N1.getOperand(N2C->getZExtValue());

      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);
          else
            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)
    if (N1.getOpcode() == ISD::EXTRACT_SUBVECTOR &&
        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();
      APInt ShiftedVal = N1C->getAPIntValue().lshr(Shift);
      return getConstant(ShiftedVal.trunc(ElementSize), DL, VT);
    }
    break;
  case ISD::EXTRACT_SUBVECTOR:
    if (VT.isSimple() && N1.getValueType().isSimple()) {
      assert(VT.isVector() && N1.getValueType().isVector() &&
             "Extract subvector VTs must be a vectors!");
      assert(VT.getVectorElementType() ==
             N1.getValueType().getVectorElementType() &&
             "Extract subvector VTs must have the same element type!");
      assert(VT.getSimpleVT() <= N1.getSimpleValueType() &&
             "Extract subvector must be from larger vector to smaller vector!");

      if (N2C) {
        assert((VT.getVectorNumElements() + N2C->getZExtValue()
                <= N1.getValueType().getVectorNumElements())
               && "Extract subvector overflow!");
      }

      // Trivial extraction.
      if (VT.getSimpleVT() == N1.getSimpleValueType())
        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 (N2C && N1.getOpcode() == ISD::CONCAT_VECTORS &&
          N1.getNumOperands() > 0 &&
          VT == N1.getOperand(0).getValueType()) {
        unsigned Factor = VT.getVectorNumElements();
        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;
  }

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

  if (SDValue V = foldConstantFPMath(Opcode, DL, VT, N1, N2))
    return V;

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

  // Fold a bunch of operators when the RHS is undef.
  if (N2.isUndef()) {
    switch (Opcode) {
    case ISD::XOR:
      if (N1.isUndef())
        // Handle undef ^ undef -> 0 special case. This is a common
        // idiom (misuse).
        return getConstant(0, DL, VT);
      LLVM_FALLTHROUGH;
    case ISD::ADD:
    case ISD::SUB:
    case ISD::UDIV:
    case ISD::SDIV:
    case ISD::UREM:
    case ISD::SREM:
      return getUNDEF(VT);       // fold op(arg1, undef) -> undef
    case ISD::MUL:
    case ISD::AND:
    case ISD::SSUBSAT:
    case ISD::USUBSAT:
      return getConstant(0, DL, VT);  // fold op(arg1, undef) -> 0
    case ISD::OR:
    case ISD::SADDSAT:
    case ISD::UADDSAT:
      return getAllOnesConstant(DL, VT);
    }
  }

  // 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,
                              const SDNodeFlags Flags) {
  // Perform various simplifications.
  switch (Opcode) {
  case ISD::FMA: {
    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();
      APFloat::opStatus s =
        V1.fusedMultiplyAdd(V2, V3, APFloat::rmNearestTiesToEven);
      if (!TLI->hasFloatingPointExceptions() || s != APFloat::opInvalidOp)
        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: {
    // Attempt to fold CONCAT_VECTORS into BUILD_VECTOR or UNDEF.
    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.getVectorNumElements() == N1.getValueType().getVectorNumElements()) &&
           "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 = FoldConstantVectorArithmetic(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::INSERT_VECTOR_ELT: {
    ConstantSDNode *N3C = dyn_cast<ConstantSDNode>(N3);
    // INSERT_VECTOR_ELT into out-of-bounds element is an UNDEF
    if (N3C && N3C->getZExtValue() >= N1.getValueType().getVectorNumElements())
      return getUNDEF(VT);
    break;
  }
  case ISD::INSERT_SUBVECTOR: {
    SDValue Index = N3;
    if (VT.isSimple() && N1.getValueType().isSimple()
        && N2.getValueType().isSimple()) {
      assert(VT.isVector() && N1.getValueType().isVector() &&
             N2.getValueType().isVector() &&
             "Insert subvector VTs must be a vectors");
      assert(VT == N1.getValueType() &&
             "Dest and insert subvector source types must match!");
      assert(N2.getSimpleValueType() <= N1.getSimpleValueType() &&
             "Insert subvector must be from smaller vector to larger vector!");
      if (isa<ConstantSDNode>(Index)) {
        assert((N2.getValueType().getVectorNumElements() +
                cast<ConstantSDNode>(Index)->getZExtValue()
                <= VT.getVectorNumElements())
               && "Insert subvector overflow!");
      }

      // Trivial insertion.
      if (VT.getSimpleVT() == N2.getSimpleValueType())
        return N2;
    }
    break;
  }
  case ISD::BITCAST:
    // Fold bit_convert nodes from a type to themselves.
    if (N1.getValueType() == VT)
      return N1;
    break;
  }

  // Memoize node if it doesn't produce a flag.
  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) {
  SDValue Ops[] = { N1, N2, N3, N4 };
  return getNode(Opcode, DL, VT, Ops);
}

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

/// 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::use_iterator U = getEntryNode().getNode()->use_begin(),
       UE = getEntryNode().getNode()->use_end(); U != UE; ++U)
    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(DAG.EVTToAPFloatSemantics(VT), 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);
    else if (VT == MVT::f32 || VT == MVT::f64 || VT == MVT::f128)
      return DAG.getConstantFP(0.0, dl, VT);
    else if (VT.isVector()) {
      unsigned NumElts = VT.getVectorNumElements();
      MVT EltVT = (VT.getVectorElementType() == MVT::f32) ? MVT::i32 : MVT::i64;
      return DAG.getNode(ISD::BITCAST, dl, VT,
                         DAG.getConstant(0, dl,
                                         EVT::getVectorVT(*DAG.getContext(),
                                                          EltVT, NumElts)));
    } else
      llvm_unreachable("Expected type!");
  }

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

SDValue SelectionDAG::getMemBasePlusOffset(SDValue Base, unsigned Offset,
                                           const SDLoc &DL) {
  EVT VT = Base.getValueType();
  return getNode(ISD::ADD, DL, VT, Base, getConstant(Offset, DL, VT));
}

/// 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 = cast<ConstantSDNode>(Src.getOperand(1))->getZExtValue();
  }
  if (!G)
    return false;

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

/// Determines the optimal series of memory ops to replace the memset / memcpy.
/// Return true if the number of memory ops is below the threshold (Limit).
/// It returns the types of the sequence of memory ops to perform
/// memset / memcpy by reference.
static bool FindOptimalMemOpLowering(std::vector<EVT> &MemOps,
                                     unsigned Limit, uint64_t Size,
                                     unsigned DstAlign, unsigned SrcAlign,
                                     bool IsMemset,
                                     bool ZeroMemset,
                                     bool MemcpyStrSrc,
                                     bool AllowOverlap,
                                     unsigned DstAS, unsigned SrcAS,
                                     SelectionDAG &DAG,
                                     const TargetLowering &TLI) {
  assert((SrcAlign == 0 || SrcAlign >= DstAlign) &&
         "Expecting memcpy / memset source to meet alignment requirement!");
  // If 'SrcAlign' is zero, that means the memory operation does not need to
  // load the value, i.e. memset or memcpy from constant string. Otherwise,
  // it's the inferred alignment of the source. 'DstAlign', on the other hand,
  // is the specified alignment of the memory operation. If it is zero, that
  // means it's possible to change the alignment of the destination.
  // 'MemcpyStrSrc' indicates whether the memcpy source is constant so it does
  // not need to be loaded.
  EVT VT = TLI.getOptimalMemOpType(Size, DstAlign, SrcAlign,
                                   IsMemset, ZeroMemset, MemcpyStrSrc,
                                   DAG.getMachineFunction());

  if (VT == MVT::Other) {
    // Use the largest integer type whose alignment constraints are satisfied.
    // We only need to check DstAlign here as SrcAlign is always greater or
    // equal to DstAlign (or zero).
    VT = MVT::i64;
    while (DstAlign && DstAlign < VT.getSizeInBits() / 8 &&
           !TLI.allowsMisalignedMemoryAccesses(VT, DstAS, DstAlign))
      VT = (MVT::SimpleValueType)(VT.getSimpleVT().SimpleTy - 1);
    assert(VT.isInteger());

    // Find the largest legal integer type.
    MVT LVT = MVT::i64;
    while (!TLI.isTypeLegal(LVT))
      LVT = (MVT::SimpleValueType)(LVT.SimpleTy - 1);
    assert(LVT.isInteger());

    // If the type we've chosen is larger than the largest legal integer type
    // then use that instead.
    if (VT.bitsGT(LVT))
      VT = LVT;
  }

  unsigned NumMemOps = 0;
  while (Size != 0) {
    unsigned VTSize = VT.getSizeInBits() / 8;
    while (VTSize > Size) {
      // For now, only use non-vector load / store's for the left-over pieces.
      EVT NewVT = VT;
      unsigned NewVTSize;

      bool Found = false;
      if (VT.isVector() || VT.isFloatingPoint()) {
        NewVT = (VT.getSizeInBits() > 64) ? MVT::i64 : MVT::i32;
        if (TLI.isOperationLegalOrCustom(ISD::STORE, NewVT) &&
            TLI.isSafeMemOpType(NewVT.getSimpleVT()))
          Found = true;
        else if (NewVT == MVT::i64 &&
                 TLI.isOperationLegalOrCustom(ISD::STORE, MVT::f64) &&
                 TLI.isSafeMemOpType(MVT::f64)) {
          // i64 is usually not legal on 32-bit targets, but f64 may be.
          NewVT = MVT::f64;
          Found = true;
        }
      }

      if (!Found) {
        do {
          NewVT = (MVT::SimpleValueType)(NewVT.getSimpleVT().SimpleTy - 1);
          if (NewVT == MVT::i8)
            break;
        } while (!TLI.isSafeMemOpType(NewVT.getSimpleVT()));
      }
      NewVTSize = NewVT.getSizeInBits() / 8;

      // If the new VT cannot cover all of the remaining bits, then consider
      // issuing a (or a pair of) unaligned and overlapping load / store.
      bool Fast;
      if (NumMemOps && AllowOverlap && NewVTSize < Size &&
          TLI.allowsMisalignedMemoryAccesses(VT, DstAS, DstAlign, &Fast) &&
          Fast)
        VTSize = Size;
      else {
        VT = NewVT;
        VTSize = NewVTSize;
      }
    }

    if (++NumMemOps > Limit)
      return false;

    MemOps.push_back(VT);
    Size -= VTSize;
  }

  return true;
}

static bool shouldLowerMemFuncForSize(const MachineFunction &MF) {
  // 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 MF.getFunction().hasOptSize();
}

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, unsigned Align,
                                       bool isVol, bool AlwaysInline,
                                       MachinePointerInfo DstPtrInfo,
                                       MachinePointerInfo SrcPtrInfo) {
  // Turn a memcpy of undef to nop.
  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);
  FrameIndexSDNode *FI = dyn_cast<FrameIndexSDNode>(Dst);
  if (FI && !MFI.isFixedObjectIndex(FI->getIndex()))
    DstAlignCanChange = true;
  unsigned SrcAlign = DAG.InferPtrAlignment(Src);
  if (Align > SrcAlign)
    SrcAlign = Align;
  ConstantDataArraySlice Slice;
  bool CopyFromConstant = isMemSrcFromConstant(Src, Slice);
  bool isZeroConstant = CopyFromConstant && Slice.Array == nullptr;
  unsigned Limit = AlwaysInline ? ~0U : TLI.getMaxStoresPerMemcpy(OptSize);

  if (!FindOptimalMemOpLowering(MemOps, Limit, Size,
                                (DstAlignCanChange ? 0 : Align),
                                (isZeroConstant ? 0 : SrcAlign),
                                false, false, CopyFromConstant, true,
                                DstPtrInfo.getAddrSpace(),
                                SrcPtrInfo.getAddrSpace(),
                                DAG, TLI))
    return SDValue();

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

    // Don't promote to an alignment that would require dynamic stack
    // realignment.
    const TargetRegisterInfo *TRI = MF.getSubtarget().getRegisterInfo();
    if (!TRI->needsStackRealignment(MF))
      while (NewAlign > Align &&
             DL.exceedsNaturalStackAlignment(NewAlign))
          NewAlign /= 2;

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

  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, DstOff, dl),
                             DstPtrInfo.getWithOffset(DstOff), Align,
                             MMOFlags);
        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;

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

      Store = DAG.getTruncStore(
          Chain, dl, Value, DAG.getMemBasePlusOffset(Dst, DstOff, dl),
          DstPtrInfo.getWithOffset(DstOff), VT, Align, MMOFlags);
      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, unsigned Align,
                                        bool isVol, bool AlwaysInline,
                                        MachinePointerInfo DstPtrInfo,
                                        MachinePointerInfo SrcPtrInfo) {
  // Turn a memmove of undef to nop.
  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);
  FrameIndexSDNode *FI = dyn_cast<FrameIndexSDNode>(Dst);
  if (FI && !MFI.isFixedObjectIndex(FI->getIndex()))
    DstAlignCanChange = true;
  unsigned SrcAlign = DAG.InferPtrAlignment(Src);
  if (Align > SrcAlign)
    SrcAlign = Align;
  unsigned Limit = AlwaysInline ? ~0U : TLI.getMaxStoresPerMemmove(OptSize);

  if (!FindOptimalMemOpLowering(MemOps, Limit, Size,
                                (DstAlignCanChange ? 0 : Align), SrcAlign,
                                false, false, false, false,
                                DstPtrInfo.getAddrSpace(),
                                SrcPtrInfo.getAddrSpace(),
                                DAG, TLI))
    return SDValue();

  if (DstAlignCanChange) {
    Type *Ty = MemOps[0].getTypeForEVT(C);
    unsigned NewAlign = (unsigned)DL.getABITypeAlignment(Ty);
    if (NewAlign > Align) {
      // Give the stack frame object a larger alignment if needed.
      if (MFI.getObjectAlignment(FI->getIndex()) < NewAlign)
        MFI.setObjectAlignment(FI->getIndex(), NewAlign);
      Align = NewAlign;
    }
  }

  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, SrcOff, dl),
                    SrcPtrInfo.getWithOffset(SrcOff), SrcAlign, SrcMMOFlags);
    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, DstOff, dl),
                         DstPtrInfo.getWithOffset(DstOff), Align, MMOFlags);
    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 Align Alignment of the destination in bytes.
/// \param isVol True if destination is volatile.
/// \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.
static SDValue getMemsetStores(SelectionDAG &DAG, const SDLoc &dl,
                               SDValue Chain, SDValue Dst, SDValue Src,
                               uint64_t Size, unsigned Align, bool isVol,
                               MachinePointerInfo DstPtrInfo) {
  // Turn a memset of undef to nop.
  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;
  MachineFunction &MF = DAG.getMachineFunction();
  MachineFrameInfo &MFI = MF.getFrameInfo();
  bool OptSize = shouldLowerMemFuncForSize(MF);
  FrameIndexSDNode *FI = dyn_cast<FrameIndexSDNode>(Dst);
  if (FI && !MFI.isFixedObjectIndex(FI->getIndex()))
    DstAlignCanChange = true;
  bool IsZeroVal =
    isa<ConstantSDNode>(Src) && cast<ConstantSDNode>(Src)->isNullValue();
  if (!FindOptimalMemOpLowering(MemOps, TLI.getMaxStoresPerMemset(OptSize),
                                Size, (DstAlignCanChange ? 0 : Align), 0,
                                true, IsZeroVal, false, true,
                                DstPtrInfo.getAddrSpace(), ~0u,
                                DAG, TLI))
    return SDValue();

  if (DstAlignCanChange) {
    Type *Ty = MemOps[0].getTypeForEVT(*DAG.getContext());
    unsigned NewAlign = (unsigned)DAG.getDataLayout().getABITypeAlignment(Ty);
    if (NewAlign > Align) {
      // Give the stack frame object a larger alignment if needed.
      if (MFI.getObjectAlignment(FI->getIndex()) < NewAlign)
        MFI.setObjectAlignment(FI->getIndex(), NewAlign);
      Align = 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);

  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.
    SDValue Value = MemSetValue;
    if (VT.bitsLT(LargestVT)) {
      if (!LargestVT.isVector() && !VT.isVector() &&
          TLI.isTruncateFree(LargestVT, VT))
        Value = DAG.getNode(ISD::TRUNCATE, dl, VT, MemSetValue);
      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, DstOff, dl),
        DstPtrInfo.getWithOffset(DstOff), Align,
        isVol ? MachineMemOperand::MOVolatile : MachineMemOperand::MONone);
    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->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, unsigned Align,
                                bool isVol, bool AlwaysInline, bool isTailCall,
                                MachinePointerInfo DstPtrInfo,
                                MachinePointerInfo SrcPtrInfo) {
  assert(Align && "The SDAG layer expects explicit alignment and reserves 0");

  // 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->isNullValue())
      return Chain;

    SDValue Result = getMemcpyLoadsAndStores(*this, dl, Chain, Dst, Src,
                                             ConstantSize->getZExtValue(),Align,
                                isVol, false, DstPtrInfo, SrcPtrInfo);
    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, Align, 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(), Align, isVol,
                                   true, DstPtrInfo, SrcPtrInfo);
  }

  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 = Type::getInt8PtrTy(*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);
  CLI.setDebugLoc(dl)
      .setChain(Chain)
      .setLibCallee(TLI->getLibcallCallingConv(RTLIB::MEMCPY),
                    Dst.getValueType().getTypeForEVT(*getContext()),
                    getExternalSymbol(TLI->getLibcallName(RTLIB::MEMCPY),
                                      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, unsigned DstAlign,
                                      SDValue Src, unsigned SrcAlign,
                                      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, unsigned Align,
                                 bool isVol, bool isTailCall,
                                 MachinePointerInfo DstPtrInfo,
                                 MachinePointerInfo SrcPtrInfo) {
  assert(Align && "The SDAG layer expects explicit alignment and reserves 0");

  // 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->isNullValue())
      return Chain;

    SDValue Result =
      getMemmoveLoadsAndStores(*this, dl, Chain, Dst, Src,
                               ConstantSize->getZExtValue(), Align, isVol,
                               false, DstPtrInfo, SrcPtrInfo);
    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, Align, 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 = Type::getInt8PtrTy(*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);
  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, unsigned DstAlign,
                                       SDValue Src, unsigned SrcAlign,
                                       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, unsigned Align,
                                bool isVol, bool isTailCall,
                                MachinePointerInfo DstPtrInfo) {
  assert(Align && "The SDAG layer expects explicit alignment and reserves 0");

  // 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->isNullValue())
      return Chain;

    SDValue Result =
      getMemsetStores(*this, dl, Chain, Dst, Src, ConstantSize->getZExtValue(),
                      Align, isVol, DstPtrInfo);

    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, Align, isVol, DstPtrInfo);
    if (Result.getNode())
      return Result;
  }

  checkAddrSpaceIsValidForLibcall(TLI, DstPtrInfo.getAddrSpace());

  // Emit a library call.
  TargetLowering::ArgListTy Args;
  TargetLowering::ArgListEntry Entry;
  Entry.Node = Dst; Entry.Ty = Type::getInt8PtrTy(*getContext());
  Args.push_back(Entry);
  Entry.Node = Src;
  Entry.Ty = Src.getValueType().getTypeForEVT(*getContext());
  Args.push_back(Entry);
  Entry.Node = Size;
  Entry.Ty = getDataLayout().getIntPtrType(*getContext());
  Args.push_back(Entry);

  // FIXME: pass in SDLoc
  TargetLowering::CallLoweringInfo CLI(*this);
  CLI.setDebugLoc(dl)
      .setChain(Chain)
      .setLibCallee(TLI->getLibcallCallingConv(RTLIB::MEMSET),
                    Dst.getValueType().getTypeForEVT(*getContext()),
                    getExternalSymbol(TLI->getLibcallName(RTLIB::MEMSET),
                                      TLI->getPointerTy(getDataLayout())),
                    std::move(Args))
      .setDiscardResult()
      .setTailCall(isTailCall);

  std::pair<SDValue,SDValue> CallResult = TLI->LowerCallTo(CLI);
  return CallResult.second;
}

SDValue SelectionDAG::getAtomicMemset(SDValue Chain, const SDLoc &dl,
                                      SDValue Dst, unsigned DstAlign,
                                      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) {
  FoldingSetNodeID ID;
  ID.AddInteger(MemVT.getRawBits());
  AddNodeIDNode(ID, Opcode, VTList, Ops);
  ID.AddInteger(MMO->getPointerInfo().getAddrSpace());
  void* IP = nullptr;
  if (SDNode *E = FindNodeOrInsertPos(ID, dl, IP)) {
    cast<AtomicSDNode>(E)->refineAlignment(MMO);
    return SDValue(E, 0);
  }

  auto *N = newSDNode<AtomicSDNode>(Opcode, dl.getIROrder(), dl.getDebugLoc(),
                                    VTList, MemVT, MMO);
  createOperands(N, Ops);

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

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_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::getAtomic(unsigned Opcode, const SDLoc &dl, EVT MemVT,
                                EVT VT, SDValue Chain, SDValue Ptr,
                                MachineMemOperand *MMO) {
  assert(Opcode == ISD::ATOMIC_LOAD && "Invalid Atomic Op");

  SDVTList VTs = getVTList(VT, MVT::Other);
  SDValue Ops[] = {Chain, Ptr};
  return getAtomic(Opcode, dl, MemVT, VTs, Ops, MMO);
}

/// 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 (unsigned i = 0; i < Ops.size(); ++i)
    VTs.push_back(Ops[i].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, unsigned Align,
    MachineMemOperand::Flags Flags, unsigned Size) {
  if (Align == 0)  // Ensure that codegen never sees alignment 0
    Align = getEVTAlignment(MemVT);

  if (!Size)
    Size = MemVT.getStoreSize();

  MachineFunction &MF = getMachineFunction();
  MachineMemOperand *MMO =
    MF.getMachineMemOperand(PtrInfo, Flags, Size, Align);

  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 == ISD::LIFETIME_START ||
          Opcode == ISD::LIFETIME_END ||
          ((int)Opcode <= std::numeric_limits<int>::max() &&
           (int)Opcode >= ISD::FIRST_TARGET_MEMORY_OPCODE)) &&
         "Opcode is not a memory-accessing opcode!");

  // Memoize the node unless it returns a flag.
  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());
    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);
  return SDValue(N, 0);
}

SDValue SelectionDAG::getLifetimeNode(bool IsStart, const SDLoc &dl,
                                      SDValue Chain, int FrameIndex,
                                      int64_t Size, int64_t Offset) {
  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);
  ID.AddInteger(Size);
  ID.AddInteger(Offset);
  void *IP = nullptr;
  if (SDNode *E = FindNodeOrInsertPos(ID, dl, IP))
    return SDValue(E, 0);

  LifetimeSDNode *N = newSDNode<LifetimeSDNode>(
      Opcode, dl.getIROrder(), dl.getDebugLoc(), VTs, Size, Offset);
  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,
                              unsigned Alignment,
                              MachineMemOperand::Flags MMOFlags,
                              const AAMDNodes &AAInfo, const MDNode *Ranges) {
  assert(Chain.getValueType() == MVT::Other &&
        "Invalid chain type");
  if (Alignment == 0)  // Ensure that codegen never sees alignment 0
    Alignment = getEVTAlignment(MemVT);

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

  MachineFunction &MF = getMachineFunction();
  MachineMemOperand *MMO = MF.getMachineMemOperand(
      PtrInfo, MMOFlags, MemVT.getStoreSize(), 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.getVectorNumElements() == MemVT.getVectorNumElements()) &&
           "Cannot use an ext load to change the number of vector elements!");
  }

  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());
  void *IP = nullptr;
  if (SDNode *E = FindNodeOrInsertPos(ID, dl, IP)) {
    cast<LoadSDNode>(E)->refineAlignment(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,
                              unsigned 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,
                                 unsigned 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->getAlignment(), MMOFlags,
                 LD->getAAInfo());
}

SDValue SelectionDAG::getStore(SDValue Chain, const SDLoc &dl, SDValue Val,
                               SDValue Ptr, MachinePointerInfo PtrInfo,
                               unsigned Alignment,
                               MachineMemOperand::Flags MMOFlags,
                               const AAMDNodes &AAInfo) {
  assert(Chain.getValueType() == MVT::Other && "Invalid chain type");
  if (Alignment == 0)  // Ensure that codegen never sees alignment 0
    Alignment = getEVTAlignment(Val.getValueType());

  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, Val.getValueType().getStoreSize(), Alignment, AAInfo);
  return getStore(Chain, dl, Val, Ptr, MMO);
}

SDValue SelectionDAG::getStore(SDValue Chain, const SDLoc &dl, SDValue Val,
                               SDValue Ptr, MachineMemOperand *MMO) {
  assert(Chain.getValueType() == MVT::Other &&
        "Invalid chain type");
  EVT VT = Val.getValueType();
  SDVTList VTs = getVTList(MVT::Other);
  SDValue Undef = getUNDEF(Ptr.getValueType());
  SDValue Ops[] = { Chain, Val, Ptr, Undef };
  FoldingSetNodeID ID;
  AddNodeIDNode(ID, ISD::STORE, VTs, Ops);
  ID.AddInteger(VT.getRawBits());
  ID.AddInteger(getSyntheticNodeSubclassData<StoreSDNode>(
      dl.getIROrder(), VTs, ISD::UNINDEXED, false, VT, MMO));
  ID.AddInteger(MMO->getPointerInfo().getAddrSpace());
  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,
                                   ISD::UNINDEXED, false, VT, 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, unsigned Alignment,
                                    MachineMemOperand::Flags MMOFlags,
                                    const AAMDNodes &AAInfo) {
  assert(Chain.getValueType() == MVT::Other &&
        "Invalid chain type");
  if (Alignment == 0)  // Ensure that codegen never sees alignment 0
    Alignment = getEVTAlignment(SVT);

  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) {
  EVT VT = Val.getValueType();

  assert(Chain.getValueType() == MVT::Other &&
        "Invalid chain type");
  if (VT == SVT)
    return getStore(Chain, dl, Val, Ptr, MMO);

  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.getVectorNumElements() == SVT.getVectorNumElements()) &&
         "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 };
  FoldingSetNodeID ID;
  AddNodeIDNode(ID, ISD::STORE, VTs, Ops);
  ID.AddInteger(SVT.getRawBits());
  ID.AddInteger(getSyntheticNodeSubclassData<StoreSDNode>(
      dl.getIROrder(), VTs, ISD::UNINDEXED, true, SVT, MMO));
  ID.AddInteger(MMO->getPointerInfo().getAddrSpace());
  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,
                                   ISD::UNINDEXED, true, 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::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!");
  SDVTList VTs = getVTList(Base.getValueType(), MVT::Other);
  SDValue Ops[] = { ST->getChain(), ST->getValue(), Base, Offset };
  FoldingSetNodeID ID;
  AddNodeIDNode(ID, ISD::STORE, VTs, Ops);
  ID.AddInteger(ST->getMemoryVT().getRawBits());
  ID.AddInteger(ST->getRawSubclassData());
  ID.AddInteger(ST->getPointerInfo().getAddrSpace());
  void *IP = nullptr;
  if (SDNode *E = FindNodeOrInsertPos(ID, dl, IP))
    return SDValue(E, 0);

  auto *N = newSDNode<StoreSDNode>(dl.getIROrder(), dl.getDebugLoc(), VTs, AM,
                                   ST->isTruncatingStore(), 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::getMaskedLoad(EVT VT, const SDLoc &dl, SDValue Chain,
                                    SDValue Ptr, SDValue Mask, SDValue PassThru,
                                    EVT MemVT, MachineMemOperand *MMO,
                                    ISD::LoadExtType ExtTy, bool isExpanding) {
  SDVTList VTs = getVTList(VT, MVT::Other);
  SDValue Ops[] = { Chain, Ptr, Mask, PassThru };
  FoldingSetNodeID ID;
  AddNodeIDNode(ID, ISD::MLOAD, VTs, Ops);
  ID.AddInteger(VT.getRawBits());
  ID.AddInteger(getSyntheticNodeSubclassData<MaskedLoadSDNode>(
      dl.getIROrder(), VTs, ExtTy, isExpanding, MemVT, MMO));
  ID.AddInteger(MMO->getPointerInfo().getAddrSpace());
  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,
                                        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::getMaskedStore(SDValue Chain, const SDLoc &dl,
                                     SDValue Val, SDValue Ptr, SDValue Mask,
                                     EVT MemVT, MachineMemOperand *MMO,
                                     bool IsTruncating, bool IsCompressing) {
  assert(Chain.getValueType() == MVT::Other &&
        "Invalid chain type");
  EVT VT = Val.getValueType();
  SDVTList VTs = getVTList(MVT::Other);
  SDValue Ops[] = { Chain, Val, Ptr, Mask };
  FoldingSetNodeID ID;
  AddNodeIDNode(ID, ISD::MSTORE, VTs, Ops);
  ID.AddInteger(VT.getRawBits());
  ID.AddInteger(getSyntheticNodeSubclassData<MaskedStoreSDNode>(
      dl.getIROrder(), VTs, IsTruncating, IsCompressing, MemVT, MMO));
  ID.AddInteger(MMO->getPointerInfo().getAddrSpace());
  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,
                                         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::getMaskedGather(SDVTList VTs, EVT VT, const SDLoc &dl,
                                      ArrayRef<SDValue> Ops,
                                      MachineMemOperand *MMO) {
  assert(Ops.size() == 6 && "Incompatible number of operands");

  FoldingSetNodeID ID;
  AddNodeIDNode(ID, ISD::MGATHER, VTs, Ops);
  ID.AddInteger(VT.getRawBits());
  ID.AddInteger(getSyntheticNodeSubclassData<MaskedGatherSDNode>(
      dl.getIROrder(), VTs, VT, MMO));
  ID.AddInteger(MMO->getPointerInfo().getAddrSpace());
  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, VT, MMO);
  createOperands(N, Ops);

  assert(N->getPassThru().getValueType() == N->getValueType(0) &&
         "Incompatible type of the PassThru value in MaskedGatherSDNode");
  assert(N->getMask().getValueType().getVectorNumElements() ==
             N->getValueType(0).getVectorNumElements() &&
         "Vector width mismatch between mask and data");
  assert(N->getIndex().getValueType().getVectorNumElements() >=
             N->getValueType(0).getVectorNumElements() &&
         "Vector width mismatch between index and data");
  assert(isa<ConstantSDNode>(N->getScale()) &&
         cast<ConstantSDNode>(N->getScale())->getAPIntValue().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 VT, const SDLoc &dl,
                                       ArrayRef<SDValue> Ops,
                                       MachineMemOperand *MMO) {
  assert(Ops.size() == 6 && "Incompatible number of operands");

  FoldingSetNodeID ID;
  AddNodeIDNode(ID, ISD::MSCATTER, VTs, Ops);
  ID.AddInteger(VT.getRawBits());
  ID.AddInteger(getSyntheticNodeSubclassData<MaskedScatterSDNode>(
      dl.getIROrder(), VTs, VT, MMO));
  ID.AddInteger(MMO->getPointerInfo().getAddrSpace());
  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, VT, MMO);
  createOperands(N, Ops);

  assert(N->getMask().getValueType().getVectorNumElements() ==
             N->getValue().getValueType().getVectorNumElements() &&
         "Vector width mismatch between mask and data");
  assert(N->getIndex().getValueType().getVectorNumElements() >=
             N->getValue().getValueType().getVectorNumElements() &&
         "Vector width mismatch between index and data");
  assert(isa<ConstantSDNode>(N->getScale()) &&
         cast<ConstantSDNode>(N->getScale())->getAPIntValue().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::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 *CondC = dyn_cast<ConstantSDNode>(Cond))
    return CondC->isNullValue() ? F : T;

  // TODO: This should simplify VSELECT with constant condition using something
  // like this (but check boolean contents to be complete?):
  //  if (ISD::isBuildVectorAllOnes(Cond.getNode()))
  //    return T;
  //  if (ISD::isBuildVectorAllZeros(Cond.getNode()))
  //    return 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());

  return SDValue();
}

// TODO: Use fast-math-flags to enable more simplifications.
SDValue SelectionDAG::simplifyFPBinop(unsigned Opcode, SDValue X, SDValue Y) {
  ConstantFPSDNode *YC = isConstOrConstSplatFP(Y, /* AllowUndefs */ true);
  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;

  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, static_cast<const SDValue>(Ops[0]));
  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.begin(), Ops.end());
  return getNode(Opcode, DL, VT, NewOps);
}

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

  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:
    // Attempt to fold CONCAT_VECTORS into BUILD_VECTOR or UNDEF.
    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!");
    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;
  }

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

  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) {
  return getNode(Opcode, DL, getVTList(ResultTys), Ops);
}

SDValue SelectionDAG::getNode(unsigned Opcode, const SDLoc &DL, SDVTList VTList,
                              ArrayRef<SDValue> Ops) {
  if (VTList.NumVTs == 1)
    return getNode(Opcode, DL, VTList.VTs[0], Ops);

#if 0
  switch (Opcode) {
  // FIXME: figure out how to safely handle things like
  // int foo(int x) { return 1 << (x & 255); }
  // int bar() { return foo(256); }
  case ISD::SRA_PARTS:
  case ISD::SRL_PARTS:
  case ISD::SHL_PARTS:
    if (N3.getOpcode() == ISD::SIGN_EXTEND_INREG &&
        cast<VTSDNode>(N3.getOperand(1))->getVT() != MVT::i1)
      return getNode(Opcode, DL, VT, N1, N2, N3.getOperand(0));
    else if (N3.getOpcode() == ISD::AND)
      if (ConstantSDNode *AndRHS = dyn_cast<ConstantSDNode>(N3.getOperand(1))) {
        // If the and is only masking out bits that cannot effect the shift,
        // eliminate the and.
        unsigned NumBits = VT.getScalarSizeInBits()*2;
        if ((AndRHS->getValue() & (NumBits-1)) == NumBits-1)
          return getNode(Opcode, DL, VT, N1, N2, N3.getOperand(0));
      }
    break;
  }
#endif

  // Memoize the node unless it returns a flag.
  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))
      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);
  }
  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, None);
}

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) {
  return makeVTList(SDNode::getValueTypeList(VT), 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, None);
}

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

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 == CodeGenOpt::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;
  bool IsUnary = false;
  bool IsTernary = false;
  switch (OrigOpc) {
  default:
    llvm_unreachable("mutateStrictFPToFP called with unexpected opcode!");
  case ISD::STRICT_FADD: NewOpc = ISD::FADD; break;
  case ISD::STRICT_FSUB: NewOpc = ISD::FSUB; break;
  case ISD::STRICT_FMUL: NewOpc = ISD::FMUL; break;
  case ISD::STRICT_FDIV: NewOpc = ISD::FDIV; break;
  case ISD::STRICT_FREM: NewOpc = ISD::FREM; break;
  case ISD::STRICT_FMA: NewOpc = ISD::FMA; IsTernary = true; break;
  case ISD::STRICT_FSQRT: NewOpc = ISD::FSQRT; IsUnary = true; break;
  case ISD::STRICT_FPOW: NewOpc = ISD::FPOW; break;
  case ISD::STRICT_FPOWI: NewOpc = ISD::FPOWI; break;
  case ISD::STRICT_FSIN: NewOpc = ISD::FSIN; IsUnary = true; break;
  case ISD::STRICT_FCOS: NewOpc = ISD::FCOS; IsUnary = true; break;
  case ISD::STRICT_FEXP: NewOpc = ISD::FEXP; IsUnary = true; break;
  case ISD::STRICT_FEXP2: NewOpc = ISD::FEXP2; IsUnary = true; break;
  case ISD::STRICT_FLOG: NewOpc = ISD::FLOG; IsUnary = true; break;
  case ISD::STRICT_FLOG10: NewOpc = ISD::FLOG10; IsUnary = true; break;
  case ISD::STRICT_FLOG2: NewOpc = ISD::FLOG2; IsUnary = true; break;
  case ISD::STRICT_FRINT: NewOpc = ISD::FRINT; IsUnary = true; break;
  case ISD::STRICT_FNEARBYINT:
    NewOpc = ISD::FNEARBYINT;
    IsUnary = true;
    break;
  case ISD::STRICT_FMAXNUM: NewOpc = ISD::FMAXNUM; break;
  case ISD::STRICT_FMINNUM: NewOpc = ISD::FMINNUM; break;
  case ISD::STRICT_FCEIL: NewOpc = ISD::FCEIL; IsUnary = true; break;
  case ISD::STRICT_FFLOOR: NewOpc = ISD::FFLOOR; IsUnary = true; break;
  case ISD::STRICT_FROUND: NewOpc = ISD::FROUND; IsUnary = true; break;
  case ISD::STRICT_FTRUNC: NewOpc = ISD::FTRUNC; IsUnary = true; break;
  }

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

  SDVTList VTs = getVTList(Node->getOperand(1).getValueType());
  SDNode *Res = nullptr;
  if (IsUnary)
    Res = MorphNodeTo(Node, NewOpc, VTs, { Node->getOperand(1) });
  else if (IsTernary)
    Res = MorphNodeTo(Node, NewOpc, VTs, { Node->getOperand(1),
                                           Node->getOperand(2),
                                           Node->getOperand(3)});
  else
    Res = MorphNodeTo(Node, NewOpc, VTs, { Node->getOperand(1),
                                           Node->getOperand(2) });

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

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

/// 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(Var, Expr, N, R, IsIndirect, DL, O);
}

/// 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(Var, Expr, C, DL, O);
}

/// 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 new (DbgInfo->getAlloc())
      SDDbgValue(Var, Expr, FI, IsIndirect, DL, O, SDDbgValue::FRAMEIX);
}

/// VReg
SDDbgValue *SelectionDAG::getVRegDbgValue(DIVariable *Var,
                                          DIExpression *Expr,
                                          unsigned 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(Var, Expr, VReg, IsIndirect, DL, O, SDDbgValue::VREG);
}

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;

  SmallVector<SDDbgValue *, 2> ClonedDVs;
  for (SDDbgValue *Dbg : GetDbgValues(FromNode)) {
    if (Dbg->getKind() != SDDbgValue::SDNODE || Dbg->isInvalidated())
      continue;

    // TODO: assert(!Dbg->isInvalidated() && "Transfer of invalid dbg value");

    // Just transfer the dbg value attached to From.
    if (Dbg->getResNo() != From.getResNo())
      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;
    }
    // Clone the SDDbgValue and move it to To.
    SDDbgValue *Clone =
        getDbgValue(Var, Expr, ToNode, To.getResNo(), Dbg->isIndirect(),
                    Dbg->getDebugLoc(), Dbg->getOrder());
    ClonedDVs.push_back(Clone);

    if (InvalidateDbg) {
      // Invalidate value and indicate the SDDbgValue should not be emitted.
      Dbg->setIsInvalidated();
      Dbg->setIsEmitted();
    }
  }

  for (SDDbgValue *Dbg : ClonedDVs)
    AddDbgValue(Dbg, ToNode, false);
}

void SelectionDAG::salvageDebugInfo(SDNode &N) {
  if (!N.getHasDebugValue())
    return;

  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 (!isConstantIntBuildVectorOrConstantInt(N0) &&
          isConstantIntBuildVectorOrConstantInt(N1)) {
        uint64_t Offset = N.getConstantOperandVal(1);
        // 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();
        DIExpr = DIExpression::prepend(DIExpr, DIExpression::NoDeref, Offset,
                                       DIExpression::NoDeref,
                                       DIExpression::WithStackValue);
        SDDbgValue *Clone =
            getDbgValue(DV->getVariable(), DIExpr, N0.getNode(), N0.getResNo(),
                        DV->isIndirect(), DV->getDebugLoc(), DV->getOrder());
        ClonedDVs.push_back(Clone);
        DV->setIsInvalidated();
        DV->setIsEmitted();
        LLVM_DEBUG(dbgs() << "SALVAGE: Rewriting";
                   N0.getNode()->dumprFull(this);
                   dbgs() << " into " << *DIExpr << '\n');
      }
    }
  }

  for (SDDbgValue *Dbg : ClonedDVs)
    AddDbgValue(Dbg, Dbg->getSDNode(), 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)
      ++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);

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

    // 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.getUse();
      ++UI;
      Use.set(To);
      if (To->isDivergent() != From->isDivergent())
        updateDivergence(User);
    } while (UI != UE && *UI == 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));
    }

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

    // 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.getUse();
      ++UI;
      Use.setNode(To);
      if (To->isDivergent() != From->isDivergent())
        updateDivergence(User);
    } while (UI != UE && *UI == 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]);

  // Preserve Debug Info.
  for (unsigned i = 0, e = From->getNumValues(); i != e; ++i)
    transferDbgValues(SDValue(From, i), To[i]);

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

    // 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.getUse();
      const SDValue &ToOp = To[Use.getResNo()];
      ++UI;
      Use.set(ToOp);
      To_IsDivergent |= ToOp->isDivergent();
    } while (UI != UE && *UI == 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);

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

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

} // end anonymous namespace

void SelectionDAG::updateDivergence(SDNode * N)
{
  if (TLI->isSDNodeAlwaysUniform(N))
    return;
  bool IsDivergent = TLI->isSDNodeSourceOfDivergence(N, FLI, DA);
  for (auto &Op : N->ops()) {
    if (Op.Val.getValueType() != MVT::Other)
      IsDivergent |= Op.getNode()->isDivergent();
  }
  if (N->SDNodeBits.IsDivergent != IsDivergent) {
    N->SDNodeBits.IsDivergent = IsDivergent;
    for (auto U : N->uses()) {
      updateDivergence(U);
    }
  }
}


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 (std::vector<SDNode *>::iterator I = Order.begin();
  I!=Order.end();++I) {
    SDNode * N = *I;
    for (auto U : N->uses()) {
      unsigned &UnsortedOps = Degree[U];
      if (0 == --UnsortedOps)
        Order.push_back(U);
    }
  }
}

#ifndef NDEBUG
void SelectionDAG::VerifyDAGDiverence()
{
  std::vector<SDNode*> TopoOrder;
  CreateTopologicalOrder(TopoOrder);
  const TargetLowering &TLI = getTargetLoweringInfo();
  DenseMap<const SDNode *, bool> DivergenceMap;
  for (auto &N : allnodes()) {
    DivergenceMap[&N] = false;
  }
  for (auto N : TopoOrder) {
    bool IsDivergent = DivergenceMap[N];
    bool IsSDNodeDivergent = TLI.isSDNodeSourceOfDivergence(N, FLI, DA);
    for (auto &Op : N->ops()) {
      if (Op.Val.getValueType() != MVT::Other)
        IsSDNodeDivergent |= DivergenceMap[Op.getNode()];
    }
    if (!IsDivergent && IsSDNodeDivergent && !TLI.isSDNodeAlwaysUniform(N)) {
      DivergenceMap[N] = true;
    }
  }
  for (auto &N : allnodes()) {
    (void)N;
    assert(DivergenceMap[&N] == N.isDivergent() &&
           "Divergence bit inconsistency detected\n");
  }
}
#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);

  // 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 (SDNode::use_iterator UI = FromNode->use_begin(),
         E = FromNode->use_end(); UI != E; ++UI) {
      SDUse &Use = UI.getUse();
      if (Use.getResNo() == FromResNo) {
        UseMemo Memo = { *UI, i, &Use };
        Uses.push_back(Memo);
      }
    }
  }

  // Sort the uses, so that all the uses from a given User are together.
  llvm::sort(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;

    // 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 (allnodes_iterator I = allnodes_begin(),E = allnodes_end(); I != E; ) {
    SDNode *N = &*I++;
    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::use_iterator UI = N->use_begin(), UE = N->use_end();
         UI != UE; ++UI) {
      SDNode *P = *UI;
      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, SDNode *SD, bool isParameter) {
  if (SD) {
    assert(DbgInfo->getSDDbgValues(SD).empty() || SD->getHasDebugValue());
    SD->setHasDebugValue(true);
  }
  DbgInfo->add(DB, SD, isParameter);
}

void SelectionDAG::AddDbgLabel(SDDbgLabel *DB) {
  DbgInfo->add(DB);
}

SDValue SelectionDAG::makeEquivalentMemoryOrdering(LoadSDNode *OldLoad,
                                                   SDValue NewMemOp) {
  assert(isa<MemSDNode>(NewMemOp.getNode()) && "Expected a memop node");
  // 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.
  SDValue OldChain = SDValue(OldLoad, 1);
  SDValue NewChain = SDValue(NewMemOp.getNode(), 1);
  if (!OldLoad->hasAnyUseOfValue(1))
    return NewChain;

  SDValue TokenFactor =
      getNode(ISD::TokenFactor, SDLoc(OldLoad), MVT::Other, OldChain, NewChain);
  ReplaceAllUsesOfValueWith(OldChain, TokenFactor);
  UpdateNodeOperands(TokenFactor.getNode(), OldChain, NewChain);
  return TokenFactor;
}

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 << '"';
  ErrorFormatter.flush();

  report_fatal_error(ErrorStr);
}

//===----------------------------------------------------------------------===//
//                              SDNode Class
//===----------------------------------------------------------------------===//

bool llvm::isNullConstant(SDValue V) {
  ConstantSDNode *Const = dyn_cast<ConstantSDNode>(V);
  return Const != nullptr && Const->isNullValue();
}

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

bool llvm::isOneConstant(SDValue V) {
  ConstantSDNode *Const = dyn_cast<ConstantSDNode>(V);
  return Const != nullptr && Const->isOne();
}

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

bool llvm::isBitwiseNot(SDValue V) {
  if (V.getOpcode() != ISD::XOR)
    return false;
  ConstantSDNode *C = isConstOrConstSplat(peekThroughBitcasts(V.getOperand(1)));
  return C && C->isAllOnesValue();
}

ConstantSDNode *llvm::isConstOrConstSplat(SDValue N, bool AllowUndefs) {
  if (ConstantSDNode *CN = dyn_cast<ConstantSDNode>(N))
    return CN;

  if (BuildVectorSDNode *BV = dyn_cast<BuildVectorSDNode>(N)) {
    BitVector UndefElements;
    ConstantSDNode *CN = BV->getConstantSplatNode(&UndefElements);

    // BuildVectors can truncate their operands. Ignore that case here.
    if (CN && (UndefElements.none() || AllowUndefs) &&
        CN->getValueType(0) == N.getValueType().getScalarType())
      return CN;
  }

  return nullptr;
}

ConstantSDNode *llvm::isConstOrConstSplat(SDValue N, const APInt &DemandedElts,
                                          bool AllowUndefs) {
  if (ConstantSDNode *CN = dyn_cast<ConstantSDNode>(N))
    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.
    if (CN && (UndefElements.none() || AllowUndefs) &&
        CN->getValueType(0) == N.getValueType().getScalarType())
      return CN;
  }

  return nullptr;
}

ConstantFPSDNode *llvm::isConstOrConstSplatFP(SDValue N, bool AllowUndefs) {
  if (ConstantFPSDNode *CN = dyn_cast<ConstantFPSDNode>(N))
    return CN;

  if (BuildVectorSDNode *BV = dyn_cast<BuildVectorSDNode>(N)) {
    BitVector UndefElements;
    ConstantFPSDNode *CN = BV->getConstantFPSplatNode(&UndefElements);
    if (CN && (UndefElements.none() || AllowUndefs))
      return CN;
  }

  return nullptr;
}

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);
    if (CN && (UndefElements.none() || AllowUndefs))
      return CN;
  }

  return nullptr;
}

bool llvm::isNullOrNullSplat(SDValue N, bool AllowUndefs) {
  // TODO: may want to use peekThroughBitcast() here.
  ConstantSDNode *C = isConstOrConstSplat(N, AllowUndefs);
  return C && C->isNullValue();
}

bool llvm::isOneOrOneSplat(SDValue N) {
  // TODO: may want to use peekThroughBitcast() here.
  unsigned BitWidth = N.getScalarValueSizeInBits();
  ConstantSDNode *C = isConstOrConstSplat(N);
  return C && C->isOne() && C->getValueSizeInBits(0) == BitWidth;
}

bool llvm::isAllOnesOrAllOnesSplat(SDValue N) {
  N = peekThroughBitcasts(N);
  unsigned BitWidth = N.getScalarValueSizeInBits();
  ConstantSDNode *C = isConstOrConstSplat(N);
  return C && C->isAllOnesValue() && C->getValueSizeInBits(0) == BitWidth;
}

HandleSDNode::~HandleSDNode() {
  DropOperands();
}

GlobalAddressSDNode::GlobalAddressSDNode(unsigned Opc, unsigned Order,
                                         const DebugLoc &DL,
                                         const GlobalValue *GA, EVT VT,
                                         int64_t o, unsigned char TF)
    : SDNode(Opc, Order, DL, getSDVTList(VT)), Offset(o), TargetFlags(TF) {
  TheGlobal = GA;
}

AddrSpaceCastSDNode::AddrSpaceCastSDNode(unsigned Order, const DebugLoc &dl,
                                         EVT VT, unsigned SrcAS,
                                         unsigned DestAS)
    : SDNode(ISD::ADDRSPACECAST, Order, dl, getSDVTList(VT)),
      SrcAddrSpace(SrcAS), DestAddrSpace(DestAS) {}

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(memvt.getStoreSize() <= MMO->getSize() && "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::LAST_VALUETYPE);
      for (unsigned i = 0; i < MVT::LAST_VALUETYPE; ++i)
        VTs.push_back(MVT((MVT::SimpleValueType)i));
    }
  };

} // end anonymous namespace

static ManagedStatic<std::set<EVT, EVT::compareRawBits>> EVTs;
static ManagedStatic<EVTArray> SimpleVTArray;
static ManagedStatic<sys::SmartMutex<true>> VTMutex;

/// getValueTypeList - Return a pointer to the specified value type.
///
const EVT *SDNode::getValueTypeList(EVT VT) {
  if (VT.isExtended()) {
    sys::SmartScopedLock<true> Lock(*VTMutex);
    return &(*EVTs->insert(VT).first);
  } else {
    assert(VT.getSimpleVT() < MVT::LAST_VALUETYPE &&
           "Value type out of range!");
    return &SimpleVTArray->VTs[VT.getSimpleVT().SimpleTy];
  }
}

/// hasNUsesOfValue - Return true if there are exactly NUSES uses of the
/// indicated value.  This method ignores uses of other values defined by this
/// operation.
bool SDNode::hasNUsesOfValue(unsigned NUses, unsigned Value) const {
  assert(Value < getNumValues() && "Bad value!");

  // TODO: Only iterate over uses of a given value of the node
  for (SDNode::use_iterator UI = use_begin(), E = use_end(); UI != E; ++UI) {
    if (UI.getUse().getResNo() == Value) {
      if (NUses == 0)
        return false;
      --NUses;
    }
  }

  // Found exactly the right number of uses?
  return NUses == 0;
}

/// 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 (SDNode::use_iterator UI = use_begin(), E = use_end(); UI != E; ++UI)
    if (UI.getUse().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 (SDNode::use_iterator I = N->use_begin(), E = N->use_end(); I != E; ++I) {
    SDNode *User = *I;
    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 (SDNode::use_iterator I = N->use_begin(), E = N->use_end(); I != E; ++I) {
    SDNode *User = *I;
    if (llvm::any_of(Nodes,
                     [&User](const SDNode *Node) { return User == Node; }))
      Seen = true;
    else
      return false;
  }

  return Seen;
}

/// isOperand - Return true if this node is an operand of N.
bool SDValue::isOperandOf(const SDNode *N) const {
  for (const SDValue &Op : N->op_values())
    if (*this == Op)
      return true;
  return false;
}

bool SDNode::isOperandOf(const SDNode *N) const {
  for (const SDValue &Op : N->op_values())
    if (this == Op.getNode())
      return true;
  return false;
}

/// 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->isVolatile())
      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.intersectWith(Flags);
}

SDValue
SelectionDAG::matchBinOpReduction(SDNode *Extract, ISD::NodeType &BinOp,
                                  ArrayRef<ISD::NodeType> CandidateBinOps) {
  // The pattern must end in an extract from index 0.
  if (Extract->getOpcode() != ISD::EXTRACT_VECTOR_ELT ||
      !isNullConstant(Extract->getOperand(1)))
    return SDValue();

  SDValue Op = Extract->getOperand(0);
  unsigned Stages = Log2_32(Op.getValueType().getVectorNumElements());

  // Match against one of the candidate binary ops.
  if (llvm::none_of(CandidateBinOps, [Op](ISD::NodeType BinOp) {
        return Op.getOpcode() == unsigned(BinOp);
      }))
    return SDValue();

  // 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>
  unsigned CandidateBinOp = Op.getOpcode();
  for (unsigned i = 0; i < Stages; ++i) {
    if (Op.getOpcode() != CandidateBinOp)
      return SDValue();

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

    // Verify the shuffle has the expected (at this stage of the pyramid) mask.
    for (int Index = 0, MaskEnd = 1 << i; Index < MaskEnd; ++Index)
      if (Shuffle->getMaskElt(Index) != MaskEnd + Index)
        return SDValue();
  }

  BinOp = (ISD::NodeType)CandidateBinOp;
  return Op;
}

SDValue SelectionDAG::UnrollVectorOp(SDNode *N, unsigned ResNE) {
  assert(N->getNumValues() == 1 &&
         "Can't unroll a vector with multiple results!");

  EVT VT = N->getValueType(0);
  unsigned NE = VT.getVectorNumElements();
  EVT EltVT = VT.getVectorElementType();
  SDLoc dl(N);

  SmallVector<SDValue, 8> Scalars;
  SmallVector<SDValue, 4> Operands(N->getNumOperands());

  // If ResNE is 0, fully unroll the vector op.
  if (ResNE == 0)
    ResNE = NE;
  else if (NE > ResNE)
    NE = ResNE;

  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] =
            getNode(ISD::EXTRACT_VECTOR_ELT, dl, OperandEltVT, Operand,
                    getConstant(i, dl, TLI->getVectorIdxTy(getDataLayout())));
      } 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:
    case ISD::FP_ROUND_INREG: {
      EVT ExtVT = cast<VTSDNode>(Operands[1])->getVT().getVectorElementType();
      Scalars.push_back(getNode(N->getOpcode(), dl, EltVT,
                                Operands[0],
                                getValueType(ExtVT)));
    }
    }
  }

  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;
  if (LD->isIndexed() || Base->isIndexed())
    return false;
  if (LD->getChain() != Base->getChain())
    return false;
  EVT VT = LD->getValueType(0);
  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 * Bytes == Offset);
  return false;
}

/// InferPtrAlignment - Infer alignment of a load / store address. Return 0 if
/// it cannot be inferred.
unsigned SelectionDAG::InferPtrAlignment(SDValue Ptr) const {
  // If this is a GlobalAddress + cst, return the alignment.
  const GlobalValue *GV;
  int64_t GVOffset = 0;
  if (TLI->isGAPlusOffset(Ptr.getNode(), GV, GVOffset)) {
    unsigned IdxWidth = getDataLayout().getIndexTypeSizeInBits(GV->getType());
    KnownBits Known(IdxWidth);
    llvm::computeKnownBits(GV, Known, getDataLayout());
    unsigned AlignBits = Known.countMinTrailingZeros();
    unsigned Align = AlignBits ? 1 << std::min(31U, AlignBits) : 0;
    if (Align)
      return MinAlign(Align, GVOffset);
  }

  // If this is a direct reference to a stack slot, use information about the
  // stack slot's alignment.
  int FrameIdx = 1 << 31;
  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 != (1 << 31)) {
    const MachineFrameInfo &MFI = getMachineFunction().getFrameInfo();
    unsigned FIInfoAlign = MinAlign(MFI.getObjectAlignment(FrameIdx),
                                    FrameOffset);
    return FIInfoAlign;
  }

  return 0;
}

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

/// 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.getVectorNumElements() + HiVT.getVectorNumElements() <=
         N.getValueType().getVectorNumElements() &&
         "More vector elements requested than available!");
  SDValue Lo, Hi;
  Lo = getNode(ISD::EXTRACT_SUBVECTOR, DL, LoVT, N,
               getConstant(0, DL, TLI->getVectorIdxTy(getDataLayout())));
  Hi = getNode(ISD::EXTRACT_SUBVECTOR, DL, HiVT, N,
               getConstant(LoVT.getVectorNumElements(), DL,
                           TLI->getVectorIdxTy(getDataLayout())));
  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 getNode(ISD::INSERT_SUBVECTOR, DL, WideVT, getUNDEF(WideVT), N,
                 getConstant(0, DL, TLI->getVectorIdxTy(getDataLayout())));
}

void SelectionDAG::ExtractVectorElements(SDValue Op,
                                         SmallVectorImpl<SDValue> &Args,
                                         unsigned Start, unsigned Count) {
  EVT VT = Op.getValueType();
  if (Count == 0)
    Count = VT.getVectorNumElements();

  EVT EltVT = VT.getVectorElementType();
  EVT IdxTy = TLI->getVectorIdxTy(getDataLayout());
  SDLoc SL(Op);
  for (unsigned i = Start, e = Start + Count; i != e; ++i) {
    Args.push_back(getNode(ISD::EXTRACT_VECTOR_ELT, SL, EltVT,
                           Op, getConstant(i, SL, IdxTy)));
  }
}

// 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) {
    unsigned HalfSize = VecWidth / 2;
    APInt HighValue = SplatValue.lshr(HalfSize).trunc(HalfSize);
    APInt LowValue = SplatValue.trunc(HalfSize);
    APInt HighUndef = SplatUndef.lshr(HalfSize).trunc(HalfSize);
    APInt LowUndef = SplatUndef.trunc(HalfSize);

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

  SplatBitSize = VecWidth;
  return true;
}

SDValue BuildVectorSDNode::getSplatValue(const APInt &DemandedElts,
                                         BitVector *UndefElements) const {
  if (UndefElements) {
    UndefElements->clear();
    UndefElements->resize(getNumOperands());
  }
  assert(getNumOperands() == DemandedElts.getBitWidth() &&
         "Unexpected vector size");
  if (!DemandedElts)
    return SDValue();
  SDValue Splatted;
  for (unsigned i = 0, e = getNumOperands(); i != e; ++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.countTrailingZeros();
    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::getAllOnesValue(getNumOperands());
  return getSplatValue(DemandedElts, 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::isConstant() const {
  for (const SDValue &Op : op_values()) {
    unsigned Opc = Op.getOpcode();
    if (Opc != ISD::UNDEF && Opc != ISD::Constant && Opc != ISD::ConstantFP)
      return false;
  }
  return true;
}

bool ShuffleVectorSDNode::isSplatMask(const int *Mask, EVT VT) {
  // Find the first non-undef value in the shuffle mask.
  unsigned i, e;
  for (i = 0, e = VT.getVectorNumElements(); 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 the SDNode if it is a constant integer BuildVector
// or constant integer.
SDNode *SelectionDAG::isConstantIntBuildVectorOrConstantInt(SDValue N) {
  if (isa<ConstantSDNode>(N))
    return N.getNode();
  if (ISD::isBuildVectorOfConstantSDNodes(N.getNode()))
    return N.getNode();
  // Treat a GlobalAddress supporting constant offset folding as a
  // constant integer.
  if (GlobalAddressSDNode *GA = dyn_cast<GlobalAddressSDNode>(N))
    if (GA->getOpcode() == ISD::GlobalAddress &&
        TLI->isOffsetFoldingLegal(GA))
      return GA;
  return nullptr;
}

SDNode *SelectionDAG::isConstantFPBuildVectorOrConstantFP(SDValue N) {
  if (isa<ConstantFPSDNode>(N))
    return N.getNode();

  if (ISD::isBuildVectorOfConstantFPSDNodes(N.getNode()))
    return N.getNode();

  return nullptr;
}

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]);
    if (Ops[I].Val.getValueType() != MVT::Other) // Skip Chain. It does not carry divergence.
      IsDivergent = IsDivergent || Ops[I].getNode()->isDivergent();
  }
  Node->NumOperands = Vals.size();
  Node->OperandList = Ops;
  IsDivergent |= TLI->isSDNodeSourceOfDivergence(Node, FLI, DA);
  if (!TLI->isSDNodeAlwaysUniform(Node))
    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);
}

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