-
Notifications
You must be signed in to change notification settings - Fork 12.4k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
CodeGenPrepare::placeDbgValues moves llvm.dbg.value without proper analysis #31226
Comments
assigned to @jmorse |
If you could verify that your input IR behaves the same for an in-tree |
reproducer |
I added example input that shows the issue on x86 when inspecting the -print-after-all log. The final assembler output for x86 looks fine though. Maybe something later in the llc hides the issue? I don't have a good understanding of the llvm.dbg.value stuff. Maybe the input to CodeGenPrepare is already strange? Is it allowed to have the call to llvm.dbg.value far away from the actual definition? I could not see anything about this in the documentation. This example has a loop where two values of "n" are live at the same time. Both values are calculated early, but the second value is not valid right where it is calculated. Is this situation allowed? When I experimented with completely disabling the placeDbgValues() function the compiled code in my out-of-tree back-end gets good debug info. For x86 it did not make a difference (the variable "n" is optimized out in much of the function). |
I have been thinking a bit more about this problem. Maybe it is %_tmp64 = add nsw i16 %n.12.0, -1 If this instruction would have had an associated line number, the I tracked the missing metadata back to opt. Below are some snippets *** IR Dump Before Global Value Numbering *** bb2: ; preds = %bb1, %bb0 !66 = !DILocation(line: 47, column: 30, scope: !56) *** IR Dump After Global Value Numbering *** bb0.bb2_crit_edge: ; preds = %bb0 bb1: ; preds = %bb0 bb2: ; preds = %bb0.bb2_crit_edge, %bb1 !66 = !DILocation(line: 47, column: 30, scope: !56) *** IR Dump After Simplify the CFG *** bb1: ; preds = %bb0 bb2: ; preds = %bb0, %bb1 At this point there is no line number information at all on the "add nsw i16 %n.12.0, -1"! Maybe PlaceDbgValues does the right thing if the instruction it |
Input to opt |
Reproducer in gdb (require both foo.c and foo1.c) Start gdb: Reading symbols from foo...done. Breakpoint 1, foo () at foo.c:17 This is false the v1 variable at this point should be 1. The value 1 exist in a register as it is about to be passed to the calls to usevals, but the DEBUG_VALUE of the dead assignment after usevals have erroneously been moved by the CodeGenPrepare pass in llvm (directly before instruction selection). *** IR Dump After Interleaved Access Pass *** |
I've just stumbled upon this ticket -- it seems I wound up rediscovering this problem in bug 38754, reaching much the same conclusions, that placeDbgValues is damaging debug experience through careless reordering. I've stuck 38754 in the blocks field to indicate these are related. I'm currently corralling patches to fix this, hopefully with as little regression as possible. |
placeDbgValues was significantly limited in 00e2388, and it looks like the patch is sticking. There's still some work to be done with debug use-before-defs (which are already an error-state), but the vast majority of faulty behaviour should now be fixed. |
mentioned in issue #38102 |
Extended Description
I think CodeGenPrepare::placeDbgValues moves llvm.dbg.value too much
in this example:
Input to CodeGenPrepare. The interesting part is the last call to llvm.dbg.value
*** IR Dump Before CodeGen Prepare ***
; Function Attrs: noinline nounwind
define void @move(i16 %from.9.par, i16 %to.10.par, i16 %aux.11.par, i16 %n.12.par, [7 x i16]* nocapture %poles.13.par, i16* nocapture %height.14.par) local_unnamed_addr #1 !dbg !6 {
tail call void @llvm.dbg.value(metadata i16 %n.12.par, i64 0, metadata !15, metadata !16), !dbg !17
%_tmp49 = getelementptr i16, i16* %height.14.par, i16 %to.10.par, !dbg !18
%_tmp55 = mul i16 %to.10.par, 7, !dbg !18
%_tmp57 = getelementptr [7 x i16], [7 x i16]* %poles.13.par, i16 0, i16 %_tmp55, !dbg !18
br label %bb0, !dbg !19
bb0: ; preds = %bb2, %0
%n.12.0 = phi i16 [ %n.12.par, %0 ], [ %_tmp64, %bb2 ]
%aux.11.0 = phi i16 [ %aux.11.par, %0 ], [ %from.9.0, %bb2 ]
%from.9.0 = phi i16 [ %from.9.par, %0 ], [ %aux.11.0, %bb2 ]
tail call void @llvm.dbg.value(metadata i16 %n.12.0, i64 0, metadata !15, metadata !16), !dbg !17
%_tmp59 = icmp sgt i16 %n.12.0, 1, !dbg !20
%_tmp64 = add nsw i16 %n.12.0, -1
br i1 %_tmp59, label %bb1, label %bb2, !dbg !20
bb1: ; preds = %bb0
tail call void @move(i16 %from.9.0, i16 %aux.11.0, i16 %to.10.par, i16 %_tmp64, [7 x i16]* %poles.13.par, i16* %height.14.par), !dbg !21
br label %bb2, !dbg !21
bb2: ; preds = %bb1, %bb0
%_tmp68 = load i16, i16* %_tmp49, align 1, !dbg !23
%_tmp70 = add i16 %_tmp68, 1, !dbg !24
store i16 %_tmp70, i16* %_tmp49, align 1, !dbg !24
%_tmp75 = getelementptr i16, i16* %height.14.par, i16 %from.9.0, !dbg !24
%_tmp77 = load i16, i16* %_tmp75, align 1, !dbg !24
%_tmp78 = add i16 %_tmp77, -1, !dbg !24
store i16 %_tmp78, i16* %_tmp75, align 1, !dbg !24
%_tmp83 = mul i16 %from.9.0, 7, !dbg !24
%_tmp85 = getelementptr [7 x i16], [7 x i16]* %poles.13.par, i16 0, i16 %_tmp83, !dbg !24
%_tmp89 = getelementptr i16, i16* %_tmp85, i16 %_tmp78, !dbg !24
%_tmp90 = load i16, i16* %_tmp89, align 1, !dbg !24
%_tmp94 = getelementptr i16, i16* %_tmp57, i16 %_tmp68, !dbg !24
store i16 %_tmp90, i16* %_tmp94, align 1, !dbg !24
%_tmp9712 = load i16, i16* %_tmp75, align 1, !dbg !25
%_tmp99 = getelementptr i16, i16* %_tmp85, i16 %_tmp9712, !dbg !25
store i16 0, i16* %_tmp99, align 1, !dbg !25
tail call void @show([7 x i16]* %poles.13.par, i16* undef), !dbg !26
;;;;;; Here "n" should get the updated value (n = n - 1).
tail call void @llvm.dbg.value(metadata i16 %_tmp64, i64 0, metadata !15, metadata !16), !dbg !17
%1 = add i16 %_tmp64, 1, !dbg !20
%bb0.termcond = icmp sgt i16 %1, 1, !dbg !20
br i1 %bb0.termcond, label %bb0, label %bb4, !dbg !27
bb4: ; preds = %bb2
ret void, !dbg !28
}
!15 = !DILocalVariable(name: "n", arg: 4, scope: !6, line: 47, type: !9)
And here's the output, note how the last llvm.dbg.value has been moved
to %bb0.
*** IR Dump After CodeGen Prepare ***
; Function Attrs: noinline nounwind
define void @move(i16 %from.9.par, i16 %to.10.par, i16 %aux.11.par, i16 %n.12.par, [7 x i16]* nocapture %poles.13.par, i16* nocapture %height.14.par) local_unnamed_addr #1 !dbg !6 {
tail call void @llvm.dbg.value(metadata i16 %n.12.par, i64 0, metadata !15, metadata !16), !dbg !17
%_tmp49 = getelementptr i16, i16* %height.14.par, i16 %to.10.par, !dbg !18
%_tmp55 = mul i16 %to.10.par, 7, !dbg !18
%_tmp57 = getelementptr [7 x i16], [7 x i16]* %poles.13.par, i16 0, i16 %_tmp55, !dbg !18
br label %bb0, !dbg !19
bb0: ; preds = %bb2, %0
%n.12.0 = phi i16 [ %n.12.par, %0 ], [ %_tmp64, %bb2 ]
%aux.11.0 = phi i16 [ %aux.11.par, %0 ], [ %from.9.0, %bb2 ]
%from.9.0 = phi i16 [ %from.9.par, %0 ], [ %aux.11.0, %bb2 ]
tail call void @llvm.dbg.value(metadata i16 %n.12.0, i64 0, metadata !15, metadata !16), !dbg !17
%_tmp59 = icmp sgt i16 %n.12.0, 1, !dbg !20
%_tmp64 = add nsw i16 %n.12.0, -1
;;;;; Now "n" is updated with its new value already in this block.
tail call void @llvm.dbg.value(metadata i16 %_tmp64, i64 0, metadata !15, metadata !16), !dbg !17
br i1 %_tmp59, label %bb1, label %bb2, !dbg !20
bb1: ; preds = %bb0
tail call void @move(i16 %from.9.0, i16 %aux.11.0, i16 %to.10.par, i16 %_tmp64, [7 x i16]* %poles.13.par, i16* %height.14.par), !dbg !21
br label %bb2, !dbg !21
bb2: ; preds = %bb1, %bb0
%_tmp68 = load i16, i16* %_tmp49, align 1, !dbg !23
%_tmp70 = add i16 %_tmp68, 1, !dbg !24
store i16 %_tmp70, i16* %_tmp49, align 1, !dbg !24
%_tmp75 = getelementptr i16, i16* %height.14.par, i16 %from.9.0, !dbg !24
%_tmp77 = load i16, i16* %_tmp75, align 1, !dbg !24
%_tmp78 = add i16 %_tmp77, -1, !dbg !24
store i16 %_tmp78, i16* %_tmp75, align 1, !dbg !24
%_tmp83 = mul i16 %from.9.0, 7, !dbg !24
%_tmp85 = getelementptr [7 x i16], [7 x i16]* %poles.13.par, i16 0, i16 %_tmp83, !dbg !24
%_tmp89 = getelementptr i16, i16* %_tmp85, i16 %_tmp78, !dbg !24
%_tmp90 = load i16, i16* %_tmp89, align 1, !dbg !24
%_tmp94 = getelementptr i16, i16* %_tmp57, i16 %_tmp68, !dbg !24
store i16 %_tmp90, i16* %_tmp94, align 1, !dbg !24
%_tmp9712 = load i16, i16* %_tmp75, align 1, !dbg !25
%_tmp99 = getelementptr i16, i16* %_tmp85, i16 %_tmp9712, !dbg !25
store i16 0, i16* %_tmp99, align 1, !dbg !25
tail call void @show([7 x i16]* %poles.13.par, i16* undef), !dbg !26
%1 = add i16 %_tmp64, 1, !dbg !20
%bb0.termcond = icmp sgt i16 %1, 1, !dbg !20
br i1 %bb0.termcond, label %bb0, label %bb4, !dbg !27
bb4: ; preds = %bb2
ret void, !dbg !28
}
Running the resulting code in a debugger shows an incorrect value for
the variable n. In this case it would have been better if this call to
llvm.dbg.value had been dropped instead of moved.
I discovered this in a testcase in our out-of-tree target. If you
agree that this looks like a bug I can try to make a reproducer for an
in-tree target.
The text was updated successfully, but these errors were encountered: