blob: f3bc5f9dda86a3d678dcb398bb920a418256e364 [file] [log] [blame]
Easwaran Ramand68aae22016-02-04 23:34:31 +00001//=-- Profilesummary.cpp - Profile summary computation ----------------------=//
2//
3// The LLVM Compiler Infrastructure
4//
5// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9//
10// This file contains support for computing profile summary data.
11//
12//===----------------------------------------------------------------------===//
13
Dehao Chenf84b6302016-02-23 03:39:24 +000014#include "llvm/IR/Attributes.h"
Easwaran Raman7c4f25d2016-03-01 18:30:58 +000015#include "llvm/IR/Constants.h"
Dehao Chenf84b6302016-02-23 03:39:24 +000016#include "llvm/IR/Function.h"
Easwaran Raman7c4f25d2016-03-01 18:30:58 +000017#include "llvm/IR/Metadata.h"
18#include "llvm/IR/Type.h"
Easwaran Ramand68aae22016-02-04 23:34:31 +000019#include "llvm/ProfileData/InstrProf.h"
Easwaran Raman40ee23d2016-02-19 03:15:33 +000020#include "llvm/ProfileData/ProfileCommon.h"
21#include "llvm/ProfileData/SampleProf.h"
Easwaran Raman7c4f25d2016-03-01 18:30:58 +000022#include "llvm/Support/Casting.h"
Easwaran Ramand68aae22016-02-04 23:34:31 +000023
24using namespace llvm;
25
Easwaran Raman40ee23d2016-02-19 03:15:33 +000026// A set of cutoff values. Each value, when divided by ProfileSummary::Scale
27// (which is 1000000) is a desired percentile of total counts.
28const std::vector<uint32_t> ProfileSummary::DefaultCutoffs(
29 {10000, /* 1% */
30 100000, /* 10% */
31 200000, 300000, 400000, 500000, 600000, 500000, 600000, 700000, 800000,
32 900000, 950000, 990000, 999000, 999900, 999990, 999999});
33
Easwaran Raman43095702016-02-17 18:18:47 +000034void InstrProfSummary::addRecord(const InstrProfRecord &R) {
35 addEntryCount(R.Counts[0]);
36 for (size_t I = 1, E = R.Counts.size(); I < E; ++I)
37 addInternalCount(R.Counts[I]);
Easwaran Ramand68aae22016-02-04 23:34:31 +000038}
39
Easwaran Raman40ee23d2016-02-19 03:15:33 +000040// To compute the detailed summary, we consider each line containing samples as
41// equivalent to a block with a count in the instrumented profile.
42void SampleProfileSummary::addRecord(const sampleprof::FunctionSamples &FS) {
43 NumFunctions++;
44 if (FS.getHeadSamples() > MaxHeadSamples)
45 MaxHeadSamples = FS.getHeadSamples();
46 for (const auto &I : FS.getBodySamples())
47 addCount(I.second.getSamples());
48}
49
Easwaran Ramand68aae22016-02-04 23:34:31 +000050// The argument to this method is a vector of cutoff percentages and the return
Easwaran Raman43095702016-02-17 18:18:47 +000051// value is a vector of (Cutoff, MinCount, NumCounts) triplets.
Easwaran Ramand68aae22016-02-04 23:34:31 +000052void ProfileSummary::computeDetailedSummary() {
53 if (DetailedSummaryCutoffs.empty())
54 return;
55 auto Iter = CountFrequencies.begin();
56 auto End = CountFrequencies.end();
57 std::sort(DetailedSummaryCutoffs.begin(), DetailedSummaryCutoffs.end());
58
Easwaran Raman43095702016-02-17 18:18:47 +000059 uint32_t CountsSeen = 0;
Easwaran Ramand68aae22016-02-04 23:34:31 +000060 uint64_t CurrSum = 0, Count = 0;
61
62 for (uint32_t Cutoff : DetailedSummaryCutoffs) {
63 assert(Cutoff <= 999999);
64 APInt Temp(128, TotalCount);
65 APInt N(128, Cutoff);
66 APInt D(128, ProfileSummary::Scale);
67 Temp *= N;
68 Temp = Temp.sdiv(D);
69 uint64_t DesiredCount = Temp.getZExtValue();
70 assert(DesiredCount <= TotalCount);
71 while (CurrSum < DesiredCount && Iter != End) {
72 Count = Iter->first;
73 uint32_t Freq = Iter->second;
74 CurrSum += (Count * Freq);
Easwaran Raman43095702016-02-17 18:18:47 +000075 CountsSeen += Freq;
Easwaran Ramand68aae22016-02-04 23:34:31 +000076 Iter++;
77 }
78 assert(CurrSum >= DesiredCount);
Easwaran Raman43095702016-02-17 18:18:47 +000079 ProfileSummaryEntry PSE = {Cutoff, Count, CountsSeen};
Easwaran Ramand68aae22016-02-04 23:34:31 +000080 DetailedSummary.push_back(PSE);
81 }
82}
83
Dehao Chenf84b6302016-02-23 03:39:24 +000084// Returns true if the function is a hot function.
85bool ProfileSummary::isFunctionHot(const Function *F) {
86 // FIXME: update when summary data is stored in module's metadata.
87 return false;
88}
89
90// Returns true if the function is a cold function.
91bool ProfileSummary::isFunctionUnlikely(const Function *F) {
92 if (F->hasFnAttribute(Attribute::Cold)) {
93 return true;
94 }
95 if (!F->getEntryCount()) {
96 return false;
97 }
98 // FIXME: update when summary data is stored in module's metadata.
99 return (*F->getEntryCount()) == 0;
100}
101
Easwaran Raman43095702016-02-17 18:18:47 +0000102InstrProfSummary::InstrProfSummary(const IndexedInstrProf::Summary &S)
Easwaran Raman7c4f25d2016-03-01 18:30:58 +0000103 : ProfileSummary(PSK_Instr),
104 MaxInternalBlockCount(
105 S.get(IndexedInstrProf::Summary::MaxInternalBlockCount)),
Easwaran Ramand68aae22016-02-04 23:34:31 +0000106 MaxFunctionCount(S.get(IndexedInstrProf::Summary::MaxFunctionCount)),
Easwaran Ramand68aae22016-02-04 23:34:31 +0000107 NumFunctions(S.get(IndexedInstrProf::Summary::TotalNumFunctions)) {
Easwaran Raman43095702016-02-17 18:18:47 +0000108
109 TotalCount = S.get(IndexedInstrProf::Summary::TotalBlockCount);
110 MaxCount = S.get(IndexedInstrProf::Summary::MaxBlockCount);
111 NumCounts = S.get(IndexedInstrProf::Summary::TotalNumBlocks);
112
Easwaran Ramand68aae22016-02-04 23:34:31 +0000113 for (unsigned I = 0; I < S.NumCutoffEntries; I++) {
114 const IndexedInstrProf::Summary::Entry &Ent = S.getEntry(I);
115 DetailedSummary.emplace_back((uint32_t)Ent.Cutoff, Ent.MinBlockCount,
116 Ent.NumBlocks);
117 }
118}
Easwaran Raman43095702016-02-17 18:18:47 +0000119void InstrProfSummary::addEntryCount(uint64_t Count) {
120 addCount(Count);
121 NumFunctions++;
122 if (Count > MaxFunctionCount)
123 MaxFunctionCount = Count;
124}
125
126void InstrProfSummary::addInternalCount(uint64_t Count) {
127 addCount(Count);
128 if (Count > MaxInternalBlockCount)
129 MaxInternalBlockCount = Count;
130}
Easwaran Raman7c4f25d2016-03-01 18:30:58 +0000131
132// Return an MDTuple with two elements. The first element is a string Key and
133// the second is a uint64_t Value.
134static Metadata *getKeyValMD(LLVMContext &Context, const char *Key,
135 uint64_t Val) {
136 Type *Int64Ty = Type::getInt64Ty(Context);
137 Metadata *Ops[2] = {MDString::get(Context, Key),
138 ConstantAsMetadata::get(ConstantInt::get(Int64Ty, Val))};
139 return MDTuple::get(Context, Ops);
140}
141
142// Return an MDTuple with two elements. The first element is a string Key and
143// the second is a string Value.
144static Metadata *getKeyValMD(LLVMContext &Context, const char *Key,
145 const char *Val) {
146 Metadata *Ops[2] = {MDString::get(Context, Key), MDString::get(Context, Val)};
147 return MDTuple::get(Context, Ops);
148}
149
150// This returns an MDTuple representing the detiled summary. The tuple has two
151// elements: a string "DetailedSummary" and an MDTuple representing the value
152// of the detailed summary. Each element of this tuple is again an MDTuple whose
153// elements are the (Cutoff, MinCount, NumCounts) triplet of the
154// DetailedSummaryEntry.
155Metadata *ProfileSummary::getDetailedSummaryMD(LLVMContext &Context) {
156 std::vector<Metadata *> Entries;
157 Type *Int32Ty = Type::getInt32Ty(Context);
158 Type *Int64Ty = Type::getInt64Ty(Context);
159 for (auto &Entry : DetailedSummary) {
160 Metadata *EntryMD[3] = {
161 ConstantAsMetadata::get(ConstantInt::get(Int32Ty, Entry.Cutoff)),
162 ConstantAsMetadata::get(ConstantInt::get(Int64Ty, Entry.MinCount)),
163 ConstantAsMetadata::get(ConstantInt::get(Int32Ty, Entry.NumCounts))};
164 Entries.push_back(MDTuple::get(Context, EntryMD));
165 }
166 Metadata *Ops[2] = {MDString::get(Context, "DetailedSummary"),
167 MDTuple::get(Context, Entries)};
168 return MDTuple::get(Context, Ops);
169}
170
171// This returns an MDTuple representing this ProfileSummary object. The first
172// entry of this tuple is another MDTuple of two elements: a string
173// "ProfileFormat" and a string representing the format ("InstrProf" or
174// "SampleProfile"). The rest of the elements of the outer MDTuple are specific
175// to the kind of profile summary as returned by getFormatSpecificMD.
176Metadata *ProfileSummary::getMD(LLVMContext &Context) {
177 std::vector<Metadata *> Components;
178 Components.push_back(getKeyValMD(Context, "ProfileFormat", getKindStr()));
179 std::vector<Metadata *> Res = getFormatSpecificMD(Context);
180 Components.insert(Components.end(), Res.begin(), Res.end());
181 return MDTuple::get(Context, Components);
182}
183
184// Returns a vector of MDTuples specific to InstrProfSummary. The first six
185// elements of this vector are (Key, Val) pairs of the six scalar fields of
186// InstrProfSummary (TotalCount, MaxBlockCount, MaxInternalBlockCount,
187// MaxFunctionCount, NumBlocks, NumFunctions). The last element of this vector
188// is an MDTuple returned by getDetailedSummaryMD.
189std::vector<Metadata *>
190InstrProfSummary::getFormatSpecificMD(LLVMContext &Context) {
191 std::vector<Metadata *> Components;
192
193 Components.push_back(getKeyValMD(Context, "TotalCount", getTotalCount()));
194 Components.push_back(
195 getKeyValMD(Context, "MaxBlockCount", getMaxBlockCount()));
196 Components.push_back(getKeyValMD(Context, "MaxInternalBlockCount",
197 getMaxInternalBlockCount()));
198 Components.push_back(
199 getKeyValMD(Context, "MaxFunctionCount", getMaxFunctionCount()));
200 Components.push_back(getKeyValMD(Context, "NumBlocks", getNumBlocks()));
201 Components.push_back(getKeyValMD(Context, "NumFunctions", getNumFunctions()));
202
203 Components.push_back(getDetailedSummaryMD(Context));
204 return Components;
205}
206
207std::vector<Metadata *>
208SampleProfileSummary::getFormatSpecificMD(LLVMContext &Context) {
209 std::vector<Metadata *> Components;
210
211 Components.push_back(getKeyValMD(Context, "TotalSamples", getTotalSamples()));
212 Components.push_back(
213 getKeyValMD(Context, "MaxSamplesPerLine", getMaxSamplesPerLine()));
214 Components.push_back(
215 getKeyValMD(Context, "MaxHeadSamples", getMaxHeadSamples()));
216 Components.push_back(
217 getKeyValMD(Context, "NumLinesWithSamples", getNumLinesWithSamples()));
218 Components.push_back(getKeyValMD(Context, "NumFunctions", NumFunctions));
219
220 Components.push_back(getDetailedSummaryMD(Context));
221 return Components;
222}
223
224// Parse an MDTuple representing (Key, Val) pair.
225static bool getVal(MDTuple *MD, const char *Key, uint64_t &Val) {
226 if (!MD)
227 return false;
228 if (MD->getNumOperands() != 2)
229 return false;
230 MDString *KeyMD = dyn_cast<MDString>(MD->getOperand(0));
231 ConstantAsMetadata *ValMD = dyn_cast<ConstantAsMetadata>(MD->getOperand(1));
232 if (!KeyMD || !ValMD)
233 return false;
234 if (!KeyMD->getString().equals(Key))
235 return false;
236 Val = cast<ConstantInt>(ValMD->getValue())->getZExtValue();
237 return true;
238}
239
240// Check if an MDTuple represents a (Key, Val) pair.
241static bool isKeyValuePair(MDTuple *MD, const char *Key, const char *Val) {
242 if (!MD || MD->getNumOperands() != 2)
243 return false;
244 MDString *KeyMD = dyn_cast<MDString>(MD->getOperand(0));
245 MDString *ValMD = dyn_cast<MDString>(MD->getOperand(1));
246 if (!KeyMD || !ValMD)
247 return false;
248 if (!KeyMD->getString().equals(Key) || !ValMD->getString().equals(Val))
249 return false;
250 return true;
251}
252
253// Parse an MDTuple representing detailed summary.
254static bool getSummaryFromMD(MDTuple *MD, SummaryEntryVector &Summary) {
255 if (!MD || MD->getNumOperands() != 2)
256 return false;
257 MDString *KeyMD = dyn_cast<MDString>(MD->getOperand(0));
258 if (!KeyMD || !KeyMD->getString().equals("DetailedSummary"))
259 return false;
260 MDTuple *EntriesMD = dyn_cast<MDTuple>(MD->getOperand(1));
261 if (!EntriesMD)
262 return false;
263 for (auto &&MDOp : EntriesMD->operands()) {
264 MDTuple *EntryMD = dyn_cast<MDTuple>(MDOp);
265 if (!EntryMD || EntryMD->getNumOperands() != 3)
266 return false;
267 ConstantAsMetadata *Op0 =
268 dyn_cast<ConstantAsMetadata>(EntryMD->getOperand(0));
269 ConstantAsMetadata *Op1 =
270 dyn_cast<ConstantAsMetadata>(EntryMD->getOperand(1));
271 ConstantAsMetadata *Op2 =
272 dyn_cast<ConstantAsMetadata>(EntryMD->getOperand(2));
273
274 if (!Op0 || !Op1 || !Op2)
275 return false;
276 Summary.emplace_back(cast<ConstantInt>(Op0->getValue())->getZExtValue(),
277 cast<ConstantInt>(Op1->getValue())->getZExtValue(),
278 cast<ConstantInt>(Op2->getValue())->getZExtValue());
279 }
280 return true;
281}
282
283// Parse an MDTuple representing an InstrProfSummary object.
284static ProfileSummary *getInstrProfSummaryFromMD(MDTuple *Tuple) {
285 uint64_t NumBlocks, TotalCount, NumFunctions, MaxFunctionCount, MaxBlockCount,
286 MaxInternalBlockCount;
287 SummaryEntryVector Summary;
288
289 if (Tuple->getNumOperands() != 8)
290 return nullptr;
291
292 // Skip operand 0 which has been already parsed in the caller
293 if (!getVal(dyn_cast<MDTuple>(Tuple->getOperand(1)), "TotalCount",
294 TotalCount))
295 return nullptr;
296 if (!getVal(dyn_cast<MDTuple>(Tuple->getOperand(2)), "MaxBlockCount",
297 MaxBlockCount))
298 return nullptr;
299 if (!getVal(dyn_cast<MDTuple>(Tuple->getOperand(3)), "MaxInternalBlockCount",
300 MaxInternalBlockCount))
301 return nullptr;
302 if (!getVal(dyn_cast<MDTuple>(Tuple->getOperand(4)), "MaxFunctionCount",
303 MaxFunctionCount))
304 return nullptr;
305 if (!getVal(dyn_cast<MDTuple>(Tuple->getOperand(5)), "NumBlocks", NumBlocks))
306 return nullptr;
307 if (!getVal(dyn_cast<MDTuple>(Tuple->getOperand(6)), "NumFunctions",
308 NumFunctions))
309 return nullptr;
310 if (!getSummaryFromMD(dyn_cast<MDTuple>(Tuple->getOperand(7)), Summary))
311 return nullptr;
312 return new InstrProfSummary(TotalCount, MaxBlockCount, MaxInternalBlockCount,
313 MaxFunctionCount, NumBlocks, NumFunctions,
314 Summary);
315}
316
317// Parse an MDTuple representing a SampleProfileSummary object.
318static ProfileSummary *getSampleProfileSummaryFromMD(MDTuple *Tuple) {
319 uint64_t TotalSamples, MaxSamplesPerLine, MaxHeadSamples, NumLinesWithSamples,
320 NumFunctions;
321 SummaryEntryVector Summary;
322
323 if (Tuple->getNumOperands() != 7)
324 return nullptr;
325
326 // Skip operand 0 which has been already parsed in the caller
327 if (!getVal(dyn_cast<MDTuple>(Tuple->getOperand(1)), "TotalSamples",
328 TotalSamples))
329 return nullptr;
330 if (!getVal(dyn_cast<MDTuple>(Tuple->getOperand(2)), "MaxSamplesPerLine",
331 MaxSamplesPerLine))
332 return nullptr;
333 if (!getVal(dyn_cast<MDTuple>(Tuple->getOperand(3)), "MaxHeadSamples",
334 MaxHeadSamples))
335 return nullptr;
336 if (!getVal(dyn_cast<MDTuple>(Tuple->getOperand(4)), "NumLinesWithSamples",
337 NumLinesWithSamples))
338 return nullptr;
339 if (!getVal(dyn_cast<MDTuple>(Tuple->getOperand(5)), "NumFunctions",
340 NumFunctions))
341 return nullptr;
342 if (!getSummaryFromMD(dyn_cast<MDTuple>(Tuple->getOperand(6)), Summary))
343 return nullptr;
344 return new SampleProfileSummary(TotalSamples, MaxSamplesPerLine,
345 MaxHeadSamples, NumLinesWithSamples,
346 NumFunctions, Summary);
347}
348
349ProfileSummary *ProfileSummary::getFromMD(Metadata *MD) {
350 if (!isa<MDTuple>(MD))
351 return nullptr;
352 MDTuple *Tuple = cast<MDTuple>(MD);
353 auto &FormatMD = Tuple->getOperand(0);
354 if (isKeyValuePair(dyn_cast_or_null<MDTuple>(FormatMD), "ProfileFormat",
355 "SampleProfile"))
356 return getSampleProfileSummaryFromMD(Tuple);
357 else if (isKeyValuePair(dyn_cast_or_null<MDTuple>(FormatMD), "ProfileFormat",
358 "InstrProf"))
359 return getInstrProfSummaryFromMD(Tuple);
360 else
361 return nullptr;
362}