[AMDGPU][AsmParser][NFC] Translate parsed MIMG instructions to MCInsts automatically.
[llvm-project.git] / llvm / lib / CodeGen / BasicBlockSectionsProfileReader.cpp
blob5dede452ec34b3bfe0194d7fa1df4eb2fbbf5d8d
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/SmallString.h"
18 #include "llvm/ADT/SmallVector.h"
19 #include "llvm/ADT/StringMap.h"
20 #include "llvm/ADT/StringRef.h"
21 #include "llvm/CodeGen/Passes.h"
22 #include "llvm/IR/DebugInfoMetadata.h"
23 #include "llvm/Support/Error.h"
24 #include "llvm/Support/LineIterator.h"
25 #include "llvm/Support/MemoryBuffer.h"
26 #include "llvm/Support/Path.h"
27 #include <llvm/ADT/STLExtras.h>
29 using namespace llvm;
31 char BasicBlockSectionsProfileReader::ID = 0;
32 INITIALIZE_PASS(BasicBlockSectionsProfileReader, "bbsections-profile-reader",
33 "Reads and parses a basic block sections profile.", false,
34 false)
36 bool BasicBlockSectionsProfileReader::isFunctionHot(StringRef FuncName) const {
37 return getBBClusterInfoForFunction(FuncName).first;
40 std::pair<bool, SmallVector<BBClusterInfo>>
41 BasicBlockSectionsProfileReader::getBBClusterInfoForFunction(
42 StringRef FuncName) const {
43 auto R = ProgramBBClusterInfo.find(getAliasName(FuncName));
44 return R != ProgramBBClusterInfo.end()
45 ? std::pair(true, R->second)
46 : std::pair(false, SmallVector<BBClusterInfo>{});
49 // Basic Block Sections can be enabled for a subset of machine basic blocks.
50 // This is done by passing a file containing names of functions for which basic
51 // block sections are desired. Additionally, machine basic block ids of the
52 // functions can also be specified for a finer granularity. Moreover, a cluster
53 // of basic blocks could be assigned to the same section.
54 // Optionally, a debug-info filename can be specified for each function to allow
55 // distinguishing internal-linkage functions of the same name.
56 // A file with basic block sections for all of function main and three blocks
57 // for function foo (of which 1 and 2 are placed in a cluster) looks like this:
58 // (Profile for function foo is only loaded when its debug-info filename
59 // matches 'path/to/foo_file.cc').
60 // ----------------------------
61 // list.txt:
62 // !main
63 // !foo M=path/to/foo_file.cc
64 // !!1 2
65 // !!4
66 Error BasicBlockSectionsProfileReader::ReadProfile() {
67 assert(MBuf);
68 line_iterator LineIt(*MBuf, /*SkipBlanks=*/true, /*CommentMarker=*/'#');
70 auto invalidProfileError = [&](auto Message) {
71 return make_error<StringError>(
72 Twine("Invalid profile " + MBuf->getBufferIdentifier() + " at line " +
73 Twine(LineIt.line_number()) + ": " + Message),
74 inconvertibleErrorCode());
77 auto FI = ProgramBBClusterInfo.end();
79 // Current cluster ID corresponding to this function.
80 unsigned CurrentCluster = 0;
81 // Current position in the current cluster.
82 unsigned CurrentPosition = 0;
84 // Temporary set to ensure every basic block ID appears once in the clusters
85 // of a function.
86 SmallSet<unsigned, 4> FuncBBIDs;
88 for (; !LineIt.is_at_eof(); ++LineIt) {
89 StringRef S(*LineIt);
90 if (S[0] == '@')
91 continue;
92 // Check for the leading "!"
93 if (!S.consume_front("!") || S.empty())
94 break;
95 // Check for second "!" which indicates a cluster of basic blocks.
96 if (S.consume_front("!")) {
97 // Skip the profile when we the profile iterator (FI) refers to the
98 // past-the-end element.
99 if (FI == ProgramBBClusterInfo.end())
100 continue;
101 SmallVector<StringRef, 4> BBIDs;
102 S.split(BBIDs, ' ');
103 // Reset current cluster position.
104 CurrentPosition = 0;
105 for (auto BBIDStr : BBIDs) {
106 unsigned long long BBID;
107 if (getAsUnsignedInteger(BBIDStr, 10, BBID))
108 return invalidProfileError(Twine("Unsigned integer expected: '") +
109 BBIDStr + "'.");
110 if (!FuncBBIDs.insert(BBID).second)
111 return invalidProfileError(Twine("Duplicate basic block id found '") +
112 BBIDStr + "'.");
113 if (BBID == 0 && CurrentPosition)
114 return invalidProfileError("Entry BB (0) does not begin a cluster.");
116 FI->second.emplace_back(
117 BBClusterInfo{((unsigned)BBID), CurrentCluster, CurrentPosition++});
119 CurrentCluster++;
120 } else {
121 // This is a function name specifier. It may include a debug info filename
122 // specifier starting with `M=`.
123 auto [AliasesStr, DIFilenameStr] = S.split(' ');
124 SmallString<128> DIFilename;
125 if (DIFilenameStr.startswith("M=")) {
126 DIFilename =
127 sys::path::remove_leading_dotslash(DIFilenameStr.substr(2));
128 if (DIFilename.empty())
129 return invalidProfileError("Empty module name specifier.");
130 } else if (!DIFilenameStr.empty()) {
131 return invalidProfileError("Unknown string found: '" + DIFilenameStr +
132 "'.");
134 // Function aliases are separated using '/'. We use the first function
135 // name for the cluster info mapping and delegate all other aliases to
136 // this one.
137 SmallVector<StringRef, 4> Aliases;
138 AliasesStr.split(Aliases, '/');
139 bool FunctionFound = any_of(Aliases, [&](StringRef Alias) {
140 auto It = FunctionNameToDIFilename.find(Alias);
141 // No match if this function name is not found in this module.
142 if (It == FunctionNameToDIFilename.end())
143 return false;
144 // Return a match if debug-info-filename is not specified. Otherwise,
145 // check for equality.
146 return DIFilename.empty() || It->second.equals(DIFilename);
148 if (!FunctionFound) {
149 // Skip the following profile by setting the profile iterator (FI) to
150 // the past-the-end element.
151 FI = ProgramBBClusterInfo.end();
152 continue;
154 for (size_t i = 1; i < Aliases.size(); ++i)
155 FuncAliasMap.try_emplace(Aliases[i], Aliases.front());
157 // Prepare for parsing clusters of this function name.
158 // Start a new cluster map for this function name.
159 auto R = ProgramBBClusterInfo.try_emplace(Aliases.front());
160 // Report error when multiple profiles have been specified for the same
161 // function.
162 if (!R.second)
163 return invalidProfileError("Duplicate profile for function '" +
164 Aliases.front() + "'.");
165 FI = R.first;
166 CurrentCluster = 0;
167 FuncBBIDs.clear();
170 return Error::success();
173 bool BasicBlockSectionsProfileReader::doInitialization(Module &M) {
174 if (!MBuf)
175 return false;
176 // Get the function name to debug info filename mapping.
177 FunctionNameToDIFilename.clear();
178 for (const Function &F : M) {
179 SmallString<128> DIFilename;
180 if (F.isDeclaration())
181 continue;
182 DISubprogram *Subprogram = F.getSubprogram();
183 if (Subprogram) {
184 llvm::DICompileUnit *CU = Subprogram->getUnit();
185 if (CU)
186 DIFilename = sys::path::remove_leading_dotslash(CU->getFilename());
188 [[maybe_unused]] bool inserted =
189 FunctionNameToDIFilename.try_emplace(F.getName(), DIFilename).second;
190 assert(inserted);
192 if (auto Err = ReadProfile())
193 report_fatal_error(std::move(Err));
194 return false;
197 ImmutablePass *
198 llvm::createBasicBlockSectionsProfileReaderPass(const MemoryBuffer *Buf) {
199 return new BasicBlockSectionsProfileReader(Buf);