This is the mail archive of the gcc@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

Re: question about inlining


On 12/06/2017 12:11 PM, Richard Biener wrote:
On December 6, 2017 6:38:11 PM GMT+01:00, Martin Sebor <msebor@gmail.com> wrote:
While testing a libstdc++ patch that relies on inlining to
expose a GCC limitation I noticed that the same member function
of a class template is inlined into one function in the test but
not into the other, even though it is inlined into each if each
is compiled separately (i.e., in a file on its own).

I wasn't aware that inlining decisions made in one function could
affect those in another, or in the whole file.  Is that expected?
And if yes, what's the rationale?

Here's a simplified test case.  When compiled with -O2 or -O3
and either just -DFOO or just -DBAR, the call to vector::resize()
and all the functions called from it, including (crucially)
vector::_M_default_append, are inlined.  But when compiled with
-DFOO -DBAR _M_default_append is not inlined.  With a somewhat
more involved test case I've also seen the first call inlined
but not the second, which was also surprising to me.

There are unit and function growth limits that can be hit.

I see, thank you for reminding me.

Nothing brings the implications into sharp focus like two virtually
identical functions optimized differently as a result of exceeding
some size limit.  It would make perfect sense to me if I were using
-Os but I can't help but wonder how useful this heuristic is at -O3.

It also makes me wonder if users are aware of how this impacts
their decisions to structure code.  If adding a new function to
a file containing carefully optimized code can result in outlining
what was previously inlined, it's probably best to define one
function per file.  I've seen C libraries laid out like that but
never a C++ program.

Martin

  #include <vector>

  void sink (std::vector<int>&);

  #if FOO
  void foo (unsigned n)
  {
    std::vector<int> a;
    a.resize (n);
    sink (a);
  }
  #endif

  #if BAR
  void bar (unsigned long n)
  {
    std::vector<int> a;
    a.resize (n);
    sink (a);
  }
  #endif

Thanks
Martin



Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]