From fa079e4be8b1b043b635a494b8c0bcc5aa79092b Mon Sep 17 00:00:00 2001 From: wangpc Date: Mon, 25 Dec 2023 18:52:36 +0800 Subject: [PATCH] [RFC][RISCV] Support RISC-V Profiles in -march option This PR implements the draft https://github.com/riscv-non-isa/riscv-toolchain-conventions/pull/36. Currently, we replace specified profile in `-march` with standard arch string. We may need to pass it to backend so that we can emit an ELF attr proposed by https://github.com/riscv-non-isa/riscv-elf-psabi-doc/pull/409. --- clang/test/Driver/riscv-profiles.c | 112 +++++++++++++++++++++++ llvm/include/llvm/Support/RISCVISAInfo.h | 4 +- llvm/lib/Support/RISCVISAInfo.cpp | 51 +++++++++++ llvm/lib/Target/RISCV/RISCV.td | 6 ++ llvm/lib/Target/RISCV/RISCVProfiles.td | 70 ++++++++++++++ llvm/lib/Target/RISCV/RISCVSubtarget.h | 14 +++ llvm/test/CodeGen/RISCV/attributes.ll | 15 +++ 7 files changed, 271 insertions(+), 1 deletion(-) create mode 100644 clang/test/Driver/riscv-profiles.c create mode 100644 llvm/lib/Target/RISCV/RISCVProfiles.td diff --git a/clang/test/Driver/riscv-profiles.c b/clang/test/Driver/riscv-profiles.c new file mode 100644 index 00000000000000..d41d68e078b976 --- /dev/null +++ b/clang/test/Driver/riscv-profiles.c @@ -0,0 +1,112 @@ +// RUN: %clang -### -c %s 2>&1 -march=rvi20u32 | FileCheck -check-prefix=RVI20U32 %s +// RVI20U32: "-target-cpu" "generic-rv32" +// RVI20U32: "-target-feature" "-a" +// RVI20U32: "-target-feature" "-c" +// RVI20U32: "-target-feature" "-d" +// RVI20U32: "-target-feature" "-f" +// RVI20U32: "-target-feature" "-m" +// RVI20U32: "-target-feature" "+rvi20u32" +// RVI20U32: "-target-abi" "ilp32" + +// RUN: %clang -### -c %s 2>&1 -march=rvi20u64 | FileCheck -check-prefix=RVI20U64 %s +// RVI20U64: "-target-cpu" "generic-rv64" +// RVI20U64: "-target-feature" "-a" +// RVI20U64: "-target-feature" "-c" +// RVI20U64: "-target-feature" "-d" +// RVI20U64: "-target-feature" "-f" +// RVI20U64: "-target-feature" "-m" +// RVI20U64: "-target-feature" "+rvi20u64" +// RVI20U64: "-target-abi" "lp64" + +// RUN: %clang -### -c %s 2>&1 -march=rva20u64 | FileCheck -check-prefix=RVA20U64 %s +// RVA20U64: "-target-cpu" "generic-rv64" +// RVA20U64: "-target-feature" "+m" +// RVA20U64: "-target-feature" "+a" +// RVA20U64: "-target-feature" "+f" +// RVA20U64: "-target-feature" "+d" +// RVA20U64: "-target-feature" "+c" +// RVA20U64: "-target-feature" "+zicsr" +// RVA20U64: "-target-feature" "+rva20u64" +// RVA20U64: "-target-abi" "lp64d" + +// RUN: %clang -### -c %s 2>&1 -march=rva20s64 | FileCheck -check-prefix=RVA20S64 %s +// RVA20S64: "-target-cpu" "generic-rv64" +// RVA20S64: "-target-feature" "+m" +// RVA20S64: "-target-feature" "+a" +// RVA20S64: "-target-feature" "+f" +// RVA20S64: "-target-feature" "+d" +// RVA20S64: "-target-feature" "+c" +// RVA20S64: "-target-feature" "+zicsr" +// RVA20S64: "-target-feature" "+zifencei" +// RVA20S64: "-target-feature" "+rva20s64" +// RVA20S64: "-target-abi" "lp64d" + +// RUN: %clang -### -c %s 2>&1 -march=rva22u64 | FileCheck -check-prefix=RVA22U64 %s +// RVA22U64: "-target-cpu" "generic-rv64" +// RVA22U64: "-target-feature" "+m" +// RVA22U64: "-target-feature" "+a" +// RVA22U64: "-target-feature" "+f" +// RVA22U64: "-target-feature" "+d" +// RVA22U64: "-target-feature" "+c" +// RVA22U64: "-target-feature" "+zicbom" +// RVA22U64: "-target-feature" "+zicbop" +// RVA22U64: "-target-feature" "+zicboz" +// RVA22U64: "-target-feature" "+zicsr" +// RVA22U64: "-target-feature" "+zihintpause" +// RVA22U64: "-target-feature" "+zfhmin" +// RVA22U64: "-target-feature" "+zba" +// RVA22U64: "-target-feature" "+zbb" +// RVA22U64: "-target-feature" "+zbs" +// RVA22U64: "-target-feature" "+zkt" +// RVA22U64: "-target-feature" "+rva22u64" +// RVA22U64: "-target-abi" "lp64d" + +// RUN: %clang -### -c %s 2>&1 -march=rva22s64 | FileCheck -check-prefix=RVA22S64 %s +// RVA22S64: "-target-cpu" "generic-rv64" +// RVA22S64: "-target-feature" "+m" +// RVA22S64: "-target-feature" "+a" +// RVA22S64: "-target-feature" "+f" +// RVA22S64: "-target-feature" "+d" +// RVA22S64: "-target-feature" "+c" +// RVA22S64: "-target-feature" "+zicbom" +// RVA22S64: "-target-feature" "+zicbop" +// RVA22S64: "-target-feature" "+zicboz" +// RVA22S64: "-target-feature" "+zicsr" +// RVA22S64: "-target-feature" "+zifencei" +// RVA22S64: "-target-feature" "+zihintpause" +// RVA22S64: "-target-feature" "+zfhmin" +// RVA22S64: "-target-feature" "+zba" +// RVA22S64: "-target-feature" "+zbb" +// RVA22S64: "-target-feature" "+zbs" +// RVA22S64: "-target-feature" "+zkt" +// RVA22S64: "-target-feature" "+svinval" +// RVA22S64: "-target-feature" "+svpbmt" +// RVA22S64: "-target-feature" "+rva22s64" +// RVA22S64: "-target-abi" "lp64d" + +// RUN: %clang -### -c %s 2>&1 -march=rva22u64_zfa | FileCheck -check-prefix=PROFILE-WITH-ADDITIONAL %s +// PROFILE-WITH-ADDITIONAL: "-target-cpu" "generic-rv64" +// PROFILE-WITH-ADDITIONAL: "-target-feature" "+m" +// PROFILE-WITH-ADDITIONAL: "-target-feature" "+a" +// PROFILE-WITH-ADDITIONAL: "-target-feature" "+f" +// PROFILE-WITH-ADDITIONAL: "-target-feature" "+d" +// PROFILE-WITH-ADDITIONAL: "-target-feature" "+c" +// PROFILE-WITH-ADDITIONAL: "-target-feature" "+zicbom" +// PROFILE-WITH-ADDITIONAL: "-target-feature" "+zicbop" +// PROFILE-WITH-ADDITIONAL: "-target-feature" "+zicboz" +// PROFILE-WITH-ADDITIONAL: "-target-feature" "+zicsr" +// PROFILE-WITH-ADDITIONAL: "-target-feature" "+zihintpause" +// PROFILE-WITH-ADDITIONAL: "-target-feature" "+zfa" +// PROFILE-WITH-ADDITIONAL: "-target-feature" "+zfhmin" +// PROFILE-WITH-ADDITIONAL: "-target-feature" "+zba" +// PROFILE-WITH-ADDITIONAL: "-target-feature" "+zbb" +// PROFILE-WITH-ADDITIONAL: "-target-feature" "+zbs" +// PROFILE-WITH-ADDITIONAL: "-target-feature" "+zkt" +// PROFILE-WITH-ADDITIONAL: "-target-feature" "+rva22u64" +// PROFILE-WITH-ADDITIONAL: "-target-abi" "lp64d" + +// RUN: not %clang -### -c %s 2>&1 -march=rva19u64_zfa | FileCheck -check-prefix=INVALID-PROFILE %s +// INVALID-PROFILE: error: invalid arch name 'rva19u64_zfa', unsupported profile + +// RUN: not %clang -### -c %s 2>&1 -march=rva22u64zfa | FileCheck -check-prefix=INVALID-ADDITIONAL %s +// INVALID-ADDITIONAL: error: invalid arch name 'rva22u64zfa', additional extensions must be after separator '_' diff --git a/llvm/include/llvm/Support/RISCVISAInfo.h b/llvm/include/llvm/Support/RISCVISAInfo.h index 09c4edd6df60e9..17c20b839f3014 100644 --- a/llvm/include/llvm/Support/RISCVISAInfo.h +++ b/llvm/include/llvm/Support/RISCVISAInfo.h @@ -80,6 +80,7 @@ class RISCVISAInfo { unsigned getMaxVLen() const { return 65536; } unsigned getMaxELen() const { return MaxELen; } unsigned getMaxELenFp() const { return MaxELenFp; } + std::string getProfile() const { return Profile; } bool hasExtension(StringRef Ext) const; std::string toString() const; @@ -97,12 +98,13 @@ class RISCVISAInfo { private: RISCVISAInfo(unsigned XLen) - : XLen(XLen), FLen(0), MinVLen(0), MaxELen(0), MaxELenFp(0) {} + : XLen(XLen), FLen(0), MinVLen(0), MaxELen(0), MaxELenFp(0), Profile() {} unsigned XLen; unsigned FLen; unsigned MinVLen; unsigned MaxELen, MaxELenFp; + std::string Profile; OrderedExtensionMap Exts; diff --git a/llvm/lib/Support/RISCVISAInfo.cpp b/llvm/lib/Support/RISCVISAInfo.cpp index 14079a0eb07603..541aaf05513211 100644 --- a/llvm/lib/Support/RISCVISAInfo.cpp +++ b/llvm/lib/Support/RISCVISAInfo.cpp @@ -39,6 +39,10 @@ struct RISCVSupportedExtension { return StringRef(Name) < StringRef(RHS.Name); } }; +struct RISCVProfile { + const char *Name; + const char *MArch; +}; } // end anonymous namespace @@ -206,6 +210,17 @@ static const RISCVSupportedExtension SupportedExperimentalExtensions[] = { {"zvfbfwma", RISCVExtensionVersion{0, 8}}, }; +static const RISCVProfile SupportedProfiles[] = { + {"rvi20u32", "rv32i"}, + {"rvi20u64", "rv64i"}, + {"rva20u64", "rv64imafdc_zicsr"}, + {"rva20s64", "rv64imafdc_zicsr_zifencei"}, + {"rva22u64", "rv64imafdc_zicsr_zihintpause_zba_zbb_zbs_zicbom_zicbop_" + "zicboz_zfhmin_zkt"}, + {"rva22s64", "rv64imafdc_zicsr_zifencei_zihintpause_zba_zbb_zbs_zicbom_" + "zicbop_zicboz_zfhmin_zkt_svpbmt_svinval"}, +}; + static void verifyTables() { #ifndef NDEBUG static std::atomic TableChecked(false); @@ -494,6 +509,10 @@ void RISCVISAInfo::toFeatures( Features.push_back(StrAlloc(Twine("-experimental-") + Ext.Name)); } } + + // Add profile feature. + if (!Profile.empty()) + Features.push_back(StrAlloc(Twine("+") + Profile)); } // Extensions may have a version number, and may be separated by @@ -710,6 +729,36 @@ RISCVISAInfo::parseArchString(StringRef Arch, bool EnableExperimentalExtension, "string must be lowercase"); } + bool IsProfile = Arch.starts_with("rvi") || Arch.starts_with("rva") || + Arch.starts_with("rvb") || Arch.starts_with("rvm"); + std::string NewArch; + std::string ProfileName; + if (IsProfile) { + const RISCVProfile *FoundProfile = nullptr; + for (const RISCVProfile &Profile : SupportedProfiles) { + if (Arch.starts_with(Profile.Name)) { + FoundProfile = &Profile; + break; + } + } + + if (!FoundProfile) + return createStringError(errc::invalid_argument, "unsupported profile"); + + ProfileName = FoundProfile->Name; + NewArch = FoundProfile->MArch; + + StringRef ArchWithoutProfile = Arch.substr(ProfileName.size()); + if (!ArchWithoutProfile.empty()) { + if (!ArchWithoutProfile.starts_with("_")) + return createStringError( + errc::invalid_argument, + "additional extensions must be after separator '_'"); + NewArch = NewArch + ArchWithoutProfile.str(); + } + Arch = NewArch; + } + bool HasRV64 = Arch.starts_with("rv64"); // ISA string must begin with rv32 or rv64. if (!(Arch.starts_with("rv32") || HasRV64) || (Arch.size() < 5)) { @@ -720,6 +769,8 @@ RISCVISAInfo::parseArchString(StringRef Arch, bool EnableExperimentalExtension, unsigned XLen = HasRV64 ? 64 : 32; std::unique_ptr ISAInfo(new RISCVISAInfo(XLen)); + if (!ProfileName.empty()) + ISAInfo->Profile = ProfileName; // The canonical order specified in ISA manual. // Ref: Table 22.1 in RISC-V User-Level ISA V2.2 diff --git a/llvm/lib/Target/RISCV/RISCV.td b/llvm/lib/Target/RISCV/RISCV.td index be93d5933d3329..b08a7686ff1265 100644 --- a/llvm/lib/Target/RISCV/RISCV.td +++ b/llvm/lib/Target/RISCV/RISCV.td @@ -44,6 +44,12 @@ include "RISCVSchedSyntacoreSCR1.td" include "RISCVProcessors.td" +//===----------------------------------------------------------------------===// +// RISC-V profiles supported. +//===----------------------------------------------------------------------===// + +include "RISCVProfiles.td" + //===----------------------------------------------------------------------===// // Define the RISC-V target. //===----------------------------------------------------------------------===// diff --git a/llvm/lib/Target/RISCV/RISCVProfiles.td b/llvm/lib/Target/RISCV/RISCVProfiles.td new file mode 100644 index 00000000000000..91e1064da4e76e --- /dev/null +++ b/llvm/lib/Target/RISCV/RISCVProfiles.td @@ -0,0 +1,70 @@ +//===------ RISCVProfiles.td - RISC-V Profiles -------------*- tablegen -*-===// +// +// 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 +// +//===----------------------------------------------------------------------===// + +class RISCVProfile features> + : SubtargetFeature; + +def RVI20U32 : RISCVProfile<"rvi20u32", [Feature32Bit]>; + +def RVI20U64 : RISCVProfile<"rvi20u64", [Feature64Bit]>; + +def RVA20U64 : RISCVProfile<"rva20u64", [Feature64Bit, + FeatureStdExtM, + FeatureStdExtA, + FeatureStdExtF, + FeatureStdExtD, + FeatureStdExtC, + FeatureStdExtZicsr]>; + +def RVA20S64 : RISCVProfile<"rva20s64", [Feature64Bit, + FeatureStdExtM, + FeatureStdExtA, + FeatureStdExtF, + FeatureStdExtD, + FeatureStdExtC, + FeatureStdExtZicsr, + FeatureStdExtZifencei]>; + +def RVA22U64 : RISCVProfile<"rva22u64", [Feature64Bit, + FeatureStdExtM, + FeatureStdExtA, + FeatureStdExtF, + FeatureStdExtD, + FeatureStdExtC, + FeatureStdExtZba, + FeatureStdExtZbb, + FeatureStdExtZbs, + FeatureStdExtZfhmin, + FeatureStdExtZicbom, + FeatureStdExtZicbop, + FeatureStdExtZicboz, + FeatureStdExtZkt, + FeatureStdExtZicsr, + FeatureStdExtZihintpause]>; + +def RVA22S64 : RISCVProfile<"rva22s64", [Feature64Bit, + FeatureStdExtM, + FeatureStdExtA, + FeatureStdExtF, + FeatureStdExtD, + FeatureStdExtC, + FeatureStdExtZba, + FeatureStdExtZbb, + FeatureStdExtZbs, + FeatureStdExtZfhmin, + FeatureStdExtZicbom, + FeatureStdExtZicbop, + FeatureStdExtZicboz, + FeatureStdExtZkt, + FeatureStdExtZicsr, + FeatureStdExtZifencei, + FeatureStdExtZihintpause, + FeatureStdExtSvpbmt, + FeatureStdExtSvinval]>; diff --git a/llvm/lib/Target/RISCV/RISCVSubtarget.h b/llvm/lib/Target/RISCV/RISCVSubtarget.h index 26320b05d9be29..dbb10c5b2d6f59 100644 --- a/llvm/lib/Target/RISCV/RISCVSubtarget.h +++ b/llvm/lib/Target/RISCV/RISCVSubtarget.h @@ -53,6 +53,16 @@ struct RISCVTuneInfo { #include "RISCVGenSearchableTables.inc" } // namespace RISCVTuneInfoTable +enum RISCVProfileEnum : uint8_t { + Unspecified, + RVA20S64, + RVA20U64, + RVA22S64, + RVA22U64, + RVI20U32, + RVI20U64, +}; + class RISCVSubtarget : public RISCVGenSubtargetInfo { public: // clang-format off @@ -67,6 +77,8 @@ class RISCVSubtarget : public RISCVGenSubtargetInfo { RISCVProcFamilyEnum RISCVProcFamily = Others; + RISCVProfileEnum RISCVProfile = Unspecified; + #define GET_SUBTARGETINFO_MACRO(ATTRIBUTE, DEFAULT, GETTER) \ bool ATTRIBUTE = DEFAULT; #include "RISCVGenSubtargetInfo.inc" @@ -135,6 +147,8 @@ class RISCVSubtarget : public RISCVGenSubtargetInfo { /// initializeProperties(). RISCVProcFamilyEnum getProcFamily() const { return RISCVProcFamily; } + RISCVProfileEnum getRISCVProfile() const { return RISCVProfile; } + #define GET_SUBTARGETINFO_MACRO(ATTRIBUTE, DEFAULT, GETTER) \ bool GETTER() const { return ATTRIBUTE; } #include "RISCVGenSubtargetInfo.inc" diff --git a/llvm/test/CodeGen/RISCV/attributes.ll b/llvm/test/CodeGen/RISCV/attributes.ll index 9a6e78c09ad8c3..b57daf0bd8248a 100644 --- a/llvm/test/CodeGen/RISCV/attributes.ll +++ b/llvm/test/CodeGen/RISCV/attributes.ll @@ -189,6 +189,14 @@ ; RUN: llc -mtriple=riscv64 -mattr=+experimental-zacas %s -o - | FileCheck --check-prefix=RV64ZACAS %s ; RUN: llc -mtriple=riscv64 -mattr=+experimental-zicfilp %s -o - | FileCheck --check-prefix=RV64ZICFILP %s +; Tests for profile features. +; RUN: llc -mtriple=riscv32 -mattr=+rvi20u32 %s -o - | FileCheck --check-prefix=RVI20U32 %s +; RUN: llc -mtriple=riscv64 -mattr=+rvi20u64 %s -o - | FileCheck --check-prefix=RVI20U64 %s +; RUN: llc -mtriple=riscv64 -mattr=+rva20u64 %s -o - | FileCheck --check-prefix=RVA20U64 %s +; RUN: llc -mtriple=riscv64 -mattr=+rva20s64 %s -o - | FileCheck --check-prefix=RVA20S64 %s +; RUN: llc -mtriple=riscv64 -mattr=+rva22u64 %s -o - | FileCheck --check-prefix=RVA22U64 %s +; RUN: llc -mtriple=riscv64 -mattr=+rva22s64 %s -o - | FileCheck --check-prefix=RVA22S64 %s + ; CHECK: .attribute 4, 16 ; RV32M: .attribute 5, "rv32i2p1_m2p0" @@ -378,6 +386,13 @@ ; RV64ZACAS: .attribute 5, "rv64i2p1_a2p1_zacas1p0" ; RV64ZICFILP: .attribute 5, "rv64i2p1_zicfilp0p4" +; RVI20U32: .attribute 5, "rv32i2p1" +; RVI20U64: .attribute 5, "rv64i2p1" +; RVA20U64: .attribute 5, "rv64i2p1_m2p0_a2p1_f2p2_d2p2_c2p0_zicsr2p0" +; RVA20S64: .attribute 5, "rv64i2p1_m2p0_a2p1_f2p2_d2p2_c2p0_zicsr2p0_zifencei2p0" +; RVA22U64: .attribute 5, "rv64i2p1_m2p0_a2p1_f2p2_d2p2_c2p0_zicbom1p0_zicbop1p0_zicboz1p0_zicsr2p0_zihintpause2p0_zfhmin1p0_zba1p0_zbb1p0_zbs1p0_zkt1p0" +; RVA22S64: .attribute 5, "rv64i2p1_m2p0_a2p1_f2p2_d2p2_c2p0_zicbom1p0_zicbop1p0_zicboz1p0_zicsr2p0_zifencei2p0_zihintpause2p0_zfhmin1p0_zba1p0_zbb1p0_zbs1p0_zkt1p0_svinval1p0_svpbmt1p0" + define i32 @addi(i32 %a) { %1 = add i32 %a, 1 ret i32 %1