Index: llvm/lib/Linker/IRMover.cpp =================================================================== --- llvm/lib/Linker/IRMover.cpp +++ llvm/lib/Linker/IRMover.cpp @@ -1443,6 +1443,8 @@ computeTypeMapping(); std::reverse(Worklist.begin(), Worklist.end()); + SmallVector, 16> MappedConstants; + while (!Worklist.empty()) { GlobalValue *GV = Worklist.back(); Worklist.pop_back(); @@ -1453,12 +1455,72 @@ continue; assert(!GV->isDeclaration()); - Mapper.mapValue(*GV); + + // Set the initializer of global variable to be empty so that + // the global varaibles in the initializer won't be generated. + Constant *InitCnst = nullptr; + StringRef Name = GV->getName(); + if (Name != "llvm.global_ctors" && Name != "llvm.global_dtors") { + if (auto *V = dyn_cast(GV)) { + if (V->hasInitializer()) { + InitCnst = V->getInitializer(); + if (InitCnst != Constant::getNullValue(V->getValueType())) + V->setInitializer(Constant::getNullValue(V->getValueType())); + else + InitCnst = nullptr; + } + } + } + + // Record the mapping between the old initializer and new + // global variable. + if (InitCnst) { + auto *NewV = Mapper.mapValue(*GV); + assert(NewV); + NewV = NewV->stripPointerCastsAndAliases(); + auto *NewGV = dyn_cast(NewV); + assert(NewGV); + MappedConstants.push_back({InitCnst, NewGV}); + } + if (FoundError) return std::move(*FoundError); flushRAUWWorklist(); } + // Generate the new iniitializer based on the + // mapping btween the old initializer and the + // new global variable. By this way, the original + // lexical order can be preserved. + for (auto &MC : MappedConstants) { + auto *OldCnst = dyn_cast(MC.first); + auto *NewCnst = Mapper.mapValue(*OldCnst); + Constant *C = dyn_cast(NewCnst); + assert(C); + if (MC.second->getInitializer() != + Constant::getNullValue(MC.second->getValueType())) { + SmallVector NewElements; + getArrayElements(MC.second->getInitializer(), NewElements); + + SmallVector OldElements; + getArrayElements(C, OldElements); + + // In some cases, the size of NewElements is larger than that + // of OldElemts. + unsigned Size = OldElements.size(); + while (Size > 0) { + NewElements.pop_back(); + Size--; + } + NewElements.append(OldElements.begin(), OldElements.end()); + ArrayType *ATyp = + dyn_cast(MC.second->getType()->getElementType()); + assert(ATyp); + C = ConstantArray::get(ATyp, NewElements); + } + MC.second->setInitializer(C); + } + // Note that we are done linking global value bodies. This prevents // metadata linking from creating new references. DoneLinkingBodies = true; Index: llvm/lib/Linker/LinkModules.cpp =================================================================== --- llvm/lib/Linker/LinkModules.cpp +++ llvm/lib/Linker/LinkModules.cpp @@ -369,10 +369,20 @@ GV.setUnnamedAddr(UnnamedAddr); } - if (!DGV && !shouldOverrideFromSrc() && - (GV.hasLocalLinkage() || GV.hasLinkOnceLinkage() || - GV.hasAvailableExternallyLinkage())) - return false; + if (!DGV && !shouldOverrideFromSrc()) { + if (GV.hasAvailableExternallyLinkage()) + return false; + if (GV.hasLocalLinkage() || GV.hasLinkOnceLinkage()) { + if (GV.getNumUses() == 0) + return false; + if (GV.hasOneUse() && isa(GV.user_back())) { + GlobalValue *G = cast(GV.user_back()); + if (G->hasLocalLinkage() || + G->hasLinkOnceLinkage()) + return false; + } + } + } if (GV.isDeclaration()) return false; @@ -390,6 +400,7 @@ return true; if (LinkFromSrc) ValuesToLink.insert(&GV); + return false; } Index: llvm/test/Linker/internalize-lazy.ll =================================================================== --- llvm/test/Linker/internalize-lazy.ll +++ llvm/test/Linker/internalize-lazy.ll @@ -1,4 +1,4 @@ ; RUN: llvm-link -S -internalize %s %p/Inputs/internalize-lazy.ll | FileCheck %s -; CHECK: define internal void @f ; CHECK: define internal void @g +; CHECK: define internal void @f Index: llvm/test/tools/llvm-link/globalorder.ll =================================================================== --- /dev/null +++ llvm/test/tools/llvm-link/globalorder.ll @@ -0,0 +1,21 @@ +; Test the order of global variables during llvm-link + +; RUN: llvm-link %s -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: @var3 = +; CHECK-NEXT: @var4 =