Index: lib/Transforms/Utils/Local.cpp =================================================================== --- lib/Transforms/Utils/Local.cpp +++ lib/Transforms/Utils/Local.cpp @@ -1702,9 +1702,6 @@ // TODO: Salvage constants from each kind of binop we know about. return nullptr; } - } else if (isa(&I)) { - // Rewrite the load into DW_OP_deref. - return DIExpression::prepend(SrcDIExpr, DIExpression::WithDeref); } return nullptr; } Index: test/DebugInfo/Generic/pr40628.ll =================================================================== --- /dev/null +++ test/DebugInfo/Generic/pr40628.ll @@ -0,0 +1,57 @@ +; RUN: opt -early-cse -S %s -o - | FileCheck %s + +; PR40628: The first load below is determined to be redundant by EarlyCSE. +; During salvaging, the corresponding dbg.value could have a DW_OP_deref used +; in its DIExpression to represent the redundant operation -- however LLVM +; cannot currently determine that the subsequent store should terminate the +; variables location range. A debugger would display zero for the "redundant" +; variable after stepping onto the return instruction. +; +; Disallow DW_OP_deref in the output entirely (until we come up with a +; solution to the range analysis). + +; CHECK-NOT: DW_OP_deref + +target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128" +target triple = "x86_64-unknown-linux-gnu" + +define dso_local i32 @foo(i32*, i32, i32) !dbg !7 { + %4 = load i32, i32* %0, align 4, !dbg !18, !tbaa !19 + call void @llvm.dbg.value(metadata i32 %4, metadata !16, metadata !DIExpression()), !dbg !23 + %5 = load i32, i32* %0, align 4, !dbg !24, !tbaa !19 + call void @llvm.dbg.value(metadata i32 %5, metadata !17, metadata !DIExpression()), !dbg !25 + store i32 0, i32* %0, align 4, !dbg !26 + ret i32 %5, !dbg !27 +} + +declare void @llvm.dbg.value(metadata, metadata, metadata) + +!llvm.dbg.cu = !{!0} +!llvm.module.flags = !{!3, !4, !5} +!llvm.ident = !{!6} + +!0 = distinct !DICompileUnit(language: DW_LANG_C99, file: !1, producer: "clang", isOptimized: true, runtimeVersion: 0, emissionKind: FullDebug, enums: !2, nameTableKind: None) +!1 = !DIFile(filename: "pr40628.c", directory: ".") +!2 = !{} +!3 = !{i32 2, !"Dwarf Version", i32 4} +!4 = !{i32 2, !"Debug Info Version", i32 3} +!5 = !{i32 1, !"wchar_size", i32 4} +!6 = !{!"clang"} +!7 = distinct !DISubprogram(name: "foo", scope: !1, file: !1, line: 2, type: !8, scopeLine: 3, flags: DIFlagPrototyped, spFlags: DISPFlagDefinition | DISPFlagOptimized, unit: !0, retainedNodes: !12) +!8 = !DISubroutineType(types: !9) +!9 = !{!10, !11, !10, !10} +!10 = !DIBasicType(name: "int", size: 32, encoding: DW_ATE_signed) +!11 = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: !10, size: 64) +!12 = !{!16, !17} +!16 = !DILocalVariable(name: "redundant", scope: !7, file: !1, line: 4, type: !10) +!17 = !DILocalVariable(name: "loaded", scope: !7, file: !1, line: 5, type: !10) +!18 = !DILocation(line: 4, column: 19, scope: !7) +!19 = !{!20, !20, i64 0} +!20 = !{!"int", !21, i64 0} +!21 = !{!"omnipotent char", !22, i64 0} +!22 = !{!"Simple C/C++ TBAA"} +!23 = !DILocation(line: 4, column: 7, scope: !7) +!24 = !DILocation(line: 5, column: 16, scope: !7) +!25 = !DILocation(line: 5, column: 7, scope: !7) +!26 = !DILocation(line: 6, column: 15, scope: !7) +!27 = !DILocation(line: 8, column: 8, scope: !7) Index: test/Transforms/DeadStoreElimination/debuginfo.ll =================================================================== --- test/Transforms/DeadStoreElimination/debuginfo.ll +++ test/Transforms/DeadStoreElimination/debuginfo.ll @@ -6,23 +6,21 @@ declare void @test_f() -define i32* @test_salvage() { +define i32* @test_salvage(i32 %arg) { ; Check that all four original local variables have their values preserved. -; CHECK-LABEL: @test_salvage() +; CHECK-LABEL: @test_salvage( ; CHECK-NEXT: malloc ; CHECK-NEXT: @llvm.dbg.value(metadata i8* %p, metadata ![[p:.*]], metadata !DIExpression()) ; CHECK-NEXT: bitcast ; CHECK-NEXT: @llvm.dbg.value(metadata i32* %P, metadata ![[P:.*]], metadata !DIExpression()) -; CHECK-NEXT: @llvm.dbg.value(metadata i32* %P, metadata ![[DEAD:.*]], metadata !DIExpression(DW_OP_deref)) -; CHECK-NEXT: call void @llvm.dbg.value(metadata i32* %P, metadata ![[DEAD2:.*]], metadata !DIExpression(DW_OP_deref, DW_OP_plus_uconst, 1, DW_OP_stack_value)) +; CHECK-NEXT: @llvm.dbg.value(metadata i32 %arg, metadata ![[DEAD:.*]], metadata !DIExpression(DW_OP_plus_uconst, 1, DW_OP_stack_value)) ; CHECK-NEXT: call void @test_f() ; CHECK-NEXT: store i32 0, i32* %P %p = tail call i8* @malloc(i32 4) %P = bitcast i8* %p to i32* - %DEAD = load i32, i32* %P - %DEAD2 = add i32 %DEAD, 1 - store i32 %DEAD2, i32* %P + %DEAD = add i32 %arg, 1 + store i32 %DEAD, i32* %P call void @test_f() store i32 0, i32* %P ret i32* %P @@ -31,4 +29,3 @@ ; CHECK: ![[p]] = !DILocalVariable(name: "1" ; CHECK: ![[P]] = !DILocalVariable(name: "2" ; CHECK: ![[DEAD]] = !DILocalVariable(name: "3" -; CHECK: ![[DEAD2]] = !DILocalVariable(name: "4" Index: test/Transforms/GVN/fence.ll =================================================================== --- test/Transforms/GVN/fence.ll +++ test/Transforms/GVN/fence.ll @@ -1,4 +1,4 @@ -; RUN: opt -S -debugify -basicaa -gvn < %s | FileCheck %s +; RUN: opt -S -basicaa -gvn < %s | FileCheck %s @a = external constant i32 ; We can value forward across the fence since we can (semantically) @@ -18,10 +18,8 @@ ; Same as above define i32 @test2(i32* %addr.i) { ; CHECK-LABEL: @test2 -; CHECK-NEXT: call void @llvm.dbg.value(metadata i32* %addr.i, metadata [[var_a:![0-9]+]], metadata !DIExpression(DW_OP_deref)) ; CHECK-NEXT: fence ; CHECK-NOT: load -; CHECK-NEXT: call void @llvm.dbg.value(metadata i32* %addr.i, metadata [[var_a2:![0-9]+]], metadata !DIExpression(DW_OP_deref)) ; CHECK: ret %a = load i32, i32* %addr.i, align 4 fence release @@ -88,6 +86,3 @@ ; } ; Given we chose to forward across the release fence, we clearly can't forward ; across the acquire fence as well. - -; CHECK: [[var_a]] = !DILocalVariable -; CHECK-NEXT: [[var_a2]] = !DILocalVariable Index: test/Transforms/InstCombine/debuginfo-dce.ll =================================================================== --- test/Transforms/InstCombine/debuginfo-dce.ll +++ test/Transforms/InstCombine/debuginfo-dce.ll @@ -23,6 +23,9 @@ %struct.entry = type { %struct.entry* } +; This salvage can't currently occur safely (PR40628), however if/when that's +; ever fixed, then this is definitely a piece of test coverage that should +; be maintained. define void @salvage_load(%struct.entry** %queue) local_unnamed_addr #0 !dbg !14 { entry: %im_not_dead = alloca %struct.entry* @@ -31,8 +34,7 @@ call void @llvm.dbg.value(metadata %struct.entry* %1, metadata !18, metadata !20), !dbg !19 ; CHECK: define void @salvage_load ; CHECK-NEXT: entry: -; CHECK-NEXT: call void @llvm.dbg.value(metadata %struct.entry** %queue, -; CHECK-SAME: metadata !DIExpression(DW_OP_deref, DW_OP_plus_uconst, 0)) +; CHECK-NOT: dbg.value store %struct.entry* %1, %struct.entry** %im_not_dead, align 8 ret void, !dbg !21 }