[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