Skip to content

Commit 2c239da

Browse files
committed
Revert D135427 "[LTO] Make local linkage GlobalValue in non-prevailing COMDAT available_externally"
This reverts commit 8901635. This change broke the following example and we need to check `if (GO->getComdat()->getName() == GO->getName())` before `NonPrevailingComdats.insert(GO->getComdat());` Revert for clarify. ``` // a.cc template <typename T> struct A final { virtual ~A() {} }; extern "C" void aa() { A<int> a; } // b.cc template <typename T> struct A final { virtual ~A() {} }; template struct A<int>; extern "C" void bb(A<int> *a) { delete a; } clang -c -fpic -O0 -flto=thin a.cc && ld.lld -shared a.o b.o ```
1 parent bbe6bd7 commit 2c239da

File tree

7 files changed

+22
-179
lines changed

7 files changed

+22
-179
lines changed

llvm/lib/LTO/LTO.cpp

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -712,11 +712,11 @@ handleNonPrevailingComdat(GlobalValue &GV,
712712
if (!NonPrevailingComdats.count(C))
713713
return;
714714

715-
// Additionally need to drop all global values from the comdat to
716-
// available_externally, to satisfy the COMDAT requirement that all members
717-
// are discarded as a unit. The non-local linkage global values avoid
718-
// duplicate definition linker errors.
719-
GV.setLinkage(GlobalValue::AvailableExternallyLinkage);
715+
// Additionally need to drop externally visible global values from the comdat
716+
// to available_externally, so that there aren't multiply defined linker
717+
// errors.
718+
if (!GV.hasLocalLinkage())
719+
GV.setLinkage(GlobalValue::AvailableExternallyLinkage);
720720

721721
if (auto GO = dyn_cast<GlobalObject>(&GV))
722722
GO->setComdat(nullptr);

llvm/lib/Transforms/IPO/FunctionImport.cpp

Lines changed: 1 addition & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -1051,7 +1051,6 @@ bool llvm::convertToDeclaration(GlobalValue &GV) {
10511051
void llvm::thinLTOFinalizeInModule(Module &TheModule,
10521052
const GVSummaryMapTy &DefinedGlobals,
10531053
bool PropagateAttrs) {
1054-
DenseSet<Comdat *> NonPrevailingComdats;
10551054
auto FinalizeInModule = [&](GlobalValue &GV, bool Propagate = false) {
10561055
// See if the global summary analysis computed a new resolved linkage.
10571056
const auto &GS = DefinedGlobals.find(GV.getGUID());
@@ -1129,10 +1128,8 @@ void llvm::thinLTOFinalizeInModule(Module &TheModule,
11291128
// as this is a declaration for the linker, and will be dropped eventually.
11301129
// It is illegal for comdats to contain declarations.
11311130
auto *GO = dyn_cast_or_null<GlobalObject>(&GV);
1132-
if (GO && GO->isDeclarationForLinker() && GO->hasComdat()) {
1133-
NonPrevailingComdats.insert(GO->getComdat());
1131+
if (GO && GO->isDeclarationForLinker() && GO->hasComdat())
11341132
GO->setComdat(nullptr);
1135-
}
11361133
};
11371134

11381135
// Process functions and global now
@@ -1142,36 +1139,6 @@ void llvm::thinLTOFinalizeInModule(Module &TheModule,
11421139
FinalizeInModule(GV);
11431140
for (auto &GV : TheModule.aliases())
11441141
FinalizeInModule(GV);
1145-
1146-
// For a non-prevailing comdat, all its members must be available_externally.
1147-
// FinalizeInModule has handled non-local-linkage GlobalValues. Here we handle
1148-
// local linkage GlobalValues.
1149-
if (NonPrevailingComdats.empty())
1150-
return;
1151-
for (auto &GO : TheModule.global_objects()) {
1152-
if (auto *C = GO.getComdat(); C && NonPrevailingComdats.count(C)) {
1153-
GO.setComdat(nullptr);
1154-
GO.setLinkage(GlobalValue::AvailableExternallyLinkage);
1155-
}
1156-
}
1157-
bool Changed;
1158-
do {
1159-
Changed = false;
1160-
// If an alias references a GlobalValue in a non-prevailing comdat, change
1161-
// it to available_externally. For simplicity we only handle GlobalValue and
1162-
// ConstantExpr with a base object. ConstantExpr without a base object is
1163-
// unlikely used in a COMDAT.
1164-
for (auto &GA : TheModule.aliases()) {
1165-
if (GA.hasAvailableExternallyLinkage())
1166-
continue;
1167-
GlobalObject *Obj = GA.getAliaseeObject();
1168-
assert(Obj && "aliasee without an base object is unimplemented");
1169-
if (Obj->hasAvailableExternallyLinkage()) {
1170-
GA.setLinkage(GlobalValue::AvailableExternallyLinkage);
1171-
Changed = true;
1172-
}
1173-
}
1174-
} while (Changed);
11751142
}
11761143

11771144
/// Run internalization on \p TheModule based on symmary analysis.

llvm/test/LTO/Resolution/X86/comdat-mixed-lto.ll

Lines changed: 3 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -8,29 +8,16 @@
88
; The copy of C from this module is prevailing. The copy of C from the
99
; regular LTO module is not prevailing, and will be dropped to
1010
; available_externally.
11-
; RUN: llvm-lto2 run -r=%t1.o,C,pl -r=%t2.o,C,l -r=%t1.o,testglobfunc,lxp -r=%t2.o,testglobfunc,lx -o %t3 %t1.o %t2.o -save-temps
11+
; RUN: llvm-lto2 run -r=%t1.o,C,pl -r=%t2.o,C,l -r=%t2.o,testglobfunc,lxp -r=%t1.o,testglobfunc,lx -o %t3 %t1.o %t2.o -save-temps
1212

1313
; The Input module (regular LTO) is %t3.0. Check to make sure that we removed
1414
; __cxx_global_var_init and testglobfunc from comdat. Also check to ensure
1515
; that testglobfunc was dropped to available_externally. Otherwise we would
1616
; have linker multiply defined errors as it is no longer in a comdat and
1717
; would clash with the copy from this module.
1818
; RUN: llvm-dis %t3.0.0.preopt.bc -o - | FileCheck %s
19-
20-
; CHECK: @llvm.global_ctors = appending global [1 x { i32, ptr, ptr }] [{ i32, ptr, ptr } { i32 65535, ptr @__cxx_global_var_init, ptr @C }]
21-
; CHECK: @C = available_externally dso_local global %"class.Test::ptr" zeroinitializer, align 4
22-
; CHECK-NOT: declare
23-
; CHECK: declare dso_local void @__cxx_global_var_init() section ".text.startup"
24-
; CHECK-NOT: declare
25-
26-
; Check the behavior with the prevailing testglobfunc in %t2.o.
27-
; RUN: llvm-lto2 run -r=%t1.o,C,pl -r=%t2.o,C,l -r=%t1.o,testglobfunc,lx -r=%t2.o,testglobfunc,plx -o %t4 %t1.o %t2.o -save-temps
28-
; RUN: llvm-dis %t4.0.0.preopt.bc -o - | FileCheck %s --check-prefix=CHECK2
29-
30-
; CHECK2: @llvm.global_ctors = appending global [1 x { i32, ptr, ptr }] [{ i32, ptr, ptr } { i32 65535, ptr @__cxx_global_var_init, ptr @C }]
31-
; CHECK2: @C = available_externally dso_local global %"class.Test::ptr" zeroinitializer, align 4
32-
; CHECK2: declare dso_local void @__cxx_global_var_init() section ".text.startup"
33-
; CHECK2: define available_externally dso_local void @testglobfunc() section ".text.startup" {
19+
; CHECK: define internal void @__cxx_global_var_init() section ".text.startup" {
20+
; CHECK: define available_externally dso_local void @testglobfunc() section ".text.startup" {
3421

3522
; ModuleID = 'comdat-mixed-lto.o'
3623
source_filename = "comdat-mixed-lto.cpp"
Lines changed: 3 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1,24 +1,13 @@
11
target datalayout = "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:128-n8:16:32:64-S128"
22
target triple = "x86_64-unknown-linux-gnu"
33

4-
$f = comdat any
5-
$g = comdat any
4+
$c2 = comdat any
65

7-
@g_private = private global i32 41, comdat($g)
8-
9-
define linkonce_odr i32 @f(i8*) unnamed_addr comdat($f) {
10-
ret i32 41
11-
}
12-
13-
define linkonce_odr i32 @g() unnamed_addr comdat($g) {
6+
define linkonce_odr i32 @f(i8*) unnamed_addr comdat($c2) {
147
ret i32 41
158
}
169

17-
define internal void @g_internal() unnamed_addr comdat($g) {
18-
ret void
19-
}
20-
21-
define i32 @h() {
10+
define i32 @g() {
2211
%i = call i32 @f(i8* null)
2312
ret i32 %i
2413
}

llvm/test/ThinLTO/X86/constructor-alias.ll

Lines changed: 0 additions & 44 deletions
This file was deleted.
Lines changed: 10 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -1,54 +1,33 @@
1-
; This test ensures that we drop the preempted copy of @f/@g from %t2.bc from their
2-
; comdats after making it available_externally. If not we would get a
3-
; verification error. g_internal/g_private are changed to available_externally
4-
; as well since it is in the same comdat of g.
1+
; This test ensures that we drop the preempted copy of @f from %t2.bc from its
2+
; comdat after making it available_externally. If not we would get a
3+
; verification error.
54
; RUN: opt -module-summary %s -o %t1.bc
65
; RUN: opt -module-summary %p/Inputs/linkonce_resolution_comdat.ll -o %t2.bc
7-
; RUN: llvm-lto -thinlto-action=run -disable-thinlto-funcattrs=0 %t1.bc %t2.bc -exported-symbol=f -exported-symbol=g -exported-symbol=h -thinlto-save-temps=%t3.
6+
; RUN: llvm-lto -thinlto-action=run -disable-thinlto-funcattrs=0 %t1.bc %t2.bc -exported-symbol=f -exported-symbol=g -thinlto-save-temps=%t3.
87

98
; RUN: llvm-dis %t3.0.3.imported.bc -o - | FileCheck %s --check-prefix=IMPORT1
109
; RUN: llvm-dis %t3.1.3.imported.bc -o - | FileCheck %s --check-prefix=IMPORT2
1110
; Copy from first module is prevailing and converted to weak_odr, copy
1211
; from second module is preempted and converted to available_externally and
1312
; removed from comdat.
14-
; IMPORT1: @g_private = private global i32 43, comdat($g)
15-
; IMPORT1: define weak_odr i32 @f(i8* %0) unnamed_addr [[ATTR:#[0-9]+]] comdat {
16-
; IMPORT1: define weak_odr i32 @g() unnamed_addr [[ATTR]] comdat {
17-
; IMPORT1: define internal void @g_internal() unnamed_addr comdat($g) {
18-
19-
; IMPORT2: @g_private = available_externally dso_local global i32 41{{$}}
13+
; IMPORT1: define weak_odr i32 @f(i8* %0) unnamed_addr [[ATTR:#[0-9]+]] comdat($c1) {
2014
; IMPORT2: define available_externally i32 @f(i8* %0) unnamed_addr [[ATTR:#[0-9]+]] {
21-
; IMPORT2: define available_externally i32 @g() unnamed_addr [[ATTR]] {
22-
; IMPORT2: define available_externally dso_local void @g_internal() unnamed_addr {
2315

2416
; CHECK-DAG: attributes [[ATTR]] = { norecurse nounwind }
2517

26-
; RUN: llvm-nm %t1.bc.thinlto.o | FileCheck %s --check-prefix=NM1
18+
; RUN: llvm-nm -o - < %t1.bc.thinlto.o | FileCheck %s --check-prefix=NM1
2719
; NM1: W f
28-
; NM1: W g
2920

30-
; RUN: llvm-nm %t2.bc.thinlto.o | FileCheck %s --check-prefix=NM2
21+
; RUN: llvm-nm -o - < %t2.bc.thinlto.o | FileCheck %s --check-prefix=NM2
3122
; f() would have been turned into available_externally since it is preempted,
32-
; and inlined into h()
23+
; and inlined into g()
3324
; NM2-NOT: f
34-
; NM2-NOT: g
3525

3626
target datalayout = "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:128-n8:16:32:64-S128"
3727
target triple = "x86_64-unknown-linux-gnu"
3828

39-
$f = comdat any
40-
$g = comdat any
41-
42-
@g_private = private global i32 43, comdat($g)
29+
$c1 = comdat any
4330

44-
define linkonce_odr i32 @f(i8*) unnamed_addr comdat {
31+
define linkonce_odr i32 @f(i8*) unnamed_addr comdat($c1) {
4532
ret i32 43
4633
}
47-
48-
define linkonce_odr i32 @g() unnamed_addr comdat {
49-
ret i32 43
50-
}
51-
52-
define internal void @g_internal() unnamed_addr comdat($g) {
53-
ret void
54-
}

llvm/test/ThinLTO/X86/windows-vftable.ll

Lines changed: 0 additions & 35 deletions
This file was deleted.

0 commit comments

Comments
 (0)