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_0.ll b/llvm/test/LTO/X86/Inputs/type-mapping-bug4_0.ll new file mode 100644 --- /dev/null +++ b/llvm/test/LTO/X86/Inputs/type-mapping-bug4_0.ll @@ -0,0 +1,11 @@ +target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128" +target triple = "x86_64-unknown-linux-gnu" + +%class.CWBD = type { float } +%"class.std::_Unique_ptr_base" = type { %class.CWBD* } + +%class.CB = type opaque + +!llvm.module.flags = !{!0, !1} +!0 = !{i32 1, !"ThinLTO", i32 0} +!1 = !{i32 2, !"Debug Info Version", i32 3} diff --git a/llvm/test/LTO/X86/Inputs/type-mapping-bug4_1.ll b/llvm/test/LTO/X86/Inputs/type-mapping-bug4_1.ll new file mode 100644 --- /dev/null +++ b/llvm/test/LTO/X86/Inputs/type-mapping-bug4_1.ll @@ -0,0 +1,55 @@ +target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128" +target triple = "x86_64-unknown-linux-gnu" + +%class.CCSM = type opaque +%class.CWBD = type { float } + +%"class.std::_Unique_ptr_base" = type { %class.CWBD* } + +%class.CB = type { %"class.std::unique_ptr_base.1" } +; (stage1.1) +; %class.std::unique_ptr_base.1(t1.o) is mapped to %class.std::unique_ptr_base(t0.o) +; %class.CCSM(t1.o) is mapped to %class.CWBD(t0.o) +%"class.std::unique_ptr_base.1" = type { %class.CCSM* } + +; (stage1.2) +; %class.CCSM(t1.o) -> %class.CWBD(t0.o) mapping of stage1.1 maps this to +; "declare void @h(%class.CWBD*)" +declare void @h(%class.CCSM*) +define void @j() { + call void @h(%class.CCSM* undef) + ret void +} + +define void @a() { + ; Without the fix in D87001 to delay materialization of @d until its module is linked + ; (stage1.3) + ; mapping `%class.CB* undef` creates the first instance of %class.CB (%class.CB). + ; (stage2) + ; mapping `!6` starts the stage2, during which second instance of %class.CB (%class.CB.1) + ; is created for the mapped @d declaration. + ; define void @d(%class.CB.1*) + ; After this, %class.CB (t2.o) (aka %class.CB.1) and + ; %"class.std::unique_ptr_base.2" (t2.o) are added to DstStructTypesSet. + call void @llvm.dbg.value(metadata %class.CB* undef, metadata !6, metadata !DIExpression()), !dbg !4 + ret void +} + +declare void @llvm.dbg.value(metadata, metadata, metadata) + +!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) +!3 = !DIFile(filename: "f2", directory: "") + +!4 = !DILocation(line: 117, column: 34, scope: !7) + +; This DICompositeType refers to !5 in type-mapping-bug4.ll +!5 = !DICompositeType(tag: DW_TAG_structure_type, flags: DIFlagFwdDecl, identifier: "SHARED") + +!6 = !DILocalVariable(name: "this", arg: 1, scope: !7, flags: DIFlagArtificial | DIFlagObjectPointer) +!7 = distinct !DISubprogram(name: "a", type: !8, unit: !2) +!8 = !DISubroutineType(types: !9) +!9 = !{null, !5} 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,77 @@ +; RUN: opt -module-summary -o %t0.o %S/Inputs/type-mapping-bug4_0.ll +; RUN: opt -module-summary -o %t1.o %S/Inputs/type-mapping-bug4_1.ll +; RUN: opt -module-summary -o %t2.o %s +; RUN: llvm-lto2 run -save-temps -o %t3 %t0.o %t1.o %t2.o -r %t1.o,a,px -r %t2.o,d,px -r %t1.o,h,x -r %t2.o,h,x -r %t1.o,j,px +; RUN: llvm-dis < %t3.0.0.preopt.bc | FileCheck %s + +; stage0: linking t0.o +; stage1: linking t1.o +; stage2: during linking t1.o, mapping @d +; stage3: linking t2.o + +; Stage0 is not described because it is not interesting for the purpose of this test. +; Stage1 and stage2 are described in type-mapping-bug4_1.ll. +; Stage3 is described in this file. + +; CHECK: %class.CCSM = type opaque +; CHECK: %class.CB = type { %"class.std::unique_ptr_base.1" } +; CHECK: %"class.std::unique_ptr_base.1" = type { %class.CCSM* } + +; CHECK: define void @j() { +; CHECK: call void @h(%class.CCSM* undef) +; CHECK: ret void +; CHECK: } + +; CHECK: declare void @h(%class.CCSM*) + +; CHECK: define void @a() { +; CHECK: call void @llvm.dbg.value(metadata %class.CB* undef, metadata !10, metadata !DIExpression()) +; CHECK: ret void +; CHECK: } + +; CHECK: declare void @llvm.dbg.value(metadata, metadata, metadata) #0 + +; CHECK: define void @d(%class.CB* %0) { +; CHECK: %2 = getelementptr inbounds %class.CB, %class.CB* undef, i64 0, i32 0, i32 0 +; CHECK: ret void +; CHECK: } + +target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128" +target triple = "x86_64-unknown-linux-gnu" + +; (stage3) Remapping this type returns itself due to D47898 and stage1.3 +%class.CB = type { %"class.std::unique_ptr_base.2" } + +; (stage3) Remapping this type returns itself due to D47898 and stage2 +%"class.std::unique_ptr_base.2" = type { %class.CCSM* } + +%class.CCSM = type opaque + +; (stage3) computeTypeMapping add the mapping %class.CCSM -> %class.CWBD due to stage1.2 +declare void @h(%class.CCSM*) + +define void @d(%class.CB*) { + ; Without the fix in D87001 to delay materialization of @d until its module is linked + ; (stage3) + ; * SourceElementType of getelementptr is remapped to itself. + ; * ResultElementType of getelementptr is incorrectly remapped to %class.CWBD*. + ; Its type should be %class.CCSM*. + %2 = getelementptr inbounds %class.CB, %class.CB* undef, i64 0, i32 0, i32 0 + ret void +} + +!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_1.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 %class.CB that gets loaded into %t1.o +!7 = !DITemplateValueParameter(value: void (%class.CB*)* @d)