[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