MIRFSDiscriminator.cpp 5.1 KB

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