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 the block chain


Occasionally, as evidenced by compiling gcc/caller-save.c and 176.gcc,
we would segfault in set_bb_for_stmt when attempting to grow the
label_to_block_map during expand.  The problem was that we were not
faithfully recreating the basic block chain, causing some unexpected
code in cfgexpand.c:construct_init_block to trigger.

The fix is to write the chain out to the LTO file and reconstruct it on
the way back in.

Committed to the LTO branch.

-Nathan

gcc/
	* tree-flow.h (init_empty_tree_cfg_for_function): Declare.
	* tree-cfg.c (init_empty_tree_cfg_for_function): Define.
	(init_empty_tree_cfg): Call it.
	* lto_function-out.c (output_cfg): Write out the block chain.

gcc/lto/
	* lto-read.c (input_cfg): Call init_empty_tree_cfg_for_function.
	Grow the basic_block_info and label_to_block_map vectors if
	necessary.  Read in the block chain.

Index: gcc/lto-function-out.c
===================================================================
--- gcc/lto-function-out.c	(revision 130659)
+++ gcc/lto-function-out.c	(working copy)
@@ -1921,6 +1921,17 @@ output_cfg (struct output_block *ob, str
 
   LTO_DEBUG_TOKEN ("bbindex");
   output_sleb128 (ob, -1);
+
+  bb = ENTRY_BLOCK_PTR;
+  while (bb->next_bb)
+    {
+      LTO_DEBUG_TOKEN ("bbchain");
+      output_sleb128 (ob, bb->next_bb->index);
+      bb = bb->next_bb;
+    }
+  LTO_DEBUG_TOKEN ("bbchain");
+  output_sleb128 (ob, -1);
+
   ob->main_stream = tmp_stream;
 }
 
Index: gcc/tree-flow.h
===================================================================
--- gcc/tree-flow.h	(revision 130658)
+++ gcc/tree-flow.h	(working copy)
@@ -780,6 +780,7 @@ extern tree gimplify_build2 (block_stmt_
 extern tree gimplify_build3 (block_stmt_iterator *, enum tree_code,
 			     tree, tree, tree, tree);
 extern void init_empty_tree_cfg (void);
+extern void init_empty_tree_cfg_for_function (struct function *);
 extern void fold_cond_expr_cond (void);
 extern void make_abnormal_goto_edges (basic_block, bool);
 extern void replace_uses_by (tree, tree);
Index: gcc/tree-cfg.c
===================================================================
--- gcc/tree-cfg.c	(revision 130658)
+++ gcc/tree-cfg.c	(working copy)
@@ -113,26 +113,41 @@ static edge find_taken_edge_switch_expr 
 static tree find_case_label_for_value (tree, tree);
 
 void
-init_empty_tree_cfg (void)
+init_empty_tree_cfg_for_function (struct function *fn)
 {
   /* Initialize the basic block array.  */
-  init_flow (cfun);
-  profile_status = PROFILE_ABSENT;
-  n_basic_blocks = NUM_FIXED_BLOCKS;
-  last_basic_block = NUM_FIXED_BLOCKS;
-  basic_block_info = VEC_alloc (basic_block, gc, initial_cfg_capacity);
-  VEC_safe_grow_cleared (basic_block, gc, basic_block_info,
+  init_flow (fn);
+  profile_status_for_function (fn) = PROFILE_ABSENT;
+  n_basic_blocks_for_function (fn) = NUM_FIXED_BLOCKS;
+  last_basic_block_for_function (fn) = NUM_FIXED_BLOCKS;
+  basic_block_info_for_function (fn)
+    = VEC_alloc (basic_block, gc, initial_cfg_capacity);
+  VEC_safe_grow_cleared (basic_block, gc,
+			 basic_block_info_for_function (fn),
 			 initial_cfg_capacity);
 
   /* Build a mapping of labels to their associated blocks.  */
-  label_to_block_map = VEC_alloc (basic_block, gc, initial_cfg_capacity);
-  VEC_safe_grow_cleared (basic_block, gc, label_to_block_map,
+  label_to_block_map_for_function (fn)
+    = VEC_alloc (basic_block, gc, initial_cfg_capacity);
+  VEC_safe_grow_cleared (basic_block, gc,
+			 label_to_block_map_for_function (fn),
 			 initial_cfg_capacity);
 
-  SET_BASIC_BLOCK (ENTRY_BLOCK, ENTRY_BLOCK_PTR);
-  SET_BASIC_BLOCK (EXIT_BLOCK, EXIT_BLOCK_PTR);
-  ENTRY_BLOCK_PTR->next_bb = EXIT_BLOCK_PTR;
-  EXIT_BLOCK_PTR->prev_bb = ENTRY_BLOCK_PTR;
+  SET_BASIC_BLOCK_FOR_FUNCTION (fn, ENTRY_BLOCK, 
+				ENTRY_BLOCK_PTR_FOR_FUNCTION (fn));
+  SET_BASIC_BLOCK_FOR_FUNCTION (fn, EXIT_BLOCK, 
+		   EXIT_BLOCK_PTR_FOR_FUNCTION (fn));
+
+  ENTRY_BLOCK_PTR_FOR_FUNCTION (fn)->next_bb
+    = EXIT_BLOCK_PTR_FOR_FUNCTION (fn);
+  EXIT_BLOCK_PTR_FOR_FUNCTION (fn)->prev_bb
+    = ENTRY_BLOCK_PTR_FOR_FUNCTION (fn);
+}
+
+void
+init_empty_tree_cfg (void)
+{
+  init_empty_tree_cfg_for_function (cfun);
 }
 
 /*---------------------------------------------------------------------------
Index: gcc/lto/lto-read.c
===================================================================
--- gcc/lto/lto-read.c	(revision 130662)
+++ gcc/lto/lto-read.c	(working copy)
@@ -1434,36 +1434,21 @@ input_cfg (struct input_block *ib, struc
   unsigned int i;
   int index;
 
-  init_flow (fn);
+  init_empty_tree_cfg_for_function (fn);
   init_ssa_operands ();
 
   LTO_DEBUG_TOKEN ("lastbb");
   bb_count = input_uleb128 (ib);
 
-  profile_status_for_function (fn) = PROFILE_ABSENT;
-  n_basic_blocks_for_function (fn) = NUM_FIXED_BLOCKS;
   last_basic_block_for_function (fn) = bb_count;
-  basic_block_info_for_function (fn)
-    = VEC_alloc (basic_block, gc, bb_count);
-  VEC_safe_grow (basic_block, gc,
-                 basic_block_info_for_function (fn), bb_count);
-  memset (VEC_address (basic_block, 
-		       basic_block_info_for_function (fn)), 
-	  0, sizeof (basic_block) * bb_count);
-
-  /* Build a mapping of labels to their associated blocks.  */
-  label_to_block_map_for_function (fn)
-    = VEC_alloc (basic_block, gc, bb_count);
-  VEC_safe_grow (basic_block, gc, 
-		 label_to_block_map_for_function (fn), bb_count);
-  memset (VEC_address (basic_block, 
-		       label_to_block_map_for_function (fn)),
-	  0, sizeof (basic_block) * bb_count);
-
-  SET_BASIC_BLOCK_FOR_FUNCTION (fn, ENTRY_BLOCK, 
-				ENTRY_BLOCK_PTR_FOR_FUNCTION (fn));
-  SET_BASIC_BLOCK_FOR_FUNCTION (fn, EXIT_BLOCK, 
-		   EXIT_BLOCK_PTR_FOR_FUNCTION (fn));
+  if (bb_count > VEC_length (basic_block,
+			     basic_block_info_for_function (fn)))
+    VEC_safe_grow_cleared (basic_block, gc,
+			   basic_block_info_for_function (fn), bb_count);
+  if (bb_count > VEC_length (basic_block,
+			     label_to_block_map_for_function (fn)))
+    VEC_safe_grow_cleared (basic_block, gc, 
+			   label_to_block_map_for_function (fn), bb_count);
 
   LTO_DEBUG_TOKEN ("bbindex");
   index = input_sleb128 (ib);
@@ -1501,19 +1486,17 @@ input_cfg (struct input_block *ib, struc
     }
 
   p_bb = ENTRY_BLOCK_PTR_FOR_FUNCTION(fn);
-  for (i = NUM_FIXED_BLOCKS; i < bb_count; i++)
+  LTO_DEBUG_TOKEN ("bbchain");
+  index = input_sleb128 (ib);
+  while (index != -1)
     {
-      basic_block bb = BASIC_BLOCK_FOR_FUNCTION (fn, i);
-      if (bb)
-	{
-	  bb->prev_bb = p_bb;
-	  p_bb->next_bb = bb;
-	  p_bb = bb;
-	}
+      basic_block bb = BASIC_BLOCK_FOR_FUNCTION (fn, index);
+      bb->prev_bb = p_bb;
+      p_bb->next_bb = bb;
+      p_bb = bb;
+      LTO_DEBUG_TOKEN ("bbchain");
+      index = input_sleb128 (ib);
     }
-
-  p_bb->next_bb = EXIT_BLOCK_PTR_FOR_FUNCTION(fn);
-  EXIT_BLOCK_PTR_FOR_FUNCTION(fn)->prev_bb = p_bb;
 }
 


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