[llvm] [GlobalISel] Preserve volatile and ordered atomic stores of undef (PR #226265)
Alex MacLean via llvm-commits
llvm-commits at lists.llvm.org
Fri Sep 25 13:17:32 PDT 2026
https://github.com/AlexMaclean updated https://github.com/llvm/llvm-project/pull/226265
>From e7ff9eac993188e9e14998d629a9d467159b77cc Mon Sep 17 00:00:00 2001
From: Alex Maclean <amaclean at nvidia.com>
Date: Thu, 24 Sep 2026 11:30:01 -0700
Subject: [PATCH 1/2] [GlobalISel] Preserve volatile and ordered atomic stores
of undef
Guard erase_undef_store with isUnordered(), matching InstCombine. An undef
value does not justify dropping a volatile access or atomic
synchronization. Ordinary and unordered atomic stores can still be removed.
SelectionDAG also guards its undef-store fold against volatile accesses,
while handling atomic stores separately.
Add AArch64 MIR coverage for ordinary, volatile, unordered, monotonic,
release, and sequentially consistent stores.
Co-authored-by: Hongyu Chen <hongchen at nvidia.com>
---
.../lib/CodeGen/GlobalISel/CombinerHelper.cpp | 2 +
.../GlobalISel/prelegalizercombiner-undef.mir | 114 ++++++++++++++++++
2 files changed, 116 insertions(+)
diff --git a/llvm/lib/CodeGen/GlobalISel/CombinerHelper.cpp b/llvm/lib/CodeGen/GlobalISel/CombinerHelper.cpp
index 4dce66a74cacc2..4bdfa20ee37c1a 100644
--- a/llvm/lib/CodeGen/GlobalISel/CombinerHelper.cpp
+++ b/llvm/lib/CodeGen/GlobalISel/CombinerHelper.cpp
@@ -2746,6 +2746,8 @@ bool CombinerHelper::matchUndefShuffleVectorMask(MachineInstr &MI) const {
bool CombinerHelper::matchUndefStore(MachineInstr &MI) const {
assert(MI.getOpcode() == TargetOpcode::G_STORE);
+ if (!cast<GStore>(MI).isUnordered())
+ return false;
return getOpcodeDef(TargetOpcode::G_IMPLICIT_DEF, MI.getOperand(0).getReg(),
MRI);
}
diff --git a/llvm/test/CodeGen/AArch64/GlobalISel/prelegalizercombiner-undef.mir b/llvm/test/CodeGen/AArch64/GlobalISel/prelegalizercombiner-undef.mir
index 33905111eb0f28..94b711460eab52 100644
--- a/llvm/test/CodeGen/AArch64/GlobalISel/prelegalizercombiner-undef.mir
+++ b/llvm/test/CodeGen/AArch64/GlobalISel/prelegalizercombiner-undef.mir
@@ -317,3 +317,117 @@ body: |
RET_ReallyLR implicit $x0
...
+---
+name: store_undef
+tracksRegLiveness: true
+body: |
+ bb.0:
+ liveins: $x0
+
+ ; CHECK-LABEL: name: store_undef
+ ; CHECK: liveins: $x0
+ ; CHECK-NEXT: {{ $}}
+ ; CHECK-NEXT: RET_ReallyLR
+ %0:_(p0) = COPY $x0
+ %1:_(s32) = G_IMPLICIT_DEF
+ G_STORE %1, %0 :: (store (s32))
+ RET_ReallyLR
+
+...
+---
+name: store_undef_volatile
+tracksRegLiveness: true
+body: |
+ bb.0:
+ liveins: $x0
+
+ ; CHECK-LABEL: name: store_undef_volatile
+ ; CHECK: liveins: $x0
+ ; CHECK-NEXT: {{ $}}
+ ; CHECK-NEXT: [[COPY:%[0-9]+]]:_(p0) = COPY $x0
+ ; CHECK-NEXT: [[DEF:%[0-9]+]]:_(s32) = G_IMPLICIT_DEF
+ ; CHECK-NEXT: G_STORE [[DEF]](s32), [[COPY]](p0) :: (volatile store (s32))
+ ; CHECK-NEXT: RET_ReallyLR
+ %0:_(p0) = COPY $x0
+ %1:_(s32) = G_IMPLICIT_DEF
+ G_STORE %1, %0 :: (volatile store (s32))
+ RET_ReallyLR
+
+...
+---
+name: store_undef_unordered
+tracksRegLiveness: true
+body: |
+ bb.0:
+ liveins: $x0
+
+ ; CHECK-LABEL: name: store_undef_unordered
+ ; CHECK: liveins: $x0
+ ; CHECK-NEXT: {{ $}}
+ ; CHECK-NEXT: RET_ReallyLR
+ %0:_(p0) = COPY $x0
+ %1:_(s32) = G_IMPLICIT_DEF
+ G_STORE %1, %0 :: (store unordered (s32))
+ RET_ReallyLR
+
+...
+---
+name: store_undef_monotonic
+tracksRegLiveness: true
+body: |
+ bb.0:
+ liveins: $x0
+
+ ; CHECK-LABEL: name: store_undef_monotonic
+ ; CHECK: liveins: $x0
+ ; CHECK-NEXT: {{ $}}
+ ; CHECK-NEXT: [[COPY:%[0-9]+]]:_(p0) = COPY $x0
+ ; CHECK-NEXT: [[DEF:%[0-9]+]]:_(s32) = G_IMPLICIT_DEF
+ ; CHECK-NEXT: G_STORE [[DEF]](s32), [[COPY]](p0) :: (store monotonic (s32))
+ ; CHECK-NEXT: RET_ReallyLR
+ %0:_(p0) = COPY $x0
+ %1:_(s32) = G_IMPLICIT_DEF
+ G_STORE %1, %0 :: (store monotonic (s32))
+ RET_ReallyLR
+
+...
+---
+name: store_undef_release
+tracksRegLiveness: true
+body: |
+ bb.0:
+ liveins: $x0
+
+ ; CHECK-LABEL: name: store_undef_release
+ ; CHECK: liveins: $x0
+ ; CHECK-NEXT: {{ $}}
+ ; CHECK-NEXT: [[COPY:%[0-9]+]]:_(p0) = COPY $x0
+ ; CHECK-NEXT: [[DEF:%[0-9]+]]:_(s32) = G_IMPLICIT_DEF
+ ; CHECK-NEXT: G_STORE [[DEF]](s32), [[COPY]](p0) :: (store release (s32))
+ ; CHECK-NEXT: RET_ReallyLR
+ %0:_(p0) = COPY $x0
+ %1:_(s32) = G_IMPLICIT_DEF
+ G_STORE %1, %0 :: (store release (s32))
+ RET_ReallyLR
+
+...
+---
+name: store_undef_seq_cst
+tracksRegLiveness: true
+body: |
+ bb.0:
+ liveins: $x0
+
+ ; CHECK-LABEL: name: store_undef_seq_cst
+ ; CHECK: liveins: $x0
+ ; CHECK-NEXT: {{ $}}
+ ; CHECK-NEXT: [[COPY:%[0-9]+]]:_(p0) = COPY $x0
+ ; CHECK-NEXT: [[DEF:%[0-9]+]]:_(s32) = G_IMPLICIT_DEF
+ ; CHECK-NEXT: G_STORE [[DEF]](s32), [[COPY]](p0) :: (store seq_cst (s32))
+ ; CHECK-NEXT: RET_ReallyLR
+ %0:_(p0) = COPY $x0
+ %1:_(s32) = G_IMPLICIT_DEF
+ G_STORE %1, %0 :: (store seq_cst (s32))
+ RET_ReallyLR
+
+...
>From efd11c0ab6651223caffc66178865ce05afb46c9 Mon Sep 17 00:00:00 2001
From: Alex Maclean <amaclean at nvidia.com>
Date: Fri, 25 Sep 2026 13:14:36 -0700
Subject: [PATCH 2/2] [GlobalISel] Update AMDGPU checks for preserved undef
stores
Regenerate AMDGPU expectations for the preserved volatile stores. Remove the unused check prefixes and the redundant opcode assertion in matchUndefStore.
---
.../lib/CodeGen/GlobalISel/CombinerHelper.cpp | 1 -
llvm/test/CodeGen/AMDGPU/call-constant.ll | 6 ++++
.../CodeGen/AMDGPU/invalid-addrspacecast.ll | 28 ++++++++-----------
.../lower-work-group-id-intrinsics-pal.ll | 6 ++++
4 files changed, 24 insertions(+), 17 deletions(-)
diff --git a/llvm/lib/CodeGen/GlobalISel/CombinerHelper.cpp b/llvm/lib/CodeGen/GlobalISel/CombinerHelper.cpp
index 4bdfa20ee37c1a..849e145ed2de46 100644
--- a/llvm/lib/CodeGen/GlobalISel/CombinerHelper.cpp
+++ b/llvm/lib/CodeGen/GlobalISel/CombinerHelper.cpp
@@ -2745,7 +2745,6 @@ bool CombinerHelper::matchUndefShuffleVectorMask(MachineInstr &MI) const {
}
bool CombinerHelper::matchUndefStore(MachineInstr &MI) const {
- assert(MI.getOpcode() == TargetOpcode::G_STORE);
if (!cast<GStore>(MI).isUnordered())
return false;
return getOpcodeDef(TargetOpcode::G_IMPLICIT_DEF, MI.getOperand(0).getReg(),
diff --git a/llvm/test/CodeGen/AMDGPU/call-constant.ll b/llvm/test/CodeGen/AMDGPU/call-constant.ll
index 8757089cf5dad7..898e7bb6dc50f4 100644
--- a/llvm/test/CodeGen/AMDGPU/call-constant.ll
+++ b/llvm/test/CodeGen/AMDGPU/call-constant.ll
@@ -29,6 +29,8 @@ define amdgpu_kernel void @test_call_undef() #0 {
; GISEL-NEXT: s_mov_b32 s14, s16
; GISEL-NEXT: s_mov_b32 s32, 0
; GISEL-NEXT: s_swappc_b64 s[30:31], s[4:5]
+; GISEL-NEXT: flat_store_dword v[0:1], v0
+; GISEL-NEXT: s_waitcnt vmcnt(0)
; GISEL-NEXT: s_endpgm
%val = call i32 undef(i32 1)
%op = add i32 %val, 1
@@ -98,6 +100,10 @@ define amdgpu_kernel void @test_call_null() #0 {
; GISEL-NEXT: s_mov_b32 s14, s16
; GISEL-NEXT: s_mov_b32 s32, 0
; GISEL-NEXT: s_swappc_b64 s[30:31], 0
+; GISEL-NEXT: v_mov_b32_e32 v0, 0
+; GISEL-NEXT: v_mov_b32_e32 v1, 0
+; GISEL-NEXT: flat_store_dword v[0:1], v0
+; GISEL-NEXT: s_waitcnt vmcnt(0)
; GISEL-NEXT: s_endpgm
%val = call i32 null(i32 1)
%op = add i32 %val, 1
diff --git a/llvm/test/CodeGen/AMDGPU/invalid-addrspacecast.ll b/llvm/test/CodeGen/AMDGPU/invalid-addrspacecast.ll
index 2bc6f0bcdb711a..ac1a3507dd9fda 100644
--- a/llvm/test/CodeGen/AMDGPU/invalid-addrspacecast.ll
+++ b/llvm/test/CodeGen/AMDGPU/invalid-addrspacecast.ll
@@ -1,6 +1,6 @@
; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py UTC_ARGS: --version 5
-; RUN: llc -global-isel=0 -mtriple=amdgpu7.00-amd-amdhsa < %s | FileCheck --check-prefixes=CHECK,SDAG %s
-; RUN: llc -global-isel=1 -mtriple=amdgpu7.00-amd-amdhsa < %s | FileCheck --check-prefixes=CHECK,GISEL %s
+; RUN: llc -global-isel=0 -mtriple=amdgpu7.00-amd-amdhsa < %s | FileCheck %s
+; RUN: llc -global-isel=1 -mtriple=amdgpu7.00-amd-amdhsa < %s | FileCheck %s
; Check illegal casts are codegened as poison, and not an error.
@@ -42,20 +42,16 @@ define amdgpu_kernel void @use_constant32bit_to_local_addrspacecast(ptr addrspac
}
define amdgpu_kernel void @use_local_to_42_addrspacecast(ptr addrspace(3) %ptr) {
-; SDAG-LABEL: use_local_to_42_addrspacecast:
-; SDAG: ; %bb.0:
-; SDAG-NEXT: s_add_i32 s12, s12, s17
-; SDAG-NEXT: s_mov_b32 flat_scratch_lo, s13
-; SDAG-NEXT: s_lshr_b32 flat_scratch_hi, s12, 8
-; SDAG-NEXT: v_mov_b32_e32 v0, 0
-; SDAG-NEXT: v_mov_b32_e32 v1, 0
-; SDAG-NEXT: flat_store_dwordx2 v[0:1], v[0:1]
-; SDAG-NEXT: s_waitcnt vmcnt(0)
-; SDAG-NEXT: s_endpgm
-;
-; GISEL-LABEL: use_local_to_42_addrspacecast:
-; GISEL: ; %bb.0:
-; GISEL-NEXT: s_endpgm
+; CHECK-LABEL: use_local_to_42_addrspacecast:
+; CHECK: ; %bb.0:
+; CHECK-NEXT: s_add_i32 s12, s12, s17
+; CHECK-NEXT: s_mov_b32 flat_scratch_lo, s13
+; CHECK-NEXT: s_lshr_b32 flat_scratch_hi, s12, 8
+; CHECK-NEXT: v_mov_b32_e32 v0, 0
+; CHECK-NEXT: v_mov_b32_e32 v1, 0
+; CHECK-NEXT: flat_store_dwordx2 v[0:1], v[0:1]
+; CHECK-NEXT: s_waitcnt vmcnt(0)
+; CHECK-NEXT: s_endpgm
%cast = addrspacecast ptr addrspace(3) %ptr to ptr addrspace(42)
store volatile ptr addrspace(42) %cast, ptr addrspace(1) null
ret void
diff --git a/llvm/test/CodeGen/AMDGPU/lower-work-group-id-intrinsics-pal.ll b/llvm/test/CodeGen/AMDGPU/lower-work-group-id-intrinsics-pal.ll
index e3c4cab6fa2f0c..092872c8749e8d 100644
--- a/llvm/test/CodeGen/AMDGPU/lower-work-group-id-intrinsics-pal.ll
+++ b/llvm/test/CodeGen/AMDGPU/lower-work-group-id-intrinsics-pal.ll
@@ -180,6 +180,12 @@ define amdgpu_gfx void @workgroup_ids_gfx(ptr addrspace(1) %outx, ptr addrspace(
; GFX9-GISEL-LABEL: workgroup_ids_gfx:
; GFX9-GISEL: ; %bb.0:
; GFX9-GISEL-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0)
+; GFX9-GISEL-NEXT: global_store_dword v[0:1], v0, off
+; GFX9-GISEL-NEXT: s_waitcnt vmcnt(0)
+; GFX9-GISEL-NEXT: global_store_dword v[2:3], v0, off
+; GFX9-GISEL-NEXT: s_waitcnt vmcnt(0)
+; GFX9-GISEL-NEXT: global_store_dword v[4:5], v0, off
+; GFX9-GISEL-NEXT: s_waitcnt vmcnt(0)
; GFX9-GISEL-NEXT: s_setpc_b64 s[30:31]
;
; GFX9ARCH-SDAG-LABEL: workgroup_ids_gfx:
More information about the llvm-commits
mailing list