summaryrefslogtreecommitdiff
path: root/lib/Transforms/IPO/ThinLTOBitcodeWriter.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'lib/Transforms/IPO/ThinLTOBitcodeWriter.cpp')
-rw-r--r--lib/Transforms/IPO/ThinLTOBitcodeWriter.cpp139
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 {