1//===-- BasicBlockSectionsProfileReader.cpp -------------------------------===//
2//
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
6//
7//===----------------------------------------------------------------------===//
8//
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).
12//
13//===----------------------------------------------------------------------===//
14
15#include "llvm/CodeGen/BasicBlockSectionsProfileReader.h"
16#include "llvm/ADT/DenseSet.h"
17#include "llvm/ADT/SmallSet.h"
18#include "llvm/ADT/SmallString.h"
19#include "llvm/ADT/SmallVector.h"
20#include "llvm/ADT/StringMap.h"
21#include "llvm/ADT/StringRef.h"
22#include "llvm/IR/DebugInfoMetadata.h"
23#include "llvm/Pass.h"
24#include "llvm/Support/Error.h"
25#include "llvm/Support/ErrorHandling.h"
26#include "llvm/Support/LineIterator.h"
27#include "llvm/Support/MemoryBuffer.h"
28#include "llvm/Support/Path.h"
29#include "llvm/Support/UniqueBBID.h"
30#include <llvm/ADT/STLExtras.h>
31
32using namespace llvm;
33
34char BasicBlockSectionsProfileReaderWrapperPass::ID = 0;
35INITIALIZE_PASS(BasicBlockSectionsProfileReaderWrapperPass,
36 "bbsections-profile-reader",
37 "Reads and parses a basic block sections profile.", false,
38 false)
39
40Expected<UniqueBBID>
41BasicBlockSectionsProfileReader::parseUniqueBBID(StringRef S) const {
42 SmallVector<StringRef, 2> Parts;
43 S.split(A&: Parts, Separator: '.');
44 if (Parts.size() > 2)
45 return createProfileParseError(Message: Twine("unable to parse basic block id: '") +
46 S + "'");
47 unsigned long long BaseBBID;
48 if (getAsUnsignedInteger(Str: Parts[0], Radix: 10, Result&: BaseBBID))
49 return createProfileParseError(
50 Message: Twine("unable to parse BB id: '" + Parts[0]) +
51 "': unsigned integer expected");
52 unsigned long long CloneID = 0;
53 if (Parts.size() > 1 && getAsUnsignedInteger(Str: Parts[1], Radix: 10, Result&: CloneID))
54 return createProfileParseError(Message: Twine("unable to parse clone id: '") +
55 Parts[1] + "': unsigned integer expected");
56 return UniqueBBID{.BaseID: static_cast<unsigned>(BaseBBID),
57 .CloneID: static_cast<unsigned>(CloneID)};
58}
59
60bool BasicBlockSectionsProfileReader::isFunctionHot(StringRef FuncName) const {
61 return !getClusterInfoForFunction(FuncName).empty();
62}
63
64SmallVector<BBClusterInfo>
65BasicBlockSectionsProfileReader::getClusterInfoForFunction(
66 StringRef FuncName) const {
67 auto R = ProgramOptimizationProfile.find(Key: getAliasName(FuncName));
68 return R != ProgramOptimizationProfile.end() ? R->second.ClusterInfo
69 : SmallVector<BBClusterInfo>();
70}
71
72SmallVector<SmallVector<unsigned>>
73BasicBlockSectionsProfileReader::getClonePathsForFunction(
74 StringRef FuncName) const {
75 auto R = ProgramOptimizationProfile.find(Key: getAliasName(FuncName));
76 return R != ProgramOptimizationProfile.end()
77 ? R->second.ClonePaths
78 : SmallVector<SmallVector<unsigned>>();
79}
80
81uint64_t BasicBlockSectionsProfileReader::getEdgeCount(
82 StringRef FuncName, const UniqueBBID &SrcBBID,
83 const UniqueBBID &SinkBBID) const {
84 const CFGProfile *CFG = getFunctionCFGProfile(FuncName);
85 if (CFG == nullptr)
86 return 0;
87 auto NodeIt = CFG->EdgeCounts.find(Val: SrcBBID);
88 if (NodeIt == CFG->EdgeCounts.end())
89 return 0;
90 auto EdgeIt = NodeIt->second.find(Val: SinkBBID);
91 if (EdgeIt == NodeIt->second.end())
92 return 0;
93 return EdgeIt->second;
94}
95
96SmallVector<CallsiteID>
97BasicBlockSectionsProfileReader::getPrefetchTargetsForFunction(
98 StringRef FuncName) const {
99 auto R = ProgramOptimizationProfile.find(Key: getAliasName(FuncName));
100 return R != ProgramOptimizationProfile.end() ? R->second.PrefetchTargets
101 : SmallVector<CallsiteID>();
102}
103
104SmallVector<PrefetchHint>
105BasicBlockSectionsProfileReader::getPrefetchHintsForFunction(
106 StringRef FuncName) const {
107 StringMap<FunctionOptimizationProfile>::const_iterator It =
108 ProgramOptimizationProfile.find(Key: getAliasName(FuncName));
109 return It != ProgramOptimizationProfile.end() ? It->second.PrefetchHints
110 : SmallVector<PrefetchHint>();
111}
112
113// Reads the version 1 basic block sections profile. Profile for each function
114// is encoded as follows:
115// m <module_name>
116// f <function_name_1> <function_name_2> ...
117// c <bb_id_1> <bb_id_2> <bb_id_3>
118// c <bb_id_4> <bb_id_5>
119// ...
120// Module name specifier (starting with 'm') is optional and allows
121// distinguishing profile for internal-linkage functions with the same name. If
122// not specified, it will apply to any function with the same name. Function
123// name specifier (starting with 'f') can specify multiple function name
124// aliases. Basic block clusters are specified by 'c' and specify the cluster of
125// basic blocks, and the internal order in which they must be placed in the same
126// section.
127// This profile can also specify cloning paths which instruct the compiler to
128// clone basic blocks along a path. The cloned blocks are then specified in the
129// cluster information.
130// The following profile lists two cloning paths (starting with 'p') for
131// function bar and places the total 9 blocks within two clusters. The first two
132// blocks of a cloning path specify the edge along which the path is cloned. For
133// instance, path 1 (1 -> 3 -> 4) instructs that 3 and 4 must be cloned along
134// the edge 1->3. Within the given clusters, each cloned block is identified by
135// "<original block id>.<clone id>". For instance, 3.1 represents the first
136// clone of block 3. Original blocks are specified just with their block ids. A
137// block cloned multiple times appears with distinct clone ids. The CFG for bar
138// is shown below before and after cloning with its final clusters labeled.
139//
140// f main
141// f bar
142// p 1 3 4 # cloning path 1
143// p 4 2 # cloning path 2
144// c 1 3.1 4.1 6 # basic block cluster 1
145// c 0 2 3 4 2.1 5 # basic block cluster 2
146// ****************************************************************************
147// function bar before and after cloning with basic block clusters shown.
148// ****************************************************************************
149// .... ..............
150// 0 -------+ : 0 :---->: 1 ---> 3.1 :
151// | | : | : :........ | :
152// v v : v : : v :
153// +--> 2 --> 5 1 ~~~~~~> +---: 2 : : 4.1: clsuter 1
154// | | | | : | : : | :
155// | v | | : v ....... : v :
156// | 3 <------+ | : 3 <--+ : : 6 :
157// | | | : | | : :....:
158// | v | : v | :
159// +--- 4 ---> 6 | : 4 | :
160// | : | | :
161// | : v | :
162// | :2.1---+ : cluster 2
163// | : | ......:
164// | : v :
165// +-->: 5 :
166// ....
167// ****************************************************************************
168// This profile can also specify prefetch targets (starting with 't') which
169// instruct the compiler to emit a prefetch symbol for the given target and
170// prefetch hints (starting with 'i') which instruct the compiler to insert a
171// prefetch hint instruction at the given site for the given target.
172//
173// A prefetch target is specified by a pair "<bbid>,<subblock_index>" where
174// bbid specifies the target basic block and subblock_index is a zero-based
175// index. Subblock 0 refers to the region at the beginning of the block up to
176// the first callsite. Subblock `i > 0` refers to the region immediately after
177// the `i`-th callsite up to the `i+1`-th callsite (or the end of the block).
178// The prefetch target is always emitted at the beginning of the subblock.
179// This is the beginning of the basic block for `i = 0` and immediately after
180// the `i`-th call for every `i > 0`.
181//
182// A prefetch hint is specified by a pair "site target", where site is
183// specified as a pair "<bbid>,<callsite_index>" similar to prefetch
184// targets, and target is specified as a triple
185// "<function_name>,<bbid>,<callsite_index>".
186//
187// Example: A basic block in function "foo" with BBID 10 and two call
188// instructions (call_A, call_B). This block is conceptually split into
189// subblocks, with the prefetch target symbol emitted at the beginning of
190// each subblock.
191//
192// +----------------------------------+
193// | __llvm_prefetch_target_foo_10_0: | <--- Subblock 0 (before call_A)
194// | Instruction 1 |
195// | Instruction 2 |
196// | call_A (Callsite 0) |
197// | __llvm_prefetch_target_foo_10_1: | <--- Subblock 1 (after call_A,
198// | | before call_B)
199// | Instruction 3 |
200// | call_B (Callsite 1) |
201// | __llvm_prefetch_target_foo_10_2: | <--- Subblock 2 (after call_B,
202// | | before call_C)
203// | Instruction 4 |
204// +----------------------------------+
205//
206// A prefetch hint specified in function "bar" as "120,1 foo,10,2" results
207// in a hint inserted after the first call in block #120 of bar targeting the
208// address immediately after the second call in block #10 of function foo.
209//
210// B
211// +----------------------------------------------------+
212// | Instruction 1 |
213// | call_C (Callsite 1) |
214// | code_prefetch __llvm_prefetch_target_foo_10 |
215// | Instruction 2 |
216// +----------------------------------------------------+
217//
218Error BasicBlockSectionsProfileReader::ReadV1Profile() {
219 auto FI = ProgramOptimizationProfile.end();
220
221 // Current cluster ID corresponding to this function.
222 unsigned CurrentCluster = 0;
223 // Current position in the current cluster.
224 unsigned CurrentPosition = 0;
225
226 // Temporary set to ensure every basic block ID appears once in the clusters
227 // of a function.
228 DenseSet<UniqueBBID> FuncBBIDs;
229
230 // Debug-info-based module filename for the current function. Empty string
231 // means no filename.
232 StringRef DIFilename;
233
234 for (; !LineIt.is_at_eof(); ++LineIt) {
235 StringRef S(*LineIt);
236 char Specifier = S[0];
237 S = S.drop_front().trim();
238 SmallVector<StringRef, 4> Values;
239 S.split(A&: Values, Separator: ' ');
240 switch (Specifier) {
241 case '@':
242 continue;
243 case 'm': // Module name speicifer.
244 if (Values.size() != 1) {
245 return createProfileParseError(Message: Twine("invalid module name value: '") +
246 S + "'");
247 }
248 DIFilename = sys::path::remove_leading_dotslash(path: Values[0]);
249 continue;
250 case 'f': { // Function names specifier.
251 bool FunctionFound = any_of(Range&: Values, P: [&](StringRef Alias) {
252 auto It = FunctionNameToDIFilename.find(Key: Alias);
253 // No match if this function name is not found in this module.
254 if (It == FunctionNameToDIFilename.end())
255 return false;
256 // Return a match if debug-info-filename is not specified. Otherwise,
257 // check for equality.
258 return DIFilename.empty() || It->second == DIFilename;
259 });
260 if (!FunctionFound) {
261 // Skip the following profile by setting the profile iterator (FI) to
262 // the past-the-end element.
263 FI = ProgramOptimizationProfile.end();
264 DIFilename = "";
265 continue;
266 }
267 for (size_t i = 1; i < Values.size(); ++i)
268 FuncAliasMap.try_emplace(Key: Values[i], Args&: Values.front());
269
270 // Prepare for parsing clusters of this function name.
271 // Start a new cluster map for this function name.
272 auto R = ProgramOptimizationProfile.try_emplace(Key: Values.front());
273 // Report error when multiple profiles have been specified for the same
274 // function.
275 if (!R.second)
276 return createProfileParseError(Message: "duplicate profile for function '" +
277 Values.front() + "'");
278 FI = R.first;
279 CurrentCluster = 0;
280 FuncBBIDs.clear();
281 // We won't need DIFilename anymore. Clean it up to avoid its application
282 // on the next function.
283 DIFilename = "";
284 continue;
285 }
286 case 'c': // Basic block cluster specifier.
287 // Skip the profile when we the profile iterator (FI) refers to the
288 // past-the-end element.
289 if (FI == ProgramOptimizationProfile.end())
290 continue;
291 // Reset current cluster position.
292 CurrentPosition = 0;
293 for (auto BasicBlockIDStr : Values) {
294 auto BasicBlockID = parseUniqueBBID(S: BasicBlockIDStr);
295 if (!BasicBlockID)
296 return BasicBlockID.takeError();
297 if (!FuncBBIDs.insert(V: *BasicBlockID).second)
298 return createProfileParseError(
299 Message: Twine("duplicate basic block id found '") + BasicBlockIDStr +
300 "'");
301
302 FI->second.ClusterInfo.emplace_back(Args: BBClusterInfo{
303 .BBID: *std::move(BasicBlockID), .ClusterID: CurrentCluster, .PositionInCluster: CurrentPosition++});
304 }
305 CurrentCluster++;
306 continue;
307 case 'p': { // Basic block cloning path specifier.
308 // Skip the profile when we the profile iterator (FI) refers to the
309 // past-the-end element.
310 if (FI == ProgramOptimizationProfile.end())
311 continue;
312 SmallSet<unsigned, 5> BBsInPath;
313 FI->second.ClonePaths.push_back(Elt: {});
314 for (size_t I = 0; I < Values.size(); ++I) {
315 auto BaseBBIDStr = Values[I];
316 unsigned long long BaseBBID = 0;
317 if (getAsUnsignedInteger(Str: BaseBBIDStr, Radix: 10, Result&: BaseBBID))
318 return createProfileParseError(Message: Twine("unsigned integer expected: '") +
319 BaseBBIDStr + "'");
320 if (I != 0 && !BBsInPath.insert(V: BaseBBID).second)
321 return createProfileParseError(
322 Message: Twine("duplicate cloned block in path: '") + BaseBBIDStr + "'");
323 FI->second.ClonePaths.back().push_back(Elt: BaseBBID);
324 }
325 continue;
326 }
327 case 'g': { // CFG profile specifier.
328 // Skip the profile when we the profile iterator (FI) refers to the
329 // past-the-end element.
330 if (FI == ProgramOptimizationProfile.end())
331 continue;
332 // For each node, its CFG profile is encoded as
333 // <src>:<count>,<sink_1>:<count_1>,<sink_2>:<count_2>,...
334 for (auto BasicBlockEdgeProfile : Values) {
335 if (BasicBlockEdgeProfile.empty())
336 continue;
337 SmallVector<StringRef, 4> NodeEdgeCounts;
338 BasicBlockEdgeProfile.split(A&: NodeEdgeCounts, Separator: ',');
339 UniqueBBID SrcBBID;
340 for (size_t i = 0; i < NodeEdgeCounts.size(); ++i) {
341 auto [BBIDStr, CountStr] = NodeEdgeCounts[i].split(Separator: ':');
342 auto BBID = parseUniqueBBID(S: BBIDStr);
343 if (!BBID)
344 return BBID.takeError();
345 unsigned long long Count = 0;
346 if (getAsUnsignedInteger(Str: CountStr, Radix: 10, Result&: Count))
347 return createProfileParseError(
348 Message: Twine("unsigned integer expected: '") + CountStr + "'");
349 if (i == 0) {
350 // The first element represents the source and its total count.
351 FI->second.CFG.NodeCounts[SrcBBID = *BBID] = Count;
352 continue;
353 }
354 FI->second.CFG.EdgeCounts[SrcBBID][*BBID] = Count;
355 }
356 }
357 continue;
358 }
359 case 'h': { // Basic block hash secifier.
360 // Skip the profile when the profile iterator (FI) refers to the
361 // past-the-end element.
362 if (FI == ProgramOptimizationProfile.end())
363 continue;
364 for (auto BBIDHashStr : Values) {
365 auto [BBIDStr, HashStr] = BBIDHashStr.split(Separator: ':');
366 unsigned long long BBID = 0, Hash = 0;
367 if (getAsUnsignedInteger(Str: BBIDStr, Radix: 10, Result&: BBID))
368 return createProfileParseError(Message: Twine("unsigned integer expected: '") +
369 BBIDStr + "'");
370 if (getAsUnsignedInteger(Str: HashStr, Radix: 16, Result&: Hash))
371 return createProfileParseError(
372 Message: Twine("unsigned integer expected in hex format: '") + HashStr +
373 "'");
374 FI->second.CFG.BBHashes[BBID] = Hash;
375 }
376 continue;
377 }
378 case 't': { // Callsite target specifier.
379 // Skip the profile when we the profile iterator (FI) refers to the
380 // past-the-end element.
381 if (FI == ProgramOptimizationProfile.end())
382 continue;
383 SmallVector<StringRef, 2> PrefetchTargetStr;
384 Values[0].split(A&: PrefetchTargetStr, Separator: ',');
385 if (PrefetchTargetStr.size() != 2)
386 return createProfileParseError(Message: Twine("Callsite target expected: ") +
387 Values[0]);
388 auto TargetBBID = parseUniqueBBID(S: PrefetchTargetStr[0]);
389 if (!TargetBBID)
390 return TargetBBID.takeError();
391 unsigned long long CallsiteIndex;
392 if (getAsUnsignedInteger(Str: PrefetchTargetStr[1], Radix: 10, Result&: CallsiteIndex))
393 return createProfileParseError(Message: Twine("signed integer expected: '") +
394 PrefetchTargetStr[1]);
395 FI->second.PrefetchTargets.push_back(
396 Elt: CallsiteID{.BBID: *TargetBBID, .CallsiteIndex: static_cast<unsigned>(CallsiteIndex)});
397 continue;
398 }
399
400 case 'i': { // Prefetch hint specifier.
401 // Skip the profile when the profile iterator (FI) refers to the
402 // past-the-end element.
403 if (FI == ProgramOptimizationProfile.end())
404 continue;
405 if (Values.size() != 2)
406 return createProfileParseError(
407 Message: Twine("Prefetch hint expected of format '<prefetch-site> "
408 "<prefetch-target>': " +
409 S));
410 SmallVector<StringRef, 2> PrefetchSiteStr;
411 Values[0].split(A&: PrefetchSiteStr, Separator: ',');
412 if (PrefetchSiteStr.size() != 2)
413 return createProfileParseError(Message: Twine("Prefetch site expected of format "
414 "'<block-id>,<callsite-id>': ") +
415 Values[0]);
416 auto SiteBBID = parseUniqueBBID(S: PrefetchSiteStr[0]);
417 if (!SiteBBID)
418 return SiteBBID.takeError();
419 unsigned long long SiteCallsiteIndex;
420 if (getAsUnsignedInteger(Str: PrefetchSiteStr[1], Radix: 10, Result&: SiteCallsiteIndex))
421 return createProfileParseError(Message: Twine("unsigned integer expected: '") +
422 PrefetchSiteStr[1]);
423
424 SmallVector<StringRef, 3> PrefetchTargetStr;
425 Values[1].split(A&: PrefetchTargetStr, Separator: ',');
426 if (PrefetchTargetStr.size() != 3)
427 return createProfileParseError(
428 Message: Twine("Prefetch target expected of format "
429 "'<function-name>,<block-id>,<callsite-id>': ") +
430 Values[1]);
431 auto TargetBBID = parseUniqueBBID(S: PrefetchTargetStr[1]);
432 if (!TargetBBID)
433 return TargetBBID.takeError();
434 unsigned long long TargetCallsiteIndex;
435 if (getAsUnsignedInteger(Str: PrefetchTargetStr[2], Radix: 10, Result&: TargetCallsiteIndex))
436 return createProfileParseError(Message: Twine("unsigned integer expected: '") +
437 PrefetchTargetStr[2]);
438 FI->second.PrefetchHints.push_back(Elt: PrefetchHint{
439 .SiteID: CallsiteID{.BBID: *SiteBBID, .CallsiteIndex: static_cast<unsigned>(SiteCallsiteIndex)},
440 .TargetFunction: PrefetchTargetStr[0],
441 .TargetID: CallsiteID{.BBID: *TargetBBID, .CallsiteIndex: static_cast<unsigned>(TargetCallsiteIndex)}});
442 continue;
443 }
444 default:
445 return createProfileParseError(Message: Twine("invalid specifier: '") +
446 Twine(Specifier) + "'");
447 }
448 llvm_unreachable("should not break from this switch statement");
449 }
450 return Error::success();
451}
452
453Error BasicBlockSectionsProfileReader::ReadV0Profile() {
454 auto FI = ProgramOptimizationProfile.end();
455 // Current cluster ID corresponding to this function.
456 unsigned CurrentCluster = 0;
457 // Current position in the current cluster.
458 unsigned CurrentPosition = 0;
459
460 // Temporary set to ensure every basic block ID appears once in the clusters
461 // of a function.
462 SmallSet<unsigned, 4> FuncBBIDs;
463
464 for (; !LineIt.is_at_eof(); ++LineIt) {
465 StringRef S(*LineIt);
466 if (S[0] == '@')
467 continue;
468 // Check for the leading "!"
469 if (!S.consume_front(Prefix: "!") || S.empty())
470 break;
471 // Check for second "!" which indicates a cluster of basic blocks.
472 if (S.consume_front(Prefix: "!")) {
473 // Skip the profile when we the profile iterator (FI) refers to the
474 // past-the-end element.
475 if (FI == ProgramOptimizationProfile.end())
476 continue;
477 SmallVector<StringRef, 4> BBIDs;
478 S.split(A&: BBIDs, Separator: ' ');
479 // Reset current cluster position.
480 CurrentPosition = 0;
481 for (auto BBIDStr : BBIDs) {
482 unsigned long long BBID;
483 if (getAsUnsignedInteger(Str: BBIDStr, Radix: 10, Result&: BBID))
484 return createProfileParseError(Message: Twine("unsigned integer expected: '") +
485 BBIDStr + "'");
486 if (!FuncBBIDs.insert(V: BBID).second)
487 return createProfileParseError(
488 Message: Twine("duplicate basic block id found '") + BBIDStr + "'");
489
490 FI->second.ClusterInfo.emplace_back(
491 Args: BBClusterInfo({.BBID: {.BaseID: static_cast<unsigned>(BBID), .CloneID: 0},
492 .ClusterID: CurrentCluster,
493 .PositionInCluster: CurrentPosition++}));
494 }
495 CurrentCluster++;
496 } else {
497 // This is a function name specifier. It may include a debug info filename
498 // specifier starting with `M=`.
499 auto [AliasesStr, DIFilenameStr] = S.split(Separator: ' ');
500 SmallString<128> DIFilename;
501 if (DIFilenameStr.starts_with(Prefix: "M=")) {
502 DIFilename =
503 sys::path::remove_leading_dotslash(path: DIFilenameStr.substr(Start: 2));
504 if (DIFilename.empty())
505 return createProfileParseError(Message: "empty module name specifier");
506 } else if (!DIFilenameStr.empty()) {
507 return createProfileParseError(Message: "unknown string found: '" +
508 DIFilenameStr + "'");
509 }
510 // Function aliases are separated using '/'. We use the first function
511 // name for the cluster info mapping and delegate all other aliases to
512 // this one.
513 SmallVector<StringRef, 4> Aliases;
514 AliasesStr.split(A&: Aliases, Separator: '/');
515 bool FunctionFound = any_of(Range&: Aliases, P: [&](StringRef Alias) {
516 auto It = FunctionNameToDIFilename.find(Key: Alias);
517 // No match if this function name is not found in this module.
518 if (It == FunctionNameToDIFilename.end())
519 return false;
520 // Return a match if debug-info-filename is not specified. Otherwise,
521 // check for equality.
522 return DIFilename.empty() || It->second == DIFilename;
523 });
524 if (!FunctionFound) {
525 // Skip the following profile by setting the profile iterator (FI) to
526 // the past-the-end element.
527 FI = ProgramOptimizationProfile.end();
528 continue;
529 }
530 for (size_t i = 1; i < Aliases.size(); ++i)
531 FuncAliasMap.try_emplace(Key: Aliases[i], Args&: Aliases.front());
532
533 // Prepare for parsing clusters of this function name.
534 // Start a new cluster map for this function name.
535 auto R = ProgramOptimizationProfile.try_emplace(Key: Aliases.front());
536 // Report error when multiple profiles have been specified for the same
537 // function.
538 if (!R.second)
539 return createProfileParseError(Message: "duplicate profile for function '" +
540 Aliases.front() + "'");
541 FI = R.first;
542 CurrentCluster = 0;
543 FuncBBIDs.clear();
544 }
545 }
546 return Error::success();
547}
548
549// Basic Block Sections can be enabled for a subset of machine basic blocks.
550// This is done by passing a file containing names of functions for which basic
551// block sections are desired. Additionally, machine basic block ids of the
552// functions can also be specified for a finer granularity. Moreover, a cluster
553// of basic blocks could be assigned to the same section.
554// Optionally, a debug-info filename can be specified for each function to allow
555// distinguishing internal-linkage functions of the same name.
556// A file with basic block sections for all of function main and three blocks
557// for function foo (of which 1 and 2 are placed in a cluster) looks like this:
558// (Profile for function foo is only loaded when its debug-info filename
559// matches 'path/to/foo_file.cc').
560// ----------------------------
561// list.txt:
562// !main
563// !foo M=path/to/foo_file.cc
564// !!1 2
565// !!4
566Error BasicBlockSectionsProfileReader::ReadProfile() {
567 assert(MBuf);
568
569 unsigned long long Version = 0;
570 StringRef FirstLine(*LineIt);
571 if (FirstLine.consume_front(Prefix: "v")) {
572 if (getAsUnsignedInteger(Str: FirstLine, Radix: 10, Result&: Version)) {
573 return createProfileParseError(Message: Twine("version number expected: '") +
574 FirstLine + "'");
575 }
576 if (Version > 1) {
577 return createProfileParseError(Message: Twine("invalid profile version: ") +
578 Twine(Version));
579 }
580 ++LineIt;
581 }
582
583 switch (Version) {
584 case 0:
585 // TODO: Deprecate V0 once V1 is fully integrated downstream.
586 return ReadV0Profile();
587 case 1:
588 return ReadV1Profile();
589 default:
590 llvm_unreachable("Invalid profile version.");
591 }
592}
593
594bool BasicBlockSectionsProfileReaderWrapperPass::doInitialization(Module &M) {
595 if (!BBSPR.MBuf)
596 return false;
597 // Get the function name to debug info filename mapping.
598 BBSPR.FunctionNameToDIFilename.clear();
599 for (const Function &F : M) {
600 SmallString<128> DIFilename;
601 if (F.isDeclaration())
602 continue;
603 DISubprogram *Subprogram = F.getSubprogram();
604 if (Subprogram) {
605 llvm::DICompileUnit *CU = Subprogram->getUnit();
606 if (CU)
607 DIFilename = sys::path::remove_leading_dotslash(path: CU->getFilename());
608 }
609 [[maybe_unused]] bool inserted =
610 BBSPR.FunctionNameToDIFilename.try_emplace(Key: F.getName(), Args&: DIFilename)
611 .second;
612 assert(inserted);
613 }
614 if (auto Err = BBSPR.ReadProfile())
615 report_fatal_error(Err: std::move(Err));
616 return false;
617}
618
619AnalysisKey BasicBlockSectionsProfileReaderAnalysis::Key;
620
621BasicBlockSectionsProfileReader
622BasicBlockSectionsProfileReaderAnalysis::run(Function &F,
623 FunctionAnalysisManager &AM) {
624 return BasicBlockSectionsProfileReader(TM->getBBSectionsFuncListBuf());
625}
626
627bool BasicBlockSectionsProfileReaderWrapperPass::isFunctionHot(
628 StringRef FuncName) const {
629 return BBSPR.isFunctionHot(FuncName);
630}
631
632SmallVector<BBClusterInfo>
633BasicBlockSectionsProfileReaderWrapperPass::getClusterInfoForFunction(
634 StringRef FuncName) const {
635 return BBSPR.getClusterInfoForFunction(FuncName);
636}
637
638SmallVector<SmallVector<unsigned>>
639BasicBlockSectionsProfileReaderWrapperPass::getClonePathsForFunction(
640 StringRef FuncName) const {
641 return BBSPR.getClonePathsForFunction(FuncName);
642}
643
644const CFGProfile *
645BasicBlockSectionsProfileReaderWrapperPass::getFunctionCFGProfile(
646 StringRef FuncName) const {
647 return BBSPR.getFunctionCFGProfile(FuncName);
648}
649
650uint64_t BasicBlockSectionsProfileReaderWrapperPass::getEdgeCount(
651 StringRef FuncName, const UniqueBBID &SrcBBID,
652 const UniqueBBID &SinkBBID) const {
653 return BBSPR.getEdgeCount(FuncName, SrcBBID, SinkBBID);
654}
655
656SmallVector<CallsiteID>
657BasicBlockSectionsProfileReaderWrapperPass::getPrefetchTargetsForFunction(
658 StringRef FuncName) const {
659 return BBSPR.getPrefetchTargetsForFunction(FuncName);
660}
661
662SmallVector<PrefetchHint>
663BasicBlockSectionsProfileReaderWrapperPass::getPrefetchHintsForFunction(
664 StringRef FuncName) const {
665 return BBSPR.getPrefetchHintsForFunction(FuncName);
666}
667
668BasicBlockSectionsProfileReader &
669BasicBlockSectionsProfileReaderWrapperPass::getBBSPR() {
670 return BBSPR;
671}
672
673ImmutablePass *llvm::createBasicBlockSectionsProfileReaderWrapperPass(
674 const MemoryBuffer *Buf) {
675 return new BasicBlockSectionsProfileReaderWrapperPass(Buf);
676}
677