Patchwork [2/2] Replace the modified flag with AA-queries

login
register
mail settings
Submitter Martin Jambor
Date June 24, 2010, 11:05 p.m.
Message ID <20100624230526.GB2773@alvy.suse.cz>
Download mbox | patch
Permalink /patch/56869/
State New
Headers show

Comments

Martin Jambor - June 24, 2010, 11:05 p.m.
Hi,

On Mon, Jun 21, 2010 at 02:21:41PM +0200, Richard Guenther wrote:
> On Mon, 21 Jun 2010, Richard Guenther wrote:
> 
> > On Mon, 21 Jun 2010, Martin Jambor wrote:
> > 
> > > Hi,
> > > 
> > > indirect inlining was written before we had AA-info at our disposal in
> > > the "early" passes and so when confronted with the necessity to
> > > guarantee that a member pointer parameter was not changed before it
> > > was used I have resorted to requiring it is never modified in the
> > > whole function.
> > > 
> > > With alias analysis information this is no longer necessary.  This
> > > code therefore does away with the flag and uses AA instead.  To big
> > > extent I have copied the clobbering identification code from IPA-SRA
> > > and hope I got it correct.
> > > 
> > > I added a new testcase checking that we so not indirect-inline when we
> > > shouldn't because a member-pointer parameter is modified before being
> > > passed on.
> > > 
> > > I am aware that there are no hunks removing testcase
> > > gcc.dg/ipa/modif-1.c in the patch, that is because I generate my
> > > patches with quilt rather than svn.  I will remember to svn-delete the
> > > file.
> > > 
> > > I have bootstrapped and tested this patch (on top of the previous one)
> > > on x86_64-linux without any issues,  OK for trunk?
> > > 
> > > Thanks,
> > > 
> > > Martin
> > > 
> > > 
> > > 2010-06-18  Martin Jambor  <mjambor@suse.cz>
> > > 
> > > 	* ipa-prop.h (struct ipa_param_descriptor): Remove the modified flag.
> > > 	(ipa_is_param_modified): Removed.
> > > 	* ipa-prop.c (visit_store_addr_for_mod_analysis): Do not set the
> > > 	modified flag.
> > > 	(mark_modified): New function.
> > > 	(is_parm_modified_at_call): Likewise.
> > > 	(compute_pass_through_member_ptrs): Use is_parm_modified_at_call
> > > 	instead of ipa_is_param_modified.
> > > 	(ipa_analyze_indirect_call_uses): Likewise.
> > > 	(ipa_print_node_params): Do not dump the modified flag.
> > > 	(ipa_write_node_info): Do not stream the modified flag.
> > > 	(ipa_read_node_info): Likewise.
> > > 
> > > 	* testsuite/g++.dg/ipa/iinline-2.C: New test.
> > > 	* testsuite/gcc.dg/ipa/modif-1.c: Removed.
> > > 
> > > Index: icln/gcc/ipa-prop.c
> > > ===================================================================
> > > --- icln.orig/gcc/ipa-prop.c	2010-06-20 18:23:13.000000000 +0200
> > > +++ icln/gcc/ipa-prop.c	2010-06-20 18:24:32.000000000 +0200
> > > @@ -212,7 +212,6 @@ visit_store_addr_for_mod_analysis (gimpl
> > >      {
> > >        int index = ipa_get_param_decl_index (info, op);
> > >        gcc_assert (index >= 0);
> > > -      info->params[index].modified = true;
> > >        info->params[index].used = true;
> > >      }
> > >  
> > > @@ -707,6 +706,34 @@ type_like_member_ptr_p (tree type, tree
> > >    return true;
> > >  }
> > >  
> > > +/* Callback of walk_aliased_vdefs.  Flags that it has been invoked to the
> > > +   boolean variable pointed to by DATA.  */
> > > +
> > > +static bool
> > > +mark_modified (ao_ref *ao ATTRIBUTE_UNUSED, tree vdef ATTRIBUTE_UNUSED,
> > > +		     void *data)
> > > +{
> > > +  bool *b = (bool *) data;
> > > +  *b = true;
> > > +  return true;
> > > +}
> > > +
> > > +/* Return true if the formal parameter PARM might have been modified in this
> > > +   function before reaching the statement CALL.  */
> > > +
> > > +static bool
> > > +is_parm_modified_at_call (gimple call, tree parm)
> > > +{
> > > +  bool modified = false;
> > > +  ao_ref refd;
> > > +
> > > +  ao_ref_init (&refd, parm);
> > > +  walk_aliased_vdefs (&refd, gimple_vuse (call), mark_modified,
> > > +		      &modified, NULL);
> > > +
> > > +  return modified;
> > > +}
> > > +
> > >  /* Go through arguments of the CALL and for every one that looks like a member
> > >     pointer, check whether it can be safely declared pass-through and if so,
> > >     mark that to the corresponding item of jump FUNCTIONS.  Return true iff
> > > @@ -733,7 +760,7 @@ compute_pass_through_member_ptrs (struct
> > >  	      int index = ipa_get_param_decl_index (info, arg);
> > >  
> > >  	      gcc_assert (index >=0);
> > > -	      if (!ipa_is_param_modified (info, index))
> > > +	      if (!is_parm_modified_at_call (call, arg))
> > 
> > Hm, I do not understand this.  Do you just want to ask whether
> > arg is modified _by_ the call?  Or do you want to know whether
> > arg is modified on any path leading from function entry to
> > the call (which is what you implement)?  In that case I suggest
> > a better name for the function, like is_parm_modified_before_call.

OK, I have renamed the function, among other things.

> > 
> > Note that you are not implementing any kind of limiting, doing many
> > of these walk can be very expensive.

Right, I wanted to start with something simple but limiting should be
done.

> >  For example in the above loop
> > I'd first check whether arg is a PARM_DECL before checking
> > type_like_member_ptr_p. 

In compute_pass_through_member_ptrs, the result of
type_like_member_ptr_p is then used to determine whether we will scan
for constant member pointer arguments, hoping that most of the time we
won't.

> > And you can use one caching bitmap
> > per PARM_DECL for the visited parms to walk_aliased_vdefs which
> > will bound complexity to number of cfun arguments times number
> > of stores in the function (much better than number of cfun arguments
> > times calls in the function times number of stores in the function).
> 
> Thinking about this again you'd need to manage this caching
> yourself somehow (and stop walking in the callback if you hit it).
> You can keep a reaches-modification and doesn't-reach-modification
> bitmap and OR them from the is_parm_modified_at_call local bitmap
> depending on result.
> 

Well, I thought about this and eventually came to the conclusion that
trying to do member pointer indirect inlining (and these AA queries
are not used for anything else) in presence of complex modifications
of the parameters probably isn't worth the complexity.  Therefore I
decided to use a single visited_stmts bitmap and if
is_parm_modified_before_call returns true once, make it return true
for that parameter always.

This might not bring much more accuracy than we have now but has the
benefit of being able to avoid one complete walk of the function.
Currently, we need to get the modified flag correct by walking the
whole function before we embark on examining call statements looking
for indirect calls (including those of member pointers) and
calculating jump functions.  If we replace the modified flag with AA,
this is not necessary and the whole analysis can be done in one walk.

Moreover, we currently do two sweeps over all nodes just to get all
parameter descriptors and parameter counts initialized and to
calculate the modified flag for all nodes before computing the jump
functions.  If we do the initialization lazily, that is not necessary
either.

And that is what the patch below does.  It still includes a removal of
gcc.dg/ipa/modif-1.c because that is just a dump scan for the result
of modification analysis which we do not perform with this patch.  I
did add a new testcase that actually tests we get AA-queries right so
the coverage should not get worse.

I have bootstrapped and tested a very similar variant on x86-64-linux
without any problems, a bootstrap and test of exactly this version is
underway.  What so you think now?

Thanks,

Martin


2010-06-24  Martin Jambor  <mjambor@suse.cz>

	* ipa-prop.h (struct ipa_param_descriptor): Removed the modified flag.
	(struct ipa_node_params): Removed the modification_analysis_done flag.
	(ipa_is_param_modified): Removed.
	(ipa_analyze_node): Declare.
	(ipa_compute_jump_functions): Remove declaration.
	(ipa_count_arguments): Likewise.
	(ipa_detect_param_modifications): Likewise.
	(ipa_analyze_params_uses): Likewise.
	* ipa-prop.c (struct param_analysis_info): New type.
	(visit_store_addr_for_mod_analysis): Removed.
	(visit_load_for_mod_analysis): Renamed to visit_ref_for_mod_analysis,
	moved down in the file.
	(ipa_detect_param_modifications): Merged into ipa_analyze_params_uses.
	(ipa_count_arguments): Made static.
	(mark_modified): New function.
	(is_parm_modified_before_call): New function.
	(compute_pass_through_member_ptrs): New parameter parms_info, call
	is_parm_modified_before_call instead of ipa_is_param_modified.
	(ipa_compute_jump_functions_for_edge): New parameter parms_info, pass
	it to compute_pass_through_member_ptrs.
	(ipa_compute_jump_functions): New parameter parms_info, pass it to
	ipa_compute_jump_functions_for_edge.  Call ipa_initialize_node_params
	on the callee if it is analyzed.  Made static.
	(ipa_analyze_indirect_call_uses): New parameter parms_info, call
	is_parm_modified_before_call instead of ipa_is_param_modified.
	(ipa_analyze_call_uses): New parameter parms_info, pass it to
	ipa_analyze_indirect_call_uses.
	(ipa_analyze_stmt_uses): New parameter parms_info, pass it to
	ipa_analyze_call_uses.
	(ipa_analyze_params_uses): New parameter parms_info, pass it to
	ipa_analyze_stmt_uses.  Also perform the used analysis.  Made static.
	(ipa_analyze_node): New function.
	(ipa_print_node_params): Do not dump the modified flag.
	(ipa_write_node_info): Assert uses_analysis_done rather than streaming
	it.  Do not stream the modified parameter flag.
	(ipa_read_node_info): Set uses_analysis_done to 1 instead of streaming
	it.  Do not stream the modified parameter flag.
	* ipa-cp.c (ipcp_analyze_node): Removed.
	(ipcp_init_stage): Iterate only once over the nodes, analyze each one
	with only a call to ipa_analyze_node.
	* ipa-inline.c (inline_indirect_intraprocedural_analysis): Analyze the
	node with only a call to ipa_analyze_node.
	
	* testsuite/g++.dg/ipa/iinline-3.C: New test.
	* testsuite/gcc.dg/ipa/modif-1.c: Removed.
Jan Hubicka - June 25, 2010, 8:38 a.m.
> +  for (i = 0; i < ipa_get_param_count (info); i++)
> +    {
> +      tree parm = ipa_get_param (info, i);
> +      /* For SSA regs see if parameter is used.  For non-SSA we compute
> +	 the flag during modification analysis.  */
> +      if (is_gimple_reg (parm)
> +	  && gimple_default_def (DECL_STRUCT_FUNCTION (node->decl), parm))
> +	info->params[i].used = true;
> +    }
> +
>    func = DECL_STRUCT_FUNCTION (decl);
>    FOR_EACH_BB_FN (bb, func)
>      {
>        for (gsi = gsi_start_bb (bb); !gsi_end_p (gsi); gsi_next (&gsi))
>  	{
>  	  gimple stmt = gsi_stmt (gsi);
> -	  ipa_analyze_stmt_uses (node, info, stmt);
> +	  ipa_analyze_stmt_uses (node, info, parms_info, stmt);
> +	  walk_stmt_load_store_addr_ops (stmt, info,
> +					 visit_ref_for_mod_analysis,
> +					 visit_ref_for_mod_analysis,
> +					 visit_ref_for_mod_analysis);

You need to skip debug statements here too.
I discussed with Jakub the first loop (handling vie gimple_default_def)
and he claims it is safe since we should not keep SSA name around only for debug
statements.

Honza
Richard Guenther - June 25, 2010, 9:20 a.m.
On Fri, Jun 25, 2010 at 10:38 AM, Jan Hubicka <hubicka@ucw.cz> wrote:
>> +  for (i = 0; i < ipa_get_param_count (info); i++)
>> +    {
>> +      tree parm = ipa_get_param (info, i);
>> +      /* For SSA regs see if parameter is used.  For non-SSA we compute
>> +      the flag during modification analysis.  */
>> +      if (is_gimple_reg (parm)
>> +       && gimple_default_def (DECL_STRUCT_FUNCTION (node->decl), parm))
>> +     info->params[i].used = true;
>> +    }
>> +
>>    func = DECL_STRUCT_FUNCTION (decl);
>>    FOR_EACH_BB_FN (bb, func)
>>      {
>>        for (gsi = gsi_start_bb (bb); !gsi_end_p (gsi); gsi_next (&gsi))
>>       {
>>         gimple stmt = gsi_stmt (gsi);
>> -       ipa_analyze_stmt_uses (node, info, stmt);
>> +       ipa_analyze_stmt_uses (node, info, parms_info, stmt);
>> +       walk_stmt_load_store_addr_ops (stmt, info,
>> +                                      visit_ref_for_mod_analysis,
>> +                                      visit_ref_for_mod_analysis,
>> +                                      visit_ref_for_mod_analysis);
>
> You need to skip debug statements here too.
> I discussed with Jakub the first loop (handling vie gimple_default_def)
> and he claims it is safe since we should not keep SSA name around only for debug
> statements.

Works for me (thus, the patch is ok with the above suggested
change).

Thanks,
Richard.
H.J. Lu - July 12, 2010, 4:09 p.m.
On Thu, Jun 24, 2010 at 4:05 PM, Martin Jambor <mjambor@suse.cz> wrote:
> Hi,
>
> On Mon, Jun 21, 2010 at 02:21:41PM +0200, Richard Guenther wrote:
>> On Mon, 21 Jun 2010, Richard Guenther wrote:
>>
>> > On Mon, 21 Jun 2010, Martin Jambor wrote:
>> >
>> > > Hi,
>> > >
>> > > indirect inlining was written before we had AA-info at our disposal in
>> > > the "early" passes and so when confronted with the necessity to
>> > > guarantee that a member pointer parameter was not changed before it
>> > > was used I have resorted to requiring it is never modified in the
>> > > whole function.
>> > >
>> > > With alias analysis information this is no longer necessary.  This
>> > > code therefore does away with the flag and uses AA instead.  To big
>> > > extent I have copied the clobbering identification code from IPA-SRA
>> > > and hope I got it correct.
>> > >
>> > > I added a new testcase checking that we so not indirect-inline when we
>> > > shouldn't because a member-pointer parameter is modified before being
>> > > passed on.
>> > >
>> > > I am aware that there are no hunks removing testcase
>> > > gcc.dg/ipa/modif-1.c in the patch, that is because I generate my
>> > > patches with quilt rather than svn.  I will remember to svn-delete the
>> > > file.
>> > >
>> > > I have bootstrapped and tested this patch (on top of the previous one)
>> > > on x86_64-linux without any issues,  OK for trunk?
>> > >
>> > > Thanks,
>> > >
>> > > Martin
>> > >
>> > >
>> > > 2010-06-18  Martin Jambor  <mjambor@suse.cz>
>> > >
>> > >   * ipa-prop.h (struct ipa_param_descriptor): Remove the modified flag.
>> > >   (ipa_is_param_modified): Removed.
>> > >   * ipa-prop.c (visit_store_addr_for_mod_analysis): Do not set the
>> > >   modified flag.
>> > >   (mark_modified): New function.
>> > >   (is_parm_modified_at_call): Likewise.
>> > >   (compute_pass_through_member_ptrs): Use is_parm_modified_at_call
>> > >   instead of ipa_is_param_modified.
>> > >   (ipa_analyze_indirect_call_uses): Likewise.
>> > >   (ipa_print_node_params): Do not dump the modified flag.
>> > >   (ipa_write_node_info): Do not stream the modified flag.
>> > >   (ipa_read_node_info): Likewise.
>> > >
>> > >   * testsuite/g++.dg/ipa/iinline-2.C: New test.
>> > >   * testsuite/gcc.dg/ipa/modif-1.c: Removed.
>> > >
>> > > Index: icln/gcc/ipa-prop.c
>> > > ===================================================================
>> > > --- icln.orig/gcc/ipa-prop.c      2010-06-20 18:23:13.000000000 +0200
>> > > +++ icln/gcc/ipa-prop.c   2010-06-20 18:24:32.000000000 +0200
>> > > @@ -212,7 +212,6 @@ visit_store_addr_for_mod_analysis (gimpl
>> > >      {
>> > >        int index = ipa_get_param_decl_index (info, op);
>> > >        gcc_assert (index >= 0);
>> > > -      info->params[index].modified = true;
>> > >        info->params[index].used = true;
>> > >      }
>> > >
>> > > @@ -707,6 +706,34 @@ type_like_member_ptr_p (tree type, tree
>> > >    return true;
>> > >  }
>> > >
>> > > +/* Callback of walk_aliased_vdefs.  Flags that it has been invoked to the
>> > > +   boolean variable pointed to by DATA.  */
>> > > +
>> > > +static bool
>> > > +mark_modified (ao_ref *ao ATTRIBUTE_UNUSED, tree vdef ATTRIBUTE_UNUSED,
>> > > +              void *data)
>> > > +{
>> > > +  bool *b = (bool *) data;
>> > > +  *b = true;
>> > > +  return true;
>> > > +}
>> > > +
>> > > +/* Return true if the formal parameter PARM might have been modified in this
>> > > +   function before reaching the statement CALL.  */
>> > > +
>> > > +static bool
>> > > +is_parm_modified_at_call (gimple call, tree parm)
>> > > +{
>> > > +  bool modified = false;
>> > > +  ao_ref refd;
>> > > +
>> > > +  ao_ref_init (&refd, parm);
>> > > +  walk_aliased_vdefs (&refd, gimple_vuse (call), mark_modified,
>> > > +               &modified, NULL);
>> > > +
>> > > +  return modified;
>> > > +}
>> > > +
>> > >  /* Go through arguments of the CALL and for every one that looks like a member
>> > >     pointer, check whether it can be safely declared pass-through and if so,
>> > >     mark that to the corresponding item of jump FUNCTIONS.  Return true iff
>> > > @@ -733,7 +760,7 @@ compute_pass_through_member_ptrs (struct
>> > >         int index = ipa_get_param_decl_index (info, arg);
>> > >
>> > >         gcc_assert (index >=0);
>> > > -       if (!ipa_is_param_modified (info, index))
>> > > +       if (!is_parm_modified_at_call (call, arg))
>> >
>> > Hm, I do not understand this.  Do you just want to ask whether
>> > arg is modified _by_ the call?  Or do you want to know whether
>> > arg is modified on any path leading from function entry to
>> > the call (which is what you implement)?  In that case I suggest
>> > a better name for the function, like is_parm_modified_before_call.
>
> OK, I have renamed the function, among other things.
>
>> >
>> > Note that you are not implementing any kind of limiting, doing many
>> > of these walk can be very expensive.
>
> Right, I wanted to start with something simple but limiting should be
> done.
>
>> >  For example in the above loop
>> > I'd first check whether arg is a PARM_DECL before checking
>> > type_like_member_ptr_p.
>
> In compute_pass_through_member_ptrs, the result of
> type_like_member_ptr_p is then used to determine whether we will scan
> for constant member pointer arguments, hoping that most of the time we
> won't.
>
>> > And you can use one caching bitmap
>> > per PARM_DECL for the visited parms to walk_aliased_vdefs which
>> > will bound complexity to number of cfun arguments times number
>> > of stores in the function (much better than number of cfun arguments
>> > times calls in the function times number of stores in the function).
>>
>> Thinking about this again you'd need to manage this caching
>> yourself somehow (and stop walking in the callback if you hit it).
>> You can keep a reaches-modification and doesn't-reach-modification
>> bitmap and OR them from the is_parm_modified_at_call local bitmap
>> depending on result.
>>
>
> Well, I thought about this and eventually came to the conclusion that
> trying to do member pointer indirect inlining (and these AA queries
> are not used for anything else) in presence of complex modifications
> of the parameters probably isn't worth the complexity.  Therefore I
> decided to use a single visited_stmts bitmap and if
> is_parm_modified_before_call returns true once, make it return true
> for that parameter always.
>
> This might not bring much more accuracy than we have now but has the
> benefit of being able to avoid one complete walk of the function.
> Currently, we need to get the modified flag correct by walking the
> whole function before we embark on examining call statements looking
> for indirect calls (including those of member pointers) and
> calculating jump functions.  If we replace the modified flag with AA,
> this is not necessary and the whole analysis can be done in one walk.
>
> Moreover, we currently do two sweeps over all nodes just to get all
> parameter descriptors and parameter counts initialized and to
> calculate the modified flag for all nodes before computing the jump
> functions.  If we do the initialization lazily, that is not necessary
> either.
>
> And that is what the patch below does.  It still includes a removal of
> gcc.dg/ipa/modif-1.c because that is just a dump scan for the result
> of modification analysis which we do not perform with this patch.  I
> did add a new testcase that actually tests we get AA-queries right so
> the coverage should not get worse.
>
> I have bootstrapped and tested a very similar variant on x86-64-linux
> without any problems, a bootstrap and test of exactly this version is
> underway.  What so you think now?
>
> Thanks,
>
> Martin
>
>
> 2010-06-24  Martin Jambor  <mjambor@suse.cz>
>
>        * ipa-prop.h (struct ipa_param_descriptor): Removed the modified flag.
>        (struct ipa_node_params): Removed the modification_analysis_done flag.
>        (ipa_is_param_modified): Removed.
>        (ipa_analyze_node): Declare.
>        (ipa_compute_jump_functions): Remove declaration.
>        (ipa_count_arguments): Likewise.
>        (ipa_detect_param_modifications): Likewise.
>        (ipa_analyze_params_uses): Likewise.
>        * ipa-prop.c (struct param_analysis_info): New type.
>        (visit_store_addr_for_mod_analysis): Removed.
>        (visit_load_for_mod_analysis): Renamed to visit_ref_for_mod_analysis,
>        moved down in the file.
>        (ipa_detect_param_modifications): Merged into ipa_analyze_params_uses.
>        (ipa_count_arguments): Made static.
>        (mark_modified): New function.
>        (is_parm_modified_before_call): New function.
>        (compute_pass_through_member_ptrs): New parameter parms_info, call
>        is_parm_modified_before_call instead of ipa_is_param_modified.
>        (ipa_compute_jump_functions_for_edge): New parameter parms_info, pass
>        it to compute_pass_through_member_ptrs.
>        (ipa_compute_jump_functions): New parameter parms_info, pass it to
>        ipa_compute_jump_functions_for_edge.  Call ipa_initialize_node_params
>        on the callee if it is analyzed.  Made static.
>        (ipa_analyze_indirect_call_uses): New parameter parms_info, call
>        is_parm_modified_before_call instead of ipa_is_param_modified.
>        (ipa_analyze_call_uses): New parameter parms_info, pass it to
>        ipa_analyze_indirect_call_uses.
>        (ipa_analyze_stmt_uses): New parameter parms_info, pass it to
>        ipa_analyze_call_uses.
>        (ipa_analyze_params_uses): New parameter parms_info, pass it to
>        ipa_analyze_stmt_uses.  Also perform the used analysis.  Made static.
>        (ipa_analyze_node): New function.
>        (ipa_print_node_params): Do not dump the modified flag.
>        (ipa_write_node_info): Assert uses_analysis_done rather than streaming
>        it.  Do not stream the modified parameter flag.
>        (ipa_read_node_info): Set uses_analysis_done to 1 instead of streaming
>        it.  Do not stream the modified parameter flag.
>        * ipa-cp.c (ipcp_analyze_node): Removed.
>        (ipcp_init_stage): Iterate only once over the nodes, analyze each one
>        with only a call to ipa_analyze_node.
>        * ipa-inline.c (inline_indirect_intraprocedural_analysis): Analyze the
>        node with only a call to ipa_analyze_node.
>
>        * testsuite/g++.dg/ipa/iinline-3.C: New test.
>        * testsuite/gcc.dg/ipa/modif-1.c: Removed.
>
>

This caused:

http://gcc.gnu.org/bugzilla/show_bug.cgi?id=44915

Patch

Index: icln/gcc/ipa-prop.c
===================================================================
--- icln.orig/gcc/ipa-prop.c	2010-06-24 12:13:10.000000000 +0200
+++ icln/gcc/ipa-prop.c	2010-06-24 23:13:47.000000000 +0200
@@ -39,6 +39,16 @@  along with GCC; see the file COPYING3.
 #include "gimple-pretty-print.h"
 #include "lto-streamer.h"
 
+
+/* Intermediate information about a parameter that is only useful during the
+   run of ipa_analyze_node and is not kept afterwards.  */
+
+struct param_analysis_info
+{
+  bool modified;
+  bitmap visited_statements;
+};
+
 /* Vector where the parameter infos are actually stored. */
 VEC (ipa_node_params_t, heap) *ipa_node_params_vector;
 /* Vector where the parameter infos are actually stored. */
@@ -196,101 +206,10 @@  ipa_initialize_node_params (struct cgrap
     }
 }
 
-/* Callback of walk_stmt_load_store_addr_ops for the visit_store and visit_addr
-   parameters.  If OP is a parameter declaration, mark it as modified in the
-   info structure passed in DATA.  */
-
-static bool
-visit_store_addr_for_mod_analysis (gimple stmt ATTRIBUTE_UNUSED,
-				   tree op, void *data)
-{
-  struct ipa_node_params *info = (struct ipa_node_params *) data;
-
-  op = get_base_address (op);
-  if (op
-      && TREE_CODE (op) == PARM_DECL)
-    {
-      int index = ipa_get_param_decl_index (info, op);
-      gcc_assert (index >= 0);
-      info->params[index].modified = true;
-      info->params[index].used = true;
-    }
-
-  return false;
-}
-
-/* Callback of walk_stmt_load_store_addr_ops for the visit_load.
-   If OP is a parameter declaration, mark it as used in the info structure
-   passed in DATA.  */
-
-static bool
-visit_load_for_mod_analysis (gimple stmt ATTRIBUTE_UNUSED,
-			     tree op, void *data)
-{
-  struct ipa_node_params *info = (struct ipa_node_params *) data;
-
-  op = get_base_address (op);
-  if (op
-      && TREE_CODE (op) == PARM_DECL)
-    {
-      int index = ipa_get_param_decl_index (info, op);
-      gcc_assert (index >= 0);
-      info->params[index].used = true;
-    }
-
-  return false;
-}
-
-/* Compute which formal parameters of function associated with NODE are locally
-   modified or their address is taken.  Note that this does not apply on
-   parameters with SSA names but those can and should be analyzed
-   differently.  */
-
-void
-ipa_detect_param_modifications (struct cgraph_node *node)
-{
-  tree decl = node->decl;
-  basic_block bb;
-  struct function *func;
-  gimple_stmt_iterator gsi;
-  struct ipa_node_params *info = IPA_NODE_REF (node);
-  int i;
-
-  if (ipa_get_param_count (info) == 0 || info->modification_analysis_done)
-    return;
-
-  for (i = 0; i < ipa_get_param_count (info); i++)
-    {
-      tree parm = ipa_get_param (info, i);
-      /* For SSA regs see if parameter is used.  For non-SSA we compute
-	 the flag during modification analysis.  */
-      if (is_gimple_reg (parm)
-	  && gimple_default_def (DECL_STRUCT_FUNCTION (node->decl), parm))
-	info->params[i].used = true;
-    }
-
-  func = DECL_STRUCT_FUNCTION (decl);
-  FOR_EACH_BB_FN (bb, func)
-    {
-      for (gsi = gsi_start_bb (bb); !gsi_end_p (gsi); gsi_next (&gsi))
-	walk_stmt_load_store_addr_ops (gsi_stmt (gsi), info,
-				       visit_load_for_mod_analysis,
-				       visit_store_addr_for_mod_analysis,
-				       visit_store_addr_for_mod_analysis);
-      for (gsi = gsi_start (phi_nodes (bb)); !gsi_end_p (gsi); gsi_next (&gsi))
-	walk_stmt_load_store_addr_ops (gsi_stmt (gsi), info,
-				       visit_load_for_mod_analysis,
-				       visit_store_addr_for_mod_analysis,
-				       visit_store_addr_for_mod_analysis);
-    }
-
-  info->modification_analysis_done = 1;
-}
-
 /* Count number of arguments callsite CS has and store it in
    ipa_edge_args structure corresponding to this callsite.  */
 
-void
+static void
 ipa_count_arguments (struct cgraph_edge *cs)
 {
   gimple stmt;
@@ -707,14 +626,53 @@  type_like_member_ptr_p (tree type, tree
   return true;
 }
 
+/* Callback of walk_aliased_vdefs.  Flags that it has been invoked to the
+   boolean variable pointed to by DATA.  */
+
+static bool
+mark_modified (ao_ref *ao ATTRIBUTE_UNUSED, tree vdef ATTRIBUTE_UNUSED,
+		     void *data)
+{
+  bool *b = (bool *) data;
+  *b = true;
+  return true;
+}
+
+/* Return true if the formal parameter PARM might have been modified in this
+   function before reaching the statement CALL.  PARM_INFO is a pointer to a
+   structure containing intermediate information about PARM.  */
+
+static bool
+is_parm_modified_before_call (struct param_analysis_info *parm_info,
+			      gimple call, tree parm)
+{
+  bool modified = false;
+  ao_ref refd;
+
+  if (parm_info->modified)
+    return true;
+
+  ao_ref_init (&refd, parm);
+  walk_aliased_vdefs (&refd, gimple_vuse (call), mark_modified,
+		      &modified, &parm_info->visited_statements);
+  if (modified)
+    {
+      parm_info->modified = true;
+      return true;
+    }
+  return false;
+}
+
 /* Go through arguments of the CALL and for every one that looks like a member
    pointer, check whether it can be safely declared pass-through and if so,
    mark that to the corresponding item of jump FUNCTIONS.  Return true iff
    there are non-pass-through member pointers within the arguments.  INFO
-   describes formal parameters of the caller.  */
+   describes formal parameters of the caller.  PARMS_INFO is a pointer to a
+   vector containing intermediate information about each formal parameter.  */
 
 static bool
 compute_pass_through_member_ptrs (struct ipa_node_params *info,
+				  struct param_analysis_info *parms_info,
 				  struct ipa_jump_func *functions,
 				  gimple call)
 {
@@ -733,7 +691,7 @@  compute_pass_through_member_ptrs (struct
 	      int index = ipa_get_param_decl_index (info, arg);
 
 	      gcc_assert (index >=0);
-	      if (!ipa_is_param_modified (info, index))
+	      if (!is_parm_modified_before_call (&parms_info[index], call, arg))
 		{
 		  functions[num].type = IPA_JF_PASS_THROUGH;
 		  functions[num].value.pass_through.formal_id = index;
@@ -887,7 +845,8 @@  compute_cst_member_ptr_arguments (struct
    to this callsite.  */
 
 static void
-ipa_compute_jump_functions_for_edge (struct cgraph_edge *cs)
+ipa_compute_jump_functions_for_edge (struct param_analysis_info *parms_info,
+				     struct cgraph_edge *cs)
 {
   struct ipa_node_params *info = IPA_NODE_REF (cs->caller);
   struct ipa_edge_args *arguments = IPA_EDGE_REF (cs);
@@ -906,7 +865,8 @@  ipa_compute_jump_functions_for_edge (str
 
   /* Let's check whether there are any potential member pointers and if so,
      whether we can determine their functions as pass_through.  */
-  if (!compute_pass_through_member_ptrs (info, arguments->jump_functions, call))
+  if (!compute_pass_through_member_ptrs (info, parms_info,
+					 arguments->jump_functions, call))
     return;
 
   /* Finally, let's check whether we actually pass a new constant member
@@ -917,8 +877,9 @@  ipa_compute_jump_functions_for_edge (str
 /* Compute jump functions for all edges - both direct and indirect - outgoing
    from NODE.  Also count the actual arguments in the process.  */
 
-void
-ipa_compute_jump_functions (struct cgraph_node *node)
+static void
+ipa_compute_jump_functions (struct cgraph_node *node,
+			    struct param_analysis_info *parms_info)
 {
   struct cgraph_edge *cs;
 
@@ -929,16 +890,20 @@  ipa_compute_jump_functions (struct cgrap
       if (!cs->callee->analyzed && !flag_lto && !flag_whopr)
 	continue;
       ipa_count_arguments (cs);
+      /* If the descriptor of the callee is not initialized yet, we have to do
+	 it now. */
+      if (cs->callee->analyzed)
+	ipa_initialize_node_params (cs->callee);
       if (ipa_get_cs_argument_count (IPA_EDGE_REF (cs))
 	  != ipa_get_param_count (IPA_NODE_REF (cs->callee)))
 	ipa_set_called_with_variable_arg (IPA_NODE_REF (cs->callee));
-      ipa_compute_jump_functions_for_edge (cs);
+      ipa_compute_jump_functions_for_edge (parms_info, cs);
     }
 
   for (cs = node->indirect_calls; cs; cs = cs->next_callee)
     {
       ipa_count_arguments (cs);
-      ipa_compute_jump_functions_for_edge (cs);
+      ipa_compute_jump_functions_for_edge (parms_info, cs);
     }
 }
 
@@ -1022,13 +987,15 @@  ipa_note_param_call (struct cgraph_node
 }
 
 /* Analyze the CALL and examine uses of formal parameters of the caller NODE
-   (described by INFO).  Currently it checks whether the call calls a pointer
-   that is a formal parameter and if so, the parameter is marked with the
-   called flag and an indirect call graph edge describing the call is created.
-   This is very simple for ordinary pointers represented in SSA but not-so-nice
-   when it comes to member pointers.  The ugly part of this function does
-   nothing more than trying to match the pattern of such a call.  An example of
-   such a pattern is the gimple dump below, the call is on the last line:
+   (described by INFO).  PARMS_INFO is a pointer to a vector containing
+   intermediate information about each formal parameter.  Currently it checks
+   whether the call calls a pointer that is a formal parameter and if so, the
+   parameter is marked with the called flag and an indirect call graph edge
+   describing the call is created.  This is very simple for ordinary pointers
+   represented in SSA but not-so-nice when it comes to member pointers.  The
+   ugly part of this function does nothing more than trying to match the
+   pattern of such a call.  An example of such a pattern is the gimple dump
+   below, the call is on the last line:
 
      <bb 2>:
        f$__delta_5 = f.__delta;
@@ -1074,6 +1041,7 @@  ipa_note_param_call (struct cgraph_node
 static void
 ipa_analyze_indirect_call_uses (struct cgraph_node *node,
 				struct ipa_node_params *info,
+				struct param_analysis_info *parms_info,
 				gimple call, tree target)
 {
   gimple def;
@@ -1185,7 +1153,8 @@  ipa_analyze_indirect_call_uses (struct c
     return;
 
   index = ipa_get_param_decl_index (info, rec);
-  if (index >= 0 && !ipa_is_param_modified (info, index))
+  if (index >= 0 && !is_parm_modified_before_call (&parms_info[index],
+						   call, rec))
     ipa_note_param_call (node, index, call, false);
 
   return;
@@ -1228,16 +1197,18 @@  ipa_analyze_virtual_call_uses (struct cg
 }
 
 /* Analyze a call statement CALL whether and how it utilizes formal parameters
-   of the caller (described by INFO). */
+   of the caller (described by INFO).  PARMS_INFO is a pointer to a vector
+   containing intermediate information about each formal parameter.  */
 
 static void
 ipa_analyze_call_uses (struct cgraph_node *node,
-		       struct ipa_node_params *info, gimple call)
+		       struct ipa_node_params *info,
+		       struct param_analysis_info *parms_info, gimple call)
 {
   tree target = gimple_call_fn (call);
 
   if (TREE_CODE (target) == SSA_NAME)
-    ipa_analyze_indirect_call_uses (node, info, call, target);
+    ipa_analyze_indirect_call_uses (node, info, parms_info, call, target);
   else if (TREE_CODE (target) == OBJ_TYPE_REF)
     ipa_analyze_virtual_call_uses (node, info, call, target);
 }
@@ -1245,45 +1216,116 @@  ipa_analyze_call_uses (struct cgraph_nod
 
 /* Analyze the call statement STMT with respect to formal parameters (described
    in INFO) of caller given by NODE.  Currently it only checks whether formal
-   parameters are called.  */
+   parameters are called.  PARMS_INFO is a pointer to a vector containing
+   intermediate information about each formal parameter.  */
 
 static void
 ipa_analyze_stmt_uses (struct cgraph_node *node, struct ipa_node_params *info,
-		       gimple stmt)
+		       struct param_analysis_info *parms_info, gimple stmt)
 {
   if (is_gimple_call (stmt))
-    ipa_analyze_call_uses (node, info, stmt);
+    ipa_analyze_call_uses (node, info, parms_info, stmt);
+}
+
+/* Callback of walk_stmt_load_store_addr_ops for the visit_load.
+   If OP is a parameter declaration, mark it as used in the info structure
+   passed in DATA.  */
+
+static bool
+visit_ref_for_mod_analysis (gimple stmt ATTRIBUTE_UNUSED,
+			     tree op, void *data)
+{
+  struct ipa_node_params *info = (struct ipa_node_params *) data;
+
+  op = get_base_address (op);
+  if (op
+      && TREE_CODE (op) == PARM_DECL)
+    {
+      int index = ipa_get_param_decl_index (info, op);
+      gcc_assert (index >= 0);
+      info->params[index].used = true;
+    }
+
+  return false;
 }
 
 /* Scan the function body of NODE and inspect the uses of formal parameters.
    Store the findings in various structures of the associated ipa_node_params
-   structure, such as parameter flags, notes etc.  */
+   structure, such as parameter flags, notes etc.  PARMS_INFO is a pointer to a
+   vector containing intermediate information about each formal parameter.   */
 
-void
-ipa_analyze_params_uses (struct cgraph_node *node)
+static void
+ipa_analyze_params_uses (struct cgraph_node *node,
+			 struct param_analysis_info *parms_info)
 {
   tree decl = node->decl;
   basic_block bb;
   struct function *func;
   gimple_stmt_iterator gsi;
   struct ipa_node_params *info = IPA_NODE_REF (node);
+  int i;
 
   if (ipa_get_param_count (info) == 0 || info->uses_analysis_done)
     return;
 
+  for (i = 0; i < ipa_get_param_count (info); i++)
+    {
+      tree parm = ipa_get_param (info, i);
+      /* For SSA regs see if parameter is used.  For non-SSA we compute
+	 the flag during modification analysis.  */
+      if (is_gimple_reg (parm)
+	  && gimple_default_def (DECL_STRUCT_FUNCTION (node->decl), parm))
+	info->params[i].used = true;
+    }
+
   func = DECL_STRUCT_FUNCTION (decl);
   FOR_EACH_BB_FN (bb, func)
     {
       for (gsi = gsi_start_bb (bb); !gsi_end_p (gsi); gsi_next (&gsi))
 	{
 	  gimple stmt = gsi_stmt (gsi);
-	  ipa_analyze_stmt_uses (node, info, stmt);
+	  ipa_analyze_stmt_uses (node, info, parms_info, stmt);
+	  walk_stmt_load_store_addr_ops (stmt, info,
+					 visit_ref_for_mod_analysis,
+					 visit_ref_for_mod_analysis,
+					 visit_ref_for_mod_analysis);
 	}
+      for (gsi = gsi_start (phi_nodes (bb)); !gsi_end_p (gsi); gsi_next (&gsi))
+	walk_stmt_load_store_addr_ops (gsi_stmt (gsi), info,
+				       visit_ref_for_mod_analysis,
+				       visit_ref_for_mod_analysis,
+				       visit_ref_for_mod_analysis);
     }
 
   info->uses_analysis_done = 1;
 }
 
+/* Initialize the array describing properties of of formal parameters of NODE,
+   analyze their uses and and compute jump functions associated witu actual
+   arguments of calls from within NODE.  */
+
+void
+ipa_analyze_node (struct cgraph_node *node)
+{
+  struct ipa_node_params *info = IPA_NODE_REF (node);
+  struct param_analysis_info *parms_info;
+  int i, param_count;
+
+  ipa_initialize_node_params (node);
+
+  param_count = ipa_get_param_count (info);
+  parms_info = XALLOCAVEC (struct param_analysis_info, param_count);
+  memset (parms_info, 0, sizeof (struct param_analysis_info) * param_count);
+
+  ipa_analyze_params_uses (node, parms_info);
+  ipa_compute_jump_functions (node, parms_info);
+
+  for (i = 0; i < param_count; i++)
+    if (parms_info[i].visited_statements)
+      BITMAP_FREE (parms_info[i].visited_statements);
+}
+
+
 /* Update the jump function DST when the call graph edge correspondng to SRC is
    is being inlined, knowing that DST is of type ancestor and src of known
    type.  */
@@ -1855,8 +1897,6 @@  ipa_print_node_params (FILE * f, struct
                  (DECL_NAME (temp)
                   ? (*lang_hooks.decl_printable_name) (temp, 2)
                   : "(unnamed)"));
-      if (ipa_is_param_modified (info, i))
-	fprintf (f, " modified");
       if (ipa_is_param_used (info, i))
 	fprintf (f, " used");
       fprintf (f, "\n");
@@ -2465,16 +2505,12 @@  ipa_write_node_info (struct output_block
 
   bp = bitpack_create (ob->main_stream);
   bp_pack_value (&bp, info->called_with_var_arguments, 1);
-  bp_pack_value (&bp, info->uses_analysis_done, 1);
-  gcc_assert (info->modification_analysis_done
+  gcc_assert (info->uses_analysis_done
 	      || ipa_get_param_count (info) == 0);
   gcc_assert (!info->node_enqueued);
   gcc_assert (!info->ipcp_orig_node);
   for (j = 0; j < ipa_get_param_count (info); j++)
-    {
-      bp_pack_value (&bp, info->params[j].modified, 1);
-      bp_pack_value (&bp, info->params[j].used, 1);
-    }
+    bp_pack_value (&bp, info->params[j].used, 1);
   lto_output_bitpack (&bp);
   for (e = node->callees; e; e = e->next_callee)
     {
@@ -2504,18 +2540,11 @@  ipa_read_node_info (struct lto_input_blo
 
   bp = lto_input_bitpack (ib);
   info->called_with_var_arguments = bp_unpack_value (&bp, 1);
-  info->uses_analysis_done = bp_unpack_value (&bp, 1);
   if (ipa_get_param_count (info) != 0)
-    {
-      info->modification_analysis_done = true;
-      info->uses_analysis_done = true;
-    }
+    info->uses_analysis_done = true;
   info->node_enqueued = false;
   for (k = 0; k < ipa_get_param_count (info); k++)
-    {
-      info->params[k].modified = bp_unpack_value (&bp, 1);
-      info->params[k].used = bp_unpack_value (&bp, 1);
-    }
+    info->params[k].used = bp_unpack_value (&bp, 1);
   for (e = node->callees; e; e = e->next_callee)
     {
       struct ipa_edge_args *args = IPA_EDGE_REF (e);
Index: icln/gcc/ipa-prop.h
===================================================================
--- icln.orig/gcc/ipa-prop.h	2010-06-24 12:13:10.000000000 +0200
+++ icln/gcc/ipa-prop.h	2010-06-24 12:13:21.000000000 +0200
@@ -161,8 +161,6 @@  struct ipa_param_descriptor
   struct ipcp_lattice ipcp_lattice;
   /* PARAM_DECL of this parameter.  */
   tree decl;
-  /* Whether the value parameter has been modified within the function.  */
-  unsigned modified : 1;
   /* The parameter is used.  */
   unsigned used : 1;
 };
@@ -179,8 +177,6 @@  struct ipa_node_params
   /* Whether this function is called with variable number of actual
      arguments.  */
   unsigned called_with_var_arguments : 1;
-  /* Whether the modification analysis has already been performed. */
-  unsigned modification_analysis_done : 1;
   /* Whether the param uses analysis has already been performed.  */
   unsigned uses_analysis_done : 1;
   /* Whether the function is enqueued in an ipa_func_list.  */
@@ -228,17 +224,6 @@  ipa_get_param (struct ipa_node_params *i
   return info->params[i].decl;
 }
 
-/* Return the modification flag corresponding to the Ith formal parameter of
-   the function associated with INFO.  Note that there is no setter method as
-   the goal is to set all flags when building the array in
-   ipa_detect_param_modifications.  */
-
-static inline bool
-ipa_is_param_modified (struct ipa_node_params *info, int i)
-{
-  return info->params[i].modified;
-}
-
 /* Return the used flag corresponding to the Ith formal parameter of
    the function associated with INFO.  */
 
@@ -412,14 +397,10 @@  ipa_push_func_to_list (struct ipa_func_l
     ipa_push_func_to_list_1 (wl, node, info);
 }
 
-/* Callsite related calculations.  */
-void ipa_compute_jump_functions (struct cgraph_node *);
-void ipa_count_arguments (struct cgraph_edge *);
+void ipa_analyze_node (struct cgraph_node *);
 
 /* Function formal parameters related computations.  */
 void ipa_initialize_node_params (struct cgraph_node *node);
-void ipa_detect_param_modifications (struct cgraph_node *);
-void ipa_analyze_params_uses (struct cgraph_node *);
 bool ipa_propagate_indirect_call_infos (struct cgraph_edge *cs,
 					VEC (cgraph_edge_p, heap) **new_edges);
 
Index: icln/gcc/testsuite/g++.dg/ipa/iinline-3.C
===================================================================
--- /dev/null	1970-01-01 00:00:00.000000000 +0000
+++ icln/gcc/testsuite/g++.dg/ipa/iinline-3.C	2010-06-24 12:13:21.000000000 +0200
@@ -0,0 +1,64 @@ 
+/* Verify that we do not indirect-inline using member pointer
+   parameters which have been modified.  */
+/* { dg-do run } */
+/* { dg-options "-O3 -fno-early-inlining"  } */
+/* { dg-add-options bind_pic_locally } */
+
+extern "C" void abort (void);
+
+class String
+{
+private:
+  const char *data;
+
+public:
+  String (const char *d) : data(d)
+  {}
+
+  int funcOne (int stuff) const;
+  int funcTwo (int stuff) const;
+};
+
+
+int String::funcOne (int stuff) const
+{
+  return stuff + 1;
+}
+
+int String::funcTwo (int stuff) const
+{
+  return stuff + 100;
+}
+
+int (String::* gmp)(int stuff) const = &String::funcTwo;
+
+int docalling_1 (int (String::* f)(int stuff) const)
+{
+  String S ("muhehehe");
+
+  return (S.*f)(4);
+}
+
+int docalling (int a, int (String::* f)(int stuff) const)
+{
+  if (a < 200)
+    f = gmp;
+
+  return docalling_1 (f);
+}
+
+int __attribute__ ((noinline,noclone)) get_input (void)
+{
+  return 1;
+}
+
+int main (int argc, char *argv[])
+{
+  int i = 0;
+  while (i < 10)
+    i += docalling (get_input (), &String::funcOne);
+
+  if (i != 104)
+    abort();
+  return 0;
+}
Index: icln/gcc/ipa-cp.c
===================================================================
--- icln.orig/gcc/ipa-cp.c	2010-06-24 12:13:10.000000000 +0200
+++ icln/gcc/ipa-cp.c	2010-06-24 23:43:34.000000000 +0200
@@ -177,18 +177,6 @@  ipcp_init_cloned_node (struct cgraph_nod
   IPA_NODE_REF (new_node)->ipcp_orig_node = orig_node;
 }
 
-/* Perform intraprocedrual analysis needed for ipcp.  */
-static void
-ipcp_analyze_node (struct cgraph_node *node)
-{
-  /* Unreachable nodes should have been eliminated before ipcp.  */
-  gcc_assert (node->needed || node->reachable);
-
-  node->local.versionable = tree_versionable_function_p (node->decl);
-  ipa_initialize_node_params (node);
-  ipa_detect_param_modifications (node);
-}
-
 /* Return scale for NODE.  */
 static inline gcov_type
 ipcp_get_node_scale (struct cgraph_node *node)
@@ -611,6 +599,7 @@  ipcp_compute_node_scale (struct cgraph_n
 /* Initialization and computation of IPCP data structures.  This is the initial
    intraprocedural analysis of functions, which gathers information to be
    propagated later on.  */
+
 static void
 ipcp_init_stage (void)
 {
@@ -618,16 +607,13 @@  ipcp_init_stage (void)
 
   for (node = cgraph_nodes; node; node = node->next)
     if (node->analyzed)
-      ipcp_analyze_node (node);
-  for (node = cgraph_nodes; node; node = node->next)
-    {
-      if (!node->analyzed)
-	continue;
-
-      ipa_analyze_params_uses (node);
-      /* building jump functions  */
-      ipa_compute_jump_functions (node);
-    }
+      {
+	/* Unreachable nodes should have been eliminated before ipcp.  */
+	gcc_assert (node->needed || node->reachable);
+
+	node->local.versionable = tree_versionable_function_p (node->decl);
+	ipa_analyze_node (node);
+      }
 }
 
 /* Return true if there are some formal parameters whose value is IPA_TOP (in
Index: icln/gcc/ipa-inline.c
===================================================================
--- icln.orig/gcc/ipa-inline.c	2010-06-24 12:13:10.000000000 +0200
+++ icln/gcc/ipa-inline.c	2010-06-24 23:52:44.000000000 +0200
@@ -2011,12 +2011,8 @@  struct gimple_opt_pass pass_inline_param
 static void
 inline_indirect_intraprocedural_analysis (struct cgraph_node *node)
 {
-  ipa_initialize_node_params (node);
-  ipa_detect_param_modifications (node);
-  ipa_analyze_params_uses (node);
-  ipa_compute_jump_functions (node);
-
-  if (dump_file)
+  ipa_analyze_node (node);
+  if (dump_file && (dump_flags & TDF_DETAILS))
     {
       ipa_print_node_params (dump_file, node);
       ipa_print_node_jump_functions (dump_file, node);