Bug 37046 - [4.4 Regression] Inlining produces calls which gimple_call_fndecl cannot handle correctly
Summary: [4.4 Regression] Inlining produces calls which gimple_call_fndecl cannot hand...
Status: RESOLVED FIXED
Alias: None
Product: gcc
Classification: Unclassified
Component: middle-end (show other bugs)
Version: 4.4.0
: P3 normal
Target Milestone: 4.4.0
Assignee: Martin Jambor
URL:
Keywords: missed-optimization
Depends on:
Blocks:
 
Reported: 2008-08-07 10:09 UTC by Martin Jambor
Modified: 2008-09-10 10:11 UTC (History)
3 users (show)

See Also:
Host:
Target:
Build:
Known to work:
Known to fail:
Last reconfirmed: 2008-08-07 10:11:37


Attachments

Note You need to log in before you can comment on or make changes to this bug.
Description Martin Jambor 2008-08-07 10:09:50 UTC
In the following example, the  fucntion hooray() does not get inlined,
even though it could.

#include <stdlib.h>
#include <stdio.h>


static __attribute__((always_inline)) void hooray ()
{
  printf ("hooray\n");
}

static __attribute__((always_inline)) void hiphip (void (*f)())
{
  printf ("hip hip\n");
  f ();    
}


int main (int argc, int *argv[])
{
  hiphip (hooray);
  return 0;
}

int d()
{
  hiphip (hooray);
  return 86;
}


The reasons  are I believe  a bit more  grave than the fact  that this
(mis)use of anlways_inline does not work.  When tree-inline.c produces
an inlined copy of hiphip() it remaps the destination of the call to f
in  remap_gimple_stmt()  to  call   hooray.   However,  the  new  call
statement has this form:

  call<addr_expr<function_decl>> 

which  is a  form  that gimple_call_fndecl()  cannot  cope with.   The
consequence  is  that  rebuild_cgraph_edges()  sees  a  call  with  an
unretrievable declaration and does not build a call graph edge for it.

Therefore, when early inlining  inlines hiphip into its callers, there
is no  call graph  edge for main->hooray  (or d->hooray) and  so these
call sites  are not even  considered when doing regular  inlining, let
alone always_inlining.
Comment 1 Martin Jambor 2008-08-07 10:11:36 UTC
I am testing the patch below which should fix the problem:

2008-08-07  Martin Jambor  <mjambor@suse.cz>

	* tree-inline.c (remap_gimple_stmt): Remove extraneous addr_expr
	from call statements.

Index: iinln/gcc/tree-inline.c
===================================================================
--- iinln.orig/gcc/tree-inline.c
+++ iinln/gcc/tree-inline.c
@@ -1209,6 +1209,14 @@ remap_gimple_stmt (gimple stmt, copy_bod
   wi.info = id;
   walk_gimple_op (copy, remap_gimple_op_r, &wi); 
 
+  /* When a parameter is propagated into a call destination, it is in the form
+     of call<addr_expr<fndecl>> which gimple_call_fndecl does not understand.
+     Therefore we need to take the extra addr_expr out here. */
+  if (is_gimple_call (copy)
+      && TREE_CODE (gimple_call_fn (copy)) == ADDR_EXPR
+      && TREE_CODE (TREE_OPERAND (gimple_call_fn (copy), 0)) == FUNCTION_DECL)
+    gimple_call_set_fn (copy, TREE_OPERAND (gimple_call_fn (copy), 0));
+
   /* We have to handle EH region remapping of GIMPLE_RESX specially because
      the region number is not an operand.  */
   if (gimple_code (stmt) == GIMPLE_RESX && id->eh_region_offset)
Comment 2 Richard Biener 2008-08-07 13:14:57 UTC
Looks good.  Similar things may happen with CCP propagation for like

void foo(void) {}

void bar(void)
{
  void (*fn)(void) = foo;
  fn();
}

can you verify this as well?  Thanks.
Comment 3 Martin Jambor 2008-08-07 15:49:59 UTC
Unfortunately, I got a fortran regression:

/abuild/mjambor/iinln/gcc/testsuite/gfortran.dg/char_cast_1.f90:24: internal com
piler error: in expand_call_inline, at tree-inline.c:3117

The assert is gcc_assert (dest->needed); so I think I might have
uncovered some unrelated hidden problem.  We will see.

I will try to investigate but may not be able to go all the way
because I'm, leaving for vacation tomorrow.

Richi, that applies, to your question too.  I will try but I may not
make it.
Comment 4 Richard Biener 2008-08-07 16:00:28 UTC
Interesting.  I may have a look into the CCP problem.
Comment 5 Martin Jambor 2008-08-08 07:50:29 UTC
(In reply to comment #4)
> Interesting.  I may have a look into the CCP problem.
> 

Well, I think that we have pass_rebuild_cgraph_edges precisely because
passes like CCP are not trusted to update call graph correctly.  It is
not an elegant solution but might just work.

However, in order for it to work, gimple_call_fndecl() must be able to
find  the  declarations  (and  this  might also  be  problem  for  CCP
generated calls too).
Comment 6 Andrew Pinski 2008-08-10 20:27:34 UTC
Parts of it is fixed by:
http://gcc.gnu.org/ml/gcc-patches/2008-08/msg00549.html

Or is it a full fix, I can't tell anymore :).
Comment 7 rguenther@suse.de 2008-08-10 20:44:18 UTC
Subject: Re:  [4.4 Regression] Inlining produces calls
 which gimple_call_fndecl cannot handle correctly

On Sun, 10 Aug 2008, pinskia at gcc dot gnu dot org wrote:

> ------- Comment #6 from pinskia at gcc dot gnu dot org  2008-08-10 20:27 -------
> Parts of it is fixed by:
> http://gcc.gnu.org/ml/gcc-patches/2008-08/msg00549.html
> 
> Or is it a full fix, I can't tell anymore :).

It should fix it fully - but I'll leave it for Martin to check.

Richard.
Comment 8 Richard Biener 2008-08-22 15:04:30 UTC
Let's just close this.  Martin, please re-open if you figure that things are
still broken.
Comment 9 Martin Jambor 2008-09-10 10:11:29 UTC
I've been away from computer for a rather long time so I could not check earlier.  However, the problem is indeed gone.  Thanks Richi.