diff --git a/llvm/lib/Linker/IRMover.cpp b/llvm/lib/Linker/IRMover.cpp --- a/llvm/lib/Linker/IRMover.cpp +++ b/llvm/lib/Linker/IRMover.cpp @@ -242,15 +242,6 @@ bool IsUniqued = !isa(Ty) || cast(Ty)->isLiteral(); if (!IsUniqued) { - StructType *STy = cast(Ty); - // This is actually a type from the destination module, this can be reached - // when this type is loaded in another module, added to DstStructTypesSet, - // and then we reach the same type in another module where it has not been - // added to MappedTypes. (PR37684) - if (STy->getContext().isODRUniquingDebugTypes() && !STy->isOpaque() && - DstStructTypesSet.hasType(STy)) - return *Entry = STy; - #ifndef NDEBUG for (auto &Pair : MappedTypes) { assert(!(Pair.first != Ty && Pair.second == Ty) && @@ -258,7 +249,7 @@ } #endif - if (!Visited.insert(STy).second) { + if (!Visited.insert(cast(Ty)).second) { StructType *DTy = StructType::create(Ty->getContext()); return *Entry = DTy; } @@ -579,6 +570,13 @@ if (!SGV) return nullptr; + // When linking a global from other modules than source & dest, skip + // materializing it because it would be mapped later when its containing + // module is linked. Linking it now would potentially pull in many types that + // may not be mapped properly. + if (SGV->getParent() != &DstM && SGV->getParent() != SrcM.get()) + return nullptr; + Expected NewProto = linkGlobalValueProto(SGV, ForIndirectSymbol); if (!NewProto) { setError(NewProto.takeError()); diff --git a/llvm/test/LTO/X86/Inputs/type-mapping-bug4.ll b/llvm/test/LTO/X86/Inputs/type-mapping-bug4.ll new file mode 100644 --- /dev/null +++ b/llvm/test/LTO/X86/Inputs/type-mapping-bug4.ll @@ -0,0 +1,25 @@ +target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128" +target triple = "x86_64-unknown-linux-gnu" + +%"T2" = type opaque +%"T3" = type { i32 } + +define i32 @a(%"T2"*) !dbg !6 { + %X = alloca %"T3" + %W = getelementptr %"T3", %"T3"* %X, i32 0, i32 0 + %V = load i32, i32* %W + ret i32 %V +} + +!llvm.module.flags = !{!0, !1} +!llvm.dbg.cu = !{!2} +!0 = !{i32 1, !"ThinLTO", i32 0} +!1 = !{i32 2, !"Debug Info Version", i32 3} +!2 = distinct !DICompileUnit(language: DW_LANG_C_plus_plus, file: !3, retainedTypes: !4) +!3 = !DIFile(filename: "f2", directory: "") +!4 = !{!5} + +; This DICompositeType refers to !5 in type-mapping-bug4.ll +!5 = !DICompositeType(tag: DW_TAG_structure_type, flags: DIFlagFwdDecl, identifier: "SHARED") + +!6 = distinct !DISubprogram(unit: !2) diff --git a/llvm/test/LTO/X86/type-mapping-bug4.ll b/llvm/test/LTO/X86/type-mapping-bug4.ll new file mode 100644 --- /dev/null +++ b/llvm/test/LTO/X86/type-mapping-bug4.ll @@ -0,0 +1,36 @@ +; RUN: opt -module-summary -o %t0.o %S/Inputs/type-mapping-bug4.ll +; RUN: opt -module-summary -o %t1.o %s +; RUN: llvm-lto2 run -o %t2 --save-temps %t0.o %t1.o -r %t0.o,a,px -r %t1.o,a, -r %t1.o,c,px +; RUN: llvm-dis < %t2.0.0.preopt.bc | FileCheck %s + +; CHECK: %T2 = type { i32 } +; makes sure %T3 was not renamed %T3.0 because the linking of C is skipped. +; CHECK: %T3 = type { i32 } + +target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128" +target triple = "x86_64-unknown-linux-gnu" + +%"T2" = type { i32 } +%"T3" = type { i32 } + +define void @c(%"T3"*) { + ret void +} + +declare void @a(%"T2"*) + +!llvm.dbg.cu = !{!2} +!llvm.module.flags = !{!0, !1} +!0 = !{i32 1, !"ThinLTO", i32 0} +!1 = !{i32 2, !"Debug Info Version", i32 3} +!2 = distinct !DICompileUnit(language: DW_LANG_C_plus_plus, file: !3, retainedTypes: !4) +!3 = !DIFile(filename: "f1", directory: "") +!4 = !{!5} + +; This DICompositeType is referenced by !5 in Inputs/type-mapping-bug4.ll +; causing the function type in !7 to be added to its module. +!5 = !DICompositeType(tag: DW_TAG_structure_type, templateParams: !6, identifier: "SHARED") +!6 = !{!7} + +; The reference to d and T3 that gets loaded into %t0.o +!7 = !DITemplateValueParameter(value: void (%"T3"*)* @c)