Index: llvm/trunk/lib/Transforms/Utils/SimplifyCFG.cpp =================================================================== --- llvm/trunk/lib/Transforms/Utils/SimplifyCFG.cpp +++ llvm/trunk/lib/Transforms/Utils/SimplifyCFG.cpp @@ -1290,31 +1290,44 @@ if (!TTI.isProfitableToHoist(I1) || !TTI.isProfitableToHoist(I2)) return Changed; - // For a normal instruction, we just move one to right before the branch, - // then replace all uses of the other with the first. Finally, we remove - // the now redundant second instruction. - BIParent->getInstList().splice(BI->getIterator(), BB1->getInstList(), I1); - if (!I2->use_empty()) - I2->replaceAllUsesWith(I1); - I1->andIRFlags(I2); - unsigned KnownIDs[] = {LLVMContext::MD_tbaa, - LLVMContext::MD_range, - LLVMContext::MD_fpmath, - LLVMContext::MD_invariant_load, - LLVMContext::MD_nonnull, - LLVMContext::MD_invariant_group, - LLVMContext::MD_align, - LLVMContext::MD_dereferenceable, - LLVMContext::MD_dereferenceable_or_null, - LLVMContext::MD_mem_parallel_loop_access}; - combineMetadata(I1, I2, KnownIDs); - - // I1 and I2 are being combined into a single instruction. Its debug - // location is the merged locations of the original instructions. - I1->applyMergedLocation(I1->getDebugLoc(), I2->getDebugLoc()); + if (isa(I1) || isa(I2)) { + assert (isa(I1) && isa(I2)); + // The debug location is an integral part of a debug info intrinsic + // and can't be separated from it or replaced. Instead of attempting + // to merge locations, simply hoist both copies of the intrinsic. + BIParent->getInstList().splice(BI->getIterator(), + BB1->getInstList(), I1); + BIParent->getInstList().splice(BI->getIterator(), + BB2->getInstList(), I2); + Changed = true; + } else { + // For a normal instruction, we just move one to right before the branch, + // then replace all uses of the other with the first. Finally, we remove + // the now redundant second instruction. + BIParent->getInstList().splice(BI->getIterator(), + BB1->getInstList(), I1); + if (!I2->use_empty()) + I2->replaceAllUsesWith(I1); + I1->andIRFlags(I2); + unsigned KnownIDs[] = {LLVMContext::MD_tbaa, + LLVMContext::MD_range, + LLVMContext::MD_fpmath, + LLVMContext::MD_invariant_load, + LLVMContext::MD_nonnull, + LLVMContext::MD_invariant_group, + LLVMContext::MD_align, + LLVMContext::MD_dereferenceable, + LLVMContext::MD_dereferenceable_or_null, + LLVMContext::MD_mem_parallel_loop_access}; + combineMetadata(I1, I2, KnownIDs); + + // I1 and I2 are being combined into a single instruction. Its debug + // location is the merged locations of the original instructions. + I1->applyMergedLocation(I1->getDebugLoc(), I2->getDebugLoc()); - I2->eraseFromParent(); - Changed = true; + I2->eraseFromParent(); + Changed = true; + } I1 = &*BB1_Itr++; I2 = &*BB2_Itr++; Index: llvm/trunk/test/Transforms/SimplifyCFG/hoist-dbgvalue-inlined.ll =================================================================== --- llvm/trunk/test/Transforms/SimplifyCFG/hoist-dbgvalue-inlined.ll +++ llvm/trunk/test/Transforms/SimplifyCFG/hoist-dbgvalue-inlined.ll @@ -0,0 +1,51 @@ +; 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 { +init: + %v9 = icmp eq i64 %flag, 0 + br i1 %v9, label %a, label %b + +; CHECK: %vala = load i64, i64* %ptr +; CHECK-NEXT: call void @llvm.dbg.value(metadata i64 %vala, metadata [[MD:![0-9]*]] +; CHECK-NEXT: call void @llvm.dbg.value(metadata i64 %vala, metadata [[MD]] +; CHECK-NEXT: %valbmasked = and i64 %vala, 1 + +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)