diff options
Diffstat (limited to 'gcc/tree-cfg.c')
-rw-r--r-- | gcc/tree-cfg.c | 44 |
1 files changed, 44 insertions, 0 deletions
diff --git a/gcc/tree-cfg.c b/gcc/tree-cfg.c index d705657..d646693 100644 --- a/gcc/tree-cfg.c +++ b/gcc/tree-cfg.c @@ -381,6 +381,50 @@ computed_goto_p (gimple t) && TREE_CODE (gimple_goto_dest (t)) != LABEL_DECL); } +/* 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: + <bb C>: + ... + if (something) + goto <bb N>; + else + goto <bb M>; + <bb N>: + __builtin_unreachable (); + <bb M>: */ + +bool +assert_unreachable_fallthru_edge_p (edge e) +{ + basic_block pred_bb = e->src; + gimple last = last_stmt (pred_bb); + if (last && gimple_code (last) == GIMPLE_COND) + { + basic_block other_bb = EDGE_SUCC (pred_bb, 0)->dest; + 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); + if (is_gimple_debug (stmt)) + { + gsi_next_nondebug (&gsi); + if (gsi_end_p (gsi)) + return false; + stmt = gsi_stmt (gsi); + } + return gimple_call_builtin_p (stmt, BUILT_IN_UNREACHABLE); + } + } + return false; +} + /* Search the CFG for any computed gotos. If found, factor them to a common computed goto site. Also record the location of that site so |