[llvm] [AArch64] Improve fixed vector lowering for cttz/ctlz when sve (PR #192427)
via llvm-commits
llvm-commits at lists.llvm.org
Thu Apr 16 03:45:34 PDT 2026
llvmbot wrote:
<!--LLVM PR SUMMARY COMMENT-->
@llvm/pr-subscribers-backend-aarch64
Author: Yashwant Singh (yashssh)
<details>
<summary>Changes</summary>
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 |
+--------------+--------------+--------------+
---
Patch is 20.66 KiB, truncated to 20.00 KiB below, full version: https://github.com/llvm/llvm-project/pull/192427.diff
3 Files Affected:
- (modified) llvm/lib/Target/AArch64/AArch64ISelLowering.cpp (+7-5)
- (added) llvm/test/CodeGen/AArch64/ctlz-cttz-fixed-vectors.ll (+391)
- (modified) llvm/test/CodeGen/AArch64/sve-fixed-length-bit-counting.ll (+36-12)
``````````diff
diff --git a/llvm/lib/Target/AArch64/AArch64ISelLowering.cpp b/llvm/lib/Target/AArch64/AArch64ISelLowering.cpp
index 4b6b0758006af..9cae72cedaae5 100644
--- a/llvm/lib/Target/AArch64/AArch64ISelLowering.cpp
+++ b/llvm/lib/Target/AArch64/AArch64ISelLowering.cpp
@@ -1930,6 +1930,12 @@ AArch64TargetLowering::AArch64TargetLowering(const TargetMachine &TM,
setOperationAction(ISD::VECREDUCE_UMIN, MVT::v2i64, Custom);
}
+ for (auto VT : {MVT::v8i8, MVT::v16i8, MVT::v4i16, MVT::v8i16,
+ MVT::v2i32, MVT::v4i32, 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()) {
@@ -1957,9 +1963,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);
@@ -1977,7 +1980,6 @@ 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);
@@ -12070,7 +12072,7 @@ SDValue AArch64TargetLowering::LowerCTTZ(SDValue Op, SelectionDAG &DAG) const {
EVT VT = Op.getValueType();
assert(VT.isScalableVector() ||
useSVEForFixedLengthVectorVT(
- VT, /*OverrideNEON=*/Subtarget->useSVEForFixedLengthVectors()));
+ VT, /*OverrideNEON=*/Subtarget->isSVEorStreamingSVEAvailable()));
SDLoc DL(Op);
SDValue RBIT = DAG.getNode(ISD::BITREVERSE, DL, VT, Op.getOperand(0));
diff --git a/llvm/test/CodeGen/AArch64/ctlz-cttz-fixed-vectors.ll b/llvm/test/CodeGen/AArch64/ctlz-cttz-fixed-vectors.ll
new file mode 100644
index 0000000000000..f17439e5f944a
--- /dev/null
+++ b/llvm/test/CodeGen/AArch64/ctlz-cttz-fixed-vectors.ll
@@ -0,0 +1,391 @@
+; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py
+; RUN: llc < %s -mtriple=aarch64-linux-gnu -mattr=+neon | FileCheck %s --check-prefix=NEON
+; RUN: llc < %s -mtriple=aarch64-linux-gnu -mattr=+sve | FileCheck %s --check-prefix=SVE
+
+; ============================================================
+; CTLZ
+; ============================================================
+
+; --- 64-bit vectors ---
+
+define <8 x i8> @ctlz_v8i8(<8 x i8> %a) {
+; NEON-LABEL: ctlz_v8i8:
+; NEON: // %bb.0:
+; NEON-NEXT: clz v0.8b, v0.8b
+; NEON-NEXT: ret
+;
+; SVE-LABEL: ctlz_v8i8:
+; SVE: // %bb.0:
+; SVE-NEXT: ptrue p0.b, vl8
+; SVE-NEXT: // kill: def $d0 killed $d0 def $z0
+; SVE-NEXT: clz z0.b, p0/m, z0.b
+; SVE-NEXT: // kill: def $d0 killed $d0 killed $z0
+; SVE-NEXT: ret
+ %r = call <8 x i8> @llvm.ctlz.v8i8(<8 x i8> %a, i1 false)
+ ret <8 x i8> %r
+}
+
+define <4 x i16> @ctlz_v4i16(<4 x i16> %a) {
+; NEON-LABEL: ctlz_v4i16:
+; NEON: // %bb.0:
+; NEON-NEXT: clz v0.4h, v0.4h
+; NEON-NEXT: ret
+;
+; SVE-LABEL: ctlz_v4i16:
+; SVE: // %bb.0:
+; SVE-NEXT: ptrue p0.h, vl4
+; SVE-NEXT: // kill: def $d0 killed $d0 def $z0
+; SVE-NEXT: clz z0.h, p0/m, z0.h
+; SVE-NEXT: // kill: def $d0 killed $d0 killed $z0
+; SVE-NEXT: ret
+ %r = call <4 x i16> @llvm.ctlz.v4i16(<4 x i16> %a, i1 false)
+ ret <4 x i16> %r
+}
+
+define <2 x i32> @ctlz_v2i32(<2 x i32> %a) {
+; NEON-LABEL: ctlz_v2i32:
+; NEON: // %bb.0:
+; NEON-NEXT: clz v0.2s, v0.2s
+; NEON-NEXT: ret
+;
+; SVE-LABEL: ctlz_v2i32:
+; SVE: // %bb.0:
+; SVE-NEXT: ptrue p0.s, vl2
+; SVE-NEXT: // kill: def $d0 killed $d0 def $z0
+; SVE-NEXT: clz z0.s, p0/m, z0.s
+; SVE-NEXT: // kill: def $d0 killed $d0 killed $z0
+; SVE-NEXT: ret
+ %r = call <2 x i32> @llvm.ctlz.v2i32(<2 x i32> %a, i1 false)
+ ret <2 x i32> %r
+}
+
+define <1 x i64> @ctlz_v1i64(<1 x i64> %a) {
+; NEON-LABEL: ctlz_v1i64:
+; NEON: // %bb.0:
+; NEON-NEXT: ushr d1, d0, #1
+; NEON-NEXT: orr v0.8b, v0.8b, v1.8b
+; NEON-NEXT: ushr d1, d0, #2
+; NEON-NEXT: orr v0.8b, v0.8b, v1.8b
+; NEON-NEXT: ushr d1, d0, #4
+; NEON-NEXT: orr v0.8b, v0.8b, v1.8b
+; NEON-NEXT: ushr d1, d0, #8
+; NEON-NEXT: orr v0.8b, v0.8b, v1.8b
+; NEON-NEXT: ushr d1, d0, #16
+; NEON-NEXT: orr v0.8b, v0.8b, v1.8b
+; NEON-NEXT: ushr d1, d0, #32
+; NEON-NEXT: orr v0.8b, v0.8b, v1.8b
+; NEON-NEXT: mvn v0.8b, v0.8b
+; NEON-NEXT: cnt v0.8b, v0.8b
+; NEON-NEXT: uaddlp v0.4h, v0.8b
+; NEON-NEXT: uaddlp v0.2s, v0.4h
+; NEON-NEXT: uaddlp v0.1d, v0.2s
+; NEON-NEXT: ret
+;
+; SVE-LABEL: ctlz_v1i64:
+; SVE: // %bb.0:
+; SVE-NEXT: ptrue p0.d, vl1
+; SVE-NEXT: // kill: def $d0 killed $d0 def $z0
+; SVE-NEXT: clz z0.d, p0/m, z0.d
+; SVE-NEXT: // kill: def $d0 killed $d0 killed $z0
+; SVE-NEXT: ret
+ %r = call <1 x i64> @llvm.ctlz.v1i64(<1 x i64> %a, i1 false)
+ ret <1 x i64> %r
+}
+
+; --- 128-bit vectors ---
+
+define <16 x i8> @ctlz_v16i8(<16 x i8> %a) {
+; NEON-LABEL: ctlz_v16i8:
+; NEON: // %bb.0:
+; NEON-NEXT: clz v0.16b, v0.16b
+; NEON-NEXT: ret
+;
+; SVE-LABEL: ctlz_v16i8:
+; SVE: // %bb.0:
+; SVE-NEXT: ptrue p0.b, vl16
+; SVE-NEXT: // kill: def $q0 killed $q0 def $z0
+; SVE-NEXT: clz z0.b, p0/m, z0.b
+; SVE-NEXT: // kill: def $q0 killed $q0 killed $z0
+; SVE-NEXT: ret
+ %r = call <16 x i8> @llvm.ctlz.v16i8(<16 x i8> %a, i1 false)
+ ret <16 x i8> %r
+}
+
+define <8 x i16> @ctlz_v8i16(<8 x i16> %a) {
+; NEON-LABEL: ctlz_v8i16:
+; NEON: // %bb.0:
+; NEON-NEXT: clz v0.8h, v0.8h
+; NEON-NEXT: ret
+;
+; SVE-LABEL: ctlz_v8i16:
+; SVE: // %bb.0:
+; SVE-NEXT: ptrue p0.h, vl8
+; SVE-NEXT: // kill: def $q0 killed $q0 def $z0
+; SVE-NEXT: clz z0.h, p0/m, z0.h
+; SVE-NEXT: // kill: def $q0 killed $q0 killed $z0
+; SVE-NEXT: ret
+ %r = call <8 x i16> @llvm.ctlz.v8i16(<8 x i16> %a, i1 false)
+ ret <8 x i16> %r
+}
+
+define <4 x i32> @ctlz_v4i32(<4 x i32> %a) {
+; NEON-LABEL: ctlz_v4i32:
+; NEON: // %bb.0:
+; NEON-NEXT: clz v0.4s, v0.4s
+; NEON-NEXT: ret
+;
+; SVE-LABEL: ctlz_v4i32:
+; SVE: // %bb.0:
+; SVE-NEXT: ptrue p0.s, vl4
+; SVE-NEXT: // kill: def $q0 killed $q0 def $z0
+; SVE-NEXT: clz z0.s, p0/m, z0.s
+; SVE-NEXT: // kill: def $q0 killed $q0 killed $z0
+; SVE-NEXT: ret
+ %r = call <4 x i32> @llvm.ctlz.v4i32(<4 x i32> %a, i1 false)
+ ret <4 x i32> %r
+}
+
+define <2 x i64> @ctlz_v2i64(<2 x i64> %a) {
+; NEON-LABEL: ctlz_v2i64:
+; NEON: // %bb.0:
+; NEON-NEXT: ushr v1.2d, v0.2d, #1
+; NEON-NEXT: orr v0.16b, v0.16b, v1.16b
+; NEON-NEXT: ushr v1.2d, v0.2d, #2
+; NEON-NEXT: orr v0.16b, v0.16b, v1.16b
+; NEON-NEXT: ushr v1.2d, v0.2d, #4
+; NEON-NEXT: orr v0.16b, v0.16b, v1.16b
+; NEON-NEXT: ushr v1.2d, v0.2d, #8
+; NEON-NEXT: orr v0.16b, v0.16b, v1.16b
+; NEON-NEXT: ushr v1.2d, v0.2d, #16
+; NEON-NEXT: orr v0.16b, v0.16b, v1.16b
+; NEON-NEXT: ushr v1.2d, v0.2d, #32
+; NEON-NEXT: orr v0.16b, v0.16b, v1.16b
+; NEON-NEXT: mvn v0.16b, v0.16b
+; NEON-NEXT: cnt v0.16b, v0.16b
+; NEON-NEXT: uaddlp v0.8h, v0.16b
+; NEON-NEXT: uaddlp v0.4s, v0.8h
+; NEON-NEXT: uaddlp v0.2d, v0.4s
+; NEON-NEXT: ret
+;
+; SVE-LABEL: ctlz_v2i64:
+; SVE: // %bb.0:
+; SVE-NEXT: ptrue p0.d, vl2
+; SVE-NEXT: // kill: def $q0 killed $q0 def $z0
+; SVE-NEXT: clz z0.d, p0/m, z0.d
+; SVE-NEXT: // kill: def $q0 killed $q0 killed $z0
+; SVE-NEXT: ret
+ %r = call <2 x i64> @llvm.ctlz.v2i64(<2 x i64> %a, i1 false)
+ ret <2 x i64> %r
+}
+
+; ============================================================
+; CTTZ
+; ============================================================
+
+; --- 64-bit vectors ---
+
+define <8 x i8> @cttz_v8i8(<8 x i8> %a) {
+; NEON-LABEL: cttz_v8i8:
+; NEON: // %bb.0:
+; NEON-NEXT: movi v1.8b, #1
+; NEON-NEXT: sub v1.8b, v0.8b, v1.8b
+; NEON-NEXT: bic v0.8b, v1.8b, v0.8b
+; NEON-NEXT: cnt v0.8b, v0.8b
+; NEON-NEXT: ret
+;
+; SVE-LABEL: cttz_v8i8:
+; SVE: // %bb.0:
+; SVE-NEXT: rbit v0.8b, v0.8b
+; SVE-NEXT: ptrue p0.b, vl8
+; SVE-NEXT: clz z0.b, p0/m, z0.b
+; SVE-NEXT: // kill: def $d0 killed $d0 killed $z0
+; SVE-NEXT: ret
+ %r = call <8 x i8> @llvm.cttz.v8i8(<8 x i8> %a, i1 false)
+ ret <8 x i8> %r
+}
+
+define <4 x i16> @cttz_v4i16(<4 x i16> %a) {
+; NEON-LABEL: cttz_v4i16:
+; NEON: // %bb.0:
+; NEON-NEXT: movi v1.4h, #1
+; NEON-NEXT: sub v1.4h, v0.4h, v1.4h
+; NEON-NEXT: bic v0.8b, v1.8b, v0.8b
+; NEON-NEXT: movi v1.4h, #16
+; NEON-NEXT: clz v0.4h, v0.4h
+; NEON-NEXT: sub v0.4h, v1.4h, v0.4h
+; NEON-NEXT: ret
+;
+; SVE-LABEL: cttz_v4i16:
+; SVE: // %bb.0:
+; SVE-NEXT: rev16 v0.8b, v0.8b
+; SVE-NEXT: ptrue p0.h, vl4
+; SVE-NEXT: rbit v0.8b, v0.8b
+; SVE-NEXT: clz z0.h, p0/m, z0.h
+; SVE-NEXT: // kill: def $d0 killed $d0 killed $z0
+; SVE-NEXT: ret
+ %r = call <4 x i16> @llvm.cttz.v4i16(<4 x i16> %a, i1 false)
+ ret <4 x i16> %r
+}
+
+define <2 x i32> @cttz_v2i32(<2 x i32> %a) {
+; NEON-LABEL: cttz_v2i32:
+; NEON: // %bb.0:
+; NEON-NEXT: movi v1.2s, #1
+; NEON-NEXT: sub v1.2s, v0.2s, v1.2s
+; NEON-NEXT: bic v0.8b, v1.8b, v0.8b
+; NEON-NEXT: movi v1.2s, #32
+; NEON-NEXT: clz v0.2s, v0.2s
+; NEON-NEXT: sub v0.2s, v1.2s, v0.2s
+; NEON-NEXT: ret
+;
+; SVE-LABEL: cttz_v2i32:
+; SVE: // %bb.0:
+; SVE-NEXT: rev32 v0.8b, v0.8b
+; SVE-NEXT: ptrue p0.s, vl2
+; SVE-NEXT: rbit v0.8b, v0.8b
+; SVE-NEXT: clz z0.s, p0/m, z0.s
+; SVE-NEXT: // kill: def $d0 killed $d0 killed $z0
+; SVE-NEXT: ret
+ %r = call <2 x i32> @llvm.cttz.v2i32(<2 x i32> %a, i1 false)
+ ret <2 x i32> %r
+}
+
+define <1 x i64> @cttz_v1i64(<1 x i64> %a) {
+; NEON-LABEL: cttz_v1i64:
+; NEON: // %bb.0:
+; NEON-NEXT: mov w8, #1 // =0x1
+; NEON-NEXT: fmov d1, x8
+; NEON-NEXT: sub d1, d0, d1
+; NEON-NEXT: bic v0.8b, v1.8b, v0.8b
+; NEON-NEXT: cnt v0.8b, v0.8b
+; NEON-NEXT: uaddlp v0.4h, v0.8b
+; NEON-NEXT: uaddlp v0.2s, v0.4h
+; NEON-NEXT: uaddlp v0.1d, v0.2s
+; NEON-NEXT: ret
+;
+; SVE-LABEL: cttz_v1i64:
+; SVE: // %bb.0:
+; SVE-NEXT: rev64 v0.8b, v0.8b
+; SVE-NEXT: ptrue p0.d, vl1
+; SVE-NEXT: rbit v0.8b, v0.8b
+; SVE-NEXT: clz z0.d, p0/m, z0.d
+; SVE-NEXT: // kill: def $d0 killed $d0 killed $z0
+; SVE-NEXT: ret
+ %r = call <1 x i64> @llvm.cttz.v1i64(<1 x i64> %a, i1 false)
+ ret <1 x i64> %r
+}
+
+; --- 128-bit vectors ---
+
+define <16 x i8> @cttz_v16i8(<16 x i8> %a) {
+; NEON-LABEL: cttz_v16i8:
+; NEON: // %bb.0:
+; NEON-NEXT: movi v1.16b, #1
+; NEON-NEXT: sub v1.16b, v0.16b, v1.16b
+; NEON-NEXT: bic v0.16b, v1.16b, v0.16b
+; NEON-NEXT: cnt v0.16b, v0.16b
+; NEON-NEXT: ret
+;
+; SVE-LABEL: cttz_v16i8:
+; SVE: // %bb.0:
+; SVE-NEXT: rbit v0.16b, v0.16b
+; SVE-NEXT: ptrue p0.b, vl16
+; SVE-NEXT: clz z0.b, p0/m, z0.b
+; SVE-NEXT: // kill: def $q0 killed $q0 killed $z0
+; SVE-NEXT: ret
+ %r = call <16 x i8> @llvm.cttz.v16i8(<16 x i8> %a, i1 false)
+ ret <16 x i8> %r
+}
+
+define <8 x i16> @cttz_v8i16(<8 x i16> %a) {
+; NEON-LABEL: cttz_v8i16:
+; NEON: // %bb.0:
+; NEON-NEXT: movi v1.8h, #1
+; NEON-NEXT: sub v1.8h, v0.8h, v1.8h
+; NEON-NEXT: bic v0.16b, v1.16b, v0.16b
+; NEON-NEXT: movi v1.8h, #16
+; NEON-NEXT: clz v0.8h, v0.8h
+; NEON-NEXT: sub v0.8h, v1.8h, v0.8h
+; NEON-NEXT: ret
+;
+; SVE-LABEL: cttz_v8i16:
+; SVE: // %bb.0:
+; SVE-NEXT: rev16 v0.16b, v0.16b
+; SVE-NEXT: ptrue p0.h, vl8
+; SVE-NEXT: rbit v0.16b, v0.16b
+; SVE-NEXT: clz z0.h, p0/m, z0.h
+; SVE-NEXT: // kill: def $q0 killed $q0 killed $z0
+; SVE-NEXT: ret
+ %r = call <8 x i16> @llvm.cttz.v8i16(<8 x i16> %a, i1 false)
+ ret <8 x i16> %r
+}
+
+define <4 x i32> @cttz_v4i32(<4 x i32> %a) {
+; NEON-LABEL: cttz_v4i32:
+; NEON: // %bb.0:
+; NEON-NEXT: movi v1.4s, #1
+; NEON-NEXT: sub v1.4s, v0.4s, v1.4s
+; NEON-NEXT: bic v0.16b, v1.16b, v0.16b
+; NEON-NEXT: movi v1.4s, #32
+; NEON-NEXT: clz v0.4s, v0.4s
+; NEON-NEXT: sub v0.4s, v1.4s, v0.4s
+; NEON-NEXT: ret
+;
+; SVE-LABEL: cttz_v4i32:
+; SVE: // %bb.0:
+; SVE-NEXT: rev32 v0.16b, v0.16b
+; SVE-NEXT: ptrue p0.s, vl4
+; SVE-NEXT: rbit v0.16b, v0.16b
+; SVE-NEXT: clz z0.s, p0/m, z0.s
+; SVE-NEXT: // kill: def $q0 killed $q0 killed $z0
+; SVE-NEXT: ret
+ %r = call <4 x i32> @llvm.cttz.v4i32(<4 x i32> %a, i1 false)
+ ret <4 x i32> %r
+}
+
+define <2 x i64> @cttz_v2i64(<2 x i64> %a) {
+; NEON-LABEL: cttz_v2i64:
+; NEON: // %bb.0:
+; NEON-NEXT: mov w8, #1 // =0x1
+; NEON-NEXT: dup v1.2d, x8
+; NEON-NEXT: sub v1.2d, v0.2d, v1.2d
+; NEON-NEXT: bic v0.16b, v1.16b, v0.16b
+; NEON-NEXT: cnt v0.16b, v0.16b
+; NEON-NEXT: uaddlp v0.8h, v0.16b
+; NEON-NEXT: uaddlp v0.4s, v0.8h
+; NEON-NEXT: uaddlp v0.2d, v0.4s
+; NEON-NEXT: ret
+;
+; SVE-LABEL: cttz_v2i64:
+; SVE: // %bb.0:
+; SVE-NEXT: rev64 v0.16b, v0.16b
+; SVE-NEXT: ptrue p0.d, vl2
+; SVE-NEXT: rbit v0.16b, v0.16b
+; SVE-NEXT: clz z0.d, p0/m, z0.d
+; SVE-NEXT: // kill: def $q0 killed $q0 killed $z0
+; SVE-NEXT: ret
+ %r = call <2 x i64> @llvm.cttz.v2i64(<2 x i64> %a, i1 false)
+ ret <2 x i64> %r
+}
+
+; ============================================================
+; Declare intrinsics
+; ============================================================
+
+declare <8 x i8> @llvm.ctlz.v8i8 (<8 x i8>, i1)
+declare <4 x i16> @llvm.ctlz.v4i16(<4 x i16>, i1)
+declare <2 x i32> @llvm.ctlz.v2i32(<2 x i32>, i1)
+declare <1 x i64> @llvm.ctlz.v1i64(<1 x i64>, i1)
+declare <16 x i8> @llvm.ctlz.v16i8 (<16 x i8>, i1)
+declare <8 x i16> @llvm.ctlz.v8i16(<8 x i16>, i1)
+declare <4 x i32> @llvm.ctlz.v4i32(<4 x i32>, i1)
+declare <2 x i64> @llvm.ctlz.v2i64(<2 x i64>, i1)
+
+declare <8 x i8> @llvm.cttz.v8i8 (<8 x i8>, i1)
+declare <4 x i16> @llvm.cttz.v4i16(<4 x i16>, i1)
+declare <2 x i32> @llvm.cttz.v2i32(<2 x i32>, i1)
+declare <1 x i64> @llvm.cttz.v1i64(<1 x i64>, i1)
+declare <16 x i8> @llvm.cttz.v16i8 (<16 x i8>, i1)
+declare <8 x i16> @llvm.cttz.v8i16(<8 x i16>, i1)
+declare <4 x i32> @llvm.cttz.v4i32(<4 x i32>, i1)
+declare <2 x i64> @llvm.cttz.v2i64(<2 x i64>, i1)
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..ef3c5d1dac26e 100644
--- a/llvm/test/CodeGen/AArch64/sve-fixed-length-bit-counting.ll
+++ b/llvm/test/CodeGen/AArch64/sve-fixed-length-bit-counting.ll
@@ -13,7 +13,10 @@ target triple = "aarch64-unknown-linux-gnu"
define <8 x i8> @ctlz_v8i8(<8 x i8> %op) vscale_range(2,0) #0 {
; CHECK-LABEL: ctlz_v8i8:
; CHECK: // %bb.0:
-; CHECK-NEXT: clz v0.8b, v0.8b
+; CHECK-NEXT: ptrue p0.b, vl8
+; CHECK-NEXT: // kill: def $d0 killed $d0 def $z0
+; CHECK-NEXT: clz z0.b, p0/m, z0.b
+; CHECK-NEXT: // kill: def $d0 killed $d0 killed $z0
; CHECK-NEXT: ret
%res = call <8 x i8> @llvm.ctlz.v8i8(<8 x i8> %op)
ret <8 x i8> %res
@@ -23,7 +26,10 @@ define <8 x i8> @ctlz_v8i8(<8 x i8> %op) vscale_range(2,0) #0 {
define <16 x i8> @ctlz_v16i8(<16 x i8> %op) vscale_range(2,0) #0 {
; CHECK-LABEL: ctlz_v16i8:
; CHECK: // %bb.0:
-; CHECK-NEXT: clz v0.16b, v0.16b
+; CHECK-NEXT: ptrue p0.b, vl16
+; CHECK-NEXT: // kill: def $q0 killed $q0 def $z0
+; CHECK-NEXT: clz z0.b, p0/m, z0.b
+; CHECK-NEXT: // kill: def $q0 killed $q0 killed $z0
; CHECK-NEXT: ret
%res = call <16 x i8> @llvm.ctlz.v16i8(<16 x i8> %op)
ret <16 x i8> %res
@@ -101,7 +107,10 @@ define void @ctlz_v256i8(ptr %a) vscale_range(16,0) #0 {
define <4 x i16> @ctlz_v4i16(<4 x i16> %op) vscale_range(2,0) #0 {
; CHECK-LABEL: ctlz_v4i16:
; CHECK: // %bb.0:
-; CHECK-NEXT: clz v0.4h, v0.4h
+; CHECK-NEXT: ptrue p0.h, vl4
+; CHECK-NEXT: // kill: def $d0 killed $d0 def $z0
+; CHECK-NEXT: clz z0.h, p0/m, z0.h
+; CHECK-NEXT: // kill: def $d0 killed $d0 killed $z0
; CHECK-NEXT: ret
%res = call <4 x i16> @llvm.ctlz.v4i16(<4 x i16> %op)
ret <4 x i16> %res
@@ -111,7 +120,10 @@ define <4 x i16> @ctlz_v4i16(<4 x i16> %op) vscale_range(2,0) #0 {
define <8 x i16> @ctlz_v8i16(<8 x i16> %op) vscale_range(2,0) #0 {
; CHECK-LABEL: ctlz_v8i16:
; CHECK: // %bb.0:
-; CHECK-NEXT: clz v0.8h, v0.8h
+; CHECK-NEXT: ptrue p0.h, vl8
+; CHECK-NEXT: // kill: def $q0 killed $q0 def $z0
+; CHECK-NEXT: clz z0.h, p0/m, z0.h
+; CHECK-NEXT: // kill: def $q0 killed $q0 killed $z0
; CHECK-NEXT: ret
%res = call <8 x i16> @llvm.ctlz.v8i16(<8 x i16> %op)
ret <8 x i16> %res
@@ -189,7 +201,10 @@ define void @ctlz_v128i16(ptr %a) vscale_range(16,0) #0 {
define <2 x i32> @ctlz_v2i32(<2 x i32> %op) vscale_range(2,0) #0 {
; CHECK-LABEL: ctlz_v2i32:
; CHECK: // %bb.0:
-; CHECK-NEXT: clz v0.2s, v0.2s
+; CHECK-NEXT: ptrue p0.s, vl2
+; CHECK-NEXT: // kill: def $d0 killed $d0 def $z0
+; CHECK-NEXT: clz z0.s, p0/m, z0.s
+; CHECK-NEXT: // kill: def $d0 killed $d0 killed $z0
; CHECK-NEXT: ret
%res = call <2 x i32> @llvm.ctlz.v2i32(<2 x i32> %op)
ret <2 x i32> %res
@@ -199,7 +214,10 @@ define <2 x i32> @ctlz_v2i32(<2 x i32> %op) vscale_range(2,0) #0 {
define <4 x i32> @ctlz_v4i32(<4 x i32> %op) vscale_range(2,0) #0 {
; CHECK-LABEL: ctlz_v4i32:
; CHECK: // %bb.0:
-; CHECK-NEXT: clz v0.4s, v0.4s
+; CHECK-NEXT: ptrue p0.s, vl4
+; CHECK-NEXT: // kill: def $q0 killed $q0 def $z0
+; CHECK-NEXT: clz z0.s, p0/m, z0.s
+; CHECK-NEXT: // kill: def $q0 killed $q0 killed $z0
; CHECK-NEXT: ret
%res = call <4 x i32> @llvm.ctlz.v4i32(<4 x i32> %op)
ret <4 x i32> %res
@@ -743,7 +761,8 @@ define <8 x i8> @cttz_v8i8(<8 x i8> %op) vscale_range(2,0) #0 {
; CHECK-NEXT: ptrue p0.b, vl8
; CHECK-NEXT: // kill: def $d0 killed $d0 def $z0
; CHECK-NEXT: rbit z0.b, p0/m, z0.b
-; CHECK-NEXT: clz v0.8b, v0.8b
+; CHECK-NEXT: clz z0.b, p0/m, z0.b
+; CHECK-NEXT: // kill: def $d0 killed $d0 killed $z0
; CHECK-NEXT: ret
%res = call <8 x i8> @llvm.cttz.v8i8(<8 x i8> %op)
ret <8 x i8> %res
@@ -755,7 +774,8 @@ define <16 x i8> @cttz_v16i8(<16 x i8> %op) vscale_range(2,0) #0 {
; CHECK-NEXT: ptrue p0.b, vl16
; CHECK-NEXT: // kill: def $q0 killed $q0 def $z0
; CHECK-NEXT: rbit z0.b, p0/m, z0.b
-; CHECK-NEXT: clz v0.16b, v0.16b
+; CHECK-NEXT: clz z0.b, p0/m, z0.b
+; CHECK-NEXT: // kill: def $q0 killed $q0 killed $z0
; CHECK-NEXT: ret
%res = call <16 x i8> @llvm.cttz.v16i8(<16 x i8> %op)
ret <16 x i8> %res
@@ -841,7 +861,8 @@ define <4 x i16> @cttz_v4i16(<4 x i16> %op) vscale_range(2,0) #0 {
; CHECK-NEXT: ptrue p0.h, vl4
; CHECK-NEXT: // kill: def $d0 killed $d0 def $z0
; CHECK-NEXT: rbit z0.h, p0/m, z0.h
-; CHECK-NEXT: clz v0.4h, v0.4h
+; CHECK-NEXT: clz z0.h, p0/m, z0.h
+; CHECK-NEXT: // kill: def $d0 killed $d0 killed $z0
; CHECK-NEXT: ret
%res = call <4 x i16> @llvm.cttz.v4i16(<4 x i16> %op)
ret <4 x i16> %res
@@ -853,7 +874,8 @@ define <8 x i16> @cttz_v8i16(<8 x i16> %op) vscale_range(2,0) #0 {
; CHECK-NEXT: ptrue p0.h, vl8
; CHECK-NEXT: // kill: def $q0 killed $q0 def $z0
; CHECK-NEXT: rbit z0.h, p0/m, z0.h
-; CHECK-NEXT: clz v0.8h, v0.8h
+; CHECK-NEXT: clz z0.h, p0/m, z0.h
+; CHECK-NEXT: // kill: def $q0 killed $q0 killed $z0
; CHECK-NEXT: ret
%res = call <8 x i16> @llvm.cttz.v8i16(<8 x i16> %op)
ret <8 x i16> %res
@@ -940,7 +962,8 @@ define <2 x i32> @cttz_v2i32(<2 x i32> %op) vscale_range(2,0) #0 {
; CHECK-NEXT: ptrue p0.s, vl2
; CHECK-NEXT: // kill: def $d0 killed $d0 def $z0
; CHECK-NEXT: rbit z0.s, p0/m, z0.s
-; CHECK...
[truncated]
``````````
</details>
https://github.com/llvm/llvm-project/pull/192427
More information about the llvm-commits
mailing list