llvm.org GIT mirror llvm / b192870
Rename LineProfiling to GCOVProfiling to more accurately represent what it does. Also mostly implement it. Still a work-in-progress, but generates legal output on crafted test cases. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@129630 91177308-0d34-0410-b5e6-96231b3b80d8 Nick Lewycky 8 years ago
9 changed file(s) with 621 addition(s) and 265 deletion(s). Raw diff Collapse all Expand all
9393 void initializeEdgeBundlesPass(PassRegistry&);
9494 void initializeEdgeProfilerPass(PassRegistry&);
9595 void initializePathProfilerPass(PassRegistry&);
96 void initializeLineProfilerPass(PassRegistry&);
96 void initializeGCOVProfilerPass(PassRegistry&);
9797 void initializeEarlyCSEPass(PassRegistry&);
9898 void initializeExpandISelPseudosPass(PassRegistry&);
9999 void initializeFindUsedTypesPass(PassRegistry&);
6969 (void) llvm::createEdgeProfilerPass();
7070 (void) llvm::createOptimalEdgeProfilerPass();
7171 (void) llvm::createPathProfilerPass();
72 (void) llvm::createLineProfilerPass();
72 (void) llvm::createGCOVProfilerPass();
7373 (void) llvm::createFunctionInliningPass();
7474 (void) llvm::createAlwaysInlinerPass();
7575 (void) llvm::createGlobalDCEPass();
2626 // Insert path profiling instrumentation
2727 ModulePass *createPathProfilerPass();
2828
29 // Insert line profiling instrumentation
30 ModulePass *createLineProfilerPass();
29 // Insert GCOV profiling instrumentation
30 ModulePass *createGCOVProfilerPass();
3131
3232 } // End llvm namespace
3333
0 //===- GCOVProfiling.cpp - Insert edge counters for gcov profiling --------===//
1 //
2 // The LLVM Compiler Infrastructure
3 //
4 // This file is distributed under the University of Illinois Open Source
5 // License. See LICENSE.TXT for details.
6 //
7 //===----------------------------------------------------------------------===//
8 //
9 // This pass implements GCOV-style profiling. When this pass is run it emits
10 // "gcno" files next to the existing source, and instruments the code that runs
11 // to records the edges between blocks that run and emit a complementary "gcda"
12 // file on exit.
13 //
14 //===----------------------------------------------------------------------===//
15
16 #define DEBUG_TYPE "insert-gcov-profiling"
17
18 #include "ProfilingUtils.h"
19 #include "llvm/Transforms/Instrumentation.h"
20 #include "llvm/Analysis/DebugInfo.h"
21 #include "llvm/Module.h"
22 #include "llvm/Pass.h"
23 #include "llvm/Instructions.h"
24 #include "llvm/Support/raw_ostream.h"
25 #include "llvm/Support/Debug.h"
26 #include "llvm/Support/DebugLoc.h"
27 #include "llvm/Support/InstIterator.h"
28 #include "llvm/Support/IRBuilder.h"
29 #include "llvm/Support/PathV2.h"
30 #include "llvm/ADT/DenseMap.h"
31 #include "llvm/ADT/Statistic.h"
32 #include "llvm/ADT/STLExtras.h"
33 #include "llvm/ADT/StringExtras.h"
34 #include "llvm/ADT/StringMap.h"
35 #include "llvm/ADT/UniqueVector.h"
36 #include
37 #include
38 using namespace llvm;
39
40 namespace {
41 class GCOVProfiler : public ModulePass {
42 bool runOnModule(Module &M);
43 public:
44 static char ID;
45 GCOVProfiler() : ModulePass(ID) {
46 initializeGCOVProfilerPass(*PassRegistry::getPassRegistry());
47 }
48 virtual const char *getPassName() const {
49 return "GCOV Profiler";
50 }
51
52 private:
53 // Create the GCNO files for the Module based on DebugInfo.
54 void EmitGCNO(DebugInfoFinder &DIF);
55
56 // Get pointers to the functions in the runtime library.
57 Constant *getStartFileFunc();
58 Constant *getEmitFunctionFunc();
59 Constant *getEmitArcsFunc();
60 Constant *getEndFileFunc();
61
62 // Add the function to write out all our counters to the global destructor
63 // list.
64 void InsertCounterWriteout(DebugInfoFinder &,
65 SmallVector
66 uint32_t>, 8> &);
67
68 Module *Mod;
69 LLVMContext *Ctx;
70 };
71 }
72
73 char GCOVProfiler::ID = 0;
74 INITIALIZE_PASS(GCOVProfiler, "insert-gcov-profiling",
75 "Insert instrumentation for GCOV profiling", false, false)
76
77 ModulePass *llvm::createGCOVProfilerPass() { return new GCOVProfiler(); }
78
79 static DISubprogram FindSubprogram(DIScope scope) {
80 while (!scope.isSubprogram()) {
81 assert(scope.isLexicalBlock() &&
82 "Debug location not lexical block or subprogram");
83 scope = DILexicalBlock(scope).getContext();
84 }
85 return DISubprogram(scope);
86 }
87
88 namespace {
89 class GCOVRecord {
90 protected:
91 static const char *lines_tag;
92 static const char *function_tag;
93 static const char *block_tag;
94 static const char *edge_tag;
95
96 GCOVRecord() {}
97
98 void WriteBytes(const char *b, int size) {
99 os->write(b, size);
100 }
101
102 void Write(uint32_t i) {
103 WriteBytes(reinterpret_cast(&i), 4);
104 }
105
106 // Returns the length measured in 4-byte blocks that will be used to
107 // represent this string in a GCOV file
108 unsigned LengthOfGCOVString(StringRef s) {
109 // A GCOV string is a length, followed by a NUL, then between 0 and 3 NULs
110 // padding out to the next 4-byte word. The length is measured in 4-byte words
111 // including padding, not bytes of actual string.
112 return (s.size() + 5) / 4;
113 }
114
115 void WriteGCOVString(StringRef s) {
116 uint32_t len = LengthOfGCOVString(s);
117 Write(len);
118 WriteBytes(s.data(), s.size());
119
120 // Write 1 to 4 bytes of NUL padding.
121 assert((unsigned)(5 - ((s.size() + 1) % 4)) > 0);
122 assert((unsigned)(5 - ((s.size() + 1) % 4)) <= 4);
123 WriteBytes("\0\0\0\0", 5 - ((s.size() + 1) % 4));
124 }
125
126 raw_ostream *os;
127 };
128 const char *GCOVRecord::lines_tag = "\0\0\x45\x01";
129 const char *GCOVRecord::function_tag = "\0\0\0\1";
130 const char *GCOVRecord::block_tag = "\0\0\x41\x01";
131 const char *GCOVRecord::edge_tag = "\0\0\x43\x01";
132
133 class GCOVFunction;
134 class GCOVBlock;
135
136 // Constructed only by requesting it from a GCOVBlock, this object stores a
137 // list of line numbers and a single filename, representing lines that belong
138 // to the block.
139 class GCOVLines : public GCOVRecord {
140 public:
141 void AddLine(uint32_t line) {
142 lines.push_back(line);
143 }
144
145 uint32_t Length() {
146 return LengthOfGCOVString(filename) + 2 + lines.size();
147 }
148
149 private:
150 friend class GCOVBlock;
151
152 GCOVLines(std::string filename, raw_ostream *os)
153 : filename(filename) {
154 this->os = os;
155 }
156
157 std::string filename;
158 SmallVector lines;
159 };
160
161 // Represent a basic block in GCOV. Each block has a unique number in the
162 // function, number of lines belonging to each block, and a set of edges to
163 // other blocks.
164 class GCOVBlock : public GCOVRecord {
165 public:
166 GCOVLines &GetFile(std::string filename) {
167 GCOVLines *&lines = lines_by_file[filename];
168 if (!lines) {
169 lines = new GCOVLines(filename, os);
170 }
171 return *lines;
172 }
173
174 void AddEdge(GCOVBlock &successor) {
175 out_edges.push_back(&successor);
176 }
177
178 void WriteOut() {
179 uint32_t len = 3;
180 for (StringMap::iterator I = lines_by_file.begin(),
181 E = lines_by_file.end(); I != E; ++I) {
182 len += I->second->Length();
183 }
184
185 WriteBytes(lines_tag, 4);
186 Write(len);
187 Write(number);
188 for (StringMap::iterator I = lines_by_file.begin(),
189 E = lines_by_file.end(); I != E; ++I) {
190 Write(0);
191 WriteGCOVString(I->second->filename);
192 for (int i = 0, e = I->second->lines.size(); i != e; ++i) {
193 Write(I->second->lines[i]);
194 }
195 }
196 Write(0);
197 Write(0);
198 }
199
200 ~GCOVBlock() {
201 DeleteContainerSeconds(lines_by_file);
202 }
203
204 private:
205 friend class GCOVFunction;
206
207 GCOVBlock(uint32_t number, raw_ostream *os)
208 : number(number) {
209 this->os = os;
210 }
211
212 uint32_t number;
213 BasicBlock *block;
214 StringMap lines_by_file;
215 SmallVector out_edges;
216 };
217
218 // A function has a unique identifier, a checksum (we leave as zero) and a
219 // set of blocks and a map of edges between blocks. This is the only GCOV
220 // object users can construct, the blocks and lines will be rooted here.
221 class GCOVFunction : public GCOVRecord {
222 public:
223 GCOVFunction(DISubprogram SP, raw_ostream *os) {
224 this->os = os;
225
226 Function *F = SP.getFunction();
227 uint32_t i = 0;
228 for (Function::iterator BB = F->begin(), E = F->end(); BB != E; ++BB) {
229 blocks[BB] = new GCOVBlock(i++, os);
230 }
231
232 WriteBytes(function_tag, 4);
233 uint32_t block_len = 1 + 1 + 1 + LengthOfGCOVString(SP.getName()) +
234 1 + LengthOfGCOVString(SP.getFilename()) + 1;
235 Write(block_len);
236 uint32_t ident = reinterpret_cast((MDNode*)SP);
237 Write(ident);
238 Write(0); // checksum
239 WriteGCOVString(SP.getName());
240 WriteGCOVString(SP.getFilename());
241 Write(SP.getLineNumber());
242 }
243
244 ~GCOVFunction() {
245 DeleteContainerSeconds(blocks);
246 }
247
248 GCOVBlock &GetBlock(BasicBlock *BB) {
249 return *blocks[BB];
250 }
251
252 void WriteOut() {
253 // Emit count of blocks.
254 WriteBytes(block_tag, 4);
255 Write(blocks.size());
256 for (int i = 0, e = blocks.size(); i != e; ++i) {
257 Write(0); // No flags on our blocks.
258 }
259
260 // Emit edges between blocks.
261 for (DenseMap::iterator I = blocks.begin(),
262 E = blocks.end(); I != E; ++I) {
263 GCOVBlock &block = *I->second;
264 if (block.out_edges.empty()) continue;
265
266 WriteBytes(edge_tag, 4);
267 Write(block.out_edges.size() * 2 + 1);
268 Write(block.number);
269 for (int i = 0, e = block.out_edges.size(); i != e; ++i) {
270 Write(block.out_edges[i]->number);
271 Write(0); // no flags
272 }
273 }
274
275 // Emit lines for each block.
276 for (DenseMap::iterator I = blocks.begin(),
277 E = blocks.end(); I != E; ++I) {
278 I->second->WriteOut();
279 }
280 }
281
282 private:
283 DenseMap blocks;
284 };
285 }
286
287 void GCOVProfiler::EmitGCNO(DebugInfoFinder &DIF) {
288 DenseMap gcno_files;
289 for (DebugInfoFinder::iterator I = DIF.compile_unit_begin(),
290 E = DIF.compile_unit_end(); I != E; ++I) {
291 // Each compile unit gets its own .gcno file. This means that whether we run
292 // this pass over the original .o's as they're produced, or run it after
293 // LTO, we'll generate the same .gcno files.
294
295 DICompileUnit CU(*I);
296 raw_fd_ostream *&Out = gcno_files[CU];
297 std::string ErrorInfo;
298 Out = new raw_fd_ostream(
299 (sys::path::stem(CU.getFilename()) + ".gcno").str().c_str(),
300 ErrorInfo, raw_fd_ostream::F_Binary);
301 Out->write("oncg*404MVLL", 12);
302 }
303
304 for (DebugInfoFinder::iterator SPI = DIF.subprogram_begin(),
305 SPE = DIF.subprogram_end(); SPI != SPE; ++SPI) {
306 DISubprogram SP(*SPI);
307 raw_fd_ostream *&os = gcno_files[SP.getCompileUnit()];
308
309 GCOVFunction function(SP, os);
310 Function *F = SP.getFunction();
311 for (Function::iterator BB = F->begin(), E = F->end(); BB != E; ++BB) {
312 GCOVBlock &block = function.GetBlock(BB);
313 TerminatorInst *TI = BB->getTerminator();
314 if (int successors = TI->getNumSuccessors()) {
315 for (int i = 0; i != successors; ++i) {
316 block.AddEdge(function.GetBlock(TI->getSuccessor(i)));
317 }
318 }
319
320 uint32_t line = 0;
321 for (BasicBlock::iterator I = BB->begin(), IE = BB->end(); I != IE; ++I) {
322 const DebugLoc &loc = I->getDebugLoc();
323 if (loc.isUnknown()) continue;
324 if (line == loc.getLine()) continue;
325 line = loc.getLine();
326 if (SP != FindSubprogram(DIScope(loc.getScope(*Ctx)))) continue;
327
328 GCOVLines &lines = block.GetFile(SP.getFilename());
329 lines.AddLine(loc.getLine());
330 }
331 }
332 function.WriteOut();
333 }
334
335 for (DenseMap::iterator
336 I = gcno_files.begin(), E = gcno_files.end(); I != E; ++I) {
337 raw_fd_ostream *&Out = I->second;
338 Out->write("\0\0\0\0\0\0\0\0", 4); // EOF
339 Out->close();
340 delete Out;
341 }
342 }
343
344 bool GCOVProfiler::runOnModule(Module &M) {
345 Mod = &M;
346 Ctx = &M.getContext();
347
348 DebugInfoFinder DIF;
349 DIF.processModule(*Mod);
350
351 EmitGCNO(DIF);
352
353 SmallVector, 8> counters_by_ident;
354 for (DebugInfoFinder::iterator SPI = DIF.subprogram_begin(),
355 SPE = DIF.subprogram_end(); SPI != SPE; ++SPI) {
356 DISubprogram SP(*SPI);
357 Function *F = SP.getFunction();
358
359 // TODO: GCOV format requires a distinct unified exit block.
360 unsigned edges = 0;
361 for (Function::iterator BB = F->begin(), E = F->end(); BB != E; ++BB) {
362 TerminatorInst *TI = BB->getTerminator();
363 edges += TI->getNumSuccessors();
364 }
365
366 const ArrayType *counter_type =
367 ArrayType::get(Type::getInt64Ty(*Ctx), edges);
368 GlobalVariable *counter =
369 new GlobalVariable(*Mod, counter_type, false,
370 GlobalValue::InternalLinkage,
371 Constant::getNullValue(counter_type),
372 "__llvm_gcov_ctr", 0, false, 0);
373 counters_by_ident.push_back(
374 std::make_pair(counter, reinterpret_cast((MDNode*)SP)));
375
376 UniqueVector complex_edge_preds;
377 UniqueVector complex_edge_succs;
378
379 unsigned edge_num = 0;
380 for (Function::iterator BB = F->begin(), E = F->end(); BB != E; ++BB) {
381 TerminatorInst *TI = BB->getTerminator();
382 if (int successors = TI->getNumSuccessors()) {
383 IRBuilder<> builder(TI);
384
385 if (successors == 1) {
386 Value *ctr = builder.CreateConstInBoundsGEP2_64(counter, 0, edge_num);
387 Value *count = builder.CreateLoad(ctr);
388 count = builder.CreateAdd(count,
389 ConstantInt::get(Type::getInt64Ty(*Ctx),1));
390 builder.CreateStore(count, ctr);
391 } else if (BranchInst *BI = dyn_cast(TI)) {
392 Value *sel = builder.CreateSelect(
393 BI->getCondition(),
394 ConstantInt::get(Type::getInt64Ty(*Ctx), edge_num),
395 ConstantInt::get(Type::getInt64Ty(*Ctx), edge_num + 1));
396 SmallVector idx;
397 idx.push_back(Constant::getNullValue(Type::getInt64Ty(*Ctx)));
398 idx.push_back(sel);
399 Value *ctr = builder.CreateInBoundsGEP(counter,
400 idx.begin(), idx.end());
401 Value *count = builder.CreateLoad(ctr);
402 count = builder.CreateAdd(count,
403 ConstantInt::get(Type::getInt64Ty(*Ctx),1));
404 builder.CreateStore(count, ctr);
405 } else {
406 complex_edge_preds.insert(BB);
407 for (int i = 0; i != successors; ++i) {
408 complex_edge_succs.insert(TI->getSuccessor(i));
409 }
410 }
411 edge_num += successors;
412 }
413 }
414
415 // TODO: support switch, invoke, indirectbr
416 if (!complex_edge_preds.empty()) {
417 // emit a [preds x [succs x i64*]].
418 for (int i = 0, e = complex_edge_preds.size(); i != e; ++i) {
419 // call runtime to state save
420 }
421 for (int i = 0, e = complex_edge_succs.size(); i != e; ++i) {
422 // call runtime to perform increment
423 }
424 }
425 }
426
427 InsertCounterWriteout(DIF, counters_by_ident);
428
429 return true;
430 }
431
432 Constant *GCOVProfiler::getStartFileFunc() {
433 const Type *Args[1] = { Type::getInt8PtrTy(*Ctx) };
434 const FunctionType *FTy = FunctionType::get(Type::getVoidTy(*Ctx),
435 Args, false);
436 return Mod->getOrInsertFunction("llvm_gcda_start_file", FTy);
437 }
438
439 Constant *GCOVProfiler::getEmitFunctionFunc() {
440 const Type *Args[1] = { Type::getInt32Ty(*Ctx) };
441 const FunctionType *FTy = FunctionType::get(Type::getVoidTy(*Ctx),
442 Args, false);
443 return Mod->getOrInsertFunction("llvm_gcda_emit_function", FTy);
444 }
445
446 Constant *GCOVProfiler::getEmitArcsFunc() {
447 const Type *Args[] = {
448 Type::getInt32Ty(*Ctx), // uint32_t num_counters
449 Type::getInt64PtrTy(*Ctx), // uint64_t *counters
450 };
451 const FunctionType *FTy = FunctionType::get(Type::getVoidTy(*Ctx),
452 Args, false);
453 return Mod->getOrInsertFunction("llvm_gcda_emit_arcs", FTy);
454 }
455
456 Constant *GCOVProfiler::getEndFileFunc() {
457 const FunctionType *FTy = FunctionType::get(Type::getVoidTy(*Ctx), false);
458 return Mod->getOrInsertFunction("llvm_gcda_end_file", FTy);
459 }
460
461 static std::string ReplaceStem(std::string orig_filename, std::string new_stem){
462 return (sys::path::stem(orig_filename) + "." + new_stem).str();
463 }
464
465 void GCOVProfiler::InsertCounterWriteout(
466 DebugInfoFinder &DIF,
467 SmallVector, 8> &counters_by_ident) {
468
469 const FunctionType *WriteoutFTy =
470 FunctionType::get(Type::getVoidTy(*Ctx), false);
471 Function *WriteoutF = Function::Create(WriteoutFTy,
472 GlobalValue::InternalLinkage,
473 "__llvm_gcda_writeout", Mod);
474 WriteoutF->setUnnamedAddr(true);
475 BasicBlock *BB = BasicBlock::Create(*Ctx, "", WriteoutF);
476 IRBuilder<> builder(BB);
477
478 Constant *StartFile = getStartFileFunc();
479 Constant *EmitFunction = getEmitFunctionFunc();
480 Constant *EmitArcs = getEmitArcsFunc();
481 Constant *EndFile = getEndFileFunc();
482
483 for (DebugInfoFinder::iterator CUI = DIF.compile_unit_begin(),
484 CUE = DIF.compile_unit_end(); CUI != CUE; ++CUI) {
485 DICompileUnit compile_unit(*CUI);
486 std::string filename_gcda = ReplaceStem(compile_unit.getFilename(), "gcda");
487 builder.CreateCall(StartFile,
488 builder.CreateGlobalStringPtr(filename_gcda));
489 for (SmallVector, 8>::iterator
490 I = counters_by_ident.begin(), E = counters_by_ident.end();
491 I != E; ++I) {
492 builder.CreateCall(EmitFunction, ConstantInt::get(Type::getInt32Ty(*Ctx),
493 I->second));
494 GlobalVariable *GV = I->first;
495 unsigned num_arcs =
496 cast(GV->getType()->getElementType())->getNumElements();
497 builder.CreateCall2(
498 EmitArcs,
499 ConstantInt::get(Type::getInt32Ty(*Ctx), num_arcs),
500 builder.CreateConstGEP2_64(GV, 0, 0));
501 }
502 builder.CreateCall(EndFile);
503 }
504 builder.CreateRetVoid();
505
506 InsertProfilingShutdownCall(WriteoutF, Mod);
507 }
2222 initializeEdgeProfilerPass(Registry);
2323 initializeOptimalEdgeProfilerPass(Registry);
2424 initializePathProfilerPass(Registry);
25 initializeLineProfilerPass(Registry);
25 initializeGCOVProfilerPass(Registry);
2626 }
2727
2828 /// LLVMInitializeInstrumentation - C binding for
+0
-217
lib/Transforms/Instrumentation/LineProfiling.cpp less more
None //===- LineProfiling.cpp - Insert counters for line profiling -------------===//
1 //
2 // The LLVM Compiler Infrastructure
3 //
4 // This file is distributed under the University of Illinois Open Source
5 // License. See LICENSE.TXT for details.
6 //
7 //===----------------------------------------------------------------------===//
8 //
9 // This pass creates counters for the number of times that the original source
10 // lines of code were executed.
11 //
12 // The lines are found from existing debug info in the LLVM IR. Iterating
13 // through LLVM instructions, every time the debug location changes we insert a
14 // new counter and instructions to increment the counter there. A global
15 // destructor runs to dump the counters out to a file.
16 //
17 //===----------------------------------------------------------------------===//
18
19 #define DEBUG_TYPE "insert-line-profiling"
20
21 #include "ProfilingUtils.h"
22 #include "llvm/Transforms/Instrumentation.h"
23 #include "llvm/Analysis/DebugInfo.h"
24 #include "llvm/Module.h"
25 #include "llvm/Pass.h"
26 #include "llvm/Instructions.h"
27 #include "llvm/Support/raw_ostream.h"
28 #include "llvm/Support/Debug.h"
29 #include "llvm/Support/DebugLoc.h"
30 #include "llvm/Support/InstIterator.h"
31 #include "llvm/Support/IRBuilder.h"
32 #include "llvm/ADT/DenseMap.h"
33 #include "llvm/ADT/Statistic.h"
34 #include "llvm/ADT/StringExtras.h"
35 #include
36 #include
37 using namespace llvm;
38
39 STATISTIC(NumUpdatesInserted, "The # of counter increments inserted.");
40
41 namespace {
42 class LineProfiler : public ModulePass {
43 bool runOnModule(Module &M);
44 public:
45 static char ID;
46 LineProfiler() : ModulePass(ID) {
47 initializeLineProfilerPass(*PassRegistry::getPassRegistry());
48 }
49 virtual const char *getPassName() const {
50 return "Line Profiler";
51 }
52
53 private:
54 // Get pointers to the functions in the runtime library.
55 Constant *getStartFileFunc();
56 Constant *getCounterFunc();
57 Constant *getEndFileFunc();
58
59 // Insert an increment of the counter before instruction I.
60 void InsertCounterUpdateBefore(Instruction *I);
61
62 // Add the function to write out all our counters to the global destructor
63 // list.
64 void InsertCounterWriteout();
65
66 // Mapping from the source location to the counter tracking that location.
67 DenseMap counters;
68
69 Module *Mod;
70 LLVMContext *Ctx;
71 };
72 }
73
74 char LineProfiler::ID = 0;
75 INITIALIZE_PASS(LineProfiler, "insert-line-profiling",
76 "Insert instrumentation for line profiling", false, false)
77
78 ModulePass *llvm::createLineProfilerPass() { return new LineProfiler(); }
79
80 bool LineProfiler::runOnModule(Module &M) {
81 Mod = &M;
82 Ctx = &M.getContext();
83
84 DebugLoc last_line; // initializes to unknown
85 bool Changed = false;
86 for (Module::iterator F = M.begin(), E = M.end(); F != E; ++F) {
87 for (inst_iterator II = inst_begin(F), IE = inst_end(F); II != IE; ++II) {
88 const DebugLoc &loc = II->getDebugLoc();
89 if (loc.isUnknown()) continue;
90 if (loc == last_line) continue;
91 last_line = loc;
92
93 InsertCounterUpdateBefore(&*II);
94 ++NumUpdatesInserted;
95 Changed = true;
96 }
97 }
98
99 if (Changed) {
100 InsertCounterWriteout();
101 }
102
103 return Changed;
104 }
105
106 void LineProfiler::InsertCounterUpdateBefore(Instruction *I) {
107 const DebugLoc &loc = I->getDebugLoc();
108 GlobalVariable *&counter = counters[loc];
109 const Type *Int64Ty = Type::getInt64Ty(*Ctx);
110 if (!counter) {
111 counter = new GlobalVariable(*Mod, Int64Ty, false,
112 GlobalValue::InternalLinkage,
113 Constant::getNullValue(Int64Ty),
114 "__llvm_prof_linecov_ctr", 0, false, 0);
115 counter->setVisibility(GlobalVariable::HiddenVisibility);
116 counter->setUnnamedAddr(true);
117 }
118
119 if (isa(I)) {
120 // We may not error out or crash in this case, because a module could put
121 // changing line numbers on phi nodes and still pass the verifier.
122 dbgs() << "Refusing to insert code before phi: " << *I << "\n";
123 I = I->getParent()->getFirstNonPHI();
124 }
125
126 IRBuilder<> builder(I);
127 Value *ctr = builder.CreateLoad(counter);
128 ctr = builder.CreateAdd(ctr, ConstantInt::get(Int64Ty, 1));
129 builder.CreateStore(ctr, counter);
130 }
131
132 static DISubprogram FindSubprogram(DIScope scope) {
133 while (!scope.isSubprogram()) {
134 assert(scope.isLexicalBlock() &&
135 "Debug location not lexical block or subprogram");
136 scope = DILexicalBlock(scope).getContext();
137 }
138 return DISubprogram(scope);
139 }
140
141 Constant *LineProfiler::getStartFileFunc() {
142 const Type *Args[1] = { Type::getInt8PtrTy(*Ctx) };
143 const FunctionType *FTy = FunctionType::get(Type::getVoidTy(*Ctx),
144 Args, false);
145 return Mod->getOrInsertFunction("llvm_prof_linectr_start_file", FTy);
146 }
147
148 Constant *LineProfiler::getCounterFunc() {
149 const Type *Args[] = {
150 Type::getInt8PtrTy(*Ctx), // const char *dir
151 Type::getInt8PtrTy(*Ctx), // const char *file
152 Type::getInt32Ty(*Ctx), // uint32_t line
153 Type::getInt32Ty(*Ctx), // uint32_t column
154 Type::getInt64PtrTy(*Ctx), // int64_t *counter
155 };
156 const FunctionType *FTy = FunctionType::get(Type::getVoidTy(*Ctx),
157 Args, false);
158 return Mod->getOrInsertFunction("llvm_prof_linectr_emit_counter", FTy);
159 }
160
161 Constant *LineProfiler::getEndFileFunc() {
162 const FunctionType *FTy = FunctionType::get(Type::getVoidTy(*Ctx), false);
163 return Mod->getOrInsertFunction("llvm_prof_linectr_end_file", FTy);
164 }
165
166 void LineProfiler::InsertCounterWriteout() {
167 std::set compile_units;
168 for (DenseMap::iterator I = counters.begin(),
169 E = counters.end(); I != E; ++I) {
170 const DebugLoc &loc = I->first;
171 DISubprogram subprogram(FindSubprogram(DIScope(loc.getScope(*Ctx))));
172 compile_units.insert(subprogram.getCompileUnit().getFilename().str());
173 }
174
175 const FunctionType *WriteoutFTy =
176 FunctionType::get(Type::getVoidTy(*Ctx), false);
177 Function *WriteoutF = Function::Create(WriteoutFTy,
178 GlobalValue::InternalLinkage,
179 "__llvm_prof_linecov_dtor",
180 Mod);
181 WriteoutF->setUnnamedAddr(true);
182 BasicBlock *BB = BasicBlock::Create(*Ctx, "", WriteoutF);
183 IRBuilder<> builder(BB);
184
185 Constant *StartFile = getStartFileFunc();
186 Constant *EmitCounter = getCounterFunc();
187 Constant *EndFile = getEndFileFunc();
188
189 for (std::set::const_iterator CUI = compile_units.begin(),
190 CUE = compile_units.end(); CUI != CUE; ++CUI) {
191 builder.CreateCall(StartFile,
192 builder.CreateGlobalStringPtr(*CUI));
193 for (DenseMap::iterator I = counters.begin(),
194 E = counters.end(); I != E; ++I) {
195 const DebugLoc &loc = I->first;
196 DISubprogram subprogram(FindSubprogram(DIScope(loc.getScope(*Ctx))));
197 DICompileUnit compileunit(subprogram.getCompileUnit());
198
199 if (compileunit.getFilename() != *CUI)
200 continue;
201
202 Value *Args[] = {
203 builder.CreateGlobalStringPtr(subprogram.getDirectory()),
204 builder.CreateGlobalStringPtr(subprogram.getFilename()),
205 ConstantInt::get(Type::getInt32Ty(*Ctx), loc.getLine()),
206 ConstantInt::get(Type::getInt32Ty(*Ctx), loc.getCol()),
207 I->second
208 };
209 builder.CreateCall(EmitCounter, Args);
210 }
211 builder.CreateCall(EndFile);
212 }
213 builder.CreateRetVoid();
214
215 InsertProfilingShutdownCall(WriteoutF, Mod);
216 }
0 /*===- GCDAProfiling.c - Support library for GCDA file emission -----------===*\
1 |*
2 |* The LLVM Compiler Infrastructure
3 |*
4 |* This file is distributed under the University of Illinois Open Source
5 |* License. See LICENSE.TXT for details.
6 |*
7 |*===----------------------------------------------------------------------===*|
8 |*
9 |* This file implements the call back routines for the gcov profiling
10 |* instrumentation pass. Link against this library when running code through
11 |* the -insert-gcov-profiling LLVM pass.
12 |*
13 |* We emit files in a corrupt version of GCOV's "gcda" file format. These files
14 |* are only close enough that LCOV will happily parse them. Anything that lcov
15 |* ignores is missing.
16 |*
17 \*===----------------------------------------------------------------------===*/
18
19 #include "llvm/Support/DataTypes.h"
20 #include
21 #include
22 #include
23 #include
24
25 // #define DEBUG_GCDAPROFILING
26
27 /*
28 * --- GCOV file format I/O primitives ---
29 */
30
31 static FILE *output_file = NULL;
32
33 static void write_int32(uint32_t i) {
34 fwrite(&i, 4, 1, output_file);
35 }
36
37 static void write_int64(uint64_t i) {
38 uint32_t lo, hi;
39 lo = i & 0x00000000ffffffff;
40 hi = i & 0xffffffff00000000;
41
42 write_int32(lo);
43 write_int32(hi);
44 }
45
46 /*
47 * --- LLVM line counter API ---
48 */
49
50 /* A file in this case is a translation unit. Each .o file built with line
51 * profiling enabled will emit to a different file. Only one file may be
52 * started at a time.
53 */
54 void llvm_gcda_start_file(const char *filename) {
55 output_file = fopen(filename, "w+");
56
57 /* gcda file, version 404*, stamp LLVM. */
58 fwrite("adcg*404MVLL", 12, 1, output_file);
59
60 #ifdef DEBUG_GCDAPROFILING
61 printf("[%s]\n", filename);
62 #endif
63 }
64
65 void llvm_gcda_emit_function(uint32_t ident) {
66 #ifdef DEBUG_GCDAPROFILING
67 printf("function id=%x\n", ident);
68 #endif
69
70 /* function tag */
71 fwrite("\0\0\0\1", 4, 1, output_file);
72 write_int32(2);
73 write_int32(ident);
74 write_int32(0);
75 }
76
77 void llvm_gcda_emit_arcs(uint32_t num_counters, uint64_t *counters) {
78 uint32_t i;
79 /* counter #1 (arcs) tag */
80 fwrite("\0\0\xa1\1", 4, 1, output_file);
81 write_int32(num_counters * 2);
82 for (i = 0; i < num_counters; ++i) {
83 write_int64(counters[i]);
84 }
85
86 #ifdef DEBUG_GCDAPROFILING
87 printf(" %u arcs\n", num_counters);
88 for (i = 0; i < num_counters; ++i) {
89 printf(" %llu\n", (unsigned long long)counters[i]);
90 }
91 #endif
92 }
93
94 void llvm_gcda_end_file() {
95 /* Write out EOF record. */
96 fwrite("\0\0\0\0\0\0\0\0", 8, 1, output_file);
97 fclose(output_file);
98 output_file = NULL;
99
100 #ifdef DEBUG_GCDAPROFILING
101 printf("-----\n");
102 #endif
103 }
+0
-40
runtime/libprofile/LineProfiling.c less more
None /*===- LineProfiling.c - Support library for line profiling ---------------===*\
1 |*
2 |* The LLVM Compiler Infrastructure
3 |*
4 |* This file is distributed under the University of Illinois Open Source
5 |* License. See LICENSE.TXT for details.
6 |*
7 |*===----------------------------------------------------------------------===*|
8 |*
9 |* This file implements the call back routines for the line profiling
10 |* instrumentation pass. Link against this library when running code through
11 |* the -insert-line-profiling LLVM pass.
12 |*
13 \*===----------------------------------------------------------------------===*/
14
15 #include
16 #include
17 #include
18
19 #include "llvm/Support/DataTypes.h"
20
21 /* A file in this case is a translation unit. Each .o file built with line
22 * profiling enabled will emit to a different file. Only one file may be
23 * started at a time.
24 */
25 void llvm_prof_linectr_start_file(const char *orig_filename) {
26 printf("[%s]\n", orig_filename);
27 }
28
29 /* Emit data about a counter to the data file. */
30 void llvm_prof_linectr_emit_counter(const char *dir, const char *file,
31 uint32_t line, uint32_t column,
32 uint64_t *counter) {
33 printf("%s/%s:%u:%u %llu\n", dir, file, line, column,
34 (unsigned long long)(*counter));
35 }
36
37 void llvm_prof_linectr_end_file() {
38 printf("-----\n");
39 }
44 llvm_trace_basic_block
55 llvm_increment_path_count
66 llvm_decrement_path_count
7 llvm_prof_linectr_start_file
8 llvm_prof_linectr_emit_counter
9 llvm_prof_linectr_end_file
7 llvm_gcda_start_file
8 llvm_gcda_emit_function
9 llvm_gcda_emit_arcs
10 llvm_gcda_end_file