From cdcf58e5af025989a8dd52bc0d9c032712a160c8 Mon Sep 17 00:00:00 2001 From: Sam Elliott Date: Mon, 14 Oct 2019 14:00:13 +0000 Subject: [PATCH] [RISCV] enable LTO support, pass some options to linker. Summary: 1. enable LTO need to pass target feature and abi to LTO code generation RISCV backend need the target feature to decide which extension used in code generation. 2. move getTargetFeatures to CommonArgs.h and add ForLTOPlugin flag 3. add general tools::getTargetABI in CommonArgs.h because different target uses different way to get the target ABI. Patch by Kuan Hsu Chen (khchen) Reviewers: lenary, lewis-revill, asb, MaskRay Reviewed By: lenary Subscribers: hiraditya, dschuff, aheejin, fedor.sergeev, mehdi_amini, inglorion, asb, rbar, johnrusso, simoncook, apazos, sabuasal, niosHD, kito-cheng, shiva0217, jrtc27, MaskRay, zzheng, edward-jones, steven_wu, rogfer01, MartinMosbeck, brucehoult, the_o, dexonsmith, rkruppe, PkmX, jocewei, psnobl, benna, Jim, lenary, s.egerton, pzheng, cfe-commits Tags: #clang Differential Revision: https://reviews.llvm.org/D67409 llvm-svn: 374774 --- clang/lib/Driver/ToolChains/Clang.cpp | 89 ------------------ clang/lib/Driver/ToolChains/CommonArgs.cpp | 120 +++++++++++++++++++++++++ clang/lib/Driver/ToolChains/CommonArgs.h | 8 ++ clang/lib/Driver/ToolChains/RISCVToolchain.cpp | 7 ++ clang/lib/Driver/ToolChains/RISCVToolchain.h | 1 + clang/test/Driver/gold-lto.c | 18 ++++ 6 files changed, 154 insertions(+), 89 deletions(-) diff --git a/clang/lib/Driver/ToolChains/Clang.cpp b/clang/lib/Driver/ToolChains/Clang.cpp index 74c698f..e354088 100644 --- a/clang/lib/Driver/ToolChains/Clang.cpp +++ b/clang/lib/Driver/ToolChains/Clang.cpp @@ -302,95 +302,6 @@ static void ParseMPreferVectorWidth(const Driver &D, const ArgList &Args, } } -static void getWebAssemblyTargetFeatures(const ArgList &Args, - std::vector &Features) { - handleTargetFeaturesGroup(Args, Features, options::OPT_m_wasm_Features_Group); -} - -static void getTargetFeatures(const ToolChain &TC, const llvm::Triple &Triple, - const ArgList &Args, ArgStringList &CmdArgs, - bool ForAS) { - const Driver &D = TC.getDriver(); - std::vector Features; - switch (Triple.getArch()) { - default: - break; - case llvm::Triple::mips: - case llvm::Triple::mipsel: - case llvm::Triple::mips64: - case llvm::Triple::mips64el: - mips::getMIPSTargetFeatures(D, Triple, Args, Features); - break; - - case llvm::Triple::arm: - case llvm::Triple::armeb: - case llvm::Triple::thumb: - case llvm::Triple::thumbeb: - arm::getARMTargetFeatures(TC, Triple, Args, CmdArgs, Features, ForAS); - break; - - case llvm::Triple::ppc: - case llvm::Triple::ppc64: - case llvm::Triple::ppc64le: - ppc::getPPCTargetFeatures(D, Triple, Args, Features); - break; - case llvm::Triple::riscv32: - case llvm::Triple::riscv64: - riscv::getRISCVTargetFeatures(D, Triple, Args, Features); - break; - case llvm::Triple::systemz: - systemz::getSystemZTargetFeatures(Args, Features); - break; - case llvm::Triple::aarch64: - case llvm::Triple::aarch64_be: - aarch64::getAArch64TargetFeatures(D, Triple, Args, Features); - break; - case llvm::Triple::x86: - case llvm::Triple::x86_64: - x86::getX86TargetFeatures(D, Triple, Args, Features); - break; - case llvm::Triple::hexagon: - hexagon::getHexagonTargetFeatures(D, Args, Features); - break; - case llvm::Triple::wasm32: - case llvm::Triple::wasm64: - getWebAssemblyTargetFeatures(Args, Features); - break; - case llvm::Triple::sparc: - case llvm::Triple::sparcel: - case llvm::Triple::sparcv9: - sparc::getSparcTargetFeatures(D, Args, Features); - break; - case llvm::Triple::r600: - case llvm::Triple::amdgcn: - amdgpu::getAMDGPUTargetFeatures(D, Args, Features); - break; - case llvm::Triple::msp430: - msp430::getMSP430TargetFeatures(D, Args, Features); - } - - // Find the last of each feature. - llvm::StringMap LastOpt; - for (unsigned I = 0, N = Features.size(); I < N; ++I) { - StringRef Name = Features[I]; - assert(Name[0] == '-' || Name[0] == '+'); - LastOpt[Name.drop_front(1)] = I; - } - - for (unsigned I = 0, N = Features.size(); I < N; ++I) { - // If this feature was overridden, ignore it. - StringRef Name = Features[I]; - llvm::StringMap::iterator LastI = LastOpt.find(Name.drop_front(1)); - assert(LastI != LastOpt.end()); - unsigned Last = LastI->second; - if (Last != I) - continue; - - CmdArgs.push_back("-target-feature"); - CmdArgs.push_back(Name.data()); - } -} - static bool shouldUseExceptionTablesForObjCExceptions(const ObjCRuntime &runtime, const llvm::Triple &Triple) { diff --git a/clang/lib/Driver/ToolChains/CommonArgs.cpp b/clang/lib/Driver/ToolChains/CommonArgs.cpp index 159b42a..1074355 100644 --- a/clang/lib/Driver/ToolChains/CommonArgs.cpp +++ b/clang/lib/Driver/ToolChains/CommonArgs.cpp @@ -11,8 +11,12 @@ #include "Arch/ARM.h" #include "Arch/Mips.h" #include "Arch/PPC.h" +#include "Arch/RISCV.h" +#include "Arch/Sparc.h" #include "Arch/SystemZ.h" #include "Arch/X86.h" +#include "AMDGPU.h" +#include "MSP430.h" #include "HIP.h" #include "Hexagon.h" #include "InputInfo.h" @@ -484,6 +488,14 @@ void tools::AddGoldPlugin(const ToolChain &ToolChain, const ArgList &Args, if (!StatsFile.empty()) CmdArgs.push_back( Args.MakeArgString(Twine("-plugin-opt=stats-file=") + StatsFile)); + + getTargetFeatures(ToolChain, ToolChain.getTriple(), Args, CmdArgs, + /* ForAS= */ false, /* ForLTOPlugin= */ true); + + StringRef ABIName = tools::getTargetABI(Args, ToolChain.getTriple()); + if (!ABIName.empty()) + CmdArgs.push_back( + Args.MakeArgString(Twine("-plugin-opt=-target-abi=") + ABIName)); } void tools::addArchSpecificRPath(const ToolChain &TC, const ArgList &Args, @@ -1380,3 +1392,111 @@ void tools::addMultilibFlag(bool Enabled, const char *const Flag, Multilib::flags_list &Flags) { Flags.push_back(std::string(Enabled ? "+" : "-") + Flag); } + +static void getWebAssemblyTargetFeatures(const ArgList &Args, + std::vector &Features) { + handleTargetFeaturesGroup(Args, Features, options::OPT_m_wasm_Features_Group); +} + +void tools::getTargetFeatures(const ToolChain &TC, const llvm::Triple &Triple, + const ArgList &Args, ArgStringList &CmdArgs, bool ForAS, + bool ForLTOPlugin) { + + const Driver &D = TC.getDriver(); + std::vector Features; + switch (Triple.getArch()) { + default: + break; + case llvm::Triple::mips: + case llvm::Triple::mipsel: + case llvm::Triple::mips64: + case llvm::Triple::mips64el: + mips::getMIPSTargetFeatures(D, Triple, Args, Features); + break; + + case llvm::Triple::arm: + case llvm::Triple::armeb: + case llvm::Triple::thumb: + case llvm::Triple::thumbeb: + arm::getARMTargetFeatures(TC, Triple, Args, CmdArgs, Features, ForAS); + break; + + case llvm::Triple::ppc: + case llvm::Triple::ppc64: + case llvm::Triple::ppc64le: + ppc::getPPCTargetFeatures(D, Triple, Args, Features); + break; + case llvm::Triple::riscv32: + case llvm::Triple::riscv64: + riscv::getRISCVTargetFeatures(D, Triple, Args, Features); + break; + case llvm::Triple::systemz: + systemz::getSystemZTargetFeatures(Args, Features); + break; + case llvm::Triple::aarch64: + case llvm::Triple::aarch64_be: + aarch64::getAArch64TargetFeatures(D, Triple, Args, Features); + break; + case llvm::Triple::x86: + case llvm::Triple::x86_64: + x86::getX86TargetFeatures(D, Triple, Args, Features); + break; + case llvm::Triple::hexagon: + hexagon::getHexagonTargetFeatures(D, Args, Features); + break; + case llvm::Triple::wasm32: + case llvm::Triple::wasm64: + getWebAssemblyTargetFeatures(Args, Features); + break; + case llvm::Triple::sparc: + case llvm::Triple::sparcel: + case llvm::Triple::sparcv9: + sparc::getSparcTargetFeatures(D, Args, Features); + break; + case llvm::Triple::r600: + case llvm::Triple::amdgcn: + amdgpu::getAMDGPUTargetFeatures(D, Args, Features); + break; + case llvm::Triple::msp430: + msp430::getMSP430TargetFeatures(D, Args, Features); + } + + // Find the last of each feature. + llvm::StringMap LastOpt; + for (unsigned I = 0, N = Features.size(); I < N; ++I) { + StringRef Name = Features[I]; + assert(Name[0] == '-' || Name[0] == '+'); + LastOpt[Name.drop_front(1)] = I; + } + + for (unsigned I = 0, N = Features.size(); I < N; ++I) { + // If this feature was overridden, ignore it. + StringRef Name = Features[I]; + llvm::StringMap::iterator LastI = + LastOpt.find(Name.drop_front(1)); + assert(LastI != LastOpt.end()); + unsigned Last = LastI->second; + if (Last != I) + continue; + if (!ForLTOPlugin) { + CmdArgs.push_back("-target-feature"); + CmdArgs.push_back(Name.data()); + } else { + CmdArgs.push_back( + Args.MakeArgString(Twine("-plugin-opt=-mattr=") + Name)); + } + } +} + +StringRef tools::getTargetABI(const ArgList &Args, const llvm::Triple &Triple) { + // TODO: Support the other target ABI + switch (Triple.getArch()) { + default: + break; + case llvm::Triple::riscv32: + case llvm::Triple::riscv64: + return tools::riscv::getRISCVABI(Args, Triple); + break; + } + return StringRef(); +} diff --git a/clang/lib/Driver/ToolChains/CommonArgs.h b/clang/lib/Driver/ToolChains/CommonArgs.h index 63359d7..79468e6 100644 --- a/clang/lib/Driver/ToolChains/CommonArgs.h +++ b/clang/lib/Driver/ToolChains/CommonArgs.h @@ -118,6 +118,14 @@ SmallString<128> getStatsFileName(const llvm::opt::ArgList &Args, void addMultilibFlag(bool Enabled, const char *const Flag, Multilib::flags_list &Flags); +StringRef getTargetABI(const llvm::opt::ArgList &Args, + const llvm::Triple &Triple); + +void getTargetFeatures(const ToolChain &TC, const llvm::Triple &Triple, + const llvm::opt::ArgList &Args, + llvm::opt::ArgStringList &CmdArgs, bool ForAS, + bool ForLTOPlugin = false); + } // end namespace tools } // end namespace driver } // end namespace clang diff --git a/clang/lib/Driver/ToolChains/RISCVToolchain.cpp b/clang/lib/Driver/ToolChains/RISCVToolchain.cpp index 8d96f605..22dc511 100644 --- a/clang/lib/Driver/ToolChains/RISCVToolchain.cpp +++ b/clang/lib/Driver/ToolChains/RISCVToolchain.cpp @@ -7,6 +7,7 @@ //===----------------------------------------------------------------------===// #include "RISCVToolchain.h" +#include "Arch/RISCV.h" #include "CommonArgs.h" #include "InputInfo.h" #include "clang/Driver/Compilation.h" @@ -100,6 +101,12 @@ void RISCV::Linker::ConstructJob(Compilation &C, const JobAction &JA, std::string Linker = getToolChain().GetProgramPath(getShortName()); + if (D.isUsingLTO()) { + assert(!Inputs.empty() && "Must have at least one input."); + AddGoldPlugin(ToolChain, Args, CmdArgs, Output, Inputs[0], + D.getLTOMode() == LTOK_Thin); + } + bool WantCRTs = !Args.hasArg(options::OPT_nostdlib, options::OPT_nostartfiles); diff --git a/clang/lib/Driver/ToolChains/RISCVToolchain.h b/clang/lib/Driver/ToolChains/RISCVToolchain.h index b2b56b0..673d749 100644 --- a/clang/lib/Driver/ToolChains/RISCVToolchain.h +++ b/clang/lib/Driver/ToolChains/RISCVToolchain.h @@ -25,6 +25,7 @@ public: void addClangTargetOptions(const llvm::opt::ArgList &DriverArgs, llvm::opt::ArgStringList &CC1Args, Action::OffloadKind) const override; + bool HasNativeLLVMSupport() const override { return true; } void AddClangSystemIncludeArgs(const llvm::opt::ArgList &DriverArgs, llvm::opt::ArgStringList &CC1Args) const override; diff --git a/clang/test/Driver/gold-lto.c b/clang/test/Driver/gold-lto.c index d16961e..c761461 100644 --- a/clang/test/Driver/gold-lto.c +++ b/clang/test/Driver/gold-lto.c @@ -26,3 +26,21 @@ // RUN: %clang -target i686-linux-android -### %t.o -flto 2>&1 \ // RUN: | FileCheck %s --check-prefix=CHECK-X86-ANDROID // CHECK-X86-ANDROID: "-plugin" "{{.*}}{{[/\\]}}LLVMgold.{{dll|dylib|so}}" +// +// RUN: %clang -target riscv64-unknown-elf -### %t.o -flto 2>&1 \ +// RUN: -march=rv64imf -mabi=lp64f \ +// RUN: | FileCheck %s --check-prefix=CHECK-RISCV-BAREMETAL +// CHECK-RISCV-BAREMETAL: "-plugin" "{{.*}}{{[/\\]}}LLVMgold.{{dll|dylib|so}}" +// CHECK-RISCV-BAREMETAL: "-plugin-opt=-mattr=+m" +// CHECK-RISCV-BAREMETAL: "-plugin-opt=-mattr=+f" +// CHECK-RISCV-BAREMETAL: "-plugin-opt=-mattr=+relax" +// CHECK-RISCV-BAREMETAL: "-plugin-opt=-target-abi=lp64f" +// +// RUN: %clang -target riscv64-unknown-linux-gnu -### %t.o -flto 2>&1 \ +// RUN: -march=rv64imf -mabi=lp64f \ +// RUN: | FileCheck %s --check-prefix=CHECK-RISCV-LINUX +// CHECK-RISCV-LINUX: "-plugin" "{{.*}}{{[/\\]}}LLVMgold.{{dll|dylib|so}}" +// CHECK-RISCV-LINUX: "-plugin-opt=-mattr=+m" +// CHECK-RISCV-LINUX: "-plugin-opt=-mattr=+f" +// CHECK-RISCV-LINUX: "-plugin-opt=-mattr=+relax" +// CHECK-RISCV-LINUX: "-plugin-opt=-target-abi=lp64f" -- 2.7.4