diff options
Diffstat (limited to 'gcc/tree-eh.c')
-rw-r--r-- | gcc/tree-eh.c | 42 |
1 files changed, 35 insertions, 7 deletions
diff --git a/gcc/tree-eh.c b/gcc/tree-eh.c index 5bb07e49d28..7a028735d4e 100644 --- a/gcc/tree-eh.c +++ b/gcc/tree-eh.c @@ -2523,6 +2523,10 @@ operation_could_trap_p (enum tree_code op, bool fp_operation, bool honor_trapv, bool honor_snans = fp_operation && flag_signaling_nans != 0; bool handled; + /* This function cannot tell whether or not COND_EXPR and VEC_COND_EXPR could + trap, because that depends on the respective condition op. */ + gcc_assert (op != COND_EXPR && op != VEC_COND_EXPR); + if (TREE_CODE_CLASS (op) != tcc_comparison && TREE_CODE_CLASS (op) != tcc_unary && TREE_CODE_CLASS (op) != tcc_binary) @@ -2610,6 +2614,10 @@ tree_could_trap_p (tree expr) if (!expr) return false; + /* For COND_EXPR and VEC_COND_EXPR only the condition may trap. */ + if (TREE_CODE (expr) == COND_EXPR || TREE_CODE (expr) == VEC_COND_EXPR) + expr = TREE_OPERAND (expr, 0); + code = TREE_CODE (expr); t = TREE_TYPE (expr); @@ -4040,15 +4048,14 @@ maybe_remove_unreachable_handlers (void) if (cfun->eh == NULL) return; - + FOR_EACH_VEC_SAFE_ELT (cfun->eh->lp_array, i, lp) - if (lp && lp->post_landing_pad) + if (lp + && (lp->post_landing_pad == NULL_TREE + || label_to_block (cfun, lp->post_landing_pad) == NULL)) { - if (label_to_block (cfun, lp->post_landing_pad) == NULL) - { - remove_unreachable_handlers (); - return; - } + remove_unreachable_handlers (); + return; } } @@ -4211,6 +4218,27 @@ unsplit_all_eh (void) return changed; } +/* Wrapper around unsplit_all_eh that makes it usable everywhere. */ + +void +unsplit_eh_edges (void) +{ + bool changed; + + /* unsplit_all_eh can die looking up unreachable landing pads. */ + maybe_remove_unreachable_handlers (); + + changed = unsplit_all_eh (); + + /* If EH edges have been unsplit, delete unreachable forwarder blocks. */ + if (changed) + { + free_dominance_info (CDI_DOMINATORS); + free_dominance_info (CDI_POST_DOMINATORS); + delete_unreachable_blocks (); + } +} + /* A subroutine of cleanup_empty_eh. Redirect all EH edges incoming to OLD_BB to NEW_BB; return true on success, false on failure. |