//===- SPIRVInstructionSelector.cpp ------------------------------*- C++ -*-==//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
//
// This file implements the targeting of the InstructionSelector class for
// SPIRV.
// TODO: This should be generated by TableGen.
//
//===----------------------------------------------------------------------===//

#include "MCTargetDesc/SPIRVBaseInfo.h"
#include "MCTargetDesc/SPIRVMCTargetDesc.h"
#include "SPIRV.h"
#include "SPIRVGlobalRegistry.h"
#include "SPIRVInstrInfo.h"
#include "SPIRVRegisterInfo.h"
#include "SPIRVTargetMachine.h"
#include "SPIRVUtils.h"
#include "llvm/ADT/APFloat.h"
#include "llvm/ADT/StringExtras.h"
#include "llvm/CodeGen/GlobalISel/GIMatchTableExecutorImpl.h"
#include "llvm/CodeGen/GlobalISel/GenericMachineInstrs.h"
#include "llvm/CodeGen/GlobalISel/InstructionSelector.h"
#include "llvm/CodeGen/MachineInstrBuilder.h"
#include "llvm/CodeGen/MachineRegisterInfo.h"
#include "llvm/CodeGen/Register.h"
#include "llvm/CodeGen/TargetOpcodes.h"
#include "llvm/IR/IntrinsicsSPIRV.h"
#include "llvm/Support/Debug.h"
#include "llvm/Support/ErrorHandling.h"

#define DEBUG_TYPE "spirv-isel"

using namespace llvm;
namespace CL = SPIRV::OpenCLExtInst;
namespace GL = SPIRV::GLSLExtInst;

using ExtInstList =
    std::vector<std::pair<SPIRV::InstructionSet::InstructionSet, uint32_t>>;

namespace {

llvm::SPIRV::SelectionControl::SelectionControl
getSelectionOperandForImm(int Imm) {
  if (Imm == 2)
    return SPIRV::SelectionControl::Flatten;
  if (Imm == 1)
    return SPIRV::SelectionControl::DontFlatten;
  if (Imm == 0)
    return SPIRV::SelectionControl::None;
  llvm_unreachable("Invalid immediate");
}

#define GET_GLOBALISEL_PREDICATE_BITSET
#include "SPIRVGenGlobalISel.inc"
#undef GET_GLOBALISEL_PREDICATE_BITSET

class SPIRVInstructionSelector : public InstructionSelector {
  const SPIRVSubtarget &STI;
  const SPIRVInstrInfo &TII;
  const SPIRVRegisterInfo &TRI;
  const RegisterBankInfo &RBI;
  SPIRVGlobalRegistry &GR;
  MachineRegisterInfo *MRI;
  MachineFunction *HasVRegsReset = nullptr;

  /// We need to keep track of the number we give to anonymous global values to
  /// generate the same name every time when this is needed.
  mutable DenseMap<const GlobalValue *, unsigned> UnnamedGlobalIDs;
  SmallPtrSet<MachineInstr *, 8> DeadMIs;

public:
  SPIRVInstructionSelector(const SPIRVTargetMachine &TM,
                           const SPIRVSubtarget &ST,
                           const RegisterBankInfo &RBI);
  void setupMF(MachineFunction &MF, GISelValueTracking *VT,
               CodeGenCoverage *CoverageInfo, ProfileSummaryInfo *PSI,
               BlockFrequencyInfo *BFI) override;
  // Common selection code. Instruction-specific selection occurs in spvSelect.
  bool select(MachineInstr &I) override;
  static const char *getName() { return DEBUG_TYPE; }

#define GET_GLOBALISEL_PREDICATES_DECL
#include "SPIRVGenGlobalISel.inc"
#undef GET_GLOBALISEL_PREDICATES_DECL

#define GET_GLOBALISEL_TEMPORARIES_DECL
#include "SPIRVGenGlobalISel.inc"
#undef GET_GLOBALISEL_TEMPORARIES_DECL

private:
  void resetVRegsType(MachineFunction &MF);

  // tblgen-erated 'select' implementation, used as the initial selector for
  // the patterns that don't require complex C++.
  bool selectImpl(MachineInstr &I, CodeGenCoverage &CoverageInfo) const;

  // All instruction-specific selection that didn't happen in "select()".
  // Is basically a large Switch/Case delegating to all other select method.
  bool spvSelect(Register ResVReg, const SPIRVType *ResType,
                 MachineInstr &I) const;

  bool selectFirstBitHigh(Register ResVReg, const SPIRVType *ResType,
                          MachineInstr &I, bool IsSigned) const;

  bool selectFirstBitLow(Register ResVReg, const SPIRVType *ResType,
                         MachineInstr &I) const;

  bool selectFirstBitSet16(Register ResVReg, const SPIRVType *ResType,
                           MachineInstr &I, unsigned ExtendOpcode,
                           unsigned BitSetOpcode) const;

  bool selectFirstBitSet32(Register ResVReg, const SPIRVType *ResType,
                           MachineInstr &I, Register SrcReg,
                           unsigned BitSetOpcode) const;

  bool selectFirstBitSet64(Register ResVReg, const SPIRVType *ResType,
                           MachineInstr &I, Register SrcReg,
                           unsigned BitSetOpcode, bool SwapPrimarySide) const;

  bool selectFirstBitSet64Overflow(Register ResVReg, const SPIRVType *ResType,
                                   MachineInstr &I, Register SrcReg,
                                   unsigned BitSetOpcode,
                                   bool SwapPrimarySide) const;

  bool selectGlobalValue(Register ResVReg, MachineInstr &I,
                         const MachineInstr *Init = nullptr) const;

  bool selectOpWithSrcs(Register ResVReg, const SPIRVType *ResType,
                        MachineInstr &I, std::vector<Register> SrcRegs,
                        unsigned Opcode) const;

  bool selectUnOp(Register ResVReg, const SPIRVType *ResType, MachineInstr &I,
                  unsigned Opcode) const;

  bool selectBitcast(Register ResVReg, const SPIRVType *ResType,
                     MachineInstr &I) const;

  bool selectLoad(Register ResVReg, const SPIRVType *ResType,
                  MachineInstr &I) const;
  bool selectStore(MachineInstr &I) const;

  bool selectStackSave(Register ResVReg, const SPIRVType *ResType,
                       MachineInstr &I) const;
  bool selectStackRestore(MachineInstr &I) const;

  bool selectMemOperation(Register ResVReg, MachineInstr &I) const;

  bool selectAtomicRMW(Register ResVReg, const SPIRVType *ResType,
                       MachineInstr &I, unsigned NewOpcode,
                       unsigned NegateOpcode = 0) const;

  bool selectAtomicCmpXchg(Register ResVReg, const SPIRVType *ResType,
                           MachineInstr &I) const;

  bool selectFence(MachineInstr &I) const;

  bool selectAddrSpaceCast(Register ResVReg, const SPIRVType *ResType,
                           MachineInstr &I) const;

  bool selectAnyOrAll(Register ResVReg, const SPIRVType *ResType,
                      MachineInstr &I, unsigned OpType) const;

  bool selectAll(Register ResVReg, const SPIRVType *ResType,
                 MachineInstr &I) const;

  bool selectAny(Register ResVReg, const SPIRVType *ResType,
                 MachineInstr &I) const;

  bool selectBitreverse(Register ResVReg, const SPIRVType *ResType,
                        MachineInstr &I) const;

  bool selectBuildVector(Register ResVReg, const SPIRVType *ResType,
                         MachineInstr &I) const;
  bool selectSplatVector(Register ResVReg, const SPIRVType *ResType,
                         MachineInstr &I) const;

  bool selectCmp(Register ResVReg, const SPIRVType *ResType,
                 unsigned comparisonOpcode, MachineInstr &I) const;
  bool selectDiscard(Register ResVReg, const SPIRVType *ResType,
                     MachineInstr &I) const;

  bool selectICmp(Register ResVReg, const SPIRVType *ResType,
                  MachineInstr &I) const;
  bool selectFCmp(Register ResVReg, const SPIRVType *ResType,
                  MachineInstr &I) const;

  bool selectSign(Register ResVReg, const SPIRVType *ResType,
                  MachineInstr &I) const;

  bool selectFloatDot(Register ResVReg, const SPIRVType *ResType,
                      MachineInstr &I) const;

  bool selectOverflowArith(Register ResVReg, const SPIRVType *ResType,
                           MachineInstr &I, unsigned Opcode) const;
  bool selectDebugTrap(Register ResVReg, const SPIRVType *ResType,
                       MachineInstr &I) const;

  bool selectIntegerDot(Register ResVReg, const SPIRVType *ResType,
                        MachineInstr &I, bool Signed) const;

  bool selectIntegerDotExpansion(Register ResVReg, const SPIRVType *ResType,
                                 MachineInstr &I) const;

  bool selectOpIsInf(Register ResVReg, const SPIRVType *ResType,
                     MachineInstr &I) const;

  bool selectOpIsNan(Register ResVReg, const SPIRVType *ResType,
                     MachineInstr &I) const;

  template <bool Signed>
  bool selectDot4AddPacked(Register ResVReg, const SPIRVType *ResType,
                           MachineInstr &I) const;
  template <bool Signed>
  bool selectDot4AddPackedExpansion(Register ResVReg, const SPIRVType *ResType,
                                    MachineInstr &I) const;

  bool selectWaveReduceMax(Register ResVReg, const SPIRVType *ResType,
                           MachineInstr &I, bool IsUnsigned) const;

  bool selectWaveReduceSum(Register ResVReg, const SPIRVType *ResType,
                           MachineInstr &I) const;

  bool selectConst(Register ResVReg, const SPIRVType *ResType,
                   MachineInstr &I) const;

  bool selectSelect(Register ResVReg, const SPIRVType *ResType,
                    MachineInstr &I) const;
  bool selectSelectDefaultArgs(Register ResVReg, const SPIRVType *ResType,
                               MachineInstr &I, bool IsSigned) const;
  bool selectIToF(Register ResVReg, const SPIRVType *ResType, MachineInstr &I,
                  bool IsSigned, unsigned Opcode) const;
  bool selectExt(Register ResVReg, const SPIRVType *ResType, MachineInstr &I,
                 bool IsSigned) const;

  bool selectTrunc(Register ResVReg, const SPIRVType *ResType,
                   MachineInstr &I) const;

  bool selectSUCmp(Register ResVReg, const SPIRVType *ResType, MachineInstr &I,
                   bool IsSigned) const;

  bool selectIntToBool(Register IntReg, Register ResVReg, MachineInstr &I,
                       const SPIRVType *intTy, const SPIRVType *boolTy) const;

  bool selectOpUndef(Register ResVReg, const SPIRVType *ResType,
                     MachineInstr &I) const;
  bool selectFreeze(Register ResVReg, const SPIRVType *ResType,
                    MachineInstr &I) const;
  bool selectIntrinsic(Register ResVReg, const SPIRVType *ResType,
                       MachineInstr &I) const;
  bool selectExtractVal(Register ResVReg, const SPIRVType *ResType,
                        MachineInstr &I) const;
  bool selectInsertVal(Register ResVReg, const SPIRVType *ResType,
                       MachineInstr &I) const;
  bool selectExtractElt(Register ResVReg, const SPIRVType *ResType,
                        MachineInstr &I) const;
  bool selectInsertElt(Register ResVReg, const SPIRVType *ResType,
                       MachineInstr &I) const;
  bool selectGEP(Register ResVReg, const SPIRVType *ResType,
                 MachineInstr &I) const;

  bool selectFrameIndex(Register ResVReg, const SPIRVType *ResType,
                        MachineInstr &I) const;
  bool selectAllocaArray(Register ResVReg, const SPIRVType *ResType,
                         MachineInstr &I) const;

  bool selectBranch(MachineInstr &I) const;
  bool selectBranchCond(MachineInstr &I) const;

  bool selectPhi(Register ResVReg, const SPIRVType *ResType,
                 MachineInstr &I) const;

  bool selectExtInst(Register ResVReg, const SPIRVType *RestType,
                     MachineInstr &I, GL::GLSLExtInst GLInst) const;
  bool selectExtInst(Register ResVReg, const SPIRVType *ResType,
                     MachineInstr &I, CL::OpenCLExtInst CLInst) const;
  bool selectExtInst(Register ResVReg, const SPIRVType *ResType,
                     MachineInstr &I, CL::OpenCLExtInst CLInst,
                     GL::GLSLExtInst GLInst) const;
  bool selectExtInst(Register ResVReg, const SPIRVType *ResType,
                     MachineInstr &I, const ExtInstList &ExtInsts) const;
  bool selectExtInstForLRound(Register ResVReg, const SPIRVType *ResType,
                              MachineInstr &I, CL::OpenCLExtInst CLInst,
                              GL::GLSLExtInst GLInst) const;
  bool selectExtInstForLRound(Register ResVReg, const SPIRVType *ResType,
                              MachineInstr &I,
                              const ExtInstList &ExtInsts) const;

  bool selectLog10(Register ResVReg, const SPIRVType *ResType,
                   MachineInstr &I) const;

  bool selectSaturate(Register ResVReg, const SPIRVType *ResType,
                      MachineInstr &I) const;

  bool selectWaveOpInst(Register ResVReg, const SPIRVType *ResType,
                        MachineInstr &I, unsigned Opcode) const;

  bool selectWaveActiveCountBits(Register ResVReg, const SPIRVType *ResType,
                                 MachineInstr &I) const;

  bool selectUnmergeValues(MachineInstr &I) const;

  bool selectHandleFromBinding(Register &ResVReg, const SPIRVType *ResType,
                               MachineInstr &I) const;

  bool selectCounterHandleFromBinding(Register &ResVReg,
                                      const SPIRVType *ResType,
                                      MachineInstr &I) const;

  bool selectReadImageIntrinsic(Register &ResVReg, const SPIRVType *ResType,
                                MachineInstr &I) const;
  bool selectImageWriteIntrinsic(MachineInstr &I) const;
  bool selectResourceGetPointer(Register &ResVReg, const SPIRVType *ResType,
                                MachineInstr &I) const;
  bool selectModf(Register ResVReg, const SPIRVType *ResType,
                  MachineInstr &I) const;
  bool selectUpdateCounter(Register &ResVReg, const SPIRVType *ResType,
                           MachineInstr &I) const;
  bool selectFrexp(Register ResVReg, const SPIRVType *ResType,
                   MachineInstr &I) const;
  // Utilities
  std::pair<Register, bool>
  buildI32Constant(uint32_t Val, MachineInstr &I,
                   const SPIRVType *ResType = nullptr) const;

  Register buildZerosVal(const SPIRVType *ResType, MachineInstr &I) const;
  Register buildZerosValF(const SPIRVType *ResType, MachineInstr &I) const;
  Register buildOnesVal(bool AllOnes, const SPIRVType *ResType,
                        MachineInstr &I) const;
  Register buildOnesValF(const SPIRVType *ResType, MachineInstr &I) const;

  bool wrapIntoSpecConstantOp(MachineInstr &I,
                              SmallVector<Register> &CompositeArgs) const;

  Register getUcharPtrTypeReg(MachineInstr &I,
                              SPIRV::StorageClass::StorageClass SC) const;
  MachineInstrBuilder buildSpecConstantOp(MachineInstr &I, Register Dest,
                                          Register Src, Register DestType,
                                          uint32_t Opcode) const;
  MachineInstrBuilder buildConstGenericPtr(MachineInstr &I, Register SrcPtr,
                                           SPIRVType *SrcPtrTy) const;
  Register buildPointerToResource(const SPIRVType *ResType,
                                  SPIRV::StorageClass::StorageClass SC,
                                  uint32_t Set, uint32_t Binding,
                                  uint32_t ArraySize, Register IndexReg,
                                  bool IsNonUniform, StringRef Name,
                                  MachineIRBuilder MIRBuilder) const;
  SPIRVType *widenTypeToVec4(const SPIRVType *Type, MachineInstr &I) const;
  bool extractSubvector(Register &ResVReg, const SPIRVType *ResType,
                        Register &ReadReg, MachineInstr &InsertionPoint) const;
  bool generateImageRead(Register &ResVReg, const SPIRVType *ResType,
                         Register ImageReg, Register IdxReg, DebugLoc Loc,
                         MachineInstr &Pos) const;
  bool BuildCOPY(Register DestReg, Register SrcReg, MachineInstr &I) const;
  bool loadVec3BuiltinInputID(SPIRV::BuiltIn::BuiltIn BuiltInValue,
                              Register ResVReg, const SPIRVType *ResType,
                              MachineInstr &I) const;
  bool loadBuiltinInputID(SPIRV::BuiltIn::BuiltIn BuiltInValue,
                          Register ResVReg, const SPIRVType *ResType,
                          MachineInstr &I) const;
  bool loadHandleBeforePosition(Register &HandleReg, const SPIRVType *ResType,
                                GIntrinsic &HandleDef, MachineInstr &Pos) const;
};

bool sampledTypeIsSignedInteger(const llvm::Type *HandleType) {
  const TargetExtType *TET = cast<TargetExtType>(HandleType);
  if (TET->getTargetExtName() == "spirv.Image") {
    return false;
  }
  assert(TET->getTargetExtName() == "spirv.SignedImage");
  return TET->getTypeParameter(0)->isIntegerTy();
}
} // end anonymous namespace

#define GET_GLOBALISEL_IMPL
#include "SPIRVGenGlobalISel.inc"
#undef GET_GLOBALISEL_IMPL

SPIRVInstructionSelector::SPIRVInstructionSelector(const SPIRVTargetMachine &TM,
                                                   const SPIRVSubtarget &ST,
                                                   const RegisterBankInfo &RBI)
    : InstructionSelector(), STI(ST), TII(*ST.getInstrInfo()),
      TRI(*ST.getRegisterInfo()), RBI(RBI), GR(*ST.getSPIRVGlobalRegistry()),
      MRI(nullptr),
#define GET_GLOBALISEL_PREDICATES_INIT
#include "SPIRVGenGlobalISel.inc"
#undef GET_GLOBALISEL_PREDICATES_INIT
#define GET_GLOBALISEL_TEMPORARIES_INIT
#include "SPIRVGenGlobalISel.inc"
#undef GET_GLOBALISEL_TEMPORARIES_INIT
{
}

void SPIRVInstructionSelector::setupMF(MachineFunction &MF,
                                       GISelValueTracking *VT,
                                       CodeGenCoverage *CoverageInfo,
                                       ProfileSummaryInfo *PSI,
                                       BlockFrequencyInfo *BFI) {
  MRI = &MF.getRegInfo();
  GR.setCurrentFunc(MF);
  InstructionSelector::setupMF(MF, VT, CoverageInfo, PSI, BFI);
}

// Ensure that register classes correspond to pattern matching rules.
void SPIRVInstructionSelector::resetVRegsType(MachineFunction &MF) {
  if (HasVRegsReset == &MF)
    return;
  HasVRegsReset = &MF;

  MachineRegisterInfo &MRI = MF.getRegInfo();
  for (unsigned I = 0, E = MRI.getNumVirtRegs(); I != E; ++I) {
    Register Reg = Register::index2VirtReg(I);
    LLT RegType = MRI.getType(Reg);
    if (RegType.isScalar())
      MRI.setType(Reg, LLT::scalar(64));
    else if (RegType.isPointer())
      MRI.setType(Reg, LLT::pointer(0, 64));
    else if (RegType.isVector())
      MRI.setType(Reg, LLT::fixed_vector(2, LLT::scalar(64)));
  }
  for (const auto &MBB : MF) {
    for (const auto &MI : MBB) {
      if (isPreISelGenericOpcode(MI.getOpcode()))
        GR.erase(&MI);
      if (MI.getOpcode() != SPIRV::ASSIGN_TYPE)
        continue;

      Register DstReg = MI.getOperand(0).getReg();
      LLT DstType = MRI.getType(DstReg);
      Register SrcReg = MI.getOperand(1).getReg();
      LLT SrcType = MRI.getType(SrcReg);
      if (DstType != SrcType)
        MRI.setType(DstReg, MRI.getType(SrcReg));

      const TargetRegisterClass *DstRC = MRI.getRegClassOrNull(DstReg);
      const TargetRegisterClass *SrcRC = MRI.getRegClassOrNull(SrcReg);
      if (DstRC != SrcRC && SrcRC)
        MRI.setRegClass(DstReg, SrcRC);
    }
  }
}

// Return true if the type represents a constant register
static bool isConstReg(MachineRegisterInfo *MRI, MachineInstr *OpDef,
                       SmallPtrSet<SPIRVType *, 4> &Visited) {
  OpDef = passCopy(OpDef, MRI);

  if (Visited.contains(OpDef))
    return true;
  Visited.insert(OpDef);

  unsigned Opcode = OpDef->getOpcode();
  switch (Opcode) {
  case TargetOpcode::G_CONSTANT:
  case TargetOpcode::G_FCONSTANT:
    return true;
  case TargetOpcode::G_INTRINSIC:
  case TargetOpcode::G_INTRINSIC_W_SIDE_EFFECTS:
  case TargetOpcode::G_INTRINSIC_CONVERGENT_W_SIDE_EFFECTS:
    return cast<GIntrinsic>(*OpDef).getIntrinsicID() ==
           Intrinsic::spv_const_composite;
  case TargetOpcode::G_BUILD_VECTOR:
  case TargetOpcode::G_SPLAT_VECTOR: {
    for (unsigned i = OpDef->getNumExplicitDefs(); i < OpDef->getNumOperands();
         i++) {
      MachineInstr *OpNestedDef =
          OpDef->getOperand(i).isReg()
              ? MRI->getVRegDef(OpDef->getOperand(i).getReg())
              : nullptr;
      if (OpNestedDef && !isConstReg(MRI, OpNestedDef, Visited))
        return false;
    }
    return true;
  case SPIRV::OpConstantTrue:
  case SPIRV::OpConstantFalse:
  case SPIRV::OpConstantI:
  case SPIRV::OpConstantF:
  case SPIRV::OpConstantComposite:
  case SPIRV::OpConstantCompositeContinuedINTEL:
  case SPIRV::OpConstantSampler:
  case SPIRV::OpConstantNull:
  case SPIRV::OpUndef:
  case SPIRV::OpConstantFunctionPointerINTEL:
    return true;
  }
  }
  return false;
}

// Return true if the virtual register represents a constant
static bool isConstReg(MachineRegisterInfo *MRI, Register OpReg) {
  SmallPtrSet<SPIRVType *, 4> Visited;
  if (MachineInstr *OpDef = MRI->getVRegDef(OpReg))
    return isConstReg(MRI, OpDef, Visited);
  return false;
}

bool isDead(const MachineInstr &MI, const MachineRegisterInfo &MRI) {
  for (const auto &MO : MI.all_defs()) {
    Register Reg = MO.getReg();
    if (Reg.isPhysical() || !MRI.use_nodbg_empty(Reg))
      return false;
  }
  if (MI.getOpcode() == TargetOpcode::LOCAL_ESCAPE || MI.isFakeUse() ||
      MI.isLifetimeMarker())
    return false;
  if (MI.isPHI())
    return true;
  if (MI.mayStore() || MI.isCall() ||
      (MI.mayLoad() && MI.hasOrderedMemoryRef()) || MI.isPosition() ||
      MI.isDebugInstr() || MI.isTerminator() || MI.isJumpTableDebugInfo())
    return false;
  return true;
}

bool SPIRVInstructionSelector::select(MachineInstr &I) {
  resetVRegsType(*I.getParent()->getParent());

  assert(I.getParent() && "Instruction should be in a basic block!");
  assert(I.getParent()->getParent() && "Instruction should be in a function!");

  Register Opcode = I.getOpcode();
  // If it's not a GMIR instruction, we've selected it already.
  if (!isPreISelGenericOpcode(Opcode)) {
    if (Opcode == SPIRV::ASSIGN_TYPE) { // These pseudos aren't needed any more.
      Register DstReg = I.getOperand(0).getReg();
      Register SrcReg = I.getOperand(1).getReg();
      auto *Def = MRI->getVRegDef(SrcReg);
      if (isTypeFoldingSupported(Def->getOpcode()) &&
          Def->getOpcode() != TargetOpcode::G_CONSTANT &&
          Def->getOpcode() != TargetOpcode::G_FCONSTANT) {
        bool Res = false;
        if (Def->getOpcode() == TargetOpcode::G_SELECT) {
          Register SelectDstReg = Def->getOperand(0).getReg();
          Res = selectSelect(SelectDstReg, GR.getSPIRVTypeForVReg(SelectDstReg),
                             *Def);
          GR.invalidateMachineInstr(Def);
          Def->removeFromParent();
          MRI->replaceRegWith(DstReg, SelectDstReg);
          GR.invalidateMachineInstr(&I);
          I.removeFromParent();
        } else
          Res = selectImpl(I, *CoverageInfo);
        LLVM_DEBUG({
          if (!Res && Def->getOpcode() != TargetOpcode::G_CONSTANT) {
            dbgs() << "Unexpected pattern in ASSIGN_TYPE.\nInstruction: ";
            I.print(dbgs());
          }
        });
        assert(Res || Def->getOpcode() == TargetOpcode::G_CONSTANT);
        if (Res) {
          if (!isTriviallyDead(*Def, *MRI) && isDead(*Def, *MRI))
            DeadMIs.insert(Def);
          return Res;
        }
      }
      MRI->setRegClass(SrcReg, MRI->getRegClass(DstReg));
      MRI->replaceRegWith(SrcReg, DstReg);
      GR.invalidateMachineInstr(&I);
      I.removeFromParent();
      return true;
    } else if (I.getNumDefs() == 1) {
      // Make all vregs 64 bits (for SPIR-V IDs).
      MRI->setType(I.getOperand(0).getReg(), LLT::scalar(64));
    }
    return constrainSelectedInstRegOperands(I, TII, TRI, RBI);
  }

  if (DeadMIs.contains(&I)) {
    // if the instruction has been already made dead by folding it away
    // erase it
    LLVM_DEBUG(dbgs() << "Instruction is folded and dead.\n");
    salvageDebugInfo(*MRI, I);
    GR.invalidateMachineInstr(&I);
    I.eraseFromParent();
    return true;
  }

  if (I.getNumOperands() != I.getNumExplicitOperands()) {
    LLVM_DEBUG(errs() << "Generic instr has unexpected implicit operands\n");
    return false;
  }

  // Common code for getting return reg+type, and removing selected instr
  // from parent occurs here. Instr-specific selection happens in spvSelect().
  bool HasDefs = I.getNumDefs() > 0;
  Register ResVReg = HasDefs ? I.getOperand(0).getReg() : Register(0);
  SPIRVType *ResType = HasDefs ? GR.getSPIRVTypeForVReg(ResVReg) : nullptr;
  assert(!HasDefs || ResType || I.getOpcode() == TargetOpcode::G_GLOBAL_VALUE ||
         I.getOpcode() == TargetOpcode::G_IMPLICIT_DEF);
  if (spvSelect(ResVReg, ResType, I)) {
    if (HasDefs) // Make all vregs 64 bits (for SPIR-V IDs).
      for (unsigned i = 0; i < I.getNumDefs(); ++i)
        MRI->setType(I.getOperand(i).getReg(), LLT::scalar(64));
    GR.invalidateMachineInstr(&I);
    I.removeFromParent();
    return true;
  }
  return false;
}

static bool mayApplyGenericSelection(unsigned Opcode) {
  switch (Opcode) {
  case TargetOpcode::G_CONSTANT:
  case TargetOpcode::G_FCONSTANT:
    return false;
  case TargetOpcode::G_SADDO:
  case TargetOpcode::G_SSUBO:
    return true;
  }
  return isTypeFoldingSupported(Opcode);
}

bool SPIRVInstructionSelector::BuildCOPY(Register DestReg, Register SrcReg,
                                         MachineInstr &I) const {
  const TargetRegisterClass *DstRC = MRI->getRegClassOrNull(DestReg);
  const TargetRegisterClass *SrcRC = MRI->getRegClassOrNull(SrcReg);
  if (DstRC != SrcRC && SrcRC)
    MRI->setRegClass(DestReg, SrcRC);
  return BuildMI(*I.getParent(), I, I.getDebugLoc(),
                 TII.get(TargetOpcode::COPY))
      .addDef(DestReg)
      .addUse(SrcReg)
      .constrainAllUses(TII, TRI, RBI);
}

bool SPIRVInstructionSelector::spvSelect(Register ResVReg,
                                         const SPIRVType *ResType,
                                         MachineInstr &I) const {
  const unsigned Opcode = I.getOpcode();
  if (mayApplyGenericSelection(Opcode))
    return selectImpl(I, *CoverageInfo);
  switch (Opcode) {
  case TargetOpcode::G_CONSTANT:
  case TargetOpcode::G_FCONSTANT:
    return selectConst(ResVReg, ResType, I);
  case TargetOpcode::G_GLOBAL_VALUE:
    return selectGlobalValue(ResVReg, I);
  case TargetOpcode::G_IMPLICIT_DEF:
    return selectOpUndef(ResVReg, ResType, I);
  case TargetOpcode::G_FREEZE:
    return selectFreeze(ResVReg, ResType, I);

  case TargetOpcode::G_INTRINSIC:
  case TargetOpcode::G_INTRINSIC_W_SIDE_EFFECTS:
  case TargetOpcode::G_INTRINSIC_CONVERGENT:
  case TargetOpcode::G_INTRINSIC_CONVERGENT_W_SIDE_EFFECTS:
    return selectIntrinsic(ResVReg, ResType, I);
  case TargetOpcode::G_BITREVERSE:
    return selectBitreverse(ResVReg, ResType, I);

  case TargetOpcode::G_BUILD_VECTOR:
    return selectBuildVector(ResVReg, ResType, I);
  case TargetOpcode::G_SPLAT_VECTOR:
    return selectSplatVector(ResVReg, ResType, I);

  case TargetOpcode::G_SHUFFLE_VECTOR: {
    MachineBasicBlock &BB = *I.getParent();
    auto MIB = BuildMI(BB, I, I.getDebugLoc(), TII.get(SPIRV::OpVectorShuffle))
                   .addDef(ResVReg)
                   .addUse(GR.getSPIRVTypeID(ResType))
                   .addUse(I.getOperand(1).getReg())
                   .addUse(I.getOperand(2).getReg());
    for (auto V : I.getOperand(3).getShuffleMask())
      MIB.addImm(V);
    return MIB.constrainAllUses(TII, TRI, RBI);
  }
  case TargetOpcode::G_MEMMOVE:
  case TargetOpcode::G_MEMCPY:
  case TargetOpcode::G_MEMSET:
    return selectMemOperation(ResVReg, I);

  case TargetOpcode::G_ICMP:
    return selectICmp(ResVReg, ResType, I);
  case TargetOpcode::G_FCMP:
    return selectFCmp(ResVReg, ResType, I);

  case TargetOpcode::G_FRAME_INDEX:
    return selectFrameIndex(ResVReg, ResType, I);

  case TargetOpcode::G_LOAD:
    return selectLoad(ResVReg, ResType, I);
  case TargetOpcode::G_STORE:
    return selectStore(I);

  case TargetOpcode::G_BR:
    return selectBranch(I);
  case TargetOpcode::G_BRCOND:
    return selectBranchCond(I);

  case TargetOpcode::G_PHI:
    return selectPhi(ResVReg, ResType, I);

  case TargetOpcode::G_FPTOSI:
    return selectUnOp(ResVReg, ResType, I, SPIRV::OpConvertFToS);
  case TargetOpcode::G_FPTOUI:
    return selectUnOp(ResVReg, ResType, I, SPIRV::OpConvertFToU);

  case TargetOpcode::G_FPTOSI_SAT:
    return selectUnOp(ResVReg, ResType, I, SPIRV::OpConvertFToS);
  case TargetOpcode::G_FPTOUI_SAT:
    return selectUnOp(ResVReg, ResType, I, SPIRV::OpConvertFToU);

  case TargetOpcode::G_SITOFP:
    return selectIToF(ResVReg, ResType, I, true, SPIRV::OpConvertSToF);
  case TargetOpcode::G_UITOFP:
    return selectIToF(ResVReg, ResType, I, false, SPIRV::OpConvertUToF);

  case TargetOpcode::G_CTPOP:
    return selectUnOp(ResVReg, ResType, I, SPIRV::OpBitCount);
  case TargetOpcode::G_SMIN:
    return selectExtInst(ResVReg, ResType, I, CL::s_min, GL::SMin);
  case TargetOpcode::G_UMIN:
    return selectExtInst(ResVReg, ResType, I, CL::u_min, GL::UMin);

  case TargetOpcode::G_SMAX:
    return selectExtInst(ResVReg, ResType, I, CL::s_max, GL::SMax);
  case TargetOpcode::G_UMAX:
    return selectExtInst(ResVReg, ResType, I, CL::u_max, GL::UMax);

  case TargetOpcode::G_SCMP:
    return selectSUCmp(ResVReg, ResType, I, true);
  case TargetOpcode::G_UCMP:
    return selectSUCmp(ResVReg, ResType, I, false);
  case TargetOpcode::G_LROUND:
  case TargetOpcode::G_LLROUND: {
    Register regForLround =
        MRI->createVirtualRegister(MRI->getRegClass(ResVReg), "lround");
    MRI->setRegClass(regForLround, &SPIRV::iIDRegClass);
    GR.assignSPIRVTypeToVReg(GR.getSPIRVTypeForVReg(I.getOperand(1).getReg()),
                             regForLround, *(I.getParent()->getParent()));
    selectExtInstForLRound(regForLround, GR.getSPIRVTypeForVReg(regForLround),
                           I, CL::round, GL::Round);
    MachineBasicBlock &BB = *I.getParent();
    auto MIB = BuildMI(BB, I, I.getDebugLoc(), TII.get(SPIRV::OpConvertFToS))
                   .addDef(ResVReg)
                   .addUse(GR.getSPIRVTypeID(ResType))
                   .addUse(regForLround);
    return MIB.constrainAllUses(TII, TRI, RBI);
  }
  case TargetOpcode::G_STRICT_FMA:
  case TargetOpcode::G_FMA:
    return selectExtInst(ResVReg, ResType, I, CL::fma, GL::Fma);

  case TargetOpcode::G_STRICT_FLDEXP:
    return selectExtInst(ResVReg, ResType, I, CL::ldexp);

  case TargetOpcode::G_FPOW:
    return selectExtInst(ResVReg, ResType, I, CL::pow, GL::Pow);
  case TargetOpcode::G_FPOWI:
    return selectExtInst(ResVReg, ResType, I, CL::pown);

  case TargetOpcode::G_FEXP:
    return selectExtInst(ResVReg, ResType, I, CL::exp, GL::Exp);
  case TargetOpcode::G_FEXP2:
    return selectExtInst(ResVReg, ResType, I, CL::exp2, GL::Exp2);
  case TargetOpcode::G_FMODF:
    return selectModf(ResVReg, ResType, I);

  case TargetOpcode::G_FLOG:
    return selectExtInst(ResVReg, ResType, I, CL::log, GL::Log);
  case TargetOpcode::G_FLOG2:
    return selectExtInst(ResVReg, ResType, I, CL::log2, GL::Log2);
  case TargetOpcode::G_FLOG10:
    return selectLog10(ResVReg, ResType, I);

  case TargetOpcode::G_FABS:
    return selectExtInst(ResVReg, ResType, I, CL::fabs, GL::FAbs);
  case TargetOpcode::G_ABS:
    return selectExtInst(ResVReg, ResType, I, CL::s_abs, GL::SAbs);

  case TargetOpcode::G_FMINNUM:
  case TargetOpcode::G_FMINIMUM:
    return selectExtInst(ResVReg, ResType, I, CL::fmin, GL::NMin);
  case TargetOpcode::G_FMAXNUM:
  case TargetOpcode::G_FMAXIMUM:
    return selectExtInst(ResVReg, ResType, I, CL::fmax, GL::NMax);

  case TargetOpcode::G_FCOPYSIGN:
    return selectExtInst(ResVReg, ResType, I, CL::copysign);

  case TargetOpcode::G_FCEIL:
    return selectExtInst(ResVReg, ResType, I, CL::ceil, GL::Ceil);
  case TargetOpcode::G_FFLOOR:
    return selectExtInst(ResVReg, ResType, I, CL::floor, GL::Floor);

  case TargetOpcode::G_FCOS:
    return selectExtInst(ResVReg, ResType, I, CL::cos, GL::Cos);
  case TargetOpcode::G_FSIN:
    return selectExtInst(ResVReg, ResType, I, CL::sin, GL::Sin);
  case TargetOpcode::G_FTAN:
    return selectExtInst(ResVReg, ResType, I, CL::tan, GL::Tan);
  case TargetOpcode::G_FACOS:
    return selectExtInst(ResVReg, ResType, I, CL::acos, GL::Acos);
  case TargetOpcode::G_FASIN:
    return selectExtInst(ResVReg, ResType, I, CL::asin, GL::Asin);
  case TargetOpcode::G_FATAN:
    return selectExtInst(ResVReg, ResType, I, CL::atan, GL::Atan);
  case TargetOpcode::G_FATAN2:
    return selectExtInst(ResVReg, ResType, I, CL::atan2, GL::Atan2);
  case TargetOpcode::G_FCOSH:
    return selectExtInst(ResVReg, ResType, I, CL::cosh, GL::Cosh);
  case TargetOpcode::G_FSINH:
    return selectExtInst(ResVReg, ResType, I, CL::sinh, GL::Sinh);
  case TargetOpcode::G_FTANH:
    return selectExtInst(ResVReg, ResType, I, CL::tanh, GL::Tanh);

  case TargetOpcode::G_STRICT_FSQRT:
  case TargetOpcode::G_FSQRT:
    return selectExtInst(ResVReg, ResType, I, CL::sqrt, GL::Sqrt);

  case TargetOpcode::G_CTTZ:
  case TargetOpcode::G_CTTZ_ZERO_UNDEF:
    return selectExtInst(ResVReg, ResType, I, CL::ctz);
  case TargetOpcode::G_CTLZ:
  case TargetOpcode::G_CTLZ_ZERO_UNDEF:
    return selectExtInst(ResVReg, ResType, I, CL::clz);

  case TargetOpcode::G_INTRINSIC_ROUND:
    return selectExtInst(ResVReg, ResType, I, CL::round, GL::Round);
  case TargetOpcode::G_INTRINSIC_ROUNDEVEN:
    return selectExtInst(ResVReg, ResType, I, CL::rint, GL::RoundEven);
  case TargetOpcode::G_INTRINSIC_TRUNC:
    return selectExtInst(ResVReg, ResType, I, CL::trunc, GL::Trunc);
  case TargetOpcode::G_FRINT:
  case TargetOpcode::G_FNEARBYINT:
    return selectExtInst(ResVReg, ResType, I, CL::rint, GL::RoundEven);

  case TargetOpcode::G_SMULH:
    return selectExtInst(ResVReg, ResType, I, CL::s_mul_hi);
  case TargetOpcode::G_UMULH:
    return selectExtInst(ResVReg, ResType, I, CL::u_mul_hi);

  case TargetOpcode::G_SADDSAT:
    return selectExtInst(ResVReg, ResType, I, CL::s_add_sat);
  case TargetOpcode::G_UADDSAT:
    return selectExtInst(ResVReg, ResType, I, CL::u_add_sat);
  case TargetOpcode::G_SSUBSAT:
    return selectExtInst(ResVReg, ResType, I, CL::s_sub_sat);
  case TargetOpcode::G_USUBSAT:
    return selectExtInst(ResVReg, ResType, I, CL::u_sub_sat);

  case TargetOpcode::G_FFREXP:
    return selectFrexp(ResVReg, ResType, I);

  case TargetOpcode::G_UADDO:
    return selectOverflowArith(ResVReg, ResType, I,
                               ResType->getOpcode() == SPIRV::OpTypeVector
                                   ? SPIRV::OpIAddCarryV
                                   : SPIRV::OpIAddCarryS);
  case TargetOpcode::G_USUBO:
    return selectOverflowArith(ResVReg, ResType, I,
                               ResType->getOpcode() == SPIRV::OpTypeVector
                                   ? SPIRV::OpISubBorrowV
                                   : SPIRV::OpISubBorrowS);
  case TargetOpcode::G_UMULO:
    return selectOverflowArith(ResVReg, ResType, I, SPIRV::OpUMulExtended);
  case TargetOpcode::G_SMULO:
    return selectOverflowArith(ResVReg, ResType, I, SPIRV::OpSMulExtended);

  case TargetOpcode::G_SEXT:
    return selectExt(ResVReg, ResType, I, true);
  case TargetOpcode::G_ANYEXT:
  case TargetOpcode::G_ZEXT:
    return selectExt(ResVReg, ResType, I, false);
  case TargetOpcode::G_TRUNC:
    return selectTrunc(ResVReg, ResType, I);
  case TargetOpcode::G_FPTRUNC:
  case TargetOpcode::G_FPEXT:
    return selectUnOp(ResVReg, ResType, I, SPIRV::OpFConvert);

  case TargetOpcode::G_PTRTOINT:
    return selectUnOp(ResVReg, ResType, I, SPIRV::OpConvertPtrToU);
  case TargetOpcode::G_INTTOPTR:
    return selectUnOp(ResVReg, ResType, I, SPIRV::OpConvertUToPtr);
  case TargetOpcode::G_BITCAST:
    return selectBitcast(ResVReg, ResType, I);
  case TargetOpcode::G_ADDRSPACE_CAST:
    return selectAddrSpaceCast(ResVReg, ResType, I);
  case TargetOpcode::G_PTR_ADD: {
    // Currently, we get G_PTR_ADD only applied to global variables.
    assert(I.getOperand(1).isReg() && I.getOperand(2).isReg());
    Register GV = I.getOperand(1).getReg();
    MachineRegisterInfo::def_instr_iterator II = MRI->def_instr_begin(GV);
    (void)II;
    assert(((*II).getOpcode() == TargetOpcode::G_GLOBAL_VALUE ||
            (*II).getOpcode() == TargetOpcode::COPY ||
            (*II).getOpcode() == SPIRV::OpVariable) &&
           getImm(I.getOperand(2), MRI));
    // It may be the initialization of a global variable.
    bool IsGVInit = false;
    for (MachineRegisterInfo::use_instr_iterator
             UseIt = MRI->use_instr_begin(I.getOperand(0).getReg()),
             UseEnd = MRI->use_instr_end();
         UseIt != UseEnd; UseIt = std::next(UseIt)) {
      if ((*UseIt).getOpcode() == TargetOpcode::G_GLOBAL_VALUE ||
          (*UseIt).getOpcode() == SPIRV::OpVariable) {
        IsGVInit = true;
        break;
      }
    }
    MachineBasicBlock &BB = *I.getParent();
    if (!IsGVInit) {
      SPIRVType *GVType = GR.getSPIRVTypeForVReg(GV);
      SPIRVType *GVPointeeType = GR.getPointeeType(GVType);
      SPIRVType *ResPointeeType = GR.getPointeeType(ResType);
      if (GVPointeeType && ResPointeeType && GVPointeeType != ResPointeeType) {
        // Build a new virtual register that is associated with the required
        // data type.
        Register NewVReg = MRI->createGenericVirtualRegister(MRI->getType(GV));
        MRI->setRegClass(NewVReg, MRI->getRegClass(GV));
        //  Having a correctly typed base we are ready to build the actually
        //  required GEP. It may not be a constant though, because all Operands
        //  of OpSpecConstantOp is to originate from other const instructions,
        //  and only the AccessChain named opcodes accept a global OpVariable
        //  instruction. We can't use an AccessChain opcode because of the type
        //  mismatch between result and base types.
        if (!GR.isBitcastCompatible(ResType, GVType))
          report_fatal_error(
              "incompatible result and operand types in a bitcast");
        Register ResTypeReg = GR.getSPIRVTypeID(ResType);
        MachineInstrBuilder MIB =
            BuildMI(BB, I, I.getDebugLoc(), TII.get(SPIRV::OpBitcast))
                .addDef(NewVReg)
                .addUse(ResTypeReg)
                .addUse(GV);
        return MIB.constrainAllUses(TII, TRI, RBI) &&
               BuildMI(BB, I, I.getDebugLoc(),
                       TII.get(STI.isLogicalSPIRV()
                                   ? SPIRV::OpInBoundsAccessChain
                                   : SPIRV::OpInBoundsPtrAccessChain))
                   .addDef(ResVReg)
                   .addUse(ResTypeReg)
                   .addUse(NewVReg)
                   .addUse(I.getOperand(2).getReg())
                   .constrainAllUses(TII, TRI, RBI);
      } else {
        return BuildMI(BB, I, I.getDebugLoc(), TII.get(SPIRV::OpSpecConstantOp))
            .addDef(ResVReg)
            .addUse(GR.getSPIRVTypeID(ResType))
            .addImm(
                static_cast<uint32_t>(SPIRV::Opcode::InBoundsPtrAccessChain))
            .addUse(GV)
            .addUse(I.getOperand(2).getReg())
            .constrainAllUses(TII, TRI, RBI);
      }
    }
    // It's possible to translate G_PTR_ADD to OpSpecConstantOp: either to
    // initialize a global variable with a constant expression (e.g., the test
    // case opencl/basic/progvar_prog_scope_init.ll), or for another use case
    Register Idx = buildZerosVal(GR.getOrCreateSPIRVIntegerType(32, I, TII), I);
    auto MIB = BuildMI(BB, I, I.getDebugLoc(), TII.get(SPIRV::OpSpecConstantOp))
                   .addDef(ResVReg)
                   .addUse(GR.getSPIRVTypeID(ResType))
                   .addImm(static_cast<uint32_t>(
                       SPIRV::Opcode::InBoundsPtrAccessChain))
                   .addUse(GV)
                   .addUse(Idx)
                   .addUse(I.getOperand(2).getReg());
    return MIB.constrainAllUses(TII, TRI, RBI);
  }

  case TargetOpcode::G_ATOMICRMW_OR:
    return selectAtomicRMW(ResVReg, ResType, I, SPIRV::OpAtomicOr);
  case TargetOpcode::G_ATOMICRMW_ADD:
    return selectAtomicRMW(ResVReg, ResType, I, SPIRV::OpAtomicIAdd);
  case TargetOpcode::G_ATOMICRMW_AND:
    return selectAtomicRMW(ResVReg, ResType, I, SPIRV::OpAtomicAnd);
  case TargetOpcode::G_ATOMICRMW_MAX:
    return selectAtomicRMW(ResVReg, ResType, I, SPIRV::OpAtomicSMax);
  case TargetOpcode::G_ATOMICRMW_MIN:
    return selectAtomicRMW(ResVReg, ResType, I, SPIRV::OpAtomicSMin);
  case TargetOpcode::G_ATOMICRMW_SUB:
    return selectAtomicRMW(ResVReg, ResType, I, SPIRV::OpAtomicISub);
  case TargetOpcode::G_ATOMICRMW_XOR:
    return selectAtomicRMW(ResVReg, ResType, I, SPIRV::OpAtomicXor);
  case TargetOpcode::G_ATOMICRMW_UMAX:
    return selectAtomicRMW(ResVReg, ResType, I, SPIRV::OpAtomicUMax);
  case TargetOpcode::G_ATOMICRMW_UMIN:
    return selectAtomicRMW(ResVReg, ResType, I, SPIRV::OpAtomicUMin);
  case TargetOpcode::G_ATOMICRMW_XCHG:
    return selectAtomicRMW(ResVReg, ResType, I, SPIRV::OpAtomicExchange);
  case TargetOpcode::G_ATOMIC_CMPXCHG:
    return selectAtomicCmpXchg(ResVReg, ResType, I);

  case TargetOpcode::G_ATOMICRMW_FADD:
    return selectAtomicRMW(ResVReg, ResType, I, SPIRV::OpAtomicFAddEXT);
  case TargetOpcode::G_ATOMICRMW_FSUB:
    // Translate G_ATOMICRMW_FSUB to OpAtomicFAddEXT with negative value operand
    return selectAtomicRMW(ResVReg, ResType, I, SPIRV::OpAtomicFAddEXT,
                           SPIRV::OpFNegate);
  case TargetOpcode::G_ATOMICRMW_FMIN:
    return selectAtomicRMW(ResVReg, ResType, I, SPIRV::OpAtomicFMinEXT);
  case TargetOpcode::G_ATOMICRMW_FMAX:
    return selectAtomicRMW(ResVReg, ResType, I, SPIRV::OpAtomicFMaxEXT);

  case TargetOpcode::G_FENCE:
    return selectFence(I);

  case TargetOpcode::G_STACKSAVE:
    return selectStackSave(ResVReg, ResType, I);
  case TargetOpcode::G_STACKRESTORE:
    return selectStackRestore(I);

  case TargetOpcode::G_UNMERGE_VALUES:
    return selectUnmergeValues(I);

  // Discard gen opcodes for intrinsics which we do not expect to actually
  // represent code after lowering or intrinsics which are not implemented but
  // should not crash when found in a customer's LLVM IR input.
  case TargetOpcode::G_TRAP:
  case TargetOpcode::G_UBSANTRAP:
  case TargetOpcode::DBG_LABEL:
    return true;
  case TargetOpcode::G_DEBUGTRAP:
    return selectDebugTrap(ResVReg, ResType, I);

  default:
    return false;
  }
}

bool SPIRVInstructionSelector::selectDebugTrap(Register ResVReg,
                                               const SPIRVType *ResType,
                                               MachineInstr &I) const {
  unsigned Opcode = SPIRV::OpNop;
  MachineBasicBlock &BB = *I.getParent();
  return BuildMI(BB, I, I.getDebugLoc(), TII.get(Opcode))
      .constrainAllUses(TII, TRI, RBI);
}

bool SPIRVInstructionSelector::selectExtInst(Register ResVReg,
                                             const SPIRVType *ResType,
                                             MachineInstr &I,
                                             GL::GLSLExtInst GLInst) const {
  if (!STI.canUseExtInstSet(
          SPIRV::InstructionSet::InstructionSet::GLSL_std_450)) {
    std::string DiagMsg;
    raw_string_ostream OS(DiagMsg);
    I.print(OS, true, false, false, false);
    DiagMsg += " is only supported with the GLSL extended instruction set.\n";
    report_fatal_error(DiagMsg.c_str(), false);
  }
  return selectExtInst(ResVReg, ResType, I,
                       {{SPIRV::InstructionSet::GLSL_std_450, GLInst}});
}

bool SPIRVInstructionSelector::selectExtInst(Register ResVReg,
                                             const SPIRVType *ResType,
                                             MachineInstr &I,
                                             CL::OpenCLExtInst CLInst) const {
  return selectExtInst(ResVReg, ResType, I,
                       {{SPIRV::InstructionSet::OpenCL_std, CLInst}});
}

bool SPIRVInstructionSelector::selectExtInst(Register ResVReg,
                                             const SPIRVType *ResType,
                                             MachineInstr &I,
                                             CL::OpenCLExtInst CLInst,
                                             GL::GLSLExtInst GLInst) const {
  ExtInstList ExtInsts = {{SPIRV::InstructionSet::OpenCL_std, CLInst},
                          {SPIRV::InstructionSet::GLSL_std_450, GLInst}};
  return selectExtInst(ResVReg, ResType, I, ExtInsts);
}

bool SPIRVInstructionSelector::selectExtInst(Register ResVReg,
                                             const SPIRVType *ResType,
                                             MachineInstr &I,
                                             const ExtInstList &Insts) const {

  for (const auto &Ex : Insts) {
    SPIRV::InstructionSet::InstructionSet Set = Ex.first;
    uint32_t Opcode = Ex.second;
    if (STI.canUseExtInstSet(Set)) {
      MachineBasicBlock &BB = *I.getParent();
      auto MIB = BuildMI(BB, I, I.getDebugLoc(), TII.get(SPIRV::OpExtInst))
                     .addDef(ResVReg)
                     .addUse(GR.getSPIRVTypeID(ResType))
                     .addImm(static_cast<uint32_t>(Set))
                     .addImm(Opcode)
                     .setMIFlags(I.getFlags());
      const unsigned NumOps = I.getNumOperands();
      unsigned Index = 1;
      if (Index < NumOps &&
          I.getOperand(Index).getType() ==
              MachineOperand::MachineOperandType::MO_IntrinsicID)
        Index = 2;
      for (; Index < NumOps; ++Index)
        MIB.add(I.getOperand(Index));
      return MIB.constrainAllUses(TII, TRI, RBI);
    }
  }
  return false;
}
bool SPIRVInstructionSelector::selectExtInstForLRound(
    Register ResVReg, const SPIRVType *ResType, MachineInstr &I,
    CL::OpenCLExtInst CLInst, GL::GLSLExtInst GLInst) const {
  ExtInstList ExtInsts = {{SPIRV::InstructionSet::OpenCL_std, CLInst},
                          {SPIRV::InstructionSet::GLSL_std_450, GLInst}};
  return selectExtInstForLRound(ResVReg, ResType, I, ExtInsts);
}

bool SPIRVInstructionSelector::selectExtInstForLRound(
    Register ResVReg, const SPIRVType *ResType, MachineInstr &I,
    const ExtInstList &Insts) const {
  for (const auto &Ex : Insts) {
    SPIRV::InstructionSet::InstructionSet Set = Ex.first;
    uint32_t Opcode = Ex.second;
    if (STI.canUseExtInstSet(Set)) {
      MachineBasicBlock &BB = *I.getParent();
      auto MIB = BuildMI(BB, I, I.getDebugLoc(), TII.get(SPIRV::OpExtInst))
                     .addDef(ResVReg)
                     .addUse(GR.getSPIRVTypeID(ResType))
                     .addImm(static_cast<uint32_t>(Set))
                     .addImm(Opcode);
      const unsigned NumOps = I.getNumOperands();
      unsigned Index = 1;
      if (Index < NumOps &&
          I.getOperand(Index).getType() ==
              MachineOperand::MachineOperandType::MO_IntrinsicID)
        Index = 2;
      for (; Index < NumOps; ++Index)
        MIB.add(I.getOperand(Index));
      MIB.constrainAllUses(TII, TRI, RBI);
      return true;
    }
  }
  return false;
}

bool SPIRVInstructionSelector::selectFrexp(Register ResVReg,
                                           const SPIRVType *ResType,
                                           MachineInstr &I) const {
  ExtInstList ExtInsts = {{SPIRV::InstructionSet::OpenCL_std, CL::frexp},
                          {SPIRV::InstructionSet::GLSL_std_450, GL::Frexp}};
  for (const auto &Ex : ExtInsts) {
    SPIRV::InstructionSet::InstructionSet Set = Ex.first;
    uint32_t Opcode = Ex.second;
    if (!STI.canUseExtInstSet(Set))
      continue;

    MachineIRBuilder MIRBuilder(I);
    SPIRVType *PointeeTy = GR.getSPIRVTypeForVReg(I.getOperand(1).getReg());
    const SPIRVType *PointerType = GR.getOrCreateSPIRVPointerType(
        PointeeTy, MIRBuilder, SPIRV::StorageClass::Function);
    Register PointerVReg =
        createVirtualRegister(PointerType, &GR, MRI, MRI->getMF());

    auto It = getOpVariableMBBIt(I);
    auto MIB = BuildMI(*It->getParent(), It, It->getDebugLoc(),
                       TII.get(SPIRV::OpVariable))
                   .addDef(PointerVReg)
                   .addUse(GR.getSPIRVTypeID(PointerType))
                   .addImm(static_cast<uint32_t>(SPIRV::StorageClass::Function))
                   .constrainAllUses(TII, TRI, RBI);

    MIB = MIB &
          BuildMI(*I.getParent(), I, I.getDebugLoc(), TII.get(SPIRV::OpExtInst))
              .addDef(ResVReg)
              .addUse(GR.getSPIRVTypeID(ResType))
              .addImm(static_cast<uint32_t>(Ex.first))
              .addImm(Opcode)
              .add(I.getOperand(2))
              .addUse(PointerVReg)
              .constrainAllUses(TII, TRI, RBI);

    MIB = MIB &
          BuildMI(*I.getParent(), I, I.getDebugLoc(), TII.get(SPIRV::OpLoad))
              .addDef(I.getOperand(1).getReg())
              .addUse(GR.getSPIRVTypeID(PointeeTy))
              .addUse(PointerVReg)
              .constrainAllUses(TII, TRI, RBI);
    return MIB;
  }
  return false;
}

bool SPIRVInstructionSelector::selectOpWithSrcs(Register ResVReg,
                                                const SPIRVType *ResType,
                                                MachineInstr &I,
                                                std::vector<Register> Srcs,
                                                unsigned Opcode) const {
  auto MIB = BuildMI(*I.getParent(), I, I.getDebugLoc(), TII.get(Opcode))
                 .addDef(ResVReg)
                 .addUse(GR.getSPIRVTypeID(ResType));
  for (Register SReg : Srcs) {
    MIB.addUse(SReg);
  }
  return MIB.constrainAllUses(TII, TRI, RBI);
}

bool SPIRVInstructionSelector::selectUnOp(Register ResVReg,
                                          const SPIRVType *ResType,
                                          MachineInstr &I,
                                          unsigned Opcode) const {
  if (STI.isPhysicalSPIRV() && I.getOperand(1).isReg()) {
    Register SrcReg = I.getOperand(1).getReg();
    bool IsGV = false;
    for (MachineRegisterInfo::def_instr_iterator DefIt =
             MRI->def_instr_begin(SrcReg);
         DefIt != MRI->def_instr_end(); DefIt = std::next(DefIt)) {
      if ((*DefIt).getOpcode() == TargetOpcode::G_GLOBAL_VALUE ||
          (*DefIt).getOpcode() == SPIRV::OpVariable) {
        IsGV = true;
        break;
      }
    }
    if (IsGV) {
      uint32_t SpecOpcode = 0;
      switch (Opcode) {
      case SPIRV::OpConvertPtrToU:
        SpecOpcode = static_cast<uint32_t>(SPIRV::Opcode::ConvertPtrToU);
        break;
      case SPIRV::OpConvertUToPtr:
        SpecOpcode = static_cast<uint32_t>(SPIRV::Opcode::ConvertUToPtr);
        break;
      }
      if (SpecOpcode)
        return BuildMI(*I.getParent(), I, I.getDebugLoc(),
                       TII.get(SPIRV::OpSpecConstantOp))
            .addDef(ResVReg)
            .addUse(GR.getSPIRVTypeID(ResType))
            .addImm(SpecOpcode)
            .addUse(SrcReg)
            .constrainAllUses(TII, TRI, RBI);
    }
  }
  return selectOpWithSrcs(ResVReg, ResType, I, {I.getOperand(1).getReg()},
                          Opcode);
}

bool SPIRVInstructionSelector::selectBitcast(Register ResVReg,
                                             const SPIRVType *ResType,
                                             MachineInstr &I) const {
  Register OpReg = I.getOperand(1).getReg();
  SPIRVType *OpType = OpReg.isValid() ? GR.getSPIRVTypeForVReg(OpReg) : nullptr;
  if (!GR.isBitcastCompatible(ResType, OpType))
    report_fatal_error("incompatible result and operand types in a bitcast");
  return selectUnOp(ResVReg, ResType, I, SPIRV::OpBitcast);
}

static void addMemoryOperands(MachineMemOperand *MemOp,
                              MachineInstrBuilder &MIB,
                              MachineIRBuilder &MIRBuilder,
                              SPIRVGlobalRegistry &GR) {
  uint32_t SpvMemOp = static_cast<uint32_t>(SPIRV::MemoryOperand::None);
  if (MemOp->isVolatile())
    SpvMemOp |= static_cast<uint32_t>(SPIRV::MemoryOperand::Volatile);
  if (MemOp->isNonTemporal())
    SpvMemOp |= static_cast<uint32_t>(SPIRV::MemoryOperand::Nontemporal);
  if (MemOp->getAlign().value())
    SpvMemOp |= static_cast<uint32_t>(SPIRV::MemoryOperand::Aligned);

  [[maybe_unused]] MachineInstr *AliasList = nullptr;
  [[maybe_unused]] MachineInstr *NoAliasList = nullptr;
  const SPIRVSubtarget *ST =
      static_cast<const SPIRVSubtarget *>(&MIRBuilder.getMF().getSubtarget());
  if (ST->canUseExtension(SPIRV::Extension::SPV_INTEL_memory_access_aliasing)) {
    if (auto *MD = MemOp->getAAInfo().Scope) {
      AliasList = GR.getOrAddMemAliasingINTELInst(MIRBuilder, MD);
      if (AliasList)
        SpvMemOp |=
            static_cast<uint32_t>(SPIRV::MemoryOperand::AliasScopeINTELMask);
    }
    if (auto *MD = MemOp->getAAInfo().NoAlias) {
      NoAliasList = GR.getOrAddMemAliasingINTELInst(MIRBuilder, MD);
      if (NoAliasList)
        SpvMemOp |=
            static_cast<uint32_t>(SPIRV::MemoryOperand::NoAliasINTELMask);
    }
  }

  if (SpvMemOp != static_cast<uint32_t>(SPIRV::MemoryOperand::None)) {
    MIB.addImm(SpvMemOp);
    if (SpvMemOp & static_cast<uint32_t>(SPIRV::MemoryOperand::Aligned))
      MIB.addImm(MemOp->getAlign().value());
    if (AliasList)
      MIB.addUse(AliasList->getOperand(0).getReg());
    if (NoAliasList)
      MIB.addUse(NoAliasList->getOperand(0).getReg());
  }
}

static void addMemoryOperands(uint64_t Flags, MachineInstrBuilder &MIB) {
  uint32_t SpvMemOp = static_cast<uint32_t>(SPIRV::MemoryOperand::None);
  if (Flags & MachineMemOperand::Flags::MOVolatile)
    SpvMemOp |= static_cast<uint32_t>(SPIRV::MemoryOperand::Volatile);
  if (Flags & MachineMemOperand::Flags::MONonTemporal)
    SpvMemOp |= static_cast<uint32_t>(SPIRV::MemoryOperand::Nontemporal);

  if (SpvMemOp != static_cast<uint32_t>(SPIRV::MemoryOperand::None))
    MIB.addImm(SpvMemOp);
}

bool SPIRVInstructionSelector::selectLoad(Register ResVReg,
                                          const SPIRVType *ResType,
                                          MachineInstr &I) const {
  unsigned OpOffset = isa<GIntrinsic>(I) ? 1 : 0;
  Register Ptr = I.getOperand(1 + OpOffset).getReg();

  auto *PtrDef = getVRegDef(*MRI, Ptr);
  auto *IntPtrDef = dyn_cast<GIntrinsic>(PtrDef);
  if (IntPtrDef &&
      IntPtrDef->getIntrinsicID() == Intrinsic::spv_resource_getpointer) {
    Register HandleReg = IntPtrDef->getOperand(2).getReg();
    SPIRVType *HandleType = GR.getSPIRVTypeForVReg(HandleReg);
    if (HandleType->getOpcode() == SPIRV::OpTypeImage) {
      Register NewHandleReg =
          MRI->createVirtualRegister(MRI->getRegClass(HandleReg));
      auto *HandleDef = cast<GIntrinsic>(getVRegDef(*MRI, HandleReg));
      if (!loadHandleBeforePosition(NewHandleReg, HandleType, *HandleDef, I)) {
        return false;
      }

      Register IdxReg = IntPtrDef->getOperand(3).getReg();
      return generateImageRead(ResVReg, ResType, NewHandleReg, IdxReg,
                               I.getDebugLoc(), I);
    }
  }

  auto MIB = BuildMI(*I.getParent(), I, I.getDebugLoc(), TII.get(SPIRV::OpLoad))
                 .addDef(ResVReg)
                 .addUse(GR.getSPIRVTypeID(ResType))
                 .addUse(Ptr);
  if (!I.getNumMemOperands()) {
    assert(I.getOpcode() == TargetOpcode::G_INTRINSIC_W_SIDE_EFFECTS ||
           I.getOpcode() ==
               TargetOpcode::G_INTRINSIC_CONVERGENT_W_SIDE_EFFECTS);
    addMemoryOperands(I.getOperand(2 + OpOffset).getImm(), MIB);
  } else {
    MachineIRBuilder MIRBuilder(I);
    addMemoryOperands(*I.memoperands_begin(), MIB, MIRBuilder, GR);
  }
  return MIB.constrainAllUses(TII, TRI, RBI);
}

bool SPIRVInstructionSelector::selectStore(MachineInstr &I) const {
  unsigned OpOffset = isa<GIntrinsic>(I) ? 1 : 0;
  Register StoreVal = I.getOperand(0 + OpOffset).getReg();
  Register Ptr = I.getOperand(1 + OpOffset).getReg();

  auto *PtrDef = getVRegDef(*MRI, Ptr);
  auto *IntPtrDef = dyn_cast<GIntrinsic>(PtrDef);
  if (IntPtrDef &&
      IntPtrDef->getIntrinsicID() == Intrinsic::spv_resource_getpointer) {
    Register HandleReg = IntPtrDef->getOperand(2).getReg();
    Register NewHandleReg =
        MRI->createVirtualRegister(MRI->getRegClass(HandleReg));
    auto *HandleDef = cast<GIntrinsic>(getVRegDef(*MRI, HandleReg));
    SPIRVType *HandleType = GR.getSPIRVTypeForVReg(HandleReg);
    if (!loadHandleBeforePosition(NewHandleReg, HandleType, *HandleDef, I)) {
      return false;
    }

    Register IdxReg = IntPtrDef->getOperand(3).getReg();
    if (HandleType->getOpcode() == SPIRV::OpTypeImage) {
      auto BMI = BuildMI(*I.getParent(), I, I.getDebugLoc(),
                         TII.get(SPIRV::OpImageWrite))
                     .addUse(NewHandleReg)
                     .addUse(IdxReg)
                     .addUse(StoreVal);

      const llvm::Type *LLVMHandleType = GR.getTypeForSPIRVType(HandleType);
      if (sampledTypeIsSignedInteger(LLVMHandleType))
        BMI.addImm(0x1000); // SignExtend

      return BMI.constrainAllUses(TII, TRI, RBI);
    }
  }

  MachineBasicBlock &BB = *I.getParent();
  auto MIB = BuildMI(BB, I, I.getDebugLoc(), TII.get(SPIRV::OpStore))
                 .addUse(Ptr)
                 .addUse(StoreVal);
  if (!I.getNumMemOperands()) {
    assert(I.getOpcode() == TargetOpcode::G_INTRINSIC_W_SIDE_EFFECTS ||
           I.getOpcode() ==
               TargetOpcode::G_INTRINSIC_CONVERGENT_W_SIDE_EFFECTS);
    addMemoryOperands(I.getOperand(2 + OpOffset).getImm(), MIB);
  } else {
    MachineIRBuilder MIRBuilder(I);
    addMemoryOperands(*I.memoperands_begin(), MIB, MIRBuilder, GR);
  }
  return MIB.constrainAllUses(TII, TRI, RBI);
}

bool SPIRVInstructionSelector::selectStackSave(Register ResVReg,
                                               const SPIRVType *ResType,
                                               MachineInstr &I) const {
  if (!STI.canUseExtension(SPIRV::Extension::SPV_INTEL_variable_length_array))
    report_fatal_error(
        "llvm.stacksave intrinsic: this instruction requires the following "
        "SPIR-V extension: SPV_INTEL_variable_length_array",
        false);
  MachineBasicBlock &BB = *I.getParent();
  return BuildMI(BB, I, I.getDebugLoc(), TII.get(SPIRV::OpSaveMemoryINTEL))
      .addDef(ResVReg)
      .addUse(GR.getSPIRVTypeID(ResType))
      .constrainAllUses(TII, TRI, RBI);
}

bool SPIRVInstructionSelector::selectStackRestore(MachineInstr &I) const {
  if (!STI.canUseExtension(SPIRV::Extension::SPV_INTEL_variable_length_array))
    report_fatal_error(
        "llvm.stackrestore intrinsic: this instruction requires the following "
        "SPIR-V extension: SPV_INTEL_variable_length_array",
        false);
  if (!I.getOperand(0).isReg())
    return false;
  MachineBasicBlock &BB = *I.getParent();
  return BuildMI(BB, I, I.getDebugLoc(), TII.get(SPIRV::OpRestoreMemoryINTEL))
      .addUse(I.getOperand(0).getReg())
      .constrainAllUses(TII, TRI, RBI);
}

bool SPIRVInstructionSelector::selectMemOperation(Register ResVReg,
                                                  MachineInstr &I) const {
  MachineBasicBlock &BB = *I.getParent();
  Register SrcReg = I.getOperand(1).getReg();
  bool Result = true;
  if (I.getOpcode() == TargetOpcode::G_MEMSET) {
    MachineIRBuilder MIRBuilder(I);
    assert(I.getOperand(1).isReg() && I.getOperand(2).isReg());
    unsigned Val = getIConstVal(I.getOperand(1).getReg(), MRI);
    unsigned Num = getIConstVal(I.getOperand(2).getReg(), MRI);
    Type *ValTy = Type::getInt8Ty(I.getMF()->getFunction().getContext());
    Type *ArrTy = ArrayType::get(ValTy, Num);
    SPIRVType *VarTy = GR.getOrCreateSPIRVPointerType(
        ArrTy, MIRBuilder, SPIRV::StorageClass::UniformConstant);

    SPIRVType *SpvArrTy = GR.getOrCreateSPIRVType(
        ArrTy, MIRBuilder, SPIRV::AccessQualifier::None, false);
    Register Const = GR.getOrCreateConstIntArray(Val, Num, I, SpvArrTy, TII);
    // TODO: check if we have such GV, add init, use buildGlobalVariable.
    Function &CurFunction = GR.CurMF->getFunction();
    Type *LLVMArrTy =
        ArrayType::get(IntegerType::get(CurFunction.getContext(), 8), Num);
    // Module takes ownership of the global var.
    GlobalVariable *GV = new GlobalVariable(*CurFunction.getParent(), LLVMArrTy,
                                            true, GlobalValue::InternalLinkage,
                                            Constant::getNullValue(LLVMArrTy));
    Register VarReg = MRI->createGenericVirtualRegister(LLT::scalar(64));
    auto MIBVar =
        BuildMI(*I.getParent(), I, I.getDebugLoc(), TII.get(SPIRV::OpVariable))
            .addDef(VarReg)
            .addUse(GR.getSPIRVTypeID(VarTy))
            .addImm(SPIRV::StorageClass::UniformConstant)
            .addUse(Const);
    Result &= MIBVar.constrainAllUses(TII, TRI, RBI);

    GR.add(GV, MIBVar);
    GR.addGlobalObject(GV, GR.CurMF, VarReg);

    buildOpDecorate(VarReg, I, TII, SPIRV::Decoration::Constant, {});
    SPIRVType *SourceTy = GR.getOrCreateSPIRVPointerType(
        ValTy, I, SPIRV::StorageClass::UniformConstant);
    SrcReg = MRI->createGenericVirtualRegister(LLT::scalar(64));
    selectOpWithSrcs(SrcReg, SourceTy, I, {VarReg}, SPIRV::OpBitcast);
  }
  auto MIB = BuildMI(BB, I, I.getDebugLoc(), TII.get(SPIRV::OpCopyMemorySized))
                 .addUse(I.getOperand(0).getReg())
                 .addUse(SrcReg)
                 .addUse(I.getOperand(2).getReg());
  if (I.getNumMemOperands()) {
    MachineIRBuilder MIRBuilder(I);
    addMemoryOperands(*I.memoperands_begin(), MIB, MIRBuilder, GR);
  }
  Result &= MIB.constrainAllUses(TII, TRI, RBI);
  if (ResVReg.isValid() && ResVReg != MIB->getOperand(0).getReg())
    Result &= BuildCOPY(ResVReg, MIB->getOperand(0).getReg(), I);
  return Result;
}

bool SPIRVInstructionSelector::selectAtomicRMW(Register ResVReg,
                                               const SPIRVType *ResType,
                                               MachineInstr &I,
                                               unsigned NewOpcode,
                                               unsigned NegateOpcode) const {
  bool Result = true;
  assert(I.hasOneMemOperand());
  const MachineMemOperand *MemOp = *I.memoperands_begin();
  uint32_t Scope = static_cast<uint32_t>(getMemScope(
      GR.CurMF->getFunction().getContext(), MemOp->getSyncScopeID()));
  auto ScopeConstant = buildI32Constant(Scope, I);
  Register ScopeReg = ScopeConstant.first;
  Result &= ScopeConstant.second;

  Register Ptr = I.getOperand(1).getReg();
  // TODO: Changed as it's implemented in the translator. See test/atomicrmw.ll
  // auto ScSem =
  // getMemSemanticsForStorageClass(GR.getPointerStorageClass(Ptr));
  AtomicOrdering AO = MemOp->getSuccessOrdering();
  uint32_t MemSem = static_cast<uint32_t>(getMemSemantics(AO));
  auto MemSemConstant = buildI32Constant(MemSem /*| ScSem*/, I);
  Register MemSemReg = MemSemConstant.first;
  Result &= MemSemConstant.second;

  Register ValueReg = I.getOperand(2).getReg();
  if (NegateOpcode != 0) {
    // Translation with negative value operand is requested
    Register TmpReg = createVirtualRegister(ResType, &GR, MRI, MRI->getMF());
    Result &= selectOpWithSrcs(TmpReg, ResType, I, {ValueReg}, NegateOpcode);
    ValueReg = TmpReg;
  }

  return Result &&
         BuildMI(*I.getParent(), I, I.getDebugLoc(), TII.get(NewOpcode))
             .addDef(ResVReg)
             .addUse(GR.getSPIRVTypeID(ResType))
             .addUse(Ptr)
             .addUse(ScopeReg)
             .addUse(MemSemReg)
             .addUse(ValueReg)
             .constrainAllUses(TII, TRI, RBI);
}

bool SPIRVInstructionSelector::selectUnmergeValues(MachineInstr &I) const {
  unsigned ArgI = I.getNumOperands() - 1;
  Register SrcReg =
      I.getOperand(ArgI).isReg() ? I.getOperand(ArgI).getReg() : Register(0);
  SPIRVType *DefType =
      SrcReg.isValid() ? GR.getSPIRVTypeForVReg(SrcReg) : nullptr;
  if (!DefType || DefType->getOpcode() != SPIRV::OpTypeVector)
    report_fatal_error(
        "cannot select G_UNMERGE_VALUES with a non-vector argument");

  SPIRVType *ScalarType =
      GR.getSPIRVTypeForVReg(DefType->getOperand(1).getReg());
  MachineBasicBlock &BB = *I.getParent();
  bool Res = false;
  for (unsigned i = 0; i < I.getNumDefs(); ++i) {
    Register ResVReg = I.getOperand(i).getReg();
    SPIRVType *ResType = GR.getSPIRVTypeForVReg(ResVReg);
    if (!ResType) {
      // There was no "assign type" actions, let's fix this now
      ResType = ScalarType;
      MRI->setRegClass(ResVReg, GR.getRegClass(ResType));
      MRI->setType(ResVReg, LLT::scalar(GR.getScalarOrVectorBitWidth(ResType)));
      GR.assignSPIRVTypeToVReg(ResType, ResVReg, *GR.CurMF);
    }
    auto MIB =
        BuildMI(BB, I, I.getDebugLoc(), TII.get(SPIRV::OpCompositeExtract))
            .addDef(ResVReg)
            .addUse(GR.getSPIRVTypeID(ResType))
            .addUse(SrcReg)
            .addImm(static_cast<int64_t>(i));
    Res |= MIB.constrainAllUses(TII, TRI, RBI);
  }
  return Res;
}

bool SPIRVInstructionSelector::selectFence(MachineInstr &I) const {
  AtomicOrdering AO = AtomicOrdering(I.getOperand(0).getImm());
  uint32_t MemSem = static_cast<uint32_t>(getMemSemantics(AO));
  auto MemSemConstant = buildI32Constant(MemSem, I);
  Register MemSemReg = MemSemConstant.first;
  bool Result = MemSemConstant.second;
  SyncScope::ID Ord = SyncScope::ID(I.getOperand(1).getImm());
  uint32_t Scope = static_cast<uint32_t>(
      getMemScope(GR.CurMF->getFunction().getContext(), Ord));
  auto ScopeConstant = buildI32Constant(Scope, I);
  Register ScopeReg = ScopeConstant.first;
  Result &= ScopeConstant.second;
  MachineBasicBlock &BB = *I.getParent();
  return Result &&
         BuildMI(BB, I, I.getDebugLoc(), TII.get(SPIRV::OpMemoryBarrier))
             .addUse(ScopeReg)
             .addUse(MemSemReg)
             .constrainAllUses(TII, TRI, RBI);
}

bool SPIRVInstructionSelector::selectOverflowArith(Register ResVReg,
                                                   const SPIRVType *ResType,
                                                   MachineInstr &I,
                                                   unsigned Opcode) const {
  Type *ResTy = nullptr;
  StringRef ResName;
  if (!GR.findValueAttrs(&I, ResTy, ResName))
    report_fatal_error(
        "Not enough info to select the arithmetic with overflow instruction");
  if (!ResTy || !ResTy->isStructTy())
    report_fatal_error("Expect struct type result for the arithmetic "
                       "with overflow instruction");
  // "Result Type must be from OpTypeStruct. The struct must have two members,
  // and the two members must be the same type."
  Type *ResElemTy = cast<StructType>(ResTy)->getElementType(0);
  ResTy = StructType::get(ResElemTy, ResElemTy);
  // Build SPIR-V types and constant(s) if needed.
  MachineIRBuilder MIRBuilder(I);
  SPIRVType *StructType = GR.getOrCreateSPIRVType(
      ResTy, MIRBuilder, SPIRV::AccessQualifier::ReadWrite, false);
  assert(I.getNumDefs() > 1 && "Not enought operands");
  SPIRVType *BoolType = GR.getOrCreateSPIRVBoolType(I, TII);
  unsigned N = GR.getScalarOrVectorComponentCount(ResType);
  if (N > 1)
    BoolType = GR.getOrCreateSPIRVVectorType(BoolType, N, I, TII);
  Register BoolTypeReg = GR.getSPIRVTypeID(BoolType);
  Register ZeroReg = buildZerosVal(ResType, I);
  // A new virtual register to store the result struct.
  Register StructVReg = MRI->createGenericVirtualRegister(LLT::scalar(64));
  MRI->setRegClass(StructVReg, &SPIRV::IDRegClass);
  // Build the result name if needed.
  if (ResName.size() > 0)
    buildOpName(StructVReg, ResName, MIRBuilder);
  // Build the arithmetic with overflow instruction.
  MachineBasicBlock &BB = *I.getParent();
  auto MIB =
      BuildMI(BB, MIRBuilder.getInsertPt(), I.getDebugLoc(), TII.get(Opcode))
          .addDef(StructVReg)
          .addUse(GR.getSPIRVTypeID(StructType));
  for (unsigned i = I.getNumDefs(); i < I.getNumOperands(); ++i)
    MIB.addUse(I.getOperand(i).getReg());
  bool Result = MIB.constrainAllUses(TII, TRI, RBI);
  // Build instructions to extract fields of the instruction's result.
  // A new virtual register to store the higher part of the result struct.
  Register HigherVReg = MRI->createGenericVirtualRegister(LLT::scalar(64));
  MRI->setRegClass(HigherVReg, &SPIRV::iIDRegClass);
  for (unsigned i = 0; i < I.getNumDefs(); ++i) {
    auto MIB =
        BuildMI(BB, I, I.getDebugLoc(), TII.get(SPIRV::OpCompositeExtract))
            .addDef(i == 1 ? HigherVReg : I.getOperand(i).getReg())
            .addUse(GR.getSPIRVTypeID(ResType))
            .addUse(StructVReg)
            .addImm(i);
    Result &= MIB.constrainAllUses(TII, TRI, RBI);
  }
  // Build boolean value from the higher part.
  return Result && BuildMI(BB, I, I.getDebugLoc(), TII.get(SPIRV::OpINotEqual))
                       .addDef(I.getOperand(1).getReg())
                       .addUse(BoolTypeReg)
                       .addUse(HigherVReg)
                       .addUse(ZeroReg)
                       .constrainAllUses(TII, TRI, RBI);
}

bool SPIRVInstructionSelector::selectAtomicCmpXchg(Register ResVReg,
                                                   const SPIRVType *ResType,
                                                   MachineInstr &I) const {
  bool Result = true;
  Register ScopeReg;
  Register MemSemEqReg;
  Register MemSemNeqReg;
  Register Ptr = I.getOperand(2).getReg();
  if (!isa<GIntrinsic>(I)) {
    assert(I.hasOneMemOperand());
    const MachineMemOperand *MemOp = *I.memoperands_begin();
    unsigned Scope = static_cast<uint32_t>(getMemScope(
        GR.CurMF->getFunction().getContext(), MemOp->getSyncScopeID()));
    auto ScopeConstant = buildI32Constant(Scope, I);
    ScopeReg = ScopeConstant.first;
    Result &= ScopeConstant.second;

    unsigned ScSem = static_cast<uint32_t>(
        getMemSemanticsForStorageClass(GR.getPointerStorageClass(Ptr)));
    AtomicOrdering AO = MemOp->getSuccessOrdering();
    unsigned MemSemEq = static_cast<uint32_t>(getMemSemantics(AO)) | ScSem;
    auto MemSemEqConstant = buildI32Constant(MemSemEq, I);
    MemSemEqReg = MemSemEqConstant.first;
    Result &= MemSemEqConstant.second;
    AtomicOrdering FO = MemOp->getFailureOrdering();
    unsigned MemSemNeq = static_cast<uint32_t>(getMemSemantics(FO)) | ScSem;
    if (MemSemEq == MemSemNeq)
      MemSemNeqReg = MemSemEqReg;
    else {
      auto MemSemNeqConstant = buildI32Constant(MemSemEq, I);
      MemSemNeqReg = MemSemNeqConstant.first;
      Result &= MemSemNeqConstant.second;
    }
  } else {
    ScopeReg = I.getOperand(5).getReg();
    MemSemEqReg = I.getOperand(6).getReg();
    MemSemNeqReg = I.getOperand(7).getReg();
  }

  Register Cmp = I.getOperand(3).getReg();
  Register Val = I.getOperand(4).getReg();
  SPIRVType *SpvValTy = GR.getSPIRVTypeForVReg(Val);
  Register ACmpRes = createVirtualRegister(SpvValTy, &GR, MRI, *I.getMF());
  const DebugLoc &DL = I.getDebugLoc();
  Result &=
      BuildMI(*I.getParent(), I, DL, TII.get(SPIRV::OpAtomicCompareExchange))
          .addDef(ACmpRes)
          .addUse(GR.getSPIRVTypeID(SpvValTy))
          .addUse(Ptr)
          .addUse(ScopeReg)
          .addUse(MemSemEqReg)
          .addUse(MemSemNeqReg)
          .addUse(Val)
          .addUse(Cmp)
          .constrainAllUses(TII, TRI, RBI);
  SPIRVType *BoolTy = GR.getOrCreateSPIRVBoolType(I, TII);
  Register CmpSuccReg = createVirtualRegister(BoolTy, &GR, MRI, *I.getMF());
  Result &= BuildMI(*I.getParent(), I, DL, TII.get(SPIRV::OpIEqual))
                .addDef(CmpSuccReg)
                .addUse(GR.getSPIRVTypeID(BoolTy))
                .addUse(ACmpRes)
                .addUse(Cmp)
                .constrainAllUses(TII, TRI, RBI);
  Register TmpReg = createVirtualRegister(ResType, &GR, MRI, *I.getMF());
  Result &= BuildMI(*I.getParent(), I, DL, TII.get(SPIRV::OpCompositeInsert))
                .addDef(TmpReg)
                .addUse(GR.getSPIRVTypeID(ResType))
                .addUse(ACmpRes)
                .addUse(GR.getOrCreateUndef(I, ResType, TII))
                .addImm(0)
                .constrainAllUses(TII, TRI, RBI);
  return Result &&
         BuildMI(*I.getParent(), I, DL, TII.get(SPIRV::OpCompositeInsert))
             .addDef(ResVReg)
             .addUse(GR.getSPIRVTypeID(ResType))
             .addUse(CmpSuccReg)
             .addUse(TmpReg)
             .addImm(1)
             .constrainAllUses(TII, TRI, RBI);
}

static bool isUSMStorageClass(SPIRV::StorageClass::StorageClass SC) {
  switch (SC) {
  case SPIRV::StorageClass::DeviceOnlyINTEL:
  case SPIRV::StorageClass::HostOnlyINTEL:
    return true;
  default:
    return false;
  }
}

// Returns true ResVReg is referred only from global vars and OpName's.
static bool isASCastInGVar(MachineRegisterInfo *MRI, Register ResVReg) {
  bool IsGRef = false;
  bool IsAllowedRefs =
      llvm::all_of(MRI->use_instructions(ResVReg), [&IsGRef](auto const &It) {
        unsigned Opcode = It.getOpcode();
        if (Opcode == SPIRV::OpConstantComposite ||
            Opcode == SPIRV::OpVariable ||
            isSpvIntrinsic(It, Intrinsic::spv_init_global))
          return IsGRef = true;
        return Opcode == SPIRV::OpName;
      });
  return IsAllowedRefs && IsGRef;
}

Register SPIRVInstructionSelector::getUcharPtrTypeReg(
    MachineInstr &I, SPIRV::StorageClass::StorageClass SC) const {
  return GR.getSPIRVTypeID(GR.getOrCreateSPIRVPointerType(
      Type::getInt8Ty(I.getMF()->getFunction().getContext()), I, SC));
}

MachineInstrBuilder
SPIRVInstructionSelector::buildSpecConstantOp(MachineInstr &I, Register Dest,
                                              Register Src, Register DestType,
                                              uint32_t Opcode) const {
  return BuildMI(*I.getParent(), I, I.getDebugLoc(),
                 TII.get(SPIRV::OpSpecConstantOp))
      .addDef(Dest)
      .addUse(DestType)
      .addImm(Opcode)
      .addUse(Src);
}

MachineInstrBuilder
SPIRVInstructionSelector::buildConstGenericPtr(MachineInstr &I, Register SrcPtr,
                                               SPIRVType *SrcPtrTy) const {
  SPIRVType *GenericPtrTy =
      GR.changePointerStorageClass(SrcPtrTy, SPIRV::StorageClass::Generic, I);
  Register Tmp = MRI->createVirtualRegister(&SPIRV::pIDRegClass);
  MRI->setType(Tmp, LLT::pointer(storageClassToAddressSpace(
                                     SPIRV::StorageClass::Generic),
                                 GR.getPointerSize()));
  MachineFunction *MF = I.getParent()->getParent();
  GR.assignSPIRVTypeToVReg(GenericPtrTy, Tmp, *MF);
  MachineInstrBuilder MIB = buildSpecConstantOp(
      I, Tmp, SrcPtr, GR.getSPIRVTypeID(GenericPtrTy),
      static_cast<uint32_t>(SPIRV::Opcode::PtrCastToGeneric));
  GR.add(MIB.getInstr(), MIB);
  return MIB;
}

// In SPIR-V address space casting can only happen to and from the Generic
// storage class. We can also only cast Workgroup, CrossWorkgroup, or Function
// pointers to and from Generic pointers. As such, we can convert e.g. from
// Workgroup to Function by going via a Generic pointer as an intermediary. All
// other combinations can only be done by a bitcast, and are probably not safe.
bool SPIRVInstructionSelector::selectAddrSpaceCast(Register ResVReg,
                                                   const SPIRVType *ResType,
                                                   MachineInstr &I) const {
  MachineBasicBlock &BB = *I.getParent();
  const DebugLoc &DL = I.getDebugLoc();

  Register SrcPtr = I.getOperand(1).getReg();
  SPIRVType *SrcPtrTy = GR.getSPIRVTypeForVReg(SrcPtr);

  // don't generate a cast for a null that may be represented by OpTypeInt
  if (SrcPtrTy->getOpcode() != SPIRV::OpTypePointer ||
      ResType->getOpcode() != SPIRV::OpTypePointer)
    return BuildCOPY(ResVReg, SrcPtr, I);

  SPIRV::StorageClass::StorageClass SrcSC = GR.getPointerStorageClass(SrcPtrTy);
  SPIRV::StorageClass::StorageClass DstSC = GR.getPointerStorageClass(ResType);

  if (isASCastInGVar(MRI, ResVReg)) {
    // AddrSpaceCast uses within OpVariable and OpConstantComposite instructions
    // are expressed by OpSpecConstantOp with an Opcode.
    // TODO: maybe insert a check whether the Kernel capability was declared and
    // so PtrCastToGeneric/GenericCastToPtr are available.
    unsigned SpecOpcode =
        DstSC == SPIRV::StorageClass::Generic && isGenericCastablePtr(SrcSC)
            ? static_cast<uint32_t>(SPIRV::Opcode::PtrCastToGeneric)
            : (SrcSC == SPIRV::StorageClass::Generic &&
                       isGenericCastablePtr(DstSC)
                   ? static_cast<uint32_t>(SPIRV::Opcode::GenericCastToPtr)
                   : 0);
    // TODO: OpConstantComposite expects i8*, so we are forced to forget a
    // correct value of ResType and use general i8* instead. Maybe this should
    // be addressed in the emit-intrinsic step to infer a correct
    // OpConstantComposite type.
    if (SpecOpcode) {
      return buildSpecConstantOp(I, ResVReg, SrcPtr,
                                 getUcharPtrTypeReg(I, DstSC), SpecOpcode)
          .constrainAllUses(TII, TRI, RBI);
    } else if (isGenericCastablePtr(SrcSC) && isGenericCastablePtr(DstSC)) {
      MachineInstrBuilder MIB = buildConstGenericPtr(I, SrcPtr, SrcPtrTy);
      return MIB.constrainAllUses(TII, TRI, RBI) &&
             buildSpecConstantOp(
                 I, ResVReg, MIB->getOperand(0).getReg(),
                 getUcharPtrTypeReg(I, DstSC),
                 static_cast<uint32_t>(SPIRV::Opcode::GenericCastToPtr))
                 .constrainAllUses(TII, TRI, RBI);
    }
  }

  // don't generate a cast between identical storage classes
  if (SrcSC == DstSC)
    return BuildCOPY(ResVReg, SrcPtr, I);

  if ((SrcSC == SPIRV::StorageClass::Function &&
       DstSC == SPIRV::StorageClass::Private) ||
      (DstSC == SPIRV::StorageClass::Function &&
       SrcSC == SPIRV::StorageClass::Private))
    return BuildCOPY(ResVReg, SrcPtr, I);

  // Casting from an eligible pointer to Generic.
  if (DstSC == SPIRV::StorageClass::Generic && isGenericCastablePtr(SrcSC))
    return selectUnOp(ResVReg, ResType, I, SPIRV::OpPtrCastToGeneric);
  // Casting from Generic to an eligible pointer.
  if (SrcSC == SPIRV::StorageClass::Generic && isGenericCastablePtr(DstSC))
    return selectUnOp(ResVReg, ResType, I, SPIRV::OpGenericCastToPtr);
  // Casting between 2 eligible pointers using Generic as an intermediary.
  if (isGenericCastablePtr(SrcSC) && isGenericCastablePtr(DstSC)) {
    SPIRVType *GenericPtrTy =
        GR.changePointerStorageClass(SrcPtrTy, SPIRV::StorageClass::Generic, I);
    Register Tmp = createVirtualRegister(GenericPtrTy, &GR, MRI, MRI->getMF());
    bool Result = BuildMI(BB, I, DL, TII.get(SPIRV::OpPtrCastToGeneric))
                      .addDef(Tmp)
                      .addUse(GR.getSPIRVTypeID(GenericPtrTy))
                      .addUse(SrcPtr)
                      .constrainAllUses(TII, TRI, RBI);
    return Result && BuildMI(BB, I, DL, TII.get(SPIRV::OpGenericCastToPtr))
                         .addDef(ResVReg)
                         .addUse(GR.getSPIRVTypeID(ResType))
                         .addUse(Tmp)
                         .constrainAllUses(TII, TRI, RBI);
  }

  // Check if instructions from the SPV_INTEL_usm_storage_classes extension may
  // be applied
  if (isUSMStorageClass(SrcSC) && DstSC == SPIRV::StorageClass::CrossWorkgroup)
    return selectUnOp(ResVReg, ResType, I,
                      SPIRV::OpPtrCastToCrossWorkgroupINTEL);
  if (SrcSC == SPIRV::StorageClass::CrossWorkgroup && isUSMStorageClass(DstSC))
    return selectUnOp(ResVReg, ResType, I,
                      SPIRV::OpCrossWorkgroupCastToPtrINTEL);
  if (isUSMStorageClass(SrcSC) && DstSC == SPIRV::StorageClass::Generic)
    return selectUnOp(ResVReg, ResType, I, SPIRV::OpPtrCastToGeneric);
  if (SrcSC == SPIRV::StorageClass::Generic && isUSMStorageClass(DstSC))
    return selectUnOp(ResVReg, ResType, I, SPIRV::OpGenericCastToPtr);

  // Bitcast for pointers requires that the address spaces must match
  return false;
}

static unsigned getFCmpOpcode(unsigned PredNum) {
  auto Pred = static_cast<CmpInst::Predicate>(PredNum);
  switch (Pred) {
  case CmpInst::FCMP_OEQ:
    return SPIRV::OpFOrdEqual;
  case CmpInst::FCMP_OGE:
    return SPIRV::OpFOrdGreaterThanEqual;
  case CmpInst::FCMP_OGT:
    return SPIRV::OpFOrdGreaterThan;
  case CmpInst::FCMP_OLE:
    return SPIRV::OpFOrdLessThanEqual;
  case CmpInst::FCMP_OLT:
    return SPIRV::OpFOrdLessThan;
  case CmpInst::FCMP_ONE:
    return SPIRV::OpFOrdNotEqual;
  case CmpInst::FCMP_ORD:
    return SPIRV::OpOrdered;
  case CmpInst::FCMP_UEQ:
    return SPIRV::OpFUnordEqual;
  case CmpInst::FCMP_UGE:
    return SPIRV::OpFUnordGreaterThanEqual;
  case CmpInst::FCMP_UGT:
    return SPIRV::OpFUnordGreaterThan;
  case CmpInst::FCMP_ULE:
    return SPIRV::OpFUnordLessThanEqual;
  case CmpInst::FCMP_ULT:
    return SPIRV::OpFUnordLessThan;
  case CmpInst::FCMP_UNE:
    return SPIRV::OpFUnordNotEqual;
  case CmpInst::FCMP_UNO:
    return SPIRV::OpUnordered;
  default:
    llvm_unreachable("Unknown predicate type for FCmp");
  }
}

static unsigned getICmpOpcode(unsigned PredNum) {
  auto Pred = static_cast<CmpInst::Predicate>(PredNum);
  switch (Pred) {
  case CmpInst::ICMP_EQ:
    return SPIRV::OpIEqual;
  case CmpInst::ICMP_NE:
    return SPIRV::OpINotEqual;
  case CmpInst::ICMP_SGE:
    return SPIRV::OpSGreaterThanEqual;
  case CmpInst::ICMP_SGT:
    return SPIRV::OpSGreaterThan;
  case CmpInst::ICMP_SLE:
    return SPIRV::OpSLessThanEqual;
  case CmpInst::ICMP_SLT:
    return SPIRV::OpSLessThan;
  case CmpInst::ICMP_UGE:
    return SPIRV::OpUGreaterThanEqual;
  case CmpInst::ICMP_UGT:
    return SPIRV::OpUGreaterThan;
  case CmpInst::ICMP_ULE:
    return SPIRV::OpULessThanEqual;
  case CmpInst::ICMP_ULT:
    return SPIRV::OpULessThan;
  default:
    llvm_unreachable("Unknown predicate type for ICmp");
  }
}

static unsigned getPtrCmpOpcode(unsigned Pred) {
  switch (static_cast<CmpInst::Predicate>(Pred)) {
  case CmpInst::ICMP_EQ:
    return SPIRV::OpPtrEqual;
  case CmpInst::ICMP_NE:
    return SPIRV::OpPtrNotEqual;
  default:
    llvm_unreachable("Unknown predicate type for pointer comparison");
  }
}

// Return the logical operation, or abort if none exists.
static unsigned getBoolCmpOpcode(unsigned PredNum) {
  auto Pred = static_cast<CmpInst::Predicate>(PredNum);
  switch (Pred) {
  case CmpInst::ICMP_EQ:
    return SPIRV::OpLogicalEqual;
  case CmpInst::ICMP_NE:
    return SPIRV::OpLogicalNotEqual;
  default:
    llvm_unreachable("Unknown predicate type for Bool comparison");
  }
}

static APFloat getZeroFP(const Type *LLVMFloatTy) {
  if (!LLVMFloatTy)
    return APFloat::getZero(APFloat::IEEEsingle());
  switch (LLVMFloatTy->getScalarType()->getTypeID()) {
  case Type::HalfTyID:
    return APFloat::getZero(APFloat::IEEEhalf());
  default:
  case Type::FloatTyID:
    return APFloat::getZero(APFloat::IEEEsingle());
  case Type::DoubleTyID:
    return APFloat::getZero(APFloat::IEEEdouble());
  }
}

static APFloat getOneFP(const Type *LLVMFloatTy) {
  if (!LLVMFloatTy)
    return APFloat::getOne(APFloat::IEEEsingle());
  switch (LLVMFloatTy->getScalarType()->getTypeID()) {
  case Type::HalfTyID:
    return APFloat::getOne(APFloat::IEEEhalf());
  default:
  case Type::FloatTyID:
    return APFloat::getOne(APFloat::IEEEsingle());
  case Type::DoubleTyID:
    return APFloat::getOne(APFloat::IEEEdouble());
  }
}

bool SPIRVInstructionSelector::selectAnyOrAll(Register ResVReg,
                                              const SPIRVType *ResType,
                                              MachineInstr &I,
                                              unsigned OpAnyOrAll) const {
  assert(I.getNumOperands() == 3);
  assert(I.getOperand(2).isReg());
  MachineBasicBlock &BB = *I.getParent();
  Register InputRegister = I.getOperand(2).getReg();
  SPIRVType *InputType = GR.getSPIRVTypeForVReg(InputRegister);

  if (!InputType)
    report_fatal_error("Input Type could not be determined.");

  bool IsBoolTy = GR.isScalarOrVectorOfType(InputRegister, SPIRV::OpTypeBool);
  bool IsVectorTy = InputType->getOpcode() == SPIRV::OpTypeVector;
  if (IsBoolTy && !IsVectorTy) {
    assert(ResVReg == I.getOperand(0).getReg());
    return BuildCOPY(ResVReg, InputRegister, I);
  }

  bool IsFloatTy = GR.isScalarOrVectorOfType(InputRegister, SPIRV::OpTypeFloat);
  unsigned SpirvNotEqualId =
      IsFloatTy ? SPIRV::OpFOrdNotEqual : SPIRV::OpINotEqual;
  SPIRVType *SpvBoolScalarTy = GR.getOrCreateSPIRVBoolType(I, TII);
  SPIRVType *SpvBoolTy = SpvBoolScalarTy;
  Register NotEqualReg = ResVReg;

  if (IsVectorTy) {
    NotEqualReg =
        IsBoolTy ? InputRegister
                 : createVirtualRegister(SpvBoolTy, &GR, MRI, MRI->getMF());
    const unsigned NumElts = InputType->getOperand(2).getImm();
    SpvBoolTy = GR.getOrCreateSPIRVVectorType(SpvBoolTy, NumElts, I, TII);
  }

  bool Result = true;
  if (!IsBoolTy) {
    Register ConstZeroReg =
        IsFloatTy ? buildZerosValF(InputType, I) : buildZerosVal(InputType, I);

    Result &= BuildMI(BB, I, I.getDebugLoc(), TII.get(SpirvNotEqualId))
                  .addDef(NotEqualReg)
                  .addUse(GR.getSPIRVTypeID(SpvBoolTy))
                  .addUse(InputRegister)
                  .addUse(ConstZeroReg)
                  .constrainAllUses(TII, TRI, RBI);
  }

  if (!IsVectorTy)
    return Result;

  return Result && BuildMI(BB, I, I.getDebugLoc(), TII.get(OpAnyOrAll))
                       .addDef(ResVReg)
                       .addUse(GR.getSPIRVTypeID(SpvBoolScalarTy))
                       .addUse(NotEqualReg)
                       .constrainAllUses(TII, TRI, RBI);
}

bool SPIRVInstructionSelector::selectAll(Register ResVReg,
                                         const SPIRVType *ResType,
                                         MachineInstr &I) const {
  return selectAnyOrAll(ResVReg, ResType, I, SPIRV::OpAll);
}

bool SPIRVInstructionSelector::selectAny(Register ResVReg,
                                         const SPIRVType *ResType,
                                         MachineInstr &I) const {
  return selectAnyOrAll(ResVReg, ResType, I, SPIRV::OpAny);
}

// Select the OpDot instruction for the given float dot
bool SPIRVInstructionSelector::selectFloatDot(Register ResVReg,
                                              const SPIRVType *ResType,
                                              MachineInstr &I) const {
  assert(I.getNumOperands() == 4);
  assert(I.getOperand(2).isReg());
  assert(I.getOperand(3).isReg());

  [[maybe_unused]] SPIRVType *VecType =
      GR.getSPIRVTypeForVReg(I.getOperand(2).getReg());

  assert(VecType->getOpcode() == SPIRV::OpTypeVector &&
         GR.getScalarOrVectorComponentCount(VecType) > 1 &&
         "dot product requires a vector of at least 2 components");

  [[maybe_unused]] SPIRVType *EltType =
      GR.getSPIRVTypeForVReg(VecType->getOperand(1).getReg());

  assert(EltType->getOpcode() == SPIRV::OpTypeFloat);

  MachineBasicBlock &BB = *I.getParent();
  return BuildMI(BB, I, I.getDebugLoc(), TII.get(SPIRV::OpDot))
      .addDef(ResVReg)
      .addUse(GR.getSPIRVTypeID(ResType))
      .addUse(I.getOperand(2).getReg())
      .addUse(I.getOperand(3).getReg())
      .constrainAllUses(TII, TRI, RBI);
}

bool SPIRVInstructionSelector::selectIntegerDot(Register ResVReg,
                                                const SPIRVType *ResType,
                                                MachineInstr &I,
                                                bool Signed) const {
  assert(I.getNumOperands() == 4);
  assert(I.getOperand(2).isReg());
  assert(I.getOperand(3).isReg());
  MachineBasicBlock &BB = *I.getParent();

  auto DotOp = Signed ? SPIRV::OpSDot : SPIRV::OpUDot;
  return BuildMI(BB, I, I.getDebugLoc(), TII.get(DotOp))
      .addDef(ResVReg)
      .addUse(GR.getSPIRVTypeID(ResType))
      .addUse(I.getOperand(2).getReg())
      .addUse(I.getOperand(3).getReg())
      .constrainAllUses(TII, TRI, RBI);
}

// Since pre-1.6 SPIRV has no integer dot implementation,
// expand by piecewise multiplying and adding the results
bool SPIRVInstructionSelector::selectIntegerDotExpansion(
    Register ResVReg, const SPIRVType *ResType, MachineInstr &I) const {
  assert(I.getNumOperands() == 4);
  assert(I.getOperand(2).isReg());
  assert(I.getOperand(3).isReg());
  MachineBasicBlock &BB = *I.getParent();

  // Multiply the vectors, then sum the results
  Register Vec0 = I.getOperand(2).getReg();
  Register Vec1 = I.getOperand(3).getReg();
  Register TmpVec = MRI->createVirtualRegister(GR.getRegClass(ResType));
  SPIRVType *VecType = GR.getSPIRVTypeForVReg(Vec0);

  bool Result = BuildMI(BB, I, I.getDebugLoc(), TII.get(SPIRV::OpIMulV))
                    .addDef(TmpVec)
                    .addUse(GR.getSPIRVTypeID(VecType))
                    .addUse(Vec0)
                    .addUse(Vec1)
                    .constrainAllUses(TII, TRI, RBI);

  assert(VecType->getOpcode() == SPIRV::OpTypeVector &&
         GR.getScalarOrVectorComponentCount(VecType) > 1 &&
         "dot product requires a vector of at least 2 components");

  Register Res = MRI->createVirtualRegister(GR.getRegClass(ResType));
  Result &= BuildMI(BB, I, I.getDebugLoc(), TII.get(SPIRV::OpCompositeExtract))
                .addDef(Res)
                .addUse(GR.getSPIRVTypeID(ResType))
                .addUse(TmpVec)
                .addImm(0)
                .constrainAllUses(TII, TRI, RBI);

  for (unsigned i = 1; i < GR.getScalarOrVectorComponentCount(VecType); i++) {
    Register Elt = MRI->createVirtualRegister(GR.getRegClass(ResType));

    Result &=
        BuildMI(BB, I, I.getDebugLoc(), TII.get(SPIRV::OpCompositeExtract))
            .addDef(Elt)
            .addUse(GR.getSPIRVTypeID(ResType))
            .addUse(TmpVec)
            .addImm(i)
            .constrainAllUses(TII, TRI, RBI);

    Register Sum = i < GR.getScalarOrVectorComponentCount(VecType) - 1
                       ? MRI->createVirtualRegister(GR.getRegClass(ResType))
                       : ResVReg;

    Result &= BuildMI(BB, I, I.getDebugLoc(), TII.get(SPIRV::OpIAddS))
                  .addDef(Sum)
                  .addUse(GR.getSPIRVTypeID(ResType))
                  .addUse(Res)
                  .addUse(Elt)
                  .constrainAllUses(TII, TRI, RBI);
    Res = Sum;
  }

  return Result;
}

bool SPIRVInstructionSelector::selectOpIsInf(Register ResVReg,
                                             const SPIRVType *ResType,
                                             MachineInstr &I) const {
  MachineBasicBlock &BB = *I.getParent();
  return BuildMI(BB, I, I.getDebugLoc(), TII.get(SPIRV::OpIsInf))
      .addDef(ResVReg)
      .addUse(GR.getSPIRVTypeID(ResType))
      .addUse(I.getOperand(2).getReg())
      .constrainAllUses(TII, TRI, RBI);
}

bool SPIRVInstructionSelector::selectOpIsNan(Register ResVReg,
                                             const SPIRVType *ResType,
                                             MachineInstr &I) const {
  MachineBasicBlock &BB = *I.getParent();
  return BuildMI(BB, I, I.getDebugLoc(), TII.get(SPIRV::OpIsNan))
      .addDef(ResVReg)
      .addUse(GR.getSPIRVTypeID(ResType))
      .addUse(I.getOperand(2).getReg())
      .constrainAllUses(TII, TRI, RBI);
}

template <bool Signed>
bool SPIRVInstructionSelector::selectDot4AddPacked(Register ResVReg,
                                                   const SPIRVType *ResType,
                                                   MachineInstr &I) const {
  assert(I.getNumOperands() == 5);
  assert(I.getOperand(2).isReg());
  assert(I.getOperand(3).isReg());
  assert(I.getOperand(4).isReg());
  MachineBasicBlock &BB = *I.getParent();

  Register Acc = I.getOperand(2).getReg();
  Register X = I.getOperand(3).getReg();
  Register Y = I.getOperand(4).getReg();

  auto DotOp = Signed ? SPIRV::OpSDot : SPIRV::OpUDot;
  Register Dot = MRI->createVirtualRegister(GR.getRegClass(ResType));
  bool Result = BuildMI(BB, I, I.getDebugLoc(), TII.get(DotOp))
                    .addDef(Dot)
                    .addUse(GR.getSPIRVTypeID(ResType))
                    .addUse(X)
                    .addUse(Y)
                    .constrainAllUses(TII, TRI, RBI);

  return Result && BuildMI(BB, I, I.getDebugLoc(), TII.get(SPIRV::OpIAddS))
                       .addDef(ResVReg)
                       .addUse(GR.getSPIRVTypeID(ResType))
                       .addUse(Dot)
                       .addUse(Acc)
                       .constrainAllUses(TII, TRI, RBI);
}

// Since pre-1.6 SPIRV has no DotProductInput4x8BitPacked implementation,
// extract the elements of the packed inputs, multiply them and add the result
// to the accumulator.
template <bool Signed>
bool SPIRVInstructionSelector::selectDot4AddPackedExpansion(
    Register ResVReg, const SPIRVType *ResType, MachineInstr &I) const {
  assert(I.getNumOperands() == 5);
  assert(I.getOperand(2).isReg());
  assert(I.getOperand(3).isReg());
  assert(I.getOperand(4).isReg());
  MachineBasicBlock &BB = *I.getParent();

  bool Result = true;

  Register Acc = I.getOperand(2).getReg();
  Register X = I.getOperand(3).getReg();
  Register Y = I.getOperand(4).getReg();

  SPIRVType *EltType = GR.getOrCreateSPIRVIntegerType(8, I, TII);
  auto ExtractOp =
      Signed ? SPIRV::OpBitFieldSExtract : SPIRV::OpBitFieldUExtract;

  bool ZeroAsNull = !STI.isShader();
  // Extract the i8 element, multiply and add it to the accumulator
  for (unsigned i = 0; i < 4; i++) {
    // A[i]
    Register AElt = MRI->createVirtualRegister(&SPIRV::IDRegClass);
    Result &=
        BuildMI(BB, I, I.getDebugLoc(), TII.get(ExtractOp))
            .addDef(AElt)
            .addUse(GR.getSPIRVTypeID(ResType))
            .addUse(X)
            .addUse(GR.getOrCreateConstInt(i * 8, I, EltType, TII, ZeroAsNull))
            .addUse(GR.getOrCreateConstInt(8, I, EltType, TII, ZeroAsNull))
            .constrainAllUses(TII, TRI, RBI);

    // B[i]
    Register BElt = MRI->createVirtualRegister(&SPIRV::IDRegClass);
    Result &=
        BuildMI(BB, I, I.getDebugLoc(), TII.get(ExtractOp))
            .addDef(BElt)
            .addUse(GR.getSPIRVTypeID(ResType))
            .addUse(Y)
            .addUse(GR.getOrCreateConstInt(i * 8, I, EltType, TII, ZeroAsNull))
            .addUse(GR.getOrCreateConstInt(8, I, EltType, TII, ZeroAsNull))
            .constrainAllUses(TII, TRI, RBI);

    // A[i] * B[i]
    Register Mul = MRI->createVirtualRegister(&SPIRV::IDRegClass);
    Result &= BuildMI(BB, I, I.getDebugLoc(), TII.get(SPIRV::OpIMulS))
                  .addDef(Mul)
                  .addUse(GR.getSPIRVTypeID(ResType))
                  .addUse(AElt)
                  .addUse(BElt)
                  .constrainAllUses(TII, TRI, RBI);

    // Discard 24 highest-bits so that stored i32 register is i8 equivalent
    Register MaskMul = MRI->createVirtualRegister(&SPIRV::IDRegClass);
    Result &=
        BuildMI(BB, I, I.getDebugLoc(), TII.get(ExtractOp))
            .addDef(MaskMul)
            .addUse(GR.getSPIRVTypeID(ResType))
            .addUse(Mul)
            .addUse(GR.getOrCreateConstInt(0, I, EltType, TII, ZeroAsNull))
            .addUse(GR.getOrCreateConstInt(8, I, EltType, TII, ZeroAsNull))
            .constrainAllUses(TII, TRI, RBI);

    // Acc = Acc + A[i] * B[i]
    Register Sum =
        i < 3 ? MRI->createVirtualRegister(&SPIRV::IDRegClass) : ResVReg;
    Result &= BuildMI(BB, I, I.getDebugLoc(), TII.get(SPIRV::OpIAddS))
                  .addDef(Sum)
                  .addUse(GR.getSPIRVTypeID(ResType))
                  .addUse(Acc)
                  .addUse(MaskMul)
                  .constrainAllUses(TII, TRI, RBI);

    Acc = Sum;
  }

  return Result;
}

/// Transform saturate(x) to clamp(x, 0.0f, 1.0f) as SPIRV
/// does not have a saturate builtin.
bool SPIRVInstructionSelector::selectSaturate(Register ResVReg,
                                              const SPIRVType *ResType,
                                              MachineInstr &I) const {
  assert(I.getNumOperands() == 3);
  assert(I.getOperand(2).isReg());
  MachineBasicBlock &BB = *I.getParent();
  Register VZero = buildZerosValF(ResType, I);
  Register VOne = buildOnesValF(ResType, I);

  return BuildMI(BB, I, I.getDebugLoc(), TII.get(SPIRV::OpExtInst))
      .addDef(ResVReg)
      .addUse(GR.getSPIRVTypeID(ResType))
      .addImm(static_cast<uint32_t>(SPIRV::InstructionSet::GLSL_std_450))
      .addImm(GL::FClamp)
      .addUse(I.getOperand(2).getReg())
      .addUse(VZero)
      .addUse(VOne)
      .constrainAllUses(TII, TRI, RBI);
}

bool SPIRVInstructionSelector::selectSign(Register ResVReg,
                                          const SPIRVType *ResType,
                                          MachineInstr &I) const {
  assert(I.getNumOperands() == 3);
  assert(I.getOperand(2).isReg());
  MachineBasicBlock &BB = *I.getParent();
  Register InputRegister = I.getOperand(2).getReg();
  SPIRVType *InputType = GR.getSPIRVTypeForVReg(InputRegister);
  auto &DL = I.getDebugLoc();

  if (!InputType)
    report_fatal_error("Input Type could not be determined.");

  bool IsFloatTy = GR.isScalarOrVectorOfType(InputRegister, SPIRV::OpTypeFloat);

  unsigned SignBitWidth = GR.getScalarOrVectorBitWidth(InputType);
  unsigned ResBitWidth = GR.getScalarOrVectorBitWidth(ResType);

  bool NeedsConversion = IsFloatTy || SignBitWidth != ResBitWidth;

  auto SignOpcode = IsFloatTy ? GL::FSign : GL::SSign;
  Register SignReg = NeedsConversion
                         ? MRI->createVirtualRegister(&SPIRV::IDRegClass)
                         : ResVReg;

  bool Result =
      BuildMI(BB, I, DL, TII.get(SPIRV::OpExtInst))
          .addDef(SignReg)
          .addUse(GR.getSPIRVTypeID(InputType))
          .addImm(static_cast<uint32_t>(SPIRV::InstructionSet::GLSL_std_450))
          .addImm(SignOpcode)
          .addUse(InputRegister)
          .constrainAllUses(TII, TRI, RBI);

  if (NeedsConversion) {
    auto ConvertOpcode = IsFloatTy ? SPIRV::OpConvertFToS : SPIRV::OpSConvert;
    Result &= BuildMI(*I.getParent(), I, DL, TII.get(ConvertOpcode))
                  .addDef(ResVReg)
                  .addUse(GR.getSPIRVTypeID(ResType))
                  .addUse(SignReg)
                  .constrainAllUses(TII, TRI, RBI);
  }

  return Result;
}

bool SPIRVInstructionSelector::selectWaveOpInst(Register ResVReg,
                                                const SPIRVType *ResType,
                                                MachineInstr &I,
                                                unsigned Opcode) const {
  MachineBasicBlock &BB = *I.getParent();
  SPIRVType *IntTy = GR.getOrCreateSPIRVIntegerType(32, I, TII);

  auto BMI = BuildMI(BB, I, I.getDebugLoc(), TII.get(Opcode))
                 .addDef(ResVReg)
                 .addUse(GR.getSPIRVTypeID(ResType))
                 .addUse(GR.getOrCreateConstInt(SPIRV::Scope::Subgroup, I,
                                                IntTy, TII, !STI.isShader()));

  for (unsigned J = 2; J < I.getNumOperands(); J++) {
    BMI.addUse(I.getOperand(J).getReg());
  }

  return BMI.constrainAllUses(TII, TRI, RBI);
}

bool SPIRVInstructionSelector::selectWaveActiveCountBits(
    Register ResVReg, const SPIRVType *ResType, MachineInstr &I) const {

  SPIRVType *IntTy = GR.getOrCreateSPIRVIntegerType(32, I, TII);
  SPIRVType *BallotType = GR.getOrCreateSPIRVVectorType(IntTy, 4, I, TII);
  Register BallotReg = MRI->createVirtualRegister(GR.getRegClass(BallotType));
  bool Result = selectWaveOpInst(BallotReg, BallotType, I,
                                 SPIRV::OpGroupNonUniformBallot);

  MachineBasicBlock &BB = *I.getParent();
  Result &= BuildMI(BB, I, I.getDebugLoc(),
                    TII.get(SPIRV::OpGroupNonUniformBallotBitCount))
                .addDef(ResVReg)
                .addUse(GR.getSPIRVTypeID(ResType))
                .addUse(GR.getOrCreateConstInt(SPIRV::Scope::Subgroup, I, IntTy,
                                               TII, !STI.isShader()))
                .addImm(SPIRV::GroupOperation::Reduce)
                .addUse(BallotReg)
                .constrainAllUses(TII, TRI, RBI);

  return Result;
}

bool SPIRVInstructionSelector::selectWaveReduceMax(Register ResVReg,
                                                   const SPIRVType *ResType,
                                                   MachineInstr &I,
                                                   bool IsUnsigned) const {
  assert(I.getNumOperands() == 3);
  assert(I.getOperand(2).isReg());
  MachineBasicBlock &BB = *I.getParent();
  Register InputRegister = I.getOperand(2).getReg();
  SPIRVType *InputType = GR.getSPIRVTypeForVReg(InputRegister);

  if (!InputType)
    report_fatal_error("Input Type could not be determined.");

  SPIRVType *IntTy = GR.getOrCreateSPIRVIntegerType(32, I, TII);
  // Retreive the operation to use based on input type
  bool IsFloatTy = GR.isScalarOrVectorOfType(InputRegister, SPIRV::OpTypeFloat);
  auto IntegerOpcodeType =
      IsUnsigned ? SPIRV::OpGroupNonUniformUMax : SPIRV::OpGroupNonUniformSMax;
  auto Opcode = IsFloatTy ? SPIRV::OpGroupNonUniformFMax : IntegerOpcodeType;
  return BuildMI(BB, I, I.getDebugLoc(), TII.get(Opcode))
      .addDef(ResVReg)
      .addUse(GR.getSPIRVTypeID(ResType))
      .addUse(GR.getOrCreateConstInt(SPIRV::Scope::Subgroup, I, IntTy, TII,
                                     !STI.isShader()))
      .addImm(SPIRV::GroupOperation::Reduce)
      .addUse(I.getOperand(2).getReg())
      .constrainAllUses(TII, TRI, RBI);
}

bool SPIRVInstructionSelector::selectWaveReduceSum(Register ResVReg,
                                                   const SPIRVType *ResType,
                                                   MachineInstr &I) const {
  assert(I.getNumOperands() == 3);
  assert(I.getOperand(2).isReg());
  MachineBasicBlock &BB = *I.getParent();
  Register InputRegister = I.getOperand(2).getReg();
  SPIRVType *InputType = GR.getSPIRVTypeForVReg(InputRegister);

  if (!InputType)
    report_fatal_error("Input Type could not be determined.");

  SPIRVType *IntTy = GR.getOrCreateSPIRVIntegerType(32, I, TII);
  // Retreive the operation to use based on input type
  bool IsFloatTy = GR.isScalarOrVectorOfType(InputRegister, SPIRV::OpTypeFloat);
  auto Opcode =
      IsFloatTy ? SPIRV::OpGroupNonUniformFAdd : SPIRV::OpGroupNonUniformIAdd;
  return BuildMI(BB, I, I.getDebugLoc(), TII.get(Opcode))
      .addDef(ResVReg)
      .addUse(GR.getSPIRVTypeID(ResType))
      .addUse(GR.getOrCreateConstInt(SPIRV::Scope::Subgroup, I, IntTy, TII,
                                     !STI.isShader()))
      .addImm(SPIRV::GroupOperation::Reduce)
      .addUse(I.getOperand(2).getReg());
}

bool SPIRVInstructionSelector::selectBitreverse(Register ResVReg,
                                                const SPIRVType *ResType,
                                                MachineInstr &I) const {
  MachineBasicBlock &BB = *I.getParent();
  return BuildMI(BB, I, I.getDebugLoc(), TII.get(SPIRV::OpBitReverse))
      .addDef(ResVReg)
      .addUse(GR.getSPIRVTypeID(ResType))
      .addUse(I.getOperand(1).getReg())
      .constrainAllUses(TII, TRI, RBI);
}

bool SPIRVInstructionSelector::selectFreeze(Register ResVReg,
                                            const SPIRVType *ResType,
                                            MachineInstr &I) const {
  // There is no way to implement `freeze` correctly without support on SPIR-V
  // standard side, but we may at least address a simple (static) case when
  // undef/poison value presence is obvious. The main benefit of even
  // incomplete `freeze` support is preventing of translation from crashing due
  // to lack of support on legalization and instruction selection steps.
  if (!I.getOperand(0).isReg() || !I.getOperand(1).isReg())
    return false;
  Register OpReg = I.getOperand(1).getReg();
  if (MachineInstr *Def = MRI->getVRegDef(OpReg)) {
    if (Def->getOpcode() == TargetOpcode::COPY)
      Def = MRI->getVRegDef(Def->getOperand(1).getReg());
    Register Reg;
    switch (Def->getOpcode()) {
    case SPIRV::ASSIGN_TYPE:
      if (MachineInstr *AssignToDef =
              MRI->getVRegDef(Def->getOperand(1).getReg())) {
        if (AssignToDef->getOpcode() == TargetOpcode::G_IMPLICIT_DEF)
          Reg = Def->getOperand(2).getReg();
      }
      break;
    case SPIRV::OpUndef:
      Reg = Def->getOperand(1).getReg();
      break;
    }
    unsigned DestOpCode;
    if (Reg.isValid()) {
      DestOpCode = SPIRV::OpConstantNull;
    } else {
      DestOpCode = TargetOpcode::COPY;
      Reg = OpReg;
    }
    return BuildMI(*I.getParent(), I, I.getDebugLoc(), TII.get(DestOpCode))
        .addDef(I.getOperand(0).getReg())
        .addUse(Reg)
        .constrainAllUses(TII, TRI, RBI);
  }
  return false;
}

bool SPIRVInstructionSelector::selectBuildVector(Register ResVReg,
                                                 const SPIRVType *ResType,
                                                 MachineInstr &I) const {
  unsigned N = 0;
  if (ResType->getOpcode() == SPIRV::OpTypeVector)
    N = GR.getScalarOrVectorComponentCount(ResType);
  else if (ResType->getOpcode() == SPIRV::OpTypeArray)
    N = getArrayComponentCount(MRI, ResType);
  else
    report_fatal_error("Cannot select G_BUILD_VECTOR with a non-vector result");
  if (I.getNumExplicitOperands() - I.getNumExplicitDefs() != N)
    report_fatal_error("G_BUILD_VECTOR and the result type are inconsistent");

  // check if we may construct a constant vector
  bool IsConst = true;
  for (unsigned i = I.getNumExplicitDefs();
       i < I.getNumExplicitOperands() && IsConst; ++i)
    if (!isConstReg(MRI, I.getOperand(i).getReg()))
      IsConst = false;

  if (!IsConst && N < 2)
    report_fatal_error(
        "There must be at least two constituent operands in a vector");

  MRI->setRegClass(ResVReg, GR.getRegClass(ResType));
  auto MIB = BuildMI(*I.getParent(), I, I.getDebugLoc(),
                     TII.get(IsConst ? SPIRV::OpConstantComposite
                                     : SPIRV::OpCompositeConstruct))
                 .addDef(ResVReg)
                 .addUse(GR.getSPIRVTypeID(ResType));
  for (unsigned i = I.getNumExplicitDefs(); i < I.getNumExplicitOperands(); ++i)
    MIB.addUse(I.getOperand(i).getReg());
  return MIB.constrainAllUses(TII, TRI, RBI);
}

bool SPIRVInstructionSelector::selectSplatVector(Register ResVReg,
                                                 const SPIRVType *ResType,
                                                 MachineInstr &I) const {
  unsigned N = 0;
  if (ResType->getOpcode() == SPIRV::OpTypeVector)
    N = GR.getScalarOrVectorComponentCount(ResType);
  else if (ResType->getOpcode() == SPIRV::OpTypeArray)
    N = getArrayComponentCount(MRI, ResType);
  else
    report_fatal_error("Cannot select G_SPLAT_VECTOR with a non-vector result");

  unsigned OpIdx = I.getNumExplicitDefs();
  if (!I.getOperand(OpIdx).isReg())
    report_fatal_error("Unexpected argument in G_SPLAT_VECTOR");

  // check if we may construct a constant vector
  Register OpReg = I.getOperand(OpIdx).getReg();
  bool IsConst = isConstReg(MRI, OpReg);

  if (!IsConst && N < 2)
    report_fatal_error(
        "There must be at least two constituent operands in a vector");

  MRI->setRegClass(ResVReg, GR.getRegClass(ResType));
  auto MIB = BuildMI(*I.getParent(), I, I.getDebugLoc(),
                     TII.get(IsConst ? SPIRV::OpConstantComposite
                                     : SPIRV::OpCompositeConstruct))
                 .addDef(ResVReg)
                 .addUse(GR.getSPIRVTypeID(ResType));
  for (unsigned i = 0; i < N; ++i)
    MIB.addUse(OpReg);
  return MIB.constrainAllUses(TII, TRI, RBI);
}

bool SPIRVInstructionSelector::selectDiscard(Register ResVReg,
                                             const SPIRVType *ResType,
                                             MachineInstr &I) const {

  unsigned Opcode;

  if (STI.canUseExtension(
          SPIRV::Extension::SPV_EXT_demote_to_helper_invocation) ||
      STI.isAtLeastSPIRVVer(llvm::VersionTuple(1, 6))) {
    Opcode = SPIRV::OpDemoteToHelperInvocation;
  } else {
    Opcode = SPIRV::OpKill;
    // OpKill must be the last operation of any basic block.
    if (MachineInstr *NextI = I.getNextNode()) {
      GR.invalidateMachineInstr(NextI);
      NextI->removeFromParent();
    }
  }

  MachineBasicBlock &BB = *I.getParent();
  return BuildMI(BB, I, I.getDebugLoc(), TII.get(Opcode))
      .constrainAllUses(TII, TRI, RBI);
}

bool SPIRVInstructionSelector::selectCmp(Register ResVReg,
                                         const SPIRVType *ResType,
                                         unsigned CmpOpc,
                                         MachineInstr &I) const {
  Register Cmp0 = I.getOperand(2).getReg();
  Register Cmp1 = I.getOperand(3).getReg();
  assert(GR.getSPIRVTypeForVReg(Cmp0)->getOpcode() ==
             GR.getSPIRVTypeForVReg(Cmp1)->getOpcode() &&
         "CMP operands should have the same type");
  return BuildMI(*I.getParent(), I, I.getDebugLoc(), TII.get(CmpOpc))
      .addDef(ResVReg)
      .addUse(GR.getSPIRVTypeID(ResType))
      .addUse(Cmp0)
      .addUse(Cmp1)
      .setMIFlags(I.getFlags())
      .constrainAllUses(TII, TRI, RBI);
}

bool SPIRVInstructionSelector::selectICmp(Register ResVReg,
                                          const SPIRVType *ResType,
                                          MachineInstr &I) const {
  auto Pred = I.getOperand(1).getPredicate();
  unsigned CmpOpc;

  Register CmpOperand = I.getOperand(2).getReg();
  if (GR.isScalarOfType(CmpOperand, SPIRV::OpTypePointer))
    CmpOpc = getPtrCmpOpcode(Pred);
  else if (GR.isScalarOrVectorOfType(CmpOperand, SPIRV::OpTypeBool))
    CmpOpc = getBoolCmpOpcode(Pred);
  else
    CmpOpc = getICmpOpcode(Pred);
  return selectCmp(ResVReg, ResType, CmpOpc, I);
}

std::pair<Register, bool>
SPIRVInstructionSelector::buildI32Constant(uint32_t Val, MachineInstr &I,
                                           const SPIRVType *ResType) const {
  Type *LLVMTy = IntegerType::get(GR.CurMF->getFunction().getContext(), 32);
  const SPIRVType *SpvI32Ty =
      ResType ? ResType : GR.getOrCreateSPIRVIntegerType(32, I, TII);
  // Find a constant in DT or build a new one.
  auto ConstInt = ConstantInt::get(LLVMTy, Val);
  Register NewReg = GR.find(ConstInt, GR.CurMF);
  bool Result = true;
  if (!NewReg.isValid()) {
    NewReg = MRI->createGenericVirtualRegister(LLT::scalar(64));
    MachineBasicBlock &BB = *I.getParent();
    MachineInstr *MI =
        Val == 0
            ? BuildMI(BB, I, I.getDebugLoc(), TII.get(SPIRV::OpConstantNull))
                  .addDef(NewReg)
                  .addUse(GR.getSPIRVTypeID(SpvI32Ty))
            : BuildMI(BB, I, I.getDebugLoc(), TII.get(SPIRV::OpConstantI))
                  .addDef(NewReg)
                  .addUse(GR.getSPIRVTypeID(SpvI32Ty))
                  .addImm(APInt(32, Val).getZExtValue());
    Result &= constrainSelectedInstRegOperands(*MI, TII, TRI, RBI);
    GR.add(ConstInt, MI);
  }
  return {NewReg, Result};
}

bool SPIRVInstructionSelector::selectFCmp(Register ResVReg,
                                          const SPIRVType *ResType,
                                          MachineInstr &I) const {
  unsigned CmpOp = getFCmpOpcode(I.getOperand(1).getPredicate());
  return selectCmp(ResVReg, ResType, CmpOp, I);
}

Register SPIRVInstructionSelector::buildZerosVal(const SPIRVType *ResType,
                                                 MachineInstr &I) const {
  // OpenCL uses nulls for Zero. In HLSL we don't use null constants.
  bool ZeroAsNull = !STI.isShader();
  if (ResType->getOpcode() == SPIRV::OpTypeVector)
    return GR.getOrCreateConstVector(0UL, I, ResType, TII, ZeroAsNull);
  return GR.getOrCreateConstInt(0, I, ResType, TII, ZeroAsNull);
}

Register SPIRVInstructionSelector::buildZerosValF(const SPIRVType *ResType,
                                                  MachineInstr &I) const {
  // OpenCL uses nulls for Zero. In HLSL we don't use null constants.
  bool ZeroAsNull = !STI.isShader();
  APFloat VZero = getZeroFP(GR.getTypeForSPIRVType(ResType));
  if (ResType->getOpcode() == SPIRV::OpTypeVector)
    return GR.getOrCreateConstVector(VZero, I, ResType, TII, ZeroAsNull);
  return GR.getOrCreateConstFP(VZero, I, ResType, TII, ZeroAsNull);
}

Register SPIRVInstructionSelector::buildOnesValF(const SPIRVType *ResType,
                                                 MachineInstr &I) const {
  // OpenCL uses nulls for Zero. In HLSL we don't use null constants.
  bool ZeroAsNull = !STI.isShader();
  APFloat VOne = getOneFP(GR.getTypeForSPIRVType(ResType));
  if (ResType->getOpcode() == SPIRV::OpTypeVector)
    return GR.getOrCreateConstVector(VOne, I, ResType, TII, ZeroAsNull);
  return GR.getOrCreateConstFP(VOne, I, ResType, TII, ZeroAsNull);
}

Register SPIRVInstructionSelector::buildOnesVal(bool AllOnes,
                                                const SPIRVType *ResType,
                                                MachineInstr &I) const {
  unsigned BitWidth = GR.getScalarOrVectorBitWidth(ResType);
  APInt One =
      AllOnes ? APInt::getAllOnes(BitWidth) : APInt::getOneBitSet(BitWidth, 0);
  if (ResType->getOpcode() == SPIRV::OpTypeVector)
    return GR.getOrCreateConstVector(One.getZExtValue(), I, ResType, TII);
  return GR.getOrCreateConstInt(One.getZExtValue(), I, ResType, TII);
}

bool SPIRVInstructionSelector::selectSelect(Register ResVReg,
                                            const SPIRVType *ResType,
                                            MachineInstr &I) const {
  Register SelectFirstArg = I.getOperand(2).getReg();
  Register SelectSecondArg = I.getOperand(3).getReg();
  assert(ResType == GR.getSPIRVTypeForVReg(SelectFirstArg) &&
         ResType == GR.getSPIRVTypeForVReg(SelectSecondArg));

  bool IsFloatTy =
      GR.isScalarOrVectorOfType(SelectFirstArg, SPIRV::OpTypeFloat);
  bool IsPtrTy =
      GR.isScalarOrVectorOfType(SelectFirstArg, SPIRV::OpTypePointer);
  bool IsVectorTy = GR.getSPIRVTypeForVReg(SelectFirstArg)->getOpcode() ==
                    SPIRV::OpTypeVector;

  bool IsScalarBool =
      GR.isScalarOfType(I.getOperand(1).getReg(), SPIRV::OpTypeBool);
  unsigned Opcode;
  if (IsVectorTy) {
    if (IsFloatTy) {
      Opcode = IsScalarBool ? SPIRV::OpSelectVFSCond : SPIRV::OpSelectVFVCond;
    } else if (IsPtrTy) {
      Opcode = IsScalarBool ? SPIRV::OpSelectVPSCond : SPIRV::OpSelectVPVCond;
    } else {
      Opcode = IsScalarBool ? SPIRV::OpSelectVISCond : SPIRV::OpSelectVIVCond;
    }
  } else {
    if (IsFloatTy) {
      Opcode = IsScalarBool ? SPIRV::OpSelectSFSCond : SPIRV::OpSelectVFVCond;
    } else if (IsPtrTy) {
      Opcode = IsScalarBool ? SPIRV::OpSelectSPSCond : SPIRV::OpSelectVPVCond;
    } else {
      Opcode = IsScalarBool ? SPIRV::OpSelectSISCond : SPIRV::OpSelectVIVCond;
    }
  }
  return BuildMI(*I.getParent(), I, I.getDebugLoc(), TII.get(Opcode))
      .addDef(ResVReg)
      .addUse(GR.getSPIRVTypeID(ResType))
      .addUse(I.getOperand(1).getReg())
      .addUse(SelectFirstArg)
      .addUse(SelectSecondArg)
      .constrainAllUses(TII, TRI, RBI);
}

bool SPIRVInstructionSelector::selectSelectDefaultArgs(Register ResVReg,
                                                       const SPIRVType *ResType,
                                                       MachineInstr &I,
                                                       bool IsSigned) const {
  // To extend a bool, we need to use OpSelect between constants.
  Register ZeroReg = buildZerosVal(ResType, I);
  Register OneReg = buildOnesVal(IsSigned, ResType, I);
  bool IsScalarBool =
      GR.isScalarOfType(I.getOperand(1).getReg(), SPIRV::OpTypeBool);
  unsigned Opcode =
      IsScalarBool ? SPIRV::OpSelectSISCond : SPIRV::OpSelectVIVCond;
  return BuildMI(*I.getParent(), I, I.getDebugLoc(), TII.get(Opcode))
      .addDef(ResVReg)
      .addUse(GR.getSPIRVTypeID(ResType))
      .addUse(I.getOperand(1).getReg())
      .addUse(OneReg)
      .addUse(ZeroReg)
      .constrainAllUses(TII, TRI, RBI);
}

bool SPIRVInstructionSelector::selectIToF(Register ResVReg,
                                          const SPIRVType *ResType,
                                          MachineInstr &I, bool IsSigned,
                                          unsigned Opcode) const {
  Register SrcReg = I.getOperand(1).getReg();
  // We can convert bool value directly to float type without OpConvert*ToF,
  // however the translator generates OpSelect+OpConvert*ToF, so we do the same.
  if (GR.isScalarOrVectorOfType(I.getOperand(1).getReg(), SPIRV::OpTypeBool)) {
    unsigned BitWidth = GR.getScalarOrVectorBitWidth(ResType);
    SPIRVType *TmpType = GR.getOrCreateSPIRVIntegerType(BitWidth, I, TII);
    if (ResType->getOpcode() == SPIRV::OpTypeVector) {
      const unsigned NumElts = ResType->getOperand(2).getImm();
      TmpType = GR.getOrCreateSPIRVVectorType(TmpType, NumElts, I, TII);
    }
    SrcReg = createVirtualRegister(TmpType, &GR, MRI, MRI->getMF());
    selectSelectDefaultArgs(SrcReg, TmpType, I, false);
  }
  return selectOpWithSrcs(ResVReg, ResType, I, {SrcReg}, Opcode);
}

bool SPIRVInstructionSelector::selectExt(Register ResVReg,
                                         const SPIRVType *ResType,
                                         MachineInstr &I, bool IsSigned) const {
  Register SrcReg = I.getOperand(1).getReg();
  if (GR.isScalarOrVectorOfType(SrcReg, SPIRV::OpTypeBool))
    return selectSelectDefaultArgs(ResVReg, ResType, I, IsSigned);

  SPIRVType *SrcType = GR.getSPIRVTypeForVReg(SrcReg);
  if (SrcType == ResType)
    return BuildCOPY(ResVReg, SrcReg, I);

  unsigned Opcode = IsSigned ? SPIRV::OpSConvert : SPIRV::OpUConvert;
  return selectUnOp(ResVReg, ResType, I, Opcode);
}

bool SPIRVInstructionSelector::selectSUCmp(Register ResVReg,
                                           const SPIRVType *ResType,
                                           MachineInstr &I,
                                           bool IsSigned) const {
  MachineIRBuilder MIRBuilder(I);
  MachineRegisterInfo *MRI = MIRBuilder.getMRI();
  MachineBasicBlock &BB = *I.getParent();
  // Ensure we have bool.
  SPIRVType *BoolType = GR.getOrCreateSPIRVBoolType(I, TII);
  unsigned N = GR.getScalarOrVectorComponentCount(ResType);
  if (N > 1)
    BoolType = GR.getOrCreateSPIRVVectorType(BoolType, N, I, TII);
  Register BoolTypeReg = GR.getSPIRVTypeID(BoolType);
  // Build less-than-equal and less-than.
  // TODO: replace with one-liner createVirtualRegister() from
  // llvm/lib/Target/SPIRV/SPIRVUtils.cpp when PR #116609 is merged.
  Register IsLessEqReg = MRI->createVirtualRegister(GR.getRegClass(ResType));
  MRI->setType(IsLessEqReg, LLT::scalar(64));
  GR.assignSPIRVTypeToVReg(ResType, IsLessEqReg, MIRBuilder.getMF());
  bool Result = BuildMI(BB, I, I.getDebugLoc(),
                        TII.get(IsSigned ? SPIRV::OpSLessThanEqual
                                         : SPIRV::OpULessThanEqual))
                    .addDef(IsLessEqReg)
                    .addUse(BoolTypeReg)
                    .addUse(I.getOperand(1).getReg())
                    .addUse(I.getOperand(2).getReg())
                    .constrainAllUses(TII, TRI, RBI);
  Register IsLessReg = MRI->createVirtualRegister(GR.getRegClass(ResType));
  MRI->setType(IsLessReg, LLT::scalar(64));
  GR.assignSPIRVTypeToVReg(ResType, IsLessReg, MIRBuilder.getMF());
  Result &= BuildMI(BB, I, I.getDebugLoc(),
                    TII.get(IsSigned ? SPIRV::OpSLessThan : SPIRV::OpULessThan))
                .addDef(IsLessReg)
                .addUse(BoolTypeReg)
                .addUse(I.getOperand(1).getReg())
                .addUse(I.getOperand(2).getReg())
                .constrainAllUses(TII, TRI, RBI);
  // Build selects.
  Register ResTypeReg = GR.getSPIRVTypeID(ResType);
  Register NegOneOrZeroReg =
      MRI->createVirtualRegister(GR.getRegClass(ResType));
  MRI->setType(NegOneOrZeroReg, LLT::scalar(64));
  GR.assignSPIRVTypeToVReg(ResType, NegOneOrZeroReg, MIRBuilder.getMF());
  unsigned SelectOpcode =
      N > 1 ? SPIRV::OpSelectVIVCond : SPIRV::OpSelectSISCond;
  Result &= BuildMI(BB, I, I.getDebugLoc(), TII.get(SelectOpcode))
                .addDef(NegOneOrZeroReg)
                .addUse(ResTypeReg)
                .addUse(IsLessReg)
                .addUse(buildOnesVal(true, ResType, I)) // -1
                .addUse(buildZerosVal(ResType, I))
                .constrainAllUses(TII, TRI, RBI);
  return Result & BuildMI(BB, I, I.getDebugLoc(), TII.get(SelectOpcode))
                      .addDef(ResVReg)
                      .addUse(ResTypeReg)
                      .addUse(IsLessEqReg)
                      .addUse(NegOneOrZeroReg) // -1 or 0
                      .addUse(buildOnesVal(false, ResType, I))
                      .constrainAllUses(TII, TRI, RBI);
}

bool SPIRVInstructionSelector::selectIntToBool(Register IntReg,
                                               Register ResVReg,
                                               MachineInstr &I,
                                               const SPIRVType *IntTy,
                                               const SPIRVType *BoolTy) const {
  // To truncate to a bool, we use OpBitwiseAnd 1 and OpINotEqual to zero.
  Register BitIntReg = createVirtualRegister(IntTy, &GR, MRI, MRI->getMF());
  bool IsVectorTy = IntTy->getOpcode() == SPIRV::OpTypeVector;
  unsigned Opcode = IsVectorTy ? SPIRV::OpBitwiseAndV : SPIRV::OpBitwiseAndS;
  Register Zero = buildZerosVal(IntTy, I);
  Register One = buildOnesVal(false, IntTy, I);
  MachineBasicBlock &BB = *I.getParent();
  bool Result = BuildMI(BB, I, I.getDebugLoc(), TII.get(Opcode))
                    .addDef(BitIntReg)
                    .addUse(GR.getSPIRVTypeID(IntTy))
                    .addUse(IntReg)
                    .addUse(One)
                    .constrainAllUses(TII, TRI, RBI);
  return Result && BuildMI(BB, I, I.getDebugLoc(), TII.get(SPIRV::OpINotEqual))
                       .addDef(ResVReg)
                       .addUse(GR.getSPIRVTypeID(BoolTy))
                       .addUse(BitIntReg)
                       .addUse(Zero)
                       .constrainAllUses(TII, TRI, RBI);
}

bool SPIRVInstructionSelector::selectTrunc(Register ResVReg,
                                           const SPIRVType *ResType,
                                           MachineInstr &I) const {
  Register IntReg = I.getOperand(1).getReg();
  const SPIRVType *ArgType = GR.getSPIRVTypeForVReg(IntReg);
  if (GR.isScalarOrVectorOfType(ResVReg, SPIRV::OpTypeBool))
    return selectIntToBool(IntReg, ResVReg, I, ArgType, ResType);
  if (ArgType == ResType)
    return BuildCOPY(ResVReg, IntReg, I);
  bool IsSigned = GR.isScalarOrVectorSigned(ResType);
  unsigned Opcode = IsSigned ? SPIRV::OpSConvert : SPIRV::OpUConvert;
  return selectUnOp(ResVReg, ResType, I, Opcode);
}

bool SPIRVInstructionSelector::selectConst(Register ResVReg,
                                           const SPIRVType *ResType,
                                           MachineInstr &I) const {
  unsigned Opcode = I.getOpcode();
  unsigned TpOpcode = ResType->getOpcode();
  Register Reg;
  if (TpOpcode == SPIRV::OpTypePointer || TpOpcode == SPIRV::OpTypeEvent) {
    assert(Opcode == TargetOpcode::G_CONSTANT &&
           I.getOperand(1).getCImm()->isZero());
    MachineBasicBlock &DepMBB = I.getMF()->front();
    MachineIRBuilder MIRBuilder(DepMBB, DepMBB.getFirstNonPHI());
    Reg = GR.getOrCreateConstNullPtr(MIRBuilder, ResType);
  } else if (Opcode == TargetOpcode::G_FCONSTANT) {
    Reg = GR.getOrCreateConstFP(I.getOperand(1).getFPImm()->getValue(), I,
                                ResType, TII, !STI.isShader());
  } else {
    Reg = GR.getOrCreateConstInt(I.getOperand(1).getCImm()->getZExtValue(), I,
                                 ResType, TII, !STI.isShader());
  }
  return Reg == ResVReg ? true : BuildCOPY(ResVReg, Reg, I);
}

bool SPIRVInstructionSelector::selectOpUndef(Register ResVReg,
                                             const SPIRVType *ResType,
                                             MachineInstr &I) const {
  return BuildMI(*I.getParent(), I, I.getDebugLoc(), TII.get(SPIRV::OpUndef))
      .addDef(ResVReg)
      .addUse(GR.getSPIRVTypeID(ResType))
      .constrainAllUses(TII, TRI, RBI);
}

bool SPIRVInstructionSelector::selectInsertVal(Register ResVReg,
                                               const SPIRVType *ResType,
                                               MachineInstr &I) const {
  MachineBasicBlock &BB = *I.getParent();
  auto MIB = BuildMI(BB, I, I.getDebugLoc(), TII.get(SPIRV::OpCompositeInsert))
                 .addDef(ResVReg)
                 .addUse(GR.getSPIRVTypeID(ResType))
                 // object to insert
                 .addUse(I.getOperand(3).getReg())
                 // composite to insert into
                 .addUse(I.getOperand(2).getReg());
  for (unsigned i = 4; i < I.getNumOperands(); i++)
    MIB.addImm(foldImm(I.getOperand(i), MRI));
  return MIB.constrainAllUses(TII, TRI, RBI);
}

bool SPIRVInstructionSelector::selectExtractVal(Register ResVReg,
                                                const SPIRVType *ResType,
                                                MachineInstr &I) const {
  MachineBasicBlock &BB = *I.getParent();
  auto MIB = BuildMI(BB, I, I.getDebugLoc(), TII.get(SPIRV::OpCompositeExtract))
                 .addDef(ResVReg)
                 .addUse(GR.getSPIRVTypeID(ResType))
                 .addUse(I.getOperand(2).getReg());
  for (unsigned i = 3; i < I.getNumOperands(); i++)
    MIB.addImm(foldImm(I.getOperand(i), MRI));
  return MIB.constrainAllUses(TII, TRI, RBI);
}

bool SPIRVInstructionSelector::selectInsertElt(Register ResVReg,
                                               const SPIRVType *ResType,
                                               MachineInstr &I) const {
  if (getImm(I.getOperand(4), MRI))
    return selectInsertVal(ResVReg, ResType, I);
  MachineBasicBlock &BB = *I.getParent();
  return BuildMI(BB, I, I.getDebugLoc(), TII.get(SPIRV::OpVectorInsertDynamic))
      .addDef(ResVReg)
      .addUse(GR.getSPIRVTypeID(ResType))
      .addUse(I.getOperand(2).getReg())
      .addUse(I.getOperand(3).getReg())
      .addUse(I.getOperand(4).getReg())
      .constrainAllUses(TII, TRI, RBI);
}

bool SPIRVInstructionSelector::selectExtractElt(Register ResVReg,
                                                const SPIRVType *ResType,
                                                MachineInstr &I) const {
  if (getImm(I.getOperand(3), MRI))
    return selectExtractVal(ResVReg, ResType, I);
  MachineBasicBlock &BB = *I.getParent();
  return BuildMI(BB, I, I.getDebugLoc(), TII.get(SPIRV::OpVectorExtractDynamic))
      .addDef(ResVReg)
      .addUse(GR.getSPIRVTypeID(ResType))
      .addUse(I.getOperand(2).getReg())
      .addUse(I.getOperand(3).getReg())
      .constrainAllUses(TII, TRI, RBI);
}

bool SPIRVInstructionSelector::selectGEP(Register ResVReg,
                                         const SPIRVType *ResType,
                                         MachineInstr &I) const {
  const bool IsGEPInBounds = I.getOperand(2).getImm();

  // OpAccessChain could be used for OpenCL, but the SPIRV-LLVM Translator only
  // relies on PtrAccessChain, so we'll try not to deviate. For Vulkan however,
  // we have to use Op[InBounds]AccessChain.
  const unsigned Opcode = STI.isLogicalSPIRV()
                              ? (IsGEPInBounds ? SPIRV::OpInBoundsAccessChain
                                               : SPIRV::OpAccessChain)
                              : (IsGEPInBounds ? SPIRV::OpInBoundsPtrAccessChain
                                               : SPIRV::OpPtrAccessChain);

  auto Res = BuildMI(*I.getParent(), I, I.getDebugLoc(), TII.get(Opcode))
                 .addDef(ResVReg)
                 .addUse(GR.getSPIRVTypeID(ResType))
                 // Object to get a pointer to.
                 .addUse(I.getOperand(3).getReg());
  // Adding indices.
  const unsigned StartingIndex =
      (Opcode == SPIRV::OpAccessChain || Opcode == SPIRV::OpInBoundsAccessChain)
          ? 5
          : 4;
  for (unsigned i = StartingIndex; i < I.getNumExplicitOperands(); ++i)
    Res.addUse(I.getOperand(i).getReg());
  return Res.constrainAllUses(TII, TRI, RBI);
}

// Maybe wrap a value into OpSpecConstantOp
bool SPIRVInstructionSelector::wrapIntoSpecConstantOp(
    MachineInstr &I, SmallVector<Register> &CompositeArgs) const {
  bool Result = true;
  unsigned Lim = I.getNumExplicitOperands();
  for (unsigned i = I.getNumExplicitDefs() + 1; i < Lim; ++i) {
    Register OpReg = I.getOperand(i).getReg();
    MachineInstr *OpDefine = MRI->getVRegDef(OpReg);
    SPIRVType *OpType = GR.getSPIRVTypeForVReg(OpReg);
    SmallPtrSet<SPIRVType *, 4> Visited;
    if (!OpDefine || !OpType || isConstReg(MRI, OpDefine, Visited) ||
        OpDefine->getOpcode() == TargetOpcode::G_ADDRSPACE_CAST ||
        GR.isAggregateType(OpType)) {
      // The case of G_ADDRSPACE_CAST inside spv_const_composite() is processed
      // by selectAddrSpaceCast()
      CompositeArgs.push_back(OpReg);
      continue;
    }
    MachineFunction *MF = I.getMF();
    Register WrapReg = GR.find(OpDefine, MF);
    if (WrapReg.isValid()) {
      CompositeArgs.push_back(WrapReg);
      continue;
    }
    // Create a new register for the wrapper
    WrapReg = MRI->createVirtualRegister(GR.getRegClass(OpType));
    CompositeArgs.push_back(WrapReg);
    // Decorate the wrapper register and generate a new instruction
    MRI->setType(WrapReg, LLT::pointer(0, 64));
    GR.assignSPIRVTypeToVReg(OpType, WrapReg, *MF);
    auto MIB = BuildMI(*I.getParent(), I, I.getDebugLoc(),
                       TII.get(SPIRV::OpSpecConstantOp))
                   .addDef(WrapReg)
                   .addUse(GR.getSPIRVTypeID(OpType))
                   .addImm(static_cast<uint32_t>(SPIRV::Opcode::Bitcast))
                   .addUse(OpReg);
    GR.add(OpDefine, MIB);
    Result = MIB.constrainAllUses(TII, TRI, RBI);
    if (!Result)
      break;
  }
  return Result;
}

bool SPIRVInstructionSelector::selectIntrinsic(Register ResVReg,
                                               const SPIRVType *ResType,
                                               MachineInstr &I) const {
  MachineBasicBlock &BB = *I.getParent();
  Intrinsic::ID IID = cast<GIntrinsic>(I).getIntrinsicID();
  switch (IID) {
  case Intrinsic::spv_load:
    return selectLoad(ResVReg, ResType, I);
  case Intrinsic::spv_store:
    return selectStore(I);
  case Intrinsic::spv_extractv:
    return selectExtractVal(ResVReg, ResType, I);
  case Intrinsic::spv_insertv:
    return selectInsertVal(ResVReg, ResType, I);
  case Intrinsic::spv_extractelt:
    return selectExtractElt(ResVReg, ResType, I);
  case Intrinsic::spv_insertelt:
    return selectInsertElt(ResVReg, ResType, I);
  case Intrinsic::spv_gep:
    return selectGEP(ResVReg, ResType, I);
  case Intrinsic::spv_unref_global:
  case Intrinsic::spv_init_global: {
    MachineInstr *MI = MRI->getVRegDef(I.getOperand(1).getReg());
    MachineInstr *Init = I.getNumExplicitOperands() > 2
                             ? MRI->getVRegDef(I.getOperand(2).getReg())
                             : nullptr;
    assert(MI);
    Register GVarVReg = MI->getOperand(0).getReg();
    bool Res = selectGlobalValue(GVarVReg, *MI, Init);
    // We violate SSA form by inserting OpVariable and still having a gMIR
    // instruction %vreg = G_GLOBAL_VALUE @gvar. We need to fix this by erasing
    // the duplicated definition.
    if (MI->getOpcode() == TargetOpcode::G_GLOBAL_VALUE) {
      GR.invalidateMachineInstr(MI);
      MI->removeFromParent();
    }
    return Res;
  }
  case Intrinsic::spv_undef: {
    auto MIB = BuildMI(BB, I, I.getDebugLoc(), TII.get(SPIRV::OpUndef))
                   .addDef(ResVReg)
                   .addUse(GR.getSPIRVTypeID(ResType));
    return MIB.constrainAllUses(TII, TRI, RBI);
  }
  case Intrinsic::spv_const_composite: {
    // If no values are attached, the composite is null constant.
    bool IsNull = I.getNumExplicitDefs() + 1 == I.getNumExplicitOperands();
    SmallVector<Register> CompositeArgs;
    MRI->setRegClass(ResVReg, GR.getRegClass(ResType));

    // skip type MD node we already used when generated assign.type for this
    if (!IsNull) {
      if (!wrapIntoSpecConstantOp(I, CompositeArgs))
        return false;
      MachineIRBuilder MIR(I);
      SmallVector<MachineInstr *, 4> Instructions = createContinuedInstructions(
          MIR, SPIRV::OpConstantComposite, 3,
          SPIRV::OpConstantCompositeContinuedINTEL, CompositeArgs, ResVReg,
          GR.getSPIRVTypeID(ResType));
      for (auto *Instr : Instructions) {
        Instr->setDebugLoc(I.getDebugLoc());
        if (!constrainSelectedInstRegOperands(*Instr, TII, TRI, RBI))
          return false;
      }
      return true;
    } else {
      auto MIB = BuildMI(BB, I, I.getDebugLoc(), TII.get(SPIRV::OpConstantNull))
                     .addDef(ResVReg)
                     .addUse(GR.getSPIRVTypeID(ResType));
      return MIB.constrainAllUses(TII, TRI, RBI);
    }
  }
  case Intrinsic::spv_assign_name: {
    auto MIB = BuildMI(BB, I, I.getDebugLoc(), TII.get(SPIRV::OpName));
    MIB.addUse(I.getOperand(I.getNumExplicitDefs() + 1).getReg());
    for (unsigned i = I.getNumExplicitDefs() + 2;
         i < I.getNumExplicitOperands(); ++i) {
      MIB.addImm(I.getOperand(i).getImm());
    }
    return MIB.constrainAllUses(TII, TRI, RBI);
  }
  case Intrinsic::spv_switch: {
    auto MIB = BuildMI(BB, I, I.getDebugLoc(), TII.get(SPIRV::OpSwitch));
    for (unsigned i = 1; i < I.getNumExplicitOperands(); ++i) {
      if (I.getOperand(i).isReg())
        MIB.addReg(I.getOperand(i).getReg());
      else if (I.getOperand(i).isCImm())
        addNumImm(I.getOperand(i).getCImm()->getValue(), MIB);
      else if (I.getOperand(i).isMBB())
        MIB.addMBB(I.getOperand(i).getMBB());
      else
        llvm_unreachable("Unexpected OpSwitch operand");
    }
    return MIB.constrainAllUses(TII, TRI, RBI);
  }
  case Intrinsic::spv_loop_merge: {
    auto MIB = BuildMI(BB, I, I.getDebugLoc(), TII.get(SPIRV::OpLoopMerge));
    for (unsigned i = 1; i < I.getNumExplicitOperands(); ++i) {
      if (I.getOperand(i).isMBB())
        MIB.addMBB(I.getOperand(i).getMBB());
      else
        MIB.addImm(foldImm(I.getOperand(i), MRI));
    }
    return MIB.constrainAllUses(TII, TRI, RBI);
  }
  case Intrinsic::spv_selection_merge: {
    auto MIB =
        BuildMI(BB, I, I.getDebugLoc(), TII.get(SPIRV::OpSelectionMerge));
    assert(I.getOperand(1).isMBB() &&
           "operand 1 to spv_selection_merge must be a basic block");
    MIB.addMBB(I.getOperand(1).getMBB());
    MIB.addImm(getSelectionOperandForImm(I.getOperand(2).getImm()));
    return MIB.constrainAllUses(TII, TRI, RBI);
  }
  case Intrinsic::spv_cmpxchg:
    return selectAtomicCmpXchg(ResVReg, ResType, I);
  case Intrinsic::spv_unreachable:
    return BuildMI(BB, I, I.getDebugLoc(), TII.get(SPIRV::OpUnreachable))
        .constrainAllUses(TII, TRI, RBI);
  case Intrinsic::spv_alloca:
    return selectFrameIndex(ResVReg, ResType, I);
  case Intrinsic::spv_alloca_array:
    return selectAllocaArray(ResVReg, ResType, I);
  case Intrinsic::spv_assume:
    if (STI.canUseExtension(SPIRV::Extension::SPV_KHR_expect_assume))
      return BuildMI(BB, I, I.getDebugLoc(), TII.get(SPIRV::OpAssumeTrueKHR))
          .addUse(I.getOperand(1).getReg())
          .constrainAllUses(TII, TRI, RBI);
    break;
  case Intrinsic::spv_expect:
    if (STI.canUseExtension(SPIRV::Extension::SPV_KHR_expect_assume))
      return BuildMI(BB, I, I.getDebugLoc(), TII.get(SPIRV::OpExpectKHR))
          .addDef(ResVReg)
          .addUse(GR.getSPIRVTypeID(ResType))
          .addUse(I.getOperand(2).getReg())
          .addUse(I.getOperand(3).getReg())
          .constrainAllUses(TII, TRI, RBI);
    break;
  case Intrinsic::arithmetic_fence:
    if (STI.canUseExtension(SPIRV::Extension::SPV_EXT_arithmetic_fence))
      return BuildMI(BB, I, I.getDebugLoc(),
                     TII.get(SPIRV::OpArithmeticFenceEXT))
          .addDef(ResVReg)
          .addUse(GR.getSPIRVTypeID(ResType))
          .addUse(I.getOperand(2).getReg())
          .constrainAllUses(TII, TRI, RBI);
    else
      return BuildCOPY(ResVReg, I.getOperand(2).getReg(), I);
    break;
  case Intrinsic::spv_thread_id:
    // The HLSL SV_DispatchThreadID semantic is lowered to llvm.spv.thread.id
    // intrinsic in LLVM IR for SPIR-V backend.
    //
    // In SPIR-V backend, llvm.spv.thread.id is now correctly translated to a
    // `GlobalInvocationId` builtin variable
    return loadVec3BuiltinInputID(SPIRV::BuiltIn::GlobalInvocationId, ResVReg,
                                  ResType, I);
  case Intrinsic::spv_thread_id_in_group:
    // The HLSL SV_GroupThreadId semantic is lowered to
    // llvm.spv.thread.id.in.group intrinsic in LLVM IR for SPIR-V backend.
    //
    // In SPIR-V backend, llvm.spv.thread.id.in.group is now correctly
    // translated to a `LocalInvocationId` builtin variable
    return loadVec3BuiltinInputID(SPIRV::BuiltIn::LocalInvocationId, ResVReg,
                                  ResType, I);
  case Intrinsic::spv_group_id:
    // The HLSL SV_GroupId semantic is lowered to
    // llvm.spv.group.id intrinsic in LLVM IR for SPIR-V backend.
    //
    // In SPIR-V backend, llvm.spv.group.id is now translated to a `WorkgroupId`
    // builtin variable
    return loadVec3BuiltinInputID(SPIRV::BuiltIn::WorkgroupId, ResVReg, ResType,
                                  I);
  case Intrinsic::spv_flattened_thread_id_in_group:
    // The HLSL SV_GroupIndex semantic is lowered to
    // llvm.spv.flattened.thread.id.in.group() intrinsic in LLVM IR for SPIR-V
    // backend.
    //
    // In SPIR-V backend, llvm.spv.flattened.thread.id.in.group is translated to
    // a `LocalInvocationIndex` builtin variable
    return loadBuiltinInputID(SPIRV::BuiltIn::LocalInvocationIndex, ResVReg,
                              ResType, I);
  case Intrinsic::spv_workgroup_size:
    return loadVec3BuiltinInputID(SPIRV::BuiltIn::WorkgroupSize, ResVReg,
                                  ResType, I);
  case Intrinsic::spv_global_size:
    return loadVec3BuiltinInputID(SPIRV::BuiltIn::GlobalSize, ResVReg, ResType,
                                  I);
  case Intrinsic::spv_global_offset:
    return loadVec3BuiltinInputID(SPIRV::BuiltIn::GlobalOffset, ResVReg,
                                  ResType, I);
  case Intrinsic::spv_num_workgroups:
    return loadVec3BuiltinInputID(SPIRV::BuiltIn::NumWorkgroups, ResVReg,
                                  ResType, I);
  case Intrinsic::spv_subgroup_size:
    return loadBuiltinInputID(SPIRV::BuiltIn::SubgroupSize, ResVReg, ResType,
                              I);
  case Intrinsic::spv_num_subgroups:
    return loadBuiltinInputID(SPIRV::BuiltIn::NumSubgroups, ResVReg, ResType,
                              I);
  case Intrinsic::spv_subgroup_id:
    return loadBuiltinInputID(SPIRV::BuiltIn::SubgroupId, ResVReg, ResType, I);
  case Intrinsic::spv_subgroup_local_invocation_id:
    return loadBuiltinInputID(SPIRV::BuiltIn::SubgroupLocalInvocationId,
                              ResVReg, ResType, I);
  case Intrinsic::spv_subgroup_max_size:
    return loadBuiltinInputID(SPIRV::BuiltIn::SubgroupMaxSize, ResVReg, ResType,
                              I);
  case Intrinsic::spv_fdot:
    return selectFloatDot(ResVReg, ResType, I);
  case Intrinsic::spv_udot:
  case Intrinsic::spv_sdot:
    if (STI.canUseExtension(SPIRV::Extension::SPV_KHR_integer_dot_product) ||
        STI.isAtLeastSPIRVVer(VersionTuple(1, 6)))
      return selectIntegerDot(ResVReg, ResType, I,
                              /*Signed=*/IID == Intrinsic::spv_sdot);
    return selectIntegerDotExpansion(ResVReg, ResType, I);
  case Intrinsic::spv_dot4add_i8packed:
    if (STI.canUseExtension(SPIRV::Extension::SPV_KHR_integer_dot_product) ||
        STI.isAtLeastSPIRVVer(VersionTuple(1, 6)))
      return selectDot4AddPacked<true>(ResVReg, ResType, I);
    return selectDot4AddPackedExpansion<true>(ResVReg, ResType, I);
  case Intrinsic::spv_dot4add_u8packed:
    if (STI.canUseExtension(SPIRV::Extension::SPV_KHR_integer_dot_product) ||
        STI.isAtLeastSPIRVVer(VersionTuple(1, 6)))
      return selectDot4AddPacked<false>(ResVReg, ResType, I);
    return selectDot4AddPackedExpansion<false>(ResVReg, ResType, I);
  case Intrinsic::spv_all:
    return selectAll(ResVReg, ResType, I);
  case Intrinsic::spv_any:
    return selectAny(ResVReg, ResType, I);
  case Intrinsic::spv_cross:
    return selectExtInst(ResVReg, ResType, I, CL::cross, GL::Cross);
  case Intrinsic::spv_distance:
    return selectExtInst(ResVReg, ResType, I, CL::distance, GL::Distance);
  case Intrinsic::spv_lerp:
    return selectExtInst(ResVReg, ResType, I, CL::mix, GL::FMix);
  case Intrinsic::spv_length:
    return selectExtInst(ResVReg, ResType, I, CL::length, GL::Length);
  case Intrinsic::spv_degrees:
    return selectExtInst(ResVReg, ResType, I, CL::degrees, GL::Degrees);
  case Intrinsic::spv_faceforward:
    return selectExtInst(ResVReg, ResType, I, GL::FaceForward);
  case Intrinsic::spv_frac:
    return selectExtInst(ResVReg, ResType, I, CL::fract, GL::Fract);
  case Intrinsic::spv_isinf:
    return selectOpIsInf(ResVReg, ResType, I);
  case Intrinsic::spv_isnan:
    return selectOpIsNan(ResVReg, ResType, I);
  case Intrinsic::spv_normalize:
    return selectExtInst(ResVReg, ResType, I, CL::normalize, GL::Normalize);
  case Intrinsic::spv_refract:
    return selectExtInst(ResVReg, ResType, I, GL::Refract);
  case Intrinsic::spv_reflect:
    return selectExtInst(ResVReg, ResType, I, GL::Reflect);
  case Intrinsic::spv_rsqrt:
    return selectExtInst(ResVReg, ResType, I, CL::rsqrt, GL::InverseSqrt);
  case Intrinsic::spv_sign:
    return selectSign(ResVReg, ResType, I);
  case Intrinsic::spv_smoothstep:
    return selectExtInst(ResVReg, ResType, I, CL::smoothstep, GL::SmoothStep);
  case Intrinsic::spv_firstbituhigh: // There is no CL equivalent of FindUMsb
    return selectFirstBitHigh(ResVReg, ResType, I, /*IsSigned=*/false);
  case Intrinsic::spv_firstbitshigh: // There is no CL equivalent of FindSMsb
    return selectFirstBitHigh(ResVReg, ResType, I, /*IsSigned=*/true);
  case Intrinsic::spv_firstbitlow: // There is no CL equivlent of FindILsb
    return selectFirstBitLow(ResVReg, ResType, I);
  case Intrinsic::spv_group_memory_barrier_with_group_sync: {
    bool Result = true;
    auto MemSemConstant =
        buildI32Constant(SPIRV::MemorySemantics::SequentiallyConsistent, I);
    Register MemSemReg = MemSemConstant.first;
    Result &= MemSemConstant.second;
    auto ScopeConstant = buildI32Constant(SPIRV::Scope::Workgroup, I);
    Register ScopeReg = ScopeConstant.first;
    Result &= ScopeConstant.second;
    MachineBasicBlock &BB = *I.getParent();
    return Result &&
           BuildMI(BB, I, I.getDebugLoc(), TII.get(SPIRV::OpControlBarrier))
               .addUse(ScopeReg)
               .addUse(ScopeReg)
               .addUse(MemSemReg)
               .constrainAllUses(TII, TRI, RBI);
  }
  case Intrinsic::spv_generic_cast_to_ptr_explicit: {
    Register PtrReg = I.getOperand(I.getNumExplicitDefs() + 1).getReg();
    SPIRV::StorageClass::StorageClass ResSC =
        GR.getPointerStorageClass(ResType);
    if (!isGenericCastablePtr(ResSC))
      report_fatal_error("The target storage class is not castable from the "
                         "Generic storage class");
    return BuildMI(BB, I, I.getDebugLoc(),
                   TII.get(SPIRV::OpGenericCastToPtrExplicit))
        .addDef(ResVReg)
        .addUse(GR.getSPIRVTypeID(ResType))
        .addUse(PtrReg)
        .addImm(ResSC)
        .constrainAllUses(TII, TRI, RBI);
  }
  case Intrinsic::spv_lifetime_start:
  case Intrinsic::spv_lifetime_end: {
    unsigned Op = IID == Intrinsic::spv_lifetime_start ? SPIRV::OpLifetimeStart
                                                       : SPIRV::OpLifetimeStop;
    int64_t Size = I.getOperand(I.getNumExplicitDefs() + 1).getImm();
    Register PtrReg = I.getOperand(I.getNumExplicitDefs() + 2).getReg();
    if (Size == -1)
      Size = 0;
    return BuildMI(BB, I, I.getDebugLoc(), TII.get(Op))
        .addUse(PtrReg)
        .addImm(Size)
        .constrainAllUses(TII, TRI, RBI);
  }
  case Intrinsic::spv_saturate:
    return selectSaturate(ResVReg, ResType, I);
  case Intrinsic::spv_nclamp:
    return selectExtInst(ResVReg, ResType, I, CL::fclamp, GL::NClamp);
  case Intrinsic::spv_uclamp:
    return selectExtInst(ResVReg, ResType, I, CL::u_clamp, GL::UClamp);
  case Intrinsic::spv_sclamp:
    return selectExtInst(ResVReg, ResType, I, CL::s_clamp, GL::SClamp);
  case Intrinsic::spv_wave_active_countbits:
    return selectWaveActiveCountBits(ResVReg, ResType, I);
  case Intrinsic::spv_wave_all:
    return selectWaveOpInst(ResVReg, ResType, I, SPIRV::OpGroupNonUniformAll);
  case Intrinsic::spv_wave_any:
    return selectWaveOpInst(ResVReg, ResType, I, SPIRV::OpGroupNonUniformAny);
  case Intrinsic::spv_wave_is_first_lane:
    return selectWaveOpInst(ResVReg, ResType, I, SPIRV::OpGroupNonUniformElect);
  case Intrinsic::spv_wave_reduce_umax:
    return selectWaveReduceMax(ResVReg, ResType, I, /*IsUnsigned*/ true);
  case Intrinsic::spv_wave_reduce_max:
    return selectWaveReduceMax(ResVReg, ResType, I, /*IsUnsigned*/ false);
  case Intrinsic::spv_wave_reduce_sum:
    return selectWaveReduceSum(ResVReg, ResType, I);
  case Intrinsic::spv_wave_readlane:
    return selectWaveOpInst(ResVReg, ResType, I,
                            SPIRV::OpGroupNonUniformShuffle);
  case Intrinsic::spv_step:
    return selectExtInst(ResVReg, ResType, I, CL::step, GL::Step);
  case Intrinsic::spv_radians:
    return selectExtInst(ResVReg, ResType, I, CL::radians, GL::Radians);
  // Discard intrinsics which we do not expect to actually represent code after
  // lowering or intrinsics which are not implemented but should not crash when
  // found in a customer's LLVM IR input.
  case Intrinsic::instrprof_increment:
  case Intrinsic::instrprof_increment_step:
  case Intrinsic::instrprof_value_profile:
    break;
  // Discard internal intrinsics.
  case Intrinsic::spv_value_md:
    break;
  case Intrinsic::spv_resource_handlefrombinding: {
    return selectHandleFromBinding(ResVReg, ResType, I);
  }
  case Intrinsic::spv_resource_counterhandlefrombinding:
    return selectCounterHandleFromBinding(ResVReg, ResType, I);
  case Intrinsic::spv_resource_updatecounter:
    return selectUpdateCounter(ResVReg, ResType, I);
  case Intrinsic::spv_resource_store_typedbuffer: {
    return selectImageWriteIntrinsic(I);
  }
  case Intrinsic::spv_resource_load_typedbuffer: {
    return selectReadImageIntrinsic(ResVReg, ResType, I);
  }
  case Intrinsic::spv_resource_getpointer: {
    return selectResourceGetPointer(ResVReg, ResType, I);
  }
  case Intrinsic::spv_discard: {
    return selectDiscard(ResVReg, ResType, I);
  }
  default: {
    std::string DiagMsg;
    raw_string_ostream OS(DiagMsg);
    I.print(OS);
    DiagMsg = "Intrinsic selection not implemented: " + DiagMsg;
    report_fatal_error(DiagMsg.c_str(), false);
  }
  }
  return true;
}

bool SPIRVInstructionSelector::selectHandleFromBinding(Register &ResVReg,
                                                       const SPIRVType *ResType,
                                                       MachineInstr &I) const {
  // The images need to be loaded in the same basic block as their use. We defer
  // loading the image to the intrinsic that uses it.
  if (ResType->getOpcode() == SPIRV::OpTypeImage)
    return true;

  return loadHandleBeforePosition(ResVReg, GR.getSPIRVTypeForVReg(ResVReg),
                                  *cast<GIntrinsic>(&I), I);
}

bool SPIRVInstructionSelector::selectCounterHandleFromBinding(
    Register &ResVReg, const SPIRVType *ResType, MachineInstr &I) const {
  auto &Intr = cast<GIntrinsic>(I);
  assert(Intr.getIntrinsicID() ==
         Intrinsic::spv_resource_counterhandlefrombinding);

  // Extract information from the intrinsic call.
  Register MainHandleReg = Intr.getOperand(2).getReg();
  auto *MainHandleDef = cast<GIntrinsic>(getVRegDef(*MRI, MainHandleReg));
  assert(MainHandleDef->getIntrinsicID() ==
         Intrinsic::spv_resource_handlefrombinding);

  uint32_t Set = getIConstVal(Intr.getOperand(4).getReg(), MRI);
  uint32_t Binding = getIConstVal(Intr.getOperand(3).getReg(), MRI);
  uint32_t ArraySize = getIConstVal(MainHandleDef->getOperand(4).getReg(), MRI);
  Register IndexReg = MainHandleDef->getOperand(5).getReg();
  const bool IsNonUniform = false;
  std::string CounterName =
      getStringValueFromReg(MainHandleDef->getOperand(6).getReg(), *MRI) +
      ".counter";

  // Create the counter variable.
  MachineIRBuilder MIRBuilder(I);
  Register CounterVarReg = buildPointerToResource(
      GR.getPointeeType(ResType), GR.getPointerStorageClass(ResType), Set,
      Binding, ArraySize, IndexReg, IsNonUniform, CounterName, MIRBuilder);

  return BuildCOPY(ResVReg, CounterVarReg, I);
}

bool SPIRVInstructionSelector::selectUpdateCounter(Register &ResVReg,
                                                   const SPIRVType *ResType,
                                                   MachineInstr &I) const {
  auto &Intr = cast<GIntrinsic>(I);
  assert(Intr.getIntrinsicID() == Intrinsic::spv_resource_updatecounter);

  Register CounterHandleReg = Intr.getOperand(2).getReg();
  Register IncrReg = Intr.getOperand(3).getReg();

  // The counter handle is a pointer to the counter variable (which is a struct
  // containing an i32). We need to get a pointer to that i32 member to do the
  // atomic operation.
#ifndef NDEBUG
  SPIRVType *CounterVarType = GR.getSPIRVTypeForVReg(CounterHandleReg);
  SPIRVType *CounterVarPointeeType = GR.getPointeeType(CounterVarType);
  assert(CounterVarPointeeType &&
         CounterVarPointeeType->getOpcode() == SPIRV::OpTypeStruct &&
         "Counter variable must be a struct");
  assert(GR.getPointerStorageClass(CounterVarType) ==
             SPIRV::StorageClass::StorageBuffer &&
         "Counter variable must be in the storage buffer storage class");
  assert(CounterVarPointeeType->getNumOperands() == 2 &&
         "Counter variable must have exactly 1 member in the struct");
  const SPIRVType *MemberType =
      GR.getSPIRVTypeForVReg(CounterVarPointeeType->getOperand(1).getReg());
  assert(MemberType->getOpcode() == SPIRV::OpTypeInt &&
         "Counter variable struct must have a single i32 member");
#endif

  // The struct has a single i32 member.
  MachineIRBuilder MIRBuilder(I);
  const Type *LLVMIntType =
      Type::getInt32Ty(I.getMF()->getFunction().getContext());

  SPIRVType *IntPtrType = GR.getOrCreateSPIRVPointerType(
      LLVMIntType, MIRBuilder, SPIRV::StorageClass::StorageBuffer);

  auto Zero = buildI32Constant(0, I);
  if (!Zero.second)
    return false;

  Register PtrToCounter =
      MRI->createVirtualRegister(GR.getRegClass(IntPtrType));
  if (!BuildMI(*I.getParent(), I, I.getDebugLoc(),
               TII.get(SPIRV::OpAccessChain))
           .addDef(PtrToCounter)
           .addUse(GR.getSPIRVTypeID(IntPtrType))
           .addUse(CounterHandleReg)
           .addUse(Zero.first)
           .constrainAllUses(TII, TRI, RBI)) {
    return false;
  }

  // For UAV/SSBO counters, the scope is Device. The counter variable is not
  // used as a flag. So the memory semantics can be None.
  auto Scope = buildI32Constant(SPIRV::Scope::Device, I);
  if (!Scope.second)
    return false;
  auto Semantics = buildI32Constant(SPIRV::MemorySemantics::None, I);
  if (!Semantics.second)
    return false;

  int64_t IncrVal = getIConstValSext(IncrReg, MRI);
  auto Incr = buildI32Constant(static_cast<uint32_t>(IncrVal), I);
  if (!Incr.second)
    return false;

  Register AtomicRes = MRI->createVirtualRegister(GR.getRegClass(ResType));
  if (!BuildMI(*I.getParent(), I, I.getDebugLoc(), TII.get(SPIRV::OpAtomicIAdd))
           .addDef(AtomicRes)
           .addUse(GR.getSPIRVTypeID(ResType))
           .addUse(PtrToCounter)
           .addUse(Scope.first)
           .addUse(Semantics.first)
           .addUse(Incr.first)
           .constrainAllUses(TII, TRI, RBI)) {
    return false;
  }
  if (IncrVal >= 0) {
    return BuildCOPY(ResVReg, AtomicRes, I);
  }

  // In HLSL, IncrementCounter returns the value *before* the increment, while
  // DecrementCounter returns the value *after* the decrement. Both are lowered
  // to the same atomic intrinsic which returns the value *before* the
  // operation. So for decrements (negative IncrVal), we must subtract the
  // increment value from the result to get the post-decrement value.
  return BuildMI(*I.getParent(), I, I.getDebugLoc(), TII.get(SPIRV::OpIAddS))
      .addDef(ResVReg)
      .addUse(GR.getSPIRVTypeID(ResType))
      .addUse(AtomicRes)
      .addUse(Incr.first)
      .constrainAllUses(TII, TRI, RBI);
}
bool SPIRVInstructionSelector::selectReadImageIntrinsic(
    Register &ResVReg, const SPIRVType *ResType, MachineInstr &I) const {

  // If the load of the image is in a different basic block, then
  // this will generate invalid code. A proper solution is to move
  // the OpLoad from selectHandleFromBinding here. However, to do
  // that we will need to change the return type of the intrinsic.
  // We will do that when we can, but for now trying to move forward with other
  // issues.
  Register ImageReg = I.getOperand(2).getReg();
  auto *ImageDef = cast<GIntrinsic>(getVRegDef(*MRI, ImageReg));
  Register NewImageReg = MRI->createVirtualRegister(MRI->getRegClass(ImageReg));
  if (!loadHandleBeforePosition(NewImageReg, GR.getSPIRVTypeForVReg(ImageReg),
                                *ImageDef, I)) {
    return false;
  }

  Register IdxReg = I.getOperand(3).getReg();
  DebugLoc Loc = I.getDebugLoc();
  MachineInstr &Pos = I;

  return generateImageRead(ResVReg, ResType, NewImageReg, IdxReg, Loc, Pos);
}

bool SPIRVInstructionSelector::generateImageRead(Register &ResVReg,
                                                 const SPIRVType *ResType,
                                                 Register ImageReg,
                                                 Register IdxReg, DebugLoc Loc,
                                                 MachineInstr &Pos) const {
  SPIRVType *ImageType = GR.getSPIRVTypeForVReg(ImageReg);
  assert(ImageType && ImageType->getOpcode() == SPIRV::OpTypeImage &&
         "ImageReg is not an image type.");
  bool IsSignedInteger =
      sampledTypeIsSignedInteger(GR.getTypeForSPIRVType(ImageType));

  uint64_t ResultSize = GR.getScalarOrVectorComponentCount(ResType);
  if (ResultSize == 4) {
    auto BMI = BuildMI(*Pos.getParent(), Pos, Loc, TII.get(SPIRV::OpImageRead))
                   .addDef(ResVReg)
                   .addUse(GR.getSPIRVTypeID(ResType))
                   .addUse(ImageReg)
                   .addUse(IdxReg);

    if (IsSignedInteger)
      BMI.addImm(0x1000); // SignExtend
    return BMI.constrainAllUses(TII, TRI, RBI);
  }

  SPIRVType *ReadType = widenTypeToVec4(ResType, Pos);
  Register ReadReg = MRI->createVirtualRegister(GR.getRegClass(ReadType));
  auto BMI = BuildMI(*Pos.getParent(), Pos, Loc, TII.get(SPIRV::OpImageRead))
                 .addDef(ReadReg)
                 .addUse(GR.getSPIRVTypeID(ReadType))
                 .addUse(ImageReg)
                 .addUse(IdxReg);
  if (IsSignedInteger)
    BMI.addImm(0x1000); // SignExtend
  bool Succeed = BMI.constrainAllUses(TII, TRI, RBI);
  if (!Succeed)
    return false;

  if (ResultSize == 1) {
    return BuildMI(*Pos.getParent(), Pos, Loc,
                   TII.get(SPIRV::OpCompositeExtract))
        .addDef(ResVReg)
        .addUse(GR.getSPIRVTypeID(ResType))
        .addUse(ReadReg)
        .addImm(0)
        .constrainAllUses(TII, TRI, RBI);
  }
  return extractSubvector(ResVReg, ResType, ReadReg, Pos);
}

bool SPIRVInstructionSelector::selectResourceGetPointer(
    Register &ResVReg, const SPIRVType *ResType, MachineInstr &I) const {
  Register ResourcePtr = I.getOperand(2).getReg();
  SPIRVType *RegType = GR.getSPIRVTypeForVReg(ResourcePtr, I.getMF());
  if (RegType->getOpcode() == SPIRV::OpTypeImage) {
    // For texel buffers, the index into the image is part of the OpImageRead or
    // OpImageWrite instructions. So we will do nothing in this case. This
    // intrinsic will be combined with the load or store when selecting the load
    // or store.
    return true;
  }

  assert(ResType->getOpcode() == SPIRV::OpTypePointer);
  MachineIRBuilder MIRBuilder(I);

  Register IndexReg = I.getOperand(3).getReg();
  Register ZeroReg =
      buildZerosVal(GR.getOrCreateSPIRVIntegerType(32, I, TII), I);
  return BuildMI(*I.getParent(), I, I.getDebugLoc(),
                 TII.get(SPIRV::OpAccessChain))
      .addDef(ResVReg)
      .addUse(GR.getSPIRVTypeID(ResType))
      .addUse(ResourcePtr)
      .addUse(ZeroReg)
      .addUse(IndexReg)
      .constrainAllUses(TII, TRI, RBI);
}

bool SPIRVInstructionSelector::extractSubvector(
    Register &ResVReg, const SPIRVType *ResType, Register &ReadReg,
    MachineInstr &InsertionPoint) const {
  SPIRVType *InputType = GR.getResultType(ReadReg);
  [[maybe_unused]] uint64_t InputSize =
      GR.getScalarOrVectorComponentCount(InputType);
  uint64_t ResultSize = GR.getScalarOrVectorComponentCount(ResType);
  assert(InputSize > 1 && "The input must be a vector.");
  assert(ResultSize > 1 && "The result must be a vector.");
  assert(ResultSize < InputSize &&
         "Cannot extract more element than there are in the input.");
  SmallVector<Register> ComponentRegisters;
  SPIRVType *ScalarType = GR.getScalarOrVectorComponentType(ResType);
  const TargetRegisterClass *ScalarRegClass = GR.getRegClass(ScalarType);
  for (uint64_t I = 0; I < ResultSize; I++) {
    Register ComponentReg = MRI->createVirtualRegister(ScalarRegClass);
    bool Succeed = BuildMI(*InsertionPoint.getParent(), InsertionPoint,
                           InsertionPoint.getDebugLoc(),
                           TII.get(SPIRV::OpCompositeExtract))
                       .addDef(ComponentReg)
                       .addUse(ScalarType->getOperand(0).getReg())
                       .addUse(ReadReg)
                       .addImm(I)
                       .constrainAllUses(TII, TRI, RBI);
    if (!Succeed)
      return false;
    ComponentRegisters.emplace_back(ComponentReg);
  }

  MachineInstrBuilder MIB = BuildMI(*InsertionPoint.getParent(), InsertionPoint,
                                    InsertionPoint.getDebugLoc(),
                                    TII.get(SPIRV::OpCompositeConstruct))
                                .addDef(ResVReg)
                                .addUse(GR.getSPIRVTypeID(ResType));

  for (Register ComponentReg : ComponentRegisters)
    MIB.addUse(ComponentReg);
  return MIB.constrainAllUses(TII, TRI, RBI);
}

bool SPIRVInstructionSelector::selectImageWriteIntrinsic(
    MachineInstr &I) const {
  // If the load of the image is in a different basic block, then
  // this will generate invalid code. A proper solution is to move
  // the OpLoad from selectHandleFromBinding here. However, to do
  // that we will need to change the return type of the intrinsic.
  // We will do that when we can, but for now trying to move forward with other
  // issues.
  Register ImageReg = I.getOperand(1).getReg();
  auto *ImageDef = cast<GIntrinsic>(getVRegDef(*MRI, ImageReg));
  Register NewImageReg = MRI->createVirtualRegister(MRI->getRegClass(ImageReg));
  if (!loadHandleBeforePosition(NewImageReg, GR.getSPIRVTypeForVReg(ImageReg),
                                *ImageDef, I)) {
    return false;
  }

  Register CoordinateReg = I.getOperand(2).getReg();
  Register DataReg = I.getOperand(3).getReg();
  assert(GR.getResultType(DataReg)->getOpcode() == SPIRV::OpTypeVector);
  assert(GR.getScalarOrVectorComponentCount(GR.getResultType(DataReg)) == 4);
  return BuildMI(*I.getParent(), I, I.getDebugLoc(),
                 TII.get(SPIRV::OpImageWrite))
      .addUse(NewImageReg)
      .addUse(CoordinateReg)
      .addUse(DataReg)
      .constrainAllUses(TII, TRI, RBI);
}

Register SPIRVInstructionSelector::buildPointerToResource(
    const SPIRVType *SpirvResType, SPIRV::StorageClass::StorageClass SC,
    uint32_t Set, uint32_t Binding, uint32_t ArraySize, Register IndexReg,
    bool IsNonUniform, StringRef Name, MachineIRBuilder MIRBuilder) const {
  const Type *ResType = GR.getTypeForSPIRVType(SpirvResType);
  if (ArraySize == 1) {
    SPIRVType *PtrType =
        GR.getOrCreateSPIRVPointerType(ResType, MIRBuilder, SC);
    assert(GR.getPointeeType(PtrType) == SpirvResType &&
           "SpirvResType did not have an explicit layout.");
    return GR.getOrCreateGlobalVariableWithBinding(PtrType, Set, Binding, Name,
                                                   MIRBuilder);
  }

  const Type *VarType = ArrayType::get(const_cast<Type *>(ResType), ArraySize);
  SPIRVType *VarPointerType =
      GR.getOrCreateSPIRVPointerType(VarType, MIRBuilder, SC);
  Register VarReg = GR.getOrCreateGlobalVariableWithBinding(
      VarPointerType, Set, Binding, Name, MIRBuilder);

  SPIRVType *ResPointerType =
      GR.getOrCreateSPIRVPointerType(ResType, MIRBuilder, SC);

  Register AcReg = MRI->createVirtualRegister(GR.getRegClass(ResPointerType));
  if (IsNonUniform) {
    // It is unclear which value needs to be marked an non-uniform, so both
    // the index and the access changed are decorated as non-uniform.
    buildOpDecorate(IndexReg, MIRBuilder, SPIRV::Decoration::NonUniformEXT, {});
    buildOpDecorate(AcReg, MIRBuilder, SPIRV::Decoration::NonUniformEXT, {});
  }

  MIRBuilder.buildInstr(SPIRV::OpAccessChain)
      .addDef(AcReg)
      .addUse(GR.getSPIRVTypeID(ResPointerType))
      .addUse(VarReg)
      .addUse(IndexReg);

  return AcReg;
}

bool SPIRVInstructionSelector::selectFirstBitSet16(
    Register ResVReg, const SPIRVType *ResType, MachineInstr &I,
    unsigned ExtendOpcode, unsigned BitSetOpcode) const {
  Register ExtReg = MRI->createVirtualRegister(GR.getRegClass(ResType));
  bool Result = selectOpWithSrcs(ExtReg, ResType, I, {I.getOperand(2).getReg()},
                                 ExtendOpcode);

  return Result &&
         selectFirstBitSet32(ResVReg, ResType, I, ExtReg, BitSetOpcode);
}

bool SPIRVInstructionSelector::selectFirstBitSet32(
    Register ResVReg, const SPIRVType *ResType, MachineInstr &I,
    Register SrcReg, unsigned BitSetOpcode) const {
  return BuildMI(*I.getParent(), I, I.getDebugLoc(), TII.get(SPIRV::OpExtInst))
      .addDef(ResVReg)
      .addUse(GR.getSPIRVTypeID(ResType))
      .addImm(static_cast<uint32_t>(SPIRV::InstructionSet::GLSL_std_450))
      .addImm(BitSetOpcode)
      .addUse(SrcReg)
      .constrainAllUses(TII, TRI, RBI);
}

bool SPIRVInstructionSelector::selectFirstBitSet64Overflow(
    Register ResVReg, const SPIRVType *ResType, MachineInstr &I,
    Register SrcReg, unsigned BitSetOpcode, bool SwapPrimarySide) const {

  // SPIR-V allow vectors of size 2,3,4 only. Calling with a larger vectors
  // requires creating a param register and return register with an invalid
  // vector size. If that is resolved, then this function can be used for
  // vectors of any component size.
  unsigned ComponentCount = GR.getScalarOrVectorComponentCount(ResType);
  assert(ComponentCount < 5 && "Vec 5+ will generate invalid SPIR-V ops");

  MachineIRBuilder MIRBuilder(I);
  SPIRVType *BaseType = GR.retrieveScalarOrVectorIntType(ResType);
  SPIRVType *I64Type = GR.getOrCreateSPIRVIntegerType(64, MIRBuilder);
  SPIRVType *I64x2Type =
      GR.getOrCreateSPIRVVectorType(I64Type, 2, MIRBuilder, false);
  SPIRVType *Vec2ResType =
      GR.getOrCreateSPIRVVectorType(BaseType, 2, MIRBuilder, false);

  std::vector<Register> PartialRegs;

  // Loops 0, 2, 4, ... but stops one loop early when ComponentCount is odd
  unsigned CurrentComponent = 0;
  for (; CurrentComponent + 1 < ComponentCount; CurrentComponent += 2) {
    // This register holds the firstbitX result for each of the i64x2 vectors
    // extracted from SrcReg
    Register BitSetResult =
        MRI->createVirtualRegister(GR.getRegClass(I64x2Type));

    auto MIB = BuildMI(*I.getParent(), I, I.getDebugLoc(),
                       TII.get(SPIRV::OpVectorShuffle))
                   .addDef(BitSetResult)
                   .addUse(GR.getSPIRVTypeID(I64x2Type))
                   .addUse(SrcReg)
                   .addUse(SrcReg)
                   .addImm(CurrentComponent)
                   .addImm(CurrentComponent + 1);

    if (!MIB.constrainAllUses(TII, TRI, RBI))
      return false;

    Register SubVecBitSetReg =
        MRI->createVirtualRegister(GR.getRegClass(Vec2ResType));

    if (!selectFirstBitSet64(SubVecBitSetReg, Vec2ResType, I, BitSetResult,
                             BitSetOpcode, SwapPrimarySide))
      return false;

    PartialRegs.push_back(SubVecBitSetReg);
  }

  // On odd component counts we need to handle one more component
  if (CurrentComponent != ComponentCount) {
    bool ZeroAsNull = !STI.isShader();
    Register FinalElemReg = MRI->createVirtualRegister(GR.getRegClass(I64Type));
    Register ConstIntLastIdx = GR.getOrCreateConstInt(
        ComponentCount - 1, I, BaseType, TII, ZeroAsNull);

    if (!selectOpWithSrcs(FinalElemReg, I64Type, I, {SrcReg, ConstIntLastIdx},
                          SPIRV::OpVectorExtractDynamic))
      return false;

    Register FinalElemBitSetReg =
        MRI->createVirtualRegister(GR.getRegClass(BaseType));

    if (!selectFirstBitSet64(FinalElemBitSetReg, BaseType, I, FinalElemReg,
                             BitSetOpcode, SwapPrimarySide))
      return false;

    PartialRegs.push_back(FinalElemBitSetReg);
  }

  // Join all the resulting registers back into the return type in order
  // (ie i32x2, i32x2, i32x1 -> i32x5)
  return selectOpWithSrcs(ResVReg, ResType, I, std::move(PartialRegs),
                          SPIRV::OpCompositeConstruct);
}

bool SPIRVInstructionSelector::selectFirstBitSet64(
    Register ResVReg, const SPIRVType *ResType, MachineInstr &I,
    Register SrcReg, unsigned BitSetOpcode, bool SwapPrimarySide) const {
  unsigned ComponentCount = GR.getScalarOrVectorComponentCount(ResType);
  SPIRVType *BaseType = GR.retrieveScalarOrVectorIntType(ResType);
  bool ZeroAsNull = !STI.isShader();
  Register ConstIntZero =
      GR.getOrCreateConstInt(0, I, BaseType, TII, ZeroAsNull);
  Register ConstIntOne =
      GR.getOrCreateConstInt(1, I, BaseType, TII, ZeroAsNull);

  // SPIRV doesn't support vectors with more than 4 components. Since the
  // algoritm below converts i64 -> i32x2 and i64x4 -> i32x8 it can only
  // operate on vectors with 2 or less components. When largers vectors are
  // seen. Split them, recurse, then recombine them.
  if (ComponentCount > 2) {
    return selectFirstBitSet64Overflow(ResVReg, ResType, I, SrcReg,
                                       BitSetOpcode, SwapPrimarySide);
  }

  // 1. Split int64 into 2 pieces using a bitcast
  MachineIRBuilder MIRBuilder(I);
  SPIRVType *PostCastType = GR.getOrCreateSPIRVVectorType(
      BaseType, 2 * ComponentCount, MIRBuilder, false);
  Register BitcastReg =
      MRI->createVirtualRegister(GR.getRegClass(PostCastType));

  if (!selectOpWithSrcs(BitcastReg, PostCastType, I, {SrcReg},
                        SPIRV::OpBitcast))
    return false;

  // 2. Find the first set bit from the primary side for all the pieces in #1
  Register FBSReg = MRI->createVirtualRegister(GR.getRegClass(PostCastType));
  if (!selectFirstBitSet32(FBSReg, PostCastType, I, BitcastReg, BitSetOpcode))
    return false;

  // 3. Split result vector into high bits and low bits
  Register HighReg = MRI->createVirtualRegister(GR.getRegClass(ResType));
  Register LowReg = MRI->createVirtualRegister(GR.getRegClass(ResType));

  bool IsScalarRes = ResType->getOpcode() != SPIRV::OpTypeVector;
  if (IsScalarRes) {
    // if scalar do a vector extract
    if (!selectOpWithSrcs(HighReg, ResType, I, {FBSReg, ConstIntZero},
                          SPIRV::OpVectorExtractDynamic))
      return false;
    if (!selectOpWithSrcs(LowReg, ResType, I, {FBSReg, ConstIntOne},
                          SPIRV::OpVectorExtractDynamic))
      return false;
  } else {
    // if vector do a shufflevector
    auto MIB = BuildMI(*I.getParent(), I, I.getDebugLoc(),
                       TII.get(SPIRV::OpVectorShuffle))
                   .addDef(HighReg)
                   .addUse(GR.getSPIRVTypeID(ResType))
                   .addUse(FBSReg)
                   // Per the spec, repeat the vector if only one vec is needed
                   .addUse(FBSReg);

    // high bits are stored in even indexes. Extract them from FBSReg
    for (unsigned J = 0; J < ComponentCount * 2; J += 2) {
      MIB.addImm(J);
    }

    if (!MIB.constrainAllUses(TII, TRI, RBI))
      return false;

    MIB = BuildMI(*I.getParent(), I, I.getDebugLoc(),
                  TII.get(SPIRV::OpVectorShuffle))
              .addDef(LowReg)
              .addUse(GR.getSPIRVTypeID(ResType))
              .addUse(FBSReg)
              // Per the spec, repeat the vector if only one vec is needed
              .addUse(FBSReg);

    // low bits are stored in odd indexes. Extract them from FBSReg
    for (unsigned J = 1; J < ComponentCount * 2; J += 2) {
      MIB.addImm(J);
    }
    if (!MIB.constrainAllUses(TII, TRI, RBI))
      return false;
  }

  // 4. Check the result. When primary bits == -1 use secondary, otherwise use
  // primary
  SPIRVType *BoolType = GR.getOrCreateSPIRVBoolType(I, TII);
  Register NegOneReg;
  Register Reg0;
  Register Reg32;
  unsigned SelectOp;
  unsigned AddOp;

  if (IsScalarRes) {
    NegOneReg =
        GR.getOrCreateConstInt((unsigned)-1, I, ResType, TII, ZeroAsNull);
    Reg0 = GR.getOrCreateConstInt(0, I, ResType, TII, ZeroAsNull);
    Reg32 = GR.getOrCreateConstInt(32, I, ResType, TII, ZeroAsNull);
    SelectOp = SPIRV::OpSelectSISCond;
    AddOp = SPIRV::OpIAddS;
  } else {
    BoolType = GR.getOrCreateSPIRVVectorType(BoolType, ComponentCount,
                                             MIRBuilder, false);
    NegOneReg =
        GR.getOrCreateConstVector((unsigned)-1, I, ResType, TII, ZeroAsNull);
    Reg0 = GR.getOrCreateConstVector(0, I, ResType, TII, ZeroAsNull);
    Reg32 = GR.getOrCreateConstVector(32, I, ResType, TII, ZeroAsNull);
    SelectOp = SPIRV::OpSelectVIVCond;
    AddOp = SPIRV::OpIAddV;
  }

  Register PrimaryReg = HighReg;
  Register SecondaryReg = LowReg;
  Register PrimaryShiftReg = Reg32;
  Register SecondaryShiftReg = Reg0;

  // By default the emitted opcodes check for the set bit from the MSB side.
  // Setting SwapPrimarySide checks the set bit from the LSB side
  if (SwapPrimarySide) {
    PrimaryReg = LowReg;
    SecondaryReg = HighReg;
    PrimaryShiftReg = Reg0;
    SecondaryShiftReg = Reg32;
  }

  // Check if the primary bits are == -1
  Register BReg = MRI->createVirtualRegister(GR.getRegClass(BoolType));
  if (!selectOpWithSrcs(BReg, BoolType, I, {PrimaryReg, NegOneReg},
                        SPIRV::OpIEqual))
    return false;

  // Select secondary bits if true in BReg, otherwise primary bits
  Register TmpReg = MRI->createVirtualRegister(GR.getRegClass(ResType));
  if (!selectOpWithSrcs(TmpReg, ResType, I, {BReg, SecondaryReg, PrimaryReg},
                        SelectOp))
    return false;

  // 5. Add 32 when high bits are used, otherwise 0 for low bits
  Register ValReg = MRI->createVirtualRegister(GR.getRegClass(ResType));
  if (!selectOpWithSrcs(ValReg, ResType, I,
                        {BReg, SecondaryShiftReg, PrimaryShiftReg}, SelectOp))
    return false;

  return selectOpWithSrcs(ResVReg, ResType, I, {ValReg, TmpReg}, AddOp);
}

bool SPIRVInstructionSelector::selectFirstBitHigh(Register ResVReg,
                                                  const SPIRVType *ResType,
                                                  MachineInstr &I,
                                                  bool IsSigned) const {
  // FindUMsb and FindSMsb intrinsics only support 32 bit integers
  Register OpReg = I.getOperand(2).getReg();
  SPIRVType *OpType = GR.getSPIRVTypeForVReg(OpReg);
  // zero or sign extend
  unsigned ExtendOpcode = IsSigned ? SPIRV::OpSConvert : SPIRV::OpUConvert;
  unsigned BitSetOpcode = IsSigned ? GL::FindSMsb : GL::FindUMsb;

  switch (GR.getScalarOrVectorBitWidth(OpType)) {
  case 16:
    return selectFirstBitSet16(ResVReg, ResType, I, ExtendOpcode, BitSetOpcode);
  case 32:
    return selectFirstBitSet32(ResVReg, ResType, I, OpReg, BitSetOpcode);
  case 64:
    return selectFirstBitSet64(ResVReg, ResType, I, OpReg, BitSetOpcode,
                               /*SwapPrimarySide=*/false);
  default:
    report_fatal_error(
        "spv_firstbituhigh and spv_firstbitshigh only support 16,32,64 bits.");
  }
}

bool SPIRVInstructionSelector::selectFirstBitLow(Register ResVReg,
                                                 const SPIRVType *ResType,
                                                 MachineInstr &I) const {
  // FindILsb intrinsic only supports 32 bit integers
  Register OpReg = I.getOperand(2).getReg();
  SPIRVType *OpType = GR.getSPIRVTypeForVReg(OpReg);
  // OpUConvert treats the operand bits as an unsigned i16 and zero extends it
  // to an unsigned i32. As this leaves all the least significant bits unchanged
  // so the first set bit from the LSB side doesn't change.
  unsigned ExtendOpcode = SPIRV::OpUConvert;
  unsigned BitSetOpcode = GL::FindILsb;

  switch (GR.getScalarOrVectorBitWidth(OpType)) {
  case 16:
    return selectFirstBitSet16(ResVReg, ResType, I, ExtendOpcode, BitSetOpcode);
  case 32:
    return selectFirstBitSet32(ResVReg, ResType, I, OpReg, BitSetOpcode);
  case 64:
    return selectFirstBitSet64(ResVReg, ResType, I, OpReg, BitSetOpcode,
                               /*SwapPrimarySide=*/true);
  default:
    report_fatal_error("spv_firstbitlow only supports 16,32,64 bits.");
  }
}

bool SPIRVInstructionSelector::selectAllocaArray(Register ResVReg,
                                                 const SPIRVType *ResType,
                                                 MachineInstr &I) const {
  // there was an allocation size parameter to the allocation instruction
  // that is not 1
  MachineBasicBlock &BB = *I.getParent();
  bool Res = BuildMI(BB, I, I.getDebugLoc(),
                     TII.get(SPIRV::OpVariableLengthArrayINTEL))
                 .addDef(ResVReg)
                 .addUse(GR.getSPIRVTypeID(ResType))
                 .addUse(I.getOperand(2).getReg())
                 .constrainAllUses(TII, TRI, RBI);
  if (!STI.isShader()) {
    unsigned Alignment = I.getOperand(3).getImm();
    buildOpDecorate(ResVReg, I, TII, SPIRV::Decoration::Alignment, {Alignment});
  }
  return Res;
}

bool SPIRVInstructionSelector::selectFrameIndex(Register ResVReg,
                                                const SPIRVType *ResType,
                                                MachineInstr &I) const {
  // Change order of instructions if needed: all OpVariable instructions in a
  // function must be the first instructions in the first block
  auto It = getOpVariableMBBIt(I);
  bool Res = BuildMI(*It->getParent(), It, It->getDebugLoc(),
                     TII.get(SPIRV::OpVariable))
                 .addDef(ResVReg)
                 .addUse(GR.getSPIRVTypeID(ResType))
                 .addImm(static_cast<uint32_t>(SPIRV::StorageClass::Function))
                 .constrainAllUses(TII, TRI, RBI);
  if (!STI.isShader()) {
    unsigned Alignment = I.getOperand(2).getImm();
    buildOpDecorate(ResVReg, *It, TII, SPIRV::Decoration::Alignment,
                    {Alignment});
  }
  return Res;
}

bool SPIRVInstructionSelector::selectBranch(MachineInstr &I) const {
  // InstructionSelector walks backwards through the instructions. We can use
  // both a G_BR and a G_BRCOND to create an OpBranchConditional. We hit G_BR
  // first, so can generate an OpBranchConditional here. If there is no
  // G_BRCOND, we just use OpBranch for a regular unconditional branch.
  const MachineInstr *PrevI = I.getPrevNode();
  MachineBasicBlock &MBB = *I.getParent();
  if (PrevI != nullptr && PrevI->getOpcode() == TargetOpcode::G_BRCOND) {
    return BuildMI(MBB, I, I.getDebugLoc(), TII.get(SPIRV::OpBranchConditional))
        .addUse(PrevI->getOperand(0).getReg())
        .addMBB(PrevI->getOperand(1).getMBB())
        .addMBB(I.getOperand(0).getMBB())
        .constrainAllUses(TII, TRI, RBI);
  }
  return BuildMI(MBB, I, I.getDebugLoc(), TII.get(SPIRV::OpBranch))
      .addMBB(I.getOperand(0).getMBB())
      .constrainAllUses(TII, TRI, RBI);
}

bool SPIRVInstructionSelector::selectBranchCond(MachineInstr &I) const {
  // InstructionSelector walks backwards through the instructions. For an
  // explicit conditional branch with no fallthrough, we use both a G_BR and a
  // G_BRCOND to create an OpBranchConditional. We should hit G_BR first, and
  // generate the OpBranchConditional in selectBranch above.
  //
  // If an OpBranchConditional has been generated, we simply return, as the work
  // is alread done. If there is no OpBranchConditional, LLVM must be relying on
  // implicit fallthrough to the next basic block, so we need to create an
  // OpBranchConditional with an explicit "false" argument pointing to the next
  // basic block that LLVM would fall through to.
  const MachineInstr *NextI = I.getNextNode();
  // Check if this has already been successfully selected.
  if (NextI != nullptr && NextI->getOpcode() == SPIRV::OpBranchConditional)
    return true;
  // Must be relying on implicit block fallthrough, so generate an
  // OpBranchConditional with the "next" basic block as the "false" target.
  MachineBasicBlock &MBB = *I.getParent();
  unsigned NextMBBNum = MBB.getNextNode()->getNumber();
  MachineBasicBlock *NextMBB = I.getMF()->getBlockNumbered(NextMBBNum);
  return BuildMI(MBB, I, I.getDebugLoc(), TII.get(SPIRV::OpBranchConditional))
      .addUse(I.getOperand(0).getReg())
      .addMBB(I.getOperand(1).getMBB())
      .addMBB(NextMBB)
      .constrainAllUses(TII, TRI, RBI);
}

bool SPIRVInstructionSelector::selectPhi(Register ResVReg,
                                         const SPIRVType *ResType,
                                         MachineInstr &I) const {
  auto MIB = BuildMI(*I.getParent(), I, I.getDebugLoc(), TII.get(SPIRV::OpPhi))
                 .addDef(ResVReg)
                 .addUse(GR.getSPIRVTypeID(ResType));
  const unsigned NumOps = I.getNumOperands();
  for (unsigned i = 1; i < NumOps; i += 2) {
    MIB.addUse(I.getOperand(i + 0).getReg());
    MIB.addMBB(I.getOperand(i + 1).getMBB());
  }
  bool Res = MIB.constrainAllUses(TII, TRI, RBI);
  MIB->setDesc(TII.get(TargetOpcode::PHI));
  MIB->removeOperand(1);
  return Res;
}

bool SPIRVInstructionSelector::selectGlobalValue(
    Register ResVReg, MachineInstr &I, const MachineInstr *Init) const {
  // FIXME: don't use MachineIRBuilder here, replace it with BuildMI.
  MachineIRBuilder MIRBuilder(I);
  const GlobalValue *GV = I.getOperand(1).getGlobal();
  Type *GVType = toTypedPointer(GR.getDeducedGlobalValueType(GV));

  std::string GlobalIdent;
  if (!GV->hasName()) {
    unsigned &ID = UnnamedGlobalIDs[GV];
    if (ID == 0)
      ID = UnnamedGlobalIDs.size();
    GlobalIdent = "__unnamed_" + Twine(ID).str();
  } else {
    GlobalIdent = GV->getName();
  }

  // Behaviour of functions as operands depends on availability of the
  // corresponding extension (SPV_INTEL_function_pointers):
  // - If there is an extension to operate with functions as operands:
  // We create a proper constant operand and evaluate a correct type for a
  // function pointer.
  // - Without the required extension:
  // We have functions as operands in tests with blocks of instruction e.g. in
  // transcoding/global_block.ll. These operands are not used and should be
  // substituted by zero constants. Their type is expected to be always
  // OpTypePointer Function %uchar.
  if (isa<Function>(GV)) {
    const Constant *ConstVal = GV;
    MachineBasicBlock &BB = *I.getParent();
    Register NewReg = GR.find(ConstVal, GR.CurMF);
    if (!NewReg.isValid()) {
      Register NewReg = ResVReg;
      const Function *GVFun =
          STI.canUseExtension(SPIRV::Extension::SPV_INTEL_function_pointers)
              ? dyn_cast<Function>(GV)
              : nullptr;
      SPIRVType *ResType = GR.getOrCreateSPIRVPointerType(
          GVType, I,
          GVFun ? SPIRV::StorageClass::CodeSectionINTEL
                : addressSpaceToStorageClass(GV->getAddressSpace(), STI));
      if (GVFun) {
        // References to a function via function pointers generate virtual
        // registers without a definition. We will resolve it later, during
        // module analysis stage.
        Register ResTypeReg = GR.getSPIRVTypeID(ResType);
        MachineRegisterInfo *MRI = MIRBuilder.getMRI();
        Register FuncVReg =
            MRI->createGenericVirtualRegister(GR.getRegType(ResType));
        MRI->setRegClass(FuncVReg, &SPIRV::pIDRegClass);
        MachineInstrBuilder MIB1 =
            BuildMI(BB, I, I.getDebugLoc(), TII.get(SPIRV::OpUndef))
                .addDef(FuncVReg)
                .addUse(ResTypeReg);
        MachineInstrBuilder MIB2 =
            BuildMI(BB, I, I.getDebugLoc(),
                    TII.get(SPIRV::OpConstantFunctionPointerINTEL))
                .addDef(NewReg)
                .addUse(ResTypeReg)
                .addUse(FuncVReg);
        GR.add(ConstVal, MIB2);
        // mapping the function pointer to the used Function
        GR.recordFunctionPointer(&MIB2.getInstr()->getOperand(2), GVFun);
        return MIB1.constrainAllUses(TII, TRI, RBI) &&
               MIB2.constrainAllUses(TII, TRI, RBI);
      }
      MachineInstrBuilder MIB3 =
          BuildMI(BB, I, I.getDebugLoc(), TII.get(SPIRV::OpConstantNull))
              .addDef(NewReg)
              .addUse(GR.getSPIRVTypeID(ResType));
      GR.add(ConstVal, MIB3);
      return MIB3.constrainAllUses(TII, TRI, RBI);
    }
    assert(NewReg != ResVReg);
    return BuildCOPY(ResVReg, NewReg, I);
  }
  auto GlobalVar = cast<GlobalVariable>(GV);
  assert(GlobalVar->getName() != "llvm.global.annotations");

  // Skip empty declaration for GVs with initializers till we get the decl with
  // passed initializer.
  if (hasInitializer(GlobalVar) && !Init)
    return true;

  bool HasLnkTy = !GV->hasInternalLinkage() && !GV->hasPrivateLinkage() &&
                  !GV->hasHiddenVisibility();
  SPIRV::LinkageType::LinkageType LnkType =
      GV->isDeclarationForLinker()
          ? SPIRV::LinkageType::Import
          : (GV->hasLinkOnceODRLinkage() &&
                     STI.canUseExtension(SPIRV::Extension::SPV_KHR_linkonce_odr)
                 ? SPIRV::LinkageType::LinkOnceODR
                 : SPIRV::LinkageType::Export);

  const unsigned AddrSpace = GV->getAddressSpace();
  SPIRV::StorageClass::StorageClass StorageClass =
      addressSpaceToStorageClass(AddrSpace, STI);
  SPIRVType *ResType = GR.getOrCreateSPIRVPointerType(GVType, I, StorageClass);
  Register Reg = GR.buildGlobalVariable(
      ResVReg, ResType, GlobalIdent, GV, StorageClass, Init,
      GlobalVar->isConstant(), HasLnkTy, LnkType, MIRBuilder, true);
  return Reg.isValid();
}

bool SPIRVInstructionSelector::selectLog10(Register ResVReg,
                                           const SPIRVType *ResType,
                                           MachineInstr &I) const {
  if (STI.canUseExtInstSet(SPIRV::InstructionSet::OpenCL_std)) {
    return selectExtInst(ResVReg, ResType, I, CL::log10);
  }

  // There is no log10 instruction in the GLSL Extended Instruction set, so it
  // is implemented as:
  // log10(x) = log2(x) * (1 / log2(10))
  //          = log2(x) * 0.30103

  MachineIRBuilder MIRBuilder(I);
  MachineBasicBlock &BB = *I.getParent();

  // Build log2(x).
  Register VarReg = MRI->createVirtualRegister(GR.getRegClass(ResType));
  bool Result =
      BuildMI(BB, I, I.getDebugLoc(), TII.get(SPIRV::OpExtInst))
          .addDef(VarReg)
          .addUse(GR.getSPIRVTypeID(ResType))
          .addImm(static_cast<uint32_t>(SPIRV::InstructionSet::GLSL_std_450))
          .addImm(GL::Log2)
          .add(I.getOperand(1))
          .constrainAllUses(TII, TRI, RBI);

  // Build 0.30103.
  assert(ResType->getOpcode() == SPIRV::OpTypeVector ||
         ResType->getOpcode() == SPIRV::OpTypeFloat);
  // TODO: Add matrix implementation once supported by the HLSL frontend.
  const SPIRVType *SpirvScalarType =
      ResType->getOpcode() == SPIRV::OpTypeVector
          ? GR.getSPIRVTypeForVReg(ResType->getOperand(1).getReg())
          : ResType;
  Register ScaleReg =
      GR.buildConstantFP(APFloat(0.30103f), MIRBuilder, SpirvScalarType);

  // Multiply log2(x) by 0.30103 to get log10(x) result.
  auto Opcode = ResType->getOpcode() == SPIRV::OpTypeVector
                    ? SPIRV::OpVectorTimesScalar
                    : SPIRV::OpFMulS;
  return Result && BuildMI(BB, I, I.getDebugLoc(), TII.get(Opcode))
                       .addDef(ResVReg)
                       .addUse(GR.getSPIRVTypeID(ResType))
                       .addUse(VarReg)
                       .addUse(ScaleReg)
                       .constrainAllUses(TII, TRI, RBI);
}

bool SPIRVInstructionSelector::selectModf(Register ResVReg,
                                          const SPIRVType *ResType,
                                          MachineInstr &I) const {
  // llvm.modf has a single arg --the number to be decomposed-- and returns a
  // struct { restype, restype }, while OpenCLLIB::modf has two args --the
  // number to be decomposed and a pointer--, returns the fractional part and
  // the integral part is stored in the pointer argument. Therefore, we can't
  // use directly the OpenCLLIB::modf intrinsic. However, we can do some
  // scaffolding to make it work. The idea is to create an alloca instruction
  // to get a ptr, pass this ptr to OpenCL::modf, and then load the value
  // from this ptr to place it in the struct. llvm.modf returns the fractional
  // part as the first element of the result, and the integral part as the
  // second element of the result.

  // At this point, the return type is not a struct anymore, but rather two
  // independent elements of SPIRVResType. We can get each independent element
  // from I.getDefs() or I.getOperands().
  if (STI.canUseExtInstSet(SPIRV::InstructionSet::OpenCL_std)) {
    MachineIRBuilder MIRBuilder(I);
    // Get pointer type for alloca variable.
    const SPIRVType *PtrType = GR.getOrCreateSPIRVPointerType(
        ResType, MIRBuilder, SPIRV::StorageClass::Function);
    // Create new register for the pointer type of alloca variable.
    Register PtrTyReg =
        MIRBuilder.getMRI()->createVirtualRegister(&SPIRV::iIDRegClass);
    MIRBuilder.getMRI()->setType(
        PtrTyReg,
        LLT::pointer(storageClassToAddressSpace(SPIRV::StorageClass::Function),
                     GR.getPointerSize()));

    // Assign SPIR-V type of the pointer type of the alloca variable to the
    // new register.
    GR.assignSPIRVTypeToVReg(PtrType, PtrTyReg, MIRBuilder.getMF());
    MachineBasicBlock &EntryBB = I.getMF()->front();
    MachineBasicBlock::iterator VarPos =
        getFirstValidInstructionInsertPoint(EntryBB);
    auto AllocaMIB =
        BuildMI(EntryBB, VarPos, I.getDebugLoc(), TII.get(SPIRV::OpVariable))
            .addDef(PtrTyReg)
            .addUse(GR.getSPIRVTypeID(PtrType))
            .addImm(static_cast<uint32_t>(SPIRV::StorageClass::Function));
    Register Variable = AllocaMIB->getOperand(0).getReg();

    MachineBasicBlock &BB = *I.getParent();
    // Create the OpenCLLIB::modf instruction.
    auto MIB =
        BuildMI(BB, I, I.getDebugLoc(), TII.get(SPIRV::OpExtInst))
            .addDef(ResVReg)
            .addUse(GR.getSPIRVTypeID(ResType))
            .addImm(static_cast<uint32_t>(SPIRV::InstructionSet::OpenCL_std))
            .addImm(CL::modf)
            .setMIFlags(I.getFlags())
            .add(I.getOperand(I.getNumExplicitDefs())) // Floating point value.
            .addUse(Variable); // Pointer to integral part.
    // Assign the integral part stored in the ptr to the second element of the
    // result.
    Register IntegralPartReg = I.getOperand(1).getReg();
    if (IntegralPartReg.isValid()) {
      // Load the value from the pointer to integral part.
      auto LoadMIB = BuildMI(BB, I, I.getDebugLoc(), TII.get(SPIRV::OpLoad))
                         .addDef(IntegralPartReg)
                         .addUse(GR.getSPIRVTypeID(ResType))
                         .addUse(Variable);
      return LoadMIB.constrainAllUses(TII, TRI, RBI);
    }

    return MIB.constrainAllUses(TII, TRI, RBI);
  } else if (STI.canUseExtInstSet(SPIRV::InstructionSet::GLSL_std_450)) {
    assert(false && "GLSL::Modf is deprecated.");
    // FIXME: GL::Modf is deprecated, use Modfstruct instead.
    return false;
  }
  return false;
}

// Generate the instructions to load 3-element vector builtin input
// IDs/Indices.
// Like: GlobalInvocationId, LocalInvocationId, etc....

bool SPIRVInstructionSelector::loadVec3BuiltinInputID(
    SPIRV::BuiltIn::BuiltIn BuiltInValue, Register ResVReg,
    const SPIRVType *ResType, MachineInstr &I) const {
  MachineIRBuilder MIRBuilder(I);
  const SPIRVType *Vec3Ty =
      GR.getOrCreateSPIRVVectorType(ResType, 3, MIRBuilder, false);
  const SPIRVType *PtrType = GR.getOrCreateSPIRVPointerType(
      Vec3Ty, MIRBuilder, SPIRV::StorageClass::Input);

  // Create new register for the input ID builtin variable.
  Register NewRegister =
      MIRBuilder.getMRI()->createVirtualRegister(&SPIRV::iIDRegClass);
  MIRBuilder.getMRI()->setType(NewRegister, LLT::pointer(0, 64));
  GR.assignSPIRVTypeToVReg(PtrType, NewRegister, MIRBuilder.getMF());

  // Build global variable with the necessary decorations for the input ID
  // builtin variable.
  Register Variable = GR.buildGlobalVariable(
      NewRegister, PtrType, getLinkStringForBuiltIn(BuiltInValue), nullptr,
      SPIRV::StorageClass::Input, nullptr, true, false,
      SPIRV::LinkageType::Import, MIRBuilder, false);

  // Create new register for loading value.
  MachineRegisterInfo *MRI = MIRBuilder.getMRI();
  Register LoadedRegister = MRI->createVirtualRegister(&SPIRV::iIDRegClass);
  MIRBuilder.getMRI()->setType(LoadedRegister, LLT::pointer(0, 64));
  GR.assignSPIRVTypeToVReg(Vec3Ty, LoadedRegister, MIRBuilder.getMF());

  // Load v3uint value from the global variable.
  bool Result =
      BuildMI(*I.getParent(), I, I.getDebugLoc(), TII.get(SPIRV::OpLoad))
          .addDef(LoadedRegister)
          .addUse(GR.getSPIRVTypeID(Vec3Ty))
          .addUse(Variable);

  // Get the input ID index. Expecting operand is a constant immediate value,
  // wrapped in a type assignment.
  assert(I.getOperand(2).isReg());
  const uint32_t ThreadId = foldImm(I.getOperand(2), MRI);

  // Extract the input ID from the loaded vector value.
  MachineBasicBlock &BB = *I.getParent();
  auto MIB = BuildMI(BB, I, I.getDebugLoc(), TII.get(SPIRV::OpCompositeExtract))
                 .addDef(ResVReg)
                 .addUse(GR.getSPIRVTypeID(ResType))
                 .addUse(LoadedRegister)
                 .addImm(ThreadId);
  return Result && MIB.constrainAllUses(TII, TRI, RBI);
}

// Generate the instructions to load 32-bit integer builtin input IDs/Indices.
// Like LocalInvocationIndex
bool SPIRVInstructionSelector::loadBuiltinInputID(
    SPIRV::BuiltIn::BuiltIn BuiltInValue, Register ResVReg,
    const SPIRVType *ResType, MachineInstr &I) const {
  MachineIRBuilder MIRBuilder(I);
  const SPIRVType *PtrType = GR.getOrCreateSPIRVPointerType(
      ResType, MIRBuilder, SPIRV::StorageClass::Input);

  // Create new register for the input ID builtin variable.
  Register NewRegister =
      MIRBuilder.getMRI()->createVirtualRegister(GR.getRegClass(PtrType));
  MIRBuilder.getMRI()->setType(
      NewRegister,
      LLT::pointer(storageClassToAddressSpace(SPIRV::StorageClass::Input),
                   GR.getPointerSize()));
  GR.assignSPIRVTypeToVReg(PtrType, NewRegister, MIRBuilder.getMF());

  // Build global variable with the necessary decorations for the input ID
  // builtin variable.
  Register Variable = GR.buildGlobalVariable(
      NewRegister, PtrType, getLinkStringForBuiltIn(BuiltInValue), nullptr,
      SPIRV::StorageClass::Input, nullptr, true, false,
      SPIRV::LinkageType::Import, MIRBuilder, false);

  // Load uint value from the global variable.
  auto MIB = BuildMI(*I.getParent(), I, I.getDebugLoc(), TII.get(SPIRV::OpLoad))
                 .addDef(ResVReg)
                 .addUse(GR.getSPIRVTypeID(ResType))
                 .addUse(Variable);

  return MIB.constrainAllUses(TII, TRI, RBI);
}

SPIRVType *SPIRVInstructionSelector::widenTypeToVec4(const SPIRVType *Type,
                                                     MachineInstr &I) const {
  MachineIRBuilder MIRBuilder(I);
  if (Type->getOpcode() != SPIRV::OpTypeVector)
    return GR.getOrCreateSPIRVVectorType(Type, 4, MIRBuilder, false);

  uint64_t VectorSize = Type->getOperand(2).getImm();
  if (VectorSize == 4)
    return Type;

  Register ScalarTypeReg = Type->getOperand(1).getReg();
  const SPIRVType *ScalarType = GR.getSPIRVTypeForVReg(ScalarTypeReg);
  return GR.getOrCreateSPIRVVectorType(ScalarType, 4, MIRBuilder, false);
}

bool SPIRVInstructionSelector::loadHandleBeforePosition(
    Register &HandleReg, const SPIRVType *ResType, GIntrinsic &HandleDef,
    MachineInstr &Pos) const {

  assert(HandleDef.getIntrinsicID() ==
         Intrinsic::spv_resource_handlefrombinding);
  uint32_t Set = foldImm(HandleDef.getOperand(2), MRI);
  uint32_t Binding = foldImm(HandleDef.getOperand(3), MRI);
  uint32_t ArraySize = foldImm(HandleDef.getOperand(4), MRI);
  Register IndexReg = HandleDef.getOperand(5).getReg();
  // FIXME: The IsNonUniform flag needs to be set based on resource analysis.
  // https://github.com/llvm/llvm-project/issues/155701
  bool IsNonUniform = false;
  std::string Name =
      getStringValueFromReg(HandleDef.getOperand(6).getReg(), *MRI);

  bool IsStructuredBuffer = ResType->getOpcode() == SPIRV::OpTypePointer;
  MachineIRBuilder MIRBuilder(HandleDef);
  SPIRVType *VarType = ResType;
  SPIRV::StorageClass::StorageClass SC = SPIRV::StorageClass::UniformConstant;

  if (IsStructuredBuffer) {
    VarType = GR.getPointeeType(ResType);
    SC = GR.getPointerStorageClass(ResType);
  }

  Register VarReg =
      buildPointerToResource(VarType, SC, Set, Binding, ArraySize, IndexReg,
                             IsNonUniform, Name, MIRBuilder);

  if (IsNonUniform)
    buildOpDecorate(HandleReg, HandleDef, TII, SPIRV::Decoration::NonUniformEXT,
                    {});

  // The handle for the buffer is the pointer to the resource. For an image, the
  // handle is the image object. So images get an extra load.
  uint32_t LoadOpcode =
      IsStructuredBuffer ? SPIRV::OpCopyObject : SPIRV::OpLoad;
  GR.assignSPIRVTypeToVReg(ResType, HandleReg, *Pos.getMF());
  return BuildMI(*Pos.getParent(), Pos, HandleDef.getDebugLoc(),
                 TII.get(LoadOpcode))
      .addDef(HandleReg)
      .addUse(GR.getSPIRVTypeID(ResType))
      .addUse(VarReg)
      .constrainAllUses(TII, TRI, RBI);
}

namespace llvm {
InstructionSelector *
createSPIRVInstructionSelector(const SPIRVTargetMachine &TM,
                               const SPIRVSubtarget &Subtarget,
                               const RegisterBankInfo &RBI) {
  return new SPIRVInstructionSelector(TM, Subtarget, RBI);
}
} // namespace llvm
