[llvm] [AMDGPU] Fuse dword load + sign/zero-extension into subword load (PR #219019)

via llvm-commits llvm-commits at lists.llvm.org
Wed Aug 26 14:55:14 PDT 2026


https://github.com/LU-JOHN updated https://github.com/llvm/llvm-project/pull/219019

>From 1d77b7a6d78aefcf783fdd7c621477ae40217917 Mon Sep 17 00:00:00 2001
From: John Lu <John.Lu at amd.com>
Date: Wed, 26 Aug 2026 10:19:39 -0500
Subject: [PATCH 1/2] Commit current results for new testcases

Signed-off-by: John Lu <John.Lu at amd.com>
---
 .../CodeGen/AMDGPU/scalar-subword-loads.ll    | 264 +++++++++
 .../AMDGPU/si-load-opt-scalar-subword.mir     | 561 ++++++++++++++++++
 2 files changed, 825 insertions(+)
 create mode 100644 llvm/test/CodeGen/AMDGPU/scalar-subword-loads.ll
 create mode 100644 llvm/test/CodeGen/AMDGPU/si-load-opt-scalar-subword.mir

diff --git a/llvm/test/CodeGen/AMDGPU/scalar-subword-loads.ll b/llvm/test/CodeGen/AMDGPU/scalar-subword-loads.ll
new file mode 100644
index 0000000000000..e39d12963633b
--- /dev/null
+++ b/llvm/test/CodeGen/AMDGPU/scalar-subword-loads.ll
@@ -0,0 +1,264 @@
+; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py UTC_ARGS: --version 6
+; Test all scalar subword load optimization variants
+; RUN: llc -mtriple=amdgcn -mcpu=gfx1250 < %s | FileCheck %s
+
+declare i32 @llvm.amdgcn.s.buffer.load.i32(<4 x i32>, i32, i32 immarg)
+
+;===----------------------------------------------------------------------===;
+; S_LOAD variants (address space 4)
+;===----------------------------------------------------------------------===;
+
+define amdgpu_kernel void @s_load_u8(ptr addrspace(1) %out) {
+; CHECK-LABEL: s_load_u8:
+; CHECK:       ; %bb.0:
+; CHECK-NEXT:    s_setreg_imm32_b32 hwreg(HW_REG_WAVE_MODE, 25, 1), 1 ; msbs: dst=0 src0=0 src1=0 src2=0
+; CHECK-NEXT:    s_mov_b64 s[64:65], 0
+; CHECK-NEXT:    v_nop
+; CHECK-NEXT:    global_prefetch_b8 v0, s[64:65] scope:SCOPE_SE
+; CHECK-NEXT:    s_mov_b64 s[0:1], 16
+; CHECK-NEXT:    s_load_b32 s6, s[0:1], 0x0 nv
+; CHECK-NEXT:    s_load_b64 s[2:3], s[4:5], 0x24 nv
+; CHECK-NEXT:    s_wait_kmcnt 0x0
+; CHECK-NEXT:    s_and_b32 s0, s6, 0xff
+; CHECK-NEXT:    s_delay_alu instid0(SALU_CYCLE_1)
+; CHECK-NEXT:    v_dual_mov_b32 v0, 0 :: v_dual_mov_b32 v1, s0
+; CHECK-NEXT:    global_store_b32 v0, v1, s[2:3]
+; CHECK-NEXT:    s_endpgm
+  %ptr = inttoptr i64 16 to ptr addrspace(4)
+  %val = load i32, ptr addrspace(4) %ptr, align 4
+  %masked = and i32 %val, 255
+  store i32 %masked, ptr addrspace(1) %out
+  ret void
+}
+
+define amdgpu_kernel void @s_load_u16(ptr addrspace(1) %out) {
+; CHECK-LABEL: s_load_u16:
+; CHECK:       ; %bb.0:
+; CHECK-NEXT:    s_setreg_imm32_b32 hwreg(HW_REG_WAVE_MODE, 25, 1), 1 ; msbs: dst=0 src0=0 src1=0 src2=0
+; CHECK-NEXT:    s_mov_b64 s[64:65], 0
+; CHECK-NEXT:    v_nop
+; CHECK-NEXT:    global_prefetch_b8 v0, s[64:65] scope:SCOPE_SE
+; CHECK-NEXT:    s_mov_b64 s[0:1], 16
+; CHECK-NEXT:    s_load_b32 s6, s[0:1], 0x0 nv
+; CHECK-NEXT:    s_load_b64 s[2:3], s[4:5], 0x24 nv
+; CHECK-NEXT:    s_wait_kmcnt 0x0
+; CHECK-NEXT:    s_and_b32 s0, s6, 0xffff
+; CHECK-NEXT:    s_delay_alu instid0(SALU_CYCLE_1)
+; CHECK-NEXT:    v_dual_mov_b32 v0, 0 :: v_dual_mov_b32 v1, s0
+; CHECK-NEXT:    global_store_b32 v0, v1, s[2:3]
+; CHECK-NEXT:    s_endpgm
+  %ptr = inttoptr i64 16 to ptr addrspace(4)
+  %val = load i32, ptr addrspace(4) %ptr, align 4
+  %masked = and i32 %val, 65535
+  store i32 %masked, ptr addrspace(1) %out
+  ret void
+}
+
+define amdgpu_kernel void @s_load_i8(ptr addrspace(1) %out) {
+; CHECK-LABEL: s_load_i8:
+; CHECK:       ; %bb.0:
+; CHECK-NEXT:    s_setreg_imm32_b32 hwreg(HW_REG_WAVE_MODE, 25, 1), 1 ; msbs: dst=0 src0=0 src1=0 src2=0
+; CHECK-NEXT:    s_mov_b64 s[64:65], 0
+; CHECK-NEXT:    v_nop
+; CHECK-NEXT:    global_prefetch_b8 v0, s[64:65] scope:SCOPE_SE
+; CHECK-NEXT:    s_mov_b64 s[0:1], 16
+; CHECK-NEXT:    s_load_i8 s6, s[0:1], 0x0 nv
+; CHECK-NEXT:    s_load_b64 s[2:3], s[4:5], 0x24 nv
+; CHECK-NEXT:    s_wait_kmcnt 0x0
+; CHECK-NEXT:    v_dual_mov_b32 v0, 0 :: v_dual_mov_b32 v1, s6
+; CHECK-NEXT:    global_store_b32 v0, v1, s[2:3]
+; CHECK-NEXT:    s_endpgm
+  %ptr = inttoptr i64 16 to ptr addrspace(4)
+  %val8 = load i8, ptr addrspace(4) %ptr, align 1
+  %ext = sext i8 %val8 to i32
+  store i32 %ext, ptr addrspace(1) %out
+  ret void
+}
+
+define amdgpu_kernel void @s_load_i16(ptr addrspace(1) %out) {
+; CHECK-LABEL: s_load_i16:
+; CHECK:       ; %bb.0:
+; CHECK-NEXT:    s_setreg_imm32_b32 hwreg(HW_REG_WAVE_MODE, 25, 1), 1 ; msbs: dst=0 src0=0 src1=0 src2=0
+; CHECK-NEXT:    s_mov_b64 s[64:65], 0
+; CHECK-NEXT:    v_nop
+; CHECK-NEXT:    global_prefetch_b8 v0, s[64:65] scope:SCOPE_SE
+; CHECK-NEXT:    s_mov_b64 s[0:1], 16
+; CHECK-NEXT:    s_load_i16 s6, s[0:1], 0x0 nv
+; CHECK-NEXT:    s_load_b64 s[2:3], s[4:5], 0x24 nv
+; CHECK-NEXT:    s_wait_kmcnt 0x0
+; CHECK-NEXT:    v_dual_mov_b32 v0, 0 :: v_dual_mov_b32 v1, s6
+; CHECK-NEXT:    global_store_b32 v0, v1, s[2:3]
+; CHECK-NEXT:    s_endpgm
+  %ptr = inttoptr i64 16 to ptr addrspace(4)
+  %val16 = load i16, ptr addrspace(4) %ptr, align 2
+  %ext = sext i16 %val16 to i32
+  store i32 %ext, ptr addrspace(1) %out
+  ret void
+}
+
+;===----------------------------------------------------------------------===;
+; S_BUFFER_LOAD variants with immediate offsets
+;===----------------------------------------------------------------------===;
+
+define amdgpu_cs i32 @s_buffer_load_u8_imm(<4 x i32> inreg %buf) {
+; CHECK-LABEL: s_buffer_load_u8_imm:
+; CHECK:       ; %bb.0:
+; CHECK-NEXT:    s_setreg_imm32_b32 hwreg(HW_REG_WAVE_MODE, 25, 1), 1 ; msbs: dst=0 src0=0 src1=0 src2=0
+; CHECK-NEXT:    s_mov_b64 s[64:65], 0
+; CHECK-NEXT:    v_nop
+; CHECK-NEXT:    global_prefetch_b8 v0, s[64:65] scope:SCOPE_SE
+; CHECK-NEXT:    s_buffer_load_b32 s0, s[0:3], 0x10 nv
+; CHECK-NEXT:    s_wait_kmcnt 0x0
+; CHECK-NEXT:    s_and_b32 s0, s0, 0xff
+; CHECK-NEXT:    ; return to shader part epilog
+  %val = call i32 @llvm.amdgcn.s.buffer.load.i32(<4 x i32> %buf, i32 16, i32 0)
+  %masked = and i32 %val, 255
+  ret i32 %masked
+}
+
+define amdgpu_cs i32 @s_buffer_load_u16_imm(<4 x i32> inreg %buf) {
+; CHECK-LABEL: s_buffer_load_u16_imm:
+; CHECK:       ; %bb.0:
+; CHECK-NEXT:    s_setreg_imm32_b32 hwreg(HW_REG_WAVE_MODE, 25, 1), 1 ; msbs: dst=0 src0=0 src1=0 src2=0
+; CHECK-NEXT:    s_mov_b64 s[64:65], 0
+; CHECK-NEXT:    v_nop
+; CHECK-NEXT:    global_prefetch_b8 v0, s[64:65] scope:SCOPE_SE
+; CHECK-NEXT:    s_buffer_load_b32 s0, s[0:3], 0x10 nv
+; CHECK-NEXT:    s_wait_kmcnt 0x0
+; CHECK-NEXT:    s_and_b32 s0, s0, 0xffff
+; CHECK-NEXT:    ; return to shader part epilog
+  %val = call i32 @llvm.amdgcn.s.buffer.load.i32(<4 x i32> %buf, i32 16, i32 0)
+  %masked = and i32 %val, 65535
+  ret i32 %masked
+}
+
+define amdgpu_cs i32 @s_buffer_load_i8_imm(<4 x i32> inreg %buf) {
+; CHECK-LABEL: s_buffer_load_i8_imm:
+; CHECK:       ; %bb.0:
+; CHECK-NEXT:    s_setreg_imm32_b32 hwreg(HW_REG_WAVE_MODE, 25, 1), 1 ; msbs: dst=0 src0=0 src1=0 src2=0
+; CHECK-NEXT:    s_mov_b64 s[64:65], 0
+; CHECK-NEXT:    v_nop
+; CHECK-NEXT:    global_prefetch_b8 v0, s[64:65] scope:SCOPE_SE
+; CHECK-NEXT:    s_buffer_load_b32 s0, s[0:3], 0x10 nv
+; CHECK-NEXT:    s_wait_kmcnt 0x0
+; CHECK-NEXT:    s_sext_i32_i8 s0, s0
+; CHECK-NEXT:    ; return to shader part epilog
+  %val = call i32 @llvm.amdgcn.s.buffer.load.i32(<4 x i32> %buf, i32 16, i32 0)
+  %trunc = trunc i32 %val to i8
+  %ext = sext i8 %trunc to i32
+  ret i32 %ext
+}
+
+define amdgpu_cs i32 @s_buffer_load_i16_imm(<4 x i32> inreg %buf) {
+; CHECK-LABEL: s_buffer_load_i16_imm:
+; CHECK:       ; %bb.0:
+; CHECK-NEXT:    s_setreg_imm32_b32 hwreg(HW_REG_WAVE_MODE, 25, 1), 1 ; msbs: dst=0 src0=0 src1=0 src2=0
+; CHECK-NEXT:    s_mov_b64 s[64:65], 0
+; CHECK-NEXT:    v_nop
+; CHECK-NEXT:    global_prefetch_b8 v0, s[64:65] scope:SCOPE_SE
+; CHECK-NEXT:    s_buffer_load_b32 s0, s[0:3], 0x10 nv
+; CHECK-NEXT:    s_wait_kmcnt 0x0
+; CHECK-NEXT:    s_sext_i32_i16 s0, s0
+; CHECK-NEXT:    ; return to shader part epilog
+  %val = call i32 @llvm.amdgcn.s.buffer.load.i32(<4 x i32> %buf, i32 16, i32 0)
+  %trunc = trunc i32 %val to i16
+  %ext = sext i16 %trunc to i32
+  ret i32 %ext
+}
+
+;===----------------------------------------------------------------------===;
+; S_BUFFER_LOAD variants with SGPR offsets (SGPR_IMM mode)
+;===----------------------------------------------------------------------===;
+
+define amdgpu_cs i32 @s_buffer_load_u8_sgpr(<4 x i32> inreg %buf, i32 inreg %offset) {
+; CHECK-LABEL: s_buffer_load_u8_sgpr:
+; CHECK:       ; %bb.0:
+; CHECK-NEXT:    s_setreg_imm32_b32 hwreg(HW_REG_WAVE_MODE, 25, 1), 1 ; msbs: dst=0 src0=0 src1=0 src2=0
+; CHECK-NEXT:    s_mov_b64 s[64:65], 0
+; CHECK-NEXT:    v_nop
+; CHECK-NEXT:    global_prefetch_b8 v0, s[64:65] scope:SCOPE_SE
+; CHECK-NEXT:    s_buffer_load_b32 s0, s[0:3], s4 offset:0x0 nv
+; CHECK-NEXT:    s_wait_kmcnt 0x0
+; CHECK-NEXT:    s_and_b32 s0, s0, 0xff
+; CHECK-NEXT:    ; return to shader part epilog
+  %val = call i32 @llvm.amdgcn.s.buffer.load.i32(<4 x i32> %buf, i32 %offset, i32 0)
+  %masked = and i32 %val, 255
+  ret i32 %masked
+}
+
+define amdgpu_cs i32 @s_buffer_load_u16_sgpr(<4 x i32> inreg %buf, i32 inreg %offset) {
+; CHECK-LABEL: s_buffer_load_u16_sgpr:
+; CHECK:       ; %bb.0:
+; CHECK-NEXT:    s_setreg_imm32_b32 hwreg(HW_REG_WAVE_MODE, 25, 1), 1 ; msbs: dst=0 src0=0 src1=0 src2=0
+; CHECK-NEXT:    s_mov_b64 s[64:65], 0
+; CHECK-NEXT:    v_nop
+; CHECK-NEXT:    global_prefetch_b8 v0, s[64:65] scope:SCOPE_SE
+; CHECK-NEXT:    s_buffer_load_b32 s0, s[0:3], s4 offset:0x0 nv
+; CHECK-NEXT:    s_wait_kmcnt 0x0
+; CHECK-NEXT:    s_and_b32 s0, s0, 0xffff
+; CHECK-NEXT:    ; return to shader part epilog
+  %val = call i32 @llvm.amdgcn.s.buffer.load.i32(<4 x i32> %buf, i32 %offset, i32 0)
+  %masked = and i32 %val, 65535
+  ret i32 %masked
+}
+
+define amdgpu_cs i32 @s_buffer_load_i8_sgpr(<4 x i32> inreg %buf, i32 inreg %offset) {
+; CHECK-LABEL: s_buffer_load_i8_sgpr:
+; CHECK:       ; %bb.0:
+; CHECK-NEXT:    s_setreg_imm32_b32 hwreg(HW_REG_WAVE_MODE, 25, 1), 1 ; msbs: dst=0 src0=0 src1=0 src2=0
+; CHECK-NEXT:    s_mov_b64 s[64:65], 0
+; CHECK-NEXT:    v_nop
+; CHECK-NEXT:    global_prefetch_b8 v0, s[64:65] scope:SCOPE_SE
+; CHECK-NEXT:    s_buffer_load_b32 s0, s[0:3], s4 offset:0x0 nv
+; CHECK-NEXT:    s_wait_kmcnt 0x0
+; CHECK-NEXT:    s_sext_i32_i8 s0, s0
+; CHECK-NEXT:    ; return to shader part epilog
+  %val = call i32 @llvm.amdgcn.s.buffer.load.i32(<4 x i32> %buf, i32 %offset, i32 0)
+  %trunc = trunc i32 %val to i8
+  %ext = sext i8 %trunc to i32
+  ret i32 %ext
+}
+
+define amdgpu_cs i32 @s_buffer_load_i16_sgpr(<4 x i32> inreg %buf, i32 inreg %offset) {
+; CHECK-LABEL: s_buffer_load_i16_sgpr:
+; CHECK:       ; %bb.0:
+; CHECK-NEXT:    s_setreg_imm32_b32 hwreg(HW_REG_WAVE_MODE, 25, 1), 1 ; msbs: dst=0 src0=0 src1=0 src2=0
+; CHECK-NEXT:    s_mov_b64 s[64:65], 0
+; CHECK-NEXT:    v_nop
+; CHECK-NEXT:    global_prefetch_b8 v0, s[64:65] scope:SCOPE_SE
+; CHECK-NEXT:    s_buffer_load_b32 s0, s[0:3], s4 offset:0x0 nv
+; CHECK-NEXT:    s_wait_kmcnt 0x0
+; CHECK-NEXT:    s_sext_i32_i16 s0, s0
+; CHECK-NEXT:    ; return to shader part epilog
+  %val = call i32 @llvm.amdgcn.s.buffer.load.i32(<4 x i32> %buf, i32 %offset, i32 0)
+  %trunc = trunc i32 %val to i16
+  %ext = sext i16 %trunc to i32
+  ret i32 %ext
+}
+
+;===----------------------------------------------------------------------===;
+; Negative tests
+;===----------------------------------------------------------------------===;
+
+define amdgpu_kernel void @no_opt_wrong_mask(ptr addrspace(1) %out) {
+; CHECK-LABEL: no_opt_wrong_mask:
+; CHECK:       ; %bb.0:
+; CHECK-NEXT:    s_setreg_imm32_b32 hwreg(HW_REG_WAVE_MODE, 25, 1), 1 ; msbs: dst=0 src0=0 src1=0 src2=0
+; CHECK-NEXT:    s_mov_b64 s[64:65], 0
+; CHECK-NEXT:    v_nop
+; CHECK-NEXT:    global_prefetch_b8 v0, s[64:65] scope:SCOPE_SE
+; CHECK-NEXT:    s_mov_b64 s[0:1], 16
+; CHECK-NEXT:    s_load_b32 s6, s[0:1], 0x0 nv
+; CHECK-NEXT:    s_load_b64 s[2:3], s[4:5], 0x24 nv
+; CHECK-NEXT:    s_wait_kmcnt 0x0
+; CHECK-NEXT:    s_and_b32 s0, s6, 0x7f
+; CHECK-NEXT:    s_delay_alu instid0(SALU_CYCLE_1)
+; CHECK-NEXT:    v_dual_mov_b32 v0, 0 :: v_dual_mov_b32 v1, s0
+; CHECK-NEXT:    global_store_b32 v0, v1, s[2:3]
+; CHECK-NEXT:    s_endpgm
+  %ptr = inttoptr i64 16 to ptr addrspace(4)
+  %val = load i32, ptr addrspace(4) %ptr, align 4
+  %masked = and i32 %val, 127
+  store i32 %masked, ptr addrspace(1) %out
+  ret void
+}
diff --git a/llvm/test/CodeGen/AMDGPU/si-load-opt-scalar-subword.mir b/llvm/test/CodeGen/AMDGPU/si-load-opt-scalar-subword.mir
new file mode 100644
index 0000000000000..c65dc6cb32764
--- /dev/null
+++ b/llvm/test/CodeGen/AMDGPU/si-load-opt-scalar-subword.mir
@@ -0,0 +1,561 @@
+# NOTE: Assertions have been autogenerated by utils/update_mir_test_checks.py UTC_ARGS: --version 5
+# RUN: llc -mtriple=amdgcn -mcpu=gfx1250 -run-pass=si-load-store-opt %s -o - | FileCheck %s
+
+# Test scalar subword load optimization at MIR level
+# Tests all combinations of: {u8, u16, i8, i16} × {IMM, SGPR, SGPR_IMM} addressing modes
+# for both S_LOAD and S_BUFFER_LOAD variants
+
+---
+name: s_load_u8_imm
+tracksRegLiveness: true
+body: |
+  bb.0:
+    liveins: $sgpr0, $sgpr1
+    ; CHECK-LABEL: name: s_load_u8_imm
+    ; CHECK: liveins: $sgpr0, $sgpr1
+    ; CHECK-NEXT: {{  $}}
+    ; CHECK-NEXT: [[COPY:%[0-9]+]]:sgpr_32 = COPY $sgpr1
+    ; CHECK-NEXT: [[COPY1:%[0-9]+]]:sgpr_32 = COPY $sgpr0
+    ; CHECK-NEXT: [[REG_SEQUENCE:%[0-9]+]]:sreg_64 = REG_SEQUENCE [[COPY1]], %subreg.sub0, [[COPY]], %subreg.sub1
+    ; CHECK-NEXT: [[S_LOAD_DWORD_IMM:%[0-9]+]]:sreg_32_xm0_xexec = S_LOAD_DWORD_IMM [[REG_SEQUENCE]], 16, 0 :: (load (s32))
+    ; CHECK-NEXT: [[S_AND_B32_:%[0-9]+]]:sreg_32 = S_AND_B32 [[S_LOAD_DWORD_IMM]], 255, implicit-def $scc
+    ; CHECK-NEXT: S_ENDPGM 0, implicit [[S_AND_B32_]]
+    %1:sgpr_32 = COPY $sgpr1
+    %0:sgpr_32 = COPY $sgpr0
+    %2:sreg_64 = REG_SEQUENCE %0, %subreg.sub0, %1, %subreg.sub1
+    %3:sreg_32_xm0_xexec = S_LOAD_DWORD_IMM %2, 16, 0 :: (load (s32))
+    %4:sreg_32 = S_AND_B32 %3, 255, implicit-def $scc
+    S_ENDPGM 0, implicit %4
+...
+
+---
+name: s_load_u16_imm
+tracksRegLiveness: true
+body: |
+  bb.0:
+    liveins: $sgpr0, $sgpr1
+    ; CHECK-LABEL: name: s_load_u16_imm
+    ; CHECK: liveins: $sgpr0, $sgpr1
+    ; CHECK-NEXT: {{  $}}
+    ; CHECK-NEXT: [[COPY:%[0-9]+]]:sgpr_32 = COPY $sgpr1
+    ; CHECK-NEXT: [[COPY1:%[0-9]+]]:sgpr_32 = COPY $sgpr0
+    ; CHECK-NEXT: [[REG_SEQUENCE:%[0-9]+]]:sreg_64 = REG_SEQUENCE [[COPY1]], %subreg.sub0, [[COPY]], %subreg.sub1
+    ; CHECK-NEXT: [[S_LOAD_DWORD_IMM:%[0-9]+]]:sreg_32_xm0_xexec = S_LOAD_DWORD_IMM [[REG_SEQUENCE]], 16, 0 :: (load (s32))
+    ; CHECK-NEXT: [[S_AND_B32_:%[0-9]+]]:sreg_32 = S_AND_B32 [[S_LOAD_DWORD_IMM]], 65535, implicit-def $scc
+    ; CHECK-NEXT: S_ENDPGM 0, implicit [[S_AND_B32_]]
+    %1:sgpr_32 = COPY $sgpr1
+    %0:sgpr_32 = COPY $sgpr0
+    %2:sreg_64 = REG_SEQUENCE %0, %subreg.sub0, %1, %subreg.sub1
+    %3:sreg_32_xm0_xexec = S_LOAD_DWORD_IMM %2, 16, 0 :: (load (s32))
+    %4:sreg_32 = S_AND_B32 %3, 65535, implicit-def $scc
+    S_ENDPGM 0, implicit %4
+...
+
+---
+name: s_load_i8_imm
+tracksRegLiveness: true
+body: |
+  bb.0:
+    liveins: $sgpr0, $sgpr1
+    ; CHECK-LABEL: name: s_load_i8_imm
+    ; CHECK: liveins: $sgpr0, $sgpr1
+    ; CHECK-NEXT: {{  $}}
+    ; CHECK-NEXT: [[COPY:%[0-9]+]]:sgpr_32 = COPY $sgpr1
+    ; CHECK-NEXT: [[COPY1:%[0-9]+]]:sgpr_32 = COPY $sgpr0
+    ; CHECK-NEXT: [[REG_SEQUENCE:%[0-9]+]]:sreg_64 = REG_SEQUENCE [[COPY1]], %subreg.sub0, [[COPY]], %subreg.sub1
+    ; CHECK-NEXT: [[S_LOAD_DWORD_IMM:%[0-9]+]]:sreg_32_xm0_xexec = S_LOAD_DWORD_IMM [[REG_SEQUENCE]], 16, 0 :: (load (s32))
+    ; CHECK-NEXT: [[S_SEXT_I32_I8_:%[0-9]+]]:sreg_32 = S_SEXT_I32_I8 [[S_LOAD_DWORD_IMM]]
+    ; CHECK-NEXT: S_ENDPGM 0, implicit [[S_SEXT_I32_I8_]]
+    %1:sgpr_32 = COPY $sgpr1
+    %0:sgpr_32 = COPY $sgpr0
+    %2:sreg_64 = REG_SEQUENCE %0, %subreg.sub0, %1, %subreg.sub1
+    %3:sreg_32_xm0_xexec = S_LOAD_DWORD_IMM %2, 16, 0 :: (load (s32))
+    %4:sreg_32 = S_SEXT_I32_I8 %3
+    S_ENDPGM 0, implicit %4
+...
+
+---
+name: s_load_i16_imm
+tracksRegLiveness: true
+body: |
+  bb.0:
+    liveins: $sgpr0, $sgpr1
+    ; CHECK-LABEL: name: s_load_i16_imm
+    ; CHECK: liveins: $sgpr0, $sgpr1
+    ; CHECK-NEXT: {{  $}}
+    ; CHECK-NEXT: [[COPY:%[0-9]+]]:sgpr_32 = COPY $sgpr1
+    ; CHECK-NEXT: [[COPY1:%[0-9]+]]:sgpr_32 = COPY $sgpr0
+    ; CHECK-NEXT: [[REG_SEQUENCE:%[0-9]+]]:sreg_64 = REG_SEQUENCE [[COPY1]], %subreg.sub0, [[COPY]], %subreg.sub1
+    ; CHECK-NEXT: [[S_LOAD_DWORD_IMM:%[0-9]+]]:sreg_32_xm0_xexec = S_LOAD_DWORD_IMM [[REG_SEQUENCE]], 16, 0 :: (load (s32))
+    ; CHECK-NEXT: [[S_SEXT_I32_I16_:%[0-9]+]]:sreg_32 = S_SEXT_I32_I16 [[S_LOAD_DWORD_IMM]]
+    ; CHECK-NEXT: S_ENDPGM 0, implicit [[S_SEXT_I32_I16_]]
+    %1:sgpr_32 = COPY $sgpr1
+    %0:sgpr_32 = COPY $sgpr0
+    %2:sreg_64 = REG_SEQUENCE %0, %subreg.sub0, %1, %subreg.sub1
+    %3:sreg_32_xm0_xexec = S_LOAD_DWORD_IMM %2, 16, 0 :: (load (s32))
+    %4:sreg_32 = S_SEXT_I32_I16 %3
+    S_ENDPGM 0, implicit %4
+...
+
+---
+name: s_load_u8_sgpr
+tracksRegLiveness: true
+body: |
+  bb.0:
+    liveins: $sgpr0, $sgpr1, $sgpr2
+    ; CHECK-LABEL: name: s_load_u8_sgpr
+    ; CHECK: liveins: $sgpr0, $sgpr1, $sgpr2
+    ; CHECK-NEXT: {{  $}}
+    ; CHECK-NEXT: [[COPY:%[0-9]+]]:sgpr_32 = COPY $sgpr2
+    ; CHECK-NEXT: [[COPY1:%[0-9]+]]:sgpr_32 = COPY $sgpr1
+    ; CHECK-NEXT: [[COPY2:%[0-9]+]]:sgpr_32 = COPY $sgpr0
+    ; CHECK-NEXT: [[REG_SEQUENCE:%[0-9]+]]:sreg_64 = REG_SEQUENCE [[COPY2]], %subreg.sub0, [[COPY1]], %subreg.sub1
+    ; CHECK-NEXT: [[S_LOAD_DWORD_SGPR:%[0-9]+]]:sreg_32_xm0_xexec = S_LOAD_DWORD_SGPR [[REG_SEQUENCE]], [[COPY]], 0 :: (load (s32))
+    ; CHECK-NEXT: [[S_AND_B32_:%[0-9]+]]:sreg_32 = S_AND_B32 [[S_LOAD_DWORD_SGPR]], 255, implicit-def $scc
+    ; CHECK-NEXT: S_ENDPGM 0, implicit [[S_AND_B32_]]
+    %2:sgpr_32 = COPY $sgpr2
+    %1:sgpr_32 = COPY $sgpr1
+    %0:sgpr_32 = COPY $sgpr0
+    %3:sreg_64 = REG_SEQUENCE %0, %subreg.sub0, %1, %subreg.sub1
+    %4:sreg_32_xm0_xexec = S_LOAD_DWORD_SGPR %3, %2, 0 :: (load (s32))
+    %5:sreg_32 = S_AND_B32 %4, 255, implicit-def $scc
+    S_ENDPGM 0, implicit %5
+...
+
+---
+name: s_load_u16_sgpr
+tracksRegLiveness: true
+body: |
+  bb.0:
+    liveins: $sgpr0, $sgpr1, $sgpr2
+    ; CHECK-LABEL: name: s_load_u16_sgpr
+    ; CHECK: liveins: $sgpr0, $sgpr1, $sgpr2
+    ; CHECK-NEXT: {{  $}}
+    ; CHECK-NEXT: [[COPY:%[0-9]+]]:sgpr_32 = COPY $sgpr2
+    ; CHECK-NEXT: [[COPY1:%[0-9]+]]:sgpr_32 = COPY $sgpr1
+    ; CHECK-NEXT: [[COPY2:%[0-9]+]]:sgpr_32 = COPY $sgpr0
+    ; CHECK-NEXT: [[REG_SEQUENCE:%[0-9]+]]:sreg_64 = REG_SEQUENCE [[COPY2]], %subreg.sub0, [[COPY1]], %subreg.sub1
+    ; CHECK-NEXT: [[S_LOAD_DWORD_SGPR:%[0-9]+]]:sreg_32_xm0_xexec = S_LOAD_DWORD_SGPR [[REG_SEQUENCE]], [[COPY]], 0 :: (load (s32))
+    ; CHECK-NEXT: [[S_AND_B32_:%[0-9]+]]:sreg_32 = S_AND_B32 [[S_LOAD_DWORD_SGPR]], 65535, implicit-def $scc
+    ; CHECK-NEXT: S_ENDPGM 0, implicit [[S_AND_B32_]]
+    %2:sgpr_32 = COPY $sgpr2
+    %1:sgpr_32 = COPY $sgpr1
+    %0:sgpr_32 = COPY $sgpr0
+    %3:sreg_64 = REG_SEQUENCE %0, %subreg.sub0, %1, %subreg.sub1
+    %4:sreg_32_xm0_xexec = S_LOAD_DWORD_SGPR %3, %2, 0 :: (load (s32))
+    %5:sreg_32 = S_AND_B32 %4, 65535, implicit-def $scc
+    S_ENDPGM 0, implicit %5
+...
+
+---
+name: s_load_i8_sgpr
+tracksRegLiveness: true
+body: |
+  bb.0:
+    liveins: $sgpr0, $sgpr1, $sgpr2
+    ; CHECK-LABEL: name: s_load_i8_sgpr
+    ; CHECK: liveins: $sgpr0, $sgpr1, $sgpr2
+    ; CHECK-NEXT: {{  $}}
+    ; CHECK-NEXT: [[COPY:%[0-9]+]]:sgpr_32 = COPY $sgpr2
+    ; CHECK-NEXT: [[COPY1:%[0-9]+]]:sgpr_32 = COPY $sgpr1
+    ; CHECK-NEXT: [[COPY2:%[0-9]+]]:sgpr_32 = COPY $sgpr0
+    ; CHECK-NEXT: [[REG_SEQUENCE:%[0-9]+]]:sreg_64 = REG_SEQUENCE [[COPY2]], %subreg.sub0, [[COPY1]], %subreg.sub1
+    ; CHECK-NEXT: [[S_LOAD_DWORD_SGPR:%[0-9]+]]:sreg_32_xm0_xexec = S_LOAD_DWORD_SGPR [[REG_SEQUENCE]], [[COPY]], 0 :: (load (s32))
+    ; CHECK-NEXT: [[S_SEXT_I32_I8_:%[0-9]+]]:sreg_32 = S_SEXT_I32_I8 [[S_LOAD_DWORD_SGPR]]
+    ; CHECK-NEXT: S_ENDPGM 0, implicit [[S_SEXT_I32_I8_]]
+    %2:sgpr_32 = COPY $sgpr2
+    %1:sgpr_32 = COPY $sgpr1
+    %0:sgpr_32 = COPY $sgpr0
+    %3:sreg_64 = REG_SEQUENCE %0, %subreg.sub0, %1, %subreg.sub1
+    %4:sreg_32_xm0_xexec = S_LOAD_DWORD_SGPR %3, %2, 0 :: (load (s32))
+    %5:sreg_32 = S_SEXT_I32_I8 %4
+    S_ENDPGM 0, implicit %5
+...
+
+---
+name: s_load_i16_sgpr
+tracksRegLiveness: true
+body: |
+  bb.0:
+    liveins: $sgpr0, $sgpr1, $sgpr2
+    ; CHECK-LABEL: name: s_load_i16_sgpr
+    ; CHECK: liveins: $sgpr0, $sgpr1, $sgpr2
+    ; CHECK-NEXT: {{  $}}
+    ; CHECK-NEXT: [[COPY:%[0-9]+]]:sgpr_32 = COPY $sgpr2
+    ; CHECK-NEXT: [[COPY1:%[0-9]+]]:sgpr_32 = COPY $sgpr1
+    ; CHECK-NEXT: [[COPY2:%[0-9]+]]:sgpr_32 = COPY $sgpr0
+    ; CHECK-NEXT: [[REG_SEQUENCE:%[0-9]+]]:sreg_64 = REG_SEQUENCE [[COPY2]], %subreg.sub0, [[COPY1]], %subreg.sub1
+    ; CHECK-NEXT: [[S_LOAD_DWORD_SGPR:%[0-9]+]]:sreg_32_xm0_xexec = S_LOAD_DWORD_SGPR [[REG_SEQUENCE]], [[COPY]], 0 :: (load (s32))
+    ; CHECK-NEXT: [[S_SEXT_I32_I16_:%[0-9]+]]:sreg_32 = S_SEXT_I32_I16 [[S_LOAD_DWORD_SGPR]]
+    ; CHECK-NEXT: S_ENDPGM 0, implicit [[S_SEXT_I32_I16_]]
+    %2:sgpr_32 = COPY $sgpr2
+    %1:sgpr_32 = COPY $sgpr1
+    %0:sgpr_32 = COPY $sgpr0
+    %3:sreg_64 = REG_SEQUENCE %0, %subreg.sub0, %1, %subreg.sub1
+    %4:sreg_32_xm0_xexec = S_LOAD_DWORD_SGPR %3, %2, 0 :: (load (s32))
+    %5:sreg_32 = S_SEXT_I32_I16 %4
+    S_ENDPGM 0, implicit %5
+...
+
+---
+name: s_buffer_load_u8_imm
+tracksRegLiveness: true
+body: |
+  bb.0:
+    liveins: $sgpr0, $sgpr1, $sgpr2, $sgpr3
+    ; CHECK-LABEL: name: s_buffer_load_u8_imm
+    ; CHECK: liveins: $sgpr0, $sgpr1, $sgpr2, $sgpr3
+    ; CHECK-NEXT: {{  $}}
+    ; CHECK-NEXT: [[COPY:%[0-9]+]]:sgpr_32 = COPY $sgpr3
+    ; CHECK-NEXT: [[COPY1:%[0-9]+]]:sgpr_32 = COPY $sgpr2
+    ; CHECK-NEXT: [[COPY2:%[0-9]+]]:sgpr_32 = COPY $sgpr1
+    ; CHECK-NEXT: [[COPY3:%[0-9]+]]:sgpr_32 = COPY $sgpr0
+    ; CHECK-NEXT: [[REG_SEQUENCE:%[0-9]+]]:sgpr_128 = REG_SEQUENCE [[COPY3]], %subreg.sub0, [[COPY2]], %subreg.sub1, [[COPY1]], %subreg.sub2, [[COPY]], %subreg.sub3
+    ; CHECK-NEXT: [[S_BUFFER_LOAD_DWORD_IMM:%[0-9]+]]:sreg_32_xm0_xexec = S_BUFFER_LOAD_DWORD_IMM [[REG_SEQUENCE]], 16, 0 :: (load (s32))
+    ; CHECK-NEXT: [[S_AND_B32_:%[0-9]+]]:sreg_32 = S_AND_B32 [[S_BUFFER_LOAD_DWORD_IMM]], 255, implicit-def $scc
+    ; CHECK-NEXT: S_ENDPGM 0, implicit [[S_AND_B32_]]
+    %3:sgpr_32 = COPY $sgpr3
+    %2:sgpr_32 = COPY $sgpr2
+    %1:sgpr_32 = COPY $sgpr1
+    %0:sgpr_32 = COPY $sgpr0
+    %4:sgpr_128 = REG_SEQUENCE %0, %subreg.sub0, %1, %subreg.sub1, %2, %subreg.sub2, %3, %subreg.sub3
+    %5:sreg_32_xm0_xexec = S_BUFFER_LOAD_DWORD_IMM %4, 16, 0 :: (load (s32))
+    %6:sreg_32 = S_AND_B32 %5, 255, implicit-def $scc
+    S_ENDPGM 0, implicit %6
+...
+
+---
+name: s_buffer_load_u16_imm
+tracksRegLiveness: true
+body: |
+  bb.0:
+    liveins: $sgpr0, $sgpr1, $sgpr2, $sgpr3
+    ; CHECK-LABEL: name: s_buffer_load_u16_imm
+    ; CHECK: liveins: $sgpr0, $sgpr1, $sgpr2, $sgpr3
+    ; CHECK-NEXT: {{  $}}
+    ; CHECK-NEXT: [[COPY:%[0-9]+]]:sgpr_32 = COPY $sgpr3
+    ; CHECK-NEXT: [[COPY1:%[0-9]+]]:sgpr_32 = COPY $sgpr2
+    ; CHECK-NEXT: [[COPY2:%[0-9]+]]:sgpr_32 = COPY $sgpr1
+    ; CHECK-NEXT: [[COPY3:%[0-9]+]]:sgpr_32 = COPY $sgpr0
+    ; CHECK-NEXT: [[REG_SEQUENCE:%[0-9]+]]:sgpr_128 = REG_SEQUENCE [[COPY3]], %subreg.sub0, [[COPY2]], %subreg.sub1, [[COPY1]], %subreg.sub2, [[COPY]], %subreg.sub3
+    ; CHECK-NEXT: [[S_BUFFER_LOAD_DWORD_IMM:%[0-9]+]]:sreg_32_xm0_xexec = S_BUFFER_LOAD_DWORD_IMM [[REG_SEQUENCE]], 16, 0 :: (load (s32))
+    ; CHECK-NEXT: [[S_AND_B32_:%[0-9]+]]:sreg_32 = S_AND_B32 [[S_BUFFER_LOAD_DWORD_IMM]], 65535, implicit-def $scc
+    ; CHECK-NEXT: S_ENDPGM 0, implicit [[S_AND_B32_]]
+    %3:sgpr_32 = COPY $sgpr3
+    %2:sgpr_32 = COPY $sgpr2
+    %1:sgpr_32 = COPY $sgpr1
+    %0:sgpr_32 = COPY $sgpr0
+    %4:sgpr_128 = REG_SEQUENCE %0, %subreg.sub0, %1, %subreg.sub1, %2, %subreg.sub2, %3, %subreg.sub3
+    %5:sreg_32_xm0_xexec = S_BUFFER_LOAD_DWORD_IMM %4, 16, 0 :: (load (s32))
+    %6:sreg_32 = S_AND_B32 %5, 65535, implicit-def $scc
+    S_ENDPGM 0, implicit %6
+...
+
+---
+name: s_buffer_load_i8_imm
+tracksRegLiveness: true
+body: |
+  bb.0:
+    liveins: $sgpr0, $sgpr1, $sgpr2, $sgpr3
+    ; CHECK-LABEL: name: s_buffer_load_i8_imm
+    ; CHECK: liveins: $sgpr0, $sgpr1, $sgpr2, $sgpr3
+    ; CHECK-NEXT: {{  $}}
+    ; CHECK-NEXT: [[COPY:%[0-9]+]]:sgpr_32 = COPY $sgpr3
+    ; CHECK-NEXT: [[COPY1:%[0-9]+]]:sgpr_32 = COPY $sgpr2
+    ; CHECK-NEXT: [[COPY2:%[0-9]+]]:sgpr_32 = COPY $sgpr1
+    ; CHECK-NEXT: [[COPY3:%[0-9]+]]:sgpr_32 = COPY $sgpr0
+    ; CHECK-NEXT: [[REG_SEQUENCE:%[0-9]+]]:sgpr_128 = REG_SEQUENCE [[COPY3]], %subreg.sub0, [[COPY2]], %subreg.sub1, [[COPY1]], %subreg.sub2, [[COPY]], %subreg.sub3
+    ; CHECK-NEXT: [[S_BUFFER_LOAD_DWORD_IMM:%[0-9]+]]:sreg_32_xm0_xexec = S_BUFFER_LOAD_DWORD_IMM [[REG_SEQUENCE]], 16, 0 :: (load (s32))
+    ; CHECK-NEXT: [[S_SEXT_I32_I8_:%[0-9]+]]:sreg_32 = S_SEXT_I32_I8 [[S_BUFFER_LOAD_DWORD_IMM]]
+    ; CHECK-NEXT: S_ENDPGM 0, implicit [[S_SEXT_I32_I8_]]
+    %3:sgpr_32 = COPY $sgpr3
+    %2:sgpr_32 = COPY $sgpr2
+    %1:sgpr_32 = COPY $sgpr1
+    %0:sgpr_32 = COPY $sgpr0
+    %4:sgpr_128 = REG_SEQUENCE %0, %subreg.sub0, %1, %subreg.sub1, %2, %subreg.sub2, %3, %subreg.sub3
+    %5:sreg_32_xm0_xexec = S_BUFFER_LOAD_DWORD_IMM %4, 16, 0 :: (load (s32))
+    %6:sreg_32 = S_SEXT_I32_I8 %5
+    S_ENDPGM 0, implicit %6
+...
+
+---
+name: s_buffer_load_i16_imm
+tracksRegLiveness: true
+body: |
+  bb.0:
+    liveins: $sgpr0, $sgpr1, $sgpr2, $sgpr3
+    ; CHECK-LABEL: name: s_buffer_load_i16_imm
+    ; CHECK: liveins: $sgpr0, $sgpr1, $sgpr2, $sgpr3
+    ; CHECK-NEXT: {{  $}}
+    ; CHECK-NEXT: [[COPY:%[0-9]+]]:sgpr_32 = COPY $sgpr3
+    ; CHECK-NEXT: [[COPY1:%[0-9]+]]:sgpr_32 = COPY $sgpr2
+    ; CHECK-NEXT: [[COPY2:%[0-9]+]]:sgpr_32 = COPY $sgpr1
+    ; CHECK-NEXT: [[COPY3:%[0-9]+]]:sgpr_32 = COPY $sgpr0
+    ; CHECK-NEXT: [[REG_SEQUENCE:%[0-9]+]]:sgpr_128 = REG_SEQUENCE [[COPY3]], %subreg.sub0, [[COPY2]], %subreg.sub1, [[COPY1]], %subreg.sub2, [[COPY]], %subreg.sub3
+    ; CHECK-NEXT: [[S_BUFFER_LOAD_DWORD_IMM:%[0-9]+]]:sreg_32_xm0_xexec = S_BUFFER_LOAD_DWORD_IMM [[REG_SEQUENCE]], 16, 0 :: (load (s32))
+    ; CHECK-NEXT: [[S_SEXT_I32_I16_:%[0-9]+]]:sreg_32 = S_SEXT_I32_I16 [[S_BUFFER_LOAD_DWORD_IMM]]
+    ; CHECK-NEXT: S_ENDPGM 0, implicit [[S_SEXT_I32_I16_]]
+    %3:sgpr_32 = COPY $sgpr3
+    %2:sgpr_32 = COPY $sgpr2
+    %1:sgpr_32 = COPY $sgpr1
+    %0:sgpr_32 = COPY $sgpr0
+    %4:sgpr_128 = REG_SEQUENCE %0, %subreg.sub0, %1, %subreg.sub1, %2, %subreg.sub2, %3, %subreg.sub3
+    %5:sreg_32_xm0_xexec = S_BUFFER_LOAD_DWORD_IMM %4, 16, 0 :: (load (s32))
+    %6:sreg_32 = S_SEXT_I32_I16 %5
+    S_ENDPGM 0, implicit %6
+...
+
+---
+name: s_buffer_load_u8_sgpr
+tracksRegLiveness: true
+body: |
+  bb.0:
+    liveins: $sgpr0, $sgpr1, $sgpr2, $sgpr3, $sgpr4
+    ; CHECK-LABEL: name: s_buffer_load_u8_sgpr
+    ; CHECK: liveins: $sgpr0, $sgpr1, $sgpr2, $sgpr3, $sgpr4
+    ; CHECK-NEXT: {{  $}}
+    ; CHECK-NEXT: [[COPY:%[0-9]+]]:sgpr_32 = COPY $sgpr4
+    ; CHECK-NEXT: [[COPY1:%[0-9]+]]:sgpr_32 = COPY $sgpr3
+    ; CHECK-NEXT: [[COPY2:%[0-9]+]]:sgpr_32 = COPY $sgpr2
+    ; CHECK-NEXT: [[COPY3:%[0-9]+]]:sgpr_32 = COPY $sgpr1
+    ; CHECK-NEXT: [[COPY4:%[0-9]+]]:sgpr_32 = COPY $sgpr0
+    ; CHECK-NEXT: [[REG_SEQUENCE:%[0-9]+]]:sgpr_128 = REG_SEQUENCE [[COPY4]], %subreg.sub0, [[COPY3]], %subreg.sub1, [[COPY2]], %subreg.sub2, [[COPY1]], %subreg.sub3
+    ; CHECK-NEXT: [[S_BUFFER_LOAD_DWORD_SGPR:%[0-9]+]]:sreg_32_xm0_xexec = S_BUFFER_LOAD_DWORD_SGPR [[REG_SEQUENCE]], [[COPY]], 0 :: (load (s32))
+    ; CHECK-NEXT: [[S_AND_B32_:%[0-9]+]]:sreg_32 = S_AND_B32 [[S_BUFFER_LOAD_DWORD_SGPR]], 255, implicit-def $scc
+    ; CHECK-NEXT: S_ENDPGM 0, implicit [[S_AND_B32_]]
+    %4:sgpr_32 = COPY $sgpr4
+    %3:sgpr_32 = COPY $sgpr3
+    %2:sgpr_32 = COPY $sgpr2
+    %1:sgpr_32 = COPY $sgpr1
+    %0:sgpr_32 = COPY $sgpr0
+    %5:sgpr_128 = REG_SEQUENCE %0, %subreg.sub0, %1, %subreg.sub1, %2, %subreg.sub2, %3, %subreg.sub3
+    %6:sreg_32_xm0_xexec = S_BUFFER_LOAD_DWORD_SGPR %5, %4, 0 :: (load (s32))
+    %7:sreg_32 = S_AND_B32 %6, 255, implicit-def $scc
+    S_ENDPGM 0, implicit %7
+...
+
+---
+name: s_buffer_load_u16_sgpr
+tracksRegLiveness: true
+body: |
+  bb.0:
+    liveins: $sgpr0, $sgpr1, $sgpr2, $sgpr3, $sgpr4
+    ; CHECK-LABEL: name: s_buffer_load_u16_sgpr
+    ; CHECK: liveins: $sgpr0, $sgpr1, $sgpr2, $sgpr3, $sgpr4
+    ; CHECK-NEXT: {{  $}}
+    ; CHECK-NEXT: [[COPY:%[0-9]+]]:sgpr_32 = COPY $sgpr4
+    ; CHECK-NEXT: [[COPY1:%[0-9]+]]:sgpr_32 = COPY $sgpr3
+    ; CHECK-NEXT: [[COPY2:%[0-9]+]]:sgpr_32 = COPY $sgpr2
+    ; CHECK-NEXT: [[COPY3:%[0-9]+]]:sgpr_32 = COPY $sgpr1
+    ; CHECK-NEXT: [[COPY4:%[0-9]+]]:sgpr_32 = COPY $sgpr0
+    ; CHECK-NEXT: [[REG_SEQUENCE:%[0-9]+]]:sgpr_128 = REG_SEQUENCE [[COPY4]], %subreg.sub0, [[COPY3]], %subreg.sub1, [[COPY2]], %subreg.sub2, [[COPY1]], %subreg.sub3
+    ; CHECK-NEXT: [[S_BUFFER_LOAD_DWORD_SGPR:%[0-9]+]]:sreg_32_xm0_xexec = S_BUFFER_LOAD_DWORD_SGPR [[REG_SEQUENCE]], [[COPY]], 0 :: (load (s32))
+    ; CHECK-NEXT: [[S_AND_B32_:%[0-9]+]]:sreg_32 = S_AND_B32 [[S_BUFFER_LOAD_DWORD_SGPR]], 65535, implicit-def $scc
+    ; CHECK-NEXT: S_ENDPGM 0, implicit [[S_AND_B32_]]
+    %4:sgpr_32 = COPY $sgpr4
+    %3:sgpr_32 = COPY $sgpr3
+    %2:sgpr_32 = COPY $sgpr2
+    %1:sgpr_32 = COPY $sgpr1
+    %0:sgpr_32 = COPY $sgpr0
+    %5:sgpr_128 = REG_SEQUENCE %0, %subreg.sub0, %1, %subreg.sub1, %2, %subreg.sub2, %3, %subreg.sub3
+    %6:sreg_32_xm0_xexec = S_BUFFER_LOAD_DWORD_SGPR %5, %4, 0 :: (load (s32))
+    %7:sreg_32 = S_AND_B32 %6, 65535, implicit-def $scc
+    S_ENDPGM 0, implicit %7
+...
+
+---
+name: s_buffer_load_i8_sgpr
+tracksRegLiveness: true
+body: |
+  bb.0:
+    liveins: $sgpr0, $sgpr1, $sgpr2, $sgpr3, $sgpr4
+    ; CHECK-LABEL: name: s_buffer_load_i8_sgpr
+    ; CHECK: liveins: $sgpr0, $sgpr1, $sgpr2, $sgpr3, $sgpr4
+    ; CHECK-NEXT: {{  $}}
+    ; CHECK-NEXT: [[COPY:%[0-9]+]]:sgpr_32 = COPY $sgpr4
+    ; CHECK-NEXT: [[COPY1:%[0-9]+]]:sgpr_32 = COPY $sgpr3
+    ; CHECK-NEXT: [[COPY2:%[0-9]+]]:sgpr_32 = COPY $sgpr2
+    ; CHECK-NEXT: [[COPY3:%[0-9]+]]:sgpr_32 = COPY $sgpr1
+    ; CHECK-NEXT: [[COPY4:%[0-9]+]]:sgpr_32 = COPY $sgpr0
+    ; CHECK-NEXT: [[REG_SEQUENCE:%[0-9]+]]:sgpr_128 = REG_SEQUENCE [[COPY4]], %subreg.sub0, [[COPY3]], %subreg.sub1, [[COPY2]], %subreg.sub2, [[COPY1]], %subreg.sub3
+    ; CHECK-NEXT: [[S_BUFFER_LOAD_DWORD_SGPR:%[0-9]+]]:sreg_32_xm0_xexec = S_BUFFER_LOAD_DWORD_SGPR [[REG_SEQUENCE]], [[COPY]], 0 :: (load (s32))
+    ; CHECK-NEXT: [[S_SEXT_I32_I8_:%[0-9]+]]:sreg_32 = S_SEXT_I32_I8 [[S_BUFFER_LOAD_DWORD_SGPR]]
+    ; CHECK-NEXT: S_ENDPGM 0, implicit [[S_SEXT_I32_I8_]]
+    %4:sgpr_32 = COPY $sgpr4
+    %3:sgpr_32 = COPY $sgpr3
+    %2:sgpr_32 = COPY $sgpr2
+    %1:sgpr_32 = COPY $sgpr1
+    %0:sgpr_32 = COPY $sgpr0
+    %5:sgpr_128 = REG_SEQUENCE %0, %subreg.sub0, %1, %subreg.sub1, %2, %subreg.sub2, %3, %subreg.sub3
+    %6:sreg_32_xm0_xexec = S_BUFFER_LOAD_DWORD_SGPR %5, %4, 0 :: (load (s32))
+    %7:sreg_32 = S_SEXT_I32_I8 %6
+    S_ENDPGM 0, implicit %7
+...
+
+---
+name: s_buffer_load_i16_sgpr
+tracksRegLiveness: true
+body: |
+  bb.0:
+    liveins: $sgpr0, $sgpr1, $sgpr2, $sgpr3, $sgpr4
+    ; CHECK-LABEL: name: s_buffer_load_i16_sgpr
+    ; CHECK: liveins: $sgpr0, $sgpr1, $sgpr2, $sgpr3, $sgpr4
+    ; CHECK-NEXT: {{  $}}
+    ; CHECK-NEXT: [[COPY:%[0-9]+]]:sgpr_32 = COPY $sgpr4
+    ; CHECK-NEXT: [[COPY1:%[0-9]+]]:sgpr_32 = COPY $sgpr3
+    ; CHECK-NEXT: [[COPY2:%[0-9]+]]:sgpr_32 = COPY $sgpr2
+    ; CHECK-NEXT: [[COPY3:%[0-9]+]]:sgpr_32 = COPY $sgpr1
+    ; CHECK-NEXT: [[COPY4:%[0-9]+]]:sgpr_32 = COPY $sgpr0
+    ; CHECK-NEXT: [[REG_SEQUENCE:%[0-9]+]]:sgpr_128 = REG_SEQUENCE [[COPY4]], %subreg.sub0, [[COPY3]], %subreg.sub1, [[COPY2]], %subreg.sub2, [[COPY1]], %subreg.sub3
+    ; CHECK-NEXT: [[S_BUFFER_LOAD_DWORD_SGPR:%[0-9]+]]:sreg_32_xm0_xexec = S_BUFFER_LOAD_DWORD_SGPR [[REG_SEQUENCE]], [[COPY]], 0 :: (load (s32))
+    ; CHECK-NEXT: [[S_SEXT_I32_I16_:%[0-9]+]]:sreg_32 = S_SEXT_I32_I16 [[S_BUFFER_LOAD_DWORD_SGPR]]
+    ; CHECK-NEXT: S_ENDPGM 0, implicit [[S_SEXT_I32_I16_]]
+    %4:sgpr_32 = COPY $sgpr4
+    %3:sgpr_32 = COPY $sgpr3
+    %2:sgpr_32 = COPY $sgpr2
+    %1:sgpr_32 = COPY $sgpr1
+    %0:sgpr_32 = COPY $sgpr0
+    %5:sgpr_128 = REG_SEQUENCE %0, %subreg.sub0, %1, %subreg.sub1, %2, %subreg.sub2, %3, %subreg.sub3
+    %6:sreg_32_xm0_xexec = S_BUFFER_LOAD_DWORD_SGPR %5, %4, 0 :: (load (s32))
+    %7:sreg_32 = S_SEXT_I32_I16 %6
+    S_ENDPGM 0, implicit %7
+...
+
+---
+name: s_buffer_load_u8_sgpr_imm
+tracksRegLiveness: true
+body: |
+  bb.0:
+    liveins: $sgpr0, $sgpr1, $sgpr2, $sgpr3, $sgpr4
+    ; CHECK-LABEL: name: s_buffer_load_u8_sgpr_imm
+    ; CHECK: liveins: $sgpr0, $sgpr1, $sgpr2, $sgpr3, $sgpr4
+    ; CHECK-NEXT: {{  $}}
+    ; CHECK-NEXT: [[COPY:%[0-9]+]]:sgpr_32 = COPY $sgpr4
+    ; CHECK-NEXT: [[COPY1:%[0-9]+]]:sgpr_32 = COPY $sgpr3
+    ; CHECK-NEXT: [[COPY2:%[0-9]+]]:sgpr_32 = COPY $sgpr2
+    ; CHECK-NEXT: [[COPY3:%[0-9]+]]:sgpr_32 = COPY $sgpr1
+    ; CHECK-NEXT: [[COPY4:%[0-9]+]]:sgpr_32 = COPY $sgpr0
+    ; CHECK-NEXT: [[REG_SEQUENCE:%[0-9]+]]:sgpr_128 = REG_SEQUENCE [[COPY4]], %subreg.sub0, [[COPY3]], %subreg.sub1, [[COPY2]], %subreg.sub2, [[COPY1]], %subreg.sub3
+    ; CHECK-NEXT: [[S_BUFFER_LOAD_DWORD_SGPR_IMM:%[0-9]+]]:sreg_32_xm0_xexec = S_BUFFER_LOAD_DWORD_SGPR_IMM [[REG_SEQUENCE]], [[COPY]], 16, 0 :: (load (s32))
+    ; CHECK-NEXT: [[S_AND_B32_:%[0-9]+]]:sreg_32 = S_AND_B32 [[S_BUFFER_LOAD_DWORD_SGPR_IMM]], 255, implicit-def $scc
+    ; CHECK-NEXT: S_ENDPGM 0, implicit [[S_AND_B32_]]
+    %4:sgpr_32 = COPY $sgpr4
+    %3:sgpr_32 = COPY $sgpr3
+    %2:sgpr_32 = COPY $sgpr2
+    %1:sgpr_32 = COPY $sgpr1
+    %0:sgpr_32 = COPY $sgpr0
+    %5:sgpr_128 = REG_SEQUENCE %0, %subreg.sub0, %1, %subreg.sub1, %2, %subreg.sub2, %3, %subreg.sub3
+    %6:sreg_32_xm0_xexec = S_BUFFER_LOAD_DWORD_SGPR_IMM %5, %4, 16, 0 :: (load (s32))
+    %7:sreg_32 = S_AND_B32 %6, 255, implicit-def $scc
+    S_ENDPGM 0, implicit %7
+...
+
+---
+name: s_buffer_load_u16_sgpr_imm
+tracksRegLiveness: true
+body: |
+  bb.0:
+    liveins: $sgpr0, $sgpr1, $sgpr2, $sgpr3, $sgpr4
+    ; CHECK-LABEL: name: s_buffer_load_u16_sgpr_imm
+    ; CHECK: liveins: $sgpr0, $sgpr1, $sgpr2, $sgpr3, $sgpr4
+    ; CHECK-NEXT: {{  $}}
+    ; CHECK-NEXT: [[COPY:%[0-9]+]]:sgpr_32 = COPY $sgpr4
+    ; CHECK-NEXT: [[COPY1:%[0-9]+]]:sgpr_32 = COPY $sgpr3
+    ; CHECK-NEXT: [[COPY2:%[0-9]+]]:sgpr_32 = COPY $sgpr2
+    ; CHECK-NEXT: [[COPY3:%[0-9]+]]:sgpr_32 = COPY $sgpr1
+    ; CHECK-NEXT: [[COPY4:%[0-9]+]]:sgpr_32 = COPY $sgpr0
+    ; CHECK-NEXT: [[REG_SEQUENCE:%[0-9]+]]:sgpr_128 = REG_SEQUENCE [[COPY4]], %subreg.sub0, [[COPY3]], %subreg.sub1, [[COPY2]], %subreg.sub2, [[COPY1]], %subreg.sub3
+    ; CHECK-NEXT: [[S_BUFFER_LOAD_DWORD_SGPR_IMM:%[0-9]+]]:sreg_32_xm0_xexec = S_BUFFER_LOAD_DWORD_SGPR_IMM [[REG_SEQUENCE]], [[COPY]], 16, 0 :: (load (s32))
+    ; CHECK-NEXT: [[S_AND_B32_:%[0-9]+]]:sreg_32 = S_AND_B32 [[S_BUFFER_LOAD_DWORD_SGPR_IMM]], 65535, implicit-def $scc
+    ; CHECK-NEXT: S_ENDPGM 0, implicit [[S_AND_B32_]]
+    %4:sgpr_32 = COPY $sgpr4
+    %3:sgpr_32 = COPY $sgpr3
+    %2:sgpr_32 = COPY $sgpr2
+    %1:sgpr_32 = COPY $sgpr1
+    %0:sgpr_32 = COPY $sgpr0
+    %5:sgpr_128 = REG_SEQUENCE %0, %subreg.sub0, %1, %subreg.sub1, %2, %subreg.sub2, %3, %subreg.sub3
+    %6:sreg_32_xm0_xexec = S_BUFFER_LOAD_DWORD_SGPR_IMM %5, %4, 16, 0 :: (load (s32))
+    %7:sreg_32 = S_AND_B32 %6, 65535, implicit-def $scc
+    S_ENDPGM 0, implicit %7
+...
+
+---
+name: s_buffer_load_i8_sgpr_imm
+tracksRegLiveness: true
+body: |
+  bb.0:
+    liveins: $sgpr0, $sgpr1, $sgpr2, $sgpr3, $sgpr4
+    ; CHECK-LABEL: name: s_buffer_load_i8_sgpr_imm
+    ; CHECK: liveins: $sgpr0, $sgpr1, $sgpr2, $sgpr3, $sgpr4
+    ; CHECK-NEXT: {{  $}}
+    ; CHECK-NEXT: [[COPY:%[0-9]+]]:sgpr_32 = COPY $sgpr4
+    ; CHECK-NEXT: [[COPY1:%[0-9]+]]:sgpr_32 = COPY $sgpr3
+    ; CHECK-NEXT: [[COPY2:%[0-9]+]]:sgpr_32 = COPY $sgpr2
+    ; CHECK-NEXT: [[COPY3:%[0-9]+]]:sgpr_32 = COPY $sgpr1
+    ; CHECK-NEXT: [[COPY4:%[0-9]+]]:sgpr_32 = COPY $sgpr0
+    ; CHECK-NEXT: [[REG_SEQUENCE:%[0-9]+]]:sgpr_128 = REG_SEQUENCE [[COPY4]], %subreg.sub0, [[COPY3]], %subreg.sub1, [[COPY2]], %subreg.sub2, [[COPY1]], %subreg.sub3
+    ; CHECK-NEXT: [[S_BUFFER_LOAD_DWORD_SGPR_IMM:%[0-9]+]]:sreg_32_xm0_xexec = S_BUFFER_LOAD_DWORD_SGPR_IMM [[REG_SEQUENCE]], [[COPY]], 16, 0 :: (load (s32))
+    ; CHECK-NEXT: [[S_SEXT_I32_I8_:%[0-9]+]]:sreg_32 = S_SEXT_I32_I8 [[S_BUFFER_LOAD_DWORD_SGPR_IMM]]
+    ; CHECK-NEXT: S_ENDPGM 0, implicit [[S_SEXT_I32_I8_]]
+    %4:sgpr_32 = COPY $sgpr4
+    %3:sgpr_32 = COPY $sgpr3
+    %2:sgpr_32 = COPY $sgpr2
+    %1:sgpr_32 = COPY $sgpr1
+    %0:sgpr_32 = COPY $sgpr0
+    %5:sgpr_128 = REG_SEQUENCE %0, %subreg.sub0, %1, %subreg.sub1, %2, %subreg.sub2, %3, %subreg.sub3
+    %6:sreg_32_xm0_xexec = S_BUFFER_LOAD_DWORD_SGPR_IMM %5, %4, 16, 0 :: (load (s32))
+    %7:sreg_32 = S_SEXT_I32_I8 %6
+    S_ENDPGM 0, implicit %7
+...
+
+---
+name: s_buffer_load_i16_sgpr_imm
+tracksRegLiveness: true
+body: |
+  bb.0:
+    liveins: $sgpr0, $sgpr1, $sgpr2, $sgpr3, $sgpr4
+    ; CHECK-LABEL: name: s_buffer_load_i16_sgpr_imm
+    ; CHECK: liveins: $sgpr0, $sgpr1, $sgpr2, $sgpr3, $sgpr4
+    ; CHECK-NEXT: {{  $}}
+    ; CHECK-NEXT: [[COPY:%[0-9]+]]:sgpr_32 = COPY $sgpr4
+    ; CHECK-NEXT: [[COPY1:%[0-9]+]]:sgpr_32 = COPY $sgpr3
+    ; CHECK-NEXT: [[COPY2:%[0-9]+]]:sgpr_32 = COPY $sgpr2
+    ; CHECK-NEXT: [[COPY3:%[0-9]+]]:sgpr_32 = COPY $sgpr1
+    ; CHECK-NEXT: [[COPY4:%[0-9]+]]:sgpr_32 = COPY $sgpr0
+    ; CHECK-NEXT: [[REG_SEQUENCE:%[0-9]+]]:sgpr_128 = REG_SEQUENCE [[COPY4]], %subreg.sub0, [[COPY3]], %subreg.sub1, [[COPY2]], %subreg.sub2, [[COPY1]], %subreg.sub3
+    ; CHECK-NEXT: [[S_BUFFER_LOAD_DWORD_SGPR_IMM:%[0-9]+]]:sreg_32_xm0_xexec = S_BUFFER_LOAD_DWORD_SGPR_IMM [[REG_SEQUENCE]], [[COPY]], 16, 0 :: (load (s32))
+    ; CHECK-NEXT: [[S_SEXT_I32_I16_:%[0-9]+]]:sreg_32 = S_SEXT_I32_I16 [[S_BUFFER_LOAD_DWORD_SGPR_IMM]]
+    ; CHECK-NEXT: S_ENDPGM 0, implicit [[S_SEXT_I32_I16_]]
+    %4:sgpr_32 = COPY $sgpr4
+    %3:sgpr_32 = COPY $sgpr3
+    %2:sgpr_32 = COPY $sgpr2
+    %1:sgpr_32 = COPY $sgpr1
+    %0:sgpr_32 = COPY $sgpr0
+    %5:sgpr_128 = REG_SEQUENCE %0, %subreg.sub0, %1, %subreg.sub1, %2, %subreg.sub2, %3, %subreg.sub3
+    %6:sreg_32_xm0_xexec = S_BUFFER_LOAD_DWORD_SGPR_IMM %5, %4, 16, 0 :: (load (s32))
+    %7:sreg_32 = S_SEXT_I32_I16 %6
+    S_ENDPGM 0, implicit %7
+...
+
+---
+name: no_opt_wrong_mask
+tracksRegLiveness: true
+body: |
+  bb.0:
+    liveins: $sgpr0, $sgpr1
+    ; CHECK-LABEL: name: no_opt_wrong_mask
+    ; CHECK: liveins: $sgpr0, $sgpr1
+    ; CHECK-NEXT: {{  $}}
+    ; CHECK-NEXT: [[COPY:%[0-9]+]]:sgpr_32 = COPY $sgpr1
+    ; CHECK-NEXT: [[COPY1:%[0-9]+]]:sgpr_32 = COPY $sgpr0
+    ; CHECK-NEXT: [[REG_SEQUENCE:%[0-9]+]]:sreg_64 = REG_SEQUENCE [[COPY1]], %subreg.sub0, [[COPY]], %subreg.sub1
+    ; CHECK-NEXT: [[S_LOAD_DWORD_IMM:%[0-9]+]]:sreg_32_xm0_xexec = S_LOAD_DWORD_IMM [[REG_SEQUENCE]], 16, 0 :: (load (s32))
+    ; CHECK-NEXT: [[S_AND_B32_:%[0-9]+]]:sreg_32 = S_AND_B32 [[S_LOAD_DWORD_IMM]], 127, implicit-def $scc
+    ; CHECK-NEXT: S_ENDPGM 0, implicit [[S_AND_B32_]]
+    %1:sgpr_32 = COPY $sgpr1
+    %0:sgpr_32 = COPY $sgpr0
+    %2:sreg_64 = REG_SEQUENCE %0, %subreg.sub0, %1, %subreg.sub1
+    %3:sreg_32_xm0_xexec = S_LOAD_DWORD_IMM %2, 16, 0 :: (load (s32))
+    %4:sreg_32 = S_AND_B32 %3, 127, implicit-def $scc
+    S_ENDPGM 0, implicit %4
+...

>From c33f902e92d64975b4ad89b0c199dcca206cd722 Mon Sep 17 00:00:00 2001
From: John Lu <John.Lu at amd.com>
Date: Wed, 26 Aug 2026 14:42:56 -0500
Subject: [PATCH 2/2] Convert dword load + extension into subword load

Signed-off-by: John Lu <John.Lu at amd.com>
---
 .../Target/AMDGPU/SILoadStoreOptimizer.cpp    | 142 +++++++++++++++++-
 .../atomic_optimizations_global_pointer.ll    |  32 ++--
 llvm/test/CodeGen/AMDGPU/max.ll               |  26 ++--
 llvm/test/CodeGen/AMDGPU/min.ll               |  26 ++--
 .../AMDGPU/reassoc-mul-add-1-to-mad.ll        |  92 ++++++------
 .../CodeGen/AMDGPU/scalar-subword-loads.ll    |  38 ++---
 .../AMDGPU/si-load-opt-scalar-subword.mir     | 106 ++++++-------
 7 files changed, 278 insertions(+), 184 deletions(-)

diff --git a/llvm/lib/Target/AMDGPU/SILoadStoreOptimizer.cpp b/llvm/lib/Target/AMDGPU/SILoadStoreOptimizer.cpp
index 555bb002a2521..18d0f622f5fb1 100644
--- a/llvm/lib/Target/AMDGPU/SILoadStoreOptimizer.cpp
+++ b/llvm/lib/Target/AMDGPU/SILoadStoreOptimizer.cpp
@@ -6,7 +6,14 @@
 //
 //===----------------------------------------------------------------------===//
 //
-// This pass tries to fuse DS instructions with close by immediate offsets.
+// This pass tries to:
+// 1. fuse DS instructions with close by immediate offsets.
+// 2. fuse dword load + sign/zero extension into a subword load.
+// Optimization #1 (fusion) must be done before optimization #2 (subword loads).
+// The additional sign/zero-extension functionality in subword loads prevents
+// them from being fused with adjacent DS instructions.
+//
+// Optimization #1, fuse DS instructions
 // This will fuse operations such as
 //  ds_read_b32 v0, v2 offset:16
 //  ds_read_b32 v1, v2 offset:32
@@ -55,6 +62,17 @@
 //   offsets, but are close enough to fit in the 8 bits, we can add to the base
 //   pointer and use the new reduced offsets.
 //
+// Optimization #2, fuse dword load + extension into subword load
+// This will transform patterns like:
+//   s_load_dword s0, ...
+//   s_and_b32 s1, s0, 0xff
+// into:
+//   s_load_u8 s1, ...
+//
+// The optimization recognizes dword loads followed by either zero-extension
+// (via AND with 0xff or 0xffff) or sign-extension (via S_SEXT_I32_I8/I16)
+// and replaces both instructions with a single subword load instruction.
+// This is only available on GFX12+ via the hasScalarSubwordLoads() feature.
 //===----------------------------------------------------------------------===//
 
 #include "SILoadStoreOptimizer.h"
@@ -313,6 +331,8 @@ class SILoadStoreOptimizer {
                                      bool &OptimizeListAgain);
   bool optimizeBlock(std::list<std::list<CombineInfo> > &MergeableInsts);
 
+  bool optimizeDwordLoadExtension(MachineBasicBlock &MBB);
+
 public:
   SILoadStoreOptimizer(AliasAnalysis *AA) : AA(AA) {}
   bool run(MachineFunction &MF);
@@ -2861,6 +2881,123 @@ bool SILoadStoreOptimizerLegacy::runOnMachineFunction(MachineFunction &MF) {
       .run(MF);
 }
 
+enum SubwordExtensionType {
+  EXT_U8 = 0,
+  EXT_U16 = 1,
+  EXT_I8 = 2,
+  EXT_I16 = 3,
+  EXT_NONE = -1
+};
+
+// Determine the extension type based on the use instruction.
+// Returns EXT_NONE if the use pattern doesn't match a subword load.
+static SubwordExtensionType getExtensionType(const MachineInstr *UseInst) {
+  switch (UseInst->getOpcode()) {
+  case AMDGPU::S_AND_B32: {
+    // Check if it's masking with 0xff or 0xffff
+    const MachineOperand &MaskOp = UseInst->getOperand(2);
+    if (!MaskOp.isImm())
+      return EXT_NONE;
+
+    int64_t Mask = MaskOp.getImm();
+    if (Mask == 0xff)
+      return EXT_U8;
+    if (Mask == 0xffff)
+      return EXT_U16;
+    return EXT_NONE;
+  }
+  case AMDGPU::S_SEXT_I32_I8:
+    return EXT_I8;
+  case AMDGPU::S_SEXT_I32_I16:
+    return EXT_I16;
+  }
+  return EXT_NONE;
+}
+
+// Optimize a dword load + mask/extend by fusing the two instructions
+// into a subword load instruction.
+//
+// Patterns:
+//   s_load_dword + s_and_b32 ... 0xff    -> s_load_u8
+//   s_load_dword + s_and_b32 ... 0xffff  -> s_load_u16
+//   s_load_dword + s_sext_i32_i8         -> s_load_i8
+//   s_load_dword + s_sext_i32_i16        -> s_load_i16
+//
+// Same patterns for s_buffer_load_dword -> s_buffer_load_u8/i8/u16/i16
+bool SILoadStoreOptimizer::optimizeDwordLoadExtension(MachineBasicBlock &MBB) {
+  if (!STM->hasScalarSubwordLoads())
+    return false;
+
+  // Opcode tables for subword loads indexed by SubwordExtensionType
+  static const unsigned S_LOAD_IMM_TABLE[] = {
+    AMDGPU::S_LOAD_U8_IMM, AMDGPU::S_LOAD_U16_IMM,
+    AMDGPU::S_LOAD_I8_IMM, AMDGPU::S_LOAD_I16_IMM
+  };
+  static const unsigned S_LOAD_SGPR_TABLE[] = {
+    AMDGPU::S_LOAD_U8_SGPR, AMDGPU::S_LOAD_U16_SGPR,
+    AMDGPU::S_LOAD_I8_SGPR, AMDGPU::S_LOAD_I16_SGPR
+  };
+  static const unsigned S_BUFFER_LOAD_IMM_TABLE[] = {
+    AMDGPU::S_BUFFER_LOAD_U8_IMM, AMDGPU::S_BUFFER_LOAD_U16_IMM,
+    AMDGPU::S_BUFFER_LOAD_I8_IMM, AMDGPU::S_BUFFER_LOAD_I16_IMM
+  };
+  static const unsigned S_BUFFER_LOAD_SGPR_TABLE[] = {
+    AMDGPU::S_BUFFER_LOAD_U8_SGPR, AMDGPU::S_BUFFER_LOAD_U16_SGPR,
+    AMDGPU::S_BUFFER_LOAD_I8_SGPR, AMDGPU::S_BUFFER_LOAD_I16_SGPR
+  };
+  static const unsigned S_BUFFER_LOAD_SGPR_IMM_TABLE[] = {
+    AMDGPU::S_BUFFER_LOAD_U8_SGPR_IMM, AMDGPU::S_BUFFER_LOAD_U16_SGPR_IMM,
+    AMDGPU::S_BUFFER_LOAD_I8_SGPR_IMM, AMDGPU::S_BUFFER_LOAD_I16_SGPR_IMM
+  };
+
+  // Map from dword load opcode to subword load opcode table
+  static const DenseMap<unsigned, const unsigned *> DwordLoadToSubwordOpcodes =
+      {{AMDGPU::S_LOAD_DWORD_IMM, S_LOAD_IMM_TABLE},
+       {AMDGPU::S_LOAD_DWORD_SGPR, S_LOAD_SGPR_TABLE},
+       {AMDGPU::S_BUFFER_LOAD_DWORD_IMM, S_BUFFER_LOAD_IMM_TABLE},
+       {AMDGPU::S_BUFFER_LOAD_DWORD_SGPR, S_BUFFER_LOAD_SGPR_TABLE},
+       {AMDGPU::S_BUFFER_LOAD_DWORD_SGPR_IMM, S_BUFFER_LOAD_SGPR_IMM_TABLE}};
+
+  bool Modified = false;
+
+  for (MachineBasicBlock::iterator I = MBB.begin(), E = MBB.end(); I != E;
+       ++I) {
+    MachineInstr &MI = *I;
+
+    // Find the subword load opcodes for this dword load opcode
+    auto It = DwordLoadToSubwordOpcodes.find(MI.getOpcode());
+    if (It == DwordLoadToSubwordOpcodes.end())
+      continue;
+    const unsigned *SubwordOpcodes =
+        It->second; // Array indexed by SubwordExtensionType
+
+    Register LoadReg = MI.getOperand(0).getReg();
+    MachineInstr *UseInst = MRI->getOneNonDBGUser(LoadReg);
+    if (!UseInst)
+      continue;
+
+    SubwordExtensionType ExtType = getExtensionType(UseInst);
+    if (ExtType == EXT_NONE)
+      continue;
+
+    assert(UseInst->getOperand(1).isReg() &&
+           UseInst->getOperand(1).getReg() == LoadReg &&
+           "Extension source operand should be the load result");
+
+    unsigned NewOpcode = SubwordOpcodes[ExtType];
+    Register UseDestReg = UseInst->getOperand(0).getReg();
+
+    MI.setDesc(TII->get(NewOpcode));
+    MI.getOperand(0).setReg(UseDestReg);
+
+    UseInst->eraseFromParent();
+
+    Modified = true;
+  }
+
+  return Modified;
+}
+
 bool SILoadStoreOptimizer::run(MachineFunction &MF) {
   this->MF = &MF;
   STM = &MF.getSubtarget<GCNSubtarget>();
@@ -2901,6 +3038,9 @@ bool SILoadStoreOptimizer::run(MachineFunction &MF) {
       } while (OptimizeAgain);
     }
 
+    // Optimize subword loads after fusion has been completed
+    Modified |= optimizeDwordLoadExtension(MBB);
+
     Visited.clear();
     AnchorList.clear();
   }
diff --git a/llvm/test/CodeGen/AMDGPU/atomic_optimizations_global_pointer.ll b/llvm/test/CodeGen/AMDGPU/atomic_optimizations_global_pointer.ll
index 3e3b5ac65eabc..29c5fbc9b5626 100644
--- a/llvm/test/CodeGen/AMDGPU/atomic_optimizations_global_pointer.ll
+++ b/llvm/test/CodeGen/AMDGPU/atomic_optimizations_global_pointer.ll
@@ -11639,7 +11639,7 @@ define amdgpu_kernel void @uniform_xchg_i8(ptr addrspace(1) %result, ptr addrspa
 ; GFX1264:       ; %bb.0:
 ; GFX1264-NEXT:    s_clause 0x1
 ; GFX1264-NEXT:    s_load_b128 s[0:3], s[4:5], 0x24
-; GFX1264-NEXT:    s_load_b32 s6, s[4:5], 0x34
+; GFX1264-NEXT:    s_load_u8 s6, s[4:5], 0x34
 ; GFX1264-NEXT:    s_mov_b64 s[8:9], 0
 ; GFX1264-NEXT:    s_wait_kmcnt 0x0
 ; GFX1264-NEXT:    s_and_b32 s4, s2, -4
@@ -11647,7 +11647,7 @@ define amdgpu_kernel void @uniform_xchg_i8(ptr addrspace(1) %result, ptr addrspa
 ; GFX1264-NEXT:    s_and_b32 s2, s2, 3
 ; GFX1264-NEXT:    s_load_b32 s5, s[4:5], 0x0
 ; GFX1264-NEXT:    s_lshl_b32 s2, s2, 3
-; GFX1264-NEXT:    s_and_b32 s6, s6, 0xff
+; GFX1264-NEXT:    s_delay_alu instid0(SALU_CYCLE_1)
 ; GFX1264-NEXT:    s_lshl_b32 s7, 0xff, s2
 ; GFX1264-NEXT:    s_lshl_b32 s11, s6, s2
 ; GFX1264-NEXT:    s_not_b32 s10, s7
@@ -11682,7 +11682,7 @@ define amdgpu_kernel void @uniform_xchg_i8(ptr addrspace(1) %result, ptr addrspa
 ; GFX1232:       ; %bb.0:
 ; GFX1232-NEXT:    s_clause 0x1
 ; GFX1232-NEXT:    s_load_b128 s[0:3], s[4:5], 0x24
-; GFX1232-NEXT:    s_load_b32 s6, s[4:5], 0x34
+; GFX1232-NEXT:    s_load_u8 s6, s[4:5], 0x34
 ; GFX1232-NEXT:    s_mov_b32 s9, 0
 ; GFX1232-NEXT:    s_wait_kmcnt 0x0
 ; GFX1232-NEXT:    s_and_b32 s4, s2, -4
@@ -11690,7 +11690,7 @@ define amdgpu_kernel void @uniform_xchg_i8(ptr addrspace(1) %result, ptr addrspa
 ; GFX1232-NEXT:    s_and_b32 s2, s2, 3
 ; GFX1232-NEXT:    s_load_b32 s5, s[4:5], 0x0
 ; GFX1232-NEXT:    s_lshl_b32 s2, s2, 3
-; GFX1232-NEXT:    s_and_b32 s6, s6, 0xff
+; GFX1232-NEXT:    s_delay_alu instid0(SALU_CYCLE_1)
 ; GFX1232-NEXT:    s_lshl_b32 s7, 0xff, s2
 ; GFX1232-NEXT:    s_lshl_b32 s10, s6, s2
 ; GFX1232-NEXT:    s_not_b32 s8, s7
@@ -11724,14 +11724,14 @@ define amdgpu_kernel void @uniform_xchg_i8(ptr addrspace(1) %result, ptr addrspa
 ; GFX1364:       ; %bb.0:
 ; GFX1364-NEXT:    s_clause 0x1
 ; GFX1364-NEXT:    s_load_b128 s[0:3], s[4:5], 0x24 nv
-; GFX1364-NEXT:    s_load_b32 s6, s[4:5], 0x34 nv
+; GFX1364-NEXT:    s_load_u8 s6, s[4:5], 0x34 nv
 ; GFX1364-NEXT:    s_mov_b32 s7, 0x31016000
 ; GFX1364-NEXT:    s_wait_kmcnt 0x0
 ; GFX1364-NEXT:    s_and_b64 s[4:5], s[2:3], -4
 ; GFX1364-NEXT:    s_and_b32 s2, s2, 3
 ; GFX1364-NEXT:    s_load_b32 s3, s[4:5], 0x0
 ; GFX1364-NEXT:    s_lshl_b32 s8, s2, 3
-; GFX1364-NEXT:    s_and_b32 s6, s6, 0xff
+; GFX1364-NEXT:    s_delay_alu instid0(SALU_CYCLE_1)
 ; GFX1364-NEXT:    s_lshl_b32 s2, 0xff, s8
 ; GFX1364-NEXT:    s_lshl_b32 s10, s6, s8
 ; GFX1364-NEXT:    s_not_b32 s9, s2
@@ -11765,14 +11765,14 @@ define amdgpu_kernel void @uniform_xchg_i8(ptr addrspace(1) %result, ptr addrspa
 ; GFX1332:       ; %bb.0:
 ; GFX1332-NEXT:    s_clause 0x1
 ; GFX1332-NEXT:    s_load_b128 s[0:3], s[4:5], 0x24 nv
-; GFX1332-NEXT:    s_load_b32 s6, s[4:5], 0x34 nv
+; GFX1332-NEXT:    s_load_u8 s6, s[4:5], 0x34 nv
 ; GFX1332-NEXT:    s_mov_b32 s9, 0
 ; GFX1332-NEXT:    s_wait_kmcnt 0x0
 ; GFX1332-NEXT:    s_and_b64 s[4:5], s[2:3], -4
 ; GFX1332-NEXT:    s_and_b32 s2, s2, 3
 ; GFX1332-NEXT:    s_load_b32 s7, s[4:5], 0x0
 ; GFX1332-NEXT:    s_lshl_b32 s2, s2, 3
-; GFX1332-NEXT:    s_and_b32 s6, s6, 0xff
+; GFX1332-NEXT:    s_delay_alu instid0(SALU_CYCLE_1)
 ; GFX1332-NEXT:    s_lshl_b32 s3, 0xff, s2
 ; GFX1332-NEXT:    s_lshl_b32 s8, s6, s2
 ; GFX1332-NEXT:    s_not_b32 s3, s3
@@ -14074,7 +14074,7 @@ define amdgpu_kernel void @uniform_xchg_i16(ptr addrspace(1) %result, ptr addrsp
 ; GFX1264:       ; %bb.0:
 ; GFX1264-NEXT:    s_clause 0x1
 ; GFX1264-NEXT:    s_load_b128 s[0:3], s[4:5], 0x24
-; GFX1264-NEXT:    s_load_b32 s6, s[4:5], 0x34
+; GFX1264-NEXT:    s_load_u16 s6, s[4:5], 0x34
 ; GFX1264-NEXT:    s_mov_b64 s[8:9], 0
 ; GFX1264-NEXT:    s_wait_kmcnt 0x0
 ; GFX1264-NEXT:    s_and_b32 s4, s2, -4
@@ -14082,7 +14082,7 @@ define amdgpu_kernel void @uniform_xchg_i16(ptr addrspace(1) %result, ptr addrsp
 ; GFX1264-NEXT:    s_and_b32 s2, s2, 3
 ; GFX1264-NEXT:    s_load_b32 s5, s[4:5], 0x0
 ; GFX1264-NEXT:    s_lshl_b32 s2, s2, 3
-; GFX1264-NEXT:    s_and_b32 s6, s6, 0xffff
+; GFX1264-NEXT:    s_delay_alu instid0(SALU_CYCLE_1)
 ; GFX1264-NEXT:    s_lshl_b32 s7, 0xffff, s2
 ; GFX1264-NEXT:    s_lshl_b32 s11, s6, s2
 ; GFX1264-NEXT:    s_not_b32 s10, s7
@@ -14117,7 +14117,7 @@ define amdgpu_kernel void @uniform_xchg_i16(ptr addrspace(1) %result, ptr addrsp
 ; GFX1232:       ; %bb.0:
 ; GFX1232-NEXT:    s_clause 0x1
 ; GFX1232-NEXT:    s_load_b128 s[0:3], s[4:5], 0x24
-; GFX1232-NEXT:    s_load_b32 s6, s[4:5], 0x34
+; GFX1232-NEXT:    s_load_u16 s6, s[4:5], 0x34
 ; GFX1232-NEXT:    s_mov_b32 s9, 0
 ; GFX1232-NEXT:    s_wait_kmcnt 0x0
 ; GFX1232-NEXT:    s_and_b32 s4, s2, -4
@@ -14125,7 +14125,7 @@ define amdgpu_kernel void @uniform_xchg_i16(ptr addrspace(1) %result, ptr addrsp
 ; GFX1232-NEXT:    s_and_b32 s2, s2, 3
 ; GFX1232-NEXT:    s_load_b32 s5, s[4:5], 0x0
 ; GFX1232-NEXT:    s_lshl_b32 s2, s2, 3
-; GFX1232-NEXT:    s_and_b32 s6, s6, 0xffff
+; GFX1232-NEXT:    s_delay_alu instid0(SALU_CYCLE_1)
 ; GFX1232-NEXT:    s_lshl_b32 s7, 0xffff, s2
 ; GFX1232-NEXT:    s_lshl_b32 s10, s6, s2
 ; GFX1232-NEXT:    s_not_b32 s8, s7
@@ -14159,14 +14159,14 @@ define amdgpu_kernel void @uniform_xchg_i16(ptr addrspace(1) %result, ptr addrsp
 ; GFX1364:       ; %bb.0:
 ; GFX1364-NEXT:    s_clause 0x1
 ; GFX1364-NEXT:    s_load_b128 s[0:3], s[4:5], 0x24 nv
-; GFX1364-NEXT:    s_load_b32 s6, s[4:5], 0x34 nv
+; GFX1364-NEXT:    s_load_u16 s6, s[4:5], 0x34 nv
 ; GFX1364-NEXT:    s_mov_b32 s7, 0x31016000
 ; GFX1364-NEXT:    s_wait_kmcnt 0x0
 ; GFX1364-NEXT:    s_and_b64 s[4:5], s[2:3], -4
 ; GFX1364-NEXT:    s_and_b32 s2, s2, 3
 ; GFX1364-NEXT:    s_load_b32 s3, s[4:5], 0x0
 ; GFX1364-NEXT:    s_lshl_b32 s8, s2, 3
-; GFX1364-NEXT:    s_and_b32 s6, s6, 0xffff
+; GFX1364-NEXT:    s_delay_alu instid0(SALU_CYCLE_1)
 ; GFX1364-NEXT:    s_lshl_b32 s2, 0xffff, s8
 ; GFX1364-NEXT:    s_lshl_b32 s10, s6, s8
 ; GFX1364-NEXT:    s_not_b32 s9, s2
@@ -14200,14 +14200,14 @@ define amdgpu_kernel void @uniform_xchg_i16(ptr addrspace(1) %result, ptr addrsp
 ; GFX1332:       ; %bb.0:
 ; GFX1332-NEXT:    s_clause 0x1
 ; GFX1332-NEXT:    s_load_b128 s[0:3], s[4:5], 0x24 nv
-; GFX1332-NEXT:    s_load_b32 s6, s[4:5], 0x34 nv
+; GFX1332-NEXT:    s_load_u16 s6, s[4:5], 0x34 nv
 ; GFX1332-NEXT:    s_mov_b32 s9, 0
 ; GFX1332-NEXT:    s_wait_kmcnt 0x0
 ; GFX1332-NEXT:    s_and_b64 s[4:5], s[2:3], -4
 ; GFX1332-NEXT:    s_and_b32 s2, s2, 3
 ; GFX1332-NEXT:    s_load_b32 s7, s[4:5], 0x0
 ; GFX1332-NEXT:    s_lshl_b32 s2, s2, 3
-; GFX1332-NEXT:    s_and_b32 s6, s6, 0xffff
+; GFX1332-NEXT:    s_delay_alu instid0(SALU_CYCLE_1)
 ; GFX1332-NEXT:    s_lshl_b32 s3, 0xffff, s2
 ; GFX1332-NEXT:    s_lshl_b32 s8, s6, s2
 ; GFX1332-NEXT:    s_not_b32 s3, s3
diff --git a/llvm/test/CodeGen/AMDGPU/max.ll b/llvm/test/CodeGen/AMDGPU/max.ll
index 01be3f8ea2323..be1aadb95bc49 100644
--- a/llvm/test/CodeGen/AMDGPU/max.ll
+++ b/llvm/test/CodeGen/AMDGPU/max.ll
@@ -982,15 +982,13 @@ define amdgpu_kernel void @simplify_demanded_bits_test_umax_ugt_i16(ptr addrspac
 ; GFX1250-NEXT:    v_nop
 ; GFX1250-NEXT:    global_prefetch_b8 v0, s[64:65] scope:SCOPE_SE
 ; GFX1250-NEXT:    s_clause 0x2
-; GFX1250-NEXT:    s_load_b32 s2, s[4:5], 0x4c nv
-; GFX1250-NEXT:    s_load_b32 s3, s[4:5], 0x70 nv
+; GFX1250-NEXT:    s_load_u16 s2, s[4:5], 0x4c nv
+; GFX1250-NEXT:    s_load_u16 s3, s[4:5], 0x70 nv
 ; GFX1250-NEXT:    s_load_b64 s[0:1], s[4:5], 0x24 nv
 ; GFX1250-NEXT:    v_mov_b32_e32 v0, 0
 ; GFX1250-NEXT:    s_wait_kmcnt 0x0
-; GFX1250-NEXT:    s_and_b32 s2, s2, 0xffff
-; GFX1250-NEXT:    s_and_b32 s3, s3, 0xffff
-; GFX1250-NEXT:    s_delay_alu instid0(SALU_CYCLE_1) | instskip(NEXT) | instid1(SALU_CYCLE_1)
 ; GFX1250-NEXT:    s_max_u32 s2, s2, s3
+; GFX1250-NEXT:    s_delay_alu instid0(SALU_CYCLE_1)
 ; GFX1250-NEXT:    v_mov_b32_e32 v1, s2
 ; GFX1250-NEXT:    global_store_b32 v0, v1, s[0:1]
 ; GFX1250-NEXT:    s_endpgm
@@ -1049,15 +1047,13 @@ define amdgpu_kernel void @simplify_demanded_bits_test_max_slt_i16(ptr addrspace
 ; GFX1250-NEXT:    v_nop
 ; GFX1250-NEXT:    global_prefetch_b8 v0, s[64:65] scope:SCOPE_SE
 ; GFX1250-NEXT:    s_clause 0x2
-; GFX1250-NEXT:    s_load_b32 s2, s[4:5], 0x4c nv
-; GFX1250-NEXT:    s_load_b32 s3, s[4:5], 0x70 nv
+; GFX1250-NEXT:    s_load_i16 s2, s[4:5], 0x4c nv
+; GFX1250-NEXT:    s_load_i16 s3, s[4:5], 0x70 nv
 ; GFX1250-NEXT:    s_load_b64 s[0:1], s[4:5], 0x24 nv
 ; GFX1250-NEXT:    v_mov_b32_e32 v0, 0
 ; GFX1250-NEXT:    s_wait_kmcnt 0x0
-; GFX1250-NEXT:    s_sext_i32_i16 s2, s2
-; GFX1250-NEXT:    s_sext_i32_i16 s3, s3
-; GFX1250-NEXT:    s_delay_alu instid0(SALU_CYCLE_1) | instskip(NEXT) | instid1(SALU_CYCLE_1)
 ; GFX1250-NEXT:    s_max_i32 s2, s2, s3
+; GFX1250-NEXT:    s_delay_alu instid0(SALU_CYCLE_1)
 ; GFX1250-NEXT:    v_mov_b32_e32 v1, s2
 ; GFX1250-NEXT:    global_store_b32 v0, v1, s[0:1]
 ; GFX1250-NEXT:    s_endpgm
@@ -1115,15 +1111,13 @@ define amdgpu_kernel void @s_test_imax_sge_i16(ptr addrspace(1) %out, [8 x i32],
 ; GFX1250-NEXT:    v_nop
 ; GFX1250-NEXT:    global_prefetch_b8 v0, s[64:65] scope:SCOPE_SE
 ; GFX1250-NEXT:    s_clause 0x2
-; GFX1250-NEXT:    s_load_b32 s2, s[4:5], 0x70 nv
-; GFX1250-NEXT:    s_load_b32 s3, s[4:5], 0x4c nv
+; GFX1250-NEXT:    s_load_i16 s2, s[4:5], 0x4c nv
+; GFX1250-NEXT:    s_load_i16 s3, s[4:5], 0x70 nv
 ; GFX1250-NEXT:    s_load_b64 s[0:1], s[4:5], 0x24 nv
 ; GFX1250-NEXT:    v_mov_b32_e32 v0, 0
 ; GFX1250-NEXT:    s_wait_kmcnt 0x0
-; GFX1250-NEXT:    s_sext_i32_i16 s2, s2
-; GFX1250-NEXT:    s_sext_i32_i16 s3, s3
-; GFX1250-NEXT:    s_delay_alu instid0(SALU_CYCLE_1) | instskip(NEXT) | instid1(SALU_CYCLE_1)
-; GFX1250-NEXT:    s_max_i32 s2, s3, s2
+; GFX1250-NEXT:    s_max_i32 s2, s2, s3
+; GFX1250-NEXT:    s_delay_alu instid0(SALU_CYCLE_1)
 ; GFX1250-NEXT:    v_mov_b32_e32 v1, s2
 ; GFX1250-NEXT:    global_store_b16 v0, v1, s[0:1]
 ; GFX1250-NEXT:    s_endpgm
diff --git a/llvm/test/CodeGen/AMDGPU/min.ll b/llvm/test/CodeGen/AMDGPU/min.ll
index f7cb1914749a7..69a394e7cdf03 100644
--- a/llvm/test/CodeGen/AMDGPU/min.ll
+++ b/llvm/test/CodeGen/AMDGPU/min.ll
@@ -595,15 +595,13 @@ define amdgpu_kernel void @s_test_imin_sle_i8(ptr addrspace(1) %out, [8 x i32],
 ; GFX1250-NEXT:    v_nop
 ; GFX1250-NEXT:    global_prefetch_b8 v0, s[64:65] scope:SCOPE_SE
 ; GFX1250-NEXT:    s_clause 0x2
-; GFX1250-NEXT:    s_load_b32 s2, s[4:5], 0x4c nv
-; GFX1250-NEXT:    s_load_b32 s3, s[4:5], 0x28 nv
+; GFX1250-NEXT:    s_load_i8 s2, s[4:5], 0x28 nv
+; GFX1250-NEXT:    s_load_i8 s3, s[4:5], 0x4c nv
 ; GFX1250-NEXT:    s_load_b64 s[0:1], s[4:5], 0x0 nv
 ; GFX1250-NEXT:    v_mov_b32_e32 v0, 0
 ; GFX1250-NEXT:    s_wait_kmcnt 0x0
-; GFX1250-NEXT:    s_sext_i32_i8 s2, s2
-; GFX1250-NEXT:    s_sext_i32_i8 s3, s3
-; GFX1250-NEXT:    s_delay_alu instid0(SALU_CYCLE_1) | instskip(NEXT) | instid1(SALU_CYCLE_1)
-; GFX1250-NEXT:    s_min_i32 s2, s3, s2
+; GFX1250-NEXT:    s_min_i32 s2, s2, s3
+; GFX1250-NEXT:    s_delay_alu instid0(SALU_CYCLE_1)
 ; GFX1250-NEXT:    v_mov_b32_e32 v1, s2
 ; GFX1250-NEXT:    global_store_b8 v0, v1, s[0:1]
 ; GFX1250-NEXT:    s_endpgm
@@ -4081,15 +4079,13 @@ define amdgpu_kernel void @simplify_demanded_bits_test_umin_ult_i16(ptr addrspac
 ; GFX1250-NEXT:    v_nop
 ; GFX1250-NEXT:    global_prefetch_b8 v0, s[64:65] scope:SCOPE_SE
 ; GFX1250-NEXT:    s_clause 0x2
-; GFX1250-NEXT:    s_load_b32 s2, s[4:5], 0x28 nv
-; GFX1250-NEXT:    s_load_b32 s3, s[4:5], 0x4c nv
+; GFX1250-NEXT:    s_load_u16 s2, s[4:5], 0x28 nv
+; GFX1250-NEXT:    s_load_u16 s3, s[4:5], 0x4c nv
 ; GFX1250-NEXT:    s_load_b64 s[0:1], s[4:5], 0x0 nv
 ; GFX1250-NEXT:    v_mov_b32_e32 v0, 0
 ; GFX1250-NEXT:    s_wait_kmcnt 0x0
-; GFX1250-NEXT:    s_and_b32 s2, s2, 0xffff
-; GFX1250-NEXT:    s_and_b32 s3, s3, 0xffff
-; GFX1250-NEXT:    s_delay_alu instid0(SALU_CYCLE_1) | instskip(NEXT) | instid1(SALU_CYCLE_1)
 ; GFX1250-NEXT:    s_min_u32 s2, s2, s3
+; GFX1250-NEXT:    s_delay_alu instid0(SALU_CYCLE_1)
 ; GFX1250-NEXT:    v_mov_b32_e32 v1, s2
 ; GFX1250-NEXT:    global_store_b32 v0, v1, s[0:1]
 ; GFX1250-NEXT:    s_endpgm
@@ -4214,15 +4210,13 @@ define amdgpu_kernel void @simplify_demanded_bits_test_min_slt_i16(ptr addrspace
 ; GFX1250-NEXT:    v_nop
 ; GFX1250-NEXT:    global_prefetch_b8 v0, s[64:65] scope:SCOPE_SE
 ; GFX1250-NEXT:    s_clause 0x2
-; GFX1250-NEXT:    s_load_b32 s2, s[4:5], 0x28 nv
-; GFX1250-NEXT:    s_load_b32 s3, s[4:5], 0x4c nv
+; GFX1250-NEXT:    s_load_i16 s2, s[4:5], 0x28 nv
+; GFX1250-NEXT:    s_load_i16 s3, s[4:5], 0x4c nv
 ; GFX1250-NEXT:    s_load_b64 s[0:1], s[4:5], 0x0 nv
 ; GFX1250-NEXT:    v_mov_b32_e32 v0, 0
 ; GFX1250-NEXT:    s_wait_kmcnt 0x0
-; GFX1250-NEXT:    s_sext_i32_i16 s2, s2
-; GFX1250-NEXT:    s_sext_i32_i16 s3, s3
-; GFX1250-NEXT:    s_delay_alu instid0(SALU_CYCLE_1) | instskip(NEXT) | instid1(SALU_CYCLE_1)
 ; GFX1250-NEXT:    s_min_i32 s2, s2, s3
+; GFX1250-NEXT:    s_delay_alu instid0(SALU_CYCLE_1)
 ; GFX1250-NEXT:    v_mov_b32_e32 v1, s2
 ; GFX1250-NEXT:    global_store_b32 v0, v1, s[0:1]
 ; GFX1250-NEXT:    s_endpgm
diff --git a/llvm/test/CodeGen/AMDGPU/reassoc-mul-add-1-to-mad.ll b/llvm/test/CodeGen/AMDGPU/reassoc-mul-add-1-to-mad.ll
index f9c85fa324fe1..3aa4d9bf8707a 100644
--- a/llvm/test/CodeGen/AMDGPU/reassoc-mul-add-1-to-mad.ll
+++ b/llvm/test/CodeGen/AMDGPU/reassoc-mul-add-1-to-mad.ll
@@ -5293,47 +5293,47 @@ define amdgpu_kernel void @compute_mad(ptr addrspace(4) %i18, ptr addrspace(4) %
 ; GFX1250-NEXT:    s_mov_b64 s[64:65], 0
 ; GFX1250-NEXT:    v_nop
 ; GFX1250-NEXT:    global_prefetch_b8 v0, s[64:65] scope:SCOPE_SE
-; GFX1250-NEXT:    s_load_b96 s[0:2], s[4:5], 0x10 nv
+; GFX1250-NEXT:    s_load_b96 s[8:10], s[4:5], 0x10 nv
 ; GFX1250-NEXT:    v_and_b32_e32 v0, 0x3ff, v0
-; GFX1250-NEXT:    s_wait_xcnt 0x0
-; GFX1250-NEXT:    s_load_b128 s[4:7], s[4:5], 0x0 nv
 ; GFX1250-NEXT:    s_wait_kmcnt 0x0
-; GFX1250-NEXT:    s_add_co_i32 s2, s2, 1
-; GFX1250-NEXT:    s_load_b32 s6, s[6:7], 0x4 nv
-; GFX1250-NEXT:    v_mul_lo_u32 v1, s2, v0
-; GFX1250-NEXT:    s_delay_alu instid0(VALU_DEP_1) | instskip(SKIP_3) | instid1(VALU_DEP_1)
-; GFX1250-NEXT:    v_dual_add_nc_u32 v2, s2, v1 :: v_dual_add_nc_u32 v1, 1, v1
-; GFX1250-NEXT:    s_bfe_u32 s2, ttmp6, 0x4000c
-; GFX1250-NEXT:    s_wait_xcnt 0x0
-; GFX1250-NEXT:    s_add_co_i32 s7, s2, 1
-; GFX1250-NEXT:    v_mul_lo_u32 v2, v2, v0
-; GFX1250-NEXT:    s_load_b64 s[2:3], s[4:5], 0x0 nv
+; GFX1250-NEXT:    s_add_co_i32 s0, s10, 1
+; GFX1250-NEXT:    s_delay_alu instid0(VALU_DEP_1) | instid1(SALU_CYCLE_1)
+; GFX1250-NEXT:    v_mul_lo_u32 v1, s0, v0
+; GFX1250-NEXT:    s_delay_alu instid0(VALU_DEP_1)
+; GFX1250-NEXT:    v_dual_add_nc_u32 v2, s0, v1 :: v_dual_add_nc_u32 v1, 1, v1
+; GFX1250-NEXT:    s_load_b128 s[0:3], s[4:5], 0x0 nv
 ; GFX1250-NEXT:    s_wait_xcnt 0x0
 ; GFX1250-NEXT:    s_and_b32 s4, ttmp6, 15
-; GFX1250-NEXT:    s_mul_i32 s5, ttmp9, s7
-; GFX1250-NEXT:    s_getreg_b32 s7, hwreg(HW_REG_IB_STS2, 6, 4)
-; GFX1250-NEXT:    s_add_co_i32 s4, s4, s5
-; GFX1250-NEXT:    s_wait_kmcnt 0x0
-; GFX1250-NEXT:    s_and_b32 s5, s6, 0xffff
-; GFX1250-NEXT:    s_cmp_eq_u32 s7, 0
+; GFX1250-NEXT:    s_getreg_b32 s5, hwreg(HW_REG_IB_STS2, 6, 4)
+; GFX1250-NEXT:    v_mul_lo_u32 v2, v2, v0
+; GFX1250-NEXT:    s_delay_alu instid0(VALU_DEP_1) | instskip(NEXT) | instid1(VALU_DEP_1)
 ; GFX1250-NEXT:    v_mul_lo_u32 v3, v2, v1
-; GFX1250-NEXT:    s_cselect_b32 s4, ttmp9, s4
-; GFX1250-NEXT:    s_delay_alu instid0(SALU_CYCLE_1) | instskip(NEXT) | instid1(VALU_DEP_2)
-; GFX1250-NEXT:    v_mad_u32 v0, s4, s5, v0
 ; GFX1250-NEXT:    v_add_nc_u32_e32 v1, v3, v1
-; GFX1250-NEXT:    s_delay_alu instid0(VALU_DEP_1) | instskip(SKIP_1) | instid1(VALU_DEP_1)
+; GFX1250-NEXT:    s_wait_kmcnt 0x0
+; GFX1250-NEXT:    s_load_u16 s2, s[2:3], 0x4 nv
+; GFX1250-NEXT:    s_wait_xcnt 0x0
+; GFX1250-NEXT:    s_bfe_u32 s3, ttmp6, 0x4000c
+; GFX1250-NEXT:    s_load_b64 s[0:1], s[0:1], 0x0 nv
+; GFX1250-NEXT:    s_add_co_i32 s3, s3, 1
 ; GFX1250-NEXT:    v_mul_lo_u32 v1, v1, v2
 ; GFX1250-NEXT:    v_add_nc_u32_e32 v2, 1, v3
+; GFX1250-NEXT:    s_mul_i32 s3, ttmp9, s3
+; GFX1250-NEXT:    s_delay_alu instid0(SALU_CYCLE_1) | instskip(SKIP_2) | instid1(VALU_DEP_2)
+; GFX1250-NEXT:    s_add_co_i32 s4, s4, s3
+; GFX1250-NEXT:    s_cmp_eq_u32 s5, 0
+; GFX1250-NEXT:    s_cselect_b32 s3, ttmp9, s4
 ; GFX1250-NEXT:    v_mul_lo_u32 v3, v1, v2
-; GFX1250-NEXT:    s_delay_alu instid0(VALU_DEP_1) | instskip(NEXT) | instid1(VALU_DEP_1)
+; GFX1250-NEXT:    s_wait_kmcnt 0x0
+; GFX1250-NEXT:    v_mad_u32 v0, s3, s2, v0
+; GFX1250-NEXT:    s_delay_alu instid0(VALU_DEP_2) | instskip(NEXT) | instid1(VALU_DEP_1)
 ; GFX1250-NEXT:    v_add_nc_u32_e32 v2, v3, v2
 ; GFX1250-NEXT:    v_mul_lo_u32 v2, v2, v1
 ; GFX1250-NEXT:    v_mov_b32_e32 v1, 0
 ; GFX1250-NEXT:    s_delay_alu instid0(VALU_DEP_1) | instskip(NEXT) | instid1(VALU_DEP_3)
-; GFX1250-NEXT:    v_add_nc_u64_e32 v[0:1], s[2:3], v[0:1]
+; GFX1250-NEXT:    v_add_nc_u64_e32 v[0:1], s[0:1], v[0:1]
 ; GFX1250-NEXT:    v_mad_u32 v3, v2, v3, v2
 ; GFX1250-NEXT:    s_delay_alu instid0(VALU_DEP_2) | instskip(NEXT) | instid1(VALU_DEP_2)
-; GFX1250-NEXT:    v_lshl_add_u64 v[0:1], v[0:1], 2, s[0:1]
+; GFX1250-NEXT:    v_lshl_add_u64 v[0:1], v[0:1], 2, s[8:9]
 ; GFX1250-NEXT:    v_mad_u32 v2, v3, v2, v3
 ; GFX1250-NEXT:    global_store_b32 v[0:1], v2, off
 ; GFX1250-NEXT:    s_endpgm
@@ -5343,46 +5343,44 @@ define amdgpu_kernel void @compute_mad(ptr addrspace(4) %i18, ptr addrspace(4) %
 ; GFX13-NEXT:    s_load_b96 s[0:2], s[4:5], 0x10 nv
 ; GFX13-NEXT:    v_and_b32_e32 v0, 0x3ff, v0
 ; GFX13-NEXT:    s_load_b128 s[4:7], s[4:5], 0x0 nv
-; GFX13-NEXT:    s_bfe_u32 s8, ttmp6, 0x4000c
-; GFX13-NEXT:    s_delay_alu instid0(SALU_CYCLE_1)
-; GFX13-NEXT:    s_add_co_i32 s8, s8, 1
 ; GFX13-NEXT:    s_wait_kmcnt 0x0
 ; GFX13-NEXT:    s_add_co_i32 s2, s2, 1
-; GFX13-NEXT:    s_load_b32 s6, s[6:7], 0x4 nv
+; GFX13-NEXT:    s_load_u16 s6, s[6:7], 0x4 nv
 ; GFX13-NEXT:    v_mul_lo_u32 v1, s2, v0
-; GFX13-NEXT:    s_and_b32 s7, ttmp6, 15
-; GFX13-NEXT:    s_delay_alu instid0(VALU_DEP_1) | instskip(SKIP_3) | instid1(VALU_DEP_1)
+; GFX13-NEXT:    s_bfe_u32 s7, ttmp6, 0x4000c
+; GFX13-NEXT:    s_delay_alu instid0(SALU_CYCLE_1) | instskip(NEXT) | instid1(VALU_DEP_1)
+; GFX13-NEXT:    s_add_co_i32 s7, s7, 1
 ; GFX13-NEXT:    v_dual_add_nc_u32 v2, s2, v1 :: v_dual_add_nc_u32 v1, 1, v1
 ; GFX13-NEXT:    s_load_b64 s[2:3], s[4:5], 0x0 nv
-; GFX13-NEXT:    s_mul_i32 s4, ttmp9, s8
-; GFX13-NEXT:    s_getreg_b32 s5, hwreg(HW_REG_IB_STS2, 6, 4)
+; GFX13-NEXT:    s_and_b32 s4, ttmp6, 15
+; GFX13-NEXT:    s_mul_i32 s5, ttmp9, s7
+; GFX13-NEXT:    s_delay_alu instid0(VALU_DEP_1) | instskip(SKIP_4) | instid1(VALU_DEP_1)
 ; GFX13-NEXT:    v_mul_lo_u32 v2, v2, v0
-; GFX13-NEXT:    s_add_co_i32 s7, s7, s4
-; GFX13-NEXT:    s_wait_kmcnt 0x0
-; GFX13-NEXT:    s_and_b32 s4, s6, 0xffff
-; GFX13-NEXT:    s_cmp_eq_u32 s5, 0
-; GFX13-NEXT:    s_delay_alu instid0(VALU_DEP_1) | instskip(SKIP_1) | instid1(VALU_DEP_1)
+; GFX13-NEXT:    s_getreg_b32 s7, hwreg(HW_REG_IB_STS2, 6, 4)
+; GFX13-NEXT:    s_add_co_i32 s4, s4, s5
+; GFX13-NEXT:    s_cmp_eq_u32 s7, 0
+; GFX13-NEXT:    s_cselect_b32 s4, ttmp9, s4
 ; GFX13-NEXT:    v_mul_lo_u32 v3, v2, v1
-; GFX13-NEXT:    s_cselect_b32 s5, ttmp9, s7
+; GFX13-NEXT:    s_delay_alu instid0(VALU_DEP_1) | instskip(NEXT) | instid1(VALU_DEP_1)
 ; GFX13-NEXT:    v_add_nc_u32_e32 v1, v3, v1
-; GFX13-NEXT:    s_delay_alu instid0(VALU_DEP_1) | instskip(SKIP_1) | instid1(VALU_DEP_1)
 ; GFX13-NEXT:    v_mul_lo_u32 v2, v1, v2
 ; GFX13-NEXT:    v_add_nc_u32_e32 v1, 1, v3
+; GFX13-NEXT:    s_delay_alu instid0(VALU_DEP_1) | instskip(NEXT) | instid1(VALU_DEP_1)
 ; GFX13-NEXT:    v_mul_lo_u32 v4, v2, v1
-; GFX13-NEXT:    s_delay_alu instid0(VALU_DEP_1) | instskip(SKIP_1) | instid1(VALU_DEP_2)
 ; GFX13-NEXT:    v_add_nc_u32_e32 v3, v4, v1
-; GFX13-NEXT:    v_mad_co_u64_u32 v[0:1], null, s5, s4, v[0:1]
+; GFX13-NEXT:    s_wait_kmcnt 0x0
+; GFX13-NEXT:    v_mad_co_u64_u32 v[0:1], null, s4, s6, v[0:1]
+; GFX13-NEXT:    s_delay_alu instid0(VALU_DEP_2) | instskip(NEXT) | instid1(VALU_DEP_2)
 ; GFX13-NEXT:    v_mul_lo_u32 v1, v3, v2
-; GFX13-NEXT:    s_delay_alu instid0(VALU_DEP_2) | instskip(NEXT) | instid1(VALU_DEP_1)
 ; GFX13-NEXT:    v_add_co_u32 v2, s2, s2, v0
+; GFX13-NEXT:    s_delay_alu instid0(VALU_DEP_1) | instskip(NEXT) | instid1(VALU_DEP_2)
 ; GFX13-NEXT:    v_add_co_ci_u32_e64 v3, null, s3, 0, s2
-; GFX13-NEXT:    s_delay_alu instid0(VALU_DEP_2) | instskip(NEXT) | instid1(VALU_DEP_2)
 ; GFX13-NEXT:    v_mad_co_u64_u32 v[4:5], null, v1, v4, v[1:2]
-; GFX13-NEXT:    v_lshlrev_b64_e32 v[2:3], 2, v[2:3]
 ; GFX13-NEXT:    s_delay_alu instid0(VALU_DEP_2) | instskip(NEXT) | instid1(VALU_DEP_2)
+; GFX13-NEXT:    v_lshlrev_b64_e32 v[2:3], 2, v[2:3]
 ; GFX13-NEXT:    v_mad_co_u64_u32 v[0:1], null, v4, v1, v[4:5]
+; GFX13-NEXT:    s_delay_alu instid0(VALU_DEP_2) | instskip(NEXT) | instid1(VALU_DEP_1)
 ; GFX13-NEXT:    v_add_co_u32 v1, vcc_lo, s0, v2
-; GFX13-NEXT:    s_delay_alu instid0(VALU_DEP_1)
 ; GFX13-NEXT:    v_add_co_ci_u32_e64 v2, null, s1, v3, vcc_lo
 ; GFX13-NEXT:    global_store_b32 v[1:2], v0, off
 ; GFX13-NEXT:    s_endpgm
diff --git a/llvm/test/CodeGen/AMDGPU/scalar-subword-loads.ll b/llvm/test/CodeGen/AMDGPU/scalar-subword-loads.ll
index e39d12963633b..7421ce6bfd450 100644
--- a/llvm/test/CodeGen/AMDGPU/scalar-subword-loads.ll
+++ b/llvm/test/CodeGen/AMDGPU/scalar-subword-loads.ll
@@ -1,6 +1,6 @@
 ; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py UTC_ARGS: --version 6
 ; Test all scalar subword load optimization variants
-; RUN: llc -mtriple=amdgcn -mcpu=gfx1250 < %s | FileCheck %s
+; RUN: llc -mtriple=amdgpu12.50 < %s | FileCheck %s
 
 declare i32 @llvm.amdgcn.s.buffer.load.i32(<4 x i32>, i32, i32 immarg)
 
@@ -16,12 +16,10 @@ define amdgpu_kernel void @s_load_u8(ptr addrspace(1) %out) {
 ; CHECK-NEXT:    v_nop
 ; CHECK-NEXT:    global_prefetch_b8 v0, s[64:65] scope:SCOPE_SE
 ; CHECK-NEXT:    s_mov_b64 s[0:1], 16
-; CHECK-NEXT:    s_load_b32 s6, s[0:1], 0x0 nv
+; CHECK-NEXT:    s_load_u8 s6, s[0:1], 0x0 nv
 ; CHECK-NEXT:    s_load_b64 s[2:3], s[4:5], 0x24 nv
 ; CHECK-NEXT:    s_wait_kmcnt 0x0
-; CHECK-NEXT:    s_and_b32 s0, s6, 0xff
-; CHECK-NEXT:    s_delay_alu instid0(SALU_CYCLE_1)
-; CHECK-NEXT:    v_dual_mov_b32 v0, 0 :: v_dual_mov_b32 v1, s0
+; CHECK-NEXT:    v_dual_mov_b32 v0, 0 :: v_dual_mov_b32 v1, s6
 ; CHECK-NEXT:    global_store_b32 v0, v1, s[2:3]
 ; CHECK-NEXT:    s_endpgm
   %ptr = inttoptr i64 16 to ptr addrspace(4)
@@ -39,12 +37,10 @@ define amdgpu_kernel void @s_load_u16(ptr addrspace(1) %out) {
 ; CHECK-NEXT:    v_nop
 ; CHECK-NEXT:    global_prefetch_b8 v0, s[64:65] scope:SCOPE_SE
 ; CHECK-NEXT:    s_mov_b64 s[0:1], 16
-; CHECK-NEXT:    s_load_b32 s6, s[0:1], 0x0 nv
+; CHECK-NEXT:    s_load_u16 s6, s[0:1], 0x0 nv
 ; CHECK-NEXT:    s_load_b64 s[2:3], s[4:5], 0x24 nv
 ; CHECK-NEXT:    s_wait_kmcnt 0x0
-; CHECK-NEXT:    s_and_b32 s0, s6, 0xffff
-; CHECK-NEXT:    s_delay_alu instid0(SALU_CYCLE_1)
-; CHECK-NEXT:    v_dual_mov_b32 v0, 0 :: v_dual_mov_b32 v1, s0
+; CHECK-NEXT:    v_dual_mov_b32 v0, 0 :: v_dual_mov_b32 v1, s6
 ; CHECK-NEXT:    global_store_b32 v0, v1, s[2:3]
 ; CHECK-NEXT:    s_endpgm
   %ptr = inttoptr i64 16 to ptr addrspace(4)
@@ -107,9 +103,8 @@ define amdgpu_cs i32 @s_buffer_load_u8_imm(<4 x i32> inreg %buf) {
 ; CHECK-NEXT:    s_mov_b64 s[64:65], 0
 ; CHECK-NEXT:    v_nop
 ; CHECK-NEXT:    global_prefetch_b8 v0, s[64:65] scope:SCOPE_SE
-; CHECK-NEXT:    s_buffer_load_b32 s0, s[0:3], 0x10 nv
+; CHECK-NEXT:    s_buffer_load_u8 s0, s[0:3], 0x10 nv
 ; CHECK-NEXT:    s_wait_kmcnt 0x0
-; CHECK-NEXT:    s_and_b32 s0, s0, 0xff
 ; CHECK-NEXT:    ; return to shader part epilog
   %val = call i32 @llvm.amdgcn.s.buffer.load.i32(<4 x i32> %buf, i32 16, i32 0)
   %masked = and i32 %val, 255
@@ -123,9 +118,8 @@ define amdgpu_cs i32 @s_buffer_load_u16_imm(<4 x i32> inreg %buf) {
 ; CHECK-NEXT:    s_mov_b64 s[64:65], 0
 ; CHECK-NEXT:    v_nop
 ; CHECK-NEXT:    global_prefetch_b8 v0, s[64:65] scope:SCOPE_SE
-; CHECK-NEXT:    s_buffer_load_b32 s0, s[0:3], 0x10 nv
+; CHECK-NEXT:    s_buffer_load_u16 s0, s[0:3], 0x10 nv
 ; CHECK-NEXT:    s_wait_kmcnt 0x0
-; CHECK-NEXT:    s_and_b32 s0, s0, 0xffff
 ; CHECK-NEXT:    ; return to shader part epilog
   %val = call i32 @llvm.amdgcn.s.buffer.load.i32(<4 x i32> %buf, i32 16, i32 0)
   %masked = and i32 %val, 65535
@@ -139,9 +133,8 @@ define amdgpu_cs i32 @s_buffer_load_i8_imm(<4 x i32> inreg %buf) {
 ; CHECK-NEXT:    s_mov_b64 s[64:65], 0
 ; CHECK-NEXT:    v_nop
 ; CHECK-NEXT:    global_prefetch_b8 v0, s[64:65] scope:SCOPE_SE
-; CHECK-NEXT:    s_buffer_load_b32 s0, s[0:3], 0x10 nv
+; CHECK-NEXT:    s_buffer_load_i8 s0, s[0:3], 0x10 nv
 ; CHECK-NEXT:    s_wait_kmcnt 0x0
-; CHECK-NEXT:    s_sext_i32_i8 s0, s0
 ; CHECK-NEXT:    ; return to shader part epilog
   %val = call i32 @llvm.amdgcn.s.buffer.load.i32(<4 x i32> %buf, i32 16, i32 0)
   %trunc = trunc i32 %val to i8
@@ -156,9 +149,8 @@ define amdgpu_cs i32 @s_buffer_load_i16_imm(<4 x i32> inreg %buf) {
 ; CHECK-NEXT:    s_mov_b64 s[64:65], 0
 ; CHECK-NEXT:    v_nop
 ; CHECK-NEXT:    global_prefetch_b8 v0, s[64:65] scope:SCOPE_SE
-; CHECK-NEXT:    s_buffer_load_b32 s0, s[0:3], 0x10 nv
+; CHECK-NEXT:    s_buffer_load_i16 s0, s[0:3], 0x10 nv
 ; CHECK-NEXT:    s_wait_kmcnt 0x0
-; CHECK-NEXT:    s_sext_i32_i16 s0, s0
 ; CHECK-NEXT:    ; return to shader part epilog
   %val = call i32 @llvm.amdgcn.s.buffer.load.i32(<4 x i32> %buf, i32 16, i32 0)
   %trunc = trunc i32 %val to i16
@@ -177,9 +169,8 @@ define amdgpu_cs i32 @s_buffer_load_u8_sgpr(<4 x i32> inreg %buf, i32 inreg %off
 ; CHECK-NEXT:    s_mov_b64 s[64:65], 0
 ; CHECK-NEXT:    v_nop
 ; CHECK-NEXT:    global_prefetch_b8 v0, s[64:65] scope:SCOPE_SE
-; CHECK-NEXT:    s_buffer_load_b32 s0, s[0:3], s4 offset:0x0 nv
+; CHECK-NEXT:    s_buffer_load_u8 s0, s[0:3], s4 offset:0x0 nv
 ; CHECK-NEXT:    s_wait_kmcnt 0x0
-; CHECK-NEXT:    s_and_b32 s0, s0, 0xff
 ; CHECK-NEXT:    ; return to shader part epilog
   %val = call i32 @llvm.amdgcn.s.buffer.load.i32(<4 x i32> %buf, i32 %offset, i32 0)
   %masked = and i32 %val, 255
@@ -193,9 +184,8 @@ define amdgpu_cs i32 @s_buffer_load_u16_sgpr(<4 x i32> inreg %buf, i32 inreg %of
 ; CHECK-NEXT:    s_mov_b64 s[64:65], 0
 ; CHECK-NEXT:    v_nop
 ; CHECK-NEXT:    global_prefetch_b8 v0, s[64:65] scope:SCOPE_SE
-; CHECK-NEXT:    s_buffer_load_b32 s0, s[0:3], s4 offset:0x0 nv
+; CHECK-NEXT:    s_buffer_load_u16 s0, s[0:3], s4 offset:0x0 nv
 ; CHECK-NEXT:    s_wait_kmcnt 0x0
-; CHECK-NEXT:    s_and_b32 s0, s0, 0xffff
 ; CHECK-NEXT:    ; return to shader part epilog
   %val = call i32 @llvm.amdgcn.s.buffer.load.i32(<4 x i32> %buf, i32 %offset, i32 0)
   %masked = and i32 %val, 65535
@@ -209,9 +199,8 @@ define amdgpu_cs i32 @s_buffer_load_i8_sgpr(<4 x i32> inreg %buf, i32 inreg %off
 ; CHECK-NEXT:    s_mov_b64 s[64:65], 0
 ; CHECK-NEXT:    v_nop
 ; CHECK-NEXT:    global_prefetch_b8 v0, s[64:65] scope:SCOPE_SE
-; CHECK-NEXT:    s_buffer_load_b32 s0, s[0:3], s4 offset:0x0 nv
+; CHECK-NEXT:    s_buffer_load_i8 s0, s[0:3], s4 offset:0x0 nv
 ; CHECK-NEXT:    s_wait_kmcnt 0x0
-; CHECK-NEXT:    s_sext_i32_i8 s0, s0
 ; CHECK-NEXT:    ; return to shader part epilog
   %val = call i32 @llvm.amdgcn.s.buffer.load.i32(<4 x i32> %buf, i32 %offset, i32 0)
   %trunc = trunc i32 %val to i8
@@ -226,9 +215,8 @@ define amdgpu_cs i32 @s_buffer_load_i16_sgpr(<4 x i32> inreg %buf, i32 inreg %of
 ; CHECK-NEXT:    s_mov_b64 s[64:65], 0
 ; CHECK-NEXT:    v_nop
 ; CHECK-NEXT:    global_prefetch_b8 v0, s[64:65] scope:SCOPE_SE
-; CHECK-NEXT:    s_buffer_load_b32 s0, s[0:3], s4 offset:0x0 nv
+; CHECK-NEXT:    s_buffer_load_i16 s0, s[0:3], s4 offset:0x0 nv
 ; CHECK-NEXT:    s_wait_kmcnt 0x0
-; CHECK-NEXT:    s_sext_i32_i16 s0, s0
 ; CHECK-NEXT:    ; return to shader part epilog
   %val = call i32 @llvm.amdgcn.s.buffer.load.i32(<4 x i32> %buf, i32 %offset, i32 0)
   %trunc = trunc i32 %val to i16
diff --git a/llvm/test/CodeGen/AMDGPU/si-load-opt-scalar-subword.mir b/llvm/test/CodeGen/AMDGPU/si-load-opt-scalar-subword.mir
index c65dc6cb32764..913849fb2f7f5 100644
--- a/llvm/test/CodeGen/AMDGPU/si-load-opt-scalar-subword.mir
+++ b/llvm/test/CodeGen/AMDGPU/si-load-opt-scalar-subword.mir
@@ -1,9 +1,9 @@
 # NOTE: Assertions have been autogenerated by utils/update_mir_test_checks.py UTC_ARGS: --version 5
-# RUN: llc -mtriple=amdgcn -mcpu=gfx1250 -run-pass=si-load-store-opt %s -o - | FileCheck %s
+# RUN: llc -mtriple=amdgpu12.50 -run-pass=si-load-store-opt %s -o - | FileCheck %s
 
 # Test scalar subword load optimization at MIR level
-# Tests all combinations of: {u8, u16, i8, i16} × {IMM, SGPR, SGPR_IMM} addressing modes
-# for both S_LOAD and S_BUFFER_LOAD variants
+# Tests all combinations of: {S_LOAD:        IMM, SGPR          } x {u8, u16, i8, i16} 
+# Tests all combinations of: {S_BUFFER_LOAD: IMM, SGPR, SGPR_IMM} x {u8, u16, i8, i16} 
 
 ---
 name: s_load_u8_imm
@@ -17,9 +17,8 @@ body: |
     ; CHECK-NEXT: [[COPY:%[0-9]+]]:sgpr_32 = COPY $sgpr1
     ; CHECK-NEXT: [[COPY1:%[0-9]+]]:sgpr_32 = COPY $sgpr0
     ; CHECK-NEXT: [[REG_SEQUENCE:%[0-9]+]]:sreg_64 = REG_SEQUENCE [[COPY1]], %subreg.sub0, [[COPY]], %subreg.sub1
-    ; CHECK-NEXT: [[S_LOAD_DWORD_IMM:%[0-9]+]]:sreg_32_xm0_xexec = S_LOAD_DWORD_IMM [[REG_SEQUENCE]], 16, 0 :: (load (s32))
-    ; CHECK-NEXT: [[S_AND_B32_:%[0-9]+]]:sreg_32 = S_AND_B32 [[S_LOAD_DWORD_IMM]], 255, implicit-def $scc
-    ; CHECK-NEXT: S_ENDPGM 0, implicit [[S_AND_B32_]]
+    ; CHECK-NEXT: [[S_LOAD_U8_IMM:%[0-9]+]]:sreg_32 = S_LOAD_U8_IMM [[REG_SEQUENCE]], 16, 0 :: (load (s32))
+    ; CHECK-NEXT: S_ENDPGM 0, implicit [[S_LOAD_U8_IMM]]
     %1:sgpr_32 = COPY $sgpr1
     %0:sgpr_32 = COPY $sgpr0
     %2:sreg_64 = REG_SEQUENCE %0, %subreg.sub0, %1, %subreg.sub1
@@ -40,9 +39,8 @@ body: |
     ; CHECK-NEXT: [[COPY:%[0-9]+]]:sgpr_32 = COPY $sgpr1
     ; CHECK-NEXT: [[COPY1:%[0-9]+]]:sgpr_32 = COPY $sgpr0
     ; CHECK-NEXT: [[REG_SEQUENCE:%[0-9]+]]:sreg_64 = REG_SEQUENCE [[COPY1]], %subreg.sub0, [[COPY]], %subreg.sub1
-    ; CHECK-NEXT: [[S_LOAD_DWORD_IMM:%[0-9]+]]:sreg_32_xm0_xexec = S_LOAD_DWORD_IMM [[REG_SEQUENCE]], 16, 0 :: (load (s32))
-    ; CHECK-NEXT: [[S_AND_B32_:%[0-9]+]]:sreg_32 = S_AND_B32 [[S_LOAD_DWORD_IMM]], 65535, implicit-def $scc
-    ; CHECK-NEXT: S_ENDPGM 0, implicit [[S_AND_B32_]]
+    ; CHECK-NEXT: [[S_LOAD_U16_IMM:%[0-9]+]]:sreg_32 = S_LOAD_U16_IMM [[REG_SEQUENCE]], 16, 0 :: (load (s32))
+    ; CHECK-NEXT: S_ENDPGM 0, implicit [[S_LOAD_U16_IMM]]
     %1:sgpr_32 = COPY $sgpr1
     %0:sgpr_32 = COPY $sgpr0
     %2:sreg_64 = REG_SEQUENCE %0, %subreg.sub0, %1, %subreg.sub1
@@ -63,9 +61,8 @@ body: |
     ; CHECK-NEXT: [[COPY:%[0-9]+]]:sgpr_32 = COPY $sgpr1
     ; CHECK-NEXT: [[COPY1:%[0-9]+]]:sgpr_32 = COPY $sgpr0
     ; CHECK-NEXT: [[REG_SEQUENCE:%[0-9]+]]:sreg_64 = REG_SEQUENCE [[COPY1]], %subreg.sub0, [[COPY]], %subreg.sub1
-    ; CHECK-NEXT: [[S_LOAD_DWORD_IMM:%[0-9]+]]:sreg_32_xm0_xexec = S_LOAD_DWORD_IMM [[REG_SEQUENCE]], 16, 0 :: (load (s32))
-    ; CHECK-NEXT: [[S_SEXT_I32_I8_:%[0-9]+]]:sreg_32 = S_SEXT_I32_I8 [[S_LOAD_DWORD_IMM]]
-    ; CHECK-NEXT: S_ENDPGM 0, implicit [[S_SEXT_I32_I8_]]
+    ; CHECK-NEXT: [[S_LOAD_I8_IMM:%[0-9]+]]:sreg_32 = S_LOAD_I8_IMM [[REG_SEQUENCE]], 16, 0 :: (load (s32))
+    ; CHECK-NEXT: S_ENDPGM 0, implicit [[S_LOAD_I8_IMM]]
     %1:sgpr_32 = COPY $sgpr1
     %0:sgpr_32 = COPY $sgpr0
     %2:sreg_64 = REG_SEQUENCE %0, %subreg.sub0, %1, %subreg.sub1
@@ -86,9 +83,8 @@ body: |
     ; CHECK-NEXT: [[COPY:%[0-9]+]]:sgpr_32 = COPY $sgpr1
     ; CHECK-NEXT: [[COPY1:%[0-9]+]]:sgpr_32 = COPY $sgpr0
     ; CHECK-NEXT: [[REG_SEQUENCE:%[0-9]+]]:sreg_64 = REG_SEQUENCE [[COPY1]], %subreg.sub0, [[COPY]], %subreg.sub1
-    ; CHECK-NEXT: [[S_LOAD_DWORD_IMM:%[0-9]+]]:sreg_32_xm0_xexec = S_LOAD_DWORD_IMM [[REG_SEQUENCE]], 16, 0 :: (load (s32))
-    ; CHECK-NEXT: [[S_SEXT_I32_I16_:%[0-9]+]]:sreg_32 = S_SEXT_I32_I16 [[S_LOAD_DWORD_IMM]]
-    ; CHECK-NEXT: S_ENDPGM 0, implicit [[S_SEXT_I32_I16_]]
+    ; CHECK-NEXT: [[S_LOAD_I16_IMM:%[0-9]+]]:sreg_32 = S_LOAD_I16_IMM [[REG_SEQUENCE]], 16, 0 :: (load (s32))
+    ; CHECK-NEXT: S_ENDPGM 0, implicit [[S_LOAD_I16_IMM]]
     %1:sgpr_32 = COPY $sgpr1
     %0:sgpr_32 = COPY $sgpr0
     %2:sreg_64 = REG_SEQUENCE %0, %subreg.sub0, %1, %subreg.sub1
@@ -110,9 +106,8 @@ body: |
     ; CHECK-NEXT: [[COPY1:%[0-9]+]]:sgpr_32 = COPY $sgpr1
     ; CHECK-NEXT: [[COPY2:%[0-9]+]]:sgpr_32 = COPY $sgpr0
     ; CHECK-NEXT: [[REG_SEQUENCE:%[0-9]+]]:sreg_64 = REG_SEQUENCE [[COPY2]], %subreg.sub0, [[COPY1]], %subreg.sub1
-    ; CHECK-NEXT: [[S_LOAD_DWORD_SGPR:%[0-9]+]]:sreg_32_xm0_xexec = S_LOAD_DWORD_SGPR [[REG_SEQUENCE]], [[COPY]], 0 :: (load (s32))
-    ; CHECK-NEXT: [[S_AND_B32_:%[0-9]+]]:sreg_32 = S_AND_B32 [[S_LOAD_DWORD_SGPR]], 255, implicit-def $scc
-    ; CHECK-NEXT: S_ENDPGM 0, implicit [[S_AND_B32_]]
+    ; CHECK-NEXT: [[S_LOAD_U8_SGPR:%[0-9]+]]:sreg_32 = S_LOAD_U8_SGPR [[REG_SEQUENCE]], [[COPY]], 0 :: (load (s32))
+    ; CHECK-NEXT: S_ENDPGM 0, implicit [[S_LOAD_U8_SGPR]]
     %2:sgpr_32 = COPY $sgpr2
     %1:sgpr_32 = COPY $sgpr1
     %0:sgpr_32 = COPY $sgpr0
@@ -135,9 +130,8 @@ body: |
     ; CHECK-NEXT: [[COPY1:%[0-9]+]]:sgpr_32 = COPY $sgpr1
     ; CHECK-NEXT: [[COPY2:%[0-9]+]]:sgpr_32 = COPY $sgpr0
     ; CHECK-NEXT: [[REG_SEQUENCE:%[0-9]+]]:sreg_64 = REG_SEQUENCE [[COPY2]], %subreg.sub0, [[COPY1]], %subreg.sub1
-    ; CHECK-NEXT: [[S_LOAD_DWORD_SGPR:%[0-9]+]]:sreg_32_xm0_xexec = S_LOAD_DWORD_SGPR [[REG_SEQUENCE]], [[COPY]], 0 :: (load (s32))
-    ; CHECK-NEXT: [[S_AND_B32_:%[0-9]+]]:sreg_32 = S_AND_B32 [[S_LOAD_DWORD_SGPR]], 65535, implicit-def $scc
-    ; CHECK-NEXT: S_ENDPGM 0, implicit [[S_AND_B32_]]
+    ; CHECK-NEXT: [[S_LOAD_U16_SGPR:%[0-9]+]]:sreg_32 = S_LOAD_U16_SGPR [[REG_SEQUENCE]], [[COPY]], 0 :: (load (s32))
+    ; CHECK-NEXT: S_ENDPGM 0, implicit [[S_LOAD_U16_SGPR]]
     %2:sgpr_32 = COPY $sgpr2
     %1:sgpr_32 = COPY $sgpr1
     %0:sgpr_32 = COPY $sgpr0
@@ -160,9 +154,8 @@ body: |
     ; CHECK-NEXT: [[COPY1:%[0-9]+]]:sgpr_32 = COPY $sgpr1
     ; CHECK-NEXT: [[COPY2:%[0-9]+]]:sgpr_32 = COPY $sgpr0
     ; CHECK-NEXT: [[REG_SEQUENCE:%[0-9]+]]:sreg_64 = REG_SEQUENCE [[COPY2]], %subreg.sub0, [[COPY1]], %subreg.sub1
-    ; CHECK-NEXT: [[S_LOAD_DWORD_SGPR:%[0-9]+]]:sreg_32_xm0_xexec = S_LOAD_DWORD_SGPR [[REG_SEQUENCE]], [[COPY]], 0 :: (load (s32))
-    ; CHECK-NEXT: [[S_SEXT_I32_I8_:%[0-9]+]]:sreg_32 = S_SEXT_I32_I8 [[S_LOAD_DWORD_SGPR]]
-    ; CHECK-NEXT: S_ENDPGM 0, implicit [[S_SEXT_I32_I8_]]
+    ; CHECK-NEXT: [[S_LOAD_I8_SGPR:%[0-9]+]]:sreg_32 = S_LOAD_I8_SGPR [[REG_SEQUENCE]], [[COPY]], 0 :: (load (s32))
+    ; CHECK-NEXT: S_ENDPGM 0, implicit [[S_LOAD_I8_SGPR]]
     %2:sgpr_32 = COPY $sgpr2
     %1:sgpr_32 = COPY $sgpr1
     %0:sgpr_32 = COPY $sgpr0
@@ -185,9 +178,8 @@ body: |
     ; CHECK-NEXT: [[COPY1:%[0-9]+]]:sgpr_32 = COPY $sgpr1
     ; CHECK-NEXT: [[COPY2:%[0-9]+]]:sgpr_32 = COPY $sgpr0
     ; CHECK-NEXT: [[REG_SEQUENCE:%[0-9]+]]:sreg_64 = REG_SEQUENCE [[COPY2]], %subreg.sub0, [[COPY1]], %subreg.sub1
-    ; CHECK-NEXT: [[S_LOAD_DWORD_SGPR:%[0-9]+]]:sreg_32_xm0_xexec = S_LOAD_DWORD_SGPR [[REG_SEQUENCE]], [[COPY]], 0 :: (load (s32))
-    ; CHECK-NEXT: [[S_SEXT_I32_I16_:%[0-9]+]]:sreg_32 = S_SEXT_I32_I16 [[S_LOAD_DWORD_SGPR]]
-    ; CHECK-NEXT: S_ENDPGM 0, implicit [[S_SEXT_I32_I16_]]
+    ; CHECK-NEXT: [[S_LOAD_I16_SGPR:%[0-9]+]]:sreg_32 = S_LOAD_I16_SGPR [[REG_SEQUENCE]], [[COPY]], 0 :: (load (s32))
+    ; CHECK-NEXT: S_ENDPGM 0, implicit [[S_LOAD_I16_SGPR]]
     %2:sgpr_32 = COPY $sgpr2
     %1:sgpr_32 = COPY $sgpr1
     %0:sgpr_32 = COPY $sgpr0
@@ -211,9 +203,8 @@ body: |
     ; CHECK-NEXT: [[COPY2:%[0-9]+]]:sgpr_32 = COPY $sgpr1
     ; CHECK-NEXT: [[COPY3:%[0-9]+]]:sgpr_32 = COPY $sgpr0
     ; CHECK-NEXT: [[REG_SEQUENCE:%[0-9]+]]:sgpr_128 = REG_SEQUENCE [[COPY3]], %subreg.sub0, [[COPY2]], %subreg.sub1, [[COPY1]], %subreg.sub2, [[COPY]], %subreg.sub3
-    ; CHECK-NEXT: [[S_BUFFER_LOAD_DWORD_IMM:%[0-9]+]]:sreg_32_xm0_xexec = S_BUFFER_LOAD_DWORD_IMM [[REG_SEQUENCE]], 16, 0 :: (load (s32))
-    ; CHECK-NEXT: [[S_AND_B32_:%[0-9]+]]:sreg_32 = S_AND_B32 [[S_BUFFER_LOAD_DWORD_IMM]], 255, implicit-def $scc
-    ; CHECK-NEXT: S_ENDPGM 0, implicit [[S_AND_B32_]]
+    ; CHECK-NEXT: [[S_BUFFER_LOAD_U8_IMM:%[0-9]+]]:sreg_32 = S_BUFFER_LOAD_U8_IMM [[REG_SEQUENCE]], 16, 0 :: (load (s32))
+    ; CHECK-NEXT: S_ENDPGM 0, implicit [[S_BUFFER_LOAD_U8_IMM]]
     %3:sgpr_32 = COPY $sgpr3
     %2:sgpr_32 = COPY $sgpr2
     %1:sgpr_32 = COPY $sgpr1
@@ -238,9 +229,8 @@ body: |
     ; CHECK-NEXT: [[COPY2:%[0-9]+]]:sgpr_32 = COPY $sgpr1
     ; CHECK-NEXT: [[COPY3:%[0-9]+]]:sgpr_32 = COPY $sgpr0
     ; CHECK-NEXT: [[REG_SEQUENCE:%[0-9]+]]:sgpr_128 = REG_SEQUENCE [[COPY3]], %subreg.sub0, [[COPY2]], %subreg.sub1, [[COPY1]], %subreg.sub2, [[COPY]], %subreg.sub3
-    ; CHECK-NEXT: [[S_BUFFER_LOAD_DWORD_IMM:%[0-9]+]]:sreg_32_xm0_xexec = S_BUFFER_LOAD_DWORD_IMM [[REG_SEQUENCE]], 16, 0 :: (load (s32))
-    ; CHECK-NEXT: [[S_AND_B32_:%[0-9]+]]:sreg_32 = S_AND_B32 [[S_BUFFER_LOAD_DWORD_IMM]], 65535, implicit-def $scc
-    ; CHECK-NEXT: S_ENDPGM 0, implicit [[S_AND_B32_]]
+    ; CHECK-NEXT: [[S_BUFFER_LOAD_U16_IMM:%[0-9]+]]:sreg_32 = S_BUFFER_LOAD_U16_IMM [[REG_SEQUENCE]], 16, 0 :: (load (s32))
+    ; CHECK-NEXT: S_ENDPGM 0, implicit [[S_BUFFER_LOAD_U16_IMM]]
     %3:sgpr_32 = COPY $sgpr3
     %2:sgpr_32 = COPY $sgpr2
     %1:sgpr_32 = COPY $sgpr1
@@ -265,9 +255,8 @@ body: |
     ; CHECK-NEXT: [[COPY2:%[0-9]+]]:sgpr_32 = COPY $sgpr1
     ; CHECK-NEXT: [[COPY3:%[0-9]+]]:sgpr_32 = COPY $sgpr0
     ; CHECK-NEXT: [[REG_SEQUENCE:%[0-9]+]]:sgpr_128 = REG_SEQUENCE [[COPY3]], %subreg.sub0, [[COPY2]], %subreg.sub1, [[COPY1]], %subreg.sub2, [[COPY]], %subreg.sub3
-    ; CHECK-NEXT: [[S_BUFFER_LOAD_DWORD_IMM:%[0-9]+]]:sreg_32_xm0_xexec = S_BUFFER_LOAD_DWORD_IMM [[REG_SEQUENCE]], 16, 0 :: (load (s32))
-    ; CHECK-NEXT: [[S_SEXT_I32_I8_:%[0-9]+]]:sreg_32 = S_SEXT_I32_I8 [[S_BUFFER_LOAD_DWORD_IMM]]
-    ; CHECK-NEXT: S_ENDPGM 0, implicit [[S_SEXT_I32_I8_]]
+    ; CHECK-NEXT: [[S_BUFFER_LOAD_I8_IMM:%[0-9]+]]:sreg_32 = S_BUFFER_LOAD_I8_IMM [[REG_SEQUENCE]], 16, 0 :: (load (s32))
+    ; CHECK-NEXT: S_ENDPGM 0, implicit [[S_BUFFER_LOAD_I8_IMM]]
     %3:sgpr_32 = COPY $sgpr3
     %2:sgpr_32 = COPY $sgpr2
     %1:sgpr_32 = COPY $sgpr1
@@ -292,9 +281,8 @@ body: |
     ; CHECK-NEXT: [[COPY2:%[0-9]+]]:sgpr_32 = COPY $sgpr1
     ; CHECK-NEXT: [[COPY3:%[0-9]+]]:sgpr_32 = COPY $sgpr0
     ; CHECK-NEXT: [[REG_SEQUENCE:%[0-9]+]]:sgpr_128 = REG_SEQUENCE [[COPY3]], %subreg.sub0, [[COPY2]], %subreg.sub1, [[COPY1]], %subreg.sub2, [[COPY]], %subreg.sub3
-    ; CHECK-NEXT: [[S_BUFFER_LOAD_DWORD_IMM:%[0-9]+]]:sreg_32_xm0_xexec = S_BUFFER_LOAD_DWORD_IMM [[REG_SEQUENCE]], 16, 0 :: (load (s32))
-    ; CHECK-NEXT: [[S_SEXT_I32_I16_:%[0-9]+]]:sreg_32 = S_SEXT_I32_I16 [[S_BUFFER_LOAD_DWORD_IMM]]
-    ; CHECK-NEXT: S_ENDPGM 0, implicit [[S_SEXT_I32_I16_]]
+    ; CHECK-NEXT: [[S_BUFFER_LOAD_I16_IMM:%[0-9]+]]:sreg_32 = S_BUFFER_LOAD_I16_IMM [[REG_SEQUENCE]], 16, 0 :: (load (s32))
+    ; CHECK-NEXT: S_ENDPGM 0, implicit [[S_BUFFER_LOAD_I16_IMM]]
     %3:sgpr_32 = COPY $sgpr3
     %2:sgpr_32 = COPY $sgpr2
     %1:sgpr_32 = COPY $sgpr1
@@ -320,9 +308,8 @@ body: |
     ; CHECK-NEXT: [[COPY3:%[0-9]+]]:sgpr_32 = COPY $sgpr1
     ; CHECK-NEXT: [[COPY4:%[0-9]+]]:sgpr_32 = COPY $sgpr0
     ; CHECK-NEXT: [[REG_SEQUENCE:%[0-9]+]]:sgpr_128 = REG_SEQUENCE [[COPY4]], %subreg.sub0, [[COPY3]], %subreg.sub1, [[COPY2]], %subreg.sub2, [[COPY1]], %subreg.sub3
-    ; CHECK-NEXT: [[S_BUFFER_LOAD_DWORD_SGPR:%[0-9]+]]:sreg_32_xm0_xexec = S_BUFFER_LOAD_DWORD_SGPR [[REG_SEQUENCE]], [[COPY]], 0 :: (load (s32))
-    ; CHECK-NEXT: [[S_AND_B32_:%[0-9]+]]:sreg_32 = S_AND_B32 [[S_BUFFER_LOAD_DWORD_SGPR]], 255, implicit-def $scc
-    ; CHECK-NEXT: S_ENDPGM 0, implicit [[S_AND_B32_]]
+    ; CHECK-NEXT: [[S_BUFFER_LOAD_U8_SGPR:%[0-9]+]]:sreg_32 = S_BUFFER_LOAD_U8_SGPR [[REG_SEQUENCE]], [[COPY]], 0 :: (load (s32))
+    ; CHECK-NEXT: S_ENDPGM 0, implicit [[S_BUFFER_LOAD_U8_SGPR]]
     %4:sgpr_32 = COPY $sgpr4
     %3:sgpr_32 = COPY $sgpr3
     %2:sgpr_32 = COPY $sgpr2
@@ -349,9 +336,8 @@ body: |
     ; CHECK-NEXT: [[COPY3:%[0-9]+]]:sgpr_32 = COPY $sgpr1
     ; CHECK-NEXT: [[COPY4:%[0-9]+]]:sgpr_32 = COPY $sgpr0
     ; CHECK-NEXT: [[REG_SEQUENCE:%[0-9]+]]:sgpr_128 = REG_SEQUENCE [[COPY4]], %subreg.sub0, [[COPY3]], %subreg.sub1, [[COPY2]], %subreg.sub2, [[COPY1]], %subreg.sub3
-    ; CHECK-NEXT: [[S_BUFFER_LOAD_DWORD_SGPR:%[0-9]+]]:sreg_32_xm0_xexec = S_BUFFER_LOAD_DWORD_SGPR [[REG_SEQUENCE]], [[COPY]], 0 :: (load (s32))
-    ; CHECK-NEXT: [[S_AND_B32_:%[0-9]+]]:sreg_32 = S_AND_B32 [[S_BUFFER_LOAD_DWORD_SGPR]], 65535, implicit-def $scc
-    ; CHECK-NEXT: S_ENDPGM 0, implicit [[S_AND_B32_]]
+    ; CHECK-NEXT: [[S_BUFFER_LOAD_U16_SGPR:%[0-9]+]]:sreg_32 = S_BUFFER_LOAD_U16_SGPR [[REG_SEQUENCE]], [[COPY]], 0 :: (load (s32))
+    ; CHECK-NEXT: S_ENDPGM 0, implicit [[S_BUFFER_LOAD_U16_SGPR]]
     %4:sgpr_32 = COPY $sgpr4
     %3:sgpr_32 = COPY $sgpr3
     %2:sgpr_32 = COPY $sgpr2
@@ -378,9 +364,8 @@ body: |
     ; CHECK-NEXT: [[COPY3:%[0-9]+]]:sgpr_32 = COPY $sgpr1
     ; CHECK-NEXT: [[COPY4:%[0-9]+]]:sgpr_32 = COPY $sgpr0
     ; CHECK-NEXT: [[REG_SEQUENCE:%[0-9]+]]:sgpr_128 = REG_SEQUENCE [[COPY4]], %subreg.sub0, [[COPY3]], %subreg.sub1, [[COPY2]], %subreg.sub2, [[COPY1]], %subreg.sub3
-    ; CHECK-NEXT: [[S_BUFFER_LOAD_DWORD_SGPR:%[0-9]+]]:sreg_32_xm0_xexec = S_BUFFER_LOAD_DWORD_SGPR [[REG_SEQUENCE]], [[COPY]], 0 :: (load (s32))
-    ; CHECK-NEXT: [[S_SEXT_I32_I8_:%[0-9]+]]:sreg_32 = S_SEXT_I32_I8 [[S_BUFFER_LOAD_DWORD_SGPR]]
-    ; CHECK-NEXT: S_ENDPGM 0, implicit [[S_SEXT_I32_I8_]]
+    ; CHECK-NEXT: [[S_BUFFER_LOAD_I8_SGPR:%[0-9]+]]:sreg_32 = S_BUFFER_LOAD_I8_SGPR [[REG_SEQUENCE]], [[COPY]], 0 :: (load (s32))
+    ; CHECK-NEXT: S_ENDPGM 0, implicit [[S_BUFFER_LOAD_I8_SGPR]]
     %4:sgpr_32 = COPY $sgpr4
     %3:sgpr_32 = COPY $sgpr3
     %2:sgpr_32 = COPY $sgpr2
@@ -407,9 +392,8 @@ body: |
     ; CHECK-NEXT: [[COPY3:%[0-9]+]]:sgpr_32 = COPY $sgpr1
     ; CHECK-NEXT: [[COPY4:%[0-9]+]]:sgpr_32 = COPY $sgpr0
     ; CHECK-NEXT: [[REG_SEQUENCE:%[0-9]+]]:sgpr_128 = REG_SEQUENCE [[COPY4]], %subreg.sub0, [[COPY3]], %subreg.sub1, [[COPY2]], %subreg.sub2, [[COPY1]], %subreg.sub3
-    ; CHECK-NEXT: [[S_BUFFER_LOAD_DWORD_SGPR:%[0-9]+]]:sreg_32_xm0_xexec = S_BUFFER_LOAD_DWORD_SGPR [[REG_SEQUENCE]], [[COPY]], 0 :: (load (s32))
-    ; CHECK-NEXT: [[S_SEXT_I32_I16_:%[0-9]+]]:sreg_32 = S_SEXT_I32_I16 [[S_BUFFER_LOAD_DWORD_SGPR]]
-    ; CHECK-NEXT: S_ENDPGM 0, implicit [[S_SEXT_I32_I16_]]
+    ; CHECK-NEXT: [[S_BUFFER_LOAD_I16_SGPR:%[0-9]+]]:sreg_32 = S_BUFFER_LOAD_I16_SGPR [[REG_SEQUENCE]], [[COPY]], 0 :: (load (s32))
+    ; CHECK-NEXT: S_ENDPGM 0, implicit [[S_BUFFER_LOAD_I16_SGPR]]
     %4:sgpr_32 = COPY $sgpr4
     %3:sgpr_32 = COPY $sgpr3
     %2:sgpr_32 = COPY $sgpr2
@@ -436,9 +420,8 @@ body: |
     ; CHECK-NEXT: [[COPY3:%[0-9]+]]:sgpr_32 = COPY $sgpr1
     ; CHECK-NEXT: [[COPY4:%[0-9]+]]:sgpr_32 = COPY $sgpr0
     ; CHECK-NEXT: [[REG_SEQUENCE:%[0-9]+]]:sgpr_128 = REG_SEQUENCE [[COPY4]], %subreg.sub0, [[COPY3]], %subreg.sub1, [[COPY2]], %subreg.sub2, [[COPY1]], %subreg.sub3
-    ; CHECK-NEXT: [[S_BUFFER_LOAD_DWORD_SGPR_IMM:%[0-9]+]]:sreg_32_xm0_xexec = S_BUFFER_LOAD_DWORD_SGPR_IMM [[REG_SEQUENCE]], [[COPY]], 16, 0 :: (load (s32))
-    ; CHECK-NEXT: [[S_AND_B32_:%[0-9]+]]:sreg_32 = S_AND_B32 [[S_BUFFER_LOAD_DWORD_SGPR_IMM]], 255, implicit-def $scc
-    ; CHECK-NEXT: S_ENDPGM 0, implicit [[S_AND_B32_]]
+    ; CHECK-NEXT: [[S_BUFFER_LOAD_U8_SGPR_IMM:%[0-9]+]]:sreg_32 = S_BUFFER_LOAD_U8_SGPR_IMM [[REG_SEQUENCE]], [[COPY]], 16, 0 :: (load (s32))
+    ; CHECK-NEXT: S_ENDPGM 0, implicit [[S_BUFFER_LOAD_U8_SGPR_IMM]]
     %4:sgpr_32 = COPY $sgpr4
     %3:sgpr_32 = COPY $sgpr3
     %2:sgpr_32 = COPY $sgpr2
@@ -465,9 +448,8 @@ body: |
     ; CHECK-NEXT: [[COPY3:%[0-9]+]]:sgpr_32 = COPY $sgpr1
     ; CHECK-NEXT: [[COPY4:%[0-9]+]]:sgpr_32 = COPY $sgpr0
     ; CHECK-NEXT: [[REG_SEQUENCE:%[0-9]+]]:sgpr_128 = REG_SEQUENCE [[COPY4]], %subreg.sub0, [[COPY3]], %subreg.sub1, [[COPY2]], %subreg.sub2, [[COPY1]], %subreg.sub3
-    ; CHECK-NEXT: [[S_BUFFER_LOAD_DWORD_SGPR_IMM:%[0-9]+]]:sreg_32_xm0_xexec = S_BUFFER_LOAD_DWORD_SGPR_IMM [[REG_SEQUENCE]], [[COPY]], 16, 0 :: (load (s32))
-    ; CHECK-NEXT: [[S_AND_B32_:%[0-9]+]]:sreg_32 = S_AND_B32 [[S_BUFFER_LOAD_DWORD_SGPR_IMM]], 65535, implicit-def $scc
-    ; CHECK-NEXT: S_ENDPGM 0, implicit [[S_AND_B32_]]
+    ; CHECK-NEXT: [[S_BUFFER_LOAD_U16_SGPR_IMM:%[0-9]+]]:sreg_32 = S_BUFFER_LOAD_U16_SGPR_IMM [[REG_SEQUENCE]], [[COPY]], 16, 0 :: (load (s32))
+    ; CHECK-NEXT: S_ENDPGM 0, implicit [[S_BUFFER_LOAD_U16_SGPR_IMM]]
     %4:sgpr_32 = COPY $sgpr4
     %3:sgpr_32 = COPY $sgpr3
     %2:sgpr_32 = COPY $sgpr2
@@ -494,9 +476,8 @@ body: |
     ; CHECK-NEXT: [[COPY3:%[0-9]+]]:sgpr_32 = COPY $sgpr1
     ; CHECK-NEXT: [[COPY4:%[0-9]+]]:sgpr_32 = COPY $sgpr0
     ; CHECK-NEXT: [[REG_SEQUENCE:%[0-9]+]]:sgpr_128 = REG_SEQUENCE [[COPY4]], %subreg.sub0, [[COPY3]], %subreg.sub1, [[COPY2]], %subreg.sub2, [[COPY1]], %subreg.sub3
-    ; CHECK-NEXT: [[S_BUFFER_LOAD_DWORD_SGPR_IMM:%[0-9]+]]:sreg_32_xm0_xexec = S_BUFFER_LOAD_DWORD_SGPR_IMM [[REG_SEQUENCE]], [[COPY]], 16, 0 :: (load (s32))
-    ; CHECK-NEXT: [[S_SEXT_I32_I8_:%[0-9]+]]:sreg_32 = S_SEXT_I32_I8 [[S_BUFFER_LOAD_DWORD_SGPR_IMM]]
-    ; CHECK-NEXT: S_ENDPGM 0, implicit [[S_SEXT_I32_I8_]]
+    ; CHECK-NEXT: [[S_BUFFER_LOAD_I8_SGPR_IMM:%[0-9]+]]:sreg_32 = S_BUFFER_LOAD_I8_SGPR_IMM [[REG_SEQUENCE]], [[COPY]], 16, 0 :: (load (s32))
+    ; CHECK-NEXT: S_ENDPGM 0, implicit [[S_BUFFER_LOAD_I8_SGPR_IMM]]
     %4:sgpr_32 = COPY $sgpr4
     %3:sgpr_32 = COPY $sgpr3
     %2:sgpr_32 = COPY $sgpr2
@@ -523,9 +504,8 @@ body: |
     ; CHECK-NEXT: [[COPY3:%[0-9]+]]:sgpr_32 = COPY $sgpr1
     ; CHECK-NEXT: [[COPY4:%[0-9]+]]:sgpr_32 = COPY $sgpr0
     ; CHECK-NEXT: [[REG_SEQUENCE:%[0-9]+]]:sgpr_128 = REG_SEQUENCE [[COPY4]], %subreg.sub0, [[COPY3]], %subreg.sub1, [[COPY2]], %subreg.sub2, [[COPY1]], %subreg.sub3
-    ; CHECK-NEXT: [[S_BUFFER_LOAD_DWORD_SGPR_IMM:%[0-9]+]]:sreg_32_xm0_xexec = S_BUFFER_LOAD_DWORD_SGPR_IMM [[REG_SEQUENCE]], [[COPY]], 16, 0 :: (load (s32))
-    ; CHECK-NEXT: [[S_SEXT_I32_I16_:%[0-9]+]]:sreg_32 = S_SEXT_I32_I16 [[S_BUFFER_LOAD_DWORD_SGPR_IMM]]
-    ; CHECK-NEXT: S_ENDPGM 0, implicit [[S_SEXT_I32_I16_]]
+    ; CHECK-NEXT: [[S_BUFFER_LOAD_I16_SGPR_IMM:%[0-9]+]]:sreg_32 = S_BUFFER_LOAD_I16_SGPR_IMM [[REG_SEQUENCE]], [[COPY]], 16, 0 :: (load (s32))
+    ; CHECK-NEXT: S_ENDPGM 0, implicit [[S_BUFFER_LOAD_I16_SGPR_IMM]]
     %4:sgpr_32 = COPY $sgpr4
     %3:sgpr_32 = COPY $sgpr3
     %2:sgpr_32 = COPY $sgpr2



More information about the llvm-commits mailing list