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

[RISCV][Clang] Added builtin support for experimental Zimop extension #79971

Open
wants to merge 6 commits into
base: main
Choose a base branch
from

Conversation

JivanH
Copy link
Contributor

@JivanH JivanH commented Jan 30, 2024

This change adds builtin of mop.r.[n] and mop.rr.[n] instructions for Zimop extension based on https://github.com/riscv-non-isa/riscv-c-api-doc/blob/master/riscv-c-api.md.

This change adds builtin of mop.r.[n] and mop.rr.[n] instructions for Zimop extension based on https://github.com/riscv-non-isa/riscv-c-api-doc/blob/master/riscv-c-api.md.
@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 Jan 30, 2024
@llvmbot
Copy link
Collaborator

llvmbot commented Jan 30, 2024

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

@llvm/pr-subscribers-clang-codegen

Author: Jivan Hakobyan (JivanH)

Changes

This change adds builtin of mop.r.[n] and mop.rr.[n] instructions for Zimop extension based on https://github.com/riscv-non-isa/riscv-c-api-doc/blob/master/riscv-c-api.md.


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

4 Files Affected:

  • (modified) clang/include/clang/Basic/BuiltinsRISCV.def (+7)
  • (modified) clang/lib/CodeGen/CGBuiltin.cpp (+14)
  • (modified) clang/lib/Sema/SemaChecking.cpp (+8)
  • (added) clang/test/CodeGen/RISCV/rvb-intrinsics/zimop.c (+105)
diff --git a/clang/include/clang/Basic/BuiltinsRISCV.def b/clang/include/clang/Basic/BuiltinsRISCV.def
index 1528b18c82ead..7e2dda21830c5 100644
--- a/clang/include/clang/Basic/BuiltinsRISCV.def
+++ b/clang/include/clang/Basic/BuiltinsRISCV.def
@@ -89,5 +89,12 @@ TARGET_BUILTIN(__builtin_riscv_sm3p1, "UiUi", "nc", "zksh")
 TARGET_BUILTIN(__builtin_riscv_ntl_load, "v.", "t", "zihintntl")
 TARGET_BUILTIN(__builtin_riscv_ntl_store, "v.", "t", "zihintntl")
 
+// Zimop extension
+TARGET_BUILTIN(__builtin_riscv_mopr_32, "UiUiUi", "nc", "experimental-zimop")
+TARGET_BUILTIN(__builtin_riscv_mopr_64, "UWiUWiUWi", "nc",
+                                        "experimental-zimop,64bit")
+TARGET_BUILTIN(__builtin_riscv_moprr_32, "UiUiUiUi", "nc", "experimental-zimop")
+TARGET_BUILTIN(__builtin_riscv_moprr_64, "UWiUWiUWiUWi", "nc",
+                                         "experimental-zimop,64bit")
 #undef BUILTIN
 #undef TARGET_BUILTIN
diff --git a/clang/lib/CodeGen/CGBuiltin.cpp b/clang/lib/CodeGen/CGBuiltin.cpp
index f3ab5ad7b08ec..28511f9e0beac 100644
--- a/clang/lib/CodeGen/CGBuiltin.cpp
+++ b/clang/lib/CodeGen/CGBuiltin.cpp
@@ -21189,6 +21189,10 @@ Value *CodeGenFunction::EmitRISCVBuiltinExpr(unsigned BuiltinID,
   case RISCV::BI__builtin_riscv_clmulh_64:
   case RISCV::BI__builtin_riscv_clmulr_32:
   case RISCV::BI__builtin_riscv_clmulr_64:
+  case RISCV::BI__builtin_riscv_mopr_32:
+  case RISCV::BI__builtin_riscv_mopr_64:
+  case RISCV::BI__builtin_riscv_moprr_32:
+  case RISCV::BI__builtin_riscv_moprr_64:
   case RISCV::BI__builtin_riscv_xperm4_32:
   case RISCV::BI__builtin_riscv_xperm4_64:
   case RISCV::BI__builtin_riscv_xperm8_32:
@@ -21237,6 +21241,16 @@ Value *CodeGenFunction::EmitRISCVBuiltinExpr(unsigned BuiltinID,
       ID = Intrinsic::riscv_clmulr;
       break;
 
+    // Zimop
+    case RISCV::BI__builtin_riscv_mopr_32:
+    case RISCV::BI__builtin_riscv_mopr_64:
+      ID = Intrinsic::riscv_mopr;
+      break;
+    case RISCV::BI__builtin_riscv_moprr_32:
+    case RISCV::BI__builtin_riscv_moprr_64:
+      ID = Intrinsic::riscv_moprr;
+      break;
+
     // Zbkx
     case RISCV::BI__builtin_riscv_xperm8_32:
     case RISCV::BI__builtin_riscv_xperm8_64:
diff --git a/clang/lib/Sema/SemaChecking.cpp b/clang/lib/Sema/SemaChecking.cpp
index 502b24bcdf8b4..c2702bec29dd7 100644
--- a/clang/lib/Sema/SemaChecking.cpp
+++ b/clang/lib/Sema/SemaChecking.cpp
@@ -5588,6 +5588,14 @@ bool Sema::CheckRISCVBuiltinFunctionCall(const TargetInfo &TI,
   // Check if rnum is in [0, 10]
   case RISCV::BI__builtin_riscv_aes64ks1i:
     return SemaBuiltinConstantArgRange(TheCall, 1, 0, 10);
+  // Check if n of mop.r.[n] is in [0, 31]
+  case RISCV::BI__builtin_riscv_mopr_32:
+  case RISCV::BI__builtin_riscv_mopr_64:
+    return SemaBuiltinConstantArgRange(TheCall, 1, 0, 31);
+  // Check if n of mop.rr.[n] is in [0, 7]
+  case RISCV::BI__builtin_riscv_moprr_32:
+  case RISCV::BI__builtin_riscv_moprr_64:
+    return SemaBuiltinConstantArgRange(TheCall, 2, 0, 7);
   // Check if value range for vxrm is in [0, 3]
   case RISCVVector::BI__builtin_rvv_vaaddu_vv:
   case RISCVVector::BI__builtin_rvv_vaaddu_vx:
diff --git a/clang/test/CodeGen/RISCV/rvb-intrinsics/zimop.c b/clang/test/CodeGen/RISCV/rvb-intrinsics/zimop.c
new file mode 100644
index 0000000000000..b4367e33bdc19
--- /dev/null
+++ b/clang/test/CodeGen/RISCV/rvb-intrinsics/zimop.c
@@ -0,0 +1,105 @@
+// NOTE: Assertions have been autogenerated by utils/update_cc_test_checks.py
+// RUN: %clang_cc1 -triple riscv32 -target-feature +experimental-zimop -emit-llvm %s -o - \
+// RUN:     -disable-O0-optnone | opt -S -passes=mem2reg \
+// RUN:     | FileCheck %s  -check-prefix=RV32ZIMOP
+// RUN: %clang_cc1 -triple riscv64 -target-feature +experimental-zimop -emit-llvm %s -o - \
+// RUN:     -disable-O0-optnone | opt -S -passes=mem2reg \
+// RUN:     | FileCheck %s  -check-prefix=RV64ZIMOP
+
+#include <stdint.h>
+
+#if __riscv_xlen == 64
+// RV64ZIMOP-LABEL: @mopr_0_64(
+// RV64ZIMOP-NEXT:  entry:
+// RV64ZIMOP-NEXT:    [[TMP0:%.*]] = call i64 @llvm.riscv.mopr.i64(i64 [[A:%.*]], i64 0)
+// RV64ZIMOP-NEXT:    ret i64 [[TMP0]]
+//
+uint64_t mopr_0_64(uint64_t a) {
+  return __builtin_riscv_mopr_64(a, 0);
+}
+
+// RV64ZIMOP-LABEL: @mopr_31_64(
+// RV64ZIMOP-NEXT:  entry:
+// RV64ZIMOP-NEXT:    [[TMP0:%.*]] = call i64 @llvm.riscv.mopr.i64(i64 [[A:%.*]], i64 31)
+// RV64ZIMOP-NEXT:    ret i64 [[TMP0]]
+//
+uint64_t mopr_31_64(uint64_t a) {
+  return __builtin_riscv_mopr_64(a, 31);
+}
+
+// RV64ZIMOP-LABEL: @moprr_0_64(
+// RV64ZIMOP-NEXT:  entry:
+// RV64ZIMOP-NEXT:    [[TMP0:%.*]] = call i64 @llvm.riscv.moprr.i64(i64 [[A:%.*]], i64 [[B:%.*]], i64 0)
+// RV64ZIMOP-NEXT:    ret i64 [[TMP0]]
+//
+uint64_t moprr_0_64(uint64_t a, uint64_t b) {
+  return __builtin_riscv_moprr_64(a, b, 0);
+}
+
+// RV64ZIMOP-LABEL: @moprr_7_64(
+// RV64ZIMOP-NEXT:  entry:
+// RV64ZIMOP-NEXT:    [[TMP0:%.*]] = call i64 @llvm.riscv.moprr.i64(i64 [[A:%.*]], i64 [[B:%.*]], i64 7)
+// RV64ZIMOP-NEXT:    ret i64 [[TMP0]]
+//
+uint64_t moprr_7_64(uint64_t a, uint64_t b) {
+  return __builtin_riscv_moprr_64(a, b, 7);
+}
+
+#endif
+
+// RV32ZIMOP-LABEL: @mopr_0_32(
+// RV32ZIMOP-NEXT:  entry:
+// RV32ZIMOP-NEXT:    [[TMP0:%.*]] = call i32 @llvm.riscv.mopr.i32(i32 [[A:%.*]], i32 0)
+// RV32ZIMOP-NEXT:    ret i32 [[TMP0]]
+//
+// RV64ZIMOP-LABEL: @mopr_0_32(
+// RV64ZIMOP-NEXT:  entry:
+// RV64ZIMOP-NEXT:    [[TMP0:%.*]] = call i32 @llvm.riscv.mopr.i32(i32 [[A:%.*]], i32 0)
+// RV64ZIMOP-NEXT:    ret i32 [[TMP0]]
+//
+uint32_t mopr_0_32(uint32_t a) {
+  return __builtin_riscv_mopr_32(a, 0);
+}
+
+// RV32ZIMOP-LABEL: @mopr_31_32(
+// RV32ZIMOP-NEXT:  entry:
+// RV32ZIMOP-NEXT:    [[TMP0:%.*]] = call i32 @llvm.riscv.mopr.i32(i32 [[A:%.*]], i32 31)
+// RV32ZIMOP-NEXT:    ret i32 [[TMP0]]
+//
+// RV64ZIMOP-LABEL: @mopr_31_32(
+// RV64ZIMOP-NEXT:  entry:
+// RV64ZIMOP-NEXT:    [[TMP0:%.*]] = call i32 @llvm.riscv.mopr.i32(i32 [[A:%.*]], i32 31)
+// RV64ZIMOP-NEXT:    ret i32 [[TMP0]]
+//
+uint32_t mopr_31_32(uint32_t a) {
+  return __builtin_riscv_mopr_32(a, 31);
+}
+
+// RV32ZIMOP-LABEL: @moprr_0_32(
+// RV32ZIMOP-NEXT:  entry:
+// RV32ZIMOP-NEXT:    [[TMP0:%.*]] = call i32 @llvm.riscv.moprr.i32(i32 [[A:%.*]], i32 [[B:%.*]], i32 0)
+// RV32ZIMOP-NEXT:    ret i32 [[TMP0]]
+//
+// RV64ZIMOP-LABEL: @moprr_0_32(
+// RV64ZIMOP-NEXT:  entry:
+// RV64ZIMOP-NEXT:    [[TMP0:%.*]] = call i32 @llvm.riscv.moprr.i32(i32 [[A:%.*]], i32 [[B:%.*]], i32 0)
+// RV64ZIMOP-NEXT:    ret i32 [[TMP0]]
+//
+uint32_t moprr_0_32(uint32_t a, uint32_t b) {
+  return __builtin_riscv_moprr_32(a, b, 0);
+}
+
+// RV32ZIMOP-LABEL: @moprr_7_32(
+// RV32ZIMOP-NEXT:  entry:
+// RV32ZIMOP-NEXT:    [[TMP0:%.*]] = call i32 @llvm.riscv.moprr.i32(i32 [[A:%.*]], i32 [[B:%.*]], i32 7)
+// RV32ZIMOP-NEXT:    ret i32 [[TMP0]]
+//
+// RV64ZIMOP-LABEL: @moprr_7_32(
+// RV64ZIMOP-NEXT:  entry:
+// RV64ZIMOP-NEXT:    [[TMP0:%.*]] = call i32 @llvm.riscv.moprr.i32(i32 [[A:%.*]], i32 [[B:%.*]], i32 7)
+// RV64ZIMOP-NEXT:    ret i32 [[TMP0]]
+//
+uint32_t moprr_7_32(uint32_t a, uint32_t b) {
+  return __builtin_riscv_moprr_32(a, b, 7);
+}
+

@JivanH
Copy link
Contributor Author

JivanH commented Jan 30, 2024

Please review
@topperc
@wangpc-pp
@dtcxzyw

@@ -21189,6 +21189,10 @@ Value *CodeGenFunction::EmitRISCVBuiltinExpr(unsigned BuiltinID,
case RISCV::BI__builtin_riscv_clmulh_64:
case RISCV::BI__builtin_riscv_clmulr_32:
case RISCV::BI__builtin_riscv_clmulr_64:
case RISCV::BI__builtin_riscv_mopr_32:
Copy link
Contributor

Choose a reason for hiding this comment

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

I think put mop between zb* builtins is not a good ideal.

Copy link
Contributor

Choose a reason for hiding this comment

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

Changed

@@ -89,5 +89,13 @@ TARGET_BUILTIN(__builtin_riscv_sm3p1, "UiUi", "nc", "zksh")
TARGET_BUILTIN(__builtin_riscv_ntl_load, "v.", "t", "zihintntl")
TARGET_BUILTIN(__builtin_riscv_ntl_store, "v.", "t", "zihintntl")

// Zimop extension
TARGET_BUILTIN(__builtin_riscv_mopr_32, "UiUiUi", "nc", "experimental-zimop")
Copy link
Collaborator

Choose a reason for hiding this comment

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

The last argument should include 'I' to indicate it needs to be a compile time constant. See __builtin_riscv_sm4ed for example.

Copy link
Contributor

Choose a reason for hiding this comment

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

Added

@JivanH
Copy link
Contributor Author

JivanH commented Mar 5, 2024

@topperc
@wangpc-pp
@dtcxzyw

REMIND:

Hi. Could you please review my patch?

@@ -89,5 +89,13 @@ TARGET_BUILTIN(__builtin_riscv_sm3p1, "UiUi", "nc", "zksh")
TARGET_BUILTIN(__builtin_riscv_ntl_load, "v.", "t", "zihintntl")
TARGET_BUILTIN(__builtin_riscv_ntl_store, "v.", "t", "zihintntl")

// Zimop extension
Copy link
Contributor

Choose a reason for hiding this comment

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

You may need to rebase as I have rewritten this file in TableGen.

Copy link
Contributor

Choose a reason for hiding this comment

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

Rebased

clang/lib/Sema/SemaChecking.cpp Show resolved Hide resolved
Copy link
Contributor

@wangpc-pp wangpc-pp left a comment

Choose a reason for hiding this comment

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

The code is OK I think.
One question: how will these builtins be used? Are their semantics bound to specific extensions that extend MOPs?

@jrtc27
Copy link
Collaborator

jrtc27 commented Mar 7, 2024

Surely we should instead be defining intrinsics with actual names for the operations we know about? What's the actual use case for needing an arbitrary unnamed one?

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

7 participants