From 4289f9882e27439f36c2dae158e8f0261c4a4e23 Mon Sep 17 00:00:00 2001 From: Philipp Krones <philipp.krones@embecosm.com> Date: Wed, 25 Nov 2020 12:20:29 +0000 Subject: [PATCH 1/4] [COREV][clang] Add information about the xcorev extensions This commit adds the `+xcorev*` target-feature flags to clang. Signed-off-by: Philipp Krones <philipp.krones@embecosm.com> --- clang/lib/Basic/Targets/RISCV.cpp | 18 ++++++++++++++++++ clang/lib/Basic/Targets/RISCV.h | 3 +++ clang/lib/Driver/ToolChains/Arch/RISCV.cpp | 8 +++++++- clang/test/Driver/riscv-arch.c | 16 ++++++++++++++++ 4 files changed, 44 insertions(+), 1 deletion(-) diff --git a/clang/lib/Basic/Targets/RISCV.cpp b/clang/lib/Basic/Targets/RISCV.cpp index 5e17b7d51175..dd23fd7bd00e 100644 --- a/clang/lib/Basic/Targets/RISCV.cpp +++ b/clang/lib/Basic/Targets/RISCV.cpp @@ -129,6 +129,13 @@ void RISCVTargetInfo::getTargetDefines(const LangOptions &Opts, if (HasB) Builder.defineMacro("__riscv_bitmanip"); + + if (HasXCoreV) + Builder.defineMacro("__riscv_xcorev"); + if (HasXCoreVHwlp) + Builder.defineMacro("__riscv_xcorevhwlp"); + if (HasXCoreVMac) + Builder.defineMacro("__riscv_xcorevmac"); } /// Return true if has this feature, need to sync with handleTargetFeatures. @@ -144,6 +151,9 @@ bool RISCVTargetInfo::hasFeature(StringRef Feature) const { .Case("d", HasD) .Case("c", HasC) .Case("experimental-b", HasB) + .Case("xcorev", HasXCoreV) + .Case("xcorevhwlp", HasXCoreVHwlp) + .Case("xcorevmac", HasXCoreVMac) .Default(false); } @@ -163,6 +173,14 @@ bool RISCVTargetInfo::handleTargetFeatures(std::vector<std::string> &Features, HasC = true; else if (Feature == "+experimental-b") HasB = true; + else if (Feature == "+xcorev") { + HasXCoreV = true; + HasXCoreVHwlp = true; + HasXCoreVMac = true; + } else if (Feature == "+xcorevhwlp") + HasXCoreVHwlp = true; + else if (Feature == "+xcorevmac") + HasXCoreVMac = true; } return true; diff --git a/clang/lib/Basic/Targets/RISCV.h b/clang/lib/Basic/Targets/RISCV.h index a4e6777a11e2..ac6bf3412658 100644 --- a/clang/lib/Basic/Targets/RISCV.h +++ b/clang/lib/Basic/Targets/RISCV.h @@ -31,6 +31,9 @@ protected: bool HasD; bool HasC; bool HasB; + bool HasXCoreV; + bool HasXCoreVHwlp; + bool HasXCoreVMac; public: RISCVTargetInfo(const llvm::Triple &Triple, const TargetOptions &) diff --git a/clang/lib/Driver/ToolChains/Arch/RISCV.cpp b/clang/lib/Driver/ToolChains/Arch/RISCV.cpp index 7ca05a1f3a39..169ea73c02b2 100644 --- a/clang/lib/Driver/ToolChains/Arch/RISCV.cpp +++ b/clang/lib/Driver/ToolChains/Arch/RISCV.cpp @@ -67,12 +67,18 @@ isExperimentalExtension(StringRef Ext) { return None; } +static bool isSupportedNonStandardUserLevelExtension(StringRef Ext) { + return Ext == "xcorev" || Ext == "xcorevhwlp" || Ext == "xcorevmac"; +} + static bool isSupportedExtension(StringRef Ext) { // LLVM supports "z" extensions which are marked as experimental. if (isExperimentalExtension(Ext)) return true; + if (isSupportedNonStandardUserLevelExtension(Ext)) + return true; - // LLVM does not support "sx", "s" nor "x" extensions. + // LLVM does not support other "sx", "s", or "x" extensions. return false; } diff --git a/clang/test/Driver/riscv-arch.c b/clang/test/Driver/riscv-arch.c index 8b630b1846c9..3f972845cda8 100644 --- a/clang/test/Driver/riscv-arch.c +++ b/clang/test/Driver/riscv-arch.c @@ -383,3 +383,19 @@ // RUN: %clang -target riscv32-unknown-elf -march=rv32iv0p9 -menable-experimental-extensions -### %s -c 2>&1 | \ // RUN: FileCheck -check-prefix=RV32-EXPERIMENTAL-V-GOODVERS %s // RV32-EXPERIMENTAL-V-GOODVERS: "-target-feature" "+experimental-v" + +// RUN: %clang -target riscv32-unknown-elf -march=rv32ixcorevunsupported -### %s -c 2>&1 | \ +// RUN: FileCheck -check-prefix=RV32-XCOREV-UNKNOWN %s +// RV32-XCOREV-UNKNOWN: unsupported non-standard user-level extension 'xcorevunsupported' + +// RUN: %clang -target riscv32-unknown-elf -march=rv32ixcorev -### %s -c 2>&1 | \ +// RUN: FileCheck -check-prefix=RV32-XCOREV %s +// RV32-XCOREV: "-target-feature" "+xcorev" + +// RUN: %clang -target riscv32-unknown-elf -march=rv32ixcorevhwlp -### %s -c 2>&1 | \ +// RUN: FileCheck -check-prefix=RV32-XCOREVHWLP %s +// RV32-XCOREVHWLP: "-target-feature" "+xcorevhwlp" + +// RUN: %clang -target riscv32-unknown-elf -march=rv32ixcorevmac -### %s -c 2>&1 | \ +// RUN: FileCheck -check-prefix=RV32-XCOREVMAC %s +// RV32-XCOREVMAC: "-target-feature" "+xcorevmac" -- GitLab From 2752ebca844e6245ad0fdde85fd3c19a92093d4a Mon Sep 17 00:00:00 2001 From: Philipp Krones <philipp.krones@embecosm.com> Date: Mon, 11 Jan 2021 16:10:06 +0000 Subject: [PATCH 2/4] [COREV][clang] Add test for MAC builtins Signed-off-by: Philipp Krones <philipp.krones@embecosm.com> --- clang/test/CodeGen/builtins-corev.c | 133 ++++++++++++++++++++++++++++ 1 file changed, 133 insertions(+) create mode 100644 clang/test/CodeGen/builtins-corev.c diff --git a/clang/test/CodeGen/builtins-corev.c b/clang/test/CodeGen/builtins-corev.c new file mode 100644 index 000000000000..73733876eb67 --- /dev/null +++ b/clang/test/CodeGen/builtins-corev.c @@ -0,0 +1,133 @@ +// RUN: %clang_cc1 -triple riscv32 -target-feature +xcorevmac -emit-llvm -o - %s | FileCheck %s + +int test_corev_mac(int dest, int src1, int src2) { + // CHECK: %3 = call i32 @llvm.riscv.cv.mac(i32 %0, i32 %1, i32 %2) + dest = __builtin_corev_mac(dest, src1, src2); + return dest; +} + +int test_corev_msu(int dest, int src1, int src2) { + // CHECK: %3 = call i32 @llvm.riscv.cv.msu(i32 %0, i32 %1, i32 %2) + dest = __builtin_corev_msu(dest, src1, src2); + return dest; +} + +int test_corev_muls(int dest, short src1, short src2) { + // CHECK: %2 = call i32 @llvm.riscv.cv.muls(i16 %0, i16 %1) + dest = __builtin_corev_muls(src1, src2); + return dest; +} + +int test_corev_mulhhs(int dest, int src1, int src2) { + // CHECK: %2 = call i32 @llvm.riscv.cv.mulhhs(i32 %0, i32 %1) + dest = __builtin_corev_mulhhs(src1, src2); + return dest; +} + +int test_corev_mulsn(int dest, short src1, short src2) { + // CHECK: %2 = call i32 @llvm.riscv.cv.mulsn(i16 %0, i16 %1, i16 0) + dest = __builtin_corev_mulsn(src1, src2, 0); + return dest; +} + +int test_corev_mulhhsn(int dest, int src1, int src2) { + // CHECK: %2 = call i32 @llvm.riscv.cv.mulhhsn(i32 %0, i32 %1, i16 0) + dest = __builtin_corev_mulhhsn(src1, src2, 0); + return dest; +} + +int test_corev_mulsrn(int dest, short src1, short src2) { + // CHECK: %2 = call i32 @llvm.riscv.cv.mulsrn(i16 %0, i16 %1, i16 0) + dest = __builtin_corev_mulsrn(src1, src2, 0); + return dest; +} + +int test_corev_mulhhsrn(int dest, int src1, int src2) { + // CHECK: %2 = call i32 @llvm.riscv.cv.mulhhsrn(i32 %0, i32 %1, i16 0) + dest = __builtin_corev_mulhhsrn(src1, src2, 0); + return dest; +} + +int test_corev_mulu(int dest, short src1, short src2) { + // CHECK: %2 = call i32 @llvm.riscv.cv.mulu(i16 %0, i16 %1) + dest = __builtin_corev_mulu(src1, src2); + return dest; +} + +int test_corev_mulhhu(int dest, int src1, int src2) { + // CHECK: %2 = call i32 @llvm.riscv.cv.mulhhu(i32 %0, i32 %1) + dest = __builtin_corev_mulhhu(src1, src2); + return dest; +} + +int test_corev_mulun(int dest, short src1, short src2) { + // CHECK: %2 = call i32 @llvm.riscv.cv.mulun(i16 %0, i16 %1, i16 0) + dest = __builtin_corev_mulun(src1, src2, 0); + return dest; +} + +int test_corev_mulhhun(int dest, int src1, int src2) { + // CHECK: %2 = call i32 @llvm.riscv.cv.mulhhun(i32 %0, i32 %1, i16 0) + dest = __builtin_corev_mulhhun(src1, src2, 0); + return dest; +} + +int test_corev_mulurn(int dest, short src1, short src2) { + // CHECK: %2 = call i32 @llvm.riscv.cv.mulurn(i16 %0, i16 %1, i16 0) + dest = __builtin_corev_mulurn(src1, src2, 0); + return dest; +} + +int test_corev_mulhhurn(int dest, int src1, int src2) { + // CHECK: %2 = call i32 @llvm.riscv.cv.mulhhurn(i32 %0, i32 %1, i16 0) + dest = __builtin_corev_mulhhurn(src1, src2, 0); + return dest; +} + +int test_corev_macsn(int dest, short src1, short src2) { + // CHECK: %3 = call i32 @llvm.riscv.cv.macsn(i32 %0, i16 %1, i16 %2, i16 0) + dest = __builtin_corev_macsn(dest, src1, src2, 0); + return dest; +} + +int test_corev_machhsn(int dest, int src1, int src2) { + // CHECK: %3 = call i32 @llvm.riscv.cv.machhsn(i32 %0, i32 %1, i32 %2, i16 0) + dest = __builtin_corev_machhsn(dest, src1, src2, 0); + return dest; +} + +int test_corev_macsrn(int dest, short src1, short src2) { + // CHECK: %3 = call i32 @llvm.riscv.cv.macsrn(i32 %0, i16 %1, i16 %2, i16 0) + dest = __builtin_corev_macsrn(dest, src1, src2, 0); + return dest; +} + +int test_corev_machhsrn(int dest, int src1, int src2) { + // CHECK: %3 = call i32 @llvm.riscv.cv.machhsrn(i32 %0, i32 %1, i32 %2, i16 0) + dest = __builtin_corev_machhsrn(dest, src1, src2, 0); + return dest; +} + +int test_corev_macun(int dest, short src1, short src2) { + // CHECK: %3 = call i32 @llvm.riscv.cv.macun(i32 %0, i16 %1, i16 %2, i16 0) + dest = __builtin_corev_macun(dest, src1, src2, 0); + return dest; +} + +int test_corev_machhun(int dest, int src1, int src2) { + // CHECK: %3 = call i32 @llvm.riscv.cv.machhun(i32 %0, i32 %1, i32 %2, i16 0) + dest = __builtin_corev_machhun(dest, src1, src2, 0); + return dest; +} + +int test_corev_macurn(int dest, short src1, short src2) { + // CHECK: %3 = call i32 @llvm.riscv.cv.macurn(i32 %0, i16 %1, i16 %2, i16 0) + dest = __builtin_corev_macurn(dest, src1, src2, 0); + return dest; +} + +int test_corev_machhurn(int dest, int src1, int src2) { + // CHECK: %3 = call i32 @llvm.riscv.cv.machhurn(i32 %0, i32 %1, i32 %2, i16 0) + dest = __builtin_corev_machhurn(dest, src1, src2, 0); + return dest; +} -- GitLab From e0405383ae915ed16b5bc96e766da0eb03174abf Mon Sep 17 00:00:00 2001 From: Philipp Krones <philipp.krones@embecosm.com> Date: Mon, 11 Jan 2021 16:12:03 +0000 Subject: [PATCH 3/4] [COREV] Add information about MAC builtins This adds the information about the builtins to clang and LLVM. This does not yet lower them to the mac instructions. Signed-off-by: Philipp Krones <philipp.krones@embecosm.com> --- clang/include/clang/Basic/BuiltinsRISCV.def | 45 ++++++++++++ clang/include/clang/Basic/TargetBuiltins.h | 12 ++- clang/include/clang/module.modulemap | 1 + clang/lib/Basic/Targets/RISCV.cpp | 14 ++++ clang/lib/Basic/Targets/RISCV.h | 3 +- llvm/include/llvm/IR/IntrinsicsRISCV.td | 81 +++++++++++++++++++++ 6 files changed, 154 insertions(+), 2 deletions(-) create mode 100644 clang/include/clang/Basic/BuiltinsRISCV.def diff --git a/clang/include/clang/Basic/BuiltinsRISCV.def b/clang/include/clang/Basic/BuiltinsRISCV.def new file mode 100644 index 000000000000..f11dfe6990af --- /dev/null +++ b/clang/include/clang/Basic/BuiltinsRISCV.def @@ -0,0 +1,45 @@ +//=== BuiltinsSystemRISCV.def - RISCV Builtin function 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 RISCV-specific builtin function database. Users of +// this file must define the BUILTIN macro to make use of this information. +// +//===----------------------------------------------------------------------===// + +// The format of this database matches clang/Basic/Builtins.def. + +#if defined(BUILTIN) && !defined(TARGET_BUILTIN) +# define TARGET_BUILTIN(ID, TYPE, ATTRS, FEATURE) BUILTIN(ID, TYPE, ATTRS) +#endif + +TARGET_BUILTIN(__builtin_corev_mac, "iiii", "", "xcorevmac") +TARGET_BUILTIN(__builtin_corev_msu, "iiii", "", "xcorevmac") + +TARGET_BUILTIN(__builtin_corev_muls, "iss", "", "xcorevmac") +TARGET_BUILTIN(__builtin_corev_mulhhs, "iii", "", "xcorevmac") +TARGET_BUILTIN(__builtin_corev_mulsn, "issIs", "", "xcorevmac") +TARGET_BUILTIN(__builtin_corev_mulhhsn, "iiiIs", "", "xcorevmac") +TARGET_BUILTIN(__builtin_corev_mulsrn, "issIs", "", "xcorevmac") +TARGET_BUILTIN(__builtin_corev_mulhhsrn, "iiiIs", "", "xcorevmac") + +TARGET_BUILTIN(__builtin_corev_mulu, "iss", "", "xcorevmac") +TARGET_BUILTIN(__builtin_corev_mulhhu, "iii", "", "xcorevmac") +TARGET_BUILTIN(__builtin_corev_mulun, "issIs", "", "xcorevmac") +TARGET_BUILTIN(__builtin_corev_mulhhun, "iiiIs", "", "xcorevmac") +TARGET_BUILTIN(__builtin_corev_mulurn, "issIs", "", "xcorevmac") +TARGET_BUILTIN(__builtin_corev_mulhhurn, "iiiIs", "", "xcorevmac") + +TARGET_BUILTIN(__builtin_corev_macsn, "iissIs", "", "xcorevmac") +TARGET_BUILTIN(__builtin_corev_machhsn, "iiiiIs", "", "xcorevmac") +TARGET_BUILTIN(__builtin_corev_macsrn, "iissIs", "", "xcorevmac") +TARGET_BUILTIN(__builtin_corev_machhsrn, "iiiiIs", "", "xcorevmac") + +TARGET_BUILTIN(__builtin_corev_macun, "iissIs", "", "xcorevmac") +TARGET_BUILTIN(__builtin_corev_machhun, "iiiiIs", "", "xcorevmac") +TARGET_BUILTIN(__builtin_corev_macurn, "iissIs", "", "xcorevmac") +TARGET_BUILTIN(__builtin_corev_machhurn, "iiiiIs", "", "xcorevmac") diff --git a/clang/include/clang/Basic/TargetBuiltins.h b/clang/include/clang/Basic/TargetBuiltins.h index b472547012f0..2e831298d0a1 100644 --- a/clang/include/clang/Basic/TargetBuiltins.h +++ b/clang/include/clang/Basic/TargetBuiltins.h @@ -310,6 +310,16 @@ namespace clang { }; } + /// RISCV builtins + namespace RISCV { + enum { + LastTIBuiltin = clang::Builtin::FirstTSBuiltin-1, +#define BUILTIN(ID, TYPE, ATTRS) BI##ID, +#include "clang/Basic/BuiltinsRISCV.def" + LastTSBuiltin + }; + } + /// WebAssembly builtins namespace WebAssembly { enum { @@ -326,7 +336,7 @@ namespace clang { NVPTX::LastTSBuiltin, AMDGPU::LastTSBuiltin, X86::LastTSBuiltin, Hexagon::LastTSBuiltin, Mips::LastTSBuiltin, XCore::LastTSBuiltin, Le64::LastTSBuiltin, SystemZ::LastTSBuiltin, - WebAssembly::LastTSBuiltin}); + WebAssembly::LastTSBuiltin, RISCV::LastTSBuiltin}); } // end namespace clang. diff --git a/clang/include/clang/module.modulemap b/clang/include/clang/module.modulemap index 332e533f0347..d597cd763086 100644 --- a/clang/include/clang/module.modulemap +++ b/clang/include/clang/module.modulemap @@ -45,6 +45,7 @@ module Clang_Basic { textual header "Basic/BuiltinsNEON.def" textual header "Basic/BuiltinsNVPTX.def" textual header "Basic/BuiltinsPPC.def" + textual header "Basic/BuiltinsRISCV.def" textual header "Basic/BuiltinsSVE.def" textual header "Basic/BuiltinsSystemZ.def" textual header "Basic/BuiltinsWebAssembly.def" diff --git a/clang/lib/Basic/Targets/RISCV.cpp b/clang/lib/Basic/Targets/RISCV.cpp index dd23fd7bd00e..3ad0e2b7b8ff 100644 --- a/clang/lib/Basic/Targets/RISCV.cpp +++ b/clang/lib/Basic/Targets/RISCV.cpp @@ -12,12 +12,21 @@ #include "RISCV.h" #include "clang/Basic/MacroBuilder.h" +#include "clang/Basic/TargetBuiltins.h" #include "llvm/ADT/StringSwitch.h" #include "llvm/Support/TargetParser.h" using namespace clang; using namespace clang::targets; +const Builtin::Info RISCVTargetInfo::BuiltinInfo[] = { +#define BUILTIN(ID, TYPE, ATTRS) \ + {#ID, TYPE, ATTRS, nullptr, ALL_LANGUAGES, nullptr}, +#define TARGET_BUILTIN(ID, TYPE, ATTRS, FEATURE) \ + {#ID, TYPE, ATTRS, nullptr, ALL_LANGUAGES, FEATURE}, +#include "clang/Basic/BuiltinsRISCV.def" +}; + ArrayRef<const char *> RISCVTargetInfo::getGCCRegNames() const { static const char *const GCCRegNames[] = { // Integer registers @@ -138,6 +147,11 @@ void RISCVTargetInfo::getTargetDefines(const LangOptions &Opts, Builder.defineMacro("__riscv_xcorevmac"); } +ArrayRef<Builtin::Info> RISCVTargetInfo::getTargetBuiltins() const { + return llvm::makeArrayRef(BuiltinInfo, clang::RISCV::LastTSBuiltin - + Builtin::FirstTSBuiltin); +} + /// Return true if has this feature, need to sync with handleTargetFeatures. bool RISCVTargetInfo::hasFeature(StringRef Feature) const { bool Is64Bit = getTriple().getArch() == llvm::Triple::riscv64; diff --git a/clang/lib/Basic/Targets/RISCV.h b/clang/lib/Basic/Targets/RISCV.h index ac6bf3412658..b0b873083430 100644 --- a/clang/lib/Basic/Targets/RISCV.h +++ b/clang/lib/Basic/Targets/RISCV.h @@ -24,6 +24,7 @@ namespace targets { // RISC-V Target class RISCVTargetInfo : public TargetInfo { protected: + static const Builtin::Info BuiltinInfo[]; std::string ABI, CPU; bool HasM; bool HasA; @@ -58,7 +59,7 @@ public: void getTargetDefines(const LangOptions &Opts, MacroBuilder &Builder) const override; - ArrayRef<Builtin::Info> getTargetBuiltins() const override { return None; } + ArrayRef<Builtin::Info> getTargetBuiltins() const override; BuiltinVaListKind getBuiltinVaListKind() const override { return TargetInfo::VoidPtrBuiltinVaList; diff --git a/llvm/include/llvm/IR/IntrinsicsRISCV.td b/llvm/include/llvm/IR/IntrinsicsRISCV.td index 7590b568c367..9c00757a665a 100644 --- a/llvm/include/llvm/IR/IntrinsicsRISCV.td +++ b/llvm/include/llvm/IR/IntrinsicsRISCV.td @@ -66,3 +66,84 @@ let TargetPrefix = "riscv" in { defm int_riscv_masked_cmpxchg : MaskedAtomicRMWFiveArgIntrinsics; } // TargetPrefix = "riscv" + +// CORE-V instrinsics +let TargetPrefix = "riscv" in { + class CoreVBuiltin<string name, + LLVMType ret_type, + list<LLVMType> param_types, + list<IntrinsicProperty> intr_properties> + : GCCBuiltin<"__builtin_corev_" # name>, + Intrinsic<[ret_type], param_types, intr_properties>; + + def int_riscv_cv_mac : CoreVBuiltin<"mac", llvm_i32_ty, + [llvm_i32_ty, llvm_i32_ty, llvm_i32_ty], + [IntrNoMem, Returned<ArgIndex<0>>]>; + def int_riscv_cv_msu : CoreVBuiltin<"msu", llvm_i32_ty, + [llvm_i32_ty, llvm_i32_ty, llvm_i32_ty], + [IntrNoMem, Returned<ArgIndex<0>>]>; + + def int_riscv_cv_muls : CoreVBuiltin<"muls", llvm_i32_ty, + [llvm_i16_ty, llvm_i16_ty], + [IntrNoMem]>; + def int_riscv_cv_mulhhs : CoreVBuiltin<"mulhhs", llvm_i32_ty, + [llvm_i32_ty, llvm_i32_ty], + [IntrNoMem]>; + def int_riscv_cv_mulsn : CoreVBuiltin<"mulsn", llvm_i32_ty, + [llvm_i16_ty, llvm_i16_ty, llvm_i16_ty], + [IntrNoMem, ImmArg<ArgIndex<2>>]>; + def int_riscv_cv_mulhhsn : CoreVBuiltin<"mulhhsn", llvm_i32_ty, + [llvm_i32_ty, llvm_i32_ty, llvm_i16_ty], + [IntrNoMem, ImmArg<ArgIndex<2>>]>; + def int_riscv_cv_mulsrn : CoreVBuiltin<"mulsrn", llvm_i32_ty, + [llvm_i16_ty, llvm_i16_ty, llvm_i16_ty], + [IntrNoMem, ImmArg<ArgIndex<2>>]>; + def int_riscv_cv_mulhhsrn : CoreVBuiltin<"mulhhsrn", llvm_i32_ty, + [llvm_i32_ty, llvm_i32_ty, llvm_i16_ty], + [IntrNoMem, ImmArg<ArgIndex<2>>]>; + + def int_riscv_cv_mulu : CoreVBuiltin<"mulu", llvm_i32_ty, + [llvm_i16_ty, llvm_i16_ty], + [IntrNoMem]>; + def int_riscv_cv_mulhhu : CoreVBuiltin<"mulhhu", llvm_i32_ty, + [llvm_i32_ty, llvm_i32_ty], + [IntrNoMem]>; + def int_riscv_cv_mulun : CoreVBuiltin<"mulun", llvm_i32_ty, + [llvm_i16_ty, llvm_i16_ty, llvm_i16_ty], + [IntrNoMem, ImmArg<ArgIndex<2>>]>; + def int_riscv_cv_mulhhun : CoreVBuiltin<"mulhhun", llvm_i32_ty, + [llvm_i32_ty, llvm_i32_ty, llvm_i16_ty], + [IntrNoMem, ImmArg<ArgIndex<2>>]>; + def int_riscv_cv_mulurn : CoreVBuiltin<"mulurn", llvm_i32_ty, + [llvm_i16_ty, llvm_i16_ty, llvm_i16_ty], + [IntrNoMem, ImmArg<ArgIndex<2>>]>; + def int_riscv_cv_mulhhurn : CoreVBuiltin<"mulhhurn", llvm_i32_ty, + [llvm_i32_ty, llvm_i32_ty, llvm_i16_ty], + [IntrNoMem, ImmArg<ArgIndex<2>>]>; + + def int_riscv_cv_macsn : CoreVBuiltin<"macsn", llvm_i32_ty, + [llvm_i32_ty, llvm_i16_ty, llvm_i16_ty, llvm_i16_ty], + [IntrNoMem, Returned<ArgIndex<0>>, ImmArg<ArgIndex<3>>]>; + def int_riscv_cv_machhsn : CoreVBuiltin<"machhsn", llvm_i32_ty, + [llvm_i32_ty, llvm_i32_ty, llvm_i32_ty, llvm_i16_ty], + [IntrNoMem, Returned<ArgIndex<0>>, ImmArg<ArgIndex<3>>]>; + def int_riscv_cv_macsrn : CoreVBuiltin<"macsrn", llvm_i32_ty, + [llvm_i32_ty, llvm_i16_ty, llvm_i16_ty, llvm_i16_ty], + [IntrNoMem, Returned<ArgIndex<0>>, ImmArg<ArgIndex<3>>]>; + def int_riscv_cv_machhsrn : CoreVBuiltin<"machhsrn", llvm_i32_ty, + [llvm_i32_ty, llvm_i32_ty, llvm_i32_ty, llvm_i16_ty], + [IntrNoMem, Returned<ArgIndex<0>>, ImmArg<ArgIndex<3>>]>; + + def int_riscv_cv_macun : CoreVBuiltin<"macun", llvm_i32_ty, + [llvm_i32_ty, llvm_i16_ty, llvm_i16_ty, llvm_i16_ty], + [IntrNoMem, Returned<ArgIndex<0>>, ImmArg<ArgIndex<3>>]>; + def int_riscv_cv_machhun : CoreVBuiltin<"machhun", llvm_i32_ty, + [llvm_i32_ty, llvm_i32_ty, llvm_i32_ty, llvm_i16_ty], + [IntrNoMem, Returned<ArgIndex<0>>, ImmArg<ArgIndex<3>>]>; + def int_riscv_cv_macurn : CoreVBuiltin<"macurn", llvm_i32_ty, + [llvm_i32_ty, llvm_i16_ty, llvm_i16_ty, llvm_i16_ty], + [IntrNoMem, Returned<ArgIndex<0>>, ImmArg<ArgIndex<3>>]>; + def int_riscv_cv_machhurn : CoreVBuiltin<"machhurn", llvm_i32_ty, + [llvm_i32_ty, llvm_i32_ty, llvm_i32_ty, llvm_i16_ty], + [IntrNoMem, Returned<ArgIndex<0>>, ImmArg<ArgIndex<3>>]>; +} -- GitLab From 2f89219d2205612f39b1501401d8bb669eda19e0 Mon Sep 17 00:00:00 2001 From: Philipp Krones <philipp.krones@embecosm.com> Date: Mon, 11 Jan 2021 16:13:33 +0000 Subject: [PATCH 4/4] [COREV] Correctly lower MAC intrinsics to the MAC instructions One the one hand this deals with the type legalization for the builtins, which partly have `i16` as input types. On the other hand it implements custom lowering of those builtins to the instruction. The custom lowering has to be used, because patterns in tablegen files are not powerful enough to represent the type conversions. Signed-off-by: Philipp Krones <philipp.krones@embecosm.com> --- llvm/lib/Target/RISCV/RISCVISelDAGToDAG.cpp | 74 ++++++++++++++++++++ llvm/lib/Target/RISCV/RISCVISelLowering.cpp | 41 +++++++++++ llvm/lib/Target/RISCV/RISCVInstrInfoCOREV.td | 12 ++-- 3 files changed, 123 insertions(+), 4 deletions(-) diff --git a/llvm/lib/Target/RISCV/RISCVISelDAGToDAG.cpp b/llvm/lib/Target/RISCV/RISCVISelDAGToDAG.cpp index 3cb710dbf4e9..091e8e0bdfc5 100644 --- a/llvm/lib/Target/RISCV/RISCVISelDAGToDAG.cpp +++ b/llvm/lib/Target/RISCV/RISCVISelDAGToDAG.cpp @@ -14,6 +14,7 @@ #include "MCTargetDesc/RISCVMCTargetDesc.h" #include "Utils/RISCVMatInt.h" #include "llvm/CodeGen/MachineFrameInfo.h" +#include "llvm/IR/IntrinsicsRISCV.h" #include "llvm/Support/Alignment.h" #include "llvm/Support/Debug.h" #include "llvm/Support/MathExtras.h" @@ -201,6 +202,79 @@ void RISCVDAGToDAGISel::Select(SDNode *Node) { Base, Offset, Chain)); return; } + case ISD::INTRINSIC_WO_CHAIN: { + auto select_mac_intrinsic = [&](unsigned Opcode) { + SmallVector<SDValue, 5> Ops; + for (unsigned i = 1; i < Node->getNumOperands(); ++i) { + Ops.push_back(Node->getOperand(i)); + } + ReplaceNode(Node, CurDAG->getMachineNode(Opcode, DL, Node->getValueType(0), ArrayRef<SDValue>(Ops))); + }; + unsigned IntNo = cast<ConstantSDNode>(Node->getOperand(0))->getZExtValue(); + switch (IntNo) { + default: + break; + case Intrinsic::riscv_cv_mac: + case Intrinsic::riscv_cv_msu: + case Intrinsic::riscv_cv_mulhhs: + case Intrinsic::riscv_cv_mulhhu: + break; // Lowered with patterns + case Intrinsic::riscv_cv_muls: + select_mac_intrinsic(RISCV::CV_MULS); + return; + case Intrinsic::riscv_cv_mulu: + select_mac_intrinsic(RISCV::CV_MULU); + return; + case Intrinsic::riscv_cv_mulsn: + select_mac_intrinsic(RISCV::CV_MULSN); + return; + case Intrinsic::riscv_cv_mulhhsn: + select_mac_intrinsic(RISCV::CV_MULHHSN); + return; + case Intrinsic::riscv_cv_mulsrn: + select_mac_intrinsic(RISCV::CV_MULSRN); + return; + case Intrinsic::riscv_cv_mulhhsrn: + select_mac_intrinsic(RISCV::CV_MULHHSRN); + return; + case Intrinsic::riscv_cv_mulun: + select_mac_intrinsic(RISCV::CV_MULUN); + return; + case Intrinsic::riscv_cv_mulhhun: + select_mac_intrinsic(RISCV::CV_MULHHUN); + return; + case Intrinsic::riscv_cv_mulurn: + select_mac_intrinsic(RISCV::CV_MULURN); + return; + case Intrinsic::riscv_cv_mulhhurn: + select_mac_intrinsic(RISCV::CV_MULHHURN); + return; + case Intrinsic::riscv_cv_macsn: + select_mac_intrinsic(RISCV::CV_MACSN); + return; + case Intrinsic::riscv_cv_machhsn: + select_mac_intrinsic(RISCV::CV_MACHHSN); + return; + case Intrinsic::riscv_cv_macsrn: + select_mac_intrinsic(RISCV::CV_MACSRN); + return; + case Intrinsic::riscv_cv_machhsrn: + select_mac_intrinsic(RISCV::CV_MACHHSRN); + return; + case Intrinsic::riscv_cv_macun: + select_mac_intrinsic(RISCV::CV_MACUN); + return; + case Intrinsic::riscv_cv_machhun: + select_mac_intrinsic(RISCV::CV_MACHHUN); + return; + case Intrinsic::riscv_cv_macurn: + select_mac_intrinsic(RISCV::CV_MACURN); + return; + case Intrinsic::riscv_cv_machhurn: + select_mac_intrinsic(RISCV::CV_MACHHURN); + return; + } + } } // Select the default instruction. diff --git a/llvm/lib/Target/RISCV/RISCVISelLowering.cpp b/llvm/lib/Target/RISCV/RISCVISelLowering.cpp index 6ba0369802c7..d032ae72a18b 100644 --- a/llvm/lib/Target/RISCV/RISCVISelLowering.cpp +++ b/llvm/lib/Target/RISCV/RISCVISelLowering.cpp @@ -233,6 +233,7 @@ RISCVTargetLowering::RISCVTargetLowering(const TargetMachine &TM, setOperationAction(ISD::TRAP, MVT::Other, Legal); setOperationAction(ISD::DEBUGTRAP, MVT::Other, Legal); setOperationAction(ISD::INTRINSIC_WO_CHAIN, MVT::Other, Custom); + setOperationAction(ISD::INTRINSIC_WO_CHAIN, MVT::i16, Custom); if (Subtarget.hasExtXCoreVAlu()) { setOperationAction(ISD::ABS, XLenVT, Legal); @@ -885,6 +886,19 @@ SDValue RISCVTargetLowering::lowerShiftRightParts(SDValue Op, SelectionDAG &DAG, SDValue RISCVTargetLowering::LowerINTRINSIC_WO_CHAIN(SDValue Op, SelectionDAG &DAG) const { + auto promote_i16 = [&](unsigned Extend) { + SDLoc DL(Op); + unsigned NumOps = Op.getNumOperands(); + SmallVector<SDValue, 5> Operands; + for (unsigned i = 0; i < NumOps; ++i) { + EVT OpType = Op->getOperand(i).getValueType(); + Operands.push_back(OpType == EVT(MVT::i16) + ? DAG.getNode(Extend, DL, MVT::i32, Op->getOperand(i)) + : Op->getOperand(i)); + } + EVT ResTy = Op->getValueType(0); + return DAG.getNode(Op->getOpcode(), DL, ResTy, ArrayRef<SDValue>(Operands)); + }; unsigned IntNo = cast<ConstantSDNode>(Op.getOperand(0))->getZExtValue(); SDLoc DL(Op); switch (IntNo) { @@ -894,6 +908,33 @@ SDValue RISCVTargetLowering::LowerINTRINSIC_WO_CHAIN(SDValue Op, EVT PtrVT = getPointerTy(DAG.getDataLayout()); return DAG.getRegister(RISCV::X4, PtrVT); } + + case Intrinsic::riscv_cv_mac: + case Intrinsic::riscv_cv_msu: + case Intrinsic::riscv_cv_muls: + case Intrinsic::riscv_cv_mulhhs: + case Intrinsic::riscv_cv_mulsn: + case Intrinsic::riscv_cv_mulhhsn: + case Intrinsic::riscv_cv_mulsrn: + case Intrinsic::riscv_cv_mulhhsrn: + case Intrinsic::riscv_cv_macsn: + case Intrinsic::riscv_cv_machhsn: + case Intrinsic::riscv_cv_macsrn: + case Intrinsic::riscv_cv_machhsrn: { + return promote_i16(ISD::SIGN_EXTEND); + } + case Intrinsic::riscv_cv_mulu: + case Intrinsic::riscv_cv_mulhhu: + case Intrinsic::riscv_cv_mulun: + case Intrinsic::riscv_cv_mulhhun: + case Intrinsic::riscv_cv_mulurn: + case Intrinsic::riscv_cv_mulhhurn: + case Intrinsic::riscv_cv_macun: + case Intrinsic::riscv_cv_machhun: + case Intrinsic::riscv_cv_macurn: + case Intrinsic::riscv_cv_machhurn: { + return promote_i16(ISD::ZERO_EXTEND); + } } } diff --git a/llvm/lib/Target/RISCV/RISCVInstrInfoCOREV.td b/llvm/lib/Target/RISCV/RISCVInstrInfoCOREV.td index 18e59ca8c33f..81e6d7038d00 100644 --- a/llvm/lib/Target/RISCV/RISCVInstrInfoCOREV.td +++ b/llvm/lib/Target/RISCV/RISCVInstrInfoCOREV.td @@ -96,10 +96,12 @@ let Predicates = [HasExtXCoreVHwlp], hasSideEffects = 1, mayLoad = 0, mayStore = let Predicates = [HasExtXCoreVMac], hasSideEffects = 0, mayLoad = 0, mayStore = 0, Constraints = "$rd = $rd_wb" in { // 32x32 bit macs def CV_MAC : RVInstMac<0b0100001, 0b000, (outs GPR:$rd_wb), (ins GPR:$rd, GPR:$rs1, GPR:$rs2), - "cv.mac", "$rd, $rs1, $rs2", []>, + "cv.mac", "$rd, $rs1, $rs2", + [(set GPR:$rd_wb, (int_riscv_cv_mac i32:$rd, i32:$rs1, i32:$rs2))]>, Sched<[]>; def CV_MSU : RVInstMac<0b0100001, 0b001, (outs GPR:$rd_wb), (ins GPR:$rd, GPR:$rs1, GPR:$rs2), - "cv.msu", "$rd, $rs1, $rs2", []>, + "cv.msu", "$rd, $rs1, $rs2", + [(set GPR:$rd_wb, (int_riscv_cv_msu i32:$rd, i32:$rs1, i32:$rs2))]>, Sched<[]>; // Signed 16x16 bit macs with imm @@ -137,7 +139,8 @@ let Predicates = [HasExtXCoreVMac], hasSideEffects = 0, mayLoad = 0, mayStore = "cv.muls", "$rd, $rs1, $rs2", []>, Sched<[]>; def CV_MULHHS : RVInstMac16<0b11, 0b000, (outs GPR:$rd), (ins GPR:$rs1, GPR:$rs2), - "cv.mulhhs", "$rd, $rs1, $rs2", []>, + "cv.mulhhs", "$rd, $rs1, $rs2", + [(set GPR:$rd, (int_riscv_cv_mulhhs i32:$rs1, i32:$rs2))]>, Sched<[]>; // Signed 16x16 bit muls with imm @@ -159,7 +162,8 @@ let Predicates = [HasExtXCoreVMac], hasSideEffects = 0, mayLoad = 0, mayStore = "cv.mulu", "$rd, $rs1, $rs2", []>, Sched<[]>; def CV_MULHHU : RVInstMac16<0b01, 0b000, (outs GPR:$rd), (ins GPR:$rs1, GPR:$rs2), - "cv.mulhhu", "$rd, $rs1, $rs2", []>, + "cv.mulhhu", "$rd, $rs1, $rs2", + [(set GPR:$rd, (int_riscv_cv_mulhhu i32:$rs1, i32:$rs2))]>, Sched<[]>; // Unsigned 16x16 bit muls with imm -- GitLab