[llvm] [AArch64][ISel] Prefer SVE over NEON for fixed-width bitreverse (PR #196264)
via llvm-commits
llvm-commits at lists.llvm.org
Thu May 7 02:15:53 PDT 2026
llvmorg-github-actions[bot] wrote:
<!--LLVM PR SUMMARY COMMENT-->
@llvm/pr-subscribers-backend-aarch64
Author: Harry Ramsey (Harry-Ramsey)
<details>
<summary>Changes</summary>
This commit enables SVE instructions for bitreverse where no equivalent NEON instructions exist. This commit affects the following NEON datatypes; v4i16, v8i16, v2i32, v4i32, v1i64, v2i64.
---
Full diff: https://github.com/llvm/llvm-project/pull/196264.diff
2 Files Affected:
- (modified) llvm/lib/Target/AArch64/AArch64ISelLowering.cpp (+8-2)
- (added) llvm/test/CodeGen/AArch64/sve-fixed-length-bitreverse.ll (+94)
``````````diff
diff --git a/llvm/lib/Target/AArch64/AArch64ISelLowering.cpp b/llvm/lib/Target/AArch64/AArch64ISelLowering.cpp
index f5082b779d1db..78bbb8be2454b 100644
--- a/llvm/lib/Target/AArch64/AArch64ISelLowering.cpp
+++ b/llvm/lib/Target/AArch64/AArch64ISelLowering.cpp
@@ -1935,6 +1935,13 @@ AArch64TargetLowering::AArch64TargetLowering(const TargetMachine &TM,
setOperationAction(ISD::MUL, MVT::v1i64, Custom);
setOperationAction(ISD::MUL, MVT::v2i64, Custom);
+ // Neon doesn't have dedicated instructions for vectors of this size but SVE
+ // does.
+ for (auto VT :
+ {MVT::v4i16, MVT::v8i16, MVT::v2i32, MVT::v4i32, MVT::v2i64}) {
+ setOperationAction(ISD::BITREVERSE, VT, Custom);
+ }
+
// With SVE2 we can try lowering these to pairwise operations (e.g. smaxp).
if (Subtarget->hasSVE2() || Subtarget->isStreamingSVEAvailable()) {
setOperationAction(ISD::VECREDUCE_SMAX, MVT::v2i64, Custom);
@@ -11820,8 +11827,7 @@ SDValue AArch64TargetLowering::LowerBitreverse(SDValue Op,
EVT VT = Op.getValueType();
if (VT.isScalableVector() ||
- useSVEForFixedLengthVectorVT(
- VT, /*OverrideNEON=*/Subtarget->useSVEForFixedLengthVectors()))
+ useSVEForFixedLengthVectorVT(VT, /*OverrideNEON=*/true))
return LowerToPredicatedOp(Op, DAG, AArch64ISD::BITREVERSE_MERGE_PASSTHRU);
SDLoc DL(Op);
diff --git a/llvm/test/CodeGen/AArch64/sve-fixed-length-bitreverse.ll b/llvm/test/CodeGen/AArch64/sve-fixed-length-bitreverse.ll
new file mode 100644
index 0000000000000..e5308b2304509
--- /dev/null
+++ b/llvm/test/CodeGen/AArch64/sve-fixed-length-bitreverse.ll
@@ -0,0 +1,94 @@
+; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py UTC_ARGS: --version 6
+; RUN: llc -mtriple=aarch64-linux-gnu -mattr=+sve < %s | FileCheck %s -check-prefixes=CHECK-SVE
+
+; Do not use SVE, NEON has a dedicated instruction for fixed vector
+define <8 x i8> @test_v8i8(<8 x i8> %a) {
+; CHECK-SVE-LABEL: test_v8i8:
+; CHECK-SVE: // %bb.0:
+; CHECK-SVE-NEXT: rbit v0.8b, v0.8b
+; CHECK-SVE-NEXT: ret
+ %r = call <8 x i8> @llvm.bitreverse(<8 x i8> %a)
+ ret <8 x i8> %r
+}
+
+; Do not use SVE, NEON has a dedicated instruction for fixed vector
+define <16 x i8> @test_v16i8(<16 x i8> %a) {
+; CHECK-SVE-LABEL: test_v16i8:
+; CHECK-SVE: // %bb.0:
+; CHECK-SVE-NEXT: rbit v0.16b, v0.16b
+; CHECK-SVE-NEXT: ret
+ %r = call <16 x i8> @llvm.bitreverse(<16 x i8> %a)
+ ret <16 x i8> %r
+}
+
+define <4 x i16> @test_v4i16(<4 x i16> %a) {
+; CHECK-SVE-LABEL: test_v4i16:
+; CHECK-SVE: // %bb.0:
+; CHECK-SVE-NEXT: ptrue p0.h, vl4
+; CHECK-SVE-NEXT: // kill: def $d0 killed $d0 def $z0
+; CHECK-SVE-NEXT: rbit z0.h, p0/m, z0.h
+; CHECK-SVE-NEXT: // kill: def $d0 killed $d0 killed $z0
+; CHECK-SVE-NEXT: ret
+ %r = call <4 x i16> @llvm.bitreverse(<4 x i16> %a)
+ ret <4 x i16> %r
+}
+
+define <8 x i16> @test_v8i16(<8 x i16> %a) {
+; CHECK-SVE-LABEL: test_v8i16:
+; CHECK-SVE: // %bb.0:
+; CHECK-SVE-NEXT: ptrue p0.h, vl8
+; CHECK-SVE-NEXT: // kill: def $q0 killed $q0 def $z0
+; CHECK-SVE-NEXT: rbit z0.h, p0/m, z0.h
+; CHECK-SVE-NEXT: // kill: def $q0 killed $q0 killed $z0
+; CHECK-SVE-NEXT: ret
+ %r = call <8 x i16> @llvm.bitreverse(<8 x i16> %a)
+ ret <8 x i16> %r
+}
+
+define <2 x i32> @test_v2i32(<2 x i32> %a) {
+; CHECK-SVE-LABEL: test_v2i32:
+; CHECK-SVE: // %bb.0:
+; CHECK-SVE-NEXT: ptrue p0.s, vl2
+; CHECK-SVE-NEXT: // kill: def $d0 killed $d0 def $z0
+; CHECK-SVE-NEXT: rbit z0.s, p0/m, z0.s
+; CHECK-SVE-NEXT: // kill: def $d0 killed $d0 killed $z0
+; CHECK-SVE-NEXT: ret
+ %r = call <2 x i32> @llvm.bitreverse(<2 x i32> %a)
+ ret <2 x i32> %r
+}
+
+define <4 x i32> @test_v4i32(<4 x i32> %a) {
+; CHECK-SVE-LABEL: test_v4i32:
+; CHECK-SVE: // %bb.0:
+; CHECK-SVE-NEXT: ptrue p0.s, vl4
+; CHECK-SVE-NEXT: // kill: def $q0 killed $q0 def $z0
+; CHECK-SVE-NEXT: rbit z0.s, p0/m, z0.s
+; CHECK-SVE-NEXT: // kill: def $q0 killed $q0 killed $z0
+; CHECK-SVE-NEXT: ret
+ %r = call <4 x i32> @llvm.bitreverse(<4 x i32> %a)
+ ret <4 x i32> %r
+}
+
+define <1 x i64> @test_v1i64(<1 x i64> %a) {
+; CHECK-SVE-LABEL: test_v1i64:
+; CHECK-SVE: // %bb.0:
+; CHECK-SVE-NEXT: ptrue p0.d, vl1
+; CHECK-SVE-NEXT: // kill: def $d0 killed $d0 def $z0
+; CHECK-SVE-NEXT: rbit z0.d, p0/m, z0.d
+; CHECK-SVE-NEXT: // kill: def $d0 killed $d0 killed $z0
+; CHECK-SVE-NEXT: ret
+ %r = call <1 x i64> @llvm.bitreverse(<1 x i64> %a)
+ ret <1 x i64> %r
+}
+
+define <2 x i64> @test_v2i64(<2 x i64> %a) {
+; CHECK-SVE-LABEL: test_v2i64:
+; CHECK-SVE: // %bb.0:
+; CHECK-SVE-NEXT: ptrue p0.d, vl2
+; CHECK-SVE-NEXT: // kill: def $q0 killed $q0 def $z0
+; CHECK-SVE-NEXT: rbit z0.d, p0/m, z0.d
+; CHECK-SVE-NEXT: // kill: def $q0 killed $q0 killed $z0
+; CHECK-SVE-NEXT: ret
+ %r = call <2 x i64> @llvm.bitreverse(<2 x i64> %a)
+ ret <2 x i64> %r
+}
``````````
</details>
https://github.com/llvm/llvm-project/pull/196264
More information about the llvm-commits
mailing list