summaryrefslogtreecommitdiff
path: root/lib/IR/LegacyPassManager.cpp
diff options
context:
space:
mode:
authorJessica Paquette <jpaquette@apple.com>2018-05-18 17:26:39 +0000
committerJessica Paquette <jpaquette@apple.com>2018-05-18 17:26:39 +0000
commit849da555d2214bed1645f02fc5cde199c7e69bde (patch)
tree32a12212946893a4bff1d7d59a5b854dde6d11b4 /lib/IR/LegacyPassManager.cpp
parent1c0183accbe8cea0fcb9aa1ca9ac6b854fac36ba (diff)
Add remarks describing when a pass changes the IR instruction count of a module
This patch adds a remark which tells the user when a pass changes the number of IR instructions in a module. It can be enabled by using -Rpass-analysis=size-info. The point of this is to make it easier to collect statistics on how passes modify programs in terms of code size. This is similar in concept to timing reports, but using a remark-based interface makes it easy to diff changes over multiple compilations of the same program. By adding functionality like this, we can see * Which passes impact code size the most * How passes impact code size at different optimization levels * Which pass might have contributed the most to an overall code size regression The patch lives in the legacy pass manager, but since it's simply emitting remarks, it shouldn't be too difficult to adapt the functionality to the new pass manager as well. This can also be adapted to handle MachineInstr counts in code gen passes. https://reviews.llvm.org/D38768 git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@332739 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/IR/LegacyPassManager.cpp')
-rw-r--r--lib/IR/LegacyPassManager.cpp69
1 files changed, 66 insertions, 3 deletions
diff --git a/lib/IR/LegacyPassManager.cpp b/lib/IR/LegacyPassManager.cpp
index c13e710dd3b..74481b0e501 100644
--- a/lib/IR/LegacyPassManager.cpp
+++ b/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"
@@ -134,8 +135,65 @@ bool PMDataManager::isPassDebuggingExecutionsOrMore() const {
return PassDebugging >= Executions;
}
+unsigned PMDataManager::initSizeRemarkInfo(Module &M) {
+ // Only calculate getInstructionCount if the size-info remark is requested.
+ if (M.getContext().getDiagHandlerPtr()->isAnalysisRemarkEnabled("size-info"))
+ return M.getInstructionCount();
+ return 0;
+}
+
+void PMDataManager::emitInstrCountChangedRemark(Pass *P, Module &M,
+ unsigned CountBefore) {
+ // Did the user request the remark? If not, quit.
+ if (!M.getContext().getDiagHandlerPtr()->isAnalysisRemarkEnabled("size-info"))
+ return;
+
+ // We need a function containing at least one basic block in order to output
+ // remarks. Since it's possible that the first function in the module doesn't
+ // actually contain a basic block, we have to go and find one that's suitable
+ // for emitting remarks.
+ auto It = std::find_if(M.begin(), M.end(),
+ [](const Function &Fn) { return !Fn.empty(); });
+ // Didn't find a function. Quit.
+ if (It == M.end())
+ return;
+
+ // We found a function containing at least one basic block.
+ Function *F = &*It;
+ // How many instructions are in the module now?
+ unsigned CountAfter = M.getInstructionCount();
+
+ // If there was no change, don't emit a remark.
+ if (CountBefore == CountAfter)
+ return;
+
+ // If it's a pass manager, don't emit a remark. (This hinges on the assumption
+ // that the only passes that return non-null with getAsPMDataManager are pass
+ // managers.) The reason we have to do this is to avoid emitting remarks for
+ // CGSCC passes.
+ if (P->getAsPMDataManager())
+ return;
+
+ // Compute a possibly negative delta between the instruction count before
+ // running P, and after running P.
+ int64_t Delta = (int64_t)CountAfter - (int64_t)CountBefore;
+
+ BasicBlock &BB = *F->begin();
+ OptimizationRemarkAnalysis R("size-info", "IRSizeChange",
+ DiagnosticLocation(), &BB);
+ // FIXME: Move ore namespace to DiagnosticInfo so that we can use it. This
+ // would let us use NV instead of DiagnosticInfoOptimizationBase::Argument.
+ R << DiagnosticInfoOptimizationBase::Argument("Pass", P->getPassName())
+ << ": IR instruction count changed from "
+ << DiagnosticInfoOptimizationBase::Argument("IRInstrsBefore", CountBefore)
+ << " to "
+ << DiagnosticInfoOptimizationBase::Argument("IRInstrsAfter", CountAfter)
+ << "; Delta: "
+ << DiagnosticInfoOptimizationBase::Argument("DeltaInstrCount", Delta);
+ F->getContext().diagnose(R); // Not using ORE for layering reasons.
+}
void PassManagerPrettyStackEntry::print(raw_ostream &OS) const {
if (!V && !M)
@@ -1284,6 +1342,7 @@ bool BBPassManager::runOnFunction(Function &F) {
return false;
bool Changed = doInitialization(F);
+ Module &M = *F.getParent();
for (BasicBlock &BB : F)
for (unsigned Index = 0; Index < getNumContainedPasses(); ++Index) {
@@ -1299,8 +1358,9 @@ bool BBPassManager::runOnFunction(Function &F) {
// If the pass crashes, remember this.
PassManagerPrettyStackEntry X(BP, BB);
TimeRegion PassTimer(getPassTimer(BP));
-
+ unsigned InstrCount = initSizeRemarkInfo(M);
LocalChanged |= BP->runOnBasicBlock(BB);
+ emitInstrCountChangedRemark(BP, M, InstrCount);
}
Changed |= LocalChanged;
@@ -1500,7 +1560,7 @@ bool FPPassManager::runOnFunction(Function &F) {
return false;
bool Changed = false;
-
+ Module &M = *F.getParent();
// Collect inherited analysis from Module level pass manager.
populateInheritedAnalysis(TPM->activeStack);
@@ -1516,8 +1576,9 @@ bool FPPassManager::runOnFunction(Function &F) {
{
PassManagerPrettyStackEntry X(FP, F);
TimeRegion PassTimer(getPassTimer(FP));
-
+ unsigned InstrCount = initSizeRemarkInfo(M);
LocalChanged |= FP->runOnFunction(F);
+ emitInstrCountChangedRemark(FP, M, InstrCount);
}
Changed |= LocalChanged;
@@ -1594,7 +1655,9 @@ MPPassManager::runOnModule(Module &M) {
PassManagerPrettyStackEntry X(MP, M);
TimeRegion PassTimer(getPassTimer(MP));
+ unsigned InstrCount = initSizeRemarkInfo(M);
LocalChanged |= MP->runOnModule(M);
+ emitInstrCountChangedRemark(MP, M, InstrCount);
}
Changed |= LocalChanged;