X-Git-Url: http://git.sourceforge.jp/view?a=blobdiff_plain;f=gcc%2Fcfgbuild.c;h=79b6183bfba639f1f57e88ef7d468b6b83ce8c00;hb=6a32eb2b91dc9f6f9d57cab53e65064c9aa87ee1;hp=012bd0b6be7ecb5bf625818096dc0e77b6f8d5af;hpb=9845d1202fec65574ca05d780859eb8c25489566;p=pf3gnuchains%2Fgcc-fork.git diff --git a/gcc/cfgbuild.c b/gcc/cfgbuild.c index 012bd0b6be7..79b6183bfba 100644 --- a/gcc/cfgbuild.c +++ b/gcc/cfgbuild.c @@ -33,8 +33,10 @@ along with GCC; see the file COPYING3. If not see #include "output.h" #include "function.h" #include "except.h" +#include "expr.h" #include "toplev.h" #include "timevar.h" +#include "sbitmap.h" static void make_edges (basic_block, basic_block, int); static void make_label_edge (sbitmap, basic_block, rtx, int); @@ -80,8 +82,6 @@ inside_basic_block_p (const_rtx insn) bool control_flow_insn_p (const_rtx insn) { - rtx note; - switch (GET_CODE (insn)) { case NOTE: @@ -101,21 +101,20 @@ control_flow_insn_p (const_rtx insn) || find_reg_note (insn, REG_NORETURN, 0)) && GET_CODE (PATTERN (insn)) != COND_EXEC) return true; + /* Call insn may return to the nonlocal goto handler. */ - return ((nonlocal_goto_handler_labels - && (0 == (note = find_reg_note (insn, REG_EH_REGION, - NULL_RTX)) - || INTVAL (XEXP (note, 0)) >= 0)) - /* Or may trap. */ - || can_throw_internal (insn)); + if (can_nonlocal_goto (insn)) + return true; + break; case INSN: /* Treat trap instructions like noreturn calls (same provision). */ if (GET_CODE (PATTERN (insn)) == TRAP_IF && XEXP (PATTERN (insn), 0) == const1_rtx) return true; - - return (flag_non_call_exceptions && can_throw_internal (insn)); + if (!flag_non_call_exceptions) + return false; + break; case BARRIER: /* It is nonsense to reach barrier when looking for the @@ -126,6 +125,8 @@ control_flow_insn_p (const_rtx insn) default: gcc_unreachable (); } + + return can_throw_internal (insn); } @@ -155,16 +156,23 @@ make_label_edge (sbitmap edge_cache, basic_block src, rtx label, int flags) void rtl_make_eh_edge (sbitmap edge_cache, basic_block src, rtx insn) { - int is_call = CALL_P (insn) ? EDGE_ABNORMAL_CALL : 0; - rtx handlers, i; + eh_landing_pad lp = get_eh_landing_pad_from_rtx (insn); - handlers = reachable_handlers (insn); + if (lp) + { + rtx label = lp->landing_pad; - for (i = handlers; i; i = XEXP (i, 1)) - make_label_edge (edge_cache, src, XEXP (i, 0), - EDGE_ABNORMAL | EDGE_EH | is_call); + /* During initial rtl generation, use the post_landing_pad. */ + if (label == NULL) + { + gcc_assert (lp->post_landing_pad); + label = label_rtx (lp->post_landing_pad); + } - free_INSN_LIST_list (&handlers); + make_label_edge (edge_cache, src, label, + EDGE_ABNORMAL | EDGE_EH + | (CALL_P (insn) ? EDGE_ABNORMAL_CALL : 0)); + } } /* States of basic block as seen by find_many_sub_basic_blocks. */ @@ -253,13 +261,9 @@ make_edges (basic_block min, basic_block max, int update_p) { rtx tmp; - /* Recognize exception handling placeholders. */ - if (GET_CODE (PATTERN (insn)) == RESX) - rtl_make_eh_edge (edge_cache, bb, insn); - /* Recognize a non-local goto as a branch outside the current function. */ - else if (find_reg_note (insn, REG_NON_LOCAL_GOTO, NULL_RTX)) + if (find_reg_note (insn, REG_NON_LOCAL_GOTO, NULL_RTX)) ; /* Recognize a tablejump and do the right thing. */ @@ -300,6 +304,15 @@ make_edges (basic_block min, basic_block max, int update_p) else if (returnjump_p (insn)) cached_make_edge (edge_cache, bb, EXIT_BLOCK_PTR, 0); + /* Recognize asm goto and do the right thing. */ + else if ((tmp = extract_asm_operands (PATTERN (insn))) != NULL) + { + int i, n = ASM_OPERANDS_LABEL_LENGTH (tmp); + for (i = 0; i < n; ++i) + make_label_edge (edge_cache, bb, + XEXP (ASM_OPERANDS_LABEL (tmp, i), 0), 0); + } + /* Otherwise, we have a plain conditional or unconditional jump. */ else { @@ -333,12 +346,7 @@ make_edges (basic_block min, basic_block max, int update_p) gotos do not have their addresses taken, then only calls to those functions or to other nested functions that use them could possibly do nonlocal gotos. */ - - /* We do know that a REG_EH_REGION note with a value less - than 0 is guaranteed not to perform a non-local goto. */ - rtx note = find_reg_note (insn, REG_EH_REGION, NULL_RTX); - - if (!note || INTVAL (XEXP (note, 0)) >= 0) + if (can_nonlocal_goto (insn)) for (x = nonlocal_goto_handler_labels; x; x = XEXP (x, 1)) make_label_edge (edge_cache, bb, XEXP (x, 0), EDGE_ABNORMAL | EDGE_ABNORMAL_CALL); @@ -446,8 +454,10 @@ find_bb_boundaries (basic_block bb) { enum rtx_code code = GET_CODE (insn); - /* On code label, split current basic block. */ - if (code == CODE_LABEL) + /* In case we've previously seen an insn that effects a control + flow transfer, split the block. */ + if ((flow_transfer_insn || code == CODE_LABEL) + && inside_basic_block_p (insn)) { fallthru = split_block (bb, PREV_INSN (insn)); if (flow_transfer_insn) @@ -465,27 +475,16 @@ find_bb_boundaries (basic_block bb) bb = fallthru->dest; remove_edge (fallthru); flow_transfer_insn = NULL_RTX; - if (LABEL_ALT_ENTRY_P (insn)) + if (code == CODE_LABEL && LABEL_ALT_ENTRY_P (insn)) make_edge (ENTRY_BLOCK_PTR, bb, 0); } - - /* In case we've previously seen an insn that effects a control - flow transfer, split the block. */ - if (flow_transfer_insn && inside_basic_block_p (insn)) + else if (code == BARRIER) { - fallthru = split_block (bb, PREV_INSN (insn)); - BB_END (bb) = flow_transfer_insn; - - /* Clean up the bb field for the insns between the blocks. */ - for (x = NEXT_INSN (flow_transfer_insn); - x != BB_HEAD (fallthru->dest); - x = NEXT_INSN (x)) - if (!BARRIER_P (x)) - set_block_for_insn (x, NULL); - - bb = fallthru->dest; - remove_edge (fallthru); - flow_transfer_insn = NULL_RTX; + /* __builtin_unreachable () may cause a barrier to be emitted in + the middle of a BB. We need to split it in the same manner as + if the barrier were preceded by a control_flow_insn_p insn. */ + if (!flow_transfer_insn) + flow_transfer_insn = prev_nonnote_insn_bb (insn); } if (control_flow_insn_p (insn))