Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Clang][RISCV] Add missing support for __builtin_riscv_cpop_32/64 #76256

Closed
wants to merge 1 commit into from

Conversation

dtcxzyw
Copy link
Member

@dtcxzyw dtcxzyw commented Dec 22, 2023

This patch adds support for __builtin_riscv_cpop_32/64, which are used by riscv_bitmanip.h.
See also

static __inline__ unsigned __attribute__((__always_inline__, __nodebug__))
__riscv_cpop_32(uint32_t __x) {
return __builtin_riscv_cpop_32(__x);
}
#if __riscv_xlen == 64
static __inline__ uint64_t __attribute__((__always_inline__, __nodebug__))
__riscv_orc_b_64(uint64_t __x) {
return __builtin_riscv_orc_b_64(__x);
}
static __inline__ unsigned __attribute__((__always_inline__, __nodebug__))
__riscv_clz_64(uint64_t __x) {
return __builtin_riscv_clz_64(__x);
}
static __inline__ unsigned __attribute__((__always_inline__, __nodebug__))
__riscv_ctz_64(uint64_t __x) {
return __builtin_riscv_ctz_64(__x);
}
static __inline__ unsigned __attribute__((__always_inline__, __nodebug__))
__riscv_cpop_64(uint64_t __x) {
return __builtin_riscv_cpop_64(__x);
}
#endif
.
Thank @Liaoshihua for reporting this!

@llvmbot llvmbot added clang Clang issues not falling into any other category backend:RISC-V clang:frontend Language frontend issues, e.g. anything involving "Sema" clang:codegen labels Dec 22, 2023
@llvmbot
Copy link
Collaborator

llvmbot commented Dec 22, 2023

@llvm/pr-subscribers-clang
@llvm/pr-subscribers-clang-codegen

@llvm/pr-subscribers-backend-risc-v

Author: Yingwei Zheng (dtcxzyw)

Changes

This patch adds support for __builtin_riscv_cpop_32/64, which are used by riscv_bitmanip.h.
See also

static __inline__ unsigned __attribute__((__always_inline__, __nodebug__))
__riscv_cpop_32(uint32_t __x) {
return __builtin_riscv_cpop_32(__x);
}
#if __riscv_xlen == 64
static __inline__ uint64_t __attribute__((__always_inline__, __nodebug__))
__riscv_orc_b_64(uint64_t __x) {
return __builtin_riscv_orc_b_64(__x);
}
static __inline__ unsigned __attribute__((__always_inline__, __nodebug__))
__riscv_clz_64(uint64_t __x) {
return __builtin_riscv_clz_64(__x);
}
static __inline__ unsigned __attribute__((__always_inline__, __nodebug__))
__riscv_ctz_64(uint64_t __x) {
return __builtin_riscv_ctz_64(__x);
}
static __inline__ unsigned __attribute__((__always_inline__, __nodebug__))
__riscv_cpop_64(uint64_t __x) {
return __builtin_riscv_cpop_64(__x);
}
#endif
.
Thank @Liaoshihua for reporting this!


Full diff: https://github.com/llvm/llvm-project/pull/76256.diff

3 Files Affected:

  • (modified) clang/include/clang/Basic/BuiltinsRISCV.def (+2)
  • (modified) clang/lib/CodeGen/CGBuiltin.cpp (+10)
  • (modified) clang/test/CodeGen/RISCV/rvb-intrinsics/zbb.c (+26)
diff --git a/clang/include/clang/Basic/BuiltinsRISCV.def b/clang/include/clang/Basic/BuiltinsRISCV.def
index 1528b18c82eade..1df1c53733cfa1 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 5081062da2862e..64210e76ed2218 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 3a421f8c6cd421..a5715e330172bd 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

@topperc
Copy link
Collaborator

topperc commented Dec 23, 2023

Can we just use __builtin_popcount and __builtin_popcountll directly in the header file?

// RV64ZBB-NEXT: [[TMP0:%.*]] = call i32 @llvm.ctpop.i32(i32 [[A:%.*]])
// RV64ZBB-NEXT: ret i32 [[TMP0]]
//
unsigned int cpop_32(unsigned int a) {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Use uint32_t and uint64_t. I already updated some of the tests to use those types but I somehow missed this one.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This should also be using the intrinsic from riscv_bitmanip.h

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
backend:RISC-V clang:codegen clang:frontend Language frontend issues, e.g. anything involving "Sema" clang Clang issues not falling into any other category
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

3 participants