10b57cec5SDimitry Andric //==-SummaryBasedOptimizations.cpp - Optimizations based on ThinLTO summary-==// 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 implements optimizations that are based on the module summaries. 100b57cec5SDimitry Andric // These optimizations are performed during the thinlink phase of the 110b57cec5SDimitry Andric // compilation. 120b57cec5SDimitry Andric // 130b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 140b57cec5SDimitry Andric 150b57cec5SDimitry Andric #include "llvm/LTO/SummaryBasedOptimizations.h" 160b57cec5SDimitry Andric #include "llvm/Analysis/SyntheticCountsUtils.h" 170b57cec5SDimitry Andric #include "llvm/IR/ModuleSummaryIndex.h" 18*480093f4SDimitry Andric #include "llvm/Support/CommandLine.h" 190b57cec5SDimitry Andric 200b57cec5SDimitry Andric using namespace llvm; 210b57cec5SDimitry Andric 228bcb0991SDimitry Andric static cl::opt<bool> ThinLTOSynthesizeEntryCounts( 230b57cec5SDimitry Andric "thinlto-synthesize-entry-counts", cl::init(false), cl::Hidden, 240b57cec5SDimitry Andric cl::desc("Synthesize entry counts based on the summary")); 250b57cec5SDimitry Andric 260b57cec5SDimitry Andric extern cl::opt<int> InitialSyntheticCount; 270b57cec5SDimitry Andric 280b57cec5SDimitry Andric static void initializeCounts(ModuleSummaryIndex &Index) { 290b57cec5SDimitry Andric auto Root = Index.calculateCallGraphRoot(); 300b57cec5SDimitry Andric // Root is a fake node. All its successors are the actual roots of the 310b57cec5SDimitry Andric // callgraph. 320b57cec5SDimitry Andric // FIXME: This initializes the entry counts of only the root nodes. This makes 330b57cec5SDimitry Andric // sense when compiling a binary with ThinLTO, but for libraries any of the 340b57cec5SDimitry Andric // non-root nodes could be called from outside. 350b57cec5SDimitry Andric for (auto &C : Root.calls()) { 360b57cec5SDimitry Andric auto &V = C.first; 370b57cec5SDimitry Andric for (auto &GVS : V.getSummaryList()) { 380b57cec5SDimitry Andric auto S = GVS.get()->getBaseObject(); 390b57cec5SDimitry Andric auto *F = cast<FunctionSummary>(S); 400b57cec5SDimitry Andric F->setEntryCount(InitialSyntheticCount); 410b57cec5SDimitry Andric } 420b57cec5SDimitry Andric } 430b57cec5SDimitry Andric } 440b57cec5SDimitry Andric 450b57cec5SDimitry Andric void llvm::computeSyntheticCounts(ModuleSummaryIndex &Index) { 460b57cec5SDimitry Andric if (!ThinLTOSynthesizeEntryCounts) 470b57cec5SDimitry Andric return; 480b57cec5SDimitry Andric 490b57cec5SDimitry Andric using Scaled64 = ScaledNumber<uint64_t>; 500b57cec5SDimitry Andric initializeCounts(Index); 510b57cec5SDimitry Andric auto GetCallSiteRelFreq = [](FunctionSummary::EdgeTy &Edge) { 520b57cec5SDimitry Andric return Scaled64(Edge.second.RelBlockFreq, -CalleeInfo::ScaleShift); 530b57cec5SDimitry Andric }; 540b57cec5SDimitry Andric auto GetEntryCount = [](ValueInfo V) { 550b57cec5SDimitry Andric if (V.getSummaryList().size()) { 560b57cec5SDimitry Andric auto S = V.getSummaryList().front().get()->getBaseObject(); 570b57cec5SDimitry Andric auto *F = cast<FunctionSummary>(S); 580b57cec5SDimitry Andric return F->entryCount(); 590b57cec5SDimitry Andric } else { 600b57cec5SDimitry Andric return UINT64_C(0); 610b57cec5SDimitry Andric } 620b57cec5SDimitry Andric }; 630b57cec5SDimitry Andric auto AddToEntryCount = [](ValueInfo V, Scaled64 New) { 640b57cec5SDimitry Andric if (!V.getSummaryList().size()) 650b57cec5SDimitry Andric return; 660b57cec5SDimitry Andric for (auto &GVS : V.getSummaryList()) { 670b57cec5SDimitry Andric auto S = GVS.get()->getBaseObject(); 680b57cec5SDimitry Andric auto *F = cast<FunctionSummary>(S); 690b57cec5SDimitry Andric F->setEntryCount( 700b57cec5SDimitry Andric SaturatingAdd(F->entryCount(), New.template toInt<uint64_t>())); 710b57cec5SDimitry Andric } 720b57cec5SDimitry Andric }; 730b57cec5SDimitry Andric 740b57cec5SDimitry Andric auto GetProfileCount = [&](ValueInfo V, FunctionSummary::EdgeTy &Edge) { 750b57cec5SDimitry Andric auto RelFreq = GetCallSiteRelFreq(Edge); 760b57cec5SDimitry Andric Scaled64 EC(GetEntryCount(V), 0); 770b57cec5SDimitry Andric return RelFreq * EC; 780b57cec5SDimitry Andric }; 790b57cec5SDimitry Andric // After initializing the counts in initializeCounts above, the counts have to 800b57cec5SDimitry Andric // be propagated across the combined callgraph. 810b57cec5SDimitry Andric // SyntheticCountsUtils::propagate takes care of this propagation on any 820b57cec5SDimitry Andric // callgraph that specialized GraphTraits. 830b57cec5SDimitry Andric SyntheticCountsUtils<ModuleSummaryIndex *>::propagate(&Index, GetProfileCount, 840b57cec5SDimitry Andric AddToEntryCount); 850b57cec5SDimitry Andric Index.setHasSyntheticEntryCounts(); 860b57cec5SDimitry Andric } 87