public inbox for gcc-patches@gcc.gnu.org
 help / color / mirror / Atom feed
* [PATCH] Set current_function_decl in {push,pop}_cfun and push_struct_function
@ 2012-08-09 14:27 Martin Jambor
  2012-08-09 14:58 ` Richard Guenther
  2012-08-10 14:58 ` Eric Botcazou
  0 siblings, 2 replies; 14+ messages in thread
From: Martin Jambor @ 2012-08-09 14:27 UTC (permalink / raw)
  To: GCC Patches

Hi,

I've always found it silly that in order to change the current
function one has to call push_cfun and pop_cfun which conveniently set
and restore the value of cfun and in addition to that also set
current_function_decl and usually also cache its old value to restore
it back afterwards.  I also think that, at least throughout the
middle-end, we should strive to have current_function_decl consistent
with cfun->decl.  There are quite a few places where we are not
consistent and I think such situations are prone to nasty surprises as
various functions rely on cfun and others on current_function_decl and
it's easy to be unaware that one of the two is incorrect at the
moment.

This week I have therefore decided to try and make push_cfun, pop_cfun
and push_struct_function also set the current_function_decl.  Being
afraid of opening a giant can of worms I only a mid-sized hole and
left various set_cfuns for later as well as places where we set
current_function_decl without bothering with cfun.  After a few
debugging sessions I came up with the patch below.  The changes are
mostly mechanical, let me try and explain some of the difficult or
not-quite-nice ones, most of which come from calls from front-ends
which generally do not care about cfun all that much.

- In order to ensure that pop_cfun will reliable restore the old
  current_function_decl, push_cfun asserts that cfun and
  current_function_decl match.  pop_cfun then simply restores
  current_function_decl to new_cfun->decl or NULL_TREE if new_cfun is
  NULL.  To check that the two remain consistent, pop_cfun has a
  similar (albeit checking) assert.

- I had to allow push_cfun(NULL) because in
  gfc_get_extern_function_decl in fortran/trans-decl.c we momentarily
  emulate top-level context by doing:

	  current_function_decl = NULL_TREE;
	  push_cfun (cfun);

	  do_something ()

	  pop_cfun ();
	  current_function_decl = save_fn_decl;

  and to keep current_function_decl consistent with cfun, cfun had to
  be made NULL too.  Co I converted the above to push_cfun (NULL)
  which also sets current_function_decl to NULL_TREE.

- I also had to allow push_cfun(NULL) because
  dwarf2out_abstract_function does just that, just it looks like:

  push_cfun (DECL_STRUCT_FUNCTION (decl));

  but DECL_STRUCT_FUNCTION is usually (always?) NULL for abstract
  origin functions.  But this also means that changed push_cfun sets
  current_function_decl to NULL, which means the abstract function is
  not dwarf2outed as it should be.  Thus, in perhaps the most awful
  thunk in this patch I re-set current_function_decl after calling
  push_cfun.  If someone has a better idea how to deal with this, I'm
  certainly interested.

  For the same reason I do not assert that
  current_function matches cfun->decl in pop_cfun if cfun is NULL.

- each cfun change also triggers a pair of init_dummy_function_start
  and expand_dummy_function_end which invoke push_struct_function and
  pop_cfun respectively.  Because we may be in the middle of another
  push/pop_cfun, the current_function_decl may not match and so the
  asserts are disabled in these cases, fortunately we can recognize
  them by looking at value of in_dummy_function.

- ada/gcc-interface/utils.c:rest_of_subprog_body_compilation calls
  dump_function which in turns calls dump_function_to_file which calls
  push_cfun.  But Ada front end has its idea of the
  current_function_decl and there is no cfun which is an inconsistency
  which makes push_cfun assert fail.  I "solved" it by temporarily
  setting current_function_decl to NULL_TREE.  It's just dumping and I
  thought that dump_function should be considered middle-end and thus
  middle-end invariants should apply.

The patch passes bootstrap and testing on x86_64-linux (all languages
+ ada + obj-c++) and ia64-linux (c,c++,fortran,objc,obj-c++).  There
is some confusing jitter in the go testing results which I have not
yet looked at (perhaps compare_tests just can't deal with it, there
are tests reported both as newly failing and newly working etc...) but
I thought that I'd send the patch now anyway to get some feedback in
case I was doing something else wrong (I also do not know whether
anyone but Ian can modify the go front-end).  I have also LTO-built
Mozilla Firefox with the patch.

Well, what do you think?

Martin


2012-08-08  Martin Jambor  <mjambor@suse.cz>

	* function.c (push_cfun): Check old current_function_decl matches
	old cfun, set new current_function_decl to the decl of the new
	cfun.
	(push_struct_function): Likewise.
	(pop_cfun): Likewise.
	(allocate_struct_function): Move call to
	invoke_set_current_function_hook to the end of the function.
	* cfgexpand.c (estimated_stack_frame_size): Do not set and restore
	current_function_decl.
	* cgraph.c (cgraph_release_function_body): Likewise.
	* cgraphunit.c (cgraph_process_new_functions): Likewise.
	(cgraph_add_new_function): Likewise.
	(cgraph_analyze_function): Likewise.
	(assemble_thunk): Set cfun to NULL at the end.
	(expand_function): Move call to set_cfun downwards.
	* dwarf2out.c (dwarf2out_abstract_function): Do not restore
	current_function_decl.
	* gimple-low.c (record_vars_into): Only check current_function_decl
	before possibly doing push_cfun.
	* gimplify.c (gimplify_function_tree): Do not set and restore
	current_function_decl.
	* ipa-inline-analysis.c (compute_inline_parameters): Likewise.
	(inline_analyze_function): Likewise.
	* ipa-prop.c (ipa_analyze_node): Likewise.
	* ipa-pure-const.c (analyze_function): Likewise.
	* lto-streamer-in.c (lto_input_function_body): Do not set
	current_function_decl.
	* lto-streamer-out.c (output_function): Do not set and restore
	current_function_decl.
	* matrix-reorg.c (transform_allocation_sites): Likewise, also use
	push/pop_cfun instead of set_cfun.
	(matrix_reorg): Do not set and restore current_function_decl.
	* omp-low.c (finalize_task_copyfn): Likewise.
	(expand_omp_taskreg): Likewise.
	(create_task_copyfn): Likewise, move push_cfun up quite a bit.
	* passes.c (dump_passes): Do not set and restore current_function_decl.
	(do_per_function): Likewise.
	(do_per_function_toporder): Likewise.
	* trans-mem.c (ipa_tm_scan_irr_function): Likewise.
	(ipa_tm_transform_transaction): Likewise.
	(ipa_tm_transform_clone): Likewise.
	(ipa_tm_execute): Likewise.
	* tree-emutls.c (lower_emutls_function_body): Likewise.
	* tree-inline.c (initialize_cfun): Do not call pop_cfun.
	(tree_function_versioning): Do not call push_cfun, do not set and
	restore current_function_decl.  Remove assert checking consistency of
	cfun and current_function_decl.
	* tree-profile.c (tree_profiling): Do not set and restore
	current_function_decl.
	* tree-sra.c (convert_callers_for_node): Do not set
	current_function_decl.
	(convert_callers): Do not restore current_function_decl.
	(modify_function): Do not set current_function_decl.
	* tree-ssa-structalias.c (ipa_pta_execute): Do not set and restore
	current_function_decl.

	* fortran/trans-decl.c (gfc_get_extern_function_decl): Do not set and
	restore current_function_decl, push NULL cfun.
	(gfc_init_coarray_decl): Do not set and restore current_function_decl.

	* go/gofrontend/gogo-tree.cc (write_initialization_function): Do not
	set and restore current_function_decl.
	(write_globals): Likewise.
	(get_tree): Likewise.

	* lto/lto.c (lto_materialize_function): Call push_struct_function
	instead of allocate_struct_function and also call pop_cfun.

	* ada/gcc-interface/utils.c (rest_of_subprog_body_compilation): Set
	current_function_decl to NULL before calling dump_function and then
	restore it.



*** /tmp/KDyIva_utils.c	Thu Aug  9 15:21:47 2012
--- gcc/ada/gcc-interface/utils.c	Thu Aug  9 13:44:00 2012
*************** end_subprog_body (tree body)
*** 2740,2746 ****
  void
  rest_of_subprog_body_compilation (tree subprog_decl)
  {
!   /* We cannot track the location of errors past this point.  */
    error_gnat_node = Empty;
  
    /* If we're only annotating types, don't actually compile this function.  */
--- 2740,2748 ----
  void
  rest_of_subprog_body_compilation (tree subprog_decl)
  {
!   tree saved_current_function_decl = current_function_decl;
! 
!  /* We cannot track the location of errors past this point.  */
    error_gnat_node = Empty;
  
    /* If we're only annotating types, don't actually compile this function.  */
*************** rest_of_subprog_body_compilation (tree s
*** 2748,2754 ****
--- 2750,2758 ----
      return;
  
    /* Dump functions before gimplification.  */
+   current_function_decl = NULL_TREE;
    dump_function (TDI_original, subprog_decl);
+   current_function_decl = saved_current_function_decl;
  
    if (!decl_function_context (subprog_decl))
      cgraph_finalize_function (subprog_decl, false);
*** /tmp/wurZNc_cfgexpand.c	Thu Aug  9 15:21:47 2012
--- gcc/cfgexpand.c	Tue Aug  7 13:15:12 2012
*************** estimated_stack_frame_size (struct cgrap
*** 1422,1433 ****
    HOST_WIDE_INT size = 0;
    size_t i;
    tree var;
-   tree old_cur_fun_decl = current_function_decl;
    struct function *fn = DECL_STRUCT_FUNCTION (node->symbol.decl);
  
-   current_function_decl = node->symbol.decl;
    push_cfun (fn);
- 
    FOR_EACH_LOCAL_DECL (fn, i, var)
      if (auto_var_in_fn_p (var, fn->decl))
        size += expand_one_var (var, true, false);
--- 1422,1430 ----
*************** estimated_stack_frame_size (struct cgrap
*** 1442,1448 ****
        fini_vars_expansion ();
      }
    pop_cfun ();
-   current_function_decl = old_cur_fun_decl;
    return size;
  }
  
--- 1439,1444 ----
*** /tmp/8XER7b_cgraph.c	Thu Aug  9 15:21:47 2012
--- gcc/cgraph.c	Tue Aug  7 13:17:24 2012
*************** cgraph_release_function_body (struct cgr
*** 1128,1134 ****
  {
    if (DECL_STRUCT_FUNCTION (node->symbol.decl))
      {
-       tree old_decl = current_function_decl;
        push_cfun (DECL_STRUCT_FUNCTION (node->symbol.decl));
        if (cfun->cfg
  	  && current_loops)
--- 1128,1133 ----
*************** cgraph_release_function_body (struct cgr
*** 1138,1148 ****
  	}
        if (cfun->gimple_df)
  	{
- 	  current_function_decl = node->symbol.decl;
  	  delete_tree_ssa ();
  	  delete_tree_cfg_annotations ();
  	  cfun->eh = NULL;
- 	  current_function_decl = old_decl;
  	}
        if (cfun->cfg)
  	{
--- 1137,1145 ----
*** /tmp/WL9Mge_cgraphunit.c	Thu Aug  9 15:21:47 2012
--- gcc/cgraphunit.c	Wed Aug  8 15:54:56 2012
*************** cgraph_process_new_functions (void)
*** 313,319 ****
  	  if (!node->analyzed)
  	    cgraph_analyze_function (node);
  	  push_cfun (DECL_STRUCT_FUNCTION (fndecl));
- 	  current_function_decl = fndecl;
  	  if ((cgraph_state == CGRAPH_STATE_IPA_SSA
  	      && !gimple_in_ssa_p (DECL_STRUCT_FUNCTION (fndecl)))
  	      /* When not optimizing, be sure we run early local passes anyway
--- 313,318 ----
*************** cgraph_process_new_functions (void)
*** 325,331 ****
  	  free_dominance_info (CDI_POST_DOMINATORS);
  	  free_dominance_info (CDI_DOMINATORS);
  	  pop_cfun ();
- 	  current_function_decl = NULL;
            cgraph_call_function_insertion_hooks (node);
  	  break;
  
--- 324,329 ----
*************** cgraph_add_new_function (tree fndecl, bo
*** 495,508 ****
  	if (!lowered && cgraph_state == CGRAPH_STATE_EXPANSION)
  	  {
  	    push_cfun (DECL_STRUCT_FUNCTION (fndecl));
- 	    current_function_decl = fndecl;
  	    gimple_register_cfg_hooks ();
  	    bitmap_obstack_initialize (NULL);
  	    execute_pass_list (all_lowering_passes);
  	    execute_pass_list (pass_early_local_passes.pass.sub);
  	    bitmap_obstack_release (NULL);
  	    pop_cfun ();
- 	    current_function_decl = NULL;
  
  	    lowered = true;
  	  }
--- 493,504 ----
*************** cgraph_add_new_function (tree fndecl, bo
*** 521,527 ****
  	  node->lowered = true;
  	cgraph_analyze_function (node);
  	push_cfun (DECL_STRUCT_FUNCTION (fndecl));
- 	current_function_decl = fndecl;
  	gimple_register_cfg_hooks ();
  	bitmap_obstack_initialize (NULL);
  	if (!gimple_in_ssa_p (DECL_STRUCT_FUNCTION (fndecl)))
--- 517,522 ----
*************** cgraph_add_new_function (tree fndecl, bo
*** 529,535 ****
  	bitmap_obstack_release (NULL);
  	pop_cfun ();
  	expand_function (node);
- 	current_function_decl = NULL;
  	break;
  
        default:
--- 524,529 ----
*************** fixup_same_cpp_alias_visibility (symtab_
*** 597,603 ****
  static void
  cgraph_analyze_function (struct cgraph_node *node)
  {
-   tree save = current_function_decl;
    tree decl = node->symbol.decl;
    location_t saved_loc = input_location;
    input_location = DECL_SOURCE_LOCATION (decl);
--- 591,596 ----
*************** cgraph_analyze_function (struct cgraph_n
*** 638,644 ****
      }
    else
      {
-       current_function_decl = decl;
        push_cfun (DECL_STRUCT_FUNCTION (decl));
  
        assign_assembler_name_if_neeeded (node->symbol.decl);
--- 631,636 ----
*************** cgraph_analyze_function (struct cgraph_n
*** 672,678 ****
      }
    node->analyzed = true;
  
-   current_function_decl = save;
    input_location = saved_loc;
  }
  
--- 664,669 ----
*************** assemble_thunk (struct cgraph_node *node
*** 1520,1525 ****
--- 1511,1517 ----
        bitmap_obstack_release (NULL);
      }
    current_function_decl = NULL;
+   set_cfun (NULL);
  }
  
  
*************** expand_function (struct cgraph_node *nod
*** 1612,1619 ****
    /* Release the default bitmap obstack.  */
    bitmap_obstack_release (NULL);
  
-   set_cfun (NULL);
- 
    /* If requested, warn about function definitions where the function will
       return a value (usually of some struct or union type) which itself will
       take up a lot of stack space.  */
--- 1604,1609 ----
*************** expand_function (struct cgraph_node *nod
*** 1658,1663 ****
--- 1648,1654 ----
  
    /* Make sure that BE didn't give up on compiling.  */
    gcc_assert (TREE_ASM_WRITTEN (decl));
+   set_cfun (NULL);
    current_function_decl = NULL;
  
    /* It would make a lot more sense to output thunks before function body to get more
*** /tmp/edrpua_dwarf2out.c	Thu Aug  9 15:21:47 2012
--- gcc/dwarf2out.c	Wed Aug  8 18:12:07 2012
*************** static void
*** 16673,16679 ****
  dwarf2out_abstract_function (tree decl)
  {
    dw_die_ref old_die;
-   tree save_fn;
    tree context;
    int was_abstract;
    htab_t old_decl_loc_table;
--- 16673,16678 ----
*************** dwarf2out_abstract_function (tree decl)
*** 16714,16736 ****
      }
  
    /* Pretend we've just finished compiling this function.  */
-   save_fn = current_function_decl;
-   current_function_decl = decl;
    push_cfun (DECL_STRUCT_FUNCTION (decl));
! 
    was_abstract = DECL_ABSTRACT (decl);
    set_decl_abstract_flags (decl, 1);
    dwarf2out_decl (decl);
    if (! was_abstract)
      set_decl_abstract_flags (decl, 0);
  
!   current_function_decl = save_fn;
    decl_loc_table = old_decl_loc_table;
    cached_dw_loc_list_table = old_cached_dw_loc_list_table;
    call_arg_locations = old_call_arg_locations;
    call_site_count = old_call_site_count;
    tail_call_site_count = old_tail_call_site_count;
-   pop_cfun ();
  }
  
  /* Helper function of premark_used_types() which gets called through
--- 16713,16735 ----
      }
  
    /* Pretend we've just finished compiling this function.  */
    push_cfun (DECL_STRUCT_FUNCTION (decl));
!   /* DECL_STRUCT_FUNCTION can be NULL and in that case push_cfun has set
!      current_function_decl to NULL which is not what we want.  Re-set it
!      again.  */
!   current_function_decl = decl;
    was_abstract = DECL_ABSTRACT (decl);
    set_decl_abstract_flags (decl, 1);
    dwarf2out_decl (decl);
    if (! was_abstract)
      set_decl_abstract_flags (decl, 0);
  
!   pop_cfun ();
    decl_loc_table = old_decl_loc_table;
    cached_dw_loc_list_table = old_cached_dw_loc_list_table;
    call_arg_locations = old_call_arg_locations;
    call_site_count = old_call_site_count;
    tail_call_site_count = old_tail_call_site_count;
  }
  
  /* Helper function of premark_used_types() which gets called through
*** /tmp/yrx7vc_trans-decl.c	Thu Aug  9 15:21:47 2012
--- gcc/fortran/trans-decl.c	Tue Aug  7 16:02:30 2012
*************** gfc_get_extern_function_decl (gfc_symbol
*** 1624,1640 ****
  	  /* By construction, the external function cannot be
  	     a contained procedure.  */
  	  locus old_loc;
- 	  tree save_fn_decl = current_function_decl;
  
- 	  current_function_decl = NULL_TREE;
  	  gfc_save_backend_locus (&old_loc);
! 	  push_cfun (cfun);
  
  	  gfc_create_function_decl (gsym->ns, true);
  
  	  pop_cfun ();
  	  gfc_restore_backend_locus (&old_loc);
- 	  current_function_decl = save_fn_decl;
  	}
  
        /* If the namespace has entries, the proc_name is the
--- 1624,1637 ----
  	  /* By construction, the external function cannot be
  	     a contained procedure.  */
  	  locus old_loc;
  
  	  gfc_save_backend_locus (&old_loc);
! 	  push_cfun (NULL);
  
  	  gfc_create_function_decl (gsym->ns, true);
  
  	  pop_cfun ();
  	  gfc_restore_backend_locus (&old_loc);
  	}
  
        /* If the namespace has entries, the proc_name is the
*************** add_argument_checking (stmtblock_t *bloc
*** 4849,4864 ****
  void
  gfc_init_coarray_decl (bool main_tu)
  {
-   tree save_fn_decl;
- 
    if (gfc_option.coarray != GFC_FCOARRAY_LIB)
      return;
  
    if (gfort_gvar_caf_this_image || gfort_gvar_caf_num_images)
      return;
  
-   save_fn_decl = current_function_decl;
-   current_function_decl = NULL_TREE;
    push_cfun (cfun);
  
    gfort_gvar_caf_this_image
--- 4846,4857 ----
*************** gfc_init_coarray_decl (bool main_tu)
*** 4894,4900 ****
    pushdecl_top_level (gfort_gvar_caf_num_images);
  
    pop_cfun ();
-   current_function_decl = save_fn_decl;
  }
  
  
--- 4887,4892 ----
*** /tmp/ccrTha_function.c	Thu Aug  9 15:21:47 2012
--- gcc/function.c	Wed Aug  8 18:06:40 2012
*************** set_cfun (struct function *new_cfun)
*** 4413,4434 ****
  
  static VEC(function_p,heap) *cfun_stack;
  
! /* Push the current cfun onto the stack, and set cfun to new_cfun.  */
  
  void
  push_cfun (struct function *new_cfun)
  {
    VEC_safe_push (function_p, heap, cfun_stack, cfun);
    set_cfun (new_cfun);
  }
  
! /* Pop cfun from the stack.  */
  
  void
  pop_cfun (void)
  {
    struct function *new_cfun = VEC_pop (function_p, cfun_stack);
    set_cfun (new_cfun);
  }
  
  /* Return value of funcdef and increase it.  */
--- 4413,4445 ----
  
  static VEC(function_p,heap) *cfun_stack;
  
! /* Push the current cfun onto the stack, and set cfun to new_cfun.  Also set
!    current_function_decl accordingly.  */
  
  void
  push_cfun (struct function *new_cfun)
  {
+   gcc_assert ((!cfun && !current_function_decl)
+ 	      || (cfun && current_function_decl == cfun->decl));
    VEC_safe_push (function_p, heap, cfun_stack, cfun);
+   current_function_decl = new_cfun ? new_cfun->decl : NULL_TREE;
    set_cfun (new_cfun);
  }
  
! /* Pop cfun from the stack.  Also set current_function_decl accordingly.  */
  
  void
  pop_cfun (void)
  {
    struct function *new_cfun = VEC_pop (function_p, cfun_stack);
+   /* When in_dummy_function, we do have a cfun but current_function_decl is
+      NULL.  OTOH, dwarf2out can push a function of an abstract origin decl
+      which is NULL but needs non-null current_function_decl.  */
+   gcc_checking_assert (in_dummy_function
+ 		       || !cfun
+ 		       || current_function_decl == cfun->decl);
    set_cfun (new_cfun);
+   current_function_decl = new_cfun ? new_cfun->decl : NULL_TREE;
  }
  
  /* Return value of funcdef and increase it.  */
*************** allocate_struct_function (tree fndecl, b
*** 4475,4482 ****
    OVERRIDE_ABI_FORMAT (fndecl);
  #endif
  
-   invoke_set_current_function_hook (fndecl);
- 
    if (fndecl != NULL_TREE)
      {
        DECL_STRUCT_FUNCTION (fndecl) = cfun;
--- 4486,4491 ----
*************** allocate_struct_function (tree fndecl, b
*** 4502,4507 ****
--- 4511,4518 ----
           but is this worth the hassle?  */
        cfun->can_throw_non_call_exceptions = flag_non_call_exceptions;
      }
+ 
+   invoke_set_current_function_hook (fndecl);
  }
  
  /* This is like allocate_struct_function, but pushes a new cfun for FNDECL
*************** allocate_struct_function (tree fndecl, b
*** 4510,4516 ****
--- 4521,4533 ----
  void
  push_struct_function (tree fndecl)
  {
+   /* When in_dummy_function we might be in the middle of a pop_cfun and
+      current_function_decl and cfun may not match.  */
+   gcc_assert (in_dummy_function
+ 	      || (!cfun && !current_function_decl)
+ 	      || (cfun && current_function_decl == cfun->decl));
    VEC_safe_push (function_p, heap, cfun_stack, cfun);
+   current_function_decl = fndecl;
    allocate_struct_function (fndecl, false);
  }
  
*** /tmp/apOtwc_gimple-low.c	Thu Aug  9 15:21:47 2012
--- gcc/gimple-low.c	Tue Aug  7 13:31:20 2012
*************** lower_builtin_setjmp (gimple_stmt_iterat
*** 991,997 ****
  void
  record_vars_into (tree vars, tree fn)
  {
!   if (fn != current_function_decl)
      push_cfun (DECL_STRUCT_FUNCTION (fn));
  
    for (; vars; vars = DECL_CHAIN (vars))
--- 991,999 ----
  void
  record_vars_into (tree vars, tree fn)
  {
!   bool change_cfun = fn != current_function_decl;
! 
!   if (change_cfun)
      push_cfun (DECL_STRUCT_FUNCTION (fn));
  
    for (; vars; vars = DECL_CHAIN (vars))
*************** record_vars_into (tree vars, tree fn)
*** 1011,1017 ****
        add_local_decl (cfun, var);
      }
  
!   if (fn != current_function_decl)
      pop_cfun ();
  }
  
--- 1013,1019 ----
        add_local_decl (cfun, var);
      }
  
!   if (change_cfun)
      pop_cfun ();
  }
  
*** /tmp/uvszca_gimplify.c	Thu Aug  9 15:21:47 2012
--- gcc/gimplify.c	Tue Aug  7 13:33:19 2012
*************** flag_instrument_functions_exclude_p (tre
*** 8258,8271 ****
  void
  gimplify_function_tree (tree fndecl)
  {
!   tree oldfn, parm, ret;
    gimple_seq seq;
    gimple bind;
  
    gcc_assert (!gimple_body (fndecl));
  
-   oldfn = current_function_decl;
-   current_function_decl = fndecl;
    if (DECL_STRUCT_FUNCTION (fndecl))
      push_cfun (DECL_STRUCT_FUNCTION (fndecl));
    else
--- 8258,8269 ----
  void
  gimplify_function_tree (tree fndecl)
  {
!   tree parm, ret;
    gimple_seq seq;
    gimple bind;
  
    gcc_assert (!gimple_body (fndecl));
  
    if (DECL_STRUCT_FUNCTION (fndecl))
      push_cfun (DECL_STRUCT_FUNCTION (fndecl));
    else
*************** gimplify_function_tree (tree fndecl)
*** 8350,8356 ****
    DECL_SAVED_TREE (fndecl) = NULL_TREE;
    cfun->curr_properties = PROP_gimple_any;
  
-   current_function_decl = oldfn;
    pop_cfun ();
  }
  
--- 8348,8353 ----
*** /tmp/gISRxc_gogo-tree.cc	Thu Aug  9 15:21:47 2012
--- gcc/go/gofrontend/gogo-tree.cc	Tue Aug  7 16:13:51 2012
*************** Gogo::write_initialization_function(tree
*** 483,489 ****
  
    DECL_SAVED_TREE(fndecl) = init_stmt_list;
  
-   current_function_decl = fndecl;
    if (DECL_STRUCT_FUNCTION(fndecl) == NULL)
      push_struct_function(fndecl);
    else
--- 483,488 ----
*************** Gogo::write_initialization_function(tree
*** 494,500 ****
  
    cgraph_add_new_function(fndecl, false);
  
-   current_function_decl = NULL_TREE;
    pop_cfun();
  }
  
--- 493,498 ----
*************** Gogo::write_globals()
*** 871,877 ****
  	      // means that we need an fndecl.
  	      if (init_fndecl == NULL_TREE)
  		init_fndecl = this->initialization_function_decl();
- 	      current_function_decl = init_fndecl;
  	      if (DECL_STRUCT_FUNCTION(init_fndecl) == NULL)
  		push_struct_function(init_fndecl);
  	      else
--- 869,874 ----
*************** Gogo::write_globals()
*** 881,887 ****
  	      var_init_tree = no->var_value()->get_init_block(this, NULL,
  							      var_decl);
  
- 	      current_function_decl = NULL_TREE;
  	      pop_cfun();
  	    }
  
--- 878,883 ----
*************** Named_object::get_tree(Gogo* gogo, Named
*** 1123,1137 ****
  		cfun->function_end_locus =
                    func->block()->end_location().gcc_location();
  
- 		current_function_decl = decl;
- 
  		func->build_tree(gogo, this);
  
  		gimplify_function_tree(decl);
  
  		cgraph_finalize_function(decl, true);
  
- 		current_function_decl = NULL_TREE;
  		pop_cfun();
  	      }
  	  }
--- 1119,1130 ----
*** /tmp/2SvTGa_ipa-inline-analysis.c	Thu Aug  9 15:21:47 2012
--- gcc/ipa-inline-analysis.c	Tue Aug  7 13:35:39 2012
*************** compute_inline_parameters (struct cgraph
*** 2068,2074 ****
    HOST_WIDE_INT self_stack_size;
    struct cgraph_edge *e;
    struct inline_summary *info;
-   tree old_decl = current_function_decl;
  
    gcc_assert (!node->global.inlined_to);
  
--- 2068,2073 ----
*************** compute_inline_parameters (struct cgraph
*** 2095,2101 ****
      }
  
    /* Even is_gimple_min_invariant rely on current_function_decl.  */
-   current_function_decl = node->symbol.decl;
    push_cfun (DECL_STRUCT_FUNCTION (node->symbol.decl));
  
    /* Estimate the stack size for the function if we're optimizing.  */
--- 2094,2099 ----
*************** compute_inline_parameters (struct cgraph
*** 2137,2143 ****
    info->size = info->self_size;
    info->stack_frame_offset = 0;
    info->estimated_stack_size = info->estimated_self_stack_size;
-   current_function_decl = old_decl;
    pop_cfun ();
  }
  
--- 2135,2140 ----
*************** static void
*** 2924,2930 ****
  inline_analyze_function (struct cgraph_node *node)
  {
    push_cfun (DECL_STRUCT_FUNCTION (node->symbol.decl));
-   current_function_decl = node->symbol.decl;
  
    if (dump_file)
      fprintf (dump_file, "\nAnalyzing function: %s/%u\n",
--- 2921,2926 ----
*************** inline_analyze_function (struct cgraph_n
*** 2933,2939 ****
      inline_indirect_intraprocedural_analysis (node);
    compute_inline_parameters (node, false);
  
-   current_function_decl = NULL;
    pop_cfun ();
  }
  
--- 2929,2934 ----
*** /tmp/6WwhXc_ipa-prop.c	Thu Aug  9 15:21:47 2012
--- gcc/ipa-prop.c	Tue Aug  7 13:36:13 2012
*************** ipa_analyze_node (struct cgraph_node *no
*** 1674,1680 ****
    ipa_check_create_edge_args ();
    info = IPA_NODE_REF (node);
    push_cfun (DECL_STRUCT_FUNCTION (node->symbol.decl));
-   current_function_decl = node->symbol.decl;
    ipa_initialize_node_params (node);
  
    param_count = ipa_get_param_count (info);
--- 1674,1679 ----
*************** ipa_analyze_node (struct cgraph_node *no
*** 1688,1694 ****
      if (parms_ainfo[i].visited_statements)
        BITMAP_FREE (parms_ainfo[i].visited_statements);
  
-   current_function_decl = NULL;
    pop_cfun ();
  }
  
--- 1687,1692 ----
*** /tmp/QSIQac_ipa-pure-const.c	Thu Aug  9 15:21:47 2012
--- gcc/ipa-pure-const.c	Tue Aug  7 13:37:57 2012
*************** static funct_state
*** 724,730 ****
  analyze_function (struct cgraph_node *fn, bool ipa)
  {
    tree decl = fn->symbol.decl;
-   tree old_decl = current_function_decl;
    funct_state l;
    basic_block this_block;
  
--- 724,729 ----
*************** analyze_function (struct cgraph_node *fn
*** 752,758 ****
      }
  
    push_cfun (DECL_STRUCT_FUNCTION (decl));
-   current_function_decl = decl;
  
    FOR_EACH_BB (this_block)
      {
--- 751,756 ----
*************** end:
*** 820,826 ****
      l->can_throw = false;
  
    pop_cfun ();
-   current_function_decl = old_decl;
    if (dump_file)
      {
        if (l->looping)
--- 818,823 ----
*** /tmp/mNj9je_lto-streamer-in.c	Thu Aug  9 15:21:47 2012
--- gcc/lto-streamer-in.c	Tue Aug  7 13:44:16 2012
*************** void
*** 1036,1042 ****
  lto_input_function_body (struct lto_file_decl_data *file_data,
  			 tree fn_decl, const char *data)
  {
-   current_function_decl = fn_decl;
    lto_read_body (file_data, fn_decl, data, LTO_section_function_body);
  }
  
--- 1036,1041 ----
*** /tmp/Mmj3jc_lto-streamer-out.c	Thu Aug  9 15:21:47 2012
--- gcc/lto-streamer-out.c	Tue Aug  7 13:46:04 2012
*************** output_function (struct cgraph_node *nod
*** 793,799 ****
    gcc_assert (current_function_decl == NULL_TREE && cfun == NULL);
  
    /* Set current_function_decl and cfun.  */
-   current_function_decl = function;
    push_cfun (fn);
  
    /* Make string 0 be a NULL string.  */
--- 793,798 ----
*************** output_function (struct cgraph_node *nod
*** 847,853 ****
  
    destroy_output_block (ob);
  
-   current_function_decl = NULL;
    pop_cfun ();
  }
  
--- 846,851 ----
*** /tmp/iXBLWd_lto.c	Thu Aug  9 15:21:47 2012
--- gcc/lto/lto.c	Wed Aug  8 12:14:32 2012
*************** lto_materialize_function (struct cgraph_
*** 221,227 ****
  
  	  gcc_assert (DECL_STRUCT_FUNCTION (decl) == NULL);
  
! 	  allocate_struct_function (decl, false);
  	  announce_function (decl);
  	  lto_input_function_body (file_data, decl, data);
  	  if (DECL_FUNCTION_PERSONALITY (decl) && !first_personality_decl)
--- 221,227 ----
  
  	  gcc_assert (DECL_STRUCT_FUNCTION (decl) == NULL);
  
! 	  push_struct_function (decl);
  	  announce_function (decl);
  	  lto_input_function_body (file_data, decl, data);
  	  if (DECL_FUNCTION_PERSONALITY (decl) && !first_personality_decl)
*************** lto_materialize_function (struct cgraph_
*** 229,234 ****
--- 229,235 ----
  	  lto_stats.num_function_bodies++;
  	  lto_free_section_data (file_data, LTO_section_function_body, name,
  				 data, len);
+ 	  pop_cfun ();
  	  ggc_collect ();
  	}
      }
*** /tmp/mJnAqb_matrix-reorg.c	Thu Aug  9 15:21:47 2012
--- gcc/matrix-reorg.c	Tue Aug  7 13:50:23 2012
*************** transform_allocation_sites (void **slot,
*** 1985,1991 ****
  {
    int i;
    struct matrix_info *mi;
!   tree type, oldfn, prev_dim_size;
    gimple call_stmt_0, use_stmt;
    struct cgraph_node *c_node;
    struct cgraph_edge *e;
--- 1985,1991 ----
  {
    int i;
    struct matrix_info *mi;
!   tree type, prev_dim_size;
    gimple call_stmt_0, use_stmt;
    struct cgraph_node *c_node;
    struct cgraph_edge *e;
*************** transform_allocation_sites (void **slot,
*** 2102,2109 ****
       We add the assignment to the global before the malloc of level 0.  */
  
    /* To be able to produce gimple temporaries.  */
-   oldfn = current_function_decl;
-   current_function_decl = mi->allocation_function_decl;
    push_cfun (DECL_STRUCT_FUNCTION (mi->allocation_function_decl));
  
    /* Set the dimension sizes as follows:
--- 2102,2107 ----
*************** transform_allocation_sites (void **slot,
*** 2213,2225 ****
        e = cgraph_edge (c_node, mi->free_stmts[i].stmt);
        gcc_assert (e);
        cgraph_remove_edge (e);
!       current_function_decl = mi->free_stmts[i].func;
!       set_cfun (DECL_STRUCT_FUNCTION (mi->free_stmts[i].func));
        gsi = gsi_for_stmt (mi->free_stmts[i].stmt);
        gsi_remove (&gsi, true);
      }
    /* Return to the previous situation.  */
-   current_function_decl = oldfn;
    pop_cfun ();
    return 1;
  
--- 2211,2222 ----
        e = cgraph_edge (c_node, mi->free_stmts[i].stmt);
        gcc_assert (e);
        cgraph_remove_edge (e);
!       push_cfun (DECL_STRUCT_FUNCTION (mi->free_stmts[i].func));
        gsi = gsi_for_stmt (mi->free_stmts[i].stmt);
        gsi_remove (&gsi, true);
+       pop_cfun ();
      }
    /* Return to the previous situation.  */
    pop_cfun ();
    return 1;
  
*************** matrix_reorg (void)
*** 2265,2274 ****
    /* Analyze the accesses of the matrices (escaping analysis).  */
    FOR_EACH_DEFINED_FUNCTION (node)
      {
-       tree temp_fn;
- 
-       temp_fn = current_function_decl;
-       current_function_decl = node->symbol.decl;
        push_cfun (DECL_STRUCT_FUNCTION (node->symbol.decl));
        bitmap_obstack_initialize (NULL);
        gimple_register_cfg_hooks ();
--- 2262,2267 ----
*************** matrix_reorg (void)
*** 2278,2284 ****
  	  free_dominance_info (CDI_DOMINATORS);
  	  free_dominance_info (CDI_POST_DOMINATORS);
  	  pop_cfun ();
- 	  current_function_decl = temp_fn;
  	  bitmap_obstack_release (NULL);
  
  	  return 0;
--- 2271,2276 ----
*************** matrix_reorg (void)
*** 2293,2299 ****
  	  free_dominance_info (CDI_DOMINATORS);
  	  free_dominance_info (CDI_POST_DOMINATORS);
  	  pop_cfun ();
- 	  current_function_decl = temp_fn;
  	  bitmap_obstack_release (NULL);
  
  	  return 0;
--- 2285,2290 ----
*************** matrix_reorg (void)
*** 2324,2330 ****
        free_dominance_info (CDI_DOMINATORS);
        free_dominance_info (CDI_POST_DOMINATORS);
        pop_cfun ();
-       current_function_decl = temp_fn;
        bitmap_obstack_release (NULL);
      }
    htab_traverse (matrices_to_reorg, transform_allocation_sites, NULL);
--- 2315,2320 ----
*************** matrix_reorg (void)
*** 2332,2341 ****
    FOR_EACH_DEFINED_FUNCTION (node)
      {
        /* Remember that allocation sites have been handled.  */
-       tree temp_fn;
- 
-       temp_fn = current_function_decl;
-       current_function_decl = node->symbol.decl;
        push_cfun (DECL_STRUCT_FUNCTION (node->symbol.decl));
        bitmap_obstack_initialize (NULL);
        gimple_register_cfg_hooks ();
--- 2322,2327 ----
*************** matrix_reorg (void)
*** 2345,2351 ****
        free_dominance_info (CDI_DOMINATORS);
        free_dominance_info (CDI_POST_DOMINATORS);
        pop_cfun ();
-       current_function_decl = temp_fn;
        bitmap_obstack_release (NULL);
      }
    htab_traverse (matrices_to_reorg, dump_matrix_reorg_analysis, NULL);
--- 2331,2336 ----
*** /tmp/EQo3Md_omp-low.c	Thu Aug  9 15:21:47 2012
--- gcc/omp-low.c	Tue Aug  7 13:54:21 2012
*************** static void
*** 1243,1249 ****
  finalize_task_copyfn (gimple task_stmt)
  {
    struct function *child_cfun;
!   tree child_fn, old_fn;
    gimple_seq seq = NULL, new_seq;
    gimple bind;
  
--- 1243,1249 ----
  finalize_task_copyfn (gimple task_stmt)
  {
    struct function *child_cfun;
!   tree child_fn;
    gimple_seq seq = NULL, new_seq;
    gimple bind;
  
*************** finalize_task_copyfn (gimple task_stmt)
*** 1257,1265 ****
    DECL_STRUCT_FUNCTION (child_fn)->curr_properties
      = cfun->curr_properties & ~PROP_loops;
  
-   old_fn = current_function_decl;
    push_cfun (child_cfun);
-   current_function_decl = child_fn;
    bind = gimplify_body (child_fn, false);
    gimple_seq_add_stmt (&seq, bind);
    new_seq = maybe_catch_exception (seq);
--- 1257,1263 ----
*************** finalize_task_copyfn (gimple task_stmt)
*** 1271,1277 ****
      }
    gimple_set_body (child_fn, seq);
    pop_cfun ();
-   current_function_decl = old_fn;
  
    cgraph_add_new_function (child_fn, false);
  }
--- 1269,1274 ----
*************** expand_omp_taskreg (struct omp_region *r
*** 3389,3395 ****
    basic_block entry_bb, exit_bb, new_bb;
    struct function *child_cfun;
    tree child_fn, block, t;
-   tree save_current;
    gimple_stmt_iterator gsi;
    gimple entry_stmt, stmt;
    edge e;
--- 3386,3391 ----
*************** expand_omp_taskreg (struct omp_region *r
*** 3589,3596 ****
        /* Fix the callgraph edges for child_cfun.  Those for cfun will be
  	 fixed in a following pass.  */
        push_cfun (child_cfun);
-       save_current = current_function_decl;
-       current_function_decl = child_fn;
        if (optimize)
  	optimize_omp_library_calls (entry_stmt);
        rebuild_cgraph_edges ();
--- 3585,3590 ----
*************** expand_omp_taskreg (struct omp_region *r
*** 3611,3617 ****
  	}
        if (gimple_in_ssa_p (cfun))
  	update_ssa (TODO_update_ssa);
-       current_function_decl = save_current;
        pop_cfun ();
      }
  
--- 3605,3610 ----
*************** create_task_copyfn (gimple task_stmt, om
*** 6460,6466 ****
  
    /* Populate the function.  */
    push_gimplify_context (&gctx);
!   current_function_decl = child_fn;
  
    bind = build3 (BIND_EXPR, void_type_node, NULL, NULL, NULL);
    TREE_SIDE_EFFECTS (bind) = 1;
--- 6453,6459 ----
  
    /* Populate the function.  */
    push_gimplify_context (&gctx);
!   push_cfun (child_cfun);
  
    bind = build3 (BIND_EXPR, void_type_node, NULL, NULL, NULL);
    TREE_SIDE_EFFECTS (bind) = 1;
*************** create_task_copyfn (gimple task_stmt, om
*** 6507,6514 ****
    else
      tcctx.cb.decl_map = NULL;
  
-   push_cfun (child_cfun);
- 
    arg = DECL_ARGUMENTS (child_fn);
    TREE_TYPE (arg) = build_pointer_type (record_type);
    sarg = DECL_CHAIN (arg);
--- 6500,6505 ----
*************** create_task_copyfn (gimple task_stmt, om
*** 6666,6672 ****
    pop_gimplify_context (NULL);
    BIND_EXPR_BODY (bind) = list;
    pop_cfun ();
!   current_function_decl = ctx->cb.src_fn;
  }
  
  /* Lower the OpenMP parallel or task directive in the current statement
--- 6657,6664 ----
    pop_gimplify_context (NULL);
    BIND_EXPR_BODY (bind) = list;
    pop_cfun ();
!   /* !!! Remove after testing.  */
!   gcc_assert (current_function_decl == ctx->cb.src_fn);
  }
  
  /* Lower the OpenMP parallel or task directive in the current statement
*** /tmp/qpEqgc_passes.c	Thu Aug  9 15:21:47 2012
--- gcc/passes.c	Tue Aug  7 13:56:40 2012
*************** void
*** 679,685 ****
  dump_passes (void)
  {
    struct cgraph_node *n, *node = NULL;
-   tree save_fndecl = current_function_decl;
  
    create_pass_tab();
  
--- 679,684 ----
*************** dump_passes (void)
*** 694,700 ****
      return;
  
    push_cfun (DECL_STRUCT_FUNCTION (node->symbol.decl));
-   current_function_decl = node->symbol.decl;
  
    dump_pass_list (all_lowering_passes, 1);
    dump_pass_list (all_small_ipa_passes, 1);
--- 693,698 ----
*************** dump_passes (void)
*** 704,710 ****
    dump_pass_list (all_passes, 1);
  
    pop_cfun ();
-   current_function_decl = save_fndecl;
  }
  
  
--- 702,707 ----
*************** do_per_function (void (*callback) (void
*** 1651,1664 ****
  	    && (!node->clone_of || node->symbol.decl != node->clone_of->symbol.decl))
  	  {
  	    push_cfun (DECL_STRUCT_FUNCTION (node->symbol.decl));
- 	    current_function_decl = node->symbol.decl;
  	    callback (data);
  	    if (!flag_wpa)
  	      {
  	        free_dominance_info (CDI_DOMINATORS);
  	        free_dominance_info (CDI_POST_DOMINATORS);
  	      }
- 	    current_function_decl = NULL;
  	    pop_cfun ();
  	    ggc_collect ();
  	  }
--- 1648,1659 ----
*************** do_per_function_toporder (void (*callbac
*** 1699,1709 ****
  	  if (cgraph_function_with_gimple_body_p (node))
  	    {
  	      push_cfun (DECL_STRUCT_FUNCTION (node->symbol.decl));
- 	      current_function_decl = node->symbol.decl;
  	      callback (data);
  	      free_dominance_info (CDI_DOMINATORS);
  	      free_dominance_info (CDI_POST_DOMINATORS);
- 	      current_function_decl = NULL;
  	      pop_cfun ();
  	      ggc_collect ();
  	    }
--- 1694,1702 ----
*** /tmp/GR8iVd_trans-mem.c	Thu Aug  9 15:21:47 2012
--- gcc/trans-mem.c	Tue Aug  7 13:59:14 2012
*************** ipa_tm_scan_irr_function (struct cgraph_
*** 3980,3986 ****
        || DECL_STRUCT_FUNCTION (node->symbol.decl)->cfg == NULL)
      return false;
  
-   current_function_decl = node->symbol.decl;
    push_cfun (DECL_STRUCT_FUNCTION (node->symbol.decl));
    calculate_dominance_info (CDI_DOMINATORS);
  
--- 3980,3985 ----
*************** ipa_tm_scan_irr_function (struct cgraph_
*** 4052,4058 ****
  
    VEC_free (basic_block, heap, queue);
    pop_cfun ();
-   current_function_decl = NULL;
  
    return ret;
  }
--- 4051,4056 ----
*************** ipa_tm_transform_transaction (struct cgr
*** 4690,4696 ****
  
    d = get_cg_data (&node, true);
  
-   current_function_decl = node->symbol.decl;
    push_cfun (DECL_STRUCT_FUNCTION (node->symbol.decl));
    calculate_dominance_info (CDI_DOMINATORS);
  
--- 4688,4693 ----
*************** ipa_tm_transform_transaction (struct cgr
*** 4715,4721 ****
      update_ssa (TODO_update_ssa_only_virtuals);
  
    pop_cfun ();
-   current_function_decl = NULL;
  }
  
  /* Transform the calls within the transactional clone of NODE.  */
--- 4712,4717 ----
*************** ipa_tm_transform_clone (struct cgraph_no
*** 4734,4741 ****
    if (!node->callees && !node->indirect_calls && !d->irrevocable_blocks_clone)
      return;
  
!   current_function_decl = d->clone->symbol.decl;
!   push_cfun (DECL_STRUCT_FUNCTION (current_function_decl));
    calculate_dominance_info (CDI_DOMINATORS);
  
    need_ssa_rename =
--- 4730,4736 ----
    if (!node->callees && !node->indirect_calls && !d->irrevocable_blocks_clone)
      return;
  
!   push_cfun (DECL_STRUCT_FUNCTION (d->clone->symbol.decl));
    calculate_dominance_info (CDI_DOMINATORS);
  
    need_ssa_rename =
*************** ipa_tm_transform_clone (struct cgraph_no
*** 4746,4752 ****
      update_ssa (TODO_update_ssa_only_virtuals);
  
    pop_cfun ();
-   current_function_decl = NULL;
  }
  
  /* Main entry point for the transactional memory IPA pass.  */
--- 4741,4746 ----
*************** ipa_tm_execute (void)
*** 4793,4799 ****
  	    continue;
  	  }
  
- 	current_function_decl = node->symbol.decl;
  	push_cfun (DECL_STRUCT_FUNCTION (node->symbol.decl));
  	calculate_dominance_info (CDI_DOMINATORS);
  
--- 4787,4792 ----
*************** ipa_tm_execute (void)
*** 4813,4819 ****
  	  }
  
  	pop_cfun ();
- 	current_function_decl = NULL;
        }
  
    /* For every local function on the callee list, scan as if we will be
--- 4806,4811 ----
*** /tmp/wwqagc_tree-emutls.c	Thu Aug  9 15:21:47 2012
--- gcc/tree-emutls.c	Tue Aug  7 14:48:01 2012
*************** lower_emutls_function_body (struct cgrap
*** 618,624 ****
    struct lower_emutls_data d;
    bool any_edge_inserts = false;
  
-   current_function_decl = node->symbol.decl;
    push_cfun (DECL_STRUCT_FUNCTION (node->symbol.decl));
  
    d.cfun_node = node;
--- 618,623 ----
*************** lower_emutls_function_body (struct cgrap
*** 689,695 ****
      gsi_commit_edge_inserts ();
  
    pop_cfun ();
-   current_function_decl = NULL;
  }
  
  /* Create emutls variable for VAR, DATA is pointer to static
--- 688,693 ----
*** /tmp/C7R3Td_tree-inline.c	Thu Aug  9 15:21:47 2012
--- gcc/tree-inline.c	Tue Aug  7 14:56:44 2012
*************** remap_decl_1 (tree decl, void *data)
*** 1998,2004 ****
  }
  
  /* Build struct function and associated datastructures for the new clone
!    NEW_FNDECL to be build.  CALLEE_FNDECL is the original */
  
  static void
  initialize_cfun (tree new_fndecl, tree callee_fndecl, gcov_type count)
--- 1998,2005 ----
  }
  
  /* Build struct function and associated datastructures for the new clone
!    NEW_FNDECL to be build.  CALLEE_FNDECL is the original.  Function changes
!    the cfun to the function of new_fndecl (and current_function_decl too).  */
  
  static void
  initialize_cfun (tree new_fndecl, tree callee_fndecl, gcov_type count)
*************** initialize_cfun (tree new_fndecl, tree c
*** 2063,2069 ****
        cfun->gimple_df->in_ssa_p = true;
        init_ssa_operands (cfun);
      }
-   pop_cfun ();
  }
  
  /* Helper function for copy_cfg_body.  Move debug stmts from the end
--- 2064,2069 ----
*************** tree_function_versioning (tree old_decl,
*** 5002,5009 ****
    struct ipa_replace_map *replace_info;
    basic_block old_entry_block, bb;
    VEC (gimple, heap) *init_stmts = VEC_alloc (gimple, heap, 10);
- 
-   tree old_current_function_decl = current_function_decl;
    tree vars = NULL_TREE;
  
    gcc_assert (TREE_CODE (old_decl) == FUNCTION_DECL
--- 5002,5007 ----
*************** tree_function_versioning (tree old_decl,
*** 5073,5086 ****
    id.transform_return_to_modify = false;
    id.transform_lang_insert_block = NULL;
  
-   current_function_decl = new_decl;
    old_entry_block = ENTRY_BLOCK_PTR_FOR_FUNCTION
      (DECL_STRUCT_FUNCTION (old_decl));
    initialize_cfun (new_decl, old_decl,
  		   old_entry_block->count);
    DECL_STRUCT_FUNCTION (new_decl)->gimple_df->ipa_pta
      = id.src_cfun->gimple_df->ipa_pta;
-   push_cfun (DECL_STRUCT_FUNCTION (new_decl));
  
    /* Copy the function's static chain.  */
    p = DECL_STRUCT_FUNCTION (old_decl)->static_chain_decl;
--- 5071,5082 ----
*************** tree_function_versioning (tree old_decl,
*** 5234,5242 ****
    gcc_assert (!id.debug_stmts);
    VEC_free (gimple, heap, init_stmts);
    pop_cfun ();
-   current_function_decl = old_current_function_decl;
-   gcc_assert (!current_function_decl
- 	      || DECL_STRUCT_FUNCTION (current_function_decl) == cfun);
    return;
  }
  
--- 5230,5235 ----
*** /tmp/QSouyb_tree-profile.c	Thu Aug  9 15:21:47 2012
--- gcc/tree-profile.c	Tue Aug  7 14:59:02 2012
*************** tree_profiling (void)
*** 479,485 ****
  	continue;
  
        push_cfun (DECL_STRUCT_FUNCTION (node->symbol.decl));
-       current_function_decl = node->symbol.decl;
  
        /* Re-set global shared temporary variable for edge-counters.  */
        gcov_type_tmp_var = NULL_TREE;
--- 479,484 ----
*************** tree_profiling (void)
*** 504,511 ****
  	 easy to adjust it, if and when there is some.  */
        free_dominance_info (CDI_DOMINATORS);
        free_dominance_info (CDI_POST_DOMINATORS);
- 
-       current_function_decl = NULL;
        pop_cfun ();
      }
  
--- 503,508 ----
*************** tree_profiling (void)
*** 540,546 ****
  	continue;
  
        push_cfun (DECL_STRUCT_FUNCTION (node->symbol.decl));
-       current_function_decl = node->symbol.decl;
  
        FOR_EACH_BB (bb)
  	{
--- 537,542 ----
*************** tree_profiling (void)
*** 557,563 ****
  
        rebuild_cgraph_edges ();
  
-       current_function_decl = NULL;
        pop_cfun ();
      }
  
--- 553,558 ----
*** /tmp/2E21Od_tree-sra.c	Thu Aug  9 15:21:47 2012
--- gcc/tree-sra.c	Tue Aug  7 15:01:55 2012
*************** convert_callers_for_node (struct cgraph_
*** 4612,4618 ****
  
    for (cs = node->callers; cs; cs = cs->next_caller)
      {
-       current_function_decl = cs->caller->symbol.decl;
        push_cfun (DECL_STRUCT_FUNCTION (cs->caller->symbol.decl));
  
        if (dump_file)
--- 4612,4617 ----
*************** static void
*** 4641,4654 ****
  convert_callers (struct cgraph_node *node, tree old_decl,
  		 ipa_parm_adjustment_vec adjustments)
  {
-   tree old_cur_fndecl = current_function_decl;
    basic_block this_block;
  
    cgraph_for_node_and_aliases (node, convert_callers_for_node,
  			       adjustments, false);
  
-   current_function_decl = old_cur_fndecl;
- 
    if (!encountered_recursive_call)
      return;
  
--- 4640,4650 ----
*************** modify_function (struct cgraph_node *nod
*** 4689,4699 ****
    rebuild_cgraph_edges ();
    free_dominance_info (CDI_DOMINATORS);
    pop_cfun ();
-   current_function_decl = NULL_TREE;
  
    new_node = cgraph_function_versioning (node, redirect_callers, NULL, NULL,
  					 false, NULL, NULL, "isra");
-   current_function_decl = new_node->symbol.decl;
    push_cfun (DECL_STRUCT_FUNCTION (new_node->symbol.decl));
  
    ipa_modify_formal_parameters (current_function_decl, adjustments, "ISRA");
--- 4685,4693 ----
*** /tmp/60W3rb_tree-ssa-structalias.c	Thu Aug  9 15:21:47 2012
--- gcc/tree-ssa-structalias.c	Tue Aug  7 15:42:56 2012
*************** ipa_pta_execute (void)
*** 6891,6897 ****
      {
        struct function *func;
        basic_block bb;
-       tree old_func_decl;
  
        /* Nodes without a body are not interesting.  */
        if (!cgraph_function_with_gimple_body_p (node))
--- 6891,6896 ----
*************** ipa_pta_execute (void)
*** 6909,6917 ****
  	}
  
        func = DECL_STRUCT_FUNCTION (node->symbol.decl);
-       old_func_decl = current_function_decl;
        push_cfun (func);
-       current_function_decl = node->symbol.decl;
  
        /* For externally visible or attribute used annotated functions use
  	 local constraints for their arguments.
--- 6908,6914 ----
*************** ipa_pta_execute (void)
*** 6968,6974 ****
  	    }
  	}
  
-       current_function_decl = old_func_decl;
        pop_cfun ();
  
        if (dump_file)
--- 6965,6970 ----

^ permalink raw reply	[flat|nested] 14+ messages in thread

* Re: [PATCH] Set current_function_decl in {push,pop}_cfun and push_struct_function
  2012-08-09 14:27 [PATCH] Set current_function_decl in {push,pop}_cfun and push_struct_function Martin Jambor
@ 2012-08-09 14:58 ` Richard Guenther
  2012-08-10 14:58 ` Eric Botcazou
  1 sibling, 0 replies; 14+ messages in thread
From: Richard Guenther @ 2012-08-09 14:58 UTC (permalink / raw)
  To: GCC Patches

On Thu, Aug 9, 2012 at 4:26 PM, Martin Jambor <mjambor@suse.cz> wrote:
> Hi,
>
> I've always found it silly that in order to change the current
> function one has to call push_cfun and pop_cfun which conveniently set
> and restore the value of cfun and in addition to that also set
> current_function_decl and usually also cache its old value to restore
> it back afterwards.  I also think that, at least throughout the
> middle-end, we should strive to have current_function_decl consistent
> with cfun->decl.  There are quite a few places where we are not
> consistent and I think such situations are prone to nasty surprises as
> various functions rely on cfun and others on current_function_decl and
> it's easy to be unaware that one of the two is incorrect at the
> moment.
>
> This week I have therefore decided to try and make push_cfun, pop_cfun
> and push_struct_function also set the current_function_decl.  Being
> afraid of opening a giant can of worms I only a mid-sized hole and
> left various set_cfuns for later as well as places where we set
> current_function_decl without bothering with cfun.  After a few
> debugging sessions I came up with the patch below.  The changes are
> mostly mechanical, let me try and explain some of the difficult or
> not-quite-nice ones, most of which come from calls from front-ends
> which generally do not care about cfun all that much.
>
> - In order to ensure that pop_cfun will reliable restore the old
>   current_function_decl, push_cfun asserts that cfun and
>   current_function_decl match.  pop_cfun then simply restores
>   current_function_decl to new_cfun->decl or NULL_TREE if new_cfun is
>   NULL.  To check that the two remain consistent, pop_cfun has a
>   similar (albeit checking) assert.
>
> - I had to allow push_cfun(NULL) because in
>   gfc_get_extern_function_decl in fortran/trans-decl.c we momentarily
>   emulate top-level context by doing:
>
>           current_function_decl = NULL_TREE;
>           push_cfun (cfun);
>
>           do_something ()
>
>           pop_cfun ();
>           current_function_decl = save_fn_decl;
>
>   and to keep current_function_decl consistent with cfun, cfun had to
>   be made NULL too.  Co I converted the above to push_cfun (NULL)
>   which also sets current_function_decl to NULL_TREE.
>
> - I also had to allow push_cfun(NULL) because
>   dwarf2out_abstract_function does just that, just it looks like:
>
>   push_cfun (DECL_STRUCT_FUNCTION (decl));
>
>   but DECL_STRUCT_FUNCTION is usually (always?) NULL for abstract
>   origin functions.  But this also means that changed push_cfun sets
>   current_function_decl to NULL, which means the abstract function is
>   not dwarf2outed as it should be.  Thus, in perhaps the most awful
>   thunk in this patch I re-set current_function_decl after calling
>   push_cfun.  If someone has a better idea how to deal with this, I'm
>   certainly interested.
>
>   For the same reason I do not assert that
>   current_function matches cfun->decl in pop_cfun if cfun is NULL.
>
> - each cfun change also triggers a pair of init_dummy_function_start
>   and expand_dummy_function_end which invoke push_struct_function and
>   pop_cfun respectively.  Because we may be in the middle of another
>   push/pop_cfun, the current_function_decl may not match and so the
>   asserts are disabled in these cases, fortunately we can recognize
>   them by looking at value of in_dummy_function.
>
> - ada/gcc-interface/utils.c:rest_of_subprog_body_compilation calls
>   dump_function which in turns calls dump_function_to_file which calls
>   push_cfun.  But Ada front end has its idea of the
>   current_function_decl and there is no cfun which is an inconsistency
>   which makes push_cfun assert fail.  I "solved" it by temporarily
>   setting current_function_decl to NULL_TREE.  It's just dumping and I
>   thought that dump_function should be considered middle-end and thus
>   middle-end invariants should apply.
>
> The patch passes bootstrap and testing on x86_64-linux (all languages
> + ada + obj-c++) and ia64-linux (c,c++,fortran,objc,obj-c++).  There
> is some confusing jitter in the go testing results which I have not
> yet looked at (perhaps compare_tests just can't deal with it, there
> are tests reported both as newly failing and newly working etc...) but
> I thought that I'd send the patch now anyway to get some feedback in
> case I was doing something else wrong (I also do not know whether
> anyone but Ian can modify the go front-end).  I have also LTO-built
> Mozilla Firefox with the patch.
>
> Well, what do you think?

Well.  We should try to get rid of most push/pop_cfun calls, and the middle-end
should never need to look at current_function_decl ... (in practice we have
tree.c and fold-const.c which has to because its shared between FE and
middle-end).

For example the use in estimate_stack_frame_size.  Or the uses in IPA
passes.  It would be nice to figure out which parts need access to
cfun/current_function_decl in them (thus, arrange cfun/current_function_decl
to be NULL there).

Other than that, yes - for the middle-end cfun and current_fuction_decl
should be consistent.

Richard.

> Martin
>
>
> 2012-08-08  Martin Jambor  <mjambor@suse.cz>
>
>         * function.c (push_cfun): Check old current_function_decl matches
>         old cfun, set new current_function_decl to the decl of the new
>         cfun.
>         (push_struct_function): Likewise.
>         (pop_cfun): Likewise.
>         (allocate_struct_function): Move call to
>         invoke_set_current_function_hook to the end of the function.
>         * cfgexpand.c (estimated_stack_frame_size): Do not set and restore
>         current_function_decl.
>         * cgraph.c (cgraph_release_function_body): Likewise.
>         * cgraphunit.c (cgraph_process_new_functions): Likewise.
>         (cgraph_add_new_function): Likewise.
>         (cgraph_analyze_function): Likewise.
>         (assemble_thunk): Set cfun to NULL at the end.
>         (expand_function): Move call to set_cfun downwards.
>         * dwarf2out.c (dwarf2out_abstract_function): Do not restore
>         current_function_decl.
>         * gimple-low.c (record_vars_into): Only check current_function_decl
>         before possibly doing push_cfun.
>         * gimplify.c (gimplify_function_tree): Do not set and restore
>         current_function_decl.
>         * ipa-inline-analysis.c (compute_inline_parameters): Likewise.
>         (inline_analyze_function): Likewise.
>         * ipa-prop.c (ipa_analyze_node): Likewise.
>         * ipa-pure-const.c (analyze_function): Likewise.
>         * lto-streamer-in.c (lto_input_function_body): Do not set
>         current_function_decl.
>         * lto-streamer-out.c (output_function): Do not set and restore
>         current_function_decl.
>         * matrix-reorg.c (transform_allocation_sites): Likewise, also use
>         push/pop_cfun instead of set_cfun.
>         (matrix_reorg): Do not set and restore current_function_decl.
>         * omp-low.c (finalize_task_copyfn): Likewise.
>         (expand_omp_taskreg): Likewise.
>         (create_task_copyfn): Likewise, move push_cfun up quite a bit.
>         * passes.c (dump_passes): Do not set and restore current_function_decl.
>         (do_per_function): Likewise.
>         (do_per_function_toporder): Likewise.
>         * trans-mem.c (ipa_tm_scan_irr_function): Likewise.
>         (ipa_tm_transform_transaction): Likewise.
>         (ipa_tm_transform_clone): Likewise.
>         (ipa_tm_execute): Likewise.
>         * tree-emutls.c (lower_emutls_function_body): Likewise.
>         * tree-inline.c (initialize_cfun): Do not call pop_cfun.
>         (tree_function_versioning): Do not call push_cfun, do not set and
>         restore current_function_decl.  Remove assert checking consistency of
>         cfun and current_function_decl.
>         * tree-profile.c (tree_profiling): Do not set and restore
>         current_function_decl.
>         * tree-sra.c (convert_callers_for_node): Do not set
>         current_function_decl.
>         (convert_callers): Do not restore current_function_decl.
>         (modify_function): Do not set current_function_decl.
>         * tree-ssa-structalias.c (ipa_pta_execute): Do not set and restore
>         current_function_decl.
>
>         * fortran/trans-decl.c (gfc_get_extern_function_decl): Do not set and
>         restore current_function_decl, push NULL cfun.
>         (gfc_init_coarray_decl): Do not set and restore current_function_decl.
>
>         * go/gofrontend/gogo-tree.cc (write_initialization_function): Do not
>         set and restore current_function_decl.
>         (write_globals): Likewise.
>         (get_tree): Likewise.
>
>         * lto/lto.c (lto_materialize_function): Call push_struct_function
>         instead of allocate_struct_function and also call pop_cfun.
>
>         * ada/gcc-interface/utils.c (rest_of_subprog_body_compilation): Set
>         current_function_decl to NULL before calling dump_function and then
>         restore it.
>
>
>
> *** /tmp/KDyIva_utils.c Thu Aug  9 15:21:47 2012
> --- gcc/ada/gcc-interface/utils.c       Thu Aug  9 13:44:00 2012
> *************** end_subprog_body (tree body)
> *** 2740,2746 ****
>   void
>   rest_of_subprog_body_compilation (tree subprog_decl)
>   {
> !   /* We cannot track the location of errors past this point.  */
>     error_gnat_node = Empty;
>
>     /* If we're only annotating types, don't actually compile this function.  */
> --- 2740,2748 ----
>   void
>   rest_of_subprog_body_compilation (tree subprog_decl)
>   {
> !   tree saved_current_function_decl = current_function_decl;
> !
> !  /* We cannot track the location of errors past this point.  */
>     error_gnat_node = Empty;
>
>     /* If we're only annotating types, don't actually compile this function.  */
> *************** rest_of_subprog_body_compilation (tree s
> *** 2748,2754 ****
> --- 2750,2758 ----
>       return;
>
>     /* Dump functions before gimplification.  */
> +   current_function_decl = NULL_TREE;
>     dump_function (TDI_original, subprog_decl);
> +   current_function_decl = saved_current_function_decl;
>
>     if (!decl_function_context (subprog_decl))
>       cgraph_finalize_function (subprog_decl, false);
> *** /tmp/wurZNc_cfgexpand.c     Thu Aug  9 15:21:47 2012
> --- gcc/cfgexpand.c     Tue Aug  7 13:15:12 2012
> *************** estimated_stack_frame_size (struct cgrap
> *** 1422,1433 ****
>     HOST_WIDE_INT size = 0;
>     size_t i;
>     tree var;
> -   tree old_cur_fun_decl = current_function_decl;
>     struct function *fn = DECL_STRUCT_FUNCTION (node->symbol.decl);
>
> -   current_function_decl = node->symbol.decl;
>     push_cfun (fn);
> -
>     FOR_EACH_LOCAL_DECL (fn, i, var)
>       if (auto_var_in_fn_p (var, fn->decl))
>         size += expand_one_var (var, true, false);
> --- 1422,1430 ----
> *************** estimated_stack_frame_size (struct cgrap
> *** 1442,1448 ****
>         fini_vars_expansion ();
>       }
>     pop_cfun ();
> -   current_function_decl = old_cur_fun_decl;
>     return size;
>   }
>
> --- 1439,1444 ----
> *** /tmp/8XER7b_cgraph.c        Thu Aug  9 15:21:47 2012
> --- gcc/cgraph.c        Tue Aug  7 13:17:24 2012
> *************** cgraph_release_function_body (struct cgr
> *** 1128,1134 ****
>   {
>     if (DECL_STRUCT_FUNCTION (node->symbol.decl))
>       {
> -       tree old_decl = current_function_decl;
>         push_cfun (DECL_STRUCT_FUNCTION (node->symbol.decl));
>         if (cfun->cfg
>           && current_loops)
> --- 1128,1133 ----
> *************** cgraph_release_function_body (struct cgr
> *** 1138,1148 ****
>         }
>         if (cfun->gimple_df)
>         {
> -         current_function_decl = node->symbol.decl;
>           delete_tree_ssa ();
>           delete_tree_cfg_annotations ();
>           cfun->eh = NULL;
> -         current_function_decl = old_decl;
>         }
>         if (cfun->cfg)
>         {
> --- 1137,1145 ----
> *** /tmp/WL9Mge_cgraphunit.c    Thu Aug  9 15:21:47 2012
> --- gcc/cgraphunit.c    Wed Aug  8 15:54:56 2012
> *************** cgraph_process_new_functions (void)
> *** 313,319 ****
>           if (!node->analyzed)
>             cgraph_analyze_function (node);
>           push_cfun (DECL_STRUCT_FUNCTION (fndecl));
> -         current_function_decl = fndecl;
>           if ((cgraph_state == CGRAPH_STATE_IPA_SSA
>               && !gimple_in_ssa_p (DECL_STRUCT_FUNCTION (fndecl)))
>               /* When not optimizing, be sure we run early local passes anyway
> --- 313,318 ----
> *************** cgraph_process_new_functions (void)
> *** 325,331 ****
>           free_dominance_info (CDI_POST_DOMINATORS);
>           free_dominance_info (CDI_DOMINATORS);
>           pop_cfun ();
> -         current_function_decl = NULL;
>             cgraph_call_function_insertion_hooks (node);
>           break;
>
> --- 324,329 ----
> *************** cgraph_add_new_function (tree fndecl, bo
> *** 495,508 ****
>         if (!lowered && cgraph_state == CGRAPH_STATE_EXPANSION)
>           {
>             push_cfun (DECL_STRUCT_FUNCTION (fndecl));
> -           current_function_decl = fndecl;
>             gimple_register_cfg_hooks ();
>             bitmap_obstack_initialize (NULL);
>             execute_pass_list (all_lowering_passes);
>             execute_pass_list (pass_early_local_passes.pass.sub);
>             bitmap_obstack_release (NULL);
>             pop_cfun ();
> -           current_function_decl = NULL;
>
>             lowered = true;
>           }
> --- 493,504 ----
> *************** cgraph_add_new_function (tree fndecl, bo
> *** 521,527 ****
>           node->lowered = true;
>         cgraph_analyze_function (node);
>         push_cfun (DECL_STRUCT_FUNCTION (fndecl));
> -       current_function_decl = fndecl;
>         gimple_register_cfg_hooks ();
>         bitmap_obstack_initialize (NULL);
>         if (!gimple_in_ssa_p (DECL_STRUCT_FUNCTION (fndecl)))
> --- 517,522 ----
> *************** cgraph_add_new_function (tree fndecl, bo
> *** 529,535 ****
>         bitmap_obstack_release (NULL);
>         pop_cfun ();
>         expand_function (node);
> -       current_function_decl = NULL;
>         break;
>
>         default:
> --- 524,529 ----
> *************** fixup_same_cpp_alias_visibility (symtab_
> *** 597,603 ****
>   static void
>   cgraph_analyze_function (struct cgraph_node *node)
>   {
> -   tree save = current_function_decl;
>     tree decl = node->symbol.decl;
>     location_t saved_loc = input_location;
>     input_location = DECL_SOURCE_LOCATION (decl);
> --- 591,596 ----
> *************** cgraph_analyze_function (struct cgraph_n
> *** 638,644 ****
>       }
>     else
>       {
> -       current_function_decl = decl;
>         push_cfun (DECL_STRUCT_FUNCTION (decl));
>
>         assign_assembler_name_if_neeeded (node->symbol.decl);
> --- 631,636 ----
> *************** cgraph_analyze_function (struct cgraph_n
> *** 672,678 ****
>       }
>     node->analyzed = true;
>
> -   current_function_decl = save;
>     input_location = saved_loc;
>   }
>
> --- 664,669 ----
> *************** assemble_thunk (struct cgraph_node *node
> *** 1520,1525 ****
> --- 1511,1517 ----
>         bitmap_obstack_release (NULL);
>       }
>     current_function_decl = NULL;
> +   set_cfun (NULL);
>   }
>
>
> *************** expand_function (struct cgraph_node *nod
> *** 1612,1619 ****
>     /* Release the default bitmap obstack.  */
>     bitmap_obstack_release (NULL);
>
> -   set_cfun (NULL);
> -
>     /* If requested, warn about function definitions where the function will
>        return a value (usually of some struct or union type) which itself will
>        take up a lot of stack space.  */
> --- 1604,1609 ----
> *************** expand_function (struct cgraph_node *nod
> *** 1658,1663 ****
> --- 1648,1654 ----
>
>     /* Make sure that BE didn't give up on compiling.  */
>     gcc_assert (TREE_ASM_WRITTEN (decl));
> +   set_cfun (NULL);
>     current_function_decl = NULL;
>
>     /* It would make a lot more sense to output thunks before function body to get more
> *** /tmp/edrpua_dwarf2out.c     Thu Aug  9 15:21:47 2012
> --- gcc/dwarf2out.c     Wed Aug  8 18:12:07 2012
> *************** static void
> *** 16673,16679 ****
>   dwarf2out_abstract_function (tree decl)
>   {
>     dw_die_ref old_die;
> -   tree save_fn;
>     tree context;
>     int was_abstract;
>     htab_t old_decl_loc_table;
> --- 16673,16678 ----
> *************** dwarf2out_abstract_function (tree decl)
> *** 16714,16736 ****
>       }
>
>     /* Pretend we've just finished compiling this function.  */
> -   save_fn = current_function_decl;
> -   current_function_decl = decl;
>     push_cfun (DECL_STRUCT_FUNCTION (decl));
> !
>     was_abstract = DECL_ABSTRACT (decl);
>     set_decl_abstract_flags (decl, 1);
>     dwarf2out_decl (decl);
>     if (! was_abstract)
>       set_decl_abstract_flags (decl, 0);
>
> !   current_function_decl = save_fn;
>     decl_loc_table = old_decl_loc_table;
>     cached_dw_loc_list_table = old_cached_dw_loc_list_table;
>     call_arg_locations = old_call_arg_locations;
>     call_site_count = old_call_site_count;
>     tail_call_site_count = old_tail_call_site_count;
> -   pop_cfun ();
>   }
>
>   /* Helper function of premark_used_types() which gets called through
> --- 16713,16735 ----
>       }
>
>     /* Pretend we've just finished compiling this function.  */
>     push_cfun (DECL_STRUCT_FUNCTION (decl));
> !   /* DECL_STRUCT_FUNCTION can be NULL and in that case push_cfun has set
> !      current_function_decl to NULL which is not what we want.  Re-set it
> !      again.  */
> !   current_function_decl = decl;
>     was_abstract = DECL_ABSTRACT (decl);
>     set_decl_abstract_flags (decl, 1);
>     dwarf2out_decl (decl);
>     if (! was_abstract)
>       set_decl_abstract_flags (decl, 0);
>
> !   pop_cfun ();
>     decl_loc_table = old_decl_loc_table;
>     cached_dw_loc_list_table = old_cached_dw_loc_list_table;
>     call_arg_locations = old_call_arg_locations;
>     call_site_count = old_call_site_count;
>     tail_call_site_count = old_tail_call_site_count;
>   }
>
>   /* Helper function of premark_used_types() which gets called through
> *** /tmp/yrx7vc_trans-decl.c    Thu Aug  9 15:21:47 2012
> --- gcc/fortran/trans-decl.c    Tue Aug  7 16:02:30 2012
> *************** gfc_get_extern_function_decl (gfc_symbol
> *** 1624,1640 ****
>           /* By construction, the external function cannot be
>              a contained procedure.  */
>           locus old_loc;
> -         tree save_fn_decl = current_function_decl;
>
> -         current_function_decl = NULL_TREE;
>           gfc_save_backend_locus (&old_loc);
> !         push_cfun (cfun);
>
>           gfc_create_function_decl (gsym->ns, true);
>
>           pop_cfun ();
>           gfc_restore_backend_locus (&old_loc);
> -         current_function_decl = save_fn_decl;
>         }
>
>         /* If the namespace has entries, the proc_name is the
> --- 1624,1637 ----
>           /* By construction, the external function cannot be
>              a contained procedure.  */
>           locus old_loc;
>
>           gfc_save_backend_locus (&old_loc);
> !         push_cfun (NULL);
>
>           gfc_create_function_decl (gsym->ns, true);
>
>           pop_cfun ();
>           gfc_restore_backend_locus (&old_loc);
>         }
>
>         /* If the namespace has entries, the proc_name is the
> *************** add_argument_checking (stmtblock_t *bloc
> *** 4849,4864 ****
>   void
>   gfc_init_coarray_decl (bool main_tu)
>   {
> -   tree save_fn_decl;
> -
>     if (gfc_option.coarray != GFC_FCOARRAY_LIB)
>       return;
>
>     if (gfort_gvar_caf_this_image || gfort_gvar_caf_num_images)
>       return;
>
> -   save_fn_decl = current_function_decl;
> -   current_function_decl = NULL_TREE;
>     push_cfun (cfun);
>
>     gfort_gvar_caf_this_image
> --- 4846,4857 ----
> *************** gfc_init_coarray_decl (bool main_tu)
> *** 4894,4900 ****
>     pushdecl_top_level (gfort_gvar_caf_num_images);
>
>     pop_cfun ();
> -   current_function_decl = save_fn_decl;
>   }
>
>
> --- 4887,4892 ----
> *** /tmp/ccrTha_function.c      Thu Aug  9 15:21:47 2012
> --- gcc/function.c      Wed Aug  8 18:06:40 2012
> *************** set_cfun (struct function *new_cfun)
> *** 4413,4434 ****
>
>   static VEC(function_p,heap) *cfun_stack;
>
> ! /* Push the current cfun onto the stack, and set cfun to new_cfun.  */
>
>   void
>   push_cfun (struct function *new_cfun)
>   {
>     VEC_safe_push (function_p, heap, cfun_stack, cfun);
>     set_cfun (new_cfun);
>   }
>
> ! /* Pop cfun from the stack.  */
>
>   void
>   pop_cfun (void)
>   {
>     struct function *new_cfun = VEC_pop (function_p, cfun_stack);
>     set_cfun (new_cfun);
>   }
>
>   /* Return value of funcdef and increase it.  */
> --- 4413,4445 ----
>
>   static VEC(function_p,heap) *cfun_stack;
>
> ! /* Push the current cfun onto the stack, and set cfun to new_cfun.  Also set
> !    current_function_decl accordingly.  */
>
>   void
>   push_cfun (struct function *new_cfun)
>   {
> +   gcc_assert ((!cfun && !current_function_decl)
> +             || (cfun && current_function_decl == cfun->decl));
>     VEC_safe_push (function_p, heap, cfun_stack, cfun);
> +   current_function_decl = new_cfun ? new_cfun->decl : NULL_TREE;
>     set_cfun (new_cfun);
>   }
>
> ! /* Pop cfun from the stack.  Also set current_function_decl accordingly.  */
>
>   void
>   pop_cfun (void)
>   {
>     struct function *new_cfun = VEC_pop (function_p, cfun_stack);
> +   /* When in_dummy_function, we do have a cfun but current_function_decl is
> +      NULL.  OTOH, dwarf2out can push a function of an abstract origin decl
> +      which is NULL but needs non-null current_function_decl.  */
> +   gcc_checking_assert (in_dummy_function
> +                      || !cfun
> +                      || current_function_decl == cfun->decl);
>     set_cfun (new_cfun);
> +   current_function_decl = new_cfun ? new_cfun->decl : NULL_TREE;
>   }
>
>   /* Return value of funcdef and increase it.  */
> *************** allocate_struct_function (tree fndecl, b
> *** 4475,4482 ****
>     OVERRIDE_ABI_FORMAT (fndecl);
>   #endif
>
> -   invoke_set_current_function_hook (fndecl);
> -
>     if (fndecl != NULL_TREE)
>       {
>         DECL_STRUCT_FUNCTION (fndecl) = cfun;
> --- 4486,4491 ----
> *************** allocate_struct_function (tree fndecl, b
> *** 4502,4507 ****
> --- 4511,4518 ----
>            but is this worth the hassle?  */
>         cfun->can_throw_non_call_exceptions = flag_non_call_exceptions;
>       }
> +
> +   invoke_set_current_function_hook (fndecl);
>   }
>
>   /* This is like allocate_struct_function, but pushes a new cfun for FNDECL
> *************** allocate_struct_function (tree fndecl, b
> *** 4510,4516 ****
> --- 4521,4533 ----
>   void
>   push_struct_function (tree fndecl)
>   {
> +   /* When in_dummy_function we might be in the middle of a pop_cfun and
> +      current_function_decl and cfun may not match.  */
> +   gcc_assert (in_dummy_function
> +             || (!cfun && !current_function_decl)
> +             || (cfun && current_function_decl == cfun->decl));
>     VEC_safe_push (function_p, heap, cfun_stack, cfun);
> +   current_function_decl = fndecl;
>     allocate_struct_function (fndecl, false);
>   }
>
> *** /tmp/apOtwc_gimple-low.c    Thu Aug  9 15:21:47 2012
> --- gcc/gimple-low.c    Tue Aug  7 13:31:20 2012
> *************** lower_builtin_setjmp (gimple_stmt_iterat
> *** 991,997 ****
>   void
>   record_vars_into (tree vars, tree fn)
>   {
> !   if (fn != current_function_decl)
>       push_cfun (DECL_STRUCT_FUNCTION (fn));
>
>     for (; vars; vars = DECL_CHAIN (vars))
> --- 991,999 ----
>   void
>   record_vars_into (tree vars, tree fn)
>   {
> !   bool change_cfun = fn != current_function_decl;
> !
> !   if (change_cfun)
>       push_cfun (DECL_STRUCT_FUNCTION (fn));
>
>     for (; vars; vars = DECL_CHAIN (vars))
> *************** record_vars_into (tree vars, tree fn)
> *** 1011,1017 ****
>         add_local_decl (cfun, var);
>       }
>
> !   if (fn != current_function_decl)
>       pop_cfun ();
>   }
>
> --- 1013,1019 ----
>         add_local_decl (cfun, var);
>       }
>
> !   if (change_cfun)
>       pop_cfun ();
>   }
>
> *** /tmp/uvszca_gimplify.c      Thu Aug  9 15:21:47 2012
> --- gcc/gimplify.c      Tue Aug  7 13:33:19 2012
> *************** flag_instrument_functions_exclude_p (tre
> *** 8258,8271 ****
>   void
>   gimplify_function_tree (tree fndecl)
>   {
> !   tree oldfn, parm, ret;
>     gimple_seq seq;
>     gimple bind;
>
>     gcc_assert (!gimple_body (fndecl));
>
> -   oldfn = current_function_decl;
> -   current_function_decl = fndecl;
>     if (DECL_STRUCT_FUNCTION (fndecl))
>       push_cfun (DECL_STRUCT_FUNCTION (fndecl));
>     else
> --- 8258,8269 ----
>   void
>   gimplify_function_tree (tree fndecl)
>   {
> !   tree parm, ret;
>     gimple_seq seq;
>     gimple bind;
>
>     gcc_assert (!gimple_body (fndecl));
>
>     if (DECL_STRUCT_FUNCTION (fndecl))
>       push_cfun (DECL_STRUCT_FUNCTION (fndecl));
>     else
> *************** gimplify_function_tree (tree fndecl)
> *** 8350,8356 ****
>     DECL_SAVED_TREE (fndecl) = NULL_TREE;
>     cfun->curr_properties = PROP_gimple_any;
>
> -   current_function_decl = oldfn;
>     pop_cfun ();
>   }
>
> --- 8348,8353 ----
> *** /tmp/gISRxc_gogo-tree.cc    Thu Aug  9 15:21:47 2012
> --- gcc/go/gofrontend/gogo-tree.cc      Tue Aug  7 16:13:51 2012
> *************** Gogo::write_initialization_function(tree
> *** 483,489 ****
>
>     DECL_SAVED_TREE(fndecl) = init_stmt_list;
>
> -   current_function_decl = fndecl;
>     if (DECL_STRUCT_FUNCTION(fndecl) == NULL)
>       push_struct_function(fndecl);
>     else
> --- 483,488 ----
> *************** Gogo::write_initialization_function(tree
> *** 494,500 ****
>
>     cgraph_add_new_function(fndecl, false);
>
> -   current_function_decl = NULL_TREE;
>     pop_cfun();
>   }
>
> --- 493,498 ----
> *************** Gogo::write_globals()
> *** 871,877 ****
>               // means that we need an fndecl.
>               if (init_fndecl == NULL_TREE)
>                 init_fndecl = this->initialization_function_decl();
> -             current_function_decl = init_fndecl;
>               if (DECL_STRUCT_FUNCTION(init_fndecl) == NULL)
>                 push_struct_function(init_fndecl);
>               else
> --- 869,874 ----
> *************** Gogo::write_globals()
> *** 881,887 ****
>               var_init_tree = no->var_value()->get_init_block(this, NULL,
>                                                               var_decl);
>
> -             current_function_decl = NULL_TREE;
>               pop_cfun();
>             }
>
> --- 878,883 ----
> *************** Named_object::get_tree(Gogo* gogo, Named
> *** 1123,1137 ****
>                 cfun->function_end_locus =
>                     func->block()->end_location().gcc_location();
>
> -               current_function_decl = decl;
> -
>                 func->build_tree(gogo, this);
>
>                 gimplify_function_tree(decl);
>
>                 cgraph_finalize_function(decl, true);
>
> -               current_function_decl = NULL_TREE;
>                 pop_cfun();
>               }
>           }
> --- 1119,1130 ----
> *** /tmp/2SvTGa_ipa-inline-analysis.c   Thu Aug  9 15:21:47 2012
> --- gcc/ipa-inline-analysis.c   Tue Aug  7 13:35:39 2012
> *************** compute_inline_parameters (struct cgraph
> *** 2068,2074 ****
>     HOST_WIDE_INT self_stack_size;
>     struct cgraph_edge *e;
>     struct inline_summary *info;
> -   tree old_decl = current_function_decl;
>
>     gcc_assert (!node->global.inlined_to);
>
> --- 2068,2073 ----
> *************** compute_inline_parameters (struct cgraph
> *** 2095,2101 ****
>       }
>
>     /* Even is_gimple_min_invariant rely on current_function_decl.  */
> -   current_function_decl = node->symbol.decl;
>     push_cfun (DECL_STRUCT_FUNCTION (node->symbol.decl));
>
>     /* Estimate the stack size for the function if we're optimizing.  */
> --- 2094,2099 ----
> *************** compute_inline_parameters (struct cgraph
> *** 2137,2143 ****
>     info->size = info->self_size;
>     info->stack_frame_offset = 0;
>     info->estimated_stack_size = info->estimated_self_stack_size;
> -   current_function_decl = old_decl;
>     pop_cfun ();
>   }
>
> --- 2135,2140 ----
> *************** static void
> *** 2924,2930 ****
>   inline_analyze_function (struct cgraph_node *node)
>   {
>     push_cfun (DECL_STRUCT_FUNCTION (node->symbol.decl));
> -   current_function_decl = node->symbol.decl;
>
>     if (dump_file)
>       fprintf (dump_file, "\nAnalyzing function: %s/%u\n",
> --- 2921,2926 ----
> *************** inline_analyze_function (struct cgraph_n
> *** 2933,2939 ****
>       inline_indirect_intraprocedural_analysis (node);
>     compute_inline_parameters (node, false);
>
> -   current_function_decl = NULL;
>     pop_cfun ();
>   }
>
> --- 2929,2934 ----
> *** /tmp/6WwhXc_ipa-prop.c      Thu Aug  9 15:21:47 2012
> --- gcc/ipa-prop.c      Tue Aug  7 13:36:13 2012
> *************** ipa_analyze_node (struct cgraph_node *no
> *** 1674,1680 ****
>     ipa_check_create_edge_args ();
>     info = IPA_NODE_REF (node);
>     push_cfun (DECL_STRUCT_FUNCTION (node->symbol.decl));
> -   current_function_decl = node->symbol.decl;
>     ipa_initialize_node_params (node);
>
>     param_count = ipa_get_param_count (info);
> --- 1674,1679 ----
> *************** ipa_analyze_node (struct cgraph_node *no
> *** 1688,1694 ****
>       if (parms_ainfo[i].visited_statements)
>         BITMAP_FREE (parms_ainfo[i].visited_statements);
>
> -   current_function_decl = NULL;
>     pop_cfun ();
>   }
>
> --- 1687,1692 ----
> *** /tmp/QSIQac_ipa-pure-const.c        Thu Aug  9 15:21:47 2012
> --- gcc/ipa-pure-const.c        Tue Aug  7 13:37:57 2012
> *************** static funct_state
> *** 724,730 ****
>   analyze_function (struct cgraph_node *fn, bool ipa)
>   {
>     tree decl = fn->symbol.decl;
> -   tree old_decl = current_function_decl;
>     funct_state l;
>     basic_block this_block;
>
> --- 724,729 ----
> *************** analyze_function (struct cgraph_node *fn
> *** 752,758 ****
>       }
>
>     push_cfun (DECL_STRUCT_FUNCTION (decl));
> -   current_function_decl = decl;
>
>     FOR_EACH_BB (this_block)
>       {
> --- 751,756 ----
> *************** end:
> *** 820,826 ****
>       l->can_throw = false;
>
>     pop_cfun ();
> -   current_function_decl = old_decl;
>     if (dump_file)
>       {
>         if (l->looping)
> --- 818,823 ----
> *** /tmp/mNj9je_lto-streamer-in.c       Thu Aug  9 15:21:47 2012
> --- gcc/lto-streamer-in.c       Tue Aug  7 13:44:16 2012
> *************** void
> *** 1036,1042 ****
>   lto_input_function_body (struct lto_file_decl_data *file_data,
>                          tree fn_decl, const char *data)
>   {
> -   current_function_decl = fn_decl;
>     lto_read_body (file_data, fn_decl, data, LTO_section_function_body);
>   }
>
> --- 1036,1041 ----
> *** /tmp/Mmj3jc_lto-streamer-out.c      Thu Aug  9 15:21:47 2012
> --- gcc/lto-streamer-out.c      Tue Aug  7 13:46:04 2012
> *************** output_function (struct cgraph_node *nod
> *** 793,799 ****
>     gcc_assert (current_function_decl == NULL_TREE && cfun == NULL);
>
>     /* Set current_function_decl and cfun.  */
> -   current_function_decl = function;
>     push_cfun (fn);
>
>     /* Make string 0 be a NULL string.  */
> --- 793,798 ----
> *************** output_function (struct cgraph_node *nod
> *** 847,853 ****
>
>     destroy_output_block (ob);
>
> -   current_function_decl = NULL;
>     pop_cfun ();
>   }
>
> --- 846,851 ----
> *** /tmp/iXBLWd_lto.c   Thu Aug  9 15:21:47 2012
> --- gcc/lto/lto.c       Wed Aug  8 12:14:32 2012
> *************** lto_materialize_function (struct cgraph_
> *** 221,227 ****
>
>           gcc_assert (DECL_STRUCT_FUNCTION (decl) == NULL);
>
> !         allocate_struct_function (decl, false);
>           announce_function (decl);
>           lto_input_function_body (file_data, decl, data);
>           if (DECL_FUNCTION_PERSONALITY (decl) && !first_personality_decl)
> --- 221,227 ----
>
>           gcc_assert (DECL_STRUCT_FUNCTION (decl) == NULL);
>
> !         push_struct_function (decl);
>           announce_function (decl);
>           lto_input_function_body (file_data, decl, data);
>           if (DECL_FUNCTION_PERSONALITY (decl) && !first_personality_decl)
> *************** lto_materialize_function (struct cgraph_
> *** 229,234 ****
> --- 229,235 ----
>           lto_stats.num_function_bodies++;
>           lto_free_section_data (file_data, LTO_section_function_body, name,
>                                  data, len);
> +         pop_cfun ();
>           ggc_collect ();
>         }
>       }
> *** /tmp/mJnAqb_matrix-reorg.c  Thu Aug  9 15:21:47 2012
> --- gcc/matrix-reorg.c  Tue Aug  7 13:50:23 2012
> *************** transform_allocation_sites (void **slot,
> *** 1985,1991 ****
>   {
>     int i;
>     struct matrix_info *mi;
> !   tree type, oldfn, prev_dim_size;
>     gimple call_stmt_0, use_stmt;
>     struct cgraph_node *c_node;
>     struct cgraph_edge *e;
> --- 1985,1991 ----
>   {
>     int i;
>     struct matrix_info *mi;
> !   tree type, prev_dim_size;
>     gimple call_stmt_0, use_stmt;
>     struct cgraph_node *c_node;
>     struct cgraph_edge *e;
> *************** transform_allocation_sites (void **slot,
> *** 2102,2109 ****
>        We add the assignment to the global before the malloc of level 0.  */
>
>     /* To be able to produce gimple temporaries.  */
> -   oldfn = current_function_decl;
> -   current_function_decl = mi->allocation_function_decl;
>     push_cfun (DECL_STRUCT_FUNCTION (mi->allocation_function_decl));
>
>     /* Set the dimension sizes as follows:
> --- 2102,2107 ----
> *************** transform_allocation_sites (void **slot,
> *** 2213,2225 ****
>         e = cgraph_edge (c_node, mi->free_stmts[i].stmt);
>         gcc_assert (e);
>         cgraph_remove_edge (e);
> !       current_function_decl = mi->free_stmts[i].func;
> !       set_cfun (DECL_STRUCT_FUNCTION (mi->free_stmts[i].func));
>         gsi = gsi_for_stmt (mi->free_stmts[i].stmt);
>         gsi_remove (&gsi, true);
>       }
>     /* Return to the previous situation.  */
> -   current_function_decl = oldfn;
>     pop_cfun ();
>     return 1;
>
> --- 2211,2222 ----
>         e = cgraph_edge (c_node, mi->free_stmts[i].stmt);
>         gcc_assert (e);
>         cgraph_remove_edge (e);
> !       push_cfun (DECL_STRUCT_FUNCTION (mi->free_stmts[i].func));
>         gsi = gsi_for_stmt (mi->free_stmts[i].stmt);
>         gsi_remove (&gsi, true);
> +       pop_cfun ();
>       }
>     /* Return to the previous situation.  */
>     pop_cfun ();
>     return 1;
>
> *************** matrix_reorg (void)
> *** 2265,2274 ****
>     /* Analyze the accesses of the matrices (escaping analysis).  */
>     FOR_EACH_DEFINED_FUNCTION (node)
>       {
> -       tree temp_fn;
> -
> -       temp_fn = current_function_decl;
> -       current_function_decl = node->symbol.decl;
>         push_cfun (DECL_STRUCT_FUNCTION (node->symbol.decl));
>         bitmap_obstack_initialize (NULL);
>         gimple_register_cfg_hooks ();
> --- 2262,2267 ----
> *************** matrix_reorg (void)
> *** 2278,2284 ****
>           free_dominance_info (CDI_DOMINATORS);
>           free_dominance_info (CDI_POST_DOMINATORS);
>           pop_cfun ();
> -         current_function_decl = temp_fn;
>           bitmap_obstack_release (NULL);
>
>           return 0;
> --- 2271,2276 ----
> *************** matrix_reorg (void)
> *** 2293,2299 ****
>           free_dominance_info (CDI_DOMINATORS);
>           free_dominance_info (CDI_POST_DOMINATORS);
>           pop_cfun ();
> -         current_function_decl = temp_fn;
>           bitmap_obstack_release (NULL);
>
>           return 0;
> --- 2285,2290 ----
> *************** matrix_reorg (void)
> *** 2324,2330 ****
>         free_dominance_info (CDI_DOMINATORS);
>         free_dominance_info (CDI_POST_DOMINATORS);
>         pop_cfun ();
> -       current_function_decl = temp_fn;
>         bitmap_obstack_release (NULL);
>       }
>     htab_traverse (matrices_to_reorg, transform_allocation_sites, NULL);
> --- 2315,2320 ----
> *************** matrix_reorg (void)
> *** 2332,2341 ****
>     FOR_EACH_DEFINED_FUNCTION (node)
>       {
>         /* Remember that allocation sites have been handled.  */
> -       tree temp_fn;
> -
> -       temp_fn = current_function_decl;
> -       current_function_decl = node->symbol.decl;
>         push_cfun (DECL_STRUCT_FUNCTION (node->symbol.decl));
>         bitmap_obstack_initialize (NULL);
>         gimple_register_cfg_hooks ();
> --- 2322,2327 ----
> *************** matrix_reorg (void)
> *** 2345,2351 ****
>         free_dominance_info (CDI_DOMINATORS);
>         free_dominance_info (CDI_POST_DOMINATORS);
>         pop_cfun ();
> -       current_function_decl = temp_fn;
>         bitmap_obstack_release (NULL);
>       }
>     htab_traverse (matrices_to_reorg, dump_matrix_reorg_analysis, NULL);
> --- 2331,2336 ----
> *** /tmp/EQo3Md_omp-low.c       Thu Aug  9 15:21:47 2012
> --- gcc/omp-low.c       Tue Aug  7 13:54:21 2012
> *************** static void
> *** 1243,1249 ****
>   finalize_task_copyfn (gimple task_stmt)
>   {
>     struct function *child_cfun;
> !   tree child_fn, old_fn;
>     gimple_seq seq = NULL, new_seq;
>     gimple bind;
>
> --- 1243,1249 ----
>   finalize_task_copyfn (gimple task_stmt)
>   {
>     struct function *child_cfun;
> !   tree child_fn;
>     gimple_seq seq = NULL, new_seq;
>     gimple bind;
>
> *************** finalize_task_copyfn (gimple task_stmt)
> *** 1257,1265 ****
>     DECL_STRUCT_FUNCTION (child_fn)->curr_properties
>       = cfun->curr_properties & ~PROP_loops;
>
> -   old_fn = current_function_decl;
>     push_cfun (child_cfun);
> -   current_function_decl = child_fn;
>     bind = gimplify_body (child_fn, false);
>     gimple_seq_add_stmt (&seq, bind);
>     new_seq = maybe_catch_exception (seq);
> --- 1257,1263 ----
> *************** finalize_task_copyfn (gimple task_stmt)
> *** 1271,1277 ****
>       }
>     gimple_set_body (child_fn, seq);
>     pop_cfun ();
> -   current_function_decl = old_fn;
>
>     cgraph_add_new_function (child_fn, false);
>   }
> --- 1269,1274 ----
> *************** expand_omp_taskreg (struct omp_region *r
> *** 3389,3395 ****
>     basic_block entry_bb, exit_bb, new_bb;
>     struct function *child_cfun;
>     tree child_fn, block, t;
> -   tree save_current;
>     gimple_stmt_iterator gsi;
>     gimple entry_stmt, stmt;
>     edge e;
> --- 3386,3391 ----
> *************** expand_omp_taskreg (struct omp_region *r
> *** 3589,3596 ****
>         /* Fix the callgraph edges for child_cfun.  Those for cfun will be
>          fixed in a following pass.  */
>         push_cfun (child_cfun);
> -       save_current = current_function_decl;
> -       current_function_decl = child_fn;
>         if (optimize)
>         optimize_omp_library_calls (entry_stmt);
>         rebuild_cgraph_edges ();
> --- 3585,3590 ----
> *************** expand_omp_taskreg (struct omp_region *r
> *** 3611,3617 ****
>         }
>         if (gimple_in_ssa_p (cfun))
>         update_ssa (TODO_update_ssa);
> -       current_function_decl = save_current;
>         pop_cfun ();
>       }
>
> --- 3605,3610 ----
> *************** create_task_copyfn (gimple task_stmt, om
> *** 6460,6466 ****
>
>     /* Populate the function.  */
>     push_gimplify_context (&gctx);
> !   current_function_decl = child_fn;
>
>     bind = build3 (BIND_EXPR, void_type_node, NULL, NULL, NULL);
>     TREE_SIDE_EFFECTS (bind) = 1;
> --- 6453,6459 ----
>
>     /* Populate the function.  */
>     push_gimplify_context (&gctx);
> !   push_cfun (child_cfun);
>
>     bind = build3 (BIND_EXPR, void_type_node, NULL, NULL, NULL);
>     TREE_SIDE_EFFECTS (bind) = 1;
> *************** create_task_copyfn (gimple task_stmt, om
> *** 6507,6514 ****
>     else
>       tcctx.cb.decl_map = NULL;
>
> -   push_cfun (child_cfun);
> -
>     arg = DECL_ARGUMENTS (child_fn);
>     TREE_TYPE (arg) = build_pointer_type (record_type);
>     sarg = DECL_CHAIN (arg);
> --- 6500,6505 ----
> *************** create_task_copyfn (gimple task_stmt, om
> *** 6666,6672 ****
>     pop_gimplify_context (NULL);
>     BIND_EXPR_BODY (bind) = list;
>     pop_cfun ();
> !   current_function_decl = ctx->cb.src_fn;
>   }
>
>   /* Lower the OpenMP parallel or task directive in the current statement
> --- 6657,6664 ----
>     pop_gimplify_context (NULL);
>     BIND_EXPR_BODY (bind) = list;
>     pop_cfun ();
> !   /* !!! Remove after testing.  */
> !   gcc_assert (current_function_decl == ctx->cb.src_fn);
>   }
>
>   /* Lower the OpenMP parallel or task directive in the current statement
> *** /tmp/qpEqgc_passes.c        Thu Aug  9 15:21:47 2012
> --- gcc/passes.c        Tue Aug  7 13:56:40 2012
> *************** void
> *** 679,685 ****
>   dump_passes (void)
>   {
>     struct cgraph_node *n, *node = NULL;
> -   tree save_fndecl = current_function_decl;
>
>     create_pass_tab();
>
> --- 679,684 ----
> *************** dump_passes (void)
> *** 694,700 ****
>       return;
>
>     push_cfun (DECL_STRUCT_FUNCTION (node->symbol.decl));
> -   current_function_decl = node->symbol.decl;
>
>     dump_pass_list (all_lowering_passes, 1);
>     dump_pass_list (all_small_ipa_passes, 1);
> --- 693,698 ----
> *************** dump_passes (void)
> *** 704,710 ****
>     dump_pass_list (all_passes, 1);
>
>     pop_cfun ();
> -   current_function_decl = save_fndecl;
>   }
>
>
> --- 702,707 ----
> *************** do_per_function (void (*callback) (void
> *** 1651,1664 ****
>             && (!node->clone_of || node->symbol.decl != node->clone_of->symbol.decl))
>           {
>             push_cfun (DECL_STRUCT_FUNCTION (node->symbol.decl));
> -           current_function_decl = node->symbol.decl;
>             callback (data);
>             if (!flag_wpa)
>               {
>                 free_dominance_info (CDI_DOMINATORS);
>                 free_dominance_info (CDI_POST_DOMINATORS);
>               }
> -           current_function_decl = NULL;
>             pop_cfun ();
>             ggc_collect ();
>           }
> --- 1648,1659 ----
> *************** do_per_function_toporder (void (*callbac
> *** 1699,1709 ****
>           if (cgraph_function_with_gimple_body_p (node))
>             {
>               push_cfun (DECL_STRUCT_FUNCTION (node->symbol.decl));
> -             current_function_decl = node->symbol.decl;
>               callback (data);
>               free_dominance_info (CDI_DOMINATORS);
>               free_dominance_info (CDI_POST_DOMINATORS);
> -             current_function_decl = NULL;
>               pop_cfun ();
>               ggc_collect ();
>             }
> --- 1694,1702 ----
> *** /tmp/GR8iVd_trans-mem.c     Thu Aug  9 15:21:47 2012
> --- gcc/trans-mem.c     Tue Aug  7 13:59:14 2012
> *************** ipa_tm_scan_irr_function (struct cgraph_
> *** 3980,3986 ****
>         || DECL_STRUCT_FUNCTION (node->symbol.decl)->cfg == NULL)
>       return false;
>
> -   current_function_decl = node->symbol.decl;
>     push_cfun (DECL_STRUCT_FUNCTION (node->symbol.decl));
>     calculate_dominance_info (CDI_DOMINATORS);
>
> --- 3980,3985 ----
> *************** ipa_tm_scan_irr_function (struct cgraph_
> *** 4052,4058 ****
>
>     VEC_free (basic_block, heap, queue);
>     pop_cfun ();
> -   current_function_decl = NULL;
>
>     return ret;
>   }
> --- 4051,4056 ----
> *************** ipa_tm_transform_transaction (struct cgr
> *** 4690,4696 ****
>
>     d = get_cg_data (&node, true);
>
> -   current_function_decl = node->symbol.decl;
>     push_cfun (DECL_STRUCT_FUNCTION (node->symbol.decl));
>     calculate_dominance_info (CDI_DOMINATORS);
>
> --- 4688,4693 ----
> *************** ipa_tm_transform_transaction (struct cgr
> *** 4715,4721 ****
>       update_ssa (TODO_update_ssa_only_virtuals);
>
>     pop_cfun ();
> -   current_function_decl = NULL;
>   }
>
>   /* Transform the calls within the transactional clone of NODE.  */
> --- 4712,4717 ----
> *************** ipa_tm_transform_clone (struct cgraph_no
> *** 4734,4741 ****
>     if (!node->callees && !node->indirect_calls && !d->irrevocable_blocks_clone)
>       return;
>
> !   current_function_decl = d->clone->symbol.decl;
> !   push_cfun (DECL_STRUCT_FUNCTION (current_function_decl));
>     calculate_dominance_info (CDI_DOMINATORS);
>
>     need_ssa_rename =
> --- 4730,4736 ----
>     if (!node->callees && !node->indirect_calls && !d->irrevocable_blocks_clone)
>       return;
>
> !   push_cfun (DECL_STRUCT_FUNCTION (d->clone->symbol.decl));
>     calculate_dominance_info (CDI_DOMINATORS);
>
>     need_ssa_rename =
> *************** ipa_tm_transform_clone (struct cgraph_no
> *** 4746,4752 ****
>       update_ssa (TODO_update_ssa_only_virtuals);
>
>     pop_cfun ();
> -   current_function_decl = NULL;
>   }
>
>   /* Main entry point for the transactional memory IPA pass.  */
> --- 4741,4746 ----
> *************** ipa_tm_execute (void)
> *** 4793,4799 ****
>             continue;
>           }
>
> -       current_function_decl = node->symbol.decl;
>         push_cfun (DECL_STRUCT_FUNCTION (node->symbol.decl));
>         calculate_dominance_info (CDI_DOMINATORS);
>
> --- 4787,4792 ----
> *************** ipa_tm_execute (void)
> *** 4813,4819 ****
>           }
>
>         pop_cfun ();
> -       current_function_decl = NULL;
>         }
>
>     /* For every local function on the callee list, scan as if we will be
> --- 4806,4811 ----
> *** /tmp/wwqagc_tree-emutls.c   Thu Aug  9 15:21:47 2012
> --- gcc/tree-emutls.c   Tue Aug  7 14:48:01 2012
> *************** lower_emutls_function_body (struct cgrap
> *** 618,624 ****
>     struct lower_emutls_data d;
>     bool any_edge_inserts = false;
>
> -   current_function_decl = node->symbol.decl;
>     push_cfun (DECL_STRUCT_FUNCTION (node->symbol.decl));
>
>     d.cfun_node = node;
> --- 618,623 ----
> *************** lower_emutls_function_body (struct cgrap
> *** 689,695 ****
>       gsi_commit_edge_inserts ();
>
>     pop_cfun ();
> -   current_function_decl = NULL;
>   }
>
>   /* Create emutls variable for VAR, DATA is pointer to static
> --- 688,693 ----
> *** /tmp/C7R3Td_tree-inline.c   Thu Aug  9 15:21:47 2012
> --- gcc/tree-inline.c   Tue Aug  7 14:56:44 2012
> *************** remap_decl_1 (tree decl, void *data)
> *** 1998,2004 ****
>   }
>
>   /* Build struct function and associated datastructures for the new clone
> !    NEW_FNDECL to be build.  CALLEE_FNDECL is the original */
>
>   static void
>   initialize_cfun (tree new_fndecl, tree callee_fndecl, gcov_type count)
> --- 1998,2005 ----
>   }
>
>   /* Build struct function and associated datastructures for the new clone
> !    NEW_FNDECL to be build.  CALLEE_FNDECL is the original.  Function changes
> !    the cfun to the function of new_fndecl (and current_function_decl too).  */
>
>   static void
>   initialize_cfun (tree new_fndecl, tree callee_fndecl, gcov_type count)
> *************** initialize_cfun (tree new_fndecl, tree c
> *** 2063,2069 ****
>         cfun->gimple_df->in_ssa_p = true;
>         init_ssa_operands (cfun);
>       }
> -   pop_cfun ();
>   }
>
>   /* Helper function for copy_cfg_body.  Move debug stmts from the end
> --- 2064,2069 ----
> *************** tree_function_versioning (tree old_decl,
> *** 5002,5009 ****
>     struct ipa_replace_map *replace_info;
>     basic_block old_entry_block, bb;
>     VEC (gimple, heap) *init_stmts = VEC_alloc (gimple, heap, 10);
> -
> -   tree old_current_function_decl = current_function_decl;
>     tree vars = NULL_TREE;
>
>     gcc_assert (TREE_CODE (old_decl) == FUNCTION_DECL
> --- 5002,5007 ----
> *************** tree_function_versioning (tree old_decl,
> *** 5073,5086 ****
>     id.transform_return_to_modify = false;
>     id.transform_lang_insert_block = NULL;
>
> -   current_function_decl = new_decl;
>     old_entry_block = ENTRY_BLOCK_PTR_FOR_FUNCTION
>       (DECL_STRUCT_FUNCTION (old_decl));
>     initialize_cfun (new_decl, old_decl,
>                    old_entry_block->count);
>     DECL_STRUCT_FUNCTION (new_decl)->gimple_df->ipa_pta
>       = id.src_cfun->gimple_df->ipa_pta;
> -   push_cfun (DECL_STRUCT_FUNCTION (new_decl));
>
>     /* Copy the function's static chain.  */
>     p = DECL_STRUCT_FUNCTION (old_decl)->static_chain_decl;
> --- 5071,5082 ----
> *************** tree_function_versioning (tree old_decl,
> *** 5234,5242 ****
>     gcc_assert (!id.debug_stmts);
>     VEC_free (gimple, heap, init_stmts);
>     pop_cfun ();
> -   current_function_decl = old_current_function_decl;
> -   gcc_assert (!current_function_decl
> -             || DECL_STRUCT_FUNCTION (current_function_decl) == cfun);
>     return;
>   }
>
> --- 5230,5235 ----
> *** /tmp/QSouyb_tree-profile.c  Thu Aug  9 15:21:47 2012
> --- gcc/tree-profile.c  Tue Aug  7 14:59:02 2012
> *************** tree_profiling (void)
> *** 479,485 ****
>         continue;
>
>         push_cfun (DECL_STRUCT_FUNCTION (node->symbol.decl));
> -       current_function_decl = node->symbol.decl;
>
>         /* Re-set global shared temporary variable for edge-counters.  */
>         gcov_type_tmp_var = NULL_TREE;
> --- 479,484 ----
> *************** tree_profiling (void)
> *** 504,511 ****
>          easy to adjust it, if and when there is some.  */
>         free_dominance_info (CDI_DOMINATORS);
>         free_dominance_info (CDI_POST_DOMINATORS);
> -
> -       current_function_decl = NULL;
>         pop_cfun ();
>       }
>
> --- 503,508 ----
> *************** tree_profiling (void)
> *** 540,546 ****
>         continue;
>
>         push_cfun (DECL_STRUCT_FUNCTION (node->symbol.decl));
> -       current_function_decl = node->symbol.decl;
>
>         FOR_EACH_BB (bb)
>         {
> --- 537,542 ----
> *************** tree_profiling (void)
> *** 557,563 ****
>
>         rebuild_cgraph_edges ();
>
> -       current_function_decl = NULL;
>         pop_cfun ();
>       }
>
> --- 553,558 ----
> *** /tmp/2E21Od_tree-sra.c      Thu Aug  9 15:21:47 2012
> --- gcc/tree-sra.c      Tue Aug  7 15:01:55 2012
> *************** convert_callers_for_node (struct cgraph_
> *** 4612,4618 ****
>
>     for (cs = node->callers; cs; cs = cs->next_caller)
>       {
> -       current_function_decl = cs->caller->symbol.decl;
>         push_cfun (DECL_STRUCT_FUNCTION (cs->caller->symbol.decl));
>
>         if (dump_file)
> --- 4612,4617 ----
> *************** static void
> *** 4641,4654 ****
>   convert_callers (struct cgraph_node *node, tree old_decl,
>                  ipa_parm_adjustment_vec adjustments)
>   {
> -   tree old_cur_fndecl = current_function_decl;
>     basic_block this_block;
>
>     cgraph_for_node_and_aliases (node, convert_callers_for_node,
>                                adjustments, false);
>
> -   current_function_decl = old_cur_fndecl;
> -
>     if (!encountered_recursive_call)
>       return;
>
> --- 4640,4650 ----
> *************** modify_function (struct cgraph_node *nod
> *** 4689,4699 ****
>     rebuild_cgraph_edges ();
>     free_dominance_info (CDI_DOMINATORS);
>     pop_cfun ();
> -   current_function_decl = NULL_TREE;
>
>     new_node = cgraph_function_versioning (node, redirect_callers, NULL, NULL,
>                                          false, NULL, NULL, "isra");
> -   current_function_decl = new_node->symbol.decl;
>     push_cfun (DECL_STRUCT_FUNCTION (new_node->symbol.decl));
>
>     ipa_modify_formal_parameters (current_function_decl, adjustments, "ISRA");
> --- 4685,4693 ----
> *** /tmp/60W3rb_tree-ssa-structalias.c  Thu Aug  9 15:21:47 2012
> --- gcc/tree-ssa-structalias.c  Tue Aug  7 15:42:56 2012
> *************** ipa_pta_execute (void)
> *** 6891,6897 ****
>       {
>         struct function *func;
>         basic_block bb;
> -       tree old_func_decl;
>
>         /* Nodes without a body are not interesting.  */
>         if (!cgraph_function_with_gimple_body_p (node))
> --- 6891,6896 ----
> *************** ipa_pta_execute (void)
> *** 6909,6917 ****
>         }
>
>         func = DECL_STRUCT_FUNCTION (node->symbol.decl);
> -       old_func_decl = current_function_decl;
>         push_cfun (func);
> -       current_function_decl = node->symbol.decl;
>
>         /* For externally visible or attribute used annotated functions use
>          local constraints for their arguments.
> --- 6908,6914 ----
> *************** ipa_pta_execute (void)
> *** 6968,6974 ****
>             }
>         }
>
> -       current_function_decl = old_func_decl;
>         pop_cfun ();
>
>         if (dump_file)
> --- 6965,6970 ----

^ permalink raw reply	[flat|nested] 14+ messages in thread

* Re: [PATCH] Set current_function_decl in {push,pop}_cfun and push_struct_function
  2012-08-09 14:27 [PATCH] Set current_function_decl in {push,pop}_cfun and push_struct_function Martin Jambor
  2012-08-09 14:58 ` Richard Guenther
@ 2012-08-10 14:58 ` Eric Botcazou
  2012-08-15 15:21   ` Martin Jambor
  1 sibling, 1 reply; 14+ messages in thread
From: Eric Botcazou @ 2012-08-10 14:58 UTC (permalink / raw)
  To: Martin Jambor; +Cc: gcc-patches

> - ada/gcc-interface/utils.c:rest_of_subprog_body_compilation calls
>   dump_function which in turns calls dump_function_to_file which calls
>   push_cfun.  But Ada front end has its idea of the
>   current_function_decl and there is no cfun which is an inconsistency
>   which makes push_cfun assert fail.  I "solved" it by temporarily
>   setting current_function_decl to NULL_TREE.  It's just dumping and I
>   thought that dump_function should be considered middle-end and thus
>   middle-end invariants should apply.

If you think that calling dump_function from rest_of_subprog_body_compilation 
is a layering violation, I don't have a problem with replacing it with a more 
"manual" scheme like the one in c-family/c-gimplify.c:c_genericize, provided 
that this yields roughly the same output.

-- 
Eric Botcazou

^ permalink raw reply	[flat|nested] 14+ messages in thread

* Re: [PATCH] Set current_function_decl in {push,pop}_cfun and push_struct_function
  2012-08-10 14:58 ` Eric Botcazou
@ 2012-08-15 15:21   ` Martin Jambor
  2012-08-16  9:30     ` Richard Guenther
  2012-08-21 11:27     ` Martin Jambor
  0 siblings, 2 replies; 14+ messages in thread
From: Martin Jambor @ 2012-08-15 15:21 UTC (permalink / raw)
  To: Eric Botcazou; +Cc: gcc-patches

Hi,

On Fri, Aug 10, 2012 at 04:57:41PM +0200, Eric Botcazou wrote:
> > - ada/gcc-interface/utils.c:rest_of_subprog_body_compilation calls
> >   dump_function which in turns calls dump_function_to_file which calls
> >   push_cfun.  But Ada front end has its idea of the
> >   current_function_decl and there is no cfun which is an inconsistency
> >   which makes push_cfun assert fail.  I "solved" it by temporarily
> >   setting current_function_decl to NULL_TREE.  It's just dumping and I
> >   thought that dump_function should be considered middle-end and thus
> >   middle-end invariants should apply.
> 
> If you think that calling dump_function from rest_of_subprog_body_compilation 
> is a layering violation, I don't have a problem with replacing it with a more 
> "manual" scheme like the one in c-family/c-gimplify.c:c_genericize, provided 
> that this yields roughly the same output.

Richi suggested on IRC that I remove the push/pop_cfun calls from
dump_function_to_file.  The only problem seems to be
dump_histograms_for_stmt (buried in a dump_bb call) which needs a
function to get the value histograms.  Richi suggested to replace the
per function hash with one global one.  I tried that and bumped into
two problems: First, I did not really know when to deallocate the
global hash and all the histograms.  More importantly, the current
gimple verifier (verify_gimple_in_cfg) checks that there are no "dead
histograms" in the hash corresponding to statements no longer in the
function.  With one global hash, it would be very cumbersome to do
this check (add cfun to each histogram?  only when checking is
enabled?).  Hash tables are now in flux anyway so I postponed that
work until the interface settles down.  Nevertheless, I guess I need a
confirmation from maintainers that I can remove the checking if I
continue this way.

When I looked at what would need to be changed if I added a function
parameter to dump_bb, the work list grew very large very quickly.  It
is probably doable, but the change will be quite big, so if anyone
thinks it is a bad idea, please email me to stop.

If I manage to change the dumping in one of the two ways, the call
will not be a layering problem any more as it probably should not be.
At the moment, it probably is.  We'll see.

Thanks,

Martin

^ permalink raw reply	[flat|nested] 14+ messages in thread

* Re: [PATCH] Set current_function_decl in {push,pop}_cfun and push_struct_function
  2012-08-15 15:21   ` Martin Jambor
@ 2012-08-16  9:30     ` Richard Guenther
  2012-08-16 12:40       ` Michael Matz
  2012-08-21 11:27     ` Martin Jambor
  1 sibling, 1 reply; 14+ messages in thread
From: Richard Guenther @ 2012-08-16  9:30 UTC (permalink / raw)
  To: Eric Botcazou, gcc-patches

On Wed, Aug 15, 2012 at 5:21 PM, Martin Jambor <mjambor@suse.cz> wrote:
> Hi,
>
> On Fri, Aug 10, 2012 at 04:57:41PM +0200, Eric Botcazou wrote:
>> > - ada/gcc-interface/utils.c:rest_of_subprog_body_compilation calls
>> >   dump_function which in turns calls dump_function_to_file which calls
>> >   push_cfun.  But Ada front end has its idea of the
>> >   current_function_decl and there is no cfun which is an inconsistency
>> >   which makes push_cfun assert fail.  I "solved" it by temporarily
>> >   setting current_function_decl to NULL_TREE.  It's just dumping and I
>> >   thought that dump_function should be considered middle-end and thus
>> >   middle-end invariants should apply.
>>
>> If you think that calling dump_function from rest_of_subprog_body_compilation
>> is a layering violation, I don't have a problem with replacing it with a more
>> "manual" scheme like the one in c-family/c-gimplify.c:c_genericize, provided
>> that this yields roughly the same output.
>
> Richi suggested on IRC that I remove the push/pop_cfun calls from
> dump_function_to_file.  The only problem seems to be
> dump_histograms_for_stmt (buried in a dump_bb call) which needs a
> function to get the value histograms.  Richi suggested to replace the
> per function hash with one global one.  I tried that and bumped into
> two problems: First, I did not really know when to deallocate the
> global hash and all the histograms.  More importantly, the current
> gimple verifier (verify_gimple_in_cfg) checks that there are no "dead
> histograms" in the hash corresponding to statements no longer in the
> function.  With one global hash, it would be very cumbersome to do
> this check (add cfun to each histogram?  only when checking is
> enabled?).  Hash tables are now in flux anyway so I postponed that
> work until the interface settles down.  Nevertheless, I guess I need a
> confirmation from maintainers that I can remove the checking if I
> continue this way.
>
> When I looked at what would need to be changed if I added a function
> parameter to dump_bb, the work list grew very large very quickly.  It
> is probably doable, but the change will be quite big, so if anyone
> thinks it is a bad idea, please email me to stop.
>
> If I manage to change the dumping in one of the two ways, the call
> will not be a layering problem any more as it probably should not be.
> At the moment, it probably is.  We'll see.

If dumping a statement needs the containing function then we need to
either pass that down, provide a way to get from statement to function,
or stop requiring the function.  Making the hash global is choice three
(deallocating the hash would be when compilation is finished, in which
case you can double-check that it is empty and preserve above checking).
Option one is ok as well, option two is probably either unreliable (going
from gimple_block to function from function scope - but maybe who cares
for dumping?) or expensive (add a pointer from basic_block to struct
function).  I'm fine with both option three (would even save a pointer in
struct function!) or one.

Other opinions?

Thanks,
Richard.

> Thanks,
>
> Martin

^ permalink raw reply	[flat|nested] 14+ messages in thread

* Re: [PATCH] Set current_function_decl in {push,pop}_cfun and push_struct_function
  2012-08-16  9:30     ` Richard Guenther
@ 2012-08-16 12:40       ` Michael Matz
  2012-08-16 13:23         ` Diego Novillo
  0 siblings, 1 reply; 14+ messages in thread
From: Michael Matz @ 2012-08-16 12:40 UTC (permalink / raw)
  To: Richard Guenther; +Cc: Eric Botcazou, gcc-patches

Hi,

On Thu, 16 Aug 2012, Richard Guenther wrote:

> If dumping a statement needs the containing function then we need to 
> either pass that down, provide a way to get from statement to function, 
> or stop requiring the function.  Making the hash global is choice three 
> (deallocating the hash would be when compilation is finished, in which 
> case you can double-check that it is empty and preserve above checking). 
> Option one is ok as well, option two is probably either unreliable 
> (going from gimple_block to function from function scope - but maybe who 
> cares for dumping?) or expensive (add a pointer from basic_block to 
> struct function).  I'm fine with both option three (would even save a 
> pointer in struct function!) or one.
> 
> Other opinions?

Actually I must say, that none of the above three options appeal to me 
very much, and that the current solution (passing cfun via a global 
variable) is better than any of these:

1) passing it down in arguments: uglifies interface for a very special 
   situation.
3) making the hash global is a layering violation in its own, and for 
   instance would complicate a scheme where the memory for instructions 
   (and their histograms) comes from per-function pools.
2) that's actually the most appealing one from a user interface, i.e. if 
   there's a generic way of mapping gimple -> FUNCTION_DECL.  Certainly 
   not at the cost of an additional pointer in each bb, but there are 
   other schemes that we could use, for instance:
   Every function has an ENTRY and EXIT block.  That one for certain is 
   reachable via going bb->prev_bb until you hit the end.  The entry block 
   doesn't contain much interesting things, so we for instance can reuse, 
   I don't know, the loop_father pointer to actually point to the 
   function_decl containing it.

   Looking up the function from a bb would hence be a fairly expensive 
   operation (walking the block chain), so it requires some care to use 
   it, but I think that's okay.


Ciao,
Michael.

^ permalink raw reply	[flat|nested] 14+ messages in thread

* Re: [PATCH] Set current_function_decl in {push,pop}_cfun and push_struct_function
  2012-08-16 12:40       ` Michael Matz
@ 2012-08-16 13:23         ` Diego Novillo
  2012-08-16 14:21           ` Michael Matz
  0 siblings, 1 reply; 14+ messages in thread
From: Diego Novillo @ 2012-08-16 13:23 UTC (permalink / raw)
  To: Michael Matz; +Cc: Richard Guenther, Eric Botcazou, gcc-patches

On Thu, Aug 16, 2012 at 8:40 AM, Michael Matz <matz@suse.de> wrote:
> Hi,
>
> On Thu, 16 Aug 2012, Richard Guenther wrote:
>
>> If dumping a statement needs the containing function then we need to
>> either pass that down, provide a way to get from statement to function,
>> or stop requiring the function.  Making the hash global is choice three
>> (deallocating the hash would be when compilation is finished, in which
>> case you can double-check that it is empty and preserve above checking).
>> Option one is ok as well, option two is probably either unreliable
>> (going from gimple_block to function from function scope - but maybe who
>> cares for dumping?) or expensive (add a pointer from basic_block to
>> struct function).  I'm fine with both option three (would even save a
>> pointer in struct function!) or one.
>>
>> Other opinions?
>
> Actually I must say, that none of the above three options appeal to me
> very much, and that the current solution (passing cfun via a global
> variable) is better than any of these:
>
> 1) passing it down in arguments: uglifies interface for a very special
>    situation.
> 3) making the hash global is a layering violation in its own, and for
>    instance would complicate a scheme where the memory for instructions
>    (and their histograms) comes from per-function pools.
> 2) that's actually the most appealing one from a user interface, i.e. if
>    there's a generic way of mapping gimple -> FUNCTION_DECL.  Certainly
>    not at the cost of an additional pointer in each bb, but there are
>    other schemes that we could use, for instance:
>    Every function has an ENTRY and EXIT block.  That one for certain is
>    reachable via going bb->prev_bb until you hit the end.  The entry block
>    doesn't contain much interesting things, so we for instance can reuse,
>    I don't know, the loop_father pointer to actually point to the
>    function_decl containing it.
>
>    Looking up the function from a bb would hence be a fairly expensive
>    operation (walking the block chain), so it requires some care to use
>    it, but I think that's okay.

I like this approach, particularly since it would be used in contexts
where there is no simpler scheme.  I'm not crazy about overloading
unused fields, but it's fine if we wrap it around a special accessor.
I suppose we could also make ENTRY/EXIT be a base class for
basic_block and use a real field (but that can wait).

There are other pieces of data that are "global" but
context-dependent.  I wonder if it wouldn't make sense to encapsulate
them in some class that is controlled by the pass manager and gets
updated as it moves from function to function (it would contain things
like cfun, current_function_decl, etc).

Diego.

^ permalink raw reply	[flat|nested] 14+ messages in thread

* Re: [PATCH] Set current_function_decl in {push,pop}_cfun and push_struct_function
  2012-08-16 13:23         ` Diego Novillo
@ 2012-08-16 14:21           ` Michael Matz
  2012-08-16 14:26             ` Diego Novillo
  0 siblings, 1 reply; 14+ messages in thread
From: Michael Matz @ 2012-08-16 14:21 UTC (permalink / raw)
  To: Diego Novillo; +Cc: Richard Guenther, Eric Botcazou, gcc-patches

Hi,

On Thu, 16 Aug 2012, Diego Novillo wrote:

> I like this approach, particularly since it would be used in contexts 
> where there is no simpler scheme.  I'm not crazy about overloading 
> unused fields, but it's fine if we wrap it around a special accessor. I 
> suppose we could also make ENTRY/EXIT be a base class for basic_block 
> and use a real field (but that can wait).

Actually the other way around (ENTRY/EXIT be a subclass), as it would be 
an additional field to the normal basic blocks.  But for central data 
structures I'm usually of the opinion that jumping through hoops just to 
not enlarge them is quite acceptable :)

> There are other pieces of data that are "global" but context-dependent.  
> I wonder if it wouldn't make sense to encapsulate them in some class 
> that is controlled by the pass manager and gets updated as it moves from 
> function to function (it would contain things like cfun, 
> current_function_decl, etc).

And on that topic: I think it makes sense to eventually get rid of one or 
the other, current_function_decl is always (well, mostly) cfun->decl, if 
cfun happens to be set.  I know there are some roadblocks in front of that 
goal, but still.

Ciao,
Michael.

^ permalink raw reply	[flat|nested] 14+ messages in thread

* Re: [PATCH] Set current_function_decl in {push,pop}_cfun and push_struct_function
  2012-08-16 14:21           ` Michael Matz
@ 2012-08-16 14:26             ` Diego Novillo
  0 siblings, 0 replies; 14+ messages in thread
From: Diego Novillo @ 2012-08-16 14:26 UTC (permalink / raw)
  To: Michael Matz; +Cc: Richard Guenther, Eric Botcazou, gcc-patches

On Thu, Aug 16, 2012 at 10:21 AM, Michael Matz <matz@suse.de> wrote:
> Hi,
>
> On Thu, 16 Aug 2012, Diego Novillo wrote:
>
>> I like this approach, particularly since it would be used in contexts
>> where there is no simpler scheme.  I'm not crazy about overloading
>> unused fields, but it's fine if we wrap it around a special accessor. I
>> suppose we could also make ENTRY/EXIT be a base class for basic_block
>> and use a real field (but that can wait).
>
> Actually the other way around (ENTRY/EXIT be a subclass), as it would be

Yeah, sorry.

> an additional field to the normal basic blocks.  But for central data
> structures I'm usually of the opinion that jumping through hoops just to
> not enlarge them is quite acceptable :)

Yeah, adding a full word when it's only used in a few places does not
seem like a good tradeoff.

>> There are other pieces of data that are "global" but context-dependent.
>> I wonder if it wouldn't make sense to encapsulate them in some class
>> that is controlled by the pass manager and gets updated as it moves from
>> function to function (it would contain things like cfun,
>> current_function_decl, etc).
>
> And on that topic: I think it makes sense to eventually get rid of one or
> the other, current_function_decl is always (well, mostly) cfun->decl, if
> cfun happens to be set.  I know there are some roadblocks in front of that
> goal, but still.

Agreed.


Diego.

^ permalink raw reply	[flat|nested] 14+ messages in thread

* Re: [PATCH] Set current_function_decl in {push,pop}_cfun and push_struct_function
  2012-08-15 15:21   ` Martin Jambor
  2012-08-16  9:30     ` Richard Guenther
@ 2012-08-21 11:27     ` Martin Jambor
  2012-08-21 11:31       ` Richard Guenther
  1 sibling, 1 reply; 14+ messages in thread
From: Martin Jambor @ 2012-08-21 11:27 UTC (permalink / raw)
  To: Eric Botcazou, gcc-patches

On Wed, Aug 15, 2012 at 05:21:04PM +0200, Martin Jambor wrote:
> Hi,
> 
> On Fri, Aug 10, 2012 at 04:57:41PM +0200, Eric Botcazou wrote:
> > > - ada/gcc-interface/utils.c:rest_of_subprog_body_compilation calls
> > >   dump_function which in turns calls dump_function_to_file which calls
> > >   push_cfun.  But Ada front end has its idea of the
> > >   current_function_decl and there is no cfun which is an inconsistency
> > >   which makes push_cfun assert fail.  I "solved" it by temporarily
> > >   setting current_function_decl to NULL_TREE.  It's just dumping and I
> > >   thought that dump_function should be considered middle-end and thus
> > >   middle-end invariants should apply.
> > 
> > If you think that calling dump_function from rest_of_subprog_body_compilation 
> > is a layering violation, I don't have a problem with replacing it with a more 
> > "manual" scheme like the one in c-family/c-gimplify.c:c_genericize, provided 
> > that this yields roughly the same output.
> 
> Richi suggested on IRC that I remove the push/pop_cfun calls from
> dump_function_to_file.  The only problem seems to be
> dump_histograms_for_stmt

Yesterday I actually tried and it is not the only problem.  Another
one is dump_function_to_file->dump_bb->maybe_hot_bb_p which uses cfun
to read profile_status.  There may be others, this one just blew up
first when I set cfun to NULL.  And in future someone is quite likely
to need cfun to dump something new too.

At the same time, re-implementing dumping
c-family/c-gimplify.c:c_genericize when dump_function suffices seems
ugly to me.

So I am going to declare dump_function a front-end interface and use
set_cfun in my original patch in dump_function_to_file like we do in
other such functions.

I hope that will be OK.  Thanks,

Martin

PS: Each of various alternatives proposed in this thread had someone
who opposed it.  If there is a consensus that some of them should be
implemented anyway (like global value profiling hash), I am willing to
do that, I just do not want to end up bickering about the result.

^ permalink raw reply	[flat|nested] 14+ messages in thread

* Re: [PATCH] Set current_function_decl in {push,pop}_cfun and push_struct_function
  2012-08-21 11:27     ` Martin Jambor
@ 2012-08-21 11:31       ` Richard Guenther
  2012-08-22 13:05         ` Martin Jambor
  0 siblings, 1 reply; 14+ messages in thread
From: Richard Guenther @ 2012-08-21 11:31 UTC (permalink / raw)
  To: Eric Botcazou, gcc-patches

On Tue, Aug 21, 2012 at 1:27 PM, Martin Jambor <mjambor@suse.cz> wrote:
> On Wed, Aug 15, 2012 at 05:21:04PM +0200, Martin Jambor wrote:
>> Hi,
>>
>> On Fri, Aug 10, 2012 at 04:57:41PM +0200, Eric Botcazou wrote:
>> > > - ada/gcc-interface/utils.c:rest_of_subprog_body_compilation calls
>> > >   dump_function which in turns calls dump_function_to_file which calls
>> > >   push_cfun.  But Ada front end has its idea of the
>> > >   current_function_decl and there is no cfun which is an inconsistency
>> > >   which makes push_cfun assert fail.  I "solved" it by temporarily
>> > >   setting current_function_decl to NULL_TREE.  It's just dumping and I
>> > >   thought that dump_function should be considered middle-end and thus
>> > >   middle-end invariants should apply.
>> >
>> > If you think that calling dump_function from rest_of_subprog_body_compilation
>> > is a layering violation, I don't have a problem with replacing it with a more
>> > "manual" scheme like the one in c-family/c-gimplify.c:c_genericize, provided
>> > that this yields roughly the same output.
>>
>> Richi suggested on IRC that I remove the push/pop_cfun calls from
>> dump_function_to_file.  The only problem seems to be
>> dump_histograms_for_stmt
>
> Yesterday I actually tried and it is not the only problem.  Another
> one is dump_function_to_file->dump_bb->maybe_hot_bb_p which uses cfun
> to read profile_status.  There may be others, this one just blew up
> first when I set cfun to NULL.  And in future someone is quite likely
> to need cfun to dump something new too.
>
> At the same time, re-implementing dumping
> c-family/c-gimplify.c:c_genericize when dump_function suffices seems
> ugly to me.
>
> So I am going to declare dump_function a front-end interface and use
> set_cfun in my original patch in dump_function_to_file like we do in
> other such functions.
>
> I hope that will be OK.  Thanks,

Setting cfun has side-effects of switching target stuff which might have
code-generation side-effects because of implementation issues we have
with target/optimize attributes.  So I don't think cfun should be changed
just for dumping.

Can you instead just set current_function_decl and access
struct function via DECL_STRUCT_FUNCTION in the dumpers then?
After all, it it is a front-end interface, the frontend way of saying
"this is the current function" is to set current_function_decl, not the
middle-end cfun.

Richard.

> Martin
>
> PS: Each of various alternatives proposed in this thread had someone
> who opposed it.  If there is a consensus that some of them should be
> implemented anyway (like global value profiling hash), I am willing to
> do that, I just do not want to end up bickering about the result.

^ permalink raw reply	[flat|nested] 14+ messages in thread

* Re: [PATCH] Set current_function_decl in {push,pop}_cfun and push_struct_function
  2012-08-21 11:31       ` Richard Guenther
@ 2012-08-22 13:05         ` Martin Jambor
  2012-08-22 13:38           ` Richard Guenther
  0 siblings, 1 reply; 14+ messages in thread
From: Martin Jambor @ 2012-08-22 13:05 UTC (permalink / raw)
  To: Richard Guenther; +Cc: Eric Botcazou, gcc-patches

Hi,

On Tue, Aug 21, 2012 at 01:30:47PM +0200, Richard Guenther wrote:
> On Tue, Aug 21, 2012 at 1:27 PM, Martin Jambor <mjambor@suse.cz> wrote:
> > On Wed, Aug 15, 2012 at 05:21:04PM +0200, Martin Jambor wrote:
> >> Hi,
> >>
> >> On Fri, Aug 10, 2012 at 04:57:41PM +0200, Eric Botcazou wrote:
> >> > > - ada/gcc-interface/utils.c:rest_of_subprog_body_compilation calls
> >> > >   dump_function which in turns calls dump_function_to_file which calls
> >> > >   push_cfun.  But Ada front end has its idea of the
> >> > >   current_function_decl and there is no cfun which is an inconsistency
> >> > >   which makes push_cfun assert fail.  I "solved" it by temporarily
> >> > >   setting current_function_decl to NULL_TREE.  It's just dumping and I
> >> > >   thought that dump_function should be considered middle-end and thus
> >> > >   middle-end invariants should apply.
> >> >
> >> > If you think that calling dump_function from rest_of_subprog_body_compilation
> >> > is a layering violation, I don't have a problem with replacing it with a more
> >> > "manual" scheme like the one in c-family/c-gimplify.c:c_genericize, provided
> >> > that this yields roughly the same output.
> >>
> >> Richi suggested on IRC that I remove the push/pop_cfun calls from
> >> dump_function_to_file.  The only problem seems to be
> >> dump_histograms_for_stmt
> >
> > Yesterday I actually tried and it is not the only problem.  Another
> > one is dump_function_to_file->dump_bb->maybe_hot_bb_p which uses cfun
> > to read profile_status.  There may be others, this one just blew up
> > first when I set cfun to NULL.  And in future someone is quite likely
> > to need cfun to dump something new too.
> >
> > At the same time, re-implementing dumping
> > c-family/c-gimplify.c:c_genericize when dump_function suffices seems
> > ugly to me.
> >
> > So I am going to declare dump_function a front-end interface and use
> > set_cfun in my original patch in dump_function_to_file like we do in
> > other such functions.
> >
> > I hope that will be OK.  Thanks,
> 
> Setting cfun has side-effects of switching target stuff which might have
> code-generation side-effects because of implementation issues we have
> with target/optimize attributes.  So I don't think cfun should be changed
> just for dumping.
> 
> Can you instead just set current_function_decl and access
> struct function via DECL_STRUCT_FUNCTION in the dumpers then?
> After all, it it is a front-end interface, the frontend way of saying
> "this is the current function" is to set current_function_decl, not the
> middle-end cfun.
> 

Like the following?  Tested and bootstrapped on x86_64-linux, it does
help avoid the ada hunk in my previous patch.  OK for trunk?

Thanks,

Martin


2012-08-21  Martin Jambor  <mjambor@suse.cz>

	* predict.c (maybe_hot_frequency_p): New parameter fun.  Use its decl
	instead of current_function_decl, use profile_status_for_function and
	ENTRY_BLOCK_PTR_FOR_FUNCTION with fun instead of their cfun variants.
	(maybe_hot_count_p): New parameter fun, use
	profile_status_for_function instead of its cfun_variant.
	(maybe_hot_bb_p): New parameter fun, checking-assert it, pass it to
	all callees.
	(maybe_hot_edge_p): Pass cfun to maybe_hot_count_p and
	maybe_hot_frequency_p.
	(probably_never_executed_bb_p): New parameter fun, use its decl
	instead of current_function_decl.
	(optimize_bb_for_size_p): Pass cfun to maybe_hot_bb_p.
	(rtl_profile_for_bb): Likewise.
	(compute_function_frequency): Pass cfun to maybe_hot_bb_p and
	probably_never_executed_bb_p.
	* tree-ssa-operands.c (ssa_operands_active): New operator fun.  Use it
	instead of cfun.
	(update_stmt_operands): Pass cfun as an argument of
	ssa_operands_active.
	(swap_tree_operands): Likewise.
	* gimple-iterator.c (update_modified_stmt): Likewise.
	(update_modified_stmts): Likewise.
	* tree-flow-inline.h (delink_stmt_imm_use): Likewise.
	* tree-ssa.c (delete_tree_ssa): Likewise.
	* bb-reorder.c (bb_to_key): Pass cfun to probably_never_executed_bb_p.
	(push_to_next_round_p): Likewise.
	(find_rarely_executed_basic_blocks_and_crossing_edges ): Likewise.
	* cfg.c: Inlude tree.h.
	(check_bb_profile): Use profile_status_for_function,
	EXIT_BLOCK_PTR_FOR_FUNCTION and ENTRY_BLOCK_PTR_FOR_FUNCTION with
	DECL_STRUCT_FUNCTION (current_function_decl) instead of their cfun
	variants.
	(dump_bb_info): Pass DECL_STRUCT_FUNCTION (current_function_decl) to
	maybe_hot_bb_p and probably_never_executed_bb_p.
	* gimple-pretty-print.c (gimple_dump_bb_buff): Checking-assert that
	DECL_STRUCT_FUNCTION (current_function_decl) is not NULL.  Pass it to
	dump_histograms_for_stmt.
	(dump_gimple_mem_ops): Pass DECL_STRUCT_FUNCTION (current_function_decl)
	as an argument to dump_gimple_mem_ops.
	* tree-cfg.c (dump_function_to_file): Rename parameter fn to fndecl.
	Do not change cfun.  Change and restore current_function_decl.
	* Makefile.in (cfg.o): Include TREE_H in dependencies.



*** /tmp/Hif6Ee_Makefile.in	Wed Aug 22 15:02:30 2012
--- gcc/Makefile.in	Wed Aug 22 11:53:02 2012
*************** auto-inc-dec.o : auto-inc-dec.c $(CONFIG
*** 3047,3053 ****
     $(REGS_H) $(FLAGS_H) $(FUNCTION_H) $(EXCEPT_H) $(DIAGNOSTIC_CORE_H) $(RECOG_H) \
     $(EXPR_H) $(TREE_PASS_H) $(DF_H) $(DBGCNT_H) $(TARGET_H)
  cfg.o : cfg.c $(CONFIG_H) $(SYSTEM_H) coretypes.h dumpfile.h $(DIAGNOSTIC_CORE_H) \
!    $(GGC_H) $(OBSTACK_H) alloc-pool.h $(HASHTAB_H) $(CFGLOOP_H) $(BASIC_BLOCK_H)
  cfghooks.o: cfghooks.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) $(RTL_H) \
     $(TREE_H) $(BASIC_BLOCK_H) $(TREE_FLOW_H) $(TIMEVAR_H) toplev.h $(DIAGNOSTIC_CORE_H) $(CFGLOOP_H)
  cfgexpand.o : cfgexpand.c $(TREE_FLOW_H) $(CONFIG_H) $(SYSTEM_H) \
--- 3047,3054 ----
     $(REGS_H) $(FLAGS_H) $(FUNCTION_H) $(EXCEPT_H) $(DIAGNOSTIC_CORE_H) $(RECOG_H) \
     $(EXPR_H) $(TREE_PASS_H) $(DF_H) $(DBGCNT_H) $(TARGET_H)
  cfg.o : cfg.c $(CONFIG_H) $(SYSTEM_H) coretypes.h dumpfile.h $(DIAGNOSTIC_CORE_H) \
!    $(GGC_H) $(OBSTACK_H) alloc-pool.h $(HASHTAB_H) $(CFGLOOP_H) $(TREE_H) \
!    $(BASIC_BLOCK_H)
  cfghooks.o: cfghooks.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) $(RTL_H) \
     $(TREE_H) $(BASIC_BLOCK_H) $(TREE_FLOW_H) $(TIMEVAR_H) toplev.h $(DIAGNOSTIC_CORE_H) $(CFGLOOP_H)
  cfgexpand.o : cfgexpand.c $(TREE_FLOW_H) $(CONFIG_H) $(SYSTEM_H) \
*** /tmp/5C1Cob_basic-block.h	Wed Aug 22 15:02:30 2012
--- gcc/basic-block.h	Wed Aug 22 11:53:02 2012
*************** extern struct edge_list *pre_edge_rev_lc
*** 693,701 ****
  extern void compute_available (sbitmap *, sbitmap *, sbitmap *, sbitmap *);
  
  /* In predict.c */
! extern bool maybe_hot_bb_p (const_basic_block);
  extern bool maybe_hot_edge_p (edge);
! extern bool probably_never_executed_bb_p (const_basic_block);
  extern bool optimize_bb_for_size_p (const_basic_block);
  extern bool optimize_bb_for_speed_p (const_basic_block);
  extern bool optimize_edge_for_size_p (edge);
--- 693,701 ----
  extern void compute_available (sbitmap *, sbitmap *, sbitmap *, sbitmap *);
  
  /* In predict.c */
! extern bool maybe_hot_bb_p (struct function *, const_basic_block);
  extern bool maybe_hot_edge_p (edge);
! extern bool probably_never_executed_bb_p (struct function *, const_basic_block);
  extern bool optimize_bb_for_size_p (const_basic_block);
  extern bool optimize_bb_for_speed_p (const_basic_block);
  extern bool optimize_edge_for_size_p (edge);
*** /tmp/d7KhXa_bb-reorder.c	Wed Aug 22 15:02:30 2012
--- gcc/bb-reorder.c	Wed Aug 22 11:53:02 2012
*************** push_to_next_round_p (const_basic_block
*** 226,232 ****
  
    block_not_hot_enough = (bb->frequency < exec_th
  			  || bb->count < count_th
! 			  || probably_never_executed_bb_p (bb));
  
    if (there_exists_another_round
        && block_not_hot_enough)
--- 226,232 ----
  
    block_not_hot_enough = (bb->frequency < exec_th
  			  || bb->count < count_th
! 			  || probably_never_executed_bb_p (cfun, bb));
  
    if (there_exists_another_round
        && block_not_hot_enough)
*************** bb_to_key (basic_block bb)
*** 823,829 ****
    /* Do not start in probably never executed blocks.  */
  
    if (BB_PARTITION (bb) == BB_COLD_PARTITION
!       || probably_never_executed_bb_p (bb))
      return BB_FREQ_MAX;
  
    /* Prefer blocks whose predecessor is an end of some trace
--- 823,829 ----
    /* Do not start in probably never executed blocks.  */
  
    if (BB_PARTITION (bb) == BB_COLD_PARTITION
!       || probably_never_executed_bb_p (cfun, bb))
      return BB_FREQ_MAX;
  
    /* Prefer blocks whose predecessor is an end of some trace
*************** find_rarely_executed_basic_blocks_and_cr
*** 1308,1314 ****
    /* Mark which partition (hot/cold) each basic block belongs in.  */
    FOR_EACH_BB (bb)
      {
!       if (probably_never_executed_bb_p (bb))
  	BB_SET_PARTITION (bb, BB_COLD_PARTITION);
        else
  	BB_SET_PARTITION (bb, BB_HOT_PARTITION);
--- 1308,1314 ----
    /* Mark which partition (hot/cold) each basic block belongs in.  */
    FOR_EACH_BB (bb)
      {
!       if (probably_never_executed_bb_p (cfun, bb))
  	BB_SET_PARTITION (bb, BB_COLD_PARTITION);
        else
  	BB_SET_PARTITION (bb, BB_HOT_PARTITION);
*** /tmp/5erstd_cfg.c	Wed Aug 22 15:02:30 2012
--- gcc/cfg.c	Wed Aug 22 11:53:02 2012
*************** along with GCC; see the file COPYING3.
*** 55,60 ****
--- 55,61 ----
  #include "ggc.h"
  #include "hashtab.h"
  #include "alloc-pool.h"
+ #include "tree.h"
  #include "basic-block.h"
  #include "df.h"
  #include "cfgloop.h" /* FIXME: For struct loop.  */
*************** check_bb_profile (basic_block bb, FILE *
*** 404,417 ****
    int sum = 0;
    gcov_type lsum;
    edge_iterator ei;
    char *s_indent = (char *) alloca ((size_t) indent + 1);
    memset ((void *) s_indent, ' ', (size_t) indent);
    s_indent[indent] = '\0';
  
!   if (profile_status == PROFILE_ABSENT)
      return;
  
!   if (bb != EXIT_BLOCK_PTR)
      {
        FOR_EACH_EDGE (e, ei, bb->succs)
  	sum += e->probability;
--- 405,419 ----
    int sum = 0;
    gcov_type lsum;
    edge_iterator ei;
+   struct function *fun = DECL_STRUCT_FUNCTION (current_function_decl);
    char *s_indent = (char *) alloca ((size_t) indent + 1);
    memset ((void *) s_indent, ' ', (size_t) indent);
    s_indent[indent] = '\0';
  
!   if (profile_status_for_function (fun) == PROFILE_ABSENT)
      return;
  
!   if (bb != EXIT_BLOCK_PTR_FOR_FUNCTION (fun))
      {
        FOR_EACH_EDGE (e, ei, bb->succs)
  	sum += e->probability;
*************** check_bb_profile (basic_block bb, FILE *
*** 428,434 ****
  		 (flags & TDF_COMMENT) ? ";; " : "", s_indent,
  		 (int) lsum, (int) bb->count);
      }
!   if (bb != ENTRY_BLOCK_PTR)
      {
        sum = 0;
        FOR_EACH_EDGE (e, ei, bb->preds)
--- 430,436 ----
  		 (flags & TDF_COMMENT) ? ";; " : "", s_indent,
  		 (int) lsum, (int) bb->count);
      }
!     if (bb != ENTRY_BLOCK_PTR_FOR_FUNCTION (fun))
      {
        sum = 0;
        FOR_EACH_EDGE (e, ei, bb->preds)
*************** dump_bb_info (FILE *outf, basic_block bb
*** 701,712 ****
  	       s_indent, bb->index, bb_loop_depth (bb));
        if (flags & TDF_DETAILS)
  	{
  	  fprintf (outf, ", count " HOST_WIDEST_INT_PRINT_DEC,
  		   (HOST_WIDEST_INT) bb->count);
  	  fprintf (outf, ", freq %i", bb->frequency);
! 	  if (maybe_hot_bb_p (bb))
  	    fputs (", maybe hot", outf);
! 	  if (probably_never_executed_bb_p (bb))
  	    fputs (", probably never executed", outf);
  	}
        fputc ('\n', outf);
--- 703,715 ----
  	       s_indent, bb->index, bb_loop_depth (bb));
        if (flags & TDF_DETAILS)
  	{
+ 	  struct function *fun = DECL_STRUCT_FUNCTION (current_function_decl);
  	  fprintf (outf, ", count " HOST_WIDEST_INT_PRINT_DEC,
  		   (HOST_WIDEST_INT) bb->count);
  	  fprintf (outf, ", freq %i", bb->frequency);
! 	  if (maybe_hot_bb_p (fun, bb))
  	    fputs (", maybe hot", outf);
! 	  if (probably_never_executed_bb_p (fun, bb))
  	    fputs (", probably never executed", outf);
  	}
        fputc ('\n', outf);
*** /tmp/Z3eGIa_gimple-iterator.c	Wed Aug 22 15:02:30 2012
--- gcc/gimple-iterator.c	Wed Aug 22 11:53:02 2012
*************** along with GCC; see the file COPYING3.
*** 33,39 ****
  static inline void
  update_modified_stmt (gimple stmt)
  {
!   if (!ssa_operands_active ())
      return;
    update_stmt_if_modified (stmt);
  }
--- 33,39 ----
  static inline void
  update_modified_stmt (gimple stmt)
  {
!   if (!ssa_operands_active (cfun))
      return;
    update_stmt_if_modified (stmt);
  }
*************** update_modified_stmts (gimple_seq seq)
*** 46,52 ****
  {
    gimple_stmt_iterator gsi;
  
!   if (!ssa_operands_active ())
      return;
    for (gsi = gsi_start (seq); !gsi_end_p (gsi); gsi_next (&gsi))
      update_stmt_if_modified (gsi_stmt (gsi));
--- 46,52 ----
  {
    gimple_stmt_iterator gsi;
  
!   if (!ssa_operands_active (cfun))
      return;
    for (gsi = gsi_start (seq); !gsi_end_p (gsi); gsi_next (&gsi))
      update_stmt_if_modified (gsi_stmt (gsi));
*** /tmp/1clpne_gimple-pretty-print.c	Wed Aug 22 15:02:30 2012
--- gcc/gimple-pretty-print.c	Wed Aug 22 11:53:02 2012
*************** dump_gimple_mem_ops (pretty_printer *buf
*** 1817,1823 ****
    tree vdef = gimple_vdef (gs);
    tree vuse = gimple_vuse (gs);
  
!   if (!ssa_operands_active () || !gimple_references_memory_p (gs))
      return;
  
    if (vdef != NULL_TREE)
--- 1817,1824 ----
    tree vdef = gimple_vdef (gs);
    tree vuse = gimple_vuse (gs);
  
!   if (!ssa_operands_active (DECL_STRUCT_FUNCTION (current_function_decl))
!       || !gimple_references_memory_p (gs))
      return;
  
    if (vdef != NULL_TREE)
*************** gimple_dump_bb_buff (pretty_printer *buf
*** 2256,2262 ****
        INDENT (curr_indent);
        dump_gimple_stmt (buffer, stmt, curr_indent, flags);
        pp_newline_and_flush (buffer);
!       dump_histograms_for_stmt (cfun, buffer->buffer->stream, stmt);
      }
  
    dump_implicit_edges (buffer, bb, indent, flags);
--- 2257,2265 ----
        INDENT (curr_indent);
        dump_gimple_stmt (buffer, stmt, curr_indent, flags);
        pp_newline_and_flush (buffer);
!       gcc_checking_assert (DECL_STRUCT_FUNCTION (current_function_decl));
!       dump_histograms_for_stmt (DECL_STRUCT_FUNCTION (current_function_decl),
! 				buffer->buffer->stream, stmt);
      }
  
    dump_implicit_edges (buffer, bb, indent, flags);
*** /tmp/nsrnlc_predict.c	Wed Aug 22 15:02:30 2012
--- gcc/predict.c	Wed Aug 22 11:53:02 2012
*************** static const struct predictor_info predi
*** 108,116 ****
  /* Return TRUE if frequency FREQ is considered to be hot.  */
  
  static inline bool
! maybe_hot_frequency_p (int freq)
  {
!   struct cgraph_node *node = cgraph_get_node (current_function_decl);
    if (!profile_info || !flag_branch_probabilities)
      {
        if (node->frequency == NODE_FREQUENCY_UNLIKELY_EXECUTED)
--- 108,116 ----
  /* Return TRUE if frequency FREQ is considered to be hot.  */
  
  static inline bool
! maybe_hot_frequency_p (struct function *fun, int freq)
  {
!   struct cgraph_node *node = cgraph_get_node (fun->decl);
    if (!profile_info || !flag_branch_probabilities)
      {
        if (node->frequency == NODE_FREQUENCY_UNLIKELY_EXECUTED)
*************** maybe_hot_frequency_p (int freq)
*** 118,129 ****
        if (node->frequency == NODE_FREQUENCY_HOT)
          return true;
      }
!   if (profile_status == PROFILE_ABSENT)
      return true;
    if (node->frequency == NODE_FREQUENCY_EXECUTED_ONCE
!       && freq < (ENTRY_BLOCK_PTR->frequency * 2 / 3))
      return false;
!   if (freq < ENTRY_BLOCK_PTR->frequency / PARAM_VALUE (HOT_BB_FREQUENCY_FRACTION))
      return false;
    return true;
  }
--- 118,130 ----
        if (node->frequency == NODE_FREQUENCY_HOT)
          return true;
      }
!   if (profile_status_for_function (fun) == PROFILE_ABSENT)
      return true;
    if (node->frequency == NODE_FREQUENCY_EXECUTED_ONCE
!       && freq < (ENTRY_BLOCK_PTR_FOR_FUNCTION (fun)->frequency * 2 / 3))
      return false;
!   if (freq < (ENTRY_BLOCK_PTR_FOR_FUNCTION (fun)->frequency
! 	      / PARAM_VALUE (HOT_BB_FREQUENCY_FRACTION)))
      return false;
    return true;
  }
*************** maybe_hot_frequency_p (int freq)
*** 131,139 ****
  /* Return TRUE if frequency FREQ is considered to be hot.  */
  
  static inline bool
! maybe_hot_count_p (gcov_type count)
  {
!   if (profile_status != PROFILE_READ)
      return true;
    /* Code executed at most once is not hot.  */
    if (profile_info->runs >= count)
--- 132,140 ----
  /* Return TRUE if frequency FREQ is considered to be hot.  */
  
  static inline bool
! maybe_hot_count_p (struct function *fun, gcov_type count)
  {
!   if (profile_status_for_function (fun) != PROFILE_READ)
      return true;
    /* Code executed at most once is not hot.  */
    if (profile_info->runs >= count)
*************** maybe_hot_count_p (gcov_type count)
*** 146,158 ****
     for maximal performance.  */
  
  bool
! maybe_hot_bb_p (const_basic_block bb)
  {
!   /* Make sure CFUN exists, for dump_bb_info.  */
!   gcc_assert (cfun);
!   if (profile_status == PROFILE_READ)
!     return maybe_hot_count_p (bb->count);
!   return maybe_hot_frequency_p (bb->frequency);
  }
  
  /* Return true if the call can be hot.  */
--- 147,158 ----
     for maximal performance.  */
  
  bool
! maybe_hot_bb_p (struct function *fun, const_basic_block bb)
  {
!   gcc_checking_assert (fun);
!   if (profile_status_for_function (fun) == PROFILE_READ)
!     return maybe_hot_count_p (fun, bb->count);
!   return maybe_hot_frequency_p (fun, bb->frequency);
  }
  
  /* Return true if the call can be hot.  */
*************** bool
*** 193,214 ****
  maybe_hot_edge_p (edge e)
  {
    if (profile_status == PROFILE_READ)
!     return maybe_hot_count_p (e->count);
!   return maybe_hot_frequency_p (EDGE_FREQUENCY (e));
  }
  
  
  /* Return true in case BB is probably never executed.  */
  
  bool
! probably_never_executed_bb_p (const_basic_block bb)
  {
!   /* Make sure CFUN exists, for dump_bb_info.  */
!   gcc_assert (cfun);
    if (profile_info && flag_branch_probabilities)
      return ((bb->count + profile_info->runs / 2) / profile_info->runs) == 0;
    if ((!profile_info || !flag_branch_probabilities)
!       && (cgraph_get_node (current_function_decl)->frequency
  	  == NODE_FREQUENCY_UNLIKELY_EXECUTED))
      return true;
    return false;
--- 193,213 ----
  maybe_hot_edge_p (edge e)
  {
    if (profile_status == PROFILE_READ)
!     return maybe_hot_count_p (cfun, e->count);
!   return maybe_hot_frequency_p (cfun, EDGE_FREQUENCY (e));
  }
  
  
  /* Return true in case BB is probably never executed.  */
  
  bool
! probably_never_executed_bb_p (struct function *fun, const_basic_block bb)
  {
!   gcc_checking_assert (fun);
    if (profile_info && flag_branch_probabilities)
      return ((bb->count + profile_info->runs / 2) / profile_info->runs) == 0;
    if ((!profile_info || !flag_branch_probabilities)
!       && (cgraph_get_node (fun->decl)->frequency
  	  == NODE_FREQUENCY_UNLIKELY_EXECUTED))
      return true;
    return false;
*************** optimize_function_for_speed_p (struct fu
*** 252,258 ****
  bool
  optimize_bb_for_size_p (const_basic_block bb)
  {
!   return optimize_function_for_size_p (cfun) || !maybe_hot_bb_p (bb);
  }
  
  /* Return TRUE when BB should be optimized for speed.  */
--- 251,257 ----
  bool
  optimize_bb_for_size_p (const_basic_block bb)
  {
!   return optimize_function_for_size_p (cfun) || !maybe_hot_bb_p (cfun, bb);
  }
  
  /* Return TRUE when BB should be optimized for speed.  */
*************** predictable_edge_p (edge e)
*** 369,375 ****
  void
  rtl_profile_for_bb (basic_block bb)
  {
!   crtl->maybe_hot_insn_p = maybe_hot_bb_p (bb);
  }
  
  /* Set RTL expansion for edge profile.  */
--- 368,374 ----
  void
  rtl_profile_for_bb (basic_block bb)
  {
!   crtl->maybe_hot_insn_p = maybe_hot_bb_p (cfun, bb);
  }
  
  /* Set RTL expansion for edge profile.  */
*************** compute_function_frequency (void)
*** 2705,2716 ****
    node->frequency = NODE_FREQUENCY_UNLIKELY_EXECUTED;
    FOR_EACH_BB (bb)
      {
!       if (maybe_hot_bb_p (bb))
  	{
  	  node->frequency = NODE_FREQUENCY_HOT;
  	  return;
  	}
!       if (!probably_never_executed_bb_p (bb))
  	node->frequency = NODE_FREQUENCY_NORMAL;
      }
  }
--- 2704,2715 ----
    node->frequency = NODE_FREQUENCY_UNLIKELY_EXECUTED;
    FOR_EACH_BB (bb)
      {
!       if (maybe_hot_bb_p (cfun, bb))
  	{
  	  node->frequency = NODE_FREQUENCY_HOT;
  	  return;
  	}
!       if (!probably_never_executed_bb_p (cfun, bb))
  	node->frequency = NODE_FREQUENCY_NORMAL;
      }
  }
*** /tmp/HcgoTd_tree-cfg.c	Wed Aug 22 15:02:30 2012
--- gcc/tree-cfg.c	Wed Aug 22 11:53:02 2012
*************** move_sese_region_to_fn (struct function
*** 6632,6650 ****
     */
  
  void
! dump_function_to_file (tree fn, FILE *file, int flags)
  {
!   tree arg, var;
    struct function *dsf;
    bool ignore_topmost_bind = false, any_var = false;
    basic_block bb;
    tree chain;
!   bool tmclone = TREE_CODE (fn) == FUNCTION_DECL && decl_is_tm_clone (fn);
  
!   fprintf (file, "%s %s(", current_function_name (),
! 	   tmclone ? "[tm-clone] " : "");
  
!   arg = DECL_ARGUMENTS (fn);
    while (arg)
      {
        print_generic_expr (file, TREE_TYPE (arg), dump_flags);
--- 6632,6652 ----
     */
  
  void
! dump_function_to_file (tree fndecl, FILE *file, int flags)
  {
!   tree arg, var, old_current_fndecl = current_function_decl;
    struct function *dsf;
    bool ignore_topmost_bind = false, any_var = false;
    basic_block bb;
    tree chain;
!   bool tmclone = (TREE_CODE (fndecl) == FUNCTION_DECL
! 		  && decl_is_tm_clone (fndecl));
!   struct function *fun = DECL_STRUCT_FUNCTION (fndecl);
  
!   current_function_decl = fndecl;
!   fprintf (file, "%s %s(", function_name (fun), tmclone ? "[tm-clone] " : "");
  
!   arg = DECL_ARGUMENTS (fndecl);
    while (arg)
      {
        print_generic_expr (file, TREE_TYPE (arg), dump_flags);
*************** dump_function_to_file (tree fn, FILE *fi
*** 6659,6689 ****
    fprintf (file, ")\n");
  
    if (flags & TDF_VERBOSE)
!     print_node (file, "", fn, 2);
  
!   dsf = DECL_STRUCT_FUNCTION (fn);
    if (dsf && (flags & TDF_EH))
      dump_eh_tree (file, dsf);
  
!   if (flags & TDF_RAW && !gimple_has_body_p (fn))
      {
!       dump_node (fn, TDF_SLIM | flags, file);
        return;
      }
  
-   /* Switch CFUN to point to FN.  */
-   push_cfun (DECL_STRUCT_FUNCTION (fn));
- 
    /* When GIMPLE is lowered, the variables are no longer available in
       BIND_EXPRs, so display them separately.  */
!   if (cfun && cfun->decl == fn && (cfun->curr_properties & PROP_gimple_lcf))
      {
        unsigned ix;
        ignore_topmost_bind = true;
  
        fprintf (file, "{\n");
!       if (!VEC_empty (tree, cfun->local_decls))
! 	FOR_EACH_LOCAL_DECL (cfun, ix, var)
  	  {
  	    print_generic_decl (file, var, flags);
  	    if (flags & TDF_VERBOSE)
--- 6661,6688 ----
    fprintf (file, ")\n");
  
    if (flags & TDF_VERBOSE)
!     print_node (file, "", fndecl, 2);
  
!   dsf = DECL_STRUCT_FUNCTION (fndecl);
    if (dsf && (flags & TDF_EH))
      dump_eh_tree (file, dsf);
  
!   if (flags & TDF_RAW && !gimple_has_body_p (fndecl))
      {
!       dump_node (fndecl, TDF_SLIM | flags, file);
        return;
      }
  
    /* When GIMPLE is lowered, the variables are no longer available in
       BIND_EXPRs, so display them separately.  */
!   if (fun && fun->decl == fndecl && (fun->curr_properties & PROP_gimple_lcf))
      {
        unsigned ix;
        ignore_topmost_bind = true;
  
        fprintf (file, "{\n");
!       if (!VEC_empty (tree, fun->local_decls))
! 	FOR_EACH_LOCAL_DECL (fun, ix, var)
  	  {
  	    print_generic_decl (file, var, flags);
  	    if (flags & TDF_VERBOSE)
*************** dump_function_to_file (tree fn, FILE *fi
*** 6709,6734 ****
  	  }
      }
  
!   if (cfun && cfun->decl == fn && cfun->cfg && basic_block_info)
      {
        /* If the CFG has been built, emit a CFG-based dump.  */
        if (!ignore_topmost_bind)
  	fprintf (file, "{\n");
  
!       if (any_var && n_basic_blocks)
  	fprintf (file, "\n");
  
!       FOR_EACH_BB (bb)
  	dump_bb (file, bb, 2, flags | TDF_COMMENT);
  
        fprintf (file, "}\n");
      }
!   else if (DECL_SAVED_TREE (fn) == NULL)
      {
        /* The function is now in GIMPLE form but the CFG has not been
  	 built yet.  Emit the single sequence of GIMPLE statements
  	 that make up its body.  */
!       gimple_seq body = gimple_body (fn);
  
        if (gimple_seq_first_stmt (body)
  	  && gimple_seq_first_stmt (body) == gimple_seq_last_stmt (body)
--- 6708,6734 ----
  	  }
      }
  
!   if (fun && fun->decl == fndecl && fun->cfg
!       && basic_block_info_for_function (fun))
      {
        /* If the CFG has been built, emit a CFG-based dump.  */
        if (!ignore_topmost_bind)
  	fprintf (file, "{\n");
  
!       if (any_var && n_basic_blocks_for_function (fun))
  	fprintf (file, "\n");
  
!       FOR_EACH_BB_FN (bb, fun)
  	dump_bb (file, bb, 2, flags | TDF_COMMENT);
  
        fprintf (file, "}\n");
      }
!   else if (DECL_SAVED_TREE (fndecl) == NULL)
      {
        /* The function is now in GIMPLE form but the CFG has not been
  	 built yet.  Emit the single sequence of GIMPLE statements
  	 that make up its body.  */
!       gimple_seq body = gimple_body (fndecl);
  
        if (gimple_seq_first_stmt (body)
  	  && gimple_seq_first_stmt (body) == gimple_seq_last_stmt (body)
*************** dump_function_to_file (tree fn, FILE *fi
*** 6751,6758 ****
        int indent;
  
        /* Make a tree based dump.  */
!       chain = DECL_SAVED_TREE (fn);
! 
        if (chain && TREE_CODE (chain) == BIND_EXPR)
  	{
  	  if (ignore_topmost_bind)
--- 6751,6757 ----
        int indent;
  
        /* Make a tree based dump.  */
!       chain = DECL_SAVED_TREE (fndecl);
        if (chain && TREE_CODE (chain) == BIND_EXPR)
  	{
  	  if (ignore_topmost_bind)
*************** dump_function_to_file (tree fn, FILE *fi
*** 6782,6792 ****
      dump_enumerated_decls (file, flags);
    fprintf (file, "\n\n");
  
!   /* Restore CFUN.  */
!   pop_cfun ();
  }
  
- 
  /* Dump FUNCTION_DECL FN to stderr using FLAGS (see TDF_* in tree.h)  */
  
  DEBUG_FUNCTION void
--- 6781,6789 ----
      dump_enumerated_decls (file, flags);
    fprintf (file, "\n\n");
  
!   current_function_decl = old_current_fndecl;
  }
  
  /* Dump FUNCTION_DECL FN to stderr using FLAGS (see TDF_* in tree.h)  */
  
  DEBUG_FUNCTION void
*** /tmp/dtEITb_tree-flow-inline.h	Wed Aug 22 15:02:30 2012
--- gcc/tree-flow-inline.h	Wed Aug 22 11:53:02 2012
*************** delink_stmt_imm_use (gimple stmt)
*** 798,804 ****
     ssa_op_iter iter;
     use_operand_p use_p;
  
!    if (ssa_operands_active ())
       FOR_EACH_PHI_OR_STMT_USE (use_p, stmt, iter, SSA_OP_ALL_USES)
         delink_imm_use (use_p);
  }
--- 798,804 ----
     ssa_op_iter iter;
     use_operand_p use_p;
  
!    if (ssa_operands_active (cfun))
       FOR_EACH_PHI_OR_STMT_USE (use_p, stmt, iter, SSA_OP_ALL_USES)
         delink_imm_use (use_p);
  }
*** /tmp/BBEfSa_tree-ssa-operands.c	Wed Aug 22 15:02:30 2012
--- gcc/tree-ssa-operands.c	Wed Aug 22 11:53:02 2012
*************** static int n_initialized = 0;
*** 130,145 ****
  /*  Return true if the SSA operands cache is active.  */
  
  bool
! ssa_operands_active (void)
  {
!   /* This function may be invoked from contexts where CFUN is NULL
!      (IPA passes), return false for now.  FIXME: operands may be
!      active in each individual function, maybe this function should
!      take CFUN as a parameter.  */
!   if (cfun == NULL)
      return false;
  
!   return cfun->gimple_df && gimple_ssa_operands (cfun)->ops_active;
  }
  
  
--- 130,141 ----
  /*  Return true if the SSA operands cache is active.  */
  
  bool
! ssa_operands_active (struct function *fun)
  {
!   if (fun == NULL)
      return false;
  
!   return fun->gimple_df && gimple_ssa_operands (fun)->ops_active;
  }
  
  
*************** update_stmt_operands (gimple stmt)
*** 1211,1217 ****
  {
    /* If update_stmt_operands is called before SSA is initialized, do
       nothing.  */
!   if (!ssa_operands_active ())
      return;
  
    timevar_push (TV_TREE_OPS);
--- 1207,1213 ----
  {
    /* If update_stmt_operands is called before SSA is initialized, do
       nothing.  */
!   if (!ssa_operands_active (cfun))
      return;
  
    timevar_push (TV_TREE_OPS);
*************** swap_tree_operands (gimple stmt, tree *e
*** 1244,1250 ****
       positions of these two operands in their respective immediate use
       lists by adjusting their use pointer to point to the new
       operand position.  */
!   if (ssa_operands_active () && op0 != op1)
      {
        use_optype_p use0, use1, ptr;
        use0 = use1 = NULL;
--- 1240,1246 ----
       positions of these two operands in their respective immediate use
       lists by adjusting their use pointer to point to the new
       operand position.  */
!   if (ssa_operands_active (cfun) && op0 != op1)
      {
        use_optype_p use0, use1, ptr;
        use0 = use1 = NULL;
*** /tmp/VXKTod_tree-ssa-operands.h	Wed Aug 22 15:02:30 2012
--- gcc/tree-ssa-operands.h	Wed Aug 22 11:53:02 2012
*************** extern void debug_immediate_uses_for (tr
*** 114,120 ****
  extern void dump_decl_set (FILE *, bitmap);
  extern void debug_decl_set (bitmap);
  
! extern bool ssa_operands_active (void);
  
  extern bool virtual_operand_p (tree);
  extern void unlink_stmt_vdef (gimple);
--- 114,120 ----
  extern void dump_decl_set (FILE *, bitmap);
  extern void debug_decl_set (bitmap);
  
! extern bool ssa_operands_active (struct function *);
  
  extern bool virtual_operand_p (tree);
  extern void unlink_stmt_vdef (gimple);
*** /tmp/NxZsCa_tree-ssa.c	Wed Aug 22 15:02:30 2012
--- gcc/tree-ssa.c	Wed Aug 22 11:53:02 2012
*************** delete_tree_ssa (void)
*** 1157,1163 ****
    fini_ssanames ();
  
    /* We no longer maintain the SSA operand cache at this point.  */
!   if (ssa_operands_active ())
      fini_ssa_operands ();
  
    htab_delete (cfun->gimple_df->default_defs);
--- 1157,1163 ----
    fini_ssanames ();
  
    /* We no longer maintain the SSA operand cache at this point.  */
!   if (ssa_operands_active (cfun))
      fini_ssa_operands ();
  
    htab_delete (cfun->gimple_df->default_defs);

^ permalink raw reply	[flat|nested] 14+ messages in thread

* Re: [PATCH] Set current_function_decl in {push,pop}_cfun and push_struct_function
  2012-08-22 13:05         ` Martin Jambor
@ 2012-08-22 13:38           ` Richard Guenther
  2012-08-24 13:24             ` Martin Jambor
  0 siblings, 1 reply; 14+ messages in thread
From: Richard Guenther @ 2012-08-22 13:38 UTC (permalink / raw)
  To: Richard Guenther, Eric Botcazou, gcc-patches

On Wed, Aug 22, 2012 at 3:04 PM, Martin Jambor <mjambor@suse.cz> wrote:
> Hi,
>
> On Tue, Aug 21, 2012 at 01:30:47PM +0200, Richard Guenther wrote:
>> On Tue, Aug 21, 2012 at 1:27 PM, Martin Jambor <mjambor@suse.cz> wrote:
>> > On Wed, Aug 15, 2012 at 05:21:04PM +0200, Martin Jambor wrote:
>> >> Hi,
>> >>
>> >> On Fri, Aug 10, 2012 at 04:57:41PM +0200, Eric Botcazou wrote:
>> >> > > - ada/gcc-interface/utils.c:rest_of_subprog_body_compilation calls
>> >> > >   dump_function which in turns calls dump_function_to_file which calls
>> >> > >   push_cfun.  But Ada front end has its idea of the
>> >> > >   current_function_decl and there is no cfun which is an inconsistency
>> >> > >   which makes push_cfun assert fail.  I "solved" it by temporarily
>> >> > >   setting current_function_decl to NULL_TREE.  It's just dumping and I
>> >> > >   thought that dump_function should be considered middle-end and thus
>> >> > >   middle-end invariants should apply.
>> >> >
>> >> > If you think that calling dump_function from rest_of_subprog_body_compilation
>> >> > is a layering violation, I don't have a problem with replacing it with a more
>> >> > "manual" scheme like the one in c-family/c-gimplify.c:c_genericize, provided
>> >> > that this yields roughly the same output.
>> >>
>> >> Richi suggested on IRC that I remove the push/pop_cfun calls from
>> >> dump_function_to_file.  The only problem seems to be
>> >> dump_histograms_for_stmt
>> >
>> > Yesterday I actually tried and it is not the only problem.  Another
>> > one is dump_function_to_file->dump_bb->maybe_hot_bb_p which uses cfun
>> > to read profile_status.  There may be others, this one just blew up
>> > first when I set cfun to NULL.  And in future someone is quite likely
>> > to need cfun to dump something new too.
>> >
>> > At the same time, re-implementing dumping
>> > c-family/c-gimplify.c:c_genericize when dump_function suffices seems
>> > ugly to me.
>> >
>> > So I am going to declare dump_function a front-end interface and use
>> > set_cfun in my original patch in dump_function_to_file like we do in
>> > other such functions.
>> >
>> > I hope that will be OK.  Thanks,
>>
>> Setting cfun has side-effects of switching target stuff which might have
>> code-generation side-effects because of implementation issues we have
>> with target/optimize attributes.  So I don't think cfun should be changed
>> just for dumping.
>>
>> Can you instead just set current_function_decl and access
>> struct function via DECL_STRUCT_FUNCTION in the dumpers then?
>> After all, it it is a front-end interface, the frontend way of saying
>> "this is the current function" is to set current_function_decl, not the
>> middle-end cfun.
>>
>
> Like the following?  Tested and bootstrapped on x86_64-linux, it does
> help avoid the ada hunk in my previous patch.  OK for trunk?

Ok if nobody complains - btw, I think you miss to restore current_function_decl
here:


> *** /tmp/HcgoTd_tree-cfg.c      Wed Aug 22 15:02:30 2012
> --- gcc/tree-cfg.c      Wed Aug 22 11:53:02 2012
> *************** move_sese_region_to_fn (struct function
> *** 6632,6650 ****
>      */
>
>   void
> ! dump_function_to_file (tree fn, FILE *file, int flags)
>   {
> !   tree arg, var;
>     struct function *dsf;
>     bool ignore_topmost_bind = false, any_var = false;
>     basic_block bb;
>     tree chain;
> !   bool tmclone = TREE_CODE (fn) == FUNCTION_DECL && decl_is_tm_clone (fn);
>
> !   fprintf (file, "%s %s(", current_function_name (),
> !          tmclone ? "[tm-clone] " : "");
>
> !   arg = DECL_ARGUMENTS (fn);
>     while (arg)
>       {
>         print_generic_expr (file, TREE_TYPE (arg), dump_flags);
> --- 6632,6652 ----
>      */
>
>   void
> ! dump_function_to_file (tree fndecl, FILE *file, int flags)
>   {
> !   tree arg, var, old_current_fndecl = current_function_decl;
>     struct function *dsf;
>     bool ignore_topmost_bind = false, any_var = false;
>     basic_block bb;
>     tree chain;
> !   bool tmclone = (TREE_CODE (fndecl) == FUNCTION_DECL
> !                 && decl_is_tm_clone (fndecl));
> !   struct function *fun = DECL_STRUCT_FUNCTION (fndecl);
>
> !   current_function_decl = fndecl;
> !   fprintf (file, "%s %s(", function_name (fun), tmclone ? "[tm-clone] " : "");
>
> !   arg = DECL_ARGUMENTS (fndecl);
>     while (arg)
>       {
>         print_generic_expr (file, TREE_TYPE (arg), dump_flags);
> *************** dump_function_to_file (tree fn, FILE *fi
> *** 6659,6689 ****
>     fprintf (file, ")\n");
>
>     if (flags & TDF_VERBOSE)
> !     print_node (file, "", fn, 2);
>
> !   dsf = DECL_STRUCT_FUNCTION (fn);
>     if (dsf && (flags & TDF_EH))
>       dump_eh_tree (file, dsf);
>
> !   if (flags & TDF_RAW && !gimple_has_body_p (fn))
>       {
> !       dump_node (fn, TDF_SLIM | flags, file);
>         return;
>       }
>
> -   /* Switch CFUN to point to FN.  */
> -   push_cfun (DECL_STRUCT_FUNCTION (fn));
> -
>     /* When GIMPLE is lowered, the variables are no longer available in
>        BIND_EXPRs, so display them separately.  */
> !   if (cfun && cfun->decl == fn && (cfun->curr_properties & PROP_gimple_lcf))
>       {
>         unsigned ix;
>         ignore_topmost_bind = true;
>
>         fprintf (file, "{\n");
> !       if (!VEC_empty (tree, cfun->local_decls))
> !       FOR_EACH_LOCAL_DECL (cfun, ix, var)
>           {
>             print_generic_decl (file, var, flags);
>             if (flags & TDF_VERBOSE)
> --- 6661,6688 ----
>     fprintf (file, ")\n");
>
>     if (flags & TDF_VERBOSE)
> !     print_node (file, "", fndecl, 2);
>
> !   dsf = DECL_STRUCT_FUNCTION (fndecl);
>     if (dsf && (flags & TDF_EH))
>       dump_eh_tree (file, dsf);
>
> !   if (flags & TDF_RAW && !gimple_has_body_p (fndecl))
>       {
> !       dump_node (fndecl, TDF_SLIM | flags, file);
>         return;

^^^^

and maybe other early exits from dump_function_to_file.

Also as said on IRC when you switch current_function_decl you should be
able to set cfun to NULL (and restore it afterwards, without invoking the
target hook for cfun switching).  Thus, encapsulating this into a
push/pop_current_function_decl would be nice.

Thanks,
Richard.

^ permalink raw reply	[flat|nested] 14+ messages in thread

* Re: [PATCH] Set current_function_decl in {push,pop}_cfun and push_struct_function
  2012-08-22 13:38           ` Richard Guenther
@ 2012-08-24 13:24             ` Martin Jambor
  0 siblings, 0 replies; 14+ messages in thread
From: Martin Jambor @ 2012-08-24 13:24 UTC (permalink / raw)
  To: Richard Guenther; +Cc: Eric Botcazou, gcc-patches

Hi,

On Wed, Aug 22, 2012 at 03:37:48PM +0200, Richard Guenther wrote:
> On Wed, Aug 22, 2012 at 3:04 PM, Martin Jambor <mjambor@suse.cz> wrote:
> > On Tue, Aug 21, 2012 at 01:30:47PM +0200, Richard Guenther wrote:
> >> On Tue, Aug 21, 2012 at 1:27 PM, Martin Jambor <mjambor@suse.cz> wrote:
> >> > On Wed, Aug 15, 2012 at 05:21:04PM +0200, Martin Jambor wrote:
> >> >> Hi,
> >> >>
> >> >> On Fri, Aug 10, 2012 at 04:57:41PM +0200, Eric Botcazou wrote:
> >> >> > > - ada/gcc-interface/utils.c:rest_of_subprog_body_compilation calls
> >> >> > >   dump_function which in turns calls dump_function_to_file which calls
> >> >> > >   push_cfun.  But Ada front end has its idea of the
> >> >> > >   current_function_decl and there is no cfun which is an inconsistency
> >> >> > >   which makes push_cfun assert fail.  I "solved" it by temporarily
> >> >> > >   setting current_function_decl to NULL_TREE.  It's just dumping and I
> >> >> > >   thought that dump_function should be considered middle-end and thus
> >> >> > >   middle-end invariants should apply.
> >> >> >
> >> >> > If you think that calling dump_function from rest_of_subprog_body_compilation
> >> >> > is a layering violation, I don't have a problem with replacing it with a more
> >> >> > "manual" scheme like the one in c-family/c-gimplify.c:c_genericize, provided
> >> >> > that this yields roughly the same output.
> >> >>
> >> >> Richi suggested on IRC that I remove the push/pop_cfun calls from
> >> >> dump_function_to_file.  The only problem seems to be
> >> >> dump_histograms_for_stmt
> >> >
> >> > Yesterday I actually tried and it is not the only problem.  Another
> >> > one is dump_function_to_file->dump_bb->maybe_hot_bb_p which uses cfun
> >> > to read profile_status.  There may be others, this one just blew up
> >> > first when I set cfun to NULL.  And in future someone is quite likely
> >> > to need cfun to dump something new too.
> >> >
> >> > At the same time, re-implementing dumping
> >> > c-family/c-gimplify.c:c_genericize when dump_function suffices seems
> >> > ugly to me.
> >> >
> >> > So I am going to declare dump_function a front-end interface and use
> >> > set_cfun in my original patch in dump_function_to_file like we do in
> >> > other such functions.
> >> >
> >> > I hope that will be OK.  Thanks,
> >>
> >> Setting cfun has side-effects of switching target stuff which might have
> >> code-generation side-effects because of implementation issues we have
> >> with target/optimize attributes.  So I don't think cfun should be changed
> >> just for dumping.
> >>
> >> Can you instead just set current_function_decl and access
> >> struct function via DECL_STRUCT_FUNCTION in the dumpers then?
> >> After all, it it is a front-end interface, the frontend way of saying
> >> "this is the current function" is to set current_function_decl, not the
> >> middle-end cfun.
> >>
> >
> > Like the following?  Tested and bootstrapped on x86_64-linux, it does
> > help avoid the ada hunk in my previous patch.  OK for trunk?
> 
> Ok if nobody complains - btw, I think you miss to restore current_function_decl
> here:
> 
> 
> > *** /tmp/HcgoTd_tree-cfg.c      Wed Aug 22 15:02:30 2012
> > --- gcc/tree-cfg.c      Wed Aug 22 11:53:02 2012
> > *************** move_sese_region_to_fn (struct function
> > *** 6632,6650 ****
> >      */
> >
> >   void
> > ! dump_function_to_file (tree fn, FILE *file, int flags)
> >   {
> > !   tree arg, var;
> >     struct function *dsf;
> >     bool ignore_topmost_bind = false, any_var = false;
> >     basic_block bb;
> >     tree chain;
> > !   bool tmclone = TREE_CODE (fn) == FUNCTION_DECL && decl_is_tm_clone (fn);
> >
> > !   fprintf (file, "%s %s(", current_function_name (),
> > !          tmclone ? "[tm-clone] " : "");
> >
> > !   arg = DECL_ARGUMENTS (fn);
> >     while (arg)
> >       {
> >         print_generic_expr (file, TREE_TYPE (arg), dump_flags);
> > --- 6632,6652 ----
> >      */
> >
> >   void
> > ! dump_function_to_file (tree fndecl, FILE *file, int flags)
> >   {
> > !   tree arg, var, old_current_fndecl = current_function_decl;
> >     struct function *dsf;
> >     bool ignore_topmost_bind = false, any_var = false;
> >     basic_block bb;
> >     tree chain;
> > !   bool tmclone = (TREE_CODE (fndecl) == FUNCTION_DECL
> > !                 && decl_is_tm_clone (fndecl));
> > !   struct function *fun = DECL_STRUCT_FUNCTION (fndecl);
> >
> > !   current_function_decl = fndecl;
> > !   fprintf (file, "%s %s(", function_name (fun), tmclone ? "[tm-clone] " : "");
> >
> > !   arg = DECL_ARGUMENTS (fndecl);
> >     while (arg)
> >       {
> >         print_generic_expr (file, TREE_TYPE (arg), dump_flags);
> > *************** dump_function_to_file (tree fn, FILE *fi
> > *** 6659,6689 ****
> >     fprintf (file, ")\n");
> >
> >     if (flags & TDF_VERBOSE)
> > !     print_node (file, "", fn, 2);
> >
> > !   dsf = DECL_STRUCT_FUNCTION (fn);
> >     if (dsf && (flags & TDF_EH))
> >       dump_eh_tree (file, dsf);
> >
> > !   if (flags & TDF_RAW && !gimple_has_body_p (fn))
> >       {
> > !       dump_node (fn, TDF_SLIM | flags, file);
> >         return;
> >       }
> >
> > -   /* Switch CFUN to point to FN.  */
> > -   push_cfun (DECL_STRUCT_FUNCTION (fn));
> > -
> >     /* When GIMPLE is lowered, the variables are no longer available in
> >        BIND_EXPRs, so display them separately.  */
> > !   if (cfun && cfun->decl == fn && (cfun->curr_properties & PROP_gimple_lcf))
> >       {
> >         unsigned ix;
> >         ignore_topmost_bind = true;
> >
> >         fprintf (file, "{\n");
> > !       if (!VEC_empty (tree, cfun->local_decls))
> > !       FOR_EACH_LOCAL_DECL (cfun, ix, var)
> >           {
> >             print_generic_decl (file, var, flags);
> >             if (flags & TDF_VERBOSE)
> > --- 6661,6688 ----
> >     fprintf (file, ")\n");
> >
> >     if (flags & TDF_VERBOSE)
> > !     print_node (file, "", fndecl, 2);
> >
> > !   dsf = DECL_STRUCT_FUNCTION (fndecl);
> >     if (dsf && (flags & TDF_EH))
> >       dump_eh_tree (file, dsf);
> >
> > !   if (flags & TDF_RAW && !gimple_has_body_p (fndecl))
> >       {
> > !       dump_node (fndecl, TDF_SLIM | flags, file);
> >         return;
> 
> ^^^^
> 
> and maybe other early exits from dump_function_to_file.
> 

Oh, I missed that, there are no further early returns in the function.
I have added another restoration of current_function_decl there and
committed the patch below after retesting.

> Also as said on IRC when you switch current_function_decl you should be
> able to set cfun to NULL (and restore it afterwards, without invoking the
> target hook for cfun switching).  Thus, encapsulating this into a
> push/pop_current_function_decl would be nice.

Good idea, I will incorporate that into my original patch.

Thanks,

Martin



2012-08-24  Martin Jambor  <mjambor@suse.cz>

	* predict.c (maybe_hot_frequency_p): New parameter fun.  Use its decl
	instead of current_function_decl, use profile_status_for_function and
	ENTRY_BLOCK_PTR_FOR_FUNCTION with fun instead of their cfun variants.
	(maybe_hot_count_p): New parameter fun, use
	profile_status_for_function instead of its cfun_variant.
	(maybe_hot_bb_p): New parameter fun, checking-assert it, pass it to
	all callees.
	(maybe_hot_edge_p): Pass cfun to maybe_hot_count_p and
	maybe_hot_frequency_p.
	(probably_never_executed_bb_p): New parameter fun, use its decl
	instead of current_function_decl.
	(optimize_bb_for_size_p): Pass cfun to maybe_hot_bb_p.
	(rtl_profile_for_bb): Likewise.
	(compute_function_frequency): Pass cfun to maybe_hot_bb_p and
	probably_never_executed_bb_p.
	* tree-ssa-operands.c (ssa_operands_active): New operator fun.  Use it
	instead of cfun.
	(update_stmt_operands): Pass cfun as an argument of
	ssa_operands_active.
	(swap_tree_operands): Likewise.
	* gimple-iterator.c (update_modified_stmt): Likewise.
	(update_modified_stmts): Likewise.
	* tree-flow-inline.h (delink_stmt_imm_use): Likewise.
	* tree-ssa.c (delete_tree_ssa): Likewise.
	* bb-reorder.c (bb_to_key): Pass cfun to probably_never_executed_bb_p.
	(push_to_next_round_p): Likewise.
	(find_rarely_executed_basic_blocks_and_crossing_edges ): Likewise.
	* cfg.c: Inlude tree.h.
	(check_bb_profile): Use profile_status_for_function,
	EXIT_BLOCK_PTR_FOR_FUNCTION and ENTRY_BLOCK_PTR_FOR_FUNCTION with
	DECL_STRUCT_FUNCTION (current_function_decl) instead of their cfun
	variants.
	(dump_bb_info): Pass DECL_STRUCT_FUNCTION (current_function_decl) to
	maybe_hot_bb_p and probably_never_executed_bb_p.
	* gimple-pretty-print.c (gimple_dump_bb_buff): Checking-assert that
	DECL_STRUCT_FUNCTION (current_function_decl) is not NULL.  Pass it to
	dump_histograms_for_stmt.
	(dump_gimple_mem_ops): Pass DECL_STRUCT_FUNCTION (current_function_decl)
	as an argument to dump_gimple_mem_ops.
	* tree-cfg.c (dump_function_to_file): Rename parameter fn to fndecl.
	Do not change cfun.  Change and restore current_function_decl.
	* Makefile.in (cfg.o): Include TREE_H in dependencies.



diff --git a/gcc/Makefile.in b/gcc/Makefile.in
index dddffb6..9886b6c 100644
--- a/gcc/Makefile.in
+++ b/gcc/Makefile.in
@@ -3047,7 +3047,8 @@ auto-inc-dec.o : auto-inc-dec.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) \
    $(REGS_H) $(FLAGS_H) $(FUNCTION_H) $(EXCEPT_H) $(DIAGNOSTIC_CORE_H) $(RECOG_H) \
    $(EXPR_H) $(TREE_PASS_H) $(DF_H) $(DBGCNT_H) $(TARGET_H)
 cfg.o : cfg.c $(CONFIG_H) $(SYSTEM_H) coretypes.h dumpfile.h $(DIAGNOSTIC_CORE_H) \
-   $(GGC_H) $(OBSTACK_H) alloc-pool.h $(HASHTAB_H) $(CFGLOOP_H) $(BASIC_BLOCK_H)
+   $(GGC_H) $(OBSTACK_H) alloc-pool.h $(HASHTAB_H) $(CFGLOOP_H) $(TREE_H) \
+   $(BASIC_BLOCK_H)
 cfghooks.o: cfghooks.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) $(RTL_H) \
    $(TREE_H) $(BASIC_BLOCK_H) $(TREE_FLOW_H) $(TIMEVAR_H) toplev.h $(DIAGNOSTIC_CORE_H) $(CFGLOOP_H)
 cfgexpand.o : cfgexpand.c $(TREE_FLOW_H) $(CONFIG_H) $(SYSTEM_H) \
diff --git a/gcc/basic-block.h b/gcc/basic-block.h
index 6e1d091..09b5eb0 100644
--- a/gcc/basic-block.h
+++ b/gcc/basic-block.h
@@ -693,9 +693,9 @@ extern struct edge_list *pre_edge_rev_lcm (int, sbitmap *,
 extern void compute_available (sbitmap *, sbitmap *, sbitmap *, sbitmap *);
 
 /* In predict.c */
-extern bool maybe_hot_bb_p (const_basic_block);
+extern bool maybe_hot_bb_p (struct function *, const_basic_block);
 extern bool maybe_hot_edge_p (edge);
-extern bool probably_never_executed_bb_p (const_basic_block);
+extern bool probably_never_executed_bb_p (struct function *, const_basic_block);
 extern bool optimize_bb_for_size_p (const_basic_block);
 extern bool optimize_bb_for_speed_p (const_basic_block);
 extern bool optimize_edge_for_size_p (edge);
diff --git a/gcc/bb-reorder.c b/gcc/bb-reorder.c
index 0d29b2d..c282fb2 100644
--- a/gcc/bb-reorder.c
+++ b/gcc/bb-reorder.c
@@ -226,7 +226,7 @@ push_to_next_round_p (const_basic_block bb, int round, int number_of_rounds,
 
   block_not_hot_enough = (bb->frequency < exec_th
 			  || bb->count < count_th
-			  || probably_never_executed_bb_p (bb));
+			  || probably_never_executed_bb_p (cfun, bb));
 
   if (there_exists_another_round
       && block_not_hot_enough)
@@ -823,7 +823,7 @@ bb_to_key (basic_block bb)
   /* Do not start in probably never executed blocks.  */
 
   if (BB_PARTITION (bb) == BB_COLD_PARTITION
-      || probably_never_executed_bb_p (bb))
+      || probably_never_executed_bb_p (cfun, bb))
     return BB_FREQ_MAX;
 
   /* Prefer blocks whose predecessor is an end of some trace
@@ -1308,7 +1308,7 @@ find_rarely_executed_basic_blocks_and_crossing_edges (void)
   /* Mark which partition (hot/cold) each basic block belongs in.  */
   FOR_EACH_BB (bb)
     {
-      if (probably_never_executed_bb_p (bb))
+      if (probably_never_executed_bb_p (cfun, bb))
 	BB_SET_PARTITION (bb, BB_COLD_PARTITION);
       else
 	BB_SET_PARTITION (bb, BB_HOT_PARTITION);
diff --git a/gcc/cfg.c b/gcc/cfg.c
index ba83208..3f14d49 100644
--- a/gcc/cfg.c
+++ b/gcc/cfg.c
@@ -55,6 +55,7 @@ along with GCC; see the file COPYING3.  If not see
 #include "ggc.h"
 #include "hashtab.h"
 #include "alloc-pool.h"
+#include "tree.h"
 #include "basic-block.h"
 #include "df.h"
 #include "cfgloop.h" /* FIXME: For struct loop.  */
@@ -404,14 +405,15 @@ check_bb_profile (basic_block bb, FILE * file, int indent, int flags)
   int sum = 0;
   gcov_type lsum;
   edge_iterator ei;
+  struct function *fun = DECL_STRUCT_FUNCTION (current_function_decl);
   char *s_indent = (char *) alloca ((size_t) indent + 1);
   memset ((void *) s_indent, ' ', (size_t) indent);
   s_indent[indent] = '\0';
 
-  if (profile_status == PROFILE_ABSENT)
+  if (profile_status_for_function (fun) == PROFILE_ABSENT)
     return;
 
-  if (bb != EXIT_BLOCK_PTR)
+  if (bb != EXIT_BLOCK_PTR_FOR_FUNCTION (fun))
     {
       FOR_EACH_EDGE (e, ei, bb->succs)
 	sum += e->probability;
@@ -428,7 +430,7 @@ check_bb_profile (basic_block bb, FILE * file, int indent, int flags)
 		 (flags & TDF_COMMENT) ? ";; " : "", s_indent,
 		 (int) lsum, (int) bb->count);
     }
-  if (bb != ENTRY_BLOCK_PTR)
+    if (bb != ENTRY_BLOCK_PTR_FOR_FUNCTION (fun))
     {
       sum = 0;
       FOR_EACH_EDGE (e, ei, bb->preds)
@@ -701,12 +703,13 @@ dump_bb_info (FILE *outf, basic_block bb, int indent, int flags,
 	       s_indent, bb->index, bb_loop_depth (bb));
       if (flags & TDF_DETAILS)
 	{
+	  struct function *fun = DECL_STRUCT_FUNCTION (current_function_decl);
 	  fprintf (outf, ", count " HOST_WIDEST_INT_PRINT_DEC,
 		   (HOST_WIDEST_INT) bb->count);
 	  fprintf (outf, ", freq %i", bb->frequency);
-	  if (maybe_hot_bb_p (bb))
+	  if (maybe_hot_bb_p (fun, bb))
 	    fputs (", maybe hot", outf);
-	  if (probably_never_executed_bb_p (bb))
+	  if (probably_never_executed_bb_p (fun, bb))
 	    fputs (", probably never executed", outf);
 	}
       fputc ('\n', outf);
diff --git a/gcc/gimple-iterator.c b/gcc/gimple-iterator.c
index 914685c..3d01566 100644
--- a/gcc/gimple-iterator.c
+++ b/gcc/gimple-iterator.c
@@ -33,7 +33,7 @@ along with GCC; see the file COPYING3.  If not see
 static inline void
 update_modified_stmt (gimple stmt)
 {
-  if (!ssa_operands_active ())
+  if (!ssa_operands_active (cfun))
     return;
   update_stmt_if_modified (stmt);
 }
@@ -46,7 +46,7 @@ update_modified_stmts (gimple_seq seq)
 {
   gimple_stmt_iterator gsi;
 
-  if (!ssa_operands_active ())
+  if (!ssa_operands_active (cfun))
     return;
   for (gsi = gsi_start (seq); !gsi_end_p (gsi); gsi_next (&gsi))
     update_stmt_if_modified (gsi_stmt (gsi));
diff --git a/gcc/gimple-pretty-print.c b/gcc/gimple-pretty-print.c
index 3b25020..658e0be 100644
--- a/gcc/gimple-pretty-print.c
+++ b/gcc/gimple-pretty-print.c
@@ -1817,7 +1817,8 @@ dump_gimple_mem_ops (pretty_printer *buffer, gimple gs, int spc, int flags)
   tree vdef = gimple_vdef (gs);
   tree vuse = gimple_vuse (gs);
 
-  if (!ssa_operands_active () || !gimple_references_memory_p (gs))
+  if (!ssa_operands_active (DECL_STRUCT_FUNCTION (current_function_decl))
+      || !gimple_references_memory_p (gs))
     return;
 
   if (vdef != NULL_TREE)
@@ -2256,7 +2257,9 @@ gimple_dump_bb_buff (pretty_printer *buffer, basic_block bb, int indent,
       INDENT (curr_indent);
       dump_gimple_stmt (buffer, stmt, curr_indent, flags);
       pp_newline_and_flush (buffer);
-      dump_histograms_for_stmt (cfun, buffer->buffer->stream, stmt);
+      gcc_checking_assert (DECL_STRUCT_FUNCTION (current_function_decl));
+      dump_histograms_for_stmt (DECL_STRUCT_FUNCTION (current_function_decl),
+				buffer->buffer->stream, stmt);
     }
 
   dump_implicit_edges (buffer, bb, indent, flags);
diff --git a/gcc/predict.c b/gcc/predict.c
index e1a064d..f0db9f4 100644
--- a/gcc/predict.c
+++ b/gcc/predict.c
@@ -108,9 +108,9 @@ static const struct predictor_info predictor_info[]= {
 /* Return TRUE if frequency FREQ is considered to be hot.  */
 
 static inline bool
-maybe_hot_frequency_p (int freq)
+maybe_hot_frequency_p (struct function *fun, int freq)
 {
-  struct cgraph_node *node = cgraph_get_node (current_function_decl);
+  struct cgraph_node *node = cgraph_get_node (fun->decl);
   if (!profile_info || !flag_branch_probabilities)
     {
       if (node->frequency == NODE_FREQUENCY_UNLIKELY_EXECUTED)
@@ -118,12 +118,13 @@ maybe_hot_frequency_p (int freq)
       if (node->frequency == NODE_FREQUENCY_HOT)
         return true;
     }
-  if (profile_status == PROFILE_ABSENT)
+  if (profile_status_for_function (fun) == PROFILE_ABSENT)
     return true;
   if (node->frequency == NODE_FREQUENCY_EXECUTED_ONCE
-      && freq < (ENTRY_BLOCK_PTR->frequency * 2 / 3))
+      && freq < (ENTRY_BLOCK_PTR_FOR_FUNCTION (fun)->frequency * 2 / 3))
     return false;
-  if (freq < ENTRY_BLOCK_PTR->frequency / PARAM_VALUE (HOT_BB_FREQUENCY_FRACTION))
+  if (freq < (ENTRY_BLOCK_PTR_FOR_FUNCTION (fun)->frequency
+	      / PARAM_VALUE (HOT_BB_FREQUENCY_FRACTION)))
     return false;
   return true;
 }
@@ -131,9 +132,9 @@ maybe_hot_frequency_p (int freq)
 /* Return TRUE if frequency FREQ is considered to be hot.  */
 
 static inline bool
-maybe_hot_count_p (gcov_type count)
+maybe_hot_count_p (struct function *fun, gcov_type count)
 {
-  if (profile_status != PROFILE_READ)
+  if (profile_status_for_function (fun) != PROFILE_READ)
     return true;
   /* Code executed at most once is not hot.  */
   if (profile_info->runs >= count)
@@ -146,13 +147,12 @@ maybe_hot_count_p (gcov_type count)
    for maximal performance.  */
 
 bool
-maybe_hot_bb_p (const_basic_block bb)
+maybe_hot_bb_p (struct function *fun, const_basic_block bb)
 {
-  /* Make sure CFUN exists, for dump_bb_info.  */
-  gcc_assert (cfun);
-  if (profile_status == PROFILE_READ)
-    return maybe_hot_count_p (bb->count);
-  return maybe_hot_frequency_p (bb->frequency);
+  gcc_checking_assert (fun);
+  if (profile_status_for_function (fun) == PROFILE_READ)
+    return maybe_hot_count_p (fun, bb->count);
+  return maybe_hot_frequency_p (fun, bb->frequency);
 }
 
 /* Return true if the call can be hot.  */
@@ -193,22 +193,21 @@ bool
 maybe_hot_edge_p (edge e)
 {
   if (profile_status == PROFILE_READ)
-    return maybe_hot_count_p (e->count);
-  return maybe_hot_frequency_p (EDGE_FREQUENCY (e));
+    return maybe_hot_count_p (cfun, e->count);
+  return maybe_hot_frequency_p (cfun, EDGE_FREQUENCY (e));
 }
 
 
 /* Return true in case BB is probably never executed.  */
 
 bool
-probably_never_executed_bb_p (const_basic_block bb)
+probably_never_executed_bb_p (struct function *fun, const_basic_block bb)
 {
-  /* Make sure CFUN exists, for dump_bb_info.  */
-  gcc_assert (cfun);
+  gcc_checking_assert (fun);
   if (profile_info && flag_branch_probabilities)
     return ((bb->count + profile_info->runs / 2) / profile_info->runs) == 0;
   if ((!profile_info || !flag_branch_probabilities)
-      && (cgraph_get_node (current_function_decl)->frequency
+      && (cgraph_get_node (fun->decl)->frequency
 	  == NODE_FREQUENCY_UNLIKELY_EXECUTED))
     return true;
   return false;
@@ -252,7 +251,7 @@ optimize_function_for_speed_p (struct function *fun)
 bool
 optimize_bb_for_size_p (const_basic_block bb)
 {
-  return optimize_function_for_size_p (cfun) || !maybe_hot_bb_p (bb);
+  return optimize_function_for_size_p (cfun) || !maybe_hot_bb_p (cfun, bb);
 }
 
 /* Return TRUE when BB should be optimized for speed.  */
@@ -369,7 +368,7 @@ predictable_edge_p (edge e)
 void
 rtl_profile_for_bb (basic_block bb)
 {
-  crtl->maybe_hot_insn_p = maybe_hot_bb_p (bb);
+  crtl->maybe_hot_insn_p = maybe_hot_bb_p (cfun, bb);
 }
 
 /* Set RTL expansion for edge profile.  */
@@ -2705,12 +2704,12 @@ compute_function_frequency (void)
   node->frequency = NODE_FREQUENCY_UNLIKELY_EXECUTED;
   FOR_EACH_BB (bb)
     {
-      if (maybe_hot_bb_p (bb))
+      if (maybe_hot_bb_p (cfun, bb))
 	{
 	  node->frequency = NODE_FREQUENCY_HOT;
 	  return;
 	}
-      if (!probably_never_executed_bb_p (bb))
+      if (!probably_never_executed_bb_p (cfun, bb))
 	node->frequency = NODE_FREQUENCY_NORMAL;
     }
 }
diff --git a/gcc/tree-cfg.c b/gcc/tree-cfg.c
index c718cc0..247f616 100644
--- a/gcc/tree-cfg.c
+++ b/gcc/tree-cfg.c
@@ -6632,19 +6632,21 @@ move_sese_region_to_fn (struct function *dest_cfun, basic_block entry_bb,
    */
 
 void
-dump_function_to_file (tree fn, FILE *file, int flags)
+dump_function_to_file (tree fndecl, FILE *file, int flags)
 {
-  tree arg, var;
+  tree arg, var, old_current_fndecl = current_function_decl;
   struct function *dsf;
   bool ignore_topmost_bind = false, any_var = false;
   basic_block bb;
   tree chain;
-  bool tmclone = TREE_CODE (fn) == FUNCTION_DECL && decl_is_tm_clone (fn);
+  bool tmclone = (TREE_CODE (fndecl) == FUNCTION_DECL
+		  && decl_is_tm_clone (fndecl));
+  struct function *fun = DECL_STRUCT_FUNCTION (fndecl);
 
-  fprintf (file, "%s %s(", current_function_name (),
-	   tmclone ? "[tm-clone] " : "");
+  current_function_decl = fndecl;
+  fprintf (file, "%s %s(", function_name (fun), tmclone ? "[tm-clone] " : "");
 
-  arg = DECL_ARGUMENTS (fn);
+  arg = DECL_ARGUMENTS (fndecl);
   while (arg)
     {
       print_generic_expr (file, TREE_TYPE (arg), dump_flags);
@@ -6659,31 +6661,29 @@ dump_function_to_file (tree fn, FILE *file, int flags)
   fprintf (file, ")\n");
 
   if (flags & TDF_VERBOSE)
-    print_node (file, "", fn, 2);
+    print_node (file, "", fndecl, 2);
 
-  dsf = DECL_STRUCT_FUNCTION (fn);
+  dsf = DECL_STRUCT_FUNCTION (fndecl);
   if (dsf && (flags & TDF_EH))
     dump_eh_tree (file, dsf);
 
-  if (flags & TDF_RAW && !gimple_has_body_p (fn))
+  if (flags & TDF_RAW && !gimple_has_body_p (fndecl))
     {
-      dump_node (fn, TDF_SLIM | flags, file);
+      dump_node (fndecl, TDF_SLIM | flags, file);
+      current_function_decl = old_current_fndecl;
       return;
     }
 
-  /* Switch CFUN to point to FN.  */
-  push_cfun (DECL_STRUCT_FUNCTION (fn));
-
   /* When GIMPLE is lowered, the variables are no longer available in
      BIND_EXPRs, so display them separately.  */
-  if (cfun && cfun->decl == fn && (cfun->curr_properties & PROP_gimple_lcf))
+  if (fun && fun->decl == fndecl && (fun->curr_properties & PROP_gimple_lcf))
     {
       unsigned ix;
       ignore_topmost_bind = true;
 
       fprintf (file, "{\n");
-      if (!VEC_empty (tree, cfun->local_decls))
-	FOR_EACH_LOCAL_DECL (cfun, ix, var)
+      if (!VEC_empty (tree, fun->local_decls))
+	FOR_EACH_LOCAL_DECL (fun, ix, var)
 	  {
 	    print_generic_decl (file, var, flags);
 	    if (flags & TDF_VERBOSE)
@@ -6709,26 +6709,27 @@ dump_function_to_file (tree fn, FILE *file, int flags)
 	  }
     }
 
-  if (cfun && cfun->decl == fn && cfun->cfg && basic_block_info)
+  if (fun && fun->decl == fndecl && fun->cfg
+      && basic_block_info_for_function (fun))
     {
       /* If the CFG has been built, emit a CFG-based dump.  */
       if (!ignore_topmost_bind)
 	fprintf (file, "{\n");
 
-      if (any_var && n_basic_blocks)
+      if (any_var && n_basic_blocks_for_function (fun))
 	fprintf (file, "\n");
 
-      FOR_EACH_BB (bb)
+      FOR_EACH_BB_FN (bb, fun)
 	dump_bb (file, bb, 2, flags | TDF_COMMENT);
 
       fprintf (file, "}\n");
     }
-  else if (DECL_SAVED_TREE (fn) == NULL)
+  else if (DECL_SAVED_TREE (fndecl) == NULL)
     {
       /* The function is now in GIMPLE form but the CFG has not been
 	 built yet.  Emit the single sequence of GIMPLE statements
 	 that make up its body.  */
-      gimple_seq body = gimple_body (fn);
+      gimple_seq body = gimple_body (fndecl);
 
       if (gimple_seq_first_stmt (body)
 	  && gimple_seq_first_stmt (body) == gimple_seq_last_stmt (body)
@@ -6751,8 +6752,7 @@ dump_function_to_file (tree fn, FILE *file, int flags)
       int indent;
 
       /* Make a tree based dump.  */
-      chain = DECL_SAVED_TREE (fn);
-
+      chain = DECL_SAVED_TREE (fndecl);
       if (chain && TREE_CODE (chain) == BIND_EXPR)
 	{
 	  if (ignore_topmost_bind)
@@ -6782,11 +6782,9 @@ dump_function_to_file (tree fn, FILE *file, int flags)
     dump_enumerated_decls (file, flags);
   fprintf (file, "\n\n");
 
-  /* Restore CFUN.  */
-  pop_cfun ();
+  current_function_decl = old_current_fndecl;
 }
 
-
 /* Dump FUNCTION_DECL FN to stderr using FLAGS (see TDF_* in tree.h)  */
 
 DEBUG_FUNCTION void
diff --git a/gcc/tree-flow-inline.h b/gcc/tree-flow-inline.h
index 7bd0db3..acb2cc4 100644
--- a/gcc/tree-flow-inline.h
+++ b/gcc/tree-flow-inline.h
@@ -798,7 +798,7 @@ delink_stmt_imm_use (gimple stmt)
    ssa_op_iter iter;
    use_operand_p use_p;
 
-   if (ssa_operands_active ())
+   if (ssa_operands_active (cfun))
      FOR_EACH_PHI_OR_STMT_USE (use_p, stmt, iter, SSA_OP_ALL_USES)
        delink_imm_use (use_p);
 }
diff --git a/gcc/tree-ssa-operands.c b/gcc/tree-ssa-operands.c
index 3a1f989..d9b3146 100644
--- a/gcc/tree-ssa-operands.c
+++ b/gcc/tree-ssa-operands.c
@@ -130,16 +130,12 @@ static int n_initialized = 0;
 /*  Return true if the SSA operands cache is active.  */
 
 bool
-ssa_operands_active (void)
+ssa_operands_active (struct function *fun)
 {
-  /* This function may be invoked from contexts where CFUN is NULL
-     (IPA passes), return false for now.  FIXME: operands may be
-     active in each individual function, maybe this function should
-     take CFUN as a parameter.  */
-  if (cfun == NULL)
+  if (fun == NULL)
     return false;
 
-  return cfun->gimple_df && gimple_ssa_operands (cfun)->ops_active;
+  return fun->gimple_df && gimple_ssa_operands (fun)->ops_active;
 }
 
 
@@ -1211,7 +1207,7 @@ update_stmt_operands (gimple stmt)
 {
   /* If update_stmt_operands is called before SSA is initialized, do
      nothing.  */
-  if (!ssa_operands_active ())
+  if (!ssa_operands_active (cfun))
     return;
 
   timevar_push (TV_TREE_OPS);
@@ -1244,7 +1240,7 @@ swap_tree_operands (gimple stmt, tree *exp0, tree *exp1)
      positions of these two operands in their respective immediate use
      lists by adjusting their use pointer to point to the new
      operand position.  */
-  if (ssa_operands_active () && op0 != op1)
+  if (ssa_operands_active (cfun) && op0 != op1)
     {
       use_optype_p use0, use1, ptr;
       use0 = use1 = NULL;
diff --git a/gcc/tree-ssa-operands.h b/gcc/tree-ssa-operands.h
index 2d899dd..76a8bd8 100644
--- a/gcc/tree-ssa-operands.h
+++ b/gcc/tree-ssa-operands.h
@@ -114,7 +114,7 @@ extern void debug_immediate_uses_for (tree var);
 extern void dump_decl_set (FILE *, bitmap);
 extern void debug_decl_set (bitmap);
 
-extern bool ssa_operands_active (void);
+extern bool ssa_operands_active (struct function *);
 
 extern bool virtual_operand_p (tree);
 extern void unlink_stmt_vdef (gimple);
diff --git a/gcc/tree-ssa.c b/gcc/tree-ssa.c
index 97a8ba5..1746c8f 100644
--- a/gcc/tree-ssa.c
+++ b/gcc/tree-ssa.c
@@ -1157,7 +1157,7 @@ delete_tree_ssa (void)
   fini_ssanames ();
 
   /* We no longer maintain the SSA operand cache at this point.  */
-  if (ssa_operands_active ())
+  if (ssa_operands_active (cfun))
     fini_ssa_operands ();
 
   htab_delete (cfun->gimple_df->default_defs);

^ permalink raw reply	[flat|nested] 14+ messages in thread

end of thread, other threads:[~2012-08-24 13:24 UTC | newest]

Thread overview: 14+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2012-08-09 14:27 [PATCH] Set current_function_decl in {push,pop}_cfun and push_struct_function Martin Jambor
2012-08-09 14:58 ` Richard Guenther
2012-08-10 14:58 ` Eric Botcazou
2012-08-15 15:21   ` Martin Jambor
2012-08-16  9:30     ` Richard Guenther
2012-08-16 12:40       ` Michael Matz
2012-08-16 13:23         ` Diego Novillo
2012-08-16 14:21           ` Michael Matz
2012-08-16 14:26             ` Diego Novillo
2012-08-21 11:27     ` Martin Jambor
2012-08-21 11:31       ` Richard Guenther
2012-08-22 13:05         ` Martin Jambor
2012-08-22 13:38           ` Richard Guenther
2012-08-24 13:24             ` Martin Jambor

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).