Hi!

In the following testcase, we have initially during RTL expansion a call
which can throw, followed by fallthrough into an empty block with two
similar predecessors (both calling the same function) and with a fallthrough
into an empty block with no successors (__builtin_unreachable).
That last block is optimized away soon and in the cfglayout mode we have
a bb with no successors that has a BARRIER in BB_FOOTER.  During cfg cleanup
during combine we actually optimize away even that other empty bb with no
successors, but end up not putting a BARRIER into BB_FOOTER of the bb with a
call.  There is in the following hunk in try_optimize_cfg code to handle
that, but a) it assumes a BARRIER has to be the first in BB_FOOTER, which
as all other spots I've found don't assume, even for the non-cfglayout
mode a few lines below we call get_last_bb_insn which walks the following
insn chain (note, this isn't a problem on this exact testcase though)
and b) punt if e->src bb already has non-NULL BB_FOOTER (that is what
breaks this testcase - the testcase has a NOTE_INSN_DELETED_LABEL in
BB_FOOTER, but of course no BARRIER, we don't add one here and later on
when outof_cfglayout we ICE because there is no BARRIER after a bb that
doesn't fall thru).  Apparently there is a function which can handle
adding a barrier, both into an empty BB_FOOTER as well as when there is
a BB_FOOTER, but doesn't contain a BARRIER in there.

So, this patch fixes both issues.

Bootstrapped/regtested on x86_64-linux and i686-linux, ok for trunk?

2019-04-12  Jakub Jelinek  <ja...@redhat.com>

        PR rtl-optimization/90026
        * cfgcleanup.c (try_optimize_cfg): When removing empty bb with no
        successors, look for BARRIERs inside of the whole BB_FOOTER chain
        rather than just at the start of it.  If e->src BB_FOOTER is not NULL
        in cfglayout mode, use emit_barrier_after_bb.

        * g++.dg/opt/pr90026.C: New test.

--- gcc/cfgcleanup.c.jj 2019-03-09 09:25:11.743785011 +0100
+++ gcc/cfgcleanup.c    2019-04-11 11:30:52.967173100 +0200
@@ -2712,23 +2712,23 @@ try_optimize_cfg (int mode)
 
                      if (current_ir_type () == IR_RTL_CFGLAYOUT)
                        {
-                         if (BB_FOOTER (b)
-                             && BARRIER_P (BB_FOOTER (b)))
+                         rtx_insn *insn;
+                         for (insn = BB_FOOTER (b);
+                              insn; insn = NEXT_INSN (insn))
+                           if (BARRIER_P (insn))
+                             break;
+                         if (insn)
                            FOR_EACH_EDGE (e, ei, b->preds)
-                             if ((e->flags & EDGE_FALLTHRU)
-                                 && BB_FOOTER (e->src) == NULL)
+                             if ((e->flags & EDGE_FALLTHRU))
                                {
-                                 if (BB_FOOTER (b))
+                                 if (BB_FOOTER (b)
+                                     && BB_FOOTER (e->src) == NULL)
                                    {
                                      BB_FOOTER (e->src) = BB_FOOTER (b);
                                      BB_FOOTER (b) = NULL;
                                    }
                                  else
-                                   {
-                                     start_sequence ();
-                                     BB_FOOTER (e->src) = emit_barrier ();
-                                     end_sequence ();
-                                   }
+                                   emit_barrier_after_bb (e->src);
                                }
                        }
                      else
--- gcc/testsuite/g++.dg/opt/pr90026.C.jj       2019-04-11 12:40:14.508840308 
+0200
+++ gcc/testsuite/g++.dg/opt/pr90026.C  2019-04-11 12:39:43.431352423 +0200
@@ -0,0 +1,24 @@
+// PR rtl-optimization/90026
+// { dg-do compile }
+// { dg-options "-fnon-call-exceptions -ftracer -O2 -w" }
+
+typedef __SIZE_TYPE__ size_t;
+struct S { int *b; ~S () { delete b; } };
+void bar ();
+char c[sizeof (int)];
+
+void *
+operator new (size_t, void *)
+{
+  __builtin_unreachable ();
+}
+
+void
+foo ()
+{
+  S a;
+  if (a.b)
+    a.b = new int ();
+  bar ();
+  new (c) int ();
+}

        Jakub

Reply via email to