[llvm] [AArch64] Tablegen patterns for `shuffle(zext(...))` to `uaddlp` (PR #195120)

Rajveer Singh Bharadwaj via llvm-commits llvm-commits at lists.llvm.org
Fri May 1 03:45:08 PDT 2026


https://github.com/Rajveer100 updated https://github.com/llvm/llvm-project/pull/195120

>From fe2b5d689e284074fbcf175644d3a59ee495fe69 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] Tablegen patterns for `shuffle(zext(...))` to
 `uaddlp`

Follow up for #189255
---
 llvm/lib/Target/AArch64/AArch64InstrInfo.td | 20 +++++++
 llvm/test/CodeGen/AArch64/addp-shuffle.ll   |  8 +--
 llvm/test/CodeGen/AArch64/uaddlp.ll         | 58 +++++++++++++++++++++
 3 files changed, 80 insertions(+), 6 deletions(-)

diff --git a/llvm/lib/Target/AArch64/AArch64InstrInfo.td b/llvm/lib/Target/AArch64/AArch64InstrInfo.td
index f20f978fe7e8a..efd1e76d3b5d2 100644
--- a/llvm/lib/Target/AArch64/AArch64InstrInfo.td
+++ b/llvm/lib/Target/AArch64/AArch64InstrInfo.td
@@ -8645,6 +8645,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)>;
@@ -8660,6 +8661,25 @@ 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)>;
+
 //------------------------------------------------------------------------------
 // AdvSIMD modified immediate instructions
 //------------------------------------------------------------------------------
diff --git a/llvm/test/CodeGen/AArch64/addp-shuffle.ll b/llvm/test/CodeGen/AArch64/addp-shuffle.ll
index b565bfe14c2ed..f85db60bcd39a 100644
--- a/llvm/test/CodeGen/AArch64/addp-shuffle.ll
+++ b/llvm/test/CodeGen/AArch64/addp-shuffle.ll
@@ -160,12 +160,8 @@ define <4 x i32> @udot(<4 x i32> %z, <16 x i8> %a, <16 x i8> %b) {
 ; CHECK:       // %bb.0:
 ; CHECK-NEXT:    umull v3.8h, v1.8b, v2.8b
 ; CHECK-NEXT:    umull2 v1.8h, v1.16b, v2.16b
-; CHECK-NEXT:    ushll2 v2.4s, v3.8h, #0
-; CHECK-NEXT:    ushll v3.4s, v3.4h, #0
-; CHECK-NEXT:    ushll2 v4.4s, v1.8h, #0
-; CHECK-NEXT:    ushll v1.4s, v1.4h, #0
-; CHECK-NEXT:    addp v2.4s, v3.4s, v2.4s
-; CHECK-NEXT:    addp v1.4s, v1.4s, v4.4s
+; 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
diff --git a/llvm/test/CodeGen/AArch64/uaddlp.ll b/llvm/test/CodeGen/AArch64/uaddlp.ll
index 015aab48e7255..10654184cd389 100644
--- a/llvm/test/CodeGen/AArch64/uaddlp.ll
+++ b/llvm/test/CodeGen/AArch64/uaddlp.ll
@@ -72,3 +72,61 @@ 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
+}



More information about the llvm-commits mailing list