[RISCV] Add support for -mcpu option.
Summary: 1. gcc uses `-march` and `-mtune` flag to chose arch and pipeline model, but clang does not have `-mtune` flag, we uses `-mcpu` to chose both infos. 2. Add SiFive e31 and u54 cpu which have default march and pipeline model. 3. Specific `-mcpu` with rocket-rv[32|64] would select pipeline model only, and use the driver's arch choosing logic to get default arch. Reviewers: lenary, asb, evandro, HsiangKai Reviewed By: lenary, asb, evandro Tags: #llvm, #clang Differential Revision: https://reviews.llvm.org/D71124
This commit is contained in:
parent
a394aa1b97
commit
294d1eae75
|
@ -13,6 +13,7 @@
|
||||||
#include "RISCV.h"
|
#include "RISCV.h"
|
||||||
#include "clang/Basic/MacroBuilder.h"
|
#include "clang/Basic/MacroBuilder.h"
|
||||||
#include "llvm/ADT/StringSwitch.h"
|
#include "llvm/ADT/StringSwitch.h"
|
||||||
|
#include "llvm/Support/TargetParser.h"
|
||||||
|
|
||||||
using namespace clang;
|
using namespace clang;
|
||||||
using namespace clang::targets;
|
using namespace clang::targets;
|
||||||
|
@ -166,3 +167,23 @@ bool RISCVTargetInfo::handleTargetFeatures(std::vector<std::string> &Features,
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool RISCV32TargetInfo::isValidCPUName(StringRef Name) const {
|
||||||
|
return llvm::RISCV::checkCPUKind(llvm::RISCV::parseCPUKind(Name),
|
||||||
|
/*Is64Bit=*/false);
|
||||||
|
}
|
||||||
|
|
||||||
|
void RISCV32TargetInfo::fillValidCPUList(
|
||||||
|
SmallVectorImpl<StringRef> &Values) const {
|
||||||
|
llvm::RISCV::fillValidCPUArchList(Values, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool RISCV64TargetInfo::isValidCPUName(StringRef Name) const {
|
||||||
|
return llvm::RISCV::checkCPUKind(llvm::RISCV::parseCPUKind(Name),
|
||||||
|
/*Is64Bit=*/true);
|
||||||
|
}
|
||||||
|
|
||||||
|
void RISCV64TargetInfo::fillValidCPUList(
|
||||||
|
SmallVectorImpl<StringRef> &Values) const {
|
||||||
|
llvm::RISCV::fillValidCPUArchList(Values, true);
|
||||||
|
}
|
||||||
|
|
|
@ -24,7 +24,7 @@ namespace targets {
|
||||||
// RISC-V Target
|
// RISC-V Target
|
||||||
class RISCVTargetInfo : public TargetInfo {
|
class RISCVTargetInfo : public TargetInfo {
|
||||||
protected:
|
protected:
|
||||||
std::string ABI;
|
std::string ABI, CPU;
|
||||||
bool HasM;
|
bool HasM;
|
||||||
bool HasA;
|
bool HasA;
|
||||||
bool HasF;
|
bool HasF;
|
||||||
|
@ -44,6 +44,13 @@ public:
|
||||||
WIntType = UnsignedInt;
|
WIntType = UnsignedInt;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool setCPU(const std::string &Name) override {
|
||||||
|
if (!isValidCPUName(Name))
|
||||||
|
return false;
|
||||||
|
CPU = Name;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
StringRef getABI() const override { return ABI; }
|
StringRef getABI() const override { return ABI; }
|
||||||
void getTargetDefines(const LangOptions &Opts,
|
void getTargetDefines(const LangOptions &Opts,
|
||||||
MacroBuilder &Builder) const override;
|
MacroBuilder &Builder) const override;
|
||||||
|
@ -97,6 +104,9 @@ public:
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool isValidCPUName(StringRef Name) const override;
|
||||||
|
void fillValidCPUList(SmallVectorImpl<StringRef> &Values) const override;
|
||||||
|
|
||||||
void setMaxAtomicWidth() override {
|
void setMaxAtomicWidth() override {
|
||||||
MaxAtomicPromoteWidth = 128;
|
MaxAtomicPromoteWidth = 128;
|
||||||
|
|
||||||
|
@ -121,6 +131,9 @@ public:
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool isValidCPUName(StringRef Name) const override;
|
||||||
|
void fillValidCPUList(SmallVectorImpl<StringRef> &Values) const override;
|
||||||
|
|
||||||
void setMaxAtomicWidth() override {
|
void setMaxAtomicWidth() override {
|
||||||
MaxAtomicPromoteWidth = 128;
|
MaxAtomicPromoteWidth = 128;
|
||||||
|
|
||||||
|
|
|
@ -446,6 +446,19 @@ static bool getArchFeatures(const Driver &D, StringRef MArch,
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Get features except standard extension feature
|
||||||
|
void getRISCFeaturesFromMcpu(const Driver &D, const llvm::Triple &Triple,
|
||||||
|
const llvm::opt::ArgList &Args,
|
||||||
|
const llvm::opt::Arg *A, StringRef Mcpu,
|
||||||
|
std::vector<StringRef> &Features) {
|
||||||
|
bool Is64Bit = (Triple.getArch() == llvm::Triple::riscv64);
|
||||||
|
llvm::RISCV::CPUKind CPUKind = llvm::RISCV::parseCPUKind(Mcpu);
|
||||||
|
if (!llvm::RISCV::checkCPUKind(CPUKind, Is64Bit) ||
|
||||||
|
!llvm::RISCV::getCPUFeaturesExceptStdExt(CPUKind, Features)) {
|
||||||
|
D.Diag(clang::diag::err_drv_clang_unsupported) << A->getAsString(Args);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void riscv::getRISCVTargetFeatures(const Driver &D, const llvm::Triple &Triple,
|
void riscv::getRISCVTargetFeatures(const Driver &D, const llvm::Triple &Triple,
|
||||||
const ArgList &Args,
|
const ArgList &Args,
|
||||||
std::vector<StringRef> &Features) {
|
std::vector<StringRef> &Features) {
|
||||||
|
@ -454,6 +467,11 @@ void riscv::getRISCVTargetFeatures(const Driver &D, const llvm::Triple &Triple,
|
||||||
if (!getArchFeatures(D, MArch, Features, Args))
|
if (!getArchFeatures(D, MArch, Features, Args))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
// If users give march and mcpu, get std extension feature from MArch
|
||||||
|
// and other features (ex. mirco architecture feature) from mcpu
|
||||||
|
if (Arg *A = Args.getLastArg(options::OPT_mcpu_EQ))
|
||||||
|
getRISCFeaturesFromMcpu(D, Triple, Args, A, A->getValue(), Features);
|
||||||
|
|
||||||
// Handle features corresponding to "-ffixed-X" options
|
// Handle features corresponding to "-ffixed-X" options
|
||||||
if (Args.hasArg(options::OPT_ffixed_x1))
|
if (Args.hasArg(options::OPT_ffixed_x1))
|
||||||
Features.push_back("+reserve-x1");
|
Features.push_back("+reserve-x1");
|
||||||
|
@ -543,11 +561,9 @@ StringRef riscv::getRISCVABI(const ArgList &Args, const llvm::Triple &Triple) {
|
||||||
|
|
||||||
// GCC's logic around choosing a default `-mabi=` is complex. If GCC is not
|
// GCC's logic around choosing a default `-mabi=` is complex. If GCC is not
|
||||||
// configured using `--with-abi=`, then the logic for the default choice is
|
// configured using `--with-abi=`, then the logic for the default choice is
|
||||||
// defined in config.gcc. This function is based on the logic in GCC 9.2.0. We
|
// defined in config.gcc. This function is based on the logic in GCC 9.2.0.
|
||||||
// deviate from GCC's default only on baremetal targets (UnknownOS) where
|
|
||||||
// neither `-march` nor `-mabi` is specified.
|
|
||||||
//
|
//
|
||||||
// The logic uses the following, in order:
|
// The logic used in GCC 9.2.0 is the following, in order:
|
||||||
// 1. Explicit choices using `--with-abi=`
|
// 1. Explicit choices using `--with-abi=`
|
||||||
// 2. A default based on `--with-arch=`, if provided
|
// 2. A default based on `--with-arch=`, if provided
|
||||||
// 3. A default based on the target triple's arch
|
// 3. A default based on the target triple's arch
|
||||||
|
@ -556,38 +572,40 @@ StringRef riscv::getRISCVABI(const ArgList &Args, const llvm::Triple &Triple) {
|
||||||
//
|
//
|
||||||
// Clang does not have `--with-arch=` or `--with-abi=`, so we use `-march=`
|
// Clang does not have `--with-arch=` or `--with-abi=`, so we use `-march=`
|
||||||
// and `-mabi=` respectively instead.
|
// and `-mabi=` respectively instead.
|
||||||
|
//
|
||||||
|
// In order to make chosing logic more clear, Clang uses the following logic,
|
||||||
|
// in order:
|
||||||
|
// 1. Explicit choices using `-mabi=`
|
||||||
|
// 2. A default based on the architecture as determined by getRISCVArch
|
||||||
|
// 3. Choose a default based on the triple
|
||||||
|
|
||||||
// 1. If `-mabi=` is specified, use it.
|
// 1. If `-mabi=` is specified, use it.
|
||||||
if (const Arg *A = Args.getLastArg(options::OPT_mabi_EQ))
|
if (const Arg *A = Args.getLastArg(options::OPT_mabi_EQ))
|
||||||
return A->getValue();
|
return A->getValue();
|
||||||
|
|
||||||
// 2. Choose a default based on `-march=`
|
// 2. Choose a default based on the target architecture.
|
||||||
//
|
//
|
||||||
// rv32g | rv32*d -> ilp32d
|
// rv32g | rv32*d -> ilp32d
|
||||||
// rv32e -> ilp32e
|
// rv32e -> ilp32e
|
||||||
// rv32* -> ilp32
|
// rv32* -> ilp32
|
||||||
// rv64g | rv64*d -> lp64d
|
// rv64g | rv64*d -> lp64d
|
||||||
// rv64* -> lp64
|
// rv64* -> lp64
|
||||||
if (const Arg *A = Args.getLastArg(options::OPT_march_EQ)) {
|
StringRef MArch = getRISCVArch(Args, Triple);
|
||||||
StringRef MArch = A->getValue();
|
|
||||||
|
|
||||||
if (MArch.startswith_lower("rv32")) {
|
if (MArch.startswith_lower("rv32")) {
|
||||||
// FIXME: parse `March` to find `D` extension properly
|
// FIXME: parse `March` to find `D` extension properly
|
||||||
if (MArch.substr(4).contains_lower("d") ||
|
if (MArch.substr(4).contains_lower("d") || MArch.startswith_lower("rv32g"))
|
||||||
MArch.startswith_lower("rv32g"))
|
return "ilp32d";
|
||||||
return "ilp32d";
|
else if (MArch.startswith_lower("rv32e"))
|
||||||
else if (MArch.startswith_lower("rv32e"))
|
return "ilp32e";
|
||||||
return "ilp32e";
|
else
|
||||||
else
|
return "ilp32";
|
||||||
return "ilp32";
|
} else if (MArch.startswith_lower("rv64")) {
|
||||||
} else if (MArch.startswith_lower("rv64")) {
|
// FIXME: parse `March` to find `D` extension properly
|
||||||
// FIXME: parse `March` to find `D` extension properly
|
if (MArch.substr(4).contains_lower("d") || MArch.startswith_lower("rv64g"))
|
||||||
if (MArch.substr(4).contains_lower("d") ||
|
return "lp64d";
|
||||||
MArch.startswith_lower("rv64g"))
|
else
|
||||||
return "lp64d";
|
return "lp64";
|
||||||
else
|
|
||||||
return "lp64";
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// 3. Choose a default based on the triple
|
// 3. Choose a default based on the triple
|
||||||
|
@ -617,10 +635,11 @@ StringRef riscv::getRISCVArch(const llvm::opt::ArgList &Args,
|
||||||
// GCC's logic around choosing a default `-march=` is complex. If GCC is not
|
// GCC's logic around choosing a default `-march=` is complex. If GCC is not
|
||||||
// configured using `--with-arch=`, then the logic for the default choice is
|
// configured using `--with-arch=`, then the logic for the default choice is
|
||||||
// defined in config.gcc. This function is based on the logic in GCC 9.2.0. We
|
// defined in config.gcc. This function is based on the logic in GCC 9.2.0. We
|
||||||
// deviate from GCC's default only on baremetal targets (UnknownOS) where
|
// deviate from GCC's default on additional `-mcpu` option (GCC does not
|
||||||
// neither `-march` nor `-mabi` is specified.
|
// support `-mcpu`) and baremetal targets (UnknownOS) where neither `-march`
|
||||||
|
// nor `-mabi` is specified.
|
||||||
//
|
//
|
||||||
// The logic uses the following, in order:
|
// The logic used in GCC 9.2.0 is the following, in order:
|
||||||
// 1. Explicit choices using `--with-arch=`
|
// 1. Explicit choices using `--with-arch=`
|
||||||
// 2. A default based on `--with-abi=`, if provided
|
// 2. A default based on `--with-abi=`, if provided
|
||||||
// 3. A default based on the target triple's arch
|
// 3. A default based on the target triple's arch
|
||||||
|
@ -630,6 +649,12 @@ StringRef riscv::getRISCVArch(const llvm::opt::ArgList &Args,
|
||||||
// Clang does not have `--with-arch=` or `--with-abi=`, so we use `-march=`
|
// Clang does not have `--with-arch=` or `--with-abi=`, so we use `-march=`
|
||||||
// and `-mabi=` respectively instead.
|
// and `-mabi=` respectively instead.
|
||||||
//
|
//
|
||||||
|
// Clang uses the following logic, in order:
|
||||||
|
// 1. Explicit choices using `-march=`
|
||||||
|
// 2. Based on `-mcpu` if the target CPU has a default ISA string
|
||||||
|
// 3. A default based on `-mabi`, if provided
|
||||||
|
// 4. A default based on the target triple's arch
|
||||||
|
//
|
||||||
// Clang does not yet support MULTILIB_REUSE, so we use `rv{XLEN}imafdc`
|
// Clang does not yet support MULTILIB_REUSE, so we use `rv{XLEN}imafdc`
|
||||||
// instead of `rv{XLEN}gc` though they are (currently) equivalent.
|
// instead of `rv{XLEN}gc` though they are (currently) equivalent.
|
||||||
|
|
||||||
|
@ -637,7 +662,15 @@ StringRef riscv::getRISCVArch(const llvm::opt::ArgList &Args,
|
||||||
if (const Arg *A = Args.getLastArg(options::OPT_march_EQ))
|
if (const Arg *A = Args.getLastArg(options::OPT_march_EQ))
|
||||||
return A->getValue();
|
return A->getValue();
|
||||||
|
|
||||||
// 2. Choose a default based on `-mabi=`
|
// 2. Get march (isa string) based on `-mcpu=`
|
||||||
|
if (const Arg *A = Args.getLastArg(options::OPT_mcpu_EQ)) {
|
||||||
|
StringRef MArch = llvm::RISCV::getMArchFromMcpu(A->getValue());
|
||||||
|
// Bypass if target cpu's default march is empty.
|
||||||
|
if (MArch != "")
|
||||||
|
return MArch;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 3. Choose a default based on `-mabi=`
|
||||||
//
|
//
|
||||||
// ilp32e -> rv32e
|
// ilp32e -> rv32e
|
||||||
// ilp32 | ilp32f | ilp32d -> rv32imafdc
|
// ilp32 | ilp32f | ilp32d -> rv32imafdc
|
||||||
|
@ -653,7 +686,7 @@ StringRef riscv::getRISCVArch(const llvm::opt::ArgList &Args,
|
||||||
return "rv64imafdc";
|
return "rv64imafdc";
|
||||||
}
|
}
|
||||||
|
|
||||||
// 3. Choose a default based on the triple
|
// 4. Choose a default based on the triple
|
||||||
//
|
//
|
||||||
// We deviate from GCC's defaults here:
|
// We deviate from GCC's defaults here:
|
||||||
// - On `riscv{XLEN}-unknown-elf` we default to `rv{XLEN}imac`
|
// - On `riscv{XLEN}-unknown-elf` we default to `rv{XLEN}imac`
|
||||||
|
|
|
@ -333,6 +333,11 @@ std::string tools::getCPUName(const ArgList &Args, const llvm::Triple &T,
|
||||||
|
|
||||||
return TargetCPUName;
|
return TargetCPUName;
|
||||||
}
|
}
|
||||||
|
case llvm::Triple::riscv32:
|
||||||
|
case llvm::Triple::riscv64:
|
||||||
|
if (const Arg *A = Args.getLastArg(options::OPT_mcpu_EQ))
|
||||||
|
return A->getValue();
|
||||||
|
return "";
|
||||||
|
|
||||||
case llvm::Triple::bpfel:
|
case llvm::Triple::bpfel:
|
||||||
case llvm::Triple::bpfeb:
|
case llvm::Triple::bpfeb:
|
||||||
|
|
|
@ -156,9 +156,9 @@
|
||||||
// RV32-LOWER: error: invalid arch name 'rv32imC',
|
// RV32-LOWER: error: invalid arch name 'rv32imC',
|
||||||
// RV32-LOWER: string must be lowercase
|
// RV32-LOWER: string must be lowercase
|
||||||
|
|
||||||
// RUN: %clang -target riscv32-unknown-elf -march=rv32 -### %s \
|
// RUN: %clang -target riscv32-unknown-elf -march=unknown -### %s \
|
||||||
// RUN: -fsyntax-only 2>&1 | FileCheck -check-prefix=RV32-STR %s
|
// RUN: -fsyntax-only 2>&1 | FileCheck -check-prefix=RV32-STR %s
|
||||||
// RV32-STR: error: invalid arch name 'rv32',
|
// RV32-STR: error: invalid arch name 'unknown',
|
||||||
// RV32-STR: string must begin with rv32{i,e,g} or rv64{i,g}
|
// RV32-STR: string must begin with rv32{i,e,g} or rv64{i,g}
|
||||||
|
|
||||||
// RUN: %clang -target riscv32-unknown-elf -march=rv32q -### %s \
|
// RUN: %clang -target riscv32-unknown-elf -march=rv32q -### %s \
|
||||||
|
|
|
@ -0,0 +1,38 @@
|
||||||
|
// Check target CPUs are correctly passed.
|
||||||
|
|
||||||
|
// RUN: %clang -target riscv32 -### -c %s 2>&1 -mcpu=rocket-rv32 | FileCheck -check-prefix=MCPU-ROCKETCHIP32 %s
|
||||||
|
// MCPU-ROCKETCHIP32: "-nostdsysteminc" "-target-cpu" "rocket-rv32"
|
||||||
|
|
||||||
|
// RUN: %clang -target riscv64 -### -c %s 2>&1 -mcpu=rocket-rv64 | FileCheck -check-prefix=MCPU-ROCKETCHIP64 %s
|
||||||
|
// MCPU-ROCKETCHIP64: "-nostdsysteminc" "-target-cpu" "rocket-rv64"
|
||||||
|
// MCPU-ROCKETCHIP64: "-target-feature" "+64bit"
|
||||||
|
|
||||||
|
// mcpu with default march
|
||||||
|
// RUN: %clang -target riscv64 -### -c %s 2>&1 -mcpu=sifive-u54 | FileCheck -check-prefix=MCPU-SIFIVE-U54 %s
|
||||||
|
// MCPU-SIFIVE-U54: "-nostdsysteminc" "-target-cpu" "sifive-u54"
|
||||||
|
// MCPU-SIFIVE-U54: "-target-feature" "+m" "-target-feature" "+a" "-target-feature" "+f" "-target-feature" "+d"
|
||||||
|
// MCPU-SIFIVE-U54: "-target-feature" "+c" "-target-feature" "+64bit"
|
||||||
|
// MCPU-SIFIVE-U54: "-target-abi" "lp64d"
|
||||||
|
|
||||||
|
// mcpu with mabi option
|
||||||
|
// RUN: %clang -target riscv64 -### -c %s 2>&1 -mcpu=sifive-u54 -mabi=lp64 | FileCheck -check-prefix=MCPU-ABI-SIFIVE-U54 %s
|
||||||
|
// MCPU-ABI-SIFIVE-U54: "-nostdsysteminc" "-target-cpu" "sifive-u54"
|
||||||
|
// MCPU-ABI-SIFIVE-U54: "-target-feature" "+m" "-target-feature" "+a" "-target-feature" "+f" "-target-feature" "+d"
|
||||||
|
// MCPU-ABI-SIFIVE-U54: "-target-feature" "+c" "-target-feature" "+64bit"
|
||||||
|
// MCPU-ABI-SIFIVE-U54: "-target-abi" "lp64"
|
||||||
|
|
||||||
|
// march overwirte mcpu's default march
|
||||||
|
// RUN: %clang -target riscv32 -### -c %s 2>&1 -mcpu=sifive-e31 -march=rv32imc | FileCheck -check-prefix=MCPU-MARCH %s
|
||||||
|
// MCPU-MARCH: "-nostdsysteminc" "-target-cpu" "sifive-e31" "-target-feature" "+m" "-target-feature" "+c"
|
||||||
|
// MCPU-MARCH: "-target-abi" "ilp32"
|
||||||
|
|
||||||
|
// Check failed cases
|
||||||
|
|
||||||
|
// RUN: %clang -target riscv32 -### -c %s 2>&1 -mcpu=generic-rv321 | FileCheck -check-prefix=FAIL-MCPU-NAME %s
|
||||||
|
// FAIL-MCPU-NAME: error: the clang compiler does not support '-mcpu=generic-rv321'
|
||||||
|
|
||||||
|
// RUN: %clang -target riscv32 -### -c %s 2>&1 -mcpu=generic-rv32 -march=rv64i | FileCheck -check-prefix=MISMATCH-ARCH %s
|
||||||
|
// MISMATCH-ARCH: error: the clang compiler does not support '-mcpu=generic-rv32'
|
||||||
|
|
||||||
|
// RUN: %clang -target riscv32 -### -c %s 2>&1 -mcpu=generic-rv64 | FileCheck -check-prefix=MISMATCH-MCPU %s
|
||||||
|
// MISMATCH-MCPU: error: the clang compiler does not support '-mcpu=generic-rv64'
|
|
@ -156,3 +156,10 @@
|
||||||
// AVR-SAME: ttiny4, attiny5, attiny9, attiny10, attiny20, attiny40, attiny102,
|
// AVR-SAME: ttiny4, attiny5, attiny9, attiny10, attiny20, attiny40, attiny102,
|
||||||
// AVR-SAME: attiny104
|
// AVR-SAME: attiny104
|
||||||
|
|
||||||
|
// RUN: not %clang_cc1 -triple riscv32 -target-cpu not-a-cpu -fsyntax-only %s 2>&1 | FileCheck %s --check-prefix RISCV32
|
||||||
|
// RISCV32: error: unknown target CPU 'not-a-cpu'
|
||||||
|
// RISCV32: note: valid target CPU values are: generic-rv32, rocket-rv32, sifive-e31
|
||||||
|
|
||||||
|
// RUN: not %clang_cc1 -triple riscv64 -target-cpu not-a-cpu -fsyntax-only %s 2>&1 | FileCheck %s --check-prefix RISCV64
|
||||||
|
// RISCV64: error: unknown target CPU 'not-a-cpu'
|
||||||
|
// RISCV64: note: valid target CPU values are: generic-rv64, rocket-rv64, sifive-u54
|
||||||
|
|
|
@ -0,0 +1,13 @@
|
||||||
|
#ifndef PROC
|
||||||
|
#define PROC(ENUM, NAME, FEATURES, DEFAULT_MARCH)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
PROC(INVALID, {"invalid"}, FK_INVALID, {""})
|
||||||
|
PROC(GENERIC_RV32, {"generic-rv32"}, FK_NONE, {""})
|
||||||
|
PROC(GENERIC_RV64, {"generic-rv64"}, FK_64BIT, {""})
|
||||||
|
PROC(ROCKET_RV32, {"rocket-rv32"}, FK_NONE, {""})
|
||||||
|
PROC(ROCKET_RV64, {"rocket-rv64"}, FK_64BIT, {""})
|
||||||
|
PROC(SIFIVE_E31, {"sifive-e31"}, FK_NONE, {"rv32imac"})
|
||||||
|
PROC(SIFIVE_U54, {"sifive-u54"}, FK_64BIT, {"rv64gc"})
|
||||||
|
|
||||||
|
#undef PROC
|
|
@ -130,6 +130,32 @@ IsaVersion getIsaVersion(StringRef GPU);
|
||||||
|
|
||||||
} // namespace AMDGPU
|
} // namespace AMDGPU
|
||||||
|
|
||||||
|
namespace RISCV {
|
||||||
|
|
||||||
|
enum CPUKind : unsigned {
|
||||||
|
#define PROC(ENUM, NAME, FEATURES, DEFAULT_MARCH) CK_##ENUM,
|
||||||
|
#include "RISCVTargetParser.def"
|
||||||
|
};
|
||||||
|
|
||||||
|
enum FeatureKind : unsigned {
|
||||||
|
FK_INVALID = 0,
|
||||||
|
FK_NONE = 1,
|
||||||
|
FK_STDEXTM = 1 << 2,
|
||||||
|
FK_STDEXTA = 1 << 3,
|
||||||
|
FK_STDEXTF = 1 << 4,
|
||||||
|
FK_STDEXTD = 1 << 5,
|
||||||
|
FK_STDEXTC = 1 << 6,
|
||||||
|
FK_64BIT = 1 << 7,
|
||||||
|
};
|
||||||
|
|
||||||
|
bool checkCPUKind(CPUKind Kind, bool IsRV64);
|
||||||
|
CPUKind parseCPUKind(StringRef CPU);
|
||||||
|
StringRef getMArchFromMcpu(StringRef CPU);
|
||||||
|
void fillValidCPUArchList(SmallVectorImpl<StringRef> &Values, bool IsRV64);
|
||||||
|
bool getCPUFeaturesExceptStdExt(CPUKind Kind, std::vector<StringRef> &Features);
|
||||||
|
|
||||||
|
} // namespace RISCV
|
||||||
|
|
||||||
} // namespace llvm
|
} // namespace llvm
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -11,11 +11,12 @@
|
||||||
//
|
//
|
||||||
//===----------------------------------------------------------------------===//
|
//===----------------------------------------------------------------------===//
|
||||||
|
|
||||||
#include "llvm/Support/ARMBuildAttributes.h"
|
|
||||||
#include "llvm/Support/TargetParser.h"
|
#include "llvm/Support/TargetParser.h"
|
||||||
#include "llvm/ADT/ArrayRef.h"
|
#include "llvm/ADT/ArrayRef.h"
|
||||||
|
#include "llvm/ADT/SmallString.h"
|
||||||
#include "llvm/ADT/StringSwitch.h"
|
#include "llvm/ADT/StringSwitch.h"
|
||||||
#include "llvm/ADT/Twine.h"
|
#include "llvm/ADT/Twine.h"
|
||||||
|
#include "llvm/Support/ARMBuildAttributes.h"
|
||||||
|
|
||||||
using namespace llvm;
|
using namespace llvm;
|
||||||
using namespace AMDGPU;
|
using namespace AMDGPU;
|
||||||
|
@ -208,3 +209,64 @@ AMDGPU::IsaVersion AMDGPU::getIsaVersion(StringRef GPU) {
|
||||||
default: return {0, 0, 0};
|
default: return {0, 0, 0};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
namespace llvm {
|
||||||
|
namespace RISCV {
|
||||||
|
|
||||||
|
struct CPUInfo {
|
||||||
|
StringLiteral Name;
|
||||||
|
CPUKind Kind;
|
||||||
|
unsigned Features;
|
||||||
|
StringLiteral DefaultMarch;
|
||||||
|
bool is64Bit() const { return (Features & FK_64BIT); }
|
||||||
|
};
|
||||||
|
|
||||||
|
constexpr CPUInfo RISCVCPUInfo[] = {
|
||||||
|
#define PROC(ENUM, NAME, FEATURES, DEFAULT_MARCH) \
|
||||||
|
{NAME, CK_##ENUM, FEATURES, DEFAULT_MARCH},
|
||||||
|
#include "llvm/Support/RISCVTargetParser.def"
|
||||||
|
};
|
||||||
|
|
||||||
|
bool checkCPUKind(CPUKind Kind, bool IsRV64) {
|
||||||
|
if (Kind == CK_INVALID)
|
||||||
|
return false;
|
||||||
|
return RISCVCPUInfo[static_cast<unsigned>(Kind)].is64Bit() == IsRV64;
|
||||||
|
}
|
||||||
|
|
||||||
|
CPUKind parseCPUKind(StringRef CPU) {
|
||||||
|
return llvm::StringSwitch<CPUKind>(CPU)
|
||||||
|
#define PROC(ENUM, NAME, FEATURES, DEFAULT_MARCH) .Case(NAME, CK_##ENUM)
|
||||||
|
#include "llvm/Support/RISCVTargetParser.def"
|
||||||
|
.Default(CK_INVALID);
|
||||||
|
}
|
||||||
|
|
||||||
|
StringRef getMArchFromMcpu(StringRef CPU) {
|
||||||
|
CPUKind Kind = parseCPUKind(CPU);
|
||||||
|
return RISCVCPUInfo[static_cast<unsigned>(Kind)].DefaultMarch;
|
||||||
|
}
|
||||||
|
|
||||||
|
void fillValidCPUArchList(SmallVectorImpl<StringRef> &Values, bool IsRV64) {
|
||||||
|
for (const auto &C : RISCVCPUInfo) {
|
||||||
|
if (C.Kind != CK_INVALID && IsRV64 == C.is64Bit())
|
||||||
|
Values.emplace_back(C.Name);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get all features except standard extension feature
|
||||||
|
bool getCPUFeaturesExceptStdExt(CPUKind Kind,
|
||||||
|
std::vector<StringRef> &Features) {
|
||||||
|
unsigned CPUFeatures = RISCVCPUInfo[static_cast<unsigned>(Kind)].Features;
|
||||||
|
|
||||||
|
if (CPUFeatures == FK_INVALID)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
if (CPUFeatures & FK_64BIT)
|
||||||
|
Features.push_back("+64bit");
|
||||||
|
else
|
||||||
|
Features.push_back("-64bit");
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace RISCV
|
||||||
|
} // namespace llvm
|
||||||
|
|
|
@ -215,6 +215,16 @@ def : ProcessorModel<"rocket-rv32", Rocket32Model, []>;
|
||||||
|
|
||||||
def : ProcessorModel<"rocket-rv64", Rocket64Model, [Feature64Bit]>;
|
def : ProcessorModel<"rocket-rv64", Rocket64Model, [Feature64Bit]>;
|
||||||
|
|
||||||
|
def : ProcessorModel<"sifive-e31", Rocket32Model, [FeatureStdExtM,
|
||||||
|
FeatureStdExtA,
|
||||||
|
FeatureStdExtC]>;
|
||||||
|
|
||||||
|
def : ProcessorModel<"sifive-u54", Rocket64Model, [Feature64Bit,
|
||||||
|
FeatureStdExtM,
|
||||||
|
FeatureStdExtA,
|
||||||
|
FeatureStdExtF,
|
||||||
|
FeatureStdExtD,
|
||||||
|
FeatureStdExtC]>;
|
||||||
|
|
||||||
//===----------------------------------------------------------------------===//
|
//===----------------------------------------------------------------------===//
|
||||||
// Define the RISC-V target.
|
// Define the RISC-V target.
|
||||||
|
|
Loading…
Reference in New Issue