//===- AMDGPUInstructionSelector.cpp ----------------------------*- C++ -*-==//
//
// 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 targeting of the InstructionSelector class for
/// AMDGPU.
/// \todo This should be generated by TableGen.
//===----------------------------------------------------------------------===//

#include "AMDGPUInstructionSelector.h"
#include "AMDGPU.h"
#include "AMDGPUGlobalISelUtils.h"
#include "AMDGPUInstrInfo.h"
#include "AMDGPURegisterBankInfo.h"
#include "AMDGPUTargetMachine.h"
#include "SIMachineFunctionInfo.h"
#include "Utils/AMDGPUBaseInfo.h"
#include "llvm/CodeGen/GlobalISel/GIMatchTableExecutorImpl.h"
#include "llvm/CodeGen/GlobalISel/GISelValueTracking.h"
#include "llvm/CodeGen/GlobalISel/GenericMachineInstrs.h"
#include "llvm/CodeGen/GlobalISel/MIPatternMatch.h"
#include "llvm/CodeGen/GlobalISel/MachineIRBuilder.h"
#include "llvm/CodeGen/MachineFrameInfo.h"
#include "llvm/IR/DiagnosticInfo.h"
#include "llvm/IR/IntrinsicsAMDGPU.h"
#include <optional>

#define DEBUG_TYPE "amdgpu-isel"

using namespace llvm;
using namespace MIPatternMatch;

#define GET_GLOBALISEL_IMPL
#define AMDGPUSubtarget GCNSubtarget
#include "AMDGPUGenGlobalISel.inc"
#undef GET_GLOBALISEL_IMPL
#undef AMDGPUSubtarget

AMDGPUInstructionSelector::AMDGPUInstructionSelector(
    const GCNSubtarget &STI, const AMDGPURegisterBankInfo &RBI,
    const AMDGPUTargetMachine &TM)
    : TII(*STI.getInstrInfo()), TRI(*STI.getRegisterInfo()), RBI(RBI), TM(TM),
      STI(STI),
#define GET_GLOBALISEL_PREDICATES_INIT
#include "AMDGPUGenGlobalISel.inc"
#undef GET_GLOBALISEL_PREDICATES_INIT
#define GET_GLOBALISEL_TEMPORARIES_INIT
#include "AMDGPUGenGlobalISel.inc"
#undef GET_GLOBALISEL_TEMPORARIES_INIT
{
}

const char *AMDGPUInstructionSelector::getName() { return DEBUG_TYPE; }

void AMDGPUInstructionSelector::setupMF(MachineFunction &MF,
                                        GISelValueTracking *VT,
                                        CodeGenCoverage *CoverageInfo,
                                        ProfileSummaryInfo *PSI,
                                        BlockFrequencyInfo *BFI) {
  MRI = &MF.getRegInfo();
  Subtarget = &MF.getSubtarget<GCNSubtarget>();
  Subtarget->checkSubtargetFeatures(MF.getFunction());
  InstructionSelector::setupMF(MF, VT, CoverageInfo, PSI, BFI);
}

// Return the wave level SGPR base address if this is a wave address.
static Register getWaveAddress(const MachineInstr *Def) {
  return Def->getOpcode() == AMDGPU::G_AMDGPU_WAVE_ADDRESS
             ? Def->getOperand(1).getReg()
             : Register();
}

bool AMDGPUInstructionSelector::isVCC(Register Reg,
                                      const MachineRegisterInfo &MRI) const {
  // The verifier is oblivious to s1 being a valid value for wavesize registers.
  if (Reg.isPhysical())
    return false;

  auto &RegClassOrBank = MRI.getRegClassOrRegBank(Reg);
  const TargetRegisterClass *RC =
      dyn_cast<const TargetRegisterClass *>(RegClassOrBank);
  if (RC) {
    const LLT Ty = MRI.getType(Reg);
    if (!Ty.isValid() || Ty.getSizeInBits() != 1)
      return false;
    // G_TRUNC s1 result is never vcc.
    return MRI.getVRegDef(Reg)->getOpcode() != AMDGPU::G_TRUNC &&
           RC->hasSuperClassEq(TRI.getBoolRC());
  }

  const RegisterBank *RB = cast<const RegisterBank *>(RegClassOrBank);
  return RB->getID() == AMDGPU::VCCRegBankID;
}

bool AMDGPUInstructionSelector::constrainCopyLikeIntrin(MachineInstr &MI,
                                                        unsigned NewOpc) const {
  MI.setDesc(TII.get(NewOpc));
  MI.removeOperand(1); // Remove intrinsic ID.
  MI.addOperand(*MF, MachineOperand::CreateReg(AMDGPU::EXEC, false, true));

  MachineOperand &Dst = MI.getOperand(0);
  MachineOperand &Src = MI.getOperand(1);

  // TODO: This should be legalized to s32 if needed
  if (MRI->getType(Dst.getReg()) == LLT::scalar(1))
    return false;

  const TargetRegisterClass *DstRC
    = TRI.getConstrainedRegClassForOperand(Dst, *MRI);
  const TargetRegisterClass *SrcRC
    = TRI.getConstrainedRegClassForOperand(Src, *MRI);
  if (!DstRC || DstRC != SrcRC)
    return false;

  if (!RBI.constrainGenericRegister(Dst.getReg(), *DstRC, *MRI) ||
      !RBI.constrainGenericRegister(Src.getReg(), *SrcRC, *MRI))
    return false;
  const MCInstrDesc &MCID = MI.getDesc();
  if (MCID.getOperandConstraint(0, MCOI::EARLY_CLOBBER) != -1) {
    MI.getOperand(0).setIsEarlyClobber(true);
  }
  return true;
}

bool AMDGPUInstructionSelector::selectCOPY(MachineInstr &I) const {
  const DebugLoc &DL = I.getDebugLoc();
  MachineBasicBlock *BB = I.getParent();
  I.setDesc(TII.get(TargetOpcode::COPY));

  const MachineOperand &Src = I.getOperand(1);
  MachineOperand &Dst = I.getOperand(0);
  Register DstReg = Dst.getReg();
  Register SrcReg = Src.getReg();

  if (isVCC(DstReg, *MRI)) {
    if (SrcReg == AMDGPU::SCC) {
      const TargetRegisterClass *RC
        = TRI.getConstrainedRegClassForOperand(Dst, *MRI);
      if (!RC)
        return true;
      return RBI.constrainGenericRegister(DstReg, *RC, *MRI);
    }

    if (!isVCC(SrcReg, *MRI)) {
      // TODO: Should probably leave the copy and let copyPhysReg expand it.
      if (!RBI.constrainGenericRegister(DstReg, *TRI.getBoolRC(), *MRI))
        return false;

      const TargetRegisterClass *SrcRC
        = TRI.getConstrainedRegClassForOperand(Src, *MRI);

      std::optional<ValueAndVReg> ConstVal =
          getIConstantVRegValWithLookThrough(SrcReg, *MRI, true);
      if (ConstVal) {
        unsigned MovOpc =
            STI.isWave64() ? AMDGPU::S_MOV_B64 : AMDGPU::S_MOV_B32;
        BuildMI(*BB, &I, DL, TII.get(MovOpc), DstReg)
            .addImm(ConstVal->Value.getBoolValue() ? -1 : 0);
      } else {
        Register MaskedReg = MRI->createVirtualRegister(SrcRC);

        // We can't trust the high bits at this point, so clear them.

        // TODO: Skip masking high bits if def is known boolean.

        if (AMDGPU::getRegBitWidth(SrcRC->getID()) == 16) {
          assert(Subtarget->useRealTrue16Insts());
          const int64_t NoMods = 0;
          BuildMI(*BB, &I, DL, TII.get(AMDGPU::V_AND_B16_t16_e64), MaskedReg)
              .addImm(NoMods)
              .addImm(1)
              .addImm(NoMods)
              .addReg(SrcReg)
              .addImm(NoMods);
          BuildMI(*BB, &I, DL, TII.get(AMDGPU::V_CMP_NE_U16_t16_e64), DstReg)
              .addImm(NoMods)
              .addImm(0)
              .addImm(NoMods)
              .addReg(MaskedReg)
              .addImm(NoMods);
        } else {
          bool IsSGPR = TRI.isSGPRClass(SrcRC);
          unsigned AndOpc = IsSGPR ? AMDGPU::S_AND_B32 : AMDGPU::V_AND_B32_e32;
          auto And = BuildMI(*BB, &I, DL, TII.get(AndOpc), MaskedReg)
                         .addImm(1)
                         .addReg(SrcReg);
          if (IsSGPR)
            And.setOperandDead(3); // Dead scc

          BuildMI(*BB, &I, DL, TII.get(AMDGPU::V_CMP_NE_U32_e64), DstReg)
              .addImm(0)
              .addReg(MaskedReg);
        }
      }

      if (!MRI->getRegClassOrNull(SrcReg))
        MRI->setRegClass(SrcReg, SrcRC);
      I.eraseFromParent();
      return true;
    }

    const TargetRegisterClass *RC =
      TRI.getConstrainedRegClassForOperand(Dst, *MRI);
    if (RC && !RBI.constrainGenericRegister(DstReg, *RC, *MRI))
      return false;

    return true;
  }

  for (const MachineOperand &MO : I.operands()) {
    if (MO.getReg().isPhysical())
      continue;

    const TargetRegisterClass *RC =
            TRI.getConstrainedRegClassForOperand(MO, *MRI);
    if (!RC)
      continue;
    RBI.constrainGenericRegister(MO.getReg(), *RC, *MRI);
  }
  return true;
}

bool AMDGPUInstructionSelector::selectCOPY_SCC_VCC(MachineInstr &I) const {
  const DebugLoc &DL = I.getDebugLoc();
  MachineBasicBlock *BB = I.getParent();
  Register VCCReg = I.getOperand(1).getReg();
  MachineInstr *Cmp;

  // Set SCC as a side effect with S_CMP or S_OR.
  if (STI.hasScalarCompareEq64()) {
    unsigned CmpOpc =
        STI.isWave64() ? AMDGPU::S_CMP_LG_U64 : AMDGPU::S_CMP_LG_U32;
    Cmp = BuildMI(*BB, &I, DL, TII.get(CmpOpc)).addReg(VCCReg).addImm(0);
  } else {
    Register DeadDst = MRI->createVirtualRegister(&AMDGPU::SReg_64RegClass);
    Cmp = BuildMI(*BB, &I, DL, TII.get(AMDGPU::S_OR_B64), DeadDst)
              .addReg(VCCReg)
              .addReg(VCCReg);
  }

  if (!constrainSelectedInstRegOperands(*Cmp, TII, TRI, RBI))
    return false;

  Register DstReg = I.getOperand(0).getReg();
  BuildMI(*BB, &I, DL, TII.get(AMDGPU::COPY), DstReg).addReg(AMDGPU::SCC);

  I.eraseFromParent();
  return RBI.constrainGenericRegister(DstReg, AMDGPU::SReg_32RegClass, *MRI);
}

bool AMDGPUInstructionSelector::selectCOPY_VCC_SCC(MachineInstr &I) const {
  const DebugLoc &DL = I.getDebugLoc();
  MachineBasicBlock *BB = I.getParent();

  Register DstReg = I.getOperand(0).getReg();
  Register SrcReg = I.getOperand(1).getReg();
  std::optional<ValueAndVReg> Arg =
      getIConstantVRegValWithLookThrough(I.getOperand(1).getReg(), *MRI);

  if (Arg) {
    const int64_t Value = Arg->Value.getZExtValue();
    if (Value == 0) {
      unsigned Opcode = STI.isWave64() ? AMDGPU::S_MOV_B64 : AMDGPU::S_MOV_B32;
      BuildMI(*BB, &I, DL, TII.get(Opcode), DstReg).addImm(0);
    } else {
      assert(Value == 1);
      BuildMI(*BB, &I, DL, TII.get(AMDGPU::COPY), DstReg).addReg(TRI.getExec());
    }
    I.eraseFromParent();
    return RBI.constrainGenericRegister(DstReg, *TRI.getBoolRC(), *MRI);
  }

  // RegBankLegalize ensures that SrcReg is bool in reg (high bits are 0).
  BuildMI(*BB, &I, DL, TII.get(AMDGPU::COPY), AMDGPU::SCC).addReg(SrcReg);

  unsigned SelectOpcode =
      STI.isWave64() ? AMDGPU::S_CSELECT_B64 : AMDGPU::S_CSELECT_B32;
  MachineInstr *Select = BuildMI(*BB, &I, DL, TII.get(SelectOpcode), DstReg)
                             .addReg(TRI.getExec())
                             .addImm(0);

  I.eraseFromParent();
  return constrainSelectedInstRegOperands(*Select, TII, TRI, RBI);
}

bool AMDGPUInstructionSelector::selectReadAnyLane(MachineInstr &I) const {
  Register DstReg = I.getOperand(0).getReg();
  Register SrcReg = I.getOperand(1).getReg();

  const DebugLoc &DL = I.getDebugLoc();
  MachineBasicBlock *BB = I.getParent();

  auto RFL = BuildMI(*BB, &I, DL, TII.get(AMDGPU::V_READFIRSTLANE_B32), DstReg)
                 .addReg(SrcReg);

  I.eraseFromParent();
  return constrainSelectedInstRegOperands(*RFL, TII, TRI, RBI);
}

bool AMDGPUInstructionSelector::selectPHI(MachineInstr &I) const {
  const Register DefReg = I.getOperand(0).getReg();
  const LLT DefTy = MRI->getType(DefReg);

  // S1 G_PHIs should not be selected in instruction-select, instead:
  // - divergent S1 G_PHI should go through lane mask merging algorithm
  //   and be fully inst-selected in AMDGPUGlobalISelDivergenceLowering
  // - uniform S1 G_PHI should be lowered into S32 G_PHI in AMDGPURegBankSelect
  if (DefTy == LLT::scalar(1))
    return false;

  // TODO: Verify this doesn't have insane operands (i.e. VGPR to SGPR copy)

  const RegClassOrRegBank &RegClassOrBank =
    MRI->getRegClassOrRegBank(DefReg);

  const TargetRegisterClass *DefRC =
      dyn_cast<const TargetRegisterClass *>(RegClassOrBank);
  if (!DefRC) {
    if (!DefTy.isValid()) {
      LLVM_DEBUG(dbgs() << "PHI operand has no type, not a gvreg?\n");
      return false;
    }

    const RegisterBank &RB = *cast<const RegisterBank *>(RegClassOrBank);
    DefRC = TRI.getRegClassForTypeOnBank(DefTy, RB);
    if (!DefRC) {
      LLVM_DEBUG(dbgs() << "PHI operand has unexpected size/bank\n");
      return false;
    }
  }

  // If inputs have register bank, assign corresponding reg class.
  // Note: registers don't need to have the same reg bank.
  for (unsigned i = 1; i != I.getNumOperands(); i += 2) {
    const Register SrcReg = I.getOperand(i).getReg();

    const RegisterBank *RB = MRI->getRegBankOrNull(SrcReg);
    if (RB) {
      const LLT SrcTy = MRI->getType(SrcReg);
      const TargetRegisterClass *SrcRC =
          TRI.getRegClassForTypeOnBank(SrcTy, *RB);
      if (!RBI.constrainGenericRegister(SrcReg, *SrcRC, *MRI))
        return false;
    }
  }

  I.setDesc(TII.get(TargetOpcode::PHI));
  return RBI.constrainGenericRegister(DefReg, *DefRC, *MRI);
}

MachineOperand
AMDGPUInstructionSelector::getSubOperand64(MachineOperand &MO,
                                           const TargetRegisterClass &SubRC,
                                           unsigned SubIdx) const {

  MachineInstr *MI = MO.getParent();
  MachineBasicBlock *BB = MO.getParent()->getParent();
  Register DstReg = MRI->createVirtualRegister(&SubRC);

  if (MO.isReg()) {
    unsigned ComposedSubIdx = TRI.composeSubRegIndices(MO.getSubReg(), SubIdx);
    Register Reg = MO.getReg();
    BuildMI(*BB, MI, MI->getDebugLoc(), TII.get(AMDGPU::COPY), DstReg)
            .addReg(Reg, 0, ComposedSubIdx);

    return MachineOperand::CreateReg(DstReg, MO.isDef(), MO.isImplicit(),
                                     MO.isKill(), MO.isDead(), MO.isUndef(),
                                     MO.isEarlyClobber(), 0, MO.isDebug(),
                                     MO.isInternalRead());
  }

  assert(MO.isImm());

  APInt Imm(64, MO.getImm());

  switch (SubIdx) {
  default:
    llvm_unreachable("do not know to split immediate with this sub index.");
  case AMDGPU::sub0:
    return MachineOperand::CreateImm(Imm.getLoBits(32).getSExtValue());
  case AMDGPU::sub1:
    return MachineOperand::CreateImm(Imm.getHiBits(32).getSExtValue());
  }
}

static unsigned getLogicalBitOpcode(unsigned Opc, bool Is64) {
  switch (Opc) {
  case AMDGPU::G_AND:
    return Is64 ? AMDGPU::S_AND_B64 : AMDGPU::S_AND_B32;
  case AMDGPU::G_OR:
    return Is64 ? AMDGPU::S_OR_B64 : AMDGPU::S_OR_B32;
  case AMDGPU::G_XOR:
    return Is64 ? AMDGPU::S_XOR_B64 : AMDGPU::S_XOR_B32;
  default:
    llvm_unreachable("not a bit op");
  }
}

bool AMDGPUInstructionSelector::selectG_AND_OR_XOR(MachineInstr &I) const {
  Register DstReg = I.getOperand(0).getReg();
  unsigned Size = RBI.getSizeInBits(DstReg, *MRI, TRI);

  const RegisterBank *DstRB = RBI.getRegBank(DstReg, *MRI, TRI);
  if (DstRB->getID() != AMDGPU::SGPRRegBankID &&
      DstRB->getID() != AMDGPU::VCCRegBankID)
    return false;

  bool Is64 = Size > 32 || (DstRB->getID() == AMDGPU::VCCRegBankID &&
                            STI.isWave64());
  I.setDesc(TII.get(getLogicalBitOpcode(I.getOpcode(), Is64)));

  // Dead implicit-def of scc
  I.addOperand(MachineOperand::CreateReg(AMDGPU::SCC, true, // isDef
                                         true, // isImp
                                         false, // isKill
                                         true)); // isDead
  return constrainSelectedInstRegOperands(I, TII, TRI, RBI);
}

bool AMDGPUInstructionSelector::selectG_ADD_SUB(MachineInstr &I) const {
  MachineBasicBlock *BB = I.getParent();
  MachineFunction *MF = BB->getParent();
  Register DstReg = I.getOperand(0).getReg();
  const DebugLoc &DL = I.getDebugLoc();
  LLT Ty = MRI->getType(DstReg);
  if (Ty.isVector())
    return false;

  unsigned Size = Ty.getSizeInBits();
  const RegisterBank *DstRB = RBI.getRegBank(DstReg, *MRI, TRI);
  const bool IsSALU = DstRB->getID() == AMDGPU::SGPRRegBankID;
  const bool Sub = I.getOpcode() == TargetOpcode::G_SUB;

  if (Size == 32) {
    if (IsSALU) {
      const unsigned Opc = Sub ? AMDGPU::S_SUB_U32 : AMDGPU::S_ADD_U32;
      MachineInstr *Add =
        BuildMI(*BB, &I, DL, TII.get(Opc), DstReg)
        .add(I.getOperand(1))
        .add(I.getOperand(2))
        .setOperandDead(3); // Dead scc
      I.eraseFromParent();
      return constrainSelectedInstRegOperands(*Add, TII, TRI, RBI);
    }

    if (STI.hasAddNoCarry()) {
      const unsigned Opc = Sub ? AMDGPU::V_SUB_U32_e64 : AMDGPU::V_ADD_U32_e64;
      I.setDesc(TII.get(Opc));
      I.addOperand(*MF, MachineOperand::CreateImm(0));
      I.addOperand(*MF, MachineOperand::CreateReg(AMDGPU::EXEC, false, true));
      return constrainSelectedInstRegOperands(I, TII, TRI, RBI);
    }

    const unsigned Opc = Sub ? AMDGPU::V_SUB_CO_U32_e64 : AMDGPU::V_ADD_CO_U32_e64;

    Register UnusedCarry = MRI->createVirtualRegister(TRI.getWaveMaskRegClass());
    MachineInstr *Add
      = BuildMI(*BB, &I, DL, TII.get(Opc), DstReg)
      .addDef(UnusedCarry, RegState::Dead)
      .add(I.getOperand(1))
      .add(I.getOperand(2))
      .addImm(0);
    I.eraseFromParent();
    return constrainSelectedInstRegOperands(*Add, TII, TRI, RBI);
  }

  assert(!Sub && "illegal sub should not reach here");

  const TargetRegisterClass &RC
    = IsSALU ? AMDGPU::SReg_64_XEXECRegClass : AMDGPU::VReg_64RegClass;
  const TargetRegisterClass &HalfRC
    = IsSALU ? AMDGPU::SReg_32RegClass : AMDGPU::VGPR_32RegClass;

  MachineOperand Lo1(getSubOperand64(I.getOperand(1), HalfRC, AMDGPU::sub0));
  MachineOperand Lo2(getSubOperand64(I.getOperand(2), HalfRC, AMDGPU::sub0));
  MachineOperand Hi1(getSubOperand64(I.getOperand(1), HalfRC, AMDGPU::sub1));
  MachineOperand Hi2(getSubOperand64(I.getOperand(2), HalfRC, AMDGPU::sub1));

  Register DstLo = MRI->createVirtualRegister(&HalfRC);
  Register DstHi = MRI->createVirtualRegister(&HalfRC);

  if (IsSALU) {
    BuildMI(*BB, &I, DL, TII.get(AMDGPU::S_ADD_U32), DstLo)
      .add(Lo1)
      .add(Lo2);
    BuildMI(*BB, &I, DL, TII.get(AMDGPU::S_ADDC_U32), DstHi)
      .add(Hi1)
      .add(Hi2)
      .setOperandDead(3); // Dead scc
  } else {
    const TargetRegisterClass *CarryRC = TRI.getWaveMaskRegClass();
    Register CarryReg = MRI->createVirtualRegister(CarryRC);
    BuildMI(*BB, &I, DL, TII.get(AMDGPU::V_ADD_CO_U32_e64), DstLo)
      .addDef(CarryReg)
      .add(Lo1)
      .add(Lo2)
      .addImm(0);
    MachineInstr *Addc = BuildMI(*BB, &I, DL, TII.get(AMDGPU::V_ADDC_U32_e64), DstHi)
      .addDef(MRI->createVirtualRegister(CarryRC), RegState::Dead)
      .add(Hi1)
      .add(Hi2)
      .addReg(CarryReg, RegState::Kill)
      .addImm(0);

    if (!constrainSelectedInstRegOperands(*Addc, TII, TRI, RBI))
      return false;
  }

  BuildMI(*BB, &I, DL, TII.get(AMDGPU::REG_SEQUENCE), DstReg)
    .addReg(DstLo)
    .addImm(AMDGPU::sub0)
    .addReg(DstHi)
    .addImm(AMDGPU::sub1);


  if (!RBI.constrainGenericRegister(DstReg, RC, *MRI))
    return false;

  I.eraseFromParent();
  return true;
}

bool AMDGPUInstructionSelector::selectG_UADDO_USUBO_UADDE_USUBE(
  MachineInstr &I) const {
  MachineBasicBlock *BB = I.getParent();
  MachineFunction *MF = BB->getParent();
  const DebugLoc &DL = I.getDebugLoc();
  Register Dst0Reg = I.getOperand(0).getReg();
  Register Dst1Reg = I.getOperand(1).getReg();
  const bool IsAdd = I.getOpcode() == AMDGPU::G_UADDO ||
                     I.getOpcode() == AMDGPU::G_UADDE;
  const bool HasCarryIn = I.getOpcode() == AMDGPU::G_UADDE ||
                          I.getOpcode() == AMDGPU::G_USUBE;

  if (isVCC(Dst1Reg, *MRI)) {
    unsigned NoCarryOpc =
        IsAdd ? AMDGPU::V_ADD_CO_U32_e64 : AMDGPU::V_SUB_CO_U32_e64;
    unsigned CarryOpc = IsAdd ? AMDGPU::V_ADDC_U32_e64 : AMDGPU::V_SUBB_U32_e64;
    I.setDesc(TII.get(HasCarryIn ? CarryOpc : NoCarryOpc));
    I.addOperand(*MF, MachineOperand::CreateReg(AMDGPU::EXEC, false, true));
    I.addOperand(*MF, MachineOperand::CreateImm(0));
    return constrainSelectedInstRegOperands(I, TII, TRI, RBI);
  }

  Register Src0Reg = I.getOperand(2).getReg();
  Register Src1Reg = I.getOperand(3).getReg();

  if (HasCarryIn) {
    BuildMI(*BB, &I, DL, TII.get(AMDGPU::COPY), AMDGPU::SCC)
      .addReg(I.getOperand(4).getReg());
  }

  unsigned NoCarryOpc = IsAdd ? AMDGPU::S_ADD_U32 : AMDGPU::S_SUB_U32;
  unsigned CarryOpc = IsAdd ? AMDGPU::S_ADDC_U32 : AMDGPU::S_SUBB_U32;

  auto CarryInst = BuildMI(*BB, &I, DL, TII.get(HasCarryIn ? CarryOpc : NoCarryOpc), Dst0Reg)
    .add(I.getOperand(2))
    .add(I.getOperand(3));

  if (MRI->use_nodbg_empty(Dst1Reg)) {
    CarryInst.setOperandDead(3); // Dead scc
  } else {
    BuildMI(*BB, &I, DL, TII.get(AMDGPU::COPY), Dst1Reg)
      .addReg(AMDGPU::SCC);
    if (!MRI->getRegClassOrNull(Dst1Reg))
      MRI->setRegClass(Dst1Reg, &AMDGPU::SReg_32RegClass);
  }

  if (!RBI.constrainGenericRegister(Dst0Reg, AMDGPU::SReg_32RegClass, *MRI) ||
      !RBI.constrainGenericRegister(Src0Reg, AMDGPU::SReg_32RegClass, *MRI) ||
      !RBI.constrainGenericRegister(Src1Reg, AMDGPU::SReg_32RegClass, *MRI))
    return false;

  if (HasCarryIn &&
      !RBI.constrainGenericRegister(I.getOperand(4).getReg(),
                                    AMDGPU::SReg_32RegClass, *MRI))
    return false;

  I.eraseFromParent();
  return true;
}

bool AMDGPUInstructionSelector::selectG_AMDGPU_MAD_64_32(
    MachineInstr &I) const {
  MachineBasicBlock *BB = I.getParent();
  MachineFunction *MF = BB->getParent();
  const bool IsUnsigned = I.getOpcode() == AMDGPU::G_AMDGPU_MAD_U64_U32;
  bool UseNoCarry = Subtarget->hasMadU64U32NoCarry() &&
                    MRI->use_nodbg_empty(I.getOperand(1).getReg());

  unsigned Opc;
  if (Subtarget->hasMADIntraFwdBug())
    Opc = IsUnsigned ? AMDGPU::V_MAD_U64_U32_gfx11_e64
                     : AMDGPU::V_MAD_I64_I32_gfx11_e64;
  else if (UseNoCarry)
    Opc = IsUnsigned ? AMDGPU::V_MAD_NC_U64_U32_e64
                     : AMDGPU::V_MAD_NC_I64_I32_e64;
  else
    Opc = IsUnsigned ? AMDGPU::V_MAD_U64_U32_e64 : AMDGPU::V_MAD_I64_I32_e64;

  if (UseNoCarry)
    I.removeOperand(1);

  I.setDesc(TII.get(Opc));
  I.addOperand(*MF, MachineOperand::CreateImm(0));
  I.addImplicitDefUseOperands(*MF);
  I.getOperand(0).setIsEarlyClobber(true);
  return constrainSelectedInstRegOperands(I, TII, TRI, RBI);
}

// TODO: We should probably legalize these to only using 32-bit results.
bool AMDGPUInstructionSelector::selectG_EXTRACT(MachineInstr &I) const {
  MachineBasicBlock *BB = I.getParent();
  Register DstReg = I.getOperand(0).getReg();
  Register SrcReg = I.getOperand(1).getReg();
  LLT DstTy = MRI->getType(DstReg);
  LLT SrcTy = MRI->getType(SrcReg);
  const unsigned SrcSize = SrcTy.getSizeInBits();
  unsigned DstSize = DstTy.getSizeInBits();

  // TODO: Should handle any multiple of 32 offset.
  unsigned Offset = I.getOperand(2).getImm();
  if (Offset % 32 != 0 || DstSize > 128)
    return false;

  // 16-bit operations really use 32-bit registers.
  // FIXME: Probably should not allow 16-bit G_EXTRACT results.
  if (DstSize == 16)
    DstSize = 32;

  const TargetRegisterClass *DstRC =
    TRI.getConstrainedRegClassForOperand(I.getOperand(0), *MRI);
  if (!DstRC || !RBI.constrainGenericRegister(DstReg, *DstRC, *MRI))
    return false;

  const RegisterBank *SrcBank = RBI.getRegBank(SrcReg, *MRI, TRI);
  const TargetRegisterClass *SrcRC =
      TRI.getRegClassForSizeOnBank(SrcSize, *SrcBank);
  if (!SrcRC)
    return false;
  unsigned SubReg = SIRegisterInfo::getSubRegFromChannel(Offset / 32,
                                                         DstSize / 32);
  SrcRC = TRI.getSubClassWithSubReg(SrcRC, SubReg);
  if (!SrcRC)
    return false;

  SrcReg = constrainOperandRegClass(*MF, TRI, *MRI, TII, RBI, I,
                                    *SrcRC, I.getOperand(1));
  const DebugLoc &DL = I.getDebugLoc();
  BuildMI(*BB, &I, DL, TII.get(TargetOpcode::COPY), DstReg)
    .addReg(SrcReg, 0, SubReg);

  I.eraseFromParent();
  return true;
}

bool AMDGPUInstructionSelector::selectG_MERGE_VALUES(MachineInstr &MI) const {
  MachineBasicBlock *BB = MI.getParent();
  Register DstReg = MI.getOperand(0).getReg();
  LLT DstTy = MRI->getType(DstReg);
  LLT SrcTy = MRI->getType(MI.getOperand(1).getReg());

  const unsigned SrcSize = SrcTy.getSizeInBits();
  if (SrcSize < 32)
    return selectImpl(MI, *CoverageInfo);

  const DebugLoc &DL = MI.getDebugLoc();
  const RegisterBank *DstBank = RBI.getRegBank(DstReg, *MRI, TRI);
  const unsigned DstSize = DstTy.getSizeInBits();
  const TargetRegisterClass *DstRC =
      TRI.getRegClassForSizeOnBank(DstSize, *DstBank);
  if (!DstRC)
    return false;

  ArrayRef<int16_t> SubRegs = TRI.getRegSplitParts(DstRC, SrcSize / 8);
  MachineInstrBuilder MIB =
    BuildMI(*BB, &MI, DL, TII.get(TargetOpcode::REG_SEQUENCE), DstReg);
  for (int I = 0, E = MI.getNumOperands() - 1; I != E; ++I) {
    MachineOperand &Src = MI.getOperand(I + 1);
    MIB.addReg(Src.getReg(), getUndefRegState(Src.isUndef()));
    MIB.addImm(SubRegs[I]);

    const TargetRegisterClass *SrcRC
      = TRI.getConstrainedRegClassForOperand(Src, *MRI);
    if (SrcRC && !RBI.constrainGenericRegister(Src.getReg(), *SrcRC, *MRI))
      return false;
  }

  if (!RBI.constrainGenericRegister(DstReg, *DstRC, *MRI))
    return false;

  MI.eraseFromParent();
  return true;
}

bool AMDGPUInstructionSelector::selectG_UNMERGE_VALUES(MachineInstr &MI) const {
  MachineBasicBlock *BB = MI.getParent();
  const int NumDst = MI.getNumOperands() - 1;

  MachineOperand &Src = MI.getOperand(NumDst);

  Register SrcReg = Src.getReg();
  Register DstReg0 = MI.getOperand(0).getReg();
  LLT DstTy = MRI->getType(DstReg0);
  LLT SrcTy = MRI->getType(SrcReg);

  const unsigned DstSize = DstTy.getSizeInBits();
  const unsigned SrcSize = SrcTy.getSizeInBits();
  const DebugLoc &DL = MI.getDebugLoc();
  const RegisterBank *SrcBank = RBI.getRegBank(SrcReg, *MRI, TRI);

  const TargetRegisterClass *SrcRC =
      TRI.getRegClassForSizeOnBank(SrcSize, *SrcBank);
  if (!SrcRC || !RBI.constrainGenericRegister(SrcReg, *SrcRC, *MRI))
    return false;

  // Note we could have mixed SGPR and VGPR destination banks for an SGPR
  // source, and this relies on the fact that the same subregister indices are
  // used for both.
  ArrayRef<int16_t> SubRegs = TRI.getRegSplitParts(SrcRC, DstSize / 8);
  for (int I = 0, E = NumDst; I != E; ++I) {
    MachineOperand &Dst = MI.getOperand(I);
    BuildMI(*BB, &MI, DL, TII.get(TargetOpcode::COPY), Dst.getReg())
      .addReg(SrcReg, 0, SubRegs[I]);

    // Make sure the subregister index is valid for the source register.
    SrcRC = TRI.getSubClassWithSubReg(SrcRC, SubRegs[I]);
    if (!SrcRC || !RBI.constrainGenericRegister(SrcReg, *SrcRC, *MRI))
      return false;

    const TargetRegisterClass *DstRC =
      TRI.getConstrainedRegClassForOperand(Dst, *MRI);
    if (DstRC && !RBI.constrainGenericRegister(Dst.getReg(), *DstRC, *MRI))
      return false;
  }

  MI.eraseFromParent();
  return true;
}

bool AMDGPUInstructionSelector::selectG_BUILD_VECTOR(MachineInstr &MI) const {
  assert(MI.getOpcode() == AMDGPU::G_BUILD_VECTOR_TRUNC ||
         MI.getOpcode() == AMDGPU::G_BUILD_VECTOR);

  Register Src0 = MI.getOperand(1).getReg();
  Register Src1 = MI.getOperand(2).getReg();
  LLT SrcTy = MRI->getType(Src0);
  const unsigned SrcSize = SrcTy.getSizeInBits();

  // BUILD_VECTOR with >=32 bits source is handled by MERGE_VALUE.
  if (MI.getOpcode() == AMDGPU::G_BUILD_VECTOR && SrcSize >= 32) {
    return selectG_MERGE_VALUES(MI);
  }

  // Selection logic below is for V2S16 only.
  // For G_BUILD_VECTOR_TRUNC, additionally check that the operands are s32.
  Register Dst = MI.getOperand(0).getReg();
  if (MRI->getType(Dst) != LLT::fixed_vector(2, 16) ||
      (MI.getOpcode() == AMDGPU::G_BUILD_VECTOR_TRUNC &&
       SrcTy != LLT::scalar(32)))
    return selectImpl(MI, *CoverageInfo);

  const RegisterBank *DstBank = RBI.getRegBank(Dst, *MRI, TRI);
  if (DstBank->getID() == AMDGPU::AGPRRegBankID)
    return false;

  assert(DstBank->getID() == AMDGPU::SGPRRegBankID ||
         DstBank->getID() == AMDGPU::VGPRRegBankID);
  const bool IsVector = DstBank->getID() == AMDGPU::VGPRRegBankID;

  const DebugLoc &DL = MI.getDebugLoc();
  MachineBasicBlock *BB = MI.getParent();

  // First, before trying TableGen patterns, check if both sources are
  // constants. In those cases, we can trivially compute the final constant
  // and emit a simple move.
  auto ConstSrc1 = getAnyConstantVRegValWithLookThrough(Src1, *MRI, true, true);
  if (ConstSrc1) {
    auto ConstSrc0 =
        getAnyConstantVRegValWithLookThrough(Src0, *MRI, true, true);
    if (ConstSrc0) {
      const int64_t K0 = ConstSrc0->Value.getSExtValue();
      const int64_t K1 = ConstSrc1->Value.getSExtValue();
      uint32_t Lo16 = static_cast<uint32_t>(K0) & 0xffff;
      uint32_t Hi16 = static_cast<uint32_t>(K1) & 0xffff;
      uint32_t Imm = Lo16 | (Hi16 << 16);

      // VALU
      if (IsVector) {
        BuildMI(*BB, &MI, DL, TII.get(AMDGPU::V_MOV_B32_e32), Dst).addImm(Imm);
        MI.eraseFromParent();
        return RBI.constrainGenericRegister(Dst, AMDGPU::VGPR_32RegClass, *MRI);
      }

      // SALU
      BuildMI(*BB, &MI, DL, TII.get(AMDGPU::S_MOV_B32), Dst).addImm(Imm);
      MI.eraseFromParent();
      return RBI.constrainGenericRegister(Dst, AMDGPU::SReg_32RegClass, *MRI);
    }
  }

  // Now try TableGen patterns.
  if (selectImpl(MI, *CoverageInfo))
    return true;

  // TODO: This should probably be a combine somewhere
  // (build_vector $src0, undef) -> copy $src0
  MachineInstr *Src1Def = getDefIgnoringCopies(Src1, *MRI);
  if (Src1Def->getOpcode() == AMDGPU::G_IMPLICIT_DEF) {
    MI.setDesc(TII.get(AMDGPU::COPY));
    MI.removeOperand(2);
    const auto &RC =
        IsVector ? AMDGPU::VGPR_32RegClass : AMDGPU::SReg_32RegClass;
    return RBI.constrainGenericRegister(Dst, RC, *MRI) &&
           RBI.constrainGenericRegister(Src0, RC, *MRI);
  }

  // TODO: Can be improved?
  if (IsVector) {
    Register TmpReg = MRI->createVirtualRegister(&AMDGPU::VGPR_32RegClass);
    auto MIB = BuildMI(*BB, MI, DL, TII.get(AMDGPU::V_AND_B32_e32), TmpReg)
                   .addImm(0xFFFF)
                   .addReg(Src0);
    if (!constrainSelectedInstRegOperands(*MIB, TII, TRI, RBI))
      return false;

    MIB = BuildMI(*BB, MI, DL, TII.get(AMDGPU::V_LSHL_OR_B32_e64), Dst)
              .addReg(Src1)
              .addImm(16)
              .addReg(TmpReg);
    if (!constrainSelectedInstRegOperands(*MIB, TII, TRI, RBI))
      return false;

    MI.eraseFromParent();
    return true;
  }

  Register ShiftSrc0;
  Register ShiftSrc1;

  // With multiple uses of the shift, this will duplicate the shift and
  // increase register pressure.
  //
  // (build_vector (lshr_oneuse $src0, 16), (lshr_oneuse $src1, 16)
  //  => (S_PACK_HH_B32_B16 $src0, $src1)
  // (build_vector (lshr_oneuse SReg_32:$src0, 16), $src1)
  //  => (S_PACK_HL_B32_B16 $src0, $src1)
  // (build_vector $src0, (lshr_oneuse SReg_32:$src1, 16))
  //  => (S_PACK_LH_B32_B16 $src0, $src1)
  // (build_vector $src0, $src1)
  //  => (S_PACK_LL_B32_B16 $src0, $src1)

  bool Shift0 = mi_match(
      Src0, *MRI, m_OneUse(m_GLShr(m_Reg(ShiftSrc0), m_SpecificICst(16))));

  bool Shift1 = mi_match(
      Src1, *MRI, m_OneUse(m_GLShr(m_Reg(ShiftSrc1), m_SpecificICst(16))));

  unsigned Opc = AMDGPU::S_PACK_LL_B32_B16;
  if (Shift0 && Shift1) {
    Opc = AMDGPU::S_PACK_HH_B32_B16;
    MI.getOperand(1).setReg(ShiftSrc0);
    MI.getOperand(2).setReg(ShiftSrc1);
  } else if (Shift1) {
    Opc = AMDGPU::S_PACK_LH_B32_B16;
    MI.getOperand(2).setReg(ShiftSrc1);
  } else if (Shift0) {
    auto ConstSrc1 =
        getAnyConstantVRegValWithLookThrough(Src1, *MRI, true, true);
    if (ConstSrc1 && ConstSrc1->Value == 0) {
      // build_vector_trunc (lshr $src0, 16), 0 -> s_lshr_b32 $src0, 16
      auto MIB = BuildMI(*BB, &MI, DL, TII.get(AMDGPU::S_LSHR_B32), Dst)
                     .addReg(ShiftSrc0)
                     .addImm(16)
                     .setOperandDead(3); // Dead scc

      MI.eraseFromParent();
      return constrainSelectedInstRegOperands(*MIB, TII, TRI, RBI);
    }
    if (STI.hasSPackHL()) {
      Opc = AMDGPU::S_PACK_HL_B32_B16;
      MI.getOperand(1).setReg(ShiftSrc0);
    }
  }

  MI.setDesc(TII.get(Opc));
  return constrainSelectedInstRegOperands(MI, TII, TRI, RBI);
}

bool AMDGPUInstructionSelector::selectG_IMPLICIT_DEF(MachineInstr &I) const {
  const MachineOperand &MO = I.getOperand(0);

  // FIXME: Interface for getConstrainedRegClassForOperand needs work. The
  // regbank check here is to know why getConstrainedRegClassForOperand failed.
  const TargetRegisterClass *RC = TRI.getConstrainedRegClassForOperand(MO, *MRI);
  if ((!RC && !MRI->getRegBankOrNull(MO.getReg())) ||
      (RC && RBI.constrainGenericRegister(MO.getReg(), *RC, *MRI))) {
    I.setDesc(TII.get(TargetOpcode::IMPLICIT_DEF));
    return true;
  }

  return false;
}

bool AMDGPUInstructionSelector::selectG_INSERT(MachineInstr &I) const {
  MachineBasicBlock *BB = I.getParent();

  Register DstReg = I.getOperand(0).getReg();
  Register Src0Reg = I.getOperand(1).getReg();
  Register Src1Reg = I.getOperand(2).getReg();
  LLT Src1Ty = MRI->getType(Src1Reg);

  unsigned DstSize = MRI->getType(DstReg).getSizeInBits();
  unsigned InsSize = Src1Ty.getSizeInBits();

  int64_t Offset = I.getOperand(3).getImm();

  // FIXME: These cases should have been illegal and unnecessary to check here.
  if (Offset % 32 != 0 || InsSize % 32 != 0)
    return false;

  // Currently not handled by getSubRegFromChannel.
  if (InsSize > 128)
    return false;

  unsigned SubReg = TRI.getSubRegFromChannel(Offset / 32, InsSize / 32);
  if (SubReg == AMDGPU::NoSubRegister)
    return false;

  const RegisterBank *DstBank = RBI.getRegBank(DstReg, *MRI, TRI);
  const TargetRegisterClass *DstRC =
      TRI.getRegClassForSizeOnBank(DstSize, *DstBank);
  if (!DstRC)
    return false;

  const RegisterBank *Src0Bank = RBI.getRegBank(Src0Reg, *MRI, TRI);
  const RegisterBank *Src1Bank = RBI.getRegBank(Src1Reg, *MRI, TRI);
  const TargetRegisterClass *Src0RC =
      TRI.getRegClassForSizeOnBank(DstSize, *Src0Bank);
  const TargetRegisterClass *Src1RC =
      TRI.getRegClassForSizeOnBank(InsSize, *Src1Bank);

  // Deal with weird cases where the class only partially supports the subreg
  // index.
  Src0RC = TRI.getSubClassWithSubReg(Src0RC, SubReg);
  if (!Src0RC || !Src1RC)
    return false;

  if (!RBI.constrainGenericRegister(DstReg, *DstRC, *MRI) ||
      !RBI.constrainGenericRegister(Src0Reg, *Src0RC, *MRI) ||
      !RBI.constrainGenericRegister(Src1Reg, *Src1RC, *MRI))
    return false;

  const DebugLoc &DL = I.getDebugLoc();
  BuildMI(*BB, &I, DL, TII.get(TargetOpcode::INSERT_SUBREG), DstReg)
    .addReg(Src0Reg)
    .addReg(Src1Reg)
    .addImm(SubReg);

  I.eraseFromParent();
  return true;
}

bool AMDGPUInstructionSelector::selectG_SBFX_UBFX(MachineInstr &MI) const {
  Register DstReg = MI.getOperand(0).getReg();
  Register SrcReg = MI.getOperand(1).getReg();
  Register OffsetReg = MI.getOperand(2).getReg();
  Register WidthReg = MI.getOperand(3).getReg();

  assert(RBI.getRegBank(DstReg, *MRI, TRI)->getID() == AMDGPU::VGPRRegBankID &&
         "scalar BFX instructions are expanded in regbankselect");
  assert(MRI->getType(MI.getOperand(0).getReg()).getSizeInBits() == 32 &&
         "64-bit vector BFX instructions are expanded in regbankselect");

  const DebugLoc &DL = MI.getDebugLoc();
  MachineBasicBlock *MBB = MI.getParent();

  bool IsSigned = MI.getOpcode() == TargetOpcode::G_SBFX;
  unsigned Opc = IsSigned ? AMDGPU::V_BFE_I32_e64 : AMDGPU::V_BFE_U32_e64;
  auto MIB = BuildMI(*MBB, &MI, DL, TII.get(Opc), DstReg)
                 .addReg(SrcReg)
                 .addReg(OffsetReg)
                 .addReg(WidthReg);
  MI.eraseFromParent();
  return constrainSelectedInstRegOperands(*MIB, TII, TRI, RBI);
}

bool AMDGPUInstructionSelector::selectInterpP1F16(MachineInstr &MI) const {
  if (STI.getLDSBankCount() != 16)
    return selectImpl(MI, *CoverageInfo);

  Register Dst = MI.getOperand(0).getReg();
  Register Src0 = MI.getOperand(2).getReg();
  Register M0Val = MI.getOperand(6).getReg();
  if (!RBI.constrainGenericRegister(M0Val, AMDGPU::SReg_32RegClass, *MRI) ||
      !RBI.constrainGenericRegister(Dst, AMDGPU::VGPR_32RegClass, *MRI) ||
      !RBI.constrainGenericRegister(Src0, AMDGPU::VGPR_32RegClass, *MRI))
    return false;

  // This requires 2 instructions. It is possible to write a pattern to support
  // this, but the generated isel emitter doesn't correctly deal with multiple
  // output instructions using the same physical register input. The copy to m0
  // is incorrectly placed before the second instruction.
  //
  // TODO: Match source modifiers.

  Register InterpMov = MRI->createVirtualRegister(&AMDGPU::VGPR_32RegClass);
  const DebugLoc &DL = MI.getDebugLoc();
  MachineBasicBlock *MBB = MI.getParent();

  BuildMI(*MBB, &MI, DL, TII.get(AMDGPU::COPY), AMDGPU::M0)
    .addReg(M0Val);
  BuildMI(*MBB, &MI, DL, TII.get(AMDGPU::V_INTERP_MOV_F32), InterpMov)
    .addImm(2)
    .addImm(MI.getOperand(4).getImm())  // $attr
    .addImm(MI.getOperand(3).getImm()); // $attrchan

  BuildMI(*MBB, &MI, DL, TII.get(AMDGPU::V_INTERP_P1LV_F16), Dst)
    .addImm(0)                          // $src0_modifiers
    .addReg(Src0)                       // $src0
    .addImm(MI.getOperand(4).getImm())  // $attr
    .addImm(MI.getOperand(3).getImm())  // $attrchan
    .addImm(0)                          // $src2_modifiers
    .addReg(InterpMov)                  // $src2 - 2 f16 values selected by high
    .addImm(MI.getOperand(5).getImm())  // $high
    .addImm(0)                          // $clamp
    .addImm(0);                         // $omod

  MI.eraseFromParent();
  return true;
}

// Writelane is special in that it can use SGPR and M0 (which would normally
// count as using the constant bus twice - but in this case it is allowed since
// the lane selector doesn't count as a use of the constant bus). However, it is
// still required to abide by the 1 SGPR rule. Fix this up if we might have
// multiple SGPRs.
bool AMDGPUInstructionSelector::selectWritelane(MachineInstr &MI) const {
  // With a constant bus limit of at least 2, there's no issue.
  if (STI.getConstantBusLimit(AMDGPU::V_WRITELANE_B32) > 1)
    return selectImpl(MI, *CoverageInfo);

  MachineBasicBlock *MBB = MI.getParent();
  const DebugLoc &DL = MI.getDebugLoc();
  Register VDst = MI.getOperand(0).getReg();
  Register Val = MI.getOperand(2).getReg();
  Register LaneSelect = MI.getOperand(3).getReg();
  Register VDstIn = MI.getOperand(4).getReg();

  auto MIB = BuildMI(*MBB, &MI, DL, TII.get(AMDGPU::V_WRITELANE_B32), VDst);

  std::optional<ValueAndVReg> ConstSelect =
      getIConstantVRegValWithLookThrough(LaneSelect, *MRI);
  if (ConstSelect) {
    // The selector has to be an inline immediate, so we can use whatever for
    // the other operands.
    MIB.addReg(Val);
    MIB.addImm(ConstSelect->Value.getSExtValue() &
               maskTrailingOnes<uint64_t>(STI.getWavefrontSizeLog2()));
  } else {
    std::optional<ValueAndVReg> ConstVal =
        getIConstantVRegValWithLookThrough(Val, *MRI);

    // If the value written is an inline immediate, we can get away without a
    // copy to m0.
    if (ConstVal && AMDGPU::isInlinableLiteral32(ConstVal->Value.getSExtValue(),
                                                 STI.hasInv2PiInlineImm())) {
      MIB.addImm(ConstVal->Value.getSExtValue());
      MIB.addReg(LaneSelect);
    } else {
      MIB.addReg(Val);

      // If the lane selector was originally in a VGPR and copied with
      // readfirstlane, there's a hazard to read the same SGPR from the
      // VALU. Constrain to a different SGPR to help avoid needing a nop later.
      RBI.constrainGenericRegister(LaneSelect, AMDGPU::SReg_32_XM0RegClass, *MRI);

      BuildMI(*MBB, *MIB, DL, TII.get(AMDGPU::COPY), AMDGPU::M0)
        .addReg(LaneSelect);
      MIB.addReg(AMDGPU::M0);
    }
  }

  MIB.addReg(VDstIn);

  MI.eraseFromParent();
  return constrainSelectedInstRegOperands(*MIB, TII, TRI, RBI);
}

// We need to handle this here because tablegen doesn't support matching
// instructions with multiple outputs.
bool AMDGPUInstructionSelector::selectDivScale(MachineInstr &MI) const {
  Register Dst0 = MI.getOperand(0).getReg();
  Register Dst1 = MI.getOperand(1).getReg();

  LLT Ty = MRI->getType(Dst0);
  unsigned Opc;
  if (Ty == LLT::scalar(32))
    Opc = AMDGPU::V_DIV_SCALE_F32_e64;
  else if (Ty == LLT::scalar(64))
    Opc = AMDGPU::V_DIV_SCALE_F64_e64;
  else
    return false;

  // TODO: Match source modifiers.

  const DebugLoc &DL = MI.getDebugLoc();
  MachineBasicBlock *MBB = MI.getParent();

  Register Numer = MI.getOperand(3).getReg();
  Register Denom = MI.getOperand(4).getReg();
  unsigned ChooseDenom = MI.getOperand(5).getImm();

  Register Src0 = ChooseDenom != 0 ? Numer : Denom;

  auto MIB = BuildMI(*MBB, &MI, DL, TII.get(Opc), Dst0)
    .addDef(Dst1)
    .addImm(0)     // $src0_modifiers
    .addUse(Src0)  // $src0
    .addImm(0)     // $src1_modifiers
    .addUse(Denom) // $src1
    .addImm(0)     // $src2_modifiers
    .addUse(Numer) // $src2
    .addImm(0)     // $clamp
    .addImm(0);    // $omod

  MI.eraseFromParent();
  return constrainSelectedInstRegOperands(*MIB, TII, TRI, RBI);
}

bool AMDGPUInstructionSelector::selectG_INTRINSIC(MachineInstr &I) const {
  Intrinsic::ID IntrinsicID = cast<GIntrinsic>(I).getIntrinsicID();
  switch (IntrinsicID) {
  case Intrinsic::amdgcn_if_break: {
    MachineBasicBlock *BB = I.getParent();

    // FIXME: Manually selecting to avoid dealing with the SReg_1 trick
    // SelectionDAG uses for wave32 vs wave64.
    BuildMI(*BB, &I, I.getDebugLoc(), TII.get(AMDGPU::SI_IF_BREAK))
      .add(I.getOperand(0))
      .add(I.getOperand(2))
      .add(I.getOperand(3));

    Register DstReg = I.getOperand(0).getReg();
    Register Src0Reg = I.getOperand(2).getReg();
    Register Src1Reg = I.getOperand(3).getReg();

    I.eraseFromParent();

    for (Register Reg : { DstReg, Src0Reg, Src1Reg })
      MRI->setRegClass(Reg, TRI.getWaveMaskRegClass());

    return true;
  }
  case Intrinsic::amdgcn_interp_p1_f16:
    return selectInterpP1F16(I);
  case Intrinsic::amdgcn_wqm:
    return constrainCopyLikeIntrin(I, AMDGPU::WQM);
  case Intrinsic::amdgcn_softwqm:
    return constrainCopyLikeIntrin(I, AMDGPU::SOFT_WQM);
  case Intrinsic::amdgcn_strict_wwm:
  case Intrinsic::amdgcn_wwm:
    return constrainCopyLikeIntrin(I, AMDGPU::STRICT_WWM);
  case Intrinsic::amdgcn_strict_wqm:
    return constrainCopyLikeIntrin(I, AMDGPU::STRICT_WQM);
  case Intrinsic::amdgcn_writelane:
    return selectWritelane(I);
  case Intrinsic::amdgcn_div_scale:
    return selectDivScale(I);
  case Intrinsic::amdgcn_icmp:
  case Intrinsic::amdgcn_fcmp:
    if (selectImpl(I, *CoverageInfo))
      return true;
    return selectIntrinsicCmp(I);
  case Intrinsic::amdgcn_ballot:
    return selectBallot(I);
  case Intrinsic::amdgcn_reloc_constant:
    return selectRelocConstant(I);
  case Intrinsic::amdgcn_groupstaticsize:
    return selectGroupStaticSize(I);
  case Intrinsic::returnaddress:
    return selectReturnAddress(I);
  case Intrinsic::amdgcn_smfmac_f32_16x16x32_f16:
  case Intrinsic::amdgcn_smfmac_f32_32x32x16_f16:
  case Intrinsic::amdgcn_smfmac_f32_16x16x32_bf16:
  case Intrinsic::amdgcn_smfmac_f32_32x32x16_bf16:
  case Intrinsic::amdgcn_smfmac_i32_16x16x64_i8:
  case Intrinsic::amdgcn_smfmac_i32_32x32x32_i8:
  case Intrinsic::amdgcn_smfmac_f32_16x16x64_bf8_bf8:
  case Intrinsic::amdgcn_smfmac_f32_16x16x64_bf8_fp8:
  case Intrinsic::amdgcn_smfmac_f32_16x16x64_fp8_bf8:
  case Intrinsic::amdgcn_smfmac_f32_16x16x64_fp8_fp8:
  case Intrinsic::amdgcn_smfmac_f32_32x32x32_bf8_bf8:
  case Intrinsic::amdgcn_smfmac_f32_32x32x32_bf8_fp8:
  case Intrinsic::amdgcn_smfmac_f32_32x32x32_fp8_bf8:
  case Intrinsic::amdgcn_smfmac_f32_32x32x32_fp8_fp8:
  case Intrinsic::amdgcn_smfmac_f32_16x16x64_f16:
  case Intrinsic::amdgcn_smfmac_f32_32x32x32_f16:
  case Intrinsic::amdgcn_smfmac_f32_16x16x64_bf16:
  case Intrinsic::amdgcn_smfmac_f32_32x32x32_bf16:
  case Intrinsic::amdgcn_smfmac_i32_16x16x128_i8:
  case Intrinsic::amdgcn_smfmac_i32_32x32x64_i8:
  case Intrinsic::amdgcn_smfmac_f32_16x16x128_bf8_bf8:
  case Intrinsic::amdgcn_smfmac_f32_16x16x128_bf8_fp8:
  case Intrinsic::amdgcn_smfmac_f32_16x16x128_fp8_bf8:
  case Intrinsic::amdgcn_smfmac_f32_16x16x128_fp8_fp8:
  case Intrinsic::amdgcn_smfmac_f32_32x32x64_bf8_bf8:
  case Intrinsic::amdgcn_smfmac_f32_32x32x64_bf8_fp8:
  case Intrinsic::amdgcn_smfmac_f32_32x32x64_fp8_bf8:
  case Intrinsic::amdgcn_smfmac_f32_32x32x64_fp8_fp8:
    return selectSMFMACIntrin(I);
  case Intrinsic::amdgcn_permlane16_swap:
  case Intrinsic::amdgcn_permlane32_swap:
    return selectPermlaneSwapIntrin(I, IntrinsicID);
  case Intrinsic::amdgcn_wave_shuffle:
    return selectWaveShuffleIntrin(I);
  default:
    return selectImpl(I, *CoverageInfo);
  }
}

static int getV_CMPOpcode(CmpInst::Predicate P, unsigned Size,
                          const GCNSubtarget &ST) {
  if (Size != 16 && Size != 32 && Size != 64)
    return -1;

  if (Size == 16 && !ST.has16BitInsts())
    return -1;

  const auto Select = [&](unsigned S16Opc, unsigned TrueS16Opc,
                          unsigned FakeS16Opc, unsigned S32Opc,
                          unsigned S64Opc) {
    if (Size == 16)
      return ST.hasTrue16BitInsts()
                 ? ST.useRealTrue16Insts() ? TrueS16Opc : FakeS16Opc
                 : S16Opc;
    if (Size == 32)
      return S32Opc;
    return S64Opc;
  };

  switch (P) {
  default:
    llvm_unreachable("Unknown condition code!");
  case CmpInst::ICMP_NE:
    return Select(AMDGPU::V_CMP_NE_U16_e64, AMDGPU::V_CMP_NE_U16_t16_e64,
                  AMDGPU::V_CMP_NE_U16_fake16_e64, AMDGPU::V_CMP_NE_U32_e64,
                  AMDGPU::V_CMP_NE_U64_e64);
  case CmpInst::ICMP_EQ:
    return Select(AMDGPU::V_CMP_EQ_U16_e64, AMDGPU::V_CMP_EQ_U16_t16_e64,
                  AMDGPU::V_CMP_EQ_U16_fake16_e64, AMDGPU::V_CMP_EQ_U32_e64,
                  AMDGPU::V_CMP_EQ_U64_e64);
  case CmpInst::ICMP_SGT:
    return Select(AMDGPU::V_CMP_GT_I16_e64, AMDGPU::V_CMP_GT_I16_t16_e64,
                  AMDGPU::V_CMP_GT_I16_fake16_e64, AMDGPU::V_CMP_GT_I32_e64,
                  AMDGPU::V_CMP_GT_I64_e64);
  case CmpInst::ICMP_SGE:
    return Select(AMDGPU::V_CMP_GE_I16_e64, AMDGPU::V_CMP_GE_I16_t16_e64,
                  AMDGPU::V_CMP_GE_I16_fake16_e64, AMDGPU::V_CMP_GE_I32_e64,
                  AMDGPU::V_CMP_GE_I64_e64);
  case CmpInst::ICMP_SLT:
    return Select(AMDGPU::V_CMP_LT_I16_e64, AMDGPU::V_CMP_LT_I16_t16_e64,
                  AMDGPU::V_CMP_LT_I16_fake16_e64, AMDGPU::V_CMP_LT_I32_e64,
                  AMDGPU::V_CMP_LT_I64_e64);
  case CmpInst::ICMP_SLE:
    return Select(AMDGPU::V_CMP_LE_I16_e64, AMDGPU::V_CMP_LE_I16_t16_e64,
                  AMDGPU::V_CMP_LE_I16_fake16_e64, AMDGPU::V_CMP_LE_I32_e64,
                  AMDGPU::V_CMP_LE_I64_e64);
  case CmpInst::ICMP_UGT:
    return Select(AMDGPU::V_CMP_GT_U16_e64, AMDGPU::V_CMP_GT_U16_t16_e64,
                  AMDGPU::V_CMP_GT_U16_fake16_e64, AMDGPU::V_CMP_GT_U32_e64,
                  AMDGPU::V_CMP_GT_U64_e64);
  case CmpInst::ICMP_UGE:
    return Select(AMDGPU::V_CMP_GE_U16_e64, AMDGPU::V_CMP_GE_U16_t16_e64,
                  AMDGPU::V_CMP_GE_U16_fake16_e64, AMDGPU::V_CMP_GE_U32_e64,
                  AMDGPU::V_CMP_GE_U64_e64);
  case CmpInst::ICMP_ULT:
    return Select(AMDGPU::V_CMP_LT_U16_e64, AMDGPU::V_CMP_LT_U16_t16_e64,
                  AMDGPU::V_CMP_LT_U16_fake16_e64, AMDGPU::V_CMP_LT_U32_e64,
                  AMDGPU::V_CMP_LT_U64_e64);
  case CmpInst::ICMP_ULE:
    return Select(AMDGPU::V_CMP_LE_U16_e64, AMDGPU::V_CMP_LE_U16_t16_e64,
                  AMDGPU::V_CMP_LE_U16_fake16_e64, AMDGPU::V_CMP_LE_U32_e64,
                  AMDGPU::V_CMP_LE_U64_e64);

  case CmpInst::FCMP_OEQ:
    return Select(AMDGPU::V_CMP_EQ_F16_e64, AMDGPU::V_CMP_EQ_F16_t16_e64,
                  AMDGPU::V_CMP_EQ_F16_fake16_e64, AMDGPU::V_CMP_EQ_F32_e64,
                  AMDGPU::V_CMP_EQ_F64_e64);
  case CmpInst::FCMP_OGT:
    return Select(AMDGPU::V_CMP_GT_F16_e64, AMDGPU::V_CMP_GT_F16_t16_e64,
                  AMDGPU::V_CMP_GT_F16_fake16_e64, AMDGPU::V_CMP_GT_F32_e64,
                  AMDGPU::V_CMP_GT_F64_e64);
  case CmpInst::FCMP_OGE:
    return Select(AMDGPU::V_CMP_GE_F16_e64, AMDGPU::V_CMP_GE_F16_t16_e64,
                  AMDGPU::V_CMP_GE_F16_fake16_e64, AMDGPU::V_CMP_GE_F32_e64,
                  AMDGPU::V_CMP_GE_F64_e64);
  case CmpInst::FCMP_OLT:
    return Select(AMDGPU::V_CMP_LT_F16_e64, AMDGPU::V_CMP_LT_F16_t16_e64,
                  AMDGPU::V_CMP_LT_F16_fake16_e64, AMDGPU::V_CMP_LT_F32_e64,
                  AMDGPU::V_CMP_LT_F64_e64);
  case CmpInst::FCMP_OLE:
    return Select(AMDGPU::V_CMP_LE_F16_e64, AMDGPU::V_CMP_LE_F16_t16_e64,
                  AMDGPU::V_CMP_LE_F16_fake16_e64, AMDGPU::V_CMP_LE_F32_e64,
                  AMDGPU::V_CMP_LE_F64_e64);
  case CmpInst::FCMP_ONE:
    return Select(AMDGPU::V_CMP_NEQ_F16_e64, AMDGPU::V_CMP_NEQ_F16_t16_e64,
                  AMDGPU::V_CMP_NEQ_F16_fake16_e64, AMDGPU::V_CMP_NEQ_F32_e64,
                  AMDGPU::V_CMP_NEQ_F64_e64);
  case CmpInst::FCMP_ORD:
    return Select(AMDGPU::V_CMP_O_F16_e64, AMDGPU::V_CMP_O_F16_t16_e64,
                  AMDGPU::V_CMP_O_F16_fake16_e64, AMDGPU::V_CMP_O_F32_e64,
                  AMDGPU::V_CMP_O_F64_e64);
  case CmpInst::FCMP_UNO:
    return Select(AMDGPU::V_CMP_U_F16_e64, AMDGPU::V_CMP_U_F16_t16_e64,
                  AMDGPU::V_CMP_U_F16_fake16_e64, AMDGPU::V_CMP_U_F32_e64,
                  AMDGPU::V_CMP_U_F64_e64);
  case CmpInst::FCMP_UEQ:
    return Select(AMDGPU::V_CMP_NLG_F16_e64, AMDGPU::V_CMP_NLG_F16_t16_e64,
                  AMDGPU::V_CMP_NLG_F16_fake16_e64, AMDGPU::V_CMP_NLG_F32_e64,
                  AMDGPU::V_CMP_NLG_F64_e64);
  case CmpInst::FCMP_UGT:
    return Select(AMDGPU::V_CMP_NLE_F16_e64, AMDGPU::V_CMP_NLE_F16_t16_e64,
                  AMDGPU::V_CMP_NLE_F16_fake16_e64, AMDGPU::V_CMP_NLE_F32_e64,
                  AMDGPU::V_CMP_NLE_F64_e64);
  case CmpInst::FCMP_UGE:
    return Select(AMDGPU::V_CMP_NLT_F16_e64, AMDGPU::V_CMP_NLT_F16_t16_e64,
                  AMDGPU::V_CMP_NLT_F16_fake16_e64, AMDGPU::V_CMP_NLT_F32_e64,
                  AMDGPU::V_CMP_NLT_F64_e64);
  case CmpInst::FCMP_ULT:
    return Select(AMDGPU::V_CMP_NGE_F16_e64, AMDGPU::V_CMP_NGE_F16_t16_e64,
                  AMDGPU::V_CMP_NGE_F16_fake16_e64, AMDGPU::V_CMP_NGE_F32_e64,
                  AMDGPU::V_CMP_NGE_F64_e64);
  case CmpInst::FCMP_ULE:
    return Select(AMDGPU::V_CMP_NGT_F16_e64, AMDGPU::V_CMP_NGT_F16_t16_e64,
                  AMDGPU::V_CMP_NGT_F16_fake16_e64, AMDGPU::V_CMP_NGT_F32_e64,
                  AMDGPU::V_CMP_NGT_F64_e64);
  case CmpInst::FCMP_UNE:
    return Select(AMDGPU::V_CMP_NEQ_F16_e64, AMDGPU::V_CMP_NEQ_F16_t16_e64,
                  AMDGPU::V_CMP_NEQ_F16_fake16_e64, AMDGPU::V_CMP_NEQ_F32_e64,
                  AMDGPU::V_CMP_NEQ_F64_e64);
  case CmpInst::FCMP_TRUE:
    return Select(AMDGPU::V_CMP_TRU_F16_e64, AMDGPU::V_CMP_TRU_F16_t16_e64,
                  AMDGPU::V_CMP_TRU_F16_fake16_e64, AMDGPU::V_CMP_TRU_F32_e64,
                  AMDGPU::V_CMP_TRU_F64_e64);
  case CmpInst::FCMP_FALSE:
    return Select(AMDGPU::V_CMP_F_F16_e64, AMDGPU::V_CMP_F_F16_t16_e64,
                  AMDGPU::V_CMP_F_F16_fake16_e64, AMDGPU::V_CMP_F_F32_e64,
                  AMDGPU::V_CMP_F_F64_e64);
  }
}

int AMDGPUInstructionSelector::getS_CMPOpcode(CmpInst::Predicate P,
                                              unsigned Size) const {
  if (Size == 64) {
    if (!STI.hasScalarCompareEq64())
      return -1;

    switch (P) {
    case CmpInst::ICMP_NE:
      return AMDGPU::S_CMP_LG_U64;
    case CmpInst::ICMP_EQ:
      return AMDGPU::S_CMP_EQ_U64;
    default:
      return -1;
    }
  }

  if (Size == 32) {
    switch (P) {
    case CmpInst::ICMP_NE:
      return AMDGPU::S_CMP_LG_U32;
    case CmpInst::ICMP_EQ:
      return AMDGPU::S_CMP_EQ_U32;
    case CmpInst::ICMP_SGT:
      return AMDGPU::S_CMP_GT_I32;
    case CmpInst::ICMP_SGE:
      return AMDGPU::S_CMP_GE_I32;
    case CmpInst::ICMP_SLT:
      return AMDGPU::S_CMP_LT_I32;
    case CmpInst::ICMP_SLE:
      return AMDGPU::S_CMP_LE_I32;
    case CmpInst::ICMP_UGT:
      return AMDGPU::S_CMP_GT_U32;
    case CmpInst::ICMP_UGE:
      return AMDGPU::S_CMP_GE_U32;
    case CmpInst::ICMP_ULT:
      return AMDGPU::S_CMP_LT_U32;
    case CmpInst::ICMP_ULE:
      return AMDGPU::S_CMP_LE_U32;
    case CmpInst::FCMP_OEQ:
      return AMDGPU::S_CMP_EQ_F32;
    case CmpInst::FCMP_OGT:
      return AMDGPU::S_CMP_GT_F32;
    case CmpInst::FCMP_OGE:
      return AMDGPU::S_CMP_GE_F32;
    case CmpInst::FCMP_OLT:
      return AMDGPU::S_CMP_LT_F32;
    case CmpInst::FCMP_OLE:
      return AMDGPU::S_CMP_LE_F32;
    case CmpInst::FCMP_ONE:
      return AMDGPU::S_CMP_LG_F32;
    case CmpInst::FCMP_ORD:
      return AMDGPU::S_CMP_O_F32;
    case CmpInst::FCMP_UNO:
      return AMDGPU::S_CMP_U_F32;
    case CmpInst::FCMP_UEQ:
      return AMDGPU::S_CMP_NLG_F32;
    case CmpInst::FCMP_UGT:
      return AMDGPU::S_CMP_NLE_F32;
    case CmpInst::FCMP_UGE:
      return AMDGPU::S_CMP_NLT_F32;
    case CmpInst::FCMP_ULT:
      return AMDGPU::S_CMP_NGE_F32;
    case CmpInst::FCMP_ULE:
      return AMDGPU::S_CMP_NGT_F32;
    case CmpInst::FCMP_UNE:
      return AMDGPU::S_CMP_NEQ_F32;
    default:
      llvm_unreachable("Unknown condition code!");
    }
  }

  if (Size == 16) {
    if (!STI.hasSALUFloatInsts())
      return -1;

    switch (P) {
    case CmpInst::FCMP_OEQ:
      return AMDGPU::S_CMP_EQ_F16;
    case CmpInst::FCMP_OGT:
      return AMDGPU::S_CMP_GT_F16;
    case CmpInst::FCMP_OGE:
      return AMDGPU::S_CMP_GE_F16;
    case CmpInst::FCMP_OLT:
      return AMDGPU::S_CMP_LT_F16;
    case CmpInst::FCMP_OLE:
      return AMDGPU::S_CMP_LE_F16;
    case CmpInst::FCMP_ONE:
      return AMDGPU::S_CMP_LG_F16;
    case CmpInst::FCMP_ORD:
      return AMDGPU::S_CMP_O_F16;
    case CmpInst::FCMP_UNO:
      return AMDGPU::S_CMP_U_F16;
    case CmpInst::FCMP_UEQ:
      return AMDGPU::S_CMP_NLG_F16;
    case CmpInst::FCMP_UGT:
      return AMDGPU::S_CMP_NLE_F16;
    case CmpInst::FCMP_UGE:
      return AMDGPU::S_CMP_NLT_F16;
    case CmpInst::FCMP_ULT:
      return AMDGPU::S_CMP_NGE_F16;
    case CmpInst::FCMP_ULE:
      return AMDGPU::S_CMP_NGT_F16;
    case CmpInst::FCMP_UNE:
      return AMDGPU::S_CMP_NEQ_F16;
    default:
      llvm_unreachable("Unknown condition code!");
    }
  }

  return -1;
}

bool AMDGPUInstructionSelector::selectG_ICMP_or_FCMP(MachineInstr &I) const {

  MachineBasicBlock *BB = I.getParent();
  const DebugLoc &DL = I.getDebugLoc();

  Register SrcReg = I.getOperand(2).getReg();
  unsigned Size = RBI.getSizeInBits(SrcReg, *MRI, TRI);

  auto Pred = (CmpInst::Predicate)I.getOperand(1).getPredicate();

  Register CCReg = I.getOperand(0).getReg();
  if (!isVCC(CCReg, *MRI)) {
    int Opcode = getS_CMPOpcode(Pred, Size);
    if (Opcode == -1)
      return false;
    MachineInstr *ICmp = BuildMI(*BB, &I, DL, TII.get(Opcode))
            .add(I.getOperand(2))
            .add(I.getOperand(3));
    BuildMI(*BB, &I, DL, TII.get(AMDGPU::COPY), CCReg)
      .addReg(AMDGPU::SCC);
    bool Ret =
        constrainSelectedInstRegOperands(*ICmp, TII, TRI, RBI) &&
        RBI.constrainGenericRegister(CCReg, AMDGPU::SReg_32RegClass, *MRI);
    I.eraseFromParent();
    return Ret;
  }

  if (I.getOpcode() == AMDGPU::G_FCMP)
    return false;

  int Opcode = getV_CMPOpcode(Pred, Size, *Subtarget);
  if (Opcode == -1)
    return false;

  MachineInstrBuilder ICmp;
  // t16 instructions
  if (AMDGPU::hasNamedOperand(Opcode, AMDGPU::OpName::src0_modifiers)) {
    ICmp = BuildMI(*BB, &I, DL, TII.get(Opcode), I.getOperand(0).getReg())
               .addImm(0)
               .add(I.getOperand(2))
               .addImm(0)
               .add(I.getOperand(3))
               .addImm(0); // op_sel
  } else {
    ICmp = BuildMI(*BB, &I, DL, TII.get(Opcode), I.getOperand(0).getReg())
               .add(I.getOperand(2))
               .add(I.getOperand(3));
  }

  RBI.constrainGenericRegister(ICmp->getOperand(0).getReg(),
                               *TRI.getBoolRC(), *MRI);
  bool Ret = constrainSelectedInstRegOperands(*ICmp, TII, TRI, RBI);
  I.eraseFromParent();
  return Ret;
}

bool AMDGPUInstructionSelector::selectIntrinsicCmp(MachineInstr &I) const {
  Register Dst = I.getOperand(0).getReg();
  if (isVCC(Dst, *MRI))
    return false;

  LLT DstTy = MRI->getType(Dst);
  if (DstTy.getSizeInBits() != STI.getWavefrontSize())
    return false;

  MachineBasicBlock *BB = I.getParent();
  const DebugLoc &DL = I.getDebugLoc();
  Register SrcReg = I.getOperand(2).getReg();
  unsigned Size = RBI.getSizeInBits(SrcReg, *MRI, TRI);

  // i1 inputs are not supported in GlobalISel.
  if (Size == 1)
    return false;

  auto Pred = static_cast<CmpInst::Predicate>(I.getOperand(4).getImm());
  if (!CmpInst::isIntPredicate(Pred) && !CmpInst::isFPPredicate(Pred)) {
    BuildMI(*BB, &I, DL, TII.get(AMDGPU::IMPLICIT_DEF), Dst);
    I.eraseFromParent();
    return RBI.constrainGenericRegister(Dst, *TRI.getBoolRC(), *MRI);
  }

  const int Opcode = getV_CMPOpcode(Pred, Size, *Subtarget);
  if (Opcode == -1)
    return false;

  MachineInstrBuilder SelectedMI;
  MachineOperand &LHS = I.getOperand(2);
  MachineOperand &RHS = I.getOperand(3);
  auto [Src0, Src0Mods] = selectVOP3ModsImpl(LHS.getReg());
  auto [Src1, Src1Mods] = selectVOP3ModsImpl(RHS.getReg());
  Register Src0Reg =
      copyToVGPRIfSrcFolded(Src0, Src0Mods, LHS, &I, /*ForceVGPR*/ true);
  Register Src1Reg =
      copyToVGPRIfSrcFolded(Src1, Src1Mods, RHS, &I, /*ForceVGPR*/ true);
  SelectedMI = BuildMI(*BB, &I, DL, TII.get(Opcode), Dst);
  if (AMDGPU::hasNamedOperand(Opcode, AMDGPU::OpName::src0_modifiers))
    SelectedMI.addImm(Src0Mods);
  SelectedMI.addReg(Src0Reg);
  if (AMDGPU::hasNamedOperand(Opcode, AMDGPU::OpName::src1_modifiers))
    SelectedMI.addImm(Src1Mods);
  SelectedMI.addReg(Src1Reg);
  if (AMDGPU::hasNamedOperand(Opcode, AMDGPU::OpName::clamp))
    SelectedMI.addImm(0); // clamp
  if (AMDGPU::hasNamedOperand(Opcode, AMDGPU::OpName::op_sel))
    SelectedMI.addImm(0); // op_sel

  RBI.constrainGenericRegister(Dst, *TRI.getBoolRC(), *MRI);
  if (!constrainSelectedInstRegOperands(*SelectedMI, TII, TRI, RBI))
    return false;

  I.eraseFromParent();
  return true;
}

// Ballot has to zero bits in input lane-mask that are zero in current exec,
// Done as AND with exec. For inputs that are results of instruction that
// implicitly use same exec, for example compares in same basic block or SCC to
// VCC copy, use copy.
static bool isLaneMaskFromSameBlock(Register Reg, MachineRegisterInfo &MRI,
                                    MachineBasicBlock *MBB) {
  MachineInstr *MI = MRI.getVRegDef(Reg);
  if (MI->getParent() != MBB)
    return false;

  // Lane mask generated by SCC to VCC copy.
  if (MI->getOpcode() == AMDGPU::COPY) {
    auto DstRB = MRI.getRegBankOrNull(MI->getOperand(0).getReg());
    auto SrcRB = MRI.getRegBankOrNull(MI->getOperand(1).getReg());
    if (DstRB && SrcRB && DstRB->getID() == AMDGPU::VCCRegBankID &&
        SrcRB->getID() == AMDGPU::SGPRRegBankID)
      return true;
  }

  // Lane mask generated using compare with same exec.
  if (isa<GAnyCmp>(MI))
    return true;

  Register LHS, RHS;
  // Look through AND.
  if (mi_match(Reg, MRI, m_GAnd(m_Reg(LHS), m_Reg(RHS))))
    return isLaneMaskFromSameBlock(LHS, MRI, MBB) ||
           isLaneMaskFromSameBlock(RHS, MRI, MBB);

  return false;
}

bool AMDGPUInstructionSelector::selectBallot(MachineInstr &I) const {
  MachineBasicBlock *BB = I.getParent();
  const DebugLoc &DL = I.getDebugLoc();
  Register DstReg = I.getOperand(0).getReg();
  Register SrcReg = I.getOperand(2).getReg();
  const unsigned BallotSize = MRI->getType(DstReg).getSizeInBits();
  const unsigned WaveSize = STI.getWavefrontSize();

  // In the common case, the return type matches the wave size.
  // However we also support emitting i64 ballots in wave32 mode.
  if (BallotSize != WaveSize && (BallotSize != 64 || WaveSize != 32))
    return false;

  std::optional<ValueAndVReg> Arg =
      getIConstantVRegValWithLookThrough(SrcReg, *MRI);

  Register Dst = DstReg;
  // i64 ballot on Wave32: new Dst(i32) for WaveSize ballot.
  if (BallotSize != WaveSize) {
    Dst = MRI->createVirtualRegister(TRI.getBoolRC());
  }

  if (Arg) {
    const int64_t Value = Arg->Value.getZExtValue();
    if (Value == 0) {
      // Dst = S_MOV 0
      unsigned Opcode = WaveSize == 64 ? AMDGPU::S_MOV_B64 : AMDGPU::S_MOV_B32;
      BuildMI(*BB, &I, DL, TII.get(Opcode), Dst).addImm(0);
    } else {
      // Dst = COPY EXEC
      assert(Value == 1);
      BuildMI(*BB, &I, DL, TII.get(AMDGPU::COPY), Dst).addReg(TRI.getExec());
    }
    if (!RBI.constrainGenericRegister(Dst, *TRI.getBoolRC(), *MRI))
      return false;
  } else {
    if (isLaneMaskFromSameBlock(SrcReg, *MRI, BB)) {
      // Dst = COPY SrcReg
      BuildMI(*BB, &I, DL, TII.get(AMDGPU::COPY), Dst).addReg(SrcReg);
      if (!RBI.constrainGenericRegister(Dst, *TRI.getBoolRC(), *MRI))
        return false;
    } else {
      // Dst = S_AND SrcReg, EXEC
      unsigned AndOpc = WaveSize == 64 ? AMDGPU::S_AND_B64 : AMDGPU::S_AND_B32;
      auto And = BuildMI(*BB, &I, DL, TII.get(AndOpc), Dst)
                     .addReg(SrcReg)
                     .addReg(TRI.getExec())
                     .setOperandDead(3); // Dead scc
      if (!constrainSelectedInstRegOperands(*And, TII, TRI, RBI))
        return false;
    }
  }

  // i64 ballot on Wave32: zero-extend i32 ballot to i64.
  if (BallotSize != WaveSize) {
    Register HiReg = MRI->createVirtualRegister(&AMDGPU::SReg_32RegClass);
    BuildMI(*BB, &I, DL, TII.get(AMDGPU::S_MOV_B32), HiReg).addImm(0);
    BuildMI(*BB, &I, DL, TII.get(AMDGPU::REG_SEQUENCE), DstReg)
        .addReg(Dst)
        .addImm(AMDGPU::sub0)
        .addReg(HiReg)
        .addImm(AMDGPU::sub1);
  }

  I.eraseFromParent();
  return true;
}

bool AMDGPUInstructionSelector::selectRelocConstant(MachineInstr &I) const {
  Register DstReg = I.getOperand(0).getReg();
  const RegisterBank *DstBank = RBI.getRegBank(DstReg, *MRI, TRI);
  const TargetRegisterClass *DstRC = TRI.getRegClassForSizeOnBank(32, *DstBank);
  if (!DstRC || !RBI.constrainGenericRegister(DstReg, *DstRC, *MRI))
    return false;

  const bool IsVALU = DstBank->getID() == AMDGPU::VGPRRegBankID;

  Module *M = MF->getFunction().getParent();
  const MDNode *Metadata = I.getOperand(2).getMetadata();
  auto SymbolName = cast<MDString>(Metadata->getOperand(0))->getString();
  auto *RelocSymbol = cast<GlobalVariable>(
      M->getOrInsertGlobal(SymbolName, Type::getInt32Ty(M->getContext())));

  MachineBasicBlock *BB = I.getParent();
  BuildMI(*BB, &I, I.getDebugLoc(),
          TII.get(IsVALU ? AMDGPU::V_MOV_B32_e32 : AMDGPU::S_MOV_B32), DstReg)
    .addGlobalAddress(RelocSymbol, 0, SIInstrInfo::MO_ABS32_LO);

  I.eraseFromParent();
  return true;
}

bool AMDGPUInstructionSelector::selectGroupStaticSize(MachineInstr &I) const {
  Triple::OSType OS = MF->getTarget().getTargetTriple().getOS();

  Register DstReg = I.getOperand(0).getReg();
  const RegisterBank *DstRB = RBI.getRegBank(DstReg, *MRI, TRI);
  unsigned Mov = DstRB->getID() == AMDGPU::SGPRRegBankID ?
    AMDGPU::S_MOV_B32 : AMDGPU::V_MOV_B32_e32;

  MachineBasicBlock *MBB = I.getParent();
  const DebugLoc &DL = I.getDebugLoc();

  auto MIB = BuildMI(*MBB, &I, DL, TII.get(Mov), DstReg);

  if (OS == Triple::AMDHSA || OS == Triple::AMDPAL) {
    const SIMachineFunctionInfo *MFI = MF->getInfo<SIMachineFunctionInfo>();
    MIB.addImm(MFI->getLDSSize());
  } else {
    Module *M = MF->getFunction().getParent();
    const GlobalValue *GV =
        Intrinsic::getOrInsertDeclaration(M, Intrinsic::amdgcn_groupstaticsize);
    MIB.addGlobalAddress(GV, 0, SIInstrInfo::MO_ABS32_LO);
  }

  I.eraseFromParent();
  return constrainSelectedInstRegOperands(*MIB, TII, TRI, RBI);
}

bool AMDGPUInstructionSelector::selectReturnAddress(MachineInstr &I) const {
  MachineBasicBlock *MBB = I.getParent();
  MachineFunction &MF = *MBB->getParent();
  const DebugLoc &DL = I.getDebugLoc();

  MachineOperand &Dst = I.getOperand(0);
  Register DstReg = Dst.getReg();
  unsigned Depth = I.getOperand(2).getImm();

  const TargetRegisterClass *RC
    = TRI.getConstrainedRegClassForOperand(Dst, *MRI);
  if (!RC->hasSubClassEq(&AMDGPU::SGPR_64RegClass) ||
      !RBI.constrainGenericRegister(DstReg, *RC, *MRI))
    return false;

  // Check for kernel and shader functions
  if (Depth != 0 ||
      MF.getInfo<SIMachineFunctionInfo>()->isEntryFunction()) {
    BuildMI(*MBB, &I, DL, TII.get(AMDGPU::S_MOV_B64), DstReg)
      .addImm(0);
    I.eraseFromParent();
    return true;
  }

  MachineFrameInfo &MFI = MF.getFrameInfo();
  // There is a call to @llvm.returnaddress in this function
  MFI.setReturnAddressIsTaken(true);

  // Get the return address reg and mark it as an implicit live-in
  Register ReturnAddrReg = TRI.getReturnAddressReg(MF);
  Register LiveIn = getFunctionLiveInPhysReg(MF, TII, ReturnAddrReg,
                                             AMDGPU::SReg_64RegClass, DL);
  BuildMI(*MBB, &I, DL, TII.get(AMDGPU::COPY), DstReg)
    .addReg(LiveIn);
  I.eraseFromParent();
  return true;
}

bool AMDGPUInstructionSelector::selectEndCfIntrinsic(MachineInstr &MI) const {
  // FIXME: Manually selecting to avoid dealing with the SReg_1 trick
  // SelectionDAG uses for wave32 vs wave64.
  MachineBasicBlock *BB = MI.getParent();
  BuildMI(*BB, &MI, MI.getDebugLoc(), TII.get(AMDGPU::SI_END_CF))
      .add(MI.getOperand(1));

  Register Reg = MI.getOperand(1).getReg();
  MI.eraseFromParent();

  if (!MRI->getRegClassOrNull(Reg))
    MRI->setRegClass(Reg, TRI.getWaveMaskRegClass());
  return true;
}

bool AMDGPUInstructionSelector::selectDSOrderedIntrinsic(
  MachineInstr &MI, Intrinsic::ID IntrID) const {
  MachineBasicBlock *MBB = MI.getParent();
  MachineFunction *MF = MBB->getParent();
  const DebugLoc &DL = MI.getDebugLoc();

  unsigned IndexOperand = MI.getOperand(7).getImm();
  bool WaveRelease = MI.getOperand(8).getImm() != 0;
  bool WaveDone = MI.getOperand(9).getImm() != 0;

  if (WaveDone && !WaveRelease) {
    // TODO: Move this to IR verifier
    const Function &Fn = MF->getFunction();
    Fn.getContext().diagnose(DiagnosticInfoUnsupported(
        Fn, "ds_ordered_count: wave_done requires wave_release", DL));
  }

  unsigned OrderedCountIndex = IndexOperand & 0x3f;
  IndexOperand &= ~0x3f;
  unsigned CountDw = 0;

  if (STI.getGeneration() >= AMDGPUSubtarget::GFX10) {
    CountDw = (IndexOperand >> 24) & 0xf;
    IndexOperand &= ~(0xf << 24);

    if (CountDw < 1 || CountDw > 4) {
      const Function &Fn = MF->getFunction();
      Fn.getContext().diagnose(DiagnosticInfoUnsupported(
          Fn, "ds_ordered_count: dword count must be between 1 and 4", DL));
      CountDw = 1;
    }
  }

  if (IndexOperand) {
    const Function &Fn = MF->getFunction();
    Fn.getContext().diagnose(DiagnosticInfoUnsupported(
        Fn, "ds_ordered_count: bad index operand", DL));
  }

  unsigned Instruction = IntrID == Intrinsic::amdgcn_ds_ordered_add ? 0 : 1;
  unsigned ShaderType = SIInstrInfo::getDSShaderTypeValue(*MF);

  unsigned Offset0 = OrderedCountIndex << 2;
  unsigned Offset1 = WaveRelease | (WaveDone << 1) | (Instruction << 4);

  if (STI.getGeneration() >= AMDGPUSubtarget::GFX10)
    Offset1 |= (CountDw - 1) << 6;

  if (STI.getGeneration() < AMDGPUSubtarget::GFX11)
    Offset1 |= ShaderType << 2;

  unsigned Offset = Offset0 | (Offset1 << 8);

  Register M0Val = MI.getOperand(2).getReg();
  BuildMI(*MBB, &MI, DL, TII.get(AMDGPU::COPY), AMDGPU::M0)
    .addReg(M0Val);

  Register DstReg = MI.getOperand(0).getReg();
  Register ValReg = MI.getOperand(3).getReg();
  MachineInstrBuilder DS =
    BuildMI(*MBB, &MI, DL, TII.get(AMDGPU::DS_ORDERED_COUNT), DstReg)
      .addReg(ValReg)
      .addImm(Offset)
      .cloneMemRefs(MI);

  if (!RBI.constrainGenericRegister(M0Val, AMDGPU::SReg_32RegClass, *MRI))
    return false;

  bool Ret = constrainSelectedInstRegOperands(*DS, TII, TRI, RBI);
  MI.eraseFromParent();
  return Ret;
}

static unsigned gwsIntrinToOpcode(unsigned IntrID) {
  switch (IntrID) {
  case Intrinsic::amdgcn_ds_gws_init:
    return AMDGPU::DS_GWS_INIT;
  case Intrinsic::amdgcn_ds_gws_barrier:
    return AMDGPU::DS_GWS_BARRIER;
  case Intrinsic::amdgcn_ds_gws_sema_v:
    return AMDGPU::DS_GWS_SEMA_V;
  case Intrinsic::amdgcn_ds_gws_sema_br:
    return AMDGPU::DS_GWS_SEMA_BR;
  case Intrinsic::amdgcn_ds_gws_sema_p:
    return AMDGPU::DS_GWS_SEMA_P;
  case Intrinsic::amdgcn_ds_gws_sema_release_all:
    return AMDGPU::DS_GWS_SEMA_RELEASE_ALL;
  default:
    llvm_unreachable("not a gws intrinsic");
  }
}

bool AMDGPUInstructionSelector::selectDSGWSIntrinsic(MachineInstr &MI,
                                                     Intrinsic::ID IID) const {
  if (!STI.hasGWS() || (IID == Intrinsic::amdgcn_ds_gws_sema_release_all &&
                        !STI.hasGWSSemaReleaseAll()))
    return false;

  // intrinsic ID, vsrc, offset
  const bool HasVSrc = MI.getNumOperands() == 3;
  assert(HasVSrc || MI.getNumOperands() == 2);

  Register BaseOffset = MI.getOperand(HasVSrc ? 2 : 1).getReg();
  const RegisterBank *OffsetRB = RBI.getRegBank(BaseOffset, *MRI, TRI);
  if (OffsetRB->getID() != AMDGPU::SGPRRegBankID)
    return false;

  MachineInstr *OffsetDef = getDefIgnoringCopies(BaseOffset, *MRI);
  unsigned ImmOffset;

  MachineBasicBlock *MBB = MI.getParent();
  const DebugLoc &DL = MI.getDebugLoc();

  MachineInstr *Readfirstlane = nullptr;

  // If we legalized the VGPR input, strip out the readfirstlane to analyze the
  // incoming offset, in case there's an add of a constant. We'll have to put it
  // back later.
  if (OffsetDef->getOpcode() == AMDGPU::V_READFIRSTLANE_B32) {
    Readfirstlane = OffsetDef;
    BaseOffset = OffsetDef->getOperand(1).getReg();
    OffsetDef = getDefIgnoringCopies(BaseOffset, *MRI);
  }

  if (OffsetDef->getOpcode() == AMDGPU::G_CONSTANT) {
    // If we have a constant offset, try to use the 0 in m0 as the base.
    // TODO: Look into changing the default m0 initialization value. If the
    // default -1 only set the low 16-bits, we could leave it as-is and add 1 to
    // the immediate offset.

    ImmOffset = OffsetDef->getOperand(1).getCImm()->getZExtValue();
    BuildMI(*MBB, &MI, DL, TII.get(AMDGPU::S_MOV_B32), AMDGPU::M0)
      .addImm(0);
  } else {
    std::tie(BaseOffset, ImmOffset) =
        AMDGPU::getBaseWithConstantOffset(*MRI, BaseOffset, VT);

    if (Readfirstlane) {
      // We have the constant offset now, so put the readfirstlane back on the
      // variable component.
      if (!RBI.constrainGenericRegister(BaseOffset, AMDGPU::VGPR_32RegClass, *MRI))
        return false;

      Readfirstlane->getOperand(1).setReg(BaseOffset);
      BaseOffset = Readfirstlane->getOperand(0).getReg();
    } else {
      if (!RBI.constrainGenericRegister(BaseOffset,
                                        AMDGPU::SReg_32RegClass, *MRI))
        return false;
    }

    Register M0Base = MRI->createVirtualRegister(&AMDGPU::SReg_32RegClass);
    BuildMI(*MBB, &MI, DL, TII.get(AMDGPU::S_LSHL_B32), M0Base)
      .addReg(BaseOffset)
      .addImm(16)
      .setOperandDead(3); // Dead scc

    BuildMI(*MBB, &MI, DL, TII.get(AMDGPU::COPY), AMDGPU::M0)
      .addReg(M0Base);
  }

  // The resource id offset is computed as (<isa opaque base> + M0[21:16] +
  // offset field) % 64. Some versions of the programming guide omit the m0
  // part, or claim it's from offset 0.

  unsigned Opc = gwsIntrinToOpcode(IID);
  const MCInstrDesc &InstrDesc = TII.get(Opc);

  if (HasVSrc) {
    Register VSrc = MI.getOperand(1).getReg();

    int Data0Idx = AMDGPU::getNamedOperandIdx(Opc, AMDGPU::OpName::data0);
    const TargetRegisterClass *DataRC = TII.getRegClass(InstrDesc, Data0Idx);
    const TargetRegisterClass *SubRC =
        TRI.getSubRegisterClass(DataRC, AMDGPU::sub0);

    if (!SubRC) {
      // 32-bit normal case.
      if (!RBI.constrainGenericRegister(VSrc, *DataRC, *MRI))
        return false;

      BuildMI(*MBB, &MI, DL, InstrDesc)
        .addReg(VSrc)
        .addImm(ImmOffset)
        .cloneMemRefs(MI);
    } else {
      // Requires even register alignment, so create 64-bit value and pad the
      // top half with undef.
      Register DataReg = MRI->createVirtualRegister(DataRC);
      if (!RBI.constrainGenericRegister(VSrc, *SubRC, *MRI))
        return false;

      Register UndefReg = MRI->createVirtualRegister(SubRC);
      BuildMI(*MBB, &MI, DL, TII.get(AMDGPU::IMPLICIT_DEF), UndefReg);
      BuildMI(*MBB, &MI, DL, TII.get(AMDGPU::REG_SEQUENCE), DataReg)
        .addReg(VSrc)
        .addImm(AMDGPU::sub0)
        .addReg(UndefReg)
        .addImm(AMDGPU::sub1);

      BuildMI(*MBB, &MI, DL, InstrDesc)
        .addReg(DataReg)
        .addImm(ImmOffset)
        .cloneMemRefs(MI);
    }
  } else {
    BuildMI(*MBB, &MI, DL, InstrDesc)
      .addImm(ImmOffset)
      .cloneMemRefs(MI);
  }

  MI.eraseFromParent();
  return true;
}

bool AMDGPUInstructionSelector::selectDSAppendConsume(MachineInstr &MI,
                                                      bool IsAppend) const {
  Register PtrBase = MI.getOperand(2).getReg();
  LLT PtrTy = MRI->getType(PtrBase);
  bool IsGDS = PtrTy.getAddressSpace() == AMDGPUAS::REGION_ADDRESS;

  unsigned Offset;
  std::tie(PtrBase, Offset) = selectDS1Addr1OffsetImpl(MI.getOperand(2));

  // TODO: Should this try to look through readfirstlane like GWS?
  if (!isDSOffsetLegal(PtrBase, Offset)) {
    PtrBase = MI.getOperand(2).getReg();
    Offset = 0;
  }

  MachineBasicBlock *MBB = MI.getParent();
  const DebugLoc &DL = MI.getDebugLoc();
  const unsigned Opc = IsAppend ? AMDGPU::DS_APPEND : AMDGPU::DS_CONSUME;

  BuildMI(*MBB, &MI, DL, TII.get(AMDGPU::COPY), AMDGPU::M0)
    .addReg(PtrBase);
  if (!RBI.constrainGenericRegister(PtrBase, AMDGPU::SReg_32RegClass, *MRI))
    return false;

  auto MIB = BuildMI(*MBB, &MI, DL, TII.get(Opc), MI.getOperand(0).getReg())
    .addImm(Offset)
    .addImm(IsGDS ? -1 : 0)
    .cloneMemRefs(MI);
  MI.eraseFromParent();
  return constrainSelectedInstRegOperands(*MIB, TII, TRI, RBI);
}

bool AMDGPUInstructionSelector::selectInitWholeWave(MachineInstr &MI) const {
  MachineFunction *MF = MI.getMF();
  SIMachineFunctionInfo *MFInfo = MF->getInfo<SIMachineFunctionInfo>();

  MFInfo->setInitWholeWave();
  return selectImpl(MI, *CoverageInfo);
}

static bool parseTexFail(uint64_t TexFailCtrl, bool &TFE, bool &LWE,
                         bool &IsTexFail) {
  if (TexFailCtrl)
    IsTexFail = true;

  TFE = TexFailCtrl & 0x1;
  TexFailCtrl &= ~(uint64_t)0x1;
  LWE = TexFailCtrl & 0x2;
  TexFailCtrl &= ~(uint64_t)0x2;

  return TexFailCtrl == 0;
}

bool AMDGPUInstructionSelector::selectImageIntrinsic(
  MachineInstr &MI, const AMDGPU::ImageDimIntrinsicInfo *Intr) const {
  MachineBasicBlock *MBB = MI.getParent();
  const DebugLoc &DL = MI.getDebugLoc();
  unsigned IntrOpcode = Intr->BaseOpcode;

  // For image atomic: use no-return opcode if result is unused.
  if (Intr->AtomicNoRetBaseOpcode != Intr->BaseOpcode) {
    Register ResultDef = MI.getOperand(0).getReg();
    if (MRI->use_nodbg_empty(ResultDef))
      IntrOpcode = Intr->AtomicNoRetBaseOpcode;
  }

  const AMDGPU::MIMGBaseOpcodeInfo *BaseOpcode =
      AMDGPU::getMIMGBaseOpcodeInfo(IntrOpcode);

  const AMDGPU::MIMGDimInfo *DimInfo = AMDGPU::getMIMGDimInfo(Intr->Dim);
  const bool IsGFX10Plus = AMDGPU::isGFX10Plus(STI);
  const bool IsGFX11Plus = AMDGPU::isGFX11Plus(STI);
  const bool IsGFX12Plus = AMDGPU::isGFX12Plus(STI);

  const unsigned ArgOffset = MI.getNumExplicitDefs() + 1;

  Register VDataIn = AMDGPU::NoRegister;
  Register VDataOut = AMDGPU::NoRegister;
  LLT VDataTy;
  int NumVDataDwords = -1;
  bool IsD16 = MI.getOpcode() == AMDGPU::G_AMDGPU_INTRIN_IMAGE_LOAD_D16 ||
               MI.getOpcode() == AMDGPU::G_AMDGPU_INTRIN_IMAGE_STORE_D16;

  bool Unorm;
  if (!BaseOpcode->Sampler)
    Unorm = true;
  else
    Unorm = MI.getOperand(ArgOffset + Intr->UnormIndex).getImm() != 0;

  bool TFE;
  bool LWE;
  bool IsTexFail = false;
  if (!parseTexFail(MI.getOperand(ArgOffset + Intr->TexFailCtrlIndex).getImm(),
                    TFE, LWE, IsTexFail))
    return false;

  const int Flags = MI.getOperand(ArgOffset + Intr->NumArgs).getImm();
  const bool IsA16 = (Flags & 1) != 0;
  const bool IsG16 = (Flags & 2) != 0;

  // A16 implies 16 bit gradients if subtarget doesn't support G16
  if (IsA16 && !STI.hasG16() && !IsG16)
    return false;

  unsigned DMask = 0;
  unsigned DMaskLanes = 0;

  if (BaseOpcode->Atomic) {
    if (!BaseOpcode->NoReturn)
      VDataOut = MI.getOperand(0).getReg();
    VDataIn = MI.getOperand(2).getReg();
    LLT Ty = MRI->getType(VDataIn);

    // Be careful to allow atomic swap on 16-bit element vectors.
    const bool Is64Bit = BaseOpcode->AtomicX2 ?
      Ty.getSizeInBits() == 128 :
      Ty.getSizeInBits() == 64;

    if (BaseOpcode->AtomicX2) {
      assert(MI.getOperand(3).getReg() == AMDGPU::NoRegister);

      DMask = Is64Bit ? 0xf : 0x3;
      NumVDataDwords = Is64Bit ? 4 : 2;
    } else {
      DMask = Is64Bit ? 0x3 : 0x1;
      NumVDataDwords = Is64Bit ? 2 : 1;
    }
  } else {
    DMask = MI.getOperand(ArgOffset + Intr->DMaskIndex).getImm();
    DMaskLanes = BaseOpcode->Gather4 ? 4 : llvm::popcount(DMask);

    if (BaseOpcode->Store) {
      VDataIn = MI.getOperand(1).getReg();
      VDataTy = MRI->getType(VDataIn);
      NumVDataDwords = (VDataTy.getSizeInBits() + 31) / 32;
    } else if (BaseOpcode->NoReturn) {
      NumVDataDwords = 0;
    } else {
      VDataOut = MI.getOperand(0).getReg();
      VDataTy = MRI->getType(VDataOut);
      NumVDataDwords = DMaskLanes;

      if (IsD16 && !STI.hasUnpackedD16VMem())
        NumVDataDwords = (DMaskLanes + 1) / 2;
    }
  }

  // Set G16 opcode
  if (Subtarget->hasG16() && IsG16) {
    const AMDGPU::MIMGG16MappingInfo *G16MappingInfo =
        AMDGPU::getMIMGG16MappingInfo(Intr->BaseOpcode);
    assert(G16MappingInfo);
    IntrOpcode = G16MappingInfo->G16; // set opcode to variant with _g16
  }

  // TODO: Check this in verifier.
  assert((!IsTexFail || DMaskLanes >= 1) && "should have legalized this");

  unsigned CPol = MI.getOperand(ArgOffset + Intr->CachePolicyIndex).getImm();
  // Keep GLC only when the atomic's result is actually used.
  if (BaseOpcode->Atomic && !BaseOpcode->NoReturn)
    CPol |= AMDGPU::CPol::GLC;
  if (CPol & ~((IsGFX12Plus ? AMDGPU::CPol::ALL : AMDGPU::CPol::ALL_pregfx12) |
               AMDGPU::CPol::VOLATILE))
    return false;

  int NumVAddrRegs = 0;
  int NumVAddrDwords = 0;
  for (unsigned I = Intr->VAddrStart; I < Intr->VAddrEnd; I++) {
    // Skip the $noregs and 0s inserted during legalization.
    MachineOperand &AddrOp = MI.getOperand(ArgOffset + I);
    if (!AddrOp.isReg())
      continue; // XXX - Break?

    Register Addr = AddrOp.getReg();
    if (!Addr)
      break;

    ++NumVAddrRegs;
    NumVAddrDwords += (MRI->getType(Addr).getSizeInBits() + 31) / 32;
  }

  // The legalizer preprocessed the intrinsic arguments. If we aren't using
  // NSA, these should have been packed into a single value in the first
  // address register
  const bool UseNSA =
      NumVAddrRegs != 1 &&
      (STI.hasPartialNSAEncoding() ? NumVAddrDwords >= NumVAddrRegs
                                   : NumVAddrDwords == NumVAddrRegs);
  if (UseNSA && !STI.hasFeature(AMDGPU::FeatureNSAEncoding)) {
    LLVM_DEBUG(dbgs() << "Trying to use NSA on non-NSA target\n");
    return false;
  }

  if (IsTexFail)
    ++NumVDataDwords;

  int Opcode = -1;
  if (IsGFX12Plus) {
    Opcode = AMDGPU::getMIMGOpcode(IntrOpcode, AMDGPU::MIMGEncGfx12,
                                   NumVDataDwords, NumVAddrDwords);
  } else if (IsGFX11Plus) {
    Opcode = AMDGPU::getMIMGOpcode(IntrOpcode,
                                   UseNSA ? AMDGPU::MIMGEncGfx11NSA
                                          : AMDGPU::MIMGEncGfx11Default,
                                   NumVDataDwords, NumVAddrDwords);
  } else if (IsGFX10Plus) {
    Opcode = AMDGPU::getMIMGOpcode(IntrOpcode,
                                   UseNSA ? AMDGPU::MIMGEncGfx10NSA
                                          : AMDGPU::MIMGEncGfx10Default,
                                   NumVDataDwords, NumVAddrDwords);
  } else {
    if (Subtarget->hasGFX90AInsts()) {
      Opcode = AMDGPU::getMIMGOpcode(IntrOpcode, AMDGPU::MIMGEncGfx90a,
                                     NumVDataDwords, NumVAddrDwords);
      if (Opcode == -1) {
        LLVM_DEBUG(
            dbgs()
            << "requested image instruction is not supported on this GPU\n");
        return false;
      }
    }
    if (Opcode == -1 &&
        STI.getGeneration() >= AMDGPUSubtarget::VOLCANIC_ISLANDS)
      Opcode = AMDGPU::getMIMGOpcode(IntrOpcode, AMDGPU::MIMGEncGfx8,
                                     NumVDataDwords, NumVAddrDwords);
    if (Opcode == -1)
      Opcode = AMDGPU::getMIMGOpcode(IntrOpcode, AMDGPU::MIMGEncGfx6,
                                     NumVDataDwords, NumVAddrDwords);
  }
  if (Opcode == -1)
    return false;

  auto MIB = BuildMI(*MBB, &MI, DL, TII.get(Opcode))
    .cloneMemRefs(MI);

  if (VDataOut) {
    if (BaseOpcode->AtomicX2) {
      const bool Is64 = MRI->getType(VDataOut).getSizeInBits() == 64;

      Register TmpReg = MRI->createVirtualRegister(
        Is64 ? &AMDGPU::VReg_128RegClass : &AMDGPU::VReg_64RegClass);
      unsigned SubReg = Is64 ? AMDGPU::sub0_sub1 : AMDGPU::sub0;

      MIB.addDef(TmpReg);
      if (!MRI->use_empty(VDataOut)) {
        BuildMI(*MBB, &MI, DL, TII.get(AMDGPU::COPY), VDataOut)
            .addReg(TmpReg, RegState::Kill, SubReg);
      }

    } else {
      MIB.addDef(VDataOut); // vdata output
    }
  }

  if (VDataIn)
    MIB.addReg(VDataIn); // vdata input

  for (int I = 0; I != NumVAddrRegs; ++I) {
    MachineOperand &SrcOp = MI.getOperand(ArgOffset + Intr->VAddrStart + I);
    if (SrcOp.isReg()) {
      assert(SrcOp.getReg() != 0);
      MIB.addReg(SrcOp.getReg());
    }
  }

  MIB.addReg(MI.getOperand(ArgOffset + Intr->RsrcIndex).getReg());
  if (BaseOpcode->Sampler)
    MIB.addReg(MI.getOperand(ArgOffset + Intr->SampIndex).getReg());

  MIB.addImm(DMask); // dmask

  if (IsGFX10Plus)
    MIB.addImm(DimInfo->Encoding);
  if (AMDGPU::hasNamedOperand(Opcode, AMDGPU::OpName::unorm))
    MIB.addImm(Unorm);

  MIB.addImm(CPol);
  MIB.addImm(IsA16 &&  // a16 or r128
             STI.hasFeature(AMDGPU::FeatureR128A16) ? -1 : 0);
  if (IsGFX10Plus)
    MIB.addImm(IsA16 ? -1 : 0);

  if (!Subtarget->hasGFX90AInsts()) {
    MIB.addImm(TFE); // tfe
  } else if (TFE) {
    LLVM_DEBUG(dbgs() << "TFE is not supported on this GPU\n");
    return false;
  }

  if (AMDGPU::hasNamedOperand(Opcode, AMDGPU::OpName::lwe))
    MIB.addImm(LWE); // lwe
  if (!IsGFX10Plus)
    MIB.addImm(DimInfo->DA ? -1 : 0);
  if (BaseOpcode->HasD16)
    MIB.addImm(IsD16 ? -1 : 0);

  MI.eraseFromParent();
  constrainSelectedInstRegOperands(*MIB, TII, TRI, RBI);
  TII.enforceOperandRCAlignment(*MIB, AMDGPU::OpName::vaddr);
  return true;
}

// We need to handle this here because tablegen doesn't support matching
// instructions with multiple outputs.
bool AMDGPUInstructionSelector::selectDSBvhStackIntrinsic(
    MachineInstr &MI) const {
  Register Dst0 = MI.getOperand(0).getReg();
  Register Dst1 = MI.getOperand(1).getReg();

  const DebugLoc &DL = MI.getDebugLoc();
  MachineBasicBlock *MBB = MI.getParent();

  Register Addr = MI.getOperand(3).getReg();
  Register Data0 = MI.getOperand(4).getReg();
  Register Data1 = MI.getOperand(5).getReg();
  unsigned Offset = MI.getOperand(6).getImm();

  unsigned Opc;
  switch (cast<GIntrinsic>(MI).getIntrinsicID()) {
  case Intrinsic::amdgcn_ds_bvh_stack_rtn:
  case Intrinsic::amdgcn_ds_bvh_stack_push4_pop1_rtn:
    Opc = AMDGPU::DS_BVH_STACK_RTN_B32;
    break;
  case Intrinsic::amdgcn_ds_bvh_stack_push8_pop1_rtn:
    Opc = AMDGPU::DS_BVH_STACK_PUSH8_POP1_RTN_B32;
    break;
  case Intrinsic::amdgcn_ds_bvh_stack_push8_pop2_rtn:
    Opc = AMDGPU::DS_BVH_STACK_PUSH8_POP2_RTN_B64;
    break;
  }

  auto MIB = BuildMI(*MBB, &MI, DL, TII.get(Opc), Dst0)
                 .addDef(Dst1)
                 .addUse(Addr)
                 .addUse(Data0)
                 .addUse(Data1)
                 .addImm(Offset)
                 .cloneMemRefs(MI);

  MI.eraseFromParent();
  return constrainSelectedInstRegOperands(*MIB, TII, TRI, RBI);
}

bool AMDGPUInstructionSelector::selectG_INTRINSIC_W_SIDE_EFFECTS(
    MachineInstr &I) const {
  Intrinsic::ID IntrinsicID = cast<GIntrinsic>(I).getIntrinsicID();
  switch (IntrinsicID) {
  case Intrinsic::amdgcn_end_cf:
    return selectEndCfIntrinsic(I);
  case Intrinsic::amdgcn_ds_ordered_add:
  case Intrinsic::amdgcn_ds_ordered_swap:
    return selectDSOrderedIntrinsic(I, IntrinsicID);
  case Intrinsic::amdgcn_ds_gws_init:
  case Intrinsic::amdgcn_ds_gws_barrier:
  case Intrinsic::amdgcn_ds_gws_sema_v:
  case Intrinsic::amdgcn_ds_gws_sema_br:
  case Intrinsic::amdgcn_ds_gws_sema_p:
  case Intrinsic::amdgcn_ds_gws_sema_release_all:
    return selectDSGWSIntrinsic(I, IntrinsicID);
  case Intrinsic::amdgcn_ds_append:
    return selectDSAppendConsume(I, true);
  case Intrinsic::amdgcn_ds_consume:
    return selectDSAppendConsume(I, false);
  case Intrinsic::amdgcn_init_whole_wave:
    return selectInitWholeWave(I);
  case Intrinsic::amdgcn_raw_buffer_load_lds:
  case Intrinsic::amdgcn_raw_ptr_buffer_load_lds:
  case Intrinsic::amdgcn_struct_buffer_load_lds:
  case Intrinsic::amdgcn_struct_ptr_buffer_load_lds:
    return selectBufferLoadLds(I);
  // Until we can store both the address space of the global and the LDS
  // arguments by having tto MachineMemOperands on an intrinsic, we just trust
  // that the argument is a global pointer (buffer pointers have been handled by
  // a LLVM IR-level lowering).
  case Intrinsic::amdgcn_load_to_lds:
  case Intrinsic::amdgcn_global_load_lds:
    return selectGlobalLoadLds(I);
  case Intrinsic::amdgcn_exp_compr:
    if (!STI.hasCompressedExport()) {
      Function &F = I.getMF()->getFunction();
      F.getContext().diagnose(
          DiagnosticInfoUnsupported(F, "intrinsic not supported on subtarget",
                                    I.getDebugLoc(), DS_Error));
      return false;
    }
    break;
  case Intrinsic::amdgcn_ds_bvh_stack_rtn:
  case Intrinsic::amdgcn_ds_bvh_stack_push4_pop1_rtn:
  case Intrinsic::amdgcn_ds_bvh_stack_push8_pop1_rtn:
  case Intrinsic::amdgcn_ds_bvh_stack_push8_pop2_rtn:
    return selectDSBvhStackIntrinsic(I);
  case Intrinsic::amdgcn_s_barrier_init:
  case Intrinsic::amdgcn_s_barrier_signal_var:
    return selectNamedBarrierInit(I, IntrinsicID);
  case Intrinsic::amdgcn_s_wakeup_barrier: {
    if (!STI.hasSWakeupBarrier()) {
      Function &F = I.getMF()->getFunction();
      F.getContext().diagnose(
          DiagnosticInfoUnsupported(F, "intrinsic not supported on subtarget",
                                    I.getDebugLoc(), DS_Error));
      return false;
    }
    return selectNamedBarrierInst(I, IntrinsicID);
  }
  case Intrinsic::amdgcn_s_barrier_join:
  case Intrinsic::amdgcn_s_get_named_barrier_state:
    return selectNamedBarrierInst(I, IntrinsicID);
  case Intrinsic::amdgcn_s_get_barrier_state:
    return selectSGetBarrierState(I, IntrinsicID);
  case Intrinsic::amdgcn_s_barrier_signal_isfirst:
    return selectSBarrierSignalIsfirst(I, IntrinsicID);
  }
  return selectImpl(I, *CoverageInfo);
}

bool AMDGPUInstructionSelector::selectG_SELECT(MachineInstr &I) const {
  if (selectImpl(I, *CoverageInfo))
    return true;

  MachineBasicBlock *BB = I.getParent();
  const DebugLoc &DL = I.getDebugLoc();

  Register DstReg = I.getOperand(0).getReg();
  unsigned Size = RBI.getSizeInBits(DstReg, *MRI, TRI);
  assert(Size <= 32 || Size == 64);
  const MachineOperand &CCOp = I.getOperand(1);
  Register CCReg = CCOp.getReg();
  if (!isVCC(CCReg, *MRI)) {
    unsigned SelectOpcode = Size == 64 ? AMDGPU::S_CSELECT_B64 :
                                         AMDGPU::S_CSELECT_B32;
    MachineInstr *CopySCC = BuildMI(*BB, &I, DL, TII.get(AMDGPU::COPY), AMDGPU::SCC)
            .addReg(CCReg);

    // The generic constrainSelectedInstRegOperands doesn't work for the scc register
    // bank, because it does not cover the register class that we used to represent
    // for it.  So we need to manually set the register class here.
    if (!MRI->getRegClassOrNull(CCReg))
        MRI->setRegClass(CCReg, TRI.getConstrainedRegClassForOperand(CCOp, *MRI));
    MachineInstr *Select = BuildMI(*BB, &I, DL, TII.get(SelectOpcode), DstReg)
            .add(I.getOperand(2))
            .add(I.getOperand(3));

    bool Ret = false;
    Ret |= constrainSelectedInstRegOperands(*Select, TII, TRI, RBI);
    Ret |= constrainSelectedInstRegOperands(*CopySCC, TII, TRI, RBI);
    I.eraseFromParent();
    return Ret;
  }

  // Wide VGPR select should have been split in RegBankSelect.
  if (Size > 32)
    return false;

  MachineInstr *Select =
      BuildMI(*BB, &I, DL, TII.get(AMDGPU::V_CNDMASK_B32_e64), DstReg)
              .addImm(0)
              .add(I.getOperand(3))
              .addImm(0)
              .add(I.getOperand(2))
              .add(I.getOperand(1));

  bool Ret = constrainSelectedInstRegOperands(*Select, TII, TRI, RBI);
  I.eraseFromParent();
  return Ret;
}

bool AMDGPUInstructionSelector::selectG_TRUNC(MachineInstr &I) const {
  Register DstReg = I.getOperand(0).getReg();
  Register SrcReg = I.getOperand(1).getReg();
  const LLT DstTy = MRI->getType(DstReg);
  const LLT SrcTy = MRI->getType(SrcReg);
  const LLT S1 = LLT::scalar(1);

  const RegisterBank *SrcRB = RBI.getRegBank(SrcReg, *MRI, TRI);
  const RegisterBank *DstRB;
  if (DstTy == S1) {
    // This is a special case. We don't treat s1 for legalization artifacts as
    // vcc booleans.
    DstRB = SrcRB;
  } else {
    DstRB = RBI.getRegBank(DstReg, *MRI, TRI);
    if (SrcRB != DstRB)
      return false;
  }

  const bool IsVALU = DstRB->getID() == AMDGPU::VGPRRegBankID;

  unsigned DstSize = DstTy.getSizeInBits();
  unsigned SrcSize = SrcTy.getSizeInBits();

  const TargetRegisterClass *SrcRC =
      TRI.getRegClassForSizeOnBank(SrcSize, *SrcRB);
  const TargetRegisterClass *DstRC =
      TRI.getRegClassForSizeOnBank(DstSize, *DstRB);
  if (!SrcRC || !DstRC)
    return false;

  if (!RBI.constrainGenericRegister(SrcReg, *SrcRC, *MRI) ||
      !RBI.constrainGenericRegister(DstReg, *DstRC, *MRI)) {
    LLVM_DEBUG(dbgs() << "Failed to constrain G_TRUNC\n");
    return false;
  }

  if (DstRC == &AMDGPU::VGPR_16RegClass && SrcSize == 32) {
    assert(STI.useRealTrue16Insts());
    const DebugLoc &DL = I.getDebugLoc();
    MachineBasicBlock *MBB = I.getParent();
    BuildMI(*MBB, I, DL, TII.get(AMDGPU::COPY), DstReg)
        .addReg(SrcReg, 0, AMDGPU::lo16);
    I.eraseFromParent();
    return true;
  }

  if (DstTy == LLT::fixed_vector(2, 16) && SrcTy == LLT::fixed_vector(2, 32)) {
    MachineBasicBlock *MBB = I.getParent();
    const DebugLoc &DL = I.getDebugLoc();

    Register LoReg = MRI->createVirtualRegister(DstRC);
    Register HiReg = MRI->createVirtualRegister(DstRC);
    BuildMI(*MBB, I, DL, TII.get(AMDGPU::COPY), LoReg)
      .addReg(SrcReg, 0, AMDGPU::sub0);
    BuildMI(*MBB, I, DL, TII.get(AMDGPU::COPY), HiReg)
      .addReg(SrcReg, 0, AMDGPU::sub1);

    if (IsVALU && STI.hasSDWA()) {
      // Write the low 16-bits of the high element into the high 16-bits of the
      // low element.
      MachineInstr *MovSDWA =
        BuildMI(*MBB, I, DL, TII.get(AMDGPU::V_MOV_B32_sdwa), DstReg)
        .addImm(0)                             // $src0_modifiers
        .addReg(HiReg)                         // $src0
        .addImm(0)                             // $clamp
        .addImm(AMDGPU::SDWA::WORD_1)          // $dst_sel
        .addImm(AMDGPU::SDWA::UNUSED_PRESERVE) // $dst_unused
        .addImm(AMDGPU::SDWA::WORD_0)          // $src0_sel
        .addReg(LoReg, RegState::Implicit);
      MovSDWA->tieOperands(0, MovSDWA->getNumOperands() - 1);
    } else {
      Register TmpReg0 = MRI->createVirtualRegister(DstRC);
      Register TmpReg1 = MRI->createVirtualRegister(DstRC);
      Register ImmReg = MRI->createVirtualRegister(DstRC);
      if (IsVALU) {
        BuildMI(*MBB, I, DL, TII.get(AMDGPU::V_LSHLREV_B32_e64), TmpReg0)
          .addImm(16)
          .addReg(HiReg);
      } else {
        BuildMI(*MBB, I, DL, TII.get(AMDGPU::S_LSHL_B32), TmpReg0)
          .addReg(HiReg)
          .addImm(16)
          .setOperandDead(3); // Dead scc
      }

      unsigned MovOpc = IsVALU ? AMDGPU::V_MOV_B32_e32 : AMDGPU::S_MOV_B32;
      unsigned AndOpc = IsVALU ? AMDGPU::V_AND_B32_e64 : AMDGPU::S_AND_B32;
      unsigned OrOpc = IsVALU ? AMDGPU::V_OR_B32_e64 : AMDGPU::S_OR_B32;

      BuildMI(*MBB, I, DL, TII.get(MovOpc), ImmReg)
        .addImm(0xffff);
      auto And = BuildMI(*MBB, I, DL, TII.get(AndOpc), TmpReg1)
        .addReg(LoReg)
        .addReg(ImmReg);
      auto Or = BuildMI(*MBB, I, DL, TII.get(OrOpc), DstReg)
        .addReg(TmpReg0)
        .addReg(TmpReg1);

      if (!IsVALU) {
        And.setOperandDead(3); // Dead scc
        Or.setOperandDead(3); // Dead scc
      }
    }

    I.eraseFromParent();
    return true;
  }

  if (!DstTy.isScalar())
    return false;

  if (SrcSize > 32) {
    unsigned SubRegIdx = DstSize < 32
                             ? static_cast<unsigned>(AMDGPU::sub0)
                             : TRI.getSubRegFromChannel(0, DstSize / 32);
    if (SubRegIdx == AMDGPU::NoSubRegister)
      return false;

    // Deal with weird cases where the class only partially supports the subreg
    // index.
    const TargetRegisterClass *SrcWithSubRC
      = TRI.getSubClassWithSubReg(SrcRC, SubRegIdx);
    if (!SrcWithSubRC)
      return false;

    if (SrcWithSubRC != SrcRC) {
      if (!RBI.constrainGenericRegister(SrcReg, *SrcWithSubRC, *MRI))
        return false;
    }

    I.getOperand(1).setSubReg(SubRegIdx);
  }

  I.setDesc(TII.get(TargetOpcode::COPY));
  return true;
}

/// \returns true if a bitmask for \p Size bits will be an inline immediate.
static bool shouldUseAndMask(unsigned Size, unsigned &Mask) {
  Mask = maskTrailingOnes<unsigned>(Size);
  int SignedMask = static_cast<int>(Mask);
  return SignedMask >= -16 && SignedMask <= 64;
}

// Like RegisterBankInfo::getRegBank, but don't assume vcc for s1.
const RegisterBank *AMDGPUInstructionSelector::getArtifactRegBank(
  Register Reg, const MachineRegisterInfo &MRI,
  const TargetRegisterInfo &TRI) const {
  const RegClassOrRegBank &RegClassOrBank = MRI.getRegClassOrRegBank(Reg);
  if (auto *RB = dyn_cast<const RegisterBank *>(RegClassOrBank))
    return RB;

  // Ignore the type, since we don't use vcc in artifacts.
  if (auto *RC = dyn_cast<const TargetRegisterClass *>(RegClassOrBank))
    return &RBI.getRegBankFromRegClass(*RC, LLT());
  return nullptr;
}

bool AMDGPUInstructionSelector::selectG_SZA_EXT(MachineInstr &I) const {
  bool InReg = I.getOpcode() == AMDGPU::G_SEXT_INREG;
  bool Signed = I.getOpcode() == AMDGPU::G_SEXT || InReg;
  const DebugLoc &DL = I.getDebugLoc();
  MachineBasicBlock &MBB = *I.getParent();
  const Register DstReg = I.getOperand(0).getReg();
  const Register SrcReg = I.getOperand(1).getReg();

  const LLT DstTy = MRI->getType(DstReg);
  const LLT SrcTy = MRI->getType(SrcReg);
  const unsigned SrcSize = I.getOpcode() == AMDGPU::G_SEXT_INREG ?
    I.getOperand(2).getImm() : SrcTy.getSizeInBits();
  const unsigned DstSize = DstTy.getSizeInBits();
  if (!DstTy.isScalar())
    return false;

  // Artifact casts should never use vcc.
  const RegisterBank *SrcBank = getArtifactRegBank(SrcReg, *MRI, TRI);

  // FIXME: This should probably be illegal and split earlier.
  if (I.getOpcode() == AMDGPU::G_ANYEXT) {
    if (DstSize <= 32)
      return selectCOPY(I);

    const TargetRegisterClass *SrcRC =
        TRI.getRegClassForTypeOnBank(SrcTy, *SrcBank);
    const RegisterBank *DstBank = RBI.getRegBank(DstReg, *MRI, TRI);
    const TargetRegisterClass *DstRC =
        TRI.getRegClassForSizeOnBank(DstSize, *DstBank);

    Register UndefReg = MRI->createVirtualRegister(SrcRC);
    BuildMI(MBB, I, DL, TII.get(AMDGPU::IMPLICIT_DEF), UndefReg);
    BuildMI(MBB, I, DL, TII.get(AMDGPU::REG_SEQUENCE), DstReg)
      .addReg(SrcReg)
      .addImm(AMDGPU::sub0)
      .addReg(UndefReg)
      .addImm(AMDGPU::sub1);
    I.eraseFromParent();

    return RBI.constrainGenericRegister(DstReg, *DstRC, *MRI) &&
           RBI.constrainGenericRegister(SrcReg, *SrcRC, *MRI);
  }

  if (SrcBank->getID() == AMDGPU::VGPRRegBankID && DstSize <= 32) {
    // 64-bit should have been split up in RegBankSelect

    // Try to use an and with a mask if it will save code size.
    unsigned Mask;
    if (!Signed && shouldUseAndMask(SrcSize, Mask)) {
      MachineInstr *ExtI =
      BuildMI(MBB, I, DL, TII.get(AMDGPU::V_AND_B32_e32), DstReg)
        .addImm(Mask)
        .addReg(SrcReg);
      I.eraseFromParent();
      return constrainSelectedInstRegOperands(*ExtI, TII, TRI, RBI);
    }

    const unsigned BFE = Signed ? AMDGPU::V_BFE_I32_e64 : AMDGPU::V_BFE_U32_e64;
    MachineInstr *ExtI =
      BuildMI(MBB, I, DL, TII.get(BFE), DstReg)
      .addReg(SrcReg)
      .addImm(0) // Offset
      .addImm(SrcSize); // Width
    I.eraseFromParent();
    return constrainSelectedInstRegOperands(*ExtI, TII, TRI, RBI);
  }

  if (SrcBank->getID() == AMDGPU::SGPRRegBankID && DstSize <= 64) {
    const TargetRegisterClass &SrcRC = InReg && DstSize > 32 ?
      AMDGPU::SReg_64RegClass : AMDGPU::SReg_32RegClass;
    if (!RBI.constrainGenericRegister(SrcReg, SrcRC, *MRI))
      return false;

    if (Signed && DstSize == 32 && (SrcSize == 8 || SrcSize == 16)) {
      const unsigned SextOpc = SrcSize == 8 ?
        AMDGPU::S_SEXT_I32_I8 : AMDGPU::S_SEXT_I32_I16;
      BuildMI(MBB, I, DL, TII.get(SextOpc), DstReg)
        .addReg(SrcReg);
      I.eraseFromParent();
      return RBI.constrainGenericRegister(DstReg, AMDGPU::SReg_32RegClass, *MRI);
    }

    // Using a single 32-bit SALU to calculate the high half is smaller than
    // S_BFE with a literal constant operand.
    if (DstSize > 32 && SrcSize == 32) {
      Register HiReg = MRI->createVirtualRegister(&AMDGPU::SReg_32RegClass);
      unsigned SubReg = InReg ? AMDGPU::sub0 : AMDGPU::NoSubRegister;
      if (Signed) {
        BuildMI(MBB, I, DL, TII.get(AMDGPU::S_ASHR_I32), HiReg)
          .addReg(SrcReg, 0, SubReg)
          .addImm(31)
          .setOperandDead(3); // Dead scc
      } else {
        BuildMI(MBB, I, DL, TII.get(AMDGPU::S_MOV_B32), HiReg)
          .addImm(0);
      }
      BuildMI(MBB, I, DL, TII.get(AMDGPU::REG_SEQUENCE), DstReg)
        .addReg(SrcReg, 0, SubReg)
        .addImm(AMDGPU::sub0)
        .addReg(HiReg)
        .addImm(AMDGPU::sub1);
      I.eraseFromParent();
      return RBI.constrainGenericRegister(DstReg, AMDGPU::SReg_64RegClass,
                                          *MRI);
    }

    const unsigned BFE64 = Signed ? AMDGPU::S_BFE_I64 : AMDGPU::S_BFE_U64;
    const unsigned BFE32 = Signed ? AMDGPU::S_BFE_I32 : AMDGPU::S_BFE_U32;

    // Scalar BFE is encoded as S1[5:0] = offset, S1[22:16]= width.
    if (DstSize > 32 && (SrcSize <= 32 || InReg)) {
      // We need a 64-bit register source, but the high bits don't matter.
      Register ExtReg = MRI->createVirtualRegister(&AMDGPU::SReg_64RegClass);
      Register UndefReg = MRI->createVirtualRegister(&AMDGPU::SReg_32RegClass);
      unsigned SubReg = InReg ? AMDGPU::sub0 : AMDGPU::NoSubRegister;

      BuildMI(MBB, I, DL, TII.get(AMDGPU::IMPLICIT_DEF), UndefReg);
      BuildMI(MBB, I, DL, TII.get(AMDGPU::REG_SEQUENCE), ExtReg)
        .addReg(SrcReg, 0, SubReg)
        .addImm(AMDGPU::sub0)
        .addReg(UndefReg)
        .addImm(AMDGPU::sub1);

      BuildMI(MBB, I, DL, TII.get(BFE64), DstReg)
        .addReg(ExtReg)
        .addImm(SrcSize << 16);

      I.eraseFromParent();
      return RBI.constrainGenericRegister(DstReg, AMDGPU::SReg_64RegClass, *MRI);
    }

    unsigned Mask;
    if (!Signed && shouldUseAndMask(SrcSize, Mask)) {
      BuildMI(MBB, I, DL, TII.get(AMDGPU::S_AND_B32), DstReg)
        .addReg(SrcReg)
        .addImm(Mask)
        .setOperandDead(3); // Dead scc
    } else {
      BuildMI(MBB, I, DL, TII.get(BFE32), DstReg)
        .addReg(SrcReg)
        .addImm(SrcSize << 16);
    }

    I.eraseFromParent();
    return RBI.constrainGenericRegister(DstReg, AMDGPU::SReg_32RegClass, *MRI);
  }

  return false;
}

static Register stripCopy(Register Reg, MachineRegisterInfo &MRI) {
  return getDefSrcRegIgnoringCopies(Reg, MRI)->Reg;
}

static Register stripBitCast(Register Reg, MachineRegisterInfo &MRI) {
  Register BitcastSrc;
  if (mi_match(Reg, MRI, m_GBitcast(m_Reg(BitcastSrc))))
    Reg = BitcastSrc;
  return Reg;
}

static bool isExtractHiElt(MachineRegisterInfo &MRI, Register In,
                           Register &Out) {
  Register Trunc;
  if (!mi_match(In, MRI, m_GTrunc(m_Reg(Trunc))))
    return false;

  Register LShlSrc;
  Register Cst;
  if (mi_match(Trunc, MRI, m_GLShr(m_Reg(LShlSrc), m_Reg(Cst)))) {
    Cst = stripCopy(Cst, MRI);
    if (mi_match(Cst, MRI, m_SpecificICst(16))) {
      Out = stripBitCast(LShlSrc, MRI);
      return true;
    }
  }

  MachineInstr *Shuffle = MRI.getVRegDef(Trunc);
  if (Shuffle->getOpcode() != AMDGPU::G_SHUFFLE_VECTOR)
    return false;

  assert(MRI.getType(Shuffle->getOperand(0).getReg()) ==
         LLT::fixed_vector(2, 16));

  ArrayRef<int> Mask = Shuffle->getOperand(3).getShuffleMask();
  assert(Mask.size() == 2);

  if (Mask[0] == 1 && Mask[1] <= 1) {
    Out = Shuffle->getOperand(0).getReg();
    return true;
  }

  return false;
}

bool AMDGPUInstructionSelector::selectG_FPEXT(MachineInstr &I) const {
  if (!Subtarget->hasSALUFloatInsts())
    return false;

  Register Dst = I.getOperand(0).getReg();
  const RegisterBank *DstRB = RBI.getRegBank(Dst, *MRI, TRI);
  if (DstRB->getID() != AMDGPU::SGPRRegBankID)
    return false;

  Register Src = I.getOperand(1).getReg();

  if (MRI->getType(Dst) == LLT::scalar(32) &&
      MRI->getType(Src) == LLT::scalar(16)) {
    if (isExtractHiElt(*MRI, Src, Src)) {
      MachineBasicBlock *BB = I.getParent();
      BuildMI(*BB, &I, I.getDebugLoc(), TII.get(AMDGPU::S_CVT_HI_F32_F16), Dst)
          .addUse(Src);
      I.eraseFromParent();
      return RBI.constrainGenericRegister(Dst, AMDGPU::SReg_32RegClass, *MRI);
    }
  }

  return false;
}

bool AMDGPUInstructionSelector::selectG_FNEG(MachineInstr &MI) const {
  // Only manually handle the f64 SGPR case.
  //
  // FIXME: This is a workaround for 2.5 different tablegen problems. Because
  // the bit ops theoretically have a second result due to the implicit def of
  // SCC, the GlobalISelEmitter is overly conservative and rejects it. Fixing
  // that is easy by disabling the check. The result works, but uses a
  // nonsensical sreg32orlds_and_sreg_1 regclass.
  //
  // The DAG emitter is more problematic, and incorrectly adds both S_XOR_B32 to
  // the variadic REG_SEQUENCE operands.

  Register Dst = MI.getOperand(0).getReg();
  const RegisterBank *DstRB = RBI.getRegBank(Dst, *MRI, TRI);
  if (DstRB->getID() != AMDGPU::SGPRRegBankID ||
      MRI->getType(Dst) != LLT::scalar(64))
    return false;

  Register Src = MI.getOperand(1).getReg();
  MachineInstr *Fabs = getOpcodeDef(TargetOpcode::G_FABS, Src, *MRI);
  if (Fabs)
    Src = Fabs->getOperand(1).getReg();

  if (!RBI.constrainGenericRegister(Src, AMDGPU::SReg_64RegClass, *MRI) ||
      !RBI.constrainGenericRegister(Dst, AMDGPU::SReg_64RegClass, *MRI))
    return false;

  MachineBasicBlock *BB = MI.getParent();
  const DebugLoc &DL = MI.getDebugLoc();
  Register LoReg = MRI->createVirtualRegister(&AMDGPU::SReg_32RegClass);
  Register HiReg = MRI->createVirtualRegister(&AMDGPU::SReg_32RegClass);
  Register ConstReg = MRI->createVirtualRegister(&AMDGPU::SReg_32RegClass);
  Register OpReg = MRI->createVirtualRegister(&AMDGPU::SReg_32RegClass);

  BuildMI(*BB, &MI, DL, TII.get(AMDGPU::COPY), LoReg)
    .addReg(Src, 0, AMDGPU::sub0);
  BuildMI(*BB, &MI, DL, TII.get(AMDGPU::COPY), HiReg)
    .addReg(Src, 0, AMDGPU::sub1);
  BuildMI(*BB, &MI, DL, TII.get(AMDGPU::S_MOV_B32), ConstReg)
    .addImm(0x80000000);

  // Set or toggle sign bit.
  unsigned Opc = Fabs ? AMDGPU::S_OR_B32 : AMDGPU::S_XOR_B32;
  BuildMI(*BB, &MI, DL, TII.get(Opc), OpReg)
    .addReg(HiReg)
    .addReg(ConstReg)
    .setOperandDead(3); // Dead scc
  BuildMI(*BB, &MI, DL, TII.get(AMDGPU::REG_SEQUENCE), Dst)
    .addReg(LoReg)
    .addImm(AMDGPU::sub0)
    .addReg(OpReg)
    .addImm(AMDGPU::sub1);
  MI.eraseFromParent();
  return true;
}

// FIXME: This is a workaround for the same tablegen problems as G_FNEG
bool AMDGPUInstructionSelector::selectG_FABS(MachineInstr &MI) const {
  Register Dst = MI.getOperand(0).getReg();
  const RegisterBank *DstRB = RBI.getRegBank(Dst, *MRI, TRI);
  if (DstRB->getID() != AMDGPU::SGPRRegBankID ||
      MRI->getType(Dst) != LLT::scalar(64))
    return false;

  Register Src = MI.getOperand(1).getReg();
  MachineBasicBlock *BB = MI.getParent();
  const DebugLoc &DL = MI.getDebugLoc();
  Register LoReg = MRI->createVirtualRegister(&AMDGPU::SReg_32RegClass);
  Register HiReg = MRI->createVirtualRegister(&AMDGPU::SReg_32RegClass);
  Register ConstReg = MRI->createVirtualRegister(&AMDGPU::SReg_32RegClass);
  Register OpReg = MRI->createVirtualRegister(&AMDGPU::SReg_32RegClass);

  if (!RBI.constrainGenericRegister(Src, AMDGPU::SReg_64RegClass, *MRI) ||
      !RBI.constrainGenericRegister(Dst, AMDGPU::SReg_64RegClass, *MRI))
    return false;

  BuildMI(*BB, &MI, DL, TII.get(AMDGPU::COPY), LoReg)
    .addReg(Src, 0, AMDGPU::sub0);
  BuildMI(*BB, &MI, DL, TII.get(AMDGPU::COPY), HiReg)
    .addReg(Src, 0, AMDGPU::sub1);
  BuildMI(*BB, &MI, DL, TII.get(AMDGPU::S_MOV_B32), ConstReg)
    .addImm(0x7fffffff);

  // Clear sign bit.
  // TODO: Should this used S_BITSET0_*?
  BuildMI(*BB, &MI, DL, TII.get(AMDGPU::S_AND_B32), OpReg)
    .addReg(HiReg)
    .addReg(ConstReg)
    .setOperandDead(3); // Dead scc
  BuildMI(*BB, &MI, DL, TII.get(AMDGPU::REG_SEQUENCE), Dst)
    .addReg(LoReg)
    .addImm(AMDGPU::sub0)
    .addReg(OpReg)
    .addImm(AMDGPU::sub1);

  MI.eraseFromParent();
  return true;
}

static bool isConstant(const MachineInstr &MI) {
  return MI.getOpcode() == TargetOpcode::G_CONSTANT;
}

void AMDGPUInstructionSelector::getAddrModeInfo(const MachineInstr &Load,
    const MachineRegisterInfo &MRI, SmallVectorImpl<GEPInfo> &AddrInfo) const {

  unsigned OpNo = Load.getOpcode() == AMDGPU::G_PREFETCH ? 0 : 1;
  const MachineInstr *PtrMI =
      MRI.getUniqueVRegDef(Load.getOperand(OpNo).getReg());

  assert(PtrMI);

  if (PtrMI->getOpcode() != TargetOpcode::G_PTR_ADD)
    return;

  GEPInfo GEPInfo;

  for (unsigned i = 1; i != 3; ++i) {
    const MachineOperand &GEPOp = PtrMI->getOperand(i);
    const MachineInstr *OpDef = MRI.getUniqueVRegDef(GEPOp.getReg());
    assert(OpDef);
    if (i == 2 && isConstant(*OpDef)) {
      // TODO: Could handle constant base + variable offset, but a combine
      // probably should have commuted it.
      assert(GEPInfo.Imm == 0);
      GEPInfo.Imm = OpDef->getOperand(1).getCImm()->getSExtValue();
      continue;
    }
    const RegisterBank *OpBank = RBI.getRegBank(GEPOp.getReg(), MRI, TRI);
    if (OpBank->getID() == AMDGPU::SGPRRegBankID)
      GEPInfo.SgprParts.push_back(GEPOp.getReg());
    else
      GEPInfo.VgprParts.push_back(GEPOp.getReg());
  }

  AddrInfo.push_back(GEPInfo);
  getAddrModeInfo(*PtrMI, MRI, AddrInfo);
}

bool AMDGPUInstructionSelector::isSGPR(Register Reg) const {
  return RBI.getRegBank(Reg, *MRI, TRI)->getID() == AMDGPU::SGPRRegBankID;
}

bool AMDGPUInstructionSelector::isInstrUniform(const MachineInstr &MI) const {
  if (!MI.hasOneMemOperand())
    return false;

  const MachineMemOperand *MMO = *MI.memoperands_begin();
  const Value *Ptr = MMO->getValue();

  // UndefValue means this is a load of a kernel input.  These are uniform.
  // Sometimes LDS instructions have constant pointers.
  // If Ptr is null, then that means this mem operand contains a
  // PseudoSourceValue like GOT.
  if (!Ptr || isa<UndefValue, Argument, Constant, GlobalValue>(Ptr))
    return true;

  if (MMO->getAddrSpace() == AMDGPUAS::CONSTANT_ADDRESS_32BIT)
    return true;

  if (MI.getOpcode() == AMDGPU::G_PREFETCH)
    return RBI.getRegBank(MI.getOperand(0).getReg(), *MRI, TRI)->getID() ==
           AMDGPU::SGPRRegBankID;

  const Instruction *I = dyn_cast<Instruction>(Ptr);
  return I && I->getMetadata("amdgpu.uniform");
}

bool AMDGPUInstructionSelector::hasVgprParts(ArrayRef<GEPInfo> AddrInfo) const {
  for (const GEPInfo &GEPInfo : AddrInfo) {
    if (!GEPInfo.VgprParts.empty())
      return true;
  }
  return false;
}

void AMDGPUInstructionSelector::initM0(MachineInstr &I) const {
  const LLT PtrTy = MRI->getType(I.getOperand(1).getReg());
  unsigned AS = PtrTy.getAddressSpace();
  if ((AS == AMDGPUAS::LOCAL_ADDRESS || AS == AMDGPUAS::REGION_ADDRESS) &&
      STI.ldsRequiresM0Init()) {
    MachineBasicBlock *BB = I.getParent();

    // If DS instructions require M0 initialization, insert it before selecting.
    BuildMI(*BB, &I, I.getDebugLoc(), TII.get(AMDGPU::S_MOV_B32), AMDGPU::M0)
      .addImm(-1);
  }
}

bool AMDGPUInstructionSelector::selectG_LOAD_STORE_ATOMICRMW(
  MachineInstr &I) const {
  initM0(I);
  return selectImpl(I, *CoverageInfo);
}

static bool isVCmpResult(Register Reg, MachineRegisterInfo &MRI) {
  if (Reg.isPhysical())
    return false;

  MachineInstr &MI = *MRI.getUniqueVRegDef(Reg);
  const unsigned Opcode = MI.getOpcode();

  if (Opcode == AMDGPU::COPY)
    return isVCmpResult(MI.getOperand(1).getReg(), MRI);

  if (Opcode == AMDGPU::G_AND || Opcode == AMDGPU::G_OR ||
      Opcode == AMDGPU::G_XOR)
    return isVCmpResult(MI.getOperand(1).getReg(), MRI) &&
           isVCmpResult(MI.getOperand(2).getReg(), MRI);

  if (auto *GI = dyn_cast<GIntrinsic>(&MI))
    return GI->is(Intrinsic::amdgcn_class);

  return Opcode == AMDGPU::G_ICMP || Opcode == AMDGPU::G_FCMP;
}

bool AMDGPUInstructionSelector::selectG_BRCOND(MachineInstr &I) const {
  MachineBasicBlock *BB = I.getParent();
  MachineOperand &CondOp = I.getOperand(0);
  Register CondReg = CondOp.getReg();
  const DebugLoc &DL = I.getDebugLoc();

  unsigned BrOpcode;
  Register CondPhysReg;
  const TargetRegisterClass *ConstrainRC;

  // In SelectionDAG, we inspect the IR block for uniformity metadata to decide
  // whether the branch is uniform when selecting the instruction. In
  // GlobalISel, we should push that decision into RegBankSelect. Assume for now
  // RegBankSelect knows what it's doing if the branch condition is scc, even
  // though it currently does not.
  if (!isVCC(CondReg, *MRI)) {
    if (MRI->getType(CondReg) != LLT::scalar(32))
      return false;

    CondPhysReg = AMDGPU::SCC;
    BrOpcode = AMDGPU::S_CBRANCH_SCC1;
    ConstrainRC = &AMDGPU::SReg_32RegClass;
  } else {
    // FIXME: Should scc->vcc copies and with exec?

    // Unless the value of CondReg is a result of a V_CMP* instruction then we
    // need to insert an and with exec.
    if (!isVCmpResult(CondReg, *MRI)) {
      const bool Is64 = STI.isWave64();
      const unsigned Opcode = Is64 ? AMDGPU::S_AND_B64 : AMDGPU::S_AND_B32;
      const Register Exec = Is64 ? AMDGPU::EXEC : AMDGPU::EXEC_LO;

      Register TmpReg = MRI->createVirtualRegister(TRI.getBoolRC());
      BuildMI(*BB, &I, DL, TII.get(Opcode), TmpReg)
          .addReg(CondReg)
          .addReg(Exec)
          .setOperandDead(3); // Dead scc
      CondReg = TmpReg;
    }

    CondPhysReg = TRI.getVCC();
    BrOpcode = AMDGPU::S_CBRANCH_VCCNZ;
    ConstrainRC = TRI.getBoolRC();
  }

  if (!MRI->getRegClassOrNull(CondReg))
    MRI->setRegClass(CondReg, ConstrainRC);

  BuildMI(*BB, &I, DL, TII.get(AMDGPU::COPY), CondPhysReg)
    .addReg(CondReg);
  BuildMI(*BB, &I, DL, TII.get(BrOpcode))
    .addMBB(I.getOperand(1).getMBB());

  I.eraseFromParent();
  return true;
}

bool AMDGPUInstructionSelector::selectG_GLOBAL_VALUE(
  MachineInstr &I) const {
  Register DstReg = I.getOperand(0).getReg();
  const RegisterBank *DstRB = RBI.getRegBank(DstReg, *MRI, TRI);
  const bool IsVGPR = DstRB->getID() == AMDGPU::VGPRRegBankID;
  I.setDesc(TII.get(IsVGPR ? AMDGPU::V_MOV_B32_e32 : AMDGPU::S_MOV_B32));
  if (IsVGPR)
    I.addOperand(*MF, MachineOperand::CreateReg(AMDGPU::EXEC, false, true));

  return RBI.constrainGenericRegister(
    DstReg, IsVGPR ? AMDGPU::VGPR_32RegClass : AMDGPU::SReg_32RegClass, *MRI);
}

bool AMDGPUInstructionSelector::selectG_PTRMASK(MachineInstr &I) const {
  Register DstReg = I.getOperand(0).getReg();
  Register SrcReg = I.getOperand(1).getReg();
  Register MaskReg = I.getOperand(2).getReg();
  LLT Ty = MRI->getType(DstReg);
  LLT MaskTy = MRI->getType(MaskReg);
  MachineBasicBlock *BB = I.getParent();
  const DebugLoc &DL = I.getDebugLoc();

  const RegisterBank *DstRB = RBI.getRegBank(DstReg, *MRI, TRI);
  const RegisterBank *SrcRB = RBI.getRegBank(SrcReg, *MRI, TRI);
  const RegisterBank *MaskRB = RBI.getRegBank(MaskReg, *MRI, TRI);
  const bool IsVGPR = DstRB->getID() == AMDGPU::VGPRRegBankID;
  if (DstRB != SrcRB) // Should only happen for hand written MIR.
    return false;

  // Try to avoid emitting a bit operation when we only need to touch half of
  // the 64-bit pointer.
  APInt MaskOnes = VT->getKnownOnes(MaskReg).zext(64);
  const APInt MaskHi32 = APInt::getHighBitsSet(64, 32);
  const APInt MaskLo32 = APInt::getLowBitsSet(64, 32);

  const bool CanCopyLow32 = (MaskOnes & MaskLo32) == MaskLo32;
  const bool CanCopyHi32 = (MaskOnes & MaskHi32) == MaskHi32;

  if (!IsVGPR && Ty.getSizeInBits() == 64 &&
      !CanCopyLow32 && !CanCopyHi32) {
    auto MIB = BuildMI(*BB, &I, DL, TII.get(AMDGPU::S_AND_B64), DstReg)
      .addReg(SrcReg)
      .addReg(MaskReg)
      .setOperandDead(3); // Dead scc
    I.eraseFromParent();
    return constrainSelectedInstRegOperands(*MIB, TII, TRI, RBI);
  }

  unsigned NewOpc = IsVGPR ? AMDGPU::V_AND_B32_e64 : AMDGPU::S_AND_B32;
  const TargetRegisterClass &RegRC
    = IsVGPR ? AMDGPU::VGPR_32RegClass : AMDGPU::SReg_32RegClass;

  const TargetRegisterClass *DstRC = TRI.getRegClassForTypeOnBank(Ty, *DstRB);
  const TargetRegisterClass *SrcRC = TRI.getRegClassForTypeOnBank(Ty, *SrcRB);
  const TargetRegisterClass *MaskRC =
      TRI.getRegClassForTypeOnBank(MaskTy, *MaskRB);

  if (!RBI.constrainGenericRegister(DstReg, *DstRC, *MRI) ||
      !RBI.constrainGenericRegister(SrcReg, *SrcRC, *MRI) ||
      !RBI.constrainGenericRegister(MaskReg, *MaskRC, *MRI))
    return false;

  if (Ty.getSizeInBits() == 32) {
    assert(MaskTy.getSizeInBits() == 32 &&
           "ptrmask should have been narrowed during legalize");

    auto NewOp = BuildMI(*BB, &I, DL, TII.get(NewOpc), DstReg)
      .addReg(SrcReg)
      .addReg(MaskReg);

    if (!IsVGPR)
      NewOp.setOperandDead(3); // Dead scc
    I.eraseFromParent();
    return true;
  }

  Register HiReg = MRI->createVirtualRegister(&RegRC);
  Register LoReg = MRI->createVirtualRegister(&RegRC);

  // Extract the subregisters from the source pointer.
  BuildMI(*BB, &I, DL, TII.get(AMDGPU::COPY), LoReg)
    .addReg(SrcReg, 0, AMDGPU::sub0);
  BuildMI(*BB, &I, DL, TII.get(AMDGPU::COPY), HiReg)
    .addReg(SrcReg, 0, AMDGPU::sub1);

  Register MaskedLo, MaskedHi;

  if (CanCopyLow32) {
    // If all the bits in the low half are 1, we only need a copy for it.
    MaskedLo = LoReg;
  } else {
    // Extract the mask subregister and apply the and.
    Register MaskLo = MRI->createVirtualRegister(&RegRC);
    MaskedLo = MRI->createVirtualRegister(&RegRC);

    BuildMI(*BB, &I, DL, TII.get(AMDGPU::COPY), MaskLo)
      .addReg(MaskReg, 0, AMDGPU::sub0);
    BuildMI(*BB, &I, DL, TII.get(NewOpc), MaskedLo)
      .addReg(LoReg)
      .addReg(MaskLo);
  }

  if (CanCopyHi32) {
    // If all the bits in the high half are 1, we only need a copy for it.
    MaskedHi = HiReg;
  } else {
    Register MaskHi = MRI->createVirtualRegister(&RegRC);
    MaskedHi = MRI->createVirtualRegister(&RegRC);

    BuildMI(*BB, &I, DL, TII.get(AMDGPU::COPY), MaskHi)
      .addReg(MaskReg, 0, AMDGPU::sub1);
    BuildMI(*BB, &I, DL, TII.get(NewOpc), MaskedHi)
      .addReg(HiReg)
      .addReg(MaskHi);
  }

  BuildMI(*BB, &I, DL, TII.get(AMDGPU::REG_SEQUENCE), DstReg)
    .addReg(MaskedLo)
    .addImm(AMDGPU::sub0)
    .addReg(MaskedHi)
    .addImm(AMDGPU::sub1);
  I.eraseFromParent();
  return true;
}

/// Return the register to use for the index value, and the subregister to use
/// for the indirectly accessed register.
static std::pair<Register, unsigned>
computeIndirectRegIndex(MachineRegisterInfo &MRI, const SIRegisterInfo &TRI,
                        const TargetRegisterClass *SuperRC, Register IdxReg,
                        unsigned EltSize, GISelValueTracking &ValueTracking) {
  Register IdxBaseReg;
  int Offset;

  std::tie(IdxBaseReg, Offset) =
      AMDGPU::getBaseWithConstantOffset(MRI, IdxReg, &ValueTracking);
  if (IdxBaseReg == AMDGPU::NoRegister) {
    // This will happen if the index is a known constant. This should ordinarily
    // be legalized out, but handle it as a register just in case.
    assert(Offset == 0);
    IdxBaseReg = IdxReg;
  }

  ArrayRef<int16_t> SubRegs = TRI.getRegSplitParts(SuperRC, EltSize);

  // Skip out of bounds offsets, or else we would end up using an undefined
  // register.
  if (static_cast<unsigned>(Offset) >= SubRegs.size())
    return std::pair(IdxReg, SubRegs[0]);
  return std::pair(IdxBaseReg, SubRegs[Offset]);
}

bool AMDGPUInstructionSelector::selectG_EXTRACT_VECTOR_ELT(
  MachineInstr &MI) const {
  Register DstReg = MI.getOperand(0).getReg();
  Register SrcReg = MI.getOperand(1).getReg();
  Register IdxReg = MI.getOperand(2).getReg();

  LLT DstTy = MRI->getType(DstReg);
  LLT SrcTy = MRI->getType(SrcReg);

  const RegisterBank *DstRB = RBI.getRegBank(DstReg, *MRI, TRI);
  const RegisterBank *SrcRB = RBI.getRegBank(SrcReg, *MRI, TRI);
  const RegisterBank *IdxRB = RBI.getRegBank(IdxReg, *MRI, TRI);

  // The index must be scalar. If it wasn't RegBankSelect should have moved this
  // into a waterfall loop.
  if (IdxRB->getID() != AMDGPU::SGPRRegBankID)
    return false;

  const TargetRegisterClass *SrcRC =
      TRI.getRegClassForTypeOnBank(SrcTy, *SrcRB);
  const TargetRegisterClass *DstRC =
      TRI.getRegClassForTypeOnBank(DstTy, *DstRB);
  if (!SrcRC || !DstRC)
    return false;
  if (!RBI.constrainGenericRegister(SrcReg, *SrcRC, *MRI) ||
      !RBI.constrainGenericRegister(DstReg, *DstRC, *MRI) ||
      !RBI.constrainGenericRegister(IdxReg, AMDGPU::SReg_32RegClass, *MRI))
    return false;

  MachineBasicBlock *BB = MI.getParent();
  const DebugLoc &DL = MI.getDebugLoc();
  const bool Is64 = DstTy.getSizeInBits() == 64;

  unsigned SubReg;
  std::tie(IdxReg, SubReg) = computeIndirectRegIndex(
      *MRI, TRI, SrcRC, IdxReg, DstTy.getSizeInBits() / 8, *VT);

  if (SrcRB->getID() == AMDGPU::SGPRRegBankID) {
    if (DstTy.getSizeInBits() != 32 && !Is64)
      return false;

    BuildMI(*BB, &MI, DL, TII.get(AMDGPU::COPY), AMDGPU::M0)
      .addReg(IdxReg);

    unsigned Opc = Is64 ? AMDGPU::S_MOVRELS_B64 : AMDGPU::S_MOVRELS_B32;
    BuildMI(*BB, &MI, DL, TII.get(Opc), DstReg)
      .addReg(SrcReg, 0, SubReg)
      .addReg(SrcReg, RegState::Implicit);
    MI.eraseFromParent();
    return true;
  }

  if (SrcRB->getID() != AMDGPU::VGPRRegBankID || DstTy.getSizeInBits() != 32)
    return false;

  if (!STI.useVGPRIndexMode()) {
    BuildMI(*BB, &MI, DL, TII.get(AMDGPU::COPY), AMDGPU::M0)
      .addReg(IdxReg);
    BuildMI(*BB, &MI, DL, TII.get(AMDGPU::V_MOVRELS_B32_e32), DstReg)
      .addReg(SrcReg, 0, SubReg)
      .addReg(SrcReg, RegState::Implicit);
    MI.eraseFromParent();
    return true;
  }

  const MCInstrDesc &GPRIDXDesc =
      TII.getIndirectGPRIDXPseudo(TRI.getRegSizeInBits(*SrcRC), true);
  BuildMI(*BB, MI, DL, GPRIDXDesc, DstReg)
      .addReg(SrcReg)
      .addReg(IdxReg)
      .addImm(SubReg);

  MI.eraseFromParent();
  return true;
}

// TODO: Fold insert_vector_elt (extract_vector_elt) into movrelsd
bool AMDGPUInstructionSelector::selectG_INSERT_VECTOR_ELT(
  MachineInstr &MI) const {
  Register DstReg = MI.getOperand(0).getReg();
  Register VecReg = MI.getOperand(1).getReg();
  Register ValReg = MI.getOperand(2).getReg();
  Register IdxReg = MI.getOperand(3).getReg();

  LLT VecTy = MRI->getType(DstReg);
  LLT ValTy = MRI->getType(ValReg);
  unsigned VecSize = VecTy.getSizeInBits();
  unsigned ValSize = ValTy.getSizeInBits();

  const RegisterBank *VecRB = RBI.getRegBank(VecReg, *MRI, TRI);
  const RegisterBank *ValRB = RBI.getRegBank(ValReg, *MRI, TRI);
  const RegisterBank *IdxRB = RBI.getRegBank(IdxReg, *MRI, TRI);

  assert(VecTy.getElementType() == ValTy);

  // The index must be scalar. If it wasn't RegBankSelect should have moved this
  // into a waterfall loop.
  if (IdxRB->getID() != AMDGPU::SGPRRegBankID)
    return false;

  const TargetRegisterClass *VecRC =
      TRI.getRegClassForTypeOnBank(VecTy, *VecRB);
  const TargetRegisterClass *ValRC =
      TRI.getRegClassForTypeOnBank(ValTy, *ValRB);

  if (!RBI.constrainGenericRegister(VecReg, *VecRC, *MRI) ||
      !RBI.constrainGenericRegister(DstReg, *VecRC, *MRI) ||
      !RBI.constrainGenericRegister(ValReg, *ValRC, *MRI) ||
      !RBI.constrainGenericRegister(IdxReg, AMDGPU::SReg_32RegClass, *MRI))
    return false;

  if (VecRB->getID() == AMDGPU::VGPRRegBankID && ValSize != 32)
    return false;

  unsigned SubReg;
  std::tie(IdxReg, SubReg) =
      computeIndirectRegIndex(*MRI, TRI, VecRC, IdxReg, ValSize / 8, *VT);

  const bool IndexMode = VecRB->getID() == AMDGPU::VGPRRegBankID &&
                         STI.useVGPRIndexMode();

  MachineBasicBlock *BB = MI.getParent();
  const DebugLoc &DL = MI.getDebugLoc();

  if (!IndexMode) {
    BuildMI(*BB, &MI, DL, TII.get(AMDGPU::COPY), AMDGPU::M0)
      .addReg(IdxReg);

    const MCInstrDesc &RegWriteOp = TII.getIndirectRegWriteMovRelPseudo(
        VecSize, ValSize, VecRB->getID() == AMDGPU::SGPRRegBankID);
    BuildMI(*BB, MI, DL, RegWriteOp, DstReg)
        .addReg(VecReg)
        .addReg(ValReg)
        .addImm(SubReg);
    MI.eraseFromParent();
    return true;
  }

  const MCInstrDesc &GPRIDXDesc =
      TII.getIndirectGPRIDXPseudo(TRI.getRegSizeInBits(*VecRC), false);
  BuildMI(*BB, MI, DL, GPRIDXDesc, DstReg)
      .addReg(VecReg)
      .addReg(ValReg)
      .addReg(IdxReg)
      .addImm(SubReg);

  MI.eraseFromParent();
  return true;
}

bool AMDGPUInstructionSelector::selectBufferLoadLds(MachineInstr &MI) const {
  if (!Subtarget->hasVMemToLDSLoad())
    return false;
  unsigned Opc;
  unsigned Size = MI.getOperand(3).getImm();

  // The struct intrinsic variants add one additional operand over raw.
  const bool HasVIndex = MI.getNumOperands() == 9;
  Register VIndex;
  int OpOffset = 0;
  if (HasVIndex) {
    VIndex = MI.getOperand(4).getReg();
    OpOffset = 1;
  }

  Register VOffset = MI.getOperand(4 + OpOffset).getReg();
  std::optional<ValueAndVReg> MaybeVOffset =
      getIConstantVRegValWithLookThrough(VOffset, *MRI);
  const bool HasVOffset = !MaybeVOffset || MaybeVOffset->Value.getZExtValue();

  switch (Size) {
  default:
    return false;
  case 1:
    Opc = HasVIndex ? HasVOffset ? AMDGPU::BUFFER_LOAD_UBYTE_LDS_BOTHEN
                                 : AMDGPU::BUFFER_LOAD_UBYTE_LDS_IDXEN
                    : HasVOffset ? AMDGPU::BUFFER_LOAD_UBYTE_LDS_OFFEN
                                 : AMDGPU::BUFFER_LOAD_UBYTE_LDS_OFFSET;
    break;
  case 2:
    Opc = HasVIndex ? HasVOffset ? AMDGPU::BUFFER_LOAD_USHORT_LDS_BOTHEN
                                 : AMDGPU::BUFFER_LOAD_USHORT_LDS_IDXEN
                    : HasVOffset ? AMDGPU::BUFFER_LOAD_USHORT_LDS_OFFEN
                                 : AMDGPU::BUFFER_LOAD_USHORT_LDS_OFFSET;
    break;
  case 4:
    Opc = HasVIndex ? HasVOffset ? AMDGPU::BUFFER_LOAD_DWORD_LDS_BOTHEN
                                 : AMDGPU::BUFFER_LOAD_DWORD_LDS_IDXEN
                    : HasVOffset ? AMDGPU::BUFFER_LOAD_DWORD_LDS_OFFEN
                                 : AMDGPU::BUFFER_LOAD_DWORD_LDS_OFFSET;
    break;
  case 12:
    if (!Subtarget->hasLDSLoadB96_B128())
      return false;

    Opc = HasVIndex ? HasVOffset ? AMDGPU::BUFFER_LOAD_DWORDX3_LDS_BOTHEN
                                 : AMDGPU::BUFFER_LOAD_DWORDX3_LDS_IDXEN
                    : HasVOffset ? AMDGPU::BUFFER_LOAD_DWORDX3_LDS_OFFEN
                                 : AMDGPU::BUFFER_LOAD_DWORDX3_LDS_OFFSET;
    break;
  case 16:
    if (!Subtarget->hasLDSLoadB96_B128())
      return false;

    Opc = HasVIndex ? HasVOffset ? AMDGPU::BUFFER_LOAD_DWORDX4_LDS_BOTHEN
                                 : AMDGPU::BUFFER_LOAD_DWORDX4_LDS_IDXEN
                    : HasVOffset ? AMDGPU::BUFFER_LOAD_DWORDX4_LDS_OFFEN
                                 : AMDGPU::BUFFER_LOAD_DWORDX4_LDS_OFFSET;
    break;
  }

  MachineBasicBlock *MBB = MI.getParent();
  const DebugLoc &DL = MI.getDebugLoc();
  BuildMI(*MBB, &MI, DL, TII.get(AMDGPU::COPY), AMDGPU::M0)
    .add(MI.getOperand(2));

  auto MIB = BuildMI(*MBB, &MI, DL, TII.get(Opc));

  if (HasVIndex && HasVOffset) {
    Register IdxReg = MRI->createVirtualRegister(TRI.getVGPR64Class());
    BuildMI(*MBB, &*MIB, DL, TII.get(AMDGPU::REG_SEQUENCE), IdxReg)
      .addReg(VIndex)
      .addImm(AMDGPU::sub0)
      .addReg(VOffset)
      .addImm(AMDGPU::sub1);

    MIB.addReg(IdxReg);
  } else if (HasVIndex) {
    MIB.addReg(VIndex);
  } else if (HasVOffset) {
    MIB.addReg(VOffset);
  }

  MIB.add(MI.getOperand(1));            // rsrc
  MIB.add(MI.getOperand(5 + OpOffset)); // soffset
  MIB.add(MI.getOperand(6 + OpOffset)); // imm offset
  bool IsGFX12Plus = AMDGPU::isGFX12Plus(STI);
  unsigned Aux = MI.getOperand(7 + OpOffset).getImm();
  MIB.addImm(Aux & (IsGFX12Plus ? AMDGPU::CPol::ALL
                                : AMDGPU::CPol::ALL_pregfx12)); // cpol
  MIB.addImm(
      Aux & (IsGFX12Plus ? AMDGPU::CPol::SWZ : AMDGPU::CPol::SWZ_pregfx12)
          ? 1
          : 0); // swz

  MachineMemOperand *LoadMMO = *MI.memoperands_begin();
  // Don't set the offset value here because the pointer points to the base of
  // the buffer.
  MachinePointerInfo LoadPtrI = LoadMMO->getPointerInfo();

  MachinePointerInfo StorePtrI = LoadPtrI;
  LoadPtrI.V = PoisonValue::get(PointerType::get(MF->getFunction().getContext(),
                                                 AMDGPUAS::BUFFER_RESOURCE));
  LoadPtrI.AddrSpace = AMDGPUAS::BUFFER_RESOURCE;
  StorePtrI.AddrSpace = AMDGPUAS::LOCAL_ADDRESS;

  auto F = LoadMMO->getFlags() &
           ~(MachineMemOperand::MOStore | MachineMemOperand::MOLoad);
  LoadMMO = MF->getMachineMemOperand(LoadPtrI, F | MachineMemOperand::MOLoad,
                                     Size, LoadMMO->getBaseAlign());

  MachineMemOperand *StoreMMO =
      MF->getMachineMemOperand(StorePtrI, F | MachineMemOperand::MOStore,
                               sizeof(int32_t), LoadMMO->getBaseAlign());

  MIB.setMemRefs({LoadMMO, StoreMMO});

  MI.eraseFromParent();
  return constrainSelectedInstRegOperands(*MIB, TII, TRI, RBI);
}

/// Match a zero extend from a 32-bit value to 64-bits.
Register AMDGPUInstructionSelector::matchZeroExtendFromS32(Register Reg) const {
  Register ZExtSrc;
  if (mi_match(Reg, *MRI, m_GZExt(m_Reg(ZExtSrc))))
    return MRI->getType(ZExtSrc) == LLT::scalar(32) ? ZExtSrc : Register();

  // Match legalized form %zext = G_MERGE_VALUES (s32 %x), (s32 0)
  const MachineInstr *Def = getDefIgnoringCopies(Reg, *MRI);
  if (Def->getOpcode() != AMDGPU::G_MERGE_VALUES)
    return Register();

  assert(Def->getNumOperands() == 3 &&
         MRI->getType(Def->getOperand(0).getReg()) == LLT::scalar(64));
  if (mi_match(Def->getOperand(2).getReg(), *MRI, m_ZeroInt())) {
    return Def->getOperand(1).getReg();
  }

  return Register();
}

/// Match a sign extend from a 32-bit value to 64-bits.
Register AMDGPUInstructionSelector::matchSignExtendFromS32(Register Reg) const {
  Register SExtSrc;
  if (mi_match(Reg, *MRI, m_GSExt(m_Reg(SExtSrc))))
    return MRI->getType(SExtSrc) == LLT::scalar(32) ? SExtSrc : Register();

  // Match legalized form %sext = G_MERGE_VALUES (s32 %x), G_ASHR((S32 %x, 31))
  const MachineInstr *Def = getDefIgnoringCopies(Reg, *MRI);
  if (Def->getOpcode() != AMDGPU::G_MERGE_VALUES)
    return Register();

  assert(Def->getNumOperands() == 3 &&
         MRI->getType(Def->getOperand(0).getReg()) == LLT::scalar(64));
  if (mi_match(Def->getOperand(2).getReg(), *MRI,
               m_GAShr(m_SpecificReg(Def->getOperand(1).getReg()),
                       m_SpecificICst(31))))
    return Def->getOperand(1).getReg();

  if (VT->signBitIsZero(Reg))
    return matchZeroExtendFromS32(Reg);

  return Register();
}

/// Match a zero extend from a 32-bit value to 64-bits, or \p Reg itself if it
/// is 32-bit.
Register
AMDGPUInstructionSelector::matchZeroExtendFromS32OrS32(Register Reg) const {
  return MRI->getType(Reg) == LLT::scalar(32) ? Reg
                                              : matchZeroExtendFromS32(Reg);
}

/// Match a sign extend from a 32-bit value to 64-bits, or \p Reg itself if it
/// is 32-bit.
Register
AMDGPUInstructionSelector::matchSignExtendFromS32OrS32(Register Reg) const {
  return MRI->getType(Reg) == LLT::scalar(32) ? Reg
                                              : matchSignExtendFromS32(Reg);
}

Register
AMDGPUInstructionSelector::matchExtendFromS32OrS32(Register Reg,
                                                   bool IsSigned) const {
  if (IsSigned)
    return matchSignExtendFromS32OrS32(Reg);

  return matchZeroExtendFromS32OrS32(Reg);
}

Register AMDGPUInstructionSelector::matchAnyExtendFromS32(Register Reg) const {
  Register AnyExtSrc;
  if (mi_match(Reg, *MRI, m_GAnyExt(m_Reg(AnyExtSrc))))
    return MRI->getType(AnyExtSrc) == LLT::scalar(32) ? AnyExtSrc : Register();

  // Match legalized form %zext = G_MERGE_VALUES (s32 %x), (s32 G_IMPLICIT_DEF)
  const MachineInstr *Def = getDefIgnoringCopies(Reg, *MRI);
  if (Def->getOpcode() != AMDGPU::G_MERGE_VALUES)
    return Register();

  assert(Def->getNumOperands() == 3 &&
         MRI->getType(Def->getOperand(0).getReg()) == LLT::scalar(64));

  if (mi_match(Def->getOperand(2).getReg(), *MRI, m_GImplicitDef()))
    return Def->getOperand(1).getReg();

  return Register();
}

bool AMDGPUInstructionSelector::selectGlobalLoadLds(MachineInstr &MI) const{
  if (!Subtarget->hasVMemToLDSLoad())
    return false;

  unsigned Opc;
  unsigned Size = MI.getOperand(3).getImm();

  switch (Size) {
  default:
    return false;
  case 1:
    Opc = AMDGPU::GLOBAL_LOAD_LDS_UBYTE;
    break;
  case 2:
    Opc = AMDGPU::GLOBAL_LOAD_LDS_USHORT;
    break;
  case 4:
    Opc = AMDGPU::GLOBAL_LOAD_LDS_DWORD;
    break;
  case 12:
    if (!Subtarget->hasLDSLoadB96_B128())
      return false;
    Opc = AMDGPU::GLOBAL_LOAD_LDS_DWORDX3;
    break;
  case 16:
    if (!Subtarget->hasLDSLoadB96_B128())
      return false;
    Opc = AMDGPU::GLOBAL_LOAD_LDS_DWORDX4;
    break;
  }

  MachineBasicBlock *MBB = MI.getParent();
  const DebugLoc &DL = MI.getDebugLoc();
  BuildMI(*MBB, &MI, DL, TII.get(AMDGPU::COPY), AMDGPU::M0)
    .add(MI.getOperand(2));

  Register Addr = MI.getOperand(1).getReg();
  Register VOffset;
  // Try to split SAddr and VOffset. Global and LDS pointers share the same
  // immediate offset, so we cannot use a regular SelectGlobalSAddr().
  if (!isSGPR(Addr)) {
    auto AddrDef = getDefSrcRegIgnoringCopies(Addr, *MRI);
    if (isSGPR(AddrDef->Reg)) {
      Addr = AddrDef->Reg;
    } else if (AddrDef->MI->getOpcode() == AMDGPU::G_PTR_ADD) {
      Register SAddr =
          getSrcRegIgnoringCopies(AddrDef->MI->getOperand(1).getReg(), *MRI);
      if (isSGPR(SAddr)) {
        Register PtrBaseOffset = AddrDef->MI->getOperand(2).getReg();
        if (Register Off = matchZeroExtendFromS32(PtrBaseOffset)) {
          Addr = SAddr;
          VOffset = Off;
        }
      }
    }
  }

  if (isSGPR(Addr)) {
    Opc = AMDGPU::getGlobalSaddrOp(Opc);
    if (!VOffset) {
      VOffset = MRI->createVirtualRegister(&AMDGPU::VGPR_32RegClass);
      BuildMI(*MBB, &MI, DL, TII.get(AMDGPU::V_MOV_B32_e32), VOffset)
        .addImm(0);
    }
  }

  auto MIB = BuildMI(*MBB, &MI, DL, TII.get(Opc))
    .addReg(Addr);

  if (isSGPR(Addr))
    MIB.addReg(VOffset);

  MIB.add(MI.getOperand(4)); // offset

  unsigned Aux = MI.getOperand(5).getImm();
  MIB.addImm(Aux & ~AMDGPU::CPol::VIRTUAL_BITS); // cpol

  MachineMemOperand *LoadMMO = *MI.memoperands_begin();
  MachinePointerInfo LoadPtrI = LoadMMO->getPointerInfo();
  LoadPtrI.Offset = MI.getOperand(4).getImm();
  MachinePointerInfo StorePtrI = LoadPtrI;
  LoadPtrI.V = PoisonValue::get(PointerType::get(MF->getFunction().getContext(),
                                                 AMDGPUAS::GLOBAL_ADDRESS));
  LoadPtrI.AddrSpace = AMDGPUAS::GLOBAL_ADDRESS;
  StorePtrI.AddrSpace = AMDGPUAS::LOCAL_ADDRESS;
  auto F = LoadMMO->getFlags() &
           ~(MachineMemOperand::MOStore | MachineMemOperand::MOLoad);
  LoadMMO = MF->getMachineMemOperand(LoadPtrI, F | MachineMemOperand::MOLoad,
                                     Size, LoadMMO->getBaseAlign());
  MachineMemOperand *StoreMMO =
      MF->getMachineMemOperand(StorePtrI, F | MachineMemOperand::MOStore,
                               sizeof(int32_t), Align(4));

  MIB.setMemRefs({LoadMMO, StoreMMO});

  MI.eraseFromParent();
  return constrainSelectedInstRegOperands(*MIB, TII, TRI, RBI);
}

bool AMDGPUInstructionSelector::selectBVHIntersectRayIntrinsic(
    MachineInstr &MI) const {
  unsigned OpcodeOpIdx =
      MI.getOpcode() == AMDGPU::G_AMDGPU_BVH_INTERSECT_RAY ? 1 : 3;
  MI.setDesc(TII.get(MI.getOperand(OpcodeOpIdx).getImm()));
  MI.removeOperand(OpcodeOpIdx);
  MI.addImplicitDefUseOperands(*MI.getMF());
  return constrainSelectedInstRegOperands(MI, TII, TRI, RBI);
}

// FIXME: This should be removed and let the patterns select. We just need the
// AGPR/VGPR combination versions.
bool AMDGPUInstructionSelector::selectSMFMACIntrin(MachineInstr &MI) const {
  unsigned Opc;
  switch (cast<GIntrinsic>(MI).getIntrinsicID()) {
  case Intrinsic::amdgcn_smfmac_f32_16x16x32_f16:
    Opc = AMDGPU::V_SMFMAC_F32_16X16X32_F16_e64;
    break;
  case Intrinsic::amdgcn_smfmac_f32_32x32x16_f16:
    Opc = AMDGPU::V_SMFMAC_F32_32X32X16_F16_e64;
    break;
  case Intrinsic::amdgcn_smfmac_f32_16x16x32_bf16:
    Opc = AMDGPU::V_SMFMAC_F32_16X16X32_BF16_e64;
    break;
  case Intrinsic::amdgcn_smfmac_f32_32x32x16_bf16:
    Opc = AMDGPU::V_SMFMAC_F32_32X32X16_BF16_e64;
    break;
  case Intrinsic::amdgcn_smfmac_i32_16x16x64_i8:
    Opc = AMDGPU::V_SMFMAC_I32_16X16X64_I8_e64;
    break;
  case Intrinsic::amdgcn_smfmac_i32_32x32x32_i8:
    Opc = AMDGPU::V_SMFMAC_I32_32X32X32_I8_e64;
    break;
  case Intrinsic::amdgcn_smfmac_f32_16x16x64_bf8_bf8:
    Opc = AMDGPU::V_SMFMAC_F32_16X16X64_BF8_BF8_e64;
    break;
  case Intrinsic::amdgcn_smfmac_f32_16x16x64_bf8_fp8:
    Opc = AMDGPU::V_SMFMAC_F32_16X16X64_BF8_FP8_e64;
    break;
  case Intrinsic::amdgcn_smfmac_f32_16x16x64_fp8_bf8:
    Opc = AMDGPU::V_SMFMAC_F32_16X16X64_FP8_BF8_e64;
    break;
  case Intrinsic::amdgcn_smfmac_f32_16x16x64_fp8_fp8:
    Opc = AMDGPU::V_SMFMAC_F32_16X16X64_FP8_FP8_e64;
    break;
  case Intrinsic::amdgcn_smfmac_f32_32x32x32_bf8_bf8:
    Opc = AMDGPU::V_SMFMAC_F32_32X32X32_BF8_BF8_e64;
    break;
  case Intrinsic::amdgcn_smfmac_f32_32x32x32_bf8_fp8:
    Opc = AMDGPU::V_SMFMAC_F32_32X32X32_BF8_FP8_e64;
    break;
  case Intrinsic::amdgcn_smfmac_f32_32x32x32_fp8_bf8:
    Opc = AMDGPU::V_SMFMAC_F32_32X32X32_FP8_BF8_e64;
    break;
  case Intrinsic::amdgcn_smfmac_f32_32x32x32_fp8_fp8:
    Opc = AMDGPU::V_SMFMAC_F32_32X32X32_FP8_FP8_e64;
    break;
  case Intrinsic::amdgcn_smfmac_f32_16x16x64_f16:
    Opc = AMDGPU::V_SMFMAC_F32_16X16X64_F16_e64;
    break;
  case Intrinsic::amdgcn_smfmac_f32_32x32x32_f16:
    Opc = AMDGPU::V_SMFMAC_F32_32X32X32_F16_e64;
    break;
  case Intrinsic::amdgcn_smfmac_f32_16x16x64_bf16:
    Opc = AMDGPU::V_SMFMAC_F32_16X16X64_BF16_e64;
    break;
  case Intrinsic::amdgcn_smfmac_f32_32x32x32_bf16:
    Opc = AMDGPU::V_SMFMAC_F32_32X32X32_BF16_e64;
    break;
  case Intrinsic::amdgcn_smfmac_i32_16x16x128_i8:
    Opc = AMDGPU::V_SMFMAC_I32_16X16X128_I8_e64;
    break;
  case Intrinsic::amdgcn_smfmac_i32_32x32x64_i8:
    Opc = AMDGPU::V_SMFMAC_I32_32X32X64_I8_e64;
    break;
  case Intrinsic::amdgcn_smfmac_f32_16x16x128_bf8_bf8:
    Opc = AMDGPU::V_SMFMAC_F32_16X16X128_BF8_BF8_e64;
    break;
  case Intrinsic::amdgcn_smfmac_f32_16x16x128_bf8_fp8:
    Opc = AMDGPU::V_SMFMAC_F32_16X16X128_BF8_FP8_e64;
    break;
  case Intrinsic::amdgcn_smfmac_f32_16x16x128_fp8_bf8:
    Opc = AMDGPU::V_SMFMAC_F32_16X16X128_FP8_BF8_e64;
    break;
  case Intrinsic::amdgcn_smfmac_f32_16x16x128_fp8_fp8:
    Opc = AMDGPU::V_SMFMAC_F32_16X16X128_FP8_FP8_e64;
    break;
  case Intrinsic::amdgcn_smfmac_f32_32x32x64_bf8_bf8:
    Opc = AMDGPU::V_SMFMAC_F32_32X32X64_BF8_BF8_e64;
    break;
  case Intrinsic::amdgcn_smfmac_f32_32x32x64_bf8_fp8:
    Opc = AMDGPU::V_SMFMAC_F32_32X32X64_BF8_FP8_e64;
    break;
  case Intrinsic::amdgcn_smfmac_f32_32x32x64_fp8_bf8:
    Opc = AMDGPU::V_SMFMAC_F32_32X32X64_FP8_BF8_e64;
    break;
  case Intrinsic::amdgcn_smfmac_f32_32x32x64_fp8_fp8:
    Opc = AMDGPU::V_SMFMAC_F32_32X32X64_FP8_FP8_e64;
    break;
  default:
    llvm_unreachable("unhandled smfmac intrinsic");
  }

  auto VDst_In = MI.getOperand(4);

  MI.setDesc(TII.get(Opc));
  MI.removeOperand(4); // VDst_In
  MI.removeOperand(1); // Intrinsic ID
  MI.addOperand(VDst_In); // Readd VDst_In to the end
  MI.addImplicitDefUseOperands(*MI.getMF());
  const MCInstrDesc &MCID = MI.getDesc();
  if (MCID.getOperandConstraint(0, MCOI::EARLY_CLOBBER) != -1) {
    MI.getOperand(0).setIsEarlyClobber(true);
  }
  return true;
}

bool AMDGPUInstructionSelector::selectPermlaneSwapIntrin(
    MachineInstr &MI, Intrinsic::ID IntrID) const {
  if (IntrID == Intrinsic::amdgcn_permlane16_swap &&
      !Subtarget->hasPermlane16Swap())
    return false;
  if (IntrID == Intrinsic::amdgcn_permlane32_swap &&
      !Subtarget->hasPermlane32Swap())
    return false;

  unsigned Opcode = IntrID == Intrinsic::amdgcn_permlane16_swap
                        ? AMDGPU::V_PERMLANE16_SWAP_B32_e64
                        : AMDGPU::V_PERMLANE32_SWAP_B32_e64;

  MI.removeOperand(2);
  MI.setDesc(TII.get(Opcode));
  MI.addOperand(*MF, MachineOperand::CreateReg(AMDGPU::EXEC, false, true));

  MachineOperand &FI = MI.getOperand(4);
  FI.setImm(FI.getImm() ? AMDGPU::DPP::DPP_FI_1 : AMDGPU::DPP::DPP_FI_0);

  return constrainSelectedInstRegOperands(MI, TII, TRI, RBI);
}

bool AMDGPUInstructionSelector::selectWaveAddress(MachineInstr &MI) const {
  Register DstReg = MI.getOperand(0).getReg();
  Register SrcReg = MI.getOperand(1).getReg();
  const RegisterBank *DstRB = RBI.getRegBank(DstReg, *MRI, TRI);
  const bool IsVALU = DstRB->getID() == AMDGPU::VGPRRegBankID;
  MachineBasicBlock *MBB = MI.getParent();
  const DebugLoc &DL = MI.getDebugLoc();

  if (IsVALU) {
    BuildMI(*MBB, MI, DL, TII.get(AMDGPU::V_LSHRREV_B32_e64), DstReg)
      .addImm(Subtarget->getWavefrontSizeLog2())
      .addReg(SrcReg);
  } else {
    BuildMI(*MBB, MI, DL, TII.get(AMDGPU::S_LSHR_B32), DstReg)
      .addReg(SrcReg)
      .addImm(Subtarget->getWavefrontSizeLog2())
      .setOperandDead(3); // Dead scc
  }

  const TargetRegisterClass &RC =
      IsVALU ? AMDGPU::VGPR_32RegClass : AMDGPU::SReg_32RegClass;
  if (!RBI.constrainGenericRegister(DstReg, RC, *MRI))
    return false;

  MI.eraseFromParent();
  return true;
}

bool AMDGPUInstructionSelector::selectWaveShuffleIntrin(
    MachineInstr &MI) const {
  assert(MI.getNumOperands() == 4);
  MachineBasicBlock *MBB = MI.getParent();
  const DebugLoc &DL = MI.getDebugLoc();

  Register DstReg = MI.getOperand(0).getReg();
  Register ValReg = MI.getOperand(2).getReg();
  Register IdxReg = MI.getOperand(3).getReg();

  const LLT DstTy = MRI->getType(DstReg);
  unsigned DstSize = DstTy.getSizeInBits();
  const RegisterBank *DstRB = RBI.getRegBank(DstReg, *MRI, TRI);
  const TargetRegisterClass *DstRC =
      TRI.getRegClassForSizeOnBank(DstSize, *DstRB);

  if (DstTy != LLT::scalar(32))
    return false;

  if (!Subtarget->supportsBPermute())
    return false;

  // If we can bpermute across the whole wave, then just do that
  if (Subtarget->supportsWaveWideBPermute()) {
    Register ShiftIdxReg = MRI->createVirtualRegister(DstRC);
    BuildMI(*MBB, MI, DL, TII.get(AMDGPU::V_LSHLREV_B32_e64), ShiftIdxReg)
        .addImm(2)
        .addReg(IdxReg);

    BuildMI(*MBB, MI, DL, TII.get(AMDGPU::DS_BPERMUTE_B32), DstReg)
        .addReg(ShiftIdxReg)
        .addReg(ValReg)
        .addImm(0);
  } else {
    // Otherwise, we need to make use of whole wave mode
    assert(Subtarget->isWave64());

    // Set inactive lanes to poison
    Register UndefValReg =
        MRI->createVirtualRegister(TRI.getRegClass(AMDGPU::SReg_32RegClassID));
    BuildMI(*MBB, MI, DL, TII.get(AMDGPU::IMPLICIT_DEF), UndefValReg);

    Register UndefExecReg = MRI->createVirtualRegister(
        TRI.getRegClass(AMDGPU::SReg_64_XEXECRegClassID));
    BuildMI(*MBB, MI, DL, TII.get(AMDGPU::IMPLICIT_DEF), UndefExecReg);

    Register PoisonValReg = MRI->createVirtualRegister(DstRC);
    BuildMI(*MBB, MI, DL, TII.get(AMDGPU::V_SET_INACTIVE_B32), PoisonValReg)
        .addImm(0)
        .addReg(ValReg)
        .addImm(0)
        .addReg(UndefValReg)
        .addReg(UndefExecReg);

    // ds_bpermute requires index to be multiplied by 4
    Register ShiftIdxReg = MRI->createVirtualRegister(DstRC);
    BuildMI(*MBB, MI, DL, TII.get(AMDGPU::V_LSHLREV_B32_e64), ShiftIdxReg)
        .addImm(2)
        .addReg(IdxReg);

    Register PoisonIdxReg = MRI->createVirtualRegister(DstRC);
    BuildMI(*MBB, MI, DL, TII.get(AMDGPU::V_SET_INACTIVE_B32), PoisonIdxReg)
        .addImm(0)
        .addReg(ShiftIdxReg)
        .addImm(0)
        .addReg(UndefValReg)
        .addReg(UndefExecReg);

    // Get permutation of each half, then we'll select which one to use
    Register SameSidePermReg = MRI->createVirtualRegister(DstRC);
    BuildMI(*MBB, MI, DL, TII.get(AMDGPU::DS_BPERMUTE_B32), SameSidePermReg)
        .addReg(PoisonIdxReg)
        .addReg(PoisonValReg)
        .addImm(0);

    Register SwappedValReg = MRI->createVirtualRegister(DstRC);
    BuildMI(*MBB, MI, DL, TII.get(AMDGPU::V_PERMLANE64_B32), SwappedValReg)
        .addReg(PoisonValReg);

    Register OppSidePermReg = MRI->createVirtualRegister(DstRC);
    BuildMI(*MBB, MI, DL, TII.get(AMDGPU::DS_BPERMUTE_B32), OppSidePermReg)
        .addReg(PoisonIdxReg)
        .addReg(SwappedValReg)
        .addImm(0);

    Register WWMSwapPermReg = MRI->createVirtualRegister(DstRC);
    BuildMI(*MBB, MI, DL, TII.get(AMDGPU::STRICT_WWM), WWMSwapPermReg)
        .addReg(OppSidePermReg);

    // Select which side to take the permute from
    // We can get away with only using mbcnt_lo here since we're only
    // trying to detect which side of 32 each lane is on, and mbcnt_lo
    // returns 32 for lanes 32-63.
    Register ThreadIDReg = MRI->createVirtualRegister(DstRC);
    BuildMI(*MBB, MI, DL, TII.get(AMDGPU::V_MBCNT_LO_U32_B32_e64), ThreadIDReg)
        .addImm(-1)
        .addImm(0);

    Register XORReg = MRI->createVirtualRegister(DstRC);
    BuildMI(*MBB, MI, DL, TII.get(AMDGPU::V_XOR_B32_e64), XORReg)
        .addReg(ThreadIDReg)
        .addReg(PoisonIdxReg);

    Register ANDReg = MRI->createVirtualRegister(DstRC);
    BuildMI(*MBB, MI, DL, TII.get(AMDGPU::V_AND_B32_e64), ANDReg)
        .addReg(XORReg)
        .addImm(32);

    Register CompareReg = MRI->createVirtualRegister(
        TRI.getRegClass(AMDGPU::SReg_64_XEXECRegClassID));
    BuildMI(*MBB, MI, DL, TII.get(AMDGPU::V_CMP_EQ_U32_e64), CompareReg)
        .addReg(ANDReg)
        .addImm(0);

    // Finally do the selection
    BuildMI(*MBB, MI, DL, TII.get(AMDGPU::V_CNDMASK_B32_e64), DstReg)
        .addImm(0)
        .addReg(WWMSwapPermReg)
        .addImm(0)
        .addReg(SameSidePermReg)
        .addReg(CompareReg);
  }

  MI.eraseFromParent();
  return true;
}

// Match BITOP3 operation and return a number of matched instructions plus
// truth table.
static std::pair<unsigned, uint8_t> BitOp3_Op(Register R,
                                              SmallVectorImpl<Register> &Src,
                                              const MachineRegisterInfo &MRI) {
  unsigned NumOpcodes = 0;
  uint8_t LHSBits, RHSBits;

  auto getOperandBits = [&Src, R, &MRI](Register Op, uint8_t &Bits) -> bool {
    // Define truth table given Src0, Src1, Src2 bits permutations:
    //                          0     0     0
    //                          0     0     1
    //                          0     1     0
    //                          0     1     1
    //                          1     0     0
    //                          1     0     1
    //                          1     1     0
    //                          1     1     1
    const uint8_t SrcBits[3] = { 0xf0, 0xcc, 0xaa };

    if (mi_match(Op, MRI, m_AllOnesInt())) {
      Bits = 0xff;
      return true;
    }
    if (mi_match(Op, MRI, m_ZeroInt())) {
      Bits = 0;
      return true;
    }

    for (unsigned I = 0; I < Src.size(); ++I) {
      // Try to find existing reused operand
      if (Src[I] == Op) {
        Bits = SrcBits[I];
        return true;
      }
      // Try to replace parent operator
      if (Src[I] == R) {
        Bits = SrcBits[I];
        Src[I] = Op;
        return true;
      }
    }

    if (Src.size() == 3) {
      // No room left for operands. Try one last time, there can be a 'not' of
      // one of our source operands. In this case we can compute the bits
      // without growing Src vector.
      Register LHS;
      if (mi_match(Op, MRI, m_Not(m_Reg(LHS)))) {
        LHS = getSrcRegIgnoringCopies(LHS, MRI);
        for (unsigned I = 0; I < Src.size(); ++I) {
          if (Src[I] == LHS) {
            Bits = ~SrcBits[I];
            return true;
          }
        }
      }

      return false;
    }

    Bits = SrcBits[Src.size()];
    Src.push_back(Op);
    return true;
  };

  MachineInstr *MI = MRI.getVRegDef(R);
  switch (MI->getOpcode()) {
  case TargetOpcode::G_AND:
  case TargetOpcode::G_OR:
  case TargetOpcode::G_XOR: {
    Register LHS = getSrcRegIgnoringCopies(MI->getOperand(1).getReg(), MRI);
    Register RHS = getSrcRegIgnoringCopies(MI->getOperand(2).getReg(), MRI);

    SmallVector<Register, 3> Backup(Src.begin(), Src.end());
    if (!getOperandBits(LHS, LHSBits) ||
        !getOperandBits(RHS, RHSBits)) {
      Src = Backup;
      return std::make_pair(0, 0);
    }

    // Recursion is naturally limited by the size of the operand vector.
    auto Op = BitOp3_Op(LHS, Src, MRI);
    if (Op.first) {
      NumOpcodes += Op.first;
      LHSBits = Op.second;
    }

    Op = BitOp3_Op(RHS, Src, MRI);
    if (Op.first) {
      NumOpcodes += Op.first;
      RHSBits = Op.second;
    }
    break;
  }
  default:
    return std::make_pair(0, 0);
  }

  uint8_t TTbl;
  switch (MI->getOpcode()) {
  case TargetOpcode::G_AND:
    TTbl = LHSBits & RHSBits;
    break;
  case TargetOpcode::G_OR:
    TTbl = LHSBits | RHSBits;
    break;
  case TargetOpcode::G_XOR:
    TTbl = LHSBits ^ RHSBits;
    break;
  default:
    break;
  }

  return std::make_pair(NumOpcodes + 1, TTbl);
}

bool AMDGPUInstructionSelector::selectBITOP3(MachineInstr &MI) const {
  if (!Subtarget->hasBitOp3Insts())
    return false;

  Register DstReg = MI.getOperand(0).getReg();
  const RegisterBank *DstRB = RBI.getRegBank(DstReg, *MRI, TRI);
  const bool IsVALU = DstRB->getID() == AMDGPU::VGPRRegBankID;
  if (!IsVALU)
    return false;

  SmallVector<Register, 3> Src;
  uint8_t TTbl;
  unsigned NumOpcodes;

  std::tie(NumOpcodes, TTbl) = BitOp3_Op(DstReg, Src, *MRI);

  // Src.empty() case can happen if all operands are all zero or all ones.
  // Normally it shall be optimized out before reaching this.
  if (NumOpcodes < 2 || Src.empty())
    return false;

  const bool IsB32 = MRI->getType(DstReg) == LLT::scalar(32);
  if (NumOpcodes == 2 && IsB32) {
    // Avoid using BITOP3 for OR3, XOR3, AND_OR. This is not faster but makes
    // asm more readable. This cannot be modeled with AddedComplexity because
    // selector does not know how many operations did we match.
    if (mi_match(MI, *MRI, m_GXor(m_GXor(m_Reg(), m_Reg()), m_Reg())) ||
        mi_match(MI, *MRI, m_GOr(m_GOr(m_Reg(), m_Reg()), m_Reg())) ||
        mi_match(MI, *MRI, m_GOr(m_GAnd(m_Reg(), m_Reg()), m_Reg())))
      return false;
  } else if (NumOpcodes < 4) {
    // For a uniform case threshold should be higher to account for moves
    // between VGPRs and SGPRs. It needs one operand in a VGPR, rest two can be
    // in SGPRs and a readtfirstlane after.
    return false;
  }

  unsigned Opc = IsB32 ? AMDGPU::V_BITOP3_B32_e64 : AMDGPU::V_BITOP3_B16_e64;
  if (!IsB32 && STI.hasTrue16BitInsts())
    Opc = STI.useRealTrue16Insts() ? AMDGPU::V_BITOP3_B16_gfx1250_t16_e64
                                   : AMDGPU::V_BITOP3_B16_gfx1250_fake16_e64;
  unsigned CBL = STI.getConstantBusLimit(Opc);
  MachineBasicBlock *MBB = MI.getParent();
  const DebugLoc &DL = MI.getDebugLoc();

  for (unsigned I = 0; I < Src.size(); ++I) {
    const RegisterBank *RB = RBI.getRegBank(Src[I], *MRI, TRI);
    if (RB->getID() != AMDGPU::SGPRRegBankID)
      continue;
    if (CBL > 0) {
      --CBL;
      continue;
    }
    Register NewReg =  MRI->createVirtualRegister(&AMDGPU::VGPR_32RegClass);
    BuildMI(*MBB, MI, DL, TII.get(AMDGPU::COPY), NewReg)
        .addReg(Src[I]);
    Src[I] = NewReg;
  }

  // Last operand can be ignored, turning a ternary operation into a binary.
  // For example: (~a & b & c) | (~a & b & ~c) -> (~a & b). We can replace
  // 'c' with 'a' here without changing the answer. In some pathological
  // cases it should be possible to get an operation with a single operand
  // too if optimizer would not catch it.
  while (Src.size() < 3)
    Src.push_back(Src[0]);

  auto MIB = BuildMI(*MBB, MI, DL, TII.get(Opc), DstReg);
  if (!IsB32)
    MIB.addImm(0); // src_mod0
  MIB.addReg(Src[0]);
  if (!IsB32)
    MIB.addImm(0); // src_mod1
  MIB.addReg(Src[1]);
  if (!IsB32)
    MIB.addImm(0); // src_mod2
  MIB.addReg(Src[2])
     .addImm(TTbl);
  if (!IsB32)
    MIB.addImm(0); // op_sel

  constrainSelectedInstRegOperands(*MIB, TII, TRI, RBI);
  MI.eraseFromParent();

  return true;
}

bool AMDGPUInstructionSelector::selectStackRestore(MachineInstr &MI) const {
  Register SrcReg = MI.getOperand(0).getReg();
  if (!RBI.constrainGenericRegister(SrcReg, AMDGPU::SReg_32RegClass, *MRI))
    return false;

  MachineInstr *DefMI = MRI->getVRegDef(SrcReg);
  Register SP =
      Subtarget->getTargetLowering()->getStackPointerRegisterToSaveRestore();
  Register WaveAddr = getWaveAddress(DefMI);
  MachineBasicBlock *MBB = MI.getParent();
  const DebugLoc &DL = MI.getDebugLoc();

  if (!WaveAddr) {
    WaveAddr = MRI->createVirtualRegister(&AMDGPU::SReg_32RegClass);
    BuildMI(*MBB, MI, DL, TII.get(AMDGPU::S_LSHR_B32), WaveAddr)
      .addReg(SrcReg)
      .addImm(Subtarget->getWavefrontSizeLog2())
      .setOperandDead(3); // Dead scc
  }

  BuildMI(*MBB, &MI, DL, TII.get(AMDGPU::COPY), SP)
    .addReg(WaveAddr);

  MI.eraseFromParent();
  return true;
}

bool AMDGPUInstructionSelector::select(MachineInstr &I) {

  if (!I.isPreISelOpcode()) {
    if (I.isCopy())
      return selectCOPY(I);
    return true;
  }

  switch (I.getOpcode()) {
  case TargetOpcode::G_AND:
  case TargetOpcode::G_OR:
  case TargetOpcode::G_XOR:
    if (selectBITOP3(I))
      return true;
    if (selectImpl(I, *CoverageInfo))
      return true;
    return selectG_AND_OR_XOR(I);
  case TargetOpcode::G_ADD:
  case TargetOpcode::G_SUB:
  case TargetOpcode::G_PTR_ADD:
    if (selectImpl(I, *CoverageInfo))
      return true;
    return selectG_ADD_SUB(I);
  case TargetOpcode::G_UADDO:
  case TargetOpcode::G_USUBO:
  case TargetOpcode::G_UADDE:
  case TargetOpcode::G_USUBE:
    return selectG_UADDO_USUBO_UADDE_USUBE(I);
  case AMDGPU::G_AMDGPU_MAD_U64_U32:
  case AMDGPU::G_AMDGPU_MAD_I64_I32:
    return selectG_AMDGPU_MAD_64_32(I);
  case TargetOpcode::G_INTTOPTR:
  case TargetOpcode::G_BITCAST:
  case TargetOpcode::G_PTRTOINT:
  case TargetOpcode::G_FREEZE:
    return selectCOPY(I);
  case TargetOpcode::G_FNEG:
    if (selectImpl(I, *CoverageInfo))
      return true;
    return selectG_FNEG(I);
  case TargetOpcode::G_FABS:
    if (selectImpl(I, *CoverageInfo))
      return true;
    return selectG_FABS(I);
  case TargetOpcode::G_EXTRACT:
    return selectG_EXTRACT(I);
  case TargetOpcode::G_MERGE_VALUES:
  case TargetOpcode::G_CONCAT_VECTORS:
    return selectG_MERGE_VALUES(I);
  case TargetOpcode::G_UNMERGE_VALUES:
    return selectG_UNMERGE_VALUES(I);
  case TargetOpcode::G_BUILD_VECTOR:
  case TargetOpcode::G_BUILD_VECTOR_TRUNC:
    return selectG_BUILD_VECTOR(I);
  case TargetOpcode::G_IMPLICIT_DEF:
    return selectG_IMPLICIT_DEF(I);
  case TargetOpcode::G_INSERT:
    return selectG_INSERT(I);
  case TargetOpcode::G_INTRINSIC:
  case TargetOpcode::G_INTRINSIC_CONVERGENT:
    return selectG_INTRINSIC(I);
  case TargetOpcode::G_INTRINSIC_W_SIDE_EFFECTS:
  case TargetOpcode::G_INTRINSIC_CONVERGENT_W_SIDE_EFFECTS:
    return selectG_INTRINSIC_W_SIDE_EFFECTS(I);
  case TargetOpcode::G_ICMP:
  case TargetOpcode::G_FCMP:
    if (selectG_ICMP_or_FCMP(I))
      return true;
    return selectImpl(I, *CoverageInfo);
  case TargetOpcode::G_LOAD:
  case TargetOpcode::G_ZEXTLOAD:
  case TargetOpcode::G_SEXTLOAD:
  case TargetOpcode::G_STORE:
  case TargetOpcode::G_ATOMIC_CMPXCHG:
  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:
  case TargetOpcode::G_ATOMICRMW_UINC_WRAP:
  case TargetOpcode::G_ATOMICRMW_UDEC_WRAP:
  case TargetOpcode::G_ATOMICRMW_USUB_COND:
  case TargetOpcode::G_ATOMICRMW_USUB_SAT:
  case TargetOpcode::G_ATOMICRMW_FADD:
  case TargetOpcode::G_ATOMICRMW_FMIN:
  case TargetOpcode::G_ATOMICRMW_FMAX:
    return selectG_LOAD_STORE_ATOMICRMW(I);
  case TargetOpcode::G_SELECT:
    return selectG_SELECT(I);
  case TargetOpcode::G_TRUNC:
    return selectG_TRUNC(I);
  case TargetOpcode::G_SEXT:
  case TargetOpcode::G_ZEXT:
  case TargetOpcode::G_ANYEXT:
  case TargetOpcode::G_SEXT_INREG:
    // This is a workaround. For extension from type i1, `selectImpl()` uses
    // patterns from TD file and generates an illegal VGPR to SGPR COPY as type
    // i1 can only be hold in a SGPR class.
    if (MRI->getType(I.getOperand(1).getReg()) != LLT::scalar(1) &&
        selectImpl(I, *CoverageInfo))
      return true;
    return selectG_SZA_EXT(I);
  case TargetOpcode::G_FPEXT:
    if (selectG_FPEXT(I))
      return true;
    return selectImpl(I, *CoverageInfo);
  case TargetOpcode::G_BRCOND:
    return selectG_BRCOND(I);
  case TargetOpcode::G_GLOBAL_VALUE:
    return selectG_GLOBAL_VALUE(I);
  case TargetOpcode::G_PTRMASK:
    return selectG_PTRMASK(I);
  case TargetOpcode::G_EXTRACT_VECTOR_ELT:
    return selectG_EXTRACT_VECTOR_ELT(I);
  case TargetOpcode::G_INSERT_VECTOR_ELT:
    return selectG_INSERT_VECTOR_ELT(I);
  case AMDGPU::G_AMDGPU_INTRIN_IMAGE_LOAD:
  case AMDGPU::G_AMDGPU_INTRIN_IMAGE_LOAD_D16:
  case AMDGPU::G_AMDGPU_INTRIN_IMAGE_LOAD_NORET:
  case AMDGPU::G_AMDGPU_INTRIN_IMAGE_STORE:
  case AMDGPU::G_AMDGPU_INTRIN_IMAGE_STORE_D16: {
    const AMDGPU::ImageDimIntrinsicInfo *Intr =
        AMDGPU::getImageDimIntrinsicInfo(AMDGPU::getIntrinsicID(I));
    assert(Intr && "not an image intrinsic with image pseudo");
    return selectImageIntrinsic(I, Intr);
  }
  case AMDGPU::G_AMDGPU_BVH_DUAL_INTERSECT_RAY:
  case AMDGPU::G_AMDGPU_BVH_INTERSECT_RAY:
  case AMDGPU::G_AMDGPU_BVH8_INTERSECT_RAY:
    return selectBVHIntersectRayIntrinsic(I);
  case AMDGPU::G_SBFX:
  case AMDGPU::G_UBFX:
    return selectG_SBFX_UBFX(I);
  case AMDGPU::G_SI_CALL:
    I.setDesc(TII.get(AMDGPU::SI_CALL));
    return true;
  case AMDGPU::G_AMDGPU_WAVE_ADDRESS:
    return selectWaveAddress(I);
  case AMDGPU::G_AMDGPU_WHOLE_WAVE_FUNC_RETURN: {
    I.setDesc(TII.get(AMDGPU::SI_WHOLE_WAVE_FUNC_RETURN));
    return true;
  }
  case AMDGPU::G_STACKRESTORE:
    return selectStackRestore(I);
  case AMDGPU::G_PHI:
    return selectPHI(I);
  case AMDGPU::G_AMDGPU_COPY_SCC_VCC:
    return selectCOPY_SCC_VCC(I);
  case AMDGPU::G_AMDGPU_COPY_VCC_SCC:
    return selectCOPY_VCC_SCC(I);
  case AMDGPU::G_AMDGPU_READANYLANE:
    return selectReadAnyLane(I);
  case TargetOpcode::G_CONSTANT:
  case TargetOpcode::G_FCONSTANT:
  default:
    return selectImpl(I, *CoverageInfo);
  }
  return false;
}

InstructionSelector::ComplexRendererFns
AMDGPUInstructionSelector::selectVCSRC(MachineOperand &Root) const {
  return {{
      [=](MachineInstrBuilder &MIB) { MIB.add(Root); }
  }};

}

std::pair<Register, unsigned> AMDGPUInstructionSelector::selectVOP3ModsImpl(
    Register Src, bool IsCanonicalizing, bool AllowAbs, bool OpSel) const {
  unsigned Mods = 0;
  MachineInstr *MI = getDefIgnoringCopies(Src, *MRI);

  if (MI->getOpcode() == AMDGPU::G_FNEG) {
    Src = MI->getOperand(1).getReg();
    Mods |= SISrcMods::NEG;
    MI = getDefIgnoringCopies(Src, *MRI);
  } else if (MI->getOpcode() == AMDGPU::G_FSUB && IsCanonicalizing) {
    // Fold fsub [+-]0 into fneg. This may not have folded depending on the
    // denormal mode, but we're implicitly canonicalizing in a source operand.
    const ConstantFP *LHS =
        getConstantFPVRegVal(MI->getOperand(1).getReg(), *MRI);
    if (LHS && LHS->isZero()) {
      Mods |= SISrcMods::NEG;
      Src = MI->getOperand(2).getReg();
    }
  }

  if (AllowAbs && MI->getOpcode() == AMDGPU::G_FABS) {
    Src = MI->getOperand(1).getReg();
    Mods |= SISrcMods::ABS;
  }

  if (OpSel)
    Mods |= SISrcMods::OP_SEL_0;

  return std::pair(Src, Mods);
}

Register AMDGPUInstructionSelector::copyToVGPRIfSrcFolded(
    Register Src, unsigned Mods, MachineOperand Root, MachineInstr *InsertPt,
    bool ForceVGPR) const {
  if ((Mods != 0 || ForceVGPR) &&
      RBI.getRegBank(Src, *MRI, TRI)->getID() != AMDGPU::VGPRRegBankID) {

    // If we looked through copies to find source modifiers on an SGPR operand,
    // we now have an SGPR register source. To avoid potentially violating the
    // constant bus restriction, we need to insert a copy to a VGPR.
    Register VGPRSrc = MRI->cloneVirtualRegister(Root.getReg());
    BuildMI(*InsertPt->getParent(), InsertPt, InsertPt->getDebugLoc(),
            TII.get(AMDGPU::COPY), VGPRSrc)
        .addReg(Src);
    Src = VGPRSrc;
  }

  return Src;
}

///
/// This will select either an SGPR or VGPR operand and will save us from
/// having to write an extra tablegen pattern.
InstructionSelector::ComplexRendererFns
AMDGPUInstructionSelector::selectVSRC0(MachineOperand &Root) const {
  return {{
      [=](MachineInstrBuilder &MIB) { MIB.add(Root); }
  }};
}

InstructionSelector::ComplexRendererFns
AMDGPUInstructionSelector::selectVOP3Mods0(MachineOperand &Root) const {
  Register Src;
  unsigned Mods;
  std::tie(Src, Mods) = selectVOP3ModsImpl(Root.getReg());

  return {{
      [=](MachineInstrBuilder &MIB) {
        MIB.addReg(copyToVGPRIfSrcFolded(Src, Mods, Root, MIB));
      },
      [=](MachineInstrBuilder &MIB) { MIB.addImm(Mods); }, // src0_mods
      [=](MachineInstrBuilder &MIB) { MIB.addImm(0); },    // clamp
      [=](MachineInstrBuilder &MIB) { MIB.addImm(0); }     // omod
  }};
}

InstructionSelector::ComplexRendererFns
AMDGPUInstructionSelector::selectVOP3BMods0(MachineOperand &Root) const {
  Register Src;
  unsigned Mods;
  std::tie(Src, Mods) = selectVOP3ModsImpl(Root.getReg(),
                                           /*IsCanonicalizing=*/true,
                                           /*AllowAbs=*/false);

  return {{
      [=](MachineInstrBuilder &MIB) {
        MIB.addReg(copyToVGPRIfSrcFolded(Src, Mods, Root, MIB));
      },
      [=](MachineInstrBuilder &MIB) { MIB.addImm(Mods); }, // src0_mods
      [=](MachineInstrBuilder &MIB) { MIB.addImm(0); },    // clamp
      [=](MachineInstrBuilder &MIB) { MIB.addImm(0); }     // omod
  }};
}

InstructionSelector::ComplexRendererFns
AMDGPUInstructionSelector::selectVOP3OMods(MachineOperand &Root) const {
  return {{
      [=](MachineInstrBuilder &MIB) { MIB.add(Root); },
      [=](MachineInstrBuilder &MIB) { MIB.addImm(0); }, // clamp
      [=](MachineInstrBuilder &MIB) { MIB.addImm(0); }  // omod
  }};
}

InstructionSelector::ComplexRendererFns
AMDGPUInstructionSelector::selectVOP3Mods(MachineOperand &Root) const {
  Register Src;
  unsigned Mods;
  std::tie(Src, Mods) = selectVOP3ModsImpl(Root.getReg());

  return {{
      [=](MachineInstrBuilder &MIB) {
        MIB.addReg(copyToVGPRIfSrcFolded(Src, Mods, Root, MIB));
      },
      [=](MachineInstrBuilder &MIB) { MIB.addImm(Mods); } // src_mods
  }};
}

InstructionSelector::ComplexRendererFns
AMDGPUInstructionSelector::selectVOP3ModsNonCanonicalizing(
    MachineOperand &Root) const {
  Register Src;
  unsigned Mods;
  std::tie(Src, Mods) =
      selectVOP3ModsImpl(Root.getReg(), /*IsCanonicalizing=*/false);

  return {{
      [=](MachineInstrBuilder &MIB) {
        MIB.addReg(copyToVGPRIfSrcFolded(Src, Mods, Root, MIB));
      },
      [=](MachineInstrBuilder &MIB) { MIB.addImm(Mods); } // src_mods
  }};
}

InstructionSelector::ComplexRendererFns
AMDGPUInstructionSelector::selectVOP3BMods(MachineOperand &Root) const {
  Register Src;
  unsigned Mods;
  std::tie(Src, Mods) =
      selectVOP3ModsImpl(Root.getReg(), /*IsCanonicalizing=*/true,
                         /*AllowAbs=*/false);

  return {{
      [=](MachineInstrBuilder &MIB) {
        MIB.addReg(copyToVGPRIfSrcFolded(Src, Mods, Root, MIB));
      },
      [=](MachineInstrBuilder &MIB) { MIB.addImm(Mods); } // src_mods
  }};
}

InstructionSelector::ComplexRendererFns
AMDGPUInstructionSelector::selectVOP3NoMods(MachineOperand &Root) const {
  Register Reg = Root.getReg();
  const MachineInstr *Def = getDefIgnoringCopies(Reg, *MRI);
  if (Def->getOpcode() == AMDGPU::G_FNEG || Def->getOpcode() == AMDGPU::G_FABS)
    return {};
  return {{
      [=](MachineInstrBuilder &MIB) { MIB.addReg(Reg); },
  }};
}

enum class SrcStatus {
  IS_SAME,
  IS_UPPER_HALF,
  IS_LOWER_HALF,
  IS_UPPER_HALF_NEG,
  // This means current op = [op_upper, op_lower] and src = -op_lower.
  IS_LOWER_HALF_NEG,
  IS_HI_NEG,
  // This means current op = [op_upper, op_lower] and src = [op_upper,
  // -op_lower].
  IS_LO_NEG,
  IS_BOTH_NEG,
  INVALID,
  NEG_START = IS_UPPER_HALF_NEG,
  NEG_END = IS_BOTH_NEG,
  HALF_START = IS_UPPER_HALF,
  HALF_END = IS_LOWER_HALF_NEG
};
/// Test if the MI is truncating to half, such as `%reg0:n = G_TRUNC %reg1:2n`
static bool isTruncHalf(const MachineInstr *MI,
                        const MachineRegisterInfo &MRI) {
  if (MI->getOpcode() != AMDGPU::G_TRUNC)
    return false;

  unsigned DstSize = MRI.getType(MI->getOperand(0).getReg()).getSizeInBits();
  unsigned SrcSize = MRI.getType(MI->getOperand(1).getReg()).getSizeInBits();
  return DstSize * 2 == SrcSize;
}

/// Test if the MI is logic shift right with half bits,
/// such as `%reg0:2n =G_LSHR %reg1:2n, CONST(n)`
static bool isLshrHalf(const MachineInstr *MI, const MachineRegisterInfo &MRI) {
  if (MI->getOpcode() != AMDGPU::G_LSHR)
    return false;

  Register ShiftSrc;
  std::optional<ValueAndVReg> ShiftAmt;
  if (mi_match(MI->getOperand(0).getReg(), MRI,
               m_GLShr(m_Reg(ShiftSrc), m_GCst(ShiftAmt)))) {
    unsigned SrcSize = MRI.getType(MI->getOperand(1).getReg()).getSizeInBits();
    unsigned Shift = ShiftAmt->Value.getZExtValue();
    return Shift * 2 == SrcSize;
  }
  return false;
}

/// Test if the MI is shift left with half bits,
/// such as `%reg0:2n =G_SHL %reg1:2n, CONST(n)`
static bool isShlHalf(const MachineInstr *MI, const MachineRegisterInfo &MRI) {
  if (MI->getOpcode() != AMDGPU::G_SHL)
    return false;

  Register ShiftSrc;
  std::optional<ValueAndVReg> ShiftAmt;
  if (mi_match(MI->getOperand(0).getReg(), MRI,
               m_GShl(m_Reg(ShiftSrc), m_GCst(ShiftAmt)))) {
    unsigned SrcSize = MRI.getType(MI->getOperand(1).getReg()).getSizeInBits();
    unsigned Shift = ShiftAmt->Value.getZExtValue();
    return Shift * 2 == SrcSize;
  }
  return false;
}

/// Test function, if the MI is `%reg0:n, %reg1:n = G_UNMERGE_VALUES %reg2:2n`
static bool isUnmergeHalf(const MachineInstr *MI,
                          const MachineRegisterInfo &MRI) {
  if (MI->getOpcode() != AMDGPU::G_UNMERGE_VALUES)
    return false;
  return MI->getNumOperands() == 3 && MI->getOperand(0).isDef() &&
         MI->getOperand(1).isDef() && !MI->getOperand(2).isDef();
}

enum class TypeClass { VECTOR_OF_TWO, SCALAR, NONE_OF_LISTED };

static TypeClass isVectorOfTwoOrScalar(Register Reg,
                                       const MachineRegisterInfo &MRI) {
  LLT OpTy = MRI.getType(Reg);
  if (OpTy.isScalar())
    return TypeClass::SCALAR;
  if (OpTy.isVector() && OpTy.getNumElements() == 2)
    return TypeClass::VECTOR_OF_TWO;
  return TypeClass::NONE_OF_LISTED;
}

static SrcStatus getNegStatus(Register Reg, SrcStatus S,
                              const MachineRegisterInfo &MRI) {
  TypeClass NegType = isVectorOfTwoOrScalar(Reg, MRI);
  if (NegType != TypeClass::VECTOR_OF_TWO && NegType != TypeClass::SCALAR)
    return SrcStatus::INVALID;

  switch (S) {
  case SrcStatus::IS_SAME:
    if (NegType == TypeClass::VECTOR_OF_TWO) {
      // Vector of 2:
      // [SrcHi, SrcLo]   = [CurrHi, CurrLo]
      // [CurrHi, CurrLo] = neg [OpHi, OpLo](2 x Type)
      // [CurrHi, CurrLo] = [-OpHi, -OpLo](2 x Type)
      // [SrcHi, SrcLo]   = [-OpHi, -OpLo]
      return SrcStatus::IS_BOTH_NEG;
    }
    if (NegType == TypeClass::SCALAR) {
      // Scalar:
      // [SrcHi, SrcLo]   = [CurrHi, CurrLo]
      // [CurrHi, CurrLo] = neg [OpHi, OpLo](Type)
      // [CurrHi, CurrLo] = [-OpHi, OpLo](Type)
      // [SrcHi, SrcLo]   = [-OpHi, OpLo]
      return SrcStatus::IS_HI_NEG;
    }
    break;
  case SrcStatus::IS_HI_NEG:
    if (NegType == TypeClass::VECTOR_OF_TWO) {
      // Vector of 2:
      // [SrcHi, SrcLo]   = [-CurrHi, CurrLo]
      // [CurrHi, CurrLo] = neg [OpHi, OpLo](2 x Type)
      // [CurrHi, CurrLo] = [-OpHi, -OpLo](2 x Type)
      // [SrcHi, SrcLo]   = [-(-OpHi), -OpLo] = [OpHi, -OpLo]
      return SrcStatus::IS_LO_NEG;
    }
    if (NegType == TypeClass::SCALAR) {
      // Scalar:
      // [SrcHi, SrcLo]   = [-CurrHi, CurrLo]
      // [CurrHi, CurrLo] = neg [OpHi, OpLo](Type)
      // [CurrHi, CurrLo] = [-OpHi, OpLo](Type)
      // [SrcHi, SrcLo]   = [-(-OpHi), OpLo] = [OpHi, OpLo]
      return SrcStatus::IS_SAME;
    }
    break;
  case SrcStatus::IS_LO_NEG:
    if (NegType == TypeClass::VECTOR_OF_TWO) {
      // Vector of 2:
      // [SrcHi, SrcLo]   = [CurrHi, -CurrLo]
      // [CurrHi, CurrLo] = fneg [OpHi, OpLo](2 x Type)
      // [CurrHi, CurrLo] = [-OpHi, -OpLo](2 x Type)
      // [SrcHi, SrcLo]   = [-OpHi, -(-OpLo)] = [-OpHi, OpLo]
      return SrcStatus::IS_HI_NEG;
    }
    if (NegType == TypeClass::SCALAR) {
      // Scalar:
      // [SrcHi, SrcLo]   = [CurrHi, -CurrLo]
      // [CurrHi, CurrLo] = fneg [OpHi, OpLo](Type)
      // [CurrHi, CurrLo] = [-OpHi, OpLo](Type)
      // [SrcHi, SrcLo]   = [-OpHi, -OpLo]
      return SrcStatus::IS_BOTH_NEG;
    }
    break;
  case SrcStatus::IS_BOTH_NEG:
    if (NegType == TypeClass::VECTOR_OF_TWO) {
      // Vector of 2:
      // [SrcHi, SrcLo]   = [-CurrHi, -CurrLo]
      // [CurrHi, CurrLo] = fneg [OpHi, OpLo](2 x Type)
      // [CurrHi, CurrLo] = [-OpHi, -OpLo](2 x Type)
      // [SrcHi, SrcLo]   = [OpHi, OpLo]
      return SrcStatus::IS_SAME;
    }
    if (NegType == TypeClass::SCALAR) {
      // Scalar:
      // [SrcHi, SrcLo]   = [-CurrHi, -CurrLo]
      // [CurrHi, CurrLo] = fneg [OpHi, OpLo](Type)
      // [CurrHi, CurrLo] = [-OpHi, OpLo](Type)
      // [SrcHi, SrcLo]   = [OpHi, -OpLo]
      return SrcStatus::IS_LO_NEG;
    }
    break;
  case SrcStatus::IS_UPPER_HALF:
    // Vector of 2:
    // Src = CurrUpper
    // Curr = [CurrUpper, CurrLower]
    // [CurrUpper, CurrLower] = fneg [OpUpper, OpLower](2 x Type)
    // [CurrUpper, CurrLower] = [-OpUpper, -OpLower](2 x Type)
    // Src = -OpUpper
    //
    // Scalar:
    // Src = CurrUpper
    // Curr = [CurrUpper, CurrLower]
    // [CurrUpper, CurrLower] = fneg [OpUpper, OpLower](Type)
    // [CurrUpper, CurrLower] = [-OpUpper, OpLower](Type)
    // Src = -OpUpper
    return SrcStatus::IS_UPPER_HALF_NEG;
  case SrcStatus::IS_LOWER_HALF:
    if (NegType == TypeClass::VECTOR_OF_TWO) {
      // Vector of 2:
      // Src = CurrLower
      // Curr = [CurrUpper, CurrLower]
      // [CurrUpper, CurrLower] = fneg [OpUpper, OpLower](2 x Type)
      // [CurrUpper, CurrLower] = [-OpUpper, -OpLower](2 x Type)
      // Src = -OpLower
      return SrcStatus::IS_LOWER_HALF_NEG;
    }
    if (NegType == TypeClass::SCALAR) {
      // Scalar:
      // Src = CurrLower
      // Curr = [CurrUpper, CurrLower]
      // [CurrUpper, CurrLower] = fneg [OpUpper, OpLower](Type)
      // [CurrUpper, CurrLower] = [-OpUpper, OpLower](Type)
      // Src = OpLower
      return SrcStatus::IS_LOWER_HALF;
    }
    break;
  case SrcStatus::IS_UPPER_HALF_NEG:
    // Vector of 2:
    // Src = -CurrUpper
    // Curr = [CurrUpper, CurrLower]
    // [CurrUpper, CurrLower] = fneg [OpUpper, OpLower](2 x Type)
    // [CurrUpper, CurrLower] = [-OpUpper, -OpLower](2 x Type)
    // Src = -(-OpUpper) = OpUpper
    //
    // Scalar:
    // Src = -CurrUpper
    // Curr = [CurrUpper, CurrLower]
    // [CurrUpper, CurrLower] = fneg [OpUpper, OpLower](Type)
    // [CurrUpper, CurrLower] = [-OpUpper, OpLower](Type)
    // Src = -(-OpUpper) = OpUpper
    return SrcStatus::IS_UPPER_HALF;
  case SrcStatus::IS_LOWER_HALF_NEG:
    if (NegType == TypeClass::VECTOR_OF_TWO) {
      // Vector of 2:
      // Src = -CurrLower
      // Curr = [CurrUpper, CurrLower]
      // [CurrUpper, CurrLower] = fneg [OpUpper, OpLower](2 x Type)
      // [CurrUpper, CurrLower] = [-OpUpper, -OpLower](2 x Type)
      // Src = -(-OpLower) = OpLower
      return SrcStatus::IS_LOWER_HALF;
    }
    if (NegType == TypeClass::SCALAR) {
      // Scalar:
      // Src = -CurrLower
      // Curr = [CurrUpper, CurrLower]
      // [CurrUpper, CurrLower] = fneg [OpUpper, OpLower](Type)
      // [CurrUpper, CurrLower] = [-OpUpper, OpLower](Type)
      // Src = -OpLower
      return SrcStatus::IS_LOWER_HALF_NEG;
    }
    break;
  default:
    break;
  }
  llvm_unreachable("unexpected SrcStatus & NegType combination");
}

static std::optional<std::pair<Register, SrcStatus>>
calcNextStatus(std::pair<Register, SrcStatus> Curr,
               const MachineRegisterInfo &MRI) {
  const MachineInstr *MI = MRI.getVRegDef(Curr.first);

  unsigned Opc = MI->getOpcode();

  // Handle general Opc cases.
  switch (Opc) {
  case AMDGPU::G_BITCAST:
    return std::optional<std::pair<Register, SrcStatus>>(
        {MI->getOperand(1).getReg(), Curr.second});
  case AMDGPU::COPY:
    if (MI->getOperand(1).getReg().isPhysical())
      return std::nullopt;
    return std::optional<std::pair<Register, SrcStatus>>(
        {MI->getOperand(1).getReg(), Curr.second});
  case AMDGPU::G_FNEG: {
    SrcStatus Stat = getNegStatus(Curr.first, Curr.second, MRI);
    if (Stat == SrcStatus::INVALID)
      return std::nullopt;
    return std::optional<std::pair<Register, SrcStatus>>(
        {MI->getOperand(1).getReg(), Stat});
  }
  default:
    break;
  }

  // Calc next Stat from current Stat.
  switch (Curr.second) {
  case SrcStatus::IS_SAME:
    if (isTruncHalf(MI, MRI))
      return std::optional<std::pair<Register, SrcStatus>>(
          {MI->getOperand(1).getReg(), SrcStatus::IS_LOWER_HALF});
    else if (isUnmergeHalf(MI, MRI)) {
      if (Curr.first == MI->getOperand(0).getReg())
        return std::optional<std::pair<Register, SrcStatus>>(
            {MI->getOperand(2).getReg(), SrcStatus::IS_LOWER_HALF});
      return std::optional<std::pair<Register, SrcStatus>>(
          {MI->getOperand(2).getReg(), SrcStatus::IS_UPPER_HALF});
    }
    break;
  case SrcStatus::IS_HI_NEG:
    if (isTruncHalf(MI, MRI)) {
      // [SrcHi, SrcLo]   = [-CurrHi, CurrLo]
      // [CurrHi, CurrLo] = trunc [OpUpper, OpLower] = OpLower
      //                  = [OpLowerHi, OpLowerLo]
      // Src = [SrcHi, SrcLo] = [-CurrHi, CurrLo]
      //     = [-OpLowerHi, OpLowerLo]
      //     = -OpLower
      return std::optional<std::pair<Register, SrcStatus>>(
          {MI->getOperand(1).getReg(), SrcStatus::IS_LOWER_HALF_NEG});
    }
    if (isUnmergeHalf(MI, MRI)) {
      if (Curr.first == MI->getOperand(0).getReg())
        return std::optional<std::pair<Register, SrcStatus>>(
            {MI->getOperand(2).getReg(), SrcStatus::IS_LOWER_HALF_NEG});
      return std::optional<std::pair<Register, SrcStatus>>(
          {MI->getOperand(2).getReg(), SrcStatus::IS_UPPER_HALF_NEG});
    }
    break;
  case SrcStatus::IS_UPPER_HALF:
    if (isShlHalf(MI, MRI))
      return std::optional<std::pair<Register, SrcStatus>>(
          {MI->getOperand(1).getReg(), SrcStatus::IS_LOWER_HALF});
    break;
  case SrcStatus::IS_LOWER_HALF:
    if (isLshrHalf(MI, MRI))
      return std::optional<std::pair<Register, SrcStatus>>(
          {MI->getOperand(1).getReg(), SrcStatus::IS_UPPER_HALF});
    break;
  case SrcStatus::IS_UPPER_HALF_NEG:
    if (isShlHalf(MI, MRI))
      return std::optional<std::pair<Register, SrcStatus>>(
          {MI->getOperand(1).getReg(), SrcStatus::IS_LOWER_HALF_NEG});
    break;
  case SrcStatus::IS_LOWER_HALF_NEG:
    if (isLshrHalf(MI, MRI))
      return std::optional<std::pair<Register, SrcStatus>>(
          {MI->getOperand(1).getReg(), SrcStatus::IS_UPPER_HALF_NEG});
    break;
  default:
    break;
  }
  return std::nullopt;
}

/// This is used to control valid status that current MI supports. For example,
/// non floating point intrinsic such as @llvm.amdgcn.sdot2 does not support NEG
/// bit on VOP3P.
/// The class can be further extended to recognize support on SEL, NEG, ABS bit
/// for different MI on different arch
class SearchOptions {
private:
  bool HasNeg = false;
  // Assume all complex pattern of VOP3P have opsel.
  bool HasOpsel = true;

public:
  SearchOptions(Register Reg, const MachineRegisterInfo &MRI) {
    const MachineInstr *MI = MRI.getVRegDef(Reg);
    unsigned Opc = MI->getOpcode();

    if (Opc < TargetOpcode::GENERIC_OP_END) {
      // Keep same for generic op.
      HasNeg = true;
    } else if (Opc == TargetOpcode::G_INTRINSIC) {
      Intrinsic::ID IntrinsicID = cast<GIntrinsic>(*MI).getIntrinsicID();
      // Only float point intrinsic has neg & neg_hi bits.
      if (IntrinsicID == Intrinsic::amdgcn_fdot2)
        HasNeg = true;
    }
  }
  bool checkOptions(SrcStatus Stat) const {
    if (!HasNeg &&
        (Stat >= SrcStatus::NEG_START && Stat <= SrcStatus::NEG_END)) {
      return false;
    }
    if (!HasOpsel &&
        (Stat >= SrcStatus::HALF_START && Stat <= SrcStatus::HALF_END)) {
      return false;
    }
    return true;
  }
};

static SmallVector<std::pair<Register, SrcStatus>>
getSrcStats(Register Reg, const MachineRegisterInfo &MRI, SearchOptions SO,
            int MaxDepth = 3) {
  int Depth = 0;
  auto Curr = calcNextStatus({Reg, SrcStatus::IS_SAME}, MRI);
  SmallVector<std::pair<Register, SrcStatus>> Statlist;

  while (Depth <= MaxDepth && Curr.has_value()) {
    Depth++;
    if (SO.checkOptions(Curr.value().second))
      Statlist.push_back(Curr.value());
    Curr = calcNextStatus(Curr.value(), MRI);
  }

  return Statlist;
}

static std::pair<Register, SrcStatus>
getLastSameOrNeg(Register Reg, const MachineRegisterInfo &MRI, SearchOptions SO,
                 int MaxDepth = 3) {
  int Depth = 0;
  std::pair<Register, SrcStatus> LastSameOrNeg = {Reg, SrcStatus::IS_SAME};
  auto Curr = calcNextStatus(LastSameOrNeg, MRI);

  while (Depth <= MaxDepth && Curr.has_value()) {
    Depth++;
    SrcStatus Stat = Curr.value().second;
    if (SO.checkOptions(Stat)) {
      if (Stat == SrcStatus::IS_SAME || Stat == SrcStatus::IS_HI_NEG ||
          Stat == SrcStatus::IS_LO_NEG || Stat == SrcStatus::IS_BOTH_NEG)
        LastSameOrNeg = Curr.value();
    }
    Curr = calcNextStatus(Curr.value(), MRI);
  }

  return LastSameOrNeg;
}

static bool isSameBitWidth(Register Reg1, Register Reg2,
                           const MachineRegisterInfo &MRI) {
  unsigned Width1 = MRI.getType(Reg1).getSizeInBits();
  unsigned Width2 = MRI.getType(Reg2).getSizeInBits();
  return Width1 == Width2;
}

static unsigned updateMods(SrcStatus HiStat, SrcStatus LoStat, unsigned Mods) {
  // SrcStatus::IS_LOWER_HALF remain 0.
  if (HiStat == SrcStatus::IS_UPPER_HALF_NEG) {
    Mods ^= SISrcMods::NEG_HI;
    Mods |= SISrcMods::OP_SEL_1;
  } else if (HiStat == SrcStatus::IS_UPPER_HALF)
    Mods |= SISrcMods::OP_SEL_1;
  else if (HiStat == SrcStatus::IS_LOWER_HALF_NEG)
    Mods ^= SISrcMods::NEG_HI;
  else if (HiStat == SrcStatus::IS_HI_NEG)
    Mods ^= SISrcMods::NEG_HI;

  if (LoStat == SrcStatus::IS_UPPER_HALF_NEG) {
    Mods ^= SISrcMods::NEG;
    Mods |= SISrcMods::OP_SEL_0;
  } else if (LoStat == SrcStatus::IS_UPPER_HALF)
    Mods |= SISrcMods::OP_SEL_0;
  else if (LoStat == SrcStatus::IS_LOWER_HALF_NEG)
    Mods |= SISrcMods::NEG;
  else if (LoStat == SrcStatus::IS_HI_NEG)
    Mods ^= SISrcMods::NEG;

  return Mods;
}

static bool isValidToPack(SrcStatus HiStat, SrcStatus LoStat, Register NewReg,
                          Register RootReg, const SIInstrInfo &TII,
                          const MachineRegisterInfo &MRI) {
  auto IsHalfState = [](SrcStatus S) {
    return S == SrcStatus::IS_UPPER_HALF || S == SrcStatus::IS_UPPER_HALF_NEG ||
           S == SrcStatus::IS_LOWER_HALF || S == SrcStatus::IS_LOWER_HALF_NEG;
  };
  return isSameBitWidth(NewReg, RootReg, MRI) && IsHalfState(LoStat) &&
         IsHalfState(HiStat);
}

std::pair<Register, unsigned> AMDGPUInstructionSelector::selectVOP3PModsImpl(
    Register RootReg, const MachineRegisterInfo &MRI, bool IsDOT) const {
  unsigned Mods = 0;
  // No modification if Root type is not form of <2 x Type>.
  if (isVectorOfTwoOrScalar(RootReg, MRI) != TypeClass::VECTOR_OF_TWO) {
    Mods |= SISrcMods::OP_SEL_1;
    return {RootReg, Mods};
  }

  SearchOptions SO(RootReg, MRI);

  std::pair<Register, SrcStatus> Stat = getLastSameOrNeg(RootReg, MRI, SO);

  if (Stat.second == SrcStatus::IS_BOTH_NEG)
    Mods ^= (SISrcMods::NEG | SISrcMods::NEG_HI);
  else if (Stat.second == SrcStatus::IS_HI_NEG)
    Mods ^= SISrcMods::NEG_HI;
  else if (Stat.second == SrcStatus::IS_LO_NEG)
    Mods ^= SISrcMods::NEG;

  MachineInstr *MI = MRI.getVRegDef(Stat.first);

  if (MI->getOpcode() != AMDGPU::G_BUILD_VECTOR || MI->getNumOperands() != 3 ||
      (IsDOT && Subtarget->hasDOTOpSelHazard())) {
    Mods |= SISrcMods::OP_SEL_1;
    return {Stat.first, Mods};
  }

  SmallVector<std::pair<Register, SrcStatus>> StatlistHi =
      getSrcStats(MI->getOperand(2).getReg(), MRI, SO);

  if (StatlistHi.empty()) {
    Mods |= SISrcMods::OP_SEL_1;
    return {Stat.first, Mods};
  }

  SmallVector<std::pair<Register, SrcStatus>> StatlistLo =
      getSrcStats(MI->getOperand(1).getReg(), MRI, SO);

  if (StatlistLo.empty()) {
    Mods |= SISrcMods::OP_SEL_1;
    return {Stat.first, Mods};
  }

  for (int I = StatlistHi.size() - 1; I >= 0; I--) {
    for (int J = StatlistLo.size() - 1; J >= 0; J--) {
      if (StatlistHi[I].first == StatlistLo[J].first &&
          isValidToPack(StatlistHi[I].second, StatlistLo[J].second,
                        StatlistHi[I].first, RootReg, TII, MRI))
        return {StatlistHi[I].first,
                updateMods(StatlistHi[I].second, StatlistLo[J].second, Mods)};
    }
  }
  // Packed instructions do not have abs modifiers.
  Mods |= SISrcMods::OP_SEL_1;

  return {Stat.first, Mods};
}

// Removed unused function `getAllKindImm` to eliminate dead code.

static bool checkRB(Register Reg, unsigned int RBNo,
                    const AMDGPURegisterBankInfo &RBI,
                    const MachineRegisterInfo &MRI,
                    const TargetRegisterInfo &TRI) {
  const RegisterBank *RB = RBI.getRegBank(Reg, MRI, TRI);
  return RB->getID() == RBNo;
}

// This function is used to get the correct register bank for returned reg.
// Assume:
// 1. VOP3P is always legal for VGPR.
// 2. RootOp's regbank is legal.
// Thus
// 1. If RootOp is SGPR, then NewOp can be SGPR or VGPR.
// 2. If RootOp is VGPR, then NewOp must be VGPR.
static Register getLegalRegBank(Register NewReg, Register RootReg,
                                const AMDGPURegisterBankInfo &RBI,
                                MachineRegisterInfo &MRI,
                                const TargetRegisterInfo &TRI,
                                const SIInstrInfo &TII) {
  // RootOp can only be VGPR or SGPR (some hand written cases such as.
  // inst-select-ashr.v2s16.mir::ashr_v2s16_vs).
  if (checkRB(RootReg, AMDGPU::SGPRRegBankID, RBI, MRI, TRI) ||
      checkRB(NewReg, AMDGPU::VGPRRegBankID, RBI, MRI, TRI))
    return NewReg;

  MachineInstr *MI = MRI.getVRegDef(RootReg);
  if (MI->getOpcode() == AMDGPU::COPY && NewReg == MI->getOperand(1).getReg()) {
    // RootOp is VGPR, NewOp is not VGPR, but RootOp = COPY NewOp.
    return RootReg;
  }

  MachineBasicBlock *BB = MI->getParent();
  Register DstReg = MRI.cloneVirtualRegister(RootReg);

  MachineInstrBuilder MIB =
      BuildMI(*BB, MI, MI->getDebugLoc(), TII.get(AMDGPU::COPY), DstReg)
          .addReg(NewReg);

  // Only accept VGPR.
  return MIB->getOperand(0).getReg();
}

InstructionSelector::ComplexRendererFns
AMDGPUInstructionSelector::selectVOP3PRetHelper(MachineOperand &Root,
                                                bool IsDOT) const {
  MachineRegisterInfo &MRI = Root.getParent()->getMF()->getRegInfo();
  Register Reg;
  unsigned Mods;
  std::tie(Reg, Mods) = selectVOP3PModsImpl(Root.getReg(), MRI, IsDOT);

  Reg = getLegalRegBank(Reg, Root.getReg(), RBI, MRI, TRI, TII);
  return {{
      [=](MachineInstrBuilder &MIB) { MIB.addReg(Reg); },
      [=](MachineInstrBuilder &MIB) { MIB.addImm(Mods); } // src_mods
  }};
}

InstructionSelector::ComplexRendererFns
AMDGPUInstructionSelector::selectVOP3PMods(MachineOperand &Root) const {

  return selectVOP3PRetHelper(Root);
}

InstructionSelector::ComplexRendererFns
AMDGPUInstructionSelector::selectVOP3PModsDOT(MachineOperand &Root) const {

  return selectVOP3PRetHelper(Root, true);
}

InstructionSelector::ComplexRendererFns
AMDGPUInstructionSelector::selectWMMAOpSelVOP3PMods(
    MachineOperand &Root) const {
  assert((Root.isImm() && (Root.getImm() == -1 || Root.getImm() == 0)) &&
         "expected i1 value");
  unsigned Mods = SISrcMods::OP_SEL_1;
  if (Root.getImm() != 0)
    Mods |= SISrcMods::OP_SEL_0;

  return {{
      [=](MachineInstrBuilder &MIB) { MIB.addImm(Mods); } // src_mods
  }};
}

static Register buildRegSequence(SmallVectorImpl<Register> &Elts,
                                 MachineInstr *InsertPt,
                                 MachineRegisterInfo &MRI) {
  const TargetRegisterClass *DstRegClass;
  switch (Elts.size()) {
  case 8:
    DstRegClass = &AMDGPU::VReg_256RegClass;
    break;
  case 4:
    DstRegClass = &AMDGPU::VReg_128RegClass;
    break;
  case 2:
    DstRegClass = &AMDGPU::VReg_64RegClass;
    break;
  default:
    llvm_unreachable("unhandled Reg sequence size");
  }

  MachineIRBuilder B(*InsertPt);
  auto MIB = B.buildInstr(AMDGPU::REG_SEQUENCE)
                 .addDef(MRI.createVirtualRegister(DstRegClass));
  for (unsigned i = 0; i < Elts.size(); ++i) {
    MIB.addReg(Elts[i]);
    MIB.addImm(SIRegisterInfo::getSubRegFromChannel(i));
  }
  return MIB->getOperand(0).getReg();
}

static void selectWMMAModsNegAbs(unsigned ModOpcode, unsigned &Mods,
                                 SmallVectorImpl<Register> &Elts, Register &Src,
                                 MachineInstr *InsertPt,
                                 MachineRegisterInfo &MRI) {
  if (ModOpcode == TargetOpcode::G_FNEG) {
    Mods |= SISrcMods::NEG;
    // Check if all elements also have abs modifier
    SmallVector<Register, 8> NegAbsElts;
    for (auto El : Elts) {
      Register FabsSrc;
      if (!mi_match(El, MRI, m_GFabs(m_Reg(FabsSrc))))
        break;
      NegAbsElts.push_back(FabsSrc);
    }
    if (Elts.size() != NegAbsElts.size()) {
      // Neg
      Src = buildRegSequence(Elts, InsertPt, MRI);
    } else {
      // Neg and Abs
      Mods |= SISrcMods::NEG_HI;
      Src = buildRegSequence(NegAbsElts, InsertPt, MRI);
    }
  } else {
    assert(ModOpcode == TargetOpcode::G_FABS);
    // Abs
    Mods |= SISrcMods::NEG_HI;
    Src = buildRegSequence(Elts, InsertPt, MRI);
  }
}

InstructionSelector::ComplexRendererFns
AMDGPUInstructionSelector::selectWMMAModsF32NegAbs(MachineOperand &Root) const {
  Register Src = Root.getReg();
  unsigned Mods = SISrcMods::OP_SEL_1;
  SmallVector<Register, 8> EltsF32;

  if (GBuildVector *BV = dyn_cast<GBuildVector>(MRI->getVRegDef(Src))) {
    assert(BV->getNumSources() > 0);
    // Based on first element decide which mod we match, neg or abs
    MachineInstr *ElF32 = MRI->getVRegDef(BV->getSourceReg(0));
    unsigned ModOpcode = (ElF32->getOpcode() == AMDGPU::G_FNEG)
                             ? AMDGPU::G_FNEG
                             : AMDGPU::G_FABS;
    for (unsigned i = 0; i < BV->getNumSources(); ++i) {
      ElF32 = MRI->getVRegDef(BV->getSourceReg(i));
      if (ElF32->getOpcode() != ModOpcode)
        break;
      EltsF32.push_back(ElF32->getOperand(1).getReg());
    }

    // All elements had ModOpcode modifier
    if (BV->getNumSources() == EltsF32.size()) {
      selectWMMAModsNegAbs(ModOpcode, Mods, EltsF32, Src, Root.getParent(),
                           *MRI);
    }
  }

  return {{[=](MachineInstrBuilder &MIB) { MIB.addReg(Src); },
           [=](MachineInstrBuilder &MIB) { MIB.addImm(Mods); }}};
}

InstructionSelector::ComplexRendererFns
AMDGPUInstructionSelector::selectWMMAModsF16Neg(MachineOperand &Root) const {
  Register Src = Root.getReg();
  unsigned Mods = SISrcMods::OP_SEL_1;
  SmallVector<Register, 8> EltsV2F16;

  if (GConcatVectors *CV = dyn_cast<GConcatVectors>(MRI->getVRegDef(Src))) {
    for (unsigned i = 0; i < CV->getNumSources(); ++i) {
      Register FNegSrc;
      if (!mi_match(CV->getSourceReg(i), *MRI, m_GFNeg(m_Reg(FNegSrc))))
        break;
      EltsV2F16.push_back(FNegSrc);
    }

    // All elements had ModOpcode modifier
    if (CV->getNumSources() == EltsV2F16.size()) {
      Mods |= SISrcMods::NEG;
      Mods |= SISrcMods::NEG_HI;
      Src = buildRegSequence(EltsV2F16, Root.getParent(), *MRI);
    }
  }

  return {{[=](MachineInstrBuilder &MIB) { MIB.addReg(Src); },
           [=](MachineInstrBuilder &MIB) { MIB.addImm(Mods); }}};
}

InstructionSelector::ComplexRendererFns
AMDGPUInstructionSelector::selectWMMAModsF16NegAbs(MachineOperand &Root) const {
  Register Src = Root.getReg();
  unsigned Mods = SISrcMods::OP_SEL_1;
  SmallVector<Register, 8> EltsV2F16;

  if (GConcatVectors *CV = dyn_cast<GConcatVectors>(MRI->getVRegDef(Src))) {
    assert(CV->getNumSources() > 0);
    MachineInstr *ElV2F16 = MRI->getVRegDef(CV->getSourceReg(0));
    // Based on first element decide which mod we match, neg or abs
    unsigned ModOpcode = (ElV2F16->getOpcode() == AMDGPU::G_FNEG)
                             ? AMDGPU::G_FNEG
                             : AMDGPU::G_FABS;

    for (unsigned i = 0; i < CV->getNumSources(); ++i) {
      ElV2F16 = MRI->getVRegDef(CV->getSourceReg(i));
      if (ElV2F16->getOpcode() != ModOpcode)
        break;
      EltsV2F16.push_back(ElV2F16->getOperand(1).getReg());
    }

    // All elements had ModOpcode modifier
    if (CV->getNumSources() == EltsV2F16.size()) {
      MachineIRBuilder B(*Root.getParent());
      selectWMMAModsNegAbs(ModOpcode, Mods, EltsV2F16, Src, Root.getParent(),
                           *MRI);
    }
  }

  return {{[=](MachineInstrBuilder &MIB) { MIB.addReg(Src); },
           [=](MachineInstrBuilder &MIB) { MIB.addImm(Mods); }}};
}

InstructionSelector::ComplexRendererFns
AMDGPUInstructionSelector::selectWMMAVISrc(MachineOperand &Root) const {
  std::optional<FPValueAndVReg> FPValReg;
  if (mi_match(Root.getReg(), *MRI, m_GFCstOrSplat(FPValReg))) {
    if (TII.isInlineConstant(FPValReg->Value)) {
      return {{[=](MachineInstrBuilder &MIB) {
        MIB.addImm(FPValReg->Value.bitcastToAPInt().getSExtValue());
      }}};
    }
    // Non-inlineable splat floats should not fall-through for integer immediate
    // checks.
    return {};
  }

  APInt ICst;
  if (mi_match(Root.getReg(), *MRI, m_ICstOrSplat(ICst))) {
    if (TII.isInlineConstant(ICst)) {
      return {
          {[=](MachineInstrBuilder &MIB) { MIB.addImm(ICst.getSExtValue()); }}};
    }
  }

  return {};
}

InstructionSelector::ComplexRendererFns
AMDGPUInstructionSelector::selectSWMMACIndex8(MachineOperand &Root) const {
  Register Src =
      getDefIgnoringCopies(Root.getReg(), *MRI)->getOperand(0).getReg();
  unsigned Key = 0;

  Register ShiftSrc;
  std::optional<ValueAndVReg> ShiftAmt;
  if (mi_match(Src, *MRI, m_GLShr(m_Reg(ShiftSrc), m_GCst(ShiftAmt))) &&
      MRI->getType(ShiftSrc).getSizeInBits() == 32 &&
      ShiftAmt->Value.getZExtValue() % 8 == 0) {
    Key = ShiftAmt->Value.getZExtValue() / 8;
    Src = ShiftSrc;
  }

  return {{
      [=](MachineInstrBuilder &MIB) { MIB.addReg(Src); },
      [=](MachineInstrBuilder &MIB) { MIB.addImm(Key); } // index_key
  }};
}

InstructionSelector::ComplexRendererFns
AMDGPUInstructionSelector::selectSWMMACIndex16(MachineOperand &Root) const {

  Register Src =
      getDefIgnoringCopies(Root.getReg(), *MRI)->getOperand(0).getReg();
  unsigned Key = 0;

  Register ShiftSrc;
  std::optional<ValueAndVReg> ShiftAmt;
  if (mi_match(Src, *MRI, m_GLShr(m_Reg(ShiftSrc), m_GCst(ShiftAmt))) &&
      MRI->getType(ShiftSrc).getSizeInBits() == 32 &&
      ShiftAmt->Value.getZExtValue() == 16) {
    Src = ShiftSrc;
    Key = 1;
  }

  return {{
      [=](MachineInstrBuilder &MIB) { MIB.addReg(Src); },
      [=](MachineInstrBuilder &MIB) { MIB.addImm(Key); } // index_key
  }};
}

InstructionSelector::ComplexRendererFns
AMDGPUInstructionSelector::selectSWMMACIndex32(MachineOperand &Root) const {
  Register Src =
      getDefIgnoringCopies(Root.getReg(), *MRI)->getOperand(0).getReg();
  unsigned Key = 0;

  Register S32 = matchZeroExtendFromS32(Src);
  if (!S32)
    S32 = matchAnyExtendFromS32(Src);

  if (S32) {
    const MachineInstr *Def = getDefIgnoringCopies(S32, *MRI);
    if (Def->getOpcode() == TargetOpcode::G_UNMERGE_VALUES) {
      assert(Def->getNumOperands() == 3);
      Register DstReg1 = Def->getOperand(1).getReg();
      if (mi_match(S32, *MRI,
                   m_any_of(m_SpecificReg(DstReg1), m_Copy(m_Reg(DstReg1))))) {
        Src = Def->getOperand(2).getReg();
        Key = 1;
      }
    }
  }

  return {{
      [=](MachineInstrBuilder &MIB) { MIB.addReg(Src); },
      [=](MachineInstrBuilder &MIB) { MIB.addImm(Key); } // index_key
  }};
}

InstructionSelector::ComplexRendererFns
AMDGPUInstructionSelector::selectVOP3OpSelMods(MachineOperand &Root) const {
  Register Src;
  unsigned Mods;
  std::tie(Src, Mods) = selectVOP3ModsImpl(Root.getReg());

  // FIXME: Handle op_sel
  return {{
      [=](MachineInstrBuilder &MIB) { MIB.addReg(Src); },
      [=](MachineInstrBuilder &MIB) { MIB.addImm(Mods); } // src_mods
  }};
}

// FIXME-TRUE16 remove when fake16 is removed
InstructionSelector::ComplexRendererFns
AMDGPUInstructionSelector::selectVINTERPMods(MachineOperand &Root) const {
  Register Src;
  unsigned Mods;
  std::tie(Src, Mods) = selectVOP3ModsImpl(Root.getReg(),
                                           /*IsCanonicalizing=*/true,
                                           /*AllowAbs=*/false,
                                           /*OpSel=*/false);

  return {{
      [=](MachineInstrBuilder &MIB) {
        MIB.addReg(
            copyToVGPRIfSrcFolded(Src, Mods, Root, MIB, /* ForceVGPR */ true));
      },
      [=](MachineInstrBuilder &MIB) { MIB.addImm(Mods); }, // src0_mods
  }};
}

InstructionSelector::ComplexRendererFns
AMDGPUInstructionSelector::selectVINTERPModsHi(MachineOperand &Root) const {
  Register Src;
  unsigned Mods;
  std::tie(Src, Mods) = selectVOP3ModsImpl(Root.getReg(),
                                           /*IsCanonicalizing=*/true,
                                           /*AllowAbs=*/false,
                                           /*OpSel=*/true);

  return {{
      [=](MachineInstrBuilder &MIB) {
        MIB.addReg(
            copyToVGPRIfSrcFolded(Src, Mods, Root, MIB, /* ForceVGPR */ true));
      },
      [=](MachineInstrBuilder &MIB) { MIB.addImm(Mods); }, // src0_mods
  }};
}

// Given \p Offset and load specified by the \p Root operand check if \p Offset
// is a multiple of the load byte size. If it is update \p Offset to a
// pre-scaled value and return true.
bool AMDGPUInstructionSelector::selectScaleOffset(MachineOperand &Root,
                                                  Register &Offset,
                                                  bool IsSigned) const {
  if (!Subtarget->hasScaleOffset())
    return false;

  const MachineInstr &MI = *Root.getParent();
  MachineMemOperand *MMO = *MI.memoperands_begin();

  if (!MMO->getSize().hasValue())
    return false;

  uint64_t Size = MMO->getSize().getValue();

  Register OffsetReg = matchExtendFromS32OrS32(Offset, IsSigned);
  if (!OffsetReg)
    OffsetReg = Offset;

  if (auto Def = getDefSrcRegIgnoringCopies(OffsetReg, *MRI))
    OffsetReg = Def->Reg;

  Register Op0;
  MachineInstr *Mul;
  bool ScaleOffset =
      (isPowerOf2_64(Size) &&
       mi_match(OffsetReg, *MRI,
                m_GShl(m_Reg(Op0),
                       m_any_of(m_SpecificICst(Log2_64(Size)),
                                m_Copy(m_SpecificICst(Log2_64(Size))))))) ||
      mi_match(OffsetReg, *MRI,
               m_GMul(m_Reg(Op0), m_any_of(m_SpecificICst(Size),
                                           m_Copy(m_SpecificICst(Size))))) ||
      mi_match(
          OffsetReg, *MRI,
          m_BinOp(IsSigned ? AMDGPU::S_MUL_I64_I32_PSEUDO : AMDGPU::S_MUL_U64,
                  m_Reg(Op0), m_SpecificICst(Size))) ||
      // Match G_AMDGPU_MAD_U64_U32 offset, c, 0
      (mi_match(OffsetReg, *MRI, m_MInstr(Mul)) &&
       (Mul->getOpcode() == (IsSigned ? AMDGPU::G_AMDGPU_MAD_I64_I32
                                      : AMDGPU::G_AMDGPU_MAD_U64_U32) ||
        (IsSigned && Mul->getOpcode() == AMDGPU::G_AMDGPU_MAD_U64_U32 &&
         VT->signBitIsZero(Mul->getOperand(2).getReg()))) &&
       mi_match(Mul->getOperand(4).getReg(), *MRI, m_ZeroInt()) &&
       mi_match(Mul->getOperand(3).getReg(), *MRI,
                m_GTrunc(m_any_of(m_SpecificICst(Size),
                                  m_Copy(m_SpecificICst(Size))))) &&
       mi_match(Mul->getOperand(2).getReg(), *MRI, m_Reg(Op0)));

  if (ScaleOffset)
    Offset = Op0;

  return ScaleOffset;
}

bool AMDGPUInstructionSelector::selectSmrdOffset(MachineOperand &Root,
                                                 Register &Base,
                                                 Register *SOffset,
                                                 int64_t *Offset,
                                                 bool *ScaleOffset) const {
  MachineInstr *MI = Root.getParent();
  MachineBasicBlock *MBB = MI->getParent();

  // FIXME: We should shrink the GEP if the offset is known to be <= 32-bits,
  // then we can select all ptr + 32-bit offsets.
  SmallVector<GEPInfo, 4> AddrInfo;
  getAddrModeInfo(*MI, *MRI, AddrInfo);

  if (AddrInfo.empty())
    return false;

  const GEPInfo &GEPI = AddrInfo[0];
  std::optional<int64_t> EncodedImm;

  if (ScaleOffset)
    *ScaleOffset = false;

  if (SOffset && Offset) {
    EncodedImm = AMDGPU::getSMRDEncodedOffset(STI, GEPI.Imm, /*IsBuffer=*/false,
                                              /*HasSOffset=*/true);
    if (GEPI.SgprParts.size() == 1 && GEPI.Imm != 0 && EncodedImm &&
        AddrInfo.size() > 1) {
      const GEPInfo &GEPI2 = AddrInfo[1];
      if (GEPI2.SgprParts.size() == 2 && GEPI2.Imm == 0) {
        Register OffsetReg = GEPI2.SgprParts[1];
        if (ScaleOffset)
          *ScaleOffset =
              selectScaleOffset(Root, OffsetReg, false /* IsSigned */);
        OffsetReg = matchZeroExtendFromS32OrS32(OffsetReg);
        if (OffsetReg) {
          Base = GEPI2.SgprParts[0];
          *SOffset = OffsetReg;
          *Offset = *EncodedImm;
          if (*Offset >= 0 || !AMDGPU::hasSMRDSignedImmOffset(STI))
            return true;

          // For unbuffered smem loads, it is illegal for the Immediate Offset
          // to be negative if the resulting (Offset + (M0 or SOffset or zero)
          // is negative. Handle the case where the Immediate Offset + SOffset
          // is negative.
          auto SKnown = VT->getKnownBits(*SOffset);
          if (*Offset + SKnown.getMinValue().getSExtValue() < 0)
            return false;

          return true;
        }
      }
    }
    return false;
  }

  EncodedImm = AMDGPU::getSMRDEncodedOffset(STI, GEPI.Imm, /*IsBuffer=*/false,
                                            /*HasSOffset=*/false);
  if (Offset && GEPI.SgprParts.size() == 1 && EncodedImm) {
    Base = GEPI.SgprParts[0];
    *Offset = *EncodedImm;
    return true;
  }

  // SGPR offset is unsigned.
  if (SOffset && GEPI.SgprParts.size() == 1 && isUInt<32>(GEPI.Imm) &&
      GEPI.Imm != 0) {
    // If we make it this far we have a load with an 32-bit immediate offset.
    // It is OK to select this using a sgpr offset, because we have already
    // failed trying to select this load into one of the _IMM variants since
    // the _IMM Patterns are considered before the _SGPR patterns.
    Base = GEPI.SgprParts[0];
    *SOffset = MRI->createVirtualRegister(&AMDGPU::SReg_32RegClass);
    BuildMI(*MBB, MI, MI->getDebugLoc(), TII.get(AMDGPU::S_MOV_B32), *SOffset)
        .addImm(GEPI.Imm);
    return true;
  }

  if (SOffset && GEPI.SgprParts.size() && GEPI.Imm == 0) {
    Register OffsetReg = GEPI.SgprParts[1];
    if (ScaleOffset)
      *ScaleOffset = selectScaleOffset(Root, OffsetReg, false /* IsSigned */);
    OffsetReg = matchZeroExtendFromS32OrS32(OffsetReg);
    if (OffsetReg) {
      Base = GEPI.SgprParts[0];
      *SOffset = OffsetReg;
      return true;
    }
  }

  return false;
}

InstructionSelector::ComplexRendererFns
AMDGPUInstructionSelector::selectSmrdImm(MachineOperand &Root) const {
  Register Base;
  int64_t Offset;
  if (!selectSmrdOffset(Root, Base, /* SOffset= */ nullptr, &Offset,
                        /* ScaleOffset */ nullptr))
    return std::nullopt;

  return {{[=](MachineInstrBuilder &MIB) { MIB.addReg(Base); },
           [=](MachineInstrBuilder &MIB) { MIB.addImm(Offset); }}};
}

InstructionSelector::ComplexRendererFns
AMDGPUInstructionSelector::selectSmrdImm32(MachineOperand &Root) const {
  SmallVector<GEPInfo, 4> AddrInfo;
  getAddrModeInfo(*Root.getParent(), *MRI, AddrInfo);

  if (AddrInfo.empty() || AddrInfo[0].SgprParts.size() != 1)
    return std::nullopt;

  const GEPInfo &GEPInfo = AddrInfo[0];
  Register PtrReg = GEPInfo.SgprParts[0];
  std::optional<int64_t> EncodedImm =
      AMDGPU::getSMRDEncodedLiteralOffset32(STI, GEPInfo.Imm);
  if (!EncodedImm)
    return std::nullopt;

  return {{
    [=](MachineInstrBuilder &MIB) { MIB.addReg(PtrReg); },
    [=](MachineInstrBuilder &MIB) { MIB.addImm(*EncodedImm); }
  }};
}

InstructionSelector::ComplexRendererFns
AMDGPUInstructionSelector::selectSmrdSgpr(MachineOperand &Root) const {
  Register Base, SOffset;
  bool ScaleOffset;
  if (!selectSmrdOffset(Root, Base, &SOffset, /* Offset= */ nullptr,
                        &ScaleOffset))
    return std::nullopt;

  unsigned CPol = ScaleOffset ? AMDGPU::CPol::SCAL : 0;
  return {{[=](MachineInstrBuilder &MIB) { MIB.addReg(Base); },
           [=](MachineInstrBuilder &MIB) { MIB.addReg(SOffset); },
           [=](MachineInstrBuilder &MIB) { MIB.addImm(CPol); }}};
}

InstructionSelector::ComplexRendererFns
AMDGPUInstructionSelector::selectSmrdSgprImm(MachineOperand &Root) const {
  Register Base, SOffset;
  int64_t Offset;
  bool ScaleOffset;
  if (!selectSmrdOffset(Root, Base, &SOffset, &Offset, &ScaleOffset))
    return std::nullopt;

  unsigned CPol = ScaleOffset ? AMDGPU::CPol::SCAL : 0;
  return {{[=](MachineInstrBuilder &MIB) { MIB.addReg(Base); },
           [=](MachineInstrBuilder &MIB) { MIB.addReg(SOffset); },
           [=](MachineInstrBuilder &MIB) { MIB.addImm(Offset); },
           [=](MachineInstrBuilder &MIB) { MIB.addImm(CPol); }}};
}

std::pair<Register, int>
AMDGPUInstructionSelector::selectFlatOffsetImpl(MachineOperand &Root,
                                                uint64_t FlatVariant) const {
  MachineInstr *MI = Root.getParent();

  auto Default = std::pair(Root.getReg(), 0);

  if (!STI.hasFlatInstOffsets())
    return Default;

  Register PtrBase;
  int64_t ConstOffset;
  bool IsInBounds;
  std::tie(PtrBase, ConstOffset, IsInBounds) =
      getPtrBaseWithConstantOffset(Root.getReg(), *MRI);

  // Adding the offset to the base address with an immediate in a FLAT
  // instruction must not change the memory aperture in which the address falls.
  // Therefore we can only fold offsets from inbounds GEPs into FLAT
  // instructions.
  if (ConstOffset == 0 ||
      (FlatVariant == SIInstrFlags::FlatScratch &&
       !isFlatScratchBaseLegal(Root.getReg())) ||
      (FlatVariant == SIInstrFlags::FLAT && !IsInBounds))
    return Default;

  unsigned AddrSpace = (*MI->memoperands_begin())->getAddrSpace();
  if (!TII.isLegalFLATOffset(ConstOffset, AddrSpace, FlatVariant))
    return Default;

  return std::pair(PtrBase, ConstOffset);
}

InstructionSelector::ComplexRendererFns
AMDGPUInstructionSelector::selectFlatOffset(MachineOperand &Root) const {
  auto PtrWithOffset = selectFlatOffsetImpl(Root, SIInstrFlags::FLAT);

  return {{
      [=](MachineInstrBuilder &MIB) { MIB.addReg(PtrWithOffset.first); },
      [=](MachineInstrBuilder &MIB) { MIB.addImm(PtrWithOffset.second); },
    }};
}

InstructionSelector::ComplexRendererFns
AMDGPUInstructionSelector::selectGlobalOffset(MachineOperand &Root) const {
  auto PtrWithOffset = selectFlatOffsetImpl(Root, SIInstrFlags::FlatGlobal);

  return {{
      [=](MachineInstrBuilder &MIB) { MIB.addReg(PtrWithOffset.first); },
      [=](MachineInstrBuilder &MIB) { MIB.addImm(PtrWithOffset.second); },
  }};
}

InstructionSelector::ComplexRendererFns
AMDGPUInstructionSelector::selectScratchOffset(MachineOperand &Root) const {
  auto PtrWithOffset = selectFlatOffsetImpl(Root, SIInstrFlags::FlatScratch);

  return {{
      [=](MachineInstrBuilder &MIB) { MIB.addReg(PtrWithOffset.first); },
      [=](MachineInstrBuilder &MIB) { MIB.addImm(PtrWithOffset.second); },
    }};
}

// Match (64-bit SGPR base) + (zext vgpr offset) + sext(imm offset)
InstructionSelector::ComplexRendererFns
AMDGPUInstructionSelector::selectGlobalSAddr(MachineOperand &Root,
                                             unsigned CPolBits,
                                             bool NeedIOffset) const {
  Register Addr = Root.getReg();
  Register PtrBase;
  int64_t ConstOffset;
  int64_t ImmOffset = 0;

  // Match the immediate offset first, which canonically is moved as low as
  // possible.
  std::tie(PtrBase, ConstOffset, std::ignore) =
      getPtrBaseWithConstantOffset(Addr, *MRI);

  if (ConstOffset != 0) {
    if (NeedIOffset &&
        TII.isLegalFLATOffset(ConstOffset, AMDGPUAS::GLOBAL_ADDRESS,
                              SIInstrFlags::FlatGlobal)) {
      Addr = PtrBase;
      ImmOffset = ConstOffset;
    } else {
      auto PtrBaseDef = getDefSrcRegIgnoringCopies(PtrBase, *MRI);
      if (isSGPR(PtrBaseDef->Reg)) {
        if (ConstOffset > 0) {
          // Offset is too large.
          //
          // saddr + large_offset -> saddr +
          //                         (voffset = large_offset & ~MaxOffset) +
          //                         (large_offset & MaxOffset);
          int64_t SplitImmOffset = 0, RemainderOffset = ConstOffset;
          if (NeedIOffset) {
            std::tie(SplitImmOffset, RemainderOffset) =
                TII.splitFlatOffset(ConstOffset, AMDGPUAS::GLOBAL_ADDRESS,
                                    SIInstrFlags::FlatGlobal);
          }

          if (Subtarget->hasSignedGVSOffset() ? isInt<32>(RemainderOffset)
                                              : isUInt<32>(RemainderOffset)) {
            MachineInstr *MI = Root.getParent();
            MachineBasicBlock *MBB = MI->getParent();
            Register HighBits =
                MRI->createVirtualRegister(&AMDGPU::VGPR_32RegClass);

            BuildMI(*MBB, MI, MI->getDebugLoc(), TII.get(AMDGPU::V_MOV_B32_e32),
                    HighBits)
                .addImm(RemainderOffset);

            if (NeedIOffset)
              return {{
                  [=](MachineInstrBuilder &MIB) {
                    MIB.addReg(PtrBase);
                  }, // saddr
                  [=](MachineInstrBuilder &MIB) {
                    MIB.addReg(HighBits);
                  }, // voffset
                  [=](MachineInstrBuilder &MIB) { MIB.addImm(SplitImmOffset); },
                  [=](MachineInstrBuilder &MIB) { MIB.addImm(CPolBits); },
              }};
            return {{
                [=](MachineInstrBuilder &MIB) { MIB.addReg(PtrBase); }, // saddr
                [=](MachineInstrBuilder &MIB) {
                  MIB.addReg(HighBits);
                }, // voffset
                [=](MachineInstrBuilder &MIB) { MIB.addImm(CPolBits); },
            }};
          }
        }

        // We are adding a 64 bit SGPR and a constant. If constant bus limit
        // is 1 we would need to perform 1 or 2 extra moves for each half of
        // the constant and it is better to do a scalar add and then issue a
        // single VALU instruction to materialize zero. Otherwise it is less
        // instructions to perform VALU adds with immediates or inline literals.
        unsigned NumLiterals =
            !TII.isInlineConstant(APInt(32, Lo_32(ConstOffset))) +
            !TII.isInlineConstant(APInt(32, Hi_32(ConstOffset)));
        if (STI.getConstantBusLimit(AMDGPU::V_ADD_U32_e64) > NumLiterals)
          return std::nullopt;
      }
    }
  }

  // Match the variable offset.
  auto AddrDef = getDefSrcRegIgnoringCopies(Addr, *MRI);
  if (AddrDef->MI->getOpcode() == AMDGPU::G_PTR_ADD) {
    // Look through the SGPR->VGPR copy.
    Register SAddr =
        getSrcRegIgnoringCopies(AddrDef->MI->getOperand(1).getReg(), *MRI);

    if (isSGPR(SAddr)) {
      Register PtrBaseOffset = AddrDef->MI->getOperand(2).getReg();

      // It's possible voffset is an SGPR here, but the copy to VGPR will be
      // inserted later.
      bool ScaleOffset = selectScaleOffset(Root, PtrBaseOffset,
                                           Subtarget->hasSignedGVSOffset());
      if (Register VOffset = matchExtendFromS32OrS32(
              PtrBaseOffset, Subtarget->hasSignedGVSOffset())) {
        if (NeedIOffset)
          return {{[=](MachineInstrBuilder &MIB) { // saddr
                     MIB.addReg(SAddr);
                   },
                   [=](MachineInstrBuilder &MIB) { // voffset
                     MIB.addReg(VOffset);
                   },
                   [=](MachineInstrBuilder &MIB) { // offset
                     MIB.addImm(ImmOffset);
                   },
                   [=](MachineInstrBuilder &MIB) { // cpol
                     MIB.addImm(CPolBits |
                                (ScaleOffset ? AMDGPU::CPol::SCAL : 0));
                   }}};
        return {{[=](MachineInstrBuilder &MIB) { // saddr
                   MIB.addReg(SAddr);
                 },
                 [=](MachineInstrBuilder &MIB) { // voffset
                   MIB.addReg(VOffset);
                 },
                 [=](MachineInstrBuilder &MIB) { // cpol
                   MIB.addImm(CPolBits |
                              (ScaleOffset ? AMDGPU::CPol::SCAL : 0));
                 }}};
      }
    }
  }

  // FIXME: We should probably have folded COPY (G_IMPLICIT_DEF) earlier, and
  // drop this.
  if (AddrDef->MI->getOpcode() == AMDGPU::G_IMPLICIT_DEF ||
      AddrDef->MI->getOpcode() == AMDGPU::G_CONSTANT || !isSGPR(AddrDef->Reg))
    return std::nullopt;

  // It's cheaper to materialize a single 32-bit zero for vaddr than the two
  // moves required to copy a 64-bit SGPR to VGPR.
  MachineInstr *MI = Root.getParent();
  MachineBasicBlock *MBB = MI->getParent();
  Register VOffset = MRI->createVirtualRegister(&AMDGPU::VGPR_32RegClass);

  BuildMI(*MBB, MI, MI->getDebugLoc(), TII.get(AMDGPU::V_MOV_B32_e32), VOffset)
      .addImm(0);

  if (NeedIOffset)
    return {{
        [=](MachineInstrBuilder &MIB) { MIB.addReg(AddrDef->Reg); }, // saddr
        [=](MachineInstrBuilder &MIB) { MIB.addReg(VOffset); },      // voffset
        [=](MachineInstrBuilder &MIB) { MIB.addImm(ImmOffset); },    // offset
        [=](MachineInstrBuilder &MIB) { MIB.addImm(CPolBits); }      // cpol
    }};
  return {{
      [=](MachineInstrBuilder &MIB) { MIB.addReg(AddrDef->Reg); }, // saddr
      [=](MachineInstrBuilder &MIB) { MIB.addReg(VOffset); },      // voffset
      [=](MachineInstrBuilder &MIB) { MIB.addImm(CPolBits); }      // cpol
  }};
}

InstructionSelector::ComplexRendererFns
AMDGPUInstructionSelector::selectGlobalSAddr(MachineOperand &Root) const {
  return selectGlobalSAddr(Root, 0);
}

InstructionSelector::ComplexRendererFns
AMDGPUInstructionSelector::selectGlobalSAddrCPol(MachineOperand &Root) const {
  const MachineInstr &I = *Root.getParent();

  // We are assuming CPol is always the last operand of the intrinsic.
  auto PassedCPol =
      I.getOperand(I.getNumOperands() - 1).getImm() & ~AMDGPU::CPol::SCAL;
  return selectGlobalSAddr(Root, PassedCPol);
}

InstructionSelector::ComplexRendererFns
AMDGPUInstructionSelector::selectGlobalSAddrCPolM0(MachineOperand &Root) const {
  const MachineInstr &I = *Root.getParent();

  // We are assuming CPol is second from last operand of the intrinsic.
  auto PassedCPol =
      I.getOperand(I.getNumOperands() - 2).getImm() & ~AMDGPU::CPol::SCAL;
  return selectGlobalSAddr(Root, PassedCPol);
}

InstructionSelector::ComplexRendererFns
AMDGPUInstructionSelector::selectGlobalSAddrGLC(MachineOperand &Root) const {
  return selectGlobalSAddr(Root, AMDGPU::CPol::GLC);
}

InstructionSelector::ComplexRendererFns
AMDGPUInstructionSelector::selectGlobalSAddrNoIOffset(
    MachineOperand &Root) const {
  const MachineInstr &I = *Root.getParent();

  // We are assuming CPol is always the last operand of the intrinsic.
  auto PassedCPol =
      I.getOperand(I.getNumOperands() - 1).getImm() & ~AMDGPU::CPol::SCAL;
  return selectGlobalSAddr(Root, PassedCPol, false);
}

InstructionSelector::ComplexRendererFns
AMDGPUInstructionSelector::selectGlobalSAddrNoIOffsetM0(
    MachineOperand &Root) const {
  const MachineInstr &I = *Root.getParent();

  // We are assuming CPol is second from last operand of the intrinsic.
  auto PassedCPol =
      I.getOperand(I.getNumOperands() - 2).getImm() & ~AMDGPU::CPol::SCAL;
  return selectGlobalSAddr(Root, PassedCPol, false);
}

InstructionSelector::ComplexRendererFns
AMDGPUInstructionSelector::selectScratchSAddr(MachineOperand &Root) const {
  Register Addr = Root.getReg();
  Register PtrBase;
  int64_t ConstOffset;
  int64_t ImmOffset = 0;

  // Match the immediate offset first, which canonically is moved as low as
  // possible.
  std::tie(PtrBase, ConstOffset, std::ignore) =
      getPtrBaseWithConstantOffset(Addr, *MRI);

  if (ConstOffset != 0 && isFlatScratchBaseLegal(Addr) &&
      TII.isLegalFLATOffset(ConstOffset, AMDGPUAS::PRIVATE_ADDRESS,
                            SIInstrFlags::FlatScratch)) {
    Addr = PtrBase;
    ImmOffset = ConstOffset;
  }

  auto AddrDef = getDefSrcRegIgnoringCopies(Addr, *MRI);
  if (AddrDef->MI->getOpcode() == AMDGPU::G_FRAME_INDEX) {
    int FI = AddrDef->MI->getOperand(1).getIndex();
    return {{
        [=](MachineInstrBuilder &MIB) { MIB.addFrameIndex(FI); }, // saddr
        [=](MachineInstrBuilder &MIB) { MIB.addImm(ImmOffset); } // offset
    }};
  }

  Register SAddr = AddrDef->Reg;

  if (AddrDef->MI->getOpcode() == AMDGPU::G_PTR_ADD) {
    Register LHS = AddrDef->MI->getOperand(1).getReg();
    Register RHS = AddrDef->MI->getOperand(2).getReg();
    auto LHSDef = getDefSrcRegIgnoringCopies(LHS, *MRI);
    auto RHSDef = getDefSrcRegIgnoringCopies(RHS, *MRI);

    if (LHSDef->MI->getOpcode() == AMDGPU::G_FRAME_INDEX &&
        isSGPR(RHSDef->Reg)) {
      int FI = LHSDef->MI->getOperand(1).getIndex();
      MachineInstr &I = *Root.getParent();
      MachineBasicBlock *BB = I.getParent();
      const DebugLoc &DL = I.getDebugLoc();
      SAddr = MRI->createVirtualRegister(&AMDGPU::SReg_32RegClass);

      BuildMI(*BB, &I, DL, TII.get(AMDGPU::S_ADD_I32), SAddr)
          .addFrameIndex(FI)
          .addReg(RHSDef->Reg)
          .setOperandDead(3); // Dead scc
    }
  }

  if (!isSGPR(SAddr))
    return std::nullopt;

  return {{
      [=](MachineInstrBuilder &MIB) { MIB.addReg(SAddr); }, // saddr
      [=](MachineInstrBuilder &MIB) { MIB.addImm(ImmOffset); } // offset
  }};
}

// Check whether the flat scratch SVS swizzle bug affects this access.
bool AMDGPUInstructionSelector::checkFlatScratchSVSSwizzleBug(
    Register VAddr, Register SAddr, uint64_t ImmOffset) const {
  if (!Subtarget->hasFlatScratchSVSSwizzleBug())
    return false;

  // The bug affects the swizzling of SVS accesses if there is any carry out
  // from the two low order bits (i.e. from bit 1 into bit 2) when adding
  // voffset to (soffset + inst_offset).
  auto VKnown = VT->getKnownBits(VAddr);
  auto SKnown = KnownBits::add(VT->getKnownBits(SAddr),
                               KnownBits::makeConstant(APInt(32, ImmOffset)));
  uint64_t VMax = VKnown.getMaxValue().getZExtValue();
  uint64_t SMax = SKnown.getMaxValue().getZExtValue();
  return (VMax & 3) + (SMax & 3) >= 4;
}

InstructionSelector::ComplexRendererFns
AMDGPUInstructionSelector::selectScratchSVAddr(MachineOperand &Root) const {
  Register Addr = Root.getReg();
  Register PtrBase;
  int64_t ConstOffset;
  int64_t ImmOffset = 0;

  // Match the immediate offset first, which canonically is moved as low as
  // possible.
  std::tie(PtrBase, ConstOffset, std::ignore) =
      getPtrBaseWithConstantOffset(Addr, *MRI);

  Register OrigAddr = Addr;
  if (ConstOffset != 0 &&
      TII.isLegalFLATOffset(ConstOffset, AMDGPUAS::PRIVATE_ADDRESS,
                            SIInstrFlags::FlatScratch)) {
    Addr = PtrBase;
    ImmOffset = ConstOffset;
  }

  auto AddrDef = getDefSrcRegIgnoringCopies(Addr, *MRI);
  if (AddrDef->MI->getOpcode() != AMDGPU::G_PTR_ADD)
    return std::nullopt;

  Register RHS = AddrDef->MI->getOperand(2).getReg();
  if (RBI.getRegBank(RHS, *MRI, TRI)->getID() != AMDGPU::VGPRRegBankID)
    return std::nullopt;

  Register LHS = AddrDef->MI->getOperand(1).getReg();
  auto LHSDef = getDefSrcRegIgnoringCopies(LHS, *MRI);

  if (OrigAddr != Addr) {
    if (!isFlatScratchBaseLegalSVImm(OrigAddr))
      return std::nullopt;
  } else {
    if (!isFlatScratchBaseLegalSV(OrigAddr))
      return std::nullopt;
  }

  if (checkFlatScratchSVSSwizzleBug(RHS, LHS, ImmOffset))
    return std::nullopt;

  unsigned CPol = selectScaleOffset(Root, RHS, true /* IsSigned */)
                      ? AMDGPU::CPol::SCAL
                      : 0;

  if (LHSDef->MI->getOpcode() == AMDGPU::G_FRAME_INDEX) {
    int FI = LHSDef->MI->getOperand(1).getIndex();
    return {{
        [=](MachineInstrBuilder &MIB) { MIB.addReg(RHS); },       // vaddr
        [=](MachineInstrBuilder &MIB) { MIB.addFrameIndex(FI); }, // saddr
        [=](MachineInstrBuilder &MIB) { MIB.addImm(ImmOffset); }, // offset
        [=](MachineInstrBuilder &MIB) { MIB.addImm(CPol); }       // cpol
    }};
  }

  if (!isSGPR(LHS))
    if (auto Def = getDefSrcRegIgnoringCopies(LHS, *MRI))
      LHS = Def->Reg;

  if (!isSGPR(LHS))
    return std::nullopt;

  return {{
      [=](MachineInstrBuilder &MIB) { MIB.addReg(RHS); },       // vaddr
      [=](MachineInstrBuilder &MIB) { MIB.addReg(LHS); },       // saddr
      [=](MachineInstrBuilder &MIB) { MIB.addImm(ImmOffset); }, // offset
      [=](MachineInstrBuilder &MIB) { MIB.addImm(CPol); }       // cpol
  }};
}

InstructionSelector::ComplexRendererFns
AMDGPUInstructionSelector::selectMUBUFScratchOffen(MachineOperand &Root) const {
  MachineInstr *MI = Root.getParent();
  MachineBasicBlock *MBB = MI->getParent();
  MachineFunction *MF = MBB->getParent();
  const SIMachineFunctionInfo *Info = MF->getInfo<SIMachineFunctionInfo>();

  int64_t Offset = 0;
  if (mi_match(Root.getReg(), *MRI, m_ICst(Offset)) &&
      Offset != TM.getNullPointerValue(AMDGPUAS::PRIVATE_ADDRESS)) {
    Register HighBits = MRI->createVirtualRegister(&AMDGPU::VGPR_32RegClass);

    // TODO: Should this be inside the render function? The iterator seems to
    // move.
    const uint32_t MaxOffset = SIInstrInfo::getMaxMUBUFImmOffset(*Subtarget);
    BuildMI(*MBB, MI, MI->getDebugLoc(), TII.get(AMDGPU::V_MOV_B32_e32),
            HighBits)
        .addImm(Offset & ~MaxOffset);

    return {{[=](MachineInstrBuilder &MIB) { // rsrc
               MIB.addReg(Info->getScratchRSrcReg());
             },
             [=](MachineInstrBuilder &MIB) { // vaddr
               MIB.addReg(HighBits);
             },
             [=](MachineInstrBuilder &MIB) { // soffset
               // Use constant zero for soffset and rely on eliminateFrameIndex
               // to choose the appropriate frame register if need be.
               MIB.addImm(0);
             },
             [=](MachineInstrBuilder &MIB) { // offset
               MIB.addImm(Offset & MaxOffset);
             }}};
  }

  assert(Offset == 0 || Offset == -1);

  // Try to fold a frame index directly into the MUBUF vaddr field, and any
  // offsets.
  std::optional<int> FI;
  Register VAddr = Root.getReg();

  const MachineInstr *RootDef = MRI->getVRegDef(Root.getReg());
  Register PtrBase;
  int64_t ConstOffset;
  std::tie(PtrBase, ConstOffset, std::ignore) =
      getPtrBaseWithConstantOffset(VAddr, *MRI);
  if (ConstOffset != 0) {
    if (TII.isLegalMUBUFImmOffset(ConstOffset) &&
        (!STI.privateMemoryResourceIsRangeChecked() ||
         VT->signBitIsZero(PtrBase))) {
      const MachineInstr *PtrBaseDef = MRI->getVRegDef(PtrBase);
      if (PtrBaseDef->getOpcode() == AMDGPU::G_FRAME_INDEX)
        FI = PtrBaseDef->getOperand(1).getIndex();
      else
        VAddr = PtrBase;
      Offset = ConstOffset;
    }
  } else if (RootDef->getOpcode() == AMDGPU::G_FRAME_INDEX) {
    FI = RootDef->getOperand(1).getIndex();
  }

  return {{[=](MachineInstrBuilder &MIB) { // rsrc
             MIB.addReg(Info->getScratchRSrcReg());
           },
           [=](MachineInstrBuilder &MIB) { // vaddr
             if (FI)
               MIB.addFrameIndex(*FI);
             else
               MIB.addReg(VAddr);
           },
           [=](MachineInstrBuilder &MIB) { // soffset
             // Use constant zero for soffset and rely on eliminateFrameIndex
             // to choose the appropriate frame register if need be.
             MIB.addImm(0);
           },
           [=](MachineInstrBuilder &MIB) { // offset
             MIB.addImm(Offset);
           }}};
}

bool AMDGPUInstructionSelector::isDSOffsetLegal(Register Base,
                                                int64_t Offset) const {
  if (!isUInt<16>(Offset))
    return false;

  if (STI.hasUsableDSOffset() || STI.unsafeDSOffsetFoldingEnabled())
    return true;

  // On Southern Islands instruction with a negative base value and an offset
  // don't seem to work.
  return VT->signBitIsZero(Base);
}

bool AMDGPUInstructionSelector::isDSOffset2Legal(Register Base, int64_t Offset0,
                                                 int64_t Offset1,
                                                 unsigned Size) const {
  if (Offset0 % Size != 0 || Offset1 % Size != 0)
    return false;
  if (!isUInt<8>(Offset0 / Size) || !isUInt<8>(Offset1 / Size))
    return false;

  if (STI.hasUsableDSOffset() || STI.unsafeDSOffsetFoldingEnabled())
    return true;

  // On Southern Islands instruction with a negative base value and an offset
  // don't seem to work.
  return VT->signBitIsZero(Base);
}

// Return whether the operation has NoUnsignedWrap property.
static bool isNoUnsignedWrap(MachineInstr *Addr) {
  return Addr->getOpcode() == TargetOpcode::G_OR ||
         (Addr->getOpcode() == TargetOpcode::G_PTR_ADD &&
          Addr->getFlag(MachineInstr::NoUWrap));
}

// Check that the base address of flat scratch load/store in the form of `base +
// offset` is legal to be put in SGPR/VGPR (i.e. unsigned per hardware
// requirement). We always treat the first operand as the base address here.
bool AMDGPUInstructionSelector::isFlatScratchBaseLegal(Register Addr) const {
  MachineInstr *AddrMI = getDefIgnoringCopies(Addr, *MRI);

  if (isNoUnsignedWrap(AddrMI))
    return true;

  // Starting with GFX12, VADDR and SADDR fields in VSCRATCH can use negative
  // values.
  if (STI.hasSignedScratchOffsets())
    return true;

  Register LHS = AddrMI->getOperand(1).getReg();
  Register RHS = AddrMI->getOperand(2).getReg();

  if (AddrMI->getOpcode() == TargetOpcode::G_PTR_ADD) {
    std::optional<ValueAndVReg> RhsValReg =
        getIConstantVRegValWithLookThrough(RHS, *MRI);
    // If the immediate offset is negative and within certain range, the base
    // address cannot also be negative. If the base is also negative, the sum
    // would be either negative or much larger than the valid range of scratch
    // memory a thread can access.
    if (RhsValReg && RhsValReg->Value.getSExtValue() < 0 &&
        RhsValReg->Value.getSExtValue() > -0x40000000)
      return true;
  }

  return VT->signBitIsZero(LHS);
}

// Check address value in SGPR/VGPR are legal for flat scratch in the form
// of: SGPR + VGPR.
bool AMDGPUInstructionSelector::isFlatScratchBaseLegalSV(Register Addr) const {
  MachineInstr *AddrMI = getDefIgnoringCopies(Addr, *MRI);

  if (isNoUnsignedWrap(AddrMI))
    return true;

  // Starting with GFX12, VADDR and SADDR fields in VSCRATCH can use negative
  // values.
  if (STI.hasSignedScratchOffsets())
    return true;

  Register LHS = AddrMI->getOperand(1).getReg();
  Register RHS = AddrMI->getOperand(2).getReg();
  return VT->signBitIsZero(RHS) && VT->signBitIsZero(LHS);
}

// Check address value in SGPR/VGPR are legal for flat scratch in the form
// of: SGPR + VGPR + Imm.
bool AMDGPUInstructionSelector::isFlatScratchBaseLegalSVImm(
    Register Addr) const {
  // Starting with GFX12, VADDR and SADDR fields in VSCRATCH can use negative
  // values.
  if (STI.hasSignedScratchOffsets())
    return true;

  MachineInstr *AddrMI = getDefIgnoringCopies(Addr, *MRI);
  Register Base = AddrMI->getOperand(1).getReg();
  std::optional<DefinitionAndSourceRegister> BaseDef =
      getDefSrcRegIgnoringCopies(Base, *MRI);
  std::optional<ValueAndVReg> RHSOffset =
      getIConstantVRegValWithLookThrough(AddrMI->getOperand(2).getReg(), *MRI);
  assert(RHSOffset);

  // If the immediate offset is negative and within certain range, the base
  // address cannot also be negative. If the base is also negative, the sum
  // would be either negative or much larger than the valid range of scratch
  // memory a thread can access.
  if (isNoUnsignedWrap(BaseDef->MI) &&
      (isNoUnsignedWrap(AddrMI) ||
       (RHSOffset->Value.getSExtValue() < 0 &&
        RHSOffset->Value.getSExtValue() > -0x40000000)))
    return true;

  Register LHS = BaseDef->MI->getOperand(1).getReg();
  Register RHS = BaseDef->MI->getOperand(2).getReg();
  return VT->signBitIsZero(RHS) && VT->signBitIsZero(LHS);
}

bool AMDGPUInstructionSelector::isUnneededShiftMask(const MachineInstr &MI,
                                                    unsigned ShAmtBits) const {
  assert(MI.getOpcode() == TargetOpcode::G_AND);

  std::optional<APInt> RHS =
      getIConstantVRegVal(MI.getOperand(2).getReg(), *MRI);
  if (!RHS)
    return false;

  if (RHS->countr_one() >= ShAmtBits)
    return true;

  const APInt &LHSKnownZeros = VT->getKnownZeroes(MI.getOperand(1).getReg());
  return (LHSKnownZeros | *RHS).countr_one() >= ShAmtBits;
}

InstructionSelector::ComplexRendererFns
AMDGPUInstructionSelector::selectMUBUFScratchOffset(
    MachineOperand &Root) const {
  Register Reg = Root.getReg();
  const SIMachineFunctionInfo *Info = MF->getInfo<SIMachineFunctionInfo>();

  std::optional<DefinitionAndSourceRegister> Def =
    getDefSrcRegIgnoringCopies(Reg, *MRI);
  assert(Def && "this shouldn't be an optional result");
  Reg = Def->Reg;

  if (Register WaveBase = getWaveAddress(Def->MI)) {
    return {{
        [=](MachineInstrBuilder &MIB) { // rsrc
          MIB.addReg(Info->getScratchRSrcReg());
        },
        [=](MachineInstrBuilder &MIB) { // soffset
          MIB.addReg(WaveBase);
        },
        [=](MachineInstrBuilder &MIB) { MIB.addImm(0); } // offset
    }};
  }

  int64_t Offset = 0;

  // FIXME: Copy check is a hack
  Register BasePtr;
  if (mi_match(Reg, *MRI,
               m_GPtrAdd(m_Reg(BasePtr),
                         m_any_of(m_ICst(Offset), m_Copy(m_ICst(Offset)))))) {
    if (!TII.isLegalMUBUFImmOffset(Offset))
      return {};
    MachineInstr *BasePtrDef = getDefIgnoringCopies(BasePtr, *MRI);
    Register WaveBase = getWaveAddress(BasePtrDef);
    if (!WaveBase)
      return {};

    return {{
        [=](MachineInstrBuilder &MIB) { // rsrc
          MIB.addReg(Info->getScratchRSrcReg());
        },
        [=](MachineInstrBuilder &MIB) { // soffset
          MIB.addReg(WaveBase);
        },
        [=](MachineInstrBuilder &MIB) { MIB.addImm(Offset); } // offset
    }};
  }

  if (!mi_match(Root.getReg(), *MRI, m_ICst(Offset)) ||
      !TII.isLegalMUBUFImmOffset(Offset))
    return {};

  return {{
      [=](MachineInstrBuilder &MIB) { // rsrc
        MIB.addReg(Info->getScratchRSrcReg());
      },
      [=](MachineInstrBuilder &MIB) { // soffset
        MIB.addImm(0);
      },
      [=](MachineInstrBuilder &MIB) { MIB.addImm(Offset); } // offset
  }};
}

std::pair<Register, unsigned>
AMDGPUInstructionSelector::selectDS1Addr1OffsetImpl(MachineOperand &Root) const {
  const MachineInstr *RootDef = MRI->getVRegDef(Root.getReg());
  int64_t ConstAddr = 0;

  Register PtrBase;
  int64_t Offset;
  std::tie(PtrBase, Offset, std::ignore) =
      getPtrBaseWithConstantOffset(Root.getReg(), *MRI);

  if (Offset) {
    if (isDSOffsetLegal(PtrBase, Offset)) {
      // (add n0, c0)
      return std::pair(PtrBase, Offset);
    }
  } else if (RootDef->getOpcode() == AMDGPU::G_SUB) {
    // TODO


  } else if (mi_match(Root.getReg(), *MRI, m_ICst(ConstAddr))) {
    // TODO

  }

  return std::pair(Root.getReg(), 0);
}

InstructionSelector::ComplexRendererFns
AMDGPUInstructionSelector::selectDS1Addr1Offset(MachineOperand &Root) const {
  Register Reg;
  unsigned Offset;
  std::tie(Reg, Offset) = selectDS1Addr1OffsetImpl(Root);
  return {{
      [=](MachineInstrBuilder &MIB) { MIB.addReg(Reg); },
      [=](MachineInstrBuilder &MIB) { MIB.addImm(Offset); }
    }};
}

InstructionSelector::ComplexRendererFns
AMDGPUInstructionSelector::selectDS64Bit4ByteAligned(MachineOperand &Root) const {
  return selectDSReadWrite2(Root, 4);
}

InstructionSelector::ComplexRendererFns
AMDGPUInstructionSelector::selectDS128Bit8ByteAligned(MachineOperand &Root) const {
  return selectDSReadWrite2(Root, 8);
}

InstructionSelector::ComplexRendererFns
AMDGPUInstructionSelector::selectDSReadWrite2(MachineOperand &Root,
                                              unsigned Size) const {
  Register Reg;
  unsigned Offset;
  std::tie(Reg, Offset) = selectDSReadWrite2Impl(Root, Size);
  return {{
      [=](MachineInstrBuilder &MIB) { MIB.addReg(Reg); },
      [=](MachineInstrBuilder &MIB) { MIB.addImm(Offset); },
      [=](MachineInstrBuilder &MIB) { MIB.addImm(Offset+1); }
    }};
}

std::pair<Register, unsigned>
AMDGPUInstructionSelector::selectDSReadWrite2Impl(MachineOperand &Root,
                                                  unsigned Size) const {
  const MachineInstr *RootDef = MRI->getVRegDef(Root.getReg());
  int64_t ConstAddr = 0;

  Register PtrBase;
  int64_t Offset;
  std::tie(PtrBase, Offset, std::ignore) =
      getPtrBaseWithConstantOffset(Root.getReg(), *MRI);

  if (Offset) {
    int64_t OffsetValue0 = Offset;
    int64_t OffsetValue1 = Offset + Size;
    if (isDSOffset2Legal(PtrBase, OffsetValue0, OffsetValue1, Size)) {
      // (add n0, c0)
      return std::pair(PtrBase, OffsetValue0 / Size);
    }
  } else if (RootDef->getOpcode() == AMDGPU::G_SUB) {
    // TODO

  } else if (mi_match(Root.getReg(), *MRI, m_ICst(ConstAddr))) {
    // TODO

  }

  return std::pair(Root.getReg(), 0);
}

/// If \p Root is a G_PTR_ADD with a G_CONSTANT on the right hand side, return
/// the base value with the constant offset, and if the offset computation is
/// known to be inbounds. There may be intervening copies between \p Root and
/// the identified constant. Returns \p Root, 0, false if this does not match
/// the pattern.
std::tuple<Register, int64_t, bool>
AMDGPUInstructionSelector::getPtrBaseWithConstantOffset(
    Register Root, const MachineRegisterInfo &MRI) const {
  MachineInstr *RootI = getDefIgnoringCopies(Root, MRI);
  if (RootI->getOpcode() != TargetOpcode::G_PTR_ADD)
    return {Root, 0, false};

  MachineOperand &RHS = RootI->getOperand(2);
  std::optional<ValueAndVReg> MaybeOffset =
      getIConstantVRegValWithLookThrough(RHS.getReg(), MRI);
  if (!MaybeOffset)
    return {Root, 0, false};
  bool IsInBounds = RootI->getFlag(MachineInstr::MIFlag::InBounds);
  return {RootI->getOperand(1).getReg(), MaybeOffset->Value.getSExtValue(),
          IsInBounds};
}

static void addZeroImm(MachineInstrBuilder &MIB) {
  MIB.addImm(0);
}

/// Return a resource descriptor for use with an arbitrary 64-bit pointer. If \p
/// BasePtr is not valid, a null base pointer will be used.
static Register buildRSRC(MachineIRBuilder &B, MachineRegisterInfo &MRI,
                          uint32_t FormatLo, uint32_t FormatHi,
                          Register BasePtr) {
  Register RSrc2 = MRI.createVirtualRegister(&AMDGPU::SReg_32RegClass);
  Register RSrc3 = MRI.createVirtualRegister(&AMDGPU::SReg_32RegClass);
  Register RSrcHi = MRI.createVirtualRegister(&AMDGPU::SReg_64RegClass);
  Register RSrc = MRI.createVirtualRegister(&AMDGPU::SGPR_128RegClass);

  B.buildInstr(AMDGPU::S_MOV_B32)
    .addDef(RSrc2)
    .addImm(FormatLo);
  B.buildInstr(AMDGPU::S_MOV_B32)
    .addDef(RSrc3)
    .addImm(FormatHi);

  // Build the half of the subregister with the constants before building the
  // full 128-bit register. If we are building multiple resource descriptors,
  // this will allow CSEing of the 2-component register.
  B.buildInstr(AMDGPU::REG_SEQUENCE)
    .addDef(RSrcHi)
    .addReg(RSrc2)
    .addImm(AMDGPU::sub0)
    .addReg(RSrc3)
    .addImm(AMDGPU::sub1);

  Register RSrcLo = BasePtr;
  if (!BasePtr) {
    RSrcLo = MRI.createVirtualRegister(&AMDGPU::SReg_64RegClass);
    B.buildInstr(AMDGPU::S_MOV_B64)
      .addDef(RSrcLo)
      .addImm(0);
  }

  B.buildInstr(AMDGPU::REG_SEQUENCE)
    .addDef(RSrc)
    .addReg(RSrcLo)
    .addImm(AMDGPU::sub0_sub1)
    .addReg(RSrcHi)
    .addImm(AMDGPU::sub2_sub3);

  return RSrc;
}

static Register buildAddr64RSrc(MachineIRBuilder &B, MachineRegisterInfo &MRI,
                                const SIInstrInfo &TII, Register BasePtr) {
  uint64_t DefaultFormat = TII.getDefaultRsrcDataFormat();

  // FIXME: Why are half the "default" bits ignored based on the addressing
  // mode?
  return buildRSRC(B, MRI, 0, Hi_32(DefaultFormat), BasePtr);
}

static Register buildOffsetSrc(MachineIRBuilder &B, MachineRegisterInfo &MRI,
                               const SIInstrInfo &TII, Register BasePtr) {
  uint64_t DefaultFormat = TII.getDefaultRsrcDataFormat();

  // FIXME: Why are half the "default" bits ignored based on the addressing
  // mode?
  return buildRSRC(B, MRI, -1, Hi_32(DefaultFormat), BasePtr);
}

AMDGPUInstructionSelector::MUBUFAddressData
AMDGPUInstructionSelector::parseMUBUFAddress(Register Src) const {
  MUBUFAddressData Data;
  Data.N0 = Src;

  Register PtrBase;
  int64_t Offset;

  std::tie(PtrBase, Offset, std::ignore) =
      getPtrBaseWithConstantOffset(Src, *MRI);
  if (isUInt<32>(Offset)) {
    Data.N0 = PtrBase;
    Data.Offset = Offset;
  }

  if (MachineInstr *InputAdd
      = getOpcodeDef(TargetOpcode::G_PTR_ADD, Data.N0, *MRI)) {
    Data.N2 = InputAdd->getOperand(1).getReg();
    Data.N3 = InputAdd->getOperand(2).getReg();

    // FIXME: Need to fix extra SGPR->VGPRcopies inserted
    // FIXME: Don't know this was defined by operand 0
    //
    // TODO: Remove this when we have copy folding optimizations after
    // RegBankSelect.
    Data.N2 = getDefIgnoringCopies(Data.N2, *MRI)->getOperand(0).getReg();
    Data.N3 = getDefIgnoringCopies(Data.N3, *MRI)->getOperand(0).getReg();
  }

  return Data;
}

/// Return if the addr64 mubuf mode should be used for the given address.
bool AMDGPUInstructionSelector::shouldUseAddr64(MUBUFAddressData Addr) const {
  // (ptr_add N2, N3) -> addr64, or
  // (ptr_add (ptr_add N2, N3), C1) -> addr64
  if (Addr.N2)
    return true;

  const RegisterBank *N0Bank = RBI.getRegBank(Addr.N0, *MRI, TRI);
  return N0Bank->getID() == AMDGPU::VGPRRegBankID;
}

/// Split an immediate offset \p ImmOffset depending on whether it fits in the
/// immediate field. Modifies \p ImmOffset and sets \p SOffset to the variable
/// component.
void AMDGPUInstructionSelector::splitIllegalMUBUFOffset(
  MachineIRBuilder &B, Register &SOffset, int64_t &ImmOffset) const {
  if (TII.isLegalMUBUFImmOffset(ImmOffset))
    return;

  // Illegal offset, store it in soffset.
  SOffset = MRI->createVirtualRegister(&AMDGPU::SReg_32RegClass);
  B.buildInstr(AMDGPU::S_MOV_B32)
    .addDef(SOffset)
    .addImm(ImmOffset);
  ImmOffset = 0;
}

bool AMDGPUInstructionSelector::selectMUBUFAddr64Impl(
  MachineOperand &Root, Register &VAddr, Register &RSrcReg,
  Register &SOffset, int64_t &Offset) const {
  // FIXME: Predicates should stop this from reaching here.
  // addr64 bit was removed for volcanic islands.
  if (!STI.hasAddr64() || STI.useFlatForGlobal())
    return false;

  MUBUFAddressData AddrData = parseMUBUFAddress(Root.getReg());
  if (!shouldUseAddr64(AddrData))
    return false;

  Register N0 = AddrData.N0;
  Register N2 = AddrData.N2;
  Register N3 = AddrData.N3;
  Offset = AddrData.Offset;

  // Base pointer for the SRD.
  Register SRDPtr;

  if (N2) {
    if (RBI.getRegBank(N2, *MRI, TRI)->getID() == AMDGPU::VGPRRegBankID) {
      assert(N3);
      if (RBI.getRegBank(N3, *MRI, TRI)->getID() == AMDGPU::VGPRRegBankID) {
        // Both N2 and N3 are divergent. Use N0 (the result of the add) as the
        // addr64, and construct the default resource from a 0 address.
        VAddr = N0;
      } else {
        SRDPtr = N3;
        VAddr = N2;
      }
    } else {
      // N2 is not divergent.
      SRDPtr = N2;
      VAddr = N3;
    }
  } else if (RBI.getRegBank(N0, *MRI, TRI)->getID() == AMDGPU::VGPRRegBankID) {
    // Use the default null pointer in the resource
    VAddr = N0;
  } else {
    // N0 -> offset, or
    // (N0 + C1) -> offset
    SRDPtr = N0;
  }

  MachineIRBuilder B(*Root.getParent());
  RSrcReg = buildAddr64RSrc(B, *MRI, TII, SRDPtr);
  splitIllegalMUBUFOffset(B, SOffset, Offset);
  return true;
}

bool AMDGPUInstructionSelector::selectMUBUFOffsetImpl(
  MachineOperand &Root, Register &RSrcReg, Register &SOffset,
  int64_t &Offset) const {

  // FIXME: Pattern should not reach here.
  if (STI.useFlatForGlobal())
    return false;

  MUBUFAddressData AddrData = parseMUBUFAddress(Root.getReg());
  if (shouldUseAddr64(AddrData))
    return false;

  // N0 -> offset, or
  // (N0 + C1) -> offset
  Register SRDPtr = AddrData.N0;
  Offset = AddrData.Offset;

  // TODO: Look through extensions for 32-bit soffset.
  MachineIRBuilder B(*Root.getParent());

  RSrcReg = buildOffsetSrc(B, *MRI, TII, SRDPtr);
  splitIllegalMUBUFOffset(B, SOffset, Offset);
  return true;
}

InstructionSelector::ComplexRendererFns
AMDGPUInstructionSelector::selectMUBUFAddr64(MachineOperand &Root) const {
  Register VAddr;
  Register RSrcReg;
  Register SOffset;
  int64_t Offset = 0;

  if (!selectMUBUFAddr64Impl(Root, VAddr, RSrcReg, SOffset, Offset))
    return {};

  // FIXME: Use defaulted operands for trailing 0s and remove from the complex
  // pattern.
  return {{
      [=](MachineInstrBuilder &MIB) {  // rsrc
        MIB.addReg(RSrcReg);
      },
      [=](MachineInstrBuilder &MIB) { // vaddr
        MIB.addReg(VAddr);
      },
      [=](MachineInstrBuilder &MIB) { // soffset
        if (SOffset)
          MIB.addReg(SOffset);
        else if (STI.hasRestrictedSOffset())
          MIB.addReg(AMDGPU::SGPR_NULL);
        else
          MIB.addImm(0);
      },
      [=](MachineInstrBuilder &MIB) { // offset
        MIB.addImm(Offset);
      },
      addZeroImm, //  cpol
      addZeroImm, //  tfe
      addZeroImm  //  swz
    }};
}

InstructionSelector::ComplexRendererFns
AMDGPUInstructionSelector::selectMUBUFOffset(MachineOperand &Root) const {
  Register RSrcReg;
  Register SOffset;
  int64_t Offset = 0;

  if (!selectMUBUFOffsetImpl(Root, RSrcReg, SOffset, Offset))
    return {};

  return {{
      [=](MachineInstrBuilder &MIB) {  // rsrc
        MIB.addReg(RSrcReg);
      },
      [=](MachineInstrBuilder &MIB) { // soffset
        if (SOffset)
          MIB.addReg(SOffset);
        else if (STI.hasRestrictedSOffset())
          MIB.addReg(AMDGPU::SGPR_NULL);
        else
          MIB.addImm(0);
      },
      [=](MachineInstrBuilder &MIB) { MIB.addImm(Offset); }, // offset
      addZeroImm, //  cpol
      addZeroImm, //  tfe
      addZeroImm, //  swz
    }};
}

InstructionSelector::ComplexRendererFns
AMDGPUInstructionSelector::selectBUFSOffset(MachineOperand &Root) const {

  Register SOffset = Root.getReg();

  if (STI.hasRestrictedSOffset() && mi_match(SOffset, *MRI, m_ZeroInt()))
    SOffset = AMDGPU::SGPR_NULL;

  return {{[=](MachineInstrBuilder &MIB) { MIB.addReg(SOffset); }}};
}

/// Get an immediate that must be 32-bits, and treated as zero extended.
static std::optional<uint64_t>
getConstantZext32Val(Register Reg, const MachineRegisterInfo &MRI) {
  // getIConstantVRegVal sexts any values, so see if that matters.
  std::optional<int64_t> OffsetVal = getIConstantVRegSExtVal(Reg, MRI);
  if (!OffsetVal || !isInt<32>(*OffsetVal))
    return std::nullopt;
  return Lo_32(*OffsetVal);
}

InstructionSelector::ComplexRendererFns
AMDGPUInstructionSelector::selectSMRDBufferImm(MachineOperand &Root) const {
  std::optional<uint64_t> OffsetVal =
      Root.isImm() ? Root.getImm() : getConstantZext32Val(Root.getReg(), *MRI);
  if (!OffsetVal)
    return {};

  std::optional<int64_t> EncodedImm =
      AMDGPU::getSMRDEncodedOffset(STI, *OffsetVal, true);
  if (!EncodedImm)
    return {};

  return {{ [=](MachineInstrBuilder &MIB) { MIB.addImm(*EncodedImm); }  }};
}

InstructionSelector::ComplexRendererFns
AMDGPUInstructionSelector::selectSMRDBufferImm32(MachineOperand &Root) const {
  assert(STI.getGeneration() == AMDGPUSubtarget::SEA_ISLANDS);

  std::optional<uint64_t> OffsetVal = getConstantZext32Val(Root.getReg(), *MRI);
  if (!OffsetVal)
    return {};

  std::optional<int64_t> EncodedImm =
      AMDGPU::getSMRDEncodedLiteralOffset32(STI, *OffsetVal);
  if (!EncodedImm)
    return {};

  return {{ [=](MachineInstrBuilder &MIB) { MIB.addImm(*EncodedImm); }  }};
}

InstructionSelector::ComplexRendererFns
AMDGPUInstructionSelector::selectSMRDBufferSgprImm(MachineOperand &Root) const {
  // Match the (soffset + offset) pair as a 32-bit register base and
  // an immediate offset.
  Register SOffset;
  unsigned Offset;
  std::tie(SOffset, Offset) = AMDGPU::getBaseWithConstantOffset(
      *MRI, Root.getReg(), VT, /*CheckNUW*/ true);
  if (!SOffset)
    return std::nullopt;

  std::optional<int64_t> EncodedOffset =
      AMDGPU::getSMRDEncodedOffset(STI, Offset, /* IsBuffer */ true);
  if (!EncodedOffset)
    return std::nullopt;

  assert(MRI->getType(SOffset) == LLT::scalar(32));
  return {{[=](MachineInstrBuilder &MIB) { MIB.addReg(SOffset); },
           [=](MachineInstrBuilder &MIB) { MIB.addImm(*EncodedOffset); }}};
}

std::pair<Register, unsigned>
AMDGPUInstructionSelector::selectVOP3PMadMixModsImpl(MachineOperand &Root,
                                                     bool &Matched) const {
  Matched = false;

  Register Src;
  unsigned Mods;
  std::tie(Src, Mods) = selectVOP3ModsImpl(Root.getReg());

  if (mi_match(Src, *MRI, m_GFPExt(m_Reg(Src)))) {
    assert(MRI->getType(Src) == LLT::scalar(16));

    // Only change Src if src modifier could be gained. In such cases new Src
    // could be sgpr but this does not violate constant bus restriction for
    // instruction that is being selected.
    Src = stripBitCast(Src, *MRI);

    const auto CheckAbsNeg = [&]() {
      // Be careful about folding modifiers if we already have an abs. fneg is
      // applied last, so we don't want to apply an earlier fneg.
      if ((Mods & SISrcMods::ABS) == 0) {
        unsigned ModsTmp;
        std::tie(Src, ModsTmp) = selectVOP3ModsImpl(Src);

        if ((ModsTmp & SISrcMods::NEG) != 0)
          Mods ^= SISrcMods::NEG;

        if ((ModsTmp & SISrcMods::ABS) != 0)
          Mods |= SISrcMods::ABS;
      }
    };

    CheckAbsNeg();

    // op_sel/op_sel_hi decide the source type and source.
    // If the source's op_sel_hi is set, it indicates to do a conversion from
    // fp16. If the sources's op_sel is set, it picks the high half of the
    // source register.

    Mods |= SISrcMods::OP_SEL_1;

    if (isExtractHiElt(*MRI, Src, Src)) {
      Mods |= SISrcMods::OP_SEL_0;
      CheckAbsNeg();
    }

    Matched = true;
  }

  return {Src, Mods};
}

InstructionSelector::ComplexRendererFns
AMDGPUInstructionSelector::selectVOP3PMadMixModsExt(
    MachineOperand &Root) const {
  Register Src;
  unsigned Mods;
  bool Matched;
  std::tie(Src, Mods) = selectVOP3PMadMixModsImpl(Root, Matched);
  if (!Matched)
    return {};

  return {{
      [=](MachineInstrBuilder &MIB) { MIB.addReg(Src); },
      [=](MachineInstrBuilder &MIB) { MIB.addImm(Mods); } // src_mods
  }};
}

InstructionSelector::ComplexRendererFns
AMDGPUInstructionSelector::selectVOP3PMadMixMods(MachineOperand &Root) const {
  Register Src;
  unsigned Mods;
  bool Matched;
  std::tie(Src, Mods) = selectVOP3PMadMixModsImpl(Root, Matched);

  return {{
      [=](MachineInstrBuilder &MIB) { MIB.addReg(Src); },
      [=](MachineInstrBuilder &MIB) { MIB.addImm(Mods); } // src_mods
  }};
}

bool AMDGPUInstructionSelector::selectSBarrierSignalIsfirst(
    MachineInstr &I, Intrinsic::ID IntrID) const {
  MachineBasicBlock *MBB = I.getParent();
  const DebugLoc &DL = I.getDebugLoc();
  Register CCReg = I.getOperand(0).getReg();

  // Set SCC to true, in case the barrier instruction gets converted to a NOP.
  BuildMI(*MBB, &I, DL, TII.get(AMDGPU::S_CMP_EQ_U32)).addImm(0).addImm(0);

  BuildMI(*MBB, &I, DL, TII.get(AMDGPU::S_BARRIER_SIGNAL_ISFIRST_IMM))
      .addImm(I.getOperand(2).getImm());

  BuildMI(*MBB, &I, DL, TII.get(AMDGPU::COPY), CCReg).addReg(AMDGPU::SCC);

  I.eraseFromParent();
  return RBI.constrainGenericRegister(CCReg, AMDGPU::SReg_32_XM0_XEXECRegClass,
                                      *MRI);
}

bool AMDGPUInstructionSelector::selectSGetBarrierState(
    MachineInstr &I, Intrinsic::ID IntrID) const {
  MachineBasicBlock *MBB = I.getParent();
  const DebugLoc &DL = I.getDebugLoc();
  const MachineOperand &BarOp = I.getOperand(2);
  std::optional<int64_t> BarValImm =
      getIConstantVRegSExtVal(BarOp.getReg(), *MRI);

  if (!BarValImm) {
    auto CopyMIB = BuildMI(*MBB, &I, DL, TII.get(AMDGPU::COPY), AMDGPU::M0)
                       .addReg(BarOp.getReg());
    constrainSelectedInstRegOperands(*CopyMIB, TII, TRI, RBI);
  }
  MachineInstrBuilder MIB;
  unsigned Opc = BarValImm ? AMDGPU::S_GET_BARRIER_STATE_IMM
                           : AMDGPU::S_GET_BARRIER_STATE_M0;
  MIB = BuildMI(*MBB, &I, DL, TII.get(Opc));

  auto DstReg = I.getOperand(0).getReg();
  const TargetRegisterClass *DstRC =
      TRI.getConstrainedRegClassForOperand(I.getOperand(0), *MRI);
  if (!DstRC || !RBI.constrainGenericRegister(DstReg, *DstRC, *MRI))
    return false;
  MIB.addDef(DstReg);
  if (BarValImm) {
    MIB.addImm(*BarValImm);
  }
  I.eraseFromParent();
  return true;
}

unsigned getNamedBarrierOp(bool HasInlineConst, Intrinsic::ID IntrID) {
  if (HasInlineConst) {
    switch (IntrID) {
    default:
      llvm_unreachable("not a named barrier op");
    case Intrinsic::amdgcn_s_barrier_join:
      return AMDGPU::S_BARRIER_JOIN_IMM;
    case Intrinsic::amdgcn_s_wakeup_barrier:
      return AMDGPU::S_WAKEUP_BARRIER_IMM;
    case Intrinsic::amdgcn_s_get_named_barrier_state:
      return AMDGPU::S_GET_BARRIER_STATE_IMM;
    };
  } else {
    switch (IntrID) {
    default:
      llvm_unreachable("not a named barrier op");
    case Intrinsic::amdgcn_s_barrier_join:
      return AMDGPU::S_BARRIER_JOIN_M0;
    case Intrinsic::amdgcn_s_wakeup_barrier:
      return AMDGPU::S_WAKEUP_BARRIER_M0;
    case Intrinsic::amdgcn_s_get_named_barrier_state:
      return AMDGPU::S_GET_BARRIER_STATE_M0;
    };
  }
}

bool AMDGPUInstructionSelector::selectNamedBarrierInit(
    MachineInstr &I, Intrinsic::ID IntrID) const {
  MachineBasicBlock *MBB = I.getParent();
  const DebugLoc &DL = I.getDebugLoc();
  const MachineOperand &BarOp = I.getOperand(1);
  const MachineOperand &CntOp = I.getOperand(2);

  // BarID = (BarOp >> 4) & 0x3F
  Register TmpReg0 = MRI->createVirtualRegister(&AMDGPU::SReg_32RegClass);
  BuildMI(*MBB, &I, DL, TII.get(AMDGPU::S_LSHR_B32), TmpReg0)
      .add(BarOp)
      .addImm(4u)
      .setOperandDead(3); // Dead scc

  Register TmpReg1 = MRI->createVirtualRegister(&AMDGPU::SReg_32RegClass);
  BuildMI(*MBB, &I, DL, TII.get(AMDGPU::S_AND_B32), TmpReg1)
      .addReg(TmpReg0)
      .addImm(0x3F)
      .setOperandDead(3); // Dead scc

  // MO = ((CntOp & 0x3F) << shAmt) | BarID
  Register TmpReg2 = MRI->createVirtualRegister(&AMDGPU::SReg_32RegClass);
  BuildMI(*MBB, &I, DL, TII.get(AMDGPU::S_AND_B32), TmpReg2)
      .add(CntOp)
      .addImm(0x3F)
      .setOperandDead(3); // Dead scc

  Register TmpReg3 = MRI->createVirtualRegister(&AMDGPU::SReg_32RegClass);
  constexpr unsigned ShAmt = 16;
  BuildMI(*MBB, &I, DL, TII.get(AMDGPU::S_LSHL_B32), TmpReg3)
      .addReg(TmpReg2)
      .addImm(ShAmt)
      .setOperandDead(3); // Dead scc

  Register TmpReg4 = MRI->createVirtualRegister(&AMDGPU::SReg_32RegClass);
  BuildMI(*MBB, &I, DL, TII.get(AMDGPU::S_OR_B32), TmpReg4)
      .addReg(TmpReg1)
      .addReg(TmpReg3)
      .setOperandDead(3); // Dead scc;

  auto CopyMIB =
      BuildMI(*MBB, &I, DL, TII.get(AMDGPU::COPY), AMDGPU::M0).addReg(TmpReg4);
  constrainSelectedInstRegOperands(*CopyMIB, TII, TRI, RBI);

  unsigned Opc = IntrID == Intrinsic::amdgcn_s_barrier_init
                     ? AMDGPU::S_BARRIER_INIT_M0
                     : AMDGPU::S_BARRIER_SIGNAL_M0;
  MachineInstrBuilder MIB;
  MIB = BuildMI(*MBB, &I, DL, TII.get(Opc));

  I.eraseFromParent();
  return true;
}

bool AMDGPUInstructionSelector::selectNamedBarrierInst(
    MachineInstr &I, Intrinsic::ID IntrID) const {
  MachineBasicBlock *MBB = I.getParent();
  const DebugLoc &DL = I.getDebugLoc();
  MachineOperand BarOp = IntrID == Intrinsic::amdgcn_s_get_named_barrier_state
                             ? I.getOperand(2)
                             : I.getOperand(1);
  std::optional<int64_t> BarValImm =
      getIConstantVRegSExtVal(BarOp.getReg(), *MRI);

  if (!BarValImm) {
    // BarID = (BarOp >> 4) & 0x3F
    Register TmpReg0 = MRI->createVirtualRegister(&AMDGPU::SReg_32RegClass);
    BuildMI(*MBB, &I, DL, TII.get(AMDGPU::S_LSHR_B32), TmpReg0)
        .addReg(BarOp.getReg())
        .addImm(4u)
        .setOperandDead(3); // Dead scc;

    Register TmpReg1 = MRI->createVirtualRegister(&AMDGPU::SReg_32RegClass);
    BuildMI(*MBB, &I, DL, TII.get(AMDGPU::S_AND_B32), TmpReg1)
        .addReg(TmpReg0)
        .addImm(0x3F)
        .setOperandDead(3); // Dead scc;

    auto CopyMIB = BuildMI(*MBB, &I, DL, TII.get(AMDGPU::COPY), AMDGPU::M0)
                       .addReg(TmpReg1);
    constrainSelectedInstRegOperands(*CopyMIB, TII, TRI, RBI);
  }

  MachineInstrBuilder MIB;
  unsigned Opc = getNamedBarrierOp(BarValImm.has_value(), IntrID);
  MIB = BuildMI(*MBB, &I, DL, TII.get(Opc));

  if (IntrID == Intrinsic::amdgcn_s_get_named_barrier_state) {
    auto DstReg = I.getOperand(0).getReg();
    const TargetRegisterClass *DstRC =
        TRI.getConstrainedRegClassForOperand(I.getOperand(0), *MRI);
    if (!DstRC || !RBI.constrainGenericRegister(DstReg, *DstRC, *MRI))
      return false;
    MIB.addDef(DstReg);
  }

  if (BarValImm) {
    auto BarId = ((*BarValImm) >> 4) & 0x3F;
    MIB.addImm(BarId);
  }

  I.eraseFromParent();
  return true;
}

void AMDGPUInstructionSelector::renderTruncImm32(MachineInstrBuilder &MIB,
                                                 const MachineInstr &MI,
                                                 int OpIdx) const {
  assert(MI.getOpcode() == TargetOpcode::G_CONSTANT && OpIdx == -1 &&
         "Expected G_CONSTANT");
  MIB.addImm(MI.getOperand(1).getCImm()->getSExtValue());
}

void AMDGPUInstructionSelector::renderNegateImm(MachineInstrBuilder &MIB,
                                                const MachineInstr &MI,
                                                int OpIdx) const {
  assert(MI.getOpcode() == TargetOpcode::G_CONSTANT && OpIdx == -1 &&
         "Expected G_CONSTANT");
  MIB.addImm(-MI.getOperand(1).getCImm()->getSExtValue());
}

void AMDGPUInstructionSelector::renderBitcastFPImm(MachineInstrBuilder &MIB,
                                                   const MachineInstr &MI,
                                                   int OpIdx) const {
  const MachineOperand &Op = MI.getOperand(1);
  assert(MI.getOpcode() == TargetOpcode::G_FCONSTANT && OpIdx == -1);
  MIB.addImm(Op.getFPImm()->getValueAPF().bitcastToAPInt().getZExtValue());
}

void AMDGPUInstructionSelector::renderPopcntImm(MachineInstrBuilder &MIB,
                                                const MachineInstr &MI,
                                                int OpIdx) const {
  assert(MI.getOpcode() == TargetOpcode::G_CONSTANT && OpIdx == -1 &&
         "Expected G_CONSTANT");
  MIB.addImm(MI.getOperand(1).getCImm()->getValue().popcount());
}

/// This only really exists to satisfy DAG type checking machinery, so is a
/// no-op here.
void AMDGPUInstructionSelector::renderTruncTImm(MachineInstrBuilder &MIB,
                                                const MachineInstr &MI,
                                                int OpIdx) const {
  const MachineOperand &Op = MI.getOperand(OpIdx);
  int64_t Imm;
  if (Op.isReg() && mi_match(Op.getReg(), *MRI, m_ICst(Imm)))
    MIB.addImm(Imm);
  else
    MIB.addImm(Op.getImm());
}

void AMDGPUInstructionSelector::renderZextBoolTImm(MachineInstrBuilder &MIB,
                                                   const MachineInstr &MI,
                                                   int OpIdx) const {
  MIB.addImm(MI.getOperand(OpIdx).getImm() != 0);
}

void AMDGPUInstructionSelector::renderOpSelTImm(MachineInstrBuilder &MIB,
                                                const MachineInstr &MI,
                                                int OpIdx) const {
  assert(OpIdx >= 0 && "expected to match an immediate operand");
  MIB.addImm(MI.getOperand(OpIdx).getImm() ? (int64_t)SISrcMods::OP_SEL_0 : 0);
}

void AMDGPUInstructionSelector::renderSrcAndDstSelToOpSelXForm_0_0(
    MachineInstrBuilder &MIB, const MachineInstr &MI, int OpIdx) const {
  assert(OpIdx >= 0 && "expected to match an immediate operand");
  MIB.addImm(
      (MI.getOperand(OpIdx).getImm() & 0x1) ? (int64_t)SISrcMods::OP_SEL_0 : 0);
}

void AMDGPUInstructionSelector::renderSrcAndDstSelToOpSelXForm_0_1(
    MachineInstrBuilder &MIB, const MachineInstr &MI, int OpIdx) const {
  assert(OpIdx >= 0 && "expected to match an immediate operand");
  MIB.addImm((MI.getOperand(OpIdx).getImm() & 0x1)
                 ? (int64_t)(SISrcMods::OP_SEL_0 | SISrcMods::DST_OP_SEL)
                 : (int64_t)SISrcMods::DST_OP_SEL);
}

void AMDGPUInstructionSelector::renderSrcAndDstSelToOpSelXForm_1_0(
    MachineInstrBuilder &MIB, const MachineInstr &MI, int OpIdx) const {
  assert(OpIdx >= 0 && "expected to match an immediate operand");
  MIB.addImm(
      (MI.getOperand(OpIdx).getImm() & 0x2) ? (int64_t)SISrcMods::OP_SEL_0 : 0);
}

void AMDGPUInstructionSelector::renderSrcAndDstSelToOpSelXForm_1_1(
    MachineInstrBuilder &MIB, const MachineInstr &MI, int OpIdx) const {
  assert(OpIdx >= 0 && "expected to match an immediate operand");
  MIB.addImm((MI.getOperand(OpIdx).getImm() & 0x2)
                 ? (int64_t)(SISrcMods::OP_SEL_0)
                 : 0);
}

void AMDGPUInstructionSelector::renderDstSelToOpSelXForm(
    MachineInstrBuilder &MIB, const MachineInstr &MI, int OpIdx) const {
  assert(OpIdx >= 0 && "expected to match an immediate operand");
  MIB.addImm(MI.getOperand(OpIdx).getImm() ? (int64_t)(SISrcMods::DST_OP_SEL)
                                           : 0);
}

void AMDGPUInstructionSelector::renderSrcSelToOpSelXForm(
    MachineInstrBuilder &MIB, const MachineInstr &MI, int OpIdx) const {
  assert(OpIdx >= 0 && "expected to match an immediate operand");
  MIB.addImm(MI.getOperand(OpIdx).getImm() ? (int64_t)(SISrcMods::OP_SEL_0)
                                           : 0);
}

void AMDGPUInstructionSelector::renderSrcAndDstSelToOpSelXForm_2_0(
    MachineInstrBuilder &MIB, const MachineInstr &MI, int OpIdx) const {
  assert(OpIdx >= 0 && "expected to match an immediate operand");
  MIB.addImm(
      (MI.getOperand(OpIdx).getImm() & 0x1) ? (int64_t)SISrcMods::OP_SEL_0 : 0);
}

void AMDGPUInstructionSelector::renderDstSelToOpSel3XFormXForm(
    MachineInstrBuilder &MIB, const MachineInstr &MI, int OpIdx) const {
  assert(OpIdx >= 0 && "expected to match an immediate operand");
  MIB.addImm((MI.getOperand(OpIdx).getImm() & 0x2)
                 ? (int64_t)SISrcMods::DST_OP_SEL
                 : 0);
}

void AMDGPUInstructionSelector::renderExtractCPol(MachineInstrBuilder &MIB,
                                                  const MachineInstr &MI,
                                                  int OpIdx) const {
  assert(OpIdx >= 0 && "expected to match an immediate operand");
  MIB.addImm(MI.getOperand(OpIdx).getImm() &
             (AMDGPU::isGFX12Plus(STI) ? AMDGPU::CPol::ALL
                                       : AMDGPU::CPol::ALL_pregfx12));
}

void AMDGPUInstructionSelector::renderExtractSWZ(MachineInstrBuilder &MIB,
                                                 const MachineInstr &MI,
                                                 int OpIdx) const {
  assert(OpIdx >= 0 && "expected to match an immediate operand");
  const bool Swizzle = MI.getOperand(OpIdx).getImm() &
                       (AMDGPU::isGFX12Plus(STI) ? AMDGPU::CPol::SWZ
                                                 : AMDGPU::CPol::SWZ_pregfx12);
  MIB.addImm(Swizzle);
}

void AMDGPUInstructionSelector::renderExtractCpolSetGLC(
    MachineInstrBuilder &MIB, const MachineInstr &MI, int OpIdx) const {
  assert(OpIdx >= 0 && "expected to match an immediate operand");
  const uint32_t Cpol = MI.getOperand(OpIdx).getImm() &
                        (AMDGPU::isGFX12Plus(STI) ? AMDGPU::CPol::ALL
                                                  : AMDGPU::CPol::ALL_pregfx12);
  MIB.addImm(Cpol | AMDGPU::CPol::GLC);
}

void AMDGPUInstructionSelector::renderFrameIndex(MachineInstrBuilder &MIB,
                                                 const MachineInstr &MI,
                                                 int OpIdx) const {
  MIB.addFrameIndex(MI.getOperand(1).getIndex());
}

void AMDGPUInstructionSelector::renderFPPow2ToExponent(MachineInstrBuilder &MIB,
                                                       const MachineInstr &MI,
                                                       int OpIdx) const {
  const APFloat &APF = MI.getOperand(1).getFPImm()->getValueAPF();
  int ExpVal = APF.getExactLog2Abs();
  assert(ExpVal != INT_MIN);
  MIB.addImm(ExpVal);
}

void AMDGPUInstructionSelector::renderRoundMode(MachineInstrBuilder &MIB,
                                                const MachineInstr &MI,
                                                int OpIdx) const {
  // "round.towardzero" -> TowardZero 0        -> FP_ROUND_ROUND_TO_ZERO 3
  // "round.tonearest"  -> NearestTiesToEven 1 -> FP_ROUND_ROUND_TO_NEAREST 0
  // "round.upward"     -> TowardPositive 2    -> FP_ROUND_ROUND_TO_INF 1
  // "round.downward    -> TowardNegative 3    -> FP_ROUND_ROUND_TO_NEGINF 2
  MIB.addImm((MI.getOperand(OpIdx).getImm() + 3) % 4);
}

void AMDGPUInstructionSelector::renderVOP3PModsNeg(MachineInstrBuilder &MIB,
                                                   const MachineInstr &MI,
                                                   int OpIdx) const {
  unsigned Mods = SISrcMods::OP_SEL_1;
  if (MI.getOperand(OpIdx).getImm())
    Mods ^= SISrcMods::NEG;
  MIB.addImm((int64_t)Mods);
}

void AMDGPUInstructionSelector::renderVOP3PModsNegs(MachineInstrBuilder &MIB,
                                                    const MachineInstr &MI,
                                                    int OpIdx) const {
  unsigned Mods = SISrcMods::OP_SEL_1;
  if (MI.getOperand(OpIdx).getImm())
    Mods ^= (SISrcMods::NEG | SISrcMods::NEG_HI);
  MIB.addImm((int64_t)Mods);
}

void AMDGPUInstructionSelector::renderVOP3PModsNegAbs(MachineInstrBuilder &MIB,
                                                      const MachineInstr &MI,
                                                      int OpIdx) const {
  unsigned Val = MI.getOperand(OpIdx).getImm();
  unsigned Mods = SISrcMods::OP_SEL_1; // default: none
  if (Val == 1) // neg
    Mods ^= SISrcMods::NEG;
  if (Val == 2) // abs
    Mods ^= SISrcMods::ABS;
  if (Val == 3) // neg and abs
    Mods ^= (SISrcMods::NEG | SISrcMods::ABS);
  MIB.addImm((int64_t)Mods);
}

void AMDGPUInstructionSelector::renderPrefetchLoc(MachineInstrBuilder &MIB,
                                                  const MachineInstr &MI,
                                                  int OpIdx) const {
  uint32_t V = MI.getOperand(2).getImm();
  V = (AMDGPU::CPol::SCOPE_MASK - (V & AMDGPU::CPol::SCOPE_MASK))
      << AMDGPU::CPol::SCOPE_SHIFT;
  if (!Subtarget->hasSafeCUPrefetch())
    V = std::max(V, (uint32_t)AMDGPU::CPol::SCOPE_SE); // CU scope is unsafe
  MIB.addImm(V);
}

/// Convert from 2-bit value to enum values used for op_sel* source modifiers.
void AMDGPUInstructionSelector::renderScaledMAIIntrinsicOperand(
    MachineInstrBuilder &MIB, const MachineInstr &MI, int OpIdx) const {
  unsigned Val = MI.getOperand(OpIdx).getImm();
  unsigned New = 0;
  if (Val & 0x1)
    New |= SISrcMods::OP_SEL_0;
  if (Val & 0x2)
    New |= SISrcMods::OP_SEL_1;
  MIB.addImm(New);
}

bool AMDGPUInstructionSelector::isInlineImmediate(const APInt &Imm) const {
  return TII.isInlineConstant(Imm);
}

bool AMDGPUInstructionSelector::isInlineImmediate(const APFloat &Imm) const {
  return TII.isInlineConstant(Imm);
}
