[llvm] [AMDGPU] Emit the relocation symbol for LDS and named barrier when object linking is enabled (PR #192380)
Shilei Tian via llvm-commits
llvm-commits at lists.llvm.org
Thu Apr 16 14:53:29 PDT 2026
https://github.com/shiltian updated https://github.com/llvm/llvm-project/pull/192380
>From 2cf7c9742f187c9f9d526ed3a91341a1f2e3f229 Mon Sep 17 00:00:00 2001
From: Shilei Tian <i at tianshilei.me>
Date: Wed, 15 Apr 2026 23:10:39 -0400
Subject: [PATCH] [AMDGPU] Emit the relocation symbol for LDS and named barrier
when object linking is enabled
---
llvm/lib/Target/AMDGPU/AMDGPUAsmPrinter.cpp | 15 ++++--
llvm/lib/Target/AMDGPU/SIISelLowering.cpp | 12 +++++
.../lds-link-time-codegen-named-barrier.ll | 35 +++++++++++++
.../CodeGen/AMDGPU/lds-link-time-codegen.ll | 50 +++++++++++++++++++
4 files changed, 109 insertions(+), 3 deletions(-)
create mode 100644 llvm/test/CodeGen/AMDGPU/lds-link-time-codegen-named-barrier.ll
create mode 100644 llvm/test/CodeGen/AMDGPU/lds-link-time-codegen.ll
diff --git a/llvm/lib/Target/AMDGPU/AMDGPUAsmPrinter.cpp b/llvm/lib/Target/AMDGPU/AMDGPUAsmPrinter.cpp
index 6ac138f97d970..718b2b154e251 100644
--- a/llvm/lib/Target/AMDGPU/AMDGPUAsmPrinter.cpp
+++ b/llvm/lib/Target/AMDGPU/AMDGPUAsmPrinter.cpp
@@ -20,6 +20,7 @@
#include "AMDGPUHSAMetadataStreamer.h"
#include "AMDGPUMCResourceInfo.h"
#include "AMDGPUResourceUsageAnalysis.h"
+#include "AMDGPUTargetMachine.h"
#include "GCNSubtarget.h"
#include "MCTargetDesc/AMDGPUInstPrinter.h"
#include "MCTargetDesc/AMDGPUMCExpr.h"
@@ -330,10 +331,18 @@ void AMDGPUAsmPrinter::emitGlobalVariable(const GlobalVariable *GV) {
return;
}
- // LDS variables aren't emitted in HSA or PAL yet.
const Triple::OSType OS = TM.getTargetTriple().getOS();
- if (OS == Triple::AMDHSA || OS == Triple::AMDPAL)
- return;
+ if (OS == Triple::AMDHSA || OS == Triple::AMDPAL) {
+ if (!AMDGPUTargetMachine::EnableObjectLinking)
+ return;
+ // With object linking, LDS definitions should have been externalized
+ // by earlier passes (e.g. LDS lowering, named barrier lowering).
+ // Only declarations reach here, emitted as SHN_AMDGPU_LDS symbols
+ // so the linker can assign their offsets.
+ assert(GV->isDeclaration() &&
+ "LDS definitions should have been externalized when object "
+ "linking is enabled");
+ }
MCSymbol *GVSym = getSymbol(GV);
diff --git a/llvm/lib/Target/AMDGPU/SIISelLowering.cpp b/llvm/lib/Target/AMDGPU/SIISelLowering.cpp
index 752ea02119e03..8bb072a9626a9 100644
--- a/llvm/lib/Target/AMDGPU/SIISelLowering.cpp
+++ b/llvm/lib/Target/AMDGPU/SIISelLowering.cpp
@@ -8348,6 +8348,18 @@ bool SITargetLowering::shouldUseLDSConstAddress(const GlobalValue *GV) const {
if (!GV->hasExternalLinkage())
return true;
+ // With object linking, external LDS declarations need relocations so the
+ // linker can assign their offsets.
+ if (AMDGPUTargetMachine::EnableObjectLinking) {
+ if (const auto *GVar = dyn_cast<GlobalVariable>(GV)) {
+ if (GVar->getAddressSpace() == AMDGPUAS::LOCAL_ADDRESS) {
+ assert(GVar->isDeclaration() && "AS3 GVs should be declaration here "
+ "when object linking is enabled");
+ return false;
+ }
+ }
+ }
+
const auto OS = getTargetMachine().getTargetTriple().getOS();
return OS == Triple::AMDHSA || OS == Triple::AMDPAL;
}
diff --git a/llvm/test/CodeGen/AMDGPU/lds-link-time-codegen-named-barrier.ll b/llvm/test/CodeGen/AMDGPU/lds-link-time-codegen-named-barrier.ll
new file mode 100644
index 0000000000000..46d4c8db00f06
--- /dev/null
+++ b/llvm/test/CodeGen/AMDGPU/lds-link-time-codegen-named-barrier.ll
@@ -0,0 +1,35 @@
+; RUN: llc -mtriple=amdgcn-amd-amdhsa -mcpu=gfx1250 -amdgpu-enable-object-linking < %s | FileCheck %s
+
+; Verify object linking codegen for named barriers on GFX1250:
+; 1. Barrier instructions use M0-based forms with relocation references
+; 2. group_segment_fixed_size = 0 (linker patches it)
+; 3. Named barrier is emitted as an SHN_AMDGPU_LDS symbol (.amdgpu_lds)
+
+ at bar = internal addrspace(3) global [2 x target("amdgcn.named.barrier", 0)] poison
+
+; CHECK-LABEL: kernel:
+; CHECK: s_lshr_b32 s{{[0-9]+}}, __amdgpu_named_barrier.bar{{[^ @]*}}@abs32 at lo, 4
+; CHECK: s_barrier_signal m0
+; CHECK: s_barrier_join m0
+; CHECK: s_barrier_wait 1
+
+; KD: group_segment_fixed_size = 0 (linker will patch).
+; CHECK: .amdhsa_group_segment_fixed_size 0
+
+; LDS symbol declaration
+; CHECK: .amdgpu_lds __amdgpu_named_barrier.bar{{[^ ,]*}}, 32, 4
+
+define amdgpu_kernel void @kernel() {
+ call void @llvm.amdgcn.s.barrier.signal.var(ptr addrspace(3) @bar, i32 3)
+ call void @llvm.amdgcn.s.barrier.join(ptr addrspace(3) @bar)
+ call void @llvm.amdgcn.s.barrier.wait(i16 1)
+ call void @helper()
+ ret void
+}
+
+declare void @helper()
+declare void @llvm.amdgcn.s.barrier.signal.var(ptr addrspace(3), i32) #0
+declare void @llvm.amdgcn.s.barrier.join(ptr addrspace(3)) #0
+declare void @llvm.amdgcn.s.barrier.wait(i16) #0
+
+attributes #0 = { convergent nounwind }
diff --git a/llvm/test/CodeGen/AMDGPU/lds-link-time-codegen.ll b/llvm/test/CodeGen/AMDGPU/lds-link-time-codegen.ll
new file mode 100644
index 0000000000000..878f3abf7ccfc
--- /dev/null
+++ b/llvm/test/CodeGen/AMDGPU/lds-link-time-codegen.ll
@@ -0,0 +1,50 @@
+; RUN: llc -mtriple=amdgcn-amd-amdhsa -mcpu=gfx900 -amdgpu-enable-object-linking < %s | FileCheck -check-prefixes=ASM %s
+; RUN: llc -mtriple=amdgcn-amd-amdhsa -mcpu=gfx900 -amdgpu-enable-object-linking -filetype=obj < %s | llvm-readobj -r --syms - | FileCheck -check-prefixes=ELF %s
+
+; Test that with object linking enabled, external LDS declarations produce
+; @abs32 at lo relocations, SHN_AMDGPU_LDS symbols, and .amdgpu_lds directives.
+; Covers multiple LDS variables with different sizes and alignments (including
+; zero-sized dynamic LDS), usage from both kernels and device functions, and
+; group_segment_fixed_size = 0 (linker patches via binary patching).
+
+ at lds_large = external addrspace(3) global [256 x i8], align 16
+ at lds_small = external addrspace(3) global [128 x i8], align 4
+ at lds_dynamic = external addrspace(3) global [0 x i8], align 8
+
+; --- Assembly checks ---
+; ASM-LABEL: {{^}}device_func:
+; ASM: v_add_u32_e32 v{{[0-9]+}}, lds_large at abs32@lo, v{{[0-9]+}}
+
+; ASM-LABEL: {{^}}test_kernel:
+; ASM-DAG: s_add_i32 s{{[0-9]+}}, s{{[0-9]+}}, lds_small at abs32@lo
+; ASM-DAG: s_add_i32 s{{[0-9]+}}, s{{[0-9]+}}, lds_dynamic at abs32@lo
+
+; ASM-DAG: .amdgpu_lds lds_large, 256, 16
+; ASM-DAG: .amdgpu_lds lds_small, 128, 4
+; ASM-DAG: .amdgpu_lds lds_dynamic, 0, 8
+
+; ASM: .group_segment_fixed_size: 0
+
+; --- ELF checks ---
+; ELF-DAG: R_AMDGPU_ABS32_LO lds_large
+; ELF-DAG: R_AMDGPU_ABS32_LO lds_small
+; ELF-DAG: R_AMDGPU_ABS32_LO lds_dynamic
+
+; ELF-DAG: Name: lds_large
+; ELF-DAG: Name: lds_small
+; ELF-DAG: Name: lds_dynamic
+
+define void @device_func(i32 %idx) {
+ %gep = getelementptr [256 x i8], ptr addrspace(3) @lds_large, i32 0, i32 %idx
+ store i8 1, ptr addrspace(3) %gep
+ ret void
+}
+
+define amdgpu_kernel void @test_kernel(i32 %idx) {
+ %gep1 = getelementptr [128 x i8], ptr addrspace(3) @lds_small, i32 0, i32 %idx
+ store i8 2, ptr addrspace(3) %gep1
+ %gep2 = getelementptr [0 x i8], ptr addrspace(3) @lds_dynamic, i32 0, i32 %idx
+ store i8 3, ptr addrspace(3) %gep2
+ call void @device_func(i32 %idx)
+ ret void
+}
More information about the llvm-commits
mailing list