xref: /src/contrib/llvm-project/llvm/lib/CodeGen/BasicBlockSectionsProfileReader.cpp (revision 0fca6ea1d4eea4c934cfff25ac9ee8ad6fe95583)
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