[llvm] [AArch64][ISel] Add custom lowering for clmul nxv8i16 (PR #195893)

Matthew Devereau via llvm-commits llvm-commits at lists.llvm.org
Mon May 11 08:04:13 PDT 2026


https://github.com/MDevereau updated https://github.com/llvm/llvm-project/pull/195893

>From 72620a635e56f05da2f69f4557725dd00b23108b Mon Sep 17 00:00:00 2001
From: Matthew Devereau <matthew.devereau at arm.com>
Date: Tue, 5 May 2026 16:24:01 +0000
Subject: [PATCH 1/3] [AArch64][ISel] Add custom lowering for clmul nxv8i16

When sve2 is available, this operation provides a faster implementation than
the current lowering:

clmul.i16(a, b) = xor(pmullb(a_lo, b_lo),
                      lsl(xor(pmul(a_hi, b_lo),
                              pmul(a_lo, b_hi)),
                          8))

Assisted-by: Codex with gpt-5.5
---
 .../Target/AArch64/AArch64ISelLowering.cpp    |  47 +-
 llvm/test/CodeGen/AArch64/clmul-scalable.ll   | 412 +++---------------
 2 files changed, 116 insertions(+), 343 deletions(-)

diff --git a/llvm/lib/Target/AArch64/AArch64ISelLowering.cpp b/llvm/lib/Target/AArch64/AArch64ISelLowering.cpp
index e3c12b9ebd3ed..27fe5776a14fb 100644
--- a/llvm/lib/Target/AArch64/AArch64ISelLowering.cpp
+++ b/llvm/lib/Target/AArch64/AArch64ISelLowering.cpp
@@ -2051,6 +2051,7 @@ AArch64TargetLowering::AArch64TargetLowering(const TargetMachine &TM,
       setPartialReduceMLAAction(MLAOps, MVT::nxv8i16, MVT::nxv16i8, Legal);
 
       setOperationAction(ISD::CLMUL, {MVT::nxv16i8, MVT::nxv4i32}, Legal);
+      setOperationAction(ISD::CLMUL, {MVT::nxv8i16}, Custom);
 
       setPartialReduceMLAAction(ISD::PARTIAL_REDUCE_FMLA, MVT::nxv4f32,
                                 MVT::nxv8f16, Legal);
@@ -8089,10 +8090,50 @@ SDValue AArch64TargetLowering::LowerFMA(SDValue Op, SelectionDAG &DAG) const {
 
 static SDValue LowerCLMUL(SDValue Op, SelectionDAG &DAG) {
   EVT VT = Op.getValueType();
-  assert(
-      (VT == MVT::i64 || VT == MVT::i32 || VT == MVT::i16 || VT == MVT::i8) &&
-      "Unexpected Type");
   SDLoc DL(Op);
+  assert((VT == MVT::i64 || VT == MVT::i32 || VT == MVT::i16 || VT == MVT::i8 ||
+          VT == MVT::nxv8i16) &&
+         "Unexpected Type");
+
+  if (VT == MVT::nxv8i16) {
+    // clmul.i16(a, b) = xor(pmullb(a_lo, b_lo),
+    //                       lsl(xor(pmul(a_hi, b_lo),
+    //                               pmul(a_lo, b_hi)),
+    //                           8))
+
+    SDValue OpA = Op.getOperand(0);
+    SDValue OpB = Op.getOperand(1);
+    SDValue SplatEight =
+        DAG.getSplatVector(VT, DL, DAG.getConstant(8, DL, MVT::i16));
+
+    // Shift >> 8 and bitcast to i8 for pmul
+    SDValue OpAHi = DAG.getNode(ISD::SRL, DL, VT, OpA, SplatEight);
+    OpAHi = DAG.getNode(ISD::BITCAST, DL, MVT::nxv16i8, OpAHi);
+    SDValue OpBHi = DAG.getNode(ISD::SRL, DL, VT, OpB, SplatEight);
+    OpBHi = DAG.getNode(ISD::BITCAST, DL, MVT::nxv16i8, OpBHi);
+
+    // Bitcast to i8 for pmullb
+    OpA = DAG.getNode(ISD::BITCAST, DL, MVT::nxv16i8, OpA);
+    OpB = DAG.getNode(ISD::BITCAST, DL, MVT::nxv16i8, OpB);
+
+    SDValue PMULLB =
+        DAG.getTargetConstant(Intrinsic::aarch64_sve_pmullb_pair, DL, MVT::i64);
+    PMULLB = DAG.getNode(ISD::INTRINSIC_WO_CHAIN, DL, MVT::nxv16i8, PMULLB, OpA,
+                         OpB);
+    PMULLB = DAG.getNode(ISD::BITCAST, DL, VT, PMULLB);
+
+    SDValue PMUL_OpALo_OpBHi =
+        DAG.getNode(ISD::CLMUL, DL, MVT::nxv16i8, OpA, OpBHi);
+    SDValue PMUL_OpAHi_OpBLo =
+        DAG.getNode(ISD::CLMUL, DL, MVT::nxv16i8, OpAHi, OpB);
+    SDValue Cross = DAG.getNode(ISD::XOR, DL, MVT::nxv16i8, PMUL_OpALo_OpBHi,
+                                PMUL_OpAHi_OpBLo);
+    Cross = DAG.getNode(ISD::SHL, DL, VT,
+                        DAG.getNode(ISD::BITCAST, DL, VT, Cross), SplatEight);
+
+    return DAG.getNode(ISD::XOR, DL, VT, PMULLB, Cross);
+  }
+
   EVT VecVT = EVT::getVectorVT(*DAG.getContext(), VT, 64 / VT.getSizeInBits());
   EVT CLMULTy = VT == MVT::i8 ? MVT::v8i8 : MVT::v1i64;
   EVT ExtractTy = VT == MVT::i64 ? MVT::i64 : MVT::i32;
diff --git a/llvm/test/CodeGen/AArch64/clmul-scalable.ll b/llvm/test/CodeGen/AArch64/clmul-scalable.ll
index ef903902b9e65..04114e1dc1807 100644
--- a/llvm/test/CodeGen/AArch64/clmul-scalable.ll
+++ b/llvm/test/CodeGen/AArch64/clmul-scalable.ll
@@ -237,242 +237,50 @@ define <vscale x 8 x i16> @clmul_nxv8i16(<vscale x 8 x i16> %x, <vscale x 8 x i1
 ;
 ; CHECK-SME-STREAMING-LABEL: clmul_nxv8i16:
 ; CHECK-SME-STREAMING:       // %bb.0:
-; CHECK-SME-STREAMING-NEXT:    movprfx z2, z1
-; CHECK-SME-STREAMING-NEXT:    and z2.h, z2.h, #0x2
-; CHECK-SME-STREAMING-NEXT:    movprfx z3, z1
-; CHECK-SME-STREAMING-NEXT:    and z3.h, z3.h, #0x1
-; CHECK-SME-STREAMING-NEXT:    movprfx z4, z1
-; CHECK-SME-STREAMING-NEXT:    and z4.h, z4.h, #0x8
-; CHECK-SME-STREAMING-NEXT:    movprfx z5, z1
-; CHECK-SME-STREAMING-NEXT:    and z5.h, z5.h, #0x4
-; CHECK-SME-STREAMING-NEXT:    movprfx z6, z1
-; CHECK-SME-STREAMING-NEXT:    and z6.h, z6.h, #0x10
-; CHECK-SME-STREAMING-NEXT:    mul z2.h, z0.h, z2.h
-; CHECK-SME-STREAMING-NEXT:    mul z3.h, z0.h, z3.h
-; CHECK-SME-STREAMING-NEXT:    mul z4.h, z0.h, z4.h
-; CHECK-SME-STREAMING-NEXT:    mul z5.h, z0.h, z5.h
-; CHECK-SME-STREAMING-NEXT:    eor z2.d, z3.d, z2.d
-; CHECK-SME-STREAMING-NEXT:    movprfx z3, z1
-; CHECK-SME-STREAMING-NEXT:    and z3.h, z3.h, #0x20
-; CHECK-SME-STREAMING-NEXT:    eor3 z2.d, z2.d, z5.d, z4.d
-; CHECK-SME-STREAMING-NEXT:    mul z3.h, z0.h, z3.h
-; CHECK-SME-STREAMING-NEXT:    mul z4.h, z0.h, z6.h
-; CHECK-SME-STREAMING-NEXT:    movprfx z5, z1
-; CHECK-SME-STREAMING-NEXT:    and z5.h, z5.h, #0x80
-; CHECK-SME-STREAMING-NEXT:    movprfx z6, z1
-; CHECK-SME-STREAMING-NEXT:    and z6.h, z6.h, #0x40
-; CHECK-SME-STREAMING-NEXT:    eor3 z2.d, z2.d, z4.d, z3.d
-; CHECK-SME-STREAMING-NEXT:    mul z3.h, z0.h, z5.h
-; CHECK-SME-STREAMING-NEXT:    mul z4.h, z0.h, z6.h
-; CHECK-SME-STREAMING-NEXT:    movprfx z5, z1
-; CHECK-SME-STREAMING-NEXT:    and z5.h, z5.h, #0x200
-; CHECK-SME-STREAMING-NEXT:    movprfx z6, z1
-; CHECK-SME-STREAMING-NEXT:    and z6.h, z6.h, #0x100
-; CHECK-SME-STREAMING-NEXT:    eor3 z2.d, z2.d, z4.d, z3.d
-; CHECK-SME-STREAMING-NEXT:    mul z3.h, z0.h, z5.h
-; CHECK-SME-STREAMING-NEXT:    mul z4.h, z0.h, z6.h
-; CHECK-SME-STREAMING-NEXT:    movprfx z5, z1
-; CHECK-SME-STREAMING-NEXT:    and z5.h, z5.h, #0x800
-; CHECK-SME-STREAMING-NEXT:    movprfx z6, z1
-; CHECK-SME-STREAMING-NEXT:    and z6.h, z6.h, #0x400
-; CHECK-SME-STREAMING-NEXT:    eor3 z2.d, z2.d, z4.d, z3.d
-; CHECK-SME-STREAMING-NEXT:    mul z3.h, z0.h, z5.h
-; CHECK-SME-STREAMING-NEXT:    mul z4.h, z0.h, z6.h
-; CHECK-SME-STREAMING-NEXT:    movprfx z5, z1
-; CHECK-SME-STREAMING-NEXT:    and z5.h, z5.h, #0x2000
-; CHECK-SME-STREAMING-NEXT:    movprfx z6, z1
-; CHECK-SME-STREAMING-NEXT:    and z6.h, z6.h, #0x1000
-; CHECK-SME-STREAMING-NEXT:    eor3 z2.d, z2.d, z4.d, z3.d
-; CHECK-SME-STREAMING-NEXT:    mul z3.h, z0.h, z5.h
-; CHECK-SME-STREAMING-NEXT:    mul z4.h, z0.h, z6.h
-; CHECK-SME-STREAMING-NEXT:    movprfx z5, z1
-; CHECK-SME-STREAMING-NEXT:    and z5.h, z5.h, #0x8000
-; CHECK-SME-STREAMING-NEXT:    and z1.h, z1.h, #0x4000
-; CHECK-SME-STREAMING-NEXT:    eor3 z2.d, z2.d, z4.d, z3.d
-; CHECK-SME-STREAMING-NEXT:    mul z3.h, z0.h, z5.h
-; CHECK-SME-STREAMING-NEXT:    mul z0.h, z0.h, z1.h
-; CHECK-SME-STREAMING-NEXT:    eor3 z2.d, z2.d, z0.d, z3.d
-; CHECK-SME-STREAMING-NEXT:    mov z0.d, z2.d
+; CHECK-SME-STREAMING-NEXT:    lsr z2.h, z0.h, #8
+; CHECK-SME-STREAMING-NEXT:    lsr z3.h, z1.h, #8
+; CHECK-SME-STREAMING-NEXT:    pmul z2.b, z2.b, z1.b
+; CHECK-SME-STREAMING-NEXT:    pmul z3.b, z0.b, z3.b
+; CHECK-SME-STREAMING-NEXT:    pmullb z0.h, z0.b, z1.b
+; CHECK-SME-STREAMING-NEXT:    eor z1.d, z3.d, z2.d
+; CHECK-SME-STREAMING-NEXT:    lsl z1.h, z1.h, #8
+; CHECK-SME-STREAMING-NEXT:    eor z0.d, z0.d, z1.d
 ; CHECK-SME-STREAMING-NEXT:    ret
 ;
 ; CHECK-SME-STREAMING-SSVE-AES-LABEL: clmul_nxv8i16:
 ; CHECK-SME-STREAMING-SSVE-AES:       // %bb.0:
-; CHECK-SME-STREAMING-SSVE-AES-NEXT:    movprfx z2, z1
-; CHECK-SME-STREAMING-SSVE-AES-NEXT:    and z2.h, z2.h, #0x2
-; CHECK-SME-STREAMING-SSVE-AES-NEXT:    movprfx z3, z1
-; CHECK-SME-STREAMING-SSVE-AES-NEXT:    and z3.h, z3.h, #0x1
-; CHECK-SME-STREAMING-SSVE-AES-NEXT:    movprfx z4, z1
-; CHECK-SME-STREAMING-SSVE-AES-NEXT:    and z4.h, z4.h, #0x8
-; CHECK-SME-STREAMING-SSVE-AES-NEXT:    movprfx z5, z1
-; CHECK-SME-STREAMING-SSVE-AES-NEXT:    and z5.h, z5.h, #0x4
-; CHECK-SME-STREAMING-SSVE-AES-NEXT:    movprfx z6, z1
-; CHECK-SME-STREAMING-SSVE-AES-NEXT:    and z6.h, z6.h, #0x10
-; CHECK-SME-STREAMING-SSVE-AES-NEXT:    mul z2.h, z0.h, z2.h
-; CHECK-SME-STREAMING-SSVE-AES-NEXT:    mul z3.h, z0.h, z3.h
-; CHECK-SME-STREAMING-SSVE-AES-NEXT:    mul z4.h, z0.h, z4.h
-; CHECK-SME-STREAMING-SSVE-AES-NEXT:    mul z5.h, z0.h, z5.h
-; CHECK-SME-STREAMING-SSVE-AES-NEXT:    eor z2.d, z3.d, z2.d
-; CHECK-SME-STREAMING-SSVE-AES-NEXT:    movprfx z3, z1
-; CHECK-SME-STREAMING-SSVE-AES-NEXT:    and z3.h, z3.h, #0x20
-; CHECK-SME-STREAMING-SSVE-AES-NEXT:    eor3 z2.d, z2.d, z5.d, z4.d
-; CHECK-SME-STREAMING-SSVE-AES-NEXT:    mul z3.h, z0.h, z3.h
-; CHECK-SME-STREAMING-SSVE-AES-NEXT:    mul z4.h, z0.h, z6.h
-; CHECK-SME-STREAMING-SSVE-AES-NEXT:    movprfx z5, z1
-; CHECK-SME-STREAMING-SSVE-AES-NEXT:    and z5.h, z5.h, #0x80
-; CHECK-SME-STREAMING-SSVE-AES-NEXT:    movprfx z6, z1
-; CHECK-SME-STREAMING-SSVE-AES-NEXT:    and z6.h, z6.h, #0x40
-; CHECK-SME-STREAMING-SSVE-AES-NEXT:    eor3 z2.d, z2.d, z4.d, z3.d
-; CHECK-SME-STREAMING-SSVE-AES-NEXT:    mul z3.h, z0.h, z5.h
-; CHECK-SME-STREAMING-SSVE-AES-NEXT:    mul z4.h, z0.h, z6.h
-; CHECK-SME-STREAMING-SSVE-AES-NEXT:    movprfx z5, z1
-; CHECK-SME-STREAMING-SSVE-AES-NEXT:    and z5.h, z5.h, #0x200
-; CHECK-SME-STREAMING-SSVE-AES-NEXT:    movprfx z6, z1
-; CHECK-SME-STREAMING-SSVE-AES-NEXT:    and z6.h, z6.h, #0x100
-; CHECK-SME-STREAMING-SSVE-AES-NEXT:    eor3 z2.d, z2.d, z4.d, z3.d
-; CHECK-SME-STREAMING-SSVE-AES-NEXT:    mul z3.h, z0.h, z5.h
-; CHECK-SME-STREAMING-SSVE-AES-NEXT:    mul z4.h, z0.h, z6.h
-; CHECK-SME-STREAMING-SSVE-AES-NEXT:    movprfx z5, z1
-; CHECK-SME-STREAMING-SSVE-AES-NEXT:    and z5.h, z5.h, #0x800
-; CHECK-SME-STREAMING-SSVE-AES-NEXT:    movprfx z6, z1
-; CHECK-SME-STREAMING-SSVE-AES-NEXT:    and z6.h, z6.h, #0x400
-; CHECK-SME-STREAMING-SSVE-AES-NEXT:    eor3 z2.d, z2.d, z4.d, z3.d
-; CHECK-SME-STREAMING-SSVE-AES-NEXT:    mul z3.h, z0.h, z5.h
-; CHECK-SME-STREAMING-SSVE-AES-NEXT:    mul z4.h, z0.h, z6.h
-; CHECK-SME-STREAMING-SSVE-AES-NEXT:    movprfx z5, z1
-; CHECK-SME-STREAMING-SSVE-AES-NEXT:    and z5.h, z5.h, #0x2000
-; CHECK-SME-STREAMING-SSVE-AES-NEXT:    movprfx z6, z1
-; CHECK-SME-STREAMING-SSVE-AES-NEXT:    and z6.h, z6.h, #0x1000
-; CHECK-SME-STREAMING-SSVE-AES-NEXT:    eor3 z2.d, z2.d, z4.d, z3.d
-; CHECK-SME-STREAMING-SSVE-AES-NEXT:    mul z3.h, z0.h, z5.h
-; CHECK-SME-STREAMING-SSVE-AES-NEXT:    mul z4.h, z0.h, z6.h
-; CHECK-SME-STREAMING-SSVE-AES-NEXT:    movprfx z5, z1
-; CHECK-SME-STREAMING-SSVE-AES-NEXT:    and z5.h, z5.h, #0x8000
-; CHECK-SME-STREAMING-SSVE-AES-NEXT:    and z1.h, z1.h, #0x4000
-; CHECK-SME-STREAMING-SSVE-AES-NEXT:    eor3 z2.d, z2.d, z4.d, z3.d
-; CHECK-SME-STREAMING-SSVE-AES-NEXT:    mul z3.h, z0.h, z5.h
-; CHECK-SME-STREAMING-SSVE-AES-NEXT:    mul z0.h, z0.h, z1.h
-; CHECK-SME-STREAMING-SSVE-AES-NEXT:    eor3 z2.d, z2.d, z0.d, z3.d
-; CHECK-SME-STREAMING-SSVE-AES-NEXT:    mov z0.d, z2.d
+; CHECK-SME-STREAMING-SSVE-AES-NEXT:    lsr z2.h, z0.h, #8
+; CHECK-SME-STREAMING-SSVE-AES-NEXT:    lsr z3.h, z1.h, #8
+; CHECK-SME-STREAMING-SSVE-AES-NEXT:    pmul z2.b, z2.b, z1.b
+; CHECK-SME-STREAMING-SSVE-AES-NEXT:    pmul z3.b, z0.b, z3.b
+; CHECK-SME-STREAMING-SSVE-AES-NEXT:    pmullb z0.h, z0.b, z1.b
+; CHECK-SME-STREAMING-SSVE-AES-NEXT:    eor z1.d, z3.d, z2.d
+; CHECK-SME-STREAMING-SSVE-AES-NEXT:    lsl z1.h, z1.h, #8
+; CHECK-SME-STREAMING-SSVE-AES-NEXT:    eor z0.d, z0.d, z1.d
 ; CHECK-SME-STREAMING-SSVE-AES-NEXT:    ret
 ;
 ; CHECK-SVE2-LABEL: clmul_nxv8i16:
 ; CHECK-SVE2:       // %bb.0:
-; CHECK-SVE2-NEXT:    movprfx z2, z1
-; CHECK-SVE2-NEXT:    and z2.h, z2.h, #0x2
-; CHECK-SVE2-NEXT:    movprfx z3, z1
-; CHECK-SVE2-NEXT:    and z3.h, z3.h, #0x1
-; CHECK-SVE2-NEXT:    movprfx z4, z1
-; CHECK-SVE2-NEXT:    and z4.h, z4.h, #0x8
-; CHECK-SVE2-NEXT:    movprfx z5, z1
-; CHECK-SVE2-NEXT:    and z5.h, z5.h, #0x4
-; CHECK-SVE2-NEXT:    movprfx z6, z1
-; CHECK-SVE2-NEXT:    and z6.h, z6.h, #0x10
-; CHECK-SVE2-NEXT:    mul z2.h, z0.h, z2.h
-; CHECK-SVE2-NEXT:    mul z3.h, z0.h, z3.h
-; CHECK-SVE2-NEXT:    mul z4.h, z0.h, z4.h
-; CHECK-SVE2-NEXT:    mul z5.h, z0.h, z5.h
-; CHECK-SVE2-NEXT:    eor z2.d, z3.d, z2.d
-; CHECK-SVE2-NEXT:    movprfx z3, z1
-; CHECK-SVE2-NEXT:    and z3.h, z3.h, #0x20
-; CHECK-SVE2-NEXT:    eor3 z2.d, z2.d, z5.d, z4.d
-; CHECK-SVE2-NEXT:    mul z3.h, z0.h, z3.h
-; CHECK-SVE2-NEXT:    mul z4.h, z0.h, z6.h
-; CHECK-SVE2-NEXT:    movprfx z5, z1
-; CHECK-SVE2-NEXT:    and z5.h, z5.h, #0x80
-; CHECK-SVE2-NEXT:    movprfx z6, z1
-; CHECK-SVE2-NEXT:    and z6.h, z6.h, #0x40
-; CHECK-SVE2-NEXT:    eor3 z2.d, z2.d, z4.d, z3.d
-; CHECK-SVE2-NEXT:    mul z3.h, z0.h, z5.h
-; CHECK-SVE2-NEXT:    mul z4.h, z0.h, z6.h
-; CHECK-SVE2-NEXT:    movprfx z5, z1
-; CHECK-SVE2-NEXT:    and z5.h, z5.h, #0x200
-; CHECK-SVE2-NEXT:    movprfx z6, z1
-; CHECK-SVE2-NEXT:    and z6.h, z6.h, #0x100
-; CHECK-SVE2-NEXT:    eor3 z2.d, z2.d, z4.d, z3.d
-; CHECK-SVE2-NEXT:    mul z3.h, z0.h, z5.h
-; CHECK-SVE2-NEXT:    mul z4.h, z0.h, z6.h
-; CHECK-SVE2-NEXT:    movprfx z5, z1
-; CHECK-SVE2-NEXT:    and z5.h, z5.h, #0x800
-; CHECK-SVE2-NEXT:    movprfx z6, z1
-; CHECK-SVE2-NEXT:    and z6.h, z6.h, #0x400
-; CHECK-SVE2-NEXT:    eor3 z2.d, z2.d, z4.d, z3.d
-; CHECK-SVE2-NEXT:    mul z3.h, z0.h, z5.h
-; CHECK-SVE2-NEXT:    mul z4.h, z0.h, z6.h
-; CHECK-SVE2-NEXT:    movprfx z5, z1
-; CHECK-SVE2-NEXT:    and z5.h, z5.h, #0x2000
-; CHECK-SVE2-NEXT:    movprfx z6, z1
-; CHECK-SVE2-NEXT:    and z6.h, z6.h, #0x1000
-; CHECK-SVE2-NEXT:    eor3 z2.d, z2.d, z4.d, z3.d
-; CHECK-SVE2-NEXT:    mul z3.h, z0.h, z5.h
-; CHECK-SVE2-NEXT:    mul z4.h, z0.h, z6.h
-; CHECK-SVE2-NEXT:    movprfx z5, z1
-; CHECK-SVE2-NEXT:    and z5.h, z5.h, #0x8000
-; CHECK-SVE2-NEXT:    and z1.h, z1.h, #0x4000
-; CHECK-SVE2-NEXT:    eor3 z2.d, z2.d, z4.d, z3.d
-; CHECK-SVE2-NEXT:    mul z3.h, z0.h, z5.h
-; CHECK-SVE2-NEXT:    mul z0.h, z0.h, z1.h
-; CHECK-SVE2-NEXT:    eor3 z2.d, z2.d, z0.d, z3.d
-; CHECK-SVE2-NEXT:    mov z0.d, z2.d
+; CHECK-SVE2-NEXT:    lsr z2.h, z0.h, #8
+; CHECK-SVE2-NEXT:    lsr z3.h, z1.h, #8
+; CHECK-SVE2-NEXT:    pmul z2.b, z2.b, z1.b
+; CHECK-SVE2-NEXT:    pmul z3.b, z0.b, z3.b
+; CHECK-SVE2-NEXT:    pmullb z0.h, z0.b, z1.b
+; CHECK-SVE2-NEXT:    eor z1.d, z3.d, z2.d
+; CHECK-SVE2-NEXT:    lsl z1.h, z1.h, #8
+; CHECK-SVE2-NEXT:    eor z0.d, z0.d, z1.d
 ; CHECK-SVE2-NEXT:    ret
 ;
 ; CHECK-SVE2-AES-LABEL: clmul_nxv8i16:
 ; CHECK-SVE2-AES:       // %bb.0:
-; CHECK-SVE2-AES-NEXT:    movprfx z2, z1
-; CHECK-SVE2-AES-NEXT:    and z2.h, z2.h, #0x2
-; CHECK-SVE2-AES-NEXT:    movprfx z3, z1
-; CHECK-SVE2-AES-NEXT:    and z3.h, z3.h, #0x1
-; CHECK-SVE2-AES-NEXT:    movprfx z4, z1
-; CHECK-SVE2-AES-NEXT:    and z4.h, z4.h, #0x8
-; CHECK-SVE2-AES-NEXT:    movprfx z5, z1
-; CHECK-SVE2-AES-NEXT:    and z5.h, z5.h, #0x4
-; CHECK-SVE2-AES-NEXT:    movprfx z6, z1
-; CHECK-SVE2-AES-NEXT:    and z6.h, z6.h, #0x10
-; CHECK-SVE2-AES-NEXT:    mul z2.h, z0.h, z2.h
-; CHECK-SVE2-AES-NEXT:    mul z3.h, z0.h, z3.h
-; CHECK-SVE2-AES-NEXT:    mul z4.h, z0.h, z4.h
-; CHECK-SVE2-AES-NEXT:    mul z5.h, z0.h, z5.h
-; CHECK-SVE2-AES-NEXT:    eor z2.d, z3.d, z2.d
-; CHECK-SVE2-AES-NEXT:    movprfx z3, z1
-; CHECK-SVE2-AES-NEXT:    and z3.h, z3.h, #0x20
-; CHECK-SVE2-AES-NEXT:    eor3 z2.d, z2.d, z5.d, z4.d
-; CHECK-SVE2-AES-NEXT:    mul z3.h, z0.h, z3.h
-; CHECK-SVE2-AES-NEXT:    mul z4.h, z0.h, z6.h
-; CHECK-SVE2-AES-NEXT:    movprfx z5, z1
-; CHECK-SVE2-AES-NEXT:    and z5.h, z5.h, #0x80
-; CHECK-SVE2-AES-NEXT:    movprfx z6, z1
-; CHECK-SVE2-AES-NEXT:    and z6.h, z6.h, #0x40
-; CHECK-SVE2-AES-NEXT:    eor3 z2.d, z2.d, z4.d, z3.d
-; CHECK-SVE2-AES-NEXT:    mul z3.h, z0.h, z5.h
-; CHECK-SVE2-AES-NEXT:    mul z4.h, z0.h, z6.h
-; CHECK-SVE2-AES-NEXT:    movprfx z5, z1
-; CHECK-SVE2-AES-NEXT:    and z5.h, z5.h, #0x200
-; CHECK-SVE2-AES-NEXT:    movprfx z6, z1
-; CHECK-SVE2-AES-NEXT:    and z6.h, z6.h, #0x100
-; CHECK-SVE2-AES-NEXT:    eor3 z2.d, z2.d, z4.d, z3.d
-; CHECK-SVE2-AES-NEXT:    mul z3.h, z0.h, z5.h
-; CHECK-SVE2-AES-NEXT:    mul z4.h, z0.h, z6.h
-; CHECK-SVE2-AES-NEXT:    movprfx z5, z1
-; CHECK-SVE2-AES-NEXT:    and z5.h, z5.h, #0x800
-; CHECK-SVE2-AES-NEXT:    movprfx z6, z1
-; CHECK-SVE2-AES-NEXT:    and z6.h, z6.h, #0x400
-; CHECK-SVE2-AES-NEXT:    eor3 z2.d, z2.d, z4.d, z3.d
-; CHECK-SVE2-AES-NEXT:    mul z3.h, z0.h, z5.h
-; CHECK-SVE2-AES-NEXT:    mul z4.h, z0.h, z6.h
-; CHECK-SVE2-AES-NEXT:    movprfx z5, z1
-; CHECK-SVE2-AES-NEXT:    and z5.h, z5.h, #0x2000
-; CHECK-SVE2-AES-NEXT:    movprfx z6, z1
-; CHECK-SVE2-AES-NEXT:    and z6.h, z6.h, #0x1000
-; CHECK-SVE2-AES-NEXT:    eor3 z2.d, z2.d, z4.d, z3.d
-; CHECK-SVE2-AES-NEXT:    mul z3.h, z0.h, z5.h
-; CHECK-SVE2-AES-NEXT:    mul z4.h, z0.h, z6.h
-; CHECK-SVE2-AES-NEXT:    movprfx z5, z1
-; CHECK-SVE2-AES-NEXT:    and z5.h, z5.h, #0x8000
-; CHECK-SVE2-AES-NEXT:    and z1.h, z1.h, #0x4000
-; CHECK-SVE2-AES-NEXT:    eor3 z2.d, z2.d, z4.d, z3.d
-; CHECK-SVE2-AES-NEXT:    mul z3.h, z0.h, z5.h
-; CHECK-SVE2-AES-NEXT:    mul z0.h, z0.h, z1.h
-; CHECK-SVE2-AES-NEXT:    eor3 z2.d, z2.d, z0.d, z3.d
-; CHECK-SVE2-AES-NEXT:    mov z0.d, z2.d
+; CHECK-SVE2-AES-NEXT:    lsr z2.h, z0.h, #8
+; CHECK-SVE2-AES-NEXT:    lsr z3.h, z1.h, #8
+; CHECK-SVE2-AES-NEXT:    pmul z2.b, z2.b, z1.b
+; CHECK-SVE2-AES-NEXT:    pmul z3.b, z0.b, z3.b
+; CHECK-SVE2-AES-NEXT:    pmullb z0.h, z0.b, z1.b
+; CHECK-SVE2-AES-NEXT:    eor z1.d, z3.d, z2.d
+; CHECK-SVE2-AES-NEXT:    lsl z1.h, z1.h, #8
+; CHECK-SVE2-AES-NEXT:    eor z0.d, z0.d, z1.d
 ; CHECK-SVE2-AES-NEXT:    ret
   %a = call <vscale x 8 x i16> @llvm.clmul.nxv8i16(<vscale x 8 x i16> %x, <vscale x 8 x i16> %y)
   ret <vscale x 8 x i16> %a
@@ -1695,134 +1503,58 @@ define <vscale x 8 x i16> @clmul_nxv8i16_zext(<vscale x 8 x i8> %x, <vscale x 8
 ;
 ; CHECK-SME-STREAMING-LABEL: clmul_nxv8i16_zext:
 ; CHECK-SME-STREAMING:       // %bb.0:
-; CHECK-SME-STREAMING-NEXT:    movprfx z2, z0
-; CHECK-SME-STREAMING-NEXT:    and z2.h, z2.h, #0xff
-; CHECK-SME-STREAMING-NEXT:    movprfx z0, z1
-; CHECK-SME-STREAMING-NEXT:    and z0.h, z0.h, #0x2
-; CHECK-SME-STREAMING-NEXT:    movprfx z3, z1
-; CHECK-SME-STREAMING-NEXT:    and z3.h, z3.h, #0x1
-; CHECK-SME-STREAMING-NEXT:    movprfx z4, z1
-; CHECK-SME-STREAMING-NEXT:    and z4.h, z4.h, #0x8
-; CHECK-SME-STREAMING-NEXT:    movprfx z5, z1
-; CHECK-SME-STREAMING-NEXT:    and z5.h, z5.h, #0x4
-; CHECK-SME-STREAMING-NEXT:    movprfx z6, z1
-; CHECK-SME-STREAMING-NEXT:    and z6.h, z6.h, #0x10
-; CHECK-SME-STREAMING-NEXT:    mul z0.h, z2.h, z0.h
-; CHECK-SME-STREAMING-NEXT:    mul z3.h, z2.h, z3.h
-; CHECK-SME-STREAMING-NEXT:    mul z4.h, z2.h, z4.h
-; CHECK-SME-STREAMING-NEXT:    mul z5.h, z2.h, z5.h
-; CHECK-SME-STREAMING-NEXT:    eor z0.d, z3.d, z0.d
-; CHECK-SME-STREAMING-NEXT:    movprfx z3, z1
-; CHECK-SME-STREAMING-NEXT:    and z3.h, z3.h, #0x20
-; CHECK-SME-STREAMING-NEXT:    eor3 z0.d, z0.d, z5.d, z4.d
-; CHECK-SME-STREAMING-NEXT:    mul z3.h, z2.h, z3.h
-; CHECK-SME-STREAMING-NEXT:    mul z4.h, z2.h, z6.h
-; CHECK-SME-STREAMING-NEXT:    movprfx z5, z1
-; CHECK-SME-STREAMING-NEXT:    and z5.h, z5.h, #0x80
-; CHECK-SME-STREAMING-NEXT:    and z1.h, z1.h, #0x40
-; CHECK-SME-STREAMING-NEXT:    eor3 z0.d, z0.d, z4.d, z3.d
-; CHECK-SME-STREAMING-NEXT:    mul z3.h, z2.h, z5.h
-; CHECK-SME-STREAMING-NEXT:    mul z1.h, z2.h, z1.h
-; CHECK-SME-STREAMING-NEXT:    eor3 z0.d, z0.d, z1.d, z3.d
+; CHECK-SME-STREAMING-NEXT:    and z0.h, z0.h, #0xff
+; CHECK-SME-STREAMING-NEXT:    and z1.h, z1.h, #0xff
+; CHECK-SME-STREAMING-NEXT:    lsr z2.h, z0.h, #8
+; CHECK-SME-STREAMING-NEXT:    lsr z3.h, z1.h, #8
+; CHECK-SME-STREAMING-NEXT:    pmul z2.b, z2.b, z1.b
+; CHECK-SME-STREAMING-NEXT:    pmul z3.b, z0.b, z3.b
+; CHECK-SME-STREAMING-NEXT:    pmullb z0.h, z0.b, z1.b
+; CHECK-SME-STREAMING-NEXT:    eor z1.d, z3.d, z2.d
+; CHECK-SME-STREAMING-NEXT:    lsl z1.h, z1.h, #8
+; CHECK-SME-STREAMING-NEXT:    eor z0.d, z0.d, z1.d
 ; CHECK-SME-STREAMING-NEXT:    ret
 ;
 ; CHECK-SME-STREAMING-SSVE-AES-LABEL: clmul_nxv8i16_zext:
 ; CHECK-SME-STREAMING-SSVE-AES:       // %bb.0:
-; CHECK-SME-STREAMING-SSVE-AES-NEXT:    movprfx z2, z0
-; CHECK-SME-STREAMING-SSVE-AES-NEXT:    and z2.h, z2.h, #0xff
-; CHECK-SME-STREAMING-SSVE-AES-NEXT:    movprfx z0, z1
-; CHECK-SME-STREAMING-SSVE-AES-NEXT:    and z0.h, z0.h, #0x2
-; CHECK-SME-STREAMING-SSVE-AES-NEXT:    movprfx z3, z1
-; CHECK-SME-STREAMING-SSVE-AES-NEXT:    and z3.h, z3.h, #0x1
-; CHECK-SME-STREAMING-SSVE-AES-NEXT:    movprfx z4, z1
-; CHECK-SME-STREAMING-SSVE-AES-NEXT:    and z4.h, z4.h, #0x8
-; CHECK-SME-STREAMING-SSVE-AES-NEXT:    movprfx z5, z1
-; CHECK-SME-STREAMING-SSVE-AES-NEXT:    and z5.h, z5.h, #0x4
-; CHECK-SME-STREAMING-SSVE-AES-NEXT:    movprfx z6, z1
-; CHECK-SME-STREAMING-SSVE-AES-NEXT:    and z6.h, z6.h, #0x10
-; CHECK-SME-STREAMING-SSVE-AES-NEXT:    mul z0.h, z2.h, z0.h
-; CHECK-SME-STREAMING-SSVE-AES-NEXT:    mul z3.h, z2.h, z3.h
-; CHECK-SME-STREAMING-SSVE-AES-NEXT:    mul z4.h, z2.h, z4.h
-; CHECK-SME-STREAMING-SSVE-AES-NEXT:    mul z5.h, z2.h, z5.h
-; CHECK-SME-STREAMING-SSVE-AES-NEXT:    eor z0.d, z3.d, z0.d
-; CHECK-SME-STREAMING-SSVE-AES-NEXT:    movprfx z3, z1
-; CHECK-SME-STREAMING-SSVE-AES-NEXT:    and z3.h, z3.h, #0x20
-; CHECK-SME-STREAMING-SSVE-AES-NEXT:    eor3 z0.d, z0.d, z5.d, z4.d
-; CHECK-SME-STREAMING-SSVE-AES-NEXT:    mul z3.h, z2.h, z3.h
-; CHECK-SME-STREAMING-SSVE-AES-NEXT:    mul z4.h, z2.h, z6.h
-; CHECK-SME-STREAMING-SSVE-AES-NEXT:    movprfx z5, z1
-; CHECK-SME-STREAMING-SSVE-AES-NEXT:    and z5.h, z5.h, #0x80
-; CHECK-SME-STREAMING-SSVE-AES-NEXT:    and z1.h, z1.h, #0x40
-; CHECK-SME-STREAMING-SSVE-AES-NEXT:    eor3 z0.d, z0.d, z4.d, z3.d
-; CHECK-SME-STREAMING-SSVE-AES-NEXT:    mul z3.h, z2.h, z5.h
-; CHECK-SME-STREAMING-SSVE-AES-NEXT:    mul z1.h, z2.h, z1.h
-; CHECK-SME-STREAMING-SSVE-AES-NEXT:    eor3 z0.d, z0.d, z1.d, z3.d
+; CHECK-SME-STREAMING-SSVE-AES-NEXT:    and z0.h, z0.h, #0xff
+; CHECK-SME-STREAMING-SSVE-AES-NEXT:    and z1.h, z1.h, #0xff
+; CHECK-SME-STREAMING-SSVE-AES-NEXT:    lsr z2.h, z0.h, #8
+; CHECK-SME-STREAMING-SSVE-AES-NEXT:    lsr z3.h, z1.h, #8
+; CHECK-SME-STREAMING-SSVE-AES-NEXT:    pmul z2.b, z2.b, z1.b
+; CHECK-SME-STREAMING-SSVE-AES-NEXT:    pmul z3.b, z0.b, z3.b
+; CHECK-SME-STREAMING-SSVE-AES-NEXT:    pmullb z0.h, z0.b, z1.b
+; CHECK-SME-STREAMING-SSVE-AES-NEXT:    eor z1.d, z3.d, z2.d
+; CHECK-SME-STREAMING-SSVE-AES-NEXT:    lsl z1.h, z1.h, #8
+; CHECK-SME-STREAMING-SSVE-AES-NEXT:    eor z0.d, z0.d, z1.d
 ; CHECK-SME-STREAMING-SSVE-AES-NEXT:    ret
 ;
 ; CHECK-SVE2-LABEL: clmul_nxv8i16_zext:
 ; CHECK-SVE2:       // %bb.0:
-; CHECK-SVE2-NEXT:    movprfx z2, z0
-; CHECK-SVE2-NEXT:    and z2.h, z2.h, #0xff
-; CHECK-SVE2-NEXT:    movprfx z0, z1
-; CHECK-SVE2-NEXT:    and z0.h, z0.h, #0x2
-; CHECK-SVE2-NEXT:    movprfx z3, z1
-; CHECK-SVE2-NEXT:    and z3.h, z3.h, #0x1
-; CHECK-SVE2-NEXT:    movprfx z4, z1
-; CHECK-SVE2-NEXT:    and z4.h, z4.h, #0x8
-; CHECK-SVE2-NEXT:    movprfx z5, z1
-; CHECK-SVE2-NEXT:    and z5.h, z5.h, #0x4
-; CHECK-SVE2-NEXT:    movprfx z6, z1
-; CHECK-SVE2-NEXT:    and z6.h, z6.h, #0x10
-; CHECK-SVE2-NEXT:    mul z0.h, z2.h, z0.h
-; CHECK-SVE2-NEXT:    mul z3.h, z2.h, z3.h
-; CHECK-SVE2-NEXT:    mul z4.h, z2.h, z4.h
-; CHECK-SVE2-NEXT:    mul z5.h, z2.h, z5.h
-; CHECK-SVE2-NEXT:    eor z0.d, z3.d, z0.d
-; CHECK-SVE2-NEXT:    movprfx z3, z1
-; CHECK-SVE2-NEXT:    and z3.h, z3.h, #0x20
-; CHECK-SVE2-NEXT:    eor3 z0.d, z0.d, z5.d, z4.d
-; CHECK-SVE2-NEXT:    mul z3.h, z2.h, z3.h
-; CHECK-SVE2-NEXT:    mul z4.h, z2.h, z6.h
-; CHECK-SVE2-NEXT:    movprfx z5, z1
-; CHECK-SVE2-NEXT:    and z5.h, z5.h, #0x80
-; CHECK-SVE2-NEXT:    and z1.h, z1.h, #0x40
-; CHECK-SVE2-NEXT:    eor3 z0.d, z0.d, z4.d, z3.d
-; CHECK-SVE2-NEXT:    mul z3.h, z2.h, z5.h
-; CHECK-SVE2-NEXT:    mul z1.h, z2.h, z1.h
-; CHECK-SVE2-NEXT:    eor3 z0.d, z0.d, z1.d, z3.d
+; CHECK-SVE2-NEXT:    and z0.h, z0.h, #0xff
+; CHECK-SVE2-NEXT:    and z1.h, z1.h, #0xff
+; CHECK-SVE2-NEXT:    lsr z2.h, z0.h, #8
+; CHECK-SVE2-NEXT:    lsr z3.h, z1.h, #8
+; CHECK-SVE2-NEXT:    pmul z2.b, z2.b, z1.b
+; CHECK-SVE2-NEXT:    pmul z3.b, z0.b, z3.b
+; CHECK-SVE2-NEXT:    pmullb z0.h, z0.b, z1.b
+; CHECK-SVE2-NEXT:    eor z1.d, z3.d, z2.d
+; CHECK-SVE2-NEXT:    lsl z1.h, z1.h, #8
+; CHECK-SVE2-NEXT:    eor z0.d, z0.d, z1.d
 ; CHECK-SVE2-NEXT:    ret
 ;
 ; CHECK-SVE2-AES-LABEL: clmul_nxv8i16_zext:
 ; CHECK-SVE2-AES:       // %bb.0:
-; CHECK-SVE2-AES-NEXT:    movprfx z2, z0
-; CHECK-SVE2-AES-NEXT:    and z2.h, z2.h, #0xff
-; CHECK-SVE2-AES-NEXT:    movprfx z0, z1
-; CHECK-SVE2-AES-NEXT:    and z0.h, z0.h, #0x2
-; CHECK-SVE2-AES-NEXT:    movprfx z3, z1
-; CHECK-SVE2-AES-NEXT:    and z3.h, z3.h, #0x1
-; CHECK-SVE2-AES-NEXT:    movprfx z4, z1
-; CHECK-SVE2-AES-NEXT:    and z4.h, z4.h, #0x8
-; CHECK-SVE2-AES-NEXT:    movprfx z5, z1
-; CHECK-SVE2-AES-NEXT:    and z5.h, z5.h, #0x4
-; CHECK-SVE2-AES-NEXT:    movprfx z6, z1
-; CHECK-SVE2-AES-NEXT:    and z6.h, z6.h, #0x10
-; CHECK-SVE2-AES-NEXT:    mul z0.h, z2.h, z0.h
-; CHECK-SVE2-AES-NEXT:    mul z3.h, z2.h, z3.h
-; CHECK-SVE2-AES-NEXT:    mul z4.h, z2.h, z4.h
-; CHECK-SVE2-AES-NEXT:    mul z5.h, z2.h, z5.h
-; CHECK-SVE2-AES-NEXT:    eor z0.d, z3.d, z0.d
-; CHECK-SVE2-AES-NEXT:    movprfx z3, z1
-; CHECK-SVE2-AES-NEXT:    and z3.h, z3.h, #0x20
-; CHECK-SVE2-AES-NEXT:    eor3 z0.d, z0.d, z5.d, z4.d
-; CHECK-SVE2-AES-NEXT:    mul z3.h, z2.h, z3.h
-; CHECK-SVE2-AES-NEXT:    mul z4.h, z2.h, z6.h
-; CHECK-SVE2-AES-NEXT:    movprfx z5, z1
-; CHECK-SVE2-AES-NEXT:    and z5.h, z5.h, #0x80
-; CHECK-SVE2-AES-NEXT:    and z1.h, z1.h, #0x40
-; CHECK-SVE2-AES-NEXT:    eor3 z0.d, z0.d, z4.d, z3.d
-; CHECK-SVE2-AES-NEXT:    mul z3.h, z2.h, z5.h
-; CHECK-SVE2-AES-NEXT:    mul z1.h, z2.h, z1.h
-; CHECK-SVE2-AES-NEXT:    eor3 z0.d, z0.d, z1.d, z3.d
+; CHECK-SVE2-AES-NEXT:    and z0.h, z0.h, #0xff
+; CHECK-SVE2-AES-NEXT:    and z1.h, z1.h, #0xff
+; CHECK-SVE2-AES-NEXT:    lsr z2.h, z0.h, #8
+; CHECK-SVE2-AES-NEXT:    lsr z3.h, z1.h, #8
+; CHECK-SVE2-AES-NEXT:    pmul z2.b, z2.b, z1.b
+; CHECK-SVE2-AES-NEXT:    pmul z3.b, z0.b, z3.b
+; CHECK-SVE2-AES-NEXT:    pmullb z0.h, z0.b, z1.b
+; CHECK-SVE2-AES-NEXT:    eor z1.d, z3.d, z2.d
+; CHECK-SVE2-AES-NEXT:    lsl z1.h, z1.h, #8
+; CHECK-SVE2-AES-NEXT:    eor z0.d, z0.d, z1.d
 ; CHECK-SVE2-AES-NEXT:    ret
   %zextx = zext <vscale x 8 x i8> %x to <vscale x 8 x i16>
   %zexty = zext <vscale x 8 x i8> %y to <vscale x 8 x i16>

>From 9ef204e68027b971ff39244220eeaaaf42aa9c48 Mon Sep 17 00:00:00 2001
From: Matthew Devereau <matthew.devereau at arm.com>
Date: Fri, 8 May 2026 14:47:16 +0000
Subject: [PATCH 2/3] Use single pmul and eortb

---
 .../Target/AArch64/AArch64ISelLowering.cpp    | 50 ++++++-------
 llvm/test/CodeGen/AArch64/clmul-scalable.ll   | 72 +++++++++----------
 2 files changed, 55 insertions(+), 67 deletions(-)

diff --git a/llvm/lib/Target/AArch64/AArch64ISelLowering.cpp b/llvm/lib/Target/AArch64/AArch64ISelLowering.cpp
index 27fe5776a14fb..d2603cc1e52c2 100644
--- a/llvm/lib/Target/AArch64/AArch64ISelLowering.cpp
+++ b/llvm/lib/Target/AArch64/AArch64ISelLowering.cpp
@@ -8097,41 +8097,37 @@ static SDValue LowerCLMUL(SDValue Op, SelectionDAG &DAG) {
 
   if (VT == MVT::nxv8i16) {
     // clmul.i16(a, b) = xor(pmullb(a_lo, b_lo),
-    //                       lsl(xor(pmul(a_hi, b_lo),
-    //                               pmul(a_lo, b_hi)),
+    //                       lsl(eorbt(pmul(trn2(a, b),
+    //                                      trn1(b, a))),
     //                           8))
-
     SDValue OpA = Op.getOperand(0);
     SDValue OpB = Op.getOperand(1);
-    SDValue SplatEight =
-        DAG.getSplatVector(VT, DL, DAG.getConstant(8, DL, MVT::i16));
-
-    // Shift >> 8 and bitcast to i8 for pmul
-    SDValue OpAHi = DAG.getNode(ISD::SRL, DL, VT, OpA, SplatEight);
-    OpAHi = DAG.getNode(ISD::BITCAST, DL, MVT::nxv16i8, OpAHi);
-    SDValue OpBHi = DAG.getNode(ISD::SRL, DL, VT, OpB, SplatEight);
-    OpBHi = DAG.getNode(ISD::BITCAST, DL, MVT::nxv16i8, OpBHi);
-
-    // Bitcast to i8 for pmullb
-    OpA = DAG.getNode(ISD::BITCAST, DL, MVT::nxv16i8, OpA);
-    OpB = DAG.getNode(ISD::BITCAST, DL, MVT::nxv16i8, OpB);
+    // Bitcast to i8 for byte-wise PMUL and PMULLB.
+    OpA = DAG.getNode(AArch64ISD::NVCAST, DL, MVT::nxv16i8, OpA);
+    OpB = DAG.getNode(AArch64ISD::NVCAST, DL, MVT::nxv16i8, OpB);
+
+    // Form adjacent byte pairs {a_hi, b_hi} and {b_lo, a_lo}. PMUL then
+    // computes {a_hi * b_lo, b_hi * a_lo}, and EORTB xors those pairs into
+    // the low byte of each half-word.
+    SDValue LoBytes = DAG.getNode(AArch64ISD::TRN1, DL, MVT::nxv16i8, OpB, OpA);
+    SDValue HiBytes = DAG.getNode(AArch64ISD::TRN2, DL, MVT::nxv16i8, OpA, OpB);
+    SDValue PMUL = DAG.getNode(ISD::CLMUL, DL, MVT::nxv16i8, HiBytes, LoBytes);
+
+    SDValue EORBT =
+        DAG.getTargetConstant(Intrinsic::aarch64_sve_eorbt, DL, MVT::i64);
+    EORBT = DAG.getNode(ISD::INTRINSIC_WO_CHAIN, DL, MVT::nxv16i8, EORBT, OpB,
+                        PMUL, PMUL);
+    SDValue SHL = DAG.getNode(ISD::SHL, DL, VT,
+                              DAG.getNode(AArch64ISD::NVCAST, DL, VT, EORBT),
+                              DAG.getConstant(8, DL, VT));
 
     SDValue PMULLB =
         DAG.getTargetConstant(Intrinsic::aarch64_sve_pmullb_pair, DL, MVT::i64);
     PMULLB = DAG.getNode(ISD::INTRINSIC_WO_CHAIN, DL, MVT::nxv16i8, PMULLB, OpA,
                          OpB);
-    PMULLB = DAG.getNode(ISD::BITCAST, DL, VT, PMULLB);
-
-    SDValue PMUL_OpALo_OpBHi =
-        DAG.getNode(ISD::CLMUL, DL, MVT::nxv16i8, OpA, OpBHi);
-    SDValue PMUL_OpAHi_OpBLo =
-        DAG.getNode(ISD::CLMUL, DL, MVT::nxv16i8, OpAHi, OpB);
-    SDValue Cross = DAG.getNode(ISD::XOR, DL, MVT::nxv16i8, PMUL_OpALo_OpBHi,
-                                PMUL_OpAHi_OpBLo);
-    Cross = DAG.getNode(ISD::SHL, DL, VT,
-                        DAG.getNode(ISD::BITCAST, DL, VT, Cross), SplatEight);
-
-    return DAG.getNode(ISD::XOR, DL, VT, PMULLB, Cross);
+    PMULLB = DAG.getNode(AArch64ISD::NVCAST, DL, VT, PMULLB);
+
+    return DAG.getNode(ISD::XOR, DL, VT, PMULLB, SHL);
   }
 
   EVT VecVT = EVT::getVectorVT(*DAG.getContext(), VT, 64 / VT.getSizeInBits());
diff --git a/llvm/test/CodeGen/AArch64/clmul-scalable.ll b/llvm/test/CodeGen/AArch64/clmul-scalable.ll
index 04114e1dc1807..5dad96074b88b 100644
--- a/llvm/test/CodeGen/AArch64/clmul-scalable.ll
+++ b/llvm/test/CodeGen/AArch64/clmul-scalable.ll
@@ -237,48 +237,44 @@ define <vscale x 8 x i16> @clmul_nxv8i16(<vscale x 8 x i16> %x, <vscale x 8 x i1
 ;
 ; CHECK-SME-STREAMING-LABEL: clmul_nxv8i16:
 ; CHECK-SME-STREAMING:       // %bb.0:
-; CHECK-SME-STREAMING-NEXT:    lsr z2.h, z0.h, #8
-; CHECK-SME-STREAMING-NEXT:    lsr z3.h, z1.h, #8
-; CHECK-SME-STREAMING-NEXT:    pmul z2.b, z2.b, z1.b
-; CHECK-SME-STREAMING-NEXT:    pmul z3.b, z0.b, z3.b
+; CHECK-SME-STREAMING-NEXT:    trn1 z2.b, z1.b, z0.b
+; CHECK-SME-STREAMING-NEXT:    trn2 z3.b, z0.b, z1.b
 ; CHECK-SME-STREAMING-NEXT:    pmullb z0.h, z0.b, z1.b
-; CHECK-SME-STREAMING-NEXT:    eor z1.d, z3.d, z2.d
+; CHECK-SME-STREAMING-NEXT:    pmul z2.b, z3.b, z2.b
+; CHECK-SME-STREAMING-NEXT:    eorbt z1.b, z2.b, z2.b
 ; CHECK-SME-STREAMING-NEXT:    lsl z1.h, z1.h, #8
 ; CHECK-SME-STREAMING-NEXT:    eor z0.d, z0.d, z1.d
 ; CHECK-SME-STREAMING-NEXT:    ret
 ;
 ; CHECK-SME-STREAMING-SSVE-AES-LABEL: clmul_nxv8i16:
 ; CHECK-SME-STREAMING-SSVE-AES:       // %bb.0:
-; CHECK-SME-STREAMING-SSVE-AES-NEXT:    lsr z2.h, z0.h, #8
-; CHECK-SME-STREAMING-SSVE-AES-NEXT:    lsr z3.h, z1.h, #8
-; CHECK-SME-STREAMING-SSVE-AES-NEXT:    pmul z2.b, z2.b, z1.b
-; CHECK-SME-STREAMING-SSVE-AES-NEXT:    pmul z3.b, z0.b, z3.b
+; CHECK-SME-STREAMING-SSVE-AES-NEXT:    trn1 z2.b, z1.b, z0.b
+; CHECK-SME-STREAMING-SSVE-AES-NEXT:    trn2 z3.b, z0.b, z1.b
 ; CHECK-SME-STREAMING-SSVE-AES-NEXT:    pmullb z0.h, z0.b, z1.b
-; CHECK-SME-STREAMING-SSVE-AES-NEXT:    eor z1.d, z3.d, z2.d
+; CHECK-SME-STREAMING-SSVE-AES-NEXT:    pmul z2.b, z3.b, z2.b
+; CHECK-SME-STREAMING-SSVE-AES-NEXT:    eorbt z1.b, z2.b, z2.b
 ; CHECK-SME-STREAMING-SSVE-AES-NEXT:    lsl z1.h, z1.h, #8
 ; CHECK-SME-STREAMING-SSVE-AES-NEXT:    eor z0.d, z0.d, z1.d
 ; CHECK-SME-STREAMING-SSVE-AES-NEXT:    ret
 ;
 ; CHECK-SVE2-LABEL: clmul_nxv8i16:
 ; CHECK-SVE2:       // %bb.0:
-; CHECK-SVE2-NEXT:    lsr z2.h, z0.h, #8
-; CHECK-SVE2-NEXT:    lsr z3.h, z1.h, #8
-; CHECK-SVE2-NEXT:    pmul z2.b, z2.b, z1.b
-; CHECK-SVE2-NEXT:    pmul z3.b, z0.b, z3.b
+; CHECK-SVE2-NEXT:    trn1 z2.b, z1.b, z0.b
+; CHECK-SVE2-NEXT:    trn2 z3.b, z0.b, z1.b
 ; CHECK-SVE2-NEXT:    pmullb z0.h, z0.b, z1.b
-; CHECK-SVE2-NEXT:    eor z1.d, z3.d, z2.d
+; CHECK-SVE2-NEXT:    pmul z2.b, z3.b, z2.b
+; CHECK-SVE2-NEXT:    eorbt z1.b, z2.b, z2.b
 ; CHECK-SVE2-NEXT:    lsl z1.h, z1.h, #8
 ; CHECK-SVE2-NEXT:    eor z0.d, z0.d, z1.d
 ; CHECK-SVE2-NEXT:    ret
 ;
 ; CHECK-SVE2-AES-LABEL: clmul_nxv8i16:
 ; CHECK-SVE2-AES:       // %bb.0:
-; CHECK-SVE2-AES-NEXT:    lsr z2.h, z0.h, #8
-; CHECK-SVE2-AES-NEXT:    lsr z3.h, z1.h, #8
-; CHECK-SVE2-AES-NEXT:    pmul z2.b, z2.b, z1.b
-; CHECK-SVE2-AES-NEXT:    pmul z3.b, z0.b, z3.b
+; CHECK-SVE2-AES-NEXT:    trn1 z2.b, z1.b, z0.b
+; CHECK-SVE2-AES-NEXT:    trn2 z3.b, z0.b, z1.b
 ; CHECK-SVE2-AES-NEXT:    pmullb z0.h, z0.b, z1.b
-; CHECK-SVE2-AES-NEXT:    eor z1.d, z3.d, z2.d
+; CHECK-SVE2-AES-NEXT:    pmul z2.b, z3.b, z2.b
+; CHECK-SVE2-AES-NEXT:    eorbt z1.b, z2.b, z2.b
 ; CHECK-SVE2-AES-NEXT:    lsl z1.h, z1.h, #8
 ; CHECK-SVE2-AES-NEXT:    eor z0.d, z0.d, z1.d
 ; CHECK-SVE2-AES-NEXT:    ret
@@ -1505,12 +1501,11 @@ define <vscale x 8 x i16> @clmul_nxv8i16_zext(<vscale x 8 x i8> %x, <vscale x 8
 ; CHECK-SME-STREAMING:       // %bb.0:
 ; CHECK-SME-STREAMING-NEXT:    and z0.h, z0.h, #0xff
 ; CHECK-SME-STREAMING-NEXT:    and z1.h, z1.h, #0xff
-; CHECK-SME-STREAMING-NEXT:    lsr z2.h, z0.h, #8
-; CHECK-SME-STREAMING-NEXT:    lsr z3.h, z1.h, #8
-; CHECK-SME-STREAMING-NEXT:    pmul z2.b, z2.b, z1.b
-; CHECK-SME-STREAMING-NEXT:    pmul z3.b, z0.b, z3.b
+; CHECK-SME-STREAMING-NEXT:    trn1 z2.b, z1.b, z0.b
+; CHECK-SME-STREAMING-NEXT:    trn2 z3.b, z0.b, z1.b
 ; CHECK-SME-STREAMING-NEXT:    pmullb z0.h, z0.b, z1.b
-; CHECK-SME-STREAMING-NEXT:    eor z1.d, z3.d, z2.d
+; CHECK-SME-STREAMING-NEXT:    pmul z2.b, z3.b, z2.b
+; CHECK-SME-STREAMING-NEXT:    eorbt z1.b, z2.b, z2.b
 ; CHECK-SME-STREAMING-NEXT:    lsl z1.h, z1.h, #8
 ; CHECK-SME-STREAMING-NEXT:    eor z0.d, z0.d, z1.d
 ; CHECK-SME-STREAMING-NEXT:    ret
@@ -1519,12 +1514,11 @@ define <vscale x 8 x i16> @clmul_nxv8i16_zext(<vscale x 8 x i8> %x, <vscale x 8
 ; CHECK-SME-STREAMING-SSVE-AES:       // %bb.0:
 ; CHECK-SME-STREAMING-SSVE-AES-NEXT:    and z0.h, z0.h, #0xff
 ; CHECK-SME-STREAMING-SSVE-AES-NEXT:    and z1.h, z1.h, #0xff
-; CHECK-SME-STREAMING-SSVE-AES-NEXT:    lsr z2.h, z0.h, #8
-; CHECK-SME-STREAMING-SSVE-AES-NEXT:    lsr z3.h, z1.h, #8
-; CHECK-SME-STREAMING-SSVE-AES-NEXT:    pmul z2.b, z2.b, z1.b
-; CHECK-SME-STREAMING-SSVE-AES-NEXT:    pmul z3.b, z0.b, z3.b
+; CHECK-SME-STREAMING-SSVE-AES-NEXT:    trn1 z2.b, z1.b, z0.b
+; CHECK-SME-STREAMING-SSVE-AES-NEXT:    trn2 z3.b, z0.b, z1.b
 ; CHECK-SME-STREAMING-SSVE-AES-NEXT:    pmullb z0.h, z0.b, z1.b
-; CHECK-SME-STREAMING-SSVE-AES-NEXT:    eor z1.d, z3.d, z2.d
+; CHECK-SME-STREAMING-SSVE-AES-NEXT:    pmul z2.b, z3.b, z2.b
+; CHECK-SME-STREAMING-SSVE-AES-NEXT:    eorbt z1.b, z2.b, z2.b
 ; CHECK-SME-STREAMING-SSVE-AES-NEXT:    lsl z1.h, z1.h, #8
 ; CHECK-SME-STREAMING-SSVE-AES-NEXT:    eor z0.d, z0.d, z1.d
 ; CHECK-SME-STREAMING-SSVE-AES-NEXT:    ret
@@ -1533,12 +1527,11 @@ define <vscale x 8 x i16> @clmul_nxv8i16_zext(<vscale x 8 x i8> %x, <vscale x 8
 ; CHECK-SVE2:       // %bb.0:
 ; CHECK-SVE2-NEXT:    and z0.h, z0.h, #0xff
 ; CHECK-SVE2-NEXT:    and z1.h, z1.h, #0xff
-; CHECK-SVE2-NEXT:    lsr z2.h, z0.h, #8
-; CHECK-SVE2-NEXT:    lsr z3.h, z1.h, #8
-; CHECK-SVE2-NEXT:    pmul z2.b, z2.b, z1.b
-; CHECK-SVE2-NEXT:    pmul z3.b, z0.b, z3.b
+; CHECK-SVE2-NEXT:    trn1 z2.b, z1.b, z0.b
+; CHECK-SVE2-NEXT:    trn2 z3.b, z0.b, z1.b
 ; CHECK-SVE2-NEXT:    pmullb z0.h, z0.b, z1.b
-; CHECK-SVE2-NEXT:    eor z1.d, z3.d, z2.d
+; CHECK-SVE2-NEXT:    pmul z2.b, z3.b, z2.b
+; CHECK-SVE2-NEXT:    eorbt z1.b, z2.b, z2.b
 ; CHECK-SVE2-NEXT:    lsl z1.h, z1.h, #8
 ; CHECK-SVE2-NEXT:    eor z0.d, z0.d, z1.d
 ; CHECK-SVE2-NEXT:    ret
@@ -1547,12 +1540,11 @@ define <vscale x 8 x i16> @clmul_nxv8i16_zext(<vscale x 8 x i8> %x, <vscale x 8
 ; CHECK-SVE2-AES:       // %bb.0:
 ; CHECK-SVE2-AES-NEXT:    and z0.h, z0.h, #0xff
 ; CHECK-SVE2-AES-NEXT:    and z1.h, z1.h, #0xff
-; CHECK-SVE2-AES-NEXT:    lsr z2.h, z0.h, #8
-; CHECK-SVE2-AES-NEXT:    lsr z3.h, z1.h, #8
-; CHECK-SVE2-AES-NEXT:    pmul z2.b, z2.b, z1.b
-; CHECK-SVE2-AES-NEXT:    pmul z3.b, z0.b, z3.b
+; CHECK-SVE2-AES-NEXT:    trn1 z2.b, z1.b, z0.b
+; CHECK-SVE2-AES-NEXT:    trn2 z3.b, z0.b, z1.b
 ; CHECK-SVE2-AES-NEXT:    pmullb z0.h, z0.b, z1.b
-; CHECK-SVE2-AES-NEXT:    eor z1.d, z3.d, z2.d
+; CHECK-SVE2-AES-NEXT:    pmul z2.b, z3.b, z2.b
+; CHECK-SVE2-AES-NEXT:    eorbt z1.b, z2.b, z2.b
 ; CHECK-SVE2-AES-NEXT:    lsl z1.h, z1.h, #8
 ; CHECK-SVE2-AES-NEXT:    eor z0.d, z0.d, z1.d
 ; CHECK-SVE2-AES-NEXT:    ret

>From 6df3e2228f02056d73de0b4ccdb080610a48d115 Mon Sep 17 00:00:00 2001
From: Matthew Devereau <matthew.devereau at arm.com>
Date: Mon, 11 May 2026 14:41:49 +0000
Subject: [PATCH 3/3] use eortb

---
 .../Target/AArch64/AArch64ISelLowering.cpp    | 19 +++++++--------
 llvm/test/CodeGen/AArch64/clmul-scalable.ll   | 24 +++++++------------
 2 files changed, 16 insertions(+), 27 deletions(-)

diff --git a/llvm/lib/Target/AArch64/AArch64ISelLowering.cpp b/llvm/lib/Target/AArch64/AArch64ISelLowering.cpp
index d2603cc1e52c2..448e74ecd3413 100644
--- a/llvm/lib/Target/AArch64/AArch64ISelLowering.cpp
+++ b/llvm/lib/Target/AArch64/AArch64ISelLowering.cpp
@@ -8096,10 +8096,8 @@ static SDValue LowerCLMUL(SDValue Op, SelectionDAG &DAG) {
          "Unexpected Type");
 
   if (VT == MVT::nxv8i16) {
-    // clmul.i16(a, b) = xor(pmullb(a_lo, b_lo),
-    //                       lsl(eorbt(pmul(trn2(a, b),
-    //                                      trn1(b, a))),
-    //                           8))
+    // clmul.i16(a, b) = eortb(pmullb(a_lo, b_lo),
+    //                         pmul(trn2(a, b), trn1(b, a)))
     SDValue OpA = Op.getOperand(0);
     SDValue OpB = Op.getOperand(1);
     // Bitcast to i8 for byte-wise PMUL and PMULLB.
@@ -8107,8 +8105,7 @@ static SDValue LowerCLMUL(SDValue Op, SelectionDAG &DAG) {
     OpB = DAG.getNode(AArch64ISD::NVCAST, DL, MVT::nxv16i8, OpB);
 
     // Form adjacent byte pairs {a_hi, b_hi} and {b_lo, a_lo}. PMUL then
-    // computes {a_hi * b_lo, b_hi * a_lo}, and EORTB xors those pairs into
-    // the low byte of each half-word.
+    // computes {a_hi * b_lo, b_hi * a_lo}, and EORBT xors those pairs.
     SDValue LoBytes = DAG.getNode(AArch64ISD::TRN1, DL, MVT::nxv16i8, OpB, OpA);
     SDValue HiBytes = DAG.getNode(AArch64ISD::TRN2, DL, MVT::nxv16i8, OpA, OpB);
     SDValue PMUL = DAG.getNode(ISD::CLMUL, DL, MVT::nxv16i8, HiBytes, LoBytes);
@@ -8117,17 +8114,17 @@ static SDValue LowerCLMUL(SDValue Op, SelectionDAG &DAG) {
         DAG.getTargetConstant(Intrinsic::aarch64_sve_eorbt, DL, MVT::i64);
     EORBT = DAG.getNode(ISD::INTRINSIC_WO_CHAIN, DL, MVT::nxv16i8, EORBT, OpB,
                         PMUL, PMUL);
-    SDValue SHL = DAG.getNode(ISD::SHL, DL, VT,
-                              DAG.getNode(AArch64ISD::NVCAST, DL, VT, EORBT),
-                              DAG.getConstant(8, DL, VT));
 
     SDValue PMULLB =
         DAG.getTargetConstant(Intrinsic::aarch64_sve_pmullb_pair, DL, MVT::i64);
     PMULLB = DAG.getNode(ISD::INTRINSIC_WO_CHAIN, DL, MVT::nxv16i8, PMULLB, OpA,
                          OpB);
-    PMULLB = DAG.getNode(AArch64ISD::NVCAST, DL, VT, PMULLB);
 
-    return DAG.getNode(ISD::XOR, DL, VT, PMULLB, SHL);
+    SDValue EORTB =
+        DAG.getTargetConstant(Intrinsic::aarch64_sve_eortb, DL, MVT::i64);
+    EORTB = DAG.getNode(ISD::INTRINSIC_WO_CHAIN, DL, MVT::nxv16i8, EORTB,
+                        PMULLB, PMULLB, EORBT);
+    return DAG.getNode(AArch64ISD::NVCAST, DL, MVT::nxv8i16, EORTB);
   }
 
   EVT VecVT = EVT::getVectorVT(*DAG.getContext(), VT, 64 / VT.getSizeInBits());
diff --git a/llvm/test/CodeGen/AArch64/clmul-scalable.ll b/llvm/test/CodeGen/AArch64/clmul-scalable.ll
index 5dad96074b88b..202d1b6c2daae 100644
--- a/llvm/test/CodeGen/AArch64/clmul-scalable.ll
+++ b/llvm/test/CodeGen/AArch64/clmul-scalable.ll
@@ -242,8 +242,7 @@ define <vscale x 8 x i16> @clmul_nxv8i16(<vscale x 8 x i16> %x, <vscale x 8 x i1
 ; CHECK-SME-STREAMING-NEXT:    pmullb z0.h, z0.b, z1.b
 ; CHECK-SME-STREAMING-NEXT:    pmul z2.b, z3.b, z2.b
 ; CHECK-SME-STREAMING-NEXT:    eorbt z1.b, z2.b, z2.b
-; CHECK-SME-STREAMING-NEXT:    lsl z1.h, z1.h, #8
-; CHECK-SME-STREAMING-NEXT:    eor z0.d, z0.d, z1.d
+; CHECK-SME-STREAMING-NEXT:    eortb z0.b, z0.b, z1.b
 ; CHECK-SME-STREAMING-NEXT:    ret
 ;
 ; CHECK-SME-STREAMING-SSVE-AES-LABEL: clmul_nxv8i16:
@@ -253,8 +252,7 @@ define <vscale x 8 x i16> @clmul_nxv8i16(<vscale x 8 x i16> %x, <vscale x 8 x i1
 ; CHECK-SME-STREAMING-SSVE-AES-NEXT:    pmullb z0.h, z0.b, z1.b
 ; CHECK-SME-STREAMING-SSVE-AES-NEXT:    pmul z2.b, z3.b, z2.b
 ; CHECK-SME-STREAMING-SSVE-AES-NEXT:    eorbt z1.b, z2.b, z2.b
-; CHECK-SME-STREAMING-SSVE-AES-NEXT:    lsl z1.h, z1.h, #8
-; CHECK-SME-STREAMING-SSVE-AES-NEXT:    eor z0.d, z0.d, z1.d
+; CHECK-SME-STREAMING-SSVE-AES-NEXT:    eortb z0.b, z0.b, z1.b
 ; CHECK-SME-STREAMING-SSVE-AES-NEXT:    ret
 ;
 ; CHECK-SVE2-LABEL: clmul_nxv8i16:
@@ -264,8 +262,7 @@ define <vscale x 8 x i16> @clmul_nxv8i16(<vscale x 8 x i16> %x, <vscale x 8 x i1
 ; CHECK-SVE2-NEXT:    pmullb z0.h, z0.b, z1.b
 ; CHECK-SVE2-NEXT:    pmul z2.b, z3.b, z2.b
 ; CHECK-SVE2-NEXT:    eorbt z1.b, z2.b, z2.b
-; CHECK-SVE2-NEXT:    lsl z1.h, z1.h, #8
-; CHECK-SVE2-NEXT:    eor z0.d, z0.d, z1.d
+; CHECK-SVE2-NEXT:    eortb z0.b, z0.b, z1.b
 ; CHECK-SVE2-NEXT:    ret
 ;
 ; CHECK-SVE2-AES-LABEL: clmul_nxv8i16:
@@ -275,8 +272,7 @@ define <vscale x 8 x i16> @clmul_nxv8i16(<vscale x 8 x i16> %x, <vscale x 8 x i1
 ; CHECK-SVE2-AES-NEXT:    pmullb z0.h, z0.b, z1.b
 ; CHECK-SVE2-AES-NEXT:    pmul z2.b, z3.b, z2.b
 ; CHECK-SVE2-AES-NEXT:    eorbt z1.b, z2.b, z2.b
-; CHECK-SVE2-AES-NEXT:    lsl z1.h, z1.h, #8
-; CHECK-SVE2-AES-NEXT:    eor z0.d, z0.d, z1.d
+; CHECK-SVE2-AES-NEXT:    eortb z0.b, z0.b, z1.b
 ; CHECK-SVE2-AES-NEXT:    ret
   %a = call <vscale x 8 x i16> @llvm.clmul.nxv8i16(<vscale x 8 x i16> %x, <vscale x 8 x i16> %y)
   ret <vscale x 8 x i16> %a
@@ -1506,8 +1502,7 @@ define <vscale x 8 x i16> @clmul_nxv8i16_zext(<vscale x 8 x i8> %x, <vscale x 8
 ; CHECK-SME-STREAMING-NEXT:    pmullb z0.h, z0.b, z1.b
 ; CHECK-SME-STREAMING-NEXT:    pmul z2.b, z3.b, z2.b
 ; CHECK-SME-STREAMING-NEXT:    eorbt z1.b, z2.b, z2.b
-; CHECK-SME-STREAMING-NEXT:    lsl z1.h, z1.h, #8
-; CHECK-SME-STREAMING-NEXT:    eor z0.d, z0.d, z1.d
+; CHECK-SME-STREAMING-NEXT:    eortb z0.b, z0.b, z1.b
 ; CHECK-SME-STREAMING-NEXT:    ret
 ;
 ; CHECK-SME-STREAMING-SSVE-AES-LABEL: clmul_nxv8i16_zext:
@@ -1519,8 +1514,7 @@ define <vscale x 8 x i16> @clmul_nxv8i16_zext(<vscale x 8 x i8> %x, <vscale x 8
 ; CHECK-SME-STREAMING-SSVE-AES-NEXT:    pmullb z0.h, z0.b, z1.b
 ; CHECK-SME-STREAMING-SSVE-AES-NEXT:    pmul z2.b, z3.b, z2.b
 ; CHECK-SME-STREAMING-SSVE-AES-NEXT:    eorbt z1.b, z2.b, z2.b
-; CHECK-SME-STREAMING-SSVE-AES-NEXT:    lsl z1.h, z1.h, #8
-; CHECK-SME-STREAMING-SSVE-AES-NEXT:    eor z0.d, z0.d, z1.d
+; CHECK-SME-STREAMING-SSVE-AES-NEXT:    eortb z0.b, z0.b, z1.b
 ; CHECK-SME-STREAMING-SSVE-AES-NEXT:    ret
 ;
 ; CHECK-SVE2-LABEL: clmul_nxv8i16_zext:
@@ -1532,8 +1526,7 @@ define <vscale x 8 x i16> @clmul_nxv8i16_zext(<vscale x 8 x i8> %x, <vscale x 8
 ; CHECK-SVE2-NEXT:    pmullb z0.h, z0.b, z1.b
 ; CHECK-SVE2-NEXT:    pmul z2.b, z3.b, z2.b
 ; CHECK-SVE2-NEXT:    eorbt z1.b, z2.b, z2.b
-; CHECK-SVE2-NEXT:    lsl z1.h, z1.h, #8
-; CHECK-SVE2-NEXT:    eor z0.d, z0.d, z1.d
+; CHECK-SVE2-NEXT:    eortb z0.b, z0.b, z1.b
 ; CHECK-SVE2-NEXT:    ret
 ;
 ; CHECK-SVE2-AES-LABEL: clmul_nxv8i16_zext:
@@ -1545,8 +1538,7 @@ define <vscale x 8 x i16> @clmul_nxv8i16_zext(<vscale x 8 x i8> %x, <vscale x 8
 ; CHECK-SVE2-AES-NEXT:    pmullb z0.h, z0.b, z1.b
 ; CHECK-SVE2-AES-NEXT:    pmul z2.b, z3.b, z2.b
 ; CHECK-SVE2-AES-NEXT:    eorbt z1.b, z2.b, z2.b
-; CHECK-SVE2-AES-NEXT:    lsl z1.h, z1.h, #8
-; CHECK-SVE2-AES-NEXT:    eor z0.d, z0.d, z1.d
+; CHECK-SVE2-AES-NEXT:    eortb z0.b, z0.b, z1.b
 ; CHECK-SVE2-AES-NEXT:    ret
   %zextx = zext <vscale x 8 x i8> %x to <vscale x 8 x i16>
   %zexty = zext <vscale x 8 x i8> %y to <vscale x 8 x i16>



More information about the llvm-commits mailing list