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]

Re: [PATCH][2/5] Add gimple_find_sub_bbs


On 19-02-15 13:41, Richard Biener wrote:
On Thu, 19 Feb 2015, Tom de Vries wrote:

On 19-02-15 11:29, Tom de Vries wrote:
Hi,

I'm posting this patch series for stage1:
- 0001-Disable-lang_hooks.gimplify_expr-in-free_lang_data.patch
- 0002-Add-gimple_find_sub_bbs.patch
- 0003-Factor-optimize_va_list_gpr_fpr_size-out-of-pass_std.patch
- 0004-Handle-internal_fn-in-operand_equal_p.patch
- 0005-Postpone-expanding-va_arg-until-pass_stdarg.patch

The patch series - based on Michael's initial patch - postpones expanding
va_arg
until pass_stdarg, which makes pass_stdarg more robust.

Bootstrapped and reg-tested on x86_64 using all languages, with unix/ and
unix/-m32 testing.

I'll post the patches in reply to this email.

This patch adds gimple_find_sub_bbs. The function adds a gimple sequence at a
point in a basic block, and takes care to split up the sequence itself into
new basic blocks where necessary.

OK for stage1?

I hope we can get rid of this again (which needs re-writing of all
targets va-arg gimplification hooks... - we are in need of some
generic diamond/triangle CFG pattern builders anyway).

Ok with a comment on the function that this is transitional and
should not be used in new code.


Updated with comment.

Thanks,
- Tom

2015-02-17  Tom de Vries  <tom@codesourcery.com>
	    Michael Matz  <matz@suse.de>

	* tree-cfg.c (make_blocks_1): Factor out of ...
	(make_blocks): ... here.
	(make_edges_bb): Factor out of ...
	(make_edges): ... here.
	(gimple_find_sub_bbs): New function.
	* tree-cfg.h (gimple_find_sub_bbs): Declare.
---
 gcc/tree-cfg.c | 262 +++++++++++++++++++++++++++++++++++----------------------
 gcc/tree-cfg.h |   1 +
 2 files changed, 163 insertions(+), 100 deletions(-)

diff --git a/gcc/tree-cfg.c b/gcc/tree-cfg.c
index 006bc08..3aaa0b9 100644
--- a/gcc/tree-cfg.c
+++ b/gcc/tree-cfg.c
@@ -513,16 +513,15 @@ gimple_call_initialize_ctrl_altering (gimple stmt)
 }
 
 
-/* Build a flowgraph for the sequence of stmts SEQ.  */
+/* Insert SEQ after BB and build a flowgraph.  */
 
-static void
-make_blocks (gimple_seq seq)
+static basic_block
+make_blocks_1 (gimple_seq seq, basic_block bb)
 {
   gimple_stmt_iterator i = gsi_start (seq);
   gimple stmt = NULL;
   bool start_new_block = true;
   bool first_stmt_of_seq = true;
-  basic_block bb = ENTRY_BLOCK_PTR_FOR_FN (cfun);
 
   while (!gsi_end_p (i))
     {
@@ -579,8 +578,16 @@ make_blocks (gimple_seq seq)
       gsi_next (&i);
       first_stmt_of_seq = false;
     }
+  return bb;
 }
 
+/* Build a flowgraph for the sequence of stmts SEQ.  */
+
+static void
+make_blocks (gimple_seq seq)
+{
+  make_blocks_1 (seq, ENTRY_BLOCK_PTR_FOR_FN (cfun));
+}
 
 /* Create and return a new empty basic block after bb AFTER.  */
 
@@ -807,6 +814,112 @@ handle_abnormal_edges (basic_block *dispatcher_bbs,
   make_edge (*dispatcher, for_bb, EDGE_ABNORMAL);
 }
 
+/* Creates outgoing edges for BB.  Returns 1 when it ends with an
+   computed goto, returns 2 when it ends with a statement that
+   might return to this function via an nonlocal goto, otherwise
+   return 0.  Updates *PCUR_REGION with the OMP region this BB is in.  */
+
+static int
+make_edges_bb (basic_block bb, struct omp_region **pcur_region, int *pomp_index)
+{
+  gimple last = last_stmt (bb);
+  bool fallthru = false;
+  int ret = 0;
+
+  if (!last)
+    return ret;
+
+  switch (gimple_code (last))
+    {
+    case GIMPLE_GOTO:
+      if (make_goto_expr_edges (bb))
+	ret = 1;
+      fallthru = false;
+      break;
+    case GIMPLE_RETURN:
+      {
+	edge e = make_edge (bb, EXIT_BLOCK_PTR_FOR_FN (cfun), 0);
+	e->goto_locus = gimple_location (last);
+	fallthru = false;
+      }
+      break;
+    case GIMPLE_COND:
+      make_cond_expr_edges (bb);
+      fallthru = false;
+      break;
+    case GIMPLE_SWITCH:
+      make_gimple_switch_edges (as_a <gswitch *> (last), bb);
+      fallthru = false;
+      break;
+    case GIMPLE_RESX:
+      make_eh_edges (last);
+      fallthru = false;
+      break;
+    case GIMPLE_EH_DISPATCH:
+      fallthru = make_eh_dispatch_edges (as_a <geh_dispatch *> (last));
+      break;
+
+    case GIMPLE_CALL:
+      /* If this function receives a nonlocal goto, then we need to
+	 make edges from this call site to all the nonlocal goto
+	 handlers.  */
+      if (stmt_can_make_abnormal_goto (last))
+	ret = 2;
+
+      /* If this statement has reachable exception handlers, then
+	 create abnormal edges to them.  */
+      make_eh_edges (last);
+
+      /* BUILTIN_RETURN is really a return statement.  */
+      if (gimple_call_builtin_p (last, BUILT_IN_RETURN))
+	{
+	  make_edge (bb, EXIT_BLOCK_PTR_FOR_FN (cfun), 0);
+	  fallthru = false;
+	}
+      /* Some calls are known not to return.  */
+      else
+	fallthru = !(gimple_call_flags (last) & ECF_NORETURN);
+      break;
+
+    case GIMPLE_ASSIGN:
+      /* A GIMPLE_ASSIGN may throw internally and thus be considered
+	 control-altering.  */
+      if (is_ctrl_altering_stmt (last))
+	make_eh_edges (last);
+      fallthru = true;
+      break;
+
+    case GIMPLE_ASM:
+      make_gimple_asm_edges (bb);
+      fallthru = true;
+      break;
+
+    CASE_GIMPLE_OMP:
+      fallthru = make_gimple_omp_edges (bb, pcur_region, pomp_index);
+      break;
+
+    case GIMPLE_TRANSACTION:
+      {
+	tree abort_label
+	  = gimple_transaction_label (as_a <gtransaction *> (last));
+	if (abort_label)
+	  make_edge (bb, label_to_block (abort_label), EDGE_TM_ABORT);
+	fallthru = true;
+      }
+      break;
+
+    default:
+      gcc_assert (!stmt_ends_bb_p (last));
+      fallthru = true;
+      break;
+    }
+
+  if (fallthru)
+    make_edge (bb, bb->next_bb, EDGE_FALLTHRU);
+
+  return ret;
+}
+
 /* Join all the blocks in the flowgraph.  */
 
 static void
@@ -828,107 +941,19 @@ make_edges (void)
   /* Traverse the basic block array placing edges.  */
   FOR_EACH_BB_FN (bb, cfun)
     {
-      gimple last = last_stmt (bb);
-      bool fallthru;
+      int mer;
 
       if (bb_to_omp_idx)
 	bb_to_omp_idx[bb->index] = cur_omp_region_idx;
 
-      if (last)
-	{
-	  enum gimple_code code = gimple_code (last);
-	  switch (code)
-	    {
-	    case GIMPLE_GOTO:
-	      if (make_goto_expr_edges (bb))
-		ab_edge_goto.safe_push (bb);
-	      fallthru = false;
-	      break;
-	    case GIMPLE_RETURN:
-	      {
-		edge e = make_edge (bb, EXIT_BLOCK_PTR_FOR_FN (cfun), 0);
-		e->goto_locus = gimple_location (last);
-		fallthru = false;
-	      }
-	      break;
-	    case GIMPLE_COND:
-	      make_cond_expr_edges (bb);
-	      fallthru = false;
-	      break;
-	    case GIMPLE_SWITCH:
-	      make_gimple_switch_edges (as_a <gswitch *> (last), bb);
-	      fallthru = false;
-	      break;
-	    case GIMPLE_RESX:
-	      make_eh_edges (last);
-	      fallthru = false;
-	      break;
-	    case GIMPLE_EH_DISPATCH:
-	      fallthru = make_eh_dispatch_edges (as_a <geh_dispatch *> (last));
-	      break;
-
-	    case GIMPLE_CALL:
-	      /* If this function receives a nonlocal goto, then we need to
-		 make edges from this call site to all the nonlocal goto
-		 handlers.  */
-	      if (stmt_can_make_abnormal_goto (last))
-		ab_edge_call.safe_push (bb);
-
-	      /* If this statement has reachable exception handlers, then
-		 create abnormal edges to them.  */
-	      make_eh_edges (last);
-
-	      /* BUILTIN_RETURN is really a return statement.  */
-	      if (gimple_call_builtin_p (last, BUILT_IN_RETURN))
-		{
-		  make_edge (bb, EXIT_BLOCK_PTR_FOR_FN (cfun), 0);
-		  fallthru = false;
-		}
-	      /* Some calls are known not to return.  */
-	      else
-	        fallthru = !(gimple_call_flags (last) & ECF_NORETURN);
-	      break;
+      mer = make_edges_bb (bb, &cur_region, &cur_omp_region_idx);
+      if (mer == 1)
+	ab_edge_goto.safe_push (bb);
+      else if (mer == 2)
+	ab_edge_call.safe_push (bb);
 
-	    case GIMPLE_ASSIGN:
-	       /* A GIMPLE_ASSIGN may throw internally and thus be considered
-		  control-altering. */
-	      if (is_ctrl_altering_stmt (last))
-		make_eh_edges (last);
-	      fallthru = true;
-	      break;
-
-	    case GIMPLE_ASM:
-	      make_gimple_asm_edges (bb);
-	      fallthru = true;
-	      break;
-
-	    CASE_GIMPLE_OMP:
-	      fallthru = make_gimple_omp_edges (bb, &cur_region,
-						&cur_omp_region_idx);
-	      if (cur_region && bb_to_omp_idx == NULL)
-		bb_to_omp_idx = XCNEWVEC (int, n_basic_blocks_for_fn (cfun));
-	      break;
-
-	    case GIMPLE_TRANSACTION:
-	      {
-		tree abort_label
-		  = gimple_transaction_label (as_a <gtransaction *> (last));
-		if (abort_label)
-		  make_edge (bb, label_to_block (abort_label), EDGE_TM_ABORT);
-		fallthru = true;
-	      }
-	      break;
-
-	    default:
-	      gcc_assert (!stmt_ends_bb_p (last));
-	      fallthru = true;
-	    }
-	}
-      else
-	fallthru = true;
-
-      if (fallthru)
-	make_edge (bb, bb->next_bb, EDGE_FALLTHRU);
+      if (cur_region && bb_to_omp_idx == NULL)
+	bb_to_omp_idx = XCNEWVEC (int, n_basic_blocks_for_fn (cfun));
     }
 
   /* Computed gotos are hell to deal with, especially if there are
@@ -1008,6 +1033,43 @@ make_edges (void)
   fold_cond_expr_cond ();
 }
 
+/* Add SEQ after GSI.  Start new bb after GSI, and created further bbs as
+   needed.  Returns true if new bbs were created.
+   Note: This is transitional code, and should not be used for new code.  We
+   should be able to get rid of this by rewriting all target va-arg
+   gimplification hooks to use an interface gimple_build_cond_value as described
+   in https://gcc.gnu.org/ml/gcc-patches/2015-02/msg01194.html.  */
+
+bool
+gimple_find_sub_bbs (gimple_seq seq, gimple_stmt_iterator *gsi)
+{
+  gimple stmt = gsi_stmt (*gsi);
+  basic_block bb = gimple_bb (stmt);
+  basic_block lastbb, afterbb;
+  int old_num_bbs = n_basic_blocks_for_fn (cfun);
+  edge e;
+  lastbb = make_blocks_1 (seq, bb);
+  if (old_num_bbs == n_basic_blocks_for_fn (cfun))
+    return false;
+  e = split_block (bb, stmt);
+  /* Move e->dest to come after the new basic blocks.  */
+  afterbb = e->dest;
+  unlink_block (afterbb);
+  link_block (afterbb, lastbb);
+  redirect_edge_succ (e, bb->next_bb);
+  bb = bb->next_bb;
+  while (bb != afterbb)
+    {
+      struct omp_region *cur_region = NULL;
+      int cur_omp_region_idx = 0;
+      int mer = make_edges_bb (bb, &cur_region, &cur_omp_region_idx);
+      gcc_assert (!mer && !cur_region);
+      add_bb_to_loop (bb, afterbb->loop_father);
+      bb = bb->next_bb;
+    }
+  return true;
+}
+
 /* Find the next available discriminator value for LOCUS.  The
    discriminator distinguishes among several basic blocks that
    share a common locus, allowing for more accurate sample-based
diff --git a/gcc/tree-cfg.h b/gcc/tree-cfg.h
index cd28a80..2fc1e88 100644
--- a/gcc/tree-cfg.h
+++ b/gcc/tree-cfg.h
@@ -103,5 +103,6 @@ extern void extract_true_false_edges_from_block (basic_block, edge *, edge *);
 extern unsigned int execute_fixup_cfg (void);
 extern unsigned int split_critical_edges (void);
 extern basic_block insert_cond_bb (basic_block, gimple, gimple);
+extern bool gimple_find_sub_bbs (gimple_seq, gimple_stmt_iterator *);
 
 #endif /* _TREE_CFG_H  */
-- 
1.9.1


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