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]

C++ PATCH for inline memory bug (version 2)



Here is finally a corrected version of the patch allowing the user
to limit the inline expansion of functions. I think (hope) that I have
taken all your remarks into account.

I sending it with the hope that 
it can make its way into
egcs-1.2 (but I'm not pushing for it).

[ Full testing is in progress (just finished stage 1), but a very 
similar version of this patch is working here for 3 months now ].

	Thank's 

		Theo.

-----------------------------------------------------------------------

The following patch corrects the problem exposed by the following 
piece of code.

//u/corse/2/robotvis/gnu/bin/egcs/bin/g++ -ftemplate-depth-100 -O4 MemBug.C

template <int n>
class X {

public:
  
  X() {
    X<n-1> x, y;
  }
};

template <>
class X<0> {
};

int main() {
  X<36> x; //internal compiler error
}

The problem is that functions can grow arbitrarily large through 
inline integration which cause memory exhaustion. The solution 
proposed is to limit the size of such functions but to add
another flag -finline-limit-<n> to avoid an arbitrary constant to be
built in the compiler. <n> corresponds to the maximum number of
instructions a function may have to be inlined.

Note: 1) in this, my patch is differing from that of Mike. IMHO an
absolute value for <n> is much much more natural than specifying
a scale factor. As noted in previous comments, instruction means
whatever gcc decides and I hope I made it clear enough in the
documentation.

2) The flag alters gcc's behaviour only for ``inline marked''
functions. Other functions are still inlined using the old
thresholds (INTEGRATE_THRESHOLD). The default value 10000 is
high to match current egcs capabilties.

3) I have not added the example above to the testsuite as it
can take awfully long before crashing.... but as I understood in a
recent message, these cases are protected by a timeout, so I'm prepared
to add such a test case if you think this is necessary.

ChangeLog:
Wed Apr	 21 23:28:37 1999  Theodore Papadopoulo <Theodore.Papadopoulo@sophia.inria.fr>

	Based on a patch by Mike Stump (mrs@wrs.com)

 	* flags.h: Declare inline_max_insns used to control the size of
 	functions that will get inlined.
 	* integrate.c: Define it here...
 	(function_cannot_inline_p): and use it here. 
 	* toplevl.c (main): Add the flag -finline-limit-n.
 	(display_help): Document it here...
 	* invoke.texi: and here.

Index: flags.h
===================================================================
RCS file: /egcs/carton/cvsfiles/egcs/gcc/flags.h,v
retrieving revision 1.25
diff -c -3 -p -r1.25 flags.h
*** flags.h	1999/01/31 17:46:18	1.25
--- flags.h	1999/04/21 23:28:37
*************** extern int current_function_is_thunk;
*** 507,512 ****
--- 507,516 ----
  extern int g_switch_value;
  extern int g_switch_set;
  
+ /* Value of the -finline-limit flag.  */
+ 
+ extern int inline_max_insns;
+ 
  /* Nonzero if we dump in VCG format, not plain text.  */
  extern int dump_for_graph;
  
Index: integrate.c
===================================================================
RCS file: /egcs/carton/cvsfiles/egcs/gcc/integrate.c,v
retrieving revision 1.53
diff -c -3 -p -r1.53 integrate.c
*** integrate.c	1999/04/14 20:28:51	1.53
--- integrate.c	1999/04/21 23:28:38
*************** static void process_reg_param		PROTO((st
*** 86,91 ****
--- 86,101 ----
  
  void set_decl_abstract_flags		PROTO((tree, int));
  static tree copy_and_set_decl_abstract_origin PROTO((tree));
+ 
+ /* The maximum number of instructions accepted for inlining a
+    function. Increasing values mean more agressive inlining.
+    This affects currently only functions explicitly marked as
+    inline (or methods defined within the class definition for C++).
+    The default value of 10000 is arbitrary but high to match the
+    previously unlimited gcc capabilities.  */
+ 
+ int inline_max_insns = 10000;
+ 
  
  /* Returns the Ith entry in the label_map contained in MAP.  If the
     Ith entry has not yet been set, return a fresh label.  This function
*************** function_cannot_inline_p (fndecl)
*** 116,122 ****
  {
    register rtx insn;
    tree last = tree_last (TYPE_ARG_TYPES (TREE_TYPE (fndecl)));
!   int max_insns = INTEGRATE_THRESHOLD (fndecl);
    register int ninsns = 0;
    register tree parms;
    rtx result;
--- 126,141 ----
  {
    register rtx insn;
    tree last = tree_last (TYPE_ARG_TYPES (TREE_TYPE (fndecl)));
! 
!   /* For functions marked as inline increase the maximum size to
!      inline_max_insns (-finline-limit-<n>). For regular functions
!      use the limit given by INTEGRATE_THRESHOLD.  */
! 
!   int max_insns = (DECL_INLINE (fndecl))
!                     ? inline_max_insns +
! 					  8 * list_length (DECL_ARGUMENTS (fndecl))
!                     : INTEGRATE_THRESHOLD (fndecl);
! 
    register int ninsns = 0;
    register tree parms;
    rtx result;
*************** function_cannot_inline_p (fndecl)
*** 136,142 ****
      return current_function_cannot_inline;
  
    /* If its not even close, don't even look.  */
!   if (!DECL_INLINE (fndecl) && get_max_uid () > 3 * max_insns)
      return N_("function too large to be inline");
  
  #if 0
--- 155,161 ----
      return current_function_cannot_inline;
  
    /* If its not even close, don't even look.  */
!   if (get_max_uid () > 3 * max_insns)
      return N_("function too large to be inline");
  
  #if 0
*************** function_cannot_inline_p (fndecl)
*** 170,176 ****
  	return N_("function with transparent unit parameter cannot be inline");
      }
  
!   if (!DECL_INLINE (fndecl) && get_max_uid () > max_insns)
      {
        for (ninsns = 0, insn = get_first_nonparm_insn ();
  	   insn && ninsns < max_insns;
--- 189,195 ----
  	return N_("function with transparent unit parameter cannot be inline");
      }
  
!   if (get_max_uid () > max_insns)
      {
        for (ninsns = 0, insn = get_first_nonparm_insn ();
  	   insn && ninsns < max_insns;
Index: invoke.texi
===================================================================
RCS file: /egcs/carton/cvsfiles/egcs/gcc/invoke.texi,v
retrieving revision 1.108
diff -c -3 -p -r1.108 invoke.texi
*** invoke.texi	1999/04/18 01:35:07	1.108
--- invoke.texi	1999/04/21 23:28:39
*************** in the following sections.
*** 154,160 ****
  -fdelayed-branch   -fexpensive-optimizations
  -ffast-math  -ffloat-store  -fforce-addr  -fforce-mem
  -fdata-sections -ffunction-sections  -fgcse 
! -finline-functions -fkeep-inline-functions
  -fno-default-inline -fno-defer-pop  -fno-function-cse
  -fno-inline  -fno-peephole  -fomit-frame-pointer -fregmove
  -frerun-cse-after-loop  -frerun-loop-opt -fschedule-insns
--- 154,160 ----
  -fdelayed-branch   -fexpensive-optimizations
  -ffast-math  -ffloat-store  -fforce-addr  -fforce-mem
  -fdata-sections -ffunction-sections  -fgcse 
! -finline-functions -finline-limit-@var{n} -fkeep-inline-functions
  -fno-default-inline -fno-defer-pop  -fno-function-cse
  -fno-inline  -fno-peephole  -fomit-frame-pointer -fregmove
  -frerun-cse-after-loop  -frerun-loop-opt -fschedule-insns
*************** integrating in this way.
*** 2301,2306 ****
--- 2301,2323 ----
  If all calls to a given function are integrated, and the function is
  declared @code{static}, then the function is normally not output as
  assembler code in its own right.
+ 
+ @item -finline-limit-@var{n}
+ By default, gcc limits the size of functions that can be inlined.  This flag
+ allows the control of this limit for functions that are explicitly marked as
+ inline (ie marked with the inline keyword or defined within the class 
+ definition in c++).  @var{n} is the size of functions that can be inlined in 
+ number of instructions (not counting parameter handling).  The default value
+ of n is 10000.  Increasing this value can result in more inlined code at the
+ cost of compilation time and memory consumption.  Decreasing usually makes the
+ compilation faster and less code will be inlined (which presumably 
+ means slower programs).  This option is particularly useful for programs that 
+ use inlining heavily such as those based on recursive templates with c++.
+ 
+ @emph{Note:} the word instruction represents, in this particular context, an
+ abstract measurement of function's size.  In no way, it represents a count
+ of assembly instructions and as such its exact meaning might change from one
+ release to an another.
  
  @item -fkeep-inline-functions
  Even if all calls to a given function are integrated, and the function
Index: toplev.c
===================================================================
RCS file: /egcs/carton/cvsfiles/egcs/gcc/toplev.c,v
retrieving revision 1.176
diff -c -3 -p -r1.176 toplev.c
*** toplev.c	1999/04/18 13:09:23	1.176
--- toplev.c	1999/04/21 23:28:45
*************** display_help ()
*** 4455,4460 ****
--- 4455,4461 ----
    printf ("  -ffixed-<register>      Mark <register> as being unavailable to the compiler\n");
    printf ("  -fcall-used-<register>  Mark <register> as being corrupted by function calls\n");
    printf ("  -fcall-saved-<register> Mark <register> as being preserved across functions\n");
+   printf ("  -finline-limit-<number> Limits the size of inlined functions to <number>\n");
  
    for (i = NUM_ELEM (f_options); i--;)
      {
*************** main (argc, argv)
*** 5029,5034 ****
--- 5030,5038 ----
  
  	      if (found)
  		;
+ 	      else if (!strncmp (p, "inline-limit-", 13))
+ 	        inline_max_insns =
+ 		  read_integral_parameter (p + 13, p - 2, inline_max_insns);
  #ifdef HAIFA
  #ifdef INSN_SCHEDULING
  	      else if (!strncmp (p, "sched-verbose-",14))



 --------------------------------------------------------------------
 Theodore Papadopoulo
 Email: Theodore.Papadopoulo@sophia.inria.fr Tel: (33) 04 92 38 76 01
 --------------------------------------------------------------------





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