From 1db10ac6ce4deb09bf12a756965bee0b78f78292 Mon Sep 17 00:00:00 2001 From: Mehdi Amini Date: Tue, 16 Feb 2016 23:02:29 +0000 Subject: [PATCH] Define the ThinLTO Pipeline (experimental) Summary: On the contrary to Full LTO, ThinLTO can afford to shift compile time from the frontend to the linker: both phases are parallel (even if it is not totally "free": projects like clang are reusing product from the "compile phase" for multiple link, think about libLLVMSupport reused for opt, llc, etc.). This pipeline is based on the proposal in D13443 for full LTO. We didn't move forward on this proposal because the LTO link was far too long after that. We believe that we can afford it with ThinLTO. The ThinLTO pipeline integrates in the regular O2/O3 flow: - The compile phase perform the inliner with a somehow lighter function simplification. (TODO: tune the inliner thresholds here) This is intendend to simplify the IR and get rid of obvious things like linkonce_odr that will be inlined. - The link phase will run the pipeline from the start, extended with some specific passes that leverage the augmented knowledge we have during LTO. Especially after the inliner is done, a sequence of globalDCE/globalOpt is performed, followed by another run of the "function simplification" passes. It is not clear if this part of the pipeline will stay as is, as the split model of ThinLTO does not allow the same benefit as FullLTO without added tricks. The measurements on the public test suite as well as on our internal suite show an overall net improvement. The binary size for the clang executable is reduced by 5%. We're still tuning it with the bringup of ThinLTO and it will evolve, but this should provide a good starting point. Reviewers: tejohnson Differential Revision: http://reviews.llvm.org/D17115 From: Mehdi Amini llvm-svn: 261029 --- .../llvm/Transforms/IPO/PassManagerBuilder.h | 3 ++ llvm/lib/Transforms/IPO/PassManagerBuilder.cpp | 46 +++++++++++++++++++++- 2 files changed, 47 insertions(+), 2 deletions(-) diff --git a/llvm/include/llvm/Transforms/IPO/PassManagerBuilder.h b/llvm/include/llvm/Transforms/IPO/PassManagerBuilder.h index 37bf0c2..89c49d1 100644 --- a/llvm/include/llvm/Transforms/IPO/PassManagerBuilder.h +++ b/llvm/include/llvm/Transforms/IPO/PassManagerBuilder.h @@ -133,6 +133,8 @@ public: bool VerifyOutput; bool MergeFunctions; bool PrepareForLTO; + bool PrepareForThinLTO; + bool PerformThinLTO; /// Profile data file name that the instrumentation will be written to. std::string PGOInstrGen; @@ -171,6 +173,7 @@ public: /// populateModulePassManager - This sets up the primary pass manager. void populateModulePassManager(legacy::PassManagerBase &MPM); void populateLTOPassManager(legacy::PassManagerBase &PM); + void populateThinLTOPassManager(legacy::PassManagerBase &PM); }; /// Registers a function for adding a standard set of passes. This should be diff --git a/llvm/lib/Transforms/IPO/PassManagerBuilder.cpp b/llvm/lib/Transforms/IPO/PassManagerBuilder.cpp index 8b0e8d3..266ba8e 100644 --- a/llvm/lib/Transforms/IPO/PassManagerBuilder.cpp +++ b/llvm/lib/Transforms/IPO/PassManagerBuilder.cpp @@ -140,6 +140,8 @@ PassManagerBuilder::PassManagerBuilder() { PrepareForLTO = false; PGOInstrGen = RunPGOInstrGen; PGOInstrUse = RunPGOInstrUse; + PrepareForThinLTO = false; + PerformThinLTO = false; } PassManagerBuilder::~PassManagerBuilder() { @@ -233,6 +235,11 @@ void PassManagerBuilder::addFunctionSimplificationPasses( MPM.add(createTailCallEliminationPass()); // Eliminate tail calls MPM.add(createCFGSimplificationPass()); // Merge & remove BBs MPM.add(createReassociatePass()); // Reassociate expressions + if (PrepareForThinLTO) { + MPM.add(createAggressiveDCEPass()); // Delete dead instructions + MPM.add(createInstructionCombiningPass()); // Combine silly seq's + return; + } // Rotate Loop - disable header duplication at -Oz MPM.add(createLoopRotatePass(SizeLevel == 2 ? 0 : -1)); MPM.add(createLICMPass()); // Hoist loop invariants @@ -356,7 +363,10 @@ void PassManagerBuilder::populateModulePassManager( MPM.add(createCFGSimplificationPass()); // Clean up after IPCP & DAE } - addPGOInstrPasses(MPM); + if (!PerformThinLTO) + /// PGO instrumentation is added during the compile phase for ThinLTO, do + /// not run it a second time + addPGOInstrPasses(MPM); if (EnableNonLTOGlobalsModRef) // We add a module alias analysis pass here. In part due to bugs in the @@ -378,6 +388,12 @@ void PassManagerBuilder::populateModulePassManager( addFunctionSimplificationPasses(MPM); + // If we are planning to perform ThinLTO later, let's not bloat the code with + // unrolling/vectorization/... now. We'll first run the inliner + CGSCC passes + // during ThinLTO and perform the rest of the optimizations afterward. + if (PrepareForThinLTO) + return; + // FIXME: This is a HACK! The inliner pass above implicitly creates a CGSCC // pass manager that we are specifically trying to avoid. To prevent this // we must insert a no-op module pass to reset the pass manager. @@ -396,7 +412,7 @@ void PassManagerBuilder::populateModulePassManager( if (!DisableUnitAtATime) MPM.add(createReversePostOrderFunctionAttrsPass()); - if (!DisableUnitAtATime && OptLevel > 1 && !PrepareForLTO) { + if (!DisableUnitAtATime && OptLevel > 1 && !PrepareForLTO) // Remove avail extern fns and globals definitions if we aren't // compiling an object file for later LTO. For LTO we want to preserve // these so they are eligible for inlining at link-time. Note if they @@ -407,6 +423,15 @@ void PassManagerBuilder::populateModulePassManager( // globals referenced by available external functions dead // and saves running remaining passes on the eliminated functions. MPM.add(createEliminateAvailableExternallyPass()); + + if (PerformThinLTO) { + // Remove dead fns and globals. Removing unreferenced functions could lead + // to more opportunities for globalopt. + MPM.add(createGlobalDCEPass()); + MPM.add(createGlobalOptimizerPass()); + // Remove dead fns and globals after globalopt. + MPM.add(createGlobalDCEPass()); + addFunctionSimplificationPasses(MPM); } if (EnableNonLTOGlobalsModRef) @@ -682,6 +707,23 @@ void PassManagerBuilder::addLateLTOOptimizationPasses( PM.add(createMergeFunctionsPass()); } +void PassManagerBuilder::populateThinLTOPassManager( + legacy::PassManagerBase &PM) { + PerformThinLTO = true; + + if (VerifyInput) + PM.add(createVerifierPass()); + + if (FunctionIndex) + PM.add(createFunctionImportPass(FunctionIndex)); + + populateModulePassManager(PM); + + if (VerifyOutput) + PM.add(createVerifierPass()); + PerformThinLTO = false; +} + void PassManagerBuilder::populateLTOPassManager(legacy::PassManagerBase &PM) { if (LibraryInfo) PM.add(new TargetLibraryInfoWrapperPass(*LibraryInfo)); -- 2.7.4