[llvm] [AMDGPU] Mark ASYNCMARK as meta instruction to fix hazard cycle miscounting (PR #189981)

via llvm-commits llvm-commits at lists.llvm.org
Fri Apr 17 04:23:52 PDT 2026


================
@@ -366,10 +366,11 @@ define void @test_pipelined_loop(ptr addrspace(1) %foo, ptr addrspace(3) %lds, p
 ; SDAG-NEXT:    s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0)
 ; SDAG-NEXT:    v_readfirstlane_b32 s4, v2
 ; SDAG-NEXT:    s_mov_b32 m0, s4
-; SDAG-NEXT:    v_mov_b32_e32 v5, 0
+; SDAG-NEXT:    s_nop 0
 ; SDAG-NEXT:    global_load_dword v[0:1], off lds
 ; SDAG-NEXT:    ; asyncmark
 ; SDAG-NEXT:    global_load_dword v[0:1], off lds
+; SDAG-NEXT:    v_mov_b32_e32 v5, 0
----------------
adeshcom14 wrote:

The v_mov didn't really get "replaced" by s_nop , marking ASYNCMARK as Meta changed the post-RA scheduler's bundling decisions, which moved v_mov later and exposed a hazard gap that s_nop now fills.

When ASYNCMARK becomes meta, the post-RA scheduler treats it as transient instr as well and bundles it with the adjacent loads {GLOBAL_LOAD_LDS_DWORD, ASYNCMARK, GLOBAL_LOAD_LDS_DWORD}. GCNHazardRecognizer::getHazardType() skips hazard checking for bundles, so the bundle gets placed right after S_MOV_B32 m0, pushing v_mov after the bundle. Previously ASYNCMARK was a standalone scheduling unit, so the first GLOBAL_LOAD_LDS_DWORD triggered an m0-to-LDS load hazard and v_mov was picked to fill the 1 cycle gap.

The post-RA hazard recognizer pass then walks inside the bundle, detects the m0-to-LDS-load hazard, and inserts S_NOP 0.



https://github.com/llvm/llvm-project/pull/189981


More information about the llvm-commits mailing list