AddDiscriminators.cpp 9.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248
  1. //===- AddDiscriminators.cpp - Insert DWARF path discriminators -----------===//
  2. //
  3. // The LLVM Compiler Infrastructure
  4. //
  5. // This file is distributed under the University of Illinois Open Source
  6. // License. See LICENSE.TXT for details.
  7. //
  8. //===----------------------------------------------------------------------===//
  9. //
  10. // This file adds DWARF discriminators to the IR. Path discriminators are
  11. // used to decide what CFG path was taken inside sub-graphs whose instructions
  12. // share the same line and column number information.
  13. //
  14. // The main user of this is the sample profiler. Instruction samples are
  15. // mapped to line number information. Since a single line may be spread
  16. // out over several basic blocks, discriminators add more precise location
  17. // for the samples.
  18. //
  19. // For example,
  20. //
  21. // 1 #define ASSERT(P)
  22. // 2 if (!(P))
  23. // 3 abort()
  24. // ...
  25. // 100 while (true) {
  26. // 101 ASSERT (sum < 0);
  27. // 102 ...
  28. // 130 }
  29. //
  30. // when converted to IR, this snippet looks something like:
  31. //
  32. // while.body: ; preds = %entry, %if.end
  33. // %0 = load i32* %sum, align 4, !dbg !15
  34. // %cmp = icmp slt i32 %0, 0, !dbg !15
  35. // br i1 %cmp, label %if.end, label %if.then, !dbg !15
  36. //
  37. // if.then: ; preds = %while.body
  38. // call void @abort(), !dbg !15
  39. // br label %if.end, !dbg !15
  40. //
  41. // Notice that all the instructions in blocks 'while.body' and 'if.then'
  42. // have exactly the same debug information. When this program is sampled
  43. // at runtime, the profiler will assume that all these instructions are
  44. // equally frequent. This, in turn, will consider the edge while.body->if.then
  45. // to be frequently taken (which is incorrect).
  46. //
  47. // By adding a discriminator value to the instructions in block 'if.then',
  48. // we can distinguish instructions at line 101 with discriminator 0 from
  49. // the instructions at line 101 with discriminator 1.
  50. //
  51. // For more details about DWARF discriminators, please visit
  52. // http://wiki.dwarfstd.org/index.php?title=Path_Discriminators
  53. //===----------------------------------------------------------------------===//
  54. #include "llvm/ADT/DenseMap.h"
  55. #include "llvm/IR/BasicBlock.h"
  56. #include "llvm/IR/Constants.h"
  57. #include "llvm/IR/DIBuilder.h"
  58. #include "llvm/IR/DebugInfo.h"
  59. #include "llvm/IR/Instructions.h"
  60. #include "llvm/IR/IntrinsicInst.h"
  61. #include "llvm/IR/LLVMContext.h"
  62. #include "llvm/IR/Module.h"
  63. #include "llvm/Pass.h"
  64. #include "llvm/Support/CommandLine.h"
  65. #include "llvm/Support/Debug.h"
  66. #include "llvm/Support/raw_ostream.h"
  67. #include "llvm/Transforms/Scalar.h"
  68. using namespace llvm;
  69. #define DEBUG_TYPE "add-discriminators"
  70. namespace {
  71. struct AddDiscriminators : public FunctionPass {
  72. static char ID; // Pass identification, replacement for typeid
  73. AddDiscriminators() : FunctionPass(ID) {
  74. initializeAddDiscriminatorsPass(*PassRegistry::getPassRegistry());
  75. }
  76. bool runOnFunction(Function &F) override;
  77. };
  78. } // end anonymous namespace
  79. char AddDiscriminators::ID = 0;
  80. INITIALIZE_PASS_BEGIN(AddDiscriminators, "add-discriminators",
  81. "Add DWARF path discriminators", false, false)
  82. INITIALIZE_PASS_END(AddDiscriminators, "add-discriminators",
  83. "Add DWARF path discriminators", false, false)
  84. // Command line option to disable discriminator generation even in the
  85. // presence of debug information. This is only needed when debugging
  86. // debug info generation issues.
  87. static cl::opt<bool> NoDiscriminators(
  88. "no-discriminators", cl::init(false),
  89. cl::desc("Disable generation of discriminator information."));
  90. FunctionPass *llvm::createAddDiscriminatorsPass() {
  91. return new AddDiscriminators();
  92. }
  93. static bool hasDebugInfo(const Function &F) {
  94. DISubprogram *S = getDISubprogram(&F);
  95. return S != nullptr;
  96. }
  97. /// \brief Assign DWARF discriminators.
  98. ///
  99. /// To assign discriminators, we examine the boundaries of every
  100. /// basic block and its successors. Suppose there is a basic block B1
  101. /// with successor B2. The last instruction I1 in B1 and the first
  102. /// instruction I2 in B2 are located at the same file and line number.
  103. /// This situation is illustrated in the following code snippet:
  104. ///
  105. /// if (i < 10) x = i;
  106. ///
  107. /// entry:
  108. /// br i1 %cmp, label %if.then, label %if.end, !dbg !10
  109. /// if.then:
  110. /// %1 = load i32* %i.addr, align 4, !dbg !10
  111. /// store i32 %1, i32* %x, align 4, !dbg !10
  112. /// br label %if.end, !dbg !10
  113. /// if.end:
  114. /// ret void, !dbg !12
  115. ///
  116. /// Notice how the branch instruction in block 'entry' and all the
  117. /// instructions in block 'if.then' have the exact same debug location
  118. /// information (!dbg !10).
  119. ///
  120. /// To distinguish instructions in block 'entry' from instructions in
  121. /// block 'if.then', we generate a new lexical block for all the
  122. /// instruction in block 'if.then' that share the same file and line
  123. /// location with the last instruction of block 'entry'.
  124. ///
  125. /// This new lexical block will have the same location information as
  126. /// the previous one, but with a new DWARF discriminator value.
  127. ///
  128. /// One of the main uses of this discriminator value is in runtime
  129. /// sample profilers. It allows the profiler to distinguish instructions
  130. /// at location !dbg !10 that execute on different basic blocks. This is
  131. /// important because while the predicate 'if (x < 10)' may have been
  132. /// executed millions of times, the assignment 'x = i' may have only
  133. /// executed a handful of times (meaning that the entry->if.then edge is
  134. /// seldom taken).
  135. ///
  136. /// If we did not have discriminator information, the profiler would
  137. /// assign the same weight to both blocks 'entry' and 'if.then', which
  138. /// in turn will make it conclude that the entry->if.then edge is very
  139. /// hot.
  140. ///
  141. /// To decide where to create new discriminator values, this function
  142. /// traverses the CFG and examines instruction at basic block boundaries.
  143. /// If the last instruction I1 of a block B1 is at the same file and line
  144. /// location as instruction I2 of successor B2, then it creates a new
  145. /// lexical block for I2 and all the instruction in B2 that share the same
  146. /// file and line location as I2. This new lexical block will have a
  147. /// different discriminator number than I1.
  148. bool AddDiscriminators::runOnFunction(Function &F) {
  149. // If the function has debug information, but the user has disabled
  150. // discriminators, do nothing.
  151. // Simlarly, if the function has no debug info, do nothing.
  152. // Finally, if this module is built with dwarf versions earlier than 4,
  153. // do nothing (discriminator support is a DWARF 4 feature).
  154. if (NoDiscriminators || !hasDebugInfo(F) ||
  155. F.getParent()->getDwarfVersion() < 4)
  156. return false;
  157. bool Changed = false;
  158. Module *M = F.getParent();
  159. LLVMContext &Ctx = M->getContext();
  160. DIBuilder Builder(*M, /*AllowUnresolved*/ false);
  161. typedef std::pair<StringRef, unsigned> Location;
  162. typedef DenseMap<const BasicBlock *, Metadata *> BBScopeMap;
  163. typedef DenseMap<Location, BBScopeMap> LocationBBMap;
  164. LocationBBMap LBM;
  165. // Traverse all instructions in the function. If the source line location
  166. // of the instruction appears in other basic block, assign a new
  167. // discriminator for this instruction.
  168. for (BasicBlock &B : F) {
  169. for (auto &I : B.getInstList()) {
  170. if (isa<DbgInfoIntrinsic>(&I))
  171. continue;
  172. const DILocation *DIL = I.getDebugLoc();
  173. if (!DIL)
  174. continue;
  175. Location L = std::make_pair(DIL->getFilename(), DIL->getLine());
  176. auto &BBMap = LBM[L];
  177. auto R = BBMap.insert(std::make_pair(&B, (Metadata *)nullptr));
  178. if (BBMap.size() == 1)
  179. continue;
  180. bool InsertSuccess = R.second;
  181. Metadata *&NewScope = R.first->second;
  182. // If we could insert a different block in the same location, a
  183. // discriminator is needed to distinguish both instructions.
  184. if (InsertSuccess) {
  185. auto *Scope = DIL->getScope();
  186. auto *File =
  187. Builder.createFile(DIL->getFilename(), Scope->getDirectory());
  188. NewScope = Builder.createLexicalBlockFile(
  189. Scope, File, DIL->computeNewDiscriminator());
  190. }
  191. I.setDebugLoc(DILocation::get(Ctx, DIL->getLine(), DIL->getColumn(),
  192. NewScope, DIL->getInlinedAt()));
  193. DEBUG(dbgs() << DIL->getFilename() << ":" << DIL->getLine() << ":"
  194. << DIL->getColumn() << ":"
  195. << dyn_cast<DILexicalBlockFile>(NewScope)->getDiscriminator()
  196. << I << "\n");
  197. Changed = true;
  198. }
  199. }
  200. // Traverse all instructions and assign new discriminators to call
  201. // instructions with the same lineno that are in the same basic block.
  202. // Sample base profile needs to distinguish different function calls within
  203. // a same source line for correct profile annotation.
  204. for (BasicBlock &B : F) {
  205. const DILocation *FirstDIL = nullptr;
  206. for (auto &I : B.getInstList()) {
  207. CallInst *Current = dyn_cast<CallInst>(&I);
  208. if (!Current || isa<DbgInfoIntrinsic>(&I))
  209. continue;
  210. DILocation *CurrentDIL = Current->getDebugLoc();
  211. if (FirstDIL) {
  212. if (CurrentDIL && CurrentDIL->getLine() == FirstDIL->getLine() &&
  213. CurrentDIL->getFilename() == FirstDIL->getFilename()) {
  214. auto *Scope = FirstDIL->getScope();
  215. auto *File = Builder.createFile(FirstDIL->getFilename(),
  216. Scope->getDirectory());
  217. auto *NewScope = Builder.createLexicalBlockFile(
  218. Scope, File, FirstDIL->computeNewDiscriminator());
  219. Current->setDebugLoc(DILocation::get(
  220. Ctx, CurrentDIL->getLine(), CurrentDIL->getColumn(), NewScope,
  221. CurrentDIL->getInlinedAt()));
  222. Changed = true;
  223. } else {
  224. FirstDIL = CurrentDIL;
  225. }
  226. } else {
  227. FirstDIL = CurrentDIL;
  228. }
  229. }
  230. }
  231. return Changed;
  232. }