Skip to content

[RISC-V] Add support for MIPS P8700 CPU #117865

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
wants to merge 6 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions clang/include/clang/Driver/Options.td
Original file line number Diff line number Diff line change
Expand Up @@ -4937,6 +4937,11 @@ def msave_restore : Flag<["-"], "msave-restore">, Group<m_riscv_Features_Group>,
def mno_save_restore : Flag<["-"], "mno-save-restore">, Group<m_riscv_Features_Group>,
HelpText<"Disable using library calls for save and restore">;
} // let Flags = [TargetSpecific]
def mload_store_pairs : Flag<["-"], "mload-store-pairs">, Group<m_riscv_Features_Group>;
def mno_load_store_pairs : Flag<["-"], "mno-load-store-pairs">, Group<m_riscv_Features_Group>;
def mccmov : Flag<["-"], "mccmov">, Group<m_riscv_Features_Group>;
def mno_ccmov : Flag<["-"], "mno-ccmov">, Group<m_riscv_Features_Group>;
def mremove_back_to_back_branches : Flag<["-"], "mremove_back_to_back_branches">, Group<m_riscv_Features_Group>;
let Flags = [TargetSpecific] in {
def menable_experimental_extensions : Flag<["-"], "menable-experimental-extensions">, Group<m_Group>,
HelpText<"Enable use of experimental RISC-V extensions.">;
Expand Down
10 changes: 8 additions & 2 deletions clang/lib/Driver/ToolChains/Arch/RISCV.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -336,12 +336,14 @@ std::string riscv::getRISCVArch(const llvm::opt::ArgList &Args,
// - On `riscv{XLEN}-unknown-elf` we default to `rv{XLEN}imac`
// - On all other OSs we use `rv{XLEN}imafdc` (equivalent to `rv{XLEN}gc`)
if (Triple.isRISCV32()) {
if (Triple.getOS() == llvm::Triple::UnknownOS)
if (Triple.getOS() == llvm::Triple::UnknownOS &&
Triple.getVendor() != llvm::Triple::MipsTechnologies)
return "rv32imac";
else
return "rv32imafdc";
} else {
if (Triple.getOS() == llvm::Triple::UnknownOS)
if (Triple.getOS() == llvm::Triple::UnknownOS &&
Triple.getVendor() != llvm::Triple::MipsTechnologies)
return "rv64imac";
else if (Triple.isAndroid())
return "rv64imafdcv_zba_zbb_zbs";
Expand All @@ -364,5 +366,9 @@ std::string riscv::getRISCVTargetCPU(const llvm::opt::ArgList &Args,
if (!CPU.empty())
return CPU;

if (Triple.getVendor() == llvm::Triple::MipsTechnologies &&
Triple.isRISCV64())
return "p8700";

return Triple.isRISCV64() ? "generic-rv64" : "generic-rv32";
}
18 changes: 18 additions & 0 deletions clang/lib/Driver/ToolChains/Clang.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2164,6 +2164,24 @@ void Clang::AddRISCVTargetArgs(const ArgList &Args,
CmdArgs.push_back(A->getValue());
}

if (Arg *A = Args.getLastArg(options::OPT_mload_store_pairs,
options::OPT_mno_load_store_pairs)) {
if (A->getOption().matches(options::OPT_mload_store_pairs)) {
CmdArgs.push_back("-mllvm");
CmdArgs.push_back("-riscv-load-store-pairs=1");
}
}

if (Arg *A = Args.getLastArg(options::OPT_mccmov, options::OPT_mno_ccmov)) {
if (A->getOption().matches(options::OPT_mno_ccmov)) {
CmdArgs.push_back("-mllvm");
CmdArgs.push_back("-riscv-ccmov=0");
}
}
if (Args.getLastArg(options::OPT_mremove_back_to_back_branches)) {
CmdArgs.push_back("-mllvm");
CmdArgs.push_back("-riscv-remove-back-to-back-branches=1");
}
// Handle -mrvv-vector-bits=<bits>
if (Arg *A = Args.getLastArg(options::OPT_mrvv_vector_bits_EQ)) {
StringRef Val = A->getValue();
Expand Down
119 changes: 113 additions & 6 deletions clang/lib/Driver/ToolChains/Gnu.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -252,9 +252,17 @@ static const char *getLDMOption(const llvm::Triple &T, const ArgList &Args) {
case llvm::Triple::ppc64le:
return "elf64lppc";
case llvm::Triple::riscv32:
return "elf32lriscv";
case llvm::Triple::riscv64:
return "elf64lriscv";
case llvm::Triple::riscv64: {
bool IsBigEndian = false;
if (Arg *A = Args.getLastArg(options::OPT_mlittle_endian,
options::OPT_mbig_endian))
IsBigEndian = A->getOption().matches(options::OPT_mbig_endian);

if (T.getArch() == llvm::Triple::riscv32)
return IsBigEndian ? "elf32briscv" : "elf32lriscv";
else
return IsBigEndian ? "elf64briscv" : "elf64lriscv";
}
Comment on lines +255 to +265
Copy link
Member

@alexrp alexrp Nov 27, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Best as I can tell, this would make RISC-V the only architecture for which there aren't any llvm::Triple::ArchType members distinguishing little-endian vs big-endian? That seems like a strange precedent to set.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Best as I can tell, this would make RISC-V the only architecture for which there aren't any llvm::Triple::ArchType members distinguishing little-endian vs big-endian? That seems like a strange precedent to set.

There had been a patch a long time ago to add riscv32be and riscv64be. Not sure if it was in github or if it got left behind in phabricator.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I will drop this part for now, since it is dummy/unsed for now. I am planning to create/add support for BE, once we are done with these p8700 patches.
This was a patch on Phabricator: https://reviews.llvm.org/D128612

case llvm::Triple::sparc:
case llvm::Triple::sparcel:
return "elf32_sparc";
Expand Down Expand Up @@ -402,6 +410,14 @@ void tools::gnutools::Linker::ConstructJob(Compilation &C, const JobAction &JA,
CmdArgs.push_back(Arch == llvm::Triple::aarch64_be ? "-EB" : "-EL");
}

if (Triple.isRISCV() &&
Triple.getVendor() == llvm::Triple::MipsTechnologies) {
bool IsBigEndian = false;
if (Arg *A = Args.getLastArg(options::OPT_mlittle_endian,
options::OPT_mbig_endian))
IsBigEndian = A->getOption().matches(options::OPT_mbig_endian);
CmdArgs.push_back(IsBigEndian ? "-EB" : "-EL");
}
// Most Android ARM64 targets should enable the linker fix for erratum
// 843419. Only non-Cortex-A53 devices are allowed to skip this flag.
if (Arch == llvm::Triple::aarch64 && (isAndroid || isOHOSFamily)) {
Expand Down Expand Up @@ -765,7 +781,8 @@ void tools::gnutools::Assembler::ConstructJob(Compilation &C,
}
case llvm::Triple::riscv32:
case llvm::Triple::riscv64: {
StringRef ABIName = riscv::getRISCVABI(Args, getToolChain().getTriple());
const llvm::Triple &Triple = getToolChain().getTriple();
StringRef ABIName = riscv::getRISCVABI(Args, Triple);
CmdArgs.push_back("-mabi");
CmdArgs.push_back(ABIName.data());
std::string MArchName =
Expand All @@ -774,6 +791,14 @@ void tools::gnutools::Assembler::ConstructJob(Compilation &C,
CmdArgs.push_back(Args.MakeArgString(MArchName));
if (!Args.hasFlag(options::OPT_mrelax, options::OPT_mno_relax, true))
Args.addOptOutFlag(CmdArgs, options::OPT_mrelax, options::OPT_mno_relax);

if (Triple.getVendor() == llvm::Triple::MipsTechnologies) {
bool IsBigEndian = false;
if (Arg *A = Args.getLastArg(options::OPT_mlittle_endian,
options::OPT_mbig_endian))
IsBigEndian = A->getOption().matches(options::OPT_mbig_endian);
CmdArgs.push_back(IsBigEndian ? "-EB" : "-EL");
}
break;
}
case llvm::Triple::sparc:
Expand Down Expand Up @@ -1873,9 +1898,18 @@ static void findRISCVBareMetalMultilibs(const Driver &D,
.flag(Twine("-march=", Element.march).str())
.flag(Twine("-mabi=", Element.mabi).str()));
}
SmallVector<MultilibBuilder, 2> Endian;
if (TargetTriple.getVendor() == llvm::Triple::MipsTechnologies) {
Endian.push_back(
MultilibBuilder("/riscv").flag("-EL").flag("-EB", /*Disallow=*/true));
Endian.push_back(
MultilibBuilder("/riscveb").flag("-EB").flag("-EL", /*Disallow=*/true));
}
MultilibSet RISCVMultilibs =
MultilibSetBuilder()
.Either(Ms)
.Either(Endian)
.Either(ArrayRef<MultilibBuilder>(Ms))
.makeMultilibSet()
.FilterOut(NonExistent)
.setFilePathsCallback([](const Multilib &M) {
Expand All @@ -1899,6 +1933,19 @@ static void findRISCVBareMetalMultilibs(const Driver &D,
}
}

bool IsBigEndian = false;
if (Arg *A = Args.getLastArg(options::OPT_mlittle_endian,
options::OPT_mbig_endian))
IsBigEndian = A->getOption().matches(options::OPT_mbig_endian);

if (IsBigEndian) {
D.Diag(diag::err_drv_unsupported_opt_for_target)
<< "-EB" << TargetTriple.str();
}

addMultilibFlag(IsBigEndian, "-EB", Flags);
addMultilibFlag(!IsBigEndian, "-EL", Flags);

if (selectRISCVMultilib(D, RISCVMultilibs, MArch, Flags,
Result.SelectedMultilibs))
Result.Multilibs = RISCVMultilibs;
Expand All @@ -1923,15 +1970,34 @@ static void findRISCVMultilibs(const Driver &D,
MultilibBuilder("lib64/lp64f").flag("-m64").flag("-mabi=lp64f");
MultilibBuilder Lp64d =
MultilibBuilder("lib64/lp64d").flag("-m64").flag("-mabi=lp64d");

SmallVector<MultilibBuilder, 2> Endian;
if (TargetTriple.getVendor() == llvm::Triple::MipsTechnologies) {
Endian.push_back(
MultilibBuilder("/riscv").flag("-EL").flag("-EB", /*Disallow=*/true));
Endian.push_back(
MultilibBuilder("/riscveb").flag("-EB").flag("-EL", /*Disallow=*/true));
}

MultilibSet RISCVMultilibs =
MultilibSetBuilder()
.Either(Endian)
.Either({Ilp32, Ilp32f, Ilp32d, Lp64, Lp64f, Lp64d})
.makeMultilibSet()
.FilterOut(NonExistent);

Multilib::flags_list Flags;
bool IsRV64 = TargetTriple.getArch() == llvm::Triple::riscv64;
StringRef ABIName = tools::riscv::getRISCVABI(Args, TargetTriple);
bool IsBigEndian = false;
if (Arg *A = Args.getLastArg(options::OPT_mlittle_endian,
options::OPT_mbig_endian))
IsBigEndian = A->getOption().matches(options::OPT_mbig_endian);

if (IsBigEndian) {
D.Diag(diag::err_drv_unsupported_opt_for_target)
<< "-EB" << TargetTriple.str();
}

addMultilibFlag(!IsRV64, "-m32", Flags);
addMultilibFlag(IsRV64, "-m64", Flags);
Expand All @@ -1941,6 +2007,8 @@ static void findRISCVMultilibs(const Driver &D,
addMultilibFlag(ABIName == "lp64", "-mabi=lp64", Flags);
addMultilibFlag(ABIName == "lp64f", "-mabi=lp64f", Flags);
addMultilibFlag(ABIName == "lp64d", "-mabi=lp64d", Flags);
addMultilibFlag(IsBigEndian, "-EB", Flags);
addMultilibFlag(!IsBigEndian, "-EL", Flags);

if (RISCVMultilibs.select(D, Flags, Result.SelectedMultilibs))
Result.Multilibs = RISCVMultilibs;
Expand Down Expand Up @@ -2565,8 +2633,8 @@ void Generic_GCC::GCCInstallationDetector::AddDefaultGCCPrefixes(
static const char *const RISCV32Triples[] = {"riscv32-unknown-linux-gnu",
"riscv32-unknown-elf"};
static const char *const RISCV64LibDirs[] = {"/lib64", "/lib"};
static const char *const RISCV64Triples[] = {"riscv64-unknown-linux-gnu",
"riscv64-unknown-elf"};
static const char *const RISCV64Triples[] = {
"riscv64-unknown-linux-gnu", "riscv64-unknown-elf", "riscv64-mti-elf"};

static const char *const SPARCv8LibDirs[] = {"/lib32", "/lib"};
static const char *const SPARCv8Triples[] = {"sparc-linux-gnu",
Expand Down Expand Up @@ -3137,6 +3205,45 @@ bool Generic_GCC::IsIntegratedAssemblerDefault() const {
case llvm::Triple::nvptx64:
case llvm::Triple::xcore:
return false;
case llvm::Triple::aarch64:
case llvm::Triple::aarch64_be:
case llvm::Triple::amdgcn:
case llvm::Triple::arm:
case llvm::Triple::armeb:
case llvm::Triple::avr:
case llvm::Triple::bpfel:
case llvm::Triple::bpfeb:
case llvm::Triple::csky:
case llvm::Triple::hexagon:
case llvm::Triple::lanai:
case llvm::Triple::loongarch32:
case llvm::Triple::loongarch64:
case llvm::Triple::m68k:
case llvm::Triple::mips:
case llvm::Triple::mipsel:
case llvm::Triple::mips64:
case llvm::Triple::mips64el:
case llvm::Triple::msp430:
case llvm::Triple::ppc:
case llvm::Triple::ppcle:
case llvm::Triple::ppc64:
case llvm::Triple::ppc64le:
case llvm::Triple::r600:
case llvm::Triple::sparc:
case llvm::Triple::sparcel:
case llvm::Triple::sparcv9:
case llvm::Triple::systemz:
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Remove this whole chunk.

case llvm::Triple::thumb:
case llvm::Triple::thumbeb:
case llvm::Triple::ve:
case llvm::Triple::x86:
case llvm::Triple::x86_64:
return true;
case llvm::Triple::riscv32:
case llvm::Triple::riscv64:
if (getTriple().getVendor() != llvm::Triple::MipsTechnologies)
return true;
return false;
default:
return true;
}
Expand Down
25 changes: 22 additions & 3 deletions clang/lib/Driver/ToolChains/Linux.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -274,11 +274,14 @@ Linux::Linux(const Driver &D, const llvm::Triple &Triple, const ArgList &Args)
const bool IsHexagon = Arch == llvm::Triple::hexagon;
const bool IsRISCV = Triple.isRISCV();
const bool IsCSKY = Triple.isCSKY();
const bool IsMipsSysRoot =
IsMips ||
(IsRISCV && Triple.getVendor() == llvm::Triple::MipsTechnologies);

if (IsCSKY && !SelectedMultilibs.empty())
SysRoot = SysRoot + SelectedMultilibs.back().osSuffix();

if ((IsMips || IsCSKY) && !SysRoot.empty())
if ((IsMipsSysRoot || IsCSKY) && !SysRoot.empty())
ExtraOpts.push_back("--sysroot=" + SysRoot);

// Do not use 'gnu' hash style for Mips targets because .gnu.hash
Expand Down Expand Up @@ -412,7 +415,12 @@ std::string Linux::computeSysRoot() const {
return std::string();
}

if (!GCCInstallation.isValid() || !getTriple().isMIPS())
const bool IsMipsSysRoot =
getTriple().isMIPS() ||
(getTriple().isRISCV() &&
getTriple().getVendor() == llvm::Triple::MipsTechnologies);

if (!GCCInstallation.isValid() || !IsMipsSysRoot)
return std::string();

// Standalone MIPS toolchains use different names for sysroot folder
Expand All @@ -422,8 +430,19 @@ std::string Linux::computeSysRoot() const {
const StringRef InstallDir = GCCInstallation.getInstallPath();
const StringRef TripleStr = GCCInstallation.getTriple().str();
const Multilib &Multilib = GCCInstallation.getMultilib();
std::string Path;
if (getTriple().isRISCV()) {
Path =
(InstallDir + "/../../../../sysroot" + Multilib.osSuffix() + "/../..")
.str();

if (getVFS().exists(Path))
return Path;

return std::string();
}

std::string Path =
Path =
(InstallDir + "/../../../../" + TripleStr + "/libc" + Multilib.osSuffix())
.str();

Expand Down
18 changes: 16 additions & 2 deletions clang/lib/Driver/ToolChains/RISCVToolchain.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -77,8 +77,8 @@ Tool *RISCVToolChain::buildLinker() const {
}

ToolChain::RuntimeLibType RISCVToolChain::GetDefaultRuntimeLibType() const {
return GCCInstallation.isValid() ?
ToolChain::RLT_Libgcc : ToolChain::RLT_CompilerRT;
return GCCInstallation.isValid() ? ToolChain::RLT_Libgcc
: ToolChain::RLT_CompilerRT;
}

ToolChain::UnwindLibType
Expand Down Expand Up @@ -173,6 +173,14 @@ void RISCV::Linker::ConstructJob(Compilation &C, const JobAction &JA,
}
CmdArgs.push_back("-X");

if (ToolChain.getTriple().getVendor() == llvm::Triple::MipsTechnologies) {
bool IsBigEndian = false;
if (Arg *A = Args.getLastArg(options::OPT_mlittle_endian,
options::OPT_mbig_endian))
IsBigEndian = A->getOption().matches(options::OPT_mbig_endian);
CmdArgs.push_back(IsBigEndian ? "-EB" : "-EL");
}

std::string Linker = getToolChain().GetLinkerPath();

bool WantCRTs =
Expand Down Expand Up @@ -229,4 +237,10 @@ void RISCV::Linker::ConstructJob(Compilation &C, const JobAction &JA,
JA, *this, ResponseFileSupport::AtFileCurCP(), Args.MakeArgString(Linker),
CmdArgs, Inputs, Output));
}

bool RISCVToolChain::IsIntegratedAssemblerDefault() const {
if (getTriple().getVendor() != llvm::Triple::MipsTechnologies)
return true;
return false;
}
// RISCV tools end.
1 change: 1 addition & 0 deletions clang/lib/Driver/ToolChains/RISCVToolchain.h
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ class LLVM_LIBRARY_VISIBILITY RISCVToolChain : public Generic_ELF {
const llvm::opt::ArgList &Args);

static bool hasGCCToolchain(const Driver &D, const llvm::opt::ArgList &Args);
bool IsIntegratedAssemblerDefault() const override;
void addClangTargetOptions(const llvm::opt::ArgList &DriverArgs,
llvm::opt::ArgStringList &CC1Args,
Action::OffloadKind) const override;
Expand Down
2 changes: 2 additions & 0 deletions clang/test/Misc/target-invalid-cpu-note/riscv.c
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@
// RISCV64: error: unknown target CPU 'not-a-cpu'
// RISCV64-NEXT: note: valid target CPU values are:
// RISCV64-SAME: {{^}} generic-rv64
// RISCV64-SAME: {{^}}, mips-p8700
// RISCV64-SAME: {{^}}, rocket-rv64
// RISCV64-SAME: {{^}}, sifive-p450
// RISCV64-SAME: {{^}}, sifive-p470
Expand Down Expand Up @@ -72,6 +73,7 @@
// TUNE-RISCV64: error: unknown target CPU 'not-a-cpu'
// TUNE-RISCV64-NEXT: note: valid target CPU values are:
// TUNE-RISCV64-SAME: {{^}} generic-rv64
// TUNE-RISCV64-SAME: {{^}}, mips-p8700
// TUNE-RISCV64-SAME: {{^}}, rocket-rv64
// TUNE-RISCV64-SAME: {{^}}, sifive-p450
// TUNE-RISCV64-SAME: {{^}}, sifive-p470
Expand Down
6 changes: 6 additions & 0 deletions llvm/docs/RISCVUsage.rst
Original file line number Diff line number Diff line change
Expand Up @@ -426,6 +426,12 @@ The current vendor extensions supported are:
``Xwchc``
LLVM implements `the custom compressed opcodes present in some QingKe cores` by WCH / Nanjing Qinheng Microelectronics. The vendor refers to these opcodes by the name "XW".

``xmipscmove``
LLVM implements conditional move for the `p8700 processor <https://mips.com/products/hardware/p8700/>` by MIPS.

``xmipslsp``
LLVM implements load/store pair instructions for the `p8700 processor <https://mips.com/products/hardware/p8700/>` by MIPS.

Experimental C Intrinsics
=========================

Expand Down
Loading