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