aboutsummaryrefslogtreecommitdiff
path: root/lib/Transforms/Instrumentation/GCOVProfiling.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'lib/Transforms/Instrumentation/GCOVProfiling.cpp')
-rw-r--r--lib/Transforms/Instrumentation/GCOVProfiling.cpp286
1 files changed, 139 insertions, 147 deletions
diff --git a/lib/Transforms/Instrumentation/GCOVProfiling.cpp b/lib/Transforms/Instrumentation/GCOVProfiling.cpp
index ffde7f8d9bae..b4070b602768 100644
--- a/lib/Transforms/Instrumentation/GCOVProfiling.cpp
+++ b/lib/Transforms/Instrumentation/GCOVProfiling.cpp
@@ -14,7 +14,6 @@
//
//===----------------------------------------------------------------------===//
-#include "llvm/Transforms/Instrumentation.h"
#include "llvm/ADT/DenseMap.h"
#include "llvm/ADT/Hashing.h"
#include "llvm/ADT/STLExtras.h"
@@ -35,6 +34,8 @@
#include "llvm/Support/FileSystem.h"
#include "llvm/Support/Path.h"
#include "llvm/Support/raw_ostream.h"
+#include "llvm/Transforms/GCOVProfiler.h"
+#include "llvm/Transforms/Instrumentation.h"
#include "llvm/Transforms/Utils/ModuleUtils.h"
#include <algorithm>
#include <memory>
@@ -68,86 +69,93 @@ GCOVOptions GCOVOptions::getDefault() {
}
namespace {
- class GCOVFunction;
+class GCOVFunction;
+
+class GCOVProfiler {
+public:
+ GCOVProfiler() : GCOVProfiler(GCOVOptions::getDefault()) {}
+ GCOVProfiler(const GCOVOptions &Opts) : Options(Opts) {
+ assert((Options.EmitNotes || Options.EmitData) &&
+ "GCOVProfiler asked to do nothing?");
+ ReversedVersion[0] = Options.Version[3];
+ ReversedVersion[1] = Options.Version[2];
+ ReversedVersion[2] = Options.Version[1];
+ ReversedVersion[3] = Options.Version[0];
+ ReversedVersion[4] = '\0';
+ }
+ bool runOnModule(Module &M);
+
+private:
+ // Create the .gcno files for the Module based on DebugInfo.
+ void emitProfileNotes();
+
+ // Modify the program to track transitions along edges and call into the
+ // profiling runtime to emit .gcda files when run.
+ bool emitProfileArcs();
+
+ // Get pointers to the functions in the runtime library.
+ Constant *getStartFileFunc();
+ Constant *getIncrementIndirectCounterFunc();
+ Constant *getEmitFunctionFunc();
+ Constant *getEmitArcsFunc();
+ Constant *getSummaryInfoFunc();
+ Constant *getEndFileFunc();
+
+ // Create or retrieve an i32 state value that is used to represent the
+ // pred block number for certain non-trivial edges.
+ GlobalVariable *getEdgeStateValue();
+
+ // Produce a table of pointers to counters, by predecessor and successor
+ // block number.
+ GlobalVariable *buildEdgeLookupTable(Function *F, GlobalVariable *Counter,
+ const UniqueVector<BasicBlock *> &Preds,
+ const UniqueVector<BasicBlock *> &Succs);
+
+ // Add the function to write out all our counters to the global destructor
+ // list.
+ Function *
+ insertCounterWriteout(ArrayRef<std::pair<GlobalVariable *, MDNode *>>);
+ Function *insertFlush(ArrayRef<std::pair<GlobalVariable *, MDNode *>>);
+ void insertIndirectCounterIncrement();
+
+ std::string mangleName(const DICompileUnit *CU, const char *NewStem);
- class GCOVProfiler : public ModulePass {
- public:
- static char ID;
- GCOVProfiler() : GCOVProfiler(GCOVOptions::getDefault()) {}
- GCOVProfiler(const GCOVOptions &Opts) : ModulePass(ID), Options(Opts) {
- assert((Options.EmitNotes || Options.EmitData) &&
- "GCOVProfiler asked to do nothing?");
- ReversedVersion[0] = Options.Version[3];
- ReversedVersion[1] = Options.Version[2];
- ReversedVersion[2] = Options.Version[1];
- ReversedVersion[3] = Options.Version[0];
- ReversedVersion[4] = '\0';
- initializeGCOVProfilerPass(*PassRegistry::getPassRegistry());
- }
- const char *getPassName() const override {
- return "GCOV Profiler";
- }
+ GCOVOptions Options;
- private:
- bool runOnModule(Module &M) override;
-
- // Create the .gcno files for the Module based on DebugInfo.
- void emitProfileNotes();
-
- // Modify the program to track transitions along edges and call into the
- // profiling runtime to emit .gcda files when run.
- bool emitProfileArcs();
-
- // Get pointers to the functions in the runtime library.
- Constant *getStartFileFunc();
- Constant *getIncrementIndirectCounterFunc();
- Constant *getEmitFunctionFunc();
- Constant *getEmitArcsFunc();
- Constant *getSummaryInfoFunc();
- Constant *getDeleteWriteoutFunctionListFunc();
- Constant *getDeleteFlushFunctionListFunc();
- Constant *getEndFileFunc();
-
- // Create or retrieve an i32 state value that is used to represent the
- // pred block number for certain non-trivial edges.
- GlobalVariable *getEdgeStateValue();
-
- // Produce a table of pointers to counters, by predecessor and successor
- // block number.
- GlobalVariable *buildEdgeLookupTable(Function *F,
- GlobalVariable *Counter,
- const UniqueVector<BasicBlock *>&Preds,
- const UniqueVector<BasicBlock*>&Succs);
-
- // Add the function to write out all our counters to the global destructor
- // list.
- Function *insertCounterWriteout(ArrayRef<std::pair<GlobalVariable*,
- MDNode*> >);
- Function *insertFlush(ArrayRef<std::pair<GlobalVariable*, MDNode*> >);
- void insertIndirectCounterIncrement();
-
- std::string mangleName(const DICompileUnit *CU, const char *NewStem);
-
- GCOVOptions Options;
-
- // Reversed, NUL-terminated copy of Options.Version.
- char ReversedVersion[5];
- // Checksum, produced by hash of EdgeDestinations
- SmallVector<uint32_t, 4> FileChecksums;
-
- Module *M;
- LLVMContext *Ctx;
- SmallVector<std::unique_ptr<GCOVFunction>, 16> Funcs;
- DenseMap<DISubprogram *, Function *> FnMap;
- };
+ // Reversed, NUL-terminated copy of Options.Version.
+ char ReversedVersion[5];
+ // Checksum, produced by hash of EdgeDestinations
+ SmallVector<uint32_t, 4> FileChecksums;
+
+ Module *M;
+ LLVMContext *Ctx;
+ SmallVector<std::unique_ptr<GCOVFunction>, 16> Funcs;
+};
+
+class GCOVProfilerLegacyPass : public ModulePass {
+public:
+ static char ID;
+ GCOVProfilerLegacyPass()
+ : GCOVProfilerLegacyPass(GCOVOptions::getDefault()) {}
+ GCOVProfilerLegacyPass(const GCOVOptions &Opts)
+ : ModulePass(ID), Profiler(Opts) {
+ initializeGCOVProfilerLegacyPassPass(*PassRegistry::getPassRegistry());
+ }
+ const char *getPassName() const override { return "GCOV Profiler"; }
+
+ bool runOnModule(Module &M) override { return Profiler.runOnModule(M); }
+
+private:
+ GCOVProfiler Profiler;
+};
}
-char GCOVProfiler::ID = 0;
-INITIALIZE_PASS(GCOVProfiler, "insert-gcov-profiling",
+char GCOVProfilerLegacyPass::ID = 0;
+INITIALIZE_PASS(GCOVProfilerLegacyPass, "insert-gcov-profiling",
"Insert instrumentation for GCOV profiling", false, false)
ModulePass *llvm::createGCOVProfilerPass(const GCOVOptions &Options) {
- return new GCOVProfiler(Options);
+ return new GCOVProfilerLegacyPass(Options);
}
static StringRef getFunctionName(const DISubprogram *SP) {
@@ -257,10 +265,9 @@ namespace {
void writeOut() {
uint32_t Len = 3;
SmallVector<StringMapEntry<GCOVLines *> *, 32> SortedLinesByFile;
- for (StringMap<GCOVLines *>::iterator I = LinesByFile.begin(),
- E = LinesByFile.end(); I != E; ++I) {
- Len += I->second->length();
- SortedLinesByFile.push_back(&*I);
+ for (auto &I : LinesByFile) {
+ Len += I.second->length();
+ SortedLinesByFile.push_back(&I);
}
writeBytes(LinesTag, 4);
@@ -272,10 +279,8 @@ namespace {
StringMapEntry<GCOVLines *> *RHS) {
return LHS->getKey() < RHS->getKey();
});
- for (SmallVectorImpl<StringMapEntry<GCOVLines *> *>::iterator
- I = SortedLinesByFile.begin(), E = SortedLinesByFile.end();
- I != E; ++I)
- (*I)->getValue()->writeOut();
+ for (auto &I : SortedLinesByFile)
+ I->getValue()->writeOut();
write(0);
write(0);
}
@@ -450,28 +455,32 @@ bool GCOVProfiler::runOnModule(Module &M) {
this->M = &M;
Ctx = &M.getContext();
- FnMap.clear();
- for (Function &F : M) {
- if (DISubprogram *SP = F.getSubprogram())
- FnMap[SP] = &F;
- }
-
if (Options.EmitNotes) emitProfileNotes();
if (Options.EmitData) return emitProfileArcs();
return false;
}
-static bool functionHasLines(Function *F) {
+PreservedAnalyses GCOVProfilerPass::run(Module &M,
+ AnalysisManager<Module> &AM) {
+
+ GCOVProfiler Profiler(GCOVOpts);
+
+ if (!Profiler.runOnModule(M))
+ return PreservedAnalyses::all();
+
+ return PreservedAnalyses::none();
+}
+
+static bool functionHasLines(Function &F) {
// Check whether this function actually has any source lines. Not only
// do these waste space, they also can crash gcov.
- for (Function::iterator BB = F->begin(), E = F->end(); BB != E; ++BB) {
- for (BasicBlock::iterator I = BB->begin(), IE = BB->end();
- I != IE; ++I) {
+ for (auto &BB : F) {
+ for (auto &I : BB) {
// Debug intrinsic locations correspond to the location of the
// declaration, not necessarily any statements or expressions.
- if (isa<DbgInfoIntrinsic>(I)) continue;
+ if (isa<DbgInfoIntrinsic>(&I)) continue;
- const DebugLoc &Loc = I->getDebugLoc();
+ const DebugLoc &Loc = I.getDebugLoc();
if (!Loc)
continue;
@@ -504,27 +513,27 @@ void GCOVProfiler::emitProfileNotes() {
std::string EdgeDestinations;
unsigned FunctionIdent = 0;
- for (auto *SP : CU->getSubprograms()) {
- Function *F = FnMap[SP];
- if (!F) continue;
+ for (auto &F : M->functions()) {
+ DISubprogram *SP = F.getSubprogram();
+ if (!SP) continue;
if (!functionHasLines(F)) continue;
// gcov expects every function to start with an entry block that has a
// single successor, so split the entry block to make sure of that.
- BasicBlock &EntryBlock = F->getEntryBlock();
+ BasicBlock &EntryBlock = F.getEntryBlock();
BasicBlock::iterator It = EntryBlock.begin();
while (isa<AllocaInst>(*It) || isa<DbgInfoIntrinsic>(*It))
++It;
EntryBlock.splitBasicBlock(It);
- Funcs.push_back(make_unique<GCOVFunction>(SP, F, &out, FunctionIdent++,
+ Funcs.push_back(make_unique<GCOVFunction>(SP, &F, &out, FunctionIdent++,
Options.UseCfgChecksum,
Options.ExitBlockBeforeBody));
GCOVFunction &Func = *Funcs.back();
- for (Function::iterator BB = F->begin(), E = F->end(); BB != E; ++BB) {
- GCOVBlock &Block = Func.getBlock(&*BB);
- TerminatorInst *TI = BB->getTerminator();
+ for (auto &BB : F) {
+ GCOVBlock &Block = Func.getBlock(&BB);
+ TerminatorInst *TI = BB.getTerminator();
if (int successors = TI->getNumSuccessors()) {
for (int i = 0; i != successors; ++i) {
Block.addEdge(Func.getBlock(TI->getSuccessor(i)));
@@ -534,13 +543,12 @@ void GCOVProfiler::emitProfileNotes() {
}
uint32_t Line = 0;
- for (BasicBlock::iterator I = BB->begin(), IE = BB->end();
- I != IE; ++I) {
+ for (auto &I : BB) {
// Debug intrinsic locations correspond to the location of the
// declaration, not necessarily any statements or expressions.
- if (isa<DbgInfoIntrinsic>(I)) continue;
+ if (isa<DbgInfoIntrinsic>(&I)) continue;
- const DebugLoc &Loc = I->getDebugLoc();
+ const DebugLoc &Loc = I.getDebugLoc();
if (!Loc)
continue;
@@ -581,16 +589,15 @@ bool GCOVProfiler::emitProfileArcs() {
bool Result = false;
bool InsertIndCounterIncrCode = false;
for (unsigned i = 0, e = CU_Nodes->getNumOperands(); i != e; ++i) {
- auto *CU = cast<DICompileUnit>(CU_Nodes->getOperand(i));
SmallVector<std::pair<GlobalVariable *, MDNode *>, 8> CountersBySP;
- for (auto *SP : CU->getSubprograms()) {
- Function *F = FnMap[SP];
- if (!F) continue;
+ for (auto &F : M->functions()) {
+ DISubprogram *SP = F.getSubprogram();
+ if (!SP) continue;
if (!functionHasLines(F)) continue;
if (!Result) Result = true;
unsigned Edges = 0;
- for (Function::iterator BB = F->begin(), E = F->end(); BB != E; ++BB) {
- TerminatorInst *TI = BB->getTerminator();
+ for (auto &BB : F) {
+ TerminatorInst *TI = BB.getTerminator();
if (isa<ReturnInst>(TI))
++Edges;
else
@@ -610,12 +617,12 @@ bool GCOVProfiler::emitProfileArcs() {
UniqueVector<BasicBlock *> ComplexEdgeSuccs;
unsigned Edge = 0;
- for (Function::iterator BB = F->begin(), E = F->end(); BB != E; ++BB) {
- TerminatorInst *TI = BB->getTerminator();
+ for (auto &BB : F) {
+ TerminatorInst *TI = BB.getTerminator();
int Successors = isa<ReturnInst>(TI) ? 1 : TI->getNumSuccessors();
if (Successors) {
if (Successors == 1) {
- IRBuilder<> Builder(&*BB->getFirstInsertionPt());
+ IRBuilder<> Builder(&*BB.getFirstInsertionPt());
Value *Counter = Builder.CreateConstInBoundsGEP2_64(Counters, 0,
Edge);
Value *Count = Builder.CreateLoad(Counter);
@@ -626,16 +633,13 @@ bool GCOVProfiler::emitProfileArcs() {
Value *Sel = Builder.CreateSelect(BI->getCondition(),
Builder.getInt64(Edge),
Builder.getInt64(Edge + 1));
- SmallVector<Value *, 2> Idx;
- Idx.push_back(Builder.getInt64(0));
- Idx.push_back(Sel);
- Value *Counter = Builder.CreateInBoundsGEP(Counters->getValueType(),
- Counters, Idx);
+ Value *Counter = Builder.CreateInBoundsGEP(
+ Counters->getValueType(), Counters, {Builder.getInt64(0), Sel});
Value *Count = Builder.CreateLoad(Counter);
Count = Builder.CreateAdd(Count, Builder.getInt64(1));
Builder.CreateStore(Count, Counter);
} else {
- ComplexEdgePreds.insert(&*BB);
+ ComplexEdgePreds.insert(&BB);
for (int i = 0; i != Successors; ++i)
ComplexEdgeSuccs.insert(TI->getSuccessor(i));
}
@@ -646,7 +650,7 @@ bool GCOVProfiler::emitProfileArcs() {
if (!ComplexEdgePreds.empty()) {
GlobalVariable *EdgeTable =
- buildEdgeLookupTable(F, Counters,
+ buildEdgeLookupTable(&F, Counters,
ComplexEdgePreds, ComplexEdgeSuccs);
GlobalVariable *EdgeState = getEdgeStateValue();
@@ -679,7 +683,7 @@ bool GCOVProfiler::emitProfileArcs() {
FunctionType *FTy = FunctionType::get(Type::getVoidTy(*Ctx), false);
Function *F = Function::Create(FTy, GlobalValue::InternalLinkage,
"__llvm_gcov_init", M);
- F->setUnnamedAddr(true);
+ F->setUnnamedAddr(GlobalValue::UnnamedAddr::Global);
F->setLinkage(GlobalValue::InternalLinkage);
F->addFnAttr(Attribute::NoInline);
if (Options.NoRedZone)
@@ -732,8 +736,8 @@ GlobalVariable *GCOVProfiler::buildEdgeLookupTable(
EdgeTable[i] = NullValue;
unsigned Edge = 0;
- for (Function::iterator BB = F->begin(), E = F->end(); BB != E; ++BB) {
- TerminatorInst *TI = BB->getTerminator();
+ for (BasicBlock &BB : *F) {
+ TerminatorInst *TI = BB.getTerminator();
int Successors = isa<ReturnInst>(TI) ? 1 : TI->getNumSuccessors();
if (Successors > 1 && !isa<BranchInst>(TI) && !isa<ReturnInst>(TI)) {
for (int i = 0; i != Successors; ++i) {
@@ -742,7 +746,7 @@ GlobalVariable *GCOVProfiler::buildEdgeLookupTable(
Value *Counter = Builder.CreateConstInBoundsGEP2_64(Counters, 0,
Edge + i);
EdgeTable[((Succs.idFor(Succ) - 1) * Preds.size()) +
- (Preds.idFor(&*BB) - 1)] = cast<Constant>(Counter);
+ (Preds.idFor(&BB) - 1)] = cast<Constant>(Counter);
}
}
Edge += Successors;
@@ -754,7 +758,7 @@ GlobalVariable *GCOVProfiler::buildEdgeLookupTable(
ConstantArray::get(EdgeTableTy,
makeArrayRef(&EdgeTable[0],TableSize)),
"__llvm_gcda_edge_table");
- EdgeTableGV->setUnnamedAddr(true);
+ EdgeTableGV->setUnnamedAddr(GlobalValue::UnnamedAddr::Global);
return EdgeTableGV;
}
@@ -805,16 +809,6 @@ Constant *GCOVProfiler::getSummaryInfoFunc() {
return M->getOrInsertFunction("llvm_gcda_summary_info", FTy);
}
-Constant *GCOVProfiler::getDeleteWriteoutFunctionListFunc() {
- FunctionType *FTy = FunctionType::get(Type::getVoidTy(*Ctx), false);
- return M->getOrInsertFunction("llvm_delete_writeout_function_list", FTy);
-}
-
-Constant *GCOVProfiler::getDeleteFlushFunctionListFunc() {
- FunctionType *FTy = FunctionType::get(Type::getVoidTy(*Ctx), false);
- return M->getOrInsertFunction("llvm_delete_flush_function_list", FTy);
-}
-
Constant *GCOVProfiler::getEndFileFunc() {
FunctionType *FTy = FunctionType::get(Type::getVoidTy(*Ctx), false);
return M->getOrInsertFunction("llvm_gcda_end_file", FTy);
@@ -828,7 +822,7 @@ GlobalVariable *GCOVProfiler::getEdgeStateValue() {
ConstantInt::get(Type::getInt32Ty(*Ctx),
0xffffffff),
"__llvm_gcov_global_state_pred");
- GV->setUnnamedAddr(true);
+ GV->setUnnamedAddr(GlobalValue::UnnamedAddr::Global);
}
return GV;
}
@@ -840,7 +834,7 @@ Function *GCOVProfiler::insertCounterWriteout(
if (!WriteoutF)
WriteoutF = Function::Create(WriteoutFTy, GlobalValue::InternalLinkage,
"__llvm_gcov_writeout", M);
- WriteoutF->setUnnamedAddr(true);
+ WriteoutF->setUnnamedAddr(GlobalValue::UnnamedAddr::Global);
WriteoutF->addFnAttr(Attribute::NoInline);
if (Options.NoRedZone)
WriteoutF->addFnAttr(Attribute::NoRedZone);
@@ -884,7 +878,7 @@ Function *GCOVProfiler::insertCounterWriteout(
GlobalVariable *GV = CountersBySP[j].first;
unsigned Arcs =
- cast<ArrayType>(GV->getType()->getElementType())->getNumElements();
+ cast<ArrayType>(GV->getValueType())->getNumElements();
Builder.CreateCall(EmitArcs, {Builder.getInt32(Arcs),
Builder.CreateConstGEP2_64(GV, 0, 0)});
}
@@ -900,7 +894,7 @@ Function *GCOVProfiler::insertCounterWriteout(
void GCOVProfiler::insertIndirectCounterIncrement() {
Function *Fn =
cast<Function>(GCOVProfiler::getIncrementIndirectCounterFunc());
- Fn->setUnnamedAddr(true);
+ Fn->setUnnamedAddr(GlobalValue::UnnamedAddr::Global);
Fn->setLinkage(GlobalValue::InternalLinkage);
Fn->addFnAttr(Attribute::NoInline);
if (Options.NoRedZone)
@@ -957,7 +951,7 @@ insertFlush(ArrayRef<std::pair<GlobalVariable*, MDNode*> > CountersBySP) {
"__llvm_gcov_flush", M);
else
FlushF->setLinkage(GlobalValue::InternalLinkage);
- FlushF->setUnnamedAddr(true);
+ FlushF->setUnnamedAddr(GlobalValue::UnnamedAddr::Global);
FlushF->addFnAttr(Attribute::NoInline);
if (Options.NoRedZone)
FlushF->addFnAttr(Attribute::NoRedZone);
@@ -972,11 +966,9 @@ insertFlush(ArrayRef<std::pair<GlobalVariable*, MDNode*> > CountersBySP) {
Builder.CreateCall(WriteoutF, {});
// Zero out the counters.
- for (ArrayRef<std::pair<GlobalVariable *, MDNode *> >::iterator
- I = CountersBySP.begin(), E = CountersBySP.end();
- I != E; ++I) {
- GlobalVariable *GV = I->first;
- Constant *Null = Constant::getNullValue(GV->getType()->getElementType());
+ for (const auto &I : CountersBySP) {
+ GlobalVariable *GV = I.first;
+ Constant *Null = Constant::getNullValue(GV->getValueType());
Builder.CreateStore(Null, GV);
}