[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