This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[tree-profiling] reorganization of static initializers analysis


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 ----


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]