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