1343171Sdim//==-SummaryBasedOptimizations.cpp - Optimizations based on ThinLTO summary-==// 2343171Sdim// 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 6343171Sdim// 7343171Sdim//===----------------------------------------------------------------------===// 8343171Sdim// 9343171Sdim// This file implements optimizations that are based on the module summaries. 10343171Sdim// These optimizations are performed during the thinlink phase of the 11343171Sdim// compilation. 12343171Sdim// 13343171Sdim//===----------------------------------------------------------------------===// 14343171Sdim 15343171Sdim#include "llvm/LTO/SummaryBasedOptimizations.h" 16343171Sdim#include "llvm/Analysis/SyntheticCountsUtils.h" 17343171Sdim#include "llvm/IR/ModuleSummaryIndex.h" 18360784Sdim#include "llvm/Support/CommandLine.h" 19343171Sdim 20343171Sdimusing namespace llvm; 21343171Sdim 22360784Sdimstatic cl::opt<bool> ThinLTOSynthesizeEntryCounts( 23343171Sdim "thinlto-synthesize-entry-counts", cl::init(false), cl::Hidden, 24343171Sdim cl::desc("Synthesize entry counts based on the summary")); 25343171Sdim 26343171Sdimextern cl::opt<int> InitialSyntheticCount; 27343171Sdim 28343171Sdimstatic void initializeCounts(ModuleSummaryIndex &Index) { 29343171Sdim auto Root = Index.calculateCallGraphRoot(); 30343171Sdim // Root is a fake node. All its successors are the actual roots of the 31343171Sdim // callgraph. 32343171Sdim // FIXME: This initializes the entry counts of only the root nodes. This makes 33343171Sdim // sense when compiling a binary with ThinLTO, but for libraries any of the 34343171Sdim // non-root nodes could be called from outside. 35343171Sdim for (auto &C : Root.calls()) { 36343171Sdim auto &V = C.first; 37343171Sdim for (auto &GVS : V.getSummaryList()) { 38343171Sdim auto S = GVS.get()->getBaseObject(); 39343171Sdim auto *F = cast<FunctionSummary>(S); 40343171Sdim F->setEntryCount(InitialSyntheticCount); 41343171Sdim } 42343171Sdim } 43343171Sdim} 44343171Sdim 45343171Sdimvoid llvm::computeSyntheticCounts(ModuleSummaryIndex &Index) { 46343171Sdim if (!ThinLTOSynthesizeEntryCounts) 47343171Sdim return; 48343171Sdim 49343171Sdim using Scaled64 = ScaledNumber<uint64_t>; 50343171Sdim initializeCounts(Index); 51343171Sdim auto GetCallSiteRelFreq = [](FunctionSummary::EdgeTy &Edge) { 52343171Sdim return Scaled64(Edge.second.RelBlockFreq, -CalleeInfo::ScaleShift); 53343171Sdim }; 54343171Sdim auto GetEntryCount = [](ValueInfo V) { 55343171Sdim if (V.getSummaryList().size()) { 56343171Sdim auto S = V.getSummaryList().front().get()->getBaseObject(); 57343171Sdim auto *F = cast<FunctionSummary>(S); 58343171Sdim return F->entryCount(); 59343171Sdim } else { 60343171Sdim return UINT64_C(0); 61343171Sdim } 62343171Sdim }; 63343171Sdim auto AddToEntryCount = [](ValueInfo V, Scaled64 New) { 64343171Sdim if (!V.getSummaryList().size()) 65343171Sdim return; 66343171Sdim for (auto &GVS : V.getSummaryList()) { 67343171Sdim auto S = GVS.get()->getBaseObject(); 68343171Sdim auto *F = cast<FunctionSummary>(S); 69343171Sdim F->setEntryCount( 70343171Sdim SaturatingAdd(F->entryCount(), New.template toInt<uint64_t>())); 71343171Sdim } 72343171Sdim }; 73343171Sdim 74343171Sdim auto GetProfileCount = [&](ValueInfo V, FunctionSummary::EdgeTy &Edge) { 75343171Sdim auto RelFreq = GetCallSiteRelFreq(Edge); 76343171Sdim Scaled64 EC(GetEntryCount(V), 0); 77343171Sdim return RelFreq * EC; 78343171Sdim }; 79343171Sdim // After initializing the counts in initializeCounts above, the counts have to 80343171Sdim // be propagated across the combined callgraph. 81343171Sdim // SyntheticCountsUtils::propagate takes care of this propagation on any 82343171Sdim // callgraph that specialized GraphTraits. 83343171Sdim SyntheticCountsUtils<ModuleSummaryIndex *>::propagate(&Index, GetProfileCount, 84343171Sdim AddToEntryCount); 85343171Sdim Index.setHasSyntheticEntryCounts(); 86343171Sdim} 87