@@ -139,9 +139,17 @@ static UnnamedAddr getMinUnnamedAddr(UnnamedAddr lhs, UnnamedAddr rhs) {
139139
140140using ComdatKind = LLVM::comdat::Comdat;
141141
142- struct ComdatSelector {
143- StringRef name;
142+ struct Comdat {
144143 ComdatKind kind;
144+ Operation *selectorOp;
145+ llvm::SmallPtrSet<Operation *, 2 > users;
146+ };
147+
148+ enum class ComdatResolution {
149+ LinkFromSrc,
150+ LinkFromDst,
151+ LinkFromBoth,
152+ Failure,
145153};
146154
147155// ===----------------------------------------------------------------------===//
@@ -172,6 +180,20 @@ class LLVMLinkerMixin {
172180 if (derived.isComdat (pair.src ))
173181 return true ;
174182
183+ // Thrown away symbol can affect the visibility
184+ if (pair.dst ) {
185+ Visibility srcVisibility = derived.getVisibility (pair.src );
186+ Visibility dstVisibility = derived.getVisibility (pair.dst );
187+ Visibility visibility = getMinVisibility (srcVisibility, dstVisibility);
188+
189+ derived.setVisibility (pair.src , visibility);
190+ derived.setVisibility (pair.dst , visibility);
191+ }
192+ if (derived.hasComdat (pair.src )) {
193+ // operations with COMDAT are selected as a group
194+ return derived.selectedByComdat (pair.src );
195+ }
196+
175197 Linkage srcLinkage = derived.getLinkage (pair.src );
176198
177199 // Always import variables with appending linkage.
@@ -218,6 +240,10 @@ class LLVMLinkerMixin {
218240 return pair.src ->emitError (error) << " dst: " << pair.dst ->getLoc ();
219241 };
220242
243+ if (derived.isComdat (pair.src ) != derived.isComdat (pair.dst )) {
244+ return linkError (" Linking ComdatOp with non-comdat op" );
245+ }
246+
221247 Linkage srcLinkage = derived.getLinkage (pair.src );
222248 Linkage dstLinkage = derived.getLinkage (pair.dst );
223249
@@ -340,6 +366,11 @@ class LLVMLinkerMixin {
340366 if (isWeakForLinker (srcLinkage)) {
341367 assert (!isExternalWeakLinkage (dstLinkage));
342368 assert (!isAvailableExternallyLinkage (dstLinkage));
369+ const Comdat *comdat = derived.getComdatResolution (pair.src );
370+ if (comdat && comdat->kind == ComdatKind::NoDeduplicate) {
371+ derived.updateNoDeduplicate (pair.src );
372+ return ConflictResolution::LinkFromBothAndRenameSrc;
373+ }
343374 if (isLinkOnceLinkage (dstLinkage) && isWeakLinkage (srcLinkage)) {
344375 return ConflictResolution::LinkFromSrc;
345376 }
@@ -349,38 +380,12 @@ class LLVMLinkerMixin {
349380
350381 if (isWeakForLinker (dstLinkage)) {
351382 assert (isExternalLinkage (srcLinkage));
352- return ConflictResolution::LinkFromSrc;
353- }
354-
355- std::optional<ComdatSelector> srcComdatSel =
356- derived.getComdatSelector (pair.src );
357- std::optional<ComdatSelector> dstComdatSel =
358- derived.getComdatSelector (pair.dst );
359- if (srcComdatSel.has_value () && dstComdatSel.has_value ()) {
360- auto srcComdatName = srcComdatSel->name ;
361- auto dstComdatName = dstComdatSel->name ;
362- auto srcComdat = srcComdatSel->kind ;
363- auto dstComdat = dstComdatSel->kind ;
364- if (srcComdatName != dstComdatName) {
365- llvm_unreachable (" Comdat selector names don't match" );
366- }
367- if (srcComdat != dstComdat) {
368- llvm_unreachable (" Comdat selector kinds don't match" );
369- }
370-
371- if (srcComdat == mlir::LLVM::comdat::Comdat::Any) {
372- return ConflictResolution::LinkFromDst;
373- }
374- if (srcComdat == mlir::LLVM::comdat::Comdat::NoDeduplicate) {
375- return ConflictResolution::Failure;
383+ const Comdat *comdat = derived.getComdatResolution (pair.dst );
384+ if (comdat && comdat->kind == ComdatKind::NoDeduplicate) {
385+ derived.updateNoDeduplicate (pair.dst );
386+ return ConflictResolution::LinkFromBothAndRenameDst;
376387 }
377- if (srcComdat == mlir::LLVM::comdat::Comdat::ExactMatch) {
378- return ConflictResolution::LinkFromDst;
379- }
380- if (srcComdat == mlir::LLVM::comdat::Comdat::SameSize) {
381- return ConflictResolution::LinkFromDst;
382- }
383- llvm_unreachable (" unimplemented comdat kind" );
388+ return ConflictResolution::LinkFromSrc;
384389 }
385390
386391 // If we reach here, we have two external definitions that can't be resolved
0 commit comments