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/Constants.h"
16 #include "llvm/IR/DerivedTypes.h"
17 #include "llvm/IR/Metadata.h"
18 #include "llvm/IR/Type.h"
19 #include "llvm/Support/Casting.h"
20 #include "llvm/Support/Format.h"
24 // Return an MDTuple with two elements. The first element is a string Key and
25 // the second is a uint64_t Value.
26 static Metadata
*getKeyValMD(LLVMContext
&Context
, const char *Key
,
28 Type
*Int64Ty
= Type::getInt64Ty(Context
);
29 Metadata
*Ops
[2] = {MDString::get(Context
, Key
),
30 ConstantAsMetadata::get(ConstantInt::get(Int64Ty
, Val
))};
31 return MDTuple::get(Context
, Ops
);
34 static Metadata
*getKeyFPValMD(LLVMContext
&Context
, const char *Key
,
36 Type
*DoubleTy
= Type::getDoubleTy(Context
);
37 Metadata
*Ops
[2] = {MDString::get(Context
, Key
),
38 ConstantAsMetadata::get(ConstantFP::get(DoubleTy
, Val
))};
39 return MDTuple::get(Context
, Ops
);
42 // Return an MDTuple with two elements. The first element is a string Key and
43 // the second is a string Value.
44 static Metadata
*getKeyValMD(LLVMContext
&Context
, const char *Key
,
46 Metadata
*Ops
[2] = {MDString::get(Context
, Key
), MDString::get(Context
, Val
)};
47 return MDTuple::get(Context
, Ops
);
50 // This returns an MDTuple representing the detiled summary. The tuple has two
51 // elements: a string "DetailedSummary" and an MDTuple representing the value
52 // of the detailed summary. Each element of this tuple is again an MDTuple whose
53 // elements are the (Cutoff, MinCount, NumCounts) triplet of the
54 // DetailedSummaryEntry.
55 Metadata
*ProfileSummary::getDetailedSummaryMD(LLVMContext
&Context
) {
56 std::vector
<Metadata
*> Entries
;
57 Type
*Int32Ty
= Type::getInt32Ty(Context
);
58 Type
*Int64Ty
= Type::getInt64Ty(Context
);
59 for (auto &Entry
: DetailedSummary
) {
60 Metadata
*EntryMD
[3] = {
61 ConstantAsMetadata::get(ConstantInt::get(Int32Ty
, Entry
.Cutoff
)),
62 ConstantAsMetadata::get(ConstantInt::get(Int64Ty
, Entry
.MinCount
)),
63 ConstantAsMetadata::get(ConstantInt::get(Int32Ty
, Entry
.NumCounts
))};
64 Entries
.push_back(MDTuple::get(Context
, EntryMD
));
66 Metadata
*Ops
[2] = {MDString::get(Context
, "DetailedSummary"),
67 MDTuple::get(Context
, Entries
)};
68 return MDTuple::get(Context
, Ops
);
71 // This returns an MDTuple representing this ProfileSummary object. The first
72 // entry of this tuple is another MDTuple of two elements: a string
73 // "ProfileFormat" and a string representing the format ("InstrProf" or
74 // "SampleProfile"). The rest of the elements of the outer MDTuple are specific
75 // to the kind of profile summary as returned by getFormatSpecificMD.
76 // IsPartialProfile is an optional field and \p AddPartialField will decide
77 // whether to add a field for it.
78 // PartialProfileRatio is an optional field and \p AddPartialProfileRatioField
79 // will decide whether to add a field for it.
80 Metadata
*ProfileSummary::getMD(LLVMContext
&Context
, bool AddPartialField
,
81 bool AddPartialProfileRatioField
) {
82 const char *KindStr
[3] = {"InstrProf", "CSInstrProf", "SampleProfile"};
83 SmallVector
<Metadata
*, 16> Components
;
84 Components
.push_back(getKeyValMD(Context
, "ProfileFormat", KindStr
[PSK
]));
85 Components
.push_back(getKeyValMD(Context
, "TotalCount", getTotalCount()));
86 Components
.push_back(getKeyValMD(Context
, "MaxCount", getMaxCount()));
88 getKeyValMD(Context
, "MaxInternalCount", getMaxInternalCount()));
90 getKeyValMD(Context
, "MaxFunctionCount", getMaxFunctionCount()));
91 Components
.push_back(getKeyValMD(Context
, "NumCounts", getNumCounts()));
92 Components
.push_back(getKeyValMD(Context
, "NumFunctions", getNumFunctions()));
95 getKeyValMD(Context
, "IsPartialProfile", isPartialProfile()));
96 if (AddPartialProfileRatioField
)
97 Components
.push_back(getKeyFPValMD(Context
, "PartialProfileRatio",
98 getPartialProfileRatio()));
99 Components
.push_back(getDetailedSummaryMD(Context
));
100 return MDTuple::get(Context
, Components
);
103 // Get the value metadata for the input MD/Key.
104 static ConstantAsMetadata
*getValMD(MDTuple
*MD
, const char *Key
) {
107 if (MD
->getNumOperands() != 2)
109 MDString
*KeyMD
= dyn_cast
<MDString
>(MD
->getOperand(0));
110 ConstantAsMetadata
*ValMD
= dyn_cast
<ConstantAsMetadata
>(MD
->getOperand(1));
111 if (!KeyMD
|| !ValMD
)
113 if (KeyMD
->getString() != Key
)
118 // Parse an MDTuple representing (Key, Val) pair.
119 static bool getVal(MDTuple
*MD
, const char *Key
, uint64_t &Val
) {
120 if (auto *ValMD
= getValMD(MD
, Key
)) {
121 Val
= cast
<ConstantInt
>(ValMD
->getValue())->getZExtValue();
127 static bool getVal(MDTuple
*MD
, const char *Key
, double &Val
) {
128 if (auto *ValMD
= getValMD(MD
, Key
)) {
129 Val
= cast
<ConstantFP
>(ValMD
->getValue())->getValueAPF().convertToDouble();
135 // Check if an MDTuple represents a (Key, Val) pair.
136 static bool isKeyValuePair(MDTuple
*MD
, const char *Key
, const char *Val
) {
137 if (!MD
|| MD
->getNumOperands() != 2)
139 MDString
*KeyMD
= dyn_cast
<MDString
>(MD
->getOperand(0));
140 MDString
*ValMD
= dyn_cast
<MDString
>(MD
->getOperand(1));
141 if (!KeyMD
|| !ValMD
)
143 if (KeyMD
->getString() != Key
|| ValMD
->getString() != Val
)
148 // Parse an MDTuple representing detailed summary.
149 static bool getSummaryFromMD(MDTuple
*MD
, SummaryEntryVector
&Summary
) {
150 if (!MD
|| MD
->getNumOperands() != 2)
152 MDString
*KeyMD
= dyn_cast
<MDString
>(MD
->getOperand(0));
153 if (!KeyMD
|| KeyMD
->getString() != "DetailedSummary")
155 MDTuple
*EntriesMD
= dyn_cast
<MDTuple
>(MD
->getOperand(1));
158 for (auto &&MDOp
: EntriesMD
->operands()) {
159 MDTuple
*EntryMD
= dyn_cast
<MDTuple
>(MDOp
);
160 if (!EntryMD
|| EntryMD
->getNumOperands() != 3)
162 ConstantAsMetadata
*Op0
=
163 dyn_cast
<ConstantAsMetadata
>(EntryMD
->getOperand(0));
164 ConstantAsMetadata
*Op1
=
165 dyn_cast
<ConstantAsMetadata
>(EntryMD
->getOperand(1));
166 ConstantAsMetadata
*Op2
=
167 dyn_cast
<ConstantAsMetadata
>(EntryMD
->getOperand(2));
169 if (!Op0
|| !Op1
|| !Op2
)
171 Summary
.emplace_back(cast
<ConstantInt
>(Op0
->getValue())->getZExtValue(),
172 cast
<ConstantInt
>(Op1
->getValue())->getZExtValue(),
173 cast
<ConstantInt
>(Op2
->getValue())->getZExtValue());
178 // Get the value of an optional field. Increment 'Idx' if it was present. Return
179 // true if we can move onto the next field.
180 template <typename ValueType
>
181 static bool getOptionalVal(MDTuple
*Tuple
, unsigned &Idx
, const char *Key
,
183 if (getVal(dyn_cast
<MDTuple
>(Tuple
->getOperand(Idx
)), Key
, Value
)) {
185 // Need to make sure when the key is present, we won't step over the bound
186 // of Tuple operand array. Since (non-optional) DetailedSummary always comes
187 // last, the next entry in the tuple operand array must exist.
188 return Idx
< Tuple
->getNumOperands();
190 // It was absent, keep going.
194 ProfileSummary
*ProfileSummary::getFromMD(Metadata
*MD
) {
195 MDTuple
*Tuple
= dyn_cast_or_null
<MDTuple
>(MD
);
196 if (!Tuple
|| Tuple
->getNumOperands() < 8 || Tuple
->getNumOperands() > 10)
200 auto &FormatMD
= Tuple
->getOperand(I
++);
201 ProfileSummary::Kind SummaryKind
;
202 if (isKeyValuePair(dyn_cast_or_null
<MDTuple
>(FormatMD
), "ProfileFormat",
204 SummaryKind
= PSK_Sample
;
205 else if (isKeyValuePair(dyn_cast_or_null
<MDTuple
>(FormatMD
), "ProfileFormat",
207 SummaryKind
= PSK_Instr
;
208 else if (isKeyValuePair(dyn_cast_or_null
<MDTuple
>(FormatMD
), "ProfileFormat",
210 SummaryKind
= PSK_CSInstr
;
214 uint64_t NumCounts
, TotalCount
, NumFunctions
, MaxFunctionCount
, MaxCount
,
216 if (!getVal(dyn_cast
<MDTuple
>(Tuple
->getOperand(I
++)), "TotalCount",
219 if (!getVal(dyn_cast
<MDTuple
>(Tuple
->getOperand(I
++)), "MaxCount", MaxCount
))
221 if (!getVal(dyn_cast
<MDTuple
>(Tuple
->getOperand(I
++)), "MaxInternalCount",
224 if (!getVal(dyn_cast
<MDTuple
>(Tuple
->getOperand(I
++)), "MaxFunctionCount",
227 if (!getVal(dyn_cast
<MDTuple
>(Tuple
->getOperand(I
++)), "NumCounts",
230 if (!getVal(dyn_cast
<MDTuple
>(Tuple
->getOperand(I
++)), "NumFunctions",
234 // Optional fields. Need to initialize because the fields are optional.
235 uint64_t IsPartialProfile
= 0;
236 if (!getOptionalVal(Tuple
, I
, "IsPartialProfile", IsPartialProfile
))
238 double PartialProfileRatio
= 0;
239 if (!getOptionalVal(Tuple
, I
, "PartialProfileRatio", PartialProfileRatio
))
242 SummaryEntryVector Summary
;
243 if (!getSummaryFromMD(dyn_cast
<MDTuple
>(Tuple
->getOperand(I
++)), Summary
))
245 return new ProfileSummary(SummaryKind
, std::move(Summary
), TotalCount
,
246 MaxCount
, MaxInternalCount
, MaxFunctionCount
,
247 NumCounts
, NumFunctions
, IsPartialProfile
,
248 PartialProfileRatio
);
251 void ProfileSummary::printSummary(raw_ostream
&OS
) const {
252 OS
<< "Total functions: " << NumFunctions
<< "\n";
253 OS
<< "Maximum function count: " << MaxFunctionCount
<< "\n";
254 OS
<< "Maximum block count: " << MaxCount
<< "\n";
255 OS
<< "Total number of blocks: " << NumCounts
<< "\n";
256 OS
<< "Total count: " << TotalCount
<< "\n";
259 void ProfileSummary::printDetailedSummary(raw_ostream
&OS
) const {
260 OS
<< "Detailed summary:\n";
261 for (const auto &Entry
: DetailedSummary
) {
262 OS
<< Entry
.NumCounts
<< " blocks with count >= " << Entry
.MinCount
264 << format("%0.6g", (float)Entry
.Cutoff
/ Scale
* 100)
265 << " percentage of the total counts.\n";