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