This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
[lto] Fix builtin streaming
- From: Diego Novillo <dnovillo at google dot com>
- To: gcc-patches at gcc dot gnu dot org
- Date: Fri, 15 May 2009 09:35:46 -0400
- Subject: [lto] Fix builtin streaming
The streamer was not dealing with builtins properly. When
writing an md/normal builtin we only need to write its class and
code, because the reading side will generate the same builtin
table on startup.
This fixes ~30 failures in check-gcc.
Tested on x86_64.
Diego.
* lto-symtab.c (lto_symtab_prevailing_decl): If DECL is a
builtin return it.
* lto-function-out.c (output_expr_operand)<FUNCTION_DECL>:
Set TAG to LTO_function_decl1 if EXPR is a builtin.
Otherwise, set it to LTO_function_decl0.
(output_function_decl): If DECL is a builtin, only write
its class and function code.
* lto-function-in.c (input_function_decl): Add argument TAG.
Update all users.
If TAG is LTO_function_decl1 retrieve the function symbol
from the built_in_decls array.
* lto-cgraph.c (input_node): Allow nodes of builtin
functions to be overwritten.
* lto-tree-tags.def: Add LTO_function_decl0 and
LTO_function_decl1.
Remove LTO_function_decl. Update all users.
* lto-tags.h (enum LTO_tags): Add LTO_function_decl0 and
LTO_function_decl1.
Remove LTO_function_decl.
lto/ChangeLog
* lto.c (lto_materialize_function): Assert that DECL is
not a builtin.
(materialize_cgraph): Don't try to materialize builtin
functions.
* lto-section-out.c (write_symbol_vec): Do not write
builtin functions.
Index: lto-symtab.c
===================================================================
--- lto-symtab.c (revision 147493)
+++ lto-symtab.c (working copy)
@@ -631,7 +631,8 @@ lto_symtab_prevailing_decl (tree decl)
tree ret;
gcc_assert (decl);
- if (!TREE_PUBLIC (decl))
+ /* Builtins and local symbols are their own prevailing decl. */
+ if (!TREE_PUBLIC (decl) || DECL_IS_BUILTIN (decl))
return decl;
/* FIXME lto. There should be no DECL_ABSTRACT in the middle end. */
Index: lto-function-out.c
===================================================================
--- lto-function-out.c (revision 147493)
+++ lto-function-out.c (working copy)
@@ -1109,6 +1109,7 @@ output_expr_operand (struct output_block
break;
case FUNCTION_DECL:
+ tag = DECL_IS_BUILTIN (expr) ? LTO_function_decl1 : LTO_function_decl0;
output_record_start (ob, NULL, NULL, tag);
lto_output_fn_decl_index (ob->decl_state, ob->main_stream, expr);
break;
@@ -2627,8 +2628,23 @@ output_function_decl (struct output_bloc
{
bool saved_external, saved_public;
- /* tag and flags */
- output_global_record_start (ob, NULL, NULL, LTO_function_decl);
+ global_vector_debug (ob);
+
+ /* If DECL is a builtin of class BUILT_IN_MD or BUILT_IN_NORMAL, we
+ only need to write its code and class. If DECL is BUILT_IN_FRONTEND
+ we have to write it out as a regular function. */
+ if (DECL_IS_BUILTIN (decl)
+ && (DECL_BUILT_IN_CLASS (decl) == BUILT_IN_NORMAL
+ || DECL_BUILT_IN_CLASS (decl) == BUILT_IN_MD))
+ {
+ output_global_record_start (ob, NULL, NULL, LTO_function_decl1);
+ output_uleb128 (ob, DECL_BUILT_IN_CLASS (decl));
+ output_uleb128 (ob, DECL_FUNCTION_CODE (decl));
+ LTO_DEBUG_TOKEN ("end_function_decl");
+ return;
+ }
+
+ output_global_record_start (ob, NULL, NULL, LTO_function_decl0);
/* This function is a cherry-picked inlined function. To avoid
multiple definition in the final link, we fake the function decl
@@ -2645,8 +2661,6 @@ output_function_decl (struct output_bloc
else
output_tree_flags (ob, ERROR_MARK, decl, true);
- global_vector_debug (ob);
-
/* uid and locus are handled specially */
output_tree (ob, decl->decl_minimal.name);
gcc_assert (decl->decl_minimal.context == NULL_TREE);
@@ -2696,8 +2710,11 @@ output_function_decl (struct output_bloc
else
output_uleb128 (ob, 0);
- output_uleb128 (ob, decl->function_decl.function_code);
- output_uleb128 (ob, decl->function_decl.built_in_class);
+ gcc_assert (!DECL_IS_BUILTIN (decl)
+ || DECL_BUILT_IN_CLASS (decl) == NOT_BUILT_IN
+ || DECL_BUILT_IN_CLASS (decl) == BUILT_IN_FRONTEND);
+ output_uleb128 (ob, DECL_BUILT_IN_CLASS (decl));
+ output_uleb128 (ob, DECL_FUNCTION_CODE (decl));
LTO_DEBUG_TOKEN ("end_function_decl");
}
Index: lto-function-in.c
===================================================================
--- lto-function-in.c (revision 147493)
+++ lto-function-in.c (working copy)
@@ -2610,16 +2610,41 @@ get_resolution (struct data_in *data_in,
/* Read a FUNCTION_DECL tree from input block IB using descriptors in
- DATA_IN. */
+ DATA_IN. TAG is one of LTO_function_decl0 or LTO_function_decl1. */
static tree
-input_function_decl (struct lto_input_block *ib, struct data_in *data_in)
+input_function_decl (struct lto_input_block *ib, struct data_in *data_in,
+ enum LTO_tags tag)
{
unsigned index;
unsigned has_personality;
- tree decl = make_node (FUNCTION_DECL);
+ tree decl;
+ lto_flags_type flags;
- lto_flags_type flags = input_tree_flags (ib, FUNCTION_DECL, true);
+ if (tag == LTO_function_decl1)
+ {
+ /* If we are going to read a built-in function, all we need is
+ the code and class. */
+ enum built_in_class fclass;
+ enum built_in_function fcode;
+
+ fclass = (enum built_in_class) lto_input_uleb128 (ib);
+ gcc_assert (fclass == BUILT_IN_NORMAL || fclass == BUILT_IN_MD);
+
+ fcode = (enum built_in_function) lto_input_uleb128 (ib);
+ gcc_assert (fcode < END_BUILTINS);
+
+ decl = built_in_decls[(size_t) fcode];
+ gcc_assert (decl);
+
+ global_vector_enter (data_in, decl);
+
+ LTO_DEBUG_TOKEN ("end_function_decl");
+ return decl;
+ }
+
+ decl = make_node (FUNCTION_DECL);
+ flags = input_tree_flags (ib, FUNCTION_DECL, true);
if (input_line_info (ib, data_in, flags))
set_line_info (data_in, decl);
process_tree_flags (decl, flags);
@@ -2651,11 +2676,13 @@ input_function_decl (struct lto_input_bl
else
decl->function_decl.personality = NULL ;
- decl->function_decl.function_code =
- (enum built_in_function) lto_input_uleb128 (ib);
- decl->function_decl.built_in_class =
- (enum built_in_class) lto_input_uleb128 (ib);
+ DECL_BUILT_IN_CLASS (decl) = (enum built_in_class) lto_input_uleb128 (ib);
+ gcc_assert (!DECL_IS_BUILTIN (decl)
+ || DECL_BUILT_IN_CLASS (decl) == NOT_BUILT_IN
+ || DECL_BUILT_IN_CLASS (decl) == BUILT_IN_FRONTEND);
+
+ DECL_FUNCTION_CODE (decl) = (enum built_in_function) lto_input_uleb128 (ib);
/* Need to ensure static entities between different files
don't clash unexpectedly. */
@@ -3343,7 +3370,7 @@ input_tree_operand (struct lto_input_blo
break;
case FUNCTION_DECL:
- result = input_function_decl (ib, data_in);
+ result = input_function_decl (ib, data_in, tag);
break;
case IMPORTED_DECL:
Index: lto-cgraph.c
===================================================================
--- lto-cgraph.c (revision 147493)
+++ lto-cgraph.c (working copy)
@@ -508,7 +508,14 @@ input_node (struct lto_file_decl_data *f
LTO_DEBUG_TOKEN ("inlined");
inlined = lto_input_uleb128 (ib);
- gcc_assert (!node->aux);
+ /* Make sure that we have not read this node before. Nodes that
+ have already been read will have their tag stored in the 'aux'
+ field. Since built-in functions can be referenced in multiple
+ functions, they are expected to be read more than once.
+ FIXME lto, this is wasteful and may lead to suboptimal code if
+ the different cgraph nodes for the same built-in have different
+ flags. */
+ gcc_assert (!node->aux || DECL_IS_BUILTIN (node->decl));
input_overwrite_node (file_data, node, tag, flags, stack_size, self_insns);
Index: lto-tree-tags.def
===================================================================
--- lto-tree-tags.def (revision 147493)
+++ lto-tree-tags.def (working copy)
@@ -58,6 +58,7 @@
MAP_EXPR_TAGS(VAR_DECL, LTO_var_decl0, 2)
MAP_EXPR_TAGS(LABEL_DECL, LTO_label_decl0, 2)
MAP_EXPR_TAGS(VECTOR_CST, LTO_vector_cst0, 2)
+ MAP_EXPR_TAGS(FUNCTION_DECL, LTO_function_decl0, 2)
#endif
#ifdef TREE_SINGLE_MECHANICAL_FALSE
@@ -73,7 +74,6 @@
MAP_EXPR_TAG(FIELD_DECL, LTO_field_decl)
MAP_EXPR_TAG(FIXED_CST, LTO_fixed_cst)
MAP_EXPR_TAG(FIXED_POINT_TYPE, LTO_fixed_point_type)
- MAP_EXPR_TAG(FUNCTION_DECL, LTO_function_decl)
MAP_EXPR_TAG(FUNCTION_TYPE, LTO_function_type)
MAP_EXPR_TAG(IDENTIFIER_NODE, LTO_identifier_node)
MAP_EXPR_TAG(INTEGER_CST, LTO_integer_cst)
@@ -246,7 +246,8 @@
SET_NAME (LTO_float_expr, "float_expr")
SET_NAME (LTO_floor_div_expr, "floor_div_expr")
SET_NAME (LTO_floor_mod_expr, "floor_mod_expr")
- SET_NAME (LTO_function_decl, "function_decl")
+ SET_NAME (LTO_function_decl0, "function_decl0")
+ SET_NAME (LTO_function_decl1, "function_decl1")
SET_NAME (LTO_ge_expr, "ge_expr")
SET_NAME (LTO_goto_expr, "goto_expr")
SET_NAME (LTO_gt_expr, "gt_expr")
Index: lto-tags.h
===================================================================
--- lto-tags.h (revision 147493)
+++ lto-tags.h (working copy)
@@ -354,7 +354,11 @@ enum LTO_tags
LTO_float_expr,
LTO_floor_div_expr,
LTO_floor_mod_expr,
- LTO_function_decl,
+
+ /* 1 for built-in functions, 0 for regular functions. */
+ LTO_function_decl0,
+ LTO_function_decl1,
+
LTO_ge_expr,
LTO_goto_expr,
LTO_gt_expr,
Index: lto/lto.c
===================================================================
--- lto/lto.c (revision 147493)
+++ lto/lto.c (working copy)
@@ -93,6 +93,8 @@ lto_materialize_function (struct cgraph_
{
struct function *fn;
+ gcc_assert (!DECL_IS_BUILTIN (decl));
+
/* This function has a definition. */
TREE_STATIC (decl) = 1;
@@ -1718,7 +1720,13 @@ materialize_cgraph (void)
for (node = cgraph_nodes; node; node = node->next)
{
- lto_materialize_function (node);
+ /* Builtin functions need not be materialized and may, in fact,
+ cause confusion because there may be a regular function in
+ the file whose assembler name matches that of the function
+ (e.g., testsuite/gcc.c-torture/execute/20030125-1.c). */
+ if (!DECL_IS_BUILTIN (node->decl))
+ lto_materialize_function (node);
+
lto_stats.num_input_cgraph_nodes++;
}
Index: lto-section-out.c
===================================================================
--- lto-section-out.c (revision 147493)
+++ lto-section-out.c (working copy)
@@ -1114,6 +1114,9 @@ write_symbol_vec (htab_t hash, struct lt
if (!TREE_PUBLIC (t))
continue;
+ if (DECL_IS_BUILTIN (t))
+ continue;
+
if (incorporeal_function_p (t))
continue;