Bug 24947

Summary: -Os should maximize inlining --param values.
Product: gcc Reporter: Mike Sharov <9ugsa9j02>
Component: middle-endAssignee: Not yet assigned to anyone <unassigned>
Status: RESOLVED INVALID    
Severity: normal CC: gcc-bugs
Priority: P3    
Version: 4.0.2   
Target Milestone: ---   
Host: Target: athlon-gnu-linux
Build: Known to work:
Known to fail: Last reconfirmed:

Description Mike Sharov 2005-11-20 00:58:32 UTC
When compiling with -Os and -Winline, many warnings like this occur:

file.cc:25: warning: inlining failed in call to 'function': --param inline-unit-growth limit reached

because the optimizer's inlining code gives up too early. The parameters most commonly exceeded are max-inline-insns-single, inline-unit-growth, and large-function-growth. This happens pretty much all the time in my code from all those deep STL interfaces, and I constantly have to specify some more appropriate (higher) values for the offending parameters.

All C++ code I have ever seen is written with lots of inlines. Those inline functions, almost always reduce code size when inlined, and when the optimizer passes them by, it leaves behind function calls to simple accessors that could have been compiled as a single movl.

Since -Os is supposed to optimize for size, it would be most logical to set those --param values to their maximum values (I use 1024, which works so far) to ensure all the inline functions are inlined. This works for -Os because -finline-functions is disabled and only those functions that are explicitly declared inline are inlined. With -finline-functions the large inlining parameters would probably generate nothing but bloat, and should remain at present values.
Comment 1 Andrew Pinski 2005-11-20 01:31:46 UTC
For 4.1, with -Os, -finline-functions is enabled, and the inlining params have been changed so that it has been tuned for -Os and csibe <http://www.csibe.org/>.
Comment 2 Andrew Pinski 2005-11-21 01:36:28 UTC
Do you have an example of where the params get in the way?
Comment 3 Mike Sharov 2005-11-21 15:07:33 UTC
By its very nature, demonstrating the problem requires a large example, so I am unable to provide a sufficiently compact one to post here. You can, however, download the project I'm having problems with from SourceForge http://sourceforge.net/projects/ustl. In it I'm using a custom configure script to set --param values and do what else I can to avoid these errors, so after running it you'll need to edit Config.mk to comment out INLINE_OPTS, add -Winline to CXXFLAGS, and change the default -O3 to -Os a little further down. The location of the resulting errors varies on different machines, but I always get them. Doing a test build now, I'm getting:

    Compiling cmemlink.cc ...
    Compiling fdostream.cc ...
cc1plus: warnings being treated as errors
memlink.h: In member function 'char* ustl::ostream::ipos()':
memlink.h:74: warning: inlining failed in call to 'char* ustl::memlink::begin()': --param max-inline-insns-single limit reached
mostream.h:62: warning: called from here
make: *** [cmemlink.o] Error 1
make: *** Waiting for unfinished jobs....
cc1plus: warnings being treated as errors
mistream.h: In member function 'virtual size_t ustl::istream::underflow(size_t)':
mistream.h:84: warning: inlining failed in call to 'size_t ustl::istream::remaining() const': --param max-inline-insns-single limit reached
mistream.h:81: warning: called from here
make: *** [fdostream.o] Error 1

Both begin() and remaining() are as simple as functions get, the former returning a member pointer, the latter subtracting two values.
Comment 4 Richard Earnshaw 2005-11-21 15:19:48 UTC
It seems to me that the problem here is that a 'warning' is too strong here, particularly with -Werror.  We really need a diagnostic that is non-fatal to the compilation, since there's nothing really wrong with the user's code.
Comment 5 Mike Sharov 2005-11-21 15:34:58 UTC
I would disagree. If the compiler ends up creating a function call where I expect a simple movl, that _is_ something I want to hear about as a warning. I have some code that uses inlines in really tight loops and having such a thing happen without any sign of what is going wrong would be a very bad thing indeed. At least now I know which --param to increase.
Comment 6 Richard Earnshaw 2005-11-21 15:49:36 UTC
Subject: Re:  -Os should maximize inlining --param
	values.

I didn't say the compiler shouldn't say anything, I said it shouldn't be
fatal.  Regardless of whether or not you think the limits are too low,
others may disagree and not want to change them.  That doesn't mean that
the compiler should reject their code because the limit has been
exceeded.  

This is not something that should cause -Werror to refuse compilation..

Comment 7 Mike Sharov 2005-11-21 16:01:21 UTC
(In reply to comment #6)
> This is not something that should cause -Werror to refuse compilation.

Well, according to the manpage, -Werror treats _all_ warnings as fatal, no matter what they are about. Since -Winline is an optional parameter that most normal people don't use, and one that is not enabled by either -Wall or -Wextra, I have no problem with the current behaviour.

> Regardless of whether or not you think the limits are too low,
> others may disagree and not want to change them.

Speaking of that, can anyone give me an example of when the limits would be considered too high? Or at all necessary? I can understand the need for them once the -finline-functions has been enabled, since it may end up inlining everything I own, but I don't think it is unreasonable to expect everything explicitly declared inline to be inlined in an optimized build. I did actually file a bug about that before, http://gcc.gnu.org/bugzilla/show_bug.cgi?id=21587, which was resolved WONTFIX, saying that "inline is always been just a hint to the compiler". It seems that this is the root of the problem right there: the refusal to distinguish explicitly inline functions from those that become inline due to -finline-functions. I'm pretty sure that if you run a poll of all the C++ programmers, they'll tell you that they expect the former to always be inlined in an optimized build, while the latter ought to depend on some specific command-line parameters. Perhaps it would be prudent to rethink 21587?
Comment 8 Andrew Pinski 2005-11-21 16:06:59 UTC
(In reply to comment #7)
I'm pretty sure that if you run a poll of all the C++
> programmers, they'll tell you that they expect the former to always be inlined
> in an optimized build, while the latter ought to depend on some specific
> command-line parameters. 

Depends on which C++ developers and if they have really thought about all their uses of inline (most have not even though they say they want functions declared as inline to be inlined)?

Also there are examples of where respecting inline will just cause the compiler to use so much memory/compile time is not funny.  An example is PR 8361.
Comment 9 Mike Sharov 2005-11-21 16:25:42 UTC
(In reply to comment #8)
> Depends on which C++ developers and if they have really thought about all their
> uses of inline (most have not even though they say they want functions declared
> as inline to be inlined)?

Since when does developer ignorance require workarounds in the compiler? If I "don't really think" about how I write my iterator loops, I fully deserve to have buffer overflows (although, if the compiler can be smart enough to generate a warning, that would be great!). Likewise, if I declare all my functions inline, then I deserve to get an incredibly bloated compiled executable. That's the spirit of C - do what I say, not what you think is good for me. If I wanted the latter, I'd be using Java.

> Also there are examples of where respecting inline will just cause the compiler
> to use so much memory/compile time is not funny.  An example is PR 8361.

Looking at that gave me the shivers :) Whoever wrote that code definitely didn't think about what should be inlined and what shouldn't be. They have inline functions a hundred lines long! I would say they got exactly what they deserved - slow compilation and a lot of bloat. If you write bad code, the bad code should be fixed, not the compiler, which is even in this case doing just what it is told to do.
Comment 10 Andrew Pinski 2006-08-21 05:35:35 UTC
No feedback in way over 3 months and the fact is there is still not a testcase after being asked a couple of times.  Second, we did maximize inlining paramaters for -Os already once for 4.1.0.
Comment 11 Jan Hubicka 2006-08-21 12:44:55 UTC
Just to note that for simple accestors (optimizing to single move), the compiler should be smart enough to figure out that inlining always reduce code size and inlining those will never hit any of the parameters mentioned. So increasing the parameters is just symptomatic fix and the metric computing profitability of inlining shall be tweaked instead.
If max-inline-isnsn-single is hit, compiler really believe that the function body is rather large and inlining cause code growth.
GCC at the moment is not terribly smart about discovering the simple wrappers and hopefully will somewhat improve with IPA branch.  However if there are really simple testcases where compiler is mistaken, I would be interested to see them.  (preferably as small self contained testcases ;)

Honza