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