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

  constrainSelectedInstRegOperands(*Cmp, TII, TRI, RBI);

  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();
  constrainSelectedInstRegOperands(*Select, TII, TRI, RBI);
  return true;
}

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();
  constrainSelectedInstRegOperands(*RFL, TII, TRI, RBI);
  return true;
}

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, {}, 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
  constrainSelectedInstRegOperands(I, TII, TRI, RBI);
  return true;
}

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();
      constrainSelectedInstRegOperands(*Add, TII, TRI, RBI);
      return true;
    }

    if (STI.hasAddNoCarryInsts()) {
      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));
      constrainSelectedInstRegOperands(I, TII, TRI, RBI);
      return true;
    }

    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();
    constrainSelectedInstRegOperands(*Add, TII, TRI, RBI);
    return true;
  }

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

    constrainSelectedInstRegOperands(*Addc, TII, TRI, RBI);
  }

  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));
    constrainSelectedInstRegOperands(I, TII, TRI, RBI);
    return true;
  }

  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);
  constrainSelectedInstRegOperands(I, TII, TRI, RBI);
  return true;
}

// 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, {}, 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);
    // hi16:sreg_32 is not allowed so explicitly shift upper 16-bits.
    if (SrcBank->getID() == AMDGPU::SGPRRegBankID &&
        SubRegs[I] == AMDGPU::hi16) {
      BuildMI(*BB, &MI, DL, TII.get(AMDGPU::S_LSHR_B32), Dst.getReg())
          .addReg(SrcReg)
          .addImm(16);
    } else {
      BuildMI(*BB, &MI, DL, TII.get(TargetOpcode::COPY), Dst.getReg())
          .addReg(SrcReg, {}, 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);
    constrainSelectedInstRegOperands(*MIB, TII, TRI, RBI);

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

    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();
      constrainSelectedInstRegOperands(*MIB, TII, TRI, RBI);
      return true;
    }
    if (STI.hasSPackHL()) {
      Opc = AMDGPU::S_PACK_HL_B32_B16;
      MI.getOperand(1).setReg(ShiftSrc0);
    }
  }

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

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();
  constrainSelectedInstRegOperands(*MIB, TII, TRI, RBI);
  return true;
}

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();
  constrainSelectedInstRegOperands(*MIB, TII, TRI, RBI);
  return true;
}

// 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();
  constrainSelectedInstRegOperands(*MIB, TII, TRI, RBI);
  return true;
}

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);
    constrainSelectedInstRegOperands(*ICmp, TII, TRI, RBI);
    bool Ret =
        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);
  constrainSelectedInstRegOperands(*ICmp, TII, TRI, RBI);
  I.eraseFromParent();
  return true;
}

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);
  constrainSelectedInstRegOperands(*SelectedMI, TII, TRI, RBI);

  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
      constrainSelectedInstRegOperands(*And, TII, TRI, RBI);
    }
  }

  // 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();
  constrainSelectedInstRegOperands(*MIB, TII, TRI, RBI);
  return true;
}

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;

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

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();
  constrainSelectedInstRegOperands(*MIB, TII, TRI, RBI);
  return true;
}

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();
  constrainSelectedInstRegOperands(*MIB, TII, TRI, RBI);
  return true;
}

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_buffer_load_async_lds:
  case Intrinsic::amdgcn_raw_ptr_buffer_load_lds:
  case Intrinsic::amdgcn_raw_ptr_buffer_load_async_lds:
  case Intrinsic::amdgcn_struct_buffer_load_lds:
  case Intrinsic::amdgcn_struct_buffer_load_async_lds:
  case Intrinsic::amdgcn_struct_ptr_buffer_load_lds:
  case Intrinsic::amdgcn_struct_ptr_buffer_load_async_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_load_async_to_lds:
  case Intrinsic::amdgcn_global_load_lds:
  case Intrinsic::amdgcn_global_load_async_lds:
    return selectGlobalLoadLds(I);
  case Intrinsic::amdgcn_tensor_load_to_lds:
  case Intrinsic::amdgcn_tensor_store_from_lds:
    return selectTensorLoadStore(I, IntrinsicID);
  case Intrinsic::amdgcn_asyncmark:
  case Intrinsic::amdgcn_wait_asyncmark:
    if (!Subtarget->hasAsyncMark())
      return false;
    break;
  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_alloc_vgpr: {
    // S_ALLOC_VGPR doesn't have a destination register, it just implicitly sets
    // SCC. We then need to COPY it into the result vreg.
    MachineBasicBlock *MBB = I.getParent();
    const DebugLoc &DL = I.getDebugLoc();

    Register ResReg = I.getOperand(0).getReg();

    MachineInstr *AllocMI = BuildMI(*MBB, &I, DL, TII.get(AMDGPU::S_ALLOC_VGPR))
                                .add(I.getOperand(2));
    (void)BuildMI(*MBB, &I, DL, TII.get(AMDGPU::COPY), ResReg)
        .addReg(AMDGPU::SCC);
    I.eraseFromParent();
    constrainSelectedInstRegOperands(*AllocMI, TII, TRI, RBI);
    return RBI.constrainGenericRegister(ResReg, AMDGPU::SReg_32RegClass, *MRI);
  }
  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));

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

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

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

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, {}, 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, {}, AMDGPU::sub0);
    BuildMI(*MBB, I, DL, TII.get(AMDGPU::COPY), HiReg)
        .addReg(SrcReg, {}, 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();
      constrainSelectedInstRegOperands(*ExtI, TII, TRI, RBI);
      return true;
    }

    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();
    constrainSelectedInstRegOperands(*ExtI, TII, TRI, RBI);
    return true;
  }

  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, {}, 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, {}, 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, {}, 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) {
  // When unmerging a register that is composed of 2 x 16-bit values allow to
  // use an extract hi instruction for the upper 16 bits. We only need to check
  // the size of `In` as all defs are guaranteed to be the same type for
  // GUnmerge.
  if (auto *Unmerge = dyn_cast<GUnmerge>(MRI.getVRegDef(In))) {
    if (Unmerge->getNumDefs() == 2 && Unmerge->getOperand(1).getReg() == In &&
        MRI.getType(In).getSizeInBits() == 16) {
      Out = Unmerge->getSourceReg();
      return true;
    }
  }

  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, {}, AMDGPU::sub0);
  BuildMI(*BB, &MI, DL, TII.get(AMDGPU::COPY), HiReg)
      .addReg(Src, {}, 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, {}, AMDGPU::sub0);
  BuildMI(*BB, &MI, DL, TII.get(AMDGPU::COPY), HiReg)
      .addReg(Src, {}, 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();
    constrainSelectedInstRegOperands(*MIB, TII, TRI, RBI);
    return true;
  }

  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, {}, AMDGPU::sub0);
  BuildMI(*BB, &I, DL, TII.get(AMDGPU::COPY), HiReg)
      .addReg(SrcReg, {}, 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, {}, 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, {}, 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, {}, 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, {}, 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;
}

static bool isAsyncLDSDMA(Intrinsic::ID Intr) {
  switch (Intr) {
  case Intrinsic::amdgcn_raw_buffer_load_async_lds:
  case Intrinsic::amdgcn_raw_ptr_buffer_load_async_lds:
  case Intrinsic::amdgcn_struct_buffer_load_async_lds:
  case Intrinsic::amdgcn_struct_ptr_buffer_load_async_lds:
  case Intrinsic::amdgcn_load_async_to_lds:
  case Intrinsic::amdgcn_global_load_async_lds:
    return true;
  }
  return false;
}

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

  // 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
  MIB.addImm(isAsyncLDSDMA(IntrinsicID));

  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();
  constrainSelectedInstRegOperands(*MIB, TII, TRI, RBI);
  return true;
}

/// 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();
  Intrinsic::ID IntrinsicID = cast<GIntrinsic>(MI).getIntrinsicID();

  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
  MIB.addImm(isAsyncLDSDMA(IntrinsicID));

  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();
  constrainSelectedInstRegOperands(*MIB, TII, TRI, RBI);
  return true;
}

bool AMDGPUInstructionSelector::selectTensorLoadStore(MachineInstr &MI,
                                                      Intrinsic::ID IID) const {
  bool IsLoad = IID == Intrinsic::amdgcn_tensor_load_to_lds;
  unsigned Opc =
      IsLoad ? AMDGPU::TENSOR_LOAD_TO_LDS_d4 : AMDGPU::TENSOR_STORE_FROM_LDS_d4;
  int NumGroups = 4;

  // A lamda function to check whether an operand is a vector of all 0s.
  const auto isAllZeros = [&](MachineOperand &Opnd) {
    const MachineInstr *DefMI = MRI->getVRegDef(Opnd.getReg());
    if (!DefMI)
      return false;
    return llvm::isBuildVectorAllZeros(*DefMI, *MRI, true);
  };

  // Use _D2 version if both group 2 and 3 are zero-initialized.
  if (isAllZeros(MI.getOperand(3)) && isAllZeros(MI.getOperand(4))) {
    NumGroups = 2;
    Opc = IsLoad ? AMDGPU::TENSOR_LOAD_TO_LDS_d2
                 : AMDGPU::TENSOR_STORE_FROM_LDS_d2;
  }

  // TODO: Handle the fifth group: MI.getOpetand(5), which is silently ignored
  // for now because all existing targets only support up to 4 groups.
  MachineBasicBlock *MBB = MI.getParent();
  auto MIB = BuildMI(*MBB, &MI, MI.getDebugLoc(), TII.get(Opc))
                 .add(MI.getOperand(1))  // D# group 0
                 .add(MI.getOperand(2)); // D# group 1

  if (NumGroups >= 4) {         // Has at least 4 groups
    MIB.add(MI.getOperand(3))   // D# group 2
        .add(MI.getOperand(4)); // D# group 3
  }

  MIB.addImm(0)               // r128
      .add(MI.getOperand(6)); // cpol

  MI.eraseFromParent();
  return true;
}

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());
  constrainSelectedInstRegOperands(MI, TII, TRI, RBI);
  return true;
}

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

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

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 = std::move(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);
}

std::pair<Register, unsigned>
AMDGPUInstructionSelector::selectVOP3PModsF32Impl(Register Src) const {
  unsigned Mods;
  std::tie(Src, Mods) = selectVOP3ModsImpl(Src);
  Mods |= SISrcMods::OP_SEL_1;
  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::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;
    } else if (TargetInstrInfo::isGenericOpcode(Opc)) {
      // Keep same for generic op.
      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::selectVOP3PNoModsDOT(MachineOperand &Root) const {
  MachineRegisterInfo &MRI = Root.getParent()->getMF()->getRegInfo();
  Register Src;
  unsigned Mods;
  std::tie(Src, Mods) = selectVOP3PModsImpl(Root.getReg(), MRI, true /*IsDOT*/);
  if (Mods != SISrcMods::OP_SEL_1)
    return {};

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

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

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

InstructionSelector::ComplexRendererFns
AMDGPUInstructionSelector::selectVOP3PNoModsF32(MachineOperand &Root) const {
  Register Src;
  unsigned Mods;
  std::tie(Src, Mods) = selectVOP3PModsF32Impl(Root.getReg());
  if (Mods != SISrcMods::OP_SEL_1)
    return {};

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

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 != AMDGPU::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);

  // A member count of 0 means "keep existing member count". That plus a known
  // constant value for the barrier ID lets us use the immarg form.
  if (IntrID == Intrinsic::amdgcn_s_barrier_signal_var) {
    std::optional<int64_t> CntImm =
        getIConstantVRegSExtVal(CntOp.getReg(), *MRI);
    if (CntImm && *CntImm == 0) {
      std::optional<int64_t> BarValImm =
          getIConstantVRegSExtVal(BarOp.getReg(), *MRI);
      if (BarValImm) {
        auto BarID = ((*BarValImm) >> 4) & 0x3F;
        BuildMI(*MBB, &I, DL, TII.get(AMDGPU::S_BARRIER_SIGNAL_IMM))
            .addImm(BarID);
        I.eraseFromParent();
        return true;
      }
    }
  }

  // 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::renderCountTrailingOnesImm(
    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().countTrailingOnes());
}

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