1dd58ef01SDimitry Andric //===- FunctionImport.cpp - ThinLTO Summary-based Function Import ---------===//
2dd58ef01SDimitry Andric //
3e6d15924SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4e6d15924SDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
5e6d15924SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6dd58ef01SDimitry Andric //
7dd58ef01SDimitry Andric //===----------------------------------------------------------------------===//
8dd58ef01SDimitry Andric //
9dd58ef01SDimitry Andric // This file implements Function import based on summaries.
10dd58ef01SDimitry Andric //
11dd58ef01SDimitry Andric //===----------------------------------------------------------------------===//
12dd58ef01SDimitry Andric
13dd58ef01SDimitry Andric #include "llvm/Transforms/IPO/FunctionImport.h"
14044eb2f6SDimitry Andric #include "llvm/ADT/ArrayRef.h"
15044eb2f6SDimitry Andric #include "llvm/ADT/STLExtras.h"
16044eb2f6SDimitry Andric #include "llvm/ADT/SetVector.h"
1701095a5dSDimitry Andric #include "llvm/ADT/SmallVector.h"
1801095a5dSDimitry Andric #include "llvm/ADT/Statistic.h"
19044eb2f6SDimitry Andric #include "llvm/ADT/StringRef.h"
20a303c417SDimitry Andric #include "llvm/Bitcode/BitcodeReader.h"
21dd58ef01SDimitry Andric #include "llvm/IR/AutoUpgrade.h"
22044eb2f6SDimitry Andric #include "llvm/IR/Constants.h"
23044eb2f6SDimitry Andric #include "llvm/IR/Function.h"
24044eb2f6SDimitry Andric #include "llvm/IR/GlobalAlias.h"
25044eb2f6SDimitry Andric #include "llvm/IR/GlobalObject.h"
26044eb2f6SDimitry Andric #include "llvm/IR/GlobalValue.h"
27044eb2f6SDimitry Andric #include "llvm/IR/GlobalVariable.h"
28044eb2f6SDimitry Andric #include "llvm/IR/Metadata.h"
29dd58ef01SDimitry Andric #include "llvm/IR/Module.h"
30044eb2f6SDimitry Andric #include "llvm/IR/ModuleSummaryIndex.h"
31dd58ef01SDimitry Andric #include "llvm/IRReader/IRReader.h"
32044eb2f6SDimitry Andric #include "llvm/Linker/IRMover.h"
33044eb2f6SDimitry Andric #include "llvm/Support/Casting.h"
34dd58ef01SDimitry Andric #include "llvm/Support/CommandLine.h"
35dd58ef01SDimitry Andric #include "llvm/Support/Debug.h"
36c0981da4SDimitry Andric #include "llvm/Support/Errc.h"
37044eb2f6SDimitry Andric #include "llvm/Support/Error.h"
38044eb2f6SDimitry Andric #include "llvm/Support/ErrorHandling.h"
39044eb2f6SDimitry Andric #include "llvm/Support/FileSystem.h"
40312c0ed1SDimitry Andric #include "llvm/Support/JSON.h"
41dd58ef01SDimitry Andric #include "llvm/Support/SourceMgr.h"
42044eb2f6SDimitry Andric #include "llvm/Support/raw_ostream.h"
4301095a5dSDimitry Andric #include "llvm/Transforms/IPO/Internalize.h"
44044eb2f6SDimitry Andric #include "llvm/Transforms/Utils/Cloning.h"
4501095a5dSDimitry Andric #include "llvm/Transforms/Utils/FunctionImportUtils.h"
46044eb2f6SDimitry Andric #include "llvm/Transforms/Utils/ValueMapper.h"
47044eb2f6SDimitry Andric #include <cassert>
48044eb2f6SDimitry Andric #include <memory>
49044eb2f6SDimitry Andric #include <set>
50044eb2f6SDimitry Andric #include <string>
51044eb2f6SDimitry Andric #include <system_error>
52044eb2f6SDimitry Andric #include <tuple>
53044eb2f6SDimitry Andric #include <utility>
54dd58ef01SDimitry Andric
55dd58ef01SDimitry Andric using namespace llvm;
56dd58ef01SDimitry Andric
57044eb2f6SDimitry Andric #define DEBUG_TYPE "function-import"
58044eb2f6SDimitry Andric
59d8e91e46SDimitry Andric STATISTIC(NumImportedFunctionsThinLink,
60d8e91e46SDimitry Andric "Number of functions thin link decided to import");
61d8e91e46SDimitry Andric STATISTIC(NumImportedHotFunctionsThinLink,
62d8e91e46SDimitry Andric "Number of hot functions thin link decided to import");
63d8e91e46SDimitry Andric STATISTIC(NumImportedCriticalFunctionsThinLink,
64d8e91e46SDimitry Andric "Number of critical functions thin link decided to import");
65d8e91e46SDimitry Andric STATISTIC(NumImportedGlobalVarsThinLink,
66d8e91e46SDimitry Andric "Number of global variables thin link decided to import");
67d8e91e46SDimitry Andric STATISTIC(NumImportedFunctions, "Number of functions imported in backend");
68d8e91e46SDimitry Andric STATISTIC(NumImportedGlobalVars,
69d8e91e46SDimitry Andric "Number of global variables imported in backend");
707e7b6700SDimitry Andric STATISTIC(NumImportedModules, "Number of modules imported from");
717e7b6700SDimitry Andric STATISTIC(NumDeadSymbols, "Number of dead stripped symbols in index");
727e7b6700SDimitry Andric STATISTIC(NumLiveSymbols, "Number of live symbols in index");
73dd58ef01SDimitry Andric
74dd58ef01SDimitry Andric /// Limit on instruction count of imported functions.
75dd58ef01SDimitry Andric static cl::opt<unsigned> ImportInstrLimit(
76dd58ef01SDimitry Andric "import-instr-limit", cl::init(100), cl::Hidden, cl::value_desc("N"),
77dd58ef01SDimitry Andric cl::desc("Only import functions with less than N instructions"));
78dd58ef01SDimitry Andric
79eb11fae6SDimitry Andric static cl::opt<int> ImportCutoff(
80eb11fae6SDimitry Andric "import-cutoff", cl::init(-1), cl::Hidden, cl::value_desc("N"),
81eb11fae6SDimitry Andric cl::desc("Only import first N functions if N>=0 (default -1)"));
82eb11fae6SDimitry Andric
83344a3780SDimitry Andric static cl::opt<bool>
84344a3780SDimitry Andric ForceImportAll("force-import-all", cl::init(false), cl::Hidden,
85344a3780SDimitry Andric cl::desc("Import functions with noinline attribute"));
86344a3780SDimitry Andric
8701095a5dSDimitry Andric static cl::opt<float>
8801095a5dSDimitry Andric ImportInstrFactor("import-instr-evolution-factor", cl::init(0.7),
8901095a5dSDimitry Andric cl::Hidden, cl::value_desc("x"),
9001095a5dSDimitry Andric cl::desc("As we import functions, multiply the "
9101095a5dSDimitry Andric "`import-instr-limit` threshold by this factor "
9201095a5dSDimitry Andric "before processing newly imported functions"));
9301095a5dSDimitry Andric
94b915e9e0SDimitry Andric static cl::opt<float> ImportHotInstrFactor(
95b915e9e0SDimitry Andric "import-hot-evolution-factor", cl::init(1.0), cl::Hidden,
96b915e9e0SDimitry Andric cl::value_desc("x"),
97b915e9e0SDimitry Andric cl::desc("As we import functions called from hot callsite, multiply the "
98b915e9e0SDimitry Andric "`import-instr-limit` threshold by this factor "
99b915e9e0SDimitry Andric "before processing newly imported functions"));
100b915e9e0SDimitry Andric
101b915e9e0SDimitry Andric static cl::opt<float> ImportHotMultiplier(
102044eb2f6SDimitry Andric "import-hot-multiplier", cl::init(10.0), cl::Hidden, cl::value_desc("x"),
103b915e9e0SDimitry Andric cl::desc("Multiply the `import-instr-limit` threshold for hot callsites"));
104b915e9e0SDimitry Andric
105ca089b24SDimitry Andric static cl::opt<float> ImportCriticalMultiplier(
106ca089b24SDimitry Andric "import-critical-multiplier", cl::init(100.0), cl::Hidden,
107ca089b24SDimitry Andric cl::value_desc("x"),
108ca089b24SDimitry Andric cl::desc(
109ca089b24SDimitry Andric "Multiply the `import-instr-limit` threshold for critical callsites"));
110ca089b24SDimitry Andric
111b915e9e0SDimitry Andric // FIXME: This multiplier was not really tuned up.
112b915e9e0SDimitry Andric static cl::opt<float> ImportColdMultiplier(
113b915e9e0SDimitry Andric "import-cold-multiplier", cl::init(0), cl::Hidden, cl::value_desc("N"),
114b915e9e0SDimitry Andric cl::desc("Multiply the `import-instr-limit` threshold for cold callsites"));
115b915e9e0SDimitry Andric
11601095a5dSDimitry Andric static cl::opt<bool> PrintImports("print-imports", cl::init(false), cl::Hidden,
11701095a5dSDimitry Andric cl::desc("Print imported functions"));
11801095a5dSDimitry Andric
119d8e91e46SDimitry Andric static cl::opt<bool> PrintImportFailures(
120d8e91e46SDimitry Andric "print-import-failures", cl::init(false), cl::Hidden,
121d8e91e46SDimitry Andric cl::desc("Print information for functions rejected for importing"));
122d8e91e46SDimitry Andric
1237e7b6700SDimitry Andric static cl::opt<bool> ComputeDead("compute-dead", cl::init(true), cl::Hidden,
1247e7b6700SDimitry Andric cl::desc("Compute dead symbols"));
1257e7b6700SDimitry Andric
12601095a5dSDimitry Andric static cl::opt<bool> EnableImportMetadata(
127b60736ecSDimitry Andric "enable-import-metadata", cl::init(false), cl::Hidden,
128ac9a064cSDimitry Andric cl::desc("Enable import metadata like 'thinlto_src_module' and "
129ac9a064cSDimitry Andric "'thinlto_src_file'"));
13001095a5dSDimitry Andric
131044eb2f6SDimitry Andric /// Summary file to use for function importing when using -function-import from
132044eb2f6SDimitry Andric /// the command line.
133044eb2f6SDimitry Andric static cl::opt<std::string>
134044eb2f6SDimitry Andric SummaryFile("summary-file",
135044eb2f6SDimitry Andric cl::desc("The summary file to use for function importing."));
136044eb2f6SDimitry Andric
137044eb2f6SDimitry Andric /// Used when testing importing from distributed indexes via opt
138044eb2f6SDimitry Andric // -function-import.
139044eb2f6SDimitry Andric static cl::opt<bool>
140044eb2f6SDimitry Andric ImportAllIndex("import-all-index",
141044eb2f6SDimitry Andric cl::desc("Import all external functions in index."));
142044eb2f6SDimitry Andric
143ac9a064cSDimitry Andric /// This is a test-only option.
144ac9a064cSDimitry Andric /// If this option is enabled, the ThinLTO indexing step will import each
145ac9a064cSDimitry Andric /// function declaration as a fallback. In a real build this may increase ram
146ac9a064cSDimitry Andric /// usage of the indexing step unnecessarily.
147ac9a064cSDimitry Andric /// TODO: Implement selective import (based on combined summary analysis) to
148ac9a064cSDimitry Andric /// ensure the imported function has a use case in the postlink pipeline.
149ac9a064cSDimitry Andric static cl::opt<bool> ImportDeclaration(
150ac9a064cSDimitry Andric "import-declaration", cl::init(false), cl::Hidden,
151ac9a064cSDimitry Andric cl::desc("If true, import function declaration as fallback if the function "
152ac9a064cSDimitry Andric "definition is not imported."));
153ac9a064cSDimitry Andric
154312c0ed1SDimitry Andric /// Pass a workload description file - an example of workload would be the
155312c0ed1SDimitry Andric /// functions executed to satisfy a RPC request. A workload is defined by a root
156312c0ed1SDimitry Andric /// function and the list of functions that are (frequently) needed to satisfy
157312c0ed1SDimitry Andric /// it. The module that defines the root will have all those functions imported.
158312c0ed1SDimitry Andric /// The file contains a JSON dictionary. The keys are root functions, the values
159312c0ed1SDimitry Andric /// are lists of functions to import in the module defining the root. It is
160312c0ed1SDimitry Andric /// assumed -funique-internal-linkage-names was used, thus ensuring function
161312c0ed1SDimitry Andric /// names are unique even for local linkage ones.
162312c0ed1SDimitry Andric static cl::opt<std::string> WorkloadDefinitions(
163312c0ed1SDimitry Andric "thinlto-workload-def",
164312c0ed1SDimitry Andric cl::desc("Pass a workload definition. This is a file containing a JSON "
165312c0ed1SDimitry Andric "dictionary. The keys are root functions, the values are lists of "
166312c0ed1SDimitry Andric "functions to import in the module defining the root. It is "
167312c0ed1SDimitry Andric "assumed -funique-internal-linkage-names was used, to ensure "
168312c0ed1SDimitry Andric "local linkage functions have unique names. For example: \n"
169312c0ed1SDimitry Andric "{\n"
170312c0ed1SDimitry Andric " \"rootFunction_1\": [\"function_to_import_1\", "
171312c0ed1SDimitry Andric "\"function_to_import_2\"], \n"
172312c0ed1SDimitry Andric " \"rootFunction_2\": [\"function_to_import_3\", "
173312c0ed1SDimitry Andric "\"function_to_import_4\"] \n"
174312c0ed1SDimitry Andric "}"),
175312c0ed1SDimitry Andric cl::Hidden);
176312c0ed1SDimitry Andric
177ac9a064cSDimitry Andric namespace llvm {
178ac9a064cSDimitry Andric extern cl::opt<bool> EnableMemProfContextDisambiguation;
179ac9a064cSDimitry Andric }
180ac9a064cSDimitry Andric
181dd58ef01SDimitry Andric // Load lazily a module from \p FileName in \p Context.
loadFile(const std::string & FileName,LLVMContext & Context)182dd58ef01SDimitry Andric static std::unique_ptr<Module> loadFile(const std::string &FileName,
183dd58ef01SDimitry Andric LLVMContext &Context) {
184dd58ef01SDimitry Andric SMDiagnostic Err;
185eb11fae6SDimitry Andric LLVM_DEBUG(dbgs() << "Loading '" << FileName << "'\n");
18601095a5dSDimitry Andric // Metadata isn't loaded until functions are imported, to minimize
18701095a5dSDimitry Andric // the memory overhead.
188050e163aSDimitry Andric std::unique_ptr<Module> Result =
189050e163aSDimitry Andric getLazyIRFileModule(FileName, Err, Context,
190050e163aSDimitry Andric /* ShouldLazyLoadMetadata = */ true);
191dd58ef01SDimitry Andric if (!Result) {
192dd58ef01SDimitry Andric Err.print("function-import", errs());
19301095a5dSDimitry Andric report_fatal_error("Abort");
194dd58ef01SDimitry Andric }
195dd58ef01SDimitry Andric
196dd58ef01SDimitry Andric return Result;
197dd58ef01SDimitry Andric }
198dd58ef01SDimitry Andric
1997fa27ce4SDimitry Andric /// Given a list of possible callee implementation for a call site, qualify the
2007fa27ce4SDimitry Andric /// legality of importing each. The return is a range of pairs. Each pair
2017fa27ce4SDimitry Andric /// corresponds to a candidate. The first value is the ImportFailureReason for
2027fa27ce4SDimitry Andric /// that candidate, the second is the candidate.
qualifyCalleeCandidates(const ModuleSummaryIndex & Index,ArrayRef<std::unique_ptr<GlobalValueSummary>> CalleeSummaryList,StringRef CallerModulePath)2037fa27ce4SDimitry Andric static auto qualifyCalleeCandidates(
2047fa27ce4SDimitry Andric const ModuleSummaryIndex &Index,
205c46e6a59SDimitry Andric ArrayRef<std::unique_ptr<GlobalValueSummary>> CalleeSummaryList,
2067fa27ce4SDimitry Andric StringRef CallerModulePath) {
2077fa27ce4SDimitry Andric return llvm::map_range(
20801095a5dSDimitry Andric CalleeSummaryList,
2097fa27ce4SDimitry Andric [&Index, CalleeSummaryList,
2107fa27ce4SDimitry Andric CallerModulePath](const std::unique_ptr<GlobalValueSummary> &SummaryPtr)
2117fa27ce4SDimitry Andric -> std::pair<FunctionImporter::ImportFailureReason,
2127fa27ce4SDimitry Andric const GlobalValueSummary *> {
21301095a5dSDimitry Andric auto *GVSummary = SummaryPtr.get();
2147fa27ce4SDimitry Andric if (!Index.isGlobalValueLive(GVSummary))
2157fa27ce4SDimitry Andric return {FunctionImporter::ImportFailureReason::NotLive, GVSummary};
216eb11fae6SDimitry Andric
2177fa27ce4SDimitry Andric if (GlobalValue::isInterposableLinkage(GVSummary->linkage()))
2187fa27ce4SDimitry Andric return {FunctionImporter::ImportFailureReason::InterposableLinkage,
2197fa27ce4SDimitry Andric GVSummary};
22001095a5dSDimitry Andric
2217fa27ce4SDimitry Andric auto *Summary = dyn_cast<FunctionSummary>(GVSummary->getBaseObject());
2227fa27ce4SDimitry Andric
2237fa27ce4SDimitry Andric // Ignore any callees that aren't actually functions. This could happen
2247fa27ce4SDimitry Andric // in the case of GUID hash collisions. It could also happen in theory
2257fa27ce4SDimitry Andric // for SamplePGO profiles collected on old versions of the code after
2267fa27ce4SDimitry Andric // renaming, since we synthesize edges to any inlined callees appearing
2277fa27ce4SDimitry Andric // in the profile.
2287fa27ce4SDimitry Andric if (!Summary)
2297fa27ce4SDimitry Andric return {FunctionImporter::ImportFailureReason::GlobalVar, GVSummary};
23001095a5dSDimitry Andric
23171d5a254SDimitry Andric // If this is a local function, make sure we import the copy
23271d5a254SDimitry Andric // in the caller's module. The only time a local function can
23371d5a254SDimitry Andric // share an entry in the index is if there is a local with the same name
23471d5a254SDimitry Andric // in another module that had the same source file name (in a different
23571d5a254SDimitry Andric // directory), where each was compiled in their own directory so there
23671d5a254SDimitry Andric // was not distinguishing path.
23771d5a254SDimitry Andric // However, do the import from another module if there is only one
23871d5a254SDimitry Andric // entry in the list - in that case this must be a reference due
23971d5a254SDimitry Andric // to indirect call profile data, since a function pointer can point to
24071d5a254SDimitry Andric // a local in another module.
24171d5a254SDimitry Andric if (GlobalValue::isLocalLinkage(Summary->linkage()) &&
24271d5a254SDimitry Andric CalleeSummaryList.size() > 1 &&
2437fa27ce4SDimitry Andric Summary->modulePath() != CallerModulePath)
2447fa27ce4SDimitry Andric return {
2457fa27ce4SDimitry Andric FunctionImporter::ImportFailureReason::LocalLinkageNotInModule,
2467fa27ce4SDimitry Andric GVSummary};
24701095a5dSDimitry Andric
248d8e91e46SDimitry Andric // Skip if it isn't legal to import (e.g. may reference unpromotable
249d8e91e46SDimitry Andric // locals).
2507fa27ce4SDimitry Andric if (Summary->notEligibleToImport())
2517fa27ce4SDimitry Andric return {FunctionImporter::ImportFailureReason::NotEligible,
2527fa27ce4SDimitry Andric GVSummary};
2537fa27ce4SDimitry Andric
2547fa27ce4SDimitry Andric return {FunctionImporter::ImportFailureReason::None, GVSummary};
2557fa27ce4SDimitry Andric });
2567fa27ce4SDimitry Andric }
2577fa27ce4SDimitry Andric
2587fa27ce4SDimitry Andric /// Given a list of possible callee implementation for a call site, select one
259ac9a064cSDimitry Andric /// that fits the \p Threshold for function definition import. If none are
260ac9a064cSDimitry Andric /// found, the Reason will give the last reason for the failure (last, in the
261ac9a064cSDimitry Andric /// order of CalleeSummaryList entries). While looking for a callee definition,
262ac9a064cSDimitry Andric /// sets \p TooLargeOrNoInlineSummary to the last seen too-large or noinline
263ac9a064cSDimitry Andric /// candidate; other modules may want to know the function summary or
264ac9a064cSDimitry Andric /// declaration even if a definition is not needed.
2657fa27ce4SDimitry Andric ///
2667fa27ce4SDimitry Andric /// FIXME: select "best" instead of first that fits. But what is "best"?
2677fa27ce4SDimitry Andric /// - The smallest: more likely to be inlined.
2687fa27ce4SDimitry Andric /// - The one with the least outgoing edges (already well optimized).
2697fa27ce4SDimitry Andric /// - One from a module already being imported from in order to reduce the
2707fa27ce4SDimitry Andric /// number of source modules parsed/linked.
2717fa27ce4SDimitry Andric /// - One that has PGO data attached.
2727fa27ce4SDimitry Andric /// - [insert you fancy metric here]
2737fa27ce4SDimitry Andric static const GlobalValueSummary *
selectCallee(const ModuleSummaryIndex & Index,ArrayRef<std::unique_ptr<GlobalValueSummary>> CalleeSummaryList,unsigned Threshold,StringRef CallerModulePath,const GlobalValueSummary * & TooLargeOrNoInlineSummary,FunctionImporter::ImportFailureReason & Reason)2747fa27ce4SDimitry Andric selectCallee(const ModuleSummaryIndex &Index,
2757fa27ce4SDimitry Andric ArrayRef<std::unique_ptr<GlobalValueSummary>> CalleeSummaryList,
2767fa27ce4SDimitry Andric unsigned Threshold, StringRef CallerModulePath,
277ac9a064cSDimitry Andric const GlobalValueSummary *&TooLargeOrNoInlineSummary,
2787fa27ce4SDimitry Andric FunctionImporter::ImportFailureReason &Reason) {
279ac9a064cSDimitry Andric // Records the last summary with reason noinline or too-large.
280ac9a064cSDimitry Andric TooLargeOrNoInlineSummary = nullptr;
2817fa27ce4SDimitry Andric auto QualifiedCandidates =
2827fa27ce4SDimitry Andric qualifyCalleeCandidates(Index, CalleeSummaryList, CallerModulePath);
2837fa27ce4SDimitry Andric for (auto QualifiedValue : QualifiedCandidates) {
2847fa27ce4SDimitry Andric Reason = QualifiedValue.first;
285ac9a064cSDimitry Andric // Skip a summary if its import is not (proved to be) legal.
2867fa27ce4SDimitry Andric if (Reason != FunctionImporter::ImportFailureReason::None)
2877fa27ce4SDimitry Andric continue;
2887fa27ce4SDimitry Andric auto *Summary =
2897fa27ce4SDimitry Andric cast<FunctionSummary>(QualifiedValue.second->getBaseObject());
2907fa27ce4SDimitry Andric
291ac9a064cSDimitry Andric // Don't bother importing the definition if the chance of inlining it is
292ac9a064cSDimitry Andric // not high enough (except under `--force-import-all`).
2937fa27ce4SDimitry Andric if ((Summary->instCount() > Threshold) && !Summary->fflags().AlwaysInline &&
2947fa27ce4SDimitry Andric !ForceImportAll) {
295ac9a064cSDimitry Andric TooLargeOrNoInlineSummary = Summary;
2967fa27ce4SDimitry Andric Reason = FunctionImporter::ImportFailureReason::TooLarge;
2977fa27ce4SDimitry Andric continue;
298d8e91e46SDimitry Andric }
299d8e91e46SDimitry Andric
300ac9a064cSDimitry Andric // Don't bother importing the definition if we can't inline it anyway.
301344a3780SDimitry Andric if (Summary->fflags().NoInline && !ForceImportAll) {
302ac9a064cSDimitry Andric TooLargeOrNoInlineSummary = Summary;
303d8e91e46SDimitry Andric Reason = FunctionImporter::ImportFailureReason::NoInline;
3047fa27ce4SDimitry Andric continue;
305d8e91e46SDimitry Andric }
30601095a5dSDimitry Andric
3077fa27ce4SDimitry Andric return Summary;
3087fa27ce4SDimitry Andric }
30901095a5dSDimitry Andric return nullptr;
31001095a5dSDimitry Andric }
31101095a5dSDimitry Andric
312044eb2f6SDimitry Andric namespace {
313044eb2f6SDimitry Andric
3147fa27ce4SDimitry Andric using EdgeInfo = std::tuple<const FunctionSummary *, unsigned /* Threshold */>;
31501095a5dSDimitry Andric
316044eb2f6SDimitry Andric } // anonymous namespace
317044eb2f6SDimitry Andric
3187fa27ce4SDimitry Andric /// Import globals referenced by a function or other globals that are being
3197fa27ce4SDimitry Andric /// imported, if importing such global is possible.
3207fa27ce4SDimitry Andric class GlobalsImporter final {
3217fa27ce4SDimitry Andric const ModuleSummaryIndex &Index;
3227fa27ce4SDimitry Andric const GVSummaryMapTy &DefinedGVSummaries;
3237fa27ce4SDimitry Andric function_ref<bool(GlobalValue::GUID, const GlobalValueSummary *)>
3247fa27ce4SDimitry Andric IsPrevailing;
3257fa27ce4SDimitry Andric FunctionImporter::ImportMapTy &ImportList;
326b1c73532SDimitry Andric DenseMap<StringRef, FunctionImporter::ExportSetTy> *const ExportLists;
3277fa27ce4SDimitry Andric
shouldImportGlobal(const ValueInfo & VI)3287fa27ce4SDimitry Andric bool shouldImportGlobal(const ValueInfo &VI) {
329344a3780SDimitry Andric const auto &GVS = DefinedGVSummaries.find(VI.getGUID());
330344a3780SDimitry Andric if (GVS == DefinedGVSummaries.end())
331344a3780SDimitry Andric return true;
3327fa27ce4SDimitry Andric // We should not skip import if the module contains a non-prevailing
3337fa27ce4SDimitry Andric // definition with interposable linkage type. This is required for
3347fa27ce4SDimitry Andric // correctness in the situation where there is a prevailing def available
3357fa27ce4SDimitry Andric // for import and marked read-only. In this case, the non-prevailing def
3367fa27ce4SDimitry Andric // will be converted to a declaration, while the prevailing one becomes
3377fa27ce4SDimitry Andric // internal, thus no definitions will be available for linking. In order to
3387fa27ce4SDimitry Andric // prevent undefined symbol link error, the prevailing definition must be
3397fa27ce4SDimitry Andric // imported.
340344a3780SDimitry Andric // FIXME: Consider adding a check that the suitable prevailing definition
341344a3780SDimitry Andric // exists and marked read-only.
342344a3780SDimitry Andric if (VI.getSummaryList().size() > 1 &&
3437fa27ce4SDimitry Andric GlobalValue::isInterposableLinkage(GVS->second->linkage()) &&
3447fa27ce4SDimitry Andric !IsPrevailing(VI.getGUID(), GVS->second))
345344a3780SDimitry Andric return true;
346344a3780SDimitry Andric
347344a3780SDimitry Andric return false;
348344a3780SDimitry Andric }
349344a3780SDimitry Andric
3507fa27ce4SDimitry Andric void
onImportingSummaryImpl(const GlobalValueSummary & Summary,SmallVectorImpl<const GlobalVarSummary * > & Worklist)3517fa27ce4SDimitry Andric onImportingSummaryImpl(const GlobalValueSummary &Summary,
3527fa27ce4SDimitry Andric SmallVectorImpl<const GlobalVarSummary *> &Worklist) {
353e3b55780SDimitry Andric for (const auto &VI : Summary.refs()) {
3547fa27ce4SDimitry Andric if (!shouldImportGlobal(VI)) {
355eb11fae6SDimitry Andric LLVM_DEBUG(
356eb11fae6SDimitry Andric dbgs() << "Ref ignored! Target already in destination module.\n");
357eb11fae6SDimitry Andric continue;
358eb11fae6SDimitry Andric }
359eb11fae6SDimitry Andric
360eb11fae6SDimitry Andric LLVM_DEBUG(dbgs() << " ref -> " << VI << "\n");
361eb11fae6SDimitry Andric
362d8e91e46SDimitry Andric // If this is a local variable, make sure we import the copy
363d8e91e46SDimitry Andric // in the caller's module. The only time a local variable can
364d8e91e46SDimitry Andric // share an entry in the index is if there is a local with the same name
365d8e91e46SDimitry Andric // in another module that had the same source file name (in a different
366d8e91e46SDimitry Andric // directory), where each was compiled in their own directory so there
367d8e91e46SDimitry Andric // was not distinguishing path.
3687fa27ce4SDimitry Andric auto LocalNotInModule =
3697fa27ce4SDimitry Andric [&](const GlobalValueSummary *RefSummary) -> bool {
370d8e91e46SDimitry Andric return GlobalValue::isLocalLinkage(RefSummary->linkage()) &&
371d8e91e46SDimitry Andric RefSummary->modulePath() != Summary.modulePath();
372d8e91e46SDimitry Andric };
373d8e91e46SDimitry Andric
3747fa27ce4SDimitry Andric for (const auto &RefSummary : VI.getSummaryList()) {
3757fa27ce4SDimitry Andric const auto *GVS = dyn_cast<GlobalVarSummary>(RefSummary.get());
3767fa27ce4SDimitry Andric // Functions could be referenced by global vars - e.g. a vtable; but we
3777fa27ce4SDimitry Andric // don't currently imagine a reason those would be imported here, rather
3787fa27ce4SDimitry Andric // than as part of the logic deciding which functions to import (i.e.
3797fa27ce4SDimitry Andric // based on profile information). Should we decide to handle them here,
3807fa27ce4SDimitry Andric // we can refactor accordingly at that time.
3817fa27ce4SDimitry Andric if (!GVS || !Index.canImportGlobalVar(GVS, /* AnalyzeRefs */ true) ||
3827fa27ce4SDimitry Andric LocalNotInModule(GVS))
3837fa27ce4SDimitry Andric continue;
384ac9a064cSDimitry Andric
385ac9a064cSDimitry Andric // If there isn't an entry for GUID, insert <GUID, Definition> pair.
386ac9a064cSDimitry Andric // Otherwise, definition should take precedence over declaration.
387ac9a064cSDimitry Andric auto [Iter, Inserted] =
388ac9a064cSDimitry Andric ImportList[RefSummary->modulePath()].try_emplace(
389ac9a064cSDimitry Andric VI.getGUID(), GlobalValueSummary::Definition);
390cfca06d7SDimitry Andric // Only update stat and exports if we haven't already imported this
391cfca06d7SDimitry Andric // variable.
392ac9a064cSDimitry Andric if (!Inserted) {
393ac9a064cSDimitry Andric // Set the value to 'std::min(existing-value, new-value)' to make
394ac9a064cSDimitry Andric // sure a definition takes precedence over a declaration.
395ac9a064cSDimitry Andric Iter->second = std::min(GlobalValueSummary::Definition, Iter->second);
396cfca06d7SDimitry Andric break;
397ac9a064cSDimitry Andric }
398d8e91e46SDimitry Andric NumImportedGlobalVarsThinLink++;
3997fa27ce4SDimitry Andric // Any references made by this variable will be marked exported
4007fa27ce4SDimitry Andric // later, in ComputeCrossModuleImport, after import decisions are
4017fa27ce4SDimitry Andric // complete, which is more efficient than adding them here.
402cfca06d7SDimitry Andric if (ExportLists)
403cfca06d7SDimitry Andric (*ExportLists)[RefSummary->modulePath()].insert(VI);
404b60736ecSDimitry Andric
405b60736ecSDimitry Andric // If variable is not writeonly we attempt to recursively analyze
406b60736ecSDimitry Andric // its references in order to import referenced constants.
4077fa27ce4SDimitry Andric if (!Index.isWriteOnly(GVS))
4087fa27ce4SDimitry Andric Worklist.emplace_back(GVS);
409eb11fae6SDimitry Andric break;
410eb11fae6SDimitry Andric }
411eb11fae6SDimitry Andric }
412eb11fae6SDimitry Andric }
413eb11fae6SDimitry Andric
4147fa27ce4SDimitry Andric public:
GlobalsImporter(const ModuleSummaryIndex & Index,const GVSummaryMapTy & DefinedGVSummaries,function_ref<bool (GlobalValue::GUID,const GlobalValueSummary *)> IsPrevailing,FunctionImporter::ImportMapTy & ImportList,DenseMap<StringRef,FunctionImporter::ExportSetTy> * ExportLists)4157fa27ce4SDimitry Andric GlobalsImporter(
4167fa27ce4SDimitry Andric const ModuleSummaryIndex &Index, const GVSummaryMapTy &DefinedGVSummaries,
4177fa27ce4SDimitry Andric function_ref<bool(GlobalValue::GUID, const GlobalValueSummary *)>
4187fa27ce4SDimitry Andric IsPrevailing,
4197fa27ce4SDimitry Andric FunctionImporter::ImportMapTy &ImportList,
420b1c73532SDimitry Andric DenseMap<StringRef, FunctionImporter::ExportSetTy> *ExportLists)
4217fa27ce4SDimitry Andric : Index(Index), DefinedGVSummaries(DefinedGVSummaries),
4227fa27ce4SDimitry Andric IsPrevailing(IsPrevailing), ImportList(ImportList),
4237fa27ce4SDimitry Andric ExportLists(ExportLists) {}
4247fa27ce4SDimitry Andric
onImportingSummary(const GlobalValueSummary & Summary)4257fa27ce4SDimitry Andric void onImportingSummary(const GlobalValueSummary &Summary) {
4267fa27ce4SDimitry Andric SmallVector<const GlobalVarSummary *, 128> Worklist;
4277fa27ce4SDimitry Andric onImportingSummaryImpl(Summary, Worklist);
4287fa27ce4SDimitry Andric while (!Worklist.empty())
4297fa27ce4SDimitry Andric onImportingSummaryImpl(*Worklist.pop_back_val(), Worklist);
4307fa27ce4SDimitry Andric }
4317fa27ce4SDimitry Andric };
4327fa27ce4SDimitry Andric
433312c0ed1SDimitry Andric static const char *getFailureName(FunctionImporter::ImportFailureReason Reason);
434312c0ed1SDimitry Andric
435b1c73532SDimitry Andric /// Determine the list of imports and exports for each module.
436312c0ed1SDimitry Andric class ModuleImportsManager {
437312c0ed1SDimitry Andric protected:
438b1c73532SDimitry Andric function_ref<bool(GlobalValue::GUID, const GlobalValueSummary *)>
439b1c73532SDimitry Andric IsPrevailing;
440b1c73532SDimitry Andric const ModuleSummaryIndex &Index;
441b1c73532SDimitry Andric DenseMap<StringRef, FunctionImporter::ExportSetTy> *const ExportLists;
442b1c73532SDimitry Andric
ModuleImportsManager(function_ref<bool (GlobalValue::GUID,const GlobalValueSummary *)> IsPrevailing,const ModuleSummaryIndex & Index,DenseMap<StringRef,FunctionImporter::ExportSetTy> * ExportLists=nullptr)443b1c73532SDimitry Andric ModuleImportsManager(
444b1c73532SDimitry Andric function_ref<bool(GlobalValue::GUID, const GlobalValueSummary *)>
445b1c73532SDimitry Andric IsPrevailing,
446b1c73532SDimitry Andric const ModuleSummaryIndex &Index,
447b1c73532SDimitry Andric DenseMap<StringRef, FunctionImporter::ExportSetTy> *ExportLists = nullptr)
448b1c73532SDimitry Andric : IsPrevailing(IsPrevailing), Index(Index), ExportLists(ExportLists) {}
449b1c73532SDimitry Andric
450312c0ed1SDimitry Andric public:
451312c0ed1SDimitry Andric virtual ~ModuleImportsManager() = default;
452312c0ed1SDimitry Andric
453b1c73532SDimitry Andric /// Given the list of globals defined in a module, compute the list of imports
454b1c73532SDimitry Andric /// as well as the list of "exports", i.e. the list of symbols referenced from
455b1c73532SDimitry Andric /// another module (that may require promotion).
456312c0ed1SDimitry Andric virtual void
457312c0ed1SDimitry Andric computeImportForModule(const GVSummaryMapTy &DefinedGVSummaries,
458b1c73532SDimitry Andric StringRef ModName,
459b1c73532SDimitry Andric FunctionImporter::ImportMapTy &ImportList);
460312c0ed1SDimitry Andric
461312c0ed1SDimitry Andric static std::unique_ptr<ModuleImportsManager>
462312c0ed1SDimitry Andric create(function_ref<bool(GlobalValue::GUID, const GlobalValueSummary *)>
463312c0ed1SDimitry Andric IsPrevailing,
464312c0ed1SDimitry Andric const ModuleSummaryIndex &Index,
465312c0ed1SDimitry Andric DenseMap<StringRef, FunctionImporter::ExportSetTy> *ExportLists =
466312c0ed1SDimitry Andric nullptr);
467b1c73532SDimitry Andric };
468b1c73532SDimitry Andric
469312c0ed1SDimitry Andric /// A ModuleImportsManager that operates based on a workload definition (see
470312c0ed1SDimitry Andric /// -thinlto-workload-def). For modules that do not define workload roots, it
471312c0ed1SDimitry Andric /// applies the base ModuleImportsManager import policy.
472312c0ed1SDimitry Andric class WorkloadImportsManager : public ModuleImportsManager {
473312c0ed1SDimitry Andric // Keep a module name -> value infos to import association. We use it to
474312c0ed1SDimitry Andric // determine if a module's import list should be done by the base
475312c0ed1SDimitry Andric // ModuleImportsManager or by us.
476312c0ed1SDimitry Andric StringMap<DenseSet<ValueInfo>> Workloads;
477312c0ed1SDimitry Andric
478312c0ed1SDimitry Andric void
computeImportForModule(const GVSummaryMapTy & DefinedGVSummaries,StringRef ModName,FunctionImporter::ImportMapTy & ImportList)479312c0ed1SDimitry Andric computeImportForModule(const GVSummaryMapTy &DefinedGVSummaries,
480312c0ed1SDimitry Andric StringRef ModName,
481312c0ed1SDimitry Andric FunctionImporter::ImportMapTy &ImportList) override {
482312c0ed1SDimitry Andric auto SetIter = Workloads.find(ModName);
483312c0ed1SDimitry Andric if (SetIter == Workloads.end()) {
484312c0ed1SDimitry Andric LLVM_DEBUG(dbgs() << "[Workload] " << ModName
485312c0ed1SDimitry Andric << " does not contain the root of any context.\n");
486312c0ed1SDimitry Andric return ModuleImportsManager::computeImportForModule(DefinedGVSummaries,
487312c0ed1SDimitry Andric ModName, ImportList);
488312c0ed1SDimitry Andric }
489312c0ed1SDimitry Andric LLVM_DEBUG(dbgs() << "[Workload] " << ModName
490312c0ed1SDimitry Andric << " contains the root(s) of context(s).\n");
491312c0ed1SDimitry Andric
492312c0ed1SDimitry Andric GlobalsImporter GVI(Index, DefinedGVSummaries, IsPrevailing, ImportList,
493312c0ed1SDimitry Andric ExportLists);
494312c0ed1SDimitry Andric auto &ValueInfos = SetIter->second;
495312c0ed1SDimitry Andric SmallVector<EdgeInfo, 128> GlobWorklist;
496312c0ed1SDimitry Andric for (auto &VI : llvm::make_early_inc_range(ValueInfos)) {
497312c0ed1SDimitry Andric auto It = DefinedGVSummaries.find(VI.getGUID());
498312c0ed1SDimitry Andric if (It != DefinedGVSummaries.end() &&
499312c0ed1SDimitry Andric IsPrevailing(VI.getGUID(), It->second)) {
500312c0ed1SDimitry Andric LLVM_DEBUG(
501312c0ed1SDimitry Andric dbgs() << "[Workload] " << VI.name()
502312c0ed1SDimitry Andric << " has the prevailing variant already in the module "
503312c0ed1SDimitry Andric << ModName << ". No need to import\n");
504312c0ed1SDimitry Andric continue;
505312c0ed1SDimitry Andric }
506312c0ed1SDimitry Andric auto Candidates =
507312c0ed1SDimitry Andric qualifyCalleeCandidates(Index, VI.getSummaryList(), ModName);
508312c0ed1SDimitry Andric
509312c0ed1SDimitry Andric const GlobalValueSummary *GVS = nullptr;
510312c0ed1SDimitry Andric auto PotentialCandidates = llvm::map_range(
511312c0ed1SDimitry Andric llvm::make_filter_range(
512312c0ed1SDimitry Andric Candidates,
513312c0ed1SDimitry Andric [&](const auto &Candidate) {
514312c0ed1SDimitry Andric LLVM_DEBUG(dbgs() << "[Workflow] Candidate for " << VI.name()
515312c0ed1SDimitry Andric << " from " << Candidate.second->modulePath()
516312c0ed1SDimitry Andric << " ImportFailureReason: "
517312c0ed1SDimitry Andric << getFailureName(Candidate.first) << "\n");
518312c0ed1SDimitry Andric return Candidate.first ==
519312c0ed1SDimitry Andric FunctionImporter::ImportFailureReason::None;
520312c0ed1SDimitry Andric }),
521312c0ed1SDimitry Andric [](const auto &Candidate) { return Candidate.second; });
522312c0ed1SDimitry Andric if (PotentialCandidates.empty()) {
523312c0ed1SDimitry Andric LLVM_DEBUG(dbgs() << "[Workload] Not importing " << VI.name()
524312c0ed1SDimitry Andric << " because can't find eligible Callee. Guid is: "
525312c0ed1SDimitry Andric << Function::getGUID(VI.name()) << "\n");
526312c0ed1SDimitry Andric continue;
527312c0ed1SDimitry Andric }
528312c0ed1SDimitry Andric /// We will prefer importing the prevailing candidate, if not, we'll
529312c0ed1SDimitry Andric /// still pick the first available candidate. The reason we want to make
530312c0ed1SDimitry Andric /// sure we do import the prevailing candidate is because the goal of
531312c0ed1SDimitry Andric /// workload-awareness is to enable optimizations specializing the call
532312c0ed1SDimitry Andric /// graph of that workload. Suppose a function is already defined in the
533312c0ed1SDimitry Andric /// module, but it's not the prevailing variant. Suppose also we do not
534312c0ed1SDimitry Andric /// inline it (in fact, if it were interposable, we can't inline it),
535312c0ed1SDimitry Andric /// but we could specialize it to the workload in other ways. However,
536312c0ed1SDimitry Andric /// the linker would drop it in the favor of the prevailing copy.
537312c0ed1SDimitry Andric /// Instead, by importing the prevailing variant (assuming also the use
538312c0ed1SDimitry Andric /// of `-avail-extern-to-local`), we keep the specialization. We could
539312c0ed1SDimitry Andric /// alteranatively make the non-prevailing variant local, but the
540312c0ed1SDimitry Andric /// prevailing one is also the one for which we would have previously
541312c0ed1SDimitry Andric /// collected profiles, making it preferrable.
542312c0ed1SDimitry Andric auto PrevailingCandidates = llvm::make_filter_range(
543312c0ed1SDimitry Andric PotentialCandidates, [&](const auto *Candidate) {
544312c0ed1SDimitry Andric return IsPrevailing(VI.getGUID(), Candidate);
545312c0ed1SDimitry Andric });
546312c0ed1SDimitry Andric if (PrevailingCandidates.empty()) {
547312c0ed1SDimitry Andric GVS = *PotentialCandidates.begin();
548312c0ed1SDimitry Andric if (!llvm::hasSingleElement(PotentialCandidates) &&
549312c0ed1SDimitry Andric GlobalValue::isLocalLinkage(GVS->linkage()))
550312c0ed1SDimitry Andric LLVM_DEBUG(
551312c0ed1SDimitry Andric dbgs()
552312c0ed1SDimitry Andric << "[Workload] Found multiple non-prevailing candidates for "
553312c0ed1SDimitry Andric << VI.name()
554312c0ed1SDimitry Andric << ". This is unexpected. Are module paths passed to the "
555312c0ed1SDimitry Andric "compiler unique for the modules passed to the linker?");
556312c0ed1SDimitry Andric // We could in theory have multiple (interposable) copies of a symbol
557312c0ed1SDimitry Andric // when there is no prevailing candidate, if say the prevailing copy was
558312c0ed1SDimitry Andric // in a native object being linked in. However, we should in theory be
559312c0ed1SDimitry Andric // marking all of these non-prevailing IR copies dead in that case, in
560312c0ed1SDimitry Andric // which case they won't be candidates.
561312c0ed1SDimitry Andric assert(GVS->isLive());
562312c0ed1SDimitry Andric } else {
563312c0ed1SDimitry Andric assert(llvm::hasSingleElement(PrevailingCandidates));
564312c0ed1SDimitry Andric GVS = *PrevailingCandidates.begin();
565312c0ed1SDimitry Andric }
566312c0ed1SDimitry Andric
567312c0ed1SDimitry Andric auto ExportingModule = GVS->modulePath();
568312c0ed1SDimitry Andric // We checked that for the prevailing case, but if we happen to have for
569312c0ed1SDimitry Andric // example an internal that's defined in this module, it'd have no
570312c0ed1SDimitry Andric // PrevailingCandidates.
571312c0ed1SDimitry Andric if (ExportingModule == ModName) {
572312c0ed1SDimitry Andric LLVM_DEBUG(dbgs() << "[Workload] Not importing " << VI.name()
573312c0ed1SDimitry Andric << " because its defining module is the same as the "
574312c0ed1SDimitry Andric "current module\n");
575312c0ed1SDimitry Andric continue;
576312c0ed1SDimitry Andric }
577312c0ed1SDimitry Andric LLVM_DEBUG(dbgs() << "[Workload][Including]" << VI.name() << " from "
578312c0ed1SDimitry Andric << ExportingModule << " : "
579312c0ed1SDimitry Andric << Function::getGUID(VI.name()) << "\n");
580ac9a064cSDimitry Andric ImportList[ExportingModule][VI.getGUID()] =
581ac9a064cSDimitry Andric GlobalValueSummary::Definition;
582312c0ed1SDimitry Andric GVI.onImportingSummary(*GVS);
583312c0ed1SDimitry Andric if (ExportLists)
584312c0ed1SDimitry Andric (*ExportLists)[ExportingModule].insert(VI);
585312c0ed1SDimitry Andric }
586312c0ed1SDimitry Andric LLVM_DEBUG(dbgs() << "[Workload] Done\n");
587312c0ed1SDimitry Andric }
588312c0ed1SDimitry Andric
589312c0ed1SDimitry Andric public:
WorkloadImportsManager(function_ref<bool (GlobalValue::GUID,const GlobalValueSummary *)> IsPrevailing,const ModuleSummaryIndex & Index,DenseMap<StringRef,FunctionImporter::ExportSetTy> * ExportLists)590312c0ed1SDimitry Andric WorkloadImportsManager(
591312c0ed1SDimitry Andric function_ref<bool(GlobalValue::GUID, const GlobalValueSummary *)>
592312c0ed1SDimitry Andric IsPrevailing,
593312c0ed1SDimitry Andric const ModuleSummaryIndex &Index,
594312c0ed1SDimitry Andric DenseMap<StringRef, FunctionImporter::ExportSetTy> *ExportLists)
595312c0ed1SDimitry Andric : ModuleImportsManager(IsPrevailing, Index, ExportLists) {
596312c0ed1SDimitry Andric // Since the workload def uses names, we need a quick lookup
597312c0ed1SDimitry Andric // name->ValueInfo.
598312c0ed1SDimitry Andric StringMap<ValueInfo> NameToValueInfo;
599312c0ed1SDimitry Andric StringSet<> AmbiguousNames;
600312c0ed1SDimitry Andric for (auto &I : Index) {
601312c0ed1SDimitry Andric ValueInfo VI = Index.getValueInfo(I);
602312c0ed1SDimitry Andric if (!NameToValueInfo.insert(std::make_pair(VI.name(), VI)).second)
603312c0ed1SDimitry Andric LLVM_DEBUG(AmbiguousNames.insert(VI.name()));
604312c0ed1SDimitry Andric }
605312c0ed1SDimitry Andric auto DbgReportIfAmbiguous = [&](StringRef Name) {
606312c0ed1SDimitry Andric LLVM_DEBUG(if (AmbiguousNames.count(Name) > 0) {
607312c0ed1SDimitry Andric dbgs() << "[Workload] Function name " << Name
608312c0ed1SDimitry Andric << " present in the workload definition is ambiguous. Consider "
609312c0ed1SDimitry Andric "compiling with -funique-internal-linkage-names.";
610312c0ed1SDimitry Andric });
611312c0ed1SDimitry Andric };
612312c0ed1SDimitry Andric std::error_code EC;
613312c0ed1SDimitry Andric auto BufferOrErr = MemoryBuffer::getFileOrSTDIN(WorkloadDefinitions);
614312c0ed1SDimitry Andric if (std::error_code EC = BufferOrErr.getError()) {
615312c0ed1SDimitry Andric report_fatal_error("Failed to open context file");
616312c0ed1SDimitry Andric return;
617312c0ed1SDimitry Andric }
618312c0ed1SDimitry Andric auto Buffer = std::move(BufferOrErr.get());
619312c0ed1SDimitry Andric std::map<std::string, std::vector<std::string>> WorkloadDefs;
620312c0ed1SDimitry Andric json::Path::Root NullRoot;
621312c0ed1SDimitry Andric // The JSON is supposed to contain a dictionary matching the type of
622312c0ed1SDimitry Andric // WorkloadDefs. For example:
623312c0ed1SDimitry Andric // {
624312c0ed1SDimitry Andric // "rootFunction_1": ["function_to_import_1", "function_to_import_2"],
625312c0ed1SDimitry Andric // "rootFunction_2": ["function_to_import_3", "function_to_import_4"]
626312c0ed1SDimitry Andric // }
627312c0ed1SDimitry Andric auto Parsed = json::parse(Buffer->getBuffer());
628312c0ed1SDimitry Andric if (!Parsed)
629312c0ed1SDimitry Andric report_fatal_error(Parsed.takeError());
630312c0ed1SDimitry Andric if (!json::fromJSON(*Parsed, WorkloadDefs, NullRoot))
631312c0ed1SDimitry Andric report_fatal_error("Invalid thinlto contextual profile format.");
632312c0ed1SDimitry Andric for (const auto &Workload : WorkloadDefs) {
633312c0ed1SDimitry Andric const auto &Root = Workload.first;
634312c0ed1SDimitry Andric DbgReportIfAmbiguous(Root);
635312c0ed1SDimitry Andric LLVM_DEBUG(dbgs() << "[Workload] Root: " << Root << "\n");
636312c0ed1SDimitry Andric const auto &AllCallees = Workload.second;
637312c0ed1SDimitry Andric auto RootIt = NameToValueInfo.find(Root);
638312c0ed1SDimitry Andric if (RootIt == NameToValueInfo.end()) {
639312c0ed1SDimitry Andric LLVM_DEBUG(dbgs() << "[Workload] Root " << Root
640312c0ed1SDimitry Andric << " not found in this linkage unit.\n");
641312c0ed1SDimitry Andric continue;
642312c0ed1SDimitry Andric }
643312c0ed1SDimitry Andric auto RootVI = RootIt->second;
644312c0ed1SDimitry Andric if (RootVI.getSummaryList().size() != 1) {
645312c0ed1SDimitry Andric LLVM_DEBUG(dbgs() << "[Workload] Root " << Root
646312c0ed1SDimitry Andric << " should have exactly one summary, but has "
647312c0ed1SDimitry Andric << RootVI.getSummaryList().size() << ". Skipping.\n");
648312c0ed1SDimitry Andric continue;
649312c0ed1SDimitry Andric }
650312c0ed1SDimitry Andric StringRef RootDefiningModule =
651312c0ed1SDimitry Andric RootVI.getSummaryList().front()->modulePath();
652312c0ed1SDimitry Andric LLVM_DEBUG(dbgs() << "[Workload] Root defining module for " << Root
653312c0ed1SDimitry Andric << " is : " << RootDefiningModule << "\n");
654312c0ed1SDimitry Andric auto &Set = Workloads[RootDefiningModule];
655312c0ed1SDimitry Andric for (const auto &Callee : AllCallees) {
656312c0ed1SDimitry Andric LLVM_DEBUG(dbgs() << "[Workload] " << Callee << "\n");
657312c0ed1SDimitry Andric DbgReportIfAmbiguous(Callee);
658312c0ed1SDimitry Andric auto ElemIt = NameToValueInfo.find(Callee);
659312c0ed1SDimitry Andric if (ElemIt == NameToValueInfo.end()) {
660312c0ed1SDimitry Andric LLVM_DEBUG(dbgs() << "[Workload] " << Callee << " not found\n");
661312c0ed1SDimitry Andric continue;
662312c0ed1SDimitry Andric }
663312c0ed1SDimitry Andric Set.insert(ElemIt->second);
664312c0ed1SDimitry Andric }
665312c0ed1SDimitry Andric LLVM_DEBUG({
666312c0ed1SDimitry Andric dbgs() << "[Workload] Root: " << Root << " we have " << Set.size()
667312c0ed1SDimitry Andric << " distinct callees.\n";
668312c0ed1SDimitry Andric for (const auto &VI : Set) {
669312c0ed1SDimitry Andric dbgs() << "[Workload] Root: " << Root
670312c0ed1SDimitry Andric << " Would include: " << VI.getGUID() << "\n";
671312c0ed1SDimitry Andric }
672312c0ed1SDimitry Andric });
673312c0ed1SDimitry Andric }
674312c0ed1SDimitry Andric }
675312c0ed1SDimitry Andric };
676312c0ed1SDimitry Andric
create(function_ref<bool (GlobalValue::GUID,const GlobalValueSummary *)> IsPrevailing,const ModuleSummaryIndex & Index,DenseMap<StringRef,FunctionImporter::ExportSetTy> * ExportLists)677312c0ed1SDimitry Andric std::unique_ptr<ModuleImportsManager> ModuleImportsManager::create(
678312c0ed1SDimitry Andric function_ref<bool(GlobalValue::GUID, const GlobalValueSummary *)>
679312c0ed1SDimitry Andric IsPrevailing,
680312c0ed1SDimitry Andric const ModuleSummaryIndex &Index,
681312c0ed1SDimitry Andric DenseMap<StringRef, FunctionImporter::ExportSetTy> *ExportLists) {
682312c0ed1SDimitry Andric if (WorkloadDefinitions.empty()) {
683312c0ed1SDimitry Andric LLVM_DEBUG(dbgs() << "[Workload] Using the regular imports manager.\n");
684312c0ed1SDimitry Andric return std::unique_ptr<ModuleImportsManager>(
685312c0ed1SDimitry Andric new ModuleImportsManager(IsPrevailing, Index, ExportLists));
686312c0ed1SDimitry Andric }
687312c0ed1SDimitry Andric LLVM_DEBUG(dbgs() << "[Workload] Using the contextual imports manager.\n");
688312c0ed1SDimitry Andric return std::make_unique<WorkloadImportsManager>(IsPrevailing, Index,
689312c0ed1SDimitry Andric ExportLists);
690312c0ed1SDimitry Andric }
691312c0ed1SDimitry Andric
692d8e91e46SDimitry Andric static const char *
getFailureName(FunctionImporter::ImportFailureReason Reason)693d8e91e46SDimitry Andric getFailureName(FunctionImporter::ImportFailureReason Reason) {
694d8e91e46SDimitry Andric switch (Reason) {
695d8e91e46SDimitry Andric case FunctionImporter::ImportFailureReason::None:
696d8e91e46SDimitry Andric return "None";
697d8e91e46SDimitry Andric case FunctionImporter::ImportFailureReason::GlobalVar:
698d8e91e46SDimitry Andric return "GlobalVar";
699d8e91e46SDimitry Andric case FunctionImporter::ImportFailureReason::NotLive:
700d8e91e46SDimitry Andric return "NotLive";
701d8e91e46SDimitry Andric case FunctionImporter::ImportFailureReason::TooLarge:
702d8e91e46SDimitry Andric return "TooLarge";
703d8e91e46SDimitry Andric case FunctionImporter::ImportFailureReason::InterposableLinkage:
704d8e91e46SDimitry Andric return "InterposableLinkage";
705d8e91e46SDimitry Andric case FunctionImporter::ImportFailureReason::LocalLinkageNotInModule:
706d8e91e46SDimitry Andric return "LocalLinkageNotInModule";
707d8e91e46SDimitry Andric case FunctionImporter::ImportFailureReason::NotEligible:
708d8e91e46SDimitry Andric return "NotEligible";
709d8e91e46SDimitry Andric case FunctionImporter::ImportFailureReason::NoInline:
710d8e91e46SDimitry Andric return "NoInline";
711d8e91e46SDimitry Andric }
712d8e91e46SDimitry Andric llvm_unreachable("invalid reason");
713d8e91e46SDimitry Andric }
714d8e91e46SDimitry Andric
71501095a5dSDimitry Andric /// Compute the list of functions to import for a given caller. Mark these
71601095a5dSDimitry Andric /// imported functions and the symbols they reference in their source module as
71701095a5dSDimitry Andric /// exported from their source module.
computeImportForFunction(const FunctionSummary & Summary,const ModuleSummaryIndex & Index,const unsigned Threshold,const GVSummaryMapTy & DefinedGVSummaries,function_ref<bool (GlobalValue::GUID,const GlobalValueSummary *)> isPrevailing,SmallVectorImpl<EdgeInfo> & Worklist,GlobalsImporter & GVImporter,FunctionImporter::ImportMapTy & ImportList,DenseMap<StringRef,FunctionImporter::ExportSetTy> * ExportLists,FunctionImporter::ImportThresholdsTy & ImportThresholds)71801095a5dSDimitry Andric static void computeImportForFunction(
71901095a5dSDimitry Andric const FunctionSummary &Summary, const ModuleSummaryIndex &Index,
720b915e9e0SDimitry Andric const unsigned Threshold, const GVSummaryMapTy &DefinedGVSummaries,
7217fa27ce4SDimitry Andric function_ref<bool(GlobalValue::GUID, const GlobalValueSummary *)>
7227fa27ce4SDimitry Andric isPrevailing,
7237fa27ce4SDimitry Andric SmallVectorImpl<EdgeInfo> &Worklist, GlobalsImporter &GVImporter,
724b915e9e0SDimitry Andric FunctionImporter::ImportMapTy &ImportList,
725b1c73532SDimitry Andric DenseMap<StringRef, FunctionImporter::ExportSetTy> *ExportLists,
726eb11fae6SDimitry Andric FunctionImporter::ImportThresholdsTy &ImportThresholds) {
7277fa27ce4SDimitry Andric GVImporter.onImportingSummary(Summary);
728eb11fae6SDimitry Andric static int ImportCount = 0;
729e3b55780SDimitry Andric for (const auto &Edge : Summary.calls()) {
730c46e6a59SDimitry Andric ValueInfo VI = Edge.first;
731eb11fae6SDimitry Andric LLVM_DEBUG(dbgs() << " edge -> " << VI << " Threshold:" << Threshold
732c46e6a59SDimitry Andric << "\n");
73301095a5dSDimitry Andric
734eb11fae6SDimitry Andric if (ImportCutoff >= 0 && ImportCount >= ImportCutoff) {
735eb11fae6SDimitry Andric LLVM_DEBUG(dbgs() << "ignored! import-cutoff value of " << ImportCutoff
736eb11fae6SDimitry Andric << " reached.\n");
737eb11fae6SDimitry Andric continue;
738eb11fae6SDimitry Andric }
739eb11fae6SDimitry Andric
740c46e6a59SDimitry Andric if (DefinedGVSummaries.count(VI.getGUID())) {
741344a3780SDimitry Andric // FIXME: Consider not skipping import if the module contains
742344a3780SDimitry Andric // a non-prevailing def with interposable linkage. The prevailing copy
743344a3780SDimitry Andric // can safely be imported (see shouldImportGlobal()).
744eb11fae6SDimitry Andric LLVM_DEBUG(dbgs() << "ignored! Target already in destination module.\n");
74501095a5dSDimitry Andric continue;
746dd58ef01SDimitry Andric }
74701095a5dSDimitry Andric
748b915e9e0SDimitry Andric auto GetBonusMultiplier = [](CalleeInfo::HotnessType Hotness) -> float {
749b915e9e0SDimitry Andric if (Hotness == CalleeInfo::HotnessType::Hot)
750b915e9e0SDimitry Andric return ImportHotMultiplier;
751b915e9e0SDimitry Andric if (Hotness == CalleeInfo::HotnessType::Cold)
752b915e9e0SDimitry Andric return ImportColdMultiplier;
753ca089b24SDimitry Andric if (Hotness == CalleeInfo::HotnessType::Critical)
754ca089b24SDimitry Andric return ImportCriticalMultiplier;
755b915e9e0SDimitry Andric return 1.0;
756b915e9e0SDimitry Andric };
757b915e9e0SDimitry Andric
758b915e9e0SDimitry Andric const auto NewThreshold =
759eb11fae6SDimitry Andric Threshold * GetBonusMultiplier(Edge.second.getHotness());
760b915e9e0SDimitry Andric
761d8e91e46SDimitry Andric auto IT = ImportThresholds.insert(std::make_pair(
762d8e91e46SDimitry Andric VI.getGUID(), std::make_tuple(NewThreshold, nullptr, nullptr)));
763eb11fae6SDimitry Andric bool PreviouslyVisited = !IT.second;
764d8e91e46SDimitry Andric auto &ProcessedThreshold = std::get<0>(IT.first->second);
765d8e91e46SDimitry Andric auto &CalleeSummary = std::get<1>(IT.first->second);
766d8e91e46SDimitry Andric auto &FailureInfo = std::get<2>(IT.first->second);
767d8e91e46SDimitry Andric
768d8e91e46SDimitry Andric bool IsHotCallsite =
769d8e91e46SDimitry Andric Edge.second.getHotness() == CalleeInfo::HotnessType::Hot;
770d8e91e46SDimitry Andric bool IsCriticalCallsite =
771d8e91e46SDimitry Andric Edge.second.getHotness() == CalleeInfo::HotnessType::Critical;
772eb11fae6SDimitry Andric
773eb11fae6SDimitry Andric const FunctionSummary *ResolvedCalleeSummary = nullptr;
774eb11fae6SDimitry Andric if (CalleeSummary) {
775eb11fae6SDimitry Andric assert(PreviouslyVisited);
776eb11fae6SDimitry Andric // Since the traversal of the call graph is DFS, we can revisit a function
777eb11fae6SDimitry Andric // a second time with a higher threshold. In this case, it is added back
778eb11fae6SDimitry Andric // to the worklist with the new threshold (so that its own callee chains
779eb11fae6SDimitry Andric // can be considered with the higher threshold).
780eb11fae6SDimitry Andric if (NewThreshold <= ProcessedThreshold) {
781eb11fae6SDimitry Andric LLVM_DEBUG(
782eb11fae6SDimitry Andric dbgs() << "ignored! Target was already imported with Threshold "
783eb11fae6SDimitry Andric << ProcessedThreshold << "\n");
784eb11fae6SDimitry Andric continue;
785eb11fae6SDimitry Andric }
786eb11fae6SDimitry Andric // Update with new larger threshold.
787eb11fae6SDimitry Andric ProcessedThreshold = NewThreshold;
788eb11fae6SDimitry Andric ResolvedCalleeSummary = cast<FunctionSummary>(CalleeSummary);
789eb11fae6SDimitry Andric } else {
790eb11fae6SDimitry Andric // If we already rejected importing a callee at the same or higher
791eb11fae6SDimitry Andric // threshold, don't waste time calling selectCallee.
792eb11fae6SDimitry Andric if (PreviouslyVisited && NewThreshold <= ProcessedThreshold) {
793eb11fae6SDimitry Andric LLVM_DEBUG(
794eb11fae6SDimitry Andric dbgs() << "ignored! Target was already rejected with Threshold "
795eb11fae6SDimitry Andric << ProcessedThreshold << "\n");
796d8e91e46SDimitry Andric if (PrintImportFailures) {
797d8e91e46SDimitry Andric assert(FailureInfo &&
798d8e91e46SDimitry Andric "Expected FailureInfo for previously rejected candidate");
799d8e91e46SDimitry Andric FailureInfo->Attempts++;
800d8e91e46SDimitry Andric }
801eb11fae6SDimitry Andric continue;
802eb11fae6SDimitry Andric }
803eb11fae6SDimitry Andric
804b1c73532SDimitry Andric FunctionImporter::ImportFailureReason Reason{};
805ac9a064cSDimitry Andric
806ac9a064cSDimitry Andric // `SummaryForDeclImport` is an summary eligible for declaration import.
807ac9a064cSDimitry Andric const GlobalValueSummary *SummaryForDeclImport = nullptr;
808ac9a064cSDimitry Andric CalleeSummary =
809ac9a064cSDimitry Andric selectCallee(Index, VI.getSummaryList(), NewThreshold,
810ac9a064cSDimitry Andric Summary.modulePath(), SummaryForDeclImport, Reason);
81101095a5dSDimitry Andric if (!CalleeSummary) {
812ac9a064cSDimitry Andric // There isn't a callee for definition import but one for declaration
813ac9a064cSDimitry Andric // import.
814ac9a064cSDimitry Andric if (ImportDeclaration && SummaryForDeclImport) {
815ac9a064cSDimitry Andric StringRef DeclSourceModule = SummaryForDeclImport->modulePath();
816ac9a064cSDimitry Andric
817ac9a064cSDimitry Andric // Since definition takes precedence over declaration for the same VI,
818ac9a064cSDimitry Andric // try emplace <VI, declaration> pair without checking insert result.
819ac9a064cSDimitry Andric // If insert doesn't happen, there must be an existing entry keyed by
820ac9a064cSDimitry Andric // VI. Note `ExportLists` only keeps track of exports due to imported
821ac9a064cSDimitry Andric // definitions.
822ac9a064cSDimitry Andric ImportList[DeclSourceModule].try_emplace(
823ac9a064cSDimitry Andric VI.getGUID(), GlobalValueSummary::Declaration);
824ac9a064cSDimitry Andric }
825eb11fae6SDimitry Andric // Update with new larger threshold if this was a retry (otherwise
826d8e91e46SDimitry Andric // we would have already inserted with NewThreshold above). Also
827d8e91e46SDimitry Andric // update failure info if requested.
828d8e91e46SDimitry Andric if (PreviouslyVisited) {
829eb11fae6SDimitry Andric ProcessedThreshold = NewThreshold;
830d8e91e46SDimitry Andric if (PrintImportFailures) {
831d8e91e46SDimitry Andric assert(FailureInfo &&
832d8e91e46SDimitry Andric "Expected FailureInfo for previously rejected candidate");
833d8e91e46SDimitry Andric FailureInfo->Reason = Reason;
834d8e91e46SDimitry Andric FailureInfo->Attempts++;
835d8e91e46SDimitry Andric FailureInfo->MaxHotness =
836d8e91e46SDimitry Andric std::max(FailureInfo->MaxHotness, Edge.second.getHotness());
837d8e91e46SDimitry Andric }
838d8e91e46SDimitry Andric } else if (PrintImportFailures) {
839d8e91e46SDimitry Andric assert(!FailureInfo &&
840d8e91e46SDimitry Andric "Expected no FailureInfo for newly rejected candidate");
8411d5ae102SDimitry Andric FailureInfo = std::make_unique<FunctionImporter::ImportFailureInfo>(
842d8e91e46SDimitry Andric VI, Edge.second.getHotness(), Reason, 1);
843d8e91e46SDimitry Andric }
844344a3780SDimitry Andric if (ForceImportAll) {
845344a3780SDimitry Andric std::string Msg = std::string("Failed to import function ") +
846344a3780SDimitry Andric VI.name().str() + " due to " +
847344a3780SDimitry Andric getFailureName(Reason);
848344a3780SDimitry Andric auto Error = make_error<StringError>(
849c0981da4SDimitry Andric Msg, make_error_code(errc::not_supported));
850344a3780SDimitry Andric logAllUnhandledErrors(std::move(Error), errs(),
851344a3780SDimitry Andric "Error importing module: ");
852344a3780SDimitry Andric break;
853344a3780SDimitry Andric } else {
854344a3780SDimitry Andric LLVM_DEBUG(dbgs()
855344a3780SDimitry Andric << "ignored! No qualifying callee with summary found.\n");
85601095a5dSDimitry Andric continue;
857dd58ef01SDimitry Andric }
858344a3780SDimitry Andric }
859044eb2f6SDimitry Andric
860044eb2f6SDimitry Andric // "Resolve" the summary
861eb11fae6SDimitry Andric CalleeSummary = CalleeSummary->getBaseObject();
862eb11fae6SDimitry Andric ResolvedCalleeSummary = cast<FunctionSummary>(CalleeSummary);
86301095a5dSDimitry Andric
864344a3780SDimitry Andric assert((ResolvedCalleeSummary->fflags().AlwaysInline || ForceImportAll ||
865706b4fc4SDimitry Andric (ResolvedCalleeSummary->instCount() <= NewThreshold)) &&
86601095a5dSDimitry Andric "selectCallee() didn't honor the threshold");
86701095a5dSDimitry Andric
86801095a5dSDimitry Andric auto ExportModulePath = ResolvedCalleeSummary->modulePath();
869ac9a064cSDimitry Andric
870ac9a064cSDimitry Andric // Try emplace the definition entry, and update stats based on insertion
871ac9a064cSDimitry Andric // status.
872ac9a064cSDimitry Andric auto [Iter, Inserted] = ImportList[ExportModulePath].try_emplace(
873ac9a064cSDimitry Andric VI.getGUID(), GlobalValueSummary::Definition);
874ac9a064cSDimitry Andric
875eb11fae6SDimitry Andric // We previously decided to import this GUID definition if it was already
876eb11fae6SDimitry Andric // inserted in the set of imports from the exporting module.
877ac9a064cSDimitry Andric if (Inserted || Iter->second == GlobalValueSummary::Declaration) {
878d8e91e46SDimitry Andric NumImportedFunctionsThinLink++;
879d8e91e46SDimitry Andric if (IsHotCallsite)
880d8e91e46SDimitry Andric NumImportedHotFunctionsThinLink++;
881d8e91e46SDimitry Andric if (IsCriticalCallsite)
882d8e91e46SDimitry Andric NumImportedCriticalFunctionsThinLink++;
883d8e91e46SDimitry Andric }
88401095a5dSDimitry Andric
885ac9a064cSDimitry Andric if (Iter->second == GlobalValueSummary::Declaration)
886ac9a064cSDimitry Andric Iter->second = GlobalValueSummary::Definition;
887ac9a064cSDimitry Andric
888cfca06d7SDimitry Andric // Any calls/references made by this function will be marked exported
889cfca06d7SDimitry Andric // later, in ComputeCrossModuleImport, after import decisions are
890cfca06d7SDimitry Andric // complete, which is more efficient than adding them here.
891cfca06d7SDimitry Andric if (ExportLists)
892cfca06d7SDimitry Andric (*ExportLists)[ExportModulePath].insert(VI);
893eb11fae6SDimitry Andric }
894eb11fae6SDimitry Andric
895eb11fae6SDimitry Andric auto GetAdjustedThreshold = [](unsigned Threshold, bool IsHotCallsite) {
896eb11fae6SDimitry Andric // Adjust the threshold for next level of imported functions.
897eb11fae6SDimitry Andric // The threshold is different for hot callsites because we can then
898eb11fae6SDimitry Andric // inline chains of hot calls.
899eb11fae6SDimitry Andric if (IsHotCallsite)
900eb11fae6SDimitry Andric return Threshold * ImportHotInstrFactor;
901eb11fae6SDimitry Andric return Threshold * ImportInstrFactor;
902eb11fae6SDimitry Andric };
903eb11fae6SDimitry Andric
904eb11fae6SDimitry Andric const auto AdjThreshold = GetAdjustedThreshold(Threshold, IsHotCallsite);
905eb11fae6SDimitry Andric
906eb11fae6SDimitry Andric ImportCount++;
907dd58ef01SDimitry Andric
90801095a5dSDimitry Andric // Insert the newly imported function to the worklist.
909b60736ecSDimitry Andric Worklist.emplace_back(ResolvedCalleeSummary, AdjThreshold);
91001095a5dSDimitry Andric }
91101095a5dSDimitry Andric }
91201095a5dSDimitry Andric
computeImportForModule(const GVSummaryMapTy & DefinedGVSummaries,StringRef ModName,FunctionImporter::ImportMapTy & ImportList)913b1c73532SDimitry Andric void ModuleImportsManager::computeImportForModule(
914b1c73532SDimitry Andric const GVSummaryMapTy &DefinedGVSummaries, StringRef ModName,
915b1c73532SDimitry Andric FunctionImporter::ImportMapTy &ImportList) {
91601095a5dSDimitry Andric // Worklist contains the list of function imported in this module, for which
91701095a5dSDimitry Andric // we will analyse the callees and may import further down the callgraph.
91801095a5dSDimitry Andric SmallVector<EdgeInfo, 128> Worklist;
919b1c73532SDimitry Andric GlobalsImporter GVI(Index, DefinedGVSummaries, IsPrevailing, ImportList,
9207fa27ce4SDimitry Andric ExportLists);
921eb11fae6SDimitry Andric FunctionImporter::ImportThresholdsTy ImportThresholds;
92201095a5dSDimitry Andric
92301095a5dSDimitry Andric // Populate the worklist with the import for the functions in the current
92401095a5dSDimitry Andric // module
925e3b55780SDimitry Andric for (const auto &GVSummary : DefinedGVSummaries) {
926eb11fae6SDimitry Andric #ifndef NDEBUG
927eb11fae6SDimitry Andric // FIXME: Change the GVSummaryMapTy to hold ValueInfo instead of GUID
928eb11fae6SDimitry Andric // so this map look up (and possibly others) can be avoided.
929eb11fae6SDimitry Andric auto VI = Index.getValueInfo(GVSummary.first);
930eb11fae6SDimitry Andric #endif
931d288ef4cSDimitry Andric if (!Index.isGlobalValueLive(GVSummary.second)) {
932eb11fae6SDimitry Andric LLVM_DEBUG(dbgs() << "Ignores Dead GUID: " << VI << "\n");
9337e7b6700SDimitry Andric continue;
9347e7b6700SDimitry Andric }
935044eb2f6SDimitry Andric auto *FuncSummary =
936044eb2f6SDimitry Andric dyn_cast<FunctionSummary>(GVSummary.second->getBaseObject());
93701095a5dSDimitry Andric if (!FuncSummary)
93801095a5dSDimitry Andric // Skip import for global variables
93901095a5dSDimitry Andric continue;
940eb11fae6SDimitry Andric LLVM_DEBUG(dbgs() << "Initialize import for " << VI << "\n");
94101095a5dSDimitry Andric computeImportForFunction(*FuncSummary, Index, ImportInstrLimit,
942b1c73532SDimitry Andric DefinedGVSummaries, IsPrevailing, Worklist, GVI,
9437fa27ce4SDimitry Andric ImportList, ExportLists, ImportThresholds);
94401095a5dSDimitry Andric }
94501095a5dSDimitry Andric
946b915e9e0SDimitry Andric // Process the newly imported functions and add callees to the worklist.
947dd58ef01SDimitry Andric while (!Worklist.empty()) {
948b60736ecSDimitry Andric auto GVInfo = Worklist.pop_back_val();
949b60736ecSDimitry Andric auto *Summary = std::get<0>(GVInfo);
950b60736ecSDimitry Andric auto Threshold = std::get<1>(GVInfo);
95101095a5dSDimitry Andric
952b60736ecSDimitry Andric if (auto *FS = dyn_cast<FunctionSummary>(Summary))
953b60736ecSDimitry Andric computeImportForFunction(*FS, Index, Threshold, DefinedGVSummaries,
954b1c73532SDimitry Andric IsPrevailing, Worklist, GVI, ImportList,
9557fa27ce4SDimitry Andric ExportLists, ImportThresholds);
956dd58ef01SDimitry Andric }
957d8e91e46SDimitry Andric
958d8e91e46SDimitry Andric // Print stats about functions considered but rejected for importing
959d8e91e46SDimitry Andric // when requested.
960d8e91e46SDimitry Andric if (PrintImportFailures) {
961d8e91e46SDimitry Andric dbgs() << "Missed imports into module " << ModName << "\n";
962d8e91e46SDimitry Andric for (auto &I : ImportThresholds) {
963d8e91e46SDimitry Andric auto &ProcessedThreshold = std::get<0>(I.second);
964d8e91e46SDimitry Andric auto &CalleeSummary = std::get<1>(I.second);
965d8e91e46SDimitry Andric auto &FailureInfo = std::get<2>(I.second);
966d8e91e46SDimitry Andric if (CalleeSummary)
967d8e91e46SDimitry Andric continue; // We are going to import.
968d8e91e46SDimitry Andric assert(FailureInfo);
969d8e91e46SDimitry Andric FunctionSummary *FS = nullptr;
970d8e91e46SDimitry Andric if (!FailureInfo->VI.getSummaryList().empty())
971d8e91e46SDimitry Andric FS = dyn_cast<FunctionSummary>(
972d8e91e46SDimitry Andric FailureInfo->VI.getSummaryList()[0]->getBaseObject());
973d8e91e46SDimitry Andric dbgs() << FailureInfo->VI
974d8e91e46SDimitry Andric << ": Reason = " << getFailureName(FailureInfo->Reason)
975d8e91e46SDimitry Andric << ", Threshold = " << ProcessedThreshold
976d8e91e46SDimitry Andric << ", Size = " << (FS ? (int)FS->instCount() : -1)
977d8e91e46SDimitry Andric << ", MaxHotness = " << getHotnessName(FailureInfo->MaxHotness)
978d8e91e46SDimitry Andric << ", Attempts = " << FailureInfo->Attempts << "\n";
979d8e91e46SDimitry Andric }
980d8e91e46SDimitry Andric }
981dd58ef01SDimitry Andric }
982dd58ef01SDimitry Andric
983eb11fae6SDimitry Andric #ifndef NDEBUG
isGlobalVarSummary(const ModuleSummaryIndex & Index,ValueInfo VI)984706b4fc4SDimitry Andric static bool isGlobalVarSummary(const ModuleSummaryIndex &Index, ValueInfo VI) {
985eb11fae6SDimitry Andric auto SL = VI.getSummaryList();
986706b4fc4SDimitry Andric return SL.empty()
987706b4fc4SDimitry Andric ? false
988706b4fc4SDimitry Andric : SL[0]->getSummaryKind() == GlobalValueSummary::GlobalVarKind;
989eb11fae6SDimitry Andric }
990eb11fae6SDimitry Andric
isGlobalVarSummary(const ModuleSummaryIndex & Index,GlobalValue::GUID G)991706b4fc4SDimitry Andric static bool isGlobalVarSummary(const ModuleSummaryIndex &Index,
992706b4fc4SDimitry Andric GlobalValue::GUID G) {
993706b4fc4SDimitry Andric if (const auto &VI = Index.getValueInfo(G))
994706b4fc4SDimitry Andric return isGlobalVarSummary(Index, VI);
995706b4fc4SDimitry Andric return false;
996706b4fc4SDimitry Andric }
997eb11fae6SDimitry Andric
998ac9a064cSDimitry Andric // Return the number of global variable summaries in ExportSet.
999ac9a064cSDimitry Andric static unsigned
numGlobalVarSummaries(const ModuleSummaryIndex & Index,FunctionImporter::ExportSetTy & ExportSet)1000ac9a064cSDimitry Andric numGlobalVarSummaries(const ModuleSummaryIndex &Index,
1001ac9a064cSDimitry Andric FunctionImporter::ExportSetTy &ExportSet) {
1002eb11fae6SDimitry Andric unsigned NumGVS = 0;
1003ac9a064cSDimitry Andric for (auto &VI : ExportSet)
1004ac9a064cSDimitry Andric if (isGlobalVarSummary(Index, VI.getGUID()))
1005eb11fae6SDimitry Andric ++NumGVS;
1006eb11fae6SDimitry Andric return NumGVS;
1007eb11fae6SDimitry Andric }
1008ac9a064cSDimitry Andric
1009ac9a064cSDimitry Andric // Given ImportMap, return the number of global variable summaries and record
1010ac9a064cSDimitry Andric // the number of defined function summaries as output parameter.
1011ac9a064cSDimitry Andric static unsigned
numGlobalVarSummaries(const ModuleSummaryIndex & Index,FunctionImporter::FunctionsToImportTy & ImportMap,unsigned & DefinedFS)1012ac9a064cSDimitry Andric numGlobalVarSummaries(const ModuleSummaryIndex &Index,
1013ac9a064cSDimitry Andric FunctionImporter::FunctionsToImportTy &ImportMap,
1014ac9a064cSDimitry Andric unsigned &DefinedFS) {
1015ac9a064cSDimitry Andric unsigned NumGVS = 0;
1016ac9a064cSDimitry Andric DefinedFS = 0;
1017ac9a064cSDimitry Andric for (auto &[GUID, Type] : ImportMap) {
1018ac9a064cSDimitry Andric if (isGlobalVarSummary(Index, GUID))
1019ac9a064cSDimitry Andric ++NumGVS;
1020ac9a064cSDimitry Andric else if (Type == GlobalValueSummary::Definition)
1021ac9a064cSDimitry Andric ++DefinedFS;
1022ac9a064cSDimitry Andric }
1023ac9a064cSDimitry Andric return NumGVS;
1024ac9a064cSDimitry Andric }
1025eb11fae6SDimitry Andric #endif
1026eb11fae6SDimitry Andric
1027706b4fc4SDimitry Andric #ifndef NDEBUG
checkVariableImport(const ModuleSummaryIndex & Index,DenseMap<StringRef,FunctionImporter::ImportMapTy> & ImportLists,DenseMap<StringRef,FunctionImporter::ExportSetTy> & ExportLists)1028b1c73532SDimitry Andric static bool checkVariableImport(
1029b1c73532SDimitry Andric const ModuleSummaryIndex &Index,
1030b1c73532SDimitry Andric DenseMap<StringRef, FunctionImporter::ImportMapTy> &ImportLists,
1031b1c73532SDimitry Andric DenseMap<StringRef, FunctionImporter::ExportSetTy> &ExportLists) {
1032706b4fc4SDimitry Andric DenseSet<GlobalValue::GUID> FlattenedImports;
1033706b4fc4SDimitry Andric
1034706b4fc4SDimitry Andric for (auto &ImportPerModule : ImportLists)
1035706b4fc4SDimitry Andric for (auto &ExportPerModule : ImportPerModule.second)
1036ac9a064cSDimitry Andric for (auto &[GUID, Type] : ExportPerModule.second)
1037ac9a064cSDimitry Andric FlattenedImports.insert(GUID);
1038706b4fc4SDimitry Andric
1039706b4fc4SDimitry Andric // Checks that all GUIDs of read/writeonly vars we see in export lists
1040706b4fc4SDimitry Andric // are also in the import lists. Otherwise we my face linker undefs,
1041706b4fc4SDimitry Andric // because readonly and writeonly vars are internalized in their
10427fa27ce4SDimitry Andric // source modules. The exception would be if it has a linkage type indicating
10437fa27ce4SDimitry Andric // that there may have been a copy existing in the importing module (e.g.
10447fa27ce4SDimitry Andric // linkonce_odr). In that case we cannot accurately do this checking.
10457fa27ce4SDimitry Andric auto IsReadOrWriteOnlyVarNeedingImporting = [&](StringRef ModulePath,
10467fa27ce4SDimitry Andric const ValueInfo &VI) {
1047706b4fc4SDimitry Andric auto *GVS = dyn_cast_or_null<GlobalVarSummary>(
1048706b4fc4SDimitry Andric Index.findSummaryInModule(VI, ModulePath));
10497fa27ce4SDimitry Andric return GVS && (Index.isReadOnly(GVS) || Index.isWriteOnly(GVS)) &&
10507fa27ce4SDimitry Andric !(GVS->linkage() == GlobalValue::AvailableExternallyLinkage ||
10517fa27ce4SDimitry Andric GVS->linkage() == GlobalValue::WeakODRLinkage ||
10527fa27ce4SDimitry Andric GVS->linkage() == GlobalValue::LinkOnceODRLinkage);
1053706b4fc4SDimitry Andric };
1054706b4fc4SDimitry Andric
1055706b4fc4SDimitry Andric for (auto &ExportPerModule : ExportLists)
1056706b4fc4SDimitry Andric for (auto &VI : ExportPerModule.second)
1057706b4fc4SDimitry Andric if (!FlattenedImports.count(VI.getGUID()) &&
1058b1c73532SDimitry Andric IsReadOrWriteOnlyVarNeedingImporting(ExportPerModule.first, VI))
1059706b4fc4SDimitry Andric return false;
1060706b4fc4SDimitry Andric
1061706b4fc4SDimitry Andric return true;
1062706b4fc4SDimitry Andric }
1063706b4fc4SDimitry Andric #endif
1064706b4fc4SDimitry Andric
106501095a5dSDimitry Andric /// Compute all the import and export for every module using the Index.
ComputeCrossModuleImport(const ModuleSummaryIndex & Index,const DenseMap<StringRef,GVSummaryMapTy> & ModuleToDefinedGVSummaries,function_ref<bool (GlobalValue::GUID,const GlobalValueSummary *)> isPrevailing,DenseMap<StringRef,FunctionImporter::ImportMapTy> & ImportLists,DenseMap<StringRef,FunctionImporter::ExportSetTy> & ExportLists)106601095a5dSDimitry Andric void llvm::ComputeCrossModuleImport(
106701095a5dSDimitry Andric const ModuleSummaryIndex &Index,
1068b1c73532SDimitry Andric const DenseMap<StringRef, GVSummaryMapTy> &ModuleToDefinedGVSummaries,
10697fa27ce4SDimitry Andric function_ref<bool(GlobalValue::GUID, const GlobalValueSummary *)>
10707fa27ce4SDimitry Andric isPrevailing,
1071b1c73532SDimitry Andric DenseMap<StringRef, FunctionImporter::ImportMapTy> &ImportLists,
1072b1c73532SDimitry Andric DenseMap<StringRef, FunctionImporter::ExportSetTy> &ExportLists) {
1073312c0ed1SDimitry Andric auto MIS = ModuleImportsManager::create(isPrevailing, Index, &ExportLists);
107401095a5dSDimitry Andric // For each module that has function defined, compute the import/export lists.
1075e3b55780SDimitry Andric for (const auto &DefinedGVSummaries : ModuleToDefinedGVSummaries) {
1076b1c73532SDimitry Andric auto &ImportList = ImportLists[DefinedGVSummaries.first];
1077eb11fae6SDimitry Andric LLVM_DEBUG(dbgs() << "Computing import for Module '"
1078b1c73532SDimitry Andric << DefinedGVSummaries.first << "'\n");
1079312c0ed1SDimitry Andric MIS->computeImportForModule(DefinedGVSummaries.second,
1080b1c73532SDimitry Andric DefinedGVSummaries.first, ImportList);
108101095a5dSDimitry Andric }
108201095a5dSDimitry Andric
1083cfca06d7SDimitry Andric // When computing imports we only added the variables and functions being
1084cfca06d7SDimitry Andric // imported to the export list. We also need to mark any references and calls
1085cfca06d7SDimitry Andric // they make as exported as well. We do this here, as it is more efficient
1086cfca06d7SDimitry Andric // since we may import the same values multiple times into different modules
1087cfca06d7SDimitry Andric // during the import computation.
1088b915e9e0SDimitry Andric for (auto &ELI : ExportLists) {
1089ac9a064cSDimitry Andric // `NewExports` tracks the VI that gets exported because the full definition
1090ac9a064cSDimitry Andric // of its user/referencer gets exported.
1091cfca06d7SDimitry Andric FunctionImporter::ExportSetTy NewExports;
1092b915e9e0SDimitry Andric const auto &DefinedGVSummaries =
1093b1c73532SDimitry Andric ModuleToDefinedGVSummaries.lookup(ELI.first);
1094cfca06d7SDimitry Andric for (auto &EI : ELI.second) {
1095cfca06d7SDimitry Andric // Find the copy defined in the exporting module so that we can mark the
1096cfca06d7SDimitry Andric // values it references in that specific definition as exported.
1097cfca06d7SDimitry Andric // Below we will add all references and called values, without regard to
1098cfca06d7SDimitry Andric // whether they are also defined in this module. We subsequently prune the
1099cfca06d7SDimitry Andric // list to only include those defined in the exporting module, see comment
1100cfca06d7SDimitry Andric // there as to why.
1101cfca06d7SDimitry Andric auto DS = DefinedGVSummaries.find(EI.getGUID());
1102cfca06d7SDimitry Andric // Anything marked exported during the import computation must have been
1103cfca06d7SDimitry Andric // defined in the exporting module.
1104cfca06d7SDimitry Andric assert(DS != DefinedGVSummaries.end());
1105cfca06d7SDimitry Andric auto *S = DS->getSecond();
1106cfca06d7SDimitry Andric S = S->getBaseObject();
1107cfca06d7SDimitry Andric if (auto *GVS = dyn_cast<GlobalVarSummary>(S)) {
1108cfca06d7SDimitry Andric // Export referenced functions and variables. We don't export/promote
1109cfca06d7SDimitry Andric // objects referenced by writeonly variable initializer, because
1110cfca06d7SDimitry Andric // we convert such variables initializers to "zeroinitializer".
1111cfca06d7SDimitry Andric // See processGlobalForThinLTO.
1112cfca06d7SDimitry Andric if (!Index.isWriteOnly(GVS))
1113cfca06d7SDimitry Andric for (const auto &VI : GVS->refs())
1114cfca06d7SDimitry Andric NewExports.insert(VI);
1115cfca06d7SDimitry Andric } else {
1116cfca06d7SDimitry Andric auto *FS = cast<FunctionSummary>(S);
1117e3b55780SDimitry Andric for (const auto &Edge : FS->calls())
1118cfca06d7SDimitry Andric NewExports.insert(Edge.first);
1119e3b55780SDimitry Andric for (const auto &Ref : FS->refs())
1120cfca06d7SDimitry Andric NewExports.insert(Ref);
1121cfca06d7SDimitry Andric }
1122cfca06d7SDimitry Andric }
1123ac9a064cSDimitry Andric // Prune list computed above to only include values defined in the
1124ac9a064cSDimitry Andric // exporting module. We do this after the above insertion since we may hit
1125ac9a064cSDimitry Andric // the same ref/call target multiple times in above loop, and it is more
1126ac9a064cSDimitry Andric // efficient to avoid a set lookup each time.
1127cfca06d7SDimitry Andric for (auto EI = NewExports.begin(); EI != NewExports.end();) {
1128706b4fc4SDimitry Andric if (!DefinedGVSummaries.count(EI->getGUID()))
1129cfca06d7SDimitry Andric NewExports.erase(EI++);
1130b915e9e0SDimitry Andric else
1131b915e9e0SDimitry Andric ++EI;
1132b915e9e0SDimitry Andric }
1133cfca06d7SDimitry Andric ELI.second.insert(NewExports.begin(), NewExports.end());
1134b915e9e0SDimitry Andric }
1135b915e9e0SDimitry Andric
1136706b4fc4SDimitry Andric assert(checkVariableImport(Index, ImportLists, ExportLists));
113701095a5dSDimitry Andric #ifndef NDEBUG
1138eb11fae6SDimitry Andric LLVM_DEBUG(dbgs() << "Import/Export lists for " << ImportLists.size()
113901095a5dSDimitry Andric << " modules:\n");
114001095a5dSDimitry Andric for (auto &ModuleImports : ImportLists) {
1141b1c73532SDimitry Andric auto ModName = ModuleImports.first;
114201095a5dSDimitry Andric auto &Exports = ExportLists[ModName];
1143eb11fae6SDimitry Andric unsigned NumGVS = numGlobalVarSummaries(Index, Exports);
1144eb11fae6SDimitry Andric LLVM_DEBUG(dbgs() << "* Module " << ModName << " exports "
1145eb11fae6SDimitry Andric << Exports.size() - NumGVS << " functions and " << NumGVS
1146eb11fae6SDimitry Andric << " vars. Imports from " << ModuleImports.second.size()
114701095a5dSDimitry Andric << " modules.\n");
114801095a5dSDimitry Andric for (auto &Src : ModuleImports.second) {
1149b1c73532SDimitry Andric auto SrcModName = Src.first;
1150ac9a064cSDimitry Andric unsigned DefinedFS = 0;
1151ac9a064cSDimitry Andric unsigned NumGVSPerMod =
1152ac9a064cSDimitry Andric numGlobalVarSummaries(Index, Src.second, DefinedFS);
1153ac9a064cSDimitry Andric LLVM_DEBUG(dbgs() << " - " << DefinedFS << " function definitions and "
1154ac9a064cSDimitry Andric << Src.second.size() - NumGVSPerMod - DefinedFS
1155ac9a064cSDimitry Andric << " function declarations imported from " << SrcModName
1156ac9a064cSDimitry Andric << "\n");
1157eb11fae6SDimitry Andric LLVM_DEBUG(dbgs() << " - " << NumGVSPerMod
1158eb11fae6SDimitry Andric << " global vars imported from " << SrcModName << "\n");
115901095a5dSDimitry Andric }
116001095a5dSDimitry Andric }
116101095a5dSDimitry Andric #endif
116201095a5dSDimitry Andric }
116301095a5dSDimitry Andric
1164044eb2f6SDimitry Andric #ifndef NDEBUG
dumpImportListForModule(const ModuleSummaryIndex & Index,StringRef ModulePath,FunctionImporter::ImportMapTy & ImportList)1165eb11fae6SDimitry Andric static void dumpImportListForModule(const ModuleSummaryIndex &Index,
1166eb11fae6SDimitry Andric StringRef ModulePath,
1167044eb2f6SDimitry Andric FunctionImporter::ImportMapTy &ImportList) {
1168eb11fae6SDimitry Andric LLVM_DEBUG(dbgs() << "* Module " << ModulePath << " imports from "
1169044eb2f6SDimitry Andric << ImportList.size() << " modules.\n");
1170044eb2f6SDimitry Andric for (auto &Src : ImportList) {
1171b1c73532SDimitry Andric auto SrcModName = Src.first;
1172ac9a064cSDimitry Andric unsigned DefinedFS = 0;
1173ac9a064cSDimitry Andric unsigned NumGVSPerMod = numGlobalVarSummaries(Index, Src.second, DefinedFS);
1174ac9a064cSDimitry Andric LLVM_DEBUG(dbgs() << " - " << DefinedFS << " function definitions and "
1175ac9a064cSDimitry Andric << Src.second.size() - DefinedFS - NumGVSPerMod
1176ac9a064cSDimitry Andric << " function declarations imported from " << SrcModName
1177ac9a064cSDimitry Andric << "\n");
1178eb11fae6SDimitry Andric LLVM_DEBUG(dbgs() << " - " << NumGVSPerMod << " vars imported from "
1179044eb2f6SDimitry Andric << SrcModName << "\n");
1180044eb2f6SDimitry Andric }
1181044eb2f6SDimitry Andric }
1182044eb2f6SDimitry Andric #endif
1183044eb2f6SDimitry Andric
1184b1c73532SDimitry Andric /// Compute all the imports for the given module using the Index.
1185b1c73532SDimitry Andric ///
1186b1c73532SDimitry Andric /// \p isPrevailing is a callback that will be called with a global value's GUID
1187b1c73532SDimitry Andric /// and summary and should return whether the module corresponding to the
1188b1c73532SDimitry Andric /// summary contains the linker-prevailing copy of that value.
1189b1c73532SDimitry Andric ///
1190b1c73532SDimitry Andric /// \p ImportList will be populated with a map that can be passed to
1191b1c73532SDimitry Andric /// FunctionImporter::importFunctions() above (see description there).
ComputeCrossModuleImportForModuleForTest(StringRef ModulePath,function_ref<bool (GlobalValue::GUID,const GlobalValueSummary *)> isPrevailing,const ModuleSummaryIndex & Index,FunctionImporter::ImportMapTy & ImportList)1192b1c73532SDimitry Andric static void ComputeCrossModuleImportForModuleForTest(
11937fa27ce4SDimitry Andric StringRef ModulePath,
11947fa27ce4SDimitry Andric function_ref<bool(GlobalValue::GUID, const GlobalValueSummary *)>
11957fa27ce4SDimitry Andric isPrevailing,
11967fa27ce4SDimitry Andric const ModuleSummaryIndex &Index,
119701095a5dSDimitry Andric FunctionImporter::ImportMapTy &ImportList) {
119801095a5dSDimitry Andric // Collect the list of functions this module defines.
119901095a5dSDimitry Andric // GUID -> Summary
120001095a5dSDimitry Andric GVSummaryMapTy FunctionSummaryMap;
120101095a5dSDimitry Andric Index.collectDefinedFunctionsForModule(ModulePath, FunctionSummaryMap);
120201095a5dSDimitry Andric
120301095a5dSDimitry Andric // Compute the import list for this module.
1204eb11fae6SDimitry Andric LLVM_DEBUG(dbgs() << "Computing import for Module '" << ModulePath << "'\n");
1205312c0ed1SDimitry Andric auto MIS = ModuleImportsManager::create(isPrevailing, Index);
1206312c0ed1SDimitry Andric MIS->computeImportForModule(FunctionSummaryMap, ModulePath, ImportList);
120701095a5dSDimitry Andric
120801095a5dSDimitry Andric #ifndef NDEBUG
1209eb11fae6SDimitry Andric dumpImportListForModule(Index, ModulePath, ImportList);
1210044eb2f6SDimitry Andric #endif
121101095a5dSDimitry Andric }
1212044eb2f6SDimitry Andric
1213b1c73532SDimitry Andric /// Mark all external summaries in \p Index for import into the given module.
1214b1c73532SDimitry Andric /// Used for testing the case of distributed builds using a distributed index.
1215b1c73532SDimitry Andric ///
1216b1c73532SDimitry Andric /// \p ImportList will be populated with a map that can be passed to
1217b1c73532SDimitry Andric /// FunctionImporter::importFunctions() above (see description there).
ComputeCrossModuleImportForModuleFromIndexForTest(StringRef ModulePath,const ModuleSummaryIndex & Index,FunctionImporter::ImportMapTy & ImportList)1218b1c73532SDimitry Andric static void ComputeCrossModuleImportForModuleFromIndexForTest(
1219044eb2f6SDimitry Andric StringRef ModulePath, const ModuleSummaryIndex &Index,
1220044eb2f6SDimitry Andric FunctionImporter::ImportMapTy &ImportList) {
1221e3b55780SDimitry Andric for (const auto &GlobalList : Index) {
1222044eb2f6SDimitry Andric // Ignore entries for undefined references.
1223044eb2f6SDimitry Andric if (GlobalList.second.SummaryList.empty())
1224044eb2f6SDimitry Andric continue;
1225044eb2f6SDimitry Andric
1226044eb2f6SDimitry Andric auto GUID = GlobalList.first;
1227044eb2f6SDimitry Andric assert(GlobalList.second.SummaryList.size() == 1 &&
1228044eb2f6SDimitry Andric "Expected individual combined index to have one summary per GUID");
1229044eb2f6SDimitry Andric auto &Summary = GlobalList.second.SummaryList[0];
1230044eb2f6SDimitry Andric // Skip the summaries for the importing module. These are included to
1231044eb2f6SDimitry Andric // e.g. record required linkage changes.
1232044eb2f6SDimitry Andric if (Summary->modulePath() == ModulePath)
1233044eb2f6SDimitry Andric continue;
1234eb11fae6SDimitry Andric // Add an entry to provoke importing by thinBackend.
1235ac9a064cSDimitry Andric auto [Iter, Inserted] = ImportList[Summary->modulePath()].try_emplace(
1236ac9a064cSDimitry Andric GUID, Summary->importType());
1237ac9a064cSDimitry Andric if (!Inserted) {
1238ac9a064cSDimitry Andric // Use 'std::min' to make sure definition (with enum value 0) takes
1239ac9a064cSDimitry Andric // precedence over declaration (with enum value 1).
1240ac9a064cSDimitry Andric Iter->second = std::min(Iter->second, Summary->importType());
1241ac9a064cSDimitry Andric }
1242044eb2f6SDimitry Andric }
1243044eb2f6SDimitry Andric #ifndef NDEBUG
1244eb11fae6SDimitry Andric dumpImportListForModule(Index, ModulePath, ImportList);
124501095a5dSDimitry Andric #endif
124601095a5dSDimitry Andric }
124701095a5dSDimitry Andric
1248c0981da4SDimitry Andric // For SamplePGO, the indirect call targets for local functions will
1249c0981da4SDimitry Andric // have its original name annotated in profile. We try to find the
1250c0981da4SDimitry Andric // corresponding PGOFuncName as the GUID, and fix up the edges
1251c0981da4SDimitry Andric // accordingly.
updateValueInfoForIndirectCalls(ModuleSummaryIndex & Index,FunctionSummary * FS)1252c0981da4SDimitry Andric void updateValueInfoForIndirectCalls(ModuleSummaryIndex &Index,
1253c0981da4SDimitry Andric FunctionSummary *FS) {
1254c0981da4SDimitry Andric for (auto &EI : FS->mutableCalls()) {
1255c0981da4SDimitry Andric if (!EI.first.getSummaryList().empty())
1256c0981da4SDimitry Andric continue;
1257c0981da4SDimitry Andric auto GUID = Index.getGUIDFromOriginalID(EI.first.getGUID());
1258c0981da4SDimitry Andric if (GUID == 0)
1259c0981da4SDimitry Andric continue;
1260c0981da4SDimitry Andric // Update the edge to point directly to the correct GUID.
1261c0981da4SDimitry Andric auto VI = Index.getValueInfo(GUID);
1262c0981da4SDimitry Andric if (llvm::any_of(
1263c0981da4SDimitry Andric VI.getSummaryList(),
1264c0981da4SDimitry Andric [&](const std::unique_ptr<GlobalValueSummary> &SummaryPtr) {
1265c0981da4SDimitry Andric // The mapping from OriginalId to GUID may return a GUID
1266c0981da4SDimitry Andric // that corresponds to a static variable. Filter it out here.
1267c0981da4SDimitry Andric // This can happen when
1268c0981da4SDimitry Andric // 1) There is a call to a library function which is not defined
1269c0981da4SDimitry Andric // in the index.
1270c0981da4SDimitry Andric // 2) There is a static variable with the OriginalGUID identical
1271c0981da4SDimitry Andric // to the GUID of the library function in 1);
1272c0981da4SDimitry Andric // When this happens the static variable in 2) will be found,
1273c0981da4SDimitry Andric // which needs to be filtered out.
1274c0981da4SDimitry Andric return SummaryPtr->getSummaryKind() ==
1275c0981da4SDimitry Andric GlobalValueSummary::GlobalVarKind;
1276c0981da4SDimitry Andric }))
1277c0981da4SDimitry Andric continue;
1278c0981da4SDimitry Andric EI.first = VI;
1279c0981da4SDimitry Andric }
1280c0981da4SDimitry Andric }
1281c0981da4SDimitry Andric
updateIndirectCalls(ModuleSummaryIndex & Index)1282c0981da4SDimitry Andric void llvm::updateIndirectCalls(ModuleSummaryIndex &Index) {
1283c0981da4SDimitry Andric for (const auto &Entry : Index) {
1284e3b55780SDimitry Andric for (const auto &S : Entry.second.SummaryList) {
1285c0981da4SDimitry Andric if (auto *FS = dyn_cast<FunctionSummary>(S.get()))
1286c0981da4SDimitry Andric updateValueInfoForIndirectCalls(Index, FS);
1287c0981da4SDimitry Andric }
1288c0981da4SDimitry Andric }
1289c0981da4SDimitry Andric }
1290c0981da4SDimitry Andric
computeDeadSymbolsAndUpdateIndirectCalls(ModuleSummaryIndex & Index,const DenseSet<GlobalValue::GUID> & GUIDPreservedSymbols,function_ref<PrevailingType (GlobalValue::GUID)> isPrevailing)1291c0981da4SDimitry Andric void llvm::computeDeadSymbolsAndUpdateIndirectCalls(
1292d288ef4cSDimitry Andric ModuleSummaryIndex &Index,
1293eb11fae6SDimitry Andric const DenseSet<GlobalValue::GUID> &GUIDPreservedSymbols,
1294eb11fae6SDimitry Andric function_ref<PrevailingType(GlobalValue::GUID)> isPrevailing) {
1295d288ef4cSDimitry Andric assert(!Index.withGlobalValueDeadStripping());
1296c0981da4SDimitry Andric if (!ComputeDead ||
12977e7b6700SDimitry Andric // Don't do anything when nothing is live, this is friendly with tests.
1298c0981da4SDimitry Andric GUIDPreservedSymbols.empty()) {
1299c0981da4SDimitry Andric // Still need to update indirect calls.
1300c0981da4SDimitry Andric updateIndirectCalls(Index);
1301d288ef4cSDimitry Andric return;
1302c0981da4SDimitry Andric }
1303d288ef4cSDimitry Andric unsigned LiveSymbols = 0;
1304c46e6a59SDimitry Andric SmallVector<ValueInfo, 128> Worklist;
1305c46e6a59SDimitry Andric Worklist.reserve(GUIDPreservedSymbols.size() * 2);
1306c46e6a59SDimitry Andric for (auto GUID : GUIDPreservedSymbols) {
1307c46e6a59SDimitry Andric ValueInfo VI = Index.getValueInfo(GUID);
1308c46e6a59SDimitry Andric if (!VI)
1309c46e6a59SDimitry Andric continue;
1310e3b55780SDimitry Andric for (const auto &S : VI.getSummaryList())
1311d288ef4cSDimitry Andric S->setLive(true);
13127e7b6700SDimitry Andric }
1313d288ef4cSDimitry Andric
13147e7b6700SDimitry Andric // Add values flagged in the index as live roots to the worklist.
1315eb11fae6SDimitry Andric for (const auto &Entry : Index) {
1316eb11fae6SDimitry Andric auto VI = Index.getValueInfo(Entry);
1317e3b55780SDimitry Andric for (const auto &S : Entry.second.SummaryList) {
1318c0981da4SDimitry Andric if (auto *FS = dyn_cast<FunctionSummary>(S.get()))
1319c0981da4SDimitry Andric updateValueInfoForIndirectCalls(Index, FS);
1320d288ef4cSDimitry Andric if (S->isLive()) {
1321eb11fae6SDimitry Andric LLVM_DEBUG(dbgs() << "Live root: " << VI << "\n");
1322eb11fae6SDimitry Andric Worklist.push_back(VI);
1323d288ef4cSDimitry Andric ++LiveSymbols;
1324d288ef4cSDimitry Andric break;
13257e7b6700SDimitry Andric }
1326eb11fae6SDimitry Andric }
1327c0981da4SDimitry Andric }
13287e7b6700SDimitry Andric
1329d288ef4cSDimitry Andric // Make value live and add it to the worklist if it was not live before.
13301d5ae102SDimitry Andric auto visit = [&](ValueInfo VI, bool IsAliasee) {
1331044eb2f6SDimitry Andric // FIXME: If we knew which edges were created for indirect call profiles,
1332044eb2f6SDimitry Andric // we could skip them here. Any that are live should be reached via
1333044eb2f6SDimitry Andric // other edges, e.g. reference edges. Otherwise, using a profile collected
1334044eb2f6SDimitry Andric // on a slightly different binary might provoke preserving, importing
1335044eb2f6SDimitry Andric // and ultimately promoting calls to functions not linked into this
1336044eb2f6SDimitry Andric // binary, which increases the binary size unnecessarily. Note that
1337044eb2f6SDimitry Andric // if this code changes, the importer needs to change so that edges
1338044eb2f6SDimitry Andric // to functions marked dead are skipped.
1339d8e91e46SDimitry Andric
1340e6d15924SDimitry Andric if (llvm::any_of(VI.getSummaryList(),
1341d8e91e46SDimitry Andric [](const std::unique_ptr<llvm::GlobalValueSummary> &S) {
1342d8e91e46SDimitry Andric return S->isLive();
1343d8e91e46SDimitry Andric }))
1344d288ef4cSDimitry Andric return;
1345eb11fae6SDimitry Andric
1346eb11fae6SDimitry Andric // We only keep live symbols that are known to be non-prevailing if any are
1347d8e91e46SDimitry Andric // available_externally, linkonceodr, weakodr. Those symbols are discarded
1348d8e91e46SDimitry Andric // later in the EliminateAvailableExternally pass and setting them to
1349d8e91e46SDimitry Andric // not-live could break downstreams users of liveness information (PR36483)
1350d8e91e46SDimitry Andric // or limit optimization opportunities.
1351eb11fae6SDimitry Andric if (isPrevailing(VI.getGUID()) == PrevailingType::No) {
1352d8e91e46SDimitry Andric bool KeepAliveLinkage = false;
1353eb11fae6SDimitry Andric bool Interposable = false;
1354e3b55780SDimitry Andric for (const auto &S : VI.getSummaryList()) {
1355d8e91e46SDimitry Andric if (S->linkage() == GlobalValue::AvailableExternallyLinkage ||
1356d8e91e46SDimitry Andric S->linkage() == GlobalValue::WeakODRLinkage ||
1357d8e91e46SDimitry Andric S->linkage() == GlobalValue::LinkOnceODRLinkage)
1358d8e91e46SDimitry Andric KeepAliveLinkage = true;
1359eb11fae6SDimitry Andric else if (GlobalValue::isInterposableLinkage(S->linkage()))
1360eb11fae6SDimitry Andric Interposable = true;
1361eb11fae6SDimitry Andric }
1362eb11fae6SDimitry Andric
13631d5ae102SDimitry Andric if (!IsAliasee) {
1364d8e91e46SDimitry Andric if (!KeepAliveLinkage)
1365eb11fae6SDimitry Andric return;
1366eb11fae6SDimitry Andric
1367eb11fae6SDimitry Andric if (Interposable)
1368d8e91e46SDimitry Andric report_fatal_error(
13691d5ae102SDimitry Andric "Interposable and available_externally/linkonce_odr/weak_odr "
13701d5ae102SDimitry Andric "symbol");
13711d5ae102SDimitry Andric }
1372eb11fae6SDimitry Andric }
1373eb11fae6SDimitry Andric
1374e3b55780SDimitry Andric for (const auto &S : VI.getSummaryList())
1375d288ef4cSDimitry Andric S->setLive(true);
1376d288ef4cSDimitry Andric ++LiveSymbols;
1377d288ef4cSDimitry Andric Worklist.push_back(VI);
1378d288ef4cSDimitry Andric };
1379d288ef4cSDimitry Andric
13807e7b6700SDimitry Andric while (!Worklist.empty()) {
1381c46e6a59SDimitry Andric auto VI = Worklist.pop_back_val();
1382e3b55780SDimitry Andric for (const auto &Summary : VI.getSummaryList()) {
1383e6d15924SDimitry Andric if (auto *AS = dyn_cast<AliasSummary>(Summary.get())) {
1384e6d15924SDimitry Andric // If this is an alias, visit the aliasee VI to ensure that all copies
1385e6d15924SDimitry Andric // are marked live and it is added to the worklist for further
1386e6d15924SDimitry Andric // processing of its references.
13871d5ae102SDimitry Andric visit(AS->getAliaseeVI(), true);
1388e6d15924SDimitry Andric continue;
1389e6d15924SDimitry Andric }
1390e6d15924SDimitry Andric for (auto Ref : Summary->refs())
13911d5ae102SDimitry Andric visit(Ref, false);
1392e6d15924SDimitry Andric if (auto *FS = dyn_cast<FunctionSummary>(Summary.get()))
1393d288ef4cSDimitry Andric for (auto Call : FS->calls())
13941d5ae102SDimitry Andric visit(Call.first, false);
13957e7b6700SDimitry Andric }
13967e7b6700SDimitry Andric }
1397d288ef4cSDimitry Andric Index.setWithGlobalValueDeadStripping();
1398d288ef4cSDimitry Andric
1399d288ef4cSDimitry Andric unsigned DeadSymbols = Index.size() - LiveSymbols;
1400eb11fae6SDimitry Andric LLVM_DEBUG(dbgs() << LiveSymbols << " symbols Live, and " << DeadSymbols
1401d288ef4cSDimitry Andric << " symbols Dead \n");
1402d288ef4cSDimitry Andric NumDeadSymbols += DeadSymbols;
1403d288ef4cSDimitry Andric NumLiveSymbols += LiveSymbols;
14047e7b6700SDimitry Andric }
14057e7b6700SDimitry Andric
1406d8e91e46SDimitry Andric // Compute dead symbols and propagate constants in combined index.
computeDeadSymbolsWithConstProp(ModuleSummaryIndex & Index,const DenseSet<GlobalValue::GUID> & GUIDPreservedSymbols,function_ref<PrevailingType (GlobalValue::GUID)> isPrevailing,bool ImportEnabled)1407d8e91e46SDimitry Andric void llvm::computeDeadSymbolsWithConstProp(
1408d8e91e46SDimitry Andric ModuleSummaryIndex &Index,
1409d8e91e46SDimitry Andric const DenseSet<GlobalValue::GUID> &GUIDPreservedSymbols,
1410d8e91e46SDimitry Andric function_ref<PrevailingType(GlobalValue::GUID)> isPrevailing,
1411d8e91e46SDimitry Andric bool ImportEnabled) {
1412c0981da4SDimitry Andric computeDeadSymbolsAndUpdateIndirectCalls(Index, GUIDPreservedSymbols,
1413c0981da4SDimitry Andric isPrevailing);
1414706b4fc4SDimitry Andric if (ImportEnabled)
1415e6d15924SDimitry Andric Index.propagateAttributes(GUIDPreservedSymbols);
1416d8e91e46SDimitry Andric }
1417d8e91e46SDimitry Andric
141801095a5dSDimitry Andric /// Compute the set of summaries needed for a ThinLTO backend compilation of
141901095a5dSDimitry Andric /// \p ModulePath.
gatherImportedSummariesForModule(StringRef ModulePath,const DenseMap<StringRef,GVSummaryMapTy> & ModuleToDefinedGVSummaries,const FunctionImporter::ImportMapTy & ImportList,std::map<std::string,GVSummaryMapTy> & ModuleToSummariesForIndex,GVSummaryPtrSet & DecSummaries)142001095a5dSDimitry Andric void llvm::gatherImportedSummariesForModule(
142101095a5dSDimitry Andric StringRef ModulePath,
1422b1c73532SDimitry Andric const DenseMap<StringRef, GVSummaryMapTy> &ModuleToDefinedGVSummaries,
1423b915e9e0SDimitry Andric const FunctionImporter::ImportMapTy &ImportList,
1424ac9a064cSDimitry Andric std::map<std::string, GVSummaryMapTy> &ModuleToSummariesForIndex,
1425ac9a064cSDimitry Andric GVSummaryPtrSet &DecSummaries) {
142601095a5dSDimitry Andric // Include all summaries from the importing module.
1427cfca06d7SDimitry Andric ModuleToSummariesForIndex[std::string(ModulePath)] =
142801095a5dSDimitry Andric ModuleToDefinedGVSummaries.lookup(ModulePath);
142901095a5dSDimitry Andric // Include summaries for imports.
1430e3b55780SDimitry Andric for (const auto &ILI : ImportList) {
1431b1c73532SDimitry Andric auto &SummariesForIndex = ModuleToSummariesForIndex[std::string(ILI.first)];
1432ac9a064cSDimitry Andric
143301095a5dSDimitry Andric const auto &DefinedGVSummaries =
1434b1c73532SDimitry Andric ModuleToDefinedGVSummaries.lookup(ILI.first);
1435ac9a064cSDimitry Andric for (const auto &[GUID, Type] : ILI.second) {
1436ac9a064cSDimitry Andric const auto &DS = DefinedGVSummaries.find(GUID);
143701095a5dSDimitry Andric assert(DS != DefinedGVSummaries.end() &&
143801095a5dSDimitry Andric "Expected a defined summary for imported global value");
1439ac9a064cSDimitry Andric if (Type == GlobalValueSummary::Declaration)
1440ac9a064cSDimitry Andric DecSummaries.insert(DS->second);
1441ac9a064cSDimitry Andric
1442ac9a064cSDimitry Andric SummariesForIndex[GUID] = DS->second;
144301095a5dSDimitry Andric }
144401095a5dSDimitry Andric }
144501095a5dSDimitry Andric }
144601095a5dSDimitry Andric
144701095a5dSDimitry Andric /// Emit the files \p ModulePath will import from into \p OutputFilename.
EmitImportsFiles(StringRef ModulePath,StringRef OutputFilename,const std::map<std::string,GVSummaryMapTy> & ModuleToSummariesForIndex)1448eb11fae6SDimitry Andric std::error_code llvm::EmitImportsFiles(
1449eb11fae6SDimitry Andric StringRef ModulePath, StringRef OutputFilename,
1450eb11fae6SDimitry Andric const std::map<std::string, GVSummaryMapTy> &ModuleToSummariesForIndex) {
145101095a5dSDimitry Andric std::error_code EC;
1452ac9a064cSDimitry Andric raw_fd_ostream ImportsOS(OutputFilename, EC, sys::fs::OpenFlags::OF_Text);
145301095a5dSDimitry Andric if (EC)
145401095a5dSDimitry Andric return EC;
1455e3b55780SDimitry Andric for (const auto &ILI : ModuleToSummariesForIndex)
1456eb11fae6SDimitry Andric // The ModuleToSummariesForIndex map includes an entry for the current
1457eb11fae6SDimitry Andric // Module (needed for writing out the index files). We don't want to
1458eb11fae6SDimitry Andric // include it in the imports file, however, so filter it out.
1459eb11fae6SDimitry Andric if (ILI.first != ModulePath)
1460eb11fae6SDimitry Andric ImportsOS << ILI.first << "\n";
146101095a5dSDimitry Andric return std::error_code();
146201095a5dSDimitry Andric }
146301095a5dSDimitry Andric
convertToDeclaration(GlobalValue & GV)1464eb11fae6SDimitry Andric bool llvm::convertToDeclaration(GlobalValue &GV) {
1465eb11fae6SDimitry Andric LLVM_DEBUG(dbgs() << "Converting to a declaration: `" << GV.getName()
1466eb11fae6SDimitry Andric << "\n");
1467eb11fae6SDimitry Andric if (Function *F = dyn_cast<Function>(&GV)) {
1468eb11fae6SDimitry Andric F->deleteBody();
1469eb11fae6SDimitry Andric F->clearMetadata();
1470eb11fae6SDimitry Andric F->setComdat(nullptr);
1471eb11fae6SDimitry Andric } else if (GlobalVariable *V = dyn_cast<GlobalVariable>(&GV)) {
1472eb11fae6SDimitry Andric V->setInitializer(nullptr);
1473eb11fae6SDimitry Andric V->setLinkage(GlobalValue::ExternalLinkage);
1474eb11fae6SDimitry Andric V->clearMetadata();
1475eb11fae6SDimitry Andric V->setComdat(nullptr);
1476eb11fae6SDimitry Andric } else {
1477eb11fae6SDimitry Andric GlobalValue *NewGV;
1478eb11fae6SDimitry Andric if (GV.getValueType()->isFunctionTy())
1479eb11fae6SDimitry Andric NewGV =
1480eb11fae6SDimitry Andric Function::Create(cast<FunctionType>(GV.getValueType()),
1481d8e91e46SDimitry Andric GlobalValue::ExternalLinkage, GV.getAddressSpace(),
1482d8e91e46SDimitry Andric "", GV.getParent());
1483eb11fae6SDimitry Andric else
1484eb11fae6SDimitry Andric NewGV =
1485eb11fae6SDimitry Andric new GlobalVariable(*GV.getParent(), GV.getValueType(),
1486eb11fae6SDimitry Andric /*isConstant*/ false, GlobalValue::ExternalLinkage,
1487eb11fae6SDimitry Andric /*init*/ nullptr, "",
1488eb11fae6SDimitry Andric /*insertbefore*/ nullptr, GV.getThreadLocalMode(),
1489eb11fae6SDimitry Andric GV.getType()->getAddressSpace());
1490eb11fae6SDimitry Andric NewGV->takeName(&GV);
1491eb11fae6SDimitry Andric GV.replaceAllUsesWith(NewGV);
1492eb11fae6SDimitry Andric return false;
1493eb11fae6SDimitry Andric }
1494cfca06d7SDimitry Andric if (!GV.isImplicitDSOLocal())
1495cfca06d7SDimitry Andric GV.setDSOLocal(false);
1496eb11fae6SDimitry Andric return true;
1497eb11fae6SDimitry Andric }
1498eb11fae6SDimitry Andric
thinLTOFinalizeInModule(Module & TheModule,const GVSummaryMapTy & DefinedGlobals,bool PropagateAttrs)1499c0981da4SDimitry Andric void llvm::thinLTOFinalizeInModule(Module &TheModule,
1500c0981da4SDimitry Andric const GVSummaryMapTy &DefinedGlobals,
1501c0981da4SDimitry Andric bool PropagateAttrs) {
1502e3b55780SDimitry Andric DenseSet<Comdat *> NonPrevailingComdats;
1503c0981da4SDimitry Andric auto FinalizeInModule = [&](GlobalValue &GV, bool Propagate = false) {
150401095a5dSDimitry Andric // See if the global summary analysis computed a new resolved linkage.
150501095a5dSDimitry Andric const auto &GS = DefinedGlobals.find(GV.getGUID());
150601095a5dSDimitry Andric if (GS == DefinedGlobals.end())
150701095a5dSDimitry Andric return;
1508c0981da4SDimitry Andric
1509c0981da4SDimitry Andric if (Propagate)
1510c0981da4SDimitry Andric if (FunctionSummary *FS = dyn_cast<FunctionSummary>(GS->second)) {
1511c0981da4SDimitry Andric if (Function *F = dyn_cast<Function>(&GV)) {
1512c0981da4SDimitry Andric // TODO: propagate ReadNone and ReadOnly.
1513c0981da4SDimitry Andric if (FS->fflags().ReadNone && !F->doesNotAccessMemory())
1514c0981da4SDimitry Andric F->setDoesNotAccessMemory();
1515c0981da4SDimitry Andric
1516c0981da4SDimitry Andric if (FS->fflags().ReadOnly && !F->onlyReadsMemory())
1517c0981da4SDimitry Andric F->setOnlyReadsMemory();
1518c0981da4SDimitry Andric
1519c0981da4SDimitry Andric if (FS->fflags().NoRecurse && !F->doesNotRecurse())
1520c0981da4SDimitry Andric F->setDoesNotRecurse();
1521c0981da4SDimitry Andric
1522c0981da4SDimitry Andric if (FS->fflags().NoUnwind && !F->doesNotThrow())
1523c0981da4SDimitry Andric F->setDoesNotThrow();
1524c0981da4SDimitry Andric }
1525c0981da4SDimitry Andric }
1526c0981da4SDimitry Andric
152701095a5dSDimitry Andric auto NewLinkage = GS->second->linkage();
1528d8e91e46SDimitry Andric if (GlobalValue::isLocalLinkage(GV.getLinkage()) ||
15291d5ae102SDimitry Andric // Don't internalize anything here, because the code below
15301d5ae102SDimitry Andric // lacks necessary correctness checks. Leave this job to
15311d5ae102SDimitry Andric // LLVM 'internalize' pass.
15321d5ae102SDimitry Andric GlobalValue::isLocalLinkage(NewLinkage) ||
1533d8e91e46SDimitry Andric // In case it was dead and already converted to declaration.
1534d8e91e46SDimitry Andric GV.isDeclaration())
1535ca089b24SDimitry Andric return;
15361d5ae102SDimitry Andric
1537344a3780SDimitry Andric // Set the potentially more constraining visibility computed from summaries.
1538344a3780SDimitry Andric // The DefaultVisibility condition is because older GlobalValueSummary does
1539344a3780SDimitry Andric // not record DefaultVisibility and we don't want to change protected/hidden
1540344a3780SDimitry Andric // to default.
1541344a3780SDimitry Andric if (GS->second->getVisibility() != GlobalValue::DefaultVisibility)
1542344a3780SDimitry Andric GV.setVisibility(GS->second->getVisibility());
1543344a3780SDimitry Andric
1544344a3780SDimitry Andric if (NewLinkage == GV.getLinkage())
1545344a3780SDimitry Andric return;
1546344a3780SDimitry Andric
154771d5a254SDimitry Andric // Check for a non-prevailing def that has interposable linkage
154871d5a254SDimitry Andric // (e.g. non-odr weak or linkonce). In that case we can't simply
154971d5a254SDimitry Andric // convert to available_externally, since it would lose the
155071d5a254SDimitry Andric // interposable property and possibly get inlined. Simply drop
155171d5a254SDimitry Andric // the definition in that case.
155271d5a254SDimitry Andric if (GlobalValue::isAvailableExternallyLinkage(NewLinkage) &&
1553eb11fae6SDimitry Andric GlobalValue::isInterposableLinkage(GV.getLinkage())) {
1554eb11fae6SDimitry Andric if (!convertToDeclaration(GV))
1555eb11fae6SDimitry Andric // FIXME: Change this to collect replaced GVs and later erase
1556d8e91e46SDimitry Andric // them from the parent module once thinLTOResolvePrevailingGUID is
1557eb11fae6SDimitry Andric // changed to enable this for aliases.
1558eb11fae6SDimitry Andric llvm_unreachable("Expected GV to be converted");
1559eb11fae6SDimitry Andric } else {
1560e6d15924SDimitry Andric // If all copies of the original symbol had global unnamed addr and
1561145449b1SDimitry Andric // linkonce_odr linkage, or if all of them had local unnamed addr linkage
1562145449b1SDimitry Andric // and are constants, then it should be an auto hide symbol. In that case
1563145449b1SDimitry Andric // the thin link would have marked it as CanAutoHide. Add hidden
1564145449b1SDimitry Andric // visibility to the symbol to preserve the property.
1565e6d15924SDimitry Andric if (NewLinkage == GlobalValue::WeakODRLinkage &&
1566e6d15924SDimitry Andric GS->second->canAutoHide()) {
1567145449b1SDimitry Andric assert(GV.canBeOmittedFromSymbolTable());
1568eb11fae6SDimitry Andric GV.setVisibility(GlobalValue::HiddenVisibility);
1569e6d15924SDimitry Andric }
1570eb11fae6SDimitry Andric
1571eb11fae6SDimitry Andric LLVM_DEBUG(dbgs() << "ODR fixing up linkage for `" << GV.getName()
1572eb11fae6SDimitry Andric << "` from " << GV.getLinkage() << " to " << NewLinkage
1573eb11fae6SDimitry Andric << "\n");
157401095a5dSDimitry Andric GV.setLinkage(NewLinkage);
157571d5a254SDimitry Andric }
157671d5a254SDimitry Andric // Remove declarations from comdats, including available_externally
1577b915e9e0SDimitry Andric // as this is a declaration for the linker, and will be dropped eventually.
1578b915e9e0SDimitry Andric // It is illegal for comdats to contain declarations.
1579b915e9e0SDimitry Andric auto *GO = dyn_cast_or_null<GlobalObject>(&GV);
1580e3b55780SDimitry Andric if (GO && GO->isDeclarationForLinker() && GO->hasComdat()) {
1581e3b55780SDimitry Andric if (GO->getComdat()->getName() == GO->getName())
1582e3b55780SDimitry Andric NonPrevailingComdats.insert(GO->getComdat());
1583b915e9e0SDimitry Andric GO->setComdat(nullptr);
1584e3b55780SDimitry Andric }
158501095a5dSDimitry Andric };
158601095a5dSDimitry Andric
158701095a5dSDimitry Andric // Process functions and global now
158801095a5dSDimitry Andric for (auto &GV : TheModule)
1589c0981da4SDimitry Andric FinalizeInModule(GV, PropagateAttrs);
159001095a5dSDimitry Andric for (auto &GV : TheModule.globals())
1591c0981da4SDimitry Andric FinalizeInModule(GV);
159201095a5dSDimitry Andric for (auto &GV : TheModule.aliases())
1593c0981da4SDimitry Andric FinalizeInModule(GV);
1594e3b55780SDimitry Andric
1595e3b55780SDimitry Andric // For a non-prevailing comdat, all its members must be available_externally.
1596e3b55780SDimitry Andric // FinalizeInModule has handled non-local-linkage GlobalValues. Here we handle
1597e3b55780SDimitry Andric // local linkage GlobalValues.
1598e3b55780SDimitry Andric if (NonPrevailingComdats.empty())
1599e3b55780SDimitry Andric return;
1600e3b55780SDimitry Andric for (auto &GO : TheModule.global_objects()) {
1601e3b55780SDimitry Andric if (auto *C = GO.getComdat(); C && NonPrevailingComdats.count(C)) {
1602e3b55780SDimitry Andric GO.setComdat(nullptr);
1603e3b55780SDimitry Andric GO.setLinkage(GlobalValue::AvailableExternallyLinkage);
1604e3b55780SDimitry Andric }
1605e3b55780SDimitry Andric }
1606e3b55780SDimitry Andric bool Changed;
1607e3b55780SDimitry Andric do {
1608e3b55780SDimitry Andric Changed = false;
1609e3b55780SDimitry Andric // If an alias references a GlobalValue in a non-prevailing comdat, change
1610e3b55780SDimitry Andric // it to available_externally. For simplicity we only handle GlobalValue and
1611e3b55780SDimitry Andric // ConstantExpr with a base object. ConstantExpr without a base object is
1612e3b55780SDimitry Andric // unlikely used in a COMDAT.
1613e3b55780SDimitry Andric for (auto &GA : TheModule.aliases()) {
1614e3b55780SDimitry Andric if (GA.hasAvailableExternallyLinkage())
1615e3b55780SDimitry Andric continue;
1616e3b55780SDimitry Andric GlobalObject *Obj = GA.getAliaseeObject();
1617e3b55780SDimitry Andric assert(Obj && "aliasee without an base object is unimplemented");
1618e3b55780SDimitry Andric if (Obj->hasAvailableExternallyLinkage()) {
1619e3b55780SDimitry Andric GA.setLinkage(GlobalValue::AvailableExternallyLinkage);
1620e3b55780SDimitry Andric Changed = true;
1621e3b55780SDimitry Andric }
1622e3b55780SDimitry Andric }
1623e3b55780SDimitry Andric } while (Changed);
162401095a5dSDimitry Andric }
162501095a5dSDimitry Andric
162601095a5dSDimitry Andric /// Run internalization on \p TheModule based on symmary analysis.
thinLTOInternalizeModule(Module & TheModule,const GVSummaryMapTy & DefinedGlobals)162701095a5dSDimitry Andric void llvm::thinLTOInternalizeModule(Module &TheModule,
162801095a5dSDimitry Andric const GVSummaryMapTy &DefinedGlobals) {
162901095a5dSDimitry Andric // Declare a callback for the internalize pass that will ask for every
163001095a5dSDimitry Andric // candidate GlobalValue if it can be internalized or not.
163101095a5dSDimitry Andric auto MustPreserveGV = [&](const GlobalValue &GV) -> bool {
16324b4fe385SDimitry Andric // It may be the case that GV is on a chain of an ifunc, its alias and
16334b4fe385SDimitry Andric // subsequent aliases. In this case, the summary for the value is not
16344b4fe385SDimitry Andric // available.
16354b4fe385SDimitry Andric if (isa<GlobalIFunc>(&GV) ||
16364b4fe385SDimitry Andric (isa<GlobalAlias>(&GV) &&
16374b4fe385SDimitry Andric isa<GlobalIFunc>(cast<GlobalAlias>(&GV)->getAliaseeObject())))
16384b4fe385SDimitry Andric return true;
16394b4fe385SDimitry Andric
164001095a5dSDimitry Andric // Lookup the linkage recorded in the summaries during global analysis.
16416b3f41edSDimitry Andric auto GS = DefinedGlobals.find(GV.getGUID());
164201095a5dSDimitry Andric if (GS == DefinedGlobals.end()) {
164301095a5dSDimitry Andric // Must have been promoted (possibly conservatively). Find original
164401095a5dSDimitry Andric // name so that we can access the correct summary and see if it can
164501095a5dSDimitry Andric // be internalized again.
164601095a5dSDimitry Andric // FIXME: Eventually we should control promotion instead of promoting
164701095a5dSDimitry Andric // and internalizing again.
164801095a5dSDimitry Andric StringRef OrigName =
164901095a5dSDimitry Andric ModuleSummaryIndex::getOriginalNameBeforePromote(GV.getName());
165001095a5dSDimitry Andric std::string OrigId = GlobalValue::getGlobalIdentifier(
165101095a5dSDimitry Andric OrigName, GlobalValue::InternalLinkage,
165201095a5dSDimitry Andric TheModule.getSourceFileName());
16536b3f41edSDimitry Andric GS = DefinedGlobals.find(GlobalValue::getGUID(OrigId));
165401095a5dSDimitry Andric if (GS == DefinedGlobals.end()) {
165501095a5dSDimitry Andric // Also check the original non-promoted non-globalized name. In some
165601095a5dSDimitry Andric // cases a preempted weak value is linked in as a local copy because
165701095a5dSDimitry Andric // it is referenced by an alias (IRLinker::linkGlobalValueProto).
165801095a5dSDimitry Andric // In that case, since it was originally not a local value, it was
165901095a5dSDimitry Andric // recorded in the index using the original name.
166001095a5dSDimitry Andric // FIXME: This may not be needed once PR27866 is fixed.
16616b3f41edSDimitry Andric GS = DefinedGlobals.find(GlobalValue::getGUID(OrigName));
166201095a5dSDimitry Andric assert(GS != DefinedGlobals.end());
166301095a5dSDimitry Andric }
16646b3f41edSDimitry Andric }
16656b3f41edSDimitry Andric return !GlobalValue::isLocalLinkage(GS->second->linkage());
166601095a5dSDimitry Andric };
166701095a5dSDimitry Andric
166801095a5dSDimitry Andric // FIXME: See if we can just internalize directly here via linkage changes
166901095a5dSDimitry Andric // based on the index, rather than invoking internalizeModule.
1670044eb2f6SDimitry Andric internalizeModule(TheModule, MustPreserveGV);
1671044eb2f6SDimitry Andric }
1672044eb2f6SDimitry Andric
1673044eb2f6SDimitry Andric /// Make alias a clone of its aliasee.
replaceAliasWithAliasee(Module * SrcModule,GlobalAlias * GA)1674044eb2f6SDimitry Andric static Function *replaceAliasWithAliasee(Module *SrcModule, GlobalAlias *GA) {
1675c0981da4SDimitry Andric Function *Fn = cast<Function>(GA->getAliaseeObject());
1676044eb2f6SDimitry Andric
1677044eb2f6SDimitry Andric ValueToValueMapTy VMap;
1678044eb2f6SDimitry Andric Function *NewFn = CloneFunction(Fn, VMap);
1679e6d15924SDimitry Andric // Clone should use the original alias's linkage, visibility and name, and we
1680e6d15924SDimitry Andric // ensure all uses of alias instead use the new clone (casted if necessary).
1681044eb2f6SDimitry Andric NewFn->setLinkage(GA->getLinkage());
1682e6d15924SDimitry Andric NewFn->setVisibility(GA->getVisibility());
1683b1c73532SDimitry Andric GA->replaceAllUsesWith(NewFn);
1684044eb2f6SDimitry Andric NewFn->takeName(GA);
1685044eb2f6SDimitry Andric return NewFn;
168601095a5dSDimitry Andric }
168701095a5dSDimitry Andric
1688d8e91e46SDimitry Andric // Internalize values that we marked with specific attribute
1689d8e91e46SDimitry Andric // in processGlobalForThinLTO.
internalizeGVsAfterImport(Module & M)1690e6d15924SDimitry Andric static void internalizeGVsAfterImport(Module &M) {
1691d8e91e46SDimitry Andric for (auto &GV : M.globals())
1692d8e91e46SDimitry Andric // Skip GVs which have been converted to declarations
1693d8e91e46SDimitry Andric // by dropDeadSymbols.
1694d8e91e46SDimitry Andric if (!GV.isDeclaration() && GV.hasAttribute("thinlto-internalize")) {
1695d8e91e46SDimitry Andric GV.setLinkage(GlobalValue::InternalLinkage);
1696d8e91e46SDimitry Andric GV.setVisibility(GlobalValue::DefaultVisibility);
1697d8e91e46SDimitry Andric }
1698d8e91e46SDimitry Andric }
1699d8e91e46SDimitry Andric
1700dd58ef01SDimitry Andric // Automatically import functions in Module \p DestModule based on the summaries
1701dd58ef01SDimitry Andric // index.
importFunctions(Module & DestModule,const FunctionImporter::ImportMapTy & ImportList)1702b915e9e0SDimitry Andric Expected<bool> FunctionImporter::importFunctions(
170371d5a254SDimitry Andric Module &DestModule, const FunctionImporter::ImportMapTy &ImportList) {
1704eb11fae6SDimitry Andric LLVM_DEBUG(dbgs() << "Starting import for Module "
1705dd58ef01SDimitry Andric << DestModule.getModuleIdentifier() << "\n");
1706eb11fae6SDimitry Andric unsigned ImportedCount = 0, ImportedGVCount = 0;
1707dd58ef01SDimitry Andric
170871d5a254SDimitry Andric IRMover Mover(DestModule);
1709dd58ef01SDimitry Andric // Do the actual import of functions now, one Module at a time
171001095a5dSDimitry Andric std::set<StringRef> ModuleNameOrderedList;
1711e3b55780SDimitry Andric for (const auto &FunctionsToImportPerModule : ImportList) {
1712b1c73532SDimitry Andric ModuleNameOrderedList.insert(FunctionsToImportPerModule.first);
171301095a5dSDimitry Andric }
1714ac9a064cSDimitry Andric
1715ac9a064cSDimitry Andric auto getImportType = [&](const FunctionsToImportTy &GUIDToImportType,
1716ac9a064cSDimitry Andric GlobalValue::GUID GUID)
1717ac9a064cSDimitry Andric -> std::optional<GlobalValueSummary::ImportKind> {
1718ac9a064cSDimitry Andric auto Iter = GUIDToImportType.find(GUID);
1719ac9a064cSDimitry Andric if (Iter == GUIDToImportType.end())
1720ac9a064cSDimitry Andric return std::nullopt;
1721ac9a064cSDimitry Andric return Iter->second;
1722ac9a064cSDimitry Andric };
1723ac9a064cSDimitry Andric
1724e3b55780SDimitry Andric for (const auto &Name : ModuleNameOrderedList) {
1725dd58ef01SDimitry Andric // Get the module for the import
172601095a5dSDimitry Andric const auto &FunctionsToImportPerModule = ImportList.find(Name);
172701095a5dSDimitry Andric assert(FunctionsToImportPerModule != ImportList.end());
1728b915e9e0SDimitry Andric Expected<std::unique_ptr<Module>> SrcModuleOrErr = ModuleLoader(Name);
1729b915e9e0SDimitry Andric if (!SrcModuleOrErr)
1730b915e9e0SDimitry Andric return SrcModuleOrErr.takeError();
1731b915e9e0SDimitry Andric std::unique_ptr<Module> SrcModule = std::move(*SrcModuleOrErr);
1732dd58ef01SDimitry Andric assert(&DestModule.getContext() == &SrcModule->getContext() &&
1733dd58ef01SDimitry Andric "Context mismatch");
1734dd58ef01SDimitry Andric
173501095a5dSDimitry Andric // If modules were created with lazy metadata loading, materialize it
173601095a5dSDimitry Andric // now, before linking it (otherwise this will be a noop).
1737b915e9e0SDimitry Andric if (Error Err = SrcModule->materializeMetadata())
1738b915e9e0SDimitry Andric return std::move(Err);
173901095a5dSDimitry Andric
174001095a5dSDimitry Andric auto &ImportGUIDs = FunctionsToImportPerModule->second;
1741ac9a064cSDimitry Andric
174201095a5dSDimitry Andric // Find the globals to import
174371d5a254SDimitry Andric SetVector<GlobalValue *> GlobalsToImport;
174401095a5dSDimitry Andric for (Function &F : *SrcModule) {
174501095a5dSDimitry Andric if (!F.hasName())
174601095a5dSDimitry Andric continue;
174701095a5dSDimitry Andric auto GUID = F.getGUID();
1748ac9a064cSDimitry Andric auto MaybeImportType = getImportType(ImportGUIDs, GUID);
1749ac9a064cSDimitry Andric
1750ac9a064cSDimitry Andric bool ImportDefinition =
1751ac9a064cSDimitry Andric (MaybeImportType &&
1752ac9a064cSDimitry Andric (*MaybeImportType == GlobalValueSummary::Definition));
1753ac9a064cSDimitry Andric
1754ac9a064cSDimitry Andric LLVM_DEBUG(dbgs() << (MaybeImportType ? "Is" : "Not")
1755ac9a064cSDimitry Andric << " importing function"
1756ac9a064cSDimitry Andric << (ImportDefinition
1757ac9a064cSDimitry Andric ? " definition "
1758ac9a064cSDimitry Andric : (MaybeImportType ? " declaration " : " "))
1759eb11fae6SDimitry Andric << GUID << " " << F.getName() << " from "
176001095a5dSDimitry Andric << SrcModule->getSourceFileName() << "\n");
1761ac9a064cSDimitry Andric if (ImportDefinition) {
1762b915e9e0SDimitry Andric if (Error Err = F.materialize())
1763b915e9e0SDimitry Andric return std::move(Err);
1764ac9a064cSDimitry Andric // MemProf should match function's definition and summary,
1765ac9a064cSDimitry Andric // 'thinlto_src_module' is needed.
1766ac9a064cSDimitry Andric if (EnableImportMetadata || EnableMemProfContextDisambiguation) {
1767ac9a064cSDimitry Andric // Add 'thinlto_src_module' and 'thinlto_src_file' metadata for
1768ac9a064cSDimitry Andric // statistics and debugging.
176901095a5dSDimitry Andric F.setMetadata(
177001095a5dSDimitry Andric "thinlto_src_module",
1771044eb2f6SDimitry Andric MDNode::get(DestModule.getContext(),
1772044eb2f6SDimitry Andric {MDString::get(DestModule.getContext(),
1773ac9a064cSDimitry Andric SrcModule->getModuleIdentifier())}));
1774ac9a064cSDimitry Andric F.setMetadata(
1775ac9a064cSDimitry Andric "thinlto_src_file",
1776ac9a064cSDimitry Andric MDNode::get(DestModule.getContext(),
1777ac9a064cSDimitry Andric {MDString::get(DestModule.getContext(),
177801095a5dSDimitry Andric SrcModule->getSourceFileName())}));
177901095a5dSDimitry Andric }
178001095a5dSDimitry Andric GlobalsToImport.insert(&F);
178101095a5dSDimitry Andric }
178201095a5dSDimitry Andric }
178301095a5dSDimitry Andric for (GlobalVariable &GV : SrcModule->globals()) {
178401095a5dSDimitry Andric if (!GV.hasName())
178501095a5dSDimitry Andric continue;
178601095a5dSDimitry Andric auto GUID = GV.getGUID();
1787ac9a064cSDimitry Andric auto MaybeImportType = getImportType(ImportGUIDs, GUID);
1788ac9a064cSDimitry Andric
1789ac9a064cSDimitry Andric bool ImportDefinition =
1790ac9a064cSDimitry Andric (MaybeImportType &&
1791ac9a064cSDimitry Andric (*MaybeImportType == GlobalValueSummary::Definition));
1792ac9a064cSDimitry Andric
1793ac9a064cSDimitry Andric LLVM_DEBUG(dbgs() << (MaybeImportType ? "Is" : "Not")
1794ac9a064cSDimitry Andric << " importing global"
1795ac9a064cSDimitry Andric << (ImportDefinition
1796ac9a064cSDimitry Andric ? " definition "
1797ac9a064cSDimitry Andric : (MaybeImportType ? " declaration " : " "))
1798eb11fae6SDimitry Andric << GUID << " " << GV.getName() << " from "
179901095a5dSDimitry Andric << SrcModule->getSourceFileName() << "\n");
1800ac9a064cSDimitry Andric if (ImportDefinition) {
1801b915e9e0SDimitry Andric if (Error Err = GV.materialize())
1802b915e9e0SDimitry Andric return std::move(Err);
1803eb11fae6SDimitry Andric ImportedGVCount += GlobalsToImport.insert(&GV);
180401095a5dSDimitry Andric }
180501095a5dSDimitry Andric }
180601095a5dSDimitry Andric for (GlobalAlias &GA : SrcModule->aliases()) {
18074b4fe385SDimitry Andric if (!GA.hasName() || isa<GlobalIFunc>(GA.getAliaseeObject()))
180801095a5dSDimitry Andric continue;
180901095a5dSDimitry Andric auto GUID = GA.getGUID();
1810ac9a064cSDimitry Andric auto MaybeImportType = getImportType(ImportGUIDs, GUID);
1811ac9a064cSDimitry Andric
1812ac9a064cSDimitry Andric bool ImportDefinition =
1813ac9a064cSDimitry Andric (MaybeImportType &&
1814ac9a064cSDimitry Andric (*MaybeImportType == GlobalValueSummary::Definition));
1815ac9a064cSDimitry Andric
1816ac9a064cSDimitry Andric LLVM_DEBUG(dbgs() << (MaybeImportType ? "Is" : "Not")
1817ac9a064cSDimitry Andric << " importing alias"
1818ac9a064cSDimitry Andric << (ImportDefinition
1819ac9a064cSDimitry Andric ? " definition "
1820ac9a064cSDimitry Andric : (MaybeImportType ? " declaration " : " "))
1821eb11fae6SDimitry Andric << GUID << " " << GA.getName() << " from "
182201095a5dSDimitry Andric << SrcModule->getSourceFileName() << "\n");
1823ac9a064cSDimitry Andric if (ImportDefinition) {
1824b915e9e0SDimitry Andric if (Error Err = GA.materialize())
1825b915e9e0SDimitry Andric return std::move(Err);
1826044eb2f6SDimitry Andric // Import alias as a copy of its aliasee.
1827c0981da4SDimitry Andric GlobalObject *GO = GA.getAliaseeObject();
1828c0981da4SDimitry Andric if (Error Err = GO->materialize())
1829044eb2f6SDimitry Andric return std::move(Err);
1830044eb2f6SDimitry Andric auto *Fn = replaceAliasWithAliasee(SrcModule.get(), &GA);
1831c0981da4SDimitry Andric LLVM_DEBUG(dbgs() << "Is importing aliasee fn " << GO->getGUID() << " "
1832c0981da4SDimitry Andric << GO->getName() << " from "
1833044eb2f6SDimitry Andric << SrcModule->getSourceFileName() << "\n");
1834ac9a064cSDimitry Andric if (EnableImportMetadata || EnableMemProfContextDisambiguation) {
1835ac9a064cSDimitry Andric // Add 'thinlto_src_module' and 'thinlto_src_file' metadata for
1836ac9a064cSDimitry Andric // statistics and debugging.
1837044eb2f6SDimitry Andric Fn->setMetadata(
1838044eb2f6SDimitry Andric "thinlto_src_module",
1839044eb2f6SDimitry Andric MDNode::get(DestModule.getContext(),
1840044eb2f6SDimitry Andric {MDString::get(DestModule.getContext(),
1841ac9a064cSDimitry Andric SrcModule->getModuleIdentifier())}));
1842ac9a064cSDimitry Andric Fn->setMetadata(
1843ac9a064cSDimitry Andric "thinlto_src_file",
1844ac9a064cSDimitry Andric MDNode::get(DestModule.getContext(),
1845ac9a064cSDimitry Andric {MDString::get(DestModule.getContext(),
1846044eb2f6SDimitry Andric SrcModule->getSourceFileName())}));
1847044eb2f6SDimitry Andric }
1848044eb2f6SDimitry Andric GlobalsToImport.insert(Fn);
184901095a5dSDimitry Andric }
185001095a5dSDimitry Andric }
1851dd58ef01SDimitry Andric
18527e7b6700SDimitry Andric // Upgrade debug info after we're done materializing all the globals and we
18537e7b6700SDimitry Andric // have loaded all the required metadata!
18547e7b6700SDimitry Andric UpgradeDebugInfo(*SrcModule);
18557e7b6700SDimitry Andric
1856cfca06d7SDimitry Andric // Set the partial sample profile ratio in the profile summary module flag
1857cfca06d7SDimitry Andric // of the imported source module, if applicable, so that the profile summary
1858cfca06d7SDimitry Andric // module flag will match with that of the destination module when it's
1859cfca06d7SDimitry Andric // imported.
1860cfca06d7SDimitry Andric SrcModule->setPartialSampleProfileRatio(Index);
1861cfca06d7SDimitry Andric
1862dd58ef01SDimitry Andric // Link in the specified functions.
1863cfca06d7SDimitry Andric if (renameModuleForThinLTO(*SrcModule, Index, ClearDSOLocalOnDeclarations,
1864cfca06d7SDimitry Andric &GlobalsToImport))
186501095a5dSDimitry Andric return true;
186601095a5dSDimitry Andric
186701095a5dSDimitry Andric if (PrintImports) {
186801095a5dSDimitry Andric for (const auto *GV : GlobalsToImport)
186901095a5dSDimitry Andric dbgs() << DestModule.getSourceFileName() << ": Import " << GV->getName()
187001095a5dSDimitry Andric << " from " << SrcModule->getSourceFileName() << "\n";
187101095a5dSDimitry Andric }
187201095a5dSDimitry Andric
1873145449b1SDimitry Andric if (Error Err = Mover.move(std::move(SrcModule),
1874145449b1SDimitry Andric GlobalsToImport.getArrayRef(), nullptr,
187571d5a254SDimitry Andric /*IsPerformingImport=*/true))
18767fa27ce4SDimitry Andric return createStringError(errc::invalid_argument,
18777fa27ce4SDimitry Andric Twine("Function Import: link error: ") +
1878cfca06d7SDimitry Andric toString(std::move(Err)));
1879dd58ef01SDimitry Andric
188001095a5dSDimitry Andric ImportedCount += GlobalsToImport.size();
18817e7b6700SDimitry Andric NumImportedModules++;
1882dd58ef01SDimitry Andric }
1883dd58ef01SDimitry Andric
1884e6d15924SDimitry Andric internalizeGVsAfterImport(DestModule);
1885d8e91e46SDimitry Andric
1886eb11fae6SDimitry Andric NumImportedFunctions += (ImportedCount - ImportedGVCount);
1887eb11fae6SDimitry Andric NumImportedGlobalVars += ImportedGVCount;
1888dd58ef01SDimitry Andric
1889ac9a064cSDimitry Andric // TODO: Print counters for definitions and declarations in the debugging log.
1890eb11fae6SDimitry Andric LLVM_DEBUG(dbgs() << "Imported " << ImportedCount - ImportedGVCount
1891eb11fae6SDimitry Andric << " functions for Module "
1892eb11fae6SDimitry Andric << DestModule.getModuleIdentifier() << "\n");
1893eb11fae6SDimitry Andric LLVM_DEBUG(dbgs() << "Imported " << ImportedGVCount
1894eb11fae6SDimitry Andric << " global variables for Module "
1895dd58ef01SDimitry Andric << DestModule.getModuleIdentifier() << "\n");
1896dd58ef01SDimitry Andric return ImportedCount;
1897dd58ef01SDimitry Andric }
1898dd58ef01SDimitry Andric
doImportingForModuleForTest(Module & M,function_ref<bool (GlobalValue::GUID,const GlobalValueSummary *)> isPrevailing)1899b1c73532SDimitry Andric static bool doImportingForModuleForTest(
19007fa27ce4SDimitry Andric Module &M, function_ref<bool(GlobalValue::GUID, const GlobalValueSummary *)>
19017fa27ce4SDimitry Andric isPrevailing) {
1902b915e9e0SDimitry Andric if (SummaryFile.empty())
1903b915e9e0SDimitry Andric report_fatal_error("error: -function-import requires -summary-file\n");
1904b915e9e0SDimitry Andric Expected<std::unique_ptr<ModuleSummaryIndex>> IndexPtrOrErr =
1905b915e9e0SDimitry Andric getModuleSummaryIndexForFile(SummaryFile);
1906b915e9e0SDimitry Andric if (!IndexPtrOrErr) {
1907b915e9e0SDimitry Andric logAllUnhandledErrors(IndexPtrOrErr.takeError(), errs(),
1908b915e9e0SDimitry Andric "Error loading file '" + SummaryFile + "': ");
1909dd58ef01SDimitry Andric return false;
1910dd58ef01SDimitry Andric }
1911b915e9e0SDimitry Andric std::unique_ptr<ModuleSummaryIndex> Index = std::move(*IndexPtrOrErr);
1912dd58ef01SDimitry Andric
191301095a5dSDimitry Andric // First step is collecting the import list.
191401095a5dSDimitry Andric FunctionImporter::ImportMapTy ImportList;
1915044eb2f6SDimitry Andric // If requested, simply import all functions in the index. This is used
1916044eb2f6SDimitry Andric // when testing distributed backend handling via the opt tool, when
1917044eb2f6SDimitry Andric // we have distributed indexes containing exactly the summaries to import.
1918044eb2f6SDimitry Andric if (ImportAllIndex)
1919b1c73532SDimitry Andric ComputeCrossModuleImportForModuleFromIndexForTest(M.getModuleIdentifier(),
19207fa27ce4SDimitry Andric *Index, ImportList);
1921b1c73532SDimitry Andric else
1922b1c73532SDimitry Andric ComputeCrossModuleImportForModuleForTest(M.getModuleIdentifier(),
1923b1c73532SDimitry Andric isPrevailing, *Index, ImportList);
192401095a5dSDimitry Andric
1925b915e9e0SDimitry Andric // Conservatively mark all internal values as promoted. This interface is
1926b915e9e0SDimitry Andric // only used when doing importing via the function importing pass. The pass
1927b915e9e0SDimitry Andric // is only enabled when testing importing via the 'opt' tool, which does
1928b915e9e0SDimitry Andric // not do the ThinLink that would normally determine what values to promote.
1929b915e9e0SDimitry Andric for (auto &I : *Index) {
1930c46e6a59SDimitry Andric for (auto &S : I.second.SummaryList) {
1931b915e9e0SDimitry Andric if (GlobalValue::isLocalLinkage(S->linkage()))
1932b915e9e0SDimitry Andric S->setLinkage(GlobalValue::ExternalLinkage);
1933b915e9e0SDimitry Andric }
1934b915e9e0SDimitry Andric }
1935b915e9e0SDimitry Andric
193601095a5dSDimitry Andric // Next we need to promote to global scope and rename any local values that
1937050e163aSDimitry Andric // are potentially exported to other modules.
1938b60736ecSDimitry Andric if (renameModuleForThinLTO(M, *Index, /*ClearDSOLocalOnDeclarations=*/false,
1939cfca06d7SDimitry Andric /*GlobalsToImport=*/nullptr)) {
1940050e163aSDimitry Andric errs() << "Error renaming module\n";
19417fa27ce4SDimitry Andric return true;
1942050e163aSDimitry Andric }
1943050e163aSDimitry Andric
1944dd58ef01SDimitry Andric // Perform the import now.
1945dd58ef01SDimitry Andric auto ModuleLoader = [&M](StringRef Identifier) {
1946cfca06d7SDimitry Andric return loadFile(std::string(Identifier), M.getContext());
1947dd58ef01SDimitry Andric };
1948cfca06d7SDimitry Andric FunctionImporter Importer(*Index, ModuleLoader,
1949cfca06d7SDimitry Andric /*ClearDSOLocalOnDeclarations=*/false);
195071d5a254SDimitry Andric Expected<bool> Result = Importer.importFunctions(M, ImportList);
1951b915e9e0SDimitry Andric
1952b915e9e0SDimitry Andric // FIXME: Probably need to propagate Errors through the pass manager.
1953b915e9e0SDimitry Andric if (!Result) {
1954b915e9e0SDimitry Andric logAllUnhandledErrors(Result.takeError(), errs(),
1955b915e9e0SDimitry Andric "Error importing module: ");
19567fa27ce4SDimitry Andric return true;
1957b915e9e0SDimitry Andric }
1958b915e9e0SDimitry Andric
19597fa27ce4SDimitry Andric return true;
1960b915e9e0SDimitry Andric }
1961b915e9e0SDimitry Andric
run(Module & M,ModuleAnalysisManager & AM)1962b915e9e0SDimitry Andric PreservedAnalyses FunctionImportPass::run(Module &M,
1963b915e9e0SDimitry Andric ModuleAnalysisManager &AM) {
19647fa27ce4SDimitry Andric // This is only used for testing the function import pass via opt, where we
19657fa27ce4SDimitry Andric // don't have prevailing information from the LTO context available, so just
19667fa27ce4SDimitry Andric // conservatively assume everything is prevailing (which is fine for the very
19677fa27ce4SDimitry Andric // limited use of prevailing checking in this pass).
19687fa27ce4SDimitry Andric auto isPrevailing = [](GlobalValue::GUID, const GlobalValueSummary *) {
19697fa27ce4SDimitry Andric return true;
19707fa27ce4SDimitry Andric };
1971b1c73532SDimitry Andric if (!doImportingForModuleForTest(M, isPrevailing))
1972b915e9e0SDimitry Andric return PreservedAnalyses::all();
1973b915e9e0SDimitry Andric
1974b915e9e0SDimitry Andric return PreservedAnalyses::none();
1975b915e9e0SDimitry Andric }
1976