//===------- LegalizeVectorTypes.cpp - Legalization of vector types -------===//
//
// 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 file performs vector type splitting and scalarization for LegalizeTypes.
// Scalarization is the act of changing a computation in an illegal one-element
// vector type to be a computation in its scalar element type.  For example,
// implementing <1 x f32> arithmetic in a scalar f32 register.  This is needed
// as a base case when scalarizing vector arithmetic like <4 x f32>, which
// eventually decomposes to scalars if the target doesn't support v4f32 or v2f32
// types.
// Splitting is the act of changing a computation in an invalid vector type to
// be a computation in two vectors of half the size.  For example, implementing
// <128 x f32> operations in terms of two <64 x f32> operations.
//
//===----------------------------------------------------------------------===//

#include "LegalizeTypes.h"
#include "llvm/Analysis/MemoryLocation.h"
#include "llvm/IR/DataLayout.h"
#include "llvm/Support/ErrorHandling.h"
#include "llvm/Support/TypeSize.h"
#include "llvm/Support/raw_ostream.h"
using namespace llvm;

#define DEBUG_TYPE "legalize-types"

//===----------------------------------------------------------------------===//
//  Result Vector Scalarization: <1 x ty> -> ty.
//===----------------------------------------------------------------------===//

void DAGTypeLegalizer::ScalarizeVectorResult(SDNode *N, unsigned ResNo) {
  LLVM_DEBUG(dbgs() << "Scalarize node result " << ResNo << ": "; N->dump(&DAG);
             dbgs() << "\n");
  SDValue R = SDValue();

  switch (N->getOpcode()) {
  default:
#ifndef NDEBUG
    dbgs() << "ScalarizeVectorResult #" << ResNo << ": ";
    N->dump(&DAG);
    dbgs() << "\n";
#endif
    report_fatal_error("Do not know how to scalarize the result of this "
                       "operator!\n");

  case ISD::MERGE_VALUES:      R = ScalarizeVecRes_MERGE_VALUES(N, ResNo);break;
  case ISD::BITCAST:           R = ScalarizeVecRes_BITCAST(N); break;
  case ISD::BUILD_VECTOR:      R = ScalarizeVecRes_BUILD_VECTOR(N); break;
  case ISD::EXTRACT_SUBVECTOR: R = ScalarizeVecRes_EXTRACT_SUBVECTOR(N); break;
  case ISD::FP_ROUND:          R = ScalarizeVecRes_FP_ROUND(N); break;
  case ISD::FPOWI:             R = ScalarizeVecRes_FPOWI(N); break;
  case ISD::INSERT_VECTOR_ELT: R = ScalarizeVecRes_INSERT_VECTOR_ELT(N); break;
  case ISD::LOAD:           R = ScalarizeVecRes_LOAD(cast<LoadSDNode>(N));break;
  case ISD::SCALAR_TO_VECTOR:  R = ScalarizeVecRes_SCALAR_TO_VECTOR(N); break;
  case ISD::SIGN_EXTEND_INREG: R = ScalarizeVecRes_InregOp(N); break;
  case ISD::VSELECT:           R = ScalarizeVecRes_VSELECT(N); break;
  case ISD::SELECT:            R = ScalarizeVecRes_SELECT(N); break;
  case ISD::SELECT_CC:         R = ScalarizeVecRes_SELECT_CC(N); break;
  case ISD::SETCC:             R = ScalarizeVecRes_SETCC(N); break;
  case ISD::UNDEF:             R = ScalarizeVecRes_UNDEF(N); break;
  case ISD::VECTOR_SHUFFLE:    R = ScalarizeVecRes_VECTOR_SHUFFLE(N); break;
  case ISD::ANY_EXTEND_VECTOR_INREG:
  case ISD::SIGN_EXTEND_VECTOR_INREG:
  case ISD::ZERO_EXTEND_VECTOR_INREG:
    R = ScalarizeVecRes_VecInregOp(N);
    break;
  case ISD::ABS:
  case ISD::ANY_EXTEND:
  case ISD::BITREVERSE:
  case ISD::BSWAP:
  case ISD::CTLZ:
  case ISD::CTLZ_ZERO_UNDEF:
  case ISD::CTPOP:
  case ISD::CTTZ:
  case ISD::CTTZ_ZERO_UNDEF:
  case ISD::FABS:
  case ISD::FCEIL:
  case ISD::FCOS:
  case ISD::FEXP:
  case ISD::FEXP2:
  case ISD::FFLOOR:
  case ISD::FLOG:
  case ISD::FLOG10:
  case ISD::FLOG2:
  case ISD::FNEARBYINT:
  case ISD::FNEG:
  case ISD::FREEZE:
  case ISD::ARITH_FENCE:
  case ISD::FP_EXTEND:
  case ISD::FP_TO_SINT:
  case ISD::FP_TO_UINT:
  case ISD::FRINT:
  case ISD::FROUND:
  case ISD::FROUNDEVEN:
  case ISD::FSIN:
  case ISD::FSQRT:
  case ISD::FTRUNC:
  case ISD::SIGN_EXTEND:
  case ISD::SINT_TO_FP:
  case ISD::TRUNCATE:
  case ISD::UINT_TO_FP:
  case ISD::ZERO_EXTEND:
  case ISD::FCANONICALIZE:
    R = ScalarizeVecRes_UnaryOp(N);
    break;

  case ISD::ADD:
  case ISD::AND:
  case ISD::FADD:
  case ISD::FCOPYSIGN:
  case ISD::FDIV:
  case ISD::FMUL:
  case ISD::FMINNUM:
  case ISD::FMAXNUM:
  case ISD::FMINNUM_IEEE:
  case ISD::FMAXNUM_IEEE:
  case ISD::FMINIMUM:
  case ISD::FMAXIMUM:
  case ISD::SMIN:
  case ISD::SMAX:
  case ISD::UMIN:
  case ISD::UMAX:

  case ISD::SADDSAT:
  case ISD::UADDSAT:
  case ISD::SSUBSAT:
  case ISD::USUBSAT:
  case ISD::SSHLSAT:
  case ISD::USHLSAT:

  case ISD::FPOW:
  case ISD::FREM:
  case ISD::FSUB:
  case ISD::MUL:
  case ISD::OR:
  case ISD::SDIV:
  case ISD::SREM:
  case ISD::SUB:
  case ISD::UDIV:
  case ISD::UREM:
  case ISD::XOR:
  case ISD::SHL:
  case ISD::SRA:
  case ISD::SRL:
  case ISD::ROTL:
  case ISD::ROTR:
    R = ScalarizeVecRes_BinOp(N);
    break;
  case ISD::FMA:
  case ISD::FSHL:
  case ISD::FSHR:
    R = ScalarizeVecRes_TernaryOp(N);
    break;

#define DAG_INSTRUCTION(NAME, NARG, ROUND_MODE, INTRINSIC, DAGN)               \
  case ISD::STRICT_##DAGN:
#include "llvm/IR/ConstrainedOps.def"
    R = ScalarizeVecRes_StrictFPOp(N);
    break;

  case ISD::FP_TO_UINT_SAT:
  case ISD::FP_TO_SINT_SAT:
    R = ScalarizeVecRes_FP_TO_XINT_SAT(N);
    break;

  case ISD::UADDO:
  case ISD::SADDO:
  case ISD::USUBO:
  case ISD::SSUBO:
  case ISD::UMULO:
  case ISD::SMULO:
    R = ScalarizeVecRes_OverflowOp(N, ResNo);
    break;
  case ISD::SMULFIX:
  case ISD::SMULFIXSAT:
  case ISD::UMULFIX:
  case ISD::UMULFIXSAT:
  case ISD::SDIVFIX:
  case ISD::SDIVFIXSAT:
  case ISD::UDIVFIX:
  case ISD::UDIVFIXSAT:
    R = ScalarizeVecRes_FIX(N);
    break;
  }

  // If R is null, the sub-method took care of registering the result.
  if (R.getNode())
    SetScalarizedVector(SDValue(N, ResNo), R);
}

SDValue DAGTypeLegalizer::ScalarizeVecRes_BinOp(SDNode *N) {
  SDValue LHS = GetScalarizedVector(N->getOperand(0));
  SDValue RHS = GetScalarizedVector(N->getOperand(1));
  return DAG.getNode(N->getOpcode(), SDLoc(N),
                     LHS.getValueType(), LHS, RHS, N->getFlags());
}

SDValue DAGTypeLegalizer::ScalarizeVecRes_TernaryOp(SDNode *N) {
  SDValue Op0 = GetScalarizedVector(N->getOperand(0));
  SDValue Op1 = GetScalarizedVector(N->getOperand(1));
  SDValue Op2 = GetScalarizedVector(N->getOperand(2));
  return DAG.getNode(N->getOpcode(), SDLoc(N), Op0.getValueType(), Op0, Op1,
                     Op2, N->getFlags());
}

SDValue DAGTypeLegalizer::ScalarizeVecRes_FIX(SDNode *N) {
  SDValue Op0 = GetScalarizedVector(N->getOperand(0));
  SDValue Op1 = GetScalarizedVector(N->getOperand(1));
  SDValue Op2 = N->getOperand(2);
  return DAG.getNode(N->getOpcode(), SDLoc(N), Op0.getValueType(), Op0, Op1,
                     Op2, N->getFlags());
}

SDValue DAGTypeLegalizer::ScalarizeVecRes_StrictFPOp(SDNode *N) {
  EVT VT = N->getValueType(0).getVectorElementType();
  unsigned NumOpers = N->getNumOperands();
  SDValue Chain = N->getOperand(0);
  EVT ValueVTs[] = {VT, MVT::Other};
  SDLoc dl(N);

  SmallVector<SDValue, 4> Opers(NumOpers);

  // The Chain is the first operand.
  Opers[0] = Chain;

  // Now process the remaining operands.
  for (unsigned i = 1; i < NumOpers; ++i) {
    SDValue Oper = N->getOperand(i);

    if (Oper.getValueType().isVector())
      Oper = GetScalarizedVector(Oper);

    Opers[i] = Oper;
  }

  SDValue Result = DAG.getNode(N->getOpcode(), dl, DAG.getVTList(ValueVTs),
                               Opers, N->getFlags());

  // Legalize the chain result - switch anything that used the old chain to
  // use the new one.
  ReplaceValueWith(SDValue(N, 1), Result.getValue(1));
  return Result;
}

SDValue DAGTypeLegalizer::ScalarizeVecRes_OverflowOp(SDNode *N,
                                                     unsigned ResNo) {
  SDLoc DL(N);
  EVT ResVT = N->getValueType(0);
  EVT OvVT = N->getValueType(1);

  SDValue ScalarLHS, ScalarRHS;
  if (getTypeAction(ResVT) == TargetLowering::TypeScalarizeVector) {
    ScalarLHS = GetScalarizedVector(N->getOperand(0));
    ScalarRHS = GetScalarizedVector(N->getOperand(1));
  } else {
    SmallVector<SDValue, 1> ElemsLHS, ElemsRHS;
    DAG.ExtractVectorElements(N->getOperand(0), ElemsLHS);
    DAG.ExtractVectorElements(N->getOperand(1), ElemsRHS);
    ScalarLHS = ElemsLHS[0];
    ScalarRHS = ElemsRHS[0];
  }

  SDVTList ScalarVTs = DAG.getVTList(
      ResVT.getVectorElementType(), OvVT.getVectorElementType());
  SDNode *ScalarNode = DAG.getNode(
      N->getOpcode(), DL, ScalarVTs, ScalarLHS, ScalarRHS).getNode();
  ScalarNode->setFlags(N->getFlags());

  // Replace the other vector result not being explicitly scalarized here.
  unsigned OtherNo = 1 - ResNo;
  EVT OtherVT = N->getValueType(OtherNo);
  if (getTypeAction(OtherVT) == TargetLowering::TypeScalarizeVector) {
    SetScalarizedVector(SDValue(N, OtherNo), SDValue(ScalarNode, OtherNo));
  } else {
    SDValue OtherVal = DAG.getNode(
        ISD::SCALAR_TO_VECTOR, DL, OtherVT, SDValue(ScalarNode, OtherNo));
    ReplaceValueWith(SDValue(N, OtherNo), OtherVal);
  }

  return SDValue(ScalarNode, ResNo);
}

SDValue DAGTypeLegalizer::ScalarizeVecRes_MERGE_VALUES(SDNode *N,
                                                       unsigned ResNo) {
  SDValue Op = DisintegrateMERGE_VALUES(N, ResNo);
  return GetScalarizedVector(Op);
}

SDValue DAGTypeLegalizer::ScalarizeVecRes_BITCAST(SDNode *N) {
  SDValue Op = N->getOperand(0);
  if (Op.getValueType().isVector()
      && Op.getValueType().getVectorNumElements() == 1
      && !isSimpleLegalType(Op.getValueType()))
    Op = GetScalarizedVector(Op);
  EVT NewVT = N->getValueType(0).getVectorElementType();
  return DAG.getNode(ISD::BITCAST, SDLoc(N),
                     NewVT, Op);
}

SDValue DAGTypeLegalizer::ScalarizeVecRes_BUILD_VECTOR(SDNode *N) {
  EVT EltVT = N->getValueType(0).getVectorElementType();
  SDValue InOp = N->getOperand(0);
  // The BUILD_VECTOR operands may be of wider element types and
  // we may need to truncate them back to the requested return type.
  if (EltVT.isInteger())
    return DAG.getNode(ISD::TRUNCATE, SDLoc(N), EltVT, InOp);
  return InOp;
}

SDValue DAGTypeLegalizer::ScalarizeVecRes_EXTRACT_SUBVECTOR(SDNode *N) {
  return DAG.getNode(ISD::EXTRACT_VECTOR_ELT, SDLoc(N),
                     N->getValueType(0).getVectorElementType(),
                     N->getOperand(0), N->getOperand(1));
}

SDValue DAGTypeLegalizer::ScalarizeVecRes_FP_ROUND(SDNode *N) {
  SDLoc DL(N);
  SDValue Op = N->getOperand(0);
  EVT OpVT = Op.getValueType();
  // The result needs scalarizing, but it's not a given that the source does.
  // See similar logic in ScalarizeVecRes_UnaryOp.
  if (getTypeAction(OpVT) == TargetLowering::TypeScalarizeVector) {
    Op = GetScalarizedVector(Op);
  } else {
    EVT VT = OpVT.getVectorElementType();
    Op = DAG.getNode(ISD::EXTRACT_VECTOR_ELT, DL, VT, Op,
                     DAG.getVectorIdxConstant(0, DL));
  }
  return DAG.getNode(ISD::FP_ROUND, DL,
                     N->getValueType(0).getVectorElementType(), Op,
                     N->getOperand(1));
}

SDValue DAGTypeLegalizer::ScalarizeVecRes_FPOWI(SDNode *N) {
  SDValue Op = GetScalarizedVector(N->getOperand(0));
  return DAG.getNode(ISD::FPOWI, SDLoc(N),
                     Op.getValueType(), Op, N->getOperand(1));
}

SDValue DAGTypeLegalizer::ScalarizeVecRes_INSERT_VECTOR_ELT(SDNode *N) {
  // The value to insert may have a wider type than the vector element type,
  // so be sure to truncate it to the element type if necessary.
  SDValue Op = N->getOperand(1);
  EVT EltVT = N->getValueType(0).getVectorElementType();
  if (Op.getValueType() != EltVT)
    // FIXME: Can this happen for floating point types?
    Op = DAG.getNode(ISD::TRUNCATE, SDLoc(N), EltVT, Op);
  return Op;
}

SDValue DAGTypeLegalizer::ScalarizeVecRes_LOAD(LoadSDNode *N) {
  assert(N->isUnindexed() && "Indexed vector load?");

  SDValue Result = DAG.getLoad(
      ISD::UNINDEXED, N->getExtensionType(),
      N->getValueType(0).getVectorElementType(), SDLoc(N), N->getChain(),
      N->getBasePtr(), DAG.getUNDEF(N->getBasePtr().getValueType()),
      N->getPointerInfo(), N->getMemoryVT().getVectorElementType(),
      N->getOriginalAlign(), N->getMemOperand()->getFlags(), N->getAAInfo());

  // Legalize the chain result - switch anything that used the old chain to
  // use the new one.
  ReplaceValueWith(SDValue(N, 1), Result.getValue(1));
  return Result;
}

SDValue DAGTypeLegalizer::ScalarizeVecRes_UnaryOp(SDNode *N) {
  // Get the dest type - it doesn't always match the input type, e.g. int_to_fp.
  EVT DestVT = N->getValueType(0).getVectorElementType();
  SDValue Op = N->getOperand(0);
  EVT OpVT = Op.getValueType();
  SDLoc DL(N);
  // The result needs scalarizing, but it's not a given that the source does.
  // This is a workaround for targets where it's impossible to scalarize the
  // result of a conversion, because the source type is legal.
  // For instance, this happens on AArch64: v1i1 is illegal but v1i{8,16,32}
  // are widened to v8i8, v4i16, and v2i32, which is legal, because v1i64 is
  // legal and was not scalarized.
  // See the similar logic in ScalarizeVecRes_SETCC
  if (getTypeAction(OpVT) == TargetLowering::TypeScalarizeVector) {
    Op = GetScalarizedVector(Op);
  } else {
    EVT VT = OpVT.getVectorElementType();
    Op = DAG.getNode(ISD::EXTRACT_VECTOR_ELT, DL, VT, Op,
                     DAG.getVectorIdxConstant(0, DL));
  }
  return DAG.getNode(N->getOpcode(), SDLoc(N), DestVT, Op, N->getFlags());
}

SDValue DAGTypeLegalizer::ScalarizeVecRes_InregOp(SDNode *N) {
  EVT EltVT = N->getValueType(0).getVectorElementType();
  EVT ExtVT = cast<VTSDNode>(N->getOperand(1))->getVT().getVectorElementType();
  SDValue LHS = GetScalarizedVector(N->getOperand(0));
  return DAG.getNode(N->getOpcode(), SDLoc(N), EltVT,
                     LHS, DAG.getValueType(ExtVT));
}

SDValue DAGTypeLegalizer::ScalarizeVecRes_VecInregOp(SDNode *N) {
  SDLoc DL(N);
  SDValue Op = N->getOperand(0);

  EVT OpVT = Op.getValueType();
  EVT OpEltVT = OpVT.getVectorElementType();
  EVT EltVT = N->getValueType(0).getVectorElementType();

  if (getTypeAction(OpVT) == TargetLowering::TypeScalarizeVector) {
    Op = GetScalarizedVector(Op);
  } else {
    Op = DAG.getNode(ISD::EXTRACT_VECTOR_ELT, DL, OpEltVT, Op,
                     DAG.getVectorIdxConstant(0, DL));
  }

  switch (N->getOpcode()) {
  case ISD::ANY_EXTEND_VECTOR_INREG:
    return DAG.getNode(ISD::ANY_EXTEND, DL, EltVT, Op);
  case ISD::SIGN_EXTEND_VECTOR_INREG:
    return DAG.getNode(ISD::SIGN_EXTEND, DL, EltVT, Op);
  case ISD::ZERO_EXTEND_VECTOR_INREG:
    return DAG.getNode(ISD::ZERO_EXTEND, DL, EltVT, Op);
  }

  llvm_unreachable("Illegal extend_vector_inreg opcode");
}

SDValue DAGTypeLegalizer::ScalarizeVecRes_SCALAR_TO_VECTOR(SDNode *N) {
  // If the operand is wider than the vector element type then it is implicitly
  // truncated.  Make that explicit here.
  EVT EltVT = N->getValueType(0).getVectorElementType();
  SDValue InOp = N->getOperand(0);
  if (InOp.getValueType() != EltVT)
    return DAG.getNode(ISD::TRUNCATE, SDLoc(N), EltVT, InOp);
  return InOp;
}

SDValue DAGTypeLegalizer::ScalarizeVecRes_VSELECT(SDNode *N) {
  SDValue Cond = N->getOperand(0);
  EVT OpVT = Cond.getValueType();
  SDLoc DL(N);
  // The vselect result and true/value operands needs scalarizing, but it's
  // not a given that the Cond does. For instance, in AVX512 v1i1 is legal.
  // See the similar logic in ScalarizeVecRes_SETCC
  if (getTypeAction(OpVT) == TargetLowering::TypeScalarizeVector) {
    Cond = GetScalarizedVector(Cond);
  } else {
    EVT VT = OpVT.getVectorElementType();
    Cond = DAG.getNode(ISD::EXTRACT_VECTOR_ELT, DL, VT, Cond,
                       DAG.getVectorIdxConstant(0, DL));
  }

  SDValue LHS = GetScalarizedVector(N->getOperand(1));
  TargetLowering::BooleanContent ScalarBool =
      TLI.getBooleanContents(false, false);
  TargetLowering::BooleanContent VecBool = TLI.getBooleanContents(true, false);

  // If integer and float booleans have different contents then we can't
  // reliably optimize in all cases. There is a full explanation for this in
  // DAGCombiner::visitSELECT() where the same issue affects folding
  // (select C, 0, 1) to (xor C, 1).
  if (TLI.getBooleanContents(false, false) !=
      TLI.getBooleanContents(false, true)) {
    // At least try the common case where the boolean is generated by a
    // comparison.
    if (Cond->getOpcode() == ISD::SETCC) {
      EVT OpVT = Cond->getOperand(0).getValueType();
      ScalarBool = TLI.getBooleanContents(OpVT.getScalarType());
      VecBool = TLI.getBooleanContents(OpVT);
    } else
      ScalarBool = TargetLowering::UndefinedBooleanContent;
  }

  EVT CondVT = Cond.getValueType();
  if (ScalarBool != VecBool) {
    switch (ScalarBool) {
      case TargetLowering::UndefinedBooleanContent:
        break;
      case TargetLowering::ZeroOrOneBooleanContent:
        assert(VecBool == TargetLowering::UndefinedBooleanContent ||
               VecBool == TargetLowering::ZeroOrNegativeOneBooleanContent);
        // Vector read from all ones, scalar expects a single 1 so mask.
        Cond = DAG.getNode(ISD::AND, SDLoc(N), CondVT,
                           Cond, DAG.getConstant(1, SDLoc(N), CondVT));
        break;
      case TargetLowering::ZeroOrNegativeOneBooleanContent:
        assert(VecBool == TargetLowering::UndefinedBooleanContent ||
               VecBool == TargetLowering::ZeroOrOneBooleanContent);
        // Vector reads from a one, scalar from all ones so sign extend.
        Cond = DAG.getNode(ISD::SIGN_EXTEND_INREG, SDLoc(N), CondVT,
                           Cond, DAG.getValueType(MVT::i1));
        break;
    }
  }

  // Truncate the condition if needed
  auto BoolVT = getSetCCResultType(CondVT);
  if (BoolVT.bitsLT(CondVT))
    Cond = DAG.getNode(ISD::TRUNCATE, SDLoc(N), BoolVT, Cond);

  return DAG.getSelect(SDLoc(N),
                       LHS.getValueType(), Cond, LHS,
                       GetScalarizedVector(N->getOperand(2)));
}

SDValue DAGTypeLegalizer::ScalarizeVecRes_SELECT(SDNode *N) {
  SDValue LHS = GetScalarizedVector(N->getOperand(1));
  return DAG.getSelect(SDLoc(N),
                       LHS.getValueType(), N->getOperand(0), LHS,
                       GetScalarizedVector(N->getOperand(2)));
}

SDValue DAGTypeLegalizer::ScalarizeVecRes_SELECT_CC(SDNode *N) {
  SDValue LHS = GetScalarizedVector(N->getOperand(2));
  return DAG.getNode(ISD::SELECT_CC, SDLoc(N), LHS.getValueType(),
                     N->getOperand(0), N->getOperand(1),
                     LHS, GetScalarizedVector(N->getOperand(3)),
                     N->getOperand(4));
}

SDValue DAGTypeLegalizer::ScalarizeVecRes_UNDEF(SDNode *N) {
  return DAG.getUNDEF(N->getValueType(0).getVectorElementType());
}

SDValue DAGTypeLegalizer::ScalarizeVecRes_VECTOR_SHUFFLE(SDNode *N) {
  // Figure out if the scalar is the LHS or RHS and return it.
  SDValue Arg = N->getOperand(2).getOperand(0);
  if (Arg.isUndef())
    return DAG.getUNDEF(N->getValueType(0).getVectorElementType());
  unsigned Op = !cast<ConstantSDNode>(Arg)->isZero();
  return GetScalarizedVector(N->getOperand(Op));
}

SDValue DAGTypeLegalizer::ScalarizeVecRes_FP_TO_XINT_SAT(SDNode *N) {
  SDValue Src = N->getOperand(0);
  EVT SrcVT = Src.getValueType();
  SDLoc dl(N);

  // Handle case where result is scalarized but operand is not
  if (getTypeAction(SrcVT) == TargetLowering::TypeScalarizeVector)
    Src = GetScalarizedVector(Src);
  else
    Src = DAG.getNode(
        ISD::EXTRACT_VECTOR_ELT, dl, SrcVT.getVectorElementType(), Src,
        DAG.getConstant(0, dl, TLI.getVectorIdxTy(DAG.getDataLayout())));

  EVT DstVT = N->getValueType(0).getVectorElementType();
  return DAG.getNode(N->getOpcode(), dl, DstVT, Src, N->getOperand(1));
}

SDValue DAGTypeLegalizer::ScalarizeVecRes_SETCC(SDNode *N) {
  assert(N->getValueType(0).isVector() &&
         N->getOperand(0).getValueType().isVector() &&
         "Operand types must be vectors");
  SDValue LHS = N->getOperand(0);
  SDValue RHS = N->getOperand(1);
  EVT OpVT = LHS.getValueType();
  EVT NVT = N->getValueType(0).getVectorElementType();
  SDLoc DL(N);

  // The result needs scalarizing, but it's not a given that the source does.
  if (getTypeAction(OpVT) == TargetLowering::TypeScalarizeVector) {
    LHS = GetScalarizedVector(LHS);
    RHS = GetScalarizedVector(RHS);
  } else {
    EVT VT = OpVT.getVectorElementType();
    LHS = DAG.getNode(ISD::EXTRACT_VECTOR_ELT, DL, VT, LHS,
                      DAG.getVectorIdxConstant(0, DL));
    RHS = DAG.getNode(ISD::EXTRACT_VECTOR_ELT, DL, VT, RHS,
                      DAG.getVectorIdxConstant(0, DL));
  }

  // Turn it into a scalar SETCC.
  SDValue Res = DAG.getNode(ISD::SETCC, DL, MVT::i1, LHS, RHS,
                            N->getOperand(2));
  // Vectors may have a different boolean contents to scalars.  Promote the
  // value appropriately.
  ISD::NodeType ExtendCode =
      TargetLowering::getExtendForContent(TLI.getBooleanContents(OpVT));
  return DAG.getNode(ExtendCode, DL, NVT, Res);
}


//===----------------------------------------------------------------------===//
//  Operand Vector Scalarization <1 x ty> -> ty.
//===----------------------------------------------------------------------===//

bool DAGTypeLegalizer::ScalarizeVectorOperand(SDNode *N, unsigned OpNo) {
  LLVM_DEBUG(dbgs() << "Scalarize node operand " << OpNo << ": "; N->dump(&DAG);
             dbgs() << "\n");
  SDValue Res = SDValue();

  switch (N->getOpcode()) {
  default:
#ifndef NDEBUG
    dbgs() << "ScalarizeVectorOperand Op #" << OpNo << ": ";
    N->dump(&DAG);
    dbgs() << "\n";
#endif
    report_fatal_error("Do not know how to scalarize this operator's "
                       "operand!\n");
  case ISD::BITCAST:
    Res = ScalarizeVecOp_BITCAST(N);
    break;
  case ISD::ANY_EXTEND:
  case ISD::ZERO_EXTEND:
  case ISD::SIGN_EXTEND:
  case ISD::TRUNCATE:
  case ISD::FP_TO_SINT:
  case ISD::FP_TO_UINT:
  case ISD::SINT_TO_FP:
  case ISD::UINT_TO_FP:
    Res = ScalarizeVecOp_UnaryOp(N);
    break;
  case ISD::STRICT_SINT_TO_FP:
  case ISD::STRICT_UINT_TO_FP:
  case ISD::STRICT_FP_TO_SINT:
  case ISD::STRICT_FP_TO_UINT:
    Res = ScalarizeVecOp_UnaryOp_StrictFP(N);
    break;
  case ISD::CONCAT_VECTORS:
    Res = ScalarizeVecOp_CONCAT_VECTORS(N);
    break;
  case ISD::EXTRACT_VECTOR_ELT:
    Res = ScalarizeVecOp_EXTRACT_VECTOR_ELT(N);
    break;
  case ISD::VSELECT:
    Res = ScalarizeVecOp_VSELECT(N);
    break;
  case ISD::SETCC:
    Res = ScalarizeVecOp_VSETCC(N);
    break;
  case ISD::STORE:
    Res = ScalarizeVecOp_STORE(cast<StoreSDNode>(N), OpNo);
    break;
  case ISD::STRICT_FP_ROUND:
    Res = ScalarizeVecOp_STRICT_FP_ROUND(N, OpNo);
    break;
  case ISD::FP_ROUND:
    Res = ScalarizeVecOp_FP_ROUND(N, OpNo);
    break;
  case ISD::STRICT_FP_EXTEND:
    Res = ScalarizeVecOp_STRICT_FP_EXTEND(N);
    break;
  case ISD::FP_EXTEND:
    Res = ScalarizeVecOp_FP_EXTEND(N);
    break;
  case ISD::VECREDUCE_FADD:
  case ISD::VECREDUCE_FMUL:
  case ISD::VECREDUCE_ADD:
  case ISD::VECREDUCE_MUL:
  case ISD::VECREDUCE_AND:
  case ISD::VECREDUCE_OR:
  case ISD::VECREDUCE_XOR:
  case ISD::VECREDUCE_SMAX:
  case ISD::VECREDUCE_SMIN:
  case ISD::VECREDUCE_UMAX:
  case ISD::VECREDUCE_UMIN:
  case ISD::VECREDUCE_FMAX:
  case ISD::VECREDUCE_FMIN:
    Res = ScalarizeVecOp_VECREDUCE(N);
    break;
  case ISD::VECREDUCE_SEQ_FADD:
  case ISD::VECREDUCE_SEQ_FMUL:
    Res = ScalarizeVecOp_VECREDUCE_SEQ(N);
    break;
  }

  // If the result is null, the sub-method took care of registering results etc.
  if (!Res.getNode()) return false;

  // If the result is N, the sub-method updated N in place.  Tell the legalizer
  // core about this.
  if (Res.getNode() == N)
    return true;

  assert(Res.getValueType() == N->getValueType(0) && N->getNumValues() == 1 &&
         "Invalid operand expansion");

  ReplaceValueWith(SDValue(N, 0), Res);
  return false;
}

/// If the value to convert is a vector that needs to be scalarized, it must be
/// <1 x ty>. Convert the element instead.
SDValue DAGTypeLegalizer::ScalarizeVecOp_BITCAST(SDNode *N) {
  SDValue Elt = GetScalarizedVector(N->getOperand(0));
  return DAG.getNode(ISD::BITCAST, SDLoc(N),
                     N->getValueType(0), Elt);
}

/// If the input is a vector that needs to be scalarized, it must be <1 x ty>.
/// Do the operation on the element instead.
SDValue DAGTypeLegalizer::ScalarizeVecOp_UnaryOp(SDNode *N) {
  assert(N->getValueType(0).getVectorNumElements() == 1 &&
         "Unexpected vector type!");
  SDValue Elt = GetScalarizedVector(N->getOperand(0));
  SDValue Op = DAG.getNode(N->getOpcode(), SDLoc(N),
                           N->getValueType(0).getScalarType(), Elt);
  // Revectorize the result so the types line up with what the uses of this
  // expression expect.
  return DAG.getNode(ISD::SCALAR_TO_VECTOR, SDLoc(N), N->getValueType(0), Op);
}

/// If the input is a vector that needs to be scalarized, it must be <1 x ty>.
/// Do the strict FP operation on the element instead.
SDValue DAGTypeLegalizer::ScalarizeVecOp_UnaryOp_StrictFP(SDNode *N) {
  assert(N->getValueType(0).getVectorNumElements() == 1 &&
         "Unexpected vector type!");
  SDValue Elt = GetScalarizedVector(N->getOperand(1));
  SDValue Res = DAG.getNode(N->getOpcode(), SDLoc(N),
                            { N->getValueType(0).getScalarType(), MVT::Other },
                            { N->getOperand(0), Elt });
  // Legalize the chain result - switch anything that used the old chain to
  // use the new one.
  ReplaceValueWith(SDValue(N, 1), Res.getValue(1));
  // Revectorize the result so the types line up with what the uses of this
  // expression expect.
  Res = DAG.getNode(ISD::SCALAR_TO_VECTOR, SDLoc(N), N->getValueType(0), Res);

  // Do our own replacement and return SDValue() to tell the caller that we
  // handled all replacements since caller can only handle a single result.
  ReplaceValueWith(SDValue(N, 0), Res);
  return SDValue();
}

/// The vectors to concatenate have length one - use a BUILD_VECTOR instead.
SDValue DAGTypeLegalizer::ScalarizeVecOp_CONCAT_VECTORS(SDNode *N) {
  SmallVector<SDValue, 8> Ops(N->getNumOperands());
  for (unsigned i = 0, e = N->getNumOperands(); i < e; ++i)
    Ops[i] = GetScalarizedVector(N->getOperand(i));
  return DAG.getBuildVector(N->getValueType(0), SDLoc(N), Ops);
}

/// If the input is a vector that needs to be scalarized, it must be <1 x ty>,
/// so just return the element, ignoring the index.
SDValue DAGTypeLegalizer::ScalarizeVecOp_EXTRACT_VECTOR_ELT(SDNode *N) {
  EVT VT = N->getValueType(0);
  SDValue Res = GetScalarizedVector(N->getOperand(0));
  if (Res.getValueType() != VT)
    Res = VT.isFloatingPoint()
              ? DAG.getNode(ISD::FP_EXTEND, SDLoc(N), VT, Res)
              : DAG.getNode(ISD::ANY_EXTEND, SDLoc(N), VT, Res);
  return Res;
}

/// If the input condition is a vector that needs to be scalarized, it must be
/// <1 x i1>, so just convert to a normal ISD::SELECT
/// (still with vector output type since that was acceptable if we got here).
SDValue DAGTypeLegalizer::ScalarizeVecOp_VSELECT(SDNode *N) {
  SDValue ScalarCond = GetScalarizedVector(N->getOperand(0));
  EVT VT = N->getValueType(0);

  return DAG.getNode(ISD::SELECT, SDLoc(N), VT, ScalarCond, N->getOperand(1),
                     N->getOperand(2));
}

/// If the operand is a vector that needs to be scalarized then the
/// result must be v1i1, so just convert to a scalar SETCC and wrap
/// with a scalar_to_vector since the res type is legal if we got here
SDValue DAGTypeLegalizer::ScalarizeVecOp_VSETCC(SDNode *N) {
  assert(N->getValueType(0).isVector() &&
         N->getOperand(0).getValueType().isVector() &&
         "Operand types must be vectors");
  assert(N->getValueType(0) == MVT::v1i1 && "Expected v1i1 type");

  EVT VT = N->getValueType(0);
  SDValue LHS = GetScalarizedVector(N->getOperand(0));
  SDValue RHS = GetScalarizedVector(N->getOperand(1));

  EVT OpVT = N->getOperand(0).getValueType();
  EVT NVT = VT.getVectorElementType();
  SDLoc DL(N);
  // Turn it into a scalar SETCC.
  SDValue Res = DAG.getNode(ISD::SETCC, DL, MVT::i1, LHS, RHS,
      N->getOperand(2));

  // Vectors may have a different boolean contents to scalars.  Promote the
  // value appropriately.
  ISD::NodeType ExtendCode =
      TargetLowering::getExtendForContent(TLI.getBooleanContents(OpVT));

  Res = DAG.getNode(ExtendCode, DL, NVT, Res);

  return DAG.getNode(ISD::SCALAR_TO_VECTOR, DL, VT, Res);
}

/// If the value to store is a vector that needs to be scalarized, it must be
/// <1 x ty>. Just store the element.
SDValue DAGTypeLegalizer::ScalarizeVecOp_STORE(StoreSDNode *N, unsigned OpNo){
  assert(N->isUnindexed() && "Indexed store of one-element vector?");
  assert(OpNo == 1 && "Do not know how to scalarize this operand!");
  SDLoc dl(N);

  if (N->isTruncatingStore())
    return DAG.getTruncStore(
        N->getChain(), dl, GetScalarizedVector(N->getOperand(1)),
        N->getBasePtr(), N->getPointerInfo(),
        N->getMemoryVT().getVectorElementType(), N->getOriginalAlign(),
        N->getMemOperand()->getFlags(), N->getAAInfo());

  return DAG.getStore(N->getChain(), dl, GetScalarizedVector(N->getOperand(1)),
                      N->getBasePtr(), N->getPointerInfo(),
                      N->getOriginalAlign(), N->getMemOperand()->getFlags(),
                      N->getAAInfo());
}

/// If the value to round is a vector that needs to be scalarized, it must be
/// <1 x ty>. Convert the element instead.
SDValue DAGTypeLegalizer::ScalarizeVecOp_FP_ROUND(SDNode *N, unsigned OpNo) {
  assert(OpNo == 0 && "Wrong operand for scalarization!");
  SDValue Elt = GetScalarizedVector(N->getOperand(0));
  SDValue Res = DAG.getNode(ISD::FP_ROUND, SDLoc(N),
                            N->getValueType(0).getVectorElementType(), Elt,
                            N->getOperand(1));
  return DAG.getNode(ISD::SCALAR_TO_VECTOR, SDLoc(N), N->getValueType(0), Res);
}

SDValue DAGTypeLegalizer::ScalarizeVecOp_STRICT_FP_ROUND(SDNode *N, 
                                                         unsigned OpNo) {
  assert(OpNo == 1 && "Wrong operand for scalarization!");
  SDValue Elt = GetScalarizedVector(N->getOperand(1));
  SDValue Res = DAG.getNode(ISD::STRICT_FP_ROUND, SDLoc(N),
                            { N->getValueType(0).getVectorElementType(), 
                              MVT::Other },
                            { N->getOperand(0), Elt, N->getOperand(2) });
  // Legalize the chain result - switch anything that used the old chain to
  // use the new one.
  ReplaceValueWith(SDValue(N, 1), Res.getValue(1));

  Res = DAG.getNode(ISD::SCALAR_TO_VECTOR, SDLoc(N), N->getValueType(0), Res);

  // Do our own replacement and return SDValue() to tell the caller that we
  // handled all replacements since caller can only handle a single result.
  ReplaceValueWith(SDValue(N, 0), Res);
  return SDValue();
}

/// If the value to extend is a vector that needs to be scalarized, it must be
/// <1 x ty>. Convert the element instead.
SDValue DAGTypeLegalizer::ScalarizeVecOp_FP_EXTEND(SDNode *N) {
  SDValue Elt = GetScalarizedVector(N->getOperand(0));
  SDValue Res = DAG.getNode(ISD::FP_EXTEND, SDLoc(N),
                            N->getValueType(0).getVectorElementType(), Elt);
  return DAG.getNode(ISD::SCALAR_TO_VECTOR, SDLoc(N), N->getValueType(0), Res);
}

/// If the value to extend is a vector that needs to be scalarized, it must be
/// <1 x ty>. Convert the element instead.
SDValue DAGTypeLegalizer::ScalarizeVecOp_STRICT_FP_EXTEND(SDNode *N) {
  SDValue Elt = GetScalarizedVector(N->getOperand(1));
  SDValue Res =
      DAG.getNode(ISD::STRICT_FP_EXTEND, SDLoc(N),
                  {N->getValueType(0).getVectorElementType(), MVT::Other},
                  {N->getOperand(0), Elt});
  // Legalize the chain result - switch anything that used the old chain to
  // use the new one.
  ReplaceValueWith(SDValue(N, 1), Res.getValue(1));

  Res = DAG.getNode(ISD::SCALAR_TO_VECTOR, SDLoc(N), N->getValueType(0), Res);

  // Do our own replacement and return SDValue() to tell the caller that we
  // handled all replacements since caller can only handle a single result.
  ReplaceValueWith(SDValue(N, 0), Res);
  return SDValue();
}

SDValue DAGTypeLegalizer::ScalarizeVecOp_VECREDUCE(SDNode *N) {
  SDValue Res = GetScalarizedVector(N->getOperand(0));
  // Result type may be wider than element type.
  if (Res.getValueType() != N->getValueType(0))
    Res = DAG.getNode(ISD::ANY_EXTEND, SDLoc(N), N->getValueType(0), Res);
  return Res;
}

SDValue DAGTypeLegalizer::ScalarizeVecOp_VECREDUCE_SEQ(SDNode *N) {
  SDValue AccOp = N->getOperand(0);
  SDValue VecOp = N->getOperand(1);

  unsigned BaseOpc = ISD::getVecReduceBaseOpcode(N->getOpcode());

  SDValue Op = GetScalarizedVector(VecOp);
  return DAG.getNode(BaseOpc, SDLoc(N), N->getValueType(0),
                     AccOp, Op, N->getFlags());
}

//===----------------------------------------------------------------------===//
//  Result Vector Splitting
//===----------------------------------------------------------------------===//

/// This method is called when the specified result of the specified node is
/// found to need vector splitting. At this point, the node may also have
/// invalid operands or may have other results that need legalization, we just
/// know that (at least) one result needs vector splitting.
void DAGTypeLegalizer::SplitVectorResult(SDNode *N, unsigned ResNo) {
  LLVM_DEBUG(dbgs() << "Split node result: "; N->dump(&DAG); dbgs() << "\n");
  SDValue Lo, Hi;

  // See if the target wants to custom expand this node.
  if (CustomLowerNode(N, N->getValueType(ResNo), true))
    return;

  switch (N->getOpcode()) {
  default:
#ifndef NDEBUG
    dbgs() << "SplitVectorResult #" << ResNo << ": ";
    N->dump(&DAG);
    dbgs() << "\n";
#endif
    report_fatal_error("Do not know how to split the result of this "
                       "operator!\n");

  case ISD::MERGE_VALUES: SplitRes_MERGE_VALUES(N, ResNo, Lo, Hi); break;
  case ISD::VSELECT:
  case ISD::SELECT:       SplitRes_SELECT(N, Lo, Hi); break;
  case ISD::SELECT_CC:    SplitRes_SELECT_CC(N, Lo, Hi); break;
  case ISD::UNDEF:        SplitRes_UNDEF(N, Lo, Hi); break;
  case ISD::BITCAST:           SplitVecRes_BITCAST(N, Lo, Hi); break;
  case ISD::BUILD_VECTOR:      SplitVecRes_BUILD_VECTOR(N, Lo, Hi); break;
  case ISD::CONCAT_VECTORS:    SplitVecRes_CONCAT_VECTORS(N, Lo, Hi); break;
  case ISD::EXTRACT_SUBVECTOR: SplitVecRes_EXTRACT_SUBVECTOR(N, Lo, Hi); break;
  case ISD::INSERT_SUBVECTOR:  SplitVecRes_INSERT_SUBVECTOR(N, Lo, Hi); break;
  case ISD::FPOWI:             SplitVecRes_FPOWI(N, Lo, Hi); break;
  case ISD::FCOPYSIGN:         SplitVecRes_FCOPYSIGN(N, Lo, Hi); break;
  case ISD::INSERT_VECTOR_ELT: SplitVecRes_INSERT_VECTOR_ELT(N, Lo, Hi); break;
  case ISD::SPLAT_VECTOR:
  case ISD::SCALAR_TO_VECTOR:
    SplitVecRes_ScalarOp(N, Lo, Hi);
    break;
  case ISD::STEP_VECTOR:
    SplitVecRes_STEP_VECTOR(N, Lo, Hi);
    break;
  case ISD::SIGN_EXTEND_INREG: SplitVecRes_InregOp(N, Lo, Hi); break;
  case ISD::LOAD:
    SplitVecRes_LOAD(cast<LoadSDNode>(N), Lo, Hi);
    break;
  case ISD::MLOAD:
    SplitVecRes_MLOAD(cast<MaskedLoadSDNode>(N), Lo, Hi);
    break;
  case ISD::MGATHER:
    SplitVecRes_MGATHER(cast<MaskedGatherSDNode>(N), Lo, Hi);
    break;
  case ISD::SETCC:
    SplitVecRes_SETCC(N, Lo, Hi);
    break;
  case ISD::VECTOR_REVERSE:
    SplitVecRes_VECTOR_REVERSE(N, Lo, Hi);
    break;
  case ISD::VECTOR_SHUFFLE:
    SplitVecRes_VECTOR_SHUFFLE(cast<ShuffleVectorSDNode>(N), Lo, Hi);
    break;
  case ISD::VECTOR_SPLICE:
    SplitVecRes_VECTOR_SPLICE(N, Lo, Hi);
    break;
  case ISD::VAARG:
    SplitVecRes_VAARG(N, Lo, Hi);
    break;

  case ISD::ANY_EXTEND_VECTOR_INREG:
  case ISD::SIGN_EXTEND_VECTOR_INREG:
  case ISD::ZERO_EXTEND_VECTOR_INREG:
    SplitVecRes_ExtVecInRegOp(N, Lo, Hi);
    break;

  case ISD::ABS:
  case ISD::BITREVERSE:
  case ISD::BSWAP:
  case ISD::CTLZ:
  case ISD::CTTZ:
  case ISD::CTLZ_ZERO_UNDEF:
  case ISD::CTTZ_ZERO_UNDEF:
  case ISD::CTPOP:
  case ISD::FABS:
  case ISD::FCEIL:
  case ISD::FCOS:
  case ISD::FEXP:
  case ISD::FEXP2:
  case ISD::FFLOOR:
  case ISD::FLOG:
  case ISD::FLOG10:
  case ISD::FLOG2:
  case ISD::FNEARBYINT:
  case ISD::FNEG:
  case ISD::FREEZE:
  case ISD::ARITH_FENCE:
  case ISD::FP_EXTEND:
  case ISD::FP_ROUND:
  case ISD::FP_TO_SINT:
  case ISD::FP_TO_UINT:
  case ISD::FRINT:
  case ISD::FROUND:
  case ISD::FROUNDEVEN:
  case ISD::FSIN:
  case ISD::FSQRT:
  case ISD::FTRUNC:
  case ISD::SINT_TO_FP:
  case ISD::TRUNCATE:
  case ISD::UINT_TO_FP:
  case ISD::FCANONICALIZE:
    SplitVecRes_UnaryOp(N, Lo, Hi);
    break;

  case ISD::ANY_EXTEND:
  case ISD::SIGN_EXTEND:
  case ISD::ZERO_EXTEND:
    SplitVecRes_ExtendOp(N, Lo, Hi);
    break;

  case ISD::ADD:
  case ISD::SUB:
  case ISD::MUL:
  case ISD::MULHS:
  case ISD::MULHU:
  case ISD::FADD:
  case ISD::FSUB:
  case ISD::FMUL:
  case ISD::FMINNUM:
  case ISD::FMAXNUM:
  case ISD::FMINIMUM:
  case ISD::FMAXIMUM:
  case ISD::SDIV:
  case ISD::UDIV:
  case ISD::FDIV:
  case ISD::FPOW:
  case ISD::AND:
  case ISD::OR:
  case ISD::XOR:
  case ISD::SHL:
  case ISD::SRA:
  case ISD::SRL:
  case ISD::UREM:
  case ISD::SREM:
  case ISD::FREM:
  case ISD::SMIN:
  case ISD::SMAX:
  case ISD::UMIN:
  case ISD::UMAX:
  case ISD::SADDSAT:
  case ISD::UADDSAT:
  case ISD::SSUBSAT:
  case ISD::USUBSAT:
  case ISD::SSHLSAT:
  case ISD::USHLSAT:
  case ISD::ROTL:
  case ISD::ROTR:
    SplitVecRes_BinOp(N, Lo, Hi, /*IsVP*/ false);
    break;
  case ISD::FMA:
  case ISD::FSHL:
  case ISD::FSHR:
    SplitVecRes_TernaryOp(N, Lo, Hi);
    break;

#define DAG_INSTRUCTION(NAME, NARG, ROUND_MODE, INTRINSIC, DAGN)               \
  case ISD::STRICT_##DAGN:
#include "llvm/IR/ConstrainedOps.def"
    SplitVecRes_StrictFPOp(N, Lo, Hi);
    break;

  case ISD::FP_TO_UINT_SAT:
  case ISD::FP_TO_SINT_SAT:
    SplitVecRes_FP_TO_XINT_SAT(N, Lo, Hi);
    break;

  case ISD::UADDO:
  case ISD::SADDO:
  case ISD::USUBO:
  case ISD::SSUBO:
  case ISD::UMULO:
  case ISD::SMULO:
    SplitVecRes_OverflowOp(N, ResNo, Lo, Hi);
    break;
  case ISD::SMULFIX:
  case ISD::SMULFIXSAT:
  case ISD::UMULFIX:
  case ISD::UMULFIXSAT:
  case ISD::SDIVFIX:
  case ISD::SDIVFIXSAT:
  case ISD::UDIVFIX:
  case ISD::UDIVFIXSAT:
    SplitVecRes_FIX(N, Lo, Hi);
    break;
  case ISD::VP_ADD:
  case ISD::VP_AND:
  case ISD::VP_MUL:
  case ISD::VP_OR:
  case ISD::VP_SUB:
  case ISD::VP_XOR:
  case ISD::VP_SHL:
  case ISD::VP_LSHR:
  case ISD::VP_ASHR:
  case ISD::VP_SDIV:
  case ISD::VP_UDIV:
  case ISD::VP_SREM:
  case ISD::VP_UREM:
  case ISD::VP_FADD:
  case ISD::VP_FSUB:
  case ISD::VP_FMUL:
  case ISD::VP_FDIV:
  case ISD::VP_FREM:
    SplitVecRes_BinOp(N, Lo, Hi, /*IsVP*/ true);
    break;
  }

  // If Lo/Hi is null, the sub-method took care of registering results etc.
  if (Lo.getNode())
    SetSplitVector(SDValue(N, ResNo), Lo, Hi);
}

void DAGTypeLegalizer::IncrementPointer(MemSDNode *N, EVT MemVT,
                                        MachinePointerInfo &MPI, SDValue &Ptr,
                                        uint64_t *ScaledOffset) {
  SDLoc DL(N);
  unsigned IncrementSize = MemVT.getSizeInBits().getKnownMinSize() / 8;

  if (MemVT.isScalableVector()) {
    SDNodeFlags Flags;
    SDValue BytesIncrement = DAG.getVScale(
        DL, Ptr.getValueType(),
        APInt(Ptr.getValueSizeInBits().getFixedSize(), IncrementSize));
    MPI = MachinePointerInfo(N->getPointerInfo().getAddrSpace());
    Flags.setNoUnsignedWrap(true);
    if (ScaledOffset)
      *ScaledOffset += IncrementSize;
    Ptr = DAG.getNode(ISD::ADD, DL, Ptr.getValueType(), Ptr, BytesIncrement,
                      Flags);
  } else {
    MPI = N->getPointerInfo().getWithOffset(IncrementSize);
    // Increment the pointer to the other half.
    Ptr = DAG.getObjectPtrOffset(DL, Ptr, TypeSize::Fixed(IncrementSize));
  }
}

void DAGTypeLegalizer::SplitVecRes_BinOp(SDNode *N, SDValue &Lo, SDValue &Hi,
                                         bool IsVP) {
  SDValue LHSLo, LHSHi;
  GetSplitVector(N->getOperand(0), LHSLo, LHSHi);
  SDValue RHSLo, RHSHi;
  GetSplitVector(N->getOperand(1), RHSLo, RHSHi);
  SDLoc dl(N);

  const SDNodeFlags Flags = N->getFlags();
  unsigned Opcode = N->getOpcode();
  if (!IsVP) {
    Lo = DAG.getNode(Opcode, dl, LHSLo.getValueType(), LHSLo, RHSLo, Flags);
    Hi = DAG.getNode(Opcode, dl, LHSHi.getValueType(), LHSHi, RHSHi, Flags);
    return;
  }

  // Split the mask.
  SDValue MaskLo, MaskHi;
  SDValue Mask = N->getOperand(2);
  EVT MaskVT = Mask.getValueType();
  if (getTypeAction(MaskVT) == TargetLowering::TypeSplitVector)
    GetSplitVector(Mask, MaskLo, MaskHi);
  else
    std::tie(MaskLo, MaskHi) = DAG.SplitVector(Mask, SDLoc(Mask));

  // Split the vector length parameter.
  // %evl -> umin(%evl, %halfnumelts) and usubsat(%evl - %halfnumelts).
  SDValue EVL = N->getOperand(3);
  EVT VecVT = N->getValueType(0);
  EVT EVLVT = EVL.getValueType();
  assert(VecVT.getVectorElementCount().isKnownEven() &&
         "Expecting the mask to be an evenly-sized vector");
  unsigned HalfMinNumElts = VecVT.getVectorMinNumElements() / 2;
  SDValue HalfNumElts =
      VecVT.isFixedLengthVector()
          ? DAG.getConstant(HalfMinNumElts, dl, EVLVT)
          : DAG.getVScale(dl, EVLVT,
                          APInt(EVLVT.getScalarSizeInBits(), HalfMinNumElts));
  SDValue EVLLo = DAG.getNode(ISD::UMIN, dl, EVLVT, EVL, HalfNumElts);
  SDValue EVLHi = DAG.getNode(ISD::USUBSAT, dl, EVLVT, EVL, HalfNumElts);

  Lo = DAG.getNode(Opcode, dl, LHSLo.getValueType(),
                   {LHSLo, RHSLo, MaskLo, EVLLo}, Flags);
  Hi = DAG.getNode(Opcode, dl, LHSHi.getValueType(),
                   {LHSHi, RHSHi, MaskHi, EVLHi}, Flags);
}

void DAGTypeLegalizer::SplitVecRes_TernaryOp(SDNode *N, SDValue &Lo,
                                             SDValue &Hi) {
  SDValue Op0Lo, Op0Hi;
  GetSplitVector(N->getOperand(0), Op0Lo, Op0Hi);
  SDValue Op1Lo, Op1Hi;
  GetSplitVector(N->getOperand(1), Op1Lo, Op1Hi);
  SDValue Op2Lo, Op2Hi;
  GetSplitVector(N->getOperand(2), Op2Lo, Op2Hi);
  SDLoc dl(N);

  Lo = DAG.getNode(N->getOpcode(), dl, Op0Lo.getValueType(), Op0Lo, Op1Lo,
                   Op2Lo, N->getFlags());
  Hi = DAG.getNode(N->getOpcode(), dl, Op0Hi.getValueType(), Op0Hi, Op1Hi,
                   Op2Hi, N->getFlags());
}

void DAGTypeLegalizer::SplitVecRes_FIX(SDNode *N, SDValue &Lo, SDValue &Hi) {
  SDValue LHSLo, LHSHi;
  GetSplitVector(N->getOperand(0), LHSLo, LHSHi);
  SDValue RHSLo, RHSHi;
  GetSplitVector(N->getOperand(1), RHSLo, RHSHi);
  SDLoc dl(N);
  SDValue Op2 = N->getOperand(2);

  unsigned Opcode = N->getOpcode();
  Lo = DAG.getNode(Opcode, dl, LHSLo.getValueType(), LHSLo, RHSLo, Op2,
                   N->getFlags());
  Hi = DAG.getNode(Opcode, dl, LHSHi.getValueType(), LHSHi, RHSHi, Op2,
                   N->getFlags());
}

void DAGTypeLegalizer::SplitVecRes_BITCAST(SDNode *N, SDValue &Lo,
                                           SDValue &Hi) {
  // We know the result is a vector.  The input may be either a vector or a
  // scalar value.
  EVT LoVT, HiVT;
  std::tie(LoVT, HiVT) = DAG.GetSplitDestVTs(N->getValueType(0));
  SDLoc dl(N);

  SDValue InOp = N->getOperand(0);
  EVT InVT = InOp.getValueType();

  // Handle some special cases efficiently.
  switch (getTypeAction(InVT)) {
  case TargetLowering::TypeLegal:
  case TargetLowering::TypePromoteInteger:
  case TargetLowering::TypePromoteFloat:
  case TargetLowering::TypeSoftPromoteHalf:
  case TargetLowering::TypeSoftenFloat:
  case TargetLowering::TypeScalarizeVector:
  case TargetLowering::TypeWidenVector:
    break;
  case TargetLowering::TypeExpandInteger:
  case TargetLowering::TypeExpandFloat:
    // A scalar to vector conversion, where the scalar needs expansion.
    // If the vector is being split in two then we can just convert the
    // expanded pieces.
    if (LoVT == HiVT) {
      GetExpandedOp(InOp, Lo, Hi);
      if (DAG.getDataLayout().isBigEndian())
        std::swap(Lo, Hi);
      Lo = DAG.getNode(ISD::BITCAST, dl, LoVT, Lo);
      Hi = DAG.getNode(ISD::BITCAST, dl, HiVT, Hi);
      return;
    }
    break;
  case TargetLowering::TypeSplitVector:
    // If the input is a vector that needs to be split, convert each split
    // piece of the input now.
    GetSplitVector(InOp, Lo, Hi);
    Lo = DAG.getNode(ISD::BITCAST, dl, LoVT, Lo);
    Hi = DAG.getNode(ISD::BITCAST, dl, HiVT, Hi);
    return;
  case TargetLowering::TypeScalarizeScalableVector:
    report_fatal_error("Scalarization of scalable vectors is not supported.");
  }

  // In the general case, convert the input to an integer and split it by hand.
  EVT LoIntVT = EVT::getIntegerVT(*DAG.getContext(), LoVT.getSizeInBits());
  EVT HiIntVT = EVT::getIntegerVT(*DAG.getContext(), HiVT.getSizeInBits());
  if (DAG.getDataLayout().isBigEndian())
    std::swap(LoIntVT, HiIntVT);

  SplitInteger(BitConvertToInteger(InOp), LoIntVT, HiIntVT, Lo, Hi);

  if (DAG.getDataLayout().isBigEndian())
    std::swap(Lo, Hi);
  Lo = DAG.getNode(ISD::BITCAST, dl, LoVT, Lo);
  Hi = DAG.getNode(ISD::BITCAST, dl, HiVT, Hi);
}

void DAGTypeLegalizer::SplitVecRes_BUILD_VECTOR(SDNode *N, SDValue &Lo,
                                                SDValue &Hi) {
  EVT LoVT, HiVT;
  SDLoc dl(N);
  std::tie(LoVT, HiVT) = DAG.GetSplitDestVTs(N->getValueType(0));
  unsigned LoNumElts = LoVT.getVectorNumElements();
  SmallVector<SDValue, 8> LoOps(N->op_begin(), N->op_begin()+LoNumElts);
  Lo = DAG.getBuildVector(LoVT, dl, LoOps);

  SmallVector<SDValue, 8> HiOps(N->op_begin()+LoNumElts, N->op_end());
  Hi = DAG.getBuildVector(HiVT, dl, HiOps);
}

void DAGTypeLegalizer::SplitVecRes_CONCAT_VECTORS(SDNode *N, SDValue &Lo,
                                                  SDValue &Hi) {
  assert(!(N->getNumOperands() & 1) && "Unsupported CONCAT_VECTORS");
  SDLoc dl(N);
  unsigned NumSubvectors = N->getNumOperands() / 2;
  if (NumSubvectors == 1) {
    Lo = N->getOperand(0);
    Hi = N->getOperand(1);
    return;
  }

  EVT LoVT, HiVT;
  std::tie(LoVT, HiVT) = DAG.GetSplitDestVTs(N->getValueType(0));

  SmallVector<SDValue, 8> LoOps(N->op_begin(), N->op_begin()+NumSubvectors);
  Lo = DAG.getNode(ISD::CONCAT_VECTORS, dl, LoVT, LoOps);

  SmallVector<SDValue, 8> HiOps(N->op_begin()+NumSubvectors, N->op_end());
  Hi = DAG.getNode(ISD::CONCAT_VECTORS, dl, HiVT, HiOps);
}

void DAGTypeLegalizer::SplitVecRes_EXTRACT_SUBVECTOR(SDNode *N, SDValue &Lo,
                                                     SDValue &Hi) {
  SDValue Vec = N->getOperand(0);
  SDValue Idx = N->getOperand(1);
  SDLoc dl(N);

  EVT LoVT, HiVT;
  std::tie(LoVT, HiVT) = DAG.GetSplitDestVTs(N->getValueType(0));

  Lo = DAG.getNode(ISD::EXTRACT_SUBVECTOR, dl, LoVT, Vec, Idx);
  uint64_t IdxVal = cast<ConstantSDNode>(Idx)->getZExtValue();
  Hi = DAG.getNode(
      ISD::EXTRACT_SUBVECTOR, dl, HiVT, Vec,
      DAG.getVectorIdxConstant(IdxVal + LoVT.getVectorMinNumElements(), dl));
}

void DAGTypeLegalizer::SplitVecRes_INSERT_SUBVECTOR(SDNode *N, SDValue &Lo,
                                                    SDValue &Hi) {
  SDValue Vec = N->getOperand(0);
  SDValue SubVec = N->getOperand(1);
  SDValue Idx = N->getOperand(2);
  SDLoc dl(N);
  GetSplitVector(Vec, Lo, Hi);

  EVT VecVT = Vec.getValueType();
  EVT LoVT = Lo.getValueType();
  EVT SubVecVT = SubVec.getValueType();
  unsigned VecElems = VecVT.getVectorMinNumElements();
  unsigned SubElems = SubVecVT.getVectorMinNumElements();
  unsigned LoElems = LoVT.getVectorMinNumElements();

  // If we know the index is in the first half, and we know the subvector
  // doesn't cross the boundary between the halves, we can avoid spilling the
  // vector, and insert into the lower half of the split vector directly.
  unsigned IdxVal = cast<ConstantSDNode>(Idx)->getZExtValue();
  if (IdxVal + SubElems <= LoElems) {
    Lo = DAG.getNode(ISD::INSERT_SUBVECTOR, dl, LoVT, Lo, SubVec, Idx);
    return;
  }
  // Similarly if the subvector is fully in the high half, but mind that we
  // can't tell whether a fixed-length subvector is fully within the high half
  // of a scalable vector.
  if (VecVT.isScalableVector() == SubVecVT.isScalableVector() &&
      IdxVal >= LoElems && IdxVal + SubElems <= VecElems) {
    Hi = DAG.getNode(ISD::INSERT_SUBVECTOR, dl, Hi.getValueType(), Hi, SubVec,
                     DAG.getVectorIdxConstant(IdxVal - LoElems, dl));
    return;
  }

  // Spill the vector to the stack.
  // In cases where the vector is illegal it will be broken down into parts
  // and stored in parts - we should use the alignment for the smallest part.
  Align SmallestAlign = DAG.getReducedAlign(VecVT, /*UseABI=*/false);
  SDValue StackPtr =
      DAG.CreateStackTemporary(VecVT.getStoreSize(), SmallestAlign);
  auto &MF = DAG.getMachineFunction();
  auto FrameIndex = cast<FrameIndexSDNode>(StackPtr.getNode())->getIndex();
  auto PtrInfo = MachinePointerInfo::getFixedStack(MF, FrameIndex);

  SDValue Store = DAG.getStore(DAG.getEntryNode(), dl, Vec, StackPtr, PtrInfo,
                               SmallestAlign);

  // Store the new subvector into the specified index.
  SDValue SubVecPtr =
      TLI.getVectorSubVecPointer(DAG, StackPtr, VecVT, SubVecVT, Idx);
  Store = DAG.getStore(Store, dl, SubVec, SubVecPtr,
                       MachinePointerInfo::getUnknownStack(MF));

  // Load the Lo part from the stack slot.
  Lo = DAG.getLoad(Lo.getValueType(), dl, Store, StackPtr, PtrInfo,
                   SmallestAlign);

  // Increment the pointer to the other part.
  auto *Load = cast<LoadSDNode>(Lo);
  MachinePointerInfo MPI = Load->getPointerInfo();
  IncrementPointer(Load, LoVT, MPI, StackPtr);

  // Load the Hi part from the stack slot.
  Hi = DAG.getLoad(Hi.getValueType(), dl, Store, StackPtr, MPI, SmallestAlign);
}

void DAGTypeLegalizer::SplitVecRes_FPOWI(SDNode *N, SDValue &Lo,
                                         SDValue &Hi) {
  SDLoc dl(N);
  GetSplitVector(N->getOperand(0), Lo, Hi);
  Lo = DAG.getNode(ISD::FPOWI, dl, Lo.getValueType(), Lo, N->getOperand(1));
  Hi = DAG.getNode(ISD::FPOWI, dl, Hi.getValueType(), Hi, N->getOperand(1));
}

void DAGTypeLegalizer::SplitVecRes_FCOPYSIGN(SDNode *N, SDValue &Lo,
                                             SDValue &Hi) {
  SDValue LHSLo, LHSHi;
  GetSplitVector(N->getOperand(0), LHSLo, LHSHi);
  SDLoc DL(N);

  SDValue RHSLo, RHSHi;
  SDValue RHS = N->getOperand(1);
  EVT RHSVT = RHS.getValueType();
  if (getTypeAction(RHSVT) == TargetLowering::TypeSplitVector)
    GetSplitVector(RHS, RHSLo, RHSHi);
  else
    std::tie(RHSLo, RHSHi) = DAG.SplitVector(RHS, SDLoc(RHS));


  Lo = DAG.getNode(ISD::FCOPYSIGN, DL, LHSLo.getValueType(), LHSLo, RHSLo);
  Hi = DAG.getNode(ISD::FCOPYSIGN, DL, LHSHi.getValueType(), LHSHi, RHSHi);
}

void DAGTypeLegalizer::SplitVecRes_InregOp(SDNode *N, SDValue &Lo,
                                           SDValue &Hi) {
  SDValue LHSLo, LHSHi;
  GetSplitVector(N->getOperand(0), LHSLo, LHSHi);
  SDLoc dl(N);

  EVT LoVT, HiVT;
  std::tie(LoVT, HiVT) =
    DAG.GetSplitDestVTs(cast<VTSDNode>(N->getOperand(1))->getVT());

  Lo = DAG.getNode(N->getOpcode(), dl, LHSLo.getValueType(), LHSLo,
                   DAG.getValueType(LoVT));
  Hi = DAG.getNode(N->getOpcode(), dl, LHSHi.getValueType(), LHSHi,
                   DAG.getValueType(HiVT));
}

void DAGTypeLegalizer::SplitVecRes_ExtVecInRegOp(SDNode *N, SDValue &Lo,
                                                 SDValue &Hi) {
  unsigned Opcode = N->getOpcode();
  SDValue N0 = N->getOperand(0);

  SDLoc dl(N);
  SDValue InLo, InHi;

  if (getTypeAction(N0.getValueType()) == TargetLowering::TypeSplitVector)
    GetSplitVector(N0, InLo, InHi);
  else
    std::tie(InLo, InHi) = DAG.SplitVectorOperand(N, 0);

  EVT InLoVT = InLo.getValueType();
  unsigned InNumElements = InLoVT.getVectorNumElements();

  EVT OutLoVT, OutHiVT;
  std::tie(OutLoVT, OutHiVT) = DAG.GetSplitDestVTs(N->getValueType(0));
  unsigned OutNumElements = OutLoVT.getVectorNumElements();
  assert((2 * OutNumElements) <= InNumElements &&
         "Illegal extend vector in reg split");

  // *_EXTEND_VECTOR_INREG instructions extend the lowest elements of the
  // input vector (i.e. we only use InLo):
  // OutLo will extend the first OutNumElements from InLo.
  // OutHi will extend the next OutNumElements from InLo.

  // Shuffle the elements from InLo for OutHi into the bottom elements to
  // create a 'fake' InHi.
  SmallVector<int, 8> SplitHi(InNumElements, -1);
  for (unsigned i = 0; i != OutNumElements; ++i)
    SplitHi[i] = i + OutNumElements;
  InHi = DAG.getVectorShuffle(InLoVT, dl, InLo, DAG.getUNDEF(InLoVT), SplitHi);

  Lo = DAG.getNode(Opcode, dl, OutLoVT, InLo);
  Hi = DAG.getNode(Opcode, dl, OutHiVT, InHi);
}

void DAGTypeLegalizer::SplitVecRes_StrictFPOp(SDNode *N, SDValue &Lo,
                                              SDValue &Hi) {
  unsigned NumOps = N->getNumOperands();
  SDValue Chain = N->getOperand(0);
  EVT LoVT, HiVT;
  SDLoc dl(N);
  std::tie(LoVT, HiVT) = DAG.GetSplitDestVTs(N->getValueType(0));

  SmallVector<SDValue, 4> OpsLo(NumOps);
  SmallVector<SDValue, 4> OpsHi(NumOps);

  // The Chain is the first operand.
  OpsLo[0] = Chain;
  OpsHi[0] = Chain;

  // Now process the remaining operands.
  for (unsigned i = 1; i < NumOps; ++i) {
    SDValue Op = N->getOperand(i);
    SDValue OpLo = Op;
    SDValue OpHi = Op;

    EVT InVT = Op.getValueType();
    if (InVT.isVector()) {
      // If the input also splits, handle it directly for a
      // compile time speedup. Otherwise split it by hand.
      if (getTypeAction(InVT) == TargetLowering::TypeSplitVector)
        GetSplitVector(Op, OpLo, OpHi);
      else
        std::tie(OpLo, OpHi) = DAG.SplitVectorOperand(N, i);
    }

    OpsLo[i] = OpLo;
    OpsHi[i] = OpHi;
  }

  EVT LoValueVTs[] = {LoVT, MVT::Other};
  EVT HiValueVTs[] = {HiVT, MVT::Other};
  Lo = DAG.getNode(N->getOpcode(), dl, DAG.getVTList(LoValueVTs), OpsLo,
                   N->getFlags());
  Hi = DAG.getNode(N->getOpcode(), dl, DAG.getVTList(HiValueVTs), OpsHi,
                   N->getFlags());

  // Build a factor node to remember that this Op is independent of the
  // other one.
  Chain = DAG.getNode(ISD::TokenFactor, dl, MVT::Other,
                      Lo.getValue(1), Hi.getValue(1));

  // Legalize the chain result - switch anything that used the old chain to
  // use the new one.
  ReplaceValueWith(SDValue(N, 1), Chain);
}

SDValue DAGTypeLegalizer::UnrollVectorOp_StrictFP(SDNode *N, unsigned ResNE) {
  SDValue Chain = N->getOperand(0);
  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;

  //The results of each unrolled operation, including the chain.
  EVT ChainVTs[] = {EltVT, MVT::Other};
  SmallVector<SDValue, 8> Chains;

  unsigned i;
  for (i = 0; i != NE; ++i) {
    Operands[0] = Chain;
    for (unsigned j = 1, e = N->getNumOperands(); j != e; ++j) {
      SDValue Operand = N->getOperand(j);
      EVT OperandVT = Operand.getValueType();
      if (OperandVT.isVector()) {
        EVT OperandEltVT = OperandVT.getVectorElementType();
        Operands[j] = DAG.getNode(ISD::EXTRACT_VECTOR_ELT, dl, OperandEltVT,
                                  Operand, DAG.getVectorIdxConstant(i, dl));
      } else {
        Operands[j] = Operand;
      }
    }
    SDValue Scalar = DAG.getNode(N->getOpcode(), dl, ChainVTs, Operands);
    Scalar.getNode()->setFlags(N->getFlags());

    //Add in the scalar as well as its chain value to the
    //result vectors.
    Scalars.push_back(Scalar);
    Chains.push_back(Scalar.getValue(1));
  }

  for (; i < ResNE; ++i)
    Scalars.push_back(DAG.getUNDEF(EltVT));

  // Build a new factor node to connect the chain back together.
  Chain = DAG.getNode(ISD::TokenFactor, dl, MVT::Other, Chains);
  ReplaceValueWith(SDValue(N, 1), Chain);

  // Create a new BUILD_VECTOR node
  EVT VecVT = EVT::getVectorVT(*DAG.getContext(), EltVT, ResNE);
  return DAG.getBuildVector(VecVT, dl, Scalars);
}

void DAGTypeLegalizer::SplitVecRes_OverflowOp(SDNode *N, unsigned ResNo,
                                              SDValue &Lo, SDValue &Hi) {
  SDLoc dl(N);
  EVT ResVT = N->getValueType(0);
  EVT OvVT = N->getValueType(1);
  EVT LoResVT, HiResVT, LoOvVT, HiOvVT;
  std::tie(LoResVT, HiResVT) = DAG.GetSplitDestVTs(ResVT);
  std::tie(LoOvVT, HiOvVT) = DAG.GetSplitDestVTs(OvVT);

  SDValue LoLHS, HiLHS, LoRHS, HiRHS;
  if (getTypeAction(ResVT) == TargetLowering::TypeSplitVector) {
    GetSplitVector(N->getOperand(0), LoLHS, HiLHS);
    GetSplitVector(N->getOperand(1), LoRHS, HiRHS);
  } else {
    std::tie(LoLHS, HiLHS) = DAG.SplitVectorOperand(N, 0);
    std::tie(LoRHS, HiRHS) = DAG.SplitVectorOperand(N, 1);
  }

  unsigned Opcode = N->getOpcode();
  SDVTList LoVTs = DAG.getVTList(LoResVT, LoOvVT);
  SDVTList HiVTs = DAG.getVTList(HiResVT, HiOvVT);
  SDNode *LoNode = DAG.getNode(Opcode, dl, LoVTs, LoLHS, LoRHS).getNode();
  SDNode *HiNode = DAG.getNode(Opcode, dl, HiVTs, HiLHS, HiRHS).getNode();
  LoNode->setFlags(N->getFlags());
  HiNode->setFlags(N->getFlags());

  Lo = SDValue(LoNode, ResNo);
  Hi = SDValue(HiNode, ResNo);

  // Replace the other vector result not being explicitly split here.
  unsigned OtherNo = 1 - ResNo;
  EVT OtherVT = N->getValueType(OtherNo);
  if (getTypeAction(OtherVT) == TargetLowering::TypeSplitVector) {
    SetSplitVector(SDValue(N, OtherNo),
                   SDValue(LoNode, OtherNo), SDValue(HiNode, OtherNo));
  } else {
    SDValue OtherVal = DAG.getNode(
        ISD::CONCAT_VECTORS, dl, OtherVT,
        SDValue(LoNode, OtherNo), SDValue(HiNode, OtherNo));
    ReplaceValueWith(SDValue(N, OtherNo), OtherVal);
  }
}

void DAGTypeLegalizer::SplitVecRes_INSERT_VECTOR_ELT(SDNode *N, SDValue &Lo,
                                                     SDValue &Hi) {
  SDValue Vec = N->getOperand(0);
  SDValue Elt = N->getOperand(1);
  SDValue Idx = N->getOperand(2);
  SDLoc dl(N);
  GetSplitVector(Vec, Lo, Hi);

  if (ConstantSDNode *CIdx = dyn_cast<ConstantSDNode>(Idx)) {
    unsigned IdxVal = CIdx->getZExtValue();
    unsigned LoNumElts = Lo.getValueType().getVectorMinNumElements();
    if (IdxVal < LoNumElts) {
      Lo = DAG.getNode(ISD::INSERT_VECTOR_ELT, dl,
                       Lo.getValueType(), Lo, Elt, Idx);
      return;
    } else if (!Vec.getValueType().isScalableVector()) {
      Hi = DAG.getNode(ISD::INSERT_VECTOR_ELT, dl, Hi.getValueType(), Hi, Elt,
                       DAG.getVectorIdxConstant(IdxVal - LoNumElts, dl));
      return;
    }
  }

  // See if the target wants to custom expand this node.
  if (CustomLowerNode(N, N->getValueType(0), true))
    return;

  // Make the vector elements byte-addressable if they aren't already.
  EVT VecVT = Vec.getValueType();
  EVT EltVT = VecVT.getVectorElementType();
  if (VecVT.getScalarSizeInBits() < 8) {
    EltVT = MVT::i8;
    VecVT = EVT::getVectorVT(*DAG.getContext(), EltVT,
                             VecVT.getVectorElementCount());
    Vec = DAG.getNode(ISD::ANY_EXTEND, dl, VecVT, Vec);
    // Extend the element type to match if needed.
    if (EltVT.bitsGT(Elt.getValueType()))
      Elt = DAG.getNode(ISD::ANY_EXTEND, dl, EltVT, Elt);
  }

  // Spill the vector to the stack.
  // In cases where the vector is illegal it will be broken down into parts
  // and stored in parts - we should use the alignment for the smallest part.
  Align SmallestAlign = DAG.getReducedAlign(VecVT, /*UseABI=*/false);
  SDValue StackPtr =
      DAG.CreateStackTemporary(VecVT.getStoreSize(), SmallestAlign);
  auto &MF = DAG.getMachineFunction();
  auto FrameIndex = cast<FrameIndexSDNode>(StackPtr.getNode())->getIndex();
  auto PtrInfo = MachinePointerInfo::getFixedStack(MF, FrameIndex);

  SDValue Store = DAG.getStore(DAG.getEntryNode(), dl, Vec, StackPtr, PtrInfo,
                               SmallestAlign);

  // Store the new element.  This may be larger than the vector element type,
  // so use a truncating store.
  SDValue EltPtr = TLI.getVectorElementPointer(DAG, StackPtr, VecVT, Idx);
  Store = DAG.getTruncStore(
      Store, dl, Elt, EltPtr, MachinePointerInfo::getUnknownStack(MF), EltVT,
      commonAlignment(SmallestAlign,
                      EltVT.getFixedSizeInBits() / 8));

  EVT LoVT, HiVT;
  std::tie(LoVT, HiVT) = DAG.GetSplitDestVTs(VecVT);

  // Load the Lo part from the stack slot.
  Lo = DAG.getLoad(LoVT, dl, Store, StackPtr, PtrInfo, SmallestAlign);

  // Increment the pointer to the other part.
  auto Load = cast<LoadSDNode>(Lo);
  MachinePointerInfo MPI = Load->getPointerInfo();
  IncrementPointer(Load, LoVT, MPI, StackPtr);

  Hi = DAG.getLoad(HiVT, dl, Store, StackPtr, MPI, SmallestAlign);

  // If we adjusted the original type, we need to truncate the results.
  std::tie(LoVT, HiVT) = DAG.GetSplitDestVTs(N->getValueType(0));
  if (LoVT != Lo.getValueType())
    Lo = DAG.getNode(ISD::TRUNCATE, dl, LoVT, Lo);
  if (HiVT != Hi.getValueType())
    Hi = DAG.getNode(ISD::TRUNCATE, dl, HiVT, Hi);
}

void DAGTypeLegalizer::SplitVecRes_STEP_VECTOR(SDNode *N, SDValue &Lo,
                                               SDValue &Hi) {
  EVT LoVT, HiVT;
  SDLoc dl(N);
  assert(N->getValueType(0).isScalableVector() &&
         "Only scalable vectors are supported for STEP_VECTOR");
  std::tie(LoVT, HiVT) = DAG.GetSplitDestVTs(N->getValueType(0));
  SDValue Step = N->getOperand(0);

  Lo = DAG.getNode(ISD::STEP_VECTOR, dl, LoVT, Step);

  // Hi = Lo + (EltCnt * Step)
  EVT EltVT = Step.getValueType();
  APInt StepVal = cast<ConstantSDNode>(Step)->getAPIntValue();
  SDValue StartOfHi =
      DAG.getVScale(dl, EltVT, StepVal * LoVT.getVectorMinNumElements());
  StartOfHi = DAG.getSExtOrTrunc(StartOfHi, dl, HiVT.getVectorElementType());
  StartOfHi = DAG.getNode(ISD::SPLAT_VECTOR, dl, HiVT, StartOfHi);

  Hi = DAG.getNode(ISD::STEP_VECTOR, dl, HiVT, Step);
  Hi = DAG.getNode(ISD::ADD, dl, HiVT, Hi, StartOfHi);
}

void DAGTypeLegalizer::SplitVecRes_ScalarOp(SDNode *N, SDValue &Lo,
                                            SDValue &Hi) {
  EVT LoVT, HiVT;
  SDLoc dl(N);
  std::tie(LoVT, HiVT) = DAG.GetSplitDestVTs(N->getValueType(0));
  Lo = DAG.getNode(N->getOpcode(), dl, LoVT, N->getOperand(0));
  if (N->getOpcode() == ISD::SCALAR_TO_VECTOR) {
    Hi = DAG.getUNDEF(HiVT);
  } else {
    assert(N->getOpcode() == ISD::SPLAT_VECTOR && "Unexpected opcode");
    Hi = Lo;
  }
}

void DAGTypeLegalizer::SplitVecRes_LOAD(LoadSDNode *LD, SDValue &Lo,
                                        SDValue &Hi) {
  assert(ISD::isUNINDEXEDLoad(LD) && "Indexed load during type legalization!");
  EVT LoVT, HiVT;
  SDLoc dl(LD);
  std::tie(LoVT, HiVT) = DAG.GetSplitDestVTs(LD->getValueType(0));

  ISD::LoadExtType ExtType = LD->getExtensionType();
  SDValue Ch = LD->getChain();
  SDValue Ptr = LD->getBasePtr();
  SDValue Offset = DAG.getUNDEF(Ptr.getValueType());
  EVT MemoryVT = LD->getMemoryVT();
  MachineMemOperand::Flags MMOFlags = LD->getMemOperand()->getFlags();
  AAMDNodes AAInfo = LD->getAAInfo();

  EVT LoMemVT, HiMemVT;
  std::tie(LoMemVT, HiMemVT) = DAG.GetSplitDestVTs(MemoryVT);

  if (!LoMemVT.isByteSized() || !HiMemVT.isByteSized()) {
    SDValue Value, NewChain;
    std::tie(Value, NewChain) = TLI.scalarizeVectorLoad(LD, DAG);
    std::tie(Lo, Hi) = DAG.SplitVector(Value, dl);
    ReplaceValueWith(SDValue(LD, 1), NewChain);
    return;
  }

  Lo = DAG.getLoad(ISD::UNINDEXED, ExtType, LoVT, dl, Ch, Ptr, Offset,
                   LD->getPointerInfo(), LoMemVT, LD->getOriginalAlign(),
                   MMOFlags, AAInfo);

  MachinePointerInfo MPI;
  IncrementPointer(LD, LoMemVT, MPI, Ptr);

  Hi = DAG.getLoad(ISD::UNINDEXED, ExtType, HiVT, dl, Ch, Ptr, Offset, MPI,
                   HiMemVT, LD->getOriginalAlign(), MMOFlags, AAInfo);

  // Build a factor node to remember that this load is independent of the
  // other one.
  Ch = DAG.getNode(ISD::TokenFactor, dl, MVT::Other, Lo.getValue(1),
                   Hi.getValue(1));

  // Legalize the chain result - switch anything that used the old chain to
  // use the new one.
  ReplaceValueWith(SDValue(LD, 1), Ch);
}

void DAGTypeLegalizer::SplitVecRes_MLOAD(MaskedLoadSDNode *MLD,
                                         SDValue &Lo, SDValue &Hi) {
  assert(MLD->isUnindexed() && "Indexed masked load during type legalization!");
  EVT LoVT, HiVT;
  SDLoc dl(MLD);
  std::tie(LoVT, HiVT) = DAG.GetSplitDestVTs(MLD->getValueType(0));

  SDValue Ch = MLD->getChain();
  SDValue Ptr = MLD->getBasePtr();
  SDValue Offset = MLD->getOffset();
  assert(Offset.isUndef() && "Unexpected indexed masked load offset");
  SDValue Mask = MLD->getMask();
  SDValue PassThru = MLD->getPassThru();
  Align Alignment = MLD->getOriginalAlign();
  ISD::LoadExtType ExtType = MLD->getExtensionType();

  // Split Mask operand
  SDValue MaskLo, MaskHi;
  if (Mask.getOpcode() == ISD::SETCC) {
    SplitVecRes_SETCC(Mask.getNode(), MaskLo, MaskHi);
  } else {
    if (getTypeAction(Mask.getValueType()) == TargetLowering::TypeSplitVector)
      GetSplitVector(Mask, MaskLo, MaskHi);
    else
      std::tie(MaskLo, MaskHi) = DAG.SplitVector(Mask, dl);
  }

  EVT MemoryVT = MLD->getMemoryVT();
  EVT LoMemVT, HiMemVT;
  bool HiIsEmpty = false;
  std::tie(LoMemVT, HiMemVT) =
      DAG.GetDependentSplitDestVTs(MemoryVT, LoVT, &HiIsEmpty);

  SDValue PassThruLo, PassThruHi;
  if (getTypeAction(PassThru.getValueType()) == TargetLowering::TypeSplitVector)
    GetSplitVector(PassThru, PassThruLo, PassThruHi);
  else
    std::tie(PassThruLo, PassThruHi) = DAG.SplitVector(PassThru, dl);

  MachineMemOperand *MMO = DAG.getMachineFunction().getMachineMemOperand(
      MLD->getPointerInfo(), MachineMemOperand::MOLoad,
      MemoryLocation::UnknownSize, Alignment, MLD->getAAInfo(),
      MLD->getRanges());

  Lo = DAG.getMaskedLoad(LoVT, dl, Ch, Ptr, Offset, MaskLo, PassThruLo, LoMemVT,
                         MMO, MLD->getAddressingMode(), ExtType,
                         MLD->isExpandingLoad());

  if (HiIsEmpty) {
    // The hi masked load has zero storage size. We therefore simply set it to
    // the low masked load and rely on subsequent removal from the chain.
    Hi = Lo;
  } else {
    // Generate hi masked load.
    Ptr = TLI.IncrementMemoryAddress(Ptr, MaskLo, dl, LoMemVT, DAG,
                                     MLD->isExpandingLoad());

    MachinePointerInfo MPI;
    if (LoMemVT.isScalableVector())
      MPI = MachinePointerInfo(MLD->getPointerInfo().getAddrSpace());
    else
      MPI = MLD->getPointerInfo().getWithOffset(
          LoMemVT.getStoreSize().getFixedSize());

    MMO = DAG.getMachineFunction().getMachineMemOperand(
        MPI, MachineMemOperand::MOLoad, MemoryLocation::UnknownSize, Alignment,
        MLD->getAAInfo(), MLD->getRanges());

    Hi = DAG.getMaskedLoad(HiVT, dl, Ch, Ptr, Offset, MaskHi, PassThruHi,
                           HiMemVT, MMO, MLD->getAddressingMode(), ExtType,
                           MLD->isExpandingLoad());
  }

  // Build a factor node to remember that this load is independent of the
  // other one.
  Ch = DAG.getNode(ISD::TokenFactor, dl, MVT::Other, Lo.getValue(1),
                   Hi.getValue(1));

  // Legalize the chain result - switch anything that used the old chain to
  // use the new one.
  ReplaceValueWith(SDValue(MLD, 1), Ch);

}

void DAGTypeLegalizer::SplitVecRes_MGATHER(MaskedGatherSDNode *MGT,
                                         SDValue &Lo, SDValue &Hi) {
  EVT LoVT, HiVT;
  SDLoc dl(MGT);
  std::tie(LoVT, HiVT) = DAG.GetSplitDestVTs(MGT->getValueType(0));

  SDValue Ch = MGT->getChain();
  SDValue Ptr = MGT->getBasePtr();
  SDValue Mask = MGT->getMask();
  SDValue PassThru = MGT->getPassThru();
  SDValue Index = MGT->getIndex();
  SDValue Scale = MGT->getScale();
  EVT MemoryVT = MGT->getMemoryVT();
  Align Alignment = MGT->getOriginalAlign();
  ISD::LoadExtType ExtType = MGT->getExtensionType();

  // Split Mask operand
  SDValue MaskLo, MaskHi;
  if (Mask.getOpcode() == ISD::SETCC) {
    SplitVecRes_SETCC(Mask.getNode(), MaskLo, MaskHi);
  } else {
    if (getTypeAction(Mask.getValueType()) == TargetLowering::TypeSplitVector)
      GetSplitVector(Mask, MaskLo, MaskHi);
    else
      std::tie(MaskLo, MaskHi) = DAG.SplitVector(Mask, dl);
  }

  EVT LoMemVT, HiMemVT;
  // Split MemoryVT
  std::tie(LoMemVT, HiMemVT) = DAG.GetSplitDestVTs(MemoryVT);

  SDValue PassThruLo, PassThruHi;
  if (getTypeAction(PassThru.getValueType()) == TargetLowering::TypeSplitVector)
    GetSplitVector(PassThru, PassThruLo, PassThruHi);
  else
    std::tie(PassThruLo, PassThruHi) = DAG.SplitVector(PassThru, dl);

  SDValue IndexHi, IndexLo;
  if (getTypeAction(Index.getValueType()) == TargetLowering::TypeSplitVector)
    GetSplitVector(Index, IndexLo, IndexHi);
  else
    std::tie(IndexLo, IndexHi) = DAG.SplitVector(Index, dl);

  MachineMemOperand *MMO = DAG.getMachineFunction().getMachineMemOperand(
      MGT->getPointerInfo(), MachineMemOperand::MOLoad,
      MemoryLocation::UnknownSize, Alignment, MGT->getAAInfo(),
      MGT->getRanges());

  SDValue OpsLo[] = {Ch, PassThruLo, MaskLo, Ptr, IndexLo, Scale};
  Lo = DAG.getMaskedGather(DAG.getVTList(LoVT, MVT::Other), LoMemVT, dl, OpsLo,
                           MMO, MGT->getIndexType(), ExtType);

  SDValue OpsHi[] = {Ch, PassThruHi, MaskHi, Ptr, IndexHi, Scale};
  Hi = DAG.getMaskedGather(DAG.getVTList(HiVT, MVT::Other), HiMemVT, dl, OpsHi,
                           MMO, MGT->getIndexType(), ExtType);

  // Build a factor node to remember that this load is independent of the
  // other one.
  Ch = DAG.getNode(ISD::TokenFactor, dl, MVT::Other, Lo.getValue(1),
                   Hi.getValue(1));

  // Legalize the chain result - switch anything that used the old chain to
  // use the new one.
  ReplaceValueWith(SDValue(MGT, 1), Ch);
}


void DAGTypeLegalizer::SplitVecRes_SETCC(SDNode *N, SDValue &Lo, SDValue &Hi) {
  assert(N->getValueType(0).isVector() &&
         N->getOperand(0).getValueType().isVector() &&
         "Operand types must be vectors");

  EVT LoVT, HiVT;
  SDLoc DL(N);
  std::tie(LoVT, HiVT) = DAG.GetSplitDestVTs(N->getValueType(0));

  // If the input also splits, handle it directly. Otherwise split it by hand.
  SDValue LL, LH, RL, RH;
  if (getTypeAction(N->getOperand(0).getValueType()) ==
      TargetLowering::TypeSplitVector)
    GetSplitVector(N->getOperand(0), LL, LH);
  else
    std::tie(LL, LH) = DAG.SplitVectorOperand(N, 0);

  if (getTypeAction(N->getOperand(1).getValueType()) ==
      TargetLowering::TypeSplitVector)
    GetSplitVector(N->getOperand(1), RL, RH);
  else
    std::tie(RL, RH) = DAG.SplitVectorOperand(N, 1);

  Lo = DAG.getNode(N->getOpcode(), DL, LoVT, LL, RL, N->getOperand(2));
  Hi = DAG.getNode(N->getOpcode(), DL, HiVT, LH, RH, N->getOperand(2));
}

void DAGTypeLegalizer::SplitVecRes_UnaryOp(SDNode *N, SDValue &Lo,
                                           SDValue &Hi) {
  // Get the dest types - they may not match the input types, e.g. int_to_fp.
  EVT LoVT, HiVT;
  SDLoc dl(N);
  std::tie(LoVT, HiVT) = DAG.GetSplitDestVTs(N->getValueType(0));

  // If the input also splits, handle it directly for a compile time speedup.
  // Otherwise split it by hand.
  unsigned OpNo = N->isStrictFPOpcode() ? 1 : 0;
  EVT InVT = N->getOperand(OpNo).getValueType();
  if (getTypeAction(InVT) == TargetLowering::TypeSplitVector)
    GetSplitVector(N->getOperand(OpNo), Lo, Hi);
  else
    std::tie(Lo, Hi) = DAG.SplitVectorOperand(N, OpNo);

  if (N->getOpcode() == ISD::FP_ROUND) {
    Lo = DAG.getNode(N->getOpcode(), dl, LoVT, Lo, N->getOperand(1),
                     N->getFlags());
    Hi = DAG.getNode(N->getOpcode(), dl, HiVT, Hi, N->getOperand(1),
                     N->getFlags());
  } else {
    Lo = DAG.getNode(N->getOpcode(), dl, LoVT, Lo, N->getFlags());
    Hi = DAG.getNode(N->getOpcode(), dl, HiVT, Hi, N->getFlags());
  }
}

void DAGTypeLegalizer::SplitVecRes_ExtendOp(SDNode *N, SDValue &Lo,
                                            SDValue &Hi) {
  SDLoc dl(N);
  EVT SrcVT = N->getOperand(0).getValueType();
  EVT DestVT = N->getValueType(0);
  EVT LoVT, HiVT;
  std::tie(LoVT, HiVT) = DAG.GetSplitDestVTs(DestVT);

  // We can do better than a generic split operation if the extend is doing
  // more than just doubling the width of the elements and the following are
  // true:
  //   - The number of vector elements is even,
  //   - the source type is legal,
  //   - the type of a split source is illegal,
  //   - the type of an extended (by doubling element size) source is legal, and
  //   - the type of that extended source when split is legal.
  //
  // This won't necessarily completely legalize the operation, but it will
  // more effectively move in the right direction and prevent falling down
  // to scalarization in many cases due to the input vector being split too
  // far.
  if (SrcVT.getVectorElementCount().isKnownEven() &&
      SrcVT.getScalarSizeInBits() * 2 < DestVT.getScalarSizeInBits()) {
    LLVMContext &Ctx = *DAG.getContext();
    EVT NewSrcVT = SrcVT.widenIntegerVectorElementType(Ctx);
    EVT SplitSrcVT = SrcVT.getHalfNumVectorElementsVT(Ctx);

    EVT SplitLoVT, SplitHiVT;
    std::tie(SplitLoVT, SplitHiVT) = DAG.GetSplitDestVTs(NewSrcVT);
    if (TLI.isTypeLegal(SrcVT) && !TLI.isTypeLegal(SplitSrcVT) &&
        TLI.isTypeLegal(NewSrcVT) && TLI.isTypeLegal(SplitLoVT)) {
      LLVM_DEBUG(dbgs() << "Split vector extend via incremental extend:";
                 N->dump(&DAG); dbgs() << "\n");
      // Extend the source vector by one step.
      SDValue NewSrc =
          DAG.getNode(N->getOpcode(), dl, NewSrcVT, N->getOperand(0));
      // Get the low and high halves of the new, extended one step, vector.
      std::tie(Lo, Hi) = DAG.SplitVector(NewSrc, dl);
      // Extend those vector halves the rest of the way.
      Lo = DAG.getNode(N->getOpcode(), dl, LoVT, Lo);
      Hi = DAG.getNode(N->getOpcode(), dl, HiVT, Hi);
      return;
    }
  }
  // Fall back to the generic unary operator splitting otherwise.
  SplitVecRes_UnaryOp(N, Lo, Hi);
}

void DAGTypeLegalizer::SplitVecRes_VECTOR_SHUFFLE(ShuffleVectorSDNode *N,
                                                  SDValue &Lo, SDValue &Hi) {
  // The low and high parts of the original input give four input vectors.
  SDValue Inputs[4];
  SDLoc dl(N);
  GetSplitVector(N->getOperand(0), Inputs[0], Inputs[1]);
  GetSplitVector(N->getOperand(1), Inputs[2], Inputs[3]);
  EVT NewVT = Inputs[0].getValueType();
  unsigned NewElts = NewVT.getVectorNumElements();

  // If Lo or Hi uses elements from at most two of the four input vectors, then
  // express it as a vector shuffle of those two inputs.  Otherwise extract the
  // input elements by hand and construct the Lo/Hi output using a BUILD_VECTOR.
  SmallVector<int, 16> Ops;
  for (unsigned High = 0; High < 2; ++High) {
    SDValue &Output = High ? Hi : Lo;

    // Build a shuffle mask for the output, discovering on the fly which
    // input vectors to use as shuffle operands (recorded in InputUsed).
    // If building a suitable shuffle vector proves too hard, then bail
    // out with useBuildVector set.
    unsigned InputUsed[2] = { -1U, -1U }; // Not yet discovered.
    unsigned FirstMaskIdx = High * NewElts;
    bool useBuildVector = false;
    for (unsigned MaskOffset = 0; MaskOffset < NewElts; ++MaskOffset) {
      // The mask element.  This indexes into the input.
      int Idx = N->getMaskElt(FirstMaskIdx + MaskOffset);

      // The input vector this mask element indexes into.
      unsigned Input = (unsigned)Idx / NewElts;

      if (Input >= array_lengthof(Inputs)) {
        // The mask element does not index into any input vector.
        Ops.push_back(-1);
        continue;
      }

      // Turn the index into an offset from the start of the input vector.
      Idx -= Input * NewElts;

      // Find or create a shuffle vector operand to hold this input.
      unsigned OpNo;
      for (OpNo = 0; OpNo < array_lengthof(InputUsed); ++OpNo) {
        if (InputUsed[OpNo] == Input) {
          // This input vector is already an operand.
          break;
        } else if (InputUsed[OpNo] == -1U) {
          // Create a new operand for this input vector.
          InputUsed[OpNo] = Input;
          break;
        }
      }

      if (OpNo >= array_lengthof(InputUsed)) {
        // More than two input vectors used!  Give up on trying to create a
        // shuffle vector.  Insert all elements into a BUILD_VECTOR instead.
        useBuildVector = true;
        break;
      }

      // Add the mask index for the new shuffle vector.
      Ops.push_back(Idx + OpNo * NewElts);
    }

    if (useBuildVector) {
      EVT EltVT = NewVT.getVectorElementType();
      SmallVector<SDValue, 16> SVOps;

      // Extract the input elements by hand.
      for (unsigned MaskOffset = 0; MaskOffset < NewElts; ++MaskOffset) {
        // The mask element.  This indexes into the input.
        int Idx = N->getMaskElt(FirstMaskIdx + MaskOffset);

        // The input vector this mask element indexes into.
        unsigned Input = (unsigned)Idx / NewElts;

        if (Input >= array_lengthof(Inputs)) {
          // The mask element is "undef" or indexes off the end of the input.
          SVOps.push_back(DAG.getUNDEF(EltVT));
          continue;
        }

        // Turn the index into an offset from the start of the input vector.
        Idx -= Input * NewElts;

        // Extract the vector element by hand.
        SVOps.push_back(DAG.getNode(ISD::EXTRACT_VECTOR_ELT, dl, EltVT,
                                    Inputs[Input],
                                    DAG.getVectorIdxConstant(Idx, dl)));
      }

      // Construct the Lo/Hi output using a BUILD_VECTOR.
      Output = DAG.getBuildVector(NewVT, dl, SVOps);
    } else if (InputUsed[0] == -1U) {
      // No input vectors were used!  The result is undefined.
      Output = DAG.getUNDEF(NewVT);
    } else {
      SDValue Op0 = Inputs[InputUsed[0]];
      // If only one input was used, use an undefined vector for the other.
      SDValue Op1 = InputUsed[1] == -1U ?
        DAG.getUNDEF(NewVT) : Inputs[InputUsed[1]];
      // At least one input vector was used.  Create a new shuffle vector.
      Output =  DAG.getVectorShuffle(NewVT, dl, Op0, Op1, Ops);
    }

    Ops.clear();
  }
}

void DAGTypeLegalizer::SplitVecRes_VAARG(SDNode *N, SDValue &Lo, SDValue &Hi) {
  EVT OVT = N->getValueType(0);
  EVT NVT = OVT.getHalfNumVectorElementsVT(*DAG.getContext());
  SDValue Chain = N->getOperand(0);
  SDValue Ptr = N->getOperand(1);
  SDValue SV = N->getOperand(2);
  SDLoc dl(N);

  const Align Alignment =
      DAG.getDataLayout().getABITypeAlign(NVT.getTypeForEVT(*DAG.getContext()));

  Lo = DAG.getVAArg(NVT, dl, Chain, Ptr, SV, Alignment.value());
  Hi = DAG.getVAArg(NVT, dl, Lo.getValue(1), Ptr, SV, Alignment.value());
  Chain = Hi.getValue(1);

  // Modified the chain - switch anything that used the old chain to use
  // the new one.
  ReplaceValueWith(SDValue(N, 1), Chain);
}

void DAGTypeLegalizer::SplitVecRes_FP_TO_XINT_SAT(SDNode *N, SDValue &Lo,
                                                  SDValue &Hi) {
  EVT DstVTLo, DstVTHi;
  std::tie(DstVTLo, DstVTHi) = DAG.GetSplitDestVTs(N->getValueType(0));
  SDLoc dl(N);

  SDValue SrcLo, SrcHi;
  EVT SrcVT = N->getOperand(0).getValueType();
  if (getTypeAction(SrcVT) == TargetLowering::TypeSplitVector)
    GetSplitVector(N->getOperand(0), SrcLo, SrcHi);
  else
    std::tie(SrcLo, SrcHi) = DAG.SplitVectorOperand(N, 0);

  Lo = DAG.getNode(N->getOpcode(), dl, DstVTLo, SrcLo, N->getOperand(1));
  Hi = DAG.getNode(N->getOpcode(), dl, DstVTHi, SrcHi, N->getOperand(1));
}

//===----------------------------------------------------------------------===//
//  Operand Vector Splitting
//===----------------------------------------------------------------------===//

/// This method is called when the specified operand of the specified node is
/// found to need vector splitting. At this point, all of the result types of
/// the node are known to be legal, but other operands of the node may need
/// legalization as well as the specified one.
bool DAGTypeLegalizer::SplitVectorOperand(SDNode *N, unsigned OpNo) {
  LLVM_DEBUG(dbgs() << "Split node operand: "; N->dump(&DAG); dbgs() << "\n");
  SDValue Res = SDValue();

  // See if the target wants to custom split this node.
  if (CustomLowerNode(N, N->getOperand(OpNo).getValueType(), false))
    return false;

  switch (N->getOpcode()) {
  default:
#ifndef NDEBUG
    dbgs() << "SplitVectorOperand Op #" << OpNo << ": ";
    N->dump(&DAG);
    dbgs() << "\n";
#endif
    report_fatal_error("Do not know how to split this operator's "
                       "operand!\n");

  case ISD::SETCC:             Res = SplitVecOp_VSETCC(N); break;
  case ISD::BITCAST:           Res = SplitVecOp_BITCAST(N); break;
  case ISD::EXTRACT_SUBVECTOR: Res = SplitVecOp_EXTRACT_SUBVECTOR(N); break;
  case ISD::INSERT_SUBVECTOR:  Res = SplitVecOp_INSERT_SUBVECTOR(N, OpNo); break;
  case ISD::EXTRACT_VECTOR_ELT:Res = SplitVecOp_EXTRACT_VECTOR_ELT(N); break;
  case ISD::CONCAT_VECTORS:    Res = SplitVecOp_CONCAT_VECTORS(N); break;
  case ISD::TRUNCATE:
    Res = SplitVecOp_TruncateHelper(N);
    break;
  case ISD::STRICT_FP_ROUND:
  case ISD::FP_ROUND:          Res = SplitVecOp_FP_ROUND(N); break;
  case ISD::FCOPYSIGN:         Res = SplitVecOp_FCOPYSIGN(N); break;
  case ISD::STORE:
    Res = SplitVecOp_STORE(cast<StoreSDNode>(N), OpNo);
    break;
  case ISD::MSTORE:
    Res = SplitVecOp_MSTORE(cast<MaskedStoreSDNode>(N), OpNo);
    break;
  case ISD::MSCATTER:
    Res = SplitVecOp_MSCATTER(cast<MaskedScatterSDNode>(N), OpNo);
    break;
  case ISD::MGATHER:
    Res = SplitVecOp_MGATHER(cast<MaskedGatherSDNode>(N), OpNo);
    break;
  case ISD::VSELECT:
    Res = SplitVecOp_VSELECT(N, OpNo);
    break;
  case ISD::STRICT_SINT_TO_FP:
  case ISD::STRICT_UINT_TO_FP:
  case ISD::SINT_TO_FP:
  case ISD::UINT_TO_FP:
    if (N->getValueType(0).bitsLT(
            N->getOperand(N->isStrictFPOpcode() ? 1 : 0).getValueType()))
      Res = SplitVecOp_TruncateHelper(N);
    else
      Res = SplitVecOp_UnaryOp(N);
    break;
  case ISD::FP_TO_SINT_SAT:
  case ISD::FP_TO_UINT_SAT:
    Res = SplitVecOp_FP_TO_XINT_SAT(N);
    break;
  case ISD::FP_TO_SINT:
  case ISD::FP_TO_UINT:
  case ISD::STRICT_FP_TO_SINT:
  case ISD::STRICT_FP_TO_UINT:
  case ISD::STRICT_FP_EXTEND:
  case ISD::FP_EXTEND:
  case ISD::SIGN_EXTEND:
  case ISD::ZERO_EXTEND:
  case ISD::ANY_EXTEND:
  case ISD::FTRUNC:
    Res = SplitVecOp_UnaryOp(N);
    break;

  case ISD::ANY_EXTEND_VECTOR_INREG:
  case ISD::SIGN_EXTEND_VECTOR_INREG:
  case ISD::ZERO_EXTEND_VECTOR_INREG:
    Res = SplitVecOp_ExtVecInRegOp(N);
    break;

  case ISD::VECREDUCE_FADD:
  case ISD::VECREDUCE_FMUL:
  case ISD::VECREDUCE_ADD:
  case ISD::VECREDUCE_MUL:
  case ISD::VECREDUCE_AND:
  case ISD::VECREDUCE_OR:
  case ISD::VECREDUCE_XOR:
  case ISD::VECREDUCE_SMAX:
  case ISD::VECREDUCE_SMIN:
  case ISD::VECREDUCE_UMAX:
  case ISD::VECREDUCE_UMIN:
  case ISD::VECREDUCE_FMAX:
  case ISD::VECREDUCE_FMIN:
    Res = SplitVecOp_VECREDUCE(N, OpNo);
    break;
  case ISD::VECREDUCE_SEQ_FADD:
  case ISD::VECREDUCE_SEQ_FMUL:
    Res = SplitVecOp_VECREDUCE_SEQ(N);
    break;
  }

  // If the result is null, the sub-method took care of registering results etc.
  if (!Res.getNode()) return false;

  // If the result is N, the sub-method updated N in place.  Tell the legalizer
  // core about this.
  if (Res.getNode() == N)
    return true;

  if (N->isStrictFPOpcode())
    assert(Res.getValueType() == N->getValueType(0) && N->getNumValues() == 2 &&
           "Invalid operand expansion");
  else
    assert(Res.getValueType() == N->getValueType(0) && N->getNumValues() == 1 &&
         "Invalid operand expansion");

  ReplaceValueWith(SDValue(N, 0), Res);
  return false;
}

SDValue DAGTypeLegalizer::SplitVecOp_VSELECT(SDNode *N, unsigned OpNo) {
  // The only possibility for an illegal operand is the mask, since result type
  // legalization would have handled this node already otherwise.
  assert(OpNo == 0 && "Illegal operand must be mask");

  SDValue Mask = N->getOperand(0);
  SDValue Src0 = N->getOperand(1);
  SDValue Src1 = N->getOperand(2);
  EVT Src0VT = Src0.getValueType();
  SDLoc DL(N);
  assert(Mask.getValueType().isVector() && "VSELECT without a vector mask?");

  SDValue Lo, Hi;
  GetSplitVector(N->getOperand(0), Lo, Hi);
  assert(Lo.getValueType() == Hi.getValueType() &&
         "Lo and Hi have differing types");

  EVT LoOpVT, HiOpVT;
  std::tie(LoOpVT, HiOpVT) = DAG.GetSplitDestVTs(Src0VT);
  assert(LoOpVT == HiOpVT && "Asymmetric vector split?");

  SDValue LoOp0, HiOp0, LoOp1, HiOp1, LoMask, HiMask;
  std::tie(LoOp0, HiOp0) = DAG.SplitVector(Src0, DL);
  std::tie(LoOp1, HiOp1) = DAG.SplitVector(Src1, DL);
  std::tie(LoMask, HiMask) = DAG.SplitVector(Mask, DL);

  SDValue LoSelect =
    DAG.getNode(ISD::VSELECT, DL, LoOpVT, LoMask, LoOp0, LoOp1);
  SDValue HiSelect =
    DAG.getNode(ISD::VSELECT, DL, HiOpVT, HiMask, HiOp0, HiOp1);

  return DAG.getNode(ISD::CONCAT_VECTORS, DL, Src0VT, LoSelect, HiSelect);
}

SDValue DAGTypeLegalizer::SplitVecOp_VECREDUCE(SDNode *N, unsigned OpNo) {
  EVT ResVT = N->getValueType(0);
  SDValue Lo, Hi;
  SDLoc dl(N);

  SDValue VecOp = N->getOperand(OpNo);
  EVT VecVT = VecOp.getValueType();
  assert(VecVT.isVector() && "Can only split reduce vector operand");
  GetSplitVector(VecOp, Lo, Hi);
  EVT LoOpVT, HiOpVT;
  std::tie(LoOpVT, HiOpVT) = DAG.GetSplitDestVTs(VecVT);

  // Use the appropriate scalar instruction on the split subvectors before
  // reducing the now partially reduced smaller vector.
  unsigned CombineOpc = ISD::getVecReduceBaseOpcode(N->getOpcode());
  SDValue Partial = DAG.getNode(CombineOpc, dl, LoOpVT, Lo, Hi, N->getFlags());
  return DAG.getNode(N->getOpcode(), dl, ResVT, Partial, N->getFlags());
}

SDValue DAGTypeLegalizer::SplitVecOp_VECREDUCE_SEQ(SDNode *N) {
  EVT ResVT = N->getValueType(0);
  SDValue Lo, Hi;
  SDLoc dl(N);

  SDValue AccOp = N->getOperand(0);
  SDValue VecOp = N->getOperand(1);
  SDNodeFlags Flags = N->getFlags();

  EVT VecVT = VecOp.getValueType();
  assert(VecVT.isVector() && "Can only split reduce vector operand");
  GetSplitVector(VecOp, Lo, Hi);
  EVT LoOpVT, HiOpVT;
  std::tie(LoOpVT, HiOpVT) = DAG.GetSplitDestVTs(VecVT);

  // Reduce low half.
  SDValue Partial = DAG.getNode(N->getOpcode(), dl, ResVT, AccOp, Lo, Flags);

  // Reduce high half, using low half result as initial value.
  return DAG.getNode(N->getOpcode(), dl, ResVT, Partial, Hi, Flags);
}

SDValue DAGTypeLegalizer::SplitVecOp_UnaryOp(SDNode *N) {
  // The result has a legal vector type, but the input needs splitting.
  EVT ResVT = N->getValueType(0);
  SDValue Lo, Hi;
  SDLoc dl(N);
  GetSplitVector(N->getOperand(N->isStrictFPOpcode() ? 1 : 0), Lo, Hi);
  EVT InVT = Lo.getValueType();

  EVT OutVT = EVT::getVectorVT(*DAG.getContext(), ResVT.getVectorElementType(),
                               InVT.getVectorElementCount());

  if (N->isStrictFPOpcode()) {
    Lo = DAG.getNode(N->getOpcode(), dl, { OutVT, MVT::Other }, 
                     { N->getOperand(0), Lo });
    Hi = DAG.getNode(N->getOpcode(), dl, { OutVT, MVT::Other }, 
                     { N->getOperand(0), Hi });

    // Build a factor node to remember that this operation is independent
    // of the other one.
    SDValue Ch = DAG.getNode(ISD::TokenFactor, dl, MVT::Other, Lo.getValue(1),
                             Hi.getValue(1));
  
    // Legalize the chain result - switch anything that used the old chain to
    // use the new one.
    ReplaceValueWith(SDValue(N, 1), Ch);
  } else {
    Lo = DAG.getNode(N->getOpcode(), dl, OutVT, Lo);
    Hi = DAG.getNode(N->getOpcode(), dl, OutVT, Hi);
  }

  return DAG.getNode(ISD::CONCAT_VECTORS, dl, ResVT, Lo, Hi);
}

SDValue DAGTypeLegalizer::SplitVecOp_BITCAST(SDNode *N) {
  // For example, i64 = BITCAST v4i16 on alpha.  Typically the vector will
  // end up being split all the way down to individual components.  Convert the
  // split pieces into integers and reassemble.
  SDValue Lo, Hi;
  GetSplitVector(N->getOperand(0), Lo, Hi);
  Lo = BitConvertToInteger(Lo);
  Hi = BitConvertToInteger(Hi);

  if (DAG.getDataLayout().isBigEndian())
    std::swap(Lo, Hi);

  return DAG.getNode(ISD::BITCAST, SDLoc(N), N->getValueType(0),
                     JoinIntegers(Lo, Hi));
}

SDValue DAGTypeLegalizer::SplitVecOp_INSERT_SUBVECTOR(SDNode *N,
                                                      unsigned OpNo) {
  assert(OpNo == 1 && "Invalid OpNo; can only split SubVec.");
  // We know that the result type is legal.
  EVT ResVT = N->getValueType(0);

  SDValue Vec = N->getOperand(0);
  SDValue SubVec = N->getOperand(1);
  SDValue Idx = N->getOperand(2);
  SDLoc dl(N);

  SDValue Lo, Hi;
  GetSplitVector(SubVec, Lo, Hi);

  uint64_t IdxVal = cast<ConstantSDNode>(Idx)->getZExtValue();
  uint64_t LoElts = Lo.getValueType().getVectorMinNumElements();

  SDValue FirstInsertion =
      DAG.getNode(ISD::INSERT_SUBVECTOR, dl, ResVT, Vec, Lo, Idx);
  SDValue SecondInsertion =
      DAG.getNode(ISD::INSERT_SUBVECTOR, dl, ResVT, FirstInsertion, Hi,
                  DAG.getVectorIdxConstant(IdxVal + LoElts, dl));

  return SecondInsertion;
}

SDValue DAGTypeLegalizer::SplitVecOp_EXTRACT_SUBVECTOR(SDNode *N) {
  // We know that the extracted result type is legal.
  EVT SubVT = N->getValueType(0);

  SDValue Idx = N->getOperand(1);
  SDLoc dl(N);
  SDValue Lo, Hi;

  if (SubVT.isScalableVector() !=
      N->getOperand(0).getValueType().isScalableVector())
    report_fatal_error("Extracting a fixed-length vector from an illegal "
                       "scalable vector is not yet supported");

  GetSplitVector(N->getOperand(0), Lo, Hi);

  uint64_t LoElts = Lo.getValueType().getVectorMinNumElements();
  uint64_t IdxVal = cast<ConstantSDNode>(Idx)->getZExtValue();

  if (IdxVal < LoElts) {
    assert(IdxVal + SubVT.getVectorMinNumElements() <= LoElts &&
           "Extracted subvector crosses vector split!");
    return DAG.getNode(ISD::EXTRACT_SUBVECTOR, dl, SubVT, Lo, Idx);
  } else {
    return DAG.getNode(ISD::EXTRACT_SUBVECTOR, dl, SubVT, Hi,
                       DAG.getVectorIdxConstant(IdxVal - LoElts, dl));
  }
}

SDValue DAGTypeLegalizer::SplitVecOp_EXTRACT_VECTOR_ELT(SDNode *N) {
  SDValue Vec = N->getOperand(0);
  SDValue Idx = N->getOperand(1);
  EVT VecVT = Vec.getValueType();

  if (isa<ConstantSDNode>(Idx)) {
    uint64_t IdxVal = cast<ConstantSDNode>(Idx)->getZExtValue();

    SDValue Lo, Hi;
    GetSplitVector(Vec, Lo, Hi);

    uint64_t LoElts = Lo.getValueType().getVectorMinNumElements();

    if (IdxVal < LoElts)
      return SDValue(DAG.UpdateNodeOperands(N, Lo, Idx), 0);
    else if (!Vec.getValueType().isScalableVector())
      return SDValue(DAG.UpdateNodeOperands(N, Hi,
                                    DAG.getConstant(IdxVal - LoElts, SDLoc(N),
                                                    Idx.getValueType())), 0);
  }

  // See if the target wants to custom expand this node.
  if (CustomLowerNode(N, N->getValueType(0), true))
    return SDValue();

  // Make the vector elements byte-addressable if they aren't already.
  SDLoc dl(N);
  EVT EltVT = VecVT.getVectorElementType();
  if (VecVT.getScalarSizeInBits() < 8) {
    EltVT = MVT::i8;
    VecVT = EVT::getVectorVT(*DAG.getContext(), EltVT,
                             VecVT.getVectorElementCount());
    Vec = DAG.getNode(ISD::ANY_EXTEND, dl, VecVT, Vec);
  }

  // Store the vector to the stack.
  // In cases where the vector is illegal it will be broken down into parts
  // and stored in parts - we should use the alignment for the smallest part.
  Align SmallestAlign = DAG.getReducedAlign(VecVT, /*UseABI=*/false);
  SDValue StackPtr =
      DAG.CreateStackTemporary(VecVT.getStoreSize(), SmallestAlign);
  auto &MF = DAG.getMachineFunction();
  auto FrameIndex = cast<FrameIndexSDNode>(StackPtr.getNode())->getIndex();
  auto PtrInfo = MachinePointerInfo::getFixedStack(MF, FrameIndex);
  SDValue Store = DAG.getStore(DAG.getEntryNode(), dl, Vec, StackPtr, PtrInfo,
                               SmallestAlign);

  // Load back the required element.
  StackPtr = TLI.getVectorElementPointer(DAG, StackPtr, VecVT, Idx);

  // FIXME: This is to handle i1 vectors with elements promoted to i8.
  // i1 vector handling needs general improvement.
  if (N->getValueType(0).bitsLT(EltVT)) {
    SDValue Load = DAG.getLoad(EltVT, dl, Store, StackPtr,
      MachinePointerInfo::getUnknownStack(DAG.getMachineFunction()));
    return DAG.getZExtOrTrunc(Load, dl, N->getValueType(0));
  }

  return DAG.getExtLoad(
      ISD::EXTLOAD, dl, N->getValueType(0), Store, StackPtr,
      MachinePointerInfo::getUnknownStack(DAG.getMachineFunction()), EltVT,
      commonAlignment(SmallestAlign, EltVT.getFixedSizeInBits() / 8));
}

SDValue DAGTypeLegalizer::SplitVecOp_ExtVecInRegOp(SDNode *N) {
  SDValue Lo, Hi;

  // *_EXTEND_VECTOR_INREG only reference the lower half of the input, so
  // splitting the result has the same effect as splitting the input operand.
  SplitVecRes_ExtVecInRegOp(N, Lo, Hi);

  return DAG.getNode(ISD::CONCAT_VECTORS, SDLoc(N), N->getValueType(0), Lo, Hi);
}

SDValue DAGTypeLegalizer::SplitVecOp_MGATHER(MaskedGatherSDNode *MGT,
                                             unsigned OpNo) {
  EVT LoVT, HiVT;
  SDLoc dl(MGT);
  std::tie(LoVT, HiVT) = DAG.GetSplitDestVTs(MGT->getValueType(0));

  SDValue Ch = MGT->getChain();
  SDValue Ptr = MGT->getBasePtr();
  SDValue Index = MGT->getIndex();
  SDValue Scale = MGT->getScale();
  SDValue Mask = MGT->getMask();
  SDValue PassThru = MGT->getPassThru();
  Align Alignment = MGT->getOriginalAlign();
  ISD::LoadExtType ExtType = MGT->getExtensionType();

  SDValue MaskLo, MaskHi;
  if (getTypeAction(Mask.getValueType()) == TargetLowering::TypeSplitVector)
    // Split Mask operand
    GetSplitVector(Mask, MaskLo, MaskHi);
  else
    std::tie(MaskLo, MaskHi) = DAG.SplitVector(Mask, dl);

  EVT MemoryVT = MGT->getMemoryVT();
  EVT LoMemVT, HiMemVT;
  std::tie(LoMemVT, HiMemVT) = DAG.GetSplitDestVTs(MemoryVT);

  SDValue PassThruLo, PassThruHi;
  if (getTypeAction(PassThru.getValueType()) == TargetLowering::TypeSplitVector)
    GetSplitVector(PassThru, PassThruLo, PassThruHi);
  else
    std::tie(PassThruLo, PassThruHi) = DAG.SplitVector(PassThru, dl);

  SDValue IndexHi, IndexLo;
  if (getTypeAction(Index.getValueType()) == TargetLowering::TypeSplitVector)
    GetSplitVector(Index, IndexLo, IndexHi);
  else
    std::tie(IndexLo, IndexHi) = DAG.SplitVector(Index, dl);

  MachineMemOperand *MMO = DAG.getMachineFunction().getMachineMemOperand(
      MGT->getPointerInfo(), MachineMemOperand::MOLoad,
      MemoryLocation::UnknownSize, Alignment, MGT->getAAInfo(),
      MGT->getRanges());

  SDValue OpsLo[] = {Ch, PassThruLo, MaskLo, Ptr, IndexLo, Scale};
  SDValue Lo = DAG.getMaskedGather(DAG.getVTList(LoVT, MVT::Other), LoMemVT, dl,
                                   OpsLo, MMO, MGT->getIndexType(), ExtType);

  SDValue OpsHi[] = {Ch, PassThruHi, MaskHi, Ptr, IndexHi, Scale};
  SDValue Hi = DAG.getMaskedGather(DAG.getVTList(HiVT, MVT::Other), HiMemVT, dl,
                                   OpsHi, MMO, MGT->getIndexType(), ExtType);

  // Build a factor node to remember that this load is independent of the
  // other one.
  Ch = DAG.getNode(ISD::TokenFactor, dl, MVT::Other, Lo.getValue(1),
                   Hi.getValue(1));

  // Legalize the chain result - switch anything that used the old chain to
  // use the new one.
  ReplaceValueWith(SDValue(MGT, 1), Ch);

  SDValue Res = DAG.getNode(ISD::CONCAT_VECTORS, dl, MGT->getValueType(0), Lo,
                            Hi);
  ReplaceValueWith(SDValue(MGT, 0), Res);
  return SDValue();
}

SDValue DAGTypeLegalizer::SplitVecOp_MSTORE(MaskedStoreSDNode *N,
                                            unsigned OpNo) {
  assert(N->isUnindexed() && "Indexed masked store of vector?");
  SDValue Ch  = N->getChain();
  SDValue Ptr = N->getBasePtr();
  SDValue Offset = N->getOffset();
  assert(Offset.isUndef() && "Unexpected indexed masked store offset");
  SDValue Mask = N->getMask();
  SDValue Data = N->getValue();
  Align Alignment = N->getOriginalAlign();
  SDLoc DL(N);

  SDValue DataLo, DataHi;
  if (getTypeAction(Data.getValueType()) == TargetLowering::TypeSplitVector)
    // Split Data operand
    GetSplitVector(Data, DataLo, DataHi);
  else
    std::tie(DataLo, DataHi) = DAG.SplitVector(Data, DL);

  // Split Mask operand
  SDValue MaskLo, MaskHi;
  if (OpNo == 1 && Mask.getOpcode() == ISD::SETCC) {
    SplitVecRes_SETCC(Mask.getNode(), MaskLo, MaskHi);
  } else {
    if (getTypeAction(Mask.getValueType()) == TargetLowering::TypeSplitVector)
      GetSplitVector(Mask, MaskLo, MaskHi);
    else
      std::tie(MaskLo, MaskHi) = DAG.SplitVector(Mask, DL);
  }

  EVT MemoryVT = N->getMemoryVT();
  EVT LoMemVT, HiMemVT;
  bool HiIsEmpty = false;
  std::tie(LoMemVT, HiMemVT) =
      DAG.GetDependentSplitDestVTs(MemoryVT, DataLo.getValueType(), &HiIsEmpty);

  SDValue Lo, Hi, Res;
  MachineMemOperand *MMO = DAG.getMachineFunction().getMachineMemOperand(
      N->getPointerInfo(), MachineMemOperand::MOStore,
      MemoryLocation::UnknownSize, Alignment, N->getAAInfo(), N->getRanges());

  Lo = DAG.getMaskedStore(Ch, DL, DataLo, Ptr, Offset, MaskLo, LoMemVT, MMO,
                          N->getAddressingMode(), N->isTruncatingStore(),
                          N->isCompressingStore());

  if (HiIsEmpty) {
    // The hi masked store has zero storage size.
    // Only the lo masked store is needed.
    Res = Lo;
  } else {

    Ptr = TLI.IncrementMemoryAddress(Ptr, MaskLo, DL, LoMemVT, DAG,
                                     N->isCompressingStore());

    MachinePointerInfo MPI;
    if (LoMemVT.isScalableVector()) {
      Alignment = commonAlignment(
          Alignment, LoMemVT.getSizeInBits().getKnownMinSize() / 8);
      MPI = MachinePointerInfo(N->getPointerInfo().getAddrSpace());
    } else
      MPI = N->getPointerInfo().getWithOffset(
          LoMemVT.getStoreSize().getFixedSize());

    MMO = DAG.getMachineFunction().getMachineMemOperand(
        MPI, MachineMemOperand::MOStore, MemoryLocation::UnknownSize, Alignment,
        N->getAAInfo(), N->getRanges());

    Hi = DAG.getMaskedStore(Ch, DL, DataHi, Ptr, Offset, MaskHi, HiMemVT, MMO,
                            N->getAddressingMode(), N->isTruncatingStore(),
                            N->isCompressingStore());

    // Build a factor node to remember that this store is independent of the
    // other one.
    Res = DAG.getNode(ISD::TokenFactor, DL, MVT::Other, Lo, Hi);
  }

  return Res;
}

SDValue DAGTypeLegalizer::SplitVecOp_MSCATTER(MaskedScatterSDNode *N,
                                              unsigned OpNo) {
  SDValue Ch  = N->getChain();
  SDValue Ptr = N->getBasePtr();
  SDValue Mask = N->getMask();
  SDValue Index = N->getIndex();
  SDValue Scale = N->getScale();
  SDValue Data = N->getValue();
  EVT MemoryVT = N->getMemoryVT();
  Align Alignment = N->getOriginalAlign();
  SDLoc DL(N);

  // Split all operands

  EVT LoMemVT, HiMemVT;
  std::tie(LoMemVT, HiMemVT) = DAG.GetSplitDestVTs(MemoryVT);

  SDValue DataLo, DataHi;
  if (getTypeAction(Data.getValueType()) == TargetLowering::TypeSplitVector)
    // Split Data operand
    GetSplitVector(Data, DataLo, DataHi);
  else
    std::tie(DataLo, DataHi) = DAG.SplitVector(Data, DL);

  // Split Mask operand
  SDValue MaskLo, MaskHi;
  if (OpNo == 1 && Mask.getOpcode() == ISD::SETCC) {
    SplitVecRes_SETCC(Mask.getNode(), MaskLo, MaskHi);
  } else {
    if (getTypeAction(Mask.getValueType()) == TargetLowering::TypeSplitVector)
      GetSplitVector(Mask, MaskLo, MaskHi);
    else
      std::tie(MaskLo, MaskHi) = DAG.SplitVector(Mask, DL);
  }

  SDValue IndexHi, IndexLo;
  if (getTypeAction(Index.getValueType()) == TargetLowering::TypeSplitVector)
    GetSplitVector(Index, IndexLo, IndexHi);
  else
    std::tie(IndexLo, IndexHi) = DAG.SplitVector(Index, DL);

  SDValue Lo;
  MachineMemOperand *MMO = DAG.getMachineFunction().getMachineMemOperand(
      N->getPointerInfo(), MachineMemOperand::MOStore,
      MemoryLocation::UnknownSize, Alignment, N->getAAInfo(), N->getRanges());

  SDValue OpsLo[] = {Ch, DataLo, MaskLo, Ptr, IndexLo, Scale};
  Lo = DAG.getMaskedScatter(DAG.getVTList(MVT::Other), LoMemVT,
                            DL, OpsLo, MMO, N->getIndexType(),
                            N->isTruncatingStore());

  // The order of the Scatter operation after split is well defined. The "Hi"
  // part comes after the "Lo". So these two operations should be chained one
  // after another.
  SDValue OpsHi[] = {Lo, DataHi, MaskHi, Ptr, IndexHi, Scale};
  return DAG.getMaskedScatter(DAG.getVTList(MVT::Other), HiMemVT,
                              DL, OpsHi, MMO, N->getIndexType(),
                              N->isTruncatingStore());
}

SDValue DAGTypeLegalizer::SplitVecOp_STORE(StoreSDNode *N, unsigned OpNo) {
  assert(N->isUnindexed() && "Indexed store of vector?");
  assert(OpNo == 1 && "Can only split the stored value");
  SDLoc DL(N);

  bool isTruncating = N->isTruncatingStore();
  SDValue Ch  = N->getChain();
  SDValue Ptr = N->getBasePtr();
  EVT MemoryVT = N->getMemoryVT();
  Align Alignment = N->getOriginalAlign();
  MachineMemOperand::Flags MMOFlags = N->getMemOperand()->getFlags();
  AAMDNodes AAInfo = N->getAAInfo();
  SDValue Lo, Hi;
  GetSplitVector(N->getOperand(1), Lo, Hi);

  EVT LoMemVT, HiMemVT;
  std::tie(LoMemVT, HiMemVT) = DAG.GetSplitDestVTs(MemoryVT);

  // Scalarize if the split halves are not byte-sized.
  if (!LoMemVT.isByteSized() || !HiMemVT.isByteSized())
    return TLI.scalarizeVectorStore(N, DAG);

  if (isTruncating)
    Lo = DAG.getTruncStore(Ch, DL, Lo, Ptr, N->getPointerInfo(), LoMemVT,
                           Alignment, MMOFlags, AAInfo);
  else
    Lo = DAG.getStore(Ch, DL, Lo, Ptr, N->getPointerInfo(), Alignment, MMOFlags,
                      AAInfo);

  MachinePointerInfo MPI;
  IncrementPointer(N, LoMemVT, MPI, Ptr);

  if (isTruncating)
    Hi = DAG.getTruncStore(Ch, DL, Hi, Ptr, MPI,
                           HiMemVT, Alignment, MMOFlags, AAInfo);
  else
    Hi = DAG.getStore(Ch, DL, Hi, Ptr, MPI, Alignment, MMOFlags, AAInfo);

  return DAG.getNode(ISD::TokenFactor, DL, MVT::Other, Lo, Hi);
}

SDValue DAGTypeLegalizer::SplitVecOp_CONCAT_VECTORS(SDNode *N) {
  SDLoc DL(N);

  // The input operands all must have the same type, and we know the result
  // type is valid.  Convert this to a buildvector which extracts all the
  // input elements.
  // TODO: If the input elements are power-two vectors, we could convert this to
  // a new CONCAT_VECTORS node with elements that are half-wide.
  SmallVector<SDValue, 32> Elts;
  EVT EltVT = N->getValueType(0).getVectorElementType();
  for (const SDValue &Op : N->op_values()) {
    for (unsigned i = 0, e = Op.getValueType().getVectorNumElements();
         i != e; ++i) {
      Elts.push_back(DAG.getNode(ISD::EXTRACT_VECTOR_ELT, DL, EltVT, Op,
                                 DAG.getVectorIdxConstant(i, DL)));
    }
  }

  return DAG.getBuildVector(N->getValueType(0), DL, Elts);
}

SDValue DAGTypeLegalizer::SplitVecOp_TruncateHelper(SDNode *N) {
  // The result type is legal, but the input type is illegal.  If splitting
  // ends up with the result type of each half still being legal, just
  // do that.  If, however, that would result in an illegal result type,
  // we can try to get more clever with power-two vectors. Specifically,
  // split the input type, but also widen the result element size, then
  // concatenate the halves and truncate again.  For example, consider a target
  // where v8i8 is legal and v8i32 is not (ARM, which doesn't have 256-bit
  // vectors). To perform a "%res = v8i8 trunc v8i32 %in" we do:
  //   %inlo = v4i32 extract_subvector %in, 0
  //   %inhi = v4i32 extract_subvector %in, 4
  //   %lo16 = v4i16 trunc v4i32 %inlo
  //   %hi16 = v4i16 trunc v4i32 %inhi
  //   %in16 = v8i16 concat_vectors v4i16 %lo16, v4i16 %hi16
  //   %res = v8i8 trunc v8i16 %in16
  //
  // Without this transform, the original truncate would end up being
  // scalarized, which is pretty much always a last resort.
  unsigned OpNo = N->isStrictFPOpcode() ? 1 : 0;
  SDValue InVec = N->getOperand(OpNo);
  EVT InVT = InVec->getValueType(0);
  EVT OutVT = N->getValueType(0);
  ElementCount NumElements = OutVT.getVectorElementCount();
  bool IsFloat = OutVT.isFloatingPoint();

  unsigned InElementSize = InVT.getScalarSizeInBits();
  unsigned OutElementSize = OutVT.getScalarSizeInBits();

  // Determine the split output VT. If its legal we can just split dirctly.
  EVT LoOutVT, HiOutVT;
  std::tie(LoOutVT, HiOutVT) = DAG.GetSplitDestVTs(OutVT);
  assert(LoOutVT == HiOutVT && "Unequal split?");

  // If the input elements are only 1/2 the width of the result elements,
  // just use the normal splitting. Our trick only work if there's room
  // to split more than once.
  if (isTypeLegal(LoOutVT) ||
      InElementSize <= OutElementSize * 2)
    return SplitVecOp_UnaryOp(N);
  SDLoc DL(N);

  // Don't touch if this will be scalarized.
  EVT FinalVT = InVT;
  while (getTypeAction(FinalVT) == TargetLowering::TypeSplitVector)
    FinalVT = FinalVT.getHalfNumVectorElementsVT(*DAG.getContext());

  if (getTypeAction(FinalVT) == TargetLowering::TypeScalarizeVector)
    return SplitVecOp_UnaryOp(N);

  // Get the split input vector.
  SDValue InLoVec, InHiVec;
  GetSplitVector(InVec, InLoVec, InHiVec);

  // Truncate them to 1/2 the element size.
  //
  // This assumes the number of elements is a power of two; any vector that
  // isn't should be widened, not split.
  EVT HalfElementVT = IsFloat ?
    EVT::getFloatingPointVT(InElementSize/2) :
    EVT::getIntegerVT(*DAG.getContext(), InElementSize/2);
  EVT HalfVT = EVT::getVectorVT(*DAG.getContext(), HalfElementVT,
                                NumElements.divideCoefficientBy(2));

  SDValue HalfLo;
  SDValue HalfHi;
  SDValue Chain;
  if (N->isStrictFPOpcode()) {
    HalfLo = DAG.getNode(N->getOpcode(), DL, {HalfVT, MVT::Other},
                         {N->getOperand(0), InLoVec});
    HalfHi = DAG.getNode(N->getOpcode(), DL, {HalfVT, MVT::Other},
                         {N->getOperand(0), InHiVec});
    // Legalize the chain result - switch anything that used the old chain to
    // use the new one.
    Chain = DAG.getNode(ISD::TokenFactor, DL, MVT::Other, HalfLo.getValue(1),
                        HalfHi.getValue(1));
  } else {
    HalfLo = DAG.getNode(N->getOpcode(), DL, HalfVT, InLoVec);
    HalfHi = DAG.getNode(N->getOpcode(), DL, HalfVT, InHiVec);
  }

  // Concatenate them to get the full intermediate truncation result.
  EVT InterVT = EVT::getVectorVT(*DAG.getContext(), HalfElementVT, NumElements);
  SDValue InterVec = DAG.getNode(ISD::CONCAT_VECTORS, DL, InterVT, HalfLo,
                                 HalfHi);
  // Now finish up by truncating all the way down to the original result
  // type. This should normally be something that ends up being legal directly,
  // but in theory if a target has very wide vectors and an annoyingly
  // restricted set of legal types, this split can chain to build things up.

  if (N->isStrictFPOpcode()) {
    SDValue Res = DAG.getNode(
        ISD::STRICT_FP_ROUND, DL, {OutVT, MVT::Other},
        {Chain, InterVec,
         DAG.getTargetConstant(0, DL, TLI.getPointerTy(DAG.getDataLayout()))});
    // Relink the chain
    ReplaceValueWith(SDValue(N, 1), SDValue(Res.getNode(), 1));
    return Res;
  }

  return IsFloat
             ? DAG.getNode(ISD::FP_ROUND, DL, OutVT, InterVec,
                           DAG.getTargetConstant(
                               0, DL, TLI.getPointerTy(DAG.getDataLayout())))
             : DAG.getNode(ISD::TRUNCATE, DL, OutVT, InterVec);
}

SDValue DAGTypeLegalizer::SplitVecOp_VSETCC(SDNode *N) {
  assert(N->getValueType(0).isVector() &&
         N->getOperand(0).getValueType().isVector() &&
         "Operand types must be vectors");
  // The result has a legal vector type, but the input needs splitting.
  SDValue Lo0, Hi0, Lo1, Hi1, LoRes, HiRes;
  SDLoc DL(N);
  GetSplitVector(N->getOperand(0), Lo0, Hi0);
  GetSplitVector(N->getOperand(1), Lo1, Hi1);
  auto PartEltCnt = Lo0.getValueType().getVectorElementCount();

  LLVMContext &Context = *DAG.getContext();
  EVT PartResVT = EVT::getVectorVT(Context, MVT::i1, PartEltCnt);
  EVT WideResVT = EVT::getVectorVT(Context, MVT::i1, PartEltCnt*2);

  LoRes = DAG.getNode(ISD::SETCC, DL, PartResVT, Lo0, Lo1, N->getOperand(2));
  HiRes = DAG.getNode(ISD::SETCC, DL, PartResVT, Hi0, Hi1, N->getOperand(2));
  SDValue Con = DAG.getNode(ISD::CONCAT_VECTORS, DL, WideResVT, LoRes, HiRes);

  EVT OpVT = N->getOperand(0).getValueType();
  ISD::NodeType ExtendCode =
      TargetLowering::getExtendForContent(TLI.getBooleanContents(OpVT));
  return DAG.getNode(ExtendCode, DL, N->getValueType(0), Con);
}


SDValue DAGTypeLegalizer::SplitVecOp_FP_ROUND(SDNode *N) {
  // The result has a legal vector type, but the input needs splitting.
  EVT ResVT = N->getValueType(0);
  SDValue Lo, Hi;
  SDLoc DL(N);
  GetSplitVector(N->getOperand(N->isStrictFPOpcode() ? 1 : 0), Lo, Hi);
  EVT InVT = Lo.getValueType();

  EVT OutVT = EVT::getVectorVT(*DAG.getContext(), ResVT.getVectorElementType(),
                               InVT.getVectorElementCount());

  if (N->isStrictFPOpcode()) {
    Lo = DAG.getNode(N->getOpcode(), DL, { OutVT, MVT::Other }, 
                     { N->getOperand(0), Lo, N->getOperand(2) });
    Hi = DAG.getNode(N->getOpcode(), DL, { OutVT, MVT::Other }, 
                     { N->getOperand(0), Hi, N->getOperand(2) });
    // Legalize the chain result - switch anything that used the old chain to
    // use the new one.
    SDValue NewChain = DAG.getNode(ISD::TokenFactor, DL, MVT::Other, 
                                   Lo.getValue(1), Hi.getValue(1));
    ReplaceValueWith(SDValue(N, 1), NewChain);
  } else {
    Lo = DAG.getNode(ISD::FP_ROUND, DL, OutVT, Lo, N->getOperand(1));
    Hi = DAG.getNode(ISD::FP_ROUND, DL, OutVT, Hi, N->getOperand(1));
  }

  return DAG.getNode(ISD::CONCAT_VECTORS, DL, ResVT, Lo, Hi);
}

SDValue DAGTypeLegalizer::SplitVecOp_FCOPYSIGN(SDNode *N) {
  // The result (and the first input) has a legal vector type, but the second
  // input needs splitting.
  return DAG.UnrollVectorOp(N, N->getValueType(0).getVectorNumElements());
}

SDValue DAGTypeLegalizer::SplitVecOp_FP_TO_XINT_SAT(SDNode *N) {
  EVT ResVT = N->getValueType(0);
  SDValue Lo, Hi;
  SDLoc dl(N);
  GetSplitVector(N->getOperand(0), Lo, Hi);
  EVT InVT = Lo.getValueType();

  EVT NewResVT =
      EVT::getVectorVT(*DAG.getContext(), ResVT.getVectorElementType(),
                       InVT.getVectorElementCount());

  Lo = DAG.getNode(N->getOpcode(), dl, NewResVT, Lo, N->getOperand(1));
  Hi = DAG.getNode(N->getOpcode(), dl, NewResVT, Hi, N->getOperand(1));

  return DAG.getNode(ISD::CONCAT_VECTORS, dl, ResVT, Lo, Hi);
}

//===----------------------------------------------------------------------===//
//  Result Vector Widening
//===----------------------------------------------------------------------===//

void DAGTypeLegalizer::WidenVectorResult(SDNode *N, unsigned ResNo) {
  LLVM_DEBUG(dbgs() << "Widen node result " << ResNo << ": "; N->dump(&DAG);
             dbgs() << "\n");

  // See if the target wants to custom widen this node.
  if (CustomWidenLowerNode(N, N->getValueType(ResNo)))
    return;

  SDValue Res = SDValue();
  switch (N->getOpcode()) {
  default:
#ifndef NDEBUG
    dbgs() << "WidenVectorResult #" << ResNo << ": ";
    N->dump(&DAG);
    dbgs() << "\n";
#endif
    llvm_unreachable("Do not know how to widen the result of this operator!");

  case ISD::MERGE_VALUES:      Res = WidenVecRes_MERGE_VALUES(N, ResNo); break;
  case ISD::BITCAST:           Res = WidenVecRes_BITCAST(N); break;
  case ISD::BUILD_VECTOR:      Res = WidenVecRes_BUILD_VECTOR(N); break;
  case ISD::CONCAT_VECTORS:    Res = WidenVecRes_CONCAT_VECTORS(N); break;
  case ISD::INSERT_SUBVECTOR:
    Res = WidenVecRes_INSERT_SUBVECTOR(N);
    break;
  case ISD::EXTRACT_SUBVECTOR: Res = WidenVecRes_EXTRACT_SUBVECTOR(N); break;
  case ISD::INSERT_VECTOR_ELT: Res = WidenVecRes_INSERT_VECTOR_ELT(N); break;
  case ISD::LOAD:              Res = WidenVecRes_LOAD(N); break;
  case ISD::SPLAT_VECTOR:
  case ISD::SCALAR_TO_VECTOR:
    Res = WidenVecRes_ScalarOp(N);
    break;
  case ISD::SIGN_EXTEND_INREG: Res = WidenVecRes_InregOp(N); break;
  case ISD::VSELECT:
  case ISD::SELECT:            Res = WidenVecRes_SELECT(N); break;
  case ISD::SELECT_CC:         Res = WidenVecRes_SELECT_CC(N); break;
  case ISD::SETCC:             Res = WidenVecRes_SETCC(N); break;
  case ISD::UNDEF:             Res = WidenVecRes_UNDEF(N); break;
  case ISD::VECTOR_SHUFFLE:
    Res = WidenVecRes_VECTOR_SHUFFLE(cast<ShuffleVectorSDNode>(N));
    break;
  case ISD::MLOAD:
    Res = WidenVecRes_MLOAD(cast<MaskedLoadSDNode>(N));
    break;
  case ISD::MGATHER:
    Res = WidenVecRes_MGATHER(cast<MaskedGatherSDNode>(N));
    break;

  case ISD::ADD:
  case ISD::AND:
  case ISD::MUL:
  case ISD::MULHS:
  case ISD::MULHU:
  case ISD::OR:
  case ISD::SUB:
  case ISD::XOR:
  case ISD::SHL:
  case ISD::SRA:
  case ISD::SRL:
  case ISD::FMINNUM:
  case ISD::FMAXNUM:
  case ISD::FMINIMUM:
  case ISD::FMAXIMUM:
  case ISD::SMIN:
  case ISD::SMAX:
  case ISD::UMIN:
  case ISD::UMAX:
  case ISD::UADDSAT:
  case ISD::SADDSAT:
  case ISD::USUBSAT:
  case ISD::SSUBSAT:
  case ISD::SSHLSAT:
  case ISD::USHLSAT:
  case ISD::ROTL:
  case ISD::ROTR:
    Res = WidenVecRes_Binary(N, /*IsVP*/ false);
    break;

  case ISD::FADD:
  case ISD::FMUL:
  case ISD::FPOW:
  case ISD::FSUB:
  case ISD::FDIV:
  case ISD::FREM:
  case ISD::SDIV:
  case ISD::UDIV:
  case ISD::SREM:
  case ISD::UREM:
    Res = WidenVecRes_BinaryCanTrap(N);
    break;

  case ISD::SMULFIX:
  case ISD::SMULFIXSAT:
  case ISD::UMULFIX:
  case ISD::UMULFIXSAT:
    // These are binary operations, but with an extra operand that shouldn't
    // be widened (the scale).
    Res = WidenVecRes_BinaryWithExtraScalarOp(N);
    break;

#define DAG_INSTRUCTION(NAME, NARG, ROUND_MODE, INTRINSIC, DAGN)               \
  case ISD::STRICT_##DAGN:
#include "llvm/IR/ConstrainedOps.def"
    Res = WidenVecRes_StrictFP(N);
    break;

  case ISD::UADDO:
  case ISD::SADDO:
  case ISD::USUBO:
  case ISD::SSUBO:
  case ISD::UMULO:
  case ISD::SMULO:
    Res = WidenVecRes_OverflowOp(N, ResNo);
    break;

  case ISD::FCOPYSIGN:
    Res = WidenVecRes_FCOPYSIGN(N);
    break;

  case ISD::FPOWI:
    Res = WidenVecRes_POWI(N);
    break;

  case ISD::ANY_EXTEND_VECTOR_INREG:
  case ISD::SIGN_EXTEND_VECTOR_INREG:
  case ISD::ZERO_EXTEND_VECTOR_INREG:
    Res = WidenVecRes_EXTEND_VECTOR_INREG(N);
    break;

  case ISD::ANY_EXTEND:
  case ISD::FP_EXTEND:
  case ISD::FP_ROUND:
  case ISD::FP_TO_SINT:
  case ISD::FP_TO_UINT:
  case ISD::SIGN_EXTEND:
  case ISD::SINT_TO_FP:
  case ISD::TRUNCATE:
  case ISD::UINT_TO_FP:
  case ISD::ZERO_EXTEND:
    Res = WidenVecRes_Convert(N);
    break;

  case ISD::FP_TO_SINT_SAT:
  case ISD::FP_TO_UINT_SAT:
    Res = WidenVecRes_FP_TO_XINT_SAT(N);
    break;

  case ISD::FABS:
  case ISD::FCEIL:
  case ISD::FCOS:
  case ISD::FEXP:
  case ISD::FEXP2:
  case ISD::FFLOOR:
  case ISD::FLOG:
  case ISD::FLOG10:
  case ISD::FLOG2:
  case ISD::FNEARBYINT:
  case ISD::FRINT:
  case ISD::FROUND:
  case ISD::FROUNDEVEN:
  case ISD::FSIN:
  case ISD::FSQRT:
  case ISD::FTRUNC: {
    // We're going to widen this vector op to a legal type by padding with undef
    // elements. If the wide vector op is eventually going to be expanded to
    // scalar libcalls, then unroll into scalar ops now to avoid unnecessary
    // libcalls on the undef elements.
    EVT VT = N->getValueType(0);
    EVT WideVecVT = TLI.getTypeToTransformTo(*DAG.getContext(), VT);
    if (!TLI.isOperationLegalOrCustom(N->getOpcode(), WideVecVT) &&
        TLI.isOperationExpand(N->getOpcode(), VT.getScalarType())) {
      Res = DAG.UnrollVectorOp(N, WideVecVT.getVectorNumElements());
      break;
    }
  }
  // If the target has custom/legal support for the scalar FP intrinsic ops
  // (they are probably not destined to become libcalls), then widen those like
  // any other unary ops.
  LLVM_FALLTHROUGH;

  case ISD::ABS:
  case ISD::BITREVERSE:
  case ISD::BSWAP:
  case ISD::CTLZ:
  case ISD::CTLZ_ZERO_UNDEF:
  case ISD::CTPOP:
  case ISD::CTTZ:
  case ISD::CTTZ_ZERO_UNDEF:
  case ISD::FNEG:
  case ISD::FREEZE:
  case ISD::ARITH_FENCE:
  case ISD::FCANONICALIZE:
    Res = WidenVecRes_Unary(N);
    break;
  case ISD::FMA:
  case ISD::FSHL:
  case ISD::FSHR:
    Res = WidenVecRes_Ternary(N);
    break;
  case ISD::VP_ADD:
  case ISD::VP_AND:
  case ISD::VP_MUL:
  case ISD::VP_OR:
  case ISD::VP_SUB:
  case ISD::VP_XOR:
  case ISD::VP_SHL:
  case ISD::VP_LSHR:
  case ISD::VP_ASHR:
  case ISD::VP_SDIV:
  case ISD::VP_UDIV:
  case ISD::VP_SREM:
  case ISD::VP_UREM:
  case ISD::VP_FADD:
  case ISD::VP_FSUB:
  case ISD::VP_FMUL:
  case ISD::VP_FDIV:
  case ISD::VP_FREM:
    // Vector-predicated binary op widening. Note that -- unlike the
    // unpredicated versions -- we don't have to worry about trapping on
    // operations like UDIV, FADD, etc., as we pass on the original vector
    // length parameter. This means the widened elements containing garbage
    // aren't active.
    Res = WidenVecRes_Binary(N, /*IsVP*/ true);
    break;
  }

  // If Res is null, the sub-method took care of registering the result.
  if (Res.getNode())
    SetWidenedVector(SDValue(N, ResNo), Res);
}

SDValue DAGTypeLegalizer::WidenVecRes_Ternary(SDNode *N) {
  // Ternary op widening.
  SDLoc dl(N);
  EVT WidenVT = TLI.getTypeToTransformTo(*DAG.getContext(), N->getValueType(0));
  SDValue InOp1 = GetWidenedVector(N->getOperand(0));
  SDValue InOp2 = GetWidenedVector(N->getOperand(1));
  SDValue InOp3 = GetWidenedVector(N->getOperand(2));
  return DAG.getNode(N->getOpcode(), dl, WidenVT, InOp1, InOp2, InOp3);
}

SDValue DAGTypeLegalizer::WidenVecRes_Binary(SDNode *N, bool IsVP) {
  // Binary op widening.
  SDLoc dl(N);
  EVT WidenVT = TLI.getTypeToTransformTo(*DAG.getContext(), N->getValueType(0));
  SDValue InOp1 = GetWidenedVector(N->getOperand(0));
  SDValue InOp2 = GetWidenedVector(N->getOperand(1));
  if (!IsVP)
    return DAG.getNode(N->getOpcode(), dl, WidenVT, InOp1, InOp2,
                       N->getFlags());
  // For VP operations, we must also widen the mask. Note that the mask type
  // may not actually need widening, leading it be split along with the VP
  // operation.
  // FIXME: This could lead to an infinite split/widen loop. We only handle the
  // case where the mask needs widening to an identically-sized type as the
  // vector inputs.
  SDValue Mask = N->getOperand(2);
  assert(getTypeAction(Mask.getValueType()) ==
             TargetLowering::TypeWidenVector &&
         "Unable to widen binary VP op");
  Mask = GetWidenedVector(Mask);
  assert(Mask.getValueType().getVectorElementCount() ==
             WidenVT.getVectorElementCount() &&
         "Unable to widen binary VP op");
  return DAG.getNode(N->getOpcode(), dl, WidenVT,
                     {InOp1, InOp2, Mask, N->getOperand(3)}, N->getFlags());
}

SDValue DAGTypeLegalizer::WidenVecRes_BinaryWithExtraScalarOp(SDNode *N) {
  // Binary op widening, but with an extra operand that shouldn't be widened.
  SDLoc dl(N);
  EVT WidenVT = TLI.getTypeToTransformTo(*DAG.getContext(), N->getValueType(0));
  SDValue InOp1 = GetWidenedVector(N->getOperand(0));
  SDValue InOp2 = GetWidenedVector(N->getOperand(1));
  SDValue InOp3 = N->getOperand(2);
  return DAG.getNode(N->getOpcode(), dl, WidenVT, InOp1, InOp2, InOp3,
                     N->getFlags());
}

// Given a vector of operations that have been broken up to widen, see
// if we can collect them together into the next widest legal VT. This
// implementation is trap-safe.
static SDValue CollectOpsToWiden(SelectionDAG &DAG, const TargetLowering &TLI,
                                 SmallVectorImpl<SDValue> &ConcatOps,
                                 unsigned ConcatEnd, EVT VT, EVT MaxVT,
                                 EVT WidenVT) {
  // Check to see if we have a single operation with the widen type.
  if (ConcatEnd == 1) {
    VT = ConcatOps[0].getValueType();
    if (VT == WidenVT)
      return ConcatOps[0];
  }

  SDLoc dl(ConcatOps[0]);
  EVT WidenEltVT = WidenVT.getVectorElementType();

  // while (Some element of ConcatOps is not of type MaxVT) {
  //   From the end of ConcatOps, collect elements of the same type and put
  //   them into an op of the next larger supported type
  // }
  while (ConcatOps[ConcatEnd-1].getValueType() != MaxVT) {
    int Idx = ConcatEnd - 1;
    VT = ConcatOps[Idx--].getValueType();
    while (Idx >= 0 && ConcatOps[Idx].getValueType() == VT)
      Idx--;

    int NextSize = VT.isVector() ? VT.getVectorNumElements() : 1;
    EVT NextVT;
    do {
      NextSize *= 2;
      NextVT = EVT::getVectorVT(*DAG.getContext(), WidenEltVT, NextSize);
    } while (!TLI.isTypeLegal(NextVT));

    if (!VT.isVector()) {
      // Scalar type, create an INSERT_VECTOR_ELEMENT of type NextVT
      SDValue VecOp = DAG.getUNDEF(NextVT);
      unsigned NumToInsert = ConcatEnd - Idx - 1;
      for (unsigned i = 0, OpIdx = Idx+1; i < NumToInsert; i++, OpIdx++) {
        VecOp = DAG.getNode(ISD::INSERT_VECTOR_ELT, dl, NextVT, VecOp,
                            ConcatOps[OpIdx], DAG.getVectorIdxConstant(i, dl));
      }
      ConcatOps[Idx+1] = VecOp;
      ConcatEnd = Idx + 2;
    } else {
      // Vector type, create a CONCAT_VECTORS of type NextVT
      SDValue undefVec = DAG.getUNDEF(VT);
      unsigned OpsToConcat = NextSize/VT.getVectorNumElements();
      SmallVector<SDValue, 16> SubConcatOps(OpsToConcat);
      unsigned RealVals = ConcatEnd - Idx - 1;
      unsigned SubConcatEnd = 0;
      unsigned SubConcatIdx = Idx + 1;
      while (SubConcatEnd < RealVals)
        SubConcatOps[SubConcatEnd++] = ConcatOps[++Idx];
      while (SubConcatEnd < OpsToConcat)
        SubConcatOps[SubConcatEnd++] = undefVec;
      ConcatOps[SubConcatIdx] = DAG.getNode(ISD::CONCAT_VECTORS, dl,
                                            NextVT, SubConcatOps);
      ConcatEnd = SubConcatIdx + 1;
    }
  }

  // Check to see if we have a single operation with the widen type.
  if (ConcatEnd == 1) {
    VT = ConcatOps[0].getValueType();
    if (VT == WidenVT)
      return ConcatOps[0];
  }

  // add undefs of size MaxVT until ConcatOps grows to length of WidenVT
  unsigned NumOps = WidenVT.getVectorNumElements()/MaxVT.getVectorNumElements();
  if (NumOps != ConcatEnd ) {
    SDValue UndefVal = DAG.getUNDEF(MaxVT);
    for (unsigned j = ConcatEnd; j < NumOps; ++j)
      ConcatOps[j] = UndefVal;
  }
  return DAG.getNode(ISD::CONCAT_VECTORS, dl, WidenVT,
                     makeArrayRef(ConcatOps.data(), NumOps));
}

SDValue DAGTypeLegalizer::WidenVecRes_BinaryCanTrap(SDNode *N) {
  // Binary op widening for operations that can trap.
  unsigned Opcode = N->getOpcode();
  SDLoc dl(N);
  EVT WidenVT = TLI.getTypeToTransformTo(*DAG.getContext(), N->getValueType(0));
  EVT WidenEltVT = WidenVT.getVectorElementType();
  EVT VT = WidenVT;
  unsigned NumElts =  VT.getVectorNumElements();
  const SDNodeFlags Flags = N->getFlags();
  while (!TLI.isTypeLegal(VT) && NumElts != 1) {
    NumElts = NumElts / 2;
    VT = EVT::getVectorVT(*DAG.getContext(), WidenEltVT, NumElts);
  }

  if (NumElts != 1 && !TLI.canOpTrap(N->getOpcode(), VT)) {
    // Operation doesn't trap so just widen as normal.
    SDValue InOp1 = GetWidenedVector(N->getOperand(0));
    SDValue InOp2 = GetWidenedVector(N->getOperand(1));
    return DAG.getNode(N->getOpcode(), dl, WidenVT, InOp1, InOp2, Flags);
  }

  // No legal vector version so unroll the vector operation and then widen.
  if (NumElts == 1)
    return DAG.UnrollVectorOp(N, WidenVT.getVectorNumElements());

  // Since the operation can trap, apply operation on the original vector.
  EVT MaxVT = VT;
  SDValue InOp1 = GetWidenedVector(N->getOperand(0));
  SDValue InOp2 = GetWidenedVector(N->getOperand(1));
  unsigned CurNumElts = N->getValueType(0).getVectorNumElements();

  SmallVector<SDValue, 16> ConcatOps(CurNumElts);
  unsigned ConcatEnd = 0;  // Current ConcatOps index.
  int Idx = 0;        // Current Idx into input vectors.

  // NumElts := greatest legal vector size (at most WidenVT)
  // while (orig. vector has unhandled elements) {
  //   take munches of size NumElts from the beginning and add to ConcatOps
  //   NumElts := next smaller supported vector size or 1
  // }
  while (CurNumElts != 0) {
    while (CurNumElts >= NumElts) {
      SDValue EOp1 = DAG.getNode(ISD::EXTRACT_SUBVECTOR, dl, VT, InOp1,
                                 DAG.getVectorIdxConstant(Idx, dl));
      SDValue EOp2 = DAG.getNode(ISD::EXTRACT_SUBVECTOR, dl, VT, InOp2,
                                 DAG.getVectorIdxConstant(Idx, dl));
      ConcatOps[ConcatEnd++] = DAG.getNode(Opcode, dl, VT, EOp1, EOp2, Flags);
      Idx += NumElts;
      CurNumElts -= NumElts;
    }
    do {
      NumElts = NumElts / 2;
      VT = EVT::getVectorVT(*DAG.getContext(), WidenEltVT, NumElts);
    } while (!TLI.isTypeLegal(VT) && NumElts != 1);

    if (NumElts == 1) {
      for (unsigned i = 0; i != CurNumElts; ++i, ++Idx) {
        SDValue EOp1 = DAG.getNode(ISD::EXTRACT_VECTOR_ELT, dl, WidenEltVT,
                                   InOp1, DAG.getVectorIdxConstant(Idx, dl));
        SDValue EOp2 = DAG.getNode(ISD::EXTRACT_VECTOR_ELT, dl, WidenEltVT,
                                   InOp2, DAG.getVectorIdxConstant(Idx, dl));
        ConcatOps[ConcatEnd++] = DAG.getNode(Opcode, dl, WidenEltVT,
                                             EOp1, EOp2, Flags);
      }
      CurNumElts = 0;
    }
  }

  return CollectOpsToWiden(DAG, TLI, ConcatOps, ConcatEnd, VT, MaxVT, WidenVT);
}

SDValue DAGTypeLegalizer::WidenVecRes_StrictFP(SDNode *N) {
  switch (N->getOpcode()) {
  case ISD::STRICT_FSETCC:
  case ISD::STRICT_FSETCCS:
    return WidenVecRes_STRICT_FSETCC(N);
  case ISD::STRICT_FP_EXTEND:
  case ISD::STRICT_FP_ROUND:
  case ISD::STRICT_FP_TO_SINT:
  case ISD::STRICT_FP_TO_UINT:
  case ISD::STRICT_SINT_TO_FP:
  case ISD::STRICT_UINT_TO_FP:
   return WidenVecRes_Convert_StrictFP(N);
  default:
    break;
  }

  // StrictFP op widening for operations that can trap.
  unsigned NumOpers = N->getNumOperands();
  unsigned Opcode = N->getOpcode();
  SDLoc dl(N);
  EVT WidenVT = TLI.getTypeToTransformTo(*DAG.getContext(), N->getValueType(0));
  EVT WidenEltVT = WidenVT.getVectorElementType();
  EVT VT = WidenVT;
  unsigned NumElts = VT.getVectorNumElements();
  while (!TLI.isTypeLegal(VT) && NumElts != 1) {
    NumElts = NumElts / 2;
    VT = EVT::getVectorVT(*DAG.getContext(), WidenEltVT, NumElts);
  }

  // No legal vector version so unroll the vector operation and then widen.
  if (NumElts == 1)
    return UnrollVectorOp_StrictFP(N, WidenVT.getVectorNumElements());

  // Since the operation can trap, apply operation on the original vector.
  EVT MaxVT = VT;
  SmallVector<SDValue, 4> InOps;
  unsigned CurNumElts = N->getValueType(0).getVectorNumElements();

  SmallVector<SDValue, 16> ConcatOps(CurNumElts);
  SmallVector<SDValue, 16> Chains;
  unsigned ConcatEnd = 0;  // Current ConcatOps index.
  int Idx = 0;        // Current Idx into input vectors.

  // The Chain is the first operand.
  InOps.push_back(N->getOperand(0));

  // Now process the remaining operands.
  for (unsigned i = 1; i < NumOpers; ++i) {
    SDValue Oper = N->getOperand(i);

    if (Oper.getValueType().isVector()) {
      assert(Oper.getValueType() == N->getValueType(0) && 
             "Invalid operand type to widen!");
      Oper = GetWidenedVector(Oper);
    }

    InOps.push_back(Oper);
  }

  // NumElts := greatest legal vector size (at most WidenVT)
  // while (orig. vector has unhandled elements) {
  //   take munches of size NumElts from the beginning and add to ConcatOps
  //   NumElts := next smaller supported vector size or 1
  // }
  while (CurNumElts != 0) {
    while (CurNumElts >= NumElts) {
      SmallVector<SDValue, 4> EOps;

      for (unsigned i = 0; i < NumOpers; ++i) {
        SDValue Op = InOps[i];

        if (Op.getValueType().isVector())
          Op = DAG.getNode(ISD::EXTRACT_SUBVECTOR, dl, VT, Op,
                           DAG.getVectorIdxConstant(Idx, dl));

        EOps.push_back(Op);
      }

      EVT OperVT[] = {VT, MVT::Other};
      SDValue Oper = DAG.getNode(Opcode, dl, OperVT, EOps);
      ConcatOps[ConcatEnd++] = Oper;
      Chains.push_back(Oper.getValue(1));
      Idx += NumElts;
      CurNumElts -= NumElts;
    }
    do {
      NumElts = NumElts / 2;
      VT = EVT::getVectorVT(*DAG.getContext(), WidenEltVT, NumElts);
    } while (!TLI.isTypeLegal(VT) && NumElts != 1);

    if (NumElts == 1) {
      for (unsigned i = 0; i != CurNumElts; ++i, ++Idx) {
        SmallVector<SDValue, 4> EOps;

        for (unsigned i = 0; i < NumOpers; ++i) {
          SDValue Op = InOps[i];

          if (Op.getValueType().isVector())
            Op = DAG.getNode(ISD::EXTRACT_VECTOR_ELT, dl, WidenEltVT, Op,
                             DAG.getVectorIdxConstant(Idx, dl));

          EOps.push_back(Op);
        }

        EVT WidenVT[] = {WidenEltVT, MVT::Other}; 
        SDValue Oper = DAG.getNode(Opcode, dl, WidenVT, EOps);
        ConcatOps[ConcatEnd++] = Oper;
        Chains.push_back(Oper.getValue(1));
      }
      CurNumElts = 0;
    }
  }

  // Build a factor node to remember all the Ops that have been created.
  SDValue NewChain;
  if (Chains.size() == 1)
    NewChain = Chains[0];
  else
    NewChain = DAG.getNode(ISD::TokenFactor, dl, MVT::Other, Chains);
  ReplaceValueWith(SDValue(N, 1), NewChain);

  return CollectOpsToWiden(DAG, TLI, ConcatOps, ConcatEnd, VT, MaxVT, WidenVT);
}

SDValue DAGTypeLegalizer::WidenVecRes_OverflowOp(SDNode *N, unsigned ResNo) {
  SDLoc DL(N);
  EVT ResVT = N->getValueType(0);
  EVT OvVT = N->getValueType(1);
  EVT WideResVT, WideOvVT;
  SDValue WideLHS, WideRHS;

  // TODO: This might result in a widen/split loop.
  if (ResNo == 0) {
    WideResVT = TLI.getTypeToTransformTo(*DAG.getContext(), ResVT);
    WideOvVT = EVT::getVectorVT(
        *DAG.getContext(), OvVT.getVectorElementType(),
        WideResVT.getVectorNumElements());

    WideLHS = GetWidenedVector(N->getOperand(0));
    WideRHS = GetWidenedVector(N->getOperand(1));
  } else {
    WideOvVT = TLI.getTypeToTransformTo(*DAG.getContext(), OvVT);
    WideResVT = EVT::getVectorVT(
        *DAG.getContext(), ResVT.getVectorElementType(),
        WideOvVT.getVectorNumElements());

    SDValue Zero = DAG.getVectorIdxConstant(0, DL);
    WideLHS = DAG.getNode(
        ISD::INSERT_SUBVECTOR, DL, WideResVT, DAG.getUNDEF(WideResVT),
        N->getOperand(0), Zero);
    WideRHS = DAG.getNode(
        ISD::INSERT_SUBVECTOR, DL, WideResVT, DAG.getUNDEF(WideResVT),
        N->getOperand(1), Zero);
  }

  SDVTList WideVTs = DAG.getVTList(WideResVT, WideOvVT);
  SDNode *WideNode = DAG.getNode(
      N->getOpcode(), DL, WideVTs, WideLHS, WideRHS).getNode();

  // Replace the other vector result not being explicitly widened here.
  unsigned OtherNo = 1 - ResNo;
  EVT OtherVT = N->getValueType(OtherNo);
  if (getTypeAction(OtherVT) == TargetLowering::TypeWidenVector) {
    SetWidenedVector(SDValue(N, OtherNo), SDValue(WideNode, OtherNo));
  } else {
    SDValue Zero = DAG.getVectorIdxConstant(0, DL);
    SDValue OtherVal = DAG.getNode(
        ISD::EXTRACT_SUBVECTOR, DL, OtherVT, SDValue(WideNode, OtherNo), Zero);
    ReplaceValueWith(SDValue(N, OtherNo), OtherVal);
  }

  return SDValue(WideNode, ResNo);
}

SDValue DAGTypeLegalizer::WidenVecRes_Convert(SDNode *N) {
  LLVMContext &Ctx = *DAG.getContext();
  SDValue InOp = N->getOperand(0);
  SDLoc DL(N);

  EVT WidenVT = TLI.getTypeToTransformTo(Ctx, N->getValueType(0));
  ElementCount WidenEC = WidenVT.getVectorElementCount();

  EVT InVT = InOp.getValueType();

  unsigned Opcode = N->getOpcode();
  const SDNodeFlags Flags = N->getFlags();

  // Handle the case of ZERO_EXTEND where the promoted InVT element size does
  // not equal that of WidenVT.
  if (N->getOpcode() == ISD::ZERO_EXTEND &&
      getTypeAction(InVT) == TargetLowering::TypePromoteInteger &&
      TLI.getTypeToTransformTo(Ctx, InVT).getScalarSizeInBits() !=
      WidenVT.getScalarSizeInBits()) {
    InOp = ZExtPromotedInteger(InOp);
    InVT = InOp.getValueType();
    if (WidenVT.getScalarSizeInBits() < InVT.getScalarSizeInBits())
      Opcode = ISD::TRUNCATE;
  }

  EVT InEltVT = InVT.getVectorElementType();
  EVT InWidenVT = EVT::getVectorVT(Ctx, InEltVT, WidenEC);
  ElementCount InVTEC = InVT.getVectorElementCount();

  if (getTypeAction(InVT) == TargetLowering::TypeWidenVector) {
    InOp = GetWidenedVector(N->getOperand(0));
    InVT = InOp.getValueType();
    InVTEC = InVT.getVectorElementCount();
    if (InVTEC == WidenEC) {
      if (N->getNumOperands() == 1)
        return DAG.getNode(Opcode, DL, WidenVT, InOp);
      return DAG.getNode(Opcode, DL, WidenVT, InOp, N->getOperand(1), Flags);
    }
    if (WidenVT.getSizeInBits() == InVT.getSizeInBits()) {
      // If both input and result vector types are of same width, extend
      // operations should be done with SIGN/ZERO_EXTEND_VECTOR_INREG, which
      // accepts fewer elements in the result than in the input.
      if (Opcode == ISD::ANY_EXTEND)
        return DAG.getNode(ISD::ANY_EXTEND_VECTOR_INREG, DL, WidenVT, InOp);
      if (Opcode == ISD::SIGN_EXTEND)
        return DAG.getNode(ISD::SIGN_EXTEND_VECTOR_INREG, DL, WidenVT, InOp);
      if (Opcode == ISD::ZERO_EXTEND)
        return DAG.getNode(ISD::ZERO_EXTEND_VECTOR_INREG, DL, WidenVT, InOp);
    }
  }

  if (TLI.isTypeLegal(InWidenVT)) {
    // Because the result and the input are different vector types, widening
    // the result could create a legal type but widening the input might make
    // it an illegal type that might lead to repeatedly splitting the input
    // and then widening it. To avoid this, we widen the input only if
    // it results in a legal type.
    if (WidenEC.isKnownMultipleOf(InVTEC.getKnownMinValue())) {
      // Widen the input and call convert on the widened input vector.
      unsigned NumConcat =
          WidenEC.getKnownMinValue() / InVTEC.getKnownMinValue();
      SmallVector<SDValue, 16> Ops(NumConcat, DAG.getUNDEF(InVT));
      Ops[0] = InOp;
      SDValue InVec = DAG.getNode(ISD::CONCAT_VECTORS, DL, InWidenVT, Ops);
      if (N->getNumOperands() == 1)
        return DAG.getNode(Opcode, DL, WidenVT, InVec);
      return DAG.getNode(Opcode, DL, WidenVT, InVec, N->getOperand(1), Flags);
    }

    if (InVTEC.isKnownMultipleOf(WidenEC.getKnownMinValue())) {
      SDValue InVal = DAG.getNode(ISD::EXTRACT_SUBVECTOR, DL, InWidenVT, InOp,
                                  DAG.getVectorIdxConstant(0, DL));
      // Extract the input and convert the shorten input vector.
      if (N->getNumOperands() == 1)
        return DAG.getNode(Opcode, DL, WidenVT, InVal);
      return DAG.getNode(Opcode, DL, WidenVT, InVal, N->getOperand(1), Flags);
    }
  }

  // Otherwise unroll into some nasty scalar code and rebuild the vector.
  EVT EltVT = WidenVT.getVectorElementType();
  SmallVector<SDValue, 16> Ops(WidenEC.getFixedValue(), DAG.getUNDEF(EltVT));
  // Use the original element count so we don't do more scalar opts than
  // necessary.
  unsigned MinElts = N->getValueType(0).getVectorNumElements();
  for (unsigned i=0; i < MinElts; ++i) {
    SDValue Val = DAG.getNode(ISD::EXTRACT_VECTOR_ELT, DL, InEltVT, InOp,
                              DAG.getVectorIdxConstant(i, DL));
    if (N->getNumOperands() == 1)
      Ops[i] = DAG.getNode(Opcode, DL, EltVT, Val);
    else
      Ops[i] = DAG.getNode(Opcode, DL, EltVT, Val, N->getOperand(1), Flags);
  }

  return DAG.getBuildVector(WidenVT, DL, Ops);
}

SDValue DAGTypeLegalizer::WidenVecRes_FP_TO_XINT_SAT(SDNode *N) {
  SDLoc dl(N);
  EVT WidenVT = TLI.getTypeToTransformTo(*DAG.getContext(), N->getValueType(0));
  ElementCount WidenNumElts = WidenVT.getVectorElementCount();

  SDValue Src = N->getOperand(0);
  EVT SrcVT = Src.getValueType();

  // Also widen the input.
  if (getTypeAction(SrcVT) == TargetLowering::TypeWidenVector) {
    Src = GetWidenedVector(Src);
    SrcVT = Src.getValueType();
  }

  // Input and output not widened to the same size, give up.
  if (WidenNumElts != SrcVT.getVectorElementCount())
    return DAG.UnrollVectorOp(N, WidenNumElts.getKnownMinValue());

  return DAG.getNode(N->getOpcode(), dl, WidenVT, Src, N->getOperand(1));
}

SDValue DAGTypeLegalizer::WidenVecRes_Convert_StrictFP(SDNode *N) {
  SDValue InOp = N->getOperand(1);
  SDLoc DL(N);
  SmallVector<SDValue, 4> NewOps(N->op_begin(), N->op_end());

  EVT WidenVT = TLI.getTypeToTransformTo(*DAG.getContext(), N->getValueType(0));
  unsigned WidenNumElts = WidenVT.getVectorNumElements();

  EVT InVT = InOp.getValueType();
  EVT InEltVT = InVT.getVectorElementType();

  unsigned Opcode = N->getOpcode();

  // FIXME: Optimizations need to be implemented here.

  // Otherwise unroll into some nasty scalar code and rebuild the vector.
  EVT EltVT = WidenVT.getVectorElementType();
  std::array<EVT, 2> EltVTs = {{EltVT, MVT::Other}};
  SmallVector<SDValue, 16> Ops(WidenNumElts, DAG.getUNDEF(EltVT));
  SmallVector<SDValue, 32> OpChains;
  // Use the original element count so we don't do more scalar opts than
  // necessary.
  unsigned MinElts = N->getValueType(0).getVectorNumElements();
  for (unsigned i=0; i < MinElts; ++i) {
    NewOps[1] = DAG.getNode(ISD::EXTRACT_VECTOR_ELT, DL, InEltVT, InOp,
                            DAG.getVectorIdxConstant(i, DL));
    Ops[i] = DAG.getNode(Opcode, DL, EltVTs, NewOps);
    OpChains.push_back(Ops[i].getValue(1));
  }
  SDValue NewChain = DAG.getNode(ISD::TokenFactor, DL, MVT::Other, OpChains);
  ReplaceValueWith(SDValue(N, 1), NewChain);

  return DAG.getBuildVector(WidenVT, DL, Ops);
}

SDValue DAGTypeLegalizer::WidenVecRes_EXTEND_VECTOR_INREG(SDNode *N) {
  unsigned Opcode = N->getOpcode();
  SDValue InOp = N->getOperand(0);
  SDLoc DL(N);

  EVT WidenVT = TLI.getTypeToTransformTo(*DAG.getContext(), N->getValueType(0));
  EVT WidenSVT = WidenVT.getVectorElementType();
  unsigned WidenNumElts = WidenVT.getVectorNumElements();

  EVT InVT = InOp.getValueType();
  EVT InSVT = InVT.getVectorElementType();
  unsigned InVTNumElts = InVT.getVectorNumElements();

  if (getTypeAction(InVT) == TargetLowering::TypeWidenVector) {
    InOp = GetWidenedVector(InOp);
    InVT = InOp.getValueType();
    if (InVT.getSizeInBits() == WidenVT.getSizeInBits()) {
      switch (Opcode) {
      case ISD::ANY_EXTEND_VECTOR_INREG:
      case ISD::SIGN_EXTEND_VECTOR_INREG:
      case ISD::ZERO_EXTEND_VECTOR_INREG:
        return DAG.getNode(Opcode, DL, WidenVT, InOp);
      }
    }
  }

  // Unroll, extend the scalars and rebuild the vector.
  SmallVector<SDValue, 16> Ops;
  for (unsigned i = 0, e = std::min(InVTNumElts, WidenNumElts); i != e; ++i) {
    SDValue Val = DAG.getNode(ISD::EXTRACT_VECTOR_ELT, DL, InSVT, InOp,
                              DAG.getVectorIdxConstant(i, DL));
    switch (Opcode) {
    case ISD::ANY_EXTEND_VECTOR_INREG:
      Val = DAG.getNode(ISD::ANY_EXTEND, DL, WidenSVT, Val);
      break;
    case ISD::SIGN_EXTEND_VECTOR_INREG:
      Val = DAG.getNode(ISD::SIGN_EXTEND, DL, WidenSVT, Val);
      break;
    case ISD::ZERO_EXTEND_VECTOR_INREG:
      Val = DAG.getNode(ISD::ZERO_EXTEND, DL, WidenSVT, Val);
      break;
    default:
      llvm_unreachable("A *_EXTEND_VECTOR_INREG node was expected");
    }
    Ops.push_back(Val);
  }

  while (Ops.size() != WidenNumElts)
    Ops.push_back(DAG.getUNDEF(WidenSVT));

  return DAG.getBuildVector(WidenVT, DL, Ops);
}

SDValue DAGTypeLegalizer::WidenVecRes_FCOPYSIGN(SDNode *N) {
  // If this is an FCOPYSIGN with same input types, we can treat it as a
  // normal (can trap) binary op.
  if (N->getOperand(0).getValueType() == N->getOperand(1).getValueType())
    return WidenVecRes_BinaryCanTrap(N);

  // If the types are different, fall back to unrolling.
  EVT WidenVT = TLI.getTypeToTransformTo(*DAG.getContext(), N->getValueType(0));
  return DAG.UnrollVectorOp(N, WidenVT.getVectorNumElements());
}

SDValue DAGTypeLegalizer::WidenVecRes_POWI(SDNode *N) {
  EVT WidenVT = TLI.getTypeToTransformTo(*DAG.getContext(), N->getValueType(0));
  SDValue InOp = GetWidenedVector(N->getOperand(0));
  SDValue ShOp = N->getOperand(1);
  return DAG.getNode(N->getOpcode(), SDLoc(N), WidenVT, InOp, ShOp);
}

SDValue DAGTypeLegalizer::WidenVecRes_Unary(SDNode *N) {
  // Unary op widening.
  EVT WidenVT = TLI.getTypeToTransformTo(*DAG.getContext(), N->getValueType(0));
  SDValue InOp = GetWidenedVector(N->getOperand(0));
  return DAG.getNode(N->getOpcode(), SDLoc(N), WidenVT, InOp);
}

SDValue DAGTypeLegalizer::WidenVecRes_InregOp(SDNode *N) {
  EVT WidenVT = TLI.getTypeToTransformTo(*DAG.getContext(), N->getValueType(0));
  EVT ExtVT = EVT::getVectorVT(*DAG.getContext(),
                               cast<VTSDNode>(N->getOperand(1))->getVT()
                                 .getVectorElementType(),
                               WidenVT.getVectorNumElements());
  SDValue WidenLHS = GetWidenedVector(N->getOperand(0));
  return DAG.getNode(N->getOpcode(), SDLoc(N),
                     WidenVT, WidenLHS, DAG.getValueType(ExtVT));
}

SDValue DAGTypeLegalizer::WidenVecRes_MERGE_VALUES(SDNode *N, unsigned ResNo) {
  SDValue WidenVec = DisintegrateMERGE_VALUES(N, ResNo);
  return GetWidenedVector(WidenVec);
}

SDValue DAGTypeLegalizer::WidenVecRes_BITCAST(SDNode *N) {
  SDValue InOp = N->getOperand(0);
  EVT InVT = InOp.getValueType();
  EVT VT = N->getValueType(0);
  EVT WidenVT = TLI.getTypeToTransformTo(*DAG.getContext(), VT);
  SDLoc dl(N);

  switch (getTypeAction(InVT)) {
  case TargetLowering::TypeLegal:
    break;
  case TargetLowering::TypeScalarizeScalableVector:
    report_fatal_error("Scalarization of scalable vectors is not supported.");
  case TargetLowering::TypePromoteInteger: {
    // If the incoming type is a vector that is being promoted, then
    // we know that the elements are arranged differently and that we
    // must perform the conversion using a stack slot.
    if (InVT.isVector())
      break;

    // If the InOp is promoted to the same size, convert it.  Otherwise,
    // fall out of the switch and widen the promoted input.
    SDValue NInOp = GetPromotedInteger(InOp);
    EVT NInVT = NInOp.getValueType();
    if (WidenVT.bitsEq(NInVT)) {
      // For big endian targets we need to shift the input integer or the
      // interesting bits will end up at the wrong place.
      if (DAG.getDataLayout().isBigEndian()) {
        unsigned ShiftAmt = NInVT.getSizeInBits() - InVT.getSizeInBits();
        EVT ShiftAmtTy = TLI.getShiftAmountTy(NInVT, DAG.getDataLayout());
        assert(ShiftAmt < WidenVT.getSizeInBits() && "Too large shift amount!");
        NInOp = DAG.getNode(ISD::SHL, dl, NInVT, NInOp,
                           DAG.getConstant(ShiftAmt, dl, ShiftAmtTy));
      }
      return DAG.getNode(ISD::BITCAST, dl, WidenVT, NInOp);
    }
    InOp = NInOp;
    InVT = NInVT;
    break;
  }
  case TargetLowering::TypeSoftenFloat:
  case TargetLowering::TypePromoteFloat:
  case TargetLowering::TypeSoftPromoteHalf:
  case TargetLowering::TypeExpandInteger:
  case TargetLowering::TypeExpandFloat:
  case TargetLowering::TypeScalarizeVector:
  case TargetLowering::TypeSplitVector:
    break;
  case TargetLowering::TypeWidenVector:
    // If the InOp is widened to the same size, convert it.  Otherwise, fall
    // out of the switch and widen the widened input.
    InOp = GetWidenedVector(InOp);
    InVT = InOp.getValueType();
    if (WidenVT.bitsEq(InVT))
      // The input widens to the same size. Convert to the widen value.
      return DAG.getNode(ISD::BITCAST, dl, WidenVT, InOp);
    break;
  }

  unsigned WidenSize = WidenVT.getSizeInBits();
  unsigned InSize = InVT.getSizeInBits();
  // x86mmx is not an acceptable vector element type, so don't try.
  if (WidenSize % InSize == 0 && InVT != MVT::x86mmx) {
    // Determine new input vector type.  The new input vector type will use
    // the same element type (if its a vector) or use the input type as a
    // vector.  It is the same size as the type to widen to.
    EVT NewInVT;
    unsigned NewNumElts = WidenSize / InSize;
    if (InVT.isVector()) {
      EVT InEltVT = InVT.getVectorElementType();
      NewInVT = EVT::getVectorVT(*DAG.getContext(), InEltVT,
                                 WidenSize / InEltVT.getSizeInBits());
    } else {
      NewInVT = EVT::getVectorVT(*DAG.getContext(), InVT, NewNumElts);
    }

    if (TLI.isTypeLegal(NewInVT)) {
      SDValue NewVec;
      if (InVT.isVector()) {
        // Because the result and the input are different vector types, widening
        // the result could create a legal type but widening the input might make
        // it an illegal type that might lead to repeatedly splitting the input
        // and then widening it. To avoid this, we widen the input only if
        // it results in a legal type.
        SmallVector<SDValue, 16> Ops(NewNumElts, DAG.getUNDEF(InVT));
        Ops[0] = InOp;

        NewVec = DAG.getNode(ISD::CONCAT_VECTORS, dl, NewInVT, Ops);
      } else {
        NewVec = DAG.getNode(ISD::SCALAR_TO_VECTOR, dl, NewInVT, InOp);
      }
      return DAG.getNode(ISD::BITCAST, dl, WidenVT, NewVec);
    }
  }

  return CreateStackStoreLoad(InOp, WidenVT);
}

SDValue DAGTypeLegalizer::WidenVecRes_BUILD_VECTOR(SDNode *N) {
  SDLoc dl(N);
  // Build a vector with undefined for the new nodes.
  EVT VT = N->getValueType(0);

  // Integer BUILD_VECTOR operands may be larger than the node's vector element
  // type. The UNDEFs need to have the same type as the existing operands.
  EVT EltVT = N->getOperand(0).getValueType();
  unsigned NumElts = VT.getVectorNumElements();

  EVT WidenVT = TLI.getTypeToTransformTo(*DAG.getContext(), VT);
  unsigned WidenNumElts = WidenVT.getVectorNumElements();

  SmallVector<SDValue, 16> NewOps(N->op_begin(), N->op_end());
  assert(WidenNumElts >= NumElts && "Shrinking vector instead of widening!");
  NewOps.append(WidenNumElts - NumElts, DAG.getUNDEF(EltVT));

  return DAG.getBuildVector(WidenVT, dl, NewOps);
}

SDValue DAGTypeLegalizer::WidenVecRes_CONCAT_VECTORS(SDNode *N) {
  EVT InVT = N->getOperand(0).getValueType();
  EVT WidenVT = TLI.getTypeToTransformTo(*DAG.getContext(), N->getValueType(0));
  SDLoc dl(N);
  unsigned NumOperands = N->getNumOperands();

  bool InputWidened = false; // Indicates we need to widen the input.
  if (getTypeAction(InVT) != TargetLowering::TypeWidenVector) {
    unsigned WidenNumElts = WidenVT.getVectorMinNumElements();
    unsigned NumInElts = InVT.getVectorMinNumElements();
    if (WidenNumElts % NumInElts == 0) {
      // Add undef vectors to widen to correct length.
      unsigned NumConcat = WidenNumElts / NumInElts;
      SDValue UndefVal = DAG.getUNDEF(InVT);
      SmallVector<SDValue, 16> Ops(NumConcat);
      for (unsigned i=0; i < NumOperands; ++i)
        Ops[i] = N->getOperand(i);
      for (unsigned i = NumOperands; i != NumConcat; ++i)
        Ops[i] = UndefVal;
      return DAG.getNode(ISD::CONCAT_VECTORS, dl, WidenVT, Ops);
    }
  } else {
    InputWidened = true;
    if (WidenVT == TLI.getTypeToTransformTo(*DAG.getContext(), InVT)) {
      // The inputs and the result are widen to the same value.
      unsigned i;
      for (i=1; i < NumOperands; ++i)
        if (!N->getOperand(i).isUndef())
          break;

      if (i == NumOperands)
        // Everything but the first operand is an UNDEF so just return the
        // widened first operand.
        return GetWidenedVector(N->getOperand(0));

      if (NumOperands == 2) {
        assert(!WidenVT.isScalableVector() &&
               "Cannot use vector shuffles to widen CONCAT_VECTOR result");
        unsigned WidenNumElts = WidenVT.getVectorNumElements();
        unsigned NumInElts = InVT.getVectorNumElements();

        // Replace concat of two operands with a shuffle.
        SmallVector<int, 16> MaskOps(WidenNumElts, -1);
        for (unsigned i = 0; i < NumInElts; ++i) {
          MaskOps[i] = i;
          MaskOps[i + NumInElts] = i + WidenNumElts;
        }
        return DAG.getVectorShuffle(WidenVT, dl,
                                    GetWidenedVector(N->getOperand(0)),
                                    GetWidenedVector(N->getOperand(1)),
                                    MaskOps);
      }
    }
  }

  assert(!WidenVT.isScalableVector() &&
         "Cannot use build vectors to widen CONCAT_VECTOR result");
  unsigned WidenNumElts = WidenVT.getVectorNumElements();
  unsigned NumInElts = InVT.getVectorNumElements();

  // Fall back to use extracts and build vector.
  EVT EltVT = WidenVT.getVectorElementType();
  SmallVector<SDValue, 16> Ops(WidenNumElts);
  unsigned Idx = 0;
  for (unsigned i=0; i < NumOperands; ++i) {
    SDValue InOp = N->getOperand(i);
    if (InputWidened)
      InOp = GetWidenedVector(InOp);
    for (unsigned j = 0; j < NumInElts; ++j)
      Ops[Idx++] = DAG.getNode(ISD::EXTRACT_VECTOR_ELT, dl, EltVT, InOp,
                               DAG.getVectorIdxConstant(j, dl));
  }
  SDValue UndefVal = DAG.getUNDEF(EltVT);
  for (; Idx < WidenNumElts; ++Idx)
    Ops[Idx] = UndefVal;
  return DAG.getBuildVector(WidenVT, dl, Ops);
}

SDValue DAGTypeLegalizer::WidenVecRes_INSERT_SUBVECTOR(SDNode *N) {
  EVT VT = N->getValueType(0);
  EVT WidenVT = TLI.getTypeToTransformTo(*DAG.getContext(), VT);
  SDValue InOp1 = GetWidenedVector(N->getOperand(0));
  SDValue InOp2 = N->getOperand(1);
  SDValue Idx = N->getOperand(2);
  SDLoc dl(N);
  return DAG.getNode(ISD::INSERT_SUBVECTOR, dl, WidenVT, InOp1, InOp2, Idx);
}

SDValue DAGTypeLegalizer::WidenVecRes_EXTRACT_SUBVECTOR(SDNode *N) {
  EVT      VT = N->getValueType(0);
  EVT      EltVT = VT.getVectorElementType();
  EVT      WidenVT = TLI.getTypeToTransformTo(*DAG.getContext(), VT);
  SDValue  InOp = N->getOperand(0);
  SDValue  Idx  = N->getOperand(1);
  SDLoc dl(N);

  auto InOpTypeAction = getTypeAction(InOp.getValueType());
  if (InOpTypeAction == TargetLowering::TypeWidenVector)
    InOp = GetWidenedVector(InOp);

  EVT InVT = InOp.getValueType();

  // Check if we can just return the input vector after widening.
  uint64_t IdxVal = cast<ConstantSDNode>(Idx)->getZExtValue();
  if (IdxVal == 0 && InVT == WidenVT)
    return InOp;

  // Check if we can extract from the vector.
  unsigned WidenNumElts = WidenVT.getVectorMinNumElements();
  unsigned InNumElts = InVT.getVectorMinNumElements();
  if (IdxVal % WidenNumElts == 0 && IdxVal + WidenNumElts < InNumElts)
    return DAG.getNode(ISD::EXTRACT_SUBVECTOR, dl, WidenVT, InOp, Idx);

  if (VT.isScalableVector()) {
    // Try to split the operation up into smaller extracts and concat the
    // results together, e.g.
    //    nxv6i64 extract_subvector(nxv12i64, 6)
    // <->
    //  nxv8i64 concat(
    //    nxv2i64 extract_subvector(nxv16i64, 6)
    //    nxv2i64 extract_subvector(nxv16i64, 8)
    //    nxv2i64 extract_subvector(nxv16i64, 10)
    //    undef)
    unsigned VTNElts = VT.getVectorMinNumElements();
    unsigned GCD = greatestCommonDivisor(VTNElts, WidenNumElts);
    assert((IdxVal % GCD) == 0 && "Expected Idx to be a multiple of the broken "
                                  "down type's element count");
    EVT PartVT = EVT::getVectorVT(*DAG.getContext(), EltVT,
                                  ElementCount::getScalable(GCD));
    // Avoid recursion around e.g. nxv1i8.
    if (getTypeAction(PartVT) != TargetLowering::TypeWidenVector) {
      SmallVector<SDValue> Parts;
      unsigned I = 0;
      for (; I < VTNElts / GCD; ++I)
        Parts.push_back(
            DAG.getNode(ISD::EXTRACT_SUBVECTOR, dl, PartVT, InOp,
                        DAG.getVectorIdxConstant(IdxVal + I * GCD, dl)));
      for (; I < WidenNumElts / GCD; ++I)
        Parts.push_back(DAG.getUNDEF(PartVT));

      return DAG.getNode(ISD::CONCAT_VECTORS, dl, WidenVT, Parts);
    }

    report_fatal_error("Don't know how to widen the result of "
                       "EXTRACT_SUBVECTOR for scalable vectors");
  }

  // We could try widening the input to the right length but for now, extract
  // the original elements, fill the rest with undefs and build a vector.
  SmallVector<SDValue, 16> Ops(WidenNumElts);
  unsigned NumElts = VT.getVectorNumElements();
  unsigned i;
  for (i = 0; i < NumElts; ++i)
    Ops[i] = DAG.getNode(ISD::EXTRACT_VECTOR_ELT, dl, EltVT, InOp,
                         DAG.getVectorIdxConstant(IdxVal + i, dl));

  SDValue UndefVal = DAG.getUNDEF(EltVT);
  for (; i < WidenNumElts; ++i)
    Ops[i] = UndefVal;
  return DAG.getBuildVector(WidenVT, dl, Ops);
}

SDValue DAGTypeLegalizer::WidenVecRes_INSERT_VECTOR_ELT(SDNode *N) {
  SDValue InOp = GetWidenedVector(N->getOperand(0));
  return DAG.getNode(ISD::INSERT_VECTOR_ELT, SDLoc(N),
                     InOp.getValueType(), InOp,
                     N->getOperand(1), N->getOperand(2));
}

SDValue DAGTypeLegalizer::WidenVecRes_LOAD(SDNode *N) {
  LoadSDNode *LD = cast<LoadSDNode>(N);
  ISD::LoadExtType ExtType = LD->getExtensionType();

  // A vector must always be stored in memory as-is, i.e. without any padding
  // between the elements, since various code depend on it, e.g. in the
  // handling of a bitcast of a vector type to int, which may be done with a
  // vector store followed by an integer load. A vector that does not have
  // elements that are byte-sized must therefore be stored as an integer
  // built out of the extracted vector elements.
  if (!LD->getMemoryVT().isByteSized()) {
    SDValue Value, NewChain;
    std::tie(Value, NewChain) = TLI.scalarizeVectorLoad(LD, DAG);
    ReplaceValueWith(SDValue(LD, 0), Value);
    ReplaceValueWith(SDValue(LD, 1), NewChain);
    return SDValue();
  }

  SDValue Result;
  SmallVector<SDValue, 16> LdChain;  // Chain for the series of load
  if (ExtType != ISD::NON_EXTLOAD)
    Result = GenWidenVectorExtLoads(LdChain, LD, ExtType);
  else
    Result = GenWidenVectorLoads(LdChain, LD);

  if (Result) {
    // If we generate a single load, we can use that for the chain.  Otherwise,
    // build a factor node to remember the multiple loads are independent and
    // chain to that.
    SDValue NewChain;
    if (LdChain.size() == 1)
      NewChain = LdChain[0];
    else
      NewChain = DAG.getNode(ISD::TokenFactor, SDLoc(LD), MVT::Other, LdChain);

    // Modified the chain - switch anything that used the old chain to use
    // the new one.
    ReplaceValueWith(SDValue(N, 1), NewChain);

    return Result;
  }

  // Generate a vector-predicated load if it is custom/legal on the target. To
  // avoid possible recursion, only do this if the widened mask type is legal.
  // FIXME: Not all targets may support EVL in VP_LOAD. These will have been
  // removed from the IR by the ExpandVectorPredication pass but we're
  // reintroducing them here.
  EVT LdVT = LD->getMemoryVT();
  EVT WideVT = TLI.getTypeToTransformTo(*DAG.getContext(), LdVT);
  EVT WideMaskVT = EVT::getVectorVT(*DAG.getContext(), MVT::i1,
                                    WideVT.getVectorElementCount());
  if (ExtType == ISD::NON_EXTLOAD && WideVT.isScalableVector() &&
      TLI.isOperationLegalOrCustom(ISD::VP_LOAD, WideVT) &&
      TLI.isTypeLegal(WideMaskVT)) {
    SDLoc DL(N);
    SDValue Mask = DAG.getAllOnesConstant(DL, WideMaskVT);
    MVT EVLVT = TLI.getVPExplicitVectorLengthTy();
    unsigned NumVTElts = LdVT.getVectorMinNumElements();
    SDValue EVL =
        DAG.getVScale(DL, EVLVT, APInt(EVLVT.getScalarSizeInBits(), NumVTElts));
    const auto *MMO = LD->getMemOperand();
    SDValue NewLoad =
        DAG.getLoadVP(WideVT, DL, LD->getChain(), LD->getBasePtr(), Mask, EVL,
                      MMO->getPointerInfo(), MMO->getAlign(), MMO->getFlags(),
                      MMO->getAAInfo());

    // Modified the chain - switch anything that used the old chain to use
    // the new one.
    ReplaceValueWith(SDValue(N, 1), NewLoad.getValue(1));

    return NewLoad;
  }

  report_fatal_error("Unable to widen vector load");
}

SDValue DAGTypeLegalizer::WidenVecRes_MLOAD(MaskedLoadSDNode *N) {

  EVT WidenVT = TLI.getTypeToTransformTo(*DAG.getContext(),N->getValueType(0));
  SDValue Mask = N->getMask();
  EVT MaskVT = Mask.getValueType();
  SDValue PassThru = GetWidenedVector(N->getPassThru());
  ISD::LoadExtType ExtType = N->getExtensionType();
  SDLoc dl(N);

  // The mask should be widened as well
  EVT WideMaskVT = EVT::getVectorVT(*DAG.getContext(),
                                    MaskVT.getVectorElementType(),
                                    WidenVT.getVectorNumElements());
  Mask = ModifyToType(Mask, WideMaskVT, true);

  SDValue Res = DAG.getMaskedLoad(
      WidenVT, dl, N->getChain(), N->getBasePtr(), N->getOffset(), Mask,
      PassThru, N->getMemoryVT(), N->getMemOperand(), N->getAddressingMode(),
      ExtType, N->isExpandingLoad());
  // Legalize the chain result - switch anything that used the old chain to
  // use the new one.
  ReplaceValueWith(SDValue(N, 1), Res.getValue(1));
  return Res;
}

SDValue DAGTypeLegalizer::WidenVecRes_MGATHER(MaskedGatherSDNode *N) {

  EVT WideVT = TLI.getTypeToTransformTo(*DAG.getContext(), N->getValueType(0));
  SDValue Mask = N->getMask();
  EVT MaskVT = Mask.getValueType();
  SDValue PassThru = GetWidenedVector(N->getPassThru());
  SDValue Scale = N->getScale();
  unsigned NumElts = WideVT.getVectorNumElements();
  SDLoc dl(N);

  // The mask should be widened as well
  EVT WideMaskVT = EVT::getVectorVT(*DAG.getContext(),
                                    MaskVT.getVectorElementType(),
                                    WideVT.getVectorNumElements());
  Mask = ModifyToType(Mask, WideMaskVT, true);

  // Widen the Index operand
  SDValue Index = N->getIndex();
  EVT WideIndexVT = EVT::getVectorVT(*DAG.getContext(),
                                     Index.getValueType().getScalarType(),
                                     NumElts);
  Index = ModifyToType(Index, WideIndexVT);
  SDValue Ops[] = { N->getChain(), PassThru, Mask, N->getBasePtr(), Index,
                    Scale };

  // Widen the MemoryType
  EVT WideMemVT = EVT::getVectorVT(*DAG.getContext(),
                                   N->getMemoryVT().getScalarType(), NumElts);
  SDValue Res = DAG.getMaskedGather(DAG.getVTList(WideVT, MVT::Other),
                                    WideMemVT, dl, Ops, N->getMemOperand(),
                                    N->getIndexType(), N->getExtensionType());

  // Legalize the chain result - switch anything that used the old chain to
  // use the new one.
  ReplaceValueWith(SDValue(N, 1), Res.getValue(1));
  return Res;
}

SDValue DAGTypeLegalizer::WidenVecRes_ScalarOp(SDNode *N) {
  EVT WidenVT = TLI.getTypeToTransformTo(*DAG.getContext(), N->getValueType(0));
  return DAG.getNode(N->getOpcode(), SDLoc(N), WidenVT, N->getOperand(0));
}

// Return true is this is a SETCC node or a strict version of it.
static inline bool isSETCCOp(unsigned Opcode) {
  switch (Opcode) {
  case ISD::SETCC:
  case ISD::STRICT_FSETCC:
  case ISD::STRICT_FSETCCS:
    return true;
  }
  return false;
}

// Return true if this is a node that could have two SETCCs as operands.
static inline bool isLogicalMaskOp(unsigned Opcode) {
  switch (Opcode) {
  case ISD::AND:
  case ISD::OR:
  case ISD::XOR:
    return true;
  }
  return false;
}

// If N is a SETCC or a strict variant of it, return the type
// of the compare operands.
static inline EVT getSETCCOperandType(SDValue N) {
  unsigned OpNo = N->isStrictFPOpcode() ? 1 : 0;
  return N->getOperand(OpNo).getValueType();
}

// This is used just for the assert in convertMask(). Check that this either
// a SETCC or a previously handled SETCC by convertMask().
#ifndef NDEBUG
static inline bool isSETCCorConvertedSETCC(SDValue N) {
  if (N.getOpcode() == ISD::EXTRACT_SUBVECTOR)
    N = N.getOperand(0);
  else if (N.getOpcode() == ISD::CONCAT_VECTORS) {
    for (unsigned i = 1; i < N->getNumOperands(); ++i)
      if (!N->getOperand(i)->isUndef())
        return false;
    N = N.getOperand(0);
  }

  if (N.getOpcode() == ISD::TRUNCATE)
    N = N.getOperand(0);
  else if (N.getOpcode() == ISD::SIGN_EXTEND)
    N = N.getOperand(0);

  if (isLogicalMaskOp(N.getOpcode()))
    return isSETCCorConvertedSETCC(N.getOperand(0)) &&
           isSETCCorConvertedSETCC(N.getOperand(1));

  return (isSETCCOp(N.getOpcode()) ||
          ISD::isBuildVectorOfConstantSDNodes(N.getNode()));
}
#endif

// Return a mask of vector type MaskVT to replace InMask. Also adjust MaskVT
// to ToMaskVT if needed with vector extension or truncation.
SDValue DAGTypeLegalizer::convertMask(SDValue InMask, EVT MaskVT,
                                      EVT ToMaskVT) {
  // Currently a SETCC or a AND/OR/XOR with two SETCCs are handled.
  // FIXME: This code seems to be too restrictive, we might consider
  // generalizing it or dropping it.
  assert(isSETCCorConvertedSETCC(InMask) && "Unexpected mask argument.");

  // Make a new Mask node, with a legal result VT.
  SDValue Mask;
  SmallVector<SDValue, 4> Ops;
  for (unsigned i = 0, e = InMask->getNumOperands(); i < e; ++i)
    Ops.push_back(InMask->getOperand(i));
  if (InMask->isStrictFPOpcode()) {
    Mask = DAG.getNode(InMask->getOpcode(), SDLoc(InMask),
                       { MaskVT, MVT::Other }, Ops);
    ReplaceValueWith(InMask.getValue(1), Mask.getValue(1));
  }
  else
    Mask = DAG.getNode(InMask->getOpcode(), SDLoc(InMask), MaskVT, Ops);

  // If MaskVT has smaller or bigger elements than ToMaskVT, a vector sign
  // extend or truncate is needed.
  LLVMContext &Ctx = *DAG.getContext();
  unsigned MaskScalarBits = MaskVT.getScalarSizeInBits();
  unsigned ToMaskScalBits = ToMaskVT.getScalarSizeInBits();
  if (MaskScalarBits < ToMaskScalBits) {
    EVT ExtVT = EVT::getVectorVT(Ctx, ToMaskVT.getVectorElementType(),
                                 MaskVT.getVectorNumElements());
    Mask = DAG.getNode(ISD::SIGN_EXTEND, SDLoc(Mask), ExtVT, Mask);
  } else if (MaskScalarBits > ToMaskScalBits) {
    EVT TruncVT = EVT::getVectorVT(Ctx, ToMaskVT.getVectorElementType(),
                                   MaskVT.getVectorNumElements());
    Mask = DAG.getNode(ISD::TRUNCATE, SDLoc(Mask), TruncVT, Mask);
  }

  assert(Mask->getValueType(0).getScalarSizeInBits() ==
             ToMaskVT.getScalarSizeInBits() &&
         "Mask should have the right element size by now.");

  // Adjust Mask to the right number of elements.
  unsigned CurrMaskNumEls = Mask->getValueType(0).getVectorNumElements();
  if (CurrMaskNumEls > ToMaskVT.getVectorNumElements()) {
    SDValue ZeroIdx = DAG.getVectorIdxConstant(0, SDLoc(Mask));
    Mask = DAG.getNode(ISD::EXTRACT_SUBVECTOR, SDLoc(Mask), ToMaskVT, Mask,
                       ZeroIdx);
  } else if (CurrMaskNumEls < ToMaskVT.getVectorNumElements()) {
    unsigned NumSubVecs = (ToMaskVT.getVectorNumElements() / CurrMaskNumEls);
    EVT SubVT = Mask->getValueType(0);
    SmallVector<SDValue, 16> SubOps(NumSubVecs, DAG.getUNDEF(SubVT));
    SubOps[0] = Mask;
    Mask = DAG.getNode(ISD::CONCAT_VECTORS, SDLoc(Mask), ToMaskVT, SubOps);
  }

  assert((Mask->getValueType(0) == ToMaskVT) &&
         "A mask of ToMaskVT should have been produced by now.");

  return Mask;
}

// This method tries to handle some special cases for the vselect mask
// and if needed adjusting the mask vector type to match that of the VSELECT.
// Without it, many cases end up with scalarization of the SETCC, with many
// unnecessary instructions.
SDValue DAGTypeLegalizer::WidenVSELECTMask(SDNode *N) {
  LLVMContext &Ctx = *DAG.getContext();
  SDValue Cond = N->getOperand(0);

  if (N->getOpcode() != ISD::VSELECT)
    return SDValue();

  if (!isSETCCOp(Cond->getOpcode()) && !isLogicalMaskOp(Cond->getOpcode()))
    return SDValue();

  // If this is a splitted VSELECT that was previously already handled, do
  // nothing.
  EVT CondVT = Cond->getValueType(0);
  if (CondVT.getScalarSizeInBits() != 1)
    return SDValue();

  EVT VSelVT = N->getValueType(0);

  // This method can't handle scalable vector types.
  // FIXME: This support could be added in the future.
  if (VSelVT.isScalableVector())
    return SDValue();

  // Only handle vector types which are a power of 2.
  if (!isPowerOf2_64(VSelVT.getSizeInBits()))
    return SDValue();

  // Don't touch if this will be scalarized.
  EVT FinalVT = VSelVT;
  while (getTypeAction(FinalVT) == TargetLowering::TypeSplitVector)
    FinalVT = FinalVT.getHalfNumVectorElementsVT(Ctx);

  if (FinalVT.getVectorNumElements() == 1)
    return SDValue();

  // If there is support for an i1 vector mask, don't touch.
  if (isSETCCOp(Cond.getOpcode())) {
    EVT SetCCOpVT = getSETCCOperandType(Cond);
    while (TLI.getTypeAction(Ctx, SetCCOpVT) != TargetLowering::TypeLegal)
      SetCCOpVT = TLI.getTypeToTransformTo(Ctx, SetCCOpVT);
    EVT SetCCResVT = getSetCCResultType(SetCCOpVT);
    if (SetCCResVT.getScalarSizeInBits() == 1)
      return SDValue();
  } else if (CondVT.getScalarType() == MVT::i1) {
    // If there is support for an i1 vector mask (or only scalar i1 conditions),
    // don't touch.
    while (TLI.getTypeAction(Ctx, CondVT) != TargetLowering::TypeLegal)
      CondVT = TLI.getTypeToTransformTo(Ctx, CondVT);

    if (CondVT.getScalarType() == MVT::i1)
      return SDValue();
  }

  // Widen the vselect result type if needed.
  if (getTypeAction(VSelVT) == TargetLowering::TypeWidenVector)
    VSelVT = TLI.getTypeToTransformTo(Ctx, VSelVT);

  // The mask of the VSELECT should have integer elements.
  EVT ToMaskVT = VSelVT;
  if (!ToMaskVT.getScalarType().isInteger())
    ToMaskVT = ToMaskVT.changeVectorElementTypeToInteger();

  SDValue Mask;
  if (isSETCCOp(Cond->getOpcode())) {
    EVT MaskVT = getSetCCResultType(getSETCCOperandType(Cond));
    Mask = convertMask(Cond, MaskVT, ToMaskVT);
  } else if (isLogicalMaskOp(Cond->getOpcode()) &&
             isSETCCOp(Cond->getOperand(0).getOpcode()) &&
             isSETCCOp(Cond->getOperand(1).getOpcode())) {
    // Cond is (AND/OR/XOR (SETCC, SETCC))
    SDValue SETCC0 = Cond->getOperand(0);
    SDValue SETCC1 = Cond->getOperand(1);
    EVT VT0 = getSetCCResultType(getSETCCOperandType(SETCC0));
    EVT VT1 = getSetCCResultType(getSETCCOperandType(SETCC1));
    unsigned ScalarBits0 = VT0.getScalarSizeInBits();
    unsigned ScalarBits1 = VT1.getScalarSizeInBits();
    unsigned ScalarBits_ToMask = ToMaskVT.getScalarSizeInBits();
    EVT MaskVT;
    // If the two SETCCs have different VTs, either extend/truncate one of
    // them to the other "towards" ToMaskVT, or truncate one and extend the
    // other to ToMaskVT.
    if (ScalarBits0 != ScalarBits1) {
      EVT NarrowVT = ((ScalarBits0 < ScalarBits1) ? VT0 : VT1);
      EVT WideVT = ((NarrowVT == VT0) ? VT1 : VT0);
      if (ScalarBits_ToMask >= WideVT.getScalarSizeInBits())
        MaskVT = WideVT;
      else if (ScalarBits_ToMask <= NarrowVT.getScalarSizeInBits())
        MaskVT = NarrowVT;
      else
        MaskVT = ToMaskVT;
    } else
      // If the two SETCCs have the same VT, don't change it.
      MaskVT = VT0;

    // Make new SETCCs and logical nodes.
    SETCC0 = convertMask(SETCC0, VT0, MaskVT);
    SETCC1 = convertMask(SETCC1, VT1, MaskVT);
    Cond = DAG.getNode(Cond->getOpcode(), SDLoc(Cond), MaskVT, SETCC0, SETCC1);

    // Convert the logical op for VSELECT if needed.
    Mask = convertMask(Cond, MaskVT, ToMaskVT);
  } else
    return SDValue();

  return Mask;
}

SDValue DAGTypeLegalizer::WidenVecRes_SELECT(SDNode *N) {
  EVT WidenVT = TLI.getTypeToTransformTo(*DAG.getContext(), N->getValueType(0));
  ElementCount WidenEC = WidenVT.getVectorElementCount();

  SDValue Cond1 = N->getOperand(0);
  EVT CondVT = Cond1.getValueType();
  if (CondVT.isVector()) {
    if (SDValue WideCond = WidenVSELECTMask(N)) {
      SDValue InOp1 = GetWidenedVector(N->getOperand(1));
      SDValue InOp2 = GetWidenedVector(N->getOperand(2));
      assert(InOp1.getValueType() == WidenVT && InOp2.getValueType() == WidenVT);
      return DAG.getNode(N->getOpcode(), SDLoc(N),
                         WidenVT, WideCond, InOp1, InOp2);
    }

    EVT CondEltVT = CondVT.getVectorElementType();
    EVT CondWidenVT = EVT::getVectorVT(*DAG.getContext(), CondEltVT, WidenEC);
    if (getTypeAction(CondVT) == TargetLowering::TypeWidenVector)
      Cond1 = GetWidenedVector(Cond1);

    // If we have to split the condition there is no point in widening the
    // select. This would result in an cycle of widening the select ->
    // widening the condition operand -> splitting the condition operand ->
    // splitting the select -> widening the select. Instead split this select
    // further and widen the resulting type.
    if (getTypeAction(CondVT) == TargetLowering::TypeSplitVector) {
      SDValue SplitSelect = SplitVecOp_VSELECT(N, 0);
      SDValue Res = ModifyToType(SplitSelect, WidenVT);
      return Res;
    }

    if (Cond1.getValueType() != CondWidenVT)
      Cond1 = ModifyToType(Cond1, CondWidenVT);
  }

  SDValue InOp1 = GetWidenedVector(N->getOperand(1));
  SDValue InOp2 = GetWidenedVector(N->getOperand(2));
  assert(InOp1.getValueType() == WidenVT && InOp2.getValueType() == WidenVT);
  return DAG.getNode(N->getOpcode(), SDLoc(N),
                     WidenVT, Cond1, InOp1, InOp2);
}

SDValue DAGTypeLegalizer::WidenVecRes_SELECT_CC(SDNode *N) {
  SDValue InOp1 = GetWidenedVector(N->getOperand(2));
  SDValue InOp2 = GetWidenedVector(N->getOperand(3));
  return DAG.getNode(ISD::SELECT_CC, SDLoc(N),
                     InOp1.getValueType(), N->getOperand(0),
                     N->getOperand(1), InOp1, InOp2, N->getOperand(4));
}

SDValue DAGTypeLegalizer::WidenVecRes_UNDEF(SDNode *N) {
 EVT WidenVT = TLI.getTypeToTransformTo(*DAG.getContext(), N->getValueType(0));
 return DAG.getUNDEF(WidenVT);
}

SDValue DAGTypeLegalizer::WidenVecRes_VECTOR_SHUFFLE(ShuffleVectorSDNode *N) {
  EVT VT = N->getValueType(0);
  SDLoc dl(N);

  EVT WidenVT = TLI.getTypeToTransformTo(*DAG.getContext(), VT);
  unsigned NumElts = VT.getVectorNumElements();
  unsigned WidenNumElts = WidenVT.getVectorNumElements();

  SDValue InOp1 = GetWidenedVector(N->getOperand(0));
  SDValue InOp2 = GetWidenedVector(N->getOperand(1));

  // Adjust mask based on new input vector length.
  SmallVector<int, 16> NewMask;
  for (unsigned i = 0; i != NumElts; ++i) {
    int Idx = N->getMaskElt(i);
    if (Idx < (int)NumElts)
      NewMask.push_back(Idx);
    else
      NewMask.push_back(Idx - NumElts + WidenNumElts);
  }
  for (unsigned i = NumElts; i != WidenNumElts; ++i)
    NewMask.push_back(-1);
  return DAG.getVectorShuffle(WidenVT, dl, InOp1, InOp2, NewMask);
}

SDValue DAGTypeLegalizer::WidenVecRes_SETCC(SDNode *N) {
  assert(N->getValueType(0).isVector() &&
         N->getOperand(0).getValueType().isVector() &&
         "Operands must be vectors");
  EVT WidenVT = TLI.getTypeToTransformTo(*DAG.getContext(), N->getValueType(0));
  unsigned WidenNumElts = WidenVT.getVectorNumElements();

  SDValue InOp1 = N->getOperand(0);
  EVT InVT = InOp1.getValueType();
  assert(InVT.isVector() && "can not widen non-vector type");
  EVT WidenInVT = EVT::getVectorVT(*DAG.getContext(),
                                   InVT.getVectorElementType(), WidenNumElts);

  // The input and output types often differ here, and it could be that while
  // we'd prefer to widen the result type, the input operands have been split.
  // In this case, we also need to split the result of this node as well.
  if (getTypeAction(InVT) == TargetLowering::TypeSplitVector) {
    SDValue SplitVSetCC = SplitVecOp_VSETCC(N);
    SDValue Res = ModifyToType(SplitVSetCC, WidenVT);
    return Res;
  }

  // If the inputs also widen, handle them directly. Otherwise widen by hand.
  SDValue InOp2 = N->getOperand(1);
  if (getTypeAction(InVT) == TargetLowering::TypeWidenVector) {
    InOp1 = GetWidenedVector(InOp1);
    InOp2 = GetWidenedVector(InOp2);
  } else {
    InOp1 = DAG.WidenVector(InOp1, SDLoc(N));
    InOp2 = DAG.WidenVector(InOp2, SDLoc(N));
  }

  // Assume that the input and output will be widen appropriately.  If not,
  // we will have to unroll it at some point.
  assert(InOp1.getValueType() == WidenInVT &&
         InOp2.getValueType() == WidenInVT &&
         "Input not widened to expected type!");
  (void)WidenInVT;
  return DAG.getNode(ISD::SETCC, SDLoc(N),
                     WidenVT, InOp1, InOp2, N->getOperand(2));
}

SDValue DAGTypeLegalizer::WidenVecRes_STRICT_FSETCC(SDNode *N) {
  assert(N->getValueType(0).isVector() &&
         N->getOperand(1).getValueType().isVector() &&
         "Operands must be vectors");
  EVT VT = N->getValueType(0);
  EVT WidenVT = TLI.getTypeToTransformTo(*DAG.getContext(), VT);
  unsigned WidenNumElts = WidenVT.getVectorNumElements();
  unsigned NumElts = VT.getVectorNumElements();
  EVT EltVT = VT.getVectorElementType();

  SDLoc dl(N);
  SDValue Chain = N->getOperand(0);
  SDValue LHS = N->getOperand(1);
  SDValue RHS = N->getOperand(2);
  SDValue CC = N->getOperand(3);
  EVT TmpEltVT = LHS.getValueType().getVectorElementType();

  // Fully unroll and reassemble.
  SmallVector<SDValue, 8> Scalars(WidenNumElts, DAG.getUNDEF(EltVT));
  SmallVector<SDValue, 8> Chains(NumElts);
  for (unsigned i = 0; i != NumElts; ++i) {
    SDValue LHSElem = DAG.getNode(ISD::EXTRACT_VECTOR_ELT, dl, TmpEltVT, LHS,
                                  DAG.getVectorIdxConstant(i, dl));
    SDValue RHSElem = DAG.getNode(ISD::EXTRACT_VECTOR_ELT, dl, TmpEltVT, RHS,
                                  DAG.getVectorIdxConstant(i, dl));

    Scalars[i] = DAG.getNode(N->getOpcode(), dl, {MVT::i1, MVT::Other},
                             {Chain, LHSElem, RHSElem, CC});
    Chains[i] = Scalars[i].getValue(1);
    Scalars[i] = DAG.getSelect(dl, EltVT, Scalars[i],
                               DAG.getBoolConstant(true, dl, EltVT, VT),
                               DAG.getBoolConstant(false, dl, EltVT, VT));
  }

  SDValue NewChain = DAG.getNode(ISD::TokenFactor, dl, MVT::Other, Chains);
  ReplaceValueWith(SDValue(N, 1), NewChain);

  return DAG.getBuildVector(WidenVT, dl, Scalars);
}

//===----------------------------------------------------------------------===//
// Widen Vector Operand
//===----------------------------------------------------------------------===//
bool DAGTypeLegalizer::WidenVectorOperand(SDNode *N, unsigned OpNo) {
  LLVM_DEBUG(dbgs() << "Widen node operand " << OpNo << ": "; N->dump(&DAG);
             dbgs() << "\n");
  SDValue Res = SDValue();

  // See if the target wants to custom widen this node.
  if (CustomLowerNode(N, N->getOperand(OpNo).getValueType(), false))
    return false;

  switch (N->getOpcode()) {
  default:
#ifndef NDEBUG
    dbgs() << "WidenVectorOperand op #" << OpNo << ": ";
    N->dump(&DAG);
    dbgs() << "\n";
#endif
    llvm_unreachable("Do not know how to widen this operator's operand!");

  case ISD::BITCAST:            Res = WidenVecOp_BITCAST(N); break;
  case ISD::CONCAT_VECTORS:     Res = WidenVecOp_CONCAT_VECTORS(N); break;
  case ISD::INSERT_SUBVECTOR:   Res = WidenVecOp_INSERT_SUBVECTOR(N); break;
  case ISD::EXTRACT_SUBVECTOR:  Res = WidenVecOp_EXTRACT_SUBVECTOR(N); break;
  case ISD::EXTRACT_VECTOR_ELT: Res = WidenVecOp_EXTRACT_VECTOR_ELT(N); break;
  case ISD::STORE:              Res = WidenVecOp_STORE(N); break;
  case ISD::MSTORE:             Res = WidenVecOp_MSTORE(N, OpNo); break;
  case ISD::MGATHER:            Res = WidenVecOp_MGATHER(N, OpNo); break;
  case ISD::MSCATTER:           Res = WidenVecOp_MSCATTER(N, OpNo); break;
  case ISD::SETCC:              Res = WidenVecOp_SETCC(N); break;
  case ISD::STRICT_FSETCC:
  case ISD::STRICT_FSETCCS:     Res = WidenVecOp_STRICT_FSETCC(N); break;
  case ISD::VSELECT:            Res = WidenVecOp_VSELECT(N); break;
  case ISD::FCOPYSIGN:          Res = WidenVecOp_FCOPYSIGN(N); break;

  case ISD::ANY_EXTEND:
  case ISD::SIGN_EXTEND:
  case ISD::ZERO_EXTEND:
    Res = WidenVecOp_EXTEND(N);
    break;

  case ISD::FP_EXTEND:
  case ISD::STRICT_FP_EXTEND:
  case ISD::FP_ROUND:
  case ISD::STRICT_FP_ROUND:
  case ISD::FP_TO_SINT:
  case ISD::STRICT_FP_TO_SINT:
  case ISD::FP_TO_UINT:
  case ISD::STRICT_FP_TO_UINT:
  case ISD::SINT_TO_FP:
  case ISD::STRICT_SINT_TO_FP:
  case ISD::UINT_TO_FP:
  case ISD::STRICT_UINT_TO_FP:
  case ISD::TRUNCATE:
    Res = WidenVecOp_Convert(N);
    break;

  case ISD::FP_TO_SINT_SAT:
  case ISD::FP_TO_UINT_SAT:
    Res = WidenVecOp_FP_TO_XINT_SAT(N);
    break;

  case ISD::VECREDUCE_FADD:
  case ISD::VECREDUCE_FMUL:
  case ISD::VECREDUCE_ADD:
  case ISD::VECREDUCE_MUL:
  case ISD::VECREDUCE_AND:
  case ISD::VECREDUCE_OR:
  case ISD::VECREDUCE_XOR:
  case ISD::VECREDUCE_SMAX:
  case ISD::VECREDUCE_SMIN:
  case ISD::VECREDUCE_UMAX:
  case ISD::VECREDUCE_UMIN:
  case ISD::VECREDUCE_FMAX:
  case ISD::VECREDUCE_FMIN:
    Res = WidenVecOp_VECREDUCE(N);
    break;
  case ISD::VECREDUCE_SEQ_FADD:
  case ISD::VECREDUCE_SEQ_FMUL:
    Res = WidenVecOp_VECREDUCE_SEQ(N);
    break;
  }

  // If Res is null, the sub-method took care of registering the result.
  if (!Res.getNode()) return false;

  // If the result is N, the sub-method updated N in place.  Tell the legalizer
  // core about this.
  if (Res.getNode() == N)
    return true;


  if (N->isStrictFPOpcode())
    assert(Res.getValueType() == N->getValueType(0) && N->getNumValues() == 2 &&
           "Invalid operand expansion");
  else
    assert(Res.getValueType() == N->getValueType(0) && N->getNumValues() == 1 &&
           "Invalid operand expansion");

  ReplaceValueWith(SDValue(N, 0), Res);
  return false;
}

SDValue DAGTypeLegalizer::WidenVecOp_EXTEND(SDNode *N) {
  SDLoc DL(N);
  EVT VT = N->getValueType(0);

  SDValue InOp = N->getOperand(0);
  assert(getTypeAction(InOp.getValueType()) ==
             TargetLowering::TypeWidenVector &&
         "Unexpected type action");
  InOp = GetWidenedVector(InOp);
  assert(VT.getVectorNumElements() <
             InOp.getValueType().getVectorNumElements() &&
         "Input wasn't widened!");

  // We may need to further widen the operand until it has the same total
  // vector size as the result.
  EVT InVT = InOp.getValueType();
  if (InVT.getSizeInBits() != VT.getSizeInBits()) {
    EVT InEltVT = InVT.getVectorElementType();
    for (EVT FixedVT : MVT::vector_valuetypes()) {
      EVT FixedEltVT = FixedVT.getVectorElementType();
      if (TLI.isTypeLegal(FixedVT) &&
          FixedVT.getSizeInBits() == VT.getSizeInBits() &&
          FixedEltVT == InEltVT) {
        assert(FixedVT.getVectorNumElements() >= VT.getVectorNumElements() &&
               "Not enough elements in the fixed type for the operand!");
        assert(FixedVT.getVectorNumElements() != InVT.getVectorNumElements() &&
               "We can't have the same type as we started with!");
        if (FixedVT.getVectorNumElements() > InVT.getVectorNumElements())
          InOp = DAG.getNode(ISD::INSERT_SUBVECTOR, DL, FixedVT,
                             DAG.getUNDEF(FixedVT), InOp,
                             DAG.getVectorIdxConstant(0, DL));
        else
          InOp = DAG.getNode(ISD::EXTRACT_SUBVECTOR, DL, FixedVT, InOp,
                             DAG.getVectorIdxConstant(0, DL));
        break;
      }
    }
    InVT = InOp.getValueType();
    if (InVT.getSizeInBits() != VT.getSizeInBits())
      // We couldn't find a legal vector type that was a widening of the input
      // and could be extended in-register to the result type, so we have to
      // scalarize.
      return WidenVecOp_Convert(N);
  }

  // Use special DAG nodes to represent the operation of extending the
  // low lanes.
  switch (N->getOpcode()) {
  default:
    llvm_unreachable("Extend legalization on extend operation!");
  case ISD::ANY_EXTEND:
    return DAG.getNode(ISD::ANY_EXTEND_VECTOR_INREG, DL, VT, InOp);
  case ISD::SIGN_EXTEND:
    return DAG.getNode(ISD::SIGN_EXTEND_VECTOR_INREG, DL, VT, InOp);
  case ISD::ZERO_EXTEND:
    return DAG.getNode(ISD::ZERO_EXTEND_VECTOR_INREG, DL, VT, InOp);
  }
}

SDValue DAGTypeLegalizer::WidenVecOp_FCOPYSIGN(SDNode *N) {
  // The result (and first input) is legal, but the second input is illegal.
  // We can't do much to fix that, so just unroll and let the extracts off of
  // the second input be widened as needed later.
  return DAG.UnrollVectorOp(N);
}

SDValue DAGTypeLegalizer::WidenVecOp_Convert(SDNode *N) {
  // Since the result is legal and the input is illegal.
  EVT VT = N->getValueType(0);
  EVT EltVT = VT.getVectorElementType();
  SDLoc dl(N);
  unsigned NumElts = VT.getVectorNumElements();
  SDValue InOp = N->getOperand(N->isStrictFPOpcode() ? 1 : 0);
  assert(getTypeAction(InOp.getValueType()) ==
             TargetLowering::TypeWidenVector &&
         "Unexpected type action");
  InOp = GetWidenedVector(InOp);
  EVT InVT = InOp.getValueType();
  unsigned Opcode = N->getOpcode();

  // See if a widened result type would be legal, if so widen the node.
  // FIXME: This isn't safe for StrictFP. Other optimization here is needed.
  EVT WideVT = EVT::getVectorVT(*DAG.getContext(), EltVT,
                                InVT.getVectorNumElements());
  if (TLI.isTypeLegal(WideVT) && !N->isStrictFPOpcode()) {
    SDValue Res;
    if (N->isStrictFPOpcode()) {
      if (Opcode == ISD::STRICT_FP_ROUND)
        Res = DAG.getNode(Opcode, dl, { WideVT, MVT::Other },
                          { N->getOperand(0), InOp, N->getOperand(2) });
      else
        Res = DAG.getNode(Opcode, dl, { WideVT, MVT::Other },
                          { N->getOperand(0), InOp });
      // Legalize the chain result - switch anything that used the old chain to
      // use the new one.
      ReplaceValueWith(SDValue(N, 1), Res.getValue(1));
    } else {
      if (Opcode == ISD::FP_ROUND)
        Res = DAG.getNode(Opcode, dl, WideVT, InOp, N->getOperand(1));
      else
        Res = DAG.getNode(Opcode, dl, WideVT, InOp);
    }
    return DAG.getNode(ISD::EXTRACT_SUBVECTOR, dl, VT, Res,
                       DAG.getVectorIdxConstant(0, dl));
  }

  EVT InEltVT = InVT.getVectorElementType();

  // Unroll the convert into some scalar code and create a nasty build vector.
  SmallVector<SDValue, 16> Ops(NumElts);
  if (N->isStrictFPOpcode()) {
    SmallVector<SDValue, 4> NewOps(N->op_begin(), N->op_end());
    SmallVector<SDValue, 32> OpChains;
    for (unsigned i=0; i < NumElts; ++i) {
      NewOps[1] = DAG.getNode(ISD::EXTRACT_VECTOR_ELT, dl, InEltVT, InOp,
                              DAG.getVectorIdxConstant(i, dl));
      Ops[i] = DAG.getNode(Opcode, dl, { EltVT, MVT::Other }, NewOps);
      OpChains.push_back(Ops[i].getValue(1));
    }
    SDValue NewChain = DAG.getNode(ISD::TokenFactor, dl, MVT::Other, OpChains);
    ReplaceValueWith(SDValue(N, 1), NewChain);
  } else {
    for (unsigned i = 0; i < NumElts; ++i)
      Ops[i] = DAG.getNode(Opcode, dl, EltVT,
                           DAG.getNode(ISD::EXTRACT_VECTOR_ELT, dl, InEltVT,
                                       InOp, DAG.getVectorIdxConstant(i, dl)));
  }

  return DAG.getBuildVector(VT, dl, Ops);
}

SDValue DAGTypeLegalizer::WidenVecOp_FP_TO_XINT_SAT(SDNode *N) {
  EVT DstVT = N->getValueType(0);
  SDValue Src = GetWidenedVector(N->getOperand(0));
  EVT SrcVT = Src.getValueType();
  ElementCount WideNumElts = SrcVT.getVectorElementCount();
  SDLoc dl(N);

  // See if a widened result type would be legal, if so widen the node.
  EVT WideDstVT = EVT::getVectorVT(*DAG.getContext(),
                                   DstVT.getVectorElementType(), WideNumElts);
  if (TLI.isTypeLegal(WideDstVT)) {
    SDValue Res =
        DAG.getNode(N->getOpcode(), dl, WideDstVT, Src, N->getOperand(1));
    return DAG.getNode(
        ISD::EXTRACT_SUBVECTOR, dl, DstVT, Res,
        DAG.getConstant(0, dl, TLI.getVectorIdxTy(DAG.getDataLayout())));
  }

  // Give up and unroll.
  return DAG.UnrollVectorOp(N);
}

SDValue DAGTypeLegalizer::WidenVecOp_BITCAST(SDNode *N) {
  EVT VT = N->getValueType(0);
  SDValue InOp = GetWidenedVector(N->getOperand(0));
  EVT InWidenVT = InOp.getValueType();
  SDLoc dl(N);

  // Check if we can convert between two legal vector types and extract.
  unsigned InWidenSize = InWidenVT.getSizeInBits();
  unsigned Size = VT.getSizeInBits();
  // x86mmx is not an acceptable vector element type, so don't try.
  if (InWidenSize % Size == 0 && !VT.isVector() && VT != MVT::x86mmx) {
    unsigned NewNumElts = InWidenSize / Size;
    EVT NewVT = EVT::getVectorVT(*DAG.getContext(), VT, NewNumElts);
    if (TLI.isTypeLegal(NewVT)) {
      SDValue BitOp = DAG.getNode(ISD::BITCAST, dl, NewVT, InOp);
      return DAG.getNode(ISD::EXTRACT_VECTOR_ELT, dl, VT, BitOp,
                         DAG.getVectorIdxConstant(0, dl));
    }
  }

  // Handle a case like bitcast v12i8 -> v3i32. Normally that would get widened
  // to v16i8 -> v4i32, but for a target where v3i32 is legal but v12i8 is not,
  // we end up here. Handling the case here with EXTRACT_SUBVECTOR avoids
  // having to copy via memory.
  if (VT.isVector()) {
    EVT EltVT = VT.getVectorElementType();
    unsigned EltSize = EltVT.getSizeInBits();
    if (InWidenSize % EltSize == 0) {
      unsigned NewNumElts = InWidenSize / EltSize;
      EVT NewVT = EVT::getVectorVT(*DAG.getContext(), EltVT, NewNumElts);
      if (TLI.isTypeLegal(NewVT)) {
        SDValue BitOp = DAG.getNode(ISD::BITCAST, dl, NewVT, InOp);
        return DAG.getNode(ISD::EXTRACT_SUBVECTOR, dl, VT, BitOp,
                           DAG.getVectorIdxConstant(0, dl));
      }
    }
  }

  return CreateStackStoreLoad(InOp, VT);
}

SDValue DAGTypeLegalizer::WidenVecOp_CONCAT_VECTORS(SDNode *N) {
  EVT VT = N->getValueType(0);
  EVT EltVT = VT.getVectorElementType();
  EVT InVT = N->getOperand(0).getValueType();
  SDLoc dl(N);

  // If the widen width for this operand is the same as the width of the concat
  // and all but the first operand is undef, just use the widened operand.
  unsigned NumOperands = N->getNumOperands();
  if (VT == TLI.getTypeToTransformTo(*DAG.getContext(), InVT)) {
    unsigned i;
    for (i = 1; i < NumOperands; ++i)
      if (!N->getOperand(i).isUndef())
        break;

    if (i == NumOperands)
      return GetWidenedVector(N->getOperand(0));
  }

  // Otherwise, fall back to a nasty build vector.
  unsigned NumElts = VT.getVectorNumElements();
  SmallVector<SDValue, 16> Ops(NumElts);

  unsigned NumInElts = InVT.getVectorNumElements();

  unsigned Idx = 0;
  for (unsigned i=0; i < NumOperands; ++i) {
    SDValue InOp = N->getOperand(i);
    assert(getTypeAction(InOp.getValueType()) ==
               TargetLowering::TypeWidenVector &&
           "Unexpected type action");
    InOp = GetWidenedVector(InOp);
    for (unsigned j = 0; j < NumInElts; ++j)
      Ops[Idx++] = DAG.getNode(ISD::EXTRACT_VECTOR_ELT, dl, EltVT, InOp,
                               DAG.getVectorIdxConstant(j, dl));
  }
  return DAG.getBuildVector(VT, dl, Ops);
}

SDValue DAGTypeLegalizer::WidenVecOp_INSERT_SUBVECTOR(SDNode *N) {
  SDValue SubVec = N->getOperand(1);
  SDValue InVec = N->getOperand(0);

  if (getTypeAction(InVec.getValueType()) == TargetLowering::TypeWidenVector)
    InVec = GetWidenedVector(InVec);

  if (getTypeAction(SubVec.getValueType()) == TargetLowering::TypeWidenVector)
    SubVec = GetWidenedVector(SubVec);

  if (SubVec.getValueType() == InVec.getValueType() && InVec.isUndef() &&
      N->getConstantOperandVal(2) == 0)
    return SubVec;

  report_fatal_error("Don't know how to widen the operands for "
                     "INSERT_SUBVECTOR");
}

SDValue DAGTypeLegalizer::WidenVecOp_EXTRACT_SUBVECTOR(SDNode *N) {
  SDValue InOp = GetWidenedVector(N->getOperand(0));
  return DAG.getNode(ISD::EXTRACT_SUBVECTOR, SDLoc(N),
                     N->getValueType(0), InOp, N->getOperand(1));
}

SDValue DAGTypeLegalizer::WidenVecOp_EXTRACT_VECTOR_ELT(SDNode *N) {
  SDValue InOp = GetWidenedVector(N->getOperand(0));
  return DAG.getNode(ISD::EXTRACT_VECTOR_ELT, SDLoc(N),
                     N->getValueType(0), InOp, N->getOperand(1));
}

SDValue DAGTypeLegalizer::WidenVecOp_STORE(SDNode *N) {
  // We have to widen the value, but we want only to store the original
  // vector type.
  StoreSDNode *ST = cast<StoreSDNode>(N);

  if (!ST->getMemoryVT().getScalarType().isByteSized())
    return TLI.scalarizeVectorStore(ST, DAG);

  if (ST->isTruncatingStore())
    return TLI.scalarizeVectorStore(ST, DAG);

  SmallVector<SDValue, 16> StChain;
  if (GenWidenVectorStores(StChain, ST)) {
    if (StChain.size() == 1)
      return StChain[0];

    return DAG.getNode(ISD::TokenFactor, SDLoc(ST), MVT::Other, StChain);
  }

  // Generate a vector-predicated store if it is custom/legal on the target.
  // To avoid possible recursion, only do this if the widened mask type is
  // legal.
  // FIXME: Not all targets may support EVL in VP_STORE. These will have been
  // removed from the IR by the ExpandVectorPredication pass but we're
  // reintroducing them here.
  SDValue StVal = ST->getValue();
  EVT StVT = StVal.getValueType();
  EVT WideVT = TLI.getTypeToTransformTo(*DAG.getContext(), StVT);
  EVT WideMaskVT = EVT::getVectorVT(*DAG.getContext(), MVT::i1,
                                    WideVT.getVectorElementCount());
  if (WideVT.isScalableVector() &&
      TLI.isOperationLegalOrCustom(ISD::VP_STORE, WideVT) &&
      TLI.isTypeLegal(WideMaskVT)) {
    // Widen the value.
    SDLoc DL(N);
    StVal = GetWidenedVector(StVal);
    SDValue Mask = DAG.getAllOnesConstant(DL, WideMaskVT);
    MVT EVLVT = TLI.getVPExplicitVectorLengthTy();
    unsigned NumVTElts = StVT.getVectorMinNumElements();
    SDValue EVL =
        DAG.getVScale(DL, EVLVT, APInt(EVLVT.getScalarSizeInBits(), NumVTElts));
    const auto *MMO = ST->getMemOperand();
    return DAG.getStoreVP(ST->getChain(), DL, StVal, ST->getBasePtr(), Mask,
                          EVL, MMO->getPointerInfo(), MMO->getAlign(),
                          MMO->getFlags(), MMO->getAAInfo());
  }

  report_fatal_error("Unable to widen vector store");
}

SDValue DAGTypeLegalizer::WidenVecOp_MSTORE(SDNode *N, unsigned OpNo) {
  assert((OpNo == 1 || OpNo == 3) &&
         "Can widen only data or mask operand of mstore");
  MaskedStoreSDNode *MST = cast<MaskedStoreSDNode>(N);
  SDValue Mask = MST->getMask();
  EVT MaskVT = Mask.getValueType();
  SDValue StVal = MST->getValue();
  SDLoc dl(N);

  if (OpNo == 1) {
    // Widen the value.
    StVal = GetWidenedVector(StVal);

    // The mask should be widened as well.
    EVT WideVT = StVal.getValueType();
    EVT WideMaskVT = EVT::getVectorVT(*DAG.getContext(),
                                      MaskVT.getVectorElementType(),
                                      WideVT.getVectorNumElements());
    Mask = ModifyToType(Mask, WideMaskVT, true);
  } else {
    // Widen the mask.
    EVT WideMaskVT = TLI.getTypeToTransformTo(*DAG.getContext(), MaskVT);
    Mask = ModifyToType(Mask, WideMaskVT, true);

    EVT ValueVT = StVal.getValueType();
    EVT WideVT = EVT::getVectorVT(*DAG.getContext(),
                                  ValueVT.getVectorElementType(),
                                  WideMaskVT.getVectorNumElements());
    StVal = ModifyToType(StVal, WideVT);
  }

  assert(Mask.getValueType().getVectorNumElements() ==
         StVal.getValueType().getVectorNumElements() &&
         "Mask and data vectors should have the same number of elements");
  return DAG.getMaskedStore(MST->getChain(), dl, StVal, MST->getBasePtr(),
                            MST->getOffset(), Mask, MST->getMemoryVT(),
                            MST->getMemOperand(), MST->getAddressingMode(),
                            false, MST->isCompressingStore());
}

SDValue DAGTypeLegalizer::WidenVecOp_MGATHER(SDNode *N, unsigned OpNo) {
  assert(OpNo == 4 && "Can widen only the index of mgather");
  auto *MG = cast<MaskedGatherSDNode>(N);
  SDValue DataOp = MG->getPassThru();
  SDValue Mask = MG->getMask();
  SDValue Scale = MG->getScale();

  // Just widen the index. It's allowed to have extra elements.
  SDValue Index = GetWidenedVector(MG->getIndex());

  SDLoc dl(N);
  SDValue Ops[] = {MG->getChain(), DataOp, Mask, MG->getBasePtr(), Index,
                   Scale};
  SDValue Res = DAG.getMaskedGather(MG->getVTList(), MG->getMemoryVT(), dl, Ops,
                                    MG->getMemOperand(), MG->getIndexType(),
                                    MG->getExtensionType());
  ReplaceValueWith(SDValue(N, 1), Res.getValue(1));
  ReplaceValueWith(SDValue(N, 0), Res.getValue(0));
  return SDValue();
}

SDValue DAGTypeLegalizer::WidenVecOp_MSCATTER(SDNode *N, unsigned OpNo) {
  MaskedScatterSDNode *MSC = cast<MaskedScatterSDNode>(N);
  SDValue DataOp = MSC->getValue();
  SDValue Mask = MSC->getMask();
  SDValue Index = MSC->getIndex();
  SDValue Scale = MSC->getScale();
  EVT WideMemVT = MSC->getMemoryVT();

  if (OpNo == 1) {
    DataOp = GetWidenedVector(DataOp);
    unsigned NumElts = DataOp.getValueType().getVectorNumElements();

    // Widen index.
    EVT IndexVT = Index.getValueType();
    EVT WideIndexVT = EVT::getVectorVT(*DAG.getContext(),
                                       IndexVT.getVectorElementType(), NumElts);
    Index = ModifyToType(Index, WideIndexVT);

    // The mask should be widened as well.
    EVT MaskVT = Mask.getValueType();
    EVT WideMaskVT = EVT::getVectorVT(*DAG.getContext(),
                                      MaskVT.getVectorElementType(), NumElts);
    Mask = ModifyToType(Mask, WideMaskVT, true);

    // Widen the MemoryType
    WideMemVT = EVT::getVectorVT(*DAG.getContext(),
                                 MSC->getMemoryVT().getScalarType(), NumElts);
  } else if (OpNo == 4) {
    // Just widen the index. It's allowed to have extra elements.
    Index = GetWidenedVector(Index);
  } else
    llvm_unreachable("Can't widen this operand of mscatter");

  SDValue Ops[] = {MSC->getChain(), DataOp, Mask, MSC->getBasePtr(), Index,
                   Scale};
  return DAG.getMaskedScatter(DAG.getVTList(MVT::Other), WideMemVT, SDLoc(N),
                              Ops, MSC->getMemOperand(), MSC->getIndexType(),
                              MSC->isTruncatingStore());
}

SDValue DAGTypeLegalizer::WidenVecOp_SETCC(SDNode *N) {
  SDValue InOp0 = GetWidenedVector(N->getOperand(0));
  SDValue InOp1 = GetWidenedVector(N->getOperand(1));
  SDLoc dl(N);
  EVT VT = N->getValueType(0);

  // WARNING: In this code we widen the compare instruction with garbage.
  // This garbage may contain denormal floats which may be slow. Is this a real
  // concern ? Should we zero the unused lanes if this is a float compare ?

  // Get a new SETCC node to compare the newly widened operands.
  // Only some of the compared elements are legal.
  EVT SVT = getSetCCResultType(InOp0.getValueType());
  // The result type is legal, if its vXi1, keep vXi1 for the new SETCC.
  if (VT.getScalarType() == MVT::i1)
    SVT = EVT::getVectorVT(*DAG.getContext(), MVT::i1,
                           SVT.getVectorNumElements());

  SDValue WideSETCC = DAG.getNode(ISD::SETCC, SDLoc(N),
                                  SVT, InOp0, InOp1, N->getOperand(2));

  // Extract the needed results from the result vector.
  EVT ResVT = EVT::getVectorVT(*DAG.getContext(),
                               SVT.getVectorElementType(),
                               VT.getVectorNumElements());
  SDValue CC = DAG.getNode(ISD::EXTRACT_SUBVECTOR, dl, ResVT, WideSETCC,
                           DAG.getVectorIdxConstant(0, dl));

  EVT OpVT = N->getOperand(0).getValueType();
  ISD::NodeType ExtendCode =
      TargetLowering::getExtendForContent(TLI.getBooleanContents(OpVT));
  return DAG.getNode(ExtendCode, dl, VT, CC);
}

SDValue DAGTypeLegalizer::WidenVecOp_STRICT_FSETCC(SDNode *N) {
  SDValue Chain = N->getOperand(0);
  SDValue LHS = GetWidenedVector(N->getOperand(1));
  SDValue RHS = GetWidenedVector(N->getOperand(2));
  SDValue CC = N->getOperand(3);
  SDLoc dl(N);

  EVT VT = N->getValueType(0);
  EVT EltVT = VT.getVectorElementType();
  EVT TmpEltVT = LHS.getValueType().getVectorElementType();
  unsigned NumElts = VT.getVectorNumElements();

  // Unroll into a build vector.
  SmallVector<SDValue, 8> Scalars(NumElts);
  SmallVector<SDValue, 8> Chains(NumElts);

  for (unsigned i = 0; i != NumElts; ++i) {
    SDValue LHSElem = DAG.getNode(ISD::EXTRACT_VECTOR_ELT, dl, TmpEltVT, LHS,
                                  DAG.getVectorIdxConstant(i, dl));
    SDValue RHSElem = DAG.getNode(ISD::EXTRACT_VECTOR_ELT, dl, TmpEltVT, RHS,
                                  DAG.getVectorIdxConstant(i, dl));

    Scalars[i] = DAG.getNode(N->getOpcode(), dl, {MVT::i1, MVT::Other},
                             {Chain, LHSElem, RHSElem, CC});
    Chains[i] = Scalars[i].getValue(1);
    Scalars[i] = DAG.getSelect(dl, EltVT, Scalars[i],
                               DAG.getBoolConstant(true, dl, EltVT, VT),
                               DAG.getBoolConstant(false, dl, EltVT, VT));
  }

  SDValue NewChain = DAG.getNode(ISD::TokenFactor, dl, MVT::Other, Chains);
  ReplaceValueWith(SDValue(N, 1), NewChain);

  return DAG.getBuildVector(VT, dl, Scalars);
}

SDValue DAGTypeLegalizer::WidenVecOp_VECREDUCE(SDNode *N) {
  SDLoc dl(N);
  SDValue Op = GetWidenedVector(N->getOperand(0));
  EVT OrigVT = N->getOperand(0).getValueType();
  EVT WideVT = Op.getValueType();
  EVT ElemVT = OrigVT.getVectorElementType();
  SDNodeFlags Flags = N->getFlags();

  unsigned Opc = N->getOpcode();
  unsigned BaseOpc = ISD::getVecReduceBaseOpcode(Opc);
  SDValue NeutralElem = DAG.getNeutralElement(BaseOpc, dl, ElemVT, Flags);
  assert(NeutralElem && "Neutral element must exist");

  // Pad the vector with the neutral element.
  unsigned OrigElts = OrigVT.getVectorNumElements();
  unsigned WideElts = WideVT.getVectorNumElements();
  for (unsigned Idx = OrigElts; Idx < WideElts; Idx++)
    Op = DAG.getNode(ISD::INSERT_VECTOR_ELT, dl, WideVT, Op, NeutralElem,
                     DAG.getVectorIdxConstant(Idx, dl));

  return DAG.getNode(Opc, dl, N->getValueType(0), Op, Flags);
}

SDValue DAGTypeLegalizer::WidenVecOp_VECREDUCE_SEQ(SDNode *N) {
  SDLoc dl(N);
  SDValue AccOp = N->getOperand(0);
  SDValue VecOp = N->getOperand(1);
  SDValue Op = GetWidenedVector(VecOp);

  EVT OrigVT = VecOp.getValueType();
  EVT WideVT = Op.getValueType();
  EVT ElemVT = OrigVT.getVectorElementType();
  SDNodeFlags Flags = N->getFlags();

  unsigned Opc = N->getOpcode();
  unsigned BaseOpc = ISD::getVecReduceBaseOpcode(Opc);
  SDValue NeutralElem = DAG.getNeutralElement(BaseOpc, dl, ElemVT, Flags);

  // Pad the vector with the neutral element.
  unsigned OrigElts = OrigVT.getVectorNumElements();
  unsigned WideElts = WideVT.getVectorNumElements();
  for (unsigned Idx = OrigElts; Idx < WideElts; Idx++)
    Op = DAG.getNode(ISD::INSERT_VECTOR_ELT, dl, WideVT, Op, NeutralElem,
                     DAG.getVectorIdxConstant(Idx, dl));

  return DAG.getNode(Opc, dl, N->getValueType(0), AccOp, Op, Flags);
}

SDValue DAGTypeLegalizer::WidenVecOp_VSELECT(SDNode *N) {
  // This only gets called in the case that the left and right inputs and
  // result are of a legal odd vector type, and the condition is illegal i1 of
  // the same odd width that needs widening.
  EVT VT = N->getValueType(0);
  assert(VT.isVector() && !VT.isPow2VectorType() && isTypeLegal(VT));

  SDValue Cond = GetWidenedVector(N->getOperand(0));
  SDValue LeftIn = DAG.WidenVector(N->getOperand(1), SDLoc(N));
  SDValue RightIn = DAG.WidenVector(N->getOperand(2), SDLoc(N));
  SDLoc DL(N);

  SDValue Select = DAG.getNode(N->getOpcode(), DL, LeftIn.getValueType(), Cond,
                               LeftIn, RightIn);
  return DAG.getNode(ISD::EXTRACT_SUBVECTOR, DL, VT, Select,
                     DAG.getVectorIdxConstant(0, DL));
}

//===----------------------------------------------------------------------===//
// Vector Widening Utilities
//===----------------------------------------------------------------------===//

// Utility function to find the type to chop up a widen vector for load/store
//  TLI:       Target lowering used to determine legal types.
//  Width:     Width left need to load/store.
//  WidenVT:   The widen vector type to load to/store from
//  Align:     If 0, don't allow use of a wider type
//  WidenEx:   If Align is not 0, the amount additional we can load/store from.

static Optional<EVT> findMemType(SelectionDAG &DAG, const TargetLowering &TLI,
                                 unsigned Width, EVT WidenVT,
                                 unsigned Align = 0, unsigned WidenEx = 0) {
  EVT WidenEltVT = WidenVT.getVectorElementType();
  const bool Scalable = WidenVT.isScalableVector();
  unsigned WidenWidth = WidenVT.getSizeInBits().getKnownMinSize();
  unsigned WidenEltWidth = WidenEltVT.getSizeInBits();
  unsigned AlignInBits = Align*8;

  // If we have one element to load/store, return it.
  EVT RetVT = WidenEltVT;
  if (!Scalable && Width == WidenEltWidth)
    return RetVT;

  // Don't bother looking for an integer type if the vector is scalable, skip
  // to vector types.
  if (!Scalable) {
    // See if there is larger legal integer than the element type to load/store.
    for (EVT MemVT : reverse(MVT::integer_valuetypes())) {
      unsigned MemVTWidth = MemVT.getSizeInBits();
      if (MemVT.getSizeInBits() <= WidenEltWidth)
        break;
      auto Action = TLI.getTypeAction(*DAG.getContext(), MemVT);
      if ((Action == TargetLowering::TypeLegal ||
           Action == TargetLowering::TypePromoteInteger) &&
          (WidenWidth % MemVTWidth) == 0 &&
          isPowerOf2_32(WidenWidth / MemVTWidth) &&
          (MemVTWidth <= Width ||
           (Align!=0 && MemVTWidth<=AlignInBits && MemVTWidth<=Width+WidenEx))) {
        if (MemVTWidth == WidenWidth)
          return MemVT;
        RetVT = MemVT;
        break;
      }
    }
  }

  // See if there is a larger vector type to load/store that has the same vector
  // element type and is evenly divisible with the WidenVT.
  for (EVT MemVT : reverse(MVT::vector_valuetypes())) {
    // Skip vector MVTs which don't match the scalable property of WidenVT.
    if (Scalable != MemVT.isScalableVector())
      continue;
    unsigned MemVTWidth = MemVT.getSizeInBits().getKnownMinSize();
    auto Action = TLI.getTypeAction(*DAG.getContext(), MemVT);
    if ((Action == TargetLowering::TypeLegal ||
         Action == TargetLowering::TypePromoteInteger) &&
        WidenEltVT == MemVT.getVectorElementType() &&
        (WidenWidth % MemVTWidth) == 0 &&
        isPowerOf2_32(WidenWidth / MemVTWidth) &&
        (MemVTWidth <= Width ||
         (Align!=0 && MemVTWidth<=AlignInBits && MemVTWidth<=Width+WidenEx))) {
      if (RetVT.getFixedSizeInBits() < MemVTWidth || MemVT == WidenVT)
        return MemVT;
    }
  }

  // Using element-wise loads and stores for widening operations is not
  // supported for scalable vectors
  if (Scalable)
    return None;

  return RetVT;
}

// Builds a vector type from scalar loads
//  VecTy: Resulting Vector type
//  LDOps: Load operators to build a vector type
//  [Start,End) the list of loads to use.
static SDValue BuildVectorFromScalar(SelectionDAG& DAG, EVT VecTy,
                                     SmallVectorImpl<SDValue> &LdOps,
                                     unsigned Start, unsigned End) {
  SDLoc dl(LdOps[Start]);
  EVT LdTy = LdOps[Start].getValueType();
  unsigned Width = VecTy.getSizeInBits();
  unsigned NumElts = Width / LdTy.getSizeInBits();
  EVT NewVecVT = EVT::getVectorVT(*DAG.getContext(), LdTy, NumElts);

  unsigned Idx = 1;
  SDValue VecOp = DAG.getNode(ISD::SCALAR_TO_VECTOR, dl, NewVecVT,LdOps[Start]);

  for (unsigned i = Start + 1; i != End; ++i) {
    EVT NewLdTy = LdOps[i].getValueType();
    if (NewLdTy != LdTy) {
      NumElts = Width / NewLdTy.getSizeInBits();
      NewVecVT = EVT::getVectorVT(*DAG.getContext(), NewLdTy, NumElts);
      VecOp = DAG.getNode(ISD::BITCAST, dl, NewVecVT, VecOp);
      // Readjust position and vector position based on new load type.
      Idx = Idx * LdTy.getSizeInBits() / NewLdTy.getSizeInBits();
      LdTy = NewLdTy;
    }
    VecOp = DAG.getNode(ISD::INSERT_VECTOR_ELT, dl, NewVecVT, VecOp, LdOps[i],
                        DAG.getVectorIdxConstant(Idx++, dl));
  }
  return DAG.getNode(ISD::BITCAST, dl, VecTy, VecOp);
}

SDValue DAGTypeLegalizer::GenWidenVectorLoads(SmallVectorImpl<SDValue> &LdChain,
                                              LoadSDNode *LD) {
  // The strategy assumes that we can efficiently load power-of-two widths.
  // The routine chops the vector into the largest vector loads with the same
  // element type or scalar loads and then recombines it to the widen vector
  // type.
  EVT WidenVT = TLI.getTypeToTransformTo(*DAG.getContext(),LD->getValueType(0));
  EVT LdVT    = LD->getMemoryVT();
  SDLoc dl(LD);
  assert(LdVT.isVector() && WidenVT.isVector());
  assert(LdVT.isScalableVector() == WidenVT.isScalableVector());
  assert(LdVT.getVectorElementType() == WidenVT.getVectorElementType());

  // Load information
  SDValue Chain = LD->getChain();
  SDValue BasePtr = LD->getBasePtr();
  MachineMemOperand::Flags MMOFlags = LD->getMemOperand()->getFlags();
  AAMDNodes AAInfo = LD->getAAInfo();

  TypeSize LdWidth = LdVT.getSizeInBits();
  TypeSize WidenWidth = WidenVT.getSizeInBits();
  TypeSize WidthDiff = WidenWidth - LdWidth;
  // Allow wider loads if they are sufficiently aligned to avoid memory faults
  // and if the original load is simple.
  unsigned LdAlign =
      (!LD->isSimple() || LdVT.isScalableVector()) ? 0 : LD->getAlignment();

  // Find the vector type that can load from.
  Optional<EVT> FirstVT =
      findMemType(DAG, TLI, LdWidth.getKnownMinSize(), WidenVT, LdAlign,
                  WidthDiff.getKnownMinSize());

  if (!FirstVT)
    return SDValue();

  SmallVector<EVT, 8> MemVTs;
  TypeSize FirstVTWidth = FirstVT->getSizeInBits();

  // Unless we're able to load in one instruction we must work out how to load
  // the remainder.
  if (!TypeSize::isKnownLE(LdWidth, FirstVTWidth)) {
    Optional<EVT> NewVT = FirstVT;
    TypeSize RemainingWidth = LdWidth;
    TypeSize NewVTWidth = FirstVTWidth;
    do {
      RemainingWidth -= NewVTWidth;
      if (TypeSize::isKnownLT(RemainingWidth, NewVTWidth)) {
        // The current type we are using is too large. Find a better size.
        NewVT = findMemType(DAG, TLI, RemainingWidth.getKnownMinSize(), WidenVT,
                            LdAlign, WidthDiff.getKnownMinSize());
        if (!NewVT)
          return SDValue();
        NewVTWidth = NewVT->getSizeInBits();
      }
      MemVTs.push_back(*NewVT);
    } while (TypeSize::isKnownGT(RemainingWidth, NewVTWidth));
  }

  SDValue LdOp = DAG.getLoad(*FirstVT, dl, Chain, BasePtr, LD->getPointerInfo(),
                             LD->getOriginalAlign(), MMOFlags, AAInfo);
  LdChain.push_back(LdOp.getValue(1));

  // Check if we can load the element with one instruction.
  if (MemVTs.empty()) {
    assert(TypeSize::isKnownLE(LdWidth, FirstVTWidth));
    if (!FirstVT->isVector()) {
      unsigned NumElts =
          WidenWidth.getFixedSize() / FirstVTWidth.getFixedSize();
      EVT NewVecVT = EVT::getVectorVT(*DAG.getContext(), *FirstVT, NumElts);
      SDValue VecOp = DAG.getNode(ISD::SCALAR_TO_VECTOR, dl, NewVecVT, LdOp);
      return DAG.getNode(ISD::BITCAST, dl, WidenVT, VecOp);
    }
    if (FirstVT == WidenVT)
      return LdOp;

    // TODO: We don't currently have any tests that exercise this code path.
    assert(WidenWidth.getFixedSize() % FirstVTWidth.getFixedSize() == 0);
    unsigned NumConcat =
        WidenWidth.getFixedSize() / FirstVTWidth.getFixedSize();
    SmallVector<SDValue, 16> ConcatOps(NumConcat);
    SDValue UndefVal = DAG.getUNDEF(*FirstVT);
    ConcatOps[0] = LdOp;
    for (unsigned i = 1; i != NumConcat; ++i)
      ConcatOps[i] = UndefVal;
    return DAG.getNode(ISD::CONCAT_VECTORS, dl, WidenVT, ConcatOps);
  }

  // Load vector by using multiple loads from largest vector to scalar.
  SmallVector<SDValue, 16> LdOps;
  LdOps.push_back(LdOp);

  uint64_t ScaledOffset = 0;
  MachinePointerInfo MPI = LD->getPointerInfo();

  // First incremement past the first load.
  IncrementPointer(cast<LoadSDNode>(LdOp), *FirstVT, MPI, BasePtr,
                   &ScaledOffset);

  for (EVT MemVT : MemVTs) {
    Align NewAlign = ScaledOffset == 0
                         ? LD->getOriginalAlign()
                         : commonAlignment(LD->getAlign(), ScaledOffset);
    SDValue L =
        DAG.getLoad(MemVT, dl, Chain, BasePtr, MPI, NewAlign, MMOFlags, AAInfo);

    LdOps.push_back(L);
    LdChain.push_back(L.getValue(1));
    IncrementPointer(cast<LoadSDNode>(L), MemVT, MPI, BasePtr, &ScaledOffset);
  }

  // Build the vector from the load operations.
  unsigned End = LdOps.size();
  if (!LdOps[0].getValueType().isVector())
    // All the loads are scalar loads.
    return BuildVectorFromScalar(DAG, WidenVT, LdOps, 0, End);

  // If the load contains vectors, build the vector using concat vector.
  // All of the vectors used to load are power-of-2, and the scalar loads can be
  // combined to make a power-of-2 vector.
  SmallVector<SDValue, 16> ConcatOps(End);
  int i = End - 1;
  int Idx = End;
  EVT LdTy = LdOps[i].getValueType();
  // First, combine the scalar loads to a vector.
  if (!LdTy.isVector())  {
    for (--i; i >= 0; --i) {
      LdTy = LdOps[i].getValueType();
      if (LdTy.isVector())
        break;
    }
    ConcatOps[--Idx] = BuildVectorFromScalar(DAG, LdTy, LdOps, i + 1, End);
  }

  ConcatOps[--Idx] = LdOps[i];
  for (--i; i >= 0; --i) {
    EVT NewLdTy = LdOps[i].getValueType();
    if (NewLdTy != LdTy) {
      // Create a larger vector.
      TypeSize LdTySize = LdTy.getSizeInBits();
      TypeSize NewLdTySize = NewLdTy.getSizeInBits();
      assert(NewLdTySize.isScalable() == LdTySize.isScalable() &&
             NewLdTySize.isKnownMultipleOf(LdTySize.getKnownMinSize()));
      unsigned NumOps =
          NewLdTySize.getKnownMinSize() / LdTySize.getKnownMinSize();
      SmallVector<SDValue, 16> WidenOps(NumOps);
      unsigned j = 0;
      for (; j != End-Idx; ++j)
        WidenOps[j] = ConcatOps[Idx+j];
      for (; j != NumOps; ++j)
        WidenOps[j] = DAG.getUNDEF(LdTy);

      ConcatOps[End-1] = DAG.getNode(ISD::CONCAT_VECTORS, dl, NewLdTy,
                                     WidenOps);
      Idx = End - 1;
      LdTy = NewLdTy;
    }
    ConcatOps[--Idx] = LdOps[i];
  }

  if (WidenWidth == LdTy.getSizeInBits() * (End - Idx))
    return DAG.getNode(ISD::CONCAT_VECTORS, dl, WidenVT,
                       makeArrayRef(&ConcatOps[Idx], End - Idx));

  // We need to fill the rest with undefs to build the vector.
  unsigned NumOps =
      WidenWidth.getKnownMinSize() / LdTy.getSizeInBits().getKnownMinSize();
  SmallVector<SDValue, 16> WidenOps(NumOps);
  SDValue UndefVal = DAG.getUNDEF(LdTy);
  {
    unsigned i = 0;
    for (; i != End-Idx; ++i)
      WidenOps[i] = ConcatOps[Idx+i];
    for (; i != NumOps; ++i)
      WidenOps[i] = UndefVal;
  }
  return DAG.getNode(ISD::CONCAT_VECTORS, dl, WidenVT, WidenOps);
}

SDValue
DAGTypeLegalizer::GenWidenVectorExtLoads(SmallVectorImpl<SDValue> &LdChain,
                                         LoadSDNode *LD,
                                         ISD::LoadExtType ExtType) {
  // For extension loads, it may not be more efficient to chop up the vector
  // and then extend it. Instead, we unroll the load and build a new vector.
  EVT WidenVT = TLI.getTypeToTransformTo(*DAG.getContext(),LD->getValueType(0));
  EVT LdVT    = LD->getMemoryVT();
  SDLoc dl(LD);
  assert(LdVT.isVector() && WidenVT.isVector());
  assert(LdVT.isScalableVector() == WidenVT.isScalableVector());

  // Load information
  SDValue Chain = LD->getChain();
  SDValue BasePtr = LD->getBasePtr();
  MachineMemOperand::Flags MMOFlags = LD->getMemOperand()->getFlags();
  AAMDNodes AAInfo = LD->getAAInfo();

  if (LdVT.isScalableVector())
    report_fatal_error("Generating widen scalable extending vector loads is "
                       "not yet supported");

  EVT EltVT = WidenVT.getVectorElementType();
  EVT LdEltVT = LdVT.getVectorElementType();
  unsigned NumElts = LdVT.getVectorNumElements();

  // Load each element and widen.
  unsigned WidenNumElts = WidenVT.getVectorNumElements();
  SmallVector<SDValue, 16> Ops(WidenNumElts);
  unsigned Increment = LdEltVT.getSizeInBits() / 8;
  Ops[0] =
      DAG.getExtLoad(ExtType, dl, EltVT, Chain, BasePtr, LD->getPointerInfo(),
                     LdEltVT, LD->getOriginalAlign(), MMOFlags, AAInfo);
  LdChain.push_back(Ops[0].getValue(1));
  unsigned i = 0, Offset = Increment;
  for (i=1; i < NumElts; ++i, Offset += Increment) {
    SDValue NewBasePtr =
        DAG.getObjectPtrOffset(dl, BasePtr, TypeSize::Fixed(Offset));
    Ops[i] = DAG.getExtLoad(ExtType, dl, EltVT, Chain, NewBasePtr,
                            LD->getPointerInfo().getWithOffset(Offset), LdEltVT,
                            LD->getOriginalAlign(), MMOFlags, AAInfo);
    LdChain.push_back(Ops[i].getValue(1));
  }

  // Fill the rest with undefs.
  SDValue UndefVal = DAG.getUNDEF(EltVT);
  for (; i != WidenNumElts; ++i)
    Ops[i] = UndefVal;

  return DAG.getBuildVector(WidenVT, dl, Ops);
}

bool DAGTypeLegalizer::GenWidenVectorStores(SmallVectorImpl<SDValue> &StChain,
                                            StoreSDNode *ST) {
  // The strategy assumes that we can efficiently store power-of-two widths.
  // The routine chops the vector into the largest vector stores with the same
  // element type or scalar stores.
  SDValue  Chain = ST->getChain();
  SDValue  BasePtr = ST->getBasePtr();
  MachineMemOperand::Flags MMOFlags = ST->getMemOperand()->getFlags();
  AAMDNodes AAInfo = ST->getAAInfo();
  SDValue  ValOp = GetWidenedVector(ST->getValue());
  SDLoc dl(ST);

  EVT StVT = ST->getMemoryVT();
  TypeSize StWidth = StVT.getSizeInBits();
  EVT ValVT = ValOp.getValueType();
  TypeSize ValWidth = ValVT.getSizeInBits();
  EVT ValEltVT = ValVT.getVectorElementType();
  unsigned ValEltWidth = ValEltVT.getFixedSizeInBits();
  assert(StVT.getVectorElementType() == ValEltVT);
  assert(StVT.isScalableVector() == ValVT.isScalableVector() &&
         "Mismatch between store and value types");

  int Idx = 0;          // current index to store

  MachinePointerInfo MPI = ST->getPointerInfo();
  uint64_t ScaledOffset = 0;

  // A breakdown of how to widen this vector store. Each element of the vector
  // is a memory VT combined with the number of times it is to be stored to,
  // e,g., v5i32 -> {{v2i32,2},{i32,1}}
  SmallVector<std::pair<EVT, unsigned>, 4> MemVTs;

  while (StWidth.isNonZero()) {
    // Find the largest vector type we can store with.
    Optional<EVT> NewVT =
        findMemType(DAG, TLI, StWidth.getKnownMinSize(), ValVT);
    if (!NewVT)
      return false;
    MemVTs.push_back({*NewVT, 0});
    TypeSize NewVTWidth = NewVT->getSizeInBits();

    do {
      StWidth -= NewVTWidth;
      MemVTs.back().second++;
    } while (StWidth.isNonZero() && TypeSize::isKnownGE(StWidth, NewVTWidth));
  }

  for (const auto &Pair : MemVTs) {
    EVT NewVT = Pair.first;
    unsigned Count = Pair.second;
    TypeSize NewVTWidth = NewVT.getSizeInBits();

    if (NewVT.isVector()) {
      unsigned NumVTElts = NewVT.getVectorMinNumElements();
      do {
        Align NewAlign = ScaledOffset == 0
                             ? ST->getOriginalAlign()
                             : commonAlignment(ST->getAlign(), ScaledOffset);
        SDValue EOp = DAG.getNode(ISD::EXTRACT_SUBVECTOR, dl, NewVT, ValOp,
                                  DAG.getVectorIdxConstant(Idx, dl));
        SDValue PartStore = DAG.getStore(Chain, dl, EOp, BasePtr, MPI, NewAlign,
                                         MMOFlags, AAInfo);
        StChain.push_back(PartStore);

        Idx += NumVTElts;
        IncrementPointer(cast<StoreSDNode>(PartStore), NewVT, MPI, BasePtr,
                         &ScaledOffset);
      } while (--Count);
    } else {
      // Cast the vector to the scalar type we can store.
      unsigned NumElts = ValWidth.getFixedSize() / NewVTWidth.getFixedSize();
      EVT NewVecVT = EVT::getVectorVT(*DAG.getContext(), NewVT, NumElts);
      SDValue VecOp = DAG.getNode(ISD::BITCAST, dl, NewVecVT, ValOp);
      // Readjust index position based on new vector type.
      Idx = Idx * ValEltWidth / NewVTWidth.getFixedSize();
      do {
        SDValue EOp = DAG.getNode(ISD::EXTRACT_VECTOR_ELT, dl, NewVT, VecOp,
                                  DAG.getVectorIdxConstant(Idx++, dl));
        SDValue PartStore =
            DAG.getStore(Chain, dl, EOp, BasePtr, MPI, ST->getOriginalAlign(),
                         MMOFlags, AAInfo);
        StChain.push_back(PartStore);

        IncrementPointer(cast<StoreSDNode>(PartStore), NewVT, MPI, BasePtr);
      } while (--Count);
      // Restore index back to be relative to the original widen element type.
      Idx = Idx * NewVTWidth.getFixedSize() / ValEltWidth;
    }
  }

  return true;
}

/// Modifies a vector input (widen or narrows) to a vector of NVT.  The
/// input vector must have the same element type as NVT.
/// FillWithZeroes specifies that the vector should be widened with zeroes.
SDValue DAGTypeLegalizer::ModifyToType(SDValue InOp, EVT NVT,
                                       bool FillWithZeroes) {
  // Note that InOp might have been widened so it might already have
  // the right width or it might need be narrowed.
  EVT InVT = InOp.getValueType();
  assert(InVT.getVectorElementType() == NVT.getVectorElementType() &&
         "input and widen element type must match");
  SDLoc dl(InOp);

  // Check if InOp already has the right width.
  if (InVT == NVT)
    return InOp;

  unsigned InNumElts = InVT.getVectorNumElements();
  unsigned WidenNumElts = NVT.getVectorNumElements();
  if (WidenNumElts > InNumElts && WidenNumElts % InNumElts == 0) {
    unsigned NumConcat = WidenNumElts / InNumElts;
    SmallVector<SDValue, 16> Ops(NumConcat);
    SDValue FillVal = FillWithZeroes ? DAG.getConstant(0, dl, InVT) :
      DAG.getUNDEF(InVT);
    Ops[0] = InOp;
    for (unsigned i = 1; i != NumConcat; ++i)
      Ops[i] = FillVal;

    return DAG.getNode(ISD::CONCAT_VECTORS, dl, NVT, Ops);
  }

  if (WidenNumElts < InNumElts && InNumElts % WidenNumElts)
    return DAG.getNode(ISD::EXTRACT_SUBVECTOR, dl, NVT, InOp,
                       DAG.getVectorIdxConstant(0, dl));

  // Fall back to extract and build.
  SmallVector<SDValue, 16> Ops(WidenNumElts);
  EVT EltVT = NVT.getVectorElementType();
  unsigned MinNumElts = std::min(WidenNumElts, InNumElts);
  unsigned Idx;
  for (Idx = 0; Idx < MinNumElts; ++Idx)
    Ops[Idx] = DAG.getNode(ISD::EXTRACT_VECTOR_ELT, dl, EltVT, InOp,
                           DAG.getVectorIdxConstant(Idx, dl));

  SDValue FillVal = FillWithZeroes ? DAG.getConstant(0, dl, EltVT) :
    DAG.getUNDEF(EltVT);
  for ( ; Idx < WidenNumElts; ++Idx)
    Ops[Idx] = FillVal;
  return DAG.getBuildVector(NVT, dl, Ops);
}

void DAGTypeLegalizer::SplitVecRes_VECTOR_REVERSE(SDNode *N, SDValue &Lo,
                                                  SDValue &Hi) {
  SDValue InLo, InHi;
  GetSplitVector(N->getOperand(0), InLo, InHi);
  SDLoc DL(N);

  Lo = DAG.getNode(ISD::VECTOR_REVERSE, DL, InHi.getValueType(), InHi);
  Hi = DAG.getNode(ISD::VECTOR_REVERSE, DL, InLo.getValueType(), InLo);
}

void DAGTypeLegalizer::SplitVecRes_VECTOR_SPLICE(SDNode *N, SDValue &Lo,
                                                 SDValue &Hi) {
  EVT VT = N->getValueType(0);
  SDLoc DL(N);

  EVT LoVT, HiVT;
  std::tie(LoVT, HiVT) = DAG.GetSplitDestVTs(VT);

  SDValue Expanded = TLI.expandVectorSplice(N, DAG);
  Lo = DAG.getNode(ISD::EXTRACT_SUBVECTOR, DL, LoVT, Expanded,
                   DAG.getVectorIdxConstant(0, DL));
  Hi =
      DAG.getNode(ISD::EXTRACT_SUBVECTOR, DL, HiVT, Expanded,
                  DAG.getVectorIdxConstant(LoVT.getVectorMinNumElements(), DL));
}
