From patchwork Fri Nov 2 12:08:11 2012 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit Subject: Fix minor inaccuracy with EDGE_SIBCALL From: Eric Botcazou X-Patchwork-Id: 196550 Message-Id: <1696289.jqbXN5KyOj@polaris> To: gcc-patches@gcc.gnu.org Date: Fri, 02 Nov 2012 13:08:11 +0100 cfg-flags.def reads: /* Edge out of a basic block that ends with a CALL_INSN with abnormal exit, like an exception, or a sibcall. This flag is only used for the RTL CFG. */ DEF_EDGE_FLAG(ABNORMAL_CALL, 2) That's wrong, ABNORMAL_CALL isn't set for a sibcall, only ABNORMAL is. That's even asserted in purge_dead_edges: else if (CALL_P (insn) && SIBLING_CALL_P (insn)) { /* First, there should not be any EH or ABCALL edges resulting from non-local gotos and the like. If there were, we shouldn't have created the sibcall in the first place. Second, there should of course never have been a fallthru edge. */ gcc_assert (single_succ_p (bb)); gcc_assert (single_succ_edge (bb)->flags == (EDGE_SIBCALL | EDGE_ABNORMAL)); return 0; } This means that the EDGE_ABNORMAL check in rtl_verify_flow_info_1 is wrong as well. But it contains a thinko that masks the bug. :-) Tested on x86_64-suse-linux, applied on the mainline. 2012-11-02 Eric Botcazou * cfg-flags.def (ABNORMAL_CALL): Fix comment. (EH): Likewise. (SIBCALL): Likewise. * cfgrtl.c (rtl_verify_flow_info_1): Adjust error messages. Deal with EDGE_SIBCALL and fix the EDGE_ABNORMAL check. Index: cfg-flags.def =================================================================== --- cfg-flags.def (revision 193090) +++ cfg-flags.def (working copy) @@ -115,13 +115,14 @@ DEF_EDGE_FLAG(FALLTHRU, 0) DEF_EDGE_FLAG(ABNORMAL, 1) /* Edge out of a basic block that ends with a CALL_INSN with abnormal - exit, like an exception, or a sibcall. + exit, like an exception or a non-local goto. + ABNORMAL_CALL edges also have ABNORMAL set. This flag is only used for the RTL CFG. */ DEF_EDGE_FLAG(ABNORMAL_CALL, 2) /* Exception edge. Exception handling edges represent possible control - transfers from a trapping instruction to an exception handler. EH - edges also have EDGE_ABNORMAL set. */ + transfers from a trapping instruction to an exception handler. + EH edges also have ABNORMAL set for the RTL CFG. */ DEF_EDGE_FLAG(EH, 3) /* Never merge blocks via this edge. This is used for exception handling, @@ -158,6 +159,7 @@ DEF_EDGE_FLAG(EXECUTABLE, 10) DEF_EDGE_FLAG(CROSSING, 11) /* Edge from a sibcall CALL_INSN to exit. + SIBCALL edges also have ABNORMAL set. This flag is only used for the RTL CFG. */ DEF_EDGE_FLAG(SIBCALL, 12) Index: cfgrtl.c =================================================================== --- cfgrtl.c (revision 193090) +++ cfgrtl.c (working copy) @@ -2095,7 +2095,8 @@ rtl_verify_flow_info_1 (void) /* Now check the basic blocks (boundaries etc.) */ FOR_EACH_BB_REVERSE (bb) { - int n_fallthru = 0, n_eh = 0, n_call = 0, n_abnormal = 0, n_branch = 0; + int n_fallthru = 0, n_branch = 0, n_abnormal_call = 0, n_sibcall = 0; + int n_eh = 0, n_abnormal = 0; edge e, fallthru = NULL; rtx note; edge_iterator ei; @@ -2132,13 +2133,13 @@ rtl_verify_flow_info_1 (void) } if (e->flags & EDGE_FALLTHRU) { - error ("fallthru edge crosses section boundary (bb %i)", + error ("fallthru edge crosses section boundary in bb %i", e->src->index); err = 1; } if (e->flags & EDGE_EH) { - error ("EH edge crosses section boundary (bb %i)", + error ("EH edge crosses section boundary in bb %i", e->src->index); err = 1; } @@ -2158,22 +2159,26 @@ rtl_verify_flow_info_1 (void) n_branch++; if (e->flags & EDGE_ABNORMAL_CALL) - n_call++; + n_abnormal_call++; + + if (e->flags & EDGE_SIBCALL) + n_sibcall++; if (e->flags & EDGE_EH) n_eh++; - else if (e->flags & EDGE_ABNORMAL) + + if (e->flags & EDGE_ABNORMAL) n_abnormal++; } if (n_eh && !find_reg_note (BB_END (bb), REG_EH_REGION, NULL_RTX)) { - error ("missing REG_EH_REGION note in the end of bb %i", bb->index); + error ("missing REG_EH_REGION note at the end of bb %i", bb->index); err = 1; } if (n_eh > 1) { - error ("too many eh edges %i", bb->index); + error ("too many exception handling edges in bb %i", bb->index); err = 1; } if (n_branch @@ -2186,29 +2191,35 @@ rtl_verify_flow_info_1 (void) } if (n_fallthru && any_uncondjump_p (BB_END (bb))) { - error ("fallthru edge after unconditional jump %i", bb->index); + error ("fallthru edge after unconditional jump in bb %i", bb->index); err = 1; } if (n_branch != 1 && any_uncondjump_p (BB_END (bb))) { - error ("wrong number of branch edges after unconditional jump %i", - bb->index); + error ("wrong number of branch edges after unconditional jump" + " in bb %i", bb->index); err = 1; } if (n_branch != 1 && any_condjump_p (BB_END (bb)) && JUMP_LABEL (BB_END (bb)) != BB_HEAD (fallthru->dest)) { - error ("wrong amount of branch edges after conditional jump %i", - bb->index); + error ("wrong amount of branch edges after conditional jump" + " in bb %i", bb->index); + err = 1; + } + if (n_abnormal_call && !CALL_P (BB_END (bb))) + { + error ("abnormal call edges for non-call insn in bb %i", bb->index); err = 1; } - if (n_call && !CALL_P (BB_END (bb))) + if (n_sibcall && !CALL_P (BB_END (bb))) { - error ("call edges for non-call insn in bb %i", bb->index); + error ("sibcall edges for non-call insn in bb %i", bb->index); err = 1; } - if (n_abnormal - && (!CALL_P (BB_END (bb)) && n_call != n_abnormal) + if (n_abnormal > n_eh + && !(CALL_P (BB_END (bb)) + && n_abnormal == n_abnormal_call + n_sibcall) && (!JUMP_P (BB_END (bb)) || any_condjump_p (BB_END (bb)) || any_uncondjump_p (BB_END (bb))))