On Thu, 25 Oct 2012, Richard Biener wrote:

> On Thu, 25 Oct 2012, Jakub Jelinek wrote:
> 
> > On Thu, Oct 25, 2012 at 12:58:26PM +0200, Richard Biener wrote:
> > > So the bug here is really in find_many_sub_basic_blocks then
> > > and your patch would certainly avoid triggering its bug
> > > (or its wrong expectations).  I'll give it testing.
> > 
> > I'd say we should insert the __builtin_unreachable already far earlier than
> > that, either when inlining the noreturn function and figuring out
> > it might return (perhaps conditionally on something that never happens),
> > or if LTO does something similar with it even without inlining.
> 
> That would be fixup_cfg which is supposed to deal with this kind of
> "fallout", like in my original patch (just using __builtin_unreachable ()
> instead of an infinite loop edge)
>   
> Honza?

Like the following, bootstrap & regtest pending on 
x86_64-unknown-linux-gnu.

Richard.

2012-10-15  Richard Biener  <rguent...@suse.de>

        PR middle-end/54824
        * tree-optimize.c (execute_fixup_cfg): Insert __builtin_unreachable
        at the end of blocks with no successors.

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

Index: gcc/tree-optimize.c
===================================================================
*** gcc/tree-optimize.c (revision 192803)
--- gcc/tree-optimize.c (working copy)
*************** execute_fixup_cfg (void)
*** 180,185 ****
--- 180,204 ----
        FOR_EACH_EDGE (e, ei, bb->succs)
          e->count = (e->count * count_scale
                    + REG_BR_PROB_BASE / 2) / REG_BR_PROB_BASE;
+ 
+       /* If we have a basic-block with no successors that does not
+        end with a control statement or a noreturn call connect it
+        to itself.  This situation can occur when inlining a noreturn
+        call that does in fact return.  */
+       if (EDGE_COUNT (bb->succs) == 0)
+       {
+         gimple stmt = last_stmt (bb);
+         if (!stmt
+             || (!is_ctrl_stmt (stmt)
+                 && (!is_gimple_call (stmt)
+                     || (gimple_call_flags (stmt) & ECF_NORETURN) == 0)))
+           {
+             stmt = gimple_build_call
+                 (builtin_decl_implicit (BUILT_IN_UNREACHABLE), 0);
+             gimple_stmt_iterator gsi = gsi_last_bb (bb);
+             gsi_insert_after (&gsi, stmt, GSI_NEW_STMT);
+           }
+       }
      }
    if (count_scale != REG_BR_PROB_BASE)
      compute_function_frequency ();
Index: gcc/testsuite/gcc.dg/torture/pr54824.c
===================================================================
*** gcc/testsuite/gcc.dg/torture/pr54824.c      (revision 0)
--- gcc/testsuite/gcc.dg/torture/pr54824.c      (working copy)
***************
*** 0 ****
--- 1,16 ----
+ /* { dg-do compile } */
+ /* { dg-options "-w" } */
+ 
+ void __attribute__((noreturn)) bar(void)
+ {
+ }
+ 
+ void foo(int i, char *p, char *q)
+ {
+   while (*p++) {
+       if (i)
+       p++;
+       if (!*q++)
+       bar();
+   }
+ }

Reply via email to