Optionally suppress debug info for inlined calls?

In general on our platform we don't want debug info for inlined calls
(messy, awkward things) but some people still like to see them. Currently
we turn them off unconditionally in our private tree, but we'd like to put
this under command-line control and send it upstream. Does anyone mind if
I do this? I was thinking a command-line option along the lines of
      -g[no-]inlined-scopes
We'd default to No on our target, Yes everywhere else. If you turn these
off, you don't get DW_TAG_inlined_scope, and the source location info for
all the inlined code becomes the call site (single-stepping would act like
it's an external call that you step over).

Thanks,
--paulr

Why do you want to turn this off?

Is it buggy? Could we fix it?
Is it too big? Could we reduce size in ways that are strict-wins instead?

I have already turned it off for my target, per request from licensees who don’t like seeing fake call frames that don’t reflect actual calls in the generated code. The size win doesn’t hurt but is secondary.

The problem now is that not everybody likes it that way, and so I want to make it optional, and I’d rather have the feature upstream than keep it private.

(While I’m not ready to file any bugs, I did notice some strangeness in the low/hi_pc ranges for some inlined ctors; the ranges mostly or completely overlapped, which didn’t seem right but I didn’t look into it. That’s not my focus right now.)

–paulr

I have _*already*_ turned it off for my target,

Right, I got that - was just trying to understand if/why that was the right
choice.

per request from licensees who don’t like seeing fake call frames that
don’t reflect actual calls in the generated code.

Just tossing around ideas to accommodate your licensees/Clang users: would
this make more sense as a feature of debuggers/stack trace tools, etc? Are
there particular places where this shows up and confuses users?

(Sorry about the quoting weirdness, Outlook sucks at HTML.)

Okay, here’s some back-story. The original desire was to suppress inlined scopes for functions that the source code said to inline. This would include things like methods defined inside the class declaration, functions with the always_inline attribute, and so forth. Methods and functions marked this way are typically small and typically not inherently interesting; getters and setters, for example. Constantly stepping into and out of these guys is just noise, from the debugging-experience point of view.

On prior Sony platforms, we achieved this effect by having the compiler omit the inlined scopes; in fact we omit ALL inlined scopes. So we were asked to do it the same way in Clang/LLVM. It wasn’t hard so we did. (The easy way to do it is actually in LLVM, not Clang.) But some teams still wanted the inlined scopes, and prior compilers had a command-line option to permit this, and that’s what I’m trying to provide now.

The space savings, while not the immediate goal, turned out to be non-trivial: In my benchmark I saw a 25% reduction. Remember that this is for “-O2 –g” not –O0, so LLVM is really trying to do a good job with inlining, and consequently dumping out a pile of DW_TAG_inlined_subroutine DIEs. It would be hard to give that up that size reduction. I know there have been a bunch of size improvements over the past year or so and the savings now might not be quite so dramatic, but DW_TAG_inlined_subroutine (and all its nested scopes and local variables) are not always cheap.

In the longer term, it would be nice if (a) Clang/LLVM would emit a DW_AT_inline attribute [which it does] with a fully correct DW_INL_foobar value [which it does not], and (b) our debugger learned to pay attention to that attribute, implicitly suppressing the frame for the case of DW_INL_declared_inlined [for example]. But it can’t do that until the attribute is correct, and even after we start emitting it correctly it still has to behave reasonably for older objects. And I can’t see how to make that happen without suppressing the scopes.

What we want right now is a way to let licensees get their inlined frames back, while preserving the current default behavior which is more-or-less consistent with our past practices.

Assuming DW_AT_inline becomes fully correct, then my proposed “-gno-inlined-scopes” would reduce to being a space-saving device, although it is potentially still a big win in those terms.

–paulr

I have _*already*_ turned it off for my target,

Right, I got that - was just trying to understand if/why that was the
right choice.

per request from licensees who don’t like seeing fake call frames that
don’t reflect actual calls in the generated code.

Just tossing around ideas to accommodate your licensees/Clang users: would
this make more sense as a feature of debuggers/stack trace tools, etc? Are
there particular places where this shows up and confuses users?

Aside from getter/setters like Paul mentioned, also SIMD vector types (as
you might expect, game engines are heavy users of SIMD vector types).
Essentially every arithmetic operation becomes a function call, and it's
not out of the ordinary to have, say, 30+ arithmetic operations in a single
short function (each compiling down to a single instruction of machine
code).

-- Sean Silva

I have _already_ turned it off for my target,

Right, I got that - was just trying to understand if/why that was the
right choice.

per request from licensees who don’t like seeing fake call frames that
don’t reflect actual calls in the generated code.

Just tossing around ideas to accommodate your licensees/Clang users: would
this make more sense as a feature of debuggers/stack trace tools, etc? Are
there particular places where this shows up and confuses users?

Aside from getter/setters like Paul mentioned, also SIMD vector types (as
you might expect, game engines are heavy users of SIMD vector types).
Essentially every arithmetic operation becomes a function call, and it's not
out of the ordinary to have, say, 30+ arithmetic operations in a single
short function (each compiling down to a single instruction of machine
code).

__attribute__((__always_inline__, __nodebug__))?

-eric

From: Eric Christopher [mailto:echristo@gmail.com]
Sent: Monday, November 25, 2013 1:33 PM
To: Sean Silva
Cc: David Blaikie; Robinson, Paul; cfe-dev@cs.uiuc.edu
Subject: Re: [cfe-dev] Optionally suppress debug info for inlined calls?

>
>
>
>>
>>
>>
>>
>>>
>>> I have _already_ turned it off for my target,
>>
>>
>> Right, I got that - was just trying to understand if/why that was the
>> right choice.
>>
>>>
>>> per request from licensees who don't like seeing fake call frames
that
>>> don't reflect actual calls in the generated code.
>>
>>
>> Just tossing around ideas to accommodate your licensees/Clang users:
would
>> this make more sense as a feature of debuggers/stack trace tools,
etc? Are
>> there particular places where this shows up and confuses users?
>
>
> Aside from getter/setters like Paul mentioned, also SIMD vector types
(as
> you might expect, game engines are heavy users of SIMD vector types).
> Essentially every arithmetic operation becomes a function call, and
it's not
> out of the ordinary to have, say, 30+ arithmetic operations in a
single
> short function (each compiling down to a single instruction of machine
> code).
>

__attribute__((__always_inline__, __nodebug__))?

In fact the intrinsics, and to a significant extent some
vector math libraries, do that. But, it's pretty tedious.
We'd like our game teams to spend their time on more productive
tasks than adding attribute(nodebug) to every method in every
header. Plus we have an interest in continuing to support
features that we have provided on previous platforms.
--paulr

From: Eric Christopher [mailto:echristo@gmail.com]
Sent: Monday, November 25, 2013 1:33 PM
To: Sean Silva
Cc: David Blaikie; Robinson, Paul; cfe-dev@cs.uiuc.edu
Subject: Re: [cfe-dev] Optionally suppress debug info for inlined calls?

>
>
>
>>
>>
>>
>>
>>>
>>> I have _already_ turned it off for my target,
>>
>>
>> Right, I got that - was just trying to understand if/why that was the
>> right choice.
>>
>>>
>>> per request from licensees who don't like seeing fake call frames
that
>>> don't reflect actual calls in the generated code.
>>
>>
>> Just tossing around ideas to accommodate your licensees/Clang users:
would
>> this make more sense as a feature of debuggers/stack trace tools,
etc? Are
>> there particular places where this shows up and confuses users?
>
>
> Aside from getter/setters like Paul mentioned, also SIMD vector types
(as
> you might expect, game engines are heavy users of SIMD vector types).
> Essentially every arithmetic operation becomes a function call, and
it's not
> out of the ordinary to have, say, 30+ arithmetic operations in a
single
> short function (each compiling down to a single instruction of machine
> code).
>

__attribute__((__always_inline__, __nodebug__))?

In fact the intrinsics, and to a significant extent some
vector math libraries, do that. But, it's pretty tedious.
We'd like our game teams to spend their time on more productive
tasks than adding attribute(nodebug) to every method in every
header. Plus we have an interest in continuing to support
features that we have provided on previous platforms.

I was replying to Sean's particular comments - I'm not sure I
understand your motivation other than compatibility. That's a pretty
strong reason, but this is the first I've heard of this sort of thing
and it really seems like it would negatively impact the debugging
experience.

What's the patch look like to do this?

-eric

> From: Eric Christopher [mailto:echristo@gmail.com]
> Sent: Monday, November 25, 2013 1:33 PM
> To: Sean Silva
> Cc: David Blaikie; Robinson, Paul; cfe-dev@cs.uiuc.edu
> Subject: Re: [cfe-dev] Optionally suppress debug info for inlined calls?
>
> >
> >
> >
> >>
> >>
> >>
> >>
> >>>
> >>> I have _already_ turned it off for my target,
> >>
> >>
> >> Right, I got that - was just trying to understand if/why that was the
> >> right choice.
> >>
> >>>
> >>> per request from licensees who don't like seeing fake call frames
> that
> >>> don't reflect actual calls in the generated code.
> >>
> >>
> >> Just tossing around ideas to accommodate your licensees/Clang users:
> would
> >> this make more sense as a feature of debuggers/stack trace tools,
> etc? Are
> >> there particular places where this shows up and confuses users?
> >
> >
> > Aside from getter/setters like Paul mentioned, also SIMD vector types
> (as
> > you might expect, game engines are heavy users of SIMD vector types).
> > Essentially every arithmetic operation becomes a function call, and
> it's not
> > out of the ordinary to have, say, 30+ arithmetic operations in a
> single
> > short function (each compiling down to a single instruction of machine
> > code).
> >
>
> __attribute__((__always_inline__, __nodebug__))?

In fact the intrinsics, and to a significant extent some
vector math libraries, do that. But, it's pretty tedious.

Most people wrap these things in macros anyway, so it wouldn't seem too bad
to add nodebug to whatever macro stamps out always_inline.

We'd like our game teams to spend their time on more productive
tasks than adding attribute(nodebug) to every method in every
header.

Fair point - this is where I was wondering if we could do a better job with
features in debuggers and/or debug info to appropriately describe such
trivial functions and have useful behavior for them in a debugger.

Dropping the information at such a coarse granularity as "all inline
functions" seems a bit, well, rough. If we could find a good heuristic for
"trivial inline functions" (maybe a function with a single setter or
return) and use that as our signal for "don't bother emitting debug info
for this" maybe that would be good. That would still provide the size wins
with the benefit that it might be beneficial to a broader range of users.

Though unless we can find a /really/ strong signal that allows us to guess
with certainty that some functions just aren't worth having debug info,
ever, I'd probably look towards debugger features that make this guess at
debug time and thus can be overridden without recompiling/rebuilding if the
guess is wrong.

Plus we have an interest in continuing to support
features that we have provided on previous platforms.

Certainly - but that's a burden for you right now. Once we add it as a
feature for Clang, it's a burden for all of us for a much longer timeframe,
perhaps. So you can see why we might want to ensure we're making the right
decision.

- David

Quick side comment - this would be helpful in some HPC use cases as well. Where stack/debugger tools can't be switched out "easily" like on other platforms

Are these class methods? Can we support slapping attribute(nodebug) on the
whole class definition maybe?

It really does seem desirable to get this to the state where little big
leaf functions have debug info but little math overloads are elided.

So again on platforms that don't support (at least) DWARF version 1.1
published October 6, 1992?

I so don't care about this part of the argument.

-eric

> > __attribute__((__always_inline__, __nodebug__))?
> In fact the intrinsics, and to a significant extent some
> vector math libraries, do that. But, it's pretty tedious.

Most people wrap these things in macros anyway, so it wouldn't seem
too bad to add nodebug to whatever macro stamps out always_inline.

There are two other ways to mark something as to-be-inlined and
they basically never have convenient macros attached; so let's not
get hung up on attributes. I should remind you that my use case
is -O2 -g not -O0 -g.

Dropping the information at such a coarse granularity as "all inline
functions" seems a bit, well, rough.

No argument there. Note that it isn't actually what our licensees
asked for; it's what was low-cost to provide. Something better is okay.
I am trying to head in that direction, however badly I am able to
express that.

If we could find a good heuristic
for "trivial inline functions" (maybe a function with a single setter
or return) and use that as our signal for "don't bother emitting debug
info for this" maybe that would be good. That would still provide the
size wins with the benefit that it might be beneficial to a broader
range of users.

How about "any indication in the source that the programmer wanted it
inlined." That is: (i) method defined inside the class declaration;
(ii) 'inline' keyword; (iii) an attribute that means "inline this."
All of these are indications that the programmer wanted the function
inlined, and if the programmer then builds the program using the
proposed -gno-inlined-scopes feature, it should not be shocking to
anyone that these inlined functions don't have debug info. (Sorry to
be proposing something that isn't shocking; it's all I got.)

This is what our licensees actually asked for and I am not averse to
giving it to them. :slight_smile:

I admit that it's not what we currently give them. This makes me sad.
But there is a path of progress that is perhaps clear only to me:
(0) all scopes are emitted
    [this is what is public today]
(1) on my target, all actually-inlined scopes are always suppressed
    [this is what I have today]
(2) give all targets control over whether all actually-inlined scopes
    are suppressed, using -g[no-]inlined-scopes
    [this is the stage I'm proposing now]
(3) make DW_AT_inline tell the actual truth about inlined functions,
    i.e. the <declared-inline?, actually-inlined?> tuple
    [improved DWARF conformance, woo-hoo!]
(4) have -gno-inlined-scopes suppress only those scopes with a tuple
    <declared=yes, actually-inlined=yes>
    [what my users actually asked for]

Now what's the debugging-experience benefit to all these stages?
(0) Being our starting point, there's no benefit. :slight_smile:
(1) My licensees don't bounce in and out of inlined functions.
    Sadly this includes functions inlined heuristically, rather than
    just the functions they asked to have inlined, so it's not optimal.
    Also: Debug info ~25% smaller.
(2) Anybody who asks, can get the debug-info size benefit. Most people
    who use -O0 -g will see a smaller benefit because only always_inline
    functions are affected. Size benefit (and debugging-experience cost)
    tracks optimization level.
    My licensees can see inlined frames, if they want.
(3) If and only if you have a debugger able to interpret the
    DW_AT_inline attribute in all its glory, and willing to give you
    control over what inlined frames you want to see, then you can start
    having an improved debugging experience. But getting to this point
    without the compiler leading the way is really a non-starter.
(4) An improved experience over (1)/(2) because heuristically-inlined
    frames are back, without needing the spiffed-up debugger from (3).
    Size benefit is less than (1), hard to know by how much.

Possibly the path I see isn't so great and there's something better to do.
Which possibly includes going away until (3) happens, but I'd obviously
rather provide interim stages that I think are beneficial to everyone.
If I'm wrong about that, well, okay.

--paulr

What's the patch look like to do this?

-eric

Aside from the usual wiring up driver->clang->llvm to pass
a flag down, there are 3 places that needed to be tweaked.
In DwarfDebug.cpp, DwarfDebug::beginInstruction() needs some
minor remodeling to chase the DL.getInlinedAt() chain, to find
the source loc of the original call site. I don't recall for
certain but I think treating these instructions as "unknown"
didn't work because there might not be any instructions left
from the original call, so we have to put the call-site loc
on something.
Also in DwarfDebug.cpp, DwarfDebug::constructScopeDIE() needs
to bail out before doing any actual work.
Then up in Clang, CGExpr.cpp had code to stuff in a column
number at the call site even if column info is suppressed, and
that shouldn't happen if we're suppressing the inlined scope.

Doing the filtering on the output side like this is clearly
much easier when you're suppressing everything. Doing the
fancier footwork (adequate to allow DW_AT_inline to tell the
truth) is way more involved, I think, but once that's
demonstrably correct (as we will be able to tell from looking
at what the new-and-improved DW_AT_inline says) then I would
expect it to be not-hard to rewire -gno-inlined-scopes to
use the same info and dial back the scopes that actually get
suppressed.

--paulr

In fact the intrinsics, and to a significant extent some vector math
libraries, do that. But, it's pretty tedious. We'd like our game teams to
spend their time on more productive tasks than adding attribute(nodebug) to
every method in every header. Plus we have an interest in continuing to
support features that we have provided on previous platforms.

Are these class methods? Can we support slapping attribute(nodebug) on
the whole class definition maybe?

That might alleviate things a bit.

One point of concern even for that is that these SIMD classes can be (and
are) in the headers of a (generally proprietary) library that you are using
(proprietary, but there's still dozens of KLOC of templates in headers that
you import into your project, besides the binary lib). In that case, the
user is suddenly in really uncomfortable territory of modifying external
headers, which I think is not something you want to tell users is "the
solution" (also, as just a user of those libraries, they likely don't
understand the logic behind their macros and how they are meant to be used
to be able to confidently know which ones to tweak to add various magic
attributes; or perhaps changing those headers might not even be allowed by
the agreement).

Ultimately Paul et al. are the ones that have the users knocking on their
door and have the clearest idea of what the use case looks like. I'm mostly
working from memory from code I've looked at.

-- Sean Silva

> > > __attribute__((__always_inline__, __nodebug__))?
> > In fact the intrinsics, and to a significant extent some
> > vector math libraries, do that. But, it's pretty tedious.
>
> Most people wrap these things in macros anyway, so it wouldn't seem
> too bad to add nodebug to whatever macro stamps out always_inline.

There are two other ways to mark something as to-be-inlined and
they basically never have convenient macros attached;

I assume you're referring to 1) implicit-inline when member functions
are defined inline and 2) explicit use of the C++ 'inline' keyword?

so let's not get hung up on attributes.

Sure

I should remind you that my use case is -O2 -g not -O0 -g.

> Dropping the information at such a coarse granularity as "all inline
> functions" seems a bit, well, rough.

No argument there. Note that it isn't actually what our licensees
asked for; it's what was low-cost to provide. Something better is okay.
I am trying to head in that direction, however badly I am able to
express that.

OK - that's somewhat of what I'm trying to discuss. It /seems/ like
your user requests aren't actually unique to your userbase. They seem
like common things anyone using a debugger might like - not to step
into/out of trivial functions.

So I'd like to think about whether there's a good, general,
on-by-default behavior we can use here.

> If we could find a good heuristic
> for "trivial inline functions" (maybe a function with a single setter
> or return) and use that as our signal for "don't bother emitting debug
> info for this" maybe that would be good. That would still provide the
> size wins with the benefit that it might be beneficial to a broader
> range of users.

How about "any indication in the source that the programmer wanted it
inlined."

I don't think that's sufficient - looking at Clang and LLVM there are
a variety of header-defined functions that are sufficiently
non-trivial as to be interesting to step through. Though perhaps, if
it were a debugger-feature, it would be sufficient to make that the
default and a debugger would have some feature to allow a user to
override it. My suspicion is that the debugger might need to do more
work to make a better decision there, though. But I'm not sure the
compiler can really give much more info - it'd essentially be up to
the debugger to examine a function, perhaps, and decide whether it was
"interesting".

That is: (i) method defined inside the class declaration;
(ii) 'inline' keyword; (iii) an attribute that means "inline this."
All of these are indications that the programmer wanted the function
inlined, and if the programmer then builds the program using the
proposed -gno-inlined-scopes feature, it should not be shocking to
anyone that these inlined functions don't have debug info. (Sorry to
be proposing something that isn't shocking; it's all I got.)

Right - what I'm suggesting is that there is an underlying
feature/usability desire that should be on by default and I'm trying
to think/talk through how we might provide a better experience to all
our users by default, rather than with an explicit switch. (and while
some of your users explicitly requested this behavior, some didn't -
so they're not all going to be in the "the programmer explicitly
turned on this switch, of course they got that behavior" - they won't
know the switch is on, so the behavior may catch them by surprise)

This is what our licensees actually asked for and I am not averse to
giving it to them. :slight_smile:

They asked for a switch powered by inline hints? Fair enough - though,
again, I'm interested in seeing whether we can design a feature better
than our customer requests that addresses their underlying issue (&
perhaps that of others who haven't even asked for anything yet).

I admit that it's not what we currently give them. This makes me sad.
But there is a path of progress that is perhaps clear only to me:
(0) all scopes are emitted
    [this is what is public today]
(1) on my target, all actually-inlined scopes are always suppressed
    [this is what I have today]
(2) give all targets control over whether all actually-inlined scopes
    are suppressed, using -g[no-]inlined-scopes
    [this is the stage I'm proposing now]
(3) make DW_AT_inline tell the actual truth about inlined functions,
    i.e. the <declared-inline?, actually-inlined?> tuple
    [improved DWARF conformance, woo-hoo!]
(4) have -gno-inlined-scopes suppress only those scopes with a tuple
    <declared=yes, actually-inlined=yes>
    [what my users actually asked for]

This still isn't necessarily the end state I see as optimal. It sounds
like this isn't something users should have to enable/disable in their
build, but should be a debugger feature if possible.

Now what's the debugging-experience benefit to all these stages?
(0) Being our starting point, there's no benefit. :slight_smile:
(1) My licensees don't bounce in and out of inlined functions.
    Sadly this includes functions inlined heuristically, rather than
    just the functions they asked to have inlined, so it's not optimal.
    Also: Debug info ~25% smaller.

I'd like to see those numbers - but also I'd generally like to
approach debug info size as a separate yet equally important goal. One
in which we know how small is "small enough" (or what we're willing to
trade off in the size/fidelity space - which might still end up
motivating such a flag, but I'd find it unfortunate if it did) and
then set about trying to make debug info that small. There's still a
fair amount of general size improvements that I think can be made to
LLVM's DWARF output that I haven't had time/priority to pursue.

(2) Anybody who asks, can get the debug-info size benefit. Most people
    who use -O0 -g will see a smaller benefit because only always_inline
    functions are affected. Size benefit (and debugging-experience cost)
    tracks optimization level.
    My licensees can see inlined frames, if they want.
(3) If and only if you have a debugger able to interpret the
    DW_AT_inline attribute in all its glory, and willing to give you
    control over what inlined frames you want to see, then you can start
    having an improved debugging experience. But getting to this point
    without the compiler leading the way is really a non-starter.

Certainly - fixing the inline attribute to have better fidelity seems
like general goodness. There's no space tradeoff - we already emit the
attribute, just without the right value.

(4) An improved experience over (1)/(2) because heuristically-inlined
    frames are back, without needing the spiffed-up debugger from (3).
    Size benefit is less than (1), hard to know by how much.

Possibly the path I see isn't so great and there's something better to do.
Which possibly includes going away until (3) happens, but I'd obviously
rather provide interim stages that I think are beneficial to everyone.
If I'm wrong about that, well, okay.

Equally I'm just one voice - I don't speak for the user or the project
anymore than anyone else. I don't have a good sense about where the
best thing for LLVM is to have a stop-gap solution versus an out of
tree solution, versus waiting for the "perfect" long-term solution.
I'm just trying to understand the landscape here a bit better - what
the needs and alternatives are, what the perfect future looks like (if
there is one), how we get there, what tradeoffs we might be willing to
make along the way. Who's going to drive us towards that future and
how long will it take (how long will we live with interim solutions).

It's not uncommon in the project that we say "that solution that would
work for one contributor just isn't general purpose enough for the
project - if they want that functionality upstream, it should be done
in <this general way>" - we all have had features that hit this
situation and have paid the cost to do more general work to get
something upstreamable. I'm not saying that's

Thanks for helping explain the issues/options,

- David

> > Dropping the information at such a coarse granularity as "all inline
> > functions" seems a bit, well, rough.
>
> No argument there. Note that it isn't actually what our licensees
> asked for; it's what was low-cost to provide. Something better is
okay.
> I am trying to head in that direction, however badly I am able to
> express that.

OK - that's somewhat of what I'm trying to discuss. It /seems/ like
your user requests aren't actually unique to your userbase. They seem
like common things anyone using a debugger might like - not to step
into/out of trivial functions.

So I'd like to think about whether there's a good, general,
on-by-default behavior we can use here.

I don't doubt we could come up with some sort of heuristic that would
make sense to us as compiler developers (e.g.: fewer than X instructions
with at most 1 conditional branch).

I am doubtful, however, that any such heuristic will conform to what
a colleague once called "the principle of least surprise." That is,
it will not be easy to explain to users how that heuristic influences
whether they can step into a "trivial" function. Having the debugger
step into or over function calls, based on mysterious compiler-internal
criteria rather than something the user can readily discern, is not
such a good experience.

> > If we could find a good heuristic
> > for "trivial inline functions" (maybe a function with a single
setter
> > or return) and use that as our signal for "don't bother emitting
debug
> > info for this" maybe that would be good. That would still provide
the
> > size wins with the benefit that it might be beneficial to a broader
> > range of users.
>
> How about "any indication in the source that the programmer wanted it
> inlined."

I don't think that's sufficient - looking at Clang and LLVM there are
a variety of header-defined functions that are sufficiently
non-trivial as to be interesting to step through. Though perhaps, if
it were a debugger-feature, it would be sufficient to make that the
default and a debugger would have some feature to allow a user to
override it. My suspicion is that the debugger might need to do more
work to make a better decision there, though. But I'm not sure the
compiler can really give much more info - it'd essentially be up to
the debugger to examine a function, perhaps, and decide whether it was
"interesting".

I offer that heuristic because it is easy to explain, easy to remember,
and easy for users to apply when eyeballing their own code. Not because
it conforms to some compiler-developer-friendly abstraction of the
dividing line between "trivial" and "interesting."

> That is: (i) method defined inside the class declaration;
> (ii) 'inline' keyword; (iii) an attribute that means "inline this."
> All of these are indications that the programmer wanted the function
> inlined, and if the programmer then builds the program using the
> proposed -gno-inlined-scopes feature, it should not be shocking to
> anyone that these inlined functions don't have debug info. (Sorry to
> be proposing something that isn't shocking; it's all I got.)

Right - what I'm suggesting is that there is an underlying
feature/usability desire that should be on by default and I'm trying
to think/talk through how we might provide a better experience to all
our users by default, rather than with an explicit switch. (and while
some of your users explicitly requested this behavior, some didn't -
so they're not all going to be in the "the programmer explicitly
turned on this switch, of course they got that behavior" - they won't
know the switch is on, so the behavior may catch them by surprise)

> This is what our licensees actually asked for and I am not averse to
> giving it to them. :slight_smile:

They asked for a switch powered by inline hints? Fair enough - though,
again, I'm interested in seeing whether we can design a feature better
than our customer requests that addresses their underlying issue (&
perhaps that of others who haven't even asked for anything yet).

yes, the criterion of "marked inline" came from them, not me.
--paulr

> > Dropping the information at such a coarse granularity as "all inline
> > functions" seems a bit, well, rough.
>
> No argument there. Note that it isn't actually what our licensees
> asked for; it's what was low-cost to provide. Something better is
okay.
> I am trying to head in that direction, however badly I am able to
> express that.

OK - that's somewhat of what I'm trying to discuss. It /seems/ like
your user requests aren't actually unique to your userbase. They seem
like common things anyone using a debugger might like - not to step
into/out of trivial functions.

So I'd like to think about whether there's a good, general,
on-by-default behavior we can use here.

I don't doubt we could come up with some sort of heuristic that would
make sense to us as compiler developers (e.g.: fewer than X instructions
with at most 1 conditional branch).

I am doubtful, however, that any such heuristic will conform to what
a colleague once called "the principle of least surprise." That is,
it will not be easy to explain to users how that heuristic influences
whether they can step into a "trivial" function. Having the debugger
step into or over function calls, based on mysterious compiler-internal
criteria rather than something the user can readily discern, is not
such a good experience.

I'm not so sure that's the case - and realistically I suspect this
would have to be a debugger feature (perhaps powered by new/improved
information in the DWARF to help the debugger make the right choice)
so that it could be overridden when necessary.

I'm not sure such a heuristic exists, but it's something that seems
worth considering.

> > If we could find a good heuristic
> > for "trivial inline functions" (maybe a function with a single
setter
> > or return) and use that as our signal for "don't bother emitting
debug
> > info for this" maybe that would be good. That would still provide
the
> > size wins with the benefit that it might be beneficial to a broader
> > range of users.
>
> How about "any indication in the source that the programmer wanted it
> inlined."

I don't think that's sufficient - looking at Clang and LLVM there are
a variety of header-defined functions that are sufficiently
non-trivial as to be interesting to step through. Though perhaps, if
it were a debugger-feature, it would be sufficient to make that the
default and a debugger would have some feature to allow a user to
override it. My suspicion is that the debugger might need to do more
work to make a better decision there, though. But I'm not sure the
compiler can really give much more info - it'd essentially be up to
the debugger to examine a function, perhaps, and decide whether it was
"interesting".

I offer that heuristic because it is easy to explain, easy to remember,
and easy for users to apply when eyeballing their own code. Not because
it conforms to some compiler-developer-friendly abstraction of the
dividing line between "trivial" and "interesting."

I'm not sure I follow what you mean by "compile-developer-friendly
abstraction" - whether you're referring to my using the LLVM codebase
as an example or you're describing my attitude, regardless of example.

I think LLVM isn't a very strange/uncommon example of C++ code as
regards to the inline function complexity.

And, yes, likely this would be better at the debugger feature than a
compiler feature - so it can be turned off/on/configured by the user.

> That is: (i) method defined inside the class declaration;
> (ii) 'inline' keyword; (iii) an attribute that means "inline this."
> All of these are indications that the programmer wanted the function
> inlined, and if the programmer then builds the program using the
> proposed -gno-inlined-scopes feature, it should not be shocking to
> anyone that these inlined functions don't have debug info. (Sorry to
> be proposing something that isn't shocking; it's all I got.)

Right - what I'm suggesting is that there is an underlying
feature/usability desire that should be on by default and I'm trying
to think/talk through how we might provide a better experience to all
our users by default, rather than with an explicit switch. (and while
some of your users explicitly requested this behavior, some didn't -
so they're not all going to be in the "the programmer explicitly
turned on this switch, of course they got that behavior" - they won't
know the switch is on, so the behavior may catch them by surprise)

> This is what our licensees actually asked for and I am not averse to
> giving it to them. :slight_smile:

They asked for a switch powered by inline hints? Fair enough - though,
again, I'm interested in seeing whether we can design a feature better
than our customer requests that addresses their underlying issue (&
perhaps that of others who haven't even asked for anything yet).

yes, the criterion of "marked inline" came from them, not me.

OK - so what was their request? Just that they don't step into
"uninteresting" functions & you chose inline as the heuristic to use?

- David

From: David Blaikie [mailto:dblaikie@gmail.com]
Sent: Wednesday, November 27, 2013 3:36 PM
To: Robinson, Paul
Cc: Eric Christopher; Sean Silva; cfe-dev@cs.uiuc.edu
Subject: Re: [cfe-dev] Optionally suppress debug info for inlined calls?

>> > > Dropping the information at such a coarse granularity as "all
inline
>> > > functions" seems a bit, well, rough.
>> >
>> > No argument there. Note that it isn't actually what our licensees
>> > asked for; it's what was low-cost to provide. Something better is
>> okay.
>> > I am trying to head in that direction, however badly I am able to
>> > express that.
>>
>> OK - that's somewhat of what I'm trying to discuss. It /seems/ like
>> your user requests aren't actually unique to your userbase. They seem
>> like common things anyone using a debugger might like - not to step
>> into/out of trivial functions.
>>
>> So I'd like to think about whether there's a good, general,
>> on-by-default behavior we can use here.
>
> I don't doubt we could come up with some sort of heuristic that would
> make sense to us as compiler developers (e.g.: fewer than X
instructions
> with at most 1 conditional branch).
>
> I am doubtful, however, that any such heuristic will conform to what
> a colleague once called "the principle of least surprise." That is,
> it will not be easy to explain to users how that heuristic influences
> whether they can step into a "trivial" function. Having the debugger
> step into or over function calls, based on mysterious compiler-
internal
> criteria rather than something the user can readily discern, is not
> such a good experience.

I'm not so sure that's the case - and realistically I suspect this
would have to be a debugger feature (perhaps powered by new/improved
information in the DWARF to help the debugger make the right choice)
so that it could be overridden when necessary.

I'm not sure such a heuristic exists, but it's something that seems
worth considering.

I can envision some sort of debugger feature that could provide control
over the stepping behavior, preferably based on debug info and really
preferably not based on analyzing function content. Although debuggers
are getting more clever these days, it might not be too painful to come
up with something based on instruction counts and/or branch counts.
So, yeah, it wouldn't have to be a compiler thing.

>
>>
>> > > If we could find a good heuristic
>> > > for "trivial inline functions" (maybe a function with a single
>> setter
>> > > or return) and use that as our signal for "don't bother emitting
>> debug
>> > > info for this" maybe that would be good. That would still provide
>> the
>> > > size wins with the benefit that it might be beneficial to a
broader
>> > > range of users.
>> >
>> > How about "any indication in the source that the programmer wanted
it
>> > inlined."
>>
>> I don't think that's sufficient - looking at Clang and LLVM there are
>> a variety of header-defined functions that are sufficiently
>> non-trivial as to be interesting to step through. Though perhaps, if
>> it were a debugger-feature, it would be sufficient to make that the
>> default and a debugger would have some feature to allow a user to
>> override it. My suspicion is that the debugger might need to do more
>> work to make a better decision there, though. But I'm not sure the
>> compiler can really give much more info - it'd essentially be up to
>> the debugger to examine a function, perhaps, and decide whether it
was
>> "interesting".
>
> I offer that heuristic because it is easy to explain, easy to
remember,
> and easy for users to apply when eyeballing their own code. Not
because
> it conforms to some compiler-developer-friendly abstraction of the
> dividing line between "trivial" and "interesting."

I'm not sure I follow what you mean by "compile-developer-friendly
abstraction" - whether you're referring to my using the LLVM codebase
as an example or you're describing my attitude, regardless of example.

No, no, no, David, please. I mean that any heuristic that the compiler
applied to this problem would necessarily be calculated on some basis
that the compiler (i.e. the developer teaching the compiler to do this
trick) would find convenient to work with. This basis is unlikely to
be readily expressed in terms relevant to the programmer, although it
is clearly a compiler-developer-friendly basis.

It's analogous to costing for an inlining heuristic; the criteria aren't
easily reflected back to the user in terms that the user can readily
apply to modifying his own code to improve the inlining behavior. The
criteria are implemented in compiler-developer-friendly terms, not in
game-developer-friendly terms. [This is actually something else that our
guys have asked for: diagnostics explaining why the compiler didn't
inline some function. I've dragged my feet for years on that one,
because I don't know how to express it in terms that would make any sense
to a non-compiler-writer. Numbers of LLVM IR instructions?? No, I don't
think so.]

Now, we could probably devise some criteria that were still easy to
explain. But it would still be the compiler deciding something, and
whatever basis we picked, somebody would want to fiddle with it, and
we probably wouldn't want to give them that knob to twist. This is
another reason why I think "marked inline" is a reasonable criterion:
The programmer can't really argue with it. "How come I can't step into
this function?" "Because you said not to." "... oh yeah."

(And if we ever get 'optnone' finished, they can apply 'optnone' to
any inlined function that's causing a problem, to keep it from being
inlined, and therefore making it feasible to debug. Granted, with a
postulated debugger feature to turn auto-step-over on and off per
function, they wouldn't have to rebuild their program. The thing is,
the compiler features are basically ready *right* *now*. This is not
to say they have to go upstream, they're just ready to roll and I'm
checking to see if upstream is the right direction.)

I think LLVM isn't a very strange/uncommon example of C++ code as
regards to the inline function complexity.

And, yes, likely this would be better at the debugger feature than a
compiler feature - so it can be turned off/on/configured by the user.

>
>>
>> > That is: (i) method defined inside the class declaration;
>> > (ii) 'inline' keyword; (iii) an attribute that means "inline this."
>> > All of these are indications that the programmer wanted the
function
>> > inlined, and if the programmer then builds the program using the
>> > proposed -gno-inlined-scopes feature, it should not be shocking to
>> > anyone that these inlined functions don't have debug info. (Sorry
to
>> > be proposing something that isn't shocking; it's all I got.)
>>
>> Right - what I'm suggesting is that there is an underlying
>> feature/usability desire that should be on by default and I'm trying
>> to think/talk through how we might provide a better experience to all
>> our users by default, rather than with an explicit switch. (and while
>> some of your users explicitly requested this behavior, some didn't -
>> so they're not all going to be in the "the programmer explicitly
>> turned on this switch, of course they got that behavior" - they won't
>> know the switch is on, so the behavior may catch them by surprise)
>>
>> > This is what our licensees actually asked for and I am not averse
to
>> > giving it to them. :slight_smile:
>>
>> They asked for a switch powered by inline hints? Fair enough -
though,
>> again, I'm interested in seeing whether we can design a feature
better
>> than our customer requests that addresses their underlying issue (&
>> perhaps that of others who haven't even asked for anything yet).
>
> yes, the criterion of "marked inline" came from them, not me.

OK - so what was their request? Just that they don't step into
"uninteresting" functions & you chose inline as the heuristic to use?

No, _they_ defined "uninteresting" functions as the ones marked inline
(explicitly in source, or implicitly by being defined inside the class
declaration). The compiler-developer-friendly solution was to have the
compiler not emit scopes for ANY inlined functions. Because it was easy
to implement that exact feature in LLVM, and DW_AT_inline was lying to
us, and it's how the compilers for our previous platforms solved the same
problem.

Given a truthful DW_AT_inline, I might have pushed back on the
debugger people to take advantage of it, but I can't do that until
DW_AT_inline tells the truth. It was a lot easier to find where the
scopes came out, and stop them, than it was to figure out how to get
the right "marked inline" indicator out of LLVM. Plus when we stopped
putting out the scopes, we got a big debug-info-size windfall along
with it; and there was much rejoicing.

So, it seemed worthwhile asking if this was of any interest upstream.
What I'm getting out of this discussion is:
- Not stepping into trivial/uninteresting functions seems like a good
  debugging-experience benefit.
- We defined criteria for picking that set of functions at compile time,
  and there is a reasonable basis for saying those criteria aren't
  really ideal. There is a reasonable basis for saying NO criteria
  defined by the compiler are really ideal.
- The long-term goal of better DW_AT_inline info is definitely good.
- If the debugging-experience improvement can be achieved by the
  debugger, rather than the compiler adding or subtracting debug info,
  that's likely the better solution.

I think that leaves me continuing on the path I outlined before, but as
private features, until we get to the point of a truthful DW_AT_inline.

Thanks,
--paulr