[llvm] [AMDGPU] Reject image-load merges when either op has TFE/LWE (PR #210583)

Yudistira Putra via llvm-commits llvm-commits at lists.llvm.org
Mon Jul 20 09:05:50 PDT 2026


https://github.com/Yudis-bit updated https://github.com/llvm/llvm-project/pull/210583

>From fdd35c6a7c37f2069dee2ff411ee7acd10f71aa8 Mon Sep 17 00:00:00 2001
From: Yudistira Putra <85178972+Yudis-bit at users.noreply.github.com>
Date: Sun, 19 Jul 2026 05:00:24 -0400
Subject: [PATCH] [AMDGPU] Reject image-load merges when either op has TFE/LWE

TFE/LWE image operations produce status-result semantics that
SILoadStoreOptimizer's image merge path does not model.

Exclude MIMG instructions with enabled TFE or LWE during mergeable
candidate collection in collectMergeableInsts(), preventing them from
entering the merge candidate list entirely. This protects both operand
orderings (ordinary->TFE/LWE and TFE/LWE->ordinary) from reaching pair
combination.

Add focused MIR regression coverage for ordinary->TFE and ordinary->LWE
orderings. Pre-existing tests image_load_not_merged_7 and
image_load_not_merged_8 already verify the reverse orderings
(TFE->ordinary and LWE->ordinary), and existing positive tests continue
to verify that status-free image loads still merge.

Fixes #187335

Assisted-by: Gemini 3.5 Flash High
---
 .../Target/AMDGPU/SILoadStoreOptimizer.cpp    | 10 ++++++
 llvm/test/CodeGen/AMDGPU/merge-image-load.mir | 35 +++++++++++++++++++
 2 files changed, 45 insertions(+)

diff --git a/llvm/lib/Target/AMDGPU/SILoadStoreOptimizer.cpp b/llvm/lib/Target/AMDGPU/SILoadStoreOptimizer.cpp
index 3d82ef9249c44..9dc4c509def7c 100644
--- a/llvm/lib/Target/AMDGPU/SILoadStoreOptimizer.cpp
+++ b/llvm/lib/Target/AMDGPU/SILoadStoreOptimizer.cpp
@@ -2674,6 +2674,16 @@ SILoadStoreOptimizer::collectMergeableInsts(
         LLVM_DEBUG(dbgs() << "Skip tbuffer with unknown format: " << MI);
         continue;
       }
+    } else if (InstClass == MIMG) {
+      // Do not merge MIMG instructions with tfe or lwe enabled.
+      // TFE/LWE add a status result that the image merge path does not model.
+      const auto *TFEOp = TII->getNamedOperand(MI, AMDGPU::OpName::tfe);
+      if (TFEOp && TFEOp->getImm())
+        continue;
+
+      const auto *LWEOp = TII->getNamedOperand(MI, AMDGPU::OpName::lwe);
+      if (LWEOp && LWEOp->getImm())
+        continue;
     }
 
     CombineInfo CI;
diff --git a/llvm/test/CodeGen/AMDGPU/merge-image-load.mir b/llvm/test/CodeGen/AMDGPU/merge-image-load.mir
index 2d3f9b0f482a7..dfebc1cc4a608 100644
--- a/llvm/test/CodeGen/AMDGPU/merge-image-load.mir
+++ b/llvm/test/CodeGen/AMDGPU/merge-image-load.mir
@@ -485,3 +485,38 @@ body:             |
 ...
 ---
 
+# GFX9-LABEL: name: image_load_tfe_second_not_merged
+# GFX9: %{{[0-9]+}}:vgpr_32 = IMAGE_LOAD_V1_V4 %5, %3, 8, 0, 0, 0, 0, 0, -1, 0, implicit $exec :: (dereferenceable load (s32), addrspace 4)
+# GFX9: %{{[0-9]+}}:vreg_128 = IMAGE_LOAD_V4_V4 %5, %3, 7, 0, 0, 0, 1, 0, -1, 0, implicit $exec :: (dereferenceable load (s96), align 16, addrspace 4)
+
+name: image_load_tfe_second_not_merged
+body:             |
+  bb.0.entry:
+    %0:sgpr_64 = COPY $sgpr0_sgpr1
+    %1:sreg_64_xexec = S_LOAD_DWORDX2_IMM %0, 36, 0
+    %2:sgpr_128 = COPY $sgpr96_sgpr97_sgpr98_sgpr99
+    %3:sgpr_256 = S_LOAD_DWORDX8_IMM %1, 208, 0
+    %4:vgpr_32 = COPY %2.sub3
+    %5:vreg_128 = BUFFER_LOAD_DWORDX4_OFFSET %2, 0, 0, 0, 0, implicit $exec :: (dereferenceable invariant load (s128))
+    %6:vgpr_32 = IMAGE_LOAD_V1_V4 %5, %3, 8, 0, 0, 0, 0, 0, -1, 0, implicit $exec :: (dereferenceable load (s32), addrspace 4)
+    %7:vreg_128 = IMAGE_LOAD_V4_V4 %5, %3, 7, 0, 0, 0, 1, 0, -1, 0, implicit $exec :: (dereferenceable load (s96), align 16, addrspace 4)
+...
+---
+
+# GFX9-LABEL: name: image_load_lwe_second_not_merged
+# GFX9: %{{[0-9]+}}:vgpr_32 = IMAGE_LOAD_V1_V4 %5, %3, 8, 0, 0, 0, 0, 0, -1, 0, implicit $exec :: (dereferenceable load (s32), addrspace 4)
+# GFX9: %{{[0-9]+}}:vreg_128 = IMAGE_LOAD_V4_V4 %5, %3, 7, 0, 0, 0, 0, 1, -1, 0, implicit $exec :: (dereferenceable load (s96), align 16, addrspace 4)
+
+name: image_load_lwe_second_not_merged
+body:             |
+  bb.0.entry:
+    %0:sgpr_64 = COPY $sgpr0_sgpr1
+    %1:sreg_64_xexec = S_LOAD_DWORDX2_IMM %0, 36, 0
+    %2:sgpr_128 = COPY $sgpr96_sgpr97_sgpr98_sgpr99
+    %3:sgpr_256 = S_LOAD_DWORDX8_IMM %1, 208, 0
+    %4:vgpr_32 = COPY %2.sub3
+    %5:vreg_128 = BUFFER_LOAD_DWORDX4_OFFSET %2, 0, 0, 0, 0, implicit $exec :: (dereferenceable invariant load (s128))
+    %6:vgpr_32 = IMAGE_LOAD_V1_V4 %5, %3, 8, 0, 0, 0, 0, 0, -1, 0, implicit $exec :: (dereferenceable load (s32), addrspace 4)
+    %7:vreg_128 = IMAGE_LOAD_V4_V4 %5, %3, 7, 0, 0, 0, 0, 1, -1, 0, implicit $exec :: (dereferenceable load (s96), align 16, addrspace 4)
+...
+---



More information about the llvm-commits mailing list