diff --git a/llvm/lib/Target/AArch64/AArch64TargetTransformInfo.cpp b/llvm/lib/Target/AArch64/AArch64TargetTransformInfo.cpp --- a/llvm/lib/Target/AArch64/AArch64TargetTransformInfo.cpp +++ b/llvm/lib/Target/AArch64/AArch64TargetTransformInfo.cpp @@ -383,6 +383,10 @@ break; } case Intrinsic::ctpop: { + if (!ST->hasNEON()) { + // 32-bit or 64-bit ctpop without NEON is 12 instructions. + return getTypeLegalizationCost(RetTy).first * 12; + } static const CostTblEntry CtpopCostTbl[] = { {ISD::CTPOP, MVT::v2i64, 4}, {ISD::CTPOP, MVT::v4i32, 3}, diff --git a/llvm/test/Analysis/CostModel/AArch64/ctpop.ll b/llvm/test/Analysis/CostModel/AArch64/ctpop.ll --- a/llvm/test/Analysis/CostModel/AArch64/ctpop.ll +++ b/llvm/test/Analysis/CostModel/AArch64/ctpop.ll @@ -156,6 +156,22 @@ ret <32 x i8> %ctpop } +define i64 @test_ctpop_noneon_i64(i64 %a) "target-features"="-fp-armv8,-neon" { +; CHECK-LABEL: 'test_ctpop_noneon_i64' +; CHECK-NEXT: Cost Model: Found an estimated cost of 12 for instruction: %ctpop = call i64 @llvm.ctpop.i64(i64 %a) +; CHECK-NEXT: Cost Model: Found an estimated cost of 0 for instruction: ret i64 %ctpop + %ctpop = call i64 @llvm.ctpop.i64(i64 %a) + ret i64 %ctpop +} + +define <2 x i64> @test_ctpop_noneon_v2i64(<2 x i64> %a) "target-features"="-fp-armv8,-neon" { +; CHECK-LABEL: 'test_ctpop_noneon_v2i64' +; CHECK-NEXT: Cost Model: Found an estimated cost of 24 for instruction: %ctpop = call <2 x i64> @llvm.ctpop.v2i64(<2 x i64> %a) +; CHECK-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 +} + declare <2 x i64> @llvm.ctpop.v2i64(<2 x i64>) declare <2 x i32> @llvm.ctpop.v2i32(<2 x i32>) declare <4 x i32> @llvm.ctpop.v4i32(<4 x i32>)