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