forked from OSchip/llvm-project
[LTO] Fix cloning of llvm*.used when splitting module
Refines the fix in 3c4c205060
to only
put globals whose defs were cloned into the split regular LTO module
on the cloned llvm*.used globals. This avoids an issue where one of the
attached values was a local that was promoted in the original module
after the module was cloned. We only need to have the values defined in
the new module on those globals.
Fixes PR49251.
Differential Revision: https://reviews.llvm.org/D97013
This commit is contained in:
parent
309b00a42e
commit
fde55a9c9b
|
@ -195,6 +195,29 @@ void forEachVirtualFunction(Constant *C, function_ref<void(Function *)> Fn) {
|
||||||
forEachVirtualFunction(cast<Constant>(Op), Fn);
|
forEachVirtualFunction(cast<Constant>(Op), Fn);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Clone any @llvm[.compiler].used over to the new module and append
|
||||||
|
// values whose defs were cloned into that module.
|
||||||
|
static void cloneUsedGlobalVariables(const Module &SrcM, Module &DestM,
|
||||||
|
bool CompilerUsed) {
|
||||||
|
SmallPtrSet<GlobalValue *, 8> Used;
|
||||||
|
SmallPtrSet<GlobalValue *, 8> NewUsed;
|
||||||
|
// First collect those in the llvm[.compiler].used set.
|
||||||
|
collectUsedGlobalVariables(SrcM, Used, CompilerUsed);
|
||||||
|
// Next build a set of the equivalent values defined in DestM.
|
||||||
|
for (auto *V : Used) {
|
||||||
|
auto *GV = DestM.getNamedValue(V->getName());
|
||||||
|
if (GV && !GV->isDeclaration())
|
||||||
|
NewUsed.insert(GV);
|
||||||
|
}
|
||||||
|
// Finally, add them to a llvm[.compiler].used variable in DestM.
|
||||||
|
if (CompilerUsed)
|
||||||
|
appendToCompilerUsed(
|
||||||
|
DestM, std::vector<GlobalValue *>(NewUsed.begin(), NewUsed.end()));
|
||||||
|
else
|
||||||
|
appendToUsed(DestM,
|
||||||
|
std::vector<GlobalValue *>(NewUsed.begin(), NewUsed.end()));
|
||||||
|
}
|
||||||
|
|
||||||
// If it's possible to split M into regular and thin LTO parts, do so and write
|
// If it's possible to split M into regular and thin LTO parts, do so and write
|
||||||
// a multi-module bitcode file with the two parts to OS. Otherwise, write only a
|
// a multi-module bitcode file with the two parts to OS. Otherwise, write only a
|
||||||
// regular LTO bitcode file to OS.
|
// regular LTO bitcode file to OS.
|
||||||
|
@ -275,11 +298,6 @@ void splitAndWriteThinLTOBitcode(
|
||||||
ValueToValueMapTy VMap;
|
ValueToValueMapTy VMap;
|
||||||
std::unique_ptr<Module> MergedM(
|
std::unique_ptr<Module> MergedM(
|
||||||
CloneModule(M, VMap, [&](const GlobalValue *GV) -> bool {
|
CloneModule(M, VMap, [&](const GlobalValue *GV) -> bool {
|
||||||
// Clone any llvm.*used globals to ensure the included values are
|
|
||||||
// not deleted.
|
|
||||||
if (GV->getName() == "llvm.used" ||
|
|
||||||
GV->getName() == "llvm.compiler.used")
|
|
||||||
return true;
|
|
||||||
if (const auto *C = GV->getComdat())
|
if (const auto *C = GV->getComdat())
|
||||||
if (MergedMComdats.count(C))
|
if (MergedMComdats.count(C))
|
||||||
return true;
|
return true;
|
||||||
|
@ -292,6 +310,11 @@ void splitAndWriteThinLTOBitcode(
|
||||||
StripDebugInfo(*MergedM);
|
StripDebugInfo(*MergedM);
|
||||||
MergedM->setModuleInlineAsm("");
|
MergedM->setModuleInlineAsm("");
|
||||||
|
|
||||||
|
// Clone any llvm.*used globals to ensure the included values are
|
||||||
|
// not deleted.
|
||||||
|
cloneUsedGlobalVariables(M, *MergedM, /*CompilerUsed*/ false);
|
||||||
|
cloneUsedGlobalVariables(M, *MergedM, /*CompilerUsed*/ true);
|
||||||
|
|
||||||
for (Function &F : *MergedM)
|
for (Function &F : *MergedM)
|
||||||
if (!F.isDeclaration()) {
|
if (!F.isDeclaration()) {
|
||||||
// Reset the linkage of all functions eligible for virtual constant
|
// Reset the linkage of all functions eligible for virtual constant
|
||||||
|
|
|
@ -76,11 +76,13 @@ static void appendToUsedList(Module &M, StringRef Name, ArrayRef<GlobalValue *>
|
||||||
SmallPtrSet<Constant *, 16> InitAsSet;
|
SmallPtrSet<Constant *, 16> InitAsSet;
|
||||||
SmallVector<Constant *, 16> Init;
|
SmallVector<Constant *, 16> Init;
|
||||||
if (GV) {
|
if (GV) {
|
||||||
auto *CA = cast<ConstantArray>(GV->getInitializer());
|
if (GV->hasInitializer()) {
|
||||||
for (auto &Op : CA->operands()) {
|
auto *CA = cast<ConstantArray>(GV->getInitializer());
|
||||||
Constant *C = cast_or_null<Constant>(Op);
|
for (auto &Op : CA->operands()) {
|
||||||
if (InitAsSet.insert(C).second)
|
Constant *C = cast_or_null<Constant>(Op);
|
||||||
Init.push_back(C);
|
if (InitAsSet.insert(C).second)
|
||||||
|
Init.push_back(C);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
GV->eraseFromParent();
|
GV->eraseFromParent();
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,30 @@
|
||||||
|
; Test to ensure that @llvm[.compiler].used is cloned to the split module for
|
||||||
|
; any globals whose defs were cloned to that module.
|
||||||
|
|
||||||
|
; RUN: opt -thinlto-bc -thinlto-split-lto-unit -o %t %s
|
||||||
|
; RUN: llvm-modextract -b -n 0 -o %t0.bc %t
|
||||||
|
; RUN: llvm-modextract -b -n 1 -o %t1.bc %t
|
||||||
|
; RUN: llvm-dis -o - %t0.bc | FileCheck --check-prefix=M0 %s
|
||||||
|
; RUN: llvm-dis -o - %t1.bc | FileCheck --check-prefix=M1 %s
|
||||||
|
|
||||||
|
; M0: @g1 = external global i8
|
||||||
|
; M0: @g2 = external global i8
|
||||||
|
; M0: @g3 = global i8 42
|
||||||
|
; M0: @g4 = global i8 42
|
||||||
|
; M1: @g1 = global i8 42, !type !0
|
||||||
|
; M1: @g2 = global i8 42, !type !0
|
||||||
|
; M1-NOT: @g
|
||||||
|
@g1 = global i8 42, !type !0
|
||||||
|
@g2 = global i8 42, !type !0
|
||||||
|
@g3 = global i8 42
|
||||||
|
@g4 = global i8 42
|
||||||
|
|
||||||
|
; M0: @llvm.used = appending global [2 x i8*] [i8* @g1, i8* @g3]
|
||||||
|
; M0: @llvm.compiler.used = appending global [2 x i8*] [i8* @g2, i8* @g4]
|
||||||
|
; M1: @llvm.used = appending global [1 x i8*] [i8* @g1]
|
||||||
|
; M1: @llvm.compiler.used = appending global [1 x i8*] [i8* @g2]
|
||||||
|
@llvm.used = appending global [2 x i8*] [ i8* @g1, i8* @g3]
|
||||||
|
@llvm.compiler.used = appending global [2 x i8*] [ i8* @g2, i8* @g4]
|
||||||
|
|
||||||
|
; M1: !0 = !{i32 0, !"typeid"}
|
||||||
|
!0 = !{i32 0, !"typeid"}
|
Loading…
Reference in New Issue