[llvm] 5e0390b - [AMDGPU] Fix XNACK alignment check in SILoadStoreOptimizer merges (#219886)

via llvm-commits llvm-commits at lists.llvm.org
Mon Aug 31 04:16:28 PDT 2026


Author: Arseniy Obolenskiy
Date: 2026-08-31T13:16:22+02:00
New Revision: 5e0390b0c093ad305274aa477e2fbcdf3aabff80

URL: https://github.com/llvm/llvm-project/commit/5e0390b0c093ad305274aa477e2fbcdf3aabff80
DIFF: https://github.com/llvm/llvm-project/commit/5e0390b0c093ad305274aa477e2fbcdf3aabff80.diff

LOG: [AMDGPU] Fix XNACK alignment check in SILoadStoreOptimizer merges (#219886)

Alignment of a merged scalar load depends on the lower offset load, not
whichever load comes first in program order, so checking the first load
could miss cases needing the constrained opcode

Added: 
    

Modified: 
    llvm/lib/Target/AMDGPU/SILoadStoreOptimizer.cpp
    llvm/test/CodeGen/AMDGPU/merge-s-load.mir

Removed: 
    


################################################################################
diff  --git a/llvm/lib/Target/AMDGPU/SILoadStoreOptimizer.cpp b/llvm/lib/Target/AMDGPU/SILoadStoreOptimizer.cpp
index d86a3c62f63c3..a730e9cd44b32 100644
--- a/llvm/lib/Target/AMDGPU/SILoadStoreOptimizer.cpp
+++ b/llvm/lib/Target/AMDGPU/SILoadStoreOptimizer.cpp
@@ -1877,6 +1877,11 @@ static bool needsConstrainedOpcode(const GCNSubtarget &STM,
 unsigned SILoadStoreOptimizer::getNewOpcode(const CombineInfo &CI,
                                             const CombineInfo &Paired) {
   const unsigned Width = CI.Width + Paired.Width;
+  const CombineInfo &Leading = Paired < CI ? Paired : CI;
+  // If XNACK is enabled, use the constrained opcodes when the first load is
+  // under-aligned.
+  const bool NeedsConstrainedOpc =
+      needsConstrainedOpcode(*STM, Leading.I->memoperands(), Width);
 
   switch (getCommonInstClass(CI, Paired)) {
   default:
@@ -1892,10 +1897,6 @@ unsigned SILoadStoreOptimizer::getNewOpcode(const CombineInfo &CI,
   case UNKNOWN:
     llvm_unreachable("Unknown instruction class");
   case S_BUFFER_LOAD_IMM: {
-    // If XNACK is enabled, use the constrained opcodes when the first load is
-    // under-aligned.
-    bool NeedsConstrainedOpc =
-        needsConstrainedOpcode(*STM, CI.I->memoperands(), Width);
     switch (Width) {
     default:
       return 0;
@@ -1914,10 +1915,6 @@ unsigned SILoadStoreOptimizer::getNewOpcode(const CombineInfo &CI,
     }
   }
   case S_BUFFER_LOAD_SGPR_IMM: {
-    // If XNACK is enabled, use the constrained opcodes when the first load is
-    // under-aligned.
-    bool NeedsConstrainedOpc =
-        needsConstrainedOpcode(*STM, CI.I->memoperands(), Width);
     switch (Width) {
     default:
       return 0;
@@ -1936,10 +1933,6 @@ unsigned SILoadStoreOptimizer::getNewOpcode(const CombineInfo &CI,
     }
   }
   case S_LOAD_IMM: {
-    // If XNACK is enabled, use the constrained opcodes when the first load is
-    // under-aligned.
-    bool NeedsConstrainedOpc =
-        needsConstrainedOpcode(*STM, CI.I->memoperands(), Width);
     switch (Width) {
     default:
       return 0;

diff  --git a/llvm/test/CodeGen/AMDGPU/merge-s-load.mir b/llvm/test/CodeGen/AMDGPU/merge-s-load.mir
index bc47cf53c0f47..d26337d8d74ce 100644
--- a/llvm/test/CodeGen/AMDGPU/merge-s-load.mir
+++ b/llvm/test/CodeGen/AMDGPU/merge-s-load.mir
@@ -480,3 +480,47 @@ body: |
     early-clobber %1:sgpr_128 = S_LOAD_DWORDX4_IMM_ec %0:sgpr_64, 0, 0 :: (dereferenceable invariant load (s128))
     early-clobber %2:sgpr_128 = S_LOAD_DWORDX4_IMM_ec %0:sgpr_64, 16, 0 :: (dereferenceable invariant load (s128))
 ...
+
+---
+# Merged offset 4/align 4 needs the constrained opcode, though the higher-offset
+# (more aligned) load comes first in program order.
+name: merge_s_load_x1_x1_high_offset_first_underaligned
+body: |
+  bb.0:
+    ; GFX10-LABEL: name: merge_s_load_x1_x1_high_offset_first_underaligned
+    ; GFX10: [[DEF:%[0-9]+]]:sgpr_64 = IMPLICIT_DEF
+    ; GFX10-NEXT: early-clobber %3:sreg_64_xexec = S_LOAD_DWORDX2_IMM_ec [[DEF]], 4, 0 :: (dereferenceable invariant load (s64), align 4)
+    ; GFX10-NEXT: [[COPY:%[0-9]+]]:sreg_32_xm0_xexec = COPY %3.sub1
+    ; GFX10-NEXT: [[COPY1:%[0-9]+]]:sreg_32_xm0_xexec = COPY killed %3.sub0
+    ;
+    ; GFX11-LABEL: name: merge_s_load_x1_x1_high_offset_first_underaligned
+    ; GFX11: [[DEF:%[0-9]+]]:sgpr_64 = IMPLICIT_DEF
+    ; GFX11-NEXT: [[S_LOAD_DWORDX2_IMM:%[0-9]+]]:sreg_64_xexec = S_LOAD_DWORDX2_IMM [[DEF]], 4, 0 :: (dereferenceable invariant load (s64), align 4)
+    ; GFX11-NEXT: [[COPY:%[0-9]+]]:sreg_32_xm0_xexec = COPY [[S_LOAD_DWORDX2_IMM]].sub1
+    ; GFX11-NEXT: [[COPY1:%[0-9]+]]:sreg_32_xm0_xexec = COPY killed [[S_LOAD_DWORDX2_IMM]].sub0
+    ;
+    ; GFX12-LABEL: name: merge_s_load_x1_x1_high_offset_first_underaligned
+    ; GFX12: [[DEF:%[0-9]+]]:sgpr_64 = IMPLICIT_DEF
+    ; GFX12-NEXT: [[S_LOAD_DWORDX2_IMM:%[0-9]+]]:sreg_64_xexec = S_LOAD_DWORDX2_IMM [[DEF]], 4, 0 :: (dereferenceable invariant load (s64), align 4)
+    ; GFX12-NEXT: [[COPY:%[0-9]+]]:sreg_32_xm0_xexec = COPY [[S_LOAD_DWORDX2_IMM]].sub1
+    ; GFX12-NEXT: [[COPY1:%[0-9]+]]:sreg_32_xm0_xexec = COPY killed [[S_LOAD_DWORDX2_IMM]].sub0
+    %0:sgpr_64 = IMPLICIT_DEF
+    %1:sreg_32_xm0_xexec = S_LOAD_DWORD_IMM %0:sgpr_64, 8, 0 :: (dereferenceable invariant load (s32), align 8)
+    %2:sreg_32_xm0_xexec = S_LOAD_DWORD_IMM %0:sgpr_64, 4, 0 :: (dereferenceable invariant load (s32), align 4)
+...
+
+---
+# Merged offset 8/align 8 is naturally aligned, though the first load in
+# program order is under-aligned.
+name: merge_s_load_x1_x1_high_offset_first_aligned
+body: |
+  bb.0:
+    ; CHECK-LABEL: name: merge_s_load_x1_x1_high_offset_first_aligned
+    ; CHECK: [[DEF:%[0-9]+]]:sgpr_64 = IMPLICIT_DEF
+    ; CHECK-NEXT: [[S_LOAD_DWORDX2_IMM:%[0-9]+]]:sreg_64_xexec = S_LOAD_DWORDX2_IMM [[DEF]], 8, 0 :: (dereferenceable invariant load (s64))
+    ; CHECK-NEXT: [[COPY:%[0-9]+]]:sreg_32_xm0_xexec = COPY [[S_LOAD_DWORDX2_IMM]].sub1
+    ; CHECK-NEXT: [[COPY1:%[0-9]+]]:sreg_32_xm0_xexec = COPY killed [[S_LOAD_DWORDX2_IMM]].sub0
+    %0:sgpr_64 = IMPLICIT_DEF
+    %1:sreg_32_xm0_xexec = S_LOAD_DWORD_IMM %0:sgpr_64, 12, 0 :: (dereferenceable invariant load (s32), align 4)
+    %2:sreg_32_xm0_xexec = S_LOAD_DWORD_IMM %0:sgpr_64, 8, 0 :: (dereferenceable invariant load (s32), align 8)
+...


        


More information about the llvm-commits mailing list