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]

[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;
 


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