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