1 //=-- Profilesummary.cpp - Profile summary support --------------------------=// 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 contains support for converting profile summary data from/to 10 // metadata. 11 // 12 //===----------------------------------------------------------------------===// 13 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 22 using namespace llvm; 23 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, 27 uint64_t Val) { 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); 32 } 33 34 // Return an MDTuple with two elements. The first element is a string Key and 35 // the second is a string Value. 36 static Metadata *getKeyValMD(LLVMContext &Context, const char *Key, 37 const char *Val) { 38 Metadata *Ops[2] = {MDString::get(Context, Key), MDString::get(Context, Val)}; 39 return MDTuple::get(Context, Ops); 40 } 41 42 // This returns an MDTuple representing the detiled summary. The tuple has two 43 // elements: a string "DetailedSummary" and an MDTuple representing the value 44 // of the detailed summary. Each element of this tuple is again an MDTuple whose 45 // elements are the (Cutoff, MinCount, NumCounts) triplet of the 46 // DetailedSummaryEntry. 47 Metadata *ProfileSummary::getDetailedSummaryMD(LLVMContext &Context) { 48 std::vector<Metadata *> Entries; 49 Type *Int32Ty = Type::getInt32Ty(Context); 50 Type *Int64Ty = Type::getInt64Ty(Context); 51 for (auto &Entry : DetailedSummary) { 52 Metadata *EntryMD[3] = { 53 ConstantAsMetadata::get(ConstantInt::get(Int32Ty, Entry.Cutoff)), 54 ConstantAsMetadata::get(ConstantInt::get(Int64Ty, Entry.MinCount)), 55 ConstantAsMetadata::get(ConstantInt::get(Int32Ty, Entry.NumCounts))}; 56 Entries.push_back(MDTuple::get(Context, EntryMD)); 57 } 58 Metadata *Ops[2] = {MDString::get(Context, "DetailedSummary"), 59 MDTuple::get(Context, Entries)}; 60 return MDTuple::get(Context, Ops); 61 } 62 63 // This returns an MDTuple representing this ProfileSummary object. The first 64 // entry of this tuple is another MDTuple of two elements: a string 65 // "ProfileFormat" and a string representing the format ("InstrProf" or 66 // "SampleProfile"). The rest of the elements of the outer MDTuple are specific 67 // to the kind of profile summary as returned by getFormatSpecificMD. 68 // IsPartialProfile is an optional field and \p AddPartialField will decide 69 // whether to add a field for it. 70 Metadata *ProfileSummary::getMD(LLVMContext &Context, bool AddPartialField) { 71 const char *KindStr[3] = {"InstrProf", "CSInstrProf", "SampleProfile"}; 72 SmallVector<Metadata *, 16> Components; 73 Components.push_back(getKeyValMD(Context, "ProfileFormat", KindStr[PSK])); 74 Components.push_back(getKeyValMD(Context, "TotalCount", getTotalCount())); 75 Components.push_back(getKeyValMD(Context, "MaxCount", getMaxCount())); 76 Components.push_back( 77 getKeyValMD(Context, "MaxInternalCount", getMaxInternalCount())); 78 Components.push_back( 79 getKeyValMD(Context, "MaxFunctionCount", getMaxFunctionCount())); 80 Components.push_back(getKeyValMD(Context, "NumCounts", getNumCounts())); 81 Components.push_back(getKeyValMD(Context, "NumFunctions", getNumFunctions())); 82 if (AddPartialField) 83 Components.push_back( 84 getKeyValMD(Context, "IsPartialProfile", isPartialProfile())); 85 Components.push_back(getDetailedSummaryMD(Context)); 86 return MDTuple::get(Context, Components); 87 } 88 89 // Parse an MDTuple representing (Key, Val) pair. 90 static bool getVal(MDTuple *MD, const char *Key, uint64_t &Val) { 91 if (!MD) 92 return false; 93 if (MD->getNumOperands() != 2) 94 return false; 95 MDString *KeyMD = dyn_cast<MDString>(MD->getOperand(0)); 96 ConstantAsMetadata *ValMD = dyn_cast<ConstantAsMetadata>(MD->getOperand(1)); 97 if (!KeyMD || !ValMD) 98 return false; 99 if (!KeyMD->getString().equals(Key)) 100 return false; 101 Val = cast<ConstantInt>(ValMD->getValue())->getZExtValue(); 102 return true; 103 } 104 105 // Check if an MDTuple represents a (Key, Val) pair. 106 static bool isKeyValuePair(MDTuple *MD, const char *Key, const char *Val) { 107 if (!MD || MD->getNumOperands() != 2) 108 return false; 109 MDString *KeyMD = dyn_cast<MDString>(MD->getOperand(0)); 110 MDString *ValMD = dyn_cast<MDString>(MD->getOperand(1)); 111 if (!KeyMD || !ValMD) 112 return false; 113 if (!KeyMD->getString().equals(Key) || !ValMD->getString().equals(Val)) 114 return false; 115 return true; 116 } 117 118 // Parse an MDTuple representing detailed summary. 119 static bool getSummaryFromMD(MDTuple *MD, SummaryEntryVector &Summary) { 120 if (!MD || MD->getNumOperands() != 2) 121 return false; 122 MDString *KeyMD = dyn_cast<MDString>(MD->getOperand(0)); 123 if (!KeyMD || !KeyMD->getString().equals("DetailedSummary")) 124 return false; 125 MDTuple *EntriesMD = dyn_cast<MDTuple>(MD->getOperand(1)); 126 if (!EntriesMD) 127 return false; 128 for (auto &&MDOp : EntriesMD->operands()) { 129 MDTuple *EntryMD = dyn_cast<MDTuple>(MDOp); 130 if (!EntryMD || EntryMD->getNumOperands() != 3) 131 return false; 132 ConstantAsMetadata *Op0 = 133 dyn_cast<ConstantAsMetadata>(EntryMD->getOperand(0)); 134 ConstantAsMetadata *Op1 = 135 dyn_cast<ConstantAsMetadata>(EntryMD->getOperand(1)); 136 ConstantAsMetadata *Op2 = 137 dyn_cast<ConstantAsMetadata>(EntryMD->getOperand(2)); 138 139 if (!Op0 || !Op1 || !Op2) 140 return false; 141 Summary.emplace_back(cast<ConstantInt>(Op0->getValue())->getZExtValue(), 142 cast<ConstantInt>(Op1->getValue())->getZExtValue(), 143 cast<ConstantInt>(Op2->getValue())->getZExtValue()); 144 } 145 return true; 146 } 147 148 ProfileSummary *ProfileSummary::getFromMD(Metadata *MD) { 149 MDTuple *Tuple = dyn_cast_or_null<MDTuple>(MD); 150 if (!Tuple && (Tuple->getNumOperands() < 8 || Tuple->getNumOperands() > 9)) 151 return nullptr; 152 153 int i = 0; 154 auto &FormatMD = Tuple->getOperand(i++); 155 ProfileSummary::Kind SummaryKind; 156 if (isKeyValuePair(dyn_cast_or_null<MDTuple>(FormatMD), "ProfileFormat", 157 "SampleProfile")) 158 SummaryKind = PSK_Sample; 159 else if (isKeyValuePair(dyn_cast_or_null<MDTuple>(FormatMD), "ProfileFormat", 160 "InstrProf")) 161 SummaryKind = PSK_Instr; 162 else if (isKeyValuePair(dyn_cast_or_null<MDTuple>(FormatMD), "ProfileFormat", 163 "CSInstrProf")) 164 SummaryKind = PSK_CSInstr; 165 else 166 return nullptr; 167 168 uint64_t NumCounts, TotalCount, NumFunctions, MaxFunctionCount, MaxCount, 169 MaxInternalCount; 170 if (!getVal(dyn_cast<MDTuple>(Tuple->getOperand(i++)), "TotalCount", 171 TotalCount)) 172 return nullptr; 173 if (!getVal(dyn_cast<MDTuple>(Tuple->getOperand(i++)), "MaxCount", MaxCount)) 174 return nullptr; 175 if (!getVal(dyn_cast<MDTuple>(Tuple->getOperand(i++)), "MaxInternalCount", 176 MaxInternalCount)) 177 return nullptr; 178 if (!getVal(dyn_cast<MDTuple>(Tuple->getOperand(i++)), "MaxFunctionCount", 179 MaxFunctionCount)) 180 return nullptr; 181 if (!getVal(dyn_cast<MDTuple>(Tuple->getOperand(i++)), "NumCounts", 182 NumCounts)) 183 return nullptr; 184 if (!getVal(dyn_cast<MDTuple>(Tuple->getOperand(i++)), "NumFunctions", 185 NumFunctions)) 186 return nullptr; 187 // Initialize IsPartialProfile because the field is optional. 188 uint64_t IsPartialProfile = 0; 189 190 // IsPartialProfile is optional so it doesn't matter even if the next val 191 // is not IsPartialProfile. 192 if (getVal(dyn_cast<MDTuple>(Tuple->getOperand(i)), "IsPartialProfile", 193 IsPartialProfile)) { 194 // Need to make sure when IsPartialProfile is presented, we won't step 195 // over the bound of Tuple operand array. 196 if (Tuple->getNumOperands() < 9) 197 return nullptr; 198 i++; 199 } 200 201 SummaryEntryVector Summary; 202 if (!getSummaryFromMD(dyn_cast<MDTuple>(Tuple->getOperand(i++)), Summary)) 203 return nullptr; 204 return new ProfileSummary(SummaryKind, std::move(Summary), TotalCount, 205 MaxCount, MaxInternalCount, MaxFunctionCount, 206 NumCounts, NumFunctions, IsPartialProfile); 207 } 208 209 void ProfileSummary::printSummary(raw_ostream &OS) { 210 OS << "Total functions: " << NumFunctions << "\n"; 211 OS << "Maximum function count: " << MaxFunctionCount << "\n"; 212 OS << "Maximum block count: " << MaxCount << "\n"; 213 OS << "Total number of blocks: " << NumCounts << "\n"; 214 OS << "Total count: " << TotalCount << "\n"; 215 } 216 217 void ProfileSummary::printDetailedSummary(raw_ostream &OS) { 218 OS << "Detailed summary:\n"; 219 for (auto Entry : DetailedSummary) { 220 OS << Entry.NumCounts << " blocks with count >= " << Entry.MinCount 221 << " account for " 222 << format("%0.6g", (float)Entry.Cutoff / Scale * 100) 223 << " percentage of the total counts.\n"; 224 } 225 } 226