//===- SIInstrInfo.cpp - SI Instruction Information  ----------------------===//
//
// 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
/// SI Implementation of TargetInstrInfo.
//
//===----------------------------------------------------------------------===//

#include "SIInstrInfo.h"
#include "AMDGPU.h"
#include "AMDGPUInstrInfo.h"
#include "AMDGPULaneMaskUtils.h"
#include "GCNHazardRecognizer.h"
#include "GCNSubtarget.h"
#include "SIMachineFunctionInfo.h"
#include "Utils/AMDGPUBaseInfo.h"
#include "llvm/ADT/STLExtras.h"
#include "llvm/Analysis/ValueTracking.h"
#include "llvm/CodeGen/GlobalISel/GenericMachineInstrs.h"
#include "llvm/CodeGen/LiveIntervals.h"
#include "llvm/CodeGen/LiveVariables.h"
#include "llvm/CodeGen/MachineCycleAnalysis.h"
#include "llvm/CodeGen/MachineDominators.h"
#include "llvm/CodeGen/MachineFrameInfo.h"
#include "llvm/CodeGen/MachineScheduler.h"
#include "llvm/CodeGen/RegisterScavenging.h"
#include "llvm/CodeGen/ScheduleDAG.h"
#include "llvm/IR/DiagnosticInfo.h"
#include "llvm/IR/IntrinsicsAMDGPU.h"
#include "llvm/MC/MCContext.h"
#include "llvm/Support/CommandLine.h"
#include "llvm/Target/TargetMachine.h"
#include <tuple>

using namespace llvm;

#define DEBUG_TYPE "si-instr-info"

#define GET_INSTRINFO_CTOR_DTOR
#include "AMDGPUGenInstrInfo.inc"

namespace llvm::AMDGPU {
#define GET_D16ImageDimIntrinsics_IMPL
#define GET_ImageDimIntrinsicTable_IMPL
#define GET_RsrcIntrinsics_IMPL
#include "AMDGPUGenSearchableTables.inc"
} // namespace llvm::AMDGPU

// Must be at least 4 to be able to branch over minimum unconditional branch
// code. This is only for making it possible to write reasonably small tests for
// long branches.
static cl::opt<unsigned>
BranchOffsetBits("amdgpu-s-branch-bits", cl::ReallyHidden, cl::init(16),
                 cl::desc("Restrict range of branch instructions (DEBUG)"));

static cl::opt<bool> Fix16BitCopies(
  "amdgpu-fix-16-bit-physreg-copies",
  cl::desc("Fix copies between 32 and 16 bit registers by extending to 32 bit"),
  cl::init(true),
  cl::ReallyHidden);

SIInstrInfo::SIInstrInfo(const GCNSubtarget &ST)
    : AMDGPUGenInstrInfo(ST, RI, AMDGPU::ADJCALLSTACKUP,
                         AMDGPU::ADJCALLSTACKDOWN),
      RI(ST), ST(ST) {
  SchedModel.init(&ST);
}

//===----------------------------------------------------------------------===//
// TargetInstrInfo callbacks
//===----------------------------------------------------------------------===//

static unsigned getNumOperandsNoGlue(SDNode *Node) {
  unsigned N = Node->getNumOperands();
  while (N && Node->getOperand(N - 1).getValueType() == MVT::Glue)
    --N;
  return N;
}

/// Returns true if both nodes have the same value for the given
///        operand \p Op, or if both nodes do not have this operand.
static bool nodesHaveSameOperandValue(SDNode *N0, SDNode *N1,
                                      AMDGPU::OpName OpName) {
  unsigned Opc0 = N0->getMachineOpcode();
  unsigned Opc1 = N1->getMachineOpcode();

  int Op0Idx = AMDGPU::getNamedOperandIdx(Opc0, OpName);
  int Op1Idx = AMDGPU::getNamedOperandIdx(Opc1, OpName);

  if (Op0Idx == -1 && Op1Idx == -1)
    return true;


  if ((Op0Idx == -1 && Op1Idx != -1) ||
      (Op1Idx == -1 && Op0Idx != -1))
    return false;

  // getNamedOperandIdx returns the index for the MachineInstr's operands,
  // which includes the result as the first operand. We are indexing into the
  // MachineSDNode's operands, so we need to skip the result operand to get
  // the real index.
  --Op0Idx;
  --Op1Idx;

  return N0->getOperand(Op0Idx) == N1->getOperand(Op1Idx);
}

static bool canRemat(const MachineInstr &MI) {

  if (SIInstrInfo::isVOP1(MI) || SIInstrInfo::isVOP2(MI) ||
      SIInstrInfo::isVOP3(MI) || SIInstrInfo::isSDWA(MI) ||
      SIInstrInfo::isSALU(MI))
    return true;

  if (SIInstrInfo::isSMRD(MI)) {
    return !MI.memoperands_empty() &&
           llvm::all_of(MI.memoperands(), [](const MachineMemOperand *MMO) {
             return MMO->isLoad() && MMO->isInvariant();
           });
  }

  return false;
}

// Split relocation flags for 64-bit global-address materialization into a
// common base and the hi/lo relocation variants.
static std::tuple<unsigned, unsigned, unsigned>
splitGlobalAddressRelocFlags(const GCNSubtarget &ST,
                             const MachineOperand &SrcOp) {
  unsigned SrcFlags = SrcOp.getTargetFlags();

  // Infer the relocation type from the existing flags on the global operand.
  // The relocation type should have been determined earlier in the pipeline.
  unsigned LoReloc = SIInstrInfo::MO_ABS32_LO;
  unsigned HiReloc = SIInstrInfo::MO_ABS32_HI;

  if (SrcFlags & SIInstrInfo::MO_REL32) {
    LoReloc = SIInstrInfo::MO_REL32_LO;
    HiReloc = SIInstrInfo::MO_REL32_HI;
  } else if (SrcFlags & SIInstrInfo::MO_GOTPCREL32_LO) {
    LoReloc = SIInstrInfo::MO_GOTPCREL32_LO;
    HiReloc = SIInstrInfo::MO_GOTPCREL32_HI;
  } else if (SrcFlags & SIInstrInfo::MO_GOTPCREL64) {
    // For 64-bit GOT-relative, use the 64-bit relocation.
    LoReloc = SIInstrInfo::MO_GOTPCREL64;
    HiReloc = SIInstrInfo::MO_GOTPCREL64;
  }

  unsigned BaseFlags =
      SrcFlags & ~(SIInstrInfo::MO_ABS32_LO | SIInstrInfo::MO_ABS32_HI |
                   SIInstrInfo::MO_REL32_LO | SIInstrInfo::MO_REL32_HI |
                   SIInstrInfo::MO_GOTPCREL32_LO |
                   SIInstrInfo::MO_GOTPCREL32_HI | SIInstrInfo::MO_GOTPCREL64);

  return std::make_tuple(BaseFlags, LoReloc, HiReloc);
}

bool SIInstrInfo::isReMaterializableImpl(
    const MachineInstr &MI) const {

  if (canRemat(MI)) {
    // Normally VALU use of exec would block the rematerialization, but that
    // is OK in this case to have an implicit exec read as all VALU do.
    // We really want all of the generic logic for this except for this.

    // Another potential implicit use is mode register. The core logic of
    // the RA will not attempt rematerialization if mode is set anywhere
    // in the function, otherwise it is safe since mode is not changed.

    // There is difference to generic method which does not allow
    // rematerialization if there are virtual register uses. We allow this,
    // therefore this method includes SOP instructions as well.
    if (!MI.hasImplicitDef() &&
        MI.getNumImplicitOperands() == MI.getDesc().implicit_uses().size() &&
        !MI.mayRaiseFPException())
      return true;
  }

  return TargetInstrInfo::isReMaterializableImpl(MI);
}

// Returns true if the result of a VALU instruction depends on exec.
bool SIInstrInfo::resultDependsOnExec(const MachineInstr &MI) const {
  assert(isVALU(MI, /*AllowLDSDMA=*/true));

  // If it is convergent it depends on EXEC.
  if (MI.isConvergent())
    return true;

  // If it defines SGPR it depends on EXEC
  const MachineRegisterInfo &MRI = MI.getMF()->getRegInfo();
  for (const MachineOperand &Def : MI.defs()) {
    if (!Def.isReg())
      continue;

    Register Reg = Def.getReg();
    if (Reg && RI.isSGPRReg(MRI, Reg))
      return true;
  }

  return false;
}

bool SIInstrInfo::isIgnorableUse(const MachineOperand &MO) const {
  // Any implicit use of exec by VALU is not a real register read.
  return MO.getReg() == AMDGPU::EXEC && MO.isImplicit() &&
         isVALU(*MO.getParent(), /*AllowLDSDMA=*/true) &&
         !resultDependsOnExec(*MO.getParent());
}

bool SIInstrInfo::isSafeToSink(MachineInstr &MI,
                               MachineBasicBlock *SuccToSinkTo,
                               MachineCycleInfo *CI) const {
  // Allow sinking if MI edits lane mask (divergent i1 in sgpr).
  if (MI.getOpcode() == AMDGPU::SI_IF_BREAK)
    return true;

  MachineRegisterInfo &MRI = MI.getMF()->getRegInfo();
  // Check if sinking of MI would create temporal divergent use.
  for (auto Op : MI.uses()) {
    if (Op.isReg() && Op.getReg().isVirtual() &&
        RI.isSGPRClass(MRI.getRegClass(Op.getReg()))) {
      MachineInstr *SgprDef = MRI.getVRegDef(Op.getReg());

      // SgprDef defined inside cycle
      MachineCycle *FromCycle = CI->getCycle(SgprDef->getParent());
      if (FromCycle == nullptr)
        continue;

      MachineCycle *ToCycle = CI->getCycle(SuccToSinkTo);
      // Check if there is a FromCycle that contains SgprDef's basic block but
      // does not contain SuccToSinkTo and also has divergent exit condition.
      while (FromCycle && !(ToCycle && CI->contains(*FromCycle, *ToCycle))) {
        SmallVector<MachineBasicBlock *, 1> ExitingBlocks;
        CI->getExitingBlocks(*FromCycle, ExitingBlocks);

        // FromCycle has divergent exit condition.
        for (MachineBasicBlock *ExitingBlock : ExitingBlocks) {
          if (hasDivergentBranch(ExitingBlock))
            return false;
        }

        FromCycle = CI->getParentCycle(*FromCycle);
      }
    }
  }

  return true;
}

bool SIInstrInfo::areLoadsFromSameBasePtr(SDNode *Load0, SDNode *Load1,
                                          int64_t &Offset0,
                                          int64_t &Offset1) const {
  if (!Load0->isMachineOpcode() || !Load1->isMachineOpcode())
    return false;

  unsigned Opc0 = Load0->getMachineOpcode();
  unsigned Opc1 = Load1->getMachineOpcode();

  // Make sure both are actually loads.
  if (!get(Opc0).mayLoad() || !get(Opc1).mayLoad())
    return false;

  // A mayLoad instruction without a def is not a load. Likely a prefetch.
  if (!get(Opc0).getNumDefs() || !get(Opc1).getNumDefs())
    return false;

  if (isDS(Opc0) && isDS(Opc1)) {

    // FIXME: Handle this case:
    if (getNumOperandsNoGlue(Load0) != getNumOperandsNoGlue(Load1))
      return false;

    // Check base reg.
    if (Load0->getOperand(0) != Load1->getOperand(0))
      return false;

    // Skip read2 / write2 variants for simplicity.
    // TODO: We should report true if the used offsets are adjacent (excluded
    // st64 versions).
    int Offset0Idx = AMDGPU::getNamedOperandIdx(Opc0, AMDGPU::OpName::offset);
    int Offset1Idx = AMDGPU::getNamedOperandIdx(Opc1, AMDGPU::OpName::offset);
    if (Offset0Idx == -1 || Offset1Idx == -1)
      return false;

    // XXX - be careful of dataless loads
    // getNamedOperandIdx returns the index for MachineInstrs.  Since they
    // include the output in the operand list, but SDNodes don't, we need to
    // subtract the index by one.
    Offset0Idx -= get(Opc0).NumDefs;
    Offset1Idx -= get(Opc1).NumDefs;
    Offset0 = Load0->getConstantOperandVal(Offset0Idx);
    Offset1 = Load1->getConstantOperandVal(Offset1Idx);
    return true;
  }

  if (isSMRD(Opc0) && isSMRD(Opc1)) {
    // Skip time and cache invalidation instructions.
    if (!AMDGPU::hasNamedOperand(Opc0, AMDGPU::OpName::sbase) ||
        !AMDGPU::hasNamedOperand(Opc1, AMDGPU::OpName::sbase))
      return false;

    unsigned NumOps = getNumOperandsNoGlue(Load0);
    if (NumOps != getNumOperandsNoGlue(Load1))
      return false;

    // Check base reg.
    if (Load0->getOperand(0) != Load1->getOperand(0))
      return false;

    // Match register offsets, if both register and immediate offsets present.
    assert(NumOps == 4 || NumOps == 5);
    if (NumOps == 5 && Load0->getOperand(1) != Load1->getOperand(1))
      return false;

    const ConstantSDNode *Load0Offset =
        dyn_cast<ConstantSDNode>(Load0->getOperand(NumOps - 3));
    const ConstantSDNode *Load1Offset =
        dyn_cast<ConstantSDNode>(Load1->getOperand(NumOps - 3));

    if (!Load0Offset || !Load1Offset)
      return false;

    Offset0 = Load0Offset->getZExtValue();
    Offset1 = Load1Offset->getZExtValue();
    return true;
  }

  // MUBUF and MTBUF can access the same addresses.
  if ((isMUBUF(Opc0) || isMTBUF(Opc0)) && (isMUBUF(Opc1) || isMTBUF(Opc1))) {

    // MUBUF and MTBUF have vaddr at different indices.
    if (!nodesHaveSameOperandValue(Load0, Load1, AMDGPU::OpName::soffset) ||
        !nodesHaveSameOperandValue(Load0, Load1, AMDGPU::OpName::vaddr) ||
        !nodesHaveSameOperandValue(Load0, Load1, AMDGPU::OpName::srsrc))
      return false;

    int OffIdx0 = AMDGPU::getNamedOperandIdx(Opc0, AMDGPU::OpName::offset);
    int OffIdx1 = AMDGPU::getNamedOperandIdx(Opc1, AMDGPU::OpName::offset);

    if (OffIdx0 == -1 || OffIdx1 == -1)
      return false;

    // getNamedOperandIdx returns the index for MachineInstrs.  Since they
    // include the output in the operand list, but SDNodes don't, we need to
    // subtract the index by one.
    OffIdx0 -= get(Opc0).NumDefs;
    OffIdx1 -= get(Opc1).NumDefs;

    SDValue Off0 = Load0->getOperand(OffIdx0);
    SDValue Off1 = Load1->getOperand(OffIdx1);

    // The offset might be a FrameIndexSDNode.
    if (!isa<ConstantSDNode>(Off0) || !isa<ConstantSDNode>(Off1))
      return false;

    Offset0 = Off0->getAsZExtVal();
    Offset1 = Off1->getAsZExtVal();
    return true;
  }

  return false;
}

static bool isStride64(unsigned Opc) {
  switch (Opc) {
  case AMDGPU::DS_READ2ST64_B32:
  case AMDGPU::DS_READ2ST64_B64:
  case AMDGPU::DS_WRITE2ST64_B32:
  case AMDGPU::DS_WRITE2ST64_B64:
    return true;
  default:
    return false;
  }
}

bool SIInstrInfo::getMemOperandsWithOffsetWidth(
    const MachineInstr &LdSt, SmallVectorImpl<const MachineOperand *> &BaseOps,
    int64_t &Offset, bool &OffsetIsScalable, LocationSize &Width,
    const TargetRegisterInfo *TRI) const {
  if (!LdSt.mayLoadOrStore())
    return false;

  unsigned Opc = LdSt.getOpcode();
  OffsetIsScalable = false;
  const MachineOperand *BaseOp, *OffsetOp;
  int DataOpIdx;

  if (isDS(LdSt)) {
    BaseOp = getNamedOperand(LdSt, AMDGPU::OpName::addr);
    OffsetOp = getNamedOperand(LdSt, AMDGPU::OpName::offset);
    if (OffsetOp) {
      // Normal, single offset LDS instruction.
      if (!BaseOp) {
        // DS_CONSUME/DS_APPEND use M0 for the base address.
        // TODO: find the implicit use operand for M0 and use that as BaseOp?
        return false;
      }
      BaseOps.push_back(BaseOp);
      Offset = OffsetOp->getImm();
      // Get appropriate operand, and compute width accordingly.
      DataOpIdx = AMDGPU::getNamedOperandIdx(Opc, AMDGPU::OpName::vdst);
      if (DataOpIdx == -1)
        DataOpIdx = AMDGPU::getNamedOperandIdx(Opc, AMDGPU::OpName::data0);
      if (Opc == AMDGPU::DS_ATOMIC_ASYNC_BARRIER_ARRIVE_B64)
        Width = LocationSize::precise(64);
      else
        Width = LocationSize::precise(getOpSize(LdSt, DataOpIdx));
    } else {
      // The 2 offset instructions use offset0 and offset1 instead. We can treat
      // these as a load with a single offset if the 2 offsets are consecutive.
      // We will use this for some partially aligned loads.
      const MachineOperand *Offset0Op =
          getNamedOperand(LdSt, AMDGPU::OpName::offset0);
      const MachineOperand *Offset1Op =
          getNamedOperand(LdSt, AMDGPU::OpName::offset1);

      unsigned Offset0 = Offset0Op->getImm() & 0xff;
      unsigned Offset1 = Offset1Op->getImm() & 0xff;
      if (Offset0 + 1 != Offset1)
        return false;

      // Each of these offsets is in element sized units, so we need to convert
      // to bytes of the individual reads.

      unsigned EltSize;
      if (LdSt.mayLoad())
        EltSize = TRI->getRegSizeInBits(*getOpRegClass(LdSt, 0)) / 16;
      else {
        assert(LdSt.mayStore());
        int Data0Idx = AMDGPU::getNamedOperandIdx(Opc, AMDGPU::OpName::data0);
        EltSize = TRI->getRegSizeInBits(*getOpRegClass(LdSt, Data0Idx)) / 8;
      }

      if (isStride64(Opc))
        EltSize *= 64;

      BaseOps.push_back(BaseOp);
      Offset = EltSize * Offset0;
      // Get appropriate operand(s), and compute width accordingly.
      DataOpIdx = AMDGPU::getNamedOperandIdx(Opc, AMDGPU::OpName::vdst);
      if (DataOpIdx == -1) {
        DataOpIdx = AMDGPU::getNamedOperandIdx(Opc, AMDGPU::OpName::data0);
        Width = LocationSize::precise(getOpSize(LdSt, DataOpIdx));
        DataOpIdx = AMDGPU::getNamedOperandIdx(Opc, AMDGPU::OpName::data1);
        Width = LocationSize::precise(
            Width.getValue() + TypeSize::getFixed(getOpSize(LdSt, DataOpIdx)));
      } else {
        Width = LocationSize::precise(getOpSize(LdSt, DataOpIdx));
      }
    }
    return true;
  }

  if (isMUBUF(LdSt) || isMTBUF(LdSt)) {
    const MachineOperand *RSrc = getNamedOperand(LdSt, AMDGPU::OpName::srsrc);
    if (!RSrc) // e.g. BUFFER_WBINVL1_VOL
      return false;
    BaseOps.push_back(RSrc);
    BaseOp = getNamedOperand(LdSt, AMDGPU::OpName::vaddr);
    if (BaseOp && !BaseOp->isFI())
      BaseOps.push_back(BaseOp);
    const MachineOperand *OffsetImm =
        getNamedOperand(LdSt, AMDGPU::OpName::offset);
    Offset = OffsetImm->getImm();
    const MachineOperand *SOffset =
        getNamedOperand(LdSt, AMDGPU::OpName::soffset);
    if (SOffset) {
      if (SOffset->isReg())
        BaseOps.push_back(SOffset);
      else
        Offset += SOffset->getImm();
    }
    // Get appropriate operand, and compute width accordingly.
    DataOpIdx = AMDGPU::getNamedOperandIdx(Opc, AMDGPU::OpName::vdst);
    if (DataOpIdx == -1)
      DataOpIdx = AMDGPU::getNamedOperandIdx(Opc, AMDGPU::OpName::vdata);
    if (DataOpIdx == -1) // LDS DMA
      return false;
    Width = LocationSize::precise(getOpSize(LdSt, DataOpIdx));
    return true;
  }

  if (isImage(LdSt)) {
    auto RsrcOpName =
        isMIMG(LdSt) ? AMDGPU::OpName::srsrc : AMDGPU::OpName::rsrc;
    int SRsrcIdx = AMDGPU::getNamedOperandIdx(Opc, RsrcOpName);
    BaseOps.push_back(&LdSt.getOperand(SRsrcIdx));
    int VAddr0Idx = AMDGPU::getNamedOperandIdx(Opc, AMDGPU::OpName::vaddr0);
    if (VAddr0Idx >= 0) {
      // GFX10 possible NSA encoding.
      for (int I = VAddr0Idx; I < SRsrcIdx; ++I)
        BaseOps.push_back(&LdSt.getOperand(I));
    } else {
      BaseOps.push_back(getNamedOperand(LdSt, AMDGPU::OpName::vaddr));
    }
    Offset = 0;
    // Get appropriate operand, and compute width accordingly.
    DataOpIdx = AMDGPU::getNamedOperandIdx(Opc, AMDGPU::OpName::vdata);
    if (DataOpIdx == -1)
      return false; // no return sampler
    Width = LocationSize::precise(getOpSize(LdSt, DataOpIdx));
    return true;
  }

  if (isSMRD(LdSt)) {
    BaseOp = getNamedOperand(LdSt, AMDGPU::OpName::sbase);
    if (!BaseOp) // e.g. S_MEMTIME
      return false;
    BaseOps.push_back(BaseOp);
    OffsetOp = getNamedOperand(LdSt, AMDGPU::OpName::offset);
    Offset = OffsetOp ? OffsetOp->getImm() : 0;
    // Get appropriate operand, and compute width accordingly.
    DataOpIdx = AMDGPU::getNamedOperandIdx(Opc, AMDGPU::OpName::sdst);
    if (DataOpIdx == -1)
      return false;
    Width = LocationSize::precise(getOpSize(LdSt, DataOpIdx));
    return true;
  }

  if (isFLAT(LdSt)) {
    // Instructions have either vaddr or saddr or both or none.
    BaseOp = getNamedOperand(LdSt, AMDGPU::OpName::vaddr);
    if (BaseOp)
      BaseOps.push_back(BaseOp);
    BaseOp = getNamedOperand(LdSt, AMDGPU::OpName::saddr);
    if (BaseOp)
      BaseOps.push_back(BaseOp);
    Offset = getNamedOperand(LdSt, AMDGPU::OpName::offset)->getImm();
    // Get appropriate operand, and compute width accordingly.
    DataOpIdx = AMDGPU::getNamedOperandIdx(Opc, AMDGPU::OpName::vdst);
    if (DataOpIdx == -1)
      DataOpIdx = AMDGPU::getNamedOperandIdx(Opc, AMDGPU::OpName::vdata);
    if (DataOpIdx == -1) // LDS DMA
      return false;
    Width = LocationSize::precise(getOpSize(LdSt, DataOpIdx));
    return true;
  }

  return false;
}

static bool memOpsHaveSameBasePtr(const MachineInstr &MI1,
                                  ArrayRef<const MachineOperand *> BaseOps1,
                                  const MachineInstr &MI2,
                                  ArrayRef<const MachineOperand *> BaseOps2) {
  // Only examine the first "base" operand of each instruction, on the
  // assumption that it represents the real base address of the memory access.
  // Other operands are typically offsets or indices from this base address.
  if (BaseOps1.front()->isIdenticalTo(*BaseOps2.front()))
    return true;

  if (!MI1.hasOneMemOperand() || !MI2.hasOneMemOperand())
    return false;

  auto *MO1 = *MI1.memoperands_begin();
  auto *MO2 = *MI2.memoperands_begin();
  if (MO1->getAddrSpace() != MO2->getAddrSpace())
    return false;

  const auto *Base1 = MO1->getValue();
  const auto *Base2 = MO2->getValue();
  if (!Base1 || !Base2)
    return false;
  Base1 = getUnderlyingObject(Base1);
  Base2 = getUnderlyingObject(Base2);

  if (isa<UndefValue>(Base1) || isa<UndefValue>(Base2))
    return false;

  return Base1 == Base2;
}

bool SIInstrInfo::shouldClusterMemOps(ArrayRef<const MachineOperand *> BaseOps1,
                                      int64_t Offset1, bool OffsetIsScalable1,
                                      ArrayRef<const MachineOperand *> BaseOps2,
                                      int64_t Offset2, bool OffsetIsScalable2,
                                      unsigned ClusterSize,
                                      unsigned NumBytes) const {
  // If the mem ops (to be clustered) do not have the same base ptr, then they
  // should not be clustered
  unsigned MaxMemoryClusterDWords = DefaultMemoryClusterDWordsLimit;
  if (!BaseOps1.empty() && !BaseOps2.empty()) {
    const MachineInstr &FirstLdSt = *BaseOps1.front()->getParent();
    const MachineInstr &SecondLdSt = *BaseOps2.front()->getParent();
    if (!memOpsHaveSameBasePtr(FirstLdSt, BaseOps1, SecondLdSt, BaseOps2))
      return false;

    const SIMachineFunctionInfo *MFI =
        FirstLdSt.getMF()->getInfo<SIMachineFunctionInfo>();
    MaxMemoryClusterDWords = MFI->getMaxMemoryClusterDWords();
  } else if (!BaseOps1.empty() || !BaseOps2.empty()) {
    // If only one base op is empty, they do not have the same base ptr
    return false;
  }

  // In order to avoid register pressure, on an average, the number of DWORDS
  // loaded together by all clustered mem ops should not exceed
  // MaxMemoryClusterDWords. This is an empirical value based on certain
  // observations and performance related experiments.
  // The good thing about this heuristic is - it avoids clustering of too many
  // sub-word loads, and also avoids clustering of wide loads. Below is the
  // brief summary of how the heuristic behaves for various `LoadSize` when
  // MaxMemoryClusterDWords is 8.
  //
  // (1) 1 <= LoadSize <= 4: cluster at max 8 mem ops
  // (2) 5 <= LoadSize <= 8: cluster at max 4 mem ops
  // (3) 9 <= LoadSize <= 12: cluster at max 2 mem ops
  // (4) 13 <= LoadSize <= 16: cluster at max 2 mem ops
  // (5) LoadSize >= 17: do not cluster
  const unsigned LoadSize = NumBytes / ClusterSize;
  const unsigned NumDWords = ((LoadSize + 3) / 4) * ClusterSize;
  return NumDWords <= MaxMemoryClusterDWords;
}

// FIXME: This behaves strangely. If, for example, you have 32 load + stores,
// the first 16 loads will be interleaved with the stores, and the next 16 will
// be clustered as expected. It should really split into 2 16 store batches.
//
// Loads are clustered until this returns false, rather than trying to schedule
// groups of stores. This also means we have to deal with saying different
// address space loads should be clustered, and ones which might cause bank
// conflicts.
//
// This might be deprecated so it might not be worth that much effort to fix.
bool SIInstrInfo::shouldScheduleLoadsNear(SDNode *Load0, SDNode *Load1,
                                          int64_t Offset0, int64_t Offset1,
                                          unsigned NumLoads) const {
  assert(Offset1 > Offset0 &&
         "Second offset should be larger than first offset!");
  // If we have less than 16 loads in a row, and the offsets are within 64
  // bytes, then schedule together.

  // A cacheline is 64 bytes (for global memory).
  return (NumLoads <= 16 && (Offset1 - Offset0) < 64);
}

static void reportIllegalCopy(const SIInstrInfo *TII, MachineBasicBlock &MBB,
                              MachineBasicBlock::iterator MI,
                              const DebugLoc &DL, MCRegister DestReg,
                              MCRegister SrcReg, bool KillSrc,
                              const char *Msg = "illegal VGPR to SGPR copy") {
  MachineFunction *MF = MBB.getParent();

  LLVMContext &C = MF->getFunction().getContext();
  C.diagnose(DiagnosticInfoUnsupported(MF->getFunction(), Msg, DL, DS_Error));

  BuildMI(MBB, MI, DL, TII->get(AMDGPU::SI_ILLEGAL_COPY), DestReg)
      .addReg(SrcReg, getKillRegState(KillSrc));
}

/// Handle copying from SGPR to AGPR, or from AGPR to AGPR on GFX908. It is not
/// possible to have a direct copy in these cases on GFX908, so an intermediate
/// VGPR copy is required.
static void indirectCopyToAGPR(const SIInstrInfo &TII, MachineBasicBlock &MBB,
                               MachineBasicBlock::iterator MI,
                               const DebugLoc &DL, MCRegister DestReg,
                               MCRegister SrcReg, bool KillSrc,
                               RegScavenger &RS, bool RegsOverlap,
                               Register ImpUseSuperReg = Register()) {
  assert((TII.getSubtarget().hasMAIInsts() &&
          !TII.getSubtarget().hasGFX90AInsts()) &&
         "Expected GFX908 subtarget.");

  assert((AMDGPU::SReg_32RegClass.contains(SrcReg) ||
          AMDGPU::AGPR_32RegClass.contains(SrcReg)) &&
         "Source register of the copy should be either an SGPR or an AGPR.");

  assert(AMDGPU::AGPR_32RegClass.contains(DestReg) &&
         "Destination register of the copy should be an AGPR.");

  const SIRegisterInfo &RI = TII.getRegisterInfo();

  // First try to find defining accvgpr_write to avoid temporary registers.
  // In the case of copies of overlapping AGPRs, we conservatively do not
  // reuse previous accvgpr_writes. Otherwise, we may incorrectly pick up
  // an accvgpr_write used for this same copy due to implicit-defs
  if (!RegsOverlap) {
    for (auto Def = MI, E = MBB.begin(); Def != E; ) {
      --Def;

      if (!Def->modifiesRegister(SrcReg, &RI))
        continue;

      if (Def->getOpcode() != AMDGPU::V_ACCVGPR_WRITE_B32_e64 ||
          Def->getOperand(0).getReg() != SrcReg)
        break;

      MachineOperand &DefOp = Def->getOperand(1);
      assert(DefOp.isReg() || DefOp.isImm());

      if (DefOp.isReg()) {
        bool SafeToPropagate = true;
        // Check that register source operand is not clobbered before MI.
        // Immediate operands are always safe to propagate.
        for (auto I = Def; I != MI && SafeToPropagate; ++I)
          if (I->modifiesRegister(DefOp.getReg(), &RI))
            SafeToPropagate = false;

        if (!SafeToPropagate)
          break;

        for (auto I = Def; I != MI; ++I)
          I->clearRegisterKills(DefOp.getReg(), &RI);
      }

      MachineInstrBuilder Builder =
          BuildMI(MBB, MI, DL, TII.get(AMDGPU::V_ACCVGPR_WRITE_B32_e64),
                  DestReg)
              .add(DefOp);

      if (ImpUseSuperReg) {
        Builder.addReg(ImpUseSuperReg,
                      getKillRegState(KillSrc) | RegState::Implicit);
      }

      return;
    }
  }

  RS.enterBasicBlockEnd(MBB);
  RS.backward(std::next(MI));

  // Ideally we want to have three registers for a long reg_sequence copy
  // to hide 2 waitstates between v_mov_b32 and accvgpr_write.
  unsigned MaxVGPRs = RI.getRegPressureLimit(&AMDGPU::VGPR_32RegClass,
                                             *MBB.getParent());

  // Registers in the sequence are allocated contiguously so we can just
  // use register number to pick one of three round-robin temps.
  unsigned RegNo = (DestReg - AMDGPU::AGPR0) % 3;
  Register Tmp =
      MBB.getParent()->getInfo<SIMachineFunctionInfo>()->getVGPRForAGPRCopy();
  assert(MBB.getParent()->getRegInfo().isReserved(Tmp) &&
         "VGPR used for an intermediate copy should have been reserved.");

  // Only loop through if there are any free registers left. We don't want to
  // spill.
  while (RegNo--) {
    Register Tmp2 = RS.scavengeRegisterBackwards(AMDGPU::VGPR_32RegClass, MI,
                                                 /* RestoreAfter */ false, 0,
                                                 /* AllowSpill */ false);
    if (!Tmp2 || RI.getHWRegIndex(Tmp2) >= MaxVGPRs)
      break;
    Tmp = Tmp2;
    RS.setRegUsed(Tmp);
  }

  // Insert copy to temporary VGPR.
  unsigned TmpCopyOp = AMDGPU::V_MOV_B32_e32;
  if (AMDGPU::AGPR_32RegClass.contains(SrcReg)) {
    TmpCopyOp = AMDGPU::V_ACCVGPR_READ_B32_e64;
  } else {
    assert(AMDGPU::SReg_32RegClass.contains(SrcReg));
  }

  MachineInstrBuilder UseBuilder = BuildMI(MBB, MI, DL, TII.get(TmpCopyOp), Tmp)
    .addReg(SrcReg, getKillRegState(KillSrc));
  if (ImpUseSuperReg) {
    UseBuilder.addReg(ImpUseSuperReg,
                      getKillRegState(KillSrc) | RegState::Implicit);
  }

  BuildMI(MBB, MI, DL, TII.get(AMDGPU::V_ACCVGPR_WRITE_B32_e64), DestReg)
      .addReg(Tmp, RegState::Kill);
}

static void expandSGPRCopy(const SIInstrInfo &TII, MachineBasicBlock &MBB,
                           MachineBasicBlock::iterator MI, const DebugLoc &DL,
                           MCRegister DestReg, MCRegister SrcReg, bool KillSrc,
                           const TargetRegisterClass *RC, bool Forward) {
  const SIRegisterInfo &RI = TII.getRegisterInfo();
  ArrayRef<int16_t> BaseIndices = RI.getRegSplitParts(RC, 4);
  MachineBasicBlock::iterator I = MI;
  MachineInstr *FirstMI = nullptr, *LastMI = nullptr;

  for (unsigned Idx = 0; Idx < BaseIndices.size(); ++Idx) {
    int16_t SubIdx = BaseIndices[Idx];
    Register DestSubReg = RI.getSubReg(DestReg, SubIdx);
    Register SrcSubReg = RI.getSubReg(SrcReg, SubIdx);
    assert(DestSubReg && SrcSubReg && "Failed to find subregs!");
    unsigned Opcode = AMDGPU::S_MOV_B32;

    // Is SGPR aligned? If so try to combine with next.
    bool AlignedDest = ((DestSubReg - AMDGPU::SGPR0) % 2) == 0;
    bool AlignedSrc = ((SrcSubReg - AMDGPU::SGPR0) % 2) == 0;
    if (AlignedDest && AlignedSrc && (Idx + 1 < BaseIndices.size())) {
      // Can use SGPR64 copy
      unsigned Channel = RI.getChannelFromSubReg(SubIdx);
      SubIdx = RI.getSubRegFromChannel(Channel, 2);
      DestSubReg = RI.getSubReg(DestReg, SubIdx);
      SrcSubReg = RI.getSubReg(SrcReg, SubIdx);
      assert(DestSubReg && SrcSubReg && "Failed to find subregs!");
      Opcode = AMDGPU::S_MOV_B64;
      Idx++;
    }

    LastMI = BuildMI(MBB, I, DL, TII.get(Opcode), DestSubReg)
                 .addReg(SrcSubReg)
                 .addReg(SrcReg, RegState::Implicit);

    if (!FirstMI)
      FirstMI = LastMI;

    if (!Forward)
      I--;
  }

  assert(FirstMI && LastMI);
  if (!Forward)
    std::swap(FirstMI, LastMI);

  if (KillSrc)
    LastMI->addRegisterKilled(SrcReg, &RI);
}

void SIInstrInfo::copyPhysReg(MachineBasicBlock &MBB,
                              MachineBasicBlock::iterator MI,
                              const DebugLoc &DL, Register DestReg,
                              Register SrcReg, bool KillSrc, bool RenamableDest,
                              bool RenamableSrc) const {
  const TargetRegisterClass *RC = RI.getPhysRegBaseClass(DestReg);
  unsigned Size = RI.getRegSizeInBits(*RC);
  const TargetRegisterClass *SrcRC = RI.getPhysRegBaseClass(SrcReg);
  unsigned SrcSize = RI.getRegSizeInBits(*SrcRC);

  // The rest of copyPhysReg assumes Src and Dst size are the same size.
  // TODO-GFX11_16BIT If all true 16 bit instruction patterns are completed can
  // we remove Fix16BitCopies and this code block?
  if (Fix16BitCopies) {
    if (((Size == 16) != (SrcSize == 16))) {
      // Non-VGPR Src and Dst will later be expanded back to 32 bits.
      assert(ST.useRealTrue16Insts());
      Register &RegToFix = (Size == 32) ? DestReg : SrcReg;
      MCRegister SubReg = RI.getSubReg(RegToFix, AMDGPU::lo16);
      RegToFix = SubReg;

      if (DestReg == SrcReg) {
        // Identity copy. Insert empty bundle since ExpandPostRA expects an
        // instruction here.
        BuildMI(MBB, MI, DL, get(AMDGPU::BUNDLE));
        return;
      }
      RC = RI.getPhysRegBaseClass(DestReg);
      Size = RI.getRegSizeInBits(*RC);
      SrcRC = RI.getPhysRegBaseClass(SrcReg);
      SrcSize = RI.getRegSizeInBits(*SrcRC);
    }
  }

  if (RC == &AMDGPU::VGPR_32RegClass) {
    assert(AMDGPU::VGPR_32RegClass.contains(SrcReg) ||
           AMDGPU::SReg_32RegClass.contains(SrcReg) ||
           AMDGPU::AGPR_32RegClass.contains(SrcReg));
    unsigned Opc = AMDGPU::AGPR_32RegClass.contains(SrcReg) ?
                     AMDGPU::V_ACCVGPR_READ_B32_e64 : AMDGPU::V_MOV_B32_e32;
    BuildMI(MBB, MI, DL, get(Opc), DestReg)
      .addReg(SrcReg, getKillRegState(KillSrc));
    return;
  }

  if (RC == &AMDGPU::SReg_32_XM0RegClass ||
      RC == &AMDGPU::SReg_32RegClass) {
    if (SrcReg == AMDGPU::SCC) {
      BuildMI(MBB, MI, DL, get(AMDGPU::S_CSELECT_B32), DestReg)
          .addImm(1)
          .addImm(0);
      return;
    }

    if (!AMDGPU::SReg_32RegClass.contains(SrcReg)) {
      if (DestReg == AMDGPU::VCC_LO) {
        // FIXME: Hack until VReg_1 removed.
        assert(AMDGPU::VGPR_32RegClass.contains(SrcReg));
        BuildMI(MBB, MI, DL, get(AMDGPU::V_CMP_NE_U32_e32))
            .addImm(0)
            .addReg(SrcReg, getKillRegState(KillSrc));
        return;
      }

      reportIllegalCopy(this, MBB, MI, DL, DestReg, SrcReg, KillSrc);
      return;
    }

    BuildMI(MBB, MI, DL, get(AMDGPU::S_MOV_B32), DestReg)
            .addReg(SrcReg, getKillRegState(KillSrc));
    return;
  }

  if (RC == &AMDGPU::SReg_64RegClass) {
    if (SrcReg == AMDGPU::SCC) {
      BuildMI(MBB, MI, DL, get(AMDGPU::S_CSELECT_B64), DestReg)
          .addImm(1)
          .addImm(0);
      return;
    }

    if (!AMDGPU::SReg_64_EncodableRegClass.contains(SrcReg)) {
      if (DestReg == AMDGPU::VCC) {
        // FIXME: Hack until VReg_1 removed.
        assert(AMDGPU::VGPR_32RegClass.contains(SrcReg));
        BuildMI(MBB, MI, DL, get(AMDGPU::V_CMP_NE_U32_e32))
            .addImm(0)
            .addReg(SrcReg, getKillRegState(KillSrc));
        return;
      }

      reportIllegalCopy(this, MBB, MI, DL, DestReg, SrcReg, KillSrc);
      return;
    }

    BuildMI(MBB, MI, DL, get(AMDGPU::S_MOV_B64), DestReg)
            .addReg(SrcReg, getKillRegState(KillSrc));
    return;
  }

  if (DestReg == AMDGPU::SCC) {
    // Copying 64-bit or 32-bit sources to SCC barely makes sense,
    // but SelectionDAG emits such copies for i1 sources.
    if (AMDGPU::SReg_64RegClass.contains(SrcReg)) {
      // This copy can only be produced by patterns
      // with explicit SCC, which are known to be enabled
      // only for subtargets with S_CMP_LG_U64 present.
      assert(ST.hasScalarCompareEq64());
      BuildMI(MBB, MI, DL, get(AMDGPU::S_CMP_LG_U64))
          .addReg(SrcReg, getKillRegState(KillSrc))
          .addImm(0);
    } else {
      assert(AMDGPU::SReg_32RegClass.contains(SrcReg));
      BuildMI(MBB, MI, DL, get(AMDGPU::S_CMP_LG_U32))
          .addReg(SrcReg, getKillRegState(KillSrc))
          .addImm(0);
    }

    return;
  }

  if (RC == &AMDGPU::AGPR_32RegClass) {
    if (AMDGPU::VGPR_32RegClass.contains(SrcReg) ||
        (ST.hasGFX90AInsts() && AMDGPU::SReg_32RegClass.contains(SrcReg))) {
      BuildMI(MBB, MI, DL, get(AMDGPU::V_ACCVGPR_WRITE_B32_e64), DestReg)
        .addReg(SrcReg, getKillRegState(KillSrc));
      return;
    }

    if (AMDGPU::AGPR_32RegClass.contains(SrcReg) && ST.hasGFX90AInsts()) {
      BuildMI(MBB, MI, DL, get(AMDGPU::V_ACCVGPR_MOV_B32), DestReg)
        .addReg(SrcReg, getKillRegState(KillSrc));
      return;
    }

    // FIXME: Pass should maintain scavenger to avoid scan through the block on
    // every AGPR spill.
    RegScavenger RS;
    const bool Overlap = RI.regsOverlap(SrcReg, DestReg);
    indirectCopyToAGPR(*this, MBB, MI, DL, DestReg, SrcReg, KillSrc, RS, Overlap);
    return;
  }

  if (Size == 16) {
    assert(AMDGPU::VGPR_16RegClass.contains(SrcReg) ||
           AMDGPU::SReg_LO16RegClass.contains(SrcReg) ||
           AMDGPU::AGPR_LO16RegClass.contains(SrcReg));

    bool IsSGPRDst = AMDGPU::SReg_LO16RegClass.contains(DestReg);
    bool IsSGPRSrc = AMDGPU::SReg_LO16RegClass.contains(SrcReg);
    bool IsAGPRDst = AMDGPU::AGPR_LO16RegClass.contains(DestReg);
    bool IsAGPRSrc = AMDGPU::AGPR_LO16RegClass.contains(SrcReg);
    bool DstLow = !AMDGPU::isHi16Reg(DestReg, RI);
    bool SrcLow = !AMDGPU::isHi16Reg(SrcReg, RI);
    MCRegister NewDestReg = RI.get32BitRegister(DestReg);
    MCRegister NewSrcReg = RI.get32BitRegister(SrcReg);

    if (IsSGPRDst) {
      if (!IsSGPRSrc) {
        reportIllegalCopy(this, MBB, MI, DL, DestReg, SrcReg, KillSrc);
        return;
      }

      BuildMI(MBB, MI, DL, get(AMDGPU::S_MOV_B32), NewDestReg)
        .addReg(NewSrcReg, getKillRegState(KillSrc));
      return;
    }

    if (IsAGPRDst || IsAGPRSrc) {
      if (!DstLow || !SrcLow) {
        reportIllegalCopy(this, MBB, MI, DL, DestReg, SrcReg, KillSrc,
                          "Cannot use hi16 subreg with an AGPR!");
      }

      copyPhysReg(MBB, MI, DL, NewDestReg, NewSrcReg, KillSrc);
      return;
    }

    if (ST.useRealTrue16Insts()) {
      if (IsSGPRSrc) {
        assert(SrcLow);
        SrcReg = NewSrcReg;
      }
      // Use the smaller instruction encoding if possible.
      if (AMDGPU::VGPR_16_Lo128RegClass.contains(DestReg) &&
          (IsSGPRSrc || AMDGPU::VGPR_16_Lo128RegClass.contains(SrcReg))) {
        BuildMI(MBB, MI, DL, get(AMDGPU::V_MOV_B16_t16_e32), DestReg)
            .addReg(SrcReg);
      } else {
        BuildMI(MBB, MI, DL, get(AMDGPU::V_MOV_B16_t16_e64), DestReg)
            .addImm(0) // src0_modifiers
            .addReg(SrcReg)
            .addImm(0); // op_sel
      }
      return;
    }

    if (IsSGPRSrc && !ST.hasSDWAScalar()) {
      if (!DstLow || !SrcLow) {
        reportIllegalCopy(this, MBB, MI, DL, DestReg, SrcReg, KillSrc,
                          "Cannot use hi16 subreg on VI!");
      }

      BuildMI(MBB, MI, DL, get(AMDGPU::V_MOV_B32_e32), NewDestReg)
        .addReg(NewSrcReg, getKillRegState(KillSrc));
      return;
    }

    auto MIB = BuildMI(MBB, MI, DL, get(AMDGPU::V_MOV_B32_sdwa), NewDestReg)
      .addImm(0) // src0_modifiers
      .addReg(NewSrcReg)
      .addImm(0) // clamp
      .addImm(DstLow ? AMDGPU::SDWA::SdwaSel::WORD_0
                     : AMDGPU::SDWA::SdwaSel::WORD_1)
      .addImm(AMDGPU::SDWA::DstUnused::UNUSED_PRESERVE)
      .addImm(SrcLow ? AMDGPU::SDWA::SdwaSel::WORD_0
                     : AMDGPU::SDWA::SdwaSel::WORD_1)
      .addReg(NewDestReg, RegState::Implicit | RegState::Undef);
    // First implicit operand is $exec.
    MIB->tieOperands(0, MIB->getNumOperands() - 1);
    return;
  }

  if (RC == RI.getVGPR64Class() && (SrcRC == RC || RI.isSGPRClass(SrcRC))) {
    if (ST.hasVMovB64Inst()) {
      BuildMI(MBB, MI, DL, get(AMDGPU::V_MOV_B64_e32), DestReg)
        .addReg(SrcReg, getKillRegState(KillSrc));
      return;
    }
    if (ST.hasPkMovB32()) {
      BuildMI(MBB, MI, DL, get(AMDGPU::V_PK_MOV_B32), DestReg)
        .addImm(SISrcMods::OP_SEL_1)
        .addReg(SrcReg)
        .addImm(SISrcMods::OP_SEL_0 | SISrcMods::OP_SEL_1)
        .addReg(SrcReg)
        .addImm(0) // op_sel_lo
        .addImm(0) // op_sel_hi
        .addImm(0) // neg_lo
        .addImm(0) // neg_hi
        .addImm(0) // clamp
        .addReg(SrcReg, getKillRegState(KillSrc) | RegState::Implicit);
      return;
    }
  }

  const bool Forward = RI.getHWRegIndex(DestReg) <= RI.getHWRegIndex(SrcReg);
  if (RI.isSGPRClass(RC)) {
    if (!RI.isSGPRClass(SrcRC)) {
      reportIllegalCopy(this, MBB, MI, DL, DestReg, SrcReg, KillSrc);
      return;
    }
    const bool CanKillSuperReg = KillSrc && !RI.regsOverlap(SrcReg, DestReg);
    expandSGPRCopy(*this, MBB, MI, DL, DestReg, SrcReg, CanKillSuperReg, RC,
                   Forward);
    return;
  }

  unsigned EltSize = 4;
  unsigned Opcode = AMDGPU::V_MOV_B32_e32;
  if (RI.isAGPRClass(RC)) {
    if (ST.hasGFX90AInsts() && RI.isAGPRClass(SrcRC))
      Opcode = AMDGPU::V_ACCVGPR_MOV_B32;
    else if (RI.hasVGPRs(SrcRC) ||
             (ST.hasGFX90AInsts() && RI.isSGPRClass(SrcRC)))
      Opcode = AMDGPU::V_ACCVGPR_WRITE_B32_e64;
    else
      Opcode = AMDGPU::INSTRUCTION_LIST_END;
  } else if (RI.hasVGPRs(RC) && RI.isAGPRClass(SrcRC)) {
    Opcode = AMDGPU::V_ACCVGPR_READ_B32_e64;
  } else if ((Size % 64 == 0) && RI.hasVGPRs(RC) &&
             (RI.isProperlyAlignedRC(*RC) &&
              (SrcRC == RC || RI.isSGPRClass(SrcRC)))) {
    // TODO: In 96-bit case, could do a 64-bit mov and then a 32-bit mov.
    if (ST.hasVMovB64Inst()) {
      Opcode = AMDGPU::V_MOV_B64_e32;
      EltSize = 8;
    } else if (ST.hasPkMovB32()) {
      Opcode = AMDGPU::V_PK_MOV_B32;
      EltSize = 8;
    }
  }

  // For the cases where we need an intermediate instruction/temporary register
  // (destination is an AGPR), we need a scavenger.
  //
  // FIXME: The pass should maintain this for us so we don't have to re-scan the
  // whole block for every handled copy.
  std::unique_ptr<RegScavenger> RS;
  if (Opcode == AMDGPU::INSTRUCTION_LIST_END)
    RS = std::make_unique<RegScavenger>();

  ArrayRef<int16_t> SubIndices = RI.getRegSplitParts(RC, EltSize);

  // If there is an overlap, we can't kill the super-register on the last
  // instruction, since it will also kill the components made live by this def.
  const bool Overlap = RI.regsOverlap(SrcReg, DestReg);
  const bool CanKillSuperReg = KillSrc && !Overlap;

  for (unsigned Idx = 0; Idx < SubIndices.size(); ++Idx) {
    unsigned SubIdx;
    if (Forward)
      SubIdx = SubIndices[Idx];
    else
      SubIdx = SubIndices[SubIndices.size() - Idx - 1];
    Register DestSubReg = RI.getSubReg(DestReg, SubIdx);
    Register SrcSubReg = RI.getSubReg(SrcReg, SubIdx);
    assert(DestSubReg && SrcSubReg && "Failed to find subregs!");

    bool UseKill = CanKillSuperReg && Idx == SubIndices.size() - 1;

    if (Opcode == AMDGPU::INSTRUCTION_LIST_END) {
      Register ImpUseSuper = SrcReg;
      indirectCopyToAGPR(*this, MBB, MI, DL, DestSubReg, SrcSubReg, UseKill,
                         *RS, Overlap, ImpUseSuper);
    } else if (Opcode == AMDGPU::V_PK_MOV_B32) {
      BuildMI(MBB, MI, DL, get(AMDGPU::V_PK_MOV_B32), DestSubReg)
          .addImm(SISrcMods::OP_SEL_1)
          .addReg(SrcSubReg)
          .addImm(SISrcMods::OP_SEL_0 | SISrcMods::OP_SEL_1)
          .addReg(SrcSubReg)
          .addImm(0) // op_sel_lo
          .addImm(0) // op_sel_hi
          .addImm(0) // neg_lo
          .addImm(0) // neg_hi
          .addImm(0) // clamp
          .addReg(SrcReg, getKillRegState(UseKill) | RegState::Implicit);
    } else {
      MachineInstrBuilder Builder =
          BuildMI(MBB, MI, DL, get(Opcode), DestSubReg).addReg(SrcSubReg);

      Builder.addReg(SrcReg, getKillRegState(UseKill) | RegState::Implicit);
    }
  }
}

int SIInstrInfo::commuteOpcode(unsigned Opcode) const {
  int32_t NewOpc;

  // Try to map original to commuted opcode
  NewOpc = AMDGPU::getCommuteRev(Opcode);
  if (NewOpc != -1)
    // Check if the commuted (REV) opcode exists on the target.
    return pseudoToMCOpcode(NewOpc) != -1 ? NewOpc : -1;

  // Try to map commuted to original opcode
  NewOpc = AMDGPU::getCommuteOrig(Opcode);
  if (NewOpc != -1)
    // Check if the original (non-REV) opcode exists on the target.
    return pseudoToMCOpcode(NewOpc) != -1 ? NewOpc : -1;

  return Opcode;
}

bool SIInstrInfo::getConstValDefinedInReg(const MachineInstr &MI,
                                          const Register Reg,
                                          int64_t &ImmVal) const {
  switch (MI.getOpcode()) {
  case AMDGPU::V_MOV_B32_e32:
  case AMDGPU::S_MOV_B32:
  case AMDGPU::S_MOVK_I32:
  case AMDGPU::S_MOV_B64:
  case AMDGPU::V_MOV_B64_e32:
  case AMDGPU::V_ACCVGPR_WRITE_B32_e64:
  case AMDGPU::AV_MOV_B32_IMM_PSEUDO:
  case AMDGPU::AV_MOV_B64_IMM_PSEUDO:
  case AMDGPU::S_MOV_B64_IMM_PSEUDO:
  case AMDGPU::V_MOV_B64_PSEUDO:
  case AMDGPU::V_MOV_B16_t16_e32: {
    const MachineOperand &Src0 = MI.getOperand(1);
    if (Src0.isImm()) {
      ImmVal = Src0.getImm();
      return MI.getOperand(0).getReg() == Reg;
    }

    return false;
  }
  case AMDGPU::V_MOV_B16_t16_e64: {
    const MachineOperand &Src0 = MI.getOperand(2);
    if (Src0.isImm() && !MI.getOperand(1).getImm()) {
      ImmVal = Src0.getImm();
      return MI.getOperand(0).getReg() == Reg;
    }

    return false;
  }
  case AMDGPU::S_BREV_B32:
  case AMDGPU::V_BFREV_B32_e32:
  case AMDGPU::V_BFREV_B32_e64: {
    const MachineOperand &Src0 = MI.getOperand(1);
    if (Src0.isImm()) {
      ImmVal = static_cast<int64_t>(reverseBits<int32_t>(Src0.getImm()));
      return MI.getOperand(0).getReg() == Reg;
    }

    return false;
  }
  case AMDGPU::S_NOT_B32:
  case AMDGPU::V_NOT_B32_e32:
  case AMDGPU::V_NOT_B32_e64: {
    const MachineOperand &Src0 = MI.getOperand(1);
    if (Src0.isImm()) {
      ImmVal = static_cast<int64_t>(~static_cast<int32_t>(Src0.getImm()));
      return MI.getOperand(0).getReg() == Reg;
    }

    return false;
  }
  default:
    return false;
  }
}

std::optional<int64_t>
SIInstrInfo::getImmOrMaterializedImm(MachineOperand &Op) const {
  if (Op.isImm())
    return Op.getImm();

  if (!Op.isReg() || !Op.getReg().isVirtual())
    return std::nullopt;
  MachineRegisterInfo &MRI = Op.getParent()->getMF()->getRegInfo();
  const MachineInstr *Def = MRI.getVRegDef(Op.getReg());
  if (Def && Def->isMoveImmediate()) {
    const MachineOperand &ImmSrc = Def->getOperand(1);
    if (ImmSrc.isImm())
      return extractSubregFromImm(ImmSrc.getImm(), Op.getSubReg());
  }

  return std::nullopt;
}

unsigned SIInstrInfo::getMovOpcode(const TargetRegisterClass *DstRC) const {

  if (RI.isAGPRClass(DstRC))
    return AMDGPU::COPY;
  if (RI.getRegSizeInBits(*DstRC) == 16) {
    // Assume hi bits are unneeded. Only _e64 true16 instructions are legal
    // before RA.
    return RI.isSGPRClass(DstRC) ? AMDGPU::COPY : AMDGPU::V_MOV_B16_t16_e64;
  }
  if (RI.getRegSizeInBits(*DstRC) == 32)
    return RI.isSGPRClass(DstRC) ? AMDGPU::S_MOV_B32 : AMDGPU::V_MOV_B32_e32;
  if (RI.getRegSizeInBits(*DstRC) == 64 && RI.isSGPRClass(DstRC))
    return AMDGPU::S_MOV_B64;
  if (RI.getRegSizeInBits(*DstRC) == 64 && !RI.isSGPRClass(DstRC))
    return AMDGPU::V_MOV_B64_PSEUDO;
  return AMDGPU::COPY;
}

const MCInstrDesc &
SIInstrInfo::getIndirectGPRIDXPseudo(unsigned VecSize,
                                     bool IsIndirectSrc) const {
  if (IsIndirectSrc) {
    if (VecSize <= 32) // 4 bytes
      return get(AMDGPU::V_INDIRECT_REG_READ_GPR_IDX_B32_V1);
    if (VecSize <= 64) // 8 bytes
      return get(AMDGPU::V_INDIRECT_REG_READ_GPR_IDX_B32_V2);
    if (VecSize <= 96) // 12 bytes
      return get(AMDGPU::V_INDIRECT_REG_READ_GPR_IDX_B32_V3);
    if (VecSize <= 128) // 16 bytes
      return get(AMDGPU::V_INDIRECT_REG_READ_GPR_IDX_B32_V4);
    if (VecSize <= 160) // 20 bytes
      return get(AMDGPU::V_INDIRECT_REG_READ_GPR_IDX_B32_V5);
    if (VecSize <= 192) // 24 bytes
      return get(AMDGPU::V_INDIRECT_REG_READ_GPR_IDX_B32_V6);
    if (VecSize <= 224) // 28 bytes
      return get(AMDGPU::V_INDIRECT_REG_READ_GPR_IDX_B32_V7);
    if (VecSize <= 256) // 32 bytes
      return get(AMDGPU::V_INDIRECT_REG_READ_GPR_IDX_B32_V8);
    if (VecSize <= 288) // 36 bytes
      return get(AMDGPU::V_INDIRECT_REG_READ_GPR_IDX_B32_V9);
    if (VecSize <= 320) // 40 bytes
      return get(AMDGPU::V_INDIRECT_REG_READ_GPR_IDX_B32_V10);
    if (VecSize <= 352) // 44 bytes
      return get(AMDGPU::V_INDIRECT_REG_READ_GPR_IDX_B32_V11);
    if (VecSize <= 384) // 48 bytes
      return get(AMDGPU::V_INDIRECT_REG_READ_GPR_IDX_B32_V12);
    if (VecSize <= 512) // 64 bytes
      return get(AMDGPU::V_INDIRECT_REG_READ_GPR_IDX_B32_V16);
    if (VecSize <= 1024) // 128 bytes
      return get(AMDGPU::V_INDIRECT_REG_READ_GPR_IDX_B32_V32);

    llvm_unreachable("unsupported size for IndirectRegReadGPRIDX pseudos");
  }

  if (VecSize <= 32) // 4 bytes
    return get(AMDGPU::V_INDIRECT_REG_WRITE_GPR_IDX_B32_V1);
  if (VecSize <= 64) // 8 bytes
    return get(AMDGPU::V_INDIRECT_REG_WRITE_GPR_IDX_B32_V2);
  if (VecSize <= 96) // 12 bytes
    return get(AMDGPU::V_INDIRECT_REG_WRITE_GPR_IDX_B32_V3);
  if (VecSize <= 128) // 16 bytes
    return get(AMDGPU::V_INDIRECT_REG_WRITE_GPR_IDX_B32_V4);
  if (VecSize <= 160) // 20 bytes
    return get(AMDGPU::V_INDIRECT_REG_WRITE_GPR_IDX_B32_V5);
  if (VecSize <= 192) // 24 bytes
    return get(AMDGPU::V_INDIRECT_REG_WRITE_GPR_IDX_B32_V6);
  if (VecSize <= 224) // 28 bytes
    return get(AMDGPU::V_INDIRECT_REG_WRITE_GPR_IDX_B32_V7);
  if (VecSize <= 256) // 32 bytes
    return get(AMDGPU::V_INDIRECT_REG_WRITE_GPR_IDX_B32_V8);
  if (VecSize <= 288) // 36 bytes
    return get(AMDGPU::V_INDIRECT_REG_WRITE_GPR_IDX_B32_V9);
  if (VecSize <= 320) // 40 bytes
    return get(AMDGPU::V_INDIRECT_REG_WRITE_GPR_IDX_B32_V10);
  if (VecSize <= 352) // 44 bytes
    return get(AMDGPU::V_INDIRECT_REG_WRITE_GPR_IDX_B32_V11);
  if (VecSize <= 384) // 48 bytes
    return get(AMDGPU::V_INDIRECT_REG_WRITE_GPR_IDX_B32_V12);
  if (VecSize <= 512) // 64 bytes
    return get(AMDGPU::V_INDIRECT_REG_WRITE_GPR_IDX_B32_V16);
  if (VecSize <= 1024) // 128 bytes
    return get(AMDGPU::V_INDIRECT_REG_WRITE_GPR_IDX_B32_V32);

  llvm_unreachable("unsupported size for IndirectRegWriteGPRIDX pseudos");
}

static unsigned getIndirectVGPRWriteMovRelPseudoOpc(unsigned VecSize) {
  if (VecSize <= 32) // 4 bytes
    return AMDGPU::V_INDIRECT_REG_WRITE_MOVREL_B32_V1;
  if (VecSize <= 64) // 8 bytes
    return AMDGPU::V_INDIRECT_REG_WRITE_MOVREL_B32_V2;
  if (VecSize <= 96) // 12 bytes
    return AMDGPU::V_INDIRECT_REG_WRITE_MOVREL_B32_V3;
  if (VecSize <= 128) // 16 bytes
    return AMDGPU::V_INDIRECT_REG_WRITE_MOVREL_B32_V4;
  if (VecSize <= 160) // 20 bytes
    return AMDGPU::V_INDIRECT_REG_WRITE_MOVREL_B32_V5;
  if (VecSize <= 192) // 24 bytes
    return AMDGPU::V_INDIRECT_REG_WRITE_MOVREL_B32_V6;
  if (VecSize <= 224) // 28 bytes
    return AMDGPU::V_INDIRECT_REG_WRITE_MOVREL_B32_V7;
  if (VecSize <= 256) // 32 bytes
    return AMDGPU::V_INDIRECT_REG_WRITE_MOVREL_B32_V8;
  if (VecSize <= 288) // 36 bytes
    return AMDGPU::V_INDIRECT_REG_WRITE_MOVREL_B32_V9;
  if (VecSize <= 320) // 40 bytes
    return AMDGPU::V_INDIRECT_REG_WRITE_MOVREL_B32_V10;
  if (VecSize <= 352) // 44 bytes
    return AMDGPU::V_INDIRECT_REG_WRITE_MOVREL_B32_V11;
  if (VecSize <= 384) // 48 bytes
    return AMDGPU::V_INDIRECT_REG_WRITE_MOVREL_B32_V12;
  if (VecSize <= 512) // 64 bytes
    return AMDGPU::V_INDIRECT_REG_WRITE_MOVREL_B32_V16;
  if (VecSize <= 1024) // 128 bytes
    return AMDGPU::V_INDIRECT_REG_WRITE_MOVREL_B32_V32;

  llvm_unreachable("unsupported size for IndirectRegWrite pseudos");
}

static unsigned getIndirectSGPRWriteMovRelPseudo32(unsigned VecSize) {
  if (VecSize <= 32) // 4 bytes
    return AMDGPU::S_INDIRECT_REG_WRITE_MOVREL_B32_V1;
  if (VecSize <= 64) // 8 bytes
    return AMDGPU::S_INDIRECT_REG_WRITE_MOVREL_B32_V2;
  if (VecSize <= 96) // 12 bytes
    return AMDGPU::S_INDIRECT_REG_WRITE_MOVREL_B32_V3;
  if (VecSize <= 128) // 16 bytes
    return AMDGPU::S_INDIRECT_REG_WRITE_MOVREL_B32_V4;
  if (VecSize <= 160) // 20 bytes
    return AMDGPU::S_INDIRECT_REG_WRITE_MOVREL_B32_V5;
  if (VecSize <= 192) // 24 bytes
    return AMDGPU::S_INDIRECT_REG_WRITE_MOVREL_B32_V6;
  if (VecSize <= 224) // 28 bytes
    return AMDGPU::S_INDIRECT_REG_WRITE_MOVREL_B32_V7;
  if (VecSize <= 256) // 32 bytes
    return AMDGPU::S_INDIRECT_REG_WRITE_MOVREL_B32_V8;
  if (VecSize <= 288) // 36 bytes
    return AMDGPU::S_INDIRECT_REG_WRITE_MOVREL_B32_V9;
  if (VecSize <= 320) // 40 bytes
    return AMDGPU::S_INDIRECT_REG_WRITE_MOVREL_B32_V10;
  if (VecSize <= 352) // 44 bytes
    return AMDGPU::S_INDIRECT_REG_WRITE_MOVREL_B32_V11;
  if (VecSize <= 384) // 48 bytes
    return AMDGPU::S_INDIRECT_REG_WRITE_MOVREL_B32_V12;
  if (VecSize <= 512) // 64 bytes
    return AMDGPU::S_INDIRECT_REG_WRITE_MOVREL_B32_V16;
  if (VecSize <= 1024) // 128 bytes
    return AMDGPU::S_INDIRECT_REG_WRITE_MOVREL_B32_V32;

  llvm_unreachable("unsupported size for IndirectRegWrite pseudos");
}

static unsigned getIndirectSGPRWriteMovRelPseudo64(unsigned VecSize) {
  if (VecSize <= 64) // 8 bytes
    return AMDGPU::S_INDIRECT_REG_WRITE_MOVREL_B64_V1;
  if (VecSize <= 128) // 16 bytes
    return AMDGPU::S_INDIRECT_REG_WRITE_MOVREL_B64_V2;
  if (VecSize <= 256) // 32 bytes
    return AMDGPU::S_INDIRECT_REG_WRITE_MOVREL_B64_V4;
  if (VecSize <= 512) // 64 bytes
    return AMDGPU::S_INDIRECT_REG_WRITE_MOVREL_B64_V8;
  if (VecSize <= 1024) // 128 bytes
    return AMDGPU::S_INDIRECT_REG_WRITE_MOVREL_B64_V16;

  llvm_unreachable("unsupported size for IndirectRegWrite pseudos");
}

const MCInstrDesc &
SIInstrInfo::getIndirectRegWriteMovRelPseudo(unsigned VecSize, unsigned EltSize,
                                             bool IsSGPR) const {
  if (IsSGPR) {
    switch (EltSize) {
    case 32:
      return get(getIndirectSGPRWriteMovRelPseudo32(VecSize));
    case 64:
      return get(getIndirectSGPRWriteMovRelPseudo64(VecSize));
    default:
      llvm_unreachable("invalid reg indexing elt size");
    }
  }

  assert(EltSize == 32 && "invalid reg indexing elt size");
  return get(getIndirectVGPRWriteMovRelPseudoOpc(VecSize));
}

static unsigned getSGPRSpillSaveOpcode(unsigned Size, bool NeedsCFI) {
  switch (Size) {
  case 4:
    return NeedsCFI ? AMDGPU::SI_SPILL_S32_CFI_SAVE : AMDGPU::SI_SPILL_S32_SAVE;
  case 8:
    return NeedsCFI ? AMDGPU::SI_SPILL_S64_CFI_SAVE : AMDGPU::SI_SPILL_S64_SAVE;
  case 12:
    return NeedsCFI ? AMDGPU::SI_SPILL_S96_CFI_SAVE : AMDGPU::SI_SPILL_S96_SAVE;
  case 16:
    return NeedsCFI ? AMDGPU::SI_SPILL_S128_CFI_SAVE
                    : AMDGPU::SI_SPILL_S128_SAVE;
  case 20:
    return NeedsCFI ? AMDGPU::SI_SPILL_S160_CFI_SAVE
                    : AMDGPU::SI_SPILL_S160_SAVE;
  case 24:
    return NeedsCFI ? AMDGPU::SI_SPILL_S192_CFI_SAVE
                    : AMDGPU::SI_SPILL_S192_SAVE;
  case 28:
    return NeedsCFI ? AMDGPU::SI_SPILL_S224_CFI_SAVE
                    : AMDGPU::SI_SPILL_S224_SAVE;
  case 32:
    return AMDGPU::SI_SPILL_S256_SAVE;
  case 36:
    return AMDGPU::SI_SPILL_S288_SAVE;
  case 40:
    return AMDGPU::SI_SPILL_S320_SAVE;
  case 44:
    return AMDGPU::SI_SPILL_S352_SAVE;
  case 48:
    return AMDGPU::SI_SPILL_S384_SAVE;
  case 64:
    return NeedsCFI ? AMDGPU::SI_SPILL_S512_CFI_SAVE
                    : AMDGPU::SI_SPILL_S512_SAVE;
  case 128:
    return NeedsCFI ? AMDGPU::SI_SPILL_S1024_CFI_SAVE
                    : AMDGPU::SI_SPILL_S1024_SAVE;
  default:
    llvm_unreachable("unknown register size");
  }
}

static unsigned getVGPRSpillSaveOpcode(unsigned Size, bool NeedsCFI) {
  switch (Size) {
  case 2:
    return AMDGPU::SI_SPILL_V16_SAVE;
  case 4:
    return NeedsCFI ? AMDGPU::SI_SPILL_V32_CFI_SAVE : AMDGPU::SI_SPILL_V32_SAVE;
  case 8:
    return NeedsCFI ? AMDGPU::SI_SPILL_V64_CFI_SAVE : AMDGPU::SI_SPILL_V64_SAVE;
  case 12:
    return NeedsCFI ? AMDGPU::SI_SPILL_V96_CFI_SAVE : AMDGPU::SI_SPILL_V96_SAVE;
  case 16:
    return NeedsCFI ? AMDGPU::SI_SPILL_V128_CFI_SAVE
                    : AMDGPU::SI_SPILL_V128_SAVE;
  case 20:
    return NeedsCFI ? AMDGPU::SI_SPILL_V160_CFI_SAVE
                    : AMDGPU::SI_SPILL_V160_SAVE;
  case 24:
    return NeedsCFI ? AMDGPU::SI_SPILL_V192_CFI_SAVE
                    : AMDGPU::SI_SPILL_V192_SAVE;
  case 28:
    return NeedsCFI ? AMDGPU::SI_SPILL_V224_CFI_SAVE
                    : AMDGPU::SI_SPILL_V224_SAVE;
  case 32:
    return NeedsCFI ? AMDGPU::SI_SPILL_V256_CFI_SAVE
                    : AMDGPU::SI_SPILL_V256_SAVE;
  case 36:
    return NeedsCFI ? AMDGPU::SI_SPILL_V288_CFI_SAVE
                    : AMDGPU::SI_SPILL_V288_SAVE;
  case 40:
    return NeedsCFI ? AMDGPU::SI_SPILL_V320_CFI_SAVE
                    : AMDGPU::SI_SPILL_V320_SAVE;
  case 44:
    return NeedsCFI ? AMDGPU::SI_SPILL_V352_CFI_SAVE
                    : AMDGPU::SI_SPILL_V352_SAVE;
  case 48:
    return NeedsCFI ? AMDGPU::SI_SPILL_V384_CFI_SAVE
                    : AMDGPU::SI_SPILL_V384_SAVE;
  case 64:
    return NeedsCFI ? AMDGPU::SI_SPILL_V512_CFI_SAVE
                    : AMDGPU::SI_SPILL_V512_SAVE;
  case 128:
    return NeedsCFI ? AMDGPU::SI_SPILL_V1024_CFI_SAVE
                    : AMDGPU::SI_SPILL_V1024_SAVE;
  default:
    llvm_unreachable("unknown register size");
  }
}

static unsigned getAVSpillSaveOpcode(unsigned Size, bool NeedsCFI) {
  switch (Size) {
  case 4:
    return NeedsCFI ? AMDGPU::SI_SPILL_AV32_CFI_SAVE
                    : AMDGPU::SI_SPILL_AV32_SAVE;
  case 8:
    return NeedsCFI ? AMDGPU::SI_SPILL_AV64_CFI_SAVE
                    : AMDGPU::SI_SPILL_AV64_SAVE;
  case 12:
    return NeedsCFI ? AMDGPU::SI_SPILL_AV96_CFI_SAVE
                    : AMDGPU::SI_SPILL_AV96_SAVE;
  case 16:
    return NeedsCFI ? AMDGPU::SI_SPILL_AV128_CFI_SAVE
                    : AMDGPU::SI_SPILL_AV128_SAVE;
  case 20:
    return NeedsCFI ? AMDGPU::SI_SPILL_AV160_CFI_SAVE
                    : AMDGPU::SI_SPILL_AV160_SAVE;
  case 24:
    return NeedsCFI ? AMDGPU::SI_SPILL_AV192_CFI_SAVE
                    : AMDGPU::SI_SPILL_AV192_SAVE;
  case 28:
    return NeedsCFI ? AMDGPU::SI_SPILL_AV224_CFI_SAVE
                    : AMDGPU::SI_SPILL_AV224_SAVE;
  case 32:
    return NeedsCFI ? AMDGPU::SI_SPILL_AV256_CFI_SAVE
                    : AMDGPU::SI_SPILL_AV256_SAVE;
  case 36:
    return AMDGPU::SI_SPILL_AV288_SAVE;
  case 40:
    return AMDGPU::SI_SPILL_AV320_SAVE;
  case 44:
    return AMDGPU::SI_SPILL_AV352_SAVE;
  case 48:
    return AMDGPU::SI_SPILL_AV384_SAVE;
  case 64:
    return NeedsCFI ? AMDGPU::SI_SPILL_AV512_CFI_SAVE
                    : AMDGPU::SI_SPILL_AV512_SAVE;
  case 128:
    return NeedsCFI ? AMDGPU::SI_SPILL_AV1024_CFI_SAVE
                    : AMDGPU::SI_SPILL_AV1024_SAVE;
  default:
    llvm_unreachable("unknown register size");
  }
}

static unsigned getWWMRegSpillSaveOpcode(unsigned Size,
                                         bool IsVectorSuperClass) {
  // Currently, there is only 32-bit WWM register spills needed.
  if (Size != 4)
    llvm_unreachable("unknown wwm register spill size");

  if (IsVectorSuperClass)
    return AMDGPU::SI_SPILL_WWM_AV32_SAVE;

  return AMDGPU::SI_SPILL_WWM_V32_SAVE;
}

unsigned SIInstrInfo::getVectorRegSpillSaveOpcode(
    Register Reg, const TargetRegisterClass *RC, unsigned Size,
    const SIMachineFunctionInfo &MFI, bool NeedsCFI) const {
  bool IsVectorSuperClass = RI.isVectorSuperClass(RC);

  // Choose the right opcode if spilling a WWM register.
  if (MFI.checkFlag(Reg, AMDGPU::VirtRegFlag::WWM_REG))
    return getWWMRegSpillSaveOpcode(Size, IsVectorSuperClass);

  // TODO: Check if AGPRs are available
  if (ST.hasMAIInsts())
    return getAVSpillSaveOpcode(Size, NeedsCFI);

  return getVGPRSpillSaveOpcode(Size, NeedsCFI);
}

void SIInstrInfo::storeRegToStackSlotImpl(
    MachineBasicBlock &MBB, MachineBasicBlock::iterator MI, Register SrcReg,
    bool isKill, int FrameIndex, const TargetRegisterClass *RC, Register VReg,
    MachineInstr::MIFlag Flags, bool NeedsCFI) const {
  MachineFunction *MF = MBB.getParent();
  SIMachineFunctionInfo *MFI = MF->getInfo<SIMachineFunctionInfo>();
  MachineFrameInfo &FrameInfo = MF->getFrameInfo();
  const DebugLoc &DL = MBB.findDebugLoc(MI);

  MachinePointerInfo PtrInfo
    = MachinePointerInfo::getFixedStack(*MF, FrameIndex);
  MachineMemOperand *MMO = MF->getMachineMemOperand(
      PtrInfo, MachineMemOperand::MOStore, FrameInfo.getObjectSize(FrameIndex),
      FrameInfo.getObjectAlign(FrameIndex));
  unsigned SpillSize = RI.getSpillSize(*RC);

  MachineRegisterInfo &MRI = MF->getRegInfo();
  if (RI.isSGPRClass(RC)) {
    if (FrameInfo.getStackID(FrameIndex) == TargetStackID::SGPRSpill)
      MFI->setHasSpilledSGPRs();
    assert(SrcReg != AMDGPU::M0 && "m0 should not be spilled");
    assert(SrcReg != AMDGPU::EXEC_LO && SrcReg != AMDGPU::EXEC_HI &&
           SrcReg != AMDGPU::EXEC && "exec should not be spilled");

    // We are only allowed to create one new instruction when spilling
    // registers, so we need to use pseudo instruction for spilling SGPRs.
    const MCInstrDesc &OpDesc =
        get(getSGPRSpillSaveOpcode(SpillSize, NeedsCFI));

    // The SGPR spill/restore instructions only work on number sgprs, so we need
    // to make sure we are using the correct register class.
    if (SrcReg.isVirtual() && SpillSize == 4) {
      MRI.constrainRegClass(SrcReg, &AMDGPU::SReg_32_XM0_XEXECRegClass);
    }

    BuildMI(MBB, MI, DL, OpDesc)
      .addReg(SrcReg, getKillRegState(isKill)) // data
      .addFrameIndex(FrameIndex)               // addr
      .addMemOperand(MMO)
      .addReg(MFI->getStackPtrOffsetReg(), RegState::Implicit);

    return;
  }

  unsigned Opcode = getVectorRegSpillSaveOpcode(VReg ? VReg : SrcReg, RC,
                                                SpillSize, *MFI, NeedsCFI);
  MFI->setHasSpilledVGPRs();

  BuildMI(MBB, MI, DL, get(Opcode))
    .addReg(SrcReg, getKillRegState(isKill)) // data
    .addFrameIndex(FrameIndex)               // addr
    .addReg(MFI->getStackPtrOffsetReg())     // scratch_offset
    .addImm(0)                               // offset
    .addMemOperand(MMO);
}

void SIInstrInfo::storeRegToStackSlot(
    MachineBasicBlock &MBB, MachineBasicBlock::iterator MI, Register SrcReg,
    bool isKill, int FrameIndex, const TargetRegisterClass *RC, Register VReg,
    MachineInstr::MIFlag Flags) const {
  storeRegToStackSlotImpl(MBB, MI, SrcReg, isKill, FrameIndex, RC, VReg, Flags,
                          false);
}

void SIInstrInfo::storeRegToStackSlotCFI(MachineBasicBlock &MBB,
                                         MachineBasicBlock::iterator MI,
                                         Register SrcReg, bool isKill,
                                         int FrameIndex,
                                         const TargetRegisterClass *RC) const {
  storeRegToStackSlotImpl(MBB, MI, SrcReg, isKill, FrameIndex, RC, Register(),
                          MachineInstr::NoFlags, true);
}

static unsigned getSGPRSpillRestoreOpcode(unsigned Size) {
  switch (Size) {
  case 4:
    return AMDGPU::SI_SPILL_S32_RESTORE;
  case 8:
    return AMDGPU::SI_SPILL_S64_RESTORE;
  case 12:
    return AMDGPU::SI_SPILL_S96_RESTORE;
  case 16:
    return AMDGPU::SI_SPILL_S128_RESTORE;
  case 20:
    return AMDGPU::SI_SPILL_S160_RESTORE;
  case 24:
    return AMDGPU::SI_SPILL_S192_RESTORE;
  case 28:
    return AMDGPU::SI_SPILL_S224_RESTORE;
  case 32:
    return AMDGPU::SI_SPILL_S256_RESTORE;
  case 36:
    return AMDGPU::SI_SPILL_S288_RESTORE;
  case 40:
    return AMDGPU::SI_SPILL_S320_RESTORE;
  case 44:
    return AMDGPU::SI_SPILL_S352_RESTORE;
  case 48:
    return AMDGPU::SI_SPILL_S384_RESTORE;
  case 64:
    return AMDGPU::SI_SPILL_S512_RESTORE;
  case 128:
    return AMDGPU::SI_SPILL_S1024_RESTORE;
  default:
    llvm_unreachable("unknown register size");
  }
}

static unsigned getVGPRSpillRestoreOpcode(unsigned Size) {
  switch (Size) {
  case 2:
    return AMDGPU::SI_SPILL_V16_RESTORE;
  case 4:
    return AMDGPU::SI_SPILL_V32_RESTORE;
  case 8:
    return AMDGPU::SI_SPILL_V64_RESTORE;
  case 12:
    return AMDGPU::SI_SPILL_V96_RESTORE;
  case 16:
    return AMDGPU::SI_SPILL_V128_RESTORE;
  case 20:
    return AMDGPU::SI_SPILL_V160_RESTORE;
  case 24:
    return AMDGPU::SI_SPILL_V192_RESTORE;
  case 28:
    return AMDGPU::SI_SPILL_V224_RESTORE;
  case 32:
    return AMDGPU::SI_SPILL_V256_RESTORE;
  case 36:
    return AMDGPU::SI_SPILL_V288_RESTORE;
  case 40:
    return AMDGPU::SI_SPILL_V320_RESTORE;
  case 44:
    return AMDGPU::SI_SPILL_V352_RESTORE;
  case 48:
    return AMDGPU::SI_SPILL_V384_RESTORE;
  case 64:
    return AMDGPU::SI_SPILL_V512_RESTORE;
  case 128:
    return AMDGPU::SI_SPILL_V1024_RESTORE;
  default:
    llvm_unreachable("unknown register size");
  }
}

static unsigned getAVSpillRestoreOpcode(unsigned Size) {
  switch (Size) {
  case 4:
    return AMDGPU::SI_SPILL_AV32_RESTORE;
  case 8:
    return AMDGPU::SI_SPILL_AV64_RESTORE;
  case 12:
    return AMDGPU::SI_SPILL_AV96_RESTORE;
  case 16:
    return AMDGPU::SI_SPILL_AV128_RESTORE;
  case 20:
    return AMDGPU::SI_SPILL_AV160_RESTORE;
  case 24:
    return AMDGPU::SI_SPILL_AV192_RESTORE;
  case 28:
    return AMDGPU::SI_SPILL_AV224_RESTORE;
  case 32:
    return AMDGPU::SI_SPILL_AV256_RESTORE;
  case 36:
    return AMDGPU::SI_SPILL_AV288_RESTORE;
  case 40:
    return AMDGPU::SI_SPILL_AV320_RESTORE;
  case 44:
    return AMDGPU::SI_SPILL_AV352_RESTORE;
  case 48:
    return AMDGPU::SI_SPILL_AV384_RESTORE;
  case 64:
    return AMDGPU::SI_SPILL_AV512_RESTORE;
  case 128:
    return AMDGPU::SI_SPILL_AV1024_RESTORE;
  default:
    llvm_unreachable("unknown register size");
  }
}

static unsigned getWWMRegSpillRestoreOpcode(unsigned Size,
                                            bool IsVectorSuperClass) {
  // Currently, there is only 32-bit WWM register spills needed.
  if (Size != 4)
    llvm_unreachable("unknown wwm register spill size");

  if (IsVectorSuperClass) // TODO: Always use this if there are AGPRs
    return AMDGPU::SI_SPILL_WWM_AV32_RESTORE;

  return AMDGPU::SI_SPILL_WWM_V32_RESTORE;
}

unsigned SIInstrInfo::getVectorRegSpillRestoreOpcode(
    Register Reg, const TargetRegisterClass *RC, unsigned Size,
    const SIMachineFunctionInfo &MFI) const {
  bool IsVectorSuperClass = RI.isVectorSuperClass(RC);

  // Choose the right opcode if restoring a WWM register.
  if (MFI.checkFlag(Reg, AMDGPU::VirtRegFlag::WWM_REG))
    return getWWMRegSpillRestoreOpcode(Size, IsVectorSuperClass);

  // TODO: Check if AGPRs are available
  if (ST.hasMAIInsts())
    return getAVSpillRestoreOpcode(Size);

  assert(!RI.isAGPRClass(RC));
  return getVGPRSpillRestoreOpcode(Size);
}

void SIInstrInfo::loadRegFromStackSlot(MachineBasicBlock &MBB,
                                       MachineBasicBlock::iterator MI,
                                       Register DestReg, int FrameIndex,
                                       const TargetRegisterClass *RC,
                                       Register VReg, unsigned SubReg,
                                       MachineInstr::MIFlag Flags) const {
  MachineFunction *MF = MBB.getParent();
  SIMachineFunctionInfo *MFI = MF->getInfo<SIMachineFunctionInfo>();
  MachineFrameInfo &FrameInfo = MF->getFrameInfo();
  const DebugLoc &DL = MBB.findDebugLoc(MI);
  unsigned SpillSize = RI.getSpillSize(*RC);

  MachinePointerInfo PtrInfo
    = MachinePointerInfo::getFixedStack(*MF, FrameIndex);

  MachineMemOperand *MMO = MF->getMachineMemOperand(
      PtrInfo, MachineMemOperand::MOLoad, FrameInfo.getObjectSize(FrameIndex),
      FrameInfo.getObjectAlign(FrameIndex));

  if (RI.isSGPRClass(RC)) {
    if (FrameInfo.getStackID(FrameIndex) == TargetStackID::SGPRSpill)
      MFI->setHasSpilledSGPRs();
    assert(DestReg != AMDGPU::M0 && "m0 should not be reloaded into");
    assert(DestReg != AMDGPU::EXEC_LO && DestReg != AMDGPU::EXEC_HI &&
           DestReg != AMDGPU::EXEC && "exec should not be spilled");

    // FIXME: Maybe this should not include a memoperand because it will be
    // lowered to non-memory instructions.
    const MCInstrDesc &OpDesc = get(getSGPRSpillRestoreOpcode(SpillSize));
    if (DestReg.isVirtual() && SpillSize == 4) {
      MachineRegisterInfo &MRI = MF->getRegInfo();
      MRI.constrainRegClass(DestReg, &AMDGPU::SReg_32_XM0_XEXECRegClass);
    }

    BuildMI(MBB, MI, DL, OpDesc, DestReg)
      .addFrameIndex(FrameIndex) // addr
      .addMemOperand(MMO)
      .addReg(MFI->getStackPtrOffsetReg(), RegState::Implicit);

    return;
  }

  unsigned Opcode = getVectorRegSpillRestoreOpcode(VReg ? VReg : DestReg, RC,
                                                   SpillSize, *MFI);
  BuildMI(MBB, MI, DL, get(Opcode), DestReg)
      .addFrameIndex(FrameIndex)           // vaddr
      .addReg(MFI->getStackPtrOffsetReg()) // scratch_offset
      .addImm(0)                           // offset
      .addMemOperand(MMO);
}

void SIInstrInfo::insertNoop(MachineBasicBlock &MBB,
                             MachineBasicBlock::iterator MI) const {
  insertNoops(MBB, MI, 1);
}

void SIInstrInfo::insertNoops(MachineBasicBlock &MBB,
                              MachineBasicBlock::iterator MI,
                              unsigned Quantity) const {
  DebugLoc DL = MBB.findDebugLoc(MI);
  unsigned MaxSNopCount = 1u << ST.getSNopBits();
  while (Quantity > 0) {
    unsigned Arg = std::min(Quantity, MaxSNopCount);
    Quantity -= Arg;
    BuildMI(MBB, MI, DL, get(AMDGPU::S_NOP)).addImm(Arg - 1);
  }
}

MachineBasicBlock *SIInstrInfo::insertSimulatedTrap(MachineRegisterInfo &MRI,
                                                    MachineBasicBlock &MBB,
                                                    MachineInstr &MI,
                                                    const DebugLoc &DL) const {
  MachineFunction *MF = MBB.getParent();
  constexpr unsigned DoorbellIDMask = 0x3ff;
  constexpr unsigned ECQueueWaveAbort = 0x400;

  MachineBasicBlock *TrapBB = &MBB;
  MachineBasicBlock *HaltLoopBB = MF->CreateMachineBasicBlock();

  if (!MBB.succ_empty() || std::next(MI.getIterator()) != MBB.end()) {
    MBB.splitAt(MI, /*UpdateLiveIns=*/false);
    TrapBB = MF->CreateMachineBasicBlock();
    BuildMI(MBB, MI, DL, get(AMDGPU::S_CBRANCH_EXECNZ)).addMBB(TrapBB);
    MF->push_back(TrapBB);
    MBB.addSuccessor(TrapBB);
  }
  // Start with a `s_trap 2`, if we're in PRIV=1 and we need the workaround this
  // will be a nop.
  BuildMI(*TrapBB, TrapBB->end(), DL, get(AMDGPU::S_TRAP))
      .addImm(static_cast<unsigned>(GCNSubtarget::TrapID::LLVMAMDHSATrap));
  Register DoorbellReg = MRI.createVirtualRegister(&AMDGPU::SReg_32RegClass);
  BuildMI(*TrapBB, TrapBB->end(), DL, get(AMDGPU::S_SENDMSG_RTN_B32),
          DoorbellReg)
      .addImm(AMDGPU::SendMsg::ID_RTN_GET_DOORBELL);
  BuildMI(*TrapBB, TrapBB->end(), DL, get(AMDGPU::S_MOV_B32), AMDGPU::TTMP2)
      .addUse(AMDGPU::M0);
  Register DoorbellRegMasked =
      MRI.createVirtualRegister(&AMDGPU::SReg_32RegClass);
  BuildMI(*TrapBB, TrapBB->end(), DL, get(AMDGPU::S_AND_B32), DoorbellRegMasked)
      .addUse(DoorbellReg)
      .addImm(DoorbellIDMask);
  Register SetWaveAbortBit =
      MRI.createVirtualRegister(&AMDGPU::SReg_32RegClass);
  BuildMI(*TrapBB, TrapBB->end(), DL, get(AMDGPU::S_OR_B32), SetWaveAbortBit)
      .addUse(DoorbellRegMasked)
      .addImm(ECQueueWaveAbort);
  BuildMI(*TrapBB, TrapBB->end(), DL, get(AMDGPU::S_MOV_B32), AMDGPU::M0)
      .addUse(SetWaveAbortBit);
  BuildMI(*TrapBB, TrapBB->end(), DL, get(AMDGPU::S_SENDMSG))
      .addImm(AMDGPU::SendMsg::ID_INTERRUPT);
  BuildMI(*TrapBB, TrapBB->end(), DL, get(AMDGPU::S_MOV_B32), AMDGPU::M0)
      .addUse(AMDGPU::TTMP2);
  BuildMI(*TrapBB, TrapBB->end(), DL, get(AMDGPU::S_BRANCH)).addMBB(HaltLoopBB);
  TrapBB->addSuccessor(HaltLoopBB);

  BuildMI(*HaltLoopBB, HaltLoopBB->end(), DL, get(AMDGPU::S_SETHALT)).addImm(5);
  BuildMI(*HaltLoopBB, HaltLoopBB->end(), DL, get(AMDGPU::S_BRANCH))
      .addMBB(HaltLoopBB);
  MF->push_back(HaltLoopBB);
  HaltLoopBB->addSuccessor(HaltLoopBB);

  return MBB.getNextNode();
}

unsigned SIInstrInfo::getNumWaitStates(const MachineInstr &MI) {
  switch (MI.getOpcode()) {
  default:
    if (MI.isMetaInstruction())
      return 0;
    return 1; // FIXME: Do wait states equal cycles?

  case AMDGPU::S_NOP:
    return MI.getOperand(0).getImm() + 1;
  // SI_RETURN_TO_EPILOG is a fallthrough to code outside of the function. The
  // hazard, even if one exist, won't really be visible. Should we handle it?
  }
}

bool SIInstrInfo::expandPostRAPseudo(MachineInstr &MI) const {
  MachineBasicBlock &MBB = *MI.getParent();
  DebugLoc DL = MBB.findDebugLoc(MI);
  const AMDGPU::LaneMaskConstants &LMC = AMDGPU::LaneMaskConstants::get(ST);

  switch (MI.getOpcode()) {
  default: return TargetInstrInfo::expandPostRAPseudo(MI);
  case AMDGPU::S_MOV_B64_term:
    // This is only a terminator to get the correct spill code placement during
    // register allocation.
    MI.setDesc(get(AMDGPU::S_MOV_B64));
    break;

  case AMDGPU::S_MOV_B32_term:
    // This is only a terminator to get the correct spill code placement during
    // register allocation.
    MI.setDesc(get(AMDGPU::S_MOV_B32));
    break;

  case AMDGPU::S_XOR_B64_term:
    // This is only a terminator to get the correct spill code placement during
    // register allocation.
    MI.setDesc(get(AMDGPU::S_XOR_B64));
    break;

  case AMDGPU::S_XOR_B32_term:
    // This is only a terminator to get the correct spill code placement during
    // register allocation.
    MI.setDesc(get(AMDGPU::S_XOR_B32));
    break;
  case AMDGPU::S_OR_B64_term:
    // This is only a terminator to get the correct spill code placement during
    // register allocation.
    MI.setDesc(get(AMDGPU::S_OR_B64));
    break;
  case AMDGPU::S_OR_B32_term:
    // This is only a terminator to get the correct spill code placement during
    // register allocation.
    MI.setDesc(get(AMDGPU::S_OR_B32));
    break;

  case AMDGPU::S_ANDN2_B64_term:
    // This is only a terminator to get the correct spill code placement during
    // register allocation.
    MI.setDesc(get(AMDGPU::S_ANDN2_B64));
    break;

  case AMDGPU::S_ANDN2_B32_term:
    // This is only a terminator to get the correct spill code placement during
    // register allocation.
    MI.setDesc(get(AMDGPU::S_ANDN2_B32));
    break;

  case AMDGPU::S_AND_B64_term:
    // This is only a terminator to get the correct spill code placement during
    // register allocation.
    MI.setDesc(get(AMDGPU::S_AND_B64));
    break;

  case AMDGPU::S_AND_B32_term:
    // This is only a terminator to get the correct spill code placement during
    // register allocation.
    MI.setDesc(get(AMDGPU::S_AND_B32));
    break;

  case AMDGPU::S_AND_SAVEEXEC_B64_term:
    // This is only a terminator to get the correct spill code placement during
    // register allocation.
    MI.setDesc(get(AMDGPU::S_AND_SAVEEXEC_B64));
    break;

  case AMDGPU::S_AND_SAVEEXEC_B32_term:
    // This is only a terminator to get the correct spill code placement during
    // register allocation.
    MI.setDesc(get(AMDGPU::S_AND_SAVEEXEC_B32));
    break;

  case AMDGPU::V_CMPX_EQ_U32_nosdst_e32_term:
    MI.setDesc(get(AMDGPU::V_CMPX_EQ_U32_nosdst_e32));
    break;
  case AMDGPU::V_CMPX_EQ_U64_nosdst_e32_term:
    MI.setDesc(get(AMDGPU::V_CMPX_EQ_U64_nosdst_e32));
    break;

  case AMDGPU::SI_SPILL_S32_TO_VGPR:
    MI.setDesc(get(AMDGPU::V_WRITELANE_B32));
    break;

  case AMDGPU::SI_RESTORE_S32_FROM_VGPR:
    MI.setDesc(get(AMDGPU::V_READLANE_B32));
    break;
  case AMDGPU::AV_MOV_B32_IMM_PSEUDO: {
    Register Dst = MI.getOperand(0).getReg();
    bool IsAGPR = SIRegisterInfo::isAGPRClass(RI.getPhysRegBaseClass(Dst));
    MI.setDesc(
        get(IsAGPR ? AMDGPU::V_ACCVGPR_WRITE_B32_e64 : AMDGPU::V_MOV_B32_e32));
    break;
  }
  case AMDGPU::AV_MOV_B64_IMM_PSEUDO: {
    Register Dst = MI.getOperand(0).getReg();
    if (SIRegisterInfo::isAGPRClass(RI.getPhysRegBaseClass(Dst))) {
      int64_t Imm = MI.getOperand(1).getImm();

      Register DstLo = RI.getSubReg(Dst, AMDGPU::sub0);
      Register DstHi = RI.getSubReg(Dst, AMDGPU::sub1);
      BuildMI(MBB, MI, DL, get(AMDGPU::V_ACCVGPR_WRITE_B32_e64), DstLo)
          .addImm(SignExtend64<32>(Imm));
      BuildMI(MBB, MI, DL, get(AMDGPU::V_ACCVGPR_WRITE_B32_e64), DstHi)
          .addImm(SignExtend64<32>(Imm >> 32));
      MI.eraseFromParent();
      break;
    }

    [[fallthrough]];
  }
  case AMDGPU::V_MOV_B64_PSEUDO: {
    Register Dst = MI.getOperand(0).getReg();
    Register DstLo = RI.getSubReg(Dst, AMDGPU::sub0);
    Register DstHi = RI.getSubReg(Dst, AMDGPU::sub1);

    const MCInstrDesc &Mov64Desc = get(AMDGPU::V_MOV_B64_e32);
    const TargetRegisterClass *Mov64RC = getRegClass(Mov64Desc, /*OpNum=*/0);

    const MachineOperand &SrcOp = MI.getOperand(1);
    // FIXME: Will this work for 64-bit floating point immediates?
    assert(!SrcOp.isFPImm());
    if (ST.hasVMovB64Inst() && Mov64RC->contains(Dst)) {
      MI.setDesc(Mov64Desc);
      if (SrcOp.isReg() || isInlineConstant(MI, 1) ||
          (SrcOp.isImm() &&
           (isUInt<32>(SrcOp.getImm()) || ST.has64BitLiterals())) ||
          (SrcOp.isGlobal() && ST.has64BitLiterals()))
        break;
    }
    if (SrcOp.isGlobal()) {
      // The address is unknown until link time, so the PK_MOV inline-constant
      // shortcut cannot apply.
      const GlobalValue *GV = SrcOp.getGlobal();
      int64_t Offset = SrcOp.getOffset();
      unsigned BaseFlags, LoReloc, HiReloc;
      std::tie(BaseFlags, LoReloc, HiReloc) =
          splitGlobalAddressRelocFlags(ST, SrcOp);

      BuildMI(MBB, MI, DL, get(AMDGPU::V_MOV_B32_e32), DstLo)
          .addGlobalAddress(GV, Offset, BaseFlags | LoReloc);
      BuildMI(MBB, MI, DL, get(AMDGPU::V_MOV_B32_e32), DstHi)
          .addGlobalAddress(GV, Offset, BaseFlags | HiReloc);
    } else if (SrcOp.isImm()) {
      APInt Imm(64, SrcOp.getImm());
      APInt Lo(32, Imm.getLoBits(32).getZExtValue());
      APInt Hi(32, Imm.getHiBits(32).getZExtValue());
      const MCInstrDesc &PkMovDesc = get(AMDGPU::V_PK_MOV_B32);
      const TargetRegisterClass *PkMovRC = getRegClass(PkMovDesc, /*OpNum=*/0);

      if (ST.hasPkMovB32() && Lo == Hi && isInlineConstant(Lo) &&
          PkMovRC->contains(Dst)) {
        BuildMI(MBB, MI, DL, PkMovDesc, Dst)
            .addImm(SISrcMods::OP_SEL_1)
            .addImm(Lo.getSExtValue())
            .addImm(SISrcMods::OP_SEL_1)
            .addImm(Lo.getSExtValue())
            .addImm(0)  // op_sel_lo
            .addImm(0)  // op_sel_hi
            .addImm(0)  // neg_lo
            .addImm(0)  // neg_hi
            .addImm(0); // clamp
      } else {
        BuildMI(MBB, MI, DL, get(AMDGPU::V_MOV_B32_e32), DstLo)
            .addImm(Lo.getSExtValue());
        BuildMI(MBB, MI, DL, get(AMDGPU::V_MOV_B32_e32), DstHi)
            .addImm(Hi.getSExtValue());
      }
    } else {
      assert(SrcOp.isReg());
      if (ST.hasPkMovB32() &&
          !RI.isAGPR(MBB.getParent()->getRegInfo(), SrcOp.getReg())) {
        BuildMI(MBB, MI, DL, get(AMDGPU::V_PK_MOV_B32), Dst)
          .addImm(SISrcMods::OP_SEL_1) // src0_mod
          .addReg(SrcOp.getReg())
          .addImm(SISrcMods::OP_SEL_0 | SISrcMods::OP_SEL_1) // src1_mod
          .addReg(SrcOp.getReg())
          .addImm(0)  // op_sel_lo
          .addImm(0)  // op_sel_hi
          .addImm(0)  // neg_lo
          .addImm(0)  // neg_hi
          .addImm(0); // clamp
      } else {
        BuildMI(MBB, MI, DL, get(AMDGPU::V_MOV_B32_e32), DstLo)
            .addReg(RI.getSubReg(SrcOp.getReg(), AMDGPU::sub0));
        BuildMI(MBB, MI, DL, get(AMDGPU::V_MOV_B32_e32), DstHi)
            .addReg(RI.getSubReg(SrcOp.getReg(), AMDGPU::sub1));
      }
    }
    MI.eraseFromParent();
    break;
  }
  case AMDGPU::V_MOV_B64_DPP_PSEUDO: {
    expandMovDPP64(MI);
    break;
  }
  case AMDGPU::S_MOV_B64_IMM_PSEUDO: {
    const MachineOperand &SrcOp = MI.getOperand(1);
    assert(!SrcOp.isFPImm());

    if (ST.has64BitLiterals()) {
      MI.setDesc(get(AMDGPU::S_MOV_B64));
      break;
    }

    if (SrcOp.isGlobal()) {
      Register Dst = MI.getOperand(0).getReg();
      Register DstLo = RI.getSubReg(Dst, AMDGPU::sub0);
      Register DstHi = RI.getSubReg(Dst, AMDGPU::sub1);
      const GlobalValue *GV = SrcOp.getGlobal();
      int64_t Offset = SrcOp.getOffset();
      unsigned BaseFlags, LoReloc, HiReloc;
      std::tie(BaseFlags, LoReloc, HiReloc) =
          splitGlobalAddressRelocFlags(ST, SrcOp);

      BuildMI(MBB, MI, DL, get(AMDGPU::S_MOV_B32), DstLo)
          .addGlobalAddress(GV, Offset, BaseFlags | LoReloc);
      BuildMI(MBB, MI, DL, get(AMDGPU::S_MOV_B32), DstHi)
          .addGlobalAddress(GV, Offset, BaseFlags | HiReloc);
      MI.eraseFromParent();
      break;
    }

    // SrcOp is immediate
    APInt Imm(64, SrcOp.getImm());
    if (Imm.isIntN(32) || isInlineConstant(Imm)) {
      MI.setDesc(get(AMDGPU::S_MOV_B64));
      break;
    }

    Register Dst = MI.getOperand(0).getReg();
    Register DstLo = RI.getSubReg(Dst, AMDGPU::sub0);
    Register DstHi = RI.getSubReg(Dst, AMDGPU::sub1);

    APInt Lo(32, Imm.getLoBits(32).getZExtValue());
    APInt Hi(32, Imm.getHiBits(32).getZExtValue());
    BuildMI(MBB, MI, DL, get(AMDGPU::S_MOV_B32), DstLo)
        .addImm(Lo.getSExtValue());
    BuildMI(MBB, MI, DL, get(AMDGPU::S_MOV_B32), DstHi)
        .addImm(Hi.getSExtValue());
    MI.eraseFromParent();
    break;
  }
  case AMDGPU::V_SET_INACTIVE_B32: {
    // Lower V_SET_INACTIVE_B32 to V_CNDMASK_B32.
    Register DstReg = MI.getOperand(0).getReg();
    BuildMI(MBB, MI, DL, get(AMDGPU::V_CNDMASK_B32_e64), DstReg)
        .add(MI.getOperand(3))
        .add(MI.getOperand(4))
        .add(MI.getOperand(1))
        .add(MI.getOperand(2))
        .add(MI.getOperand(5));
    MI.eraseFromParent();
    break;
  }
  case AMDGPU::V_INDIRECT_REG_WRITE_MOVREL_B32_V1:
  case AMDGPU::V_INDIRECT_REG_WRITE_MOVREL_B32_V2:
  case AMDGPU::V_INDIRECT_REG_WRITE_MOVREL_B32_V3:
  case AMDGPU::V_INDIRECT_REG_WRITE_MOVREL_B32_V4:
  case AMDGPU::V_INDIRECT_REG_WRITE_MOVREL_B32_V5:
  case AMDGPU::V_INDIRECT_REG_WRITE_MOVREL_B32_V6:
  case AMDGPU::V_INDIRECT_REG_WRITE_MOVREL_B32_V7:
  case AMDGPU::V_INDIRECT_REG_WRITE_MOVREL_B32_V8:
  case AMDGPU::V_INDIRECT_REG_WRITE_MOVREL_B32_V9:
  case AMDGPU::V_INDIRECT_REG_WRITE_MOVREL_B32_V10:
  case AMDGPU::V_INDIRECT_REG_WRITE_MOVREL_B32_V11:
  case AMDGPU::V_INDIRECT_REG_WRITE_MOVREL_B32_V12:
  case AMDGPU::V_INDIRECT_REG_WRITE_MOVREL_B32_V16:
  case AMDGPU::V_INDIRECT_REG_WRITE_MOVREL_B32_V32:
  case AMDGPU::S_INDIRECT_REG_WRITE_MOVREL_B32_V1:
  case AMDGPU::S_INDIRECT_REG_WRITE_MOVREL_B32_V2:
  case AMDGPU::S_INDIRECT_REG_WRITE_MOVREL_B32_V3:
  case AMDGPU::S_INDIRECT_REG_WRITE_MOVREL_B32_V4:
  case AMDGPU::S_INDIRECT_REG_WRITE_MOVREL_B32_V5:
  case AMDGPU::S_INDIRECT_REG_WRITE_MOVREL_B32_V6:
  case AMDGPU::S_INDIRECT_REG_WRITE_MOVREL_B32_V7:
  case AMDGPU::S_INDIRECT_REG_WRITE_MOVREL_B32_V8:
  case AMDGPU::S_INDIRECT_REG_WRITE_MOVREL_B32_V9:
  case AMDGPU::S_INDIRECT_REG_WRITE_MOVREL_B32_V10:
  case AMDGPU::S_INDIRECT_REG_WRITE_MOVREL_B32_V11:
  case AMDGPU::S_INDIRECT_REG_WRITE_MOVREL_B32_V12:
  case AMDGPU::S_INDIRECT_REG_WRITE_MOVREL_B32_V16:
  case AMDGPU::S_INDIRECT_REG_WRITE_MOVREL_B32_V32:
  case AMDGPU::S_INDIRECT_REG_WRITE_MOVREL_B64_V1:
  case AMDGPU::S_INDIRECT_REG_WRITE_MOVREL_B64_V2:
  case AMDGPU::S_INDIRECT_REG_WRITE_MOVREL_B64_V4:
  case AMDGPU::S_INDIRECT_REG_WRITE_MOVREL_B64_V8:
  case AMDGPU::S_INDIRECT_REG_WRITE_MOVREL_B64_V16: {
    const TargetRegisterClass *EltRC = getOpRegClass(MI, 2);

    unsigned Opc;
    if (RI.hasVGPRs(EltRC)) {
      Opc = AMDGPU::V_MOVRELD_B32_e32;
    } else {
      Opc = RI.getRegSizeInBits(*EltRC) == 64 ? AMDGPU::S_MOVRELD_B64
                                              : AMDGPU::S_MOVRELD_B32;
    }

    const MCInstrDesc &OpDesc = get(Opc);
    Register VecReg = MI.getOperand(0).getReg();
    bool IsUndef = MI.getOperand(1).isUndef();
    unsigned SubReg = MI.getOperand(3).getImm();
    assert(VecReg == MI.getOperand(1).getReg());

    MachineInstrBuilder MIB =
        BuildMI(MBB, MI, DL, OpDesc)
            .addReg(RI.getSubReg(VecReg, SubReg), RegState::Undef)
            .add(MI.getOperand(2))
            .addReg(VecReg, RegState::ImplicitDefine)
            .addReg(VecReg, RegState::Implicit | getUndefRegState(IsUndef));

    const int ImpDefIdx =
        OpDesc.getNumOperands() + OpDesc.implicit_uses().size();
    const int ImpUseIdx = ImpDefIdx + 1;
    MIB->tieOperands(ImpDefIdx, ImpUseIdx);
    MI.eraseFromParent();
    break;
  }
  case AMDGPU::V_INDIRECT_REG_WRITE_GPR_IDX_B32_V1:
  case AMDGPU::V_INDIRECT_REG_WRITE_GPR_IDX_B32_V2:
  case AMDGPU::V_INDIRECT_REG_WRITE_GPR_IDX_B32_V3:
  case AMDGPU::V_INDIRECT_REG_WRITE_GPR_IDX_B32_V4:
  case AMDGPU::V_INDIRECT_REG_WRITE_GPR_IDX_B32_V5:
  case AMDGPU::V_INDIRECT_REG_WRITE_GPR_IDX_B32_V6:
  case AMDGPU::V_INDIRECT_REG_WRITE_GPR_IDX_B32_V7:
  case AMDGPU::V_INDIRECT_REG_WRITE_GPR_IDX_B32_V8:
  case AMDGPU::V_INDIRECT_REG_WRITE_GPR_IDX_B32_V9:
  case AMDGPU::V_INDIRECT_REG_WRITE_GPR_IDX_B32_V10:
  case AMDGPU::V_INDIRECT_REG_WRITE_GPR_IDX_B32_V11:
  case AMDGPU::V_INDIRECT_REG_WRITE_GPR_IDX_B32_V12:
  case AMDGPU::V_INDIRECT_REG_WRITE_GPR_IDX_B32_V16:
  case AMDGPU::V_INDIRECT_REG_WRITE_GPR_IDX_B32_V32: {
    assert(ST.useVGPRIndexMode());
    Register VecReg = MI.getOperand(0).getReg();
    bool IsUndef = MI.getOperand(1).isUndef();
    MachineOperand &Idx = MI.getOperand(3);
    Register SubReg = MI.getOperand(4).getImm();

    MachineInstr *SetOn = BuildMI(MBB, MI, DL, get(AMDGPU::S_SET_GPR_IDX_ON))
                              .add(Idx)
                              .addImm(AMDGPU::VGPRIndexMode::DST_ENABLE);
    SetOn->getOperand(3).setIsUndef();

    const MCInstrDesc &OpDesc = get(AMDGPU::V_MOV_B32_indirect_write);
    MachineInstrBuilder MIB =
        BuildMI(MBB, MI, DL, OpDesc)
            .addReg(RI.getSubReg(VecReg, SubReg), RegState::Undef)
            .add(MI.getOperand(2))
            .addReg(VecReg, RegState::ImplicitDefine)
            .addReg(VecReg, RegState::Implicit | getUndefRegState(IsUndef));

    const int ImpDefIdx =
        OpDesc.getNumOperands() + OpDesc.implicit_uses().size();
    const int ImpUseIdx = ImpDefIdx + 1;
    MIB->tieOperands(ImpDefIdx, ImpUseIdx);

    MachineInstr *SetOff = BuildMI(MBB, MI, DL, get(AMDGPU::S_SET_GPR_IDX_OFF));

    finalizeBundle(MBB, SetOn->getIterator(), std::next(SetOff->getIterator()));

    MI.eraseFromParent();
    break;
  }
  case AMDGPU::V_INDIRECT_REG_READ_GPR_IDX_B32_V1:
  case AMDGPU::V_INDIRECT_REG_READ_GPR_IDX_B32_V2:
  case AMDGPU::V_INDIRECT_REG_READ_GPR_IDX_B32_V3:
  case AMDGPU::V_INDIRECT_REG_READ_GPR_IDX_B32_V4:
  case AMDGPU::V_INDIRECT_REG_READ_GPR_IDX_B32_V5:
  case AMDGPU::V_INDIRECT_REG_READ_GPR_IDX_B32_V6:
  case AMDGPU::V_INDIRECT_REG_READ_GPR_IDX_B32_V7:
  case AMDGPU::V_INDIRECT_REG_READ_GPR_IDX_B32_V8:
  case AMDGPU::V_INDIRECT_REG_READ_GPR_IDX_B32_V9:
  case AMDGPU::V_INDIRECT_REG_READ_GPR_IDX_B32_V10:
  case AMDGPU::V_INDIRECT_REG_READ_GPR_IDX_B32_V11:
  case AMDGPU::V_INDIRECT_REG_READ_GPR_IDX_B32_V12:
  case AMDGPU::V_INDIRECT_REG_READ_GPR_IDX_B32_V16:
  case AMDGPU::V_INDIRECT_REG_READ_GPR_IDX_B32_V32: {
    assert(ST.useVGPRIndexMode());
    Register Dst = MI.getOperand(0).getReg();
    Register VecReg = MI.getOperand(1).getReg();
    bool IsUndef = MI.getOperand(1).isUndef();
    Register SubReg = MI.getOperand(3).getImm();

    MachineInstr *SetOn = BuildMI(MBB, MI, DL, get(AMDGPU::S_SET_GPR_IDX_ON))
                              .add(MI.getOperand(2))
                              .addImm(AMDGPU::VGPRIndexMode::SRC0_ENABLE);
    SetOn->getOperand(3).setIsUndef();

    BuildMI(MBB, MI, DL, get(AMDGPU::V_MOV_B32_indirect_read))
        .addDef(Dst)
        .addReg(RI.getSubReg(VecReg, SubReg), RegState::Undef)
        .addReg(VecReg, RegState::Implicit | getUndefRegState(IsUndef));

    MachineInstr *SetOff = BuildMI(MBB, MI, DL, get(AMDGPU::S_SET_GPR_IDX_OFF));

    finalizeBundle(MBB, SetOn->getIterator(), std::next(SetOff->getIterator()));

    MI.eraseFromParent();
    break;
  }
  case AMDGPU::SI_PC_ADD_REL_OFFSET: {
    MachineFunction &MF = *MBB.getParent();
    Register Reg = MI.getOperand(0).getReg();
    Register RegLo = RI.getSubReg(Reg, AMDGPU::sub0);
    Register RegHi = RI.getSubReg(Reg, AMDGPU::sub1);
    MachineOperand OpLo = MI.getOperand(1);
    MachineOperand OpHi = MI.getOperand(2);

    // Create a bundle so these instructions won't be re-ordered by the
    // post-RA scheduler.
    MIBundleBuilder Bundler(MBB, MI);
    Bundler.append(BuildMI(MF, DL, get(AMDGPU::S_GETPC_B64), Reg));

    // What we want here is an offset from the value returned by s_getpc (which
    // is the address of the s_add_u32 instruction) to the global variable, but
    // since the encoding of $symbol starts 4 bytes after the start of the
    // s_add_u32 instruction, we end up with an offset that is 4 bytes too
    // small. This requires us to add 4 to the global variable offset in order
    // to compute the correct address. Similarly for the s_addc_u32 instruction,
    // the encoding of $symbol starts 12 bytes after the start of the s_add_u32
    // instruction.

    int64_t Adjust = 0;
    if (ST.hasGetPCZeroExtension()) {
      // Fix up hardware that does not sign-extend the 48-bit PC value by
      // inserting: s_sext_i32_i16 reghi, reghi
      Bundler.append(
          BuildMI(MF, DL, get(AMDGPU::S_SEXT_I32_I16), RegHi).addReg(RegHi));
      Adjust += 4;
    }

    if (OpLo.isGlobal())
      OpLo.setOffset(OpLo.getOffset() + Adjust + 4);
    Bundler.append(
        BuildMI(MF, DL, get(AMDGPU::S_ADD_U32), RegLo).addReg(RegLo).add(OpLo));

    if (OpHi.isGlobal())
      OpHi.setOffset(OpHi.getOffset() + Adjust + 12);
    Bundler.append(BuildMI(MF, DL, get(AMDGPU::S_ADDC_U32), RegHi)
                       .addReg(RegHi)
                       .add(OpHi));

    finalizeBundle(MBB, Bundler.begin());

    MI.eraseFromParent();
    break;
  }
  case AMDGPU::SI_PC_ADD_REL_OFFSET64: {
    MachineFunction &MF = *MBB.getParent();
    Register Reg = MI.getOperand(0).getReg();
    MachineOperand Op = MI.getOperand(1);

    // Create a bundle so these instructions won't be re-ordered by the
    // post-RA scheduler.
    MIBundleBuilder Bundler(MBB, MI);
    Bundler.append(BuildMI(MF, DL, get(AMDGPU::S_GETPC_B64), Reg));
    if (Op.isGlobal())
      Op.setOffset(Op.getOffset() + 4);
    Bundler.append(
        BuildMI(MF, DL, get(AMDGPU::S_ADD_U64), Reg).addReg(Reg).add(Op));

    finalizeBundle(MBB, Bundler.begin());

    MI.eraseFromParent();
    break;
  }
  case AMDGPU::ENTER_STRICT_WWM: {
    // This only gets its own opcode so that SIPreAllocateWWMRegs can tell when
    // Whole Wave Mode is entered.
    MI.setDesc(get(LMC.OrSaveExecOpc));
    break;
  }
  case AMDGPU::ENTER_STRICT_WQM: {
    // This only gets its own opcode so that SIPreAllocateWWMRegs can tell when
    // STRICT_WQM is entered.
    BuildMI(MBB, MI, DL, get(LMC.MovOpc), MI.getOperand(0).getReg())
        .addReg(LMC.ExecReg);
    BuildMI(MBB, MI, DL, get(LMC.WQMOpc), LMC.ExecReg).addReg(LMC.ExecReg);

    MI.eraseFromParent();
    break;
  }
  case AMDGPU::EXIT_STRICT_WWM:
  case AMDGPU::EXIT_STRICT_WQM: {
    // This only gets its own opcode so that SIPreAllocateWWMRegs can tell when
    // WWM/STICT_WQM is exited.
    MI.setDesc(get(LMC.MovOpc));
    break;
  }
  case AMDGPU::SI_RETURN: {
    const MachineFunction *MF = MBB.getParent();
    const GCNSubtarget &ST = MF->getSubtarget<GCNSubtarget>();
    const SIRegisterInfo *TRI = ST.getRegisterInfo();
    // Hiding the return address use with SI_RETURN may lead to extra kills in
    // the function and missing live-ins. We are fine in practice because callee
    // saved register handling ensures the register value is restored before
    // RET, but we need the undef flag here to appease the MachineVerifier
    // liveness checks.
    MachineInstrBuilder MIB =
        BuildMI(MBB, MI, DL, get(AMDGPU::S_SETPC_B64_return))
            .addReg(TRI->getReturnAddressReg(*MF), RegState::Undef);

    MIB.copyImplicitOps(MI);
    MI.eraseFromParent();
    break;
  }

  case AMDGPU::S_MUL_U64_U32_PSEUDO:
  case AMDGPU::S_MUL_I64_I32_PSEUDO:
    MI.setDesc(get(AMDGPU::S_MUL_U64));
    break;

  case AMDGPU::S_GETPC_B64_pseudo:
    MI.setDesc(get(AMDGPU::S_GETPC_B64));
    if (ST.hasGetPCZeroExtension()) {
      Register Dst = MI.getOperand(0).getReg();
      Register DstHi = RI.getSubReg(Dst, AMDGPU::sub1);
      // Fix up hardware that does not sign-extend the 48-bit PC value by
      // inserting: s_sext_i32_i16 dsthi, dsthi
      BuildMI(MBB, std::next(MI.getIterator()), DL, get(AMDGPU::S_SEXT_I32_I16),
              DstHi)
          .addReg(DstHi);
    }
    break;

  case AMDGPU::V_MAX_BF16_PSEUDO_e64: {
    assert(ST.hasBF16PackedInsts());
    MI.setDesc(get(AMDGPU::V_PK_MAX_NUM_BF16));
    MI.addOperand(MachineOperand::CreateImm(0)); // op_sel
    MI.addOperand(MachineOperand::CreateImm(0)); // neg_lo
    MI.addOperand(MachineOperand::CreateImm(0)); // neg_hi
    auto Op0 = getNamedOperand(MI, AMDGPU::OpName::src0_modifiers);
    Op0->setImm(Op0->getImm() | SISrcMods::OP_SEL_1);
    auto Op1 = getNamedOperand(MI, AMDGPU::OpName::src1_modifiers);
    Op1->setImm(Op1->getImm() | SISrcMods::OP_SEL_1);
    break;
  }

  case AMDGPU::GET_STACK_BASE:
    // The stack starts at offset 0 unless we need to reserve some space at the
    // bottom.
    if (ST.getFrameLowering()->mayReserveScratchForCWSR(*MBB.getParent())) {
      // When CWSR is used in dynamic VGPR mode, the trap handler needs to save
      // some of the VGPRs. The size of the required scratch space has already
      // been computed by prolog epilog insertion.
      const SIMachineFunctionInfo *MFI =
          MBB.getParent()->getInfo<SIMachineFunctionInfo>();
      unsigned VGPRSize = MFI->getScratchReservedForDynamicVGPRs();
      Register DestReg = MI.getOperand(0).getReg();
      BuildMI(MBB, MI, DL, get(AMDGPU::S_GETREG_B32), DestReg)
          .addImm(AMDGPU::Hwreg::HwregEncoding::encode(
              AMDGPU::Hwreg::ID_HW_ID2, AMDGPU::Hwreg::OFFSET_ME_ID, 2));
      // The MicroEngine ID is 0 for the graphics queue, and 1 or 2 for compute
      // (3 is unused, so we ignore it). Unfortunately, S_GETREG doesn't set
      // SCC, so we need to check for 0 manually.
      BuildMI(MBB, MI, DL, get(AMDGPU::S_CMP_LG_U32)).addImm(0).addReg(DestReg);
      // Change the implicif-def of SCC to an explicit use (but first remove
      // the dead flag if present).
      MI.getOperand(MI.getNumExplicitOperands()).setIsDead(false);
      MI.getOperand(MI.getNumExplicitOperands()).setIsUse();
      MI.setDesc(get(AMDGPU::S_CMOVK_I32));
      MI.addOperand(MachineOperand::CreateImm(VGPRSize));
    } else {
      MI.setDesc(get(AMDGPU::S_MOV_B32));
      MI.addOperand(MachineOperand::CreateImm(0));
      MI.removeOperand(
          MI.getNumExplicitOperands()); // Drop implicit def of SCC.
    }
    break;
  }

  return true;
}

void SIInstrInfo::reMaterialize(MachineBasicBlock &MBB,
                                MachineBasicBlock::iterator I, Register DestReg,
                                unsigned SubIdx, const MachineInstr &Orig,
                                LaneBitmask UsedLanes) const {

  // Try shrinking the instruction to remat only the part needed for current
  // context.
  // TODO: Handle more cases.
  unsigned Opcode = Orig.getOpcode();
  switch (Opcode) {
  case AMDGPU::S_MOV_B64:
  case AMDGPU::S_MOV_B64_IMM_PSEUDO: {
    if (SubIdx != 0)
      break;

    if (!Orig.getOperand(1).isImm())
      break;

    // Shrink S_MOV_B64 to S_MOV_B32 when UsedLanes indicates only a single
    // 32-bit lane of the 64-bit value is live at the rematerialization point.
    if (UsedLanes.all())
      break;

    // Determine which half of the 64-bit immediate corresponds to the use.
    unsigned OrigSubReg = Orig.getOperand(0).getSubReg();
    unsigned LoSubReg = RI.composeSubRegIndices(OrigSubReg, AMDGPU::sub0);
    unsigned HiSubReg = RI.composeSubRegIndices(OrigSubReg, AMDGPU::sub1);

    bool NeedLo = (UsedLanes & RI.getSubRegIndexLaneMask(LoSubReg)).any();
    bool NeedHi = (UsedLanes & RI.getSubRegIndexLaneMask(HiSubReg)).any();

    if (NeedLo && NeedHi)
      break;

    int64_t Imm64 = Orig.getOperand(1).getImm();
    int32_t Imm32 = NeedLo ? Lo_32(Imm64) : Hi_32(Imm64);

    unsigned UseSubReg = NeedLo ? LoSubReg : HiSubReg;

    // Emit S_MOV_B32 defining just the needed 32-bit subreg of DestReg.
    BuildMI(MBB, I, Orig.getDebugLoc(), get(AMDGPU::S_MOV_B32))
        .addReg(DestReg, RegState::Define | RegState::Undef, UseSubReg)
        .addImm(Imm32);
    return;
  }

  case AMDGPU::S_LOAD_DWORDX16_IMM:
  case AMDGPU::S_LOAD_DWORDX8_IMM: {
    if (SubIdx != 0)
      break;

    if (I == MBB.end())
      break;

    if (I->isBundled())
      break;

    // Look for a single use of the register that is also a subreg.
    Register RegToFind = Orig.getOperand(0).getReg();
    MachineOperand *UseMO = nullptr;
    for (auto &CandMO : I->operands()) {
      if (!CandMO.isReg() || CandMO.getReg() != RegToFind || CandMO.isDef())
        continue;
      if (UseMO) {
        UseMO = nullptr;
        break;
      }
      UseMO = &CandMO;
    }
    if (!UseMO || UseMO->getSubReg() == AMDGPU::NoSubRegister)
      break;

    unsigned Offset = RI.getSubRegIdxOffset(UseMO->getSubReg());
    unsigned SubregSize = RI.getSubRegIdxSize(UseMO->getSubReg());

    MachineFunction *MF = MBB.getParent();
    MachineRegisterInfo &MRI = MF->getRegInfo();
    assert(MRI.use_nodbg_empty(DestReg) && "DestReg should have no users yet.");

    unsigned NewOpcode = -1;
    if (SubregSize == 256)
      NewOpcode = AMDGPU::S_LOAD_DWORDX8_IMM;
    else if (SubregSize == 128)
      NewOpcode = AMDGPU::S_LOAD_DWORDX4_IMM;
    else
      break;

    const MCInstrDesc &TID = get(NewOpcode);
    const TargetRegisterClass *NewRC =
        RI.getAllocatableClass(getRegClass(TID, 0));
    MRI.setRegClass(DestReg, NewRC);

    UseMO->setReg(DestReg);
    UseMO->setSubReg(AMDGPU::NoSubRegister);

    // Use a smaller load with the desired size, possibly with updated offset.
    MachineInstr *MI = MF->CloneMachineInstr(&Orig);
    MI->setDesc(TID);
    MI->getOperand(0).setReg(DestReg);
    MI->getOperand(0).setSubReg(AMDGPU::NoSubRegister);
    if (Offset) {
      MachineOperand *OffsetMO = getNamedOperand(*MI, AMDGPU::OpName::offset);
      int64_t FinalOffset = OffsetMO->getImm() + Offset / 8;
      OffsetMO->setImm(FinalOffset);
    }
    SmallVector<MachineMemOperand *> NewMMOs;
    for (const MachineMemOperand *MemOp : Orig.memoperands())
      NewMMOs.push_back(MF->getMachineMemOperand(MemOp, MemOp->getPointerInfo(),
                                                 SubregSize / 8));
    MI->setMemRefs(*MF, NewMMOs);

    MBB.insert(I, MI);
    return;
  }

  default:
    break;
  }

  TargetInstrInfo::reMaterialize(MBB, I, DestReg, SubIdx, Orig, UsedLanes);
}

std::pair<MachineInstr*, MachineInstr*>
SIInstrInfo::expandMovDPP64(MachineInstr &MI) const {
  assert (MI.getOpcode() == AMDGPU::V_MOV_B64_DPP_PSEUDO);

  if (ST.hasVMovB64Inst() && ST.hasFeature(AMDGPU::FeatureDPALU_DPP) &&
      AMDGPU::isLegalDPALU_DPPControl(
          ST, getNamedOperand(MI, AMDGPU::OpName::dpp_ctrl)->getImm())) {
    MI.setDesc(get(AMDGPU::V_MOV_B64_dpp));
    return std::pair(&MI, nullptr);
  }

  MachineBasicBlock &MBB = *MI.getParent();
  DebugLoc DL = MBB.findDebugLoc(MI);
  MachineFunction *MF = MBB.getParent();
  MachineRegisterInfo &MRI = MF->getRegInfo();
  Register Dst = MI.getOperand(0).getReg();
  unsigned Part = 0;
  MachineInstr *Split[2];

  for (auto Sub : { AMDGPU::sub0, AMDGPU::sub1 }) {
    auto MovDPP = BuildMI(MBB, MI, DL, get(AMDGPU::V_MOV_B32_dpp));
    if (Dst.isPhysical()) {
      MovDPP.addDef(RI.getSubReg(Dst, Sub));
    } else {
      assert(MRI.isSSA());
      auto Tmp = MRI.createVirtualRegister(&AMDGPU::VGPR_32RegClass);
      MovDPP.addDef(Tmp);
    }

    for (unsigned I = 1; I <= 2; ++I) { // old and src operands.
      const MachineOperand &SrcOp = MI.getOperand(I);
      assert(!SrcOp.isFPImm());
      if (SrcOp.isImm()) {
        APInt Imm(64, SrcOp.getImm());
        Imm.ashrInPlace(Part * 32);
        MovDPP.addImm(Imm.getLoBits(32).getZExtValue());
      } else {
        assert(SrcOp.isReg());
        Register Src = SrcOp.getReg();
        if (Src.isPhysical())
          MovDPP.addReg(RI.getSubReg(Src, Sub));
        else
          MovDPP.addReg(Src, getUndefRegState(SrcOp.isUndef()), Sub);
      }
    }

    for (const MachineOperand &MO : llvm::drop_begin(MI.explicit_operands(), 3))
      MovDPP.addImm(MO.getImm());

    Split[Part] = MovDPP;
    ++Part;
  }

  if (Dst.isVirtual())
    BuildMI(MBB, MI, DL, get(AMDGPU::REG_SEQUENCE), Dst)
      .addReg(Split[0]->getOperand(0).getReg())
      .addImm(AMDGPU::sub0)
      .addReg(Split[1]->getOperand(0).getReg())
      .addImm(AMDGPU::sub1);

  MI.eraseFromParent();
  return std::pair(Split[0], Split[1]);
}

std::optional<DestSourcePair>
SIInstrInfo::isCopyInstrImpl(const MachineInstr &MI) const {
  if (MI.getOpcode() == AMDGPU::WWM_COPY)
    return DestSourcePair{MI.getOperand(0), MI.getOperand(1)};

  return std::nullopt;
}

bool SIInstrInfo::swapSourceModifiers(MachineInstr &MI, MachineOperand &Src0,
                                      AMDGPU::OpName Src0OpName,
                                      MachineOperand &Src1,
                                      AMDGPU::OpName Src1OpName) const {
  MachineOperand *Src0Mods = getNamedOperand(MI, Src0OpName);
  if (!Src0Mods)
    return false;

  MachineOperand *Src1Mods = getNamedOperand(MI, Src1OpName);
  assert(Src1Mods &&
         "All commutable instructions have both src0 and src1 modifiers");

  int Src0ModsVal = Src0Mods->getImm();
  int Src1ModsVal = Src1Mods->getImm();

  Src1Mods->setImm(Src0ModsVal);
  Src0Mods->setImm(Src1ModsVal);
  return true;
}

static MachineInstr *swapRegAndNonRegOperand(MachineInstr &MI,
                                             MachineOperand &RegOp,
                                             MachineOperand &NonRegOp) {
  Register Reg = RegOp.getReg();
  unsigned SubReg = RegOp.getSubReg();
  bool IsKill = RegOp.isKill();
  bool IsDead = RegOp.isDead();
  bool IsUndef = RegOp.isUndef();
  bool IsDebug = RegOp.isDebug();

  if (NonRegOp.isImm())
    RegOp.ChangeToImmediate(NonRegOp.getImm());
  else if (NonRegOp.isFI())
    RegOp.ChangeToFrameIndex(NonRegOp.getIndex());
  else if (NonRegOp.isGlobal()) {
    RegOp.ChangeToGA(NonRegOp.getGlobal(), NonRegOp.getOffset(),
                     NonRegOp.getTargetFlags());
  } else
    return nullptr;

  // Make sure we don't reinterpret a subreg index in the target flags.
  RegOp.setTargetFlags(NonRegOp.getTargetFlags());

  NonRegOp.ChangeToRegister(Reg, false, false, IsKill, IsDead, IsUndef, IsDebug);
  NonRegOp.setSubReg(SubReg);

  return &MI;
}

static MachineInstr *swapImmOperands(MachineInstr &MI,
                                     MachineOperand &NonRegOp1,
                                     MachineOperand &NonRegOp2) {
  unsigned TargetFlags = NonRegOp1.getTargetFlags();
  int64_t NonRegVal = NonRegOp1.getImm();

  NonRegOp1.setImm(NonRegOp2.getImm());
  NonRegOp2.setImm(NonRegVal);
  NonRegOp1.setTargetFlags(NonRegOp2.getTargetFlags());
  NonRegOp2.setTargetFlags(TargetFlags);
  return &MI;
}

bool SIInstrInfo::isLegalToSwap(const MachineInstr &MI, unsigned OpIdx0,
                                unsigned OpIdx1) const {
  const MCInstrDesc &InstDesc = MI.getDesc();
  const MCOperandInfo &OpInfo0 = InstDesc.operands()[OpIdx0];
  const MCOperandInfo &OpInfo1 = InstDesc.operands()[OpIdx1];

  unsigned Opc = MI.getOpcode();
  int Src0Idx = AMDGPU::getNamedOperandIdx(Opc, AMDGPU::OpName::src0);

  const MachineOperand &MO0 = MI.getOperand(OpIdx0);
  const MachineOperand &MO1 = MI.getOperand(OpIdx1);

  // Swap doesn't breach constant bus or literal limits
  // It may move literal to position other than src0, this is not allowed
  // pre-gfx10 However, most test cases need literals in Src0 for VOP
  // FIXME: After gfx9, literal can be in place other than Src0
  if (isVALU(MI, /*AllowLDSDMA=*/true)) {
    if ((int)OpIdx0 == Src0Idx && !MO0.isReg() &&
        !isInlineConstant(MO0, OpInfo1))
      return false;
    if ((int)OpIdx1 == Src0Idx && !MO1.isReg() &&
        !isInlineConstant(MO1, OpInfo0))
      return false;
  }

  if ((int)OpIdx1 != Src0Idx && MO0.isReg()) {
    if (OpInfo1.RegClass == -1)
      return OpInfo1.OperandType == MCOI::OPERAND_UNKNOWN;
    return isLegalRegOperand(MI, OpIdx1, MO0) &&
           (!MO1.isReg() || isLegalRegOperand(MI, OpIdx0, MO1));
  }
  if ((int)OpIdx0 != Src0Idx && MO1.isReg()) {
    if (OpInfo0.RegClass == -1)
      return OpInfo0.OperandType == MCOI::OPERAND_UNKNOWN;
    return (!MO0.isReg() || isLegalRegOperand(MI, OpIdx1, MO0)) &&
           isLegalRegOperand(MI, OpIdx0, MO1);
  }

  // No need to check 64-bit literals since swapping does not bring new
  // 64-bit literals into current instruction to fold to 32-bit

  return isImmOperandLegal(MI, OpIdx1, MO0);
}

MachineInstr *SIInstrInfo::commuteInstructionImpl(MachineInstr &MI, bool NewMI,
                                                  unsigned Src0Idx,
                                                  unsigned Src1Idx) const {
  assert(!NewMI && "this should never be used");

  unsigned Opc = MI.getOpcode();
  int CommutedOpcode = commuteOpcode(Opc);
  if (CommutedOpcode == -1)
    return nullptr;

  if (Src0Idx > Src1Idx)
    std::swap(Src0Idx, Src1Idx);

  assert(AMDGPU::getNamedOperandIdx(Opc, AMDGPU::OpName::src0) ==
           static_cast<int>(Src0Idx) &&
         AMDGPU::getNamedOperandIdx(Opc, AMDGPU::OpName::src1) ==
           static_cast<int>(Src1Idx) &&
         "inconsistency with findCommutedOpIndices");

  if (!isLegalToSwap(MI, Src0Idx, Src1Idx))
    return nullptr;

  MachineInstr *CommutedMI = nullptr;
  MachineOperand &Src0 = MI.getOperand(Src0Idx);
  MachineOperand &Src1 = MI.getOperand(Src1Idx);
  if (Src0.isReg() && Src1.isReg()) {
    // Be sure to copy the source modifiers to the right place.
    CommutedMI =
        TargetInstrInfo::commuteInstructionImpl(MI, NewMI, Src0Idx, Src1Idx);
  } else if (Src0.isReg() && !Src1.isReg()) {
    CommutedMI = swapRegAndNonRegOperand(MI, Src0, Src1);
  } else if (!Src0.isReg() && Src1.isReg()) {
    CommutedMI = swapRegAndNonRegOperand(MI, Src1, Src0);
  } else if (Src0.isImm() && Src1.isImm()) {
    CommutedMI = swapImmOperands(MI, Src0, Src1);
  } else {
    // FIXME: Found two non registers to commute. This does happen.
    return nullptr;
  }

  if (CommutedMI) {
    swapSourceModifiers(MI, Src0, AMDGPU::OpName::src0_modifiers,
                        Src1, AMDGPU::OpName::src1_modifiers);

    swapSourceModifiers(MI, Src0, AMDGPU::OpName::src0_sel, Src1,
                        AMDGPU::OpName::src1_sel);

    CommutedMI->setDesc(get(CommutedOpcode));
  }

  return CommutedMI;
}

// This needs to be implemented because the source modifiers may be inserted
// between the true commutable operands, and the base
// TargetInstrInfo::commuteInstruction uses it.
bool SIInstrInfo::findCommutedOpIndices(const MachineInstr &MI,
                                        unsigned &SrcOpIdx0,
                                        unsigned &SrcOpIdx1) const {
  return findCommutedOpIndices(MI.getDesc(), SrcOpIdx0, SrcOpIdx1);
}

bool SIInstrInfo::findCommutedOpIndices(const MCInstrDesc &Desc,
                                        unsigned &SrcOpIdx0,
                                        unsigned &SrcOpIdx1) const {
  if (!Desc.isCommutable())
    return false;

  unsigned Opc = Desc.getOpcode();
  int Src0Idx = AMDGPU::getNamedOperandIdx(Opc, AMDGPU::OpName::src0);
  if (Src0Idx == -1)
    return false;

  int Src1Idx = AMDGPU::getNamedOperandIdx(Opc, AMDGPU::OpName::src1);
  if (Src1Idx == -1)
    return false;

  return fixCommutedOpIndices(SrcOpIdx0, SrcOpIdx1, Src0Idx, Src1Idx);
}

bool SIInstrInfo::isBranchOffsetInRange(unsigned BranchOp,
                                        int64_t BrOffset) const {
  // BranchRelaxation should never have to check s_setpc_b64 or s_add_pc_i64
  // because its dest block is unanalyzable.
  assert(isSOPP(BranchOp) || isSOPK(BranchOp));

  // Convert to dwords.
  BrOffset /= 4;

  // The branch instructions do PC += signext(SIMM16 * 4) + 4, so the offset is
  // from the next instruction.
  BrOffset -= 1;

  return isIntN(BranchOffsetBits, BrOffset);
}

MachineBasicBlock *
SIInstrInfo::getBranchDestBlock(const MachineInstr &MI) const {
  return MI.getOperand(0).getMBB();
}

bool SIInstrInfo::hasDivergentBranch(const MachineBasicBlock *MBB) const {
  for (const MachineInstr &MI : MBB->terminators()) {
    if (MI.getOpcode() == AMDGPU::SI_IF || MI.getOpcode() == AMDGPU::SI_ELSE ||
        MI.getOpcode() == AMDGPU::SI_LOOP)
      return true;
  }
  return false;
}

void SIInstrInfo::insertIndirectBranch(MachineBasicBlock &MBB,
                                       MachineBasicBlock &DestBB,
                                       MachineBasicBlock &RestoreBB,
                                       const DebugLoc &DL, int64_t BrOffset,
                                       RegScavenger *RS) const {
  assert(MBB.empty() &&
         "new block should be inserted for expanding unconditional branch");
  assert(MBB.pred_size() == 1);
  assert(RestoreBB.empty() &&
         "restore block should be inserted for restoring clobbered registers");

  MachineFunction *MF = MBB.getParent();
  MachineRegisterInfo &MRI = MF->getRegInfo();
  const SIMachineFunctionInfo *MFI = MF->getInfo<SIMachineFunctionInfo>();
  auto I = MBB.end();
  auto &MCCtx = MF->getContext();

  if (ST.useAddPC64Inst()) {
    MCSymbol *Offset =
        MCCtx.createTempSymbol("offset", /*AlwaysAddSuffix=*/true);
    auto AddPC = BuildMI(MBB, I, DL, get(AMDGPU::S_ADD_PC_I64))
                     .addSym(Offset, MO_FAR_BRANCH_OFFSET);
    MCSymbol *PostAddPCLabel =
        MCCtx.createTempSymbol("post_addpc", /*AlwaysAddSuffix=*/true);
    AddPC->setPostInstrSymbol(*MF, PostAddPCLabel);
    auto *OffsetExpr = MCBinaryExpr::createSub(
        MCSymbolRefExpr::create(DestBB.getSymbol(), MCCtx),
        MCSymbolRefExpr::create(PostAddPCLabel, MCCtx), MCCtx);
    Offset->setVariableValue(OffsetExpr);
    return;
  }

  assert(RS && "RegScavenger required for long branching");

  // FIXME: Virtual register workaround for RegScavenger not working with empty
  // blocks.
  Register PCReg = MRI.createVirtualRegister(&AMDGPU::SReg_64RegClass);

  // Note: as this is used after hazard recognizer we need to apply some hazard
  // workarounds directly.
  const bool FlushSGPRWrites = (ST.isWave64() && ST.hasVALUMaskWriteHazard()) ||
                               ST.hasVALUReadSGPRHazard();
  auto ApplyHazardWorkarounds = [this, &MBB, &I, &DL, FlushSGPRWrites]() {
    if (FlushSGPRWrites)
      BuildMI(MBB, I, DL, get(AMDGPU::S_WAITCNT_DEPCTR))
          .addImm(AMDGPU::DepCtr::encodeFieldSaSdst(0, ST));
  };

  // We need to compute the offset relative to the instruction immediately after
  // s_getpc_b64. Insert pc arithmetic code before last terminator.
  MachineInstr *GetPC = BuildMI(MBB, I, DL, get(AMDGPU::S_GETPC_B64), PCReg);
  ApplyHazardWorkarounds();

  MCSymbol *PostGetPCLabel =
      MCCtx.createTempSymbol("post_getpc", /*AlwaysAddSuffix=*/true);
  GetPC->setPostInstrSymbol(*MF, PostGetPCLabel);

  MCSymbol *OffsetLo =
      MCCtx.createTempSymbol("offset_lo", /*AlwaysAddSuffix=*/true);
  MCSymbol *OffsetHi =
      MCCtx.createTempSymbol("offset_hi", /*AlwaysAddSuffix=*/true);
  BuildMI(MBB, I, DL, get(AMDGPU::S_ADD_U32))
      .addReg(PCReg, RegState::Define, AMDGPU::sub0)
      .addReg(PCReg, {}, AMDGPU::sub0)
      .addSym(OffsetLo, MO_FAR_BRANCH_OFFSET);
  BuildMI(MBB, I, DL, get(AMDGPU::S_ADDC_U32))
      .addReg(PCReg, RegState::Define, AMDGPU::sub1)
      .addReg(PCReg, {}, AMDGPU::sub1)
      .addSym(OffsetHi, MO_FAR_BRANCH_OFFSET);
  ApplyHazardWorkarounds();

  // Insert the indirect branch after the other terminator.
  BuildMI(&MBB, DL, get(AMDGPU::S_SETPC_B64))
    .addReg(PCReg);

  // If a spill is needed for the pc register pair, we need to insert a spill
  // restore block right before the destination block, and insert a short branch
  // into the old destination block's fallthrough predecessor.
  // e.g.:
  //
  // s_cbranch_scc0 skip_long_branch:
  //
  // long_branch_bb:
  //   spill s[8:9]
  //   s_getpc_b64 s[8:9]
  //   s_add_u32 s8, s8, restore_bb
  //   s_addc_u32 s9, s9, 0
  //   s_setpc_b64 s[8:9]
  //
  // skip_long_branch:
  //   foo;
  //
  // .....
  //
  // dest_bb_fallthrough_predecessor:
  // bar;
  // s_branch dest_bb
  //
  // restore_bb:
  //  restore s[8:9]
  //  fallthrough dest_bb
  ///
  // dest_bb:
  //   buzz;

  Register LongBranchReservedReg = MFI->getLongBranchReservedReg();
  Register Scav;

  // If we've previously reserved a register for long branches
  // avoid running the scavenger and just use those registers
  if (LongBranchReservedReg) {
    RS->enterBasicBlock(MBB);
    Scav = LongBranchReservedReg;
  } else {
    RS->enterBasicBlockEnd(MBB);
    Scav = RS->scavengeRegisterBackwards(
        AMDGPU::SReg_64RegClass, MachineBasicBlock::iterator(GetPC),
        /* RestoreAfter */ false, 0, /* AllowSpill */ false);
  }
  if (Scav) {
    RS->setRegUsed(Scav);
    MRI.replaceRegWith(PCReg, Scav);
    MRI.clearVirtRegs();
  } else {
    // As SGPR needs VGPR to be spilled, we reuse the slot of temporary VGPR for
    // SGPR spill.
    const GCNSubtarget &ST = MF->getSubtarget<GCNSubtarget>();
    const SIRegisterInfo *TRI = ST.getRegisterInfo();
    TRI->spillEmergencySGPR(GetPC, RestoreBB, AMDGPU::SGPR0_SGPR1, RS);
    MRI.replaceRegWith(PCReg, AMDGPU::SGPR0_SGPR1);
    MRI.clearVirtRegs();
  }

  MCSymbol *DestLabel = Scav ? DestBB.getSymbol() : RestoreBB.getSymbol();
  // Now, the distance could be defined.
  auto *Offset = MCBinaryExpr::createSub(
      MCSymbolRefExpr::create(DestLabel, MCCtx),
      MCSymbolRefExpr::create(PostGetPCLabel, MCCtx), MCCtx);
  // Add offset assignments.
  auto *Mask = MCConstantExpr::create(0xFFFFFFFFULL, MCCtx);
  OffsetLo->setVariableValue(MCBinaryExpr::createAnd(Offset, Mask, MCCtx));
  auto *ShAmt = MCConstantExpr::create(32, MCCtx);
  OffsetHi->setVariableValue(MCBinaryExpr::createAShr(Offset, ShAmt, MCCtx));
}

unsigned SIInstrInfo::getBranchOpcode(SIInstrInfo::BranchPredicate Cond) {
  switch (Cond) {
  case SIInstrInfo::SCC_TRUE:
    return AMDGPU::S_CBRANCH_SCC1;
  case SIInstrInfo::SCC_FALSE:
    return AMDGPU::S_CBRANCH_SCC0;
  case SIInstrInfo::VCCNZ:
    return AMDGPU::S_CBRANCH_VCCNZ;
  case SIInstrInfo::VCCZ:
    return AMDGPU::S_CBRANCH_VCCZ;
  case SIInstrInfo::EXECNZ:
    return AMDGPU::S_CBRANCH_EXECNZ;
  case SIInstrInfo::EXECZ:
    return AMDGPU::S_CBRANCH_EXECZ;
  default:
    llvm_unreachable("invalid branch predicate");
  }
}

SIInstrInfo::BranchPredicate SIInstrInfo::getBranchPredicate(unsigned Opcode) {
  switch (Opcode) {
  case AMDGPU::S_CBRANCH_SCC0:
    return SCC_FALSE;
  case AMDGPU::S_CBRANCH_SCC1:
    return SCC_TRUE;
  case AMDGPU::S_CBRANCH_VCCNZ:
    return VCCNZ;
  case AMDGPU::S_CBRANCH_VCCZ:
    return VCCZ;
  case AMDGPU::S_CBRANCH_EXECNZ:
    return EXECNZ;
  case AMDGPU::S_CBRANCH_EXECZ:
    return EXECZ;
  default:
    return INVALID_BR;
  }
}

bool SIInstrInfo::analyzeBranchImpl(MachineBasicBlock &MBB,
                                    MachineBasicBlock::iterator I,
                                    MachineBasicBlock *&TBB,
                                    MachineBasicBlock *&FBB,
                                    SmallVectorImpl<MachineOperand> &Cond,
                                    bool AllowModify) const {
  if (I->getOpcode() == AMDGPU::S_BRANCH) {
    // Unconditional Branch
    TBB = I->getOperand(0).getMBB();
    return false;
  }

  BranchPredicate Pred = getBranchPredicate(I->getOpcode());
  if (Pred == INVALID_BR)
    return true;

  MachineBasicBlock *CondBB = I->getOperand(0).getMBB();
  Cond.push_back(MachineOperand::CreateImm(Pred));
  Cond.push_back(I->getOperand(1)); // Save the branch register.

  ++I;

  if (I == MBB.end()) {
    // Conditional branch followed by fall-through.
    TBB = CondBB;
    return false;
  }

  if (I->getOpcode() == AMDGPU::S_BRANCH) {
    TBB = CondBB;
    FBB = I->getOperand(0).getMBB();
    return false;
  }

  return true;
}

bool SIInstrInfo::analyzeBranch(MachineBasicBlock &MBB, MachineBasicBlock *&TBB,
                                MachineBasicBlock *&FBB,
                                SmallVectorImpl<MachineOperand> &Cond,
                                bool AllowModify) const {
  MachineBasicBlock::iterator I = MBB.getFirstTerminator();
  auto E = MBB.end();
  if (I == E)
    return false;

  // Skip over the instructions that are artificially terminators for special
  // exec management.
  while (I != E && !I->isBranch() && !I->isReturn()) {
    switch (I->getOpcode()) {
    case AMDGPU::S_MOV_B64_term:
    case AMDGPU::S_XOR_B64_term:
    case AMDGPU::S_OR_B64_term:
    case AMDGPU::S_ANDN2_B64_term:
    case AMDGPU::S_AND_B64_term:
    case AMDGPU::S_AND_SAVEEXEC_B64_term:
    case AMDGPU::S_MOV_B32_term:
    case AMDGPU::S_XOR_B32_term:
    case AMDGPU::S_OR_B32_term:
    case AMDGPU::S_ANDN2_B32_term:
    case AMDGPU::S_AND_B32_term:
    case AMDGPU::S_AND_SAVEEXEC_B32_term:
    case AMDGPU::V_CMPX_EQ_U32_nosdst_e32_term:
    case AMDGPU::V_CMPX_EQ_U64_nosdst_e32_term:
      break;
    case AMDGPU::SI_IF:
    case AMDGPU::SI_ELSE:
    case AMDGPU::SI_KILL_I1_TERMINATOR:
    case AMDGPU::SI_KILL_F32_COND_IMM_TERMINATOR:
      // FIXME: It's messy that these need to be considered here at all.
      return true;
    default:
      llvm_unreachable("unexpected non-branch terminator inst");
    }

    ++I;
  }

  if (I == E)
    return false;

  return analyzeBranchImpl(MBB, I, TBB, FBB, Cond, AllowModify);
}

unsigned SIInstrInfo::removeBranch(MachineBasicBlock &MBB,
                                   int *BytesRemoved) const {
  unsigned Count = 0;
  unsigned RemovedSize = 0;
  for (MachineInstr &MI : llvm::make_early_inc_range(MBB.terminators())) {
    // Skip over artificial terminators when removing instructions.
    if (MI.isBranch() || MI.isReturn()) {
      RemovedSize += getInstSizeInBytes(MI);
      MI.eraseFromParent();
      ++Count;
    }
  }

  if (BytesRemoved)
    *BytesRemoved = RemovedSize;

  return Count;
}

// Copy the flags onto the implicit condition register operand.
static void preserveCondRegFlags(MachineOperand &CondReg,
                                 const MachineOperand &OrigCond) {
  CondReg.setIsUndef(OrigCond.isUndef());
  CondReg.setIsKill(OrigCond.isKill());
}

unsigned SIInstrInfo::insertBranch(MachineBasicBlock &MBB,
                                   MachineBasicBlock *TBB,
                                   MachineBasicBlock *FBB,
                                   ArrayRef<MachineOperand> Cond,
                                   const DebugLoc &DL,
                                   int *BytesAdded) const {
  if (!FBB && Cond.empty()) {
    BuildMI(&MBB, DL, get(AMDGPU::S_BRANCH))
      .addMBB(TBB);
    if (BytesAdded)
      *BytesAdded = ST.hasOffset3fBug() ? 8 : 4;
    return 1;
  }

  assert(TBB && Cond[0].isImm());

  unsigned Opcode
    = getBranchOpcode(static_cast<BranchPredicate>(Cond[0].getImm()));

  if (!FBB) {
    MachineInstr *CondBr =
      BuildMI(&MBB, DL, get(Opcode))
      .addMBB(TBB);

    // Copy the flags onto the implicit condition register operand.
    preserveCondRegFlags(CondBr->getOperand(1), Cond[1]);
    fixImplicitOperands(*CondBr);

    if (BytesAdded)
      *BytesAdded = ST.hasOffset3fBug() ? 8 : 4;
    return 1;
  }

  assert(TBB && FBB);

  MachineInstr *CondBr =
    BuildMI(&MBB, DL, get(Opcode))
    .addMBB(TBB);
  fixImplicitOperands(*CondBr);
  BuildMI(&MBB, DL, get(AMDGPU::S_BRANCH))
    .addMBB(FBB);

  MachineOperand &CondReg = CondBr->getOperand(1);
  CondReg.setIsUndef(Cond[1].isUndef());
  CondReg.setIsKill(Cond[1].isKill());

  if (BytesAdded)
    *BytesAdded = ST.hasOffset3fBug() ? 16 : 8;

  return 2;
}

bool SIInstrInfo::reverseBranchCondition(
  SmallVectorImpl<MachineOperand> &Cond) const {
  if (Cond.size() != 2) {
    return true;
  }

  if (Cond[0].isImm()) {
    Cond[0].setImm(-Cond[0].getImm());
    return false;
  }

  return true;
}

bool SIInstrInfo::canInsertSelect(const MachineBasicBlock &MBB,
                                  ArrayRef<MachineOperand> Cond,
                                  Register DstReg, Register TrueReg,
                                  Register FalseReg, int &CondCycles,
                                  int &TrueCycles, int &FalseCycles) const {
  switch (Cond[0].getImm()) {
  case VCCNZ:
  case VCCZ: {
    const MachineRegisterInfo &MRI = MBB.getParent()->getRegInfo();
    const TargetRegisterClass *RC = MRI.getRegClass(TrueReg);
    if (MRI.getRegClass(FalseReg) != RC)
      return false;

    int NumInsts = AMDGPU::getRegBitWidth(*RC) / 32;
    CondCycles = TrueCycles = FalseCycles = NumInsts; // ???

    // Limit to equal cost for branch vs. N v_cndmask_b32s.
    return RI.hasVGPRs(RC) && NumInsts <= 6;
  }
  case SCC_TRUE:
  case SCC_FALSE: {
    // FIXME: We could insert for VGPRs if we could replace the original compare
    // with a vector one.
    const MachineRegisterInfo &MRI = MBB.getParent()->getRegInfo();
    const TargetRegisterClass *RC = MRI.getRegClass(TrueReg);
    if (MRI.getRegClass(FalseReg) != RC)
      return false;

    int NumInsts = AMDGPU::getRegBitWidth(*RC) / 32;

    // Multiples of 8 can do s_cselect_b64
    if (NumInsts % 2 == 0)
      NumInsts /= 2;

    CondCycles = TrueCycles = FalseCycles = NumInsts; // ???
    return RI.isSGPRClass(RC);
  }
  default:
    return false;
  }
}

void SIInstrInfo::insertSelect(MachineBasicBlock &MBB,
                               MachineBasicBlock::iterator I, const DebugLoc &DL,
                               Register DstReg, ArrayRef<MachineOperand> Cond,
                               Register TrueReg, Register FalseReg) const {
  BranchPredicate Pred = static_cast<BranchPredicate>(Cond[0].getImm());
  if (Pred == VCCZ || Pred == SCC_FALSE) {
    Pred = static_cast<BranchPredicate>(-Pred);
    std::swap(TrueReg, FalseReg);
  }

  MachineRegisterInfo &MRI = MBB.getParent()->getRegInfo();
  const TargetRegisterClass *DstRC = MRI.getRegClass(DstReg);
  unsigned DstSize = RI.getRegSizeInBits(*DstRC);

  if (DstSize == 32) {
    MachineInstr *Select;
    if (Pred == SCC_TRUE) {
      Select = BuildMI(MBB, I, DL, get(AMDGPU::S_CSELECT_B32), DstReg)
        .addReg(TrueReg)
        .addReg(FalseReg);
    } else {
      // Instruction's operands are backwards from what is expected.
      Select = BuildMI(MBB, I, DL, get(AMDGPU::V_CNDMASK_B32_e32), DstReg)
        .addReg(FalseReg)
        .addReg(TrueReg);
    }

    preserveCondRegFlags(Select->getOperand(3), Cond[1]);
    return;
  }

  if (DstSize == 64 && Pred == SCC_TRUE) {
    MachineInstr *Select =
      BuildMI(MBB, I, DL, get(AMDGPU::S_CSELECT_B64), DstReg)
      .addReg(TrueReg)
      .addReg(FalseReg);

    preserveCondRegFlags(Select->getOperand(3), Cond[1]);
    return;
  }

  static const int16_t Sub0_15[] = {
    AMDGPU::sub0, AMDGPU::sub1, AMDGPU::sub2, AMDGPU::sub3,
    AMDGPU::sub4, AMDGPU::sub5, AMDGPU::sub6, AMDGPU::sub7,
    AMDGPU::sub8, AMDGPU::sub9, AMDGPU::sub10, AMDGPU::sub11,
    AMDGPU::sub12, AMDGPU::sub13, AMDGPU::sub14, AMDGPU::sub15,
  };

  static const int16_t Sub0_15_64[] = {
    AMDGPU::sub0_sub1, AMDGPU::sub2_sub3,
    AMDGPU::sub4_sub5, AMDGPU::sub6_sub7,
    AMDGPU::sub8_sub9, AMDGPU::sub10_sub11,
    AMDGPU::sub12_sub13, AMDGPU::sub14_sub15,
  };

  unsigned SelOp = AMDGPU::V_CNDMASK_B32_e32;
  const TargetRegisterClass *EltRC = &AMDGPU::VGPR_32RegClass;
  const int16_t *SubIndices = Sub0_15;
  int NElts = DstSize / 32;

  // 64-bit select is only available for SALU.
  // TODO: Split 96-bit into 64-bit and 32-bit, not 3x 32-bit.
  if (Pred == SCC_TRUE) {
    if (NElts % 2) {
      SelOp = AMDGPU::S_CSELECT_B32;
      EltRC = &AMDGPU::SGPR_32RegClass;
    } else {
      SelOp = AMDGPU::S_CSELECT_B64;
      EltRC = &AMDGPU::SGPR_64RegClass;
      SubIndices = Sub0_15_64;
      NElts /= 2;
    }
  }

  MachineInstrBuilder MIB = BuildMI(
    MBB, I, DL, get(AMDGPU::REG_SEQUENCE), DstReg);

  I = MIB->getIterator();

  SmallVector<Register, 8> Regs;
  for (int Idx = 0; Idx != NElts; ++Idx) {
    Register DstElt = MRI.createVirtualRegister(EltRC);
    Regs.push_back(DstElt);

    unsigned SubIdx = SubIndices[Idx];

    MachineInstr *Select;
    if (SelOp == AMDGPU::V_CNDMASK_B32_e32) {
      Select = BuildMI(MBB, I, DL, get(SelOp), DstElt)
                   .addReg(FalseReg, {}, SubIdx)
                   .addReg(TrueReg, {}, SubIdx);
    } else {
      Select = BuildMI(MBB, I, DL, get(SelOp), DstElt)
                   .addReg(TrueReg, {}, SubIdx)
                   .addReg(FalseReg, {}, SubIdx);
    }

    preserveCondRegFlags(Select->getOperand(3), Cond[1]);
    fixImplicitOperands(*Select);

    MIB.addReg(DstElt)
       .addImm(SubIdx);
  }
}

bool SIInstrInfo::isXcntDrain(const MachineInstr &MI) {

  if (MI.isBranch() || MI.isCall() || MI.isReturn() || MI.isIndirectBranch())
    return true;

  switch (MI.getOpcode()) {
  case AMDGPU::S_ENDPGM:
  case AMDGPU::S_ENDPGM_SAVED:
  case AMDGPU::S_TRAP:
  case AMDGPU::S_GETREG_B32:
  case AMDGPU::S_SETREG_B32:
  case AMDGPU::S_SETREG_B32_mode:
  case AMDGPU::S_SETREG_IMM32_B32:
  case AMDGPU::S_SETREG_IMM32_B32_mode:
  case AMDGPU::S_SENDMSG:
  case AMDGPU::S_SENDMSGHALT:
  case AMDGPU::S_SENDMSG_RTN_B32:
  case AMDGPU::S_SENDMSG_RTN_B64:
  case AMDGPU::S_BARRIER_WAIT:
  case AMDGPU::S_BARRIER_SIGNAL_M0:
  case AMDGPU::S_BARRIER_SIGNAL_IMM:
  case AMDGPU::S_BARRIER_SIGNAL_ISFIRST_M0:
  case AMDGPU::S_BARRIER_SIGNAL_ISFIRST_IMM:
    return true;
  default:
    return false;
  }
}

bool SIInstrInfo::isFoldableCopy(const MachineInstr &MI) {
  switch (MI.getOpcode()) {
  case AMDGPU::V_MOV_B16_t16_e32:
  case AMDGPU::V_MOV_B16_t16_e64:
  case AMDGPU::V_MOV_B32_e32:
  case AMDGPU::V_MOV_B32_e64:
  case AMDGPU::V_MOV_B64_PSEUDO:
  case AMDGPU::V_MOV_B64_e32:
  case AMDGPU::V_MOV_B64_e64:
  case AMDGPU::S_MOV_B32:
  case AMDGPU::S_MOV_B64:
  case AMDGPU::S_MOV_B64_IMM_PSEUDO:
  case AMDGPU::COPY:
  case AMDGPU::WWM_COPY:
  case AMDGPU::V_ACCVGPR_WRITE_B32_e64:
  case AMDGPU::V_ACCVGPR_READ_B32_e64:
  case AMDGPU::V_ACCVGPR_MOV_B32:
  case AMDGPU::AV_MOV_B32_IMM_PSEUDO:
  case AMDGPU::AV_MOV_B64_IMM_PSEUDO:
    return true;
  default:
    return false;
  }
}

unsigned SIInstrInfo::getFoldableCopySrcIdx(const MachineInstr &MI) {
  switch (MI.getOpcode()) {
  case AMDGPU::V_MOV_B16_t16_e32:
  case AMDGPU::V_MOV_B16_t16_e64:
    return 2;
  case AMDGPU::V_MOV_B32_e32:
  case AMDGPU::V_MOV_B32_e64:
  case AMDGPU::V_MOV_B64_PSEUDO:
  case AMDGPU::V_MOV_B64_e32:
  case AMDGPU::V_MOV_B64_e64:
  case AMDGPU::S_MOV_B32:
  case AMDGPU::S_MOV_B64:
  case AMDGPU::S_MOV_B64_IMM_PSEUDO:
  case AMDGPU::COPY:
  case AMDGPU::WWM_COPY:
  case AMDGPU::V_ACCVGPR_WRITE_B32_e64:
  case AMDGPU::V_ACCVGPR_READ_B32_e64:
  case AMDGPU::V_ACCVGPR_MOV_B32:
  case AMDGPU::AV_MOV_B32_IMM_PSEUDO:
  case AMDGPU::AV_MOV_B64_IMM_PSEUDO:
    return 1;
  default:
    llvm_unreachable("MI is not a foldable copy");
  }
}

static constexpr AMDGPU::OpName ModifierOpNames[] = {
    AMDGPU::OpName::src0_modifiers, AMDGPU::OpName::src1_modifiers,
    AMDGPU::OpName::src2_modifiers, AMDGPU::OpName::clamp,
    AMDGPU::OpName::omod,           AMDGPU::OpName::op_sel};

void SIInstrInfo::removeModOperands(MachineInstr &MI) const {
  unsigned Opc = MI.getOpcode();
  for (AMDGPU::OpName Name : reverse(ModifierOpNames)) {
    int Idx = AMDGPU::getNamedOperandIdx(Opc, Name);
    if (Idx >= 0)
      MI.removeOperand(Idx);
  }
}

void SIInstrInfo::mutateAndCleanupImplicit(MachineInstr &MI,
                                           const MCInstrDesc &NewDesc) const {
  MI.setDesc(NewDesc);

  // Remove any leftover implicit operands from mutating the instruction. e.g.
  // if we replace an s_and_b32 with a copy, we don't need the implicit scc def
  // anymore.
  const MCInstrDesc &Desc = MI.getDesc();
  unsigned NumOps = Desc.getNumOperands() + Desc.implicit_uses().size() +
                    Desc.implicit_defs().size();

  for (unsigned I = MI.getNumOperands() - 1; I >= NumOps; --I)
    MI.removeOperand(I);
}

std::optional<int64_t> SIInstrInfo::extractSubregFromImm(int64_t Imm,
                                                         unsigned SubRegIndex) {
  switch (SubRegIndex) {
  case AMDGPU::NoSubRegister:
    return Imm;
  case AMDGPU::sub0:
    return SignExtend64<32>(Imm);
  case AMDGPU::sub1:
    return SignExtend64<32>(Imm >> 32);
  case AMDGPU::lo16:
    return SignExtend64<16>(Imm);
  case AMDGPU::hi16:
    return SignExtend64<16>(Imm >> 16);
  case AMDGPU::sub1_lo16:
    return SignExtend64<16>(Imm >> 32);
  case AMDGPU::sub1_hi16:
    return SignExtend64<16>(Imm >> 48);
  default:
    return std::nullopt;
  }

  llvm_unreachable("covered subregister switch");
}

static unsigned getNewFMAAKInst(const GCNSubtarget &ST, unsigned Opc) {
  switch (Opc) {
  case AMDGPU::V_MAC_F16_e32:
  case AMDGPU::V_MAC_F16_e64:
  case AMDGPU::V_MAD_F16_e64:
    return AMDGPU::V_MADAK_F16;
  case AMDGPU::V_MAC_F32_e32:
  case AMDGPU::V_MAC_F32_e64:
  case AMDGPU::V_MAD_F32_e64:
    return AMDGPU::V_MADAK_F32;
  case AMDGPU::V_FMAC_F32_e32:
  case AMDGPU::V_FMAC_F32_e64:
  case AMDGPU::V_FMA_F32_e64:
    return AMDGPU::V_FMAAK_F32;
  case AMDGPU::V_FMAC_F16_e32:
  case AMDGPU::V_FMAC_F16_e64:
  case AMDGPU::V_FMAC_F16_t16_e64:
  case AMDGPU::V_FMAC_F16_fake16_e64:
  case AMDGPU::V_FMAC_F16_t16_e32:
  case AMDGPU::V_FMAC_F16_fake16_e32:
  case AMDGPU::V_FMA_F16_e64:
    return ST.hasTrue16BitInsts() ? ST.useRealTrue16Insts()
                                        ? AMDGPU::V_FMAAK_F16_t16
                                        : AMDGPU::V_FMAAK_F16_fake16
                                  : AMDGPU::V_FMAAK_F16;
  case AMDGPU::V_FMAC_F64_e32:
  case AMDGPU::V_FMAC_F64_e64:
  case AMDGPU::V_FMA_F64_e64:
    return AMDGPU::V_FMAAK_F64;
  default:
    llvm_unreachable("invalid instruction");
  }
}

static unsigned getNewFMAMKInst(const GCNSubtarget &ST, unsigned Opc) {
  switch (Opc) {
  case AMDGPU::V_MAC_F16_e32:
  case AMDGPU::V_MAC_F16_e64:
  case AMDGPU::V_MAD_F16_e64:
    return AMDGPU::V_MADMK_F16;
  case AMDGPU::V_MAC_F32_e32:
  case AMDGPU::V_MAC_F32_e64:
  case AMDGPU::V_MAD_F32_e64:
    return AMDGPU::V_MADMK_F32;
  case AMDGPU::V_FMAC_F32_e32:
  case AMDGPU::V_FMAC_F32_e64:
  case AMDGPU::V_FMA_F32_e64:
    return AMDGPU::V_FMAMK_F32;
  case AMDGPU::V_FMAC_F16_e32:
  case AMDGPU::V_FMAC_F16_e64:
  case AMDGPU::V_FMAC_F16_t16_e64:
  case AMDGPU::V_FMAC_F16_fake16_e64:
  case AMDGPU::V_FMAC_F16_t16_e32:
  case AMDGPU::V_FMAC_F16_fake16_e32:
  case AMDGPU::V_FMA_F16_e64:
    return ST.hasTrue16BitInsts() ? ST.useRealTrue16Insts()
                                        ? AMDGPU::V_FMAMK_F16_t16
                                        : AMDGPU::V_FMAMK_F16_fake16
                                  : AMDGPU::V_FMAMK_F16;
  case AMDGPU::V_FMAC_F64_e32:
  case AMDGPU::V_FMAC_F64_e64:
  case AMDGPU::V_FMA_F64_e64:
    return AMDGPU::V_FMAMK_F64;
  default:
    llvm_unreachable("invalid instruction");
  }
}

bool SIInstrInfo::foldImmediate(MachineInstr &UseMI, MachineInstr &DefMI,
                                Register Reg, MachineRegisterInfo *MRI) const {
  int64_t Imm;
  if (!getConstValDefinedInReg(DefMI, Reg, Imm))
    return false;

  const bool HasMultipleUses = !MRI->hasOneNonDBGUse(Reg);

  assert(!DefMI.getOperand(0).getSubReg() && "Expected SSA form");

  unsigned Opc = UseMI.getOpcode();
  if (Opc == AMDGPU::COPY) {
    assert(!UseMI.getOperand(0).getSubReg() && "Expected SSA form");

    Register DstReg = UseMI.getOperand(0).getReg();
    Register UseSubReg = UseMI.getOperand(1).getSubReg();

    const TargetRegisterClass *DstRC = RI.getRegClassForReg(*MRI, DstReg);

    if (HasMultipleUses) {
      // TODO: This should fold in more cases with multiple use, but we need to
      // more carefully consider what those uses are.
      unsigned ImmDefSize = RI.getRegSizeInBits(*MRI->getRegClass(Reg));

      // Avoid breaking up a 64-bit inline immediate into a subregister extract.
      if (UseSubReg != AMDGPU::NoSubRegister && ImmDefSize == 64)
        return false;

      // Most of the time folding a 32-bit inline constant is free (though this
      // might not be true if we can't later fold it into a real user).
      //
      // FIXME: This isInlineConstant check is imprecise if
      // getConstValDefinedInReg handled the tricky non-mov cases.
      if (ImmDefSize == 32 &&
          !isInlineConstant(Imm, AMDGPU::OPERAND_REG_IMM_INT32))
        return false;
    }

    bool Is16Bit = UseSubReg != AMDGPU::NoSubRegister &&
                   RI.getSubRegIdxSize(UseSubReg) == 16;

    if (Is16Bit) {
      if (RI.hasVGPRs(DstRC))
        return false; // Do not clobber vgpr_hi16

      if (DstReg.isVirtual() && UseSubReg != AMDGPU::lo16)
        return false;
    }

    MachineFunction *MF = UseMI.getMF();

    unsigned NewOpc = AMDGPU::INSTRUCTION_LIST_END;
    MCRegister MovDstPhysReg =
        DstReg.isPhysical() ? DstReg.asMCReg() : MCRegister();

    std::optional<int64_t> SubRegImm = extractSubregFromImm(Imm, UseSubReg);

    // TODO: Try to fold with AMDGPU::V_MOV_B16_t16_e64
    for (unsigned MovOp :
         {AMDGPU::S_MOV_B32, AMDGPU::V_MOV_B32_e32, AMDGPU::S_MOV_B64,
          AMDGPU::V_MOV_B64_PSEUDO, AMDGPU::V_ACCVGPR_WRITE_B32_e64}) {
      const MCInstrDesc &MovDesc = get(MovOp);

      const TargetRegisterClass *MovDstRC = getRegClass(MovDesc, 0);
      if (Is16Bit) {
        // We just need to find a correctly sized register class, so the
        // subregister index compatibility doesn't matter since we're statically
        // extracting the immediate value.
        MovDstRC = RI.getMatchingSuperRegClass(MovDstRC, DstRC, AMDGPU::lo16);
        if (!MovDstRC)
          continue;

        if (MovDstPhysReg) {
          // FIXME: We probably should not do this. If there is a live value in
          // the high half of the register, it will be corrupted.
          MovDstPhysReg =
              RI.getMatchingSuperReg(MovDstPhysReg, AMDGPU::lo16, MovDstRC);
          if (!MovDstPhysReg)
            continue;
        }
      }

      // Result class isn't the right size, try the next instruction.
      if (MovDstPhysReg) {
        if (!MovDstRC->contains(MovDstPhysReg))
          return false;
      } else if (!MRI->constrainRegClass(DstReg, MovDstRC)) {
        // TODO: This will be overly conservative in the case of 16-bit virtual
        // SGPRs. We could hack up the virtual register uses to use a compatible
        // 32-bit class.
        continue;
      }

      const MCOperandInfo &OpInfo = MovDesc.operands()[1];

      // Ensure the interpreted immediate value is a valid operand in the new
      // mov.
      //
      // FIXME: isImmOperandLegal should have form that doesn't require existing
      // MachineInstr or MachineOperand
      if (!RI.opCanUseLiteralConstant(OpInfo.OperandType) &&
          !isInlineConstant(*SubRegImm, OpInfo.OperandType))
        break;

      NewOpc = MovOp;
      break;
    }

    if (NewOpc == AMDGPU::INSTRUCTION_LIST_END)
      return false;

    if (Is16Bit) {
      UseMI.getOperand(0).setSubReg(AMDGPU::NoSubRegister);
      if (MovDstPhysReg)
        UseMI.getOperand(0).setReg(MovDstPhysReg);
      assert(UseMI.getOperand(1).getReg().isVirtual());
    }

    const MCInstrDesc &NewMCID = get(NewOpc);
    UseMI.setDesc(NewMCID);
    UseMI.getOperand(1).ChangeToImmediate(*SubRegImm);
    UseMI.addImplicitDefUseOperands(*MF);
    return true;
  }

  if (HasMultipleUses)
    return false;

  if (Opc == AMDGPU::V_MAD_F32_e64 || Opc == AMDGPU::V_MAC_F32_e64 ||
      Opc == AMDGPU::V_MAD_F16_e64 || Opc == AMDGPU::V_MAC_F16_e64 ||
      Opc == AMDGPU::V_FMA_F32_e64 || Opc == AMDGPU::V_FMAC_F32_e64 ||
      Opc == AMDGPU::V_FMA_F16_e64 || Opc == AMDGPU::V_FMAC_F16_e64 ||
      Opc == AMDGPU::V_FMAC_F16_t16_e64 ||
      Opc == AMDGPU::V_FMAC_F16_fake16_e64 || Opc == AMDGPU::V_FMA_F64_e64 ||
      Opc == AMDGPU::V_FMAC_F64_e64) {
    // Don't fold if we are using source or output modifiers. The new VOP2
    // instructions don't have them.
    if (hasAnyModifiersSet(UseMI))
      return false;

    // If this is a free constant, there's no reason to do this.
    // TODO: We could fold this here instead of letting SIFoldOperands do it
    // later.
    int Src0Idx = getNamedOperandIdx(UseMI.getOpcode(), AMDGPU::OpName::src0);

    // Any src operand can be used for the legality check.
    if (isInlineConstant(UseMI, Src0Idx, Imm))
      return false;

    MachineOperand *Src0 = &UseMI.getOperand(Src0Idx);

    MachineOperand *Src1 = getNamedOperand(UseMI, AMDGPU::OpName::src1);
    MachineOperand *Src2 = getNamedOperand(UseMI, AMDGPU::OpName::src2);

    auto CopyRegOperandToNarrowerRC =
        [MRI, this](MachineInstr &MI, unsigned OpNo,
                    const TargetRegisterClass *NewRC) -> void {
      if (!MI.getOperand(OpNo).isReg())
        return;
      Register Reg = MI.getOperand(OpNo).getReg();
      const TargetRegisterClass *RC = RI.getRegClassForReg(*MRI, Reg);
      if (RI.getCommonSubClass(RC, NewRC) != NewRC)
        return;
      Register Tmp = MRI->createVirtualRegister(NewRC);
      BuildMI(*MI.getParent(), MI.getIterator(), MI.getDebugLoc(),
              get(AMDGPU::COPY), Tmp)
          .addReg(Reg);
      MI.getOperand(OpNo).setReg(Tmp);
      MI.getOperand(OpNo).setIsKill();
    };

    // Multiplied part is the constant: Use v_madmk_{f16, f32}.
    if ((Src0->isReg() && Src0->getReg() == Reg) ||
        (Src1->isReg() && Src1->getReg() == Reg)) {
      MachineOperand *RegSrc =
          Src1->isReg() && Src1->getReg() == Reg ? Src0 : Src1;
      if (!RegSrc->isReg())
        return false;
      if (RI.isSGPRClass(MRI->getRegClass(RegSrc->getReg())) &&
          ST.getConstantBusLimit(Opc) < 2)
        return false;

      if (!Src2->isReg() || RI.isSGPRClass(MRI->getRegClass(Src2->getReg())))
        return false;

      // If src2 is also a literal constant then we have to choose which one to
      // fold. In general it is better to choose madak so that the other literal
      // can be materialized in an sgpr instead of a vgpr:
      //   s_mov_b32 s0, literal
      //   v_madak_f32 v0, s0, v0, literal
      // Instead of:
      //   v_mov_b32 v1, literal
      //   v_madmk_f32 v0, v0, literal, v1
      MachineInstr *Def = MRI->getUniqueVRegDef(Src2->getReg());
      if (Def && Def->isMoveImmediate() &&
          !isInlineConstant(Def->getOperand(1)))
        return false;

      unsigned NewOpc = getNewFMAMKInst(ST, Opc);
      if (pseudoToMCOpcode(NewOpc) == -1)
        return false;

      const std::optional<int64_t> SubRegImm = extractSubregFromImm(
          Imm, RegSrc == Src1 ? Src0->getSubReg() : Src1->getSubReg());

      // FIXME: This would be a lot easier if we could return a new instruction
      // instead of having to modify in place.

      Register SrcReg = RegSrc->getReg();
      unsigned SrcSubReg = RegSrc->getSubReg();
      Src0->setReg(SrcReg);
      Src0->setSubReg(SrcSubReg);
      Src0->setIsKill(RegSrc->isKill());

      if (Opc == AMDGPU::V_MAC_F32_e64 || Opc == AMDGPU::V_MAC_F16_e64 ||
          Opc == AMDGPU::V_FMAC_F32_e64 || Opc == AMDGPU::V_FMAC_F16_t16_e64 ||
          Opc == AMDGPU::V_FMAC_F16_fake16_e64 ||
          Opc == AMDGPU::V_FMAC_F16_e64 || Opc == AMDGPU::V_FMAC_F64_e64)
        UseMI.untieRegOperand(
            AMDGPU::getNamedOperandIdx(Opc, AMDGPU::OpName::src2));

      Src1->ChangeToImmediate(*SubRegImm);

      removeModOperands(UseMI);
      UseMI.setDesc(get(NewOpc));

      if (NewOpc == AMDGPU::V_FMAMK_F16_t16 ||
          NewOpc == AMDGPU::V_FMAMK_F16_fake16) {
        const TargetRegisterClass *NewRC = getRegClass(get(NewOpc), 0);
        Register Tmp = MRI->createVirtualRegister(NewRC);
        BuildMI(*UseMI.getParent(), std::next(UseMI.getIterator()),
                UseMI.getDebugLoc(), get(AMDGPU::COPY),
                UseMI.getOperand(0).getReg())
            .addReg(Tmp, RegState::Kill);
        UseMI.getOperand(0).setReg(Tmp);
        CopyRegOperandToNarrowerRC(UseMI, 1, NewRC);
        CopyRegOperandToNarrowerRC(UseMI, 3, NewRC);
      }

      bool DeleteDef = MRI->use_nodbg_empty(Reg);
      if (DeleteDef)
        DefMI.eraseFromParent();

      return true;
    }

    // Added part is the constant: Use v_madak_{f16, f32}.
    if (Src2->isReg() && Src2->getReg() == Reg) {
      if (ST.getConstantBusLimit(Opc) < 2) {
        // Not allowed to use constant bus for another operand.
        // We can however allow an inline immediate as src0.
        bool Src0Inlined = false;
        if (Src0->isReg()) {
          // Try to inline constant if possible.
          // If the Def moves immediate and the use is single
          // We are saving VGPR here.
          MachineInstr *Def = MRI->getUniqueVRegDef(Src0->getReg());
          if (Def && Def->isMoveImmediate() &&
              isInlineConstant(Def->getOperand(1)) &&
              MRI->hasOneNonDBGUse(Src0->getReg())) {
            Src0->ChangeToImmediate(Def->getOperand(1).getImm());
            Src0Inlined = true;
          } else if (ST.getConstantBusLimit(Opc) <= 1 &&
                     RI.isSGPRReg(*MRI, Src0->getReg())) {
            return false;
          }
          // VGPR is okay as Src0 - fallthrough
        }

        if (Src1->isReg() && !Src0Inlined) {
          // We have one slot for inlinable constant so far - try to fill it
          MachineInstr *Def = MRI->getUniqueVRegDef(Src1->getReg());
          if (Def && Def->isMoveImmediate() &&
              isInlineConstant(Def->getOperand(1)) &&
              MRI->hasOneNonDBGUse(Src1->getReg()) && commuteInstruction(UseMI))
            Src0->ChangeToImmediate(Def->getOperand(1).getImm());
          else if (RI.isSGPRReg(*MRI, Src1->getReg()))
            return false;
          // VGPR is okay as Src1 - fallthrough
        }
      }

      unsigned NewOpc = getNewFMAAKInst(ST, Opc);
      if (pseudoToMCOpcode(NewOpc) == -1)
        return false;

      // FIXME: This would be a lot easier if we could return a new instruction
      // instead of having to modify in place.

      if (Opc == AMDGPU::V_MAC_F32_e64 || Opc == AMDGPU::V_MAC_F16_e64 ||
          Opc == AMDGPU::V_FMAC_F32_e64 || Opc == AMDGPU::V_FMAC_F16_t16_e64 ||
          Opc == AMDGPU::V_FMAC_F16_fake16_e64 ||
          Opc == AMDGPU::V_FMAC_F16_e64 || Opc == AMDGPU::V_FMAC_F64_e64)
        UseMI.untieRegOperand(
            AMDGPU::getNamedOperandIdx(Opc, AMDGPU::OpName::src2));

      const std::optional<int64_t> SubRegImm =
          extractSubregFromImm(Imm, Src2->getSubReg());

      // ChangingToImmediate adds Src2 back to the instruction.
      Src2->ChangeToImmediate(*SubRegImm);

      // These come before src2.
      removeModOperands(UseMI);
      UseMI.setDesc(get(NewOpc));

      if (NewOpc == AMDGPU::V_FMAAK_F16_t16 ||
          NewOpc == AMDGPU::V_FMAAK_F16_fake16) {
        const TargetRegisterClass *NewRC = getRegClass(get(NewOpc), 0);
        Register Tmp = MRI->createVirtualRegister(NewRC);
        BuildMI(*UseMI.getParent(), std::next(UseMI.getIterator()),
                UseMI.getDebugLoc(), get(AMDGPU::COPY),
                UseMI.getOperand(0).getReg())
            .addReg(Tmp, RegState::Kill);
        UseMI.getOperand(0).setReg(Tmp);
        CopyRegOperandToNarrowerRC(UseMI, 1, NewRC);
        CopyRegOperandToNarrowerRC(UseMI, 2, NewRC);
      }

      // It might happen that UseMI was commuted
      // and we now have SGPR as SRC1. If so 2 inlined
      // constant and SGPR are illegal.
      legalizeOperands(UseMI);

      bool DeleteDef = MRI->use_nodbg_empty(Reg);
      if (DeleteDef)
        DefMI.eraseFromParent();

      return true;
    }
  }

  return false;
}

static bool
memOpsHaveSameBaseOperands(ArrayRef<const MachineOperand *> BaseOps1,
                           ArrayRef<const MachineOperand *> BaseOps2) {
  if (BaseOps1.size() != BaseOps2.size())
    return false;
  for (size_t I = 0, E = BaseOps1.size(); I < E; ++I) {
    if (!BaseOps1[I]->isIdenticalTo(*BaseOps2[I]))
      return false;
  }
  return true;
}

static bool offsetsDoNotOverlap(LocationSize WidthA, int OffsetA,
                                LocationSize WidthB, int OffsetB) {
  int LowOffset = OffsetA < OffsetB ? OffsetA : OffsetB;
  int HighOffset = OffsetA < OffsetB ? OffsetB : OffsetA;
  LocationSize LowWidth = (LowOffset == OffsetA) ? WidthA : WidthB;
  return LowWidth.hasValue() &&
         LowOffset + (int)LowWidth.getValue() <= HighOffset;
}

bool SIInstrInfo::checkInstOffsetsDoNotOverlap(const MachineInstr &MIa,
                                               const MachineInstr &MIb) const {
  SmallVector<const MachineOperand *, 4> BaseOps0, BaseOps1;
  int64_t Offset0, Offset1;
  LocationSize Dummy0 = LocationSize::precise(0);
  LocationSize Dummy1 = LocationSize::precise(0);
  bool Offset0IsScalable, Offset1IsScalable;
  if (!getMemOperandsWithOffsetWidth(MIa, BaseOps0, Offset0, Offset0IsScalable,
                                     Dummy0, &RI) ||
      !getMemOperandsWithOffsetWidth(MIb, BaseOps1, Offset1, Offset1IsScalable,
                                     Dummy1, &RI))
    return false;

  if (!memOpsHaveSameBaseOperands(BaseOps0, BaseOps1))
    return false;

  if (!MIa.hasOneMemOperand() || !MIb.hasOneMemOperand()) {
    // FIXME: Handle ds_read2 / ds_write2.
    return false;
  }
  LocationSize Width0 = MIa.memoperands().front()->getSize();
  LocationSize Width1 = MIb.memoperands().front()->getSize();
  return offsetsDoNotOverlap(Width0, Offset0, Width1, Offset1);
}

bool SIInstrInfo::areMemAccessesTriviallyDisjoint(const MachineInstr &MIa,
                                                  const MachineInstr &MIb) const {
  assert(MIa.mayLoadOrStore() &&
         "MIa must load from or modify a memory location");
  assert(MIb.mayLoadOrStore() &&
         "MIb must load from or modify a memory location");

  if (MIa.hasUnmodeledSideEffects() || MIb.hasUnmodeledSideEffects())
    return false;

  // XXX - Can we relax this between address spaces?
  if (MIa.hasOrderedMemoryRef() || MIb.hasOrderedMemoryRef())
    return false;

  if (isLDSDMA(MIa) || isLDSDMA(MIb))
    return false;

  if (MIa.isBundle() || MIb.isBundle())
    return false;

  // TODO: Should we check the address space from the MachineMemOperand? That
  // would allow us to distinguish objects we know don't alias based on the
  // underlying address space, even if it was lowered to a different one,
  // e.g. private accesses lowered to use MUBUF instructions on a scratch
  // buffer.
  if (isDS(MIa)) {
    if (isDS(MIb))
      return checkInstOffsetsDoNotOverlap(MIa, MIb);

    return !isFLAT(MIb) || isSegmentSpecificFLAT(MIb);
  }

  if (isMUBUF(MIa) || isMTBUF(MIa)) {
    if (isMUBUF(MIb) || isMTBUF(MIb))
      return checkInstOffsetsDoNotOverlap(MIa, MIb);

    if (isFLAT(MIb))
      return isFLATScratch(MIb);

    return !isSMRD(MIb);
  }

  if (isSMRD(MIa)) {
    if (isSMRD(MIb))
      return checkInstOffsetsDoNotOverlap(MIa, MIb);

    if (isFLAT(MIb))
      return isFLATScratch(MIb);

    return !isMUBUF(MIb) && !isMTBUF(MIb);
  }

  if (isFLAT(MIa)) {
    if (isFLAT(MIb)) {
      if ((isFLATScratch(MIa) && isFLATGlobal(MIb)) ||
          (isFLATGlobal(MIa) && isFLATScratch(MIb)))
        return true;

      return checkInstOffsetsDoNotOverlap(MIa, MIb);
    }

    return false;
  }

  return false;
}

static bool getFoldableImm(Register Reg, const MachineRegisterInfo &MRI,
                           int64_t &Imm, MachineInstr **DefMI = nullptr) {
  if (Reg.isPhysical())
    return false;
  auto *Def = MRI.getUniqueVRegDef(Reg);
  if (Def && SIInstrInfo::isFoldableCopy(*Def) && Def->getOperand(1).isImm()) {
    Imm = Def->getOperand(1).getImm();
    if (DefMI)
      *DefMI = Def;
    return true;
  }
  return false;
}

static bool getFoldableImm(const MachineOperand *MO, int64_t &Imm,
                           MachineInstr **DefMI = nullptr) {
  if (!MO->isReg())
    return false;
  const MachineFunction *MF = MO->getParent()->getMF();
  const MachineRegisterInfo &MRI = MF->getRegInfo();
  return getFoldableImm(MO->getReg(), MRI, Imm, DefMI);
}

static void updateLiveVariables(LiveVariables *LV, MachineInstr &MI,
                                MachineInstr &NewMI) {
  if (LV) {
    unsigned NumOps = MI.getNumOperands();
    for (unsigned I = 1; I < NumOps; ++I) {
      MachineOperand &Op = MI.getOperand(I);
      if (Op.isReg() && Op.isKill())
        LV->replaceKillInstruction(Op.getReg(), MI, NewMI);
    }
  }
}

static unsigned getNewFMAInst(const GCNSubtarget &ST, unsigned Opc) {
  switch (Opc) {
  case AMDGPU::V_MAC_F16_e32:
  case AMDGPU::V_MAC_F16_e64:
    return AMDGPU::V_MAD_F16_e64;
  case AMDGPU::V_MAC_F32_e32:
  case AMDGPU::V_MAC_F32_e64:
    return AMDGPU::V_MAD_F32_e64;
  case AMDGPU::V_MAC_LEGACY_F32_e32:
  case AMDGPU::V_MAC_LEGACY_F32_e64:
    return AMDGPU::V_MAD_LEGACY_F32_e64;
  case AMDGPU::V_FMAC_LEGACY_F32_e32:
  case AMDGPU::V_FMAC_LEGACY_F32_e64:
    return AMDGPU::V_FMA_LEGACY_F32_e64;
  case AMDGPU::V_FMAC_F16_e32:
  case AMDGPU::V_FMAC_F16_e64:
  case AMDGPU::V_FMAC_F16_t16_e64:
  case AMDGPU::V_FMAC_F16_fake16_e64:
    return ST.hasTrue16BitInsts() ? ST.useRealTrue16Insts()
                                        ? AMDGPU::V_FMA_F16_gfx9_t16_e64
                                        : AMDGPU::V_FMA_F16_gfx9_fake16_e64
                                  : AMDGPU::V_FMA_F16_gfx9_e64;
  case AMDGPU::V_FMAC_F32_e32:
  case AMDGPU::V_FMAC_F32_e64:
    return AMDGPU::V_FMA_F32_e64;
  case AMDGPU::V_FMAC_F64_e32:
  case AMDGPU::V_FMAC_F64_e64:
    return AMDGPU::V_FMA_F64_e64;
  default:
    llvm_unreachable("invalid instruction");
  }
}

/// Helper struct for the implementation of 3-address conversion to communicate
/// updates made to instruction operands.
struct SIInstrInfo::ThreeAddressUpdates {
  /// Other instruction whose def is no longer used by the converted
  /// instruction.
  MachineInstr *RemoveMIUse = nullptr;
};

MachineInstr *SIInstrInfo::convertToThreeAddress(MachineInstr &MI,
                                                 LiveVariables *LV,
                                                 LiveIntervals *LIS) const {
  MachineBasicBlock &MBB = *MI.getParent();
  MachineInstr *CandidateMI = &MI;

  if (MI.isBundle()) {
    // This is a temporary placeholder for bundle handling that enables us to
    // exercise the relevant code paths in the two-address instruction pass.
    if (MI.getBundleSize() != 1)
      return nullptr;
    CandidateMI = MI.getNextNode();
  }

  ThreeAddressUpdates U;
  MachineInstr *NewMI = convertToThreeAddressImpl(*CandidateMI, U);
  if (!NewMI)
    return nullptr;

  if (MI.isBundle()) {
    CandidateMI->eraseFromBundle();

    for (MachineOperand &MO : MI.all_defs()) {
      if (MO.isTied())
        MI.untieRegOperand(MO.getOperandNo());
    }
  } else {
    updateLiveVariables(LV, MI, *NewMI);
    if (LIS) {
      LIS->ReplaceMachineInstrInMaps(MI, *NewMI);
      // SlotIndex of defs needs to be updated when converting to early-clobber
      MachineOperand &Def = NewMI->getOperand(0);
      if (Def.isEarlyClobber() && Def.isReg() &&
          LIS->hasInterval(Def.getReg())) {
        SlotIndex OldIndex = LIS->getInstructionIndex(*NewMI).getRegSlot(false);
        SlotIndex NewIndex = LIS->getInstructionIndex(*NewMI).getRegSlot(true);
        auto &LI = LIS->getInterval(Def.getReg());
        auto UpdateDefIndex = [&](LiveRange &LR) {
          auto *S = LR.find(OldIndex);
          if (S != LR.end() && S->start == OldIndex) {
            assert(S->valno && S->valno->def == OldIndex);
            S->start = NewIndex;
            S->valno->def = NewIndex;
          }
        };
        UpdateDefIndex(LI);
        for (auto &SR : LI.subranges())
          UpdateDefIndex(SR);
      }
    }
  }

  if (U.RemoveMIUse) {
    MachineRegisterInfo &MRI = MBB.getParent()->getRegInfo();
    // The only user is the instruction which will be killed.
    Register DefReg = U.RemoveMIUse->getOperand(0).getReg();

    if (MRI.hasOneNonDBGUse(DefReg)) {
      // We cannot just remove the DefMI here, calling pass will crash.
      U.RemoveMIUse->setDesc(get(AMDGPU::IMPLICIT_DEF));
      U.RemoveMIUse->getOperand(0).setIsDead(true);
      for (unsigned I = U.RemoveMIUse->getNumOperands() - 1; I != 0; --I)
        U.RemoveMIUse->removeOperand(I);
      if (LV)
        LV->getVarInfo(DefReg).AliveBlocks.clear();
    }

    if (MI.isBundle()) {
      VirtRegInfo VRI = AnalyzeVirtRegInBundle(MI, DefReg);
      if (!VRI.Reads && !VRI.Writes) {
        for (MachineOperand &MO : MI.all_uses()) {
          if (MO.isReg() && MO.getReg() == DefReg) {
            assert(MO.getSubReg() == 0 &&
                   "tied sub-registers in bundles currently not supported");
            MI.removeOperand(MO.getOperandNo());
            break;
          }
        }

        if (LIS)
          LIS->shrinkToUses(&LIS->getInterval(DefReg));
      }
    } else if (LIS) {
      LiveInterval &DefLI = LIS->getInterval(DefReg);

      // We cannot delete the original instruction here, so hack out the use
      // in the original instruction with a dummy register so we can use
      // shrinkToUses to deal with any multi-use edge cases. Other targets do
      // not have the complexity of deleting a use to consider here.
      Register DummyReg = MRI.cloneVirtualRegister(DefReg);
      for (MachineOperand &MIOp : MI.uses()) {
        if (MIOp.isReg() && MIOp.getReg() == DefReg) {
          MIOp.setIsUndef(true);
          MIOp.setReg(DummyReg);
        }
      }

      if (MI.isBundle()) {
        VirtRegInfo VRI = AnalyzeVirtRegInBundle(MI, DefReg);
        if (!VRI.Reads && !VRI.Writes) {
          for (MachineOperand &MIOp : MI.uses()) {
            if (MIOp.isReg() && MIOp.getReg() == DefReg) {
              MIOp.setIsUndef(true);
              MIOp.setReg(DummyReg);
            }
          }
        }

        MI.addOperand(MachineOperand::CreateReg(DummyReg, false, false, false,
                                                false, /*isUndef=*/true));
      }

      LIS->shrinkToUses(&DefLI);
    }
  }

  return MI.isBundle() ? &MI : NewMI;
}

MachineInstr *
SIInstrInfo::convertToThreeAddressImpl(MachineInstr &MI,
                                       ThreeAddressUpdates &U) const {
  MachineBasicBlock &MBB = *MI.getParent();
  unsigned Opc = MI.getOpcode();

  // Handle MFMA.
  int NewMFMAOpc = AMDGPU::getMFMAEarlyClobberOp(Opc);
  if (NewMFMAOpc != -1) {
    MachineInstrBuilder MIB =
        BuildMI(MBB, MI, MI.getDebugLoc(), get(NewMFMAOpc));
    for (unsigned I = 0, E = MI.getNumExplicitOperands(); I != E; ++I)
      MIB.add(MI.getOperand(I));
    return MIB;
  }

  if (SIInstrInfo::isWMMA(MI)) {
    unsigned NewOpc = AMDGPU::mapWMMA2AddrTo3AddrOpcode(MI.getOpcode());
    MachineInstrBuilder MIB = BuildMI(MBB, MI, MI.getDebugLoc(), get(NewOpc))
                                  .setMIFlags(MI.getFlags());
    for (unsigned I = 0, E = MI.getNumExplicitOperands(); I != E; ++I)
      MIB->addOperand(MI.getOperand(I));
    return MIB;
  }

  assert(Opc != AMDGPU::V_FMAC_F16_t16_e32 &&
         Opc != AMDGPU::V_FMAC_F16_fake16_e32 &&
         "V_FMAC_F16_t16/fake16_e32 is not supported and not expected to be "
         "present pre-RA");

  // Handle MAC/FMAC.
  bool IsF64 = Opc == AMDGPU::V_FMAC_F64_e32 || Opc == AMDGPU::V_FMAC_F64_e64;
  bool IsLegacy = Opc == AMDGPU::V_MAC_LEGACY_F32_e32 ||
                  Opc == AMDGPU::V_MAC_LEGACY_F32_e64 ||
                  Opc == AMDGPU::V_FMAC_LEGACY_F32_e32 ||
                  Opc == AMDGPU::V_FMAC_LEGACY_F32_e64;
  bool Src0Literal = false;

  switch (Opc) {
  default:
    return nullptr;
  case AMDGPU::V_MAC_F16_e64:
  case AMDGPU::V_FMAC_F16_e64:
  case AMDGPU::V_FMAC_F16_t16_e64:
  case AMDGPU::V_FMAC_F16_fake16_e64:
  case AMDGPU::V_MAC_F32_e64:
  case AMDGPU::V_MAC_LEGACY_F32_e64:
  case AMDGPU::V_FMAC_F32_e64:
  case AMDGPU::V_FMAC_LEGACY_F32_e64:
  case AMDGPU::V_FMAC_F64_e64:
    break;
  case AMDGPU::V_MAC_F16_e32:
  case AMDGPU::V_FMAC_F16_e32:
  case AMDGPU::V_MAC_F32_e32:
  case AMDGPU::V_MAC_LEGACY_F32_e32:
  case AMDGPU::V_FMAC_F32_e32:
  case AMDGPU::V_FMAC_LEGACY_F32_e32:
  case AMDGPU::V_FMAC_F64_e32: {
    int Src0Idx = AMDGPU::getNamedOperandIdx(MI.getOpcode(),
                                             AMDGPU::OpName::src0);
    const MachineOperand *Src0 = &MI.getOperand(Src0Idx);
    if (!Src0->isReg() && !Src0->isImm())
      return nullptr;

    if (Src0->isImm() && !isInlineConstant(MI, Src0Idx, *Src0))
      Src0Literal = true;

    break;
  }
  }

  MachineInstrBuilder MIB;
  const MachineOperand *Dst = getNamedOperand(MI, AMDGPU::OpName::vdst);
  const MachineOperand *Src0 = getNamedOperand(MI, AMDGPU::OpName::src0);
  const MachineOperand *Src0Mods =
    getNamedOperand(MI, AMDGPU::OpName::src0_modifiers);
  const MachineOperand *Src1 = getNamedOperand(MI, AMDGPU::OpName::src1);
  const MachineOperand *Src1Mods =
    getNamedOperand(MI, AMDGPU::OpName::src1_modifiers);
  const MachineOperand *Src2 = getNamedOperand(MI, AMDGPU::OpName::src2);
  const MachineOperand *Src2Mods =
      getNamedOperand(MI, AMDGPU::OpName::src2_modifiers);
  const MachineOperand *Clamp = getNamedOperand(MI, AMDGPU::OpName::clamp);
  const MachineOperand *Omod = getNamedOperand(MI, AMDGPU::OpName::omod);
  const MachineOperand *OpSel = getNamedOperand(MI, AMDGPU::OpName::op_sel);

  if (!Src0Mods && !Src1Mods && !Src2Mods && !Clamp && !Omod && !IsLegacy &&
      (!IsF64 || ST.hasFmaakFmamkF64Insts()) &&
      // If we have an SGPR input, we will violate the constant bus restriction.
      (ST.getConstantBusLimit(Opc) > 1 || !Src0->isReg() ||
       !RI.isSGPRReg(MBB.getParent()->getRegInfo(), Src0->getReg()))) {
    MachineInstr *DefMI = nullptr;

    int64_t Imm;
    if (!Src0Literal && getFoldableImm(Src2, Imm, &DefMI)) {
      unsigned NewOpc = getNewFMAAKInst(ST, Opc);
      if (pseudoToMCOpcode(NewOpc) != -1) {
        MIB = BuildMI(MBB, MI, MI.getDebugLoc(), get(NewOpc))
                  .add(*Dst)
                  .add(*Src0)
                  .add(*Src1)
                  .addImm(Imm)
                  .setMIFlags(MI.getFlags());
        U.RemoveMIUse = DefMI;
        return MIB;
      }
    }
    unsigned NewOpc = getNewFMAMKInst(ST, Opc);
    if (!Src0Literal && getFoldableImm(Src1, Imm, &DefMI)) {
      if (pseudoToMCOpcode(NewOpc) != -1) {
        MIB = BuildMI(MBB, MI, MI.getDebugLoc(), get(NewOpc))
                  .add(*Dst)
                  .add(*Src0)
                  .addImm(Imm)
                  .add(*Src2)
                  .setMIFlags(MI.getFlags());
        U.RemoveMIUse = DefMI;
        return MIB;
      }
    }
    if (Src0Literal || getFoldableImm(Src0, Imm, &DefMI)) {
      if (Src0Literal) {
        Imm = Src0->getImm();
        DefMI = nullptr;
      }
      if (pseudoToMCOpcode(NewOpc) != -1 &&
          isOperandLegal(
              MI, AMDGPU::getNamedOperandIdx(NewOpc, AMDGPU::OpName::src0),
              Src1)) {
        MIB = BuildMI(MBB, MI, MI.getDebugLoc(), get(NewOpc))
                  .add(*Dst)
                  .add(*Src1)
                  .addImm(Imm)
                  .add(*Src2)
                  .setMIFlags(MI.getFlags());
        U.RemoveMIUse = DefMI;
        return MIB;
      }
    }
  }

  // VOP2 mac/fmac with a literal operand cannot be converted to VOP3 mad/fma
  // if VOP3 does not allow a literal operand.
  if (Src0Literal && !ST.hasVOP3Literal())
    return nullptr;

  unsigned NewOpc = getNewFMAInst(ST, Opc);

  if (pseudoToMCOpcode(NewOpc) == -1)
    return nullptr;

  MIB = BuildMI(MBB, MI, MI.getDebugLoc(), get(NewOpc))
            .add(*Dst)
            .addImm(Src0Mods ? Src0Mods->getImm() : 0)
            .add(*Src0)
            .addImm(Src1Mods ? Src1Mods->getImm() : 0)
            .add(*Src1)
            .addImm(Src2Mods ? Src2Mods->getImm() : 0)
            .add(*Src2)
            .addImm(Clamp ? Clamp->getImm() : 0)
            .addImm(Omod ? Omod->getImm() : 0)
            .setMIFlags(MI.getFlags());
  if (AMDGPU::hasNamedOperand(NewOpc, AMDGPU::OpName::op_sel))
    MIB.addImm(OpSel ? OpSel->getImm() : 0);
  return MIB;
}

// It's not generally safe to move VALU instructions across these since it will
// start using the register as a base index rather than directly.
// XXX - Why isn't hasSideEffects sufficient for these?
static bool changesVGPRIndexingMode(const MachineInstr &MI) {
  switch (MI.getOpcode()) {
  case AMDGPU::S_SET_GPR_IDX_ON:
  case AMDGPU::S_SET_GPR_IDX_MODE:
  case AMDGPU::S_SET_GPR_IDX_OFF:
    return true;
  default:
    return false;
  }
}

bool SIInstrInfo::isSchedulingBoundary(const MachineInstr &MI,
                                       const MachineBasicBlock *MBB,
                                       const MachineFunction &MF) const {
  // Skipping the check for SP writes in the base implementation. The reason it
  // was added was apparently due to compile time concerns.
  //
  // TODO: Do we really want this barrier? It triggers unnecessary hazard nops
  // but is probably avoidable.

  // Copied from base implementation.
  // Terminators and labels can't be scheduled around.
  if (MI.isTerminator() || MI.isPosition())
    return true;

  // INLINEASM_BR can jump to another block
  if (MI.getOpcode() == TargetOpcode::INLINEASM_BR)
    return true;

  if (MI.getOpcode() == AMDGPU::SCHED_BARRIER && MI.getOperand(0).getImm() == 0)
    return true;

  // Target-independent instructions do not have an implicit-use of EXEC, even
  // when they operate on VGPRs. Treating EXEC modifications as scheduling
  // boundaries prevents incorrect movements of such instructions.
  return MI.modifiesRegister(AMDGPU::EXEC, &RI) ||
         MI.getOpcode() == AMDGPU::S_SETREG_IMM32_B32 ||
         MI.getOpcode() == AMDGPU::S_SETREG_B32 ||
         MI.getOpcode() == AMDGPU::S_SETPRIO ||
         MI.getOpcode() == AMDGPU::S_SETPRIO_INC_WG ||
         changesVGPRIndexingMode(MI);
}

bool SIInstrInfo::isAlwaysGDS(uint32_t Opcode) const {
  return Opcode == AMDGPU::DS_ORDERED_COUNT ||
         Opcode == AMDGPU::DS_ADD_GS_REG_RTN ||
         Opcode == AMDGPU::DS_SUB_GS_REG_RTN || isGWS(Opcode);
}

bool SIInstrInfo::mayAccessScratch(const MachineInstr &MI) const {
  // Instructions that access scratch use FLAT encoding or BUF encodings.
  if ((!isFLAT(MI) || isFLATGlobal(MI)) && !isBUF(MI))
    return false;

  // SCRATCH instructions always access scratch.
  if (isFLATScratch(MI))
    return true;

  // If FLAT_SCRATCH registers are not initialized, we can never access scratch
  // via the aperture.
  if (MI.getMF()->getFunction().hasFnAttribute("amdgpu-no-flat-scratch-init"))
    return false;

  // If there are no memory operands then conservatively assume the flat
  // operation may access scratch.
  if (MI.memoperands_empty())
    return true;

  // See if any memory operand specifies an address space that involves scratch.
  return any_of(MI.memoperands(), [](const MachineMemOperand *Memop) {
    unsigned AS = Memop->getAddrSpace();
    if (AS == AMDGPUAS::FLAT_ADDRESS) {
      const MDNode *MD = Memop->getAAInfo().NoAliasAddrSpace;
      return !MD || !AMDGPU::hasValueInRangeLikeMetadata(
                        *MD, AMDGPUAS::PRIVATE_ADDRESS);
    }
    return AS == AMDGPUAS::PRIVATE_ADDRESS;
  });
}

bool SIInstrInfo::mayAccessVMEMThroughFlat(const MachineInstr &MI) const {
  assert(isFLAT(MI));

  // All flat instructions use the VMEM counter except prefetch.
  if (!usesVM_CNT(MI))
    return false;

  // If there are no memory operands then conservatively assume the flat
  // operation may access VMEM.
  if (MI.memoperands_empty())
    return true;

  // See if any memory operand specifies an address space that involves VMEM.
  // Flat operations only supported FLAT, LOCAL (LDS), or address spaces
  // involving VMEM such as GLOBAL, CONSTANT, PRIVATE (SCRATCH), etc. The REGION
  // (GDS) address space is not supported by flat operations. Therefore, simply
  // return true unless only the LDS address space is found.
  for (const MachineMemOperand *Memop : MI.memoperands()) {
    unsigned AS = Memop->getAddrSpace();
    assert(AS != AMDGPUAS::REGION_ADDRESS);
    if (AS != AMDGPUAS::LOCAL_ADDRESS)
      return true;
  }

  return false;
}

bool SIInstrInfo::mayAccessLDSThroughFlat(const MachineInstr &MI,
                                          bool TgSplit) const {
  assert(isFLAT(MI));

  // Flat instruction such as SCRATCH and GLOBAL do not use the lgkm counter.
  if (!usesLGKM_CNT(MI))
    return false;

  // If in tgsplit mode then there can be no use of LDS.
  if (TgSplit)
    return false;

  // If there are no memory operands then conservatively assume the flat
  // operation may access LDS.
  if (MI.memoperands_empty())
    return true;

  // See if any memory operand specifies an address space that involves LDS.
  for (const MachineMemOperand *Memop : MI.memoperands()) {
    unsigned AS = Memop->getAddrSpace();
    if (AS == AMDGPUAS::LOCAL_ADDRESS || AS == AMDGPUAS::FLAT_ADDRESS)
      return true;
  }

  return false;
}

bool SIInstrInfo::modifiesModeRegister(const MachineInstr &MI) {
  // Skip the full operand and register alias search modifiesRegister
  // does. There's only a handful of instructions that touch this, it's only an
  // implicit def, and doesn't alias any other registers.
  return is_contained(MI.getDesc().implicit_defs(), AMDGPU::MODE);
}

bool SIInstrInfo::hasUnwantedEffectsWhenEXECEmpty(const MachineInstr &MI) const {
  unsigned Opcode = MI.getOpcode();

  if (MI.mayStore() && isSMRD(MI))
    return true; // scalar store or atomic

  // This will terminate the function when other lanes may need to continue.
  if (MI.isReturn())
    return true;

  // These instructions cause shader I/O that may cause hardware lockups
  // when executed with an empty EXEC mask.
  //
  // Note: exp with VM = DONE = 0 is automatically skipped by hardware when
  //       EXEC = 0, but checking for that case here seems not worth it
  //       given the typical code patterns.
  if (Opcode == AMDGPU::S_SENDMSG || Opcode == AMDGPU::S_SENDMSGHALT ||
      isEXP(Opcode) || Opcode == AMDGPU::DS_ORDERED_COUNT ||
      Opcode == AMDGPU::S_TRAP || Opcode == AMDGPU::S_WAIT_EVENT ||
      Opcode == AMDGPU::S_SETHALT)
    return true;

  if (MI.isCall() || MI.isInlineAsm())
    return true; // conservative assumption

  // Assume that barrier interactions are only intended with active lanes.
  if (isBarrier(Opcode))
    return true;

  // A mode change is a scalar operation that influences vector instructions.
  if (modifiesModeRegister(MI))
    return true;

  // These are like SALU instructions in terms of effects, so it's questionable
  // whether we should return true for those.
  //
  // However, executing them with EXEC = 0 causes them to operate on undefined
  // data, which we avoid by returning true here.
  if (Opcode == AMDGPU::V_READFIRSTLANE_B32 ||
      Opcode == AMDGPU::V_READLANE_B32 || Opcode == AMDGPU::V_WRITELANE_B32 ||
      Opcode == AMDGPU::SI_RESTORE_S32_FROM_VGPR ||
      Opcode == AMDGPU::SI_SPILL_S32_TO_VGPR)
    return true;

  return false;
}

bool SIInstrInfo::mayReadEXEC(const MachineRegisterInfo &MRI,
                              const MachineInstr &MI) const {
  if (MI.isMetaInstruction())
    return false;

  // This won't read exec if this is an SGPR->SGPR copy.
  if (MI.isCopyLike()) {
    if (!RI.isSGPRReg(MRI, MI.getOperand(0).getReg()))
      return true;

    // Make sure this isn't copying exec as a normal operand
    return MI.readsRegister(AMDGPU::EXEC, &RI);
  }

  // Make a conservative assumption about the callee.
  if (MI.isCall())
    return true;

  // Be conservative with any unhandled generic opcodes.
  if (!isTargetSpecificOpcode(MI.getOpcode()))
    return true;

  return !isSALU(MI) || MI.readsRegister(AMDGPU::EXEC, &RI);
}

bool SIInstrInfo::isInlineConstant(const APInt &Imm) const {
  switch (Imm.getBitWidth()) {
  case 1: // This likely will be a condition code mask.
    return true;

  case 32:
    return AMDGPU::isInlinableLiteral32(Imm.getSExtValue(),
                                        ST.hasInv2PiInlineImm());
  case 64:
    return AMDGPU::isInlinableLiteral64(Imm.getSExtValue(),
                                        ST.hasInv2PiInlineImm());
  case 16:
    return ST.has16BitInsts() &&
           AMDGPU::isInlinableLiteralI16(Imm.getSExtValue(),
                                         ST.hasInv2PiInlineImm());
  default:
    llvm_unreachable("invalid bitwidth");
  }
}

bool SIInstrInfo::isInlineConstant(const APFloat &Imm) const {
  APInt IntImm = Imm.bitcastToAPInt();
  int64_t IntImmVal = IntImm.getSExtValue();
  bool HasInv2Pi = ST.hasInv2PiInlineImm();
  switch (APFloat::SemanticsToEnum(Imm.getSemantics())) {
  default:
    llvm_unreachable("invalid fltSemantics");
  case APFloatBase::S_IEEEsingle:
  case APFloatBase::S_IEEEdouble:
    return isInlineConstant(IntImm);
  case APFloatBase::S_BFloat:
    return ST.has16BitInsts() &&
           AMDGPU::isInlinableLiteralBF16(IntImmVal, HasInv2Pi);
  case APFloatBase::S_IEEEhalf:
    return ST.has16BitInsts() &&
           AMDGPU::isInlinableLiteralFP16(IntImmVal, HasInv2Pi);
  }
}

bool SIInstrInfo::isInlineConstant(int64_t Imm, uint8_t OperandType) const {
  // MachineOperand provides no way to tell the true operand size, since it only
  // records a 64-bit value. We need to know the size to determine if a 32-bit
  // floating point immediate bit pattern is legal for an integer immediate. It
  // would be for any 32-bit integer operand, but would not be for a 64-bit one.
  switch (OperandType) {
  case AMDGPU::OPERAND_REG_IMM_INT32:
  case AMDGPU::OPERAND_REG_IMM_FP32:
  case AMDGPU::OPERAND_REG_INLINE_C_INT32:
  case AMDGPU::OPERAND_REG_INLINE_C_FP32:
  case AMDGPU::OPERAND_REG_IMM_V2FP32:
  case AMDGPU::OPERAND_REG_IMM_V2INT32:
  case AMDGPU::OPERAND_REG_INLINE_AC_INT32:
  case AMDGPU::OPERAND_REG_INLINE_AC_FP32:
  case AMDGPU::OPERAND_INLINE_SPLIT_BARRIER_INT32: {
    int32_t Trunc = static_cast<int32_t>(Imm);
    return AMDGPU::isInlinableLiteral32(Trunc, ST.hasInv2PiInlineImm());
  }
  case AMDGPU::OPERAND_REG_IMM_INT64:
  case AMDGPU::OPERAND_REG_IMM_FP64:
  case AMDGPU::OPERAND_REG_INLINE_C_INT64:
  case AMDGPU::OPERAND_REG_INLINE_C_FP64:
  case AMDGPU::OPERAND_REG_INLINE_AC_FP64:
  case AMDGPU::OPERAND_REG_IMM_V2FP64:
  case AMDGPU::OPERAND_REG_IMM_V2INT64:
    return AMDGPU::isInlinableLiteral64(Imm, ST.hasInv2PiInlineImm());
  case AMDGPU::OPERAND_REG_IMM_INT16:
  case AMDGPU::OPERAND_REG_INLINE_C_INT16:
    // We would expect inline immediates to not be concerned with an integer/fp
    // distinction. However, in the case of 16-bit integer operations, the
    // "floating point" values appear to not work. It seems read the low 16-bits
    // of 32-bit immediates, which happens to always work for the integer
    // values.
    //
    // See llvm bugzilla 46302.
    //
    // TODO: Theoretically we could use op-sel to use the high bits of the
    // 32-bit FP values.
    return AMDGPU::isInlinableIntLiteral(Imm);
  case AMDGPU::OPERAND_REG_IMM_V2INT16:
  case AMDGPU::OPERAND_REG_INLINE_C_V2INT16:
    return AMDGPU::isInlinableLiteralV2I16(Imm);
  case AMDGPU::OPERAND_REG_IMM_V2FP16:
  case AMDGPU::OPERAND_REG_INLINE_C_V2FP16:
    return AMDGPU::isInlinableLiteralV2F16(Imm);
  case AMDGPU::OPERAND_REG_IMM_V2FP16_SPLAT:
    return AMDGPU::isPKFMACF16InlineConstant(Imm, ST.isGFX11Plus());
  case AMDGPU::OPERAND_REG_IMM_V2BF16:
  case AMDGPU::OPERAND_REG_INLINE_C_V2BF16:
    return AMDGPU::isInlinableLiteralV2BF16(Imm);
  case AMDGPU::OPERAND_REG_IMM_NOINLINE_V2FP16:
    return false;
  case AMDGPU::OPERAND_REG_IMM_FP16:
  case AMDGPU::OPERAND_REG_INLINE_C_FP16: {
    if (isInt<16>(Imm) || isUInt<16>(Imm)) {
      // A few special case instructions have 16-bit operands on subtargets
      // where 16-bit instructions are not legal.
      // TODO: Do the 32-bit immediates work? We shouldn't really need to handle
      // constants in these cases
      int16_t Trunc = static_cast<int16_t>(Imm);
      return ST.has16BitInsts() &&
             AMDGPU::isInlinableLiteralFP16(Trunc, ST.hasInv2PiInlineImm());
    }

    return false;
  }
  case AMDGPU::OPERAND_REG_IMM_BF16:
  case AMDGPU::OPERAND_REG_INLINE_C_BF16: {
    if (isInt<16>(Imm) || isUInt<16>(Imm)) {
      int16_t Trunc = static_cast<int16_t>(Imm);
      return ST.has16BitInsts() &&
             AMDGPU::isInlinableLiteralBF16(Trunc, ST.hasInv2PiInlineImm());
    }
    return false;
  }
  case AMDGPU::OPERAND_KIMM32:
  case AMDGPU::OPERAND_KIMM16:
  case AMDGPU::OPERAND_KIMM64:
    return false;
  case AMDGPU::OPERAND_INLINE_C_AV64_PSEUDO:
    return isLegalAV64PseudoImm(Imm);
  case AMDGPU::OPERAND_INPUT_MODS:
  case MCOI::OPERAND_IMMEDIATE:
    // Always embedded in the instruction for free.
    return true;
  case MCOI::OPERAND_UNKNOWN:
  case MCOI::OPERAND_REGISTER:
  case MCOI::OPERAND_PCREL:
  case MCOI::OPERAND_GENERIC_0:
  case MCOI::OPERAND_GENERIC_1:
  case MCOI::OPERAND_GENERIC_2:
  case MCOI::OPERAND_GENERIC_3:
  case MCOI::OPERAND_GENERIC_4:
  case MCOI::OPERAND_GENERIC_5:
    // Just ignore anything else.
    return true;
  default:
    llvm_unreachable("invalid operand type");
  }
}

static bool compareMachineOp(const MachineOperand &Op0,
                             const MachineOperand &Op1) {
  if (Op0.getType() != Op1.getType())
    return false;

  switch (Op0.getType()) {
  case MachineOperand::MO_Register:
    return Op0.getReg() == Op1.getReg();
  case MachineOperand::MO_Immediate:
    return Op0.getImm() == Op1.getImm();
  default:
    llvm_unreachable("Didn't expect to be comparing these operand types");
  }
}

bool SIInstrInfo::isLiteralOperandLegal(const MCInstrDesc &InstDesc,
                                        const MCOperandInfo &OpInfo) const {
  if (OpInfo.OperandType == MCOI::OPERAND_IMMEDIATE)
    return true;

  if (!RI.opCanUseLiteralConstant(OpInfo.OperandType))
    return false;

  if (!isVOP3(InstDesc) || !AMDGPU::isSISrcOperand(OpInfo))
    return true;

  return ST.hasVOP3Literal();
}

bool SIInstrInfo::isImmOperandLegal(const MCInstrDesc &InstDesc, unsigned OpNo,
                                    int64_t ImmVal) const {
  const unsigned Opc = InstDesc.getOpcode();
  int Src1Idx = AMDGPU::getNamedOperandIdx(Opc, AMDGPU::OpName::src1);
  if (Src1Idx != -1 && isDPP(Opc) && !ST.hasDPPSrc1SGPR() &&
      OpNo == static_cast<unsigned>(Src1Idx))
    return false;

  const MCOperandInfo &OpInfo = InstDesc.operands()[OpNo];
  if (isInlineConstant(ImmVal, OpInfo.OperandType)) {
    if (isMAI(InstDesc) && ST.hasMFMAInlineLiteralBug() &&
        OpNo == (unsigned)AMDGPU::getNamedOperandIdx(InstDesc.getOpcode(),
                                                     AMDGPU::OpName::src2))
      return false;
    return RI.opCanUseInlineConstant(OpInfo.OperandType);
  }

  return isLiteralOperandLegal(InstDesc, OpInfo);
}

bool SIInstrInfo::isImmOperandLegal(const MCInstrDesc &InstDesc, unsigned OpNo,
                                    const MachineOperand &MO) const {
  if (MO.isImm())
    return isImmOperandLegal(InstDesc, OpNo, MO.getImm());

  assert((MO.isTargetIndex() || MO.isFI() || MO.isGlobal()) &&
         "unexpected imm-like operand kind");
  const MCOperandInfo &OpInfo = InstDesc.operands()[OpNo];
  return isLiteralOperandLegal(InstDesc, OpInfo);
}

bool SIInstrInfo::isLegalAV64PseudoImm(uint64_t Imm) const {
  // 2 32-bit inline constants packed into one.
  return AMDGPU::isInlinableLiteral32(Lo_32(Imm), ST.hasInv2PiInlineImm()) &&
         AMDGPU::isInlinableLiteral32(Hi_32(Imm), ST.hasInv2PiInlineImm());
}

bool SIInstrInfo::hasVALU32BitEncoding(unsigned Opcode) const {
  // GFX90A does not have V_MUL_LEGACY_F32_e32.
  if (Opcode == AMDGPU::V_MUL_LEGACY_F32_e64 && ST.hasGFX90AInsts())
    return false;

  int Op32 = AMDGPU::getVOPe32(Opcode);
  if (Op32 == -1)
    return false;

  return pseudoToMCOpcode(Op32) != -1;
}

bool SIInstrInfo::hasModifiers(unsigned Opcode) const {
  // The src0_modifier operand is present on all instructions
  // that have modifiers.

  return AMDGPU::hasNamedOperand(Opcode, AMDGPU::OpName::src0_modifiers);
}

bool SIInstrInfo::hasModifiersSet(const MachineInstr &MI,
                                  AMDGPU::OpName OpName) const {
  const MachineOperand *Mods = getNamedOperand(MI, OpName);
  return Mods && Mods->getImm();
}

bool SIInstrInfo::hasAnyModifiersSet(const MachineInstr &MI) const {
  return any_of(ModifierOpNames,
                [&](AMDGPU::OpName Name) { return hasModifiersSet(MI, Name); });
}

bool SIInstrInfo::canShrink(const MachineInstr &MI,
                            const MachineRegisterInfo &MRI) const {
  const MachineOperand *Src2 = getNamedOperand(MI, AMDGPU::OpName::src2);
  // Can't shrink instruction with three operands.
  if (Src2) {
    switch (MI.getOpcode()) {
      default: return false;

      case AMDGPU::V_ADDC_U32_e64:
      case AMDGPU::V_SUBB_U32_e64:
      case AMDGPU::V_SUBBREV_U32_e64: {
        const MachineOperand *Src1
          = getNamedOperand(MI, AMDGPU::OpName::src1);
        if (!Src1->isReg() || !RI.isVGPR(MRI, Src1->getReg()))
          return false;
        // Additional verification is needed for sdst/src2.
        return true;
      }
      case AMDGPU::V_MAC_F16_e64:
      case AMDGPU::V_MAC_F32_e64:
      case AMDGPU::V_MAC_LEGACY_F32_e64:
      case AMDGPU::V_FMAC_F16_e64:
      case AMDGPU::V_FMAC_F16_t16_e64:
      case AMDGPU::V_FMAC_F16_fake16_e64:
      case AMDGPU::V_FMAC_F32_e64:
      case AMDGPU::V_FMAC_F64_e64:
      case AMDGPU::V_FMAC_LEGACY_F32_e64:
        if (!Src2->isReg() || !RI.isVGPR(MRI, Src2->getReg()) ||
            hasModifiersSet(MI, AMDGPU::OpName::src2_modifiers))
          return false;
        break;

      case AMDGPU::V_CNDMASK_B32_e64:
        break;
    }
  }

  const MachineOperand *Src1 = getNamedOperand(MI, AMDGPU::OpName::src1);
  if (Src1 && (!Src1->isReg() || !RI.isVGPR(MRI, Src1->getReg()) ||
               hasModifiersSet(MI, AMDGPU::OpName::src1_modifiers)))
    return false;

  // We don't need to check src0, all input types are legal, so just make sure
  // src0 isn't using any modifiers.
  if (hasModifiersSet(MI, AMDGPU::OpName::src0_modifiers))
    return false;

  // Can it be shrunk to a valid 32 bit opcode?
  if (!hasVALU32BitEncoding(MI.getOpcode()))
    return false;

  // Check output modifiers
  return !hasModifiersSet(MI, AMDGPU::OpName::omod) &&
         !hasModifiersSet(MI, AMDGPU::OpName::clamp) &&
         !hasModifiersSet(MI, AMDGPU::OpName::byte_sel) &&
         // TODO: Can we avoid checking bound_ctrl/fi here?
         // They are only used by permlane*_swap special case.
         !hasModifiersSet(MI, AMDGPU::OpName::bound_ctrl) &&
         !hasModifiersSet(MI, AMDGPU::OpName::fi);
}

// Set VCC operand with all flags from \p Orig, except for setting it as
// implicit.
static void copyFlagsToImplicitVCC(MachineInstr &MI,
                                   const MachineOperand &Orig) {

  for (MachineOperand &Use : MI.implicit_operands()) {
    if (Use.isUse() &&
        (Use.getReg() == AMDGPU::VCC || Use.getReg() == AMDGPU::VCC_LO)) {
      Use.setIsUndef(Orig.isUndef());
      Use.setIsKill(Orig.isKill());
      return;
    }
  }
}

MachineInstr *SIInstrInfo::buildShrunkInst(MachineInstr &MI,
                                           unsigned Op32) const {
  MachineBasicBlock *MBB = MI.getParent();

  const MCInstrDesc &Op32Desc = get(Op32);
  MachineInstrBuilder Inst32 =
    BuildMI(*MBB, MI, MI.getDebugLoc(), Op32Desc)
    .setMIFlags(MI.getFlags());

  // Add the dst operand if the 32-bit encoding also has an explicit $vdst.
  // For VOPC instructions, this is replaced by an implicit def of vcc.

  // We assume the defs of the shrunk opcode are in the same order, and the
  // shrunk opcode loses the last def (SGPR def, in the VOP3->VOPC case).
  for (int I = 0, E = Op32Desc.getNumDefs(); I != E; ++I)
    Inst32.add(MI.getOperand(I));

  const MachineOperand *Src2 = getNamedOperand(MI, AMDGPU::OpName::src2);

  int Idx = MI.getNumExplicitDefs();
  for (const MachineOperand &Use : MI.explicit_uses()) {
    int OpTy = MI.getDesc().operands()[Idx++].OperandType;
    if (OpTy == AMDGPU::OPERAND_INPUT_MODS || OpTy == MCOI::OPERAND_IMMEDIATE)
      continue;

    if (&Use == Src2) {
      if (AMDGPU::getNamedOperandIdx(Op32, AMDGPU::OpName::src2) == -1) {
        // In the case of V_CNDMASK_B32_e32, the explicit operand src2 is
        // replaced with an implicit read of vcc or vcc_lo. The implicit read
        // of vcc was already added during the initial BuildMI, but we
        // 1) may need to change vcc to vcc_lo to preserve the original register
        // 2) have to preserve the original flags.
        copyFlagsToImplicitVCC(*Inst32, *Src2);
        continue;
      }
    }

    Inst32.add(Use);
  }

  // FIXME: Losing implicit operands
  fixImplicitOperands(*Inst32);
  return Inst32;
}

bool SIInstrInfo::physRegUsesConstantBus(const MachineOperand &RegOp) const {
  // Null is free
  Register Reg = RegOp.getReg();
  if (Reg == AMDGPU::SGPR_NULL || Reg == AMDGPU::SGPR_NULL64)
    return false;

  // SGPRs use the constant bus

  // FIXME: implicit registers that are not part of the MCInstrDesc's implicit
  // physical register operands should also count, except for exec.
  if (RegOp.isImplicit())
    return Reg == AMDGPU::VCC || Reg == AMDGPU::VCC_LO || Reg == AMDGPU::M0;

  // SGPRs use the constant bus
  return AMDGPU::SReg_32RegClass.contains(Reg) ||
         AMDGPU::SReg_64RegClass.contains(Reg);
}

bool SIInstrInfo::regUsesConstantBus(const MachineOperand &RegOp,
                                     const MachineRegisterInfo &MRI) const {
  Register Reg = RegOp.getReg();
  return Reg.isVirtual() ? RI.isSGPRClass(MRI.getRegClass(Reg))
                         : physRegUsesConstantBus(RegOp);
}

bool SIInstrInfo::usesConstantBus(const MachineRegisterInfo &MRI,
                                  const MachineOperand &MO,
                                  const MCOperandInfo &OpInfo) const {
  // Literal constants use the constant bus.
  if (!MO.isReg())
    return !isInlineConstant(MO, OpInfo);

  Register Reg = MO.getReg();
  return Reg.isVirtual() ? RI.isSGPRClass(MRI.getRegClass(Reg))
                         : physRegUsesConstantBus(MO);
}

static Register findImplicitSGPRRead(const MachineInstr &MI) {
  for (const MachineOperand &MO : MI.implicit_operands()) {
    // We only care about reads.
    if (MO.isDef())
      continue;

    switch (MO.getReg()) {
    case AMDGPU::VCC:
    case AMDGPU::VCC_LO:
    case AMDGPU::VCC_HI:
    case AMDGPU::M0:
    case AMDGPU::FLAT_SCR:
      return MO.getReg();

    default:
      break;
    }
  }

  return Register();
}

static bool shouldReadExec(const MachineInstr &MI) {
  if (SIInstrInfo::isVALU(MI, /*AllowLDSDMA=*/true)) {
    switch (MI.getOpcode()) {
    case AMDGPU::V_READLANE_B32:
    case AMDGPU::SI_RESTORE_S32_FROM_VGPR:
    case AMDGPU::V_WRITELANE_B32:
    case AMDGPU::SI_SPILL_S32_TO_VGPR:
      return false;
    }

    return true;
  }

  if (MI.isPreISelOpcode() ||
      SIInstrInfo::isGenericOpcode(MI.getOpcode()) ||
      SIInstrInfo::isSALU(MI) ||
      SIInstrInfo::isSMRD(MI))
    return false;

  return true;
}

static bool isRegOrFI(const MachineOperand &MO) {
  return MO.isReg() || MO.isFI();
}

static bool isSubRegOf(const SIRegisterInfo &TRI,
                       const MachineOperand &SuperVec,
                       const MachineOperand &SubReg) {
  if (SubReg.getReg().isPhysical())
    return TRI.isSubRegister(SuperVec.getReg(), SubReg.getReg());

  return SubReg.getSubReg() != AMDGPU::NoSubRegister &&
         SubReg.getReg() == SuperVec.getReg();
}

// Verify the illegal copy from vector register to SGPR for generic opcode COPY
bool SIInstrInfo::verifyCopy(const MachineInstr &MI,
                             const MachineRegisterInfo &MRI,
                             StringRef &ErrInfo) const {
  Register DstReg = MI.getOperand(0).getReg();
  Register SrcReg = MI.getOperand(1).getReg();
  // This is a check for copy from vector register to SGPR
  if (RI.isVectorRegister(MRI, SrcReg) && RI.isSGPRReg(MRI, DstReg)) {
    ErrInfo = "illegal copy from vector register to SGPR";
    return false;
  }
  return true;
}

bool SIInstrInfo::verifyInstruction(const MachineInstr &MI,
                                    StringRef &ErrInfo) const {
  uint32_t Opcode = MI.getOpcode();
  const MachineFunction *MF = MI.getMF();
  const MachineRegisterInfo &MRI = MF->getRegInfo();

  // FIXME: At this point the COPY verify is done only for non-ssa forms.
  // Find a better property to recognize the point where instruction selection
  // is just done.
  // We can only enforce this check after SIFixSGPRCopies pass so that the
  // illegal copies are legalized and thereafter we don't expect a pass
  // inserting similar copies.
  if (!MRI.isSSA() && MI.isCopy())
    return verifyCopy(MI, MRI, ErrInfo);

  if (SIInstrInfo::isGenericOpcode(Opcode))
    return true;

  int Src0Idx = AMDGPU::getNamedOperandIdx(Opcode, AMDGPU::OpName::src0);
  int Src1Idx = AMDGPU::getNamedOperandIdx(Opcode, AMDGPU::OpName::src1);
  int Src2Idx = AMDGPU::getNamedOperandIdx(Opcode, AMDGPU::OpName::src2);
  int Src3Idx = -1;
  if (Src0Idx == -1) {
    // VOPD V_DUAL_* instructions use different operand names.
    Src0Idx = AMDGPU::getNamedOperandIdx(Opcode, AMDGPU::OpName::src0X);
    Src1Idx = AMDGPU::getNamedOperandIdx(Opcode, AMDGPU::OpName::vsrc1X);
    Src2Idx = AMDGPU::getNamedOperandIdx(Opcode, AMDGPU::OpName::src0Y);
    Src3Idx = AMDGPU::getNamedOperandIdx(Opcode, AMDGPU::OpName::vsrc1Y);
  }

  // Make sure the number of operands is correct.
  const MCInstrDesc &Desc = get(Opcode);
  if (!Desc.isVariadic() &&
      Desc.getNumOperands() != MI.getNumExplicitOperands()) {
    ErrInfo = "Instruction has wrong number of operands.";
    return false;
  }

  if (MI.isInlineAsm()) {
    // Verify register classes for inlineasm constraints.
    for (unsigned I = InlineAsm::MIOp_FirstOperand, E = MI.getNumOperands();
         I != E; ++I) {
      const TargetRegisterClass *RC = MI.getRegClassConstraint(I, this, &RI);
      if (!RC)
        continue;

      const MachineOperand &Op = MI.getOperand(I);
      if (!Op.isReg())
        continue;

      Register Reg = Op.getReg();
      if (!Reg.isVirtual() && !RC->contains(Reg)) {
        ErrInfo = "inlineasm operand has incorrect register class.";
        return false;
      }
    }

    return true;
  }

  if (isImage(MI) && MI.memoperands_empty() && MI.mayLoadOrStore()) {
    ErrInfo = "missing memory operand from image instruction.";
    return false;
  }

  // Make sure the register classes are correct.
  for (int i = 0, e = Desc.getNumOperands(); i != e; ++i) {
    const MachineOperand &MO = MI.getOperand(i);
    if (MO.isFPImm()) {
      ErrInfo = "FPImm Machine Operands are not supported. ISel should bitcast "
                "all fp values to integers.";
      return false;
    }

    const MCOperandInfo &OpInfo = Desc.operands()[i];
    int16_t RegClass = getOpRegClassID(OpInfo);

    switch (OpInfo.OperandType) {
    case MCOI::OPERAND_REGISTER:
      if (MI.getOperand(i).isImm() || MI.getOperand(i).isGlobal()) {
        ErrInfo = "Illegal immediate value for operand.";
        return false;
      }
      break;
    case AMDGPU::OPERAND_REG_IMM_INT32:
    case AMDGPU::OPERAND_REG_IMM_INT16:
    case AMDGPU::OPERAND_REG_IMM_FP32:
    case AMDGPU::OPERAND_REG_IMM_BF16:
    case AMDGPU::OPERAND_REG_IMM_FP16:
    case AMDGPU::OPERAND_REG_IMM_V2FP16:
    case AMDGPU::OPERAND_REG_IMM_V2FP16_SPLAT:
    case AMDGPU::OPERAND_REG_IMM_V2INT16:
    case AMDGPU::OPERAND_REG_IMM_V2BF16:
    case AMDGPU::OPERAND_REG_IMM_V2FP64:
    case AMDGPU::OPERAND_REG_IMM_V2INT64:
      break;
    case AMDGPU::OPERAND_REG_IMM_NOINLINE_V2FP16:
      break;
      break;
    case AMDGPU::OPERAND_REG_INLINE_C_INT16:
    case AMDGPU::OPERAND_REG_INLINE_C_INT32:
    case AMDGPU::OPERAND_REG_INLINE_C_INT64:
    case AMDGPU::OPERAND_REG_INLINE_C_FP32:
    case AMDGPU::OPERAND_REG_INLINE_C_FP64:
    case AMDGPU::OPERAND_REG_INLINE_C_BF16:
    case AMDGPU::OPERAND_REG_INLINE_C_FP16:
    case AMDGPU::OPERAND_REG_INLINE_C_V2INT16:
    case AMDGPU::OPERAND_REG_INLINE_C_V2BF16:
    case AMDGPU::OPERAND_REG_INLINE_C_V2FP16:
    case AMDGPU::OPERAND_REG_INLINE_AC_INT32:
    case AMDGPU::OPERAND_REG_INLINE_AC_FP32:
    case AMDGPU::OPERAND_REG_INLINE_AC_FP64: {
      if (!MO.isReg() && (!MO.isImm() || !isInlineConstant(MI, i))) {
        ErrInfo = "Illegal immediate value for operand.";
        return false;
      }
      break;
    }
    case AMDGPU::OPERAND_REG_IMM_FP64:
    case AMDGPU::OPERAND_REG_IMM_INT64:
    case AMDGPU::OPERAND_REG_IMM_V2INT32:
    case AMDGPU::OPERAND_REG_IMM_V2FP32:
      if (ST.has64BitLiterals() && Desc.getSize() != 4 && MO.isImm() &&
          !isInlineConstant(MI, i) &&
          !AMDGPU::isValid32BitLiteral(MO.getImm(),
                                       OpInfo.OperandType ==
                                           AMDGPU::OPERAND_REG_IMM_FP64)) {
        ErrInfo = "illegal 64-bit immediate value for operand.";
        return false;
      }
      break;
    case AMDGPU::OPERAND_INLINE_SPLIT_BARRIER_INT32:
    case AMDGPU::OPERAND_INPUT_MODS:
      if (!MI.getOperand(i).isImm() || !isInlineConstant(MI, i)) {
        ErrInfo = "Expected inline constant for operand.";
        return false;
      }
      break;
    case AMDGPU::OPERAND_SDWA_VOPC_DST:
    case AMDGPU::OPERAND_KIMM16:
      break;
    case MCOI::OPERAND_IMMEDIATE:
    case AMDGPU::OPERAND_KIMM32:
    case AMDGPU::OPERAND_KIMM64:
    case AMDGPU::OPERAND_INLINE_C_AV64_PSEUDO:
      // Check if this operand is an immediate.
      // FrameIndex operands will be replaced by immediates, so they are
      // allowed.
      if (!MI.getOperand(i).isImm() && !MI.getOperand(i).isFI()) {
        ErrInfo = "Expected immediate, but got non-immediate";
        return false;
      }
      break;
    case MCOI::OPERAND_UNKNOWN:
    case MCOI::OPERAND_MEMORY:
    case MCOI::OPERAND_PCREL:
      break;
    default:
      if (OpInfo.isGenericType())
        continue;
      break;
    }

    if (!MO.isReg())
      continue;
    Register Reg = MO.getReg();
    if (!Reg)
      continue;

    // FIXME: Ideally we would have separate instruction definitions with the
    // aligned register constraint.
    // FIXME: We do not verify inline asm operands, but custom inline asm
    // verification is broken anyway
    if (ST.needsAlignedVGPRs() && Opcode != AMDGPU::AV_MOV_B64_IMM_PSEUDO &&
        Opcode != AMDGPU::V_MOV_B64_PSEUDO && !isSpill(MI)) {
      const TargetRegisterClass *RC = RI.getRegClassForReg(MRI, Reg);
      if (RI.hasVectorRegisters(RC) && MO.getSubReg()) {
        if (const TargetRegisterClass *SubRC =
                RI.getSubRegisterClass(RC, MO.getSubReg())) {
          RC = RI.getCompatibleSubRegClass(RC, SubRC, MO.getSubReg());
          if (RC)
            RC = SubRC;
        }
      }

      // Check that this is the aligned version of the class.
      if (!RC || !RI.isProperlyAlignedRC(*RC)) {
        ErrInfo = "Subtarget requires even aligned vector registers";
        return false;
      }
    }

    if (RegClass != -1) {
      if (Reg.isVirtual())
        continue;

      const TargetRegisterClass *RC = RI.getRegClass(RegClass);
      if (!RC->contains(Reg)) {
        ErrInfo = "Operand has incorrect register class.";
        return false;
      }
    }
  }

  // Verify SDWA
  if (isSDWA(MI)) {
    if (!ST.hasSDWA()) {
      ErrInfo = "SDWA is not supported on this target";
      return false;
    }

    for (auto Op : {AMDGPU::OpName::src0_sel, AMDGPU::OpName::src1_sel,
                    AMDGPU::OpName::dst_sel}) {
      const MachineOperand *MO = getNamedOperand(MI, Op);
      if (!MO)
        continue;
      int64_t Imm = MO->getImm();
      if (Imm < 0 || Imm > AMDGPU::SDWA::SdwaSel::DWORD) {
        ErrInfo = "Invalid SDWA selection";
        return false;
      }
    }

    int DstIdx = AMDGPU::getNamedOperandIdx(Opcode, AMDGPU::OpName::vdst);

    for (int OpIdx : {DstIdx, Src0Idx, Src1Idx, Src2Idx}) {
      if (OpIdx == -1)
        continue;
      const MachineOperand &MO = MI.getOperand(OpIdx);

      if (!ST.hasSDWAScalar()) {
        // Only VGPRS on VI
        if (!MO.isReg() || !RI.hasVGPRs(RI.getRegClassForReg(MRI, MO.getReg()))) {
          ErrInfo = "Only VGPRs allowed as operands in SDWA instructions on VI";
          return false;
        }
      } else {
        // No immediates on GFX9
        if (!MO.isReg()) {
          ErrInfo =
            "Only reg allowed as operands in SDWA instructions on GFX9+";
          return false;
        }
      }
    }

    if (!ST.hasSDWAOmod()) {
      // No omod allowed on VI
      const MachineOperand *OMod = getNamedOperand(MI, AMDGPU::OpName::omod);
      if (OMod != nullptr &&
        (!OMod->isImm() || OMod->getImm() != 0)) {
        ErrInfo = "OMod not allowed in SDWA instructions on VI";
        return false;
      }
    }

    if (Opcode == AMDGPU::V_CVT_F32_FP8_sdwa ||
        Opcode == AMDGPU::V_CVT_F32_BF8_sdwa ||
        Opcode == AMDGPU::V_CVT_PK_F32_FP8_sdwa ||
        Opcode == AMDGPU::V_CVT_PK_F32_BF8_sdwa) {
      const MachineOperand *Src0ModsMO =
          getNamedOperand(MI, AMDGPU::OpName::src0_modifiers);
      unsigned Mods = Src0ModsMO->getImm();
      if (Mods & SISrcMods::ABS || Mods & SISrcMods::NEG ||
          Mods & SISrcMods::SEXT) {
        ErrInfo = "sext, abs and neg are not allowed on this instruction";
        return false;
      }
    }

    uint32_t BasicOpcode = AMDGPU::getBasicFromSDWAOp(Opcode);
    if (isVOPC(BasicOpcode)) {
      if (!ST.hasSDWASdst() && DstIdx != -1) {
        // Only vcc allowed as dst on VI for VOPC
        const MachineOperand &Dst = MI.getOperand(DstIdx);
        if (!Dst.isReg() || Dst.getReg() != AMDGPU::VCC) {
          ErrInfo = "Only VCC allowed as dst in SDWA instructions on VI";
          return false;
        }
      } else if (!ST.hasSDWAOutModsVOPC()) {
        // No clamp allowed on GFX9 for VOPC
        const MachineOperand *Clamp = getNamedOperand(MI, AMDGPU::OpName::clamp);
        if (Clamp && (!Clamp->isImm() || Clamp->getImm() != 0)) {
          ErrInfo = "Clamp not allowed in VOPC SDWA instructions on VI";
          return false;
        }

        // No omod allowed on GFX9 for VOPC
        const MachineOperand *OMod = getNamedOperand(MI, AMDGPU::OpName::omod);
        if (OMod && (!OMod->isImm() || OMod->getImm() != 0)) {
          ErrInfo = "OMod not allowed in VOPC SDWA instructions on VI";
          return false;
        }
      }
    }

    const MachineOperand *DstUnused = getNamedOperand(MI, AMDGPU::OpName::dst_unused);
    if (DstUnused && DstUnused->isImm() &&
        DstUnused->getImm() == AMDGPU::SDWA::UNUSED_PRESERVE) {
      const MachineOperand &Dst = MI.getOperand(DstIdx);
      if (!Dst.isReg() || !Dst.isTied()) {
        ErrInfo = "Dst register should have tied register";
        return false;
      }

      const MachineOperand &TiedMO =
          MI.getOperand(MI.findTiedOperandIdx(DstIdx));
      if (!TiedMO.isReg() || !TiedMO.isImplicit() || !TiedMO.isUse()) {
        ErrInfo =
            "Dst register should be tied to implicit use of preserved register";
        return false;
      }
      if (TiedMO.getReg().isPhysical() && Dst.getReg() != TiedMO.getReg()) {
        ErrInfo = "Dst register should use same physical register as preserved";
        return false;
      }
    }
  }

  if (isDPP(MI) && !ST.hasDPPSrc1SGPR() && Src1Idx != -1) {
    const MachineOperand &Src1MO = MI.getOperand(Src1Idx);
    if (Src1MO.isReg() && RI.isSGPRReg(MRI, Src1MO.getReg())) {
      ErrInfo = "DPP src1 cannot be SGPR on this subtarget";
      return false;
    }
    if (Src1MO.isImm()) {
      ErrInfo = "DPP src1 cannot be an immediate on this subtarget";
      return false;
    }
  }

  // Verify MIMG / VIMAGE / VSAMPLE
  if (isImage(Opcode) && !MI.mayStore()) {
    // Ensure that the return type used is large enough for all the options
    // being used TFE/LWE require an extra result register.
    const MachineOperand *DMask = getNamedOperand(MI, AMDGPU::OpName::dmask);
    if (DMask) {
      uint64_t DMaskImm = DMask->getImm();
      uint32_t RegCount = isGather4(Opcode) ? 4 : llvm::popcount(DMaskImm);
      const MachineOperand *TFE = getNamedOperand(MI, AMDGPU::OpName::tfe);
      const MachineOperand *LWE = getNamedOperand(MI, AMDGPU::OpName::lwe);
      const MachineOperand *D16 = getNamedOperand(MI, AMDGPU::OpName::d16);

      // Adjust for packed 16 bit values
      if (D16 && D16->getImm() && !ST.hasUnpackedD16VMem())
        RegCount = divideCeil(RegCount, 2);

      // Adjust if using LWE or TFE
      if ((LWE && LWE->getImm()) || (TFE && TFE->getImm()))
        RegCount += 1;

      const uint32_t DstIdx =
          AMDGPU::getNamedOperandIdx(Opcode, AMDGPU::OpName::vdata);
      const MachineOperand &Dst = MI.getOperand(DstIdx);
      if (Dst.isReg()) {
        const TargetRegisterClass *DstRC = getOpRegClass(MI, DstIdx);
        uint32_t DstSize = RI.getRegSizeInBits(*DstRC) / 32;
        if (RegCount > DstSize) {
          ErrInfo = "Image instruction returns too many registers for dst "
                    "register class";
          return false;
        }
      }
    }
  }

  // Verify VOP*. Ignore multiple sgpr operands on writelane.
  if (isVALU(MI, /*AllowLDSDMA=*/true) &&
      Desc.getOpcode() != AMDGPU::V_WRITELANE_B32) {
    unsigned ConstantBusCount = 0;
    bool UsesLiteral = false;
    const MachineOperand *LiteralVal = nullptr;

    int ImmIdx = AMDGPU::getNamedOperandIdx(Opcode, AMDGPU::OpName::imm);
    if (ImmIdx != -1) {
      ++ConstantBusCount;
      UsesLiteral = true;
      LiteralVal = &MI.getOperand(ImmIdx);
    }

    SmallVector<Register, 2> SGPRsUsed;
    Register SGPRUsed;

    // Only look at the true operands. Only a real operand can use the constant
    // bus, and we don't want to check pseudo-operands like the source modifier
    // flags.
    for (int OpIdx : {Src0Idx, Src1Idx, Src2Idx, Src3Idx}) {
      if (OpIdx == -1)
        continue;
      const MachineOperand &MO = MI.getOperand(OpIdx);
      if (usesConstantBus(MRI, MO, MI.getDesc().operands()[OpIdx])) {
        if (MO.isReg()) {
          SGPRUsed = MO.getReg();
          if (!llvm::is_contained(SGPRsUsed, SGPRUsed)) {
            ++ConstantBusCount;
            SGPRsUsed.push_back(SGPRUsed);
          }
        } else if (!MO.isFI()) { // Treat FI like a register.
          if (!UsesLiteral) {
            ++ConstantBusCount;
            UsesLiteral = true;
            LiteralVal = &MO;
          } else if (!MO.isIdenticalTo(*LiteralVal)) {
            assert(isVOP2(MI) || isVOP3(MI));
            ErrInfo = "VOP2/VOP3 instruction uses more than one literal";
            return false;
          }
        }
      }
    }

    SGPRUsed = findImplicitSGPRRead(MI);
    if (SGPRUsed) {
      // Implicit uses may safely overlap true operands
      if (llvm::all_of(SGPRsUsed, [this, SGPRUsed](unsigned SGPR) {
            return !RI.regsOverlap(SGPRUsed, SGPR);
          })) {
        ++ConstantBusCount;
        SGPRsUsed.push_back(SGPRUsed);
      }
    }

    // v_writelane_b32 is an exception from constant bus restriction:
    // vsrc0 can be sgpr, const or m0 and lane select sgpr, m0 or inline-const
    if (ConstantBusCount > ST.getConstantBusLimit(Opcode) &&
        Opcode != AMDGPU::V_WRITELANE_B32) {
      ErrInfo = "VOP* instruction violates constant bus restriction";
      return false;
    }

    if (isVOP3(MI) && UsesLiteral && !ST.hasVOP3Literal()) {
      ErrInfo = "VOP3 instruction uses literal";
      return false;
    }
  }

  // Special case for writelane - this can break the multiple constant bus rule,
  // but still can't use more than one SGPR register
  if (Desc.getOpcode() == AMDGPU::V_WRITELANE_B32) {
    unsigned SGPRCount = 0;
    Register SGPRUsed;

    for (int OpIdx : {Src0Idx, Src1Idx}) {
      if (OpIdx == -1)
        break;

      const MachineOperand &MO = MI.getOperand(OpIdx);

      if (usesConstantBus(MRI, MO, MI.getDesc().operands()[OpIdx])) {
        if (MO.isReg() && MO.getReg() != AMDGPU::M0) {
          if (MO.getReg() != SGPRUsed)
            ++SGPRCount;
          SGPRUsed = MO.getReg();
        }
      }
      if (SGPRCount > ST.getConstantBusLimit(Opcode)) {
        ErrInfo = "WRITELANE instruction violates constant bus restriction";
        return false;
      }
    }
  }

  // Verify misc. restrictions on specific instructions.
  if (Desc.getOpcode() == AMDGPU::V_DIV_SCALE_F32_e64 ||
      Desc.getOpcode() == AMDGPU::V_DIV_SCALE_F64_e64) {
    const MachineOperand &Src0 = MI.getOperand(Src0Idx);
    const MachineOperand &Src1 = MI.getOperand(Src1Idx);
    const MachineOperand &Src2 = MI.getOperand(Src2Idx);
    if (Src0.isReg() && Src1.isReg() && Src2.isReg()) {
      if (!compareMachineOp(Src0, Src1) &&
          !compareMachineOp(Src0, Src2)) {
        ErrInfo = "v_div_scale_{f32|f64} require src0 = src1 or src2";
        return false;
      }
    }
    if ((getNamedOperand(MI, AMDGPU::OpName::src0_modifiers)->getImm() &
         SISrcMods::ABS) ||
        (getNamedOperand(MI, AMDGPU::OpName::src1_modifiers)->getImm() &
         SISrcMods::ABS) ||
        (getNamedOperand(MI, AMDGPU::OpName::src2_modifiers)->getImm() &
         SISrcMods::ABS)) {
      ErrInfo = "ABS not allowed in VOP3B instructions";
      return false;
    }
  }

  if (isSOP2(MI) || isSOPC(MI)) {
    const MachineOperand &Src0 = MI.getOperand(Src0Idx);
    const MachineOperand &Src1 = MI.getOperand(Src1Idx);

    if (!isRegOrFI(Src0) && !isRegOrFI(Src1) &&
        !isInlineConstant(Src0, Desc.operands()[Src0Idx]) &&
        !isInlineConstant(Src1, Desc.operands()[Src1Idx]) &&
        !Src0.isIdenticalTo(Src1)) {
      ErrInfo = "SOP2/SOPC instruction requires too many immediate constants";
      return false;
    }
  }

  if (isSOPK(MI)) {
    const auto *Op = getNamedOperand(MI, AMDGPU::OpName::simm16);
    if (Desc.isBranch()) {
      if (!Op->isMBB()) {
        ErrInfo = "invalid branch target for SOPK instruction";
        return false;
      }
    } else {
      uint64_t Imm = Op->getImm();
      if (sopkIsZext(Opcode)) {
        if (!isUInt<16>(Imm)) {
          ErrInfo = "invalid immediate for SOPK instruction";
          return false;
        }
      } else {
        if (!isInt<16>(Imm)) {
          ErrInfo = "invalid immediate for SOPK instruction";
          return false;
        }
      }
    }
  }

  if (Desc.getOpcode() == AMDGPU::V_MOVRELS_B32_e32 ||
      Desc.getOpcode() == AMDGPU::V_MOVRELS_B32_e64 ||
      Desc.getOpcode() == AMDGPU::V_MOVRELD_B32_e32 ||
      Desc.getOpcode() == AMDGPU::V_MOVRELD_B32_e64) {
    const bool IsDst = Desc.getOpcode() == AMDGPU::V_MOVRELD_B32_e32 ||
                       Desc.getOpcode() == AMDGPU::V_MOVRELD_B32_e64;

    const unsigned StaticNumOps =
        Desc.getNumOperands() + Desc.implicit_uses().size();
    const unsigned NumImplicitOps = IsDst ? 2 : 1;

    // Require additional implicit operands. This allows a fixup done by the
    // post RA scheduler where the main implicit operand is killed and
    // implicit-defs are added for sub-registers that remain live after this
    // instruction.
    if (MI.getNumOperands() < StaticNumOps + NumImplicitOps) {
      ErrInfo = "missing implicit register operands";
      return false;
    }

    const MachineOperand *Dst = getNamedOperand(MI, AMDGPU::OpName::vdst);
    if (IsDst) {
      if (!Dst->isUse()) {
        ErrInfo = "v_movreld_b32 vdst should be a use operand";
        return false;
      }

      unsigned UseOpIdx;
      if (!MI.isRegTiedToUseOperand(StaticNumOps, &UseOpIdx) ||
          UseOpIdx != StaticNumOps + 1) {
        ErrInfo = "movrel implicit operands should be tied";
        return false;
      }
    }

    const MachineOperand &Src0 = MI.getOperand(Src0Idx);
    const MachineOperand &ImpUse
      = MI.getOperand(StaticNumOps + NumImplicitOps - 1);
    if (!ImpUse.isReg() || !ImpUse.isUse() ||
        !isSubRegOf(RI, ImpUse, IsDst ? *Dst : Src0)) {
      ErrInfo = "src0 should be subreg of implicit vector use";
      return false;
    }
  }

  // Make sure we aren't losing exec uses in the td files. This mostly requires
  // being careful when using let Uses to try to add other use registers.
  if (shouldReadExec(MI)) {
    if (!MI.hasRegisterImplicitUseOperand(AMDGPU::EXEC)) {
      ErrInfo = "VALU instruction does not implicitly read exec mask";
      return false;
    }
  }

  if (isSMRD(MI)) {
    if (MI.mayStore() &&
        ST.getGeneration() == AMDGPUSubtarget::VOLCANIC_ISLANDS) {
      // The register offset form of scalar stores may only use m0 as the
      // soffset register.
      const MachineOperand *Soff = getNamedOperand(MI, AMDGPU::OpName::soffset);
      if (Soff && Soff->getReg() != AMDGPU::M0) {
        ErrInfo = "scalar stores must use m0 as offset register";
        return false;
      }
    }
  }

  if (isFLAT(MI) && !ST.hasFlatInstOffsets()) {
    const MachineOperand *Offset = getNamedOperand(MI, AMDGPU::OpName::offset);
    if (Offset->getImm() != 0) {
      ErrInfo = "subtarget does not support offsets in flat instructions";
      return false;
    }
  }

  if (isDS(MI) && !ST.hasGDS()) {
    const MachineOperand *GDSOp = getNamedOperand(MI, AMDGPU::OpName::gds);
    if (GDSOp && GDSOp->getImm() != 0) {
      ErrInfo = "GDS is not supported on this subtarget";
      return false;
    }
  }

  if (isImage(MI)) {
    const MachineOperand *DimOp = getNamedOperand(MI, AMDGPU::OpName::dim);
    if (DimOp) {
      int VAddr0Idx = AMDGPU::getNamedOperandIdx(Opcode,
                                                 AMDGPU::OpName::vaddr0);
      AMDGPU::OpName RSrcOpName =
          isMIMG(MI) ? AMDGPU::OpName::srsrc : AMDGPU::OpName::rsrc;
      int RsrcIdx = AMDGPU::getNamedOperandIdx(Opcode, RSrcOpName);
      const AMDGPU::MIMGInfo *Info = AMDGPU::getMIMGInfo(Opcode);
      const AMDGPU::MIMGBaseOpcodeInfo *BaseOpcode =
          AMDGPU::getMIMGBaseOpcodeInfo(Info->BaseOpcode);
      const AMDGPU::MIMGDimInfo *Dim =
          AMDGPU::getMIMGDimInfoByEncoding(DimOp->getImm());

      if (!Dim) {
        ErrInfo = "dim is out of range";
        return false;
      }

      bool IsA16 = false;
      if (ST.hasR128A16()) {
        const MachineOperand *R128A16 = getNamedOperand(MI, AMDGPU::OpName::r128);
        IsA16 = R128A16->getImm() != 0;
      } else if (ST.hasA16()) {
        const MachineOperand *A16 = getNamedOperand(MI, AMDGPU::OpName::a16);
        IsA16 = A16->getImm() != 0;
      }

      bool IsNSA = RsrcIdx - VAddr0Idx > 1;

      unsigned AddrWords =
          AMDGPU::getAddrSizeMIMGOp(BaseOpcode, Dim, IsA16, ST.hasG16());

      unsigned VAddrWords;
      if (IsNSA) {
        VAddrWords = RsrcIdx - VAddr0Idx;
        if (ST.hasPartialNSAEncoding() &&
            AddrWords > ST.getNSAMaxSize(isVSAMPLE(MI))) {
          unsigned LastVAddrIdx = RsrcIdx - 1;
          VAddrWords += getOpSize(MI, LastVAddrIdx) / 4 - 1;
        }
      } else {
        VAddrWords = getOpSize(MI, VAddr0Idx) / 4;
        if (AddrWords > 12)
          AddrWords = 16;
      }

      if (VAddrWords != AddrWords) {
        LLVM_DEBUG(dbgs() << "bad vaddr size, expected " << AddrWords
                          << " but got " << VAddrWords << "\n");
        ErrInfo = "bad vaddr size";
        return false;
      }
    }
  }

  const MachineOperand *DppCt = getNamedOperand(MI, AMDGPU::OpName::dpp_ctrl);
  if (DppCt) {
    using namespace AMDGPU::DPP;

    unsigned DC = DppCt->getImm();
    if (DC == DppCtrl::DPP_UNUSED1 || DC == DppCtrl::DPP_UNUSED2 ||
        DC == DppCtrl::DPP_UNUSED3 || DC > DppCtrl::DPP_LAST ||
        (DC >= DppCtrl::DPP_UNUSED4_FIRST && DC <= DppCtrl::DPP_UNUSED4_LAST) ||
        (DC >= DppCtrl::DPP_UNUSED5_FIRST && DC <= DppCtrl::DPP_UNUSED5_LAST) ||
        (DC >= DppCtrl::DPP_UNUSED6_FIRST && DC <= DppCtrl::DPP_UNUSED6_LAST) ||
        (DC >= DppCtrl::DPP_UNUSED7_FIRST && DC <= DppCtrl::DPP_UNUSED7_LAST) ||
        (DC >= DppCtrl::DPP_UNUSED8_FIRST && DC <= DppCtrl::DPP_UNUSED8_LAST)) {
      ErrInfo = "Invalid dpp_ctrl value";
      return false;
    }
    if (DC >= DppCtrl::WAVE_SHL1 && DC <= DppCtrl::WAVE_ROR1 &&
        !ST.hasDPPWavefrontShifts()) {
      ErrInfo = "Invalid dpp_ctrl value: "
                "wavefront shifts are not supported on GFX10+";
      return false;
    }
    if (DC >= DppCtrl::BCAST15 && DC <= DppCtrl::BCAST31 &&
        !ST.hasDPPBroadcasts()) {
      ErrInfo = "Invalid dpp_ctrl value: "
                "broadcasts are not supported on GFX10+";
      return false;
    }
    if (DC >= DppCtrl::ROW_SHARE_FIRST && DC <= DppCtrl::ROW_XMASK_LAST &&
        ST.getGeneration() < AMDGPUSubtarget::GFX10) {
      if (DC >= DppCtrl::ROW_NEWBCAST_FIRST &&
          DC <= DppCtrl::ROW_NEWBCAST_LAST &&
          !ST.hasGFX90AInsts()) {
        ErrInfo = "Invalid dpp_ctrl value: "
                  "row_newbroadcast/row_share is not supported before "
                  "GFX90A/GFX10";
        return false;
      }
      if (DC > DppCtrl::ROW_NEWBCAST_LAST || !ST.hasGFX90AInsts()) {
        ErrInfo = "Invalid dpp_ctrl value: "
                  "row_share and row_xmask are not supported before GFX10";
        return false;
      }
    }

    if (Opcode != AMDGPU::V_MOV_B64_DPP_PSEUDO &&
        !AMDGPU::isLegalDPALU_DPPControl(ST, DC) &&
        AMDGPU::isDPALU_DPP(Desc, *this, ST)) {
      ErrInfo = "Invalid dpp_ctrl value: "
                "DP ALU dpp only support row_newbcast";
      return false;
    }
  }

  if ((MI.mayStore() || MI.mayLoad()) && !isVGPRSpill(MI)) {
    const MachineOperand *Dst = getNamedOperand(MI, AMDGPU::OpName::vdst);
    AMDGPU::OpName DataName =
        isDS(Opcode) ? AMDGPU::OpName::data0 : AMDGPU::OpName::vdata;
    const MachineOperand *Data = getNamedOperand(MI, DataName);
    const MachineOperand *Data2 = getNamedOperand(MI, AMDGPU::OpName::data1);
    if (Data && !Data->isReg())
      Data = nullptr;

    if (ST.hasGFX90AInsts()) {
      if (Dst && Data && !Dst->isTied() && !Data->isTied() &&
          (RI.isAGPR(MRI, Dst->getReg()) != RI.isAGPR(MRI, Data->getReg()))) {
        ErrInfo = "Invalid register class: "
                  "vdata and vdst should be both VGPR or AGPR";
        return false;
      }
      if (Data && Data2 &&
          (RI.isAGPR(MRI, Data->getReg()) != RI.isAGPR(MRI, Data2->getReg()))) {
        ErrInfo = "Invalid register class: "
                  "both data operands should be VGPR or AGPR";
        return false;
      }
    } else {
      if ((Dst && RI.isAGPR(MRI, Dst->getReg())) ||
          (Data && RI.isAGPR(MRI, Data->getReg())) ||
          (Data2 && RI.isAGPR(MRI, Data2->getReg()))) {
        ErrInfo = "Invalid register class: "
                  "agpr loads and stores not supported on this GPU";
        return false;
      }
    }
  }

  if (ST.needsAlignedVGPRs()) {
    const auto isAlignedReg = [&MI, &MRI, this](AMDGPU::OpName OpName) -> bool {
      const MachineOperand *Op = getNamedOperand(MI, OpName);
      if (!Op)
        return true;
      Register Reg = Op->getReg();
      if (Reg.isPhysical())
        return !(RI.getHWRegIndex(Reg) & 1);
      const TargetRegisterClass &RC = *MRI.getRegClass(Reg);
      return RI.getRegSizeInBits(RC) > 32 && RI.isProperlyAlignedRC(RC) &&
             !(RI.getChannelFromSubReg(Op->getSubReg()) & 1);
    };

    if (Opcode == AMDGPU::DS_GWS_INIT || Opcode == AMDGPU::DS_GWS_SEMA_BR ||
        Opcode == AMDGPU::DS_GWS_BARRIER) {

      if (!isAlignedReg(AMDGPU::OpName::data0)) {
        ErrInfo = "Subtarget requires even aligned vector registers "
                  "for DS_GWS instructions";
        return false;
      }
    }

    if (isMIMG(MI)) {
      if (!isAlignedReg(AMDGPU::OpName::vaddr)) {
        ErrInfo = "Subtarget requires even aligned vector registers "
                  "for vaddr operand of image instructions";
        return false;
      }
    }
  }

  if (Opcode == AMDGPU::V_ACCVGPR_WRITE_B32_e64 && !ST.hasGFX90AInsts()) {
    const MachineOperand *Src = getNamedOperand(MI, AMDGPU::OpName::src0);
    if (Src->isReg() && RI.isSGPRReg(MRI, Src->getReg())) {
      ErrInfo = "Invalid register class: "
                "v_accvgpr_write with an SGPR is not supported on this GPU";
      return false;
    }
  }

  if (Desc.getOpcode() == AMDGPU::G_AMDGPU_WAVE_ADDRESS) {
    const MachineOperand &SrcOp = MI.getOperand(1);
    if (!SrcOp.isReg() || SrcOp.getReg().isVirtual()) {
      ErrInfo = "pseudo expects only physical SGPRs";
      return false;
    }
  }

  if (const MachineOperand *CPol = getNamedOperand(MI, AMDGPU::OpName::cpol)) {
    if (CPol->getImm() & AMDGPU::CPol::SCAL) {
      if (!ST.hasScaleOffset()) {
        ErrInfo = "Subtarget does not support offset scaling";
        return false;
      }
      if (!AMDGPU::supportsScaleOffset(*this, MI.getOpcode())) {
        ErrInfo = "Instruction does not support offset scaling";
        return false;
      }
    }
  }

  // See SIInstrInfo::isLegalGFX12PlusPackedMathFP32or64BitOperand for more
  // information.
  if (AMDGPU::isPackedFP32or64BitInst(Opcode) && AMDGPU::isGFX12Plus(ST)) {
    for (unsigned I = 0; I < 3; ++I) {
      if (!isLegalGFX12PlusPackedMathFP32or64BitOperand(MRI, MI, I))
        return false;
    }
  }

  if (ST.hasFlatScratchHiInB64InstHazard() && isSALU(MI) &&
      MI.readsRegister(AMDGPU::SRC_FLAT_SCRATCH_BASE_HI, nullptr)) {
    const MachineOperand *Dst = getNamedOperand(MI, AMDGPU::OpName::sdst);
    if ((Dst && RI.getRegClassForReg(MRI, Dst->getReg()) ==
                    &AMDGPU::SReg_64RegClass) ||
        Opcode == AMDGPU::S_BITCMP0_B64 || Opcode == AMDGPU::S_BITCMP1_B64) {
      ErrInfo = "Instruction cannot read flat_scratch_base_hi";
      return false;
    }
  }

  return true;
}

unsigned SIInstrInfo::getVALUOp(const MachineInstr &MI) const {
  if (MI.getOpcode() == AMDGPU::S_MOV_B32) {
    const MachineRegisterInfo &MRI = MI.getMF()->getRegInfo();
    return MI.getOperand(1).isReg() || RI.isAGPR(MRI, MI.getOperand(0).getReg())
               ? AMDGPU::COPY
               : AMDGPU::V_MOV_B32_e32;
  }
  return getVALUOp(MI.getOpcode());
}

// It is more readable to list mapped opcodes on the same line.
// clang-format off

unsigned SIInstrInfo::getVALUOp(unsigned Opc) const {
  switch (Opc) {
  default: return AMDGPU::INSTRUCTION_LIST_END;
  case AMDGPU::REG_SEQUENCE: return AMDGPU::REG_SEQUENCE;
  case AMDGPU::COPY: return AMDGPU::COPY;
  case AMDGPU::PHI: return AMDGPU::PHI;
  case AMDGPU::INSERT_SUBREG: return AMDGPU::INSERT_SUBREG;
  case AMDGPU::WQM: return AMDGPU::WQM;
  case AMDGPU::SOFT_WQM: return AMDGPU::SOFT_WQM;
  case AMDGPU::STRICT_WWM: return AMDGPU::STRICT_WWM;
  case AMDGPU::STRICT_WQM: return AMDGPU::STRICT_WQM;
  case AMDGPU::S_ADD_I32:
    return ST.hasAddNoCarryInsts() ? AMDGPU::V_ADD_U32_e64 : AMDGPU::V_ADD_CO_U32_e32;
  case AMDGPU::S_ADDC_U32:
    return AMDGPU::V_ADDC_U32_e32;
  case AMDGPU::S_SUB_I32:
    return ST.hasAddNoCarryInsts() ? AMDGPU::V_SUB_U32_e64 : AMDGPU::V_SUB_CO_U32_e32;
    // FIXME: These are not consistently handled, and selected when the carry is
    // used.
  case AMDGPU::S_ADD_U32:
    return AMDGPU::V_ADD_CO_U32_e32;
  case AMDGPU::S_SUB_U32:
    return AMDGPU::V_SUB_CO_U32_e32;
  case AMDGPU::S_ADD_U64_PSEUDO:
    return AMDGPU::V_ADD_U64_PSEUDO;
  case AMDGPU::S_SUB_U64_PSEUDO:
    return AMDGPU::V_SUB_U64_PSEUDO;
  case AMDGPU::S_SUBB_U32: return AMDGPU::V_SUBB_U32_e32;
  case AMDGPU::S_MUL_I32: return AMDGPU::V_MUL_LO_U32_e64;
  case AMDGPU::S_MUL_HI_U32: return AMDGPU::V_MUL_HI_U32_e64;
  case AMDGPU::S_MUL_HI_I32: return AMDGPU::V_MUL_HI_I32_e64;
  case AMDGPU::S_AND_B32: return AMDGPU::V_AND_B32_e64;
  case AMDGPU::S_OR_B32: return AMDGPU::V_OR_B32_e64;
  case AMDGPU::S_XOR_B32: return AMDGPU::V_XOR_B32_e64;
  case AMDGPU::S_XNOR_B32:
    return ST.hasDLInsts() ? AMDGPU::V_XNOR_B32_e64 : AMDGPU::INSTRUCTION_LIST_END;
  case AMDGPU::S_MIN_I32: return AMDGPU::V_MIN_I32_e64;
  case AMDGPU::S_MIN_U32: return AMDGPU::V_MIN_U32_e64;
  case AMDGPU::S_MAX_I32: return AMDGPU::V_MAX_I32_e64;
  case AMDGPU::S_MAX_U32: return AMDGPU::V_MAX_U32_e64;
  case AMDGPU::S_ASHR_I32: return AMDGPU::V_ASHR_I32_e32;
  case AMDGPU::S_ASHR_I64: return AMDGPU::V_ASHR_I64_e64;
  case AMDGPU::S_LSHL_B32: return AMDGPU::V_LSHL_B32_e32;
  case AMDGPU::S_LSHL_B64: return AMDGPU::V_LSHL_B64_e64;
  case AMDGPU::S_LSHR_B32: return AMDGPU::V_LSHR_B32_e32;
  case AMDGPU::S_LSHR_B64: return AMDGPU::V_LSHR_B64_e64;
  case AMDGPU::S_SEXT_I32_I8: return AMDGPU::V_BFE_I32_e64;
  case AMDGPU::S_SEXT_I32_I16: return AMDGPU::V_BFE_I32_e64;
  case AMDGPU::S_BFE_U32: return AMDGPU::V_BFE_U32_e64;
  case AMDGPU::S_BFE_I32: return AMDGPU::V_BFE_I32_e64;
  case AMDGPU::S_BFM_B32: return AMDGPU::V_BFM_B32_e64;
  case AMDGPU::S_BREV_B32: return AMDGPU::V_BFREV_B32_e32;
  case AMDGPU::S_NOT_B32: return AMDGPU::V_NOT_B32_e32;
  case AMDGPU::S_NOT_B64: return AMDGPU::V_NOT_B32_e32;
  case AMDGPU::S_CMP_EQ_I32: return AMDGPU::V_CMP_EQ_I32_e64;
  case AMDGPU::S_CMP_LG_I32: return AMDGPU::V_CMP_NE_I32_e64;
  case AMDGPU::S_CMP_GT_I32: return AMDGPU::V_CMP_GT_I32_e64;
  case AMDGPU::S_CMP_GE_I32: return AMDGPU::V_CMP_GE_I32_e64;
  case AMDGPU::S_CMP_LT_I32: return AMDGPU::V_CMP_LT_I32_e64;
  case AMDGPU::S_CMP_LE_I32: return AMDGPU::V_CMP_LE_I32_e64;
  case AMDGPU::S_CMP_EQ_U32: return AMDGPU::V_CMP_EQ_U32_e64;
  case AMDGPU::S_CMP_LG_U32: return AMDGPU::V_CMP_NE_U32_e64;
  case AMDGPU::S_CMP_GT_U32: return AMDGPU::V_CMP_GT_U32_e64;
  case AMDGPU::S_CMP_GE_U32: return AMDGPU::V_CMP_GE_U32_e64;
  case AMDGPU::S_CMP_LT_U32: return AMDGPU::V_CMP_LT_U32_e64;
  case AMDGPU::S_CMP_LE_U32: return AMDGPU::V_CMP_LE_U32_e64;
  case AMDGPU::S_CMP_EQ_U64: return AMDGPU::V_CMP_EQ_U64_e64;
  case AMDGPU::S_CMP_LG_U64: return AMDGPU::V_CMP_NE_U64_e64;
  case AMDGPU::S_BCNT1_I32_B32: return AMDGPU::V_BCNT_U32_B32_e64;
  case AMDGPU::S_FF1_I32_B32: return AMDGPU::V_FFBL_B32_e32;
  case AMDGPU::S_FLBIT_I32_B32: return AMDGPU::V_FFBH_U32_e32;
  case AMDGPU::S_FLBIT_I32: return AMDGPU::V_FFBH_I32_e64;
  case AMDGPU::S_CBRANCH_SCC0: return AMDGPU::S_CBRANCH_VCCZ;
  case AMDGPU::S_CBRANCH_SCC1: return AMDGPU::S_CBRANCH_VCCNZ;
  case AMDGPU::S_CVT_F32_I32: return AMDGPU::V_CVT_F32_I32_e64;
  case AMDGPU::S_CVT_F32_U32: return AMDGPU::V_CVT_F32_U32_e64;
  case AMDGPU::S_CVT_I32_F32: return AMDGPU::V_CVT_I32_F32_e64;
  case AMDGPU::S_CVT_U32_F32: return AMDGPU::V_CVT_U32_F32_e64;
  case AMDGPU::S_CVT_F32_F16:
  case AMDGPU::S_CVT_HI_F32_F16:
    return ST.useRealTrue16Insts() ? AMDGPU::V_CVT_F32_F16_t16_e64
                                   : AMDGPU::V_CVT_F32_F16_fake16_e64;
  case AMDGPU::S_CVT_F16_F32:
    return ST.useRealTrue16Insts() ? AMDGPU::V_CVT_F16_F32_t16_e64
                                   : AMDGPU::V_CVT_F16_F32_fake16_e64;
  case AMDGPU::S_CEIL_F32: return AMDGPU::V_CEIL_F32_e64;
  case AMDGPU::S_FLOOR_F32: return AMDGPU::V_FLOOR_F32_e64;
  case AMDGPU::S_TRUNC_F32: return AMDGPU::V_TRUNC_F32_e64;
  case AMDGPU::S_RNDNE_F32: return AMDGPU::V_RNDNE_F32_e64;
  case AMDGPU::S_CEIL_F16:
    return ST.useRealTrue16Insts() ? AMDGPU::V_CEIL_F16_t16_e64
                                   : AMDGPU::V_CEIL_F16_fake16_e64;
  case AMDGPU::S_FLOOR_F16:
    return ST.useRealTrue16Insts() ? AMDGPU::V_FLOOR_F16_t16_e64
                                   : AMDGPU::V_FLOOR_F16_fake16_e64;
  case AMDGPU::S_TRUNC_F16:
    return ST.useRealTrue16Insts() ? AMDGPU::V_TRUNC_F16_t16_e64
                                   : AMDGPU::V_TRUNC_F16_fake16_e64;
  case AMDGPU::S_RNDNE_F16:
    return ST.useRealTrue16Insts() ? AMDGPU::V_RNDNE_F16_t16_e64
                                   : AMDGPU::V_RNDNE_F16_fake16_e64;
  case AMDGPU::S_ADD_F32: return AMDGPU::V_ADD_F32_e64;
  case AMDGPU::S_SUB_F32: return AMDGPU::V_SUB_F32_e64;
  case AMDGPU::S_MIN_F32: return AMDGPU::V_MIN_F32_e64;
  case AMDGPU::S_MAX_F32: return AMDGPU::V_MAX_F32_e64;
  case AMDGPU::S_MINIMUM_F32: return AMDGPU::V_MINIMUM_F32_e64;
  case AMDGPU::S_MAXIMUM_F32: return AMDGPU::V_MAXIMUM_F32_e64;
  case AMDGPU::S_MUL_F32: return AMDGPU::V_MUL_F32_e64;
  case AMDGPU::S_ADD_F16:
    return ST.useRealTrue16Insts() ? AMDGPU::V_ADD_F16_t16_e64
                                   : AMDGPU::V_ADD_F16_fake16_e64;
  case AMDGPU::S_SUB_F16:
    return ST.useRealTrue16Insts() ? AMDGPU::V_SUB_F16_t16_e64
                                   : AMDGPU::V_SUB_F16_fake16_e64;
  case AMDGPU::S_MIN_F16:
    return ST.useRealTrue16Insts() ? AMDGPU::V_MIN_F16_t16_e64
                                   : AMDGPU::V_MIN_F16_fake16_e64;
  case AMDGPU::S_MAX_F16:
    return ST.useRealTrue16Insts() ? AMDGPU::V_MAX_F16_t16_e64
                                   : AMDGPU::V_MAX_F16_fake16_e64;
  case AMDGPU::S_MINIMUM_F16:
    return ST.useRealTrue16Insts() ? AMDGPU::V_MINIMUM_F16_t16_e64
                                   : AMDGPU::V_MINIMUM_F16_fake16_e64;
  case AMDGPU::S_MAXIMUM_F16:
    return ST.useRealTrue16Insts() ? AMDGPU::V_MAXIMUM_F16_t16_e64
                                   : AMDGPU::V_MAXIMUM_F16_fake16_e64;
  case AMDGPU::S_MUL_F16:
    return ST.useRealTrue16Insts() ? AMDGPU::V_MUL_F16_t16_e64
                                   : AMDGPU::V_MUL_F16_fake16_e64;
  case AMDGPU::S_CVT_PK_RTZ_F16_F32: return AMDGPU::V_CVT_PKRTZ_F16_F32_e64;
  case AMDGPU::S_FMAC_F32: return AMDGPU::V_FMAC_F32_e64;
  case AMDGPU::S_FMAC_F16:
    return ST.useRealTrue16Insts() ? AMDGPU::V_FMAC_F16_t16_e64
                                   : AMDGPU::V_FMAC_F16_fake16_e64;
  case AMDGPU::S_FMAMK_F32: return AMDGPU::V_FMAMK_F32;
  case AMDGPU::S_FMAAK_F32: return AMDGPU::V_FMAAK_F32;
  case AMDGPU::S_CMP_LT_F32: return AMDGPU::V_CMP_LT_F32_e64;
  case AMDGPU::S_CMP_EQ_F32: return AMDGPU::V_CMP_EQ_F32_e64;
  case AMDGPU::S_CMP_LE_F32: return AMDGPU::V_CMP_LE_F32_e64;
  case AMDGPU::S_CMP_GT_F32: return AMDGPU::V_CMP_GT_F32_e64;
  case AMDGPU::S_CMP_LG_F32: return AMDGPU::V_CMP_LG_F32_e64;
  case AMDGPU::S_CMP_GE_F32: return AMDGPU::V_CMP_GE_F32_e64;
  case AMDGPU::S_CMP_O_F32: return AMDGPU::V_CMP_O_F32_e64;
  case AMDGPU::S_CMP_U_F32: return AMDGPU::V_CMP_U_F32_e64;
  case AMDGPU::S_CMP_NGE_F32: return AMDGPU::V_CMP_NGE_F32_e64;
  case AMDGPU::S_CMP_NLG_F32: return AMDGPU::V_CMP_NLG_F32_e64;
  case AMDGPU::S_CMP_NGT_F32: return AMDGPU::V_CMP_NGT_F32_e64;
  case AMDGPU::S_CMP_NLE_F32: return AMDGPU::V_CMP_NLE_F32_e64;
  case AMDGPU::S_CMP_NEQ_F32: return AMDGPU::V_CMP_NEQ_F32_e64;
  case AMDGPU::S_CMP_NLT_F32: return AMDGPU::V_CMP_NLT_F32_e64;
  case AMDGPU::S_CMP_LT_F16:
    return ST.useRealTrue16Insts() ? AMDGPU::V_CMP_LT_F16_t16_e64
                                   : AMDGPU::V_CMP_LT_F16_fake16_e64;
  case AMDGPU::S_CMP_EQ_F16:
    return ST.useRealTrue16Insts() ? AMDGPU::V_CMP_EQ_F16_t16_e64
                                   : AMDGPU::V_CMP_EQ_F16_fake16_e64;
  case AMDGPU::S_CMP_LE_F16:
    return ST.useRealTrue16Insts() ? AMDGPU::V_CMP_LE_F16_t16_e64
                                   : AMDGPU::V_CMP_LE_F16_fake16_e64;
  case AMDGPU::S_CMP_GT_F16:
    return ST.useRealTrue16Insts() ? AMDGPU::V_CMP_GT_F16_t16_e64
                                   : AMDGPU::V_CMP_GT_F16_fake16_e64;
  case AMDGPU::S_CMP_LG_F16:
    return ST.useRealTrue16Insts() ? AMDGPU::V_CMP_LG_F16_t16_e64
                                   : AMDGPU::V_CMP_LG_F16_fake16_e64;
  case AMDGPU::S_CMP_GE_F16:
    return ST.useRealTrue16Insts() ? AMDGPU::V_CMP_GE_F16_t16_e64
                                   : AMDGPU::V_CMP_GE_F16_fake16_e64;
  case AMDGPU::S_CMP_O_F16:
    return ST.useRealTrue16Insts() ? AMDGPU::V_CMP_O_F16_t16_e64
                                   : AMDGPU::V_CMP_O_F16_fake16_e64;
  case AMDGPU::S_CMP_U_F16:
    return ST.useRealTrue16Insts() ? AMDGPU::V_CMP_U_F16_t16_e64
                                   : AMDGPU::V_CMP_U_F16_fake16_e64;
  case AMDGPU::S_CMP_NGE_F16:
    return ST.useRealTrue16Insts() ? AMDGPU::V_CMP_NGE_F16_t16_e64
                                   : AMDGPU::V_CMP_NGE_F16_fake16_e64;
  case AMDGPU::S_CMP_NLG_F16:
    return ST.useRealTrue16Insts() ? AMDGPU::V_CMP_NLG_F16_t16_e64
                                   : AMDGPU::V_CMP_NLG_F16_fake16_e64;
  case AMDGPU::S_CMP_NGT_F16:
    return ST.useRealTrue16Insts() ? AMDGPU::V_CMP_NGT_F16_t16_e64
                                   : AMDGPU::V_CMP_NGT_F16_fake16_e64;
  case AMDGPU::S_CMP_NLE_F16:
    return ST.useRealTrue16Insts() ? AMDGPU::V_CMP_NLE_F16_t16_e64
                                   : AMDGPU::V_CMP_NLE_F16_fake16_e64;
  case AMDGPU::S_CMP_NEQ_F16:
    return ST.useRealTrue16Insts() ? AMDGPU::V_CMP_NEQ_F16_t16_e64
                                   : AMDGPU::V_CMP_NEQ_F16_fake16_e64;
  case AMDGPU::S_CMP_NLT_F16:
    return ST.useRealTrue16Insts() ? AMDGPU::V_CMP_NLT_F16_t16_e64
                                   : AMDGPU::V_CMP_NLT_F16_fake16_e64;
  case AMDGPU::V_S_EXP_F32_e64: return AMDGPU::V_EXP_F32_e64;
  case AMDGPU::V_S_EXP_F16_e64:
    return ST.useRealTrue16Insts() ? AMDGPU::V_EXP_F16_t16_e64
                                   : AMDGPU::V_EXP_F16_fake16_e64;
  case AMDGPU::V_S_LOG_F32_e64: return AMDGPU::V_LOG_F32_e64;
  case AMDGPU::V_S_LOG_F16_e64:
    return ST.useRealTrue16Insts() ? AMDGPU::V_LOG_F16_t16_e64
                                   : AMDGPU::V_LOG_F16_fake16_e64;
  case AMDGPU::V_S_RCP_F32_e64: return AMDGPU::V_RCP_F32_e64;
  case AMDGPU::V_S_RCP_F16_e64:
    return ST.useRealTrue16Insts() ? AMDGPU::V_RCP_F16_t16_e64
                                   : AMDGPU::V_RCP_F16_fake16_e64;
  case AMDGPU::V_S_RSQ_F32_e64: return AMDGPU::V_RSQ_F32_e64;
  case AMDGPU::V_S_RSQ_F16_e64:
    return ST.useRealTrue16Insts() ? AMDGPU::V_RSQ_F16_t16_e64
                                   : AMDGPU::V_RSQ_F16_fake16_e64;
  case AMDGPU::V_S_SQRT_F32_e64: return AMDGPU::V_SQRT_F32_e64;
  case AMDGPU::V_S_SQRT_F16_e64:
    return ST.useRealTrue16Insts() ? AMDGPU::V_SQRT_F16_t16_e64
                                   : AMDGPU::V_SQRT_F16_fake16_e64;
  }
  llvm_unreachable(
      "Unexpected scalar opcode without corresponding vector one!");
}

// clang-format on

void SIInstrInfo::insertScratchExecCopy(MachineFunction &MF,
                                        MachineBasicBlock &MBB,
                                        MachineBasicBlock::iterator MBBI,
                                        const DebugLoc &DL, Register Reg,
                                        bool IsSCCLive,
                                        SlotIndexes *Indexes) const {
  const GCNSubtarget &ST = MF.getSubtarget<GCNSubtarget>();
  const SIInstrInfo *TII = ST.getInstrInfo();
  const AMDGPU::LaneMaskConstants &LMC = AMDGPU::LaneMaskConstants::get(ST);
  if (IsSCCLive) {
    // Insert two move instructions, one to save the original value of EXEC and
    // the other to turn on all bits in EXEC. This is required as we can't use
    // the single instruction S_OR_SAVEEXEC that clobbers SCC.
    auto StoreExecMI = BuildMI(MBB, MBBI, DL, TII->get(LMC.MovOpc), Reg)
                           .addReg(LMC.ExecReg, RegState::Kill);
    auto FlipExecMI =
        BuildMI(MBB, MBBI, DL, TII->get(LMC.MovOpc), LMC.ExecReg).addImm(-1);
    if (Indexes) {
      Indexes->insertMachineInstrInMaps(*StoreExecMI);
      Indexes->insertMachineInstrInMaps(*FlipExecMI);
    }
  } else {
    auto SaveExec =
        BuildMI(MBB, MBBI, DL, TII->get(LMC.OrSaveExecOpc), Reg).addImm(-1);
    SaveExec->getOperand(3).setIsDead(); // Mark SCC as dead.
    if (Indexes)
      Indexes->insertMachineInstrInMaps(*SaveExec);
  }
}

void SIInstrInfo::restoreExec(MachineFunction &MF, MachineBasicBlock &MBB,
                              MachineBasicBlock::iterator MBBI,
                              const DebugLoc &DL, Register Reg,
                              SlotIndexes *Indexes) const {
  const AMDGPU::LaneMaskConstants &LMC = AMDGPU::LaneMaskConstants::get(ST);
  auto ExecRestoreMI = BuildMI(MBB, MBBI, DL, get(LMC.MovOpc), LMC.ExecReg)
                           .addReg(Reg, RegState::Kill);
  if (Indexes)
    Indexes->insertMachineInstrInMaps(*ExecRestoreMI);
}

MachineInstr *
SIInstrInfo::getWholeWaveFunctionSetup(MachineFunction &MF) const {
  assert(MF.getInfo<SIMachineFunctionInfo>()->isWholeWaveFunction() &&
         "Not a whole wave func");
  MachineBasicBlock &MBB = *MF.begin();
  for (MachineInstr &MI : MBB)
    if (MI.getOpcode() == AMDGPU::SI_WHOLE_WAVE_FUNC_SETUP ||
        MI.getOpcode() == AMDGPU::G_AMDGPU_WHOLE_WAVE_FUNC_SETUP)
      return &MI;

  llvm_unreachable("Couldn't find SI_SETUP_WHOLE_WAVE_FUNC instruction");
}

const TargetRegisterClass *SIInstrInfo::getOpRegClass(const MachineInstr &MI,
                                                      unsigned OpNo) const {
  const MCInstrDesc &Desc = get(MI.getOpcode());
  if (MI.isVariadic() || OpNo >= Desc.getNumOperands() ||
      Desc.operands()[OpNo].RegClass == -1) {
    Register Reg = MI.getOperand(OpNo).getReg();

    if (Reg.isVirtual()) {
      const MachineRegisterInfo &MRI = MI.getMF()->getRegInfo();
      return MRI.getRegClass(Reg);
    }
    return RI.getPhysRegBaseClass(Reg);
  }

  int16_t RegClass = getOpRegClassID(Desc.operands()[OpNo]);
  return RegClass < 0 ? nullptr : RI.getRegClass(RegClass);
}

void SIInstrInfo::legalizeOpWithMove(MachineInstr &MI, unsigned OpIdx) const {
  MachineBasicBlock::iterator I = MI;
  MachineBasicBlock *MBB = MI.getParent();
  MachineOperand &MO = MI.getOperand(OpIdx);
  MachineRegisterInfo &MRI = MBB->getParent()->getRegInfo();
  unsigned RCID = getOpRegClassID(get(MI.getOpcode()).operands()[OpIdx]);
  const TargetRegisterClass *RC = RI.getRegClass(RCID);
  unsigned Size = RI.getRegSizeInBits(*RC);
  unsigned Opcode = (Size == 64) ? AMDGPU::V_MOV_B64_PSEUDO
                    : Size == 16 ? AMDGPU::V_MOV_B16_t16_e64
                                 : AMDGPU::V_MOV_B32_e32;
  if (MO.isReg())
    Opcode = AMDGPU::COPY;
  else if (RI.isSGPRClass(RC))
    Opcode = (Size == 64) ? AMDGPU::S_MOV_B64 : AMDGPU::S_MOV_B32;

  const TargetRegisterClass *VRC = RI.getEquivalentVGPRClass(RC);
  Register Reg = MRI.createVirtualRegister(VRC);
  DebugLoc DL = MBB->findDebugLoc(I);
  BuildMI(*MI.getParent(), I, DL, get(Opcode), Reg).add(MO);
  MO.ChangeToRegister(Reg, false);
}

unsigned SIInstrInfo::buildExtractSubReg(
    MachineBasicBlock::iterator MI, MachineRegisterInfo &MRI,
    const MachineOperand &SuperReg, const TargetRegisterClass *SuperRC,
    unsigned SubIdx, const TargetRegisterClass *SubRC) const {
  if (!SuperReg.getReg().isVirtual())
    return RI.getSubReg(SuperReg.getReg(), SubIdx);

  MachineBasicBlock *MBB = MI->getParent();
  const DebugLoc &DL = MI->getDebugLoc();
  Register SubReg = MRI.createVirtualRegister(SubRC);

  unsigned NewSubIdx = RI.composeSubRegIndices(SuperReg.getSubReg(), SubIdx);
  BuildMI(*MBB, MI, DL, get(TargetOpcode::COPY), SubReg)
      .addReg(SuperReg.getReg(), {}, NewSubIdx);
  return SubReg;
}

MachineOperand SIInstrInfo::buildExtractSubRegOrImm(
    MachineBasicBlock::iterator MII, MachineRegisterInfo &MRI,
    const MachineOperand &Op, const TargetRegisterClass *SuperRC,
    unsigned SubIdx, const TargetRegisterClass *SubRC) const {
  if (Op.isImm()) {
    if (SubIdx == AMDGPU::sub0)
      return MachineOperand::CreateImm(static_cast<int32_t>(Op.getImm()));
    if (SubIdx == AMDGPU::sub1)
      return MachineOperand::CreateImm(static_cast<int32_t>(Op.getImm() >> 32));

    llvm_unreachable("Unhandled register index for immediate");
  }

  unsigned SubReg = buildExtractSubReg(MII, MRI, Op, SuperRC,
                                       SubIdx, SubRC);
  return MachineOperand::CreateReg(SubReg, false);
}

// Change the order of operands from (0, 1, 2) to (0, 2, 1)
void SIInstrInfo::swapOperands(MachineInstr &Inst) const {
  assert(Inst.getNumExplicitOperands() == 3);
  MachineOperand Op1 = Inst.getOperand(1);
  Inst.removeOperand(1);
  Inst.addOperand(Op1);
}

bool SIInstrInfo::isLegalRegOperand(const MachineRegisterInfo &MRI,
                                    const MCOperandInfo &OpInfo,
                                    const MachineOperand &MO) const {
  if (!MO.isReg())
    return false;

  Register Reg = MO.getReg();

  const TargetRegisterClass *DRC = RI.getRegClass(getOpRegClassID(OpInfo));
  if (Reg.isPhysical())
    return DRC->contains(Reg);

  const TargetRegisterClass *RC = MRI.getRegClass(Reg);

  if (MO.getSubReg()) {
    const MachineFunction *MF = MO.getParent()->getMF();
    const TargetRegisterClass *SuperRC = RI.getLargestLegalSuperClass(RC, *MF);
    if (!SuperRC)
      return false;
    return RI.getMatchingSuperRegClass(SuperRC, DRC, MO.getSubReg()) != nullptr;
  }

  return RI.getCommonSubClass(DRC, RC) != nullptr;
}

bool SIInstrInfo::isLegalRegOperand(const MachineInstr &MI, unsigned OpIdx,
                                    const MachineOperand &MO) const {
  const MachineRegisterInfo &MRI = MI.getMF()->getRegInfo();
  const MCOperandInfo OpInfo = MI.getDesc().operands()[OpIdx];
  unsigned Opc = MI.getOpcode();

  // See SIInstrInfo::isLegalGFX12PlusPackedMathFP32or64BitOperand for more
  // information.
  if (AMDGPU::isPackedFP32or64BitInst(MI.getOpcode()) &&
      AMDGPU::isGFX12Plus(ST) && MO.isReg() && RI.isSGPRReg(MRI, MO.getReg())) {
    constexpr AMDGPU::OpName OpNames[] = {
        AMDGPU::OpName::src0, AMDGPU::OpName::src1, AMDGPU::OpName::src2};

    for (auto [I, OpName] : enumerate(OpNames)) {
      int SrcIdx = AMDGPU::getNamedOperandIdx(MI.getOpcode(), OpNames[I]);
      if (static_cast<unsigned>(SrcIdx) == OpIdx &&
          !isLegalGFX12PlusPackedMathFP32or64BitOperand(MRI, MI, I, &MO))
        return false;
    }
  }

  if (!isLegalRegOperand(MRI, OpInfo, MO))
    return false;

  // check Accumulate GPR operand
  bool IsAGPR = RI.isAGPR(MRI, MO.getReg());
  if (IsAGPR && !ST.hasMAIInsts())
    return false;
  if (IsAGPR && (!ST.hasGFX90AInsts() || !MRI.reservedRegsFrozen()) &&
      (MI.mayLoad() || MI.mayStore() || isDS(Opc) || isMIMG(Opc)))
    return false;
  // Atomics should have both vdst and vdata either vgpr or agpr.
  const int VDstIdx = AMDGPU::getNamedOperandIdx(Opc, AMDGPU::OpName::vdst);
  const int DataIdx = AMDGPU::getNamedOperandIdx(
      Opc, isDS(Opc) ? AMDGPU::OpName::data0 : AMDGPU::OpName::vdata);
  if ((int)OpIdx == VDstIdx && DataIdx != -1 &&
      MI.getOperand(DataIdx).isReg() &&
      RI.isAGPR(MRI, MI.getOperand(DataIdx).getReg()) != IsAGPR)
    return false;
  if ((int)OpIdx == DataIdx) {
    if (VDstIdx != -1 &&
        RI.isAGPR(MRI, MI.getOperand(VDstIdx).getReg()) != IsAGPR)
      return false;
    // DS instructions with 2 src operands also must have tied RC.
    const int Data1Idx = AMDGPU::getNamedOperandIdx(Opc, AMDGPU::OpName::data1);
    if (Data1Idx != -1 && MI.getOperand(Data1Idx).isReg() &&
        RI.isAGPR(MRI, MI.getOperand(Data1Idx).getReg()) != IsAGPR)
      return false;
  }

  // Check V_ACCVGPR_WRITE_B32_e64
  if (Opc == AMDGPU::V_ACCVGPR_WRITE_B32_e64 && !ST.hasGFX90AInsts() &&
      (int)OpIdx == AMDGPU::getNamedOperandIdx(Opc, AMDGPU::OpName::src0) &&
      RI.isSGPRReg(MRI, MO.getReg()))
    return false;

  if (ST.hasFlatScratchHiInB64InstHazard() &&
      MO.getReg() == AMDGPU::SRC_FLAT_SCRATCH_BASE_HI && isSALU(MI)) {
    if (const MachineOperand *Dst = getNamedOperand(MI, AMDGPU::OpName::sdst)) {
      if (AMDGPU::getRegBitWidth(*RI.getRegClassForReg(MRI, Dst->getReg())) ==
          64)
        return false;
    }
    if (Opc == AMDGPU::S_BITCMP0_B64 || Opc == AMDGPU::S_BITCMP1_B64)
      return false;
  }
  if (!ST.hasDPPSrc1SGPR() && isDPP(MI) && RI.isSGPRReg(MRI, MO.getReg()) &&
      (int)OpIdx == AMDGPU::getNamedOperandIdx(Opc, AMDGPU::OpName::src1))
    return false;

  return true;
}

bool SIInstrInfo::isLegalVSrcOperand(const MachineRegisterInfo &MRI,
                                     const MCOperandInfo &OpInfo,
                                     const MachineOperand &MO) const {
  if (MO.isReg())
    return isLegalRegOperand(MRI, OpInfo, MO);

  // Handle non-register types that are treated like immediates.
  assert(MO.isImm() || MO.isTargetIndex() || MO.isFI() || MO.isGlobal());
  return true;
}

bool SIInstrInfo::isLegalGFX12PlusPackedMathFP32or64BitOperand(
    const MachineRegisterInfo &MRI, const MachineInstr &MI, unsigned SrcN,
    const MachineOperand *MO) const {
  constexpr unsigned NumOps = 3;
  constexpr AMDGPU::OpName OpNames[NumOps * 2] = {
      AMDGPU::OpName::src0,           AMDGPU::OpName::src1,
      AMDGPU::OpName::src2,           AMDGPU::OpName::src0_modifiers,
      AMDGPU::OpName::src1_modifiers, AMDGPU::OpName::src2_modifiers};

  assert(SrcN < NumOps);

  if (!MO) {
    int SrcIdx = AMDGPU::getNamedOperandIdx(MI.getOpcode(), OpNames[SrcN]);
    if (SrcIdx == -1)
      return true;
    MO = &MI.getOperand(SrcIdx);
  }

  if (!MO->isReg() || !RI.isSGPRReg(MRI, MO->getReg()))
    return true;

  int ModsIdx =
      AMDGPU::getNamedOperandIdx(MI.getOpcode(), OpNames[NumOps + SrcN]);
  if (ModsIdx == -1)
    return false;

  unsigned Mods = MI.getOperand(ModsIdx).getImm();
  bool OpSel = Mods & SISrcMods::OP_SEL_0;
  bool OpSelHi = Mods & SISrcMods::OP_SEL_1;

  return !OpSel && !OpSelHi;
}

bool SIInstrInfo::isOperandLegal(const MachineInstr &MI, unsigned OpIdx,
                                 const MachineOperand *MO) const {
  const MachineFunction &MF = *MI.getMF();
  const MachineRegisterInfo &MRI = MF.getRegInfo();
  const MCInstrDesc &InstDesc = MI.getDesc();
  const MCOperandInfo &OpInfo = InstDesc.operands()[OpIdx];
  int64_t RegClass = getOpRegClassID(OpInfo);
  const TargetRegisterClass *DefinedRC =
      RegClass != -1 ? RI.getRegClass(RegClass) : nullptr;
  if (!MO)
    MO = &MI.getOperand(OpIdx);

  const bool IsInlineConst = !MO->isReg() && isInlineConstant(*MO, OpInfo);

  if (isVALU(MI, /*AllowLDSDMA=*/true) && !IsInlineConst &&
      usesConstantBus(MRI, *MO, OpInfo)) {
    const MachineOperand *UsedLiteral = nullptr;

    int ConstantBusLimit = ST.getConstantBusLimit(MI.getOpcode());
    int LiteralLimit = !isVOP3(MI) || ST.hasVOP3Literal() ? 1 : 0;

    // TODO: Be more permissive with frame indexes.
    if (!MO->isReg() && !isInlineConstant(*MO, OpInfo)) {
      if (!LiteralLimit--)
        return false;

      UsedLiteral = MO;
    }

    SmallDenseSet<RegSubRegPair> SGPRsUsed;
    if (MO->isReg())
      SGPRsUsed.insert(RegSubRegPair(MO->getReg(), MO->getSubReg()));

    for (unsigned i = 0, e = MI.getNumOperands(); i != e; ++i) {
      if (i == OpIdx)
        continue;
      const MachineOperand &Op = MI.getOperand(i);
      if (Op.isReg()) {
        if (Op.isUse()) {
          RegSubRegPair SGPR(Op.getReg(), Op.getSubReg());
          if (regUsesConstantBus(Op, MRI) && SGPRsUsed.insert(SGPR).second) {
            if (--ConstantBusLimit <= 0)
              return false;
          }
        }
      } else if (AMDGPU::isSISrcOperand(InstDesc.operands()[i]) &&
                 !isInlineConstant(Op, InstDesc.operands()[i])) {
        // The same literal may be used multiple times.
        if (!UsedLiteral)
          UsedLiteral = &Op;
        else if (UsedLiteral->isIdenticalTo(Op))
          continue;

        if (!LiteralLimit--)
          return false;
        if (--ConstantBusLimit <= 0)
          return false;
      }
    }
  } else if (!IsInlineConst && !MO->isReg() && isSALU(MI)) {
    // There can be at most one literal operand, but it can be repeated.
    for (unsigned i = 0, e = MI.getNumOperands(); i != e; ++i) {
      if (i == OpIdx)
        continue;
      const MachineOperand &Op = MI.getOperand(i);
      if (!Op.isReg() && !Op.isFI() && !Op.isRegMask() &&
          !isInlineConstant(Op, InstDesc.operands()[i]) &&
          !Op.isIdenticalTo(*MO))
        return false;

      // Do not fold a non-inlineable and non-register operand into an
      // instruction that already has a frame index. The frame index handling
      // code could not handle well when a frame index co-exists with another
      // non-register operand, unless that operand is an inlineable immediate.
      if (Op.isFI())
        return false;
    }
  } else if (IsInlineConst && ST.hasNoF16PseudoScalarTransInlineConstants() &&
             isF16PseudoScalarTrans(MI.getOpcode())) {
    return false;
  }

  if (MO->isReg()) {
    if (!DefinedRC)
      return OpInfo.OperandType == MCOI::OPERAND_UNKNOWN;
    return isLegalRegOperand(MI, OpIdx, *MO);
  }

  if (MO->isImm()) {
    uint64_t Imm = MO->getImm();
    bool Is64BitFPOp = OpInfo.OperandType == AMDGPU::OPERAND_REG_IMM_FP64 ||
                       OpInfo.OperandType == AMDGPU::OPERAND_REG_IMM_V2FP64;
    bool Is64BitOp = Is64BitFPOp ||
                     OpInfo.OperandType == AMDGPU::OPERAND_REG_IMM_INT64 ||
                     OpInfo.OperandType == AMDGPU::OPERAND_REG_IMM_V2INT32 ||
                     OpInfo.OperandType == AMDGPU::OPERAND_REG_IMM_V2FP32 ||
                     OpInfo.OperandType == AMDGPU::OPERAND_REG_IMM_V2INT64;
    if (Is64BitOp &&
        !AMDGPU::isInlinableLiteral64(Imm, ST.hasInv2PiInlineImm())) {
      if (!AMDGPU::isValid32BitLiteral(Imm, Is64BitFPOp) &&
          (!ST.has64BitLiterals() || InstDesc.getSize() != 4))
        return false;

      // FIXME: We can use sign extended 64-bit literals, but only for signed
      //        operands. At the moment we do not know if an operand is signed.
      //        Such operand will be encoded as its low 32 bits and then either
      //        correctly sign extended or incorrectly zero extended by HW.
      //        If 64-bit literals are supported and the literal will be encoded
      //        as full 64 bit we still can use it.
      if (!Is64BitFPOp && (int32_t)Imm < 0 &&
          (!ST.has64BitLiterals() || AMDGPU::isValid32BitLiteral(Imm, false)))
        return false;
    }
  }

  // Handle non-register types that are treated like immediates.
  assert(MO->isImm() || MO->isTargetIndex() || MO->isFI() || MO->isGlobal());

  if (!DefinedRC) {
    // This operand expects an immediate.
    return true;
  }

  return isImmOperandLegal(MI, OpIdx, *MO);
}

bool SIInstrInfo::isNeverCoissue(MachineInstr &MI) const {
  bool IsGFX950Only = ST.hasGFX950Insts();
  bool IsGFX940Only = ST.hasGFX940Insts();

  if (!IsGFX950Only && !IsGFX940Only)
    return false;

  if (!isVALU(MI, /*AllowLDSDMA=*/true))
    return false;

  // V_COS, V_EXP, V_RCP, etc.
  if (isTRANS(MI))
    return true;

  // DOT2, DOT2C, DOT4, etc.
  if (isDOT(MI))
    return true;

  // MFMA, SMFMA
  if (isMFMA(MI))
    return true;

  unsigned Opcode = MI.getOpcode();
  switch (Opcode) {
  case AMDGPU::V_CVT_PK_BF8_F32_e64:
  case AMDGPU::V_CVT_PK_FP8_F32_e64:
  case AMDGPU::V_MQSAD_PK_U16_U8_e64:
  case AMDGPU::V_MQSAD_U32_U8_e64:
  case AMDGPU::V_PK_ADD_F16:
  case AMDGPU::V_PK_ADD_F32:
  case AMDGPU::V_PK_ADD_I16:
  case AMDGPU::V_PK_ADD_U16:
  case AMDGPU::V_PK_ASHRREV_I16:
  case AMDGPU::V_PK_FMA_F16:
  case AMDGPU::V_PK_FMA_F32:
  case AMDGPU::V_PK_FMAC_F16_e32:
  case AMDGPU::V_PK_FMAC_F16_e64:
  case AMDGPU::V_PK_LSHLREV_B16:
  case AMDGPU::V_PK_LSHRREV_B16:
  case AMDGPU::V_PK_MAD_I16:
  case AMDGPU::V_PK_MAD_U16:
  case AMDGPU::V_PK_MAX_F16:
  case AMDGPU::V_PK_MAX_I16:
  case AMDGPU::V_PK_MAX_U16:
  case AMDGPU::V_PK_MIN_F16:
  case AMDGPU::V_PK_MIN_I16:
  case AMDGPU::V_PK_MIN_U16:
  case AMDGPU::V_PK_MOV_B32:
  case AMDGPU::V_PK_MUL_F16:
  case AMDGPU::V_PK_MUL_F32:
  case AMDGPU::V_PK_MUL_LO_U16:
  case AMDGPU::V_PK_SUB_I16:
  case AMDGPU::V_PK_SUB_U16:
  case AMDGPU::V_QSAD_PK_U16_U8_e64:
    return true;
  default:
    return false;
  }
}

void SIInstrInfo::legalizeOperandsVOP2(MachineRegisterInfo &MRI,
                                       MachineInstr &MI) const {
  unsigned Opc = MI.getOpcode();
  const MCInstrDesc &InstrDesc = get(Opc);

  int Src0Idx = AMDGPU::getNamedOperandIdx(Opc, AMDGPU::OpName::src0);
  MachineOperand &Src0 = MI.getOperand(Src0Idx);

  int Src1Idx = AMDGPU::getNamedOperandIdx(Opc, AMDGPU::OpName::src1);
  MachineOperand &Src1 = MI.getOperand(Src1Idx);

  // If there is an implicit SGPR use such as VCC use for v_addc_u32/v_subb_u32
  // we need to only have one constant bus use before GFX10.
  bool HasImplicitSGPR = findImplicitSGPRRead(MI);
  if (HasImplicitSGPR && ST.getConstantBusLimit(Opc) <= 1 && Src0.isReg() &&
      RI.isSGPRReg(MRI, Src0.getReg()))
    legalizeOpWithMove(MI, Src0Idx);

  // Special case: V_WRITELANE_B32 accepts only immediate or SGPR operands for
  // both the value to write (src0) and lane select (src1).  Fix up non-SGPR
  // src0/src1 with V_READFIRSTLANE.
  if (Opc == AMDGPU::V_WRITELANE_B32) {
    const DebugLoc &DL = MI.getDebugLoc();
    if (Src0.isReg() && RI.isVGPR(MRI, Src0.getReg())) {
      Register Reg = MRI.createVirtualRegister(&AMDGPU::SReg_32_XM0RegClass);
      BuildMI(*MI.getParent(), MI, DL, get(AMDGPU::V_READFIRSTLANE_B32), Reg)
          .add(Src0);
      Src0.ChangeToRegister(Reg, false);
    }
    if (Src1.isReg() && RI.isVGPR(MRI, Src1.getReg())) {
      Register Reg = MRI.createVirtualRegister(&AMDGPU::SReg_32_XM0RegClass);
      const DebugLoc &DL = MI.getDebugLoc();
      BuildMI(*MI.getParent(), MI, DL, get(AMDGPU::V_READFIRSTLANE_B32), Reg)
          .add(Src1);
      Src1.ChangeToRegister(Reg, false);
    }
    return;
  }

  // Special case: V_FMAC_F32 and V_FMAC_F16 have src2.
  if (Opc == AMDGPU::V_FMAC_F32_e32 || Opc == AMDGPU::V_FMAC_F16_e32) {
    int Src2Idx = AMDGPU::getNamedOperandIdx(Opc, AMDGPU::OpName::src2);
    if (!RI.isVGPR(MRI, MI.getOperand(Src2Idx).getReg()))
      legalizeOpWithMove(MI, Src2Idx);
  }

  // VOP2 src0 instructions support all operand types, so we don't need to check
  // their legality. If src1 is already legal, we don't need to do anything.
  if (isLegalRegOperand(MRI, InstrDesc.operands()[Src1Idx], Src1))
    return;

  // Special case: V_READLANE_B32 accepts only immediate or SGPR operands for
  // lane select. Fix up using V_READFIRSTLANE, since we assume that the lane
  // select is uniform.
  if (Opc == AMDGPU::V_READLANE_B32 && Src1.isReg() &&
      RI.isVGPR(MRI, Src1.getReg())) {
    Register Reg = MRI.createVirtualRegister(&AMDGPU::SReg_32_XM0RegClass);
    const DebugLoc &DL = MI.getDebugLoc();
    BuildMI(*MI.getParent(), MI, DL, get(AMDGPU::V_READFIRSTLANE_B32), Reg)
        .add(Src1);
    Src1.ChangeToRegister(Reg, false);
    return;
  }

  // We do not use commuteInstruction here because it is too aggressive and will
  // commute if it is possible. We only want to commute here if it improves
  // legality. This can be called a fairly large number of times so don't waste
  // compile time pointlessly swapping and checking legality again.
  if (HasImplicitSGPR || !MI.isCommutable()) {
    legalizeOpWithMove(MI, Src1Idx);
    return;
  }

  // If src0 can be used as src1, commuting will make the operands legal.
  // Otherwise we have to give up and insert a move.
  //
  // TODO: Other immediate-like operand kinds could be commuted if there was a
  // MachineOperand::ChangeTo* for them.
  if ((!Src1.isImm() && !Src1.isReg()) ||
      !isLegalRegOperand(MRI, InstrDesc.operands()[Src1Idx], Src0)) {
    legalizeOpWithMove(MI, Src1Idx);
    return;
  }

  int CommutedOpc = commuteOpcode(MI);
  if (CommutedOpc == -1) {
    legalizeOpWithMove(MI, Src1Idx);
    return;
  }

  MI.setDesc(get(CommutedOpc));

  Register Src0Reg = Src0.getReg();
  unsigned Src0SubReg = Src0.getSubReg();
  bool Src0Kill = Src0.isKill();

  if (Src1.isImm())
    Src0.ChangeToImmediate(Src1.getImm());
  else if (Src1.isReg()) {
    Src0.ChangeToRegister(Src1.getReg(), false, false, Src1.isKill());
    Src0.setSubReg(Src1.getSubReg());
  } else
    llvm_unreachable("Should only have register or immediate operands");

  Src1.ChangeToRegister(Src0Reg, false, false, Src0Kill);
  Src1.setSubReg(Src0SubReg);
  fixImplicitOperands(MI);
}

// Legalize VOP3 operands. All operand types are supported for any operand
// but only one literal constant and only starting from GFX10.
void SIInstrInfo::legalizeOperandsVOP3(MachineRegisterInfo &MRI,
                                       MachineInstr &MI) const {
  unsigned Opc = MI.getOpcode();

  int VOP3Idx[3] = {
    AMDGPU::getNamedOperandIdx(Opc, AMDGPU::OpName::src0),
    AMDGPU::getNamedOperandIdx(Opc, AMDGPU::OpName::src1),
    AMDGPU::getNamedOperandIdx(Opc, AMDGPU::OpName::src2)
  };

  if (Opc == AMDGPU::V_PERMLANE16_B32_e64 ||
      Opc == AMDGPU::V_PERMLANEX16_B32_e64 ||
      Opc == AMDGPU::V_PERMLANE_BCAST_B32_e64 ||
      Opc == AMDGPU::V_PERMLANE_UP_B32_e64 ||
      Opc == AMDGPU::V_PERMLANE_DOWN_B32_e64 ||
      Opc == AMDGPU::V_PERMLANE_XOR_B32_e64 ||
      Opc == AMDGPU::V_PERMLANE_IDX_GEN_B32_e64) {
    // src1 and src2 must be scalar
    MachineOperand &Src1 = MI.getOperand(VOP3Idx[1]);
    const DebugLoc &DL = MI.getDebugLoc();
    if (Src1.isReg() && !RI.isSGPRClass(MRI.getRegClass(Src1.getReg()))) {
      Register Reg = MRI.createVirtualRegister(&AMDGPU::SReg_32_XM0RegClass);
      BuildMI(*MI.getParent(), MI, DL, get(AMDGPU::V_READFIRSTLANE_B32), Reg)
        .add(Src1);
      Src1.ChangeToRegister(Reg, false);
    }
    if (VOP3Idx[2] != -1) {
      MachineOperand &Src2 = MI.getOperand(VOP3Idx[2]);
      if (Src2.isReg() && !RI.isSGPRClass(MRI.getRegClass(Src2.getReg()))) {
        Register Reg = MRI.createVirtualRegister(&AMDGPU::SReg_32_XM0RegClass);
        BuildMI(*MI.getParent(), MI, DL, get(AMDGPU::V_READFIRSTLANE_B32), Reg)
            .add(Src2);
        Src2.ChangeToRegister(Reg, false);
      }
    }
  }

  // Find the one SGPR operand we are allowed to use.
  int ConstantBusLimit = ST.getConstantBusLimit(Opc);
  int LiteralLimit = ST.hasVOP3Literal() ? 1 : 0;
  SmallDenseSet<unsigned> SGPRsUsed;
  Register SGPRReg = findUsedSGPR(MI, VOP3Idx);
  if (SGPRReg) {
    SGPRsUsed.insert(SGPRReg);
    --ConstantBusLimit;
  }

  for (int Idx : VOP3Idx) {
    if (Idx == -1)
      break;
    MachineOperand &MO = MI.getOperand(Idx);

    if (!MO.isReg()) {
      if (isInlineConstant(MO, get(Opc).operands()[Idx]))
        continue;

      if (LiteralLimit > 0 && ConstantBusLimit > 0) {
        --LiteralLimit;
        --ConstantBusLimit;
        continue;
      }

      --LiteralLimit;
      --ConstantBusLimit;
      legalizeOpWithMove(MI, Idx);
      continue;
    }

    if (!RI.isSGPRClass(RI.getRegClassForReg(MRI, MO.getReg())))
      continue; // VGPRs are legal

    // We can use one SGPR in each VOP3 instruction prior to GFX10
    // and two starting from GFX10.
    if (SGPRsUsed.count(MO.getReg()))
      continue;
    if (ConstantBusLimit > 0) {
      SGPRsUsed.insert(MO.getReg());
      --ConstantBusLimit;
      continue;
    }

    // If we make it this far, then the operand is not legal and we must
    // legalize it.
    legalizeOpWithMove(MI, Idx);
  }

  // Special case: V_FMAC_F32 and V_FMAC_F16 have src2 tied to vdst.
  if ((Opc == AMDGPU::V_FMAC_F32_e64 || Opc == AMDGPU::V_FMAC_F16_e64) &&
      !RI.isVGPR(MRI, MI.getOperand(VOP3Idx[2]).getReg()))
    legalizeOpWithMove(MI, VOP3Idx[2]);

  // Fix the register class of packed FP32 instructions on gfx12+. See
  // SIInstrInfo::isLegalGFX12PlusPackedMathFP32or64BitOperand for more
  // information.
  if (AMDGPU::isPackedFP32or64BitInst(Opc) && AMDGPU::isGFX12Plus(ST)) {
    for (unsigned I = 0; I < 3; ++I) {
      if (!isLegalGFX12PlusPackedMathFP32or64BitOperand(MRI, MI, /*SrcN=*/I))
        legalizeOpWithMove(MI, VOP3Idx[I]);
    }
  }
}

Register SIInstrInfo::readlaneVGPRToSGPR(
    Register SrcReg, MachineInstr &UseMI, MachineRegisterInfo &MRI,
    const TargetRegisterClass *DstRC /*=nullptr*/) const {
  const TargetRegisterClass *VRC = MRI.getRegClass(SrcReg);
  const TargetRegisterClass *SRC = RI.getEquivalentSGPRClass(VRC);
  if (DstRC)
    SRC = RI.getCommonSubClass(SRC, DstRC);

  Register DstReg = MRI.createVirtualRegister(SRC);
  unsigned SubRegs = RI.getRegSizeInBits(*VRC) / 32;

  if (RI.hasAGPRs(VRC)) {
    VRC = RI.getEquivalentVGPRClass(VRC);
    Register NewSrcReg = MRI.createVirtualRegister(VRC);
    BuildMI(*UseMI.getParent(), UseMI, UseMI.getDebugLoc(),
            get(TargetOpcode::COPY), NewSrcReg)
        .addReg(SrcReg);
    SrcReg = NewSrcReg;
  }

  if (SubRegs == 1) {
    BuildMI(*UseMI.getParent(), UseMI, UseMI.getDebugLoc(),
            get(AMDGPU::V_READFIRSTLANE_B32), DstReg)
        .addReg(SrcReg);
    return DstReg;
  }

  SmallVector<Register, 8> SRegs;
  for (unsigned i = 0; i < SubRegs; ++i) {
    Register SGPR = MRI.createVirtualRegister(&AMDGPU::SGPR_32RegClass);
    BuildMI(*UseMI.getParent(), UseMI, UseMI.getDebugLoc(),
            get(AMDGPU::V_READFIRSTLANE_B32), SGPR)
        .addReg(SrcReg, {}, RI.getSubRegFromChannel(i));
    SRegs.push_back(SGPR);
  }

  MachineInstrBuilder MIB =
      BuildMI(*UseMI.getParent(), UseMI, UseMI.getDebugLoc(),
              get(AMDGPU::REG_SEQUENCE), DstReg);
  for (unsigned i = 0; i < SubRegs; ++i) {
    MIB.addReg(SRegs[i]);
    MIB.addImm(RI.getSubRegFromChannel(i));
  }
  return DstReg;
}

void SIInstrInfo::legalizeOperandsSMRD(MachineRegisterInfo &MRI,
                                       MachineInstr &MI) const {

  // If the pointer is store in VGPRs, then we need to move them to
  // SGPRs using v_readfirstlane.  This is safe because we only select
  // loads with uniform pointers to SMRD instruction so we know the
  // pointer value is uniform.
  MachineOperand *SBase = getNamedOperand(MI, AMDGPU::OpName::sbase);
  if (SBase && !RI.isSGPRClass(MRI.getRegClass(SBase->getReg()))) {
    Register SGPR = readlaneVGPRToSGPR(SBase->getReg(), MI, MRI);
    SBase->setReg(SGPR);
  }
  MachineOperand *SOff = getNamedOperand(MI, AMDGPU::OpName::soffset);
  if (SOff && !RI.isSGPRReg(MRI, SOff->getReg())) {
    Register SGPR = readlaneVGPRToSGPR(SOff->getReg(), MI, MRI);
    SOff->setReg(SGPR);
  }
}

bool SIInstrInfo::moveFlatAddrToVGPR(MachineInstr &Inst) const {
  unsigned Opc = Inst.getOpcode();
  int OldSAddrIdx = AMDGPU::getNamedOperandIdx(Opc, AMDGPU::OpName::saddr);
  if (OldSAddrIdx < 0)
    return false;

  assert(isSegmentSpecificFLAT(Inst) || (isFLAT(Inst) && ST.hasFlatGVSMode()));

  int NewOpc = AMDGPU::getGlobalVaddrOp(Opc);
  if (NewOpc < 0)
    NewOpc = AMDGPU::getFlatScratchInstSVfromSS(Opc);
  if (NewOpc < 0)
    return false;

  MachineRegisterInfo &MRI = Inst.getMF()->getRegInfo();
  MachineOperand &SAddr = Inst.getOperand(OldSAddrIdx);
  if (RI.isSGPRReg(MRI, SAddr.getReg()))
    return false;

  int NewVAddrIdx = AMDGPU::getNamedOperandIdx(NewOpc, AMDGPU::OpName::vaddr);
  if (NewVAddrIdx < 0)
    return false;

  int OldVAddrIdx = AMDGPU::getNamedOperandIdx(Opc, AMDGPU::OpName::vaddr);

  // Check vaddr, it shall be zero or absent.
  MachineInstr *VAddrDef = nullptr;
  if (OldVAddrIdx >= 0) {
    MachineOperand &VAddr = Inst.getOperand(OldVAddrIdx);
    VAddrDef = MRI.getUniqueVRegDef(VAddr.getReg());
    if (!VAddrDef || !VAddrDef->isMoveImmediate() ||
        !VAddrDef->getOperand(1).isImm() ||
        VAddrDef->getOperand(1).getImm() != 0)
      return false;
  }

  const MCInstrDesc &NewDesc = get(NewOpc);
  Inst.setDesc(NewDesc);

  // Callers expect iterator to be valid after this call, so modify the
  // instruction in place.
  if (OldVAddrIdx == NewVAddrIdx) {
    MachineOperand &NewVAddr = Inst.getOperand(NewVAddrIdx);
    // Clear use list from the old vaddr holding a zero register.
    MRI.removeRegOperandFromUseList(&NewVAddr);
    MRI.moveOperands(&NewVAddr, &SAddr, 1);
    Inst.removeOperand(OldSAddrIdx);
    // Update the use list with the pointer we have just moved from vaddr to
    // saddr position. Otherwise new vaddr will be missing from the use list.
    MRI.removeRegOperandFromUseList(&NewVAddr);
    MRI.addRegOperandToUseList(&NewVAddr);
  } else {
    assert(OldSAddrIdx == NewVAddrIdx);

    if (OldVAddrIdx >= 0) {
      int NewVDstIn = AMDGPU::getNamedOperandIdx(NewOpc,
                                                 AMDGPU::OpName::vdst_in);

      // removeOperand doesn't try to fixup tied operand indexes at it goes, so
      // it asserts. Untie the operands for now and retie them afterwards.
      if (NewVDstIn != -1) {
        int OldVDstIn = AMDGPU::getNamedOperandIdx(Opc, AMDGPU::OpName::vdst_in);
        Inst.untieRegOperand(OldVDstIn);
      }

      Inst.removeOperand(OldVAddrIdx);

      if (NewVDstIn != -1) {
        int NewVDst = AMDGPU::getNamedOperandIdx(NewOpc, AMDGPU::OpName::vdst);
        Inst.tieOperands(NewVDst, NewVDstIn);
      }
    }
  }

  if (VAddrDef && MRI.use_nodbg_empty(VAddrDef->getOperand(0).getReg()))
    VAddrDef->eraseFromParent();

  return true;
}

// FIXME: Remove this when SelectionDAG is obsoleted.
void SIInstrInfo::legalizeOperandsFLAT(MachineRegisterInfo &MRI,
                                       MachineInstr &MI) const {
  if (!isSegmentSpecificFLAT(MI) && !ST.hasFlatGVSMode())
    return;

  // Fixup SGPR operands in VGPRs. We only select these when the DAG divergence
  // thinks they are uniform, so a readfirstlane should be valid.
  MachineOperand *SAddr = getNamedOperand(MI, AMDGPU::OpName::saddr);
  if (!SAddr || RI.isSGPRClass(MRI.getRegClass(SAddr->getReg())))
    return;

  if (moveFlatAddrToVGPR(MI))
    return;

  const TargetRegisterClass *DeclaredRC =
      getRegClass(MI.getDesc(), SAddr->getOperandNo());

  Register ToSGPR = readlaneVGPRToSGPR(SAddr->getReg(), MI, MRI, DeclaredRC);
  SAddr->setReg(ToSGPR);
}

void SIInstrInfo::legalizeGenericOperand(MachineBasicBlock &InsertMBB,
                                         MachineBasicBlock::iterator I,
                                         const TargetRegisterClass *DstRC,
                                         MachineOperand &Op,
                                         MachineRegisterInfo &MRI,
                                         const DebugLoc &DL) const {
  Register OpReg = Op.getReg();
  unsigned OpSubReg = Op.getSubReg();

  const TargetRegisterClass *OpRC = RI.getSubClassWithSubReg(
      RI.getRegClassForReg(MRI, OpReg), OpSubReg);

  // Check if operand is already the correct register class.
  if (DstRC == OpRC)
    return;

  Register DstReg = MRI.createVirtualRegister(DstRC);
  auto Copy =
      BuildMI(InsertMBB, I, DL, get(AMDGPU::COPY), DstReg).addReg(OpReg);
  Op.setReg(DstReg);

  MachineInstr *Def = MRI.getVRegDef(OpReg);
  if (!Def)
    return;

  // Try to eliminate the copy if it is copying an immediate value.
  if (Def->isMoveImmediate() && DstRC != &AMDGPU::VReg_1RegClass)
    foldImmediate(*Copy, *Def, OpReg, &MRI);

  bool ImpDef = Def->isImplicitDef();
  while (!ImpDef && Def && Def->isCopy()) {
    if (Def->getOperand(1).getReg().isPhysical())
      break;
    Def = MRI.getUniqueVRegDef(Def->getOperand(1).getReg());
    ImpDef = Def && Def->isImplicitDef();
  }
  if (!RI.isSGPRClass(DstRC) && !Copy->readsRegister(AMDGPU::EXEC, &RI) &&
      !ImpDef)
    Copy.addReg(AMDGPU::EXEC, RegState::Implicit);
}

// Emit the actual waterfall loop, executing the wrapped instruction for each
// unique value of \p ScalarOps across all lanes. In the best case we execute 1
// iteration, in the worst case we execute 64 (once per lane).
static void emitLoadScalarOpsFromVGPRLoop(
    const SIInstrInfo &TII, MachineRegisterInfo &MRI, MachineBasicBlock &PredBB,
    MachineBasicBlock &LoopBB, MachineBasicBlock &BodyBB, const DebugLoc &DL,
    ArrayRef<MachineOperand *> ScalarOps, ArrayRef<Register> PhySGPRs = {}) {
  MachineFunction &MF = *LoopBB.getParent();
  const GCNSubtarget &ST = MF.getSubtarget<GCNSubtarget>();
  const SIRegisterInfo *TRI = ST.getRegisterInfo();
  const AMDGPU::LaneMaskConstants &LMC = AMDGPU::LaneMaskConstants::get(ST);
  const auto *BoolXExecRC = TRI->getWaveMaskRegClass();

  // Emit v_cmpx_eq and s_andn2_wrexec when both instructions are
  // available. Otherwise, use the previous pattern of v_cmp_eq,
  // s_and_saveexec, and s_xor.
  bool UseNewExecInstructions =
      ST.hasNoSdstCMPX() && TII.pseudoToMCOpcode(LMC.AndN2WrExecOpc) != -1;

  MachineBasicBlock::iterator I = LoopBB.begin();
  Register CondReg;

  Register PhiExec;
  Register NewExec;

  if (UseNewExecInstructions) {
    PhiExec = MRI.createVirtualRegister(BoolXExecRC);
    NewExec = MRI.createVirtualRegister(BoolXExecRC);
    Register InitExec = MRI.createVirtualRegister(BoolXExecRC);
    BuildMI(PredBB, PredBB.end(), DL, TII.get(LMC.MovOpc), InitExec)
        .addReg(LMC.ExecReg);

    BuildMI(LoopBB, I, DL, TII.get(TargetOpcode::PHI), PhiExec)
        .addReg(InitExec)
        .addMBB(&PredBB)
        .addReg(NewExec)
        .addMBB(&BodyBB);
  }

  // Placement of v_cmpx instructions (when index is longer than 64 bit)
  // involves a trade-off between register pressure and latency:
  // (a) Defering all v_cmpx after all v_readfirstlane may increase
  // register pressure because arguments and results of all
  // v_readfirstlane instructions must stay live until deferred v_cmpx use them.
  // (b) Interleaving v_cmpx with v_readfirstlanes may reduce live ranges and
  // increase latency by placing v_readfirstlane instructions
  // immediately before v_cmpx instruction that directly depend on it.
  ///
  // Emitting interleaved v_cmpx and v_readfirstlane requires
  // block splitting because v_cmpx changes EXEC mask and therefore for safety
  // v_cmpx needs to be treated as terminator until after register allocation
  // (spill placement) and instruction reordering.
  //
  // Current implementation defers v_cmpx and leaves other instruction
  // scheduling decisions to later passes, where register pressure is known or
  // easier to approximate.
  // Non-terminators (V_READFIRSTLANE and REG_SEQUENCE) are inserted before I;
  // v_cmpx instructions are inserted at the end of LoopBB.
  // After the first v_cmpx is emitted, I is updated to point to it
  // so subsequent non-terminators are inserted before all v_cmpx instructions.
  for (auto [Idx, ScalarOp] : enumerate(ScalarOps)) {
    unsigned RegSize = TRI->getRegSizeInBits(ScalarOp->getReg(), MRI);
    unsigned NumSubRegs = RegSize / 32;
    Register VScalarOp = ScalarOp->getReg();

    const TargetRegisterClass *RFLSrcRC =
        TII.getRegClass(TII.get(AMDGPU::V_READFIRSTLANE_B32), 1);

    if (NumSubRegs == 1) {
      const TargetRegisterClass *VScalarOpRC = MRI.getRegClass(VScalarOp);
      if (const TargetRegisterClass *Common =
              TRI->getCommonSubClass(VScalarOpRC, RFLSrcRC);
          Common != VScalarOpRC) {
        Register VRReg = MRI.createVirtualRegister(Common);
        BuildMI(LoopBB, I, DL, TII.get(AMDGPU::COPY), VRReg).addReg(VScalarOp);
        VScalarOp = VRReg;
      }
      Register CurReg = MRI.createVirtualRegister(&AMDGPU::SReg_32_XM0RegClass);

      BuildMI(LoopBB, I, DL, TII.get(AMDGPU::V_READFIRSTLANE_B32), CurReg)
          .addReg(VScalarOp);

      if (UseNewExecInstructions) {
        auto CmpxMI = BuildMI(LoopBB, LoopBB.end(), DL,
                              TII.get(AMDGPU::V_CMPX_EQ_U32_nosdst_e32_term))
                          .addReg(CurReg)
                          .addReg(VScalarOp);
        if (I == LoopBB.end())
          I = CmpxMI.getInstr()->getIterator();
      } else {
        Register NewCondReg = MRI.createVirtualRegister(BoolXExecRC);

        BuildMI(LoopBB, I, DL, TII.get(AMDGPU::V_CMP_EQ_U32_e64), NewCondReg)
            .addReg(CurReg)
            .addReg(VScalarOp);

        // Combine the comparison results with AND.
        if (!CondReg) { // First.
          CondReg = NewCondReg;
        } else { // If not the first, we create an AND.
          Register AndReg = MRI.createVirtualRegister(BoolXExecRC);
          BuildMI(LoopBB, I, DL, TII.get(LMC.AndOpc), AndReg)
              .addReg(CondReg)
              .addReg(NewCondReg);
          CondReg = AndReg;
        }
      }

      // Update ScalarOp operand to use the SGPR ScalarOp.
      if (PhySGPRs.empty() || !PhySGPRs[Idx].isValid())
        ScalarOp->setReg(CurReg);
      else {
        // Insert into the same block of use
        BuildMI(*ScalarOp->getParent()->getParent(), ScalarOp->getParent(), DL,
                TII.get(AMDGPU::COPY), PhySGPRs[Idx])
            .addReg(CurReg);
        ScalarOp->setReg(PhySGPRs[Idx]);
      }
      ScalarOp->setIsKill();
    } else {
      SmallVector<Register, 8> ReadlanePieces;
      RegState VScalarOpUndef = getUndefRegState(ScalarOp->isUndef());
      assert(NumSubRegs % 2 == 0 && NumSubRegs <= 32 &&
             "Unhandled register size");

      for (unsigned Idx = 0; Idx < NumSubRegs; Idx += 2) {
        Register CurRegLo =
            MRI.createVirtualRegister(&AMDGPU::SReg_32_XM0RegClass);
        Register CurRegHi =
            MRI.createVirtualRegister(&AMDGPU::SReg_32_XM0RegClass);

        // Read the next variant <- also loop target.
        BuildMI(LoopBB, I, DL, TII.get(AMDGPU::V_READFIRSTLANE_B32), CurRegLo)
            .addReg(VScalarOp, VScalarOpUndef, TRI->getSubRegFromChannel(Idx));

        // Read the next variant <- also loop target.
        BuildMI(LoopBB, I, DL, TII.get(AMDGPU::V_READFIRSTLANE_B32), CurRegHi)
            .addReg(VScalarOp, VScalarOpUndef,
                    TRI->getSubRegFromChannel(Idx + 1));

        ReadlanePieces.push_back(CurRegLo);
        ReadlanePieces.push_back(CurRegHi);

        // Comparison is to be done as 64-bit.
        Register CurReg = MRI.createVirtualRegister(&AMDGPU::SGPR_64RegClass);
        BuildMI(LoopBB, I, DL, TII.get(AMDGPU::REG_SEQUENCE), CurReg)
            .addReg(CurRegLo)
            .addImm(AMDGPU::sub0)
            .addReg(CurRegHi)
            .addImm(AMDGPU::sub1);

        unsigned SubReg =
            NumSubRegs <= 2 ? 0 : TRI->getSubRegFromChannel(Idx, 2);

        if (UseNewExecInstructions) {
          auto CmpxMI = BuildMI(LoopBB, LoopBB.end(), DL,
                                TII.get(AMDGPU::V_CMPX_EQ_U64_nosdst_e32_term))
                            .addReg(CurReg)
                            .addReg(VScalarOp, VScalarOpUndef, SubReg);
          if (I == LoopBB.end())
            I = CmpxMI.getInstr()->getIterator();
        } else {
          Register NewCondReg = MRI.createVirtualRegister(BoolXExecRC);
          BuildMI(LoopBB, I, DL, TII.get(AMDGPU::V_CMP_EQ_U64_e64), NewCondReg)
              .addReg(CurReg)
              .addReg(VScalarOp, VScalarOpUndef, SubReg);

          // Combine the comparison results with AND.
          if (!CondReg) { // First.
            CondReg = NewCondReg;
          } else { // If not the first, we create an AND.
            Register AndReg = MRI.createVirtualRegister(BoolXExecRC);
            BuildMI(LoopBB, I, DL, TII.get(LMC.AndOpc), AndReg)
                .addReg(CondReg)
                .addReg(NewCondReg);
            CondReg = AndReg;
          }
        }
      } // End for loop.

      const auto *SScalarOpRC =
          TRI->getEquivalentSGPRClass(MRI.getRegClass(VScalarOp));
      Register SScalarOp = MRI.createVirtualRegister(SScalarOpRC);

      // Build scalar ScalarOp.
      auto Merge =
          BuildMI(LoopBB, I, DL, TII.get(AMDGPU::REG_SEQUENCE), SScalarOp);
      unsigned Channel = 0;
      for (Register Piece : ReadlanePieces) {
        Merge.addReg(Piece).addImm(TRI->getSubRegFromChannel(Channel++));
      }

      // Update ScalarOp operand to use the SGPR ScalarOp.
      if (PhySGPRs.empty() || !PhySGPRs[Idx].isValid())
        ScalarOp->setReg(SScalarOp);
      else {
        BuildMI(*ScalarOp->getParent()->getParent(), ScalarOp->getParent(), DL,
                TII.get(AMDGPU::COPY), PhySGPRs[Idx])
            .addReg(SScalarOp);
        ScalarOp->setReg(PhySGPRs[Idx]);
      }
      ScalarOp->setIsKill();
    }
  }

  // Instructions AndSaveExecOpc and AndN2WrExecOpc that modify EXEC mask
  // should have isTerminator=1 but terminators that define
  // virtual registers are not supported.
  Register SaveExec;
  if (!UseNewExecInstructions) {
    SaveExec = MRI.createVirtualRegister(BoolXExecRC);
    MRI.setSimpleHint(SaveExec, CondReg);

    // Update EXEC to matching lanes, saving original to SaveExec.
    BuildMI(LoopBB, I, DL, TII.get(LMC.AndSaveExecOpc), SaveExec)
        .addReg(CondReg, RegState::Kill);
  }

  // The original instruction is here; we insert the terminators after it.
  I = BodyBB.end();

  if (UseNewExecInstructions) {
    MRI.setSimpleHint(NewExec, PhiExec);
    BuildMI(BodyBB, I, DL, TII.get(LMC.AndN2WrExecOpc), NewExec)
        .addReg(PhiExec);
  } else {
    // Update EXEC, switch all done bits to 0 and all todo bits to 1.
    BuildMI(BodyBB, I, DL, TII.get(LMC.XorTermOpc), LMC.ExecReg)
        .addReg(LMC.ExecReg)
        .addReg(SaveExec);
  }

  BuildMI(BodyBB, I, DL, TII.get(AMDGPU::SI_WATERFALL_LOOP)).addMBB(&LoopBB);
}

// Build a waterfall loop around \p MI, replacing the VGPR \p ScalarOp register
// with SGPRs by iterating over all unique values across all lanes.
// Returns the loop basic block that now contains \p MI.
static MachineBasicBlock *
generateWaterFallLoop(const SIInstrInfo &TII, MachineInstr &MI,
                      ArrayRef<MachineOperand *> ScalarOps,
                      MachineDominatorTree *MDT,
                      MachineBasicBlock::iterator Begin = nullptr,
                      MachineBasicBlock::iterator End = nullptr,
                      ArrayRef<Register> PhySGPRs = {}) {
  assert((PhySGPRs.empty() || PhySGPRs.size() == ScalarOps.size()) &&
         "Physical SGPRs must be empty or match the number of scalar operands");
  MachineBasicBlock &MBB = *MI.getParent();
  MachineFunction &MF = *MBB.getParent();
  const GCNSubtarget &ST = MF.getSubtarget<GCNSubtarget>();
  const SIRegisterInfo *TRI = ST.getRegisterInfo();
  MachineRegisterInfo &MRI = MF.getRegInfo();
  if (!Begin.isValid())
    Begin = &MI;
  if (!End.isValid()) {
    End = &MI;
    ++End;
  }
  const DebugLoc &DL = MI.getDebugLoc();
  const AMDGPU::LaneMaskConstants &LMC = AMDGPU::LaneMaskConstants::get(ST);
  const auto *BoolXExecRC = TRI->getWaveMaskRegClass();

  // Save SCC. Waterfall Loop may overwrite SCC.
  Register SaveSCCReg;

  // FIXME: We should maintain SCC liveness while doing the FixSGPRCopies walk
  // rather than unlimited scan everywhere
  bool SCCNotDead =
      MBB.computeRegisterLiveness(TRI, AMDGPU::SCC, MI,
                                  std::numeric_limits<unsigned>::max()) !=
      MachineBasicBlock::LQR_Dead;
  if (SCCNotDead) {
    SaveSCCReg = MRI.createVirtualRegister(&AMDGPU::SReg_32RegClass);
    BuildMI(MBB, Begin, DL, TII.get(AMDGPU::S_CSELECT_B32), SaveSCCReg)
        .addImm(1)
        .addImm(0);
  }

  Register SaveExec = MRI.createVirtualRegister(BoolXExecRC);

  // Save the EXEC mask
  BuildMI(MBB, Begin, DL, TII.get(LMC.MovOpc), SaveExec).addReg(LMC.ExecReg);

  // Killed uses in the instruction we are waterfalling around will be
  // incorrect due to the added control-flow.
  MachineBasicBlock::iterator AfterMI = MI;
  ++AfterMI;
  for (auto I = Begin; I != AfterMI; I++) {
    for (auto &MO : I->all_uses())
      MRI.clearKillFlags(MO.getReg());
  }

  // To insert the loop we need to split the block. Move everything after this
  // point to a new block, and insert a new empty block between the two.
  MachineBasicBlock *LoopBB = MF.CreateMachineBasicBlock();
  MachineBasicBlock *BodyBB = MF.CreateMachineBasicBlock();
  MachineBasicBlock *RemainderBB = MF.CreateMachineBasicBlock();
  MachineFunction::iterator MBBI(MBB);
  ++MBBI;

  MF.insert(MBBI, LoopBB);
  MF.insert(MBBI, BodyBB);
  MF.insert(MBBI, RemainderBB);

  LoopBB->addSuccessor(BodyBB);
  BodyBB->addSuccessor(LoopBB);
  BodyBB->addSuccessor(RemainderBB);

  // Move Begin to MI to the BodyBB, and the remainder of the block to
  // RemainderBB.
  RemainderBB->transferSuccessorsAndUpdatePHIs(&MBB);
  RemainderBB->splice(RemainderBB->begin(), &MBB, End, MBB.end());
  BodyBB->splice(BodyBB->begin(), &MBB, Begin, MBB.end());

  MBB.addSuccessor(LoopBB);

  // Update dominators. We know that MBB immediately dominates LoopBB, that
  // LoopBB immediately dominates BodyBB, and BodyBB immediately dominates
  // RemainderBB. RemainderBB immediately dominates all of the successors
  // transferred to it from MBB that MBB used to properly dominate.
  if (MDT) {
    MDT->addNewBlock(LoopBB, &MBB);
    MDT->addNewBlock(BodyBB, LoopBB);
    MDT->addNewBlock(RemainderBB, BodyBB);
    for (auto &Succ : RemainderBB->successors()) {
      if (MDT->properlyDominates(&MBB, Succ)) {
        MDT->changeImmediateDominator(Succ, RemainderBB);
      }
    }
  }

  emitLoadScalarOpsFromVGPRLoop(TII, MRI, MBB, *LoopBB, *BodyBB, DL, ScalarOps,
                                PhySGPRs);

  MachineBasicBlock::iterator First = RemainderBB->begin();
  // Restore SCC
  if (SCCNotDead) {
    BuildMI(*RemainderBB, First, DL, TII.get(AMDGPU::S_CMP_LG_U32))
        .addReg(SaveSCCReg, RegState::Kill)
        .addImm(0);
  }

  // Restore the EXEC mask
  BuildMI(*RemainderBB, First, DL, TII.get(LMC.MovOpc), LMC.ExecReg)
      .addReg(SaveExec);
  return BodyBB;
}

// Extract pointer from Rsrc and return a zero-value Rsrc replacement.
static std::tuple<unsigned, unsigned>
extractRsrcPtr(const SIInstrInfo &TII, MachineInstr &MI, MachineOperand &Rsrc) {
  MachineBasicBlock &MBB = *MI.getParent();
  MachineFunction &MF = *MBB.getParent();
  MachineRegisterInfo &MRI = MF.getRegInfo();

  // Extract the ptr from the resource descriptor.
  unsigned RsrcPtr =
      TII.buildExtractSubReg(MI, MRI, Rsrc, &AMDGPU::VReg_128RegClass,
                             AMDGPU::sub0_sub1, &AMDGPU::VReg_64RegClass);

  // Create an empty resource descriptor
  Register Zero64 = MRI.createVirtualRegister(&AMDGPU::SReg_64RegClass);
  Register SRsrcFormatLo = MRI.createVirtualRegister(&AMDGPU::SGPR_32RegClass);
  Register SRsrcFormatHi = MRI.createVirtualRegister(&AMDGPU::SGPR_32RegClass);
  Register NewSRsrc = MRI.createVirtualRegister(&AMDGPU::SGPR_128RegClass);
  uint64_t RsrcDataFormat = TII.getDefaultRsrcDataFormat();

  // Zero64 = 0
  BuildMI(MBB, MI, MI.getDebugLoc(), TII.get(AMDGPU::S_MOV_B64), Zero64)
      .addImm(0);

  // SRsrcFormatLo = RSRC_DATA_FORMAT{31-0}
  BuildMI(MBB, MI, MI.getDebugLoc(), TII.get(AMDGPU::S_MOV_B32), SRsrcFormatLo)
      .addImm(Lo_32(RsrcDataFormat));

  // SRsrcFormatHi = RSRC_DATA_FORMAT{63-32}
  BuildMI(MBB, MI, MI.getDebugLoc(), TII.get(AMDGPU::S_MOV_B32), SRsrcFormatHi)
      .addImm(Hi_32(RsrcDataFormat));

  // NewSRsrc = {Zero64, SRsrcFormat}
  BuildMI(MBB, MI, MI.getDebugLoc(), TII.get(AMDGPU::REG_SEQUENCE), NewSRsrc)
      .addReg(Zero64)
      .addImm(AMDGPU::sub0_sub1)
      .addReg(SRsrcFormatLo)
      .addImm(AMDGPU::sub2)
      .addReg(SRsrcFormatHi)
      .addImm(AMDGPU::sub3);

  return std::tuple(RsrcPtr, NewSRsrc);
}

MachineBasicBlock *
SIInstrInfo::legalizeOperands(MachineInstr &MI,
                              MachineDominatorTree *MDT) const {
  MachineFunction &MF = *MI.getMF();
  MachineRegisterInfo &MRI = MF.getRegInfo();
  MachineBasicBlock *CreatedBB = nullptr;

  // Legalize VOP2
  if (isVOP2(MI) || isVOPC(MI)) {
    legalizeOperandsVOP2(MRI, MI);
    return CreatedBB;
  }

  // Legalize VOP3
  if (isVOP3(MI)) {
    legalizeOperandsVOP3(MRI, MI);
    return CreatedBB;
  }

  // Legalize SMRD
  if (isSMRD(MI)) {
    legalizeOperandsSMRD(MRI, MI);
    return CreatedBB;
  }

  // Legalize FLAT
  if (isFLAT(MI)) {
    legalizeOperandsFLAT(MRI, MI);
    return CreatedBB;
  }

  // Legalize PHI
  // The register class of the operands must be the same type as the register
  // class of the output.
  if (MI.getOpcode() == AMDGPU::PHI) {
    const TargetRegisterClass *VRC = getOpRegClass(MI, 0);
    assert(!RI.isSGPRClass(VRC));

    // Update all the operands so they have the same type.
    for (unsigned I = 1, E = MI.getNumOperands(); I != E; I += 2) {
      MachineOperand &Op = MI.getOperand(I);
      if (!Op.isReg() || !Op.getReg().isVirtual())
        continue;

      // MI is a PHI instruction.
      MachineBasicBlock *InsertBB = MI.getOperand(I + 1).getMBB();
      MachineBasicBlock::iterator Insert = InsertBB->getFirstTerminator();

      // Avoid creating no-op copies with the same src and dst reg class.  These
      // confuse some of the machine passes.
      legalizeGenericOperand(*InsertBB, Insert, VRC, Op, MRI, MI.getDebugLoc());
    }
  }

  // REG_SEQUENCE doesn't really require operand legalization, but if one has a
  // VGPR dest type and SGPR sources, insert copies so all operands are
  // VGPRs. This seems to help operand folding / the register coalescer.
  if (MI.getOpcode() == AMDGPU::REG_SEQUENCE) {
    MachineBasicBlock *MBB = MI.getParent();
    const TargetRegisterClass *DstRC = getOpRegClass(MI, 0);
    if (RI.hasVGPRs(DstRC)) {
      // Update all the operands so they are VGPR register classes. These may
      // not be the same register class because REG_SEQUENCE supports mixing
      // subregister index types e.g. sub0_sub1 + sub2 + sub3
      for (unsigned I = 1, E = MI.getNumOperands(); I != E; I += 2) {
        MachineOperand &Op = MI.getOperand(I);
        if (!Op.isReg() || !Op.getReg().isVirtual())
          continue;

        const TargetRegisterClass *OpRC = MRI.getRegClass(Op.getReg());
        const TargetRegisterClass *VRC = RI.getEquivalentVGPRClass(OpRC);
        if (VRC == OpRC)
          continue;

        legalizeGenericOperand(*MBB, MI, VRC, Op, MRI, MI.getDebugLoc());
        Op.setIsKill();
      }
    }

    return CreatedBB;
  }

  // Legalize INSERT_SUBREG
  // src0 must have the same register class as dst
  if (MI.getOpcode() == AMDGPU::INSERT_SUBREG) {
    Register Dst = MI.getOperand(0).getReg();
    Register Src0 = MI.getOperand(1).getReg();
    const TargetRegisterClass *DstRC = MRI.getRegClass(Dst);
    const TargetRegisterClass *Src0RC = MRI.getRegClass(Src0);
    if (DstRC != Src0RC) {
      MachineBasicBlock *MBB = MI.getParent();
      MachineOperand &Op = MI.getOperand(1);
      legalizeGenericOperand(*MBB, MI, DstRC, Op, MRI, MI.getDebugLoc());
    }
    return CreatedBB;
  }

  // Legalize SI_INIT_M0
  if (MI.getOpcode() == AMDGPU::SI_INIT_M0) {
    MachineOperand &Src = MI.getOperand(0);
    if (Src.isReg() && RI.hasVectorRegisters(MRI.getRegClass(Src.getReg())))
      Src.setReg(readlaneVGPRToSGPR(Src.getReg(), MI, MRI));
    return CreatedBB;
  }

  // Legalize S_BITREPLICATE, S_QUADMASK and S_WQM
  if (MI.getOpcode() == AMDGPU::S_BITREPLICATE_B64_B32 ||
      MI.getOpcode() == AMDGPU::S_QUADMASK_B32 ||
      MI.getOpcode() == AMDGPU::S_QUADMASK_B64 ||
      MI.getOpcode() == AMDGPU::S_WQM_B32 ||
      MI.getOpcode() == AMDGPU::S_WQM_B64 ||
      MI.getOpcode() == AMDGPU::S_INVERSE_BALLOT_U32 ||
      MI.getOpcode() == AMDGPU::S_INVERSE_BALLOT_U64) {
    MachineOperand &Src = MI.getOperand(1);
    if (Src.isReg() && RI.hasVectorRegisters(MRI.getRegClass(Src.getReg())))
      Src.setReg(readlaneVGPRToSGPR(Src.getReg(), MI, MRI));
    return CreatedBB;
  }

  // Legalize MIMG/VIMAGE/VSAMPLE and MUBUF/MTBUF for shaders.
  //
  // Shaders only generate MUBUF/MTBUF instructions via intrinsics or via
  // scratch memory access. In both cases, the legalization never involves
  // conversion to the addr64 form.
  if (isImage(MI) || (AMDGPU::isGraphics(MF.getFunction().getCallingConv()) &&
                      (isMUBUF(MI) || isMTBUF(MI)))) {
    AMDGPU::OpName RSrcOpName = (isVIMAGE(MI) || isVSAMPLE(MI))
                                    ? AMDGPU::OpName::rsrc
                                    : AMDGPU::OpName::srsrc;
    MachineOperand *SRsrc = getNamedOperand(MI, RSrcOpName);
    if (SRsrc && !RI.isSGPRClass(MRI.getRegClass(SRsrc->getReg())))
      CreatedBB = generateWaterFallLoop(*this, MI, {SRsrc}, MDT);

    AMDGPU::OpName SampOpName =
        isMIMG(MI) ? AMDGPU::OpName::ssamp : AMDGPU::OpName::samp;
    MachineOperand *SSamp = getNamedOperand(MI, SampOpName);
    if (SSamp && !RI.isSGPRClass(MRI.getRegClass(SSamp->getReg())))
      CreatedBB = generateWaterFallLoop(*this, MI, {SSamp}, MDT);

    return CreatedBB;
  }

  // Legalize SI_CALL
  if (MI.getOpcode() == AMDGPU::SI_CALL_ISEL) {
    MachineOperand *Dest = &MI.getOperand(0);
    if (!RI.isSGPRClass(MRI.getRegClass(Dest->getReg()))) {
      createWaterFallForSiCall(&MI, MDT, {Dest});
    }
  }

  // Legalize s_sleep_var.
  if (MI.getOpcode() == AMDGPU::S_SLEEP_VAR) {
    const DebugLoc &DL = MI.getDebugLoc();
    Register Reg = MRI.createVirtualRegister(&AMDGPU::SReg_32_XM0RegClass);
    int Src0Idx =
        AMDGPU::getNamedOperandIdx(MI.getOpcode(), AMDGPU::OpName::src0);
    MachineOperand &Src0 = MI.getOperand(Src0Idx);
    BuildMI(*MI.getParent(), MI, DL, get(AMDGPU::V_READFIRSTLANE_B32), Reg)
        .add(Src0);
    Src0.ChangeToRegister(Reg, false);
    return nullptr;
  }

  // Legalize TENSOR_LOAD_TO_LDS_d2/_d4, TENSOR_STORE_FROM_LDS_d2/_d4. All their
  // operands are scalar.
  if (MI.getOpcode() == AMDGPU::TENSOR_LOAD_TO_LDS_d2 ||
      MI.getOpcode() == AMDGPU::TENSOR_LOAD_TO_LDS_d4 ||
      MI.getOpcode() == AMDGPU::TENSOR_STORE_FROM_LDS_d2 ||
      MI.getOpcode() == AMDGPU::TENSOR_STORE_FROM_LDS_d4) {
    for (MachineOperand &Src : MI.explicit_operands()) {
      if (Src.isReg() && RI.hasVectorRegisters(MRI.getRegClass(Src.getReg())))
        Src.setReg(readlaneVGPRToSGPR(Src.getReg(), MI, MRI));
    }
    return CreatedBB;
  }

  // Legalize MUBUF instructions.
  bool isSoffsetLegal = true;
  int SoffsetIdx =
      AMDGPU::getNamedOperandIdx(MI.getOpcode(), AMDGPU::OpName::soffset);
  if (SoffsetIdx != -1) {
    MachineOperand *Soffset = &MI.getOperand(SoffsetIdx);
    if (Soffset->isReg() && Soffset->getReg().isVirtual() &&
        !RI.isSGPRClass(MRI.getRegClass(Soffset->getReg()))) {
      isSoffsetLegal = false;
    }
  }

  bool isRsrcLegal = true;
  int RsrcIdx =
      AMDGPU::getNamedOperandIdx(MI.getOpcode(), AMDGPU::OpName::srsrc);
  if (RsrcIdx != -1) {
    MachineOperand *Rsrc = &MI.getOperand(RsrcIdx);
    if (Rsrc->isReg() && !RI.isSGPRReg(MRI, Rsrc->getReg()))
      isRsrcLegal = false;
  }

  // The operands are legal.
  if (isRsrcLegal && isSoffsetLegal)
    return CreatedBB;

  if (!isRsrcLegal) {
    // Legalize a VGPR Rsrc
    //
    // If the instruction is _ADDR64, we can avoid a waterfall by extracting
    // the base pointer from the VGPR Rsrc, adding it to the VAddr, then using
    // a zero-value SRsrc.
    //
    // If the instruction is _OFFSET (both idxen and offen disabled), and we
    // support ADDR64 instructions, we can convert to ADDR64 and do the same as
    // above.
    //
    // Otherwise we are on non-ADDR64 hardware, and/or we have
    // idxen/offen/bothen and we fall back to a waterfall loop.

    MachineOperand *Rsrc = &MI.getOperand(RsrcIdx);
    MachineBasicBlock &MBB = *MI.getParent();

    MachineOperand *VAddr = getNamedOperand(MI, AMDGPU::OpName::vaddr);
    if (VAddr && AMDGPU::getIfAddr64Inst(MI.getOpcode()) != -1) {
      // This is already an ADDR64 instruction so we need to add the pointer
      // extracted from the resource descriptor to the current value of VAddr.
      Register NewVAddrLo = MRI.createVirtualRegister(&AMDGPU::VGPR_32RegClass);
      Register NewVAddrHi = MRI.createVirtualRegister(&AMDGPU::VGPR_32RegClass);
      Register NewVAddr = MRI.createVirtualRegister(&AMDGPU::VReg_64RegClass);

      const auto *BoolXExecRC = RI.getWaveMaskRegClass();
      Register CondReg0 = MRI.createVirtualRegister(BoolXExecRC);
      Register CondReg1 = MRI.createVirtualRegister(BoolXExecRC);

      unsigned RsrcPtr, NewSRsrc;
      std::tie(RsrcPtr, NewSRsrc) = extractRsrcPtr(*this, MI, *Rsrc);

      // NewVaddrLo = RsrcPtr:sub0 + VAddr:sub0
      const DebugLoc &DL = MI.getDebugLoc();
      BuildMI(MBB, MI, DL, get(AMDGPU::V_ADD_CO_U32_e64), NewVAddrLo)
          .addDef(CondReg0)
          .addReg(RsrcPtr, {}, AMDGPU::sub0)
          .addReg(VAddr->getReg(), {}, AMDGPU::sub0)
          .addImm(0);

      // NewVaddrHi = RsrcPtr:sub1 + VAddr:sub1
      BuildMI(MBB, MI, DL, get(AMDGPU::V_ADDC_U32_e64), NewVAddrHi)
          .addDef(CondReg1, RegState::Dead)
          .addReg(RsrcPtr, {}, AMDGPU::sub1)
          .addReg(VAddr->getReg(), {}, AMDGPU::sub1)
          .addReg(CondReg0, RegState::Kill)
          .addImm(0);

      // NewVaddr = {NewVaddrHi, NewVaddrLo}
      BuildMI(MBB, MI, MI.getDebugLoc(), get(AMDGPU::REG_SEQUENCE), NewVAddr)
          .addReg(NewVAddrLo)
          .addImm(AMDGPU::sub0)
          .addReg(NewVAddrHi)
          .addImm(AMDGPU::sub1);

      VAddr->setReg(NewVAddr);
      Rsrc->setReg(NewSRsrc);
    } else if (!VAddr && ST.hasAddr64()) {
      // This instructions is the _OFFSET variant, so we need to convert it to
      // ADDR64.
      assert(ST.getGeneration() < AMDGPUSubtarget::VOLCANIC_ISLANDS &&
             "FIXME: Need to emit flat atomics here");

      unsigned RsrcPtr, NewSRsrc;
      std::tie(RsrcPtr, NewSRsrc) = extractRsrcPtr(*this, MI, *Rsrc);

      Register NewVAddr = MRI.createVirtualRegister(&AMDGPU::VReg_64RegClass);
      MachineOperand *VData = getNamedOperand(MI, AMDGPU::OpName::vdata);
      MachineOperand *Offset = getNamedOperand(MI, AMDGPU::OpName::offset);
      MachineOperand *SOffset = getNamedOperand(MI, AMDGPU::OpName::soffset);
      unsigned Addr64Opcode = AMDGPU::getAddr64Inst(MI.getOpcode());

      // Atomics with return have an additional tied operand and are
      // missing some of the special bits.
      MachineOperand *VDataIn = getNamedOperand(MI, AMDGPU::OpName::vdata_in);
      MachineInstr *Addr64;

      if (!VDataIn) {
        // Regular buffer load / store.
        MachineInstrBuilder MIB =
            BuildMI(MBB, MI, MI.getDebugLoc(), get(Addr64Opcode))
                .add(*VData)
                .addReg(NewVAddr)
                .addReg(NewSRsrc)
                .add(*SOffset)
                .add(*Offset);

        if (const MachineOperand *CPol =
                getNamedOperand(MI, AMDGPU::OpName::cpol)) {
          MIB.addImm(CPol->getImm());
        }

        if (const MachineOperand *TFE =
                getNamedOperand(MI, AMDGPU::OpName::tfe)) {
          MIB.addImm(TFE->getImm());
        }

        MIB.addImm(getNamedImmOperand(MI, AMDGPU::OpName::swz));

        MIB.cloneMemRefs(MI);
        Addr64 = MIB;
      } else {
        // Atomics with return.
        Addr64 = BuildMI(MBB, MI, MI.getDebugLoc(), get(Addr64Opcode))
                     .add(*VData)
                     .add(*VDataIn)
                     .addReg(NewVAddr)
                     .addReg(NewSRsrc)
                     .add(*SOffset)
                     .add(*Offset)
                     .addImm(getNamedImmOperand(MI, AMDGPU::OpName::cpol))
                     .cloneMemRefs(MI);
      }

      MI.removeFromParent();

      // NewVaddr = {NewVaddrHi, NewVaddrLo}
      BuildMI(MBB, Addr64, Addr64->getDebugLoc(), get(AMDGPU::REG_SEQUENCE),
              NewVAddr)
          .addReg(RsrcPtr, {}, AMDGPU::sub0)
          .addImm(AMDGPU::sub0)
          .addReg(RsrcPtr, {}, AMDGPU::sub1)
          .addImm(AMDGPU::sub1);
    } else {
      // Legalize a VGPR Rsrc and soffset together.
      if (!isSoffsetLegal) {
        MachineOperand *Soffset = getNamedOperand(MI, AMDGPU::OpName::soffset);
        CreatedBB = generateWaterFallLoop(*this, MI, {Rsrc, Soffset}, MDT);
        return CreatedBB;
      }
      CreatedBB = generateWaterFallLoop(*this, MI, {Rsrc}, MDT);
      return CreatedBB;
    }
  }

  // Legalize a VGPR soffset.
  if (!isSoffsetLegal) {
    MachineOperand *Soffset = getNamedOperand(MI, AMDGPU::OpName::soffset);
    CreatedBB = generateWaterFallLoop(*this, MI, {Soffset}, MDT);
    return CreatedBB;
  }
  return CreatedBB;
}

void SIInstrWorklist::insert(MachineInstr *MI) {
  InstrList.insert(MI);
  // Add MBUF instructiosn to deferred list.
  int RsrcIdx =
      AMDGPU::getNamedOperandIdx(MI->getOpcode(), AMDGPU::OpName::srsrc);
  if (RsrcIdx != -1) {
    DeferredList.insert(MI);
  }
}

bool SIInstrWorklist::isDeferred(MachineInstr *MI) {
  return DeferredList.contains(MI);
}

// Legalize size mismatches between 16bit and 32bit registers in v2s copy
// lowering (change sgpr to vgpr).
// This is mainly caused by 16bit SALU and 16bit VALU using reg with different
// size. Need to legalize the size of the operands during the vgpr lowering
// chain. This can be removed after we have sgpr16 in place
void SIInstrInfo::legalizeOperandsVALUt16(MachineInstr &MI, unsigned OpIdx,
                                          MachineRegisterInfo &MRI) const {
  if (!ST.useRealTrue16Insts())
    return;

  unsigned Opcode = MI.getOpcode();
  MachineBasicBlock *MBB = MI.getParent();
  // Legalize operands and check for size mismatch
  if (!OpIdx || OpIdx >= MI.getNumExplicitOperands() ||
      OpIdx >= get(Opcode).getNumOperands() ||
      get(Opcode).operands()[OpIdx].RegClass == -1)
    return;

  MachineOperand &Op = MI.getOperand(OpIdx);
  if (!Op.isReg() || !Op.getReg().isVirtual())
    return;

  const TargetRegisterClass *CurrRC = MRI.getRegClass(Op.getReg());
  if (!RI.isVGPRClass(CurrRC))
    return;

  int16_t RCID = getOpRegClassID(get(Opcode).operands()[OpIdx]);
  const TargetRegisterClass *ExpectedRC = RI.getRegClass(RCID);
  if (RI.getMatchingSuperRegClass(CurrRC, ExpectedRC, AMDGPU::lo16)) {
    Op.setSubReg(AMDGPU::lo16);
  } else if (RI.getMatchingSuperRegClass(ExpectedRC, CurrRC, AMDGPU::lo16)) {
    const DebugLoc &DL = MI.getDebugLoc();
    Register NewDstReg = MRI.createVirtualRegister(&AMDGPU::VGPR_32RegClass);
    Register Undef = MRI.createVirtualRegister(&AMDGPU::VGPR_16RegClass);
    BuildMI(*MBB, MI, DL, get(AMDGPU::IMPLICIT_DEF), Undef);
    BuildMI(*MBB, MI, DL, get(AMDGPU::REG_SEQUENCE), NewDstReg)
        .addReg(Op.getReg())
        .addImm(AMDGPU::lo16)
        .addReg(Undef)
        .addImm(AMDGPU::hi16);
    Op.setReg(NewDstReg);
  }
}
void SIInstrInfo::legalizeOperandsVALUt16(MachineInstr &MI,
                                          MachineRegisterInfo &MRI) const {
  for (unsigned OpIdx = 1; OpIdx < MI.getNumExplicitOperands(); OpIdx++)
    legalizeOperandsVALUt16(MI, OpIdx, MRI);
}

void SIInstrInfo::createWaterFallForSiCall(MachineInstr *MI,
                                           MachineDominatorTree *MDT,
                                           ArrayRef<MachineOperand *> ScalarOps,
                                           ArrayRef<Register> PhySGPRs) const {
  assert(MI->getOpcode() == AMDGPU::SI_CALL_ISEL &&
         "This only handle waterfall for SI_CALL_ISEL");
  // Move everything between ADJCALLSTACKUP and ADJCALLSTACKDOWN and
  // following copies, we also need to move copies from and to physical
  // registers into the loop block.
  // Also move the copies to physical registers into the loop block
  MachineBasicBlock &MBB = *MI->getParent();
  MachineBasicBlock::iterator Start(MI);
  while (Start->getOpcode() != AMDGPU::ADJCALLSTACKUP)
    --Start;
  MachineBasicBlock::iterator End(MI);
  while (End->getOpcode() != AMDGPU::ADJCALLSTACKDOWN)
    ++End;

  // Also include following copies of the return value
  ++End;
  while (End != MBB.end() && End->isCopy() &&
         MI->definesRegister(End->getOperand(1).getReg(), &RI))
    ++End;

  generateWaterFallLoop(*this, *MI, ScalarOps, MDT, Start, End, PhySGPRs);
}

void SIInstrInfo::moveToVALU(SIInstrWorklist &Worklist,
                             MachineDominatorTree *MDT) const {
  DenseMap<MachineInstr *, V2PhysSCopyInfo> WaterFalls;
  DenseMap<MachineInstr *, bool> V2SPhyCopiesToErase;
  while (!Worklist.empty()) {
    MachineInstr &Inst = *Worklist.top();
    Worklist.erase_top();
    // Skip MachineInstr in the deferred list.
    if (Worklist.isDeferred(&Inst))
      continue;
    moveToVALUImpl(Worklist, MDT, Inst, WaterFalls, V2SPhyCopiesToErase);
  }

  // Deferred list of instructions will be processed once
  // all the MachineInstr in the worklist are done.
  for (MachineInstr *Inst : Worklist.getDeferredList()) {
    moveToVALUImpl(Worklist, MDT, *Inst, WaterFalls, V2SPhyCopiesToErase);
    assert(Worklist.empty() &&
           "Deferred MachineInstr are not supposed to re-populate worklist");
  }

  for (std::pair<MachineInstr *, V2PhysSCopyInfo> &Entry : WaterFalls) {
    if (Entry.first->getOpcode() == AMDGPU::SI_CALL_ISEL)
      createWaterFallForSiCall(Entry.first, MDT, Entry.second.MOs,
                               Entry.second.SGPRs);
  }

  for (std::pair<MachineInstr *, bool> Entry : V2SPhyCopiesToErase)
    if (Entry.second)
      Entry.first->eraseFromParent();
}
void SIInstrInfo::createReadFirstLaneFromCopyToPhysReg(
    MachineRegisterInfo &MRI, Register DstReg, MachineInstr &Inst) const {
  // If it's a copy of a VGPR to a physical SGPR, insert a V_READFIRSTLANE and
  // hope for the best.
  const TargetRegisterClass *DstRC = RI.getRegClassForReg(MRI, DstReg);
  ArrayRef<int16_t> SubRegIndices = RI.getRegSplitParts(DstRC, 4);
  if (SubRegIndices.size() <= 1) {
    Register NewDst = MRI.createVirtualRegister(&AMDGPU::SReg_32_XM0RegClass);
    BuildMI(*Inst.getParent(), &Inst, Inst.getDebugLoc(),
            get(AMDGPU::V_READFIRSTLANE_B32), NewDst)
        .add(Inst.getOperand(1));
    BuildMI(*Inst.getParent(), &Inst, Inst.getDebugLoc(), get(AMDGPU::COPY),
            DstReg)
        .addReg(NewDst);
  } else {
    SmallVector<Register, 8> DstRegs;
    for (int16_t Indice : SubRegIndices) {
      Register NewDst = MRI.createVirtualRegister(&AMDGPU::SReg_32_XM0RegClass);
      BuildMI(*Inst.getParent(), &Inst, Inst.getDebugLoc(),
              get(AMDGPU::V_READFIRSTLANE_B32), NewDst)
          .addReg(Inst.getOperand(1).getReg(), {}, Indice);

      DstRegs.push_back(NewDst);
    }
    MachineInstrBuilder MIB =
        BuildMI(*Inst.getParent(), &Inst, Inst.getDebugLoc(),
                get(AMDGPU::REG_SEQUENCE), DstReg);
    for (unsigned i = 0; i < SubRegIndices.size(); ++i) {
      MIB.addReg(DstRegs[i]);
      MIB.addImm(RI.getSubRegFromChannel(i));
    }
  }
}

void SIInstrInfo::handleCopyToPhysHelper(
    SIInstrWorklist &Worklist, Register DstReg, MachineInstr &Inst,
    MachineRegisterInfo &MRI,
    DenseMap<MachineInstr *, V2PhysSCopyInfo> &WaterFalls,
    DenseMap<MachineInstr *, bool> &V2SPhyCopiesToErase) const {
  if (DstReg == AMDGPU::M0) {
    createReadFirstLaneFromCopyToPhysReg(MRI, DstReg, Inst);
    V2SPhyCopiesToErase.try_emplace(&Inst, true);
    return;
  }
  Register SrcReg = Inst.getOperand(1).getReg();
  MachineBasicBlock::iterator I = Inst.getIterator();
  MachineBasicBlock::iterator E = Inst.getParent()->end();
  // Only search current block since phyreg's def & use cannot cross
  // blocks when MF.NoPhi = false.
  while (++I != E) {
    // For SI_CALL_ISEL users, replace the phys SGPR with the VGPR source
    // and record the operand for later waterfall loop generation.
    if (I->getOpcode() == AMDGPU::SI_CALL_ISEL) {
      MachineInstr *UseMI = &*I;
      for (unsigned i = 0; i < UseMI->getNumOperands(); ++i) {
        if (UseMI->getOperand(i).isReg() &&
            UseMI->getOperand(i).getReg() == DstReg) {
          MachineOperand *MO = &UseMI->getOperand(i);
          MO->setReg(SrcReg);
          V2PhysSCopyInfo &V2SCopyInfo = WaterFalls[UseMI];
          V2SCopyInfo.MOs.push_back(MO);
          V2SCopyInfo.SGPRs.push_back(DstReg);
          V2SPhyCopiesToErase.try_emplace(&Inst, true);
        }
      }
    } else if (I->getOpcode() == AMDGPU::SI_RETURN_TO_EPILOG &&
               I->getOperand(0).isReg() &&
               I->getOperand(0).getReg() == DstReg) {
      createReadFirstLaneFromCopyToPhysReg(MRI, DstReg, Inst);
      V2SPhyCopiesToErase.try_emplace(&Inst, true);
    } else if (I->readsRegister(DstReg, &RI)) {
      // COPY cannot be erased if other type of inst uses it.
      V2SPhyCopiesToErase[&Inst] = false;
    }
    if (I->findRegisterDefOperand(DstReg, &RI))
      break;
  }
}

void SIInstrInfo::moveToVALUImpl(
    SIInstrWorklist &Worklist, MachineDominatorTree *MDT, MachineInstr &Inst,
    DenseMap<MachineInstr *, V2PhysSCopyInfo> &WaterFalls,
    DenseMap<MachineInstr *, bool> &V2SPhyCopiesToErase) const {

  MachineBasicBlock *MBB = Inst.getParent();
  if (!MBB)
    return;
  MachineRegisterInfo &MRI = MBB->getParent()->getRegInfo();
  unsigned Opcode = Inst.getOpcode();
  unsigned NewOpcode = getVALUOp(Inst);
  const DebugLoc &DL = Inst.getDebugLoc();

  // Handle some special cases
  switch (Opcode) {
  default:
    break;
  case AMDGPU::S_ADD_I32:
  case AMDGPU::S_SUB_I32: {
    // FIXME: The u32 versions currently selected use the carry.
    bool Changed;
    MachineBasicBlock *CreatedBBTmp = nullptr;
    std::tie(Changed, CreatedBBTmp) = moveScalarAddSub(Worklist, Inst, MDT);
    if (Changed)
      return;

    // Default handling
    break;
  }

  case AMDGPU::S_MUL_U64:
    if (ST.hasVMulU64Inst()) {
      NewOpcode = AMDGPU::V_MUL_U64_e64;
      break;
    }
    // Split s_mul_u64 in 32-bit vector multiplications.
    splitScalarSMulU64(Worklist, Inst, MDT);
    Inst.eraseFromParent();
    return;

  case AMDGPU::S_MUL_U64_U32_PSEUDO:
  case AMDGPU::S_MUL_I64_I32_PSEUDO:
    // This is a special case of s_mul_u64 where all the operands are either
    // zero extended or sign extended.
    splitScalarSMulPseudo(Worklist, Inst, MDT);
    Inst.eraseFromParent();
    return;

  case AMDGPU::S_AND_B64:
    splitScalar64BitBinaryOp(Worklist, Inst, AMDGPU::S_AND_B32, MDT);
    Inst.eraseFromParent();
    return;

  case AMDGPU::S_OR_B64:
    splitScalar64BitBinaryOp(Worklist, Inst, AMDGPU::S_OR_B32, MDT);
    Inst.eraseFromParent();
    return;

  case AMDGPU::S_XOR_B64:
    splitScalar64BitBinaryOp(Worklist, Inst, AMDGPU::S_XOR_B32, MDT);
    Inst.eraseFromParent();
    return;

  case AMDGPU::S_NAND_B64:
    splitScalar64BitBinaryOp(Worklist, Inst, AMDGPU::S_NAND_B32, MDT);
    Inst.eraseFromParent();
    return;

  case AMDGPU::S_NOR_B64:
    splitScalar64BitBinaryOp(Worklist, Inst, AMDGPU::S_NOR_B32, MDT);
    Inst.eraseFromParent();
    return;

  case AMDGPU::S_XNOR_B64:
    if (ST.hasDLInsts())
      splitScalar64BitBinaryOp(Worklist, Inst, AMDGPU::S_XNOR_B32, MDT);
    else
      splitScalar64BitXnor(Worklist, Inst, MDT);
    Inst.eraseFromParent();
    return;

  case AMDGPU::S_ANDN2_B64:
    splitScalar64BitBinaryOp(Worklist, Inst, AMDGPU::S_ANDN2_B32, MDT);
    Inst.eraseFromParent();
    return;

  case AMDGPU::S_ORN2_B64:
    splitScalar64BitBinaryOp(Worklist, Inst, AMDGPU::S_ORN2_B32, MDT);
    Inst.eraseFromParent();
    return;

  case AMDGPU::S_BREV_B64:
    splitScalar64BitUnaryOp(Worklist, Inst, AMDGPU::S_BREV_B32, true);
    Inst.eraseFromParent();
    return;

  case AMDGPU::S_NOT_B64:
    splitScalar64BitUnaryOp(Worklist, Inst, AMDGPU::S_NOT_B32);
    Inst.eraseFromParent();
    return;

  case AMDGPU::S_BCNT1_I32_B64:
    splitScalar64BitBCNT(Worklist, Inst);
    Inst.eraseFromParent();
    return;

  case AMDGPU::S_BFE_I64:
    splitScalar64BitBFE(Worklist, Inst);
    Inst.eraseFromParent();
    return;

  case AMDGPU::S_FLBIT_I32_B64:
    splitScalar64BitCountOp(Worklist, Inst, AMDGPU::V_FFBH_U32_e32);
    Inst.eraseFromParent();
    return;
  case AMDGPU::S_FF1_I32_B64:
    splitScalar64BitCountOp(Worklist, Inst, AMDGPU::V_FFBL_B32_e32);
    Inst.eraseFromParent();
    return;

  case AMDGPU::S_LSHL_B32:
    if (ST.hasOnlyRevVALUShifts()) {
      NewOpcode = AMDGPU::V_LSHLREV_B32_e64;
      swapOperands(Inst);
    }
    break;
  case AMDGPU::S_ASHR_I32:
    if (ST.hasOnlyRevVALUShifts()) {
      NewOpcode = AMDGPU::V_ASHRREV_I32_e64;
      swapOperands(Inst);
    }
    break;
  case AMDGPU::S_LSHR_B32:
    if (ST.hasOnlyRevVALUShifts()) {
      NewOpcode = AMDGPU::V_LSHRREV_B32_e64;
      swapOperands(Inst);
    }
    break;
  case AMDGPU::S_LSHL_B64:
    if (ST.hasOnlyRevVALUShifts()) {
      NewOpcode = ST.getGeneration() >= AMDGPUSubtarget::GFX12
                      ? AMDGPU::V_LSHLREV_B64_pseudo_e64
                      : AMDGPU::V_LSHLREV_B64_e64;
      swapOperands(Inst);
    }
    break;
  case AMDGPU::S_ASHR_I64:
    if (ST.hasOnlyRevVALUShifts()) {
      NewOpcode = AMDGPU::V_ASHRREV_I64_e64;
      swapOperands(Inst);
    }
    break;
  case AMDGPU::S_LSHR_B64:
    if (ST.hasOnlyRevVALUShifts()) {
      NewOpcode = AMDGPU::V_LSHRREV_B64_e64;
      swapOperands(Inst);
    }
    break;

  case AMDGPU::S_ABS_I32:
    lowerScalarAbs(Worklist, Inst);
    Inst.eraseFromParent();
    return;

  case AMDGPU::S_ABSDIFF_I32:
    lowerScalarAbsDiff(Worklist, Inst);
    Inst.eraseFromParent();
    return;

  case AMDGPU::S_CBRANCH_SCC0:
  case AMDGPU::S_CBRANCH_SCC1: {
    // Clear unused bits of vcc
    Register CondReg = Inst.getOperand(1).getReg();
    bool IsSCC = CondReg == AMDGPU::SCC;
    const AMDGPU::LaneMaskConstants &LMC = AMDGPU::LaneMaskConstants::get(ST);
    BuildMI(*MBB, Inst, Inst.getDebugLoc(), get(LMC.AndOpc), LMC.VccReg)
        .addReg(LMC.ExecReg)
        .addReg(IsSCC ? LMC.VccReg : CondReg);
    Inst.removeOperand(1);
  } break;

  case AMDGPU::S_BFE_U64:
  case AMDGPU::S_BFM_B64:
    llvm_unreachable("Moving this op to VALU not implemented");

  case AMDGPU::S_PACK_LL_B32_B16:
  case AMDGPU::S_PACK_LH_B32_B16:
  case AMDGPU::S_PACK_HL_B32_B16:
  case AMDGPU::S_PACK_HH_B32_B16:
    movePackToVALU(Worklist, MRI, Inst);
    Inst.eraseFromParent();
    return;

  case AMDGPU::S_XNOR_B32:
    lowerScalarXnor(Worklist, Inst);
    Inst.eraseFromParent();
    return;

  case AMDGPU::S_NAND_B32:
    splitScalarNotBinop(Worklist, Inst, AMDGPU::S_AND_B32);
    Inst.eraseFromParent();
    return;

  case AMDGPU::S_NOR_B32:
    splitScalarNotBinop(Worklist, Inst, AMDGPU::S_OR_B32);
    Inst.eraseFromParent();
    return;

  case AMDGPU::S_ANDN2_B32:
    splitScalarBinOpN2(Worklist, Inst, AMDGPU::S_AND_B32);
    Inst.eraseFromParent();
    return;

  case AMDGPU::S_ORN2_B32:
    splitScalarBinOpN2(Worklist, Inst, AMDGPU::S_OR_B32);
    Inst.eraseFromParent();
    return;

  // TODO: remove as soon as everything is ready
  // to replace VGPR to SGPR copy with V_READFIRSTLANEs.
  // S_ADD/SUB_CO_PSEUDO as well as S_UADDO/USUBO_PSEUDO
  // can only be selected from the uniform SDNode.
  case AMDGPU::S_ADD_CO_PSEUDO:
  case AMDGPU::S_SUB_CO_PSEUDO: {
    unsigned Opc = (Inst.getOpcode() == AMDGPU::S_ADD_CO_PSEUDO)
                       ? AMDGPU::V_ADDC_U32_e64
                       : AMDGPU::V_SUBB_U32_e64;
    const auto *CarryRC = RI.getWaveMaskRegClass();

    Register CarryInReg = Inst.getOperand(4).getReg();
    if (!MRI.constrainRegClass(CarryInReg, CarryRC)) {
      Register NewCarryReg = MRI.createVirtualRegister(CarryRC);
      BuildMI(*MBB, Inst, Inst.getDebugLoc(), get(AMDGPU::COPY), NewCarryReg)
          .addReg(CarryInReg);
    }

    Register CarryOutReg = Inst.getOperand(1).getReg();

    Register DestReg = MRI.createVirtualRegister(RI.getEquivalentVGPRClass(
        MRI.getRegClass(Inst.getOperand(0).getReg())));
    MachineInstr *CarryOp =
        BuildMI(*MBB, &Inst, Inst.getDebugLoc(), get(Opc), DestReg)
            .addReg(CarryOutReg, RegState::Define)
            .add(Inst.getOperand(2))
            .add(Inst.getOperand(3))
            .addReg(CarryInReg)
            .addImm(0);
    legalizeOperands(*CarryOp);
    MRI.replaceRegWith(Inst.getOperand(0).getReg(), DestReg);
    addUsersToMoveToVALUWorklist(DestReg, MRI, Worklist);
    Inst.eraseFromParent();
  }
    return;
  case AMDGPU::S_UADDO_PSEUDO:
  case AMDGPU::S_USUBO_PSEUDO: {
    MachineOperand &Dest0 = Inst.getOperand(0);
    MachineOperand &Dest1 = Inst.getOperand(1);
    MachineOperand &Src0 = Inst.getOperand(2);
    MachineOperand &Src1 = Inst.getOperand(3);

    unsigned Opc = (Inst.getOpcode() == AMDGPU::S_UADDO_PSEUDO)
                       ? AMDGPU::V_ADD_CO_U32_e64
                       : AMDGPU::V_SUB_CO_U32_e64;
    const TargetRegisterClass *NewRC =
        RI.getEquivalentVGPRClass(MRI.getRegClass(Dest0.getReg()));
    Register DestReg = MRI.createVirtualRegister(NewRC);
    MachineInstr *NewInstr = BuildMI(*MBB, &Inst, DL, get(Opc), DestReg)
                                 .addReg(Dest1.getReg(), RegState::Define)
                                 .add(Src0)
                                 .add(Src1)
                                 .addImm(0); // clamp bit

    legalizeOperands(*NewInstr, MDT);
    MRI.replaceRegWith(Dest0.getReg(), DestReg);
    addUsersToMoveToVALUWorklist(DestReg, MRI, Worklist);
    Inst.eraseFromParent();
  }
    return;
  case AMDGPU::S_LSHL1_ADD_U32:
  case AMDGPU::S_LSHL2_ADD_U32:
  case AMDGPU::S_LSHL3_ADD_U32:
  case AMDGPU::S_LSHL4_ADD_U32: {
    MachineOperand &Dest = Inst.getOperand(0);
    MachineOperand &Src0 = Inst.getOperand(1);
    MachineOperand &Src1 = Inst.getOperand(2);
    unsigned ShiftAmt = (Opcode == AMDGPU::S_LSHL1_ADD_U32   ? 1
                         : Opcode == AMDGPU::S_LSHL2_ADD_U32 ? 2
                         : Opcode == AMDGPU::S_LSHL3_ADD_U32 ? 3
                                                             : 4);

    const TargetRegisterClass *NewRC =
        RI.getEquivalentVGPRClass(MRI.getRegClass(Dest.getReg()));
    Register DestReg = MRI.createVirtualRegister(NewRC);
    MachineInstr *NewInstr =
        BuildMI(*MBB, &Inst, DL, get(AMDGPU::V_LSHL_ADD_U32_e64), DestReg)
            .add(Src0)
            .addImm(ShiftAmt)
            .add(Src1);

    legalizeOperands(*NewInstr, MDT);
    MRI.replaceRegWith(Dest.getReg(), DestReg);
    addUsersToMoveToVALUWorklist(DestReg, MRI, Worklist);
    Inst.eraseFromParent();
  }
    return;
  case AMDGPU::S_CSELECT_B32:
  case AMDGPU::S_CSELECT_B64:
    lowerSelect(Worklist, Inst, MDT);
    Inst.eraseFromParent();
    return;
  case AMDGPU::S_CMP_EQ_I32:
  case AMDGPU::S_CMP_LG_I32:
  case AMDGPU::S_CMP_GT_I32:
  case AMDGPU::S_CMP_GE_I32:
  case AMDGPU::S_CMP_LT_I32:
  case AMDGPU::S_CMP_LE_I32:
  case AMDGPU::S_CMP_EQ_U32:
  case AMDGPU::S_CMP_LG_U32:
  case AMDGPU::S_CMP_GT_U32:
  case AMDGPU::S_CMP_GE_U32:
  case AMDGPU::S_CMP_LT_U32:
  case AMDGPU::S_CMP_LE_U32:
  case AMDGPU::S_CMP_EQ_U64:
  case AMDGPU::S_CMP_LG_U64:
  case AMDGPU::S_CMP_LT_F32:
  case AMDGPU::S_CMP_EQ_F32:
  case AMDGPU::S_CMP_LE_F32:
  case AMDGPU::S_CMP_GT_F32:
  case AMDGPU::S_CMP_LG_F32:
  case AMDGPU::S_CMP_GE_F32:
  case AMDGPU::S_CMP_O_F32:
  case AMDGPU::S_CMP_U_F32:
  case AMDGPU::S_CMP_NGE_F32:
  case AMDGPU::S_CMP_NLG_F32:
  case AMDGPU::S_CMP_NGT_F32:
  case AMDGPU::S_CMP_NLE_F32:
  case AMDGPU::S_CMP_NEQ_F32:
  case AMDGPU::S_CMP_NLT_F32: {
    Register CondReg = MRI.createVirtualRegister(RI.getWaveMaskRegClass());
    auto NewInstr =
        BuildMI(*MBB, Inst, Inst.getDebugLoc(), get(NewOpcode), CondReg)
            .setMIFlags(Inst.getFlags());
    if (AMDGPU::getNamedOperandIdx(NewOpcode, AMDGPU::OpName::src0_modifiers) >=
        0) {
      NewInstr
          .addImm(0)               // src0_modifiers
          .add(Inst.getOperand(0)) // src0
          .addImm(0)               // src1_modifiers
          .add(Inst.getOperand(1)) // src1
          .addImm(0);              // clamp
    } else {
      NewInstr.add(Inst.getOperand(0)).add(Inst.getOperand(1));
    }
    legalizeOperands(*NewInstr, MDT);
    int SCCIdx = Inst.findRegisterDefOperandIdx(AMDGPU::SCC, /*TRI=*/nullptr);
    const MachineOperand &SCCOp = Inst.getOperand(SCCIdx);
    addSCCDefUsersToVALUWorklist(SCCOp, Inst, Worklist, CondReg);
    Inst.eraseFromParent();
    return;
  }
  case AMDGPU::S_CMP_LT_F16:
  case AMDGPU::S_CMP_EQ_F16:
  case AMDGPU::S_CMP_LE_F16:
  case AMDGPU::S_CMP_GT_F16:
  case AMDGPU::S_CMP_LG_F16:
  case AMDGPU::S_CMP_GE_F16:
  case AMDGPU::S_CMP_O_F16:
  case AMDGPU::S_CMP_U_F16:
  case AMDGPU::S_CMP_NGE_F16:
  case AMDGPU::S_CMP_NLG_F16:
  case AMDGPU::S_CMP_NGT_F16:
  case AMDGPU::S_CMP_NLE_F16:
  case AMDGPU::S_CMP_NEQ_F16:
  case AMDGPU::S_CMP_NLT_F16: {
    Register CondReg = MRI.createVirtualRegister(RI.getWaveMaskRegClass());
    auto NewInstr =
        BuildMI(*MBB, Inst, Inst.getDebugLoc(), get(NewOpcode), CondReg)
        .setMIFlags(Inst.getFlags());
    if (AMDGPU::hasNamedOperand(NewOpcode, AMDGPU::OpName::src0_modifiers)) {
      NewInstr
          .addImm(0)               // src0_modifiers
          .add(Inst.getOperand(0)) // src0
          .addImm(0)               // src1_modifiers
          .add(Inst.getOperand(1)) // src1
          .addImm(0);              // clamp
      if (AMDGPU::hasNamedOperand(NewOpcode, AMDGPU::OpName::op_sel))
        NewInstr.addImm(0); // op_sel0
    } else {
      NewInstr
          .add(Inst.getOperand(0))
          .add(Inst.getOperand(1));
    }
    legalizeOperandsVALUt16(*NewInstr, MRI);
    legalizeOperands(*NewInstr, MDT);
    int SCCIdx = Inst.findRegisterDefOperandIdx(AMDGPU::SCC, /*TRI=*/nullptr);
    const MachineOperand &SCCOp = Inst.getOperand(SCCIdx);
    addSCCDefUsersToVALUWorklist(SCCOp, Inst, Worklist, CondReg);
    Inst.eraseFromParent();
    return;
  }
  case AMDGPU::S_CVT_HI_F32_F16: {
    Register TmpReg = MRI.createVirtualRegister(&AMDGPU::VGPR_32RegClass);
    Register NewDst = MRI.createVirtualRegister(&AMDGPU::VGPR_32RegClass);
    if (ST.useRealTrue16Insts()) {
      BuildMI(*MBB, Inst, DL, get(AMDGPU::COPY), TmpReg)
          .add(Inst.getOperand(1));
      BuildMI(*MBB, Inst, DL, get(NewOpcode), NewDst)
          .addImm(0) // src0_modifiers
          .addReg(TmpReg, {}, AMDGPU::hi16)
          .addImm(0)  // clamp
          .addImm(0)  // omod
          .addImm(0); // op_sel0
    } else {
      BuildMI(*MBB, Inst, DL, get(AMDGPU::V_LSHRREV_B32_e64), TmpReg)
          .addImm(16)
          .add(Inst.getOperand(1));
      BuildMI(*MBB, Inst, DL, get(NewOpcode), NewDst)
          .addImm(0) // src0_modifiers
          .addReg(TmpReg)
          .addImm(0)  // clamp
          .addImm(0); // omod
    }

    MRI.replaceRegWith(Inst.getOperand(0).getReg(), NewDst);
    addUsersToMoveToVALUWorklist(NewDst, MRI, Worklist);
    Inst.eraseFromParent();
    return;
  }
  case AMDGPU::S_MINIMUM_F32:
  case AMDGPU::S_MAXIMUM_F32: {
    Register NewDst = MRI.createVirtualRegister(&AMDGPU::VGPR_32RegClass);
    MachineInstr *NewInstr = BuildMI(*MBB, Inst, DL, get(NewOpcode), NewDst)
                                 .addImm(0) // src0_modifiers
                                 .add(Inst.getOperand(1))
                                 .addImm(0) // src1_modifiers
                                 .add(Inst.getOperand(2))
                                 .addImm(0)  // clamp
                                 .addImm(0); // omod
    MRI.replaceRegWith(Inst.getOperand(0).getReg(), NewDst);

    legalizeOperands(*NewInstr, MDT);
    addUsersToMoveToVALUWorklist(NewDst, MRI, Worklist);
    Inst.eraseFromParent();
    return;
  }
  case AMDGPU::S_MINIMUM_F16:
  case AMDGPU::S_MAXIMUM_F16: {
    Register NewDst = MRI.createVirtualRegister(ST.useRealTrue16Insts()
                                                    ? &AMDGPU::VGPR_16RegClass
                                                    : &AMDGPU::VGPR_32RegClass);
    MachineInstr *NewInstr = BuildMI(*MBB, Inst, DL, get(NewOpcode), NewDst)
                                 .addImm(0) // src0_modifiers
                                 .add(Inst.getOperand(1))
                                 .addImm(0) // src1_modifiers
                                 .add(Inst.getOperand(2))
                                 .addImm(0)  // clamp
                                 .addImm(0)  // omod
                                 .addImm(0); // opsel0
    MRI.replaceRegWith(Inst.getOperand(0).getReg(), NewDst);
    legalizeOperandsVALUt16(*NewInstr, MRI);
    legalizeOperands(*NewInstr, MDT);
    addUsersToMoveToVALUWorklist(NewDst, MRI, Worklist);
    Inst.eraseFromParent();
    return;
  }
  case AMDGPU::V_S_EXP_F16_e64:
  case AMDGPU::V_S_LOG_F16_e64:
  case AMDGPU::V_S_RCP_F16_e64:
  case AMDGPU::V_S_RSQ_F16_e64:
  case AMDGPU::V_S_SQRT_F16_e64: {
    Register NewDst = MRI.createVirtualRegister(ST.useRealTrue16Insts()
                                                    ? &AMDGPU::VGPR_16RegClass
                                                    : &AMDGPU::VGPR_32RegClass);
    auto NewInstr = BuildMI(*MBB, Inst, DL, get(NewOpcode), NewDst)
                        .add(Inst.getOperand(1)) // src0_modifiers
                        .add(Inst.getOperand(2))
                        .add(Inst.getOperand(3)) // clamp
                        .add(Inst.getOperand(4)) // omod
                        .setMIFlags(Inst.getFlags());
    if (AMDGPU::hasNamedOperand(NewOpcode, AMDGPU::OpName::op_sel))
      NewInstr.addImm(0); // opsel0
    MRI.replaceRegWith(Inst.getOperand(0).getReg(), NewDst);
    legalizeOperandsVALUt16(*NewInstr, MRI);
    legalizeOperands(*NewInstr, MDT);
    addUsersToMoveToVALUWorklist(NewDst, MRI, Worklist);
    Inst.eraseFromParent();
    return;
  }
  }

  if (NewOpcode == AMDGPU::INSTRUCTION_LIST_END) {
    // We cannot move this instruction to the VALU, so we should try to
    // legalize its operands instead.
    legalizeOperands(Inst, MDT);
    return;
  }
  // Handle converting generic instructions like COPY-to-SGPR into
  // COPY-to-VGPR.
  if (NewOpcode == Opcode) {
    Register DstReg = Inst.getOperand(0).getReg();
    const TargetRegisterClass *NewDstRC = getDestEquivalentVGPRClass(Inst);

    if (Inst.isCopy() && DstReg.isPhysical() &&
        Inst.getOperand(1).getReg().isVirtual()) {
      handleCopyToPhysHelper(Worklist, DstReg, Inst, MRI, WaterFalls,
                             V2SPhyCopiesToErase);
      return;
    }

    if (Inst.isCopy() && Inst.getOperand(1).getReg().isVirtual()) {
      Register NewDstReg = Inst.getOperand(1).getReg();
      const TargetRegisterClass *SrcRC = RI.getRegClassForReg(MRI, NewDstReg);
      if (const TargetRegisterClass *CommonRC =
              RI.getCommonSubClass(NewDstRC, SrcRC)) {
        // Instead of creating a copy where src and dst are the same register
        // class, we just replace all uses of dst with src.  These kinds of
        // copies interfere with the heuristics MachineSink uses to decide
        // whether or not to split a critical edge.  Since the pass assumes
        // that copies will end up as machine instructions and not be
        // eliminated.
        addUsersToMoveToVALUWorklist(DstReg, MRI, Worklist);
        MRI.replaceRegWith(DstReg, NewDstReg);
        MRI.clearKillFlags(NewDstReg);
        Inst.getOperand(0).setReg(DstReg);

        if (!MRI.constrainRegClass(NewDstReg, CommonRC))
          llvm_unreachable("failed to constrain register");

        Inst.eraseFromParent();

        for (MachineOperand &UseMO :
             make_early_inc_range(MRI.use_operands(NewDstReg))) {
          MachineInstr &UseMI = *UseMO.getParent();

          // Legalize t16 operands since replaceReg is called after
          // addUsersToVALU.
          legalizeOperandsVALUt16(UseMI, MRI);

          unsigned OpIdx = UseMI.getOperandNo(&UseMO);
          if (const TargetRegisterClass *OpRC =
                  getRegClass(UseMI.getDesc(), OpIdx))
            MRI.constrainRegClass(NewDstReg, OpRC);
        }

        return;
      }
    }

    // If this is a v2s copy between 16bit and 32bit reg,
    // replace vgpr copy to reg_sequence/extract_subreg
    // This can be remove after we have sgpr16 in place
    if (ST.useRealTrue16Insts() && Inst.isCopy() &&
        Inst.getOperand(1).getReg().isVirtual() &&
        RI.isVGPR(MRI, Inst.getOperand(1).getReg())) {
      const TargetRegisterClass *SrcRegRC = getOpRegClass(Inst, 1);
      if (RI.getMatchingSuperRegClass(NewDstRC, SrcRegRC, AMDGPU::lo16)) {
        Register NewDstReg = MRI.createVirtualRegister(NewDstRC);
        Register Undef = MRI.createVirtualRegister(&AMDGPU::VGPR_16RegClass);
        BuildMI(*Inst.getParent(), &Inst, Inst.getDebugLoc(),
                get(AMDGPU::IMPLICIT_DEF), Undef);
        BuildMI(*Inst.getParent(), &Inst, Inst.getDebugLoc(),
                get(AMDGPU::REG_SEQUENCE), NewDstReg)
            .addReg(Inst.getOperand(1).getReg())
            .addImm(AMDGPU::lo16)
            .addReg(Undef)
            .addImm(AMDGPU::hi16);
        Inst.eraseFromParent();
        MRI.replaceRegWith(DstReg, NewDstReg);
        addUsersToMoveToVALUWorklist(NewDstReg, MRI, Worklist);
        return;
      } else if (RI.getMatchingSuperRegClass(SrcRegRC, NewDstRC,
                                             AMDGPU::lo16)) {
        Inst.getOperand(1).setSubReg(AMDGPU::lo16);
        Register NewDstReg = MRI.createVirtualRegister(NewDstRC);
        MRI.replaceRegWith(DstReg, NewDstReg);
        addUsersToMoveToVALUWorklist(NewDstReg, MRI, Worklist);
        return;
      }
    }

    Register NewDstReg = MRI.createVirtualRegister(NewDstRC);
    MRI.replaceRegWith(DstReg, NewDstReg);
    legalizeOperands(Inst, MDT);
    addUsersToMoveToVALUWorklist(NewDstReg, MRI, Worklist);
    return;
  }

  // Use the new VALU Opcode.
  auto NewInstr = BuildMI(*MBB, Inst, Inst.getDebugLoc(), get(NewOpcode))
                      .setMIFlags(Inst.getFlags());
  if (isVOP3(NewOpcode) && !isVOP3(Opcode)) {
    // Intersperse VOP3 modifiers among the SALU operands.
    NewInstr->addOperand(Inst.getOperand(0));
    if (AMDGPU::getNamedOperandIdx(NewOpcode,
                                   AMDGPU::OpName::src0_modifiers) >= 0)
      NewInstr.addImm(0);
    if (AMDGPU::hasNamedOperand(NewOpcode, AMDGPU::OpName::src0)) {
      const MachineOperand &Src = Inst.getOperand(1);
      NewInstr->addOperand(Src);
    }

    if (Opcode == AMDGPU::S_SEXT_I32_I8 || Opcode == AMDGPU::S_SEXT_I32_I16) {
      // We are converting these to a BFE, so we need to add the missing
      // operands for the size and offset.
      unsigned Size = (Opcode == AMDGPU::S_SEXT_I32_I8) ? 8 : 16;
      NewInstr.addImm(0);
      NewInstr.addImm(Size);
    } else if (Opcode == AMDGPU::S_BCNT1_I32_B32) {
      // The VALU version adds the second operand to the result, so insert an
      // extra 0 operand.
      NewInstr.addImm(0);
    } else if (Opcode == AMDGPU::S_BFE_I32 || Opcode == AMDGPU::S_BFE_U32) {
      const MachineOperand &OffsetWidthOp = Inst.getOperand(2);
      // If we need to move this to VGPRs, we need to unpack the second
      // operand back into the 2 separate ones for bit offset and width.
      assert(OffsetWidthOp.isImm() &&
             "Scalar BFE is only implemented for constant width and offset");
      uint32_t Imm = OffsetWidthOp.getImm();

      uint32_t Offset = Imm & 0x3f;               // Extract bits [5:0].
      uint32_t BitWidth = (Imm & 0x7f0000) >> 16; // Extract bits [22:16].
      NewInstr.addImm(Offset);
      NewInstr.addImm(BitWidth);
    } else {
      if (AMDGPU::getNamedOperandIdx(NewOpcode,
                                     AMDGPU::OpName::src1_modifiers) >= 0)
        NewInstr.addImm(0);
      if (AMDGPU::getNamedOperandIdx(NewOpcode, AMDGPU::OpName::src1) >= 0)
        NewInstr->addOperand(Inst.getOperand(2));
      if (AMDGPU::getNamedOperandIdx(NewOpcode,
                                     AMDGPU::OpName::src2_modifiers) >= 0)
        NewInstr.addImm(0);
      if (AMDGPU::getNamedOperandIdx(NewOpcode, AMDGPU::OpName::src2) >= 0)
        NewInstr->addOperand(Inst.getOperand(3));
      if (AMDGPU::getNamedOperandIdx(NewOpcode, AMDGPU::OpName::clamp) >= 0)
        NewInstr.addImm(0);
      if (AMDGPU::getNamedOperandIdx(NewOpcode, AMDGPU::OpName::omod) >= 0)
        NewInstr.addImm(0);
      if (AMDGPU::getNamedOperandIdx(NewOpcode, AMDGPU::OpName::op_sel) >= 0)
        NewInstr.addImm(0);
    }
  } else {
    // Just copy the SALU operands.
    for (const MachineOperand &Op : Inst.explicit_operands())
      NewInstr->addOperand(Op);
  }

  // Remove any references to SCC. Vector instructions can't read from it, and
  // We're just about to add the implicit use / defs of VCC, and we don't want
  // both.
  for (MachineOperand &Op : Inst.implicit_operands()) {
    if (Op.getReg() == AMDGPU::SCC) {
      // Only propagate through live-def of SCC.
      if (Op.isDef() && !Op.isDead())
        addSCCDefUsersToVALUWorklist(Op, Inst, Worklist);
      if (Op.isUse())
        addSCCDefsToVALUWorklist(NewInstr, Worklist);
    }
  }
  Inst.eraseFromParent();
  Register NewDstReg;
  if (NewInstr->getOperand(0).isReg() && NewInstr->getOperand(0).isDef()) {
    Register DstReg = NewInstr->getOperand(0).getReg();
    assert(DstReg.isVirtual());
    // Update the destination register class.
    const TargetRegisterClass *NewDstRC = getDestEquivalentVGPRClass(*NewInstr);
    assert(NewDstRC);
    NewDstReg = MRI.createVirtualRegister(NewDstRC);
    MRI.replaceRegWith(DstReg, NewDstReg);
  }
  fixImplicitOperands(*NewInstr);

  legalizeOperandsVALUt16(*NewInstr, MRI);

  // Legalize the operands
  legalizeOperands(*NewInstr, MDT);
  if (NewDstReg)
    addUsersToMoveToVALUWorklist(NewDstReg, MRI, Worklist);
}

// Add/sub require special handling to deal with carry outs.
std::pair<bool, MachineBasicBlock *>
SIInstrInfo::moveScalarAddSub(SIInstrWorklist &Worklist, MachineInstr &Inst,
                              MachineDominatorTree *MDT) const {
  if (ST.hasAddNoCarryInsts()) {
    // Assume there is no user of scc since we don't select this in that case.
    // Since scc isn't used, it doesn't really matter if the i32 or u32 variant
    // is used.

    MachineBasicBlock &MBB = *Inst.getParent();
    MachineRegisterInfo &MRI = MBB.getParent()->getRegInfo();

    Register OldDstReg = Inst.getOperand(0).getReg();
    Register ResultReg = MRI.createVirtualRegister(&AMDGPU::VGPR_32RegClass);

    unsigned Opc = Inst.getOpcode();
    assert(Opc == AMDGPU::S_ADD_I32 || Opc == AMDGPU::S_SUB_I32);

    unsigned NewOpc = Opc == AMDGPU::S_ADD_I32 ?
      AMDGPU::V_ADD_U32_e64 : AMDGPU::V_SUB_U32_e64;

    assert(Inst.getOperand(3).getReg() == AMDGPU::SCC);
    Inst.removeOperand(3);

    Inst.setDesc(get(NewOpc));
    Inst.addOperand(MachineOperand::CreateImm(0)); // clamp bit
    Inst.addImplicitDefUseOperands(*MBB.getParent());
    MRI.replaceRegWith(OldDstReg, ResultReg);
    MachineBasicBlock *NewBB = legalizeOperands(Inst, MDT);

    addUsersToMoveToVALUWorklist(ResultReg, MRI, Worklist);
    return std::pair(true, NewBB);
  }

  return std::pair(false, nullptr);
}

void SIInstrInfo::lowerSelect(SIInstrWorklist &Worklist, MachineInstr &Inst,
                              MachineDominatorTree *MDT) const {

  MachineBasicBlock &MBB = *Inst.getParent();
  MachineRegisterInfo &MRI = MBB.getParent()->getRegInfo();
  MachineBasicBlock::iterator MII = Inst;
  const DebugLoc &DL = Inst.getDebugLoc();

  MachineOperand &Dest = Inst.getOperand(0);
  MachineOperand &Src0 = Inst.getOperand(1);
  MachineOperand &Src1 = Inst.getOperand(2);
  MachineOperand &Cond = Inst.getOperand(3);

  Register CondReg = Cond.getReg();
  bool IsSCC = (CondReg == AMDGPU::SCC);

  // Remove S_CSELECT instructions that we previously inserted to feed the SCC
  // condition output from S_CMP into the SGPR condition input of V_CNDMASK. If
  // the S_CMP has been promoted to V_CMP then we can feed its SGPR condition
  // output directly into the V_CNDMASK.
  if (!IsSCC && Src0.isImm() && (Src0.getImm() == -1) && Src1.isImm() &&
      (Src1.getImm() == 0)) {
    for (MachineOperand &UseMO :
         make_early_inc_range(MRI.use_nodbg_operands(Dest.getReg()))) {
      MachineInstr &UseMI = *UseMO.getParent();
      switch (UseMI.getOpcode()) {
      case AMDGPU::V_CNDMASK_B16_fake16_e32:
      case AMDGPU::V_CNDMASK_B16_fake16_e64:
      case AMDGPU::V_CNDMASK_B16_t16_e32:
      case AMDGPU::V_CNDMASK_B16_t16_e64:
      case AMDGPU::V_CNDMASK_B32_e32:
      case AMDGPU::V_CNDMASK_B32_e64:
      case AMDGPU::V_CNDMASK_B64_PSEUDO:
        if (UseMO.isImplicit() ||
            &UseMO == getNamedOperand(UseMI, AMDGPU::OpName::src2))
          UseMO.setReg(CondReg);
      }
    }
    if (MRI.use_nodbg_empty(Dest.getReg()))
      return;
  }

  Register NewCondReg = CondReg;
  if (IsSCC) {
    const TargetRegisterClass *TC = RI.getWaveMaskRegClass();
    NewCondReg = MRI.createVirtualRegister(TC);

    // Now look for the closest SCC def if it is a copy
    // replacing the CondReg with the COPY source register
    bool CopyFound = false;
    for (MachineInstr &CandI :
         make_range(std::next(MachineBasicBlock::reverse_iterator(Inst)),
                    Inst.getParent()->rend())) {
      if (CandI.findRegisterDefOperandIdx(AMDGPU::SCC, &RI, false, false) !=
          -1) {
        if (CandI.isCopy() && CandI.getOperand(0).getReg() == AMDGPU::SCC) {
          BuildMI(MBB, MII, DL, get(AMDGPU::COPY), NewCondReg)
              .addReg(CandI.getOperand(1).getReg());
          CopyFound = true;
        }
        break;
      }
    }
    if (!CopyFound) {
      // SCC def is not a copy
      // Insert a trivial select instead of creating a copy, because a copy from
      // SCC would semantically mean just copying a single bit, but we may need
      // the result to be a vector condition mask that needs preserving.
      unsigned Opcode =
          ST.isWave64() ? AMDGPU::S_CSELECT_B64 : AMDGPU::S_CSELECT_B32;
      auto NewSelect =
          BuildMI(MBB, MII, DL, get(Opcode), NewCondReg).addImm(-1).addImm(0);
      NewSelect->getOperand(3).setIsUndef(Cond.isUndef());
    }
  }

  Register NewDestReg = MRI.createVirtualRegister(
      RI.getEquivalentVGPRClass(MRI.getRegClass(Dest.getReg())));
  MachineInstr *NewInst;
  if (Inst.getOpcode() == AMDGPU::S_CSELECT_B32) {
    NewInst = BuildMI(MBB, MII, DL, get(AMDGPU::V_CNDMASK_B32_e64), NewDestReg)
                  .addImm(0)
                  .add(Src1) // False
                  .addImm(0)
                  .add(Src0) // True
                  .addReg(NewCondReg);
  } else {
    NewInst =
        BuildMI(MBB, MII, DL, get(AMDGPU::V_CNDMASK_B64_PSEUDO), NewDestReg)
            .add(Src1) // False
            .add(Src0) // True
            .addReg(NewCondReg);
  }
  MRI.replaceRegWith(Dest.getReg(), NewDestReg);
  legalizeOperands(*NewInst, MDT);
  addUsersToMoveToVALUWorklist(NewDestReg, MRI, Worklist);
}

void SIInstrInfo::lowerScalarAbs(SIInstrWorklist &Worklist,
                                 MachineInstr &Inst) const {
  MachineBasicBlock &MBB = *Inst.getParent();
  MachineRegisterInfo &MRI = MBB.getParent()->getRegInfo();
  MachineBasicBlock::iterator MII = Inst;
  const DebugLoc &DL = Inst.getDebugLoc();

  MachineOperand &Dest = Inst.getOperand(0);
  MachineOperand &Src = Inst.getOperand(1);
  Register TmpReg = MRI.createVirtualRegister(&AMDGPU::VGPR_32RegClass);
  Register ResultReg = MRI.createVirtualRegister(&AMDGPU::VGPR_32RegClass);

  unsigned SubOp = ST.hasAddNoCarryInsts() ? AMDGPU::V_SUB_U32_e32
                                           : AMDGPU::V_SUB_CO_U32_e32;

  BuildMI(MBB, MII, DL, get(SubOp), TmpReg)
    .addImm(0)
    .addReg(Src.getReg());

  BuildMI(MBB, MII, DL, get(AMDGPU::V_MAX_I32_e64), ResultReg)
    .addReg(Src.getReg())
    .addReg(TmpReg);

  MRI.replaceRegWith(Dest.getReg(), ResultReg);
  addUsersToMoveToVALUWorklist(ResultReg, MRI, Worklist);
}

void SIInstrInfo::lowerScalarAbsDiff(SIInstrWorklist &Worklist,
                                     MachineInstr &Inst) const {
  MachineBasicBlock &MBB = *Inst.getParent();
  MachineRegisterInfo &MRI = MBB.getParent()->getRegInfo();
  MachineBasicBlock::iterator MII = Inst;
  const DebugLoc &DL = Inst.getDebugLoc();

  MachineOperand &Dest = Inst.getOperand(0);
  MachineOperand &Src1 = Inst.getOperand(1);
  MachineOperand &Src2 = Inst.getOperand(2);
  Register SubResultReg = MRI.createVirtualRegister(&AMDGPU::VGPR_32RegClass);
  Register TmpReg = MRI.createVirtualRegister(&AMDGPU::VGPR_32RegClass);
  Register ResultReg = MRI.createVirtualRegister(&AMDGPU::VGPR_32RegClass);

  unsigned SubOp = ST.hasAddNoCarryInsts() ? AMDGPU::V_SUB_U32_e32
                                           : AMDGPU::V_SUB_CO_U32_e32;

  BuildMI(MBB, MII, DL, get(SubOp), SubResultReg)
      .addReg(Src1.getReg())
      .addReg(Src2.getReg());

  BuildMI(MBB, MII, DL, get(SubOp), TmpReg).addImm(0).addReg(SubResultReg);

  BuildMI(MBB, MII, DL, get(AMDGPU::V_MAX_I32_e64), ResultReg)
      .addReg(SubResultReg)
      .addReg(TmpReg);

  MRI.replaceRegWith(Dest.getReg(), ResultReg);
  addUsersToMoveToVALUWorklist(ResultReg, MRI, Worklist);
}

void SIInstrInfo::lowerScalarXnor(SIInstrWorklist &Worklist,
                                  MachineInstr &Inst) const {
  MachineBasicBlock &MBB = *Inst.getParent();
  MachineRegisterInfo &MRI = MBB.getParent()->getRegInfo();
  MachineBasicBlock::iterator MII = Inst;
  const DebugLoc &DL = Inst.getDebugLoc();

  MachineOperand &Dest = Inst.getOperand(0);
  MachineOperand &Src0 = Inst.getOperand(1);
  MachineOperand &Src1 = Inst.getOperand(2);

  if (ST.hasDLInsts()) {
    Register NewDest = MRI.createVirtualRegister(&AMDGPU::VGPR_32RegClass);
    legalizeGenericOperand(MBB, MII, &AMDGPU::VGPR_32RegClass, Src0, MRI, DL);
    legalizeGenericOperand(MBB, MII, &AMDGPU::VGPR_32RegClass, Src1, MRI, DL);

    BuildMI(MBB, MII, DL, get(AMDGPU::V_XNOR_B32_e64), NewDest)
      .add(Src0)
      .add(Src1);

    MRI.replaceRegWith(Dest.getReg(), NewDest);
    addUsersToMoveToVALUWorklist(NewDest, MRI, Worklist);
  } else {
    // Using the identity !(x ^ y) == (!x ^ y) == (x ^ !y), we can
    // invert either source and then perform the XOR. If either source is a
    // scalar register, then we can leave the inversion on the scalar unit to
    // achieve a better distribution of scalar and vector instructions.
    bool Src0IsSGPR = Src0.isReg() &&
                      RI.isSGPRClass(MRI.getRegClass(Src0.getReg()));
    bool Src1IsSGPR = Src1.isReg() &&
                      RI.isSGPRClass(MRI.getRegClass(Src1.getReg()));
    MachineInstr *Xor;
    Register Temp = MRI.createVirtualRegister(&AMDGPU::SReg_32RegClass);
    Register NewDest = MRI.createVirtualRegister(&AMDGPU::SReg_32RegClass);

    // Build a pair of scalar instructions and add them to the work list.
    // The next iteration over the work list will lower these to the vector
    // unit as necessary.
    if (Src0IsSGPR) {
      BuildMI(MBB, MII, DL, get(AMDGPU::S_NOT_B32), Temp).add(Src0);
      Xor = BuildMI(MBB, MII, DL, get(AMDGPU::S_XOR_B32), NewDest)
      .addReg(Temp)
      .add(Src1);
    } else if (Src1IsSGPR) {
      BuildMI(MBB, MII, DL, get(AMDGPU::S_NOT_B32), Temp).add(Src1);
      Xor = BuildMI(MBB, MII, DL, get(AMDGPU::S_XOR_B32), NewDest)
      .add(Src0)
      .addReg(Temp);
    } else {
      Xor = BuildMI(MBB, MII, DL, get(AMDGPU::S_XOR_B32), Temp)
        .add(Src0)
        .add(Src1);
      MachineInstr *Not =
          BuildMI(MBB, MII, DL, get(AMDGPU::S_NOT_B32), NewDest).addReg(Temp);
      Worklist.insert(Not);
    }

    MRI.replaceRegWith(Dest.getReg(), NewDest);

    Worklist.insert(Xor);

    addUsersToMoveToVALUWorklist(NewDest, MRI, Worklist);
  }
}

void SIInstrInfo::splitScalarNotBinop(SIInstrWorklist &Worklist,
                                      MachineInstr &Inst,
                                      unsigned Opcode) const {
  MachineBasicBlock &MBB = *Inst.getParent();
  MachineRegisterInfo &MRI = MBB.getParent()->getRegInfo();
  MachineBasicBlock::iterator MII = Inst;
  const DebugLoc &DL = Inst.getDebugLoc();

  MachineOperand &Dest = Inst.getOperand(0);
  MachineOperand &Src0 = Inst.getOperand(1);
  MachineOperand &Src1 = Inst.getOperand(2);

  Register NewDest = MRI.createVirtualRegister(&AMDGPU::SReg_32RegClass);
  Register Interm = MRI.createVirtualRegister(&AMDGPU::SReg_32RegClass);

  MachineInstr &Op = *BuildMI(MBB, MII, DL, get(Opcode), Interm)
    .add(Src0)
    .add(Src1);

  MachineInstr &Not = *BuildMI(MBB, MII, DL, get(AMDGPU::S_NOT_B32), NewDest)
    .addReg(Interm);

  Worklist.insert(&Op);
  Worklist.insert(&Not);

  MRI.replaceRegWith(Dest.getReg(), NewDest);
  addUsersToMoveToVALUWorklist(NewDest, MRI, Worklist);
}

void SIInstrInfo::splitScalarBinOpN2(SIInstrWorklist &Worklist,
                                     MachineInstr &Inst,
                                     unsigned Opcode) const {
  MachineBasicBlock &MBB = *Inst.getParent();
  MachineRegisterInfo &MRI = MBB.getParent()->getRegInfo();
  MachineBasicBlock::iterator MII = Inst;
  const DebugLoc &DL = Inst.getDebugLoc();

  MachineOperand &Dest = Inst.getOperand(0);
  MachineOperand &Src0 = Inst.getOperand(1);
  MachineOperand &Src1 = Inst.getOperand(2);

  Register NewDest = MRI.createVirtualRegister(&AMDGPU::SReg_32_XM0RegClass);
  Register Interm = MRI.createVirtualRegister(&AMDGPU::SReg_32_XM0RegClass);

  MachineInstr &Not = *BuildMI(MBB, MII, DL, get(AMDGPU::S_NOT_B32), Interm)
    .add(Src1);

  MachineInstr &Op = *BuildMI(MBB, MII, DL, get(Opcode), NewDest)
    .add(Src0)
    .addReg(Interm);

  Worklist.insert(&Not);
  Worklist.insert(&Op);

  MRI.replaceRegWith(Dest.getReg(), NewDest);
  addUsersToMoveToVALUWorklist(NewDest, MRI, Worklist);
}

void SIInstrInfo::splitScalar64BitUnaryOp(SIInstrWorklist &Worklist,
                                          MachineInstr &Inst, unsigned Opcode,
                                          bool Swap) const {
  MachineBasicBlock &MBB = *Inst.getParent();
  MachineRegisterInfo &MRI = MBB.getParent()->getRegInfo();

  MachineOperand &Dest = Inst.getOperand(0);
  MachineOperand &Src0 = Inst.getOperand(1);
  const DebugLoc &DL = Inst.getDebugLoc();

  MachineBasicBlock::iterator MII = Inst;

  const MCInstrDesc &InstDesc = get(Opcode);
  const TargetRegisterClass *Src0RC = Src0.isReg() ?
    MRI.getRegClass(Src0.getReg()) :
    &AMDGPU::SGPR_32RegClass;

  const TargetRegisterClass *Src0SubRC =
      RI.getSubRegisterClass(Src0RC, AMDGPU::sub0);

  MachineOperand SrcReg0Sub0 = buildExtractSubRegOrImm(MII, MRI, Src0, Src0RC,
                                                       AMDGPU::sub0, Src0SubRC);

  const TargetRegisterClass *DestRC = MRI.getRegClass(Dest.getReg());
  const TargetRegisterClass *NewDestRC = RI.getEquivalentVGPRClass(DestRC);
  const TargetRegisterClass *NewDestSubRC =
      RI.getSubRegisterClass(NewDestRC, AMDGPU::sub0);

  Register DestSub0 = MRI.createVirtualRegister(NewDestSubRC);
  MachineInstr &LoHalf = *BuildMI(MBB, MII, DL, InstDesc, DestSub0).add(SrcReg0Sub0);

  MachineOperand SrcReg0Sub1 = buildExtractSubRegOrImm(MII, MRI, Src0, Src0RC,
                                                       AMDGPU::sub1, Src0SubRC);

  Register DestSub1 = MRI.createVirtualRegister(NewDestSubRC);
  MachineInstr &HiHalf = *BuildMI(MBB, MII, DL, InstDesc, DestSub1).add(SrcReg0Sub1);

  if (Swap)
    std::swap(DestSub0, DestSub1);

  Register FullDestReg = MRI.createVirtualRegister(NewDestRC);
  BuildMI(MBB, MII, DL, get(TargetOpcode::REG_SEQUENCE), FullDestReg)
    .addReg(DestSub0)
    .addImm(AMDGPU::sub0)
    .addReg(DestSub1)
    .addImm(AMDGPU::sub1);

  MRI.replaceRegWith(Dest.getReg(), FullDestReg);

  Worklist.insert(&LoHalf);
  Worklist.insert(&HiHalf);

  // We don't need to legalizeOperands here because for a single operand, src0
  // will support any kind of input.

  // Move all users of this moved value.
  addUsersToMoveToVALUWorklist(FullDestReg, MRI, Worklist);
}

// There is not a vector equivalent of s_mul_u64. For this reason, we need to
// split the s_mul_u64 in 32-bit vector multiplications.
void SIInstrInfo::splitScalarSMulU64(SIInstrWorklist &Worklist,
                                     MachineInstr &Inst,
                                     MachineDominatorTree *MDT) const {
  MachineBasicBlock &MBB = *Inst.getParent();
  MachineRegisterInfo &MRI = MBB.getParent()->getRegInfo();

  Register FullDestReg = MRI.createVirtualRegister(&AMDGPU::VReg_64RegClass);
  Register DestSub0 = MRI.createVirtualRegister(&AMDGPU::VGPR_32RegClass);
  Register DestSub1 = MRI.createVirtualRegister(&AMDGPU::VGPR_32RegClass);

  MachineOperand &Dest = Inst.getOperand(0);
  MachineOperand &Src0 = Inst.getOperand(1);
  MachineOperand &Src1 = Inst.getOperand(2);
  const DebugLoc &DL = Inst.getDebugLoc();
  MachineBasicBlock::iterator MII = Inst;

  const TargetRegisterClass *Src0RC = MRI.getRegClass(Src0.getReg());
  const TargetRegisterClass *Src1RC = MRI.getRegClass(Src1.getReg());
  const TargetRegisterClass *Src0SubRC =
      RI.getSubRegisterClass(Src0RC, AMDGPU::sub0);
  if (RI.isSGPRClass(Src0SubRC))
    Src0SubRC = RI.getEquivalentVGPRClass(Src0SubRC);
  const TargetRegisterClass *Src1SubRC =
      RI.getSubRegisterClass(Src1RC, AMDGPU::sub0);
  if (RI.isSGPRClass(Src1SubRC))
    Src1SubRC = RI.getEquivalentVGPRClass(Src1SubRC);

  // First, we extract the low 32-bit and high 32-bit values from each of the
  // operands.
  MachineOperand Op0L =
      buildExtractSubRegOrImm(MII, MRI, Src0, Src0RC, AMDGPU::sub0, Src0SubRC);
  MachineOperand Op1L =
      buildExtractSubRegOrImm(MII, MRI, Src1, Src1RC, AMDGPU::sub0, Src1SubRC);
  MachineOperand Op0H =
      buildExtractSubRegOrImm(MII, MRI, Src0, Src0RC, AMDGPU::sub1, Src0SubRC);
  MachineOperand Op1H =
      buildExtractSubRegOrImm(MII, MRI, Src1, Src1RC, AMDGPU::sub1, Src1SubRC);

  // The multilication is done as follows:
  //
  //                            Op1H  Op1L
  //                          * Op0H  Op0L
  //                       --------------------
  //                       Op1H*Op0L  Op1L*Op0L
  //          + Op1H*Op0H  Op1L*Op0H
  // -----------------------------------------
  // (Op1H*Op0L + Op1L*Op0H + carry)  Op1L*Op0L
  //
  //  We drop Op1H*Op0H because the result of the multiplication is a 64-bit
  //  value and that would overflow.
  //  The low 32-bit value is Op1L*Op0L.
  //  The high 32-bit value is Op1H*Op0L + Op1L*Op0H + carry (from Op1L*Op0L).

  Register Op1L_Op0H_Reg = MRI.createVirtualRegister(&AMDGPU::VGPR_32RegClass);
  MachineInstr *Op1L_Op0H =
      BuildMI(MBB, MII, DL, get(AMDGPU::V_MUL_LO_U32_e64), Op1L_Op0H_Reg)
          .add(Op1L)
          .add(Op0H);

  Register Op1H_Op0L_Reg = MRI.createVirtualRegister(&AMDGPU::VGPR_32RegClass);
  MachineInstr *Op1H_Op0L =
      BuildMI(MBB, MII, DL, get(AMDGPU::V_MUL_LO_U32_e64), Op1H_Op0L_Reg)
          .add(Op1H)
          .add(Op0L);

  Register CarryReg = MRI.createVirtualRegister(&AMDGPU::VGPR_32RegClass);
  MachineInstr *Carry =
      BuildMI(MBB, MII, DL, get(AMDGPU::V_MUL_HI_U32_e64), CarryReg)
          .add(Op1L)
          .add(Op0L);

  MachineInstr *LoHalf =
      BuildMI(MBB, MII, DL, get(AMDGPU::V_MUL_LO_U32_e64), DestSub0)
          .add(Op1L)
          .add(Op0L);

  Register AddReg = MRI.createVirtualRegister(&AMDGPU::VGPR_32RegClass);
  MachineInstr *Add = BuildMI(MBB, MII, DL, get(AMDGPU::V_ADD_U32_e32), AddReg)
                          .addReg(Op1L_Op0H_Reg)
                          .addReg(Op1H_Op0L_Reg);

  MachineInstr *HiHalf =
      BuildMI(MBB, MII, DL, get(AMDGPU::V_ADD_U32_e32), DestSub1)
          .addReg(AddReg)
          .addReg(CarryReg);

  BuildMI(MBB, MII, DL, get(TargetOpcode::REG_SEQUENCE), FullDestReg)
      .addReg(DestSub0)
      .addImm(AMDGPU::sub0)
      .addReg(DestSub1)
      .addImm(AMDGPU::sub1);

  MRI.replaceRegWith(Dest.getReg(), FullDestReg);

  // Try to legalize the operands in case we need to swap the order to keep it
  // valid.
  legalizeOperands(*Op1L_Op0H, MDT);
  legalizeOperands(*Op1H_Op0L, MDT);
  legalizeOperands(*Carry, MDT);
  legalizeOperands(*LoHalf, MDT);
  legalizeOperands(*Add, MDT);
  legalizeOperands(*HiHalf, MDT);

  // Move all users of this moved value.
  addUsersToMoveToVALUWorklist(FullDestReg, MRI, Worklist);
}

// Lower S_MUL_U64_U32_PSEUDO/S_MUL_I64_I32_PSEUDO in two 32-bit vector
// multiplications.
void SIInstrInfo::splitScalarSMulPseudo(SIInstrWorklist &Worklist,
                                        MachineInstr &Inst,
                                        MachineDominatorTree *MDT) const {
  MachineBasicBlock &MBB = *Inst.getParent();
  MachineRegisterInfo &MRI = MBB.getParent()->getRegInfo();

  Register FullDestReg = MRI.createVirtualRegister(&AMDGPU::VReg_64RegClass);
  Register DestSub0 = MRI.createVirtualRegister(&AMDGPU::VGPR_32RegClass);
  Register DestSub1 = MRI.createVirtualRegister(&AMDGPU::VGPR_32RegClass);

  MachineOperand &Dest = Inst.getOperand(0);
  MachineOperand &Src0 = Inst.getOperand(1);
  MachineOperand &Src1 = Inst.getOperand(2);
  const DebugLoc &DL = Inst.getDebugLoc();
  MachineBasicBlock::iterator MII = Inst;

  const TargetRegisterClass *Src0RC = MRI.getRegClass(Src0.getReg());
  const TargetRegisterClass *Src1RC = MRI.getRegClass(Src1.getReg());
  const TargetRegisterClass *Src0SubRC =
      RI.getSubRegisterClass(Src0RC, AMDGPU::sub0);
  if (RI.isSGPRClass(Src0SubRC))
    Src0SubRC = RI.getEquivalentVGPRClass(Src0SubRC);
  const TargetRegisterClass *Src1SubRC =
      RI.getSubRegisterClass(Src1RC, AMDGPU::sub0);
  if (RI.isSGPRClass(Src1SubRC))
    Src1SubRC = RI.getEquivalentVGPRClass(Src1SubRC);

  // First, we extract the low 32-bit and high 32-bit values from each of the
  // operands.
  MachineOperand Op0L =
      buildExtractSubRegOrImm(MII, MRI, Src0, Src0RC, AMDGPU::sub0, Src0SubRC);
  MachineOperand Op1L =
      buildExtractSubRegOrImm(MII, MRI, Src1, Src1RC, AMDGPU::sub0, Src1SubRC);

  unsigned Opc = Inst.getOpcode();
  unsigned NewOpc = Opc == AMDGPU::S_MUL_U64_U32_PSEUDO
                        ? AMDGPU::V_MUL_HI_U32_e64
                        : AMDGPU::V_MUL_HI_I32_e64;
  MachineInstr *HiHalf =
      BuildMI(MBB, MII, DL, get(NewOpc), DestSub1).add(Op1L).add(Op0L);

  MachineInstr *LoHalf =
      BuildMI(MBB, MII, DL, get(AMDGPU::V_MUL_LO_U32_e64), DestSub0)
          .add(Op1L)
          .add(Op0L);

  BuildMI(MBB, MII, DL, get(TargetOpcode::REG_SEQUENCE), FullDestReg)
      .addReg(DestSub0)
      .addImm(AMDGPU::sub0)
      .addReg(DestSub1)
      .addImm(AMDGPU::sub1);

  MRI.replaceRegWith(Dest.getReg(), FullDestReg);

  // Try to legalize the operands in case we need to swap the order to keep it
  // valid.
  legalizeOperands(*HiHalf, MDT);
  legalizeOperands(*LoHalf, MDT);

  // Move all users of this moved value.
  addUsersToMoveToVALUWorklist(FullDestReg, MRI, Worklist);
}

void SIInstrInfo::splitScalar64BitBinaryOp(SIInstrWorklist &Worklist,
                                           MachineInstr &Inst, unsigned Opcode,
                                           MachineDominatorTree *MDT) const {
  MachineBasicBlock &MBB = *Inst.getParent();
  MachineRegisterInfo &MRI = MBB.getParent()->getRegInfo();

  MachineOperand &Dest = Inst.getOperand(0);
  MachineOperand &Src0 = Inst.getOperand(1);
  MachineOperand &Src1 = Inst.getOperand(2);
  const DebugLoc &DL = Inst.getDebugLoc();

  MachineBasicBlock::iterator MII = Inst;

  const MCInstrDesc &InstDesc = get(Opcode);
  const TargetRegisterClass *Src0RC = Src0.isReg() ?
    MRI.getRegClass(Src0.getReg()) :
    &AMDGPU::SGPR_32RegClass;

  const TargetRegisterClass *Src0SubRC =
      RI.getSubRegisterClass(Src0RC, AMDGPU::sub0);
  const TargetRegisterClass *Src1RC = Src1.isReg() ?
    MRI.getRegClass(Src1.getReg()) :
    &AMDGPU::SGPR_32RegClass;

  const TargetRegisterClass *Src1SubRC =
      RI.getSubRegisterClass(Src1RC, AMDGPU::sub0);

  MachineOperand SrcReg0Sub0 = buildExtractSubRegOrImm(MII, MRI, Src0, Src0RC,
                                                       AMDGPU::sub0, Src0SubRC);
  MachineOperand SrcReg1Sub0 = buildExtractSubRegOrImm(MII, MRI, Src1, Src1RC,
                                                       AMDGPU::sub0, Src1SubRC);
  MachineOperand SrcReg0Sub1 = buildExtractSubRegOrImm(MII, MRI, Src0, Src0RC,
                                                       AMDGPU::sub1, Src0SubRC);
  MachineOperand SrcReg1Sub1 = buildExtractSubRegOrImm(MII, MRI, Src1, Src1RC,
                                                       AMDGPU::sub1, Src1SubRC);

  const TargetRegisterClass *DestRC = MRI.getRegClass(Dest.getReg());
  const TargetRegisterClass *NewDestRC = RI.getEquivalentVGPRClass(DestRC);
  const TargetRegisterClass *NewDestSubRC =
      RI.getSubRegisterClass(NewDestRC, AMDGPU::sub0);

  Register DestSub0 = MRI.createVirtualRegister(NewDestSubRC);
  MachineInstr &LoHalf = *BuildMI(MBB, MII, DL, InstDesc, DestSub0)
                              .add(SrcReg0Sub0)
                              .add(SrcReg1Sub0);

  Register DestSub1 = MRI.createVirtualRegister(NewDestSubRC);
  MachineInstr &HiHalf = *BuildMI(MBB, MII, DL, InstDesc, DestSub1)
                              .add(SrcReg0Sub1)
                              .add(SrcReg1Sub1);

  Register FullDestReg = MRI.createVirtualRegister(NewDestRC);
  BuildMI(MBB, MII, DL, get(TargetOpcode::REG_SEQUENCE), FullDestReg)
    .addReg(DestSub0)
    .addImm(AMDGPU::sub0)
    .addReg(DestSub1)
    .addImm(AMDGPU::sub1);

  MRI.replaceRegWith(Dest.getReg(), FullDestReg);

  Worklist.insert(&LoHalf);
  Worklist.insert(&HiHalf);

  // Move all users of this moved value.
  addUsersToMoveToVALUWorklist(FullDestReg, MRI, Worklist);
}

void SIInstrInfo::splitScalar64BitXnor(SIInstrWorklist &Worklist,
                                       MachineInstr &Inst,
                                       MachineDominatorTree *MDT) const {
  MachineBasicBlock &MBB = *Inst.getParent();
  MachineRegisterInfo &MRI = MBB.getParent()->getRegInfo();

  MachineOperand &Dest = Inst.getOperand(0);
  MachineOperand &Src0 = Inst.getOperand(1);
  MachineOperand &Src1 = Inst.getOperand(2);
  const DebugLoc &DL = Inst.getDebugLoc();

  MachineBasicBlock::iterator MII = Inst;

  const TargetRegisterClass *DestRC = MRI.getRegClass(Dest.getReg());

  Register Interm = MRI.createVirtualRegister(&AMDGPU::SReg_64RegClass);

  MachineOperand* Op0;
  MachineOperand* Op1;

  if (Src0.isReg() && RI.isSGPRReg(MRI, Src0.getReg())) {
    Op0 = &Src0;
    Op1 = &Src1;
  } else {
    Op0 = &Src1;
    Op1 = &Src0;
  }

  BuildMI(MBB, MII, DL, get(AMDGPU::S_NOT_B64), Interm)
    .add(*Op0);

  Register NewDest = MRI.createVirtualRegister(DestRC);

  MachineInstr &Xor = *BuildMI(MBB, MII, DL, get(AMDGPU::S_XOR_B64), NewDest)
    .addReg(Interm)
    .add(*Op1);

  MRI.replaceRegWith(Dest.getReg(), NewDest);

  Worklist.insert(&Xor);
}

void SIInstrInfo::splitScalar64BitBCNT(SIInstrWorklist &Worklist,
                                       MachineInstr &Inst) const {
  MachineBasicBlock &MBB = *Inst.getParent();
  MachineRegisterInfo &MRI = MBB.getParent()->getRegInfo();

  MachineBasicBlock::iterator MII = Inst;
  const DebugLoc &DL = Inst.getDebugLoc();

  MachineOperand &Dest = Inst.getOperand(0);
  MachineOperand &Src = Inst.getOperand(1);

  const MCInstrDesc &InstDesc = get(AMDGPU::V_BCNT_U32_B32_e64);
  const TargetRegisterClass *SrcRC = Src.isReg() ?
    MRI.getRegClass(Src.getReg()) :
    &AMDGPU::SGPR_32RegClass;

  Register MidReg = MRI.createVirtualRegister(&AMDGPU::VGPR_32RegClass);
  Register ResultReg = MRI.createVirtualRegister(&AMDGPU::VGPR_32RegClass);

  const TargetRegisterClass *SrcSubRC =
      RI.getSubRegisterClass(SrcRC, AMDGPU::sub0);

  MachineOperand SrcRegSub0 = buildExtractSubRegOrImm(MII, MRI, Src, SrcRC,
                                                      AMDGPU::sub0, SrcSubRC);
  MachineOperand SrcRegSub1 = buildExtractSubRegOrImm(MII, MRI, Src, SrcRC,
                                                      AMDGPU::sub1, SrcSubRC);

  BuildMI(MBB, MII, DL, InstDesc, MidReg).add(SrcRegSub0).addImm(0);

  BuildMI(MBB, MII, DL, InstDesc, ResultReg).add(SrcRegSub1).addReg(MidReg);

  MRI.replaceRegWith(Dest.getReg(), ResultReg);

  // We don't need to legalize operands here. src0 for either instruction can be
  // an SGPR, and the second input is unused or determined here.
  addUsersToMoveToVALUWorklist(ResultReg, MRI, Worklist);
}

void SIInstrInfo::splitScalar64BitBFE(SIInstrWorklist &Worklist,
                                      MachineInstr &Inst) const {
  MachineBasicBlock &MBB = *Inst.getParent();
  MachineRegisterInfo &MRI = MBB.getParent()->getRegInfo();
  MachineBasicBlock::iterator MII = Inst;
  const DebugLoc &DL = Inst.getDebugLoc();

  MachineOperand &Dest = Inst.getOperand(0);
  uint32_t Imm = Inst.getOperand(2).getImm();
  uint32_t Offset = Imm & 0x3f; // Extract bits [5:0].
  uint32_t BitWidth = (Imm & 0x7f0000) >> 16; // Extract bits [22:16].

  (void) Offset;

  // Only sext_inreg cases handled.
  assert(Inst.getOpcode() == AMDGPU::S_BFE_I64 && BitWidth <= 32 &&
         Offset == 0 && "Not implemented");

  if (BitWidth < 32) {
    Register MidRegLo = MRI.createVirtualRegister(&AMDGPU::VGPR_32RegClass);
    Register MidRegHi = MRI.createVirtualRegister(&AMDGPU::VGPR_32RegClass);
    Register ResultReg = MRI.createVirtualRegister(&AMDGPU::VReg_64RegClass);

    BuildMI(MBB, MII, DL, get(AMDGPU::V_BFE_I32_e64), MidRegLo)
        .addReg(Inst.getOperand(1).getReg(), {}, AMDGPU::sub0)
        .addImm(0)
        .addImm(BitWidth);

    BuildMI(MBB, MII, DL, get(AMDGPU::V_ASHRREV_I32_e32), MidRegHi)
      .addImm(31)
      .addReg(MidRegLo);

    BuildMI(MBB, MII, DL, get(TargetOpcode::REG_SEQUENCE), ResultReg)
      .addReg(MidRegLo)
      .addImm(AMDGPU::sub0)
      .addReg(MidRegHi)
      .addImm(AMDGPU::sub1);

    MRI.replaceRegWith(Dest.getReg(), ResultReg);
    addUsersToMoveToVALUWorklist(ResultReg, MRI, Worklist);
    return;
  }

  MachineOperand &Src = Inst.getOperand(1);
  Register TmpReg = MRI.createVirtualRegister(&AMDGPU::VGPR_32RegClass);
  Register ResultReg = MRI.createVirtualRegister(&AMDGPU::VReg_64RegClass);

  BuildMI(MBB, MII, DL, get(AMDGPU::V_ASHRREV_I32_e64), TmpReg)
      .addImm(31)
      .addReg(Src.getReg(), {}, AMDGPU::sub0);

  BuildMI(MBB, MII, DL, get(TargetOpcode::REG_SEQUENCE), ResultReg)
      .addReg(Src.getReg(), {}, AMDGPU::sub0)
      .addImm(AMDGPU::sub0)
      .addReg(TmpReg)
      .addImm(AMDGPU::sub1);

  MRI.replaceRegWith(Dest.getReg(), ResultReg);
  addUsersToMoveToVALUWorklist(ResultReg, MRI, Worklist);
}

void SIInstrInfo::splitScalar64BitCountOp(SIInstrWorklist &Worklist,
                                          MachineInstr &Inst, unsigned Opcode,
                                          MachineDominatorTree *MDT) const {
  //  (S_FLBIT_I32_B64 hi:lo) ->
  // -> (umin (V_FFBH_U32_e32 hi), (uaddsat (V_FFBH_U32_e32 lo), 32))
  //  (S_FF1_I32_B64 hi:lo) ->
  // ->(umin (uaddsat (V_FFBL_B32_e32 hi), 32) (V_FFBL_B32_e32 lo))

  MachineBasicBlock &MBB = *Inst.getParent();
  MachineRegisterInfo &MRI = MBB.getParent()->getRegInfo();
  MachineBasicBlock::iterator MII = Inst;
  const DebugLoc &DL = Inst.getDebugLoc();

  MachineOperand &Dest = Inst.getOperand(0);
  MachineOperand &Src = Inst.getOperand(1);

  const MCInstrDesc &InstDesc = get(Opcode);

  bool IsCtlz = Opcode == AMDGPU::V_FFBH_U32_e32;
  unsigned OpcodeAdd = ST.hasAddNoCarryInsts() ? AMDGPU::V_ADD_U32_e64
                                               : AMDGPU::V_ADD_CO_U32_e32;

  const TargetRegisterClass *SrcRC =
      Src.isReg() ? MRI.getRegClass(Src.getReg()) : &AMDGPU::SGPR_32RegClass;
  const TargetRegisterClass *SrcSubRC =
      RI.getSubRegisterClass(SrcRC, AMDGPU::sub0);

  MachineOperand SrcRegSub0 =
      buildExtractSubRegOrImm(MII, MRI, Src, SrcRC, AMDGPU::sub0, SrcSubRC);
  MachineOperand SrcRegSub1 =
      buildExtractSubRegOrImm(MII, MRI, Src, SrcRC, AMDGPU::sub1, SrcSubRC);

  Register MidReg1 = MRI.createVirtualRegister(&AMDGPU::VGPR_32RegClass);
  Register MidReg2 = MRI.createVirtualRegister(&AMDGPU::VGPR_32RegClass);
  Register MidReg3 = MRI.createVirtualRegister(&AMDGPU::VGPR_32RegClass);
  Register MidReg4 = MRI.createVirtualRegister(&AMDGPU::VGPR_32RegClass);

  BuildMI(MBB, MII, DL, InstDesc, MidReg1).add(SrcRegSub0);

  BuildMI(MBB, MII, DL, InstDesc, MidReg2).add(SrcRegSub1);

  BuildMI(MBB, MII, DL, get(OpcodeAdd), MidReg3)
      .addReg(IsCtlz ? MidReg1 : MidReg2)
      .addImm(32)
      .addImm(1); // enable clamp

  BuildMI(MBB, MII, DL, get(AMDGPU::V_MIN_U32_e64), MidReg4)
      .addReg(MidReg3)
      .addReg(IsCtlz ? MidReg2 : MidReg1);

  MRI.replaceRegWith(Dest.getReg(), MidReg4);

  addUsersToMoveToVALUWorklist(MidReg4, MRI, Worklist);
}

void SIInstrInfo::addUsersToMoveToVALUWorklist(
    Register DstReg, MachineRegisterInfo &MRI,
    SIInstrWorklist &Worklist) const {
  for (MachineOperand &MO : make_early_inc_range(MRI.use_operands(DstReg))) {
    MachineInstr &UseMI = *MO.getParent();

    unsigned OpNo = 0;

    switch (UseMI.getOpcode()) {
    case AMDGPU::COPY:
    case AMDGPU::WQM:
    case AMDGPU::SOFT_WQM:
    case AMDGPU::STRICT_WWM:
    case AMDGPU::STRICT_WQM:
    case AMDGPU::REG_SEQUENCE:
    case AMDGPU::PHI:
    case AMDGPU::INSERT_SUBREG:
      break;
    default:
      OpNo = MO.getOperandNo();
      break;
    }

    const TargetRegisterClass *OpRC = getOpRegClass(UseMI, OpNo);
    MRI.constrainRegClass(DstReg, OpRC);

    if (!RI.hasVectorRegisters(OpRC))
      Worklist.insert(&UseMI);
    else
      // Legalization could change user list.
      legalizeOperandsVALUt16(UseMI, OpNo, MRI);
  }
}

void SIInstrInfo::movePackToVALU(SIInstrWorklist &Worklist,
                                 MachineRegisterInfo &MRI,
                                 MachineInstr &Inst) const {
  Register ResultReg = MRI.createVirtualRegister(&AMDGPU::VGPR_32RegClass);
  MachineBasicBlock *MBB = Inst.getParent();
  MachineOperand &Src0 = Inst.getOperand(1);
  MachineOperand &Src1 = Inst.getOperand(2);
  const DebugLoc &DL = Inst.getDebugLoc();

  if (ST.useRealTrue16Insts()) {
    Register SrcReg0, SrcReg1;
    if (!Src0.isReg() || !RI.isVGPR(MRI, Src0.getReg())) {
      SrcReg0 = MRI.createVirtualRegister(&AMDGPU::VGPR_32RegClass);
      BuildMI(*MBB, Inst, DL,
              get(Src0.isImm() ? AMDGPU::V_MOV_B32_e32 : AMDGPU::COPY), SrcReg0)
          .add(Src0);
    } else {
      SrcReg0 = Src0.getReg();
    }

    if (!Src1.isReg() || !RI.isVGPR(MRI, Src1.getReg())) {
      SrcReg1 = MRI.createVirtualRegister(&AMDGPU::VGPR_32RegClass);
      BuildMI(*MBB, Inst, DL,
              get(Src1.isImm() ? AMDGPU::V_MOV_B32_e32 : AMDGPU::COPY), SrcReg1)
          .add(Src1);
    } else {
      SrcReg1 = Src1.getReg();
    }

    bool isSrc0Reg16 = MRI.constrainRegClass(SrcReg0, &AMDGPU::VGPR_16RegClass);
    bool isSrc1Reg16 = MRI.constrainRegClass(SrcReg1, &AMDGPU::VGPR_16RegClass);

    auto NewMI = BuildMI(*MBB, Inst, DL, get(AMDGPU::REG_SEQUENCE), ResultReg);
    switch (Inst.getOpcode()) {
    case AMDGPU::S_PACK_LL_B32_B16:
      NewMI
          .addReg(SrcReg0, {},
                  isSrc0Reg16 ? AMDGPU::NoSubRegister : AMDGPU::lo16)
          .addImm(AMDGPU::lo16)
          .addReg(SrcReg1, {},
                  isSrc1Reg16 ? AMDGPU::NoSubRegister : AMDGPU::lo16)
          .addImm(AMDGPU::hi16);
      break;
    case AMDGPU::S_PACK_LH_B32_B16:
      NewMI
          .addReg(SrcReg0, {},
                  isSrc0Reg16 ? AMDGPU::NoSubRegister : AMDGPU::lo16)
          .addImm(AMDGPU::lo16)
          .addReg(SrcReg1, {}, AMDGPU::hi16)
          .addImm(AMDGPU::hi16);
      break;
    case AMDGPU::S_PACK_HL_B32_B16:
      NewMI.addReg(SrcReg0, {}, AMDGPU::hi16)
          .addImm(AMDGPU::lo16)
          .addReg(SrcReg1, {},
                  isSrc1Reg16 ? AMDGPU::NoSubRegister : AMDGPU::lo16)
          .addImm(AMDGPU::hi16);
      break;
    case AMDGPU::S_PACK_HH_B32_B16:
      NewMI.addReg(SrcReg0, {}, AMDGPU::hi16)
          .addImm(AMDGPU::lo16)
          .addReg(SrcReg1, {}, AMDGPU::hi16)
          .addImm(AMDGPU::hi16);
      break;
    default:
      llvm_unreachable("unhandled s_pack_* instruction");
    }

    MachineOperand &Dest = Inst.getOperand(0);
    MRI.replaceRegWith(Dest.getReg(), ResultReg);
    addUsersToMoveToVALUWorklist(ResultReg, MRI, Worklist);
    return;
  }

  switch (Inst.getOpcode()) {
  case AMDGPU::S_PACK_LL_B32_B16: {
    Register ImmReg = MRI.createVirtualRegister(&AMDGPU::VGPR_32RegClass);
    Register TmpReg = MRI.createVirtualRegister(&AMDGPU::VGPR_32RegClass);

    // FIXME: Can do a lot better if we know the high bits of src0 or src1 are
    // 0.
    BuildMI(*MBB, Inst, DL, get(AMDGPU::V_MOV_B32_e32), ImmReg)
      .addImm(0xffff);

    BuildMI(*MBB, Inst, DL, get(AMDGPU::V_AND_B32_e64), TmpReg)
      .addReg(ImmReg, RegState::Kill)
      .add(Src0);

    BuildMI(*MBB, Inst, DL, get(AMDGPU::V_LSHL_OR_B32_e64), ResultReg)
      .add(Src1)
      .addImm(16)
      .addReg(TmpReg, RegState::Kill);
    break;
  }
  case AMDGPU::S_PACK_LH_B32_B16: {
    Register ImmReg = MRI.createVirtualRegister(&AMDGPU::VGPR_32RegClass);
    BuildMI(*MBB, Inst, DL, get(AMDGPU::V_MOV_B32_e32), ImmReg)
      .addImm(0xffff);
    BuildMI(*MBB, Inst, DL, get(AMDGPU::V_BFI_B32_e64), ResultReg)
      .addReg(ImmReg, RegState::Kill)
      .add(Src0)
      .add(Src1);
    break;
  }
  case AMDGPU::S_PACK_HL_B32_B16: {
    Register TmpReg = MRI.createVirtualRegister(&AMDGPU::VGPR_32RegClass);
    BuildMI(*MBB, Inst, DL, get(AMDGPU::V_LSHRREV_B32_e64), TmpReg)
        .addImm(16)
        .add(Src0);
    BuildMI(*MBB, Inst, DL, get(AMDGPU::V_LSHL_OR_B32_e64), ResultReg)
        .add(Src1)
        .addImm(16)
        .addReg(TmpReg, RegState::Kill);
    break;
  }
  case AMDGPU::S_PACK_HH_B32_B16: {
    Register ImmReg = MRI.createVirtualRegister(&AMDGPU::VGPR_32RegClass);
    Register TmpReg = MRI.createVirtualRegister(&AMDGPU::VGPR_32RegClass);
    BuildMI(*MBB, Inst, DL, get(AMDGPU::V_LSHRREV_B32_e64), TmpReg)
      .addImm(16)
      .add(Src0);
    BuildMI(*MBB, Inst, DL, get(AMDGPU::V_MOV_B32_e32), ImmReg)
      .addImm(0xffff0000);
    BuildMI(*MBB, Inst, DL, get(AMDGPU::V_AND_OR_B32_e64), ResultReg)
      .add(Src1)
      .addReg(ImmReg, RegState::Kill)
      .addReg(TmpReg, RegState::Kill);
    break;
  }
  default:
    llvm_unreachable("unhandled s_pack_* instruction");
  }

  MachineOperand &Dest = Inst.getOperand(0);
  MRI.replaceRegWith(Dest.getReg(), ResultReg);
  addUsersToMoveToVALUWorklist(ResultReg, MRI, Worklist);
}

void SIInstrInfo::addSCCDefUsersToVALUWorklist(const MachineOperand &Op,
                                               MachineInstr &SCCDefInst,
                                               SIInstrWorklist &Worklist,
                                               Register NewCond) const {

  // Ensure that def inst defines SCC, which is still live.
  assert(Op.isReg() && Op.getReg() == AMDGPU::SCC && Op.isDef() &&
         !Op.isDead() && Op.getParent() == &SCCDefInst);
  SmallVector<MachineInstr *, 4> CopyToDelete;
  // This assumes that all the users of SCC are in the same block
  // as the SCC def.
  for (MachineInstr &MI : // Skip the def inst itself.
       make_range(std::next(MachineBasicBlock::iterator(SCCDefInst)),
                  SCCDefInst.getParent()->end())) {
    // Check if SCC is used first.
    int SCCIdx = MI.findRegisterUseOperandIdx(AMDGPU::SCC, &RI, false);
    if (SCCIdx != -1) {
      if (MI.isCopy()) {
        MachineRegisterInfo &MRI = MI.getMF()->getRegInfo();
        Register DestReg = MI.getOperand(0).getReg();

        MRI.replaceRegWith(DestReg, NewCond);
        CopyToDelete.push_back(&MI);
      } else {

        if (NewCond.isValid())
          MI.getOperand(SCCIdx).setReg(NewCond);

        Worklist.insert(&MI);
      }
    }
    // Exit if we find another SCC def.
    if (MI.findRegisterDefOperandIdx(AMDGPU::SCC, &RI, false, false) != -1)
      break;
  }
  for (auto &Copy : CopyToDelete)
    Copy->eraseFromParent();
}

// Instructions that use SCC may be converted to VALU instructions. When that
// happens, the SCC register is changed to VCC_LO. The instruction that defines
// SCC must be changed to an instruction that defines VCC. This function makes
// sure that the instruction that defines SCC is added to the moveToVALU
// worklist.
void SIInstrInfo::addSCCDefsToVALUWorklist(MachineInstr *SCCUseInst,
                                           SIInstrWorklist &Worklist) const {
  // Look for a preceding instruction that either defines VCC or SCC. If VCC
  // then there is nothing to do because the defining instruction has been
  // converted to a VALU already. If SCC then that instruction needs to be
  // converted to a VALU.
  for (MachineInstr &MI :
       make_range(std::next(MachineBasicBlock::reverse_iterator(SCCUseInst)),
                  SCCUseInst->getParent()->rend())) {
    if (MI.modifiesRegister(AMDGPU::VCC, &RI))
      break;
    if (MI.definesRegister(AMDGPU::SCC, &RI)) {
      Worklist.insert(&MI);
      break;
    }
  }
}

const TargetRegisterClass *SIInstrInfo::getDestEquivalentVGPRClass(
  const MachineInstr &Inst) const {
  const TargetRegisterClass *NewDstRC = getOpRegClass(Inst, 0);

  switch (Inst.getOpcode()) {
  // For target instructions, getOpRegClass just returns the virtual register
  // class associated with the operand, so we need to find an equivalent VGPR
  // register class in order to move the instruction to the VALU.
  case AMDGPU::COPY:
  case AMDGPU::PHI:
  case AMDGPU::REG_SEQUENCE:
  case AMDGPU::INSERT_SUBREG:
  case AMDGPU::WQM:
  case AMDGPU::SOFT_WQM:
  case AMDGPU::STRICT_WWM:
  case AMDGPU::STRICT_WQM: {
    const TargetRegisterClass *SrcRC = getOpRegClass(Inst, 1);
    if (RI.isAGPRClass(SrcRC)) {
      if (RI.isAGPRClass(NewDstRC))
        return nullptr;

      switch (Inst.getOpcode()) {
      case AMDGPU::PHI:
      case AMDGPU::REG_SEQUENCE:
      case AMDGPU::INSERT_SUBREG:
        NewDstRC = RI.getEquivalentAGPRClass(NewDstRC);
        break;
      default:
        NewDstRC = RI.getEquivalentVGPRClass(NewDstRC);
      }

      if (!NewDstRC)
        return nullptr;
    } else {
      if (RI.isVGPRClass(NewDstRC) || NewDstRC == &AMDGPU::VReg_1RegClass)
        return nullptr;

      NewDstRC = RI.getEquivalentVGPRClass(NewDstRC);
      if (!NewDstRC)
        return nullptr;
    }

    return NewDstRC;
  }
  default:
    return NewDstRC;
  }
}

// Find the one SGPR operand we are allowed to use.
Register SIInstrInfo::findUsedSGPR(const MachineInstr &MI,
                                   int OpIndices[3]) const {
  const MCInstrDesc &Desc = MI.getDesc();

  // Find the one SGPR operand we are allowed to use.
  //
  // First we need to consider the instruction's operand requirements before
  // legalizing. Some operands are required to be SGPRs, such as implicit uses
  // of VCC, but we are still bound by the constant bus requirement to only use
  // one.
  //
  // If the operand's class is an SGPR, we can never move it.

  Register SGPRReg = findImplicitSGPRRead(MI);
  if (SGPRReg)
    return SGPRReg;

  Register UsedSGPRs[3] = {Register()};
  const MachineRegisterInfo &MRI = MI.getMF()->getRegInfo();

  for (unsigned i = 0; i < 3; ++i) {
    int Idx = OpIndices[i];
    if (Idx == -1)
      break;

    const MachineOperand &MO = MI.getOperand(Idx);
    if (!MO.isReg())
      continue;

    // Is this operand statically required to be an SGPR based on the operand
    // constraints?
    const TargetRegisterClass *OpRC =
        RI.getRegClass(getOpRegClassID(Desc.operands()[Idx]));
    bool IsRequiredSGPR = RI.isSGPRClass(OpRC);
    if (IsRequiredSGPR)
      return MO.getReg();

    // If this could be a VGPR or an SGPR, Check the dynamic register class.
    Register Reg = MO.getReg();
    const TargetRegisterClass *RegRC = MRI.getRegClass(Reg);
    if (RI.isSGPRClass(RegRC))
      UsedSGPRs[i] = Reg;
  }

  // We don't have a required SGPR operand, so we have a bit more freedom in
  // selecting operands to move.

  // Try to select the most used SGPR. If an SGPR is equal to one of the
  // others, we choose that.
  //
  // e.g.
  // V_FMA_F32 v0, s0, s0, s0 -> No moves
  // V_FMA_F32 v0, s0, s1, s0 -> Move s1

  // TODO: If some of the operands are 64-bit SGPRs and some 32, we should
  // prefer those.

  if (UsedSGPRs[0]) {
    if (UsedSGPRs[0] == UsedSGPRs[1] || UsedSGPRs[0] == UsedSGPRs[2])
      SGPRReg = UsedSGPRs[0];
  }

  if (!SGPRReg && UsedSGPRs[1]) {
    if (UsedSGPRs[1] == UsedSGPRs[2])
      SGPRReg = UsedSGPRs[1];
  }

  return SGPRReg;
}

MachineOperand *SIInstrInfo::getNamedOperand(MachineInstr &MI,
                                             AMDGPU::OpName OperandName) const {
  if (OperandName == AMDGPU::OpName::NUM_OPERAND_NAMES)
    return nullptr;

  int Idx = AMDGPU::getNamedOperandIdx(MI.getOpcode(), OperandName);
  if (Idx == -1)
    return nullptr;

  return &MI.getOperand(Idx);
}

uint64_t SIInstrInfo::getDefaultRsrcDataFormat() const {
  if (ST.getGeneration() >= AMDGPUSubtarget::GFX10) {
    int64_t Format = ST.getGeneration() >= AMDGPUSubtarget::GFX11
                         ? (int64_t)AMDGPU::UfmtGFX11::UFMT_32_FLOAT
                         : (int64_t)AMDGPU::UfmtGFX10::UFMT_32_FLOAT;
    return (Format << 44) |
           (1ULL << 56) | // RESOURCE_LEVEL = 1
           (3ULL << 60); // OOB_SELECT = 3
  }

  uint64_t RsrcDataFormat = AMDGPU::RSRC_DATA_FORMAT;
  if (ST.isAmdHsaOS()) {
    // Set ATC = 1. GFX9 doesn't have this bit.
    if (ST.getGeneration() <= AMDGPUSubtarget::VOLCANIC_ISLANDS)
      RsrcDataFormat |= (1ULL << 56);

    // Set MTYPE = 2 (MTYPE_UC = uncached). GFX9 doesn't have this.
    // BTW, it disables TC L2 and therefore decreases performance.
    if (ST.getGeneration() == AMDGPUSubtarget::VOLCANIC_ISLANDS)
      RsrcDataFormat |= (2ULL << 59);
  }

  return RsrcDataFormat;
}

uint64_t SIInstrInfo::getScratchRsrcWords23() const {
  uint64_t Rsrc23 = getDefaultRsrcDataFormat() |
                    AMDGPU::RSRC_TID_ENABLE |
                    0xffffffff; // Size;

  // GFX9 doesn't have ELEMENT_SIZE.
  if (ST.getGeneration() <= AMDGPUSubtarget::VOLCANIC_ISLANDS) {
    uint64_t EltSizeValue = Log2_32(ST.getMaxPrivateElementSize(true)) - 1;
    Rsrc23 |= EltSizeValue << AMDGPU::RSRC_ELEMENT_SIZE_SHIFT;
  }

  // IndexStride = 64 / 32.
  uint64_t IndexStride = ST.isWave64() ? 3 : 2;
  Rsrc23 |= IndexStride << AMDGPU::RSRC_INDEX_STRIDE_SHIFT;

  // If TID_ENABLE is set, DATA_FORMAT specifies stride bits [14:17].
  // Clear them unless we want a huge stride.
  if (ST.getGeneration() >= AMDGPUSubtarget::VOLCANIC_ISLANDS &&
      ST.getGeneration() <= AMDGPUSubtarget::GFX9)
    Rsrc23 &= ~AMDGPU::RSRC_DATA_FORMAT;

  return Rsrc23;
}

bool SIInstrInfo::isLowLatencyInstruction(const MachineInstr &MI) const {
  unsigned Opc = MI.getOpcode();

  return isSMRD(Opc);
}

bool SIInstrInfo::isHighLatencyDef(int Opc) const {
  return get(Opc).mayLoad() &&
         (isMUBUF(Opc) || isMTBUF(Opc) || isMIMG(Opc) || isFLAT(Opc));
}

Register SIInstrInfo::isStackAccess(const MachineInstr &MI, int &FrameIndex,
                                    TypeSize &MemBytes) const {
  const MachineOperand *Addr = getNamedOperand(MI, AMDGPU::OpName::vaddr);
  if (!Addr || !Addr->isFI())
    return Register();

  assert(!MI.memoperands_empty() &&
         (*MI.memoperands_begin())->getAddrSpace() == AMDGPUAS::PRIVATE_ADDRESS);

  FrameIndex = Addr->getIndex();

  int VDataIdx =
      AMDGPU::getNamedOperandIdx(MI.getOpcode(), AMDGPU::OpName::vdata);
  MemBytes = TypeSize::getFixed(getOpSize(MI.getOpcode(), VDataIdx));
  return MI.getOperand(VDataIdx).getReg();
}

Register SIInstrInfo::isSGPRStackAccess(const MachineInstr &MI, int &FrameIndex,
                                        TypeSize &MemBytes) const {
  const MachineOperand *Addr = getNamedOperand(MI, AMDGPU::OpName::addr);
  assert(Addr && Addr->isFI());
  FrameIndex = Addr->getIndex();

  int DataIdx =
      AMDGPU::getNamedOperandIdx(MI.getOpcode(), AMDGPU::OpName::data);
  MemBytes = TypeSize::getFixed(getOpSize(MI.getOpcode(), DataIdx));
  return MI.getOperand(DataIdx).getReg();
}

Register SIInstrInfo::isLoadFromStackSlot(const MachineInstr &MI,
                                          int &FrameIndex,
                                          TypeSize &MemBytes) const {
  if (!MI.mayLoad())
    return Register();

  if (isMUBUF(MI) || isVGPRSpill(MI))
    return isStackAccess(MI, FrameIndex, MemBytes);

  if (isSGPRSpill(MI))
    return isSGPRStackAccess(MI, FrameIndex, MemBytes);

  return Register();
}

Register SIInstrInfo::isStoreToStackSlot(const MachineInstr &MI,
                                         int &FrameIndex,
                                         TypeSize &MemBytes) const {
  if (!MI.mayStore())
    return Register();

  if (isMUBUF(MI) || isVGPRSpill(MI))
    return isStackAccess(MI, FrameIndex, MemBytes);

  if (isSGPRSpill(MI))
    return isSGPRStackAccess(MI, FrameIndex, MemBytes);

  return Register();
}

unsigned SIInstrInfo::getInstSizeInBytes(const MachineInstr &MI) const {
  unsigned Opc = MI.getOpcode();
  const MCInstrDesc &Desc = getMCOpcodeFromPseudo(Opc);
  unsigned DescSize = Desc.getSize();

  // If we have a definitive size, we can use it. Otherwise we need to inspect
  // the operands to know the size.
  if (isFixedSize(MI)) {
    unsigned Size = DescSize;

    // If we hit the buggy offset, an extra nop will be inserted in MC so
    // estimate the worst case.
    if (MI.isBranch() && ST.hasOffset3fBug())
      Size += 4;

    return Size;
  }

  // Instructions may have a 32-bit literal encoded after them. Check
  // operands that could ever be literals.
  if (isVALU(MI, /*AllowLDSDMA=*/true) || isSALU(MI)) {
    if (isDPP(MI))
      return DescSize;
    bool HasLiteral = false;
    unsigned LiteralSize = 4;
    for (int I = 0, E = MI.getNumExplicitOperands(); I != E; ++I) {
      const MachineOperand &Op = MI.getOperand(I);
      const MCOperandInfo &OpInfo = Desc.operands()[I];
      if (!Op.isReg() && !isInlineConstant(Op, OpInfo)) {
        HasLiteral = true;
        if (ST.has64BitLiterals()) {
          switch (OpInfo.OperandType) {
          default:
            break;
          case AMDGPU::OPERAND_REG_IMM_FP64:
          case AMDGPU::OPERAND_REG_IMM_V2FP64:
            if (!AMDGPU::isValid32BitLiteral(Op.getImm(), true))
              LiteralSize = 8;
            break;
          case AMDGPU::OPERAND_REG_IMM_INT64:
          case AMDGPU::OPERAND_REG_IMM_V2INT64:
            // A 32-bit literal is only valid when the value fits in BOTH signed
            // and unsigned 32-bit ranges [0, 2^31-1], matching the MC code
            // emitter's getLit64Encoding logic. This is because of the lack of
            // abilility to tell signedness of the literal, therefore we need to
            // be conservative and assume values outside this range require a
            // 64-bit literal encoding (8 bytes).
            if (!Op.isImm() || !isInt<32>(Op.getImm()) ||
                !isUInt<32>(Op.getImm()))
              LiteralSize = 8;
            break;
          }
        }
        break;
      }
    }
    return HasLiteral ? DescSize + LiteralSize : DescSize;
  }

  // Check whether we have extra NSA words.
  if (isMIMG(MI)) {
    int VAddr0Idx = AMDGPU::getNamedOperandIdx(Opc, AMDGPU::OpName::vaddr0);
    if (VAddr0Idx < 0)
      return 8;

    int RSrcIdx = AMDGPU::getNamedOperandIdx(Opc, AMDGPU::OpName::srsrc);
    return 8 + 4 * ((RSrcIdx - VAddr0Idx + 2) / 4);
  }

  switch (Opc) {
  case TargetOpcode::BUNDLE:
    return getInstBundleSize(MI);
  case TargetOpcode::INLINEASM:
  case TargetOpcode::INLINEASM_BR: {
    const MachineFunction *MF = MI.getMF();
    const char *AsmStr = MI.getOperand(0).getSymbolName();
    return getInlineAsmLength(AsmStr, MF->getTarget().getMCAsmInfo(), &ST);
  }
  default:
    if (MI.isMetaInstruction())
      return 0;

    // If D16 Pseudo inst, get correct MC code size
    const auto *D16Info = AMDGPU::getT16D16Helper(Opc);
    if (D16Info) {
      // Assume d16_lo/hi inst are always in same size
      unsigned LoInstOpcode = D16Info->LoOp;
      const MCInstrDesc &Desc = getMCOpcodeFromPseudo(LoInstOpcode);
      DescSize = Desc.getSize();
    }

    // If FMA Pseudo inst, get correct MC code size
    if (Opc == AMDGPU::V_FMA_MIX_F16_t16 || Opc == AMDGPU::V_FMA_MIX_BF16_t16) {
      // All potential lowerings are the same size; arbitrarily pick one.
      const MCInstrDesc &Desc = getMCOpcodeFromPseudo(AMDGPU::V_FMA_MIXLO_F16);
      DescSize = Desc.getSize();
    }

    return DescSize;
  }
}

TargetInstrInfo::InstSizeVerifyMode
SIInstrInfo::getInstSizeVerifyMode(const MachineInstr &MI) const {
  if (MI.isBranch() && ST.hasOffset3fBug())
    return InstSizeVerifyMode::NoVerify;
  return InstSizeVerifyMode::ExactSize;
}

bool SIInstrInfo::mayAccessFlatAddressSpace(const MachineInstr &MI) const {
  if (!isFLAT(MI))
    return false;

  if (MI.memoperands_empty())
    return true;

  for (const MachineMemOperand *MMO : MI.memoperands()) {
    if (MMO->getAddrSpace() == AMDGPUAS::FLAT_ADDRESS)
      return true;
  }
  return false;
}

ArrayRef<std::pair<int, const char *>>
SIInstrInfo::getSerializableTargetIndices() const {
  static const std::pair<int, const char *> TargetIndices[] = {
      {AMDGPU::TI_CONSTDATA_START, "amdgpu-constdata-start"},
      {AMDGPU::TI_SCRATCH_RSRC_DWORD0, "amdgpu-scratch-rsrc-dword0"},
      {AMDGPU::TI_SCRATCH_RSRC_DWORD1, "amdgpu-scratch-rsrc-dword1"},
      {AMDGPU::TI_SCRATCH_RSRC_DWORD2, "amdgpu-scratch-rsrc-dword2"},
      {AMDGPU::TI_SCRATCH_RSRC_DWORD3, "amdgpu-scratch-rsrc-dword3"}};
  return ArrayRef(TargetIndices);
}

/// This is used by the post-RA scheduler (SchedulePostRAList.cpp).  The
/// post-RA version of misched uses CreateTargetMIHazardRecognizer.
ScheduleHazardRecognizer *
SIInstrInfo::CreateTargetPostRAHazardRecognizer(const InstrItineraryData *II,
                                            const ScheduleDAG *DAG) const {
  return new GCNHazardRecognizer(DAG->MF);
}

/// This is the hazard recognizer used at -O0 by the PostRAHazardRecognizer
/// pass.
ScheduleHazardRecognizer *
SIInstrInfo::CreateTargetPostRAHazardRecognizer(const MachineFunction &MF,
                                                MachineLoopInfo *MLI) const {
  return new GCNHazardRecognizer(MF, MLI);
}

// Called during:
// - pre-RA scheduling and post-RA scheduling
ScheduleHazardRecognizer *
SIInstrInfo::CreateTargetMIHazardRecognizer(const InstrItineraryData *II,
                                            const ScheduleDAGMI *DAG) const {
  // Borrowed from Arm Target
  // We would like to restrict this hazard recognizer to only
  // post-RA scheduling; we can tell that we're post-RA because we don't
  // track VRegLiveness.
  if (!DAG->hasVRegLiveness())
    return new GCNHazardRecognizer(DAG->MF);
  return TargetInstrInfo::CreateTargetMIHazardRecognizer(II, DAG);
}

std::pair<unsigned, unsigned>
SIInstrInfo::decomposeMachineOperandsTargetFlags(unsigned TF) const {
  return std::pair(TF & MO_MASK, TF & ~MO_MASK);
}

ArrayRef<std::pair<unsigned, const char *>>
SIInstrInfo::getSerializableDirectMachineOperandTargetFlags() const {
  static const std::pair<unsigned, const char *> TargetFlags[] = {
      {MO_GOTPCREL, "amdgpu-gotprel"},
      {MO_GOTPCREL32_LO, "amdgpu-gotprel32-lo"},
      {MO_GOTPCREL32_HI, "amdgpu-gotprel32-hi"},
      {MO_GOTPCREL64, "amdgpu-gotprel64"},
      {MO_REL32_LO, "amdgpu-rel32-lo"},
      {MO_REL32_HI, "amdgpu-rel32-hi"},
      {MO_REL64, "amdgpu-rel64"},
      {MO_ABS32_LO, "amdgpu-abs32-lo"},
      {MO_ABS32_HI, "amdgpu-abs32-hi"},
      {MO_ABS64, "amdgpu-abs64"},
  };

  return ArrayRef(TargetFlags);
}

ArrayRef<std::pair<MachineMemOperand::Flags, const char *>>
SIInstrInfo::getSerializableMachineMemOperandTargetFlags() const {
  static const std::pair<MachineMemOperand::Flags, const char *> TargetFlags[] =
      {
          {MONoClobber, "amdgpu-noclobber"},
          {MOLastUse, "amdgpu-last-use"},
          {MOCooperative, "amdgpu-cooperative"},
          {MOThreadPrivate, "amdgpu-thread-private"},
      };

  return ArrayRef(TargetFlags);
}

unsigned SIInstrInfo::getLiveRangeSplitOpcode(Register SrcReg,
                                              const MachineFunction &MF) const {
  const SIMachineFunctionInfo *MFI = MF.getInfo<SIMachineFunctionInfo>();
  assert(SrcReg.isVirtual());
  if (MFI->checkFlag(SrcReg, AMDGPU::VirtRegFlag::WWM_REG))
    return AMDGPU::WWM_COPY;

  return AMDGPU::COPY;
}

bool SIInstrInfo::canAddToBBProlog(const MachineInstr &MI) const {
  uint32_t Opcode = MI.getOpcode();
  // Check if it is SGPR spill or wwm-register spill Opcode.
  if (isSGPRSpill(Opcode) || isWWMRegSpillOpcode(Opcode))
    return true;

  const MachineFunction *MF = MI.getMF();
  const MachineRegisterInfo &MRI = MF->getRegInfo();
  const SIMachineFunctionInfo *MFI = MF->getInfo<SIMachineFunctionInfo>();

  // See if this is Liverange split instruction inserted for SGPR or
  // wwm-register. The implicit def inserted for wwm-registers should also be
  // included as they can appear at the bb begin.
  bool IsLRSplitInst = MI.getFlag(MachineInstr::LRSplit);
  if (!IsLRSplitInst && Opcode != AMDGPU::IMPLICIT_DEF)
    return false;

  Register Reg = MI.getOperand(0).getReg();
  if (RI.isSGPRClass(RI.getRegClassForReg(MRI, Reg)))
    return IsLRSplitInst;

  return MFI->isWWMReg(Reg);
}

bool SIInstrInfo::isBasicBlockPrologue(const MachineInstr &MI,
                                       Register Reg) const {
  // We need to handle instructions which may be inserted during register
  // allocation to handle the prolog. The initial prolog instruction may have
  // been separated from the start of the block by spills and copies inserted
  // needed by the prolog. However, the insertions for scalar registers can
  // always be placed at the BB top as they are independent of the exec mask
  // value.
  bool IsNullOrVectorRegister = true;
  if (Reg) {
    const MachineFunction *MF = MI.getMF();
    const MachineRegisterInfo &MRI = MF->getRegInfo();
    IsNullOrVectorRegister = !RI.isSGPRClass(RI.getRegClassForReg(MRI, Reg));
  }

  return IsNullOrVectorRegister &&
         (canAddToBBProlog(MI) ||
          (!MI.isTerminator() && MI.getOpcode() != AMDGPU::COPY &&
           MI.modifiesRegister(AMDGPU::EXEC, &RI)));
}

MachineInstrBuilder
SIInstrInfo::getAddNoCarry(MachineBasicBlock &MBB,
                           MachineBasicBlock::iterator I,
                           const DebugLoc &DL,
                           Register DestReg) const {
  if (ST.hasAddNoCarryInsts())
    return BuildMI(MBB, I, DL, get(AMDGPU::V_ADD_U32_e64), DestReg);

  MachineRegisterInfo &MRI = MBB.getParent()->getRegInfo();
  Register UnusedCarry = MRI.createVirtualRegister(RI.getBoolRC());
  MRI.setRegAllocationHint(UnusedCarry, 0, RI.getVCC());

  return BuildMI(MBB, I, DL, get(AMDGPU::V_ADD_CO_U32_e64), DestReg)
           .addReg(UnusedCarry, RegState::Define | RegState::Dead);
}

MachineInstrBuilder SIInstrInfo::getAddNoCarry(MachineBasicBlock &MBB,
                                               MachineBasicBlock::iterator I,
                                               const DebugLoc &DL,
                                               Register DestReg,
                                               RegScavenger &RS) const {
  if (ST.hasAddNoCarryInsts())
    return BuildMI(MBB, I, DL, get(AMDGPU::V_ADD_U32_e32), DestReg);

  // If available, prefer to use vcc.
  Register UnusedCarry = !RS.isRegUsed(AMDGPU::VCC)
                             ? Register(RI.getVCC())
                             : RS.scavengeRegisterBackwards(
                                   *RI.getBoolRC(), I, /* RestoreAfter */ false,
                                   0, /* AllowSpill */ false);

  // TODO: Users need to deal with this.
  if (!UnusedCarry.isValid())
    return MachineInstrBuilder();

  return BuildMI(MBB, I, DL, get(AMDGPU::V_ADD_CO_U32_e64), DestReg)
           .addReg(UnusedCarry, RegState::Define | RegState::Dead);
}

bool SIInstrInfo::isKillTerminator(unsigned Opcode) {
  switch (Opcode) {
  case AMDGPU::SI_KILL_F32_COND_IMM_TERMINATOR:
  case AMDGPU::SI_KILL_I1_TERMINATOR:
    return true;
  default:
    return false;
  }
}

const MCInstrDesc &SIInstrInfo::getKillTerminatorFromPseudo(unsigned Opcode) const {
  switch (Opcode) {
  case AMDGPU::SI_KILL_F32_COND_IMM_PSEUDO:
    return get(AMDGPU::SI_KILL_F32_COND_IMM_TERMINATOR);
  case AMDGPU::SI_KILL_I1_PSEUDO:
    return get(AMDGPU::SI_KILL_I1_TERMINATOR);
  default:
    llvm_unreachable("invalid opcode, expected SI_KILL_*_PSEUDO");
  }
}

bool SIInstrInfo::isLegalMUBUFImmOffset(unsigned Imm) const {
  return Imm <= getMaxMUBUFImmOffset(ST);
}

unsigned SIInstrInfo::getMaxMUBUFImmOffset(const GCNSubtarget &ST) {
  // GFX12 field is non-negative 24-bit signed byte offset.
  const unsigned OffsetBits =
      ST.getGeneration() >= AMDGPUSubtarget::GFX12 ? 23 : 12;
  return (1 << OffsetBits) - 1;
}

void SIInstrInfo::fixImplicitOperands(MachineInstr &MI) const {
  if (!ST.isWave32())
    return;

  if (MI.isInlineAsm())
    return;

  if (MI.getNumOperands() < MI.getNumExplicitOperands())
    return;

  for (auto &Op : MI.implicit_operands()) {
    if (Op.isReg() && Op.getReg() == AMDGPU::VCC)
      Op.setReg(AMDGPU::VCC_LO);
  }
}

bool SIInstrInfo::isBufferSMRD(const MachineInstr &MI) const {
  if (!isSMRD(MI))
    return false;

  // Check that it is using a buffer resource.
  int Idx = AMDGPU::getNamedOperandIdx(MI.getOpcode(), AMDGPU::OpName::sbase);
  if (Idx == -1) // e.g. s_memtime
    return false;

  const int16_t RCID = getOpRegClassID(MI.getDesc().operands()[Idx]);
  return RI.getRegClass(RCID)->hasSubClassEq(&AMDGPU::SGPR_128RegClass);
}

// Given Imm, split it into the values to put into the SOffset and ImmOffset
// fields in an MUBUF instruction. Return false if it is not possible (due to a
// hardware bug needing a workaround).
//
// The required alignment ensures that individual address components remain
// aligned if they are aligned to begin with. It also ensures that additional
// offsets within the given alignment can be added to the resulting ImmOffset.
bool SIInstrInfo::splitMUBUFOffset(uint32_t Imm, uint32_t &SOffset,
                                   uint32_t &ImmOffset, Align Alignment) const {
  const uint64_t MaxOffset = SIInstrInfo::getMaxMUBUFImmOffset(ST);
  const uint32_t MaxImm = alignDown(MaxOffset, Alignment.value());
  uint32_t Overflow = 0;

  if (Imm > MaxImm) {
    if (Imm <= MaxImm + 64) {
      // Use an SOffset inline constant for 4..64
      Overflow = Imm - MaxImm;
      Imm = MaxImm;
    } else {
      // Try to keep the same value in SOffset for adjacent loads, so that
      // the corresponding register contents can be re-used.
      //
      // Load values with all low-bits (except for alignment bits) set into
      // SOffset, so that a larger range of values can be covered using
      // s_movk_i32.
      //
      // Atomic operations fail to work correctly when individual address
      // components are unaligned, even if their sum is aligned.
      uint32_t High = (Imm + Alignment.value()) & ~MaxOffset;
      uint32_t Low = (Imm + Alignment.value()) & MaxOffset;
      Imm = Low;
      Overflow = High - Alignment.value();
    }
  }

  if (Overflow > 0) {
    // There is a hardware bug in SI and CI which prevents address clamping in
    // MUBUF instructions from working correctly with SOffsets. The immediate
    // offset is unaffected.
    if (ST.getGeneration() <= AMDGPUSubtarget::SEA_ISLANDS)
      return false;

    // It is not possible to set immediate in SOffset field on some targets.
    if (ST.hasRestrictedSOffset())
      return false;
  }

  ImmOffset = Imm;
  SOffset = Overflow;
  return true;
}

// Depending on the used address space and instructions, some immediate offsets
// are allowed and some are not.
// Pre-GFX12, flat instruction offsets can only be non-negative, global and
// scratch instruction offsets can also be negative. On GFX12, offsets can be
// negative for all variants.
//
// There are several bugs related to these offsets:
// On gfx10.1, flat instructions that go into the global address space cannot
// use an offset.
//
// For scratch instructions, the address can be either an SGPR or a VGPR.
// The following offsets can be used, depending on the architecture (x means
// cannot be used):
// +----------------------------+------+------+
// | Address-Mode               | SGPR | VGPR |
// +----------------------------+------+------+
// | gfx9                       |      |      |
// | negative, 4-aligned offset | x    | ok   |
// | negative, unaligned offset | x    | ok   |
// +----------------------------+------+------+
// | gfx10                      |      |      |
// | negative, 4-aligned offset | ok   | ok   |
// | negative, unaligned offset | ok   | x    |
// +----------------------------+------+------+
// | gfx10.3                    |      |      |
// | negative, 4-aligned offset | ok   | ok   |
// | negative, unaligned offset | ok   | ok   |
// +----------------------------+------+------+
//
// This function ignores the addressing mode, so if an offset cannot be used in
// one addressing mode, it is considered illegal.
bool SIInstrInfo::isLegalFLATOffset(int64_t Offset, unsigned AddrSpace,
                                    AMDGPU::FlatAddrSpace FlatVariant) const {
  // TODO: Should 0 be special cased?
  if (!ST.hasFlatInstOffsets())
    return false;

  using AMDGPU::FlatAddrSpace;
  if (ST.hasFlatSegmentOffsetBug() && FlatVariant == FlatAddrSpace::FLAT &&
      (AddrSpace == AMDGPUAS::FLAT_ADDRESS ||
       AddrSpace == AMDGPUAS::GLOBAL_ADDRESS))
    return false;

  if (ST.hasNegativeUnalignedScratchOffsetBug() &&
      FlatVariant == FlatAddrSpace::FlatScratch && Offset < 0 &&
      (Offset % 4) != 0) {
    return false;
  }

  bool AllowNegative = allowNegativeFlatOffset(FlatVariant);
  unsigned N = AMDGPU::getNumFlatOffsetBits(ST);
  return isIntN(N, Offset) && (AllowNegative || Offset >= 0);
}

// See comment on SIInstrInfo::isLegalFLATOffset for what is legal and what not.
std::pair<int64_t, int64_t>
SIInstrInfo::splitFlatOffset(int64_t COffsetVal, unsigned AddrSpace,
                             AMDGPU::FlatAddrSpace FlatVariant) const {
  int64_t RemainderOffset = COffsetVal;
  int64_t ImmField = 0;

  bool AllowNegative = allowNegativeFlatOffset(FlatVariant);
  const unsigned NumBits = AMDGPU::getNumFlatOffsetBits(ST) - 1;

  if (AllowNegative) {
    // Use signed division by a power of two to truncate towards 0.
    int64_t D = 1LL << NumBits;
    RemainderOffset = (COffsetVal / D) * D;
    ImmField = COffsetVal - RemainderOffset;

    if (ST.hasNegativeUnalignedScratchOffsetBug() &&
        FlatVariant == AMDGPU::FlatAddrSpace::FlatScratch && ImmField < 0 &&
        (ImmField % 4) != 0) {
      // Make ImmField a multiple of 4
      RemainderOffset += ImmField % 4;
      ImmField -= ImmField % 4;
    }
  } else if (COffsetVal >= 0) {
    ImmField = COffsetVal & maskTrailingOnes<uint64_t>(NumBits);
    RemainderOffset = COffsetVal - ImmField;
  }

  assert(isLegalFLATOffset(ImmField, AddrSpace, FlatVariant));
  assert(RemainderOffset + ImmField == COffsetVal);
  return {ImmField, RemainderOffset};
}

bool SIInstrInfo::allowNegativeFlatOffset(
    AMDGPU::FlatAddrSpace FlatVariant) const {
  if (ST.hasNegativeScratchOffsetBug() &&
      FlatVariant == AMDGPU::FlatAddrSpace::FlatScratch)
    return false;

  return FlatVariant != AMDGPU::FlatAddrSpace::FLAT || AMDGPU::isGFX12Plus(ST);
}

static unsigned subtargetEncodingFamily(const GCNSubtarget &ST) {
  switch (ST.getGeneration()) {
  default:
    break;
  case AMDGPUSubtarget::SOUTHERN_ISLANDS:
  case AMDGPUSubtarget::SEA_ISLANDS:
    return SIEncodingFamily::SI;
  case AMDGPUSubtarget::VOLCANIC_ISLANDS:
  case AMDGPUSubtarget::GFX9:
    return SIEncodingFamily::VI;
  case AMDGPUSubtarget::GFX10:
    return SIEncodingFamily::GFX10;
  case AMDGPUSubtarget::GFX11:
    return ST.hasGFX11_7Insts() ? SIEncodingFamily::GFX1170
                                : SIEncodingFamily::GFX11;
  case AMDGPUSubtarget::GFX12:
    return ST.hasGFX1250Insts() ? SIEncodingFamily::GFX1250
                                : SIEncodingFamily::GFX12;
  case AMDGPUSubtarget::GFX13:
    return SIEncodingFamily::GFX13;
  }
  llvm_unreachable("Unknown subtarget generation!");
}

bool SIInstrInfo::isAsmOnlyOpcode(int MCOp) const {
  switch(MCOp) {
  // These opcodes use indirect register addressing so
  // they need special handling by codegen (currently missing).
  // Therefore it is too risky to allow these opcodes
  // to be selected by dpp combiner or sdwa peepholer.
  case AMDGPU::V_MOVRELS_B32_dpp_gfx10:
  case AMDGPU::V_MOVRELS_B32_sdwa_gfx10:
  case AMDGPU::V_MOVRELD_B32_dpp_gfx10:
  case AMDGPU::V_MOVRELD_B32_sdwa_gfx10:
  case AMDGPU::V_MOVRELSD_B32_dpp_gfx10:
  case AMDGPU::V_MOVRELSD_B32_sdwa_gfx10:
  case AMDGPU::V_MOVRELSD_2_B32_dpp_gfx10:
  case AMDGPU::V_MOVRELSD_2_B32_sdwa_gfx10:
    return true;
  default:
    return false;
  }
}

#define GENERATE_RENAMED_GFX9_CASES(OPCODE)                                    \
  case OPCODE##_dpp:                                                           \
  case OPCODE##_e32:                                                           \
  case OPCODE##_e64:                                                           \
  case OPCODE##_e64_dpp:                                                       \
  case OPCODE##_sdwa:

static bool isRenamedInGFX9(int Opcode) {
  switch (Opcode) {
    GENERATE_RENAMED_GFX9_CASES(AMDGPU::V_ADDC_U32)
    GENERATE_RENAMED_GFX9_CASES(AMDGPU::V_ADD_CO_U32)
    GENERATE_RENAMED_GFX9_CASES(AMDGPU::V_ADD_U32)
    GENERATE_RENAMED_GFX9_CASES(AMDGPU::V_SUBBREV_U32)
    GENERATE_RENAMED_GFX9_CASES(AMDGPU::V_SUBB_U32)
    GENERATE_RENAMED_GFX9_CASES(AMDGPU::V_SUBREV_CO_U32)
    GENERATE_RENAMED_GFX9_CASES(AMDGPU::V_SUBREV_U32)
    GENERATE_RENAMED_GFX9_CASES(AMDGPU::V_SUB_CO_U32)
    GENERATE_RENAMED_GFX9_CASES(AMDGPU::V_SUB_U32)
  //
  case AMDGPU::V_DIV_FIXUP_F16_gfx9_e64:
  case AMDGPU::V_DIV_FIXUP_F16_gfx9_fake16_e64:
  case AMDGPU::V_FMA_F16_gfx9_e64:
  case AMDGPU::V_FMA_F16_gfx9_fake16_e64:
  case AMDGPU::V_INTERP_P2_F16:
  case AMDGPU::V_MAD_F16_e64:
  case AMDGPU::V_MAD_U16_e64:
  case AMDGPU::V_MAD_I16_e64:
    return true;
  default:
    return false;
  }
}

int SIInstrInfo::pseudoToMCOpcode(int Opcode) const {
  assert(Opcode == (int)SIInstrInfo::getNonSoftWaitcntOpcode(Opcode) &&
         "SIInsertWaitcnts should have promoted soft waitcnt instructions!");

  unsigned Gen = subtargetEncodingFamily(ST);

  if (ST.getGeneration() == AMDGPUSubtarget::GFX9 && isRenamedInGFX9(Opcode))
    Gen = SIEncodingFamily::GFX9;

  // Adjust the encoding family to GFX80 for D16 buffer instructions when the
  // subtarget has UnpackedD16VMem feature.
  // TODO: remove this when we discard GFX80 encoding.
  if (ST.hasUnpackedD16VMem() && SIInstrFlags::isD16Buf(get(Opcode)))
    Gen = SIEncodingFamily::GFX80;

  if (SIInstrFlags::isSDWA(get(Opcode))) {
    switch (ST.getGeneration()) {
    default:
      Gen = SIEncodingFamily::SDWA;
      break;
    case AMDGPUSubtarget::GFX9:
      Gen = SIEncodingFamily::SDWA9;
      break;
    case AMDGPUSubtarget::GFX10:
      Gen = SIEncodingFamily::SDWA10;
      break;
    }
  }

  if (isMAI(Opcode)) {
    int MFMAOp = AMDGPU::getMFMAEarlyClobberOp(Opcode);
    if (MFMAOp != -1)
      Opcode = MFMAOp;
  }

  int32_t MCOp = AMDGPU::getMCOpcode(Opcode, Gen);

  if (MCOp == AMDGPU::INSTRUCTION_LIST_END && ST.hasGFX11_7Insts())
    MCOp = AMDGPU::getMCOpcode(Opcode, SIEncodingFamily::GFX11);

  if (MCOp == AMDGPU::INSTRUCTION_LIST_END && ST.hasGFX1250Insts())
    MCOp = AMDGPU::getMCOpcode(Opcode, SIEncodingFamily::GFX12);

  // -1 means that Opcode is already a native instruction.
  if (MCOp == -1)
    return Opcode;

  if (ST.hasGFX90AInsts()) {
    uint32_t NMCOp = AMDGPU::INSTRUCTION_LIST_END;
    if (ST.hasGFX940Insts())
      NMCOp = AMDGPU::getMCOpcode(Opcode, SIEncodingFamily::GFX940);
    if (NMCOp == AMDGPU::INSTRUCTION_LIST_END)
      NMCOp = AMDGPU::getMCOpcode(Opcode, SIEncodingFamily::GFX90A);
    if (NMCOp == AMDGPU::INSTRUCTION_LIST_END)
      NMCOp = AMDGPU::getMCOpcode(Opcode, SIEncodingFamily::GFX9);
    if (NMCOp != AMDGPU::INSTRUCTION_LIST_END)
      MCOp = NMCOp;
  }

  // INSTRUCTION_LIST_END means that Opcode is a pseudo instruction that has no
  // encoding in the given subtarget generation.
  if (MCOp == AMDGPU::INSTRUCTION_LIST_END)
    return -1;

  if (isAsmOnlyOpcode(MCOp))
    return -1;

  return MCOp;
}

static
TargetInstrInfo::RegSubRegPair getRegOrUndef(const MachineOperand &RegOpnd) {
  assert(RegOpnd.isReg());
  return RegOpnd.isUndef() ? TargetInstrInfo::RegSubRegPair() :
                             getRegSubRegPair(RegOpnd);
}

TargetInstrInfo::RegSubRegPair
llvm::getRegSequenceSubReg(MachineInstr &MI, unsigned SubReg) {
  assert(MI.isRegSequence());
  for (unsigned I = 0, E = (MI.getNumOperands() - 1)/ 2; I < E; ++I)
    if (MI.getOperand(1 + 2 * I + 1).getImm() == SubReg) {
      auto &RegOp = MI.getOperand(1 + 2 * I);
      return getRegOrUndef(RegOp);
    }
  return TargetInstrInfo::RegSubRegPair();
}

// Try to find the definition of reg:subreg in subreg-manipulation pseudos
// Following a subreg of reg:subreg isn't supported
static bool followSubRegDef(MachineInstr &MI,
                            TargetInstrInfo::RegSubRegPair &RSR) {
  if (!RSR.SubReg)
    return false;
  switch (MI.getOpcode()) {
  default: break;
  case AMDGPU::REG_SEQUENCE:
    RSR = getRegSequenceSubReg(MI, RSR.SubReg);
    return true;
  // EXTRACT_SUBREG ins't supported as this would follow a subreg of subreg
  case AMDGPU::INSERT_SUBREG:
    if (RSR.SubReg == (unsigned)MI.getOperand(3).getImm())
      // inserted the subreg we're looking for
      RSR = getRegOrUndef(MI.getOperand(2));
    else { // the subreg in the rest of the reg
      auto R1 = getRegOrUndef(MI.getOperand(1));
      if (R1.SubReg) // subreg of subreg isn't supported
        return false;
      RSR.Reg = R1.Reg;
    }
    return true;
  }
  return false;
}

MachineInstr *llvm::getVRegSubRegDef(const TargetInstrInfo::RegSubRegPair &P,
                                     const MachineRegisterInfo &MRI) {
  assert(MRI.isSSA());
  if (!P.Reg.isVirtual())
    return nullptr;

  auto RSR = P;
  auto *DefInst = MRI.getVRegDef(RSR.Reg);
  while (auto *MI = DefInst) {
    DefInst = nullptr;
    switch (MI->getOpcode()) {
    case AMDGPU::COPY:
    case AMDGPU::V_MOV_B32_e32: {
      auto &Op1 = MI->getOperand(1);
      if (Op1.isReg() && Op1.getReg().isVirtual()) {
        if (Op1.isUndef())
          return nullptr;
        RSR = getRegSubRegPair(Op1);
        DefInst = MRI.getVRegDef(RSR.Reg);
      }
      break;
    }
    default:
      if (followSubRegDef(*MI, RSR)) {
        if (!RSR.Reg)
          return nullptr;
        DefInst = MRI.getVRegDef(RSR.Reg);
      }
    }
    if (!DefInst)
      return MI;
  }
  return nullptr;
}

bool llvm::execMayBeModifiedBeforeUse(const MachineRegisterInfo &MRI,
                                      Register VReg,
                                      const MachineInstr &DefMI,
                                      const MachineInstr &UseMI) {
  assert(MRI.isSSA() && "Must be run on SSA");

  auto *TRI = MRI.getTargetRegisterInfo();
  auto *DefBB = DefMI.getParent();

  // Don't bother searching between blocks, although it is possible this block
  // doesn't modify exec.
  if (UseMI.getParent() != DefBB)
    return true;

  const int MaxInstScan = 20;
  int NumInst = 0;

  // Stop scan at the use.
  auto E = UseMI.getIterator();
  for (auto I = std::next(DefMI.getIterator()); I != E; ++I) {
    if (I->isDebugInstr())
      continue;

    if (++NumInst > MaxInstScan)
      return true;

    if (I->modifiesRegister(AMDGPU::EXEC, TRI))
      return true;
  }

  return false;
}

bool llvm::execMayBeModifiedBeforeAnyUse(const MachineRegisterInfo &MRI,
                                         Register VReg,
                                         const MachineInstr &DefMI) {
  assert(MRI.isSSA() && "Must be run on SSA");

  auto *TRI = MRI.getTargetRegisterInfo();
  auto *DefBB = DefMI.getParent();

  const int MaxUseScan = 10;
  int NumUse = 0;

  for (auto &Use : MRI.use_nodbg_operands(VReg)) {
    auto &UseInst = *Use.getParent();
    // Don't bother searching between blocks, although it is possible this block
    // doesn't modify exec.
    if (UseInst.getParent() != DefBB || UseInst.isPHI())
      return true;

    if (++NumUse > MaxUseScan)
      return true;
  }

  if (NumUse == 0)
    return false;

  const int MaxInstScan = 20;
  int NumInst = 0;

  // Stop scan when we have seen all the uses.
  for (auto I = std::next(DefMI.getIterator()); ; ++I) {
    assert(I != DefBB->end());

    if (I->isDebugInstr())
      continue;

    if (++NumInst > MaxInstScan)
      return true;

    for (const MachineOperand &Op : I->operands()) {
      // We don't check reg masks here as they're used only on calls:
      // 1. EXEC is only considered const within one BB
      // 2. Call should be a terminator instruction if present in a BB

      if (!Op.isReg())
        continue;

      Register Reg = Op.getReg();
      if (Op.isUse()) {
        if (Reg == VReg && --NumUse == 0)
          return false;
      } else if (TRI->regsOverlap(Reg, AMDGPU::EXEC))
        return true;
    }
  }
}

MachineInstr *SIInstrInfo::createPHIDestinationCopy(
    MachineBasicBlock &MBB, MachineBasicBlock::iterator LastPHIIt,
    const DebugLoc &DL, Register Src, Register Dst) const {
  auto Cur = MBB.begin();
  if (Cur != MBB.end())
    do {
      if (!Cur->isPHI() && Cur->readsRegister(Dst, /*TRI=*/nullptr))
        return BuildMI(MBB, Cur, DL, get(TargetOpcode::COPY), Dst).addReg(Src);
      ++Cur;
    } while (Cur != MBB.end() && Cur != LastPHIIt);

  return TargetInstrInfo::createPHIDestinationCopy(MBB, LastPHIIt, DL, Src,
                                                   Dst);
}

MachineInstr *SIInstrInfo::createPHISourceCopy(
    MachineBasicBlock &MBB, MachineBasicBlock::iterator InsPt,
    const DebugLoc &DL, Register Src, unsigned SrcSubReg, Register Dst) const {
  if (InsPt != MBB.end() &&
      (InsPt->getOpcode() == AMDGPU::SI_IF ||
       InsPt->getOpcode() == AMDGPU::SI_ELSE ||
       InsPt->getOpcode() == AMDGPU::SI_IF_BREAK) &&
      InsPt->definesRegister(Src, /*TRI=*/nullptr)) {
    InsPt++;
    return BuildMI(MBB, InsPt, DL,
                   get(AMDGPU::LaneMaskConstants::get(ST).MovTermOpc), Dst)
        .addReg(Src, {}, SrcSubReg)
        .addReg(AMDGPU::EXEC, RegState::Implicit);
  }
  return TargetInstrInfo::createPHISourceCopy(MBB, InsPt, DL, Src, SrcSubReg,
                                              Dst);
}

bool llvm::SIInstrInfo::isWave32() const { return ST.isWave32(); }

bool SIInstrInfo::hasRAWDependency(const MachineInstr &FirstMI,
                                   const MachineInstr &SecondMI) const {
  for (const auto &Use : SecondMI.all_uses()) {
    if (Use.isReg() && FirstMI.modifiesRegister(Use.getReg(), &RI))
      return true;
  }
  return false;
}

/// If OpX is multicycle, anti-dependencies are not allowed.
/// isDPMACCInstruction was not designed for VOPD, but it is fit for the
/// purpose.
bool llvm::SIInstrInfo::isVOPDAntidependencyAllowed(
    const MachineInstr &OpX) const {
  return !AMDGPU::isDPMACCInstruction(OpX.getOpcode());
}

MachineInstr *
SIInstrInfo::foldMemoryOperandImpl(MachineFunction &MF, MachineInstr &MI,
                                   ArrayRef<unsigned> Ops, int FrameIndex,
                                   MachineInstr *&CopyMI, LiveIntervals *LIS,
                                   VirtRegMap *VRM) const {
  // This is a bit of a hack (copied from AArch64). Consider this instruction:
  //
  //   %0:sreg_32 = COPY $m0
  //
  // We explicitly chose SReg_32 for the virtual register so such a copy might
  // be eliminated by RegisterCoalescer. However, that may not be possible, and
  // %0 may even spill. We can't spill $m0 normally (it would require copying to
  // a numbered SGPR anyway), and since it is in the SReg_32 register class,
  // TargetInstrInfo::foldMemoryOperand() is going to try.
  // A similar issue also exists with spilling and reloading $exec registers.
  //
  // To prevent that, constrain the %0 register class here.
  if (isFullCopyInstr(MI)) {
    Register DstReg = MI.getOperand(0).getReg();
    Register SrcReg = MI.getOperand(1).getReg();
    if ((DstReg.isVirtual() || SrcReg.isVirtual()) &&
        (DstReg.isVirtual() != SrcReg.isVirtual())) {
      MachineRegisterInfo &MRI = MF.getRegInfo();
      Register VirtReg = DstReg.isVirtual() ? DstReg : SrcReg;
      const TargetRegisterClass *RC = MRI.getRegClass(VirtReg);
      if (RC->hasSuperClassEq(&AMDGPU::SReg_32RegClass)) {
        MRI.constrainRegClass(VirtReg, &AMDGPU::SReg_32_XM0_XEXECRegClass);
        return nullptr;
      }
      if (RC->hasSuperClassEq(&AMDGPU::SReg_64RegClass)) {
        MRI.constrainRegClass(VirtReg, &AMDGPU::SReg_64_XEXECRegClass);
        return nullptr;
      }
    }
  }

  return nullptr;
}

unsigned SIInstrInfo::getInstrLatency(const InstrItineraryData *ItinData,
                                      const MachineInstr &MI,
                                      unsigned *PredCost) const {
  if (MI.isBundle()) {
    MachineBasicBlock::const_instr_iterator I(MI.getIterator());
    MachineBasicBlock::const_instr_iterator E(MI.getParent()->instr_end());
    unsigned Lat = 0, Count = 0;
    for (++I; I != E && I->isBundledWithPred(); ++I) {
      ++Count;
      Lat = std::max(Lat, SchedModel.computeInstrLatency(&*I));
    }
    return Lat + Count - 1;
  }

  return SchedModel.computeInstrLatency(&MI);
}

const MachineOperand &
SIInstrInfo::getCalleeOperand(const MachineInstr &MI) const {
  if (const MachineOperand *CallAddrOp =
          getNamedOperand(MI, AMDGPU::OpName::src0))
    return *CallAddrOp;
  return TargetInstrInfo::getCalleeOperand(MI);
}

ValueUniformity
SIInstrInfo::getGenericValueUniformity(const MachineInstr &MI) const {
  const MachineRegisterInfo &MRI = MI.getMF()->getRegInfo();
  unsigned Opcode = MI.getOpcode();

  auto HandleAddrSpaceCast = [this, &MRI](const MachineInstr &MI) {
    Register Dst = MI.getOperand(0).getReg();
    Register Src = isa<GIntrinsic>(MI) ? MI.getOperand(2).getReg()
                                       : MI.getOperand(1).getReg();
    LLT DstTy = MRI.getType(Dst);
    LLT SrcTy = MRI.getType(Src);
    unsigned DstAS = DstTy.getAddressSpace();
    unsigned SrcAS = SrcTy.getAddressSpace();
    return SrcAS == AMDGPUAS::PRIVATE_ADDRESS &&
                   DstAS == AMDGPUAS::FLAT_ADDRESS &&
                   ST.hasGloballyAddressableScratch()
               ? ValueUniformity::NeverUniform
               : ValueUniformity::Default;
  };

  // If the target supports globally addressable scratch, the mapping from
  // scratch memory to the flat aperture changes therefore an address space cast
  // is no longer uniform.
  if (Opcode == TargetOpcode::G_ADDRSPACE_CAST)
    return HandleAddrSpaceCast(MI);

  if (auto *GI = dyn_cast<GIntrinsic>(&MI)) {
    auto IID = GI->getIntrinsicID();
    if (AMDGPU::isIntrinsicSourceOfDivergence(IID))
      return ValueUniformity::NeverUniform;
    if (AMDGPU::isIntrinsicAlwaysUniform(IID))
      return ValueUniformity::AlwaysUniform;

    switch (IID) {
    case Intrinsic::amdgcn_addrspacecast_nonnull:
      return HandleAddrSpaceCast(MI);
    case Intrinsic::amdgcn_if:
    case Intrinsic::amdgcn_else:
      // FIXME: Uniform if second result
      break;
    }

    return ValueUniformity::Default;
  }

  // Loads from the private and flat address spaces are divergent, because
  // threads can execute the load instruction with the same inputs and get
  // different results.
  //
  // All other loads are not divergent, because if threads issue loads with the
  // same arguments, they will always get the same result.
  if (Opcode == AMDGPU::G_LOAD || Opcode == AMDGPU::G_ZEXTLOAD ||
      Opcode == AMDGPU::G_SEXTLOAD) {
    if (MI.memoperands_empty())
      return ValueUniformity::NeverUniform; // conservative assumption

    if (llvm::any_of(MI.memoperands(), [](const MachineMemOperand *mmo) {
          return mmo->getAddrSpace() == AMDGPUAS::PRIVATE_ADDRESS ||
                 mmo->getAddrSpace() == AMDGPUAS::FLAT_ADDRESS;
        })) {
      // At least one MMO in a non-global address space.
      return ValueUniformity::NeverUniform;
    }
    return ValueUniformity::Default;
  }

  if (SIInstrInfo::isGenericAtomicRMWOpcode(Opcode) ||
      Opcode == AMDGPU::G_ATOMIC_CMPXCHG ||
      Opcode == AMDGPU::G_ATOMIC_CMPXCHG_WITH_SUCCESS ||
      AMDGPU::isGenericAtomic(Opcode)) {
    return ValueUniformity::NeverUniform;
  }

  // Result is computed from uniform SP and uniform wave-wide max size.
  if (Opcode == TargetOpcode::G_DYN_STACKALLOC)
    return ValueUniformity::AlwaysUniform;

  if (Opcode == AMDGPU::G_AMDGPU_WHOLE_WAVE_FUNC_SETUP)
    return ValueUniformity::NeverUniform;

  return ValueUniformity::Default;
}

const MIRFormatter *SIInstrInfo::getMIRFormatter() const {
  if (!Formatter)
    Formatter = std::make_unique<AMDGPUMIRFormatter>(ST);
  return Formatter.get();
}

ValueUniformity SIInstrInfo::getValueUniformity(const MachineInstr &MI) const {

  if (isNeverUniform(MI))
    return ValueUniformity::NeverUniform;

  unsigned opcode = MI.getOpcode();
  if (opcode == AMDGPU::V_READLANE_B32 ||
      opcode == AMDGPU::V_READFIRSTLANE_B32 ||
      opcode == AMDGPU::SI_RESTORE_S32_FROM_VGPR)
    return ValueUniformity::AlwaysUniform;

  // If any of defs is divergent, report as NeverUniform. isUniformReg will
  // calculate in more detail for each def from its reg class, if available.
  if (MI.isInlineAsm()) {
    for (const MachineOperand &MO : MI.operands()) {
      if (!MO.isReg() || !MO.isDef())
        continue;
      const TargetRegisterClass *RC =
          MI.getRegClassConstraint(MO.getOperandNo(), this, &RI);
      if (!RC || !RI.isSGPRClass(RC))
        return ValueUniformity::NeverUniform;
    }
  }

  if (isCopyInstr(MI)) {
    const MachineOperand &srcOp = MI.getOperand(1);
    if (srcOp.isReg() && srcOp.getReg().isPhysical()) {
      const TargetRegisterClass *regClass =
          RI.getPhysRegBaseClass(srcOp.getReg());
      return RI.isSGPRClass(regClass) ? ValueUniformity::AlwaysUniform
                                      : ValueUniformity::NeverUniform;
    }
    return ValueUniformity::Default;
  }

  // GMIR handling
  if (MI.isPreISelOpcode())
    return SIInstrInfo::getGenericValueUniformity(MI);

  // Atomics are divergent because they are executed sequentially: when an
  // atomic operation refers to the same address in each thread, then each
  // thread after the first sees the value written by the previous thread as
  // original value.

  if (isAtomic(MI))
    return ValueUniformity::NeverUniform;

  // Loads from the private and flat address spaces are divergent, because
  // threads can execute the load instruction with the same inputs and get
  // different results.
  if (isFLAT(MI) && MI.mayLoad()) {
    if (MI.memoperands_empty())
      return ValueUniformity::NeverUniform; // conservative assumption

    if (llvm::any_of(MI.memoperands(), [](const MachineMemOperand *mmo) {
          return mmo->getAddrSpace() == AMDGPUAS::PRIVATE_ADDRESS ||
                 mmo->getAddrSpace() == AMDGPUAS::FLAT_ADDRESS;
        })) {
      // At least one MMO in a non-global address space.
      return ValueUniformity::NeverUniform;
    }

    return ValueUniformity::Default;
  }

  const MachineRegisterInfo &MRI = MI.getMF()->getRegInfo();
  const AMDGPURegisterBankInfo *RBI = ST.getRegBankInfo();

  // FIXME: It's conceptually broken to report this for an instruction, and not
  // a specific def operand. For inline asm in particular, there could be mixed
  // uniform and divergent results.
  for (unsigned I = 0, E = MI.getNumOperands(); I != E; ++I) {
    const MachineOperand &SrcOp = MI.getOperand(I);
    if (!SrcOp.isReg())
      continue;

    Register Reg = SrcOp.getReg();
    if (!Reg || !SrcOp.readsReg())
      continue;

    // If RegBank is null, this is unassigned or an unallocatable special
    // register, which are all scalars.
    const RegisterBank *RegBank = RBI->getRegBank(Reg, MRI, RI);
    if (RegBank && RegBank->getID() != AMDGPU::SGPRRegBankID)
      return ValueUniformity::NeverUniform;
  }

  // TODO: Uniformity check condtions above can be rearranged for more
  // redability

  // TODO: amdgcn.{ballot, [if]cmp} should be AlwaysUniform, but they are
  //       currently turned into no-op COPYs by SelectionDAG ISel and are
  //       therefore no longer recognizable.

  return ValueUniformity::Default;
}

unsigned SIInstrInfo::getDSShaderTypeValue(const MachineFunction &MF) {
  switch (MF.getFunction().getCallingConv()) {
  case CallingConv::AMDGPU_PS:
    return 1;
  case CallingConv::AMDGPU_VS:
    return 2;
  case CallingConv::AMDGPU_GS:
    return 3;
  case CallingConv::AMDGPU_HS:
  case CallingConv::AMDGPU_LS:
  case CallingConv::AMDGPU_ES: {
    const Function &F = MF.getFunction();
    F.getContext().diagnose(DiagnosticInfoUnsupported(
        F, "ds_ordered_count unsupported for this calling conv"));
    [[fallthrough]];
  }
  case CallingConv::AMDGPU_CS:
  case CallingConv::AMDGPU_KERNEL:
  case CallingConv::C:
  case CallingConv::Fast:
  default:
    // Assume other calling conventions are various compute callable functions
    return 0;
  }
}

bool SIInstrInfo::analyzeCompare(const MachineInstr &MI, Register &SrcReg,
                                 Register &SrcReg2, int64_t &CmpMask,
                                 int64_t &CmpValue) const {
  if (!MI.getOperand(0).isReg() || MI.getOperand(0).getSubReg())
    return false;

  switch (MI.getOpcode()) {
  default:
    break;
  case AMDGPU::S_CMP_EQ_U32:
  case AMDGPU::S_CMP_EQ_I32:
  case AMDGPU::S_CMP_LG_U32:
  case AMDGPU::S_CMP_LG_I32:
  case AMDGPU::S_CMP_LT_U32:
  case AMDGPU::S_CMP_LT_I32:
  case AMDGPU::S_CMP_GT_U32:
  case AMDGPU::S_CMP_GT_I32:
  case AMDGPU::S_CMP_LE_U32:
  case AMDGPU::S_CMP_LE_I32:
  case AMDGPU::S_CMP_GE_U32:
  case AMDGPU::S_CMP_GE_I32:
  case AMDGPU::S_CMP_EQ_U64:
  case AMDGPU::S_CMP_LG_U64:
    SrcReg = MI.getOperand(0).getReg();
    if (MI.getOperand(1).isReg()) {
      if (MI.getOperand(1).getSubReg())
        return false;
      SrcReg2 = MI.getOperand(1).getReg();
      CmpValue = 0;
    } else if (MI.getOperand(1).isImm()) {
      SrcReg2 = Register();
      CmpValue = MI.getOperand(1).getImm();
    } else {
      return false;
    }
    CmpMask = ~0;
    return true;
  case AMDGPU::S_CMPK_EQ_U32:
  case AMDGPU::S_CMPK_EQ_I32:
  case AMDGPU::S_CMPK_LG_U32:
  case AMDGPU::S_CMPK_LG_I32:
  case AMDGPU::S_CMPK_LT_U32:
  case AMDGPU::S_CMPK_LT_I32:
  case AMDGPU::S_CMPK_GT_U32:
  case AMDGPU::S_CMPK_GT_I32:
  case AMDGPU::S_CMPK_LE_U32:
  case AMDGPU::S_CMPK_LE_I32:
  case AMDGPU::S_CMPK_GE_U32:
  case AMDGPU::S_CMPK_GE_I32:
    SrcReg = MI.getOperand(0).getReg();
    SrcReg2 = Register();
    CmpValue = MI.getOperand(1).getImm();
    CmpMask = ~0;
    return true;
  }

  return false;
}

static bool isSCCDeadOnExit(MachineBasicBlock *MBB) {
  for (MachineBasicBlock *S : MBB->successors()) {
    if (S->isLiveIn(AMDGPU::SCC))
      return false;
  }
  return true;
}

// Invert all uses of SCC following SCCDef because SCCDef may be deleted and
// (incoming SCC) = !(SCC defined by SCCDef).
// Return true if all uses can be re-written, false otherwise.
bool SIInstrInfo::invertSCCUse(MachineInstr *SCCDef) const {
  MachineBasicBlock *MBB = SCCDef->getParent();
  SmallVector<MachineInstr *> InvertInstr;
  bool SCCIsDead = false;

  // Scan instructions for SCC uses that need to be inverted until SCC is dead.
  constexpr unsigned ScanLimit = 12;
  unsigned Count = 0;
  for (MachineInstr &MI :
       make_range(std::next(MachineBasicBlock::iterator(SCCDef)), MBB->end())) {
    if (++Count > ScanLimit)
      return false;
    if (MI.readsRegister(AMDGPU::SCC, &RI)) {
      if (MI.getOpcode() == AMDGPU::S_CSELECT_B32 ||
          MI.getOpcode() == AMDGPU::S_CSELECT_B64 ||
          MI.getOpcode() == AMDGPU::S_CBRANCH_SCC0 ||
          MI.getOpcode() == AMDGPU::S_CBRANCH_SCC1)
        InvertInstr.push_back(&MI);
      else
        return false;
    }
    if (MI.definesRegister(AMDGPU::SCC, &RI)) {
      SCCIsDead = true;
      break;
    }
  }
  if (!SCCIsDead && isSCCDeadOnExit(MBB))
    SCCIsDead = true;

  // SCC may have more uses.  Can't invert all of them.
  if (!SCCIsDead)
    return false;

  // Invert uses
  for (MachineInstr *MI : InvertInstr) {
    if (MI->getOpcode() == AMDGPU::S_CSELECT_B32 ||
        MI->getOpcode() == AMDGPU::S_CSELECT_B64) {
      swapOperands(*MI);
    } else if (MI->getOpcode() == AMDGPU::S_CBRANCH_SCC0 ||
               MI->getOpcode() == AMDGPU::S_CBRANCH_SCC1) {
      MI->setDesc(get(MI->getOpcode() == AMDGPU::S_CBRANCH_SCC0
                          ? AMDGPU::S_CBRANCH_SCC1
                          : AMDGPU::S_CBRANCH_SCC0));
    } else {
      llvm_unreachable("SCC used but no inversion handling");
    }
  }
  return true;
}

// SCC is already valid after SCCValid.
// SCCRedefine will redefine SCC to the same value already available after
// SCCValid. If there are no intervening SCC conflicts delete SCCRedefine and
// update kill/dead flags if necessary.
bool SIInstrInfo::optimizeSCC(MachineInstr *SCCValid, MachineInstr *SCCRedefine,
                              bool NeedInversion) const {
  MachineInstr *KillsSCC = nullptr;
  if (SCCValid->getParent() != SCCRedefine->getParent())
    return false;
  for (MachineInstr &MI : make_range(std::next(SCCValid->getIterator()),
                                     SCCRedefine->getIterator())) {
    if (MI.modifiesRegister(AMDGPU::SCC, &RI))
      return false;
    if (MI.killsRegister(AMDGPU::SCC, &RI))
      KillsSCC = &MI;
  }
  if (NeedInversion && !invertSCCUse(SCCRedefine))
    return false;
  if (MachineOperand *SccDef =
          SCCValid->findRegisterDefOperand(AMDGPU::SCC, /*TRI=*/nullptr))
    SccDef->setIsDead(false);
  if (KillsSCC)
    KillsSCC->clearRegisterKills(AMDGPU::SCC, /*TRI=*/nullptr);
  SCCRedefine->eraseFromParent();
  return true;
}

static bool foldableSelect(const MachineInstr &Def) {
  if (Def.getOpcode() != AMDGPU::S_CSELECT_B32 &&
      Def.getOpcode() != AMDGPU::S_CSELECT_B64)
    return false;
  bool Op1IsNonZeroImm =
      Def.getOperand(1).isImm() && Def.getOperand(1).getImm() != 0;
  bool Op2IsZeroImm =
      Def.getOperand(2).isImm() && Def.getOperand(2).getImm() == 0;
  if (!Op1IsNonZeroImm || !Op2IsZeroImm)
    return false;
  return true;
}

static bool setsSCCIfResultIsZero(const MachineInstr &Def, bool &NeedInversion,
                                  unsigned &NewDefOpc) {
  // S_ADD_U32 X, 1 sets SCC on carryout which can only happen if result==0.
  // S_ADD_I32 X, 1 can be converted to S_ADD_U32 X, 1 if SCC is dead.
  if (Def.getOpcode() != AMDGPU::S_ADD_I32 &&
      Def.getOpcode() != AMDGPU::S_ADD_U32)
    return false;
  const MachineOperand &AddSrc1 = Def.getOperand(1);
  const MachineOperand &AddSrc2 = Def.getOperand(2);
  int64_t addend;

  if ((!AddSrc1.isImm() || AddSrc1.getImm() != 1) &&
      (!AddSrc2.isImm() || AddSrc2.getImm() != 1) &&
      (!getFoldableImm(&AddSrc1, addend) || addend != 1) &&
      (!getFoldableImm(&AddSrc2, addend) || addend != 1))
    return false;

  if (Def.getOpcode() == AMDGPU::S_ADD_I32) {
    const MachineOperand *SccDef =
        Def.findRegisterDefOperand(AMDGPU::SCC, /*TRI=*/nullptr);
    if (!SccDef->isDead())
      return false;
    NewDefOpc = AMDGPU::S_ADD_U32;
  }
  NeedInversion = !NeedInversion;
  return true;
}

bool SIInstrInfo::optimizeCompareInstr(MachineInstr &CmpInstr, Register SrcReg,
                                       Register SrcReg2, int64_t CmpMask,
                                       int64_t CmpValue,
                                       const MachineRegisterInfo *MRI) const {
  if (!SrcReg || SrcReg.isPhysical())
    return false;

  if (SrcReg2 && !getFoldableImm(SrcReg2, *MRI, CmpValue))
    return false;

  const auto optimizeCmpSelect = [&CmpInstr, SrcReg, CmpValue, MRI,
                                  this](bool NeedInversion) -> bool {
    if (CmpValue != 0)
      return false;

    MachineInstr *Def = MRI->getVRegDef(SrcReg);
    if (!Def)
      return false;

    // For S_OP that set SCC = DST!=0, do the transformation
    //
    //   s_cmp_[lg|eq]_* (S_OP ...), 0 => (S_OP ...)
    //
    // For (S_OP ...) that set SCC = DST==0, invert NeedInversion and
    // do the transformation:
    //
    //   s_cmp_[lg|eq]_* (S_OP ...), 0 => (S_OP ...)
    //
    // If foldableSelect, s_cmp_lg_* is redundant because the SCC input value
    // for S_CSELECT* already has the same value that will be calculated by
    // s_cmp_lg_*
    //
    //   s_cmp_[lg|eq]_* (S_CSELECT* (non-zero imm), 0), 0 => (S_CSELECT*
    //   (non-zero imm), 0)

    unsigned NewDefOpc = Def->getOpcode();
    if (!setsSCCIfResultIsNonZero(*Def) &&
        !setsSCCIfResultIsZero(*Def, NeedInversion, NewDefOpc) &&
        !foldableSelect(*Def))
      return false;

    if (!optimizeSCC(Def, &CmpInstr, NeedInversion))
      return false;

    if (NewDefOpc != Def->getOpcode())
      Def->setDesc(get(NewDefOpc));

    // If s_or_b32 result, sY, is unused (i.e. it is effectively a 64-bit
    // s_cmp_lg of a register pair) and the inputs are the hi and lo-halves of a
    // 64-bit foldableSelect then delete s_or_b32 in the sequence:
    //    sX = s_cselect_b64 (non-zero imm), 0
    //    sLo = copy sX.sub0
    //    sHi = copy sX.sub1
    //    sY = s_or_b32 sLo, sHi
    if (Def->getOpcode() == AMDGPU::S_OR_B32 &&
        MRI->use_nodbg_empty(Def->getOperand(0).getReg())) {
      const MachineOperand &OrOpnd1 = Def->getOperand(1);
      const MachineOperand &OrOpnd2 = Def->getOperand(2);
      if (OrOpnd1.isReg() && OrOpnd2.isReg()) {
        MachineInstr *Def1 = MRI->getVRegDef(OrOpnd1.getReg());
        MachineInstr *Def2 = MRI->getVRegDef(OrOpnd2.getReg());
        if (Def1 && Def1->getOpcode() == AMDGPU::COPY && Def2 &&
            Def2->getOpcode() == AMDGPU::COPY && Def1->getOperand(1).isReg() &&
            Def2->getOperand(1).isReg() &&
            Def1->getOperand(1).getSubReg() == AMDGPU::sub0 &&
            Def2->getOperand(1).getSubReg() == AMDGPU::sub1 &&
            Def1->getOperand(1).getReg() == Def2->getOperand(1).getReg()) {
          MachineInstr *Select = MRI->getVRegDef(Def1->getOperand(1).getReg());
          if (Select && foldableSelect(*Select))
            optimizeSCC(Select, Def, /*NeedInversion=*/false);
        }
      }
    }
    return true;
  };

  const auto optimizeCmpAnd = [&CmpInstr, SrcReg, CmpValue, MRI,
                               this](int64_t ExpectedValue, unsigned SrcSize,
                                     bool IsReversible, bool IsSigned) -> bool {
    // s_cmp_eq_u32 (s_and_b32 $src, 1 << n), 1 << n => s_and_b32 $src, 1 << n
    // s_cmp_eq_i32 (s_and_b32 $src, 1 << n), 1 << n => s_and_b32 $src, 1 << n
    // s_cmp_ge_u32 (s_and_b32 $src, 1 << n), 1 << n => s_and_b32 $src, 1 << n
    // s_cmp_ge_i32 (s_and_b32 $src, 1 << n), 1 << n => s_and_b32 $src, 1 << n
    // s_cmp_eq_u64 (s_and_b64 $src, 1 << n), 1 << n => s_and_b64 $src, 1 << n
    // s_cmp_lg_u32 (s_and_b32 $src, 1 << n), 0 => s_and_b32 $src, 1 << n
    // s_cmp_lg_i32 (s_and_b32 $src, 1 << n), 0 => s_and_b32 $src, 1 << n
    // s_cmp_gt_u32 (s_and_b32 $src, 1 << n), 0 => s_and_b32 $src, 1 << n
    // s_cmp_gt_i32 (s_and_b32 $src, 1 << n), 0 => s_and_b32 $src, 1 << n
    // s_cmp_lg_u64 (s_and_b64 $src, 1 << n), 0 => s_and_b64 $src, 1 << n
    //
    // Signed ge/gt are not used for the sign bit.
    //
    // If result of the AND is unused except in the compare:
    // s_and_b(32|64) $src, 1 << n => s_bitcmp1_b(32|64) $src, n
    //
    // s_cmp_eq_u32 (s_and_b32 $src, 1 << n), 0 => s_bitcmp0_b32 $src, n
    // s_cmp_eq_i32 (s_and_b32 $src, 1 << n), 0 => s_bitcmp0_b32 $src, n
    // s_cmp_eq_u64 (s_and_b64 $src, 1 << n), 0 => s_bitcmp0_b64 $src, n
    // s_cmp_lg_u32 (s_and_b32 $src, 1 << n), 1 << n => s_bitcmp0_b32 $src, n
    // s_cmp_lg_i32 (s_and_b32 $src, 1 << n), 1 << n => s_bitcmp0_b32 $src, n
    // s_cmp_lg_u64 (s_and_b64 $src, 1 << n), 1 << n => s_bitcmp0_b64 $src, n

    MachineInstr *Def = MRI->getVRegDef(SrcReg);
    if (!Def)
      return false;

    if (Def->getOpcode() != AMDGPU::S_AND_B32 &&
        Def->getOpcode() != AMDGPU::S_AND_B64)
      return false;

    int64_t Mask;
    const auto isMask = [&Mask, SrcSize](const MachineOperand *MO) -> bool {
      if (MO->isImm())
        Mask = MO->getImm();
      else if (!getFoldableImm(MO, Mask))
        return false;
      Mask &= maxUIntN(SrcSize);
      return isPowerOf2_64(Mask);
    };

    MachineOperand *SrcOp = &Def->getOperand(1);
    if (isMask(SrcOp))
      SrcOp = &Def->getOperand(2);
    else if (isMask(&Def->getOperand(2)))
      SrcOp = &Def->getOperand(1);
    else
      return false;

    // A valid Mask is required to have a single bit set, hence a non-zero and
    // power-of-two value. This verifies that we will not do 64-bit shift below.
    assert(llvm::has_single_bit<uint64_t>(Mask) && "Invalid mask.");
    unsigned BitNo = llvm::countr_zero((uint64_t)Mask);
    if (IsSigned && BitNo == SrcSize - 1)
      return false;

    ExpectedValue <<= BitNo;

    bool IsReversedCC = false;
    if (CmpValue != ExpectedValue) {
      if (!IsReversible)
        return false;
      IsReversedCC = CmpValue == (ExpectedValue ^ Mask);
      if (!IsReversedCC)
        return false;
    }

    Register DefReg = Def->getOperand(0).getReg();
    if (IsReversedCC && !MRI->hasOneNonDBGUse(DefReg))
      return false;

    if (!optimizeSCC(Def, &CmpInstr, /*NeedInversion=*/false))
      return false;

    if (!MRI->use_nodbg_empty(DefReg)) {
      assert(!IsReversedCC);
      return true;
    }

    // Replace AND with unused result with a S_BITCMP.
    MachineBasicBlock *MBB = Def->getParent();

    unsigned NewOpc = (SrcSize == 32) ? IsReversedCC ? AMDGPU::S_BITCMP0_B32
                                                     : AMDGPU::S_BITCMP1_B32
                                      : IsReversedCC ? AMDGPU::S_BITCMP0_B64
                                                     : AMDGPU::S_BITCMP1_B64;

    BuildMI(*MBB, Def, Def->getDebugLoc(), get(NewOpc))
      .add(*SrcOp)
      .addImm(BitNo);
    Def->eraseFromParent();

    return true;
  };

  switch (CmpInstr.getOpcode()) {
  default:
    break;
  case AMDGPU::S_CMP_EQ_U32:
  case AMDGPU::S_CMP_EQ_I32:
  case AMDGPU::S_CMPK_EQ_U32:
  case AMDGPU::S_CMPK_EQ_I32:
    return optimizeCmpAnd(1, 32, true, false) ||
           optimizeCmpSelect(/*NeedInversion=*/true);
  case AMDGPU::S_CMP_GE_U32:
  case AMDGPU::S_CMPK_GE_U32:
    return optimizeCmpAnd(1, 32, false, false);
  case AMDGPU::S_CMP_GE_I32:
  case AMDGPU::S_CMPK_GE_I32:
    return optimizeCmpAnd(1, 32, false, true);
  case AMDGPU::S_CMP_EQ_U64:
    return optimizeCmpAnd(1, 64, true, false);
  case AMDGPU::S_CMP_LG_U32:
  case AMDGPU::S_CMP_LG_I32:
  case AMDGPU::S_CMPK_LG_U32:
  case AMDGPU::S_CMPK_LG_I32:
    return optimizeCmpAnd(0, 32, true, false) ||
           optimizeCmpSelect(/*NeedInversion=*/false);
  case AMDGPU::S_CMP_GT_U32:
  case AMDGPU::S_CMPK_GT_U32:
    return optimizeCmpAnd(0, 32, false, false);
  case AMDGPU::S_CMP_GT_I32:
  case AMDGPU::S_CMPK_GT_I32:
    return optimizeCmpAnd(0, 32, false, true);
  case AMDGPU::S_CMP_LG_U64:
    return optimizeCmpAnd(0, 64, true, false) ||
           optimizeCmpSelect(/*NeedInversion=*/false);
  }

  return false;
}

void SIInstrInfo::enforceOperandRCAlignment(MachineInstr &MI,
                                            AMDGPU::OpName OpName) const {
  if (!ST.needsAlignedVGPRs())
    return;

  int OpNo = AMDGPU::getNamedOperandIdx(MI.getOpcode(), OpName);
  if (OpNo < 0)
    return;
  MachineOperand &Op = MI.getOperand(OpNo);
  if (getOpSize(MI, OpNo) > 4)
    return;

  // Add implicit aligned super-reg to force alignment on the data operand.
  const DebugLoc &DL = MI.getDebugLoc();
  MachineBasicBlock *BB = MI.getParent();
  MachineRegisterInfo &MRI = BB->getParent()->getRegInfo();
  Register DataReg = Op.getReg();
  bool IsAGPR = RI.isAGPR(MRI, DataReg);
  Register Undef = MRI.createVirtualRegister(
      IsAGPR ? &AMDGPU::AGPR_32RegClass : &AMDGPU::VGPR_32RegClass);
  BuildMI(*BB, MI, DL, get(AMDGPU::IMPLICIT_DEF), Undef);
  Register NewVR =
      MRI.createVirtualRegister(IsAGPR ? &AMDGPU::AReg_64_Align2RegClass
                                       : &AMDGPU::VReg_64_Align2RegClass);
  BuildMI(*BB, MI, DL, get(AMDGPU::REG_SEQUENCE), NewVR)
      .addReg(DataReg, {}, Op.getSubReg())
      .addImm(AMDGPU::sub0)
      .addReg(Undef)
      .addImm(AMDGPU::sub1);
  Op.setReg(NewVR);
  Op.setSubReg(AMDGPU::sub0);
  MI.addOperand(MachineOperand::CreateReg(NewVR, false, true));
}

bool SIInstrInfo::isGlobalMemoryObject(const MachineInstr *MI) const {
  if (isIGLP(*MI))
    return false;

  return TargetInstrInfo::isGlobalMemoryObject(MI);
}

bool SIInstrInfo::isXDLWMMA(const MachineInstr &MI) const {
  if (!isWMMA(MI) && !isSWMMAC(MI))
    return false;

  if (ST.hasGFX1250Insts())
    return AMDGPU::getWMMAIsXDL(MI.getOpcode());

  return true;
}

bool SIInstrInfo::isXDL(const MachineInstr &MI) const {
  unsigned Opcode = MI.getOpcode();

  if (AMDGPU::isGFX12Plus(ST))
    return isDOT(MI) || isXDLWMMA(MI);

  if (!isMAI(MI) || isDGEMM(Opcode) ||
      Opcode == AMDGPU::V_ACCVGPR_WRITE_B32_e64 ||
      Opcode == AMDGPU::V_ACCVGPR_READ_B32_e64)
    return false;

  if (!ST.hasGFX940Insts())
    return true;

  return AMDGPU::getMAIIsGFX940XDL(Opcode);
}
