Consider the following example:
target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128" define i32 @foo(i32 %X, i32* %Y) !dbg !6 { entry: %0 = load i32, i32* %Y, align 4, !dbg !8 %cmp = icmp sgt i32 %X, -1, !dbg !9 br i1 %cmp, label %if.then, label %if.end, !dbg !10 if.then: ; preds = %entry %1 = load i32, i32* %Y, align 4, !dbg !11 %add = add nsw i32 %0, %1, !dbg !12 call void (...) @fubar() #2, !dbg !13 br label %if.end, !dbg !14 if.end: ; preds = %if.then, %entry %Result.0 = phi i32 [ %add, %if.then ], [ %0, %entry ] ret i32 %Result.0, !dbg !15 } declare void @fubar(...)
Where:
!8 = !DILocation(line: 3, column: 16, scope: !6) !9 = !DILocation(line: 5, column: 9, scope: !6) !10 = !DILocation(line: 5, column: 7, scope: !6) !11 = !DILocation(line: 6, column: 15, scope: !6) !12 = !DILocation(line: 6, column: 12, scope: !6) !13 = !DILocation(line: 7, column: 5, scope: !6) !14 = !DILocation(line: 8, column: 3, scope: !6) !15 = !DILocation(line: 10, column: 3, scope: !6)
GVN would remove the redundant load from basic block %if.then since it is trivially dominated by an equivalent load from the entry block.
The redundant load from %if.then is:
%1 = load i32, i32* %Y, align 4, !dbg !11
The dominating load from %entry is:
%0 = load i32, i32* %Y, align 4, !dbg !8
When removing the redundant load %1, GVN also updates the debug location of %0 with the debugloc of %1.
As a result, the load from %entry now incorrectly refers to "line: 6, column: 15" instead of "line: 3,
column: 16".
In the case of a fully redundant load LI dominated by an equivalent load V, GVN should always preserve the original debug location of V. Otherwise, we risk to introduce an incorrect stepping.
If V has debug info, then clearly it should not be modified. If V has a null debugloc, then it is still potentially incorrect to propagate LI's debugloc because LI may not post-dominate V (this is what happens in the example).
Please let me know if okay to commit.
Thanks,
Andrea