On January 31, 2014 10:24:22 PM GMT+01:00, Jakub Jelinek <ja...@redhat.com> 
wrote:
>Hi!
>
>As described in the PR, __builtin_setjmp_receiver isn't declared to
>returns_twice, and thus after dce cfun->calls_setjmp might be no longer
>true.
>At RTL __builtin_setjmp_receiver is handled as non-local label, so this
>patch just forces cfun->has_nonlocal_label already in GIMPLE, so that
>e.g. the inliner still sees stmt_can_make_nonlocal_goto.
>
>Bootstrapped/regtested on x86_64-linux and i686-linux, ok for trunk?

Ok.

Thanks,
Richard.

>2014-01-31  Jakub Jelinek  <ja...@redhat.com>
>
>       PR tree-optimization/60003
>       * gimple-low.c (lower_builtin_setjmp): Set cfun->has_nonlocal_label.
>       * profile.c (branch_prob): Use gimple_call_builtin_p
>       to check for BUILT_IN_SETJMP_RECEIVER.
>       * tree-inline.c (copy_bb): Call notice_special_calls.
>
>       * gcc.c-torture/execute/pr60003.c: New test.
>
>--- gcc/gimple-low.c.jj        2014-01-29 12:43:25.000000000 +0100
>+++ gcc/gimple-low.c   2014-01-31 10:02:38.843026680 +0100
>@@ -709,6 +709,12 @@ lower_builtin_setjmp (gimple_stmt_iterat
>   tree dest, t, arg;
>   gimple g;
>
>+  /* __builtin_setjmp_{setup,receiver} aren't ECF_RETURNS_TWICE and
>for RTL
>+     these builtins are modelled as non-local label jumps to the label
>+     that is passed to these two builtins, so pretend we have a
>non-local
>+     label during GIMPLE passes too.  See PR60003.  */ 
>+  cfun->has_nonlocal_label = true;
>+
>/* NEXT_LABEL is the label __builtin_longjmp will jump to.  Its address
>is
>passed to both __builtin_setjmp_setup and __builtin_setjmp_receiver. 
>*/
>   FORCED_LABEL (next_label) = 1;
>--- gcc/profile.c.jj   2014-01-29 12:43:25.000000000 +0100
>+++ gcc/profile.c      2014-01-31 10:18:00.450198256 +0100
>@@ -1104,7 +1104,6 @@ branch_prob (void)
>           {
>             gimple_stmt_iterator gsi;
>             gimple first;
>-            tree fndecl;
> 
>             gsi = gsi_start_nondebug_after_labels_bb (bb);
>             gcc_checking_assert (!gsi_end_p (gsi));
>@@ -1114,10 +1113,7 @@ branch_prob (void)
>                special and don't expect anything to be inserted before
>                them.  */
>             if (is_gimple_call (first)
>-                && (((fndecl = gimple_call_fndecl (first)) != NULL
>-                     && DECL_BUILT_IN_CLASS (fndecl) == BUILT_IN_NORMAL
>-                     && (DECL_FUNCTION_CODE (fndecl)
>-                         == BUILT_IN_SETJMP_RECEIVER))
>+                && (gimple_call_builtin_p (first, BUILT_IN_SETJMP_RECEIVER)
>                     || (gimple_call_flags (first) & ECF_RETURNS_TWICE)
>                     || (gimple_call_internal_p (first)
>                         && (gimple_call_internal_fn (first)
>--- gcc/tree-inline.c.jj       2014-01-29 12:43:24.000000000 +0100
>+++ gcc/tree-inline.c  2014-01-31 10:19:13.849815593 +0100
>@@ -1745,7 +1745,6 @@ copy_bb (copy_body_data *id, basic_block
>         if (is_gimple_call (stmt))
>           {
>             struct cgraph_edge *edge;
>-            int flags;
> 
>             switch (id->transform_call_graph_edges)
>               {
>@@ -1868,11 +1867,7 @@ copy_bb (copy_body_data *id, basic_block
>                   }
>               }
> 
>-            flags = gimple_call_flags (stmt);
>-            if (flags & ECF_MAY_BE_ALLOCA)
>-              cfun->calls_alloca = true;
>-            if (flags & ECF_RETURNS_TWICE)
>-              cfun->calls_setjmp = true;
>+            notice_special_calls (stmt);
>           }
> 
>         maybe_duplicate_eh_stmt_fn (cfun, stmt, id->src_cfun, orig_stmt,
>--- gcc/testsuite/gcc.c-torture/execute/pr60003.c.jj   2014-01-31
>10:05:15.095205547 +0100
>+++ gcc/testsuite/gcc.c-torture/execute/pr60003.c      2014-01-31
>10:04:59.000000000 +0100
>@@ -0,0 +1,48 @@
>+/* PR tree-optimization/60003 */
>+
>+extern void abort (void);
>+
>+unsigned long long jmp_buf[5];
>+
>+__attribute__((noinline, noclone)) void
>+baz (void)
>+{
>+  __builtin_longjmp (&jmp_buf, 1);
>+}
>+
>+void
>+bar (void)
>+{
>+  baz ();
>+}
>+
>+__attribute__((noinline, noclone)) int
>+foo (int x)
>+{
>+  int a = 0;
>+
>+  if (__builtin_setjmp (&jmp_buf) == 0)
>+    {
>+      while (1)
>+      {
>+        a = 1;
>+        bar ();  /* OK if baz () instead */
>+      }
>+    }
>+  else
>+    {
>+      if (a == 0)
>+      return 0;
>+      else
>+      return x;
>+    }
>+}
>+
>+int
>+main ()
>+{
>+  if (foo (1) == 0)
>+    abort ();
>+
>+  return 0;
>+}
>
>       Jakub


Reply via email to