LLVM 22.0.0git
ProfDataUtils.cpp
Go to the documentation of this file.
1//===- ProfDataUtils.cpp - Utility functions for MD_prof Metadata ---------===//
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// This file implements utilities for working with Profiling Metadata.
10//
11//===----------------------------------------------------------------------===//
12
14
15#include "llvm/ADT/STLExtras.h"
17#include "llvm/IR/Constants.h"
18#include "llvm/IR/Function.h"
20#include "llvm/IR/LLVMContext.h"
21#include "llvm/IR/MDBuilder.h"
22#include "llvm/IR/Metadata.h"
24
25using namespace llvm;
26
27// MD_prof nodes have the following layout
28//
29// In general:
30// { String name, Array of i32 }
31//
32// In terms of Types:
33// { MDString, [i32, i32, ...]}
34//
35// Concretely for Branch Weights
36// { "branch_weights", [i32 1, i32 10000]}
37//
38// We maintain some constants here to ensure that we access the branch weights
39// correctly, and can change the behavior in the future if the layout changes
40
41// the minimum number of operands for MD_prof nodes with branch weights
42static constexpr unsigned MinBWOps = 3;
43
44// the minimum number of operands for MD_prof nodes with value profiles
45static constexpr unsigned MinVPOps = 5;
46
47// We may want to add support for other MD_prof types, so provide an abstraction
48// for checking the metadata type.
49static bool isTargetMD(const MDNode *ProfData, const char *Name,
50 unsigned MinOps) {
51 // TODO: This routine may be simplified if MD_prof used an enum instead of a
52 // string to differentiate the types of MD_prof nodes.
53 if (!ProfData || !Name || MinOps < 2)
54 return false;
55
56 unsigned NOps = ProfData->getNumOperands();
57 if (NOps < MinOps)
58 return false;
59
60 auto *ProfDataName = dyn_cast<MDString>(ProfData->getOperand(0));
61 if (!ProfDataName)
62 return false;
63
64 return ProfDataName->getString() == Name;
65}
66
67template <typename T,
68 typename = typename std::enable_if<std::is_arithmetic_v<T>>>
69static void extractFromBranchWeightMD(const MDNode *ProfileData,
70 SmallVectorImpl<T> &Weights) {
71 assert(isBranchWeightMD(ProfileData) && "wrong metadata");
72
73 unsigned NOps = ProfileData->getNumOperands();
74 unsigned WeightsIdx = getBranchWeightOffset(ProfileData);
75 assert(WeightsIdx < NOps && "Weights Index must be less than NOps.");
76 Weights.resize(NOps - WeightsIdx);
77
78 for (unsigned Idx = WeightsIdx, E = NOps; Idx != E; ++Idx) {
79 ConstantInt *Weight =
81 assert(Weight && "Malformed branch_weight in MD_prof node");
82 assert(Weight->getValue().getActiveBits() <= (sizeof(T) * 8) &&
83 "Too many bits for MD_prof branch_weight");
84 Weights[Idx - WeightsIdx] = Weight->getZExtValue();
85 }
86}
87
88/// Push the weights right to fit in uint32_t.
91 Ret.reserve(Weights.size());
92 uint64_t Max = *llvm::max_element(Weights);
93 if (Max > UINT_MAX) {
94 unsigned Offset = 32 - llvm::countl_zero(Max);
95 for (const uint64_t &Value : Weights)
96 Ret.push_back(static_cast<uint32_t>(Value >> Offset));
97 } else {
98 append_range(Ret, Weights);
99 }
100 return Ret;
101}
102
103static cl::opt<bool> ElideAllZeroBranchWeights("elide-all-zero-branch-weights",
104#if defined(LLVM_ENABLE_PROFCHECK)
105 cl::init(false)
106#else
107 cl::init(true)
108#endif
109);
110const char *MDProfLabels::BranchWeights = "branch_weights";
111const char *MDProfLabels::ExpectedBranchWeights = "expected";
112const char *MDProfLabels::ValueProfile = "VP";
113const char *MDProfLabels::FunctionEntryCount = "function_entry_count";
115 "synthetic_function_entry_count";
116const char *MDProfLabels::UnknownBranchWeightsMarker = "unknown";
117const char *llvm::LLVMLoopEstimatedTripCount = "llvm.loop.estimated_trip_count";
118
120 return I.hasMetadata(LLVMContext::MD_prof);
121}
122
123bool llvm::isBranchWeightMD(const MDNode *ProfileData) {
124 return isTargetMD(ProfileData, MDProfLabels::BranchWeights, MinBWOps);
125}
126
127bool llvm::isValueProfileMD(const MDNode *ProfileData) {
128 return isTargetMD(ProfileData, MDProfLabels::ValueProfile, MinVPOps);
129}
130
132 auto *ProfileData = I.getMetadata(LLVMContext::MD_prof);
133 return isBranchWeightMD(ProfileData);
134}
135
136static bool hasCountTypeMD(const Instruction &I) {
137 auto *ProfileData = I.getMetadata(LLVMContext::MD_prof);
138 // Value profiles record count-type information.
139 if (isValueProfileMD(ProfileData))
140 return true;
141 // Conservatively assume non CallBase instruction only get taken/not-taken
142 // branch probability, so not interpret them as count.
143 return isa<CallBase>(I) && !isBranchWeightMD(ProfileData);
144}
145
149
151 auto *ProfileData = I.getMetadata(LLVMContext::MD_prof);
152 return hasBranchWeightOrigin(ProfileData);
153}
154
155bool llvm::hasBranchWeightOrigin(const MDNode *ProfileData) {
156 if (!isBranchWeightMD(ProfileData))
157 return false;
158 auto *ProfDataName = dyn_cast<MDString>(ProfileData->getOperand(1));
159 // NOTE: if we ever have more types of branch weight provenance,
160 // we need to check the string value is "expected". For now, we
161 // supply a more generic API, and avoid the spurious comparisons.
162 assert(ProfDataName == nullptr ||
163 ProfDataName->getString() == MDProfLabels::ExpectedBranchWeights);
164 return ProfDataName != nullptr;
165}
166
167unsigned llvm::getBranchWeightOffset(const MDNode *ProfileData) {
168 return hasBranchWeightOrigin(ProfileData) ? 2 : 1;
169}
170
171unsigned llvm::getNumBranchWeights(const MDNode &ProfileData) {
172 return ProfileData.getNumOperands() - getBranchWeightOffset(&ProfileData);
173}
174
176 auto *ProfileData = I.getMetadata(LLVMContext::MD_prof);
177 if (!isBranchWeightMD(ProfileData))
178 return nullptr;
179 return ProfileData;
180}
181
183 auto *ProfileData = getBranchWeightMDNode(I);
184 if (ProfileData && getNumBranchWeights(*ProfileData) == I.getNumSuccessors())
185 return ProfileData;
186 return nullptr;
187}
188
190 SmallVectorImpl<uint32_t> &Weights) {
191 extractFromBranchWeightMD(ProfileData, Weights);
192}
193
195 SmallVectorImpl<uint64_t> &Weights) {
196 extractFromBranchWeightMD(ProfileData, Weights);
197}
198
199bool llvm::extractBranchWeights(const MDNode *ProfileData,
200 SmallVectorImpl<uint32_t> &Weights) {
201 if (!isBranchWeightMD(ProfileData))
202 return false;
203 extractFromBranchWeightMD(ProfileData, Weights);
204 return true;
205}
206
208 SmallVectorImpl<uint32_t> &Weights) {
209 auto *ProfileData = I.getMetadata(LLVMContext::MD_prof);
210 return extractBranchWeights(ProfileData, Weights);
211}
212
214 uint64_t &FalseVal) {
215 assert((I.getOpcode() == Instruction::Br ||
216 I.getOpcode() == Instruction::Select) &&
217 "Looking for branch weights on something besides branch, select, or "
218 "switch");
219
221 auto *ProfileData = I.getMetadata(LLVMContext::MD_prof);
222 if (!extractBranchWeights(ProfileData, Weights))
223 return false;
224
225 if (Weights.size() > 2)
226 return false;
227
228 TrueVal = Weights[0];
229 FalseVal = Weights[1];
230 return true;
231}
232
233bool llvm::extractProfTotalWeight(const MDNode *ProfileData,
234 uint64_t &TotalVal) {
235 TotalVal = 0;
236 if (!ProfileData)
237 return false;
238
239 auto *ProfDataName = dyn_cast<MDString>(ProfileData->getOperand(0));
240 if (!ProfDataName)
241 return false;
242
243 if (ProfDataName->getString() == MDProfLabels::BranchWeights) {
244 unsigned Offset = getBranchWeightOffset(ProfileData);
245 for (unsigned Idx = Offset; Idx < ProfileData->getNumOperands(); ++Idx) {
246 auto *V = mdconst::extract<ConstantInt>(ProfileData->getOperand(Idx));
247 TotalVal += V->getValue().getZExtValue();
248 }
249 return true;
250 }
251
252 if (ProfDataName->getString() == MDProfLabels::ValueProfile &&
253 ProfileData->getNumOperands() > 3) {
254 TotalVal = mdconst::dyn_extract<ConstantInt>(ProfileData->getOperand(2))
255 ->getValue()
256 .getZExtValue();
257 return true;
258 }
259 return false;
260}
261
263 return extractProfTotalWeight(I.getMetadata(LLVMContext::MD_prof), TotalVal);
264}
265
268 MDBuilder MDB(I.getContext());
269 I.setMetadata(
270 LLVMContext::MD_prof,
271 MDNode::get(I.getContext(),
272 {MDB.createString(MDProfLabels::UnknownBranchWeightsMarker),
273 MDB.createString(PassName)}));
274}
275
277 Function &F,
279 if (std::optional<Function::ProfileCount> EC = F.getEntryCount();
280 EC && EC->getCount() > 0)
282}
283
286 MDBuilder MDB(F.getContext());
287 F.setMetadata(
288 LLVMContext::MD_prof,
289 MDNode::get(F.getContext(),
290 {MDB.createString(MDProfLabels::UnknownBranchWeightsMarker),
291 MDB.createString(PassName)}));
292}
293
295 if (MD.getNumOperands() != 2)
296 return false;
298}
299
301 auto *MD = I.getMetadata(LLVMContext::MD_prof);
302 if (!MD)
303 return false;
305}
306
308 bool IsExpected, bool ElideAllZero) {
309 if ((ElideAllZeroBranchWeights && ElideAllZero) &&
310 llvm::all_of(Weights, [](uint32_t V) { return V == 0; })) {
311 I.setMetadata(LLVMContext::MD_prof, nullptr);
312 return;
313 }
314
315 MDBuilder MDB(I.getContext());
316 MDNode *BranchWeights = MDB.createBranchWeights(Weights, IsExpected);
317 I.setMetadata(LLVMContext::MD_prof, BranchWeights);
318}
319
321 bool IsExpected, bool ElideAllZero) {
322 setBranchWeights(I, fitWeights(Weights), IsExpected, ElideAllZero);
323}
324
327 std::optional<uint64_t> KnownMaxCount) {
328 uint64_t MaxCount = KnownMaxCount.has_value() ? KnownMaxCount.value()
329 : *llvm::max_element(Weights);
330 assert(MaxCount > 0 && "Bad max count");
331 uint64_t Scale = calculateCountScale(MaxCount);
332 SmallVector<uint32_t> DownscaledWeights;
333 for (const auto &ECI : Weights)
334 DownscaledWeights.push_back(scaleBranchCount(ECI, Scale));
335 return DownscaledWeights;
336}
337
339 assert(T != 0 && "Caller should guarantee");
340 auto *ProfileData = I.getMetadata(LLVMContext::MD_prof);
341 if (ProfileData == nullptr)
342 return;
343
344 auto *ProfDataName = dyn_cast<MDString>(ProfileData->getOperand(0));
345 if (!ProfDataName ||
346 (ProfDataName->getString() != MDProfLabels::BranchWeights &&
347 ProfDataName->getString() != MDProfLabels::ValueProfile))
348 return;
349
350 if (!hasCountTypeMD(I))
351 return;
352
353 LLVMContext &C = I.getContext();
354
355 MDBuilder MDB(C);
357 Vals.push_back(ProfileData->getOperand(0));
358 APInt APS(128, S), APT(128, T);
359 if (ProfDataName->getString() == MDProfLabels::BranchWeights &&
360 ProfileData->getNumOperands() > 0) {
361 // Using APInt::div may be expensive, but most cases should fit 64 bits.
362 APInt Val(128,
364 ProfileData->getOperand(getBranchWeightOffset(ProfileData)))
365 ->getValue()
366 .getZExtValue());
367 Val *= APS;
368 Vals.push_back(MDB.createConstant(ConstantInt::get(
369 Type::getInt32Ty(C), Val.udiv(APT).getLimitedValue(UINT32_MAX))));
370 } else if (ProfDataName->getString() == MDProfLabels::ValueProfile)
371 for (unsigned Idx = 1; Idx < ProfileData->getNumOperands(); Idx += 2) {
372 // The first value is the key of the value profile, which will not change.
373 Vals.push_back(ProfileData->getOperand(Idx));
375 mdconst::dyn_extract<ConstantInt>(ProfileData->getOperand(Idx + 1))
376 ->getValue()
377 .getZExtValue();
378 // Don't scale the magic number.
379 if (Count == NOMORE_ICP_MAGICNUM) {
380 Vals.push_back(ProfileData->getOperand(Idx + 1));
381 continue;
382 }
383 // Using APInt::div may be expensive, but most cases should fit 64 bits.
384 APInt Val(128, Count);
385 Val *= APS;
386 Vals.push_back(MDB.createConstant(ConstantInt::get(
387 Type::getInt64Ty(C), Val.udiv(APT).getLimitedValue())));
388 }
389 I.setMetadata(LLVMContext::MD_prof, MDNode::get(C, Vals));
390}
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
static GCRegistry::Add< CoreCLRGC > E("coreclr", "CoreCLR-compatible GC")
This file contains the declarations for the subclasses of Constant, which represent the different fla...
#define F(x, y, z)
Definition MD5.cpp:55
#define I(x, y, z)
Definition MD5.cpp:58
This file contains the declarations for metadata subclasses.
#define T
static SmallVector< uint32_t > fitWeights(ArrayRef< uint64_t > Weights)
Push the weights right to fit in uint32_t.
static constexpr unsigned MinVPOps
static cl::opt< bool > ElideAllZeroBranchWeights("elide-all-zero-branch-weights", cl::init(true))
static bool isTargetMD(const MDNode *ProfData, const char *Name, unsigned MinOps)
static void extractFromBranchWeightMD(const MDNode *ProfileData, SmallVectorImpl< T > &Weights)
static bool hasCountTypeMD(const Instruction &I)
static constexpr unsigned MinBWOps
This file contains the declarations for profiling metadata utility functions.
This file contains some templates that are useful if you are working with the STL at all.
This file defines the SmallVector class.
static const char PassName[]
Class for arbitrary precision integers.
Definition APInt.h:78
LLVM_ABI APInt udiv(const APInt &RHS) const
Unsigned division operation.
Definition APInt.cpp:1573
unsigned getActiveBits() const
Compute the number of active bits in the value.
Definition APInt.h:1512
uint64_t getLimitedValue(uint64_t Limit=UINT64_MAX) const
If this value is smaller than the specified limit, return it, otherwise return the limit value.
Definition APInt.h:475
ArrayRef - Represent a constant reference to an array (0 or more elements consecutively in memory),...
Definition ArrayRef.h:41
size_t size() const
size - Get the array size.
Definition ArrayRef.h:147
This is the shared class of boolean and integer constants.
Definition Constants.h:87
uint64_t getZExtValue() const
Return the constant as a 64-bit unsigned integer value after it has been zero extended as appropriate...
Definition Constants.h:163
const APInt & getValue() const
Return the constant as an APInt value reference.
Definition Constants.h:154
This is an important class for using LLVM in a threaded context.
Definition LLVMContext.h:68
LLVM_ABI ConstantAsMetadata * createConstant(Constant *C)
Return the given constant as metadata.
Definition MDBuilder.cpp:25
LLVM_ABI MDNode * createBranchWeights(uint32_t TrueWeight, uint32_t FalseWeight, bool IsExpected=false)
Return metadata containing two branch weights.
Definition MDBuilder.cpp:38
Metadata node.
Definition Metadata.h:1078
const MDOperand & getOperand(unsigned I) const
Definition Metadata.h:1442
static MDTuple * get(LLVMContext &Context, ArrayRef< Metadata * > MDs)
Definition Metadata.h:1569
unsigned getNumOperands() const
Return number of MDNode operands.
Definition Metadata.h:1448
bool equalsStr(StringRef Str) const
Definition Metadata.h:922
This class consists of common code factored out of the SmallVector class to reduce code duplication b...
void resize(size_type N)
void push_back(const T &Elt)
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
StringRef - Represent a constant reference to a string, i.e.
Definition StringRef.h:55
static LLVM_ABI IntegerType * getInt64Ty(LLVMContext &C)
Definition Type.cpp:298
static LLVM_ABI IntegerType * getInt32Ty(LLVMContext &C)
Definition Type.cpp:297
LLVM Value Representation.
Definition Value.h:75
@ C
The default llvm calling convention, compatible with C.
Definition CallingConv.h:34
initializer< Ty > init(const Ty &Val)
std::enable_if_t< detail::IsValidPointer< X, Y >::value, X * > dyn_extract(Y &&MD)
Extract a Value from Metadata, if any.
Definition Metadata.h:695
std::enable_if_t< detail::IsValidPointer< X, Y >::value, X * > extract(Y &&MD)
Extract a Value from Metadata.
Definition Metadata.h:667
This is an optimization pass for GlobalISel generic memory operations.
@ Offset
Definition DWP.cpp:477
bool all_of(R &&range, UnaryPredicate P)
Provide wrappers to std::all_of which take ranges instead of having to pass begin/end explicitly.
Definition STLExtras.h:1705
LLVM_ABI bool extractProfTotalWeight(const MDNode *ProfileData, uint64_t &TotalWeights)
Retrieve the total of all weights from MD_prof data.
LLVM_ABI unsigned getBranchWeightOffset(const MDNode *ProfileData)
Return the offset to the first branch weight data.
LLVM_ABI bool isBranchWeightMD(const MDNode *ProfileData)
Checks if an MDNode contains Branch Weight Metadata.
decltype(auto) dyn_cast(const From &Val)
dyn_cast<X> - Return the argument parameter cast to the specified type.
Definition Casting.h:644
LLVM_ABI void setExplicitlyUnknownBranchWeightsIfProfiled(Instruction &I, Function &F, StringRef PassName)
Like setExplicitlyUnknownBranchWeights(...), but only sets unknown branch weights in the new instruct...
LLVM_ABI bool isExplicitlyUnknownProfileMetadata(const MDNode &MD)
LLVM_ABI MDNode * getBranchWeightMDNode(const Instruction &I)
Get the branch weights metadata node.
void append_range(Container &C, Range &&R)
Wrapper function to append range R to container C.
Definition STLExtras.h:2116
LLVM_ABI void setExplicitlyUnknownBranchWeights(Instruction &I, StringRef PassName)
Specify that the branch weights for this terminator cannot be known at compile time.
LLVM_ABI bool hasBranchWeightOrigin(const Instruction &I)
Check if Branch Weight Metadata has an "expected" field from an llvm.expect* intrinsic.
LLVM_ABI void setBranchWeights(Instruction &I, ArrayRef< uint32_t > Weights, bool IsExpected, bool ElideAllZero=false)
Create a new branch_weights metadata node and add or overwrite a prof metadata reference to instructi...
int countl_zero(T Val)
Count number of 0's from the most significant bit to the least stopping at the first 1.
Definition bit.h:222
LLVM_ABI MDNode * getValidBranchWeightMDNode(const Instruction &I)
Get the valid branch weights metadata node.
LLVM_ABI bool hasValidBranchWeightMD(const Instruction &I)
Checks if an instructions has valid Branch Weight Metadata.
FunctionAddr VTableAddr Count
Definition InstrProf.h:139
bool isa(const From &Val)
isa<X> - Return true if the parameter to the template is an instance of one of the template type argu...
Definition Casting.h:548
LLVM_ABI void setExplicitlyUnknownFunctionEntryCount(Function &F, StringRef PassName)
Analogous to setExplicitlyUnknownBranchWeights, but for functions and their entry counts.
LLVM_ABI bool isValueProfileMD(const MDNode *ProfileData)
Checks if an MDNode contains value profiling Metadata.
LLVM_ABI unsigned getNumBranchWeights(const MDNode &ProfileData)
LLVM_ABI void extractFromBranchWeightMD32(const MDNode *ProfileData, SmallVectorImpl< uint32_t > &Weights)
Faster version of extractBranchWeights() that skips checks and must only be called with "branch_weigh...
LLVM_ABI bool hasExplicitlyUnknownBranchWeights(const Instruction &I)
LLVM_ABI bool hasProfMD(const Instruction &I)
Checks if an Instruction has MD_prof Metadata.
auto max_element(R &&Range)
Provide wrappers to std::max_element which take ranges instead of having to pass begin/end explicitly...
Definition STLExtras.h:2010
LLVM_ABI bool extractBranchWeights(const MDNode *ProfileData, SmallVectorImpl< uint32_t > &Weights)
Extract branch weights from MD_prof metadata.
LLVM_ABI const char * LLVMLoopEstimatedTripCount
Profile-based loop metadata that should be accessed only by using llvm::getLoopEstimatedTripCount and...
uint32_t scaleBranchCount(uint64_t Count, uint64_t Scale)
Scale an individual branch count.
LLVM_ABI bool hasBranchWeightMD(const Instruction &I)
Checks if an instructions has Branch Weight Metadata.
LLVM_ABI void setFittedBranchWeights(Instruction &I, ArrayRef< uint64_t > Weights, bool IsExpected, bool ElideAllZero=false)
Variant of setBranchWeights where the Weights will be fit first to uint32_t by shifting right.
uint64_t calculateCountScale(uint64_t MaxCount)
Calculate what to divide by to scale counts.
LLVM_ABI SmallVector< uint32_t > downscaleWeights(ArrayRef< uint64_t > Weights, std::optional< uint64_t > KnownMaxCount=std::nullopt)
downscale the given weights preserving the ratio.
const uint64_t NOMORE_ICP_MAGICNUM
Magic number in the value profile metadata showing a target has been promoted for the instruction and...
Definition Metadata.h:59
LLVM_ABI void scaleProfData(Instruction &I, uint64_t S, uint64_t T)
Scaling the profile data attached to 'I' using the ratio of S/T.
LLVM_ABI void extractFromBranchWeightMD64(const MDNode *ProfileData, SmallVectorImpl< uint64_t > &Weights)
Faster version of extractBranchWeights() that skips checks and must only be called with "branch_weigh...
static LLVM_ABI const char * ExpectedBranchWeights
static LLVM_ABI const char * SyntheticFunctionEntryCount
static LLVM_ABI const char * UnknownBranchWeightsMarker
static LLVM_ABI const char * ValueProfile
static LLVM_ABI const char * FunctionEntryCount
static LLVM_ABI const char * BranchWeights