[tree-profiling] reorganization of static initializers analysis

Jan Hubicka jh@suse.cz
Fri Oct 15 23:09:00 GMT 2004


Hi,
this patch actually removes the old hooks from assembly output functions
and solves some of the problems in my previous patch.  I've ifdeffed out
code clearing DECL_RTL of variables in late stages of compilation.  This
looks wrong and doing so don't cause any regressions.  I will sen
separate mail about that.

	* cgraph.c (decide_is_variable_needed): New function.
	(cgraph_varpool_finalize_decl): Use it.
	* cgraphunit.c (cgraph_optimize): Assemble_pending_decls when not doing
	unit-at-a-time.
	* final.c (output_addr_const): Do not call mark_referenced.
	* passes.c (rest_of_decl_compilation): ifdef out DECL_RTL_SET_P hack;
	always go via cgraph.
	* toplev.c (wrapup_global_declarations): Kill non-unit-at-a-time code.
	(check_global_declarations): Ifdef out code clearing DECL_RTL.
	* tree-optimize.c (execute_inline): Mark functions called.
	* i386.c (output_pic_addr_const): Do not call mark_decl_referenced.
Index: cgraph.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/cgraph.c,v
retrieving revision 1.4.4.18.2.9
diff -c -3 -p -r1.4.4.18.2.9 cgraph.c
*** cgraph.c	10 Oct 2004 23:37:04 -0000	1.4.4.18.2.9
--- cgraph.c	15 Oct 2004 19:09:50 -0000
*************** cgraph_varpool_mark_needed_node (struct 
*** 610,615 ****
--- 610,657 ----
    node->needed = 1;
  }
  
+ /* Determine if variable DECL is needed.  That is, visible to something
+    either outside this translation unit, something magic in the system
+    configury, or (if not doing unit-at-a-time) to something we haven't
+    seen yet.  */
+ 
+ static bool
+ decide_is_variable_needed (struct cgraph_varpool_node *node, tree decl)
+ {
+   /* If we decided it was needed before, but at the time we didn't have
+      the body of the function available, then it's still needed.  We have
+      to go back and re-check its dependencies now.  */
+   if (node->needed)
+     return true;
+ 
+   /* Externally visible functions must be output.  The exception is
+      COMDAT functions that must be output only when they are needed.  */
+   if (TREE_PUBLIC (decl) && !DECL_COMDAT (decl) && !DECL_EXTERNAL (decl))
+     return true;
+ 
+   /* If the user told us it is used, then it must be so.  */
+   if (lookup_attribute ("used", DECL_ATTRIBUTES (decl)))
+     return true;
+ 
+   /* ??? If the assembler name is set by hand, it is possible to assemble
+      the name later after finalizing the function and the fact is noticed
+      in assemble_name then.  This is arguably a bug.  */
+   if (DECL_ASSEMBLER_NAME_SET_P (decl)
+       && TREE_SYMBOL_REFERENCED (DECL_ASSEMBLER_NAME (decl)))
+     return true;
+ 
+   if (flag_unit_at_a_time)
+     return false;
+ 
+   /* If not doing unit at a time, then we'll only defer this function
+      if its marked for inlining.  Otherwise we want to emit it now.  */
+ 
+   /* We want to emit COMDAT variables only when absolutely necessary.  */
+   if (DECL_COMDAT (decl))
+     return false;
+   return true;
+ }
+ 
  void
  cgraph_varpool_finalize_decl (tree decl)
  {
*************** cgraph_varpool_finalize_decl (tree decl)
*** 620,641 ****
       or local (in C, has internal linkage).  So do nothing more
       if this function has already run.  */
    if (node->finalized)
!     return;
    if (node->needed)
      enqueue_needed_varpool_node (node);
    node->finalized = true;
  
!   if (/* Externally visible variables must be output.  The exception are
! 	 COMDAT functions that must be output only when they are needed.  */
!       (TREE_PUBLIC (decl) && !DECL_COMDAT (decl))
!       /* Function whose name is output to the assembler file must be produced.
! 	 It is possible to assemble the name later after finalizing the function
! 	 and the fact is noticed in assemble_name then.  */
!       || (DECL_ASSEMBLER_NAME_SET_P (decl)
! 	  && TREE_SYMBOL_REFERENCED (DECL_ASSEMBLER_NAME (decl))))
!     {
!       cgraph_varpool_mark_needed_node (node);
!     }
  }
  
  
--- 662,680 ----
       or local (in C, has internal linkage).  So do nothing more
       if this function has already run.  */
    if (node->finalized)
!     {
!       if (cgraph_global_info_ready || !flag_unit_at_a_time)
! 	cgraph_varpool_assemble_pending_decls ();
!       return;
!     }
    if (node->needed)
      enqueue_needed_varpool_node (node);
    node->finalized = true;
  
!   if (decide_is_variable_needed (node, decl))
!     cgraph_varpool_mark_needed_node (node);
!   if (cgraph_global_info_ready || !flag_unit_at_a_time)
!     cgraph_varpool_assemble_pending_decls ();
  }
  
  
Index: cgraphunit.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/cgraphunit.c,v
retrieving revision 1.1.4.35.2.17
diff -c -3 -p -r1.1.4.35.2.17 cgraphunit.c
*** cgraphunit.c	10 Oct 2004 23:37:04 -0000	1.1.4.35.2.17
--- cgraphunit.c	15 Oct 2004 19:09:50 -0000
*************** cgraph_optimize (void)
*** 2834,2840 ****
    verify_cgraph ();
  #endif
    if (!flag_unit_at_a_time)
!     return;
    if (flag_ipa_cp && flag_ipa_no_cloning)
      ipcp_driver ();
    timevar_push (TV_CGRAPHOPT);
--- 2834,2843 ----
    verify_cgraph ();
  #endif
    if (!flag_unit_at_a_time)
!     {
!       cgraph_varpool_assemble_pending_decls ();
!       return;
!     }
    if (flag_ipa_cp && flag_ipa_no_cloning)
      ipcp_driver ();
    timevar_push (TV_CGRAPHOPT);
Index: final.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/final.c,v
retrieving revision 1.262.2.23.2.10
diff -c -3 -p -r1.262.2.23.2.10 final.c
*** final.c	12 Sep 2004 16:39:07 -0000	1.262.2.23.2.10
--- final.c	15 Oct 2004 19:09:51 -0000
*************** output_addr_const (FILE *file, rtx x)
*** 3239,3246 ****
        break;
  
      case SYMBOL_REF:
-       if (SYMBOL_REF_DECL (x))
- 	mark_decl_referenced (SYMBOL_REF_DECL (x));
  #ifdef ASM_OUTPUT_SYMBOL_REF
        ASM_OUTPUT_SYMBOL_REF (file, x);
  #else
--- 3239,3244 ----
Index: passes.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/passes.c,v
retrieving revision 2.2.4.13
diff -c -3 -p -r2.2.4.13 passes.c
*** passes.c	25 Sep 2004 23:17:51 -0000	2.2.4.13
--- passes.c	15 Oct 2004 19:09:51 -0000
*************** rest_of_decl_compilation (tree decl,
*** 225,242 ****
  	 (see gcc.c-torture/compile/920624-1.c) */
        if ((at_end
  	   || !DECL_DEFER_OUTPUT (decl)
! 	   || (flag_unit_at_a_time && DECL_INITIAL (decl)))
  	  && !DECL_EXTERNAL (decl))
  	{
! 	  if (flag_unit_at_a_time && !cgraph_global_info_ready
! 	      && TREE_CODE (decl) != FUNCTION_DECL && top_level
! 	      /* If we defer processing of decls that have had their
! 		 DECL_RTL set above (say, in make_decl_rtl),
! 		 check_global_declarations() will clear it before
! 		 assemble_variable has a chance to act on it.  This
! 		 would remove all traces of the register name in a
! 		 global register variable, for example.  */
  	      && !DECL_RTL_SET_P (decl))
  	    cgraph_varpool_finalize_decl (decl);
  	  else
  	    assemble_variable (decl, top_level, at_end, 0);
--- 225,244 ----
  	 (see gcc.c-torture/compile/920624-1.c) */
        if ((at_end
  	   || !DECL_DEFER_OUTPUT (decl)
! 	   || DECL_INITIAL (decl))
  	  && !DECL_EXTERNAL (decl))
  	{
! 	  /* If we defer processing of decls that have had their
! 	     DECL_RTL set above (say, in make_decl_rtl),
! 	     check_global_declarations() will clear it before
! 	     assemble_variable has a chance to act on it.  This
! 	     would remove all traces of the register name in a
! 	     global register variable, for example.  */
! 	  if (TREE_CODE (decl) != FUNCTION_DECL && top_level
! #if 0
  	      && !DECL_RTL_SET_P (decl))
+ #endif
+ 	      )
  	    cgraph_varpool_finalize_decl (decl);
  	  else
  	    assemble_variable (decl, top_level, at_end, 0);
Index: toplev.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/toplev.c,v
retrieving revision 1.654.2.97.2.17
diff -c -3 -p -r1.654.2.97.2.17 toplev.c
*** toplev.c	1 Oct 2004 22:10:01 -0000	1.654.2.97.2.17
--- toplev.c	15 Oct 2004 19:09:51 -0000
*************** wrapup_global_declarations (tree *vec, i
*** 774,782 ****
  	      bool needed = 1;
  	      node = cgraph_varpool_node (decl);
  
! 	      if (flag_unit_at_a_time && node->finalized)
  		needed = 0;
! 	      else if ((flag_unit_at_a_time && !cgraph_global_info_ready)
  		       && (TREE_USED (decl)
  			   || TREE_USED (DECL_ASSEMBLER_NAME (decl))))
  		/* needed */;
--- 774,782 ----
  	      bool needed = 1;
  	      node = cgraph_varpool_node (decl);
  
! 	      if (node->finalized)
  		needed = 0;
! 	      else if (!cgraph_global_info_ready
  		       && (TREE_USED (decl)
  			   || TREE_USED (DECL_ASSEMBLER_NAME (decl))))
  		/* needed */;
*************** check_global_declarations (tree *vec, in
*** 818,829 ****
--- 818,831 ----
      {
        decl = vec[i];
  
+ #if 0
        if (TREE_CODE (decl) == VAR_DECL && TREE_STATIC (decl)
  	  && ! TREE_ASM_WRITTEN (decl))
  	/* Cancel the RTL for this decl so that, if debugging info
  	   output for global variables is still to come,
  	   this one will be omitted.  */
  	SET_DECL_RTL (decl, NULL_RTX);
+ #endif
  
        /* Warn about any function
  	 declared static but not defined.
Index: tree-optimize.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/tree-optimize.c,v
retrieving revision 1.1.4.122.2.20
diff -c -3 -p -r1.1.4.122.2.20 tree-optimize.c
*** tree-optimize.c	25 Sep 2004 23:17:57 -0000	1.1.4.122.2.20
--- tree-optimize.c	15 Oct 2004 19:09:51 -0000
*************** execute_inline (void)
*** 83,89 ****
    /* We are not going to maintain the cgraph edges up to date.
       Kill it so it won't confuse us.  */
    while (node->callees)
!     cgraph_remove_edge (node->callees);
  }
  
  static struct tree_opt_pass pass_inline = 
--- 83,95 ----
    /* We are not going to maintain the cgraph edges up to date.
       Kill it so it won't confuse us.  */
    while (node->callees)
!     {
!       /* In non-unit-at-a-time we must mark all referenced functions as needed.
!          */
!       if (node->callees->callee->analyzed && !flag_unit_at_a_time)
!         cgraph_mark_needed_node (node->callees->callee);
!       cgraph_remove_edge (node->callees);
!     }
  }
  
  static struct tree_opt_pass pass_inline = 
Index: config/i386/i386.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/config/i386/i386.c,v
retrieving revision 1.425.2.42.2.12
diff -c -3 -p -r1.425.2.42.2.12 i386.c
*** config/i386/i386.c	25 Sep 2004 23:18:21 -0000	1.425.2.42.2.12
--- config/i386/i386.c	15 Oct 2004 19:09:55 -0000
*************** output_pic_addr_const (FILE *file, rtx x
*** 5791,5800 ****
        break;
  
      case SYMBOL_REF:
-      /* Mark the decl as referenced so that cgraph will output the function.  */
-      if (SYMBOL_REF_DECL (x))
-        mark_decl_referenced (SYMBOL_REF_DECL (x));
- 
        assemble_name (file, XSTR (x, 0));
        if (!TARGET_MACHO && code == 'P' && ! SYMBOL_REF_LOCAL_P (x))
  	fputs ("@PLT", file);
--- 5791,5796 ----



More information about the Gcc-patches mailing list