Index: llvm/include/llvm/InitializePasses.h =================================================================== --- llvm/include/llvm/InitializePasses.h +++ llvm/include/llvm/InitializePasses.h @@ -421,7 +421,7 @@ void initializeWriteBitcodePassPass(PassRegistry&); void initializeWriteThinLTOBitcodePass(PassRegistry&); void initializeXRayInstrumentationPass(PassRegistry&); - +void initializeCGProfileLegacyPassPass(PassRegistry &); } // end namespace llvm #endif // LLVM_INITIALIZEPASSES_H Index: llvm/include/llvm/LinkAllPasses.h =================================================================== --- llvm/include/llvm/LinkAllPasses.h +++ llvm/include/llvm/LinkAllPasses.h @@ -84,6 +84,7 @@ (void) llvm::createCFGSimplificationPass(); (void) llvm::createCFLAndersAAWrapperPass(); (void) llvm::createCFLSteensAAWrapperPass(); + (void)llvm::createCGProfilePass(); (void) llvm::createStructurizeCFGPass(); (void) llvm::createLibCallsShrinkWrapPass(); (void) llvm::createCalledValuePropagationPass(); Index: llvm/include/llvm/Transforms/IPO.h =================================================================== --- llvm/include/llvm/Transforms/IPO.h +++ llvm/include/llvm/Transforms/IPO.h @@ -89,6 +89,12 @@ ModulePass *createGVExtractionPass(std::vector& GVs, bool deleteFn = false); +//===----------------------------------------------------------------------===// +/// createCGProfilePass - This function returns a new pass that generates +/// call graph profile metadata. +/// +ModulePass *createCGProfilePass(); + //===----------------------------------------------------------------------===// /// This pass performs iterative function importing from other modules. Pass *createFunctionImportPass(); Index: llvm/include/llvm/Transforms/Instrumentation/CGProfile.h =================================================================== --- llvm/include/llvm/Transforms/Instrumentation/CGProfile.h +++ llvm/include/llvm/Transforms/Instrumentation/CGProfile.h @@ -19,12 +19,9 @@ class CGProfilePass : public PassInfoMixin { public: PreservedAnalyses run(Module &M, ModuleAnalysisManager &AM); - -private: - void addModuleFlags( - Module &M, - MapVector, uint64_t> &Counts) const; }; + +ModulePass *createCGProfilePass(); } // end namespace llvm #endif // LLVM_TRANSFORMS_CGPROFILE_H Index: llvm/lib/Transforms/IPO/PassManagerBuilder.cpp =================================================================== --- llvm/lib/Transforms/IPO/PassManagerBuilder.cpp +++ llvm/lib/Transforms/IPO/PassManagerBuilder.cpp @@ -777,6 +777,9 @@ // resulted in single-entry-single-exit or empty blocks. Clean up the CFG. MPM.add(createCFGSimplificationPass()); + // Create CG profile metadata if appropriate + MPM.add(createCGProfilePass()); + addExtensionsToPM(EP_OptimizerLast, MPM); if (PrepareForLTO) { Index: llvm/lib/Transforms/Instrumentation/CGProfile.cpp =================================================================== --- llvm/lib/Transforms/Instrumentation/CGProfile.cpp +++ llvm/lib/Transforms/Instrumentation/CGProfile.cpp @@ -23,11 +23,11 @@ using namespace llvm; -PreservedAnalyses CGProfilePass::run(Module &M, ModuleAnalysisManager &MAM) { - MapVector, uint64_t> Counts; - FunctionAnalysisManager &FAM = - MAM.getResult(M).getManager(); +static void generateCGProfileMetadata( + Module &M, function_ref GetTTI, + function_ref GetBFI) { InstrProfSymtab Symtab; + MapVector, uint64_t> Counts; auto UpdateCounts = [&](TargetTransformInfo &TTI, Function *F, Function *CalledF, uint64_t NewCount) { if (!CalledF || !TTI.isLoweredToCall(CalledF)) @@ -40,10 +40,10 @@ for (auto &F : M) { if (F.isDeclaration()) continue; - auto &BFI = FAM.getResult(F); + auto &BFI = GetBFI(F); if (BFI.getEntryFreq() == 0) continue; - TargetTransformInfo &TTI = FAM.getResult(F); + TargetTransformInfo &TTI = GetTTI(F); for (auto &BB : F) { Optional BBCount = BFI.getBlockProfileCount(&BB); if (!BBCount) @@ -71,14 +71,6 @@ } } - addModuleFlags(M, Counts); - - return PreservedAnalyses::all(); -} - -void CGProfilePass::addModuleFlags( - Module &M, - MapVector, uint64_t> &Counts) const { if (Counts.empty()) return; @@ -96,3 +88,62 @@ M.addModuleFlag(Module::Append, "CG Profile", MDNode::get(Context, Nodes)); } + +PreservedAnalyses CGProfilePass::run(Module &M, ModuleAnalysisManager &MAM) { + FunctionAnalysisManager &FAM = + MAM.getResult(M).getManager(); + + auto GetTTI = [&FAM](Function &F) -> TargetTransformInfo & { + return FAM.getResult(F); + }; + + auto GetBFI = [&FAM](Function &F) -> BlockFrequencyInfo & { + return FAM.getResult(F); + }; + generateCGProfileMetadata(M, GetTTI, GetBFI); + return PreservedAnalyses::all(); +} + +namespace { + +struct CGProfileLegacyPass : public ModulePass { + static char ID; // Pass identification, replacement for typeid + + CGProfileLegacyPass() : ModulePass(ID) { + initializeCGProfileLegacyPassPass(*PassRegistry::getPassRegistry()); + } + + bool runOnModule(Module &M) override { + if (skipModule(M)) + return false; + + auto GetTTI = [this](Function &F) -> TargetTransformInfo & { + return this->getAnalysis().getTTI(F); + }; + + auto GetBFI = [this](Function &F) -> BlockFrequencyInfo & { + return this->getAnalysis(F).getBFI(); + }; + + generateCGProfileMetadata(M, GetTTI, GetBFI); + return false; + } + + void getAnalysisUsage(AnalysisUsage &AU) const override { + AU.addRequired(); + AU.addRequired(); + } +}; + +} // end anonymous namespace + +char CGProfileLegacyPass::ID = 0; + +INITIALIZE_PASS_BEGIN(CGProfileLegacyPass, "cgprofile", + "CG profile metadata generator", false, false) +INITIALIZE_PASS_DEPENDENCY(TargetTransformInfoWrapperPass) +INITIALIZE_PASS_DEPENDENCY(BlockFrequencyInfoWrapperPass) +INITIALIZE_PASS_END(CGProfileLegacyPass, "cgprofile", + "CG profile metadata generator", false, false) + +ModulePass *llvm::createCGProfilePass() { return new CGProfileLegacyPass(); } Index: llvm/test/Other/opt-O2-pipeline.ll =================================================================== --- llvm/test/Other/opt-O2-pipeline.ll +++ llvm/test/Other/opt-O2-pipeline.ll @@ -295,6 +295,13 @@ ; CHECK-NEXT: Remove redundant instructions ; CHECK-NEXT: Hoist/decompose integer division and remainder ; CHECK-NEXT: Simplify the CFG +; CHECK-NEXT: CG profile metadata generator +; CHECK-NEXT: FunctionPass Manager +; CHECK-NEXT: Dominator Tree Construction +; CHECK-NEXT: Natural Loop Information +; CHECK-NEXT: Branch Probability Analysis +; CHECK-NEXT: Block Frequency Analysis +; CHECK-NEXT: FunctionPass Manager ; CHECK-NEXT: Module Verifier ; CHECK-NEXT: Bitcode Writer ; CHECK-NEXT: Pass Arguments: Index: llvm/test/Other/opt-O3-pipeline.ll =================================================================== --- llvm/test/Other/opt-O3-pipeline.ll +++ llvm/test/Other/opt-O3-pipeline.ll @@ -300,6 +300,13 @@ ; CHECK-NEXT: Remove redundant instructions ; CHECK-NEXT: Hoist/decompose integer division and remainder ; CHECK-NEXT: Simplify the CFG +; CHECK-NEXT: CG profile metadata generator +; CHECK-NEXT: FunctionPass Manager +; CHECK-NEXT: Dominator Tree Construction +; CHECK-NEXT: Natural Loop Information +; CHECK-NEXT: Branch Probability Analysis +; CHECK-NEXT: Block Frequency Analysis +; CHECK-NEXT: FunctionPass Manager ; CHECK-NEXT: Module Verifier ; CHECK-NEXT: Bitcode Writer ; CHECK-NEXT: Pass Arguments: Index: llvm/test/Other/opt-Os-pipeline.ll =================================================================== --- llvm/test/Other/opt-Os-pipeline.ll +++ llvm/test/Other/opt-Os-pipeline.ll @@ -282,6 +282,13 @@ ; CHECK-NEXT: Remove redundant instructions ; CHECK-NEXT: Hoist/decompose integer division and remainder ; CHECK-NEXT: Simplify the CFG +; CHECK-NEXT: CG profile metadata generator +; CHECK-NEXT: FunctionPass Manager +; CHECK-NEXT: Dominator Tree Construction +; CHECK-NEXT: Natural Loop Information +; CHECK-NEXT: Branch Probability Analysis +; CHECK-NEXT: Block Frequency Analysis +; CHECK-NEXT: FunctionPass Manager ; CHECK-NEXT: Module Verifier ; CHECK-NEXT: Bitcode Writer ; CHECK-NEXT: Pass Arguments: Index: llvm/test/Other/pass-pipelines.ll =================================================================== --- llvm/test/Other/pass-pipelines.ll +++ llvm/test/Other/pass-pipelines.ll @@ -104,7 +104,6 @@ ; CHECK-O2: Loop Pass Manager ; CHECK-O2-NEXT: Loop Sink ; CHECK-O2: Simplify the CFG -; CHECK-O2-NOT: Manager ; ; FIXME: There really shouldn't be another pass manager, especially one that ; just builds the domtree. It doesn't even run the verifier.