@@ -604,6 +604,8 @@ Error DataAggregator::readProfile(BinaryContext &BC) {
604
604
// BAT YAML is handled by DataAggregator since normal YAML output requires
605
605
// CFG which is not available in BAT mode.
606
606
if (usesBAT ()) {
607
+ // Postprocess split function profile for BAT
608
+ fixupBATProfile (BC);
607
609
if (opts::ProfileFormat == opts::ProfileFormatKind::PF_YAML)
608
610
if (std::error_code EC = writeBATYAML (BC, opts::OutputFilename))
609
611
report_error (" cannot create output data file" , EC);
@@ -2271,6 +2273,29 @@ DataAggregator::writeAggregatedFile(StringRef OutputFilename) const {
2271
2273
return std::error_code ();
2272
2274
}
2273
2275
2276
+ void DataAggregator::fixupBATProfile (BinaryContext &BC) {
2277
+ for (auto &[FuncName, Branches] : NamesToBranches) {
2278
+ BinaryData *BD = BC.getBinaryDataByName (FuncName);
2279
+ assert (BD);
2280
+ uint64_t FuncAddress = BD->getAddress ();
2281
+ if (!BAT->isBATFunction (FuncAddress))
2282
+ continue ;
2283
+ // Filter out cold fragments
2284
+ if (!BD->getSectionName ().equals (BC.getMainCodeSectionName ()))
2285
+ continue ;
2286
+ // Convert inter-branches between hot and cold fragments into
2287
+ // intra-branches.
2288
+ for (auto &[OffsetFrom, CallToMap] : Branches.InterIndex ) {
2289
+ for (auto &[CallToLoc, CallToIdx] : CallToMap) {
2290
+ if (CallToLoc.Name != FuncName)
2291
+ continue ;
2292
+ Branches.IntraIndex [OffsetFrom][CallToLoc.Offset ] = CallToIdx;
2293
+ Branches.InterIndex [OffsetFrom].erase (CallToLoc);
2294
+ }
2295
+ }
2296
+ }
2297
+ }
2298
+
2274
2299
std::error_code DataAggregator::writeBATYAML (BinaryContext &BC,
2275
2300
StringRef OutputFilename) const {
2276
2301
std::error_code EC;
@@ -2343,6 +2368,63 @@ std::error_code DataAggregator::writeBATYAML(BinaryContext &BC,
2343
2368
YamlBB.Successors .emplace_back (SI);
2344
2369
};
2345
2370
2371
+ std::unordered_map<uint32_t , std::vector<uint32_t >> BFBranches =
2372
+ BAT->getBFBranches (FuncAddress);
2373
+
2374
+ auto addCallsProfile = [&](yaml::bolt::BinaryBasicBlockProfile &YamlBB,
2375
+ uint64_t Offset) {
2376
+ // Iterate over BRANCHENTRY records in the current block
2377
+ for (uint32_t BranchOffset : BFBranches[Offset]) {
2378
+ if (!Branches.InterIndex .contains (BranchOffset))
2379
+ continue ;
2380
+ for (const auto &[CallToLoc, CallToIdx] :
2381
+ Branches.InterIndex .at (BranchOffset)) {
2382
+ const llvm::bolt::BranchInfo &BI = Branches.Data .at (CallToIdx);
2383
+ yaml::bolt::CallSiteInfo YamlCSI;
2384
+ YamlCSI.DestId = 0 ; // designated for unknown functions
2385
+ YamlCSI.EntryDiscriminator = 0 ;
2386
+ YamlCSI.Count = BI.Branches ;
2387
+ YamlCSI.Mispreds = BI.Mispreds ;
2388
+ YamlCSI.Offset = BranchOffset - Offset;
2389
+ BinaryData *CallTargetBD = BC.getBinaryDataByName (CallToLoc.Name );
2390
+ if (!CallTargetBD) {
2391
+ YamlBB.CallSites .emplace_back (YamlCSI);
2392
+ continue ;
2393
+ }
2394
+ uint64_t CallTargetAddress = CallTargetBD->getAddress ();
2395
+ BinaryFunction *CallTargetBF =
2396
+ BC.getBinaryFunctionAtAddress (CallTargetAddress);
2397
+ if (!CallTargetBF) {
2398
+ YamlBB.CallSites .emplace_back (YamlCSI);
2399
+ continue ;
2400
+ }
2401
+ // Calls between hot and cold fragments must be handled in
2402
+ // fixupBATProfile.
2403
+ assert (CallTargetBF != BF && " invalid CallTargetBF" );
2404
+ YamlCSI.DestId = CallTargetBF->getFunctionNumber ();
2405
+ if (CallToLoc.Offset ) {
2406
+ if (BAT->isBATFunction (CallTargetAddress)) {
2407
+ LLVM_DEBUG (dbgs () << " BOLT-DEBUG: Unsupported secondary "
2408
+ " entry point in BAT function "
2409
+ << CallToLoc.Name << ' \n ' );
2410
+ } else if (const BinaryBasicBlock *CallTargetBB =
2411
+ CallTargetBF->getBasicBlockAtOffset (
2412
+ CallToLoc.Offset )) {
2413
+ // Only record true call information, ignoring returns (normally
2414
+ // won't have a target basic block) and jumps to the landing
2415
+ // pads (not an entry point).
2416
+ if (CallTargetBB->isEntryPoint ()) {
2417
+ YamlCSI.EntryDiscriminator =
2418
+ CallTargetBF->getEntryIDForSymbol (
2419
+ CallTargetBB->getLabel ());
2420
+ }
2421
+ }
2422
+ }
2423
+ YamlBB.CallSites .emplace_back (YamlCSI);
2424
+ }
2425
+ }
2426
+ };
2427
+
2346
2428
for (const auto &[FromOffset, SuccKV] : Branches.IntraIndex ) {
2347
2429
yaml::bolt::BinaryBasicBlockProfile YamlBB;
2348
2430
if (!BlockMap.isInputBlock (FromOffset))
@@ -2351,7 +2433,9 @@ std::error_code DataAggregator::writeBATYAML(BinaryContext &BC,
2351
2433
YamlBB.Hash = BlockMap.getBBHash (FromOffset);
2352
2434
for (const auto &[SuccOffset, SuccDataIdx] : SuccKV)
2353
2435
addSuccProfile (YamlBB, SuccOffset, SuccDataIdx);
2354
- if (YamlBB.ExecCount || !YamlBB.Successors .empty ())
2436
+ addCallsProfile (YamlBB, FromOffset);
2437
+ if (YamlBB.ExecCount || !YamlBB.Successors .empty () ||
2438
+ !YamlBB.CallSites .empty ())
2355
2439
YamlBF.Blocks .emplace_back (YamlBB);
2356
2440
}
2357
2441
BP.Functions .emplace_back (YamlBF);
0 commit comments