extending liveness of 'this' pointer via FAKE_USE opcode

Hello!

At Sony we’ve seen some serious customer interest in having the ‘this’ pointer visible throughout an entire function during

debugging. However, optimizations may eliminate it after its last use, so we’ve been looking for a way to artificially extend its

liverange to the end of the function.

So far, the most compelling way we can think of, and one we have used successfully in the past in at least one other compiler,

is to create a ‘fake use’ of the ‘this’ pointer at the end of the function, compelling the rest of the compiler to not optimize it away.

At the moment there doesn’t seem to be a good way to create such a fake use in LLVM (please enlighten us if you know of one), so we are

proposing to introduce a new intrinsic (e.g. llvm.fake_use), which would take a single value argument, representing a use of that value.

The intrinsic would be lowered to a new invariant TargetOpcode (e.g. FAKE_USE), which serves the same purpose at the MI level.

Code emission would simply ignore the new opcode.

Frontends could use the intrinsic to extend liveranges of variables as desired. As a first use case, clang would accept a new option

(e.g. -fkeep-this-ptr) which would cause a fake use of ‘this’ to be inserted at the end of a function, making it available for inspection

throughout the entire function body.

One important note is that since such an option would affect code generation, it cannot be automatically enabled by -g. However, should there be

eventually support for a -Og mode (optimize for debugging), that mode could enable it.

Any comments or alternative ideas are appreciated.

Oops, forgot to reply-all (& adding a few other people to the ‘to’ line)

Oops, forgot to reply-all (& adding a few other people to the 'to' line)

Hello!

At Sony we've seen some serious customer interest in having the 'this' pointer visible throughout an entire function during
debugging. However, optimizations may eliminate it after its last use, so we've been looking for a way to artificially extend its
liverange to the end of the function.

So far, the most compelling way we can think of, and one we have used successfully in the past in at least one other compiler,
is to create a 'fake use' of the 'this' pointer at the end of the function, compelling the rest of the compiler to not optimize it away.

At the moment there doesn't seem to be a good way to create such a fake use in LLVM (please enlighten us if you know of one), so we are
proposing to introduce a new intrinsic (e.g. llvm.fake_use), which would take a single value argument, representing a use of that value.
The intrinsic would be lowered to a new invariant TargetOpcode (e.g. FAKE_USE), which serves the same purpose at the MI level.
Code emission would simply ignore the new opcode.

Frontends could use the intrinsic to extend liveranges of variables as desired. As a first use case, clang would accept a new option
(e.g. -fkeep-this-ptr) which would cause a fake use of 'this' to be inserted at the end of a function, making it available for inspection
throughout the entire function body.

One important note is that since such an option would affect code generation, it cannot be automatically enabled by -g. However, should there be
eventually support for a -Og mode (optimize for debugging), that mode could enable it.

Any comments or alternative ideas are appreciated.

The clang frontend creates all variables in stack slots and relies on LLVM to lower them into registers if applicable. Would the new intrinsic refer to the stack slot, would it describe a load of the value?

What happens if the function is inlined, will the new intrinsic prevent other optimizations?

— adrian

From: David Blaikie [mailto:dblaikie@gmail.com]
Sent: Monday, September 21, 2015 11:23 AM
To: llvm-dev; Pieb, Wolfgang; Adrian Prantl; Frédéric Riss
Cc: Eric Christopher
Subject: Fwd: [llvm-dev] extending liveness of 'this' pointer via FAKE_USE opcode

Oops, forgot to reply-all (& adding a few other people to the 'to' line)
From: David Blaikie <dblaikie@gmail.com <mailto:dblaikie@gmail.com>>
Date: Mon, Sep 21, 2015 at 11:22 AM
Subject: Re: [llvm-dev] extending liveness of 'this' pointer via FAKE_USE opcode
To: "Pieb, Wolfgang" <Wolfgang_Pieb@playstation.sony.com <mailto:Wolfgang_Pieb@playstation.sony.com>>

Hello!

At Sony we've seen some serious customer interest in having the 'this' pointer visible throughout an entire function during debugging. However, optimizations may eliminate it after its last use, so we've been looking for a way to artificially extend its liverange to the end of the function.

How much have you observed the actual (usually a register, yes?) register being reused, versus the debug info just not successfully describing its location? LLVM's optimized debug info still does a pretty bad job tracking optimized values (especially anything that gets promoted out of an alloca into a register)

With respect to the ‘this’ pointer, (or parameters in general) I have observed register reuse after the last actual use of ‘this’. I haven’t seen any instance of the register still holding the value while the debug info is not describing it, but the sample of code I’ve looked at is not very large.

I’m still investigating locals in general.

Your experience does not sound very encouraging, but it would also be interesting to monitor the impact of http://reviews.llvm.org/D11933 regarding this problem.

— adrian

We faced a similar issue in LLILC, where our runtime requires us to report certain GC pointers as live (and have their values preserved) throughout certain methods. We considered some sort of fake_use construct, but we need these things to be live even in code that doesn’t reach return (e.g. paths that end in a noreturn call and unreachable), and weren’t keen on adding them to all such paths (and making sure optimizations can’t expose new such paths as they discover that code is unreachable), nor did we put much thought into how that might interfere with tailcall generation/modeling. So, at least for now, we’re calling the @llvm.localescape intrinsic on these addresses in the function entry block, with the expectation that doing so will make them appear live wherever we need them to be (which specifically is GC safe-points, which for us all involve calls to external code).

Your situation sounds different both in that you want this for debugging whereas we need it for correctness (so maybe the paths that lead to unreachable or infinite loops aren’t as interesting for you) and in that you may care about extending liveness past the last call (unlike we who just need to cover the GC safe-points), but FYI that’s what we’ve done in a somewhat similar situation.

We’d be happy to have something to use that’s explicitly for lifetime extension, so long as it covers the paths which don’t reach return.

Thanks

-Joseph

Why extend the live-range?

If it isn’t already in memory (and for many architectures, it is already in memory), put the this pointer into memory, and change the

debug information so that the location-expression of the this parameter is marked to be that memory?

That has two nice properties:

1 – If you do this early (in the function IR, not necessarily in the pass ordering), it really only costs a single store, and doesn’t otherwise really affect register allocation. Mark the memory itself in such a way that it cannot be deleted.

2 – This is only required for architectures/calling conventions where the this ptr isn’t already in memory, and where this extra debugging is required/desired.

Kevin Smith

From: aprantl@apple.com [mailto:aprantl@apple.com]
Sent: Monday, September 21, 2015 4:27 PM
To: Pieb, Wolfgang
Cc: llvm-dev@lists.llvm.org
Subject: Re: [llvm-dev] extending liveness of 'this' pointer via
FAKE_USE opcode

>
> Hello!
>
> At Sony we've seen some serious customer interest in having the
'this'
> pointer visible throughout an entire function during debugging.
> However, optimizations may eliminate it after its last use, so we've
been looking for a way to artificially extend its liverange to the end
of the function.
>
> So far, the most compelling way we can think of, and one we have used
> successfully in the past in at least one other compiler, is to create
a 'fake use' of the 'this' pointer at the end of the function,
compelling the rest of the compiler to not optimize it away.
>
> At the moment there doesn't seem to be a good way to create such a
> fake use in LLVM (please enlighten us if you know of one), so we are
proposing to introduce a new intrinsic (e.g. llvm.fake_use), which
would take a single value argument, representing a use of that value.
> The intrinsic would be lowered to a new invariant TargetOpcode (e.g.
FAKE_USE), which serves the same purpose at the MI level.
> Code emission would simply ignore the new opcode.
>
> Frontends could use the intrinsic to extend liveranges of variables
as
> desired. As a first use case, clang would accept a new option (e.g.
> -fkeep-this-ptr) which would cause a fake use of 'this' to be
inserted at the end of a function, making it available for inspection
throughout the entire function body.

>
> One important note is that since such an option would affect code
> generation, it cannot be automatically enabled by -g. However, should
there be eventually support for a -Og mode (optimize for debugging),
that mode could enable it.
>
> Any comments or alternative ideas are appreciated.

The clang frontend creates all variables in stack slots and relies on
LLVM to lower them into registers if applicable. Would the new
intrinsic refer to the stack slot, would it describe a load of the
value?

The intent is to represent a 'use' as if it were passed to a function as an argument, so a load would precede the invocation of the intrinsic.

What happens if the function is inlined, will the new intrinsic prevent
other optimizations?

Only indirectly as a result of extending its argument's lifetime. Obviously we'd have to make sure inline heuristics are not influenced by the presence of the intrinsic. Register pressure may increase which may influence scheduling etc. but there shouldn’t be any explicit suppression of particular optimizations.

We thought about putting the ‘this’ pointer into memory but that would mean that even small member functions would acquire a stack frame (on architectures where leaf routines can get away without one), which may degrade performance considerably. You could apply some heuristics and determine when a store is unnecessary, but inlining may complicate things. A fake_use operation would be inlined like any other instruction.

We performed some internal evaluations of location coverage (at –O1 on x86), and about half of the member functions already had 100% location coverage for the this pointer, mostly because they are small. For these methods extending the live range to the end of the function would probably make no difference in code generation anyway. For the longer routines, a fake-use at the end of the function would probably cause a spill early on, similar to the effect of an explicit store.

Another consideration is that we’d like to extend the concept to other variables as well. This ‘this’ pointer Is invariant, but other parameters and locals are generally not, so we believe extending the live range would be a more general solution.

– wolfgang

For the record I’m not a huge fan of this idea - mostly because I strongly believe that debug info should not change code generation. Under a flag might be ok, but I’d really rather not.

To ask, perhaps, a different question: what kind of debugging experience are you trying to accomplish here by extending the this pointer? I’m assuming something about method calls inside other methods? Might we figure out a different way to accomplish the same task?

Thanks!

-eric

For the record I'm not a huge fan of this idea - mostly because I strongly believe that debug info should not change code generation. Under a flag might be ok, but I'd really rather not.

To ask, perhaps, a different question: what kind of debugging experience are you trying to accomplish here by extending the this pointer? I'm assuming something about method calls inside other methods? Might we figure out a different way to accomplish the same task?

Well, generically, we’re trying to address the common case of the ‘this’ pointer (or any parameter and variable) having been optimized away at the point where the user is trying to see it. In the case of parameters, it may be possible to go up a stack frame and see it there, but that’s not guaranteed.
I understand that an alternative is for the debugger to capture values before they become unavailable (perhaps by setting breakpoints at the point of call). Interesting thought, but what would this do to debugging performance, which is one of our primary objectives with the extending-the-live range approach? Even if you make it cheap, what about other local variables that got optimized away?

-- wolfgang

Thanks!

-eric

David Blaikie via llvm-dev <llvm-dev@lists.llvm.org> writes:

Oops, forgot to reply-all (& adding a few other people to the 'to' line)
From: David Blaikie <dblaikie@gmail.com>
Date: Mon, Sep 21, 2015 at 11:22 AM
Subject: Re: [llvm-dev] extending liveness of 'this' pointer via FAKE_USE
opcode
To: "Pieb, Wolfgang" <Wolfgang_Pieb@playstation.sony.com>

Hello!

At Sony we've seen some serious customer interest in having the 'this'
pointer visible throughout an entire function during debugging. However,
optimizations may eliminate it after its last use, so we've been looking
for a way to artificially extend its liverange to the end of the function.

How much have you observed the actual (usually a register, yes?) register
being reused, versus the debug info just not successfully describing its
location? LLVM's optimized debug info still does a pretty bad job tracking
optimized values (especially anything that gets promoted out of an alloca
into a register)

In my experience, when the 'this' pointer is inaccessible when debugging
clang-generated code it's almost always the debug info failing to
describe the location. That is, I can very often find the correct value
by looking at the frame's registers.

I don't really see much value in trying to extend the live range until
after we've improved that situation, personally. Maybe you have a
different experience of how these issues come up than I do, though.