1145449b1SDimitry Andric //===-- BasicBlockSectionsProfileReader.cpp -------------------------------===//
2145449b1SDimitry Andric //
3145449b1SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4145449b1SDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
5145449b1SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6145449b1SDimitry Andric //
7145449b1SDimitry Andric //===----------------------------------------------------------------------===//
8145449b1SDimitry Andric //
9145449b1SDimitry Andric // Implementation of the basic block sections profile reader pass. It parses
10145449b1SDimitry Andric // and stores the basic block sections profile file (which is specified via the
11145449b1SDimitry Andric // `-basic-block-sections` flag).
12145449b1SDimitry Andric //
13145449b1SDimitry Andric //===----------------------------------------------------------------------===//
14145449b1SDimitry Andric
15145449b1SDimitry Andric #include "llvm/CodeGen/BasicBlockSectionsProfileReader.h"
16b1c73532SDimitry Andric #include "llvm/ADT/DenseSet.h"
17145449b1SDimitry Andric #include "llvm/ADT/SmallSet.h"
187fa27ce4SDimitry Andric #include "llvm/ADT/SmallString.h"
19145449b1SDimitry Andric #include "llvm/ADT/SmallVector.h"
20145449b1SDimitry Andric #include "llvm/ADT/StringMap.h"
21145449b1SDimitry Andric #include "llvm/ADT/StringRef.h"
227fa27ce4SDimitry Andric #include "llvm/IR/DebugInfoMetadata.h"
23b1c73532SDimitry Andric #include "llvm/Pass.h"
24145449b1SDimitry Andric #include "llvm/Support/Error.h"
25b1c73532SDimitry Andric #include "llvm/Support/ErrorHandling.h"
26145449b1SDimitry Andric #include "llvm/Support/LineIterator.h"
27145449b1SDimitry Andric #include "llvm/Support/MemoryBuffer.h"
287fa27ce4SDimitry Andric #include "llvm/Support/Path.h"
297fa27ce4SDimitry Andric #include <llvm/ADT/STLExtras.h>
30145449b1SDimitry Andric
31145449b1SDimitry Andric using namespace llvm;
32145449b1SDimitry Andric
33aca2e42cSDimitry Andric char BasicBlockSectionsProfileReaderWrapperPass::ID = 0;
34aca2e42cSDimitry Andric INITIALIZE_PASS(BasicBlockSectionsProfileReaderWrapperPass,
35aca2e42cSDimitry Andric "bbsections-profile-reader",
36145449b1SDimitry Andric "Reads and parses a basic block sections profile.", false,
37145449b1SDimitry Andric false)
38145449b1SDimitry Andric
39b1c73532SDimitry Andric Expected<UniqueBBID>
parseUniqueBBID(StringRef S) const40b1c73532SDimitry Andric BasicBlockSectionsProfileReader::parseUniqueBBID(StringRef S) const {
41b1c73532SDimitry Andric SmallVector<StringRef, 2> Parts;
42b1c73532SDimitry Andric S.split(Parts, '.');
43b1c73532SDimitry Andric if (Parts.size() > 2)
44b1c73532SDimitry Andric return createProfileParseError(Twine("unable to parse basic block id: '") +
45b1c73532SDimitry Andric S + "'");
46b1c73532SDimitry Andric unsigned long long BaseBBID;
47b1c73532SDimitry Andric if (getAsUnsignedInteger(Parts[0], 10, BaseBBID))
48b1c73532SDimitry Andric return createProfileParseError(
49b1c73532SDimitry Andric Twine("unable to parse BB id: '" + Parts[0]) +
50b1c73532SDimitry Andric "': unsigned integer expected");
51b1c73532SDimitry Andric unsigned long long CloneID = 0;
52b1c73532SDimitry Andric if (Parts.size() > 1 && getAsUnsignedInteger(Parts[1], 10, CloneID))
53b1c73532SDimitry Andric return createProfileParseError(Twine("unable to parse clone id: '") +
54b1c73532SDimitry Andric Parts[1] + "': unsigned integer expected");
55b1c73532SDimitry Andric return UniqueBBID{static_cast<unsigned>(BaseBBID),
56b1c73532SDimitry Andric static_cast<unsigned>(CloneID)};
57b1c73532SDimitry Andric }
58b1c73532SDimitry Andric
isFunctionHot(StringRef FuncName) const59145449b1SDimitry Andric bool BasicBlockSectionsProfileReader::isFunctionHot(StringRef FuncName) const {
60b1c73532SDimitry Andric return getClusterInfoForFunction(FuncName).first;
61145449b1SDimitry Andric }
62145449b1SDimitry Andric
63145449b1SDimitry Andric std::pair<bool, SmallVector<BBClusterInfo>>
getClusterInfoForFunction(StringRef FuncName) const64b1c73532SDimitry Andric BasicBlockSectionsProfileReader::getClusterInfoForFunction(
65145449b1SDimitry Andric StringRef FuncName) const {
66b1c73532SDimitry Andric auto R = ProgramPathAndClusterInfo.find(getAliasName(FuncName));
67b1c73532SDimitry Andric return R != ProgramPathAndClusterInfo.end()
68b1c73532SDimitry Andric ? std::pair(true, R->second.ClusterInfo)
69b1c73532SDimitry Andric : std::pair(false, SmallVector<BBClusterInfo>());
70b1c73532SDimitry Andric }
71b1c73532SDimitry Andric
72b1c73532SDimitry Andric SmallVector<SmallVector<unsigned>>
getClonePathsForFunction(StringRef FuncName) const73b1c73532SDimitry Andric BasicBlockSectionsProfileReader::getClonePathsForFunction(
74b1c73532SDimitry Andric StringRef FuncName) const {
75b1c73532SDimitry Andric return ProgramPathAndClusterInfo.lookup(getAliasName(FuncName)).ClonePaths;
76b1c73532SDimitry Andric }
77b1c73532SDimitry Andric
78b1c73532SDimitry Andric // Reads the version 1 basic block sections profile. Profile for each function
79b1c73532SDimitry Andric // is encoded as follows:
80b1c73532SDimitry Andric // m <module_name>
81b1c73532SDimitry Andric // f <function_name_1> <function_name_2> ...
82b1c73532SDimitry Andric // c <bb_id_1> <bb_id_2> <bb_id_3>
83b1c73532SDimitry Andric // c <bb_id_4> <bb_id_5>
84b1c73532SDimitry Andric // ...
85b1c73532SDimitry Andric // Module name specifier (starting with 'm') is optional and allows
86b1c73532SDimitry Andric // distinguishing profile for internal-linkage functions with the same name. If
87b1c73532SDimitry Andric // not specified, it will apply to any function with the same name. Function
88b1c73532SDimitry Andric // name specifier (starting with 'f') can specify multiple function name
89b1c73532SDimitry Andric // aliases. Basic block clusters are specified by 'c' and specify the cluster of
90b1c73532SDimitry Andric // basic blocks, and the internal order in which they must be placed in the same
91b1c73532SDimitry Andric // section.
92b1c73532SDimitry Andric // This profile can also specify cloning paths which instruct the compiler to
93b1c73532SDimitry Andric // clone basic blocks along a path. The cloned blocks are then specified in the
94b1c73532SDimitry Andric // cluster information.
95b1c73532SDimitry Andric // The following profile lists two cloning paths (starting with 'p') for
96b1c73532SDimitry Andric // function bar and places the total 9 blocks within two clusters. The first two
97b1c73532SDimitry Andric // blocks of a cloning path specify the edge along which the path is cloned. For
98b1c73532SDimitry Andric // instance, path 1 (1 -> 3 -> 4) instructs that 3 and 4 must be cloned along
99b1c73532SDimitry Andric // the edge 1->3. Within the given clusters, each cloned block is identified by
100b1c73532SDimitry Andric // "<original block id>.<clone id>". For instance, 3.1 represents the first
101b1c73532SDimitry Andric // clone of block 3. Original blocks are specified just with their block ids. A
102b1c73532SDimitry Andric // block cloned multiple times appears with distinct clone ids. The CFG for bar
103b1c73532SDimitry Andric // is shown below before and after cloning with its final clusters labeled.
104b1c73532SDimitry Andric //
105b1c73532SDimitry Andric // f main
106b1c73532SDimitry Andric // f bar
107b1c73532SDimitry Andric // p 1 3 4 # cloning path 1
108b1c73532SDimitry Andric // p 4 2 # cloning path 2
109b1c73532SDimitry Andric // c 1 3.1 4.1 6 # basic block cluster 1
110b1c73532SDimitry Andric // c 0 2 3 4 2.1 5 # basic block cluster 2
111b1c73532SDimitry Andric // ****************************************************************************
112b1c73532SDimitry Andric // function bar before and after cloning with basic block clusters shown.
113b1c73532SDimitry Andric // ****************************************************************************
114b1c73532SDimitry Andric // .... ..............
115b1c73532SDimitry Andric // 0 -------+ : 0 :---->: 1 ---> 3.1 :
116b1c73532SDimitry Andric // | | : | : :........ | :
117b1c73532SDimitry Andric // v v : v : : v :
118b1c73532SDimitry Andric // +--> 2 --> 5 1 ~~~~~~> +---: 2 : : 4.1: clsuter 1
119b1c73532SDimitry Andric // | | | | : | : : | :
120b1c73532SDimitry Andric // | v | | : v ....... : v :
121b1c73532SDimitry Andric // | 3 <------+ | : 3 <--+ : : 6 :
122b1c73532SDimitry Andric // | | | : | | : :....:
123b1c73532SDimitry Andric // | v | : v | :
124b1c73532SDimitry Andric // +--- 4 ---> 6 | : 4 | :
125b1c73532SDimitry Andric // | : | | :
126b1c73532SDimitry Andric // | : v | :
127b1c73532SDimitry Andric // | :2.1---+ : cluster 2
128b1c73532SDimitry Andric // | : | ......:
129b1c73532SDimitry Andric // | : v :
130b1c73532SDimitry Andric // +-->: 5 :
131b1c73532SDimitry Andric // ....
132b1c73532SDimitry Andric // ****************************************************************************
ReadV1Profile()133b1c73532SDimitry Andric Error BasicBlockSectionsProfileReader::ReadV1Profile() {
134b1c73532SDimitry Andric auto FI = ProgramPathAndClusterInfo.end();
135b1c73532SDimitry Andric
136b1c73532SDimitry Andric // Current cluster ID corresponding to this function.
137b1c73532SDimitry Andric unsigned CurrentCluster = 0;
138b1c73532SDimitry Andric // Current position in the current cluster.
139b1c73532SDimitry Andric unsigned CurrentPosition = 0;
140b1c73532SDimitry Andric
141b1c73532SDimitry Andric // Temporary set to ensure every basic block ID appears once in the clusters
142b1c73532SDimitry Andric // of a function.
143b1c73532SDimitry Andric DenseSet<UniqueBBID> FuncBBIDs;
144b1c73532SDimitry Andric
145b1c73532SDimitry Andric // Debug-info-based module filename for the current function. Empty string
146b1c73532SDimitry Andric // means no filename.
147b1c73532SDimitry Andric StringRef DIFilename;
148b1c73532SDimitry Andric
149b1c73532SDimitry Andric for (; !LineIt.is_at_eof(); ++LineIt) {
150b1c73532SDimitry Andric StringRef S(*LineIt);
151b1c73532SDimitry Andric char Specifier = S[0];
152b1c73532SDimitry Andric S = S.drop_front().trim();
153b1c73532SDimitry Andric SmallVector<StringRef, 4> Values;
154b1c73532SDimitry Andric S.split(Values, ' ');
155b1c73532SDimitry Andric switch (Specifier) {
156b1c73532SDimitry Andric case '@':
157b1c73532SDimitry Andric continue;
158b1c73532SDimitry Andric case 'm': // Module name speicifer.
159b1c73532SDimitry Andric if (Values.size() != 1) {
160b1c73532SDimitry Andric return createProfileParseError(Twine("invalid module name value: '") +
161b1c73532SDimitry Andric S + "'");
162b1c73532SDimitry Andric }
163b1c73532SDimitry Andric DIFilename = sys::path::remove_leading_dotslash(Values[0]);
164b1c73532SDimitry Andric continue;
165b1c73532SDimitry Andric case 'f': { // Function names specifier.
166b1c73532SDimitry Andric bool FunctionFound = any_of(Values, [&](StringRef Alias) {
167b1c73532SDimitry Andric auto It = FunctionNameToDIFilename.find(Alias);
168b1c73532SDimitry Andric // No match if this function name is not found in this module.
169b1c73532SDimitry Andric if (It == FunctionNameToDIFilename.end())
170b1c73532SDimitry Andric return false;
171b1c73532SDimitry Andric // Return a match if debug-info-filename is not specified. Otherwise,
172b1c73532SDimitry Andric // check for equality.
173ac9a064cSDimitry Andric return DIFilename.empty() || It->second == DIFilename;
174b1c73532SDimitry Andric });
175b1c73532SDimitry Andric if (!FunctionFound) {
176b1c73532SDimitry Andric // Skip the following profile by setting the profile iterator (FI) to
177b1c73532SDimitry Andric // the past-the-end element.
178b1c73532SDimitry Andric FI = ProgramPathAndClusterInfo.end();
179b1c73532SDimitry Andric DIFilename = "";
180b1c73532SDimitry Andric continue;
181b1c73532SDimitry Andric }
182b1c73532SDimitry Andric for (size_t i = 1; i < Values.size(); ++i)
183b1c73532SDimitry Andric FuncAliasMap.try_emplace(Values[i], Values.front());
184b1c73532SDimitry Andric
185b1c73532SDimitry Andric // Prepare for parsing clusters of this function name.
186b1c73532SDimitry Andric // Start a new cluster map for this function name.
187b1c73532SDimitry Andric auto R = ProgramPathAndClusterInfo.try_emplace(Values.front());
188b1c73532SDimitry Andric // Report error when multiple profiles have been specified for the same
189b1c73532SDimitry Andric // function.
190b1c73532SDimitry Andric if (!R.second)
191b1c73532SDimitry Andric return createProfileParseError("duplicate profile for function '" +
192b1c73532SDimitry Andric Values.front() + "'");
193b1c73532SDimitry Andric FI = R.first;
194b1c73532SDimitry Andric CurrentCluster = 0;
195b1c73532SDimitry Andric FuncBBIDs.clear();
196b1c73532SDimitry Andric // We won't need DIFilename anymore. Clean it up to avoid its application
197b1c73532SDimitry Andric // on the next function.
198b1c73532SDimitry Andric DIFilename = "";
199b1c73532SDimitry Andric continue;
200b1c73532SDimitry Andric }
201b1c73532SDimitry Andric case 'c': // Basic block cluster specifier.
202b1c73532SDimitry Andric // Skip the profile when we the profile iterator (FI) refers to the
203b1c73532SDimitry Andric // past-the-end element.
204b1c73532SDimitry Andric if (FI == ProgramPathAndClusterInfo.end())
205b1c73532SDimitry Andric continue;
206b1c73532SDimitry Andric // Reset current cluster position.
207b1c73532SDimitry Andric CurrentPosition = 0;
208b1c73532SDimitry Andric for (auto BasicBlockIDStr : Values) {
209b1c73532SDimitry Andric auto BasicBlockID = parseUniqueBBID(BasicBlockIDStr);
210b1c73532SDimitry Andric if (!BasicBlockID)
211b1c73532SDimitry Andric return BasicBlockID.takeError();
212b1c73532SDimitry Andric if (!FuncBBIDs.insert(*BasicBlockID).second)
213b1c73532SDimitry Andric return createProfileParseError(
214b1c73532SDimitry Andric Twine("duplicate basic block id found '") + BasicBlockIDStr +
215b1c73532SDimitry Andric "'");
216b1c73532SDimitry Andric
217b1c73532SDimitry Andric FI->second.ClusterInfo.emplace_back(BBClusterInfo{
218b1c73532SDimitry Andric *std::move(BasicBlockID), CurrentCluster, CurrentPosition++});
219b1c73532SDimitry Andric }
220b1c73532SDimitry Andric CurrentCluster++;
221b1c73532SDimitry Andric continue;
222b1c73532SDimitry Andric case 'p': { // Basic block cloning path specifier.
223b1c73532SDimitry Andric // Skip the profile when we the profile iterator (FI) refers to the
224b1c73532SDimitry Andric // past-the-end element.
225b1c73532SDimitry Andric if (FI == ProgramPathAndClusterInfo.end())
226b1c73532SDimitry Andric continue;
227b1c73532SDimitry Andric SmallSet<unsigned, 5> BBsInPath;
228b1c73532SDimitry Andric FI->second.ClonePaths.push_back({});
229b1c73532SDimitry Andric for (size_t I = 0; I < Values.size(); ++I) {
230b1c73532SDimitry Andric auto BaseBBIDStr = Values[I];
231b1c73532SDimitry Andric unsigned long long BaseBBID = 0;
232b1c73532SDimitry Andric if (getAsUnsignedInteger(BaseBBIDStr, 10, BaseBBID))
233b1c73532SDimitry Andric return createProfileParseError(Twine("unsigned integer expected: '") +
234b1c73532SDimitry Andric BaseBBIDStr + "'");
235b1c73532SDimitry Andric if (I != 0 && !BBsInPath.insert(BaseBBID).second)
236b1c73532SDimitry Andric return createProfileParseError(
237b1c73532SDimitry Andric Twine("duplicate cloned block in path: '") + BaseBBIDStr + "'");
238b1c73532SDimitry Andric FI->second.ClonePaths.back().push_back(BaseBBID);
239b1c73532SDimitry Andric }
240b1c73532SDimitry Andric continue;
241b1c73532SDimitry Andric }
242b1c73532SDimitry Andric default:
243b1c73532SDimitry Andric return createProfileParseError(Twine("invalid specifier: '") +
244b1c73532SDimitry Andric Twine(Specifier) + "'");
245b1c73532SDimitry Andric }
246b1c73532SDimitry Andric llvm_unreachable("should not break from this switch statement");
247b1c73532SDimitry Andric }
248b1c73532SDimitry Andric return Error::success();
249b1c73532SDimitry Andric }
250b1c73532SDimitry Andric
ReadV0Profile()251b1c73532SDimitry Andric Error BasicBlockSectionsProfileReader::ReadV0Profile() {
252b1c73532SDimitry Andric auto FI = ProgramPathAndClusterInfo.end();
253b1c73532SDimitry Andric // Current cluster ID corresponding to this function.
254b1c73532SDimitry Andric unsigned CurrentCluster = 0;
255b1c73532SDimitry Andric // Current position in the current cluster.
256b1c73532SDimitry Andric unsigned CurrentPosition = 0;
257b1c73532SDimitry Andric
258b1c73532SDimitry Andric // Temporary set to ensure every basic block ID appears once in the clusters
259b1c73532SDimitry Andric // of a function.
260b1c73532SDimitry Andric SmallSet<unsigned, 4> FuncBBIDs;
261b1c73532SDimitry Andric
262b1c73532SDimitry Andric for (; !LineIt.is_at_eof(); ++LineIt) {
263b1c73532SDimitry Andric StringRef S(*LineIt);
264b1c73532SDimitry Andric if (S[0] == '@')
265b1c73532SDimitry Andric continue;
266b1c73532SDimitry Andric // Check for the leading "!"
267b1c73532SDimitry Andric if (!S.consume_front("!") || S.empty())
268b1c73532SDimitry Andric break;
269b1c73532SDimitry Andric // Check for second "!" which indicates a cluster of basic blocks.
270b1c73532SDimitry Andric if (S.consume_front("!")) {
271b1c73532SDimitry Andric // Skip the profile when we the profile iterator (FI) refers to the
272b1c73532SDimitry Andric // past-the-end element.
273b1c73532SDimitry Andric if (FI == ProgramPathAndClusterInfo.end())
274b1c73532SDimitry Andric continue;
275b1c73532SDimitry Andric SmallVector<StringRef, 4> BBIDs;
276b1c73532SDimitry Andric S.split(BBIDs, ' ');
277b1c73532SDimitry Andric // Reset current cluster position.
278b1c73532SDimitry Andric CurrentPosition = 0;
279b1c73532SDimitry Andric for (auto BBIDStr : BBIDs) {
280b1c73532SDimitry Andric unsigned long long BBID;
281b1c73532SDimitry Andric if (getAsUnsignedInteger(BBIDStr, 10, BBID))
282b1c73532SDimitry Andric return createProfileParseError(Twine("unsigned integer expected: '") +
283b1c73532SDimitry Andric BBIDStr + "'");
284b1c73532SDimitry Andric if (!FuncBBIDs.insert(BBID).second)
285b1c73532SDimitry Andric return createProfileParseError(
286b1c73532SDimitry Andric Twine("duplicate basic block id found '") + BBIDStr + "'");
287b1c73532SDimitry Andric
288b1c73532SDimitry Andric FI->second.ClusterInfo.emplace_back(
289b1c73532SDimitry Andric BBClusterInfo({{static_cast<unsigned>(BBID), 0},
290b1c73532SDimitry Andric CurrentCluster,
291b1c73532SDimitry Andric CurrentPosition++}));
292b1c73532SDimitry Andric }
293b1c73532SDimitry Andric CurrentCluster++;
294b1c73532SDimitry Andric } else {
295b1c73532SDimitry Andric // This is a function name specifier. It may include a debug info filename
296b1c73532SDimitry Andric // specifier starting with `M=`.
297b1c73532SDimitry Andric auto [AliasesStr, DIFilenameStr] = S.split(' ');
298b1c73532SDimitry Andric SmallString<128> DIFilename;
299312c0ed1SDimitry Andric if (DIFilenameStr.starts_with("M=")) {
300b1c73532SDimitry Andric DIFilename =
301b1c73532SDimitry Andric sys::path::remove_leading_dotslash(DIFilenameStr.substr(2));
302b1c73532SDimitry Andric if (DIFilename.empty())
303b1c73532SDimitry Andric return createProfileParseError("empty module name specifier");
304b1c73532SDimitry Andric } else if (!DIFilenameStr.empty()) {
305b1c73532SDimitry Andric return createProfileParseError("unknown string found: '" +
306b1c73532SDimitry Andric DIFilenameStr + "'");
307b1c73532SDimitry Andric }
308b1c73532SDimitry Andric // Function aliases are separated using '/'. We use the first function
309b1c73532SDimitry Andric // name for the cluster info mapping and delegate all other aliases to
310b1c73532SDimitry Andric // this one.
311b1c73532SDimitry Andric SmallVector<StringRef, 4> Aliases;
312b1c73532SDimitry Andric AliasesStr.split(Aliases, '/');
313b1c73532SDimitry Andric bool FunctionFound = any_of(Aliases, [&](StringRef Alias) {
314b1c73532SDimitry Andric auto It = FunctionNameToDIFilename.find(Alias);
315b1c73532SDimitry Andric // No match if this function name is not found in this module.
316b1c73532SDimitry Andric if (It == FunctionNameToDIFilename.end())
317b1c73532SDimitry Andric return false;
318b1c73532SDimitry Andric // Return a match if debug-info-filename is not specified. Otherwise,
319b1c73532SDimitry Andric // check for equality.
320ac9a064cSDimitry Andric return DIFilename.empty() || It->second == DIFilename;
321b1c73532SDimitry Andric });
322b1c73532SDimitry Andric if (!FunctionFound) {
323b1c73532SDimitry Andric // Skip the following profile by setting the profile iterator (FI) to
324b1c73532SDimitry Andric // the past-the-end element.
325b1c73532SDimitry Andric FI = ProgramPathAndClusterInfo.end();
326b1c73532SDimitry Andric continue;
327b1c73532SDimitry Andric }
328b1c73532SDimitry Andric for (size_t i = 1; i < Aliases.size(); ++i)
329b1c73532SDimitry Andric FuncAliasMap.try_emplace(Aliases[i], Aliases.front());
330b1c73532SDimitry Andric
331b1c73532SDimitry Andric // Prepare for parsing clusters of this function name.
332b1c73532SDimitry Andric // Start a new cluster map for this function name.
333b1c73532SDimitry Andric auto R = ProgramPathAndClusterInfo.try_emplace(Aliases.front());
334b1c73532SDimitry Andric // Report error when multiple profiles have been specified for the same
335b1c73532SDimitry Andric // function.
336b1c73532SDimitry Andric if (!R.second)
337b1c73532SDimitry Andric return createProfileParseError("duplicate profile for function '" +
338b1c73532SDimitry Andric Aliases.front() + "'");
339b1c73532SDimitry Andric FI = R.first;
340b1c73532SDimitry Andric CurrentCluster = 0;
341b1c73532SDimitry Andric FuncBBIDs.clear();
342b1c73532SDimitry Andric }
343b1c73532SDimitry Andric }
344b1c73532SDimitry Andric return Error::success();
345145449b1SDimitry Andric }
346145449b1SDimitry Andric
347145449b1SDimitry Andric // Basic Block Sections can be enabled for a subset of machine basic blocks.
348145449b1SDimitry Andric // This is done by passing a file containing names of functions for which basic
349145449b1SDimitry Andric // block sections are desired. Additionally, machine basic block ids of the
350145449b1SDimitry Andric // functions can also be specified for a finer granularity. Moreover, a cluster
351145449b1SDimitry Andric // of basic blocks could be assigned to the same section.
3527fa27ce4SDimitry Andric // Optionally, a debug-info filename can be specified for each function to allow
3537fa27ce4SDimitry Andric // distinguishing internal-linkage functions of the same name.
354145449b1SDimitry Andric // A file with basic block sections for all of function main and three blocks
355145449b1SDimitry Andric // for function foo (of which 1 and 2 are placed in a cluster) looks like this:
3567fa27ce4SDimitry Andric // (Profile for function foo is only loaded when its debug-info filename
3577fa27ce4SDimitry Andric // matches 'path/to/foo_file.cc').
358145449b1SDimitry Andric // ----------------------------
359145449b1SDimitry Andric // list.txt:
360145449b1SDimitry Andric // !main
3617fa27ce4SDimitry Andric // !foo M=path/to/foo_file.cc
362145449b1SDimitry Andric // !!1 2
363145449b1SDimitry Andric // !!4
ReadProfile()3647fa27ce4SDimitry Andric Error BasicBlockSectionsProfileReader::ReadProfile() {
365145449b1SDimitry Andric assert(MBuf);
366145449b1SDimitry Andric
367b1c73532SDimitry Andric unsigned long long Version = 0;
368b1c73532SDimitry Andric StringRef FirstLine(*LineIt);
369b1c73532SDimitry Andric if (FirstLine.consume_front("v")) {
370b1c73532SDimitry Andric if (getAsUnsignedInteger(FirstLine, 10, Version)) {
371b1c73532SDimitry Andric return createProfileParseError(Twine("version number expected: '") +
372b1c73532SDimitry Andric FirstLine + "'");
373145449b1SDimitry Andric }
374b1c73532SDimitry Andric if (Version > 1) {
375b1c73532SDimitry Andric return createProfileParseError(Twine("invalid profile version: ") +
376b1c73532SDimitry Andric Twine(Version));
3777fa27ce4SDimitry Andric }
378b1c73532SDimitry Andric ++LineIt;
3797fa27ce4SDimitry Andric }
380145449b1SDimitry Andric
381b1c73532SDimitry Andric switch (Version) {
382b1c73532SDimitry Andric case 0:
383b1c73532SDimitry Andric // TODO: Deprecate V0 once V1 is fully integrated downstream.
384b1c73532SDimitry Andric return ReadV0Profile();
385b1c73532SDimitry Andric case 1:
386b1c73532SDimitry Andric return ReadV1Profile();
387b1c73532SDimitry Andric default:
388b1c73532SDimitry Andric llvm_unreachable("Invalid profile version.");
389145449b1SDimitry Andric }
390145449b1SDimitry Andric }
391145449b1SDimitry Andric
doInitialization(Module & M)392aca2e42cSDimitry Andric bool BasicBlockSectionsProfileReaderWrapperPass::doInitialization(Module &M) {
393aca2e42cSDimitry Andric if (!BBSPR.MBuf)
3947fa27ce4SDimitry Andric return false;
3957fa27ce4SDimitry Andric // Get the function name to debug info filename mapping.
396aca2e42cSDimitry Andric BBSPR.FunctionNameToDIFilename.clear();
3977fa27ce4SDimitry Andric for (const Function &F : M) {
3987fa27ce4SDimitry Andric SmallString<128> DIFilename;
3997fa27ce4SDimitry Andric if (F.isDeclaration())
4007fa27ce4SDimitry Andric continue;
4017fa27ce4SDimitry Andric DISubprogram *Subprogram = F.getSubprogram();
4027fa27ce4SDimitry Andric if (Subprogram) {
4037fa27ce4SDimitry Andric llvm::DICompileUnit *CU = Subprogram->getUnit();
4047fa27ce4SDimitry Andric if (CU)
4057fa27ce4SDimitry Andric DIFilename = sys::path::remove_leading_dotslash(CU->getFilename());
4067fa27ce4SDimitry Andric }
4077fa27ce4SDimitry Andric [[maybe_unused]] bool inserted =
408aca2e42cSDimitry Andric BBSPR.FunctionNameToDIFilename.try_emplace(F.getName(), DIFilename)
409aca2e42cSDimitry Andric .second;
4107fa27ce4SDimitry Andric assert(inserted);
4117fa27ce4SDimitry Andric }
412aca2e42cSDimitry Andric if (auto Err = BBSPR.ReadProfile())
413145449b1SDimitry Andric report_fatal_error(std::move(Err));
4147fa27ce4SDimitry Andric return false;
415145449b1SDimitry Andric }
416145449b1SDimitry Andric
417aca2e42cSDimitry Andric AnalysisKey BasicBlockSectionsProfileReaderAnalysis::Key;
418aca2e42cSDimitry Andric
419aca2e42cSDimitry Andric BasicBlockSectionsProfileReader
run(Function & F,FunctionAnalysisManager & AM)420aca2e42cSDimitry Andric BasicBlockSectionsProfileReaderAnalysis::run(Function &F,
421aca2e42cSDimitry Andric FunctionAnalysisManager &AM) {
422aca2e42cSDimitry Andric return BasicBlockSectionsProfileReader(TM->getBBSectionsFuncListBuf());
423aca2e42cSDimitry Andric }
424aca2e42cSDimitry Andric
isFunctionHot(StringRef FuncName) const425aca2e42cSDimitry Andric bool BasicBlockSectionsProfileReaderWrapperPass::isFunctionHot(
426aca2e42cSDimitry Andric StringRef FuncName) const {
427aca2e42cSDimitry Andric return BBSPR.isFunctionHot(FuncName);
428aca2e42cSDimitry Andric }
429aca2e42cSDimitry Andric
430aca2e42cSDimitry Andric std::pair<bool, SmallVector<BBClusterInfo>>
getClusterInfoForFunction(StringRef FuncName) const431aca2e42cSDimitry Andric BasicBlockSectionsProfileReaderWrapperPass::getClusterInfoForFunction(
432aca2e42cSDimitry Andric StringRef FuncName) const {
433aca2e42cSDimitry Andric return BBSPR.getClusterInfoForFunction(FuncName);
434aca2e42cSDimitry Andric }
435aca2e42cSDimitry Andric
436aca2e42cSDimitry Andric SmallVector<SmallVector<unsigned>>
getClonePathsForFunction(StringRef FuncName) const437aca2e42cSDimitry Andric BasicBlockSectionsProfileReaderWrapperPass::getClonePathsForFunction(
438aca2e42cSDimitry Andric StringRef FuncName) const {
439aca2e42cSDimitry Andric return BBSPR.getClonePathsForFunction(FuncName);
440aca2e42cSDimitry Andric }
441aca2e42cSDimitry Andric
442aca2e42cSDimitry Andric BasicBlockSectionsProfileReader &
getBBSPR()443aca2e42cSDimitry Andric BasicBlockSectionsProfileReaderWrapperPass::getBBSPR() {
444aca2e42cSDimitry Andric return BBSPR;
445aca2e42cSDimitry Andric }
446aca2e42cSDimitry Andric
createBasicBlockSectionsProfileReaderWrapperPass(const MemoryBuffer * Buf)447aca2e42cSDimitry Andric ImmutablePass *llvm::createBasicBlockSectionsProfileReaderWrapperPass(
448aca2e42cSDimitry Andric const MemoryBuffer *Buf) {
449aca2e42cSDimitry Andric return new BasicBlockSectionsProfileReaderWrapperPass(Buf);
450145449b1SDimitry Andric }
451