Index: lib/Linker/IRMover.cpp =================================================================== --- lib/Linker/IRMover.cpp +++ lib/Linker/IRMover.cpp @@ -550,8 +550,10 @@ Value *IRLinker::materialize(Value *V, bool ForAlias) { auto *SGV = dyn_cast(V); - if (!SGV) - return nullptr; + + // Don't materialize GV from different source module. + if (!SGV || SGV->getParent() != SrcM.get()) + return nullptr; Expected NewProto = linkGlobalValueProto(SGV, ForAlias); if (!NewProto) { Index: test/ThinLTO/X86/Inputs/fwd-decl.ll =================================================================== --- test/ThinLTO/X86/Inputs/fwd-decl.ll +++ test/ThinLTO/X86/Inputs/fwd-decl.ll @@ -0,0 +1,29 @@ +target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128" +target triple = "x86_64-unknown-linux-gnu" + +%struct.TA = type opaque +@gv = external dso_local global %struct.TA * + +define i1 @b(%struct.TA*) { + unreachable +} + +define i1 @a(%struct.TA* %a) { + call i1 @b(%struct.TA* %a) + unreachable +} + +!llvm.module.flags = !{!0, !1} +!llvm.dbg.cu = !{!2} +!0 = !{i32 2, !"Debug Info Version", i32 3} +!1 = !{i32 1, !"ThinLTO", i32 0} +!2 = distinct !DICompileUnit(language: DW_LANG_C_plus_plus, file: !3, retainedTypes: !4) +!3 = !DIFile(filename: "f1", directory: "") +!4 = !{!5, !9} +!5 = !DICompositeType(tag: DW_TAG_class_type, file: !3, templateParams: !6, scope: !8) +!6 = !{!7} + +; The reference to @b and struct.TA.0 (renamed) that will be loaded in %a.o +!7 = !DITemplateValueParameter(value: i1 (%struct.TA*)* @b) +!8 = distinct !DISubprogram(unit: !2) +!9 = !DICompositeType(tag: DW_TAG_array_type, identifier: "SHARED", scope: !8) Index: test/ThinLTO/X86/fwd-decl.ll =================================================================== --- test/ThinLTO/X86/fwd-decl.ll +++ test/ThinLTO/X86/fwd-decl.ll @@ -0,0 +1,32 @@ +; Ensures IRMover only materializes values from current source module. +; RUN: opt -module-summary %s -o %t1.bc +; RUN: opt -module-summary %p/Inputs/fwd-decl.ll -o %t2.bc +; RUN: llvm-lto2 run -save-temps -o %t3.bc %t1.bc %t2.bc -r %t1.bc,c,px -r %t2.bc,a,px -r %t2.bc,b,px -r %t1.bc,gv -r %t2.bc,gv +; RUN: llvm-dis %t3.bc.0.0.preopt.bc -o - | FileCheck %s + +; CHECK: define i1 @a(%struct.TA* %a) +; CHECK-NEXT: %1 = call i1 @b(%struct.TA* %a) + +target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128" +target triple = "x86_64-unknown-linux-gnu" + +%struct.TA = type {} + +@gv = dso_local global %struct.TA * zeroinitializer + +define i32 @c() !dbg !6 { + bitcast %struct.TA ** @gv to i8* + unreachable +} + +!llvm.module.flags = !{!0, !1} +!llvm.dbg.cu = !{!2} +!0 = !{i32 2, !"Debug Info Version", i32 3} +!1 = !{i32 1, !"ThinLTO", i32 0} +!2 = distinct !DICompileUnit(language: DW_LANG_C_plus_plus, file: !3, retainedTypes: !4) +!3 = !DIFile(filename: "f2", directory: "") +!4 = !{!5} +!5 = !DICompositeType(tag: DW_TAG_class_type, file: !3, flags: DIFlagFwdDecl, identifier: "SHARED") +!6 = distinct !DISubprogram(unit: !2) + +