BasicBlockSectionsProfileReader.cpp 5.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144
  1. //===-- BasicBlockSectionsProfileReader.cpp -------------------------------===//
  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. // Implementation of the basic block sections profile reader pass. It parses
  10. // and stores the basic block sections profile file (which is specified via the
  11. // `-basic-block-sections` flag).
  12. //
  13. //===----------------------------------------------------------------------===//
  14. #include "llvm/CodeGen/BasicBlockSectionsProfileReader.h"
  15. #include "llvm/ADT/SmallSet.h"
  16. #include "llvm/ADT/SmallVector.h"
  17. #include "llvm/ADT/StringMap.h"
  18. #include "llvm/ADT/StringRef.h"
  19. #include "llvm/Support/Error.h"
  20. #include "llvm/Support/LineIterator.h"
  21. #include "llvm/Support/MemoryBuffer.h"
  22. using namespace llvm;
  23. char BasicBlockSectionsProfileReader::ID = 0;
  24. INITIALIZE_PASS(BasicBlockSectionsProfileReader, "bbsections-profile-reader",
  25. "Reads and parses a basic block sections profile.", false,
  26. false)
  27. bool BasicBlockSectionsProfileReader::isFunctionHot(StringRef FuncName) const {
  28. return getBBClusterInfoForFunction(FuncName).first;
  29. }
  30. std::pair<bool, SmallVector<BBClusterInfo>>
  31. BasicBlockSectionsProfileReader::getBBClusterInfoForFunction(
  32. StringRef FuncName) const {
  33. std::pair<bool, SmallVector<BBClusterInfo>> cluster_info(false, {});
  34. auto R = ProgramBBClusterInfo.find(getAliasName(FuncName));
  35. if (R != ProgramBBClusterInfo.end()) {
  36. cluster_info.second = R->second;
  37. cluster_info.first = true;
  38. }
  39. return cluster_info;
  40. }
  41. // Basic Block Sections can be enabled for a subset of machine basic blocks.
  42. // This is done by passing a file containing names of functions for which basic
  43. // block sections are desired. Additionally, machine basic block ids of the
  44. // functions can also be specified for a finer granularity. Moreover, a cluster
  45. // of basic blocks could be assigned to the same section.
  46. // A file with basic block sections for all of function main and three blocks
  47. // for function foo (of which 1 and 2 are placed in a cluster) looks like this:
  48. // ----------------------------
  49. // list.txt:
  50. // !main
  51. // !foo
  52. // !!1 2
  53. // !!4
  54. static Error getBBClusterInfo(const MemoryBuffer *MBuf,
  55. ProgramBBClusterInfoMapTy &ProgramBBClusterInfo,
  56. StringMap<StringRef> &FuncAliasMap) {
  57. assert(MBuf);
  58. line_iterator LineIt(*MBuf, /*SkipBlanks=*/true, /*CommentMarker=*/'#');
  59. auto invalidProfileError = [&](auto Message) {
  60. return make_error<StringError>(
  61. Twine("Invalid profile " + MBuf->getBufferIdentifier() + " at line " +
  62. Twine(LineIt.line_number()) + ": " + Message),
  63. inconvertibleErrorCode());
  64. };
  65. auto FI = ProgramBBClusterInfo.end();
  66. // Current cluster ID corresponding to this function.
  67. unsigned CurrentCluster = 0;
  68. // Current position in the current cluster.
  69. unsigned CurrentPosition = 0;
  70. // Temporary set to ensure every basic block ID appears once in the clusters
  71. // of a function.
  72. SmallSet<unsigned, 4> FuncBBIDs;
  73. for (; !LineIt.is_at_eof(); ++LineIt) {
  74. StringRef S(*LineIt);
  75. if (S[0] == '@')
  76. continue;
  77. // Check for the leading "!"
  78. if (!S.consume_front("!") || S.empty())
  79. break;
  80. // Check for second "!" which indicates a cluster of basic blocks.
  81. if (S.consume_front("!")) {
  82. if (FI == ProgramBBClusterInfo.end())
  83. return invalidProfileError(
  84. "Cluster list does not follow a function name specifier.");
  85. SmallVector<StringRef, 4> BBIDs;
  86. S.split(BBIDs, ' ');
  87. // Reset current cluster position.
  88. CurrentPosition = 0;
  89. for (auto BBIDStr : BBIDs) {
  90. unsigned long long BBID;
  91. if (getAsUnsignedInteger(BBIDStr, 10, BBID))
  92. return invalidProfileError(Twine("Unsigned integer expected: '") +
  93. BBIDStr + "'.");
  94. if (!FuncBBIDs.insert(BBID).second)
  95. return invalidProfileError(Twine("Duplicate basic block id found '") +
  96. BBIDStr + "'.");
  97. if (BBID == 0 && CurrentPosition)
  98. return invalidProfileError("Entry BB (0) does not begin a cluster.");
  99. FI->second.emplace_back(
  100. BBClusterInfo{((unsigned)BBID), CurrentCluster, CurrentPosition++});
  101. }
  102. CurrentCluster++;
  103. } else { // This is a function name specifier.
  104. // Function aliases are separated using '/'. We use the first function
  105. // name for the cluster info mapping and delegate all other aliases to
  106. // this one.
  107. SmallVector<StringRef, 4> Aliases;
  108. S.split(Aliases, '/');
  109. for (size_t i = 1; i < Aliases.size(); ++i)
  110. FuncAliasMap.try_emplace(Aliases[i], Aliases.front());
  111. // Prepare for parsing clusters of this function name.
  112. // Start a new cluster map for this function name.
  113. FI = ProgramBBClusterInfo.try_emplace(Aliases.front()).first;
  114. CurrentCluster = 0;
  115. FuncBBIDs.clear();
  116. }
  117. }
  118. return Error::success();
  119. }
  120. void BasicBlockSectionsProfileReader::initializePass() {
  121. if (!MBuf)
  122. return;
  123. if (auto Err = getBBClusterInfo(MBuf, ProgramBBClusterInfo, FuncAliasMap))
  124. report_fatal_error(std::move(Err));
  125. }
  126. ImmutablePass *
  127. llvm::createBasicBlockSectionsProfileReaderPass(const MemoryBuffer *Buf) {
  128. return new BasicBlockSectionsProfileReader(Buf);
  129. }