//===-- llvm/CodeGen/GlobalISel/LegalizerHelper.cpp -----------------------===//
//
// 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
//
//===----------------------------------------------------------------------===//
//
/// \file This file implements the LegalizerHelper class to legalize
/// individual instructions and the LegalizeMachineIR wrapper pass for the
/// primary legalization.
//
//===----------------------------------------------------------------------===//

#include "llvm/CodeGen/GlobalISel/LegalizerHelper.h"
#include "llvm/CodeGen/GlobalISel/CallLowering.h"
#include "llvm/CodeGen/GlobalISel/GISelChangeObserver.h"
#include "llvm/CodeGen/GlobalISel/GISelValueTracking.h"
#include "llvm/CodeGen/GlobalISel/GenericMachineInstrs.h"
#include "llvm/CodeGen/GlobalISel/LegalizerInfo.h"
#include "llvm/CodeGen/GlobalISel/LostDebugLocObserver.h"
#include "llvm/CodeGen/GlobalISel/MIPatternMatch.h"
#include "llvm/CodeGen/GlobalISel/MachineIRBuilder.h"
#include "llvm/CodeGen/GlobalISel/Utils.h"
#include "llvm/CodeGen/LowLevelTypeUtils.h"
#include "llvm/CodeGen/MachineConstantPool.h"
#include "llvm/CodeGen/MachineFrameInfo.h"
#include "llvm/CodeGen/MachineRegisterInfo.h"
#include "llvm/CodeGen/RuntimeLibcallUtil.h"
#include "llvm/CodeGen/TargetFrameLowering.h"
#include "llvm/CodeGen/TargetInstrInfo.h"
#include "llvm/CodeGen/TargetLowering.h"
#include "llvm/CodeGen/TargetOpcodes.h"
#include "llvm/CodeGen/TargetSubtargetInfo.h"
#include "llvm/IR/Instructions.h"
#include "llvm/Support/Debug.h"
#include "llvm/Support/MathExtras.h"
#include "llvm/Support/raw_ostream.h"
#include "llvm/Target/TargetMachine.h"
#include <cassert>
#include <numeric>
#include <optional>

#define DEBUG_TYPE "legalizer"

using namespace llvm;
using namespace LegalizeActions;
using namespace MIPatternMatch;

/// Try to break down \p OrigTy into \p NarrowTy sized pieces.
///
/// Returns the number of \p NarrowTy elements needed to reconstruct \p OrigTy,
/// with any leftover piece as type \p LeftoverTy
///
/// Returns -1 in the first element of the pair if the breakdown is not
/// satisfiable.
static std::pair<int, int>
getNarrowTypeBreakDown(LLT OrigTy, LLT NarrowTy, LLT &LeftoverTy) {
  assert(!LeftoverTy.isValid() && "this is an out argument");

  unsigned Size = OrigTy.getSizeInBits();
  unsigned NarrowSize = NarrowTy.getSizeInBits();
  unsigned NumParts = Size / NarrowSize;
  unsigned LeftoverSize = Size - NumParts * NarrowSize;
  assert(Size > NarrowSize);

  if (LeftoverSize == 0)
    return {NumParts, 0};

  if (NarrowTy.isVector()) {
    unsigned EltSize = OrigTy.getScalarSizeInBits();
    if (LeftoverSize % EltSize != 0)
      return {-1, -1};
    LeftoverTy = OrigTy.changeElementCount(
        ElementCount::getFixed(LeftoverSize / EltSize));
  } else {
    LeftoverTy = LLT::integer(LeftoverSize);
  }

  int NumLeftover = LeftoverSize / LeftoverTy.getSizeInBits();
  return std::make_pair(NumParts, NumLeftover);
}

static Type *getFloatTypeForLLT(LLVMContext &Ctx, LLT Ty) {

  if (!Ty.isScalar())
    return nullptr;

  switch (Ty.getSizeInBits()) {
  case 16:
    return Type::getHalfTy(Ctx);
  case 32:
    return Type::getFloatTy(Ctx);
  case 64:
    return Type::getDoubleTy(Ctx);
  case 80:
    return Type::getX86_FP80Ty(Ctx);
  case 128:
    return Type::getFP128Ty(Ctx);
  default:
    return nullptr;
  }
}

LegalizerHelper::LegalizerHelper(MachineFunction &MF,
                                 GISelChangeObserver &Observer,
                                 MachineIRBuilder &Builder,
                                 const LibcallLoweringInfo *Libcalls)
    : MIRBuilder(Builder), Observer(Observer), MRI(MF.getRegInfo()),
      LI(*MF.getSubtarget().getLegalizerInfo()),
      TLI(*MF.getSubtarget().getTargetLowering()), Libcalls(Libcalls) {}

LegalizerHelper::LegalizerHelper(MachineFunction &MF, const LegalizerInfo &LI,
                                 GISelChangeObserver &Observer,
                                 MachineIRBuilder &B,
                                 const LibcallLoweringInfo *Libcalls,
                                 GISelValueTracking *VT)
    : MIRBuilder(B), Observer(Observer), MRI(MF.getRegInfo()), LI(LI),
      TLI(*MF.getSubtarget().getTargetLowering()), Libcalls(Libcalls), VT(VT) {}

LegalizerHelper::LegalizeResult
LegalizerHelper::legalizeInstrStep(MachineInstr &MI,
                                   LostDebugLocObserver &LocObserver) {
  LLVM_DEBUG(dbgs() << "\nLegalizing: " << MI);

  MIRBuilder.setInstrAndDebugLoc(MI);

  if (isa<GIntrinsic>(MI))
    return LI.legalizeIntrinsic(*this, MI) ? Legalized : UnableToLegalize;
  auto Step = LI.getAction(MI, MRI);
  switch (Step.Action) {
  case Legal:
    LLVM_DEBUG(dbgs() << ".. Already legal\n");
    return AlreadyLegal;
  case Libcall:
    LLVM_DEBUG(dbgs() << ".. Convert to libcall\n");
    return libcall(MI, LocObserver);
  case NarrowScalar:
    LLVM_DEBUG(dbgs() << ".. Narrow scalar\n");
    return narrowScalar(MI, Step.TypeIdx, Step.NewType);
  case WidenScalar:
    LLVM_DEBUG(dbgs() << ".. Widen scalar\n");
    return widenScalar(MI, Step.TypeIdx, Step.NewType);
  case Bitcast:
    LLVM_DEBUG(dbgs() << ".. Bitcast type\n");
    return bitcast(MI, Step.TypeIdx, Step.NewType);
  case Lower:
    LLVM_DEBUG(dbgs() << ".. Lower\n");
    return lower(MI, Step.TypeIdx, Step.NewType);
  case FewerElements:
    LLVM_DEBUG(dbgs() << ".. Reduce number of elements\n");
    return fewerElementsVector(MI, Step.TypeIdx, Step.NewType);
  case MoreElements:
    LLVM_DEBUG(dbgs() << ".. Increase number of elements\n");
    return moreElementsVector(MI, Step.TypeIdx, Step.NewType);
  case Custom:
    LLVM_DEBUG(dbgs() << ".. Custom legalization\n");
    return LI.legalizeCustom(*this, MI, LocObserver) ? Legalized
                                                     : UnableToLegalize;
  default:
    LLVM_DEBUG(dbgs() << ".. Unable to legalize\n");
    return UnableToLegalize;
  }
}

void LegalizerHelper::insertParts(Register DstReg,
                                  LLT ResultTy, LLT PartTy,
                                  ArrayRef<Register> PartRegs,
                                  LLT LeftoverTy,
                                  ArrayRef<Register> LeftoverRegs) {
  if (!LeftoverTy.isValid()) {
    assert(LeftoverRegs.empty());

    if (!ResultTy.isVector()) {
      MIRBuilder.buildMergeLikeInstr(DstReg, PartRegs);
      return;
    }

    if (PartTy.isVector())
      MIRBuilder.buildConcatVectors(DstReg, PartRegs);
    else
      MIRBuilder.buildBuildVector(DstReg, PartRegs);
    return;
  }

  // Merge sub-vectors with different number of elements and insert into DstReg.
  if (ResultTy.isVector()) {
    assert(LeftoverRegs.size() == 1 && "Expected one leftover register");
    SmallVector<Register, 8> AllRegs(PartRegs);
    AllRegs.append(LeftoverRegs.begin(), LeftoverRegs.end());
    return mergeMixedSubvectors(DstReg, AllRegs);
  }

  SmallVector<Register> GCDRegs;
  LLT GCDTy = getGCDType(getGCDType(ResultTy, LeftoverTy), PartTy);
  for (auto PartReg : concat<const Register>(PartRegs, LeftoverRegs))
    extractGCDType(GCDRegs, GCDTy, PartReg);
  LLT ResultLCMTy = buildLCMMergePieces(ResultTy, LeftoverTy, GCDTy, GCDRegs);
  buildWidenedRemergeToDst(DstReg, ResultLCMTy, GCDRegs);
}

void LegalizerHelper::appendVectorElts(SmallVectorImpl<Register> &Elts,
                                       Register Reg) {
  LLT Ty = MRI.getType(Reg);
  SmallVector<Register, 8> RegElts;
  extractParts(Reg, Ty.getScalarType(), Ty.getNumElements(), RegElts,
               MIRBuilder, MRI);
  Elts.append(RegElts);
}

/// Merge \p PartRegs with different types into \p DstReg.
void LegalizerHelper::mergeMixedSubvectors(Register DstReg,
                                           ArrayRef<Register> PartRegs) {
  SmallVector<Register, 8> AllElts;
  for (unsigned i = 0; i < PartRegs.size() - 1; ++i)
    appendVectorElts(AllElts, PartRegs[i]);

  Register Leftover = PartRegs[PartRegs.size() - 1];
  if (!MRI.getType(Leftover).isVector())
    AllElts.push_back(Leftover);
  else
    appendVectorElts(AllElts, Leftover);

  MIRBuilder.buildMergeLikeInstr(DstReg, AllElts);
}

/// Append the result registers of G_UNMERGE_VALUES \p MI to \p Regs.
static void getUnmergeResults(SmallVectorImpl<Register> &Regs,
                              const MachineInstr &MI) {
  assert(MI.getOpcode() == TargetOpcode::G_UNMERGE_VALUES);

  const int StartIdx = Regs.size();
  const int NumResults = MI.getNumOperands() - 1;
  Regs.resize(Regs.size() + NumResults);
  for (int I = 0; I != NumResults; ++I)
    Regs[StartIdx + I] = MI.getOperand(I).getReg();
}

void LegalizerHelper::extractGCDType(SmallVectorImpl<Register> &Parts,
                                     LLT GCDTy, Register SrcReg) {
  LLT SrcTy = MRI.getType(SrcReg);
  if (SrcTy == GCDTy) {
    // If the source already evenly divides the result type, we don't need to do
    // anything.
    Parts.push_back(SrcReg);
  } else {
    // Need to split into common type sized pieces.
    auto Unmerge = MIRBuilder.buildUnmerge(GCDTy, SrcReg);
    getUnmergeResults(Parts, *Unmerge);
  }
}

LLT LegalizerHelper::extractGCDType(SmallVectorImpl<Register> &Parts, LLT DstTy,
                                    LLT NarrowTy, Register SrcReg) {
  LLT SrcTy = MRI.getType(SrcReg);
  LLT GCDTy = getGCDType(getGCDType(SrcTy, NarrowTy), DstTy);
  extractGCDType(Parts, GCDTy, SrcReg);
  return GCDTy;
}

LLT LegalizerHelper::buildLCMMergePieces(LLT DstTy, LLT NarrowTy, LLT GCDTy,
                                         SmallVectorImpl<Register> &VRegs,
                                         unsigned PadStrategy) {
  LLT LCMTy = getLCMType(DstTy, NarrowTy);

  int NumParts = LCMTy.getSizeInBits() / NarrowTy.getSizeInBits();
  int NumSubParts = NarrowTy.getSizeInBits() / GCDTy.getSizeInBits();
  int NumOrigSrc = VRegs.size();

  Register PadReg;

  // Get a value we can use to pad the source value if the sources won't evenly
  // cover the result type.
  if (NumOrigSrc < NumParts * NumSubParts) {
    if (PadStrategy == TargetOpcode::G_ZEXT)
      PadReg = MIRBuilder.buildConstant(GCDTy, 0).getReg(0);
    else if (PadStrategy == TargetOpcode::G_ANYEXT)
      PadReg = MIRBuilder.buildUndef(GCDTy).getReg(0);
    else {
      assert(PadStrategy == TargetOpcode::G_SEXT);

      // Shift the sign bit of the low register through the high register.
      auto ShiftAmt =
          MIRBuilder.buildConstant(LLT::integer(64), GCDTy.getSizeInBits() - 1);
      PadReg = MIRBuilder.buildAShr(GCDTy, VRegs.back(), ShiftAmt).getReg(0);
    }
  }

  // Registers for the final merge to be produced.
  SmallVector<Register, 4> Remerge(NumParts);

  // Registers needed for intermediate merges, which will be merged into a
  // source for Remerge.
  SmallVector<Register, 4> SubMerge(NumSubParts);

  // Once we've fully read off the end of the original source bits, we can reuse
  // the same high bits for remaining padding elements.
  Register AllPadReg;

  // Build merges to the LCM type to cover the original result type.
  for (int I = 0; I != NumParts; ++I) {
    bool AllMergePartsArePadding = true;

    // Build the requested merges to the requested type.
    for (int J = 0; J != NumSubParts; ++J) {
      int Idx = I * NumSubParts + J;
      if (Idx >= NumOrigSrc) {
        SubMerge[J] = PadReg;
        continue;
      }

      SubMerge[J] = VRegs[Idx];

      // There are meaningful bits here we can't reuse later.
      AllMergePartsArePadding = false;
    }

    // If we've filled up a complete piece with padding bits, we can directly
    // emit the natural sized constant if applicable, rather than a merge of
    // smaller constants.
    if (AllMergePartsArePadding && !AllPadReg) {
      if (PadStrategy == TargetOpcode::G_ANYEXT)
        AllPadReg = MIRBuilder.buildUndef(NarrowTy).getReg(0);
      else if (PadStrategy == TargetOpcode::G_ZEXT)
        AllPadReg = MIRBuilder.buildConstant(NarrowTy, 0).getReg(0);

      // If this is a sign extension, we can't materialize a trivial constant
      // with the right type and have to produce a merge.
    }

    if (AllPadReg) {
      // Avoid creating additional instructions if we're just adding additional
      // copies of padding bits.
      Remerge[I] = AllPadReg;
      continue;
    }

    if (NumSubParts == 1)
      Remerge[I] = SubMerge[0];
    else
      Remerge[I] = MIRBuilder.buildMergeLikeInstr(NarrowTy, SubMerge).getReg(0);

    // In the sign extend padding case, re-use the first all-signbit merge.
    if (AllMergePartsArePadding && !AllPadReg)
      AllPadReg = Remerge[I];
  }

  VRegs = std::move(Remerge);
  return LCMTy;
}

void LegalizerHelper::buildWidenedRemergeToDst(Register DstReg, LLT LCMTy,
                                               ArrayRef<Register> RemergeRegs) {
  LLT DstTy = MRI.getType(DstReg);

  // Create the merge to the widened source, and extract the relevant bits into
  // the result.

  if (DstTy == LCMTy) {
    MIRBuilder.buildMergeLikeInstr(DstReg, RemergeRegs);
    return;
  }

  auto Remerge = MIRBuilder.buildMergeLikeInstr(LCMTy, RemergeRegs);
  if (DstTy.isScalar() && LCMTy.isScalar()) {
    MIRBuilder.buildTrunc(DstReg, Remerge);
    return;
  }

  if (LCMTy.isVector()) {
    unsigned NumDefs = LCMTy.getSizeInBits() / DstTy.getSizeInBits();
    SmallVector<Register, 8> UnmergeDefs(NumDefs);
    UnmergeDefs[0] = DstReg;
    for (unsigned I = 1; I != NumDefs; ++I)
      UnmergeDefs[I] = MRI.createGenericVirtualRegister(DstTy);

    MIRBuilder.buildUnmerge(UnmergeDefs,
                            MIRBuilder.buildMergeLikeInstr(LCMTy, RemergeRegs));
    return;
  }

  llvm_unreachable("unhandled case");
}

static RTLIB::Libcall getRTLibDesc(unsigned Opcode, unsigned Size) {
#define RTLIBCASE_INT(LibcallPrefix)                                           \
  do {                                                                         \
    switch (Size) {                                                            \
    case 32:                                                                   \
      return RTLIB::LibcallPrefix##32;                                         \
    case 64:                                                                   \
      return RTLIB::LibcallPrefix##64;                                         \
    case 128:                                                                  \
      return RTLIB::LibcallPrefix##128;                                        \
    default:                                                                   \
      llvm_unreachable("unexpected size");                                     \
    }                                                                          \
  } while (0)

#define RTLIBCASE(LibcallPrefix)                                               \
  do {                                                                         \
    switch (Size) {                                                            \
    case 32:                                                                   \
      return RTLIB::LibcallPrefix##32;                                         \
    case 64:                                                                   \
      return RTLIB::LibcallPrefix##64;                                         \
    case 80:                                                                   \
      return RTLIB::LibcallPrefix##80;                                         \
    case 128:                                                                  \
      return RTLIB::LibcallPrefix##128;                                        \
    default:                                                                   \
      llvm_unreachable("unexpected size");                                     \
    }                                                                          \
  } while (0)

  switch (Opcode) {
  case TargetOpcode::G_LROUND:
    RTLIBCASE(LROUND_F);
  case TargetOpcode::G_LLROUND:
    RTLIBCASE(LLROUND_F);
  case TargetOpcode::G_MUL:
    RTLIBCASE_INT(MUL_I);
  case TargetOpcode::G_SDIV:
    RTLIBCASE_INT(SDIV_I);
  case TargetOpcode::G_UDIV:
    RTLIBCASE_INT(UDIV_I);
  case TargetOpcode::G_SREM:
    RTLIBCASE_INT(SREM_I);
  case TargetOpcode::G_UREM:
    RTLIBCASE_INT(UREM_I);
  case TargetOpcode::G_CTLZ_ZERO_POISON:
    RTLIBCASE_INT(CTLZ_I);
  case TargetOpcode::G_FADD:
    RTLIBCASE(ADD_F);
  case TargetOpcode::G_FSUB:
    RTLIBCASE(SUB_F);
  case TargetOpcode::G_FMUL:
    RTLIBCASE(MUL_F);
  case TargetOpcode::G_FDIV:
    RTLIBCASE(DIV_F);
  case TargetOpcode::G_FEXP:
    RTLIBCASE(EXP_F);
  case TargetOpcode::G_FEXP2:
    RTLIBCASE(EXP2_F);
  case TargetOpcode::G_FEXP10:
    RTLIBCASE(EXP10_F);
  case TargetOpcode::G_FREM:
    RTLIBCASE(REM_F);
  case TargetOpcode::G_FPOW:
    RTLIBCASE(POW_F);
  case TargetOpcode::G_FPOWI:
    RTLIBCASE(POWI_F);
  case TargetOpcode::G_FMA:
    RTLIBCASE(FMA_F);
  case TargetOpcode::G_FSIN:
    RTLIBCASE(SIN_F);
  case TargetOpcode::G_FCOS:
    RTLIBCASE(COS_F);
  case TargetOpcode::G_FTAN:
    RTLIBCASE(TAN_F);
  case TargetOpcode::G_FASIN:
    RTLIBCASE(ASIN_F);
  case TargetOpcode::G_FACOS:
    RTLIBCASE(ACOS_F);
  case TargetOpcode::G_FATAN:
    RTLIBCASE(ATAN_F);
  case TargetOpcode::G_FATAN2:
    RTLIBCASE(ATAN2_F);
  case TargetOpcode::G_FSINH:
    RTLIBCASE(SINH_F);
  case TargetOpcode::G_FCOSH:
    RTLIBCASE(COSH_F);
  case TargetOpcode::G_FTANH:
    RTLIBCASE(TANH_F);
  case TargetOpcode::G_FSINCOS:
    RTLIBCASE(SINCOS_F);
  case TargetOpcode::G_FMODF:
    RTLIBCASE(MODF_F);
  case TargetOpcode::G_FLOG10:
    RTLIBCASE(LOG10_F);
  case TargetOpcode::G_FLOG:
    RTLIBCASE(LOG_F);
  case TargetOpcode::G_FLOG2:
    RTLIBCASE(LOG2_F);
  case TargetOpcode::G_FLDEXP:
    RTLIBCASE(LDEXP_F);
  case TargetOpcode::G_FCEIL:
    RTLIBCASE(CEIL_F);
  case TargetOpcode::G_FFLOOR:
    RTLIBCASE(FLOOR_F);
  case TargetOpcode::G_FMINNUM:
    RTLIBCASE(FMIN_F);
  case TargetOpcode::G_FMAXNUM:
    RTLIBCASE(FMAX_F);
  case TargetOpcode::G_FMINIMUMNUM:
    RTLIBCASE(FMINIMUM_NUM_F);
  case TargetOpcode::G_FMAXIMUMNUM:
    RTLIBCASE(FMAXIMUM_NUM_F);
  case TargetOpcode::G_FSQRT:
    RTLIBCASE(SQRT_F);
  case TargetOpcode::G_FRINT:
    RTLIBCASE(RINT_F);
  case TargetOpcode::G_FNEARBYINT:
    RTLIBCASE(NEARBYINT_F);
  case TargetOpcode::G_INTRINSIC_TRUNC:
    RTLIBCASE(TRUNC_F);
  case TargetOpcode::G_INTRINSIC_ROUND:
    RTLIBCASE(ROUND_F);
  case TargetOpcode::G_INTRINSIC_ROUNDEVEN:
    RTLIBCASE(ROUNDEVEN_F);
  case TargetOpcode::G_INTRINSIC_LRINT:
    RTLIBCASE(LRINT_F);
  case TargetOpcode::G_INTRINSIC_LLRINT:
    RTLIBCASE(LLRINT_F);
  }
  llvm_unreachable("Unknown libcall function");
#undef RTLIBCASE_INT
#undef RTLIBCASE
}

/// True if an instruction is in tail position in its caller. Intended for
/// legalizing libcalls as tail calls when possible.
static bool isLibCallInTailPosition(const CallLowering::ArgInfo &Result,
                                    MachineInstr &MI,
                                    const TargetInstrInfo &TII,
                                    MachineRegisterInfo &MRI) {
  MachineBasicBlock &MBB = *MI.getParent();
  const Function &F = MBB.getParent()->getFunction();

  // Conservatively require the attributes of the call to match those of
  // the return. Ignore NoAlias and NonNull because they don't affect the
  // call sequence.
  AttributeList CallerAttrs = F.getAttributes();
  if (AttrBuilder(F.getContext(), CallerAttrs.getRetAttrs())
          .removeAttribute(Attribute::NoAlias)
          .removeAttribute(Attribute::NonNull)
          .hasAttributes())
    return false;

  // It's not safe to eliminate the sign / zero extension of the return value.
  if (CallerAttrs.hasRetAttr(Attribute::ZExt) ||
      CallerAttrs.hasRetAttr(Attribute::SExt))
    return false;

  // Only tail call if the following instruction is a standard return or if we
  // have a `thisreturn` callee, and a sequence like:
  //
  //   G_MEMCPY %0, %1, %2
  //   $x0 = COPY %0
  //   RET_ReallyLR implicit $x0
  auto Next = next_nodbg(MI.getIterator(), MBB.instr_end());
  if (Next != MBB.instr_end() && Next->isCopy()) {
    if (MI.getOpcode() == TargetOpcode::G_BZERO)
      return false;

    // For MEMCPY/MOMMOVE/MEMSET these will be the first use (the dst), as the
    // mempy/etc routines return the same parameter. For other it will be the
    // returned value.
    Register VReg = MI.getOperand(0).getReg();
    if (!VReg.isVirtual() || VReg != Next->getOperand(1).getReg())
      return false;

    Register PReg = Next->getOperand(0).getReg();
    if (!PReg.isPhysical())
      return false;

    auto Ret = next_nodbg(Next, MBB.instr_end());
    if (Ret == MBB.instr_end() || !Ret->isReturn())
      return false;

    if (Ret->getNumImplicitOperands() != 1)
      return false;

    if (!Ret->getOperand(0).isReg() || PReg != Ret->getOperand(0).getReg())
      return false;

    // Skip over the COPY that we just validated.
    Next = Ret;
  }

  if (Next == MBB.instr_end() || TII.isTailCall(*Next) || !Next->isReturn())
    return false;

  return true;
}

LegalizerHelper::LegalizeResult LegalizerHelper::createLibcall(
    const char *Name, const CallLowering::ArgInfo &Result,
    ArrayRef<CallLowering::ArgInfo> Args, const CallingConv::ID CC,
    LostDebugLocObserver &LocObserver, MachineInstr *MI) const {
  auto &CLI = *MIRBuilder.getMF().getSubtarget().getCallLowering();

  CallLowering::CallLoweringInfo Info;
  Info.CallConv = CC;
  Info.Callee = MachineOperand::CreateES(Name);
  Info.OrigRet = Result;
  if (MI)
    Info.IsTailCall =
        (Result.Ty->isVoidTy() ||
         Result.Ty == MIRBuilder.getMF().getFunction().getReturnType()) &&
        isLibCallInTailPosition(Result, *MI, MIRBuilder.getTII(),
                                *MIRBuilder.getMRI());

  llvm::append_range(Info.OrigArgs, Args);
  if (!CLI.lowerCall(MIRBuilder, Info))
    return LegalizerHelper::UnableToLegalize;

  if (MI && Info.LoweredTailCall) {
    assert(Info.IsTailCall && "Lowered tail call when it wasn't a tail call?");

    // Check debug locations before removing the return.
    LocObserver.checkpoint(true);

    // We must have a return following the call (or debug insts) to get past
    // isLibCallInTailPosition.
    do {
      MachineInstr *Next = MI->getNextNode();
      assert(Next &&
             (Next->isCopy() || Next->isReturn() || Next->isDebugInstr()) &&
             "Expected instr following MI to be return or debug inst?");
      // We lowered a tail call, so the call is now the return from the block.
      // Delete the old return.
      Next->eraseFromParent();
    } while (MI->getNextNode());

    // We expect to lose the debug location from the return.
    LocObserver.checkpoint(false);
  }
  return LegalizerHelper::Legalized;
}

LegalizerHelper::LegalizeResult LegalizerHelper::createLibcall(
    RTLIB::Libcall Libcall, const CallLowering::ArgInfo &Result,
    ArrayRef<CallLowering::ArgInfo> Args, LostDebugLocObserver &LocObserver,
    MachineInstr *MI) const {
  if (!Libcalls)
    return LegalizerHelper::UnableToLegalize;

  RTLIB::LibcallImpl LibcallImpl = Libcalls->getLibcallImpl(Libcall);
  if (LibcallImpl == RTLIB::Unsupported)
    return LegalizerHelper::UnableToLegalize;

  StringRef Name = RTLIB::RuntimeLibcallsInfo::getLibcallImplName(LibcallImpl);
  const CallingConv::ID CC = Libcalls->getLibcallImplCallingConv(LibcallImpl);
  return createLibcall(Name.data(), Result, Args, CC, LocObserver, MI);
}

// Useful for libcalls where all operands have the same type.
LegalizerHelper::LegalizeResult
LegalizerHelper::simpleLibcall(MachineInstr &MI, MachineIRBuilder &MIRBuilder,
                               unsigned Size, Type *OpType,
                               LostDebugLocObserver &LocObserver) const {
  auto Libcall = getRTLibDesc(MI.getOpcode(), Size);

  // FIXME: What does the original arg index mean here?
  SmallVector<CallLowering::ArgInfo, 3> Args;
  for (const MachineOperand &MO : llvm::drop_begin(MI.operands()))
    Args.push_back({MO.getReg(), OpType, 0});
  return createLibcall(Libcall, {MI.getOperand(0).getReg(), OpType, 0}, Args,
                       LocObserver, &MI);
}

LegalizerHelper::LegalizeResult LegalizerHelper::emitSincosLibcall(
    MachineInstr &MI, MachineIRBuilder &MIRBuilder, unsigned Size, Type *OpType,
    LostDebugLocObserver &LocObserver) {
  MachineFunction &MF = *MI.getMF();
  MachineRegisterInfo &MRI = MF.getRegInfo();

  Register DstSin = MI.getOperand(0).getReg();
  Register DstCos = MI.getOperand(1).getReg();
  Register Src = MI.getOperand(2).getReg();
  LLT DstTy = MRI.getType(DstSin);

  int MemSize = DstTy.getSizeInBytes();
  Align Alignment = getStackTemporaryAlignment(DstTy);
  const DataLayout &DL = MIRBuilder.getDataLayout();
  unsigned AddrSpace = DL.getAllocaAddrSpace();
  MachinePointerInfo PtrInfo;

  Register StackPtrSin =
      createStackTemporary(TypeSize::getFixed(MemSize), Alignment, PtrInfo)
          .getReg(0);
  Register StackPtrCos =
      createStackTemporary(TypeSize::getFixed(MemSize), Alignment, PtrInfo)
          .getReg(0);

  auto &Ctx = MF.getFunction().getContext();
  auto LibcallResult = createLibcall(
      getRTLibDesc(MI.getOpcode(), Size), {{0}, Type::getVoidTy(Ctx), 0},
      {{Src, OpType, 0},
       {StackPtrSin, PointerType::get(Ctx, AddrSpace), 1},
       {StackPtrCos, PointerType::get(Ctx, AddrSpace), 2}},
      LocObserver, &MI);

  if (LibcallResult != LegalizeResult::Legalized)
    return LegalizerHelper::UnableToLegalize;

  MachineMemOperand *LoadMMOSin = MF.getMachineMemOperand(
      PtrInfo, MachineMemOperand::MOLoad, MemSize, Alignment);
  MachineMemOperand *LoadMMOCos = MF.getMachineMemOperand(
      PtrInfo, MachineMemOperand::MOLoad, MemSize, Alignment);

  MIRBuilder.buildLoad(DstSin, StackPtrSin, *LoadMMOSin);
  MIRBuilder.buildLoad(DstCos, StackPtrCos, *LoadMMOCos);
  MI.eraseFromParent();

  return LegalizerHelper::Legalized;
}

LegalizerHelper::LegalizeResult
LegalizerHelper::emitModfLibcall(MachineInstr &MI, MachineIRBuilder &MIRBuilder,
                                 unsigned Size, Type *OpType,
                                 LostDebugLocObserver &LocObserver) {
  MachineFunction &MF = MIRBuilder.getMF();
  MachineRegisterInfo &MRI = MF.getRegInfo();

  Register DstFrac = MI.getOperand(0).getReg();
  Register DstInt = MI.getOperand(1).getReg();
  Register Src = MI.getOperand(2).getReg();
  LLT DstTy = MRI.getType(DstFrac);

  int MemSize = DstTy.getSizeInBytes();
  Align Alignment = getStackTemporaryAlignment(DstTy);
  const DataLayout &DL = MIRBuilder.getDataLayout();
  unsigned AddrSpace = DL.getAllocaAddrSpace();
  MachinePointerInfo PtrInfo;

  Register StackPtrInt =
      createStackTemporary(TypeSize::getFixed(MemSize), Alignment, PtrInfo)
          .getReg(0);

  auto &Ctx = MF.getFunction().getContext();
  auto LibcallResult = createLibcall(
      getRTLibDesc(MI.getOpcode(), Size), {DstFrac, OpType, 0},
      {{Src, OpType, 0}, {StackPtrInt, PointerType::get(Ctx, AddrSpace), 1}},
      LocObserver, &MI);

  if (LibcallResult != LegalizeResult::Legalized)
    return LegalizerHelper::UnableToLegalize;

  MachineMemOperand *LoadMMOInt = MF.getMachineMemOperand(
      PtrInfo, MachineMemOperand::MOLoad, MemSize, Alignment);

  MIRBuilder.buildLoad(DstInt, StackPtrInt, *LoadMMOInt);
  MI.eraseFromParent();

  return LegalizerHelper::Legalized;
}

static RTLIB::Libcall getConvRTLibDesc(unsigned Opcode, Type *ToType,
                                       Type *FromType) {
  auto ToMVT = MVT::getVT(ToType);
  auto FromMVT = MVT::getVT(FromType);

  switch (Opcode) {
  case TargetOpcode::G_FPEXT:
    return RTLIB::getFPEXT(FromMVT, ToMVT);
  case TargetOpcode::G_FPTRUNC:
    return RTLIB::getFPROUND(FromMVT, ToMVT);
  case TargetOpcode::G_FPTOSI:
    return RTLIB::getFPTOSINT(FromMVT, ToMVT);
  case TargetOpcode::G_FPTOUI:
    return RTLIB::getFPTOUINT(FromMVT, ToMVT);
  case TargetOpcode::G_SITOFP:
    return RTLIB::getSINTTOFP(FromMVT, ToMVT);
  case TargetOpcode::G_UITOFP:
    return RTLIB::getUINTTOFP(FromMVT, ToMVT);
  }
  llvm_unreachable("Unsupported libcall function");
}

LegalizerHelper::LegalizeResult LegalizerHelper::conversionLibcall(
    MachineInstr &MI, Type *ToType, Type *FromType,
    LostDebugLocObserver &LocObserver, bool IsSigned) const {
  CallLowering::ArgInfo Arg = {MI.getOperand(1).getReg(), FromType, 0};
  if (FromType->isIntegerTy()) {
    if (TLI.shouldSignExtendTypeInLibCall(FromType, IsSigned))
      Arg.Flags[0].setSExt();
    else
      Arg.Flags[0].setZExt();
  }

  RTLIB::Libcall Libcall = getConvRTLibDesc(MI.getOpcode(), ToType, FromType);
  return createLibcall(Libcall, {MI.getOperand(0).getReg(), ToType, 0}, Arg,
                       LocObserver, &MI);
}

LegalizerHelper::LegalizeResult
LegalizerHelper::createMemLibcall(MachineRegisterInfo &MRI, MachineInstr &MI,
                                  LostDebugLocObserver &LocObserver) const {
  auto &Ctx = MIRBuilder.getMF().getFunction().getContext();

  SmallVector<CallLowering::ArgInfo, 3> Args;
  // Add all the args, except for the last which is an imm denoting 'tail'.
  for (unsigned i = 0; i < MI.getNumOperands() - 1; ++i) {
    Register Reg = MI.getOperand(i).getReg();

    // Need derive an IR type for call lowering.
    LLT OpLLT = MRI.getType(Reg);
    Type *OpTy = nullptr;
    if (OpLLT.isPointer())
      OpTy = PointerType::get(Ctx, OpLLT.getAddressSpace());
    else
      OpTy = IntegerType::get(Ctx, OpLLT.getSizeInBits());
    Args.push_back({Reg, OpTy, 0});
  }

  auto &CLI = *MIRBuilder.getMF().getSubtarget().getCallLowering();
  RTLIB::Libcall RTLibcall;
  unsigned Opc = MI.getOpcode();
  switch (Opc) {
  case TargetOpcode::G_BZERO:
    RTLibcall = RTLIB::BZERO;
    break;
  case TargetOpcode::G_MEMCPY:
    RTLibcall = RTLIB::MEMCPY;
    Args[0].Flags[0].setReturned();
    break;
  case TargetOpcode::G_MEMMOVE:
    RTLibcall = RTLIB::MEMMOVE;
    Args[0].Flags[0].setReturned();
    break;
  case TargetOpcode::G_MEMSET:
    RTLibcall = RTLIB::MEMSET;
    Args[0].Flags[0].setReturned();
    break;
  default:
    llvm_unreachable("unsupported opcode");
  }

  if (!Libcalls) // FIXME: Should be mandatory
    return LegalizerHelper::UnableToLegalize;

  RTLIB::LibcallImpl RTLibcallImpl = Libcalls->getLibcallImpl(RTLibcall);

  // Unsupported libcall on the target.
  if (RTLibcallImpl == RTLIB::Unsupported) {
    LLVM_DEBUG(dbgs() << ".. .. Could not find libcall name for "
                      << MIRBuilder.getTII().getName(Opc) << "\n");
    return LegalizerHelper::UnableToLegalize;
  }

  CallLowering::CallLoweringInfo Info;
  Info.CallConv = Libcalls->getLibcallImplCallingConv(RTLibcallImpl);

  StringRef LibcallName =
      RTLIB::RuntimeLibcallsInfo::getLibcallImplName(RTLibcallImpl);
  Info.Callee = MachineOperand::CreateES(LibcallName.data());
  Info.OrigRet = CallLowering::ArgInfo({0}, Type::getVoidTy(Ctx), 0);
  Info.IsTailCall =
      MI.getOperand(MI.getNumOperands() - 1).getImm() &&
      isLibCallInTailPosition(Info.OrigRet, MI, MIRBuilder.getTII(), MRI);

  llvm::append_range(Info.OrigArgs, Args);
  if (!CLI.lowerCall(MIRBuilder, Info))
    return LegalizerHelper::UnableToLegalize;

  if (Info.LoweredTailCall) {
    assert(Info.IsTailCall && "Lowered tail call when it wasn't a tail call?");

    // Check debug locations before removing the return.
    LocObserver.checkpoint(true);

    // We must have a return following the call (or debug insts) to get past
    // isLibCallInTailPosition.
    do {
      MachineInstr *Next = MI.getNextNode();
      assert(Next &&
             (Next->isCopy() || Next->isReturn() || Next->isDebugInstr()) &&
             "Expected instr following MI to be return or debug inst?");
      // We lowered a tail call, so the call is now the return from the block.
      // Delete the old return.
      Next->eraseFromParent();
    } while (MI.getNextNode());

    // We expect to lose the debug location from the return.
    LocObserver.checkpoint(false);
  }

  return LegalizerHelper::Legalized;
}

static RTLIB::Libcall getOutlineAtomicLibcall(MachineInstr &MI) {
  unsigned Opc = MI.getOpcode();
  auto &AtomicMI = cast<GMemOperation>(MI);
  auto &MMO = AtomicMI.getMMO();
  auto Ordering = MMO.getMergedOrdering();
  LLT MemType = MMO.getMemoryType();
  uint64_t MemSize = MemType.getSizeInBytes();
  if (MemType.isVector())
    return RTLIB::UNKNOWN_LIBCALL;

#define LCALLS(A, B) {A##B##_RELAX, A##B##_ACQ, A##B##_REL, A##B##_ACQ_REL}
#define LCALL5(A)                                                              \
  LCALLS(A, 1), LCALLS(A, 2), LCALLS(A, 4), LCALLS(A, 8), LCALLS(A, 16)
  switch (Opc) {
  case TargetOpcode::G_ATOMIC_CMPXCHG:
  case TargetOpcode::G_ATOMIC_CMPXCHG_WITH_SUCCESS: {
    const RTLIB::Libcall LC[5][4] = {LCALL5(RTLIB::OUTLINE_ATOMIC_CAS)};
    return getOutlineAtomicHelper(LC, Ordering, MemSize);
  }
  case TargetOpcode::G_ATOMICRMW_XCHG: {
    const RTLIB::Libcall LC[5][4] = {LCALL5(RTLIB::OUTLINE_ATOMIC_SWP)};
    return getOutlineAtomicHelper(LC, Ordering, MemSize);
  }
  case TargetOpcode::G_ATOMICRMW_ADD:
  case TargetOpcode::G_ATOMICRMW_SUB: {
    const RTLIB::Libcall LC[5][4] = {LCALL5(RTLIB::OUTLINE_ATOMIC_LDADD)};
    return getOutlineAtomicHelper(LC, Ordering, MemSize);
  }
  case TargetOpcode::G_ATOMICRMW_AND: {
    const RTLIB::Libcall LC[5][4] = {LCALL5(RTLIB::OUTLINE_ATOMIC_LDCLR)};
    return getOutlineAtomicHelper(LC, Ordering, MemSize);
  }
  case TargetOpcode::G_ATOMICRMW_OR: {
    const RTLIB::Libcall LC[5][4] = {LCALL5(RTLIB::OUTLINE_ATOMIC_LDSET)};
    return getOutlineAtomicHelper(LC, Ordering, MemSize);
  }
  case TargetOpcode::G_ATOMICRMW_XOR: {
    const RTLIB::Libcall LC[5][4] = {LCALL5(RTLIB::OUTLINE_ATOMIC_LDEOR)};
    return getOutlineAtomicHelper(LC, Ordering, MemSize);
  }
  default:
    return RTLIB::UNKNOWN_LIBCALL;
  }
#undef LCALLS
#undef LCALL5
}

LegalizerHelper::LegalizeResult
LegalizerHelper::createAtomicLibcall(MachineInstr &MI) const {
  auto &Ctx = MIRBuilder.getContext();

  Type *RetTy;
  SmallVector<Register> RetRegs;
  SmallVector<CallLowering::ArgInfo, 3> Args;
  unsigned Opc = MI.getOpcode();
  switch (Opc) {
  case TargetOpcode::G_ATOMIC_CMPXCHG:
  case TargetOpcode::G_ATOMIC_CMPXCHG_WITH_SUCCESS: {
    Register Success;
    LLT SuccessLLT;
    auto [Ret, RetLLT, Mem, MemLLT, Cmp, CmpLLT, New, NewLLT] =
        MI.getFirst4RegLLTs();
    RetRegs.push_back(Ret);
    RetTy = IntegerType::get(Ctx, RetLLT.getSizeInBits());
    if (Opc == TargetOpcode::G_ATOMIC_CMPXCHG_WITH_SUCCESS) {
      std::tie(Ret, RetLLT, Success, SuccessLLT, Mem, MemLLT, Cmp, CmpLLT, New,
               NewLLT) = MI.getFirst5RegLLTs();
      RetRegs.push_back(Success);
      RetTy = StructType::get(
          Ctx, {RetTy, IntegerType::get(Ctx, SuccessLLT.getSizeInBits())});
    }
    Args.push_back({Cmp, IntegerType::get(Ctx, CmpLLT.getSizeInBits()), 0});
    Args.push_back({New, IntegerType::get(Ctx, NewLLT.getSizeInBits()), 0});
    Args.push_back({Mem, PointerType::get(Ctx, MemLLT.getAddressSpace()), 0});
    break;
  }
  case TargetOpcode::G_ATOMICRMW_XCHG:
  case TargetOpcode::G_ATOMICRMW_ADD:
  case TargetOpcode::G_ATOMICRMW_SUB:
  case TargetOpcode::G_ATOMICRMW_AND:
  case TargetOpcode::G_ATOMICRMW_OR:
  case TargetOpcode::G_ATOMICRMW_XOR: {
    auto [Ret, RetLLT, Mem, MemLLT, Val, ValLLT] = MI.getFirst3RegLLTs();
    RetRegs.push_back(Ret);
    RetTy = IntegerType::get(Ctx, RetLLT.getSizeInBits());
    if (Opc == TargetOpcode::G_ATOMICRMW_AND)
      Val =
          MIRBuilder.buildXor(ValLLT, MIRBuilder.buildConstant(ValLLT, -1), Val)
              .getReg(0);
    else if (Opc == TargetOpcode::G_ATOMICRMW_SUB)
      Val =
          MIRBuilder.buildSub(ValLLT, MIRBuilder.buildConstant(ValLLT, 0), Val)
              .getReg(0);
    Args.push_back({Val, IntegerType::get(Ctx, ValLLT.getSizeInBits()), 0});
    Args.push_back({Mem, PointerType::get(Ctx, MemLLT.getAddressSpace()), 0});
    break;
  }
  default:
    llvm_unreachable("unsupported opcode");
  }

  if (!Libcalls) // FIXME: Should be mandatory
    return LegalizerHelper::UnableToLegalize;

  auto &CLI = *MIRBuilder.getMF().getSubtarget().getCallLowering();
  RTLIB::Libcall RTLibcall = getOutlineAtomicLibcall(MI);
  RTLIB::LibcallImpl RTLibcallImpl = Libcalls->getLibcallImpl(RTLibcall);

  // Unsupported libcall on the target.
  if (RTLibcallImpl == RTLIB::Unsupported) {
    LLVM_DEBUG(dbgs() << ".. .. Could not find libcall name for "
                      << MIRBuilder.getTII().getName(Opc) << "\n");
    return LegalizerHelper::UnableToLegalize;
  }

  CallLowering::CallLoweringInfo Info;
  Info.CallConv = Libcalls->getLibcallImplCallingConv(RTLibcallImpl);

  StringRef LibcallName =
      RTLIB::RuntimeLibcallsInfo::getLibcallImplName(RTLibcallImpl);
  Info.Callee = MachineOperand::CreateES(LibcallName.data());
  Info.OrigRet = CallLowering::ArgInfo(RetRegs, RetTy, 0);

  llvm::append_range(Info.OrigArgs, Args);
  if (!CLI.lowerCall(MIRBuilder, Info))
    return LegalizerHelper::UnableToLegalize;

  return LegalizerHelper::Legalized;
}

static RTLIB::Libcall
getStateLibraryFunctionFor(MachineInstr &MI, const TargetLowering &TLI) {
  RTLIB::Libcall RTLibcall;
  switch (MI.getOpcode()) {
  case TargetOpcode::G_GET_FPENV:
    RTLibcall = RTLIB::FEGETENV;
    break;
  case TargetOpcode::G_SET_FPENV:
  case TargetOpcode::G_RESET_FPENV:
    RTLibcall = RTLIB::FESETENV;
    break;
  case TargetOpcode::G_GET_FPMODE:
    RTLibcall = RTLIB::FEGETMODE;
    break;
  case TargetOpcode::G_SET_FPMODE:
  case TargetOpcode::G_RESET_FPMODE:
    RTLibcall = RTLIB::FESETMODE;
    break;
  default:
    llvm_unreachable("Unexpected opcode");
  }
  return RTLibcall;
}

// Some library functions that read FP state (fegetmode, fegetenv) write the
// state into a region in memory. IR intrinsics that do the same operations
// (get_fpmode, get_fpenv) return the state as integer value. To implement these
// intrinsics via the library functions, we need to use temporary variable,
// for example:
//
//     %0:_(s32) = G_GET_FPMODE
//
// is transformed to:
//
//     %1:_(p0) = G_FRAME_INDEX %stack.0
//     BL &fegetmode
//     %0:_(s32) = G_LOAD % 1
//
LegalizerHelper::LegalizeResult
LegalizerHelper::createGetStateLibcall(MachineInstr &MI,
                                       LostDebugLocObserver &LocObserver) {
  const DataLayout &DL = MIRBuilder.getDataLayout();
  auto &MF = MIRBuilder.getMF();
  auto &MRI = *MIRBuilder.getMRI();
  auto &Ctx = MF.getFunction().getContext();

  // Create temporary, where library function will put the read state.
  Register Dst = MI.getOperand(0).getReg();
  LLT StateTy = MRI.getType(Dst);
  TypeSize StateSize = StateTy.getSizeInBytes();
  Align TempAlign = getStackTemporaryAlignment(StateTy);
  MachinePointerInfo TempPtrInfo;
  auto Temp = createStackTemporary(StateSize, TempAlign, TempPtrInfo);

  // Create a call to library function, with the temporary as an argument.
  unsigned TempAddrSpace = DL.getAllocaAddrSpace();
  Type *StatePtrTy = PointerType::get(Ctx, TempAddrSpace);
  RTLIB::Libcall RTLibcall = getStateLibraryFunctionFor(MI, TLI);
  auto Res = createLibcall(
      RTLibcall, CallLowering::ArgInfo({0}, Type::getVoidTy(Ctx), 0),
      CallLowering::ArgInfo({Temp.getReg(0), StatePtrTy, 0}), LocObserver,
      nullptr);
  if (Res != LegalizerHelper::Legalized)
    return Res;

  // Create a load from the temporary.
  MachineMemOperand *MMO = MF.getMachineMemOperand(
      TempPtrInfo, MachineMemOperand::MOLoad, StateTy, TempAlign);
  MIRBuilder.buildLoadInstr(TargetOpcode::G_LOAD, Dst, Temp, *MMO);

  return LegalizerHelper::Legalized;
}

// Similar to `createGetStateLibcall` the function calls a library function
// using transient space in stack. In this case the library function reads
// content of memory region.
LegalizerHelper::LegalizeResult
LegalizerHelper::createSetStateLibcall(MachineInstr &MI,
                                       LostDebugLocObserver &LocObserver) {
  const DataLayout &DL = MIRBuilder.getDataLayout();
  auto &MF = MIRBuilder.getMF();
  auto &MRI = *MIRBuilder.getMRI();
  auto &Ctx = MF.getFunction().getContext();

  // Create temporary, where library function will get the new state.
  Register Src = MI.getOperand(0).getReg();
  LLT StateTy = MRI.getType(Src);
  TypeSize StateSize = StateTy.getSizeInBytes();
  Align TempAlign = getStackTemporaryAlignment(StateTy);
  MachinePointerInfo TempPtrInfo;
  auto Temp = createStackTemporary(StateSize, TempAlign, TempPtrInfo);

  // Put the new state into the temporary.
  MachineMemOperand *MMO = MF.getMachineMemOperand(
      TempPtrInfo, MachineMemOperand::MOStore, StateTy, TempAlign);
  MIRBuilder.buildStore(Src, Temp, *MMO);

  // Create a call to library function, with the temporary as an argument.
  unsigned TempAddrSpace = DL.getAllocaAddrSpace();
  Type *StatePtrTy = PointerType::get(Ctx, TempAddrSpace);
  RTLIB::Libcall RTLibcall = getStateLibraryFunctionFor(MI, TLI);
  return createLibcall(RTLibcall,
                       CallLowering::ArgInfo({0}, Type::getVoidTy(Ctx), 0),
                       CallLowering::ArgInfo({Temp.getReg(0), StatePtrTy, 0}),
                       LocObserver, nullptr);
}

/// Returns the corresponding libcall for the given Pred and
/// the ICMP predicate that should be generated to compare with #0
/// after the libcall.
static std::pair<RTLIB::Libcall, CmpInst::Predicate>
getFCMPLibcallDesc(const CmpInst::Predicate Pred, unsigned Size) {
#define RTLIBCASE_CMP(LibcallPrefix, ICmpPred)                                 \
  do {                                                                         \
    switch (Size) {                                                            \
    case 32:                                                                   \
      return {RTLIB::LibcallPrefix##32, ICmpPred};                             \
    case 64:                                                                   \
      return {RTLIB::LibcallPrefix##64, ICmpPred};                             \
    case 128:                                                                  \
      return {RTLIB::LibcallPrefix##128, ICmpPred};                            \
    default:                                                                   \
      llvm_unreachable("unexpected size");                                     \
    }                                                                          \
  } while (0)

  switch (Pred) {
  case CmpInst::FCMP_OEQ:
    RTLIBCASE_CMP(OEQ_F, CmpInst::ICMP_EQ);
  case CmpInst::FCMP_UNE:
    RTLIBCASE_CMP(UNE_F, CmpInst::ICMP_NE);
  case CmpInst::FCMP_OGE:
    RTLIBCASE_CMP(OGE_F, CmpInst::ICMP_SGE);
  case CmpInst::FCMP_OLT:
    RTLIBCASE_CMP(OLT_F, CmpInst::ICMP_SLT);
  case CmpInst::FCMP_OLE:
    RTLIBCASE_CMP(OLE_F, CmpInst::ICMP_SLE);
  case CmpInst::FCMP_OGT:
    RTLIBCASE_CMP(OGT_F, CmpInst::ICMP_SGT);
  case CmpInst::FCMP_UNO:
    RTLIBCASE_CMP(UO_F, CmpInst::ICMP_NE);
  default:
    return {RTLIB::UNKNOWN_LIBCALL, CmpInst::BAD_ICMP_PREDICATE};
  }
}

LegalizerHelper::LegalizeResult
LegalizerHelper::createFCMPLibcall(MachineInstr &MI,
                                   LostDebugLocObserver &LocObserver) {
  auto &MF = MIRBuilder.getMF();
  auto &Ctx = MF.getFunction().getContext();
  const GFCmp *Cmp = cast<GFCmp>(&MI);

  LLT OpLLT = MRI.getType(Cmp->getLHSReg());
  unsigned Size = OpLLT.getSizeInBits();
  if ((Size != 32 && Size != 64 && Size != 128) ||
      OpLLT != MRI.getType(Cmp->getRHSReg()))
    return UnableToLegalize;

  Type *OpType = getFloatTypeForLLT(Ctx, OpLLT);

  // DstReg type is s32
  const Register DstReg = Cmp->getReg(0);
  LLT DstTy = MRI.getType(DstReg);
  const auto Cond = Cmp->getCond();

  // Reference:
  // https://gcc.gnu.org/onlinedocs/gccint/Soft-float-library-routines.html#Comparison-functions-1
  // Generates a libcall followed by ICMP.
  const auto BuildLibcall = [&](const RTLIB::Libcall Libcall,
                                const CmpInst::Predicate ICmpPred,
                                const DstOp &Res) -> Register {
    // FCMP libcall always returns an i32, and needs an ICMP with #0.
    LLT TempLLT = LLT::integer(32);
    Register Temp = MRI.createGenericVirtualRegister(TempLLT);
    // Generate libcall, holding result in Temp
    const auto Status = createLibcall(
        Libcall, {Temp, Type::getInt32Ty(Ctx), 0},
        {{Cmp->getLHSReg(), OpType, 0}, {Cmp->getRHSReg(), OpType, 1}},
        LocObserver, &MI);
    if (!Status)
      return {};

    // Compare temp with #0 to get the final result.
    return MIRBuilder
        .buildICmp(ICmpPred, Res, Temp, MIRBuilder.buildConstant(TempLLT, 0))
        .getReg(0);
  };

  // Simple case if we have a direct mapping from predicate to libcall
  if (const auto [Libcall, ICmpPred] = getFCMPLibcallDesc(Cond, Size);
      Libcall != RTLIB::UNKNOWN_LIBCALL &&
      ICmpPred != CmpInst::BAD_ICMP_PREDICATE) {
    if (BuildLibcall(Libcall, ICmpPred, DstReg)) {
      return Legalized;
    }
    return UnableToLegalize;
  }

  // No direct mapping found, should be generated as combination of libcalls.

  switch (Cond) {
  case CmpInst::FCMP_UEQ: {
    // FCMP_UEQ: unordered or equal
    // Convert into (FCMP_OEQ || FCMP_UNO).

    const auto [OeqLibcall, OeqPred] =
        getFCMPLibcallDesc(CmpInst::FCMP_OEQ, Size);
    const auto Oeq = BuildLibcall(OeqLibcall, OeqPred, DstTy);

    const auto [UnoLibcall, UnoPred] =
        getFCMPLibcallDesc(CmpInst::FCMP_UNO, Size);
    const auto Uno = BuildLibcall(UnoLibcall, UnoPred, DstTy);
    if (Oeq && Uno)
      MIRBuilder.buildOr(DstReg, Oeq, Uno);
    else
      return UnableToLegalize;

    break;
  }
  case CmpInst::FCMP_ONE: {
    // FCMP_ONE: ordered and operands are unequal
    // Convert into (!FCMP_OEQ && !FCMP_UNO).

    // We inverse the predicate instead of generating a NOT
    // to save one instruction.
    // On AArch64 isel can even select two cmp into a single ccmp.
    const auto [OeqLibcall, OeqPred] =
        getFCMPLibcallDesc(CmpInst::FCMP_OEQ, Size);
    const auto NotOeq =
        BuildLibcall(OeqLibcall, CmpInst::getInversePredicate(OeqPred), DstTy);

    const auto [UnoLibcall, UnoPred] =
        getFCMPLibcallDesc(CmpInst::FCMP_UNO, Size);
    const auto NotUno =
        BuildLibcall(UnoLibcall, CmpInst::getInversePredicate(UnoPred), DstTy);

    if (NotOeq && NotUno)
      MIRBuilder.buildAnd(DstReg, NotOeq, NotUno);
    else
      return UnableToLegalize;

    break;
  }
  case CmpInst::FCMP_ULT:
  case CmpInst::FCMP_UGE:
  case CmpInst::FCMP_UGT:
  case CmpInst::FCMP_ULE:
  case CmpInst::FCMP_ORD: {
    // Convert into: !(inverse(Pred))
    // E.g. FCMP_ULT becomes !FCMP_OGE
    // This is equivalent to the following, but saves some instructions.
    //   MIRBuilder.buildNot(
    //       PredTy,
    //       MIRBuilder.buildFCmp(CmpInst::getInversePredicate(Pred), PredTy,
    //                            Op1, Op2));
    const auto [InversedLibcall, InversedPred] =
        getFCMPLibcallDesc(CmpInst::getInversePredicate(Cond), Size);
    if (!BuildLibcall(InversedLibcall,
                      CmpInst::getInversePredicate(InversedPred), DstReg))
      return UnableToLegalize;
    break;
  }
  default:
    return UnableToLegalize;
  }

  return Legalized;
}

// The function is used to legalize operations that set default environment
// state. In C library a call like `fesetmode(FE_DFL_MODE)` is used for that.
// On most targets supported in glibc FE_DFL_MODE is defined as
// `((const femode_t *) -1)`. Such assumption is used here. If for some target
// it is not true, the target must provide custom lowering.
LegalizerHelper::LegalizeResult
LegalizerHelper::createResetStateLibcall(MachineInstr &MI,
                                         LostDebugLocObserver &LocObserver) {
  const DataLayout &DL = MIRBuilder.getDataLayout();
  auto &MF = MIRBuilder.getMF();
  auto &Ctx = MF.getFunction().getContext();

  // Create an argument for the library function.
  unsigned AddrSpace = DL.getDefaultGlobalsAddressSpace();
  Type *StatePtrTy = PointerType::get(Ctx, AddrSpace);
  unsigned PtrSize = DL.getPointerSizeInBits(AddrSpace);
  LLT MemTy = LLT::pointer(AddrSpace, PtrSize);
  auto DefValue = MIRBuilder.buildConstant(LLT::integer(PtrSize), -1LL);
  DstOp Dest(MRI.createGenericVirtualRegister(MemTy));
  MIRBuilder.buildIntToPtr(Dest, DefValue);

  RTLIB::Libcall RTLibcall = getStateLibraryFunctionFor(MI, TLI);
  return createLibcall(
      RTLibcall, CallLowering::ArgInfo({0}, Type::getVoidTy(Ctx), 0),
      CallLowering::ArgInfo({Dest.getReg(), StatePtrTy, 0}), LocObserver, &MI);
}

LegalizerHelper::LegalizeResult
LegalizerHelper::libcall(MachineInstr &MI, LostDebugLocObserver &LocObserver) {
  auto &Ctx = MIRBuilder.getMF().getFunction().getContext();

  switch (MI.getOpcode()) {
  default:
    return UnableToLegalize;
  case TargetOpcode::G_MUL:
  case TargetOpcode::G_SDIV:
  case TargetOpcode::G_UDIV:
  case TargetOpcode::G_SREM:
  case TargetOpcode::G_UREM:
  case TargetOpcode::G_CTLZ_ZERO_POISON: {
    LLT LLTy = MRI.getType(MI.getOperand(0).getReg());
    unsigned Size = LLTy.getSizeInBits();
    Type *HLTy = IntegerType::get(Ctx, Size);
    auto Status = simpleLibcall(MI, MIRBuilder, Size, HLTy, LocObserver);
    if (Status != Legalized)
      return Status;
    break;
  }
  case TargetOpcode::G_FADD:
  case TargetOpcode::G_FSUB:
  case TargetOpcode::G_FMUL:
  case TargetOpcode::G_FDIV:
  case TargetOpcode::G_FMA:
  case TargetOpcode::G_FPOW:
  case TargetOpcode::G_FREM:
  case TargetOpcode::G_FCOS:
  case TargetOpcode::G_FSIN:
  case TargetOpcode::G_FTAN:
  case TargetOpcode::G_FACOS:
  case TargetOpcode::G_FASIN:
  case TargetOpcode::G_FATAN:
  case TargetOpcode::G_FATAN2:
  case TargetOpcode::G_FCOSH:
  case TargetOpcode::G_FSINH:
  case TargetOpcode::G_FTANH:
  case TargetOpcode::G_FLOG10:
  case TargetOpcode::G_FLOG:
  case TargetOpcode::G_FLOG2:
  case TargetOpcode::G_FEXP:
  case TargetOpcode::G_FEXP2:
  case TargetOpcode::G_FEXP10:
  case TargetOpcode::G_FCEIL:
  case TargetOpcode::G_FFLOOR:
  case TargetOpcode::G_FMINNUM:
  case TargetOpcode::G_FMAXNUM:
  case TargetOpcode::G_FMINIMUMNUM:
  case TargetOpcode::G_FMAXIMUMNUM:
  case TargetOpcode::G_FSQRT:
  case TargetOpcode::G_FRINT:
  case TargetOpcode::G_FNEARBYINT:
  case TargetOpcode::G_INTRINSIC_TRUNC:
  case TargetOpcode::G_INTRINSIC_ROUND:
  case TargetOpcode::G_INTRINSIC_ROUNDEVEN: {
    LLT LLTy = MRI.getType(MI.getOperand(0).getReg());
    unsigned Size = LLTy.getSizeInBits();
    Type *HLTy = getFloatTypeForLLT(Ctx, LLTy);
    if (!HLTy || (Size != 32 && Size != 64 && Size != 80 && Size != 128)) {
      LLVM_DEBUG(dbgs() << "No libcall available for type " << LLTy << ".\n");
      return UnableToLegalize;
    }
    auto Status = simpleLibcall(MI, MIRBuilder, Size, HLTy, LocObserver);
    if (Status != Legalized)
      return Status;
    break;
  }
  case TargetOpcode::G_FSINCOS: {
    LLT LLTy = MRI.getType(MI.getOperand(0).getReg());
    unsigned Size = LLTy.getSizeInBits();
    Type *HLTy = getFloatTypeForLLT(Ctx, LLTy);
    if (!HLTy || (Size != 32 && Size != 64 && Size != 80 && Size != 128)) {
      LLVM_DEBUG(dbgs() << "No libcall available for type " << LLTy << ".\n");
      return UnableToLegalize;
    }
    return emitSincosLibcall(MI, MIRBuilder, Size, HLTy, LocObserver);
  }
  case TargetOpcode::G_FMODF: {
    LLT LLTy = MRI.getType(MI.getOperand(0).getReg());
    unsigned Size = LLTy.getSizeInBits();
    Type *HLTy = getFloatTypeForLLT(Ctx, LLTy);
    if (!HLTy || (Size != 32 && Size != 64 && Size != 80 && Size != 128)) {
      LLVM_DEBUG(dbgs() << "No libcall available for type " << LLTy << ".\n");
      return UnableToLegalize;
    }
    return emitModfLibcall(MI, MIRBuilder, Size, HLTy, LocObserver);
  }
  case TargetOpcode::G_LROUND:
  case TargetOpcode::G_LLROUND:
  case TargetOpcode::G_INTRINSIC_LRINT:
  case TargetOpcode::G_INTRINSIC_LLRINT: {
    LLT LLTy = MRI.getType(MI.getOperand(1).getReg());
    unsigned Size = LLTy.getSizeInBits();
    Type *HLTy = getFloatTypeForLLT(Ctx, LLTy);
    Type *ITy = IntegerType::get(
        Ctx, MRI.getType(MI.getOperand(0).getReg()).getSizeInBits());
    if (!HLTy || (Size != 32 && Size != 64 && Size != 80 && Size != 128)) {
      LLVM_DEBUG(dbgs() << "No libcall available for type " << LLTy << ".\n");
      return UnableToLegalize;
    }
    auto Libcall = getRTLibDesc(MI.getOpcode(), Size);
    LegalizeResult Status =
        createLibcall(Libcall, {MI.getOperand(0).getReg(), ITy, 0},
                      {{MI.getOperand(1).getReg(), HLTy, 0}}, LocObserver, &MI);
    if (Status != Legalized)
      return Status;
    MI.eraseFromParent();
    return Legalized;
  }
  case TargetOpcode::G_FPOWI:
  case TargetOpcode::G_FLDEXP: {
    LLT LLTy = MRI.getType(MI.getOperand(0).getReg());
    unsigned Size = LLTy.getSizeInBits();
    Type *HLTy = getFloatTypeForLLT(Ctx, LLTy);
    Type *ITy = IntegerType::get(
        Ctx, MRI.getType(MI.getOperand(2).getReg()).getSizeInBits());
    if (!HLTy || (Size != 32 && Size != 64 && Size != 80 && Size != 128)) {
      LLVM_DEBUG(dbgs() << "No libcall available for type " << LLTy << ".\n");
      return UnableToLegalize;
    }
    auto Libcall = getRTLibDesc(MI.getOpcode(), Size);
    SmallVector<CallLowering::ArgInfo, 2> Args = {
        {MI.getOperand(1).getReg(), HLTy, 0},
        {MI.getOperand(2).getReg(), ITy, 1}};
    Args[1].Flags[0].setSExt();
    LegalizeResult Status = createLibcall(
        Libcall, {MI.getOperand(0).getReg(), HLTy, 0}, Args, LocObserver, &MI);
    if (Status != Legalized)
      return Status;
    break;
  }
  case TargetOpcode::G_FPEXT:
  case TargetOpcode::G_FPTRUNC: {
    Type *FromTy = getFloatTypeForLLT(Ctx,  MRI.getType(MI.getOperand(1).getReg()));
    Type *ToTy = getFloatTypeForLLT(Ctx, MRI.getType(MI.getOperand(0).getReg()));
    if (!FromTy || !ToTy)
      return UnableToLegalize;
    LegalizeResult Status = conversionLibcall(MI, ToTy, FromTy, LocObserver);
    if (Status != Legalized)
      return Status;
    break;
  }
  case TargetOpcode::G_FCMP: {
    LegalizeResult Status = createFCMPLibcall(MI, LocObserver);
    if (Status != Legalized)
      return Status;
    MI.eraseFromParent();
    return Status;
  }
  case TargetOpcode::G_FPTOSI:
  case TargetOpcode::G_FPTOUI: {
    // FIXME: Support other types
    Type *FromTy =
        getFloatTypeForLLT(Ctx, MRI.getType(MI.getOperand(1).getReg()));
    unsigned ToSize = MRI.getType(MI.getOperand(0).getReg()).getSizeInBits();
    if ((ToSize != 32 && ToSize != 64 && ToSize != 128) || !FromTy)
      return UnableToLegalize;
    LegalizeResult Status = conversionLibcall(MI, Type::getIntNTy(Ctx, ToSize),
                                              FromTy, LocObserver);
    if (Status != Legalized)
      return Status;
    break;
  }
  case TargetOpcode::G_SITOFP:
  case TargetOpcode::G_UITOFP: {
    unsigned FromSize = MRI.getType(MI.getOperand(1).getReg()).getSizeInBits();
    Type *ToTy =
        getFloatTypeForLLT(Ctx, MRI.getType(MI.getOperand(0).getReg()));
    if ((FromSize != 32 && FromSize != 64 && FromSize != 128) || !ToTy)
      return UnableToLegalize;
    bool IsSigned = MI.getOpcode() == TargetOpcode::G_SITOFP;
    LegalizeResult Status = conversionLibcall(
        MI, ToTy, Type::getIntNTy(Ctx, FromSize), LocObserver, IsSigned);
    if (Status != Legalized)
      return Status;
    break;
  }
  case TargetOpcode::G_ATOMICRMW_XCHG:
  case TargetOpcode::G_ATOMICRMW_ADD:
  case TargetOpcode::G_ATOMICRMW_SUB:
  case TargetOpcode::G_ATOMICRMW_AND:
  case TargetOpcode::G_ATOMICRMW_OR:
  case TargetOpcode::G_ATOMICRMW_XOR:
  case TargetOpcode::G_ATOMIC_CMPXCHG:
  case TargetOpcode::G_ATOMIC_CMPXCHG_WITH_SUCCESS: {
    auto Status = createAtomicLibcall(MI);
    if (Status != Legalized)
      return Status;
    break;
  }
  case TargetOpcode::G_BZERO:
  case TargetOpcode::G_MEMCPY:
  case TargetOpcode::G_MEMMOVE:
  case TargetOpcode::G_MEMSET: {
    LegalizeResult Result =
        createMemLibcall(*MIRBuilder.getMRI(), MI, LocObserver);
    if (Result != Legalized)
      return Result;
    MI.eraseFromParent();
    return Result;
  }
  case TargetOpcode::G_GET_FPENV:
  case TargetOpcode::G_GET_FPMODE: {
    LegalizeResult Result = createGetStateLibcall(MI, LocObserver);
    if (Result != Legalized)
      return Result;
    break;
  }
  case TargetOpcode::G_SET_FPENV:
  case TargetOpcode::G_SET_FPMODE: {
    LegalizeResult Result = createSetStateLibcall(MI, LocObserver);
    if (Result != Legalized)
      return Result;
    break;
  }
  case TargetOpcode::G_RESET_FPENV:
  case TargetOpcode::G_RESET_FPMODE: {
    LegalizeResult Result = createResetStateLibcall(MI, LocObserver);
    if (Result != Legalized)
      return Result;
    break;
  }
  }

  MI.eraseFromParent();
  return Legalized;
}

LegalizerHelper::LegalizeResult LegalizerHelper::narrowScalar(MachineInstr &MI,
                                                              unsigned TypeIdx,
                                                              LLT NarrowTy) {
  uint64_t SizeOp0 = MRI.getType(MI.getOperand(0).getReg()).getSizeInBits();
  uint64_t NarrowSize = NarrowTy.getSizeInBits();

  switch (MI.getOpcode()) {
  default:
    return UnableToLegalize;
  case TargetOpcode::G_IMPLICIT_DEF: {
    Register DstReg = MI.getOperand(0).getReg();
    LLT DstTy = MRI.getType(DstReg);

    // If SizeOp0 is not an exact multiple of NarrowSize, emit
    // G_ANYEXT(G_IMPLICIT_DEF). Cast result to vector if needed.
    // FIXME: Although this would also be legal for the general case, it causes
    //  a lot of regressions in the emitted code (superfluous COPYs, artifact
    //  combines not being hit). This seems to be a problem related to the
    //  artifact combiner.
    if (SizeOp0 % NarrowSize != 0) {
      LLT ImplicitTy = DstTy.changeElementType(NarrowTy);
      Register ImplicitReg = MIRBuilder.buildUndef(ImplicitTy).getReg(0);
      MIRBuilder.buildAnyExt(DstReg, ImplicitReg);

      MI.eraseFromParent();
      return Legalized;
    }

    int NumParts = SizeOp0 / NarrowSize;

    SmallVector<Register, 2> DstRegs;
    for (int i = 0; i < NumParts; ++i)
      DstRegs.push_back(MIRBuilder.buildUndef(NarrowTy).getReg(0));

    if (DstTy.isVector())
      MIRBuilder.buildBuildVector(DstReg, DstRegs);
    else
      MIRBuilder.buildMergeLikeInstr(DstReg, DstRegs);
    MI.eraseFromParent();
    return Legalized;
  }
  case TargetOpcode::G_CONSTANT: {
    LLT Ty = MRI.getType(MI.getOperand(0).getReg());
    const APInt &Val = MI.getOperand(1).getCImm()->getValue();
    unsigned TotalSize = Ty.getSizeInBits();
    unsigned NarrowSize = NarrowTy.getSizeInBits();
    int NumParts = TotalSize / NarrowSize;

    SmallVector<Register, 4> PartRegs;
    for (int I = 0; I != NumParts; ++I) {
      unsigned Offset = I * NarrowSize;
      auto K = MIRBuilder.buildConstant(NarrowTy,
                                        Val.lshr(Offset).trunc(NarrowSize));
      PartRegs.push_back(K.getReg(0));
    }

    LLT LeftoverTy;
    unsigned LeftoverBits = TotalSize - NumParts * NarrowSize;
    SmallVector<Register, 1> LeftoverRegs;
    if (LeftoverBits != 0) {
      LeftoverTy = LLT::scalar(LeftoverBits);
      auto K = MIRBuilder.buildConstant(
        LeftoverTy,
        Val.lshr(NumParts * NarrowSize).trunc(LeftoverBits));
      LeftoverRegs.push_back(K.getReg(0));
    }

    insertParts(MI.getOperand(0).getReg(),
                Ty, NarrowTy, PartRegs, LeftoverTy, LeftoverRegs);

    MI.eraseFromParent();
    return Legalized;
  }
  case TargetOpcode::G_SEXT:
  case TargetOpcode::G_ZEXT:
  case TargetOpcode::G_ANYEXT:
    return narrowScalarExt(MI, TypeIdx, NarrowTy);
  case TargetOpcode::G_TRUNC: {
    if (TypeIdx != 1)
      return UnableToLegalize;

    uint64_t SizeOp1 = MRI.getType(MI.getOperand(1).getReg()).getSizeInBits();
    if (NarrowTy.getSizeInBits() * 2 != SizeOp1) {
      LLVM_DEBUG(dbgs() << "Can't narrow trunc to type " << NarrowTy << "\n");
      return UnableToLegalize;
    }

    auto Unmerge = MIRBuilder.buildUnmerge(NarrowTy, MI.getOperand(1));
    MIRBuilder.buildCopy(MI.getOperand(0), Unmerge.getReg(0));
    MI.eraseFromParent();
    return Legalized;
  }
  case TargetOpcode::G_CONSTANT_FOLD_BARRIER:
  case TargetOpcode::G_FREEZE: {
    if (TypeIdx != 0)
      return UnableToLegalize;

    LLT Ty = MRI.getType(MI.getOperand(0).getReg());
    // Should widen scalar first
    if (Ty.getSizeInBits() % NarrowTy.getSizeInBits() != 0)
      return UnableToLegalize;

    auto Unmerge = MIRBuilder.buildUnmerge(NarrowTy, MI.getOperand(1).getReg());
    SmallVector<Register, 8> Parts;
    for (unsigned i = 0; i < Unmerge->getNumDefs(); ++i) {
      Parts.push_back(
          MIRBuilder.buildInstr(MI.getOpcode(), {NarrowTy}, {Unmerge.getReg(i)})
              .getReg(0));
    }

    MIRBuilder.buildMergeLikeInstr(MI.getOperand(0).getReg(), Parts);
    MI.eraseFromParent();
    return Legalized;
  }
  case TargetOpcode::G_ADD:
  case TargetOpcode::G_SUB:
  case TargetOpcode::G_SADDO:
  case TargetOpcode::G_SSUBO:
  case TargetOpcode::G_SADDE:
  case TargetOpcode::G_SSUBE:
  case TargetOpcode::G_UADDO:
  case TargetOpcode::G_USUBO:
  case TargetOpcode::G_UADDE:
  case TargetOpcode::G_USUBE:
    return narrowScalarAddSub(MI, TypeIdx, NarrowTy);
  case TargetOpcode::G_MUL:
  case TargetOpcode::G_UMULH:
    return narrowScalarMul(MI, NarrowTy);
  case TargetOpcode::G_EXTRACT:
    return narrowScalarExtract(MI, TypeIdx, NarrowTy);
  case TargetOpcode::G_INSERT:
    return narrowScalarInsert(MI, TypeIdx, NarrowTy);
  case TargetOpcode::G_LOAD: {
    auto &LoadMI = cast<GLoad>(MI);
    Register DstReg = LoadMI.getDstReg();
    LLT DstTy = MRI.getType(DstReg);
    if (DstTy.isVector())
      return UnableToLegalize;

    if (8 * LoadMI.getMemSize().getValue() != DstTy.getSizeInBits()) {
      Register TmpReg = MRI.createGenericVirtualRegister(NarrowTy);
      MIRBuilder.buildLoad(TmpReg, LoadMI.getPointerReg(), LoadMI.getMMO());
      MIRBuilder.buildAnyExt(DstReg, TmpReg);
      LoadMI.eraseFromParent();
      return Legalized;
    }

    return reduceLoadStoreWidth(LoadMI, TypeIdx, NarrowTy);
  }
  case TargetOpcode::G_ZEXTLOAD:
  case TargetOpcode::G_SEXTLOAD:
  case TargetOpcode::G_FPEXTLOAD: {
    auto &LoadMI = cast<GExtLoad>(MI);
    Register DstReg = LoadMI.getDstReg();
    Register PtrReg = LoadMI.getPointerReg();

    Register TmpReg = MRI.createGenericVirtualRegister(NarrowTy);
    auto &MMO = LoadMI.getMMO();
    unsigned MemSize = MMO.getSizeInBits().getValue();

    if (MemSize == NarrowSize) {
      MIRBuilder.buildLoad(TmpReg, PtrReg, MMO);
    } else if (MemSize < NarrowSize) {
      MIRBuilder.buildLoadInstr(LoadMI.getOpcode(), TmpReg, PtrReg, MMO);
    } else if (MemSize > NarrowSize) {
      // FIXME: Need to split the load.
      return UnableToLegalize;
    }

    if (isa<GZExtLoad>(LoadMI))
      MIRBuilder.buildZExt(DstReg, TmpReg);
    else if (isa<GSExtLoad>(LoadMI))
      MIRBuilder.buildSExt(DstReg, TmpReg);
    else
      MIRBuilder.buildFPExt(DstReg, TmpReg);

    LoadMI.eraseFromParent();
    return Legalized;
  }
  case TargetOpcode::G_STORE: {
    auto &StoreMI = cast<GStore>(MI);

    Register SrcReg = StoreMI.getValueReg();
    LLT SrcTy = MRI.getType(SrcReg);
    if (SrcTy.isVector())
      return UnableToLegalize;

    int NumParts = SizeOp0 / NarrowSize;
    unsigned HandledSize = NumParts * NarrowTy.getSizeInBits();
    unsigned LeftoverBits = SrcTy.getSizeInBits() - HandledSize;
    if (SrcTy.isVector() && LeftoverBits != 0)
      return UnableToLegalize;

    if (8 * StoreMI.getMemSize().getValue() != SrcTy.getSizeInBits()) {
      Register TmpReg = MRI.createGenericVirtualRegister(NarrowTy);
      MIRBuilder.buildTrunc(TmpReg, SrcReg);
      MIRBuilder.buildStore(TmpReg, StoreMI.getPointerReg(), StoreMI.getMMO());
      StoreMI.eraseFromParent();
      return Legalized;
    }

    return reduceLoadStoreWidth(StoreMI, 0, NarrowTy);
  }
  case TargetOpcode::G_FPTRUNCSTORE: {
    auto &StoreMI = cast<GFPTruncStore>(MI);
    Register SrcReg = StoreMI.getValueReg();
    Register PtrReg = StoreMI.getPointerReg();

    auto &MMO = StoreMI.getMMO();
    unsigned MemSize = MMO.getSizeInBits().getValue();
    if (MemSize > NarrowSize) {
      return UnableToLegalize;
    }

    auto TmpReg = MIRBuilder.buildFPTrunc(NarrowTy, SrcReg);
    if (MemSize == NarrowSize) {
      MIRBuilder.buildStore(TmpReg, PtrReg, MMO);
    } else if (MemSize < NarrowSize) {
      MIRBuilder.buildStoreInstr(TargetOpcode::G_FPTRUNCSTORE, TmpReg, PtrReg,
                                 MMO);
    }

    StoreMI.eraseFromParent();
    return Legalized;
  }
  case TargetOpcode::G_SELECT:
    return narrowScalarSelect(MI, TypeIdx, NarrowTy);
  case TargetOpcode::G_AND:
  case TargetOpcode::G_OR:
  case TargetOpcode::G_XOR: {
    // Legalize bitwise operation:
    // A = BinOp<Ty> B, C
    // into:
    // B1, ..., BN = G_UNMERGE_VALUES B
    // C1, ..., CN = G_UNMERGE_VALUES C
    // A1 = BinOp<Ty/N> B1, C2
    // ...
    // AN = BinOp<Ty/N> BN, CN
    // A = G_MERGE_VALUES A1, ..., AN
    return narrowScalarBasic(MI, TypeIdx, NarrowTy);
  }
  case TargetOpcode::G_SHL:
  case TargetOpcode::G_LSHR:
  case TargetOpcode::G_ASHR:
    return narrowScalarShift(MI, TypeIdx, NarrowTy);
  case TargetOpcode::G_CTLZ:
  case TargetOpcode::G_CTLZ_ZERO_POISON:
  case TargetOpcode::G_CTTZ:
  case TargetOpcode::G_CTTZ_ZERO_POISON:
  case TargetOpcode::G_CTLS:
  case TargetOpcode::G_CTPOP:
    if (TypeIdx == 1)
      switch (MI.getOpcode()) {
      case TargetOpcode::G_CTLZ:
      case TargetOpcode::G_CTLZ_ZERO_POISON:
        return narrowScalarCTLZ(MI, TypeIdx, NarrowTy);
      case TargetOpcode::G_CTTZ:
      case TargetOpcode::G_CTTZ_ZERO_POISON:
        return narrowScalarCTTZ(MI, TypeIdx, NarrowTy);
      case TargetOpcode::G_CTPOP:
        return narrowScalarCTPOP(MI, TypeIdx, NarrowTy);
      case TargetOpcode::G_CTLS:
        return narrowScalarCTLS(MI, TypeIdx, NarrowTy);
      default:
        return UnableToLegalize;
      }

    Observer.changingInstr(MI);
    narrowScalarDst(MI, NarrowTy, 0, TargetOpcode::G_ZEXT);
    Observer.changedInstr(MI);
    return Legalized;
  case TargetOpcode::G_INTTOPTR:
    if (TypeIdx != 1)
      return UnableToLegalize;

    Observer.changingInstr(MI);
    narrowScalarSrc(MI, NarrowTy, 1);
    Observer.changedInstr(MI);
    return Legalized;
  case TargetOpcode::G_PTRTOINT:
    if (TypeIdx != 0)
      return UnableToLegalize;

    Observer.changingInstr(MI);
    narrowScalarDst(MI, NarrowTy, 0, TargetOpcode::G_ZEXT);
    Observer.changedInstr(MI);
    return Legalized;
  case TargetOpcode::G_PHI: {
    // FIXME: add support for when SizeOp0 isn't an exact multiple of
    // NarrowSize.
    if (SizeOp0 % NarrowSize != 0)
      return UnableToLegalize;

    unsigned NumParts = SizeOp0 / NarrowSize;
    SmallVector<Register, 2> DstRegs(NumParts);
    SmallVector<SmallVector<Register, 2>, 2> SrcRegs(MI.getNumOperands() / 2);
    Observer.changingInstr(MI);
    for (unsigned i = 1; i < MI.getNumOperands(); i += 2) {
      MachineBasicBlock &OpMBB = *MI.getOperand(i + 1).getMBB();
      MIRBuilder.setInsertPt(OpMBB, OpMBB.getFirstTerminatorForward());
      extractParts(MI.getOperand(i).getReg(), NarrowTy, NumParts,
                   SrcRegs[i / 2], MIRBuilder, MRI);
    }
    MachineBasicBlock &MBB = *MI.getParent();
    MIRBuilder.setInsertPt(MBB, MI);
    for (unsigned i = 0; i < NumParts; ++i) {
      DstRegs[i] = MRI.createGenericVirtualRegister(NarrowTy);
      MachineInstrBuilder MIB =
          MIRBuilder.buildInstr(TargetOpcode::G_PHI).addDef(DstRegs[i]);
      for (unsigned j = 1; j < MI.getNumOperands(); j += 2)
        MIB.addUse(SrcRegs[j / 2][i]).add(MI.getOperand(j + 1));
    }
    MIRBuilder.setInsertPt(MBB, MBB.getFirstNonPHI());
    MIRBuilder.buildMergeLikeInstr(MI.getOperand(0), DstRegs);
    Observer.changedInstr(MI);
    MI.eraseFromParent();
    return Legalized;
  }
  case TargetOpcode::G_EXTRACT_VECTOR_ELT:
  case TargetOpcode::G_INSERT_VECTOR_ELT: {
    if (TypeIdx != 2)
      return UnableToLegalize;

    int OpIdx = MI.getOpcode() == TargetOpcode::G_EXTRACT_VECTOR_ELT ? 2 : 3;
    Observer.changingInstr(MI);
    narrowScalarSrc(MI, NarrowTy, OpIdx);
    Observer.changedInstr(MI);
    return Legalized;
  }
  case TargetOpcode::G_ICMP: {
    Register LHS = MI.getOperand(2).getReg();
    LLT SrcTy = MRI.getType(LHS);
    CmpInst::Predicate Pred =
        static_cast<CmpInst::Predicate>(MI.getOperand(1).getPredicate());

    LLT LeftoverTy; // Example: s88 -> s64 (NarrowTy) + s24 (leftover)
    SmallVector<Register, 4> LHSPartRegs, LHSLeftoverRegs;
    if (!extractParts(LHS, SrcTy, NarrowTy, LeftoverTy, LHSPartRegs,
                      LHSLeftoverRegs, MIRBuilder, MRI))
      return UnableToLegalize;

    LLT Unused; // Matches LeftoverTy; G_ICMP LHS and RHS are the same type.
    SmallVector<Register, 4> RHSPartRegs, RHSLeftoverRegs;
    if (!extractParts(MI.getOperand(3).getReg(), SrcTy, NarrowTy, Unused,
                      RHSPartRegs, RHSLeftoverRegs, MIRBuilder, MRI))
      return UnableToLegalize;

    // We now have the LHS and RHS of the compare split into narrow-type
    // registers, plus potentially some leftover type.
    Register Dst = MI.getOperand(0).getReg();
    LLT ResTy = MRI.getType(Dst);
    if (ICmpInst::isEquality(Pred)) {
      // For each part on the LHS and RHS, keep track of the result of XOR-ing
      // them together. For each equal part, the result should be all 0s. For
      // each non-equal part, we'll get at least one 1.
      auto Zero = MIRBuilder.buildConstant(NarrowTy, 0);
      SmallVector<Register, 4> Xors;
      for (auto LHSAndRHS : zip(LHSPartRegs, RHSPartRegs)) {
        auto LHS = std::get<0>(LHSAndRHS);
        auto RHS = std::get<1>(LHSAndRHS);
        auto Xor = MIRBuilder.buildXor(NarrowTy, LHS, RHS).getReg(0);
        Xors.push_back(Xor);
      }

      // Build a G_XOR for each leftover register. Each G_XOR must be widened
      // to the desired narrow type so that we can OR them together later.
      SmallVector<Register, 4> WidenedXors;
      for (auto LHSAndRHS : zip(LHSLeftoverRegs, RHSLeftoverRegs)) {
        auto LHS = std::get<0>(LHSAndRHS);
        auto RHS = std::get<1>(LHSAndRHS);
        auto Xor = MIRBuilder.buildXor(LeftoverTy, LHS, RHS).getReg(0);
        LLT GCDTy = extractGCDType(WidenedXors, NarrowTy, LeftoverTy, Xor);
        buildLCMMergePieces(LeftoverTy, NarrowTy, GCDTy, WidenedXors,
                            /* PadStrategy = */ TargetOpcode::G_ZEXT);
        llvm::append_range(Xors, WidenedXors);
      }

      // Now, for each part we broke up, we know if they are equal/not equal
      // based off the G_XOR. We can OR these all together and compare against
      // 0 to get the result.
      assert(Xors.size() >= 2 && "Should have gotten at least two Xors?");
      auto Or = MIRBuilder.buildOr(NarrowTy, Xors[0], Xors[1]);
      for (unsigned I = 2, E = Xors.size(); I < E; ++I)
        Or = MIRBuilder.buildOr(NarrowTy, Or, Xors[I]);
      MIRBuilder.buildICmp(Pred, Dst, Or, Zero);
    } else {
      Register CmpIn;
      for (unsigned I = 0, E = LHSPartRegs.size(); I != E; ++I) {
        Register CmpOut;
        CmpInst::Predicate PartPred;

        if (I == E - 1 && LHSLeftoverRegs.empty()) {
          PartPred = Pred;
          CmpOut = Dst;
        } else {
          PartPred = ICmpInst::getUnsignedPredicate(Pred);
          CmpOut = MRI.createGenericVirtualRegister(ResTy);
        }

        if (!CmpIn) {
          MIRBuilder.buildICmp(PartPred, CmpOut, LHSPartRegs[I],
                               RHSPartRegs[I]);
        } else {
          auto Cmp = MIRBuilder.buildICmp(PartPred, ResTy, LHSPartRegs[I],
                                          RHSPartRegs[I]);
          auto CmpEq = MIRBuilder.buildICmp(CmpInst::Predicate::ICMP_EQ, ResTy,
                                            LHSPartRegs[I], RHSPartRegs[I]);
          MIRBuilder.buildSelect(CmpOut, CmpEq, CmpIn, Cmp);
        }

        CmpIn = CmpOut;
      }

      for (unsigned I = 0, E = LHSLeftoverRegs.size(); I != E; ++I) {
        Register CmpOut;
        CmpInst::Predicate PartPred;

        if (I == E - 1) {
          PartPred = Pred;
          CmpOut = Dst;
        } else {
          PartPred = ICmpInst::getUnsignedPredicate(Pred);
          CmpOut = MRI.createGenericVirtualRegister(ResTy);
        }

        if (!CmpIn) {
          MIRBuilder.buildICmp(PartPred, CmpOut, LHSLeftoverRegs[I],
                               RHSLeftoverRegs[I]);
        } else {
          auto Cmp = MIRBuilder.buildICmp(PartPred, ResTy, LHSLeftoverRegs[I],
                                          RHSLeftoverRegs[I]);
          auto CmpEq =
              MIRBuilder.buildICmp(CmpInst::Predicate::ICMP_EQ, ResTy,
                                   LHSLeftoverRegs[I], RHSLeftoverRegs[I]);
          MIRBuilder.buildSelect(CmpOut, CmpEq, CmpIn, Cmp);
        }

        CmpIn = CmpOut;
      }
    }
    MI.eraseFromParent();
    return Legalized;
  }
  case TargetOpcode::G_FCMP:
    if (TypeIdx != 0)
      return UnableToLegalize;

    Observer.changingInstr(MI);
    narrowScalarDst(MI, NarrowTy, 0, TargetOpcode::G_ZEXT);
    Observer.changedInstr(MI);
    return Legalized;

  case TargetOpcode::G_SEXT_INREG: {
    if (TypeIdx != 0)
      return UnableToLegalize;

    int64_t SizeInBits = MI.getOperand(2).getImm();

    // So long as the new type has more bits than the bits we're extending we
    // don't need to break it apart.
    if (NarrowTy.getScalarSizeInBits() > SizeInBits) {
      Observer.changingInstr(MI);
      // We don't lose any non-extension bits by truncating the src and
      // sign-extending the dst.
      MachineOperand &MO1 = MI.getOperand(1);
      auto TruncMIB = MIRBuilder.buildTrunc(NarrowTy, MO1);
      MO1.setReg(TruncMIB.getReg(0));

      MachineOperand &MO2 = MI.getOperand(0);
      Register DstExt = MRI.createGenericVirtualRegister(NarrowTy);
      MIRBuilder.setInsertPt(MIRBuilder.getMBB(), ++MIRBuilder.getInsertPt());
      MIRBuilder.buildSExt(MO2, DstExt);
      MO2.setReg(DstExt);
      Observer.changedInstr(MI);
      return Legalized;
    }

    // Break it apart. Components below the extension point are unmodified. The
    // component containing the extension point becomes a narrower SEXT_INREG.
    // Components above it are ashr'd from the component containing the
    // extension point.
    if (SizeOp0 % NarrowSize != 0)
      return UnableToLegalize;
    int NumParts = SizeOp0 / NarrowSize;

    // List the registers where the destination will be scattered.
    SmallVector<Register, 2> DstRegs;
    // List the registers where the source will be split.
    SmallVector<Register, 2> SrcRegs;

    // Create all the temporary registers.
    for (int i = 0; i < NumParts; ++i) {
      Register SrcReg = MRI.createGenericVirtualRegister(NarrowTy);

      SrcRegs.push_back(SrcReg);
    }

    // Explode the big arguments into smaller chunks.
    MIRBuilder.buildUnmerge(SrcRegs, MI.getOperand(1));

    Register AshrCstReg =
        MIRBuilder.buildConstant(NarrowTy, NarrowTy.getScalarSizeInBits() - 1)
            .getReg(0);
    Register FullExtensionReg;
    Register PartialExtensionReg;

    // Do the operation on each small part.
    for (int i = 0; i < NumParts; ++i) {
      if ((i + 1) * NarrowTy.getScalarSizeInBits() <= SizeInBits) {
        DstRegs.push_back(SrcRegs[i]);
        PartialExtensionReg = DstRegs.back();
      } else if (i * NarrowTy.getScalarSizeInBits() >= SizeInBits) {
        assert(PartialExtensionReg &&
               "Expected to visit partial extension before full");
        if (FullExtensionReg) {
          DstRegs.push_back(FullExtensionReg);
          continue;
        }
        DstRegs.push_back(
            MIRBuilder.buildAShr(NarrowTy, PartialExtensionReg, AshrCstReg)
                .getReg(0));
        FullExtensionReg = DstRegs.back();
      } else {
        DstRegs.push_back(
            MIRBuilder
                .buildInstr(
                    TargetOpcode::G_SEXT_INREG, {NarrowTy},
                    {SrcRegs[i], SizeInBits % NarrowTy.getScalarSizeInBits()})
                .getReg(0));
        PartialExtensionReg = DstRegs.back();
      }
    }

    // Gather the destination registers into the final destination.
    Register DstReg = MI.getOperand(0).getReg();
    MIRBuilder.buildMergeLikeInstr(DstReg, DstRegs);
    MI.eraseFromParent();
    return Legalized;
  }
  case TargetOpcode::G_BSWAP:
  case TargetOpcode::G_BITREVERSE: {
    if (SizeOp0 % NarrowSize != 0)
      return UnableToLegalize;

    Observer.changingInstr(MI);
    SmallVector<Register, 2> SrcRegs, DstRegs;
    unsigned NumParts = SizeOp0 / NarrowSize;
    extractParts(MI.getOperand(1).getReg(), NarrowTy, NumParts, SrcRegs,
                 MIRBuilder, MRI);

    for (unsigned i = 0; i < NumParts; ++i) {
      auto DstPart = MIRBuilder.buildInstr(MI.getOpcode(), {NarrowTy},
                                           {SrcRegs[NumParts - 1 - i]});
      DstRegs.push_back(DstPart.getReg(0));
    }

    MIRBuilder.buildMergeLikeInstr(MI.getOperand(0), DstRegs);

    Observer.changedInstr(MI);
    MI.eraseFromParent();
    return Legalized;
  }
  case TargetOpcode::G_PTR_ADD:
  case TargetOpcode::G_PTRMASK: {
    if (TypeIdx != 1)
      return UnableToLegalize;
    Observer.changingInstr(MI);
    narrowScalarSrc(MI, NarrowTy, 2);
    Observer.changedInstr(MI);
    return Legalized;
  }
  case TargetOpcode::G_FPTOUI:
  case TargetOpcode::G_FPTOSI:
  case TargetOpcode::G_FPTOUI_SAT:
  case TargetOpcode::G_FPTOSI_SAT:
    return narrowScalarFPTOI(MI, TypeIdx, NarrowTy);
  case TargetOpcode::G_FPEXT:
    if (TypeIdx != 0)
      return UnableToLegalize;
    Observer.changingInstr(MI);
    narrowScalarDst(MI, NarrowTy, 0, TargetOpcode::G_FPEXT);
    Observer.changedInstr(MI);
    return Legalized;
  case TargetOpcode::G_FLDEXP:
  case TargetOpcode::G_STRICT_FLDEXP:
    return narrowScalarFLDEXP(MI, TypeIdx, NarrowTy);
  case TargetOpcode::G_VSCALE: {
    Register Dst = MI.getOperand(0).getReg();
    LLT Ty = MRI.getType(Dst);

    // Assume VSCALE(1) fits into a legal integer
    const APInt One(NarrowTy.getSizeInBits(), 1);
    auto VScaleBase = MIRBuilder.buildVScale(NarrowTy, One);
    auto ZExt = MIRBuilder.buildZExt(Ty, VScaleBase);
    auto C = MIRBuilder.buildConstant(Ty, *MI.getOperand(1).getCImm());
    MIRBuilder.buildMul(Dst, ZExt, C);

    MI.eraseFromParent();
    return Legalized;
  }
  }
}

Register LegalizerHelper::coerceToScalar(Register Val) {
  LLT Ty = MRI.getType(Val);
  if (Ty.isScalar())
    return Val;

  const DataLayout &DL = MIRBuilder.getDataLayout();
  LLT NewTy = LLT::scalar(Ty.getSizeInBits());
  if (Ty.isPointer()) {
    if (DL.isNonIntegralAddressSpace(Ty.getAddressSpace()))
      return Register();
    return MIRBuilder.buildPtrToInt(NewTy, Val).getReg(0);
  }

  Register NewVal = Val;

  assert(Ty.isVector());
  if (Ty.isPointerVector())
    NewVal = MIRBuilder.buildPtrToInt(NewTy, NewVal).getReg(0);
  return MIRBuilder.buildBitcast(NewTy, NewVal).getReg(0);
}

void LegalizerHelper::widenScalarSrc(MachineInstr &MI, LLT WideTy,
                                     unsigned OpIdx, unsigned ExtOpcode) {
  MachineOperand &MO = MI.getOperand(OpIdx);
  auto ExtB = MIRBuilder.buildInstr(ExtOpcode, {WideTy}, {MO});
  MO.setReg(ExtB.getReg(0));
}

void LegalizerHelper::widenScalarSrcUsingFPExt(MachineInstr &MI, LLT WideTy,
                                               unsigned OpIdx) {
  MachineOperand &MO = MI.getOperand(OpIdx);
  auto ExtB = MIRBuilder.buildInstr(TargetOpcode::G_FPEXT, {WideTy}, {MO},
                                    MI.getFlags());
  MO.setReg(ExtB.getReg(0));
}

void LegalizerHelper::narrowScalarSrc(MachineInstr &MI, LLT NarrowTy,
                                      unsigned OpIdx) {
  MachineOperand &MO = MI.getOperand(OpIdx);
  auto ExtB = MIRBuilder.buildTrunc(NarrowTy, MO);
  MO.setReg(ExtB.getReg(0));
}

void LegalizerHelper::widenScalarDst(MachineInstr &MI, LLT WideTy,
                                     unsigned OpIdx, unsigned TruncOpcode) {
  MachineOperand &MO = MI.getOperand(OpIdx);
  Register DstExt = MRI.createGenericVirtualRegister(WideTy);
  MIRBuilder.setInsertPt(MIRBuilder.getMBB(), ++MIRBuilder.getInsertPt());
  MIRBuilder.buildInstr(TruncOpcode, {MO}, {DstExt});
  MO.setReg(DstExt);
}

void LegalizerHelper::widenScalarDstUsingFPTrunc(MachineInstr &MI, LLT WideTy,
                                                 unsigned OpIdx) {
  MachineOperand &MO = MI.getOperand(OpIdx);
  Register DstExt = MRI.createGenericVirtualRegister(WideTy);
  MIRBuilder.setInsertPt(MIRBuilder.getMBB(), ++MIRBuilder.getInsertPt());
  MIRBuilder.buildInstr(TargetOpcode::G_FPTRUNC, {MO}, {DstExt}, MI.getFlags());
  MO.setReg(DstExt);
}

void LegalizerHelper::narrowScalarDst(MachineInstr &MI, LLT NarrowTy,
                                      unsigned OpIdx, unsigned ExtOpcode) {
  MachineOperand &MO = MI.getOperand(OpIdx);
  Register DstTrunc = MRI.createGenericVirtualRegister(NarrowTy);
  MIRBuilder.setInsertPt(MIRBuilder.getMBB(), ++MIRBuilder.getInsertPt());
  MIRBuilder.buildInstr(ExtOpcode, {MO}, {DstTrunc});
  MO.setReg(DstTrunc);
}

void LegalizerHelper::moreElementsVectorDst(MachineInstr &MI, LLT WideTy,
                                            unsigned OpIdx) {
  MachineOperand &MO = MI.getOperand(OpIdx);
  MIRBuilder.setInsertPt(MIRBuilder.getMBB(), ++MIRBuilder.getInsertPt());
  Register Dst = MO.getReg();
  Register DstExt = MRI.createGenericVirtualRegister(WideTy);
  MO.setReg(DstExt);
  MIRBuilder.buildDeleteTrailingVectorElements(Dst, DstExt);
}

void LegalizerHelper::moreElementsVectorSrc(MachineInstr &MI, LLT MoreTy,
                                            unsigned OpIdx) {
  MachineOperand &MO = MI.getOperand(OpIdx);
  MO.setReg(MIRBuilder.buildPadVectorWithUndefElements(MoreTy, MO).getReg(0));
}

void LegalizerHelper::bitcastSrc(MachineInstr &MI, LLT CastTy, unsigned OpIdx) {
  MachineOperand &Op = MI.getOperand(OpIdx);
  Op.setReg(MIRBuilder.buildBitcast(CastTy, Op).getReg(0));
}

void LegalizerHelper::bitcastDst(MachineInstr &MI, LLT CastTy, unsigned OpIdx) {
  MachineOperand &MO = MI.getOperand(OpIdx);
  Register CastDst = MRI.createGenericVirtualRegister(CastTy);
  MIRBuilder.setInsertPt(MIRBuilder.getMBB(), ++MIRBuilder.getInsertPt());
  MIRBuilder.buildBitcast(MO, CastDst);
  MO.setReg(CastDst);
}

LegalizerHelper::LegalizeResult
LegalizerHelper::widenScalarMergeValues(MachineInstr &MI, unsigned TypeIdx,
                                        LLT WideTy) {
  if (TypeIdx != 1)
    return UnableToLegalize;

  auto [DstReg, DstTy, Src1Reg, Src1Ty] = MI.getFirst2RegLLTs();
  if (DstTy.isVector())
    return UnableToLegalize;

  LLT SrcTy = MRI.getType(Src1Reg);
  const int DstSize = DstTy.getSizeInBits();
  const int SrcSize = SrcTy.getSizeInBits();
  const int WideSize = WideTy.getSizeInBits();
  const int NumMerge = (DstSize + WideSize - 1) / WideSize;

  unsigned NumOps = MI.getNumOperands();
  unsigned NumSrc = MI.getNumOperands() - 1;
  unsigned PartSize = DstTy.getSizeInBits() / NumSrc;

  if (WideSize >= DstSize) {
    // Directly pack the bits in the target type.
    Register ResultReg = MIRBuilder.buildZExt(WideTy, Src1Reg).getReg(0);

    for (unsigned I = 2; I != NumOps; ++I) {
      const unsigned Offset = (I - 1) * PartSize;

      Register SrcReg = MI.getOperand(I).getReg();
      assert(MRI.getType(SrcReg) == LLT::scalar(PartSize));

      auto ZextInput = MIRBuilder.buildZExt(WideTy, SrcReg);

      Register NextResult = I + 1 == NumOps && WideTy == DstTy ? DstReg :
        MRI.createGenericVirtualRegister(WideTy);

      auto ShiftAmt = MIRBuilder.buildConstant(WideTy, Offset);
      auto Shl = MIRBuilder.buildShl(WideTy, ZextInput, ShiftAmt);
      MIRBuilder.buildOr(NextResult, ResultReg, Shl);
      ResultReg = NextResult;
    }

    if (WideSize > DstSize)
      MIRBuilder.buildTrunc(DstReg, ResultReg);
    else if (DstTy.isPointer())
      MIRBuilder.buildIntToPtr(DstReg, ResultReg);

    MI.eraseFromParent();
    return Legalized;
  }

  // Unmerge the original values to the GCD type, and recombine to the next
  // multiple greater than the original type.
  //
  // %3:_(s12) = G_MERGE_VALUES %0:_(s4), %1:_(s4), %2:_(s4) -> s6
  // %4:_(s2), %5:_(s2) = G_UNMERGE_VALUES %0
  // %6:_(s2), %7:_(s2) = G_UNMERGE_VALUES %1
  // %8:_(s2), %9:_(s2) = G_UNMERGE_VALUES %2
  // %10:_(s6) = G_MERGE_VALUES %4, %5, %6
  // %11:_(s6) = G_MERGE_VALUES %7, %8, %9
  // %12:_(s12) = G_MERGE_VALUES %10, %11
  //
  // Padding with undef if necessary:
  //
  // %2:_(s8) = G_MERGE_VALUES %0:_(s4), %1:_(s4) -> s6
  // %3:_(s2), %4:_(s2) = G_UNMERGE_VALUES %0
  // %5:_(s2), %6:_(s2) = G_UNMERGE_VALUES %1
  // %7:_(s2) = G_IMPLICIT_DEF
  // %8:_(s6) = G_MERGE_VALUES %3, %4, %5
  // %9:_(s6) = G_MERGE_VALUES %6, %7, %7
  // %10:_(s12) = G_MERGE_VALUES %8, %9

  const int GCD = std::gcd(SrcSize, WideSize);
  LLT GCDTy = WideTy.changeElementSize(GCD);

  SmallVector<Register, 8> NewMergeRegs;
  SmallVector<Register, 8> Unmerges;
  LLT WideDstTy = WideTy.changeElementSize(NumMerge * WideSize);

  // Decompose the original operands if they don't evenly divide.
  for (const MachineOperand &MO : llvm::drop_begin(MI.operands())) {
    Register SrcReg = MO.getReg();
    if (GCD == SrcSize) {
      Unmerges.push_back(SrcReg);
    } else {
      auto Unmerge = MIRBuilder.buildUnmerge(GCDTy, SrcReg);
      for (int J = 0, JE = Unmerge->getNumOperands() - 1; J != JE; ++J)
        Unmerges.push_back(Unmerge.getReg(J));
    }
  }

  // Pad with undef to the next size that is a multiple of the requested size.
  if (static_cast<int>(Unmerges.size()) != NumMerge * WideSize) {
    Register UndefReg = MIRBuilder.buildUndef(GCDTy).getReg(0);
    for (int I = Unmerges.size(); I != NumMerge * WideSize; ++I)
      Unmerges.push_back(UndefReg);
  }

  const int PartsPerGCD = WideSize / GCD;

  // Build merges of each piece.
  ArrayRef<Register> Slicer(Unmerges);
  for (int I = 0; I != NumMerge; ++I, Slicer = Slicer.drop_front(PartsPerGCD)) {
    auto Merge =
        MIRBuilder.buildMergeLikeInstr(WideTy, Slicer.take_front(PartsPerGCD));
    NewMergeRegs.push_back(Merge.getReg(0));
  }

  // A truncate may be necessary if the requested type doesn't evenly divide the
  // original result type.
  if (DstTy.getSizeInBits() == WideDstTy.getSizeInBits()) {
    MIRBuilder.buildMergeLikeInstr(DstReg, NewMergeRegs);
  } else {
    auto FinalMerge = MIRBuilder.buildMergeLikeInstr(WideDstTy, NewMergeRegs);
    MIRBuilder.buildTrunc(DstReg, FinalMerge.getReg(0));
  }

  MI.eraseFromParent();
  return Legalized;
}

LegalizerHelper::LegalizeResult
LegalizerHelper::widenScalarUnmergeValues(MachineInstr &MI, unsigned TypeIdx,
                                          LLT WideTy) {
  if (TypeIdx != 0)
    return UnableToLegalize;

  int NumDst = MI.getNumOperands() - 1;
  Register SrcReg = MI.getOperand(NumDst).getReg();
  LLT SrcTy = MRI.getType(SrcReg);
  if (SrcTy.isVector())
    return UnableToLegalize;

  Register Dst0Reg = MI.getOperand(0).getReg();
  LLT DstTy = MRI.getType(Dst0Reg);
  if (!DstTy.isScalar())
    return UnableToLegalize;

  if (WideTy.getSizeInBits() >= SrcTy.getSizeInBits()) {
    if (SrcTy.isPointer()) {
      const DataLayout &DL = MIRBuilder.getDataLayout();
      if (DL.isNonIntegralAddressSpace(SrcTy.getAddressSpace())) {
        LLVM_DEBUG(
            dbgs() << "Not casting non-integral address space integer\n");
        return UnableToLegalize;
      }

      SrcTy = LLT::scalar(SrcTy.getSizeInBits());
      SrcReg = MIRBuilder.buildPtrToInt(SrcTy, SrcReg).getReg(0);
    }

    // Widen SrcTy to WideTy. This does not affect the result, but since the
    // user requested this size, it is probably better handled than SrcTy and
    // should reduce the total number of legalization artifacts.
    if (WideTy.getSizeInBits() > SrcTy.getSizeInBits()) {
      SrcTy = WideTy;
      SrcReg = MIRBuilder.buildAnyExt(WideTy, SrcReg).getReg(0);
    }

    // Theres no unmerge type to target. Directly extract the bits from the
    // source type
    unsigned DstSize = DstTy.getSizeInBits();

    MIRBuilder.buildTrunc(Dst0Reg, SrcReg);
    for (int I = 1; I != NumDst; ++I) {
      auto ShiftAmt = MIRBuilder.buildConstant(SrcTy, DstSize * I);
      auto Shr = MIRBuilder.buildLShr(SrcTy, SrcReg, ShiftAmt);
      MIRBuilder.buildTrunc(MI.getOperand(I), Shr);
    }

    MI.eraseFromParent();
    return Legalized;
  }

  // Extend the source to a wider type.
  LLT LCMTy = getLCMType(SrcTy, WideTy);

  Register WideSrc = SrcReg;
  if (LCMTy.getSizeInBits() != SrcTy.getSizeInBits()) {
    // TODO: If this is an integral address space, cast to integer and anyext.
    if (SrcTy.isPointer()) {
      LLVM_DEBUG(dbgs() << "Widening pointer source types not implemented\n");
      return UnableToLegalize;
    }

    WideSrc = MIRBuilder.buildAnyExt(LCMTy, WideSrc).getReg(0);
  }

  auto Unmerge = MIRBuilder.buildUnmerge(WideTy, WideSrc);

  // Create a sequence of unmerges and merges to the original results. Since we
  // may have widened the source, we will need to pad the results with dead defs
  // to cover the source register.
  // e.g. widen s48 to s64:
  // %1:_(s48), %2:_(s48) = G_UNMERGE_VALUES %0:_(s96)
  //
  // =>
  //  %4:_(s192) = G_ANYEXT %0:_(s96)
  //  %5:_(s64), %6, %7 = G_UNMERGE_VALUES %4 ; Requested unmerge
  //  ; unpack to GCD type, with extra dead defs
  //  %8:_(s16), %9, %10, %11 = G_UNMERGE_VALUES %5:_(s64)
  //  %12:_(s16), %13, dead %14, dead %15 = G_UNMERGE_VALUES %6:_(s64)
  //  dead %16:_(s16), dead %17, dead %18, dead %18 = G_UNMERGE_VALUES %7:_(s64)
  //  %1:_(s48) = G_MERGE_VALUES %8:_(s16), %9, %10   ; Remerge to destination
  //  %2:_(s48) = G_MERGE_VALUES %11:_(s16), %12, %13 ; Remerge to destination
  const LLT GCDTy = getGCDType(WideTy, DstTy);
  const int NumUnmerge = Unmerge->getNumOperands() - 1;
  const int PartsPerRemerge = DstTy.getSizeInBits() / GCDTy.getSizeInBits();

  // Directly unmerge to the destination without going through a GCD type
  // if possible
  if (PartsPerRemerge == 1) {
    const int PartsPerUnmerge = WideTy.getSizeInBits() / DstTy.getSizeInBits();

    for (int I = 0; I != NumUnmerge; ++I) {
      auto MIB = MIRBuilder.buildInstr(TargetOpcode::G_UNMERGE_VALUES);

      for (int J = 0; J != PartsPerUnmerge; ++J) {
        int Idx = I * PartsPerUnmerge + J;
        if (Idx < NumDst)
          MIB.addDef(MI.getOperand(Idx).getReg());
        else {
          // Create dead def for excess components.
          MIB.addDef(MRI.createGenericVirtualRegister(DstTy));
        }
      }

      MIB.addUse(Unmerge.getReg(I));
    }
  } else {
    SmallVector<Register, 16> Parts;
    for (int J = 0; J != NumUnmerge; ++J)
      extractGCDType(Parts, GCDTy, Unmerge.getReg(J));

    SmallVector<Register, 8> RemergeParts;
    for (int I = 0; I != NumDst; ++I) {
      for (int J = 0; J < PartsPerRemerge; ++J) {
        const int Idx = I * PartsPerRemerge + J;
        RemergeParts.emplace_back(Parts[Idx]);
      }

      MIRBuilder.buildMergeLikeInstr(MI.getOperand(I).getReg(), RemergeParts);
      RemergeParts.clear();
    }
  }

  MI.eraseFromParent();
  return Legalized;
}

LegalizerHelper::LegalizeResult
LegalizerHelper::widenScalarExtract(MachineInstr &MI, unsigned TypeIdx,
                                    LLT WideTy) {
  auto [DstReg, DstTy, SrcReg, SrcTy] = MI.getFirst2RegLLTs();
  unsigned Offset = MI.getOperand(2).getImm();

  if (TypeIdx == 0) {
    if (SrcTy.isVector() || DstTy.isVector())
      return UnableToLegalize;

    SrcOp Src(SrcReg);
    if (SrcTy.isPointer()) {
      // Extracts from pointers can be handled only if they are really just
      // simple integers.
      const DataLayout &DL = MIRBuilder.getDataLayout();
      if (DL.isNonIntegralAddressSpace(SrcTy.getAddressSpace()))
        return UnableToLegalize;

      LLT SrcAsIntTy = LLT::scalar(SrcTy.getSizeInBits());
      Src = MIRBuilder.buildPtrToInt(SrcAsIntTy, Src);
      SrcTy = SrcAsIntTy;
    }

    if (DstTy.isPointer())
      return UnableToLegalize;

    if (Offset == 0) {
      // Avoid a shift in the degenerate case.
      MIRBuilder.buildTrunc(DstReg,
                            MIRBuilder.buildAnyExtOrTrunc(WideTy, Src));
      MI.eraseFromParent();
      return Legalized;
    }

    // Do a shift in the source type.
    LLT ShiftTy = SrcTy;
    if (WideTy.getSizeInBits() > SrcTy.getSizeInBits()) {
      Src = MIRBuilder.buildAnyExt(WideTy, Src);
      ShiftTy = WideTy;
    }

    auto LShr = MIRBuilder.buildLShr(
      ShiftTy, Src, MIRBuilder.buildConstant(ShiftTy, Offset));
    MIRBuilder.buildTrunc(DstReg, LShr);
    MI.eraseFromParent();
    return Legalized;
  }

  if (SrcTy.isScalar()) {
    Observer.changingInstr(MI);
    widenScalarSrc(MI, WideTy, 1, TargetOpcode::G_ANYEXT);
    Observer.changedInstr(MI);
    return Legalized;
  }

  if (!SrcTy.isVector())
    return UnableToLegalize;

  if (DstTy != SrcTy.getElementType())
    return UnableToLegalize;

  if (Offset % SrcTy.getScalarSizeInBits() != 0)
    return UnableToLegalize;

  Observer.changingInstr(MI);
  widenScalarSrc(MI, WideTy, 1, TargetOpcode::G_ANYEXT);

  MI.getOperand(2).setImm((WideTy.getSizeInBits() / SrcTy.getSizeInBits()) *
                          Offset);
  widenScalarDst(MI, WideTy.getScalarType(), 0);
  Observer.changedInstr(MI);
  return Legalized;
}

LegalizerHelper::LegalizeResult
LegalizerHelper::widenScalarInsert(MachineInstr &MI, unsigned TypeIdx,
                                   LLT WideTy) {
  if (TypeIdx != 0 || WideTy.isVector())
    return UnableToLegalize;
  Observer.changingInstr(MI);
  widenScalarSrc(MI, WideTy, 1, TargetOpcode::G_ANYEXT);
  widenScalarDst(MI, WideTy);
  Observer.changedInstr(MI);
  return Legalized;
}

LegalizerHelper::LegalizeResult
LegalizerHelper::widenScalarAddSubOverflow(MachineInstr &MI, unsigned TypeIdx,
                                           LLT WideTy) {
  unsigned Opcode;
  unsigned ExtOpcode;
  std::optional<Register> CarryIn;
  switch (MI.getOpcode()) {
  default:
    llvm_unreachable("Unexpected opcode!");
  case TargetOpcode::G_SADDO:
    Opcode = TargetOpcode::G_ADD;
    ExtOpcode = TargetOpcode::G_SEXT;
    break;
  case TargetOpcode::G_SSUBO:
    Opcode = TargetOpcode::G_SUB;
    ExtOpcode = TargetOpcode::G_SEXT;
    break;
  case TargetOpcode::G_UADDO:
    Opcode = TargetOpcode::G_ADD;
    ExtOpcode = TargetOpcode::G_ZEXT;
    break;
  case TargetOpcode::G_USUBO:
    Opcode = TargetOpcode::G_SUB;
    ExtOpcode = TargetOpcode::G_ZEXT;
    break;
  case TargetOpcode::G_SADDE:
    Opcode = TargetOpcode::G_UADDE;
    ExtOpcode = TargetOpcode::G_SEXT;
    CarryIn = MI.getOperand(4).getReg();
    break;
  case TargetOpcode::G_SSUBE:
    Opcode = TargetOpcode::G_USUBE;
    ExtOpcode = TargetOpcode::G_SEXT;
    CarryIn = MI.getOperand(4).getReg();
    break;
  case TargetOpcode::G_UADDE:
    Opcode = TargetOpcode::G_UADDE;
    ExtOpcode = TargetOpcode::G_ZEXT;
    CarryIn = MI.getOperand(4).getReg();
    break;
  case TargetOpcode::G_USUBE:
    Opcode = TargetOpcode::G_USUBE;
    ExtOpcode = TargetOpcode::G_ZEXT;
    CarryIn = MI.getOperand(4).getReg();
    break;
  }

  if (TypeIdx == 1) {
    unsigned BoolExtOp = MIRBuilder.getBoolExtOp(WideTy.isVector(), false);

    Observer.changingInstr(MI);
    if (CarryIn)
      widenScalarSrc(MI, WideTy, 4, BoolExtOp);
    widenScalarDst(MI, WideTy, 1);

    Observer.changedInstr(MI);
    return Legalized;
  }

  auto LHSExt = MIRBuilder.buildInstr(ExtOpcode, {WideTy}, {MI.getOperand(2)});
  auto RHSExt = MIRBuilder.buildInstr(ExtOpcode, {WideTy}, {MI.getOperand(3)});
  // Do the arithmetic in the larger type.
  Register NewOp;
  if (CarryIn) {
    LLT CarryOutTy = MRI.getType(MI.getOperand(1).getReg());
    NewOp = MIRBuilder
                .buildInstr(Opcode, {WideTy, CarryOutTy},
                            {LHSExt, RHSExt, *CarryIn})
                .getReg(0);
  } else {
    NewOp = MIRBuilder.buildInstr(Opcode, {WideTy}, {LHSExt, RHSExt}).getReg(0);
  }
  LLT OrigTy = MRI.getType(MI.getOperand(0).getReg());
  auto TruncOp = MIRBuilder.buildTrunc(OrigTy, NewOp);
  auto ExtOp = MIRBuilder.buildInstr(ExtOpcode, {WideTy}, {TruncOp});
  // There is no overflow if the ExtOp is the same as NewOp.
  MIRBuilder.buildICmp(CmpInst::ICMP_NE, MI.getOperand(1), NewOp, ExtOp);
  // Now trunc the NewOp to the original result.
  MIRBuilder.buildTrunc(MI.getOperand(0), NewOp);
  MI.eraseFromParent();
  return Legalized;
}

LegalizerHelper::LegalizeResult
LegalizerHelper::widenScalarAddSubShlSat(MachineInstr &MI, unsigned TypeIdx,
                                         LLT WideTy) {
  bool IsSigned = MI.getOpcode() == TargetOpcode::G_SADDSAT ||
                  MI.getOpcode() == TargetOpcode::G_SSUBSAT ||
                  MI.getOpcode() == TargetOpcode::G_SSHLSAT;
  bool IsShift = MI.getOpcode() == TargetOpcode::G_SSHLSAT ||
                 MI.getOpcode() == TargetOpcode::G_USHLSAT;
  // We can convert this to:
  //   1. Any extend iN to iM
  //   2. SHL by M-N
  //   3. [US][ADD|SUB|SHL]SAT
  //   4. L/ASHR by M-N
  //
  // It may be more efficient to lower this to a min and a max operation in
  // the higher precision arithmetic if the promoted operation isn't legal,
  // but this decision is up to the target's lowering request.
  Register DstReg = MI.getOperand(0).getReg();

  unsigned NewBits = WideTy.getScalarSizeInBits();
  unsigned SHLAmount = NewBits - MRI.getType(DstReg).getScalarSizeInBits();

  // Shifts must zero-extend the RHS to preserve the unsigned quantity, and
  // must not left shift the RHS to preserve the shift amount.
  auto LHS = MIRBuilder.buildAnyExt(WideTy, MI.getOperand(1));
  auto RHS = IsShift ? MIRBuilder.buildZExt(WideTy, MI.getOperand(2))
                     : MIRBuilder.buildAnyExt(WideTy, MI.getOperand(2));
  auto ShiftK = MIRBuilder.buildConstant(WideTy, SHLAmount);
  auto ShiftL = MIRBuilder.buildShl(WideTy, LHS, ShiftK);
  auto ShiftR = IsShift ? RHS : MIRBuilder.buildShl(WideTy, RHS, ShiftK);

  auto WideInst = MIRBuilder.buildInstr(MI.getOpcode(), {WideTy},
                                        {ShiftL, ShiftR}, MI.getFlags());

  // Use a shift that will preserve the number of sign bits when the trunc is
  // folded away.
  auto Result = IsSigned ? MIRBuilder.buildAShr(WideTy, WideInst, ShiftK)
                         : MIRBuilder.buildLShr(WideTy, WideInst, ShiftK);

  MIRBuilder.buildTrunc(DstReg, Result);
  MI.eraseFromParent();
  return Legalized;
}

LegalizerHelper::LegalizeResult
LegalizerHelper::widenScalarMulo(MachineInstr &MI, unsigned TypeIdx,
                                 LLT WideTy) {
  if (TypeIdx == 1) {
    Observer.changingInstr(MI);
    widenScalarDst(MI, WideTy, 1);
    Observer.changedInstr(MI);
    return Legalized;
  }

  bool IsSigned = MI.getOpcode() == TargetOpcode::G_SMULO;
  auto [Result, OriginalOverflow, LHS, RHS] = MI.getFirst4Regs();
  LLT SrcTy = MRI.getType(LHS);
  LLT OverflowTy = MRI.getType(OriginalOverflow);
  unsigned SrcBitWidth = SrcTy.getScalarSizeInBits();

  // To determine if the result overflowed in the larger type, we extend the
  // input to the larger type, do the multiply (checking if it overflows),
  // then also check the high bits of the result to see if overflow happened
  // there.
  unsigned ExtOp = IsSigned ? TargetOpcode::G_SEXT : TargetOpcode::G_ZEXT;
  auto LeftOperand = MIRBuilder.buildInstr(ExtOp, {WideTy}, {LHS});
  auto RightOperand = MIRBuilder.buildInstr(ExtOp, {WideTy}, {RHS});

  // Multiplication cannot overflow if the WideTy is >= 2 * original width,
  // so we don't need to check the overflow result of larger type Mulo.
  bool WideMulCanOverflow = WideTy.getScalarSizeInBits() < 2 * SrcBitWidth;

  unsigned MulOpc =
      WideMulCanOverflow ? MI.getOpcode() : (unsigned)TargetOpcode::G_MUL;

  MachineInstrBuilder Mulo;
  if (WideMulCanOverflow)
    Mulo = MIRBuilder.buildInstr(MulOpc, {WideTy, OverflowTy},
                                 {LeftOperand, RightOperand});
  else
    Mulo = MIRBuilder.buildInstr(MulOpc, {WideTy}, {LeftOperand, RightOperand});

  auto Mul = Mulo->getOperand(0);
  MIRBuilder.buildTrunc(Result, Mul);

  MachineInstrBuilder ExtResult;
  // Overflow occurred if it occurred in the larger type, or if the high part
  // of the result does not zero/sign-extend the low part.  Check this second
  // possibility first.
  if (IsSigned) {
    // For signed, overflow occurred when the high part does not sign-extend
    // the low part.
    ExtResult = MIRBuilder.buildSExtInReg(WideTy, Mul, SrcBitWidth);
  } else {
    // Unsigned overflow occurred when the high part does not zero-extend the
    // low part.
    ExtResult = MIRBuilder.buildZExtInReg(WideTy, Mul, SrcBitWidth);
  }

  if (WideMulCanOverflow) {
    auto Overflow =
        MIRBuilder.buildICmp(CmpInst::ICMP_NE, OverflowTy, Mul, ExtResult);
    // Finally check if the multiplication in the larger type itself overflowed.
    MIRBuilder.buildOr(OriginalOverflow, Mulo->getOperand(1), Overflow);
  } else {
    MIRBuilder.buildICmp(CmpInst::ICMP_NE, OriginalOverflow, Mul, ExtResult);
  }
  MI.eraseFromParent();
  return Legalized;
}

LegalizerHelper::LegalizeResult
LegalizerHelper::widenScalar(MachineInstr &MI, unsigned TypeIdx, LLT WideTy) {
  unsigned Opcode = MI.getOpcode();
  switch (Opcode) {
  default:
    return UnableToLegalize;
  case TargetOpcode::G_ATOMICRMW_XCHG:
  case TargetOpcode::G_ATOMICRMW_ADD:
  case TargetOpcode::G_ATOMICRMW_SUB:
  case TargetOpcode::G_ATOMICRMW_AND:
  case TargetOpcode::G_ATOMICRMW_OR:
  case TargetOpcode::G_ATOMICRMW_XOR:
  case TargetOpcode::G_ATOMICRMW_MIN:
  case TargetOpcode::G_ATOMICRMW_MAX:
  case TargetOpcode::G_ATOMICRMW_UMIN:
  case TargetOpcode::G_ATOMICRMW_UMAX:
    assert(TypeIdx == 0 && "atomicrmw with second scalar type");
    Observer.changingInstr(MI);
    widenScalarSrc(MI, WideTy, 2, TargetOpcode::G_ANYEXT);
    widenScalarDst(MI, WideTy, 0);
    Observer.changedInstr(MI);
    return Legalized;
  case TargetOpcode::G_ATOMIC_CMPXCHG:
    assert(TypeIdx == 0 && "G_ATOMIC_CMPXCHG with second scalar type");
    Observer.changingInstr(MI);
    widenScalarSrc(MI, WideTy, 2, TargetOpcode::G_ANYEXT);
    widenScalarSrc(MI, WideTy, 3, TargetOpcode::G_ANYEXT);
    widenScalarDst(MI, WideTy, 0);
    Observer.changedInstr(MI);
    return Legalized;
  case TargetOpcode::G_ATOMIC_CMPXCHG_WITH_SUCCESS:
    if (TypeIdx == 0) {
      Observer.changingInstr(MI);
      widenScalarSrc(MI, WideTy, 3, TargetOpcode::G_ANYEXT);
      widenScalarSrc(MI, WideTy, 4, TargetOpcode::G_ANYEXT);
      widenScalarDst(MI, WideTy, 0);
      Observer.changedInstr(MI);
      return Legalized;
    }
    assert(TypeIdx == 1 &&
           "G_ATOMIC_CMPXCHG_WITH_SUCCESS with third scalar type");
    Observer.changingInstr(MI);
    widenScalarDst(MI, WideTy, 1);
    Observer.changedInstr(MI);
    return Legalized;
  case TargetOpcode::G_EXTRACT:
    return widenScalarExtract(MI, TypeIdx, WideTy);
  case TargetOpcode::G_INSERT:
    return widenScalarInsert(MI, TypeIdx, WideTy);
  case TargetOpcode::G_MERGE_VALUES:
    return widenScalarMergeValues(MI, TypeIdx, WideTy);
  case TargetOpcode::G_UNMERGE_VALUES:
    return widenScalarUnmergeValues(MI, TypeIdx, WideTy);
  case TargetOpcode::G_SADDO:
  case TargetOpcode::G_SSUBO:
  case TargetOpcode::G_UADDO:
  case TargetOpcode::G_USUBO:
  case TargetOpcode::G_SADDE:
  case TargetOpcode::G_SSUBE:
  case TargetOpcode::G_UADDE:
  case TargetOpcode::G_USUBE:
    return widenScalarAddSubOverflow(MI, TypeIdx, WideTy);
  case TargetOpcode::G_UMULO:
  case TargetOpcode::G_SMULO:
    return widenScalarMulo(MI, TypeIdx, WideTy);
  case TargetOpcode::G_SADDSAT:
  case TargetOpcode::G_SSUBSAT:
  case TargetOpcode::G_SSHLSAT:
  case TargetOpcode::G_UADDSAT:
  case TargetOpcode::G_USUBSAT:
  case TargetOpcode::G_USHLSAT:
    return widenScalarAddSubShlSat(MI, TypeIdx, WideTy);
  case TargetOpcode::G_CTTZ:
  case TargetOpcode::G_CTTZ_ZERO_POISON:
  case TargetOpcode::G_CTLZ:
  case TargetOpcode::G_CTLZ_ZERO_POISON:
  case TargetOpcode::G_CTLS:
  case TargetOpcode::G_CTPOP: {
    if (TypeIdx == 0) {
      Observer.changingInstr(MI);
      widenScalarDst(MI, WideTy, 0);
      Observer.changedInstr(MI);
      return Legalized;
    }

    Register SrcReg = MI.getOperand(1).getReg();

    // First extend the input.
    unsigned ExtOpc;
    switch (Opcode) {
    case TargetOpcode::G_CTTZ:
    case TargetOpcode::G_CTTZ_ZERO_POISON:
    case TargetOpcode::G_CTLZ_ZERO_POISON: // poison shifted out below
      ExtOpc = TargetOpcode::G_ANYEXT;
      break;
    case TargetOpcode::G_CTLS:
      ExtOpc = TargetOpcode::G_SEXT;
      break;
    default:
      ExtOpc = TargetOpcode::G_ZEXT;
    }

    auto MIBSrc = MIRBuilder.buildInstr(ExtOpc, {WideTy}, {SrcReg});
    LLT CurTy = MRI.getType(SrcReg);
    unsigned NewOpc = Opcode;
    if (NewOpc == TargetOpcode::G_CTTZ) {
      // The count is the same in the larger type except if the original
      // value was zero.  This can be handled by setting the bit just off
      // the top of the original type.
      auto TopBit = APInt::getOneBitSet(WideTy.getScalarSizeInBits(),
                                        CurTy.getScalarSizeInBits());
      MIBSrc = MIRBuilder.buildOr(
        WideTy, MIBSrc, MIRBuilder.buildConstant(WideTy, TopBit));
      // Now we know the operand is non-zero, use the more relaxed opcode.
      NewOpc = TargetOpcode::G_CTTZ_ZERO_POISON;
    }

    unsigned SizeDiff =
        WideTy.getScalarSizeInBits() - CurTy.getScalarSizeInBits();

    if (Opcode == TargetOpcode::G_CTLZ_ZERO_POISON) {
      // An optimization where the result is the CTLZ after the left shift by
      // (Difference in widety and current ty), that is,
      // MIBSrc = MIBSrc << (sizeinbits(WideTy) - sizeinbits(CurTy))
      // Result = ctlz MIBSrc
      MIBSrc = MIRBuilder.buildShl(WideTy, MIBSrc,
                                   MIRBuilder.buildConstant(WideTy, SizeDiff));
    }

    // Perform the operation at the larger size.
    auto MIBNewOp = MIRBuilder.buildInstr(NewOpc, {WideTy}, {MIBSrc});
    // This is already the correct result for CTPOP and CTTZs
    if (Opcode == TargetOpcode::G_CTLZ || Opcode == TargetOpcode::G_CTLS) {
      // The correct result is NewOp - (Difference in widety and current ty).
      // At this stage SUB is guaranteed to be positive no-wrap,
      // that to be used in further KnownBits optimizations for CTLZ.
      MIBNewOp = MIRBuilder.buildSub(
          WideTy, MIBNewOp, MIRBuilder.buildConstant(WideTy, SizeDiff),
          Opcode == TargetOpcode::G_CTLZ
              ? std::optional<unsigned>(MachineInstr::NoUWrap)
              : std::nullopt);
    }

    MIRBuilder.buildZExtOrTrunc(MI.getOperand(0), MIBNewOp);
    MI.eraseFromParent();
    return Legalized;
  }
  case TargetOpcode::G_BSWAP: {
    Observer.changingInstr(MI);
    Register DstReg = MI.getOperand(0).getReg();

    Register ShrReg = MRI.createGenericVirtualRegister(WideTy);
    Register DstExt = MRI.createGenericVirtualRegister(WideTy);
    Register ShiftAmtReg = MRI.createGenericVirtualRegister(WideTy);
    widenScalarSrc(MI, WideTy, 1, TargetOpcode::G_ANYEXT);

    MI.getOperand(0).setReg(DstExt);

    MIRBuilder.setInsertPt(MIRBuilder.getMBB(), ++MIRBuilder.getInsertPt());

    LLT Ty = MRI.getType(DstReg);
    unsigned DiffBits = WideTy.getScalarSizeInBits() - Ty.getScalarSizeInBits();
    MIRBuilder.buildConstant(ShiftAmtReg, DiffBits);
    MIRBuilder.buildLShr(ShrReg, DstExt, ShiftAmtReg);

    MIRBuilder.buildTrunc(DstReg, ShrReg);
    Observer.changedInstr(MI);
    return Legalized;
  }
  case TargetOpcode::G_BITREVERSE: {
    Observer.changingInstr(MI);

    Register DstReg = MI.getOperand(0).getReg();
    LLT Ty = MRI.getType(DstReg);
    unsigned DiffBits = WideTy.getScalarSizeInBits() - Ty.getScalarSizeInBits();

    Register DstExt = MRI.createGenericVirtualRegister(WideTy);
    widenScalarSrc(MI, WideTy, 1, TargetOpcode::G_ANYEXT);
    MI.getOperand(0).setReg(DstExt);
    MIRBuilder.setInsertPt(MIRBuilder.getMBB(), ++MIRBuilder.getInsertPt());

    auto ShiftAmt = MIRBuilder.buildConstant(WideTy, DiffBits);
    auto Shift = MIRBuilder.buildLShr(WideTy, DstExt, ShiftAmt);
    MIRBuilder.buildTrunc(DstReg, Shift);
    Observer.changedInstr(MI);
    return Legalized;
  }
  case TargetOpcode::G_FREEZE:
  case TargetOpcode::G_CONSTANT_FOLD_BARRIER:
    Observer.changingInstr(MI);
    widenScalarSrc(MI, WideTy, 1, TargetOpcode::G_ANYEXT);
    widenScalarDst(MI, WideTy);
    Observer.changedInstr(MI);
    return Legalized;

  case TargetOpcode::G_ABS:
    Observer.changingInstr(MI);
    widenScalarSrc(MI, WideTy, 1, TargetOpcode::G_SEXT);
    widenScalarDst(MI, WideTy);
    Observer.changedInstr(MI);
    return Legalized;

  case TargetOpcode::G_ADD:
  case TargetOpcode::G_AND:
  case TargetOpcode::G_MUL:
  case TargetOpcode::G_OR:
  case TargetOpcode::G_XOR:
  case TargetOpcode::G_SUB:
  case TargetOpcode::G_SHUFFLE_VECTOR:
    // Perform operation at larger width (any extension is fines here, high bits
    // don't affect the result) and then truncate the result back to the
    // original type.
    Observer.changingInstr(MI);
    widenScalarSrc(MI, WideTy, 1, TargetOpcode::G_ANYEXT);
    widenScalarSrc(MI, WideTy, 2, TargetOpcode::G_ANYEXT);
    widenScalarDst(MI, WideTy);
    Observer.changedInstr(MI);
    return Legalized;

  case TargetOpcode::G_SBFX:
  case TargetOpcode::G_UBFX:
    Observer.changingInstr(MI);

    if (TypeIdx == 0) {
      widenScalarSrc(MI, WideTy, 1, TargetOpcode::G_ANYEXT);
      widenScalarDst(MI, WideTy);
    } else {
      widenScalarSrc(MI, WideTy, 2, TargetOpcode::G_ZEXT);
      widenScalarSrc(MI, WideTy, 3, TargetOpcode::G_ZEXT);
    }

    Observer.changedInstr(MI);
    return Legalized;

  case TargetOpcode::G_SHL:
    Observer.changingInstr(MI);

    if (TypeIdx == 0) {
      widenScalarSrc(MI, WideTy, 1, TargetOpcode::G_ANYEXT);
      widenScalarDst(MI, WideTy);
    } else {
      assert(TypeIdx == 1);
      // The "number of bits to shift" operand must preserve its value as an
      // unsigned integer:
      widenScalarSrc(MI, WideTy, 2, TargetOpcode::G_ZEXT);
    }

    Observer.changedInstr(MI);
    return Legalized;

  case TargetOpcode::G_ROTR:
  case TargetOpcode::G_ROTL:
    if (TypeIdx != 1)
      return UnableToLegalize;

    Observer.changingInstr(MI);
    widenScalarSrc(MI, WideTy, 2, TargetOpcode::G_ZEXT);
    Observer.changedInstr(MI);
    return Legalized;

  case TargetOpcode::G_SDIV:
  case TargetOpcode::G_SREM:
  case TargetOpcode::G_SMIN:
  case TargetOpcode::G_SMAX:
  case TargetOpcode::G_ABDS:
    Observer.changingInstr(MI);
    widenScalarSrc(MI, WideTy, 1, TargetOpcode::G_SEXT);
    widenScalarSrc(MI, WideTy, 2, TargetOpcode::G_SEXT);
    widenScalarDst(MI, WideTy);
    Observer.changedInstr(MI);
    return Legalized;

  case TargetOpcode::G_SDIVREM:
    Observer.changingInstr(MI);
    widenScalarSrc(MI, WideTy, 2, TargetOpcode::G_SEXT);
    widenScalarSrc(MI, WideTy, 3, TargetOpcode::G_SEXT);
    widenScalarDst(MI, WideTy);
    MIRBuilder.setInsertPt(MIRBuilder.getMBB(), --MIRBuilder.getInsertPt());
    widenScalarDst(MI, WideTy, 1);
    Observer.changedInstr(MI);
    return Legalized;

  case TargetOpcode::G_ASHR:
  case TargetOpcode::G_LSHR:
    Observer.changingInstr(MI);

    if (TypeIdx == 0) {
      unsigned CvtOp = Opcode == TargetOpcode::G_ASHR ? TargetOpcode::G_SEXT
                                                      : TargetOpcode::G_ZEXT;

      widenScalarSrc(MI, WideTy, 1, CvtOp);
      widenScalarDst(MI, WideTy);
    } else {
      assert(TypeIdx == 1);
      // The "number of bits to shift" operand must preserve its value as an
      // unsigned integer:
      widenScalarSrc(MI, WideTy, 2, TargetOpcode::G_ZEXT);
    }

    Observer.changedInstr(MI);
    return Legalized;
  case TargetOpcode::G_UDIV:
  case TargetOpcode::G_UREM:
  case TargetOpcode::G_ABDU:
    Observer.changingInstr(MI);
    widenScalarSrc(MI, WideTy, 1, TargetOpcode::G_ZEXT);
    widenScalarSrc(MI, WideTy, 2, TargetOpcode::G_ZEXT);
    widenScalarDst(MI, WideTy);
    Observer.changedInstr(MI);
    return Legalized;
  case TargetOpcode::G_UDIVREM:
    Observer.changingInstr(MI);
    widenScalarSrc(MI, WideTy, 2, TargetOpcode::G_ZEXT);
    widenScalarSrc(MI, WideTy, 3, TargetOpcode::G_ZEXT);
    widenScalarDst(MI, WideTy);
    MIRBuilder.setInsertPt(MIRBuilder.getMBB(), --MIRBuilder.getInsertPt());
    widenScalarDst(MI, WideTy, 1);
    Observer.changedInstr(MI);
    return Legalized;
  case TargetOpcode::G_UMIN:
  case TargetOpcode::G_UMAX: {
    LLT Ty = MRI.getType(MI.getOperand(0).getReg());

    auto &Ctx = MIRBuilder.getMF().getFunction().getContext();
    unsigned ExtOpc =
        TLI.isSExtCheaperThanZExt(getApproximateEVTForLLT(Ty, Ctx),
                                  getApproximateEVTForLLT(WideTy, Ctx))
            ? TargetOpcode::G_SEXT
            : TargetOpcode::G_ZEXT;

    Observer.changingInstr(MI);
    widenScalarSrc(MI, WideTy, 1, ExtOpc);
    widenScalarSrc(MI, WideTy, 2, ExtOpc);
    widenScalarDst(MI, WideTy);
    Observer.changedInstr(MI);
    return Legalized;
  }

  case TargetOpcode::G_SELECT:
    Observer.changingInstr(MI);
    if (TypeIdx == 0) {
      // Perform operation at larger width (any extension is fine here, high
      // bits don't affect the result) and then truncate the result back to the
      // original type.
      widenScalarSrc(MI, WideTy, 2, TargetOpcode::G_ANYEXT);
      widenScalarSrc(MI, WideTy, 3, TargetOpcode::G_ANYEXT);
      widenScalarDst(MI, WideTy);
    } else {
      bool IsVec = MRI.getType(MI.getOperand(1).getReg()).isVector();
      // Explicit extension is required here since high bits affect the result.
      widenScalarSrc(MI, WideTy, 1, MIRBuilder.getBoolExtOp(IsVec, false));
    }
    Observer.changedInstr(MI);
    return Legalized;

  case TargetOpcode::G_FPEXT:
    if (TypeIdx != 1)
      return UnableToLegalize;

    Observer.changingInstr(MI);
    widenScalarSrcUsingFPExt(MI, WideTy, 1);
    Observer.changedInstr(MI);
    return Legalized;
  case TargetOpcode::G_FPTOSI:
  case TargetOpcode::G_FPTOUI:
  case TargetOpcode::G_INTRINSIC_LRINT:
  case TargetOpcode::G_INTRINSIC_LLRINT:
  case TargetOpcode::G_IS_FPCLASS:
    Observer.changingInstr(MI);

    if (TypeIdx == 0)
      widenScalarDst(MI, WideTy);
    else
      widenScalarSrcUsingFPExt(MI, WideTy, 1);

    Observer.changedInstr(MI);
    return Legalized;
  case TargetOpcode::G_SITOFP:
    Observer.changingInstr(MI);

    if (TypeIdx == 0)
      widenScalarDstUsingFPTrunc(MI, WideTy, 0);
    else
      widenScalarSrc(MI, WideTy, 1, TargetOpcode::G_SEXT);

    Observer.changedInstr(MI);
    return Legalized;
  case TargetOpcode::G_UITOFP:
    Observer.changingInstr(MI);

    if (TypeIdx == 0)
      widenScalarDstUsingFPTrunc(MI, WideTy, 0);
    else
      widenScalarSrc(MI, WideTy, 1, TargetOpcode::G_ZEXT);

    Observer.changedInstr(MI);
    return Legalized;
  case TargetOpcode::G_FPTOSI_SAT:
  case TargetOpcode::G_FPTOUI_SAT:
    Observer.changingInstr(MI);

    if (TypeIdx == 0) {
      Register OldDst = MI.getOperand(0).getReg();
      LLT Ty = MRI.getType(OldDst);
      Register ExtReg = MRI.createGenericVirtualRegister(WideTy);
      Register NewDst;
      MI.getOperand(0).setReg(ExtReg);
      uint64_t ShortBits = Ty.getScalarSizeInBits();
      uint64_t WideBits = WideTy.getScalarSizeInBits();
      MIRBuilder.setInsertPt(MIRBuilder.getMBB(), ++MIRBuilder.getInsertPt());
      if (Opcode == TargetOpcode::G_FPTOSI_SAT) {
        // z = i16 fptosi_sat(a)
        // ->
        // x = i32 fptosi_sat(a)
        // y = smin(x, 32767)
        // z = smax(y, -32768)
        auto MaxVal = MIRBuilder.buildConstant(
            WideTy, APInt::getSignedMaxValue(ShortBits).sext(WideBits));
        auto MinVal = MIRBuilder.buildConstant(
            WideTy, APInt::getSignedMinValue(ShortBits).sext(WideBits));
        Register MidReg =
            MIRBuilder.buildSMin(WideTy, ExtReg, MaxVal).getReg(0);
        NewDst = MIRBuilder.buildSMax(WideTy, MidReg, MinVal).getReg(0);
      } else {
        // z = i16 fptoui_sat(a)
        // ->
        // x = i32 fptoui_sat(a)
        // y = smin(x, 65535)
        auto MaxVal = MIRBuilder.buildConstant(
            WideTy, APInt::getAllOnes(ShortBits).zext(WideBits));
        NewDst = MIRBuilder.buildUMin(WideTy, ExtReg, MaxVal).getReg(0);
      }
      MIRBuilder.buildTrunc(OldDst, NewDst);
    } else
      widenScalarSrcUsingFPExt(MI, WideTy, 1);

    Observer.changedInstr(MI);
    return Legalized;
  case TargetOpcode::G_LOAD:
  case TargetOpcode::G_SEXTLOAD:
  case TargetOpcode::G_ZEXTLOAD:
  case TargetOpcode::G_FPEXTLOAD:
    Observer.changingInstr(MI);
    widenScalarDst(MI, WideTy);
    Observer.changedInstr(MI);
    return Legalized;

  case TargetOpcode::G_STORE: {
    if (TypeIdx != 0)
      return UnableToLegalize;

    LLT Ty = MRI.getType(MI.getOperand(0).getReg());
    assert(!Ty.isPointerOrPointerVector() && "Can't widen type");
    if (!Ty.isScalar()) {
      // We need to widen the vector element type.
      Observer.changingInstr(MI);
      widenScalarSrc(MI, WideTy, 0, TargetOpcode::G_ANYEXT);
      // We also need to adjust the MMO to turn this into a truncating store.
      MachineMemOperand &MMO = **MI.memoperands_begin();
      MachineFunction &MF = MIRBuilder.getMF();
      auto *NewMMO = MF.getMachineMemOperand(&MMO, MMO.getPointerInfo(), Ty);
      MI.setMemRefs(MF, {NewMMO});
      Observer.changedInstr(MI);
      return Legalized;
    }

    Observer.changingInstr(MI);

    unsigned ExtType = Ty.getScalarSizeInBits() == 1 ?
      TargetOpcode::G_ZEXT : TargetOpcode::G_ANYEXT;
    widenScalarSrc(MI, WideTy, 0, ExtType);

    Observer.changedInstr(MI);
    return Legalized;
  }
  case TargetOpcode::G_FPTRUNCSTORE:
    if (TypeIdx != 0)
      return UnableToLegalize;
    Observer.changingInstr(MI);
    widenScalarSrc(MI, WideTy, 0, TargetOpcode::G_FPEXT);
    Observer.changedInstr(MI);
    return Legalized;
  case TargetOpcode::G_CONSTANT: {
    MachineOperand &SrcMO = MI.getOperand(1);
    LLVMContext &Ctx = MIRBuilder.getMF().getFunction().getContext();
    unsigned ExtOpc = LI.getExtOpcodeForWideningConstant(
        MRI.getType(MI.getOperand(0).getReg()));
    assert((ExtOpc == TargetOpcode::G_ZEXT || ExtOpc == TargetOpcode::G_SEXT ||
            ExtOpc == TargetOpcode::G_ANYEXT) &&
           "Illegal Extend");
    const APInt &SrcVal = SrcMO.getCImm()->getValue();
    const APInt &Val = (ExtOpc == TargetOpcode::G_SEXT)
                           ? SrcVal.sext(WideTy.getSizeInBits())
                           : SrcVal.zext(WideTy.getSizeInBits());
    Observer.changingInstr(MI);
    SrcMO.setCImm(ConstantInt::get(Ctx, Val));

    widenScalarDst(MI, WideTy);
    Observer.changedInstr(MI);
    return Legalized;
  }
  case TargetOpcode::G_FCONSTANT: {
    // To avoid changing the bits of the constant due to extension to a larger
    // type and then using G_FPTRUNC, we simply convert to a G_CONSTANT.
    MachineOperand &SrcMO = MI.getOperand(1);
    APInt Val = SrcMO.getFPImm()->getValueAPF().bitcastToAPInt();
    MIRBuilder.setInstrAndDebugLoc(MI);
    auto IntCst = MIRBuilder.buildConstant(MI.getOperand(0).getReg(), Val);
    widenScalarDst(*IntCst, WideTy, 0, TargetOpcode::G_TRUNC);
    MI.eraseFromParent();
    return Legalized;
  }
  case TargetOpcode::G_IMPLICIT_DEF: {
    Observer.changingInstr(MI);
    widenScalarDst(MI, WideTy);
    Observer.changedInstr(MI);
    return Legalized;
  }
  case TargetOpcode::G_BRCOND:
    Observer.changingInstr(MI);
    widenScalarSrc(MI, WideTy, 0, MIRBuilder.getBoolExtOp(false, false));
    Observer.changedInstr(MI);
    return Legalized;

  case TargetOpcode::G_FCMP:
    Observer.changingInstr(MI);
    if (TypeIdx == 0)
      widenScalarDst(MI, WideTy);
    else {
      widenScalarSrcUsingFPExt(MI, WideTy, 2);
      widenScalarSrcUsingFPExt(MI, WideTy, 3);
    }
    Observer.changedInstr(MI);
    return Legalized;

  case TargetOpcode::G_ICMP:
    Observer.changingInstr(MI);
    if (TypeIdx == 0)
      widenScalarDst(MI, WideTy);
    else {
      LLT SrcTy = MRI.getType(MI.getOperand(2).getReg());
      CmpInst::Predicate Pred =
          static_cast<CmpInst::Predicate>(MI.getOperand(1).getPredicate());

      auto &Ctx = MIRBuilder.getMF().getFunction().getContext();
      unsigned ExtOpcode =
          (CmpInst::isSigned(Pred) ||
           TLI.isSExtCheaperThanZExt(getApproximateEVTForLLT(SrcTy, Ctx),
                                     getApproximateEVTForLLT(WideTy, Ctx)))
              ? TargetOpcode::G_SEXT
              : TargetOpcode::G_ZEXT;
      widenScalarSrc(MI, WideTy, 2, ExtOpcode);
      widenScalarSrc(MI, WideTy, 3, ExtOpcode);
    }
    Observer.changedInstr(MI);
    return Legalized;

  case TargetOpcode::G_PTR_ADD:
    assert(TypeIdx == 1 && "unable to legalize pointer of G_PTR_ADD");
    Observer.changingInstr(MI);
    widenScalarSrc(MI, WideTy, 2, TargetOpcode::G_SEXT);
    Observer.changedInstr(MI);
    return Legalized;

  case TargetOpcode::G_PHI: {
    assert(TypeIdx == 0 && "Expecting only Idx 0");

    Observer.changingInstr(MI);
    for (unsigned I = 1; I < MI.getNumOperands(); I += 2) {
      MachineBasicBlock &OpMBB = *MI.getOperand(I + 1).getMBB();
      MIRBuilder.setInsertPt(OpMBB, OpMBB.getFirstTerminatorForward());
      widenScalarSrc(MI, WideTy, I, TargetOpcode::G_ANYEXT);
    }

    MachineBasicBlock &MBB = *MI.getParent();
    MIRBuilder.setInsertPt(MBB, --MBB.getFirstNonPHI());
    widenScalarDst(MI, WideTy);
    Observer.changedInstr(MI);
    return Legalized;
  }
  case TargetOpcode::G_EXTRACT_VECTOR_ELT: {
    if (TypeIdx == 0) {
      Register VecReg = MI.getOperand(1).getReg();
      LLT VecTy = MRI.getType(VecReg);
      Observer.changingInstr(MI);

      widenScalarSrc(MI, LLT::vector(VecTy.getElementCount(), WideTy), 1,
                     TargetOpcode::G_ANYEXT);

      widenScalarDst(MI, WideTy, 0);
      Observer.changedInstr(MI);
      return Legalized;
    }

    if (TypeIdx != 2)
      return UnableToLegalize;
    Observer.changingInstr(MI);
    widenScalarSrc(MI, WideTy, 2, TargetOpcode::G_ZEXT);
    Observer.changedInstr(MI);
    return Legalized;
  }
  case TargetOpcode::G_INSERT_VECTOR_ELT: {
    if (TypeIdx == 0) {
      Observer.changingInstr(MI);
      const LLT WideEltTy = WideTy.getElementType();

      widenScalarSrc(MI, WideTy, 1, TargetOpcode::G_ANYEXT);
      widenScalarSrc(MI, WideEltTy, 2, TargetOpcode::G_ANYEXT);
      widenScalarDst(MI, WideTy, 0);
      Observer.changedInstr(MI);
      return Legalized;
    }

    if (TypeIdx == 1) {
      Observer.changingInstr(MI);

      Register VecReg = MI.getOperand(1).getReg();
      LLT VecTy = MRI.getType(VecReg);
      LLT WideVecTy = VecTy.changeVectorElementType(WideTy);

      widenScalarSrc(MI, WideVecTy, 1, TargetOpcode::G_ANYEXT);
      widenScalarSrc(MI, WideTy, 2, TargetOpcode::G_ANYEXT);
      widenScalarDst(MI, WideVecTy, 0);
      Observer.changedInstr(MI);
      return Legalized;
    }

    if (TypeIdx == 2) {
      Observer.changingInstr(MI);
      widenScalarSrc(MI, WideTy, 3, TargetOpcode::G_ZEXT);
      Observer.changedInstr(MI);
      return Legalized;
    }

    return UnableToLegalize;
  }
  case TargetOpcode::G_FADD:
  case TargetOpcode::G_FMUL:
  case TargetOpcode::G_FSUB:
  case TargetOpcode::G_FMA:
  case TargetOpcode::G_FMAD:
  case TargetOpcode::G_FNEG:
  case TargetOpcode::G_FABS:
  case TargetOpcode::G_FCANONICALIZE:
  case TargetOpcode::G_FMINNUM:
  case TargetOpcode::G_FMAXNUM:
  case TargetOpcode::G_FMINNUM_IEEE:
  case TargetOpcode::G_FMAXNUM_IEEE:
  case TargetOpcode::G_FMINIMUM:
  case TargetOpcode::G_FMAXIMUM:
  case TargetOpcode::G_FMINIMUMNUM:
  case TargetOpcode::G_FMAXIMUMNUM:
  case TargetOpcode::G_FDIV:
  case TargetOpcode::G_FREM:
  case TargetOpcode::G_FCEIL:
  case TargetOpcode::G_FFLOOR:
  case TargetOpcode::G_FCOS:
  case TargetOpcode::G_FSIN:
  case TargetOpcode::G_FTAN:
  case TargetOpcode::G_FACOS:
  case TargetOpcode::G_FASIN:
  case TargetOpcode::G_FATAN:
  case TargetOpcode::G_FATAN2:
  case TargetOpcode::G_FCOSH:
  case TargetOpcode::G_FSINH:
  case TargetOpcode::G_FTANH:
  case TargetOpcode::G_FLOG10:
  case TargetOpcode::G_FLOG:
  case TargetOpcode::G_FLOG2:
  case TargetOpcode::G_FRINT:
  case TargetOpcode::G_FNEARBYINT:
  case TargetOpcode::G_FSQRT:
  case TargetOpcode::G_FEXP:
  case TargetOpcode::G_FEXP2:
  case TargetOpcode::G_FEXP10:
  case TargetOpcode::G_FPOW:
  case TargetOpcode::G_INTRINSIC_TRUNC:
  case TargetOpcode::G_INTRINSIC_ROUND:
  case TargetOpcode::G_INTRINSIC_ROUNDEVEN:
    assert(TypeIdx == 0);
    Observer.changingInstr(MI);

    for (unsigned I = 1, E = MI.getNumOperands(); I != E; ++I)
      widenScalarSrcUsingFPExt(MI, WideTy, I);

    widenScalarDstUsingFPTrunc(MI, WideTy, 0);
    Observer.changedInstr(MI);
    return Legalized;
  case TargetOpcode::G_FMODF: {
    Observer.changingInstr(MI);
    widenScalarSrcUsingFPExt(MI, WideTy, 2);

    widenScalarDstUsingFPTrunc(MI, WideTy, 1);
    MIRBuilder.setInsertPt(MIRBuilder.getMBB(), --MIRBuilder.getInsertPt());
    widenScalarDstUsingFPTrunc(MI, WideTy, 0);
    Observer.changedInstr(MI);
    return Legalized;
  }
  case TargetOpcode::G_FPOWI:
  case TargetOpcode::G_FLDEXP:
  case TargetOpcode::G_STRICT_FLDEXP: {
    if (TypeIdx == 0) {
      if (Opcode == TargetOpcode::G_STRICT_FLDEXP)
        return UnableToLegalize;

      Observer.changingInstr(MI);
      widenScalarSrcUsingFPExt(MI, WideTy, 1);
      widenScalarDstUsingFPTrunc(MI, WideTy, 0);
      Observer.changedInstr(MI);
      return Legalized;
    }

    if (TypeIdx == 1) {
      // For some reason SelectionDAG tries to promote to a libcall without
      // actually changing the integer type for promotion.
      Observer.changingInstr(MI);
      widenScalarSrc(MI, WideTy, 2, TargetOpcode::G_SEXT);
      Observer.changedInstr(MI);
      return Legalized;
    }

    return UnableToLegalize;
  }
  case TargetOpcode::G_FFREXP: {
    Observer.changingInstr(MI);

    if (TypeIdx == 0) {
      widenScalarSrcUsingFPExt(MI, WideTy, 2);
      widenScalarDstUsingFPTrunc(MI, WideTy, 0);
    } else {
      widenScalarDst(MI, WideTy, 1);
    }

    Observer.changedInstr(MI);
    return Legalized;
  }
  case TargetOpcode::G_LROUND:
  case TargetOpcode::G_LLROUND:
    Observer.changingInstr(MI);

    if (TypeIdx == 0)
      widenScalarDst(MI, WideTy);
    else
      widenScalarSrcUsingFPExt(MI, WideTy, 1);

    Observer.changedInstr(MI);
    return Legalized;

  case TargetOpcode::G_INTTOPTR:
    if (TypeIdx != 1)
      return UnableToLegalize;

    Observer.changingInstr(MI);
    widenScalarSrc(MI, WideTy, 1, TargetOpcode::G_ZEXT);
    Observer.changedInstr(MI);
    return Legalized;
  case TargetOpcode::G_PTRTOINT:
    if (TypeIdx != 0)
      return UnableToLegalize;

    Observer.changingInstr(MI);
    widenScalarDst(MI, WideTy, 0);
    Observer.changedInstr(MI);
    return Legalized;
  case TargetOpcode::G_BUILD_VECTOR: {
    Observer.changingInstr(MI);

    const LLT WideEltTy = TypeIdx == 1 ? WideTy : WideTy.getElementType();
    for (int I = 1, E = MI.getNumOperands(); I != E; ++I)
      widenScalarSrc(MI, WideEltTy, I, TargetOpcode::G_ANYEXT);

    // Avoid changing the result vector type if the source element type was
    // requested.
    if (TypeIdx == 1) {
      MI.setDesc(MIRBuilder.getTII().get(TargetOpcode::G_BUILD_VECTOR_TRUNC));
    } else {
      widenScalarDst(MI, WideTy, 0);
    }

    Observer.changedInstr(MI);
    return Legalized;
  }
  case TargetOpcode::G_SEXT_INREG:
    if (TypeIdx != 0)
      return UnableToLegalize;

    Observer.changingInstr(MI);
    widenScalarSrc(MI, WideTy, 1, TargetOpcode::G_ANYEXT);
    widenScalarDst(MI, WideTy, 0, TargetOpcode::G_TRUNC);
    Observer.changedInstr(MI);
    return Legalized;
  case TargetOpcode::G_PTRMASK: {
    if (TypeIdx != 1)
      return UnableToLegalize;
    Observer.changingInstr(MI);
    widenScalarSrc(MI, WideTy, 2, TargetOpcode::G_ZEXT);
    Observer.changedInstr(MI);
    return Legalized;
  }
  case TargetOpcode::G_VECREDUCE_ADD: {
    if (TypeIdx != 1)
      return UnableToLegalize;
    Observer.changingInstr(MI);
    widenScalarSrc(MI, WideTy, 1, TargetOpcode::G_ANYEXT);
    widenScalarDst(MI, WideTy.getScalarType(), 0, TargetOpcode::G_TRUNC);
    Observer.changedInstr(MI);
    return Legalized;
  }
  case TargetOpcode::G_VECREDUCE_FADD:
  case TargetOpcode::G_VECREDUCE_FMUL:
  case TargetOpcode::G_VECREDUCE_FMIN:
  case TargetOpcode::G_VECREDUCE_FMAX:
  case TargetOpcode::G_VECREDUCE_FMINIMUM:
  case TargetOpcode::G_VECREDUCE_FMAXIMUM: {
    if (TypeIdx != 0)
      return UnableToLegalize;
    Observer.changingInstr(MI);
    Register VecReg = MI.getOperand(1).getReg();
    LLT VecTy = MRI.getType(VecReg);
    LLT WideVecTy = VecTy.changeElementType(WideTy);
    widenScalarSrcUsingFPExt(MI, WideVecTy, 1);
    widenScalarDstUsingFPTrunc(MI, WideTy, 0);
    Observer.changedInstr(MI);
    return Legalized;
  }
  case TargetOpcode::G_VSCALE: {
    MachineOperand &SrcMO = MI.getOperand(1);
    LLVMContext &Ctx = MIRBuilder.getMF().getFunction().getContext();
    const APInt &SrcVal = SrcMO.getCImm()->getValue();
    // The CImm is always a signed value
    const APInt Val = SrcVal.sext(WideTy.getSizeInBits());
    Observer.changingInstr(MI);
    SrcMO.setCImm(ConstantInt::get(Ctx, Val));
    widenScalarDst(MI, WideTy);
    Observer.changedInstr(MI);
    return Legalized;
  }
  case TargetOpcode::G_SPLAT_VECTOR: {
    if (TypeIdx != 1)
      return UnableToLegalize;

    Observer.changingInstr(MI);
    widenScalarSrc(MI, WideTy, 1, TargetOpcode::G_ANYEXT);
    Observer.changedInstr(MI);
    return Legalized;
  }
  case TargetOpcode::G_INSERT_SUBVECTOR: {
    if (TypeIdx != 0)
      return UnableToLegalize;

    GInsertSubvector &IS = cast<GInsertSubvector>(MI);
    Register BigVec = IS.getBigVec();
    Register SubVec = IS.getSubVec();

    LLT SubVecTy = MRI.getType(SubVec);
    LLT SubVecWideTy = SubVecTy.changeElementType(WideTy.getElementType());

    // Widen the G_INSERT_SUBVECTOR
    auto BigZExt = MIRBuilder.buildZExt(WideTy, BigVec);
    auto SubZExt = MIRBuilder.buildZExt(SubVecWideTy, SubVec);
    auto WideInsert = MIRBuilder.buildInsertSubvector(WideTy, BigZExt, SubZExt,
                                                      IS.getIndexImm());

    // Truncate back down
    auto SplatZero = MIRBuilder.buildSplatVector(
        WideTy, MIRBuilder.buildConstant(WideTy.getElementType(), 0));
    MIRBuilder.buildICmp(CmpInst::Predicate::ICMP_NE, IS.getReg(0), WideInsert,
                         SplatZero);

    MI.eraseFromParent();

    return Legalized;
  }
  }
}

static void getUnmergePieces(SmallVectorImpl<Register> &Pieces,
                             MachineIRBuilder &B, Register Src, LLT Ty) {
  auto Unmerge = B.buildUnmerge(Ty, Src);
  for (int I = 0, E = Unmerge->getNumOperands() - 1; I != E; ++I)
    Pieces.push_back(Unmerge.getReg(I));
}

static void emitLoadFromConstantPool(Register DstReg, const Constant *ConstVal,
                                     MachineIRBuilder &MIRBuilder) {
  MachineRegisterInfo &MRI = *MIRBuilder.getMRI();
  MachineFunction &MF = MIRBuilder.getMF();
  const DataLayout &DL = MIRBuilder.getDataLayout();
  unsigned AddrSpace = DL.getDefaultGlobalsAddressSpace();
  LLT AddrPtrTy = LLT::pointer(AddrSpace, DL.getPointerSizeInBits(AddrSpace));
  LLT DstLLT = MRI.getType(DstReg);

  Align Alignment(DL.getABITypeAlign(ConstVal->getType()));

  auto Addr = MIRBuilder.buildConstantPool(
      AddrPtrTy,
      MF.getConstantPool()->getConstantPoolIndex(ConstVal, Alignment));

  MachineMemOperand *MMO =
      MF.getMachineMemOperand(MachinePointerInfo::getConstantPool(MF),
                              MachineMemOperand::MOLoad, DstLLT, Alignment);

  MIRBuilder.buildLoadInstr(TargetOpcode::G_LOAD, DstReg, Addr, *MMO);
}

LegalizerHelper::LegalizeResult
LegalizerHelper::lowerConstant(MachineInstr &MI) {
  const MachineOperand &ConstOperand = MI.getOperand(1);
  const Constant *ConstantVal = ConstOperand.getCImm();

  emitLoadFromConstantPool(MI.getOperand(0).getReg(), ConstantVal, MIRBuilder);
  MI.eraseFromParent();

  return Legalized;
}

LegalizerHelper::LegalizeResult
LegalizerHelper::lowerFConstant(MachineInstr &MI) {
  const MachineOperand &ConstOperand = MI.getOperand(1);
  const Constant *ConstantVal = ConstOperand.getFPImm();

  emitLoadFromConstantPool(MI.getOperand(0).getReg(), ConstantVal, MIRBuilder);
  MI.eraseFromParent();

  return Legalized;
}

LegalizerHelper::LegalizeResult
LegalizerHelper::lowerBitcast(MachineInstr &MI) {
  auto [Dst, DstTy, Src, SrcTy] = MI.getFirst2RegLLTs();
  if (SrcTy.isVector()) {
    LLT SrcEltTy = SrcTy.getElementType();
    SmallVector<Register, 8> SrcRegs;

    if (DstTy.isVector()) {
      int NumDstElt = DstTy.getNumElements();
      int NumSrcElt = SrcTy.getNumElements();

      LLT DstEltTy = DstTy.getElementType();
      LLT DstCastTy = DstEltTy; // Intermediate bitcast result type
      LLT SrcPartTy = SrcEltTy; // Original unmerge result type.

      // If there's an element size mismatch, insert intermediate casts to match
      // the result element type.
      if (NumSrcElt < NumDstElt) { // Source element type is larger.
        // %1:_(<4 x s8>) = G_BITCAST %0:_(<2 x s16>)
        //
        // =>
        //
        // %2:_(s16), %3:_(s16) = G_UNMERGE_VALUES %0
        // %3:_(<2 x s8>) = G_BITCAST %2
        // %4:_(<2 x s8>) = G_BITCAST %3
        // %1:_(<4 x s16>) = G_CONCAT_VECTORS %3, %4
        DstCastTy = DstTy.changeVectorElementCount(
            ElementCount::getFixed(NumDstElt / NumSrcElt));
        SrcPartTy = SrcEltTy;
      } else if (NumSrcElt > NumDstElt) { // Source element type is smaller.
        //
        // %1:_(<2 x s16>) = G_BITCAST %0:_(<4 x s8>)
        //
        // =>
        //
        // %2:_(<2 x s8>), %3:_(<2 x s8>) = G_UNMERGE_VALUES %0
        // %3:_(s16) = G_BITCAST %2
        // %4:_(s16) = G_BITCAST %3
        // %1:_(<2 x s16>) = G_BUILD_VECTOR %3, %4
        SrcPartTy = SrcTy.changeVectorElementCount(
            ElementCount::getFixed(NumSrcElt / NumDstElt));
        DstCastTy = DstEltTy;
      }

      getUnmergePieces(SrcRegs, MIRBuilder, Src, SrcPartTy);
      for (Register &SrcReg : SrcRegs)
        SrcReg = MIRBuilder.buildBitcast(DstCastTy, SrcReg).getReg(0);
    } else
      getUnmergePieces(SrcRegs, MIRBuilder, Src, SrcEltTy);

    MIRBuilder.buildMergeLikeInstr(Dst, SrcRegs);
    MI.eraseFromParent();
    return Legalized;
  }

  if (DstTy.isVector()) {
    SmallVector<Register, 8> SrcRegs;
    getUnmergePieces(SrcRegs, MIRBuilder, Src, DstTy.getElementType());
    MIRBuilder.buildMergeLikeInstr(Dst, SrcRegs);
    MI.eraseFromParent();
    return Legalized;
  }

  return UnableToLegalize;
}

/// Figure out the bit offset into a register when coercing a vector index for
/// the wide element type. This is only for the case when promoting vector to
/// one with larger elements.
//
///
/// %offset_idx = G_AND %idx, ~(-1 << Log2(DstEltSize / SrcEltSize))
/// %offset_bits = G_SHL %offset_idx, Log2(SrcEltSize)
static Register getBitcastWiderVectorElementOffset(MachineIRBuilder &B,
                                                   Register Idx,
                                                   unsigned NewEltSize,
                                                   unsigned OldEltSize) {
  const unsigned Log2EltRatio = Log2_32(NewEltSize / OldEltSize);
  LLT IdxTy = B.getMRI()->getType(Idx);

  // Now figure out the amount we need to shift to get the target bits.
  auto OffsetMask = B.buildConstant(
      IdxTy, ~(APInt::getAllOnes(IdxTy.getSizeInBits()) << Log2EltRatio));
  auto OffsetIdx = B.buildAnd(IdxTy, Idx, OffsetMask);
  return B.buildShl(IdxTy, OffsetIdx,
                    B.buildConstant(IdxTy, Log2_32(OldEltSize))).getReg(0);
}

/// Perform a G_EXTRACT_VECTOR_ELT in a different sized vector element. If this
/// is casting to a vector with a smaller element size, perform multiple element
/// extracts and merge the results. If this is coercing to a vector with larger
/// elements, index the bitcasted vector and extract the target element with bit
/// operations. This is intended to force the indexing in the native register
/// size for architectures that can dynamically index the register file.
LegalizerHelper::LegalizeResult
LegalizerHelper::bitcastExtractVectorElt(MachineInstr &MI, unsigned TypeIdx,
                                         LLT CastTy) {
  if (TypeIdx != 1)
    return UnableToLegalize;

  auto [Dst, DstTy, SrcVec, SrcVecTy, Idx, IdxTy] = MI.getFirst3RegLLTs();

  LLT SrcEltTy = SrcVecTy.getElementType();
  unsigned NewNumElts = CastTy.isVector() ? CastTy.getNumElements() : 1;
  unsigned OldNumElts = SrcVecTy.getNumElements();

  LLT NewEltTy = CastTy.getScalarType();
  Register CastVec = MIRBuilder.buildBitcast(CastTy, SrcVec).getReg(0);

  const unsigned NewEltSize = NewEltTy.getSizeInBits();
  const unsigned OldEltSize = SrcEltTy.getSizeInBits();
  if (NewNumElts > OldNumElts) {
    // Decreasing the vector element size
    //
    // e.g. i64 = extract_vector_elt x:v2i64, y:i32
    //  =>
    //  v4i32:castx = bitcast x:v2i64
    //
    // i64 = bitcast
    //   (v2i32 build_vector (i32 (extract_vector_elt castx, (2 * y))),
    //                       (i32 (extract_vector_elt castx, (2 * y + 1)))
    //
    if (NewNumElts % OldNumElts != 0)
      return UnableToLegalize;

    // Type of the intermediate result vector.
    const unsigned NewEltsPerOldElt = NewNumElts / OldNumElts;
    LLT MidTy =
        CastTy.changeElementCount(ElementCount::getFixed(NewEltsPerOldElt));

    auto NewEltsPerOldEltK = MIRBuilder.buildConstant(IdxTy, NewEltsPerOldElt);

    SmallVector<Register, 8> NewOps(NewEltsPerOldElt);
    auto NewBaseIdx = MIRBuilder.buildMul(IdxTy, Idx, NewEltsPerOldEltK);

    for (unsigned I = 0; I < NewEltsPerOldElt; ++I) {
      auto IdxOffset = MIRBuilder.buildConstant(IdxTy, I);
      auto TmpIdx = MIRBuilder.buildAdd(IdxTy, NewBaseIdx, IdxOffset);
      auto Elt = MIRBuilder.buildExtractVectorElement(NewEltTy, CastVec, TmpIdx);
      NewOps[I] = Elt.getReg(0);
    }

    auto NewVec = MIRBuilder.buildBuildVector(MidTy, NewOps);
    MIRBuilder.buildBitcast(Dst, NewVec);
    MI.eraseFromParent();
    return Legalized;
  }

  if (NewNumElts < OldNumElts) {
    if (NewEltSize % OldEltSize != 0)
      return UnableToLegalize;

    // This only depends on powers of 2 because we use bit tricks to figure out
    // the bit offset we need to shift to get the target element. A general
    // expansion could emit division/multiply.
    if (!isPowerOf2_32(NewEltSize / OldEltSize))
      return UnableToLegalize;

    // Increasing the vector element size.
    // %elt:_(small_elt) = G_EXTRACT_VECTOR_ELT %vec:_(<N x small_elt>), %idx
    //
    //   =>
    //
    // %cast = G_BITCAST %vec
    // %scaled_idx = G_LSHR %idx, Log2(DstEltSize / SrcEltSize)
    // %wide_elt  = G_EXTRACT_VECTOR_ELT %cast, %scaled_idx
    // %offset_idx = G_AND %idx, ~(-1 << Log2(DstEltSize / SrcEltSize))
    // %offset_bits = G_SHL %offset_idx, Log2(SrcEltSize)
    // %elt_bits = G_LSHR %wide_elt, %offset_bits
    // %elt = G_TRUNC %elt_bits

    const unsigned Log2EltRatio = Log2_32(NewEltSize / OldEltSize);
    auto Log2Ratio = MIRBuilder.buildConstant(IdxTy, Log2EltRatio);

    // Divide to get the index in the wider element type.
    auto ScaledIdx = MIRBuilder.buildLShr(IdxTy, Idx, Log2Ratio);

    Register WideElt = CastVec;
    if (CastTy.isVector()) {
      WideElt = MIRBuilder.buildExtractVectorElement(NewEltTy, CastVec,
                                                     ScaledIdx).getReg(0);
    }

    // Compute the bit offset into the register of the target element.
    Register OffsetBits = getBitcastWiderVectorElementOffset(
      MIRBuilder, Idx, NewEltSize, OldEltSize);

    // Shift the wide element to get the target element.
    auto ExtractedBits = MIRBuilder.buildLShr(NewEltTy, WideElt, OffsetBits);
    MIRBuilder.buildTrunc(Dst, ExtractedBits);
    MI.eraseFromParent();
    return Legalized;
  }

  return UnableToLegalize;
}

/// Emit code to insert \p InsertReg into \p TargetRet at \p OffsetBits in \p
/// TargetReg, while preserving other bits in \p TargetReg.
///
/// (InsertReg << Offset) | (TargetReg & ~(-1 >> InsertReg.size()) << Offset)
static Register buildBitFieldInsert(MachineIRBuilder &B,
                                    Register TargetReg, Register InsertReg,
                                    Register OffsetBits) {
  LLT TargetTy = B.getMRI()->getType(TargetReg);
  LLT InsertTy = B.getMRI()->getType(InsertReg);
  auto ZextVal = B.buildZExt(TargetTy, InsertReg);
  auto ShiftedInsertVal = B.buildShl(TargetTy, ZextVal, OffsetBits);

  // Produce a bitmask of the value to insert
  auto EltMask = B.buildConstant(
    TargetTy, APInt::getLowBitsSet(TargetTy.getSizeInBits(),
                                   InsertTy.getSizeInBits()));
  // Shift it into position
  auto ShiftedMask = B.buildShl(TargetTy, EltMask, OffsetBits);
  auto InvShiftedMask = B.buildNot(TargetTy, ShiftedMask);

  // Clear out the bits in the wide element
  auto MaskedOldElt = B.buildAnd(TargetTy, TargetReg, InvShiftedMask);

  // The value to insert has all zeros already, so stick it into the masked
  // wide element.
  return B.buildOr(TargetTy, MaskedOldElt, ShiftedInsertVal).getReg(0);
}

/// Perform a G_INSERT_VECTOR_ELT in a different sized vector element. If this
/// is increasing the element size, perform the indexing in the target element
/// type, and use bit operations to insert at the element position. This is
/// intended for architectures that can dynamically index the register file and
/// want to force indexing in the native register size.
LegalizerHelper::LegalizeResult
LegalizerHelper::bitcastInsertVectorElt(MachineInstr &MI, unsigned TypeIdx,
                                        LLT CastTy) {
  if (TypeIdx != 0)
    return UnableToLegalize;

  auto [Dst, DstTy, SrcVec, SrcVecTy, Val, ValTy, Idx, IdxTy] =
      MI.getFirst4RegLLTs();
  LLT VecTy = DstTy;

  LLT VecEltTy = VecTy.getElementType();
  LLT NewEltTy = CastTy.isVector() ? CastTy.getElementType() : CastTy;
  const unsigned NewEltSize = NewEltTy.getSizeInBits();
  const unsigned OldEltSize = VecEltTy.getSizeInBits();

  unsigned NewNumElts = CastTy.isVector() ? CastTy.getNumElements() : 1;
  unsigned OldNumElts = VecTy.getNumElements();

  Register CastVec = MIRBuilder.buildBitcast(CastTy, SrcVec).getReg(0);
  if (NewNumElts < OldNumElts) {
    if (NewEltSize % OldEltSize != 0)
      return UnableToLegalize;

    // This only depends on powers of 2 because we use bit tricks to figure out
    // the bit offset we need to shift to get the target element. A general
    // expansion could emit division/multiply.
    if (!isPowerOf2_32(NewEltSize / OldEltSize))
      return UnableToLegalize;

    const unsigned Log2EltRatio = Log2_32(NewEltSize / OldEltSize);
    auto Log2Ratio = MIRBuilder.buildConstant(IdxTy, Log2EltRatio);

    // Divide to get the index in the wider element type.
    auto ScaledIdx = MIRBuilder.buildLShr(IdxTy, Idx, Log2Ratio);

    Register ExtractedElt = CastVec;
    if (CastTy.isVector()) {
      ExtractedElt = MIRBuilder.buildExtractVectorElement(NewEltTy, CastVec,
                                                          ScaledIdx).getReg(0);
    }

    // Compute the bit offset into the register of the target element.
    Register OffsetBits = getBitcastWiderVectorElementOffset(
      MIRBuilder, Idx, NewEltSize, OldEltSize);

    Register InsertedElt = buildBitFieldInsert(MIRBuilder, ExtractedElt,
                                               Val, OffsetBits);
    if (CastTy.isVector()) {
      InsertedElt = MIRBuilder.buildInsertVectorElement(
        CastTy, CastVec, InsertedElt, ScaledIdx).getReg(0);
    }

    MIRBuilder.buildBitcast(Dst, InsertedElt);
    MI.eraseFromParent();
    return Legalized;
  }

  return UnableToLegalize;
}

// This attempts to handle G_CONCAT_VECTORS with illegal operands, particularly
// those that have smaller than legal operands.
//
// <16 x s8> = G_CONCAT_VECTORS <4 x s8>, <4 x s8>, <4 x s8>, <4 x s8>
//
// ===>
//
// s32 = G_BITCAST <4 x s8>
// s32 = G_BITCAST <4 x s8>
// s32 = G_BITCAST <4 x s8>
// s32 = G_BITCAST <4 x s8>
// <4 x s32> = G_BUILD_VECTOR s32, s32, s32, s32
// <16 x s8> = G_BITCAST <4 x s32>
LegalizerHelper::LegalizeResult
LegalizerHelper::bitcastConcatVector(MachineInstr &MI, unsigned TypeIdx,
                                     LLT CastTy) {
  // Convert it to CONCAT instruction
  auto ConcatMI = dyn_cast<GConcatVectors>(&MI);
  if (!ConcatMI) {
    return UnableToLegalize;
  }

  // Check if bitcast is Legal
  auto [DstReg, DstTy, SrcReg, SrcTy] = MI.getFirst2RegLLTs();
  LLT SrcScalTy = CastTy.getScalarType();

  // Check if the build vector is Legal
  if (!LI.isLegal({TargetOpcode::G_BUILD_VECTOR, {CastTy, SrcScalTy}})) {
    return UnableToLegalize;
  }

  // Bitcast the sources
  SmallVector<Register> BitcastRegs;
  for (unsigned i = 0; i < ConcatMI->getNumSources(); i++) {
    BitcastRegs.push_back(
        MIRBuilder.buildBitcast(SrcScalTy, ConcatMI->getSourceReg(i))
            .getReg(0));
  }

  // Build the scalar values into a vector
  Register BuildReg =
      MIRBuilder.buildBuildVector(CastTy, BitcastRegs).getReg(0);
  MIRBuilder.buildBitcast(DstReg, BuildReg);

  MI.eraseFromParent();
  return Legalized;
}

// This bitcasts a shuffle vector to a different type currently of the same
// element size. Mostly used to legalize ptr vectors, where ptrtoint/inttoptr
// will be used instead.
//
// <16 x p0> = G_CONCAT_VECTORS <4 x p0>, <4 x p0>, mask
// ===>
// <4 x s64> = G_PTRTOINT <4 x p0>
// <4 x s64> = G_PTRTOINT <4 x p0>
// <16 x s64> = G_CONCAT_VECTORS <4 x s64>, <4 x s64>, mask
// <16 x p0> = G_INTTOPTR <16 x s64>
LegalizerHelper::LegalizeResult
LegalizerHelper::bitcastShuffleVector(MachineInstr &MI, unsigned TypeIdx,
                                      LLT CastTy) {
  auto ShuffleMI = cast<GShuffleVector>(&MI);
  LLT DstTy = MRI.getType(ShuffleMI->getReg(0));
  LLT SrcTy = MRI.getType(ShuffleMI->getReg(1));

  // We currently only handle vectors of the same size.
  if (TypeIdx != 0 ||
      CastTy.getScalarSizeInBits() != DstTy.getScalarSizeInBits() ||
      CastTy.getElementCount() != DstTy.getElementCount())
    return UnableToLegalize;

  LLT NewSrcTy = SrcTy.changeElementType(CastTy.getScalarType());

  auto Inp1 = MIRBuilder.buildCast(NewSrcTy, ShuffleMI->getReg(1));
  auto Inp2 = MIRBuilder.buildCast(NewSrcTy, ShuffleMI->getReg(2));
  auto Shuf =
      MIRBuilder.buildShuffleVector(CastTy, Inp1, Inp2, ShuffleMI->getMask());
  MIRBuilder.buildCast(ShuffleMI->getReg(0), Shuf);

  MI.eraseFromParent();
  return Legalized;
}

/// This attempts to bitcast G_EXTRACT_SUBVECTOR to CastTy.
///
///  <vscale x 8 x i1> = G_EXTRACT_SUBVECTOR <vscale x 16 x i1>, N
///
/// ===>
///
///  <vscale x 2 x i1> = G_BITCAST <vscale x 16 x i1>
///  <vscale x 1 x i8> = G_EXTRACT_SUBVECTOR <vscale x 2 x i1>, N / 8
///  <vscale x 8 x i1> = G_BITCAST <vscale x 1 x i8>
LegalizerHelper::LegalizeResult
LegalizerHelper::bitcastExtractSubvector(MachineInstr &MI, unsigned TypeIdx,
                                         LLT CastTy) {
  auto ES = cast<GExtractSubvector>(&MI);

  if (!CastTy.isVector())
    return UnableToLegalize;

  if (TypeIdx != 0)
    return UnableToLegalize;

  Register Dst = ES->getReg(0);
  Register Src = ES->getSrcVec();
  uint64_t Idx = ES->getIndexImm();

  MachineRegisterInfo &MRI = *MIRBuilder.getMRI();

  LLT DstTy = MRI.getType(Dst);
  LLT SrcTy = MRI.getType(Src);
  ElementCount DstTyEC = DstTy.getElementCount();
  ElementCount SrcTyEC = SrcTy.getElementCount();
  auto DstTyMinElts = DstTyEC.getKnownMinValue();
  auto SrcTyMinElts = SrcTyEC.getKnownMinValue();

  if (DstTy == CastTy)
    return Legalized;

  if (DstTy.getSizeInBits() != CastTy.getSizeInBits())
    return UnableToLegalize;

  unsigned CastEltSize = CastTy.getElementType().getSizeInBits();
  unsigned DstEltSize = DstTy.getElementType().getSizeInBits();
  if (CastEltSize < DstEltSize)
    return UnableToLegalize;

  auto AdjustAmt = CastEltSize / DstEltSize;
  if (Idx % AdjustAmt != 0 || DstTyMinElts % AdjustAmt != 0 ||
      SrcTyMinElts % AdjustAmt != 0)
    return UnableToLegalize;

  Idx /= AdjustAmt;
  SrcTy = LLT::vector(SrcTyEC.divideCoefficientBy(AdjustAmt), AdjustAmt);
  auto CastVec = MIRBuilder.buildBitcast(SrcTy, Src);
  auto PromotedES = MIRBuilder.buildExtractSubvector(CastTy, CastVec, Idx);
  MIRBuilder.buildBitcast(Dst, PromotedES);

  ES->eraseFromParent();
  return Legalized;
}

/// This attempts to bitcast G_INSERT_SUBVECTOR to CastTy.
///
///  <vscale x 16 x i1> = G_INSERT_SUBVECTOR <vscale x 16 x i1>,
///                                          <vscale x 8 x i1>,
///                                          N
///
/// ===>
///
///  <vscale x 2 x i8> = G_BITCAST <vscale x 16 x i1>
///  <vscale x 1 x i8> = G_BITCAST <vscale x 8 x i1>
///  <vscale x 2 x i8> = G_INSERT_SUBVECTOR <vscale x 2 x i8>,
///                                         <vscale x 1 x i8>, N / 8
///  <vscale x 16 x i1> = G_BITCAST <vscale x 2 x i8>
LegalizerHelper::LegalizeResult
LegalizerHelper::bitcastInsertSubvector(MachineInstr &MI, unsigned TypeIdx,
                                        LLT CastTy) {
  auto ES = cast<GInsertSubvector>(&MI);

  if (!CastTy.isVector())
    return UnableToLegalize;

  if (TypeIdx != 0)
    return UnableToLegalize;

  Register Dst = ES->getReg(0);
  Register BigVec = ES->getBigVec();
  Register SubVec = ES->getSubVec();
  uint64_t Idx = ES->getIndexImm();

  MachineRegisterInfo &MRI = *MIRBuilder.getMRI();

  LLT DstTy = MRI.getType(Dst);
  LLT BigVecTy = MRI.getType(BigVec);
  LLT SubVecTy = MRI.getType(SubVec);

  if (DstTy == CastTy)
    return Legalized;

  if (DstTy.getSizeInBits() != CastTy.getSizeInBits())
    return UnableToLegalize;

  ElementCount DstTyEC = DstTy.getElementCount();
  ElementCount BigVecTyEC = BigVecTy.getElementCount();
  ElementCount SubVecTyEC = SubVecTy.getElementCount();
  auto DstTyMinElts = DstTyEC.getKnownMinValue();
  auto BigVecTyMinElts = BigVecTyEC.getKnownMinValue();
  auto SubVecTyMinElts = SubVecTyEC.getKnownMinValue();

  unsigned CastEltSize = CastTy.getElementType().getSizeInBits();
  unsigned DstEltSize = DstTy.getElementType().getSizeInBits();
  if (CastEltSize < DstEltSize)
    return UnableToLegalize;

  auto AdjustAmt = CastEltSize / DstEltSize;
  if (Idx % AdjustAmt != 0 || DstTyMinElts % AdjustAmt != 0 ||
      BigVecTyMinElts % AdjustAmt != 0 || SubVecTyMinElts % AdjustAmt != 0)
    return UnableToLegalize;

  Idx /= AdjustAmt;
  BigVecTy = LLT::vector(BigVecTyEC.divideCoefficientBy(AdjustAmt), AdjustAmt);
  SubVecTy = LLT::vector(SubVecTyEC.divideCoefficientBy(AdjustAmt), AdjustAmt);
  auto CastBigVec = MIRBuilder.buildBitcast(BigVecTy, BigVec);
  auto CastSubVec = MIRBuilder.buildBitcast(SubVecTy, SubVec);
  auto PromotedIS =
      MIRBuilder.buildInsertSubvector(CastTy, CastBigVec, CastSubVec, Idx);
  MIRBuilder.buildBitcast(Dst, PromotedIS);

  ES->eraseFromParent();
  return Legalized;
}

LegalizerHelper::LegalizeResult LegalizerHelper::lowerLoad(GAnyLoad &LoadMI) {
  // Lower to a memory-width G_LOAD and a G_SEXT/G_ZEXT/G_ANYEXT
  Register DstReg = LoadMI.getDstReg();
  Register PtrReg = LoadMI.getPointerReg();
  LLT DstTy = MRI.getType(DstReg);
  MachineMemOperand &MMO = LoadMI.getMMO();
  LLT MemTy = MMO.getMemoryType();
  MachineFunction &MF = MIRBuilder.getMF();

  LLT EltTy = MemTy.getScalarType();

  unsigned MemSizeInBits = MemTy.getSizeInBits();
  unsigned MemStoreSizeInBits = 8 * MemTy.getSizeInBytes();

  if (MemSizeInBits != MemStoreSizeInBits) {
    if (MemTy.isVector())
      return UnableToLegalize;

    // Promote to a byte-sized load if not loading an integral number of
    // bytes.  For example, promote EXTLOAD:i20 -> EXTLOAD:i24.
    LLT WideMemTy = EltTy.changeElementSize(MemStoreSizeInBits);
    MachineMemOperand *NewMMO =
        MF.getMachineMemOperand(&MMO, MMO.getPointerInfo(), WideMemTy);

    Register LoadReg = DstReg;
    LLT LoadTy = DstTy;

    // If this wasn't already an extending load, we need to widen the result
    // register to avoid creating a load with a narrower result than the source.
    if (MemStoreSizeInBits > DstTy.getSizeInBits()) {
      LoadTy = WideMemTy;
      LoadReg = MRI.createGenericVirtualRegister(WideMemTy);
    }

    if (isa<GSExtLoad>(LoadMI)) {
      auto NewLoad = MIRBuilder.buildLoad(LoadTy, PtrReg, *NewMMO);
      MIRBuilder.buildSExtInReg(LoadReg, NewLoad, MemSizeInBits);
    } else if (isa<GZExtLoad>(LoadMI) || WideMemTy == LoadTy) {
      auto NewLoad = MIRBuilder.buildLoad(LoadTy, PtrReg, *NewMMO);
      // The extra bits are guaranteed to be zero, since we stored them that
      // way.  A zext load from Wide thus automatically gives zext from MemVT.
      MIRBuilder.buildAssertZExt(LoadReg, NewLoad, MemSizeInBits);
    } else {
      MIRBuilder.buildLoad(LoadReg, PtrReg, *NewMMO);
    }

    if (DstTy != LoadTy)
      MIRBuilder.buildTrunc(DstReg, LoadReg);

    LoadMI.eraseFromParent();
    return Legalized;
  }

  // Big endian lowering not implemented.
  if (MIRBuilder.getDataLayout().isBigEndian())
    return UnableToLegalize;

  // This load needs splitting into power of 2 sized loads.
  //
  // Our strategy here is to generate anyextending loads for the smaller
  // types up to next power-2 result type, and then combine the two larger
  // result values together, before truncating back down to the non-pow-2
  // type.
  // E.g. v1 = i24 load =>
  // v2 = i32 zextload (2 byte)
  // v3 = i32 load (1 byte)
  // v4 = i32 shl v3, 16
  // v5 = i32 or v4, v2
  // v1 = i24 trunc v5
  // By doing this we generate the correct truncate which should get
  // combined away as an artifact with a matching extend.

  uint64_t LargeSplitSize, SmallSplitSize;

  if (!isPowerOf2_32(MemSizeInBits)) {
    // This load needs splitting into power of 2 sized loads.
    LargeSplitSize = llvm::bit_floor(MemSizeInBits);
    SmallSplitSize = MemSizeInBits - LargeSplitSize;
  } else {
    // This is already a power of 2, but we still need to split this in half.
    //
    // Assume we're being asked to decompose an unaligned load.
    // TODO: If this requires multiple splits, handle them all at once.
    auto &Ctx = MF.getFunction().getContext();
    if (TLI.allowsMemoryAccess(Ctx, MIRBuilder.getDataLayout(), MemTy, MMO))
      return UnableToLegalize;

    SmallSplitSize = LargeSplitSize = MemSizeInBits / 2;
  }

  if (MemTy.isVector()) {
    // TODO: Handle vector extloads
    if (MemTy != DstTy)
      return UnableToLegalize;

    Align Alignment = LoadMI.getAlign();
    // Given an alignment larger than the size of the memory, we can increase
    // the size of the load without needing to scalarize it.
    if (Alignment.value() * 8 > MemSizeInBits &&
        isPowerOf2_64(DstTy.getScalarSizeInBits())) {
      LLT MoreTy = DstTy.changeVectorElementCount(
          ElementCount::getFixed(NextPowerOf2(DstTy.getNumElements())));
      MachineMemOperand *NewMMO = MF.getMachineMemOperand(&MMO, 0, MoreTy);
      auto NewLoad = MIRBuilder.buildLoad(MoreTy, PtrReg, *NewMMO);
      MIRBuilder.buildDeleteTrailingVectorElements(LoadMI.getReg(0),
                                                   NewLoad.getReg(0));
      LoadMI.eraseFromParent();
      return Legalized;
    }

    // TODO: We can do better than scalarizing the vector and at least split it
    // in half.
    return reduceLoadStoreWidth(LoadMI, 0, DstTy.getElementType());
  }

  MachineMemOperand *LargeMMO =
      MF.getMachineMemOperand(&MMO, 0, LargeSplitSize / 8);
  MachineMemOperand *SmallMMO =
      MF.getMachineMemOperand(&MMO, LargeSplitSize / 8, SmallSplitSize / 8);

  LLT PtrTy = MRI.getType(PtrReg);
  unsigned AnyExtSize = PowerOf2Ceil(DstTy.getSizeInBits());

  LLT AnyExtTy;
  LLT OffsetCstRes;
  if (EltTy.isPointer()) {
    AnyExtTy = LLT::scalar(AnyExtSize);
    OffsetCstRes = LLT::scalar(PtrTy.getSizeInBits());
  } else {
    AnyExtTy = DstTy.changeElementSize(AnyExtSize);
    OffsetCstRes = DstTy.changeElementSize(PtrTy.getSizeInBits());
  }

  auto LargeLoad = MIRBuilder.buildLoadInstr(TargetOpcode::G_ZEXTLOAD, AnyExtTy,
                                             PtrReg, *LargeMMO);

  auto OffsetCst = MIRBuilder.buildConstant(OffsetCstRes, LargeSplitSize / 8);
  Register PtrAddReg = MRI.createGenericVirtualRegister(PtrTy);
  auto SmallPtr = MIRBuilder.buildObjectPtrOffset(PtrAddReg, PtrReg, OffsetCst);
  auto SmallLoad = MIRBuilder.buildLoadInstr(LoadMI.getOpcode(), AnyExtTy,
                                             SmallPtr, *SmallMMO);

  auto ShiftAmt = MIRBuilder.buildConstant(AnyExtTy, LargeSplitSize);
  auto Shift = MIRBuilder.buildShl(AnyExtTy, SmallLoad, ShiftAmt);

  if (AnyExtTy == DstTy)
    MIRBuilder.buildOr(DstReg, Shift, LargeLoad);
  else if (AnyExtTy.getSizeInBits() != DstTy.getSizeInBits()) {
    auto Or = MIRBuilder.buildOr(AnyExtTy, Shift, LargeLoad);
    MIRBuilder.buildTrunc(DstReg, {Or});
  } else {
    assert(DstTy.isPointer() && "expected pointer");
    auto Or = MIRBuilder.buildOr(AnyExtTy, Shift, LargeLoad);

    // FIXME: We currently consider this to be illegal for non-integral address
    // spaces, but we need still need a way to reinterpret the bits.
    MIRBuilder.buildIntToPtr(DstReg, Or);
  }

  LoadMI.eraseFromParent();
  return Legalized;
}

LegalizerHelper::LegalizeResult LegalizerHelper::lowerStore(GStore &StoreMI) {
  // Lower a non-power of 2 store into multiple pow-2 stores.
  // E.g. split an i24 store into an i16 store + i8 store.
  // We do this by first extending the stored value to the next largest power
  // of 2 type, and then using truncating stores to store the components.
  // By doing this, likewise with G_LOAD, generate an extend that can be
  // artifact-combined away instead of leaving behind extracts.
  Register SrcReg = StoreMI.getValueReg();
  Register PtrReg = StoreMI.getPointerReg();
  LLT SrcTy = MRI.getType(SrcReg);
  MachineFunction &MF = MIRBuilder.getMF();
  MachineMemOperand &MMO = **StoreMI.memoperands_begin();
  LLT MemTy = MMO.getMemoryType();

  unsigned StoreWidth = MemTy.getSizeInBits();
  unsigned StoreSizeInBits = 8 * MemTy.getSizeInBytes();

  if (StoreWidth != StoreSizeInBits && !SrcTy.isVector()) {
    // Promote to a byte-sized store with upper bits zero if not
    // storing an integral number of bytes.  For example, promote
    // TRUNCSTORE:i1 X -> TRUNCSTORE:i8 (and X, 1)
    LLT WideTy = LLT::integer(StoreSizeInBits);

    if (StoreSizeInBits > SrcTy.getSizeInBits()) {
      // Avoid creating a store with a narrower source than result.
      SrcReg = MIRBuilder.buildAnyExt(WideTy, SrcReg).getReg(0);
      SrcTy = WideTy;
    }

    auto ZextInReg = MIRBuilder.buildZExtInReg(SrcTy, SrcReg, StoreWidth);

    MachineMemOperand *NewMMO =
        MF.getMachineMemOperand(&MMO, MMO.getPointerInfo(), WideTy);
    MIRBuilder.buildStore(ZextInReg, PtrReg, *NewMMO);
    StoreMI.eraseFromParent();
    return Legalized;
  }

  if (MemTy.isVector()) {
    if (MemTy != SrcTy)
      return scalarizeVectorBooleanStore(StoreMI);

    // TODO: We can do better than scalarizing the vector and at least split it
    // in half.
    return reduceLoadStoreWidth(StoreMI, 0, SrcTy.getElementType());
  }

  unsigned MemSizeInBits = MemTy.getSizeInBits();
  uint64_t LargeSplitSize, SmallSplitSize;

  if (!isPowerOf2_32(MemSizeInBits)) {
    LargeSplitSize = llvm::bit_floor<uint64_t>(MemTy.getSizeInBits());
    SmallSplitSize = MemTy.getSizeInBits() - LargeSplitSize;
  } else {
    auto &Ctx = MF.getFunction().getContext();
    if (TLI.allowsMemoryAccess(Ctx, MIRBuilder.getDataLayout(), MemTy, MMO))
      return UnableToLegalize; // Don't know what we're being asked to do.

    SmallSplitSize = LargeSplitSize = MemSizeInBits / 2;
  }

  // Extend to the next pow-2. If this store was itself the result of lowering,
  // e.g. an s56 store being broken into s32 + s24, we might have a stored type
  // that's wider than the stored size.
  unsigned AnyExtSize = PowerOf2Ceil(MemTy.getSizeInBits());
  const LLT NewSrcTy = LLT::integer(AnyExtSize);

  if (SrcTy.isPointer()) {
    const LLT IntPtrTy = LLT::integer(SrcTy.getSizeInBits());
    SrcReg = MIRBuilder.buildPtrToInt(IntPtrTy, SrcReg).getReg(0);
  }

  auto ExtVal = MIRBuilder.buildAnyExtOrTrunc(NewSrcTy, SrcReg);

  // Obtain the smaller value by shifting away the larger value.
  auto ShiftAmt = MIRBuilder.buildConstant(NewSrcTy, LargeSplitSize);
  auto SmallVal = MIRBuilder.buildLShr(NewSrcTy, ExtVal, ShiftAmt);

  // Generate the PtrAdd and truncating stores.
  LLT PtrTy = MRI.getType(PtrReg);
  auto OffsetCst = MIRBuilder.buildConstant(LLT::integer(PtrTy.getSizeInBits()),
                                            LargeSplitSize / 8);
  auto SmallPtr = MIRBuilder.buildObjectPtrOffset(PtrTy, PtrReg, OffsetCst);

  MachineMemOperand *LargeMMO =
    MF.getMachineMemOperand(&MMO, 0, LargeSplitSize / 8);
  MachineMemOperand *SmallMMO =
    MF.getMachineMemOperand(&MMO, LargeSplitSize / 8, SmallSplitSize / 8);
  MIRBuilder.buildStore(ExtVal, PtrReg, *LargeMMO);
  MIRBuilder.buildStore(SmallVal, SmallPtr, *SmallMMO);
  StoreMI.eraseFromParent();
  return Legalized;
}

LegalizerHelper::LegalizeResult
LegalizerHelper::scalarizeVectorBooleanStore(GStore &StoreMI) {
  Register SrcReg = StoreMI.getValueReg();
  Register PtrReg = StoreMI.getPointerReg();
  LLT SrcTy = MRI.getType(SrcReg);
  MachineMemOperand &MMO = **StoreMI.memoperands_begin();
  LLT MemTy = MMO.getMemoryType();
  LLT MemScalarTy = MemTy.getElementType();
  MachineFunction &MF = MIRBuilder.getMF();

  assert(SrcTy.isVector() && "Expect a vector store type");

  if (!MemScalarTy.isByteSized()) {
    // We need to build an integer scalar of the vector bit pattern.
    // It's not legal for us to add padding when storing a vector.
    unsigned NumBits = MemTy.getSizeInBits();
    LLT IntTy = LLT::integer(NumBits);
    auto CurrVal = MIRBuilder.buildConstant(IntTy, 0);
    LLT IdxTy = TLI.getVectorIdxLLT(MF.getDataLayout());

    for (unsigned I = 0, E = MemTy.getNumElements(); I < E; ++I) {
      auto Elt = MIRBuilder.buildExtractVectorElement(
          SrcTy.getElementType(), SrcReg, MIRBuilder.buildConstant(IdxTy, I));
      auto Trunc = MIRBuilder.buildTrunc(MemScalarTy, Elt);
      auto ZExt = MIRBuilder.buildZExt(IntTy, Trunc);
      unsigned ShiftIntoIdx = MF.getDataLayout().isBigEndian()
                                  ? (MemTy.getNumElements() - 1) - I
                                  : I;
      auto ShiftAmt = MIRBuilder.buildConstant(
          IntTy, ShiftIntoIdx * MemScalarTy.getSizeInBits());
      auto Shifted = MIRBuilder.buildShl(IntTy, ZExt, ShiftAmt);
      CurrVal = MIRBuilder.buildOr(IntTy, CurrVal, Shifted);
    }
    auto PtrInfo = MMO.getPointerInfo();
    auto *NewMMO = MF.getMachineMemOperand(&MMO, PtrInfo, IntTy);
    MIRBuilder.buildStore(CurrVal, PtrReg, *NewMMO);
    StoreMI.eraseFromParent();
    return Legalized;
  }

  // TODO: implement simple scalarization.
  return UnableToLegalize;
}

LegalizerHelper::LegalizeResult
LegalizerHelper::bitcast(MachineInstr &MI, unsigned TypeIdx, LLT CastTy) {
  switch (MI.getOpcode()) {
  case TargetOpcode::G_LOAD: {
    if (TypeIdx != 0)
      return UnableToLegalize;
    MachineMemOperand &MMO = **MI.memoperands_begin();

    // Not sure how to interpret a bitcast of an extending load.
    if (MMO.getMemoryType().getSizeInBits() != CastTy.getSizeInBits())
      return UnableToLegalize;

    Observer.changingInstr(MI);
    bitcastDst(MI, CastTy, 0);
    MMO.setType(CastTy);
    // The range metadata is no longer valid when reinterpreted as a different
    // type.
    MMO.clearRanges();
    Observer.changedInstr(MI);
    return Legalized;
  }
  case TargetOpcode::G_STORE: {
    if (TypeIdx != 0)
      return UnableToLegalize;

    MachineMemOperand &MMO = **MI.memoperands_begin();

    // Not sure how to interpret a bitcast of a truncating store.
    if (MMO.getMemoryType().getSizeInBits() != CastTy.getSizeInBits())
      return UnableToLegalize;

    Observer.changingInstr(MI);
    bitcastSrc(MI, CastTy, 0);
    MMO.setType(CastTy);
    Observer.changedInstr(MI);
    return Legalized;
  }
  case TargetOpcode::G_SELECT: {
    if (TypeIdx != 0)
      return UnableToLegalize;

    if (MRI.getType(MI.getOperand(1).getReg()).isVector()) {
      LLVM_DEBUG(
          dbgs() << "bitcast action not implemented for vector select\n");
      return UnableToLegalize;
    }

    Observer.changingInstr(MI);
    bitcastSrc(MI, CastTy, 2);
    bitcastSrc(MI, CastTy, 3);
    bitcastDst(MI, CastTy, 0);
    Observer.changedInstr(MI);
    return Legalized;
  }
  case TargetOpcode::G_AND:
  case TargetOpcode::G_OR:
  case TargetOpcode::G_XOR: {
    Observer.changingInstr(MI);
    bitcastSrc(MI, CastTy, 1);
    bitcastSrc(MI, CastTy, 2);
    bitcastDst(MI, CastTy, 0);
    Observer.changedInstr(MI);
    return Legalized;
  }
  case TargetOpcode::G_EXTRACT_VECTOR_ELT:
    return bitcastExtractVectorElt(MI, TypeIdx, CastTy);
  case TargetOpcode::G_INSERT_VECTOR_ELT:
    return bitcastInsertVectorElt(MI, TypeIdx, CastTy);
  case TargetOpcode::G_CONCAT_VECTORS:
    return bitcastConcatVector(MI, TypeIdx, CastTy);
  case TargetOpcode::G_SHUFFLE_VECTOR:
    return bitcastShuffleVector(MI, TypeIdx, CastTy);
  case TargetOpcode::G_EXTRACT_SUBVECTOR:
    return bitcastExtractSubvector(MI, TypeIdx, CastTy);
  case TargetOpcode::G_INSERT_SUBVECTOR:
    return bitcastInsertSubvector(MI, TypeIdx, CastTy);
  default:
    return UnableToLegalize;
  }
}

// Legalize an instruction by changing the opcode in place.
void LegalizerHelper::changeOpcode(MachineInstr &MI, unsigned NewOpcode) {
    Observer.changingInstr(MI);
    MI.setDesc(MIRBuilder.getTII().get(NewOpcode));
    Observer.changedInstr(MI);
}

LegalizerHelper::LegalizeResult
LegalizerHelper::lower(MachineInstr &MI, unsigned TypeIdx, LLT LowerHintTy) {
  using namespace TargetOpcode;
  switch(MI.getOpcode()) {
  default:
    return UnableToLegalize;
  case TargetOpcode::G_FCONSTANT:
    return lowerFConstant(MI);
  case TargetOpcode::G_BITCAST:
    return lowerBitcast(MI);
  case TargetOpcode::G_SREM:
  case TargetOpcode::G_UREM: {
    LLT Ty = MRI.getType(MI.getOperand(0).getReg());
    auto Quot =
        MIRBuilder.buildInstr(MI.getOpcode() == G_SREM ? G_SDIV : G_UDIV, {Ty},
                              {MI.getOperand(1), MI.getOperand(2)});

    auto Prod = MIRBuilder.buildMul(Ty, Quot, MI.getOperand(2));
    MIRBuilder.buildSub(MI.getOperand(0), MI.getOperand(1), Prod);
    MI.eraseFromParent();
    return Legalized;
  }
  case TargetOpcode::G_SADDO:
  case TargetOpcode::G_SSUBO:
    return lowerSADDO_SSUBO(MI);
  case TargetOpcode::G_SADDE:
    return lowerSADDE(MI);
  case TargetOpcode::G_SSUBE:
    return lowerSSUBE(MI);
  case TargetOpcode::G_UMULH:
  case TargetOpcode::G_SMULH:
    return lowerSMULH_UMULH(MI);
  case TargetOpcode::G_SMULO:
  case TargetOpcode::G_UMULO: {
    // Generate G_UMULH/G_SMULH to check for overflow and a normal G_MUL for the
    // result.
    auto [Res, Overflow, LHS, RHS] = MI.getFirst4Regs();
    LLT Ty = MRI.getType(Res);

    unsigned Opcode = MI.getOpcode() == TargetOpcode::G_SMULO
                          ? TargetOpcode::G_SMULH
                          : TargetOpcode::G_UMULH;

    Observer.changingInstr(MI);
    const auto &TII = MIRBuilder.getTII();
    MI.setDesc(TII.get(TargetOpcode::G_MUL));
    MI.removeOperand(1);
    Observer.changedInstr(MI);

    auto HiPart = MIRBuilder.buildInstr(Opcode, {Ty}, {LHS, RHS});
    auto Zero = MIRBuilder.buildConstant(Ty, 0);

    // Move insert point forward so we can use the Res register if needed.
    MIRBuilder.setInsertPt(MIRBuilder.getMBB(), ++MIRBuilder.getInsertPt());

    // For *signed* multiply, overflow is detected by checking:
    // (hi != (lo >> bitwidth-1))
    if (Opcode == TargetOpcode::G_SMULH) {
      auto ShiftAmt = MIRBuilder.buildConstant(Ty, Ty.getSizeInBits() - 1);
      auto Shifted = MIRBuilder.buildAShr(Ty, Res, ShiftAmt);
      MIRBuilder.buildICmp(CmpInst::ICMP_NE, Overflow, HiPart, Shifted);
    } else {
      MIRBuilder.buildICmp(CmpInst::ICMP_NE, Overflow, HiPart, Zero);
    }
    return Legalized;
  }
  case TargetOpcode::G_FNEG: {
    auto [Res, ResTy, SubByReg, SubByRegTy] = MI.getFirst2RegLLTs();
    LLT TyInt =
        ResTy.changeElementType(LLT::integer(ResTy.getScalarSizeInBits()));
    Register CastedSubByReg = SubByReg;

    if (!SubByRegTy.getScalarType().isAnyScalar() &&
        !SubByRegTy.getScalarType().isInteger()) {
      auto BitcastDst = SubByRegTy.changeElementType(
          LLT::integer(SubByRegTy.getScalarSizeInBits()));
      CastedSubByReg = MIRBuilder.buildBitcast(BitcastDst, SubByReg).getReg(0);
    }

    auto SignMask = MIRBuilder.buildConstant(
        TyInt, APInt::getSignMask(TyInt.getScalarSizeInBits()));

    if (ResTy != TyInt) {
      Register NewDst =
          MIRBuilder.buildXor(TyInt, CastedSubByReg, SignMask).getReg(0);
      MIRBuilder.buildBitcast(Res, NewDst);
    } else
      MIRBuilder.buildXor(Res, CastedSubByReg, SignMask).getReg(0);

    MI.eraseFromParent();
    return Legalized;
  }
  case TargetOpcode::G_FSUB:
  case TargetOpcode::G_STRICT_FSUB: {
    auto [Res, LHS, RHS] = MI.getFirst3Regs();
    LLT Ty = MRI.getType(Res);

    // Lower (G_FSUB LHS, RHS) to (G_FADD LHS, (G_FNEG RHS)).
    auto Neg = MIRBuilder.buildFNeg(Ty, RHS);

    if (MI.getOpcode() == TargetOpcode::G_STRICT_FSUB)
      MIRBuilder.buildStrictFAdd(Res, LHS, Neg, MI.getFlags());
    else
      MIRBuilder.buildFAdd(Res, LHS, Neg, MI.getFlags());

    MI.eraseFromParent();
    return Legalized;
  }
  case TargetOpcode::G_FMAD:
    return lowerFMad(MI);
  case TargetOpcode::G_FFLOOR:
    return lowerFFloor(MI);
  case TargetOpcode::G_LROUND:
  case TargetOpcode::G_LLROUND: {
    Register DstReg = MI.getOperand(0).getReg();
    Register SrcReg = MI.getOperand(1).getReg();
    LLT SrcTy = MRI.getType(SrcReg);
    auto Round = MIRBuilder.buildInstr(TargetOpcode::G_INTRINSIC_ROUND, {SrcTy},
                                       {SrcReg});
    MIRBuilder.buildFPTOSI(DstReg, Round);
    MI.eraseFromParent();
    return Legalized;
  }
  case TargetOpcode::G_INTRINSIC_ROUND:
    return lowerIntrinsicRound(MI);
  case TargetOpcode::G_FRINT: {
    // Since round even is the assumed rounding mode for unconstrained FP
    // operations, rint and roundeven are the same operation.
    changeOpcode(MI, TargetOpcode::G_INTRINSIC_ROUNDEVEN);
    return Legalized;
  }
  case TargetOpcode::G_INTRINSIC_LRINT:
  case TargetOpcode::G_INTRINSIC_LLRINT: {
    Register DstReg = MI.getOperand(0).getReg();
    Register SrcReg = MI.getOperand(1).getReg();
    LLT SrcTy = MRI.getType(SrcReg);
    auto Round =
        MIRBuilder.buildInstr(TargetOpcode::G_FRINT, {SrcTy}, {SrcReg});
    MIRBuilder.buildFPTOSI(DstReg, Round);
    MI.eraseFromParent();
    return Legalized;
  }
  case TargetOpcode::G_ATOMIC_CMPXCHG_WITH_SUCCESS: {
    auto [OldValRes, SuccessRes, Addr, CmpVal, NewVal] = MI.getFirst5Regs();
    Register NewOldValRes = MRI.cloneVirtualRegister(OldValRes);
    MIRBuilder.buildAtomicCmpXchg(NewOldValRes, Addr, CmpVal, NewVal,
                                  **MI.memoperands_begin());
    MIRBuilder.buildICmp(CmpInst::ICMP_EQ, SuccessRes, NewOldValRes, CmpVal);
    MIRBuilder.buildCopy(OldValRes, NewOldValRes);
    MI.eraseFromParent();
    return Legalized;
  }
  case TargetOpcode::G_LOAD:
  case TargetOpcode::G_SEXTLOAD:
  case TargetOpcode::G_ZEXTLOAD:
    return lowerLoad(cast<GAnyLoad>(MI));
  case TargetOpcode::G_STORE:
    return lowerStore(cast<GStore>(MI));
  case TargetOpcode::G_CTLZ_ZERO_POISON:
  case TargetOpcode::G_CTTZ_ZERO_POISON:
  case TargetOpcode::G_CTLZ:
  case TargetOpcode::G_CTTZ:
  case TargetOpcode::G_CTPOP:
  case TargetOpcode::G_CTLS:
    return lowerBitCount(MI);
  case G_UADDO: {
    auto [Res, CarryOut, LHS, RHS] = MI.getFirst4Regs();

    Register NewRes = MRI.cloneVirtualRegister(Res);

    MIRBuilder.buildAdd(NewRes, LHS, RHS);
    MIRBuilder.buildICmp(CmpInst::ICMP_ULT, CarryOut, NewRes, RHS);

    MIRBuilder.buildCopy(Res, NewRes);

    MI.eraseFromParent();
    return Legalized;
  }
  case G_UADDE: {
    auto [Res, CarryOut, LHS, RHS, CarryIn] = MI.getFirst5Regs();
    const LLT CondTy = MRI.getType(CarryOut);
    const LLT Ty = MRI.getType(Res);

    Register NewRes = MRI.cloneVirtualRegister(Res);

    // Initial add of the two operands.
    auto TmpRes = MIRBuilder.buildAdd(Ty, LHS, RHS);

    // Initial check for carry.
    auto Carry = MIRBuilder.buildICmp(CmpInst::ICMP_ULT, CondTy, TmpRes, LHS);

    // Add the sum and the carry.
    auto ZExtCarryIn = MIRBuilder.buildZExt(Ty, CarryIn);
    MIRBuilder.buildAdd(NewRes, TmpRes, ZExtCarryIn);

    // Second check for carry. We can only carry if the initial sum is all 1s
    // and the carry is set, resulting in a new sum of 0.
    auto Zero = MIRBuilder.buildConstant(Ty, 0);
    auto ResEqZero =
        MIRBuilder.buildICmp(CmpInst::ICMP_EQ, CondTy, NewRes, Zero);
    auto Carry2 = MIRBuilder.buildAnd(CondTy, ResEqZero, CarryIn);
    MIRBuilder.buildOr(CarryOut, Carry, Carry2);

    MIRBuilder.buildCopy(Res, NewRes);

    MI.eraseFromParent();
    return Legalized;
  }
  case G_USUBO: {
    auto [Res, BorrowOut, LHS, RHS] = MI.getFirst4Regs();

    MIRBuilder.buildSub(Res, LHS, RHS);
    MIRBuilder.buildICmp(CmpInst::ICMP_ULT, BorrowOut, LHS, RHS);

    MI.eraseFromParent();
    return Legalized;
  }
  case G_USUBE: {
    auto [Res, BorrowOut, LHS, RHS, BorrowIn] = MI.getFirst5Regs();
    const LLT CondTy = MRI.getType(BorrowOut);
    const LLT Ty = MRI.getType(Res);

    // Initial subtract of the two operands.
    auto TmpRes = MIRBuilder.buildSub(Ty, LHS, RHS);

    // Initial check for borrow.
    auto Borrow = MIRBuilder.buildICmp(CmpInst::ICMP_UGT, CondTy, TmpRes, LHS);

    // Subtract the borrow from the first subtract.
    auto ZExtBorrowIn = MIRBuilder.buildZExt(Ty, BorrowIn);
    MIRBuilder.buildSub(Res, TmpRes, ZExtBorrowIn);

    // Second check for borrow. We can only borrow if the initial difference is
    // 0 and the borrow is set, resulting in a new difference of all 1s.
    auto Zero = MIRBuilder.buildConstant(Ty, 0);
    auto TmpResEqZero =
        MIRBuilder.buildICmp(CmpInst::ICMP_EQ, CondTy, TmpRes, Zero);
    auto Borrow2 = MIRBuilder.buildAnd(CondTy, TmpResEqZero, BorrowIn);
    MIRBuilder.buildOr(BorrowOut, Borrow, Borrow2);

    MI.eraseFromParent();
    return Legalized;
  }
  case G_UITOFP:
    return lowerUITOFP(MI);
  case G_SITOFP:
    return lowerSITOFP(MI);
  case G_FPTOUI:
    return lowerFPTOUI(MI);
  case G_FPTOSI:
    return lowerFPTOSI(MI);
  case G_FPTOUI_SAT:
  case G_FPTOSI_SAT:
    return lowerFPTOINT_SAT(MI);
  case G_FPEXT:
    return lowerFPExtAndTruncMem(MI);
  case G_FPTRUNC:
    return lowerFPTRUNC(MI);
  case G_FPOWI:
    return lowerFPOWI(MI);
  case G_FMODF:
    return lowerFMODF(MI);
  case G_SMIN:
  case G_SMAX:
  case G_UMIN:
  case G_UMAX:
    return lowerMinMax(MI);
  case G_SCMP:
  case G_UCMP:
    return lowerThreewayCompare(MI);
  case G_FCOPYSIGN:
    return lowerFCopySign(MI);
  case G_FMINNUM:
  case G_FMAXNUM:
  case G_FMINIMUMNUM:
  case G_FMAXIMUMNUM:
    return lowerFMinNumMaxNum(MI);
  case G_FMINIMUM:
  case G_FMAXIMUM:
    return lowerFMinimumMaximum(MI);
  case G_MERGE_VALUES:
    return lowerMergeValues(MI);
  case G_UNMERGE_VALUES:
    return lowerUnmergeValues(MI);
  case TargetOpcode::G_SEXT_INREG: {
    assert(MI.getOperand(2).isImm() && "Expected immediate");
    int64_t SizeInBits = MI.getOperand(2).getImm();

    auto [DstReg, SrcReg] = MI.getFirst2Regs();
    LLT DstTy = MRI.getType(DstReg);
    Register TmpRes = MRI.createGenericVirtualRegister(DstTy);

    auto MIBSz = MIRBuilder.buildConstant(DstTy, DstTy.getScalarSizeInBits() - SizeInBits);
    MIRBuilder.buildShl(TmpRes, SrcReg, MIBSz->getOperand(0));
    MIRBuilder.buildAShr(DstReg, TmpRes, MIBSz->getOperand(0));
    MI.eraseFromParent();
    return Legalized;
  }
  case G_EXTRACT_VECTOR_ELT:
  case G_INSERT_VECTOR_ELT:
    return lowerExtractInsertVectorElt(MI);
  case G_SHUFFLE_VECTOR:
    return lowerShuffleVector(MI);
  case G_VECTOR_COMPRESS:
    return lowerVECTOR_COMPRESS(MI);
  case G_DYN_STACKALLOC:
    return lowerDynStackAlloc(MI);
  case G_INSERT_SUBVECTOR: {
    if (MRI.getType(MI.getOperand(1).getReg()).isScalable() ||
        MRI.getType(MI.getOperand(2).getReg()).isScalable())
      return UnableToLegalize;

    // Check that subvector is half size of main vector
    Register Vector = MI.getOperand(1).getReg();
    Register Subvector = MI.getOperand(2).getReg();
    auto InsertionPointImm = MI.getOperand(3).getImm();

    LLT VectorTy = MRI.getType(Vector);
    LLT SubvectorTy = MRI.getType(Subvector);
    // If so, -> concat(subvector, extract(half of vector))
    // (Operands can be either way round depending on insertion point
    if (VectorTy.getSizeInBits() == SubvectorTy.getSizeInBits() * 2) {
      bool InsertInLowHalf = InsertionPointImm == 0;
      auto Extract = MIRBuilder.buildExtractSubvector(
          SubvectorTy, Vector,
          (uint64_t)(InsertInLowHalf ? VectorTy.getNumElements() / 2 : 0));

      auto LowHalf = InsertInLowHalf ? Subvector : Extract.getReg(0);
      auto HighHalf = InsertInLowHalf ? Extract.getReg(0) : Subvector;

      MIRBuilder.buildInstr(TargetOpcode::G_CONCAT_VECTORS, {MI.getOperand(0)},
                            {LowHalf, HighHalf});
      MI.eraseFromParent();
      return Legalized;
    }
    // Else -> shuffle(vector, extend(subvector, size(vector)), mask)
    else {
      // Extend subvector to same size as vector
      Register ExtendedSubvector = MRI.createGenericVirtualRegister(VectorTy);
      MIRBuilder.buildPadVectorWithUndefElements(ExtendedSubvector, Subvector);

      // Calculate mask required for this shuffle
      SmallVector<int> Mask;
      for (int i = 0; i < VectorTy.getNumElements(); i++) {
        // If this index is within bounds, put subvector's index into mask
        if (i >= InsertionPointImm &&
            i < InsertionPointImm + SubvectorTy.getNumElements())
          Mask.push_back(VectorTy.getNumElements() + i - InsertionPointImm);
        else
          Mask.push_back(i);
      }

      // Build shuffle
      MIRBuilder.buildShuffleVector(MI.getOperand(0), Vector, ExtendedSubvector,
                                    Mask);
      MI.eraseFromParent();
      return Legalized;
    }
  }
  case G_STACKSAVE:
    return lowerStackSave(MI);
  case G_STACKRESTORE:
    return lowerStackRestore(MI);
  case G_EXTRACT:
    return lowerExtract(MI);
  case G_INSERT:
    return lowerInsert(MI);
  case G_BSWAP:
    return lowerBswap(MI);
  case G_BITREVERSE:
    return lowerBitreverse(MI);
  case G_READ_REGISTER:
  case G_WRITE_REGISTER:
    return lowerReadWriteRegister(MI);
  case G_UADDSAT:
  case G_USUBSAT: {
    // Try to make a reasonable guess about which lowering strategy to use. The
    // target can override this with custom lowering and calling the
    // implementation functions.
    LLT Ty = MRI.getType(MI.getOperand(0).getReg());
    if (LI.isLegalOrCustom({G_UMIN, Ty}))
      return lowerAddSubSatToMinMax(MI);
    return lowerAddSubSatToAddoSubo(MI);
  }
  case G_SADDSAT:
  case G_SSUBSAT: {
    LLT Ty = MRI.getType(MI.getOperand(0).getReg());

    // FIXME: It would probably make more sense to see if G_SADDO is preferred,
    // since it's a shorter expansion. However, we would need to figure out the
    // preferred boolean type for the carry out for the query.
    if (LI.isLegalOrCustom({G_SMIN, Ty}) && LI.isLegalOrCustom({G_SMAX, Ty}))
      return lowerAddSubSatToMinMax(MI);
    return lowerAddSubSatToAddoSubo(MI);
  }
  case G_SSHLSAT:
  case G_USHLSAT:
    return lowerShlSat(MI);
  case G_ABS:
    return lowerAbsToAddXor(MI);
  case G_ABDS:
  case G_ABDU: {
    bool IsSigned = MI.getOpcode() == G_ABDS;
    LLT Ty = MRI.getType(MI.getOperand(0).getReg());
    if ((IsSigned && LI.isLegal({G_SMIN, Ty}) && LI.isLegal({G_SMAX, Ty})) ||
        (!IsSigned && LI.isLegal({G_UMIN, Ty}) && LI.isLegal({G_UMAX, Ty}))) {
      return lowerAbsDiffToMinMax(MI);
    }
    return lowerAbsDiffToSelect(MI);
  }
  case G_FABS:
    return lowerFAbs(MI);
  case G_SELECT:
    return lowerSelect(MI);
  case G_IS_FPCLASS:
    return lowerISFPCLASS(MI);
  case G_SDIVREM:
  case G_UDIVREM:
    return lowerDIVREM(MI);
  case G_FSHL:
  case G_FSHR:
    return lowerFunnelShift(MI);
  case G_ROTL:
  case G_ROTR:
    return lowerRotate(MI);
  case G_MEMSET:
  case G_MEMCPY:
  case G_MEMMOVE:
  case G_MEMCPY_INLINE:
  case G_MEMSET_INLINE:
    return lowerMemCpyFamily(MI);
  case G_ZEXT:
  case G_SEXT:
  case G_ANYEXT:
    return lowerEXT(MI);
  case G_TRUNC:
    return lowerTRUNC(MI);
  GISEL_VECREDUCE_CASES_NONSEQ
    return lowerVectorReduction(MI);
  case G_VAARG:
    return lowerVAArg(MI);
  case G_ATOMICRMW_SUB: {
    auto [Ret, Mem, Val] = MI.getFirst3Regs();
    const LLT ValTy = MRI.getType(Val);
    MachineMemOperand *MMO = *MI.memoperands_begin();

    auto VNeg = MIRBuilder.buildNeg(ValTy, Val);
    MIRBuilder.buildAtomicRMW(G_ATOMICRMW_ADD, Ret, Mem, VNeg, *MMO);
    MI.eraseFromParent();
    return Legalized;
  }
  case G_SMULFIX:
  case G_UMULFIX:
    return lowerMulfix(MI);
  }
}

Align LegalizerHelper::getStackTemporaryAlignment(LLT Ty,
                                                  Align MinAlign) const {
  // FIXME: We're missing a way to go back from LLT to llvm::Type to query the
  // datalayout for the preferred alignment. Also there should be a target hook
  // for this to allow targets to reduce the alignment and ignore the
  // datalayout. e.g. AMDGPU should always use a 4-byte alignment, regardless of
  // the type.
  return std::max(Align(PowerOf2Ceil(Ty.getSizeInBytes())), MinAlign);
}

MachineInstrBuilder
LegalizerHelper::createStackTemporary(TypeSize Bytes, Align Alignment,
                                      MachinePointerInfo &PtrInfo) {
  MachineFunction &MF = MIRBuilder.getMF();
  const DataLayout &DL = MIRBuilder.getDataLayout();
  int FrameIdx = MF.getFrameInfo().CreateStackObject(Bytes, Alignment, false);

  unsigned AddrSpace = DL.getAllocaAddrSpace();
  LLT FramePtrTy = LLT::pointer(AddrSpace, DL.getPointerSizeInBits(AddrSpace));

  PtrInfo = MachinePointerInfo::getFixedStack(MF, FrameIdx);
  return MIRBuilder.buildFrameIndex(FramePtrTy, FrameIdx);
}

MachineInstrBuilder LegalizerHelper::createStackStoreLoad(const DstOp &Res,
                                                          const SrcOp &Val) {
  LLT SrcTy = Val.getLLTTy(MRI);
  Align StackTypeAlign =
      std::max(getStackTemporaryAlignment(SrcTy),
               getStackTemporaryAlignment(Res.getLLTTy(MRI)));
  MachinePointerInfo PtrInfo;
  auto StackTemp =
      createStackTemporary(SrcTy.getSizeInBytes(), StackTypeAlign, PtrInfo);

  MIRBuilder.buildStore(Val, StackTemp, PtrInfo, StackTypeAlign);
  return MIRBuilder.buildLoad(Res, StackTemp, PtrInfo, StackTypeAlign);
}

static Register clampVectorIndex(MachineIRBuilder &B, Register IdxReg,
                                 LLT VecTy) {
  LLT IdxTy = B.getMRI()->getType(IdxReg);
  unsigned NElts = VecTy.getNumElements();

  int64_t IdxVal;
  if (mi_match(IdxReg, *B.getMRI(), m_ICst(IdxVal))) {
    if (IdxVal < VecTy.getNumElements())
      return IdxReg;
    // If a constant index would be out of bounds, clamp it as well.
  }

  if (isPowerOf2_32(NElts)) {
    APInt Imm = APInt::getLowBitsSet(IdxTy.getSizeInBits(), Log2_32(NElts));
    return B.buildAnd(IdxTy, IdxReg, B.buildConstant(IdxTy, Imm)).getReg(0);
  }

  return B.buildUMin(IdxTy, IdxReg, B.buildConstant(IdxTy, NElts - 1))
      .getReg(0);
}

Register LegalizerHelper::getVectorElementPointer(Register VecPtr, LLT VecTy,
                                                  Register Index) {
  LLT EltTy = VecTy.getElementType();

  // Calculate the element offset and add it to the pointer.
  unsigned EltSize = EltTy.getSizeInBits() / 8; // FIXME: should be ABI size.
  assert(EltSize * 8 == EltTy.getSizeInBits() &&
         "Converting bits to bytes lost precision");

  Index = clampVectorIndex(MIRBuilder, Index, VecTy);

  // Convert index to the correct size for the address space.
  const DataLayout &DL = MIRBuilder.getDataLayout();
  unsigned AS = MRI.getType(VecPtr).getAddressSpace();
  unsigned IndexSizeInBits = DL.getIndexSize(AS) * 8;
  LLT IdxTy = MRI.getType(Index).changeElementSize(IndexSizeInBits);
  if (IdxTy != MRI.getType(Index))
    Index = MIRBuilder.buildSExtOrTrunc(IdxTy, Index).getReg(0);

  auto Mul = MIRBuilder.buildMul(IdxTy, Index,
                                 MIRBuilder.buildConstant(IdxTy, EltSize));

  LLT PtrTy = MRI.getType(VecPtr);
  return MIRBuilder.buildPtrAdd(PtrTy, VecPtr, Mul).getReg(0);
}

#ifndef NDEBUG
/// Check that all vector operands have same number of elements. Other operands
/// should be listed in NonVecOp.
static bool hasSameNumEltsOnAllVectorOperands(
    GenericMachineInstr &MI, MachineRegisterInfo &MRI,
    std::initializer_list<unsigned> NonVecOpIndices) {
  if (MI.getNumMemOperands() != 0)
    return false;

  LLT VecTy = MRI.getType(MI.getReg(0));
  if (!VecTy.isVector())
    return false;
  unsigned NumElts = VecTy.getNumElements();

  for (unsigned OpIdx = 1; OpIdx < MI.getNumOperands(); ++OpIdx) {
    MachineOperand &Op = MI.getOperand(OpIdx);
    if (!Op.isReg()) {
      if (!is_contained(NonVecOpIndices, OpIdx))
        return false;
      continue;
    }

    LLT Ty = MRI.getType(Op.getReg());
    if (!Ty.isVector()) {
      if (!is_contained(NonVecOpIndices, OpIdx))
        return false;
      continue;
    }

    if (Ty.getNumElements() != NumElts)
      return false;
  }

  return true;
}
#endif

/// Fill \p DstOps with DstOps that have same number of elements combined as
/// the Ty. These DstOps have either scalar type when \p NumElts = 1 or are
/// vectors with \p NumElts elements. When Ty.getNumElements() is not multiple
/// of \p NumElts last DstOp (leftover) has fewer then \p NumElts elements.
static void makeDstOps(SmallVectorImpl<DstOp> &DstOps, LLT Ty,
                       unsigned NumElts) {
  LLT LeftoverTy;
  assert(Ty.isVector() && "Expected vector type");
  LLT NarrowTy = Ty.changeElementCount(ElementCount::getFixed(NumElts));
  int NumParts, NumLeftover;
  std::tie(NumParts, NumLeftover) =
      getNarrowTypeBreakDown(Ty, NarrowTy, LeftoverTy);

  assert(NumParts > 0 && "Error in getNarrowTypeBreakDown");
  for (int i = 0; i < NumParts; ++i) {
    DstOps.push_back(NarrowTy);
  }

  if (LeftoverTy.isValid()) {
    assert(NumLeftover == 1 && "expected exactly one leftover");
    DstOps.push_back(LeftoverTy);
  }
}

/// Operand \p Op is used on \p N sub-instructions. Fill \p Ops with \p N SrcOps
/// made from \p Op depending on operand type.
static void broadcastSrcOp(SmallVectorImpl<SrcOp> &Ops, unsigned N,
                           MachineOperand &Op) {
  for (unsigned i = 0; i < N; ++i) {
    if (Op.isReg())
      Ops.push_back(Op.getReg());
    else if (Op.isImm())
      Ops.push_back(Op.getImm());
    else if (Op.isPredicate())
      Ops.push_back(static_cast<CmpInst::Predicate>(Op.getPredicate()));
    else
      llvm_unreachable("Unsupported type");
  }
}

// Handle splitting vector operations which need to have the same number of
// elements in each type index, but each type index may have a different element
// type.
//
// e.g.  <4 x s64> = G_SHL <4 x s64>, <4 x s32> ->
//       <2 x s64> = G_SHL <2 x s64>, <2 x s32>
//       <2 x s64> = G_SHL <2 x s64>, <2 x s32>
//
// Also handles some irregular breakdown cases, e.g.
// e.g.  <3 x s64> = G_SHL <3 x s64>, <3 x s32> ->
//       <2 x s64> = G_SHL <2 x s64>, <2 x s32>
//             s64 = G_SHL s64, s32
LegalizerHelper::LegalizeResult
LegalizerHelper::fewerElementsVectorMultiEltType(
    GenericMachineInstr &MI, unsigned NumElts,
    std::initializer_list<unsigned> NonVecOpIndices) {
  assert(hasSameNumEltsOnAllVectorOperands(MI, MRI, NonVecOpIndices) &&
         "Non-compatible opcode or not specified non-vector operands");
  unsigned OrigNumElts = MRI.getType(MI.getReg(0)).getNumElements();

  unsigned NumInputs = MI.getNumOperands() - MI.getNumDefs();
  unsigned NumDefs = MI.getNumDefs();

  // Create DstOps (sub-vectors with NumElts elts + Leftover) for each output.
  // Build instructions with DstOps to use instruction found by CSE directly.
  // CSE copies found instruction into given vreg when building with vreg dest.
  SmallVector<SmallVector<DstOp, 8>, 2> OutputOpsPieces(NumDefs);
  // Output registers will be taken from created instructions.
  SmallVector<SmallVector<Register, 8>, 2> OutputRegs(NumDefs);
  for (unsigned i = 0; i < NumDefs; ++i) {
    makeDstOps(OutputOpsPieces[i], MRI.getType(MI.getReg(i)), NumElts);
  }

  // Split vector input operands into sub-vectors with NumElts elts + Leftover.
  // Operands listed in NonVecOpIndices will be used as is without splitting;
  // examples: compare predicate in icmp and fcmp (op 1), vector select with i1
  // scalar condition (op 1), immediate in sext_inreg (op 2).
  SmallVector<SmallVector<SrcOp, 8>, 3> InputOpsPieces(NumInputs);
  for (unsigned UseIdx = NumDefs, UseNo = 0; UseIdx < MI.getNumOperands();
       ++UseIdx, ++UseNo) {
    if (is_contained(NonVecOpIndices, UseIdx)) {
      broadcastSrcOp(InputOpsPieces[UseNo], OutputOpsPieces[0].size(),
                     MI.getOperand(UseIdx));
    } else {
      SmallVector<Register, 8> SplitPieces;
      extractVectorParts(MI.getReg(UseIdx), NumElts, SplitPieces, MIRBuilder,
                         MRI);
      llvm::append_range(InputOpsPieces[UseNo], SplitPieces);
    }
  }

  unsigned NumLeftovers = OrigNumElts % NumElts ? 1 : 0;

  // Take i-th piece of each input operand split and build sub-vector/scalar
  // instruction. Set i-th DstOp(s) from OutputOpsPieces as destination(s).
  for (unsigned i = 0; i < OrigNumElts / NumElts + NumLeftovers; ++i) {
    SmallVector<DstOp, 2> Defs;
    for (unsigned DstNo = 0; DstNo < NumDefs; ++DstNo)
      Defs.push_back(OutputOpsPieces[DstNo][i]);

    SmallVector<SrcOp, 3> Uses;
    for (unsigned InputNo = 0; InputNo < NumInputs; ++InputNo)
      Uses.push_back(InputOpsPieces[InputNo][i]);

    auto I = MIRBuilder.buildInstr(MI.getOpcode(), Defs, Uses, MI.getFlags());
    for (unsigned DstNo = 0; DstNo < NumDefs; ++DstNo)
      OutputRegs[DstNo].push_back(I.getReg(DstNo));
  }

  // Merge small outputs into MI's output for each def operand.
  if (NumLeftovers) {
    for (unsigned i = 0; i < NumDefs; ++i)
      mergeMixedSubvectors(MI.getReg(i), OutputRegs[i]);
  } else {
    for (unsigned i = 0; i < NumDefs; ++i)
      MIRBuilder.buildMergeLikeInstr(MI.getReg(i), OutputRegs[i]);
  }

  MI.eraseFromParent();
  return Legalized;
}

LegalizerHelper::LegalizeResult
LegalizerHelper::fewerElementsVectorPhi(GenericMachineInstr &MI,
                                        unsigned NumElts) {
  unsigned OrigNumElts = MRI.getType(MI.getReg(0)).getNumElements();

  unsigned NumInputs = MI.getNumOperands() - MI.getNumDefs();
  unsigned NumDefs = MI.getNumDefs();

  SmallVector<DstOp, 8> OutputOpsPieces;
  SmallVector<Register, 8> OutputRegs;
  makeDstOps(OutputOpsPieces, MRI.getType(MI.getReg(0)), NumElts);

  // Instructions that perform register split will be inserted in basic block
  // where register is defined (basic block is in the next operand).
  SmallVector<SmallVector<Register, 8>, 3> InputOpsPieces(NumInputs / 2);
  for (unsigned UseIdx = NumDefs, UseNo = 0; UseIdx < MI.getNumOperands();
       UseIdx += 2, ++UseNo) {
    MachineBasicBlock &OpMBB = *MI.getOperand(UseIdx + 1).getMBB();
    MIRBuilder.setInsertPt(OpMBB, OpMBB.getFirstTerminatorForward());
    extractVectorParts(MI.getReg(UseIdx), NumElts, InputOpsPieces[UseNo],
                       MIRBuilder, MRI);
  }

  // Build PHIs with fewer elements.
  unsigned NumLeftovers = OrigNumElts % NumElts ? 1 : 0;
  MIRBuilder.setInsertPt(*MI.getParent(), MI);
  for (unsigned i = 0; i < OrigNumElts / NumElts + NumLeftovers; ++i) {
    auto Phi = MIRBuilder.buildInstr(TargetOpcode::G_PHI);
    Phi.addDef(
        MRI.createGenericVirtualRegister(OutputOpsPieces[i].getLLTTy(MRI)));
    OutputRegs.push_back(Phi.getReg(0));

    for (unsigned j = 0; j < NumInputs / 2; ++j) {
      Phi.addUse(InputOpsPieces[j][i]);
      Phi.add(MI.getOperand(1 + j * 2 + 1));
    }
  }

  // Set the insert point after the existing PHIs
  MachineBasicBlock &MBB = *MI.getParent();
  MIRBuilder.setInsertPt(MBB, MBB.getFirstNonPHI());

  // Merge small outputs into MI's def.
  if (NumLeftovers) {
    mergeMixedSubvectors(MI.getReg(0), OutputRegs);
  } else {
    MIRBuilder.buildMergeLikeInstr(MI.getReg(0), OutputRegs);
  }

  MI.eraseFromParent();
  return Legalized;
}

LegalizerHelper::LegalizeResult
LegalizerHelper::fewerElementsVectorUnmergeValues(MachineInstr &MI,
                                                  unsigned TypeIdx,
                                                  LLT NarrowTy) {
  const int NumDst = MI.getNumOperands() - 1;
  const Register SrcReg = MI.getOperand(NumDst).getReg();
  LLT DstTy = MRI.getType(MI.getOperand(0).getReg());
  LLT SrcTy = MRI.getType(SrcReg);

  if (TypeIdx != 1 || NarrowTy == DstTy)
    return UnableToLegalize;

  // Requires compatible types. Otherwise SrcReg should have been defined by
  // merge-like instruction that would get artifact combined. Most likely
  // instruction that defines SrcReg has to perform more/fewer elements
  // legalization compatible with NarrowTy.
  assert(SrcTy.isVector() && NarrowTy.isVector() && "Expected vector types");
  assert((SrcTy.getScalarType() == NarrowTy.getScalarType()) && "bad type");

  if ((SrcTy.getSizeInBits() % NarrowTy.getSizeInBits() != 0) ||
      (NarrowTy.getSizeInBits() % DstTy.getSizeInBits() != 0))
    return UnableToLegalize;

  // This is most likely DstTy (smaller then register size) packed in SrcTy
  // (larger then register size) and since unmerge was not combined it will be
  // lowered to bit sequence extracts from register. Unpack SrcTy to NarrowTy
  // (register size) pieces first. Then unpack each of NarrowTy pieces to DstTy.

  // %1:_(DstTy), %2, %3, %4 = G_UNMERGE_VALUES %0:_(SrcTy)
  //
  // %5:_(NarrowTy), %6 = G_UNMERGE_VALUES %0:_(SrcTy) - reg sequence
  // %1:_(DstTy), %2 = G_UNMERGE_VALUES %5:_(NarrowTy) - sequence of bits in reg
  // %3:_(DstTy), %4 = G_UNMERGE_VALUES %6:_(NarrowTy)
  auto Unmerge = MIRBuilder.buildUnmerge(NarrowTy, SrcReg);
  const int NumUnmerge = Unmerge->getNumOperands() - 1;
  const int PartsPerUnmerge = NumDst / NumUnmerge;

  for (int I = 0; I != NumUnmerge; ++I) {
    auto MIB = MIRBuilder.buildInstr(TargetOpcode::G_UNMERGE_VALUES);

    for (int J = 0; J != PartsPerUnmerge; ++J)
      MIB.addDef(MI.getOperand(I * PartsPerUnmerge + J).getReg());
    MIB.addUse(Unmerge.getReg(I));
  }

  MI.eraseFromParent();
  return Legalized;
}

LegalizerHelper::LegalizeResult
LegalizerHelper::fewerElementsVectorMerge(MachineInstr &MI, unsigned TypeIdx,
                                          LLT NarrowTy) {
  auto [DstReg, DstTy, SrcReg, SrcTy] = MI.getFirst2RegLLTs();
  // Requires compatible types. Otherwise user of DstReg did not perform unmerge
  // that should have been artifact combined. Most likely instruction that uses
  // DstReg has to do more/fewer elements legalization compatible with NarrowTy.
  assert(DstTy.isVector() && NarrowTy.isVector() && "Expected vector types");
  assert((DstTy.getScalarType() == NarrowTy.getScalarType()) && "bad type");
  if (NarrowTy == SrcTy)
    return UnableToLegalize;

  // This attempts to lower part of LCMTy merge/unmerge sequence. Intended use
  // is for old mir tests. Since the changes to more/fewer elements it should no
  // longer be possible to generate MIR like this when starting from llvm-ir
  // because LCMTy approach was replaced with merge/unmerge to vector elements.
  if (TypeIdx == 1) {
    assert(SrcTy.isVector() && "Expected vector types");
    assert((SrcTy.getScalarType() == NarrowTy.getScalarType()) && "bad type");
    if ((DstTy.getSizeInBits() % NarrowTy.getSizeInBits() != 0) ||
        (NarrowTy.getNumElements() >= SrcTy.getNumElements()))
      return UnableToLegalize;
    // %2:_(DstTy) = G_CONCAT_VECTORS %0:_(SrcTy), %1:_(SrcTy)
    //
    // %3:_(EltTy), %4, %5 = G_UNMERGE_VALUES %0:_(SrcTy)
    // %6:_(EltTy), %7, %8 = G_UNMERGE_VALUES %1:_(SrcTy)
    // %9:_(NarrowTy) = G_BUILD_VECTOR %3:_(EltTy), %4
    // %10:_(NarrowTy) = G_BUILD_VECTOR %5:_(EltTy), %6
    // %11:_(NarrowTy) = G_BUILD_VECTOR %7:_(EltTy), %8
    // %2:_(DstTy) = G_CONCAT_VECTORS %9:_(NarrowTy), %10, %11

    SmallVector<Register, 8> Elts;
    LLT EltTy = MRI.getType(MI.getOperand(1).getReg()).getScalarType();
    for (unsigned i = 1; i < MI.getNumOperands(); ++i) {
      auto Unmerge = MIRBuilder.buildUnmerge(EltTy, MI.getOperand(i).getReg());
      for (unsigned j = 0; j < Unmerge->getNumDefs(); ++j)
        Elts.push_back(Unmerge.getReg(j));
    }

    SmallVector<Register, 8> NarrowTyElts;
    unsigned NumNarrowTyElts = NarrowTy.getNumElements();
    unsigned NumNarrowTyPieces = DstTy.getNumElements() / NumNarrowTyElts;
    for (unsigned i = 0, Offset = 0; i < NumNarrowTyPieces;
         ++i, Offset += NumNarrowTyElts) {
      ArrayRef<Register> Pieces(&Elts[Offset], NumNarrowTyElts);
      NarrowTyElts.push_back(
          MIRBuilder.buildMergeLikeInstr(NarrowTy, Pieces).getReg(0));
    }

    MIRBuilder.buildMergeLikeInstr(DstReg, NarrowTyElts);
    MI.eraseFromParent();
    return Legalized;
  }

  assert(TypeIdx == 0 && "Bad type index");
  if ((NarrowTy.getSizeInBits() % SrcTy.getSizeInBits() != 0) ||
      (DstTy.getSizeInBits() % NarrowTy.getSizeInBits() != 0))
    return UnableToLegalize;

  // This is most likely SrcTy (smaller then register size) packed in DstTy
  // (larger then register size) and since merge was not combined it will be
  // lowered to bit sequence packing into register. Merge SrcTy to NarrowTy
  // (register size) pieces first. Then merge each of NarrowTy pieces to DstTy.

  // %0:_(DstTy) = G_MERGE_VALUES %1:_(SrcTy), %2, %3, %4
  //
  // %5:_(NarrowTy) = G_MERGE_VALUES %1:_(SrcTy), %2 - sequence of bits in reg
  // %6:_(NarrowTy) = G_MERGE_VALUES %3:_(SrcTy), %4
  // %0:_(DstTy)  = G_MERGE_VALUES %5:_(NarrowTy), %6 - reg sequence
  SmallVector<Register, 8> NarrowTyElts;
  unsigned NumParts = DstTy.getNumElements() / NarrowTy.getNumElements();
  unsigned NumSrcElts = SrcTy.isVector() ? SrcTy.getNumElements() : 1;
  unsigned NumElts = NarrowTy.getNumElements() / NumSrcElts;
  for (unsigned i = 0; i < NumParts; ++i) {
    SmallVector<Register, 8> Sources;
    for (unsigned j = 0; j < NumElts; ++j)
      Sources.push_back(MI.getOperand(1 + i * NumElts + j).getReg());
    NarrowTyElts.push_back(
        MIRBuilder.buildMergeLikeInstr(NarrowTy, Sources).getReg(0));
  }

  MIRBuilder.buildMergeLikeInstr(DstReg, NarrowTyElts);
  MI.eraseFromParent();
  return Legalized;
}

LegalizerHelper::LegalizeResult
LegalizerHelper::fewerElementsVectorExtractInsertVectorElt(MachineInstr &MI,
                                                           unsigned TypeIdx,
                                                           LLT NarrowVecTy) {
  auto [DstReg, SrcVec] = MI.getFirst2Regs();
  Register InsertVal;
  bool IsInsert = MI.getOpcode() == TargetOpcode::G_INSERT_VECTOR_ELT;

  assert((IsInsert ? TypeIdx == 0 : TypeIdx == 1) && "not a vector type index");
  if (IsInsert)
    InsertVal = MI.getOperand(2).getReg();

  Register Idx = MI.getOperand(MI.getNumOperands() - 1).getReg();
  LLT VecTy = MRI.getType(SrcVec);

  // If the index is a constant, we can really break this down as you would
  // expect, and index into the target size pieces.
  auto MaybeCst = getIConstantVRegValWithLookThrough(Idx, MRI);
  if (MaybeCst) {
    uint64_t IdxVal = MaybeCst->Value.getZExtValue();
    // Avoid out of bounds indexing the pieces.
    if (IdxVal >= VecTy.getNumElements()) {
      MIRBuilder.buildUndef(DstReg);
      MI.eraseFromParent();
      return Legalized;
    }

    if (!NarrowVecTy.isVector()) {
      SmallVector<Register, 8> SplitPieces;
      extractParts(MI.getOperand(1).getReg(), NarrowVecTy,
                   VecTy.getNumElements(), SplitPieces, MIRBuilder, MRI);
      if (IsInsert) {
        SplitPieces[IdxVal] = InsertVal;
        MIRBuilder.buildMergeLikeInstr(MI.getOperand(0).getReg(), SplitPieces);
      } else {
        MIRBuilder.buildCopy(MI.getOperand(0).getReg(), SplitPieces[IdxVal]);
      }
    } else {
      SmallVector<Register, 8> VecParts;
      LLT GCDTy = extractGCDType(VecParts, VecTy, NarrowVecTy, SrcVec);

      // Build a sequence of NarrowTy pieces in VecParts for this operand.
      LLT LCMTy = buildLCMMergePieces(VecTy, NarrowVecTy, GCDTy, VecParts,
                                      TargetOpcode::G_ANYEXT);

      unsigned NewNumElts = NarrowVecTy.getNumElements();

      LLT IdxTy = MRI.getType(Idx);
      int64_t PartIdx = IdxVal / NewNumElts;
      auto NewIdx =
          MIRBuilder.buildConstant(IdxTy, IdxVal - NewNumElts * PartIdx);

      if (IsInsert) {
        LLT PartTy = MRI.getType(VecParts[PartIdx]);

        // Use the adjusted index to insert into one of the subvectors.
        auto InsertPart = MIRBuilder.buildInsertVectorElement(
            PartTy, VecParts[PartIdx], InsertVal, NewIdx);
        VecParts[PartIdx] = InsertPart.getReg(0);

        // Recombine the inserted subvector with the others to reform the result
        // vector.
        buildWidenedRemergeToDst(DstReg, LCMTy, VecParts);
      } else {
        MIRBuilder.buildExtractVectorElement(DstReg, VecParts[PartIdx], NewIdx);
      }
    }

    MI.eraseFromParent();
    return Legalized;
  }

  // With a variable index, we can't perform the operation in a smaller type, so
  // we're forced to expand this.
  //
  // TODO: We could emit a chain of compare/select to figure out which piece to
  // index.
  return lowerExtractInsertVectorElt(MI);
}

LegalizerHelper::LegalizeResult
LegalizerHelper::reduceLoadStoreWidth(GLoadStore &LdStMI, unsigned TypeIdx,
                                      LLT NarrowTy) {
  // FIXME: Don't know how to handle secondary types yet.
  if (TypeIdx != 0)
    return UnableToLegalize;

  if (!NarrowTy.isByteSized()) {
    LLVM_DEBUG(dbgs() << "Can't narrow load/store to non-byte-sized type\n");
    return UnableToLegalize;
  }

  // This implementation doesn't work for atomics. Give up instead of doing
  // something invalid.
  if (LdStMI.isAtomic())
    return UnableToLegalize;

  bool IsLoad = isa<GLoad>(LdStMI);
  Register ValReg = LdStMI.getReg(0);
  Register AddrReg = LdStMI.getPointerReg();
  LLT ValTy = MRI.getType(ValReg);

  // FIXME: Do we need a distinct NarrowMemory legalize action?
  if (ValTy.getSizeInBits() != 8 * LdStMI.getMemSize().getValue()) {
    LLVM_DEBUG(dbgs() << "Can't narrow extload/truncstore\n");
    return UnableToLegalize;
  }

  int NumParts = -1;
  int NumLeftover = -1;
  LLT LeftoverTy;
  SmallVector<Register, 8> NarrowRegs, NarrowLeftoverRegs;
  if (IsLoad) {
    std::tie(NumParts, NumLeftover) = getNarrowTypeBreakDown(ValTy, NarrowTy, LeftoverTy);
  } else {
    if (extractParts(ValReg, ValTy, NarrowTy, LeftoverTy, NarrowRegs,
                     NarrowLeftoverRegs, MIRBuilder, MRI)) {
      NumParts = NarrowRegs.size();
      NumLeftover = NarrowLeftoverRegs.size();
    }
  }

  if (NumParts == -1)
    return UnableToLegalize;

  LLT PtrTy = MRI.getType(AddrReg);
  const LLT OffsetTy = LLT::integer(PtrTy.getSizeInBits());

  unsigned TotalSize = ValTy.getSizeInBits();

  // Split the load/store into PartTy sized pieces starting at Offset. If this
  // is a load, return the new registers in ValRegs. For a store, each elements
  // of ValRegs should be PartTy. Returns the next offset that needs to be
  // handled.
  bool isBigEndian = MIRBuilder.getDataLayout().isBigEndian();
  auto MMO = LdStMI.getMMO();
  auto splitTypePieces = [=](LLT PartTy, SmallVectorImpl<Register> &ValRegs,
                             unsigned NumParts, unsigned Offset) -> unsigned {
    MachineFunction &MF = MIRBuilder.getMF();
    unsigned PartSize = PartTy.getSizeInBits();
    for (unsigned Idx = 0, E = NumParts; Idx != E && Offset < TotalSize;
         ++Idx) {
      unsigned ByteOffset = Offset / 8;
      Register NewAddrReg;

      MIRBuilder.materializeObjectPtrOffset(NewAddrReg, AddrReg, OffsetTy,
                                            ByteOffset);

      MachineMemOperand *NewMMO =
          MF.getMachineMemOperand(&MMO, ByteOffset, PartTy);

      if (IsLoad) {
        Register Dst = MRI.createGenericVirtualRegister(PartTy);
        ValRegs.push_back(Dst);
        MIRBuilder.buildLoad(Dst, NewAddrReg, *NewMMO);
      } else {
        MIRBuilder.buildStore(ValRegs[Idx], NewAddrReg, *NewMMO);
      }
      Offset = isBigEndian ? Offset - PartSize : Offset + PartSize;
    }

    return Offset;
  };

  unsigned Offset = isBigEndian ? TotalSize - NarrowTy.getSizeInBits() : 0;
  unsigned HandledOffset =
      splitTypePieces(NarrowTy, NarrowRegs, NumParts, Offset);

  // Handle the rest of the register if this isn't an even type breakdown.
  if (LeftoverTy.isValid())
    splitTypePieces(LeftoverTy, NarrowLeftoverRegs, NumLeftover, HandledOffset);

  if (IsLoad) {
    insertParts(ValReg, ValTy, NarrowTy, NarrowRegs,
                LeftoverTy, NarrowLeftoverRegs);
  }

  LdStMI.eraseFromParent();
  return Legalized;
}

LegalizerHelper::LegalizeResult
LegalizerHelper::fewerElementsVector(MachineInstr &MI, unsigned TypeIdx,
                                     LLT NarrowTy) {
  using namespace TargetOpcode;
  GenericMachineInstr &GMI = cast<GenericMachineInstr>(MI);
  unsigned NumElts = NarrowTy.isVector() ? NarrowTy.getNumElements() : 1;

  switch (MI.getOpcode()) {
  case G_IMPLICIT_DEF:
  case G_TRUNC:
  case G_AND:
  case G_OR:
  case G_XOR:
  case G_ADD:
  case G_SUB:
  case G_MUL:
  case G_PTR_ADD:
  case G_SMULH:
  case G_UMULH:
  case G_FADD:
  case G_FMUL:
  case G_FSUB:
  case G_FNEG:
  case G_FABS:
  case G_FCANONICALIZE:
  case G_FDIV:
  case G_FREM:
  case G_FMA:
  case G_FMAD:
  case G_FPOW:
  case G_FEXP:
  case G_FEXP2:
  case G_FEXP10:
  case G_FLOG:
  case G_FLOG2:
  case G_FLOG10:
  case G_FLDEXP:
  case G_FNEARBYINT:
  case G_FCEIL:
  case G_FFLOOR:
  case G_FRINT:
  case G_INTRINSIC_LRINT:
  case G_INTRINSIC_LLRINT:
  case G_INTRINSIC_ROUND:
  case G_INTRINSIC_ROUNDEVEN:
  case G_LROUND:
  case G_LLROUND:
  case G_INTRINSIC_TRUNC:
  case G_FMODF:
  case G_FCOS:
  case G_FSIN:
  case G_FTAN:
  case G_FACOS:
  case G_FASIN:
  case G_FATAN:
  case G_FATAN2:
  case G_FCOSH:
  case G_FSINH:
  case G_FTANH:
  case G_FSQRT:
  case G_BSWAP:
  case G_BITREVERSE:
  case G_SDIV:
  case G_UDIV:
  case G_SREM:
  case G_UREM:
  case G_SDIVREM:
  case G_UDIVREM:
  case G_SMIN:
  case G_SMAX:
  case G_UMIN:
  case G_UMAX:
  case G_ABS:
  case G_FMINNUM:
  case G_FMAXNUM:
  case G_FMINNUM_IEEE:
  case G_FMAXNUM_IEEE:
  case G_FMINIMUM:
  case G_FMAXIMUM:
  case G_FMINIMUMNUM:
  case G_FMAXIMUMNUM:
  case G_FSHL:
  case G_FSHR:
  case G_ROTL:
  case G_ROTR:
  case G_FREEZE:
  case G_SADDSAT:
  case G_SSUBSAT:
  case G_UADDSAT:
  case G_USUBSAT:
  case G_UMULO:
  case G_SMULO:
  case G_SHL:
  case G_LSHR:
  case G_ASHR:
  case G_SSHLSAT:
  case G_USHLSAT:
  case G_CTLZ:
  case G_CTLZ_ZERO_POISON:
  case G_CTTZ:
  case G_CTTZ_ZERO_POISON:
  case G_CTPOP:
  case G_CTLS:
  case G_FCOPYSIGN:
  case G_ZEXT:
  case G_SEXT:
  case G_ANYEXT:
  case G_FPEXT:
  case G_FPTRUNC:
  case G_SITOFP:
  case G_UITOFP:
  case G_FPTOSI:
  case G_FPTOUI:
  case G_FPTOSI_SAT:
  case G_FPTOUI_SAT:
  case G_INTTOPTR:
  case G_PTRTOINT:
  case G_ADDRSPACE_CAST:
  case G_UADDO:
  case G_USUBO:
  case G_UADDE:
  case G_USUBE:
  case G_SADDO:
  case G_SSUBO:
  case G_SADDE:
  case G_SSUBE:
  case G_STRICT_FADD:
  case G_STRICT_FSUB:
  case G_STRICT_FMUL:
  case G_STRICT_FMA:
  case G_STRICT_FLDEXP:
  case G_FFREXP:
  case G_TRUNC_SSAT_S:
  case G_TRUNC_SSAT_U:
  case G_TRUNC_USAT_U:
    return fewerElementsVectorMultiEltType(GMI, NumElts);
  case G_ICMP:
  case G_FCMP:
    return fewerElementsVectorMultiEltType(GMI, NumElts, {1 /*cpm predicate*/});
  case G_IS_FPCLASS:
    return fewerElementsVectorMultiEltType(GMI, NumElts, {2, 3 /*mask,fpsem*/});
  case G_SELECT:
    if (MRI.getType(MI.getOperand(1).getReg()).isVector())
      return fewerElementsVectorMultiEltType(GMI, NumElts);
    return fewerElementsVectorMultiEltType(GMI, NumElts, {1 /*scalar cond*/});
  case G_PHI:
    return fewerElementsVectorPhi(GMI, NumElts);
  case G_UNMERGE_VALUES:
    return fewerElementsVectorUnmergeValues(MI, TypeIdx, NarrowTy);
  case G_BUILD_VECTOR:
    assert(TypeIdx == 0 && "not a vector type index");
    return fewerElementsVectorMerge(MI, TypeIdx, NarrowTy);
  case G_CONCAT_VECTORS:
    if (TypeIdx != 1) // TODO: This probably does work as expected already.
      return UnableToLegalize;
    return fewerElementsVectorMerge(MI, TypeIdx, NarrowTy);
  case G_EXTRACT_VECTOR_ELT:
  case G_INSERT_VECTOR_ELT:
    return fewerElementsVectorExtractInsertVectorElt(MI, TypeIdx, NarrowTy);
  case G_LOAD:
  case G_STORE:
    return reduceLoadStoreWidth(cast<GLoadStore>(MI), TypeIdx, NarrowTy);
  case G_SEXT_INREG:
    return fewerElementsVectorMultiEltType(GMI, NumElts, {2 /*imm*/});
  GISEL_VECREDUCE_CASES_NONSEQ
    return fewerElementsVectorReductions(MI, TypeIdx, NarrowTy);
  case TargetOpcode::G_VECREDUCE_SEQ_FADD:
  case TargetOpcode::G_VECREDUCE_SEQ_FMUL:
    return fewerElementsVectorSeqReductions(MI, TypeIdx, NarrowTy);
  case G_SHUFFLE_VECTOR:
    return fewerElementsVectorShuffle(MI, TypeIdx, NarrowTy);
  case G_FPOWI:
    return fewerElementsVectorMultiEltType(GMI, NumElts, {2 /*pow*/});
  case G_BITCAST:
    return fewerElementsBitcast(MI, TypeIdx, NarrowTy);
  case G_INTRINSIC_FPTRUNC_ROUND:
    return fewerElementsVectorMultiEltType(GMI, NumElts, {2});
  default:
    return UnableToLegalize;
  }
}

LegalizerHelper::LegalizeResult
LegalizerHelper::fewerElementsBitcast(MachineInstr &MI, unsigned int TypeIdx,
                                      LLT NarrowTy) {
  assert(MI.getOpcode() == TargetOpcode::G_BITCAST &&
         "Not a bitcast operation");

  if (TypeIdx != 0)
    return UnableToLegalize;

  auto [DstReg, DstTy, SrcReg, SrcTy] = MI.getFirst2RegLLTs();

  unsigned NewElemCount =
      NarrowTy.getSizeInBits() / SrcTy.getScalarSizeInBits();
  SmallVector<Register> SrcVRegs, BitcastVRegs;
  if (NewElemCount == 1) {
    LLT SrcNarrowTy = SrcTy.getElementType();

    auto Unmerge = MIRBuilder.buildUnmerge(SrcNarrowTy, SrcReg);
    getUnmergeResults(SrcVRegs, *Unmerge);
  } else {
    LLT SrcNarrowTy =
        SrcTy.changeVectorElementCount(ElementCount::getFixed(NewElemCount));

    // Split the Src and Dst Reg into smaller registers
    if (extractGCDType(SrcVRegs, DstTy, SrcNarrowTy, SrcReg) != SrcNarrowTy)
      return UnableToLegalize;
  }

  // Build new smaller bitcast instructions
  // Not supporting Leftover types for now but will have to
  for (Register Reg : SrcVRegs)
    BitcastVRegs.push_back(MIRBuilder.buildBitcast(NarrowTy, Reg).getReg(0));

  MIRBuilder.buildMergeLikeInstr(DstReg, BitcastVRegs);
  MI.eraseFromParent();
  return Legalized;
}

LegalizerHelper::LegalizeResult LegalizerHelper::fewerElementsVectorShuffle(
    MachineInstr &MI, unsigned int TypeIdx, LLT NarrowTy) {
  assert(MI.getOpcode() == TargetOpcode::G_SHUFFLE_VECTOR);
  if (TypeIdx != 0)
    return UnableToLegalize;

  auto [DstReg, DstTy, Src1Reg, Src1Ty, Src2Reg, Src2Ty] =
      MI.getFirst3RegLLTs();
  ArrayRef<int> Mask = MI.getOperand(3).getShuffleMask();
  // The shuffle should be canonicalized by now.
  if (DstTy != Src1Ty)
    return UnableToLegalize;
  if (DstTy != Src2Ty)
    return UnableToLegalize;

  if (!isPowerOf2_32(DstTy.getNumElements()))
    return UnableToLegalize;

  // We only support splitting a shuffle into 2, so adjust NarrowTy accordingly.
  // Further legalization attempts will be needed to do split further.
  NarrowTy =
      DstTy.changeElementCount(DstTy.getElementCount().divideCoefficientBy(2));
  unsigned NewElts = NarrowTy.isVector() ? NarrowTy.getNumElements() : 1;

  SmallVector<Register> SplitSrc1Regs, SplitSrc2Regs;
  extractParts(Src1Reg, NarrowTy, 2, SplitSrc1Regs, MIRBuilder, MRI);
  extractParts(Src2Reg, NarrowTy, 2, SplitSrc2Regs, MIRBuilder, MRI);
  Register Inputs[4] = {SplitSrc1Regs[0], SplitSrc1Regs[1], SplitSrc2Regs[0],
                        SplitSrc2Regs[1]};

  Register Hi, Lo;

  // 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) {
    Register &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 = Mask[FirstMaskIdx + MaskOffset];

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

      if (Input >= std::size(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 < std::size(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 >= std::size(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) {
      LLT EltTy = NarrowTy.getElementType();
      SmallVector<Register, 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 = Mask[FirstMaskIdx + MaskOffset];

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

        if (Input >= std::size(Inputs)) {
          // The mask element is "undef" or indexes off the end of the input.
          SVOps.push_back(MIRBuilder.buildUndef(EltTy).getReg(0));
          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(MIRBuilder
                            .buildExtractVectorElement(
                                EltTy, Inputs[Input],
                                MIRBuilder.buildConstant(LLT::scalar(32), Idx))
                            .getReg(0));
      }

      // Construct the Lo/Hi output using a G_BUILD_VECTOR.
      Output = MIRBuilder.buildBuildVector(NarrowTy, SVOps).getReg(0);
    } else if (InputUsed[0] == -1U) {
      // No input vectors were used! The result is undefined.
      Output = MIRBuilder.buildUndef(NarrowTy).getReg(0);
    } else if (NewElts == 1) {
      Output = MIRBuilder.buildCopy(NarrowTy, Inputs[InputUsed[0]]).getReg(0);
    } else {
      Register Op0 = Inputs[InputUsed[0]];
      // If only one input was used, use an undefined vector for the other.
      Register Op1 = InputUsed[1] == -1U
                         ? MIRBuilder.buildUndef(NarrowTy).getReg(0)
                         : Inputs[InputUsed[1]];
      // At least one input vector was used. Create a new shuffle vector.
      Output = MIRBuilder.buildShuffleVector(NarrowTy, Op0, Op1, Ops).getReg(0);
    }

    Ops.clear();
  }

  MIRBuilder.buildMergeLikeInstr(DstReg, {Lo, Hi});
  MI.eraseFromParent();
  return Legalized;
}

LegalizerHelper::LegalizeResult LegalizerHelper::fewerElementsVectorReductions(
    MachineInstr &MI, unsigned int TypeIdx, LLT NarrowTy) {
  auto &RdxMI = cast<GVecReduce>(MI);

  if (TypeIdx != 1)
    return UnableToLegalize;

  // The semantics of the normal non-sequential reductions allow us to freely
  // re-associate the operation.
  auto [DstReg, DstTy, SrcReg, SrcTy] = RdxMI.getFirst2RegLLTs();

  if (NarrowTy.isVector() &&
      (SrcTy.getNumElements() % NarrowTy.getNumElements() != 0))
    return UnableToLegalize;

  unsigned ScalarOpc = RdxMI.getScalarOpcForReduction();
  SmallVector<Register> SplitSrcs;
  // If NarrowTy is a scalar then we're being asked to scalarize.
  const unsigned NumParts =
      NarrowTy.isVector() ? SrcTy.getNumElements() / NarrowTy.getNumElements()
                          : SrcTy.getNumElements();

  extractParts(SrcReg, NarrowTy, NumParts, SplitSrcs, MIRBuilder, MRI);
  if (NarrowTy.isScalar()) {
    if (DstTy != NarrowTy)
      return UnableToLegalize; // FIXME: handle implicit extensions.

    if (isPowerOf2_32(NumParts)) {
      // Generate a tree of scalar operations to reduce the critical path.
      SmallVector<Register> PartialResults;
      unsigned NumPartsLeft = NumParts;
      while (NumPartsLeft > 1) {
        for (unsigned Idx = 0; Idx < NumPartsLeft - 1; Idx += 2) {
          PartialResults.emplace_back(
              MIRBuilder
                  .buildInstr(ScalarOpc, {NarrowTy},
                              {SplitSrcs[Idx], SplitSrcs[Idx + 1]})
                  .getReg(0));
        }
        SplitSrcs = PartialResults;
        PartialResults.clear();
        NumPartsLeft = SplitSrcs.size();
      }
      assert(SplitSrcs.size() == 1);
      MIRBuilder.buildCopy(DstReg, SplitSrcs[0]);
      MI.eraseFromParent();
      return Legalized;
    }
    // If we can't generate a tree, then just do sequential operations.
    Register Acc = SplitSrcs[0];
    for (unsigned Idx = 1; Idx < NumParts; ++Idx)
      Acc = MIRBuilder.buildInstr(ScalarOpc, {NarrowTy}, {Acc, SplitSrcs[Idx]})
                .getReg(0);
    MIRBuilder.buildCopy(DstReg, Acc);
    MI.eraseFromParent();
    return Legalized;
  }
  SmallVector<Register> PartialReductions;
  for (unsigned Part = 0; Part < NumParts; ++Part) {
    PartialReductions.push_back(
        MIRBuilder.buildInstr(RdxMI.getOpcode(), {DstTy}, {SplitSrcs[Part]})
            .getReg(0));
  }

  // If the types involved are powers of 2, we can generate intermediate vector
  // ops, before generating a final reduction operation.
  if (isPowerOf2_32(SrcTy.getNumElements()) &&
      isPowerOf2_32(NarrowTy.getNumElements())) {
    return tryNarrowPow2Reduction(MI, SrcReg, SrcTy, NarrowTy, ScalarOpc);
  }

  Register Acc = PartialReductions[0];
  for (unsigned Part = 1; Part < NumParts; ++Part) {
    if (Part == NumParts - 1) {
      MIRBuilder.buildInstr(ScalarOpc, {DstReg},
                            {Acc, PartialReductions[Part]});
    } else {
      Acc = MIRBuilder
                .buildInstr(ScalarOpc, {DstTy}, {Acc, PartialReductions[Part]})
                .getReg(0);
    }
  }
  MI.eraseFromParent();
  return Legalized;
}

LegalizerHelper::LegalizeResult
LegalizerHelper::fewerElementsVectorSeqReductions(MachineInstr &MI,
                                                  unsigned int TypeIdx,
                                                  LLT NarrowTy) {
  auto [DstReg, DstTy, ScalarReg, ScalarTy, SrcReg, SrcTy] =
      MI.getFirst3RegLLTs();
  if (!NarrowTy.isScalar() || TypeIdx != 2 || DstTy != ScalarTy ||
      DstTy != NarrowTy)
    return UnableToLegalize;

  assert((MI.getOpcode() == TargetOpcode::G_VECREDUCE_SEQ_FADD ||
          MI.getOpcode() == TargetOpcode::G_VECREDUCE_SEQ_FMUL) &&
         "Unexpected vecreduce opcode");
  unsigned ScalarOpc = MI.getOpcode() == TargetOpcode::G_VECREDUCE_SEQ_FADD
                           ? TargetOpcode::G_FADD
                           : TargetOpcode::G_FMUL;

  SmallVector<Register> SplitSrcs;
  unsigned NumParts = SrcTy.getNumElements();
  extractParts(SrcReg, NarrowTy, NumParts, SplitSrcs, MIRBuilder, MRI);
  Register Acc = ScalarReg;
  for (unsigned i = 0; i < NumParts; i++)
    Acc = MIRBuilder.buildInstr(ScalarOpc, {NarrowTy}, {Acc, SplitSrcs[i]})
              .getReg(0);

  MIRBuilder.buildCopy(DstReg, Acc);
  MI.eraseFromParent();
  return Legalized;
}

LegalizerHelper::LegalizeResult
LegalizerHelper::tryNarrowPow2Reduction(MachineInstr &MI, Register SrcReg,
                                        LLT SrcTy, LLT NarrowTy,
                                        unsigned ScalarOpc) {
  SmallVector<Register> SplitSrcs;
  // Split the sources into NarrowTy size pieces.
  extractParts(SrcReg, NarrowTy,
               SrcTy.getNumElements() / NarrowTy.getNumElements(), SplitSrcs,
               MIRBuilder, MRI);
  // We're going to do a tree reduction using vector operations until we have
  // one NarrowTy size value left.
  while (SplitSrcs.size() > 1) {
    SmallVector<Register> PartialRdxs;
    for (unsigned Idx = 0; Idx < SplitSrcs.size()-1; Idx += 2) {
      Register LHS = SplitSrcs[Idx];
      Register RHS = SplitSrcs[Idx + 1];
      // Create the intermediate vector op.
      Register Res =
          MIRBuilder.buildInstr(ScalarOpc, {NarrowTy}, {LHS, RHS}).getReg(0);
      PartialRdxs.push_back(Res);
    }
    SplitSrcs = std::move(PartialRdxs);
  }
  // Finally generate the requested NarrowTy based reduction.
  Observer.changingInstr(MI);
  MI.getOperand(1).setReg(SplitSrcs[0]);
  Observer.changedInstr(MI);
  return Legalized;
}

LegalizerHelper::LegalizeResult
LegalizerHelper::narrowScalarShiftByConstant(MachineInstr &MI, const APInt &Amt,
                                             const LLT HalfTy, const LLT AmtTy) {

  Register InL = MRI.createGenericVirtualRegister(HalfTy);
  Register InH = MRI.createGenericVirtualRegister(HalfTy);
  MIRBuilder.buildUnmerge({InL, InH}, MI.getOperand(1));

  if (Amt.isZero()) {
    MIRBuilder.buildMergeLikeInstr(MI.getOperand(0), {InL, InH});
    MI.eraseFromParent();
    return Legalized;
  }

  LLT NVT = HalfTy;
  unsigned NVTBits = HalfTy.getSizeInBits();
  unsigned VTBits = 2 * NVTBits;

  SrcOp Lo(Register(0)), Hi(Register(0));
  if (MI.getOpcode() == TargetOpcode::G_SHL) {
    if (Amt.ugt(VTBits)) {
      Lo = Hi = MIRBuilder.buildConstant(NVT, 0);
    } else if (Amt.ugt(NVTBits)) {
      Lo = MIRBuilder.buildConstant(NVT, 0);
      Hi = MIRBuilder.buildShl(NVT, InL,
                               MIRBuilder.buildConstant(AmtTy, Amt - NVTBits));
    } else if (Amt == NVTBits) {
      Lo = MIRBuilder.buildConstant(NVT, 0);
      Hi = InL;
    } else {
      Lo = MIRBuilder.buildShl(NVT, InL, MIRBuilder.buildConstant(AmtTy, Amt));
      auto OrLHS =
          MIRBuilder.buildShl(NVT, InH, MIRBuilder.buildConstant(AmtTy, Amt));
      auto OrRHS = MIRBuilder.buildLShr(
          NVT, InL, MIRBuilder.buildConstant(AmtTy, -Amt + NVTBits));
      Hi = MIRBuilder.buildOr(NVT, OrLHS, OrRHS);
    }
  } else if (MI.getOpcode() == TargetOpcode::G_LSHR) {
    if (Amt.ugt(VTBits)) {
      Lo = Hi = MIRBuilder.buildConstant(NVT, 0);
    } else if (Amt.ugt(NVTBits)) {
      Lo = MIRBuilder.buildLShr(NVT, InH,
                                MIRBuilder.buildConstant(AmtTy, Amt - NVTBits));
      Hi = MIRBuilder.buildConstant(NVT, 0);
    } else if (Amt == NVTBits) {
      Lo = InH;
      Hi = MIRBuilder.buildConstant(NVT, 0);
    } else {
      auto ShiftAmtConst = MIRBuilder.buildConstant(AmtTy, Amt);

      auto OrLHS = MIRBuilder.buildLShr(NVT, InL, ShiftAmtConst);
      auto OrRHS = MIRBuilder.buildShl(
          NVT, InH, MIRBuilder.buildConstant(AmtTy, -Amt + NVTBits));

      Lo = MIRBuilder.buildOr(NVT, OrLHS, OrRHS);
      Hi = MIRBuilder.buildLShr(NVT, InH, ShiftAmtConst);
    }
  } else {
    if (Amt.ugt(VTBits)) {
      Hi = Lo = MIRBuilder.buildAShr(
          NVT, InH, MIRBuilder.buildConstant(AmtTy, NVTBits - 1));
    } else if (Amt.ugt(NVTBits)) {
      Lo = MIRBuilder.buildAShr(NVT, InH,
                                MIRBuilder.buildConstant(AmtTy, Amt - NVTBits));
      Hi = MIRBuilder.buildAShr(NVT, InH,
                                MIRBuilder.buildConstant(AmtTy, NVTBits - 1));
    } else if (Amt == NVTBits) {
      Lo = InH;
      Hi = MIRBuilder.buildAShr(NVT, InH,
                                MIRBuilder.buildConstant(AmtTy, NVTBits - 1));
    } else {
      auto ShiftAmtConst = MIRBuilder.buildConstant(AmtTy, Amt);

      auto OrLHS = MIRBuilder.buildLShr(NVT, InL, ShiftAmtConst);
      auto OrRHS = MIRBuilder.buildShl(
          NVT, InH, MIRBuilder.buildConstant(AmtTy, -Amt + NVTBits));

      Lo = MIRBuilder.buildOr(NVT, OrLHS, OrRHS);
      Hi = MIRBuilder.buildAShr(NVT, InH, ShiftAmtConst);
    }
  }

  MIRBuilder.buildMergeLikeInstr(MI.getOperand(0), {Lo, Hi});
  MI.eraseFromParent();

  return Legalized;
}

LegalizerHelper::LegalizeResult
LegalizerHelper::narrowScalarShift(MachineInstr &MI, unsigned TypeIdx,
                                   LLT RequestedTy) {
  if (TypeIdx == 1) {
    Observer.changingInstr(MI);
    narrowScalarSrc(MI, RequestedTy, 2);
    Observer.changedInstr(MI);
    return Legalized;
  }

  Register DstReg = MI.getOperand(0).getReg();
  LLT DstTy = MRI.getType(DstReg);
  if (DstTy.isVector())
    return UnableToLegalize;

  Register Amt = MI.getOperand(2).getReg();
  LLT ShiftAmtTy = MRI.getType(Amt);
  const unsigned DstEltSize = DstTy.getScalarSizeInBits();
  if (DstEltSize % 2 != 0)
    return UnableToLegalize;

  // Check if we should use multi-way splitting instead of recursive binary
  // splitting.
  //
  // Multi-way splitting directly decomposes wide shifts (e.g., 128-bit ->
  // 4×32-bit) in a single legalization step, avoiding the recursive overhead
  // and dependency chains created by usual binary splitting approach
  // (128->64->32).
  //
  // The >= 8 parts threshold ensures we only use this optimization when binary
  // splitting would require multiple recursive passes, avoiding overhead for
  // simple 2-way splits where binary approach is sufficient.
  if (RequestedTy.isValid() && RequestedTy.isScalar() &&
      DstEltSize % RequestedTy.getSizeInBits() == 0) {
    const unsigned NumParts = DstEltSize / RequestedTy.getSizeInBits();
    // Use multiway if we have 8 or more parts (i.e., would need 3+ recursive
    // steps).
    if (NumParts >= 8)
      return narrowScalarShiftMultiway(MI, RequestedTy);
  }

  // Fall back to binary splitting:
  // Ignore the input type. We can only go to exactly half the size of the
  // input. If that isn't small enough, the resulting pieces will be further
  // legalized.
  const unsigned NewBitSize = DstEltSize / 2;
  const LLT HalfTy = DstTy.getScalarType().changeElementSize(NewBitSize);
  const LLT CondTy = LLT::integer(1);

  if (auto VRegAndVal = getIConstantVRegValWithLookThrough(Amt, MRI)) {
    return narrowScalarShiftByConstant(MI, VRegAndVal->Value, HalfTy,
                                       ShiftAmtTy);
  }

  // TODO: Expand with known bits.

  // Handle the fully general expansion by an unknown amount.
  auto NewBits = MIRBuilder.buildConstant(ShiftAmtTy, NewBitSize);

  Register InL = MRI.createGenericVirtualRegister(HalfTy);
  Register InH = MRI.createGenericVirtualRegister(HalfTy);
  MIRBuilder.buildUnmerge({InL, InH}, MI.getOperand(1));

  auto AmtExcess = MIRBuilder.buildSub(ShiftAmtTy, Amt, NewBits);
  auto AmtLack = MIRBuilder.buildSub(ShiftAmtTy, NewBits, Amt);

  auto Zero = MIRBuilder.buildConstant(ShiftAmtTy, 0);
  auto IsShort = MIRBuilder.buildICmp(ICmpInst::ICMP_ULT, CondTy, Amt, NewBits);
  auto IsZero = MIRBuilder.buildICmp(ICmpInst::ICMP_EQ, CondTy, Amt, Zero);

  Register ResultRegs[2];
  switch (MI.getOpcode()) {
  case TargetOpcode::G_SHL: {
    // Short: ShAmt < NewBitSize
    auto LoS = MIRBuilder.buildShl(HalfTy, InL, Amt);

    auto LoOr = MIRBuilder.buildLShr(HalfTy, InL, AmtLack);
    auto HiOr = MIRBuilder.buildShl(HalfTy, InH, Amt);
    auto HiS = MIRBuilder.buildOr(HalfTy, LoOr, HiOr);

    // Long: ShAmt >= NewBitSize
    auto LoL = MIRBuilder.buildConstant(HalfTy, 0);         // Lo part is zero.
    auto HiL = MIRBuilder.buildShl(HalfTy, InL, AmtExcess); // Hi from Lo part.

    auto Lo = MIRBuilder.buildSelect(HalfTy, IsShort, LoS, LoL);
    auto Hi = MIRBuilder.buildSelect(
        HalfTy, IsZero, InH, MIRBuilder.buildSelect(HalfTy, IsShort, HiS, HiL));

    ResultRegs[0] = Lo.getReg(0);
    ResultRegs[1] = Hi.getReg(0);
    break;
  }
  case TargetOpcode::G_LSHR:
  case TargetOpcode::G_ASHR: {
    // Short: ShAmt < NewBitSize
    auto HiS = MIRBuilder.buildInstr(MI.getOpcode(), {HalfTy}, {InH, Amt});

    auto LoOr = MIRBuilder.buildLShr(HalfTy, InL, Amt);
    auto HiOr = MIRBuilder.buildShl(HalfTy, InH, AmtLack);
    auto LoS = MIRBuilder.buildOr(HalfTy, LoOr, HiOr);

    // Long: ShAmt >= NewBitSize
    MachineInstrBuilder HiL;
    if (MI.getOpcode() == TargetOpcode::G_LSHR) {
      HiL = MIRBuilder.buildConstant(HalfTy, 0);            // Hi part is zero.
    } else {
      auto ShiftAmt = MIRBuilder.buildConstant(ShiftAmtTy, NewBitSize - 1);
      HiL = MIRBuilder.buildAShr(HalfTy, InH, ShiftAmt);    // Sign of Hi part.
    }
    auto LoL = MIRBuilder.buildInstr(MI.getOpcode(), {HalfTy},
                                     {InH, AmtExcess});     // Lo from Hi part.

    auto Lo = MIRBuilder.buildSelect(
        HalfTy, IsZero, InL, MIRBuilder.buildSelect(HalfTy, IsShort, LoS, LoL));

    auto Hi = MIRBuilder.buildSelect(HalfTy, IsShort, HiS, HiL);

    ResultRegs[0] = Lo.getReg(0);
    ResultRegs[1] = Hi.getReg(0);
    break;
  }
  default:
    llvm_unreachable("not a shift");
  }

  MIRBuilder.buildMergeLikeInstr(DstReg, ResultRegs);
  MI.eraseFromParent();
  return Legalized;
}

Register LegalizerHelper::buildConstantShiftPart(unsigned Opcode,
                                                 unsigned PartIdx,
                                                 unsigned NumParts,
                                                 ArrayRef<Register> SrcParts,
                                                 const ShiftParams &Params,
                                                 LLT TargetTy, LLT ShiftAmtTy) {
  auto WordShiftConst = getIConstantVRegVal(Params.WordShift, MRI);
  auto BitShiftConst = getIConstantVRegVal(Params.BitShift, MRI);
  assert(WordShiftConst && BitShiftConst && "Expected constants");

  const unsigned ShiftWords = WordShiftConst->getZExtValue();
  const unsigned ShiftBits = BitShiftConst->getZExtValue();
  const bool NeedsInterWordShift = ShiftBits != 0;

  switch (Opcode) {
  case TargetOpcode::G_SHL: {
    // Data moves from lower indices to higher indices
    // If this part would come from a source beyond our range, it's zero
    if (PartIdx < ShiftWords)
      return Params.Zero;

    unsigned SrcIdx = PartIdx - ShiftWords;
    if (!NeedsInterWordShift)
      return SrcParts[SrcIdx];

    // Combine shifted main part with carry from previous part
    auto Hi = MIRBuilder.buildShl(TargetTy, SrcParts[SrcIdx], Params.BitShift);
    if (SrcIdx > 0) {
      auto Lo = MIRBuilder.buildLShr(TargetTy, SrcParts[SrcIdx - 1],
                                     Params.InvBitShift);
      return MIRBuilder.buildOr(TargetTy, Hi, Lo).getReg(0);
    }
    return Hi.getReg(0);
  }

  case TargetOpcode::G_LSHR: {
    unsigned SrcIdx = PartIdx + ShiftWords;
    if (SrcIdx >= NumParts)
      return Params.Zero;
    if (!NeedsInterWordShift)
      return SrcParts[SrcIdx];

    // Combine shifted main part with carry from next part
    auto Lo = MIRBuilder.buildLShr(TargetTy, SrcParts[SrcIdx], Params.BitShift);
    if (SrcIdx + 1 < NumParts) {
      auto Hi = MIRBuilder.buildShl(TargetTy, SrcParts[SrcIdx + 1],
                                    Params.InvBitShift);
      return MIRBuilder.buildOr(TargetTy, Lo, Hi).getReg(0);
    }
    return Lo.getReg(0);
  }

  case TargetOpcode::G_ASHR: {
    // Like LSHR but preserves sign bit
    unsigned SrcIdx = PartIdx + ShiftWords;
    if (SrcIdx >= NumParts)
      return Params.SignBit;
    if (!NeedsInterWordShift)
      return SrcParts[SrcIdx];

    // Only the original MSB part uses arithmetic shift to preserve sign. All
    // other parts use logical shift since they're just moving data bits.
    auto Lo =
        (SrcIdx == NumParts - 1)
            ? MIRBuilder.buildAShr(TargetTy, SrcParts[SrcIdx], Params.BitShift)
            : MIRBuilder.buildLShr(TargetTy, SrcParts[SrcIdx], Params.BitShift);
    Register HiSrc =
        (SrcIdx + 1 < NumParts) ? SrcParts[SrcIdx + 1] : Params.SignBit;
    auto Hi = MIRBuilder.buildShl(TargetTy, HiSrc, Params.InvBitShift);
    return MIRBuilder.buildOr(TargetTy, Lo, Hi).getReg(0);
  }

  default:
    llvm_unreachable("not a shift");
  }
}

Register LegalizerHelper::buildVariableShiftPart(unsigned Opcode,
                                                 Register MainOperand,
                                                 Register ShiftAmt,
                                                 LLT TargetTy,
                                                 Register CarryOperand) {
  // This helper generates a single output part for variable shifts by combining
  // the main operand (shifted by BitShift) with carry bits from an adjacent
  // part.

  // For G_ASHR, individual parts don't have their own sign bit, only the
  // complete value does. So we use LSHR for the main operand shift in ASHR
  // context.
  unsigned MainOpcode = (Opcode == TargetOpcode::G_ASHR)
                            ? static_cast<unsigned>(TargetOpcode::G_LSHR)
                            : Opcode;

  // Perform the primary shift on the main operand
  Register MainShifted =
      MIRBuilder.buildInstr(MainOpcode, {TargetTy}, {MainOperand, ShiftAmt})
          .getReg(0);

  // No carry operand available
  if (!CarryOperand.isValid())
    return MainShifted;

  // If BitShift is 0 (word-aligned shift), no inter-word bit movement occurs,
  // so carry bits aren't needed.
  LLT ShiftAmtTy = MRI.getType(ShiftAmt);
  auto ZeroConst = MIRBuilder.buildConstant(ShiftAmtTy, 0);
  LLT BoolTy = LLT::scalar(1);
  auto IsZeroBitShift =
      MIRBuilder.buildICmp(ICmpInst::ICMP_EQ, BoolTy, ShiftAmt, ZeroConst);

  // Extract bits from the adjacent part that will "carry over" into this part.
  // The carry direction is opposite to the main shift direction, so we can
  // align the two shifted values before combining them with OR.

  // Determine the carry shift opcode (opposite direction)
  unsigned CarryOpcode = (Opcode == TargetOpcode::G_SHL) ? TargetOpcode::G_LSHR
                                                         : TargetOpcode::G_SHL;

  // Calculate inverse shift amount: BitWidth - ShiftAmt
  auto TargetBitsConst =
      MIRBuilder.buildConstant(ShiftAmtTy, TargetTy.getScalarSizeInBits());
  auto InvShiftAmt = MIRBuilder.buildSub(ShiftAmtTy, TargetBitsConst, ShiftAmt);

  // Shift the carry operand
  Register CarryBits =
      MIRBuilder
          .buildInstr(CarryOpcode, {TargetTy}, {CarryOperand, InvShiftAmt})
          .getReg(0);

  // If BitShift is 0, don't include carry bits (InvShiftAmt would equal
  // TargetBits which would be poison for the individual carry shift operation).
  auto ZeroReg = MIRBuilder.buildConstant(TargetTy, 0);
  Register SafeCarryBits =
      MIRBuilder.buildSelect(TargetTy, IsZeroBitShift, ZeroReg, CarryBits)
          .getReg(0);

  // Combine the main shifted part with the carry bits
  return MIRBuilder.buildOr(TargetTy, MainShifted, SafeCarryBits).getReg(0);
}

LegalizerHelper::LegalizeResult
LegalizerHelper::narrowScalarShiftByConstantMultiway(MachineInstr &MI,
                                                     const APInt &Amt,
                                                     LLT TargetTy,
                                                     LLT ShiftAmtTy) {
  // Any wide shift can be decomposed into WordShift + BitShift components.
  // When shift amount is known constant, directly compute the decomposition
  // values and generate constant registers.
  Register DstReg = MI.getOperand(0).getReg();
  Register SrcReg = MI.getOperand(1).getReg();
  LLT DstTy = MRI.getType(DstReg);

  const unsigned DstBits = DstTy.getScalarSizeInBits();
  const unsigned TargetBits = TargetTy.getScalarSizeInBits();
  const unsigned NumParts = DstBits / TargetBits;

  assert(DstBits % TargetBits == 0 && "Target type must evenly divide source");

  // When the shift amount is known at compile time, we just calculate which
  // source parts contribute to each output part.

  SmallVector<Register, 8> SrcParts;
  extractParts(SrcReg, TargetTy, NumParts, SrcParts, MIRBuilder, MRI);

  if (Amt.isZero()) {
    // No shift needed, just copy
    MIRBuilder.buildMergeLikeInstr(DstReg, SrcParts);
    MI.eraseFromParent();
    return Legalized;
  }

  ShiftParams Params;
  const unsigned ShiftWords = Amt.getZExtValue() / TargetBits;
  const unsigned ShiftBits = Amt.getZExtValue() % TargetBits;

  // Generate constants and values needed by all shift types
  Params.WordShift = MIRBuilder.buildConstant(ShiftAmtTy, ShiftWords).getReg(0);
  Params.BitShift = MIRBuilder.buildConstant(ShiftAmtTy, ShiftBits).getReg(0);
  Params.InvBitShift =
      MIRBuilder.buildConstant(ShiftAmtTy, TargetBits - ShiftBits).getReg(0);
  Params.Zero = MIRBuilder.buildConstant(TargetTy, 0).getReg(0);

  // For ASHR, we need the sign-extended value to fill shifted-out positions
  if (MI.getOpcode() == TargetOpcode::G_ASHR)
    Params.SignBit =
        MIRBuilder
            .buildAShr(TargetTy, SrcParts[SrcParts.size() - 1],
                       MIRBuilder.buildConstant(ShiftAmtTy, TargetBits - 1))
            .getReg(0);

  SmallVector<Register, 8> DstParts(NumParts);
  for (unsigned I = 0; I < NumParts; ++I)
    DstParts[I] = buildConstantShiftPart(MI.getOpcode(), I, NumParts, SrcParts,
                                         Params, TargetTy, ShiftAmtTy);

  MIRBuilder.buildMergeLikeInstr(DstReg, DstParts);
  MI.eraseFromParent();
  return Legalized;
}

LegalizerHelper::LegalizeResult
LegalizerHelper::narrowScalarShiftMultiway(MachineInstr &MI, LLT TargetTy) {
  Register DstReg = MI.getOperand(0).getReg();
  Register SrcReg = MI.getOperand(1).getReg();
  Register AmtReg = MI.getOperand(2).getReg();
  LLT DstTy = MRI.getType(DstReg);
  LLT ShiftAmtTy = MRI.getType(AmtReg);

  const unsigned DstBits = DstTy.getScalarSizeInBits();
  const unsigned TargetBits = TargetTy.getScalarSizeInBits();
  const unsigned NumParts = DstBits / TargetBits;

  assert(DstBits % TargetBits == 0 && "Target type must evenly divide source");
  assert(isPowerOf2_32(TargetBits) && "Target bit width must be power of 2");

  // If the shift amount is known at compile time, we can use direct indexing
  // instead of generating select chains in the general case.
  if (auto VRegAndVal = getIConstantVRegValWithLookThrough(AmtReg, MRI))
    return narrowScalarShiftByConstantMultiway(MI, VRegAndVal->Value, TargetTy,
                                               ShiftAmtTy);

  // For runtime-variable shift amounts, we must generate a more complex
  // sequence that handles all possible shift values using select chains.

  // Split the input into target-sized pieces
  SmallVector<Register, 8> SrcParts;
  extractParts(SrcReg, TargetTy, NumParts, SrcParts, MIRBuilder, MRI);

  // Shifting by zero should be a no-op.
  auto ZeroAmtConst = MIRBuilder.buildConstant(ShiftAmtTy, 0);
  LLT BoolTy = LLT::scalar(1);
  auto IsZeroShift =
      MIRBuilder.buildICmp(ICmpInst::ICMP_EQ, BoolTy, AmtReg, ZeroAmtConst);

  // Any wide shift can be decomposed into two components:
  // 1. WordShift: number of complete target-sized words to shift
  // 2. BitShift: number of bits to shift within each word
  //
  // Example: 128-bit >> 50 with 32-bit target:
  //   WordShift = 50 / 32 = 1 (shift right by 1 complete word)
  //   BitShift = 50 % 32 = 18 (shift each word right by 18 bits)
  unsigned TargetBitsLog2 = Log2_32(TargetBits);
  auto TargetBitsLog2Const =
      MIRBuilder.buildConstant(ShiftAmtTy, TargetBitsLog2);
  auto TargetBitsMask = MIRBuilder.buildConstant(ShiftAmtTy, TargetBits - 1);

  Register WordShift =
      MIRBuilder.buildLShr(ShiftAmtTy, AmtReg, TargetBitsLog2Const).getReg(0);
  Register BitShift =
      MIRBuilder.buildAnd(ShiftAmtTy, AmtReg, TargetBitsMask).getReg(0);

  // Fill values:
  // - SHL/LSHR: fill with zeros
  // - ASHR: fill with sign-extended MSB
  Register ZeroReg = MIRBuilder.buildConstant(TargetTy, 0).getReg(0);

  Register FillValue;
  if (MI.getOpcode() == TargetOpcode::G_ASHR) {
    auto TargetBitsMinusOneConst =
        MIRBuilder.buildConstant(ShiftAmtTy, TargetBits - 1);
    FillValue = MIRBuilder
                    .buildAShr(TargetTy, SrcParts[NumParts - 1],
                               TargetBitsMinusOneConst)
                    .getReg(0);
  } else {
    FillValue = ZeroReg;
  }

  SmallVector<Register, 8> DstParts(NumParts);

  // For each output part, generate a select chain that chooses the correct
  // result based on the runtime WordShift value. This handles all possible
  // word shift amounts by pre-calculating what each would produce.
  for (unsigned I = 0; I < NumParts; ++I) {
    // Initialize with appropriate default value for this shift type
    Register InBoundsResult = FillValue;

    // clang-format off
    // Build a branchless select chain by pre-computing results for all possible
    // WordShift values (0 to NumParts-1). Each iteration nests a new select:
    //
    // K=0: select(WordShift==0, result0, FillValue)
    // K=1: select(WordShift==1, result1, select(WordShift==0, result0, FillValue))
    // K=2: select(WordShift==2, result2, select(WordShift==1, result1, select(...)))
    // clang-format on
    for (unsigned K = 0; K < NumParts; ++K) {
      auto WordShiftKConst = MIRBuilder.buildConstant(ShiftAmtTy, K);
      auto IsWordShiftK = MIRBuilder.buildICmp(ICmpInst::ICMP_EQ, BoolTy,
                                               WordShift, WordShiftKConst);

      // Calculate source indices for this word shift
      //
      // For 4-part 128-bit value with K=1 word shift:
      // SHL:  [3][2][1][0] << K  =>  [2][1][0][Z]
      //     -> (MainIdx = I-K, CarryIdx = I-K-1)
      // LSHR: [3][2][1][0] >> K  =>  [Z][3][2][1]
      //     -> (MainIdx = I+K, CarryIdx = I+K+1)
      int MainSrcIdx;
      int CarrySrcIdx; // Index for the word that provides the carried-in bits.

      switch (MI.getOpcode()) {
      case TargetOpcode::G_SHL:
        MainSrcIdx = (int)I - (int)K;
        CarrySrcIdx = MainSrcIdx - 1;
        break;
      case TargetOpcode::G_LSHR:
      case TargetOpcode::G_ASHR:
        MainSrcIdx = (int)I + (int)K;
        CarrySrcIdx = MainSrcIdx + 1;
        break;
      default:
        llvm_unreachable("Not a shift");
      }

      // Check bounds and build the result for this word shift
      Register ResultForK;
      if (MainSrcIdx >= 0 && MainSrcIdx < (int)NumParts) {
        Register MainOp = SrcParts[MainSrcIdx];
        Register CarryOp;

        // Determine carry operand with bounds checking
        if (CarrySrcIdx >= 0 && CarrySrcIdx < (int)NumParts)
          CarryOp = SrcParts[CarrySrcIdx];
        else if (MI.getOpcode() == TargetOpcode::G_ASHR &&
                 CarrySrcIdx >= (int)NumParts)
          CarryOp = FillValue; // Use sign extension

        ResultForK = buildVariableShiftPart(MI.getOpcode(), MainOp, BitShift,
                                            TargetTy, CarryOp);
      } else {
        // Out of bounds - use fill value for this k
        ResultForK = FillValue;
      }

      // Select this result if WordShift equals k
      InBoundsResult =
          MIRBuilder
              .buildSelect(TargetTy, IsWordShiftK, ResultForK, InBoundsResult)
              .getReg(0);
    }

    // Handle zero-shift special case: if shift is 0, use original input
    DstParts[I] =
        MIRBuilder
            .buildSelect(TargetTy, IsZeroShift, SrcParts[I], InBoundsResult)
            .getReg(0);
  }

  MIRBuilder.buildMergeLikeInstr(DstReg, DstParts);
  MI.eraseFromParent();
  return Legalized;
}

LegalizerHelper::LegalizeResult
LegalizerHelper::moreElementsVectorPhi(MachineInstr &MI, unsigned TypeIdx,
                                       LLT MoreTy) {
  assert(TypeIdx == 0 && "Expecting only Idx 0");

  Observer.changingInstr(MI);
  for (unsigned I = 1, E = MI.getNumOperands(); I != E; I += 2) {
    MachineBasicBlock &OpMBB = *MI.getOperand(I + 1).getMBB();
    MIRBuilder.setInsertPt(OpMBB, OpMBB.getFirstTerminator());
    moreElementsVectorSrc(MI, MoreTy, I);
  }

  MachineBasicBlock &MBB = *MI.getParent();
  MIRBuilder.setInsertPt(MBB, --MBB.getFirstNonPHI());
  moreElementsVectorDst(MI, MoreTy, 0);
  Observer.changedInstr(MI);
  return Legalized;
}

MachineInstrBuilder LegalizerHelper::getNeutralElementForVecReduce(
    unsigned Opcode, MachineIRBuilder &MIRBuilder, LLT Ty) {
  assert(Ty.isScalar() && "Expected scalar type to make neutral element for");

  switch (Opcode) {
  default:
    llvm_unreachable(
        "getNeutralElementForVecReduce called with invalid opcode!");
  case TargetOpcode::G_VECREDUCE_ADD:
  case TargetOpcode::G_VECREDUCE_OR:
  case TargetOpcode::G_VECREDUCE_XOR:
  case TargetOpcode::G_VECREDUCE_UMAX:
    return MIRBuilder.buildConstant(Ty, 0);
  case TargetOpcode::G_VECREDUCE_MUL:
    return MIRBuilder.buildConstant(Ty, 1);
  case TargetOpcode::G_VECREDUCE_AND:
  case TargetOpcode::G_VECREDUCE_UMIN:
    return MIRBuilder.buildConstant(
        Ty, APInt::getAllOnes(Ty.getScalarSizeInBits()));
  case TargetOpcode::G_VECREDUCE_SMAX:
    return MIRBuilder.buildConstant(
        Ty, APInt::getSignedMinValue(Ty.getSizeInBits()));
  case TargetOpcode::G_VECREDUCE_SMIN:
    return MIRBuilder.buildConstant(
        Ty, APInt::getSignedMaxValue(Ty.getSizeInBits()));
  case TargetOpcode::G_VECREDUCE_FADD:
    return MIRBuilder.buildFConstant(Ty, -0.0);
  case TargetOpcode::G_VECREDUCE_FMUL:
    return MIRBuilder.buildFConstant(Ty, 1.0);
  case TargetOpcode::G_VECREDUCE_FMINIMUM:
  case TargetOpcode::G_VECREDUCE_FMAXIMUM:
    assert(false && "getNeutralElementForVecReduce unimplemented for "
                    "G_VECREDUCE_FMINIMUM and G_VECREDUCE_FMAXIMUM!");
  }
  llvm_unreachable("switch expected to return!");
}

LegalizerHelper::LegalizeResult
LegalizerHelper::moreElementsVector(MachineInstr &MI, unsigned TypeIdx,
                                    LLT MoreTy) {
  unsigned Opc = MI.getOpcode();
  switch (Opc) {
  case TargetOpcode::G_IMPLICIT_DEF:
  case TargetOpcode::G_LOAD: {
    if (TypeIdx != 0)
      return UnableToLegalize;
    Observer.changingInstr(MI);
    moreElementsVectorDst(MI, MoreTy, 0);
    Observer.changedInstr(MI);
    return Legalized;
  }
  case TargetOpcode::G_STORE:
    if (TypeIdx != 0)
      return UnableToLegalize;
    Observer.changingInstr(MI);
    moreElementsVectorSrc(MI, MoreTy, 0);
    Observer.changedInstr(MI);
    return Legalized;
  case TargetOpcode::G_AND:
  case TargetOpcode::G_OR:
  case TargetOpcode::G_XOR:
  case TargetOpcode::G_ADD:
  case TargetOpcode::G_SUB:
  case TargetOpcode::G_MUL:
  case TargetOpcode::G_FADD:
  case TargetOpcode::G_FSUB:
  case TargetOpcode::G_FMUL:
  case TargetOpcode::G_FDIV:
  case TargetOpcode::G_FCOPYSIGN:
  case TargetOpcode::G_UADDSAT:
  case TargetOpcode::G_USUBSAT:
  case TargetOpcode::G_SADDSAT:
  case TargetOpcode::G_SSUBSAT:
  case TargetOpcode::G_SMIN:
  case TargetOpcode::G_SMAX:
  case TargetOpcode::G_UMIN:
  case TargetOpcode::G_UMAX:
  case TargetOpcode::G_FMINNUM:
  case TargetOpcode::G_FMAXNUM:
  case TargetOpcode::G_FMINNUM_IEEE:
  case TargetOpcode::G_FMAXNUM_IEEE:
  case TargetOpcode::G_FMINIMUM:
  case TargetOpcode::G_FMAXIMUM:
  case TargetOpcode::G_FMINIMUMNUM:
  case TargetOpcode::G_FMAXIMUMNUM:
  case TargetOpcode::G_STRICT_FADD:
  case TargetOpcode::G_STRICT_FSUB:
  case TargetOpcode::G_STRICT_FMUL: {
    Observer.changingInstr(MI);
    moreElementsVectorSrc(MI, MoreTy, 1);
    moreElementsVectorSrc(MI, MoreTy, 2);
    moreElementsVectorDst(MI, MoreTy, 0);
    Observer.changedInstr(MI);
    return Legalized;
  }
  case TargetOpcode::G_SHL:
  case TargetOpcode::G_ASHR:
  case TargetOpcode::G_LSHR: {
    Observer.changingInstr(MI);
    moreElementsVectorSrc(MI, MoreTy, 1);
    // The shift operand may have a different scalar type from the source and
    // destination operands.
    LLT ShiftMoreTy = MoreTy.changeElementType(
        MRI.getType(MI.getOperand(2).getReg()).getElementType());
    moreElementsVectorSrc(MI, ShiftMoreTy, 2);
    moreElementsVectorDst(MI, MoreTy, 0);
    Observer.changedInstr(MI);
    return Legalized;
  }
  case TargetOpcode::G_FMA:
  case TargetOpcode::G_STRICT_FMA:
  case TargetOpcode::G_FSHR:
  case TargetOpcode::G_FSHL: {
    Observer.changingInstr(MI);
    moreElementsVectorSrc(MI, MoreTy, 1);
    moreElementsVectorSrc(MI, MoreTy, 2);
    moreElementsVectorSrc(MI, MoreTy, 3);
    moreElementsVectorDst(MI, MoreTy, 0);
    Observer.changedInstr(MI);
    return Legalized;
  }
  case TargetOpcode::G_EXTRACT_VECTOR_ELT:
  case TargetOpcode::G_EXTRACT:
    if (TypeIdx != 1)
      return UnableToLegalize;
    Observer.changingInstr(MI);
    moreElementsVectorSrc(MI, MoreTy, 1);
    Observer.changedInstr(MI);
    return Legalized;
  case TargetOpcode::G_INSERT:
  case TargetOpcode::G_INSERT_VECTOR_ELT:
  case TargetOpcode::G_FREEZE:
  case TargetOpcode::G_FNEG:
  case TargetOpcode::G_FABS:
  case TargetOpcode::G_FSQRT:
  case TargetOpcode::G_FCEIL:
  case TargetOpcode::G_FFLOOR:
  case TargetOpcode::G_FNEARBYINT:
  case TargetOpcode::G_FRINT:
  case TargetOpcode::G_INTRINSIC_ROUND:
  case TargetOpcode::G_INTRINSIC_ROUNDEVEN:
  case TargetOpcode::G_INTRINSIC_TRUNC:
  case TargetOpcode::G_BITREVERSE:
  case TargetOpcode::G_BSWAP:
  case TargetOpcode::G_FCANONICALIZE:
  case TargetOpcode::G_SEXT_INREG:
  case TargetOpcode::G_ABS:
  case TargetOpcode::G_CTLZ:
  case TargetOpcode::G_CTPOP:
    if (TypeIdx != 0)
      return UnableToLegalize;
    Observer.changingInstr(MI);
    moreElementsVectorSrc(MI, MoreTy, 1);
    moreElementsVectorDst(MI, MoreTy, 0);
    Observer.changedInstr(MI);
    return Legalized;
  case TargetOpcode::G_SELECT: {
    auto [DstReg, DstTy, CondReg, CondTy] = MI.getFirst2RegLLTs();
    if (TypeIdx == 1) {
      if (!CondTy.isScalar() ||
          DstTy.getElementCount() != MoreTy.getElementCount())
        return UnableToLegalize;

      // This is turning a scalar select of vectors into a vector
      // select. Broadcast the select condition.
      auto ShufSplat = MIRBuilder.buildShuffleSplat(MoreTy, CondReg);
      Observer.changingInstr(MI);
      MI.getOperand(1).setReg(ShufSplat.getReg(0));
      Observer.changedInstr(MI);
      return Legalized;
    }

    if (CondTy.isVector())
      return UnableToLegalize;

    Observer.changingInstr(MI);
    moreElementsVectorSrc(MI, MoreTy, 2);
    moreElementsVectorSrc(MI, MoreTy, 3);
    moreElementsVectorDst(MI, MoreTy, 0);
    Observer.changedInstr(MI);
    return Legalized;
  }
  case TargetOpcode::G_UNMERGE_VALUES:
    return UnableToLegalize;
  case TargetOpcode::G_PHI:
    return moreElementsVectorPhi(MI, TypeIdx, MoreTy);
  case TargetOpcode::G_SHUFFLE_VECTOR:
    return moreElementsVectorShuffle(MI, TypeIdx, MoreTy);
  case TargetOpcode::G_BUILD_VECTOR: {
    SmallVector<SrcOp, 8> Elts;
    for (auto Op : MI.uses()) {
      Elts.push_back(Op.getReg());
    }

    for (unsigned i = Elts.size(); i < MoreTy.getNumElements(); ++i) {
      Elts.push_back(MIRBuilder.buildUndef(MoreTy.getScalarType()));
    }

    MIRBuilder.buildDeleteTrailingVectorElements(
        MI.getOperand(0).getReg(), MIRBuilder.buildInstr(Opc, {MoreTy}, Elts));
    MI.eraseFromParent();
    return Legalized;
  }
  case TargetOpcode::G_SEXT:
  case TargetOpcode::G_ZEXT:
  case TargetOpcode::G_ANYEXT:
  case TargetOpcode::G_TRUNC:
  case TargetOpcode::G_FPTRUNC:
  case TargetOpcode::G_FPEXT:
  case TargetOpcode::G_FPTOSI:
  case TargetOpcode::G_FPTOUI:
  case TargetOpcode::G_FPTOSI_SAT:
  case TargetOpcode::G_FPTOUI_SAT:
  case TargetOpcode::G_SITOFP:
  case TargetOpcode::G_UITOFP: {
    Observer.changingInstr(MI);
    LLT SrcExtTy;
    LLT DstExtTy;
    if (TypeIdx == 0) {
      DstExtTy = MoreTy;
      SrcExtTy = MoreTy.changeElementType(
          MRI.getType(MI.getOperand(1).getReg()).getElementType());
    } else {
      DstExtTy = MoreTy.changeElementType(
          MRI.getType(MI.getOperand(0).getReg()).getElementType());
      SrcExtTy = MoreTy;
    }
    moreElementsVectorSrc(MI, SrcExtTy, 1);
    moreElementsVectorDst(MI, DstExtTy, 0);
    Observer.changedInstr(MI);
    return Legalized;
  }
  case TargetOpcode::G_ICMP:
  case TargetOpcode::G_FCMP: {
    if (TypeIdx != 1)
      return UnableToLegalize;

    Observer.changingInstr(MI);
    moreElementsVectorSrc(MI, MoreTy, 2);
    moreElementsVectorSrc(MI, MoreTy, 3);
    LLT CondTy = MoreTy.changeVectorElementType(
        MRI.getType(MI.getOperand(0).getReg()).getElementType());
    moreElementsVectorDst(MI, CondTy, 0);
    Observer.changedInstr(MI);
    return Legalized;
  }
  case TargetOpcode::G_BITCAST: {
    if (TypeIdx != 0)
      return UnableToLegalize;

    LLT SrcTy = MRI.getType(MI.getOperand(1).getReg());
    LLT DstTy = MRI.getType(MI.getOperand(0).getReg());

    unsigned coefficient = SrcTy.getNumElements() * MoreTy.getNumElements();
    if (coefficient % DstTy.getNumElements() != 0)
      return UnableToLegalize;

    coefficient = coefficient / DstTy.getNumElements();

    LLT NewTy = SrcTy.changeElementCount(
        ElementCount::get(coefficient, MoreTy.isScalable()));
    Observer.changingInstr(MI);
    moreElementsVectorSrc(MI, NewTy, 1);
    moreElementsVectorDst(MI, MoreTy, 0);
    Observer.changedInstr(MI);
    return Legalized;
  }
  case TargetOpcode::G_VECREDUCE_FADD:
  case TargetOpcode::G_VECREDUCE_FMUL:
  case TargetOpcode::G_VECREDUCE_ADD:
  case TargetOpcode::G_VECREDUCE_MUL:
  case TargetOpcode::G_VECREDUCE_AND:
  case TargetOpcode::G_VECREDUCE_OR:
  case TargetOpcode::G_VECREDUCE_XOR:
  case TargetOpcode::G_VECREDUCE_SMAX:
  case TargetOpcode::G_VECREDUCE_SMIN:
  case TargetOpcode::G_VECREDUCE_UMAX:
  case TargetOpcode::G_VECREDUCE_UMIN: {
    LLT OrigTy = MRI.getType(MI.getOperand(1).getReg());
    MachineOperand &MO = MI.getOperand(1);
    auto NewVec = MIRBuilder.buildPadVectorWithUndefElements(MoreTy, MO);
    auto NeutralElement = getNeutralElementForVecReduce(
        MI.getOpcode(), MIRBuilder, MoreTy.getElementType());

    LLT IdxTy(TLI.getVectorIdxLLT(MIRBuilder.getDataLayout()));
    for (size_t i = OrigTy.getNumElements(), e = MoreTy.getNumElements();
         i != e; i++) {
      auto Idx = MIRBuilder.buildConstant(IdxTy, i);
      NewVec = MIRBuilder.buildInsertVectorElement(MoreTy, NewVec,
                                                   NeutralElement, Idx);
    }

    Observer.changingInstr(MI);
    MO.setReg(NewVec.getReg(0));
    Observer.changedInstr(MI);
    return Legalized;
  }

  default:
    return UnableToLegalize;
  }
}

LegalizerHelper::LegalizeResult
LegalizerHelper::equalizeVectorShuffleLengths(MachineInstr &MI) {
  auto [DstReg, DstTy, SrcReg, SrcTy] = MI.getFirst2RegLLTs();
  ArrayRef<int> Mask = MI.getOperand(3).getShuffleMask();
  unsigned MaskNumElts = Mask.size();
  unsigned SrcNumElts = SrcTy.getNumElements();
  LLT DestEltTy = DstTy.getElementType();

  if (MaskNumElts == SrcNumElts)
    return Legalized;

  if (MaskNumElts < SrcNumElts) {
    // Extend mask to match new destination vector size with
    // undef values.
    SmallVector<int, 16> NewMask(SrcNumElts, -1);
    llvm::copy(Mask, NewMask.begin());

    moreElementsVectorDst(MI, SrcTy, 0);
    MIRBuilder.setInstrAndDebugLoc(MI);
    MIRBuilder.buildShuffleVector(MI.getOperand(0).getReg(),
                                  MI.getOperand(1).getReg(),
                                  MI.getOperand(2).getReg(), NewMask);
    MI.eraseFromParent();

    return Legalized;
  }

  unsigned PaddedMaskNumElts = alignTo(MaskNumElts, SrcNumElts);
  unsigned NumConcat = PaddedMaskNumElts / SrcNumElts;
  LLT PaddedTy =
      DstTy.changeVectorElementCount(ElementCount::getFixed(PaddedMaskNumElts));

  // Create new source vectors by concatenating the initial
  // source vectors with undefined vectors of the same size.
  auto Undef = MIRBuilder.buildUndef(SrcTy);
  SmallVector<Register, 8> MOps1(NumConcat, Undef.getReg(0));
  SmallVector<Register, 8> MOps2(NumConcat, Undef.getReg(0));
  MOps1[0] = MI.getOperand(1).getReg();
  MOps2[0] = MI.getOperand(2).getReg();

  auto Src1 = MIRBuilder.buildConcatVectors(PaddedTy, MOps1);
  auto Src2 = MIRBuilder.buildConcatVectors(PaddedTy, MOps2);

  // Readjust mask for new input vector length.
  SmallVector<int, 8> MappedOps(PaddedMaskNumElts, -1);
  for (unsigned I = 0; I != MaskNumElts; ++I) {
    int Idx = Mask[I];
    if (Idx >= static_cast<int>(SrcNumElts))
      Idx += PaddedMaskNumElts - SrcNumElts;
    MappedOps[I] = Idx;
  }

  // If we got more elements than required, extract subvector.
  if (MaskNumElts != PaddedMaskNumElts) {
    auto Shuffle =
        MIRBuilder.buildShuffleVector(PaddedTy, Src1, Src2, MappedOps);

    SmallVector<Register, 16> Elts(MaskNumElts);
    for (unsigned I = 0; I < MaskNumElts; ++I) {
      Elts[I] =
          MIRBuilder.buildExtractVectorElementConstant(DestEltTy, Shuffle, I)
              .getReg(0);
    }
    MIRBuilder.buildBuildVector(DstReg, Elts);
  } else {
    MIRBuilder.buildShuffleVector(DstReg, Src1, Src2, MappedOps);
  }

  MI.eraseFromParent();
  return LegalizerHelper::LegalizeResult::Legalized;
}

LegalizerHelper::LegalizeResult
LegalizerHelper::moreElementsVectorShuffle(MachineInstr &MI,
                                           unsigned int TypeIdx, LLT MoreTy) {
  auto [DstTy, Src1Ty, Src2Ty] = MI.getFirst3LLTs();
  ArrayRef<int> Mask = MI.getOperand(3).getShuffleMask();
  unsigned NumElts = DstTy.getNumElements();
  unsigned WidenNumElts = MoreTy.getNumElements();

  if (DstTy.isVector() && Src1Ty.isVector() &&
      DstTy.getNumElements() != Src1Ty.getNumElements()) {
    return equalizeVectorShuffleLengths(MI);
  }

  if (TypeIdx != 0)
    return UnableToLegalize;

  // Expect a canonicalized shuffle.
  if (DstTy != Src1Ty || DstTy != Src2Ty)
    return UnableToLegalize;

  moreElementsVectorSrc(MI, MoreTy, 1);
  moreElementsVectorSrc(MI, MoreTy, 2);

  // Adjust mask based on new input vector length.
  SmallVector<int, 16> NewMask(WidenNumElts, -1);
  for (unsigned I = 0; I != NumElts; ++I) {
    int Idx = Mask[I];
    if (Idx < static_cast<int>(NumElts))
      NewMask[I] = Idx;
    else
      NewMask[I] = Idx - NumElts + WidenNumElts;
  }
  moreElementsVectorDst(MI, MoreTy, 0);
  MIRBuilder.setInstrAndDebugLoc(MI);
  MIRBuilder.buildShuffleVector(MI.getOperand(0).getReg(),
                                MI.getOperand(1).getReg(),
                                MI.getOperand(2).getReg(), NewMask);
  MI.eraseFromParent();
  return Legalized;
}

void LegalizerHelper::multiplyRegisters(SmallVectorImpl<Register> &DstRegs,
                                        ArrayRef<Register> Src1Regs,
                                        ArrayRef<Register> Src2Regs,
                                        LLT NarrowTy) {
  MachineIRBuilder &B = MIRBuilder;
  unsigned SrcParts = Src1Regs.size();
  unsigned DstParts = DstRegs.size();

  unsigned DstIdx = 0; // Low bits of the result.
  Register FactorSum =
      B.buildMul(NarrowTy, Src1Regs[DstIdx], Src2Regs[DstIdx]).getReg(0);
  DstRegs[DstIdx] = FactorSum;

  Register CarrySumPrevDstIdx;
  SmallVector<Register, 4> Factors;

  for (DstIdx = 1; DstIdx < DstParts; DstIdx++) {
    // Collect high parts of muls from previous DstIdx.
    for (unsigned i = DstIdx < SrcParts ? 0 : DstIdx - SrcParts;
         i <= std::min(DstIdx - 1, SrcParts - 1); ++i) {
      MachineInstrBuilder Umulh =
          B.buildUMulH(NarrowTy, Src1Regs[DstIdx - 1 - i], Src2Regs[i]);
      Factors.push_back(Umulh.getReg(0));
    }
    // Collect low parts of muls for DstIdx. Visit the diagonal starting with
    // the low Src1 part, so multiply-add selectors can use it as the first
    // accumulated cross product.
    unsigned LowStart = DstIdx + 1 < SrcParts ? 0 : DstIdx - SrcParts + 1;
    unsigned LowEnd = std::min(DstIdx, SrcParts - 1);
    for (unsigned RevI = LowEnd + 1; RevI != LowStart; --RevI) {
      unsigned i = RevI - 1;
      MachineInstrBuilder Mul =
          B.buildMul(NarrowTy, Src1Regs[DstIdx - i], Src2Regs[i]);
      Factors.push_back(Mul.getReg(0));
    }
    // Add CarrySum from additions calculated for previous DstIdx.
    if (DstIdx != 1) {
      Factors.push_back(CarrySumPrevDstIdx);
    }

    Register CarrySum;
    // Add all factors and accumulate all carries into CarrySum.
    if (DstIdx != DstParts - 1) {
      MachineInstrBuilder Uaddo =
          B.buildUAddo(NarrowTy, LLT::integer(1), Factors[0], Factors[1]);
      FactorSum = Uaddo.getReg(0);
      CarrySum = B.buildZExt(NarrowTy, Uaddo.getReg(1)).getReg(0);
      for (unsigned i = 2; i < Factors.size(); ++i) {
        MachineInstrBuilder Uaddo =
            B.buildUAddo(NarrowTy, LLT::integer(1), FactorSum, Factors[i]);
        FactorSum = Uaddo.getReg(0);
        MachineInstrBuilder Carry = B.buildZExt(NarrowTy, Uaddo.getReg(1));
        CarrySum = B.buildAdd(NarrowTy, CarrySum, Carry).getReg(0);
      }
    } else {
      // Since value for the next index is not calculated, neither is CarrySum.
      FactorSum = B.buildAdd(NarrowTy, Factors[0], Factors[1]).getReg(0);
      for (unsigned i = 2; i < Factors.size(); ++i)
        FactorSum = B.buildAdd(NarrowTy, FactorSum, Factors[i]).getReg(0);
    }

    CarrySumPrevDstIdx = CarrySum;
    DstRegs[DstIdx] = FactorSum;
    Factors.clear();
  }
}

LegalizerHelper::LegalizeResult
LegalizerHelper::narrowScalarAddSub(MachineInstr &MI, unsigned TypeIdx,
                                    LLT NarrowTy) {
  if (TypeIdx != 0)
    return UnableToLegalize;

  Register DstReg = MI.getOperand(0).getReg();
  LLT DstType = MRI.getType(DstReg);
  // FIXME: add support for vector types
  if (DstType.isVector())
    return UnableToLegalize;

  unsigned Opcode = MI.getOpcode();
  unsigned OpO, OpE, OpF;
  switch (Opcode) {
  case TargetOpcode::G_SADDO:
  case TargetOpcode::G_SADDE:
  case TargetOpcode::G_UADDO:
  case TargetOpcode::G_UADDE:
  case TargetOpcode::G_ADD:
    OpO = TargetOpcode::G_UADDO;
    OpE = TargetOpcode::G_UADDE;
    OpF = TargetOpcode::G_UADDE;
    if (Opcode == TargetOpcode::G_SADDO || Opcode == TargetOpcode::G_SADDE)
      OpF = TargetOpcode::G_SADDE;
    break;
  case TargetOpcode::G_SSUBO:
  case TargetOpcode::G_SSUBE:
  case TargetOpcode::G_USUBO:
  case TargetOpcode::G_USUBE:
  case TargetOpcode::G_SUB:
    OpO = TargetOpcode::G_USUBO;
    OpE = TargetOpcode::G_USUBE;
    OpF = TargetOpcode::G_USUBE;
    if (Opcode == TargetOpcode::G_SSUBO || Opcode == TargetOpcode::G_SSUBE)
      OpF = TargetOpcode::G_SSUBE;
    break;
  default:
    llvm_unreachable("Unexpected add/sub opcode!");
  }

  // 1 for a plain add/sub, 2 if this is an operation with a carry-out.
  unsigned NumDefs = MI.getNumExplicitDefs();
  Register Src1 = MI.getOperand(NumDefs).getReg();
  Register Src2 = MI.getOperand(NumDefs + 1).getReg();
  Register CarryDst, CarryIn;
  if (NumDefs == 2)
    CarryDst = MI.getOperand(1).getReg();
  if (MI.getNumOperands() == NumDefs + 3)
    CarryIn = MI.getOperand(NumDefs + 2).getReg();

  LLT RegTy = MRI.getType(MI.getOperand(0).getReg());
  LLT LeftoverTy, DummyTy;
  SmallVector<Register, 2> Src1Regs, Src2Regs, Src1Left, Src2Left, DstRegs;
  extractParts(Src1, RegTy, NarrowTy, LeftoverTy, Src1Regs, Src1Left,
               MIRBuilder, MRI);
  extractParts(Src2, RegTy, NarrowTy, DummyTy, Src2Regs, Src2Left, MIRBuilder,
               MRI);

  int NarrowParts = Src1Regs.size();
  Src1Regs.append(Src1Left);
  Src2Regs.append(Src2Left);
  DstRegs.reserve(Src1Regs.size());

  for (int i = 0, e = Src1Regs.size(); i != e; ++i) {
    Register DstReg =
        MRI.createGenericVirtualRegister(MRI.getType(Src1Regs[i]));
    Register CarryOut;
    // Forward the final carry-out to the destination register
    if (i == e - 1 && CarryDst)
      CarryOut = CarryDst;
    else
      CarryOut = MRI.createGenericVirtualRegister(LLT::integer(1));

    if (!CarryIn) {
      MIRBuilder.buildInstr(OpO, {DstReg, CarryOut},
                            {Src1Regs[i], Src2Regs[i]});
    } else if (i == e - 1) {
      MIRBuilder.buildInstr(OpF, {DstReg, CarryOut},
                            {Src1Regs[i], Src2Regs[i], CarryIn});
    } else {
      MIRBuilder.buildInstr(OpE, {DstReg, CarryOut},
                            {Src1Regs[i], Src2Regs[i], CarryIn});
    }

    DstRegs.push_back(DstReg);
    CarryIn = CarryOut;
  }
  insertParts(MI.getOperand(0).getReg(), RegTy, NarrowTy,
              ArrayRef(DstRegs).take_front(NarrowParts), LeftoverTy,
              ArrayRef(DstRegs).drop_front(NarrowParts));

  MI.eraseFromParent();
  return Legalized;
}

LegalizerHelper::LegalizeResult
LegalizerHelper::narrowScalarMul(MachineInstr &MI, LLT NarrowTy) {
  auto [DstReg, Src1, Src2] = MI.getFirst3Regs();

  LLT Ty = MRI.getType(DstReg);
  if (Ty.isVector())
    return UnableToLegalize;

  unsigned Size = Ty.getSizeInBits();
  unsigned NarrowSize = NarrowTy.getSizeInBits();
  if (Size % NarrowSize != 0)
    return UnableToLegalize;

  unsigned NumParts = Size / NarrowSize;
  bool IsMulHigh = MI.getOpcode() == TargetOpcode::G_UMULH;
  unsigned DstTmpParts = NumParts * (IsMulHigh ? 2 : 1);

  SmallVector<Register, 2> Src1Parts, Src2Parts;
  SmallVector<Register, 2> DstTmpRegs(DstTmpParts);
  extractParts(Src1, NarrowTy, NumParts, Src1Parts, MIRBuilder, MRI);
  extractParts(Src2, NarrowTy, NumParts, Src2Parts, MIRBuilder, MRI);
  multiplyRegisters(DstTmpRegs, Src1Parts, Src2Parts, NarrowTy);

  // Take only high half of registers if this is high mul.
  ArrayRef<Register> DstRegs(&DstTmpRegs[DstTmpParts - NumParts], NumParts);
  MIRBuilder.buildMergeLikeInstr(DstReg, DstRegs);
  MI.eraseFromParent();
  return Legalized;
}

LegalizerHelper::LegalizeResult
LegalizerHelper::narrowScalarFPTOI(MachineInstr &MI, unsigned TypeIdx,
                                   LLT NarrowTy) {
  if (TypeIdx != 0)
    return UnableToLegalize;

  bool IsSigned = MI.getOpcode() == TargetOpcode::G_FPTOSI;

  Register Src = MI.getOperand(1).getReg();
  LLT SrcTy = MRI.getType(Src);

  // If all finite floats fit into the narrowed integer type, we can just swap
  // out the result type. This is practically only useful for conversions from
  // half to at least 16-bits, so just handle the one case.
  if (SrcTy.getScalarType() != LLT::scalar(16) ||
      NarrowTy.getScalarSizeInBits() < (IsSigned ? 17u : 16u))
    return UnableToLegalize;

  Observer.changingInstr(MI);
  narrowScalarDst(MI, NarrowTy, 0,
                  IsSigned ? TargetOpcode::G_SEXT : TargetOpcode::G_ZEXT);
  Observer.changedInstr(MI);
  return Legalized;
}

LegalizerHelper::LegalizeResult
LegalizerHelper::narrowScalarExtract(MachineInstr &MI, unsigned TypeIdx,
                                     LLT NarrowTy) {
  if (TypeIdx != 1)
    return UnableToLegalize;

  uint64_t NarrowSize = NarrowTy.getSizeInBits();

  int64_t SizeOp1 = MRI.getType(MI.getOperand(1).getReg()).getSizeInBits();
  // FIXME: add support for when SizeOp1 isn't an exact multiple of
  // NarrowSize.
  if (SizeOp1 % NarrowSize != 0)
    return UnableToLegalize;
  int NumParts = SizeOp1 / NarrowSize;

  SmallVector<Register, 2> SrcRegs, DstRegs;
  extractParts(MI.getOperand(1).getReg(), NarrowTy, NumParts, SrcRegs,
               MIRBuilder, MRI);

  Register OpReg = MI.getOperand(0).getReg();
  uint64_t OpStart = MI.getOperand(2).getImm();
  uint64_t OpSize = MRI.getType(OpReg).getSizeInBits();
  for (int i = 0; i < NumParts; ++i) {
    unsigned SrcStart = i * NarrowSize;

    if (SrcStart + NarrowSize <= OpStart || SrcStart >= OpStart + OpSize) {
      // No part of the extract uses this subregister, ignore it.
      continue;
    } else if (SrcStart == OpStart && NarrowTy == MRI.getType(OpReg)) {
      // The entire subregister is extracted, forward the value.
      DstRegs.push_back(SrcRegs[i]);
      continue;
    }

    // OpSegStart is where this destination segment would start in OpReg if it
    // extended infinitely in both directions.
    int64_t ExtractOffset;
    uint64_t SegSize;
    if (OpStart < SrcStart) {
      ExtractOffset = 0;
      SegSize = std::min(NarrowSize, OpStart + OpSize - SrcStart);
    } else {
      ExtractOffset = OpStart - SrcStart;
      SegSize = std::min(SrcStart + NarrowSize - OpStart, OpSize);
    }

    Register SegReg = SrcRegs[i];
    if (ExtractOffset != 0 || SegSize != NarrowSize) {
      // A genuine extract is needed.
      SegReg = MRI.createGenericVirtualRegister(LLT::scalar(SegSize));
      MIRBuilder.buildExtract(SegReg, SrcRegs[i], ExtractOffset);
    }

    DstRegs.push_back(SegReg);
  }

  Register DstReg = MI.getOperand(0).getReg();
  if (MRI.getType(DstReg).isVector())
    MIRBuilder.buildBuildVector(DstReg, DstRegs);
  else if (DstRegs.size() > 1)
    MIRBuilder.buildMergeLikeInstr(DstReg, DstRegs);
  else
    MIRBuilder.buildCopy(DstReg, DstRegs[0]);
  MI.eraseFromParent();
  return Legalized;
}

LegalizerHelper::LegalizeResult
LegalizerHelper::narrowScalarInsert(MachineInstr &MI, unsigned TypeIdx,
                                    LLT NarrowTy) {
  // FIXME: Don't know how to handle secondary types yet.
  if (TypeIdx != 0)
    return UnableToLegalize;

  SmallVector<Register, 2> SrcRegs, LeftoverRegs, DstRegs;
  LLT RegTy = MRI.getType(MI.getOperand(0).getReg());
  LLT LeftoverTy;
  extractParts(MI.getOperand(1).getReg(), RegTy, NarrowTy, LeftoverTy, SrcRegs,
               LeftoverRegs, MIRBuilder, MRI);

  SrcRegs.append(LeftoverRegs);

  uint64_t NarrowSize = NarrowTy.getSizeInBits();
  Register OpReg = MI.getOperand(2).getReg();
  uint64_t OpStart = MI.getOperand(3).getImm();
  uint64_t OpSize = MRI.getType(OpReg).getSizeInBits();
  for (int I = 0, E = SrcRegs.size(); I != E; ++I) {
    unsigned DstStart = I * NarrowSize;

    if (DstStart == OpStart && NarrowTy == MRI.getType(OpReg)) {
      // The entire subregister is defined by this insert, forward the new
      // value.
      DstRegs.push_back(OpReg);
      continue;
    }

    Register SrcReg = SrcRegs[I];
    if (MRI.getType(SrcRegs[I]) == LeftoverTy) {
      // The leftover reg is smaller than NarrowTy, so we need to extend it.
      SrcReg = MRI.createGenericVirtualRegister(NarrowTy);
      MIRBuilder.buildAnyExt(SrcReg, SrcRegs[I]);
    }

    if (DstStart + NarrowSize <= OpStart || DstStart >= OpStart + OpSize) {
      // No part of the insert affects this subregister, forward the original.
      DstRegs.push_back(SrcReg);
      continue;
    }

    // OpSegStart is where this destination segment would start in OpReg if it
    // extended infinitely in both directions.
    int64_t ExtractOffset, InsertOffset;
    uint64_t SegSize;
    if (OpStart < DstStart) {
      InsertOffset = 0;
      ExtractOffset = DstStart - OpStart;
      SegSize = std::min(NarrowSize, OpStart + OpSize - DstStart);
    } else {
      InsertOffset = OpStart - DstStart;
      ExtractOffset = 0;
      SegSize =
        std::min(NarrowSize - InsertOffset, OpStart + OpSize - DstStart);
    }

    Register SegReg = OpReg;
    if (ExtractOffset != 0 || SegSize != OpSize) {
      // A genuine extract is needed.
      SegReg = MRI.createGenericVirtualRegister(LLT::scalar(SegSize));
      MIRBuilder.buildExtract(SegReg, OpReg, ExtractOffset);
    }

    Register DstReg = MRI.createGenericVirtualRegister(NarrowTy);
    MIRBuilder.buildInsert(DstReg, SrcReg, SegReg, InsertOffset);
    DstRegs.push_back(DstReg);
  }

  uint64_t WideSize = DstRegs.size() * NarrowSize;
  Register DstReg = MI.getOperand(0).getReg();
  if (WideSize > RegTy.getSizeInBits()) {
    Register MergeReg = MRI.createGenericVirtualRegister(LLT::scalar(WideSize));
    MIRBuilder.buildMergeLikeInstr(MergeReg, DstRegs);
    MIRBuilder.buildTrunc(DstReg, MergeReg);
  } else
    MIRBuilder.buildMergeLikeInstr(DstReg, DstRegs);

  MI.eraseFromParent();
  return Legalized;
}

LegalizerHelper::LegalizeResult
LegalizerHelper::narrowScalarBasic(MachineInstr &MI, unsigned TypeIdx,
                                   LLT NarrowTy) {
  Register DstReg = MI.getOperand(0).getReg();
  LLT DstTy = MRI.getType(DstReg);

  assert(MI.getNumOperands() == 3 && TypeIdx == 0);

  SmallVector<Register, 4> DstRegs, DstLeftoverRegs;
  SmallVector<Register, 4> Src0Regs, Src0LeftoverRegs;
  SmallVector<Register, 4> Src1Regs, Src1LeftoverRegs;
  LLT LeftoverTy;
  if (!extractParts(MI.getOperand(1).getReg(), DstTy, NarrowTy, LeftoverTy,
                    Src0Regs, Src0LeftoverRegs, MIRBuilder, MRI))
    return UnableToLegalize;

  LLT Unused;
  if (!extractParts(MI.getOperand(2).getReg(), DstTy, NarrowTy, Unused,
                    Src1Regs, Src1LeftoverRegs, MIRBuilder, MRI))
    llvm_unreachable("inconsistent extractParts result");

  for (unsigned I = 0, E = Src1Regs.size(); I != E; ++I) {
    auto Inst = MIRBuilder.buildInstr(MI.getOpcode(), {NarrowTy},
                                        {Src0Regs[I], Src1Regs[I]});
    DstRegs.push_back(Inst.getReg(0));
  }

  for (unsigned I = 0, E = Src1LeftoverRegs.size(); I != E; ++I) {
    auto Inst = MIRBuilder.buildInstr(
      MI.getOpcode(),
      {LeftoverTy}, {Src0LeftoverRegs[I], Src1LeftoverRegs[I]});
    DstLeftoverRegs.push_back(Inst.getReg(0));
  }

  insertParts(DstReg, DstTy, NarrowTy, DstRegs,
              LeftoverTy, DstLeftoverRegs);

  MI.eraseFromParent();
  return Legalized;
}

LegalizerHelper::LegalizeResult
LegalizerHelper::narrowScalarExt(MachineInstr &MI, unsigned TypeIdx,
                                 LLT NarrowTy) {
  if (TypeIdx != 0)
    return UnableToLegalize;

  auto [DstReg, SrcReg] = MI.getFirst2Regs();

  LLT DstTy = MRI.getType(DstReg);
  if (DstTy.isVector())
    return UnableToLegalize;

  SmallVector<Register, 8> Parts;
  LLT GCDTy = extractGCDType(Parts, DstTy, NarrowTy, SrcReg);
  LLT LCMTy = buildLCMMergePieces(DstTy, NarrowTy, GCDTy, Parts, MI.getOpcode());
  buildWidenedRemergeToDst(DstReg, LCMTy, Parts);

  MI.eraseFromParent();
  return Legalized;
}

LegalizerHelper::LegalizeResult
LegalizerHelper::narrowScalarSelect(MachineInstr &MI, unsigned TypeIdx,
                                    LLT NarrowTy) {
  if (TypeIdx != 0)
    return UnableToLegalize;

  Register CondReg = MI.getOperand(1).getReg();
  LLT CondTy = MRI.getType(CondReg);
  if (CondTy.isVector()) // TODO: Handle vselect
    return UnableToLegalize;

  Register DstReg = MI.getOperand(0).getReg();
  LLT DstTy = MRI.getType(DstReg);

  SmallVector<Register, 4> DstRegs, DstLeftoverRegs;
  SmallVector<Register, 4> Src1Regs, Src1LeftoverRegs;
  SmallVector<Register, 4> Src2Regs, Src2LeftoverRegs;
  LLT LeftoverTy;
  if (!extractParts(MI.getOperand(2).getReg(), DstTy, NarrowTy, LeftoverTy,
                    Src1Regs, Src1LeftoverRegs, MIRBuilder, MRI))
    return UnableToLegalize;

  LLT Unused;
  if (!extractParts(MI.getOperand(3).getReg(), DstTy, NarrowTy, Unused,
                    Src2Regs, Src2LeftoverRegs, MIRBuilder, MRI))
    llvm_unreachable("inconsistent extractParts result");

  for (unsigned I = 0, E = Src1Regs.size(); I != E; ++I) {
    auto Select = MIRBuilder.buildSelect(NarrowTy,
                                         CondReg, Src1Regs[I], Src2Regs[I]);
    DstRegs.push_back(Select.getReg(0));
  }

  for (unsigned I = 0, E = Src1LeftoverRegs.size(); I != E; ++I) {
    auto Select = MIRBuilder.buildSelect(
      LeftoverTy, CondReg, Src1LeftoverRegs[I], Src2LeftoverRegs[I]);
    DstLeftoverRegs.push_back(Select.getReg(0));
  }

  insertParts(DstReg, DstTy, NarrowTy, DstRegs,
              LeftoverTy, DstLeftoverRegs);

  MI.eraseFromParent();
  return Legalized;
}

LegalizerHelper::LegalizeResult
LegalizerHelper::narrowScalarCTLZ(MachineInstr &MI, unsigned TypeIdx,
                                  LLT NarrowTy) {
  if (TypeIdx != 1)
    return UnableToLegalize;

  auto [DstReg, DstTy, SrcReg, SrcTy] = MI.getFirst2RegLLTs();
  unsigned NarrowSize = NarrowTy.getSizeInBits();

  if (SrcTy.isScalar() && SrcTy.getSizeInBits() == 2 * NarrowSize) {
    const bool IsUndef = MI.getOpcode() == TargetOpcode::G_CTLZ_ZERO_POISON;

    MachineIRBuilder &B = MIRBuilder;
    auto UnmergeSrc = B.buildUnmerge(NarrowTy, SrcReg);
    // ctlz(Hi:Lo) -> Hi == 0 ? (NarrowSize + ctlz(Lo)) : ctlz(Hi)
    auto C_0 = B.buildConstant(NarrowTy, 0);
    auto HiIsZero = B.buildICmp(CmpInst::ICMP_EQ, LLT::integer(1),
                                UnmergeSrc.getReg(1), C_0);
    auto LoCTLZ = IsUndef ? B.buildCTLZ_ZERO_POISON(DstTy, UnmergeSrc.getReg(0))
                          : B.buildCTLZ(DstTy, UnmergeSrc.getReg(0));
    auto C_NarrowSize = B.buildConstant(DstTy, NarrowSize);
    auto HiIsZeroCTLZ = B.buildAdd(DstTy, LoCTLZ, C_NarrowSize);
    auto HiCTLZ = B.buildCTLZ_ZERO_POISON(DstTy, UnmergeSrc.getReg(1));
    B.buildSelect(DstReg, HiIsZero, HiIsZeroCTLZ, HiCTLZ);

    MI.eraseFromParent();
    return Legalized;
  }

  return UnableToLegalize;
}

LegalizerHelper::LegalizeResult
LegalizerHelper::narrowScalarCTTZ(MachineInstr &MI, unsigned TypeIdx,
                                  LLT NarrowTy) {
  if (TypeIdx != 1)
    return UnableToLegalize;

  auto [DstReg, DstTy, SrcReg, SrcTy] = MI.getFirst2RegLLTs();
  unsigned NarrowSize = NarrowTy.getSizeInBits();

  if (SrcTy.isScalar() && SrcTy.getSizeInBits() == 2 * NarrowSize) {
    const bool IsUndef = MI.getOpcode() == TargetOpcode::G_CTTZ_ZERO_POISON;

    MachineIRBuilder &B = MIRBuilder;
    auto UnmergeSrc = B.buildUnmerge(NarrowTy, SrcReg);
    // cttz(Hi:Lo) -> Lo == 0 ? (cttz(Hi) + NarrowSize) : cttz(Lo)
    auto C_0 = B.buildConstant(NarrowTy, 0);
    auto LoIsZero = B.buildICmp(CmpInst::ICMP_EQ, LLT::scalar(1),
                                UnmergeSrc.getReg(0), C_0);
    auto HiCTTZ = IsUndef ? B.buildCTTZ_ZERO_POISON(DstTy, UnmergeSrc.getReg(1))
                          : B.buildCTTZ(DstTy, UnmergeSrc.getReg(1));
    auto C_NarrowSize = B.buildConstant(DstTy, NarrowSize);
    auto LoIsZeroCTTZ = B.buildAdd(DstTy, HiCTTZ, C_NarrowSize);
    auto LoCTTZ = B.buildCTTZ_ZERO_POISON(DstTy, UnmergeSrc.getReg(0));
    B.buildSelect(DstReg, LoIsZero, LoIsZeroCTTZ, LoCTTZ);

    MI.eraseFromParent();
    return Legalized;
  }

  return UnableToLegalize;
}

LegalizerHelper::LegalizeResult
LegalizerHelper::narrowScalarCTLS(MachineInstr &MI, unsigned TypeIdx,
                                  LLT NarrowTy) {
  if (TypeIdx != 1)
    return UnableToLegalize;

  auto [DstReg, DstTy, SrcReg, SrcTy] = MI.getFirst2RegLLTs();
  unsigned NarrowSize = NarrowTy.getSizeInBits();

  if (!SrcTy.isScalar() || SrcTy.getSizeInBits() != 2 * NarrowSize)
    return UnableToLegalize;

  MachineIRBuilder &B = MIRBuilder;

  auto UnmergeSrc = B.buildUnmerge(NarrowTy, SrcReg);
  Register Lo = UnmergeSrc.getReg(0);
  Register Hi = UnmergeSrc.getReg(1);

  auto ShAmt = B.buildConstant(NarrowTy, NarrowSize - 1);
  auto Sign = B.buildAShr(NarrowTy, Hi, ShAmt);

  auto HiIsSign = B.buildICmp(CmpInst::ICMP_EQ, LLT::scalar(1), Hi, Sign);

  // Invert Lo if Hi is negative. Then count the leading zeros. If there are no
  // leading zeros, then the MSB of Lo is different than the MSB of Hi.
  // Otherwise the leading zeros represent additional sign bits of the original
  // value.
  auto LoInv = B.buildXor(DstTy, Lo, Sign);
  auto LoCTLZ = B.buildCTLZ(DstTy, LoInv);

  // Add NarrowSize-1 to LoCTLZ. This is the full CTLS if Hi is all sign bits.
  auto C_NarrowSizeM1 = B.buildConstant(DstTy, NarrowSize - 1);
  auto HiIsSignCTLS = B.buildAdd(DstTy, LoCTLZ, C_NarrowSizeM1);

  auto HiCTLS = B.buildCTLS(DstTy, Hi);

  B.buildSelect(DstReg, HiIsSign, HiIsSignCTLS, HiCTLS);

  MI.eraseFromParent();
  return Legalized;
}

LegalizerHelper::LegalizeResult
LegalizerHelper::narrowScalarCTPOP(MachineInstr &MI, unsigned TypeIdx,
                                   LLT NarrowTy) {
  if (TypeIdx != 1)
    return UnableToLegalize;

  auto [DstReg, DstTy, SrcReg, SrcTy] = MI.getFirst2RegLLTs();
  unsigned NarrowSize = NarrowTy.getSizeInBits();

  if (SrcTy.isScalar() && SrcTy.getSizeInBits() == 2 * NarrowSize) {
    auto UnmergeSrc = MIRBuilder.buildUnmerge(NarrowTy, MI.getOperand(1));

    auto LoCTPOP = MIRBuilder.buildCTPOP(DstTy, UnmergeSrc.getReg(0));
    auto HiCTPOP = MIRBuilder.buildCTPOP(DstTy, UnmergeSrc.getReg(1));
    MIRBuilder.buildAdd(DstReg, HiCTPOP, LoCTPOP);

    MI.eraseFromParent();
    return Legalized;
  }

  return UnableToLegalize;
}

LegalizerHelper::LegalizeResult
LegalizerHelper::narrowScalarFLDEXP(MachineInstr &MI, unsigned TypeIdx,
                                    LLT NarrowTy) {
  if (TypeIdx != 1)
    return UnableToLegalize;

  MachineIRBuilder &B = MIRBuilder;
  Register ExpReg = MI.getOperand(2).getReg();
  LLT ExpTy = MRI.getType(ExpReg);

  unsigned ClampSize = NarrowTy.getScalarSizeInBits();

  // Clamp the exponent to the range of the target type.
  auto MinExp = B.buildConstant(ExpTy, minIntN(ClampSize));
  auto ClampMin = B.buildSMax(ExpTy, ExpReg, MinExp);
  auto MaxExp = B.buildConstant(ExpTy, maxIntN(ClampSize));
  auto Clamp = B.buildSMin(ExpTy, ClampMin, MaxExp);

  auto Trunc = B.buildTrunc(NarrowTy, Clamp);
  Observer.changingInstr(MI);
  MI.getOperand(2).setReg(Trunc.getReg(0));
  Observer.changedInstr(MI);
  return Legalized;
}

LegalizerHelper::LegalizeResult
LegalizerHelper::lowerBitCount(MachineInstr &MI) {
  unsigned Opc = MI.getOpcode();
  const auto &TII = MIRBuilder.getTII();
  auto isSupported = [this](const LegalityQuery &Q) {
    auto QAction = LI.getAction(Q).Action;
    return QAction == Legal || QAction == Libcall || QAction == Custom;
  };
  switch (Opc) {
  default:
    return UnableToLegalize;
  case TargetOpcode::G_CTLZ_ZERO_POISON: {
    // This trivially expands to CTLZ.
    Observer.changingInstr(MI);
    MI.setDesc(TII.get(TargetOpcode::G_CTLZ));
    Observer.changedInstr(MI);
    return Legalized;
  }
  case TargetOpcode::G_CTLZ: {
    auto [DstReg, DstTy, SrcReg, SrcTy] = MI.getFirst2RegLLTs();
    unsigned Len = SrcTy.getScalarSizeInBits();

    if (isSupported({TargetOpcode::G_CTLZ_ZERO_POISON, {DstTy, SrcTy}})) {
      // If CTLZ_ZERO_POISON is supported, emit that and a select for zero.
      auto CtlzZU = MIRBuilder.buildCTLZ_ZERO_POISON(DstTy, SrcReg);
      auto ZeroSrc = MIRBuilder.buildConstant(SrcTy, 0);
      auto ICmp = MIRBuilder.buildICmp(
          CmpInst::ICMP_EQ, SrcTy.changeElementSize(1), SrcReg, ZeroSrc);
      auto LenConst = MIRBuilder.buildConstant(DstTy, Len);
      MIRBuilder.buildSelect(DstReg, ICmp, LenConst, CtlzZU);
      MI.eraseFromParent();
      return Legalized;
    }
    // for now, we do this:
    // NewLen = NextPowerOf2(Len);
    // x = x | (x >> 1);
    // x = x | (x >> 2);
    // ...
    // x = x | (x >>16);
    // x = x | (x >>32); // for 64-bit input
    // Upto NewLen/2
    // return Len - popcount(x);
    //
    // Ref: "Hacker's Delight" by Henry Warren
    Register Op = SrcReg;
    unsigned NewLen = PowerOf2Ceil(Len);
    for (unsigned i = 0; (1U << i) <= (NewLen / 2); ++i) {
      auto MIBShiftAmt = MIRBuilder.buildConstant(SrcTy, 1ULL << i);
      auto MIBOp = MIRBuilder.buildOr(
          SrcTy, Op, MIRBuilder.buildLShr(SrcTy, Op, MIBShiftAmt));
      Op = MIBOp.getReg(0);
    }
    auto MIBPop = MIRBuilder.buildCTPOP(DstTy, Op);
    MIRBuilder.buildSub(MI.getOperand(0), MIRBuilder.buildConstant(DstTy, Len),
                        MIBPop);
    MI.eraseFromParent();
    return Legalized;
  }
  case TargetOpcode::G_CTTZ_ZERO_POISON: {
    // This trivially expands to CTTZ.
    Observer.changingInstr(MI);
    MI.setDesc(TII.get(TargetOpcode::G_CTTZ));
    Observer.changedInstr(MI);
    return Legalized;
  }
  case TargetOpcode::G_CTTZ: {
    auto [DstReg, DstTy, SrcReg, SrcTy] = MI.getFirst2RegLLTs();

    unsigned Len = SrcTy.getScalarSizeInBits();
    if (isSupported({TargetOpcode::G_CTTZ_ZERO_POISON, {DstTy, SrcTy}})) {
      // If CTTZ_ZERO_POISON is legal or custom, emit that and a select with
      // zero.
      auto CttzZU = MIRBuilder.buildCTTZ_ZERO_POISON(DstTy, SrcReg);
      auto Zero = MIRBuilder.buildConstant(SrcTy, 0);
      auto ICmp = MIRBuilder.buildICmp(
          CmpInst::ICMP_EQ, DstTy.changeElementSize(1), SrcReg, Zero);
      auto LenConst = MIRBuilder.buildConstant(DstTy, Len);
      MIRBuilder.buildSelect(DstReg, ICmp, LenConst, CttzZU);
      MI.eraseFromParent();
      return Legalized;
    }
    // for now, we use: { return popcount(~x & (x - 1)); }
    // unless the target has ctlz but not ctpop, in which case we use:
    // { return 32 - nlz(~x & (x-1)); }
    // Ref: "Hacker's Delight" by Henry Warren
    auto MIBCstNeg1 = MIRBuilder.buildConstant(SrcTy, -1);
    auto MIBNot = MIRBuilder.buildXor(SrcTy, SrcReg, MIBCstNeg1);
    auto MIBTmp = MIRBuilder.buildAnd(
        SrcTy, MIBNot, MIRBuilder.buildAdd(SrcTy, SrcReg, MIBCstNeg1));
    if (!isSupported({TargetOpcode::G_CTPOP, {SrcTy, SrcTy}}) &&
        isSupported({TargetOpcode::G_CTLZ, {SrcTy, SrcTy}})) {
      auto MIBCstLen = MIRBuilder.buildConstant(SrcTy, Len);
      MIRBuilder.buildSub(MI.getOperand(0), MIBCstLen,
                          MIRBuilder.buildCTLZ(SrcTy, MIBTmp));
      MI.eraseFromParent();
      return Legalized;
    }
    Observer.changingInstr(MI);
    MI.setDesc(TII.get(TargetOpcode::G_CTPOP));
    MI.getOperand(1).setReg(MIBTmp.getReg(0));
    Observer.changedInstr(MI);
    return Legalized;
  }
  case TargetOpcode::G_CTPOP: {
    Register SrcReg = MI.getOperand(1).getReg();
    LLT Ty = MRI.getType(SrcReg);
    unsigned Size = Ty.getScalarSizeInBits();
    MachineIRBuilder &B = MIRBuilder;

    // Bail out on irregular type lengths.
    if (Size > 128 || Size % 8 != 0)
      return UnableToLegalize;

    // Count set bits in blocks of 2 bits. Default approach would be
    // B2Count = { val & 0x55555555 } + { (val >> 1) & 0x55555555 }
    // We use following formula instead:
    // B2Count = val - { (val >> 1) & 0x55555555 }
    // since it gives same result in blocks of 2 with one instruction less.
    auto C_1 = B.buildConstant(Ty, 1);
    auto B2Set1LoTo1Hi = B.buildLShr(Ty, SrcReg, C_1);
    APInt B2Mask1HiTo0 = APInt::getSplat(Size, APInt(8, 0x55));
    auto C_B2Mask1HiTo0 = B.buildConstant(Ty, B2Mask1HiTo0);
    auto B2Count1Hi = B.buildAnd(Ty, B2Set1LoTo1Hi, C_B2Mask1HiTo0);
    auto B2Count = B.buildSub(Ty, SrcReg, B2Count1Hi);

    // In order to get count in blocks of 4 add values from adjacent block of 2.
    // B4Count = { B2Count & 0x33333333 } + { (B2Count >> 2) & 0x33333333 }
    auto C_2 = B.buildConstant(Ty, 2);
    auto B4Set2LoTo2Hi = B.buildLShr(Ty, B2Count, C_2);
    APInt B4Mask2HiTo0 = APInt::getSplat(Size, APInt(8, 0x33));
    auto C_B4Mask2HiTo0 = B.buildConstant(Ty, B4Mask2HiTo0);
    auto B4HiB2Count = B.buildAnd(Ty, B4Set2LoTo2Hi, C_B4Mask2HiTo0);
    auto B4LoB2Count = B.buildAnd(Ty, B2Count, C_B4Mask2HiTo0);
    auto B4Count = B.buildAdd(Ty, B4HiB2Count, B4LoB2Count);

    // For count in blocks of 8 bits we don't have to mask high 4 bits before
    // addition since count value sits in range {0,...,8} and 4 bits are enough
    // to hold such binary values. After addition high 4 bits still hold count
    // of set bits in high 4 bit block, set them to zero and get 8 bit result.
    // B8Count = { B4Count + (B4Count >> 4) } & 0x0F0F0F0F
    auto C_4 = B.buildConstant(Ty, 4);
    auto B8HiB4Count = B.buildLShr(Ty, B4Count, C_4);
    auto B8CountDirty4Hi = B.buildAdd(Ty, B8HiB4Count, B4Count);
    APInt B8Mask4HiTo0 = APInt::getSplat(Size, APInt(8, 0x0F));
    auto C_B8Mask4HiTo0 = B.buildConstant(Ty, B8Mask4HiTo0);
    auto B8Count = B.buildAnd(Ty, B8CountDirty4Hi, C_B8Mask4HiTo0);

    assert(Size <= 128 && "Scalar size is too large for CTPOP lower algorithm");

    // Avoid the multiply when shift-add is cheaper.
    if (Size == 16 && !Ty.isVector()) {
      // v = (v + (v >> 8)) & 0xFF;
      auto C_8 = B.buildConstant(Ty, 8);
      auto HighSum = B.buildLShr(Ty, B8Count, C_8);
      auto Res = B.buildAdd(Ty, B8Count, HighSum);
      B.buildAnd(MI.getOperand(0).getReg(), Res, B.buildConstant(Ty, 0xFF));
      MI.eraseFromParent();
      return Legalized;
    }

    // 8 bits can hold CTPOP result of 128 bit int or smaller. Mul with this
    // bitmask will set 8 msb in ResTmp to sum of all B8Counts in 8 bit blocks.
    auto MulMask = B.buildConstant(Ty, APInt::getSplat(Size, APInt(8, 0x01)));

    // Shift count result from 8 high bits to low bits.
    auto C_SizeM8 = B.buildConstant(Ty, Size - 8);

    auto IsMulSupported = [this](const LLT Ty) {
      auto Action = LI.getAction({TargetOpcode::G_MUL, {Ty}}).Action;
      return Action == Legal || Action == WidenScalar || Action == Custom;
    };
    if (IsMulSupported(Ty)) {
      auto ResTmp = B.buildMul(Ty, B8Count, MulMask);
      B.buildLShr(MI.getOperand(0).getReg(), ResTmp, C_SizeM8);
    } else {
      auto ResTmp = B8Count;
      for (unsigned Shift = 8; Shift < Size; Shift *= 2) {
        auto ShiftC = B.buildConstant(Ty, Shift);
        auto Shl = B.buildShl(Ty, ResTmp, ShiftC);
        ResTmp = B.buildAdd(Ty, ResTmp, Shl);
      }
      B.buildLShr(MI.getOperand(0).getReg(), ResTmp, C_SizeM8);
    }
    MI.eraseFromParent();
    return Legalized;
  }
  case TargetOpcode::G_CTLS: {
    auto [DstReg, DstTy, SrcReg, SrcTy] = MI.getFirst2RegLLTs();

    // ctls(x) -> ctlz(x ^ (x >> (N - 1))) - 1
    auto SignIdxC =
        MIRBuilder.buildConstant(SrcTy, SrcTy.getScalarSizeInBits() - 1);
    auto OneC = MIRBuilder.buildConstant(DstTy, 1);

    auto Shr = MIRBuilder.buildAShr(SrcTy, SrcReg, SignIdxC);

    auto Xor = MIRBuilder.buildXor(SrcTy, SrcReg, Shr);
    auto Ctlz = MIRBuilder.buildCTLZ(DstTy, Xor);

    MIRBuilder.buildSub(DstReg, Ctlz, OneC);
    MI.eraseFromParent();
    return Legalized;
  }
  }
}

// Check that (every element of) Reg is undef or not an exact multiple of BW.
static bool isNonZeroModBitWidthOrUndef(const MachineRegisterInfo &MRI,
                                        Register Reg, unsigned BW) {
  return matchUnaryPredicate(
      MRI, Reg,
      [=](const Constant *C) {
        // Null constant here means an undef.
        const ConstantInt *CI = dyn_cast_or_null<ConstantInt>(C);
        return !CI || CI->getValue().urem(BW) != 0;
      },
      /*AllowUndefs*/ true);
}

LegalizerHelper::LegalizeResult
LegalizerHelper::lowerFunnelShiftWithInverse(MachineInstr &MI) {
  auto [Dst, X, Y, Z] = MI.getFirst4Regs();
  LLT Ty = MRI.getType(Dst);
  LLT ShTy = MRI.getType(Z);

  unsigned BW = Ty.getScalarSizeInBits();

  if (!isPowerOf2_32(BW))
    return UnableToLegalize;

  const bool IsFSHL = MI.getOpcode() == TargetOpcode::G_FSHL;
  unsigned RevOpcode = IsFSHL ? TargetOpcode::G_FSHR : TargetOpcode::G_FSHL;

  if (isNonZeroModBitWidthOrUndef(MRI, Z, BW)) {
    // fshl X, Y, Z -> fshr X, Y, -Z
    // fshr X, Y, Z -> fshl X, Y, -Z
    auto Zero = MIRBuilder.buildConstant(ShTy, 0);
    Z = MIRBuilder.buildSub(Ty, Zero, Z).getReg(0);
  } else {
    // fshl X, Y, Z -> fshr (srl X, 1), (fshr X, Y, 1), ~Z
    // fshr X, Y, Z -> fshl (fshl X, Y, 1), (shl Y, 1), ~Z
    auto One = MIRBuilder.buildConstant(ShTy, 1);
    if (IsFSHL) {
      Y = MIRBuilder.buildInstr(RevOpcode, {Ty}, {X, Y, One}).getReg(0);
      X = MIRBuilder.buildLShr(Ty, X, One).getReg(0);
    } else {
      X = MIRBuilder.buildInstr(RevOpcode, {Ty}, {X, Y, One}).getReg(0);
      Y = MIRBuilder.buildShl(Ty, Y, One).getReg(0);
    }

    Z = MIRBuilder.buildNot(ShTy, Z).getReg(0);
  }

  MIRBuilder.buildInstr(RevOpcode, {Dst}, {X, Y, Z});
  MI.eraseFromParent();
  return Legalized;
}

LegalizerHelper::LegalizeResult
LegalizerHelper::lowerFunnelShiftAsShifts(MachineInstr &MI) {
  auto [Dst, X, Y, Z] = MI.getFirst4Regs();
  LLT Ty = MRI.getType(Dst);
  LLT ShTy = MRI.getType(Z);

  const unsigned BW = Ty.getScalarSizeInBits();
  const bool IsFSHL = MI.getOpcode() == TargetOpcode::G_FSHL;

  Register ShX, ShY;
  Register ShAmt, InvShAmt;

  // FIXME: Emit optimized urem by constant instead of letting it expand later.
  if (isNonZeroModBitWidthOrUndef(MRI, Z, BW)) {
    // fshl: X << C | Y >> (BW - C)
    // fshr: X << (BW - C) | Y >> C
    // where C = Z % BW is not zero
    auto BitWidthC = MIRBuilder.buildConstant(ShTy, BW);
    ShAmt = MIRBuilder.buildURem(ShTy, Z, BitWidthC).getReg(0);
    InvShAmt = MIRBuilder.buildSub(ShTy, BitWidthC, ShAmt).getReg(0);
    ShX = MIRBuilder.buildShl(Ty, X, IsFSHL ? ShAmt : InvShAmt).getReg(0);
    ShY = MIRBuilder.buildLShr(Ty, Y, IsFSHL ? InvShAmt : ShAmt).getReg(0);
  } else {
    // fshl: X << (Z % BW) | Y >> 1 >> (BW - 1 - (Z % BW))
    // fshr: X << 1 << (BW - 1 - (Z % BW)) | Y >> (Z % BW)
    auto Mask = MIRBuilder.buildConstant(ShTy, BW - 1);
    if (isPowerOf2_32(BW)) {
      // Z % BW -> Z & (BW - 1)
      ShAmt = MIRBuilder.buildAnd(ShTy, Z, Mask).getReg(0);
      // (BW - 1) - (Z % BW) -> ~Z & (BW - 1)
      auto NotZ = MIRBuilder.buildNot(ShTy, Z);
      InvShAmt = MIRBuilder.buildAnd(ShTy, NotZ, Mask).getReg(0);
    } else {
      auto BitWidthC = MIRBuilder.buildConstant(ShTy, BW);
      ShAmt = MIRBuilder.buildURem(ShTy, Z, BitWidthC).getReg(0);
      InvShAmt = MIRBuilder.buildSub(ShTy, Mask, ShAmt).getReg(0);
    }

    auto One = MIRBuilder.buildConstant(ShTy, 1);
    if (IsFSHL) {
      ShX = MIRBuilder.buildShl(Ty, X, ShAmt).getReg(0);
      auto ShY1 = MIRBuilder.buildLShr(Ty, Y, One);
      ShY = MIRBuilder.buildLShr(Ty, ShY1, InvShAmt).getReg(0);
    } else {
      auto ShX1 = MIRBuilder.buildShl(Ty, X, One);
      ShX = MIRBuilder.buildShl(Ty, ShX1, InvShAmt).getReg(0);
      ShY = MIRBuilder.buildLShr(Ty, Y, ShAmt).getReg(0);
    }
  }

  MIRBuilder.buildOr(Dst, ShX, ShY, MachineInstr::Disjoint);
  MI.eraseFromParent();
  return Legalized;
}

LegalizerHelper::LegalizeResult
LegalizerHelper::lowerFunnelShift(MachineInstr &MI) {
  // These operations approximately do the following (while avoiding undefined
  // shifts by BW):
  // G_FSHL: (X << (Z % BW)) | (Y >> (BW - (Z % BW)))
  // G_FSHR: (X << (BW - (Z % BW))) | (Y >> (Z % BW))
  Register Dst = MI.getOperand(0).getReg();
  LLT Ty = MRI.getType(Dst);
  LLT ShTy = MRI.getType(MI.getOperand(3).getReg());

  bool IsFSHL = MI.getOpcode() == TargetOpcode::G_FSHL;
  unsigned RevOpcode = IsFSHL ? TargetOpcode::G_FSHR : TargetOpcode::G_FSHL;

  // TODO: Use smarter heuristic that accounts for vector legalization.
  if (LI.getAction({RevOpcode, {Ty, ShTy}}).Action == Lower)
    return lowerFunnelShiftAsShifts(MI);

  // This only works for powers of 2, fallback to shifts if it fails.
  LegalizerHelper::LegalizeResult Result = lowerFunnelShiftWithInverse(MI);
  if (Result == UnableToLegalize)
    return lowerFunnelShiftAsShifts(MI);
  return Result;
}

LegalizerHelper::LegalizeResult LegalizerHelper::lowerEXT(MachineInstr &MI) {
  auto [Dst, Src] = MI.getFirst2Regs();
  LLT DstTy = MRI.getType(Dst);
  LLT SrcTy = MRI.getType(Src);

  uint32_t DstTySize = DstTy.getSizeInBits();
  uint32_t DstTyScalarSize = DstTy.getScalarSizeInBits();
  uint32_t SrcTyScalarSize = SrcTy.getScalarSizeInBits();

  if (!isPowerOf2_32(DstTySize) || !isPowerOf2_32(DstTyScalarSize) ||
      !isPowerOf2_32(SrcTyScalarSize))
    return UnableToLegalize;

  // The step between extend is too large, split it by creating an intermediate
  // extend instruction
  if (SrcTyScalarSize * 2 < DstTyScalarSize) {
    LLT MidTy = SrcTy.changeElementSize(SrcTyScalarSize * 2);
    // If the destination type is illegal, split it into multiple statements
    // zext x -> zext(merge(zext(unmerge), zext(unmerge)))
    auto NewExt = MIRBuilder.buildInstr(MI.getOpcode(), {MidTy}, {Src});
    // Unmerge the vector
    LLT EltTy = MidTy.changeElementCount(
        MidTy.getElementCount().divideCoefficientBy(2));
    auto UnmergeSrc = MIRBuilder.buildUnmerge(EltTy, NewExt);

    // ZExt the vectors
    LLT ZExtResTy = DstTy.changeElementCount(
        DstTy.getElementCount().divideCoefficientBy(2));
    auto ZExtRes1 = MIRBuilder.buildInstr(MI.getOpcode(), {ZExtResTy},
                                          {UnmergeSrc.getReg(0)});
    auto ZExtRes2 = MIRBuilder.buildInstr(MI.getOpcode(), {ZExtResTy},
                                          {UnmergeSrc.getReg(1)});

    // Merge the ending vectors
    MIRBuilder.buildMergeLikeInstr(Dst, {ZExtRes1, ZExtRes2});

    MI.eraseFromParent();
    return Legalized;
  }
  return UnableToLegalize;
}

LegalizerHelper::LegalizeResult LegalizerHelper::lowerTRUNC(MachineInstr &MI) {
  // MachineIRBuilder &MIRBuilder = Helper.MIRBuilder;
  MachineRegisterInfo &MRI = *MIRBuilder.getMRI();
  // Similar to how operand splitting is done in SelectiondDAG, we can handle
  // %res(v8s8) = G_TRUNC %in(v8s32) by generating:
  //   %inlo(<4x s32>), %inhi(<4 x s32>) = G_UNMERGE %in(<8 x s32>)
  //   %lo16(<4 x s16>) = G_TRUNC %inlo
  //   %hi16(<4 x s16>) = G_TRUNC %inhi
  //   %in16(<8 x s16>) = G_CONCAT_VECTORS %lo16, %hi16
  //   %res(<8 x s8>) = G_TRUNC %in16

  assert(MI.getOpcode() == TargetOpcode::G_TRUNC);

  Register DstReg = MI.getOperand(0).getReg();
  Register SrcReg = MI.getOperand(1).getReg();
  LLT DstTy = MRI.getType(DstReg);
  LLT SrcTy = MRI.getType(SrcReg);

  if (DstTy.isVector() && isPowerOf2_32(DstTy.getNumElements()) &&
      isPowerOf2_32(DstTy.getScalarSizeInBits()) &&
      isPowerOf2_32(SrcTy.getNumElements()) &&
      isPowerOf2_32(SrcTy.getScalarSizeInBits())) {
    // Split input type.
    LLT SplitSrcTy = SrcTy.changeElementCount(
        SrcTy.getElementCount().divideCoefficientBy(2));

    // First, split the source into two smaller vectors.
    SmallVector<Register, 2> SplitSrcs;
    extractParts(SrcReg, SplitSrcTy, 2, SplitSrcs, MIRBuilder, MRI);

    // Truncate the splits into intermediate narrower elements.
    LLT InterTy;
    if (DstTy.getScalarSizeInBits() * 2 < SrcTy.getScalarSizeInBits())
      InterTy = SplitSrcTy.changeElementSize(DstTy.getScalarSizeInBits() * 2);
    else
      InterTy = SplitSrcTy.changeElementSize(DstTy.getScalarSizeInBits());
    for (Register &Src : SplitSrcs)
      Src = MIRBuilder.buildTrunc(InterTy, Src).getReg(0);

    // Combine the new truncates into one vector
    auto Merge = MIRBuilder.buildMergeLikeInstr(
        DstTy.changeElementSize(InterTy.getScalarSizeInBits()), SplitSrcs);

    // Truncate the new vector to the final result type
    if (DstTy.getScalarSizeInBits() * 2 < SrcTy.getScalarSizeInBits())
      MIRBuilder.buildTrunc(MI.getOperand(0).getReg(), Merge.getReg(0));
    else
      MIRBuilder.buildCopy(MI.getOperand(0).getReg(), Merge.getReg(0));

    MI.eraseFromParent();

    return Legalized;
  }
  return UnableToLegalize;
}

LegalizerHelper::LegalizeResult
LegalizerHelper::lowerRotateWithReverseRotate(MachineInstr &MI) {
  auto [Dst, DstTy, Src, SrcTy, Amt, AmtTy] = MI.getFirst3RegLLTs();
  auto Zero = MIRBuilder.buildConstant(AmtTy, 0);
  bool IsLeft = MI.getOpcode() == TargetOpcode::G_ROTL;
  unsigned RevRot = IsLeft ? TargetOpcode::G_ROTR : TargetOpcode::G_ROTL;
  auto Neg = MIRBuilder.buildSub(AmtTy, Zero, Amt);
  MIRBuilder.buildInstr(RevRot, {Dst}, {Src, Neg});
  MI.eraseFromParent();
  return Legalized;
}

LegalizerHelper::LegalizeResult LegalizerHelper::lowerRotate(MachineInstr &MI) {
  auto [Dst, DstTy, Src, SrcTy, Amt, AmtTy] = MI.getFirst3RegLLTs();

  unsigned EltSizeInBits = DstTy.getScalarSizeInBits();
  bool IsLeft = MI.getOpcode() == TargetOpcode::G_ROTL;

  MIRBuilder.setInstrAndDebugLoc(MI);

  // If a rotate in the other direction is supported, use it.
  unsigned RevRot = IsLeft ? TargetOpcode::G_ROTR : TargetOpcode::G_ROTL;
  if (LI.isLegalOrCustom({RevRot, {DstTy, SrcTy}}) &&
      isPowerOf2_32(EltSizeInBits))
    return lowerRotateWithReverseRotate(MI);

  // If a funnel shift is supported, use it.
  unsigned FShOpc = IsLeft ? TargetOpcode::G_FSHL : TargetOpcode::G_FSHR;
  unsigned RevFsh = !IsLeft ? TargetOpcode::G_FSHL : TargetOpcode::G_FSHR;
  bool IsFShLegal = false;
  if ((IsFShLegal = LI.isLegalOrCustom({FShOpc, {DstTy, AmtTy}})) ||
      LI.isLegalOrCustom({RevFsh, {DstTy, AmtTy}})) {
    auto buildFunnelShift = [&](unsigned Opc, Register R1, Register R2,
                                Register R3) {
      MIRBuilder.buildInstr(Opc, {R1}, {R2, R2, R3});
      MI.eraseFromParent();
      return Legalized;
    };
    // If a funnel shift in the other direction is supported, use it.
    if (IsFShLegal) {
      return buildFunnelShift(FShOpc, Dst, Src, Amt);
    } else if (isPowerOf2_32(EltSizeInBits)) {
      Amt = MIRBuilder.buildNeg(DstTy, Amt).getReg(0);
      return buildFunnelShift(RevFsh, Dst, Src, Amt);
    }
  }

  auto Zero = MIRBuilder.buildConstant(AmtTy, 0);
  unsigned ShOpc = IsLeft ? TargetOpcode::G_SHL : TargetOpcode::G_LSHR;
  unsigned RevShiftOpc = IsLeft ? TargetOpcode::G_LSHR : TargetOpcode::G_SHL;
  auto BitWidthMinusOneC = MIRBuilder.buildConstant(AmtTy, EltSizeInBits - 1);
  Register ShVal;
  Register RevShiftVal;
  if (isPowerOf2_32(EltSizeInBits)) {
    // (rotl x, c) -> x << (c & (w - 1)) | x >> (-c & (w - 1))
    // (rotr x, c) -> x >> (c & (w - 1)) | x << (-c & (w - 1))
    auto NegAmt = MIRBuilder.buildSub(AmtTy, Zero, Amt);
    auto ShAmt = MIRBuilder.buildAnd(AmtTy, Amt, BitWidthMinusOneC);
    ShVal = MIRBuilder.buildInstr(ShOpc, {DstTy}, {Src, ShAmt}).getReg(0);
    auto RevAmt = MIRBuilder.buildAnd(AmtTy, NegAmt, BitWidthMinusOneC);
    RevShiftVal =
        MIRBuilder.buildInstr(RevShiftOpc, {DstTy}, {Src, RevAmt}).getReg(0);
  } else {
    // (rotl x, c) -> x << (c % w) | x >> 1 >> (w - 1 - (c % w))
    // (rotr x, c) -> x >> (c % w) | x << 1 << (w - 1 - (c % w))
    auto BitWidthC = MIRBuilder.buildConstant(AmtTy, EltSizeInBits);
    auto ShAmt = MIRBuilder.buildURem(AmtTy, Amt, BitWidthC);
    ShVal = MIRBuilder.buildInstr(ShOpc, {DstTy}, {Src, ShAmt}).getReg(0);
    auto RevAmt = MIRBuilder.buildSub(AmtTy, BitWidthMinusOneC, ShAmt);
    auto One = MIRBuilder.buildConstant(AmtTy, 1);
    auto Inner = MIRBuilder.buildInstr(RevShiftOpc, {DstTy}, {Src, One});
    RevShiftVal =
        MIRBuilder.buildInstr(RevShiftOpc, {DstTy}, {Inner, RevAmt}).getReg(0);
  }
  MIRBuilder.buildOr(Dst, ShVal, RevShiftVal, MachineInstr::Disjoint);
  MI.eraseFromParent();
  return Legalized;
}

// Expand s32 = G_UITOFP s64 using bit operations to an IEEE float
// representation.
LegalizerHelper::LegalizeResult
LegalizerHelper::lowerU64ToF32BitOps(MachineInstr &MI) {
  auto [Dst, Src] = MI.getFirst2Regs();
  const LLT S64 = LLT::scalar(64);
  const LLT S32 = LLT::scalar(32);
  const LLT S1 = LLT::scalar(1);

  assert(MRI.getType(Src) == S64 && MRI.getType(Dst) == S32);

  // unsigned cul2f(ulong u) {
  //   uint lz = clz(u);
  //   uint e = (u != 0) ? 127U + 63U - lz : 0;
  //   u = (u << lz) & 0x7fffffffffffffffUL;
  //   ulong t = u & 0xffffffffffUL;
  //   uint v = (e << 23) | (uint)(u >> 40);
  //   uint r = t > 0x8000000000UL ? 1U : (t == 0x8000000000UL ? v & 1U : 0U);
  //   return as_float(v + r);
  // }

  auto Zero32 = MIRBuilder.buildConstant(S32, 0);
  auto Zero64 = MIRBuilder.buildConstant(S64, 0);

  auto LZ = MIRBuilder.buildCTLZ_ZERO_POISON(S32, Src);

  auto K = MIRBuilder.buildConstant(S32, 127U + 63U);
  auto Sub = MIRBuilder.buildSub(S32, K, LZ);

  auto NotZero = MIRBuilder.buildICmp(CmpInst::ICMP_NE, S1, Src, Zero64);
  auto E = MIRBuilder.buildSelect(S32, NotZero, Sub, Zero32);

  auto Mask0 = MIRBuilder.buildConstant(S64, (-1ULL) >> 1);
  auto ShlLZ = MIRBuilder.buildShl(S64, Src, LZ);

  auto U = MIRBuilder.buildAnd(S64, ShlLZ, Mask0);

  auto Mask1 = MIRBuilder.buildConstant(S64, 0xffffffffffULL);
  auto T = MIRBuilder.buildAnd(S64, U, Mask1);

  auto UShl = MIRBuilder.buildLShr(S64, U, MIRBuilder.buildConstant(S64, 40));
  auto ShlE = MIRBuilder.buildShl(S32, E, MIRBuilder.buildConstant(S32, 23));
  auto V = MIRBuilder.buildOr(S32, ShlE, MIRBuilder.buildTrunc(S32, UShl));

  auto C = MIRBuilder.buildConstant(S64, 0x8000000000ULL);
  auto RCmp = MIRBuilder.buildICmp(CmpInst::ICMP_UGT, S1, T, C);
  auto TCmp = MIRBuilder.buildICmp(CmpInst::ICMP_EQ, S1, T, C);
  auto One = MIRBuilder.buildConstant(S32, 1);

  auto VTrunc1 = MIRBuilder.buildAnd(S32, V, One);
  auto Select0 = MIRBuilder.buildSelect(S32, TCmp, VTrunc1, Zero32);
  auto R = MIRBuilder.buildSelect(S32, RCmp, One, Select0);
  MIRBuilder.buildAdd(Dst, V, R);

  MI.eraseFromParent();
  return Legalized;
}

// Expand s32 = G_UITOFP s64 to an IEEE float representation using bit
// operations and G_SITOFP
LegalizerHelper::LegalizeResult
LegalizerHelper::lowerU64ToF32WithSITOFP(MachineInstr &MI) {
  auto [Dst, Src] = MI.getFirst2Regs();
  const LLT S64 = LLT::scalar(64);
  const LLT S32 = LLT::scalar(32);
  const LLT S1 = LLT::scalar(1);

  assert(MRI.getType(Src) == S64 && MRI.getType(Dst) == S32);

  // For i64 < INT_MAX we simply reuse SITOFP.
  // Otherwise, divide i64 by 2, round result by ORing with the lowest bit
  // saved before division, convert to float by SITOFP, multiply the result
  // by 2.
  auto One = MIRBuilder.buildConstant(S64, 1);
  auto Zero = MIRBuilder.buildConstant(S64, 0);
  // Result if Src < INT_MAX
  auto SmallResult = MIRBuilder.buildSITOFP(S32, Src);
  // Result if Src >= INT_MAX
  auto Halved = MIRBuilder.buildLShr(S64, Src, One);
  auto LowerBit = MIRBuilder.buildAnd(S64, Src, One);
  auto RoundedHalved = MIRBuilder.buildOr(S64, Halved, LowerBit);
  auto HalvedFP = MIRBuilder.buildSITOFP(S32, RoundedHalved);
  auto LargeResult = MIRBuilder.buildFAdd(S32, HalvedFP, HalvedFP);
  // Check if the original value is larger than INT_MAX by comparing with
  // zero to pick one of the two conversions.
  auto IsLarge =
      MIRBuilder.buildICmp(CmpInst::Predicate::ICMP_SLT, S1, Src, Zero);
  MIRBuilder.buildSelect(Dst, IsLarge, LargeResult, SmallResult);

  MI.eraseFromParent();
  return Legalized;
}

// Expand s64 = G_UITOFP s64 using bit and float arithmetic operations to an
// IEEE double representation.
LegalizerHelper::LegalizeResult
LegalizerHelper::lowerU64ToF64BitFloatOps(MachineInstr &MI) {
  auto [Dst, Src] = MI.getFirst2Regs();
  const LLT S64 = LLT::scalar(64);
  const LLT S32 = LLT::scalar(32);

  assert(MRI.getType(Src) == S64 && MRI.getType(Dst) == S64);

  // We create double value from 32 bit parts with 32 exponent difference.
  // Note that + and - are float operations that adjust the implicit leading
  // one, the bases 2^52 and 2^84 are for illustrative purposes.
  //
  // X = 2^52 * 1.0...LowBits
  // Y = 2^84 * 1.0...HighBits
  // Scratch = 2^84 * 1.0...HighBits - 2^84 * 1.0 - 2^52 * 1.0
  //         = - 2^52 * 1.0...HighBits
  // Result = - 2^52 * 1.0...HighBits + 2^52 * 1.0...LowBits
  auto TwoP52 = MIRBuilder.buildConstant(S64, UINT64_C(0x4330000000000000));
  auto TwoP84 = MIRBuilder.buildConstant(S64, UINT64_C(0x4530000000000000));
  auto TwoP52P84 = llvm::bit_cast<double>(UINT64_C(0x4530000000100000));
  auto TwoP52P84FP = MIRBuilder.buildFConstant(S64, TwoP52P84);
  auto HalfWidth = MIRBuilder.buildConstant(S64, 32);

  auto LowBits = MIRBuilder.buildTrunc(S32, Src);
  LowBits = MIRBuilder.buildZExt(S64, LowBits);
  auto LowBitsFP = MIRBuilder.buildOr(S64, TwoP52, LowBits);
  auto HighBits = MIRBuilder.buildLShr(S64, Src, HalfWidth);
  auto HighBitsFP = MIRBuilder.buildOr(S64, TwoP84, HighBits);
  auto Scratch = MIRBuilder.buildFSub(S64, HighBitsFP, TwoP52P84FP);
  MIRBuilder.buildFAdd(Dst, Scratch, LowBitsFP);

  MI.eraseFromParent();
  return Legalized;
}

/// i64->fp16 itofp can be lowered to i64->f64,f64->f32,f32->f16. We cannot
/// convert fpround f64->f16 without double-rounding, so we manually perform the
/// lowering here where we know it is valid.
static LegalizerHelper::LegalizeResult
loweri64tof16ITOFP(MachineInstr &MI, Register Dst, LLT DstTy, Register Src,
                   LLT SrcTy, MachineIRBuilder &MIRBuilder) {
  auto DstFpTy =
      SrcTy.changeElementType(LLT::floatIEEE(SrcTy.getScalarSizeInBits()));
  auto M1 = MI.getOpcode() == TargetOpcode::G_UITOFP
                ? MIRBuilder.buildUITOFP(DstFpTy, Src)
                : MIRBuilder.buildSITOFP(DstFpTy, Src);
  LLT F32Ty = DstFpTy.changeElementSize(32);
  auto M2 = MIRBuilder.buildFPTrunc(F32Ty, M1);
  MIRBuilder.buildFPTrunc(Dst, M2);
  MI.eraseFromParent();
  return LegalizerHelper::Legalized;
}

LegalizerHelper::LegalizeResult LegalizerHelper::lowerUITOFP(MachineInstr &MI) {
  auto [Dst, DstTy, Src, SrcTy] = MI.getFirst2RegLLTs();

  if (SrcTy == LLT::scalar(1)) {
    auto True = MIRBuilder.buildFConstant(DstTy, 1.0);
    auto False = MIRBuilder.buildFConstant(DstTy, 0.0);
    MIRBuilder.buildSelect(Dst, Src, True, False);
    MI.eraseFromParent();
    return Legalized;
  }

  if (DstTy.getScalarSizeInBits() == 16 && SrcTy.getScalarSizeInBits() == 64)
    return loweri64tof16ITOFP(MI, Dst, DstTy, Src, SrcTy, MIRBuilder);

  if (SrcTy != LLT::scalar(64))
    return UnableToLegalize;

  if (DstTy == LLT::scalar(32))
    // TODO: SelectionDAG has several alternative expansions to port which may
    // be more reasonable depending on the available instructions. We also need
    // a more advanced mechanism to choose an optimal version depending on
    // target features such as sitofp or CTLZ availability.
    return lowerU64ToF32WithSITOFP(MI);

  if (DstTy == LLT::scalar(64))
    return lowerU64ToF64BitFloatOps(MI);

  return UnableToLegalize;
}

LegalizerHelper::LegalizeResult LegalizerHelper::lowerSITOFP(MachineInstr &MI) {
  auto [Dst, DstTy, Src, SrcTy] = MI.getFirst2RegLLTs();

  const LLT I64 = LLT::integer(64);
  const LLT I32 = LLT::integer(32);
  const LLT I1 = LLT::integer(1);

  if (SrcTy == I1) {
    auto True = MIRBuilder.buildFConstant(DstTy, -1.0);
    auto False = MIRBuilder.buildFConstant(DstTy, 0.0);
    MIRBuilder.buildSelect(Dst, Src, True, False);
    MI.eraseFromParent();
    return Legalized;
  }

  if (DstTy.getScalarSizeInBits() == 16 && SrcTy.getScalarSizeInBits() == 64)
    return loweri64tof16ITOFP(MI, Dst, DstTy, Src, SrcTy, MIRBuilder);

  if (SrcTy != I64)
    return UnableToLegalize;

  if (DstTy.getScalarSizeInBits() == 32) {
    // signed cl2f(long l) {
    //   long s = l >> 63;
    //   float r = cul2f((l + s) ^ s);
    //   return s ? -r : r;
    // }
    Register L = Src;
    auto SignBit = MIRBuilder.buildConstant(I64, 63);
    auto S = MIRBuilder.buildAShr(I64, L, SignBit);

    auto LPlusS = MIRBuilder.buildAdd(I64, L, S);
    auto Xor = MIRBuilder.buildXor(I64, LPlusS, S);
    auto R = MIRBuilder.buildUITOFP(I32, Xor);

    auto RNeg = MIRBuilder.buildFNeg(I32, R);
    auto SignNotZero = MIRBuilder.buildICmp(CmpInst::ICMP_NE, I1, S,
                                            MIRBuilder.buildConstant(I64, 0));
    MIRBuilder.buildSelect(Dst, SignNotZero, RNeg, R);
    MI.eraseFromParent();
    return Legalized;
  }

  return UnableToLegalize;
}

LegalizerHelper::LegalizeResult LegalizerHelper::lowerFPTOUI(MachineInstr &MI) {
  auto [Dst, DstTy, Src, SrcTy] = MI.getFirst2RegLLTs();
  const LLT S64 = LLT::scalar(64);
  const LLT S32 = LLT::scalar(32);

  if (SrcTy != S64 && SrcTy != S32)
    return UnableToLegalize;
  if (DstTy != S32 && DstTy != S64)
    return UnableToLegalize;

  // FPTOSI gives same result as FPTOUI for positive signed integers.
  // FPTOUI needs to deal with fp values that convert to unsigned integers
  // greater or equal to 2^31 for float or 2^63 for double. For brevity 2^Exp.

  APInt TwoPExpInt = APInt::getSignMask(DstTy.getSizeInBits());
  APFloat TwoPExpFP(SrcTy.getSizeInBits() == 32 ? APFloat::IEEEsingle()
                                                : APFloat::IEEEdouble(),
                    APInt::getZero(SrcTy.getSizeInBits()));
  TwoPExpFP.convertFromAPInt(TwoPExpInt, false, APFloat::rmNearestTiesToEven);

  MachineInstrBuilder FPTOSI = MIRBuilder.buildFPTOSI(DstTy, Src);

  MachineInstrBuilder Threshold = MIRBuilder.buildFConstant(SrcTy, TwoPExpFP);
  // For fp Value greater or equal to Threshold(2^Exp), we use FPTOSI on
  // (Value - 2^Exp) and add 2^Exp by setting highest bit in result to 1.
  MachineInstrBuilder FSub = MIRBuilder.buildFSub(SrcTy, Src, Threshold);
  MachineInstrBuilder ResLowBits = MIRBuilder.buildFPTOSI(DstTy, FSub);
  MachineInstrBuilder ResHighBit = MIRBuilder.buildConstant(DstTy, TwoPExpInt);
  MachineInstrBuilder Res = MIRBuilder.buildXor(DstTy, ResLowBits, ResHighBit);

  const LLT S1 = LLT::scalar(1);

  MachineInstrBuilder FCMP =
      MIRBuilder.buildFCmp(CmpInst::FCMP_ULT, S1, Src, Threshold);
  MIRBuilder.buildSelect(Dst, FCMP, FPTOSI, Res);

  MI.eraseFromParent();
  return Legalized;
}

LegalizerHelper::LegalizeResult LegalizerHelper::lowerFPTOSI(MachineInstr &MI) {
  auto [Dst, DstTy, Src, SrcTy] = MI.getFirst2RegLLTs();
  const LLT S64 = LLT::scalar(64);
  const LLT S32 = LLT::scalar(32);

  // FIXME: Only f32 to i64 conversions are supported.
  if (SrcTy.getScalarType() != S32 || DstTy.getScalarType() != S64)
    return UnableToLegalize;

  // Expand f32 -> i64 conversion
  // This algorithm comes from compiler-rt's implementation of fixsfdi:
  // https://github.com/llvm/llvm-project/blob/main/compiler-rt/lib/builtins/fixsfdi.c

  unsigned SrcEltBits = SrcTy.getScalarSizeInBits();

  auto ExponentMask = MIRBuilder.buildConstant(SrcTy, 0x7F800000);
  auto ExponentLoBit = MIRBuilder.buildConstant(SrcTy, 23);

  auto AndExpMask = MIRBuilder.buildAnd(SrcTy, Src, ExponentMask);
  auto ExponentBits = MIRBuilder.buildLShr(SrcTy, AndExpMask, ExponentLoBit);

  auto SignMask = MIRBuilder.buildConstant(SrcTy,
                                           APInt::getSignMask(SrcEltBits));
  auto AndSignMask = MIRBuilder.buildAnd(SrcTy, Src, SignMask);
  auto SignLowBit = MIRBuilder.buildConstant(SrcTy, SrcEltBits - 1);
  auto Sign = MIRBuilder.buildAShr(SrcTy, AndSignMask, SignLowBit);
  Sign = MIRBuilder.buildSExt(DstTy, Sign);

  auto MantissaMask = MIRBuilder.buildConstant(SrcTy, 0x007FFFFF);
  auto AndMantissaMask = MIRBuilder.buildAnd(SrcTy, Src, MantissaMask);
  auto K = MIRBuilder.buildConstant(SrcTy, 0x00800000);

  auto R = MIRBuilder.buildOr(SrcTy, AndMantissaMask, K);
  R = MIRBuilder.buildZExt(DstTy, R);

  auto Bias = MIRBuilder.buildConstant(SrcTy, 127);
  auto Exponent = MIRBuilder.buildSub(SrcTy, ExponentBits, Bias);
  auto SubExponent = MIRBuilder.buildSub(SrcTy, Exponent, ExponentLoBit);
  auto ExponentSub = MIRBuilder.buildSub(SrcTy, ExponentLoBit, Exponent);

  auto Shl = MIRBuilder.buildShl(DstTy, R, SubExponent);
  auto Srl = MIRBuilder.buildLShr(DstTy, R, ExponentSub);

  const LLT S1 = LLT::scalar(1);
  auto CmpGt = MIRBuilder.buildICmp(CmpInst::ICMP_SGT,
                                    S1, Exponent, ExponentLoBit);

  R = MIRBuilder.buildSelect(DstTy, CmpGt, Shl, Srl);

  auto XorSign = MIRBuilder.buildXor(DstTy, R, Sign);
  auto Ret = MIRBuilder.buildSub(DstTy, XorSign, Sign);

  auto ZeroSrcTy = MIRBuilder.buildConstant(SrcTy, 0);

  auto ExponentLt0 = MIRBuilder.buildICmp(CmpInst::ICMP_SLT,
                                          S1, Exponent, ZeroSrcTy);

  auto ZeroDstTy = MIRBuilder.buildConstant(DstTy, 0);
  MIRBuilder.buildSelect(Dst, ExponentLt0, ZeroDstTy, Ret);

  MI.eraseFromParent();
  return Legalized;
}

LegalizerHelper::LegalizeResult
LegalizerHelper::lowerFPTOINT_SAT(MachineInstr &MI) {
  auto [Dst, DstTy, Src, SrcTy] = MI.getFirst2RegLLTs();

  bool IsSigned = MI.getOpcode() == TargetOpcode::G_FPTOSI_SAT;
  unsigned SatWidth = DstTy.getScalarSizeInBits();

  // Determine minimum and maximum integer values and their corresponding
  // floating-point values.
  APInt MinInt, MaxInt;
  if (IsSigned) {
    MinInt = APInt::getSignedMinValue(SatWidth);
    MaxInt = APInt::getSignedMaxValue(SatWidth);
  } else {
    MinInt = APInt::getMinValue(SatWidth);
    MaxInt = APInt::getMaxValue(SatWidth);
  }

  const fltSemantics &Semantics = getFltSemanticForLLT(SrcTy.getScalarType());
  APFloat MinFloat(Semantics);
  APFloat MaxFloat(Semantics);

  APFloat::opStatus MinStatus =
      MinFloat.convertFromAPInt(MinInt, IsSigned, APFloat::rmTowardZero);
  APFloat::opStatus MaxStatus =
      MaxFloat.convertFromAPInt(MaxInt, IsSigned, APFloat::rmTowardZero);
  bool AreExactFloatBounds = !(MinStatus & APFloat::opStatus::opInexact) &&
                             !(MaxStatus & APFloat::opStatus::opInexact);

  // If the integer bounds are exactly representable as floats, emit a
  // min+max+fptoi sequence. Otherwise we have to use a sequence of comparisons
  // and selects.
  if (AreExactFloatBounds) {
    // Clamp Src by MinFloat from below. If Src is NaN the result is MinFloat.
    auto MaxC = MIRBuilder.buildFConstant(SrcTy, MinFloat);
    auto MaxP =
        MIRBuilder.buildFCmp(CmpInst::FCMP_OGT, LLT::integer(1), Src, MaxC);
    auto Max = MIRBuilder.buildSelect(SrcTy, MaxP, Src, MaxC);
    // Clamp by MaxFloat from above. NaN cannot occur.
    auto MinC = MIRBuilder.buildFConstant(SrcTy, MaxFloat);
    auto MinP = MIRBuilder.buildFCmp(CmpInst::FCMP_OLT, LLT::integer(1), Max,
                                     MinC, MachineInstr::FmNoNans);
    auto Min =
        MIRBuilder.buildSelect(SrcTy, MinP, Max, MinC, MachineInstr::FmNoNans);
    // Convert clamped value to integer. In the unsigned case we're done,
    // because we mapped NaN to MinFloat, which will cast to zero.
    if (!IsSigned) {
      MIRBuilder.buildFPTOUI(Dst, Min);
      MI.eraseFromParent();
      return Legalized;
    }

    // Otherwise, select 0 if Src is NaN.
    auto FpToInt = MIRBuilder.buildFPTOSI(DstTy, Min);
    auto IsZero =
        MIRBuilder.buildFCmp(CmpInst::FCMP_UNO, LLT::integer(1), Src, Src);
    MIRBuilder.buildSelect(Dst, IsZero, MIRBuilder.buildConstant(DstTy, 0),
                           FpToInt);
    MI.eraseFromParent();
    return Legalized;
  }

  // Result of direct conversion. The assumption here is that the operation is
  // non-trapping and it's fine to apply it to an out-of-range value if we
  // select it away later.
  auto FpToInt = IsSigned ? MIRBuilder.buildFPTOSI(DstTy, Src)
                          : MIRBuilder.buildFPTOUI(DstTy, Src);

  // If Src ULT MinFloat, select MinInt. In particular, this also selects
  // MinInt if Src is NaN.
  auto ULT = MIRBuilder.buildFCmp(CmpInst::FCMP_ULT, LLT::integer(1), Src,
                                  MIRBuilder.buildFConstant(SrcTy, MinFloat));
  auto Max = MIRBuilder.buildSelect(
      DstTy, ULT, MIRBuilder.buildConstant(DstTy, MinInt), FpToInt);
  // If Src OGT MaxFloat, select MaxInt.
  auto OGT = MIRBuilder.buildFCmp(CmpInst::FCMP_OGT, LLT::integer(1), Src,
                                  MIRBuilder.buildFConstant(SrcTy, MaxFloat));

  // In the unsigned case we are done, because we mapped NaN to MinInt, which
  // is already zero.
  if (!IsSigned) {
    MIRBuilder.buildSelect(Dst, OGT, MIRBuilder.buildConstant(DstTy, MaxInt),
                           Max);
    MI.eraseFromParent();
    return Legalized;
  }

  // Otherwise, select 0 if Src is NaN.
  auto Min = MIRBuilder.buildSelect(
      DstTy, OGT, MIRBuilder.buildConstant(DstTy, MaxInt), Max);
  auto IsZero =
      MIRBuilder.buildFCmp(CmpInst::FCMP_UNO, LLT::integer(1), Src, Src);
  MIRBuilder.buildSelect(Dst, IsZero, MIRBuilder.buildConstant(DstTy, 0), Min);
  MI.eraseFromParent();
  return Legalized;
}

// Floating-point conversions using truncating and extending loads and stores.
LegalizerHelper::LegalizeResult
LegalizerHelper::lowerFPExtAndTruncMem(MachineInstr &MI) {
  assert((MI.getOpcode() == TargetOpcode::G_FPEXT ||
          MI.getOpcode() == TargetOpcode::G_FPTRUNC) &&
         "Only G_FPEXT and G_FPTRUNC are expected");

  auto [DstReg, DstTy, SrcReg, SrcTy] = MI.getFirst2RegLLTs();
  MachinePointerInfo PtrInfo;
  unsigned StoreOpc;
  unsigned LoadOpc;
  LLT StackTy;
  if (MI.getOpcode() == TargetOpcode::G_FPEXT) {
    StackTy = SrcTy;
    StoreOpc = TargetOpcode::G_STORE;
    LoadOpc = TargetOpcode::G_FPEXTLOAD;
  } else {
    StackTy = DstTy;
    StoreOpc = TargetOpcode::G_FPTRUNCSTORE;
    LoadOpc = TargetOpcode::G_LOAD;
  }

  Align StackTyAlign = getStackTemporaryAlignment(StackTy);
  auto StackTemp =
      createStackTemporary(StackTy.getSizeInBytes(), StackTyAlign, PtrInfo);

  MachineFunction &MF = MIRBuilder.getMF();
  auto *StoreMMO = MF.getMachineMemOperand(PtrInfo, MachineMemOperand::MOStore,
                                           StackTy, StackTyAlign);
  MIRBuilder.buildStoreInstr(StoreOpc, SrcReg, StackTemp, *StoreMMO);

  auto *LoadMMO = MF.getMachineMemOperand(PtrInfo, MachineMemOperand::MOLoad,
                                          StackTy, StackTyAlign);
  MIRBuilder.buildLoadInstr(LoadOpc, DstReg, StackTemp, *LoadMMO);

  MI.eraseFromParent();
  return Legalized;
}

// f64 -> f16 conversion using round-to-nearest-even rounding mode.
LegalizerHelper::LegalizeResult
LegalizerHelper::lowerFPTRUNC_F64_TO_F16(MachineInstr &MI) {
  const LLT S1 = LLT::scalar(1);
  const LLT S32 = LLT::scalar(32);

  auto [Dst, Src] = MI.getFirst2Regs();
  assert(MRI.getType(Dst).getScalarType() == LLT::float16() &&
         MRI.getType(Src).getScalarType() == LLT::float64());

  if (MRI.getType(Src).isVector()) // TODO: Handle vectors directly.
    return UnableToLegalize;

  if (MI.getFlag(MachineInstr::FmAfn)) {
    unsigned Flags = MI.getFlags();
    auto Src32 = MIRBuilder.buildFPTrunc(S32, Src, Flags);
    MIRBuilder.buildFPTrunc(Dst, Src32, Flags);
    MI.eraseFromParent();
    return Legalized;
  }

  const unsigned ExpMask = 0x7ff;
  const unsigned ExpBiasf64 = 1023;
  const unsigned ExpBiasf16 = 15;

  auto Unmerge = MIRBuilder.buildUnmerge(S32, Src);
  Register U = Unmerge.getReg(0);
  Register UH = Unmerge.getReg(1);

  auto E = MIRBuilder.buildLShr(S32, UH, MIRBuilder.buildConstant(S32, 20));
  E = MIRBuilder.buildAnd(S32, E, MIRBuilder.buildConstant(S32, ExpMask));

  // Subtract the fp64 exponent bias (1023) to get the real exponent and
  // add the f16 bias (15) to get the biased exponent for the f16 format.
  E = MIRBuilder.buildAdd(
    S32, E, MIRBuilder.buildConstant(S32, -ExpBiasf64 + ExpBiasf16));

  auto M = MIRBuilder.buildLShr(S32, UH, MIRBuilder.buildConstant(S32, 8));
  M = MIRBuilder.buildAnd(S32, M, MIRBuilder.buildConstant(S32, 0xffe));

  auto MaskedSig = MIRBuilder.buildAnd(S32, UH,
                                       MIRBuilder.buildConstant(S32, 0x1ff));
  MaskedSig = MIRBuilder.buildOr(S32, MaskedSig, U);

  auto Zero = MIRBuilder.buildConstant(S32, 0);
  auto SigCmpNE0 = MIRBuilder.buildICmp(CmpInst::ICMP_NE, S1, MaskedSig, Zero);
  auto Lo40Set = MIRBuilder.buildZExt(S32, SigCmpNE0);
  M = MIRBuilder.buildOr(S32, M, Lo40Set);

  // (M != 0 ? 0x0200 : 0) | 0x7c00;
  auto Bits0x200 = MIRBuilder.buildConstant(S32, 0x0200);
  auto CmpM_NE0 = MIRBuilder.buildICmp(CmpInst::ICMP_NE, S1, M, Zero);
  auto SelectCC = MIRBuilder.buildSelect(S32, CmpM_NE0, Bits0x200, Zero);

  auto Bits0x7c00 = MIRBuilder.buildConstant(S32, 0x7c00);
  auto I = MIRBuilder.buildOr(S32, SelectCC, Bits0x7c00);

  // N = M | (E << 12);
  auto EShl12 = MIRBuilder.buildShl(S32, E, MIRBuilder.buildConstant(S32, 12));
  auto N = MIRBuilder.buildOr(S32, M, EShl12);

  // B = clamp(1-E, 0, 13);
  auto One = MIRBuilder.buildConstant(S32, 1);
  auto OneSubExp = MIRBuilder.buildSub(S32, One, E);
  auto B = MIRBuilder.buildSMax(S32, OneSubExp, Zero);
  B = MIRBuilder.buildSMin(S32, B, MIRBuilder.buildConstant(S32, 13));

  auto SigSetHigh = MIRBuilder.buildOr(S32, M,
                                       MIRBuilder.buildConstant(S32, 0x1000));

  auto D = MIRBuilder.buildLShr(S32, SigSetHigh, B);
  auto D0 = MIRBuilder.buildShl(S32, D, B);

  auto D0_NE_SigSetHigh = MIRBuilder.buildICmp(CmpInst::ICMP_NE, S1,
                                             D0, SigSetHigh);
  auto D1 = MIRBuilder.buildZExt(S32, D0_NE_SigSetHigh);
  D = MIRBuilder.buildOr(S32, D, D1);

  auto CmpELtOne = MIRBuilder.buildICmp(CmpInst::ICMP_SLT, S1, E, One);
  auto V = MIRBuilder.buildSelect(S32, CmpELtOne, D, N);

  auto VLow3 = MIRBuilder.buildAnd(S32, V, MIRBuilder.buildConstant(S32, 7));
  V = MIRBuilder.buildLShr(S32, V, MIRBuilder.buildConstant(S32, 2));

  auto VLow3Eq3 = MIRBuilder.buildICmp(CmpInst::ICMP_EQ, S1, VLow3,
                                       MIRBuilder.buildConstant(S32, 3));
  auto V0 = MIRBuilder.buildZExt(S32, VLow3Eq3);

  auto VLow3Gt5 = MIRBuilder.buildICmp(CmpInst::ICMP_SGT, S1, VLow3,
                                       MIRBuilder.buildConstant(S32, 5));
  auto V1 = MIRBuilder.buildZExt(S32, VLow3Gt5);

  V1 = MIRBuilder.buildOr(S32, V0, V1);
  V = MIRBuilder.buildAdd(S32, V, V1);

  auto CmpEGt30 = MIRBuilder.buildICmp(CmpInst::ICMP_SGT,  S1,
                                       E, MIRBuilder.buildConstant(S32, 30));
  V = MIRBuilder.buildSelect(S32, CmpEGt30,
                             MIRBuilder.buildConstant(S32, 0x7c00), V);

  auto CmpEGt1039 = MIRBuilder.buildICmp(CmpInst::ICMP_EQ, S1,
                                         E, MIRBuilder.buildConstant(S32, 1039));
  V = MIRBuilder.buildSelect(S32, CmpEGt1039, I, V);

  // Extract the sign bit.
  auto Sign = MIRBuilder.buildLShr(S32, UH, MIRBuilder.buildConstant(S32, 16));
  Sign = MIRBuilder.buildAnd(S32, Sign, MIRBuilder.buildConstant(S32, 0x8000));

  // Insert the sign bit
  V = MIRBuilder.buildOr(S32, Sign, V);

  MIRBuilder.buildTrunc(Dst, V);
  MI.eraseFromParent();
  return Legalized;
}

// f32 -> bf16 conversion using round-to-nearest-even rounding mode.
LegalizerHelper::LegalizeResult
LegalizerHelper::lowerFPTRUNC_F32_TO_BF16(MachineInstr &MI) {
  auto [DstReg, DstTy, SrcReg, SrcTy] = MI.getFirst2RegLLTs();
  assert(DstTy.getScalarType() == LLT::bfloat16() &&
         SrcTy.getScalarType() == LLT::float32());

  LLT I1Ty = SrcTy.changeElementType(LLT::integer(1));
  LLT I16Ty = SrcTy.changeElementType(LLT::integer(16));
  LLT I32Ty = SrcTy.changeElementType(LLT::integer(32));

  auto SrcI = MIRBuilder.buildBitcast(I32Ty, SrcReg);

  // Conversions should set NaN's quiet bit. This also prevents NaNs from
  // turning into infinities.
  auto NaN = MIRBuilder.buildOr(I32Ty, SrcI,
                                MIRBuilder.buildConstant(I32Ty, 0x400000));

  // Factor in the contribution of the low 16 bits.
  auto Lsb =
      MIRBuilder.buildLShr(I32Ty, SrcI, MIRBuilder.buildConstant(I32Ty, 16));
  Lsb = MIRBuilder.buildAnd(I32Ty, Lsb, MIRBuilder.buildConstant(I32Ty, 1));
  auto RoundingBias =
      MIRBuilder.buildAdd(I32Ty, Lsb, MIRBuilder.buildConstant(I32Ty, 0x7fff));
  auto Add = MIRBuilder.buildAdd(I32Ty, SrcI, RoundingBias);

  // Don't round if we had a NaN, we don't want to turn 0x7fffffff into
  // 0x80000000.
  if (!MI.getFlag(MachineInstr::FmNoNans)) {
    auto IsNaN = MIRBuilder.buildFCmp(CmpInst::FCMP_UNO, I1Ty, SrcReg,
                                      MIRBuilder.buildFConstant(SrcTy, 0));
    Add = MIRBuilder.buildSelect(I32Ty, IsNaN, NaN, Add);
  }

  // Now that we have rounded, shift the bits into position.
  auto Srl =
      MIRBuilder.buildLShr(I32Ty, Add, MIRBuilder.buildConstant(I32Ty, 16));
  auto Trunc = MIRBuilder.buildTrunc(I16Ty, Srl);
  MIRBuilder.buildBitcast(DstReg, Trunc);
  MI.eraseFromParent();
  return Legalized;
}

LegalizerHelper::LegalizeResult
LegalizerHelper::lowerFPTRUNC(MachineInstr &MI) {
  auto [DstTy, SrcTy] = MI.getFirst2LLTs();
  if (DstTy.getScalarType().isFloat16() && SrcTy.getScalarType().isFloat64())
    return lowerFPTRUNC_F64_TO_F16(MI);

  if (DstTy.getScalarType().isBFloat16() && SrcTy.getScalarType().isFloat32())
    return lowerFPTRUNC_F32_TO_BF16(MI);

  return lowerFPExtAndTruncMem(MI);
}

LegalizerHelper::LegalizeResult LegalizerHelper::lowerFPOWI(MachineInstr &MI) {
  auto [Dst, Src0, Src1] = MI.getFirst3Regs();
  LLT Ty = MRI.getType(Dst);

  auto CvtSrc1 = MIRBuilder.buildSITOFP(Ty, Src1);
  MIRBuilder.buildFPow(Dst, Src0, CvtSrc1, MI.getFlags());
  MI.eraseFromParent();
  return Legalized;
}

LegalizerHelper::LegalizeResult LegalizerHelper::lowerFMODF(MachineInstr &MI) {
  auto [DstFrac, DstInt, Src] = MI.getFirst3Regs();
  LLT Ty = MRI.getType(Src);
  auto Flags = MI.getFlags();
  const LLT CondTy = Ty.changeElementType(LLT::integer(1));

  auto IntPart = MIRBuilder.buildIntrinsicTrunc(Ty, Src, Flags);
  auto FracPart = MIRBuilder.buildFSub(Ty, Src, IntPart, Flags);

  Register FracToUse;
  if (MI.getFlag(MachineInstr::FmNoInfs)) {
    FracToUse = FracPart.getReg(0);
  } else {
    auto Abs = MIRBuilder.buildFAbs(Ty, Src, Flags);
    const fltSemantics &Semantics = getFltSemanticForLLT(Ty.getScalarType());
    auto Inf = MIRBuilder.buildFConstant(Ty, APFloat::getInf(Semantics));
    auto IsInf = MIRBuilder.buildFCmp(CmpInst::FCMP_OEQ, CondTy, Abs, Inf);
    auto Zero = MIRBuilder.buildFConstant(Ty, 0.0);
    auto Select = MIRBuilder.buildSelect(Ty, IsInf, Zero, FracPart);
    FracToUse = Select.getReg(0);
  }

  MIRBuilder.buildFCopysign(DstFrac, FracToUse, Src, Flags);
  MIRBuilder.buildCopy(DstInt, IntPart.getReg(0));

  MI.eraseFromParent();
  return Legalized;
}

static CmpInst::Predicate minMaxToCompare(unsigned Opc) {
  switch (Opc) {
  case TargetOpcode::G_SMIN:
    return CmpInst::ICMP_SLT;
  case TargetOpcode::G_SMAX:
    return CmpInst::ICMP_SGT;
  case TargetOpcode::G_UMIN:
    return CmpInst::ICMP_ULT;
  case TargetOpcode::G_UMAX:
    return CmpInst::ICMP_UGT;
  default:
    llvm_unreachable("not in integer min/max");
  }
}

LegalizerHelper::LegalizeResult LegalizerHelper::lowerMinMax(MachineInstr &MI) {
  auto [Dst, Src0, Src1] = MI.getFirst3Regs();

  const CmpInst::Predicate Pred = minMaxToCompare(MI.getOpcode());
  LLT CmpType = MRI.getType(Dst).changeElementType(LLT::integer(1));

  auto Cmp = MIRBuilder.buildICmp(Pred, CmpType, Src0, Src1);
  MIRBuilder.buildSelect(Dst, Cmp, Src0, Src1);

  MI.eraseFromParent();
  return Legalized;
}

LegalizerHelper::LegalizeResult
LegalizerHelper::lowerThreewayCompare(MachineInstr &MI) {
  GSUCmp *Cmp = cast<GSUCmp>(&MI);

  Register Dst = Cmp->getReg(0);
  LLT DstTy = MRI.getType(Dst);
  LLT SrcTy = MRI.getType(Cmp->getReg(1));
  LLT CmpTy = DstTy.changeElementSize(1);

  CmpInst::Predicate LTPredicate = Cmp->isSigned()
                                       ? CmpInst::Predicate::ICMP_SLT
                                       : CmpInst::Predicate::ICMP_ULT;
  CmpInst::Predicate GTPredicate = Cmp->isSigned()
                                       ? CmpInst::Predicate::ICMP_SGT
                                       : CmpInst::Predicate::ICMP_UGT;

  auto Zero = MIRBuilder.buildConstant(DstTy, 0);
  auto IsGT = MIRBuilder.buildICmp(GTPredicate, CmpTy, Cmp->getLHSReg(),
                                   Cmp->getRHSReg());
  auto IsLT = MIRBuilder.buildICmp(LTPredicate, CmpTy, Cmp->getLHSReg(),
                                   Cmp->getRHSReg());

  auto &Ctx = MIRBuilder.getMF().getFunction().getContext();
  auto BC = TLI.getBooleanContents(DstTy.isVector(), /*isFP=*/false);
  if (TLI.preferSelectsOverBooleanArithmetic(
          getApproximateEVTForLLT(SrcTy, Ctx)) ||
      BC == TargetLowering::UndefinedBooleanContent) {
    auto One = MIRBuilder.buildConstant(DstTy, 1);
    auto SelectZeroOrOne = MIRBuilder.buildSelect(DstTy, IsGT, One, Zero);

    auto MinusOne = MIRBuilder.buildConstant(DstTy, -1);
    MIRBuilder.buildSelect(Dst, IsLT, MinusOne, SelectZeroOrOne);
  } else {
    if (BC == TargetLowering::ZeroOrNegativeOneBooleanContent)
      std::swap(IsGT, IsLT);
    // Extend boolean results to DstTy, which is at least i2, before subtracting
    // them.
    unsigned BoolExtOp =
        MIRBuilder.getBoolExtOp(DstTy.isVector(), /*isFP=*/false);
    IsGT = MIRBuilder.buildInstr(BoolExtOp, {DstTy}, {IsGT});
    IsLT = MIRBuilder.buildInstr(BoolExtOp, {DstTy}, {IsLT});
    MIRBuilder.buildSub(Dst, IsGT, IsLT);
  }

  MI.eraseFromParent();
  return Legalized;
}

LegalizerHelper::LegalizeResult
LegalizerHelper::lowerFCopySign(MachineInstr &MI) {
  auto [Dst, DstTy, Src0, Src0Ty, Src1, Src1Ty] = MI.getFirst3RegLLTs();
  const int Src0Size = Src0Ty.getScalarSizeInBits();
  const int Src1Size = Src1Ty.getScalarSizeInBits();

  LLT DstIntTy =
      DstTy.changeElementType(LLT::integer(DstTy.getScalarSizeInBits()));
  LLT Src0IntTy = Src0Ty.changeElementType(LLT::integer(Src0Size));
  LLT Src1IntTy = Src1Ty.changeElementType(LLT::integer(Src1Size));

  Register Src0Int = Src0;
  Register Src1Int = Src1;

  if (!(Src0Ty.getScalarType().isAnyScalar() ||
        Src0Ty.getScalarType().isInteger()))
    Src0Int = MIRBuilder.buildBitcast(Src0IntTy, Src0).getReg(0);

  if (!(Src1Ty.getScalarType().isAnyScalar() ||
        Src1Ty.getScalarType().isInteger()))
    Src1Int = MIRBuilder.buildBitcast(Src1IntTy, Src1).getReg(0);

  auto SignBitMask =
      MIRBuilder.buildConstant(Src0IntTy, APInt::getSignMask(Src0Size));

  auto NotSignBitMask = MIRBuilder.buildConstant(
      Src0IntTy, APInt::getLowBitsSet(Src0Size, Src0Size - 1));

  Register And0 =
      MIRBuilder.buildAnd(Src0IntTy, Src0Int, NotSignBitMask).getReg(0);
  Register And1;
  if (Src0Ty == Src1Ty) {
    And1 = MIRBuilder.buildAnd(Src1IntTy, Src1Int, SignBitMask).getReg(0);
  } else if (Src0Size > Src1Size) {
    auto ShiftAmt = MIRBuilder.buildConstant(Src0IntTy, Src0Size - Src1Size);
    auto Zext = MIRBuilder.buildZExt(Src0IntTy, Src1Int);
    auto Shift = MIRBuilder.buildShl(Src0IntTy, Zext, ShiftAmt);
    And1 = MIRBuilder.buildAnd(Src0Ty, Shift, SignBitMask).getReg(0);
  } else {
    auto ShiftAmt = MIRBuilder.buildConstant(Src1IntTy, Src1Size - Src0Size);
    auto Shift = MIRBuilder.buildLShr(Src1IntTy, Src1Int, ShiftAmt);
    auto Trunc = MIRBuilder.buildTrunc(Src0IntTy, Shift);
    And1 = MIRBuilder.buildAnd(Src0IntTy, Trunc, SignBitMask).getReg(0);
  }

  // Be careful about setting nsz/nnan/ninf on every instruction, since the
  // constants are a nan and -0.0, but the final result should preserve
  // everything.
  unsigned Flags = MI.getFlags();

  // We masked the sign bit and the not-sign bit, so these are disjoint.
  Flags |= MachineInstr::Disjoint;

  if (DstTy == DstIntTy)
    MIRBuilder.buildOr(Dst, And0, And1, Flags).getReg(0);
  else {
    Register NewDst = MIRBuilder.buildOr(DstIntTy, And0, And1, Flags).getReg(0);
    MIRBuilder.buildBitcast(Dst, NewDst);
  }

  MI.eraseFromParent();
  return Legalized;
}

LegalizerHelper::LegalizeResult
LegalizerHelper::lowerFMinNumMaxNum(MachineInstr &MI) {
  // FIXME: fminnum/fmaxnum and fminimumnum/fmaximumnum should not have
  // identical handling. fminimumnum/fmaximumnum also need a path that do not
  // depend on fminnum/fmaxnum.

  unsigned NewOp;
  switch (MI.getOpcode()) {
  case TargetOpcode::G_FMINNUM:
    NewOp = TargetOpcode::G_FMINNUM_IEEE;
    break;
  case TargetOpcode::G_FMINIMUMNUM:
    NewOp = TargetOpcode::G_FMINNUM;
    break;
  case TargetOpcode::G_FMAXNUM:
    NewOp = TargetOpcode::G_FMAXNUM_IEEE;
    break;
  case TargetOpcode::G_FMAXIMUMNUM:
    NewOp = TargetOpcode::G_FMAXNUM;
    break;
  default:
    llvm_unreachable("unexpected min/max opcode");
  }

  auto [Dst, Src0, Src1] = MI.getFirst3Regs();
  LLT Ty = MRI.getType(Dst);

  if (!MI.getFlag(MachineInstr::FmNoNans)) {
    // Insert canonicalizes if it's possible we need to quiet to get correct
    // sNaN behavior.

    // Note this must be done here, and not as an optimization combine in the
    // absence of a dedicate quiet-snan instruction as we're using an
    // omni-purpose G_FCANONICALIZE.
    if (!VT->isKnownNeverSNaN(Src0))
      Src0 = MIRBuilder.buildFCanonicalize(Ty, Src0, MI.getFlags()).getReg(0);

    if (!VT->isKnownNeverSNaN(Src1))
      Src1 = MIRBuilder.buildFCanonicalize(Ty, Src1, MI.getFlags()).getReg(0);
  }

  // If there are no nans, it's safe to simply replace this with the non-IEEE
  // version.
  MIRBuilder.buildInstr(NewOp, {Dst}, {Src0, Src1}, MI.getFlags());
  MI.eraseFromParent();
  return Legalized;
}

LegalizerHelper::LegalizeResult
LegalizerHelper::lowerFMinimumMaximum(MachineInstr &MI) {
  unsigned Opc = MI.getOpcode();
  auto [Dst, Src0, Src1] = MI.getFirst3Regs();
  LLT Ty = MRI.getType(Dst);
  const LLT CmpTy = Ty.changeElementType(LLT::integer(1));

  bool IsMax = (Opc == TargetOpcode::G_FMAXIMUM);
  unsigned OpcIeee =
      IsMax ? TargetOpcode::G_FMAXNUM_IEEE : TargetOpcode::G_FMINNUM_IEEE;
  unsigned OpcNonIeee =
      IsMax ? TargetOpcode::G_FMAXNUM : TargetOpcode::G_FMINNUM;
  bool MinMaxMustRespectOrderedZero = false;
  Register Res;

  // IEEE variants don't need canonicalization
  if (LI.isLegalOrCustom({OpcIeee, Ty})) {
    Res = MIRBuilder.buildInstr(OpcIeee, {Ty}, {Src0, Src1}).getReg(0);
    MinMaxMustRespectOrderedZero = true;
  } else if (LI.isLegalOrCustom({OpcNonIeee, Ty})) {
    Res = MIRBuilder.buildInstr(OpcNonIeee, {Ty}, {Src0, Src1}).getReg(0);
  } else {
    auto Compare = MIRBuilder.buildFCmp(
        IsMax ? CmpInst::FCMP_OGT : CmpInst::FCMP_OLT, CmpTy, Src0, Src1);
    Res = MIRBuilder.buildSelect(Ty, Compare, Src0, Src1).getReg(0);
  }

  // Propagate any NaN of both operands
  if (!MI.getFlag(MachineInstr::FmNoNans) &&
      (!VT->isKnownNeverNaN(Src0) || !VT->isKnownNeverNaN(Src1))) {
    auto IsOrdered = MIRBuilder.buildFCmp(CmpInst::FCMP_ORD, CmpTy, Src0, Src1);

    LLT ElementTy = Ty.isScalar() ? Ty : Ty.getElementType();
    APFloat NaNValue = APFloat::getNaN(getFltSemanticForLLT(ElementTy));
    Register NaN = MIRBuilder.buildFConstant(ElementTy, NaNValue).getReg(0);
    if (Ty.isVector())
      NaN = MIRBuilder.buildSplatBuildVector(Ty, NaN).getReg(0);

    Res = MIRBuilder.buildSelect(Ty, IsOrdered, Res, NaN).getReg(0);
  }

  // fminimum/fmaximum requires -0.0 less than +0.0
  if (!MinMaxMustRespectOrderedZero && !MI.getFlag(MachineInstr::FmNsz)) {
    GISelValueTracking VT(MIRBuilder.getMF());
    KnownFPClass Src0Info = VT.computeKnownFPClass(Src0, fcZero);
    KnownFPClass Src1Info = VT.computeKnownFPClass(Src1, fcZero);

    if (!Src0Info.isKnownNeverZero() && !Src1Info.isKnownNeverZero()) {
      const unsigned Flags = MI.getFlags();
      Register Zero = MIRBuilder.buildFConstant(Ty, 0.0).getReg(0);
      auto IsZero = MIRBuilder.buildFCmp(CmpInst::FCMP_OEQ, CmpTy, Res, Zero);

      unsigned TestClass = IsMax ? fcPosZero : fcNegZero;

      auto LHSTestZero = MIRBuilder.buildIsFPClass(CmpTy, Src0, TestClass);
      auto LHSSelect =
          MIRBuilder.buildSelect(Ty, LHSTestZero, Src0, Res, Flags);

      auto RHSTestZero = MIRBuilder.buildIsFPClass(CmpTy, Src1, TestClass);
      auto RHSSelect =
          MIRBuilder.buildSelect(Ty, RHSTestZero, Src1, LHSSelect, Flags);

      Res = MIRBuilder.buildSelect(Ty, IsZero, RHSSelect, Res, Flags).getReg(0);
    }
  }

  MIRBuilder.buildCopy(Dst, Res);
  MI.eraseFromParent();
  return Legalized;
}

LegalizerHelper::LegalizeResult LegalizerHelper::lowerFMad(MachineInstr &MI) {
  // Expand G_FMAD a, b, c -> G_FADD (G_FMUL a, b), c
  Register DstReg = MI.getOperand(0).getReg();
  LLT Ty = MRI.getType(DstReg);
  unsigned Flags = MI.getFlags();

  auto Mul = MIRBuilder.buildFMul(Ty, MI.getOperand(1), MI.getOperand(2),
                                  Flags);
  MIRBuilder.buildFAdd(DstReg, Mul, MI.getOperand(3), Flags);
  MI.eraseFromParent();
  return Legalized;
}

LegalizerHelper::LegalizeResult
LegalizerHelper::lowerIntrinsicRound(MachineInstr &MI) {
  auto [DstReg, X] = MI.getFirst2Regs();
  const unsigned Flags = MI.getFlags();
  const LLT Ty = MRI.getType(DstReg);
  const LLT CondTy = Ty.changeElementType(LLT::integer(1));

  // round(x) =>
  //  t = trunc(x);
  //  d = fabs(x - t);
  //  o = copysign(d >= 0.5 ? 1.0 : 0.0, x);
  //  return t + o;

  auto T = MIRBuilder.buildIntrinsicTrunc(Ty, X, Flags);

  auto Diff = MIRBuilder.buildFSub(Ty, X, T, Flags);
  auto AbsDiff = MIRBuilder.buildFAbs(Ty, Diff, Flags);

  auto Half = MIRBuilder.buildFConstant(Ty, 0.5);
  auto Cmp =
      MIRBuilder.buildFCmp(CmpInst::FCMP_OGE, CondTy, AbsDiff, Half, Flags);

  // Could emit G_UITOFP instead
  auto One = MIRBuilder.buildFConstant(Ty, 1.0);
  auto Zero = MIRBuilder.buildFConstant(Ty, 0.0);
  auto BoolFP = MIRBuilder.buildSelect(Ty, Cmp, One, Zero);
  auto SignedOffset = MIRBuilder.buildFCopysign(Ty, BoolFP, X);

  MIRBuilder.buildFAdd(DstReg, T, SignedOffset, Flags);

  MI.eraseFromParent();
  return Legalized;
}

LegalizerHelper::LegalizeResult LegalizerHelper::lowerFFloor(MachineInstr &MI) {
  auto [DstReg, SrcReg] = MI.getFirst2Regs();
  unsigned Flags = MI.getFlags();
  LLT Ty = MRI.getType(DstReg);
  const LLT CondTy = Ty.changeElementType(LLT::integer(1));

  // result = trunc(src);
  // if (src < 0.0 && src != result)
  //   result += -1.0.

  auto Trunc = MIRBuilder.buildIntrinsicTrunc(Ty, SrcReg, Flags);
  auto Zero = MIRBuilder.buildFConstant(Ty, 0.0);

  auto Lt0 = MIRBuilder.buildFCmp(CmpInst::FCMP_OLT, CondTy,
                                  SrcReg, Zero, Flags);
  auto NeTrunc = MIRBuilder.buildFCmp(CmpInst::FCMP_ONE, CondTy,
                                      SrcReg, Trunc, Flags);
  auto And = MIRBuilder.buildAnd(CondTy, Lt0, NeTrunc);
  auto AddVal = MIRBuilder.buildSITOFP(Ty, And);

  MIRBuilder.buildFAdd(DstReg, Trunc, AddVal, Flags);
  MI.eraseFromParent();
  return Legalized;
}

LegalizerHelper::LegalizeResult
LegalizerHelper::lowerMergeValues(MachineInstr &MI) {
  const unsigned NumOps = MI.getNumOperands();
  auto [DstReg, DstTy, Src0Reg, Src0Ty] = MI.getFirst2RegLLTs();
  unsigned PartSize = Src0Ty.getSizeInBits();

  LLT WideTy = LLT::scalar(DstTy.getSizeInBits());
  Register ResultReg = MIRBuilder.buildZExt(WideTy, Src0Reg).getReg(0);

  for (unsigned I = 2; I != NumOps; ++I) {
    const unsigned Offset = (I - 1) * PartSize;

    Register SrcReg = MI.getOperand(I).getReg();
    auto ZextInput = MIRBuilder.buildZExt(WideTy, SrcReg);

    Register NextResult = I + 1 == NumOps && WideTy == DstTy ? DstReg :
      MRI.createGenericVirtualRegister(WideTy);

    auto ShiftAmt = MIRBuilder.buildConstant(WideTy, Offset);
    auto Shl = MIRBuilder.buildShl(WideTy, ZextInput, ShiftAmt);
    MIRBuilder.buildOr(NextResult, ResultReg, Shl);
    ResultReg = NextResult;
  }

  if (DstTy.isPointer()) {
    if (MIRBuilder.getDataLayout().isNonIntegralAddressSpace(
          DstTy.getAddressSpace())) {
      LLVM_DEBUG(dbgs() << "Not casting nonintegral address space\n");
      return UnableToLegalize;
    }

    MIRBuilder.buildIntToPtr(DstReg, ResultReg);
  }

  MI.eraseFromParent();
  return Legalized;
}

LegalizerHelper::LegalizeResult
LegalizerHelper::lowerUnmergeValues(MachineInstr &MI) {
  const unsigned NumDst = MI.getNumOperands() - 1;
  Register SrcReg = MI.getOperand(NumDst).getReg();
  Register Dst0Reg = MI.getOperand(0).getReg();
  LLT DstTy = MRI.getType(Dst0Reg);
  if (DstTy.isPointer())
    return UnableToLegalize; // TODO

  SrcReg = coerceToScalar(SrcReg);
  if (!SrcReg)
    return UnableToLegalize;

  // Expand scalarizing unmerge as bitcast to integer and shift.
  LLT IntTy = MRI.getType(SrcReg);

  MIRBuilder.buildTrunc(Dst0Reg, SrcReg);

  const unsigned DstSize = DstTy.getSizeInBits();
  unsigned Offset = DstSize;
  for (unsigned I = 1; I != NumDst; ++I, Offset += DstSize) {
    auto ShiftAmt = MIRBuilder.buildConstant(IntTy, Offset);
    auto Shift = MIRBuilder.buildLShr(IntTy, SrcReg, ShiftAmt);
    MIRBuilder.buildTrunc(MI.getOperand(I), Shift);
  }

  MI.eraseFromParent();
  return Legalized;
}

/// Lower a vector extract or insert by writing the vector to a stack temporary
/// and reloading the element or vector.
///
/// %dst = G_EXTRACT_VECTOR_ELT %vec, %idx
///  =>
///  %stack_temp = G_FRAME_INDEX
///  G_STORE %vec, %stack_temp
///  %idx = clamp(%idx, %vec.getNumElements())
///  %element_ptr = G_PTR_ADD %stack_temp, %idx
///  %dst = G_LOAD %element_ptr
LegalizerHelper::LegalizeResult
LegalizerHelper::lowerExtractInsertVectorElt(MachineInstr &MI) {
  Register DstReg = MI.getOperand(0).getReg();
  Register SrcVec = MI.getOperand(1).getReg();
  Register InsertVal;
  if (MI.getOpcode() == TargetOpcode::G_INSERT_VECTOR_ELT)
    InsertVal = MI.getOperand(2).getReg();

  Register Idx = MI.getOperand(MI.getNumOperands() - 1).getReg();

  LLT VecTy = MRI.getType(SrcVec);
  LLT EltTy = VecTy.getElementType();
  unsigned NumElts = VecTy.getNumElements();

  int64_t IdxVal;
  if (mi_match(Idx, MRI, m_ICst(IdxVal)) && IdxVal <= NumElts) {
    SmallVector<Register, 8> SrcRegs;
    extractParts(SrcVec, EltTy, NumElts, SrcRegs, MIRBuilder, MRI);

    if (InsertVal) {
      SrcRegs[IdxVal] = MI.getOperand(2).getReg();
      MIRBuilder.buildMergeLikeInstr(DstReg, SrcRegs);
    } else {
      MIRBuilder.buildCopy(DstReg, SrcRegs[IdxVal]);
    }

    MI.eraseFromParent();
    return Legalized;
  }

  if (!EltTy.isByteSized()) { // Not implemented.
    LLVM_DEBUG(dbgs() << "Can't handle non-byte element vectors yet\n");
    return UnableToLegalize;
  }

  unsigned EltBytes = EltTy.getSizeInBytes();
  Align VecAlign = getStackTemporaryAlignment(VecTy);
  Align EltAlign;

  MachinePointerInfo PtrInfo;
  auto StackTemp = createStackTemporary(
      TypeSize::getFixed(VecTy.getSizeInBytes()), VecAlign, PtrInfo);
  MIRBuilder.buildStore(SrcVec, StackTemp, PtrInfo, VecAlign);

  // Get the pointer to the element, and be sure not to hit undefined behavior
  // if the index is out of bounds.
  Register EltPtr = getVectorElementPointer(StackTemp.getReg(0), VecTy, Idx);

  if (mi_match(Idx, MRI, m_ICst(IdxVal))) {
    int64_t Offset = IdxVal * EltBytes;
    PtrInfo = PtrInfo.getWithOffset(Offset);
    EltAlign = commonAlignment(VecAlign, Offset);
  } else {
    // We lose information with a variable offset.
    EltAlign = getStackTemporaryAlignment(EltTy);
    PtrInfo = MachinePointerInfo(MRI.getType(EltPtr).getAddressSpace());
  }

  if (InsertVal) {
    // Write the inserted element
    MIRBuilder.buildStore(InsertVal, EltPtr, PtrInfo, EltAlign);

    // Reload the whole vector.
    MIRBuilder.buildLoad(DstReg, StackTemp, PtrInfo, VecAlign);
  } else {
    MIRBuilder.buildLoad(DstReg, EltPtr, PtrInfo, EltAlign);
  }

  MI.eraseFromParent();
  return Legalized;
}

LegalizerHelper::LegalizeResult
LegalizerHelper::lowerShuffleVector(MachineInstr &MI) {
  auto [DstReg, DstTy, Src0Reg, Src0Ty, Src1Reg, Src1Ty] =
      MI.getFirst3RegLLTs();
  LLT IdxTy = LLT::scalar(32);

  ArrayRef<int> Mask = MI.getOperand(3).getShuffleMask();
  Register Undef;
  SmallVector<Register, 32> BuildVec;
  LLT EltTy = DstTy.getScalarType();

  DenseMap<unsigned, Register> CachedExtract;

  for (int Idx : Mask) {
    if (Idx < 0) {
      if (!Undef.isValid())
        Undef = MIRBuilder.buildUndef(EltTy).getReg(0);
      BuildVec.push_back(Undef);
      continue;
    }

    assert(!Src0Ty.isScalar() && "Unexpected scalar G_SHUFFLE_VECTOR");

    int NumElts = Src0Ty.getNumElements();
    Register SrcVec = Idx < NumElts ? Src0Reg : Src1Reg;
    int ExtractIdx = Idx < NumElts ? Idx : Idx - NumElts;
    auto [It, Inserted] = CachedExtract.try_emplace(Idx);
    if (Inserted) {
      auto IdxK = MIRBuilder.buildConstant(IdxTy, ExtractIdx);
      It->second =
          MIRBuilder.buildExtractVectorElement(EltTy, SrcVec, IdxK).getReg(0);
    }
    BuildVec.push_back(It->second);
  }

  assert(DstTy.isVector() && "Unexpected scalar G_SHUFFLE_VECTOR");
  MIRBuilder.buildBuildVector(DstReg, BuildVec);
  MI.eraseFromParent();
  return Legalized;
}

LegalizerHelper::LegalizeResult
LegalizerHelper::lowerVECTOR_COMPRESS(llvm::MachineInstr &MI) {
  auto [Dst, DstTy, Vec, VecTy, Mask, MaskTy, Passthru, PassthruTy] =
      MI.getFirst4RegLLTs();

  if (VecTy.isScalableVector())
    report_fatal_error("Cannot expand masked_compress for scalable vectors.");

  Align VecAlign = getStackTemporaryAlignment(VecTy);
  MachinePointerInfo PtrInfo;
  Register StackPtr =
      createStackTemporary(TypeSize::getFixed(VecTy.getSizeInBytes()), VecAlign,
                           PtrInfo)
          .getReg(0);
  MachinePointerInfo ValPtrInfo =
      MachinePointerInfo::getUnknownStack(*MI.getMF());

  LLT IdxTy = LLT::scalar(32);
  LLT ValTy = VecTy.getElementType();
  Align ValAlign = getStackTemporaryAlignment(ValTy);

  auto OutPos = MIRBuilder.buildConstant(IdxTy, 0);

  bool HasPassthru =
      MRI.getVRegDef(Passthru)->getOpcode() != TargetOpcode::G_IMPLICIT_DEF;

  if (HasPassthru)
    MIRBuilder.buildStore(Passthru, StackPtr, PtrInfo, VecAlign);

  Register LastWriteVal;
  std::optional<APInt> PassthruSplatVal =
      isConstantOrConstantSplatVector(Passthru, MRI);

  if (PassthruSplatVal.has_value()) {
    LastWriteVal =
        MIRBuilder.buildConstant(ValTy, PassthruSplatVal.value()).getReg(0);
  } else if (HasPassthru) {
    auto Popcount = MIRBuilder.buildZExt(MaskTy.changeElementSize(32), Mask);
    Popcount = MIRBuilder.buildInstr(TargetOpcode::G_VECREDUCE_ADD,
                                     {LLT::scalar(32)}, {Popcount});

    Register LastElmtPtr =
        getVectorElementPointer(StackPtr, VecTy, Popcount.getReg(0));
    LastWriteVal =
        MIRBuilder.buildLoad(ValTy, LastElmtPtr, ValPtrInfo, ValAlign)
            .getReg(0);
  }

  unsigned NumElmts = VecTy.getNumElements();
  for (unsigned I = 0; I < NumElmts; ++I) {
    auto Idx = MIRBuilder.buildConstant(IdxTy, I);
    auto Val = MIRBuilder.buildExtractVectorElement(ValTy, Vec, Idx);
    Register ElmtPtr =
        getVectorElementPointer(StackPtr, VecTy, OutPos.getReg(0));
    MIRBuilder.buildStore(Val, ElmtPtr, ValPtrInfo, ValAlign);

    LLT MaskITy = MaskTy.getElementType();
    auto MaskI = MIRBuilder.buildExtractVectorElement(MaskITy, Mask, Idx);
    if (MaskITy.getSizeInBits() > 1)
      MaskI = MIRBuilder.buildTrunc(LLT::scalar(1), MaskI);

    MaskI = MIRBuilder.buildZExt(IdxTy, MaskI);
    OutPos = MIRBuilder.buildAdd(IdxTy, OutPos, MaskI);

    if (HasPassthru && I == NumElmts - 1) {
      auto EndOfVector =
          MIRBuilder.buildConstant(IdxTy, VecTy.getNumElements() - 1);
      auto AllLanesSelected = MIRBuilder.buildICmp(
          CmpInst::ICMP_UGT, LLT::scalar(1), OutPos, EndOfVector);
      OutPos = MIRBuilder.buildInstr(TargetOpcode::G_UMIN, {IdxTy},
                                     {OutPos, EndOfVector});
      ElmtPtr = getVectorElementPointer(StackPtr, VecTy, OutPos.getReg(0));

      LastWriteVal =
          MIRBuilder.buildSelect(ValTy, AllLanesSelected, Val, LastWriteVal)
              .getReg(0);
      MIRBuilder.buildStore(LastWriteVal, ElmtPtr, ValPtrInfo, ValAlign);
    }
  }

  // TODO: Use StackPtr's FrameIndex alignment.
  MIRBuilder.buildLoad(Dst, StackPtr, PtrInfo, VecAlign);

  MI.eraseFromParent();
  return Legalized;
}

Register LegalizerHelper::getDynStackAllocTargetPtr(Register SPReg,
                                                    Register AllocSize,
                                                    Align Alignment,
                                                    LLT PtrTy) {
  LLT IntPtrTy = LLT::integer(PtrTy.getSizeInBits());

  auto SPTmp = MIRBuilder.buildCopy(PtrTy, SPReg);
  SPTmp = MIRBuilder.buildCast(IntPtrTy, SPTmp);

  // Subtract the final alloc from the SP. We use G_PTRTOINT here so we don't
  // have to generate an extra instruction to negate the alloc and then use
  // G_PTR_ADD to add the negative offset.
  auto Alloc = MIRBuilder.buildSub(IntPtrTy, SPTmp, AllocSize);
  if (Alignment > Align(1)) {
    APInt AlignMask(IntPtrTy.getSizeInBits(), Alignment.value(), true);
    AlignMask.negate();
    auto AlignCst = MIRBuilder.buildConstant(IntPtrTy, AlignMask);
    Alloc = MIRBuilder.buildAnd(IntPtrTy, Alloc, AlignCst);
  }

  return MIRBuilder.buildCast(PtrTy, Alloc).getReg(0);
}

LegalizerHelper::LegalizeResult
LegalizerHelper::lowerDynStackAlloc(MachineInstr &MI) {
  const auto &MF = *MI.getMF();
  const auto &TFI = *MF.getSubtarget().getFrameLowering();
  if (TFI.getStackGrowthDirection() == TargetFrameLowering::StackGrowsUp)
    return UnableToLegalize;

  Register Dst = MI.getOperand(0).getReg();
  Register AllocSize = MI.getOperand(1).getReg();
  Align Alignment = assumeAligned(MI.getOperand(2).getImm());

  LLT PtrTy = MRI.getType(Dst);
  Register SPReg = TLI.getStackPointerRegisterToSaveRestore();
  Register SPTmp =
      getDynStackAllocTargetPtr(SPReg, AllocSize, Alignment, PtrTy);

  MIRBuilder.buildCopy(SPReg, SPTmp);
  MIRBuilder.buildCopy(Dst, SPTmp);

  MI.eraseFromParent();
  return Legalized;
}

LegalizerHelper::LegalizeResult
LegalizerHelper::lowerStackSave(MachineInstr &MI) {
  Register StackPtr = TLI.getStackPointerRegisterToSaveRestore();
  if (!StackPtr)
    return UnableToLegalize;

  MIRBuilder.buildCopy(MI.getOperand(0), StackPtr);
  MI.eraseFromParent();
  return Legalized;
}

LegalizerHelper::LegalizeResult
LegalizerHelper::lowerStackRestore(MachineInstr &MI) {
  Register StackPtr = TLI.getStackPointerRegisterToSaveRestore();
  if (!StackPtr)
    return UnableToLegalize;

  MIRBuilder.buildCopy(StackPtr, MI.getOperand(0));
  MI.eraseFromParent();
  return Legalized;
}

LegalizerHelper::LegalizeResult
LegalizerHelper::lowerExtract(MachineInstr &MI) {
  auto [DstReg, DstTy, SrcReg, SrcTy] = MI.getFirst2RegLLTs();
  unsigned Offset = MI.getOperand(2).getImm();

  // Extract sub-vector or one element
  if (SrcTy.isVector()) {
    unsigned SrcEltSize = SrcTy.getElementType().getSizeInBits();
    unsigned DstSize = DstTy.getSizeInBits();

    if ((Offset % SrcEltSize == 0) && (DstSize % SrcEltSize == 0) &&
        (Offset + DstSize <= SrcTy.getSizeInBits())) {
      // Unmerge and allow access to each Src element for the artifact combiner.
      auto Unmerge = MIRBuilder.buildUnmerge(SrcTy.getElementType(), SrcReg);

      // Take element(s) we need to extract and copy it (merge them).
      SmallVector<Register, 8> SubVectorElts;
      for (unsigned Idx = Offset / SrcEltSize;
           Idx < (Offset + DstSize) / SrcEltSize; ++Idx) {
        SubVectorElts.push_back(Unmerge.getReg(Idx));
      }
      if (SubVectorElts.size() == 1)
        MIRBuilder.buildCopy(DstReg, SubVectorElts[0]);
      else
        MIRBuilder.buildMergeLikeInstr(DstReg, SubVectorElts);

      MI.eraseFromParent();
      return Legalized;
    }
  }

  const DataLayout &DL = MIRBuilder.getDataLayout();
  if ((SrcTy.isPointer() &&
       DL.isNonIntegralAddressSpace(SrcTy.getAddressSpace())) ||
      (DstTy.isPointer() &&
       DL.isNonIntegralAddressSpace(DstTy.getAddressSpace()))) {
    LLVM_DEBUG(dbgs() << "Not casting non-integral address space integer\n");
    return UnableToLegalize;
  }

  if ((DstTy.isScalar() || DstTy.isPointer()) &&
      (SrcTy.isScalar() || SrcTy.isPointer() ||
       (SrcTy.isVector() && DstTy == SrcTy.getElementType()))) {
    LLT SrcIntTy = SrcTy;
    if (!SrcTy.isScalar()) {
      SrcIntTy = LLT::scalar(SrcTy.getSizeInBits());
      SrcReg = MIRBuilder.buildCast(SrcIntTy, SrcReg).getReg(0);
    }

    Register ResultReg = DstReg;
    if (DstTy.isPointer())
      ResultReg =
          MRI.createGenericVirtualRegister(LLT::scalar(DstTy.getSizeInBits()));

    if (Offset == 0)
      MIRBuilder.buildTrunc(ResultReg, SrcReg);
    else {
      auto ShiftAmt = MIRBuilder.buildConstant(SrcIntTy, Offset);
      auto Shr = MIRBuilder.buildLShr(SrcIntTy, SrcReg, ShiftAmt);
      MIRBuilder.buildTrunc(ResultReg, Shr);
    }

    if (DstTy.isPointer())
      MIRBuilder.buildIntToPtr(DstReg, ResultReg);

    MI.eraseFromParent();
    return Legalized;
  }

  return UnableToLegalize;
}

LegalizerHelper::LegalizeResult LegalizerHelper::lowerInsert(MachineInstr &MI) {
  auto [Dst, Src, InsertSrc] = MI.getFirst3Regs();
  uint64_t Offset = MI.getOperand(3).getImm();

  LLT DstTy = MRI.getType(Src);
  LLT InsertTy = MRI.getType(InsertSrc);

  const DataLayout &DL = MIRBuilder.getDataLayout();
  bool IsNonIntegralInsert =
      InsertTy.isPointerOrPointerVector() &&
      DL.isNonIntegralAddressSpace(InsertTy.getAddressSpace());
  bool IsNonIntegralDst = DstTy.isPointerOrPointerVector() &&
                          DL.isNonIntegralAddressSpace(DstTy.getAddressSpace());

  // Insert sub-vector or one element
  if (DstTy.isVector()) {
    LLT EltTy = DstTy.getElementType();

    if ((IsNonIntegralInsert || IsNonIntegralDst) && InsertTy != EltTy) {
      LLVM_DEBUG(dbgs() << "Not casting non-integral address space integer\n");
      return UnableToLegalize;
    }

    unsigned EltSize = EltTy.getSizeInBits();
    unsigned InsertSize = InsertTy.getSizeInBits();

    if ((Offset % EltSize == 0) && (InsertSize % EltSize == 0) &&
        (Offset + InsertSize <= DstTy.getSizeInBits())) {
      auto UnmergeSrc = MIRBuilder.buildUnmerge(EltTy, Src);
      SmallVector<Register, 8> DstElts;
      unsigned Idx = 0;
      // Elements from Src before insert start Offset
      for (; Idx < Offset / EltSize; ++Idx) {
        DstElts.push_back(UnmergeSrc.getReg(Idx));
      }

      // Replace elements in Src with elements from InsertSrc
      if (InsertTy.getSizeInBits() > EltSize) {
        auto UnmergeInsertSrc = MIRBuilder.buildUnmerge(EltTy, InsertSrc);
        for (unsigned i = 0; Idx < (Offset + InsertSize) / EltSize;
             ++Idx, ++i) {
          DstElts.push_back(UnmergeInsertSrc.getReg(i));
        }
      } else {
        if (InsertTy.isPointer() && !EltTy.isPointer())
          InsertSrc = MIRBuilder.buildPtrToInt(EltTy, InsertSrc).getReg(0);
        else if (!InsertTy.isPointer() && EltTy.isPointer())
          InsertSrc = MIRBuilder.buildIntToPtr(EltTy, InsertSrc).getReg(0);
        DstElts.push_back(InsertSrc);
        ++Idx;
      }

      // Remaining elements from Src after insert
      for (; Idx < DstTy.getNumElements(); ++Idx) {
        DstElts.push_back(UnmergeSrc.getReg(Idx));
      }

      MIRBuilder.buildMergeLikeInstr(Dst, DstElts);
      MI.eraseFromParent();
      return Legalized;
    }
  }

  if (InsertTy.isVector() ||
      (DstTy.isVector() && DstTy.getElementType() != InsertTy))
    return UnableToLegalize;

  if (IsNonIntegralDst || IsNonIntegralInsert) {
    LLVM_DEBUG(dbgs() << "Not casting non-integral address space integer\n");
    return UnableToLegalize;
  }

  LLT IntDstTy = DstTy;

  if (!DstTy.isScalar()) {
    IntDstTy = LLT::scalar(DstTy.getSizeInBits());
    Src = MIRBuilder.buildCast(IntDstTy, Src).getReg(0);
  }

  if (!InsertTy.isScalar()) {
    const LLT IntInsertTy = LLT::scalar(InsertTy.getSizeInBits());
    InsertSrc = MIRBuilder.buildPtrToInt(IntInsertTy, InsertSrc).getReg(0);
  }

  Register ExtInsSrc = MIRBuilder.buildZExt(IntDstTy, InsertSrc).getReg(0);
  if (Offset != 0) {
    auto ShiftAmt = MIRBuilder.buildConstant(IntDstTy, Offset);
    ExtInsSrc = MIRBuilder.buildShl(IntDstTy, ExtInsSrc, ShiftAmt).getReg(0);
  }

  APInt MaskVal = APInt::getBitsSetWithWrap(
      DstTy.getSizeInBits(), Offset + InsertTy.getSizeInBits(), Offset);

  auto Mask = MIRBuilder.buildConstant(IntDstTy, MaskVal);
  auto MaskedSrc = MIRBuilder.buildAnd(IntDstTy, Src, Mask);
  auto Or = MIRBuilder.buildOr(IntDstTy, MaskedSrc, ExtInsSrc);

  MIRBuilder.buildCast(Dst, Or);
  MI.eraseFromParent();
  return Legalized;
}

LegalizerHelper::LegalizeResult
LegalizerHelper::lowerSADDO_SSUBO(MachineInstr &MI) {
  auto [Dst0, Dst0Ty, Dst1, Dst1Ty, LHS, LHSTy, RHS, RHSTy] =
      MI.getFirst4RegLLTs();
  const bool IsAdd = MI.getOpcode() == TargetOpcode::G_SADDO;

  LLT Ty = Dst0Ty;
  LLT BoolTy = Dst1Ty;

  Register NewDst0 = MRI.cloneVirtualRegister(Dst0);

  if (IsAdd)
    MIRBuilder.buildAdd(NewDst0, LHS, RHS);
  else
    MIRBuilder.buildSub(NewDst0, LHS, RHS);

  // TODO: If SADDSAT/SSUBSAT is legal, compare results to detect overflow.

  auto Zero = MIRBuilder.buildConstant(Ty, 0);

  if (IsAdd) {
    // For an addition, the result should be less than one of the operands (LHS)
    // if and only if the other operand (RHS) is negative, otherwise there will
    // be overflow.
    auto ResultLowerThanLHS =
        MIRBuilder.buildICmp(CmpInst::ICMP_SLT, BoolTy, NewDst0, LHS);
    auto RHSNegative =
        MIRBuilder.buildICmp(CmpInst::ICMP_SLT, BoolTy, RHS, Zero);
    MIRBuilder.buildXor(Dst1, RHSNegative, ResultLowerThanLHS);
  } else {
    // For subtraction, overflow occurs when the signed comparison of operands
    // doesn't match the sign of the result.
    auto LHSLessThanRHS =
        MIRBuilder.buildICmp(CmpInst::ICMP_SLT, BoolTy, LHS, RHS);
    auto ResultNegative =
        MIRBuilder.buildICmp(CmpInst::ICMP_SLT, BoolTy, NewDst0, Zero);
    MIRBuilder.buildXor(Dst1, LHSLessThanRHS, ResultNegative);
  }

  MIRBuilder.buildCopy(Dst0, NewDst0);
  MI.eraseFromParent();

  return Legalized;
}

LegalizerHelper::LegalizeResult LegalizerHelper::lowerSADDE(MachineInstr &MI) {
  auto [Res, OvOut, LHS, RHS, CarryIn] = MI.getFirst5Regs();
  const LLT Ty = MRI.getType(Res);

  // sum = LHS + RHS + zext(CarryIn)
  auto Tmp = MIRBuilder.buildAdd(Ty, LHS, RHS);
  auto CarryZ = MIRBuilder.buildZExt(Ty, CarryIn);
  auto Sum = MIRBuilder.buildAdd(Ty, Tmp, CarryZ);
  MIRBuilder.buildCopy(Res, Sum);

  // OvOut = icmp slt ((sum ^ lhs) & (sum ^ rhs)), 0
  auto AX = MIRBuilder.buildXor(Ty, Sum, LHS);
  auto BX = MIRBuilder.buildXor(Ty, Sum, RHS);
  auto T = MIRBuilder.buildAnd(Ty, AX, BX);

  auto Zero = MIRBuilder.buildConstant(Ty, 0);
  MIRBuilder.buildICmp(CmpInst::ICMP_SLT, OvOut, T, Zero);

  MI.eraseFromParent();
  return Legalized;
}

LegalizerHelper::LegalizeResult LegalizerHelper::lowerSSUBE(MachineInstr &MI) {
  auto [Res, OvOut, LHS, RHS, CarryIn] = MI.getFirst5Regs();
  const LLT Ty = MRI.getType(Res);

  // Diff = LHS - (RHS + zext(CarryIn))
  auto CarryZ = MIRBuilder.buildZExt(Ty, CarryIn);
  auto RHSPlusCI = MIRBuilder.buildAdd(Ty, RHS, CarryZ);
  auto Diff = MIRBuilder.buildSub(Ty, LHS, RHSPlusCI);
  MIRBuilder.buildCopy(Res, Diff);

  // ov = msb((LHS ^ RHS) & (LHS ^ Diff))
  auto X1 = MIRBuilder.buildXor(Ty, LHS, RHS);
  auto X2 = MIRBuilder.buildXor(Ty, LHS, Diff);
  auto T = MIRBuilder.buildAnd(Ty, X1, X2);
  auto Zero = MIRBuilder.buildConstant(Ty, 0);
  MIRBuilder.buildICmp(CmpInst::ICMP_SLT, OvOut, T, Zero);

  MI.eraseFromParent();
  return Legalized;
}

LegalizerHelper::LegalizeResult
LegalizerHelper::lowerAddSubSatToMinMax(MachineInstr &MI) {
  auto [Res, LHS, RHS] = MI.getFirst3Regs();
  LLT Ty = MRI.getType(Res);
  bool IsSigned;
  bool IsAdd;
  unsigned BaseOp;
  switch (MI.getOpcode()) {
  default:
    llvm_unreachable("unexpected addsat/subsat opcode");
  case TargetOpcode::G_UADDSAT:
    IsSigned = false;
    IsAdd = true;
    BaseOp = TargetOpcode::G_ADD;
    break;
  case TargetOpcode::G_SADDSAT:
    IsSigned = true;
    IsAdd = true;
    BaseOp = TargetOpcode::G_ADD;
    break;
  case TargetOpcode::G_USUBSAT:
    IsSigned = false;
    IsAdd = false;
    BaseOp = TargetOpcode::G_SUB;
    break;
  case TargetOpcode::G_SSUBSAT:
    IsSigned = true;
    IsAdd = false;
    BaseOp = TargetOpcode::G_SUB;
    break;
  }

  if (IsSigned) {
    // sadd.sat(a, b) ->
    //   hi = 0x7fffffff - smax(a, 0)
    //   lo = 0x80000000 - smin(a, 0)
    //   a + smin(smax(lo, b), hi)
    // ssub.sat(a, b) ->
    //   lo = smax(a, -1) - 0x7fffffff
    //   hi = smin(a, -1) - 0x80000000
    //   a - smin(smax(lo, b), hi)
    // TODO: AMDGPU can use a "median of 3" instruction here:
    //   a +/- med3(lo, b, hi)
    uint64_t NumBits = Ty.getScalarSizeInBits();
    auto MaxVal =
        MIRBuilder.buildConstant(Ty, APInt::getSignedMaxValue(NumBits));
    auto MinVal =
        MIRBuilder.buildConstant(Ty, APInt::getSignedMinValue(NumBits));
    MachineInstrBuilder Hi, Lo;
    if (IsAdd) {
      auto Zero = MIRBuilder.buildConstant(Ty, 0);
      Hi = MIRBuilder.buildSub(Ty, MaxVal, MIRBuilder.buildSMax(Ty, LHS, Zero));
      Lo = MIRBuilder.buildSub(Ty, MinVal, MIRBuilder.buildSMin(Ty, LHS, Zero));
    } else {
      auto NegOne = MIRBuilder.buildConstant(Ty, -1);
      Lo = MIRBuilder.buildSub(Ty, MIRBuilder.buildSMax(Ty, LHS, NegOne),
                               MaxVal);
      Hi = MIRBuilder.buildSub(Ty, MIRBuilder.buildSMin(Ty, LHS, NegOne),
                               MinVal);
    }
    auto RHSClamped =
        MIRBuilder.buildSMin(Ty, MIRBuilder.buildSMax(Ty, Lo, RHS), Hi);
    MIRBuilder.buildInstr(BaseOp, {Res}, {LHS, RHSClamped});
  } else {
    // uadd.sat(a, b) -> a + umin(~a, b)
    // usub.sat(a, b) -> a - umin(a, b)
    Register Not = IsAdd ? MIRBuilder.buildNot(Ty, LHS).getReg(0) : LHS;
    auto Min = MIRBuilder.buildUMin(Ty, Not, RHS);
    MIRBuilder.buildInstr(BaseOp, {Res}, {LHS, Min});
  }

  MI.eraseFromParent();
  return Legalized;
}

LegalizerHelper::LegalizeResult
LegalizerHelper::lowerAddSubSatToAddoSubo(MachineInstr &MI) {
  auto [Res, LHS, RHS] = MI.getFirst3Regs();
  LLT Ty = MRI.getType(Res);
  LLT BoolTy = Ty.changeElementSize(1);
  bool IsSigned;
  bool IsAdd;
  unsigned OverflowOp;
  switch (MI.getOpcode()) {
  default:
    llvm_unreachable("unexpected addsat/subsat opcode");
  case TargetOpcode::G_UADDSAT:
    IsSigned = false;
    IsAdd = true;
    OverflowOp = TargetOpcode::G_UADDO;
    break;
  case TargetOpcode::G_SADDSAT:
    IsSigned = true;
    IsAdd = true;
    OverflowOp = TargetOpcode::G_SADDO;
    break;
  case TargetOpcode::G_USUBSAT:
    IsSigned = false;
    IsAdd = false;
    OverflowOp = TargetOpcode::G_USUBO;
    break;
  case TargetOpcode::G_SSUBSAT:
    IsSigned = true;
    IsAdd = false;
    OverflowOp = TargetOpcode::G_SSUBO;
    break;
  }

  auto OverflowRes =
      MIRBuilder.buildInstr(OverflowOp, {Ty, BoolTy}, {LHS, RHS});
  Register Tmp = OverflowRes.getReg(0);
  Register Ov = OverflowRes.getReg(1);
  MachineInstrBuilder Clamp;
  if (IsSigned) {
    // sadd.sat(a, b) ->
    //   {tmp, ov} = saddo(a, b)
    //   ov ? (tmp >>s 31) + 0x80000000 : r
    // ssub.sat(a, b) ->
    //   {tmp, ov} = ssubo(a, b)
    //   ov ? (tmp >>s 31) + 0x80000000 : r
    uint64_t NumBits = Ty.getScalarSizeInBits();
    auto ShiftAmount = MIRBuilder.buildConstant(Ty, NumBits - 1);
    auto Sign = MIRBuilder.buildAShr(Ty, Tmp, ShiftAmount);
    auto MinVal =
        MIRBuilder.buildConstant(Ty, APInt::getSignedMinValue(NumBits));
    Clamp = MIRBuilder.buildAdd(Ty, Sign, MinVal);
  } else {
    // uadd.sat(a, b) ->
    //   {tmp, ov} = uaddo(a, b)
    //   ov ? 0xffffffff : tmp
    // usub.sat(a, b) ->
    //   {tmp, ov} = usubo(a, b)
    //   ov ? 0 : tmp
    Clamp = MIRBuilder.buildConstant(Ty, IsAdd ? -1 : 0);
  }
  MIRBuilder.buildSelect(Res, Ov, Clamp, Tmp);

  MI.eraseFromParent();
  return Legalized;
}

LegalizerHelper::LegalizeResult
LegalizerHelper::lowerShlSat(MachineInstr &MI) {
  assert((MI.getOpcode() == TargetOpcode::G_SSHLSAT ||
          MI.getOpcode() == TargetOpcode::G_USHLSAT) &&
         "Expected shlsat opcode!");
  bool IsSigned = MI.getOpcode() == TargetOpcode::G_SSHLSAT;
  auto [Res, LHS, RHS] = MI.getFirst3Regs();
  LLT Ty = MRI.getType(Res);
  LLT BoolTy = Ty.changeElementSize(1);

  unsigned BW = Ty.getScalarSizeInBits();
  auto Result = MIRBuilder.buildShl(Ty, LHS, RHS);
  auto Orig = IsSigned ? MIRBuilder.buildAShr(Ty, Result, RHS)
                       : MIRBuilder.buildLShr(Ty, Result, RHS);

  MachineInstrBuilder SatVal;
  if (IsSigned) {
    auto SatMin = MIRBuilder.buildConstant(Ty, APInt::getSignedMinValue(BW));
    auto SatMax = MIRBuilder.buildConstant(Ty, APInt::getSignedMaxValue(BW));
    auto Cmp = MIRBuilder.buildICmp(CmpInst::ICMP_SLT, BoolTy, LHS,
                                    MIRBuilder.buildConstant(Ty, 0));
    SatVal = MIRBuilder.buildSelect(Ty, Cmp, SatMin, SatMax);
  } else {
    SatVal = MIRBuilder.buildConstant(Ty, APInt::getMaxValue(BW));
  }
  auto Ov = MIRBuilder.buildICmp(CmpInst::ICMP_NE, BoolTy, LHS, Orig);
  MIRBuilder.buildSelect(Res, Ov, SatVal, Result);

  MI.eraseFromParent();
  return Legalized;
}

LegalizerHelper::LegalizeResult LegalizerHelper::lowerBswap(MachineInstr &MI) {
  auto [Dst, Src] = MI.getFirst2Regs();
  const LLT Ty = MRI.getType(Src);
  unsigned SizeInBytes = (Ty.getScalarSizeInBits() + 7) / 8;
  unsigned BaseShiftAmt = (SizeInBytes - 1) * 8;

  // Swap most and least significant byte, set remaining bytes in Res to zero.
  auto ShiftAmt = MIRBuilder.buildConstant(Ty, BaseShiftAmt);
  auto LSByteShiftedLeft = MIRBuilder.buildShl(Ty, Src, ShiftAmt);
  auto MSByteShiftedRight = MIRBuilder.buildLShr(Ty, Src, ShiftAmt);
  auto Res = MIRBuilder.buildOr(Ty, MSByteShiftedRight, LSByteShiftedLeft);

  // Set i-th high/low byte in Res to i-th low/high byte from Src.
  for (unsigned i = 1; i < SizeInBytes / 2; ++i) {
    // AND with Mask leaves byte i unchanged and sets remaining bytes to 0.
    APInt APMask = APInt::getBitsSet(SizeInBytes * 8, i * 8, i * 8 + 8);
    auto Mask = MIRBuilder.buildConstant(Ty, APMask);
    auto ShiftAmt = MIRBuilder.buildConstant(Ty, BaseShiftAmt - 16 * i);
    // Low byte shifted left to place of high byte: (Src & Mask) << ShiftAmt.
    auto LoByte = MIRBuilder.buildAnd(Ty, Src, Mask);
    auto LoShiftedLeft = MIRBuilder.buildShl(Ty, LoByte, ShiftAmt);
    Res = MIRBuilder.buildOr(Ty, Res, LoShiftedLeft);
    // High byte shifted right to place of low byte: (Src >> ShiftAmt) & Mask.
    auto SrcShiftedRight = MIRBuilder.buildLShr(Ty, Src, ShiftAmt);
    auto HiShiftedRight = MIRBuilder.buildAnd(Ty, SrcShiftedRight, Mask);
    Res = MIRBuilder.buildOr(Ty, Res, HiShiftedRight);
  }
  Res.getInstr()->getOperand(0).setReg(Dst);

  MI.eraseFromParent();
  return Legalized;
}

//{ (Src & Mask) >> N } | { (Src << N) & Mask }
static MachineInstrBuilder SwapN(unsigned N, DstOp Dst, MachineIRBuilder &B,
                                 MachineInstrBuilder Src, const APInt &Mask) {
  const LLT Ty = Dst.getLLTTy(*B.getMRI());
  MachineInstrBuilder C_N = B.buildConstant(Ty, N);
  MachineInstrBuilder MaskLoNTo0 = B.buildConstant(Ty, Mask);
  auto LHS = B.buildLShr(Ty, B.buildAnd(Ty, Src, MaskLoNTo0), C_N);
  auto RHS = B.buildAnd(Ty, B.buildShl(Ty, Src, C_N), MaskLoNTo0);
  return B.buildOr(Dst, LHS, RHS);
}

LegalizerHelper::LegalizeResult
LegalizerHelper::lowerBitreverse(MachineInstr &MI) {
  auto [Dst, Src] = MI.getFirst2Regs();
  const LLT SrcTy = MRI.getType(Src);
  unsigned Size = SrcTy.getScalarSizeInBits();
  unsigned VSize = SrcTy.getSizeInBits();

  if (Size >= 8) {
    if (SrcTy.isVector() && (VSize % 8 == 0) &&
        (LI.isLegal({TargetOpcode::G_BITREVERSE,
                     {LLT::fixed_vector(VSize / 8, LLT::integer(8)),
                      LLT::fixed_vector(VSize / 8, LLT::integer(8))}}))) {
      // If bitreverse is legal for i8 vector of the same size, then cast
      // to i8 vector type.
      // e.g. v4s32 -> v16s8
      LLT VTy = LLT::fixed_vector(VSize / 8, LLT::integer(8));
      auto BSWAP = MIRBuilder.buildBSwap(SrcTy, Src);
      auto Cast = MIRBuilder.buildBitcast(VTy, BSWAP);
      auto RBIT = MIRBuilder.buildBitReverse(VTy, Cast);
      MIRBuilder.buildBitcast(Dst, RBIT);
    } else {
      MachineInstrBuilder BSWAP =
          MIRBuilder.buildInstr(TargetOpcode::G_BSWAP, {SrcTy}, {Src});

      // swap high and low 4 bits in 8 bit blocks 7654|3210 -> 3210|7654
      //    [(val & 0xF0F0F0F0) >> 4] | [(val & 0x0F0F0F0F) << 4]
      // -> [(val & 0xF0F0F0F0) >> 4] | [(val << 4) & 0xF0F0F0F0]
      MachineInstrBuilder Swap4 = SwapN(4, SrcTy, MIRBuilder, BSWAP,
                                        APInt::getSplat(Size, APInt(8, 0xF0)));

      // swap high and low 2 bits in 4 bit blocks 32|10 76|54 -> 10|32 54|76
      //    [(val & 0xCCCCCCCC) >> 2] & [(val & 0x33333333) << 2]
      // -> [(val & 0xCCCCCCCC) >> 2] & [(val << 2) & 0xCCCCCCCC]
      MachineInstrBuilder Swap2 = SwapN(2, SrcTy, MIRBuilder, Swap4,
                                        APInt::getSplat(Size, APInt(8, 0xCC)));

      // swap high and low 1 bit in 2 bit blocks 1|0 3|2 5|4 7|6 -> 0|1 2|3 4|5
      // 6|7
      //    [(val & 0xAAAAAAAA) >> 1] & [(val & 0x55555555) << 1]
      // -> [(val & 0xAAAAAAAA) >> 1] & [(val << 1) & 0xAAAAAAAA]
      SwapN(1, Dst, MIRBuilder, Swap2, APInt::getSplat(Size, APInt(8, 0xAA)));
    }
  } else {
    // Expand bitreverse for types smaller than 8 bits.
    MachineInstrBuilder Tmp;
    for (unsigned I = 0, J = Size - 1; I < Size; ++I, --J) {
      MachineInstrBuilder Tmp2;
      if (I < J) {
        auto ShAmt = MIRBuilder.buildConstant(SrcTy, J - I);
        Tmp2 = MIRBuilder.buildShl(SrcTy, Src, ShAmt);
      } else {
        auto ShAmt = MIRBuilder.buildConstant(SrcTy, I - J);
        Tmp2 = MIRBuilder.buildLShr(SrcTy, Src, ShAmt);
      }

      auto Mask = MIRBuilder.buildConstant(SrcTy, 1ULL << J);
      Tmp2 = MIRBuilder.buildAnd(SrcTy, Tmp2, Mask);
      if (I == 0)
        Tmp = Tmp2;
      else
        Tmp = MIRBuilder.buildOr(SrcTy, Tmp, Tmp2);
    }
    MIRBuilder.buildCopy(Dst, Tmp);
  }

  MI.eraseFromParent();
  return Legalized;
}

LegalizerHelper::LegalizeResult
LegalizerHelper::lowerReadWriteRegister(MachineInstr &MI) {
  MachineFunction &MF = MIRBuilder.getMF();

  bool IsRead = MI.getOpcode() == TargetOpcode::G_READ_REGISTER;
  int NameOpIdx = IsRead ? 1 : 0;
  int ValRegIndex = IsRead ? 0 : 1;

  Register ValReg = MI.getOperand(ValRegIndex).getReg();
  const LLT Ty = MRI.getType(ValReg);
  const MDString *RegStr = cast<MDString>(
    cast<MDNode>(MI.getOperand(NameOpIdx).getMetadata())->getOperand(0));

  Register PhysReg = TLI.getRegisterByName(RegStr->getString().data(), Ty, MF);
  if (!PhysReg) {
    const Function &Fn = MF.getFunction();
    Fn.getContext().diagnose(DiagnosticInfoGenericWithLoc(
        "invalid register \"" + Twine(RegStr->getString().data()) + "\" for " +
            (IsRead ? "llvm.read_register" : "llvm.write_register"),
        Fn, MI.getDebugLoc()));
    if (IsRead)
      MIRBuilder.buildUndef(ValReg);

    MI.eraseFromParent();
    return Legalized;
  }

  if (IsRead)
    MIRBuilder.buildCopy(ValReg, PhysReg);
  else
    MIRBuilder.buildCopy(PhysReg, ValReg);

  MI.eraseFromParent();
  return Legalized;
}

LegalizerHelper::LegalizeResult
LegalizerHelper::lowerSMULH_UMULH(MachineInstr &MI) {
  bool IsSigned = MI.getOpcode() == TargetOpcode::G_SMULH;
  unsigned ExtOp = IsSigned ? TargetOpcode::G_SEXT : TargetOpcode::G_ZEXT;
  Register Result = MI.getOperand(0).getReg();
  LLT OrigTy = MRI.getType(Result);
  auto SizeInBits = OrigTy.getScalarSizeInBits();
  LLT WideTy = OrigTy.changeElementSize(SizeInBits * 2);

  auto LHS = MIRBuilder.buildInstr(ExtOp, {WideTy}, {MI.getOperand(1)});
  auto RHS = MIRBuilder.buildInstr(ExtOp, {WideTy}, {MI.getOperand(2)});
  auto Mul = MIRBuilder.buildMul(WideTy, LHS, RHS);
  unsigned ShiftOp = IsSigned ? TargetOpcode::G_ASHR : TargetOpcode::G_LSHR;

  auto ShiftAmt = MIRBuilder.buildConstant(WideTy, SizeInBits);
  auto Shifted = MIRBuilder.buildInstr(ShiftOp, {WideTy}, {Mul, ShiftAmt});
  MIRBuilder.buildTrunc(Result, Shifted);

  MI.eraseFromParent();
  return Legalized;
}

LegalizerHelper::LegalizeResult
LegalizerHelper::lowerISFPCLASS(MachineInstr &MI) {
  auto [DstReg, DstTy, SrcReg, SrcTy] = MI.getFirst2RegLLTs();
  FPClassTest Mask = static_cast<FPClassTest>(MI.getOperand(2).getImm());

  if (Mask == fcNone) {
    MIRBuilder.buildConstant(DstReg, 0);
    MI.eraseFromParent();
    return Legalized;
  }
  if (Mask == fcAllFlags) {
    MIRBuilder.buildConstant(DstReg, 1);
    MI.eraseFromParent();
    return Legalized;
  }

  // TODO: Try inverting the test with getInvertedFPClassTest like the DAG
  // version

  unsigned BitSize = SrcTy.getScalarSizeInBits();
  const fltSemantics &Semantics = getFltSemanticForLLT(SrcTy.getScalarType());

  LLT IntTy = SrcTy.changeElementType(LLT::integer(BitSize));
  auto AsInt = SrcTy == IntTy ? MIRBuilder.buildCopy(IntTy, SrcReg)
                              : MIRBuilder.buildBitcast(IntTy, SrcReg);

  // Various masks.
  APInt SignBit = APInt::getSignMask(BitSize);
  APInt ValueMask = APInt::getSignedMaxValue(BitSize);     // All bits but sign.
  APInt Inf = APFloat::getInf(Semantics).bitcastToAPInt(); // Exp and int bit.
  APInt ExpMask = Inf;
  APInt AllOneMantissa = APFloat::getLargest(Semantics).bitcastToAPInt() & ~Inf;
  APInt QNaNBitMask =
      APInt::getOneBitSet(BitSize, AllOneMantissa.getActiveBits() - 1);
  APInt InversionMask = APInt::getAllOnes(DstTy.getScalarSizeInBits());

  auto SignBitC = MIRBuilder.buildConstant(IntTy, SignBit);
  auto ValueMaskC = MIRBuilder.buildConstant(IntTy, ValueMask);
  auto InfC = MIRBuilder.buildConstant(IntTy, Inf);
  auto ExpMaskC = MIRBuilder.buildConstant(IntTy, ExpMask);
  auto ZeroC = MIRBuilder.buildConstant(IntTy, 0);

  auto Abs = MIRBuilder.buildAnd(IntTy, AsInt, ValueMaskC);
  auto Sign =
      MIRBuilder.buildICmp(CmpInst::Predicate::ICMP_NE, DstTy, AsInt, Abs);

  auto Res = MIRBuilder.buildConstant(DstTy, 0);
  // Clang doesn't support capture of structured bindings:
  LLT DstTyCopy = DstTy;
  const auto appendToRes = [&](MachineInstrBuilder ToAppend) {
    Res = MIRBuilder.buildOr(DstTyCopy, Res, ToAppend);
  };

  // Tests that involve more than one class should be processed first.
  if ((Mask & fcFinite) == fcFinite) {
    // finite(V) ==> abs(V) u< exp_mask
    appendToRes(MIRBuilder.buildICmp(CmpInst::Predicate::ICMP_ULT, DstTy, Abs,
                                     ExpMaskC));
    Mask &= ~fcFinite;
  } else if ((Mask & fcFinite) == fcPosFinite) {
    // finite(V) && V > 0 ==> V u< exp_mask
    appendToRes(MIRBuilder.buildICmp(CmpInst::Predicate::ICMP_ULT, DstTy, AsInt,
                                     ExpMaskC));
    Mask &= ~fcPosFinite;
  } else if ((Mask & fcFinite) == fcNegFinite) {
    // finite(V) && V < 0 ==> abs(V) u< exp_mask && signbit == 1
    auto Cmp = MIRBuilder.buildICmp(CmpInst::Predicate::ICMP_ULT, DstTy, Abs,
                                    ExpMaskC);
    auto And = MIRBuilder.buildAnd(DstTy, Cmp, Sign);
    appendToRes(And);
    Mask &= ~fcNegFinite;
  }

  if (FPClassTest PartialCheck = Mask & (fcZero | fcSubnormal)) {
    // fcZero | fcSubnormal => test all exponent bits are 0
    // TODO: Handle sign bit specific cases
    // TODO: Handle inverted case
    if (PartialCheck == (fcZero | fcSubnormal)) {
      auto ExpBits = MIRBuilder.buildAnd(IntTy, AsInt, ExpMaskC);
      appendToRes(MIRBuilder.buildICmp(CmpInst::Predicate::ICMP_EQ, DstTy,
                                       ExpBits, ZeroC));
      Mask &= ~PartialCheck;
    }
  }

  // Check for individual classes.
  if (FPClassTest PartialCheck = Mask & fcZero) {
    if (PartialCheck == fcPosZero)
      appendToRes(MIRBuilder.buildICmp(CmpInst::Predicate::ICMP_EQ, DstTy,
                                       AsInt, ZeroC));
    else if (PartialCheck == fcZero)
      appendToRes(
          MIRBuilder.buildICmp(CmpInst::Predicate::ICMP_EQ, DstTy, Abs, ZeroC));
    else // fcNegZero
      appendToRes(MIRBuilder.buildICmp(CmpInst::Predicate::ICMP_EQ, DstTy,
                                       AsInt, SignBitC));
  }

  if (FPClassTest PartialCheck = Mask & fcSubnormal) {
    // issubnormal(V) ==> unsigned(abs(V) - 1) u< (all mantissa bits set)
    // issubnormal(V) && V>0 ==> unsigned(V - 1) u< (all mantissa bits set)
    auto V = (PartialCheck == fcPosSubnormal) ? AsInt : Abs;
    auto OneC = MIRBuilder.buildConstant(IntTy, 1);
    auto VMinusOne = MIRBuilder.buildSub(IntTy, V, OneC);
    auto SubnormalRes =
        MIRBuilder.buildICmp(CmpInst::Predicate::ICMP_ULT, DstTy, VMinusOne,
                             MIRBuilder.buildConstant(IntTy, AllOneMantissa));
    if (PartialCheck == fcNegSubnormal)
      SubnormalRes = MIRBuilder.buildAnd(DstTy, SubnormalRes, Sign);
    appendToRes(SubnormalRes);
  }

  if (FPClassTest PartialCheck = Mask & fcInf) {
    if (PartialCheck == fcPosInf)
      appendToRes(MIRBuilder.buildICmp(CmpInst::Predicate::ICMP_EQ, DstTy,
                                       AsInt, InfC));
    else if (PartialCheck == fcInf)
      appendToRes(
          MIRBuilder.buildICmp(CmpInst::Predicate::ICMP_EQ, DstTy, Abs, InfC));
    else { // fcNegInf
      APInt NegInf = APFloat::getInf(Semantics, true).bitcastToAPInt();
      auto NegInfC = MIRBuilder.buildConstant(IntTy, NegInf);
      appendToRes(MIRBuilder.buildICmp(CmpInst::Predicate::ICMP_EQ, DstTy,
                                       AsInt, NegInfC));
    }
  }

  if (FPClassTest PartialCheck = Mask & fcNan) {
    auto InfWithQnanBitC = MIRBuilder.buildConstant(IntTy, Inf | QNaNBitMask);
    if (PartialCheck == fcNan) {
      // isnan(V) ==> abs(V) u> int(inf)
      appendToRes(
          MIRBuilder.buildICmp(CmpInst::Predicate::ICMP_UGT, DstTy, Abs, InfC));
    } else if (PartialCheck == fcQNan) {
      // isquiet(V) ==> abs(V) u>= (unsigned(Inf) | quiet_bit)
      appendToRes(MIRBuilder.buildICmp(CmpInst::Predicate::ICMP_UGE, DstTy, Abs,
                                       InfWithQnanBitC));
    } else { // fcSNan
      // issignaling(V) ==> abs(V) u> unsigned(Inf) &&
      //                    abs(V) u< (unsigned(Inf) | quiet_bit)
      auto IsNan =
          MIRBuilder.buildICmp(CmpInst::Predicate::ICMP_UGT, DstTy, Abs, InfC);
      auto IsNotQnan = MIRBuilder.buildICmp(CmpInst::Predicate::ICMP_ULT, DstTy,
                                            Abs, InfWithQnanBitC);
      appendToRes(MIRBuilder.buildAnd(DstTy, IsNan, IsNotQnan));
    }
  }

  if (FPClassTest PartialCheck = Mask & fcNormal) {
    // isnormal(V) ==> (0 u< exp u< max_exp) ==> (unsigned(exp-1) u<
    // (max_exp-1))
    APInt ExpLSB = ExpMask & ~(ExpMask.shl(1));
    auto ExpMinusOne = MIRBuilder.buildSub(
        IntTy, Abs, MIRBuilder.buildConstant(IntTy, ExpLSB));
    APInt MaxExpMinusOne = ExpMask - ExpLSB;
    auto NormalRes =
        MIRBuilder.buildICmp(CmpInst::Predicate::ICMP_ULT, DstTy, ExpMinusOne,
                             MIRBuilder.buildConstant(IntTy, MaxExpMinusOne));
    if (PartialCheck == fcNegNormal)
      NormalRes = MIRBuilder.buildAnd(DstTy, NormalRes, Sign);
    else if (PartialCheck == fcPosNormal) {
      auto PosSign = MIRBuilder.buildXor(
          DstTy, Sign, MIRBuilder.buildConstant(DstTy, InversionMask));
      NormalRes = MIRBuilder.buildAnd(DstTy, NormalRes, PosSign);
    }
    appendToRes(NormalRes);
  }

  MIRBuilder.buildCopy(DstReg, Res);
  MI.eraseFromParent();
  return Legalized;
}

LegalizerHelper::LegalizeResult LegalizerHelper::lowerSelect(MachineInstr &MI) {
  // Implement G_SELECT in terms of XOR, AND, OR.
  auto [DstReg, DstTy, MaskReg, MaskTy, Op1Reg, Op1Ty, Op2Reg, Op2Ty] =
      MI.getFirst4RegLLTs();

  LLT Op1TyInt =
      Op1Ty.changeElementType(LLT::integer(Op1Ty.getScalarSizeInBits()));

  bool IsEltPtr = DstTy.isPointerOrPointerVector();
  if (IsEltPtr) {
    LLT ScalarPtrTy = LLT::integer(DstTy.getScalarSizeInBits());
    LLT NewTy = DstTy.changeElementType(ScalarPtrTy);
    Op1Reg = MIRBuilder.buildPtrToInt(NewTy, Op1Reg).getReg(0);
    Op1Ty = MRI.getType(Op1Reg);
    Op2Reg = MIRBuilder.buildPtrToInt(NewTy, Op2Reg).getReg(0);
    Op2Ty = MRI.getType(Op2Reg);
    DstTy = NewTy;
  }

  if (MaskTy.isScalar()) {
    // Turn the scalar condition into a vector condition mask if needed.

    Register MaskElt = MaskReg;

    // The condition was potentially zero extended before, but we want a sign
    // extended boolean.
    if (MaskTy != LLT::scalar(1))
      MaskElt = MIRBuilder.buildSExtInReg(MaskTy, MaskElt, 1).getReg(0);

    // Continue the sign extension (or truncate) to match the data type.
    MaskTy = DstTy.changeElementType(LLT::integer(DstTy.getScalarSizeInBits()));
    MaskElt =
        MIRBuilder.buildSExtOrTrunc(MaskTy.getScalarType(), MaskElt).getReg(0);

    if (DstTy.isVector()) {
      // Generate a vector splat idiom.
      auto ShufSplat = MIRBuilder.buildShuffleSplat(MaskTy, MaskElt);
      MaskReg = ShufSplat.getReg(0);
    } else {
      MaskReg = MaskElt;
    }
  } else if (!DstTy.isVector()) {
    // Cannot handle the case that mask is a vector and dst is a scalar.
    return UnableToLegalize;
  }

  if (MaskTy.getSizeInBits() != DstTy.getSizeInBits()) {
    return UnableToLegalize;
  }

  if (!Op1Ty.getScalarType().isAnyScalar() &&
      !Op1Ty.getScalarType().isInteger())
    Op1Reg = MIRBuilder.buildBitcast(Op1TyInt, Op1Reg).getReg(0);

  if (!Op2Ty.getScalarType().isAnyScalar() &&
      !Op2Ty.getScalarType().isInteger()) {
    auto Op2TyInt =
        Op2Ty.changeElementType(LLT::integer(Op2Ty.getScalarSizeInBits()));
    Op2Reg = MIRBuilder.buildBitcast(Op2TyInt, Op2Reg).getReg(0);
  }

  auto NotMask = MIRBuilder.buildNot(MaskTy, MaskReg);
  auto NewOp1 = MIRBuilder.buildAnd(MaskTy, Op1Reg, MaskReg);
  auto NewOp2 = MIRBuilder.buildAnd(MaskTy, Op2Reg, NotMask);
  if (IsEltPtr) {
    auto Or = MIRBuilder.buildOr(DstTy, NewOp1, NewOp2);
    MIRBuilder.buildIntToPtr(DstReg, Or);
  } else {
    if (DstTy == Op1TyInt)
      MIRBuilder.buildOr(DstReg, NewOp1, NewOp2);
    else {
      auto Or = MIRBuilder.buildOr(Op1TyInt, NewOp1, NewOp2);
      MIRBuilder.buildBitcast(DstReg, Or.getReg(0));
    }
  }
  MI.eraseFromParent();
  return Legalized;
}

LegalizerHelper::LegalizeResult LegalizerHelper::lowerDIVREM(MachineInstr &MI) {
  // Split DIVREM into individual instructions.
  unsigned Opcode = MI.getOpcode();

  MIRBuilder.buildInstr(
      Opcode == TargetOpcode::G_SDIVREM ? TargetOpcode::G_SDIV
                                        : TargetOpcode::G_UDIV,
      {MI.getOperand(0).getReg()}, {MI.getOperand(2), MI.getOperand(3)});
  MIRBuilder.buildInstr(
      Opcode == TargetOpcode::G_SDIVREM ? TargetOpcode::G_SREM
                                        : TargetOpcode::G_UREM,
      {MI.getOperand(1).getReg()}, {MI.getOperand(2), MI.getOperand(3)});
  MI.eraseFromParent();
  return Legalized;
}

LegalizerHelper::LegalizeResult
LegalizerHelper::lowerAbsToAddXor(MachineInstr &MI) {
  // Expand %res = G_ABS %a into:
  // %v1 = G_ASHR %a, scalar_size-1
  // %v2 = G_ADD %a, %v1
  // %res = G_XOR %v2, %v1
  LLT DstTy = MRI.getType(MI.getOperand(0).getReg());
  Register OpReg = MI.getOperand(1).getReg();
  auto ShiftAmt =
      MIRBuilder.buildConstant(DstTy, DstTy.getScalarSizeInBits() - 1);
  auto Shift = MIRBuilder.buildAShr(DstTy, OpReg, ShiftAmt);
  auto Add = MIRBuilder.buildAdd(DstTy, OpReg, Shift);
  MIRBuilder.buildXor(MI.getOperand(0).getReg(), Add, Shift);
  MI.eraseFromParent();
  return Legalized;
}

LegalizerHelper::LegalizeResult
LegalizerHelper::lowerAbsToMaxNeg(MachineInstr &MI) {
  // Expand %res = G_ABS %a into:
  // %v1 = G_CONSTANT 0
  // %v2 = G_SUB %v1, %a
  // %res = G_SMAX %a, %v2
  Register SrcReg = MI.getOperand(1).getReg();
  LLT Ty = MRI.getType(SrcReg);
  auto Zero = MIRBuilder.buildConstant(Ty, 0);
  auto Sub = MIRBuilder.buildSub(Ty, Zero, SrcReg);
  MIRBuilder.buildSMax(MI.getOperand(0), SrcReg, Sub);
  MI.eraseFromParent();
  return Legalized;
}

LegalizerHelper::LegalizeResult
LegalizerHelper::lowerAbsToCNeg(MachineInstr &MI) {
  Register SrcReg = MI.getOperand(1).getReg();
  Register DestReg = MI.getOperand(0).getReg();
  LLT Ty = MRI.getType(SrcReg), IType = LLT::scalar(1);
  auto Zero = MIRBuilder.buildConstant(Ty, 0).getReg(0);
  auto Sub = MIRBuilder.buildSub(Ty, Zero, SrcReg).getReg(0);
  auto ICmp = MIRBuilder.buildICmp(CmpInst::ICMP_SGT, IType, SrcReg, Zero);
  MIRBuilder.buildSelect(DestReg, ICmp, SrcReg, Sub);
  MI.eraseFromParent();
  return Legalized;
}

LegalizerHelper::LegalizeResult
LegalizerHelper::lowerAbsDiffToSelect(MachineInstr &MI) {
  assert((MI.getOpcode() == TargetOpcode::G_ABDS ||
          MI.getOpcode() == TargetOpcode::G_ABDU) &&
         "Expected G_ABDS or G_ABDU instruction");

  auto [DstReg, LHS, RHS] = MI.getFirst3Regs();
  LLT Ty = MRI.getType(LHS);

  // abds(lhs, rhs) -> select(sgt(lhs,rhs), sub(lhs,rhs), sub(rhs,lhs))
  // abdu(lhs, rhs) -> select(ugt(lhs,rhs), sub(lhs,rhs), sub(rhs,lhs))
  Register LHSSub = MIRBuilder.buildSub(Ty, LHS, RHS).getReg(0);
  Register RHSSub = MIRBuilder.buildSub(Ty, RHS, LHS).getReg(0);
  CmpInst::Predicate Pred = (MI.getOpcode() == TargetOpcode::G_ABDS)
                                ? CmpInst::ICMP_SGT
                                : CmpInst::ICMP_UGT;
  auto ICmp = MIRBuilder.buildICmp(Pred, LLT::scalar(1), LHS, RHS);
  MIRBuilder.buildSelect(DstReg, ICmp, LHSSub, RHSSub);

  MI.eraseFromParent();
  return Legalized;
}

LegalizerHelper::LegalizeResult
LegalizerHelper::lowerAbsDiffToMinMax(MachineInstr &MI) {
  assert((MI.getOpcode() == TargetOpcode::G_ABDS ||
          MI.getOpcode() == TargetOpcode::G_ABDU) &&
         "Expected G_ABDS or G_ABDU instruction");

  auto [DstReg, LHS, RHS] = MI.getFirst3Regs();
  LLT Ty = MRI.getType(LHS);

  // abds(lhs, rhs) -→ sub(smax(lhs, rhs), smin(lhs, rhs))
  // abdu(lhs, rhs) -→ sub(umax(lhs, rhs), umin(lhs, rhs))
  Register MaxReg, MinReg;
  if (MI.getOpcode() == TargetOpcode::G_ABDS) {
    MaxReg = MIRBuilder.buildSMax(Ty, LHS, RHS).getReg(0);
    MinReg = MIRBuilder.buildSMin(Ty, LHS, RHS).getReg(0);
  } else {
    MaxReg = MIRBuilder.buildUMax(Ty, LHS, RHS).getReg(0);
    MinReg = MIRBuilder.buildUMin(Ty, LHS, RHS).getReg(0);
  }
  MIRBuilder.buildSub(DstReg, MaxReg, MinReg);

  MI.eraseFromParent();
  return Legalized;
}

LegalizerHelper::LegalizeResult LegalizerHelper::lowerFAbs(MachineInstr &MI) {
  auto [DstReg, DstTy, SrcReg, SrcTy] = MI.getFirst2RegLLTs();
  LLT TyInt =
      DstTy.changeElementType(LLT::integer(DstTy.getScalarSizeInBits()));
  Register CastedSrc = SrcReg;

  if (!(SrcTy.getScalarType().isAnyScalar() ||
        SrcTy.getScalarType().isInteger())) {
    auto SrcTyInt =
        SrcTy.changeElementType(LLT::integer(SrcTy.getScalarSizeInBits()));
    CastedSrc = MIRBuilder.buildBitcast(SrcTyInt, SrcReg).getReg(0);
  }

  if (MRI.getType(DstReg) != TyInt) {
    // Reset sign bit
    Register NewDst =
        MIRBuilder
            .buildAnd(TyInt, CastedSrc,
                      MIRBuilder.buildConstant(
                          TyInt, APInt::getSignedMaxValue(
                                     DstTy.getScalarSizeInBits())))
            .getReg(0);

    MIRBuilder.buildBitcast(DstReg, NewDst);
  } else
    MIRBuilder
        .buildAnd(
            DstReg, CastedSrc,
            MIRBuilder.buildConstant(
                TyInt, APInt::getSignedMaxValue(DstTy.getScalarSizeInBits())))
        .getReg(0);

  MI.eraseFromParent();
  return Legalized;
}

LegalizerHelper::LegalizeResult
LegalizerHelper::lowerVectorReduction(MachineInstr &MI) {
  Register SrcReg = MI.getOperand(1).getReg();
  LLT SrcTy = MRI.getType(SrcReg);
  LLT DstTy = MRI.getType(SrcReg);

  // The source could be a scalar if the IR type was <1 x sN>.
  if (SrcTy.isScalar()) {
    if (DstTy.getSizeInBits() > SrcTy.getSizeInBits())
      return UnableToLegalize; // FIXME: handle extension.
    // This can be just a plain copy.
    Observer.changingInstr(MI);
    MI.setDesc(MIRBuilder.getTII().get(TargetOpcode::COPY));
    Observer.changedInstr(MI);
    return Legalized;
  }
  return UnableToLegalize;
}

LegalizerHelper::LegalizeResult LegalizerHelper::lowerVAArg(MachineInstr &MI) {
  MachineFunction &MF = *MI.getMF();
  const DataLayout &DL = MIRBuilder.getDataLayout();
  LLVMContext &Ctx = MF.getFunction().getContext();
  Register ListPtr = MI.getOperand(1).getReg();
  LLT PtrTy = MRI.getType(ListPtr);

  // LstPtr is a pointer to the head of the list. Get the address
  // of the head of the list.
  Align PtrAlignment = DL.getABITypeAlign(getTypeForLLT(PtrTy, Ctx));
  MachineMemOperand *PtrLoadMMO = MF.getMachineMemOperand(
      MachinePointerInfo(), MachineMemOperand::MOLoad, PtrTy, PtrAlignment);
  auto VAList = MIRBuilder.buildLoad(PtrTy, ListPtr, *PtrLoadMMO).getReg(0);

  const Align A(MI.getOperand(2).getImm());
  LLT PtrTyAsScalarTy = LLT::scalar(PtrTy.getSizeInBits());
  if (A > TLI.getMinStackArgumentAlignment()) {
    Register AlignAmt =
        MIRBuilder.buildConstant(PtrTyAsScalarTy, A.value() - 1).getReg(0);
    auto AddDst = MIRBuilder.buildPtrAdd(PtrTy, VAList, AlignAmt);
    auto AndDst = MIRBuilder.buildMaskLowPtrBits(PtrTy, AddDst, Log2(A));
    VAList = AndDst.getReg(0);
  }

  // Increment the pointer, VAList, to the next vaarg
  // The list should be bumped by the size of element in the current head of
  // list.
  Register Dst = MI.getOperand(0).getReg();
  LLT LLTTy = MRI.getType(Dst);
  Type *Ty = getTypeForLLT(LLTTy, Ctx);
  auto IncAmt =
      MIRBuilder.buildConstant(PtrTyAsScalarTy, DL.getTypeAllocSize(Ty));
  auto Succ = MIRBuilder.buildPtrAdd(PtrTy, VAList, IncAmt);

  // Store the increment VAList to the legalized pointer
  MachineMemOperand *StoreMMO = MF.getMachineMemOperand(
      MachinePointerInfo(), MachineMemOperand::MOStore, PtrTy, PtrAlignment);
  MIRBuilder.buildStore(Succ, ListPtr, *StoreMMO);
  // Load the actual argument out of the pointer VAList
  Align EltAlignment = DL.getABITypeAlign(Ty);
  MachineMemOperand *EltLoadMMO = MF.getMachineMemOperand(
      MachinePointerInfo(), MachineMemOperand::MOLoad, LLTTy, EltAlignment);
  MIRBuilder.buildLoad(Dst, VAList, *EltLoadMMO);

  MI.eraseFromParent();
  return Legalized;
}

LegalizerHelper::LegalizeResult LegalizerHelper::lowerMulfix(MachineInstr &MI) {
  [[maybe_unused]] unsigned OpCode = MI.getOpcode();
  assert((OpCode == TargetOpcode::G_SMULFIX ||
          OpCode == TargetOpcode::G_UMULFIX) &&
         "Operator must be either G_SMULFIX or G_UMULFIX!");
  auto [Dst, LHS, RHS] = MI.getFirst3Regs();
  LLT Ty = MRI.getType(Dst);
  unsigned Scale = MI.getOperand(3).getImm();

  if (Scale == 0) {
    MIRBuilder.buildMul(Dst, LHS, RHS);
    MI.eraseFromParent();
    return Legalized;
  }

  // TODO: Port other lowerng paths from SelectionDAG.
  LLT WideTy = Ty.changeElementSize(Ty.getScalarSizeInBits() * 2);
  auto ShiftAmt = MIRBuilder.buildConstant(WideTy, Scale);
  MachineInstrBuilder ExtLHS{}, ExtRHS{}, Shift{};
  if (MI.getOpcode() == TargetOpcode::G_SMULFIX) {
    ExtLHS = MIRBuilder.buildSExt(WideTy, LHS);
    ExtRHS = MIRBuilder.buildSExt(WideTy, RHS);
  } else {
    ExtLHS = MIRBuilder.buildZExt(WideTy, LHS);
    ExtRHS = MIRBuilder.buildZExt(WideTy, RHS);
  }

  auto Mul = MIRBuilder.buildMul(WideTy, ExtLHS, ExtRHS);
  if (MI.getOpcode() == TargetOpcode::G_SMULFIX)
    Shift = MIRBuilder.buildAShr(WideTy, Mul, ShiftAmt);
  else
    Shift = MIRBuilder.buildLShr(WideTy, Mul, ShiftAmt);

  MIRBuilder.buildTrunc(Dst, Shift);

  MI.eraseFromParent();
  return Legalized;
}

// Get a vectorized representation of the memset value operand, GISel edition.
static Register getMemsetValue(Register Val, LLT Ty, MachineIRBuilder &MIB) {
  MachineRegisterInfo &MRI = *MIB.getMRI();
  unsigned NumBits = Ty.getScalarSizeInBits();
  auto ValVRegAndVal = getIConstantVRegValWithLookThrough(Val, MRI);
  if (!Ty.isVector() && ValVRegAndVal) {
    APInt Scalar = ValVRegAndVal->Value.trunc(8);
    APInt SplatVal = APInt::getSplat(NumBits, Scalar);
    return MIB.buildConstant(Ty, SplatVal).getReg(0);
  }

  // Extend the byte value to the larger type, and then multiply by a magic
  // value 0x010101... in order to replicate it across every byte.
  // Unless it's zero, in which case just emit a larger G_CONSTANT 0.
  if (ValVRegAndVal && ValVRegAndVal->Value == 0) {
    return MIB.buildConstant(Ty, 0).getReg(0);
  }

  LLT ExtType = Ty.getScalarType();
  auto ZExt = MIB.buildZExtOrTrunc(ExtType, Val);
  if (NumBits > 8) {
    APInt Magic = APInt::getSplat(NumBits, APInt(8, 0x01));
    auto MagicMI = MIB.buildConstant(ExtType, Magic);
    Val = MIB.buildMul(ExtType, ZExt, MagicMI).getReg(0);
  }

  // For vector types create a G_BUILD_VECTOR.
  if (Ty.isVector())
    Val = MIB.buildSplatBuildVector(Ty, Val).getReg(0);

  return Val;
}

LegalizerHelper::LegalizeResult
LegalizerHelper::lowerMemset(MachineInstr &MI, Register Dst, Register Val,
                             uint64_t KnownLen, Align Alignment,
                             bool DstAlignCanChange, ArrayRef<LLT> MemOps) {
  auto &MF = *MI.getParent()->getParent();
  const auto &TLI = *MF.getSubtarget().getTargetLowering();
  auto &DL = MF.getDataLayout();
  LLVMContext &C = MF.getFunction().getContext();

  assert(KnownLen != 0 && "Have a zero length memset length!");
  assert(!MemOps.empty() && "Expected at least one memory op");

  MachineFrameInfo &MFI = MF.getFrameInfo();
  MachineInstr *FIDef = getOpcodeDef(TargetOpcode::G_FRAME_INDEX, Dst, MRI);
  const auto &DstMMO = **MI.memoperands_begin();

  if (DstAlignCanChange) {
    // Get an estimate of the type from the LLT.
    Type *IRTy = getTypeForLLT(MemOps[0], C);
    Align NewAlign = DL.getABITypeAlign(IRTy);
    if (NewAlign > Alignment) {
      Alignment = NewAlign;
      unsigned FI = FIDef->getOperand(1).getIndex();
      // Give the stack frame object a larger alignment if needed.
      if (MFI.getObjectAlign(FI) < Alignment)
        MFI.setObjectAlignment(FI, Alignment);
    }
  }

  MachineIRBuilder MIB(MI);
  // Find the largest store and generate the bit pattern for it.
  LLT LargestTy = MemOps[0];
  for (unsigned i = 1; i < MemOps.size(); i++)
    if (MemOps[i].getSizeInBits() > LargestTy.getSizeInBits())
      LargestTy = MemOps[i];

  // The memset stored value is always defined as an s8, so in order to make it
  // work with larger store types we need to repeat the bit pattern across the
  // wider type.
  Register MemSetValue = getMemsetValue(Val, LargestTy, MIB);

  if (!MemSetValue)
    return UnableToLegalize;

  // Generate the stores. For each store type in the list, we generate the
  // matching store of that type to the destination address.
  LLT PtrTy = MRI.getType(Dst);
  unsigned DstOff = 0;
  unsigned Size = KnownLen;
  for (unsigned I = 0; I < MemOps.size(); I++) {
    LLT Ty = MemOps[I];
    unsigned TySize = Ty.getSizeInBytes();
    if (TySize > Size) {
      // Issuing an unaligned load / store pair that overlaps with the previous
      // pair. Adjust the offset accordingly.
      assert(I == MemOps.size() - 1 && I != 0);
      DstOff -= TySize - Size;
    }

    // If this store is smaller than the largest store see whether we can get
    // the smaller value for free with a truncate.
    Register Value = MemSetValue;
    if (Ty.getSizeInBits() < LargestTy.getSizeInBits()) {
      MVT VT = getMVTForLLT(Ty);
      MVT LargestVT = getMVTForLLT(LargestTy);
      if (!LargestTy.isVector() && !Ty.isVector() &&
          TLI.isTruncateFree(LargestVT, VT))
        Value = MIB.buildTrunc(Ty, MemSetValue).getReg(0);
      else
        Value = getMemsetValue(Val, Ty, MIB);
      if (!Value)
        return UnableToLegalize;
    }

    auto *StoreMMO = MF.getMachineMemOperand(&DstMMO, DstOff, Ty);

    Register Ptr = Dst;
    if (DstOff != 0) {
      auto Offset =
          MIB.buildConstant(LLT::scalar(PtrTy.getSizeInBits()), DstOff);
      Ptr = MIB.buildObjectPtrOffset(PtrTy, Dst, Offset).getReg(0);
    }

    MIB.buildStore(Value, Ptr, *StoreMMO);
    DstOff += Ty.getSizeInBytes();
    Size -= TySize;
  }

  MI.eraseFromParent();
  return Legalized;
}

LegalizerHelper::LegalizeResult
LegalizerHelper::lowerMemcpy(MachineInstr &MI, Register Dst, Register Src,
                             uint64_t KnownLen, Align Alignment,
                             bool DstAlignCanChange, ArrayRef<LLT> MemOps) {
  auto &MF = *MI.getParent()->getParent();
  auto &DL = MF.getDataLayout();
  LLVMContext &C = MF.getFunction().getContext();

  assert(KnownLen != 0 && "Have a zero length memcpy length!");
  assert(!MemOps.empty() && "Expected at least one memory op");

  MachineFrameInfo &MFI = MF.getFrameInfo();
  MachineInstr *FIDef = getOpcodeDef(TargetOpcode::G_FRAME_INDEX, Dst, MRI);

  // FIXME: infer better src pointer alignment like SelectionDAG does here.
  // FIXME: also use the equivalent of isMemSrcFromConstant and alwaysinlining
  // if the memcpy is in a tail call position.

  const auto &DstMMO = **MI.memoperands_begin();
  const auto &SrcMMO = **std::next(MI.memoperands_begin());

  if (DstAlignCanChange) {
    // Get an estimate of the type from the LLT.
    Type *IRTy = getTypeForLLT(MemOps[0], C);
    Align NewAlign = DL.getABITypeAlign(IRTy);

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

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

  LLVM_DEBUG(dbgs() << "Inlining memcpy: " << MI << " into loads & stores\n");

  MachineIRBuilder MIB(MI);
  // Now we need to emit a pair of load and stores for each of the types we've
  // collected. I.e. for each type, generate a load from the source pointer of
  // that type width, and then generate a corresponding store to the dest buffer
  // of that value loaded. This can result in a sequence of loads and stores
  // mixed types, depending on what the target specifies as good types to use.
  unsigned CurrOffset = 0;
  unsigned Size = KnownLen;
  for (auto CopyTy : MemOps) {
    // Issuing an unaligned load / store pair  that overlaps with the previous
    // pair. Adjust the offset accordingly.
    if (CopyTy.getSizeInBytes() > Size)
      CurrOffset -= CopyTy.getSizeInBytes() - Size;

    // Construct MMOs for the accesses.
    auto *LoadMMO =
        MF.getMachineMemOperand(&SrcMMO, CurrOffset, CopyTy.getSizeInBytes());
    auto *StoreMMO =
        MF.getMachineMemOperand(&DstMMO, CurrOffset, CopyTy.getSizeInBytes());

    // Create the load.
    Register LoadPtr = Src;
    Register Offset;
    if (CurrOffset != 0) {
      LLT SrcTy = MRI.getType(Src);
      Offset =
          MIB.buildConstant(LLT::integer(SrcTy.getSizeInBits()), CurrOffset)
              .getReg(0);
      LoadPtr = MIB.buildObjectPtrOffset(SrcTy, Src, Offset).getReg(0);
    }
    auto LdVal = MIB.buildLoad(CopyTy, LoadPtr, *LoadMMO);

    // Create the store.
    Register StorePtr = Dst;
    if (CurrOffset != 0) {
      LLT DstTy = MRI.getType(Dst);
      StorePtr = MIB.buildObjectPtrOffset(DstTy, Dst, Offset).getReg(0);
    }
    MIB.buildStore(LdVal, StorePtr, *StoreMMO);
    CurrOffset += CopyTy.getSizeInBytes();
    Size -= CopyTy.getSizeInBytes();
  }

  MI.eraseFromParent();
  return Legalized;
}

LegalizerHelper::LegalizeResult
LegalizerHelper::lowerMemmove(MachineInstr &MI, Register Dst, Register Src,
                              uint64_t KnownLen, Align Alignment,
                              bool DstAlignCanChange, ArrayRef<LLT> MemOps) {
  auto &MF = *MI.getParent()->getParent();
  auto &DL = MF.getDataLayout();
  LLVMContext &C = MF.getFunction().getContext();

  assert(KnownLen != 0 && "Have a zero length memmove length!");
  assert(!MemOps.empty() && "Expected at least one memory op");

  MachineFrameInfo &MFI = MF.getFrameInfo();
  MachineInstr *FIDef = getOpcodeDef(TargetOpcode::G_FRAME_INDEX, Dst, MRI);
  const auto &DstMMO = **MI.memoperands_begin();
  const auto &SrcMMO = **std::next(MI.memoperands_begin());

  if (DstAlignCanChange) {
    // Get an estimate of the type from the LLT.
    Type *IRTy = getTypeForLLT(MemOps[0], C);
    Align NewAlign = DL.getABITypeAlign(IRTy);

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

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

  LLVM_DEBUG(dbgs() << "Inlining memmove: " << MI << " into loads & stores\n");

  MachineIRBuilder MIB(MI);
  // Memmove requires that we perform the loads first before issuing the stores.
  // Apart from that, this loop is pretty much doing the same thing as the
  // memcpy codegen function.
  unsigned CurrOffset = 0;
  SmallVector<Register, 16> LoadVals;
  for (auto CopyTy : MemOps) {
    // Construct MMO for the load.
    auto *LoadMMO =
        MF.getMachineMemOperand(&SrcMMO, CurrOffset, CopyTy.getSizeInBytes());

    // Create the load.
    Register LoadPtr = Src;
    if (CurrOffset != 0) {
      LLT SrcTy = MRI.getType(Src);
      auto Offset =
          MIB.buildConstant(LLT::scalar(SrcTy.getSizeInBits()), CurrOffset);
      LoadPtr = MIB.buildObjectPtrOffset(SrcTy, Src, Offset).getReg(0);
    }
    LoadVals.push_back(MIB.buildLoad(CopyTy, LoadPtr, *LoadMMO).getReg(0));
    CurrOffset += CopyTy.getSizeInBytes();
  }

  CurrOffset = 0;
  for (unsigned I = 0; I < MemOps.size(); ++I) {
    LLT CopyTy = MemOps[I];
    // Now store the values loaded.
    auto *StoreMMO =
        MF.getMachineMemOperand(&DstMMO, CurrOffset, CopyTy.getSizeInBytes());

    Register StorePtr = Dst;
    if (CurrOffset != 0) {
      LLT DstTy = MRI.getType(Dst);
      auto Offset =
          MIB.buildConstant(LLT::scalar(DstTy.getSizeInBits()), CurrOffset);
      StorePtr = MIB.buildObjectPtrOffset(DstTy, Dst, Offset).getReg(0);
    }
    MIB.buildStore(LoadVals[I], StorePtr, *StoreMMO);
    CurrOffset += CopyTy.getSizeInBytes();
  }
  MI.eraseFromParent();
  return Legalized;
}

LegalizerHelper::LegalizeResult LegalizerHelper::lowerMemCpyFamily(
    MachineInstr &MI, Register Dst, Register Src, uint64_t KnownLen,
    Align Alignment, bool DstAlignCanChange, ArrayRef<LLT> MemOps) {
  const unsigned Opc = MI.getOpcode();
  assert((Opc == TargetOpcode::G_MEMCPY ||
          Opc == TargetOpcode::G_MEMCPY_INLINE ||
          Opc == TargetOpcode::G_MEMMOVE || Opc == TargetOpcode::G_MEMSET ||
          Opc == TargetOpcode::G_MEMSET_INLINE) &&
         "Expected memcpy like instruction");

  if (KnownLen == 0) {
    MI.eraseFromParent();
    return Legalized;
  }

  if (Opc == TargetOpcode::G_MEMCPY || Opc == TargetOpcode::G_MEMCPY_INLINE) {
    return lowerMemcpy(MI, Dst, Src, KnownLen, Alignment, DstAlignCanChange,
                       MemOps);
  }
  if (Opc == TargetOpcode::G_MEMMOVE)
    return lowerMemmove(MI, Dst, Src, KnownLen, Alignment, DstAlignCanChange,
                        MemOps);
  if (Opc == TargetOpcode::G_MEMSET || Opc == TargetOpcode::G_MEMSET_INLINE)
    return lowerMemset(MI, Dst, Src, KnownLen, Alignment, DstAlignCanChange,
                       MemOps);
  return UnableToLegalize;
}

LegalizerHelper::LegalizeResult
LegalizerHelper::lowerMemCpyFamily(MachineInstr &MI, unsigned MaxLen) {
  Register Dst, Src;
  uint64_t KnownLen;
  Align Alignment;
  bool DstAlignCanChange;
  std::vector<LLT> MemOps;
  if (!canLowerMemCpyFamily(MI, MRI, MaxLen, Dst, Src, KnownLen, Alignment,
                            DstAlignCanChange, MemOps))
    return UnableToLegalize;
  return lowerMemCpyFamily(MI, Dst, Src, KnownLen, Alignment, DstAlignCanChange,
                           MemOps);
}
