[llvm] [AArch64] Improve fixed vector lowering for cttz/ctlz when sve (PR #192427)
Yashwant Singh via llvm-commits
llvm-commits at lists.llvm.org
Thu May 7 20:05:15 PDT 2026
https://github.com/yashssh updated https://github.com/llvm/llvm-project/pull/192427
>From 59b491b56150318d42dd575ad616c06a2d83ec0c Mon Sep 17 00:00:00 2001
From: Yashwant Singh <yashwants at nvidia.com>
Date: Thu, 16 Apr 2026 04:34:35 -0700
Subject: [PATCH] [AArch64] Improve fixed vector lowering for cttz/ctlz when
sve
When available we should be able to lower fixed size 64/128 bit cttz/ctlz vector instructions using sve. Below are the performance uplifts
+--------------+--------------+--------------+
| Function | CTTZ Speedup | CTLZ Speedup |
+--------------+--------------+--------------+
| u8x8 | 1.33x | 1.00x |
| u16x4 | 1.26x | 1.00x |
| u32x2 | 1.26x | 1.00x |
| u64x1 | 1.00x | 7.00x |
+--------------+--------------+--------------+
| u8x16 | 1.67x | 1.00x |
| u16x8 | 1.51x | 1.00x |
| u32x4 | 1.51x | 1.00x |
| u64x2 | 1.26x | 7.00x |
+--------------+--------------+--------------+
---
llvm/lib/Target/AArch64/AArch64ISelLowering.cpp | 13 +++++++++----
.../AArch64/sve-fixed-length-bit-counting.ll | 8 ++++----
2 files changed, 13 insertions(+), 8 deletions(-)
diff --git a/llvm/lib/Target/AArch64/AArch64ISelLowering.cpp b/llvm/lib/Target/AArch64/AArch64ISelLowering.cpp
index 8c53ea0dd94eb..73c0e39e98f82 100644
--- a/llvm/lib/Target/AArch64/AArch64ISelLowering.cpp
+++ b/llvm/lib/Target/AArch64/AArch64ISelLowering.cpp
@@ -1943,6 +1943,11 @@ AArch64TargetLowering::AArch64TargetLowering(const TargetMachine &TM,
setOperationAction(ISD::VECREDUCE_UMIN, MVT::v2i64, Custom);
}
+ for (auto VT : {MVT::v1i64, MVT::v2i64}) {
+ setOperationAction(ISD::CTLZ, VT, Custom);
+ setOperationAction(ISD::CTTZ, VT, Custom);
+ }
+
// NOTE: Currently this has to happen after computeRegisterProperties rather
// than the preferred option of combining it with the addRegisterClass call.
if (Subtarget->useSVEForFixedLengthVectors()) {
@@ -1970,9 +1975,6 @@ AArch64TargetLowering::AArch64TargetLowering(const TargetMachine &TM,
// These operations are not supported on NEON but SVE can do them.
setOperationAction(ISD::BITREVERSE, MVT::v1i64, Custom);
- setOperationAction(ISD::CTLZ, MVT::v1i64, Custom);
- setOperationAction(ISD::CTLZ, MVT::v2i64, Custom);
- setOperationAction(ISD::CTTZ, MVT::v1i64, Custom);
setOperationAction(ISD::SMAX, MVT::v1i64, Custom);
setOperationAction(ISD::SMAX, MVT::v2i64, Custom);
setOperationAction(ISD::SMIN, MVT::v1i64, Custom);
@@ -1990,11 +1992,14 @@ AArch64TargetLowering::AArch64TargetLowering(const TargetMachine &TM,
for (auto VT : {MVT::v8i8, MVT::v16i8, MVT::v4i16, MVT::v8i16,
MVT::v2i32, MVT::v4i32, MVT::v2i64}) {
setOperationAction(ISD::BITREVERSE, VT, Custom);
- setOperationAction(ISD::CTTZ, VT, Custom);
setOperationAction(ISD::VECREDUCE_AND, VT, Custom);
setOperationAction(ISD::VECREDUCE_OR, VT, Custom);
setOperationAction(ISD::VECREDUCE_XOR, VT, Custom);
}
+ for (auto VT : {MVT::v8i8, MVT::v16i8, MVT::v4i16, MVT::v8i16, MVT::v2i32,
+ MVT::v4i32}) {
+ setOperationAction(ISD::CTTZ, VT, Custom);
+ }
// Use SVE for vectors with more than 2 elements.
for (auto VT : {MVT::v4f16, MVT::v8f16, MVT::v4f32})
diff --git a/llvm/test/CodeGen/AArch64/sve-fixed-length-bit-counting.ll b/llvm/test/CodeGen/AArch64/sve-fixed-length-bit-counting.ll
index b62b850434469..57797d04453bc 100644
--- a/llvm/test/CodeGen/AArch64/sve-fixed-length-bit-counting.ll
+++ b/llvm/test/CodeGen/AArch64/sve-fixed-length-bit-counting.ll
@@ -273,7 +273,7 @@ define void @ctlz_v64i32(ptr %a) vscale_range(16,0) #0 {
ret void
}
-define <1 x i64> @ctlz_v1i64(<1 x i64> %op) vscale_range(2,0) #0 {
+define <1 x i64> @ctlz_v1i64(<1 x i64> %op) #0 {
; CHECK-LABEL: ctlz_v1i64:
; CHECK: // %bb.0:
; CHECK-NEXT: ptrue p0.d, vl1
@@ -285,7 +285,7 @@ define <1 x i64> @ctlz_v1i64(<1 x i64> %op) vscale_range(2,0) #0 {
ret <1 x i64> %res
}
-define <2 x i64> @ctlz_v2i64(<2 x i64> %op) vscale_range(2,0) #0 {
+define <2 x i64> @ctlz_v2i64(<2 x i64> %op) #0 {
; CHECK-LABEL: ctlz_v2i64:
; CHECK: // %bb.0:
; CHECK-NEXT: ptrue p0.d, vl2
@@ -1033,7 +1033,7 @@ define void @cttz_v64i32(ptr %a) vscale_range(16,0) #0 {
ret void
}
-define <1 x i64> @cttz_v1i64(<1 x i64> %op) vscale_range(2,0) #0 {
+define <1 x i64> @cttz_v1i64(<1 x i64> %op) #0 {
; CHECK-LABEL: cttz_v1i64:
; CHECK: // %bb.0:
; CHECK-NEXT: ptrue p0.d, vl1
@@ -1046,7 +1046,7 @@ define <1 x i64> @cttz_v1i64(<1 x i64> %op) vscale_range(2,0) #0 {
ret <1 x i64> %res
}
-define <2 x i64> @cttz_v2i64(<2 x i64> %op) vscale_range(2,0) #0 {
+define <2 x i64> @cttz_v2i64(<2 x i64> %op) #0 {
; CHECK-LABEL: cttz_v2i64:
; CHECK: // %bb.0:
; CHECK-NEXT: ptrue p0.d, vl2
More information about the llvm-commits
mailing list