This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
[PATCH][LTO] Stream BLOCK_VARS lazily
- From: Richard Guenther <rguenther at suse dot de>
- To: gcc-patches at gcc dot gnu dot org
- Cc: Diego Novillo <dnovillo at google dot com>
- Date: Fri, 8 Oct 2010 14:27:46 +0200 (CEST)
- Subject: [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);