Skip to content

Commit b5e51c6

Browse files
committed
[𝘀𝗽𝗿] initial version
Created using spr 1.3.4
2 parents 4c3e032 + a921265 commit b5e51c6

14 files changed

+782
-413
lines changed

bolt/include/bolt/Core/BinaryContext.h

Lines changed: 4 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -760,10 +760,8 @@ class BinaryContext {
760760
uint32_t NumExactMatchedBlocks{0};
761761
/// the number of loosely matched basic blocks
762762
uint32_t NumLooseMatchedBlocks{0};
763-
/// the number of exactly pseudo probe matched basic blocks
764-
uint32_t NumPseudoProbeExactMatchedBlocks{0};
765-
/// the number of loosely pseudo probe matched basic blocks
766-
uint32_t NumPseudoProbeLooseMatchedBlocks{0};
763+
/// the number of pseudo probe matched basic blocks
764+
uint32_t NumPseudoProbeMatchedBlocks{0};
767765
/// the number of call matched basic blocks
768766
uint32_t NumCallMatchedBlocks{0};
769767
/// the total count of samples in the profile
@@ -772,10 +770,8 @@ class BinaryContext {
772770
uint64_t ExactMatchedSampleCount{0};
773771
/// the count of loosely matched samples
774772
uint64_t LooseMatchedSampleCount{0};
775-
/// the count of exactly pseudo probe matched samples
776-
uint64_t PseudoProbeExactMatchedSampleCount{0};
777-
/// the count of loosely pseudo probe matched samples
778-
uint64_t PseudoProbeLooseMatchedSampleCount{0};
773+
/// the count of pseudo probe matched samples
774+
uint64_t PseudoProbeMatchedSampleCount{0};
779775
/// the count of call matched samples
780776
uint64_t CallMatchedSampleCount{0};
781777
} Stats;

bolt/include/bolt/Profile/ProfileYAMLMapping.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -140,6 +140,7 @@ struct BinaryBasicBlockProfile {
140140
std::vector<CallSiteInfo> CallSites;
141141
std::vector<SuccessorInfo> Successors;
142142
std::vector<PseudoProbeInfo> PseudoProbes;
143+
std::string PseudoProbesStr;
143144

144145
bool operator==(const BinaryBasicBlockProfile &Other) const {
145146
return Index == Other.Index;
@@ -163,6 +164,7 @@ template <> struct MappingTraits<bolt::BinaryBasicBlockProfile> {
163164
std::vector<bolt::SuccessorInfo>());
164165
YamlIO.mapOptional("probes", BBP.PseudoProbes,
165166
std::vector<bolt::PseudoProbeInfo>());
167+
YamlIO.mapOptional("probe", BBP.PseudoProbesStr, std::string());
166168
}
167169
};
168170

@@ -207,6 +209,7 @@ struct BinaryFunctionProfile {
207209
uint64_t ExternEntryCount{0};
208210
std::vector<BinaryBasicBlockProfile> Blocks;
209211
std::vector<InlineTreeNode> InlineTree;
212+
std::string InlineTreeStr;
210213
bool Used{false};
211214
};
212215
} // end namespace bolt
@@ -223,6 +226,7 @@ template <> struct MappingTraits<bolt::BinaryFunctionProfile> {
223226
std::vector<bolt::BinaryBasicBlockProfile>());
224227
YamlIO.mapOptional("inline_tree", BFP.InlineTree,
225228
std::vector<bolt::InlineTreeNode>());
229+
YamlIO.mapOptional("ppit", BFP.InlineTreeStr, std::string());
226230
}
227231
};
228232

bolt/include/bolt/Profile/YAMLProfileReader.h

Lines changed: 70 additions & 47 deletions
Original file line numberDiff line numberDiff line change
@@ -45,9 +45,6 @@ class YAMLProfileReader : public ProfileReaderBase {
4545
using ProfileLookupMap =
4646
DenseMap<uint32_t, yaml::bolt::BinaryFunctionProfile *>;
4747

48-
using GUIDInlineTreeMap =
49-
std::unordered_map<uint64_t, const MCDecodedPseudoProbeInlineTree *>;
50-
5148
/// A class for matching binary functions in functions in the YAML profile.
5249
/// First, a call graph is constructed for both profiled and binary functions.
5350
/// Then functions are hashed based on the names of their callee/caller
@@ -110,51 +107,40 @@ class YAMLProfileReader : public ProfileReaderBase {
110107
// (profile) (binary)
111108
// | blocks ^
112109
// v |
113-
// yaml::bolt::BinaryBasicBlockProfile ~= FlowBlock
114-
// ||| probes ^ (majority vote)
115-
// v ||| BBPseudoProbeToBlock
116-
// yaml::bolt::PseudoProbeInfo MCDecodedPseudoProbe
110+
// BinaryBasicBlockProfile BasicBlock
111+
// | probes ^
112+
// v | address
113+
// PseudoProbeInfo MCDecodedPseudoProbe
117114
// | InlineTreeIndex ^
118115
// v | probe id
119116
// [ profile node id (uint32_t) -> MCDecodedPseudoProbeInlineTree *]
120117
// InlineTreeNodeMapTy
121-
class InlineTreeNodeMapTy {
122-
DenseMap<uint32_t, const MCDecodedPseudoProbeInlineTree *> Map;
123-
124-
void mapInlineTreeNode(uint32_t ProfileNodeIdx,
125-
const MCDecodedPseudoProbeInlineTree *BinaryNode) {
126-
auto Res = Map.try_emplace(ProfileNodeIdx, BinaryNode);
127-
assert(Res.second &&
128-
"Duplicate mapping from profile node index to binary inline tree");
129-
(void)Res;
130-
}
131-
132-
public:
133-
/// Returns matched InlineTree * for a given profile inline_tree_id.
134-
const MCDecodedPseudoProbeInlineTree *
135-
getInlineTreeNode(uint32_t ProfileInlineTreeNodeId) const {
136-
auto It = Map.find(ProfileInlineTreeNodeId);
137-
if (It == Map.end())
138-
return nullptr;
139-
return It->second;
140-
}
118+
using InlineTreeNodeMapTy =
119+
std::vector<const MCDecodedPseudoProbeInlineTree *>;
141120

142-
// Match up \p YamlInlineTree with binary inline tree rooted at \p Root.
143-
// Return the number of matched nodes.
144-
//
145-
// This function populates the mapping from profile inline tree node id to a
146-
// corresponding binary MCDecodedPseudoProbeInlineTree node.
147-
size_t matchInlineTrees(
148-
const MCPseudoProbeDecoder &Decoder,
149-
const std::vector<yaml::bolt::InlineTreeNode> &YamlInlineTree,
150-
const MCDecodedPseudoProbeInlineTree *Root);
151-
};
152-
153-
// Partial probe matching specification: matched inline tree and corresponding
154-
// BinaryFunctionProfile
121+
// Match up \p YamlInlineTree with binary inline tree rooted at \p Root.
122+
// Return the number of matched nodes.
123+
//
124+
// This function populates the \p Map indexed by \p YamlInlineTree from
125+
// profile inline tree node id to a corresponding binary
126+
// MCDecodedPseudoProbeInlineTree node on a successful match or nullptr.
127+
size_t matchInlineTreesImpl(
128+
BinaryFunction &BF, yaml::bolt::BinaryFunctionProfile &YamlBF,
129+
const MCDecodedPseudoProbeInlineTree &Root, uint32_t RootIdx,
130+
ArrayRef<yaml::bolt::InlineTreeNode> YamlInlineTree,
131+
MutableArrayRef<const MCDecodedPseudoProbeInlineTree *> Map, float Scale);
132+
133+
/// Support mapping the profile to the same binary function more than once.
134+
/// The index is used to check and prevent recursive (backtracking) matches.
135+
/// The value is a node map and scale factor, used to downscale outlined
136+
/// profile when inlining it into the function.
137+
using RootIdxToMapTy =
138+
std::map<uint32_t, std::pair<InlineTreeNodeMapTy, float>>;
139+
/// Probe matching specification: map from \p BinaryFunctionProfile to the
140+
/// partial match specification \p RootIdxToMapTy.
155141
using ProbeMatchSpec =
156-
std::pair<InlineTreeNodeMapTy,
157-
std::reference_wrapper<yaml::bolt::BinaryFunctionProfile>>;
142+
std::unordered_map<const yaml::bolt::BinaryFunctionProfile *,
143+
RootIdxToMapTy>;
158144

159145
private:
160146
/// Adjustments for basic samples profiles (without LBR).
@@ -183,18 +169,43 @@ class YAMLProfileReader : public ProfileReaderBase {
183169
/// Map a common LTO prefix to a set of binary functions.
184170
StringMap<std::unordered_set<BinaryFunction *>> LTOCommonNameFunctionMap;
185171

172+
/// For pseudo probe function matching.
173+
/// Set of profile GUIDs.
174+
std::unordered_set<uint64_t> YamlGUIDs;
175+
/// Map binary function GUID to binary function.
176+
std::unordered_multimap<uint64_t, BinaryFunction *> GUIDToBF;
177+
186178
/// Function names in profile.
187179
StringSet<> ProfileFunctionNames;
188180

189181
/// BinaryFunction pointers indexed by YamlBP functions.
190182
std::vector<BinaryFunction *> ProfileBFs;
191183

192-
// Pseudo probe function GUID to inline tree node
193-
GUIDInlineTreeMap TopLevelGUIDToInlineTree;
194-
195184
// Mapping from a binary function to its partial match specification
196185
// (YAML profile and its inline tree mapping to binary).
197-
DenseMap<BinaryFunction *, std::vector<ProbeMatchSpec>> BFToProbeMatchSpecs;
186+
DenseMap<BinaryFunction *, ProbeMatchSpec> BFToProbeMatchSpecs;
187+
188+
/// Pseudo probe matching stats.
189+
struct {
190+
// Inline tree root mismatch causes.
191+
uint64_t MismatchingRootGUID{0};
192+
uint64_t MismatchingRootHash{0};
193+
// Inline tree internal node mismatch causes.
194+
uint64_t MismatchingNodeHash{0};
195+
uint64_t MissingProfileNode{0};
196+
// Incomplete profile causes.
197+
uint64_t MissingCallProbe{0};
198+
uint64_t MissingCallee{0};
199+
uint64_t MissingInlineTree{0};
200+
uint64_t TotalCallSites{0};
201+
uint64_t MissingCallCount{0};
202+
uint64_t TotalCallCount{0};
203+
// Total matched stats.
204+
uint64_t MatchedRoots{0};
205+
uint64_t MatchedNodes{0};
206+
uint64_t AttemptedNodes{0};
207+
uint64_t AttemptedRoots{0};
208+
} ProbeMatchingStats;
198209

199210
/// Populate \p Function profile with the one supplied in YAML format.
200211
bool parseFunctionProfile(BinaryFunction &Function,
@@ -207,7 +218,7 @@ class YAMLProfileReader : public ProfileReaderBase {
207218
/// Infer function profile from stale data (collected on older binaries).
208219
bool inferStaleProfile(BinaryFunction &Function,
209220
const yaml::bolt::BinaryFunctionProfile &YamlBF,
210-
const ArrayRef<ProbeMatchSpec> ProbeMatchSpecs);
221+
const ProbeMatchSpec &ProbeMatchSpecs);
211222

212223
/// Initialize maps for profile matching.
213224
void buildNameMaps(BinaryContext &BC);
@@ -242,6 +253,18 @@ class YAMLProfileReader : public ProfileReaderBase {
242253
ProfiledFunctions.emplace(&BF);
243254
}
244255

256+
/// Return a top-level binary inline tree node for a given \p BF
257+
const MCDecodedPseudoProbeInlineTree *
258+
lookupTopLevelNode(const BinaryFunction &BF);
259+
260+
/// Match up \p BF binary inline trees starting at root or \p Node if set, and
261+
/// \p YamlBF profile starting at \p NodeIdx and record the mapping in
262+
/// BFToProbeMatchSpecs.
263+
void matchInlineTrees(BinaryFunction &BF,
264+
const MCDecodedPseudoProbeInlineTree *Node,
265+
yaml::bolt::BinaryFunctionProfile &YamlBF,
266+
uint32_t NodeIdx, float Scale);
267+
245268
/// Check if the profile uses an event with a given \p Name.
246269
bool usesEvent(StringRef Name) const;
247270
};

bolt/include/bolt/Profile/YAMLProfileWriter.h

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -36,16 +36,14 @@ class YAMLProfileWriter {
3636
DenseMap<const MCDecodedPseudoProbeInlineTree *, uint32_t>;
3737
struct InlineTreeDesc {
3838
template <typename T> using GUIDMapTy = std::unordered_map<uint64_t, T>;
39-
using GUIDNodeMap = GUIDMapTy<const MCDecodedPseudoProbeInlineTree *>;
4039
using GUIDNumMap = GUIDMapTy<uint32_t>;
41-
GUIDNodeMap TopLevelGUIDToInlineTree;
4240
GUIDNumMap GUIDIdxMap;
4341
GUIDNumMap HashIdxMap;
4442
};
4543

46-
static std::tuple<std::vector<yaml::bolt::InlineTreeNode>, InlineTreeMapTy>
47-
convertBFInlineTree(const MCPseudoProbeDecoder &Decoder,
48-
const InlineTreeDesc &InlineTree, uint64_t GUID);
44+
static InlineTreeMapTy convertBFInlineTree(
45+
const MCPseudoProbeDecoder &Decoder, const InlineTreeDesc &InlineTree,
46+
const BinaryFunction &BF, yaml::bolt::BinaryFunctionProfile &YamlBF);
4947

5048
static std::tuple<yaml::bolt::ProfilePseudoProbeDesc, InlineTreeDesc>
5149
convertPseudoProbeDesc(const MCPseudoProbeDecoder &PseudoProbeDecoder);

bolt/include/bolt/Utils/CommandLineOpts.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -134,6 +134,7 @@ enum GadgetScannerKind { GS_PACRET, GS_PAUTH, GS_ALL };
134134

135135
extern llvm::cl::bits<GadgetScannerKind> GadgetScannersToRun;
136136

137+
enum ProbesWriteMode : char { PWM_None = 0, PWM_Default, PWM_Compact };
137138
} // namespace opts
138139

139140
namespace llvm {

bolt/lib/Passes/BinaryPasses.cpp

Lines changed: 5 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1555,25 +1555,14 @@ Error PrintProgramStats::runOnFunctions(BinaryContext &BC) {
15551555
100.0 * BC.Stats.ExactMatchedSampleCount / BC.Stats.StaleSampleCount,
15561556
BC.Stats.ExactMatchedSampleCount, BC.Stats.StaleSampleCount);
15571557
BC.outs() << format(
1558-
"BOLT-INFO: inference found an exact pseudo probe match for %.2f%% of "
1558+
"BOLT-INFO: inference found pseudo probe match for %.2f%% of "
15591559
"basic blocks (%zu out of %zu stale) responsible for %.2f%% samples"
15601560
" (%zu out of %zu stale)\n",
1561-
100.0 * BC.Stats.NumPseudoProbeExactMatchedBlocks /
1562-
BC.Stats.NumStaleBlocks,
1563-
BC.Stats.NumPseudoProbeExactMatchedBlocks, BC.Stats.NumStaleBlocks,
1564-
100.0 * BC.Stats.PseudoProbeExactMatchedSampleCount /
1561+
100.0 * BC.Stats.NumPseudoProbeMatchedBlocks / BC.Stats.NumStaleBlocks,
1562+
BC.Stats.NumPseudoProbeMatchedBlocks, BC.Stats.NumStaleBlocks,
1563+
100.0 * BC.Stats.PseudoProbeMatchedSampleCount /
15651564
BC.Stats.StaleSampleCount,
1566-
BC.Stats.PseudoProbeExactMatchedSampleCount, BC.Stats.StaleSampleCount);
1567-
BC.outs() << format(
1568-
"BOLT-INFO: inference found a loose pseudo probe match for %.2f%% of "
1569-
"basic blocks (%zu out of %zu stale) responsible for %.2f%% samples"
1570-
" (%zu out of %zu stale)\n",
1571-
100.0 * BC.Stats.NumPseudoProbeLooseMatchedBlocks /
1572-
BC.Stats.NumStaleBlocks,
1573-
BC.Stats.NumPseudoProbeLooseMatchedBlocks, BC.Stats.NumStaleBlocks,
1574-
100.0 * BC.Stats.PseudoProbeLooseMatchedSampleCount /
1575-
BC.Stats.StaleSampleCount,
1576-
BC.Stats.PseudoProbeLooseMatchedSampleCount, BC.Stats.StaleSampleCount);
1565+
BC.Stats.PseudoProbeMatchedSampleCount, BC.Stats.StaleSampleCount);
15771566
BC.outs() << format(
15781567
"BOLT-INFO: inference found a call match for %.2f%% of basic "
15791568
"blocks"

bolt/lib/Profile/DataAggregator.cpp

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -114,7 +114,7 @@ MaxSamples("max-samples",
114114
cl::cat(AggregatorCategory));
115115

116116
extern cl::opt<opts::ProfileFormatKind> ProfileFormat;
117-
extern cl::opt<bool> ProfileWritePseudoProbes;
117+
extern cl::opt<ProbesWriteMode> ProfileWritePseudoProbes;
118118
extern cl::opt<std::string> SaveProfile;
119119

120120
cl::opt<bool> ReadPreAggregated(
@@ -2388,9 +2388,8 @@ std::error_code DataAggregator::writeBATYAML(BinaryContext &BC,
23882388
DenseMap<const MCDecodedPseudoProbeInlineTree *, uint32_t>
23892389
InlineTreeNodeId;
23902390
if (BF->getGUID()) {
2391-
std::tie(YamlBF.InlineTree, InlineTreeNodeId) =
2392-
YAMLProfileWriter::convertBFInlineTree(*PseudoProbeDecoder,
2393-
InlineTree, BF->getGUID());
2391+
InlineTreeNodeId = YAMLProfileWriter::convertBFInlineTree(
2392+
*PseudoProbeDecoder, InlineTree, *BF, YamlBF);
23942393
}
23952394
// Fetch probes belonging to all fragments
23962395
const AddressProbesMap &ProbeMap =

0 commit comments

Comments
 (0)