diff --git a/llvm/lib/Target/RISCV/RISCVISelLowering.cpp b/llvm/lib/Target/RISCV/RISCVISelLowering.cpp index c3071ad5cd697..f9b484b98739f 100644 --- a/llvm/lib/Target/RISCV/RISCVISelLowering.cpp +++ b/llvm/lib/Target/RISCV/RISCVISelLowering.cpp @@ -24844,8 +24844,7 @@ bool RISCVTargetLowering::isCtpopFast(EVT VT) const { return isTypeLegal(VT) && Subtarget.hasStdExtZvbb(); if (VT.isFixedLengthVector() && Subtarget.hasStdExtZvbb()) return true; - // FIXME: Should use hasCPOPLike here. - return Subtarget.hasStdExtZbb() && + return Subtarget.hasCPOPLike() && (VT == MVT::i32 || VT == MVT::i64 || VT.isFixedLengthVector()); } diff --git a/llvm/lib/Target/RISCV/RISCVTargetTransformInfo.cpp b/llvm/lib/Target/RISCV/RISCVTargetTransformInfo.cpp index 1ca513214f67c..a06faa414a2ef 100644 --- a/llvm/lib/Target/RISCV/RISCVTargetTransformInfo.cpp +++ b/llvm/lib/Target/RISCV/RISCVTargetTransformInfo.cpp @@ -289,9 +289,7 @@ bool RISCVTTIImpl::hasActiveVectorLength() const { TargetTransformInfo::PopcntSupportKind RISCVTTIImpl::getPopcntSupport(unsigned TyWidth) const { assert(isPowerOf2_32(TyWidth) && "Ty width must be power of 2"); - return ST->hasStdExtZbb() || (ST->hasVendorXCVbitmanip() && !ST->is64Bit()) - ? TTI::PSK_FastHardware - : TTI::PSK_Software; + return ST->hasCPOPLike() ? TTI::PSK_FastHardware : TTI::PSK_Software; } InstructionCost RISCVTTIImpl::getPartialReductionCost( diff --git a/llvm/test/CodeGen/RISCV/xcvbitmanip.ll b/llvm/test/CodeGen/RISCV/xcvbitmanip.ll index d25ff28475c4b..b2cebabb7df8b 100644 --- a/llvm/test/CodeGen/RISCV/xcvbitmanip.ll +++ b/llvm/test/CodeGen/RISCV/xcvbitmanip.ll @@ -229,3 +229,50 @@ define i32 @test.llvm.bitrev(i32 %a) { %1 = call i32 @llvm.bitreverse(i32 %a) ret i32 %1 } + +define i1 @ctpop_i32_ult_two(i32 signext %a) nounwind { +; CHECK-LABEL: ctpop_i32_ult_two: +; CHECK: # %bb.0: +; CHECK-NEXT: cv.cnt a0, a0 +; CHECK-NEXT: sltiu a0, a0, 2 +; CHECK-NEXT: ret + %1 = call i32 @llvm.ctpop.i32(i32 %a) + %2 = icmp ult i32 %1, 2 + ret i1 %2 +} + +define i1 @ctpop_i32_ugt_one(i32 signext %a) nounwind { +; CHECK-LABEL: ctpop_i32_ugt_one: +; CHECK: # %bb.0: +; CHECK-NEXT: cv.cnt a0, a0 +; CHECK-NEXT: sltiu a0, a0, 2 +; CHECK-NEXT: xori a0, a0, 1 +; CHECK-NEXT: ret + %1 = call i32 @llvm.ctpop.i32(i32 %a) + %2 = icmp ugt i32 %1, 1 + ret i1 %2 +} + +define i1 @ctpop_i32_eq_one(i32 signext %a) nounwind { +; CHECK-LABEL: ctpop_i32_eq_one: +; CHECK: # %bb.0: +; CHECK-NEXT: cv.cnt a0, a0 +; CHECK-NEXT: addi a0, a0, -1 +; CHECK-NEXT: seqz a0, a0 +; CHECK-NEXT: ret + %1 = call i32 @llvm.ctpop.i32(i32 %a) + %2 = icmp eq i32 %1, 1 + ret i1 %2 +} + +define i1 @ctpop_i32_ne_one(i32 signext %a) nounwind { +; CHECK-LABEL: ctpop_i32_ne_one: +; CHECK: # %bb.0: +; CHECK-NEXT: cv.cnt a0, a0 +; CHECK-NEXT: addi a0, a0, -1 +; CHECK-NEXT: snez a0, a0 +; CHECK-NEXT: ret + %1 = call i32 @llvm.ctpop.i32(i32 %a) + %2 = icmp ne i32 %1, 1 + ret i1 %2 +}