diff --git a/clang/include/clang/Basic/BuiltinsRISCV.def b/clang/include/clang/Basic/BuiltinsRISCV.def index 1528b18c82ead..1df1c53733cfa 100644 --- a/clang/include/clang/Basic/BuiltinsRISCV.def +++ b/clang/include/clang/Basic/BuiltinsRISCV.def @@ -22,6 +22,8 @@ TARGET_BUILTIN(__builtin_riscv_clz_32, "UiUi", "nc", "zbb|xtheadbb") TARGET_BUILTIN(__builtin_riscv_clz_64, "UiUWi", "nc", "zbb|xtheadbb,64bit") TARGET_BUILTIN(__builtin_riscv_ctz_32, "UiUi", "nc", "zbb") TARGET_BUILTIN(__builtin_riscv_ctz_64, "UiUWi", "nc", "zbb,64bit") +TARGET_BUILTIN(__builtin_riscv_cpop_32, "UiUi", "nc", "zbb") +TARGET_BUILTIN(__builtin_riscv_cpop_64, "UiUWi", "nc", "zbb,64bit") // Zbc or Zbkc extension TARGET_BUILTIN(__builtin_riscv_clmul_32, "UiUiUi", "nc", "zbc|zbkc") diff --git a/clang/lib/CodeGen/CGBuiltin.cpp b/clang/lib/CodeGen/CGBuiltin.cpp index 5081062da2862..64210e76ed221 100644 --- a/clang/lib/CodeGen/CGBuiltin.cpp +++ b/clang/lib/CodeGen/CGBuiltin.cpp @@ -20696,6 +20696,8 @@ Value *CodeGenFunction::EmitRISCVBuiltinExpr(unsigned BuiltinID, case RISCV::BI__builtin_riscv_clz_64: case RISCV::BI__builtin_riscv_ctz_32: case RISCV::BI__builtin_riscv_ctz_64: + case RISCV::BI__builtin_riscv_cpop_32: + case RISCV::BI__builtin_riscv_cpop_64: case RISCV::BI__builtin_riscv_clmul_32: case RISCV::BI__builtin_riscv_clmul_64: case RISCV::BI__builtin_riscv_clmulh_32: @@ -20735,6 +20737,14 @@ Value *CodeGenFunction::EmitRISCVBuiltinExpr(unsigned BuiltinID, "cast"); return Result; } + case RISCV::BI__builtin_riscv_cpop_32: + case RISCV::BI__builtin_riscv_cpop_64: { + Value *Result = Builder.CreateUnaryIntrinsic(Intrinsic::ctpop, Ops[0]); + if (Result->getType() != ResultType) + Result = Builder.CreateIntCast(Result, ResultType, /*isSigned*/ true, + "cast"); + return Result; + } // Zbc case RISCV::BI__builtin_riscv_clmul_32: diff --git a/clang/test/CodeGen/RISCV/rvb-intrinsics/zbb.c b/clang/test/CodeGen/RISCV/rvb-intrinsics/zbb.c index 3a421f8c6cd42..a5715e330172b 100644 --- a/clang/test/CodeGen/RISCV/rvb-intrinsics/zbb.c +++ b/clang/test/CodeGen/RISCV/rvb-intrinsics/zbb.c @@ -82,3 +82,29 @@ unsigned int ctz_64(unsigned long a) { return __builtin_riscv_ctz_64(a); } #endif + +// RV32ZBB-LABEL: @cpop_32( +// RV32ZBB-NEXT: entry: +// RV32ZBB-NEXT: [[TMP0:%.*]] = call i32 @llvm.ctpop.i32(i32 [[A:%.*]]) +// RV32ZBB-NEXT: ret i32 [[TMP0]] +// +// RV64ZBB-LABEL: @cpop_32( +// RV64ZBB-NEXT: entry: +// RV64ZBB-NEXT: [[TMP0:%.*]] = call i32 @llvm.ctpop.i32(i32 [[A:%.*]]) +// RV64ZBB-NEXT: ret i32 [[TMP0]] +// +unsigned int cpop_32(unsigned int a) { + return __builtin_riscv_cpop_32(a); +} + +#if __riscv_xlen == 64 +// RV64ZBB-LABEL: @cpop_64( +// RV64ZBB-NEXT: entry: +// RV64ZBB-NEXT: [[TMP0:%.*]] = call i64 @llvm.ctpop.i64(i64 [[A:%.*]]) +// RV64ZBB-NEXT: [[CAST:%.*]] = trunc i64 [[TMP0]] to i32 +// RV64ZBB-NEXT: ret i32 [[CAST]] +// +unsigned int cpop_64(unsigned long a) { + return __builtin_riscv_cpop_64(a); +} +#endif