[llvm] [AArch64][CostModel] Model sve costs for ctpop (PR #192428)
via llvm-commits
llvm-commits at lists.llvm.org
Thu Apr 16 03:52:30 PDT 2026
llvmbot wrote:
<!--LLVM PR SUMMARY COMMENT-->
@llvm/pr-subscribers-backend-aarch64
@llvm/pr-subscribers-llvm-analysis
Author: Yashwant Singh (yashssh)
<details>
<summary>Changes</summary>
Targets supporting sve prefer sve for ctpop with fixed length vectors.
However, the cost model reports same costs for both neon and sve targets
https://godbolt.org/z/44hYhWPhx
---
Full diff: https://github.com/llvm/llvm-project/pull/192428.diff
2 Files Affected:
- (modified) llvm/lib/Target/AArch64/AArch64TargetTransformInfo.cpp (+26-3)
- (added) llvm/test/Analysis/CostModel/AArch64/ctpop-neon-sve.ll (+97)
``````````diff
diff --git a/llvm/lib/Target/AArch64/AArch64TargetTransformInfo.cpp b/llvm/lib/Target/AArch64/AArch64TargetTransformInfo.cpp
index 734339e5c7a05..0f940191c15b4 100644
--- a/llvm/lib/Target/AArch64/AArch64TargetTransformInfo.cpp
+++ b/llvm/lib/Target/AArch64/AArch64TargetTransformInfo.cpp
@@ -807,14 +807,37 @@ AArch64TTIImpl::getIntrinsicInstrCost(const IntrinsicCostAttributes &ICA,
{ISD::CTPOP, MVT::v4i32, 3},
{ISD::CTPOP, MVT::v8i16, 2},
{ISD::CTPOP, MVT::v16i8, 1},
- {ISD::CTPOP, MVT::i64, 4},
+ {ISD::CTPOP, MVT::i64, 4},
{ISD::CTPOP, MVT::v2i32, 3},
{ISD::CTPOP, MVT::v4i16, 2},
- {ISD::CTPOP, MVT::v8i8, 1},
- {ISD::CTPOP, MVT::i32, 5},
+ {ISD::CTPOP, MVT::v8i8, 1},
+ {ISD::CTPOP, MVT::i32, 5},
+ // SVE types (For targets that override NEON for fixed length vectors)
+ {ISD::CTPOP, MVT::nxv2i64, 2},
+ {ISD::CTPOP, MVT::nxv4i32, 2},
+ {ISD::CTPOP, MVT::nxv8i16, 1},
+ {ISD::CTPOP, MVT::nxv16i8, 1},
+ {ISD::CTPOP, MVT::nxv2i32, 2},
+ {ISD::CTPOP, MVT::nxv4i16, 2},
+ {ISD::CTPOP, MVT::nxv8i8, 1},
};
auto LT = getTypeLegalizationCost(RetTy);
MVT MTy = LT.second;
+
+ // When SVE is available, fixed-length vector ctpop is lowered using SVE
+ // (useSVEForFixedLengthVectorVT with OverrideNEON=true), so look up the
+ // scalable equivalent type for accurate costing.
+ if (ST->isSVEorStreamingSVEAvailable() && MTy.isFixedLengthVector()) {
+ EVT ScalableVT = MVT::getScalableVectorVT(
+ MTy.getVectorElementType(),
+ MTy.is128BitVector()
+ ? 128 / MTy.getVectorElementType().getSizeInBits()
+ : 64 / MTy.getVectorElementType().getSizeInBits());
+ if (const auto *Entry = CostTableLookup(CtpopCostTbl, ISD::CTPOP,
+ ScalableVT.getSimpleVT()))
+ return LT.first * Entry->Cost;
+ }
+
if (const auto *Entry = CostTableLookup(CtpopCostTbl, ISD::CTPOP, MTy)) {
// Extra cost of +1 when illegal vector types are legalized by promoting
// the integer type.
diff --git a/llvm/test/Analysis/CostModel/AArch64/ctpop-neon-sve.ll b/llvm/test/Analysis/CostModel/AArch64/ctpop-neon-sve.ll
new file mode 100644
index 0000000000000..bc62baea96d5f
--- /dev/null
+++ b/llvm/test/Analysis/CostModel/AArch64/ctpop-neon-sve.ll
@@ -0,0 +1,97 @@
+; NOTE: Assertions have been autogenerated by utils/update_analyze_test_checks.py
+; RUN: opt < %s -passes='print<cost-model>' -disable-output 2>&1 | FileCheck %s --check-prefix=NEON
+; RUN: opt < %s -passes='print<cost-model>' -disable-output -mattr=+sve 2>&1 | FileCheck %s --check-prefix=SVE
+
+target datalayout = "e-m:e-i8:8:32-i16:16:32-i64:64-i128:128-n32:64-S128-Fn32"
+target triple = "aarch64-unknown-linux-gnu"
+
+define <2 x i64> @test_ctpop_v2i64(<2 x i64> %a) {
+; NEON-LABEL: 'test_ctpop_v2i64'
+; NEON-NEXT: Cost Model: Found an estimated cost of 4 for instruction: %ctpop = call <2 x i64> @llvm.ctpop.v2i64(<2 x i64> %a)
+; NEON-NEXT: Cost Model: Found an estimated cost of 0 for instruction: ret <2 x i64> %ctpop
+;
+; SVE-LABEL: 'test_ctpop_v2i64'
+; SVE-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %ctpop = call <2 x i64> @llvm.ctpop.v2i64(<2 x i64> %a)
+; SVE-NEXT: Cost Model: Found an estimated cost of 0 for instruction: ret <2 x i64> %ctpop
+;
+ %ctpop = call <2 x i64> @llvm.ctpop.v2i64(<2 x i64> %a)
+ ret <2 x i64> %ctpop
+}
+
+define <4 x i32> @test_ctpop_v4i32(<4 x i32> %a) {
+; NEON-LABEL: 'test_ctpop_v4i32'
+; NEON-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %ctpop = call <4 x i32> @llvm.ctpop.v4i32(<4 x i32> %a)
+; NEON-NEXT: Cost Model: Found an estimated cost of 0 for instruction: ret <4 x i32> %ctpop
+;
+; SVE-LABEL: 'test_ctpop_v4i32'
+; SVE-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %ctpop = call <4 x i32> @llvm.ctpop.v4i32(<4 x i32> %a)
+; SVE-NEXT: Cost Model: Found an estimated cost of 0 for instruction: ret <4 x i32> %ctpop
+;
+ %ctpop = call <4 x i32> @llvm.ctpop.v4i32(<4 x i32> %a)
+ ret <4 x i32> %ctpop
+}
+
+define <8 x i16> @test_ctpop_v8i16(<8 x i16> %a) {
+; NEON-LABEL: 'test_ctpop_v8i16'
+; NEON-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %ctpop = call <8 x i16> @llvm.ctpop.v8i16(<8 x i16> %a)
+; NEON-NEXT: Cost Model: Found an estimated cost of 0 for instruction: ret <8 x i16> %ctpop
+;
+; SVE-LABEL: 'test_ctpop_v8i16'
+; SVE-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %ctpop = call <8 x i16> @llvm.ctpop.v8i16(<8 x i16> %a)
+; SVE-NEXT: Cost Model: Found an estimated cost of 0 for instruction: ret <8 x i16> %ctpop
+;
+ %ctpop = call <8 x i16> @llvm.ctpop.v8i16(<8 x i16> %a)
+ ret <8 x i16> %ctpop
+}
+
+define <16 x i8> @test_ctpop_v16i8(<16 x i8> %a) {
+; NEON-LABEL: 'test_ctpop_v16i8'
+; NEON-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %ctpop = call <16 x i8> @llvm.ctpop.v16i8(<16 x i8> %a)
+; NEON-NEXT: Cost Model: Found an estimated cost of 0 for instruction: ret <16 x i8> %ctpop
+;
+; SVE-LABEL: 'test_ctpop_v16i8'
+; SVE-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %ctpop = call <16 x i8> @llvm.ctpop.v16i8(<16 x i8> %a)
+; SVE-NEXT: Cost Model: Found an estimated cost of 0 for instruction: ret <16 x i8> %ctpop
+;
+ %ctpop = call <16 x i8> @llvm.ctpop.v16i8(<16 x i8> %a)
+ ret <16 x i8> %ctpop
+}
+
+define <2 x i32> @test_ctpop_v2i32(<2 x i32> %a) {
+; NEON-LABEL: 'test_ctpop_v2i32'
+; NEON-NEXT: Cost Model: Found an estimated cost of 3 for instruction: %ctpop = call <2 x i32> @llvm.ctpop.v2i32(<2 x i32> %a)
+; NEON-NEXT: Cost Model: Found an estimated cost of 0 for instruction: ret <2 x i32> %ctpop
+;
+; SVE-LABEL: 'test_ctpop_v2i32'
+; SVE-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %ctpop = call <2 x i32> @llvm.ctpop.v2i32(<2 x i32> %a)
+; SVE-NEXT: Cost Model: Found an estimated cost of 0 for instruction: ret <2 x i32> %ctpop
+;
+ %ctpop = call <2 x i32> @llvm.ctpop.v2i32(<2 x i32> %a)
+ ret <2 x i32> %ctpop
+}
+
+define <4 x i16> @test_ctpop_v4i16(<4 x i16> %a) {
+; NEON-LABEL: 'test_ctpop_v4i16'
+; NEON-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %ctpop = call <4 x i16> @llvm.ctpop.v4i16(<4 x i16> %a)
+; NEON-NEXT: Cost Model: Found an estimated cost of 0 for instruction: ret <4 x i16> %ctpop
+;
+; SVE-LABEL: 'test_ctpop_v4i16'
+; SVE-NEXT: Cost Model: Found an estimated cost of 2 for instruction: %ctpop = call <4 x i16> @llvm.ctpop.v4i16(<4 x i16> %a)
+; SVE-NEXT: Cost Model: Found an estimated cost of 0 for instruction: ret <4 x i16> %ctpop
+;
+ %ctpop = call <4 x i16> @llvm.ctpop.v4i16(<4 x i16> %a)
+ ret <4 x i16> %ctpop
+}
+
+define <8 x i8> @test_ctpop_v8i8(<8 x i8> %a) {
+; NEON-LABEL: 'test_ctpop_v8i8'
+; NEON-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %ctpop = call <8 x i8> @llvm.ctpop.v8i8(<8 x i8> %a)
+; NEON-NEXT: Cost Model: Found an estimated cost of 0 for instruction: ret <8 x i8> %ctpop
+;
+; SVE-LABEL: 'test_ctpop_v8i8'
+; SVE-NEXT: Cost Model: Found an estimated cost of 1 for instruction: %ctpop = call <8 x i8> @llvm.ctpop.v8i8(<8 x i8> %a)
+; SVE-NEXT: Cost Model: Found an estimated cost of 0 for instruction: ret <8 x i8> %ctpop
+;
+ %ctpop = call <8 x i8> @llvm.ctpop.v8i8(<8 x i8> %a)
+ ret <8 x i8> %ctpop
+}
``````````
</details>
https://github.com/llvm/llvm-project/pull/192428
More information about the llvm-commits
mailing list