[llvm] 0877565 - [AMDGPU] Make LowerModuleLDS a noop on an already lowered module (#217075)
via llvm-commits
llvm-commits at lists.llvm.org
Wed Aug 26 07:13:59 PDT 2026
Author: Arseniy Obolenskiy
Date: 2026-08-26T16:13:54+02:00
New Revision: 087756557aca1b8782e47a00a73b290ece9f852d
URL: https://github.com/llvm/llvm-project/commit/087756557aca1b8782e47a00a73b290ece9f852d
DIFF: https://github.com/llvm/llvm-project/commit/087756557aca1b8782e47a00a73b290ece9f852d.diff
LOG: [AMDGPU] Make LowerModuleLDS a noop on an already lowered module (#217075)
Full LTO reruns the pass on each codegen partition, where it matched its
own lowered structs and re-expanded their constexpr uses
Added:
Modified:
llvm/lib/Target/AMDGPU/AMDGPULowerModuleLDSPass.cpp
llvm/test/CodeGen/AMDGPU/lds-run-twice.ll
Removed:
################################################################################
diff --git a/llvm/lib/Target/AMDGPU/AMDGPULowerModuleLDSPass.cpp b/llvm/lib/Target/AMDGPU/AMDGPULowerModuleLDSPass.cpp
index ef86d279d193b..3371a34cda7b6 100644
--- a/llvm/lib/Target/AMDGPU/AMDGPULowerModuleLDSPass.cpp
+++ b/llvm/lib/Target/AMDGPU/AMDGPULowerModuleLDSPass.cpp
@@ -1078,13 +1078,14 @@ class AMDGPULowerModuleLDS {
}
bool runOnModuleNormal(Module &M) {
- CallGraph CG = CallGraph(M);
bool Changed = superAlignLDSGlobals(M);
- Changed |=
- eliminateGVConstantExprUsesFromAllInstructions(M, isLDSVariableToLower);
+ Changed |= any_of(M.globals(), isNotYetLoweredLDSVariable);
+
+ CallGraph CG(M);
- Changed = true; // todo: narrow this down
+ eliminateGVConstantExprUsesFromAllInstructions(M,
+ isNotYetLoweredLDSVariable);
// For each kernel, what variables does it access directly or through
// callees
@@ -1258,7 +1259,7 @@ class AMDGPULowerModuleLDS {
}
for (auto &GV : make_early_inc_range(M.globals()))
- if (AMDGPU::isLDSVariableToLower(GV)) {
+ if (isNotYetLoweredLDSVariable(GV)) {
// probably want to remove from used lists
GV.removeDeadConstantUsers();
if (GV.use_empty())
@@ -1269,6 +1270,11 @@ class AMDGPULowerModuleLDS {
}
private:
+ // An absolute address means a previous run already placed the variable.
+ static bool isNotYetLoweredLDSVariable(const GlobalVariable &GV) {
+ return isLDSVariableToLower(GV) && !GV.isAbsoluteSymbolRef();
+ }
+
// Increase the alignment of LDS globals if necessary to maximise the chance
// that we can use aligned LDS instructions to access them.
static bool superAlignLDSGlobals(Module &M) {
diff --git a/llvm/test/CodeGen/AMDGPU/lds-run-twice.ll b/llvm/test/CodeGen/AMDGPU/lds-run-twice.ll
index 2f92f7e32a239..c022a6321323c 100644
--- a/llvm/test/CodeGen/AMDGPU/lds-run-twice.ll
+++ b/llvm/test/CodeGen/AMDGPU/lds-run-twice.ll
@@ -3,14 +3,50 @@
; RUN:
diff -ub %t.ll %t.second.ll -I ".*ModuleID.*"
; Check AMDGPULowerModuleLDS can run more than once on the same module, and that
-; the second run is a no-op.
+; the second run is a no-op, as full LTO reruns it on each codegen partition.
- at dynlds = external addrspace(3) global [0 x i32], align 4
+; Kernel-only static LDS. @lds2 pushes @lds to a non-zero offset, so the first
+; run leaves a constexpr GEP, which the second run used to re-expand.
@lds = internal unnamed_addr addrspace(3) global i32 poison, align 4
+ at lds2 = internal unnamed_addr addrspace(3) global i64 poison, align 8
+
+; Called from a function shared by two kernels: module struct plus lookup table.
+ at lds.function = internal addrspace(3) global [8 x i16] poison, align 2
+
+; Dynamic LDS from a function lowers to per-kernel shadows plus an offset table.
+ at dynlds.function = external hidden addrspace(3) global [0 x float], align 8
+
+; Dynamic LDS used only from a kernel is left in place.
+ at dynlds = external addrspace(3) global [0 x i32], align 4
+
+; Never lowered, so these survive the first run without an absolute address.
+ at const.lds = internal addrspace(3) constant [4 x i32] poison, align 4
+ at initialized.lds = internal addrspace(3) global i16 0, align 2
+
+; Escapes into a global initializer, so lowering cannot place it either.
+ at escaped = internal addrspace(3) global i32 poison, align 4
+ at escape.ptr = addrspace(1) global ptr addrspace(3) @escaped, align 4
+
+define void @helper() {
+ store i16 1, ptr addrspace(3) getelementptr inbounds ([8 x i16], ptr addrspace(3) @lds.function, i32 0, i32 3), align 2
+ store float 2.0, ptr addrspace(3) @dynlds.function, align 8
+ ret void
+}
define amdgpu_kernel void @test() {
entry:
+ call void @helper()
store i32 0, ptr addrspace(3) @dynlds
store i32 1, ptr addrspace(3) @lds
+ store i64 2, ptr addrspace(3) @lds2
+ store i32 3, ptr addrspace(3) @escaped
+ %c = load i32, ptr addrspace(3) getelementptr inbounds ([4 x i32], ptr addrspace(3) @const.lds, i32 0, i32 2), align 4
+ store i16 9, ptr addrspace(3) @initialized.lds, align 2
+ ret void
+}
+
+define amdgpu_kernel void @test2() {
+entry:
+ call void @helper()
ret void
}
More information about the llvm-commits
mailing list