[llvm] [AArch64] Use EXT for byte shuffles with leading zeros (PR #193466)

Shreeyash Pandey via llvm-commits llvm-commits at lists.llvm.org
Thu May 7 04:39:09 PDT 2026


https://github.com/bojle updated https://github.com/llvm/llvm-project/pull/193466

>From 61551252aa1f17ec11b53ed156bf746483b0fca4 Mon Sep 17 00:00:00 2001
From: Shreeyash Pandey <shrpand at qti.qualcomm.com>
Date: Wed, 22 Apr 2026 04:08:10 -0700
Subject: [PATCH 1/4] [AArch64]  Use EXT for byte shuffles with leading zeros

Fixes: https://github.com/llvm/llvm-project/issues/191735

Teach AArch64 LowerVECTOR_SHUFFLE to recognize byte shuffles that are a
zero fill right shift and lower them to EXT with a zero vector. Adds a
regression test too.

Change-Id: Iffe97ff7e35cfaff790f537b4f1f5ba9aded4f92
---
 .../Target/AArch64/AArch64ISelLowering.cpp    | 21 +++++++++
 llvm/test/CodeGen/AArch64/shuffles.ll         | 46 ++++++++++++-------
 2 files changed, 50 insertions(+), 17 deletions(-)

diff --git a/llvm/lib/Target/AArch64/AArch64ISelLowering.cpp b/llvm/lib/Target/AArch64/AArch64ISelLowering.cpp
index 9b34d9b385b4e..13190d8472c18 100644
--- a/llvm/lib/Target/AArch64/AArch64ISelLowering.cpp
+++ b/llvm/lib/Target/AArch64/AArch64ISelLowering.cpp
@@ -15048,6 +15048,27 @@ SDValue AArch64TargetLowering::LowerVECTOR_SHUFFLE(SDValue Op,
                        DAG.getConstant(8, DL, MVT::i32));
   }
 
+  if (EltSize == 8 && V2.getValueType() == VT && isZeroOrZeroSplat(V2, true)) {
+    unsigned PrefixElts = 0;
+    while (PrefixElts != NumElts && (ShuffleMask[PrefixElts] < 0 ||
+                                     ShuffleMask[PrefixElts] >= (int)NumElts))
+      ++PrefixElts;
+
+    if (0 < PrefixElts && PrefixElts < NumElts) {
+      bool IsZeroShift = true;
+      for (unsigned I = PrefixElts; I != NumElts; ++I) {
+        if (ShuffleMask[I] >= 0 && ShuffleMask[I] != (int)(I - PrefixElts)) {
+          IsZeroShift = false;
+          break;
+        }
+      }
+
+      if (IsZeroShift)
+        return DAG.getNode(AArch64ISD::EXT, DL, VT, V2, V1,
+                           DAG.getConstant(NumElts - PrefixElts, DL, MVT::i32));
+    }
+  }
+
   bool ReverseEXT = false;
   unsigned Imm;
   if (isEXTMask(ShuffleMask, VT, ReverseEXT, Imm)) {
diff --git a/llvm/test/CodeGen/AArch64/shuffles.ll b/llvm/test/CodeGen/AArch64/shuffles.ll
index 930c3dfc54730..69ef3620395fd 100644
--- a/llvm/test/CodeGen/AArch64/shuffles.ll
+++ b/llvm/test/CodeGen/AArch64/shuffles.ll
@@ -443,12 +443,25 @@ define <8 x half> @test_shuf11(<8 x half> %a, <8 x half> %b)
   ret <8 x half> %r
 }
 
+define <16 x i8> @test_shuf_zero_ext_rhs(<16 x i8> %a) {
+; CHECKLE-LABEL: test_shuf_zero_ext_rhs:
+; CHECKLE:       // %bb.0:
+; CHECKLE-NEXT:    movi v1.2d, #0000000000000000
+; CHECKLE-NEXT:    ext v0.16b, v1.16b, v0.16b, #15
+; CHECKLE-NEXT:    ret
+;
+; CHECKBE-LABEL: test_shuf_zero_ext_rhs:
+; CHECKBE:       // %bb.0:
+  %r = shufflevector <16 x i8> %a, <16 x i8> zeroinitializer, <16 x i32> <i32 16, i32 0, i32 1, i32 2, i32 3, i32 4, i32 5, i32 6, i32 7, i32 8, i32 9, i32 10, i32 11, i32 12, i32 13, i32 14>
+  ret <16 x i8> %r
+}
+
 define <8 x half> @test_shuf12(<8 x half> %a, <8 x half> %b)
 ; CHECKLE-LABEL: test_shuf12:
 ; CHECKLE:       // %bb.0:
-; CHECKLE-NEXT:    adrp x8, .LCPI16_0
+; CHECKLE-NEXT:    adrp x8, .LCPI17_0
 ; CHECKLE-NEXT:    // kill: def $q1 killed $q1 killed $q0_q1 def $q0_q1
-; CHECKLE-NEXT:    ldr q2, [x8, :lo12:.LCPI16_0]
+; CHECKLE-NEXT:    ldr q2, [x8, :lo12:.LCPI17_0]
 ; CHECKLE-NEXT:    // kill: def $q0 killed $q0 killed $q0_q1 def $q0_q1
 ; CHECKLE-NEXT:    tbl v0.16b, { v0.16b, v1.16b }, v2.16b
 ; CHECKLE-NEXT:    ret
@@ -457,8 +470,8 @@ define <8 x half> @test_shuf12(<8 x half> %a, <8 x half> %b)
 ; CHECKBE:       // %bb.0:
 ; CHECKBE-NEXT:    rev64 v1.16b, v1.16b
 ; CHECKBE-NEXT:    rev64 v0.16b, v0.16b
-; CHECKBE-NEXT:    adrp x8, .LCPI16_0
-; CHECKBE-NEXT:    add x8, x8, :lo12:.LCPI16_0
+; CHECKBE-NEXT:    adrp x8, .LCPI17_0
+; CHECKBE-NEXT:    add x8, x8, :lo12:.LCPI17_0
 ; CHECKBE-NEXT:    ext v2.16b, v1.16b, v1.16b, #8
 ; CHECKBE-NEXT:    ext v1.16b, v0.16b, v0.16b, #8
 ; CHECKBE-NEXT:    ld1 { v0.16b }, [x8]
@@ -474,9 +487,9 @@ define <8 x half> @test_shuf12(<8 x half> %a, <8 x half> %b)
 define <8 x half> @test_shuf13(<8 x half> %a, <8 x half> %b)
 ; CHECKLE-LABEL: test_shuf13:
 ; CHECKLE:       // %bb.0:
-; CHECKLE-NEXT:    adrp x8, .LCPI17_0
+; CHECKLE-NEXT:    adrp x8, .LCPI18_0
 ; CHECKLE-NEXT:    // kill: def $q1 killed $q1 killed $q0_q1 def $q0_q1
-; CHECKLE-NEXT:    ldr q2, [x8, :lo12:.LCPI17_0]
+; CHECKLE-NEXT:    ldr q2, [x8, :lo12:.LCPI18_0]
 ; CHECKLE-NEXT:    // kill: def $q0 killed $q0 killed $q0_q1 def $q0_q1
 ; CHECKLE-NEXT:    tbl v0.16b, { v0.16b, v1.16b }, v2.16b
 ; CHECKLE-NEXT:    ret
@@ -485,8 +498,8 @@ define <8 x half> @test_shuf13(<8 x half> %a, <8 x half> %b)
 ; CHECKBE:       // %bb.0:
 ; CHECKBE-NEXT:    rev64 v1.16b, v1.16b
 ; CHECKBE-NEXT:    rev64 v0.16b, v0.16b
-; CHECKBE-NEXT:    adrp x8, .LCPI17_0
-; CHECKBE-NEXT:    add x8, x8, :lo12:.LCPI17_0
+; CHECKBE-NEXT:    adrp x8, .LCPI18_0
+; CHECKBE-NEXT:    add x8, x8, :lo12:.LCPI18_0
 ; CHECKBE-NEXT:    ext v2.16b, v1.16b, v1.16b, #8
 ; CHECKBE-NEXT:    ext v1.16b, v0.16b, v0.16b, #8
 ; CHECKBE-NEXT:    ld1 { v0.16b }, [x8]
@@ -502,9 +515,9 @@ define <8 x half> @test_shuf13(<8 x half> %a, <8 x half> %b)
 define <8 x half> @test_shuf14(<8 x half> %a, <8 x half> %b)
 ; CHECKLE-LABEL: test_shuf14:
 ; CHECKLE:       // %bb.0:
-; CHECKLE-NEXT:    adrp x8, .LCPI18_0
+; CHECKLE-NEXT:    adrp x8, .LCPI19_0
 ; CHECKLE-NEXT:    // kill: def $q1 killed $q1 killed $q0_q1 def $q0_q1
-; CHECKLE-NEXT:    ldr q2, [x8, :lo12:.LCPI18_0]
+; CHECKLE-NEXT:    ldr q2, [x8, :lo12:.LCPI19_0]
 ; CHECKLE-NEXT:    // kill: def $q0 killed $q0 killed $q0_q1 def $q0_q1
 ; CHECKLE-NEXT:    tbl v0.16b, { v0.16b, v1.16b }, v2.16b
 ; CHECKLE-NEXT:    ret
@@ -513,8 +526,8 @@ define <8 x half> @test_shuf14(<8 x half> %a, <8 x half> %b)
 ; CHECKBE:       // %bb.0:
 ; CHECKBE-NEXT:    rev64 v1.16b, v1.16b
 ; CHECKBE-NEXT:    rev64 v0.16b, v0.16b
-; CHECKBE-NEXT:    adrp x8, .LCPI18_0
-; CHECKBE-NEXT:    add x8, x8, :lo12:.LCPI18_0
+; CHECKBE-NEXT:    adrp x8, .LCPI19_0
+; CHECKBE-NEXT:    add x8, x8, :lo12:.LCPI19_0
 ; CHECKBE-NEXT:    ext v2.16b, v1.16b, v1.16b, #8
 ; CHECKBE-NEXT:    ext v1.16b, v0.16b, v0.16b, #8
 ; CHECKBE-NEXT:    ld1 { v0.16b }, [x8]
@@ -530,9 +543,9 @@ define <8 x half> @test_shuf14(<8 x half> %a, <8 x half> %b)
 define <8 x half> @test_shuf15(<8 x half> %a, <8 x half> %b)
 ; CHECKLE-LABEL: test_shuf15:
 ; CHECKLE:       // %bb.0:
-; CHECKLE-NEXT:    adrp x8, .LCPI19_0
+; CHECKLE-NEXT:    adrp x8, .LCPI20_0
 ; CHECKLE-NEXT:    // kill: def $q1 killed $q1 killed $q0_q1 def $q0_q1
-; CHECKLE-NEXT:    ldr q2, [x8, :lo12:.LCPI19_0]
+; CHECKLE-NEXT:    ldr q2, [x8, :lo12:.LCPI20_0]
 ; CHECKLE-NEXT:    // kill: def $q0 killed $q0 killed $q0_q1 def $q0_q1
 ; CHECKLE-NEXT:    tbl v0.16b, { v0.16b, v1.16b }, v2.16b
 ; CHECKLE-NEXT:    ret
@@ -541,8 +554,8 @@ define <8 x half> @test_shuf15(<8 x half> %a, <8 x half> %b)
 ; CHECKBE:       // %bb.0:
 ; CHECKBE-NEXT:    rev64 v1.16b, v1.16b
 ; CHECKBE-NEXT:    rev64 v0.16b, v0.16b
-; CHECKBE-NEXT:    adrp x8, .LCPI19_0
-; CHECKBE-NEXT:    add x8, x8, :lo12:.LCPI19_0
+; CHECKBE-NEXT:    adrp x8, .LCPI20_0
+; CHECKBE-NEXT:    add x8, x8, :lo12:.LCPI20_0
 ; CHECKBE-NEXT:    ext v2.16b, v1.16b, v1.16b, #8
 ; CHECKBE-NEXT:    ext v1.16b, v0.16b, v0.16b, #8
 ; CHECKBE-NEXT:    ld1 { v0.16b }, [x8]
@@ -575,4 +588,3 @@ define <4 x i32> @extract_shuffle(<8 x i16> %j, <4 x i16> %k) {
   %d = shl <4 x i32> %c, <i32 3, i32 3, i32 3, i32 3>
   ret <4 x i32> %d
 }
-

>From 4b38717ed117c609c98b19304b5bef3f3aedc997 Mon Sep 17 00:00:00 2001
From: Shreeyash Pandey <shrpand at qti.qualcomm.com>
Date: Wed, 29 Apr 2026 06:58:13 -0700
Subject: [PATCH 2/4] refactor to include other shuf patterns too

Change-Id: I2cfd7ce672ff3bc452b24f04087e1ddef4fe3ac1
---
 .../Target/AArch64/AArch64ISelLowering.cpp    |  92 +++++--
 .../CodeGen/AArch64/build-vector-extract.ll   |   4 +-
 .../CodeGen/AArch64/build-vector-two-dup.ll   |   5 +-
 llvm/test/CodeGen/AArch64/shuffles.ll         | 256 +++++++++++++++---
 4 files changed, 292 insertions(+), 65 deletions(-)

diff --git a/llvm/lib/Target/AArch64/AArch64ISelLowering.cpp b/llvm/lib/Target/AArch64/AArch64ISelLowering.cpp
index 13190d8472c18..f662771d945f7 100644
--- a/llvm/lib/Target/AArch64/AArch64ISelLowering.cpp
+++ b/llvm/lib/Target/AArch64/AArch64ISelLowering.cpp
@@ -14352,6 +14352,65 @@ static bool isEXTMask(ArrayRef<int> M, EVT VT, bool &ReverseEXT,
   return true;
 }
 
+// check if an EXT instruction can handle the shuffle mask when one source is a
+// splat. This matches shuffles where the splat occupies either a prefix or a
+// suffix and the remaining lanes are a contiguous slice from the non-splat
+// source.
+static bool isEXTMaskWithSplat(ArrayRef<int> M, EVT VT, unsigned SplatOperand,
+                               bool &ReverseEXT, unsigned &Imm) {
+  unsigned NumElts = VT.getVectorNumElements();
+  unsigned OtherBase = SplatOperand == 0 ? NumElts : 0;
+  auto IsSplatElt = [=](int Elt) {
+    return Elt < 0 ||
+           (SplatOperand == 0 ? Elt < (int)NumElts : Elt >= (int)NumElts);
+  };
+
+  unsigned PrefixSplatElts = 0;
+  while (PrefixSplatElts != NumElts && IsSplatElt(M[PrefixSplatElts]))
+    ++PrefixSplatElts;
+
+  if (0 < PrefixSplatElts && PrefixSplatElts < NumElts) {
+    bool Match = true;
+    for (unsigned I = PrefixSplatElts; I != NumElts; ++I) {
+      int Expected = OtherBase + I - PrefixSplatElts;
+      if (M[I] >= 0 && M[I] != Expected) {
+        Match = false;
+        break;
+      }
+    }
+
+    if (Match) {
+      ReverseEXT = SplatOperand == 1;
+      Imm = NumElts - PrefixSplatElts;
+      return true;
+    }
+  }
+
+  unsigned SuffixSplatElts = 0;
+  while (SuffixSplatElts != NumElts &&
+         IsSplatElt(M[NumElts - 1 - SuffixSplatElts]))
+    ++SuffixSplatElts;
+
+  if (0 < SuffixSplatElts && SuffixSplatElts < NumElts) {
+    bool Match = true;
+    for (unsigned I = 0; I != NumElts - SuffixSplatElts; ++I) {
+      int Expected = OtherBase + I + SuffixSplatElts;
+      if (M[I] >= 0 && M[I] != Expected) {
+        Match = false;
+        break;
+      }
+    }
+
+    if (Match) {
+      ReverseEXT = SplatOperand == 0;
+      Imm = SuffixSplatElts;
+      return true;
+    }
+  }
+
+  return false;
+}
+
 /// isZIP_v_undef_Mask - Special case of isZIPMask for canonical form of
 /// "vector_shuffle v, v", i.e., "vector_shuffle v, undef".
 /// Mask is e.g., <0, 0, 1, 1> instead of <0, 4, 1, 5>.
@@ -15048,24 +15107,23 @@ SDValue AArch64TargetLowering::LowerVECTOR_SHUFFLE(SDValue Op,
                        DAG.getConstant(8, DL, MVT::i32));
   }
 
-  if (EltSize == 8 && V2.getValueType() == VT && isZeroOrZeroSplat(V2, true)) {
-    unsigned PrefixElts = 0;
-    while (PrefixElts != NumElts && (ShuffleMask[PrefixElts] < 0 ||
-                                     ShuffleMask[PrefixElts] >= (int)NumElts))
-      ++PrefixElts;
-
-    if (0 < PrefixElts && PrefixElts < NumElts) {
-      bool IsZeroShift = true;
-      for (unsigned I = PrefixElts; I != NumElts; ++I) {
-        if (ShuffleMask[I] >= 0 && ShuffleMask[I] != (int)(I - PrefixElts)) {
-          IsZeroShift = false;
-          break;
-        }
-      }
+  bool IsSplat1 = V1.getValueType() == VT && DAG.isSplatValue(V1, true);
+  bool IsSplat2 = V2.getValueType() == VT && DAG.isSplatValue(V2, true);
+  for (unsigned SplatOperand : {0U, 1U}) {
+    if ((SplatOperand == 0 && !IsSplat1) || (SplatOperand == 1 && !IsSplat2))
+      continue;
 
-      if (IsZeroShift)
-        return DAG.getNode(AArch64ISD::EXT, DL, VT, V2, V1,
-                           DAG.getConstant(NumElts - PrefixElts, DL, MVT::i32));
+    bool ReverseSplatEXT = false;
+    unsigned SplatImm;
+    if (isEXTMaskWithSplat(ShuffleMask, VT, SplatOperand, ReverseSplatEXT,
+                           SplatImm)) {
+      SDValue ExtOp1 = V1;
+      SDValue ExtOp2 = V2;
+      if (ReverseSplatEXT)
+        std::swap(ExtOp1, ExtOp2);
+      SplatImm *= getExtFactor(ExtOp1);
+      return DAG.getNode(AArch64ISD::EXT, DL, VT, ExtOp1, ExtOp2,
+                         DAG.getConstant(SplatImm, DL, MVT::i32));
     }
   }
 
diff --git a/llvm/test/CodeGen/AArch64/build-vector-extract.ll b/llvm/test/CodeGen/AArch64/build-vector-extract.ll
index 36b1b2cdcb432..f3e40021b616a 100644
--- a/llvm/test/CodeGen/AArch64/build-vector-extract.ll
+++ b/llvm/test/CodeGen/AArch64/build-vector-extract.ll
@@ -91,8 +91,7 @@ define <2 x i64> @extract3_i32_zext_insert0_i64_zero(<4 x i32> %x) {
 ; CHECK-LABEL: extract3_i32_zext_insert0_i64_zero:
 ; CHECK:       // %bb.0:
 ; CHECK-NEXT:    movi v1.2d, #0000000000000000
-; CHECK-NEXT:    mov v1.s[0], v0.s[3]
-; CHECK-NEXT:    mov v0.16b, v1.16b
+; CHECK-NEXT:    ext v0.16b, v0.16b, v1.16b, #12
 ; CHECK-NEXT:    ret
   %e = extractelement <4 x i32> %x, i32 3
   %z = zext i32 %e to i64
@@ -640,4 +639,3 @@ define <4 x i32> @larger_bv_than_source(<4 x i16> %t0) {
   %t2 = insertelement <4 x i32> undef, i32 %vgetq_lane, i64 0
   ret <4 x i32> %t2
 }
-
diff --git a/llvm/test/CodeGen/AArch64/build-vector-two-dup.ll b/llvm/test/CodeGen/AArch64/build-vector-two-dup.ll
index f725c19081deb..1bd2ceb815ead 100644
--- a/llvm/test/CodeGen/AArch64/build-vector-two-dup.ll
+++ b/llvm/test/CodeGen/AArch64/build-vector-two-dup.ll
@@ -22,10 +22,9 @@ entry:
 define <16 x i8> @test2(ptr nocapture noundef readonly %a, ptr nocapture noundef readonly %b) {
 ; CHECK-LABEL: test2:
 ; CHECK:       // %bb.0: // %entry
+; CHECK-NEXT:    ld1r { v0.8b }, [x0]
 ; CHECK-NEXT:    ld1r { v1.8b }, [x1]
-; CHECK-NEXT:    ldrb w8, [x0]
-; CHECK-NEXT:    dup v0.8b, w8
-; CHECK-NEXT:    mov v1.b[7], w8
+; CHECK-NEXT:    ext v1.8b, v1.8b, v0.8b, #1
 ; CHECK-NEXT:    mov v0.d[1], v1.d[0]
 ; CHECK-NEXT:    ret
 entry:
diff --git a/llvm/test/CodeGen/AArch64/shuffles.ll b/llvm/test/CodeGen/AArch64/shuffles.ll
index 69ef3620395fd..c0249309d5eb0 100644
--- a/llvm/test/CodeGen/AArch64/shuffles.ll
+++ b/llvm/test/CodeGen/AArch64/shuffles.ll
@@ -6,18 +6,18 @@ define <16 x i32> @test_shuf1(<16 x i32> %x, <16 x i32> %y) {
 ; CHECKLE-LABEL: test_shuf1:
 ; CHECKLE:       // %bb.0:
 ; CHECKLE-NEXT:    ext v3.16b, v6.16b, v1.16b, #4
-; CHECKLE-NEXT:    uzp1 v5.4s, v1.4s, v0.4s
 ; CHECKLE-NEXT:    uzp2 v16.4s, v2.4s, v4.4s
-; CHECKLE-NEXT:    dup v17.4s, v4.s[0]
+; CHECKLE-NEXT:    dup v4.4s, v4.s[0]
+; CHECKLE-NEXT:    uzp1 v5.4s, v1.4s, v0.4s
+; CHECKLE-NEXT:    ext v6.16b, v6.16b, v4.16b, #12
 ; CHECKLE-NEXT:    trn2 v4.4s, v1.4s, v3.4s
-; CHECKLE-NEXT:    mov v17.s[0], v6.s[3]
-; CHECKLE-NEXT:    trn2 v1.4s, v5.4s, v1.4s
 ; CHECKLE-NEXT:    rev64 v3.4s, v7.4s
 ; CHECKLE-NEXT:    trn1 v2.4s, v16.4s, v2.4s
+; CHECKLE-NEXT:    trn2 v1.4s, v5.4s, v1.4s
 ; CHECKLE-NEXT:    mov v4.s[0], v7.s[1]
-; CHECKLE-NEXT:    ext v1.16b, v0.16b, v1.16b, #12
-; CHECKLE-NEXT:    mov v3.d[0], v17.d[0]
+; CHECKLE-NEXT:    mov v3.d[0], v6.d[0]
 ; CHECKLE-NEXT:    mov v2.s[3], v7.s[0]
+; CHECKLE-NEXT:    ext v1.16b, v0.16b, v1.16b, #12
 ; CHECKLE-NEXT:    mov v0.16b, v4.16b
 ; CHECKLE-NEXT:    ret
 ;
@@ -41,21 +41,21 @@ define <16 x i32> @test_shuf1(<16 x i32> %x, <16 x i32> %y) {
 ; CHECKBE-NEXT:    dup v4.4s, v4.s[0]
 ; CHECKBE-NEXT:    rev64 v17.4s, v5.4s
 ; CHECKBE-NEXT:    trn2 v6.4s, v1.4s, v6.4s
-; CHECKBE-NEXT:    mov v4.s[0], v3.s[3]
+; CHECKBE-NEXT:    ext v3.16b, v3.16b, v4.16b, #12
 ; CHECKBE-NEXT:    trn2 v1.4s, v16.4s, v1.4s
 ; CHECKBE-NEXT:    trn1 v2.4s, v7.4s, v2.4s
-; CHECKBE-NEXT:    rev64 v3.4s, v17.4s
+; CHECKBE-NEXT:    rev64 v4.4s, v17.4s
 ; CHECKBE-NEXT:    mov v6.s[0], v5.s[1]
-; CHECKBE-NEXT:    rev64 v4.4s, v4.4s
+; CHECKBE-NEXT:    rev64 v3.4s, v3.4s
 ; CHECKBE-NEXT:    ext v0.16b, v0.16b, v1.16b, #12
 ; CHECKBE-NEXT:    mov v2.s[3], v5.s[0]
 ; CHECKBE-NEXT:    rev64 v1.4s, v6.4s
-; CHECKBE-NEXT:    mov v3.d[0], v4.d[0]
-; CHECKBE-NEXT:    rev64 v4.4s, v0.4s
+; CHECKBE-NEXT:    mov v4.d[0], v3.d[0]
+; CHECKBE-NEXT:    rev64 v5.4s, v0.4s
 ; CHECKBE-NEXT:    rev64 v2.4s, v2.4s
 ; CHECKBE-NEXT:    ext v0.16b, v1.16b, v1.16b, #8
-; CHECKBE-NEXT:    ext v3.16b, v3.16b, v3.16b, #8
-; CHECKBE-NEXT:    ext v1.16b, v4.16b, v4.16b, #8
+; CHECKBE-NEXT:    ext v3.16b, v4.16b, v4.16b, #8
+; CHECKBE-NEXT:    ext v1.16b, v5.16b, v5.16b, #8
 ; CHECKBE-NEXT:    ext v2.16b, v2.16b, v2.16b, #8
 ; CHECKBE-NEXT:    ret
   %s3 = shufflevector <16 x i32> %x, <16 x i32> %y, <16 x i32> <i32 29, i32 26, i32 7, i32 4, i32 3, i32 6, i32 5, i32 2, i32 9, i32 8, i32 17, i32 28, i32 27, i32 16, i32 31, i32 30>
@@ -443,25 +443,12 @@ define <8 x half> @test_shuf11(<8 x half> %a, <8 x half> %b)
   ret <8 x half> %r
 }
 
-define <16 x i8> @test_shuf_zero_ext_rhs(<16 x i8> %a) {
-; CHECKLE-LABEL: test_shuf_zero_ext_rhs:
-; CHECKLE:       // %bb.0:
-; CHECKLE-NEXT:    movi v1.2d, #0000000000000000
-; CHECKLE-NEXT:    ext v0.16b, v1.16b, v0.16b, #15
-; CHECKLE-NEXT:    ret
-;
-; CHECKBE-LABEL: test_shuf_zero_ext_rhs:
-; CHECKBE:       // %bb.0:
-  %r = shufflevector <16 x i8> %a, <16 x i8> zeroinitializer, <16 x i32> <i32 16, i32 0, i32 1, i32 2, i32 3, i32 4, i32 5, i32 6, i32 7, i32 8, i32 9, i32 10, i32 11, i32 12, i32 13, i32 14>
-  ret <16 x i8> %r
-}
-
 define <8 x half> @test_shuf12(<8 x half> %a, <8 x half> %b)
 ; CHECKLE-LABEL: test_shuf12:
 ; CHECKLE:       // %bb.0:
-; CHECKLE-NEXT:    adrp x8, .LCPI17_0
+; CHECKLE-NEXT:    adrp x8, .LCPI16_0
 ; CHECKLE-NEXT:    // kill: def $q1 killed $q1 killed $q0_q1 def $q0_q1
-; CHECKLE-NEXT:    ldr q2, [x8, :lo12:.LCPI17_0]
+; CHECKLE-NEXT:    ldr q2, [x8, :lo12:.LCPI16_0]
 ; CHECKLE-NEXT:    // kill: def $q0 killed $q0 killed $q0_q1 def $q0_q1
 ; CHECKLE-NEXT:    tbl v0.16b, { v0.16b, v1.16b }, v2.16b
 ; CHECKLE-NEXT:    ret
@@ -470,8 +457,8 @@ define <8 x half> @test_shuf12(<8 x half> %a, <8 x half> %b)
 ; CHECKBE:       // %bb.0:
 ; CHECKBE-NEXT:    rev64 v1.16b, v1.16b
 ; CHECKBE-NEXT:    rev64 v0.16b, v0.16b
-; CHECKBE-NEXT:    adrp x8, .LCPI17_0
-; CHECKBE-NEXT:    add x8, x8, :lo12:.LCPI17_0
+; CHECKBE-NEXT:    adrp x8, .LCPI16_0
+; CHECKBE-NEXT:    add x8, x8, :lo12:.LCPI16_0
 ; CHECKBE-NEXT:    ext v2.16b, v1.16b, v1.16b, #8
 ; CHECKBE-NEXT:    ext v1.16b, v0.16b, v0.16b, #8
 ; CHECKBE-NEXT:    ld1 { v0.16b }, [x8]
@@ -487,9 +474,9 @@ define <8 x half> @test_shuf12(<8 x half> %a, <8 x half> %b)
 define <8 x half> @test_shuf13(<8 x half> %a, <8 x half> %b)
 ; CHECKLE-LABEL: test_shuf13:
 ; CHECKLE:       // %bb.0:
-; CHECKLE-NEXT:    adrp x8, .LCPI18_0
+; CHECKLE-NEXT:    adrp x8, .LCPI17_0
 ; CHECKLE-NEXT:    // kill: def $q1 killed $q1 killed $q0_q1 def $q0_q1
-; CHECKLE-NEXT:    ldr q2, [x8, :lo12:.LCPI18_0]
+; CHECKLE-NEXT:    ldr q2, [x8, :lo12:.LCPI17_0]
 ; CHECKLE-NEXT:    // kill: def $q0 killed $q0 killed $q0_q1 def $q0_q1
 ; CHECKLE-NEXT:    tbl v0.16b, { v0.16b, v1.16b }, v2.16b
 ; CHECKLE-NEXT:    ret
@@ -498,8 +485,8 @@ define <8 x half> @test_shuf13(<8 x half> %a, <8 x half> %b)
 ; CHECKBE:       // %bb.0:
 ; CHECKBE-NEXT:    rev64 v1.16b, v1.16b
 ; CHECKBE-NEXT:    rev64 v0.16b, v0.16b
-; CHECKBE-NEXT:    adrp x8, .LCPI18_0
-; CHECKBE-NEXT:    add x8, x8, :lo12:.LCPI18_0
+; CHECKBE-NEXT:    adrp x8, .LCPI17_0
+; CHECKBE-NEXT:    add x8, x8, :lo12:.LCPI17_0
 ; CHECKBE-NEXT:    ext v2.16b, v1.16b, v1.16b, #8
 ; CHECKBE-NEXT:    ext v1.16b, v0.16b, v0.16b, #8
 ; CHECKBE-NEXT:    ld1 { v0.16b }, [x8]
@@ -515,9 +502,9 @@ define <8 x half> @test_shuf13(<8 x half> %a, <8 x half> %b)
 define <8 x half> @test_shuf14(<8 x half> %a, <8 x half> %b)
 ; CHECKLE-LABEL: test_shuf14:
 ; CHECKLE:       // %bb.0:
-; CHECKLE-NEXT:    adrp x8, .LCPI19_0
+; CHECKLE-NEXT:    adrp x8, .LCPI18_0
 ; CHECKLE-NEXT:    // kill: def $q1 killed $q1 killed $q0_q1 def $q0_q1
-; CHECKLE-NEXT:    ldr q2, [x8, :lo12:.LCPI19_0]
+; CHECKLE-NEXT:    ldr q2, [x8, :lo12:.LCPI18_0]
 ; CHECKLE-NEXT:    // kill: def $q0 killed $q0 killed $q0_q1 def $q0_q1
 ; CHECKLE-NEXT:    tbl v0.16b, { v0.16b, v1.16b }, v2.16b
 ; CHECKLE-NEXT:    ret
@@ -526,8 +513,8 @@ define <8 x half> @test_shuf14(<8 x half> %a, <8 x half> %b)
 ; CHECKBE:       // %bb.0:
 ; CHECKBE-NEXT:    rev64 v1.16b, v1.16b
 ; CHECKBE-NEXT:    rev64 v0.16b, v0.16b
-; CHECKBE-NEXT:    adrp x8, .LCPI19_0
-; CHECKBE-NEXT:    add x8, x8, :lo12:.LCPI19_0
+; CHECKBE-NEXT:    adrp x8, .LCPI18_0
+; CHECKBE-NEXT:    add x8, x8, :lo12:.LCPI18_0
 ; CHECKBE-NEXT:    ext v2.16b, v1.16b, v1.16b, #8
 ; CHECKBE-NEXT:    ext v1.16b, v0.16b, v0.16b, #8
 ; CHECKBE-NEXT:    ld1 { v0.16b }, [x8]
@@ -543,9 +530,9 @@ define <8 x half> @test_shuf14(<8 x half> %a, <8 x half> %b)
 define <8 x half> @test_shuf15(<8 x half> %a, <8 x half> %b)
 ; CHECKLE-LABEL: test_shuf15:
 ; CHECKLE:       // %bb.0:
-; CHECKLE-NEXT:    adrp x8, .LCPI20_0
+; CHECKLE-NEXT:    adrp x8, .LCPI19_0
 ; CHECKLE-NEXT:    // kill: def $q1 killed $q1 killed $q0_q1 def $q0_q1
-; CHECKLE-NEXT:    ldr q2, [x8, :lo12:.LCPI20_0]
+; CHECKLE-NEXT:    ldr q2, [x8, :lo12:.LCPI19_0]
 ; CHECKLE-NEXT:    // kill: def $q0 killed $q0 killed $q0_q1 def $q0_q1
 ; CHECKLE-NEXT:    tbl v0.16b, { v0.16b, v1.16b }, v2.16b
 ; CHECKLE-NEXT:    ret
@@ -554,8 +541,8 @@ define <8 x half> @test_shuf15(<8 x half> %a, <8 x half> %b)
 ; CHECKBE:       // %bb.0:
 ; CHECKBE-NEXT:    rev64 v1.16b, v1.16b
 ; CHECKBE-NEXT:    rev64 v0.16b, v0.16b
-; CHECKBE-NEXT:    adrp x8, .LCPI20_0
-; CHECKBE-NEXT:    add x8, x8, :lo12:.LCPI20_0
+; CHECKBE-NEXT:    adrp x8, .LCPI19_0
+; CHECKBE-NEXT:    add x8, x8, :lo12:.LCPI19_0
 ; CHECKBE-NEXT:    ext v2.16b, v1.16b, v1.16b, #8
 ; CHECKBE-NEXT:    ext v1.16b, v0.16b, v0.16b, #8
 ; CHECKBE-NEXT:    ld1 { v0.16b }, [x8]
@@ -588,3 +575,188 @@ define <4 x i32> @extract_shuffle(<8 x i16> %j, <4 x i16> %k) {
   %d = shl <4 x i32> %c, <i32 3, i32 3, i32 3, i32 3>
   ret <4 x i32> %d
 }
+
+; Zero/splat-fill EXT: splat prefix (zero inserted at the start, data shifted right)
+define <16 x i8> @test_shuf_zero_ext_start_lhs(<16 x i8> %a) {
+; CHECKLE-LABEL: test_shuf_zero_ext_start_lhs:
+; CHECKLE:       // %bb.0:
+; CHECKLE-NEXT:    movi v1.2d, #0000000000000000
+; CHECKLE-NEXT:    ext v0.16b, v1.16b, v0.16b, #15
+; CHECKLE-NEXT:    ret
+;
+; CHECKBE-LABEL: test_shuf_zero_ext_start_lhs:
+; CHECKBE:       // %bb.0:
+; CHECKBE-NEXT:    rev64 v0.16b, v0.16b
+; CHECKBE-NEXT:    movi v1.2d, #0000000000000000
+; CHECKBE-NEXT:    ext v0.16b, v0.16b, v0.16b, #8
+; CHECKBE-NEXT:    ext v0.16b, v1.16b, v0.16b, #15
+; CHECKBE-NEXT:    rev64 v0.16b, v0.16b
+; CHECKBE-NEXT:    ext v0.16b, v0.16b, v0.16b, #8
+; CHECKBE-NEXT:    ret
+  %r = shufflevector <16 x i8> %a, <16 x i8> zeroinitializer, <16 x i32> <i32 16, i32 0, i32 1, i32 2, i32 3, i32 4, i32 5, i32 6, i32 7, i32 8, i32 9, i32 10, i32 11, i32 12, i32 13, i32 14>
+  ret <16 x i8> %r
+}
+
+define <16 x i8> @test_shuf_zero_ext_start_lhs2(<16 x i8> %a) {
+; CHECKLE-LABEL: test_shuf_zero_ext_start_lhs2:
+; CHECKLE:       // %bb.0:
+; CHECKLE-NEXT:    movi v1.2d, #0000000000000000
+; CHECKLE-NEXT:    ext v0.16b, v1.16b, v0.16b, #14
+; CHECKLE-NEXT:    ret
+;
+; CHECKBE-LABEL: test_shuf_zero_ext_start_lhs2:
+; CHECKBE:       // %bb.0:
+; CHECKBE-NEXT:    rev64 v0.16b, v0.16b
+; CHECKBE-NEXT:    movi v1.2d, #0000000000000000
+; CHECKBE-NEXT:    ext v0.16b, v0.16b, v0.16b, #8
+; CHECKBE-NEXT:    ext v0.16b, v1.16b, v0.16b, #14
+; CHECKBE-NEXT:    rev64 v0.16b, v0.16b
+; CHECKBE-NEXT:    ext v0.16b, v0.16b, v0.16b, #8
+; CHECKBE-NEXT:    ret
+  %r = shufflevector <16 x i8> %a, <16 x i8> zeroinitializer, <16 x i32> <i32 16, i32 16, i32 0, i32 1, i32 2, i32 3, i32 4, i32 5, i32 6, i32 7, i32 8, i32 9, i32 10, i32 11, i32 12, i32 13>
+  ret <16 x i8> %r
+}
+
+define <16 x i8> @test_shuf_zero_ext_start_rhs(<16 x i8> %a) {
+; CHECKLE-LABEL: test_shuf_zero_ext_start_rhs:
+; CHECKLE:       // %bb.0:
+; CHECKLE-NEXT:    movi v1.2d, #0000000000000000
+; CHECKLE-NEXT:    ext v0.16b, v1.16b, v0.16b, #15
+; CHECKLE-NEXT:    ret
+;
+; CHECKBE-LABEL: test_shuf_zero_ext_start_rhs:
+; CHECKBE:       // %bb.0:
+; CHECKBE-NEXT:    rev64 v0.16b, v0.16b
+; CHECKBE-NEXT:    movi v1.2d, #0000000000000000
+; CHECKBE-NEXT:    ext v0.16b, v0.16b, v0.16b, #8
+; CHECKBE-NEXT:    ext v0.16b, v1.16b, v0.16b, #15
+; CHECKBE-NEXT:    rev64 v0.16b, v0.16b
+; CHECKBE-NEXT:    ext v0.16b, v0.16b, v0.16b, #8
+; CHECKBE-NEXT:    ret
+  %r = shufflevector <16 x i8> zeroinitializer, <16 x i8> %a, <16 x i32> <i32 0, i32 16, i32 17, i32 18, i32 19, i32 20, i32 21, i32 22, i32 23, i32 24, i32 25, i32 26, i32 27, i32 28, i32 29, i32 30>
+  ret <16 x i8> %r
+}
+
+define <16 x i8> @test_shuf_zero_ext_start_rhs2(<16 x i8> %a) {
+; CHECKLE-LABEL: test_shuf_zero_ext_start_rhs2:
+; CHECKLE:       // %bb.0:
+; CHECKLE-NEXT:    movi v1.2d, #0000000000000000
+; CHECKLE-NEXT:    ext v0.16b, v1.16b, v0.16b, #14
+; CHECKLE-NEXT:    ret
+;
+; CHECKBE-LABEL: test_shuf_zero_ext_start_rhs2:
+; CHECKBE:       // %bb.0:
+; CHECKBE-NEXT:    rev64 v0.16b, v0.16b
+; CHECKBE-NEXT:    movi v1.2d, #0000000000000000
+; CHECKBE-NEXT:    ext v0.16b, v0.16b, v0.16b, #8
+; CHECKBE-NEXT:    ext v0.16b, v1.16b, v0.16b, #14
+; CHECKBE-NEXT:    rev64 v0.16b, v0.16b
+; CHECKBE-NEXT:    ext v0.16b, v0.16b, v0.16b, #8
+; CHECKBE-NEXT:    ret
+  %r = shufflevector <16 x i8> zeroinitializer, <16 x i8> %a, <16 x i32> <i32 0, i32 0, i32 16, i32 17, i32 18, i32 19, i32 20, i32 21, i32 22, i32 23, i32 24, i32 25, i32 26, i32 27, i32 28, i32 29>
+  ret <16 x i8> %r
+}
+
+; Zero/splat-fill EXT: splat suffix (zero appended at the end, data shifted left)
+define <16 x i8> @test_shuf_zero_ext_end_lhs(<16 x i8> %a) {
+; CHECKLE-LABEL: test_shuf_zero_ext_end_lhs:
+; CHECKLE:       // %bb.0:
+; CHECKLE-NEXT:    movi v1.2d, #0000000000000000
+; CHECKLE-NEXT:    ext v0.16b, v0.16b, v1.16b, #1
+; CHECKLE-NEXT:    ret
+;
+; CHECKBE-LABEL: test_shuf_zero_ext_end_lhs:
+; CHECKBE:       // %bb.0:
+; CHECKBE-NEXT:    rev64 v0.16b, v0.16b
+; CHECKBE-NEXT:    movi v1.2d, #0000000000000000
+; CHECKBE-NEXT:    ext v0.16b, v0.16b, v0.16b, #8
+; CHECKBE-NEXT:    ext v0.16b, v0.16b, v1.16b, #1
+; CHECKBE-NEXT:    rev64 v0.16b, v0.16b
+; CHECKBE-NEXT:    ext v0.16b, v0.16b, v0.16b, #8
+; CHECKBE-NEXT:    ret
+  %r = shufflevector <16 x i8> %a, <16 x i8> zeroinitializer, <16 x i32> <i32 1, i32 2, i32 3, i32 4, i32 5, i32 6, i32 7, i32 8, i32 9, i32 10, i32 11, i32 12, i32 13, i32 14, i32 15, i32 16>
+  ret <16 x i8> %r
+}
+
+define <16 x i8> @test_shuf_zero_ext_end_lhs2(<16 x i8> %a) {
+; CHECKLE-LABEL: test_shuf_zero_ext_end_lhs2:
+; CHECKLE:       // %bb.0:
+; CHECKLE-NEXT:    movi v1.2d, #0000000000000000
+; CHECKLE-NEXT:    ext v0.16b, v0.16b, v1.16b, #2
+; CHECKLE-NEXT:    ret
+;
+; CHECKBE-LABEL: test_shuf_zero_ext_end_lhs2:
+; CHECKBE:       // %bb.0:
+; CHECKBE-NEXT:    rev64 v0.16b, v0.16b
+; CHECKBE-NEXT:    movi v1.2d, #0000000000000000
+; CHECKBE-NEXT:    ext v0.16b, v0.16b, v0.16b, #8
+; CHECKBE-NEXT:    ext v0.16b, v0.16b, v1.16b, #2
+; CHECKBE-NEXT:    rev64 v0.16b, v0.16b
+; CHECKBE-NEXT:    ext v0.16b, v0.16b, v0.16b, #8
+; CHECKBE-NEXT:    ret
+  %r = shufflevector <16 x i8> %a, <16 x i8> zeroinitializer, <16 x i32> <i32 2, i32 3, i32 4, i32 5, i32 6, i32 7, i32 8, i32 9, i32 10, i32 11, i32 12, i32 13, i32 14, i32 15, i32 16, i32 16>
+  ret <16 x i8> %r
+}
+
+define <16 x i8> @test_shuf_zero_ext_end_rhs(<16 x i8> %a) {
+; CHECKLE-LABEL: test_shuf_zero_ext_end_rhs:
+; CHECKLE:       // %bb.0:
+; CHECKLE-NEXT:    movi v1.2d, #0000000000000000
+; CHECKLE-NEXT:    ext v0.16b, v1.16b, v0.16b, #15
+; CHECKLE-NEXT:    ret
+;
+; CHECKBE-LABEL: test_shuf_zero_ext_end_rhs:
+; CHECKBE:       // %bb.0:
+; CHECKBE-NEXT:    rev64 v0.16b, v0.16b
+; CHECKBE-NEXT:    movi v1.2d, #0000000000000000
+; CHECKBE-NEXT:    ext v0.16b, v0.16b, v0.16b, #8
+; CHECKBE-NEXT:    ext v0.16b, v1.16b, v0.16b, #15
+; CHECKBE-NEXT:    rev64 v0.16b, v0.16b
+; CHECKBE-NEXT:    ext v0.16b, v0.16b, v0.16b, #8
+; CHECKBE-NEXT:    ret
+  %r = shufflevector <16 x i8> zeroinitializer, <16 x i8> %a, <16 x i32> <i32 0, i32 16, i32 17, i32 18, i32 19, i32 20, i32 21, i32 22, i32 23, i32 24, i32 25, i32 26, i32 27, i32 28, i32 29, i32 30>
+  ret <16 x i8> %r
+}
+
+define <16 x i8> @test_shuf_zero_ext_end_rhs2(<16 x i8> %a) {
+; CHECKLE-LABEL: test_shuf_zero_ext_end_rhs2:
+; CHECKLE:       // %bb.0:
+; CHECKLE-NEXT:    movi v1.2d, #0000000000000000
+; CHECKLE-NEXT:    ext v0.16b, v1.16b, v0.16b, #14
+; CHECKLE-NEXT:    ret
+;
+; CHECKBE-LABEL: test_shuf_zero_ext_end_rhs2:
+; CHECKBE:       // %bb.0:
+; CHECKBE-NEXT:    rev64 v0.16b, v0.16b
+; CHECKBE-NEXT:    movi v1.2d, #0000000000000000
+; CHECKBE-NEXT:    ext v0.16b, v0.16b, v0.16b, #8
+; CHECKBE-NEXT:    ext v0.16b, v1.16b, v0.16b, #14
+; CHECKBE-NEXT:    rev64 v0.16b, v0.16b
+; CHECKBE-NEXT:    ext v0.16b, v0.16b, v0.16b, #8
+; CHECKBE-NEXT:    ret
+  %r = shufflevector <16 x i8> zeroinitializer, <16 x i8> %a, <16 x i32> <i32 0, i32 0, i32 16, i32 17, i32 18, i32 19, i32 20, i32 21, i32 22, i32 23, i32 24, i32 25, i32 26, i32 27, i32 28, i32 29>
+  ret <16 x i8> %r
+}
+
+; Zero/splat-fill EXT: non-zero splat prefix (splat of a scalar, data shifted right)
+define <4 x i32> @test_shuf_zero_ext_start_lhs_splat(<4 x i32> %a, i32 %b) {
+; CHECKLE-LABEL: test_shuf_zero_ext_start_lhs_splat:
+; CHECKLE:       // %bb.0:
+; CHECKLE-NEXT:    dup v1.4s, w0
+; CHECKLE-NEXT:    ext v0.16b, v1.16b, v0.16b, #12
+; CHECKLE-NEXT:    ret
+;
+; CHECKBE-LABEL: test_shuf_zero_ext_start_lhs_splat:
+; CHECKBE:       // %bb.0:
+; CHECKBE-NEXT:    rev64 v0.4s, v0.4s
+; CHECKBE-NEXT:    dup v1.4s, w0
+; CHECKBE-NEXT:    ext v0.16b, v0.16b, v0.16b, #8
+; CHECKBE-NEXT:    ext v0.16b, v1.16b, v0.16b, #12
+; CHECKBE-NEXT:    rev64 v0.4s, v0.4s
+; CHECKBE-NEXT:    ext v0.16b, v0.16b, v0.16b, #8
+; CHECKBE-NEXT:    ret
+  %i = insertelement <4 x i32> poison, i32 %b, i64 0
+  %s = shufflevector <4 x i32> %i, <4 x i32> poison, <4 x i32> zeroinitializer
+  %r = shufflevector <4 x i32> %a, <4 x i32> %s, <4 x i32> <i32 4, i32 0, i32 1, i32 2>
+  ret <4 x i32> %r
+}

>From 6b382ac8b0de1ef270388353137a1787d5dde5d9 Mon Sep 17 00:00:00 2001
From: Shreeyash Pandey <shrpand at qti.qualcomm.com>
Date: Thu, 7 May 2026 04:28:17 -0700
Subject: [PATCH 3/4] address comments

Change-Id: Id4b75ae80855b02fac4010aa564786f31fd9be8e
---
 .../Target/AArch64/AArch64ISelLowering.cpp    |  8 ++--
 llvm/test/CodeGen/AArch64/shuffles.ll         | 38 +++++++++----------
 2 files changed, 23 insertions(+), 23 deletions(-)

diff --git a/llvm/lib/Target/AArch64/AArch64ISelLowering.cpp b/llvm/lib/Target/AArch64/AArch64ISelLowering.cpp
index f662771d945f7..b64dcc46ec633 100644
--- a/llvm/lib/Target/AArch64/AArch64ISelLowering.cpp
+++ b/llvm/lib/Target/AArch64/AArch64ISelLowering.cpp
@@ -14352,7 +14352,7 @@ static bool isEXTMask(ArrayRef<int> M, EVT VT, bool &ReverseEXT,
   return true;
 }
 
-// check if an EXT instruction can handle the shuffle mask when one source is a
+// Check if an EXT instruction can handle the shuffle mask when one source is a
 // splat. This matches shuffles where the splat occupies either a prefix or a
 // suffix and the remaining lanes are a contiguous slice from the non-splat
 // source.
@@ -14369,7 +14369,7 @@ static bool isEXTMaskWithSplat(ArrayRef<int> M, EVT VT, unsigned SplatOperand,
   while (PrefixSplatElts != NumElts && IsSplatElt(M[PrefixSplatElts]))
     ++PrefixSplatElts;
 
-  if (0 < PrefixSplatElts && PrefixSplatElts < NumElts) {
+  if (PrefixSplatElts > 0 && PrefixSplatElts < NumElts) {
     bool Match = true;
     for (unsigned I = PrefixSplatElts; I != NumElts; ++I) {
       int Expected = OtherBase + I - PrefixSplatElts;
@@ -15107,8 +15107,8 @@ SDValue AArch64TargetLowering::LowerVECTOR_SHUFFLE(SDValue Op,
                        DAG.getConstant(8, DL, MVT::i32));
   }
 
-  bool IsSplat1 = V1.getValueType() == VT && DAG.isSplatValue(V1, true);
-  bool IsSplat2 = V2.getValueType() == VT && DAG.isSplatValue(V2, true);
+  bool IsSplat1 = V1.getValueType() == VT && DAG.isSplatValue(V1, /*AllowUndefs=*/false);
+  bool IsSplat2 = V2.getValueType() == VT && DAG.isSplatValue(V2, /*AllowUndefs=*/false);
   for (unsigned SplatOperand : {0U, 1U}) {
     if ((SplatOperand == 0 && !IsSplat1) || (SplatOperand == 1 && !IsSplat2))
       continue;
diff --git a/llvm/test/CodeGen/AArch64/shuffles.ll b/llvm/test/CodeGen/AArch64/shuffles.ll
index c0249309d5eb0..375aff747d768 100644
--- a/llvm/test/CodeGen/AArch64/shuffles.ll
+++ b/llvm/test/CodeGen/AArch64/shuffles.ll
@@ -6,18 +6,18 @@ define <16 x i32> @test_shuf1(<16 x i32> %x, <16 x i32> %y) {
 ; CHECKLE-LABEL: test_shuf1:
 ; CHECKLE:       // %bb.0:
 ; CHECKLE-NEXT:    ext v3.16b, v6.16b, v1.16b, #4
-; CHECKLE-NEXT:    uzp2 v16.4s, v2.4s, v4.4s
-; CHECKLE-NEXT:    dup v4.4s, v4.s[0]
 ; CHECKLE-NEXT:    uzp1 v5.4s, v1.4s, v0.4s
-; CHECKLE-NEXT:    ext v6.16b, v6.16b, v4.16b, #12
+; CHECKLE-NEXT:    uzp2 v16.4s, v2.4s, v4.4s
+; CHECKLE-NEXT:    dup v17.4s, v4.s[0]
 ; CHECKLE-NEXT:    trn2 v4.4s, v1.4s, v3.4s
+; CHECKLE-NEXT:    mov v17.s[0], v6.s[3]
+; CHECKLE-NEXT:    trn2 v1.4s, v5.4s, v1.4s
 ; CHECKLE-NEXT:    rev64 v3.4s, v7.4s
 ; CHECKLE-NEXT:    trn1 v2.4s, v16.4s, v2.4s
-; CHECKLE-NEXT:    trn2 v1.4s, v5.4s, v1.4s
 ; CHECKLE-NEXT:    mov v4.s[0], v7.s[1]
-; CHECKLE-NEXT:    mov v3.d[0], v6.d[0]
-; CHECKLE-NEXT:    mov v2.s[3], v7.s[0]
 ; CHECKLE-NEXT:    ext v1.16b, v0.16b, v1.16b, #12
+; CHECKLE-NEXT:    mov v3.d[0], v17.d[0]
+; CHECKLE-NEXT:    mov v2.s[3], v7.s[0]
 ; CHECKLE-NEXT:    mov v0.16b, v4.16b
 ; CHECKLE-NEXT:    ret
 ;
@@ -41,21 +41,21 @@ define <16 x i32> @test_shuf1(<16 x i32> %x, <16 x i32> %y) {
 ; CHECKBE-NEXT:    dup v4.4s, v4.s[0]
 ; CHECKBE-NEXT:    rev64 v17.4s, v5.4s
 ; CHECKBE-NEXT:    trn2 v6.4s, v1.4s, v6.4s
-; CHECKBE-NEXT:    ext v3.16b, v3.16b, v4.16b, #12
+; CHECKBE-NEXT:    mov v4.s[0], v3.s[3]
 ; CHECKBE-NEXT:    trn2 v1.4s, v16.4s, v1.4s
 ; CHECKBE-NEXT:    trn1 v2.4s, v7.4s, v2.4s
-; CHECKBE-NEXT:    rev64 v4.4s, v17.4s
+; CHECKBE-NEXT:    rev64 v3.4s, v17.4s
 ; CHECKBE-NEXT:    mov v6.s[0], v5.s[1]
-; CHECKBE-NEXT:    rev64 v3.4s, v3.4s
+; CHECKBE-NEXT:    rev64 v4.4s, v4.4s
 ; CHECKBE-NEXT:    ext v0.16b, v0.16b, v1.16b, #12
 ; CHECKBE-NEXT:    mov v2.s[3], v5.s[0]
 ; CHECKBE-NEXT:    rev64 v1.4s, v6.4s
-; CHECKBE-NEXT:    mov v4.d[0], v3.d[0]
-; CHECKBE-NEXT:    rev64 v5.4s, v0.4s
+; CHECKBE-NEXT:    mov v3.d[0], v4.d[0]
+; CHECKBE-NEXT:    rev64 v4.4s, v0.4s
 ; CHECKBE-NEXT:    rev64 v2.4s, v2.4s
 ; CHECKBE-NEXT:    ext v0.16b, v1.16b, v1.16b, #8
-; CHECKBE-NEXT:    ext v3.16b, v4.16b, v4.16b, #8
-; CHECKBE-NEXT:    ext v1.16b, v5.16b, v5.16b, #8
+; CHECKBE-NEXT:    ext v3.16b, v3.16b, v3.16b, #8
+; CHECKBE-NEXT:    ext v1.16b, v4.16b, v4.16b, #8
 ; CHECKBE-NEXT:    ext v2.16b, v2.16b, v2.16b, #8
 ; CHECKBE-NEXT:    ret
   %s3 = shufflevector <16 x i32> %x, <16 x i32> %y, <16 x i32> <i32 29, i32 26, i32 7, i32 4, i32 3, i32 6, i32 5, i32 2, i32 9, i32 8, i32 17, i32 28, i32 27, i32 16, i32 31, i32 30>
@@ -702,7 +702,7 @@ define <16 x i8> @test_shuf_zero_ext_end_rhs(<16 x i8> %a) {
 ; CHECKLE-LABEL: test_shuf_zero_ext_end_rhs:
 ; CHECKLE:       // %bb.0:
 ; CHECKLE-NEXT:    movi v1.2d, #0000000000000000
-; CHECKLE-NEXT:    ext v0.16b, v1.16b, v0.16b, #15
+; CHECKLE-NEXT:    ext v0.16b, v0.16b, v1.16b, #1
 ; CHECKLE-NEXT:    ret
 ;
 ; CHECKBE-LABEL: test_shuf_zero_ext_end_rhs:
@@ -710,11 +710,11 @@ define <16 x i8> @test_shuf_zero_ext_end_rhs(<16 x i8> %a) {
 ; CHECKBE-NEXT:    rev64 v0.16b, v0.16b
 ; CHECKBE-NEXT:    movi v1.2d, #0000000000000000
 ; CHECKBE-NEXT:    ext v0.16b, v0.16b, v0.16b, #8
-; CHECKBE-NEXT:    ext v0.16b, v1.16b, v0.16b, #15
+; CHECKBE-NEXT:    ext v0.16b, v0.16b, v1.16b, #1
 ; CHECKBE-NEXT:    rev64 v0.16b, v0.16b
 ; CHECKBE-NEXT:    ext v0.16b, v0.16b, v0.16b, #8
 ; CHECKBE-NEXT:    ret
-  %r = shufflevector <16 x i8> zeroinitializer, <16 x i8> %a, <16 x i32> <i32 0, i32 16, i32 17, i32 18, i32 19, i32 20, i32 21, i32 22, i32 23, i32 24, i32 25, i32 26, i32 27, i32 28, i32 29, i32 30>
+  %r = shufflevector <16 x i8> zeroinitializer, <16 x i8> %a, <16 x i32> <i32 17, i32 18, i32 19, i32 20, i32 21, i32 22, i32 23, i32 24, i32 25, i32 26, i32 27, i32 28, i32 29, i32 30, i32 31, i32 0>
   ret <16 x i8> %r
 }
 
@@ -722,7 +722,7 @@ define <16 x i8> @test_shuf_zero_ext_end_rhs2(<16 x i8> %a) {
 ; CHECKLE-LABEL: test_shuf_zero_ext_end_rhs2:
 ; CHECKLE:       // %bb.0:
 ; CHECKLE-NEXT:    movi v1.2d, #0000000000000000
-; CHECKLE-NEXT:    ext v0.16b, v1.16b, v0.16b, #14
+; CHECKLE-NEXT:    ext v0.16b, v0.16b, v1.16b, #2
 ; CHECKLE-NEXT:    ret
 ;
 ; CHECKBE-LABEL: test_shuf_zero_ext_end_rhs2:
@@ -730,11 +730,11 @@ define <16 x i8> @test_shuf_zero_ext_end_rhs2(<16 x i8> %a) {
 ; CHECKBE-NEXT:    rev64 v0.16b, v0.16b
 ; CHECKBE-NEXT:    movi v1.2d, #0000000000000000
 ; CHECKBE-NEXT:    ext v0.16b, v0.16b, v0.16b, #8
-; CHECKBE-NEXT:    ext v0.16b, v1.16b, v0.16b, #14
+; CHECKBE-NEXT:    ext v0.16b, v0.16b, v1.16b, #2
 ; CHECKBE-NEXT:    rev64 v0.16b, v0.16b
 ; CHECKBE-NEXT:    ext v0.16b, v0.16b, v0.16b, #8
 ; CHECKBE-NEXT:    ret
-  %r = shufflevector <16 x i8> zeroinitializer, <16 x i8> %a, <16 x i32> <i32 0, i32 0, i32 16, i32 17, i32 18, i32 19, i32 20, i32 21, i32 22, i32 23, i32 24, i32 25, i32 26, i32 27, i32 28, i32 29>
+  %r = shufflevector <16 x i8> zeroinitializer, <16 x i8> %a, <16 x i32> <i32 18, i32 19, i32 20, i32 21, i32 22, i32 23, i32 24, i32 25, i32 26, i32 27, i32 28, i32 29, i32 30, i32 31, i32 0, i32 0>
   ret <16 x i8> %r
 }
 

>From ba4cda042c304e963e7a6a47d83e8456e4f1b48a Mon Sep 17 00:00:00 2001
From: Shreeyash Pandey <shrpand at qti.qualcomm.com>
Date: Thu, 7 May 2026 04:38:55 -0700
Subject: [PATCH 4/4] clang format

Change-Id: Ic705d6064df21cb03e455a4d4dff722b55738186
---
 llvm/lib/Target/AArch64/AArch64ISelLowering.cpp | 6 ++++--
 1 file changed, 4 insertions(+), 2 deletions(-)

diff --git a/llvm/lib/Target/AArch64/AArch64ISelLowering.cpp b/llvm/lib/Target/AArch64/AArch64ISelLowering.cpp
index b64dcc46ec633..fe21930fe0b45 100644
--- a/llvm/lib/Target/AArch64/AArch64ISelLowering.cpp
+++ b/llvm/lib/Target/AArch64/AArch64ISelLowering.cpp
@@ -15107,8 +15107,10 @@ SDValue AArch64TargetLowering::LowerVECTOR_SHUFFLE(SDValue Op,
                        DAG.getConstant(8, DL, MVT::i32));
   }
 
-  bool IsSplat1 = V1.getValueType() == VT && DAG.isSplatValue(V1, /*AllowUndefs=*/false);
-  bool IsSplat2 = V2.getValueType() == VT && DAG.isSplatValue(V2, /*AllowUndefs=*/false);
+  bool IsSplat1 =
+      V1.getValueType() == VT && DAG.isSplatValue(V1, /*AllowUndefs=*/false);
+  bool IsSplat2 =
+      V2.getValueType() == VT && DAG.isSplatValue(V2, /*AllowUndefs=*/false);
   for (unsigned SplatOperand : {0U, 1U}) {
     if ((SplatOperand == 0 && !IsSplat1) || (SplatOperand == 1 && !IsSplat2))
       continue;



More information about the llvm-commits mailing list