Index: llvm/include/llvm/IR/IntrinsicsAMDGPU.td =================================================================== --- llvm/include/llvm/IR/IntrinsicsAMDGPU.td +++ llvm/include/llvm/IR/IntrinsicsAMDGPU.td @@ -1986,4 +1986,11 @@ [llvm_float_ty], [llvm_float_ty, llvm_float_ty], [IntrNoMem, IntrSpeculatable] >; + +// Emits the offset of the descriptor for the given set and binding. +// Will generate a fixup. +def int_amdgcn_reloc_constant : Intrinsic< + [llvm_i32_ty], [llvm_metadata_ty], + [IntrNoMem, IntrSpeculatable] +>; } Index: llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp =================================================================== --- llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp +++ llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp @@ -1607,6 +1607,9 @@ return RFV.getCopyFromRegs(DAG, FuncInfo, getCurSDLoc(), Chain, nullptr, V); } + if (const MetadataAsValue *MD = dyn_cast(V)) { + return DAG.getMDNode(cast(MD->getMetadata())); + } llvm_unreachable("Can't get register for value!"); } Index: llvm/lib/Target/AMDGPU/AMDGPUISelDAGToDAG.cpp =================================================================== --- llvm/lib/Target/AMDGPU/AMDGPUISelDAGToDAG.cpp +++ llvm/lib/Target/AMDGPU/AMDGPUISelDAGToDAG.cpp @@ -1760,11 +1760,24 @@ bool AMDGPUDAGToDAGISel::SelectSMRDOffset(SDValue ByteOffsetNode, SDValue &Offset, bool &Imm) const { - - // FIXME: Handle non-constant offsets. ConstantSDNode *C = dyn_cast(ByteOffsetNode); if (!C) + { + if (ByteOffsetNode.getValueType().isScalarInteger() && + ByteOffsetNode.getValueType().getSizeInBits() == 32) + { + Offset = ByteOffsetNode; + Imm = false; + return true; + } + if (ByteOffsetNode.getOpcode() == ISD::ZERO_EXTEND) + { + Offset = ByteOffsetNode.getOperand(0); + Imm = false; + return true; + } return false; + } SDLoc SL(ByteOffsetNode); GCNSubtarget::Generation Gen = Subtarget->getGeneration(); @@ -1829,7 +1842,8 @@ // wraparound, because s_load instructions perform the addition in 64 bits. if ((Addr.getValueType() != MVT::i32 || Addr->getFlags().hasNoUnsignedWrap()) && - CurDAG->isBaseWithConstantOffset(Addr)) { + (CurDAG->isBaseWithConstantOffset(Addr) || + Addr.getOpcode() == ISD::ADD)) { SDValue N0 = Addr.getOperand(0); SDValue N1 = Addr.getOperand(1); Index: llvm/lib/Target/AMDGPU/SIISelLowering.cpp =================================================================== --- llvm/lib/Target/AMDGPU/SIISelLowering.cpp +++ llvm/lib/Target/AMDGPU/SIISelLowering.cpp @@ -6046,6 +6046,16 @@ DAG.getConstant(1, SL, MVT::i32)); return DAG.getSetCC(SL, MVT::i1, SrcHi, Aperture, ISD::SETEQ); } + case Intrinsic::amdgcn_reloc_constant: { + Module *M = const_cast(MF.getFunction().getParent()); + const MDNode* metadata = cast(Op.getOperand(1))->getMD(); + auto symbolName = cast(metadata->getOperand(0))->getString(); + auto relocSymbol = cast(M->getOrInsertGlobal(symbolName, + Type::getInt32Ty(M->getContext()))); + SDValue GA = DAG.getTargetGlobalAddress(relocSymbol, DL, MVT::i32, 0, + SIInstrInfo::MO_ABS32_LO); + return {DAG.getMachineNode(AMDGPU::S_MOV_B32, DL, MVT::i32, GA), 0}; + } default: if (const AMDGPU::ImageDimIntrinsicInfo *ImageDimIntr = AMDGPU::getImageDimIntrinsicInfo(IntrinsicID)) Index: llvm/test/CodeGen/AMDGPU/amdgpu-reloc-const.ll =================================================================== --- /dev/null +++ llvm/test/CodeGen/AMDGPU/amdgpu-reloc-const.ll @@ -0,0 +1,27 @@ +; RUN: llc -march=amdgcn -verify-machineinstrs < %s | FileCheck -check-prefix=GCN %s + +; GCN-LABEL: {{^}}ham: +; GCN: v_mov_b32_{{.*}} v[[relocreg:[0-9]+]], doff_0_0@abs32@lo +; GCN-NEXT: exp pos0 v[[relocreg]], {{.*}} +; GCN-NEXT: s_endpgm +; GCN-NEXT: .Lfunc_end + +; Function Attrs: inaccessiblememonly nounwind writeonly +declare void @llvm.amdgcn.exp.f32(i32 immarg, i32 immarg, float, float, float, float, i1 immarg, i1 immarg) #1 + +; Function Attrs: nounwind readnone speculatable +declare i32 @llvm.amdgcn.reloc.constant(metadata) #2 + +define amdgpu_vs void @ham(float %arg, float %arg1) { + %rc = call i32 @llvm.amdgcn.reloc.constant(metadata !1) + %rcf = bitcast i32 %rc to float + %zero = bitcast i32 0 to float + call void @llvm.amdgcn.exp.f32(i32 immarg 12, i32 immarg 15, float %rcf, float %zero, float %zero, float %zero, i1 immarg true, i1 immarg false) + ret void +} + + +attributes #1 = { inaccessiblememonly nounwind writeonly } +attributes #2 = { nounwind readnone speculatable } + +!1 = !{!"doff_0_0"}