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]

[PATCH][LTO] Stream BLOCK_VARS lazily


This makes us stream BLOCK_VARS lazily and save 40% (yes!) WPA memory
on 447.dealII.

For testing I added some checking code at streaming time that
BLOCK_VARS works as I think it does.  I also disabled all mucking
with DECL_CONTEXT in free_lang_data_in_decl, something that is
pending in another patch to improve debug information with LTO.
I'd like to combine this with the lazy BLOCK_VARS streaming.

The patch also fixes an ICE in expr.c I run into earlier with
the non-clearing of DECL_CONTEXT, it's pretty obvious (at LTRANS
stage we have DECL_EXTERNAL inlined local static from another unit).

As for the checking code in lto-streamer-out.c I plan to at least
remove the quadratic loop before committing, eventually also the
assert, as maybe the BLOCK_VARS working (vs. BLOCK_NONLOCALIZED_VARS)
is really obvious(?)

Bootstrapped on x86_64-unknown-linux-gnu, SPEC 2k6 built w/o
regressions but faster and with less memory usage (despite the tree.c
change), testing in progress (the LTO testsuite was fine).  I'm now
testing SPEC 2k6 build with -g enabled in addition to -fwhopr.

Ok for trunk?

Thanks,
Richard.

2010-10-08  Richard Guenther  <rguenther@suse.de>

	* lto-streamer-in.c (lto_input_ts_decl_minimal_tree_pointers):
	Re-construct BLOCK_VARS.
	(lto_input_ts_block_tree_pointers): Do not stream BLOCK_VARS.
	* lto-streamer-out.c (lto_output_ts_block_tree_pointers): Likewise.
	* tree.c (free_lang_data_in_block): Remove.
	(free_lang_data_in_decl): Do not touch DECL_CONTEXT of non-PARM_DECLs.
	Do not touch the BLOCK tree.
	* expr.c (expand_expr_real_1): Allow externals.

Index: trunk/gcc/lto-streamer-in.c
===================================================================
*** trunk.orig/gcc/lto-streamer-in.c	2010-10-08 12:48:08.000000000 +0200
--- trunk/gcc/lto-streamer-in.c	2010-10-08 13:14:56.000000000 +0200
*************** lto_input_ts_decl_minimal_tree_pointers
*** 1945,1950 ****
--- 1945,1957 ----
  {
    DECL_NAME (expr) = lto_input_tree (ib, data_in);
    DECL_CONTEXT (expr) = lto_input_tree (ib, data_in);
+   /* We do not stream BLOCK_VARS but lazily construct it here.  */
+   if (DECL_CONTEXT (expr)
+       && TREE_CODE (DECL_CONTEXT (expr)) == BLOCK)
+     {
+       TREE_CHAIN (expr) = BLOCK_VARS (DECL_CONTEXT (expr));
+       BLOCK_VARS (DECL_CONTEXT (expr)) = expr;
+     }
    DECL_SOURCE_LOCATION (expr) = lto_input_location (ib, data_in);
  }
  
*************** lto_input_ts_block_tree_pointers (struct
*** 2166,2172 ****
    unsigned i, len;
  
    BLOCK_SOURCE_LOCATION (expr) = lto_input_location (ib, data_in);
!   BLOCK_VARS (expr) = lto_input_chain (ib, data_in);
  
    len = lto_input_uleb128 (ib);
    if (len > 0)
--- 2173,2180 ----
    unsigned i, len;
  
    BLOCK_SOURCE_LOCATION (expr) = lto_input_location (ib, data_in);
!   /* We do not stream BLOCK_VARS but lazily construct it when reading
!      in decls.  */
  
    len = lto_input_uleb128 (ib);
    if (len > 0)
Index: trunk/gcc/lto-streamer-out.c
===================================================================
*** trunk.orig/gcc/lto-streamer-out.c	2010-10-08 12:48:08.000000000 +0200
--- trunk/gcc/lto-streamer-out.c	2010-10-08 13:15:42.000000000 +0200
*************** lto_output_ts_decl_minimal_tree_pointers
*** 832,837 ****
--- 832,848 ----
  {
    lto_output_tree_or_ref (ob, DECL_NAME (expr), ref_p);
    lto_output_tree_or_ref (ob, DECL_CONTEXT (expr), ref_p);
+   if (DECL_CONTEXT (expr)
+       && TREE_CODE (DECL_CONTEXT (expr)) == BLOCK)
+     {
+       tree t;
+       for (t = BLOCK_VARS (DECL_CONTEXT (expr));
+ 	   t;
+ 	   t = TREE_CHAIN (t))
+ 	if (t == expr)
+ 	  break;
+       gcc_assert (t != NULL_TREE);
+     }
    lto_output_location (ob, DECL_SOURCE_LOCATION (expr));
  }
  
*************** lto_output_ts_block_tree_pointers (struc
*** 1055,1065 ****
    tree t;
  
    lto_output_location (ob, BLOCK_SOURCE_LOCATION (expr));
!   lto_output_chain (ob, BLOCK_VARS (expr), ref_p);
  
    output_uleb128 (ob, VEC_length (tree, BLOCK_NONLOCALIZED_VARS (expr)));
    FOR_EACH_VEC_ELT (tree, BLOCK_NONLOCALIZED_VARS (expr), i, t)
!     lto_output_tree_or_ref (ob, t, ref_p);
  
    lto_output_tree_or_ref (ob, BLOCK_SUPERCONTEXT (expr), ref_p);
    lto_output_tree_or_ref (ob, BLOCK_ABSTRACT_ORIGIN (expr), ref_p);
--- 1066,1080 ----
    tree t;
  
    lto_output_location (ob, BLOCK_SOURCE_LOCATION (expr));
!   /* We do not stream BLOCK_VARS but lazily construct it when reading
!      in decls.  */
  
    output_uleb128 (ob, VEC_length (tree, BLOCK_NONLOCALIZED_VARS (expr)));
    FOR_EACH_VEC_ELT (tree, BLOCK_NONLOCALIZED_VARS (expr), i, t)
!     {
!       gcc_assert (DECL_CONTEXT (t) != expr);
!       lto_output_tree_or_ref (ob, t, ref_p);
!     }
  
    lto_output_tree_or_ref (ob, BLOCK_SUPERCONTEXT (expr), ref_p);
    lto_output_tree_or_ref (ob, BLOCK_ABSTRACT_ORIGIN (expr), ref_p);
Index: trunk/gcc/tree.c
===================================================================
*** trunk.orig/gcc/tree.c	2010-10-04 10:51:42.000000000 +0200
--- trunk/gcc/tree.c	2010-10-08 14:11:10.000000000 +0200
*************** need_assembler_name_p (tree decl)
*** 4455,4483 ****
  }
  
  
- /* Remove all the non-variable decls from BLOCK.  LOCALS is the set of
-    variables in DECL_STRUCT_FUNCTION (FN)->local_decls.  Every decl
-    in BLOCK that is not in LOCALS is removed.  */
- 
- static void
- free_lang_data_in_block (tree fn, tree block, struct pointer_set_t *locals)
- {
-   tree *tp, t;
- 
-   tp = &BLOCK_VARS (block);
-   while (*tp)
-     {
-       if (!pointer_set_contains (locals, *tp))
- 	*tp = TREE_CHAIN (*tp);
-       else
- 	tp = &TREE_CHAIN (*tp);
-     }
- 
-   for (t = BLOCK_SUBBLOCKS (block); t; t = BLOCK_CHAIN (t))
-     free_lang_data_in_block (fn, t, locals);
- }
- 
- 
  /* Reset all language specific information still present in symbol
     DECL.  */
  
--- 4455,4460 ----
*************** free_lang_data_in_decl (tree decl)
*** 4501,4516 ****
    if (DECL_NAME (decl))
      TREE_TYPE (DECL_NAME (decl)) = NULL_TREE;
  
-   /* Ignore any intervening types, because we are going to clear their
-      TYPE_CONTEXT fields.  */
-   if (TREE_CODE (decl) != FIELD_DECL
-       && TREE_CODE (decl) != FUNCTION_DECL)
-     DECL_CONTEXT (decl) = decl_function_context (decl);
- 
-   if (DECL_CONTEXT (decl)
-       && TREE_CODE (DECL_CONTEXT (decl)) == NAMESPACE_DECL)
-     DECL_CONTEXT (decl) = NULL_TREE;
- 
   if (TREE_CODE (decl) == VAR_DECL)
     {
       tree context = DECL_CONTEXT (decl);
--- 4478,4483 ----
*************** free_lang_data_in_decl (tree decl)
*** 4524,4532 ****
  	        all vars to global ones.  */
  	     DECL_INITIAL (decl) = NULL_TREE;
  	   }
- 
- 	 if (TREE_STATIC (decl))
- 	   DECL_CONTEXT (decl) = NULL_TREE;
         }
     }
  
--- 4491,4496 ----
*************** free_lang_data_in_decl (tree decl)
*** 4545,4552 ****
        if (gimple_has_body_p (decl))
  	{
  	  tree t;
- 	  unsigned ix;
- 	  struct pointer_set_t *locals;
  
  	  /* If DECL has a gimple body, then the context for its
  	     arguments must be DECL.  Otherwise, it doesn't really
--- 4509,4514 ----
*************** free_lang_data_in_decl (tree decl)
*** 4559,4580 ****
  	     the PARM_DECL will be used in the function's body).  */
  	  for (t = DECL_ARGUMENTS (decl); t; t = TREE_CHAIN (t))
  	    DECL_CONTEXT (t) = decl;
- 
- 	  /* Collect all the symbols declared in DECL.  */
- 	  locals = pointer_set_create ();
- 	  FOR_EACH_LOCAL_DECL (DECL_STRUCT_FUNCTION (decl), ix, t)
- 	    {
- 	      pointer_set_insert (locals, t);
- 
- 	      /* All the local symbols should have DECL as their
- 		 context.  */
- 	      DECL_CONTEXT (t) = decl;
- 	    }
- 
- 	  /* Get rid of any decl not in local_decls.  */
- 	  free_lang_data_in_block (decl, DECL_INITIAL (decl), locals);
- 
- 	  pointer_set_destroy (locals);
  	}
  
        /* DECL_SAVED_TREE holds the GENERIC representation for DECL.
--- 4521,4526 ----
*************** free_lang_data_in_decl (tree decl)
*** 4588,4602 ****
  	DECL_INITIAL (decl) = NULL_TREE;
      }
    else if (TREE_CODE (decl) == TYPE_DECL)
!     {
!       DECL_INITIAL (decl) = NULL_TREE;
! 
!       /* DECL_CONTEXT is overloaded as DECL_FIELD_CONTEXT for
! 	 FIELD_DECLs, which should be preserved.  Otherwise,
! 	 we shouldn't be concerned with source-level lexical
! 	 nesting beyond this point. */
!       DECL_CONTEXT (decl) = NULL_TREE;
!     }
  }
  
  
--- 4534,4540 ----
  	DECL_INITIAL (decl) = NULL_TREE;
      }
    else if (TREE_CODE (decl) == TYPE_DECL)
!     DECL_INITIAL (decl) = NULL_TREE;
  }
  
  
Index: trunk/gcc/expr.c
===================================================================
*** trunk.orig/gcc/expr.c	2010-10-05 12:16:54.000000000 +0200
--- trunk/gcc/expr.c	2010-10-08 13:46:43.000000000 +0200
*************** expand_expr_real_1 (tree exp, rtx target
*** 8448,8453 ****
--- 8448,8454 ----
        gcc_assert (!context
  		  || context == current_function_decl
  		  || TREE_STATIC (exp)
+ 		  || DECL_EXTERNAL (exp)
  		  /* ??? C++ creates functions that are not TREE_STATIC.  */
  		  || TREE_CODE (exp) == FUNCTION_DECL);
  


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