Index: llvm/include/llvm/Transforms/IPO/PassManagerBuilder.h =================================================================== --- llvm/include/llvm/Transforms/IPO/PassManagerBuilder.h +++ llvm/include/llvm/Transforms/IPO/PassManagerBuilder.h @@ -153,6 +153,7 @@ bool PrepareForLTO; bool PrepareForThinLTO; bool PerformThinLTO; + bool PerformLTO; /// Enable profile instrumentation pass. bool EnablePGOInstrGen; @@ -180,8 +181,6 @@ void addExtensionsToPM(ExtensionPointTy ETy, legacy::PassManagerBase &PM) const; void addInitialAliasAnalysisPasses(legacy::PassManagerBase &PM) const; - void addLTOOptimizationPasses(legacy::PassManagerBase &PM); - void addLateLTOOptimizationPasses(legacy::PassManagerBase &PM); void addPGOInstrPasses(legacy::PassManagerBase &MPM); void addFunctionSimplificationPasses(legacy::PassManagerBase &MPM); void addInstructionCombiningPass(legacy::PassManagerBase &MPM) const; @@ -194,7 +193,8 @@ /// populateModulePassManager - This sets up the primary pass manager. void populateModulePassManager(legacy::PassManagerBase &MPM); - void populateLTOPassManager(legacy::PassManagerBase &PM); + void populateLTOPassManager(legacy::PassManagerBase &PM, + bool IsThinLTO = false); void populateThinLTOPassManager(legacy::PassManagerBase &PM); }; Index: llvm/lib/Transforms/IPO/PassManagerBuilder.cpp =================================================================== --- llvm/lib/Transforms/IPO/PassManagerBuilder.cpp +++ llvm/lib/Transforms/IPO/PassManagerBuilder.cpp @@ -444,6 +444,11 @@ // Promote any localized global vars. MPM.add(createPromoteMemoryToRegisterPass()); + // Linking modules together can lead to duplicated global constants, only + // keep one copy of each constant. + if (PerformLTO) + MPM.add(createConstantMergePass()); + MPM.add(createDeadArgEliminationPass()); // Dead argument elimination addInstructionCombiningPass(MPM); // Clean up after IPCP & DAE @@ -506,11 +511,12 @@ // 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) { + if (PrepareForThinLTO || PrepareForLTO) { // Reduce the size of the IR as much as possible. MPM.add(createGlobalOptimizerPass()); - // Rename anon globals to be able to export them in the summary. - MPM.add(createNameAnonGlobalPass()); + if (PrepareForThinLTO) + // Rename anon globals to be able to export them in the summary. + MPM.add(createNameAnonGlobalPass()); return; } @@ -662,210 +668,66 @@ addExtensionsToPM(EP_OptimizerLast, MPM); } -void PassManagerBuilder::addLTOOptimizationPasses(legacy::PassManagerBase &PM) { - // Remove unused virtual tables to improve the quality of code generated by - // whole-program devirtualization and bitset lowering. - PM.add(createGlobalDCEPass()); - - // Provide AliasAnalysis services for optimizations. - addInitialAliasAnalysisPasses(PM); - - // Allow forcing function attributes as a debugging and tuning aid. - PM.add(createForceFunctionAttrsLegacyPass()); - - // Infer attributes about declarations if possible. - PM.add(createInferFunctionAttrsLegacyPass()); - - if (OptLevel > 1) { - // Indirect call promotion. This should promote all the targets that are - // left by the earlier promotion pass that promotes intra-module targets. - // This two-step promotion is to save the compile time. For LTO, it should - // produce the same result as if we only do promotion here. - PM.add(createPGOIndirectCallPromotionLegacyPass(true)); - - // Propagate constants at call sites into the functions they call. This - // opens opportunities for globalopt (and inlining) by substituting function - // pointers passed as arguments to direct uses of functions. - PM.add(createIPSCCPPass()); - } - - // Infer attributes about definitions. The readnone attribute in particular is - // required for virtual constant propagation. - PM.add(createPostOrderFunctionAttrsLegacyPass()); - PM.add(createReversePostOrderFunctionAttrsPass()); - - // Split globals using inrange annotations on GEP indices. This can help - // improve the quality of generated code when virtual constant propagation or - // control flow integrity are enabled. - PM.add(createGlobalSplitPass()); - - // Apply whole-program devirtualization and virtual constant propagation. - PM.add(createWholeProgramDevirtPass()); - - // That's all we need at opt level 1. - if (OptLevel == 1) - return; - - // Now that we internalized some globals, see if we can hack on them! - PM.add(createGlobalOptimizerPass()); - // Promote any localized global vars. - PM.add(createPromoteMemoryToRegisterPass()); - - // Linking modules together can lead to duplicated global constants, only - // keep one copy of each constant. - PM.add(createConstantMergePass()); - - // Remove unused arguments from functions. - PM.add(createDeadArgEliminationPass()); - - // Reduce the code after globalopt and ipsccp. Both can open up significant - // simplification opportunities, and both can propagate functions through - // function pointers. When this happens, we often have to resolve varargs - // calls, etc, so let instcombine do this. - addInstructionCombiningPass(PM); - addExtensionsToPM(EP_Peephole, PM); - - // Inline small functions - bool RunInliner = Inliner; - if (RunInliner) { - PM.add(Inliner); - Inliner = nullptr; - } - - PM.add(createPruneEHPass()); // Remove dead EH info. - - // Optimize globals again if we ran the inliner. - if (RunInliner) - PM.add(createGlobalOptimizerPass()); - PM.add(createGlobalDCEPass()); // Remove dead functions. - - // If we didn't decide to inline a function, check to see if we can - // transform it to pass arguments by value instead of by reference. - PM.add(createArgumentPromotionPass()); - - // The IPO passes may leave cruft around. Clean up after them. - addInstructionCombiningPass(PM); - addExtensionsToPM(EP_Peephole, PM); - PM.add(createJumpThreadingPass()); - - // Break up allocas - PM.add(createSROAPass()); - - // Run a few AA driven optimizations here and now, to cleanup the code. - PM.add(createPostOrderFunctionAttrsLegacyPass()); // Add nocapture. - PM.add(createGlobalsAAWrapperPass()); // IP alias analysis. - - PM.add(createLICMPass()); // Hoist loop invariants. - PM.add(createMergedLoadStoreMotionPass()); // Merge ld/st in diamonds. - PM.add(NewGVN ? createNewGVNPass() - : createGVNPass(DisableGVNLoadPRE)); // Remove redundancies. - PM.add(createMemCpyOptPass()); // Remove dead memcpys. - - // Nuke dead stores. - PM.add(createDeadStoreEliminationPass()); - - // More loops are countable; try to optimize them. - PM.add(createIndVarSimplifyPass()); - PM.add(createLoopDeletionPass()); - if (EnableLoopInterchange) - PM.add(createLoopInterchangePass()); - - if (!DisableUnrollLoops) - PM.add(createSimpleLoopUnrollPass()); // Unroll small loops - PM.add(createLoopVectorizePass(true, LoopVectorize)); - // The vectorizer may have significantly shortened a loop body; unroll again. - if (!DisableUnrollLoops) - PM.add(createLoopUnrollPass()); - - // Now that we've optimized loops (in particular loop induction variables), - // we may have exposed more scalar opportunities. Run parts of the scalar - // optimizer again at this point. - addInstructionCombiningPass(PM); // Initial cleanup - PM.add(createCFGSimplificationPass()); // if-convert - PM.add(createSCCPPass()); // Propagate exposed constants - addInstructionCombiningPass(PM); // Clean up again - PM.add(createBitTrackingDCEPass()); - - // More scalar chains could be vectorized due to more alias information - if (RunSLPAfterLoopVectorization) - if (SLPVectorize) - PM.add(createSLPVectorizerPass()); // Vectorize parallel scalar chains. - - // After vectorization, assume intrinsics may tell us more about pointer - // alignments. - PM.add(createAlignmentFromAssumptionsPass()); - - if (LoadCombine) - PM.add(createLoadCombinePass()); - - // Cleanup and simplify the code after the scalar optimizations. - addInstructionCombiningPass(PM); - addExtensionsToPM(EP_Peephole, PM); - - PM.add(createJumpThreadingPass()); -} - -void PassManagerBuilder::addLateLTOOptimizationPasses( - legacy::PassManagerBase &PM) { - // Delete basic blocks, which optimization passes may have killed. - PM.add(createCFGSimplificationPass()); - - // Drop bodies of available externally objects to improve GlobalDCE. - PM.add(createEliminateAvailableExternallyPass()); - - // Now that we have optimized the program, discard unreachable functions. - PM.add(createGlobalDCEPass()); - - // FIXME: this is profitable (for compiler time) to do at -O0 too, but - // currently it damages debug info. - if (MergeFunctions) - PM.add(createMergeFunctionsPass()); -} - void PassManagerBuilder::populateThinLTOPassManager( legacy::PassManagerBase &PM) { - PerformThinLTO = true; - - if (VerifyInput) - PM.add(createVerifierPass()); - - if (Summary) - PM.add( - createLowerTypeTestsPass(LowerTypeTestsSummaryAction::Import, Summary)); - - populateModulePassManager(PM); - - if (VerifyOutput) - PM.add(createVerifierPass()); - PerformThinLTO = false; + populateLTOPassManager(PM, true); } -void PassManagerBuilder::populateLTOPassManager(legacy::PassManagerBase &PM) { - if (LibraryInfo) - PM.add(new TargetLibraryInfoWrapperPass(*LibraryInfo)); +void PassManagerBuilder::populateLTOPassManager(legacy::PassManagerBase &PM, + bool IsThinLTO) { + if (IsThinLTO) + PerformThinLTO = true; + else + PerformLTO = true; if (VerifyInput) PM.add(createVerifierPass()); - if (OptLevel != 0) - addLTOOptimizationPasses(PM); + // Always start with GlobalDCE to prune after internalization. + // FIXME: if the frontend emits optnone at O0, we could always run DCE + // unconditionally. + if (OptLevel != 0) { + PM.add(createGlobalDCEPass()); + + if (PerformLTO) { + // Split globals using inrange annotations on GEP indices. This can help + // improve the quality of generated code when virtual constant propagation + // or + // control flow integrity are enabled. + PM.add(createGlobalSplitPass()); + + // Apply whole-program devirtualization and virtual constant propagation. + PM.add(createWholeProgramDevirtPass()); + } - // Create a function that performs CFI checks for cross-DSO calls with targets - // in the current module. - PM.add(createCrossDSOCFIPass()); + // Schedule the optimizations now. + populateModulePassManager(PM); + } - // Lower type metadata and the type.test intrinsic. This pass supports Clang's - // control flow integrity mechanisms (-fsanitize=cfi*) and needs to run at - // link time if CFI is enabled. The pass does nothing if CFI is disabled. - PM.add(createLowerTypeTestsPass(Summary ? LowerTypeTestsSummaryAction::Export - : LowerTypeTestsSummaryAction::None, - Summary)); + if (PerformThinLTO && Summary) + PM.add( + createLowerTypeTestsPass(LowerTypeTestsSummaryAction::Import, Summary)); - if (OptLevel != 0) - addLateLTOOptimizationPasses(PM); + if (PerformLTO) { + // Create a function that performs CFI checks for cross-DSO calls with + // targets in the current module. + PM.add(createCrossDSOCFIPass()); + + // Lower type metadata and the type.test intrinsic. This pass supports + // Clang's control flow integrity mechanisms (-fsanitize=cfi*) and needs to + // run at link time if CFI is enabled. The pass does nothing if CFI is + // disabled. + PM.add(createLowerTypeTestsPass(Summary + ? LowerTypeTestsSummaryAction::Export + : LowerTypeTestsSummaryAction::None, + Summary)); + } if (VerifyOutput) PM.add(createVerifierPass()); + + PerformThinLTO = false; + PerformLTO = false; } inline PassManagerBuilder *unwrap(LLVMPassManagerBuilderRef P) {