diff options
Diffstat (limited to 'lib/Transforms/IPO/ThinLTOBitcodeWriter.cpp')
-rw-r--r-- | lib/Transforms/IPO/ThinLTOBitcodeWriter.cpp | 139 |
1 files changed, 77 insertions, 62 deletions
diff --git a/lib/Transforms/IPO/ThinLTOBitcodeWriter.cpp b/lib/Transforms/IPO/ThinLTOBitcodeWriter.cpp index caffc03339c4..8fe7ae1282cc 100644 --- a/lib/Transforms/IPO/ThinLTOBitcodeWriter.cpp +++ b/lib/Transforms/IPO/ThinLTOBitcodeWriter.cpp @@ -18,11 +18,13 @@ #include "llvm/IR/Intrinsics.h" #include "llvm/IR/Module.h" #include "llvm/IR/PassManager.h" +#include "llvm/Object/ModuleSymbolTable.h" #include "llvm/Pass.h" #include "llvm/Support/ScopedPrinter.h" #include "llvm/Support/raw_ostream.h" #include "llvm/Transforms/IPO.h" #include "llvm/Transforms/IPO/FunctionAttrs.h" +#include "llvm/Transforms/IPO/FunctionImport.h" #include "llvm/Transforms/Utils/Cloning.h" #include "llvm/Transforms/Utils/ModuleUtils.h" using namespace llvm; @@ -128,8 +130,7 @@ void promoteTypeIds(Module &M, StringRef ModuleId) { } GO.addMetadata( LLVMContext::MD_type, - *MDNode::get(M.getContext(), - ArrayRef<Metadata *>{MD->getOperand(0), I->second})); + *MDNode::get(M.getContext(), {MD->getOperand(0), I->second})); } } } @@ -169,46 +170,17 @@ void simplifyExternals(Module &M) { } } -void filterModule( - Module *M, function_ref<bool(const GlobalValue *)> ShouldKeepDefinition) { - for (Module::alias_iterator I = M->alias_begin(), E = M->alias_end(); - I != E;) { - GlobalAlias *GA = &*I++; - if (ShouldKeepDefinition(GA)) - continue; - - GlobalObject *GO; - if (GA->getValueType()->isFunctionTy()) - GO = Function::Create(cast<FunctionType>(GA->getValueType()), - GlobalValue::ExternalLinkage, "", M); - else - GO = new GlobalVariable( - *M, GA->getValueType(), false, GlobalValue::ExternalLinkage, - nullptr, "", nullptr, - GA->getThreadLocalMode(), GA->getType()->getAddressSpace()); - GO->takeName(GA); - GA->replaceAllUsesWith(GO); - GA->eraseFromParent(); - } - - for (Function &F : *M) { - if (ShouldKeepDefinition(&F)) - continue; - - F.deleteBody(); - F.setComdat(nullptr); - F.clearMetadata(); - } - - for (GlobalVariable &GV : M->globals()) { - if (ShouldKeepDefinition(&GV)) - continue; - - GV.setInitializer(nullptr); - GV.setLinkage(GlobalValue::ExternalLinkage); - GV.setComdat(nullptr); - GV.clearMetadata(); - } +static void +filterModule(Module *M, + function_ref<bool(const GlobalValue *)> ShouldKeepDefinition) { + std::vector<GlobalValue *> V; + for (GlobalValue &GV : M->global_values()) + if (!ShouldKeepDefinition(&GV)) + V.push_back(&GV); + + for (GlobalValue *GV : V) + if (!convertToDeclaration(*GV)) + GV->eraseFromParent(); } void forEachVirtualFunction(Constant *C, function_ref<void(Function *)> Fn) { @@ -228,13 +200,19 @@ void splitAndWriteThinLTOBitcode( function_ref<AAResults &(Function &)> AARGetter, Module &M) { std::string ModuleId = getUniqueModuleId(&M); if (ModuleId.empty()) { - // We couldn't generate a module ID for this module, just write it out as a - // regular LTO module. - WriteBitcodeToFile(&M, OS); + // We couldn't generate a module ID for this module, write it out as a + // regular LTO module with an index for summary-based dead stripping. + ProfileSummaryInfo PSI(M); + M.addModuleFlag(Module::Error, "ThinLTO", uint32_t(0)); + ModuleSummaryIndex Index = buildModuleSummaryIndex(M, nullptr, &PSI); + WriteBitcodeToFile(M, OS, /*ShouldPreserveUseListOrder=*/false, &Index); + if (ThinLinkOS) // We don't have a ThinLTO part, but still write the module to the // ThinLinkOS if requested so that the expected output file is produced. - WriteBitcodeToFile(&M, *ThinLinkOS); + WriteBitcodeToFile(M, *ThinLinkOS, /*ShouldPreserveUseListOrder=*/false, + &Index); + return; } @@ -243,10 +221,8 @@ void splitAndWriteThinLTOBitcode( // Returns whether a global has attached type metadata. Such globals may // participate in CFI or whole-program devirtualization, so they need to // appear in the merged module instead of the thin LTO module. - auto HasTypeMetadata = [&](const GlobalObject *GO) { - SmallVector<MDNode *, 1> MDs; - GO->getMetadata(LLVMContext::MD_type, MDs); - return !MDs.empty(); + auto HasTypeMetadata = [](const GlobalObject *GO) { + return GO->hasMetadata(LLVMContext::MD_type); }; // Collect the set of virtual functions that are eligible for virtual constant @@ -287,7 +263,7 @@ void splitAndWriteThinLTOBitcode( ValueToValueMapTy VMap; std::unique_ptr<Module> MergedM( - CloneModule(&M, VMap, [&](const GlobalValue *GV) -> bool { + CloneModule(M, VMap, [&](const GlobalValue *GV) -> bool { if (const auto *C = GV->getComdat()) if (MergedMComdats.count(C)) return true; @@ -298,6 +274,7 @@ void splitAndWriteThinLTOBitcode( return false; })); StripDebugInfo(*MergedM); + MergedM->setModuleInlineAsm(""); for (Function &F : *MergedM) if (!F.isDeclaration()) { @@ -328,13 +305,13 @@ void splitAndWriteThinLTOBitcode( promoteInternals(*MergedM, M, ModuleId, CfiFunctions); promoteInternals(M, *MergedM, ModuleId, CfiFunctions); + auto &Ctx = MergedM->getContext(); SmallVector<MDNode *, 8> CfiFunctionMDs; for (auto V : CfiFunctions) { Function &F = *cast<Function>(V); SmallVector<MDNode *, 2> Types; F.getMetadata(LLVMContext::MD_type, Types); - auto &Ctx = MergedM->getContext(); SmallVector<Metadata *, 4> Elts; Elts.push_back(MDString::get(Ctx, F.getName())); CfiFunctionLinkage Linkage; @@ -357,6 +334,47 @@ void splitAndWriteThinLTOBitcode( NMD->addOperand(MD); } + SmallVector<MDNode *, 8> FunctionAliases; + for (auto &A : M.aliases()) { + if (!isa<Function>(A.getAliasee())) + continue; + + auto *F = cast<Function>(A.getAliasee()); + + Metadata *Elts[] = { + MDString::get(Ctx, A.getName()), + MDString::get(Ctx, F->getName()), + ConstantAsMetadata::get( + ConstantInt::get(Type::getInt8Ty(Ctx), A.getVisibility())), + ConstantAsMetadata::get( + ConstantInt::get(Type::getInt8Ty(Ctx), A.isWeakForLinker())), + }; + + FunctionAliases.push_back(MDTuple::get(Ctx, Elts)); + } + + if (!FunctionAliases.empty()) { + NamedMDNode *NMD = MergedM->getOrInsertNamedMetadata("aliases"); + for (auto MD : FunctionAliases) + NMD->addOperand(MD); + } + + SmallVector<MDNode *, 8> Symvers; + ModuleSymbolTable::CollectAsmSymvers(M, [&](StringRef Name, StringRef Alias) { + Function *F = M.getFunction(Name); + if (!F || F->use_empty()) + return; + + Symvers.push_back(MDTuple::get( + Ctx, {MDString::get(Ctx, Name), MDString::get(Ctx, Alias)})); + }); + + if (!Symvers.empty()) { + NamedMDNode *NMD = MergedM->getOrInsertNamedMetadata("symvers"); + for (auto MD : Symvers) + NMD->addOperand(MD); + } + simplifyExternals(*MergedM); // FIXME: Try to re-use BSI and PFI from the original module here. @@ -376,10 +394,9 @@ void splitAndWriteThinLTOBitcode( // be used in the backends, and use that in the minimized bitcode // produced for the full link. ModuleHash ModHash = {{0}}; - W.writeModule(&M, /*ShouldPreserveUseListOrder=*/false, &Index, + W.writeModule(M, /*ShouldPreserveUseListOrder=*/false, &Index, /*GenerateHash=*/true, &ModHash); - W.writeModule(MergedM.get(), /*ShouldPreserveUseListOrder=*/false, - &MergedMIndex); + W.writeModule(*MergedM, /*ShouldPreserveUseListOrder=*/false, &MergedMIndex); W.writeSymtab(); W.writeStrtab(); OS << Buffer; @@ -391,8 +408,8 @@ void splitAndWriteThinLTOBitcode( Buffer.clear(); BitcodeWriter W2(Buffer); StripDebugInfo(M); - W2.writeThinLinkBitcode(&M, Index, ModHash); - W2.writeModule(MergedM.get(), /*ShouldPreserveUseListOrder=*/false, + W2.writeThinLinkBitcode(M, Index, ModHash); + W2.writeModule(*MergedM, /*ShouldPreserveUseListOrder=*/false, &MergedMIndex); W2.writeSymtab(); W2.writeStrtab(); @@ -402,10 +419,8 @@ void splitAndWriteThinLTOBitcode( // Returns whether this module needs to be split because it uses type metadata. bool requiresSplit(Module &M) { - SmallVector<MDNode *, 1> MDs; for (auto &GO : M.global_objects()) { - GO.getMetadata(LLVMContext::MD_type, MDs); - if (!MDs.empty()) + if (GO.hasMetadata(LLVMContext::MD_type)) return true; } @@ -425,13 +440,13 @@ void writeThinLTOBitcode(raw_ostream &OS, raw_ostream *ThinLinkOS, // be used in the backends, and use that in the minimized bitcode // produced for the full link. ModuleHash ModHash = {{0}}; - WriteBitcodeToFile(&M, OS, /*ShouldPreserveUseListOrder=*/false, Index, + WriteBitcodeToFile(M, OS, /*ShouldPreserveUseListOrder=*/false, Index, /*GenerateHash=*/true, &ModHash); // If a minimized bitcode module was requested for the thin link, only // the information that is needed by thin link will be written in the // given OS. if (ThinLinkOS && Index) - WriteThinLinkBitcodeToFile(&M, *ThinLinkOS, *Index, ModHash); + WriteThinLinkBitcodeToFile(M, *ThinLinkOS, *Index, ModHash); } class WriteThinLTOBitcode : public ModulePass { |