xref: /freebsd-src/contrib/llvm-project/llvm/lib/IR/ProfileSummary.cpp (revision 0fca6ea1d4eea4c934cfff25ac9ee8ad6fe95583)
10b57cec5SDimitry Andric //=-- Profilesummary.cpp - Profile summary support --------------------------=//
20b57cec5SDimitry Andric //
30b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
40b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
50b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
60b57cec5SDimitry Andric //
70b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
80b57cec5SDimitry Andric //
90b57cec5SDimitry Andric // This file contains support for converting profile summary data from/to
100b57cec5SDimitry Andric // metadata.
110b57cec5SDimitry Andric //
120b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
130b57cec5SDimitry Andric 
140b57cec5SDimitry Andric #include "llvm/IR/ProfileSummary.h"
150b57cec5SDimitry Andric #include "llvm/IR/Constants.h"
161fd87a68SDimitry Andric #include "llvm/IR/DerivedTypes.h"
170b57cec5SDimitry Andric #include "llvm/IR/Metadata.h"
180b57cec5SDimitry Andric #include "llvm/IR/Type.h"
190b57cec5SDimitry Andric #include "llvm/Support/Casting.h"
205ffd83dbSDimitry Andric #include "llvm/Support/Format.h"
210b57cec5SDimitry Andric 
220b57cec5SDimitry Andric using namespace llvm;
230b57cec5SDimitry Andric 
240b57cec5SDimitry Andric // Return an MDTuple with two elements. The first element is a string Key and
250b57cec5SDimitry Andric // the second is a uint64_t Value.
260b57cec5SDimitry Andric static Metadata *getKeyValMD(LLVMContext &Context, const char *Key,
270b57cec5SDimitry Andric                              uint64_t Val) {
280b57cec5SDimitry Andric   Type *Int64Ty = Type::getInt64Ty(Context);
290b57cec5SDimitry Andric   Metadata *Ops[2] = {MDString::get(Context, Key),
300b57cec5SDimitry Andric                       ConstantAsMetadata::get(ConstantInt::get(Int64Ty, Val))};
310b57cec5SDimitry Andric   return MDTuple::get(Context, Ops);
320b57cec5SDimitry Andric }
330b57cec5SDimitry Andric 
345ffd83dbSDimitry Andric static Metadata *getKeyFPValMD(LLVMContext &Context, const char *Key,
355ffd83dbSDimitry Andric                                double Val) {
365ffd83dbSDimitry Andric   Type *DoubleTy = Type::getDoubleTy(Context);
375ffd83dbSDimitry Andric   Metadata *Ops[2] = {MDString::get(Context, Key),
385ffd83dbSDimitry Andric                       ConstantAsMetadata::get(ConstantFP::get(DoubleTy, Val))};
395ffd83dbSDimitry Andric   return MDTuple::get(Context, Ops);
405ffd83dbSDimitry Andric }
415ffd83dbSDimitry Andric 
420b57cec5SDimitry Andric // Return an MDTuple with two elements. The first element is a string Key and
430b57cec5SDimitry Andric // the second is a string Value.
440b57cec5SDimitry Andric static Metadata *getKeyValMD(LLVMContext &Context, const char *Key,
450b57cec5SDimitry Andric                              const char *Val) {
460b57cec5SDimitry Andric   Metadata *Ops[2] = {MDString::get(Context, Key), MDString::get(Context, Val)};
470b57cec5SDimitry Andric   return MDTuple::get(Context, Ops);
480b57cec5SDimitry Andric }
490b57cec5SDimitry Andric 
500b57cec5SDimitry Andric // This returns an MDTuple representing the detiled summary. The tuple has two
510b57cec5SDimitry Andric // elements: a string "DetailedSummary" and an MDTuple representing the value
520b57cec5SDimitry Andric // of the detailed summary. Each element of this tuple is again an MDTuple whose
530b57cec5SDimitry Andric // elements are the (Cutoff, MinCount, NumCounts) triplet of the
540b57cec5SDimitry Andric // DetailedSummaryEntry.
550b57cec5SDimitry Andric Metadata *ProfileSummary::getDetailedSummaryMD(LLVMContext &Context) {
560b57cec5SDimitry Andric   std::vector<Metadata *> Entries;
570b57cec5SDimitry Andric   Type *Int32Ty = Type::getInt32Ty(Context);
580b57cec5SDimitry Andric   Type *Int64Ty = Type::getInt64Ty(Context);
590b57cec5SDimitry Andric   for (auto &Entry : DetailedSummary) {
600b57cec5SDimitry Andric     Metadata *EntryMD[3] = {
610b57cec5SDimitry Andric         ConstantAsMetadata::get(ConstantInt::get(Int32Ty, Entry.Cutoff)),
620b57cec5SDimitry Andric         ConstantAsMetadata::get(ConstantInt::get(Int64Ty, Entry.MinCount)),
630b57cec5SDimitry Andric         ConstantAsMetadata::get(ConstantInt::get(Int32Ty, Entry.NumCounts))};
640b57cec5SDimitry Andric     Entries.push_back(MDTuple::get(Context, EntryMD));
650b57cec5SDimitry Andric   }
660b57cec5SDimitry Andric   Metadata *Ops[2] = {MDString::get(Context, "DetailedSummary"),
670b57cec5SDimitry Andric                       MDTuple::get(Context, Entries)};
680b57cec5SDimitry Andric   return MDTuple::get(Context, Ops);
690b57cec5SDimitry Andric }
700b57cec5SDimitry Andric 
710b57cec5SDimitry Andric // This returns an MDTuple representing this ProfileSummary object. The first
720b57cec5SDimitry Andric // entry of this tuple is another MDTuple of two elements: a string
730b57cec5SDimitry Andric // "ProfileFormat" and a string representing the format ("InstrProf" or
740b57cec5SDimitry Andric // "SampleProfile"). The rest of the elements of the outer MDTuple are specific
750b57cec5SDimitry Andric // to the kind of profile summary as returned by getFormatSpecificMD.
765ffd83dbSDimitry Andric // IsPartialProfile is an optional field and \p AddPartialField will decide
775ffd83dbSDimitry Andric // whether to add a field for it.
785ffd83dbSDimitry Andric // PartialProfileRatio is an optional field and \p AddPartialProfileRatioField
795ffd83dbSDimitry Andric // will decide whether to add a field for it.
805ffd83dbSDimitry Andric Metadata *ProfileSummary::getMD(LLVMContext &Context, bool AddPartialField,
815ffd83dbSDimitry Andric                                 bool AddPartialProfileRatioField) {
820b57cec5SDimitry Andric   const char *KindStr[3] = {"InstrProf", "CSInstrProf", "SampleProfile"};
835ffd83dbSDimitry Andric   SmallVector<Metadata *, 16> Components;
845ffd83dbSDimitry Andric   Components.push_back(getKeyValMD(Context, "ProfileFormat", KindStr[PSK]));
855ffd83dbSDimitry Andric   Components.push_back(getKeyValMD(Context, "TotalCount", getTotalCount()));
865ffd83dbSDimitry Andric   Components.push_back(getKeyValMD(Context, "MaxCount", getMaxCount()));
875ffd83dbSDimitry Andric   Components.push_back(
885ffd83dbSDimitry Andric       getKeyValMD(Context, "MaxInternalCount", getMaxInternalCount()));
895ffd83dbSDimitry Andric   Components.push_back(
905ffd83dbSDimitry Andric       getKeyValMD(Context, "MaxFunctionCount", getMaxFunctionCount()));
915ffd83dbSDimitry Andric   Components.push_back(getKeyValMD(Context, "NumCounts", getNumCounts()));
925ffd83dbSDimitry Andric   Components.push_back(getKeyValMD(Context, "NumFunctions", getNumFunctions()));
935ffd83dbSDimitry Andric   if (AddPartialField)
945ffd83dbSDimitry Andric     Components.push_back(
955ffd83dbSDimitry Andric         getKeyValMD(Context, "IsPartialProfile", isPartialProfile()));
965ffd83dbSDimitry Andric   if (AddPartialProfileRatioField)
975ffd83dbSDimitry Andric     Components.push_back(getKeyFPValMD(Context, "PartialProfileRatio",
985ffd83dbSDimitry Andric                                        getPartialProfileRatio()));
995ffd83dbSDimitry Andric   Components.push_back(getDetailedSummaryMD(Context));
1000b57cec5SDimitry Andric   return MDTuple::get(Context, Components);
1010b57cec5SDimitry Andric }
1020b57cec5SDimitry Andric 
1035ffd83dbSDimitry Andric // Get the value metadata for the input MD/Key.
1045ffd83dbSDimitry Andric static ConstantAsMetadata *getValMD(MDTuple *MD, const char *Key) {
1055ffd83dbSDimitry Andric   if (!MD)
1065ffd83dbSDimitry Andric     return nullptr;
1075ffd83dbSDimitry Andric   if (MD->getNumOperands() != 2)
1085ffd83dbSDimitry Andric     return nullptr;
1095ffd83dbSDimitry Andric   MDString *KeyMD = dyn_cast<MDString>(MD->getOperand(0));
1105ffd83dbSDimitry Andric   ConstantAsMetadata *ValMD = dyn_cast<ConstantAsMetadata>(MD->getOperand(1));
1115ffd83dbSDimitry Andric   if (!KeyMD || !ValMD)
1125ffd83dbSDimitry Andric     return nullptr;
113*0fca6ea1SDimitry Andric   if (KeyMD->getString() != Key)
1145ffd83dbSDimitry Andric     return nullptr;
1155ffd83dbSDimitry Andric   return ValMD;
1165ffd83dbSDimitry Andric }
1175ffd83dbSDimitry Andric 
1180b57cec5SDimitry Andric // Parse an MDTuple representing (Key, Val) pair.
1190b57cec5SDimitry Andric static bool getVal(MDTuple *MD, const char *Key, uint64_t &Val) {
1205ffd83dbSDimitry Andric   if (auto *ValMD = getValMD(MD, Key)) {
1210b57cec5SDimitry Andric     Val = cast<ConstantInt>(ValMD->getValue())->getZExtValue();
1220b57cec5SDimitry Andric     return true;
1230b57cec5SDimitry Andric   }
1245ffd83dbSDimitry Andric   return false;
1255ffd83dbSDimitry Andric }
1265ffd83dbSDimitry Andric 
1275ffd83dbSDimitry Andric static bool getVal(MDTuple *MD, const char *Key, double &Val) {
1285ffd83dbSDimitry Andric   if (auto *ValMD = getValMD(MD, Key)) {
1295ffd83dbSDimitry Andric     Val = cast<ConstantFP>(ValMD->getValue())->getValueAPF().convertToDouble();
1305ffd83dbSDimitry Andric     return true;
1315ffd83dbSDimitry Andric   }
1325ffd83dbSDimitry Andric   return false;
1335ffd83dbSDimitry Andric }
1340b57cec5SDimitry Andric 
1350b57cec5SDimitry Andric // Check if an MDTuple represents a (Key, Val) pair.
1360b57cec5SDimitry Andric static bool isKeyValuePair(MDTuple *MD, const char *Key, const char *Val) {
1370b57cec5SDimitry Andric   if (!MD || MD->getNumOperands() != 2)
1380b57cec5SDimitry Andric     return false;
1390b57cec5SDimitry Andric   MDString *KeyMD = dyn_cast<MDString>(MD->getOperand(0));
1400b57cec5SDimitry Andric   MDString *ValMD = dyn_cast<MDString>(MD->getOperand(1));
1410b57cec5SDimitry Andric   if (!KeyMD || !ValMD)
1420b57cec5SDimitry Andric     return false;
143*0fca6ea1SDimitry Andric   if (KeyMD->getString() != Key || ValMD->getString() != Val)
1440b57cec5SDimitry Andric     return false;
1450b57cec5SDimitry Andric   return true;
1460b57cec5SDimitry Andric }
1470b57cec5SDimitry Andric 
1480b57cec5SDimitry Andric // Parse an MDTuple representing detailed summary.
1490b57cec5SDimitry Andric static bool getSummaryFromMD(MDTuple *MD, SummaryEntryVector &Summary) {
1500b57cec5SDimitry Andric   if (!MD || MD->getNumOperands() != 2)
1510b57cec5SDimitry Andric     return false;
1520b57cec5SDimitry Andric   MDString *KeyMD = dyn_cast<MDString>(MD->getOperand(0));
153*0fca6ea1SDimitry Andric   if (!KeyMD || KeyMD->getString() != "DetailedSummary")
1540b57cec5SDimitry Andric     return false;
1550b57cec5SDimitry Andric   MDTuple *EntriesMD = dyn_cast<MDTuple>(MD->getOperand(1));
1560b57cec5SDimitry Andric   if (!EntriesMD)
1570b57cec5SDimitry Andric     return false;
1580b57cec5SDimitry Andric   for (auto &&MDOp : EntriesMD->operands()) {
1590b57cec5SDimitry Andric     MDTuple *EntryMD = dyn_cast<MDTuple>(MDOp);
1600b57cec5SDimitry Andric     if (!EntryMD || EntryMD->getNumOperands() != 3)
1610b57cec5SDimitry Andric       return false;
1620b57cec5SDimitry Andric     ConstantAsMetadata *Op0 =
1630b57cec5SDimitry Andric         dyn_cast<ConstantAsMetadata>(EntryMD->getOperand(0));
1640b57cec5SDimitry Andric     ConstantAsMetadata *Op1 =
1650b57cec5SDimitry Andric         dyn_cast<ConstantAsMetadata>(EntryMD->getOperand(1));
1660b57cec5SDimitry Andric     ConstantAsMetadata *Op2 =
1670b57cec5SDimitry Andric         dyn_cast<ConstantAsMetadata>(EntryMD->getOperand(2));
1680b57cec5SDimitry Andric 
1690b57cec5SDimitry Andric     if (!Op0 || !Op1 || !Op2)
1700b57cec5SDimitry Andric       return false;
1710b57cec5SDimitry Andric     Summary.emplace_back(cast<ConstantInt>(Op0->getValue())->getZExtValue(),
1720b57cec5SDimitry Andric                          cast<ConstantInt>(Op1->getValue())->getZExtValue(),
1730b57cec5SDimitry Andric                          cast<ConstantInt>(Op2->getValue())->getZExtValue());
1740b57cec5SDimitry Andric   }
1750b57cec5SDimitry Andric   return true;
1760b57cec5SDimitry Andric }
1770b57cec5SDimitry Andric 
1785ffd83dbSDimitry Andric // Get the value of an optional field. Increment 'Idx' if it was present. Return
1795ffd83dbSDimitry Andric // true if we can move onto the next field.
1805ffd83dbSDimitry Andric template <typename ValueType>
1815ffd83dbSDimitry Andric static bool getOptionalVal(MDTuple *Tuple, unsigned &Idx, const char *Key,
1825ffd83dbSDimitry Andric                            ValueType &Value) {
1835ffd83dbSDimitry Andric   if (getVal(dyn_cast<MDTuple>(Tuple->getOperand(Idx)), Key, Value)) {
1845ffd83dbSDimitry Andric     Idx++;
1855ffd83dbSDimitry Andric     // Need to make sure when the key is present, we won't step over the bound
1865ffd83dbSDimitry Andric     // of Tuple operand array. Since (non-optional) DetailedSummary always comes
1875ffd83dbSDimitry Andric     // last, the next entry in the tuple operand array must exist.
1885ffd83dbSDimitry Andric     return Idx < Tuple->getNumOperands();
1895ffd83dbSDimitry Andric   }
1905ffd83dbSDimitry Andric   // It was absent, keep going.
1915ffd83dbSDimitry Andric   return true;
1925ffd83dbSDimitry Andric }
1935ffd83dbSDimitry Andric 
1940b57cec5SDimitry Andric ProfileSummary *ProfileSummary::getFromMD(Metadata *MD) {
1950b57cec5SDimitry Andric   MDTuple *Tuple = dyn_cast_or_null<MDTuple>(MD);
1965ffd83dbSDimitry Andric   if (!Tuple || Tuple->getNumOperands() < 8 || Tuple->getNumOperands() > 10)
1970b57cec5SDimitry Andric     return nullptr;
1980b57cec5SDimitry Andric 
1995ffd83dbSDimitry Andric   unsigned I = 0;
2005ffd83dbSDimitry Andric   auto &FormatMD = Tuple->getOperand(I++);
2010b57cec5SDimitry Andric   ProfileSummary::Kind SummaryKind;
2020b57cec5SDimitry Andric   if (isKeyValuePair(dyn_cast_or_null<MDTuple>(FormatMD), "ProfileFormat",
2030b57cec5SDimitry Andric                      "SampleProfile"))
2040b57cec5SDimitry Andric     SummaryKind = PSK_Sample;
2050b57cec5SDimitry Andric   else if (isKeyValuePair(dyn_cast_or_null<MDTuple>(FormatMD), "ProfileFormat",
2060b57cec5SDimitry Andric                           "InstrProf"))
2070b57cec5SDimitry Andric     SummaryKind = PSK_Instr;
2080b57cec5SDimitry Andric   else if (isKeyValuePair(dyn_cast_or_null<MDTuple>(FormatMD), "ProfileFormat",
2090b57cec5SDimitry Andric                           "CSInstrProf"))
2100b57cec5SDimitry Andric     SummaryKind = PSK_CSInstr;
2110b57cec5SDimitry Andric   else
2120b57cec5SDimitry Andric     return nullptr;
2130b57cec5SDimitry Andric 
2140b57cec5SDimitry Andric   uint64_t NumCounts, TotalCount, NumFunctions, MaxFunctionCount, MaxCount,
2150b57cec5SDimitry Andric       MaxInternalCount;
2165ffd83dbSDimitry Andric   if (!getVal(dyn_cast<MDTuple>(Tuple->getOperand(I++)), "TotalCount",
2170b57cec5SDimitry Andric               TotalCount))
2180b57cec5SDimitry Andric     return nullptr;
2195ffd83dbSDimitry Andric   if (!getVal(dyn_cast<MDTuple>(Tuple->getOperand(I++)), "MaxCount", MaxCount))
2200b57cec5SDimitry Andric     return nullptr;
2215ffd83dbSDimitry Andric   if (!getVal(dyn_cast<MDTuple>(Tuple->getOperand(I++)), "MaxInternalCount",
2220b57cec5SDimitry Andric               MaxInternalCount))
2230b57cec5SDimitry Andric     return nullptr;
2245ffd83dbSDimitry Andric   if (!getVal(dyn_cast<MDTuple>(Tuple->getOperand(I++)), "MaxFunctionCount",
2250b57cec5SDimitry Andric               MaxFunctionCount))
2260b57cec5SDimitry Andric     return nullptr;
2275ffd83dbSDimitry Andric   if (!getVal(dyn_cast<MDTuple>(Tuple->getOperand(I++)), "NumCounts",
2285ffd83dbSDimitry Andric               NumCounts))
2290b57cec5SDimitry Andric     return nullptr;
2305ffd83dbSDimitry Andric   if (!getVal(dyn_cast<MDTuple>(Tuple->getOperand(I++)), "NumFunctions",
2310b57cec5SDimitry Andric               NumFunctions))
2320b57cec5SDimitry Andric     return nullptr;
2330b57cec5SDimitry Andric 
2345ffd83dbSDimitry Andric   // Optional fields. Need to initialize because the fields are optional.
2355ffd83dbSDimitry Andric   uint64_t IsPartialProfile = 0;
2365ffd83dbSDimitry Andric   if (!getOptionalVal(Tuple, I, "IsPartialProfile", IsPartialProfile))
2375ffd83dbSDimitry Andric     return nullptr;
2385ffd83dbSDimitry Andric   double PartialProfileRatio = 0;
2395ffd83dbSDimitry Andric   if (!getOptionalVal(Tuple, I, "PartialProfileRatio", PartialProfileRatio))
2405ffd83dbSDimitry Andric     return nullptr;
2415ffd83dbSDimitry Andric 
2420b57cec5SDimitry Andric   SummaryEntryVector Summary;
2435ffd83dbSDimitry Andric   if (!getSummaryFromMD(dyn_cast<MDTuple>(Tuple->getOperand(I++)), Summary))
2440b57cec5SDimitry Andric     return nullptr;
2450b57cec5SDimitry Andric   return new ProfileSummary(SummaryKind, std::move(Summary), TotalCount,
2460b57cec5SDimitry Andric                             MaxCount, MaxInternalCount, MaxFunctionCount,
2475ffd83dbSDimitry Andric                             NumCounts, NumFunctions, IsPartialProfile,
2485ffd83dbSDimitry Andric                             PartialProfileRatio);
2495ffd83dbSDimitry Andric }
2505ffd83dbSDimitry Andric 
251349cc55cSDimitry Andric void ProfileSummary::printSummary(raw_ostream &OS) const {
2525ffd83dbSDimitry Andric   OS << "Total functions: " << NumFunctions << "\n";
2535ffd83dbSDimitry Andric   OS << "Maximum function count: " << MaxFunctionCount << "\n";
2545ffd83dbSDimitry Andric   OS << "Maximum block count: " << MaxCount << "\n";
2555ffd83dbSDimitry Andric   OS << "Total number of blocks: " << NumCounts << "\n";
2565ffd83dbSDimitry Andric   OS << "Total count: " << TotalCount << "\n";
2575ffd83dbSDimitry Andric }
2585ffd83dbSDimitry Andric 
259349cc55cSDimitry Andric void ProfileSummary::printDetailedSummary(raw_ostream &OS) const {
2605ffd83dbSDimitry Andric   OS << "Detailed summary:\n";
261e8d8bef9SDimitry Andric   for (const auto &Entry : DetailedSummary) {
2625ffd83dbSDimitry Andric     OS << Entry.NumCounts << " blocks with count >= " << Entry.MinCount
2635ffd83dbSDimitry Andric        << " account for "
2645ffd83dbSDimitry Andric        << format("%0.6g", (float)Entry.Cutoff / Scale * 100)
2655ffd83dbSDimitry Andric        << " percentage of the total counts.\n";
2665ffd83dbSDimitry Andric   }
2670b57cec5SDimitry Andric }
268