1 //=-- Profilesummary.cpp - Profile summary support --------------------------=//
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
7 //===----------------------------------------------------------------------===//
9 // This file contains support for converting profile summary data from/to
12 //===----------------------------------------------------------------------===//
14 #include "llvm/IR/ProfileSummary.h"
15 #include "llvm/IR/Attributes.h"
16 #include "llvm/IR/Constants.h"
17 #include "llvm/IR/Function.h"
18 #include "llvm/IR/Metadata.h"
19 #include "llvm/IR/Type.h"
20 #include "llvm/Support/Casting.h"
21 #include "llvm/Support/Format.h"
25 // Return an MDTuple with two elements. The first element is a string Key and
26 // the second is a uint64_t Value.
27 static Metadata
*getKeyValMD(LLVMContext
&Context
, const char *Key
,
29 Type
*Int64Ty
= Type::getInt64Ty(Context
);
30 Metadata
*Ops
[2] = {MDString::get(Context
, Key
),
31 ConstantAsMetadata::get(ConstantInt::get(Int64Ty
, Val
))};
32 return MDTuple::get(Context
, Ops
);
35 static Metadata
*getKeyFPValMD(LLVMContext
&Context
, const char *Key
,
37 Type
*DoubleTy
= Type::getDoubleTy(Context
);
38 Metadata
*Ops
[2] = {MDString::get(Context
, Key
),
39 ConstantAsMetadata::get(ConstantFP::get(DoubleTy
, Val
))};
40 return MDTuple::get(Context
, Ops
);
43 // Return an MDTuple with two elements. The first element is a string Key and
44 // the second is a string Value.
45 static Metadata
*getKeyValMD(LLVMContext
&Context
, const char *Key
,
47 Metadata
*Ops
[2] = {MDString::get(Context
, Key
), MDString::get(Context
, Val
)};
48 return MDTuple::get(Context
, Ops
);
51 // This returns an MDTuple representing the detiled summary. The tuple has two
52 // elements: a string "DetailedSummary" and an MDTuple representing the value
53 // of the detailed summary. Each element of this tuple is again an MDTuple whose
54 // elements are the (Cutoff, MinCount, NumCounts) triplet of the
55 // DetailedSummaryEntry.
56 Metadata
*ProfileSummary::getDetailedSummaryMD(LLVMContext
&Context
) {
57 std::vector
<Metadata
*> Entries
;
58 Type
*Int32Ty
= Type::getInt32Ty(Context
);
59 Type
*Int64Ty
= Type::getInt64Ty(Context
);
60 for (auto &Entry
: DetailedSummary
) {
61 Metadata
*EntryMD
[3] = {
62 ConstantAsMetadata::get(ConstantInt::get(Int32Ty
, Entry
.Cutoff
)),
63 ConstantAsMetadata::get(ConstantInt::get(Int64Ty
, Entry
.MinCount
)),
64 ConstantAsMetadata::get(ConstantInt::get(Int32Ty
, Entry
.NumCounts
))};
65 Entries
.push_back(MDTuple::get(Context
, EntryMD
));
67 Metadata
*Ops
[2] = {MDString::get(Context
, "DetailedSummary"),
68 MDTuple::get(Context
, Entries
)};
69 return MDTuple::get(Context
, Ops
);
72 // This returns an MDTuple representing this ProfileSummary object. The first
73 // entry of this tuple is another MDTuple of two elements: a string
74 // "ProfileFormat" and a string representing the format ("InstrProf" or
75 // "SampleProfile"). The rest of the elements of the outer MDTuple are specific
76 // to the kind of profile summary as returned by getFormatSpecificMD.
77 // IsPartialProfile is an optional field and \p AddPartialField will decide
78 // whether to add a field for it.
79 // PartialProfileRatio is an optional field and \p AddPartialProfileRatioField
80 // will decide whether to add a field for it.
81 Metadata
*ProfileSummary::getMD(LLVMContext
&Context
, bool AddPartialField
,
82 bool AddPartialProfileRatioField
) {
83 const char *KindStr
[3] = {"InstrProf", "CSInstrProf", "SampleProfile"};
84 SmallVector
<Metadata
*, 16> Components
;
85 Components
.push_back(getKeyValMD(Context
, "ProfileFormat", KindStr
[PSK
]));
86 Components
.push_back(getKeyValMD(Context
, "TotalCount", getTotalCount()));
87 Components
.push_back(getKeyValMD(Context
, "MaxCount", getMaxCount()));
89 getKeyValMD(Context
, "MaxInternalCount", getMaxInternalCount()));
91 getKeyValMD(Context
, "MaxFunctionCount", getMaxFunctionCount()));
92 Components
.push_back(getKeyValMD(Context
, "NumCounts", getNumCounts()));
93 Components
.push_back(getKeyValMD(Context
, "NumFunctions", getNumFunctions()));
96 getKeyValMD(Context
, "IsPartialProfile", isPartialProfile()));
97 if (AddPartialProfileRatioField
)
98 Components
.push_back(getKeyFPValMD(Context
, "PartialProfileRatio",
99 getPartialProfileRatio()));
100 Components
.push_back(getDetailedSummaryMD(Context
));
101 return MDTuple::get(Context
, Components
);
104 // Get the value metadata for the input MD/Key.
105 static ConstantAsMetadata
*getValMD(MDTuple
*MD
, const char *Key
) {
108 if (MD
->getNumOperands() != 2)
110 MDString
*KeyMD
= dyn_cast
<MDString
>(MD
->getOperand(0));
111 ConstantAsMetadata
*ValMD
= dyn_cast
<ConstantAsMetadata
>(MD
->getOperand(1));
112 if (!KeyMD
|| !ValMD
)
114 if (!KeyMD
->getString().equals(Key
))
119 // Parse an MDTuple representing (Key, Val) pair.
120 static bool getVal(MDTuple
*MD
, const char *Key
, uint64_t &Val
) {
121 if (auto *ValMD
= getValMD(MD
, Key
)) {
122 Val
= cast
<ConstantInt
>(ValMD
->getValue())->getZExtValue();
128 static bool getVal(MDTuple
*MD
, const char *Key
, double &Val
) {
129 if (auto *ValMD
= getValMD(MD
, Key
)) {
130 Val
= cast
<ConstantFP
>(ValMD
->getValue())->getValueAPF().convertToDouble();
136 // Check if an MDTuple represents a (Key, Val) pair.
137 static bool isKeyValuePair(MDTuple
*MD
, const char *Key
, const char *Val
) {
138 if (!MD
|| MD
->getNumOperands() != 2)
140 MDString
*KeyMD
= dyn_cast
<MDString
>(MD
->getOperand(0));
141 MDString
*ValMD
= dyn_cast
<MDString
>(MD
->getOperand(1));
142 if (!KeyMD
|| !ValMD
)
144 if (!KeyMD
->getString().equals(Key
) || !ValMD
->getString().equals(Val
))
149 // Parse an MDTuple representing detailed summary.
150 static bool getSummaryFromMD(MDTuple
*MD
, SummaryEntryVector
&Summary
) {
151 if (!MD
|| MD
->getNumOperands() != 2)
153 MDString
*KeyMD
= dyn_cast
<MDString
>(MD
->getOperand(0));
154 if (!KeyMD
|| !KeyMD
->getString().equals("DetailedSummary"))
156 MDTuple
*EntriesMD
= dyn_cast
<MDTuple
>(MD
->getOperand(1));
159 for (auto &&MDOp
: EntriesMD
->operands()) {
160 MDTuple
*EntryMD
= dyn_cast
<MDTuple
>(MDOp
);
161 if (!EntryMD
|| EntryMD
->getNumOperands() != 3)
163 ConstantAsMetadata
*Op0
=
164 dyn_cast
<ConstantAsMetadata
>(EntryMD
->getOperand(0));
165 ConstantAsMetadata
*Op1
=
166 dyn_cast
<ConstantAsMetadata
>(EntryMD
->getOperand(1));
167 ConstantAsMetadata
*Op2
=
168 dyn_cast
<ConstantAsMetadata
>(EntryMD
->getOperand(2));
170 if (!Op0
|| !Op1
|| !Op2
)
172 Summary
.emplace_back(cast
<ConstantInt
>(Op0
->getValue())->getZExtValue(),
173 cast
<ConstantInt
>(Op1
->getValue())->getZExtValue(),
174 cast
<ConstantInt
>(Op2
->getValue())->getZExtValue());
179 // Get the value of an optional field. Increment 'Idx' if it was present. Return
180 // true if we can move onto the next field.
181 template <typename ValueType
>
182 static bool getOptionalVal(MDTuple
*Tuple
, unsigned &Idx
, const char *Key
,
184 if (getVal(dyn_cast
<MDTuple
>(Tuple
->getOperand(Idx
)), Key
, Value
)) {
186 // Need to make sure when the key is present, we won't step over the bound
187 // of Tuple operand array. Since (non-optional) DetailedSummary always comes
188 // last, the next entry in the tuple operand array must exist.
189 return Idx
< Tuple
->getNumOperands();
191 // It was absent, keep going.
195 ProfileSummary
*ProfileSummary::getFromMD(Metadata
*MD
) {
196 MDTuple
*Tuple
= dyn_cast_or_null
<MDTuple
>(MD
);
197 if (!Tuple
|| Tuple
->getNumOperands() < 8 || Tuple
->getNumOperands() > 10)
201 auto &FormatMD
= Tuple
->getOperand(I
++);
202 ProfileSummary::Kind SummaryKind
;
203 if (isKeyValuePair(dyn_cast_or_null
<MDTuple
>(FormatMD
), "ProfileFormat",
205 SummaryKind
= PSK_Sample
;
206 else if (isKeyValuePair(dyn_cast_or_null
<MDTuple
>(FormatMD
), "ProfileFormat",
208 SummaryKind
= PSK_Instr
;
209 else if (isKeyValuePair(dyn_cast_or_null
<MDTuple
>(FormatMD
), "ProfileFormat",
211 SummaryKind
= PSK_CSInstr
;
215 uint64_t NumCounts
, TotalCount
, NumFunctions
, MaxFunctionCount
, MaxCount
,
217 if (!getVal(dyn_cast
<MDTuple
>(Tuple
->getOperand(I
++)), "TotalCount",
220 if (!getVal(dyn_cast
<MDTuple
>(Tuple
->getOperand(I
++)), "MaxCount", MaxCount
))
222 if (!getVal(dyn_cast
<MDTuple
>(Tuple
->getOperand(I
++)), "MaxInternalCount",
225 if (!getVal(dyn_cast
<MDTuple
>(Tuple
->getOperand(I
++)), "MaxFunctionCount",
228 if (!getVal(dyn_cast
<MDTuple
>(Tuple
->getOperand(I
++)), "NumCounts",
231 if (!getVal(dyn_cast
<MDTuple
>(Tuple
->getOperand(I
++)), "NumFunctions",
235 // Optional fields. Need to initialize because the fields are optional.
236 uint64_t IsPartialProfile
= 0;
237 if (!getOptionalVal(Tuple
, I
, "IsPartialProfile", IsPartialProfile
))
239 double PartialProfileRatio
= 0;
240 if (!getOptionalVal(Tuple
, I
, "PartialProfileRatio", PartialProfileRatio
))
243 SummaryEntryVector Summary
;
244 if (!getSummaryFromMD(dyn_cast
<MDTuple
>(Tuple
->getOperand(I
++)), Summary
))
246 return new ProfileSummary(SummaryKind
, std::move(Summary
), TotalCount
,
247 MaxCount
, MaxInternalCount
, MaxFunctionCount
,
248 NumCounts
, NumFunctions
, IsPartialProfile
,
249 PartialProfileRatio
);
252 void ProfileSummary::printSummary(raw_ostream
&OS
) {
253 OS
<< "Total functions: " << NumFunctions
<< "\n";
254 OS
<< "Maximum function count: " << MaxFunctionCount
<< "\n";
255 OS
<< "Maximum block count: " << MaxCount
<< "\n";
256 OS
<< "Total number of blocks: " << NumCounts
<< "\n";
257 OS
<< "Total count: " << TotalCount
<< "\n";
260 void ProfileSummary::printDetailedSummary(raw_ostream
&OS
) {
261 OS
<< "Detailed summary:\n";
262 for (const auto &Entry
: DetailedSummary
) {
263 OS
<< Entry
.NumCounts
<< " blocks with count >= " << Entry
.MinCount
265 << format("%0.6g", (float)Entry
.Cutoff
/ Scale
* 100)
266 << " percentage of the total counts.\n";