[llvm] [AArch64] Improve v1i64/v2i64 clmulh. (PR #196694)

Craig Topper via llvm-commits llvm-commits at lists.llvm.org
Mon May 11 08:07:25 PDT 2026


https://github.com/topperc updated https://github.com/llvm/llvm-project/pull/196694

>From efbb8e2f8f525829a58516106db6f2ff8efa3663 Mon Sep 17 00:00:00 2001
From: Craig Topper <craig.topper at sifive.com>
Date: Fri, 8 May 2026 23:45:57 -0700
Subject: [PATCH 1/2] [AArch64] Improve v1i64/v2i64 clmulh.

We can use the pmull/pmull2 to commut the full product then take
the high half.
---
 .../Target/AArch64/AArch64ISelLowering.cpp    |  1 +
 llvm/lib/Target/AArch64/AArch64InstrInfo.td   |  9 ++++
 llvm/test/CodeGen/AArch64/clmul-fixed.ll      | 41 ++++++-------------
 3 files changed, 22 insertions(+), 29 deletions(-)

diff --git a/llvm/lib/Target/AArch64/AArch64ISelLowering.cpp b/llvm/lib/Target/AArch64/AArch64ISelLowering.cpp
index b53605e917e2b..69f399646a804 100644
--- a/llvm/lib/Target/AArch64/AArch64ISelLowering.cpp
+++ b/llvm/lib/Target/AArch64/AArch64ISelLowering.cpp
@@ -1533,6 +1533,7 @@ AArch64TargetLowering::AArch64TargetLowering(const TargetMachine &TM,
     if (Subtarget->hasAES()) {
       setOperationAction(ISD::CLMUL, {MVT::i16, MVT::i32, MVT::i64}, Custom);
       setOperationAction(ISD::CLMUL, {MVT::v1i64, MVT::v2i64}, Legal);
+      setOperationAction(ISD::CLMULH, {MVT::v1i64, MVT::v2i64}, Legal);
     }
 
   } else /* !isNeonAvailable */ {
diff --git a/llvm/lib/Target/AArch64/AArch64InstrInfo.td b/llvm/lib/Target/AArch64/AArch64InstrInfo.td
index 6c20efffb1944..54c29ce2bcf04 100644
--- a/llvm/lib/Target/AArch64/AArch64InstrInfo.td
+++ b/llvm/lib/Target/AArch64/AArch64InstrInfo.td
@@ -7987,6 +7987,15 @@ let Predicates = [HasAES] in {
                                 (i64 1),
                                 (v2i64 (PMULLv2i64 $Rn, $Rm)),
                                 (i64 0)))>;
+
+  def : Pat<(v1i64 (clmulh V64:$Rn, V64:$Rm)),
+            (EXTRACT_SUBREG (v2i64 (EXTv16i8 (v2i64 (PMULLv1i64 V64:$Rn, V64:$Rm)),
+                                             (v2i64 (PMULLv1i64 V64:$Rn, V64:$Rm)),
+                                             8)), dsub)>;
+  def : Pat<(v2i64 (clmulh V128:$Rn, V128:$Rm)),
+            (ZIP2v2i64 (v2i64 (PMULLv1i64 (v1i64 (EXTRACT_SUBREG V128:$Rn, dsub)),
+                                          (v1i64 (EXTRACT_SUBREG V128:$Rm, dsub)))),
+                       (v2i64 (PMULLv2i64 V128:$Rn, V128:$Rm)))>;
 }
 
 def : Pat<(v16i8 (vec_ins_or_scal_vec GPR32:$Rn)),
diff --git a/llvm/test/CodeGen/AArch64/clmul-fixed.ll b/llvm/test/CodeGen/AArch64/clmul-fixed.ll
index 70ddde74aafbc..56753dc33db96 100644
--- a/llvm/test/CodeGen/AArch64/clmul-fixed.ll
+++ b/llvm/test/CodeGen/AArch64/clmul-fixed.ll
@@ -6536,15 +6536,13 @@ define <2 x i64> @clmulr_v2i64_neon(<2 x i64> %a, <2 x i64> %b) nounwind {
 ;
 ; CHECK-AES-LABEL: clmulr_v2i64_neon:
 ; CHECK-AES:       // %bb.0:
-; CHECK-AES-NEXT:    rev64 v1.16b, v1.16b
-; CHECK-AES-NEXT:    rev64 v0.16b, v0.16b
-; CHECK-AES-NEXT:    rbit v1.16b, v1.16b
-; CHECK-AES-NEXT:    rbit v0.16b, v0.16b
 ; CHECK-AES-NEXT:    pmull2 v2.1q, v0.2d, v1.2d
 ; CHECK-AES-NEXT:    pmull v0.1q, v0.1d, v1.1d
-; CHECK-AES-NEXT:    mov v0.d[1], v2.d[0]
-; CHECK-AES-NEXT:    rev64 v0.16b, v0.16b
-; CHECK-AES-NEXT:    rbit v0.16b, v0.16b
+; CHECK-AES-NEXT:    zip2 v1.2d, v0.2d, v2.2d
+; CHECK-AES-NEXT:    mov v3.16b, v0.16b
+; CHECK-AES-NEXT:    mov v3.d[1], v2.d[0]
+; CHECK-AES-NEXT:    add v0.2d, v1.2d, v1.2d
+; CHECK-AES-NEXT:    usra v0.2d, v3.2d, #63
 ; CHECK-AES-NEXT:    ret
   %a.ext = zext <2 x i64> %a to <2 x i128>
   %b.ext = zext <2 x i64> %b to <2 x i128>
@@ -7015,13 +7013,10 @@ define <1 x i64> @clmulr_v1i64_neon(<1 x i64> %a, <1 x i64> %b) nounwind {
 ;
 ; CHECK-AES-LABEL: clmulr_v1i64_neon:
 ; CHECK-AES:       // %bb.0:
-; CHECK-AES-NEXT:    rev64 v1.8b, v1.8b
-; CHECK-AES-NEXT:    rev64 v0.8b, v0.8b
-; CHECK-AES-NEXT:    rbit v1.8b, v1.8b
-; CHECK-AES-NEXT:    rbit v0.8b, v0.8b
-; CHECK-AES-NEXT:    pmull v0.1q, v0.1d, v1.1d
-; CHECK-AES-NEXT:    rev64 v0.8b, v0.8b
-; CHECK-AES-NEXT:    rbit v0.8b, v0.8b
+; CHECK-AES-NEXT:    pmull v1.1q, v0.1d, v1.1d
+; CHECK-AES-NEXT:    ext v0.16b, v1.16b, v1.16b, #8
+; CHECK-AES-NEXT:    shl d0, d0, #1
+; CHECK-AES-NEXT:    usra d0, d1, #63
 ; CHECK-AES-NEXT:    ret
   %a.ext = zext <1 x i64> %a to <1 x i128>
   %b.ext = zext <1 x i64> %b to <1 x i128>
@@ -8089,16 +8084,9 @@ define <2 x i64> @clmulh_v2i64_neon(<2 x i64> %a, <2 x i64> %b) nounwind {
 ;
 ; CHECK-AES-LABEL: clmulh_v2i64_neon:
 ; CHECK-AES:       // %bb.0:
-; CHECK-AES-NEXT:    rev64 v1.16b, v1.16b
-; CHECK-AES-NEXT:    rev64 v0.16b, v0.16b
-; CHECK-AES-NEXT:    rbit v1.16b, v1.16b
-; CHECK-AES-NEXT:    rbit v0.16b, v0.16b
 ; CHECK-AES-NEXT:    pmull2 v2.1q, v0.2d, v1.2d
 ; CHECK-AES-NEXT:    pmull v0.1q, v0.1d, v1.1d
-; CHECK-AES-NEXT:    mov v0.d[1], v2.d[0]
-; CHECK-AES-NEXT:    rev64 v0.16b, v0.16b
-; CHECK-AES-NEXT:    rbit v0.16b, v0.16b
-; CHECK-AES-NEXT:    ushr v0.2d, v0.2d, #1
+; CHECK-AES-NEXT:    zip2 v0.2d, v0.2d, v2.2d
 ; CHECK-AES-NEXT:    ret
   %a.ext = zext <2 x i64> %a to <2 x i128>
   %b.ext = zext <2 x i64> %b to <2 x i128>
@@ -8570,14 +8558,9 @@ define <1 x i64> @clmulh_v1i64_neon(<1 x i64> %a, <1 x i64> %b) nounwind {
 ;
 ; CHECK-AES-LABEL: clmulh_v1i64_neon:
 ; CHECK-AES:       // %bb.0:
-; CHECK-AES-NEXT:    rev64 v1.8b, v1.8b
-; CHECK-AES-NEXT:    rev64 v0.8b, v0.8b
-; CHECK-AES-NEXT:    rbit v1.8b, v1.8b
-; CHECK-AES-NEXT:    rbit v0.8b, v0.8b
 ; CHECK-AES-NEXT:    pmull v0.1q, v0.1d, v1.1d
-; CHECK-AES-NEXT:    rev64 v0.8b, v0.8b
-; CHECK-AES-NEXT:    rbit v0.8b, v0.8b
-; CHECK-AES-NEXT:    ushr d0, d0, #1
+; CHECK-AES-NEXT:    ext v0.16b, v0.16b, v0.16b, #8
+; CHECK-AES-NEXT:    // kill: def $d0 killed $d0 killed $q0
 ; CHECK-AES-NEXT:    ret
   %a.ext = zext <1 x i64> %a to <1 x i128>
   %b.ext = zext <1 x i64> %b to <1 x i128>

>From bd6535b4f12f00ade51e1f1d1f393008563b22a6 Mon Sep 17 00:00:00 2001
From: Craig Topper <craig.topper at sifive.com>
Date: Mon, 11 May 2026 08:07:16 -0700
Subject: [PATCH 2/2] Update llvm/lib/Target/AArch64/AArch64InstrInfo.td

Co-authored-by: Matthew Devereau <matthew.devereau at arm.com>
---
 llvm/lib/Target/AArch64/AArch64InstrInfo.td | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)

diff --git a/llvm/lib/Target/AArch64/AArch64InstrInfo.td b/llvm/lib/Target/AArch64/AArch64InstrInfo.td
index 54c29ce2bcf04..ab8d6e4bffa6c 100644
--- a/llvm/lib/Target/AArch64/AArch64InstrInfo.td
+++ b/llvm/lib/Target/AArch64/AArch64InstrInfo.td
@@ -7988,9 +7988,9 @@ let Predicates = [HasAES] in {
                                 (v2i64 (PMULLv2i64 $Rn, $Rm)),
                                 (i64 0)))>;
 
-  def : Pat<(v1i64 (clmulh V64:$Rn, V64:$Rm)),
-            (EXTRACT_SUBREG (v2i64 (EXTv16i8 (v2i64 (PMULLv1i64 V64:$Rn, V64:$Rm)),
-                                             (v2i64 (PMULLv1i64 V64:$Rn, V64:$Rm)),
+  def : Pat<(clmulh v1i64:$Rn, v1i64:$Rm),
+            (EXTRACT_SUBREG (v2i64 (EXTv16i8 (v2i64 (PMULLv1i64 $Rn, $Rm)),
+                                             (v2i64 (PMULLv1i64 $Rn, $Rm)),
                                              8)), dsub)>;
   def : Pat<(v2i64 (clmulh V128:$Rn, V128:$Rm)),
             (ZIP2v2i64 (v2i64 (PMULLv1i64 (v1i64 (EXTRACT_SUBREG V128:$Rn, dsub)),



More information about the llvm-commits mailing list