diff options
author | Peter Bergner <bergner@vnet.ibm.com> | 2017-05-10 11:44:45 -0500 |
---|---|---|
committer | Peter Bergner <bergner@gcc.gnu.org> | 2017-05-10 11:44:45 -0500 |
commit | ca4d28516878755a01ab8c2ba48d083100aba3fb (patch) | |
tree | 70d19af5ced974c859545f07f4ad66c75b41b3be /gcc/tree-cfg.c | |
parent | 415dcf965368a67599b93579848181ecec24f860 (diff) | |
download | gcc-ca4d28516878755a01ab8c2ba48d083100aba3fb.zip gcc-ca4d28516878755a01ab8c2ba48d083100aba3fb.tar.gz gcc-ca4d28516878755a01ab8c2ba48d083100aba3fb.tar.bz2 |
tree-cfg.c (gimple_seq_unreachable_p): New function.
gcc/
* tree-cfg.c (gimple_seq_unreachable_p): New function.
(assert_unreachable_fallthru_edge_p): Use it.
(group_case_labels_stmt): Likewise.
* tree-cfg.h: Prototype it.
* stmt.c: Include cfghooks.h and tree-cfg.h.
(emit_case_dispatch_table) <gap_label>: New local variable.
Use it to fill dispatch table gaps.
Test for default_label before updating probabilities.
(expand_case) <default_label>: Remove unneeded initialization.
Test for unreachable default case statement and remove its edge.
Set default_label accordingly.
* tree-ssa-ccp.c (optimize_unreachable): Update comment.
gcc/testsuite/
* gcc.target/powerpc/pr51513.c: New test.
* gcc.dg/predict-13.c: Replace __builtin_unreachable() with
__builtin_abort().
* gcc.dg/predict-14.c: Likewise.
From-SVN: r247844
Diffstat (limited to 'gcc/tree-cfg.c')
-rw-r--r-- | gcc/tree-cfg.c | 50 |
1 files changed, 31 insertions, 19 deletions
diff --git a/gcc/tree-cfg.c b/gcc/tree-cfg.c index a540416..77cb3d6 100644 --- a/gcc/tree-cfg.c +++ b/gcc/tree-cfg.c @@ -452,6 +452,31 @@ computed_goto_p (gimple *t) && TREE_CODE (gimple_goto_dest (t)) != LABEL_DECL); } +/* Returns true if the sequence of statements STMTS only contains + a call to __builtin_unreachable (). */ + +bool +gimple_seq_unreachable_p (gimple_seq stmts) +{ + if (stmts == NULL) + return false; + + gimple_stmt_iterator gsi = gsi_last (stmts); + + if (!gimple_call_builtin_p (gsi_stmt (gsi), BUILT_IN_UNREACHABLE)) + return false; + + for (gsi_prev (&gsi); !gsi_end_p (gsi); gsi_prev (&gsi)) + { + gimple *stmt = gsi_stmt (gsi); + if (gimple_code (stmt) != GIMPLE_LABEL + && !is_gimple_debug (stmt) + && !gimple_clobber_p (stmt)) + return false; + } + return true; +} + /* Returns true for edge E where e->src ends with a GIMPLE_COND and the other edge points to a bb with just __builtin_unreachable (). I.e. return true for C->M edge in: @@ -476,22 +501,7 @@ assert_unreachable_fallthru_edge_p (edge e) if (other_bb == e->dest) other_bb = EDGE_SUCC (pred_bb, 1)->dest; if (EDGE_COUNT (other_bb->succs) == 0) - { - gimple_stmt_iterator gsi = gsi_after_labels (other_bb); - gimple *stmt; - - if (gsi_end_p (gsi)) - return false; - stmt = gsi_stmt (gsi); - while (is_gimple_debug (stmt) || gimple_clobber_p (stmt)) - { - gsi_next (&gsi); - if (gsi_end_p (gsi)) - return false; - stmt = gsi_stmt (gsi); - } - return gimple_call_builtin_p (stmt, BUILT_IN_UNREACHABLE); - } + return gimple_seq_unreachable_p (bb_seq (other_bb)); } return false; } @@ -1668,9 +1678,11 @@ group_case_labels_stmt (gswitch *stmt) gcc_assert (base_case); base_bb = label_to_block (CASE_LABEL (base_case)); - /* Discard cases that have the same destination as the - default case. */ - if (base_bb == default_bb) + /* Discard cases that have the same destination as the default case + or if their destination block is unreachable. */ + if (base_bb == default_bb + || (EDGE_COUNT (base_bb->succs) == 0 + && gimple_seq_unreachable_p (bb_seq (base_bb)))) { gimple_switch_set_label (stmt, i, NULL_TREE); i++; |