[C++ patch]: reorganize tree inlining

Nathan Sidwell nathan@codesourcery.com
Sun Jul 1 13:02:00 GMT 2001


Hi,
this patch reorganizes the tree based inlining by breaking out the
inliner into a separate function (inline_into_function), and leaving
optimize_function to call the different tree optimizer functions
(of which there is only one at the moment).
It also adds a new ast dump, just after inlining.

This is in preparation to attacking the inliner heuristics.

booted & tested on i686-pc-linux-gnu, ok?

nathan

-- 
Dr Nathan Sidwell   ::   http://www.codesourcery.com   ::   CodeSourcery LLC
         'But that's a lie.' - 'Yes it is. What's your point?'
nathan@codesourcery.com : http://www.cs.bris.ac.uk/~nathan/ : nathan@acm.org
optimize1.patch

-------------- next part --------------
2001-07-01  Nathan Sidwell  <nathan@codesourcery.com>

	* optimize.c (inline_into_function): New function, broken out
	of ...
	(optimize_function): ... here. Call it. Don't inline if it is
	a thunk.
	(dump_function): Print name of dump flag causing this dump.
	* semantics.c (expand_body): Move thunk inline check to
	optimize_function.

2001-07-01  Nathan Sidwell  <nathan@codesourcery.com>

	* c-common.h (TDI_inlined): New ast dump phase.
	(dump_flag_name): New function.
	* c-dump.c (dump_files): Add inlined phase.
	(dump_flag_name): Define.
	* doc/invoke.texi (-fdump-ast-inlined): Document.

Index: cp/optimize.c
===================================================================
RCS file: /cvs/gcc/egcs/gcc/cp/optimize.c,v
retrieving revision 1.73
diff -c -3 -p -r1.73 optimize.c
*** optimize.c	2001/06/05 08:03:45	1.73
--- optimize.c	2001/06/29 14:58:17
*************** typedef struct inline_data
*** 78,84 ****
    int inlined_stmts;
    /* We use the same mechanism to build clones that we do to perform
       inlining.  However, there are a few places where we need to
!      distinguish between those two situations.  This flag is true nif
       we are cloning, rather than inlining.  */
    bool cloning_p;
    /* Hash table used to prevent walk_tree from visiting the same node
--- 78,84 ----
    int inlined_stmts;
    /* We use the same mechanism to build clones that we do to perform
       inlining.  However, there are a few places where we need to
!      distinguish between those two situations.  This flag is true if
       we are cloning, rather than inlining.  */
    bool cloning_p;
    /* Hash table used to prevent walk_tree from visiting the same node
*************** static int inlinable_function_p PARAMS (
*** 98,103 ****
--- 98,104 ----
  static tree remap_decl PARAMS ((tree, inline_data *));
  static void remap_block PARAMS ((tree, tree, inline_data *));
  static void copy_scope_stmt PARAMS ((tree *, int *, inline_data *));
+ static void inline_into_function PARAMS ((tree));
  static tree calls_setjmp_r PARAMS ((tree *, int *, void *));
  static void update_cloned_parm PARAMS ((tree, tree));
  static void dump_function PARAMS ((enum tree_dump_index, tree));
*************** expand_calls_inline (tp, id)
*** 934,939 ****
--- 935,1003 ----
    walk_tree (tp, expand_call_inline, id, id->tree_pruner);
  }
  
+ /* Expand calls to inline functions.  */
+ 
+ static void
+ inline_into_function (fn)
+      tree fn;
+ {
+   inline_data id;
+   tree prev_fn;
+   struct saved_scope *s;
+   
+   /* Clear out ID.  */
+   memset (&id, 0, sizeof (id));
+ 
+   /* Don't allow recursion into FN.  */
+   VARRAY_TREE_INIT (id.fns, 32, "fns");
+   VARRAY_PUSH_TREE (id.fns, fn);
+   /* Or any functions that aren't finished yet.  */
+   prev_fn = NULL_TREE;
+   if (current_function_decl)
+     {
+       VARRAY_PUSH_TREE (id.fns, current_function_decl);
+       prev_fn = current_function_decl;
+     }
+   for (s = scope_chain; s; s = s->prev)
+     if (s->function_decl && s->function_decl != prev_fn)
+       {
+ 	VARRAY_PUSH_TREE (id.fns, s->function_decl);
+ 	prev_fn = s->function_decl;
+       }
+   
+   /* Create the stack of TARGET_EXPRs.  */
+   VARRAY_TREE_INIT (id.target_exprs, 32, "target_exprs");
+ 
+   /* Create the list of functions this call will inline.  */
+   VARRAY_TREE_INIT (id.inlined_fns, 32, "inlined_fns");
+ 
+   /* Keep track of the low-water mark, i.e., the point where the first
+      real inlining is represented in ID.FNS.  */
+   id.first_inlined_fn = VARRAY_ACTIVE_SIZE (id.fns);
+ 
+   /* Replace all calls to inline functions with the bodies of those
+      functions.  */
+   id.tree_pruner = htab_create (37, htab_hash_pointer,
+ 				htab_eq_pointer, NULL);
+   expand_calls_inline (&DECL_SAVED_TREE (fn), &id);
+ 
+   /* Clean up.  */
+   htab_delete (id.tree_pruner);
+   VARRAY_FREE (id.fns);
+   VARRAY_FREE (id.target_exprs);
+   if (DECL_LANG_SPECIFIC (fn))
+     {
+       tree ifn = make_tree_vec (VARRAY_ACTIVE_SIZE (id.inlined_fns));
+       
+       memcpy (&TREE_VEC_ELT (ifn, 0), &VARRAY_TREE (id.inlined_fns, 0),
+ 	      VARRAY_ACTIVE_SIZE (id.inlined_fns) * sizeof (tree));
+       DECL_INLINED_FNS (fn) = ifn;
+     }
+   VARRAY_FREE (id.inlined_fns);
+   
+   dump_function (TDI_inlined, fn);
+ }
+ 
  /* Optimize the body of FN. */
  
  void
*************** optimize_function (fn)
*** 952,1016 ****
       must protect ourselves, just as we do while building up the body
       of the function.  */
    ++function_depth;
- 
-   /* Expand calls to inline functions.  */
-   if (flag_inline_trees)
-     {
-       inline_data id;
-       tree prev_fn;
-       struct saved_scope *s;
- 
-       /* Clear out ID.  */
-       memset (&id, 0, sizeof (id));
- 
-       /* Don't allow recursion into FN.  */
-       VARRAY_TREE_INIT (id.fns, 32, "fns");
-       VARRAY_PUSH_TREE (id.fns, fn);
-       /* Or any functions that aren't finished yet.  */
-       prev_fn = NULL_TREE;
-       if (current_function_decl)
- 	{
- 	  VARRAY_PUSH_TREE (id.fns, current_function_decl);
- 	  prev_fn = current_function_decl;
- 	}
-       for (s = scope_chain; s; s = s->prev)
- 	if (s->function_decl && s->function_decl != prev_fn)
- 	  {
- 	    VARRAY_PUSH_TREE (id.fns, s->function_decl);
- 	    prev_fn = s->function_decl;
- 	  }
- 
-       /* Create the stack of TARGET_EXPRs.  */
-       VARRAY_TREE_INIT (id.target_exprs, 32, "target_exprs");
- 
-       /* Create the list of functions this call will inline.  */
-       VARRAY_TREE_INIT (id.inlined_fns, 32, "inlined_fns");
- 
-       /* Keep track of the low-water mark, i.e., the point where
- 	 the first real inlining is represented in ID.FNS.  */
-       id.first_inlined_fn = VARRAY_ACTIVE_SIZE (id.fns);
- 
-       /* Replace all calls to inline functions with the bodies of those
- 	 functions.  */
-       id.tree_pruner = htab_create (37, htab_hash_pointer,
- 				    htab_eq_pointer, NULL);
-       expand_calls_inline (&DECL_SAVED_TREE (fn), &id);
- 
-       /* Clean up.  */
-       htab_delete (id.tree_pruner);
-       VARRAY_FREE (id.fns);
-       VARRAY_FREE (id.target_exprs);
-       if (DECL_LANG_SPECIFIC (fn))
- 	{
- 	  tree ifn = make_tree_vec (VARRAY_ACTIVE_SIZE (id.inlined_fns));
  
! 	  memcpy (&TREE_VEC_ELT (ifn, 0), &VARRAY_TREE (id.inlined_fns, 0),
! 		  VARRAY_ACTIVE_SIZE (id.inlined_fns) * sizeof (tree));
! 	  DECL_INLINED_FNS (fn) = ifn;
! 	}
!       VARRAY_FREE (id.inlined_fns);
!     }
! 
    /* Undo the call to ggc_push_context above.  */
    --function_depth;
    
--- 1016,1030 ----
       must protect ourselves, just as we do while building up the body
       of the function.  */
    ++function_depth;
  
!   if (flag_inline_trees
!       /* We do not inline thunks, as (a) the backend tries to optimize
!          the call to the thunkee, (b) tree based inlining breaks that
!          optimization, (c) virtual functions are rarely inlineable,
!          and (d) ASM_OUTPUT_MI_THUNK is there to DTRT anyway.  */
!       && !DECL_THUNK_P (fn))
!     inline_into_function (fn);
!   
    /* Undo the call to ggc_push_context above.  */
    --function_depth;
    
*************** dump_function (phase, fn)
*** 1246,1252 ****
      {
        fprintf (stream, "\n;; Function %s",
  	       decl_as_string (fn, TFF_DECL_SPECIFIERS));
!       fprintf (stream, " (%s)", decl_as_string (DECL_ASSEMBLER_NAME (fn), 0));
        fprintf (stream, "\n\n");
        
        dump_node (fn, TDF_SLIM | flags, stream);
--- 1260,1268 ----
      {
        fprintf (stream, "\n;; Function %s",
  	       decl_as_string (fn, TFF_DECL_SPECIFIERS));
!       fprintf (stream, " (%s)\n",
! 	       decl_as_string (DECL_ASSEMBLER_NAME (fn), 0));
!       fprintf (stream, ";; enabled by -%s", dump_flag_name (phase));
        fprintf (stream, "\n\n");
        
        dump_node (fn, TDF_SLIM | flags, stream);
Index: cp/semantics.c
===================================================================
RCS file: /cvs/gcc/egcs/gcc/cp/semantics.c,v
retrieving revision 1.214
diff -c -3 -p -r1.214 semantics.c
*** semantics.c	2001/06/18 16:15:12	1.214
--- semantics.c	2001/06/29 14:58:18
*************** expand_body (fn)
*** 2408,2420 ****
  
    timevar_push (TV_INTEGRATION);
  
!   /* Optimize the body of the function before expanding it.  We do not
!      optimize thunks, as (1) the backend tries to optimize the call to
!      the thunkee, (b) the tree based inliner breaks that optimization,
!      (c) virtual functions are rarely inlineable, and (d)
!      ASM_OUTPUT_MI_THUNK is there to DTRT anyway.  */
!   if (!DECL_THUNK_P (fn))
!     optimize_function (fn);
  
    timevar_pop (TV_INTEGRATION);
    timevar_push (TV_EXPAND);
--- 2408,2415 ----
  
    timevar_push (TV_INTEGRATION);
  
!   /* Optimize the body of the function before expanding it.  */
!   optimize_function (fn);
  
    timevar_pop (TV_INTEGRATION);
    timevar_push (TV_EXPAND);
Index: c-common.h
===================================================================
RCS file: /cvs/gcc/egcs/gcc/c-common.h,v
retrieving revision 1.75
diff -c -3 -p -r1.75 c-common.h
*** c-common.h	2001/06/18 16:15:01	1.75
--- c-common.h	2001/06/29 14:58:19
*************** enum tree_dump_index
*** 814,821 ****
  {
    TDI_all,			/* dump the whole translation unit */
    TDI_original,			/* dump each function before optimizing it */
!   TDI_optimized,			/* dump each function after optimizing it */
    TDI_class,			/* dump class heirarchy */
    TDI_end
  };
  
--- 814,823 ----
  {
    TDI_all,			/* dump the whole translation unit */
    TDI_original,			/* dump each function before optimizing it */
!   TDI_optimized,		/* dump each function after optimizing it */
    TDI_class,			/* dump class heirarchy */
+   TDI_inlined,			/* dump each function after inlining
+ 				   within it. */
    TDI_end
  };
  
*************** extern FILE *dump_begin			PARAMS ((enum 
*** 839,844 ****
--- 841,847 ----
  extern void dump_end			PARAMS ((enum tree_dump_index, FILE *));
  extern void dump_node			PARAMS ((tree, int, FILE *));
  extern int dump_switch_p                PARAMS ((const char *));
+ extern const char *dump_flag_name	PARAMS ((enum tree_dump_index));
  
  /* Information recorded about each file examined during compilation.  */
  
Index: doc/invoke.texi
===================================================================
RCS file: /cvs/gcc/egcs/gcc/doc/invoke.texi,v
retrieving revision 1.24
diff -c -3 -p -r1.24 invoke.texi
*** invoke.texi	2001/06/27 15:04:15	1.24
--- invoke.texi	2001/06/29 14:58:24
*************** in the following sections.
*** 239,244 ****
--- 239,245 ----
  -a  -ax  -d@var{letters}  -dumpspecs  -dumpmachine  -dumpversion @gol
  -fdump-unnumbered -fdump-translation-unit@r{[}-@var{n}@r{]} -fdump-class-hierarchy@r{[}-@var{n}@r{]} @gol
  -fdump-ast-original@r{[}-@var{n}@r{]} -fdump-ast-optimized@r{[}-@var{n}@r{]} @gol
+ -fdump-ast-inlined@r{[}-@var{n}@r{]} @gol
  -fmem-report  -fpretend-float @gol
  -fprofile-arcs  -ftest-coverage  -ftime-report @gol
  -g  -g@var{level}  -gcoff  -gdwarf  -gdwarf-1  -gdwarf-1+  -gdwarf-2 @gol
*************** The following tree dumps are possible:
*** 3029,3034 ****
--- 3030,3038 ----
  Dump before any tree based optimization, to @file{@var{file}.original}.
  @item optimized
  Dump after all tree based optimization, to @file{@var{file}.optimized}.
+ @item inlined
+ Dump after inlining within the body of the function, to
+ @file{@var{file}.inlined}.
  @end table
  
  @item -fpretend-float
Index: c-dump.c
===================================================================
RCS file: /cvs/gcc/egcs/gcc/c-dump.c,v
retrieving revision 1.4
diff -c -3 -p -r1.4 c-dump.c
*** c-dump.c	2001/06/05 08:03:44	1.4
--- c-dump.c	2001/07/01 19:44:57
*************** static struct dump_file_info dump_files[
*** 802,807 ****
--- 802,808 ----
    {".original", "dump-ast-original", 0, 0},
    {".optimized", "dump-ast-optimized", 0, 0},
    {".class", "dump-class-hierarchy", 0, 0},
+   {".inlined", "dump-ast-inlined", 0, 0},
  };
  
  /* Begin a tree dump for PHASE. Stores any user supplied flag in
*************** dump_begin (phase, flag_ptr)
*** 835,850 ****
  
  /* Returns non-zero if tree dump PHASE is enabled. */
  
! int dump_enabled_p (phase)
       enum tree_dump_index phase;
  {
    return dump_files[phase].state;
  }
  
  /* Finish a tree dump for PHASE. STREAM is the stream created by
     dump_begin. */
  
! void dump_end (phase, stream)
       enum tree_dump_index phase ATTRIBUTE_UNUSED;
       FILE *stream;
  {
--- 836,862 ----
  
  /* Returns non-zero if tree dump PHASE is enabled. */
  
! int
! dump_enabled_p (phase)
       enum tree_dump_index phase;
  {
    return dump_files[phase].state;
  }
  
+ /* Returns the switch name of PHASE. */
+ 
+ const char *
+ dump_flag_name (phase)
+      enum tree_dump_index phase;
+ {
+   return dump_files[phase].swtch;
+ }
+ 
  /* Finish a tree dump for PHASE. STREAM is the stream created by
     dump_begin. */
  
! void
! dump_end (phase, stream)
       enum tree_dump_index phase ATTRIBUTE_UNUSED;
       FILE *stream;
  {
*************** void dump_end (phase, stream)
*** 854,860 ****
  /* Parse ARG as a dump switch. Return non-zero if it is, and store the
     relevant details in the dump_files array. */
  
! int dump_switch_p (arg)
       const char *arg;
  {
    unsigned ix;
--- 866,873 ----
  /* Parse ARG as a dump switch. Return non-zero if it is, and store the
     relevant details in the dump_files array. */
  
! int
! dump_switch_p (arg)
       const char *arg;
  {
    unsigned ix;


More information about the Gcc-patches mailing list