Bug 31362 - gcc should not inline functions with 'section' attribute
Summary: gcc should not inline functions with 'section' attribute
Status: RESOLVED INVALID
Alias: None
Product: gcc
Classification: Unclassified
Component: c (show other bugs)
Version: 4.1.1
: P3 normal
Target Milestone: ---
Assignee: Not yet assigned to anyone
URL:
Keywords:
Depends on:
Blocks:
 
Reported: 2007-03-26 15:06 UTC by thutt
Modified: 2007-03-27 14:44 UTC (History)
2 users (show)

See Also:
Host:
Target:
Build:
Known to work: 3.3.6
Known to fail: 3.4.0 4.3.0
Last reconfirmed:


Attachments
Simple Script which will build the original C source (315 bytes, text/plain)
2007-03-26 15:08 UTC, thutt
Details
original source (115 bytes, text/plain)
2007-03-26 15:09 UTC, thutt
Details
preprocessed source (950 bytes, text/plain)
2007-03-26 15:09 UTC, thutt
Details

Note You need to log in before you can comment on or make changes to this bug.
Description thutt 2007-03-26 15:06:50 UTC
gcc should never inline functions which have a 'section' attribute set
on them.

If the section is placed at a specific location in memory via a linker
script, then the function will not be placed into its correct address,
and the resultant executable is incorrect.

gcc 4.1.1 will inline static function at -O1 and -O2, but not -O0 and
-O3; this can be seen by compiling the attached test program at
various optimization levels.

    static int __attribute__((section(".special_section"))) 
    special_function_0(void)
    {
       return 0;
    }

    int __attribute__((section(".special_section"))) 
    special_function_1(void)
    {
       return 0;
    }

    int main(void)
    {
       special_function_0();
       special_function_1();
       return 0;
    }
Comment 1 thutt 2007-03-26 15:08:18 UTC
Created attachment 13288 [details]
Simple Script which will build the original C source

Simple Script which will build the original C source
Comment 2 thutt 2007-03-26 15:09:11 UTC
Created attachment 13289 [details]
original source
Comment 3 thutt 2007-03-26 15:09:43 UTC
Created attachment 13290 [details]
preprocessed source
Comment 4 Richard Biener 2007-03-26 15:11:03 UTC
If it is incorrect to inline a function you should specify that with __attribute__((noinline)), I don't see why in general inlining a function which
out of line copy is in a special section is wrong.
Comment 5 thutt 2007-03-26 15:40:56 UTC
I'm going to argue that comment #4 is incorrect.

1.  This new behavior is a regression from previous versions of gcc.

2.  The 4.1.1 compiler gets it right at -O0 and -O3.  Previous
    versions of gcc which we've been using also get this right at all
    optimization levels.

3.  The function is 'static', not '__attribute__((inline))'.  The use
    of static doesn't implicitly give the optimizer permission to
    inline the function, it only declares the linkage to be
    'internal'.

    However, if the compiler determines that the function meets
    certain criteria, such as being static and not having its address
    taken, then it *can* inline it.

    These 'certain criteria' should be expanded to include changing
    the section of a function; if it's not in the default text
    section, it shouldn't be inlined.  (Of course, this shouldn't
    impact gcc's internal garbage collection mechanism of changing
    function & data sections).

In the actual implementation from which this test case was derived,
the function *must* reside at a specific location in memory, but due
to the inlining, it does not.  This causes failures in the
application.
Comment 6 Richard Biener 2007-03-26 15:47:14 UTC
<qoute>
In the actual implementation from which this test case was derived,
the function *must* reside at a specific location in memory, but due
to the inlining, it does not.  This causes failures in the
application.
</quote>

You should tell the compiler this.  This is exactly what we have the
noinline and the always_inline (for the opposite case) attributes for.

Note that 'inline' is a mere hint to the compiler, the compiler is free
to inline functions not marked as such if it is possible and looks profitable.
You could for example put a function in section .text.hot but of course still
want inlining if possible.

The behavior is not a regression really, as it is not documented that
the section attribute prevents inlining.  Overloading the section attribute
with this additional restriction does not look right.
Comment 7 Richard Biener 2007-03-26 15:51:32 UTC
Note that for your testcase even if you specify the noinline attribute the
function calls will be optimized away as the function calls do not have
side-effects.
Comment 8 thutt 2007-03-26 15:57:49 UTC
Furthermore, 

   4.  By placing the code in a different section, I'm instructing the
       the compiler to *not* put it in '.text'.  By inlining it, it
       places it in '.text' despite my instructions.
Comment 9 Richard Biener 2007-03-26 16:28:34 UTC
We inline static functions used once (special_function_0 in your testcase)
starting with the tree inliner which appeared in 3.4.0.  So the "bug" is present
in all releases starting from 3.4.0 and still present in mainline.
Comment 10 Andrew Pinski 2007-03-26 16:58:02 UTC
And now there is already an option to stop this inlining static functions called once.
http://gcc.gnu.org/onlinedocs/gcc/Optimize-Options.html#index-finline_002dfunctions_002dcalled_002donce-507
Comment 11 Richard Biener 2007-03-26 17:02:24 UTC
4.1.2 also inlines the other one, so that won't help.  Still noinline will.
Comment 12 thutt 2007-03-26 17:46:24 UTC
I respectfully submit that I think you guys are missing the point.

    The problem isn't that the compiler is inlining functions which
    are called once, the problem is that the compiler is inlining a
    function which I told it not to put into the '.text' section.

I fully understand that there are many ways to make gcc *not* inline
the function (noinline attribute, not static, call more than once,
take it's address), and I've already done that.

If I tell gcc to place code or data into another section, then it
should do that -- always.
Comment 13 Andrew Pinski 2007-03-26 18:10:45 UTC
Why do you think sections are special?
GCC does not know if a section is special or not and it really should not know.
Comment 14 thutt 2007-03-26 18:54:50 UTC
> Why do you think sections are special?
> GCC does not know if a section is special or not and it really should not know.

I don't necessarily think that sections are 'special', but since gcc
has the capability to change the section, it seems like it ought to
follow instructions.

If that's not convincing enough, let me quote from the gcc 'info' page
about function attributes:

     `section ("SECTION-NAME")'

          Normally, the compiler places the code it generates in the
          `text' section.  Sometimes, however, you need additional
          sections, or you need certain particular functions to appear
          in special sections.  The `section' attribute specifies that
          a function lives in a particular section.  For example, the
          declaration:

               extern void foobar (void) __attribute__ ((section ("bar")));

          puts the function `foobar' in the `bar' section.

          Some file formats do not support arbitrary sections so the
          `section' attribute is not available on all platforms.  If
          you need to map the entire contents of a module to a
          particular section, consider using the facilities of the
          linker instead.

I don't think that I can be more clear than this text -- placing an
__attribute__(section ("bar")) will place the attributed function into
the 'bar' section.

By inlining the function, it's *not* placing it into the 'bar'
section.

There are many reasons why a function might need to be placed into a
special section but those reasons are really moot since the
documentation of the compiler states exactly what the section attribute
is supposed to do.

Comment 15 Eric Weddington 2007-03-26 20:22:36 UTC
FWIW, I agree with the OP. This will place a burden on users who work with embedded systems such as the AVR. Special sections are sometimes needed in the AVR to place code into a special bootloader area that gets relocated at link time to a user defined address. Many times there is only a single function call to the bootloader code. As the problem is described, there is a potential that the bootloader call would be inlined, hence no longer properly in the section that has to be relocated to a special address. Now the burden will be left to the end user to figure out that they need to add noinline to work around a too aggressive, and too stupid inliner.
Comment 16 Andrew Pinski 2007-03-26 21:21:30 UTC
You supposed to mark all functions which you don't want inlined as noinline.  that is what the noinline attribute is there for.  The inliner is just too smart that is all.  If you want a dumber inliner fine, but don't complain to us when the inliner is not as good any more.
Comment 17 thutt 2007-03-27 13:49:29 UTC
In response to comment #16:

I wouldn't call an inliner which inlines functions specifically marked as "do not put this in '.text'" as 'smart'.  I'd use a more pejorative adjective, such as 'broken' or 'dumb'.
Comment 18 Richard Biener 2007-03-27 14:22:28 UTC
Well, you can continue to waste your time arguing here instead of fixing your code
with a few additions of noinline.

         'The `section' attribute specifies that
          a function lives in a particular section.'

this just says that the function (the out-of-line copy) lives in a particular
section.  It doesn't mention inlined copies of the function _body_.
Comment 19 thutt 2007-03-27 14:44:08 UTC
I guess I need a bigger typeface because I don't see where it says
'(the out-of-line copy)'.

Or, perhaps, you've simply added that '(the out-of-line copy)'
annotation yourself because that's what the code currently does, and
because it suits your agenda.  I guess you also felt free to interpret
that it's ok to inline such functions, even though it doesn't say any
such thing, and even though it goes against exactly what the 'section'
attribute intends to do.

But, as you stated, it's a waste of my time, and you folks obviously
aren't going to treat this as a legitmate defect, so there's no point
in continuing this.