diff --git a/bolt/include/bolt/Profile/ProfileYAMLMapping.h b/bolt/include/bolt/Profile/ProfileYAMLMapping.h index c4e5f2b284a8..2a0514d7d930 100644 --- a/bolt/include/bolt/Profile/ProfileYAMLMapping.h +++ b/bolt/include/bolt/Profile/ProfileYAMLMapping.h @@ -93,11 +93,36 @@ template <> struct MappingTraits { static const bool flow = true; }; +namespace bolt { +struct PseudoProbeInfo { + llvm::yaml::Hex64 GUID; + uint64_t Index; + uint8_t Type; + + bool operator==(const PseudoProbeInfo &Other) const { + return GUID == Other.GUID && Index == Other.Index; + } + bool operator!=(const PseudoProbeInfo &Other) const { + return !(*this == Other); + } +}; +} // end namespace bolt + +template <> struct MappingTraits { + static void mapping(IO &YamlIO, bolt::PseudoProbeInfo &PI) { + YamlIO.mapRequired("guid", PI.GUID); + YamlIO.mapRequired("id", PI.Index); + YamlIO.mapRequired("type", PI.Type); + } + + static const bool flow = true; +}; } // end namespace yaml } // end namespace llvm LLVM_YAML_IS_FLOW_SEQUENCE_VECTOR(llvm::yaml::bolt::CallSiteInfo) LLVM_YAML_IS_FLOW_SEQUENCE_VECTOR(llvm::yaml::bolt::SuccessorInfo) +LLVM_YAML_IS_FLOW_SEQUENCE_VECTOR(llvm::yaml::bolt::PseudoProbeInfo) namespace llvm { namespace yaml { @@ -111,6 +136,7 @@ struct BinaryBasicBlockProfile { uint64_t EventCount{0}; std::vector CallSites; std::vector Successors; + std::vector PseudoProbes; bool operator==(const BinaryBasicBlockProfile &Other) const { return Index == Other.Index; @@ -132,6 +158,8 @@ template <> struct MappingTraits { std::vector()); YamlIO.mapOptional("succ", BBP.Successors, std::vector()); + YamlIO.mapOptional("pseudo_probes", BBP.PseudoProbes, + std::vector()); } }; diff --git a/bolt/lib/Profile/DataAggregator.cpp b/bolt/lib/Profile/DataAggregator.cpp index fd0a526e31b7..c9668bddd0d7 100644 --- a/bolt/lib/Profile/DataAggregator.cpp +++ b/bolt/lib/Profile/DataAggregator.cpp @@ -2406,6 +2406,26 @@ std::error_code DataAggregator::writeBATYAML(BinaryContext &BC, PseudoProbeDecoder->getFuncDescForGUID(YamlBF.GUID); YamlBF.PseudoProbeDescHash = FuncDesc->FuncHash; } + // Fetch probes belonging to all fragments + const AddressProbesMap &ProbeMap = + PseudoProbeDecoder->getAddress2ProbesMap(); + BinaryFunction::FragmentsSetTy Fragments(BF->Fragments); + Fragments.insert(BF); + for (const BinaryFunction *F : Fragments) { + const uint64_t FuncAddr = F->getAddress(); + const auto &FragmentProbes = + llvm::make_range(ProbeMap.lower_bound(FuncAddr), + ProbeMap.lower_bound(FuncAddr + F->getSize())); + for (const auto &[OutputAddress, Probes] : FragmentProbes) { + const uint32_t InputOffset = BAT->translate( + FuncAddr, OutputAddress - FuncAddr, /*IsBranchSrc=*/true); + const unsigned BlockIndex = getBlock(InputOffset).second; + for (const MCDecodedPseudoProbe &Probe : Probes) + YamlBF.Blocks[BlockIndex].PseudoProbes.emplace_back( + yaml::bolt::PseudoProbeInfo{Probe.getGuid(), Probe.getIndex(), + Probe.getType()}); + } + } } // Drop blocks without a hash, won't be useful for stale matching. llvm::erase_if(YamlBF.Blocks, diff --git a/bolt/lib/Profile/YAMLProfileWriter.cpp b/bolt/lib/Profile/YAMLProfileWriter.cpp index 82d70e540e5e..b9fcb5df29fd 100644 --- a/bolt/lib/Profile/YAMLProfileWriter.cpp +++ b/bolt/lib/Profile/YAMLProfileWriter.cpp @@ -185,6 +185,21 @@ YAMLProfileWriter::convert(const BinaryFunction &BF, bool UseDFS, ++BranchInfo; } + if (PseudoProbeDecoder) { + const AddressProbesMap &ProbeMap = + PseudoProbeDecoder->getAddress2ProbesMap(); + const uint64_t FuncAddr = BF.getAddress(); + const std::pair &BlockRange = + BB->getInputAddressRange(); + const auto &BlockProbes = + llvm::make_range(ProbeMap.lower_bound(FuncAddr + BlockRange.first), + ProbeMap.lower_bound(FuncAddr + BlockRange.second)); + for (const auto &[_, Probes] : BlockProbes) + for (const MCDecodedPseudoProbe &Probe : Probes) + YamlBB.PseudoProbes.emplace_back(yaml::bolt::PseudoProbeInfo{ + Probe.getGuid(), Probe.getIndex(), Probe.getType()}); + } + YamlBF.Blocks.emplace_back(YamlBB); } return YamlBF; diff --git a/bolt/test/X86/pseudoprobe-decoding-inline.test b/bolt/test/X86/pseudoprobe-decoding-inline.test index c32660c41a09..924331e34c76 100644 --- a/bolt/test/X86/pseudoprobe-decoding-inline.test +++ b/bolt/test/X86/pseudoprobe-decoding-inline.test @@ -13,12 +13,20 @@ # RUN: perf2bolt %t.bolt -p %t.preagg2 --pa -w %t.yaml2 -o %t.fdata2 # RUN: FileCheck --input-file %t.yaml2 %s --check-prefix CHECK-YAML # CHECK-YAML: name: bar +# CHECK-YAML: - bid: 0 +# CHECK-YAML: pseudo_probes: [ { guid: 0xE413754A191DB537, id: 1, type: 0 }, { guid: 0xE413754A191DB537, id: 4, type: 0 } ] # CHECK-YAML: guid: 0xE413754A191DB537 # CHECK-YAML: pseudo_probe_desc_hash: 0x10E852DA94 +# # CHECK-YAML: name: foo +# CHECK-YAML: - bid: 0 +# CHECK-YAML: pseudo_probes: [ { guid: 0x5CF8C24CDB18BDAC, id: 1, type: 0 }, { guid: 0x5CF8C24CDB18BDAC, id: 2, type: 0 } ] # CHECK-YAML: guid: 0x5CF8C24CDB18BDAC # CHECK-YAML: pseudo_probe_desc_hash: 0x200205A19C5B4 +# # CHECK-YAML: name: main +# CHECK-YAML: - bid: 0 +# CHECK-YAML: pseudo_probes: [ { guid: 0xDB956436E78DD5FA, id: 1, type: 0 }, { guid: 0x5CF8C24CDB18BDAC, id: 1, type: 0 }, { guid: 0x5CF8C24CDB18BDAC, id: 2, type: 0 } ] # CHECK-YAML: guid: 0xDB956436E78DD5FA # CHECK-YAML: pseudo_probe_desc_hash: 0x10000FFFFFFFF