[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