Index: lib/LTO/LTO.cpp =================================================================== --- lib/LTO/LTO.cpp +++ lib/LTO/LTO.cpp @@ -457,18 +457,35 @@ if (Sym.getFlags() & object::BasicSymbolRef::SF_Undefined) continue; - if (Res.Prevailing && Sym.isGV()) { + if (Sym.isGV()) { GlobalValue *GV = Sym.getGV(); - Keep.push_back(GV); - switch (GV->getLinkage()) { - default: - break; - case GlobalValue::LinkOnceAnyLinkage: - GV->setLinkage(GlobalValue::WeakAnyLinkage); - break; - case GlobalValue::LinkOnceODRLinkage: - GV->setLinkage(GlobalValue::WeakODRLinkage); - break; + if (Res.Prevailing) { + Keep.push_back(GV); + switch (GV->getLinkage()) { + default: + break; + case GlobalValue::LinkOnceAnyLinkage: + GV->setLinkage(GlobalValue::WeakAnyLinkage); + break; + case GlobalValue::LinkOnceODRLinkage: + GV->setLinkage(GlobalValue::WeakODRLinkage); + break; + } + } else { + // This definition is not prevailing, but we can still use it for + // optimization if it has ODR linkage. This is done by setting its + // linkage to AvailableExternallyLinkage. + // This causes a declaration to be emitted, and declarations cannot + // have comdats. Therefore, we can only set AvailableExternallyLinkage + // on symbols that don't have a comdat or from which we can remove + // the comdat. + if (GV->hasLinkOnceODRLinkage() || GV->hasWeakODRLinkage()) { + if (auto *G = dyn_cast(GV)) + G->setComdat(nullptr); + if (!GV->hasComdat()) { + GV->setLinkage(GlobalValue::AvailableExternallyLinkage); + } + } } } // Common resolution: collect the maximum size/alignment over all commons.