Index: llvm/include/llvm/CodeGen/GlobalISel/LegalizerHelper.h =================================================================== --- llvm/include/llvm/CodeGen/GlobalISel/LegalizerHelper.h +++ llvm/include/llvm/CodeGen/GlobalISel/LegalizerHelper.h @@ -240,6 +240,7 @@ LegalizeResult lowerSADDO_SSUBO(MachineInstr &MI); LegalizeResult lowerBswap(MachineInstr &MI); LegalizeResult lowerBitreverse(MachineInstr &MI); + LegalizeResult lowerReadRegister(MachineInstr &MI); private: MachineRegisterInfo &MRI; Index: llvm/include/llvm/Support/TargetOpcodes.def =================================================================== --- llvm/include/llvm/Support/TargetOpcodes.def +++ llvm/include/llvm/Support/TargetOpcodes.def @@ -614,12 +614,16 @@ /// Generic dynamic stack allocation. HANDLE_TARGET_OPCODE(G_DYN_STACKALLOC) -// TODO: Add more generic opcodes as we move along. +/// read_register intrinsic +HANDLE_TARGET_OPCODE(G_READ_REGISTER) + +/// write_register intrinsic +HANDLE_TARGET_OPCODE(G_WRITE_REGISTER) /// Marker for the end of the generic opcode. /// This is used to check if an opcode is in the range of the /// generic opcodes. -HANDLE_TARGET_OPCODE_MARKER(PRE_ISEL_GENERIC_OPCODE_END, G_DYN_STACKALLOC) +HANDLE_TARGET_OPCODE_MARKER(PRE_ISEL_GENERIC_OPCODE_END, G_WRITE_REGISTER) /// BUILTIN_OP_END - This must be the last enum value in this list. /// The target-specific post-isel opcode values start here. Index: llvm/include/llvm/Target/GenericOpcodes.td =================================================================== --- llvm/include/llvm/Target/GenericOpcodes.td +++ llvm/include/llvm/Target/GenericOpcodes.td @@ -1012,6 +1012,26 @@ let isTerminator = 1; } +def G_READ_REGISTER : GenericInstruction { + let OutOperandList = (outs type0:$dst); + let InOperandList = (ins unknown:$register); + let hasSideEffects = 1; + + // Assume convergent. It's probably not worth the effort of somehow + // modeling convergent and nonconvergent register accesses. + let isConvergent = 1; +} + +def G_WRITE_REGISTER : GenericInstruction { + let OutOperandList = (outs); + let InOperandList = (ins unknown:$register, type0:$value); + let hasSideEffects = 1; + + // Assume convergent. It's probably not worth the effort of somehow + // modeling convergent and nonconvergent register accesses. + let isConvergent = 1; +} + //------------------------------------------------------------------------------ // Vector ops //------------------------------------------------------------------------------ Index: llvm/lib/CodeGen/GlobalISel/IRTranslator.cpp =================================================================== --- llvm/lib/CodeGen/GlobalISel/IRTranslator.cpp +++ llvm/lib/CodeGen/GlobalISel/IRTranslator.cpp @@ -1526,6 +1526,13 @@ case Intrinsic::sideeffect: // Discard annotate attributes, assumptions, and artificial side-effects. return true; + case Intrinsic::read_register: { + Value *Arg = CI.getArgOperand(0); + MIRBuilder.buildInstr(TargetOpcode::G_READ_REGISTER) + .addDef(getOrCreateVReg(CI)) + .addMetadata(cast(cast(Arg)->getMetadata())); + return true; + } } return false; } Index: llvm/lib/CodeGen/GlobalISel/LegalizerHelper.cpp =================================================================== --- llvm/lib/CodeGen/GlobalISel/LegalizerHelper.cpp +++ llvm/lib/CodeGen/GlobalISel/LegalizerHelper.cpp @@ -2317,6 +2317,8 @@ return lowerBswap(MI); case G_BITREVERSE: return lowerBitreverse(MI); + case G_READ_REGISTER: + return lowerReadRegister(MI); } } @@ -4469,3 +4471,22 @@ MI.eraseFromParent(); return Legalized; } + +LegalizerHelper::LegalizeResult +LegalizerHelper::lowerReadRegister(MachineInstr &MI) { + Register Dst = MI.getOperand(0).getReg(); + const LLT Ty = MRI.getType(Dst); + const MDString *RegStr = cast( + cast(MI.getOperand(1).getMetadata())->getOperand(0)); + + MachineFunction &MF = MIRBuilder.getMF(); + const TargetSubtargetInfo &STI = MF.getSubtarget(); + const TargetLowering *TLI = STI.getTargetLowering(); + Register Reg = TLI->getRegisterByName(RegStr->getString().data(), Ty, MF); + if (!Reg.isValid()) + return UnableToLegalize; + + MIRBuilder.buildCopy(Dst, Reg); + MI.eraseFromParent(); + return Legalized; +} Index: llvm/lib/Target/AMDGPU/AMDGPULegalizerInfo.cpp =================================================================== --- llvm/lib/Target/AMDGPU/AMDGPULegalizerInfo.cpp +++ llvm/lib/Target/AMDGPU/AMDGPULegalizerInfo.cpp @@ -1115,6 +1115,8 @@ getActionDefinitionsBuilder(G_SEXT_INREG).lower(); + getActionDefinitionsBuilder({G_READ_REGISTER, G_WRITE_REGISTER}).lower(); + getActionDefinitionsBuilder(G_READCYCLECOUNTER) .legalFor({S64}); Index: llvm/test/CodeGen/AMDGPU/GlobalISel/read_register.ll =================================================================== --- /dev/null +++ llvm/test/CodeGen/AMDGPU/GlobalISel/read_register.ll @@ -0,0 +1,2 @@ +; Runs original SDAG test with -global-isel +; RUN: llc -global-isel -mtriple=amdgcn-amd-amdhsa -mcpu=bonaire -verify-machineinstrs < %S/../read_register.ll | FileCheck -enable-var-scope %S/../read_register.ll