Patchwork Fix PR57147, fix edge removal code

login
register
mail settings
Submitter Richard Guenther
Date May 3, 2013, 1:07 p.m.
Message ID <alpine.LNX.2.00.1305031506510.24881@zhemvz.fhfr.qr>
Download mbox | patch
Permalink /patch/241308/
State New
Headers show

Comments

Richard Guenther - May 3, 2013, 1:07 p.m.
On Fri, 3 May 2013, Richard Biener wrote:

> 
> The following fixes a bug in gimple_purge_dead_abnormal_call_edges
> which happily removes a EDGE_FALLTHRU|EDGE_ABNORMAL edge.
> The CFG builder via make_edge generally seems to merge edge flags
> and edges for edges between the same basic-blocks, so any
> abnormal call edges we insert may shadow the edge from the
> normal return.
> 
> The simplest fix is to just clear the EDGE_ABNORMAL flag in this
> case.
> 
> A similar bug is in remove_fallthru_edge.  Finally we get
> more decent test coverage for the non-local goto code.
> 
> Bootstrap and regtest pending on x86_64-unknown-linux-gnu.
> 
> Comments?

The following at least gets me past bootstrapping.  The rest
will have to wait till monday.

Richard.

2013-05-03  Richard Biener  <rguenther@suse.de>

	PR middle-end/57147
	* tree-cfg.c (gimple_purge_dead_abnormal_call_edges): If
	the edge is also fallthru, preserve it and just clear the
	abnormal flag.
	* tree-cfgcleanup.c (remove_fallthru_edge): If the edge is
	also complex, preserve that and just clear the fallthru flag.
	* tree-inline.c (update_ssa_across_abnormal_edges): Also
	update virtual operands.

	* gcc.dg/torture/pr57147-1.c: New testcase.
	* gcc.dg/torture/pr57147-2.c: Likewise.
	* gcc.dg/torture/pr57147-3.c: Likewise.

Index: gcc/tree-cfg.c
===================================================================
*** gcc/tree-cfg.c	(revision 198572)
--- gcc/tree-cfg.c	(working copy)
*************** gimple_purge_dead_abnormal_call_edges (b
*** 7628,7634 ****
      {
        if (e->flags & EDGE_ABNORMAL)
  	{
! 	  remove_edge_and_dominated_blocks (e);
  	  changed = true;
  	}
        else
--- 7648,7657 ----
      {
        if (e->flags & EDGE_ABNORMAL)
  	{
! 	  if (e->flags & EDGE_FALLTHRU)
! 	    e->flags &= ~EDGE_ABNORMAL;
! 	  else
! 	    remove_edge_and_dominated_blocks (e);
  	  changed = true;
  	}
        else
Index: gcc/tree-cfgcleanup.c
===================================================================
*** gcc/tree-cfgcleanup.c	(revision 198572)
--- gcc/tree-cfgcleanup.c	(working copy)
*************** remove_fallthru_edge (vec<edge, va_gc> *
*** 57,63 ****
    FOR_EACH_EDGE (e, ei, ev)
      if ((e->flags & EDGE_FALLTHRU) != 0)
        {
! 	remove_edge_and_dominated_blocks (e);
  	return true;
        }
    return false;
--- 57,66 ----
    FOR_EACH_EDGE (e, ei, ev)
      if ((e->flags & EDGE_FALLTHRU) != 0)
        {
! 	if (e->flags & EDGE_COMPLEX)
! 	  e->flags &= ~EDGE_FALLTHRU;
! 	else
! 	  remove_edge_and_dominated_blocks (e);
  	return true;
        }
    return false;
Index: gcc/tree-inline.c
===================================================================
*** gcc/tree-inline.c	(revision 198577)
--- gcc/tree-inline.c	(working copy)
*************** update_ssa_across_abnormal_edges (basic_
*** 1841,1854 ****
  	    gcc_assert ((e->flags & EDGE_EH)
  			|| SSA_NAME_OCCURS_IN_ABNORMAL_PHI (PHI_RESULT (phi)));
  
- 	    if (virtual_operand_p (PHI_RESULT (phi)))
- 	      {
- 		mark_virtual_operands_for_renaming (cfun);
- 		continue;
- 	      }
- 
  	    re = find_edge (ret_bb, e->dest);
! 	    gcc_assert (re);
  	    gcc_assert ((re->flags & (EDGE_EH | EDGE_ABNORMAL))
  			== (e->flags & (EDGE_EH | EDGE_ABNORMAL)));
  
--- 1845,1852 ----
  	    gcc_assert ((e->flags & EDGE_EH)
  			|| SSA_NAME_OCCURS_IN_ABNORMAL_PHI (PHI_RESULT (phi)));
  
  	    re = find_edge (ret_bb, e->dest);
! 	    gcc_checking_assert (re);
  	    gcc_assert ((re->flags & (EDGE_EH | EDGE_ABNORMAL))
  			== (e->flags & (EDGE_EH | EDGE_ABNORMAL)));
  
Index: gcc/testsuite/gcc.dg/torture/pr57147-3.c
===================================================================
*** gcc/testsuite/gcc.dg/torture/pr57147-3.c	(revision 0)
--- gcc/testsuite/gcc.dg/torture/pr57147-3.c	(working copy)
***************
*** 0 ****
--- 1,20 ----
+ /* { dg-do compile } */
+ 
+ typedef char * ptr_t;
+ struct __jmp_buf_tag   {
+ };
+ typedef struct __jmp_buf_tag sigjmp_buf[1];
+ sigjmp_buf GC_jmp_buf;
+ void GC_fault_handler(int sig)
+ {
+ }
+ void GC_setup_temporary_fault_handler()     {
+     GC_set_and_save_fault_handler(GC_fault_handler);
+ }
+ ptr_t GC_find_limit(ptr_t p)
+ {
+   GC_setup_temporary_fault_handler();
+   if (__sigsetjmp (GC_jmp_buf, 1) == 0)
+     for (;;)
+       ;
+ }

Patch

Index: gcc/testsuite/gcc.dg/torture/pr57147-1.c
===================================================================
--- gcc/testsuite/gcc.dg/torture/pr57147-1.c	(revision 0)
+++ gcc/testsuite/gcc.dg/torture/pr57147-1.c	(working copy)
@@ -0,0 +1,20 @@ 
+/* { dg-do compile } */
+/* { dg-options "-fdump-tree-optimized" } */
+
+struct __jmp_buf_tag {};
+typedef struct __jmp_buf_tag jmp_buf[1];
+extern int _setjmp (struct __jmp_buf_tag __env[1]);
+
+jmp_buf g_return_jmp_buf;
+
+void SetNaClSwitchExpectations (void)
+{
+}
+void TestSyscall(void)
+{
+  SetNaClSwitchExpectations();
+  _setjmp (g_return_jmp_buf);
+}
+
+/* { dg-final { scan-tree-dump-not "builtin_unreachable" "optimized" } } */
+/* { dg-final { cleanup-tree-dump "optimized" } } */
Index: gcc/testsuite/gcc.dg/torture/pr57147-2.c
===================================================================
--- gcc/testsuite/gcc.dg/torture/pr57147-2.c	(revision 0)
+++ gcc/testsuite/gcc.dg/torture/pr57147-2.c	(working copy)
@@ -0,0 +1,21 @@ 
+/* { dg-do compile } */
+/* { dg-options "-fdump-tree-optimized" } */
+
+struct __jmp_buf_tag {};
+typedef struct __jmp_buf_tag jmp_buf[1];
+extern int _setjmp (struct __jmp_buf_tag __env[1]);
+
+jmp_buf g_return_jmp_buf;
+
+void SetNaClSwitchExpectations (void)
+{
+  __builtin_longjmp (g_return_jmp_buf, 1);
+}
+void TestSyscall(void)
+{
+  SetNaClSwitchExpectations();
+  _setjmp (g_return_jmp_buf);
+}
+
+/* { dg-final { scan-tree-dump "setjmp" "optimized" } } */
+/* { dg-final { cleanup-tree-dump "optimized" } } */