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