Index: lib/Transforms/Utils/SimplifyCFG.cpp =================================================================== --- lib/Transforms/Utils/SimplifyCFG.cpp +++ lib/Transforms/Utils/SimplifyCFG.cpp @@ -1254,23 +1254,23 @@ BasicBlock::iterator BB2_Itr = BB2->begin(); Instruction *I1 = &*BB1_Itr++, *I2 = &*BB2_Itr++; - // Skip debug info if it is not identical. - DbgInfoIntrinsic *DBI1 = dyn_cast(I1); - DbgInfoIntrinsic *DBI2 = dyn_cast(I2); - if (!DBI1 || !DBI2 || !DBI1->isIdenticalToWhenDefined(DBI2)) { - while (isa(I1)) + BasicBlock *BIParent = BI->getParent(); + + bool Changed = false; + for (;;) { + // Move over debug info from both sides unchanged. + while (isa(I1)) { + BIParent->getInstList().splice(BI->getIterator(), BB1->getInstList(), I1); I1 = &*BB1_Itr++; - while (isa(I2)) + } + while (isa(I2)) { + BIParent->getInstList().splice(BI->getIterator(), BB2->getInstList(), I2); I2 = &*BB2_Itr++; - } - if (isa(I1) || !I1->isIdenticalToWhenDefined(I2) || - (isa(I1) && !isSafeToHoistInvoke(BB1, BB2, I1, I2))) - return false; + } - BasicBlock *BIParent = BI->getParent(); + if (isa(I1) || !I1->isIdenticalToWhenDefined(I2)) + return Changed; - bool Changed = false; - do { // If we are hoisting the terminator instruction, don't move one (making a // broken BB), instead clone it, and remove BI. if (isa(I1)) @@ -1318,18 +1318,7 @@ I1 = &*BB1_Itr++; I2 = &*BB2_Itr++; - // Skip debug info if it is not identical. - DbgInfoIntrinsic *DBI1 = dyn_cast(I1); - DbgInfoIntrinsic *DBI2 = dyn_cast(I2); - if (!DBI1 || !DBI2 || !DBI1->isIdenticalToWhenDefined(DBI2)) { - while (isa(I1)) - I1 = &*BB1_Itr++; - while (isa(I2)) - I2 = &*BB2_Itr++; - } - } while (I1->isIdenticalToWhenDefined(I2)); - - return true; + } HoistTerminator: // It may not be possible to hoist an invoke. Index: test/Transforms/SimplifyCFG/hoist-dbgvalue-inlined.ll =================================================================== --- test/Transforms/SimplifyCFG/hoist-dbgvalue-inlined.ll +++ test/Transforms/SimplifyCFG/hoist-dbgvalue-inlined.ll @@ -0,0 +1,47 @@ +; RUN: opt -simplifycfg -S < %s | FileCheck %s +; Verify that we don't crash due an invalid !dbg location on the hoisted llvm.dbg.value + +define i64 @caller(i64* %ptr, i64 %flag) !dbg !10 { +; CHECK: llvm.dbg.value +init: + %v9 = icmp eq i64 %flag, 0 + br i1 %v9, label %a, label %b + +a: ; preds = %init + %vala = load i64, i64* %ptr, align 8 + call void @llvm.dbg.value(metadata i64 %vala, metadata !8, metadata !DIExpression()), !dbg !12 + br label %test.exit + +b: ; preds = %init + %valb = load i64, i64* %ptr, align 8 + call void @llvm.dbg.value(metadata i64 %valb, metadata !8, metadata !DIExpression()), !dbg !13 + %valbmasked = and i64 %valb, 1 + br label %test.exit + +test.exit: ; preds = %a, %b + %retv = phi i64 [ %vala, %a ], [ %valbmasked, %b ] + ret i64 %retv +} + +; Function Attrs: nounwind readnone speculatable +declare void @llvm.dbg.value(metadata, metadata, metadata) #0 + +attributes #0 = { nounwind readnone speculatable } + +!llvm.module.flags = !{!0} +!llvm.dbg.cu = !{!1} + +!0 = !{i32 2, !"Debug Info Version", i32 3} +!1 = distinct !DICompileUnit(language: DW_LANG_C_plus_plus, file: !2, isOptimized: true, runtimeVersion: 0, emissionKind: FullDebug, enums: !3) +!2 = !DIFile(filename: "optbug", directory: "") +!3 = !{} +!4 = distinct !DISubprogram(name: "callee", scope: !2, file: !2, line: 1, type: !5, isLocal: false, isDefinition: true, scopeLine: 1, isOptimized: false, unit: !1, variables: !7) +!5 = !DISubroutineType(types: !6) +!6 = !{null} +!7 = !{!8} +!8 = !DILocalVariable(name: "var", scope: !4, file: !2, type: !9) +!9 = !DIBasicType(name: "var_t", size: 64, encoding: DW_ATE_unsigned) +!10 = distinct !DISubprogram(name: "caller", scope: !2, file: !2, line: 5, type: !5, isLocal: false, isDefinition: true, scopeLine: 5, isOptimized: false, unit: !1, variables: !3) +!11 = distinct !DILocation(line: 6, scope: !10) +!12 = !DILocation(line: 2, scope: !4, inlinedAt: !11) +!13 = !DILocation(line: 3, scope: !4, inlinedAt: !11)