[llvm] [AMDGPU] Make `(v2i32 (trunc v2i64:$a))` legal (PR #207761)

Juan Manuel Martinez CaamaƱo via llvm-commits llvm-commits at lists.llvm.org
Fri Jul 10 05:32:56 PDT 2026


https://github.com/jmmartinez updated https://github.com/llvm/llvm-project/pull/207761

>From 14c7ce30ab096735324892027a8cddc284e886d7 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Juan=20Manuel=20Martinez=20Caama=C3=B1o?=
 <jmartinezcaamao at gmail.com>
Date: Mon, 6 Jul 2026 17:19:27 +0200
Subject: [PATCH 01/10] [AMDGPU] Pre-commit test

---
 .../CodeGen/AMDGPU/packed_shl64_combine.ll    | 117 ++++++++++++++++++
 1 file changed, 117 insertions(+)
 create mode 100644 llvm/test/CodeGen/AMDGPU/packed_shl64_combine.ll

diff --git a/llvm/test/CodeGen/AMDGPU/packed_shl64_combine.ll b/llvm/test/CodeGen/AMDGPU/packed_shl64_combine.ll
new file mode 100644
index 0000000000000..a48739f3793f8
--- /dev/null
+++ b/llvm/test/CodeGen/AMDGPU/packed_shl64_combine.ll
@@ -0,0 +1,117 @@
+; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py UTC_ARGS: --version 6
+; RUN: llc -mtriple=amdgcn-amd-amdhsa -mcpu=gfx1251 < %s | FileCheck %s
+
+define amdgpu_kernel void @kernel_2xi64(<2 x i64> %arg) {
+; CHECK-LABEL: kernel_2xi64:
+; 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_load_b128 s[0:3], s[4:5], 0x0 nv
+; CHECK-NEXT:    s_wait_kmcnt 0x0
+; CHECK-NEXT:    s_lshl_b64 s[0:1], s[0:1], 32
+; CHECK-NEXT:    s_delay_alu instid0(SALU_CYCLE_1) | instskip(SKIP_2) | instid1(VALU_DEP_1)
+; CHECK-NEXT:    s_lshl_b64 s[2:3], s[2:3], s0
+; CHECK-NEXT:    v_mov_b64_e32 v[0:1], s[0:1]
+; CHECK-NEXT:    v_mov_b64_e32 v[2:3], s[2:3]
+; CHECK-NEXT:    v_pk_add_f64 v[0:3], v[0:3], 1.0
+; CHECK-NEXT:    s_delay_alu instid0(VALU_DEP_1) | instskip(SKIP_1) | instid1(VALU_DEP_2)
+; CHECK-NEXT:    v_pk_add_f64 v[0:3], v[0:3], 1.0
+; CHECK-NEXT:    v_mov_b64_e32 v[2:3], 0
+; CHECK-NEXT:    v_ashrrev_i32_e32 v1, 31, v0
+; CHECK-NEXT:    global_store_b64 v[2:3], v[0:1], off
+; CHECK-NEXT:    s_endpgm
+  %i = shl <2 x i64> %arg, <i64 32, i64 31>
+  %i1 = bitcast <2 x i64> %i to <2 x double>
+  %i2 = fadd <2 x double> %i1, zeroinitializer
+  %i3 = fadd <2 x double> %i2, splat (double 1.000000e+00)
+  %i4 = fadd <2 x double> %i3, splat (double 1.000000e+00)
+  %i5 = bitcast <2 x double> %i4 to <4 x i32>
+  %i6 = extractelement <4 x i32> %i5, i64 0
+  %i7 = sext i32 %i6 to i64
+  store i64 %i7, ptr addrspace(1) null, align 8
+  ret void
+}
+
+define amdgpu_kernel void @kernel_4xi64(<4 x i64> %arg) {
+; CHECK-LABEL: kernel_4xi64:
+; 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_load_b32 s1, s[4:5], 0x0 nv
+; CHECK-NEXT:    s_mov_b32 s0, 0
+; CHECK-NEXT:    v_mov_b64_e32 v[2:3], 0
+; CHECK-NEXT:    s_wait_kmcnt 0x0
+; CHECK-NEXT:    v_mov_b64_e32 v[0:1], s[0:1]
+; CHECK-NEXT:    s_delay_alu instid0(VALU_DEP_1) | instskip(NEXT) | instid1(VALU_DEP_1)
+; CHECK-NEXT:    v_pk_add_f64 v[0:3], v[0:3], 1.0
+; CHECK-NEXT:    v_pk_add_f64 v[0:3], v[0:3], 1.0
+; CHECK-NEXT:    v_mov_b64_e32 v[2:3], 0
+; CHECK-NEXT:    s_delay_alu instid0(VALU_DEP_2)
+; CHECK-NEXT:    v_ashrrev_i32_e32 v1, 31, v0
+; CHECK-NEXT:    global_store_b64 v[2:3], v[0:1], off
+; CHECK-NEXT:    s_endpgm
+  %i = shl <4 x i64> %arg, <i64 32, i64 32, i64 32, i64 31>
+  %i1 = bitcast <4 x i64> %i to <4 x double>
+  %i2 = fadd <4 x double> %i1, zeroinitializer
+  %i3 = fadd <4 x double> %i2, splat (double 1.000000e+00)
+  %i4 = fadd <4 x double> %i3, splat (double 1.000000e+00)
+  %i5 = bitcast <4 x double> %i4 to <8 x i32>
+  %i6 = extractelement <8 x i32> %i5, i64 0
+  %i7 = sext i32 %i6 to i64
+  store i64 %i7, ptr addrspace(1) null, align 8
+  ret void
+}
+
+define amdgpu_kernel void @kernel_8xi64(<8 x i64> %arg) {
+; CHECK-LABEL: kernel_8xi64:
+; 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_load_b128 s[0:3], s[4:5], 0x0 nv
+; CHECK-NEXT:    s_wait_kmcnt 0x0
+; CHECK-NEXT:    v_dual_mov_b32 v0, 0 :: v_dual_mov_b32 v1, s0
+; CHECK-NEXT:    s_delay_alu instid0(VALU_DEP_1) | instskip(NEXT) | instid1(VALU_DEP_1)
+; CHECK-NEXT:    v_dual_mov_b32 v2, v0 :: v_dual_mov_b32 v3, s2
+; CHECK-NEXT:    v_pk_add_f64 v[0:3], v[0:3], 1.0
+; CHECK-NEXT:    s_delay_alu instid0(VALU_DEP_1) | instskip(SKIP_1) | instid1(VALU_DEP_2)
+; CHECK-NEXT:    v_pk_add_f64 v[0:3], v[0:3], 1.0
+; CHECK-NEXT:    v_mov_b64_e32 v[2:3], 0
+; CHECK-NEXT:    v_ashrrev_i32_e32 v1, 31, v0
+; CHECK-NEXT:    global_store_b64 v[2:3], v[0:1], off
+; CHECK-NEXT:    s_endpgm
+  %i = shl <8 x i64> %arg, <i64 32, i64 32, i64 32, i64 32, i64 32, i64 32, i64 32, i64 31>
+  %i1 = bitcast <8 x i64> %i to <8 x double>
+  %i2 = fadd <8 x double> %i1, zeroinitializer
+  %i3 = fadd <8 x double> %i2, splat (double 1.000000e+00)
+  %i4 = fadd <8 x double> %i3, splat (double 1.000000e+00)
+  %i5 = bitcast <8 x double> %i4 to <16 x i32>
+  %i6 = extractelement <16 x i32> %i5, i64 0
+  %i7 = sext i32 %i6 to i64
+  store i64 %i7, ptr addrspace(1) null, align 8
+  ret void
+}
+
+define amdgpu_kernel void @kernel_16xi64(<16 x i64> %arg) {
+; CHECK-LABEL: kernel_16xi64:
+; 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_load_b128 s[0:3], s[4:5], 0x0 nv
+; CHECK-NEXT:    s_wait_kmcnt 0x0
+; CHECK-NEXT:    v_dual_mov_b32 v0, 0 :: v_dual_mov_b32 v1, s0
+; CHECK-NEXT:    s_delay_alu instid0(VALU_DEP_1) | instskip(NEXT) | instid1(VALU_DEP_1)
+; CHECK-NEXT:    v_dual_mov_b32 v2, v0 :: v_dual_mov_b32 v3, s2
+; CHECK-NEXT:    v_pk_add_f64 v[0:3], v[0:3], 1.0
+; CHECK-NEXT:    s_delay_alu instid0(VALU_DEP_1) | instskip(SKIP_1) | instid1(VALU_DEP_2)
+; CHECK-NEXT:    v_pk_add_f64 v[0:3], v[0:3], 1.0
+; CHECK-NEXT:    v_mov_b64_e32 v[2:3], 0
+; CHECK-NEXT:    v_ashrrev_i32_e32 v1, 31, v0
+; CHECK-NEXT:    global_store_b64 v[2:3], v[0:1], off
+; CHECK-NEXT:    s_endpgm
+  %i = shl <16 x i64> %arg, <i64 32, i64 32, i64 32, i64 32, i64 32, i64 32, i64 32, i64 32, i64 32, i64 32, i64 32, i64 32, i64 32, i64 32, i64 32, i64 31>
+  %i1 = bitcast <16 x i64> %i to <16 x double>
+  %i2 = fadd <16 x double> %i1, zeroinitializer
+  %i3 = fadd <16 x double> %i2, splat (double 1.000000e+00)
+  %i4 = fadd <16 x double> %i3, splat (double 1.000000e+00)
+  %i5 = bitcast <16 x double> %i4 to <32 x i32>
+  %i6 = extractelement <32 x i32> %i5, i64 0
+  %i7 = sext i32 %i6 to i64
+  store i64 %i7, ptr addrspace(1) null, align 8
+  ret void
+}

>From c26a0f56496fbd623500d1b8f1c6705b6a2147a9 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Juan=20Manuel=20Martinez=20Caama=C3=B1o?=
 <jmartinezcaamao at gmail.com>
Date: Mon, 6 Jul 2026 17:21:25 +0200
Subject: [PATCH 02/10] [AMDGPU] Unroll illegal vector TRUNCATE after
 legalization

`performShlCombine` introduced a `v2i32 truncate x:v2i64`. This
pattern is not legal, and is normally expanded by the legalizer.

However, since the combine is done after legalization the illegal
pattern remains.

This happens on gfx1251 since it has legal `shl v2i64` instructions.
---
 llvm/lib/Target/AMDGPU/AMDGPUISelLowering.cpp | 8 ++++++++
 1 file changed, 8 insertions(+)

diff --git a/llvm/lib/Target/AMDGPU/AMDGPUISelLowering.cpp b/llvm/lib/Target/AMDGPU/AMDGPUISelLowering.cpp
index ccf73a6aeef84..ee9971993eb45 100644
--- a/llvm/lib/Target/AMDGPU/AMDGPUISelLowering.cpp
+++ b/llvm/lib/Target/AMDGPU/AMDGPUISelLowering.cpp
@@ -4739,6 +4739,14 @@ SDValue AMDGPUTargetLowering::performTruncateCombine(
     }
   }
 
+  // Unroll illegal vector truncate: This is normally done by the legalizer,
+  // however patterns introduced by the dag combiner may reintroduce the illegal
+  // pattern.
+  if (DCI.isAfterLegalizeDAG() && VT.isVector() &&
+      isOperationExpand(ISD::TRUNCATE, VT)) {
+    return DAG.UnrollVectorOp(N);
+  }
+
   return SDValue();
 }
 

>From fe066898769e9cced7516f4e20d0daaec8e6e374 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Juan=20Manuel=20Martinez=20Caama=C3=B1o?=
 <jmartinezcaamao at gmail.com>
Date: Tue, 7 Jul 2026 13:56:29 +0200
Subject: [PATCH 03/10] [Review] Move the unroll to avoid generating the
 illegal pattern in the first place

---
 llvm/lib/Target/AMDGPU/AMDGPUISelLowering.cpp | 14 ++++++--------
 1 file changed, 6 insertions(+), 8 deletions(-)

diff --git a/llvm/lib/Target/AMDGPU/AMDGPUISelLowering.cpp b/llvm/lib/Target/AMDGPU/AMDGPUISelLowering.cpp
index ee9971993eb45..ed2b8cedc72fb 100644
--- a/llvm/lib/Target/AMDGPU/AMDGPUISelLowering.cpp
+++ b/llvm/lib/Target/AMDGPU/AMDGPUISelLowering.cpp
@@ -4417,6 +4417,12 @@ SDValue AMDGPUTargetLowering::performShlCombine(SDNode *N,
   }
 
   SDValue Lo = DAG.getNode(ISD::TRUNCATE, SL, TargetType, LHS);
+
+  // Unroll illegal vector truncate: This is normally done by the legalizer,
+  // but we might reintroduce the illegal pattern here.
+  if (DCI.isAfterLegalizeDAG() && TargetType.isVector())
+    Lo = DAG.UnrollVectorOp(Lo.getNode());
+
   SDValue NewShift =
       DAG.getNode(ISD::SHL, SL, TargetType, Lo, ShiftAmt, N->getFlags());
 
@@ -4739,14 +4745,6 @@ SDValue AMDGPUTargetLowering::performTruncateCombine(
     }
   }
 
-  // Unroll illegal vector truncate: This is normally done by the legalizer,
-  // however patterns introduced by the dag combiner may reintroduce the illegal
-  // pattern.
-  if (DCI.isAfterLegalizeDAG() && VT.isVector() &&
-      isOperationExpand(ISD::TRUNCATE, VT)) {
-    return DAG.UnrollVectorOp(N);
-  }
-
   return SDValue();
 }
 

>From aba078a240d4208c77ecb5f4d634d352fe9d8db3 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Juan=20Manuel=20Martinez=20Caama=C3=B1o?=
 <jmartinezcaamao at gmail.com>
Date: Tue, 7 Jul 2026 16:14:48 +0200
Subject: [PATCH 04/10] [Review] Remove amdgpu_kernel and make 2 variants,
 inreg/normal

---
 .../CodeGen/AMDGPU/packed_shl64_combine.ll    | 158 +++++++++++++++---
 1 file changed, 132 insertions(+), 26 deletions(-)

diff --git a/llvm/test/CodeGen/AMDGPU/packed_shl64_combine.ll b/llvm/test/CodeGen/AMDGPU/packed_shl64_combine.ll
index a48739f3793f8..e12e1dc84e290 100644
--- a/llvm/test/CodeGen/AMDGPU/packed_shl64_combine.ll
+++ b/llvm/test/CodeGen/AMDGPU/packed_shl64_combine.ll
@@ -1,11 +1,37 @@
 ; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py UTC_ARGS: --version 6
-; RUN: llc -mtriple=amdgcn-amd-amdhsa -mcpu=gfx1251 < %s | FileCheck %s
+; RUN: llc -mtriple=amdgcn-- -mcpu=gfx1251 < %s | FileCheck %s
 
-define amdgpu_kernel void @kernel_2xi64(<2 x i64> %arg) {
-; CHECK-LABEL: kernel_2xi64:
+define void @func_2xi64(<2 x i64> %arg) {
+; CHECK-LABEL: func_2xi64:
 ; 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_load_b128 s[0:3], s[4:5], 0x0 nv
+; CHECK-NEXT:    s_wait_loadcnt_dscnt 0x0
+; CHECK-NEXT:    s_wait_kmcnt 0x0
+; CHECK-NEXT:    v_lshlrev_b64_e32 v[2:3], s0, v[2:3]
+; CHECK-NEXT:    v_lshlrev_b64_e32 v[0:1], 32, v[0:1]
+; CHECK-NEXT:    s_delay_alu instid0(VALU_DEP_1) | instskip(NEXT) | instid1(VALU_DEP_1)
+; CHECK-NEXT:    v_pk_add_f64 v[0:3], v[0:3], 1.0
+; CHECK-NEXT:    v_pk_add_f64 v[0:3], v[0:3], 1.0
+; CHECK-NEXT:    v_mov_b64_e32 v[2:3], 0
+; CHECK-NEXT:    s_delay_alu instid0(VALU_DEP_2)
+; CHECK-NEXT:    v_ashrrev_i32_e32 v1, 31, v0
+; CHECK-NEXT:    global_store_b64 v[2:3], v[0:1], off
+; CHECK-NEXT:    s_set_pc_i64 s[30:31]
+  %i = shl <2 x i64> %arg, <i64 32, i64 31>
+  %i1 = bitcast <2 x i64> %i to <2 x double>
+  %i2 = fadd <2 x double> %i1, zeroinitializer
+  %i3 = fadd <2 x double> %i2, splat (double 1.000000e+00)
+  %i4 = fadd <2 x double> %i3, splat (double 1.000000e+00)
+  %i5 = bitcast <2 x double> %i4 to <4 x i32>
+  %i6 = extractelement <4 x i32> %i5, i64 0
+  %i7 = sext i32 %i6 to i64
+  store i64 %i7, ptr addrspace(1) null, align 8
+  ret void
+}
+
+define void @func_2xi64_inreg(<2 x i64> inreg %arg) {
+; CHECK-LABEL: func_2xi64_inreg:
+; CHECK:       ; %bb.0:
+; CHECK-NEXT:    s_wait_loadcnt_dscnt 0x0
 ; CHECK-NEXT:    s_wait_kmcnt 0x0
 ; CHECK-NEXT:    s_lshl_b64 s[0:1], s[0:1], 32
 ; CHECK-NEXT:    s_delay_alu instid0(SALU_CYCLE_1) | instskip(SKIP_2) | instid1(VALU_DEP_1)
@@ -18,7 +44,7 @@ define amdgpu_kernel void @kernel_2xi64(<2 x i64> %arg) {
 ; CHECK-NEXT:    v_mov_b64_e32 v[2:3], 0
 ; CHECK-NEXT:    v_ashrrev_i32_e32 v1, 31, v0
 ; CHECK-NEXT:    global_store_b64 v[2:3], v[0:1], off
-; CHECK-NEXT:    s_endpgm
+; CHECK-NEXT:    s_set_pc_i64 s[30:31]
   %i = shl <2 x i64> %arg, <i64 32, i64 31>
   %i1 = bitcast <2 x i64> %i to <2 x double>
   %i2 = fadd <2 x double> %i1, zeroinitializer
@@ -31,23 +57,49 @@ define amdgpu_kernel void @kernel_2xi64(<2 x i64> %arg) {
   ret void
 }
 
-define amdgpu_kernel void @kernel_4xi64(<4 x i64> %arg) {
-; CHECK-LABEL: kernel_4xi64:
+define void @func_4xi64(<4 x i64> %arg) {
+; CHECK-LABEL: func_4xi64:
 ; 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_load_b32 s1, s[4:5], 0x0 nv
-; CHECK-NEXT:    s_mov_b32 s0, 0
+; CHECK-NEXT:    s_wait_loadcnt_dscnt 0x0
+; CHECK-NEXT:    s_wait_kmcnt 0x0
+; CHECK-NEXT:    v_dual_mov_b32 v3, v2 :: v_dual_mov_b32 v1, v0
+; CHECK-NEXT:    v_mov_b32_e32 v0, 0
+; CHECK-NEXT:    s_delay_alu instid0(VALU_DEP_1) | instskip(NEXT) | instid1(VALU_DEP_1)
+; CHECK-NEXT:    v_mov_b32_e32 v2, v0
+; CHECK-NEXT:    v_pk_add_f64 v[0:3], v[0:3], 1.0
+; CHECK-NEXT:    s_delay_alu instid0(VALU_DEP_1) | instskip(SKIP_1) | instid1(VALU_DEP_2)
+; CHECK-NEXT:    v_pk_add_f64 v[0:3], v[0:3], 1.0
 ; CHECK-NEXT:    v_mov_b64_e32 v[2:3], 0
+; CHECK-NEXT:    v_ashrrev_i32_e32 v1, 31, v0
+; CHECK-NEXT:    global_store_b64 v[2:3], v[0:1], off
+; CHECK-NEXT:    s_set_pc_i64 s[30:31]
+  %i = shl <4 x i64> %arg, <i64 32, i64 32, i64 32, i64 31>
+  %i1 = bitcast <4 x i64> %i to <4 x double>
+  %i2 = fadd <4 x double> %i1, zeroinitializer
+  %i3 = fadd <4 x double> %i2, splat (double 1.000000e+00)
+  %i4 = fadd <4 x double> %i3, splat (double 1.000000e+00)
+  %i5 = bitcast <4 x double> %i4 to <8 x i32>
+  %i6 = extractelement <8 x i32> %i5, i64 0
+  %i7 = sext i32 %i6 to i64
+  store i64 %i7, ptr addrspace(1) null, align 8
+  ret void
+}
+
+define void @func_4xi64_inreg(<4 x i64> inreg %arg) {
+; CHECK-LABEL: func_4xi64_inreg:
+; CHECK:       ; %bb.0:
+; CHECK-NEXT:    s_wait_loadcnt_dscnt 0x0
 ; CHECK-NEXT:    s_wait_kmcnt 0x0
-; CHECK-NEXT:    v_mov_b64_e32 v[0:1], s[0:1]
+; CHECK-NEXT:    v_dual_mov_b32 v0, 0 :: v_dual_mov_b32 v1, s0
 ; CHECK-NEXT:    s_delay_alu instid0(VALU_DEP_1) | instskip(NEXT) | instid1(VALU_DEP_1)
+; CHECK-NEXT:    v_dual_mov_b32 v3, s2 :: v_dual_mov_b32 v2, v0
 ; CHECK-NEXT:    v_pk_add_f64 v[0:3], v[0:3], 1.0
+; CHECK-NEXT:    s_delay_alu instid0(VALU_DEP_1) | instskip(SKIP_1) | instid1(VALU_DEP_2)
 ; CHECK-NEXT:    v_pk_add_f64 v[0:3], v[0:3], 1.0
 ; CHECK-NEXT:    v_mov_b64_e32 v[2:3], 0
-; CHECK-NEXT:    s_delay_alu instid0(VALU_DEP_2)
 ; CHECK-NEXT:    v_ashrrev_i32_e32 v1, 31, v0
 ; CHECK-NEXT:    global_store_b64 v[2:3], v[0:1], off
-; CHECK-NEXT:    s_endpgm
+; CHECK-NEXT:    s_set_pc_i64 s[30:31]
   %i = shl <4 x i64> %arg, <i64 32, i64 32, i64 32, i64 31>
   %i1 = bitcast <4 x i64> %i to <4 x double>
   %i2 = fadd <4 x double> %i1, zeroinitializer
@@ -60,22 +112,49 @@ define amdgpu_kernel void @kernel_4xi64(<4 x i64> %arg) {
   ret void
 }
 
-define amdgpu_kernel void @kernel_8xi64(<8 x i64> %arg) {
-; CHECK-LABEL: kernel_8xi64:
+define void @func_8xi64(<8 x i64> %arg) {
+; CHECK-LABEL: func_8xi64:
+; CHECK:       ; %bb.0:
+; CHECK-NEXT:    s_wait_loadcnt_dscnt 0x0
+; CHECK-NEXT:    s_wait_kmcnt 0x0
+; CHECK-NEXT:    v_dual_mov_b32 v3, v2 :: v_dual_mov_b32 v1, v0
+; CHECK-NEXT:    v_mov_b32_e32 v0, 0
+; CHECK-NEXT:    s_delay_alu instid0(VALU_DEP_1) | instskip(NEXT) | instid1(VALU_DEP_1)
+; CHECK-NEXT:    v_mov_b32_e32 v2, v0
+; CHECK-NEXT:    v_pk_add_f64 v[0:3], v[0:3], 1.0
+; CHECK-NEXT:    s_delay_alu instid0(VALU_DEP_1) | instskip(SKIP_1) | instid1(VALU_DEP_2)
+; CHECK-NEXT:    v_pk_add_f64 v[0:3], v[0:3], 1.0
+; CHECK-NEXT:    v_mov_b64_e32 v[2:3], 0
+; CHECK-NEXT:    v_ashrrev_i32_e32 v1, 31, v0
+; CHECK-NEXT:    global_store_b64 v[2:3], v[0:1], off
+; CHECK-NEXT:    s_set_pc_i64 s[30:31]
+  %i = shl <8 x i64> %arg, <i64 32, i64 32, i64 32, i64 32, i64 32, i64 32, i64 32, i64 31>
+  %i1 = bitcast <8 x i64> %i to <8 x double>
+  %i2 = fadd <8 x double> %i1, zeroinitializer
+  %i3 = fadd <8 x double> %i2, splat (double 1.000000e+00)
+  %i4 = fadd <8 x double> %i3, splat (double 1.000000e+00)
+  %i5 = bitcast <8 x double> %i4 to <16 x i32>
+  %i6 = extractelement <16 x i32> %i5, i64 0
+  %i7 = sext i32 %i6 to i64
+  store i64 %i7, ptr addrspace(1) null, align 8
+  ret void
+}
+
+define void @func_8xi64_inreg(<8 x i64> inreg %arg) {
+; CHECK-LABEL: func_8xi64_inreg:
 ; 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_load_b128 s[0:3], s[4:5], 0x0 nv
+; CHECK-NEXT:    s_wait_loadcnt_dscnt 0x0
 ; CHECK-NEXT:    s_wait_kmcnt 0x0
 ; CHECK-NEXT:    v_dual_mov_b32 v0, 0 :: v_dual_mov_b32 v1, s0
 ; CHECK-NEXT:    s_delay_alu instid0(VALU_DEP_1) | instskip(NEXT) | instid1(VALU_DEP_1)
-; CHECK-NEXT:    v_dual_mov_b32 v2, v0 :: v_dual_mov_b32 v3, s2
+; CHECK-NEXT:    v_dual_mov_b32 v3, s2 :: v_dual_mov_b32 v2, v0
 ; CHECK-NEXT:    v_pk_add_f64 v[0:3], v[0:3], 1.0
 ; CHECK-NEXT:    s_delay_alu instid0(VALU_DEP_1) | instskip(SKIP_1) | instid1(VALU_DEP_2)
 ; CHECK-NEXT:    v_pk_add_f64 v[0:3], v[0:3], 1.0
 ; CHECK-NEXT:    v_mov_b64_e32 v[2:3], 0
 ; CHECK-NEXT:    v_ashrrev_i32_e32 v1, 31, v0
 ; CHECK-NEXT:    global_store_b64 v[2:3], v[0:1], off
-; CHECK-NEXT:    s_endpgm
+; CHECK-NEXT:    s_set_pc_i64 s[30:31]
   %i = shl <8 x i64> %arg, <i64 32, i64 32, i64 32, i64 32, i64 32, i64 32, i64 32, i64 31>
   %i1 = bitcast <8 x i64> %i to <8 x double>
   %i2 = fadd <8 x double> %i1, zeroinitializer
@@ -88,22 +167,49 @@ define amdgpu_kernel void @kernel_8xi64(<8 x i64> %arg) {
   ret void
 }
 
-define amdgpu_kernel void @kernel_16xi64(<16 x i64> %arg) {
-; CHECK-LABEL: kernel_16xi64:
+define void @func_16xi64(<16 x i64> %arg) {
+; CHECK-LABEL: func_16xi64:
+; CHECK:       ; %bb.0:
+; CHECK-NEXT:    s_wait_loadcnt_dscnt 0x0
+; CHECK-NEXT:    s_wait_kmcnt 0x0
+; CHECK-NEXT:    v_dual_mov_b32 v3, v2 :: v_dual_mov_b32 v1, v0
+; CHECK-NEXT:    v_mov_b32_e32 v0, 0
+; CHECK-NEXT:    s_delay_alu instid0(VALU_DEP_1) | instskip(NEXT) | instid1(VALU_DEP_1)
+; CHECK-NEXT:    v_mov_b32_e32 v2, v0
+; CHECK-NEXT:    v_pk_add_f64 v[0:3], v[0:3], 1.0
+; CHECK-NEXT:    s_delay_alu instid0(VALU_DEP_1) | instskip(SKIP_1) | instid1(VALU_DEP_2)
+; CHECK-NEXT:    v_pk_add_f64 v[0:3], v[0:3], 1.0
+; CHECK-NEXT:    v_mov_b64_e32 v[2:3], 0
+; CHECK-NEXT:    v_ashrrev_i32_e32 v1, 31, v0
+; CHECK-NEXT:    global_store_b64 v[2:3], v[0:1], off
+; CHECK-NEXT:    s_set_pc_i64 s[30:31]
+  %i = shl <16 x i64> %arg, <i64 32, i64 32, i64 32, i64 32, i64 32, i64 32, i64 32, i64 32, i64 32, i64 32, i64 32, i64 32, i64 32, i64 32, i64 32, i64 31>
+  %i1 = bitcast <16 x i64> %i to <16 x double>
+  %i2 = fadd <16 x double> %i1, zeroinitializer
+  %i3 = fadd <16 x double> %i2, splat (double 1.000000e+00)
+  %i4 = fadd <16 x double> %i3, splat (double 1.000000e+00)
+  %i5 = bitcast <16 x double> %i4 to <32 x i32>
+  %i6 = extractelement <32 x i32> %i5, i64 0
+  %i7 = sext i32 %i6 to i64
+  store i64 %i7, ptr addrspace(1) null, align 8
+  ret void
+}
+
+define void @func_16xi64_inreg(<16 x i64> inreg %arg) {
+; CHECK-LABEL: func_16xi64_inreg:
 ; 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_load_b128 s[0:3], s[4:5], 0x0 nv
+; CHECK-NEXT:    s_wait_loadcnt_dscnt 0x0
 ; CHECK-NEXT:    s_wait_kmcnt 0x0
 ; CHECK-NEXT:    v_dual_mov_b32 v0, 0 :: v_dual_mov_b32 v1, s0
 ; CHECK-NEXT:    s_delay_alu instid0(VALU_DEP_1) | instskip(NEXT) | instid1(VALU_DEP_1)
-; CHECK-NEXT:    v_dual_mov_b32 v2, v0 :: v_dual_mov_b32 v3, s2
+; CHECK-NEXT:    v_dual_mov_b32 v3, s2 :: v_dual_mov_b32 v2, v0
 ; CHECK-NEXT:    v_pk_add_f64 v[0:3], v[0:3], 1.0
 ; CHECK-NEXT:    s_delay_alu instid0(VALU_DEP_1) | instskip(SKIP_1) | instid1(VALU_DEP_2)
 ; CHECK-NEXT:    v_pk_add_f64 v[0:3], v[0:3], 1.0
 ; CHECK-NEXT:    v_mov_b64_e32 v[2:3], 0
 ; CHECK-NEXT:    v_ashrrev_i32_e32 v1, 31, v0
 ; CHECK-NEXT:    global_store_b64 v[2:3], v[0:1], off
-; CHECK-NEXT:    s_endpgm
+; CHECK-NEXT:    s_set_pc_i64 s[30:31]
   %i = shl <16 x i64> %arg, <i64 32, i64 32, i64 32, i64 32, i64 32, i64 32, i64 32, i64 32, i64 32, i64 32, i64 32, i64 32, i64 32, i64 32, i64 32, i64 31>
   %i1 = bitcast <16 x i64> %i to <16 x double>
   %i2 = fadd <16 x double> %i1, zeroinitializer

>From 0217fcaed0b2f9c6dacb632839f9ffb2657f246c Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Juan=20Manuel=20Martinez=20Caama=C3=B1o?=
 <jmartinezcaamao at gmail.com>
Date: Thu, 9 Jul 2026 16:59:47 +0200
Subject: [PATCH 05/10] [Review] Reduced the test and renames

---
 .../CodeGen/AMDGPU/packed_shl64_combine.ll    | 283 +++++++-----------
 1 file changed, 111 insertions(+), 172 deletions(-)

diff --git a/llvm/test/CodeGen/AMDGPU/packed_shl64_combine.ll b/llvm/test/CodeGen/AMDGPU/packed_shl64_combine.ll
index e12e1dc84e290..1b758529b80ff 100644
--- a/llvm/test/CodeGen/AMDGPU/packed_shl64_combine.ll
+++ b/llvm/test/CodeGen/AMDGPU/packed_shl64_combine.ll
@@ -1,223 +1,162 @@
 ; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py UTC_ARGS: --version 6
 ; RUN: llc -mtriple=amdgcn-- -mcpu=gfx1251 < %s | FileCheck %s
 
-define void @func_2xi64(<2 x i64> %arg) {
-; CHECK-LABEL: func_2xi64:
+define <2 x i64> @func_v2i64(<2 x i64> %arg) {
+; CHECK-LABEL: func_v2i64:
 ; CHECK:       ; %bb.0:
 ; CHECK-NEXT:    s_wait_loadcnt_dscnt 0x0
 ; CHECK-NEXT:    s_wait_kmcnt 0x0
-; CHECK-NEXT:    v_lshlrev_b64_e32 v[2:3], s0, v[2:3]
 ; CHECK-NEXT:    v_lshlrev_b64_e32 v[0:1], 32, v[0:1]
-; CHECK-NEXT:    s_delay_alu instid0(VALU_DEP_1) | instskip(NEXT) | instid1(VALU_DEP_1)
-; CHECK-NEXT:    v_pk_add_f64 v[0:3], v[0:3], 1.0
-; CHECK-NEXT:    v_pk_add_f64 v[0:3], v[0:3], 1.0
-; CHECK-NEXT:    v_mov_b64_e32 v[2:3], 0
-; CHECK-NEXT:    s_delay_alu instid0(VALU_DEP_2)
-; CHECK-NEXT:    v_ashrrev_i32_e32 v1, 31, v0
-; CHECK-NEXT:    global_store_b64 v[2:3], v[0:1], off
+; CHECK-NEXT:    v_lshlrev_b64_e32 v[2:3], 31, v[2:3]
 ; CHECK-NEXT:    s_set_pc_i64 s[30:31]
   %i = shl <2 x i64> %arg, <i64 32, i64 31>
-  %i1 = bitcast <2 x i64> %i to <2 x double>
-  %i2 = fadd <2 x double> %i1, zeroinitializer
-  %i3 = fadd <2 x double> %i2, splat (double 1.000000e+00)
-  %i4 = fadd <2 x double> %i3, splat (double 1.000000e+00)
-  %i5 = bitcast <2 x double> %i4 to <4 x i32>
-  %i6 = extractelement <4 x i32> %i5, i64 0
-  %i7 = sext i32 %i6 to i64
-  store i64 %i7, ptr addrspace(1) null, align 8
-  ret void
+  ret <2 x i64> %i
 }
 
-define void @func_2xi64_inreg(<2 x i64> inreg %arg) {
-; CHECK-LABEL: func_2xi64_inreg:
+define amdgpu_ps <2 x i64> @func_v2i64_scalar(<2 x i64> inreg %arg) {
+; CHECK-LABEL: func_v2i64_scalar:
 ; CHECK:       ; %bb.0:
-; CHECK-NEXT:    s_wait_loadcnt_dscnt 0x0
-; CHECK-NEXT:    s_wait_kmcnt 0x0
+; 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_lshl_b64 s[0:1], s[0:1], 32
-; CHECK-NEXT:    s_delay_alu instid0(SALU_CYCLE_1) | instskip(SKIP_2) | instid1(VALU_DEP_1)
-; CHECK-NEXT:    s_lshl_b64 s[2:3], s[2:3], s0
-; CHECK-NEXT:    v_mov_b64_e32 v[0:1], s[0:1]
-; CHECK-NEXT:    v_mov_b64_e32 v[2:3], s[2:3]
-; CHECK-NEXT:    v_pk_add_f64 v[0:3], v[0:3], 1.0
-; CHECK-NEXT:    s_delay_alu instid0(VALU_DEP_1) | instskip(SKIP_1) | instid1(VALU_DEP_2)
-; CHECK-NEXT:    v_pk_add_f64 v[0:3], v[0:3], 1.0
-; CHECK-NEXT:    v_mov_b64_e32 v[2:3], 0
-; CHECK-NEXT:    v_ashrrev_i32_e32 v1, 31, v0
-; CHECK-NEXT:    global_store_b64 v[2:3], v[0:1], off
-; CHECK-NEXT:    s_set_pc_i64 s[30:31]
+; CHECK-NEXT:    s_lshl_b64 s[2:3], s[2:3], 31
+; CHECK-NEXT:    ; return to shader part epilog
   %i = shl <2 x i64> %arg, <i64 32, i64 31>
-  %i1 = bitcast <2 x i64> %i to <2 x double>
-  %i2 = fadd <2 x double> %i1, zeroinitializer
-  %i3 = fadd <2 x double> %i2, splat (double 1.000000e+00)
-  %i4 = fadd <2 x double> %i3, splat (double 1.000000e+00)
-  %i5 = bitcast <2 x double> %i4 to <4 x i32>
-  %i6 = extractelement <4 x i32> %i5, i64 0
-  %i7 = sext i32 %i6 to i64
-  store i64 %i7, ptr addrspace(1) null, align 8
-  ret void
+  ret <2 x i64> %i
 }
 
-define void @func_4xi64(<4 x i64> %arg) {
-; CHECK-LABEL: func_4xi64:
+define <4 x i64> @func_4xi64_vector(<4 x i64> %arg) {
+; CHECK-LABEL: func_4xi64_vector:
 ; CHECK:       ; %bb.0:
 ; CHECK-NEXT:    s_wait_loadcnt_dscnt 0x0
 ; CHECK-NEXT:    s_wait_kmcnt 0x0
 ; CHECK-NEXT:    v_dual_mov_b32 v3, v2 :: v_dual_mov_b32 v1, v0
-; CHECK-NEXT:    v_mov_b32_e32 v0, 0
-; CHECK-NEXT:    s_delay_alu instid0(VALU_DEP_1) | instskip(NEXT) | instid1(VALU_DEP_1)
-; CHECK-NEXT:    v_mov_b32_e32 v2, v0
-; CHECK-NEXT:    v_pk_add_f64 v[0:3], v[0:3], 1.0
-; CHECK-NEXT:    s_delay_alu instid0(VALU_DEP_1) | instskip(SKIP_1) | instid1(VALU_DEP_2)
-; CHECK-NEXT:    v_pk_add_f64 v[0:3], v[0:3], 1.0
-; CHECK-NEXT:    v_mov_b64_e32 v[2:3], 0
-; CHECK-NEXT:    v_ashrrev_i32_e32 v1, 31, v0
-; CHECK-NEXT:    global_store_b64 v[2:3], v[0:1], off
+; CHECK-NEXT:    v_lshlrev_b64_e32 v[6:7], 31, v[6:7]
+; CHECK-NEXT:    v_lshlrev_b64_e32 v[4:5], 32, v[4:5]
+; CHECK-NEXT:    v_dual_mov_b32 v0, 0 :: v_dual_mov_b32 v2, 0
 ; CHECK-NEXT:    s_set_pc_i64 s[30:31]
   %i = shl <4 x i64> %arg, <i64 32, i64 32, i64 32, i64 31>
-  %i1 = bitcast <4 x i64> %i to <4 x double>
-  %i2 = fadd <4 x double> %i1, zeroinitializer
-  %i3 = fadd <4 x double> %i2, splat (double 1.000000e+00)
-  %i4 = fadd <4 x double> %i3, splat (double 1.000000e+00)
-  %i5 = bitcast <4 x double> %i4 to <8 x i32>
-  %i6 = extractelement <8 x i32> %i5, i64 0
-  %i7 = sext i32 %i6 to i64
-  store i64 %i7, ptr addrspace(1) null, align 8
-  ret void
+  ret <4 x i64> %i
 }
 
-define void @func_4xi64_inreg(<4 x i64> inreg %arg) {
-; CHECK-LABEL: func_4xi64_inreg:
+define amdgpu_ps <4 x i64> @func_4xi64_scalar(<4 x i64> inreg %arg) {
+; CHECK-LABEL: func_4xi64_scalar:
 ; CHECK:       ; %bb.0:
-; CHECK-NEXT:    s_wait_loadcnt_dscnt 0x0
-; CHECK-NEXT:    s_wait_kmcnt 0x0
-; CHECK-NEXT:    v_dual_mov_b32 v0, 0 :: v_dual_mov_b32 v1, s0
-; CHECK-NEXT:    s_delay_alu instid0(VALU_DEP_1) | instskip(NEXT) | instid1(VALU_DEP_1)
-; CHECK-NEXT:    v_dual_mov_b32 v3, s2 :: v_dual_mov_b32 v2, v0
-; CHECK-NEXT:    v_pk_add_f64 v[0:3], v[0:3], 1.0
-; CHECK-NEXT:    s_delay_alu instid0(VALU_DEP_1) | instskip(SKIP_1) | instid1(VALU_DEP_2)
-; CHECK-NEXT:    v_pk_add_f64 v[0:3], v[0:3], 1.0
-; CHECK-NEXT:    v_mov_b64_e32 v[2:3], 0
-; CHECK-NEXT:    v_ashrrev_i32_e32 v1, 31, v0
-; CHECK-NEXT:    global_store_b64 v[2:3], v[0:1], off
-; CHECK-NEXT:    s_set_pc_i64 s[30:31]
+; 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_b32 s3, s2
+; CHECK-NEXT:    s_mov_b32 s1, s0
+; CHECK-NEXT:    s_lshl_b64 s[6:7], s[6:7], 31
+; CHECK-NEXT:    s_lshl_b64 s[4:5], s[4:5], 32
+; CHECK-NEXT:    s_mov_b32 s0, 0
+; CHECK-NEXT:    s_mov_b32 s2, 0
+; CHECK-NEXT:    ; return to shader part epilog
   %i = shl <4 x i64> %arg, <i64 32, i64 32, i64 32, i64 31>
-  %i1 = bitcast <4 x i64> %i to <4 x double>
-  %i2 = fadd <4 x double> %i1, zeroinitializer
-  %i3 = fadd <4 x double> %i2, splat (double 1.000000e+00)
-  %i4 = fadd <4 x double> %i3, splat (double 1.000000e+00)
-  %i5 = bitcast <4 x double> %i4 to <8 x i32>
-  %i6 = extractelement <8 x i32> %i5, i64 0
-  %i7 = sext i32 %i6 to i64
-  store i64 %i7, ptr addrspace(1) null, align 8
-  ret void
+  ret <4 x i64> %i
 }
 
-define void @func_8xi64(<8 x i64> %arg) {
-; CHECK-LABEL: func_8xi64:
+define <8 x i64> @func_8xi64_vector(<8 x i64> %arg) {
+; CHECK-LABEL: func_8xi64_vector:
 ; CHECK:       ; %bb.0:
 ; CHECK-NEXT:    s_wait_loadcnt_dscnt 0x0
 ; CHECK-NEXT:    s_wait_kmcnt 0x0
+; CHECK-NEXT:    v_dual_mov_b32 v11, v10 :: v_dual_mov_b32 v9, v8
+; CHECK-NEXT:    v_dual_mov_b32 v7, v6 :: v_dual_mov_b32 v5, v4
 ; CHECK-NEXT:    v_dual_mov_b32 v3, v2 :: v_dual_mov_b32 v1, v0
-; CHECK-NEXT:    v_mov_b32_e32 v0, 0
-; CHECK-NEXT:    s_delay_alu instid0(VALU_DEP_1) | instskip(NEXT) | instid1(VALU_DEP_1)
-; CHECK-NEXT:    v_mov_b32_e32 v2, v0
-; CHECK-NEXT:    v_pk_add_f64 v[0:3], v[0:3], 1.0
-; CHECK-NEXT:    s_delay_alu instid0(VALU_DEP_1) | instskip(SKIP_1) | instid1(VALU_DEP_2)
-; CHECK-NEXT:    v_pk_add_f64 v[0:3], v[0:3], 1.0
-; CHECK-NEXT:    v_mov_b64_e32 v[2:3], 0
-; CHECK-NEXT:    v_ashrrev_i32_e32 v1, 31, v0
-; CHECK-NEXT:    global_store_b64 v[2:3], v[0:1], off
+; CHECK-NEXT:    v_lshlrev_b64_e32 v[14:15], 31, v[14:15]
+; CHECK-NEXT:    v_lshlrev_b64_e32 v[12:13], 32, v[12:13]
+; CHECK-NEXT:    v_dual_mov_b32 v0, 0 :: v_dual_mov_b32 v2, 0
+; CHECK-NEXT:    v_dual_mov_b32 v4, 0 :: v_dual_mov_b32 v6, 0
+; CHECK-NEXT:    v_dual_mov_b32 v8, 0 :: v_dual_mov_b32 v10, 0
 ; CHECK-NEXT:    s_set_pc_i64 s[30:31]
   %i = shl <8 x i64> %arg, <i64 32, i64 32, i64 32, i64 32, i64 32, i64 32, i64 32, i64 31>
-  %i1 = bitcast <8 x i64> %i to <8 x double>
-  %i2 = fadd <8 x double> %i1, zeroinitializer
-  %i3 = fadd <8 x double> %i2, splat (double 1.000000e+00)
-  %i4 = fadd <8 x double> %i3, splat (double 1.000000e+00)
-  %i5 = bitcast <8 x double> %i4 to <16 x i32>
-  %i6 = extractelement <16 x i32> %i5, i64 0
-  %i7 = sext i32 %i6 to i64
-  store i64 %i7, ptr addrspace(1) null, align 8
-  ret void
+  ret <8 x i64> %i
 }
 
-define void @func_8xi64_inreg(<8 x i64> inreg %arg) {
-; CHECK-LABEL: func_8xi64_inreg:
+define amdgpu_ps <8 x i64> @func_8xi64_scalar(<8 x i64> inreg %arg) {
+; CHECK-LABEL: func_8xi64_scalar:
 ; CHECK:       ; %bb.0:
-; CHECK-NEXT:    s_wait_loadcnt_dscnt 0x0
-; CHECK-NEXT:    s_wait_kmcnt 0x0
-; CHECK-NEXT:    v_dual_mov_b32 v0, 0 :: v_dual_mov_b32 v1, s0
-; CHECK-NEXT:    s_delay_alu instid0(VALU_DEP_1) | instskip(NEXT) | instid1(VALU_DEP_1)
-; CHECK-NEXT:    v_dual_mov_b32 v3, s2 :: v_dual_mov_b32 v2, v0
-; CHECK-NEXT:    v_pk_add_f64 v[0:3], v[0:3], 1.0
-; CHECK-NEXT:    s_delay_alu instid0(VALU_DEP_1) | instskip(SKIP_1) | instid1(VALU_DEP_2)
-; CHECK-NEXT:    v_pk_add_f64 v[0:3], v[0:3], 1.0
-; CHECK-NEXT:    v_mov_b64_e32 v[2:3], 0
-; CHECK-NEXT:    v_ashrrev_i32_e32 v1, 31, v0
-; CHECK-NEXT:    global_store_b64 v[2:3], v[0:1], off
-; CHECK-NEXT:    s_set_pc_i64 s[30:31]
+; 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_b32 s11, s10
+; CHECK-NEXT:    s_mov_b32 s9, s8
+; CHECK-NEXT:    s_mov_b32 s7, s6
+; CHECK-NEXT:    s_mov_b32 s5, s4
+; CHECK-NEXT:    s_mov_b32 s3, s2
+; CHECK-NEXT:    s_mov_b32 s1, s0
+; CHECK-NEXT:    s_lshl_b64 s[14:15], s[14:15], 31
+; CHECK-NEXT:    s_lshl_b64 s[12:13], s[12:13], 32
+; CHECK-NEXT:    s_mov_b32 s0, 0
+; CHECK-NEXT:    s_mov_b32 s2, 0
+; CHECK-NEXT:    s_mov_b32 s4, 0
+; CHECK-NEXT:    s_mov_b32 s6, 0
+; CHECK-NEXT:    s_mov_b32 s8, 0
+; CHECK-NEXT:    s_mov_b32 s10, 0
+; CHECK-NEXT:    ; return to shader part epilog
   %i = shl <8 x i64> %arg, <i64 32, i64 32, i64 32, i64 32, i64 32, i64 32, i64 32, i64 31>
-  %i1 = bitcast <8 x i64> %i to <8 x double>
-  %i2 = fadd <8 x double> %i1, zeroinitializer
-  %i3 = fadd <8 x double> %i2, splat (double 1.000000e+00)
-  %i4 = fadd <8 x double> %i3, splat (double 1.000000e+00)
-  %i5 = bitcast <8 x double> %i4 to <16 x i32>
-  %i6 = extractelement <16 x i32> %i5, i64 0
-  %i7 = sext i32 %i6 to i64
-  store i64 %i7, ptr addrspace(1) null, align 8
-  ret void
+  ret <8 x i64> %i
 }
 
-define void @func_16xi64(<16 x i64> %arg) {
-; CHECK-LABEL: func_16xi64:
+define <16 x i64> @func_16xi64_vector(<16 x i64> %arg) {
+; CHECK-LABEL: func_16xi64_vector:
 ; CHECK:       ; %bb.0:
 ; CHECK-NEXT:    s_wait_loadcnt_dscnt 0x0
 ; CHECK-NEXT:    s_wait_kmcnt 0x0
+; CHECK-NEXT:    scratch_load_b32 v31, off, s32
+; CHECK-NEXT:    v_dual_mov_b32 v27, v26 :: v_dual_mov_b32 v25, v24
+; CHECK-NEXT:    v_dual_mov_b32 v23, v22 :: v_dual_mov_b32 v21, v20
+; CHECK-NEXT:    v_dual_mov_b32 v19, v18 :: v_dual_mov_b32 v17, v16
+; CHECK-NEXT:    v_dual_mov_b32 v15, v14 :: v_dual_mov_b32 v13, v12
+; CHECK-NEXT:    v_dual_mov_b32 v11, v10 :: v_dual_mov_b32 v9, v8
+; CHECK-NEXT:    v_dual_mov_b32 v7, v6 :: v_dual_mov_b32 v5, v4
 ; CHECK-NEXT:    v_dual_mov_b32 v3, v2 :: v_dual_mov_b32 v1, v0
-; CHECK-NEXT:    v_mov_b32_e32 v0, 0
-; CHECK-NEXT:    s_delay_alu instid0(VALU_DEP_1) | instskip(NEXT) | instid1(VALU_DEP_1)
-; CHECK-NEXT:    v_mov_b32_e32 v2, v0
-; CHECK-NEXT:    v_pk_add_f64 v[0:3], v[0:3], 1.0
-; CHECK-NEXT:    s_delay_alu instid0(VALU_DEP_1) | instskip(SKIP_1) | instid1(VALU_DEP_2)
-; CHECK-NEXT:    v_pk_add_f64 v[0:3], v[0:3], 1.0
-; CHECK-NEXT:    v_mov_b64_e32 v[2:3], 0
-; CHECK-NEXT:    v_ashrrev_i32_e32 v1, 31, v0
-; CHECK-NEXT:    global_store_b64 v[2:3], v[0:1], off
+; CHECK-NEXT:    v_lshlrev_b64_e32 v[28:29], 32, v[28:29]
+; CHECK-NEXT:    v_dual_mov_b32 v0, 0 :: v_dual_mov_b32 v2, 0
+; CHECK-NEXT:    v_dual_mov_b32 v4, 0 :: v_dual_mov_b32 v6, 0
+; CHECK-NEXT:    v_dual_mov_b32 v8, 0 :: v_dual_mov_b32 v10, 0
+; CHECK-NEXT:    v_dual_mov_b32 v12, 0 :: v_dual_mov_b32 v14, 0
+; CHECK-NEXT:    v_dual_mov_b32 v16, 0 :: v_dual_mov_b32 v18, 0
+; CHECK-NEXT:    v_dual_mov_b32 v20, 0 :: v_dual_mov_b32 v22, 0
+; CHECK-NEXT:    v_dual_mov_b32 v24, 0 :: v_dual_mov_b32 v26, 0
+; CHECK-NEXT:    s_wait_loadcnt 0x0
+; CHECK-NEXT:    v_lshlrev_b64_e32 v[30:31], 31, v[30:31]
 ; CHECK-NEXT:    s_set_pc_i64 s[30:31]
   %i = shl <16 x i64> %arg, <i64 32, i64 32, i64 32, i64 32, i64 32, i64 32, i64 32, i64 32, i64 32, i64 32, i64 32, i64 32, i64 32, i64 32, i64 32, i64 31>
-  %i1 = bitcast <16 x i64> %i to <16 x double>
-  %i2 = fadd <16 x double> %i1, zeroinitializer
-  %i3 = fadd <16 x double> %i2, splat (double 1.000000e+00)
-  %i4 = fadd <16 x double> %i3, splat (double 1.000000e+00)
-  %i5 = bitcast <16 x double> %i4 to <32 x i32>
-  %i6 = extractelement <32 x i32> %i5, i64 0
-  %i7 = sext i32 %i6 to i64
-  store i64 %i7, ptr addrspace(1) null, align 8
-  ret void
+  ret <16 x i64> %i
 }
 
-define void @func_16xi64_inreg(<16 x i64> inreg %arg) {
-; CHECK-LABEL: func_16xi64_inreg:
+define amdgpu_ps <16 x i64> @func_16xi64_scalar(<16 x i64> inreg %arg) {
+; CHECK-LABEL: func_16xi64_scalar:
 ; CHECK:       ; %bb.0:
-; CHECK-NEXT:    s_wait_loadcnt_dscnt 0x0
-; CHECK-NEXT:    s_wait_kmcnt 0x0
-; CHECK-NEXT:    v_dual_mov_b32 v0, 0 :: v_dual_mov_b32 v1, s0
-; CHECK-NEXT:    s_delay_alu instid0(VALU_DEP_1) | instskip(NEXT) | instid1(VALU_DEP_1)
-; CHECK-NEXT:    v_dual_mov_b32 v3, s2 :: v_dual_mov_b32 v2, v0
-; CHECK-NEXT:    v_pk_add_f64 v[0:3], v[0:3], 1.0
-; CHECK-NEXT:    s_delay_alu instid0(VALU_DEP_1) | instskip(SKIP_1) | instid1(VALU_DEP_2)
-; CHECK-NEXT:    v_pk_add_f64 v[0:3], v[0:3], 1.0
-; CHECK-NEXT:    v_mov_b64_e32 v[2:3], 0
-; CHECK-NEXT:    v_ashrrev_i32_e32 v1, 31, v0
-; CHECK-NEXT:    global_store_b64 v[2:3], v[0:1], off
-; CHECK-NEXT:    s_set_pc_i64 s[30:31]
+; 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_b32 s27, s26
+; CHECK-NEXT:    s_mov_b32 s25, s24
+; CHECK-NEXT:    s_mov_b32 s23, s22
+; CHECK-NEXT:    s_mov_b32 s21, s20
+; CHECK-NEXT:    s_mov_b32 s19, s18
+; CHECK-NEXT:    s_mov_b32 s17, s16
+; CHECK-NEXT:    s_mov_b32 s15, s14
+; CHECK-NEXT:    s_mov_b32 s13, s12
+; CHECK-NEXT:    s_mov_b32 s11, s10
+; CHECK-NEXT:    s_mov_b32 s9, s8
+; CHECK-NEXT:    s_mov_b32 s7, s6
+; CHECK-NEXT:    s_mov_b32 s5, s4
+; CHECK-NEXT:    s_mov_b32 s3, s2
+; CHECK-NEXT:    s_mov_b32 s1, s0
+; CHECK-NEXT:    s_lshl_b64 s[30:31], s[30:31], 31
+; CHECK-NEXT:    s_lshl_b64 s[28:29], s[28:29], 32
+; CHECK-NEXT:    s_mov_b32 s0, 0
+; CHECK-NEXT:    s_mov_b32 s2, 0
+; CHECK-NEXT:    s_mov_b32 s4, 0
+; CHECK-NEXT:    s_mov_b32 s6, 0
+; CHECK-NEXT:    s_mov_b32 s8, 0
+; CHECK-NEXT:    s_mov_b32 s10, 0
+; CHECK-NEXT:    s_mov_b32 s12, 0
+; CHECK-NEXT:    s_mov_b32 s14, 0
+; CHECK-NEXT:    s_mov_b32 s16, 0
+; CHECK-NEXT:    s_mov_b32 s18, 0
+; CHECK-NEXT:    s_mov_b32 s20, 0
+; CHECK-NEXT:    s_mov_b32 s22, 0
+; CHECK-NEXT:    s_mov_b32 s24, 0
+; CHECK-NEXT:    s_mov_b32 s26, 0
+; CHECK-NEXT:    ; return to shader part epilog
   %i = shl <16 x i64> %arg, <i64 32, i64 32, i64 32, i64 32, i64 32, i64 32, i64 32, i64 32, i64 32, i64 32, i64 32, i64 32, i64 32, i64 32, i64 32, i64 31>
-  %i1 = bitcast <16 x i64> %i to <16 x double>
-  %i2 = fadd <16 x double> %i1, zeroinitializer
-  %i3 = fadd <16 x double> %i2, splat (double 1.000000e+00)
-  %i4 = fadd <16 x double> %i3, splat (double 1.000000e+00)
-  %i5 = bitcast <16 x double> %i4 to <32 x i32>
-  %i6 = extractelement <32 x i32> %i5, i64 0
-  %i7 = sext i32 %i6 to i64
-  store i64 %i7, ptr addrspace(1) null, align 8
-  ret void
+  ret <16 x i64> %i
 }

>From 45946334aee6b3e4929726db0cbb44816637279d Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Juan=20Manuel=20Martinez=20Caama=C3=B1o?=
 <jmartinezcaamao at gmail.com>
Date: Thu, 9 Jul 2026 17:36:01 +0200
Subject: [PATCH 06/10] [Review] Move the unroll of trunc v2i64 to v2i32 out of
 performShlCombine

---
 llvm/lib/Target/AMDGPU/AMDGPUISelLowering.cpp |  5 -----
 llvm/lib/Target/AMDGPU/SIISelLowering.cpp     |  5 +++--
 llvm/lib/Target/AMDGPU/SIInstructions.td      | 14 ++++++++++++++
 3 files changed, 17 insertions(+), 7 deletions(-)

diff --git a/llvm/lib/Target/AMDGPU/AMDGPUISelLowering.cpp b/llvm/lib/Target/AMDGPU/AMDGPUISelLowering.cpp
index ed2b8cedc72fb..30e85cf7726d1 100644
--- a/llvm/lib/Target/AMDGPU/AMDGPUISelLowering.cpp
+++ b/llvm/lib/Target/AMDGPU/AMDGPUISelLowering.cpp
@@ -4418,11 +4418,6 @@ SDValue AMDGPUTargetLowering::performShlCombine(SDNode *N,
 
   SDValue Lo = DAG.getNode(ISD::TRUNCATE, SL, TargetType, LHS);
 
-  // Unroll illegal vector truncate: This is normally done by the legalizer,
-  // but we might reintroduce the illegal pattern here.
-  if (DCI.isAfterLegalizeDAG() && TargetType.isVector())
-    Lo = DAG.UnrollVectorOp(Lo.getNode());
-
   SDValue NewShift =
       DAG.getNode(ISD::SHL, SL, TargetType, Lo, ShiftAmt, N->getFlags());
 
diff --git a/llvm/lib/Target/AMDGPU/SIISelLowering.cpp b/llvm/lib/Target/AMDGPU/SIISelLowering.cpp
index 9cf33b4ccbb87..9c56d6707973d 100644
--- a/llvm/lib/Target/AMDGPU/SIISelLowering.cpp
+++ b/llvm/lib/Target/AMDGPU/SIISelLowering.cpp
@@ -920,8 +920,9 @@ SITargetLowering::SITargetLowering(const TargetMachine &TM,
     }
 
     if (Subtarget->hasPackedU64Ops()) {
-      setOperationAction({ISD::ADD, ISD::SUB, ISD::SHL, ISD::BUILD_VECTOR},
-                         MVT::v2i64, Legal);
+      setOperationAction(
+          {ISD::ADD, ISD::SUB, ISD::SHL, ISD::BUILD_VECTOR, ISD::TRUNCATE},
+          MVT::v2i64, Legal);
       setOperationAction({ISD::ADD, ISD::SUB, ISD::SHL},
                          {MVT::v4i64, MVT::v8i64, MVT::v16i64, MVT::v32i64},
                          Custom);
diff --git a/llvm/lib/Target/AMDGPU/SIInstructions.td b/llvm/lib/Target/AMDGPU/SIInstructions.td
index d3ea76ebb647d..d978735a92db8 100644
--- a/llvm/lib/Target/AMDGPU/SIInstructions.td
+++ b/llvm/lib/Target/AMDGPU/SIInstructions.td
@@ -3570,6 +3570,20 @@ def : GCNPat <
   (EXTRACT_SUBREG $a, sub0)
 >;
 
+def : GCNPat <
+  (v2i32 (UniformUnaryFrag<trunc> v2i64:$a)),
+  (v2i32 (REG_SEQUENCE SReg_64,
+         (i32 (EXTRACT_SUBREG $a, sub0)), sub0,
+         (i32 (EXTRACT_SUBREG $a, sub2)), sub1))
+>;
+
+def : GCNPat <
+  (v2i32 (DivergentUnaryFrag<trunc> v2i64:$a)),
+  (v2i32 (REG_SEQUENCE VReg_64,
+         (i32 (EXTRACT_SUBREG $a, sub0)), sub0,
+         (i32 (EXTRACT_SUBREG $a, sub2)), sub1))
+>;
+
 def : GCNPat <
   (i1 (UniformUnaryFrag<trunc> i32:$a)),
   (S_CMP_EQ_U32 (S_AND_B32 (i32 1), $a), (i32 1))

>From 231c3d8afc351c7a36409fce0e89523f28406932 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Juan=20Manuel=20Martinez=20Caama=C3=B1o?=
 <jmartinezcaamao at gmail.com>
Date: Thu, 9 Jul 2026 18:13:07 +0200
Subject: [PATCH 07/10] whopsy

---
 llvm/lib/Target/AMDGPU/AMDGPUISelLowering.cpp | 1 -
 1 file changed, 1 deletion(-)

diff --git a/llvm/lib/Target/AMDGPU/AMDGPUISelLowering.cpp b/llvm/lib/Target/AMDGPU/AMDGPUISelLowering.cpp
index 30e85cf7726d1..ccf73a6aeef84 100644
--- a/llvm/lib/Target/AMDGPU/AMDGPUISelLowering.cpp
+++ b/llvm/lib/Target/AMDGPU/AMDGPUISelLowering.cpp
@@ -4417,7 +4417,6 @@ SDValue AMDGPUTargetLowering::performShlCombine(SDNode *N,
   }
 
   SDValue Lo = DAG.getNode(ISD::TRUNCATE, SL, TargetType, LHS);
-
   SDValue NewShift =
       DAG.getNode(ISD::SHL, SL, TargetType, Lo, ShiftAmt, N->getFlags());
 

>From a86424403c914aa2a095b520f4b1b91b21cde120 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Juan=20Manuel=20Martinez=20Caama=C3=B1o?=
 <jmartinezcaamao at gmail.com>
Date: Thu, 9 Jul 2026 18:14:14 +0200
Subject: [PATCH 08/10] whopsy++

---
 llvm/test/CodeGen/AMDGPU/packed_shl64_combine.ll | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/llvm/test/CodeGen/AMDGPU/packed_shl64_combine.ll b/llvm/test/CodeGen/AMDGPU/packed_shl64_combine.ll
index 1b758529b80ff..6c4a4f9465e35 100644
--- a/llvm/test/CodeGen/AMDGPU/packed_shl64_combine.ll
+++ b/llvm/test/CodeGen/AMDGPU/packed_shl64_combine.ll
@@ -1,8 +1,8 @@
 ; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py UTC_ARGS: --version 6
 ; RUN: llc -mtriple=amdgcn-- -mcpu=gfx1251 < %s | FileCheck %s
 
-define <2 x i64> @func_v2i64(<2 x i64> %arg) {
-; CHECK-LABEL: func_v2i64:
+define <2 x i64> @func_v2i64_vector(<2 x i64> %arg) {
+; CHECK-LABEL: func_v2i64_vector:
 ; CHECK:       ; %bb.0:
 ; CHECK-NEXT:    s_wait_loadcnt_dscnt 0x0
 ; CHECK-NEXT:    s_wait_kmcnt 0x0

>From 7a7c1a15a64cfa9b586e2a01584e3586805437f6 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Juan=20Manuel=20Martinez=20Caama=C3=B1o?=
 <jmartinezcaamao at gmail.com>
Date: Fri, 10 Jul 2026 09:24:41 +0200
Subject: [PATCH 09/10] Make truncate legal

---
 llvm/lib/Target/AMDGPU/SIISelLowering.cpp | 7 ++++---
 1 file changed, 4 insertions(+), 3 deletions(-)

diff --git a/llvm/lib/Target/AMDGPU/SIISelLowering.cpp b/llvm/lib/Target/AMDGPU/SIISelLowering.cpp
index 9c56d6707973d..a8805503f1f2e 100644
--- a/llvm/lib/Target/AMDGPU/SIISelLowering.cpp
+++ b/llvm/lib/Target/AMDGPU/SIISelLowering.cpp
@@ -362,6 +362,8 @@ SITargetLowering::SITargetLowering(const TargetMachine &TM,
 
   setOperationAction(ISD::FP_EXTEND, MVT::v4f32, Expand);
 
+  setOperationAction(ISD::TRUNCATE, MVT::v2i64, Legal);
+
   // TODO: For dynamic 64-bit vector inserts/extracts, should emit a pseudo that
   // is expanded to avoid having two separate loops in case the index is a VGPR.
 
@@ -920,9 +922,8 @@ SITargetLowering::SITargetLowering(const TargetMachine &TM,
     }
 
     if (Subtarget->hasPackedU64Ops()) {
-      setOperationAction(
-          {ISD::ADD, ISD::SUB, ISD::SHL, ISD::BUILD_VECTOR, ISD::TRUNCATE},
-          MVT::v2i64, Legal);
+      setOperationAction({ISD::ADD, ISD::SUB, ISD::SHL, ISD::BUILD_VECTOR},
+                         MVT::v2i64, Legal);
       setOperationAction({ISD::ADD, ISD::SUB, ISD::SHL},
                          {MVT::v4i64, MVT::v8i64, MVT::v16i64, MVT::v32i64},
                          Custom);

>From 04579810c35c831c7bf4d58e987d42af80bd0be9 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Juan=20Manuel=20Martinez=20Caama=C3=B1o?=
 <jmartinezcaamao at gmail.com>
Date: Fri, 10 Jul 2026 14:14:58 +0200
Subject: [PATCH 10/10] remove legalizer rule

---
 llvm/lib/Target/AMDGPU/SIISelLowering.cpp | 2 --
 1 file changed, 2 deletions(-)

diff --git a/llvm/lib/Target/AMDGPU/SIISelLowering.cpp b/llvm/lib/Target/AMDGPU/SIISelLowering.cpp
index a8805503f1f2e..9cf33b4ccbb87 100644
--- a/llvm/lib/Target/AMDGPU/SIISelLowering.cpp
+++ b/llvm/lib/Target/AMDGPU/SIISelLowering.cpp
@@ -362,8 +362,6 @@ SITargetLowering::SITargetLowering(const TargetMachine &TM,
 
   setOperationAction(ISD::FP_EXTEND, MVT::v4f32, Expand);
 
-  setOperationAction(ISD::TRUNCATE, MVT::v2i64, Legal);
-
   // TODO: For dynamic 64-bit vector inserts/extracts, should emit a pseudo that
   // is expanded to avoid having two separate loops in case the index is a VGPR.
 



More information about the llvm-commits mailing list