1*0b57cec5SDimitry Andric //==-SummaryBasedOptimizations.cpp - Optimizations based on ThinLTO summary-==// 2*0b57cec5SDimitry Andric // 3*0b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4*0b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information. 5*0b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6*0b57cec5SDimitry Andric // 7*0b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 8*0b57cec5SDimitry Andric // 9*0b57cec5SDimitry Andric // This file implements optimizations that are based on the module summaries. 10*0b57cec5SDimitry Andric // These optimizations are performed during the thinlink phase of the 11*0b57cec5SDimitry Andric // compilation. 12*0b57cec5SDimitry Andric // 13*0b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 14*0b57cec5SDimitry Andric 15*0b57cec5SDimitry Andric #include "llvm/LTO/SummaryBasedOptimizations.h" 16*0b57cec5SDimitry Andric #include "llvm/Analysis/SyntheticCountsUtils.h" 17*0b57cec5SDimitry Andric #include "llvm/IR/ModuleSummaryIndex.h" 18*0b57cec5SDimitry Andric 19*0b57cec5SDimitry Andric using namespace llvm; 20*0b57cec5SDimitry Andric 21*0b57cec5SDimitry Andric cl::opt<bool> ThinLTOSynthesizeEntryCounts( 22*0b57cec5SDimitry Andric "thinlto-synthesize-entry-counts", cl::init(false), cl::Hidden, 23*0b57cec5SDimitry Andric cl::desc("Synthesize entry counts based on the summary")); 24*0b57cec5SDimitry Andric 25*0b57cec5SDimitry Andric extern cl::opt<int> InitialSyntheticCount; 26*0b57cec5SDimitry Andric 27*0b57cec5SDimitry Andric static void initializeCounts(ModuleSummaryIndex &Index) { 28*0b57cec5SDimitry Andric auto Root = Index.calculateCallGraphRoot(); 29*0b57cec5SDimitry Andric // Root is a fake node. All its successors are the actual roots of the 30*0b57cec5SDimitry Andric // callgraph. 31*0b57cec5SDimitry Andric // FIXME: This initializes the entry counts of only the root nodes. This makes 32*0b57cec5SDimitry Andric // sense when compiling a binary with ThinLTO, but for libraries any of the 33*0b57cec5SDimitry Andric // non-root nodes could be called from outside. 34*0b57cec5SDimitry Andric for (auto &C : Root.calls()) { 35*0b57cec5SDimitry Andric auto &V = C.first; 36*0b57cec5SDimitry Andric for (auto &GVS : V.getSummaryList()) { 37*0b57cec5SDimitry Andric auto S = GVS.get()->getBaseObject(); 38*0b57cec5SDimitry Andric auto *F = cast<FunctionSummary>(S); 39*0b57cec5SDimitry Andric F->setEntryCount(InitialSyntheticCount); 40*0b57cec5SDimitry Andric } 41*0b57cec5SDimitry Andric } 42*0b57cec5SDimitry Andric } 43*0b57cec5SDimitry Andric 44*0b57cec5SDimitry Andric void llvm::computeSyntheticCounts(ModuleSummaryIndex &Index) { 45*0b57cec5SDimitry Andric if (!ThinLTOSynthesizeEntryCounts) 46*0b57cec5SDimitry Andric return; 47*0b57cec5SDimitry Andric 48*0b57cec5SDimitry Andric using Scaled64 = ScaledNumber<uint64_t>; 49*0b57cec5SDimitry Andric initializeCounts(Index); 50*0b57cec5SDimitry Andric auto GetCallSiteRelFreq = [](FunctionSummary::EdgeTy &Edge) { 51*0b57cec5SDimitry Andric return Scaled64(Edge.second.RelBlockFreq, -CalleeInfo::ScaleShift); 52*0b57cec5SDimitry Andric }; 53*0b57cec5SDimitry Andric auto GetEntryCount = [](ValueInfo V) { 54*0b57cec5SDimitry Andric if (V.getSummaryList().size()) { 55*0b57cec5SDimitry Andric auto S = V.getSummaryList().front().get()->getBaseObject(); 56*0b57cec5SDimitry Andric auto *F = cast<FunctionSummary>(S); 57*0b57cec5SDimitry Andric return F->entryCount(); 58*0b57cec5SDimitry Andric } else { 59*0b57cec5SDimitry Andric return UINT64_C(0); 60*0b57cec5SDimitry Andric } 61*0b57cec5SDimitry Andric }; 62*0b57cec5SDimitry Andric auto AddToEntryCount = [](ValueInfo V, Scaled64 New) { 63*0b57cec5SDimitry Andric if (!V.getSummaryList().size()) 64*0b57cec5SDimitry Andric return; 65*0b57cec5SDimitry Andric for (auto &GVS : V.getSummaryList()) { 66*0b57cec5SDimitry Andric auto S = GVS.get()->getBaseObject(); 67*0b57cec5SDimitry Andric auto *F = cast<FunctionSummary>(S); 68*0b57cec5SDimitry Andric F->setEntryCount( 69*0b57cec5SDimitry Andric SaturatingAdd(F->entryCount(), New.template toInt<uint64_t>())); 70*0b57cec5SDimitry Andric } 71*0b57cec5SDimitry Andric }; 72*0b57cec5SDimitry Andric 73*0b57cec5SDimitry Andric auto GetProfileCount = [&](ValueInfo V, FunctionSummary::EdgeTy &Edge) { 74*0b57cec5SDimitry Andric auto RelFreq = GetCallSiteRelFreq(Edge); 75*0b57cec5SDimitry Andric Scaled64 EC(GetEntryCount(V), 0); 76*0b57cec5SDimitry Andric return RelFreq * EC; 77*0b57cec5SDimitry Andric }; 78*0b57cec5SDimitry Andric // After initializing the counts in initializeCounts above, the counts have to 79*0b57cec5SDimitry Andric // be propagated across the combined callgraph. 80*0b57cec5SDimitry Andric // SyntheticCountsUtils::propagate takes care of this propagation on any 81*0b57cec5SDimitry Andric // callgraph that specialized GraphTraits. 82*0b57cec5SDimitry Andric SyntheticCountsUtils<ModuleSummaryIndex *>::propagate(&Index, GetProfileCount, 83*0b57cec5SDimitry Andric AddToEntryCount); 84*0b57cec5SDimitry Andric Index.setHasSyntheticEntryCounts(); 85*0b57cec5SDimitry Andric } 86