Patchwork Fix minor inaccuracy with EDGE_SIBCALL

login
register
mail settings
Submitter Eric Botcazou
Date Nov. 2, 2012, 12:08 p.m.
Message ID <1696289.jqbXN5KyOj@polaris>
Download mbox | patch
Permalink /patch/196550/
State New
Headers show

Comments

Eric Botcazou - Nov. 2, 2012, 12:08 p.m.
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  <ebotcazou@adacore.com>

	* 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.

Patch

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))))