public inbox for gcc-bugs@sourceware.org
help / color / mirror / Atom feed
* [Bug c/101279] New: Function attributes often block inlining
@ 2021-07-01  8:16 david at westcontrol dot com
  2021-07-01 21:30 ` [Bug ipa/101279] " pinskia at gcc dot gnu.org
                   ` (7 more replies)
  0 siblings, 8 replies; 9+ messages in thread
From: david at westcontrol dot com @ 2021-07-01  8:16 UTC (permalink / raw)
  To: gcc-bugs

https://gcc.gnu.org/bugzilla/show_bug.cgi?id=101279

            Bug ID: 101279
           Summary: Function attributes often block inlining
           Product: gcc
           Version: unknown
            Status: UNCONFIRMED
          Severity: normal
          Priority: P3
         Component: c
          Assignee: unassigned at gcc dot gnu.org
          Reporter: david at westcontrol dot com
  Target Milestone: ---

When using many function attributes, the attributes only apply when the
function is not inlined.  And in some cases, they actively disable inlining
which would normally be expected.

For example, a programmer may have occasional need for two's complement
wrapping semantics for signed integers.  They don't want to use "-fwrapv"
globally, because that would lose some optimisation opportunities for the rest
of the code.  So they define functions like "wrapped_add" :

  __attribute__((optimize("-fwrapv")))
  static inline int wrapped_add(int a, int b) {
      return a + b;
  }

  int foo(int x, int y, int z) {
      return wrapped_add(wrapped_add(x, y), z);
  }

When used in a function like "foo" which does not have "-fwrapv" active,
function calls are made rather than the expected inlining.  The result is
significantly poorer code than the programmer would predict.

If "foo" also has "-fwrapv" from a compiler flag, attribute or pragma, the
generated code is inlined nicely.


The same issues apply to a range of function attributes.  (Obviously some, such
as "section", make no sense to inline to functions that don't share the same
attribute.)  For some attributes, such as "access", inlining disables the
attribute rather than the attribute disabling inlining.

Steadily more code is inlined in modern programming - helped by LTO.  Often the
code works the same whether code is inlined or not, with only minor differences
in speed.  But in template-heavy C++ code, inlining is essential as you have
large numbers of functions that generate very little (if any) code - failure to
inline as expected can have severe efficiency effects.  Conversely, if inlining
disables checking attributes like "access" or "nonnull" the result is a false
sense of security in the programmer.


I think it is important for the manual to be updated to reflect these
limitations as a first step.

Then of course it would be best to remove the limitations!

Ref. mailing list conversation
<https://gcc.gnu.org/pipermail/gcc/2021-June/236592.html> and Martin Sebor's
blog article
<https://developers.redhat.com/articles/2021/06/25/use-source-level-annotations-help-gcc-detect-buffer-overflows>.

(Thanks to Martin for his article and discussion that made me aware of these
points.)

^ permalink raw reply	[flat|nested] 9+ messages in thread

* [Bug ipa/101279] Function attributes often block inlining
  2021-07-01  8:16 [Bug c/101279] New: Function attributes often block inlining david at westcontrol dot com
@ 2021-07-01 21:30 ` pinskia at gcc dot gnu.org
  2021-07-02  0:08 ` msebor at gcc dot gnu.org
                   ` (6 subsequent siblings)
  7 siblings, 0 replies; 9+ messages in thread
From: pinskia at gcc dot gnu.org @ 2021-07-01 21:30 UTC (permalink / raw)
  To: gcc-bugs

https://gcc.gnu.org/bugzilla/show_bug.cgi?id=101279

--- Comment #1 from Andrew Pinski <pinskia at gcc dot gnu.org> ---
See also https://gcc.gnu.org/legacy-ml/gcc/2009-02/msg00408.html which was a
way forward for wrapv but there was not much work on it really since that year.
 The work on this has a huge impact to the IR really.

^ permalink raw reply	[flat|nested] 9+ messages in thread

* [Bug ipa/101279] Function attributes often block inlining
  2021-07-01  8:16 [Bug c/101279] New: Function attributes often block inlining david at westcontrol dot com
  2021-07-01 21:30 ` [Bug ipa/101279] " pinskia at gcc dot gnu.org
@ 2021-07-02  0:08 ` msebor at gcc dot gnu.org
  2022-06-28 12:20 ` frankhb1989 at gmail dot com
                   ` (5 subsequent siblings)
  7 siblings, 0 replies; 9+ messages in thread
From: msebor at gcc dot gnu.org @ 2021-07-02  0:08 UTC (permalink / raw)
  To: gcc-bugs

https://gcc.gnu.org/bugzilla/show_bug.cgi?id=101279

Martin Sebor <msebor at gcc dot gnu.org> changed:

           What    |Removed                     |Added
----------------------------------------------------------------------------
     Ever confirmed|0                           |1
   Last reconfirmed|                            |2021-07-02
                 CC|                            |msebor at gcc dot gnu.org
             Status|UNCONFIRMED                 |NEW

--- Comment #2 from Martin Sebor <msebor at gcc dot gnu.org> ---
Compiling the test case with -Winline shows the problem:

pr101279.c: In function ‘foo’:
pr101279.c:2:19: warning: inlining failed in call to ‘wrapped_add’:
optimization level attribute mismatch [-Winline]
    2 | static inline int wrapped_add(int a, int b) {
      |                   ^~~~~~~~~~~
pr101279.c:7:12: note: called from here
    7 |     return wrapped_add(wrapped_add(x, y), z);
      |            ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
pr101279.c:2:19: warning: inlining failed in call to ‘wrapped_add’:
optimization level attribute mismatch [-Winline]
    2 | static inline int wrapped_add(int a, int b) {
      |                   ^~~~~~~~~~~
pr101279.c:7:12: note: called from here
    7 |     return wrapped_add(wrapped_add(x, y), z);
      |            ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

Declaring wrapped_add() with attribute always_inline avoids the warning but
also loses the -fwrapv option.  This also seems somewhat surprising and could
stand be made clearer in the manual.  The manual says "this attribute inlines
the function independent of any restrictions that otherwise apply to inlining."
but I see no such restrictions discussed under the optimize attribute or in the
inlining setion (https://gcc.gnu.org/onlinedocs/gcc/Inline.html).

But this report isn't just about attribute optimize but rather about the
general inconsistency of the interplay between inlining and each function
attribute, and the lack of documentation of it.  Confirmed.  I'll see if I can
add a few words to the manual for now.

^ permalink raw reply	[flat|nested] 9+ messages in thread

* [Bug ipa/101279] Function attributes often block inlining
  2021-07-01  8:16 [Bug c/101279] New: Function attributes often block inlining david at westcontrol dot com
  2021-07-01 21:30 ` [Bug ipa/101279] " pinskia at gcc dot gnu.org
  2021-07-02  0:08 ` msebor at gcc dot gnu.org
@ 2022-06-28 12:20 ` frankhb1989 at gmail dot com
  2022-06-28 12:33 ` rguenth at gcc dot gnu.org
                   ` (4 subsequent siblings)
  7 siblings, 0 replies; 9+ messages in thread
From: frankhb1989 at gmail dot com @ 2022-06-28 12:20 UTC (permalink / raw)
  To: gcc-bugs

https://gcc.gnu.org/bugzilla/show_bug.cgi?id=101279

frankhb1989 at gmail dot com changed:

           What    |Removed                     |Added
----------------------------------------------------------------------------
                 CC|                            |frankhb1989 at gmail dot com

--- Comment #3 from frankhb1989 at gmail dot com ---
There is a more specific instance here: can_inline_edge_by_limits_p in
ipa-inline.cc treats flags and "optimize" attributes differently.

While it is reasonable to reject inlining for semantic mismatch from different
global flags, "opts_for_fn (caller->decl) != opts_for_fn (callee->decl)" looks
quite unnatural. In practice it means missing of valid opportunity of inlining,
unless the programmer knows what should go under the hood and decides to
propagate "always_inline" plus the "optimize" attributes manually in the
declarations of *all* callees (including lambda-expressions in C++),
*recursively*. Adding "__attribute__((flatten))" can be a workaround sometimes,
but it does not always generated desired code, and often too slow.

This is somewhat worse than the case of "-fwrapv" whose semantic is easier to
reason in the generated code.

^ permalink raw reply	[flat|nested] 9+ messages in thread

* [Bug ipa/101279] Function attributes often block inlining
  2021-07-01  8:16 [Bug c/101279] New: Function attributes often block inlining david at westcontrol dot com
                   ` (2 preceding siblings ...)
  2022-06-28 12:20 ` frankhb1989 at gmail dot com
@ 2022-06-28 12:33 ` rguenth at gcc dot gnu.org
  2022-06-28 12:53 ` david at westcontrol dot com
                   ` (3 subsequent siblings)
  7 siblings, 0 replies; 9+ messages in thread
From: rguenth at gcc dot gnu.org @ 2022-06-28 12:33 UTC (permalink / raw)
  To: gcc-bugs

https://gcc.gnu.org/bugzilla/show_bug.cgi?id=101279

--- Comment #4 from Richard Biener <rguenth at gcc dot gnu.org> ---
(In reply to frankhb1989 from comment #3)
> There is a more specific instance here: can_inline_edge_by_limits_p in
> ipa-inline.cc treats flags and "optimize" attributes differently.

A bit up there's a blacklist we maintain where inlining is not OK because it
results in semantic differences.

Generally we it's hard to second-guess the users intention when looking
at an inline edge with different optimization settings of caller and callee.
For C++ comdats there might be even multiple variants with different
optimization level (but we only keep one, special-casing this a bit).

^ permalink raw reply	[flat|nested] 9+ messages in thread

* [Bug ipa/101279] Function attributes often block inlining
  2021-07-01  8:16 [Bug c/101279] New: Function attributes often block inlining david at westcontrol dot com
                   ` (3 preceding siblings ...)
  2022-06-28 12:33 ` rguenth at gcc dot gnu.org
@ 2022-06-28 12:53 ` david at westcontrol dot com
  2022-06-28 13:25 ` rguenther at suse dot de
                   ` (2 subsequent siblings)
  7 siblings, 0 replies; 9+ messages in thread
From: david at westcontrol dot com @ 2022-06-28 12:53 UTC (permalink / raw)
  To: gcc-bugs

https://gcc.gnu.org/bugzilla/show_bug.cgi?id=101279

--- Comment #5 from David Brown <david at westcontrol dot com> ---
(In reply to Richard Biener from comment #4)
> (In reply to frankhb1989 from comment #3)
> > There is a more specific instance here: can_inline_edge_by_limits_p in
> > ipa-inline.cc treats flags and "optimize" attributes differently.
> 
> A bit up there's a blacklist we maintain where inlining is not OK because it
> results in semantic differences.
> 
> Generally we it's hard to second-guess the users intention when looking
> at an inline edge with different optimization settings of caller and callee.
> For C++ comdats there might be even multiple variants with different
> optimization level (but we only keep one, special-casing this a bit).

I appreciate the "err on the side of caution" attitude.  Perhaps there could be
an extra "I know what I'm doing" attribute that lets you override the
blacklisting in a particular case.  This would only really make sense in cases
where the attribute can be attached to the expressions and statements within
the function (I think "-fwrapv" would be in this category).  In cases where
this is not possible, an error or warning message would be in order as the
compiler can't do what the programmer is asking.

^ permalink raw reply	[flat|nested] 9+ messages in thread

* [Bug ipa/101279] Function attributes often block inlining
  2021-07-01  8:16 [Bug c/101279] New: Function attributes often block inlining david at westcontrol dot com
                   ` (4 preceding siblings ...)
  2022-06-28 12:53 ` david at westcontrol dot com
@ 2022-06-28 13:25 ` rguenther at suse dot de
  2022-06-28 14:20 ` david at westcontrol dot com
  2022-06-29  9:07 ` rguenth at gcc dot gnu.org
  7 siblings, 0 replies; 9+ messages in thread
From: rguenther at suse dot de @ 2022-06-28 13:25 UTC (permalink / raw)
  To: gcc-bugs

https://gcc.gnu.org/bugzilla/show_bug.cgi?id=101279

--- Comment #6 from rguenther at suse dot de <rguenther at suse dot de> ---
> Am 28.06.2022 um 14:53 schrieb david at westcontrol dot com <gcc-bugzilla@gcc.gnu.org>:
> 
> https://gcc.gnu.org/bugzilla/show_bug.cgi?id=101279
> 
> --- Comment #5 from David Brown <david at westcontrol dot com> ---
> (In reply to Richard Biener from comment #4)
>> (In reply to frankhb1989 from comment #3)
>>> There is a more specific instance here: can_inline_edge_by_limits_p in
>>> ipa-inline.cc treats flags and "optimize" attributes differently.
>> 
>> A bit up there's a blacklist we maintain where inlining is not OK because it
>> results in semantic differences.
>> 
>> Generally we it's hard to second-guess the users intention when looking
>> at an inline edge with different optimization settings of caller and callee.
>> For C++ comdats there might be even multiple variants with different
>> optimization level (but we only keep one, special-casing this a bit).
> 
> I appreciate the "err on the side of caution" attitude.  Perhaps there could be
> an extra "I know what I'm doing" attribute that lets you override the
> blacklisting in a particular case.  This would only really make sense in cases
> where the attribute can be attached to the expressions and statements within
> the function (I think "-fwrapv" would be in this category).  In cases where
> this is not possible, an error or warning message would be in order as the
> compiler can't do what the programmer is asking.

Can you provide a specific example that you would allow this way?


> -- 
> You are receiving this mail because:
> You are on the CC list for the bug.

^ permalink raw reply	[flat|nested] 9+ messages in thread

* [Bug ipa/101279] Function attributes often block inlining
  2021-07-01  8:16 [Bug c/101279] New: Function attributes often block inlining david at westcontrol dot com
                   ` (5 preceding siblings ...)
  2022-06-28 13:25 ` rguenther at suse dot de
@ 2022-06-28 14:20 ` david at westcontrol dot com
  2022-06-29  9:07 ` rguenth at gcc dot gnu.org
  7 siblings, 0 replies; 9+ messages in thread
From: david at westcontrol dot com @ 2022-06-28 14:20 UTC (permalink / raw)
  To: gcc-bugs

https://gcc.gnu.org/bugzilla/show_bug.cgi?id=101279

--- Comment #7 from David Brown <david at westcontrol dot com> ---
(In reply to rguenther@suse.de from comment #6)
> > Am 28.06.2022 um 14:53 schrieb david at westcontrol dot com <gcc-bugzilla@gcc.gnu.org>:
> > 
> > https://gcc.gnu.org/bugzilla/show_bug.cgi?id=101279
> > 
> > --- Comment #5 from David Brown <david at westcontrol dot com> ---
> > (In reply to Richard Biener from comment #4)
> >> (In reply to frankhb1989 from comment #3)
> >>> There is a more specific instance here: can_inline_edge_by_limits_p in
> >>> ipa-inline.cc treats flags and "optimize" attributes differently.
> >> 
> >> A bit up there's a blacklist we maintain where inlining is not OK because it
> >> results in semantic differences.
> >> 
> >> Generally we it's hard to second-guess the users intention when looking
> >> at an inline edge with different optimization settings of caller and callee.
> >> For C++ comdats there might be even multiple variants with different
> >> optimization level (but we only keep one, special-casing this a bit).
> > 
> > I appreciate the "err on the side of caution" attitude.  Perhaps there could be
> > an extra "I know what I'm doing" attribute that lets you override the
> > blacklisting in a particular case.  This would only really make sense in cases
> > where the attribute can be attached to the expressions and statements within
> > the function (I think "-fwrapv" would be in this category).  In cases where
> > this is not possible, an error or warning message would be in order as the
> > compiler can't do what the programmer is asking.
> 
> Can you provide a specific example that you would allow this way?
> 
> 

I'd go back to my original example :


  __attribute__((optimize("-fwrapv")))
  static inline int wrapped_add(int a, int b) {
      return a + b;
  }

  int foo(int x, int y, int z) {
      return wrapped_add(wrapped_add(x, y), z);
  }

If you want to disable inlining of "wrapped_add" due to the change in the
semantics of integer arithmetic, that's fair enough.  But if I /really/ want
inlining, and write something like :

  __attribute__((optimize("-fwrapv"), always_inline))
  static inline int wrapped_add(int a, int b) {
      return a + b;
  }

then I want the code treated as :

  return (__wrapping_int) a + (__wrapping_int) b;

or

  return __wrapping_add_int(a, b);

If the way gcc marks and handles "-fwrapv" arithmetic does not support
something like that, which would allow inline mixing with other code, then that
would result in a compiler warning or error message.


It might be best to have a new attribute name here rather than using
"always_inline" - I have not thought through the consequences.

It might also be that if the compiler can be changed to support inlining of a
given optimisation attribute, then the attribute in question can be whitelisted
for inlining for everyone.  I suppose what I am saying is that if the compiler
can't be sure that inlining is safe, then it could be cautious by default while
letting the programmer override that caution explicitly.

^ permalink raw reply	[flat|nested] 9+ messages in thread

* [Bug ipa/101279] Function attributes often block inlining
  2021-07-01  8:16 [Bug c/101279] New: Function attributes often block inlining david at westcontrol dot com
                   ` (6 preceding siblings ...)
  2022-06-28 14:20 ` david at westcontrol dot com
@ 2022-06-29  9:07 ` rguenth at gcc dot gnu.org
  7 siblings, 0 replies; 9+ messages in thread
From: rguenth at gcc dot gnu.org @ 2022-06-29  9:07 UTC (permalink / raw)
  To: gcc-bugs

https://gcc.gnu.org/bugzilla/show_bug.cgi?id=101279

--- Comment #8 from Richard Biener <rguenth at gcc dot gnu.org> ---
(In reply to David Brown from comment #7)
> (In reply to rguenther@suse.de from comment #6)
> > Can you provide a specific example that you would allow this way?
> > 
> > 
> 
> I'd go back to my original example :
> 
> 
>   __attribute__((optimize("-fwrapv")))
>   static inline int wrapped_add(int a, int b) {
>       return a + b;
>   }
> 
>   int foo(int x, int y, int z) {
>       return wrapped_add(wrapped_add(x, y), z);
>   }
> 
> If you want to disable inlining of "wrapped_add" due to the change in the
> semantics of integer arithmetic, that's fair enough.  But if I /really/ want
> inlining, and write something like :
> 
>   __attribute__((optimize("-fwrapv"), always_inline))
>   static inline int wrapped_add(int a, int b) {
>       return a + b;
>   }
> 
> then I want the code treated as :
> 
>   return (__wrapping_int) a + (__wrapping_int) b;
> 
> or
> 
>   return __wrapping_add_int(a, b);
> 
> If the way gcc marks and handles "-fwrapv" arithmetic does not support
> something like that, which would allow inline mixing with other code, then
> that would result in a compiler warning or error message.

There is no way to do something like that for signed integer division because
the way GCC supports is using unsigned integer arithmetic and then an
unsigned to signed conversion.

GCC also currently does not support re-writing the inlined function
on-the-fly.

> It might be best to have a new attribute name here rather than using
> "always_inline" - I have not thought through the consequences.
> 
> It might also be that if the compiler can be changed to support inlining of
> a given optimisation attribute, then the attribute in question can be
> whitelisted for inlining for everyone.  I suppose what I am saying is that
> if the compiler can't be sure that inlining is safe, then it could be
> cautious by default while letting the programmer override that caution
> explicitly.

Indeed what we are missing is a diagnostic on the cases where always_inline
(or any other exception) overrides the explicit list of problematic
option mismatches.

For an example I was more looking into a case where there it is not one of
the explicitly rejected cases.  Like if people do

__attribute__((optimize("-fno-tree-pre")))
static inline int foo (...) { ... }

int bar (...) { ... foo (); ... }

there isn't a way to honor disabling PRE for the inlined code portion but
still enabling it for the code originating from bar.  So we can't fulfil
users expectation honoring the optimize attribute and inlining at the same
time.  Would you prioritize inlining here?  We most of the time prioritize
the 'optimize' attribute and -Winline diagnoses this fact.

^ permalink raw reply	[flat|nested] 9+ messages in thread

end of thread, other threads:[~2022-06-29  9:07 UTC | newest]

Thread overview: 9+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2021-07-01  8:16 [Bug c/101279] New: Function attributes often block inlining david at westcontrol dot com
2021-07-01 21:30 ` [Bug ipa/101279] " pinskia at gcc dot gnu.org
2021-07-02  0:08 ` msebor at gcc dot gnu.org
2022-06-28 12:20 ` frankhb1989 at gmail dot com
2022-06-28 12:33 ` rguenth at gcc dot gnu.org
2022-06-28 12:53 ` david at westcontrol dot com
2022-06-28 13:25 ` rguenther at suse dot de
2022-06-28 14:20 ` david at westcontrol dot com
2022-06-29  9:07 ` rguenth at gcc dot gnu.org

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).