[llvm-branch-commits] [llvm] [AMDGPU][True16] Add regbank combiner cases to fix regression around G_SEXTLOAD (PR #198671)

Domenic Nutile via llvm-branch-commits llvm-branch-commits at lists.llvm.org
Mon May 25 09:18:44 PDT 2026


https://github.com/saxlungs updated https://github.com/llvm/llvm-project/pull/198671

>From 45a06ac8adb891bc593b822c13ae5f8a44ce391b Mon Sep 17 00:00:00 2001
From: Domenic Nutile <domenic.nutile at gmail.com>
Date: Tue, 5 May 2026 11:46:40 -0400
Subject: [PATCH 1/2] [AMDGPU][True16] Add regbank combiner cases to fix
 regression around G_SEXTLOAD

---
 .../Target/AMDGPU/AMDGPURegBankCombiner.cpp   |  19 +-
 .../CodeGen/AMDGPU/GlobalISel/load-d16.ll     | 228 +++++-------------
 2 files changed, 80 insertions(+), 167 deletions(-)

diff --git a/llvm/lib/Target/AMDGPU/AMDGPURegBankCombiner.cpp b/llvm/lib/Target/AMDGPU/AMDGPURegBankCombiner.cpp
index a2cdd32be92f6..27da32f2a1e89 100644
--- a/llvm/lib/Target/AMDGPU/AMDGPURegBankCombiner.cpp
+++ b/llvm/lib/Target/AMDGPU/AMDGPURegBankCombiner.cpp
@@ -420,7 +420,8 @@ bool AMDGPURegBankCombinerImpl::combineD16Load(MachineInstr &MI) const {
 
     if (mi_match(
             Load, MRI,
-            m_GAnd(m_MInstr(SextLoad), m_Copy(m_SpecificICst(CleanHi16))))) {
+            m_GAnd(m_MInstr(SextLoad), m_Copy(m_SpecificICst(CleanHi16)))) ||
+        mi_match(Load, MRI, m_GZExt(m_MInstr(SextLoad)))) {
       if (SextLoad->getOpcode() != AMDGPU::G_SEXTLOAD)
         return false;
 
@@ -428,6 +429,12 @@ bool AMDGPURegBankCombinerImpl::combineD16Load(MachineInstr &MI) const {
       if (MMO->getSizeInBits().getValue() != 8)
         return false;
 
+      if (Load->getOpcode() == TargetOpcode::G_ZEXT) {
+        LLT SextDstTy = MRI.getType(SextLoad->getOperand(0).getReg());
+        if (SextDstTy.getSizeInBits() != 16)
+          return false;
+      }
+
       return applyD16Load(AMDGPU::G_AMDGPU_LOAD_D16_LO_I8, MI, SextLoad, Dst);
     }
 
@@ -452,13 +459,21 @@ bool AMDGPURegBankCombinerImpl::combineD16Load(MachineInstr &MI) const {
 
     if (mi_match(
             Load, MRI,
-            m_GAnd(m_MInstr(SextLoad), m_Copy(m_SpecificICst(CleanHi16))))) {
+            m_GAnd(m_MInstr(SextLoad), m_Copy(m_SpecificICst(CleanHi16)))) ||
+        mi_match(Load, MRI, m_GZExt(m_MInstr(SextLoad)))) {
       if (SextLoad->getOpcode() != AMDGPU::G_SEXTLOAD)
         return false;
+
       const MachineMemOperand *MMO = *SextLoad->memoperands_begin();
       if (MMO->getSizeInBits().getValue() != 8)
         return false;
 
+      if (Load->getOpcode() == TargetOpcode::G_ZEXT) {
+        LLT SextDstTy = MRI.getType(SextLoad->getOperand(0).getReg());
+        if (SextDstTy.getSizeInBits() != 16)
+          return false;
+      }
+
       return applyD16Load(AMDGPU::G_AMDGPU_LOAD_D16_HI_I8, MI, SextLoad, Dst);
     }
 
diff --git a/llvm/test/CodeGen/AMDGPU/GlobalISel/load-d16.ll b/llvm/test/CodeGen/AMDGPU/GlobalISel/load-d16.ll
index 387944cf7811a..166f439a61430 100644
--- a/llvm/test/CodeGen/AMDGPU/GlobalISel/load-d16.ll
+++ b/llvm/test/CodeGen/AMDGPU/GlobalISel/load-d16.ll
@@ -29,22 +29,12 @@ define amdgpu_ps void @load_P0_B16_D16_Hi(<2 x i16> %vec, ptr addrspace(0) %ptra
 }
 
 define amdgpu_ps void @sextload_P0_i8_D16(<2 x i16> %vec, ptr addrspace(0) %ptra, ptr addrspace(0) %out) {
-; GFX12-TRUE16-LABEL: sextload_P0_i8_D16:
-; GFX12-TRUE16:       ; %bb.0:
-; GFX12-TRUE16-NEXT:    flat_load_d16_i8 v1, v[1:2]
-; GFX12-TRUE16-NEXT:    s_wait_loadcnt_dscnt 0x0
-; GFX12-TRUE16-NEXT:    v_mov_b16_e32 v1.h, 0
-; GFX12-TRUE16-NEXT:    s_delay_alu instid0(VALU_DEP_1)
-; GFX12-TRUE16-NEXT:    v_and_or_b32 v0, 0xffff0000, v0, v1
-; GFX12-TRUE16-NEXT:    flat_store_b32 v[3:4], v0
-; GFX12-TRUE16-NEXT:    s_endpgm
-;
-; GFX12-FAKE16-LABEL: sextload_P0_i8_D16:
-; GFX12-FAKE16:       ; %bb.0:
-; GFX12-FAKE16-NEXT:    flat_load_d16_i8 v0, v[1:2]
-; GFX12-FAKE16-NEXT:    s_wait_loadcnt_dscnt 0x0
-; GFX12-FAKE16-NEXT:    flat_store_b32 v[3:4], v0
-; GFX12-FAKE16-NEXT:    s_endpgm
+; GFX12-LABEL: sextload_P0_i8_D16:
+; GFX12:       ; %bb.0:
+; GFX12-NEXT:    flat_load_d16_i8 v0, v[1:2]
+; GFX12-NEXT:    s_wait_loadcnt_dscnt 0x0
+; GFX12-NEXT:    flat_store_b32 v[3:4], v0
+; GFX12-NEXT:    s_endpgm
   %a = load i8, ptr addrspace(0) %ptra
   %a16 = sext i8 %a to i16
   %res = insertelement <2 x i16> %vec, i16 %a16, i32 0
@@ -53,23 +43,12 @@ define amdgpu_ps void @sextload_P0_i8_D16(<2 x i16> %vec, ptr addrspace(0) %ptra
 }
 
 define amdgpu_ps void @sextload_P0_i8_D16_Hi(<2 x i16> %vec, ptr addrspace(0) %ptra, ptr addrspace(0) %out) {
-; GFX12-TRUE16-LABEL: sextload_P0_i8_D16_Hi:
-; GFX12-TRUE16:       ; %bb.0:
-; GFX12-TRUE16-NEXT:    flat_load_d16_i8 v1, v[1:2]
-; GFX12-TRUE16-NEXT:    s_wait_loadcnt_dscnt 0x0
-; GFX12-TRUE16-NEXT:    v_mov_b16_e32 v1.h, 0
-; GFX12-TRUE16-NEXT:    s_delay_alu instid0(VALU_DEP_1) | instskip(NEXT) | instid1(VALU_DEP_1)
-; GFX12-TRUE16-NEXT:    v_lshlrev_b32_e32 v1, 16, v1
-; GFX12-TRUE16-NEXT:    v_and_or_b32 v0, 0xffff, v0, v1
-; GFX12-TRUE16-NEXT:    flat_store_b32 v[3:4], v0
-; GFX12-TRUE16-NEXT:    s_endpgm
-;
-; GFX12-FAKE16-LABEL: sextload_P0_i8_D16_Hi:
-; GFX12-FAKE16:       ; %bb.0:
-; GFX12-FAKE16-NEXT:    flat_load_d16_hi_i8 v0, v[1:2]
-; GFX12-FAKE16-NEXT:    s_wait_loadcnt_dscnt 0x0
-; GFX12-FAKE16-NEXT:    flat_store_b32 v[3:4], v0
-; GFX12-FAKE16-NEXT:    s_endpgm
+; GFX12-LABEL: sextload_P0_i8_D16_Hi:
+; GFX12:       ; %bb.0:
+; GFX12-NEXT:    flat_load_d16_hi_i8 v0, v[1:2]
+; GFX12-NEXT:    s_wait_loadcnt_dscnt 0x0
+; GFX12-NEXT:    flat_store_b32 v[3:4], v0
+; GFX12-NEXT:    s_endpgm
   %a = load i8, ptr addrspace(0) %ptra
   %a16 = sext i8 %a to i16
   %res = insertelement <2 x i16> %vec, i16 %a16, i32 1
@@ -132,22 +111,12 @@ define amdgpu_ps void @load_P1_B16_D16_Hi(<2 x i16> %vec, ptr addrspace(1) %ptra
 }
 
 define amdgpu_ps void @sextload_P1_i8_D16(<2 x i16> %vec, ptr addrspace(1) %ptra, ptr addrspace(1) %out) {
-; GFX12-TRUE16-LABEL: sextload_P1_i8_D16:
-; GFX12-TRUE16:       ; %bb.0:
-; GFX12-TRUE16-NEXT:    global_load_d16_i8 v1, v[1:2], off
-; GFX12-TRUE16-NEXT:    s_wait_loadcnt 0x0
-; GFX12-TRUE16-NEXT:    v_mov_b16_e32 v1.h, 0
-; GFX12-TRUE16-NEXT:    s_delay_alu instid0(VALU_DEP_1)
-; GFX12-TRUE16-NEXT:    v_and_or_b32 v0, 0xffff0000, v0, v1
-; GFX12-TRUE16-NEXT:    global_store_b32 v[3:4], v0, off
-; GFX12-TRUE16-NEXT:    s_endpgm
-;
-; GFX12-FAKE16-LABEL: sextload_P1_i8_D16:
-; GFX12-FAKE16:       ; %bb.0:
-; GFX12-FAKE16-NEXT:    global_load_d16_i8 v0, v[1:2], off
-; GFX12-FAKE16-NEXT:    s_wait_loadcnt 0x0
-; GFX12-FAKE16-NEXT:    global_store_b32 v[3:4], v0, off
-; GFX12-FAKE16-NEXT:    s_endpgm
+; GFX12-LABEL: sextload_P1_i8_D16:
+; GFX12:       ; %bb.0:
+; GFX12-NEXT:    global_load_d16_i8 v0, v[1:2], off
+; GFX12-NEXT:    s_wait_loadcnt 0x0
+; GFX12-NEXT:    global_store_b32 v[3:4], v0, off
+; GFX12-NEXT:    s_endpgm
   %a = load i8, ptr addrspace(1) %ptra
   %a16 = sext i8 %a to i16
   %res = insertelement <2 x i16> %vec, i16 %a16, i32 0
@@ -156,23 +125,12 @@ define amdgpu_ps void @sextload_P1_i8_D16(<2 x i16> %vec, ptr addrspace(1) %ptra
 }
 
 define amdgpu_ps void @sextload_P1_i8_D16_Hi(<2 x i16> %vec, ptr addrspace(1) %ptra, ptr addrspace(1) %out) {
-; GFX12-TRUE16-LABEL: sextload_P1_i8_D16_Hi:
-; GFX12-TRUE16:       ; %bb.0:
-; GFX12-TRUE16-NEXT:    global_load_d16_i8 v1, v[1:2], off
-; GFX12-TRUE16-NEXT:    s_wait_loadcnt 0x0
-; GFX12-TRUE16-NEXT:    v_mov_b16_e32 v1.h, 0
-; GFX12-TRUE16-NEXT:    s_delay_alu instid0(VALU_DEP_1) | instskip(NEXT) | instid1(VALU_DEP_1)
-; GFX12-TRUE16-NEXT:    v_lshlrev_b32_e32 v1, 16, v1
-; GFX12-TRUE16-NEXT:    v_and_or_b32 v0, 0xffff, v0, v1
-; GFX12-TRUE16-NEXT:    global_store_b32 v[3:4], v0, off
-; GFX12-TRUE16-NEXT:    s_endpgm
-;
-; GFX12-FAKE16-LABEL: sextload_P1_i8_D16_Hi:
-; GFX12-FAKE16:       ; %bb.0:
-; GFX12-FAKE16-NEXT:    global_load_d16_hi_i8 v0, v[1:2], off
-; GFX12-FAKE16-NEXT:    s_wait_loadcnt 0x0
-; GFX12-FAKE16-NEXT:    global_store_b32 v[3:4], v0, off
-; GFX12-FAKE16-NEXT:    s_endpgm
+; GFX12-LABEL: sextload_P1_i8_D16_Hi:
+; GFX12:       ; %bb.0:
+; GFX12-NEXT:    global_load_d16_hi_i8 v0, v[1:2], off
+; GFX12-NEXT:    s_wait_loadcnt 0x0
+; GFX12-NEXT:    global_store_b32 v[3:4], v0, off
+; GFX12-NEXT:    s_endpgm
   %a = load i8, ptr addrspace(1) %ptra
   %a16 = sext i8 %a to i16
   %res = insertelement <2 x i16> %vec, i16 %a16, i32 1
@@ -235,22 +193,12 @@ define amdgpu_ps void @load_P3_B16_D16_Hi(<2 x i16> %vec, ptr addrspace(3) %ptra
 }
 
 define amdgpu_ps void @sextload_P3_i8_D16(<2 x i16> %vec, ptr addrspace(3) %ptra, ptr addrspace(3) %out) {
-; GFX12-TRUE16-LABEL: sextload_P3_i8_D16:
-; GFX12-TRUE16:       ; %bb.0:
-; GFX12-TRUE16-NEXT:    ds_load_i8_d16 v1, v1
-; GFX12-TRUE16-NEXT:    s_wait_dscnt 0x0
-; GFX12-TRUE16-NEXT:    v_mov_b16_e32 v1.h, 0
-; GFX12-TRUE16-NEXT:    s_delay_alu instid0(VALU_DEP_1)
-; GFX12-TRUE16-NEXT:    v_and_or_b32 v0, 0xffff0000, v0, v1
-; GFX12-TRUE16-NEXT:    ds_store_b32 v2, v0
-; GFX12-TRUE16-NEXT:    s_endpgm
-;
-; GFX12-FAKE16-LABEL: sextload_P3_i8_D16:
-; GFX12-FAKE16:       ; %bb.0:
-; GFX12-FAKE16-NEXT:    ds_load_i8_d16 v0, v1
-; GFX12-FAKE16-NEXT:    s_wait_dscnt 0x0
-; GFX12-FAKE16-NEXT:    ds_store_b32 v2, v0
-; GFX12-FAKE16-NEXT:    s_endpgm
+; GFX12-LABEL: sextload_P3_i8_D16:
+; GFX12:       ; %bb.0:
+; GFX12-NEXT:    ds_load_i8_d16 v0, v1
+; GFX12-NEXT:    s_wait_dscnt 0x0
+; GFX12-NEXT:    ds_store_b32 v2, v0
+; GFX12-NEXT:    s_endpgm
   %a = load i8, ptr addrspace(3) %ptra
   %a16 = sext i8 %a to i16
   %res = insertelement <2 x i16> %vec, i16 %a16, i32 0
@@ -259,23 +207,12 @@ define amdgpu_ps void @sextload_P3_i8_D16(<2 x i16> %vec, ptr addrspace(3) %ptra
 }
 
 define amdgpu_ps void @sextload_P3_i8_D16_Hi(<2 x i16> %vec, ptr addrspace(3) %ptra, ptr addrspace(3) %out) {
-; GFX12-TRUE16-LABEL: sextload_P3_i8_D16_Hi:
-; GFX12-TRUE16:       ; %bb.0:
-; GFX12-TRUE16-NEXT:    ds_load_i8_d16 v1, v1
-; GFX12-TRUE16-NEXT:    s_wait_dscnt 0x0
-; GFX12-TRUE16-NEXT:    v_mov_b16_e32 v1.h, 0
-; GFX12-TRUE16-NEXT:    s_delay_alu instid0(VALU_DEP_1) | instskip(NEXT) | instid1(VALU_DEP_1)
-; GFX12-TRUE16-NEXT:    v_lshlrev_b32_e32 v1, 16, v1
-; GFX12-TRUE16-NEXT:    v_and_or_b32 v0, 0xffff, v0, v1
-; GFX12-TRUE16-NEXT:    ds_store_b32 v2, v0
-; GFX12-TRUE16-NEXT:    s_endpgm
-;
-; GFX12-FAKE16-LABEL: sextload_P3_i8_D16_Hi:
-; GFX12-FAKE16:       ; %bb.0:
-; GFX12-FAKE16-NEXT:    ds_load_i8_d16_hi v0, v1
-; GFX12-FAKE16-NEXT:    s_wait_dscnt 0x0
-; GFX12-FAKE16-NEXT:    ds_store_b32 v2, v0
-; GFX12-FAKE16-NEXT:    s_endpgm
+; GFX12-LABEL: sextload_P3_i8_D16_Hi:
+; GFX12:       ; %bb.0:
+; GFX12-NEXT:    ds_load_i8_d16_hi v0, v1
+; GFX12-NEXT:    s_wait_dscnt 0x0
+; GFX12-NEXT:    ds_store_b32 v2, v0
+; GFX12-NEXT:    s_endpgm
   %a = load i8, ptr addrspace(3) %ptra
   %a16 = sext i8 %a to i16
   %res = insertelement <2 x i16> %vec, i16 %a16, i32 1
@@ -338,22 +275,12 @@ define amdgpu_ps void @load_P4_B16_D16_Hi(<2 x i16> %vec, ptr addrspace(4) %ptra
 }
 
 define amdgpu_ps void @sextload_P4_i8_D16(<2 x i16> %vec, ptr addrspace(4) %ptra, ptr addrspace(1) %out) {
-; GFX12-TRUE16-LABEL: sextload_P4_i8_D16:
-; GFX12-TRUE16:       ; %bb.0:
-; GFX12-TRUE16-NEXT:    global_load_d16_i8 v1, v[1:2], off
-; GFX12-TRUE16-NEXT:    s_wait_loadcnt 0x0
-; GFX12-TRUE16-NEXT:    v_mov_b16_e32 v1.h, 0
-; GFX12-TRUE16-NEXT:    s_delay_alu instid0(VALU_DEP_1)
-; GFX12-TRUE16-NEXT:    v_and_or_b32 v0, 0xffff0000, v0, v1
-; GFX12-TRUE16-NEXT:    global_store_b32 v[3:4], v0, off
-; GFX12-TRUE16-NEXT:    s_endpgm
-;
-; GFX12-FAKE16-LABEL: sextload_P4_i8_D16:
-; GFX12-FAKE16:       ; %bb.0:
-; GFX12-FAKE16-NEXT:    global_load_d16_i8 v0, v[1:2], off
-; GFX12-FAKE16-NEXT:    s_wait_loadcnt 0x0
-; GFX12-FAKE16-NEXT:    global_store_b32 v[3:4], v0, off
-; GFX12-FAKE16-NEXT:    s_endpgm
+; GFX12-LABEL: sextload_P4_i8_D16:
+; GFX12:       ; %bb.0:
+; GFX12-NEXT:    global_load_d16_i8 v0, v[1:2], off
+; GFX12-NEXT:    s_wait_loadcnt 0x0
+; GFX12-NEXT:    global_store_b32 v[3:4], v0, off
+; GFX12-NEXT:    s_endpgm
   %a = load i8, ptr addrspace(4) %ptra
   %a16 = sext i8 %a to i16
   %res = insertelement <2 x i16> %vec, i16 %a16, i32 0
@@ -362,23 +289,12 @@ define amdgpu_ps void @sextload_P4_i8_D16(<2 x i16> %vec, ptr addrspace(4) %ptra
 }
 
 define amdgpu_ps void @sextload_P4_i8_D16_Hi(<2 x i16> %vec, ptr addrspace(4) %ptra, ptr addrspace(1) %out) {
-; GFX12-TRUE16-LABEL: sextload_P4_i8_D16_Hi:
-; GFX12-TRUE16:       ; %bb.0:
-; GFX12-TRUE16-NEXT:    global_load_d16_i8 v1, v[1:2], off
-; GFX12-TRUE16-NEXT:    s_wait_loadcnt 0x0
-; GFX12-TRUE16-NEXT:    v_mov_b16_e32 v1.h, 0
-; GFX12-TRUE16-NEXT:    s_delay_alu instid0(VALU_DEP_1) | instskip(NEXT) | instid1(VALU_DEP_1)
-; GFX12-TRUE16-NEXT:    v_lshlrev_b32_e32 v1, 16, v1
-; GFX12-TRUE16-NEXT:    v_and_or_b32 v0, 0xffff, v0, v1
-; GFX12-TRUE16-NEXT:    global_store_b32 v[3:4], v0, off
-; GFX12-TRUE16-NEXT:    s_endpgm
-;
-; GFX12-FAKE16-LABEL: sextload_P4_i8_D16_Hi:
-; GFX12-FAKE16:       ; %bb.0:
-; GFX12-FAKE16-NEXT:    global_load_d16_hi_i8 v0, v[1:2], off
-; GFX12-FAKE16-NEXT:    s_wait_loadcnt 0x0
-; GFX12-FAKE16-NEXT:    global_store_b32 v[3:4], v0, off
-; GFX12-FAKE16-NEXT:    s_endpgm
+; GFX12-LABEL: sextload_P4_i8_D16_Hi:
+; GFX12:       ; %bb.0:
+; GFX12-NEXT:    global_load_d16_hi_i8 v0, v[1:2], off
+; GFX12-NEXT:    s_wait_loadcnt 0x0
+; GFX12-NEXT:    global_store_b32 v[3:4], v0, off
+; GFX12-NEXT:    s_endpgm
   %a = load i8, ptr addrspace(4) %ptra
   %a16 = sext i8 %a to i16
   %res = insertelement <2 x i16> %vec, i16 %a16, i32 1
@@ -441,22 +357,12 @@ define amdgpu_ps void @load_P5_B16_D16_Hi(<2 x i16> %vec, ptr addrspace(5) %ptra
 }
 
 define amdgpu_ps void @sextload_P5_i8_D16(<2 x i16> %vec, ptr addrspace(5) %ptra, ptr addrspace(5) %out) {
-; GFX12-TRUE16-LABEL: sextload_P5_i8_D16:
-; GFX12-TRUE16:       ; %bb.0:
-; GFX12-TRUE16-NEXT:    scratch_load_d16_i8 v1, v1, off
-; GFX12-TRUE16-NEXT:    s_wait_loadcnt 0x0
-; GFX12-TRUE16-NEXT:    v_mov_b16_e32 v1.h, 0
-; GFX12-TRUE16-NEXT:    s_delay_alu instid0(VALU_DEP_1)
-; GFX12-TRUE16-NEXT:    v_and_or_b32 v0, 0xffff0000, v0, v1
-; GFX12-TRUE16-NEXT:    scratch_store_b32 v2, v0, off
-; GFX12-TRUE16-NEXT:    s_endpgm
-;
-; GFX12-FAKE16-LABEL: sextload_P5_i8_D16:
-; GFX12-FAKE16:       ; %bb.0:
-; GFX12-FAKE16-NEXT:    scratch_load_d16_i8 v0, v1, off
-; GFX12-FAKE16-NEXT:    s_wait_loadcnt 0x0
-; GFX12-FAKE16-NEXT:    scratch_store_b32 v2, v0, off
-; GFX12-FAKE16-NEXT:    s_endpgm
+; GFX12-LABEL: sextload_P5_i8_D16:
+; GFX12:       ; %bb.0:
+; GFX12-NEXT:    scratch_load_d16_i8 v0, v1, off
+; GFX12-NEXT:    s_wait_loadcnt 0x0
+; GFX12-NEXT:    scratch_store_b32 v2, v0, off
+; GFX12-NEXT:    s_endpgm
   %a = load i8, ptr addrspace(5) %ptra
   %a16 = sext i8 %a to i16
   %res = insertelement <2 x i16> %vec, i16 %a16, i32 0
@@ -465,23 +371,12 @@ define amdgpu_ps void @sextload_P5_i8_D16(<2 x i16> %vec, ptr addrspace(5) %ptra
 }
 
 define amdgpu_ps void @sextload_P5_i8_D16_Hi(<2 x i16> %vec, ptr addrspace(5) %ptra, ptr addrspace(5) %out) {
-; GFX12-TRUE16-LABEL: sextload_P5_i8_D16_Hi:
-; GFX12-TRUE16:       ; %bb.0:
-; GFX12-TRUE16-NEXT:    scratch_load_d16_i8 v1, v1, off
-; GFX12-TRUE16-NEXT:    s_wait_loadcnt 0x0
-; GFX12-TRUE16-NEXT:    v_mov_b16_e32 v1.h, 0
-; GFX12-TRUE16-NEXT:    s_delay_alu instid0(VALU_DEP_1) | instskip(NEXT) | instid1(VALU_DEP_1)
-; GFX12-TRUE16-NEXT:    v_lshlrev_b32_e32 v1, 16, v1
-; GFX12-TRUE16-NEXT:    v_and_or_b32 v0, 0xffff, v0, v1
-; GFX12-TRUE16-NEXT:    scratch_store_b32 v2, v0, off
-; GFX12-TRUE16-NEXT:    s_endpgm
-;
-; GFX12-FAKE16-LABEL: sextload_P5_i8_D16_Hi:
-; GFX12-FAKE16:       ; %bb.0:
-; GFX12-FAKE16-NEXT:    scratch_load_d16_hi_i8 v0, v1, off
-; GFX12-FAKE16-NEXT:    s_wait_loadcnt 0x0
-; GFX12-FAKE16-NEXT:    scratch_store_b32 v2, v0, off
-; GFX12-FAKE16-NEXT:    s_endpgm
+; GFX12-LABEL: sextload_P5_i8_D16_Hi:
+; GFX12:       ; %bb.0:
+; GFX12-NEXT:    scratch_load_d16_hi_i8 v0, v1, off
+; GFX12-NEXT:    s_wait_loadcnt 0x0
+; GFX12-NEXT:    scratch_store_b32 v2, v0, off
+; GFX12-NEXT:    s_endpgm
   %a = load i8, ptr addrspace(5) %ptra
   %a16 = sext i8 %a to i16
   %res = insertelement <2 x i16> %vec, i16 %a16, i32 1
@@ -516,3 +411,6 @@ define amdgpu_ps void @zextload_P5_i8_D16_Hi(<2 x i16> %vec, ptr addrspace(5) %p
   store <2 x i16> %res, ptr addrspace(5) %out
   ret void
 }
+;; NOTE: These prefixes are unused and the list is autogenerated. Do not add tests below this line:
+; GFX12-FAKE16: {{.*}}
+; GFX12-TRUE16: {{.*}}

>From a97f71f416abb0f9495cb681264cdaf770efcf9d Mon Sep 17 00:00:00 2001
From: Domenic Nutile <domenic.nutile at amd.com>
Date: Wed, 20 May 2026 16:14:13 -0400
Subject: [PATCH 2/2] PR feedback, fix tests

---
 .../Target/AMDGPU/AMDGPURegBankCombiner.cpp   |  26 ++--
 llvm/test/CodeGen/AMDGPU/global-saddr-load.ll | 114 ++++--------------
 2 files changed, 36 insertions(+), 104 deletions(-)

diff --git a/llvm/lib/Target/AMDGPU/AMDGPURegBankCombiner.cpp b/llvm/lib/Target/AMDGPU/AMDGPURegBankCombiner.cpp
index 27da32f2a1e89..35c0d4046f41e 100644
--- a/llvm/lib/Target/AMDGPU/AMDGPURegBankCombiner.cpp
+++ b/llvm/lib/Target/AMDGPU/AMDGPURegBankCombiner.cpp
@@ -418,10 +418,15 @@ bool AMDGPURegBankCombinerImpl::combineD16Load(MachineInstr &MI) const {
       return false;
     }
 
+    // s32 Load_lo16 holds SextLoad i8, Load_hi16 is zero.
+    // fake16: and  (sextload i8 -> s32), 0xFFFF
+    // true16: zext (sextload i8 -> s16) -> s32
     if (mi_match(
             Load, MRI,
             m_GAnd(m_MInstr(SextLoad), m_Copy(m_SpecificICst(CleanHi16)))) ||
-        mi_match(Load, MRI, m_GZExt(m_MInstr(SextLoad)))) {
+        mi_match(Load, MRI,
+                 m_GZExt(m_all_of(m_SpecificType(LLT::scalar(16)),
+                                  m_MInstr(SextLoad))))) {
       if (SextLoad->getOpcode() != AMDGPU::G_SEXTLOAD)
         return false;
 
@@ -429,12 +434,6 @@ bool AMDGPURegBankCombinerImpl::combineD16Load(MachineInstr &MI) const {
       if (MMO->getSizeInBits().getValue() != 8)
         return false;
 
-      if (Load->getOpcode() == TargetOpcode::G_ZEXT) {
-        LLT SextDstTy = MRI.getType(SextLoad->getOperand(0).getReg());
-        if (SextDstTy.getSizeInBits() != 16)
-          return false;
-      }
-
       return applyD16Load(AMDGPU::G_AMDGPU_LOAD_D16_LO_I8, MI, SextLoad, Dst);
     }
 
@@ -457,10 +456,15 @@ bool AMDGPURegBankCombinerImpl::combineD16Load(MachineInstr &MI) const {
       return false;
     }
 
+    // s32 Load_lo16 holds SextLoad i8, Load_hi16 is zero.
+    // fake16: and  (sextload i8 -> s32), 0xFFFF
+    // true16: zext (sextload i8 -> s16) -> s32
     if (mi_match(
             Load, MRI,
             m_GAnd(m_MInstr(SextLoad), m_Copy(m_SpecificICst(CleanHi16)))) ||
-        mi_match(Load, MRI, m_GZExt(m_MInstr(SextLoad)))) {
+        mi_match(Load, MRI,
+                 m_GZExt(m_all_of(m_SpecificType(LLT::scalar(16)),
+                                  m_MInstr(SextLoad))))) {
       if (SextLoad->getOpcode() != AMDGPU::G_SEXTLOAD)
         return false;
 
@@ -468,12 +472,6 @@ bool AMDGPURegBankCombinerImpl::combineD16Load(MachineInstr &MI) const {
       if (MMO->getSizeInBits().getValue() != 8)
         return false;
 
-      if (Load->getOpcode() == TargetOpcode::G_ZEXT) {
-        LLT SextDstTy = MRI.getType(SextLoad->getOperand(0).getReg());
-        if (SextDstTy.getSizeInBits() != 16)
-          return false;
-      }
-
       return applyD16Load(AMDGPU::G_AMDGPU_LOAD_D16_HI_I8, MI, SextLoad, Dst);
     }
 
diff --git a/llvm/test/CodeGen/AMDGPU/global-saddr-load.ll b/llvm/test/CodeGen/AMDGPU/global-saddr-load.ll
index 2c16351a9bb4d..9e4c6e6935596 100644
--- a/llvm/test/CodeGen/AMDGPU/global-saddr-load.ll
+++ b/llvm/test/CodeGen/AMDGPU/global-saddr-load.ll
@@ -4203,28 +4203,12 @@ define amdgpu_ps <2 x half> @global_load_saddr_i16_d16lo_sexti8_reg_hi(ptr addrs
 ; GFX11-NEXT:    v_mov_b32_e32 v0, v1
 ; GFX11-NEXT:    ; return to shader part epilog
 ;
-; GFX12-SDAG-LABEL: global_load_saddr_i16_d16lo_sexti8_reg_hi:
-; GFX12-SDAG:       ; %bb.0:
-; GFX12-SDAG-NEXT:    global_load_d16_i8 v1, v0, s[2:3]
-; GFX12-SDAG-NEXT:    s_wait_loadcnt 0x0
-; GFX12-SDAG-NEXT:    v_mov_b32_e32 v0, v1
-; GFX12-SDAG-NEXT:    ; return to shader part epilog
-;
-; GFX12-GISEL-TRUE16-LABEL: global_load_saddr_i16_d16lo_sexti8_reg_hi:
-; GFX12-GISEL-TRUE16:       ; %bb.0:
-; GFX12-GISEL-TRUE16-NEXT:    global_load_d16_i8 v0, v0, s[2:3]
-; GFX12-GISEL-TRUE16-NEXT:    s_wait_loadcnt 0x0
-; GFX12-GISEL-TRUE16-NEXT:    v_mov_b16_e32 v0.h, 0
-; GFX12-GISEL-TRUE16-NEXT:    s_delay_alu instid0(VALU_DEP_1)
-; GFX12-GISEL-TRUE16-NEXT:    v_and_or_b32 v0, 0xffff0000, v1, v0
-; GFX12-GISEL-TRUE16-NEXT:    ; return to shader part epilog
-;
-; GFX12-GISEL-FAKE16-LABEL: global_load_saddr_i16_d16lo_sexti8_reg_hi:
-; GFX12-GISEL-FAKE16:       ; %bb.0:
-; GFX12-GISEL-FAKE16-NEXT:    global_load_d16_i8 v1, v0, s[2:3]
-; GFX12-GISEL-FAKE16-NEXT:    s_wait_loadcnt 0x0
-; GFX12-GISEL-FAKE16-NEXT:    v_mov_b32_e32 v0, v1
-; GFX12-GISEL-FAKE16-NEXT:    ; return to shader part epilog
+; GFX12-LABEL: global_load_saddr_i16_d16lo_sexti8_reg_hi:
+; GFX12:       ; %bb.0:
+; GFX12-NEXT:    global_load_d16_i8 v1, v0, s[2:3]
+; GFX12-NEXT:    s_wait_loadcnt 0x0
+; GFX12-NEXT:    v_mov_b32_e32 v0, v1
+; GFX12-NEXT:    ; return to shader part epilog
   %zext.offset = zext i32 %voffset to i64
   %gep0 = getelementptr inbounds i8, ptr addrspace(1) %sbase, i64 %zext.offset
   %load = load i8, ptr addrspace(1) %gep0
@@ -4249,28 +4233,12 @@ define amdgpu_ps <2 x half> @global_load_saddr_i16_d16lo_sexti8_reg_hi_immneg128
 ; GFX11-NEXT:    v_mov_b32_e32 v0, v1
 ; GFX11-NEXT:    ; return to shader part epilog
 ;
-; GFX12-SDAG-LABEL: global_load_saddr_i16_d16lo_sexti8_reg_hi_immneg128:
-; GFX12-SDAG:       ; %bb.0:
-; GFX12-SDAG-NEXT:    global_load_d16_i8 v1, v0, s[2:3] offset:-128
-; GFX12-SDAG-NEXT:    s_wait_loadcnt 0x0
-; GFX12-SDAG-NEXT:    v_mov_b32_e32 v0, v1
-; GFX12-SDAG-NEXT:    ; return to shader part epilog
-;
-; GFX12-GISEL-TRUE16-LABEL: global_load_saddr_i16_d16lo_sexti8_reg_hi_immneg128:
-; GFX12-GISEL-TRUE16:       ; %bb.0:
-; GFX12-GISEL-TRUE16-NEXT:    global_load_d16_i8 v0, v0, s[2:3] offset:-128
-; GFX12-GISEL-TRUE16-NEXT:    s_wait_loadcnt 0x0
-; GFX12-GISEL-TRUE16-NEXT:    v_mov_b16_e32 v0.h, 0
-; GFX12-GISEL-TRUE16-NEXT:    s_delay_alu instid0(VALU_DEP_1)
-; GFX12-GISEL-TRUE16-NEXT:    v_and_or_b32 v0, 0xffff0000, v1, v0
-; GFX12-GISEL-TRUE16-NEXT:    ; return to shader part epilog
-;
-; GFX12-GISEL-FAKE16-LABEL: global_load_saddr_i16_d16lo_sexti8_reg_hi_immneg128:
-; GFX12-GISEL-FAKE16:       ; %bb.0:
-; GFX12-GISEL-FAKE16-NEXT:    global_load_d16_i8 v1, v0, s[2:3] offset:-128
-; GFX12-GISEL-FAKE16-NEXT:    s_wait_loadcnt 0x0
-; GFX12-GISEL-FAKE16-NEXT:    v_mov_b32_e32 v0, v1
-; GFX12-GISEL-FAKE16-NEXT:    ; return to shader part epilog
+; GFX12-LABEL: global_load_saddr_i16_d16lo_sexti8_reg_hi_immneg128:
+; GFX12:       ; %bb.0:
+; GFX12-NEXT:    global_load_d16_i8 v1, v0, s[2:3] offset:-128
+; GFX12-NEXT:    s_wait_loadcnt 0x0
+; GFX12-NEXT:    v_mov_b32_e32 v0, v1
+; GFX12-NEXT:    ; return to shader part epilog
   %zext.offset = zext i32 %voffset to i64
   %gep0 = getelementptr inbounds i8, ptr addrspace(1) %sbase, i64 %zext.offset
   %gep1 = getelementptr inbounds i8, ptr addrspace(1) %gep0, i64 -128
@@ -4628,29 +4596,12 @@ define amdgpu_ps <2 x half> @global_load_saddr_i16_d16hi_sexti8_reg_hi(ptr addrs
 ; GFX11-NEXT:    v_mov_b32_e32 v0, v1
 ; GFX11-NEXT:    ; return to shader part epilog
 ;
-; GFX12-SDAG-LABEL: global_load_saddr_i16_d16hi_sexti8_reg_hi:
-; GFX12-SDAG:       ; %bb.0:
-; GFX12-SDAG-NEXT:    global_load_d16_hi_i8 v1, v0, s[2:3]
-; GFX12-SDAG-NEXT:    s_wait_loadcnt 0x0
-; GFX12-SDAG-NEXT:    v_mov_b32_e32 v0, v1
-; GFX12-SDAG-NEXT:    ; return to shader part epilog
-;
-; GFX12-GISEL-TRUE16-LABEL: global_load_saddr_i16_d16hi_sexti8_reg_hi:
-; GFX12-GISEL-TRUE16:       ; %bb.0:
-; GFX12-GISEL-TRUE16-NEXT:    global_load_d16_i8 v0, v0, s[2:3]
-; GFX12-GISEL-TRUE16-NEXT:    s_wait_loadcnt 0x0
-; GFX12-GISEL-TRUE16-NEXT:    v_mov_b16_e32 v0.h, 0
-; GFX12-GISEL-TRUE16-NEXT:    s_delay_alu instid0(VALU_DEP_1) | instskip(NEXT) | instid1(VALU_DEP_1)
-; GFX12-GISEL-TRUE16-NEXT:    v_lshlrev_b32_e32 v0, 16, v0
-; GFX12-GISEL-TRUE16-NEXT:    v_and_or_b32 v0, 0xffff, v1, v0
-; GFX12-GISEL-TRUE16-NEXT:    ; return to shader part epilog
-;
-; GFX12-GISEL-FAKE16-LABEL: global_load_saddr_i16_d16hi_sexti8_reg_hi:
-; GFX12-GISEL-FAKE16:       ; %bb.0:
-; GFX12-GISEL-FAKE16-NEXT:    global_load_d16_hi_i8 v1, v0, s[2:3]
-; GFX12-GISEL-FAKE16-NEXT:    s_wait_loadcnt 0x0
-; GFX12-GISEL-FAKE16-NEXT:    v_mov_b32_e32 v0, v1
-; GFX12-GISEL-FAKE16-NEXT:    ; return to shader part epilog
+; GFX12-LABEL: global_load_saddr_i16_d16hi_sexti8_reg_hi:
+; GFX12:       ; %bb.0:
+; GFX12-NEXT:    global_load_d16_hi_i8 v1, v0, s[2:3]
+; GFX12-NEXT:    s_wait_loadcnt 0x0
+; GFX12-NEXT:    v_mov_b32_e32 v0, v1
+; GFX12-NEXT:    ; return to shader part epilog
   %zext.offset = zext i32 %voffset to i64
   %gep0 = getelementptr inbounds i8, ptr addrspace(1) %sbase, i64 %zext.offset
   %load = load i8, ptr addrspace(1) %gep0
@@ -4675,29 +4626,12 @@ define amdgpu_ps <2 x half> @global_load_saddr_i16_d16hi_sexti8_reg_hi_immneg128
 ; GFX11-NEXT:    v_mov_b32_e32 v0, v1
 ; GFX11-NEXT:    ; return to shader part epilog
 ;
-; GFX12-SDAG-LABEL: global_load_saddr_i16_d16hi_sexti8_reg_hi_immneg128:
-; GFX12-SDAG:       ; %bb.0:
-; GFX12-SDAG-NEXT:    global_load_d16_hi_i8 v1, v0, s[2:3] offset:-128
-; GFX12-SDAG-NEXT:    s_wait_loadcnt 0x0
-; GFX12-SDAG-NEXT:    v_mov_b32_e32 v0, v1
-; GFX12-SDAG-NEXT:    ; return to shader part epilog
-;
-; GFX12-GISEL-TRUE16-LABEL: global_load_saddr_i16_d16hi_sexti8_reg_hi_immneg128:
-; GFX12-GISEL-TRUE16:       ; %bb.0:
-; GFX12-GISEL-TRUE16-NEXT:    global_load_d16_i8 v0, v0, s[2:3] offset:-128
-; GFX12-GISEL-TRUE16-NEXT:    s_wait_loadcnt 0x0
-; GFX12-GISEL-TRUE16-NEXT:    v_mov_b16_e32 v0.h, 0
-; GFX12-GISEL-TRUE16-NEXT:    s_delay_alu instid0(VALU_DEP_1) | instskip(NEXT) | instid1(VALU_DEP_1)
-; GFX12-GISEL-TRUE16-NEXT:    v_lshlrev_b32_e32 v0, 16, v0
-; GFX12-GISEL-TRUE16-NEXT:    v_and_or_b32 v0, 0xffff, v1, v0
-; GFX12-GISEL-TRUE16-NEXT:    ; return to shader part epilog
-;
-; GFX12-GISEL-FAKE16-LABEL: global_load_saddr_i16_d16hi_sexti8_reg_hi_immneg128:
-; GFX12-GISEL-FAKE16:       ; %bb.0:
-; GFX12-GISEL-FAKE16-NEXT:    global_load_d16_hi_i8 v1, v0, s[2:3] offset:-128
-; GFX12-GISEL-FAKE16-NEXT:    s_wait_loadcnt 0x0
-; GFX12-GISEL-FAKE16-NEXT:    v_mov_b32_e32 v0, v1
-; GFX12-GISEL-FAKE16-NEXT:    ; return to shader part epilog
+; GFX12-LABEL: global_load_saddr_i16_d16hi_sexti8_reg_hi_immneg128:
+; GFX12:       ; %bb.0:
+; GFX12-NEXT:    global_load_d16_hi_i8 v1, v0, s[2:3] offset:-128
+; GFX12-NEXT:    s_wait_loadcnt 0x0
+; GFX12-NEXT:    v_mov_b32_e32 v0, v1
+; GFX12-NEXT:    ; return to shader part epilog
   %zext.offset = zext i32 %voffset to i64
   %gep0 = getelementptr inbounds i8, ptr addrspace(1) %sbase, i64 %zext.offset
   %gep1 = getelementptr inbounds i8, ptr addrspace(1) %gep0, i64 -128



More information about the llvm-branch-commits mailing list