1//===- ThinLTOBitcodeWriter.cpp - Bitcode writing pass for ThinLTO --------===//
2//
3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6//
7//===----------------------------------------------------------------------===//
8
9#include "llvm/Transforms/IPO/ThinLTOBitcodeWriter.h"
10#include "llvm/Analysis/BasicAliasAnalysis.h"
11#include "llvm/Analysis/BlockFrequencyInfo.h"
12#include "llvm/Analysis/ModuleSummaryAnalysis.h"
13#include "llvm/Analysis/ProfileSummaryInfo.h"
14#include "llvm/Bitcode/BitcodeWriter.h"
15#include "llvm/IR/Constants.h"
16#include "llvm/IR/DebugInfo.h"
17#include "llvm/IR/Instructions.h"
18#include "llvm/IR/Intrinsics.h"
19#include "llvm/IR/Module.h"
20#include "llvm/IR/PassManager.h"
21#include "llvm/Support/raw_ostream.h"
22#include "llvm/Transforms/IPO.h"
23#include "llvm/Transforms/IPO/FunctionAttrs.h"
24#include "llvm/Transforms/IPO/FunctionImport.h"
25#include "llvm/Transforms/IPO/LowerTypeTests.h"
26#include "llvm/Transforms/Utils/Cloning.h"
27#include "llvm/Transforms/Utils/ModuleUtils.h"
28using namespace llvm;
29
30namespace {
31
32// Promote each local-linkage entity defined by ExportM and used by ImportM by
33// changing visibility and appending the given ModuleId.
34void promoteInternals(Module &ExportM, Module &ImportM, StringRef ModuleId,
35 SetVector<GlobalValue *> *PromoteExtra = nullptr) {
36 DenseMap<const Comdat *, Comdat *> RenamedComdats;
37 for (auto &ExportGV : ExportM.global_values()) {
38 if (!ExportGV.hasLocalLinkage())
39 continue;
40
41 auto Name = ExportGV.getName();
42 GlobalValue *ImportGV = nullptr;
43 const bool MustPromote = PromoteExtra && PromoteExtra->count(key: &ExportGV);
44 if (!MustPromote) {
45 ImportGV = ImportM.getNamedValue(Name);
46 if (!ImportGV)
47 continue;
48 ImportGV->removeDeadConstantUsers();
49 if (ImportGV->use_empty()) {
50 ImportGV->eraseFromParent();
51 continue;
52 }
53 }
54
55 std::string OldName = Name.str();
56 std::string NewName = (Name + ModuleId).str();
57
58 if (const auto *C = ExportGV.getComdat())
59 if (C->getName() == Name)
60 RenamedComdats.try_emplace(Key: C, Args: ExportM.getOrInsertComdat(Name: NewName));
61
62 Constant *Aliasee = &ExportGV;
63 while (auto *GA = dyn_cast<GlobalAlias>(Val: Aliasee))
64 Aliasee = GA->getAliasee();
65
66 // We must use the function's value type (FunctionType), not ptr - hence
67 // ExportGV.getValueType() rather than getType(). Otherwise, when an
68 // internal coroutine is imported into another module, IRMover sees a
69 // non-function value type for the unimported alias and materializes it as
70 // an external GlobalVariable rather than a Function declaration. That
71 // violates the verifier requirement that the coroutine argument of
72 // @llvm.coro.id must refer to a function. We could "pierce through" by
73 // stripping pointers, and cases other than coro do that, but this is
74 // cleaner.
75 auto *ExternalAlias = GlobalAlias::create(
76 Ty: ExportGV.getValueType(), AddressSpace: ExportGV.getAddressSpace(),
77 Linkage: GlobalValue::ExternalLinkage, Name: NewName, Aliasee, Parent: &ExportM);
78 ExternalAlias->setVisibility(GlobalValue::HiddenVisibility);
79
80 if (MustPromote) {
81 ExportGV.replaceUsesWithIf(
82 New: ExternalAlias, ShouldReplace: [](Use &U) { return !isa<GlobalAlias>(Val: U.getUser()); });
83 PromoteExtra->remove(X: &ExportGV);
84 PromoteExtra->insert(X: ExternalAlias);
85 }
86
87 if (ImportGV) {
88 ImportGV->setName(NewName);
89 ImportGV->setVisibility(GlobalValue::HiddenVisibility);
90 ImportGV->reassignGUID();
91 }
92 }
93
94 if (!RenamedComdats.empty())
95 for (auto &GO : ExportM.global_objects())
96 if (auto *C = GO.getComdat()) {
97 auto Replacement = RenamedComdats.find(Val: C);
98 if (Replacement != RenamedComdats.end())
99 GO.setComdat(Replacement->second);
100 }
101}
102
103// Promote all internal (i.e. distinct) type ids used by the module by replacing
104// them with external type ids formed using the module id.
105//
106// Note that this needs to be done before we clone the module because each clone
107// will receive its own set of distinct metadata nodes.
108void promoteTypeIds(Module &M, StringRef ModuleId) {
109 DenseMap<Metadata *, Metadata *> LocalToGlobal;
110 auto ExternalizeTypeId = [&](CallInst *CI, unsigned ArgNo) {
111 Metadata *MD =
112 cast<MetadataAsValue>(Val: CI->getArgOperand(i: ArgNo))->getMetadata();
113
114 if (isa<MDNode>(Val: MD) && cast<MDNode>(Val: MD)->isDistinct()) {
115 Metadata *&GlobalMD = LocalToGlobal[MD];
116 if (!GlobalMD) {
117 std::string NewName = (Twine(LocalToGlobal.size()) + ModuleId).str();
118 GlobalMD = MDString::get(Context&: M.getContext(), Str: NewName);
119 }
120
121 CI->setArgOperand(i: ArgNo,
122 v: MetadataAsValue::get(Context&: M.getContext(), MD: GlobalMD));
123 }
124 };
125
126 if (Function *TypeTestFunc =
127 Intrinsic::getDeclarationIfExists(M: &M, id: Intrinsic::type_test)) {
128 for (const Use &U : TypeTestFunc->uses()) {
129 auto CI = cast<CallInst>(Val: U.getUser());
130 ExternalizeTypeId(CI, 1);
131 }
132 }
133
134 if (Function *PublicTypeTestFunc =
135 Intrinsic::getDeclarationIfExists(M: &M, id: Intrinsic::public_type_test)) {
136 for (const Use &U : PublicTypeTestFunc->uses()) {
137 auto CI = cast<CallInst>(Val: U.getUser());
138 ExternalizeTypeId(CI, 1);
139 }
140 }
141
142 if (Function *TypeCheckedLoadFunc =
143 Intrinsic::getDeclarationIfExists(M: &M, id: Intrinsic::type_checked_load)) {
144 for (const Use &U : TypeCheckedLoadFunc->uses()) {
145 auto CI = cast<CallInst>(Val: U.getUser());
146 ExternalizeTypeId(CI, 2);
147 }
148 }
149
150 if (Function *TypeCheckedLoadRelativeFunc = Intrinsic::getDeclarationIfExists(
151 M: &M, id: Intrinsic::type_checked_load_relative)) {
152 for (const Use &U : TypeCheckedLoadRelativeFunc->uses()) {
153 auto CI = cast<CallInst>(Val: U.getUser());
154 ExternalizeTypeId(CI, 2);
155 }
156 }
157
158 for (GlobalObject &GO : M.global_objects()) {
159 SmallVector<MDNode *, 1> MDs;
160 GO.getMetadata(KindID: LLVMContext::MD_type, MDs);
161
162 GO.eraseMetadata(KindID: LLVMContext::MD_type);
163 for (auto *MD : MDs) {
164 auto I = LocalToGlobal.find(Val: MD->getOperand(I: 1));
165 if (I == LocalToGlobal.end()) {
166 GO.addMetadata(KindID: LLVMContext::MD_type, MD&: *MD);
167 continue;
168 }
169 GO.addMetadata(
170 KindID: LLVMContext::MD_type,
171 MD&: *MDNode::get(Context&: M.getContext(), MDs: {MD->getOperand(I: 0), I->second}));
172 }
173
174 SmallVector<MDNode *, 1> CGMDs;
175 GO.getMetadata(KindID: LLVMContext::MD_callgraph, MDs&: CGMDs);
176
177 GO.eraseMetadata(KindID: LLVMContext::MD_callgraph);
178 for (auto *MD : CGMDs) {
179 if (MD->getNumOperands() == 1) {
180 auto I = LocalToGlobal.find(Val: MD->getOperand(I: 0));
181 if (I == LocalToGlobal.end()) {
182 GO.addMetadata(KindID: LLVMContext::MD_callgraph, MD&: *MD);
183 continue;
184 }
185 GO.addMetadata(KindID: LLVMContext::MD_callgraph,
186 MD&: *MDNode::get(Context&: M.getContext(), MDs: {I->second}));
187 }
188 }
189 }
190}
191
192// Drop unused globals, and drop type information from function declarations.
193// FIXME: If we made functions typeless then there would be no need to do this.
194void simplifyExternals(Module &M) {
195 FunctionType *EmptyFT =
196 FunctionType::get(Result: Type::getVoidTy(C&: M.getContext()), isVarArg: false);
197
198 for (Function &F : llvm::make_early_inc_range(Range&: M)) {
199 if (F.isDeclaration() && F.use_empty()) {
200 F.eraseFromParent();
201 continue;
202 }
203
204 if (!F.isDeclaration() || F.getFunctionType() == EmptyFT ||
205 // Changing the type of an intrinsic may invalidate the IR.
206 F.getName().starts_with(Prefix: "llvm."))
207 continue;
208
209 Function *NewF = Function::Create(Ty: EmptyFT, Linkage: GlobalValue::ExternalLinkage,
210 AddrSpace: F.getAddressSpace(), N: "", M: &M);
211 NewF->copyAttributesFrom(Src: &F);
212 // Only copy function attribtues.
213 NewF->setAttributes(AttributeList::get(C&: M.getContext(),
214 Index: AttributeList::FunctionIndex,
215 Attrs: F.getAttributes().getFnAttrs()));
216 NewF->takeName(V: &F);
217 NewF->setMetadata(KindID: LLVMContext::MD_guid,
218 Node: F.getMetadata(KindID: LLVMContext::MD_guid));
219 F.replaceAllUsesWith(V: NewF);
220 F.eraseFromParent();
221 }
222
223 for (GlobalIFunc &I : llvm::make_early_inc_range(Range: M.ifuncs())) {
224 if (I.use_empty())
225 I.eraseFromParent();
226 else
227 assert(I.getResolverFunction() && "ifunc misses its resolver function");
228 }
229
230 for (GlobalVariable &GV : llvm::make_early_inc_range(Range: M.globals())) {
231 if (GV.isDeclaration() && GV.use_empty()) {
232 GV.eraseFromParent();
233 continue;
234 }
235 }
236}
237
238static void
239filterModule(Module *M,
240 function_ref<bool(const GlobalValue *)> ShouldKeepDefinition) {
241 std::vector<GlobalValue *> V;
242 for (GlobalValue &GV : M->global_values())
243 if (!ShouldKeepDefinition(&GV))
244 V.push_back(x: &GV);
245
246 for (GlobalValue *GV : V)
247 if (!convertToDeclaration(GV&: *GV))
248 GV->eraseFromParent();
249}
250
251void forEachVirtualFunction(Constant *C, function_ref<void(Function *)> Fn) {
252 if (auto *F = dyn_cast<Function>(Val: C))
253 return Fn(F);
254 if (isa<GlobalValue>(Val: C))
255 return;
256 for (Value *Op : C->operands())
257 forEachVirtualFunction(C: cast<Constant>(Val: Op), Fn);
258}
259
260// Clone any @llvm[.compiler].used over to the new module and append
261// values whose defs were cloned into that module.
262static void cloneUsedGlobalVariables(const Module &SrcM, Module &DestM,
263 bool CompilerUsed) {
264 SmallVector<GlobalValue *, 4> Used, NewUsed;
265 // First collect those in the llvm[.compiler].used set.
266 collectUsedGlobalVariables(M: SrcM, Vec&: Used, CompilerUsed);
267 // Next build a set of the equivalent values defined in DestM.
268 for (auto *V : Used) {
269 auto *GV = DestM.getNamedValue(Name: V->getName());
270 if (GV && !GV->isDeclaration())
271 NewUsed.push_back(Elt: GV);
272 }
273 // Finally, add them to a llvm[.compiler].used variable in DestM.
274 if (CompilerUsed)
275 appendToCompilerUsed(M&: DestM, Values: NewUsed);
276 else
277 appendToUsed(M&: DestM, Values: NewUsed);
278}
279
280#ifndef NDEBUG
281static bool enableUnifiedLTO(Module &M) {
282 bool UnifiedLTO = false;
283 if (auto *MD =
284 mdconst::extract_or_null<ConstantInt>(M.getModuleFlag("UnifiedLTO")))
285 UnifiedLTO = MD->getZExtValue();
286 return UnifiedLTO;
287}
288#endif
289
290bool mustEmitToMergedModule(const GlobalValue *GV) {
291 // The __cfi_check definition is filled in by the CrossDSOCFI pass which
292 // runs only in the merged module.
293 return GV->getName() == "__cfi_check";
294}
295
296// If it's possible to split M into regular and thin LTO parts, do so and write
297// a multi-module bitcode file with the two parts to OS. Otherwise, write only a
298// regular LTO bitcode file to OS.
299void splitAndWriteThinLTOBitcode(
300 raw_ostream &OS, raw_ostream *ThinLinkOS,
301 function_ref<AAResults &(Function &)> AARGetter,
302 function_ref<const BlockFrequencyInfo &(Function &)> BFIGetter, Module &M,
303 const bool ShouldPreserveUseListOrder) {
304 std::string ModuleId = getUniqueModuleId(M: &M);
305 if (ModuleId.empty()) {
306 assert(!enableUnifiedLTO(M));
307 // We couldn't generate a module ID for this module, write it out as a
308 // regular LTO module with an index for summary-based dead stripping.
309 ProfileSummaryInfo PSI(M);
310 M.addModuleFlag(Behavior: Module::Error, Key: "ThinLTO", Val: uint32_t(0));
311 ModuleSummaryIndex Index = buildModuleSummaryIndex(M, GetBFICallback: nullptr, PSI: &PSI);
312 WriteBitcodeToFile(M, Out&: OS, ShouldPreserveUseListOrder, Index: &Index,
313 /*UnifiedLTO=*/GenerateHash: false);
314
315 if (ThinLinkOS)
316 // We don't have a ThinLTO part, but still write the module to the
317 // ThinLinkOS if requested so that the expected output file is produced.
318 WriteBitcodeToFile(M, Out&: *ThinLinkOS, ShouldPreserveUseListOrder, Index: &Index,
319 /*UnifiedLTO=*/GenerateHash: false);
320
321 return;
322 }
323
324 promoteTypeIds(M, ModuleId);
325
326 // Collect the set of virtual functions that are eligible for virtual constant
327 // propagation. Each eligible function must not access memory, must return
328 // an integer of width <=64 bits, must take at least one argument, must not
329 // use its first argument (assumed to be "this") and all arguments other than
330 // the first one must be of <=64 bit integer type.
331 //
332 // Note that we test whether this copy of the function is readnone, rather
333 // than testing function attributes, which must hold for any copy of the
334 // function, even a less optimized version substituted at link time. This is
335 // sound because the virtual constant propagation optimizations effectively
336 // inline all implementations of the virtual function into each call site,
337 // rather than using function attributes to perform local optimization.
338 DenseSet<const Function *> EligibleVirtualFns;
339 // If any member of a comdat lives in MergedM, put all members of that
340 // comdat in MergedM to keep the comdat together.
341 DenseSet<const Comdat *> MergedMComdats;
342 for (GlobalVariable &GV : M.globals())
343 if (!GV.isDeclaration() && lowertypetests::hasTypeMetadata(GO: GV)) {
344 if (const auto *C = GV.getComdat())
345 MergedMComdats.insert(V: C);
346 forEachVirtualFunction(C: GV.getInitializer(), Fn: [&](Function *F) {
347 auto *RT = dyn_cast<IntegerType>(Val: F->getReturnType());
348 if (!RT || RT->getBitWidth() > 64 || F->arg_empty() ||
349 !F->arg_begin()->use_empty())
350 return;
351 for (auto &Arg : drop_begin(RangeOrContainer: F->args())) {
352 auto *ArgT = dyn_cast<IntegerType>(Val: Arg.getType());
353 if (!ArgT || ArgT->getBitWidth() > 64)
354 return;
355 }
356 if (!F->isDeclaration() &&
357 computeFunctionBodyMemoryAccess(F&: *F, AAR&: AARGetter(*F))
358 .doesNotAccessMemory())
359 EligibleVirtualFns.insert(V: F);
360 });
361 }
362
363 ValueToValueMapTy VMap;
364 std::unique_ptr<Module> MergedM(
365 CloneModule(M, VMap, ShouldCloneDefinition: [&](const GlobalValue *GV) -> bool {
366 if (const auto *C = GV->getComdat())
367 if (MergedMComdats.count(V: C))
368 return true;
369 if (mustEmitToMergedModule(GV))
370 return true;
371 if (auto *F = dyn_cast<Function>(Val: GV))
372 return EligibleVirtualFns.count(V: F);
373 if (auto *GVar =
374 dyn_cast_or_null<GlobalVariable>(Val: GV->getAliaseeObject()))
375 return lowertypetests::hasTypeMetadata(GO: *GVar);
376 return false;
377 }));
378 StripDebugInfo(M&: *MergedM);
379 MergedM->removeModuleInlineAsm();
380
381 // Clone any llvm.*used globals to ensure the included values are
382 // not deleted.
383 cloneUsedGlobalVariables(SrcM: M, DestM&: *MergedM, /*CompilerUsed*/ false);
384 cloneUsedGlobalVariables(SrcM: M, DestM&: *MergedM, /*CompilerUsed*/ true);
385
386 for (Function &F : *MergedM)
387 if (!F.isDeclaration() && !mustEmitToMergedModule(GV: &F)) {
388 // Reset the linkage of all functions eligible for virtual constant
389 // propagation. The canonical definitions live in the thin LTO module so
390 // that they can be imported.
391 F.setLinkage(GlobalValue::AvailableExternallyLinkage);
392 F.setComdat(nullptr);
393 }
394
395 SetVector<GlobalValue *> CfiFunctions = lowertypetests::findCfiFunctions(M);
396
397 // Remove all globals with type metadata, globals with comdats that live in
398 // MergedM, and aliases pointing to such globals from the thin LTO module.
399 filterModule(M: &M, ShouldKeepDefinition: [&](const GlobalValue *GV) {
400 if (auto *GVar = dyn_cast_or_null<GlobalVariable>(Val: GV->getAliaseeObject()))
401 if (lowertypetests::hasTypeMetadata(GO: *GVar))
402 return false;
403 if (const auto *C = GV->getComdat())
404 if (MergedMComdats.count(V: C))
405 return false;
406 if (mustEmitToMergedModule(GV))
407 return false;
408 return true;
409 });
410
411 // CfiFunctions contains only symbols from M. promoteInternals tries to find
412 // match values from its first argument (the "exporting module") in
413 // CfiFunctions. So we only need CfiFunctions for the second promotion (M ->
414 // MergedM)
415 promoteInternals(ExportM&: *MergedM, ImportM&: M, ModuleId, PromoteExtra: nullptr);
416 promoteInternals(ExportM&: M, ImportM&: *MergedM, ModuleId, PromoteExtra: &CfiFunctions);
417
418 // FIXME: Try to re-use PSI from the original module here.
419 ProfileSummaryInfo PSI(M);
420
421 lowertypetests::createCfiMetadata(DestM&: *MergedM, SrcM: M, CfiFunctions: CfiFunctions.getArrayRef(),
422 PSI, BFIGetter);
423
424 simplifyExternals(M&: *MergedM);
425
426 // FIXME: Try to re-use BSI from the original module here.
427 ModuleSummaryIndex Index = buildModuleSummaryIndex(M, GetBFICallback: nullptr, PSI: &PSI);
428
429 // Mark the merged module as requiring full LTO. We still want an index for
430 // it though, so that it can participate in summary-based dead stripping.
431 MergedM->addModuleFlag(Behavior: Module::Error, Key: "ThinLTO", Val: uint32_t(0));
432 ModuleSummaryIndex MergedMIndex =
433 buildModuleSummaryIndex(M: *MergedM, GetBFICallback: nullptr, PSI: &PSI);
434
435 SmallVector<char, 0> Buffer;
436
437 BitcodeWriter W(Buffer);
438 // Save the module hash produced for the full bitcode, which will
439 // be used in the backends, and use that in the minimized bitcode
440 // produced for the full link.
441 ModuleHash ModHash = {._M_elems: {0}};
442 W.writeModule(M, ShouldPreserveUseListOrder, Index: &Index,
443 /*GenerateHash=*/true, ModHash: &ModHash);
444 W.writeModule(M: *MergedM, ShouldPreserveUseListOrder, Index: &MergedMIndex);
445 W.writeSymtab();
446 W.writeStrtab();
447 OS << Buffer;
448
449 // If a minimized bitcode module was requested for the thin link, only
450 // the information that is needed by thin link will be written in the
451 // given OS (the merged module will be written as usual).
452 if (ThinLinkOS) {
453 Buffer.clear();
454 BitcodeWriter W2(Buffer);
455 StripDebugInfo(M);
456 W2.writeThinLinkBitcode(M, Index, ModHash);
457 W2.writeModule(M: *MergedM, /*ShouldPreserveUseListOrder=*/false,
458 Index: &MergedMIndex);
459 W2.writeSymtab();
460 W2.writeStrtab();
461 *ThinLinkOS << Buffer;
462 }
463}
464
465// Check if the LTO Unit splitting has been enabled.
466bool enableSplitLTOUnit(Module &M) {
467 bool EnableSplitLTOUnit = false;
468 if (auto *MD = mdconst::extract_or_null<ConstantInt>(
469 MD: M.getModuleFlag(Key: "EnableSplitLTOUnit")))
470 EnableSplitLTOUnit = MD->getZExtValue();
471 return EnableSplitLTOUnit;
472}
473
474// Returns whether this module needs to be split (if splitting is enabled).
475bool requiresSplit(Module &M) {
476 for (auto &GO : M.global_objects()) {
477 if (GO.hasMetadata(KindID: LLVMContext::MD_type))
478 return true;
479 if (mustEmitToMergedModule(GV: &GO))
480 return true;
481 }
482 return false;
483}
484
485bool writeThinLTOBitcode(
486 raw_ostream &OS, raw_ostream *ThinLinkOS,
487 function_ref<AAResults &(Function &)> AARGetter,
488 function_ref<const BlockFrequencyInfo &(Function &)> BFIGetter, Module &M,
489 const ModuleSummaryIndex *Index, const bool ShouldPreserveUseListOrder) {
490 std::unique_ptr<ModuleSummaryIndex> NewIndex = nullptr;
491 // See if this module needs to be split. If so, we try to split it
492 // or at least promote type ids to enable WPD.
493 if (requiresSplit(M)) {
494 if (enableSplitLTOUnit(M)) {
495 splitAndWriteThinLTOBitcode(OS, ThinLinkOS, AARGetter, BFIGetter, M,
496 ShouldPreserveUseListOrder);
497 return true;
498 }
499 // Promote type ids as needed for index-based WPD.
500 std::string ModuleId = getUniqueModuleId(M: &M);
501 if (!ModuleId.empty()) {
502 promoteTypeIds(M, ModuleId);
503 // Need to rebuild the index so that it contains type metadata
504 // for the newly promoted type ids.
505 // FIXME: Probably should not bother building the index at all
506 // in the caller of writeThinLTOBitcode (which does so via the
507 // ModuleSummaryIndexAnalysis pass), since we have to rebuild it
508 // anyway whenever there is type metadata (here or in
509 // splitAndWriteThinLTOBitcode). Just always build it once via the
510 // buildModuleSummaryIndex when Module(s) are ready.
511 ProfileSummaryInfo PSI(M);
512 NewIndex = std::make_unique<ModuleSummaryIndex>(
513 args: buildModuleSummaryIndex(M, GetBFICallback: nullptr, PSI: &PSI));
514 Index = NewIndex.get();
515 }
516 }
517
518 // Write it out as an unsplit ThinLTO module.
519
520 // Save the module hash produced for the full bitcode, which will
521 // be used in the backends, and use that in the minimized bitcode
522 // produced for the full link.
523 ModuleHash ModHash = {._M_elems: {0}};
524 WriteBitcodeToFile(M, Out&: OS, ShouldPreserveUseListOrder, Index,
525 /*GenerateHash=*/true, ModHash: &ModHash);
526 // If a minimized bitcode module was requested for the thin link, only
527 // the information that is needed by thin link will be written in the
528 // given OS.
529 if (ThinLinkOS && Index)
530 writeThinLinkBitcodeToFile(M, Out&: *ThinLinkOS, Index: *Index, ModHash);
531 return false;
532}
533
534} // anonymous namespace
535
536PreservedAnalyses
537llvm::ThinLTOBitcodeWriterPass::run(Module &M, ModuleAnalysisManager &AM) {
538 FunctionAnalysisManager &FAM =
539 AM.getResult<FunctionAnalysisManagerModuleProxy>(IR&: M).getManager();
540
541 bool Changed = writeThinLTOBitcode(
542 OS, ThinLinkOS,
543 AARGetter: [&FAM](Function &F) -> AAResults & {
544 return FAM.getResult<AAManager>(IR&: F);
545 },
546 BFIGetter: [&FAM](Function &F) -> const BlockFrequencyInfo & {
547 return FAM.getResult<BlockFrequencyAnalysis>(IR&: F);
548 },
549 M, Index: &AM.getResult<ModuleSummaryIndexAnalysis>(IR&: M),
550 ShouldPreserveUseListOrder);
551
552 return Changed ? PreservedAnalyses::none() : PreservedAnalyses::all();
553}
554