xref: /llvm-project/llvm/lib/CodeGen/BasicBlockSectionsProfileReader.cpp (revision aaa8a8000009890b79effb0d0f3c6f989a3d5563)
108cc0585SRahman Lavaee //===-- BasicBlockSectionsProfileReader.cpp -------------------------------===//
208cc0585SRahman Lavaee //
308cc0585SRahman Lavaee // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
408cc0585SRahman Lavaee // See https://llvm.org/LICENSE.txt for license information.
508cc0585SRahman Lavaee // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
608cc0585SRahman Lavaee //
708cc0585SRahman Lavaee //===----------------------------------------------------------------------===//
808cc0585SRahman Lavaee //
908cc0585SRahman Lavaee // Implementation of the basic block sections profile reader pass. It parses
1008cc0585SRahman Lavaee // and stores the basic block sections profile file (which is specified via the
1108cc0585SRahman Lavaee // `-basic-block-sections` flag).
1208cc0585SRahman Lavaee //
1308cc0585SRahman Lavaee //===----------------------------------------------------------------------===//
1408cc0585SRahman Lavaee 
1508cc0585SRahman Lavaee #include "llvm/CodeGen/BasicBlockSectionsProfileReader.h"
1628b91268SRahman Lavaee #include "llvm/ADT/DenseSet.h"
1708cc0585SRahman Lavaee #include "llvm/ADT/SmallSet.h"
18c13b046dSRahman Lavaee #include "llvm/ADT/SmallString.h"
1908cc0585SRahman Lavaee #include "llvm/ADT/SmallVector.h"
2008cc0585SRahman Lavaee #include "llvm/ADT/StringMap.h"
2108cc0585SRahman Lavaee #include "llvm/ADT/StringRef.h"
22c13b046dSRahman Lavaee #include "llvm/IR/DebugInfoMetadata.h"
236ac71a01SRahman Lavaee #include "llvm/Pass.h"
2408cc0585SRahman Lavaee #include "llvm/Support/Error.h"
256ac71a01SRahman Lavaee #include "llvm/Support/ErrorHandling.h"
2608cc0585SRahman Lavaee #include "llvm/Support/LineIterator.h"
2708cc0585SRahman Lavaee #include "llvm/Support/MemoryBuffer.h"
28c13b046dSRahman Lavaee #include "llvm/Support/Path.h"
29c13b046dSRahman Lavaee #include <llvm/ADT/STLExtras.h>
3008cc0585SRahman Lavaee 
3108cc0585SRahman Lavaee using namespace llvm;
3208cc0585SRahman Lavaee 
33f1ec0d12SNick Anderson char BasicBlockSectionsProfileReaderWrapperPass::ID = 0;
34f1ec0d12SNick Anderson INITIALIZE_PASS(BasicBlockSectionsProfileReaderWrapperPass,
35f1ec0d12SNick Anderson                 "bbsections-profile-reader",
3608cc0585SRahman Lavaee                 "Reads and parses a basic block sections profile.", false,
3708cc0585SRahman Lavaee                 false)
3808cc0585SRahman Lavaee 
39f70e39ecSRahman Lavaee Expected<UniqueBBID>
parseUniqueBBID(StringRef S) const40f70e39ecSRahman Lavaee BasicBlockSectionsProfileReader::parseUniqueBBID(StringRef S) const {
4128b91268SRahman Lavaee   SmallVector<StringRef, 2> Parts;
4228b91268SRahman Lavaee   S.split(Parts, '.');
4328b91268SRahman Lavaee   if (Parts.size() > 2)
4428b91268SRahman Lavaee     return createProfileParseError(Twine("unable to parse basic block id: '") +
4528b91268SRahman Lavaee                                    S + "'");
46f70e39ecSRahman Lavaee   unsigned long long BaseBBID;
47f70e39ecSRahman Lavaee   if (getAsUnsignedInteger(Parts[0], 10, BaseBBID))
4828b91268SRahman Lavaee     return createProfileParseError(
4928b91268SRahman Lavaee         Twine("unable to parse BB id: '" + Parts[0]) +
5028b91268SRahman Lavaee         "': unsigned integer expected");
5128b91268SRahman Lavaee   unsigned long long CloneID = 0;
5228b91268SRahman Lavaee   if (Parts.size() > 1 && getAsUnsignedInteger(Parts[1], 10, CloneID))
5328b91268SRahman Lavaee     return createProfileParseError(Twine("unable to parse clone id: '") +
5428b91268SRahman Lavaee                                    Parts[1] + "': unsigned integer expected");
55f70e39ecSRahman Lavaee   return UniqueBBID{static_cast<unsigned>(BaseBBID),
5628b91268SRahman Lavaee                     static_cast<unsigned>(CloneID)};
5708cc0585SRahman Lavaee }
5808cc0585SRahman Lavaee 
isFunctionHot(StringRef FuncName) const5928b91268SRahman Lavaee bool BasicBlockSectionsProfileReader::isFunctionHot(StringRef FuncName) const {
60f70e39ecSRahman Lavaee   return getClusterInfoForFunction(FuncName).first;
6128b91268SRahman Lavaee }
6228b91268SRahman Lavaee 
63f70e39ecSRahman Lavaee std::pair<bool, SmallVector<BBClusterInfo>>
getClusterInfoForFunction(StringRef FuncName) const64f70e39ecSRahman Lavaee BasicBlockSectionsProfileReader::getClusterInfoForFunction(
6508cc0585SRahman Lavaee     StringRef FuncName) const {
6628b91268SRahman Lavaee   auto R = ProgramPathAndClusterInfo.find(getAliasName(FuncName));
6728b91268SRahman Lavaee   return R != ProgramPathAndClusterInfo.end()
68f70e39ecSRahman Lavaee              ? std::pair(true, R->second.ClusterInfo)
69f70e39ecSRahman Lavaee              : std::pair(false, SmallVector<BBClusterInfo>());
70f70e39ecSRahman Lavaee }
71f70e39ecSRahman Lavaee 
72f70e39ecSRahman Lavaee SmallVector<SmallVector<unsigned>>
getClonePathsForFunction(StringRef FuncName) const73f70e39ecSRahman Lavaee BasicBlockSectionsProfileReader::getClonePathsForFunction(
74f70e39ecSRahman Lavaee     StringRef FuncName) const {
75f70e39ecSRahman Lavaee   return ProgramPathAndClusterInfo.lookup(getAliasName(FuncName)).ClonePaths;
7608cc0585SRahman Lavaee }
7708cc0585SRahman Lavaee 
786ac71a01SRahman Lavaee // Reads the version 1 basic block sections profile. Profile for each function
796ac71a01SRahman Lavaee // is encoded as follows:
806ac71a01SRahman Lavaee //   m <module_name>
816ac71a01SRahman Lavaee //   f <function_name_1> <function_name_2> ...
826ac71a01SRahman Lavaee //   c <bb_id_1> <bb_id_2> <bb_id_3>
836ac71a01SRahman Lavaee //   c <bb_id_4> <bb_id_5>
846ac71a01SRahman Lavaee //   ...
856ac71a01SRahman Lavaee // Module name specifier (starting with 'm') is optional and allows
866ac71a01SRahman Lavaee // distinguishing profile for internal-linkage functions with the same name. If
876ac71a01SRahman Lavaee // not specified, it will apply to any function with the same name. Function
886ac71a01SRahman Lavaee // name specifier (starting with 'f') can specify multiple function name
896ac71a01SRahman Lavaee // aliases. Basic block clusters are specified by 'c' and specify the cluster of
906ac71a01SRahman Lavaee // basic blocks, and the internal order in which they must be placed in the same
916ac71a01SRahman Lavaee // section.
9228b91268SRahman Lavaee // This profile can also specify cloning paths which instruct the compiler to
9328b91268SRahman Lavaee // clone basic blocks along a path. The cloned blocks are then specified in the
9428b91268SRahman Lavaee // cluster information.
9528b91268SRahman Lavaee // The following profile lists two cloning paths (starting with 'p') for
9628b91268SRahman Lavaee // function bar and places the total 9 blocks within two clusters. The first two
9728b91268SRahman Lavaee // blocks of a cloning path specify the edge along which the path is cloned. For
9828b91268SRahman Lavaee // instance, path 1 (1 -> 3 -> 4) instructs that 3 and 4 must be cloned along
9928b91268SRahman Lavaee // the edge 1->3. Within the given clusters, each cloned block is identified by
10028b91268SRahman Lavaee // "<original block id>.<clone id>". For instance, 3.1 represents the first
10128b91268SRahman Lavaee // clone of block 3. Original blocks are specified just with their block ids. A
10228b91268SRahman Lavaee // block cloned multiple times appears with distinct clone ids. The CFG for bar
10328b91268SRahman Lavaee // is shown below before and after cloning with its final clusters labeled.
10428b91268SRahman Lavaee //
10528b91268SRahman Lavaee // f main
10628b91268SRahman Lavaee // f bar
10728b91268SRahman Lavaee // p 1 3 4           # cloning path 1
10828b91268SRahman Lavaee // p 4 2             # cloning path 2
10928b91268SRahman Lavaee // c 1 3.1 4.1 6     # basic block cluster 1
11028b91268SRahman Lavaee // c 0 2 3 4 2.1 5   # basic block cluster 2
11128b91268SRahman Lavaee // ****************************************************************************
11228b91268SRahman Lavaee // function bar before and after cloning with basic block clusters shown.
11328b91268SRahman Lavaee // ****************************************************************************
11428b91268SRahman Lavaee //                                ....      ..............
11528b91268SRahman Lavaee //      0 -------+                : 0 :---->: 1 ---> 3.1 :
11628b91268SRahman Lavaee //      |        |                : | :     :........ |  :
11728b91268SRahman Lavaee //      v        v                : v :             : v  :
11828b91268SRahman Lavaee // +--> 2 --> 5  1   ~~~~~~>  +---: 2 :             : 4.1: clsuter 1
11928b91268SRahman Lavaee // |    |        |            |   : | :             : |  :
12028b91268SRahman Lavaee // |    v        |            |   : v .......       : v  :
12128b91268SRahman Lavaee // |    3 <------+            |   : 3 <--+  :       : 6  :
12228b91268SRahman Lavaee // |    |                     |   : |    |  :       :....:
12328b91268SRahman Lavaee // |    v                     |   : v    |  :
12428b91268SRahman Lavaee // +--- 4 ---> 6              |   : 4    |  :
12528b91268SRahman Lavaee //                            |   : |    |  :
12628b91268SRahman Lavaee //                            |   : v    |  :
12728b91268SRahman Lavaee //                            |   :2.1---+  : cluster 2
12828b91268SRahman Lavaee //                            |   : | ......:
12928b91268SRahman Lavaee //                            |   : v :
13028b91268SRahman Lavaee //                            +-->: 5 :
13128b91268SRahman Lavaee //                                ....
13228b91268SRahman Lavaee // ****************************************************************************
ReadV1Profile()1336ac71a01SRahman Lavaee Error BasicBlockSectionsProfileReader::ReadV1Profile() {
13428b91268SRahman Lavaee   auto FI = ProgramPathAndClusterInfo.end();
13508cc0585SRahman Lavaee 
1366ac71a01SRahman Lavaee   // Current cluster ID corresponding to this function.
1376ac71a01SRahman Lavaee   unsigned CurrentCluster = 0;
1386ac71a01SRahman Lavaee   // Current position in the current cluster.
1396ac71a01SRahman Lavaee   unsigned CurrentPosition = 0;
14008cc0585SRahman Lavaee 
1416ac71a01SRahman Lavaee   // Temporary set to ensure every basic block ID appears once in the clusters
1426ac71a01SRahman Lavaee   // of a function.
143f70e39ecSRahman Lavaee   DenseSet<UniqueBBID> FuncBBIDs;
1446ac71a01SRahman Lavaee 
1456ac71a01SRahman Lavaee   // Debug-info-based module filename for the current function. Empty string
1466ac71a01SRahman Lavaee   // means no filename.
1476ac71a01SRahman Lavaee   StringRef DIFilename;
1486ac71a01SRahman Lavaee 
1496ac71a01SRahman Lavaee   for (; !LineIt.is_at_eof(); ++LineIt) {
1506ac71a01SRahman Lavaee     StringRef S(*LineIt);
1516ac71a01SRahman Lavaee     char Specifier = S[0];
1526ac71a01SRahman Lavaee     S = S.drop_front().trim();
1536ac71a01SRahman Lavaee     SmallVector<StringRef, 4> Values;
1546ac71a01SRahman Lavaee     S.split(Values, ' ');
1556ac71a01SRahman Lavaee     switch (Specifier) {
1566ac71a01SRahman Lavaee     case '@':
15728b91268SRahman Lavaee       continue;
1586ac71a01SRahman Lavaee     case 'm': // Module name speicifer.
1596ac71a01SRahman Lavaee       if (Values.size() != 1) {
1606ac71a01SRahman Lavaee         return createProfileParseError(Twine("invalid module name value: '") +
1616ac71a01SRahman Lavaee                                        S + "'");
1626ac71a01SRahman Lavaee       }
1636ac71a01SRahman Lavaee       DIFilename = sys::path::remove_leading_dotslash(Values[0]);
1646ac71a01SRahman Lavaee       continue;
1656ac71a01SRahman Lavaee     case 'f': { // Function names specifier.
1666ac71a01SRahman Lavaee       bool FunctionFound = any_of(Values, [&](StringRef Alias) {
1676ac71a01SRahman Lavaee         auto It = FunctionNameToDIFilename.find(Alias);
1686ac71a01SRahman Lavaee         // No match if this function name is not found in this module.
1696ac71a01SRahman Lavaee         if (It == FunctionNameToDIFilename.end())
1706ac71a01SRahman Lavaee           return false;
1716ac71a01SRahman Lavaee         // Return a match if debug-info-filename is not specified. Otherwise,
1726ac71a01SRahman Lavaee         // check for equality.
173*aaa8a800SKazu Hirata         return DIFilename.empty() || It->second == DIFilename;
1746ac71a01SRahman Lavaee       });
1756ac71a01SRahman Lavaee       if (!FunctionFound) {
1766ac71a01SRahman Lavaee         // Skip the following profile by setting the profile iterator (FI) to
1776ac71a01SRahman Lavaee         // the past-the-end element.
17828b91268SRahman Lavaee         FI = ProgramPathAndClusterInfo.end();
1796ac71a01SRahman Lavaee         DIFilename = "";
1806ac71a01SRahman Lavaee         continue;
1816ac71a01SRahman Lavaee       }
1826ac71a01SRahman Lavaee       for (size_t i = 1; i < Values.size(); ++i)
1836ac71a01SRahman Lavaee         FuncAliasMap.try_emplace(Values[i], Values.front());
1846ac71a01SRahman Lavaee 
1856ac71a01SRahman Lavaee       // Prepare for parsing clusters of this function name.
1866ac71a01SRahman Lavaee       // Start a new cluster map for this function name.
18728b91268SRahman Lavaee       auto R = ProgramPathAndClusterInfo.try_emplace(Values.front());
1886ac71a01SRahman Lavaee       // Report error when multiple profiles have been specified for the same
1896ac71a01SRahman Lavaee       // function.
1906ac71a01SRahman Lavaee       if (!R.second)
1916ac71a01SRahman Lavaee         return createProfileParseError("duplicate profile for function '" +
1926ac71a01SRahman Lavaee                                        Values.front() + "'");
1936ac71a01SRahman Lavaee       FI = R.first;
1946ac71a01SRahman Lavaee       CurrentCluster = 0;
1956ac71a01SRahman Lavaee       FuncBBIDs.clear();
1966ac71a01SRahman Lavaee       // We won't need DIFilename anymore. Clean it up to avoid its application
1976ac71a01SRahman Lavaee       // on the next function.
1986ac71a01SRahman Lavaee       DIFilename = "";
1996ac71a01SRahman Lavaee       continue;
2006ac71a01SRahman Lavaee     }
2016ac71a01SRahman Lavaee     case 'c': // Basic block cluster specifier.
2026ac71a01SRahman Lavaee       // Skip the profile when we the profile iterator (FI) refers to the
2036ac71a01SRahman Lavaee       // past-the-end element.
20428b91268SRahman Lavaee       if (FI == ProgramPathAndClusterInfo.end())
20528b91268SRahman Lavaee         continue;
2066ac71a01SRahman Lavaee       // Reset current cluster position.
2076ac71a01SRahman Lavaee       CurrentPosition = 0;
20828b91268SRahman Lavaee       for (auto BasicBlockIDStr : Values) {
209f70e39ecSRahman Lavaee         auto BasicBlockID = parseUniqueBBID(BasicBlockIDStr);
21028b91268SRahman Lavaee         if (!BasicBlockID)
21128b91268SRahman Lavaee           return BasicBlockID.takeError();
21228b91268SRahman Lavaee         if (!FuncBBIDs.insert(*BasicBlockID).second)
2136ac71a01SRahman Lavaee           return createProfileParseError(
21428b91268SRahman Lavaee               Twine("duplicate basic block id found '") + BasicBlockIDStr +
21528b91268SRahman Lavaee               "'");
2166ac71a01SRahman Lavaee 
217f70e39ecSRahman Lavaee         FI->second.ClusterInfo.emplace_back(BBClusterInfo{
21828b91268SRahman Lavaee             *std::move(BasicBlockID), CurrentCluster, CurrentPosition++});
2196ac71a01SRahman Lavaee       }
2206ac71a01SRahman Lavaee       CurrentCluster++;
2216ac71a01SRahman Lavaee       continue;
22228b91268SRahman Lavaee     case 'p': { // Basic block cloning path specifier.
223f70e39ecSRahman Lavaee       // Skip the profile when we the profile iterator (FI) refers to the
224f70e39ecSRahman Lavaee       // past-the-end element.
225f70e39ecSRahman Lavaee       if (FI == ProgramPathAndClusterInfo.end())
226f70e39ecSRahman Lavaee         continue;
22728b91268SRahman Lavaee       SmallSet<unsigned, 5> BBsInPath;
22828b91268SRahman Lavaee       FI->second.ClonePaths.push_back({});
22928b91268SRahman Lavaee       for (size_t I = 0; I < Values.size(); ++I) {
230f70e39ecSRahman Lavaee         auto BaseBBIDStr = Values[I];
231f70e39ecSRahman Lavaee         unsigned long long BaseBBID = 0;
232f70e39ecSRahman Lavaee         if (getAsUnsignedInteger(BaseBBIDStr, 10, BaseBBID))
23328b91268SRahman Lavaee           return createProfileParseError(Twine("unsigned integer expected: '") +
234f70e39ecSRahman Lavaee                                          BaseBBIDStr + "'");
235f70e39ecSRahman Lavaee         if (I != 0 && !BBsInPath.insert(BaseBBID).second)
23628b91268SRahman Lavaee           return createProfileParseError(
237f70e39ecSRahman Lavaee               Twine("duplicate cloned block in path: '") + BaseBBIDStr + "'");
238f70e39ecSRahman Lavaee         FI->second.ClonePaths.back().push_back(BaseBBID);
23928b91268SRahman Lavaee       }
24028b91268SRahman Lavaee       continue;
24128b91268SRahman Lavaee     }
2426ac71a01SRahman Lavaee     default:
2436ac71a01SRahman Lavaee       return createProfileParseError(Twine("invalid specifier: '") +
2446ac71a01SRahman Lavaee                                      Twine(Specifier) + "'");
2456ac71a01SRahman Lavaee     }
24628b91268SRahman Lavaee     llvm_unreachable("should not break from this switch statement");
2476ac71a01SRahman Lavaee   }
2486ac71a01SRahman Lavaee   return Error::success();
2496ac71a01SRahman Lavaee }
2506ac71a01SRahman Lavaee 
ReadV0Profile()2516ac71a01SRahman Lavaee Error BasicBlockSectionsProfileReader::ReadV0Profile() {
25228b91268SRahman Lavaee   auto FI = ProgramPathAndClusterInfo.end();
25308cc0585SRahman Lavaee   // Current cluster ID corresponding to this function.
25408cc0585SRahman Lavaee   unsigned CurrentCluster = 0;
25508cc0585SRahman Lavaee   // Current position in the current cluster.
25608cc0585SRahman Lavaee   unsigned CurrentPosition = 0;
25708cc0585SRahman Lavaee 
25808cc0585SRahman Lavaee   // Temporary set to ensure every basic block ID appears once in the clusters
25908cc0585SRahman Lavaee   // of a function.
26008cc0585SRahman Lavaee   SmallSet<unsigned, 4> FuncBBIDs;
26108cc0585SRahman Lavaee 
26208cc0585SRahman Lavaee   for (; !LineIt.is_at_eof(); ++LineIt) {
26308cc0585SRahman Lavaee     StringRef S(*LineIt);
26408cc0585SRahman Lavaee     if (S[0] == '@')
26508cc0585SRahman Lavaee       continue;
26608cc0585SRahman Lavaee     // Check for the leading "!"
26708cc0585SRahman Lavaee     if (!S.consume_front("!") || S.empty())
26808cc0585SRahman Lavaee       break;
26908cc0585SRahman Lavaee     // Check for second "!" which indicates a cluster of basic blocks.
27008cc0585SRahman Lavaee     if (S.consume_front("!")) {
271c13b046dSRahman Lavaee       // Skip the profile when we the profile iterator (FI) refers to the
272c13b046dSRahman Lavaee       // past-the-end element.
27328b91268SRahman Lavaee       if (FI == ProgramPathAndClusterInfo.end())
274c13b046dSRahman Lavaee         continue;
2753d6841b2SRahman Lavaee       SmallVector<StringRef, 4> BBIDs;
2763d6841b2SRahman Lavaee       S.split(BBIDs, ' ');
27708cc0585SRahman Lavaee       // Reset current cluster position.
27808cc0585SRahman Lavaee       CurrentPosition = 0;
2793d6841b2SRahman Lavaee       for (auto BBIDStr : BBIDs) {
2803d6841b2SRahman Lavaee         unsigned long long BBID;
2813d6841b2SRahman Lavaee         if (getAsUnsignedInteger(BBIDStr, 10, BBID))
2826ac71a01SRahman Lavaee           return createProfileParseError(Twine("unsigned integer expected: '") +
2836ac71a01SRahman Lavaee                                          BBIDStr + "'");
2843d6841b2SRahman Lavaee         if (!FuncBBIDs.insert(BBID).second)
2856ac71a01SRahman Lavaee           return createProfileParseError(
2866ac71a01SRahman Lavaee               Twine("duplicate basic block id found '") + BBIDStr + "'");
28708cc0585SRahman Lavaee 
28828b91268SRahman Lavaee         FI->second.ClusterInfo.emplace_back(
289f70e39ecSRahman Lavaee             BBClusterInfo({{static_cast<unsigned>(BBID), 0},
29028b91268SRahman Lavaee                            CurrentCluster,
29128b91268SRahman Lavaee                            CurrentPosition++}));
29208cc0585SRahman Lavaee       }
29308cc0585SRahman Lavaee       CurrentCluster++;
294c13b046dSRahman Lavaee     } else {
295c13b046dSRahman Lavaee       // This is a function name specifier. It may include a debug info filename
296c13b046dSRahman Lavaee       // specifier starting with `M=`.
297c13b046dSRahman Lavaee       auto [AliasesStr, DIFilenameStr] = S.split(' ');
298c13b046dSRahman Lavaee       SmallString<128> DIFilename;
299586ecdf2SKazu Hirata       if (DIFilenameStr.starts_with("M=")) {
300c13b046dSRahman Lavaee         DIFilename =
301c13b046dSRahman Lavaee             sys::path::remove_leading_dotslash(DIFilenameStr.substr(2));
302c13b046dSRahman Lavaee         if (DIFilename.empty())
3036ac71a01SRahman Lavaee           return createProfileParseError("empty module name specifier");
304c13b046dSRahman Lavaee       } else if (!DIFilenameStr.empty()) {
3056ac71a01SRahman Lavaee         return createProfileParseError("unknown string found: '" +
3066ac71a01SRahman Lavaee                                        DIFilenameStr + "'");
307c13b046dSRahman Lavaee       }
30808cc0585SRahman Lavaee       // Function aliases are separated using '/'. We use the first function
30908cc0585SRahman Lavaee       // name for the cluster info mapping and delegate all other aliases to
31008cc0585SRahman Lavaee       // this one.
31108cc0585SRahman Lavaee       SmallVector<StringRef, 4> Aliases;
312c13b046dSRahman Lavaee       AliasesStr.split(Aliases, '/');
313c13b046dSRahman Lavaee       bool FunctionFound = any_of(Aliases, [&](StringRef Alias) {
314c13b046dSRahman Lavaee         auto It = FunctionNameToDIFilename.find(Alias);
315c13b046dSRahman Lavaee         // No match if this function name is not found in this module.
316c13b046dSRahman Lavaee         if (It == FunctionNameToDIFilename.end())
317c13b046dSRahman Lavaee           return false;
318c13b046dSRahman Lavaee         // Return a match if debug-info-filename is not specified. Otherwise,
319c13b046dSRahman Lavaee         // check for equality.
320*aaa8a800SKazu Hirata         return DIFilename.empty() || It->second == DIFilename;
321c13b046dSRahman Lavaee       });
322c13b046dSRahman Lavaee       if (!FunctionFound) {
323c13b046dSRahman Lavaee         // Skip the following profile by setting the profile iterator (FI) to
324c13b046dSRahman Lavaee         // the past-the-end element.
32528b91268SRahman Lavaee         FI = ProgramPathAndClusterInfo.end();
326c13b046dSRahman Lavaee         continue;
327c13b046dSRahman Lavaee       }
32808cc0585SRahman Lavaee       for (size_t i = 1; i < Aliases.size(); ++i)
32908cc0585SRahman Lavaee         FuncAliasMap.try_emplace(Aliases[i], Aliases.front());
33008cc0585SRahman Lavaee 
33108cc0585SRahman Lavaee       // Prepare for parsing clusters of this function name.
33208cc0585SRahman Lavaee       // Start a new cluster map for this function name.
33328b91268SRahman Lavaee       auto R = ProgramPathAndClusterInfo.try_emplace(Aliases.front());
334c13b046dSRahman Lavaee       // Report error when multiple profiles have been specified for the same
335c13b046dSRahman Lavaee       // function.
336c13b046dSRahman Lavaee       if (!R.second)
3376ac71a01SRahman Lavaee         return createProfileParseError("duplicate profile for function '" +
3386ac71a01SRahman Lavaee                                        Aliases.front() + "'");
339c13b046dSRahman Lavaee       FI = R.first;
34008cc0585SRahman Lavaee       CurrentCluster = 0;
34108cc0585SRahman Lavaee       FuncBBIDs.clear();
34208cc0585SRahman Lavaee     }
34308cc0585SRahman Lavaee   }
34408cc0585SRahman Lavaee   return Error::success();
34508cc0585SRahman Lavaee }
34608cc0585SRahman Lavaee 
3476ac71a01SRahman Lavaee // Basic Block Sections can be enabled for a subset of machine basic blocks.
3486ac71a01SRahman Lavaee // This is done by passing a file containing names of functions for which basic
3496ac71a01SRahman Lavaee // block sections are desired. Additionally, machine basic block ids of the
3506ac71a01SRahman Lavaee // functions can also be specified for a finer granularity. Moreover, a cluster
3516ac71a01SRahman Lavaee // of basic blocks could be assigned to the same section.
3526ac71a01SRahman Lavaee // Optionally, a debug-info filename can be specified for each function to allow
3536ac71a01SRahman Lavaee // distinguishing internal-linkage functions of the same name.
3546ac71a01SRahman Lavaee // A file with basic block sections for all of function main and three blocks
3556ac71a01SRahman Lavaee // for function foo (of which 1 and 2 are placed in a cluster) looks like this:
3566ac71a01SRahman Lavaee // (Profile for function foo is only loaded when its debug-info filename
3576ac71a01SRahman Lavaee // matches 'path/to/foo_file.cc').
3586ac71a01SRahman Lavaee // ----------------------------
3596ac71a01SRahman Lavaee // list.txt:
3606ac71a01SRahman Lavaee // !main
3616ac71a01SRahman Lavaee // !foo M=path/to/foo_file.cc
3626ac71a01SRahman Lavaee // !!1 2
3636ac71a01SRahman Lavaee // !!4
ReadProfile()3646ac71a01SRahman Lavaee Error BasicBlockSectionsProfileReader::ReadProfile() {
3656ac71a01SRahman Lavaee   assert(MBuf);
3666ac71a01SRahman Lavaee 
3676ac71a01SRahman Lavaee   unsigned long long Version = 0;
3686ac71a01SRahman Lavaee   StringRef FirstLine(*LineIt);
3696ac71a01SRahman Lavaee   if (FirstLine.consume_front("v")) {
3706ac71a01SRahman Lavaee     if (getAsUnsignedInteger(FirstLine, 10, Version)) {
3716ac71a01SRahman Lavaee       return createProfileParseError(Twine("version number expected: '") +
3726ac71a01SRahman Lavaee                                      FirstLine + "'");
3736ac71a01SRahman Lavaee     }
3746ac71a01SRahman Lavaee     if (Version > 1) {
3756ac71a01SRahman Lavaee       return createProfileParseError(Twine("invalid profile version: ") +
3766ac71a01SRahman Lavaee                                      Twine(Version));
3776ac71a01SRahman Lavaee     }
3786ac71a01SRahman Lavaee     ++LineIt;
3796ac71a01SRahman Lavaee   }
3806ac71a01SRahman Lavaee 
3816ac71a01SRahman Lavaee   switch (Version) {
3826ac71a01SRahman Lavaee   case 0:
3836ac71a01SRahman Lavaee     // TODO: Deprecate V0 once V1 is fully integrated downstream.
3846ac71a01SRahman Lavaee     return ReadV0Profile();
3856ac71a01SRahman Lavaee   case 1:
3866ac71a01SRahman Lavaee     return ReadV1Profile();
3876ac71a01SRahman Lavaee   default:
3886ac71a01SRahman Lavaee     llvm_unreachable("Invalid profile version.");
3896ac71a01SRahman Lavaee   }
3906ac71a01SRahman Lavaee }
3916ac71a01SRahman Lavaee 
doInitialization(Module & M)392f1ec0d12SNick Anderson bool BasicBlockSectionsProfileReaderWrapperPass::doInitialization(Module &M) {
393f1ec0d12SNick Anderson   if (!BBSPR.MBuf)
394c13b046dSRahman Lavaee     return false;
395c13b046dSRahman Lavaee   // Get the function name to debug info filename mapping.
396f1ec0d12SNick Anderson   BBSPR.FunctionNameToDIFilename.clear();
397c13b046dSRahman Lavaee   for (const Function &F : M) {
398c13b046dSRahman Lavaee     SmallString<128> DIFilename;
399c13b046dSRahman Lavaee     if (F.isDeclaration())
400c13b046dSRahman Lavaee       continue;
401c13b046dSRahman Lavaee     DISubprogram *Subprogram = F.getSubprogram();
402c13b046dSRahman Lavaee     if (Subprogram) {
403c13b046dSRahman Lavaee       llvm::DICompileUnit *CU = Subprogram->getUnit();
404c13b046dSRahman Lavaee       if (CU)
405c13b046dSRahman Lavaee         DIFilename = sys::path::remove_leading_dotslash(CU->getFilename());
406c13b046dSRahman Lavaee     }
407c13b046dSRahman Lavaee     [[maybe_unused]] bool inserted =
408f1ec0d12SNick Anderson         BBSPR.FunctionNameToDIFilename.try_emplace(F.getName(), DIFilename)
409f1ec0d12SNick Anderson             .second;
410c13b046dSRahman Lavaee     assert(inserted);
411c13b046dSRahman Lavaee   }
412f1ec0d12SNick Anderson   if (auto Err = BBSPR.ReadProfile())
41308cc0585SRahman Lavaee     report_fatal_error(std::move(Err));
414c13b046dSRahman Lavaee   return false;
41508cc0585SRahman Lavaee }
41608cc0585SRahman Lavaee 
417f1ec0d12SNick Anderson AnalysisKey BasicBlockSectionsProfileReaderAnalysis::Key;
418f1ec0d12SNick Anderson 
419f1ec0d12SNick Anderson BasicBlockSectionsProfileReader
run(Function & F,FunctionAnalysisManager & AM)420f1ec0d12SNick Anderson BasicBlockSectionsProfileReaderAnalysis::run(Function &F,
421f1ec0d12SNick Anderson                                              FunctionAnalysisManager &AM) {
422f1ec0d12SNick Anderson   return BasicBlockSectionsProfileReader(TM->getBBSectionsFuncListBuf());
423f1ec0d12SNick Anderson }
424f1ec0d12SNick Anderson 
isFunctionHot(StringRef FuncName) const425f1ec0d12SNick Anderson bool BasicBlockSectionsProfileReaderWrapperPass::isFunctionHot(
426f1ec0d12SNick Anderson     StringRef FuncName) const {
427f1ec0d12SNick Anderson   return BBSPR.isFunctionHot(FuncName);
428f1ec0d12SNick Anderson }
429f1ec0d12SNick Anderson 
430f1ec0d12SNick Anderson std::pair<bool, SmallVector<BBClusterInfo>>
getClusterInfoForFunction(StringRef FuncName) const431f1ec0d12SNick Anderson BasicBlockSectionsProfileReaderWrapperPass::getClusterInfoForFunction(
432f1ec0d12SNick Anderson     StringRef FuncName) const {
433f1ec0d12SNick Anderson   return BBSPR.getClusterInfoForFunction(FuncName);
434f1ec0d12SNick Anderson }
435f1ec0d12SNick Anderson 
436f1ec0d12SNick Anderson SmallVector<SmallVector<unsigned>>
getClonePathsForFunction(StringRef FuncName) const437f1ec0d12SNick Anderson BasicBlockSectionsProfileReaderWrapperPass::getClonePathsForFunction(
438f1ec0d12SNick Anderson     StringRef FuncName) const {
439f1ec0d12SNick Anderson   return BBSPR.getClonePathsForFunction(FuncName);
440f1ec0d12SNick Anderson }
441f1ec0d12SNick Anderson 
442f1ec0d12SNick Anderson BasicBlockSectionsProfileReader &
getBBSPR()443f1ec0d12SNick Anderson BasicBlockSectionsProfileReaderWrapperPass::getBBSPR() {
444f1ec0d12SNick Anderson   return BBSPR;
445f1ec0d12SNick Anderson }
446f1ec0d12SNick Anderson 
createBasicBlockSectionsProfileReaderWrapperPass(const MemoryBuffer * Buf)447f1ec0d12SNick Anderson ImmutablePass *llvm::createBasicBlockSectionsProfileReaderWrapperPass(
448f1ec0d12SNick Anderson     const MemoryBuffer *Buf) {
449f1ec0d12SNick Anderson   return new BasicBlockSectionsProfileReaderWrapperPass(Buf);
45008cc0585SRahman Lavaee }
451