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 Metadata *ProfileSummary::getMD(LLVMContext &Context) { 69 const char *KindStr[3] = {"InstrProf", "CSInstrProf", "SampleProfile"}; 70 Metadata *Components[] = { 71 getKeyValMD(Context, "ProfileFormat", KindStr[PSK]), 72 getKeyValMD(Context, "TotalCount", getTotalCount()), 73 getKeyValMD(Context, "MaxCount", getMaxCount()), 74 getKeyValMD(Context, "MaxInternalCount", getMaxInternalCount()), 75 getKeyValMD(Context, "MaxFunctionCount", getMaxFunctionCount()), 76 getKeyValMD(Context, "NumCounts", getNumCounts()), 77 getKeyValMD(Context, "NumFunctions", getNumFunctions()), 78 getDetailedSummaryMD(Context), 79 }; 80 return MDTuple::get(Context, Components); 81 } 82 83 // Parse an MDTuple representing (Key, Val) pair. 84 static bool getVal(MDTuple *MD, const char *Key, uint64_t &Val) { 85 if (!MD) 86 return false; 87 if (MD->getNumOperands() != 2) 88 return false; 89 MDString *KeyMD = dyn_cast<MDString>(MD->getOperand(0)); 90 ConstantAsMetadata *ValMD = dyn_cast<ConstantAsMetadata>(MD->getOperand(1)); 91 if (!KeyMD || !ValMD) 92 return false; 93 if (!KeyMD->getString().equals(Key)) 94 return false; 95 Val = cast<ConstantInt>(ValMD->getValue())->getZExtValue(); 96 return true; 97 } 98 99 // Check if an MDTuple represents a (Key, Val) pair. 100 static bool isKeyValuePair(MDTuple *MD, const char *Key, const char *Val) { 101 if (!MD || MD->getNumOperands() != 2) 102 return false; 103 MDString *KeyMD = dyn_cast<MDString>(MD->getOperand(0)); 104 MDString *ValMD = dyn_cast<MDString>(MD->getOperand(1)); 105 if (!KeyMD || !ValMD) 106 return false; 107 if (!KeyMD->getString().equals(Key) || !ValMD->getString().equals(Val)) 108 return false; 109 return true; 110 } 111 112 // Parse an MDTuple representing detailed summary. 113 static bool getSummaryFromMD(MDTuple *MD, SummaryEntryVector &Summary) { 114 if (!MD || MD->getNumOperands() != 2) 115 return false; 116 MDString *KeyMD = dyn_cast<MDString>(MD->getOperand(0)); 117 if (!KeyMD || !KeyMD->getString().equals("DetailedSummary")) 118 return false; 119 MDTuple *EntriesMD = dyn_cast<MDTuple>(MD->getOperand(1)); 120 if (!EntriesMD) 121 return false; 122 for (auto &&MDOp : EntriesMD->operands()) { 123 MDTuple *EntryMD = dyn_cast<MDTuple>(MDOp); 124 if (!EntryMD || EntryMD->getNumOperands() != 3) 125 return false; 126 ConstantAsMetadata *Op0 = 127 dyn_cast<ConstantAsMetadata>(EntryMD->getOperand(0)); 128 ConstantAsMetadata *Op1 = 129 dyn_cast<ConstantAsMetadata>(EntryMD->getOperand(1)); 130 ConstantAsMetadata *Op2 = 131 dyn_cast<ConstantAsMetadata>(EntryMD->getOperand(2)); 132 133 if (!Op0 || !Op1 || !Op2) 134 return false; 135 Summary.emplace_back(cast<ConstantInt>(Op0->getValue())->getZExtValue(), 136 cast<ConstantInt>(Op1->getValue())->getZExtValue(), 137 cast<ConstantInt>(Op2->getValue())->getZExtValue()); 138 } 139 return true; 140 } 141 142 ProfileSummary *ProfileSummary::getFromMD(Metadata *MD) { 143 MDTuple *Tuple = dyn_cast_or_null<MDTuple>(MD); 144 if (!Tuple || Tuple->getNumOperands() != 8) 145 return nullptr; 146 147 auto &FormatMD = Tuple->getOperand(0); 148 ProfileSummary::Kind SummaryKind; 149 if (isKeyValuePair(dyn_cast_or_null<MDTuple>(FormatMD), "ProfileFormat", 150 "SampleProfile")) 151 SummaryKind = PSK_Sample; 152 else if (isKeyValuePair(dyn_cast_or_null<MDTuple>(FormatMD), "ProfileFormat", 153 "InstrProf")) 154 SummaryKind = PSK_Instr; 155 else if (isKeyValuePair(dyn_cast_or_null<MDTuple>(FormatMD), "ProfileFormat", 156 "CSInstrProf")) 157 SummaryKind = PSK_CSInstr; 158 else 159 return nullptr; 160 161 uint64_t NumCounts, TotalCount, NumFunctions, MaxFunctionCount, MaxCount, 162 MaxInternalCount; 163 if (!getVal(dyn_cast<MDTuple>(Tuple->getOperand(1)), "TotalCount", 164 TotalCount)) 165 return nullptr; 166 if (!getVal(dyn_cast<MDTuple>(Tuple->getOperand(2)), "MaxCount", MaxCount)) 167 return nullptr; 168 if (!getVal(dyn_cast<MDTuple>(Tuple->getOperand(3)), "MaxInternalCount", 169 MaxInternalCount)) 170 return nullptr; 171 if (!getVal(dyn_cast<MDTuple>(Tuple->getOperand(4)), "MaxFunctionCount", 172 MaxFunctionCount)) 173 return nullptr; 174 if (!getVal(dyn_cast<MDTuple>(Tuple->getOperand(5)), "NumCounts", NumCounts)) 175 return nullptr; 176 if (!getVal(dyn_cast<MDTuple>(Tuple->getOperand(6)), "NumFunctions", 177 NumFunctions)) 178 return nullptr; 179 180 SummaryEntryVector Summary; 181 if (!getSummaryFromMD(dyn_cast<MDTuple>(Tuple->getOperand(7)), Summary)) 182 return nullptr; 183 return new ProfileSummary(SummaryKind, std::move(Summary), TotalCount, 184 MaxCount, MaxInternalCount, MaxFunctionCount, 185 NumCounts, NumFunctions); 186 } 187