[llvm] [AMDGPU] Preserve scoped-AA metadata when lowering barriers to wave_barrier (PR #191858)
via llvm-commits
llvm-commits at lists.llvm.org
Mon Apr 13 11:51:37 PDT 2026
https://github.com/hidekisaito updated https://github.com/llvm/llvm-project/pull/191858
>From 268694408057172ddbed8e5347f710168181fc02 Mon Sep 17 00:00:00 2001
From: Hideki Saito <hidekido at amd.com>
Date: Mon, 13 Apr 2026 12:25:53 -0500
Subject: [PATCH] [AMDGPU] Preserve scoped-AA metadata when lowering barriers
to wave_barrier
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
AMDGPULowerIntrinsics downgrades s_barrier/s_barrier_wait to
wave_barrier on single-wave workgroups, but dropped all metadata from
the original instruction. The lost !noalias and !alias.scope metadata
prevented MemorySSA's optimized walker from skipping past the barrier,
causing isClobberedInFunction to walk further and reach unrelated
side-effecting defs (e.g. tensor_load_to_lds) that are misclassified
as clobbers — ultimately losing !amdgpu.noclobber on global loads.
Copy !noalias, !alias.scope, and !tbaa from the old instruction to the
replacement wave_barrier.
Made-with: Cursor
---
.../Target/AMDGPU/AMDGPULowerIntrinsics.cpp | 10 ++++-
.../lower-intrinsics-noalias-metadata.ll | 39 +++++++++++++++++++
2 files changed, 47 insertions(+), 2 deletions(-)
create mode 100644 llvm/test/CodeGen/AMDGPU/lower-intrinsics-noalias-metadata.ll
diff --git a/llvm/lib/Target/AMDGPU/AMDGPULowerIntrinsics.cpp b/llvm/lib/Target/AMDGPU/AMDGPULowerIntrinsics.cpp
index e089498693b2f..ff83be1fbb688 100644
--- a/llvm/lib/Target/AMDGPU/AMDGPULowerIntrinsics.cpp
+++ b/llvm/lib/Target/AMDGPU/AMDGPULowerIntrinsics.cpp
@@ -105,7 +105,10 @@ bool AMDGPULowerIntrinsicsImpl::visitBarrier(IntrinsicInst &I) {
// The default cluster barrier expects one signal per workgroup. So we need
// a workgroup barrier first.
if (IsSingleWaveWG) {
- B.CreateIntrinsic(B.getVoidTy(), Intrinsic::amdgcn_wave_barrier, {});
+ B.CreateIntrinsic(B.getVoidTy(), Intrinsic::amdgcn_wave_barrier, {})
+ ->copyMetadata(I,
+ {LLVMContext::MD_noalias, LLVMContext::MD_alias_scope,
+ LLVMContext::MD_tbaa});
} else {
Value *BarrierID_32 = B.getInt32(AMDGPU::Barrier::WORKGROUP);
Value *BarrierID_16 = B.getInt16(AMDGPU::Barrier::WORKGROUP);
@@ -155,7 +158,10 @@ bool AMDGPULowerIntrinsicsImpl::visitBarrier(IntrinsicInst &I) {
// Down-grade waits, remove split signals.
if (I.getIntrinsicID() == Intrinsic::amdgcn_s_barrier ||
I.getIntrinsicID() == Intrinsic::amdgcn_s_barrier_wait) {
- B.CreateIntrinsic(B.getVoidTy(), Intrinsic::amdgcn_wave_barrier, {});
+ B.CreateIntrinsic(B.getVoidTy(), Intrinsic::amdgcn_wave_barrier, {})
+ ->copyMetadata(I,
+ {LLVMContext::MD_noalias, LLVMContext::MD_alias_scope,
+ LLVMContext::MD_tbaa});
} else if (I.getIntrinsicID() ==
Intrinsic::amdgcn_s_barrier_signal_isfirst) {
// If we're the only wave of the workgroup, we're always first.
diff --git a/llvm/test/CodeGen/AMDGPU/lower-intrinsics-noalias-metadata.ll b/llvm/test/CodeGen/AMDGPU/lower-intrinsics-noalias-metadata.ll
new file mode 100644
index 0000000000000..e4d09d83830a9
--- /dev/null
+++ b/llvm/test/CodeGen/AMDGPU/lower-intrinsics-noalias-metadata.ll
@@ -0,0 +1,39 @@
+; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
+; RUN: opt -passes='amdgpu-lower-intrinsics,function(amdgpu-annotate-uniform)' -S -mtriple=amdgcn-amd-amdhsa -mcpu=gfx1100 -codegen-opt-level=1 -mattr=+wavefrontsize32 < %s | FileCheck %s
+
+; When amdgpu-lower-intrinsics downgrades s_barrier to wave_barrier on a
+; single-wave workgroup it must preserve scoped-AA metadata (!noalias,
+; !alias.scope, !tbaa). Without it MemorySSA can no longer see past the
+; barrier, walks further, and may reach an unrelated side-effecting def
+; that falsely blocks !amdgpu.noclobber on a later global load.
+
+define amdgpu_kernel void @noclobber_after_barrier_lowering(ptr addrspace(1) %arg, ptr addrspace(3) %lds) "amdgpu-flat-work-group-size"="1,32" {
+; CHECK-LABEL: @noclobber_after_barrier_lowering(
+; CHECK-NEXT: bb:
+; CHECK-NEXT: store i32 99, ptr addrspace(3) [[LDS:%.*]], align 4, !tbaa [[TBAA0:![0-9]+]], !alias.scope [[META4:![0-9]+]], !noalias [[META7:![0-9]+]]
+; CHECK-NEXT: call void @llvm.amdgcn.wave.barrier(), !tbaa [[TBAA0]], !alias.scope [[META4]], !noalias [[META7]]
+; CHECK-NEXT: [[GEP:%.*]] = getelementptr inbounds i32, ptr addrspace(1) [[ARG:%.*]], i64 1, !amdgpu.uniform [[META9:![0-9]+]]
+; CHECK-NEXT: [[VAL:%.*]] = load i32, ptr addrspace(1) [[GEP]], align 4, !alias.scope [[META7]], !noalias [[META4]], !amdgpu.noclobber [[META9]]
+; CHECK-NEXT: store i32 [[VAL]], ptr addrspace(1) [[ARG]], align 4
+; CHECK-NEXT: ret void
+;
+bb:
+ store i32 99, ptr addrspace(3) %lds, align 4, !alias.scope !4, !noalias !1, !tbaa !5
+ tail call void @llvm.amdgcn.s.barrier(), !noalias !1, !alias.scope !4, !tbaa !5
+ %gep = getelementptr inbounds i32, ptr addrspace(1) %arg, i64 1
+ %val = load i32, ptr addrspace(1) %gep, align 4, !alias.scope !1, !noalias !4
+ store i32 %val, ptr addrspace(1) %arg, align 4
+ ret void
+}
+
+declare void @llvm.amdgcn.s.barrier()
+
+!0 = distinct !{!0, !"domain"}
+!2 = distinct !{!2, !0, !"global_scope"}
+!3 = distinct !{!3, !0, !"lds_scope"}
+!1 = !{!2}
+!4 = !{!3}
+!5 = !{!6, !6, i64 0}
+!6 = !{!"int", !7, i64 0}
+!7 = !{!"omnipotent char", !8, i64 0}
+!8 = !{!"Simple C/C++ TBAA"}
More information about the llvm-commits
mailing list