Skip to content

Commit

Permalink
[RISCV][LTO] Enable LTO (#18)
Browse files Browse the repository at this point in the history
* [LLVM] D72624 TargetMachine Hook for Module Metadata

* [RISCV][LTO] enable LTO/ThinLTO on RISCV (D78035)

* [LTO] Pass Module to TMFactory to correctly set-up ABI

* [LLVM] disable assertion for in set options

* [RISCV] LTO tests

* [RISCV] gold/LTO mixed thin/regular test
  • Loading branch information
huettern committed Sep 3, 2021
1 parent 6836559 commit 08abb15
Show file tree
Hide file tree
Showing 35 changed files with 287 additions and 22 deletions.
4 changes: 3 additions & 1 deletion clang/lib/CodeGen/BackendUtil.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -922,8 +922,10 @@ void EmitAssemblyHelper::EmitAssembly(BackendAction Action,

if (UsesCodeGen && !TM)
return;
if (TM)
if (TM) {
TM->initializeOptionsWithModuleMetadata(*TheModule);
TheModule->setDataLayout(TM->createDataLayout());
}

legacy::PassManager PerModulePasses;
PerModulePasses.add(
Expand Down
6 changes: 6 additions & 0 deletions clang/lib/Driver/ToolChains/RISCVToolchain.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -159,6 +159,12 @@ void RISCV::Linker::ConstructJob(Compilation &C, const JobAction &JA,

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

if (D.isUsingLTO()) {
assert(!Inputs.empty() && "Must have at least one input.");
addLTOOptions(ToolChain, Args, CmdArgs, Output, Inputs[0],
D.getLTOMode() == LTOK_Thin);
}

bool WantCRTs =
!Args.hasArg(options::OPT_nostdlib, options::OPT_nostartfiles);

Expand Down
1 change: 1 addition & 0 deletions clang/lib/Driver/ToolChains/RISCVToolchain.h
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ class LLVM_LIBRARY_VISIBILITY RISCVToolChain : public Generic_ELF {
void addClangTargetOptions(const llvm::opt::ArgList &DriverArgs,
llvm::opt::ArgStringList &CC1Args,
Action::OffloadKind) const override;
bool HasNativeLLVMSupport() const override { return true; }
RuntimeLibType GetDefaultRuntimeLibType() const override;
UnwindLibType
GetUnwindLibType(const llvm::opt::ArgList &Args) const override;
Expand Down
2 changes: 2 additions & 0 deletions clang/tools/clang-fuzzer/handle-llvm/handle_llvm.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -117,6 +117,8 @@ static std::string OptLLVM(const std::string &IR, CodeGenOpt::Level OLvl) {
if (!TM)
ErrorAndExit("Could not create target machine");

TM->initializeOptionsWithModuleMetadata(*M);

codegen::setFunctionAttributes(codegen::getCPUStr(),
codegen::getFeaturesStr(), *M);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -147,6 +147,7 @@ bool RenderScriptRuntimeModulePass::runOnModule(llvm::Module &module) {
target_machine->createDataLayout().getStringRepresentation().c_str());
}
module.setTargetTriple(real_triple);
target_machine->initializeOptionsWithModuleMetadata(module);
module.setDataLayout(target_machine->createDataLayout());
}
return changed_module;
Expand Down
3 changes: 2 additions & 1 deletion llvm/docs/tutorial/MyFirstLanguageFrontend/LangImpl08.rst
Original file line number Diff line number Diff line change
Expand Up @@ -129,8 +129,9 @@ layout.

.. code-block:: c++

TheModule->setDataLayout(TargetMachine->createDataLayout());
TheModule->setTargetTriple(TargetTriple);
TargetMachine->initializeOptionsWithModuleMetadata(*TheModule);
TheModule->setDataLayout(TargetMachine->createDataLayout());
Emit Object Code
================
Expand Down
1 change: 1 addition & 0 deletions llvm/examples/Kaleidoscope/Chapter8/toy.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1246,6 +1246,7 @@ int main() {
auto TheTargetMachine =
Target->createTargetMachine(TargetTriple, CPU, Features, opt, RM);

TheTargetMachine->initializeOptionsWithModuleMetadata(*TheModule);
TheModule->setDataLayout(TheTargetMachine->createDataLayout());

auto Filename = "output.o";
Expand Down
2 changes: 1 addition & 1 deletion llvm/include/llvm/CodeGen/ParallelCG.h
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ class raw_pwrite_stream;
std::unique_ptr<Module>
splitCodeGen(std::unique_ptr<Module> M, ArrayRef<raw_pwrite_stream *> OSs,
ArrayRef<llvm::raw_pwrite_stream *> BCOSs,
const std::function<std::unique_ptr<TargetMachine>()> &TMFactory,
const std::function<std::unique_ptr<TargetMachine>(Module &)> &TMFactory,
CodeGenFileType FileType = CGFT_ObjectFile,
bool PreserveLocals = false);

Expand Down
2 changes: 1 addition & 1 deletion llvm/include/llvm/LTO/legacy/LTOCodeGenerator.h
Original file line number Diff line number Diff line change
Expand Up @@ -204,7 +204,7 @@ struct LTOCodeGenerator {
llvm::function_ref<bool(const GlobalValue &)> mustPreserveGV);

bool determineTarget();
std::unique_ptr<TargetMachine> createTargetMachine();
std::unique_ptr<TargetMachine> createTargetMachine(Module &M);

void emitError(const std::string &ErrMsg);
void emitWarning(const std::string &ErrMsg);
Expand Down
1 change: 1 addition & 0 deletions llvm/include/llvm/LTO/legacy/ThinLTOCodeGenerator.h
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@ struct TargetMachineBuilder {
Optional<Reloc::Model> RelocModel;
CodeGenOpt::Level CGOptLevel = CodeGenOpt::Aggressive;

std::unique_ptr<TargetMachine> create(Module &TheModule) const;
std::unique_ptr<TargetMachine> create() const;
};

Expand Down
19 changes: 18 additions & 1 deletion llvm/include/llvm/Target/TargetMachine.h
Original file line number Diff line number Diff line change
Expand Up @@ -110,6 +110,9 @@ class TargetMachine {
unsigned RequireStructuredCFG : 1;
unsigned O0WantsFastISel : 1;

private:
mutable unsigned OptionsCanBeInitalizedFromModule : 1;

public:
const TargetOptions DefaultOptions;
mutable TargetOptions Options;
Expand Down Expand Up @@ -163,7 +166,10 @@ class TargetMachine {
}

/// Create a DataLayout.
const DataLayout createDataLayout() const { return DL; }
const DataLayout createDataLayout() const {
OptionsCanBeInitalizedFromModule = false;
return DL;
}

/// Test if a DataLayout if compatible with the CodeGen for this target.
///
Expand Down Expand Up @@ -193,6 +199,17 @@ class TargetMachine {
return DL.getPointerSize(DL.getAllocaAddrSpace());
}

/// Target hook for updating this TargetMachine's Options based
// on the provided module metadata.
virtual void
setTargetOptionsWithModuleMetadata(const Module &M LLVM_ATTRIBUTE_UNUSED) {}

/// This method ensures that `setTargetOptionsWithModuleMetadata` is
// called, and ensures that is called before `createDataLayout` so that
// Options set from module metadata are modified as early as possible
// before they are used.
void initializeOptionsWithModuleMetadata(const Module &M);

/// Reset the target options based on the function's attributes.
// FIXME: Remove TargetOptions that affect per-function code generation
// from TargetMachine.
Expand Down
6 changes: 3 additions & 3 deletions llvm/lib/CodeGen/ParallelCG.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -25,9 +25,9 @@
using namespace llvm;

static void codegen(Module *M, llvm::raw_pwrite_stream &OS,
function_ref<std::unique_ptr<TargetMachine>()> TMFactory,
function_ref<std::unique_ptr<TargetMachine>(Module &)> TMFactory,
CodeGenFileType FileType) {
std::unique_ptr<TargetMachine> TM = TMFactory();
std::unique_ptr<TargetMachine> TM = TMFactory(*M);
assert(TM && "Failed to create target machine!");

legacy::PassManager CodeGenPasses;
Expand All @@ -39,7 +39,7 @@ static void codegen(Module *M, llvm::raw_pwrite_stream &OS,
std::unique_ptr<Module> llvm::splitCodeGen(
std::unique_ptr<Module> M, ArrayRef<llvm::raw_pwrite_stream *> OSs,
ArrayRef<llvm::raw_pwrite_stream *> BCOSs,
const std::function<std::unique_ptr<TargetMachine>()> &TMFactory,
const std::function<std::unique_ptr<TargetMachine>(Module &)> &TMFactory,
CodeGenFileType FileType, bool PreserveLocals) {
assert(BCOSs.empty() || BCOSs.size() == OSs.size());

Expand Down
1 change: 1 addition & 0 deletions llvm/lib/LTO/LTOBackend.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -201,6 +201,7 @@ createTargetMachine(const Config &Conf, const Target *TheTarget, Module &M) {
TheTriple, Conf.CPU, Features.getString(), Conf.Options, RelocModel,
CodeModel, Conf.CGOptLevel));
assert(TM && "Failed to create target machine");
TM->initializeOptionsWithModuleMetadata(M);
return TM;
}

Expand Down
10 changes: 6 additions & 4 deletions llvm/lib/LTO/LTOCodeGenerator.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -377,16 +377,18 @@ bool LTOCodeGenerator::determineTarget() {
MCpu = "cyclone";
}

TargetMach = createTargetMachine();
TargetMach = createTargetMachine(*MergedModule);
assert(TargetMach && "Unable to create target machine");

return true;
}

std::unique_ptr<TargetMachine> LTOCodeGenerator::createTargetMachine() {
std::unique_ptr<TargetMachine> LTOCodeGenerator::createTargetMachine(Module &M) {
assert(MArch && "MArch is not set!");
return std::unique_ptr<TargetMachine>(MArch->createTargetMachine(
std::unique_ptr<TargetMachine> TM(MArch->createTargetMachine(
TripleStr, MCpu, FeatureStr, Options, RelocModel, None, CGOptLevel));
TM->initializeOptionsWithModuleMetadata(M);
return TM;
}

// If a linkonce global is present in the MustPreserveSymbols, we need to make
Expand Down Expand Up @@ -619,7 +621,7 @@ bool LTOCodeGenerator::compileOptimized(ArrayRef<raw_pwrite_stream *> Out) {
// original module at parallelism level 1 which we then assign back to
// MergedModule.
MergedModule = splitCodeGen(std::move(MergedModule), Out, {},
[&]() { return createTargetMachine(); }, FileType,
[&](Module &M) { return createTargetMachine(M); }, FileType,
ShouldRestoreGlobalsLinkage);

// If statistics were requested, save them to the specified file or
Expand Down
15 changes: 9 additions & 6 deletions llvm/lib/LTO/ThinLTOCodeGenerator.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -565,7 +565,8 @@ void ThinLTOCodeGenerator::crossReferenceSymbol(StringRef Name) {
}

// TargetMachine factory
std::unique_ptr<TargetMachine> TargetMachineBuilder::create() const {
std::unique_ptr<TargetMachine>
TargetMachineBuilder::create(Module &TheModule) const {
std::string ErrMsg;
const Target *TheTarget =
TargetRegistry::lookupTarget(TheTriple.str(), ErrMsg);
Expand All @@ -582,6 +583,7 @@ std::unique_ptr<TargetMachine> TargetMachineBuilder::create() const {
TheTarget->createTargetMachine(TheTriple.str(), MCpu, FeatureStr, Options,
RelocModel, None, CGOptLevel));
assert(TM && "Cannot create target machine");
TM->initializeOptionsWithModuleMetadata(TheModule);

return TM;
}
Expand Down Expand Up @@ -879,8 +881,8 @@ void ThinLTOCodeGenerator::optimize(Module &TheModule) {
initTMBuilder(TMBuilder, Triple(TheModule.getTargetTriple()));

// Optimize now
optimizeModule(TheModule, *TMBuilder.create(), OptLevel, Freestanding,
nullptr);
optimizeModule(TheModule, *TMBuilder.create(TheModule), OptLevel,
Freestanding, nullptr);
}

/// Write out the generated object file, either from CacheEntryPath or from
Expand Down Expand Up @@ -951,7 +953,8 @@ void ThinLTOCodeGenerator::run() {
/*IsImporting*/ false);

// CodeGen
auto OutputBuffer = codegenModule(*TheModule, *TMBuilder.create());
auto OutputBuffer =
codegenModule(*TheModule, *TMBuilder.create(*TheModule));
if (SavedObjectsDirectoryPath.empty())
ProducedBinaries[count] = std::move(OutputBuffer);
else
Expand Down Expand Up @@ -1124,8 +1127,8 @@ void ThinLTOCodeGenerator::run() {
auto &ImportList = ImportLists[ModuleIdentifier];
// Run the main process now, and generates a binary
auto OutputBuffer = ProcessThinLTOModule(
*TheModule, *Index, ModuleMap, *TMBuilder.create(), ImportList,
ExportList, GUIDPreservedSymbols,
*TheModule, *Index, ModuleMap, *TMBuilder.create(*TheModule),
ImportList, ExportList, GUIDPreservedSymbols,
ModuleToDefinedGVSummaries[ModuleIdentifier], CacheOptions,
DisableCodeGen, SaveTempsDir, Freestanding, OptLevel, count);

Expand Down
1 change: 1 addition & 0 deletions llvm/lib/Target/RISCV/RISCV.td
Original file line number Diff line number Diff line change
Expand Up @@ -313,6 +313,7 @@ def : ProcessorModel<"snitch", SnitchModel, [FeatureStdExtM,
FeatureStdExtA,
FeatureStdExtF,
FeatureStdExtD,
FeatureExtZfh,
FeatureExtXfrep,
FeatureExtXdma,
FeatureExtXssr]>;
Expand Down
13 changes: 13 additions & 0 deletions llvm/lib/Target/RISCV/RISCVTargetMachine.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -109,6 +109,19 @@ RISCVTargetMachine::getSubtargetImpl(const Function &F) const {
return I.get();
}

void RISCVTargetMachine::setTargetOptionsWithModuleMetadata(
const Module &M LLVM_ATTRIBUTE_UNUSED) {
StringRef ABIName = Options.MCOptions.getABIName();
if (const MDString *ModuleTargetABI =
dyn_cast_or_null<MDString>(M.getModuleFlag("target-abi"))) {
StringRef ModuleABIName = ModuleTargetABI->getString();
if (!ABIName.empty() && ModuleABIName != ABIName)
report_fatal_error("-target-abi option != target-abi module flag");
if (ABIName.empty())
Options.MCOptions.ABIName = ModuleABIName.str();
}
}

TargetTransformInfo
RISCVTargetMachine::getTargetTransformInfo(const Function &F) {
return TargetTransformInfo(RISCVTTIImpl(this, F));
Expand Down
3 changes: 3 additions & 0 deletions llvm/lib/Target/RISCV/RISCVTargetMachine.h
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,9 @@ class RISCVTargetMachine : public LLVMTargetMachine {
return TLOF.get();
}

void setTargetOptionsWithModuleMetadata(
const Module &M LLVM_ATTRIBUTE_UNUSED) override;

TargetTransformInfo getTargetTransformInfo(const Function &F) override;

virtual bool isNoopAddrSpaceCast(unsigned SrcAS,
Expand Down
16 changes: 15 additions & 1 deletion llvm/lib/Target/TargetMachine.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -37,14 +37,28 @@ TargetMachine::TargetMachine(const Target &T, StringRef DataLayoutString,
: TheTarget(T), DL(DataLayoutString), TargetTriple(TT),
TargetCPU(std::string(CPU)), TargetFS(std::string(FS)), AsmInfo(nullptr),
MRI(nullptr), MII(nullptr), STI(nullptr), RequireStructuredCFG(false),
O0WantsFastISel(false), DefaultOptions(Options), Options(Options) {}
O0WantsFastISel(false), OptionsCanBeInitalizedFromModule(true),
DefaultOptions(Options), Options(Options) {}

TargetMachine::~TargetMachine() = default;

bool TargetMachine::isPositionIndependent() const {
return getRelocationModel() == Reloc::PIC_;
}

void TargetMachine::initializeOptionsWithModuleMetadata(const Module &M) {
// TODO: This was added in the original patch (D72624) but now fails for llc
// because the lambda function `SetDataLayout` is called during IR parsing (llc.cpp).
// For RISCV the data layout is independent of the module metadata currently parsed
// (target-abi). Other targets don't use this hook

// assert(
// OptionsCanBeInitalizedFromModule &&
// "setOptionsWithModuleMetadata cannot be called after createDataLayout");

setTargetOptionsWithModuleMetadata(M);
}

/// Reset the target options based on the function's attributes.
/// setFunctionAttributes should have made the raw attribute value consistent
/// with the command line flag if used.
Expand Down
1 change: 1 addition & 0 deletions llvm/lib/Target/TargetMachineC.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -193,6 +193,7 @@ static LLVMBool LLVMTargetMachineEmit(LLVMTargetMachineRef T, LLVMModuleRef M,

std::string error;

TM->initializeOptionsWithModuleMetadata(*Mod);
Mod->setDataLayout(TM->createDataLayout());

CodeGenFileType ft;
Expand Down
3 changes: 1 addition & 2 deletions llvm/test/CodeGen/RISCV/module-target-abi2.ll
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,7 @@

; RV32IF-ILP32: -target-abi option != target-abi module flag

; FLAGS: Flags: 0x0
; // this should be "Flags :0x2, single-float ABI", it will be fixed later.
; FLAGS: Flags: 0x2, single-float ABI

define float @foo(i32 %a) nounwind #0 {
; DEFAULT: # %bb.0:
Expand Down
14 changes: 14 additions & 0 deletions llvm/test/LTO/RISCV/Inputs/mabi-invalid.ll
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
target datalayout = "e-m:e-p:32:32-i64:64-n32-S128"
target triple = "riscv32-unknown-linux-gnu"

define float @foo(float %x) #0 {
%conv = fpext float %x to double
%add = fadd double %conv, 0x400921FD80C9BEFB
%conv1 = fptrunc double %add to float
ret float %conv1
}

attributes #0 = { nounwind "target-features"="+a,+c,+f,+m,+relax" }

!llvm.module.flags = !{!0}
!0 = !{i32 1, !"target-abi", !"ilp32"}
14 changes: 14 additions & 0 deletions llvm/test/LTO/RISCV/Inputs/mabi.ll
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
target datalayout = "e-m:e-p:32:32-i64:64-n32-S128"
target triple = "riscv32-unknown-linux-gnu"

define float @foo(float %x) #0 {
%conv = fpext float %x to double
%add = fadd double %conv, 0x400921FD80C9BEFB
%conv1 = fptrunc double %add to float
ret float %conv1
}

attributes #0 = { nounwind "target-features"="+a,+c,+f,+m,+relax" }

!llvm.module.flags = !{!0}
!0 = !{i32 1, !"target-abi", !"ilp32f"}
2 changes: 2 additions & 0 deletions llvm/test/LTO/RISCV/lit.local.cfg
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
if not 'RISCV' in config.root.targets:
config.unsupported = True
Loading

0 comments on commit 08abb15

Please sign in to comment.