llvm.org GIT mirror llvm / ae8374b
[LTO] Remove values from non-prevailing comdats Summary: When linking a regular LTO module, if it has any non-prevailing values (dropped to available_externally) in comdats, we need to do more than just remove those values from their comdat. We also remove all values from that comdat, so as to avoid leaving an incomplete comdat. This is necessary in case we are compiling in mixed regular and ThinLTO mode, since the resulting regularLTO native object is always linked into the final binary first. We need to prevent the linker from selecting an incomplete comdat that was not the prevailing copy. Fixes PR32980. Reviewers: pcc, rafael Subscribers: mehdi_amini, david2050, llvm-commits, inglorion Differential Revision: https://reviews.llvm.org/D34803 git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@306826 91177308-0d34-0410-b5e6-96231b3b80d8 Teresa Johnson 3 years ago
3 changed file(s) with 101 addition(s) and 0 deletion(s). Raw diff Collapse all Expand all
471471 return Error::success();
472472 }
473473
474 // Checks whether the given global value is in a non-prevailing comdat
475 // (comdat containing values the linker indicated were not prevailing,
476 // which we then dropped to available_externally), and if so, removes
477 // it from the comdat. This is called for all global values to ensure the
478 // comdat is empty rather than leaving an incomplete comdat. It is needed for
479 // regular LTO modules, in case we are in a mixed-LTO mode (both regular
480 // and thin LTO modules) compilation. Since the regular LTO module will be
481 // linked first in the final native link, we want to make sure the linker
482 // doesn't select any of these incomplete comdats that would be left
483 // in the regular LTO module without this cleanup.
484 static void
485 handleNonPrevailingComdat(GlobalValue &GV,
486 std::set &NonPrevailingComdats) {
487 Comdat *C = GV.getComdat();
488 if (!C)
489 return;
490
491 if (!NonPrevailingComdats.count(C))
492 return;
493
494 // Additionally need to drop externally visible global values from the comdat
495 // to available_externally, so that there aren't multiply defined linker
496 // errors.
497 if (!GV.hasLocalLinkage())
498 GV.setLinkage(GlobalValue::AvailableExternallyLinkage);
499
500 if (auto GO = dyn_cast(&GV))
501 GO->setComdat(nullptr);
502 }
503
474504 // Add a regular LTO object to the link.
475505 // The resulting module needs to be linked into the combined LTO module with
476506 // linkRegularLTO.
522552 };
523553 Skip();
524554
555 std::set NonPrevailingComdats;
525556 for (const InputFile::Symbol &Sym : Syms) {
526557 assert(ResI != ResE);
527558 SymbolResolution Res = *ResI++;
556587 // module (in linkRegularLTO), based on whether it is undefined.
557588 Mod.Keep.push_back(GV);
558589 GV->setLinkage(GlobalValue::AvailableExternallyLinkage);
590 if (GV->hasComdat())
591 NonPrevailingComdats.insert(GV->getComdat());
559592 cast(GV)->setComdat(nullptr);
560593 }
561594 }
573606
574607 // FIXME: use proposed local attribute for FinalDefinitionInLinkageUnit.
575608 }
609 if (!M.getComdatSymbolTable().empty())
610 for (GlobalValue &GV : M.global_values())
611 handleNonPrevailingComdat(GV, NonPrevailingComdats);
576612 assert(MsymI == MsymE);
577613 return std::move(Mod);
578614 }
0 ; ModuleID = 'comdat-mixed-lto1.o'
1 source_filename = "comdat-mixed-lto1.cpp"
2 target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"
3 target triple = "x86_64-unknown-linux-gnu"
4
5 %"class.Test::ptr" = type { i32 }
6
7 $C = comdat any
8
9 @C = linkonce_odr global %"class.Test::ptr" zeroinitializer, comdat, align 4
10 @llvm.global_ctors = appending global [1 x { i32, void ()*, i8* }] [{ i32, void ()*, i8* } { i32 65535, void ()* @__cxx_global_var_init, i8* bitcast (%"class.Test::ptr"* @C to i8*) }]
11
12 define void @testglobfunc() #1 section ".text.startup" comdat($C) {
13 entry:
14 ret void
15 }
16
17 ; Function Attrs: noinline uwtable
18 define internal void @__cxx_global_var_init() #1 section ".text.startup" comdat($C) {
19 entry:
20 store i32 0, i32* getelementptr inbounds (%"class.Test::ptr", %"class.Test::ptr"* @C, i32 0, i32 0), align 4
21 ret void
22 }
0 ; Test of comdat handling with mixed thinlto and regular lto compilation.
1
2 ; This module is compiled with ThinLTO
3 ; RUN: opt -module-summary -o %t1.o %s
4 ; Input module compiled for regular LTO
5 ; RUN: opt -o %t2.o %p/Inputs/comdat-mixed-lto.ll
6
7 ; The copy of C from this module is prevailing. The copy of C from the
8 ; regular LTO module is not prevailing, and will be dropped to
9 ; available_externally.
10 ; 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
11
12 ; The Input module (regular LTO) is %t3.0. Check to make sure that we removed
13 ; __cxx_global_var_init and testglobfunc from comdat. Also check to ensure
14 ; that testglobfunc was dropped to available_externally. Otherwise we would
15 ; have linker multiply defined errors as it is no longer in a comdat and
16 ; would clash with the copy from this module.
17 ; RUN: llvm-dis %t3.0.0.preopt.bc -o - | FileCheck %s
18 ; CHECK: define internal void @__cxx_global_var_init() section ".text.startup" {
19 ; CHECK: define available_externally void @testglobfunc() section ".text.startup" {
20
21 ; ModuleID = 'comdat-mixed-lto.o'
22 source_filename = "comdat-mixed-lto.cpp"
23 target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"
24 target triple = "x86_64-unknown-linux-gnu"
25
26 %"class.Test::ptr" = type { i32 }
27
28 $C = comdat any
29
30 @C = linkonce_odr global %"class.Test::ptr" zeroinitializer, comdat, align 4
31 @llvm.global_ctors = appending global [1 x { i32, void ()*, i8* }] [{ i32, void ()*, i8* } { i32 65535, void ()* @__cxx_global_var_init, i8* bitcast (%"class.Test::ptr"* @C to i8*) }]
32 define void @testglobfunc() #1 section ".text.startup" comdat($C) {
33 entry:
34 ret void
35 }
36
37 ; Function Attrs: noinline uwtable
38 define internal void @__cxx_global_var_init() #1 section ".text.startup" comdat($C) {
39 entry:
40 ret void
41 }