[all-commits] [llvm/llvm-project] 73a366: [AMDGPU] Add SIPromoteGlobalLoadSAddr: promote loo...

Matthias Gehre via All-commits all-commits at lists.llvm.org
Thu Jul 16 02:51:34 PDT 2026


  Branch: refs/heads/users/mgehre-amd/si-promote-global-load-saddr
  Home:   https://github.com/llvm/llvm-project
  Commit: 73a366fa244d8ad9e75e19e4a5c09a8d9869921d
      https://github.com/llvm/llvm-project/commit/73a366fa244d8ad9e75e19e4a5c09a8d9869921d
  Author: Matthias Gehre <matthias.gehre at amd.com>
  Date:   2026-06-24 (Wed, 24 Jun 2026)

  Changed paths:
    M llvm/lib/Target/AMDGPU/AMDGPU.h
    M llvm/lib/Target/AMDGPU/AMDGPUTargetMachine.cpp
    M llvm/lib/Target/AMDGPU/CMakeLists.txt
    A llvm/lib/Target/AMDGPU/SIPromoteGlobalLoadToSAddr.cpp
    A llvm/test/CodeGen/AMDGPU/si-promote-global-load-saddr.ll

  Log Message:
  -----------
  [AMDGPU] Add SIPromoteGlobalLoadSAddr: promote loop-carried ptr phi to SADDR

Adds a pre-RA peephole pass that promotes global loads whose address is a
loop-carried vreg_64 phi of the form (sgpr_base + divergent_tid_offset) to the
SADDR addressing mode, replacing the VGPR address advance with scalar
S_ADD_U32/S_ADDC_U32 instructions.

Problem
-------
When a uniform global pointer is advanced by a uniform stride inside a loop
and indexed by threadIdx.x, the compiler fails to select the
`global_load ... SADDR+VADDR` form. Instead it keeps the full 64-bit address
as a per-lane VGPR induction variable and emits a pure-VGPR
`global_load ... off`, advancing the address with two V_ADD_CO_U32 per
iteration. This is the textbook SADDR+VADDR shape, but the compiler's
SelectionDAG divergence analysis conservatively treats the loop-carried phi
as divergent even though all incoming values are uniform.

Root cause
----------
The miss is in the LLVM mid-end: LICM cannot hoist the load (base is
loop-carried, not invariant), IndVarSimplify does not normalize pointer IVs
of the form {base, +, stride} into an integer IV, and ISel does not recover
the split from a loop-carried phi node. The fix is a post-ISel, pre-RA
peephole that operates on Machine IR where SGPR/VGPR assignment is concrete.

Pattern matched (after SIFoldOperands expands V_ADD_U64_PSEUDO)
---------------------------------------------------------------
Preheader:
  %lo, %carry = V_ADD_CO_U32_e64  sgpr_base.sub0, vgpr_tid_bytes
  %hi, dead _ = V_ADDC_U32_e64    sgpr_base.sub1, 0, carry
  %addr_init:vreg_64 = REG_SEQUENCE %lo, sub0, %hi, sub1

Loop:
  %addr:vreg_64 = PHI [%addr_init, ph], [%addr_next, loop]
  GLOBAL_LOAD_*  vdst, %addr:vreg_64, off
  %lo2, %c2 = V_ADD_CO_U32_e64  %addr.sub0, stride_imm
  %hi2, _   = V_ADDC_U32_e64    %addr.sub1, 0, c2
  %addr_next:vreg_64 = REG_SEQUENCE %lo2, sub0, %hi2, sub1

Transformation
--------------
Loop (after):
  %sbase:sreg_64 = PHI [sgpr_base, ph], [%snext, loop]
  GLOBAL_LOAD_*_SADDR  vdst, %sbase:sreg_64, vgpr_tid_bytes, off
  %snext_lo = S_ADD_U32  %sbase.sub0, stride_imm
  %snext_hi = S_ADDC_U32 %sbase.sub1, 0
  %snext:sreg_64 = REG_SEQUENCE %snext_lo, sub0, %snext_hi, sub1

The dead vreg_64 phi cycle is explicitly removed to avoid leaving dead
V_ADD_CO_U32 instructions that DCE cannot break due to the self-referential
phi structure.

Covers all common GLOBAL_LOAD widths (d16/b16, ubyte, ushort, dword, dwordx2,
dwordx3, dwordx4) and their _t16 variants. Tested on gfx1010 and gfx1100;
end-to-end correctness verified on gfx1151 (exact bitwise match).

Changes:
- SIPromoteGlobalLoadToSAddr.cpp: new pre-RA MachineFunctionPass
- AMDGPU.h: declare pass creation function and initialize symbol
- AMDGPUTargetMachine.cpp: register pass and insert after SIFoldOperands
  in GCNPassConfig::addMachineSSAOptimization
- CMakeLists.txt: add new source file
- si-promote-global-load-saddr.ll: lit test covering the promoted loop body
  with no v_add_co_u32 remaining (gfx1010, gfx1100)



To unsubscribe from these emails, change your notification settings at https://github.com/llvm/llvm-project/settings/notifications


More information about the All-commits mailing list