MIRFSDiscriminator.cpp 5.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142
  1. //===-------- MIRFSDiscriminator.cpp: Flow Sensitive Discriminator --------===//
  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 provides the implementation of a machine pass that adds the flow
  10. // sensitive discriminator to the instruction debug information.
  11. //
  12. //===----------------------------------------------------------------------===//
  13. #include "llvm/CodeGen/MIRFSDiscriminator.h"
  14. #include "llvm/ADT/DenseMap.h"
  15. #include "llvm/ADT/DenseSet.h"
  16. #include "llvm/Analysis/BlockFrequencyInfoImpl.h"
  17. #include "llvm/CodeGen/Passes.h"
  18. #include "llvm/IR/DebugInfoMetadata.h"
  19. #include "llvm/IR/Function.h"
  20. #include "llvm/InitializePasses.h"
  21. #include "llvm/Support/CommandLine.h"
  22. #include "llvm/Support/Debug.h"
  23. #include "llvm/Support/raw_ostream.h"
  24. #include "llvm/Transforms/Utils/SampleProfileLoaderBaseUtil.h"
  25. using namespace llvm;
  26. using namespace sampleprof;
  27. using namespace sampleprofutil;
  28. #define DEBUG_TYPE "mirfs-discriminators"
  29. char MIRAddFSDiscriminators::ID = 0;
  30. INITIALIZE_PASS(MIRAddFSDiscriminators, DEBUG_TYPE,
  31. "Add MIR Flow Sensitive Discriminators",
  32. /* cfg = */ false, /* is_analysis = */ false)
  33. char &llvm::MIRAddFSDiscriminatorsID = MIRAddFSDiscriminators::ID;
  34. FunctionPass *llvm::createMIRAddFSDiscriminatorsPass(FSDiscriminatorPass P) {
  35. return new MIRAddFSDiscriminators(P);
  36. }
  37. // Compute a hash value using debug line number, and the line numbers from the
  38. // inline stack.
  39. static uint64_t getCallStackHash(const MachineBasicBlock &BB,
  40. const MachineInstr &MI,
  41. const DILocation *DIL) {
  42. auto updateHash = [](const StringRef &Str) -> uint64_t {
  43. if (Str.empty())
  44. return 0;
  45. return MD5Hash(Str);
  46. };
  47. uint64_t Ret = updateHash(std::to_string(DIL->getLine()));
  48. Ret ^= updateHash(BB.getName());
  49. Ret ^= updateHash(DIL->getScope()->getSubprogram()->getLinkageName());
  50. for (DIL = DIL->getInlinedAt(); DIL; DIL = DIL->getInlinedAt()) {
  51. Ret ^= updateHash(std::to_string(DIL->getLine()));
  52. Ret ^= updateHash(DIL->getScope()->getSubprogram()->getLinkageName());
  53. }
  54. return Ret;
  55. }
  56. // Traverse the CFG and assign FD discriminators. If two instructions
  57. // have the same lineno and discriminator, but residing in different BBs,
  58. // the latter instruction will get a new discriminator value. The new
  59. // discriminator keeps the existing discriminator value but sets new bits
  60. // b/w LowBit and HighBit.
  61. bool MIRAddFSDiscriminators::runOnMachineFunction(MachineFunction &MF) {
  62. if (!EnableFSDiscriminator)
  63. return false;
  64. if (!MF.getFunction().shouldEmitDebugInfoForProfiling())
  65. return false;
  66. bool Changed = false;
  67. using LocationDiscriminator = std::tuple<StringRef, unsigned, unsigned>;
  68. using BBSet = DenseSet<const MachineBasicBlock *>;
  69. using LocationDiscriminatorBBMap = DenseMap<LocationDiscriminator, BBSet>;
  70. using LocationDiscriminatorCurrPassMap =
  71. DenseMap<LocationDiscriminator, unsigned>;
  72. LocationDiscriminatorBBMap LDBM;
  73. LocationDiscriminatorCurrPassMap LDCM;
  74. // Mask of discriminators before this pass.
  75. unsigned BitMaskBefore = getN1Bits(LowBit);
  76. // Mask of discriminators including this pass.
  77. unsigned BitMaskNow = getN1Bits(HighBit);
  78. // Mask of discriminators for bits specific to this pass.
  79. unsigned BitMaskThisPass = BitMaskNow ^ BitMaskBefore;
  80. unsigned NumNewD = 0;
  81. LLVM_DEBUG(dbgs() << "MIRAddFSDiscriminators working on Func: "
  82. << MF.getFunction().getName() << "\n");
  83. for (MachineBasicBlock &BB : MF) {
  84. for (MachineInstr &I : BB) {
  85. const DILocation *DIL = I.getDebugLoc().get();
  86. if (!DIL)
  87. continue;
  88. unsigned LineNo = DIL->getLine();
  89. if (LineNo == 0)
  90. continue;
  91. unsigned Discriminator = DIL->getDiscriminator();
  92. LocationDiscriminator LD{DIL->getFilename(), LineNo, Discriminator};
  93. auto &BBMap = LDBM[LD];
  94. auto R = BBMap.insert(&BB);
  95. if (BBMap.size() == 1)
  96. continue;
  97. unsigned DiscriminatorCurrPass;
  98. DiscriminatorCurrPass = R.second ? ++LDCM[LD] : LDCM[LD];
  99. DiscriminatorCurrPass = DiscriminatorCurrPass << LowBit;
  100. DiscriminatorCurrPass += getCallStackHash(BB, I, DIL);
  101. DiscriminatorCurrPass &= BitMaskThisPass;
  102. unsigned NewD = Discriminator | DiscriminatorCurrPass;
  103. const auto *const NewDIL = DIL->cloneWithDiscriminator(NewD);
  104. if (!NewDIL) {
  105. LLVM_DEBUG(dbgs() << "Could not encode discriminator: "
  106. << DIL->getFilename() << ":" << DIL->getLine() << ":"
  107. << DIL->getColumn() << ":" << Discriminator << " "
  108. << I << "\n");
  109. continue;
  110. }
  111. I.setDebugLoc(NewDIL);
  112. NumNewD++;
  113. LLVM_DEBUG(dbgs() << DIL->getFilename() << ":" << DIL->getLine() << ":"
  114. << DIL->getColumn() << ": add FS discriminator, from "
  115. << Discriminator << " -> " << NewD << "\n");
  116. Changed = true;
  117. }
  118. }
  119. if (Changed) {
  120. createFSDiscriminatorVariable(MF.getFunction().getParent());
  121. LLVM_DEBUG(dbgs() << "Num of FS Discriminators: " << NumNewD << "\n");
  122. (void) NumNewD;
  123. }
  124. return Changed;
  125. }