1303231Sdim//=-- Profilesummary.cpp - Profile summary support --------------------------=// 2303231Sdim// 3353358Sdim// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4353358Sdim// See https://llvm.org/LICENSE.txt for license information. 5353358Sdim// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6303231Sdim// 7303231Sdim//===----------------------------------------------------------------------===// 8303231Sdim// 9303231Sdim// This file contains support for converting profile summary data from/to 10303231Sdim// metadata. 11303231Sdim// 12303231Sdim//===----------------------------------------------------------------------===// 13303231Sdim 14303231Sdim#include "llvm/IR/ProfileSummary.h" 15303231Sdim#include "llvm/IR/Attributes.h" 16303231Sdim#include "llvm/IR/Constants.h" 17303231Sdim#include "llvm/IR/Function.h" 18303231Sdim#include "llvm/IR/Metadata.h" 19303231Sdim#include "llvm/IR/Type.h" 20303231Sdim#include "llvm/Support/Casting.h" 21303231Sdim 22303231Sdimusing namespace llvm; 23303231Sdim 24303231Sdim// Return an MDTuple with two elements. The first element is a string Key and 25303231Sdim// the second is a uint64_t Value. 26303231Sdimstatic Metadata *getKeyValMD(LLVMContext &Context, const char *Key, 27303231Sdim uint64_t Val) { 28303231Sdim Type *Int64Ty = Type::getInt64Ty(Context); 29303231Sdim Metadata *Ops[2] = {MDString::get(Context, Key), 30303231Sdim ConstantAsMetadata::get(ConstantInt::get(Int64Ty, Val))}; 31303231Sdim return MDTuple::get(Context, Ops); 32303231Sdim} 33303231Sdim 34303231Sdim// Return an MDTuple with two elements. The first element is a string Key and 35303231Sdim// the second is a string Value. 36303231Sdimstatic Metadata *getKeyValMD(LLVMContext &Context, const char *Key, 37303231Sdim const char *Val) { 38303231Sdim Metadata *Ops[2] = {MDString::get(Context, Key), MDString::get(Context, Val)}; 39303231Sdim return MDTuple::get(Context, Ops); 40303231Sdim} 41303231Sdim 42303231Sdim// This returns an MDTuple representing the detiled summary. The tuple has two 43303231Sdim// elements: a string "DetailedSummary" and an MDTuple representing the value 44303231Sdim// of the detailed summary. Each element of this tuple is again an MDTuple whose 45303231Sdim// elements are the (Cutoff, MinCount, NumCounts) triplet of the 46303231Sdim// DetailedSummaryEntry. 47303231SdimMetadata *ProfileSummary::getDetailedSummaryMD(LLVMContext &Context) { 48303231Sdim std::vector<Metadata *> Entries; 49303231Sdim Type *Int32Ty = Type::getInt32Ty(Context); 50303231Sdim Type *Int64Ty = Type::getInt64Ty(Context); 51303231Sdim for (auto &Entry : DetailedSummary) { 52303231Sdim Metadata *EntryMD[3] = { 53303231Sdim ConstantAsMetadata::get(ConstantInt::get(Int32Ty, Entry.Cutoff)), 54303231Sdim ConstantAsMetadata::get(ConstantInt::get(Int64Ty, Entry.MinCount)), 55303231Sdim ConstantAsMetadata::get(ConstantInt::get(Int32Ty, Entry.NumCounts))}; 56303231Sdim Entries.push_back(MDTuple::get(Context, EntryMD)); 57303231Sdim } 58303231Sdim Metadata *Ops[2] = {MDString::get(Context, "DetailedSummary"), 59303231Sdim MDTuple::get(Context, Entries)}; 60303231Sdim return MDTuple::get(Context, Ops); 61303231Sdim} 62303231Sdim 63303231Sdim// This returns an MDTuple representing this ProfileSummary object. The first 64303231Sdim// entry of this tuple is another MDTuple of two elements: a string 65303231Sdim// "ProfileFormat" and a string representing the format ("InstrProf" or 66303231Sdim// "SampleProfile"). The rest of the elements of the outer MDTuple are specific 67303231Sdim// to the kind of profile summary as returned by getFormatSpecificMD. 68303231SdimMetadata *ProfileSummary::getMD(LLVMContext &Context) { 69353358Sdim const char *KindStr[3] = {"InstrProf", "CSInstrProf", "SampleProfile"}; 70341825Sdim Metadata *Components[] = { 71341825Sdim getKeyValMD(Context, "ProfileFormat", KindStr[PSK]), 72341825Sdim getKeyValMD(Context, "TotalCount", getTotalCount()), 73341825Sdim getKeyValMD(Context, "MaxCount", getMaxCount()), 74341825Sdim getKeyValMD(Context, "MaxInternalCount", getMaxInternalCount()), 75341825Sdim getKeyValMD(Context, "MaxFunctionCount", getMaxFunctionCount()), 76341825Sdim getKeyValMD(Context, "NumCounts", getNumCounts()), 77341825Sdim getKeyValMD(Context, "NumFunctions", getNumFunctions()), 78341825Sdim getDetailedSummaryMD(Context), 79341825Sdim }; 80303231Sdim return MDTuple::get(Context, Components); 81303231Sdim} 82303231Sdim 83303231Sdim// Parse an MDTuple representing (Key, Val) pair. 84303231Sdimstatic bool getVal(MDTuple *MD, const char *Key, uint64_t &Val) { 85303231Sdim if (!MD) 86303231Sdim return false; 87303231Sdim if (MD->getNumOperands() != 2) 88303231Sdim return false; 89303231Sdim MDString *KeyMD = dyn_cast<MDString>(MD->getOperand(0)); 90303231Sdim ConstantAsMetadata *ValMD = dyn_cast<ConstantAsMetadata>(MD->getOperand(1)); 91303231Sdim if (!KeyMD || !ValMD) 92303231Sdim return false; 93303231Sdim if (!KeyMD->getString().equals(Key)) 94303231Sdim return false; 95303231Sdim Val = cast<ConstantInt>(ValMD->getValue())->getZExtValue(); 96303231Sdim return true; 97303231Sdim} 98303231Sdim 99303231Sdim// Check if an MDTuple represents a (Key, Val) pair. 100303231Sdimstatic bool isKeyValuePair(MDTuple *MD, const char *Key, const char *Val) { 101303231Sdim if (!MD || MD->getNumOperands() != 2) 102303231Sdim return false; 103303231Sdim MDString *KeyMD = dyn_cast<MDString>(MD->getOperand(0)); 104303231Sdim MDString *ValMD = dyn_cast<MDString>(MD->getOperand(1)); 105303231Sdim if (!KeyMD || !ValMD) 106303231Sdim return false; 107303231Sdim if (!KeyMD->getString().equals(Key) || !ValMD->getString().equals(Val)) 108303231Sdim return false; 109303231Sdim return true; 110303231Sdim} 111303231Sdim 112303231Sdim// Parse an MDTuple representing detailed summary. 113303231Sdimstatic bool getSummaryFromMD(MDTuple *MD, SummaryEntryVector &Summary) { 114303231Sdim if (!MD || MD->getNumOperands() != 2) 115303231Sdim return false; 116303231Sdim MDString *KeyMD = dyn_cast<MDString>(MD->getOperand(0)); 117303231Sdim if (!KeyMD || !KeyMD->getString().equals("DetailedSummary")) 118303231Sdim return false; 119303231Sdim MDTuple *EntriesMD = dyn_cast<MDTuple>(MD->getOperand(1)); 120303231Sdim if (!EntriesMD) 121303231Sdim return false; 122303231Sdim for (auto &&MDOp : EntriesMD->operands()) { 123303231Sdim MDTuple *EntryMD = dyn_cast<MDTuple>(MDOp); 124303231Sdim if (!EntryMD || EntryMD->getNumOperands() != 3) 125303231Sdim return false; 126303231Sdim ConstantAsMetadata *Op0 = 127303231Sdim dyn_cast<ConstantAsMetadata>(EntryMD->getOperand(0)); 128303231Sdim ConstantAsMetadata *Op1 = 129303231Sdim dyn_cast<ConstantAsMetadata>(EntryMD->getOperand(1)); 130303231Sdim ConstantAsMetadata *Op2 = 131303231Sdim dyn_cast<ConstantAsMetadata>(EntryMD->getOperand(2)); 132303231Sdim 133303231Sdim if (!Op0 || !Op1 || !Op2) 134303231Sdim return false; 135303231Sdim Summary.emplace_back(cast<ConstantInt>(Op0->getValue())->getZExtValue(), 136303231Sdim cast<ConstantInt>(Op1->getValue())->getZExtValue(), 137303231Sdim cast<ConstantInt>(Op2->getValue())->getZExtValue()); 138303231Sdim } 139303231Sdim return true; 140303231Sdim} 141303231Sdim 142303231SdimProfileSummary *ProfileSummary::getFromMD(Metadata *MD) { 143341825Sdim MDTuple *Tuple = dyn_cast_or_null<MDTuple>(MD); 144341825Sdim if (!Tuple || Tuple->getNumOperands() != 8) 145303231Sdim return nullptr; 146303231Sdim 147303231Sdim auto &FormatMD = Tuple->getOperand(0); 148303231Sdim ProfileSummary::Kind SummaryKind; 149303231Sdim if (isKeyValuePair(dyn_cast_or_null<MDTuple>(FormatMD), "ProfileFormat", 150303231Sdim "SampleProfile")) 151303231Sdim SummaryKind = PSK_Sample; 152303231Sdim else if (isKeyValuePair(dyn_cast_or_null<MDTuple>(FormatMD), "ProfileFormat", 153303231Sdim "InstrProf")) 154303231Sdim SummaryKind = PSK_Instr; 155353358Sdim else if (isKeyValuePair(dyn_cast_or_null<MDTuple>(FormatMD), "ProfileFormat", 156353358Sdim "CSInstrProf")) 157353358Sdim SummaryKind = PSK_CSInstr; 158303231Sdim else 159303231Sdim return nullptr; 160303231Sdim 161303231Sdim uint64_t NumCounts, TotalCount, NumFunctions, MaxFunctionCount, MaxCount, 162303231Sdim MaxInternalCount; 163303231Sdim if (!getVal(dyn_cast<MDTuple>(Tuple->getOperand(1)), "TotalCount", 164303231Sdim TotalCount)) 165303231Sdim return nullptr; 166303231Sdim if (!getVal(dyn_cast<MDTuple>(Tuple->getOperand(2)), "MaxCount", MaxCount)) 167303231Sdim return nullptr; 168303231Sdim if (!getVal(dyn_cast<MDTuple>(Tuple->getOperand(3)), "MaxInternalCount", 169303231Sdim MaxInternalCount)) 170303231Sdim return nullptr; 171303231Sdim if (!getVal(dyn_cast<MDTuple>(Tuple->getOperand(4)), "MaxFunctionCount", 172303231Sdim MaxFunctionCount)) 173303231Sdim return nullptr; 174303231Sdim if (!getVal(dyn_cast<MDTuple>(Tuple->getOperand(5)), "NumCounts", NumCounts)) 175303231Sdim return nullptr; 176303231Sdim if (!getVal(dyn_cast<MDTuple>(Tuple->getOperand(6)), "NumFunctions", 177303231Sdim NumFunctions)) 178303231Sdim return nullptr; 179303231Sdim 180303231Sdim SummaryEntryVector Summary; 181303231Sdim if (!getSummaryFromMD(dyn_cast<MDTuple>(Tuple->getOperand(7)), Summary)) 182303231Sdim return nullptr; 183341825Sdim return new ProfileSummary(SummaryKind, std::move(Summary), TotalCount, 184341825Sdim MaxCount, MaxInternalCount, MaxFunctionCount, 185341825Sdim NumCounts, NumFunctions); 186303231Sdim} 187