@@ -604,6 +604,8 @@ Error DataAggregator::readProfile(BinaryContext &BC) {
604604 // BAT YAML is handled by DataAggregator since normal YAML output requires
605605 // CFG which is not available in BAT mode.
606606 if (usesBAT ()) {
607+ // Postprocess split function profile for BAT
608+ fixupBATProfile (BC);
607609 if (opts::ProfileFormat == opts::ProfileFormatKind::PF_YAML)
608610 if (std::error_code EC = writeBATYAML (BC, opts::OutputFilename))
609611 report_error (" cannot create output data file" , EC);
@@ -2271,6 +2273,29 @@ DataAggregator::writeAggregatedFile(StringRef OutputFilename) const {
22712273 return std::error_code ();
22722274}
22732275
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+
22742299std::error_code DataAggregator::writeBATYAML (BinaryContext &BC,
22752300 StringRef OutputFilename) const {
22762301 std::error_code EC;
@@ -2343,6 +2368,63 @@ std::error_code DataAggregator::writeBATYAML(BinaryContext &BC,
23432368 YamlBB.Successors .emplace_back (SI);
23442369 };
23452370
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+
23462428 for (const auto &[FromOffset, SuccKV] : Branches.IntraIndex ) {
23472429 yaml::bolt::BinaryBasicBlockProfile YamlBB;
23482430 if (!BlockMap.isInputBlock (FromOffset))
@@ -2351,7 +2433,9 @@ std::error_code DataAggregator::writeBATYAML(BinaryContext &BC,
23512433 YamlBB.Hash = BlockMap.getBBHash (FromOffset);
23522434 for (const auto &[SuccOffset, SuccDataIdx] : SuccKV)
23532435 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 ())
23552439 YamlBF.Blocks .emplace_back (YamlBB);
23562440 }
23572441 BP.Functions .emplace_back (YamlBF);
0 commit comments