diff --git a/clang/include/clang/Basic/BuiltinsRISCV.td b/clang/include/clang/Basic/BuiltinsRISCV.td index b2cd5648e008f..5927eaf80d57a 100644 --- a/clang/include/clang/Basic/BuiltinsRISCV.td +++ b/clang/include/clang/Basic/BuiltinsRISCV.td @@ -157,3 +157,8 @@ def pause : RISCVBuiltin<"void()">; // XCV extensions. //===----------------------------------------------------------------------===// include "clang/Basic/BuiltinsRISCVXCV.td" + +//===----------------------------------------------------------------------===// +// XAndes extensions. +//===----------------------------------------------------------------------===// +include "clang/Basic/BuiltinsRISCVXAndes.td" diff --git a/clang/include/clang/Basic/BuiltinsRISCVXAndes.td b/clang/include/clang/Basic/BuiltinsRISCVXAndes.td new file mode 100644 index 0000000000000..8ebcc18889d6c --- /dev/null +++ b/clang/include/clang/Basic/BuiltinsRISCVXAndes.td @@ -0,0 +1,29 @@ +//==- BuiltinsRISCVXAndes.td - RISC-V Andes Builtin database -----*- C++ -*-==// +// +// 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 +// +//===----------------------------------------------------------------------===// +// +// This file defines the Andes-specific builtin function database. Users of +// this file must define the BUILTIN macro to make use of this information. +// +//===----------------------------------------------------------------------===// + +class RISCVXAndesBuiltin : TargetBuiltin { + let Spellings = ["__builtin_riscv_nds_" # NAME]; + let Prototype = prototype; + let Features = features; +} + +let Attributes = [NoThrow, Const] in { +//===----------------------------------------------------------------------===// +// XAndesPerf extension. +//===----------------------------------------------------------------------===// + +def ffb : RISCVXAndesBuiltin<"long int(unsigned long int, unsigned long int)", "xandesperf">; +def ffzmism : RISCVXAndesBuiltin<"long int(unsigned long int, unsigned long int)", "xandesperf">; +def ffmism : RISCVXAndesBuiltin<"long int(unsigned long int, unsigned long int)", "xandesperf">; +def flmism : RISCVXAndesBuiltin<"long int(unsigned long int, unsigned long int)", "xandesperf">; +} // Attributes = [NoThrow, Const] diff --git a/clang/lib/CodeGen/TargetBuiltins/RISCV.cpp b/clang/lib/CodeGen/TargetBuiltins/RISCV.cpp index 89e3f6f203df3..48a497b32a4a6 100644 --- a/clang/lib/CodeGen/TargetBuiltins/RISCV.cpp +++ b/clang/lib/CodeGen/TargetBuiltins/RISCV.cpp @@ -413,6 +413,24 @@ Value *CodeGenFunction::EmitRISCVBuiltinExpr(unsigned BuiltinID, ID = Intrinsic::riscv_cv_alu_subuRN; break; + // XAndesPerf + case RISCV::BI__builtin_riscv_nds_ffb: + IntrinsicTypes = {ResultType}; + ID = Intrinsic::riscv_nds_ffb; + break; + case RISCV::BI__builtin_riscv_nds_ffzmism: + IntrinsicTypes = {ResultType}; + ID = Intrinsic::riscv_nds_ffzmism; + break; + case RISCV::BI__builtin_riscv_nds_ffmism: + IntrinsicTypes = {ResultType}; + ID = Intrinsic::riscv_nds_ffmism; + break; + case RISCV::BI__builtin_riscv_nds_flmism: + IntrinsicTypes = {ResultType}; + ID = Intrinsic::riscv_nds_flmism; + 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 c96d209c1fc0c..44e2d4b1174c0 100644 --- a/clang/lib/Headers/CMakeLists.txt +++ b/clang/lib/Headers/CMakeLists.txt @@ -126,6 +126,7 @@ set(ppc_htm_files set(riscv_files riscv_bitmanip.h riscv_corev_alu.h + riscv_nds.h riscv_crypto.h riscv_ntlh.h sifive_vector.h diff --git a/clang/lib/Headers/riscv_nds.h b/clang/lib/Headers/riscv_nds.h new file mode 100644 index 0000000000000..dcce943f59b71 --- /dev/null +++ b/clang/lib/Headers/riscv_nds.h @@ -0,0 +1,47 @@ +/*===---- riscv_nds.h - Andes 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_NDS_H +#define __RISCV_NDS_H + +#if defined(__cplusplus) +extern "C" { +#endif + +#if defined(__riscv_xandesperf) + +#define __DEFAULT_FN_ATTRS __attribute__((__always_inline__, __nodebug__)) + +static __inline__ long __DEFAULT_FN_ATTRS __riscv_nds_ffb(unsigned long a, + unsigned long b) { + return __builtin_riscv_nds_ffb(a, b); +} + +static __inline__ long __DEFAULT_FN_ATTRS __riscv_nds_ffzmism(unsigned long a, + unsigned long b) { + return __builtin_riscv_nds_ffzmism(a, b); +} + +static __inline__ long __DEFAULT_FN_ATTRS __riscv_nds_ffmism(unsigned long a, + unsigned long b) { + return __builtin_riscv_nds_ffmism(a, b); +} + +static __inline__ long __DEFAULT_FN_ATTRS __riscv_nds_flmism(unsigned long a, + unsigned long b) { + return __builtin_riscv_nds_flmism(a, b); +} + +#endif // defined(__riscv_nds) + +#if defined(__cplusplus) +} +#endif + +#endif // define __RISCV_NDS_H diff --git a/clang/test/CodeGen/RISCV/riscv-xandesperf-c-api.c b/clang/test/CodeGen/RISCV/riscv-xandesperf-c-api.c new file mode 100644 index 0000000000000..56a0dfacb80b5 --- /dev/null +++ b/clang/test/CodeGen/RISCV/riscv-xandesperf-c-api.c @@ -0,0 +1,65 @@ +// NOTE: Assertions have been autogenerated by utils/update_cc_test_checks.py +// RUN: %clang_cc1 -triple riscv32 -target-feature +xandesperf -emit-llvm %s -o - \ +// RUN: -disable-O0-optnone | opt -S -passes=mem2reg \ +// RUN: | FileCheck %s --check-prefix=CHECK-RV32 +// RUN: %clang_cc1 -triple riscv64 -target-feature +xandesperf -emit-llvm %s -o - \ +// RUN: -disable-O0-optnone | opt -S -passes=mem2reg \ +// RUN: | FileCheck %s --check-prefix=CHECK-RV64 + +#include + +// CHECK-RV32-LABEL: @test_ffb( +// CHECK-RV32-NEXT: entry: +// CHECK-RV32-NEXT: [[TMP0:%.*]] = call i32 @llvm.riscv.nds.ffb.i32(i32 [[A:%.*]], i32 [[B:%.*]]) +// CHECK-RV32-NEXT: ret i32 [[TMP0]] +// +// CHECK-RV64-LABEL: @test_ffb( +// CHECK-RV64-NEXT: entry: +// CHECK-RV64-NEXT: [[TMP0:%.*]] = call i64 @llvm.riscv.nds.ffb.i64(i64 [[A:%.*]], i64 [[B:%.*]]) +// CHECK-RV64-NEXT: ret i64 [[TMP0]] +// +long test_ffb(unsigned long a, unsigned long b) { + return __riscv_nds_ffb(a, b); +} + +// CHECK-RV32-LABEL: @test_ffzmism( +// CHECK-RV32-NEXT: entry: +// CHECK-RV32-NEXT: [[TMP0:%.*]] = call i32 @llvm.riscv.nds.ffzmism.i32(i32 [[A:%.*]], i32 [[B:%.*]]) +// CHECK-RV32-NEXT: ret i32 [[TMP0]] +// +// CHECK-RV64-LABEL: @test_ffzmism( +// CHECK-RV64-NEXT: entry: +// CHECK-RV64-NEXT: [[TMP0:%.*]] = call i64 @llvm.riscv.nds.ffzmism.i64(i64 [[A:%.*]], i64 [[B:%.*]]) +// CHECK-RV64-NEXT: ret i64 [[TMP0]] +// +long test_ffzmism(unsigned long a, unsigned long b) { + return __riscv_nds_ffzmism(a, b); +} + +// CHECK-RV32-LABEL: @test_ffmism( +// CHECK-RV32-NEXT: entry: +// CHECK-RV32-NEXT: [[TMP0:%.*]] = call i32 @llvm.riscv.nds.ffmism.i32(i32 [[A:%.*]], i32 [[B:%.*]]) +// CHECK-RV32-NEXT: ret i32 [[TMP0]] +// +// CHECK-RV64-LABEL: @test_ffmism( +// CHECK-RV64-NEXT: entry: +// CHECK-RV64-NEXT: [[TMP0:%.*]] = call i64 @llvm.riscv.nds.ffmism.i64(i64 [[A:%.*]], i64 [[B:%.*]]) +// CHECK-RV64-NEXT: ret i64 [[TMP0]] +// +long test_ffmism(unsigned long a, unsigned long b) { + return __riscv_nds_ffmism(a, b); +} + +// CHECK-RV32-LABEL: @test_flmism( +// CHECK-RV32-NEXT: entry: +// CHECK-RV32-NEXT: [[TMP0:%.*]] = call i32 @llvm.riscv.nds.flmism.i32(i32 [[A:%.*]], i32 [[B:%.*]]) +// CHECK-RV32-NEXT: ret i32 [[TMP0]] +// +// CHECK-RV64-LABEL: @test_flmism( +// CHECK-RV64-NEXT: entry: +// CHECK-RV64-NEXT: [[TMP0:%.*]] = call i64 @llvm.riscv.nds.flmism.i64(i64 [[A:%.*]], i64 [[B:%.*]]) +// CHECK-RV64-NEXT: ret i64 [[TMP0]] +// +long test_flmism(unsigned long a, unsigned long b) { + return __riscv_nds_flmism(a, b); +} diff --git a/clang/test/CodeGen/RISCV/riscv-xandesperf.c b/clang/test/CodeGen/RISCV/riscv-xandesperf.c new file mode 100644 index 0000000000000..4946c14709c80 --- /dev/null +++ b/clang/test/CodeGen/RISCV/riscv-xandesperf.c @@ -0,0 +1,63 @@ +// NOTE: Assertions have been autogenerated by utils/update_cc_test_checks.py +// RUN: %clang_cc1 -triple riscv32 -target-feature +xandesperf -emit-llvm %s -o - \ +// RUN: -disable-O0-optnone | opt -S -passes=mem2reg \ +// RUN: | FileCheck %s --check-prefix=CHECK-RV32 +// RUN: %clang_cc1 -triple riscv64 -target-feature +xandesperf -emit-llvm %s -o - \ +// RUN: -disable-O0-optnone | opt -S -passes=mem2reg \ +// RUN: | FileCheck %s --check-prefix=CHECK-RV64 + +// CHECK-RV32-LABEL: @test_ffb( +// CHECK-RV32-NEXT: entry: +// CHECK-RV32-NEXT: [[TMP0:%.*]] = call i32 @llvm.riscv.nds.ffb.i32(i32 [[A:%.*]], i32 [[B:%.*]]) +// CHECK-RV32-NEXT: ret i32 [[TMP0]] +// +// CHECK-RV64-LABEL: @test_ffb( +// CHECK-RV64-NEXT: entry: +// CHECK-RV64-NEXT: [[TMP0:%.*]] = call i64 @llvm.riscv.nds.ffb.i64(i64 [[A:%.*]], i64 [[B:%.*]]) +// CHECK-RV64-NEXT: ret i64 [[TMP0]] +// +long test_ffb(unsigned long a, unsigned long b) { + return __builtin_riscv_nds_ffb(a, b); +} + +// CHECK-RV32-LABEL: @test_ffzmism( +// CHECK-RV32-NEXT: entry: +// CHECK-RV32-NEXT: [[TMP0:%.*]] = call i32 @llvm.riscv.nds.ffzmism.i32(i32 [[A:%.*]], i32 [[B:%.*]]) +// CHECK-RV32-NEXT: ret i32 [[TMP0]] +// +// CHECK-RV64-LABEL: @test_ffzmism( +// CHECK-RV64-NEXT: entry: +// CHECK-RV64-NEXT: [[TMP0:%.*]] = call i64 @llvm.riscv.nds.ffzmism.i64(i64 [[A:%.*]], i64 [[B:%.*]]) +// CHECK-RV64-NEXT: ret i64 [[TMP0]] +// +long test_ffzmism(unsigned long a, unsigned long b) { + return __builtin_riscv_nds_ffzmism(a, b); +} + +// CHECK-RV32-LABEL: @test_ffmism( +// CHECK-RV32-NEXT: entry: +// CHECK-RV32-NEXT: [[TMP0:%.*]] = call i32 @llvm.riscv.nds.ffmism.i32(i32 [[A:%.*]], i32 [[B:%.*]]) +// CHECK-RV32-NEXT: ret i32 [[TMP0]] +// +// CHECK-RV64-LABEL: @test_ffmism( +// CHECK-RV64-NEXT: entry: +// CHECK-RV64-NEXT: [[TMP0:%.*]] = call i64 @llvm.riscv.nds.ffmism.i64(i64 [[A:%.*]], i64 [[B:%.*]]) +// CHECK-RV64-NEXT: ret i64 [[TMP0]] +// +long test_ffmism(unsigned long a, unsigned long b) { + return __builtin_riscv_nds_ffmism(a, b); +} + +// CHECK-RV32-LABEL: @test_flmism( +// CHECK-RV32-NEXT: entry: +// CHECK-RV32-NEXT: [[TMP0:%.*]] = call i32 @llvm.riscv.nds.flmism.i32(i32 [[A:%.*]], i32 [[B:%.*]]) +// CHECK-RV32-NEXT: ret i32 [[TMP0]] +// +// CHECK-RV64-LABEL: @test_flmism( +// CHECK-RV64-NEXT: entry: +// CHECK-RV64-NEXT: [[TMP0:%.*]] = call i64 @llvm.riscv.nds.flmism.i64(i64 [[A:%.*]], i64 [[B:%.*]]) +// CHECK-RV64-NEXT: ret i64 [[TMP0]] +// +long test_flmism(unsigned long a, unsigned long b) { + return __builtin_riscv_nds_flmism(a, b); +} diff --git a/llvm/include/llvm/IR/IntrinsicsRISCVXAndes.td b/llvm/include/llvm/IR/IntrinsicsRISCVXAndes.td index 92a07e9a6a5d0..0fa7b4d60ace0 100644 --- a/llvm/include/llvm/IR/IntrinsicsRISCVXAndes.td +++ b/llvm/include/llvm/IR/IntrinsicsRISCVXAndes.td @@ -11,6 +11,20 @@ //===----------------------------------------------------------------------===// let TargetPrefix = "riscv" in { + // Andes Performance Extension + def int_riscv_nds_ffb : Intrinsic<[llvm_anyint_ty], + [LLVMMatchType<0>, LLVMMatchType<0>], + [IntrNoMem, IntrSpeculatable]>; + def int_riscv_nds_ffzmism : Intrinsic<[llvm_anyint_ty], + [LLVMMatchType<0>, LLVMMatchType<0>], + [IntrNoMem, IntrSpeculatable]>; + def int_riscv_nds_ffmism : Intrinsic<[llvm_anyint_ty], + [LLVMMatchType<0>, LLVMMatchType<0>], + [IntrNoMem, IntrSpeculatable]>; + def int_riscv_nds_flmism : Intrinsic<[llvm_anyint_ty], + [LLVMMatchType<0>, LLVMMatchType<0>], + [IntrNoMem, IntrSpeculatable]>; + // Andes Vector BFloat16 Conversion Extension def int_riscv_nds_vfwcvt_s_bf16 : RISCVConversionUnMasked; def int_riscv_nds_vfncvt_bf16_s : RISCVConversionUnMaskedRoundingMode; diff --git a/llvm/lib/Target/RISCV/RISCVInstrInfoXAndes.td b/llvm/lib/Target/RISCV/RISCVInstrInfoXAndes.td index f2a1866510ded..d54d934fe3ed4 100644 --- a/llvm/lib/Target/RISCV/RISCVInstrInfoXAndes.td +++ b/llvm/lib/Target/RISCV/RISCVInstrInfoXAndes.td @@ -642,6 +642,17 @@ def : Sh2AddPat; def : Sh3AddPat; } // Predicates = [HasVendorXAndesPerf, IsRV64] +let Predicates = [HasVendorXAndesPerf] in { +def : Pat<(XLenVT (int_riscv_nds_ffb (XLenVT GPR:$rs1), (XLenVT GPR:$rs2))), + (NDS_FFB GPR:$rs1, GPR:$rs2)>; +def : Pat<(XLenVT (int_riscv_nds_ffzmism (XLenVT GPR:$rs1), (XLenVT GPR:$rs2))), + (NDS_FFZMISM GPR:$rs1, GPR:$rs2)>; +def : Pat<(XLenVT (int_riscv_nds_ffmism (XLenVT GPR:$rs1), (XLenVT GPR:$rs2))), + (NDS_FFMISM GPR:$rs1, GPR:$rs2)>; +def : Pat<(XLenVT (int_riscv_nds_flmism (XLenVT GPR:$rs1), (XLenVT GPR:$rs2))), + (NDS_FLMISM GPR:$rs1, GPR:$rs2)>; +} // Predicates = [HasVendorXAndesPerf] + let Predicates = [HasVendorXAndesVBFHCvt] in { defm PseudoNDS_VFWCVT_S_BF16 : VPseudoVWCVT_S_BF16; defm PseudoNDS_VFNCVT_BF16_S : VPseudoVNCVT_BF16_S; diff --git a/llvm/test/CodeGen/RISCV/rv32xandesperf.ll b/llvm/test/CodeGen/RISCV/rv32xandesperf.ll index 5cabb8c53e261..4c8fd5617abc1 100644 --- a/llvm/test/CodeGen/RISCV/rv32xandesperf.ll +++ b/llvm/test/CodeGen/RISCV/rv32xandesperf.ll @@ -492,3 +492,50 @@ define i64 @sexti32_i64_2(i32 %a) { %1 = sext i32 %a to i64 ret i64 %1 } + +; NDS.FFB/NDS.FFZMISM/NDS.FFMISM/NDS.FLMISM + +declare i32 @llvm.riscv.nds.ffb.i32(i32, i32) +declare i32 @llvm.riscv.nds.ffzmism.i32(i32, i32) +declare i32 @llvm.riscv.nds.ffmism.i32(i32, i32) +declare i32 @llvm.riscv.nds.flmism.i32(i32, i32) + +define i32 @ffb(i32 %a, i32 %b) nounwind { +; CHECK-LABEL: ffb: +; CHECK: # %bb.0: # %entry +; CHECK-NEXT: nds.ffb a0, a0, a1 +; CHECK-NEXT: ret +entry: + %0 = call i32 @llvm.riscv.nds.ffb.i32(i32 %a, i32 %b) + ret i32 %0 +} + +define i32 @ffzmism(i32 %a, i32 %b) nounwind { +; CHECK-LABEL: ffzmism: +; CHECK: # %bb.0: # %entry +; CHECK-NEXT: nds.ffzmism a0, a0, a1 +; CHECK-NEXT: ret +entry: + %0 = call i32 @llvm.riscv.nds.ffzmism.i32(i32 %a, i32 %b) + ret i32 %0 +} + +define i32 @ffmism(i32 %a, i32 %b) nounwind { +; CHECK-LABEL: ffmism: +; CHECK: # %bb.0: # %entry +; CHECK-NEXT: nds.ffmism a0, a0, a1 +; CHECK-NEXT: ret +entry: + %0 = call i32 @llvm.riscv.nds.ffmism.i32(i32 %a, i32 %b) + ret i32 %0 +} + +define i32 @flmism(i32 %a, i32 %b) nounwind { +; CHECK-LABEL: flmism: +; CHECK: # %bb.0: # %entry +; CHECK-NEXT: nds.flmism a0, a0, a1 +; CHECK-NEXT: ret +entry: + %0 = call i32 @llvm.riscv.nds.flmism.i32(i32 %a, i32 %b) + ret i32 %0 +} diff --git a/llvm/test/CodeGen/RISCV/rv64xandesperf.ll b/llvm/test/CodeGen/RISCV/rv64xandesperf.ll index 98cda42665169..09815b81c1a48 100644 --- a/llvm/test/CodeGen/RISCV/rv64xandesperf.ll +++ b/llvm/test/CodeGen/RISCV/rv64xandesperf.ll @@ -389,3 +389,50 @@ define i64 @sexti32_i64_2(i32 signext %a) { %1 = sext i32 %a to i64 ret i64 %1 } + +; NDS.FFB/NDS.FFZMISM/NDS.FFMISM/NDS.FLMISM + +declare i64 @llvm.riscv.nds.ffb.i64(i64, i64) +declare i64 @llvm.riscv.nds.ffzmism.i64(i64, i64) +declare i64 @llvm.riscv.nds.ffmism.i64(i64, i64) +declare i64 @llvm.riscv.nds.flmism.i64(i64, i64) + +define i64 @ffb(i64 %a, i64 %b) nounwind { +; CHECK-LABEL: ffb: +; CHECK: # %bb.0: # %entry +; CHECK-NEXT: nds.ffb a0, a0, a1 +; CHECK-NEXT: ret +entry: + %0 = call i64 @llvm.riscv.nds.ffb.i64(i64 %a, i64 %b) + ret i64 %0 +} + +define i64 @ffzmism(i64 %a, i64 %b) nounwind { +; CHECK-LABEL: ffzmism: +; CHECK: # %bb.0: # %entry +; CHECK-NEXT: nds.ffzmism a0, a0, a1 +; CHECK-NEXT: ret +entry: + %0 = call i64 @llvm.riscv.nds.ffzmism.i64(i64 %a, i64 %b) + ret i64 %0 +} + +define i64 @ffmism(i64 %a, i64 %b) nounwind { +; CHECK-LABEL: ffmism: +; CHECK: # %bb.0: # %entry +; CHECK-NEXT: nds.ffmism a0, a0, a1 +; CHECK-NEXT: ret +entry: + %0 = call i64 @llvm.riscv.nds.ffmism.i64(i64 %a, i64 %b) + ret i64 %0 +} + +define i64 @flmism(i64 %a, i64 %b) nounwind { +; CHECK-LABEL: flmism: +; CHECK: # %bb.0: # %entry +; CHECK-NEXT: nds.flmism a0, a0, a1 +; CHECK-NEXT: ret +entry: + %0 = call i64 @llvm.riscv.nds.flmism.i64(i64 %a, i64 %b) + ret i64 %0 +}