From e4c5b69aa39406c7559ad28ece3a48e86d9508d8 Mon Sep 17 00:00:00 2001 From: Mehdi Amini Date: Tue, 28 Mar 2017 18:55:44 +0000 Subject: [PATCH] Add support for -fno-builtin to LTO and ThinLTO to libLTO Reviewers: tejohnson, pcc Subscribers: Prazek, dexonsmith, llvm-commits Differential Revision: https://reviews.llvm.org/D30791 git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@298936 91177308-0d34-0410-b5e6-96231b3b80d8 --- include/llvm/LTO/legacy/LTOCodeGenerator.h | 5 ++ .../llvm/LTO/legacy/ThinLTOCodeGenerator.h | 8 ++++ lib/LTO/LTOCodeGenerator.cpp | 2 + lib/LTO/ThinLTOCodeGenerator.cpp | 17 ++++--- test/ThinLTO/X86/tli-nobuiltin.ll | 46 +++++++++++++++++++ tools/llvm-lto/llvm-lto.cpp | 6 +++ tools/lto/lto.cpp | 12 +++-- 7 files changed, 86 insertions(+), 10 deletions(-) create mode 100644 test/ThinLTO/X86/tli-nobuiltin.ll diff --git a/include/llvm/LTO/legacy/LTOCodeGenerator.h b/include/llvm/LTO/legacy/LTOCodeGenerator.h index ef62a840cbd..952875fc854 100644 --- a/include/llvm/LTO/legacy/LTOCodeGenerator.h +++ b/include/llvm/LTO/legacy/LTOCodeGenerator.h @@ -175,6 +175,10 @@ struct LTOCodeGenerator { /// Calls \a verifyMergedModuleOnce(). bool compileOptimized(ArrayRef Out); + /// Enable the Freestanding mode: indicate that the optimizer should not + /// assume builtins are present on the target. + void setFreestanding(bool Enabled) { Freestanding = Enabled; } + void setDiagnosticHandler(lto_diagnostic_handler_t, void *); LLVMContext &getContext() { return Context; } @@ -237,6 +241,7 @@ private: bool ShouldRestoreGlobalsLinkage = false; TargetMachine::CodeGenFileType FileType = TargetMachine::CGFT_ObjectFile; std::unique_ptr DiagnosticOutputFile; + bool Freestanding = false; }; } #endif diff --git a/include/llvm/LTO/legacy/ThinLTOCodeGenerator.h b/include/llvm/LTO/legacy/ThinLTOCodeGenerator.h index 28e61cb382b..f9545333aab 100644 --- a/include/llvm/LTO/legacy/ThinLTOCodeGenerator.h +++ b/include/llvm/LTO/legacy/ThinLTOCodeGenerator.h @@ -205,6 +205,10 @@ public: TMBuilder.Options = std::move(Options); } + /// Enable the Freestanding mode: indicate that the optimizer should not + /// assume builtins are present on the target. + void setFreestanding(bool Enabled) { Freestanding = Enabled; } + /// CodeModel void setCodePICModel(Optional Model) { TMBuilder.RelocModel = Model; @@ -322,6 +326,10 @@ private: /// importing or optimization. bool CodeGenOnly = false; + /// Flag to indicate that the optimizer should not assume builtins are present + /// on the target. + bool Freestanding = false; + /// IR Optimization Level [0-3]. unsigned OptLevel = 3; }; diff --git a/lib/LTO/LTOCodeGenerator.cpp b/lib/LTO/LTOCodeGenerator.cpp index 79f5a3c6031..86fba843e98 100644 --- a/lib/LTO/LTOCodeGenerator.cpp +++ b/lib/LTO/LTOCodeGenerator.cpp @@ -555,6 +555,8 @@ bool LTOCodeGenerator::optimize(bool DisableVerify, bool DisableInline, if (!DisableInline) PMB.Inliner = createFunctionInliningPass(); PMB.LibraryInfo = new TargetLibraryInfoImpl(TargetTriple); + if (Freestanding) + PMB.LibraryInfo->disableAllFunctions(); PMB.OptLevel = OptLevel; PMB.VerifyInput = !DisableVerify; PMB.VerifyOutput = !DisableVerify; diff --git a/lib/LTO/ThinLTOCodeGenerator.cpp b/lib/LTO/ThinLTOCodeGenerator.cpp index aa4d32a9c57..970c75e4ace 100644 --- a/lib/LTO/ThinLTOCodeGenerator.cpp +++ b/lib/LTO/ThinLTOCodeGenerator.cpp @@ -187,10 +187,12 @@ crossImportIntoModule(Module &TheModule, const ModuleSummaryIndex &Index, } static void optimizeModule(Module &TheModule, TargetMachine &TM, - unsigned OptLevel) { + unsigned OptLevel, bool Freestanding) { // Populate the PassManager PassManagerBuilder PMB; PMB.LibraryInfo = new TargetLibraryInfoImpl(TM.getTargetTriple()); + if (Freestanding) + PMB.LibraryInfo->disableAllFunctions(); PMB.Inliner = createFunctionInliningPass(); // FIXME: should get it from the bitcode? PMB.OptLevel = OptLevel; @@ -264,7 +266,7 @@ public: const std::map &ResolvedODR, const GVSummaryMapTy &DefinedFunctions, const DenseSet &PreservedSymbols, unsigned OptLevel, - const TargetMachineBuilder &TMBuilder) { + bool Freestanding, const TargetMachineBuilder &TMBuilder) { if (CachePath.empty()) return; @@ -321,6 +323,7 @@ public: AddUnsigned(*TMBuilder.RelocModel); AddUnsigned(TMBuilder.CGOptLevel); AddUnsigned(OptLevel); + AddUnsigned(Freestanding); Hasher.update(ArrayRef((uint8_t *)&ModHash[0], sizeof(ModHash))); for (auto F : ExportList) @@ -404,7 +407,7 @@ ProcessThinLTOModule(Module &TheModule, ModuleSummaryIndex &Index, const GVSummaryMapTy &DefinedGlobals, const ThinLTOCodeGenerator::CachingOptions &CacheOptions, bool DisableCodeGen, StringRef SaveTempsDir, - unsigned OptLevel, unsigned count) { + bool Freestanding, unsigned OptLevel, unsigned count) { // "Benchmark"-like optimization: single-source case bool SingleModule = (ModuleMap.size() == 1); @@ -436,7 +439,7 @@ ProcessThinLTOModule(Module &TheModule, ModuleSummaryIndex &Index, saveTempBitcode(TheModule, SaveTempsDir, count, ".3.imported.bc"); } - optimizeModule(TheModule, TM, OptLevel); + optimizeModule(TheModule, TM, OptLevel, Freestanding); saveTempBitcode(TheModule, SaveTempsDir, count, ".4.opt.bc"); @@ -762,7 +765,7 @@ void ThinLTOCodeGenerator::optimize(Module &TheModule) { initTMBuilder(TMBuilder, Triple(TheModule.getTargetTriple())); // Optimize now - optimizeModule(TheModule, *TMBuilder.create(), OptLevel); + optimizeModule(TheModule, *TMBuilder.create(), OptLevel, Freestanding); } /** @@ -948,7 +951,7 @@ void ThinLTOCodeGenerator::run() { ImportLists[ModuleIdentifier], ExportList, ResolvedODR[ModuleIdentifier], DefinedFunctions, GUIDPreservedSymbols, - OptLevel, TMBuilder); + OptLevel, Freestanding, TMBuilder); auto CacheEntryPath = CacheEntry.getEntryPath(); { @@ -994,7 +997,7 @@ void ThinLTOCodeGenerator::run() { *TheModule, *Index, ModuleMap, *TMBuilder.create(), ImportList, ExportList, GUIDPreservedSymbols, ModuleToDefinedGVSummaries[ModuleIdentifier], CacheOptions, - DisableCodeGen, SaveTempsDir, OptLevel, count); + DisableCodeGen, SaveTempsDir, Freestanding, OptLevel, count); // Commit to the cache (if enabled) CacheEntry.write(*OutputBuffer); diff --git a/test/ThinLTO/X86/tli-nobuiltin.ll b/test/ThinLTO/X86/tli-nobuiltin.ll new file mode 100644 index 00000000000..9a480cba115 --- /dev/null +++ b/test/ThinLTO/X86/tli-nobuiltin.ll @@ -0,0 +1,46 @@ +; Test -lto-freestanding option for libLTO. +; RUN: llvm-as < %s > %t.bc + +; Regular run: expects fprintf to be turned into fwrite +; RUN: llvm-lto %t.bc -exported-symbol=_foo -o %t.o +; RUN: llvm-nm %t.o | FileCheck %s --check-prefix=LTO +; LTO: fwrite + +; Freestanding run: expects fprintf to NOT be turned into fwrite +; RUN: llvm-lto %t.bc -lto-freestanding -exported-symbol=_foo -o %t.o +; RUN: llvm-nm %t.o | FileCheck %s --check-prefix=LTO-FREESTANDING +; LTO-FREESTANDING: fprintf + +; Same with ThinLTO now. +; RUN: opt -module-hash -module-summary %s -o %t.bc + +; Regular run: expects fprintf to be turned into fwrite +; RUN: llvm-lto -exported-symbol=_foo -thinlto-action=run %t.bc +; RUN: llvm-nm %t.bc.thinlto.o | FileCheck %s --check-prefix=ThinLTO +; ThinLTO: fwrite + +; Freestanding run: expects fprintf to NOT be turned into fwrite +; RUN: llvm-lto -lto-freestanding -exported-symbol=_foo -thinlto-action=run %t.bc +; RUN: llvm-nm %t.bc.thinlto.o | FileCheck %s --check-prefix=ThinLTO-FREESTANDING +; ThinLTO-FREESTANDING: fprintf + + +target datalayout = "e-m:o-i64:64-f80:128-n8:16:32:64-S128" +target triple = "x86_64-apple-macosx10.11.0" + +declare i32 @fprintf(%FILE*, i8*, ...) + +%FILE = type { } + +@hello_world = constant [13 x i8] c"hello world\0A\00" +@percent_s = constant [3 x i8] c"%s\00" + +; Check fprintf(fp, "%s", str) -> fwrite(str, fp) only when builtins are enabled + +define void @foo(%FILE* %fp) { + %fmt = getelementptr [3 x i8], [3 x i8]* @percent_s, i32 0, i32 0 + %str = getelementptr [13 x i8], [13 x i8]* @hello_world, i32 0, i32 0 + call i32 (%FILE*, i8*, ...) @fprintf(%FILE* %fp, i8* %fmt, i8* %str) + ret void +} + diff --git a/tools/llvm-lto/llvm-lto.cpp b/tools/llvm-lto/llvm-lto.cpp index 475350c8ecf..2f005412a3b 100644 --- a/tools/llvm-lto/llvm-lto.cpp +++ b/tools/llvm-lto/llvm-lto.cpp @@ -63,6 +63,10 @@ static cl::opt DisableLTOVectorization( "disable-lto-vectorization", cl::init(false), cl::desc("Do not run loop or slp vectorization during LTO")); +static cl::opt EnableFreestanding( + "lto-freestanding", cl::init(false), + cl::desc("Enable Freestanding (disable builtins / TLI) during LTO")); + static cl::opt UseDiagnosticHandler( "use-diagnostic-handler", cl::init(false), cl::desc("Use a diagnostic handler to test the handler interface")); @@ -433,6 +437,7 @@ public: ThinGenerator.setCodePICModel(getRelocModel()); ThinGenerator.setTargetOptions(Options); ThinGenerator.setCacheDir(ThinLTOCacheDir); + ThinGenerator.setFreestanding(EnableFreestanding); // Add all the exported symbols to the table of symbols to preserve. for (unsigned i = 0; i < ExportedSymbols.size(); ++i) @@ -809,6 +814,7 @@ int main(int argc, char **argv) { CodeGen.setDiagnosticHandler(handleDiagnostics, nullptr); CodeGen.setCodePICModel(getRelocModel()); + CodeGen.setFreestanding(EnableFreestanding); CodeGen.setDebugInfo(LTO_DEBUG_MODEL_DWARF); CodeGen.setTargetOptions(Options); diff --git a/tools/lto/lto.cpp b/tools/lto/lto.cpp index a1dd4ebbccb..e28c7aaf526 100644 --- a/tools/lto/lto.cpp +++ b/tools/lto/lto.cpp @@ -44,9 +44,13 @@ static cl::opt DisableGVNLoadPRE("disable-gvn-loadpre", cl::init(false), cl::desc("Do not run the GVN load PRE pass")); -static cl::opt -DisableLTOVectorization("disable-lto-vectorization", cl::init(false), - cl::desc("Do not run loop or slp vectorization during LTO")); +static cl::opt DisableLTOVectorization( + "disable-lto-vectorization", cl::init(false), + cl::desc("Do not run loop or slp vectorization during LTO")); + +static cl::opt EnableFreestanding( + "lto-freestanding", cl::init(false), + cl::desc("Enable Freestanding (disable builtins / TLI) during LTO")); #ifdef NDEBUG static bool VerifyByDefault = false; @@ -159,6 +163,7 @@ static void lto_add_attrs(lto_code_gen_t cg) { if (OptLevel < '0' || OptLevel > '3') report_fatal_error("Optimization level must be between 0 and 3"); CG->setOptLevel(OptLevel - '0'); + CG->setFreestanding(EnableFreestanding); } extern const char* lto_get_version() { @@ -464,6 +469,7 @@ thinlto_code_gen_t thinlto_create_codegen(void) { lto_initialize(); ThinLTOCodeGenerator *CodeGen = new ThinLTOCodeGenerator(); CodeGen->setTargetOptions(InitTargetOptionsFromCodeGenFlags()); + CodeGen->setFreestanding(EnableFreestanding); if (OptLevel.getNumOccurrences()) { if (OptLevel < '0' || OptLevel > '3') -- 2.40.0