diff --git a/llvm/lib/Linker/IRMover.cpp b/llvm/lib/Linker/IRMover.cpp --- a/llvm/lib/Linker/IRMover.cpp +++ b/llvm/lib/Linker/IRMover.cpp @@ -1509,6 +1509,20 @@ }); } + // Reorder the globals just added to the destination module to match their + // original order in the source module. + Module::GlobalListType &Globals = DstM.getGlobalList(); + for (GlobalVariable &GV : SrcM->globals()) { + if (GV.hasAppendingLinkage()) + continue; + Value *NewValue = Mapper.mapValue(GV); + if (NewValue) { + auto *NewGV = dyn_cast(NewValue->stripPointerCasts()); + if (NewGV) + Globals.splice(Globals.end(), Globals, NewGV->getIterator()); + } + } + // Merge the module flags into the DstM module. return linkModuleFlagsMetadata(); } diff --git a/llvm/test/Linker/Inputs/globalorder-2.ll b/llvm/test/Linker/Inputs/globalorder-2.ll new file mode 100644 --- /dev/null +++ b/llvm/test/Linker/Inputs/globalorder-2.ll @@ -0,0 +1,14 @@ +@var5 = internal global i32 0, align 4 +@var6 = internal global i32 0, align 4 +@var7 = global i32* @var5, align 4 +@var8 = global i32* @var6, align 4 + +define i32 @foo2() { +entry: + %0 = load i32*, i32** @var7, align 4 + %1 = load i32, i32* %0, align 4 + %2 = load i32*, i32** @var8, align 4 + %3 = load i32, i32* %2, align 4 + %add = add nsw i32 %3, %1 + ret i32 %add +} diff --git a/llvm/test/Linker/comdat.ll b/llvm/test/Linker/comdat.ll --- a/llvm/test/Linker/comdat.ll +++ b/llvm/test/Linker/comdat.ll @@ -23,9 +23,9 @@ ; CHECK: $foo = comdat largest ; CHECK: $any = comdat any +; CHECK: @foo = global i64 43, comdat{{$}} ; CHECK: @qux = global i64 12, comdat{{$}} ; CHECK: @any = global i64 6, comdat{{$}} -; CHECK: @foo = global i64 43, comdat{{$}} ; CHECK-NOT: @in_unselected_group = global i32 13, comdat $qux ; CHECK: define i32 @baz() comdat($qux) diff --git a/llvm/test/Linker/comdat14.ll b/llvm/test/Linker/comdat14.ll --- a/llvm/test/Linker/comdat14.ll +++ b/llvm/test/Linker/comdat14.ll @@ -5,5 +5,5 @@ @v = global i32 0, comdat ($c) ; CHECK: @v = global i32 0, comdat($c) -; CHECK: @v2 = external dllexport global i32 ; CHECK: @v3 = external global i32 +; CHECK: @v2 = external dllexport global i32 diff --git a/llvm/test/Linker/ctors.ll b/llvm/test/Linker/ctors.ll --- a/llvm/test/Linker/ctors.ll +++ b/llvm/test/Linker/ctors.ll @@ -6,12 +6,12 @@ ; Test the bitcode writer too. It used to crash. ; RUN: llvm-link %s %p/Inputs/ctors.ll -o %t.bc +; ALL: @llvm.global_ctors = appending global [1 x { i32, void ()*, i8* }] [{ i32, void ()*, i8* } { i32 65535, void ()* @f, i8* @v }] @v = weak global i8 0 ; CHECK1: @v = weak global i8 0 ; CHECK2: @v = weak global i8 1 @llvm.global_ctors = appending global [1 x { i32, void ()*, i8* }] [{ i32, void ()*, i8* } { i32 65535, void ()* @f, i8* @v }] -; ALL: @llvm.global_ctors = appending global [1 x { i32, void ()*, i8* }] [{ i32, void ()*, i8* } { i32 65535, void ()* @f, i8* @v }] define weak void @f() { ret void diff --git a/llvm/test/Linker/ctors2.ll b/llvm/test/Linker/ctors2.ll --- a/llvm/test/Linker/ctors2.ll +++ b/llvm/test/Linker/ctors2.ll @@ -3,5 +3,5 @@ $foo = comdat any @foo = global i8 0, comdat -; CHECK: @foo = global i8 0, comdat ; CHECK: @llvm.global_ctors = appending global [0 x { i32, void ()*, i8* }] zeroinitializer +; CHECK: @foo = global i8 0, comdat diff --git a/llvm/test/Linker/ctors3.ll b/llvm/test/Linker/ctors3.ll --- a/llvm/test/Linker/ctors3.ll +++ b/llvm/test/Linker/ctors3.ll @@ -4,5 +4,5 @@ %t = type { i8 } @foo = global %t zeroinitializer, comdat -; CHECK: @foo = global %t zeroinitializer, comdat ; CHECK: @llvm.global_ctors = appending global [0 x { i32, void ()*, i8* }] zeroinitializer +; CHECK: @foo = global %t zeroinitializer, comdat diff --git a/llvm/test/Linker/globalorder.ll b/llvm/test/Linker/globalorder.ll new file mode 100644 --- /dev/null +++ b/llvm/test/Linker/globalorder.ll @@ -0,0 +1,27 @@ +; Test the order of global variables during llvm-link + +; RUN: llvm-link %s %S/Inputs/globalorder-2.ll -o %t.bc +; RUN: llvm-dis -o - %t.bc | FileCheck %s + +@var1 = internal global i32 0, align 4 +@var2 = internal global i32 0, align 4 +@var3 = global i32* @var1, align 4 +@var4 = global i32* @var2, align 4 + +define i32 @foo() { +entry: + %0 = load i32*, i32** @var3, align 4 + %1 = load i32, i32* %0, align 4 + %2 = load i32*, i32** @var4, align 4 + %3 = load i32, i32* %2, align 4 + %add = add nsw i32 %3, %1 + ret i32 %add +} +; CHECK: @var1 = +; CHECK-NEXT: @var2 = +; CHECK-NEXT: @var3 = +; CHECK-NEXT: @var4 = +; CHECK-NEXT: @var5 = +; CHECK-NEXT: @var6 = +; CHECK-NEXT: @var7 = +; CHECK-NEXT: @var8 = diff --git a/llvm/test/Linker/link-flags.ll b/llvm/test/Linker/link-flags.ll --- a/llvm/test/Linker/link-flags.ll +++ b/llvm/test/Linker/link-flags.ll @@ -9,8 +9,8 @@ CU-LABEL:@U = global i32 6 CI-LABEL:@U = internal global i32 6 CN-NOT:@U -DI-LABEL: @Y = global i8 42 DI-LABEL: @llvm.used = appending global [2 x i8*] [i8* @Y, i8* bitcast (i64 ()* @foo to i8*)], section "llvm.metadata" +DI-LABEL: @Y = global i8 42 B-LABEL: define void @bar() { diff --git a/llvm/test/Linker/metadata-attach.ll b/llvm/test/Linker/metadata-attach.ll --- a/llvm/test/Linker/metadata-attach.ll +++ b/llvm/test/Linker/metadata-attach.ll @@ -6,17 +6,17 @@ ; CHECK-LINKED1: @g1 = global i32 0, !attach !0{{$}} @g1 = global i32 0, !attach !0 -; CHECK: @g3 = weak global i32 1, !attach !0{{$}} ; CHECK: @g2 = external global i32, !attach !0{{$}} +; CHECK: @g3 = weak global i32 1, !attach !0{{$}} ; CHECK-LINKED1: @g2 = global i32 1, !attach !1{{$}} @g2 = external global i32, !attach !0 ; CHECK-LINKED1: @g3 = global i32 2, !attach !1{{$}} @g3 = weak global i32 1, !attach !0 -; CHECK-LINKED2: @g2 = global i32 1, !attach !0{{$}} -; CHECK-LINKED2: @g3 = global i32 2, !attach !0{{$}} -; CHECK-LINKED2: @g1 = global i32 0, !attach !1{{$}} +; CHECK-LINKED2: @g1 = global i32 0, !attach !0{{$}} +; CHECK-LINKED2: @g2 = global i32 1, !attach !1{{$}} +; CHECK-LINKED2: @g3 = global i32 2, !attach !1{{$}} ; CHECK: define void @f1() !attach !0 { ; CHECK-LINKED1: define void @f1() !attach !0 { @@ -36,14 +36,14 @@ ret void } -; CHECK-LINKED2: define void @f2() !attach !0 { -; CHECK-LINKED2: define void @f3() !attach !0 { -; CHECK-LINKED2: define void @f1() !attach !1 { +; CHECK-LINKED2: define void @f2() !attach !1 { +; CHECK-LINKED2: define void @f3() !attach !1 { +; CHECK-LINKED2: define void @f1() !attach !0 { ; CHECK-LINKED1: !0 = !{i32 0} ; CHECK-LINKED1: !1 = !{i32 1} -; CHECK-LINKED2: !0 = !{i32 1} -; CHECK-LINKED2: !1 = !{i32 0} +; CHECK-LINKED2: !0 = !{i32 0} +; CHECK-LINKED2: !1 = !{i32 1} !0 = !{i32 0} diff --git a/llvm/test/Linker/testlink.ll b/llvm/test/Linker/testlink.ll --- a/llvm/test/Linker/testlink.ll +++ b/llvm/test/Linker/testlink.ll @@ -1,7 +1,7 @@ ; RUN: llvm-link %s %S/Inputs/testlink.ll -S | FileCheck %s -; CHECK: %Ty2 = type { %Ty1* } ; CHECK: %Ty1 = type { %Ty2* } +; CHECK: %Ty2 = type { %Ty1* } %Ty1 = type opaque %Ty2 = type { %Ty1* } diff --git a/llvm/test/ThinLTO/X86/import-constant.ll b/llvm/test/ThinLTO/X86/import-constant.ll --- a/llvm/test/ThinLTO/X86/import-constant.ll +++ b/llvm/test/ThinLTO/X86/import-constant.ll @@ -28,9 +28,9 @@ ; PROMOTE: @_ZL3Obj.llvm.{{.*}} = hidden constant %struct.S { i32 4, i32 8, i32* @val } ; @outer is a write-only variable, so it's been converted to zeroinitializer. -; IMPORT: @outer = internal local_unnamed_addr global %struct.Q zeroinitializer +; IMPORT: @val = available_externally global i32 42 ; IMPORT-NEXT: @_ZL3Obj.llvm.{{.*}} = available_externally hidden constant %struct.S { i32 4, i32 8, i32* @val } -; IMPORT-NEXT: @val = available_externally global i32 42 +; IMPORT-NEXT: @outer = internal local_unnamed_addr global %struct.Q zeroinitializer ; OPT: @outer = internal unnamed_addr global %struct.Q zeroinitializer @@ -39,8 +39,8 @@ ; OPT-NEXT: store %struct.S* null, %struct.S** getelementptr inbounds (%struct.Q, %struct.Q* @outer, i64 0, i32 0) ; OPT-NEXT: ret i32 12 -; NOREFS: @outer = internal local_unnamed_addr global %struct.Q zeroinitializer -; NOREFS-NEXT: @_ZL3Obj.llvm.{{.*}} = external hidden constant %struct.S +; NOREFS: @_ZL3Obj.llvm.{{.*}} = external hidden constant %struct.S +; NOREFS-NEXT: @outer = internal local_unnamed_addr global %struct.Q zeroinitializer target datalayout = "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:128-n8:16:32:64-S128" target triple = "x86_64-unknown-linux-gnu" diff --git a/llvm/test/ThinLTO/X86/index-const-prop.ll b/llvm/test/ThinLTO/X86/index-const-prop.ll --- a/llvm/test/ThinLTO/X86/index-const-prop.ll +++ b/llvm/test/ThinLTO/X86/index-const-prop.ll @@ -19,14 +19,14 @@ ; RUN: llvm-lto -thinlto-action=import -exported-symbol main -exported-symbol gBar %t1.bc -thinlto-index=%t3.index.bc -o %t1.imported2.bc ; RUN: llvm-dis %t1.imported2.bc -o - | FileCheck %s --check-prefix=IMPORT2 -; IMPORT: @gFoo.llvm.0 = internal unnamed_addr global i32 1, align 4, !dbg !0 -; IMPORT-NEXT: @gBar = internal local_unnamed_addr global i32 2, align 4, !dbg !5 +; IMPORT: @gBar = internal local_unnamed_addr global i32 2, align 4, !dbg !0 +; IMPORT-NEXT: @gFoo.llvm.0 = internal unnamed_addr global i32 1, align 4, !dbg !5 ; IMPORT: !DICompileUnit({{.*}}) ; OPTIMIZE: define i32 @main ; OPTIMIZE-NEXT: ret i32 3 -; IMPORT2: @gBar = available_externally local_unnamed_addr global i32 2, align 4, !dbg !5 +; IMPORT2: @gBar = available_externally local_unnamed_addr global i32 2, align 4, !dbg !0 target datalayout = "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:128-n8:16:32:64-S128" target triple = "x86_64-pc-linux-gnu" diff --git a/llvm/test/ThinLTO/X86/index-const-prop2.ll b/llvm/test/ThinLTO/X86/index-const-prop2.ll --- a/llvm/test/ThinLTO/X86/index-const-prop2.ll +++ b/llvm/test/ThinLTO/X86/index-const-prop2.ll @@ -57,13 +57,13 @@ ; with corresponsing stores ; RUN: llvm-dis %t5.2.5.precodegen.bc -o - | FileCheck %s --check-prefix=CODEGEN2-SRC -; IMPORT: @gFoo.llvm.0 = internal unnamed_addr global i32 1, align 4 -; IMPORT-NEXT: @gBar = internal local_unnamed_addr global i32 2, align 4 +; IMPORT: @gBar = internal local_unnamed_addr global i32 2, align 4 +; IMPORT-NEXT: @gFoo.llvm.0 = internal unnamed_addr global i32 1, align 4 ; IMPORT: !DICompileUnit({{.*}}) ; Write only variables are imported with a zero initializer. -; IMPORT-WRITEONLY: @gFoo.llvm.0 = internal unnamed_addr global i32 0 ; IMPORT-WRITEONLY: @gBar = internal local_unnamed_addr global i32 0 +; IMPORT-WRITEONLY: @gFoo.llvm.0 = internal unnamed_addr global i32 0 ; CODEGEN: i32 @main() ; CODEGEN-NEXT: ret i32 3 diff --git a/llvm/test/ThinLTO/X86/writeonly.ll b/llvm/test/ThinLTO/X86/writeonly.ll --- a/llvm/test/ThinLTO/X86/writeonly.ll +++ b/llvm/test/ThinLTO/X86/writeonly.ll @@ -11,8 +11,8 @@ ; RUN: llvm-dis %t1.imported.bc -o - | FileCheck %s --check-prefix=IMPORT ; RUN: llvm-lto -thinlto-action=optimize %t1.imported.bc -o - | llvm-dis - -o - | FileCheck %s --check-prefix=OPTIMIZE -; IMPORT: @gFoo.llvm.0 = internal unnamed_addr global i32 0, align 4, !dbg !0 -; IMPORT-NEXT: @gBar = internal local_unnamed_addr global i32 0, align 4, !dbg !5 +; IMPORT: @gBar = internal local_unnamed_addr global i32 0, align 4, !dbg !0 +; IMPORT-NEXT: @gFoo.llvm.0 = internal unnamed_addr global i32 0, align 4, !dbg !5 ; IMPORT: !DICompileUnit({{.*}}) ; STATS: 2 module-summary-index - Number of live global variables marked write only @@ -29,8 +29,8 @@ ; RUN: llvm-lto -propagate-attrs=false -thinlto-action=import -exported-symbol=main %t1.bc -thinlto-index=%t3.index.bc -o %t1.imported.bc -stats 2>&1 | FileCheck %s --check-prefix=STATS-NOPROP ; RUN: llvm-dis %t1.imported.bc -o - | FileCheck %s --check-prefix=IMPORT-NOPROP ; STATS-NOPROP-NOT: Number of live global variables marked write only -; IMPORT-NOPROP: @gFoo.llvm.0 = available_externally -; IMPORT-NOPROP-NEXT: @gBar = available_externally +; IMPORT-NOPROP: @gBar = available_externally +; IMPORT-NOPROP-NEXT: @gFoo.llvm.0 = available_externally target datalayout = "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:128-n8:16:32:64-S128" target triple = "x86_64-pc-linux-gnu" diff --git a/llvm/test/ThinLTO/X86/writeonly2.ll b/llvm/test/ThinLTO/X86/writeonly2.ll --- a/llvm/test/ThinLTO/X86/writeonly2.ll +++ b/llvm/test/ThinLTO/X86/writeonly2.ll @@ -19,8 +19,8 @@ ; with corresponsing stores ; RUN: llvm-dis %t3.2.5.precodegen.bc -o - | FileCheck %s --check-prefix=CODEGEN-SRC -; IMPORT: @gFoo.llvm.0 = internal unnamed_addr global i32 0, align 4 -; IMPORT-NEXT: @gBar = internal local_unnamed_addr global i32 0, align 4 +; IMPORT: @gBar = internal local_unnamed_addr global i32 0, align 4 +; IMPORT-NEXT: @gFoo.llvm.0 = internal unnamed_addr global i32 0, align 4 ; IMPORT: !DICompileUnit({{.*}}) ; CODEGEN-NOT: gFoo