summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorvries <vries@138bc75d-0d04-0410-961f-82ee72b054a4>2015-04-17 09:26:33 +0000
committervries <vries@138bc75d-0d04-0410-961f-82ee72b054a4>2015-04-17 09:26:33 +0000
commit5f8ad053a1928714fc3a3fda4bea13433839274d (patch)
treef97d8f0327b1105dc675e7dc80c7d23f006676da
parent5cb32292316d6092cf9abd74b46da2941bb7b8b8 (diff)
downloadgcc-5f8ad053a1928714fc3a3fda4bea13433839274d.tar.gz
Add gimple_find_sub_bbs
2015-04-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. git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@222170 138bc75d-0d04-0410-961f-82ee72b054a4
-rw-r--r--gcc/ChangeLog10
-rw-r--r--gcc/tree-cfg.c262
-rw-r--r--gcc/tree-cfg.h1
3 files changed, 173 insertions, 100 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index a533ad4c4eb..36429850c23 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -1,4 +1,14 @@
2015-04-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.
+
+2015-04-17 Tom de Vries <tom@codesourcery.com>
* tree.c (free_lang_data): Disable lang_hooks.gimplify_expr.
diff --git a/gcc/tree-cfg.c b/gcc/tree-cfg.c
index 64bdc92e681..1cfb67a4831 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 cd28a80c7f6..2fc1e886ff0 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 */