[llvm] [AArch64] Tablegen patterns for `shuffle(zext(...))` to `uaddlp` (PR #195120)
Rajveer Singh Bharadwaj via llvm-commits
llvm-commits at lists.llvm.org
Sun May 10 05:05:28 PDT 2026
https://github.com/Rajveer100 updated https://github.com/llvm/llvm-project/pull/195120
>From 6d8857d7912e9c4b66922e67f33ef0e086b912f7 Mon Sep 17 00:00:00 2001
From: Rajveer <rajveer.developer at icloud.com>
Date: Thu, 30 Apr 2026 21:39:37 +0530
Subject: [PATCH] [AArch64] Additional Tablegen patterns for
`shuffle(zext(...))` and `shuffle(sext(...))` to `uaddlp`
Follow up for #189255
---
llvm/lib/Target/AArch64/AArch64InstrInfo.td | 39 +++++++
llvm/test/CodeGen/AArch64/addp-shuffle.ll | 9 ++
llvm/test/CodeGen/AArch64/uaddlp.ll | 111 ++++++++++++++++++++
3 files changed, 159 insertions(+)
diff --git a/llvm/lib/Target/AArch64/AArch64InstrInfo.td b/llvm/lib/Target/AArch64/AArch64InstrInfo.td
index 6c20efffb1944..57c624209114a 100644
--- a/llvm/lib/Target/AArch64/AArch64InstrInfo.td
+++ b/llvm/lib/Target/AArch64/AArch64InstrInfo.td
@@ -8663,6 +8663,7 @@ def : Pat<(v2i64 (AArch64saddlv (v2i32 V64:$Rn))),
def : Pat<(v2i64 (AArch64uaddlv (v2i32 V64:$Rn))),
(v2i64 (INSERT_SUBREG (v2i64 (IMPLICIT_DEF)), (UADDLPv2i32_v1i64 V64:$Rn), dsub))>;
+// shuffle + zext
def : Pat<(add (AArch64bici (v8i16 (bitconvert v16i8:$src)), (i32 255), (i32 8)),
(AArch64vlshr (v8i16 (AArch64NvCast v16i8:$src)), (i32 8))),
(UADDLPv16i8_v8i16 V128:$src)>;
@@ -8678,6 +8679,44 @@ def : Pat<(add (v2i64 (zext (v2i32 (AArch64zip1 (v2i32 (extract_subvector v4i32:
(v2i32 (extract_subvector v4i32:$src, (i64 2)))))))),
(UADDLPv4i32_v2i64 V128:$src)>;
+// zext + shuffle
+def : Pat<(add (AArch64uzp1 (v8i16 (zext (v8i8 (extract_subvector v16i8:$src, (i64 0))))),
+ (v8i16 (zext (v8i8 (extract_subvector v16i8:$src, (i64 8)))))),
+ (AArch64uzp2 (v8i16 (zext (v8i8 (extract_subvector v16i8:$src, (i64 0))))),
+ (v8i16 (zext (v8i8 (extract_subvector v16i8:$src, (i64 8))))))),
+ (UADDLPv16i8_v8i16 V128:$src)>;
+
+def : Pat<(add (AArch64uzp1 (v4i32 (zext (v4i16 (extract_subvector v8i16:$src, (i64 0))))),
+ (v4i32 (zext (v4i16 (extract_subvector v8i16:$src, (i64 4)))))),
+ (AArch64uzp2 (v4i32 (zext (v4i16 (extract_subvector v8i16:$src, (i64 0))))),
+ (v4i32 (zext (v4i16 (extract_subvector v8i16:$src, (i64 4))))))),
+ (UADDLPv8i16_v4i32 V128:$src)>;
+
+def : Pat<(add (AArch64zip1 (v2i64 (zext (v2i32 (extract_subvector v4i32:$src, (i64 0))))),
+ (v2i64 (zext (v2i32 (extract_subvector v4i32:$src, (i64 2)))))),
+ (AArch64zip2 (v2i64 (zext (v2i32 (extract_subvector v4i32:$src, (i64 0))))),
+ (v2i64 (zext (v2i32 (extract_subvector v4i32:$src, (i64 2))))))),
+ (UADDLPv4i32_v2i64 V128:$src)>;
+
+// sext + shuffle
+def : Pat<(add (AArch64uzp1 (v8i16 (sext (v8i8 (extract_subvector v16i8:$src, (i64 0))))),
+ (v8i16 (sext (v8i8 (extract_subvector v16i8:$src, (i64 8)))))),
+ (AArch64uzp2 (v8i16 (sext (v8i8 (extract_subvector v16i8:$src, (i64 0))))),
+ (v8i16 (sext (v8i8 (extract_subvector v16i8:$src, (i64 8))))))),
+ (UADDLPv16i8_v8i16 V128:$src)>;
+
+def : Pat<(add (AArch64uzp1 (v4i32 (sext (v4i16 (extract_subvector v8i16:$src, (i64 0))))),
+ (v4i32 (sext (v4i16 (extract_subvector v8i16:$src, (i64 4)))))),
+ (AArch64uzp2 (v4i32 (sext (v4i16 (extract_subvector v8i16:$src, (i64 0))))),
+ (v4i32 (sext (v4i16 (extract_subvector v8i16:$src, (i64 4))))))),
+ (UADDLPv8i16_v4i32 V128:$src)>;
+
+def : Pat<(add (AArch64zip1 (v2i64 (sext (v2i32 (extract_subvector v4i32:$src, (i64 0))))),
+ (v2i64 (sext (v2i32 (extract_subvector v4i32:$src, (i64 2)))))),
+ (AArch64zip2 (v2i64 (sext (v2i32 (extract_subvector v4i32:$src, (i64 0))))),
+ (v2i64 (sext (v2i32 (extract_subvector v4i32:$src, (i64 2))))))),
+ (UADDLPv4i32_v2i64 V128:$src)>;
+
//------------------------------------------------------------------------------
// AdvSIMD modified immediate instructions
//------------------------------------------------------------------------------
diff --git a/llvm/test/CodeGen/AArch64/addp-shuffle.ll b/llvm/test/CodeGen/AArch64/addp-shuffle.ll
index e71d23921785c..6ccfa58960277 100644
--- a/llvm/test/CodeGen/AArch64/addp-shuffle.ll
+++ b/llvm/test/CodeGen/AArch64/addp-shuffle.ll
@@ -325,6 +325,15 @@ define <4 x i32> @udot(<4 x i32> %z, <16 x i8> %a, <16 x i8> %b) {
; CHECK-FP16-GI-NEXT: addp v1.4s, v2.4s, v1.4s
; CHECK-FP16-GI-NEXT: add v0.4s, v0.4s, v1.4s
; CHECK-FP16-GI-NEXT: ret
+; CHECK-LABEL: udot:
+; CHECK: // %bb.0:
+; CHECK-NEXT: umull v3.8h, v1.8b, v2.8b
+; CHECK-NEXT: umull2 v1.8h, v1.16b, v2.16b
+; CHECK-NEXT: uaddlp v1.4s, v1.8h
+; CHECK-NEXT: uaddlp v2.4s, v3.8h
+; CHECK-NEXT: addp v1.4s, v2.4s, v1.4s
+; CHECK-NEXT: add v0.4s, v0.4s, v1.4s
+; CHECK-NEXT: ret
%za = zext <16 x i8> %a to <16 x i32>
%zb = zext <16 x i8> %b to <16 x i32>
%m = mul <16 x i32> %za, %zb
diff --git a/llvm/test/CodeGen/AArch64/uaddlp.ll b/llvm/test/CodeGen/AArch64/uaddlp.ll
index 015aab48e7255..16c0ecb4e949c 100644
--- a/llvm/test/CodeGen/AArch64/uaddlp.ll
+++ b/llvm/test/CodeGen/AArch64/uaddlp.ll
@@ -72,3 +72,114 @@ start:
%4 = add nuw nsw <8 x i16> %2, %3
ret <8 x i16> %4
}
+
+define <8 x i16> @vpaddlq_v16i8_zext_shuffle(<16 x i8> %a) unnamed_addr {
+; CHECK-LABEL: vpaddlq_v16i8_zext_shuffle:
+; CHECK: // %bb.0: // %start
+; CHECK-NEXT: uaddlp v0.8h, v0.16b
+; CHECK-NEXT: ret
+start:
+ %0 = zext <16 x i8> %a to <16 x i16>
+ %1 = shufflevector <16 x i16> %0, <16 x i16> poison, <8 x i32> <i32 0, i32 2, i32 4, i32 6, i32 8, i32 10, i32 12, i32 14>
+ %2 = shufflevector <16 x i16> %0, <16 x i16> poison, <8 x i32> <i32 1, i32 3, i32 5, i32 7, i32 9, i32 11, i32 13, i32 15>
+ %3 = add nuw nsw <8 x i16> %1, %2
+ ret <8 x i16> %3
+}
+
+define <4 x i32> @vpaddlq_v8i16_zext_shuffle(<8 x i16> %a) unnamed_addr {
+; CHECK-LABEL: vpaddlq_v8i16_zext_shuffle:
+; CHECK: // %bb.0: // %start
+; CHECK-NEXT: uaddlp v0.4s, v0.8h
+; CHECK-NEXT: ret
+start:
+ %0 = zext <8 x i16> %a to <8 x i32>
+ %1 = shufflevector <8 x i32> %0, <8 x i32> poison, <4 x i32> <i32 0, i32 2, i32 4, i32 6>
+ %2 = shufflevector <8 x i32> %0, <8 x i32> poison, <4 x i32> <i32 1, i32 3, i32 5, i32 7>
+ %3 = add nuw nsw <4 x i32> %1, %2
+ ret <4 x i32> %3
+}
+
+define <2 x i64> @vpaddlq_v4i32_zext_shuffle(<4 x i32> %a) unnamed_addr {
+; CHECK-LABEL: vpaddlq_v4i32_zext_shuffle:
+; CHECK: // %bb.0: // %start
+; CHECK-NEXT: uaddlp v0.2d, v0.4s
+; CHECK-NEXT: ret
+start:
+ %0 = zext <4 x i32> %a to <4 x i64>
+ %1 = shufflevector <4 x i64> %0, <4 x i64> poison, <2 x i32> <i32 0, i32 2>
+ %2 = shufflevector <4 x i64> %0, <4 x i64> poison, <2 x i32> <i32 1, i32 3>
+ %3 = add nuw nsw <2 x i64> %1, %2
+ ret <2 x i64> %3
+}
+
+define <4 x i32> @vpaddlq_v8i16_zext_shuffle_neg(<8 x i16> %a) unnamed_addr {
+; CHECK-LABEL: vpaddlq_v8i16_zext_shuffle_neg:
+; CHECK: // %bb.0: // %start
+; CHECK-NEXT: ushll2 v1.4s, v0.8h, #0
+; CHECK-NEXT: ushll v0.4s, v0.4h, #0
+; CHECK-NEXT: uzp1 v2.4s, v0.4s, v1.4s
+; CHECK-NEXT: uzp2 v3.4s, v0.4s, v1.4s
+; CHECK-NEXT: mov v2.s[2], v0.s[3]
+; CHECK-NEXT: mov v3.s[1], v1.s[0]
+; CHECK-NEXT: add v0.4s, v2.4s, v3.4s
+; CHECK-NEXT: ret
+start:
+ %0 = zext <8 x i16> %a to <8 x i32>
+ %1 = shufflevector <8 x i32> %0, <8 x i32> poison, <4 x i32> <i32 0, i32 2, i32 3, i32 6>
+ %2 = shufflevector <8 x i32> %0, <8 x i32> poison, <4 x i32> <i32 1, i32 4, i32 5, i32 7>
+ %3 = add nuw nsw <4 x i32> %1, %2
+ ret <4 x i32> %3
+}
+
+define <8 x i16> @vpaddlq_v16i8_sext_shuffle(<16 x i8> %a) unnamed_addr {
+; CHECK-LABEL: vpaddlq_v16i8_sext_shuffle:
+; CHECK: // %bb.0: // %start
+; CHECK-NEXT: uaddlp v0.8h, v0.16b
+; CHECK-NEXT: ret
+start:
+ %0 = sext <16 x i8> %a to <16 x i16>
+ %1 = shufflevector <16 x i16> %0, <16 x i16> poison, <8 x i32> <i32 0, i32 2, i32 4, i32 6, i32 8, i32 10, i32 12, i32 14>
+ %2 = shufflevector <16 x i16> %0, <16 x i16> poison, <8 x i32> <i32 1, i32 3, i32 5, i32 7, i32 9, i32 11, i32 13, i32 15>
+ %3 = add nuw nsw <8 x i16> %1, %2
+ ret <8 x i16> %3
+}
+
+define <4 x i32> @vpaddlq_v8i16_sext_shuffle(<8 x i16> %a) unnamed_addr {
+; CHECK-LABEL: vpaddlq_v8i16_sext_shuffle:
+; CHECK: // %bb.0: // %start
+; CHECK-NEXT: uaddlp v0.4s, v0.8h
+; CHECK-NEXT: ret
+start:
+ %0 = sext <8 x i16> %a to <8 x i32>
+ %1 = shufflevector <8 x i32> %0, <8 x i32> poison, <4 x i32> <i32 0, i32 2, i32 4, i32 6>
+ %2 = shufflevector <8 x i32> %0, <8 x i32> poison, <4 x i32> <i32 1, i32 3, i32 5, i32 7>
+ %3 = add nuw nsw <4 x i32> %1, %2
+ ret <4 x i32> %3
+}
+
+define <2 x i64> @vpaddlq_v4i32_sext_shuffle(<4 x i32> %a) unnamed_addr {
+; CHECK-LABEL: vpaddlq_v4i32_sext_shuffle:
+; CHECK: // %bb.0: // %start
+; CHECK-NEXT: uaddlp v0.2d, v0.4s
+; CHECK-NEXT: ret
+start:
+ %0 = sext <4 x i32> %a to <4 x i64>
+ %1 = shufflevector <4 x i64> %0, <4 x i64> poison, <2 x i32> <i32 0, i32 2>
+ %2 = shufflevector <4 x i64> %0, <4 x i64> poison, <2 x i32> <i32 1, i32 3>
+ %3 = add nuw nsw <2 x i64> %1, %2
+ ret <2 x i64> %3
+}
+
+define <2 x i64> @vpaddlq_v4i32_sext_shuffle_neg(<4 x i32> %a) unnamed_addr {
+; CHECK-LABEL: vpaddlq_v4i32_sext_shuffle_neg:
+; CHECK: // %bb.0: // %start
+; CHECK-NEXT: sshll v1.2d, v0.2s, #0
+; CHECK-NEXT: saddw2 v0.2d, v1.2d, v0.4s
+; CHECK-NEXT: ret
+start:
+ %0 = sext <4 x i32> %a to <4 x i64>
+ %1 = shufflevector <4 x i64> %0, <4 x i64> poison, <2 x i32> <i32 0, i32 1>
+ %2 = shufflevector <4 x i64> %0, <4 x i64> poison, <2 x i32> <i32 2, i32 3>
+ %3 = add nuw nsw <2 x i64> %1, %2
+ ret <2 x i64> %3
+}
More information about the llvm-commits
mailing list