From b4024b5751077705debc87d3abe8b10164d4d5d8 Mon Sep 17 00:00:00 2001 From: Craig Topper Date: Thu, 11 Sep 2025 13:20:18 -0700 Subject: [PATCH] [RISCV] Add helper functions to detect CLZ/CTZ/CPOP-like support. --- llvm/lib/Target/RISCV/RISCVISelLowering.cpp | 16 ++++++++-------- llvm/lib/Target/RISCV/RISCVSubtarget.h | 11 +++++++++++ 2 files changed, 19 insertions(+), 8 deletions(-) diff --git a/llvm/lib/Target/RISCV/RISCVISelLowering.cpp b/llvm/lib/Target/RISCV/RISCVISelLowering.cpp index 037eec05e4301..4f137756d2f48 100644 --- a/llvm/lib/Target/RISCV/RISCVISelLowering.cpp +++ b/llvm/lib/Target/RISCV/RISCVISelLowering.cpp @@ -403,12 +403,14 @@ RISCVTargetLowering::RISCVTargetLowering(const TargetMachine &TM, Legal); } - if (Subtarget.hasStdExtZbb() || - (Subtarget.hasVendorXCVbitmanip() && !Subtarget.is64Bit())) { + if (Subtarget.hasCTZLike()) { if (Subtarget.is64Bit()) setOperationAction({ISD::CTTZ, ISD::CTTZ_ZERO_UNDEF}, MVT::i32, Custom); } else { setOperationAction(ISD::CTTZ, XLenVT, Expand); + } + + if (!Subtarget.hasCPOPLike()) { // TODO: These should be set to LibCall, but this currently breaks // the Linux kernel build. See #101786. Lacks i128 tests, too. if (Subtarget.is64Bit()) @@ -418,8 +420,7 @@ RISCVTargetLowering::RISCVTargetLowering(const TargetMachine &TM, setOperationAction(ISD::CTPOP, MVT::i64, Expand); } - if (Subtarget.hasStdExtZbb() || Subtarget.hasVendorXTHeadBb() || - (Subtarget.hasVendorXCVbitmanip() && !Subtarget.is64Bit())) { + if (Subtarget.hasCLZLike()) { // We need the custom lowering to make sure that the resulting sequence // for the 32bit case is efficient on 64bit targets. // Use default promotion for i32 without Zbb. @@ -2158,13 +2159,11 @@ bool RISCVTargetLowering::signExtendConstant(const ConstantInt *CI) const { } bool RISCVTargetLowering::isCheapToSpeculateCttz(Type *Ty) const { - return Subtarget.hasStdExtZbb() || - (Subtarget.hasVendorXCVbitmanip() && !Subtarget.is64Bit()); + return Subtarget.hasCTZLike(); } bool RISCVTargetLowering::isCheapToSpeculateCtlz(Type *Ty) const { - return Subtarget.hasStdExtZbb() || Subtarget.hasVendorXTHeadBb() || - (Subtarget.hasVendorXCVbitmanip() && !Subtarget.is64Bit()); + return Subtarget.hasCLZLike(); } bool RISCVTargetLowering::isMaskAndCmp0FoldingBeneficial( @@ -24843,6 +24842,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() && (VT == MVT::i32 || VT == MVT::i64 || VT.isFixedLengthVector()); } diff --git a/llvm/lib/Target/RISCV/RISCVSubtarget.h b/llvm/lib/Target/RISCV/RISCVSubtarget.h index 50e76df56e575..0d9cd16a77937 100644 --- a/llvm/lib/Target/RISCV/RISCVSubtarget.h +++ b/llvm/lib/Target/RISCV/RISCVSubtarget.h @@ -186,6 +186,17 @@ class RISCVSubtarget : public RISCVGenSubtargetInfo { return HasStdExtZfhmin || HasStdExtZfbfmin; } + bool hasCLZLike() const { + return HasStdExtZbb || HasVendorXTHeadBb || + (HasVendorXCVbitmanip && !IsRV64); + } + bool hasCTZLike() const { + return HasStdExtZbb || (HasVendorXCVbitmanip && !IsRV64); + } + bool hasCPOPLike() const { + return HasStdExtZbb || (HasVendorXCVbitmanip && !IsRV64); + } + bool hasBEXTILike() const { return HasStdExtZbs || HasVendorXTHeadBs; } bool hasCZEROLike() const {