[PATCH] Fix PR89710

Richard Biener rguenther@suse.de
Thu Mar 14 10:32:00 GMT 2019


I am testing the following.  There's IMHO also a missed optimization
(for CFG-cleanup?) that when a block does not end up in a call
outgoing abnormal edges can be purged?  In this case it is
IPA inlining leaving us with this - the inliner calls
gimple_purge_dead_abnormal_call_edges on the return block
but both cfun->has_nonlocal_label and cfun->calls_setjmp are
false so the function does nothing.  This is probably
a premature check there?

Anyhow, the fix below is safer at this point (also for backporting),
but it's the 2nd spot of this kind I fix so I wonder if we should
fix the above for GCC 9?  The real issue might be that we
are removing the "last" returns_twice call but retain
abnormal edges not originating from it (and we'll never cleanup
the rest because of those early outs).  DCE is the one that
recomputes calls_setjmp but does not remove abnormal edges.
Other passes might also elide such calls but they leave
calls_setjmp as-is.  I'm a bit nervous with an idea that
DCE can purge all abnormal edges if !cfun->calls_setjmp
&& !cfun->has_nonlocal_label.  Anyway, looks a bit like a
can of worms and it's better to not rely on abnormal edges
not being present when the block is empty.

Richard.

2019-03-14  Richard Biener  <rguenther@suse.de>

	PR tree-optimization/89710
	* tree-ssa-loop-ch.c (should_duplicate_loop_header_p): Use
	safe_dyn_cast.

	* gcc.dg/torture/pr89710.c: New testcase.

Index: gcc/tree-ssa-loop-ch.c
===================================================================
--- gcc/tree-ssa-loop-ch.c	(revision 269678)
+++ gcc/tree-ssa-loop-ch.c	(working copy)
@@ -100,7 +100,7 @@ should_duplicate_loop_header_p (basic_bl
       return false;
     }
 
-  gcond *last = dyn_cast <gcond *> (last_stmt (header));
+  gcond *last = safe_dyn_cast <gcond *> (last_stmt (header));
   if (!last)
     {
       if (dump_file && (dump_flags & TDF_DETAILS))
Index: gcc/testsuite/gcc.dg/torture/pr89710.c
===================================================================
--- gcc/testsuite/gcc.dg/torture/pr89710.c	(nonexistent)
+++ gcc/testsuite/gcc.dg/torture/pr89710.c	(working copy)
@@ -0,0 +1,30 @@
+/* { dg-do compile } */
+
+void
+gm (int *);
+
+__attribute__ ((returns_twice)) void
+jg (void)
+{
+}
+
+void
+eb (void)
+{
+  int r6 = 0;
+
+  if (r6 != 0)
+    gm (&r6);
+}
+
+void
+gm (int *r6)
+{
+  jg ();
+
+  for (;;)
+    {
+      eb ();
+      *r6 = 0;
+    }
+}


diff --git a/gcc/tree-cfg.c b/gcc/tree-cfg.c
index 0dc94ea41d4..69837328279 100644
--- a/gcc/tree-cfg.c
+++ b/gcc/tree-cfg.c
@@ -2585,13 +2585,8 @@ debug_cfg_stats (void)
 static bool
 call_can_make_abnormal_goto (gimple *t)
 {
-  /* If the function has no non-local labels, then a call cannot make an
+  /* If the call has no side effects, then it cannot make an
      abnormal transfer of control.  */
-  if (!cfun->has_nonlocal_label
-      && !cfun->calls_setjmp)
-   return false;
-
-  /* Likewise if the call has no side effects.  */
   if (!gimple_has_side_effects (t))
     return false;
 
@@ -8670,10 +8665,6 @@ gimple_purge_dead_abnormal_call_edges (basic_block bb)
   edge_iterator ei;
   gimple *stmt = last_stmt (bb);
 
-  if (!cfun->has_nonlocal_label
-      && !cfun->calls_setjmp)
-    return false;
-
   if (stmt && stmt_can_make_abnormal_goto (stmt))
     return false;
 



More information about the Gcc-patches mailing list