//===------- 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::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) {
  EVT NewVT = N->getValueType(0).getVectorElementType();
  SDValue Op = GetScalarizedVector(N->getOperand(0));
  return DAG.getNode(ISD::FP_ROUND, SDLoc(N),
                     NewVT, 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)->isNullValue();
  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::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::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::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);
    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;
  }

  // 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) {
  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();
  Lo = DAG.getNode(Opcode, dl, LHSLo.getValueType(), LHSLo, RHSLo, Flags);
  Hi = DAG.getNode(Opcode, dl, LHSHi.getValueType(), LHSHi, RHSHi, 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.getVectorNumElements(), 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();
  unsigned VecElems = VecVT.getVectorNumElements();
  unsigned SubElems = SubVec.getValueType().getVectorNumElements();

  // If we know the index is 0, 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.
  // TODO: The IdxVal == 0 constraint is artificial, we could do this whenever
  // there is no boundary crossing. But those cases don't seem to get hit in
  // practice.
  unsigned IdxVal = cast<ConstantSDNode>(Idx)->getZExtValue();
  if ((IdxVal == 0) && (IdxVal + SubElems <= VecElems / 2)) {
    EVT LoVT, HiVT;
    std::tie(LoVT, HiVT) = DAG.GetSplitDestVTs(N->getValueType(0));
    Lo = DAG.getNode(ISD::INSERT_SUBVECTOR, dl, LoVT, Lo, SubVec, Idx);
    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.getVectorElementPointer(DAG, StackPtr, VecVT, 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.
  unsigned IncrementSize = Lo.getValueSizeInBits() / 8;
  StackPtr =
      DAG.getMemBasePlusOffset(StackPtr, TypeSize::Fixed(IncrementSize), dl);

  // Load the Hi part from the stack slot.
  Hi = DAG.getLoad(Hi.getValueType(), dl, Store, StackPtr,
                   PtrInfo.getWithOffset(IncrementSize), 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_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);

  unsigned LoSize = MemoryLocation::getSizeOrUnknown(LoMemVT.getStoreSize());
  MachineMemOperand *MMO = DAG.getMachineFunction().getMachineMemOperand(
      MLD->getPointerInfo(), MachineMemOperand::MOLoad, LoSize, 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());
    unsigned HiSize = MemoryLocation::getSizeOrUnknown(HiMemVT.getStoreSize());

    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, HiSize, 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;
  unsigned LoSize = MemoryLocation::getSizeOrUnknown(LoMemVT.getStoreSize());
  MachineMemOperand *MMO = DAG.getMachineFunction().getMachineMemOperand(
      N->getPointerInfo(), MachineMemOperand::MOStore, LoSize, 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());

    unsigned HiSize = MemoryLocation::getSizeOrUnknown(HiMemVT.getStoreSize());
    MMO = DAG.getMachineFunction().getMachineMemOperand(
        MPI, MachineMemOperand::MOStore, HiSize, 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::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);
    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::FCANONICALIZE:
    Res = WidenVecRes_Unary(N);
    break;
  case ISD::FMA:
  case ISD::FSHL:
  case ISD::FSHR:
    Res = WidenVecRes_Ternary(N);
    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) {
  // 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));
  return DAG.getNode(N->getOpcode(), dl, WidenVT, InOp1, InOp2, 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));
  unsigned WidenNumElts = WidenVT.getVectorNumElements();

  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, WidenNumElts);
  unsigned InVTNumElts = InVT.getVectorNumElements();

  if (getTypeAction(InVT) == TargetLowering::TypeWidenVector) {
    InOp = GetWidenedVector(N->getOperand(0));
    InVT = InOp.getValueType();
    InVTNumElts = InVT.getVectorNumElements();
    if (InVTNumElts == WidenNumElts) {
      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 (WidenNumElts % InVTNumElts == 0) {
      // Widen the input and call convert on the widened input vector.
      unsigned NumConcat = WidenNumElts/InVTNumElts;
      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 (InVTNumElts % WidenNumElts == 0) {
      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(WidenNumElts, 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_EXTRACT_SUBVECTOR(SDNode *N) {
  EVT      VT = N->getValueType(0);
  EVT      WidenVT = TLI.getTypeToTransformTo(*DAG.getContext(), VT);
  unsigned WidenNumElts = WidenVT.getVectorNumElements();
  SDValue  InOp = N->getOperand(0);
  SDValue  Idx  = N->getOperand(1);
  SDLoc dl(N);

  if (getTypeAction(InOp.getValueType()) == 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 InNumElts = InVT.getVectorNumElements();
  if (IdxVal % WidenNumElts == 0 && IdxVal + WidenNumElts < InNumElts)
    return DAG.getNode(ISD::EXTRACT_SUBVECTOR, dl, WidenVT, InOp, Idx);

  // 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);
  EVT EltVT = VT.getVectorElementType();
  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 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;
}

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);
  // 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));
  unsigned WidenNumElts = WidenVT.getVectorNumElements();

  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, WidenNumElts);
    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::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 (int i = MVT::FIRST_VECTOR_VALUETYPE, e = MVT::LAST_VECTOR_VALUETYPE; i < e; ++i) {
      EVT FixedVT = (MVT::SimpleValueType)i;
      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_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;
  GenWidenVectorStores(StChain, ST);

  if (StChain.size() == 1)
    return StChain[0];
  else
    return DAG.getNode(ISD::TokenFactor, SDLoc(ST), MVT::Other, StChain);
}

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

  // See if there is larger legal integer than the element type to load/store.
  unsigned VT;
  // Don't bother looking for an integer type if the vector is scalable, skip
  // to vector types.
  if (!Scalable) {
    for (VT = (unsigned)MVT::LAST_INTEGER_VALUETYPE;
         VT >= (unsigned)MVT::FIRST_INTEGER_VALUETYPE; --VT) {
      EVT MemVT((MVT::SimpleValueType) VT);
      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 (VT = (unsigned)MVT::LAST_VECTOR_VALUETYPE;
       VT >= (unsigned)MVT::FIRST_VECTOR_VALUETYPE; --VT) {
    EVT MemVT = (MVT::SimpleValueType) VT;
    // 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;
    }
  }

  if (Scalable)
    report_fatal_error("Using element-wise loads and stores for widening "
                       "operations is not supported for scalable vectors");
  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()) ? 0 : LD->getAlignment();

  // Find the vector type that can load from.
  EVT NewVT = FindMemType(DAG, TLI, LdWidth.getKnownMinSize(), WidenVT, LdAlign,
                          WidthDiff.getKnownMinSize());
  TypeSize NewVTWidth = NewVT.getSizeInBits();
  SDValue LdOp = DAG.getLoad(NewVT, 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 (TypeSize::isKnownLE(LdWidth, NewVTWidth)) {
    if (!NewVT.isVector()) {
      unsigned NumElts = WidenWidth.getFixedSize() / NewVTWidth.getFixedSize();
      EVT NewVecVT = EVT::getVectorVT(*DAG.getContext(), NewVT, NumElts);
      SDValue VecOp = DAG.getNode(ISD::SCALAR_TO_VECTOR, dl, NewVecVT, LdOp);
      return DAG.getNode(ISD::BITCAST, dl, WidenVT, VecOp);
    }
    if (NewVT == WidenVT)
      return LdOp;

    // TODO: We don't currently have any tests that exercise this code path.
    assert(WidenWidth.getFixedSize() % NewVTWidth.getFixedSize() == 0);
    unsigned NumConcat = WidenWidth.getFixedSize() / NewVTWidth.getFixedSize();
    SmallVector<SDValue, 16> ConcatOps(NumConcat);
    SDValue UndefVal = DAG.getUNDEF(NewVT);
    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();
  do {
    LdWidth -= NewVTWidth;
    IncrementPointer(cast<LoadSDNode>(LdOp), NewVT, MPI, BasePtr,
                     &ScaledOffset);

    if (TypeSize::isKnownLT(LdWidth, NewVTWidth)) {
      // The current type we are using is too large. Find a better size.
      NewVT = FindMemType(DAG, TLI, LdWidth.getKnownMinSize(), WidenVT, LdAlign,
                          WidthDiff.getKnownMinSize());
      NewVTWidth = NewVT.getSizeInBits();
    }

    Align NewAlign = ScaledOffset == 0
                         ? LD->getOriginalAlign()
                         : commonAlignment(LD->getAlign(), ScaledOffset);
    SDValue L =
        DAG.getLoad(NewVT, dl, Chain, BasePtr, MPI, NewAlign, MMOFlags, AAInfo);
    LdChain.push_back(L.getValue(1));

    LdOps.push_back(L);
    LdOp = L;
  } while (TypeSize::isKnownGT(LdWidth, NewVTWidth));

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

void 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;
  while (StWidth.isNonZero()) {
    // Find the largest vector type we can store with.
    EVT NewVT = FindMemType(DAG, TLI, StWidth.getKnownMinSize(), ValVT);
    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);

        StWidth -= NewVTWidth;
        Idx += NumVTElts;

        IncrementPointer(cast<StoreSDNode>(PartStore), NewVT, MPI, BasePtr,
                         &ScaledOffset);
      } while (StWidth.isNonZero() && TypeSize::isKnownGE(StWidth, NewVTWidth));
    } 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);

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

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