Why variables get "optimized away" after the last use in unoptimized code?

I am seeing this with llvm generated code, and before also saw this with gcc generated code.
In unoptimized code, debugger would say something like this when the variable isn't used any more, but is still in scope:
(gdb) p this
$11 = <optimized out>

Looking at the debug records, I don't see what is wrong, for example:
   call void @llvm.dbg.declare(metadata !{%struct.Object* %1}, metadata !73), !dbg !74
!73 = metadata !{i32 786689, metadata !63, metadata !"this", metadata !68, i32 33554949, metadata !12, i32 0, i32 0} ; [ DW_TAG_arg_variable ] [this] [line 517]
!63 is DW_TAG_subprogram scope.

'this' should exist through this subprogram, and never disappear. But it becomes "optimized away" after the last explicit use. Same is true with any other variable.
Doesn't this mean that llvm generates wrong DWARF info?
I don't think that debugger should ever say <optimized out> in unoptimized code.

Yuri

In most calling conventions, this is a callee-save register. After its last use, the register allocator may reuse that register. On x86 and ARM, the register that contains this is also (usually) the register used for return values, so it definitely will reuse it at some point before return in any method that returns a value. The only way to avoid this would be to spill it to the stack and have the debug information point to the spill slot. If there are any function / method calls within the method, this will be spilled and so there will be a copy of it on the stack. It might be quite nice for the debug info to prefer to reference this one, but it's not possible for most other parameters.

David

But the rule "after the last use, the register allocator may reuse it" is also introduced by llvm, since register allocator is also llvm. So this means that the rule "preserve any values while in scope as much as possible" is probably a better one for debugging.

Yuri

I submitted the issue with my proposal: http://llvm.org/bugs/show_bug.cgi?id=18697

Yuri

This means that debug info would change code generation in order to
artificially lengthen the lifetimes of variables and is something that
is generally verboten when compiling for debug.

-eric

From: llvmdev-bounces@cs.uiuc.edu [mailto:llvmdev-bounces@cs.uiuc.edu]
On Behalf Of Eric Christopher
Sent: Sunday, February 02, 2014 10:04 PM
To: Yuri
Cc: LLVM Dev
Subject: Re: [LLVMdev] Why variables get "optimized away" after the last
use in unoptimized code?

This means that debug info would change code generation in order to
artificially lengthen the lifetimes of variables and is something that
is generally verboten when compiling for debug.

The "this" pointer is the most painful thing to lose, and two different
compilers I've known have introduced an artificial use of "this" in the
method epilog. Tie it to -O0 instead of -g to avoid the "-g changes
codegen" issue.

There's also the recent talk about extending ranges by not using "last
use" but "next clobber" as the endpoint. This is opportunistic rather
than intentional and requires dataflow on {reg, var} tuples, but it
also helps some.
--paulr

From: llvmdev-bounces@cs.uiuc.edu [mailto:llvmdev-bounces@cs.uiuc.edu]
On Behalf Of Eric Christopher
Sent: Sunday, February 02, 2014 10:04 PM
To: Yuri
Cc: LLVM Dev
Subject: Re: [LLVMdev] Why variables get "optimized away" after the last
use in unoptimized code?

This means that debug info would change code generation in order to
artificially lengthen the lifetimes of variables and is something that
is generally verboten when compiling for debug.

The "this" pointer is the most painful thing to lose, and two different
compilers I've known have introduced an artificial use of "this" in the
method epilog. Tie it to -O0 instead of -g to avoid the "-g changes
codegen" issue.

*shrug* The variable the user wants is always the most important, but
I agree 'this' can be pretty useful. I'm wary of introducing any
artificial uses though.

There's also the recent talk about extending ranges by not using "last
use" but "next clobber" as the endpoint. This is opportunistic rather
than intentional and requires dataflow on {reg, var} tuples, but it
also helps some.

*nod* That might be more interesting. Not sure about how much this
will add to compile time, but if it greatly increases usefulness (as
something we'd want to measure) then I'm not against it.

-eric