Skip to content
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

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

Draft
wants to merge 6 commits into
base: main
Choose a base branch
from

Conversation

djtodoro
Copy link
Collaborator

@djtodoro djtodoro commented Nov 27, 2024

The P8700 is a high-performance processor from MIPS designed to meet the demands of modern workloads, offering exceptional scalability and efficiency. It builds on MIPS's established architectural strengths while introducing enhancements that set it apart. For more details, you can check out the official product page here: https://mips.com/products/hardware/p8700/.

RFC: https://discourse.llvm.org/t/rfc-risc-v-add-support-for-mips-p8700-cpu/83365

@djtodoro djtodoro marked this pull request as draft November 27, 2024 10:32
@llvmbot llvmbot added clang Clang issues not falling into any other category backend:RISC-V clang:driver 'clang' and 'clang++' user-facing binaries. Not 'clang-cl' mc Machine (object) code llvm:globalisel labels Nov 27, 2024
@llvmbot
Copy link
Member

llvmbot commented Nov 27, 2024

@llvm/pr-subscribers-clang
@llvm/pr-subscribers-clang-driver
@llvm/pr-subscribers-backend-risc-v

@llvm/pr-subscribers-llvm-globalisel

Author: Djordje Todorovic (djtodoro)

Changes

The P8700 is a high-performance processor from MIPS designed to meet the demands of modern workloads, offering exceptional scalability and efficiency. It builds on MIPS's established architectural strengths while introducing enhancements that set it apart. For more details, you can check out the official product page here: https://mips.com/products/hardware/p8700/.

RFC: TODO


Patch is 143.83 KiB, truncated to 20.00 KiB below, full version: https://github.com/llvm/llvm-project/pull/117865.diff

48 Files Affected:

  • (modified) clang/include/clang/Driver/Options.td (+5)
  • (modified) clang/lib/Driver/ToolChains/Arch/RISCV.cpp (+8-2)
  • (modified) clang/lib/Driver/ToolChains/Clang.cpp (+19)
  • (modified) clang/lib/Driver/ToolChains/Gnu.cpp (+113-4)
  • (modified) clang/lib/Driver/ToolChains/Linux.cpp (+20-3)
  • (modified) clang/lib/Driver/ToolChains/RISCVToolchain.cpp (+15-1)
  • (modified) clang/lib/Driver/ToolChains/RISCVToolchain.h (+1)
  • (modified) clang/test/Misc/target-invalid-cpu-note/riscv.c (+2)
  • (modified) llvm/docs/RISCVUsage.rst (+6)
  • (modified) llvm/lib/Target/RISCV/AsmParser/RISCVAsmParser.cpp (+10)
  • (modified) llvm/lib/Target/RISCV/CMakeLists.txt (+2)
  • (modified) llvm/lib/Target/RISCV/MCTargetDesc/RISCVBaseInfo.h (+1)
  • (modified) llvm/lib/Target/RISCV/MCTargetDesc/RISCVMCAsmInfo.cpp (+8)
  • (modified) llvm/lib/Target/RISCV/MCTargetDesc/RISCVMCAsmInfo.h (+2)
  • (modified) llvm/lib/Target/RISCV/RISCV.h (+5)
  • (modified) llvm/lib/Target/RISCV/RISCV.td (+1)
  • (modified) llvm/lib/Target/RISCV/RISCVFeatures.td (+17)
  • (modified) llvm/lib/Target/RISCV/RISCVISelLowering.cpp (+3-1)
  • (modified) llvm/lib/Target/RISCV/RISCVInstrFormats.td (+72)
  • (modified) llvm/lib/Target/RISCV/RISCVInstrInfo.cpp (+43)
  • (modified) llvm/lib/Target/RISCV/RISCVInstrInfo.h (+9)
  • (modified) llvm/lib/Target/RISCV/RISCVInstrInfo.td (+220)
  • (modified) llvm/lib/Target/RISCV/RISCVInstrInfoC.td (-125)
  • (modified) llvm/lib/Target/RISCV/RISCVInstrInfoZb.td (+1-1)
  • (added) llvm/lib/Target/RISCV/RISCVLoadStoreOptimizer.cpp (+371)
  • (modified) llvm/lib/Target/RISCV/RISCVProcessors.td (+15-1)
  • (added) llvm/lib/Target/RISCV/RISCVRemoveBackToBackBranches.cpp (+158)
  • (added) llvm/lib/Target/RISCV/RISCVSchedMIPSP8700.td (+279)
  • (modified) llvm/lib/Target/RISCV/RISCVSchedule.td (+1)
  • (modified) llvm/lib/Target/RISCV/RISCVSubtarget.cpp (+38-2)
  • (modified) llvm/lib/Target/RISCV/RISCVSubtarget.h (+4-1)
  • (modified) llvm/lib/Target/RISCV/RISCVTargetMachine.cpp (+36-2)
  • (added) llvm/test/CodeGen/MIR/RISCV/riscv-remove-back-to-back-branches.mir (+108)
  • (modified) llvm/test/CodeGen/RISCV/GlobalISel/rv64zba.ll (+14-14)
  • (modified) llvm/test/CodeGen/RISCV/O0-pipeline.ll (+3-1)
  • (modified) llvm/test/CodeGen/RISCV/O3-pipeline.ll (+4-1)
  • (modified) llvm/test/CodeGen/RISCV/div-by-constant.ll (+1-1)
  • (added) llvm/test/CodeGen/RISCV/load-store-pair.ll (+509)
  • (added) llvm/test/CodeGen/RISCV/riscv-enable-gep-opt.ll (+10)
  • (modified) llvm/test/CodeGen/RISCV/rv64i-exhaustive-w-insts.ll (+50-50)
  • (modified) llvm/test/CodeGen/RISCV/rv64zba.ll (+5-5)
  • (modified) llvm/test/CodeGen/RISCV/select-and.ll (+25)
  • (modified) llvm/test/CodeGen/RISCV/select-bare.ll (+14)
  • (modified) llvm/test/CodeGen/RISCV/select-cc.ll (+86)
  • (modified) llvm/test/CodeGen/RISCV/select-or.ll (+25)
  • (modified) llvm/test/CodeGen/RISCV/xaluo.ll (+11-11)
  • (modified) llvm/test/CodeGen/RISCV/zcb-regalloc-hints.ll (+1-1)
  • (modified) llvm/test/MC/RISCV/rv64zba-aliases-valid.s (+2-2)
diff --git a/clang/include/clang/Driver/Options.td b/clang/include/clang/Driver/Options.td
index e5f2fec88706d8..822ead08392734 100644
--- a/clang/include/clang/Driver/Options.td
+++ b/clang/include/clang/Driver/Options.td
@@ -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.">;
diff --git a/clang/lib/Driver/ToolChains/Arch/RISCV.cpp b/clang/lib/Driver/ToolChains/Arch/RISCV.cpp
index 6935904a24edbf..7a2408477e2d7b 100644
--- a/clang/lib/Driver/ToolChains/Arch/RISCV.cpp
+++ b/clang/lib/Driver/ToolChains/Arch/RISCV.cpp
@@ -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";
@@ -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";
 }
diff --git a/clang/lib/Driver/ToolChains/Clang.cpp b/clang/lib/Driver/ToolChains/Clang.cpp
index d3eec9fea0d498..a2887fe49d940d 100644
--- a/clang/lib/Driver/ToolChains/Clang.cpp
+++ b/clang/lib/Driver/ToolChains/Clang.cpp
@@ -2164,6 +2164,25 @@ 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();
diff --git a/clang/lib/Driver/ToolChains/Gnu.cpp b/clang/lib/Driver/ToolChains/Gnu.cpp
index 8397f1121ec2ce..b404b7ab07894b 100644
--- a/clang/lib/Driver/ToolChains/Gnu.cpp
+++ b/clang/lib/Driver/ToolChains/Gnu.cpp
@@ -252,9 +252,18 @@ 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";
+  {
+    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";
+  }
   case llvm::Triple::sparc:
   case llvm::Triple::sparcel:
     return "elf32_sparc";
@@ -402,6 +411,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)) {
@@ -765,7 +782,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 =
@@ -774,6 +792,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:
@@ -1873,9 +1899,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) {
@@ -1899,6 +1934,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;
@@ -1923,8 +1971,18 @@ 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);
@@ -1932,6 +1990,15 @@ static void findRISCVMultilibs(const Driver &D,
   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);
@@ -1941,6 +2008,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;
@@ -2566,7 +2635,8 @@ void Generic_GCC::GCCInstallationDetector::AddDefaultGCCPrefixes(
                                                "riscv32-unknown-elf"};
   static const char *const RISCV64LibDirs[] = {"/lib64", "/lib"};
   static const char *const RISCV64Triples[] = {"riscv64-unknown-linux-gnu",
-                                               "riscv64-unknown-elf"};
+                                               "riscv64-unknown-elf",
+                                               "riscv64-mti-elf"};
 
   static const char *const SPARCv8LibDirs[] = {"/lib32", "/lib"};
   static const char *const SPARCv8Triples[] = {"sparc-linux-gnu",
@@ -3137,6 +3207,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:
+  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;
   }
diff --git a/clang/lib/Driver/ToolChains/Linux.cpp b/clang/lib/Driver/ToolChains/Linux.cpp
index d1cb625613415b..3759b01b436e5c 100644
--- a/clang/lib/Driver/ToolChains/Linux.cpp
+++ b/clang/lib/Driver/ToolChains/Linux.cpp
@@ -274,11 +274,13 @@ 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
@@ -412,7 +414,11 @@ 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
@@ -422,8 +428,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();
 
diff --git a/clang/lib/Driver/ToolChains/RISCVToolchain.cpp b/clang/lib/Driver/ToolChains/RISCVToolchain.cpp
index 624099d21ae124..6d0e0935135dd9 100644
--- a/clang/lib/Driver/ToolChains/RISCVToolchain.cpp
+++ b/clang/lib/Driver/ToolChains/RISCVToolchain.cpp
@@ -77,7 +77,7 @@ Tool *RISCVToolChain::buildLinker() const {
 }
 
 ToolChain::RuntimeLibType RISCVToolChain::GetDefaultRuntimeLibType() const {
-  return GCCInstallation.isValid() ?
+    return GCCInstallation.isValid() ?
     ToolChain::RLT_Libgcc : ToolChain::RLT_CompilerRT;
 }
 
@@ -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 =
@@ -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.
diff --git a/clang/lib/Driver/ToolChains/RISCVToolchain.h b/clang/lib/Driver/ToolChains/RISCVToolchain.h
index fa0aa265d842bb..c189772cc0d0ca 100644
--- a/clang/lib/Driver/ToolChains/RISCVToolchain.h
+++ b/clang/lib/Driver/ToolChains/RISCVToolchain.h
@@ -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;
diff --git a/clang/test/Misc/target-invalid-cpu-note/riscv.c b/clang/test/Misc/target-invalid-cpu-note/riscv.c
index 8c5df5884cd791..fc8536d99cb804 100644
--- a/clang/test/Misc/target-invalid-cpu-note/riscv.c
+++ b/clang/test/Misc/target-invalid-cpu-note/riscv.c
@@ -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
@@ -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
diff --git a/llvm/docs/RISCVUsage.rst b/llvm/docs/RISCVUsage.rst
index 1317221448ea5b..7fc1f1d49faf4e 100644
--- a/llvm/docs/RISCVUsage.rst
+++ b/llvm/docs/RISCVUsage.rst
@@ -423,6 +423,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
 =========================
 
diff --git a/llvm/lib/Target/RISCV/AsmParser/RISCVAsmParser.cpp b/llvm/lib/Target/RISCV/AsmParser/RISCVAsmParser.cpp
index b843bb5ae43100..4edeb07a0fc980 100644
--- a/llvm/lib/Target/RISCV/AsmParser/RISCVAsmParser.cpp
+++ b/llvm/lib/Target/RISCV/AsmParser/RISCVAsmParser.cpp
@@ -855,6 +855,16 @@ struct RISCVOperand final : public MCParsedAsmOperand {
            VK == RISCVMCExpr::VK_RISCV_None;
   }
 
+  bool isUImm7Lsb000() const {
+    if (!isImm())
+      return false;
+    int64_t Imm;
+    RISCVMCExpr::VariantKind VK = RISCVMCExpr::VK_RISCV_None;
+    bool IsConstantImm = evaluateConstantImm(getImm(), Imm, VK);
+    return IsConstantImm && isShiftedUInt<4, 3>(Imm) &&
+           VK == RISCVMCExpr::VK_RISCV_None;
+  }
+
   bool isUImm8Lsb00() const {
     if (!isImm())
       return false;
diff --git a/llvm/lib/Target/RISCV/CMakeLists.txt b/llvm/lib/Target/RISCV/CMakeLists.txt
index fd049d1a57860e..2f63d7f1e4c39f 100644
--- a/llvm/lib/Target/RISCV/CMakeLists.txt
+++ b/llvm/lib/Target/RISCV/CMakeLists.txt
@@ -47,6 +47,7 @@ add_llvm_target(RISCVCodeGen
   RISCVISelLowering.cpp
   RISCVLandingPadSetup.cpp
   RISCVMachineFunctionInfo.cpp
+  RISCVLoadStoreOptimizer.cpp
   RISCVMergeBaseOffset.cpp
   RISCVOptWInstrs.cpp
   RISCVPostRAExpandPseudoInsts.cpp
@@ -54,6 +55,7 @@ add_llvm_target(RISCVCodeGen
   RISCVMoveMerger.cpp
   RISCVPushPopOptimizer.cpp
   RISCVRegisterInfo.cpp
+  RISCVRemoveBackToBackBranches.cpp
   RISCVSubtarget.cpp
   RISCVTargetMachine.cpp
   RISCVTargetObjectFile.cpp
diff --git a/llvm/lib/Target/RISCV/MCTargetDesc/RISCVBaseInfo.h b/llvm/lib/Target/RISCV/MCTargetDesc/RISCVBaseInfo.h
index 19103e219cb800..746a73b1936810 100644
--- a/llvm/lib/Target/RISCV/MCTargetDesc/RISCVBaseInfo.h
+++ b/llvm/lib/Target/RISCV/MCTargetDesc/RISCVBaseInfo.h
@@ -300,6 +300,7 @@ enum OperandType : unsigned {
   OPERAND_UIMM6_LSB0,
   OPERAND_UIMM7,
   OPERAND_UIMM7_LSB00,
+  OPERAND_UIMM7_LSB000,
   OPERAND_UIMM8_LSB00,
   OPERAND_UIMM8,
   OPERAND_UIMM8_LSB000,
diff --git a/llvm/lib/Target/RISCV/MCTargetDesc/RISCVMCAsmInfo.cpp b/llvm/lib/Target/RISCV/MCTargetDesc/RISCVMCAsmInfo.cpp
index 7b927522d39549..30ad5c84e996b6 100644
--- a/llvm/lib/Target/RISCV/MCTargetDesc/RISCVMCAsmInfo.cpp
+++ b/llvm/lib/Target/RISCV/MCTargetDesc/RISCVMCAsmInfo.cpp
@@ -45,3 +45,11 @@ const MCExpr *RISCVMCAsmInfo::getExprForFDESymbol(const MCSymbol *Sym,
   assert(Encoding & dwarf::DW_EH_PE_sdata4 && "Unexpected encoding");
   return RISCVMCExpr::create(ME, RISCVMCExpr::VK_RISCV_32_PCREL, Ctx);
 }
+
+void RISCVMCAsmInfo::setUseIntegratedAssembler(bool Value) {
+  UseIntegratedAssembler = V...
[truncated]

@llvmbot
Copy link
Member

llvmbot commented Nov 27, 2024

@llvm/pr-subscribers-mc

Author: Djordje Todorovic (djtodoro)

Changes

The P8700 is a high-performance processor from MIPS designed to meet the demands of modern workloads, offering exceptional scalability and efficiency. It builds on MIPS's established architectural strengths while introducing enhancements that set it apart. For more details, you can check out the official product page here: https://mips.com/products/hardware/p8700/.

RFC: TODO


Patch is 143.83 KiB, truncated to 20.00 KiB below, full version: https://github.com/llvm/llvm-project/pull/117865.diff

48 Files Affected:

  • (modified) clang/include/clang/Driver/Options.td (+5)
  • (modified) clang/lib/Driver/ToolChains/Arch/RISCV.cpp (+8-2)
  • (modified) clang/lib/Driver/ToolChains/Clang.cpp (+19)
  • (modified) clang/lib/Driver/ToolChains/Gnu.cpp (+113-4)
  • (modified) clang/lib/Driver/ToolChains/Linux.cpp (+20-3)
  • (modified) clang/lib/Driver/ToolChains/RISCVToolchain.cpp (+15-1)
  • (modified) clang/lib/Driver/ToolChains/RISCVToolchain.h (+1)
  • (modified) clang/test/Misc/target-invalid-cpu-note/riscv.c (+2)
  • (modified) llvm/docs/RISCVUsage.rst (+6)
  • (modified) llvm/lib/Target/RISCV/AsmParser/RISCVAsmParser.cpp (+10)
  • (modified) llvm/lib/Target/RISCV/CMakeLists.txt (+2)
  • (modified) llvm/lib/Target/RISCV/MCTargetDesc/RISCVBaseInfo.h (+1)
  • (modified) llvm/lib/Target/RISCV/MCTargetDesc/RISCVMCAsmInfo.cpp (+8)
  • (modified) llvm/lib/Target/RISCV/MCTargetDesc/RISCVMCAsmInfo.h (+2)
  • (modified) llvm/lib/Target/RISCV/RISCV.h (+5)
  • (modified) llvm/lib/Target/RISCV/RISCV.td (+1)
  • (modified) llvm/lib/Target/RISCV/RISCVFeatures.td (+17)
  • (modified) llvm/lib/Target/RISCV/RISCVISelLowering.cpp (+3-1)
  • (modified) llvm/lib/Target/RISCV/RISCVInstrFormats.td (+72)
  • (modified) llvm/lib/Target/RISCV/RISCVInstrInfo.cpp (+43)
  • (modified) llvm/lib/Target/RISCV/RISCVInstrInfo.h (+9)
  • (modified) llvm/lib/Target/RISCV/RISCVInstrInfo.td (+220)
  • (modified) llvm/lib/Target/RISCV/RISCVInstrInfoC.td (-125)
  • (modified) llvm/lib/Target/RISCV/RISCVInstrInfoZb.td (+1-1)
  • (added) llvm/lib/Target/RISCV/RISCVLoadStoreOptimizer.cpp (+371)
  • (modified) llvm/lib/Target/RISCV/RISCVProcessors.td (+15-1)
  • (added) llvm/lib/Target/RISCV/RISCVRemoveBackToBackBranches.cpp (+158)
  • (added) llvm/lib/Target/RISCV/RISCVSchedMIPSP8700.td (+279)
  • (modified) llvm/lib/Target/RISCV/RISCVSchedule.td (+1)
  • (modified) llvm/lib/Target/RISCV/RISCVSubtarget.cpp (+38-2)
  • (modified) llvm/lib/Target/RISCV/RISCVSubtarget.h (+4-1)
  • (modified) llvm/lib/Target/RISCV/RISCVTargetMachine.cpp (+36-2)
  • (added) llvm/test/CodeGen/MIR/RISCV/riscv-remove-back-to-back-branches.mir (+108)
  • (modified) llvm/test/CodeGen/RISCV/GlobalISel/rv64zba.ll (+14-14)
  • (modified) llvm/test/CodeGen/RISCV/O0-pipeline.ll (+3-1)
  • (modified) llvm/test/CodeGen/RISCV/O3-pipeline.ll (+4-1)
  • (modified) llvm/test/CodeGen/RISCV/div-by-constant.ll (+1-1)
  • (added) llvm/test/CodeGen/RISCV/load-store-pair.ll (+509)
  • (added) llvm/test/CodeGen/RISCV/riscv-enable-gep-opt.ll (+10)
  • (modified) llvm/test/CodeGen/RISCV/rv64i-exhaustive-w-insts.ll (+50-50)
  • (modified) llvm/test/CodeGen/RISCV/rv64zba.ll (+5-5)
  • (modified) llvm/test/CodeGen/RISCV/select-and.ll (+25)
  • (modified) llvm/test/CodeGen/RISCV/select-bare.ll (+14)
  • (modified) llvm/test/CodeGen/RISCV/select-cc.ll (+86)
  • (modified) llvm/test/CodeGen/RISCV/select-or.ll (+25)
  • (modified) llvm/test/CodeGen/RISCV/xaluo.ll (+11-11)
  • (modified) llvm/test/CodeGen/RISCV/zcb-regalloc-hints.ll (+1-1)
  • (modified) llvm/test/MC/RISCV/rv64zba-aliases-valid.s (+2-2)
diff --git a/clang/include/clang/Driver/Options.td b/clang/include/clang/Driver/Options.td
index e5f2fec88706d8..822ead08392734 100644
--- a/clang/include/clang/Driver/Options.td
+++ b/clang/include/clang/Driver/Options.td
@@ -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.">;
diff --git a/clang/lib/Driver/ToolChains/Arch/RISCV.cpp b/clang/lib/Driver/ToolChains/Arch/RISCV.cpp
index 6935904a24edbf..7a2408477e2d7b 100644
--- a/clang/lib/Driver/ToolChains/Arch/RISCV.cpp
+++ b/clang/lib/Driver/ToolChains/Arch/RISCV.cpp
@@ -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";
@@ -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";
 }
diff --git a/clang/lib/Driver/ToolChains/Clang.cpp b/clang/lib/Driver/ToolChains/Clang.cpp
index d3eec9fea0d498..a2887fe49d940d 100644
--- a/clang/lib/Driver/ToolChains/Clang.cpp
+++ b/clang/lib/Driver/ToolChains/Clang.cpp
@@ -2164,6 +2164,25 @@ 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();
diff --git a/clang/lib/Driver/ToolChains/Gnu.cpp b/clang/lib/Driver/ToolChains/Gnu.cpp
index 8397f1121ec2ce..b404b7ab07894b 100644
--- a/clang/lib/Driver/ToolChains/Gnu.cpp
+++ b/clang/lib/Driver/ToolChains/Gnu.cpp
@@ -252,9 +252,18 @@ 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";
+  {
+    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";
+  }
   case llvm::Triple::sparc:
   case llvm::Triple::sparcel:
     return "elf32_sparc";
@@ -402,6 +411,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)) {
@@ -765,7 +782,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 =
@@ -774,6 +792,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:
@@ -1873,9 +1899,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) {
@@ -1899,6 +1934,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;
@@ -1923,8 +1971,18 @@ 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);
@@ -1932,6 +1990,15 @@ static void findRISCVMultilibs(const Driver &D,
   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);
@@ -1941,6 +2008,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;
@@ -2566,7 +2635,8 @@ void Generic_GCC::GCCInstallationDetector::AddDefaultGCCPrefixes(
                                                "riscv32-unknown-elf"};
   static const char *const RISCV64LibDirs[] = {"/lib64", "/lib"};
   static const char *const RISCV64Triples[] = {"riscv64-unknown-linux-gnu",
-                                               "riscv64-unknown-elf"};
+                                               "riscv64-unknown-elf",
+                                               "riscv64-mti-elf"};
 
   static const char *const SPARCv8LibDirs[] = {"/lib32", "/lib"};
   static const char *const SPARCv8Triples[] = {"sparc-linux-gnu",
@@ -3137,6 +3207,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:
+  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;
   }
diff --git a/clang/lib/Driver/ToolChains/Linux.cpp b/clang/lib/Driver/ToolChains/Linux.cpp
index d1cb625613415b..3759b01b436e5c 100644
--- a/clang/lib/Driver/ToolChains/Linux.cpp
+++ b/clang/lib/Driver/ToolChains/Linux.cpp
@@ -274,11 +274,13 @@ 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
@@ -412,7 +414,11 @@ 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
@@ -422,8 +428,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();
 
diff --git a/clang/lib/Driver/ToolChains/RISCVToolchain.cpp b/clang/lib/Driver/ToolChains/RISCVToolchain.cpp
index 624099d21ae124..6d0e0935135dd9 100644
--- a/clang/lib/Driver/ToolChains/RISCVToolchain.cpp
+++ b/clang/lib/Driver/ToolChains/RISCVToolchain.cpp
@@ -77,7 +77,7 @@ Tool *RISCVToolChain::buildLinker() const {
 }
 
 ToolChain::RuntimeLibType RISCVToolChain::GetDefaultRuntimeLibType() const {
-  return GCCInstallation.isValid() ?
+    return GCCInstallation.isValid() ?
     ToolChain::RLT_Libgcc : ToolChain::RLT_CompilerRT;
 }
 
@@ -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 =
@@ -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.
diff --git a/clang/lib/Driver/ToolChains/RISCVToolchain.h b/clang/lib/Driver/ToolChains/RISCVToolchain.h
index fa0aa265d842bb..c189772cc0d0ca 100644
--- a/clang/lib/Driver/ToolChains/RISCVToolchain.h
+++ b/clang/lib/Driver/ToolChains/RISCVToolchain.h
@@ -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;
diff --git a/clang/test/Misc/target-invalid-cpu-note/riscv.c b/clang/test/Misc/target-invalid-cpu-note/riscv.c
index 8c5df5884cd791..fc8536d99cb804 100644
--- a/clang/test/Misc/target-invalid-cpu-note/riscv.c
+++ b/clang/test/Misc/target-invalid-cpu-note/riscv.c
@@ -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
@@ -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
diff --git a/llvm/docs/RISCVUsage.rst b/llvm/docs/RISCVUsage.rst
index 1317221448ea5b..7fc1f1d49faf4e 100644
--- a/llvm/docs/RISCVUsage.rst
+++ b/llvm/docs/RISCVUsage.rst
@@ -423,6 +423,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
 =========================
 
diff --git a/llvm/lib/Target/RISCV/AsmParser/RISCVAsmParser.cpp b/llvm/lib/Target/RISCV/AsmParser/RISCVAsmParser.cpp
index b843bb5ae43100..4edeb07a0fc980 100644
--- a/llvm/lib/Target/RISCV/AsmParser/RISCVAsmParser.cpp
+++ b/llvm/lib/Target/RISCV/AsmParser/RISCVAsmParser.cpp
@@ -855,6 +855,16 @@ struct RISCVOperand final : public MCParsedAsmOperand {
            VK == RISCVMCExpr::VK_RISCV_None;
   }
 
+  bool isUImm7Lsb000() const {
+    if (!isImm())
+      return false;
+    int64_t Imm;
+    RISCVMCExpr::VariantKind VK = RISCVMCExpr::VK_RISCV_None;
+    bool IsConstantImm = evaluateConstantImm(getImm(), Imm, VK);
+    return IsConstantImm && isShiftedUInt<4, 3>(Imm) &&
+           VK == RISCVMCExpr::VK_RISCV_None;
+  }
+
   bool isUImm8Lsb00() const {
     if (!isImm())
       return false;
diff --git a/llvm/lib/Target/RISCV/CMakeLists.txt b/llvm/lib/Target/RISCV/CMakeLists.txt
index fd049d1a57860e..2f63d7f1e4c39f 100644
--- a/llvm/lib/Target/RISCV/CMakeLists.txt
+++ b/llvm/lib/Target/RISCV/CMakeLists.txt
@@ -47,6 +47,7 @@ add_llvm_target(RISCVCodeGen
   RISCVISelLowering.cpp
   RISCVLandingPadSetup.cpp
   RISCVMachineFunctionInfo.cpp
+  RISCVLoadStoreOptimizer.cpp
   RISCVMergeBaseOffset.cpp
   RISCVOptWInstrs.cpp
   RISCVPostRAExpandPseudoInsts.cpp
@@ -54,6 +55,7 @@ add_llvm_target(RISCVCodeGen
   RISCVMoveMerger.cpp
   RISCVPushPopOptimizer.cpp
   RISCVRegisterInfo.cpp
+  RISCVRemoveBackToBackBranches.cpp
   RISCVSubtarget.cpp
   RISCVTargetMachine.cpp
   RISCVTargetObjectFile.cpp
diff --git a/llvm/lib/Target/RISCV/MCTargetDesc/RISCVBaseInfo.h b/llvm/lib/Target/RISCV/MCTargetDesc/RISCVBaseInfo.h
index 19103e219cb800..746a73b1936810 100644
--- a/llvm/lib/Target/RISCV/MCTargetDesc/RISCVBaseInfo.h
+++ b/llvm/lib/Target/RISCV/MCTargetDesc/RISCVBaseInfo.h
@@ -300,6 +300,7 @@ enum OperandType : unsigned {
   OPERAND_UIMM6_LSB0,
   OPERAND_UIMM7,
   OPERAND_UIMM7_LSB00,
+  OPERAND_UIMM7_LSB000,
   OPERAND_UIMM8_LSB00,
   OPERAND_UIMM8,
   OPERAND_UIMM8_LSB000,
diff --git a/llvm/lib/Target/RISCV/MCTargetDesc/RISCVMCAsmInfo.cpp b/llvm/lib/Target/RISCV/MCTargetDesc/RISCVMCAsmInfo.cpp
index 7b927522d39549..30ad5c84e996b6 100644
--- a/llvm/lib/Target/RISCV/MCTargetDesc/RISCVMCAsmInfo.cpp
+++ b/llvm/lib/Target/RISCV/MCTargetDesc/RISCVMCAsmInfo.cpp
@@ -45,3 +45,11 @@ const MCExpr *RISCVMCAsmInfo::getExprForFDESymbol(const MCSymbol *Sym,
   assert(Encoding & dwarf::DW_EH_PE_sdata4 && "Unexpected encoding");
   return RISCVMCExpr::create(ME, RISCVMCExpr::VK_RISCV_32_PCREL, Ctx);
 }
+
+void RISCVMCAsmInfo::setUseIntegratedAssembler(bool Value) {
+  UseIntegratedAssembler = V...
[truncated]

Copy link

github-actions bot commented Nov 27, 2024

✅ With the latest revision this PR passed the C/C++ code formatter.

@jrtc27
Copy link
Collaborator

jrtc27 commented Nov 27, 2024

Extensions belong in their own PRs, ditto CPU/scheduler, driver and any additional passes. Each PR is one commit and this is not one commit's worth of changes.

@djtodoro
Copy link
Collaborator Author

Extensions belong in their own PRs, ditto CPU/scheduler, driver and any additional passes. Each PR is one commit and this is not one commit's worth of changes.

@jrtc27 Yes! I agree. That is why I marked it as Draft. The next step is to divide it into multiple commits. Thanks.

Add support for MIPS's p8700 CPU.

co-authored by Nemanja Rakovic <[email protected]>
Introduce MIPS extensions by adding:
  1) ccmov (+xmipscmov)
  2) load/store pairs (+xmipslsp)

The -mload-store-pairs imply l[w|d]p and s[w|d]p usage.
The `ccmov` feature is ON by default, so we introduce
an option for disabling the feature - `-mno-ccmov`.

co-authored by Dragan Mladjenovic <[email protected]>
co-authored by Jovan Dmitrović <[email protected]>
MipsTechnologies vendor is set up to use the p8700 processor by
default.

co-authored by Jovan Dmitrović <[email protected]>
Default to not using integrated as and adjust assembler output
to be compatible with v0.97 gas. Rudimentary big-endian support.

co-authored by Dragan Mladjenovic <[email protected]>
We see benefits in terms of performance.
CoreMark benchmarking demonstrates a 2.5% performance improvement.
According to the MIPS specification, there shouldn't be
two conditional branches in the same 8-byte aligned
region of code.
Comment on lines +29 to +30
// According to the MIPS specification, there shouldn't be two conditional
// branches in the same 8-byte aligned region of code.
Copy link
Member

Choose a reason for hiding this comment

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

Can you describe this Pass in a bit more depth? The RISC-V specification doesn't have this restriction as far as I understand - is this a performance optimisation for your core, or is it required for your core to work correctly?

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Sure, I’ll describe it in more detail. To clarify, this is not a general RISC-V specification but rather a MIPS-specific requirement necessary for our core to function correctly.

Copy link
Collaborator

Choose a reason for hiding this comment

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

If it's a requirement to function correctly then your core is not a RISC-V core...

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 try to explain in detail why it was needed :)

@michaelmaitland
Copy link
Contributor

Please split a3ed355 into multiple commits (and eventually PRs). One for CPU definition and one for scheduler model.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
backend:RISC-V clang:driver 'clang' and 'clang++' user-facing binaries. Not 'clang-cl' clang Clang issues not falling into any other category llvm:globalisel mc Machine (object) code
Projects
None yet
Development

Successfully merging this pull request may close these issues.

5 participants