Bug 9079 - [tree-ssa] Inline constant function pointers
Summary: [tree-ssa] Inline constant function pointers
Status: RESOLVED FIXED
Alias: None
Product: gcc
Classification: Unclassified
Component: tree-optimization (show other bugs)
Version: 3.2.1
: P3 enhancement
Target Milestone: ---
Assignee: Martin Jambor
URL:
Keywords: missed-optimization
: 28470 32751 (view as bug list)
Depends on:
Blocks: 8826
  Show dependency treegraph
 
Reported: 2002-12-28 03:26 UTC by 173513
Modified: 2008-10-22 15:09 UTC (History)
7 users (show)

See Also:
Host:
Target:
Build:
Known to work:
Known to fail:
Last reconfirmed: 2008-04-01 14:50:54


Attachments

Note You need to log in before you can comment on or make changes to this bug.
Description 173513 2002-12-28 03:26:05 UTC
[ Reported to the Debian BTS as report #173513.
  Please CC 173513@bugs.debian.org on replies.
  Log of report can be found at http://bugs.debian.org/173513 ]
	

Currently GCC will not inline a call of a function pointer that is known 
at compile time. For example, the following code will still result in 
the instruction "call funk" when run with -finline-functions on i386:

#include <stdio.h>

static char* funk() {
  return "Hello World.\n";
}

static void funky(char*(*func)()) {
  printf("%s", func());
}

void main() {
  funky(funk);
}

Although the call to funky is inlined, the call to funk is not, because 
in the source code it appears as a call of a function pointer. But as a 
consequence of funky being inlined, it would be possible to inline funk 
as well.

Release:
3.2.1 (Debian) (Debian unstable)

Environment:
System: Debian GNU/Linux (unstable)
Architecture: i686
host: i386-linux
Configured with: ../src/configure -v --enable-languages=c,c++,java,f77,proto,pascal,objc,ada --prefix=/usr --mandir=/usr/share/man --infodir=/usr/share/info --with-gxx-include-dir=/usr/include/c++/3.2 --enable-shared --with-system-zlib --enable-nls --without-included-gettext --enable-__cxa_atexit --enable-clocale=gnu --enable-java-gc=boehm --enable-objc-gc i386-linux
Thread model: posix
gcc version 3.2.2 20021212 (Debian prerelease)
Comment 1 Wolfgang Bangerth 2003-03-22 18:24:45 UTC
State-Changed-From-To: open->analyzed
State-Changed-Why: Confirmed on all branches
Comment 2 Andrew Pinski 2003-07-08 00:53:52 UTC
Mark this a dup of bug 3713 which was for c++ but now for all languages.

*** This bug has been marked as a duplicate of 3713 ***
Comment 3 Matthias Klose 2003-07-08 04:50:31 UTC
Subject: Re: Bug#173513:  Inline constant function pointers

pinskia at physics dot uc dot edu writes:
> Mark this a dup of bug 3713 which was for c++ but now for all languages.
> 
> *** This bug has been marked as a duplicate of 3713 ***

I fail to see a resolution to this report. The call to funk is not
inlined.
Comment 4 Andrew Pinski 2003-07-08 10:46:46 UTC
Subject: Re:  Inline constant function pointers

On Tuesday, Jul 8, 2003, at 00:50 US/Eastern, doko at cs dot tu-berlin 
dot de wrote:
> ------- Additional Comments From doko at cs dot tu-berlin dot de  
> 2003-07-08 04:50 -------
> Subject: Re: Bug#173513:  Inline constant function pointers
>
> pinskia at physics dot uc dot edu writes:
>> Mark this a dup of bug 3713 which was for c++ but now for all 
>> languages.
>>
>> *** This bug has been marked as a duplicate of 3713 ***
>
> I fail to see a resolution to this report. The call to funk is not
> inlined.

This bug was the same bug as 3713 which means that they were the same 
bug.
Having two bugs referring to the same bug in the database is usually 
not good
because we cannot keep track of which bugs are important and which bugs 
or not
and we also cannot keep track of which bugs get fixed, that is why bugs 
are
marked as duplicates of each other.

I hope this bug gets fixed for the tree-ssa branch which makes working 
on the tree a
lot easier and the it can fold the constant function pointer and then 
maybe inline it.

Thanks,
Andrew Pinski

Comment 5 Andrew Pinski 2004-04-21 02:22:01 UTC
Actually this is different than PR 3713.
Comment 6 Andrew Pinski 2004-04-21 02:23:22 UTC
And I have a patch which is for tree-ssa.
Comment 7 Andrew Pinski 2004-04-21 02:25:01 UTC
I should say that I have a partial fix for the tree-ssa, what needs to be done is inlining 
again.
Comment 8 Andrew Pinski 2004-05-17 01:32:12 UTC
Patch which also helps it the same way as my cast pass (which I am not going to submit 
at all).
Comment 9 Andrew Pinski 2004-05-17 15:33:00 UTC
The patch which helps is here: <http://gcc.gnu.org/ml/gcc-patches/2004-05/msg00991.html>.
Comment 10 Cesar Eduardo Barros 2004-05-20 00:10:01 UTC
I just hit this bug in a hairy piece of code which I reduced to the testcase
below (a should compile to the same thing as expected).

It's the same as this bug but with two layers of indirection instead of one.

#define inline inline __attribute__((always_inline))
#define regparm __attribute__((regparm(3)))
extern void regparm f(void);
static inline void regparm e(void)
{
	f();
}
static inline void regparm d(void)
{
	f();
}
static inline void regparm c(int x, void (regparm *p1)(void), void (regparm
*p2)(void))
{
	if (x)
		p1();
	else
		p2();
}
static inline void regparm b(int x, void (regparm *p)(int x, void (regparm
*p1)(void), void (regparm *p2)(void)))
{
	p(x, d, e);
}
void regparm a(int x)
{
	b(x, c);
}
void regparm expected(int x __attribute__((unused)))
{
	f();
}
Comment 11 stelios 2004-12-13 22:25:52 UTC
This is present in 3.4 too

--------------------------------------------
static inline int foo ()
{
	return 100;
}

typedef int (*fptr)();

static const fptr a [] = { foo };

static inline int call (int i)
{
	return a [i]();
}

static inline int call2 (fptr f)
{
	return f();
}

static const fptr F = foo;

int main ()
{
	return call (0) + call2 (foo) + F() +foo();
}
---------------------------------------------------

Here only F() and foo() are added at compile time
but it would be better if gcc just returned 400 w/o any other code.

Please fix!
Comment 12 Steven Bosscher 2005-01-23 15:14:51 UTC

*** This bug has been marked as a duplicate of 3713 ***
Comment 13 Andrew Pinski 2005-01-23 15:17:51 UTC
Again this is different than PR 3713. (steven is closing bugs which are not really fixed or dups right 
now).
Comment 14 Andrew Pinski 2006-07-24 19:41:23 UTC
*** Bug 28470 has been marked as a duplicate of this bug. ***
Comment 15 Andrew Pinski 2007-07-13 15:46:18 UTC
*** Bug 32751 has been marked as a duplicate of this bug. ***
Comment 16 rusty 2008-03-28 02:38:29 UTC
OK, this is fixed in gcc 4.3 (woot!), but the unused "funk" is still omitted.

See http://gcc.gnu.org/bugzilla/show_bug.cgi?id=35728
Comment 17 Richard Biener 2008-03-28 10:13:51 UTC
Note this is only fixed because we run inlining "twice".  It isn't fixed
properly in that the new inlining opportunity should be exposed during the
first inlining pass.
Comment 18 Martin Jambor 2008-04-01 14:50:54 UTC
I'm now working on a proper fix.
Comment 19 Martin Jambor 2008-07-25 17:51:59 UTC
As of revision 138092 we are handling this much better.

The example in bug description gets inlined at -O2 even with
-fno-early-inlining.

The example  in comment #10  does not work  as expected yet.   The new
edge is discovered but  the always_inline attribute is disregarded and
the inlined does  not decide to inline  it on its own.  I  will try to
fix this but it should be  noted that few guarantees can be made about
indirect  calls  to always_inline  functions  and about  always_inline
functions which have their addresses taken in general.

As far  as the  third example  in comment #11  is concerned,  the only
problem is  loading the  target function from  the array.   The loaded
value is not  recognized to be constant early  enough to be considered
for inlining.  That is really a separate issue though, quite different
from the one originally described.  I  will have a look at what we can
do earlier but I will close the bug if this is the only outstanding
issue and I don't see an easy fix.
Comment 20 Martin Jambor 2008-10-22 15:09:38 UTC
OK, here is the status regarding the trunk (4.4) and the test cases
posted here:

1. The test case in the bug description now works in the sense that
   funk is inlined even when not performing early inlining because
   both indirect inlining and copy propagation can help the inliner do
   this.  

2. When compiling the code from comment #10 with indirect inlining
   turned on (default on -O2) we end up with (taken from the
   "optimized" tree dump):

   a (int x)
   {
   <bb 2>:
     if (x != 0)
       goto <bb 3>;
     else
       goto <bb 4>;
   
   <bb 3>:
     f (); [tail call]
     goto <bb 5>;
   
   <bb 4>:
     f (); [tail call]
   
   <bb 5>:
     return;
   }

   Which obviously might be optimized even further but this is no
   longer an inlining issue.

3. Finally,  let's look at code  from comment #11.   The function main
   still retains  one call  to foo(), specifically  the one  that came
   from function  call().  The reason is  that early cpp  does not see
   the index  being constant and  thus does not replace  the array_ref
   directly  with the  constant.   Arguments could  be  made that  cpp
   should be run  few more times at various  places (after ipa-cp, for
   example)  but IMHO  pass ordering  would need  bigger justification
   than this  artificial example and  this would be very  difficult to
   implement  while also  retaining the  three phase  division  of ipa
   passes for lto.

Because we  are done  with all  three examples as  far as  inlining is
concerned, I think this is fixed.