[llvm] [AMDGPU] Do not generate illegal vector TRUNCATE after legalization in `performShlCombine` (PR #207761)
Juan Manuel Martinez CaamaƱo via llvm-commits
llvm-commits at lists.llvm.org
Thu Jul 9 09:14:36 PDT 2026
https://github.com/jmmartinez updated https://github.com/llvm/llvm-project/pull/207761
>From 8990c029e40f8d11950e9769822a8e3016c4fefe 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 1/8] [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 5ade95968bf1d62be018c2a32935a4729cc0d854 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 2/8] [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 5010720ca8e76..0d258e64d46ce 100644
--- a/llvm/lib/Target/AMDGPU/AMDGPUISelLowering.cpp
+++ b/llvm/lib/Target/AMDGPU/AMDGPUISelLowering.cpp
@@ -4738,6 +4738,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 e295fc969922f4b1df4ceef2654abdcdd65899c3 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 3/8] [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 0d258e64d46ce..45c1e97e0405e 100644
--- a/llvm/lib/Target/AMDGPU/AMDGPUISelLowering.cpp
+++ b/llvm/lib/Target/AMDGPU/AMDGPUISelLowering.cpp
@@ -4416,6 +4416,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());
@@ -4738,14 +4744,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 78c8996840501faeeb039dd7bcfe3041b8823ec1 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 4/8] [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 a335c1323f81a300b8283fa2dd3a69b123d1616b 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 5/8] [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 cc95b1e41f6b078e2a05eb79decaed4c58bf60fd 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 6/8] [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 45c1e97e0405e..7b0c5352c32a9 100644
--- a/llvm/lib/Target/AMDGPU/AMDGPUISelLowering.cpp
+++ b/llvm/lib/Target/AMDGPU/AMDGPUISelLowering.cpp
@@ -4417,11 +4417,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 b46359ec91e8a..50302e0e1ed90 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 15bc6704e076b..a2a158eab3938 100644
--- a/llvm/lib/Target/AMDGPU/SIInstructions.td
+++ b/llvm/lib/Target/AMDGPU/SIInstructions.td
@@ -3568,6 +3568,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 e3baddf0ac1eac73a5dcd48a87afae60d09b2e62 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 7/8] 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 7b0c5352c32a9..5010720ca8e76 100644
--- a/llvm/lib/Target/AMDGPU/AMDGPUISelLowering.cpp
+++ b/llvm/lib/Target/AMDGPU/AMDGPUISelLowering.cpp
@@ -4416,7 +4416,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 ac18fc20f908198a8fb893e68c3d12a559b426c9 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 8/8] 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
More information about the llvm-commits
mailing list