Index: test/tools/gold/X86/Inputs/common.ll =================================================================== --- test/tools/gold/X86/Inputs/common.ll +++ test/tools/gold/X86/Inputs/common.ll @@ -1 +1 @@ -@a = common global i16 0, align 4 +@a = common global i32 0, align 4 Index: test/tools/gold/X86/Inputs/common2.ll =================================================================== --- /dev/null +++ test/tools/gold/X86/Inputs/common2.ll @@ -0,0 +1 @@ +@a = common global i8 0, align 16 Index: test/tools/gold/X86/common.ll =================================================================== --- test/tools/gold/X86/common.ll +++ test/tools/gold/X86/common.ll @@ -1,15 +1,24 @@ ; RUN: llvm-as %s -o %t1.o ; RUN: llvm-as %p/Inputs/common.ll -o %t2.o +; RUN: llvm-as %p/Inputs/common2.ll -o %t2a.o ; RUN: %gold -plugin %llvmshlibdir/LLVMgold.so \ ; RUN: --plugin-opt=emit-llvm \ ; RUN: -shared %t1.o %t2.o -o %t3.o -; RUN: llvm-dis %t3.o -o - | FileCheck %s +; RUN: llvm-dis %t3.o -o - | FileCheck %s --check-prefix=A -@a = common global i8 0, align 8 +; RUN: %gold -plugin %llvmshlibdir/LLVMgold.so \ +; RUN: --plugin-opt=emit-llvm \ +; RUN: -shared %t1.o %t2a.o -o %t3.o +; RUN: llvm-dis %t3.o -o - | FileCheck %s --check-prefix=B + +@a = common global i16 0, align 8 ; Shared library case, we merge @a as common and keep it for the symbol table. -; CHECK: @a = common global i16 0, align 8 +; A: @a = common global i32 0, align 8 + +; (i16 align 8) + (i8 align 16) = i16 align 16 +; B: @a = common global i16 0, align 16 ; RUN: %gold -plugin %llvmshlibdir/LLVMgold.so \ ; RUN: --plugin-opt=emit-llvm \ @@ -17,13 +26,13 @@ ; RUN: llvm-dis %t3.o -o - | FileCheck --check-prefix=EXEC %s ; All IR case, we internalize a after merging. -; EXEC: @a = internal global i16 0, align 8 +; EXEC: @a = internal global i32 0, align 8 -; RUN: llc %p/Inputs/common.ll -o %t2.o -filetype=obj +; RUN: llc %p/Inputs/common.ll -o %t2native.o -filetype=obj ; RUN: %gold -plugin %llvmshlibdir/LLVMgold.so \ ; RUN: --plugin-opt=emit-llvm \ -; RUN: %t1.o %t2.o -o %t3.o +; RUN: %t1.o %t2native.o -o %t3.o ; RUN: llvm-dis %t3.o -o - | FileCheck --check-prefix=MIXED %s ; Mixed ELF and IR. We keep ours as common so the linker will finish the merge. -; MIXED: @a = common global i8 0, align 8 +; MIXED: @a = common global i16 0, align 8 Index: tools/gold/gold-plugin.cpp =================================================================== --- tools/gold/gold-plugin.cpp +++ tools/gold/gold-plugin.cpp @@ -90,14 +90,13 @@ }; struct ResolutionInfo { + uint64_t CommonSize = 0; + unsigned CommonAlign = 0; bool IsLinkonceOdr = true; bool UnnamedAddr = true; GlobalValue::VisibilityTypes Visibility = GlobalValue::DefaultVisibility; bool CommonInternal = false; bool UseCommon = false; - unsigned CommonSize = 0; - unsigned CommonAlign = 0; - claimed_file *CommonFile = nullptr; }; } @@ -465,15 +464,6 @@ if (GV) { Res.UnnamedAddr &= GV->hasUnnamedAddr(); Res.IsLinkonceOdr &= GV->hasLinkOnceLinkage(); - if (GV->hasCommonLinkage()) { - Res.CommonAlign = std::max(Res.CommonAlign, GV->getAlignment()); - const DataLayout &DL = GV->getParent()->getDataLayout(); - uint64_t Size = DL.getTypeAllocSize(GV->getType()->getElementType()); - if (Size >= Res.CommonSize) { - Res.CommonSize = Size; - Res.CommonFile = &cf; - } - } Res.Visibility = getMinVisibility(Res.Visibility, GV->getVisibility()); switch (GV->getVisibility()) { case GlobalValue::DefaultVisibility: @@ -602,12 +592,10 @@ return Obj.takeIndex(); } -static std::unique_ptr -getModuleForFile(LLVMContext &Context, claimed_file &F, - ld_plugin_input_file &Info, raw_fd_ostream *ApiFile, - StringSet<> &Internalize, StringSet<> &Maybe, - std::vector &Keep) { - +static std::unique_ptr getModuleForFile( + LLVMContext &Context, claimed_file &F, ld_plugin_input_file &Info, + raw_fd_ostream *ApiFile, StringSet<> &Internalize, StringSet<> &Maybe, + std::vector &Keep, StringMap &Realign) { ld_plugin_status status = get_symbols(F.handle, F.syms.size(), F.syms.data()); if (status == LDPS_NO_SYMS) return nullptr; @@ -670,7 +658,6 @@ // Override gold's resolution for common symbols. We want the largest // one to win. if (GV->hasCommonLinkage()) { - cast(GV)->setAlignment(Res.CommonAlign); if (Resolution == LDPR_PREVAILING_DEF_IRONLY) Res.CommonInternal = true; @@ -678,14 +665,29 @@ Resolution == LDPR_PREVAILING_DEF) Res.UseCommon = true; - if (Res.CommonFile == &F && Res.UseCommon) { + const DataLayout &DL = GV->getParent()->getDataLayout(); + uint64_t Size = DL.getTypeAllocSize(GV->getType()->getElementType()); + unsigned Align = GV->getAlignment(); + + if (Res.UseCommon && Size >= Res.CommonSize) { + // Take GV. if (Res.CommonInternal) Resolution = LDPR_PREVAILING_DEF_IRONLY; else Resolution = LDPR_PREVAILING_DEF; + cast(GV)->setAlignment( + std::max(Res.CommonAlign, Align)); } else { + // Do not take GV, it's smaller than what we already have in the + // combined module. Resolution = LDPR_PREEMPTED_IR; + if (Align > Res.CommonAlign) + // Need to raise the alignment though. + Realign[Sym.name] = Align; } + + Res.CommonSize = std::max(Res.CommonSize, Size); + Res.CommonAlign = std::max(Res.CommonAlign, Align); } switch (Resolution) { @@ -914,8 +916,10 @@ for (claimed_file &F : Modules) { PluginInputFile InputFile(F.handle); std::vector Keep; - std::unique_ptr M = getModuleForFile( - Context, F, InputFile.file(), ApiFile, Internalize, Maybe, Keep); + StringMap Realign; + std::unique_ptr M = + getModuleForFile(Context, F, InputFile.file(), ApiFile, Internalize, + Maybe, Keep, Realign); if (!M.get()) continue; if (!options::triple.empty()) @@ -925,6 +929,13 @@ if (L.move(std::move(M), Keep, [](GlobalValue &, IRMover::ValueAdder) {})) message(LDPL_FATAL, "Failed to link module"); + + for (const auto &I : Realign) { + GlobalValue *Dst = Combined->getNamedValue(I.first()); + if (!Dst) + continue; + cast(Dst)->setAlignment(I.second); + } } for (const auto &Name : Internalize) {