llvm / llvm-project

The LLVM Project is a collection of modular and reusable compiler and toolchain technologies.
http://llvm.org
Other
29.12k stars 12.01k forks source link

[DebugInfo@O2][Dexter] Misleading value for local variable at the return statement. #38687

Open CarlosAlbertoEnciso opened 6 years ago

CarlosAlbertoEnciso commented 6 years ago
Bugzilla Link 39339
Version trunk
OS Linux
Blocks llvm/llvm-project#38116
CC @adrian-prantl,@dstenb,@dwblaikie,@flametop,@gregbedwell,@JDevlieghere,@jmorse,@pogo59,@Melamoto,@vedantk,@wjristow,@wolfy1961

Extended Description

Spawned from bug 39187:

By modifying the original test case to:

--------8<-------- int main() { volatile int foo = 4;

int beards = 0; int birds = 0;

if (foo == 4) { beards = 8; birds = 3; } else { beards = 4; birds = 6; }

return beards; } -------->8--------

When stopping at the return, the variable 'birds' shows always the value of zero.

SLTozer commented 4 years ago

A fix has been completed for this issue (see the above comment), but it has twice now been reverted after being merged in due to causing timeouts and build failures, which apparently result from a massive increase in the number of debug intrinsics remaining, described and addressed for one case in[0]. It seems as though it's going to be difficult to implement this change in a way that doesn't result in an excessive number of undef intrinsics being left in the program in order to defend against values falling out of date. There may need to be some broader changes made to how we handle intrinsics (especially undef values) before we can fix this issue permanently.

[0] https://reviews.llvm.org/D73054

SLTozer commented 4 years ago

Closed in: https://reviews.llvm.org/D70318

The patch above is currently reverted and pending remerge, but otherwise is the fix for the issue described here.

jmorse commented 5 years ago

As it happens, this isn't a duplicate of bug llvm/llvm-bugzilla-archive#40795 . Instead, it seems that what's happening here is SimplifyCFG is folding two now empty blocks together:

--------8<-------- %4 = icmp eq i32 %3, 4, !dbg !​26 br i1 %4, label %5, label %6, !dbg !​27 5:
call void @​llvm.dbg.value(metadata i32 8, metadata !​14, [...] call void @​llvm.dbg.value(metadata i32 3, metadata !​15, [...] br label %7, !dbg !​28 6:
call void @​llvm.dbg.value(metadata i32 4, metadata !​14, [...] call void @​llvm.dbg.value(metadata i32 6, metadata !​15, [...] br label %7 7:
%8 = phi i32 [ 8, %5 ], [ 4, %6 ], !dbg !​30 -------->8--------

And dropping all the dbg.values, allowing earlier ones to propagate to the return statement, representing assignments that are now untrue.

jmorse commented 5 years ago

Smells like this might be very similar to bug 40795, the value of "birds" would require a PHI after the conditionals, but SROA/mem2reg doesn't insert one because by that point it's dead code. No dbg.value gets inserted either, and stale variable assignments are left valid until the end of the function.

CarlosAlbertoEnciso commented 6 years ago

What happens in the return beards + birds situation?

At the return statement, both variables show the value 0.

CarlosAlbertoEnciso commented 6 years ago

If birds has been completely DCEd, I'd hope to see an "optimized out" message rather than 0 here at least.

Just to confirm that no "optimized out" message is displayed.

gregbedwell commented 6 years ago

If birds has been completely DCEd, I'd hope to see an "optimized out" message rather than 0 here at least.

What happens in the return beards + birds situation?

CarlosAlbertoEnciso commented 6 years ago

The following links seems to deal with this situation:

https://reviews.llvm.org/D41044

http://lists.llvm.org/pipermail/llvm-dev/2015-September/090611.html

https://groups.google.com/forum/#!topic/llvm-dev/eNbpOxFYytA

The concept of extending the use (fake) of local variables to improve the debugging experience of optimized code.

CarlosAlbertoEnciso commented 6 years ago

When stopping at the return, the variable 'birds' shows always the value of zero.

For this case, no debug values are generated for 'birds'.

After SROA:

define i32 @​main() #​0 !dbg !​8 { entry: [...]

if.then: [...] br label %if.end, !dbg !​27

if.else: [...] br label %if.end

if.end: %beards.0 = phi i32 [ 8, %if.then ], [ 4, %if.else ], !dbg !​29 call void @​llvm.dbg.value(... %beards.0, ...), !dbg !​22 [...] ret i32 %beards.0, !dbg !​31 }

At the return statement, there is no debug_value intrinsic for 'birds'.

All the instructions associated with 'birds' are deleted:

Deleting dead instruction: store i32 6, i32 %birds, align 4, !dbg !​33 Deleting dead instruction: store i32 3, i32 %birds, align 4, !dbg !​29 Deleting dead instruction: store i32 0, i32* %birds, align 4, !dbg !​23

CarlosAlbertoEnciso commented 6 years ago

For the test in comment 0, when stopping at the return statement:

Original 'return beards;'

'birds' shows 0 'beards' shows 8

Changing the return statement to:

'return beards + birds;'

'birds' shows 0 'beards' shows 0

CarlosAlbertoEnciso commented 6 years ago

I'll have a look.

CarlosAlbertoEnciso commented 6 years ago

assigned to @CarlosAlbertoEnciso