Skip to content

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

@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 IR generation bugs: mangling, exceptions, etc. labels Oct 1, 2024
@llvmbot
Copy link
Member

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
Member

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
Member

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] 
@github-actions
Copy link

github-actions bot commented Oct 1, 2024

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

@realqhc realqhc force-pushed the xcvmac-clang-builtins branch from a84b749 to 5a08917 Compare October 1, 2024 04:02
@realqhc realqhc force-pushed the xcvmac-clang-builtins branch from 974262e to accf9db Compare September 5, 2025 04:54
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 IR generation bugs: mangling, exceptions, etc. 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

4 participants