AddDiscriminators.cpp 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283
  1. //===- AddDiscriminators.cpp - Insert DWARF path discriminators -----------===//
  2. //
  3. // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
  4. // See https://llvm.org/LICENSE.txt for license information.
  5. // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
  6. //
  7. //===----------------------------------------------------------------------===//
  8. //
  9. // This file adds DWARF discriminators to the IR. Path discriminators are
  10. // used to decide what CFG path was taken inside sub-graphs whose instructions
  11. // share the same line and column number information.
  12. //
  13. // The main user of this is the sample profiler. Instruction samples are
  14. // mapped to line number information. Since a single line may be spread
  15. // out over several basic blocks, discriminators add more precise location
  16. // for the samples.
  17. //
  18. // For example,
  19. //
  20. // 1 #define ASSERT(P)
  21. // 2 if (!(P))
  22. // 3 abort()
  23. // ...
  24. // 100 while (true) {
  25. // 101 ASSERT (sum < 0);
  26. // 102 ...
  27. // 130 }
  28. //
  29. // when converted to IR, this snippet looks something like:
  30. //
  31. // while.body: ; preds = %entry, %if.end
  32. // %0 = load i32* %sum, align 4, !dbg !15
  33. // %cmp = icmp slt i32 %0, 0, !dbg !15
  34. // br i1 %cmp, label %if.end, label %if.then, !dbg !15
  35. //
  36. // if.then: ; preds = %while.body
  37. // call void @abort(), !dbg !15
  38. // br label %if.end, !dbg !15
  39. //
  40. // Notice that all the instructions in blocks 'while.body' and 'if.then'
  41. // have exactly the same debug information. When this program is sampled
  42. // at runtime, the profiler will assume that all these instructions are
  43. // equally frequent. This, in turn, will consider the edge while.body->if.then
  44. // to be frequently taken (which is incorrect).
  45. //
  46. // By adding a discriminator value to the instructions in block 'if.then',
  47. // we can distinguish instructions at line 101 with discriminator 0 from
  48. // the instructions at line 101 with discriminator 1.
  49. //
  50. // For more details about DWARF discriminators, please visit
  51. // http://wiki.dwarfstd.org/index.php?title=Path_Discriminators
  52. //
  53. //===----------------------------------------------------------------------===//
  54. #include "llvm/Transforms/Utils/AddDiscriminators.h"
  55. #include "llvm/ADT/DenseMap.h"
  56. #include "llvm/ADT/DenseSet.h"
  57. #include "llvm/ADT/StringRef.h"
  58. #include "llvm/IR/BasicBlock.h"
  59. #include "llvm/IR/DebugInfoMetadata.h"
  60. #include "llvm/IR/Function.h"
  61. #include "llvm/IR/Instruction.h"
  62. #include "llvm/IR/Instructions.h"
  63. #include "llvm/IR/IntrinsicInst.h"
  64. #include "llvm/IR/PassManager.h"
  65. #include "llvm/InitializePasses.h"
  66. #include "llvm/Pass.h"
  67. #include "llvm/Support/Casting.h"
  68. #include "llvm/Support/CommandLine.h"
  69. #include "llvm/Support/Debug.h"
  70. #include "llvm/Support/raw_ostream.h"
  71. #include "llvm/Transforms/Utils.h"
  72. #include "llvm/Transforms/Utils/SampleProfileLoaderBaseUtil.h"
  73. #include <utility>
  74. using namespace llvm;
  75. using namespace sampleprofutil;
  76. #define DEBUG_TYPE "add-discriminators"
  77. // Command line option to disable discriminator generation even in the
  78. // presence of debug information. This is only needed when debugging
  79. // debug info generation issues.
  80. static cl::opt<bool> NoDiscriminators(
  81. "no-discriminators", cl::init(false),
  82. cl::desc("Disable generation of discriminator information."));
  83. namespace {
  84. // The legacy pass of AddDiscriminators.
  85. struct AddDiscriminatorsLegacyPass : public FunctionPass {
  86. static char ID; // Pass identification, replacement for typeid
  87. AddDiscriminatorsLegacyPass() : FunctionPass(ID) {
  88. initializeAddDiscriminatorsLegacyPassPass(*PassRegistry::getPassRegistry());
  89. }
  90. bool runOnFunction(Function &F) override;
  91. };
  92. } // end anonymous namespace
  93. char AddDiscriminatorsLegacyPass::ID = 0;
  94. INITIALIZE_PASS_BEGIN(AddDiscriminatorsLegacyPass, "add-discriminators",
  95. "Add DWARF path discriminators", false, false)
  96. INITIALIZE_PASS_END(AddDiscriminatorsLegacyPass, "add-discriminators",
  97. "Add DWARF path discriminators", false, false)
  98. // Create the legacy AddDiscriminatorsPass.
  99. FunctionPass *llvm::createAddDiscriminatorsPass() {
  100. return new AddDiscriminatorsLegacyPass();
  101. }
  102. static bool shouldHaveDiscriminator(const Instruction *I) {
  103. return !isa<IntrinsicInst>(I) || isa<MemIntrinsic>(I);
  104. }
  105. /// Assign DWARF discriminators.
  106. ///
  107. /// To assign discriminators, we examine the boundaries of every
  108. /// basic block and its successors. Suppose there is a basic block B1
  109. /// with successor B2. The last instruction I1 in B1 and the first
  110. /// instruction I2 in B2 are located at the same file and line number.
  111. /// This situation is illustrated in the following code snippet:
  112. ///
  113. /// if (i < 10) x = i;
  114. ///
  115. /// entry:
  116. /// br i1 %cmp, label %if.then, label %if.end, !dbg !10
  117. /// if.then:
  118. /// %1 = load i32* %i.addr, align 4, !dbg !10
  119. /// store i32 %1, i32* %x, align 4, !dbg !10
  120. /// br label %if.end, !dbg !10
  121. /// if.end:
  122. /// ret void, !dbg !12
  123. ///
  124. /// Notice how the branch instruction in block 'entry' and all the
  125. /// instructions in block 'if.then' have the exact same debug location
  126. /// information (!dbg !10).
  127. ///
  128. /// To distinguish instructions in block 'entry' from instructions in
  129. /// block 'if.then', we generate a new lexical block for all the
  130. /// instruction in block 'if.then' that share the same file and line
  131. /// location with the last instruction of block 'entry'.
  132. ///
  133. /// This new lexical block will have the same location information as
  134. /// the previous one, but with a new DWARF discriminator value.
  135. ///
  136. /// One of the main uses of this discriminator value is in runtime
  137. /// sample profilers. It allows the profiler to distinguish instructions
  138. /// at location !dbg !10 that execute on different basic blocks. This is
  139. /// important because while the predicate 'if (x < 10)' may have been
  140. /// executed millions of times, the assignment 'x = i' may have only
  141. /// executed a handful of times (meaning that the entry->if.then edge is
  142. /// seldom taken).
  143. ///
  144. /// If we did not have discriminator information, the profiler would
  145. /// assign the same weight to both blocks 'entry' and 'if.then', which
  146. /// in turn will make it conclude that the entry->if.then edge is very
  147. /// hot.
  148. ///
  149. /// To decide where to create new discriminator values, this function
  150. /// traverses the CFG and examines instruction at basic block boundaries.
  151. /// If the last instruction I1 of a block B1 is at the same file and line
  152. /// location as instruction I2 of successor B2, then it creates a new
  153. /// lexical block for I2 and all the instruction in B2 that share the same
  154. /// file and line location as I2. This new lexical block will have a
  155. /// different discriminator number than I1.
  156. static bool addDiscriminators(Function &F) {
  157. // If the function has debug information, but the user has disabled
  158. // discriminators, do nothing.
  159. // Simlarly, if the function has no debug info, do nothing.
  160. if (NoDiscriminators || !F.getSubprogram())
  161. return false;
  162. // Create FSDiscriminatorVariable if flow sensitive discriminators are used.
  163. if (EnableFSDiscriminator)
  164. createFSDiscriminatorVariable(F.getParent());
  165. bool Changed = false;
  166. using Location = std::pair<StringRef, unsigned>;
  167. using BBSet = DenseSet<const BasicBlock *>;
  168. using LocationBBMap = DenseMap<Location, BBSet>;
  169. using LocationDiscriminatorMap = DenseMap<Location, unsigned>;
  170. using LocationSet = DenseSet<Location>;
  171. LocationBBMap LBM;
  172. LocationDiscriminatorMap LDM;
  173. // Traverse all instructions in the function. If the source line location
  174. // of the instruction appears in other basic block, assign a new
  175. // discriminator for this instruction.
  176. for (BasicBlock &B : F) {
  177. for (auto &I : B.getInstList()) {
  178. // Not all intrinsic calls should have a discriminator.
  179. // We want to avoid a non-deterministic assignment of discriminators at
  180. // different debug levels. We still allow discriminators on memory
  181. // intrinsic calls because those can be early expanded by SROA into
  182. // pairs of loads and stores, and the expanded load/store instructions
  183. // should have a valid discriminator.
  184. if (!shouldHaveDiscriminator(&I))
  185. continue;
  186. const DILocation *DIL = I.getDebugLoc();
  187. if (!DIL)
  188. continue;
  189. Location L = std::make_pair(DIL->getFilename(), DIL->getLine());
  190. auto &BBMap = LBM[L];
  191. auto R = BBMap.insert(&B);
  192. if (BBMap.size() == 1)
  193. continue;
  194. // If we could insert more than one block with the same line+file, a
  195. // discriminator is needed to distinguish both instructions.
  196. // Only the lowest 7 bits are used to represent a discriminator to fit
  197. // it in 1 byte ULEB128 representation.
  198. unsigned Discriminator = R.second ? ++LDM[L] : LDM[L];
  199. auto NewDIL = DIL->cloneWithBaseDiscriminator(Discriminator);
  200. if (!NewDIL) {
  201. LLVM_DEBUG(dbgs() << "Could not encode discriminator: "
  202. << DIL->getFilename() << ":" << DIL->getLine() << ":"
  203. << DIL->getColumn() << ":" << Discriminator << " "
  204. << I << "\n");
  205. } else {
  206. I.setDebugLoc(NewDIL.getValue());
  207. LLVM_DEBUG(dbgs() << DIL->getFilename() << ":" << DIL->getLine() << ":"
  208. << DIL->getColumn() << ":" << Discriminator << " " << I
  209. << "\n");
  210. }
  211. Changed = true;
  212. }
  213. }
  214. // Traverse all instructions and assign new discriminators to call
  215. // instructions with the same lineno that are in the same basic block.
  216. // Sample base profile needs to distinguish different function calls within
  217. // a same source line for correct profile annotation.
  218. for (BasicBlock &B : F) {
  219. LocationSet CallLocations;
  220. for (auto &I : B.getInstList()) {
  221. // We bypass intrinsic calls for the following two reasons:
  222. // 1) We want to avoid a non-deterministic assignment of
  223. // discriminators.
  224. // 2) We want to minimize the number of base discriminators used.
  225. if (!isa<InvokeInst>(I) && (!isa<CallInst>(I) || isa<IntrinsicInst>(I)))
  226. continue;
  227. DILocation *CurrentDIL = I.getDebugLoc();
  228. if (!CurrentDIL)
  229. continue;
  230. Location L =
  231. std::make_pair(CurrentDIL->getFilename(), CurrentDIL->getLine());
  232. if (!CallLocations.insert(L).second) {
  233. unsigned Discriminator = ++LDM[L];
  234. auto NewDIL = CurrentDIL->cloneWithBaseDiscriminator(Discriminator);
  235. if (!NewDIL) {
  236. LLVM_DEBUG(dbgs()
  237. << "Could not encode discriminator: "
  238. << CurrentDIL->getFilename() << ":"
  239. << CurrentDIL->getLine() << ":" << CurrentDIL->getColumn()
  240. << ":" << Discriminator << " " << I << "\n");
  241. } else {
  242. I.setDebugLoc(NewDIL.getValue());
  243. Changed = true;
  244. }
  245. }
  246. }
  247. }
  248. return Changed;
  249. }
  250. bool AddDiscriminatorsLegacyPass::runOnFunction(Function &F) {
  251. return addDiscriminators(F);
  252. }
  253. PreservedAnalyses AddDiscriminatorsPass::run(Function &F,
  254. FunctionAnalysisManager &AM) {
  255. if (!addDiscriminators(F))
  256. return PreservedAnalyses::all();
  257. // FIXME: should be all()
  258. return PreservedAnalyses::none();
  259. }