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] Implement Clang Builtins for XCVmac Extension in CV32E40P #110623

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

Conversation

realqhc
Copy link
Contributor

@realqhc realqhc commented Oct 1, 2024

This commit adds the Clang Builtins, C API header and relevant tests for XCVmac extension.

Spec:
https://github.com/openhwgroup/core-v-sw/blob/master/specifications/corev-builtin-spec.md

Contributor: @PaoloS02

This commit adds the Clang Builtins, C API header and relevant tests for
XCVmac extension.

Spec:
https://github.com/openhwgroup/core-v-sw/blob/master/specifications/corev-builtin-spec.md

Contributor: @PaoloS02
@realqhc realqhc requested review from jrtc27 and topperc October 1, 2024 02:16
@realqhc realqhc self-assigned this Oct 1, 2024
@llvmbot llvmbot added clang Clang issues not falling into any other category backend:RISC-V backend:X86 clang:frontend Language frontend issues, e.g. anything involving "Sema" clang:headers Headers provided by Clang, e.g. for intrinsics clang:codegen labels Oct 1, 2024
@llvmbot
Copy link

llvmbot commented Oct 1, 2024

@llvm/pr-subscribers-clang

@llvm/pr-subscribers-backend-x86

Author: None (realqhc)

Changes

This commit adds the Clang Builtins, C API header and relevant tests for XCVmac extension.

Spec:
https://github.com/openhwgroup/core-v-sw/blob/master/specifications/corev-builtin-spec.md

Contributor: @PaoloS02


Patch is 45.71 KiB, truncated to 20.00 KiB below, full version: https://github.com/llvm/llvm-project/pull/110623.diff

6 Files Affected:

  • (modified) clang/include/clang/Basic/BuiltinsRISCVXCV.td (+55-17)
  • (modified) clang/lib/CodeGen/CGBuiltin.cpp (+55)
  • (modified) clang/lib/Headers/CMakeLists.txt (+1)
  • (added) clang/lib/Headers/riscv_corev_mac.h (+109)
  • (added) clang/test/CodeGen/RISCV/riscv-xcvmac-c-api.c (+343)
  • (added) clang/test/CodeGen/RISCV/riscv-xcvmac.c (+309)
diff --git a/clang/include/clang/Basic/BuiltinsRISCVXCV.td b/clang/include/clang/Basic/BuiltinsRISCVXCV.td
index 06ce07ade5c122..4c813ecf3d33d3 100644
--- a/clang/include/clang/Basic/BuiltinsRISCVXCV.td
+++ b/clang/include/clang/Basic/BuiltinsRISCVXCV.td
@@ -11,7 +11,7 @@
 //
 //===----------------------------------------------------------------------===//
 
-class RISCXCVBuiltin<string prototype, string features = ""> : TargetBuiltin {
+class RISCVXCVBuiltin<string prototype, string features = ""> : TargetBuiltin {
   let Spellings = ["__builtin_riscv_cv_" # NAME];
   let Prototype = prototype;
   let Features = features;
@@ -21,21 +21,59 @@ let Attributes = [NoThrow, Const] in {
 //===----------------------------------------------------------------------===//
 // XCValu extension.
 //===----------------------------------------------------------------------===//
-def alu_slet  : RISCXCVBuiltin<"int(int, int)", "xcvalu">;
-def alu_sletu : RISCXCVBuiltin<"int(unsigned int, unsigned int)", "xcvalu">;
-def alu_exths : RISCXCVBuiltin<"int(int)", "xcvalu">;
-def alu_exthz : RISCXCVBuiltin<"unsigned int(unsigned int)", "xcvalu">;
-def alu_extbs : RISCXCVBuiltin<"int(int)", "xcvalu">;
-def alu_extbz : RISCXCVBuiltin<"unsigned int(unsigned int)", "xcvalu">;
+def alu_slet  : RISCVXCVBuiltin<"int(int, int)", "xcvalu">;
+def alu_sletu : RISCVXCVBuiltin<"int(unsigned int, unsigned int)", "xcvalu">;
+def alu_exths : RISCVXCVBuiltin<"int(int)", "xcvalu">;
+def alu_exthz : RISCVXCVBuiltin<"unsigned int(unsigned int)", "xcvalu">;
+def alu_extbs : RISCVXCVBuiltin<"int(int)", "xcvalu">;
+def alu_extbz : RISCVXCVBuiltin<"unsigned int(unsigned int)", "xcvalu">;
 
-def alu_clip   : RISCXCVBuiltin<"int(int, int)", "xcvalu">;
-def alu_clipu  : RISCXCVBuiltin<"unsigned int(unsigned int, unsigned int)", "xcvalu">;
-def alu_addN   : RISCXCVBuiltin<"int(int, int, unsigned int)", "xcvalu">;
-def alu_adduN  : RISCXCVBuiltin<"unsigned int(unsigned int, unsigned int, unsigned int)", "xcvalu">;
-def alu_addRN  : RISCXCVBuiltin<"int(int, int, unsigned int)", "xcvalu">;
-def alu_adduRN : RISCXCVBuiltin<"unsigned int(unsigned int, unsigned int, unsigned int)", "xcvalu">;
-def alu_subN   : RISCXCVBuiltin<"int(int, int, unsigned int)", "xcvalu">;
-def alu_subuN  : RISCXCVBuiltin<"unsigned int(unsigned int, unsigned int, unsigned int)", "xcvalu">;
-def alu_subRN  : RISCXCVBuiltin<"int(int, int, unsigned int)", "xcvalu">;
-def alu_subuRN : RISCXCVBuiltin<"unsigned int(unsigned int, unsigned int, unsigned int)", "xcvalu">;
+def alu_clip   : RISCVXCVBuiltin<"int(int, int)", "xcvalu">;
+def alu_clipu  : RISCVXCVBuiltin<"unsigned int(unsigned int, unsigned int)", "xcvalu">;
+def alu_addN   : RISCVXCVBuiltin<"int(int, int, unsigned int)", "xcvalu">;
+def alu_adduN  : RISCVXCVBuiltin<"unsigned int(unsigned int, unsigned int, unsigned int)", "xcvalu">;
+def alu_addRN  : RISCVXCVBuiltin<"int(int, int, unsigned int)", "xcvalu">;
+def alu_adduRN : RISCVXCVBuiltin<"unsigned int(unsigned int, unsigned int, unsigned int)", "xcvalu">;
+def alu_subN   : RISCVXCVBuiltin<"int(int, int, unsigned int)", "xcvalu">;
+def alu_subuN  : RISCVXCVBuiltin<"unsigned int(unsigned int, unsigned int, unsigned int)", "xcvalu">;
+def alu_subRN  : RISCVXCVBuiltin<"int(int, int, unsigned int)", "xcvalu">;
+def alu_subuRN : RISCVXCVBuiltin<"unsigned int(unsigned int, unsigned int, unsigned int)", "xcvalu">;
+
+//===----------------------------------------------------------------------===//
+// XCVmac extension.
+//===----------------------------------------------------------------------===//
+def mac_mac      : RISCVXCVBuiltin<"int(int, int, int)", "xcvmac">;
+def mac_msu      : RISCVXCVBuiltin<"int(int, int, int)", "xcvmac">;
+def mac_muluN    : RISCVXCVBuiltin<"unsigned int(unsigned int, unsigned int, unsigned int)",
+                                   "xcvmac">;
+def mac_mulhhuN  : RISCVXCVBuiltin<"unsigned int(unsigned int, unsigned int, unsigned int)",
+                                   "xcvmac">;
+def mac_mulsN    : RISCVXCVBuiltin<"int(unsigned int, unsigned int, unsigned int)",
+                                   "xcvmac">;
+def mac_mulhhsN  : RISCVXCVBuiltin<"int(unsigned int, unsigned int, unsigned int)",
+                                   "xcvmac">;
+def mac_muluRN   : RISCVXCVBuiltin<"unsigned int(unsigned int, unsigned int, unsigned int)",
+                                   "xcvmac">;
+def mac_mulhhuRN : RISCVXCVBuiltin<"unsigned int(unsigned int, unsigned int, unsigned int)",
+                                   "xcvmac">;
+def mac_mulsRN   : RISCVXCVBuiltin<"int(unsigned int, unsigned int, unsigned int)",
+                                   "xcvmac">;
+def mac_mulhhsRN : RISCVXCVBuiltin<"int(unsigned int, unsigned int, unsigned int)",
+                                   "xcvmac">;
+def mac_macuN    : RISCVXCVBuiltin<"unsigned int(unsigned int, unsigned int, unsigned int, unsigned int)",
+                                   "xcvmac">;
+def mac_machhuN  : RISCVXCVBuiltin<"unsigned int(unsigned int, unsigned int, unsigned int, unsigned int)",
+                                   "xcvmac">;
+def mac_macsN    : RISCVXCVBuiltin<"int(unsigned int, unsigned int, unsigned int, unsigned int)",
+                                   "xcvmac">;
+def mac_machhsN  : RISCVXCVBuiltin<"int(unsigned int, unsigned int, unsigned int, unsigned int)",
+                                   "xcvmac">;
+def mac_macuRN   : RISCVXCVBuiltin<"unsigned int(unsigned int, unsigned int, unsigned int, unsigned int)",
+                                    "xcvmac">;
+def mac_machhuRN : RISCVXCVBuiltin<"unsigned int(unsigned int, unsigned int, unsigned int, unsigned int)",
+                                   "xcvmac">;
+def mac_macsRN   : RISCVXCVBuiltin<"int(unsigned int, unsigned int, unsigned int, unsigned int)",
+                                   "xcvmac">;
+def mac_machhsRN : RISCVXCVBuiltin<"int(unsigned int, unsigned int, unsigned int, unsigned int)",
+                                   "xcvmac">;
 } // Attributes = [NoThrow, Const]
diff --git a/clang/lib/CodeGen/CGBuiltin.cpp b/clang/lib/CodeGen/CGBuiltin.cpp
index da3eca73bfb575..c6b9e23721b7db 100644
--- a/clang/lib/CodeGen/CGBuiltin.cpp
+++ b/clang/lib/CodeGen/CGBuiltin.cpp
@@ -22389,6 +22389,61 @@ Value *CodeGenFunction::EmitRISCVBuiltinExpr(unsigned BuiltinID,
   case RISCV::BI__builtin_riscv_cv_alu_subuRN:
     ID = Intrinsic::riscv_cv_alu_subuRN;
     break;
+  // XCVmac
+  case RISCV::BI__builtin_riscv_cv_mac_mac:
+    ID = Intrinsic::riscv_cv_mac_mac;
+    break;
+  case RISCV::BI__builtin_riscv_cv_mac_msu:
+    ID = Intrinsic::riscv_cv_mac_msu;
+    break;
+  case RISCV::BI__builtin_riscv_cv_mac_muluN:
+    ID = Intrinsic::riscv_cv_mac_muluN;
+    break;
+  case RISCV::BI__builtin_riscv_cv_mac_mulhhuN:
+    ID = Intrinsic::riscv_cv_mac_mulhhuN;
+    break;
+  case RISCV::BI__builtin_riscv_cv_mac_mulsN:
+    ID = Intrinsic::riscv_cv_mac_mulsN;
+    break;
+  case RISCV::BI__builtin_riscv_cv_mac_mulhhsN:
+    ID = Intrinsic::riscv_cv_mac_mulhhsN;
+    break;
+  case RISCV::BI__builtin_riscv_cv_mac_muluRN:
+    ID = Intrinsic::riscv_cv_mac_muluRN;
+    break;
+  case RISCV::BI__builtin_riscv_cv_mac_mulhhuRN:
+    ID = Intrinsic::riscv_cv_mac_mulhhuRN;
+    break;
+  case RISCV::BI__builtin_riscv_cv_mac_mulsRN:
+    ID = Intrinsic::riscv_cv_mac_mulsRN;
+    break;
+  case RISCV::BI__builtin_riscv_cv_mac_mulhhsRN:
+    ID = Intrinsic::riscv_cv_mac_mulhhsRN;
+    break;
+  case RISCV::BI__builtin_riscv_cv_mac_macuN:
+    ID = Intrinsic::riscv_cv_mac_macuN;
+    break;
+  case RISCV::BI__builtin_riscv_cv_mac_machhuN:
+    ID = Intrinsic::riscv_cv_mac_machhuN;
+    break;
+  case RISCV::BI__builtin_riscv_cv_mac_macsN:
+    ID = Intrinsic::riscv_cv_mac_macsN;
+    break;
+  case RISCV::BI__builtin_riscv_cv_mac_machhsN:
+    ID = Intrinsic::riscv_cv_mac_machhsN;
+    break;
+  case RISCV::BI__builtin_riscv_cv_mac_macuRN:
+    ID = Intrinsic::riscv_cv_mac_macuRN;
+    break;
+  case RISCV::BI__builtin_riscv_cv_mac_machhuRN:
+    ID = Intrinsic::riscv_cv_mac_machhuRN;
+    break;
+  case RISCV::BI__builtin_riscv_cv_mac_macsRN:
+    ID = Intrinsic::riscv_cv_mac_macsRN;
+    break;
+  case RISCV::BI__builtin_riscv_cv_mac_machhsRN:
+    ID = Intrinsic::riscv_cv_mac_machhsRN;
+    break;
 
     // Vector builtins are handled from here.
 #include "clang/Basic/riscv_vector_builtin_cg.inc"
diff --git a/clang/lib/Headers/CMakeLists.txt b/clang/lib/Headers/CMakeLists.txt
index ff392e7122a448..ff2aa6c999e851 100644
--- a/clang/lib/Headers/CMakeLists.txt
+++ b/clang/lib/Headers/CMakeLists.txt
@@ -121,6 +121,7 @@ set(ppc_htm_files
 set(riscv_files
   riscv_bitmanip.h
         riscv_corev_alu.h
+        riscv_corev_mac.h
   riscv_crypto.h
   riscv_ntlh.h
   sifive_vector.h
diff --git a/clang/lib/Headers/riscv_corev_mac.h b/clang/lib/Headers/riscv_corev_mac.h
new file mode 100644
index 00000000000000..9863162647606c
--- /dev/null
+++ b/clang/lib/Headers/riscv_corev_mac.h
@@ -0,0 +1,109 @@
+/*===---- riscv_corev_mac.h - CORE-V multiply accumulate intrinsics --------===
+ *
+ * Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+ * See https://llvm.org/LICENSE.txt for license information.
+ * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+ *
+ *===-----------------------------------------------------------------------===
+ */
+
+#ifndef __RISCV_COREV_MAC_H
+#define __RISCV_COREV_MAC_H
+
+#include <stdint.h>
+
+#if defined(__cplusplus)
+extern "C" {
+#endif
+
+#if defined(__riscv_xcvmac)
+
+#define __DEFAULT_FN_ATTRS __attribute__((__always_inline__, __nodebug__))
+
+static __inline__ long __DEFAULT_FN_ATTRS __riscv_cv_mac_mac(long a, long b, long c) {
+  return __builtin_riscv_cv_mac_mac(a, b, c);
+}
+
+static __inline__ long __DEFAULT_FN_ATTRS __riscv_cv_mac_msu(long a, long b, long c) {
+  return __builtin_riscv_cv_mac_msu(a, b, c);
+}
+
+#define __riscv_cv_mac_muluN(rs1, rs2, SHIFT) \
+  (unsigned long) __builtin_riscv_cv_mac_muluN((unsigned long) (rs1), \
+                                 (unsigned long) (rs2), (const uint8_t) (SHIFT))
+
+#define __riscv_cv_mac_mulhhuN(rs1, rs2, SHIFT) \
+  (unsigned long) __builtin_riscv_cv_mac_mulhhuN((unsigned long) (rs1), \
+                                 (unsigned long) (rs2), (const uint8_t) (SHIFT))
+
+#define __riscv_cv_mac_mulsN(rs1, rs2, SHIFT) \
+  (long) __builtin_riscv_cv_mac_mulsN((unsigned long) (rs1), \
+                                 (unsigned long) (rs2), (const uint8_t) (SHIFT))
+
+#define __riscv_cv_mac_mulhhsN(rs1, rs2, SHIFT) \
+  (long) __builtin_riscv_cv_mac_mulhhsN((unsigned long) (rs1), \
+                                 (unsigned long) (rs2), (const uint8_t) (SHIFT))
+
+#define __riscv_cv_mac_muluRN(rs1, rs2, SHIFT) \
+  (unsigned long) __builtin_riscv_cv_mac_muluRN((unsigned long) (rs1), \
+                                 (unsigned long) (rs2), (const uint8_t) (SHIFT))
+
+#define __riscv_cv_mac_mulhhuRN(rs1, rs2, SHIFT) \
+  (unsigned long) __builtin_riscv_cv_mac_mulhhuRN((unsigned long) (rs1), \
+                                 (unsigned long) (rs2), (const uint8_t) (SHIFT))
+
+#define __riscv_cv_mac_mulsRN(rs1, rs2, SHIFT) \
+  (long) __builtin_riscv_cv_mac_mulsRN((unsigned long) (rs1), \
+                                 (unsigned long) (rs2), (const uint8_t) (SHIFT))
+
+#define __riscv_cv_mac_mulhhsRN(rs1, rs2, SHIFT) \
+  (long) __builtin_riscv_cv_mac_mulhhsRN((unsigned long) (rs1), \
+                                 (unsigned long) (rs2), (const uint8_t) (SHIFT))
+
+#define __riscv_cv_mac_macuN(rs1, rs2, rD, SHIFT) \
+  (unsigned long) __builtin_riscv_cv_mac_macuN((unsigned long) (rs1), \
+                                  (unsigned long) (rs2), (unsigned long) (rD), \
+                                  (const uint8_t) (SHIFT))
+
+#define __riscv_cv_mac_machhuN(rs1, rs2, rD, SHIFT) \
+  (unsigned long) __builtin_riscv_cv_mac_machhuN((unsigned long) (rs1), \
+                                  (unsigned long) (rs2), (unsigned long) (rD), \
+                                  (const uint8_t) (SHIFT))
+
+#define __riscv_cv_mac_macsN(rs1, rs2, rD, SHIFT) \
+  (long) __builtin_riscv_cv_mac_macsN((unsigned long) (rs1), \
+                                  (unsigned long) (rs2), (unsigned long) (rD), \
+                                  (const uint8_t) (SHIFT))
+
+#define __riscv_cv_mac_machhsN(rs1, rs2, rD, SHIFT) \
+  (long) __builtin_riscv_cv_mac_machhsN((unsigned long) (rs1), \
+                                  (unsigned long) (rs2), (unsigned long) (rD), \
+                                  (const uint8_t) (SHIFT))
+
+#define __riscv_cv_mac_macuRN(rs1, rs2, rD, SHIFT) \
+  (unsigned long) __builtin_riscv_cv_mac_macuRN((unsigned long) (rs1), \
+                                  (unsigned long) (rs2), (unsigned long) (rD), \
+                                  (const uint8_t) (SHIFT))
+
+#define __riscv_cv_mac_machhuRN(rs1, rs2, rD, SHIFT) \
+  (unsigned long) __builtin_riscv_cv_mac_machhuRN((unsigned long) (rs1), \
+                                  (unsigned long) (rs2), (unsigned long) (rD), \
+                                  (const uint8_t) (SHIFT))
+
+#define __riscv_cv_mac_macsRN(rs1, rs2, rD, SHIFT) \
+  (long) __builtin_riscv_cv_mac_macsRN((unsigned long) (rs1), \
+                                  (unsigned long) (rs2), (unsigned long) (rD), \
+                                  (const uint8_t) (SHIFT))
+
+#define __riscv_cv_mac_machhsRN(rs1, rs2, rD, SHIFT) \
+  (long) __builtin_riscv_cv_mac_machhsRN((unsigned long) (rs1), \
+                                  (unsigned long) (rs2), (unsigned long) (rD), \
+                                  (const uint8_t) (SHIFT))
+
+#endif // defined(__riscv_xcvmac)
+
+#if defined(__cplusplus)
+}
+#endif
+
+#endif // define __RISCV_COREV_MAC_H
diff --git a/clang/test/CodeGen/RISCV/riscv-xcvmac-c-api.c b/clang/test/CodeGen/RISCV/riscv-xcvmac-c-api.c
new file mode 100644
index 00000000000000..34ed4bfe27c7e1
--- /dev/null
+++ b/clang/test/CodeGen/RISCV/riscv-xcvmac-c-api.c
@@ -0,0 +1,343 @@
+// NOTE: Assertions have been autogenerated by utils/update_cc_test_checks.py UTC_ARGS: --version 5
+// RUN: %clang_cc1 -triple riscv32 -target-feature +xcvmac -emit-llvm %s -o - \
+// RUN:     | FileCheck %s
+
+#include <stdint.h>
+#include <riscv_corev_mac.h>
+
+// CHECK-LABEL: define dso_local i32 @test_mac_mac(
+// CHECK-SAME: i32 noundef [[X:%.*]], i32 noundef [[Y:%.*]], i32 noundef [[Z:%.*]]) #[[ATTR0:[0-9]+]] {
+// CHECK-NEXT:  [[ENTRY:.*:]]
+// CHECK-NEXT:    [[A_ADDR_I:%.*]] = alloca i32, align 4
+// CHECK-NEXT:    [[B_ADDR_I:%.*]] = alloca i32, align 4
+// CHECK-NEXT:    [[C_ADDR_I:%.*]] = alloca i32, align 4
+// CHECK-NEXT:    [[X_ADDR:%.*]] = alloca i32, align 4
+// CHECK-NEXT:    [[Y_ADDR:%.*]] = alloca i32, align 4
+// CHECK-NEXT:    [[Z_ADDR:%.*]] = alloca i32, align 4
+// CHECK-NEXT:    store i32 [[X]], ptr [[X_ADDR]], align 4
+// CHECK-NEXT:    store i32 [[Y]], ptr [[Y_ADDR]], align 4
+// CHECK-NEXT:    store i32 [[Z]], ptr [[Z_ADDR]], align 4
+// CHECK-NEXT:    [[TMP0:%.*]] = load i32, ptr [[X_ADDR]], align 4
+// CHECK-NEXT:    [[TMP1:%.*]] = load i32, ptr [[Y_ADDR]], align 4
+// CHECK-NEXT:    [[TMP2:%.*]] = load i32, ptr [[Z_ADDR]], align 4
+// CHECK-NEXT:    store i32 [[TMP0]], ptr [[A_ADDR_I]], align 4
+// CHECK-NEXT:    store i32 [[TMP1]], ptr [[B_ADDR_I]], align 4
+// CHECK-NEXT:    store i32 [[TMP2]], ptr [[C_ADDR_I]], align 4
+// CHECK-NEXT:    [[TMP3:%.*]] = load i32, ptr [[A_ADDR_I]], align 4
+// CHECK-NEXT:    [[TMP4:%.*]] = load i32, ptr [[B_ADDR_I]], align 4
+// CHECK-NEXT:    [[TMP5:%.*]] = load i32, ptr [[C_ADDR_I]], align 4
+// CHECK-NEXT:    [[TMP6:%.*]] = call i32 @llvm.riscv.cv.mac.mac(i32 [[TMP3]], i32 [[TMP4]], i32 [[TMP5]])
+// CHECK-NEXT:    ret i32 [[TMP6]]
+//
+int32_t test_mac_mac(int32_t x, int32_t y, int32_t z) {
+    return __riscv_cv_mac_mac(x, y, z);
+}
+
+// CHECK-LABEL: define dso_local i32 @test_mac_msu(
+// CHECK-SAME: i32 noundef [[X:%.*]], i32 noundef [[Y:%.*]], i32 noundef [[Z:%.*]]) #[[ATTR0]] {
+// CHECK-NEXT:  [[ENTRY:.*:]]
+// CHECK-NEXT:    [[A_ADDR_I:%.*]] = alloca i32, align 4
+// CHECK-NEXT:    [[B_ADDR_I:%.*]] = alloca i32, align 4
+// CHECK-NEXT:    [[C_ADDR_I:%.*]] = alloca i32, align 4
+// CHECK-NEXT:    [[X_ADDR:%.*]] = alloca i32, align 4
+// CHECK-NEXT:    [[Y_ADDR:%.*]] = alloca i32, align 4
+// CHECK-NEXT:    [[Z_ADDR:%.*]] = alloca i32, align 4
+// CHECK-NEXT:    store i32 [[X]], ptr [[X_ADDR]], align 4
+// CHECK-NEXT:    store i32 [[Y]], ptr [[Y_ADDR]], align 4
+// CHECK-NEXT:    store i32 [[Z]], ptr [[Z_ADDR]], align 4
+// CHECK-NEXT:    [[TMP0:%.*]] = load i32, ptr [[X_ADDR]], align 4
+// CHECK-NEXT:    [[TMP1:%.*]] = load i32, ptr [[Y_ADDR]], align 4
+// CHECK-NEXT:    [[TMP2:%.*]] = load i32, ptr [[Z_ADDR]], align 4
+// CHECK-NEXT:    store i32 [[TMP0]], ptr [[A_ADDR_I]], align 4
+// CHECK-NEXT:    store i32 [[TMP1]], ptr [[B_ADDR_I]], align 4
+// CHECK-NEXT:    store i32 [[TMP2]], ptr [[C_ADDR_I]], align 4
+// CHECK-NEXT:    [[TMP3:%.*]] = load i32, ptr [[A_ADDR_I]], align 4
+// CHECK-NEXT:    [[TMP4:%.*]] = load i32, ptr [[B_ADDR_I]], align 4
+// CHECK-NEXT:    [[TMP5:%.*]] = load i32, ptr [[C_ADDR_I]], align 4
+// CHECK-NEXT:    [[TMP6:%.*]] = call i32 @llvm.riscv.cv.mac.msu(i32 [[TMP3]], i32 [[TMP4]], i32 [[TMP5]])
+// CHECK-NEXT:    ret i32 [[TMP6]]
+//
+int32_t test_mac_msu(int32_t x, int32_t y, int32_t z) {
+    return __riscv_cv_mac_msu(x, y, z);
+}
+
+// CHECK-LABEL: define dso_local i32 @test_mac_muluN(
+// CHECK-SAME: i32 noundef [[X:%.*]], i32 noundef [[Y:%.*]]) #[[ATTR0]] {
+// CHECK-NEXT:  [[ENTRY:.*:]]
+// CHECK-NEXT:    [[X_ADDR:%.*]] = alloca i32, align 4
+// CHECK-NEXT:    [[Y_ADDR:%.*]] = alloca i32, align 4
+// CHECK-NEXT:    store i32 [[X]], ptr [[X_ADDR]], align 4
+// CHECK-NEXT:    store i32 [[Y]], ptr [[Y_ADDR]], align 4
+// CHECK-NEXT:    [[TMP0:%.*]] = load i32, ptr [[X_ADDR]], align 4
+// CHECK-NEXT:    [[TMP1:%.*]] = load i32, ptr [[Y_ADDR]], align 4
+// CHECK-NEXT:    [[TMP2:%.*]] = call i32 @llvm.riscv.cv.mac.muluN(i32 [[TMP0]], i32 [[TMP1]], i32 0)
+// CHECK-NEXT:    ret i32 [[TMP2]]
+//
+uint32_t test_mac_muluN(uint32_t x, uint32_t y) {
+    return __riscv_cv_mac_muluN(x, y, 0);
+}
+
+// CHECK-LABEL: define dso_local i32 @test_mac_mulhhuN(
+// CHECK-SAME: i32 noundef [[X:%.*]], i32 noundef [[Y:%.*]]) #[[ATTR0]] {
+// CHECK-NEXT:  [[ENTRY:.*:]]
+// CHECK-NEXT:    [[X_ADDR:%.*]] = alloca i32, align 4
+// CHECK-NEXT:    [[Y_ADDR:%.*]] = alloca i32, align 4
+// CHECK-NEXT:    store i32 [[X]], ptr [[X_ADDR]], align 4
+// CHECK-NEXT:    store i32 [[Y]], ptr [[Y_ADDR]], align 4
+// CHECK-NEXT:    [[TMP0:%.*]] = load i32, ptr [[X_ADDR]], align 4
+// CHECK-NEXT:    [[TMP1:%.*]] = load i32, ptr [[Y_ADDR]], align 4
+// CHECK-NEXT:    [[TMP2:%.*]] = call i32 @llvm.riscv.cv.mac.mulhhuN(i32 [[TMP0]], i32 [[TMP1]], i32 0)
+// CHECK-NEXT:    ret i32 [[TMP2]]
+//
+uint32_t test_mac_mulhhuN(uint32_t x, uint32_t y) {
+    return __riscv_cv_mac_mulhhuN(x, y, 0);
+}
+
+// CHECK-LABEL: define dso_local i32 @test_mac_mulsN(
+// CHECK-SAME: i32 noundef [[X:%.*]], i32 noundef [[Y:%.*]]) #[[ATTR0]] {
+// CHECK-NEXT:  [[ENTRY:.*:]]
+// CHECK-NEXT:    [[X_ADDR:%.*]] = alloca i32, align 4
+// CHECK-NEXT:    [[Y_ADDR:%.*]] = alloca i32, align 4
+// CHECK-NEXT:    store i32 [[X]], ptr [[X_ADDR]], align 4
+// CHECK-NEXT:    store i32 [[Y]], ptr [[Y_ADDR]], align 4
+// CHECK-NEXT:    [[TMP0:%.*]] = load i32, ptr [[X_ADDR]], align 4
+// CHECK-NEXT:    [[TMP1:%.*]] = load i32, ptr [[Y_ADDR]], align 4
+// CHECK-NEXT:    [[TMP2:%.*]] = call i32 @llvm.riscv.cv.mac.mulsN(i32 [[TMP0]], i32 [[TMP1]], i32 0)
+// CHECK-NEXT:    ret i32 [[TMP2]]
+//
+int32_t test_mac_mulsN(uint32_t x, uint32_t y) {
+    return __riscv_cv_mac_mulsN(x, y, 0);
+}
+
+// CHECK-LABEL: define dso_local i32 @test_mac_mulhhsN(
+// CHECK-SAME: i32 noundef [[X:%.*]], i32 noundef [[Y:%.*]]) #[[ATTR0]] {
+// CHECK-NEXT:  [[ENTRY:.*:]]
+// CHECK-NEXT:    [[X_ADDR:%.*]] = alloca i32, align 4
+// CHECK-NEXT:    [[Y_ADDR:%.*]] = alloca i32, align 4
+// CHECK-NEXT:    store i32 [[X]], ptr [[X_ADDR]], align 4
+// CHECK-NEXT:    store i32 [[Y]], ptr [[Y_ADDR]], align 4
+// CHECK-NEXT:    [[TMP0:%.*]] = load i32, ptr [[X_ADDR]], align 4
+// CHECK-NEXT:    [[TMP1:%.*]] = load i32, ptr [[Y_ADDR]], align 4
+// CHECK-NEXT:    [[TMP2:%.*]] = call i32 @llvm.riscv.cv.mac.mulhhsN(i32 [[TMP0]], i32 [[TMP1]], i32 0)
+// CHECK-NEXT:    ret i32 [[TMP2]]
+//
+int32_t test_mac_mulhhsN(uint...
[truncated]

@llvmbot
Copy link

llvmbot commented Oct 1, 2024

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

Author: None (realqhc)

Changes

This commit adds the Clang Builtins, C API header and relevant tests for XCVmac extension.

Spec:
https://github.com/openhwgroup/core-v-sw/blob/master/specifications/corev-builtin-spec.md

Contributor: @PaoloS02


Patch is 45.71 KiB, truncated to 20.00 KiB below, full version: https://github.com/llvm/llvm-project/pull/110623.diff

6 Files Affected:

  • (modified) clang/include/clang/Basic/BuiltinsRISCVXCV.td (+55-17)
  • (modified) clang/lib/CodeGen/CGBuiltin.cpp (+55)
  • (modified) clang/lib/Headers/CMakeLists.txt (+1)
  • (added) clang/lib/Headers/riscv_corev_mac.h (+109)
  • (added) clang/test/CodeGen/RISCV/riscv-xcvmac-c-api.c (+343)
  • (added) clang/test/CodeGen/RISCV/riscv-xcvmac.c (+309)
diff --git a/clang/include/clang/Basic/BuiltinsRISCVXCV.td b/clang/include/clang/Basic/BuiltinsRISCVXCV.td
index 06ce07ade5c122..4c813ecf3d33d3 100644
--- a/clang/include/clang/Basic/BuiltinsRISCVXCV.td
+++ b/clang/include/clang/Basic/BuiltinsRISCVXCV.td
@@ -11,7 +11,7 @@
 //
 //===----------------------------------------------------------------------===//
 
-class RISCXCVBuiltin<string prototype, string features = ""> : TargetBuiltin {
+class RISCVXCVBuiltin<string prototype, string features = ""> : TargetBuiltin {
   let Spellings = ["__builtin_riscv_cv_" # NAME];
   let Prototype = prototype;
   let Features = features;
@@ -21,21 +21,59 @@ let Attributes = [NoThrow, Const] in {
 //===----------------------------------------------------------------------===//
 // XCValu extension.
 //===----------------------------------------------------------------------===//
-def alu_slet  : RISCXCVBuiltin<"int(int, int)", "xcvalu">;
-def alu_sletu : RISCXCVBuiltin<"int(unsigned int, unsigned int)", "xcvalu">;
-def alu_exths : RISCXCVBuiltin<"int(int)", "xcvalu">;
-def alu_exthz : RISCXCVBuiltin<"unsigned int(unsigned int)", "xcvalu">;
-def alu_extbs : RISCXCVBuiltin<"int(int)", "xcvalu">;
-def alu_extbz : RISCXCVBuiltin<"unsigned int(unsigned int)", "xcvalu">;
+def alu_slet  : RISCVXCVBuiltin<"int(int, int)", "xcvalu">;
+def alu_sletu : RISCVXCVBuiltin<"int(unsigned int, unsigned int)", "xcvalu">;
+def alu_exths : RISCVXCVBuiltin<"int(int)", "xcvalu">;
+def alu_exthz : RISCVXCVBuiltin<"unsigned int(unsigned int)", "xcvalu">;
+def alu_extbs : RISCVXCVBuiltin<"int(int)", "xcvalu">;
+def alu_extbz : RISCVXCVBuiltin<"unsigned int(unsigned int)", "xcvalu">;
 
-def alu_clip   : RISCXCVBuiltin<"int(int, int)", "xcvalu">;
-def alu_clipu  : RISCXCVBuiltin<"unsigned int(unsigned int, unsigned int)", "xcvalu">;
-def alu_addN   : RISCXCVBuiltin<"int(int, int, unsigned int)", "xcvalu">;
-def alu_adduN  : RISCXCVBuiltin<"unsigned int(unsigned int, unsigned int, unsigned int)", "xcvalu">;
-def alu_addRN  : RISCXCVBuiltin<"int(int, int, unsigned int)", "xcvalu">;
-def alu_adduRN : RISCXCVBuiltin<"unsigned int(unsigned int, unsigned int, unsigned int)", "xcvalu">;
-def alu_subN   : RISCXCVBuiltin<"int(int, int, unsigned int)", "xcvalu">;
-def alu_subuN  : RISCXCVBuiltin<"unsigned int(unsigned int, unsigned int, unsigned int)", "xcvalu">;
-def alu_subRN  : RISCXCVBuiltin<"int(int, int, unsigned int)", "xcvalu">;
-def alu_subuRN : RISCXCVBuiltin<"unsigned int(unsigned int, unsigned int, unsigned int)", "xcvalu">;
+def alu_clip   : RISCVXCVBuiltin<"int(int, int)", "xcvalu">;
+def alu_clipu  : RISCVXCVBuiltin<"unsigned int(unsigned int, unsigned int)", "xcvalu">;
+def alu_addN   : RISCVXCVBuiltin<"int(int, int, unsigned int)", "xcvalu">;
+def alu_adduN  : RISCVXCVBuiltin<"unsigned int(unsigned int, unsigned int, unsigned int)", "xcvalu">;
+def alu_addRN  : RISCVXCVBuiltin<"int(int, int, unsigned int)", "xcvalu">;
+def alu_adduRN : RISCVXCVBuiltin<"unsigned int(unsigned int, unsigned int, unsigned int)", "xcvalu">;
+def alu_subN   : RISCVXCVBuiltin<"int(int, int, unsigned int)", "xcvalu">;
+def alu_subuN  : RISCVXCVBuiltin<"unsigned int(unsigned int, unsigned int, unsigned int)", "xcvalu">;
+def alu_subRN  : RISCVXCVBuiltin<"int(int, int, unsigned int)", "xcvalu">;
+def alu_subuRN : RISCVXCVBuiltin<"unsigned int(unsigned int, unsigned int, unsigned int)", "xcvalu">;
+
+//===----------------------------------------------------------------------===//
+// XCVmac extension.
+//===----------------------------------------------------------------------===//
+def mac_mac      : RISCVXCVBuiltin<"int(int, int, int)", "xcvmac">;
+def mac_msu      : RISCVXCVBuiltin<"int(int, int, int)", "xcvmac">;
+def mac_muluN    : RISCVXCVBuiltin<"unsigned int(unsigned int, unsigned int, unsigned int)",
+                                   "xcvmac">;
+def mac_mulhhuN  : RISCVXCVBuiltin<"unsigned int(unsigned int, unsigned int, unsigned int)",
+                                   "xcvmac">;
+def mac_mulsN    : RISCVXCVBuiltin<"int(unsigned int, unsigned int, unsigned int)",
+                                   "xcvmac">;
+def mac_mulhhsN  : RISCVXCVBuiltin<"int(unsigned int, unsigned int, unsigned int)",
+                                   "xcvmac">;
+def mac_muluRN   : RISCVXCVBuiltin<"unsigned int(unsigned int, unsigned int, unsigned int)",
+                                   "xcvmac">;
+def mac_mulhhuRN : RISCVXCVBuiltin<"unsigned int(unsigned int, unsigned int, unsigned int)",
+                                   "xcvmac">;
+def mac_mulsRN   : RISCVXCVBuiltin<"int(unsigned int, unsigned int, unsigned int)",
+                                   "xcvmac">;
+def mac_mulhhsRN : RISCVXCVBuiltin<"int(unsigned int, unsigned int, unsigned int)",
+                                   "xcvmac">;
+def mac_macuN    : RISCVXCVBuiltin<"unsigned int(unsigned int, unsigned int, unsigned int, unsigned int)",
+                                   "xcvmac">;
+def mac_machhuN  : RISCVXCVBuiltin<"unsigned int(unsigned int, unsigned int, unsigned int, unsigned int)",
+                                   "xcvmac">;
+def mac_macsN    : RISCVXCVBuiltin<"int(unsigned int, unsigned int, unsigned int, unsigned int)",
+                                   "xcvmac">;
+def mac_machhsN  : RISCVXCVBuiltin<"int(unsigned int, unsigned int, unsigned int, unsigned int)",
+                                   "xcvmac">;
+def mac_macuRN   : RISCVXCVBuiltin<"unsigned int(unsigned int, unsigned int, unsigned int, unsigned int)",
+                                    "xcvmac">;
+def mac_machhuRN : RISCVXCVBuiltin<"unsigned int(unsigned int, unsigned int, unsigned int, unsigned int)",
+                                   "xcvmac">;
+def mac_macsRN   : RISCVXCVBuiltin<"int(unsigned int, unsigned int, unsigned int, unsigned int)",
+                                   "xcvmac">;
+def mac_machhsRN : RISCVXCVBuiltin<"int(unsigned int, unsigned int, unsigned int, unsigned int)",
+                                   "xcvmac">;
 } // Attributes = [NoThrow, Const]
diff --git a/clang/lib/CodeGen/CGBuiltin.cpp b/clang/lib/CodeGen/CGBuiltin.cpp
index da3eca73bfb575..c6b9e23721b7db 100644
--- a/clang/lib/CodeGen/CGBuiltin.cpp
+++ b/clang/lib/CodeGen/CGBuiltin.cpp
@@ -22389,6 +22389,61 @@ Value *CodeGenFunction::EmitRISCVBuiltinExpr(unsigned BuiltinID,
   case RISCV::BI__builtin_riscv_cv_alu_subuRN:
     ID = Intrinsic::riscv_cv_alu_subuRN;
     break;
+  // XCVmac
+  case RISCV::BI__builtin_riscv_cv_mac_mac:
+    ID = Intrinsic::riscv_cv_mac_mac;
+    break;
+  case RISCV::BI__builtin_riscv_cv_mac_msu:
+    ID = Intrinsic::riscv_cv_mac_msu;
+    break;
+  case RISCV::BI__builtin_riscv_cv_mac_muluN:
+    ID = Intrinsic::riscv_cv_mac_muluN;
+    break;
+  case RISCV::BI__builtin_riscv_cv_mac_mulhhuN:
+    ID = Intrinsic::riscv_cv_mac_mulhhuN;
+    break;
+  case RISCV::BI__builtin_riscv_cv_mac_mulsN:
+    ID = Intrinsic::riscv_cv_mac_mulsN;
+    break;
+  case RISCV::BI__builtin_riscv_cv_mac_mulhhsN:
+    ID = Intrinsic::riscv_cv_mac_mulhhsN;
+    break;
+  case RISCV::BI__builtin_riscv_cv_mac_muluRN:
+    ID = Intrinsic::riscv_cv_mac_muluRN;
+    break;
+  case RISCV::BI__builtin_riscv_cv_mac_mulhhuRN:
+    ID = Intrinsic::riscv_cv_mac_mulhhuRN;
+    break;
+  case RISCV::BI__builtin_riscv_cv_mac_mulsRN:
+    ID = Intrinsic::riscv_cv_mac_mulsRN;
+    break;
+  case RISCV::BI__builtin_riscv_cv_mac_mulhhsRN:
+    ID = Intrinsic::riscv_cv_mac_mulhhsRN;
+    break;
+  case RISCV::BI__builtin_riscv_cv_mac_macuN:
+    ID = Intrinsic::riscv_cv_mac_macuN;
+    break;
+  case RISCV::BI__builtin_riscv_cv_mac_machhuN:
+    ID = Intrinsic::riscv_cv_mac_machhuN;
+    break;
+  case RISCV::BI__builtin_riscv_cv_mac_macsN:
+    ID = Intrinsic::riscv_cv_mac_macsN;
+    break;
+  case RISCV::BI__builtin_riscv_cv_mac_machhsN:
+    ID = Intrinsic::riscv_cv_mac_machhsN;
+    break;
+  case RISCV::BI__builtin_riscv_cv_mac_macuRN:
+    ID = Intrinsic::riscv_cv_mac_macuRN;
+    break;
+  case RISCV::BI__builtin_riscv_cv_mac_machhuRN:
+    ID = Intrinsic::riscv_cv_mac_machhuRN;
+    break;
+  case RISCV::BI__builtin_riscv_cv_mac_macsRN:
+    ID = Intrinsic::riscv_cv_mac_macsRN;
+    break;
+  case RISCV::BI__builtin_riscv_cv_mac_machhsRN:
+    ID = Intrinsic::riscv_cv_mac_machhsRN;
+    break;
 
     // Vector builtins are handled from here.
 #include "clang/Basic/riscv_vector_builtin_cg.inc"
diff --git a/clang/lib/Headers/CMakeLists.txt b/clang/lib/Headers/CMakeLists.txt
index ff392e7122a448..ff2aa6c999e851 100644
--- a/clang/lib/Headers/CMakeLists.txt
+++ b/clang/lib/Headers/CMakeLists.txt
@@ -121,6 +121,7 @@ set(ppc_htm_files
 set(riscv_files
   riscv_bitmanip.h
         riscv_corev_alu.h
+        riscv_corev_mac.h
   riscv_crypto.h
   riscv_ntlh.h
   sifive_vector.h
diff --git a/clang/lib/Headers/riscv_corev_mac.h b/clang/lib/Headers/riscv_corev_mac.h
new file mode 100644
index 00000000000000..9863162647606c
--- /dev/null
+++ b/clang/lib/Headers/riscv_corev_mac.h
@@ -0,0 +1,109 @@
+/*===---- riscv_corev_mac.h - CORE-V multiply accumulate intrinsics --------===
+ *
+ * Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+ * See https://llvm.org/LICENSE.txt for license information.
+ * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+ *
+ *===-----------------------------------------------------------------------===
+ */
+
+#ifndef __RISCV_COREV_MAC_H
+#define __RISCV_COREV_MAC_H
+
+#include <stdint.h>
+
+#if defined(__cplusplus)
+extern "C" {
+#endif
+
+#if defined(__riscv_xcvmac)
+
+#define __DEFAULT_FN_ATTRS __attribute__((__always_inline__, __nodebug__))
+
+static __inline__ long __DEFAULT_FN_ATTRS __riscv_cv_mac_mac(long a, long b, long c) {
+  return __builtin_riscv_cv_mac_mac(a, b, c);
+}
+
+static __inline__ long __DEFAULT_FN_ATTRS __riscv_cv_mac_msu(long a, long b, long c) {
+  return __builtin_riscv_cv_mac_msu(a, b, c);
+}
+
+#define __riscv_cv_mac_muluN(rs1, rs2, SHIFT) \
+  (unsigned long) __builtin_riscv_cv_mac_muluN((unsigned long) (rs1), \
+                                 (unsigned long) (rs2), (const uint8_t) (SHIFT))
+
+#define __riscv_cv_mac_mulhhuN(rs1, rs2, SHIFT) \
+  (unsigned long) __builtin_riscv_cv_mac_mulhhuN((unsigned long) (rs1), \
+                                 (unsigned long) (rs2), (const uint8_t) (SHIFT))
+
+#define __riscv_cv_mac_mulsN(rs1, rs2, SHIFT) \
+  (long) __builtin_riscv_cv_mac_mulsN((unsigned long) (rs1), \
+                                 (unsigned long) (rs2), (const uint8_t) (SHIFT))
+
+#define __riscv_cv_mac_mulhhsN(rs1, rs2, SHIFT) \
+  (long) __builtin_riscv_cv_mac_mulhhsN((unsigned long) (rs1), \
+                                 (unsigned long) (rs2), (const uint8_t) (SHIFT))
+
+#define __riscv_cv_mac_muluRN(rs1, rs2, SHIFT) \
+  (unsigned long) __builtin_riscv_cv_mac_muluRN((unsigned long) (rs1), \
+                                 (unsigned long) (rs2), (const uint8_t) (SHIFT))
+
+#define __riscv_cv_mac_mulhhuRN(rs1, rs2, SHIFT) \
+  (unsigned long) __builtin_riscv_cv_mac_mulhhuRN((unsigned long) (rs1), \
+                                 (unsigned long) (rs2), (const uint8_t) (SHIFT))
+
+#define __riscv_cv_mac_mulsRN(rs1, rs2, SHIFT) \
+  (long) __builtin_riscv_cv_mac_mulsRN((unsigned long) (rs1), \
+                                 (unsigned long) (rs2), (const uint8_t) (SHIFT))
+
+#define __riscv_cv_mac_mulhhsRN(rs1, rs2, SHIFT) \
+  (long) __builtin_riscv_cv_mac_mulhhsRN((unsigned long) (rs1), \
+                                 (unsigned long) (rs2), (const uint8_t) (SHIFT))
+
+#define __riscv_cv_mac_macuN(rs1, rs2, rD, SHIFT) \
+  (unsigned long) __builtin_riscv_cv_mac_macuN((unsigned long) (rs1), \
+                                  (unsigned long) (rs2), (unsigned long) (rD), \
+                                  (const uint8_t) (SHIFT))
+
+#define __riscv_cv_mac_machhuN(rs1, rs2, rD, SHIFT) \
+  (unsigned long) __builtin_riscv_cv_mac_machhuN((unsigned long) (rs1), \
+                                  (unsigned long) (rs2), (unsigned long) (rD), \
+                                  (const uint8_t) (SHIFT))
+
+#define __riscv_cv_mac_macsN(rs1, rs2, rD, SHIFT) \
+  (long) __builtin_riscv_cv_mac_macsN((unsigned long) (rs1), \
+                                  (unsigned long) (rs2), (unsigned long) (rD), \
+                                  (const uint8_t) (SHIFT))
+
+#define __riscv_cv_mac_machhsN(rs1, rs2, rD, SHIFT) \
+  (long) __builtin_riscv_cv_mac_machhsN((unsigned long) (rs1), \
+                                  (unsigned long) (rs2), (unsigned long) (rD), \
+                                  (const uint8_t) (SHIFT))
+
+#define __riscv_cv_mac_macuRN(rs1, rs2, rD, SHIFT) \
+  (unsigned long) __builtin_riscv_cv_mac_macuRN((unsigned long) (rs1), \
+                                  (unsigned long) (rs2), (unsigned long) (rD), \
+                                  (const uint8_t) (SHIFT))
+
+#define __riscv_cv_mac_machhuRN(rs1, rs2, rD, SHIFT) \
+  (unsigned long) __builtin_riscv_cv_mac_machhuRN((unsigned long) (rs1), \
+                                  (unsigned long) (rs2), (unsigned long) (rD), \
+                                  (const uint8_t) (SHIFT))
+
+#define __riscv_cv_mac_macsRN(rs1, rs2, rD, SHIFT) \
+  (long) __builtin_riscv_cv_mac_macsRN((unsigned long) (rs1), \
+                                  (unsigned long) (rs2), (unsigned long) (rD), \
+                                  (const uint8_t) (SHIFT))
+
+#define __riscv_cv_mac_machhsRN(rs1, rs2, rD, SHIFT) \
+  (long) __builtin_riscv_cv_mac_machhsRN((unsigned long) (rs1), \
+                                  (unsigned long) (rs2), (unsigned long) (rD), \
+                                  (const uint8_t) (SHIFT))
+
+#endif // defined(__riscv_xcvmac)
+
+#if defined(__cplusplus)
+}
+#endif
+
+#endif // define __RISCV_COREV_MAC_H
diff --git a/clang/test/CodeGen/RISCV/riscv-xcvmac-c-api.c b/clang/test/CodeGen/RISCV/riscv-xcvmac-c-api.c
new file mode 100644
index 00000000000000..34ed4bfe27c7e1
--- /dev/null
+++ b/clang/test/CodeGen/RISCV/riscv-xcvmac-c-api.c
@@ -0,0 +1,343 @@
+// NOTE: Assertions have been autogenerated by utils/update_cc_test_checks.py UTC_ARGS: --version 5
+// RUN: %clang_cc1 -triple riscv32 -target-feature +xcvmac -emit-llvm %s -o - \
+// RUN:     | FileCheck %s
+
+#include <stdint.h>
+#include <riscv_corev_mac.h>
+
+// CHECK-LABEL: define dso_local i32 @test_mac_mac(
+// CHECK-SAME: i32 noundef [[X:%.*]], i32 noundef [[Y:%.*]], i32 noundef [[Z:%.*]]) #[[ATTR0:[0-9]+]] {
+// CHECK-NEXT:  [[ENTRY:.*:]]
+// CHECK-NEXT:    [[A_ADDR_I:%.*]] = alloca i32, align 4
+// CHECK-NEXT:    [[B_ADDR_I:%.*]] = alloca i32, align 4
+// CHECK-NEXT:    [[C_ADDR_I:%.*]] = alloca i32, align 4
+// CHECK-NEXT:    [[X_ADDR:%.*]] = alloca i32, align 4
+// CHECK-NEXT:    [[Y_ADDR:%.*]] = alloca i32, align 4
+// CHECK-NEXT:    [[Z_ADDR:%.*]] = alloca i32, align 4
+// CHECK-NEXT:    store i32 [[X]], ptr [[X_ADDR]], align 4
+// CHECK-NEXT:    store i32 [[Y]], ptr [[Y_ADDR]], align 4
+// CHECK-NEXT:    store i32 [[Z]], ptr [[Z_ADDR]], align 4
+// CHECK-NEXT:    [[TMP0:%.*]] = load i32, ptr [[X_ADDR]], align 4
+// CHECK-NEXT:    [[TMP1:%.*]] = load i32, ptr [[Y_ADDR]], align 4
+// CHECK-NEXT:    [[TMP2:%.*]] = load i32, ptr [[Z_ADDR]], align 4
+// CHECK-NEXT:    store i32 [[TMP0]], ptr [[A_ADDR_I]], align 4
+// CHECK-NEXT:    store i32 [[TMP1]], ptr [[B_ADDR_I]], align 4
+// CHECK-NEXT:    store i32 [[TMP2]], ptr [[C_ADDR_I]], align 4
+// CHECK-NEXT:    [[TMP3:%.*]] = load i32, ptr [[A_ADDR_I]], align 4
+// CHECK-NEXT:    [[TMP4:%.*]] = load i32, ptr [[B_ADDR_I]], align 4
+// CHECK-NEXT:    [[TMP5:%.*]] = load i32, ptr [[C_ADDR_I]], align 4
+// CHECK-NEXT:    [[TMP6:%.*]] = call i32 @llvm.riscv.cv.mac.mac(i32 [[TMP3]], i32 [[TMP4]], i32 [[TMP5]])
+// CHECK-NEXT:    ret i32 [[TMP6]]
+//
+int32_t test_mac_mac(int32_t x, int32_t y, int32_t z) {
+    return __riscv_cv_mac_mac(x, y, z);
+}
+
+// CHECK-LABEL: define dso_local i32 @test_mac_msu(
+// CHECK-SAME: i32 noundef [[X:%.*]], i32 noundef [[Y:%.*]], i32 noundef [[Z:%.*]]) #[[ATTR0]] {
+// CHECK-NEXT:  [[ENTRY:.*:]]
+// CHECK-NEXT:    [[A_ADDR_I:%.*]] = alloca i32, align 4
+// CHECK-NEXT:    [[B_ADDR_I:%.*]] = alloca i32, align 4
+// CHECK-NEXT:    [[C_ADDR_I:%.*]] = alloca i32, align 4
+// CHECK-NEXT:    [[X_ADDR:%.*]] = alloca i32, align 4
+// CHECK-NEXT:    [[Y_ADDR:%.*]] = alloca i32, align 4
+// CHECK-NEXT:    [[Z_ADDR:%.*]] = alloca i32, align 4
+// CHECK-NEXT:    store i32 [[X]], ptr [[X_ADDR]], align 4
+// CHECK-NEXT:    store i32 [[Y]], ptr [[Y_ADDR]], align 4
+// CHECK-NEXT:    store i32 [[Z]], ptr [[Z_ADDR]], align 4
+// CHECK-NEXT:    [[TMP0:%.*]] = load i32, ptr [[X_ADDR]], align 4
+// CHECK-NEXT:    [[TMP1:%.*]] = load i32, ptr [[Y_ADDR]], align 4
+// CHECK-NEXT:    [[TMP2:%.*]] = load i32, ptr [[Z_ADDR]], align 4
+// CHECK-NEXT:    store i32 [[TMP0]], ptr [[A_ADDR_I]], align 4
+// CHECK-NEXT:    store i32 [[TMP1]], ptr [[B_ADDR_I]], align 4
+// CHECK-NEXT:    store i32 [[TMP2]], ptr [[C_ADDR_I]], align 4
+// CHECK-NEXT:    [[TMP3:%.*]] = load i32, ptr [[A_ADDR_I]], align 4
+// CHECK-NEXT:    [[TMP4:%.*]] = load i32, ptr [[B_ADDR_I]], align 4
+// CHECK-NEXT:    [[TMP5:%.*]] = load i32, ptr [[C_ADDR_I]], align 4
+// CHECK-NEXT:    [[TMP6:%.*]] = call i32 @llvm.riscv.cv.mac.msu(i32 [[TMP3]], i32 [[TMP4]], i32 [[TMP5]])
+// CHECK-NEXT:    ret i32 [[TMP6]]
+//
+int32_t test_mac_msu(int32_t x, int32_t y, int32_t z) {
+    return __riscv_cv_mac_msu(x, y, z);
+}
+
+// CHECK-LABEL: define dso_local i32 @test_mac_muluN(
+// CHECK-SAME: i32 noundef [[X:%.*]], i32 noundef [[Y:%.*]]) #[[ATTR0]] {
+// CHECK-NEXT:  [[ENTRY:.*:]]
+// CHECK-NEXT:    [[X_ADDR:%.*]] = alloca i32, align 4
+// CHECK-NEXT:    [[Y_ADDR:%.*]] = alloca i32, align 4
+// CHECK-NEXT:    store i32 [[X]], ptr [[X_ADDR]], align 4
+// CHECK-NEXT:    store i32 [[Y]], ptr [[Y_ADDR]], align 4
+// CHECK-NEXT:    [[TMP0:%.*]] = load i32, ptr [[X_ADDR]], align 4
+// CHECK-NEXT:    [[TMP1:%.*]] = load i32, ptr [[Y_ADDR]], align 4
+// CHECK-NEXT:    [[TMP2:%.*]] = call i32 @llvm.riscv.cv.mac.muluN(i32 [[TMP0]], i32 [[TMP1]], i32 0)
+// CHECK-NEXT:    ret i32 [[TMP2]]
+//
+uint32_t test_mac_muluN(uint32_t x, uint32_t y) {
+    return __riscv_cv_mac_muluN(x, y, 0);
+}
+
+// CHECK-LABEL: define dso_local i32 @test_mac_mulhhuN(
+// CHECK-SAME: i32 noundef [[X:%.*]], i32 noundef [[Y:%.*]]) #[[ATTR0]] {
+// CHECK-NEXT:  [[ENTRY:.*:]]
+// CHECK-NEXT:    [[X_ADDR:%.*]] = alloca i32, align 4
+// CHECK-NEXT:    [[Y_ADDR:%.*]] = alloca i32, align 4
+// CHECK-NEXT:    store i32 [[X]], ptr [[X_ADDR]], align 4
+// CHECK-NEXT:    store i32 [[Y]], ptr [[Y_ADDR]], align 4
+// CHECK-NEXT:    [[TMP0:%.*]] = load i32, ptr [[X_ADDR]], align 4
+// CHECK-NEXT:    [[TMP1:%.*]] = load i32, ptr [[Y_ADDR]], align 4
+// CHECK-NEXT:    [[TMP2:%.*]] = call i32 @llvm.riscv.cv.mac.mulhhuN(i32 [[TMP0]], i32 [[TMP1]], i32 0)
+// CHECK-NEXT:    ret i32 [[TMP2]]
+//
+uint32_t test_mac_mulhhuN(uint32_t x, uint32_t y) {
+    return __riscv_cv_mac_mulhhuN(x, y, 0);
+}
+
+// CHECK-LABEL: define dso_local i32 @test_mac_mulsN(
+// CHECK-SAME: i32 noundef [[X:%.*]], i32 noundef [[Y:%.*]]) #[[ATTR0]] {
+// CHECK-NEXT:  [[ENTRY:.*:]]
+// CHECK-NEXT:    [[X_ADDR:%.*]] = alloca i32, align 4
+// CHECK-NEXT:    [[Y_ADDR:%.*]] = alloca i32, align 4
+// CHECK-NEXT:    store i32 [[X]], ptr [[X_ADDR]], align 4
+// CHECK-NEXT:    store i32 [[Y]], ptr [[Y_ADDR]], align 4
+// CHECK-NEXT:    [[TMP0:%.*]] = load i32, ptr [[X_ADDR]], align 4
+// CHECK-NEXT:    [[TMP1:%.*]] = load i32, ptr [[Y_ADDR]], align 4
+// CHECK-NEXT:    [[TMP2:%.*]] = call i32 @llvm.riscv.cv.mac.mulsN(i32 [[TMP0]], i32 [[TMP1]], i32 0)
+// CHECK-NEXT:    ret i32 [[TMP2]]
+//
+int32_t test_mac_mulsN(uint32_t x, uint32_t y) {
+    return __riscv_cv_mac_mulsN(x, y, 0);
+}
+
+// CHECK-LABEL: define dso_local i32 @test_mac_mulhhsN(
+// CHECK-SAME: i32 noundef [[X:%.*]], i32 noundef [[Y:%.*]]) #[[ATTR0]] {
+// CHECK-NEXT:  [[ENTRY:.*:]]
+// CHECK-NEXT:    [[X_ADDR:%.*]] = alloca i32, align 4
+// CHECK-NEXT:    [[Y_ADDR:%.*]] = alloca i32, align 4
+// CHECK-NEXT:    store i32 [[X]], ptr [[X_ADDR]], align 4
+// CHECK-NEXT:    store i32 [[Y]], ptr [[Y_ADDR]], align 4
+// CHECK-NEXT:    [[TMP0:%.*]] = load i32, ptr [[X_ADDR]], align 4
+// CHECK-NEXT:    [[TMP1:%.*]] = load i32, ptr [[Y_ADDR]], align 4
+// CHECK-NEXT:    [[TMP2:%.*]] = call i32 @llvm.riscv.cv.mac.mulhhsN(i32 [[TMP0]], i32 [[TMP1]], i32 0)
+// CHECK-NEXT:    ret i32 [[TMP2]]
+//
+int32_t test_mac_mulhhsN(uint...
[truncated]

@llvmbot
Copy link

llvmbot commented Oct 1, 2024

@llvm/pr-subscribers-clang-codegen

Author: None (realqhc)

Changes

This commit adds the Clang Builtins, C API header and relevant tests for XCVmac extension.

Spec:
https://github.com/openhwgroup/core-v-sw/blob/master/specifications/corev-builtin-spec.md

Contributor: @PaoloS02


Patch is 45.71 KiB, truncated to 20.00 KiB below, full version: https://github.com/llvm/llvm-project/pull/110623.diff

6 Files Affected:

  • (modified) clang/include/clang/Basic/BuiltinsRISCVXCV.td (+55-17)
  • (modified) clang/lib/CodeGen/CGBuiltin.cpp (+55)
  • (modified) clang/lib/Headers/CMakeLists.txt (+1)
  • (added) clang/lib/Headers/riscv_corev_mac.h (+109)
  • (added) clang/test/CodeGen/RISCV/riscv-xcvmac-c-api.c (+343)
  • (added) clang/test/CodeGen/RISCV/riscv-xcvmac.c (+309)
diff --git a/clang/include/clang/Basic/BuiltinsRISCVXCV.td b/clang/include/clang/Basic/BuiltinsRISCVXCV.td
index 06ce07ade5c122..4c813ecf3d33d3 100644
--- a/clang/include/clang/Basic/BuiltinsRISCVXCV.td
+++ b/clang/include/clang/Basic/BuiltinsRISCVXCV.td
@@ -11,7 +11,7 @@
 //
 //===----------------------------------------------------------------------===//
 
-class RISCXCVBuiltin<string prototype, string features = ""> : TargetBuiltin {
+class RISCVXCVBuiltin<string prototype, string features = ""> : TargetBuiltin {
   let Spellings = ["__builtin_riscv_cv_" # NAME];
   let Prototype = prototype;
   let Features = features;
@@ -21,21 +21,59 @@ let Attributes = [NoThrow, Const] in {
 //===----------------------------------------------------------------------===//
 // XCValu extension.
 //===----------------------------------------------------------------------===//
-def alu_slet  : RISCXCVBuiltin<"int(int, int)", "xcvalu">;
-def alu_sletu : RISCXCVBuiltin<"int(unsigned int, unsigned int)", "xcvalu">;
-def alu_exths : RISCXCVBuiltin<"int(int)", "xcvalu">;
-def alu_exthz : RISCXCVBuiltin<"unsigned int(unsigned int)", "xcvalu">;
-def alu_extbs : RISCXCVBuiltin<"int(int)", "xcvalu">;
-def alu_extbz : RISCXCVBuiltin<"unsigned int(unsigned int)", "xcvalu">;
+def alu_slet  : RISCVXCVBuiltin<"int(int, int)", "xcvalu">;
+def alu_sletu : RISCVXCVBuiltin<"int(unsigned int, unsigned int)", "xcvalu">;
+def alu_exths : RISCVXCVBuiltin<"int(int)", "xcvalu">;
+def alu_exthz : RISCVXCVBuiltin<"unsigned int(unsigned int)", "xcvalu">;
+def alu_extbs : RISCVXCVBuiltin<"int(int)", "xcvalu">;
+def alu_extbz : RISCVXCVBuiltin<"unsigned int(unsigned int)", "xcvalu">;
 
-def alu_clip   : RISCXCVBuiltin<"int(int, int)", "xcvalu">;
-def alu_clipu  : RISCXCVBuiltin<"unsigned int(unsigned int, unsigned int)", "xcvalu">;
-def alu_addN   : RISCXCVBuiltin<"int(int, int, unsigned int)", "xcvalu">;
-def alu_adduN  : RISCXCVBuiltin<"unsigned int(unsigned int, unsigned int, unsigned int)", "xcvalu">;
-def alu_addRN  : RISCXCVBuiltin<"int(int, int, unsigned int)", "xcvalu">;
-def alu_adduRN : RISCXCVBuiltin<"unsigned int(unsigned int, unsigned int, unsigned int)", "xcvalu">;
-def alu_subN   : RISCXCVBuiltin<"int(int, int, unsigned int)", "xcvalu">;
-def alu_subuN  : RISCXCVBuiltin<"unsigned int(unsigned int, unsigned int, unsigned int)", "xcvalu">;
-def alu_subRN  : RISCXCVBuiltin<"int(int, int, unsigned int)", "xcvalu">;
-def alu_subuRN : RISCXCVBuiltin<"unsigned int(unsigned int, unsigned int, unsigned int)", "xcvalu">;
+def alu_clip   : RISCVXCVBuiltin<"int(int, int)", "xcvalu">;
+def alu_clipu  : RISCVXCVBuiltin<"unsigned int(unsigned int, unsigned int)", "xcvalu">;
+def alu_addN   : RISCVXCVBuiltin<"int(int, int, unsigned int)", "xcvalu">;
+def alu_adduN  : RISCVXCVBuiltin<"unsigned int(unsigned int, unsigned int, unsigned int)", "xcvalu">;
+def alu_addRN  : RISCVXCVBuiltin<"int(int, int, unsigned int)", "xcvalu">;
+def alu_adduRN : RISCVXCVBuiltin<"unsigned int(unsigned int, unsigned int, unsigned int)", "xcvalu">;
+def alu_subN   : RISCVXCVBuiltin<"int(int, int, unsigned int)", "xcvalu">;
+def alu_subuN  : RISCVXCVBuiltin<"unsigned int(unsigned int, unsigned int, unsigned int)", "xcvalu">;
+def alu_subRN  : RISCVXCVBuiltin<"int(int, int, unsigned int)", "xcvalu">;
+def alu_subuRN : RISCVXCVBuiltin<"unsigned int(unsigned int, unsigned int, unsigned int)", "xcvalu">;
+
+//===----------------------------------------------------------------------===//
+// XCVmac extension.
+//===----------------------------------------------------------------------===//
+def mac_mac      : RISCVXCVBuiltin<"int(int, int, int)", "xcvmac">;
+def mac_msu      : RISCVXCVBuiltin<"int(int, int, int)", "xcvmac">;
+def mac_muluN    : RISCVXCVBuiltin<"unsigned int(unsigned int, unsigned int, unsigned int)",
+                                   "xcvmac">;
+def mac_mulhhuN  : RISCVXCVBuiltin<"unsigned int(unsigned int, unsigned int, unsigned int)",
+                                   "xcvmac">;
+def mac_mulsN    : RISCVXCVBuiltin<"int(unsigned int, unsigned int, unsigned int)",
+                                   "xcvmac">;
+def mac_mulhhsN  : RISCVXCVBuiltin<"int(unsigned int, unsigned int, unsigned int)",
+                                   "xcvmac">;
+def mac_muluRN   : RISCVXCVBuiltin<"unsigned int(unsigned int, unsigned int, unsigned int)",
+                                   "xcvmac">;
+def mac_mulhhuRN : RISCVXCVBuiltin<"unsigned int(unsigned int, unsigned int, unsigned int)",
+                                   "xcvmac">;
+def mac_mulsRN   : RISCVXCVBuiltin<"int(unsigned int, unsigned int, unsigned int)",
+                                   "xcvmac">;
+def mac_mulhhsRN : RISCVXCVBuiltin<"int(unsigned int, unsigned int, unsigned int)",
+                                   "xcvmac">;
+def mac_macuN    : RISCVXCVBuiltin<"unsigned int(unsigned int, unsigned int, unsigned int, unsigned int)",
+                                   "xcvmac">;
+def mac_machhuN  : RISCVXCVBuiltin<"unsigned int(unsigned int, unsigned int, unsigned int, unsigned int)",
+                                   "xcvmac">;
+def mac_macsN    : RISCVXCVBuiltin<"int(unsigned int, unsigned int, unsigned int, unsigned int)",
+                                   "xcvmac">;
+def mac_machhsN  : RISCVXCVBuiltin<"int(unsigned int, unsigned int, unsigned int, unsigned int)",
+                                   "xcvmac">;
+def mac_macuRN   : RISCVXCVBuiltin<"unsigned int(unsigned int, unsigned int, unsigned int, unsigned int)",
+                                    "xcvmac">;
+def mac_machhuRN : RISCVXCVBuiltin<"unsigned int(unsigned int, unsigned int, unsigned int, unsigned int)",
+                                   "xcvmac">;
+def mac_macsRN   : RISCVXCVBuiltin<"int(unsigned int, unsigned int, unsigned int, unsigned int)",
+                                   "xcvmac">;
+def mac_machhsRN : RISCVXCVBuiltin<"int(unsigned int, unsigned int, unsigned int, unsigned int)",
+                                   "xcvmac">;
 } // Attributes = [NoThrow, Const]
diff --git a/clang/lib/CodeGen/CGBuiltin.cpp b/clang/lib/CodeGen/CGBuiltin.cpp
index da3eca73bfb575..c6b9e23721b7db 100644
--- a/clang/lib/CodeGen/CGBuiltin.cpp
+++ b/clang/lib/CodeGen/CGBuiltin.cpp
@@ -22389,6 +22389,61 @@ Value *CodeGenFunction::EmitRISCVBuiltinExpr(unsigned BuiltinID,
   case RISCV::BI__builtin_riscv_cv_alu_subuRN:
     ID = Intrinsic::riscv_cv_alu_subuRN;
     break;
+  // XCVmac
+  case RISCV::BI__builtin_riscv_cv_mac_mac:
+    ID = Intrinsic::riscv_cv_mac_mac;
+    break;
+  case RISCV::BI__builtin_riscv_cv_mac_msu:
+    ID = Intrinsic::riscv_cv_mac_msu;
+    break;
+  case RISCV::BI__builtin_riscv_cv_mac_muluN:
+    ID = Intrinsic::riscv_cv_mac_muluN;
+    break;
+  case RISCV::BI__builtin_riscv_cv_mac_mulhhuN:
+    ID = Intrinsic::riscv_cv_mac_mulhhuN;
+    break;
+  case RISCV::BI__builtin_riscv_cv_mac_mulsN:
+    ID = Intrinsic::riscv_cv_mac_mulsN;
+    break;
+  case RISCV::BI__builtin_riscv_cv_mac_mulhhsN:
+    ID = Intrinsic::riscv_cv_mac_mulhhsN;
+    break;
+  case RISCV::BI__builtin_riscv_cv_mac_muluRN:
+    ID = Intrinsic::riscv_cv_mac_muluRN;
+    break;
+  case RISCV::BI__builtin_riscv_cv_mac_mulhhuRN:
+    ID = Intrinsic::riscv_cv_mac_mulhhuRN;
+    break;
+  case RISCV::BI__builtin_riscv_cv_mac_mulsRN:
+    ID = Intrinsic::riscv_cv_mac_mulsRN;
+    break;
+  case RISCV::BI__builtin_riscv_cv_mac_mulhhsRN:
+    ID = Intrinsic::riscv_cv_mac_mulhhsRN;
+    break;
+  case RISCV::BI__builtin_riscv_cv_mac_macuN:
+    ID = Intrinsic::riscv_cv_mac_macuN;
+    break;
+  case RISCV::BI__builtin_riscv_cv_mac_machhuN:
+    ID = Intrinsic::riscv_cv_mac_machhuN;
+    break;
+  case RISCV::BI__builtin_riscv_cv_mac_macsN:
+    ID = Intrinsic::riscv_cv_mac_macsN;
+    break;
+  case RISCV::BI__builtin_riscv_cv_mac_machhsN:
+    ID = Intrinsic::riscv_cv_mac_machhsN;
+    break;
+  case RISCV::BI__builtin_riscv_cv_mac_macuRN:
+    ID = Intrinsic::riscv_cv_mac_macuRN;
+    break;
+  case RISCV::BI__builtin_riscv_cv_mac_machhuRN:
+    ID = Intrinsic::riscv_cv_mac_machhuRN;
+    break;
+  case RISCV::BI__builtin_riscv_cv_mac_macsRN:
+    ID = Intrinsic::riscv_cv_mac_macsRN;
+    break;
+  case RISCV::BI__builtin_riscv_cv_mac_machhsRN:
+    ID = Intrinsic::riscv_cv_mac_machhsRN;
+    break;
 
     // Vector builtins are handled from here.
 #include "clang/Basic/riscv_vector_builtin_cg.inc"
diff --git a/clang/lib/Headers/CMakeLists.txt b/clang/lib/Headers/CMakeLists.txt
index ff392e7122a448..ff2aa6c999e851 100644
--- a/clang/lib/Headers/CMakeLists.txt
+++ b/clang/lib/Headers/CMakeLists.txt
@@ -121,6 +121,7 @@ set(ppc_htm_files
 set(riscv_files
   riscv_bitmanip.h
         riscv_corev_alu.h
+        riscv_corev_mac.h
   riscv_crypto.h
   riscv_ntlh.h
   sifive_vector.h
diff --git a/clang/lib/Headers/riscv_corev_mac.h b/clang/lib/Headers/riscv_corev_mac.h
new file mode 100644
index 00000000000000..9863162647606c
--- /dev/null
+++ b/clang/lib/Headers/riscv_corev_mac.h
@@ -0,0 +1,109 @@
+/*===---- riscv_corev_mac.h - CORE-V multiply accumulate intrinsics --------===
+ *
+ * Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+ * See https://llvm.org/LICENSE.txt for license information.
+ * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+ *
+ *===-----------------------------------------------------------------------===
+ */
+
+#ifndef __RISCV_COREV_MAC_H
+#define __RISCV_COREV_MAC_H
+
+#include <stdint.h>
+
+#if defined(__cplusplus)
+extern "C" {
+#endif
+
+#if defined(__riscv_xcvmac)
+
+#define __DEFAULT_FN_ATTRS __attribute__((__always_inline__, __nodebug__))
+
+static __inline__ long __DEFAULT_FN_ATTRS __riscv_cv_mac_mac(long a, long b, long c) {
+  return __builtin_riscv_cv_mac_mac(a, b, c);
+}
+
+static __inline__ long __DEFAULT_FN_ATTRS __riscv_cv_mac_msu(long a, long b, long c) {
+  return __builtin_riscv_cv_mac_msu(a, b, c);
+}
+
+#define __riscv_cv_mac_muluN(rs1, rs2, SHIFT) \
+  (unsigned long) __builtin_riscv_cv_mac_muluN((unsigned long) (rs1), \
+                                 (unsigned long) (rs2), (const uint8_t) (SHIFT))
+
+#define __riscv_cv_mac_mulhhuN(rs1, rs2, SHIFT) \
+  (unsigned long) __builtin_riscv_cv_mac_mulhhuN((unsigned long) (rs1), \
+                                 (unsigned long) (rs2), (const uint8_t) (SHIFT))
+
+#define __riscv_cv_mac_mulsN(rs1, rs2, SHIFT) \
+  (long) __builtin_riscv_cv_mac_mulsN((unsigned long) (rs1), \
+                                 (unsigned long) (rs2), (const uint8_t) (SHIFT))
+
+#define __riscv_cv_mac_mulhhsN(rs1, rs2, SHIFT) \
+  (long) __builtin_riscv_cv_mac_mulhhsN((unsigned long) (rs1), \
+                                 (unsigned long) (rs2), (const uint8_t) (SHIFT))
+
+#define __riscv_cv_mac_muluRN(rs1, rs2, SHIFT) \
+  (unsigned long) __builtin_riscv_cv_mac_muluRN((unsigned long) (rs1), \
+                                 (unsigned long) (rs2), (const uint8_t) (SHIFT))
+
+#define __riscv_cv_mac_mulhhuRN(rs1, rs2, SHIFT) \
+  (unsigned long) __builtin_riscv_cv_mac_mulhhuRN((unsigned long) (rs1), \
+                                 (unsigned long) (rs2), (const uint8_t) (SHIFT))
+
+#define __riscv_cv_mac_mulsRN(rs1, rs2, SHIFT) \
+  (long) __builtin_riscv_cv_mac_mulsRN((unsigned long) (rs1), \
+                                 (unsigned long) (rs2), (const uint8_t) (SHIFT))
+
+#define __riscv_cv_mac_mulhhsRN(rs1, rs2, SHIFT) \
+  (long) __builtin_riscv_cv_mac_mulhhsRN((unsigned long) (rs1), \
+                                 (unsigned long) (rs2), (const uint8_t) (SHIFT))
+
+#define __riscv_cv_mac_macuN(rs1, rs2, rD, SHIFT) \
+  (unsigned long) __builtin_riscv_cv_mac_macuN((unsigned long) (rs1), \
+                                  (unsigned long) (rs2), (unsigned long) (rD), \
+                                  (const uint8_t) (SHIFT))
+
+#define __riscv_cv_mac_machhuN(rs1, rs2, rD, SHIFT) \
+  (unsigned long) __builtin_riscv_cv_mac_machhuN((unsigned long) (rs1), \
+                                  (unsigned long) (rs2), (unsigned long) (rD), \
+                                  (const uint8_t) (SHIFT))
+
+#define __riscv_cv_mac_macsN(rs1, rs2, rD, SHIFT) \
+  (long) __builtin_riscv_cv_mac_macsN((unsigned long) (rs1), \
+                                  (unsigned long) (rs2), (unsigned long) (rD), \
+                                  (const uint8_t) (SHIFT))
+
+#define __riscv_cv_mac_machhsN(rs1, rs2, rD, SHIFT) \
+  (long) __builtin_riscv_cv_mac_machhsN((unsigned long) (rs1), \
+                                  (unsigned long) (rs2), (unsigned long) (rD), \
+                                  (const uint8_t) (SHIFT))
+
+#define __riscv_cv_mac_macuRN(rs1, rs2, rD, SHIFT) \
+  (unsigned long) __builtin_riscv_cv_mac_macuRN((unsigned long) (rs1), \
+                                  (unsigned long) (rs2), (unsigned long) (rD), \
+                                  (const uint8_t) (SHIFT))
+
+#define __riscv_cv_mac_machhuRN(rs1, rs2, rD, SHIFT) \
+  (unsigned long) __builtin_riscv_cv_mac_machhuRN((unsigned long) (rs1), \
+                                  (unsigned long) (rs2), (unsigned long) (rD), \
+                                  (const uint8_t) (SHIFT))
+
+#define __riscv_cv_mac_macsRN(rs1, rs2, rD, SHIFT) \
+  (long) __builtin_riscv_cv_mac_macsRN((unsigned long) (rs1), \
+                                  (unsigned long) (rs2), (unsigned long) (rD), \
+                                  (const uint8_t) (SHIFT))
+
+#define __riscv_cv_mac_machhsRN(rs1, rs2, rD, SHIFT) \
+  (long) __builtin_riscv_cv_mac_machhsRN((unsigned long) (rs1), \
+                                  (unsigned long) (rs2), (unsigned long) (rD), \
+                                  (const uint8_t) (SHIFT))
+
+#endif // defined(__riscv_xcvmac)
+
+#if defined(__cplusplus)
+}
+#endif
+
+#endif // define __RISCV_COREV_MAC_H
diff --git a/clang/test/CodeGen/RISCV/riscv-xcvmac-c-api.c b/clang/test/CodeGen/RISCV/riscv-xcvmac-c-api.c
new file mode 100644
index 00000000000000..34ed4bfe27c7e1
--- /dev/null
+++ b/clang/test/CodeGen/RISCV/riscv-xcvmac-c-api.c
@@ -0,0 +1,343 @@
+// NOTE: Assertions have been autogenerated by utils/update_cc_test_checks.py UTC_ARGS: --version 5
+// RUN: %clang_cc1 -triple riscv32 -target-feature +xcvmac -emit-llvm %s -o - \
+// RUN:     | FileCheck %s
+
+#include <stdint.h>
+#include <riscv_corev_mac.h>
+
+// CHECK-LABEL: define dso_local i32 @test_mac_mac(
+// CHECK-SAME: i32 noundef [[X:%.*]], i32 noundef [[Y:%.*]], i32 noundef [[Z:%.*]]) #[[ATTR0:[0-9]+]] {
+// CHECK-NEXT:  [[ENTRY:.*:]]
+// CHECK-NEXT:    [[A_ADDR_I:%.*]] = alloca i32, align 4
+// CHECK-NEXT:    [[B_ADDR_I:%.*]] = alloca i32, align 4
+// CHECK-NEXT:    [[C_ADDR_I:%.*]] = alloca i32, align 4
+// CHECK-NEXT:    [[X_ADDR:%.*]] = alloca i32, align 4
+// CHECK-NEXT:    [[Y_ADDR:%.*]] = alloca i32, align 4
+// CHECK-NEXT:    [[Z_ADDR:%.*]] = alloca i32, align 4
+// CHECK-NEXT:    store i32 [[X]], ptr [[X_ADDR]], align 4
+// CHECK-NEXT:    store i32 [[Y]], ptr [[Y_ADDR]], align 4
+// CHECK-NEXT:    store i32 [[Z]], ptr [[Z_ADDR]], align 4
+// CHECK-NEXT:    [[TMP0:%.*]] = load i32, ptr [[X_ADDR]], align 4
+// CHECK-NEXT:    [[TMP1:%.*]] = load i32, ptr [[Y_ADDR]], align 4
+// CHECK-NEXT:    [[TMP2:%.*]] = load i32, ptr [[Z_ADDR]], align 4
+// CHECK-NEXT:    store i32 [[TMP0]], ptr [[A_ADDR_I]], align 4
+// CHECK-NEXT:    store i32 [[TMP1]], ptr [[B_ADDR_I]], align 4
+// CHECK-NEXT:    store i32 [[TMP2]], ptr [[C_ADDR_I]], align 4
+// CHECK-NEXT:    [[TMP3:%.*]] = load i32, ptr [[A_ADDR_I]], align 4
+// CHECK-NEXT:    [[TMP4:%.*]] = load i32, ptr [[B_ADDR_I]], align 4
+// CHECK-NEXT:    [[TMP5:%.*]] = load i32, ptr [[C_ADDR_I]], align 4
+// CHECK-NEXT:    [[TMP6:%.*]] = call i32 @llvm.riscv.cv.mac.mac(i32 [[TMP3]], i32 [[TMP4]], i32 [[TMP5]])
+// CHECK-NEXT:    ret i32 [[TMP6]]
+//
+int32_t test_mac_mac(int32_t x, int32_t y, int32_t z) {
+    return __riscv_cv_mac_mac(x, y, z);
+}
+
+// CHECK-LABEL: define dso_local i32 @test_mac_msu(
+// CHECK-SAME: i32 noundef [[X:%.*]], i32 noundef [[Y:%.*]], i32 noundef [[Z:%.*]]) #[[ATTR0]] {
+// CHECK-NEXT:  [[ENTRY:.*:]]
+// CHECK-NEXT:    [[A_ADDR_I:%.*]] = alloca i32, align 4
+// CHECK-NEXT:    [[B_ADDR_I:%.*]] = alloca i32, align 4
+// CHECK-NEXT:    [[C_ADDR_I:%.*]] = alloca i32, align 4
+// CHECK-NEXT:    [[X_ADDR:%.*]] = alloca i32, align 4
+// CHECK-NEXT:    [[Y_ADDR:%.*]] = alloca i32, align 4
+// CHECK-NEXT:    [[Z_ADDR:%.*]] = alloca i32, align 4
+// CHECK-NEXT:    store i32 [[X]], ptr [[X_ADDR]], align 4
+// CHECK-NEXT:    store i32 [[Y]], ptr [[Y_ADDR]], align 4
+// CHECK-NEXT:    store i32 [[Z]], ptr [[Z_ADDR]], align 4
+// CHECK-NEXT:    [[TMP0:%.*]] = load i32, ptr [[X_ADDR]], align 4
+// CHECK-NEXT:    [[TMP1:%.*]] = load i32, ptr [[Y_ADDR]], align 4
+// CHECK-NEXT:    [[TMP2:%.*]] = load i32, ptr [[Z_ADDR]], align 4
+// CHECK-NEXT:    store i32 [[TMP0]], ptr [[A_ADDR_I]], align 4
+// CHECK-NEXT:    store i32 [[TMP1]], ptr [[B_ADDR_I]], align 4
+// CHECK-NEXT:    store i32 [[TMP2]], ptr [[C_ADDR_I]], align 4
+// CHECK-NEXT:    [[TMP3:%.*]] = load i32, ptr [[A_ADDR_I]], align 4
+// CHECK-NEXT:    [[TMP4:%.*]] = load i32, ptr [[B_ADDR_I]], align 4
+// CHECK-NEXT:    [[TMP5:%.*]] = load i32, ptr [[C_ADDR_I]], align 4
+// CHECK-NEXT:    [[TMP6:%.*]] = call i32 @llvm.riscv.cv.mac.msu(i32 [[TMP3]], i32 [[TMP4]], i32 [[TMP5]])
+// CHECK-NEXT:    ret i32 [[TMP6]]
+//
+int32_t test_mac_msu(int32_t x, int32_t y, int32_t z) {
+    return __riscv_cv_mac_msu(x, y, z);
+}
+
+// CHECK-LABEL: define dso_local i32 @test_mac_muluN(
+// CHECK-SAME: i32 noundef [[X:%.*]], i32 noundef [[Y:%.*]]) #[[ATTR0]] {
+// CHECK-NEXT:  [[ENTRY:.*:]]
+// CHECK-NEXT:    [[X_ADDR:%.*]] = alloca i32, align 4
+// CHECK-NEXT:    [[Y_ADDR:%.*]] = alloca i32, align 4
+// CHECK-NEXT:    store i32 [[X]], ptr [[X_ADDR]], align 4
+// CHECK-NEXT:    store i32 [[Y]], ptr [[Y_ADDR]], align 4
+// CHECK-NEXT:    [[TMP0:%.*]] = load i32, ptr [[X_ADDR]], align 4
+// CHECK-NEXT:    [[TMP1:%.*]] = load i32, ptr [[Y_ADDR]], align 4
+// CHECK-NEXT:    [[TMP2:%.*]] = call i32 @llvm.riscv.cv.mac.muluN(i32 [[TMP0]], i32 [[TMP1]], i32 0)
+// CHECK-NEXT:    ret i32 [[TMP2]]
+//
+uint32_t test_mac_muluN(uint32_t x, uint32_t y) {
+    return __riscv_cv_mac_muluN(x, y, 0);
+}
+
+// CHECK-LABEL: define dso_local i32 @test_mac_mulhhuN(
+// CHECK-SAME: i32 noundef [[X:%.*]], i32 noundef [[Y:%.*]]) #[[ATTR0]] {
+// CHECK-NEXT:  [[ENTRY:.*:]]
+// CHECK-NEXT:    [[X_ADDR:%.*]] = alloca i32, align 4
+// CHECK-NEXT:    [[Y_ADDR:%.*]] = alloca i32, align 4
+// CHECK-NEXT:    store i32 [[X]], ptr [[X_ADDR]], align 4
+// CHECK-NEXT:    store i32 [[Y]], ptr [[Y_ADDR]], align 4
+// CHECK-NEXT:    [[TMP0:%.*]] = load i32, ptr [[X_ADDR]], align 4
+// CHECK-NEXT:    [[TMP1:%.*]] = load i32, ptr [[Y_ADDR]], align 4
+// CHECK-NEXT:    [[TMP2:%.*]] = call i32 @llvm.riscv.cv.mac.mulhhuN(i32 [[TMP0]], i32 [[TMP1]], i32 0)
+// CHECK-NEXT:    ret i32 [[TMP2]]
+//
+uint32_t test_mac_mulhhuN(uint32_t x, uint32_t y) {
+    return __riscv_cv_mac_mulhhuN(x, y, 0);
+}
+
+// CHECK-LABEL: define dso_local i32 @test_mac_mulsN(
+// CHECK-SAME: i32 noundef [[X:%.*]], i32 noundef [[Y:%.*]]) #[[ATTR0]] {
+// CHECK-NEXT:  [[ENTRY:.*:]]
+// CHECK-NEXT:    [[X_ADDR:%.*]] = alloca i32, align 4
+// CHECK-NEXT:    [[Y_ADDR:%.*]] = alloca i32, align 4
+// CHECK-NEXT:    store i32 [[X]], ptr [[X_ADDR]], align 4
+// CHECK-NEXT:    store i32 [[Y]], ptr [[Y_ADDR]], align 4
+// CHECK-NEXT:    [[TMP0:%.*]] = load i32, ptr [[X_ADDR]], align 4
+// CHECK-NEXT:    [[TMP1:%.*]] = load i32, ptr [[Y_ADDR]], align 4
+// CHECK-NEXT:    [[TMP2:%.*]] = call i32 @llvm.riscv.cv.mac.mulsN(i32 [[TMP0]], i32 [[TMP1]], i32 0)
+// CHECK-NEXT:    ret i32 [[TMP2]]
+//
+int32_t test_mac_mulsN(uint32_t x, uint32_t y) {
+    return __riscv_cv_mac_mulsN(x, y, 0);
+}
+
+// CHECK-LABEL: define dso_local i32 @test_mac_mulhhsN(
+// CHECK-SAME: i32 noundef [[X:%.*]], i32 noundef [[Y:%.*]]) #[[ATTR0]] {
+// CHECK-NEXT:  [[ENTRY:.*:]]
+// CHECK-NEXT:    [[X_ADDR:%.*]] = alloca i32, align 4
+// CHECK-NEXT:    [[Y_ADDR:%.*]] = alloca i32, align 4
+// CHECK-NEXT:    store i32 [[X]], ptr [[X_ADDR]], align 4
+// CHECK-NEXT:    store i32 [[Y]], ptr [[Y_ADDR]], align 4
+// CHECK-NEXT:    [[TMP0:%.*]] = load i32, ptr [[X_ADDR]], align 4
+// CHECK-NEXT:    [[TMP1:%.*]] = load i32, ptr [[Y_ADDR]], align 4
+// CHECK-NEXT:    [[TMP2:%.*]] = call i32 @llvm.riscv.cv.mac.mulhhsN(i32 [[TMP0]], i32 [[TMP1]], i32 0)
+// CHECK-NEXT:    ret i32 [[TMP2]]
+//
+int32_t test_mac_mulhhsN(uint...
[truncated]

Copy link

github-actions bot commented Oct 1, 2024

✅ With the latest revision this PR passed the C/C++ code formatter.

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

Successfully merging this pull request may close these issues.

4 participants