Index: include/llvm/Transforms/Utils/Cloning.h =================================================================== --- include/llvm/Transforms/Utils/Cloning.h +++ include/llvm/Transforms/Utils/Cloning.h @@ -144,7 +144,8 @@ const char *NameSuffix = "", ClonedCodeInfo *CodeInfo = nullptr, ValueMapTypeRemapper *TypeMapper = nullptr, - ValueMaterializer *Materializer = nullptr); + ValueMaterializer *Materializer = nullptr, + bool ExtractingFunctions = false); void CloneAndPruneIntoFromInst(Function *NewFunc, const Function *OldFunc, const Instruction *StartingInst, Index: lib/Transforms/IPO/MergeSimilarFunctions.cpp =================================================================== --- lib/Transforms/IPO/MergeSimilarFunctions.cpp +++ lib/Transforms/IPO/MergeSimilarFunctions.cpp @@ -1847,7 +1847,8 @@ (*DestI).setName("__merge_arg"); SmallVector Returns; - CloneFunctionInto(NewF, F1, VMap, false, Returns); + CloneFunctionInto(NewF, F1, VMap, false, Returns, "", nullptr, nullptr, + nullptr, true); // Set linkage to set visibility to default. NewF->setLinkage(GlobalValue::InternalLinkage); Index: lib/Transforms/Utils/CloneFunction.cpp =================================================================== --- lib/Transforms/Utils/CloneFunction.cpp +++ lib/Transforms/Utils/CloneFunction.cpp @@ -97,7 +97,8 @@ SmallVectorImpl &Returns, const char *NameSuffix, ClonedCodeInfo *CodeInfo, ValueMapTypeRemapper *TypeMapper, - ValueMaterializer *Materializer) { + ValueMaterializer *Materializer, + bool ExtractingFunction) { assert(NameSuffix && "NameSuffix cannot be null!"); #ifndef NDEBUG @@ -133,7 +134,7 @@ AttributeList::get(NewFunc->getContext(), OldAttrs.getFnAttributes(), OldAttrs.getRetAttributes(), NewArgAttrs)); - bool MustCloneSP = + bool MustCloneSP = !ExtractingFunction && OldFunc->getParent() && OldFunc->getParent() == NewFunc->getParent(); DISubprogram *SP = OldFunc->getSubprogram(); if (SP) { Index: test/Transforms/MergeSimilarFunc/merge-debug-info-2.ll =================================================================== --- /dev/null +++ test/Transforms/MergeSimilarFunc/merge-debug-info-2.ll @@ -0,0 +1,133 @@ +; RUN: opt -S -mergesimilarfunc < %s | FileCheck %s +; This used to fail with assertion in CloneFunction +; REQUIRES: asserts +; CHECK-LABEL: @foo__merged( + +target datalayout = "e-m:o-i64:64-i128:128-n32:64-S128" +target triple = "arm64-apple-ios8.0.0" + +%struct.wibble = type { %struct.wibble.0*, %struct.wibble* } +%struct.wibble.0 = type { i64*, i8*, i64*, i64*, %struct.eggs*, %struct.wibble* } +%struct.eggs = type { %struct.wombat*, %struct.eggs* } +%struct.wombat = type { i8*, %struct.blam*, %struct.blam* } +%struct.blam = type { i8*, %struct.blam* } +%struct.snork = type { %struct.bar*, %struct.snork* } +%struct.bar = type { i64*, i8* } + +; Function Attrs: argmemonly nounwind +declare void @llvm.lifetime.start.p0i8(i64, i8* nocapture) #0 + +; Function Attrs: minsize nounwind optsize ssp uwtable +define hidden void @foo(%struct.wibble* %arg) #1 align 2 !dbg !4 { +bb: + %tmp = alloca %struct.wibble*, align 8 + %tmp1 = alloca %struct.wibble*, align 8 + store %struct.wibble* %arg, %struct.wibble** %tmp, align 8 + %tmp2 = load %struct.wibble*, %struct.wibble** %tmp, align 8, !dbg !12 + %tmp3 = icmp ne %struct.wibble* %tmp2, null, !dbg !13 + br i1 %tmp3, label %bb4, label %bb13, !dbg !14 + +bb4: ; preds = %bb + %tmp5 = bitcast %struct.wibble** %tmp1 to i8*, !dbg !15 + call void @llvm.lifetime.start.p0i8(i64 8, i8* %tmp5) #2, !dbg !15 + %tmp6 = load %struct.wibble*, %struct.wibble** %tmp, align 8, !dbg !16 + store %struct.wibble* %tmp6, %struct.wibble** %tmp1, align 8, !dbg !17 + %tmp7 = load %struct.wibble*, %struct.wibble** %tmp, align 8, !dbg !18 + %tmp8 = getelementptr inbounds %struct.wibble, %struct.wibble* %tmp7, i32 0, i32 1, !dbg !19 + %tmp9 = load %struct.wibble*, %struct.wibble** %tmp8, align 8, !dbg !19 + store %struct.wibble* %tmp9, %struct.wibble** %tmp, align 8, !dbg !22 + call void @foo.1() #3, !dbg !26 + unreachable + +bb13: ; preds = %bb + ret void, !dbg !27 +} + +; Function Attrs: minsize nounwind optsize ssp uwtable +declare hidden void @foo.1() #1 align 2 + +; Function Attrs: minsize nounwind optsize ssp uwtable +define void @quux() unnamed_addr #1 align 2 !dbg !28 { +bb: + ret void +} + +; Function Attrs: minsize nounwind optsize ssp uwtable +define hidden void @baz(%struct.snork* %arg) #1 align 2 !dbg !30 { +bb: + %tmp = alloca %struct.snork*, align 8 + %tmp1 = alloca %struct.snork*, align 8 + store %struct.snork* %arg, %struct.snork** %tmp, align 8 + %tmp2 = load %struct.snork*, %struct.snork** %tmp, align 8, !dbg !31 + %tmp3 = icmp ne %struct.snork* %tmp2, null, !dbg !32 + br i1 %tmp3, label %bb4, label %bb13, !dbg !33 + +bb4: ; preds = %bb + %tmp5 = bitcast %struct.snork** %tmp1 to i8*, !dbg !34 + call void @llvm.lifetime.start.p0i8(i64 8, i8* %tmp5) #2, !dbg !34 + %tmp6 = load %struct.snork*, %struct.snork** %tmp, align 8, !dbg !35 + store %struct.snork* %tmp6, %struct.snork** %tmp1, align 8, !dbg !36 + %tmp7 = load %struct.snork*, %struct.snork** %tmp, align 8, !dbg !37 + %tmp8 = getelementptr inbounds %struct.snork, %struct.snork* %tmp7, i32 0, i32 1, !dbg !38 + %tmp9 = load %struct.snork*, %struct.snork** %tmp8, align 8, !dbg !38 + store %struct.snork* %tmp9, %struct.snork** %tmp, align 8, !dbg !39 + call void @blam() #3, !dbg !42 + unreachable + +bb13: ; preds = %bb + ret void, !dbg !43 +} + +; Function Attrs: minsize nounwind optsize ssp uwtable +declare hidden void @blam() #1 align 2 + +attributes #0 = { argmemonly nounwind } +attributes #1 = { minsize nounwind optsize ssp uwtable } +attributes #2 = { nounwind } +attributes #3 = { minsize optsize } + +!llvm.dbg.cu = !{!0} +!llvm.module.flags = !{!2, !3} + +!0 = distinct !DICompileUnit(language: DW_LANG_C_plus_plus, file: !1, producer: "(based on LLVM 5.0.0)", isOptimized: true, runtimeVersion: 0, emissionKind: LineTablesOnly) +!1 = !DIFile(filename: "foo.cpp", directory: "/") +!2 = !{i32 2, !"Debug Info Version", i32 3} +!3 = !{i32 7, !"PIC Level", i32 2} +!4 = distinct !DISubprogram(name: "delete", scope: !5, file: !5, line: 31, type: !6, isLocal: false, isDefinition: true, scopeLine: 32, flags: DIFlagPrototyped, isOptimized: true, unit: !0) +!5 = !DIFile(filename: "foo.h", directory: "/") +!6 = !DISubroutineType(types: !7) +!7 = !{} +!9 = !{!"any pointer", !10, i64 0} +!10 = !{!"omnipotent char", !11, i64 0} +!11 = !{!"Simple C++ TBAA"} +!12 = !DILocation(line: 33, column: 11, scope: !4) +!13 = !DILocation(line: 33, column: 16, scope: !4) +!14 = !DILocation(line: 33, column: 5, scope: !4) +!15 = !DILocation(line: 34, column: 7, scope: !4) +!16 = !DILocation(line: 34, column: 25, scope: !4) +!17 = !DILocation(line: 34, column: 18, scope: !4) +!18 = !DILocation(line: 35, column: 14, scope: !4) +!19 = !DILocation(line: 35, column: 20, scope: !4) +!21 = !{!"_ZTSN", !9, i64 0, !9, i64 8} +!22 = !DILocation(line: 35, column: 12, scope: !4) +!23 = !DILocation(line: 37, column: 25, scope: !4) +!24 = !DILocation(line: 37, column: 31, scope: !4) +!25 = !{!21, !9, i64 0} +!26 = !DILocation(line: 37, column: 7, scope: !4) +!27 = !DILocation(line: 41, column: 3, scope: !4) +!28 = distinct !DISubprogram(name: "~destruct", scope: !29, file: !29, line: 31, type: !6, isLocal: false, isDefinition: true, scopeLine: 32, flags: DIFlagPrototyped, isOptimized: true, unit: !0) +!29 = !DIFile(filename: "bar.h", directory: "/") +!30 = distinct !DISubprogram(name: "delete", scope: !5, file: !5, line: 31, type: !6, isLocal: false, isDefinition: true, scopeLine: 32, flags: DIFlagPrototyped, isOptimized: true, unit: !0) +!31 = !DILocation(line: 33, column: 11, scope: !30) +!32 = !DILocation(line: 33, column: 16, scope: !30) +!33 = !DILocation(line: 33, column: 5, scope: !30) +!34 = !DILocation(line: 34, column: 7, scope: !30) +!35 = !DILocation(line: 34, column: 25, scope: !30) +!36 = !DILocation(line: 34, column: 18, scope: !30) +!37 = !DILocation(line: 35, column: 14, scope: !30) +!38 = !DILocation(line: 35, column: 20, scope: !30) +!39 = !DILocation(line: 35, column: 12, scope: !30) +!40 = !DILocation(line: 37, column: 25, scope: !30) +!41 = !DILocation(line: 37, column: 31, scope: !30) +!42 = !DILocation(line: 37, column: 7, scope: !30) +!43 = !DILocation(line: 41, column: 3, scope: !30)