Merge alignment of common GlobalValue.
[oota-llvm.git] / lib / Linker / LinkModules.cpp
index 87d075fb03ee2658dfe40449ad252615c1771827..0313e2b8a7e085f55453873d2898276537c90f0e 100644 (file)
@@ -688,6 +688,9 @@ bool ModuleLinker::shouldLinkFromSource(const GlobalValue &Dest,
   bool SrcIsDeclaration = isDeclaration(Src);
   bool DestIsDeclaration = isDeclaration(Dest);
 
+  // FIXME: Make datalayout mandatory and just use getDataLayout().
+  DataLayout DL(Dest.getParent());
+
   if (SrcIsDeclaration) {
     // If Src is external or if both Src & Dest are external..  Just link the
     // external globals, we aren't adding anything.
@@ -702,14 +705,26 @@ bool ModuleLinker::shouldLinkFromSource(const GlobalValue &Dest,
     // If Dest is external but Src is not:
     return true;
 
+  if (Src.hasCommonLinkage()) {
+    if (Dest.hasLinkOnceLinkage() || Dest.hasWeakLinkage())
+      return true;
+
+    if (!Dest.hasCommonLinkage())
+      return false;
+
+    uint64_t DestSize = DL.getTypeAllocSize(Dest.getType()->getElementType());
+    uint64_t SrcSize = DL.getTypeAllocSize(Src.getType()->getElementType());
+    return SrcSize > DestSize;
+  }
+
   if (Src.isWeakForLinker()) {
     assert(!Dest.hasExternalWeakLinkage());
     assert(!Dest.hasAvailableExternallyLinkage());
+
     if (Dest.hasLinkOnceLinkage() && Src.hasWeakLinkage())
       return true;
 
-    return (Dest.hasLinkOnceLinkage() || Dest.hasWeakLinkage()) &&
-           Src.hasCommonLinkage();
+    return false;
   }
 
   if (Dest.isWeakForLinker()) {
@@ -986,6 +1001,7 @@ bool ModuleLinker::linkGlobalProto(GlobalVariable *SGV) {
   GlobalValue *DGV = getLinkedToGlobal(SGV);
   llvm::Optional<GlobalValue::VisibilityTypes> NewVisibility;
   bool HasUnnamedAddr = SGV->hasUnnamedAddr();
+  unsigned Alignment = SGV->getAlignment();
 
   bool LinkFromSrc = false;
   Comdat *DC = nullptr;
@@ -1010,15 +1026,22 @@ bool ModuleLinker::linkGlobalProto(GlobalVariable *SGV) {
         return true;
       NewVisibility = NV;
       HasUnnamedAddr = HasUnnamedAddr && DGV->hasUnnamedAddr();
+      if (DGV->hasCommonLinkage() && SGV->hasCommonLinkage())
+        Alignment = std::max(Alignment, DGV->getAlignment());
+      else if (!LinkFromSrc)
+        Alignment = DGV->getAlignment();
 
       // If we're not linking from the source, then keep the definition that we
       // have.
       if (!LinkFromSrc) {
         // Special case for const propagation.
-        if (GlobalVariable *DGVar = dyn_cast<GlobalVariable>(DGV))
+        if (GlobalVariable *DGVar = dyn_cast<GlobalVariable>(DGV)) {
+          DGVar->setAlignment(Alignment);
+
           if (DGVar->isDeclaration() && SGV->isConstant() &&
               !DGVar->isConstant())
             DGVar->setConstant(true);
+        }
 
         // Set calculated linkage, visibility and unnamed_addr.
         DGV->setLinkage(NewLinkage);
@@ -1056,6 +1079,7 @@ bool ModuleLinker::linkGlobalProto(GlobalVariable *SGV) {
                        SGV->getType()->getAddressSpace());
   // Propagate alignment, visibility and section info.
   copyGVAttributes(NewDGV, SGV);
+  NewDGV->setAlignment(Alignment);
   if (NewVisibility)
     NewDGV->setVisibility(*NewVisibility);
   NewDGV->setUnnamedAddr(HasUnnamedAddr);