[llvm] [AMDGPU/GISEL] Legalizing sub-dword scalar load for pre-gfx12 arch (PR #195800)

Abhinav Garg via llvm-commits llvm-commits at lists.llvm.org
Mon May 4 23:50:51 PDT 2026


https://github.com/abhigargrepo created https://github.com/llvm/llvm-project/pull/195800

Pre-GFX12 sub targets lack native 8-bit and 16-bit scalar buffer load instructions. This patch extends legalizeSBufferLoad() to handle s8/s16 loads on these targets by widening the load to 32 bits (G_AMDGPU_S_BUFFER_LOAD) and inserting a G_TRUNC to recover the original narrow type, since sub-dword SGPR register types are not valid.


>From 2ac9bbe8118efa80c6019f3b028671d89cc60d7f Mon Sep 17 00:00:00 2001
From: Abhinav Garg <abhigarg at amd.com>
Date: Tue, 5 May 2026 06:35:54 +0000
Subject: [PATCH] Legalizing sub-dword scalar load for pre-gfx12 architecture

---
 .../lib/Target/AMDGPU/AMDGPULegalizerInfo.cpp |  7 +++
 .../legalize-llvm.amdgcn.s.buffer.load.mir    | 60 +++++++++++++++++++
 2 files changed, 67 insertions(+)

diff --git a/llvm/lib/Target/AMDGPU/AMDGPULegalizerInfo.cpp b/llvm/lib/Target/AMDGPU/AMDGPULegalizerInfo.cpp
index be5bc4da93b7d..842f746d99c56 100644
--- a/llvm/lib/Target/AMDGPU/AMDGPULegalizerInfo.cpp
+++ b/llvm/lib/Target/AMDGPU/AMDGPULegalizerInfo.cpp
@@ -7515,6 +7515,13 @@ bool AMDGPULegalizerInfo::legalizeSBufferLoad(LegalizerHelper &Helper,
     // The 8-bit and 16-bit scalar buffer load instructions have 32-bit
     // destination register.
     Dst = B.getMRI()->createGenericVirtualRegister(LLT::scalar(32));
+  } else if (Size < 32) {
+    // No native sub-dword scalar buffer load on this subtarget.
+    // Widen to a 32-bit load; a G_TRUNC is inserted after to recover the
+    // original narrow type. s8/s16 are not valid SGPR register types.
+    assert(Size == 8 || Size == 16);
+    Opc = AMDGPU::G_AMDGPU_S_BUFFER_LOAD;
+    Dst = B.getMRI()->createGenericVirtualRegister(LLT::scalar(32));
   } else {
     Opc = AMDGPU::G_AMDGPU_S_BUFFER_LOAD;
     Dst = OrigDst;
diff --git a/llvm/test/CodeGen/AMDGPU/GlobalISel/legalize-llvm.amdgcn.s.buffer.load.mir b/llvm/test/CodeGen/AMDGPU/GlobalISel/legalize-llvm.amdgcn.s.buffer.load.mir
index cbd9c2173b7e3..92f0b3eb695cc 100644
--- a/llvm/test/CodeGen/AMDGPU/GlobalISel/legalize-llvm.amdgcn.s.buffer.load.mir
+++ b/llvm/test/CodeGen/AMDGPU/GlobalISel/legalize-llvm.amdgcn.s.buffer.load.mir
@@ -291,3 +291,63 @@ body:             |
     S_ENDPGM 0, implicit %2
 
 ...
+
+---
+name: s_buffer_load_s16
+body:             |
+  bb.0:
+    liveins: $sgpr0_sgpr1_sgpr2_sgpr3
+
+    ; GFX67-LABEL: name: s_buffer_load_s16
+    ; GFX67: liveins: $sgpr0_sgpr1_sgpr2_sgpr3
+    ; GFX67-NEXT: {{  $}}
+    ; GFX67-NEXT: [[COPY:%[0-9]+]]:_(<4 x s32>) = COPY $sgpr0_sgpr1_sgpr2_sgpr3
+    ; GFX67-NEXT: [[C:%[0-9]+]]:_(s32) = G_CONSTANT i32 0
+    ; GFX67-NEXT: [[AMDGPU_S_BUFFER_LOAD:%[0-9]+]]:_(s32) = G_AMDGPU_S_BUFFER_LOAD [[COPY]](<4 x s32>), [[C]](s32), 0 :: (dereferenceable invariant load (s16))
+    ; GFX67-NEXT: [[TRUNC:%[0-9]+]]:_(s16) = G_TRUNC [[AMDGPU_S_BUFFER_LOAD]](s32)
+    ; GFX67-NEXT: S_ENDPGM 0, implicit [[TRUNC]](s16)
+    ;
+    ; GFX12-LABEL: name: s_buffer_load_s16
+    ; GFX12: liveins: $sgpr0_sgpr1_sgpr2_sgpr3
+    ; GFX12-NEXT: {{  $}}
+    ; GFX12-NEXT: [[COPY:%[0-9]+]]:_(<4 x s32>) = COPY $sgpr0_sgpr1_sgpr2_sgpr3
+    ; GFX12-NEXT: [[C:%[0-9]+]]:_(s32) = G_CONSTANT i32 0
+    ; GFX12-NEXT: [[AMDGPU_S_BUFFER_LOAD_USHORT:%[0-9]+]]:_(s32) = G_AMDGPU_S_BUFFER_LOAD_USHORT [[COPY]](<4 x s32>), [[C]](s32), 0 :: (dereferenceable invariant load (s16))
+    ; GFX12-NEXT: [[TRUNC:%[0-9]+]]:_(s16) = G_TRUNC [[AMDGPU_S_BUFFER_LOAD_USHORT]](s32)
+    ; GFX12-NEXT: S_ENDPGM 0, implicit [[TRUNC]](s16)
+    %0:_(<4 x s32>) = COPY $sgpr0_sgpr1_sgpr2_sgpr3
+    %1:_(s32) = G_CONSTANT i32 0
+    %2:_(s16) = G_INTRINSIC intrinsic(@llvm.amdgcn.s.buffer.load), %0, %1, 0
+    S_ENDPGM 0, implicit %2
+
+...
+
+---
+name: s_buffer_load_s8
+body:             |
+  bb.0:
+    liveins: $sgpr0_sgpr1_sgpr2_sgpr3
+
+    ; GFX67-LABEL: name: s_buffer_load_s8
+    ; GFX67: liveins: $sgpr0_sgpr1_sgpr2_sgpr3
+    ; GFX67-NEXT: {{  $}}
+    ; GFX67-NEXT: [[COPY:%[0-9]+]]:_(<4 x s32>) = COPY $sgpr0_sgpr1_sgpr2_sgpr3
+    ; GFX67-NEXT: [[C:%[0-9]+]]:_(s32) = G_CONSTANT i32 0
+    ; GFX67-NEXT: [[AMDGPU_S_BUFFER_LOAD:%[0-9]+]]:_(s32) = G_AMDGPU_S_BUFFER_LOAD [[COPY]](<4 x s32>), [[C]](s32), 0 :: (dereferenceable invariant load (s8))
+    ; GFX67-NEXT: [[TRUNC:%[0-9]+]]:_(s8) = G_TRUNC [[AMDGPU_S_BUFFER_LOAD]](s32)
+    ; GFX67-NEXT: S_ENDPGM 0, implicit [[TRUNC]](s8)
+    ;
+    ; GFX12-LABEL: name: s_buffer_load_s8
+    ; GFX12: liveins: $sgpr0_sgpr1_sgpr2_sgpr3
+    ; GFX12-NEXT: {{  $}}
+    ; GFX12-NEXT: [[COPY:%[0-9]+]]:_(<4 x s32>) = COPY $sgpr0_sgpr1_sgpr2_sgpr3
+    ; GFX12-NEXT: [[C:%[0-9]+]]:_(s32) = G_CONSTANT i32 0
+    ; GFX12-NEXT: [[AMDGPU_S_BUFFER_LOAD_UBYTE:%[0-9]+]]:_(s32) = G_AMDGPU_S_BUFFER_LOAD_UBYTE [[COPY]](<4 x s32>), [[C]](s32), 0 :: (dereferenceable invariant load (s8))
+    ; GFX12-NEXT: [[TRUNC:%[0-9]+]]:_(s8) = G_TRUNC [[AMDGPU_S_BUFFER_LOAD_UBYTE]](s32)
+    ; GFX12-NEXT: S_ENDPGM 0, implicit [[TRUNC]](s8)
+    %0:_(<4 x s32>) = COPY $sgpr0_sgpr1_sgpr2_sgpr3
+    %1:_(s32) = G_CONSTANT i32 0
+    %2:_(s8) = G_INTRINSIC intrinsic(@llvm.amdgcn.s.buffer.load), %0, %1, 0
+    S_ENDPGM 0, implicit %2
+
+...



More information about the llvm-commits mailing list