1818#include " llvm/ADT/SmallVector.h"
1919#include " llvm/ADT/StringMap.h"
2020#include " llvm/ADT/StringRef.h"
21- #include " llvm/CodeGen/Passes.h"
2221#include " llvm/IR/DebugInfoMetadata.h"
22+ #include " llvm/Pass.h"
2323#include " llvm/Support/Error.h"
24+ #include " llvm/Support/ErrorHandling.h"
2425#include " llvm/Support/LineIterator.h"
2526#include " llvm/Support/MemoryBuffer.h"
2627#include " llvm/Support/Path.h"
@@ -46,34 +47,121 @@ BasicBlockSectionsProfileReader::getBBClusterInfoForFunction(
4647 : std::pair (false , SmallVector<BBClusterInfo>{});
4748}
4849
49- // Basic Block Sections can be enabled for a subset of machine basic blocks.
50- // This is done by passing a file containing names of functions for which basic
51- // block sections are desired. Additionally, machine basic block ids of the
52- // functions can also be specified for a finer granularity. Moreover, a cluster
53- // of basic blocks could be assigned to the same section.
54- // Optionally, a debug-info filename can be specified for each function to allow
55- // distinguishing internal-linkage functions of the same name.
56- // A file with basic block sections for all of function main and three blocks
57- // for function foo (of which 1 and 2 are placed in a cluster) looks like this:
58- // (Profile for function foo is only loaded when its debug-info filename
59- // matches 'path/to/foo_file.cc').
60- // ----------------------------
61- // list.txt:
62- // !main
63- // !foo M=path/to/foo_file.cc
64- // !!1 2
65- // !!4
66- Error BasicBlockSectionsProfileReader::ReadProfile () {
67- assert (MBuf);
68- line_iterator LineIt (*MBuf, /* SkipBlanks=*/ true , /* CommentMarker=*/ ' #' );
50+ // Reads the version 1 basic block sections profile. Profile for each function
51+ // is encoded as follows:
52+ // m <module_name>
53+ // f <function_name_1> <function_name_2> ...
54+ // c <bb_id_1> <bb_id_2> <bb_id_3>
55+ // c <bb_id_4> <bb_id_5>
56+ // ...
57+ // Module name specifier (starting with 'm') is optional and allows
58+ // distinguishing profile for internal-linkage functions with the same name. If
59+ // not specified, it will apply to any function with the same name. Function
60+ // name specifier (starting with 'f') can specify multiple function name
61+ // aliases. Basic block clusters are specified by 'c' and specify the cluster of
62+ // basic blocks, and the internal order in which they must be placed in the same
63+ // section.
64+ Error BasicBlockSectionsProfileReader::ReadV1Profile () {
65+ auto FI = ProgramBBClusterInfo.end ();
66+
67+ // Current cluster ID corresponding to this function.
68+ unsigned CurrentCluster = 0 ;
69+ // Current position in the current cluster.
70+ unsigned CurrentPosition = 0 ;
71+
72+ // Temporary set to ensure every basic block ID appears once in the clusters
73+ // of a function.
74+ SmallSet<unsigned , 4 > FuncBBIDs;
75+
76+ // Debug-info-based module filename for the current function. Empty string
77+ // means no filename.
78+ StringRef DIFilename;
79+
80+ for (; !LineIt.is_at_eof (); ++LineIt) {
81+ StringRef S (*LineIt);
82+ char Specifier = S[0 ];
83+ S = S.drop_front ().trim ();
84+ SmallVector<StringRef, 4 > Values;
85+ S.split (Values, ' ' );
86+ switch (Specifier) {
87+ case ' @' :
88+ break ;
89+ case ' m' : // Module name speicifer.
90+ if (Values.size () != 1 ) {
91+ return createProfileParseError (Twine (" invalid module name value: '" ) +
92+ S + " '" );
93+ }
94+ DIFilename = sys::path::remove_leading_dotslash (Values[0 ]);
95+ continue ;
96+ case ' f' : { // Function names specifier.
97+ bool FunctionFound = any_of (Values, [&](StringRef Alias) {
98+ auto It = FunctionNameToDIFilename.find (Alias);
99+ // No match if this function name is not found in this module.
100+ if (It == FunctionNameToDIFilename.end ())
101+ return false ;
102+ // Return a match if debug-info-filename is not specified. Otherwise,
103+ // check for equality.
104+ return DIFilename.empty () || It->second .equals (DIFilename);
105+ });
106+ if (!FunctionFound) {
107+ // Skip the following profile by setting the profile iterator (FI) to
108+ // the past-the-end element.
109+ FI = ProgramBBClusterInfo.end ();
110+ DIFilename = " " ;
111+ continue ;
112+ }
113+ for (size_t i = 1 ; i < Values.size (); ++i)
114+ FuncAliasMap.try_emplace (Values[i], Values.front ());
115+
116+ // Prepare for parsing clusters of this function name.
117+ // Start a new cluster map for this function name.
118+ auto R = ProgramBBClusterInfo.try_emplace (Values.front ());
119+ // Report error when multiple profiles have been specified for the same
120+ // function.
121+ if (!R.second )
122+ return createProfileParseError (" duplicate profile for function '" +
123+ Values.front () + " '" );
124+ FI = R.first ;
125+ CurrentCluster = 0 ;
126+ FuncBBIDs.clear ();
127+ // We won't need DIFilename anymore. Clean it up to avoid its application
128+ // on the next function.
129+ DIFilename = " " ;
130+ continue ;
131+ }
132+ case ' c' : // Basic block cluster specifier.
133+ // Skip the profile when we the profile iterator (FI) refers to the
134+ // past-the-end element.
135+ if (FI == ProgramBBClusterInfo.end ())
136+ break ;
137+ // Reset current cluster position.
138+ CurrentPosition = 0 ;
139+ for (auto BBIDStr : Values) {
140+ unsigned long long BBID;
141+ if (getAsUnsignedInteger (BBIDStr, 10 , BBID))
142+ return createProfileParseError (Twine (" unsigned integer expected: '" ) +
143+ BBIDStr + " '" );
144+ if (!FuncBBIDs.insert (BBID).second )
145+ return createProfileParseError (
146+ Twine (" duplicate basic block id found '" ) + BBIDStr + " '" );
147+ if (BBID == 0 && CurrentPosition)
148+ return createProfileParseError (
149+ " entry BB (0) does not begin a cluster" );
69150
70- auto invalidProfileError = [&](auto Message) {
71- return make_error<StringError>(
72- Twine (" Invalid profile " + MBuf->getBufferIdentifier () + " at line " +
73- Twine (LineIt.line_number ()) + " : " + Message),
74- inconvertibleErrorCode ());
75- };
151+ FI->second .emplace_back (
152+ BBClusterInfo{((unsigned )BBID), CurrentCluster, CurrentPosition++});
153+ }
154+ CurrentCluster++;
155+ continue ;
156+ default :
157+ return createProfileParseError (Twine (" invalid specifier: '" ) +
158+ Twine (Specifier) + " '" );
159+ }
160+ }
161+ return Error::success ();
162+ }
76163
164+ Error BasicBlockSectionsProfileReader::ReadV0Profile () {
77165 auto FI = ProgramBBClusterInfo.end ();
78166
79167 // Current cluster ID corresponding to this function.
@@ -105,13 +193,14 @@ Error BasicBlockSectionsProfileReader::ReadProfile() {
105193 for (auto BBIDStr : BBIDs) {
106194 unsigned long long BBID;
107195 if (getAsUnsignedInteger (BBIDStr, 10 , BBID))
108- return invalidProfileError (Twine (" Unsigned integer expected: '" ) +
109- BBIDStr + " '. " );
196+ return createProfileParseError (Twine (" unsigned integer expected: '" ) +
197+ BBIDStr + " '" );
110198 if (!FuncBBIDs.insert (BBID).second )
111- return invalidProfileError ( Twine ( " Duplicate basic block id found ' " ) +
112- BBIDStr + " '. " );
199+ return createProfileParseError (
200+ Twine ( " duplicate basic block id found ' " ) + BBIDStr + " '" );
113201 if (BBID == 0 && CurrentPosition)
114- return invalidProfileError (" Entry BB (0) does not begin a cluster." );
202+ return createProfileParseError (
203+ " entry BB (0) does not begin a cluster" );
115204
116205 FI->second .emplace_back (
117206 BBClusterInfo{((unsigned )BBID), CurrentCluster, CurrentPosition++});
@@ -126,10 +215,10 @@ Error BasicBlockSectionsProfileReader::ReadProfile() {
126215 DIFilename =
127216 sys::path::remove_leading_dotslash (DIFilenameStr.substr (2 ));
128217 if (DIFilename.empty ())
129- return invalidProfileError ( " Empty module name specifier. " );
218+ return createProfileParseError ( " empty module name specifier" );
130219 } else if (!DIFilenameStr.empty ()) {
131- return invalidProfileError ( " Unknown string found: '" + DIFilenameStr +
132- " '. " );
220+ return createProfileParseError ( " unknown string found: '" +
221+ DIFilenameStr + " ' " );
133222 }
134223 // Function aliases are separated using '/'. We use the first function
135224 // name for the cluster info mapping and delegate all other aliases to
@@ -160,8 +249,8 @@ Error BasicBlockSectionsProfileReader::ReadProfile() {
160249 // Report error when multiple profiles have been specified for the same
161250 // function.
162251 if (!R.second )
163- return invalidProfileError ( " Duplicate profile for function '" +
164- Aliases.front () + " '. " );
252+ return createProfileParseError ( " duplicate profile for function '" +
253+ Aliases.front () + " '" );
165254 FI = R.first ;
166255 CurrentCluster = 0 ;
167256 FuncBBIDs.clear ();
@@ -170,6 +259,51 @@ Error BasicBlockSectionsProfileReader::ReadProfile() {
170259 return Error::success ();
171260}
172261
262+ // Basic Block Sections can be enabled for a subset of machine basic blocks.
263+ // This is done by passing a file containing names of functions for which basic
264+ // block sections are desired. Additionally, machine basic block ids of the
265+ // functions can also be specified for a finer granularity. Moreover, a cluster
266+ // of basic blocks could be assigned to the same section.
267+ // Optionally, a debug-info filename can be specified for each function to allow
268+ // distinguishing internal-linkage functions of the same name.
269+ // A file with basic block sections for all of function main and three blocks
270+ // for function foo (of which 1 and 2 are placed in a cluster) looks like this:
271+ // (Profile for function foo is only loaded when its debug-info filename
272+ // matches 'path/to/foo_file.cc').
273+ // ----------------------------
274+ // list.txt:
275+ // !main
276+ // !foo M=path/to/foo_file.cc
277+ // !!1 2
278+ // !!4
279+ Error BasicBlockSectionsProfileReader::ReadProfile () {
280+ assert (MBuf);
281+
282+ unsigned long long Version = 0 ;
283+ StringRef FirstLine (*LineIt);
284+ if (FirstLine.consume_front (" v" )) {
285+ if (getAsUnsignedInteger (FirstLine, 10 , Version)) {
286+ return createProfileParseError (Twine (" version number expected: '" ) +
287+ FirstLine + " '" );
288+ }
289+ if (Version > 1 ) {
290+ return createProfileParseError (Twine (" invalid profile version: " ) +
291+ Twine (Version));
292+ }
293+ ++LineIt;
294+ }
295+
296+ switch (Version) {
297+ case 0 :
298+ // TODO: Deprecate V0 once V1 is fully integrated downstream.
299+ return ReadV0Profile ();
300+ case 1 :
301+ return ReadV1Profile ();
302+ default :
303+ llvm_unreachable (" Invalid profile version." );
304+ }
305+ }
306+
173307bool BasicBlockSectionsProfileReader::doInitialization (Module &M) {
174308 if (!MBuf)
175309 return false ;
0 commit comments