[llvm] [AMDGPU] Fix incorrect VM_VSRC simplification after async instruction (PR #212481)

Jay Foad via llvm-commits llvm-commits at lists.llvm.org
Tue Jul 28 06:26:50 PDT 2026


https://github.com/jayfoad updated https://github.com/llvm/llvm-project/pull/212481

>From 85154126e771acc513fa58b701391815b546a683 Mon Sep 17 00:00:00 2001
From: Jay Foad <jay.foad at amd.com>
Date: Tue, 28 Jul 2026 13:38:47 +0100
Subject: [PATCH 1/4] Precommit test

---
 .../CodeGen/AMDGPU/soft-waitcnt-deletion.mir  | 431 ++++++++++++++++++
 1 file changed, 431 insertions(+)
 create mode 100644 llvm/test/CodeGen/AMDGPU/soft-waitcnt-deletion.mir

diff --git a/llvm/test/CodeGen/AMDGPU/soft-waitcnt-deletion.mir b/llvm/test/CodeGen/AMDGPU/soft-waitcnt-deletion.mir
new file mode 100644
index 0000000000000..7b9060243e98c
--- /dev/null
+++ b/llvm/test/CodeGen/AMDGPU/soft-waitcnt-deletion.mir
@@ -0,0 +1,431 @@
+# NOTE: Assertions have been autogenerated by utils/update_mir_test_checks.py UTC_ARGS: --version 6
+# RUN: llc -mtriple=amdgcn-amd-amdhsa -mcpu=gfx1250 -run-pass=si-insert-waitcnts -amdgpu-expert-scheduling-mode -o - %s | FileCheck %s
+
+---
+name:            soft_wait_before_s_barrier
+tracksRegLiveness: true
+machineFunctionInfo:
+  isEntryFunction: true
+body:             |
+  ; CHECK-LABEL: name: soft_wait_before_s_barrier
+  ; CHECK: bb.0:
+  ; CHECK-NEXT:   successors: %bb.1(0x80000000)
+  ; CHECK-NEXT: {{  $}}
+  ; CHECK-NEXT:   GLOBAL_PREFETCH_B8_SADDR undef $sgpr0_sgpr1, undef $vgpr0, 0, 8, implicit $exec
+  ; CHECK-NEXT:   V_NOP_e32 implicit $exec
+  ; CHECK-NEXT:   S_SETREG_IMM32_B32 2, 2074, implicit-def $mode, implicit $mode
+  ; CHECK-NEXT:   renamable $vgpr17 = V_MOV_B32_e32 0, implicit $exec
+  ; CHECK-NEXT:   renamable $vgpr32_vgpr33 = V_MOV_B64_e32 0, implicit $exec
+  ; CHECK-NEXT:   $vcc_lo = S_MOV_B32 $exec_lo
+  ; CHECK-NEXT:   S_WAITCNT_DEPCTR .VaVdst_1
+  ; CHECK-NEXT:   renamable $vgpr0 = DS_READ_B32_gfx9 renamable $vgpr17, 0, 0, implicit $exec
+  ; CHECK-NEXT:   S_WAIT_DSCNT 0
+  ; CHECK-NEXT: {{  $}}
+  ; CHECK-NEXT: bb.1:
+  ; CHECK-NEXT:   successors: %bb.2(0x40000000), %bb.1(0x40000000)
+  ; CHECK-NEXT:   liveins: $vgpr32_vgpr33, $vgpr17, $vgpr0, $vcc_lo
+  ; CHECK-NEXT: {{  $}}
+  ; CHECK-NEXT:   S_BARRIER_SIGNAL_IMM -1
+  ; CHECK-NEXT:   $vgpr1 = V_MOV_B32_e32 $vgpr0, implicit $exec
+  ; CHECK-NEXT:   S_WAITCNT_DEPCTR .VaVdst_1
+  ; CHECK-NEXT:   GLOBAL_LOAD_ASYNC_TO_LDS_B64 $vgpr17, $vgpr32_vgpr33, 0, 0, implicit-def dead $asynccnt, implicit $exec, implicit $asynccnt
+  ; CHECK-NEXT:   S_CBRANCH_VCCNZ %bb.1, implicit $vcc_lo, implicit $vcc_lo
+  ; CHECK-NEXT: {{  $}}
+  ; CHECK-NEXT: bb.2:
+  ; CHECK-NEXT:   S_ENDPGM 0
+  bb.0:
+    successors: %bb.1
+
+    renamable $vgpr17 = V_MOV_B32_e32 0, implicit $exec
+    renamable $vgpr32_vgpr33 = V_MOV_B64_e32 0, implicit $exec
+    $vcc_lo = S_MOV_B32 $exec_lo
+    renamable $vgpr0 = DS_READ_B32_gfx9 renamable $vgpr17, 0, 0, implicit $exec
+
+  bb.1:
+    successors: %bb.2, %bb.1
+    liveins: $vgpr32_vgpr33, $vgpr17, $vgpr0, $vcc_lo
+
+    S_WAIT_DSCNT_soft 0
+    S_BARRIER_SIGNAL_IMM -1
+    $vgpr1 = V_MOV_B32_e32 $vgpr0, implicit $exec
+    GLOBAL_LOAD_ASYNC_TO_LDS_B64 $vgpr17, $vgpr32_vgpr33, 0, 0, implicit-def dead $asynccnt, implicit $exec, implicit $asynccnt
+    S_CBRANCH_VCCNZ %bb.1, implicit $vcc_lo, implicit $vcc
+
+  bb.2:
+    S_ENDPGM 0
+...
+
+---
+name:            soft_wait_multipath_first_pred_needs_wait
+tracksRegLiveness: true
+machineFunctionInfo:
+  isEntryFunction: true
+body:             |
+  ; CHECK-LABEL: name: soft_wait_multipath_first_pred_needs_wait
+  ; CHECK: bb.0:
+  ; CHECK-NEXT:   successors: %bb.1(0x40000000), %bb.2(0x40000000)
+  ; CHECK-NEXT:   liveins: $sgpr0
+  ; CHECK-NEXT: {{  $}}
+  ; CHECK-NEXT:   GLOBAL_PREFETCH_B8_SADDR undef $sgpr0_sgpr1, undef $vgpr0, 0, 8, implicit $exec
+  ; CHECK-NEXT:   V_NOP_e32 implicit $exec
+  ; CHECK-NEXT:   S_SETREG_IMM32_B32 2, 2074, implicit-def $mode, implicit $mode
+  ; CHECK-NEXT:   $vgpr0 = V_MOV_B32_e32 0, implicit $exec
+  ; CHECK-NEXT:   S_CMP_EQ_U32 $sgpr0, 0, implicit-def $scc
+  ; CHECK-NEXT:   S_CBRANCH_SCC1 %bb.2, implicit $scc
+  ; CHECK-NEXT: {{  $}}
+  ; CHECK-NEXT: bb.1:
+  ; CHECK-NEXT:   successors: %bb.3(0x80000000)
+  ; CHECK-NEXT:   liveins: $vgpr0
+  ; CHECK-NEXT: {{  $}}
+  ; CHECK-NEXT:   S_WAITCNT_DEPCTR .VaVdst_0
+  ; CHECK-NEXT:   $vgpr1 = DS_READ_B32_gfx9 $vgpr0, 0, 0, implicit $exec
+  ; CHECK-NEXT:   S_BRANCH %bb.3
+  ; CHECK-NEXT: {{  $}}
+  ; CHECK-NEXT: bb.2:
+  ; CHECK-NEXT:   successors: %bb.3(0x80000000)
+  ; CHECK-NEXT:   liveins: $vgpr0
+  ; CHECK-NEXT: {{  $}}
+  ; CHECK-NEXT:   $vgpr1 = V_MOV_B32_e32 42, implicit $exec
+  ; CHECK-NEXT: {{  $}}
+  ; CHECK-NEXT: bb.3:
+  ; CHECK-NEXT:   liveins: $vgpr0, $vgpr1
+  ; CHECK-NEXT: {{  $}}
+  ; CHECK-NEXT:   S_WAIT_DSCNT 0
+  ; CHECK-NEXT:   S_BARRIER_SIGNAL_IMM -1
+  ; CHECK-NEXT:   $vgpr2 = V_MOV_B32_e32 $vgpr1, implicit $exec
+  ; CHECK-NEXT:   S_ENDPGM 0
+  bb.0:
+    successors: %bb.1(0x40000000), %bb.2(0x40000000)
+    liveins: $sgpr0
+
+    $vgpr0 = V_MOV_B32_e32 0, implicit $exec
+    S_CMP_EQ_U32 $sgpr0, 0, implicit-def $scc
+    S_CBRANCH_SCC1 %bb.2, implicit $scc
+
+  bb.1:
+    successors: %bb.3(0x80000000)
+    liveins: $vgpr0
+
+    $vgpr1 = DS_READ_B32_gfx9 $vgpr0, 0, 0, implicit $exec
+    S_BRANCH %bb.3
+
+  bb.2:
+    successors: %bb.3(0x80000000)
+    liveins: $vgpr0
+
+    $vgpr1 = V_MOV_B32_e32 42, implicit $exec
+
+  bb.3:
+    liveins: $vgpr0, $vgpr1
+
+    S_WAIT_DSCNT_soft 0
+    S_BARRIER_SIGNAL_IMM -1
+    $vgpr2 = V_MOV_B32_e32 $vgpr1, implicit $exec
+    S_ENDPGM 0
+...
+
+---
+name:            soft_wait_second_pred_needs_wait
+tracksRegLiveness: true
+machineFunctionInfo:
+  isEntryFunction: true
+body:             |
+  ; CHECK-LABEL: name: soft_wait_second_pred_needs_wait
+  ; CHECK: bb.0:
+  ; CHECK-NEXT:   successors: %bb.1(0x40000000), %bb.2(0x40000000)
+  ; CHECK-NEXT:   liveins: $sgpr0
+  ; CHECK-NEXT: {{  $}}
+  ; CHECK-NEXT:   GLOBAL_PREFETCH_B8_SADDR undef $sgpr0_sgpr1, undef $vgpr0, 0, 8, implicit $exec
+  ; CHECK-NEXT:   V_NOP_e32 implicit $exec
+  ; CHECK-NEXT:   S_SETREG_IMM32_B32 2, 2074, implicit-def $mode, implicit $mode
+  ; CHECK-NEXT:   $vgpr0 = V_MOV_B32_e32 0, implicit $exec
+  ; CHECK-NEXT:   S_CMP_EQ_U32 $sgpr0, 0, implicit-def $scc
+  ; CHECK-NEXT:   S_CBRANCH_SCC1 %bb.2, implicit $scc
+  ; CHECK-NEXT: {{  $}}
+  ; CHECK-NEXT: bb.1:
+  ; CHECK-NEXT:   successors: %bb.3(0x80000000)
+  ; CHECK-NEXT:   liveins: $vgpr0
+  ; CHECK-NEXT: {{  $}}
+  ; CHECK-NEXT:   $vgpr1 = V_MOV_B32_e32 42, implicit $exec
+  ; CHECK-NEXT:   S_BRANCH %bb.3
+  ; CHECK-NEXT: {{  $}}
+  ; CHECK-NEXT: bb.2:
+  ; CHECK-NEXT:   successors: %bb.3(0x80000000)
+  ; CHECK-NEXT:   liveins: $vgpr0
+  ; CHECK-NEXT: {{  $}}
+  ; CHECK-NEXT:   S_WAITCNT_DEPCTR .VaVdst_0
+  ; CHECK-NEXT:   $vgpr1 = DS_READ_B32_gfx9 $vgpr0, 0, 0, implicit $exec
+  ; CHECK-NEXT: {{  $}}
+  ; CHECK-NEXT: bb.3:
+  ; CHECK-NEXT:   liveins: $vgpr0, $vgpr1
+  ; CHECK-NEXT: {{  $}}
+  ; CHECK-NEXT:   S_WAIT_DSCNT 0
+  ; CHECK-NEXT:   $vgpr2 = V_MOV_B32_e32 $vgpr1, implicit $exec
+  ; CHECK-NEXT:   S_ENDPGM 0
+  bb.0:
+    successors: %bb.1(0x40000000), %bb.2(0x40000000)
+    liveins: $sgpr0
+
+    $vgpr0 = V_MOV_B32_e32 0, implicit $exec
+    S_CMP_EQ_U32 $sgpr0, 0, implicit-def $scc
+    S_CBRANCH_SCC1 %bb.2, implicit $scc
+
+  bb.1:
+    successors: %bb.3(0x80000000)
+    liveins: $vgpr0
+
+    $vgpr1 = V_MOV_B32_e32 42, implicit $exec
+    S_BRANCH %bb.3
+
+  bb.2:
+    successors: %bb.3(0x80000000)
+    liveins: $vgpr0
+
+    $vgpr1 = DS_READ_B32_gfx9 $vgpr0, 0, 0, implicit $exec
+
+  bb.3:
+    liveins: $vgpr0, $vgpr1
+
+    S_WAIT_DSCNT_soft 0
+    $vgpr2 = V_MOV_B32_e32 $vgpr1, implicit $exec
+    S_ENDPGM 0
+...
+
+# Test that soft wait in RequiredWait does not incorrectly simplify VM_VSRC.
+# When processing from the path without DS operations first:
+# - soft S_WAIT_DSCNT goes to RequiredWait (AllowWaitDeletion=false)
+# - hard S_WAITCNT_DEPCTR with VM_VSRC=0 goes to Wait
+# If we incorrectly used RequiredWait in simplifyVmVsrc's CheckWait,
+# the VM_VSRC would be simplified away because DS_CNT=0 is present.
+# Then when the soft wait is deleted (not needed from second path),
+# we'd lose the required VM_VSRC wait.
+---
+name:            soft_wait_does_not_simplify_vm_vsrc
+tracksRegLiveness: true
+machineFunctionInfo:
+  isEntryFunction: true
+body:             |
+  ; CHECK-LABEL: name: soft_wait_does_not_simplify_vm_vsrc
+  ; CHECK: bb.0:
+  ; CHECK-NEXT:   successors: %bb.1(0x40000000), %bb.2(0x40000000)
+  ; CHECK-NEXT:   liveins: $sgpr0, $sgpr0_sgpr1_sgpr2_sgpr3_sgpr4_sgpr5_sgpr6_sgpr7, $vgpr0
+  ; CHECK-NEXT: {{  $}}
+  ; CHECK-NEXT:   GLOBAL_PREFETCH_B8_SADDR undef $sgpr0_sgpr1, undef $vgpr0, 0, 8, implicit $exec
+  ; CHECK-NEXT:   V_NOP_e32 implicit $exec
+  ; CHECK-NEXT:   S_SETREG_IMM32_B32 2, 2074, implicit-def $mode, implicit $mode
+  ; CHECK-NEXT:   S_CMP_EQ_U32 $sgpr0, 0, implicit-def $scc
+  ; CHECK-NEXT:   S_CBRANCH_SCC1 %bb.2, implicit $scc
+  ; CHECK-NEXT: {{  $}}
+  ; CHECK-NEXT: bb.1:
+  ; CHECK-NEXT:   successors: %bb.3(0x80000000)
+  ; CHECK-NEXT:   liveins: $vgpr0
+  ; CHECK-NEXT: {{  $}}
+  ; CHECK-NEXT:   $vgpr1 = DS_READ_B32_gfx9 $vgpr0, 0, 0, implicit $exec
+  ; CHECK-NEXT:   S_BRANCH %bb.3
+  ; CHECK-NEXT: {{  $}}
+  ; CHECK-NEXT: bb.2:
+  ; CHECK-NEXT:   successors: %bb.3(0x80000000)
+  ; CHECK-NEXT:   liveins: $sgpr0_sgpr1_sgpr2_sgpr3_sgpr4_sgpr5_sgpr6_sgpr7, $vgpr0
+  ; CHECK-NEXT: {{  $}}
+  ; CHECK-NEXT:   $vgpr0_vgpr1_vgpr2_vgpr3 = IMAGE_LOAD_V4_V1_gfx12 $vgpr0, $sgpr0_sgpr1_sgpr2_sgpr3_sgpr4_sgpr5_sgpr6_sgpr7, 15, 0, 0, 0, 0, 0, 0, implicit $exec :: (dereferenceable load (s128), addrspace 8)
+  ; CHECK-NEXT: {{  $}}
+  ; CHECK-NEXT: bb.3:
+  ; CHECK-NEXT:   liveins: $vgpr0, $vgpr1
+  ; CHECK-NEXT: {{  $}}
+  ; CHECK-NEXT:   S_WAITCNT_DEPCTR .VmVsrc_0
+  ; CHECK-NEXT:   S_WAIT_LOADCNT_DSCNT .Loadcnt_0_Dscnt_0
+  ; CHECK-NEXT:   $vgpr4 = V_ADD_F32_e32 $vgpr0, $vgpr1, implicit $mode, implicit $exec
+  ; CHECK-NEXT:   S_ENDPGM 0
+  bb.0:
+    successors: %bb.1(0x40000000), %bb.2(0x40000000)
+    liveins: $sgpr0, $sgpr0_sgpr1_sgpr2_sgpr3_sgpr4_sgpr5_sgpr6_sgpr7, $vgpr0
+
+    S_CMP_EQ_U32 $sgpr0, 0, implicit-def $scc
+    S_CBRANCH_SCC1 %bb.2, implicit $scc
+
+  bb.1:
+    successors: %bb.3(0x80000000)
+    liveins: $vgpr0
+
+    ; DS operation - requires DS_CNT wait
+    $vgpr1 = DS_READ_B32_gfx9 $vgpr0, 0, 0, implicit $exec
+    S_BRANCH %bb.3
+
+  bb.2:
+    successors: %bb.3(0x80000000)
+    liveins: $sgpr0_sgpr1_sgpr2_sgpr3_sgpr4_sgpr5_sgpr6_sgpr7, $vgpr0
+
+    $vgpr0_vgpr1_vgpr2_vgpr3 = IMAGE_LOAD_V4_V1_gfx12 $vgpr0, $sgpr0_sgpr1_sgpr2_sgpr3_sgpr4_sgpr5_sgpr6_sgpr7, 15, 0, 0, 0, 0, 0, 0, implicit $exec :: (dereferenceable load (s128), addrspace 8)
+
+  bb.3:
+    liveins: $vgpr0, $vgpr1
+
+    S_WAIT_DSCNT_soft 0
+    S_WAITCNT_DEPCTR .VmVsrc_0
+    $vgpr4 = V_ADD_F32_e32 $vgpr0, $vgpr1, implicit $mode, implicit $exec
+    S_ENDPGM 0
+...
+
+---
+name:            soft_wait_no_vmsrc_simplify
+tracksRegLiveness: true
+machineFunctionInfo:
+  isEntryFunction: true
+body:             |
+  ; CHECK-LABEL: name: soft_wait_no_vmsrc_simplify
+  ; CHECK: bb.0:
+  ; CHECK-NEXT:   successors: %bb.1(0x80000000)
+  ; CHECK-NEXT: {{  $}}
+  ; CHECK-NEXT:   GLOBAL_PREFETCH_B8_SADDR undef $sgpr0_sgpr1, undef $vgpr0, 0, 8, implicit $exec
+  ; CHECK-NEXT:   V_NOP_e32 implicit $exec
+  ; CHECK-NEXT:   S_SETREG_IMM32_B32 2, 2074, implicit-def $mode, implicit $mode
+  ; CHECK-NEXT:   renamable $vgpr17 = V_MOV_B32_e32 0, implicit $exec
+  ; CHECK-NEXT:   renamable $vgpr32_vgpr33 = V_MOV_B64_e32 0, implicit $exec
+  ; CHECK-NEXT:   $vcc_lo = S_MOV_B32 $exec_lo
+  ; CHECK-NEXT:   S_WAITCNT_DEPCTR .VaVdst_1
+  ; CHECK-NEXT:   renamable $vgpr0 = DS_READ_B32_gfx9 renamable $vgpr17, 0, 0, implicit $exec
+  ; CHECK-NEXT:   S_WAIT_DSCNT 0
+  ; CHECK-NEXT: {{  $}}
+  ; CHECK-NEXT: bb.1:
+  ; CHECK-NEXT:   successors: %bb.2(0x40000000), %bb.1(0x40000000)
+  ; CHECK-NEXT:   liveins: $vgpr32_vgpr33, $vgpr17, $vgpr0, $vcc_lo
+  ; CHECK-NEXT: {{  $}}
+  ; CHECK-NEXT:   S_WAITCNT_DEPCTR .VaVdst_0
+  ; CHECK-NEXT:   GLOBAL_LOAD_ASYNC_TO_LDS_B64 $vgpr17, $vgpr32_vgpr33, 0, 0, implicit-def dead $asynccnt, implicit $exec, implicit $asynccnt
+  ; CHECK-NEXT:   S_WAITCNT_DEPCTR .VmVsrc_0
+  ; CHECK-NEXT:   $vgpr17 = V_MOV_B32_e32 $vgpr0, implicit $exec
+  ; CHECK-NEXT:   S_BARRIER_SIGNAL_IMM -1
+  ; CHECK-NEXT:   S_CBRANCH_VCCNZ %bb.1, implicit $vcc_lo, implicit $vcc_lo
+  ; CHECK-NEXT: {{  $}}
+  ; CHECK-NEXT: bb.2:
+  ; CHECK-NEXT:   S_ENDPGM 0
+  bb.0:
+    successors: %bb.1
+
+    renamable $vgpr17 = V_MOV_B32_e32 0, implicit $exec
+    renamable $vgpr32_vgpr33 = V_MOV_B64_e32 0, implicit $exec
+    $vcc_lo = S_MOV_B32 $exec_lo
+    renamable $vgpr0 = DS_READ_B32_gfx9 renamable $vgpr17, 0, 0, implicit $exec
+
+  bb.1:
+    successors: %bb.2, %bb.1
+    liveins: $vgpr32_vgpr33, $vgpr17, $vgpr0, $vcc_lo
+    GLOBAL_LOAD_ASYNC_TO_LDS_B64 $vgpr17, $vgpr32_vgpr33, 0, 0, implicit-def dead $asynccnt, implicit $exec, implicit $asynccnt
+    S_WAIT_DSCNT_soft 0
+    $vgpr17 = V_MOV_B32_e32 $vgpr0, implicit $exec
+    S_BARRIER_SIGNAL_IMM -1
+    S_CBRANCH_VCCNZ %bb.1, implicit $vcc_lo, implicit $vcc
+
+  bb.2:
+    S_ENDPGM 0
+...
+
+---
+name:            soft_wait_no_vmsrc_simplify2
+tracksRegLiveness: true
+machineFunctionInfo:
+  isEntryFunction: true
+body:             |
+  ; CHECK-LABEL: name: soft_wait_no_vmsrc_simplify2
+  ; CHECK: bb.0:
+  ; CHECK-NEXT:   successors: %bb.1(0x80000000)
+  ; CHECK-NEXT: {{  $}}
+  ; CHECK-NEXT:   GLOBAL_PREFETCH_B8_SADDR undef $sgpr0_sgpr1, undef $vgpr0, 0, 8, implicit $exec
+  ; CHECK-NEXT:   V_NOP_e32 implicit $exec
+  ; CHECK-NEXT:   S_SETREG_IMM32_B32 2, 2074, implicit-def $mode, implicit $mode
+  ; CHECK-NEXT:   renamable $vgpr17 = V_MOV_B32_e32 0, implicit $exec
+  ; CHECK-NEXT:   renamable $vgpr32_vgpr33 = V_MOV_B64_e32 0, implicit $exec
+  ; CHECK-NEXT:   $vcc_lo = S_MOV_B32 $exec_lo
+  ; CHECK-NEXT:   S_WAITCNT_DEPCTR .VaVdst_1
+  ; CHECK-NEXT:   renamable $vgpr0 = DS_READ_B32_gfx9 renamable $vgpr17, 0, 0, implicit $exec
+  ; CHECK-NEXT:   S_WAIT_DSCNT 0
+  ; CHECK-NEXT: {{  $}}
+  ; CHECK-NEXT: bb.1:
+  ; CHECK-NEXT:   successors: %bb.2(0x40000000), %bb.1(0x40000000)
+  ; CHECK-NEXT:   liveins: $vgpr32_vgpr33, $vgpr17, $vgpr0, $vcc_lo
+  ; CHECK-NEXT: {{  $}}
+  ; CHECK-NEXT:   S_WAITCNT_DEPCTR .VmVsrc_0
+  ; CHECK-NEXT:   $vgpr17 = V_MOV_B32_e32 $vgpr0, implicit $exec
+  ; CHECK-NEXT:   S_BARRIER_SIGNAL_IMM -1
+  ; CHECK-NEXT:   S_WAITCNT_DEPCTR .VaVdst_0
+  ; CHECK-NEXT:   GLOBAL_LOAD_ASYNC_TO_LDS_B64 $vgpr17, $vgpr32_vgpr33, 0, 0, implicit-def dead $asynccnt, implicit $exec, implicit $asynccnt
+  ; CHECK-NEXT:   S_CBRANCH_VCCNZ %bb.1, implicit $vcc_lo, implicit $vcc_lo
+  ; CHECK-NEXT: {{  $}}
+  ; CHECK-NEXT: bb.2:
+  ; CHECK-NEXT:   S_ENDPGM 0
+  bb.0:
+    successors: %bb.1
+
+    renamable $vgpr17 = V_MOV_B32_e32 0, implicit $exec
+    renamable $vgpr32_vgpr33 = V_MOV_B64_e32 0, implicit $exec
+    $vcc_lo = S_MOV_B32 $exec_lo
+    renamable $vgpr0 = DS_READ_B32_gfx9 renamable $vgpr17, 0, 0, implicit $exec
+
+  bb.1:
+    successors: %bb.2, %bb.1
+    liveins: $vgpr32_vgpr33, $vgpr17, $vgpr0, $vcc_lo
+    S_WAIT_DSCNT_soft 0
+    $vgpr17 = V_MOV_B32_e32 $vgpr0, implicit $exec
+    S_BARRIER_SIGNAL_IMM -1
+    GLOBAL_LOAD_ASYNC_TO_LDS_B64 $vgpr17, $vgpr32_vgpr33, 0, 0, implicit-def dead $asynccnt, implicit $exec, implicit $asynccnt
+    S_CBRANCH_VCCNZ %bb.1, implicit $vcc_lo, implicit $vcc
+
+  bb.2:
+    S_ENDPGM 0
+...
+
+---
+name:            soft_wait_promote_simplify
+tracksRegLiveness: true
+machineFunctionInfo:
+  isEntryFunction: true
+body:             |
+  ; CHECK-LABEL: name: soft_wait_promote_simplify
+  ; CHECK: bb.0:
+  ; CHECK-NEXT:   successors: %bb.1(0x80000000)
+  ; CHECK-NEXT: {{  $}}
+  ; CHECK-NEXT:   GLOBAL_PREFETCH_B8_SADDR undef $sgpr0_sgpr1, undef $vgpr0, 0, 8, implicit $exec
+  ; CHECK-NEXT:   V_NOP_e32 implicit $exec
+  ; CHECK-NEXT:   S_SETREG_IMM32_B32 2, 2074, implicit-def $mode, implicit $mode
+  ; CHECK-NEXT:   renamable $vgpr17 = V_MOV_B32_e32 0, implicit $exec
+  ; CHECK-NEXT:   renamable $vgpr32_vgpr33 = V_MOV_B64_e32 0, implicit $exec
+  ; CHECK-NEXT:   $vcc_lo = S_MOV_B32 $exec_lo
+  ; CHECK-NEXT:   S_WAITCNT_DEPCTR .VaVdst_1
+  ; CHECK-NEXT:   renamable $vgpr0 = DS_READ_B32_gfx9 renamable $vgpr17, 0, 0, implicit $exec
+  ; CHECK-NEXT:   S_WAIT_DSCNT 0
+  ; CHECK-NEXT: {{  $}}
+  ; CHECK-NEXT: bb.1:
+  ; CHECK-NEXT:   successors: %bb.2(0x40000000), %bb.1(0x40000000)
+  ; CHECK-NEXT:   liveins: $vgpr32_vgpr33, $vgpr17, $vgpr0, $vcc_lo
+  ; CHECK-NEXT: {{  $}}
+  ; CHECK-NEXT:   S_WAIT_DSCNT 0
+  ; CHECK-NEXT:   $vgpr17 = V_MOV_B32_e32 $vgpr0, implicit $exec
+  ; CHECK-NEXT:   S_BARRIER_SIGNAL_IMM -1
+  ; CHECK-NEXT:   S_WAITCNT_DEPCTR .VaVdst_0
+  ; CHECK-NEXT:   GLOBAL_LOAD_ASYNC_TO_LDS_B64 $vgpr17, $vgpr32_vgpr33, 0, 0, implicit-def dead $asynccnt, implicit $exec, implicit $asynccnt
+  ; CHECK-NEXT:   renamable $vgpr0 = DS_READ_B32_gfx9 renamable $vgpr17, 0, 0, implicit $exec
+  ; CHECK-NEXT:   S_CBRANCH_VCCNZ %bb.1, implicit $vcc_lo, implicit $vcc_lo
+  ; CHECK-NEXT: {{  $}}
+  ; CHECK-NEXT: bb.2:
+  ; CHECK-NEXT:   S_ENDPGM 0
+  bb.0:
+    successors: %bb.1
+
+    renamable $vgpr17 = V_MOV_B32_e32 0, implicit $exec
+    renamable $vgpr32_vgpr33 = V_MOV_B64_e32 0, implicit $exec
+    $vcc_lo = S_MOV_B32 $exec_lo
+    renamable $vgpr0 = DS_READ_B32_gfx9 renamable $vgpr17, 0, 0, implicit $exec
+
+  bb.1:
+    successors: %bb.2, %bb.1
+    liveins: $vgpr32_vgpr33, $vgpr17, $vgpr0, $vcc_lo
+    S_WAIT_DSCNT_soft 0
+    $vgpr17 = V_MOV_B32_e32 $vgpr0, implicit $exec
+    S_BARRIER_SIGNAL_IMM -1
+    GLOBAL_LOAD_ASYNC_TO_LDS_B64 $vgpr17, $vgpr32_vgpr33, 0, 0, implicit-def dead $asynccnt, implicit $exec, implicit $asynccnt
+    renamable $vgpr0 = DS_READ_B32_gfx9 renamable $vgpr17, 0, 0, implicit $exec
+    S_CBRANCH_VCCNZ %bb.1, implicit $vcc_lo, implicit $vcc
+
+  bb.2:
+    S_ENDPGM 0
+...

>From 59385ccdf3a6a858df042c7463bcaba49139897b Mon Sep 17 00:00:00 2001
From: Jay Foad <jay.foad at amd.com>
Date: Tue, 28 Jul 2026 13:39:30 +0100
Subject: [PATCH 2/4] Fix incorrect vm_vsrc simplification

---
 llvm/lib/Target/AMDGPU/SIInsertWaitcnts.cpp        | 2 +-
 llvm/test/CodeGen/AMDGPU/soft-waitcnt-deletion.mir | 1 +
 2 files changed, 2 insertions(+), 1 deletion(-)

diff --git a/llvm/lib/Target/AMDGPU/SIInsertWaitcnts.cpp b/llvm/lib/Target/AMDGPU/SIInsertWaitcnts.cpp
index 22247238d5542..2a694d6354193 100644
--- a/llvm/lib/Target/AMDGPU/SIInsertWaitcnts.cpp
+++ b/llvm/lib/Target/AMDGPU/SIInsertWaitcnts.cpp
@@ -1323,7 +1323,7 @@ void WaitcntBrackets::simplifyVmVsrc(const AMDGPU::Waitcnt &CheckWait,
   // operations that use a different counter (like SAMPLE_CNT).
   static constexpr AMDGPU::InstCounterType VmemCounters[] = {
       AMDGPU::LOAD_CNT, AMDGPU::STORE_CNT, AMDGPU::SAMPLE_CNT, AMDGPU::BVH_CNT,
-      AMDGPU::DS_CNT};
+      AMDGPU::DS_CNT, AMDGPU::ASYNC_CNT, AMDGPU::TENSOR_CNT};
   HWEvents VmemEvents = llvm::accumulate(
       VmemCounters, HWEvents(), [&](HWEvents Acc, AMDGPU::InstCounterType T) {
         return Acc | Context->getWaitEvents(T);
diff --git a/llvm/test/CodeGen/AMDGPU/soft-waitcnt-deletion.mir b/llvm/test/CodeGen/AMDGPU/soft-waitcnt-deletion.mir
index 7b9060243e98c..76ec64772f2cf 100644
--- a/llvm/test/CodeGen/AMDGPU/soft-waitcnt-deletion.mir
+++ b/llvm/test/CodeGen/AMDGPU/soft-waitcnt-deletion.mir
@@ -399,6 +399,7 @@ body:             |
   ; CHECK-NEXT:   liveins: $vgpr32_vgpr33, $vgpr17, $vgpr0, $vcc_lo
   ; CHECK-NEXT: {{  $}}
   ; CHECK-NEXT:   S_WAIT_DSCNT 0
+  ; CHECK-NEXT:   S_WAITCNT_DEPCTR .VmVsrc_0
   ; CHECK-NEXT:   $vgpr17 = V_MOV_B32_e32 $vgpr0, implicit $exec
   ; CHECK-NEXT:   S_BARRIER_SIGNAL_IMM -1
   ; CHECK-NEXT:   S_WAITCNT_DEPCTR .VaVdst_0

>From 5e98d190d428368cbdaf9dc792879e01fe6bac50 Mon Sep 17 00:00:00 2001
From: Jay Foad <jay.foad at amd.com>
Date: Tue, 28 Jul 2026 14:05:32 +0100
Subject: [PATCH 3/4] clang-format

---
 llvm/lib/Target/AMDGPU/SIInsertWaitcnts.cpp | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/llvm/lib/Target/AMDGPU/SIInsertWaitcnts.cpp b/llvm/lib/Target/AMDGPU/SIInsertWaitcnts.cpp
index 2a694d6354193..15580b101ebcb 100644
--- a/llvm/lib/Target/AMDGPU/SIInsertWaitcnts.cpp
+++ b/llvm/lib/Target/AMDGPU/SIInsertWaitcnts.cpp
@@ -1323,7 +1323,7 @@ void WaitcntBrackets::simplifyVmVsrc(const AMDGPU::Waitcnt &CheckWait,
   // operations that use a different counter (like SAMPLE_CNT).
   static constexpr AMDGPU::InstCounterType VmemCounters[] = {
       AMDGPU::LOAD_CNT, AMDGPU::STORE_CNT, AMDGPU::SAMPLE_CNT, AMDGPU::BVH_CNT,
-      AMDGPU::DS_CNT, AMDGPU::ASYNC_CNT, AMDGPU::TENSOR_CNT};
+      AMDGPU::DS_CNT,   AMDGPU::ASYNC_CNT, AMDGPU::TENSOR_CNT};
   HWEvents VmemEvents = llvm::accumulate(
       VmemCounters, HWEvents(), [&](HWEvents Acc, AMDGPU::InstCounterType T) {
         return Acc | Context->getWaitEvents(T);

>From 560a8a498eb9a6cbd8b1e6de165c390b144ff6ef Mon Sep 17 00:00:00 2001
From: Jay Foad <jay.foad at gmail.com>
Date: Tue, 28 Jul 2026 14:26:39 +0100
Subject: [PATCH 4/4] Update llvm/test/CodeGen/AMDGPU/soft-waitcnt-deletion.mir

Co-authored-by: Matt Arsenault <arsenm2 at gmail.com>
---
 llvm/test/CodeGen/AMDGPU/soft-waitcnt-deletion.mir | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/llvm/test/CodeGen/AMDGPU/soft-waitcnt-deletion.mir b/llvm/test/CodeGen/AMDGPU/soft-waitcnt-deletion.mir
index 76ec64772f2cf..53d0b67e59331 100644
--- a/llvm/test/CodeGen/AMDGPU/soft-waitcnt-deletion.mir
+++ b/llvm/test/CodeGen/AMDGPU/soft-waitcnt-deletion.mir
@@ -1,5 +1,5 @@
 # NOTE: Assertions have been autogenerated by utils/update_mir_test_checks.py UTC_ARGS: --version 6
-# RUN: llc -mtriple=amdgcn-amd-amdhsa -mcpu=gfx1250 -run-pass=si-insert-waitcnts -amdgpu-expert-scheduling-mode -o - %s | FileCheck %s
+# RUN: llc -mtriple=amdgpu12.50-amd-amdhsa -run-pass=si-insert-waitcnts -amdgpu-expert-scheduling-mode -o - %s | FileCheck %s
 
 ---
 name:            soft_wait_before_s_barrier



More information about the llvm-commits mailing list