10b57cec5SDimitry Andric //=-- ProfilesummaryBuilder.cpp - Profile summary computation ---------------=// 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 computing profile summary data. 100b57cec5SDimitry Andric // 110b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 120b57cec5SDimitry Andric 130b57cec5SDimitry Andric #include "llvm/IR/Attributes.h" 140b57cec5SDimitry Andric #include "llvm/IR/Function.h" 150b57cec5SDimitry Andric #include "llvm/IR/Metadata.h" 160b57cec5SDimitry Andric #include "llvm/IR/Type.h" 170b57cec5SDimitry Andric #include "llvm/ProfileData/InstrProf.h" 180b57cec5SDimitry Andric #include "llvm/ProfileData/ProfileCommon.h" 190b57cec5SDimitry Andric #include "llvm/ProfileData/SampleProf.h" 200b57cec5SDimitry Andric #include "llvm/Support/Casting.h" 210b57cec5SDimitry Andric 220b57cec5SDimitry Andric using namespace llvm; 230b57cec5SDimitry Andric 240b57cec5SDimitry Andric // A set of cutoff values. Each value, when divided by ProfileSummary::Scale 250b57cec5SDimitry Andric // (which is 1000000) is a desired percentile of total counts. 260b57cec5SDimitry Andric static const uint32_t DefaultCutoffsData[] = { 270b57cec5SDimitry Andric 10000, /* 1% */ 280b57cec5SDimitry Andric 100000, /* 10% */ 290b57cec5SDimitry Andric 200000, 300000, 400000, 500000, 600000, 700000, 800000, 300b57cec5SDimitry Andric 900000, 950000, 990000, 999000, 999900, 999990, 999999}; 310b57cec5SDimitry Andric const ArrayRef<uint32_t> ProfileSummaryBuilder::DefaultCutoffs = 320b57cec5SDimitry Andric DefaultCutoffsData; 330b57cec5SDimitry Andric 340b57cec5SDimitry Andric void InstrProfSummaryBuilder::addRecord(const InstrProfRecord &R) { 350b57cec5SDimitry Andric // The first counter is not necessarily an entry count for IR 360b57cec5SDimitry Andric // instrumentation profiles. 370b57cec5SDimitry Andric // Eventually MaxFunctionCount will become obsolete and this can be 380b57cec5SDimitry Andric // removed. 390b57cec5SDimitry Andric addEntryCount(R.Counts[0]); 400b57cec5SDimitry Andric for (size_t I = 1, E = R.Counts.size(); I < E; ++I) 410b57cec5SDimitry Andric addInternalCount(R.Counts[I]); 420b57cec5SDimitry Andric } 430b57cec5SDimitry Andric 440b57cec5SDimitry Andric // To compute the detailed summary, we consider each line containing samples as 450b57cec5SDimitry Andric // equivalent to a block with a count in the instrumented profile. 460b57cec5SDimitry Andric void SampleProfileSummaryBuilder::addRecord( 470b57cec5SDimitry Andric const sampleprof::FunctionSamples &FS, bool isCallsiteSample) { 480b57cec5SDimitry Andric if (!isCallsiteSample) { 490b57cec5SDimitry Andric NumFunctions++; 500b57cec5SDimitry Andric if (FS.getHeadSamples() > MaxFunctionCount) 510b57cec5SDimitry Andric MaxFunctionCount = FS.getHeadSamples(); 520b57cec5SDimitry Andric } 530b57cec5SDimitry Andric for (const auto &I : FS.getBodySamples()) 540b57cec5SDimitry Andric addCount(I.second.getSamples()); 550b57cec5SDimitry Andric for (const auto &I : FS.getCallsiteSamples()) 560b57cec5SDimitry Andric for (const auto &CS : I.second) 570b57cec5SDimitry Andric addRecord(CS.second, true); 580b57cec5SDimitry Andric } 590b57cec5SDimitry Andric 600b57cec5SDimitry Andric // The argument to this method is a vector of cutoff percentages and the return 610b57cec5SDimitry Andric // value is a vector of (Cutoff, MinCount, NumCounts) triplets. 620b57cec5SDimitry Andric void ProfileSummaryBuilder::computeDetailedSummary() { 630b57cec5SDimitry Andric if (DetailedSummaryCutoffs.empty()) 640b57cec5SDimitry Andric return; 650b57cec5SDimitry Andric llvm::sort(DetailedSummaryCutoffs); 660b57cec5SDimitry Andric auto Iter = CountFrequencies.begin(); 670b57cec5SDimitry Andric const auto End = CountFrequencies.end(); 680b57cec5SDimitry Andric 690b57cec5SDimitry Andric uint32_t CountsSeen = 0; 700b57cec5SDimitry Andric uint64_t CurrSum = 0, Count = 0; 710b57cec5SDimitry Andric 720b57cec5SDimitry Andric for (const uint32_t Cutoff : DetailedSummaryCutoffs) { 730b57cec5SDimitry Andric assert(Cutoff <= 999999); 740b57cec5SDimitry Andric APInt Temp(128, TotalCount); 750b57cec5SDimitry Andric APInt N(128, Cutoff); 760b57cec5SDimitry Andric APInt D(128, ProfileSummary::Scale); 770b57cec5SDimitry Andric Temp *= N; 780b57cec5SDimitry Andric Temp = Temp.sdiv(D); 790b57cec5SDimitry Andric uint64_t DesiredCount = Temp.getZExtValue(); 800b57cec5SDimitry Andric assert(DesiredCount <= TotalCount); 810b57cec5SDimitry Andric while (CurrSum < DesiredCount && Iter != End) { 820b57cec5SDimitry Andric Count = Iter->first; 830b57cec5SDimitry Andric uint32_t Freq = Iter->second; 840b57cec5SDimitry Andric CurrSum += (Count * Freq); 850b57cec5SDimitry Andric CountsSeen += Freq; 860b57cec5SDimitry Andric Iter++; 870b57cec5SDimitry Andric } 880b57cec5SDimitry Andric assert(CurrSum >= DesiredCount); 890b57cec5SDimitry Andric ProfileSummaryEntry PSE = {Cutoff, Count, CountsSeen}; 900b57cec5SDimitry Andric DetailedSummary.push_back(PSE); 910b57cec5SDimitry Andric } 920b57cec5SDimitry Andric } 930b57cec5SDimitry Andric 940b57cec5SDimitry Andric std::unique_ptr<ProfileSummary> SampleProfileSummaryBuilder::getSummary() { 950b57cec5SDimitry Andric computeDetailedSummary(); 96*8bcb0991SDimitry Andric return std::make_unique<ProfileSummary>( 970b57cec5SDimitry Andric ProfileSummary::PSK_Sample, DetailedSummary, TotalCount, MaxCount, 0, 980b57cec5SDimitry Andric MaxFunctionCount, NumCounts, NumFunctions); 990b57cec5SDimitry Andric } 1000b57cec5SDimitry Andric 1010b57cec5SDimitry Andric std::unique_ptr<ProfileSummary> InstrProfSummaryBuilder::getSummary() { 1020b57cec5SDimitry Andric computeDetailedSummary(); 103*8bcb0991SDimitry Andric return std::make_unique<ProfileSummary>( 1040b57cec5SDimitry Andric ProfileSummary::PSK_Instr, DetailedSummary, TotalCount, MaxCount, 1050b57cec5SDimitry Andric MaxInternalBlockCount, MaxFunctionCount, NumCounts, NumFunctions); 1060b57cec5SDimitry Andric } 1070b57cec5SDimitry Andric 1080b57cec5SDimitry Andric void InstrProfSummaryBuilder::addEntryCount(uint64_t Count) { 1090b57cec5SDimitry Andric addCount(Count); 1100b57cec5SDimitry Andric NumFunctions++; 1110b57cec5SDimitry Andric if (Count > MaxFunctionCount) 1120b57cec5SDimitry Andric MaxFunctionCount = Count; 1130b57cec5SDimitry Andric } 1140b57cec5SDimitry Andric 1150b57cec5SDimitry Andric void InstrProfSummaryBuilder::addInternalCount(uint64_t Count) { 1160b57cec5SDimitry Andric addCount(Count); 1170b57cec5SDimitry Andric if (Count > MaxInternalBlockCount) 1180b57cec5SDimitry Andric MaxInternalBlockCount = Count; 1190b57cec5SDimitry Andric } 120