Skip to content

Commit fde55a9

Browse files
committed
[LTO] Fix cloning of llvm*.used when splitting module
Refines the fix in 3c4c205 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
1 parent 309b00a commit fde55a9

File tree

3 files changed

+65
-10
lines changed

3 files changed

+65
-10
lines changed

llvm/lib/Transforms/IPO/ThinLTOBitcodeWriter.cpp

Lines changed: 28 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -195,6 +195,29 @@ void forEachVirtualFunction(Constant *C, function_ref<void(Function *)> Fn) {
195195
forEachVirtualFunction(cast<Constant>(Op), Fn);
196196
}
197197

198+
// Clone any @llvm[.compiler].used over to the new module and append
199+
// values whose defs were cloned into that module.
200+
static void cloneUsedGlobalVariables(const Module &SrcM, Module &DestM,
201+
bool CompilerUsed) {
202+
SmallPtrSet<GlobalValue *, 8> Used;
203+
SmallPtrSet<GlobalValue *, 8> NewUsed;
204+
// First collect those in the llvm[.compiler].used set.
205+
collectUsedGlobalVariables(SrcM, Used, CompilerUsed);
206+
// Next build a set of the equivalent values defined in DestM.
207+
for (auto *V : Used) {
208+
auto *GV = DestM.getNamedValue(V->getName());
209+
if (GV && !GV->isDeclaration())
210+
NewUsed.insert(GV);
211+
}
212+
// Finally, add them to a llvm[.compiler].used variable in DestM.
213+
if (CompilerUsed)
214+
appendToCompilerUsed(
215+
DestM, std::vector<GlobalValue *>(NewUsed.begin(), NewUsed.end()));
216+
else
217+
appendToUsed(DestM,
218+
std::vector<GlobalValue *>(NewUsed.begin(), NewUsed.end()));
219+
}
220+
198221
// If it's possible to split M into regular and thin LTO parts, do so and write
199222
// a multi-module bitcode file with the two parts to OS. Otherwise, write only a
200223
// regular LTO bitcode file to OS.
@@ -275,11 +298,6 @@ void splitAndWriteThinLTOBitcode(
275298
ValueToValueMapTy VMap;
276299
std::unique_ptr<Module> MergedM(
277300
CloneModule(M, VMap, [&](const GlobalValue *GV) -> bool {
278-
// Clone any llvm.*used globals to ensure the included values are
279-
// not deleted.
280-
if (GV->getName() == "llvm.used" ||
281-
GV->getName() == "llvm.compiler.used")
282-
return true;
283301
if (const auto *C = GV->getComdat())
284302
if (MergedMComdats.count(C))
285303
return true;
@@ -292,6 +310,11 @@ void splitAndWriteThinLTOBitcode(
292310
StripDebugInfo(*MergedM);
293311
MergedM->setModuleInlineAsm("");
294312

313+
// Clone any llvm.*used globals to ensure the included values are
314+
// not deleted.
315+
cloneUsedGlobalVariables(M, *MergedM, /*CompilerUsed*/ false);
316+
cloneUsedGlobalVariables(M, *MergedM, /*CompilerUsed*/ true);
317+
295318
for (Function &F : *MergedM)
296319
if (!F.isDeclaration()) {
297320
// Reset the linkage of all functions eligible for virtual constant

llvm/lib/Transforms/Utils/ModuleUtils.cpp

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -76,11 +76,13 @@ static void appendToUsedList(Module &M, StringRef Name, ArrayRef<GlobalValue *>
7676
SmallPtrSet<Constant *, 16> InitAsSet;
7777
SmallVector<Constant *, 16> Init;
7878
if (GV) {
79-
auto *CA = cast<ConstantArray>(GV->getInitializer());
80-
for (auto &Op : CA->operands()) {
81-
Constant *C = cast_or_null<Constant>(Op);
82-
if (InitAsSet.insert(C).second)
83-
Init.push_back(C);
79+
if (GV->hasInitializer()) {
80+
auto *CA = cast<ConstantArray>(GV->getInitializer());
81+
for (auto &Op : CA->operands()) {
82+
Constant *C = cast_or_null<Constant>(Op);
83+
if (InitAsSet.insert(C).second)
84+
Init.push_back(C);
85+
}
8486
}
8587
GV->eraseFromParent();
8688
}
Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
; Test to ensure that @llvm[.compiler].used is cloned to the split module for
2+
; any globals whose defs were cloned to that module.
3+
4+
; RUN: opt -thinlto-bc -thinlto-split-lto-unit -o %t %s
5+
; RUN: llvm-modextract -b -n 0 -o %t0.bc %t
6+
; RUN: llvm-modextract -b -n 1 -o %t1.bc %t
7+
; RUN: llvm-dis -o - %t0.bc | FileCheck --check-prefix=M0 %s
8+
; RUN: llvm-dis -o - %t1.bc | FileCheck --check-prefix=M1 %s
9+
10+
; M0: @g1 = external global i8
11+
; M0: @g2 = external global i8
12+
; M0: @g3 = global i8 42
13+
; M0: @g4 = global i8 42
14+
; M1: @g1 = global i8 42, !type !0
15+
; M1: @g2 = global i8 42, !type !0
16+
; M1-NOT: @g
17+
@g1 = global i8 42, !type !0
18+
@g2 = global i8 42, !type !0
19+
@g3 = global i8 42
20+
@g4 = global i8 42
21+
22+
; M0: @llvm.used = appending global [2 x i8*] [i8* @g1, i8* @g3]
23+
; M0: @llvm.compiler.used = appending global [2 x i8*] [i8* @g2, i8* @g4]
24+
; M1: @llvm.used = appending global [1 x i8*] [i8* @g1]
25+
; M1: @llvm.compiler.used = appending global [1 x i8*] [i8* @g2]
26+
@llvm.used = appending global [2 x i8*] [ i8* @g1, i8* @g3]
27+
@llvm.compiler.used = appending global [2 x i8*] [ i8* @g2, i8* @g4]
28+
29+
; M1: !0 = !{i32 0, !"typeid"}
30+
!0 = !{i32 0, !"typeid"}

0 commit comments

Comments
 (0)