(C++) patch to change deferring of templates

Jason Merrill jason@cygnus.com
Thu Jan 6 23:06:00 GMT 2000


On 11-13 I changed comdat_linkage to set DECL_DEFER_OUTPUT, so as to
avoid emitting unneeded template instantiations for code like

  template <class T> void g () { }

  inline void f () { g<int>(); }

  int main ()
  {
  }

This caused memory usage to increase significantly, since now many
instantiations were being kept in memory where previously they had
been written out and forgotten.  This patch reduces that penalty
by not deferring things that we already know will be needed, but does
not eliminate it.  See the comment in instantiate_decl for more
discussion.

2000-01-06  Jason Merrill  <jason@casey.cygnus.com>

	* decl2.c (comdat_linkage): Don't set DECL_DEFER_OUTPUT.
	* pt.c (instantiate_decl): Defer comdat templates that might not be
	needed.
	
Index: decl2.c
===================================================================
RCS file: /cvs/gcc/egcs/gcc/cp/decl2.c,v
retrieving revision 1.293
diff -c -p -r1.293 decl2.c
*** decl2.c	2000/01/05 11:45:33	1.293
--- decl2.c	2000/01/07 06:00:15
*************** comdat_linkage (decl)
*** 2347,2355 ****
  
    if (DECL_LANG_SPECIFIC (decl))
      DECL_COMDAT (decl) = 1;
- 
-   if (TREE_CODE (decl) == FUNCTION_DECL)
-     DECL_DEFER_OUTPUT (decl) = 1;
  }
  
  /* For win32 we also want to put explicit instantiations in
--- 2347,2352 ----
Index: pt.c
===================================================================
RCS file: /cvs/gcc/egcs/gcc/cp/pt.c,v
retrieving revision 1.389
diff -c -p -r1.389 pt.c
*** pt.c	1999/12/21 00:19:01	1.389
--- pt.c	2000/01/07 06:00:21
*************** instantiate_decl (d)
*** 9385,9390 ****
--- 9385,9391 ----
    int pattern_defined;
    int line = lineno;
    char *file = input_filename;
+   tree old_fn = current_function_decl;
  
    /* This function should only be used to instantiate templates for
       functions and static member variables.  */
*************** instantiate_decl (d)
*** 9510,9523 ****
        && DECL_INITIAL (d) == NULL_TREE
        && DECL_INITIAL (code_pattern) != NULL_TREE)
      /* We need to set up DECL_INITIAL regardless of pattern_defined if
! 	 the variable is a static const initialized in the class body.  */;
!   else if (! pattern_defined
! 	   || (! (TREE_CODE (d) == FUNCTION_DECL && DECL_INLINE (d) && nested)
! 	       && ! at_eof))
      {
!       /* Defer all templates except inline functions used in another
!          function.  We restore the source position here because it's used
!          by add_pending_template.  */
        lineno = line;
        input_filename = file;
  
--- 9511,9525 ----
        && DECL_INITIAL (d) == NULL_TREE
        && DECL_INITIAL (code_pattern) != NULL_TREE)
      /* We need to set up DECL_INITIAL regardless of pattern_defined if
!        the variable is a static const initialized in the class body.  */;
!   else if (pattern_defined && nested
! 	   && TREE_CODE (d) == FUNCTION_DECL && DECL_INLINE (d))
!     /* An inline function used in another function; instantiate it now so
!        we can inline it.  */;
!   else if (! pattern_defined || ! at_eof)
      {
!       /* Defer all other templates.  We restore the source position
!          here because it's used by add_pending_template.  */
        lineno = line;
        input_filename = file;
  
*************** instantiate_decl (d)
*** 9536,9541 ****
--- 9538,9562 ----
        add_pending_template (d);
        goto out;
      }
+ 
+   /* If this instantiation is COMDAT, we don't know whether or not we
+      will really need to write it out.  If we can't be sure, mark it
+      DECL_DEFER_OUTPUT.  NOTE: This increases memory consumption,
+      since we keep some instantiations in memory rather than write
+      them out immediately and forget them.  A better approach would be
+      to wait until we know we need them to do the instantiation, but
+      that would break templates with static locals, because we
+      generate the functions to destroy statics before we determine
+      which functions are needed.  A better solution would be to
+      generate the ctor and dtor functions as we go.  */
+ 
+   if (TREE_CODE (d) == FUNCTION_DECL
+       && DECL_COMDAT (d)
+       && ! DECL_NEEDED_P (d)
+       /* If the function that caused us to be instantiated is needed, we
+ 	 will be needed, too.  */
+       && (! nested || ! DECL_NEEDED_P (old_fn)))
+     DECL_DEFER_OUTPUT (d) = 1;
  
    /* We're now committed to instantiating this template.  Mark it as
       instantiated so that recursive calls to instantiate_decl do not


More information about the Gcc-patches mailing list