Index: llvm/lib/Target/AMDGPU/AMDGPUInstructionSelector.h =================================================================== --- llvm/lib/Target/AMDGPU/AMDGPUInstructionSelector.h +++ llvm/lib/Target/AMDGPU/AMDGPUInstructionSelector.h @@ -108,6 +108,7 @@ bool selectDivScale(MachineInstr &MI) const; bool selectIntrinsicIcmp(MachineInstr &MI) const; bool selectBallot(MachineInstr &I) const; + bool selectRelocConstant(MachineInstr &I) const; bool selectG_INTRINSIC(MachineInstr &I) const; bool selectEndCfIntrinsic(MachineInstr &MI) const; Index: llvm/lib/Target/AMDGPU/AMDGPUInstructionSelector.cpp =================================================================== --- llvm/lib/Target/AMDGPU/AMDGPUInstructionSelector.cpp +++ llvm/lib/Target/AMDGPU/AMDGPUInstructionSelector.cpp @@ -891,6 +891,8 @@ return selectIntrinsicIcmp(I); case Intrinsic::amdgcn_ballot: return selectBallot(I); + case Intrinsic::amdgcn_reloc_constant: + return selectRelocConstant(I); default: return selectImpl(I, *CoverageInfo); } @@ -1071,6 +1073,31 @@ return true; } +bool AMDGPUInstructionSelector::selectRelocConstant(MachineInstr &I) const { + Register DstReg = I.getOperand(0).getReg(); + const RegisterBank *DstBank = RBI.getRegBank(DstReg, *MRI, TRI); + const TargetRegisterClass *DstRC = + TRI.getRegClassForSizeOnBank(32, *DstBank, *MRI); + if (!DstRC || !RBI.constrainGenericRegister(DstReg, *DstRC, *MRI)) + return false; + + const bool IsVALU = DstBank->getID() == AMDGPU::VGPRRegBankID; + + Module *M = MF->getFunction().getParent(); + const MDNode *Metadata = I.getOperand(2).getMetadata(); + auto SymbolName = cast(Metadata->getOperand(0))->getString(); + auto RelocSymbol = cast( + M->getOrInsertGlobal(SymbolName, Type::getInt32Ty(M->getContext()))); + + MachineBasicBlock *BB = I.getParent(); + BuildMI(*BB, &I, I.getDebugLoc(), + TII.get(IsVALU ? AMDGPU::V_MOV_B32_e32 : AMDGPU::S_MOV_B32), DstReg) + .addGlobalAddress(RelocSymbol, 0, SIInstrInfo::MO_ABS32_LO); + + I.eraseFromParent(); + return true; +} + bool AMDGPUInstructionSelector::selectEndCfIntrinsic(MachineInstr &MI) const { // FIXME: Manually selecting to avoid dealiing with the SReg_1 trick // SelectionDAG uses for wave32 vs wave64. Index: llvm/lib/Target/AMDGPU/AMDGPURegisterBankInfo.cpp =================================================================== --- llvm/lib/Target/AMDGPU/AMDGPURegisterBankInfo.cpp +++ llvm/lib/Target/AMDGPU/AMDGPURegisterBankInfo.cpp @@ -4018,7 +4018,8 @@ return getDefaultMappingAllVGPR(MI); case Intrinsic::amdgcn_kernarg_segment_ptr: case Intrinsic::amdgcn_s_getpc: - case Intrinsic::amdgcn_groupstaticsize: { + case Intrinsic::amdgcn_groupstaticsize: + case Intrinsic::amdgcn_reloc_constant: { unsigned Size = MRI.getType(MI.getOperand(0).getReg()).getSizeInBits(); OpdsMapping[0] = AMDGPU::getValueMapping(AMDGPU::SGPRRegBankID, Size); break; Index: llvm/test/CodeGen/AMDGPU/GlobalISel/inst-select-amdgcn.reloc.constant.mir =================================================================== --- /dev/null +++ llvm/test/CodeGen/AMDGPU/GlobalISel/inst-select-amdgcn.reloc.constant.mir @@ -0,0 +1,52 @@ +# NOTE: Assertions have been autogenerated by utils/update_mir_test_checks.py +# RUN: llc -march=amdgcn -mcpu=tahiti -run-pass=instruction-select -verify-machineinstrs -o - %s | FileCheck -check-prefix=GCN %s + +--- | + + define void @reloc_constant_sgpr32() { ret void } + define void @reloc_constant_vgpr32() { ret void } + + declare i32 @llvm.amdgcn.reloc.constant(metadata) + + !0 = !{!"arst"} + +... + +--- +name: reloc_constant_sgpr32 +alignment: 1 +legalized: true +regBankSelected: true +tracksRegLiveness: true +body: | + bb.0: + + ; GCN-LABEL: name: reloc_constant_sgpr32 + ; GCN: [[S_MOV_B32_:%[0-9]+]]:sreg_32 = S_MOV_B32 target-flags(amdgpu-abs32-lo) @arst + ; GCN: $sgpr0 = COPY [[S_MOV_B32_]] + ; GCN: S_ENDPGM 0, implicit $sgpr0 + %0:sgpr(s32) = G_INTRINSIC intrinsic(@llvm.amdgcn.reloc.constant), !0 + $sgpr0 = COPY %0 + S_ENDPGM 0, implicit $sgpr0 + +... + +--- +name: reloc_constant_vgpr32 +alignment: 1 +legalized: true +regBankSelected: true +tracksRegLiveness: true +body: | + bb.0: + + ; GCN-LABEL: name: reloc_constant_vgpr32 + ; GCN: [[V_MOV_B32_e32_:%[0-9]+]]:vgpr_32 = V_MOV_B32_e32 target-flags(amdgpu-abs32-lo) @arst, implicit $exec + ; GCN: $vgpr0 = COPY [[V_MOV_B32_e32_]] + ; GCN: S_ENDPGM 0, implicit $vgpr0 + %0:vgpr(s32) = G_INTRINSIC intrinsic(@llvm.amdgcn.reloc.constant), !0 + $vgpr0 = COPY %0 + S_ENDPGM 0, implicit $vgpr0 + +... + Index: llvm/test/CodeGen/AMDGPU/amdgpu-reloc-const.ll =================================================================== --- llvm/test/CodeGen/AMDGPU/amdgpu-reloc-const.ll +++ llvm/test/CodeGen/AMDGPU/amdgpu-reloc-const.ll @@ -1,5 +1,9 @@ ; RUN: llc -march=amdgcn -verify-machineinstrs < %s | FileCheck -check-prefix=GCN %s ; RUN: llc -mtriple=amdgcn--amdpal -mcpu=gfx900 -filetype=obj -o %t.o < %s && llvm-readobj -relocations %t.o | FileCheck --check-prefix=ELF %s + +; RUN: llc -global-isel -march=amdgcn -verify-machineinstrs < %s | FileCheck -check-prefix=GCN %s +; RUN: llc -global-isel -mtriple=amdgcn--amdpal -mcpu=gfx900 -filetype=obj -o %t.o < %s && llvm-readobj -relocations %t.o | FileCheck --check-prefix=ELF %s + ; GCN-LABEL: {{^}}ps_main: ; GCN: v_mov_b32_{{.*}} v[[relocreg:[0-9]+]], doff_0_0_b@abs32@lo ; GCN-NEXT: exp {{.*}} v[[relocreg]], {{.*}}