Index: include/llvm/IR/LegacyPassManagers.h =================================================================== --- include/llvm/IR/LegacyPassManagers.h +++ include/llvm/IR/LegacyPassManagers.h @@ -403,6 +403,14 @@ InheritedAnalysis[Index++] = (*I)->getAvailableAnalysis(); } + /// Return the total number of IR instructions in \p M. + int getModuleInstrCount(Module &M); + + /// \brief Emit a remark signifying that the number of IR instructions in the + /// module changed. + void emitIRSizeChangedRemark(Pass *P, Module &M, const int &OriginalCount, + const int &FinalCount); + protected: // Top level manager. PMTopLevelManager *TPM; Index: lib/Analysis/CallGraphSCCPass.cpp =================================================================== --- lib/Analysis/CallGraphSCCPass.cpp +++ lib/Analysis/CallGraphSCCPass.cpp @@ -120,7 +120,7 @@ bool &DevirtualizedCall) { bool Changed = false; PMDataManager *PM = P->getAsPMDataManager(); - + Module &M = CG.getModule(); if (!PM) { CallGraphSCCPass *CGSP = (CallGraphSCCPass*)P; if (!CallGraphUpToDate) { @@ -130,7 +130,10 @@ { TimeRegion PassTimer(getPassTimer(CGSP)); + int OriginalCount = getModuleInstrCount(M); Changed = CGSP->runOnSCC(CurSCC); + int FinalCount = getModuleInstrCount(M); + emitIRSizeChangedRemark(P, M, OriginalCount, FinalCount); } // After the CGSCCPass is done, when assertions are enabled, use @@ -153,7 +156,10 @@ dumpPassInfo(P, EXECUTION_MSG, ON_FUNCTION_MSG, F->getName()); { TimeRegion PassTimer(getPassTimer(FPP)); + int OriginalCount = getModuleInstrCount(M); Changed |= FPP->runOnFunction(*F); + int FinalCount = getModuleInstrCount(M); + emitIRSizeChangedRemark(P, M, OriginalCount, FinalCount); } F->getContext().yield(); } Index: lib/IR/LegacyPassManager.cpp =================================================================== --- lib/IR/LegacyPassManager.cpp +++ lib/IR/LegacyPassManager.cpp @@ -13,6 +13,7 @@ #include "llvm/IR/LegacyPassManager.h" #include "llvm/ADT/Statistic.h" +#include "llvm/IR/DiagnosticInfo.h" #include "llvm/IR/IRPrintingPasses.h" #include "llvm/IR/LLVMContext.h" #include "llvm/IR/LegacyPassManagers.h" @@ -128,8 +129,40 @@ return PassDebugging >= Executions; } - - +int PMDataManager::getModuleInstrCount(Module &M) { + int Instrs = 0; + for (Function &F : M) + for (BasicBlock &BB : F) + Instrs += BB.size(); + return Instrs; +} + +void PMDataManager::emitIRSizeChangedRemark(Pass *P, Module &M, + const int &OriginalCount, + const int &FinalCount) { + // If there was no change, don't emit a remark. + if (OriginalCount == FinalCount) + return; + + // If it's a pass manager, don't emit a remark. + if (P->getAsPMDataManager()) + return; + + Function &F = *M.begin(); + BasicBlock &BB = *F.begin(); + assert(OriginalCount != FinalCount && "IR size did not change!"); + OptimizationRemarkAnalysis R("size-info", "IRSizeChange", + DiagnosticLocation(), &BB); + R << DiagnosticInfoOptimizationBase::Argument("Pass", P->getPassName()) + << ": IR instruction count changed from " + << DiagnosticInfoOptimizationBase::Argument("IRInstrsBefore", OriginalCount) + << " to " + << DiagnosticInfoOptimizationBase::Argument("IRInstrsAfter", FinalCount) + << "; Delta: " + << DiagnosticInfoOptimizationBase::Argument("DeltaInstrCount", + FinalCount - OriginalCount); + F.getContext().diagnose(R); +} void PassManagerPrettyStackEntry::print(raw_ostream &OS) const { if (!V && !M) @@ -173,7 +206,7 @@ public: static char ID; - explicit BBPassManager() + explicit BBPassManager() : PMDataManager(), FunctionPass(ID) {} /// Execute all of the passes scheduled for execution. Keep track of @@ -322,7 +355,7 @@ using llvm::Pass::doInitialization; using llvm::Pass::doFinalization; - + /// Pass Manager itself does not invalidate any analysis info. void getAnalysisUsage(AnalysisUsage &Info) const override { Info.setPreservesAll(); @@ -350,7 +383,7 @@ ModulePass *MP = getContainedPass(Index); MP->dumpPassStructure(Offset + 1); std::map::const_iterator I = - OnTheFlyManagers.find(MP); + OnTheFlyManagers.find(MP); if (I != OnTheFlyManagers.end()) I->second->dumpPassStructure(Offset + 2); dumpLastUses(MP, Offset+1); @@ -366,7 +399,7 @@ return PMT_ModulePassManager; } - private: +private: /// Collection of on the fly FPPassManagers. These managers manage /// function passes that are required by module passes. std::map OnTheFlyManagers; @@ -394,8 +427,8 @@ PMTopLevelManager(new MPPassManager()) {} /// \copydoc PassManager::add() - void add(Pass *P) { - schedulePass(P); + void add(Pass *P) { + schedulePass(P); } /// createPrinterPass - Get a module printer pass. @@ -410,7 +443,7 @@ using llvm::Pass::doInitialization; using llvm::Pass::doFinalization; - + /// Pass Manager itself does not invalidate any analysis info. void getAnalysisUsage(AnalysisUsage &Info) const override { Info.setPreservesAll(); @@ -467,8 +500,8 @@ static void createTheTimeInfo(); // print - Prints out timing information and then resets the timers. - void print() { - TG.print(*CreateInfoOutputFile()); + void print() { + TG.print(*CreateInfoOutputFile()); } /// getPassTimer - Return the timer for the specified pass if it exists. @@ -554,7 +587,7 @@ void PMTopLevelManager::collectLastUses(SmallVectorImpl &LastUses, Pass *P) { DenseMap >::iterator DMI = - InversedLastUser.find(P); + InversedLastUser.find(P); if (DMI == InversedLastUser.end()) return; @@ -579,7 +612,7 @@ // of dependencies. AnalysisUsage AU; P->getAnalysisUsage(AU); - + AUFoldingSetNode* Node = nullptr; FoldingSetNodeID ID; AUFoldingSetNode::Profile(ID, AU); @@ -873,7 +906,7 @@ const AnalysisUsage::VectorType &PreservedSet = AnUsage->getPreservedSet(); for (DenseMap::iterator I = AvailableAnalysis.begin(), - E = AvailableAnalysis.end(); I != E; ) { + E = AvailableAnalysis.end(); I != E; ) { DenseMap::iterator Info = I++; if (Info->second->getAsImmutablePass() == nullptr && !is_contained(PreservedSet, Info->first)) { @@ -895,8 +928,8 @@ continue; for (DenseMap::iterator - I = InheritedAnalysis[Index]->begin(), - E = InheritedAnalysis[Index]->end(); I != E; ) { + I = InheritedAnalysis[Index]->begin(), + E = InheritedAnalysis[Index]->end(); I != E; ) { DenseMap::iterator Info = I++; if (Info->second->getAsImmutablePass() == nullptr && !is_contained(PreservedSet, Info->first)) { @@ -956,7 +989,7 @@ const std::vector &II = PInf->getInterfacesImplemented(); for (unsigned i = 0, e = II.size(); i != e; ++i) { DenseMap::iterator Pos = - AvailableAnalysis.find(II[i]->getTypeInfo()); + AvailableAnalysis.find(II[i]->getTypeInfo()); if (Pos != AvailableAnalysis.end() && Pos->second == P) AvailableAnalysis.erase(Pos); } @@ -1120,16 +1153,16 @@ for (Pass *P : PassVector) { if (PMDataManager *PMD = P->getAsPMDataManager()) PMD->dumpPassArguments(); - else - if (const PassInfo *PI = + else + if (const PassInfo *PI = TPM->findAnalysisPassInfo(P->getPassID())) - if (!PI->isAnalysisGroup()) - dbgs() << " -" << PI->getPassArgument(); + if (!PI->isAnalysisGroup()) + dbgs() << " -" << PI->getPassArgument(); } } void PMDataManager::dumpPassInfo(Pass *P, enum PassDebuggingString S1, - enum PassDebuggingString S2, + enum PassDebuggingString S2, StringRef Msg) { if (PassDebugging < Executions) return; @@ -1278,6 +1311,7 @@ return false; bool Changed = doInitialization(F); + Module &M = *F.getParent(); for (BasicBlock &BB : F) for (unsigned Index = 0; Index < getNumContainedPasses(); ++Index) { @@ -1294,7 +1328,10 @@ PassManagerPrettyStackEntry X(BP, BB); TimeRegion PassTimer(getPassTimer(BP)); + int OriginalCount = getModuleInstrCount(M); LocalChanged |= BP->runOnBasicBlock(BB); + int FinalCount = getModuleInstrCount(M); + emitIRSizeChangedRemark(BP, M, OriginalCount, FinalCount); } Changed |= LocalChanged; @@ -1368,12 +1405,12 @@ FPM->setResolver(AR); } -FunctionPassManager::~FunctionPassManager() { - delete FPM; +FunctionPassManager::~FunctionPassManager() { + delete FPM; } -void FunctionPassManager::add(Pass *P) { - FPM->add(P); +void FunctionPassManager::add(Pass *P) { + FPM->add(P); } /// run - Execute all of the passes scheduled for execution. Keep @@ -1396,8 +1433,8 @@ /// doFinalization - Run all of the finalizers for the function passes. /// -bool FunctionPassManager::doFinalization() { - return FPM->doFinalization(*M); +bool FunctionPassManager::doFinalization() { + return FPM->doFinalization(*M); } //===----------------------------------------------------------------------===// @@ -1432,12 +1469,12 @@ /// cleanup - After running all passes, clean up pass manager cache. void FPPassManager::cleanup() { - for (unsigned Index = 0; Index < getNumContainedPasses(); ++Index) { + for (unsigned Index = 0; Index < getNumContainedPasses(); ++Index) { FunctionPass *FP = getContainedPass(Index); AnalysisResolver *AR = FP->getResolver(); assert(AR && "Analysis Resolver is not set"); AR->clearAnalysisImpls(); - } + } } void FunctionPassManagerImpl::releaseMemoryOnTheFly() { @@ -1494,6 +1531,7 @@ return false; bool Changed = false; + Module &M = *(F.getParent()); // Collect inherited analysis from Module level pass manager. populateInheritedAnalysis(TPM->activeStack); @@ -1510,8 +1548,10 @@ { PassManagerPrettyStackEntry X(FP, F); TimeRegion PassTimer(getPassTimer(FP)); - + int OriginalCount = getModuleInstrCount(M); LocalChanged |= FP->runOnFunction(F); + int FinalCount = getModuleInstrCount(*F.getParent()); + emitIRSizeChangedRemark(FP, *F.getParent(), OriginalCount, FinalCount); } Changed |= LocalChanged; @@ -1588,11 +1628,14 @@ PassManagerPrettyStackEntry X(MP, M); TimeRegion PassTimer(getPassTimer(MP)); + int OriginalCount = getModuleInstrCount(M); LocalChanged |= MP->runOnModule(M); + int FinalCount = getModuleInstrCount(M); + emitIRSizeChangedRemark(MP, M, OriginalCount, FinalCount); } Changed |= LocalChanged; - if (LocalChanged) + if (LocalChanged) dumpPassInfo(MP, MODIFICATION_MSG, ON_MODULE_MSG, M.getModuleIdentifier()); dumpPreservedSet(MP); @@ -1646,7 +1689,7 @@ Pass *FoundPass = nullptr; if (RequiredPassPI && RequiredPassPI->isAnalysis()) { FoundPass = - ((PMTopLevelManager*)FPP)->findAnalysisPass(RequiredPass->getPassID()); + ((PMTopLevelManager*)FPP)->findAnalysisPass(RequiredPass->getPassID()); } if (!FoundPass) { FoundPass = RequiredPass; @@ -1902,4 +1945,4 @@ BBP->add(this); } -PassManagerBase::~PassManagerBase() {} +PassManagerBase::~PassManagerBase() {} \ No newline at end of file Index: test/Other/size-remarks.ll =================================================================== --- /dev/null +++ test/Other/size-remarks.ll @@ -0,0 +1,42 @@ +; RUN: opt < %s -inline -pass-remarks-analysis='size-info' -S 2>&1 \ +; RUN: | FileCheck %s +; CHECK: remark: :0:0: Function Integration/Inlining: +; CHECK-SAME: IR instruction count changed from 15 to 29; Delta: 14 +; RUN: opt < %s -inline -pass-remarks-analysis='size-info' -S \ +; RUN: -pass-remarks-output=%t.yaml -o /dev/null +; RUN: cat %t.yaml | FileCheck %s -check-prefix=YAML +; YAML: --- !Analysis +; YAML-NEXT: Pass: size-info +; YAML-NEXT: Name: IRSizeChange +; YAML-NEXT: Function: foo +; YAML-NEXT: Args: +; YAML-NEXT: - Pass: Function Integration/Inlining +; YAML-NEXT: - String: ': IR instruction count changed from ' +; YAML-NEXT: - IRInstrsBefore: '15' +; YAML-NEXT: - String: ' to ' +; YAML-NEXT: - IRInstrsAfter: '29' +; YAML-NEXT: - String: '; Delta: ' +; YAML-NEXT: - DeltaInstrCount: '14' + +define i32 @foo(i32 %x, i32 %y) #0 { +entry: + %x.addr = alloca i32, align 4 + %y.addr = alloca i32, align 4 + store i32 %x, i32* %x.addr, align 4 + store i32 %y, i32* %y.addr, align 4 + %0 = load i32, i32* %x.addr, align 4 + %1 = load i32, i32* %y.addr, align 4 + %add = add nsw i32 %0, %1 + ret i32 %add +} + +define i32 @bar(i32 %j) #0 { +entry: + %j.addr = alloca i32, align 4 + store i32 %j, i32* %j.addr, align 4 + %0 = load i32, i32* %j.addr, align 4 + %1 = load i32, i32* %j.addr, align 4 + %sub = sub nsw i32 %1, 2 + %call = call i32 @foo(i32 %0, i32 %sub) + ret i32 %call +} \ No newline at end of file